From bdaab165b537cc1645a3e504144abc02cc4c960d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:04:30 +0000 Subject: [PATCH 0001/1502] overlay: name enqueue_hero_glow_quad --- src/overlays/shared/hero/hero_idle_sequence.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index e9137d636a..ad3932c13f 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -1707,7 +1707,9 @@ extern G_00208038 D_0013F350_00208038 __asm__("D_0013F350"); void enqueue_hero_glow_draw_callback_once(void) __asm__("FUN_L00_00207d00"); /* Appends v, b, x and y to the list in ((char *)&hero) and calls FUN_L00_00207d00. */ -void FUN_L00_00208038(u128 *glow_position, int b, float x, float y) { +void enqueue_hero_glow_quad(u128 *glow_position, int b, float x, float y) __asm__("FUN_L00_00208038"); + +void enqueue_hero_glow_quad(u128 *glow_position, int b, float x, float y) { G_00208038 *hero_glow_queue_owner = &D_0013F350_00208038; short n = hero_glow_queue_owner->n; u128 *pos = hero_glow_queue_owner->pos; From a7477c0342d6ffff7748674cb7eb1f1e5c27e854 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:10:47 +0000 Subject: [PATCH 0002/1502] decomp: clarify names in vo_buf_get_data buf -> video_output_buffer: In vo_buf_get_data, struct VoBuf *buf is passed to vo_buf_is_full and supplies buf->data + buf->write. Retail 0x0023d298 preserves the object pointer from a0 in s0; 0x0023d2a4 and 0x0023d2ac load its write index and data base at offsets 8 and 0, then 0x0023d2b0/0x0023d2b4 return data base + write index * 0xd0000. The original Ghidra *param_1 + param_1[2] * 0xd0000 agrees. Thus this is the video-output buffer owning the returned writable data slot, rather than the slot data pointer itself. --- src/movies/decoder/video_output/vo_buf_get_data.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/movies/decoder/video_output/vo_buf_get_data.c b/src/movies/decoder/video_output/vo_buf_get_data.c index bb49ed7e93..2d3b01a154 100644 --- a/src/movies/decoder/video_output/vo_buf_get_data.c +++ b/src/movies/decoder/video_output/vo_buf_get_data.c @@ -3,11 +3,11 @@ struct VoData *vo_buf_get_data(struct VoBuf *buf) __asm__("FUN_0023d288"); -struct VoData *vo_buf_get_data(struct VoBuf *buf) { - if (vo_buf_is_full(buf) != 0) { +struct VoData *vo_buf_get_data(struct VoBuf *video_output_buffer) { + if (vo_buf_is_full(video_output_buffer) != 0) { return 0; } - return buf->data + buf->write; + return video_output_buffer->data + video_output_buffer->write; } /* Recovered original symbol name. */ From 3281fd8c86e70857134f4a5d7ad55517cec0550e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:10:47 +0000 Subject: [PATCH 0003/1502] decomp: clarify names in vo_buf_dec_count buf -> video_output_buffer: In authoritative src/movies/decoder/video_output/vo_buf_dec_count.c (SHA-256 741be7d62cd11225401718bcf589b714d877051c0d3e15ce81bcb17ffa87f92b), buf has type struct VoBuf * and is the video output buffer passed to vo_buf_dec_count. Retail Ghidra accesses param_1+0xc; instructions at 0x0023d340 and 0x0023d34c load its count, 0x0023d344 skips nonpositive counts, and 0x0023d350/0x0023d354 decrement and store that same object's count. The name identifies the video-output object rather than merely expanding buf. --- src/movies/decoder/video_output/vo_buf_dec_count.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/movies/decoder/video_output/vo_buf_dec_count.c b/src/movies/decoder/video_output/vo_buf_dec_count.c index 6900a93f8f..7e0c5b5720 100644 --- a/src/movies/decoder/video_output/vo_buf_dec_count.c +++ b/src/movies/decoder/video_output/vo_buf_dec_count.c @@ -3,8 +3,8 @@ void vo_buf_dec_count(struct VoBuf *buf) __asm__("func_0023D340"); -void vo_buf_dec_count(struct VoBuf *buf) { - if (buf->count > 0) { - buf->count--; +void vo_buf_dec_count(struct VoBuf *video_output_buffer) { + if (video_output_buffer->count > 0) { + video_output_buffer->count--; } } From e430c339f1e19294a9060c104f119c3b291456dc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:10:58 +0000 Subject: [PATCH 0004/1502] decomp: clarify names in FUN_L00_002e4fe8 D_L00_00161D3C_gp -> l00_follow_camera_ground_focus_exit_transition_frames_gp: Authoritative follow_camera_springs.c SHA-256 701495ce75a0b467623ddd985ce53bade26498023994070bad9b2c49047b4e0c binds this short SDA alias to D_L00_00161D3C. In CAM_ATTACH_GROUND_AWARE_FOCUS_VELOCITY, retail 002e517c selects attachment mode 1; 002e5180 lhu from gp-0x4ec4 loads this global, 002e5188 stores its low halfword to attach_state+0xC6, and 002e518c-002e51a4 converts the signed short and stores its reciprocal at +0xC8. Original Ghidra shows the same uGpffffb13c timer/inverse pair. Source follow_camera_transition multiplies the countdown at +0xC6 by the reciprocal at +0xC8 to interpolate stiffness/damping. Thus this supplies the ground-aware focus exit transition duration, also reused on entry into mode 1 by the supplied sibling source; no gameplay meaning is inferred. D_L00_00161D54_gp -> l00_follow_camera_post_blend_focus_transition_frames_gp: Authoritative follow_camera_springs.c binds this short SDA alias to D_L00_00161D54. Retail 002e5404 tests completion of the movement countdown at attach_state+0xD4; after excluding modes 9 and 6, 002e5498 selects mode 4 (existing CAM_ATTACH_PROJECT_HERO_FOCUS_VELOCITY). Retail 002e549c lhu from gp-0x4eac loads this global, 002e54a4 stores the short countdown at attach_state+0xC6, and 002e54a8-002e54c4 converts the signed short and stores its reciprocal at +0xC8. Original Ghidra agrees via uGpffffb154. Source follow_camera_transition uses countdown*reciprocal to interpolate position-spring stiffness/damping. This proves a post-blend focus transition duration; sibling source also reuses its full-width reinterpretation through scale_game_frames for several mode exits. Preserve that reinterpretation and the short declaration exactly. --- .../shared/camera/follow_camera_springs.c | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/overlays/shared/camera/follow_camera_springs.c b/src/overlays/shared/camera/follow_camera_springs.c index 1e4a2b4850..11111a7cbf 100644 --- a/src/overlays/shared/camera/follow_camera_springs.c +++ b/src/overlays/shared/camera/follow_camera_springs.c @@ -111,14 +111,14 @@ extern float D_L00_00166EEC NOT_SDA; extern s32 D_L00_00161D24_gp __asm__("D_L00_00161D24") __attribute__((sda)); extern short follow_camera_ground_aware_focus_transition_frames_gp __asm__("D_L00_00161D38") __attribute__((sda)); -extern short D_L00_00161D3C_gp __asm__("D_L00_00161D3C") __attribute__((sda)); +extern short l00_follow_camera_ground_focus_exit_transition_frames_gp __asm__("D_L00_00161D3C") __attribute__((sda)); extern short D_L00_00161D40_gp __asm__("D_L00_00161D40") __attribute__((sda)); extern short follow_camera_blend_out_focus_offset_gp __asm__("D_L00_00161D48") __attribute__((sda)); extern short follow_camera_project_hero_focus_blend_base_frames_gp __asm__("D_L00_00161D4C") __attribute__((sda)); extern short follow_camera_focus_blend_transition_frames_gp __asm__("D_L00_00161D50") __attribute__((sda)); -extern short D_L00_00161D54_gp __asm__("D_L00_00161D54") __attribute__((sda)); +extern short l00_follow_camera_post_blend_focus_transition_frames_gp __asm__("D_L00_00161D54") __attribute__((sda)); extern short follow_camera_project_hero_focus_offset_gp __asm__("D_L00_00161D58") __attribute__((sda)); extern short follow_camera_hold_focus_blend_base_frames_gp __asm__("D_L00_00161D5C") @@ -840,7 +840,7 @@ void FUN_L00_002e4930(char *camera) { if (player->state.control_mode == 2) { attach_state->prev = attach_state->state; attach_state->state = 1; - attach_state->timer = D_L00_00161D3C_gp; + attach_state->timer = l00_follow_camera_ground_focus_exit_transition_frames_gp; attach_state->invTimer = 1.0f / convert_integer_to_float(attach_state->timer); } else { struct Hero *current_player = &hero; @@ -963,7 +963,7 @@ void FUN_L00_002e4930(char *camera) { if (p->state.control_mode == 2) { attach_state->prev = attach_state->state; attach_state->state = 1; - attach_state->timer = scale_game_frames(*(int *)&D_L00_00161D54_gp); + attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); attach_state->invTimer = 1.0f / convert_integer_to_float(attach_state->timer); return; } @@ -972,12 +972,12 @@ void FUN_L00_002e4930(char *camera) { if (D_001413DC == 2) { attach_state->prev = 4; attach_state->state = 1; - attach_state->timer = scale_game_frames(*(int *)&D_L00_00161D54_gp); + attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); attach_state->invTimer = 1.0f / convert_integer_to_float(attach_state->timer); } else { attach_state->prev = 4; attach_state->state = 0; - attach_state->timer = scale_game_frames(*(int *)&D_L00_00161D54_gp); + attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); attach_state->invTimer = 1.0f / convert_integer_to_float(attach_state->timer); } return; @@ -1015,14 +1015,14 @@ void FUN_L00_002e4930(char *camera) { if (attach_state->state == 6 && camera_secondary_mode_lui != 0xB) { attach_state->prev = attach_state->state; attach_state->state = 0; - attach_state->timer = scale_game_frames(*(int *)&D_L00_00161D54_gp); + attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); attach_state->invTimer = 1.0f / convert_integer_to_float(attach_state->timer); return; } if ((attach_state->state == 3 || attach_state->state == 5) && D_001413DC != 4) { attach_state->prev = attach_state->state; attach_state->state = 0; - attach_state->timer = scale_game_frames(*(int *)&D_L00_00161D54_gp); + attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); attach_state->invTimer = 1.0f / convert_integer_to_float(attach_state->timer); return; } @@ -1039,7 +1039,7 @@ void FUN_L00_002e4930(char *camera) { to_one: attach_state->prev = attach_state->state; attach_state->state = 1; - attach_state->timer = scale_game_frames(*(int *)&D_L00_00161D54_gp); + attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); r = 1.0f / convert_integer_to_float(attach_state->timer); camera_timer_base_frames = *(int *)&D_L00_00161D24_gp; attach_state->invTimer = r; @@ -1059,7 +1059,7 @@ void FUN_L00_002e4930(char *camera) { if (attach_state->state == 0xA && FUN_001f9770_c2(&attach_state->moveTimer)) { attach_state->prev = attach_state->state; attach_state->state = 0; - attach_state->timer = scale_game_frames(*(int *)&D_L00_00161D54_gp); + attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); attach_state->invTimer = 1.0f / convert_integer_to_float(attach_state->timer); return; } @@ -1117,7 +1117,7 @@ void FUN_L00_002e4fe8(char *camera, float *out_focus_velocity) { *(float *)&follow_camera_ground_focus_angle_upper_bound_gp < y))) { int v; *(unsigned char *)(attach_state + 0xC4) = 1; - v = *(unsigned short *)&D_L00_00161D3C_gp; + v = *(unsigned short *)&l00_follow_camera_ground_focus_exit_transition_frames_gp; *(short *)(attach_state + 0xC6) = v; *(float *)(attach_state + 0xC8) = 1.0f / convert_integer_to_float((short)v); } @@ -1195,7 +1195,7 @@ void FUN_L00_002e4fe8(char *camera, float *out_focus_velocity) { } else { int v; *(unsigned char *)(attach_state + 0xC4) = 4; - v = *(unsigned short *)&D_L00_00161D54_gp; + v = *(unsigned short *)&l00_follow_camera_post_blend_focus_transition_frames_gp; *(short *)(attach_state + 0xC6) = v; *(float *)(attach_state + 0xC8) = 1.0f / convert_integer_to_float((short)v); } From 6ce1d83b609873f4f2000201c7d97b0b58e91d94 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:10:58 +0000 Subject: [PATCH 0005/1502] decomp: clarify names in read_buf_end_put buf -> read_ring_buffer: The authoritative src/movies/decoder/buffers/read_buf_end_put.c snapshot (SHA-256 bec7903e2bcda8f14223f3a42ab2e4ee3252b695a16787addae31c0bcbf1284c) types buf as struct ReadBuf *. Retail 0x0023b990-0x0023b9a0 accesses this object's put/count/capacity state at +0x50000/+0x50004/+0x50008. At 0x0023b9ac-0x0023b9b4 capacity minus count bounds the committed byte count; 0x0023b9b8-0x0023b9d0 adds it to put and count and stores put modulo capacity. The original Ghidra decompilation shows these same first-argument state updates, proving the read ring-buffer role in established read_buf_end_put. --- src/movies/decoder/buffers/read_buf_end_put.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/movies/decoder/buffers/read_buf_end_put.c b/src/movies/decoder/buffers/read_buf_end_put.c index 443037e0ad..369b46672f 100644 --- a/src/movies/decoder/buffers/read_buf_end_put.c +++ b/src/movies/decoder/buffers/read_buf_end_put.c @@ -3,12 +3,12 @@ void read_buf_end_put(struct ReadBuf *buf, s32 size) __asm__("FUN_0023b990"); /* Commits size bytes after a put, clamped to the free space. */ -void read_buf_end_put(struct ReadBuf *buf, s32 size) { - s32 free = buf->size - buf->count; +void read_buf_end_put(struct ReadBuf *read_ring_buffer, s32 size) { + s32 free = read_ring_buffer->size - read_ring_buffer->count; s32 committed = (size < free) ? size : free; - buf->put = (buf->put + committed) % buf->size; - buf->count += committed; + read_ring_buffer->put = (read_ring_buffer->put + committed) % read_ring_buffer->size; + read_ring_buffer->count += committed; } extern __typeof__(read_buf_end_put) func_0023B990 __attribute__((alias("FUN_0023b990"))); From 092e44aba59f03eea37c21e58b9137cc21183efa Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:10:58 +0000 Subject: [PATCH 0006/1502] decomp: clarify names in read_buf_begin_get buf -> ring_buffer: The authoritative struct ReadBuf * supplies data, put, count and size. Retail 0x0023b9dc preserves this argument in a3; 0x0023b9e0-0x0023b9f4 load its controls at +0x50000/+0x50004/+0x50008. At 0x0023b9f8-0x0023ba10, (put-count+size)%size is added to its storage base, proving a circular (ring) buffer. ptr -> read_start_out: The authoritative u8 ** parameter receives data + (put-count+size)%size only when count is nonzero. Retail 0x0023ba0c takes the modulo remainder, 0x0023ba10 adds the buffer base, and 0x0023ba14 stores that address through a1. In read_buf_begin_get this is the output pointer to the start of queued readable data. --- src/movies/decoder/buffers/read_buf_begin_get.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/movies/decoder/buffers/read_buf_begin_get.c b/src/movies/decoder/buffers/read_buf_begin_get.c index 0974415977..a65551894d 100644 --- a/src/movies/decoder/buffers/read_buf_begin_get.c +++ b/src/movies/decoder/buffers/read_buf_begin_get.c @@ -2,11 +2,11 @@ s32 read_buf_begin_get(struct ReadBuf *buf, u8 **ptr) __asm__("FUN_0023b9d8"); -s32 read_buf_begin_get(struct ReadBuf *buf, u8 **ptr) { - if (buf->count != 0) { - *ptr = buf->data + (buf->put - buf->count + buf->size) % buf->size; +s32 read_buf_begin_get(struct ReadBuf *ring_buffer, u8 **read_start_out) { + if (ring_buffer->count != 0) { + *read_start_out = ring_buffer->data + (ring_buffer->put - ring_buffer->count + ring_buffer->size) % ring_buffer->size; } - return buf->count; + return ring_buffer->count; } extern __typeof__(read_buf_begin_get) func_0023B9D8 __attribute__((alias("FUN_0023b9d8"))); From f632ca7730feec260475e0adfff334763dfb502a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:13:24 +0000 Subject: [PATCH 0007/1502] overlay: name vector_length_xyz_cf --- .../l03/hero/update_hero_motion_for_current_state.c | 6 +++--- src/overlays/l05/hero/update_hero_motion_by_state.c | 6 +++--- .../l06/hero/update_hero_motion_for_current_state.c | 2 +- .../l08/hero/update_hero_motion_for_current_state.c | 6 +++--- src/overlays/l11/hero/update_hero_motion_by_state.c | 6 +++--- .../l12/hero/update_hero_motion_for_current_state.c | 6 +++--- src/overlays/l14/hero/update_hero_motion_by_state.c | 2 +- .../l15/hero/update_hero_motion_for_current_state.c | 6 +++--- .../l16/hero/update_hero_motion_for_current_state.c | 6 +++--- .../l17/hero/update_hero_motion_for_current_state.c | 6 +++--- .../l18/hero/update_hero_motion_for_current_state.c | 6 +++--- src/overlays/shared/hero/hero_idle_sequence.c | 4 ++-- src/overlays/shared/hero/hero_update_movement.c | 6 +++--- 13 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/overlays/l03/hero/update_hero_motion_for_current_state.c b/src/overlays/l03/hero/update_hero_motion_for_current_state.c index 165641f969..452da57a01 100644 --- a/src/overlays/l03/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l03/hero/update_hero_motion_for_current_state.c @@ -225,7 +225,7 @@ extern void moby_point_position(struct MobyView *, s32, void *) __asm__("FUN_L00 extern u8 *FUN_L00_0026f080(void *, void *, f32, f32); extern s32 random_int_between(s32, s32) __asm__("FUN_L00_00257b90"); extern void FUN_L00_00262cf0(void *, void *, f32, f32, f32); -extern f32 FUN_L00_00209018(void *, s32); +extern f32 vector_length_xyz_cf(void *, s32) __asm__("FUN_L00_00209018"); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern void set_first_hero_easing_parameters(f32, f32) __asm__("FUN_L00_0020a1e0"); extern void FUN_L03_002030a0(f32, f32); @@ -769,7 +769,7 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { f32 sp = hero.ground_speed * - FUN_L00_00209018(swim_animation_speed_scale_table, 0x1E) * 5.0f; + vector_length_xyz_cf(swim_animation_speed_scale_table, 0x1E) * 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -900,7 +900,7 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { f32 sp = hero.ground_speed * - FUN_L00_00209018(swim_animation_speed_scale_table, 0x1E) * 5.5f; + vector_length_xyz_cf(swim_animation_speed_scale_table, 0x1E) * 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; diff --git a/src/overlays/l05/hero/update_hero_motion_by_state.c b/src/overlays/l05/hero/update_hero_motion_by_state.c index a0fdd16a37..5e869b9a9f 100644 --- a/src/overlays/l05/hero/update_hero_motion_by_state.c +++ b/src/overlays/l05/hero/update_hero_motion_by_state.c @@ -178,7 +178,7 @@ extern void moby_point_position(struct MobyView *, s32, void *) __asm__("FUN_L00 extern u8 *FUN_L00_0026f080(void *, void *, f32, f32); extern s32 random_int_between(s32, s32) __asm__("FUN_L00_00257b90"); extern void FUN_L00_00262cf0(void *, void *, f32, f32, f32); -extern f32 FUN_L00_00209018(void *, s32); +extern f32 vector_length_xyz_cf(void *, s32) __asm__("FUN_L00_00209018"); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern void set_first_hero_easing_parameters(f32, f32) __asm__("FUN_L00_0020a1e0"); extern void FUN_L05_00238858(f32, f32); @@ -729,7 +729,7 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { f32 sp = - hero.ground_speed * FUN_L00_00209018(swim_motion_scale_samples, 0x1E) * 5.0f; + hero.ground_speed * vector_length_xyz_cf(swim_motion_scale_samples, 0x1E) * 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -858,7 +858,7 @@ void update_hero_motion_by_state(void) { speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { f32 sp = - hero.ground_speed * FUN_L00_00209018(swim_motion_scale_samples, 0x1E) * 5.5f; + hero.ground_speed * vector_length_xyz_cf(swim_motion_scale_samples, 0x1E) * 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; diff --git a/src/overlays/l06/hero/update_hero_motion_for_current_state.c b/src/overlays/l06/hero/update_hero_motion_for_current_state.c index 4909a1e3c2..d86c137fbe 100644 --- a/src/overlays/l06/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l06/hero/update_hero_motion_for_current_state.c @@ -909,7 +909,7 @@ extern u8 *FUN_L00_0026f080(void *, void *, f32, f32); extern s32 random_int_between(s32, s32) __asm__("FUN_L00_00257b90"); extern void FUN_L00_00262cf0(void *, void *, f32, f32, f32); extern void build_spherical_offset(void *, f32, f32, f32) __asm__("FUN_00214db0"); -extern f32 FUN_L00_00209018(void *, s32); +extern f32 vector_length_xyz_cf(void *, s32) __asm__("FUN_L00_00209018"); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern void set_first_hero_easing_parameters(f32, f32) __asm__("FUN_L00_0020a1e0"); extern void FUN_L06_00221850(f32, f32); diff --git a/src/overlays/l08/hero/update_hero_motion_for_current_state.c b/src/overlays/l08/hero/update_hero_motion_for_current_state.c index 1493d8da10..c2eedee649 100644 --- a/src/overlays/l08/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l08/hero/update_hero_motion_for_current_state.c @@ -286,7 +286,7 @@ extern void moby_point_position(struct MobyView *, s32, void *) __asm__("FUN_L00 extern u8 *FUN_L00_0026f080(void *, void *, f32, f32); extern s32 random_int_between(s32, s32) __asm__("FUN_L00_00257b90"); extern void FUN_L00_00262cf0(void *, void *, f32, f32, f32); -extern f32 FUN_L00_00209018(void *, s32); +extern f32 vector_length_xyz_cf(void *, s32) __asm__("FUN_L00_00209018"); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern void set_first_hero_easing_parameters(f32, f32) __asm__("FUN_L00_0020a1e0"); extern void FUN_L08_0021c270(f32, f32); @@ -835,7 +835,7 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { f32 sp = hero.ground_speed * - FUN_L00_00209018(l08_swim_speed_animation_samples, 0x1E) * 5.0f; + vector_length_xyz_cf(l08_swim_speed_animation_samples, 0x1E) * 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -966,7 +966,7 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { f32 sp = hero.ground_speed * - FUN_L00_00209018(l08_swim_speed_animation_samples, 0x1E) * 5.5f; + vector_length_xyz_cf(l08_swim_speed_animation_samples, 0x1E) * 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; diff --git a/src/overlays/l11/hero/update_hero_motion_by_state.c b/src/overlays/l11/hero/update_hero_motion_by_state.c index d69a98d8a0..e399d981f9 100644 --- a/src/overlays/l11/hero/update_hero_motion_by_state.c +++ b/src/overlays/l11/hero/update_hero_motion_by_state.c @@ -273,7 +273,7 @@ extern void moby_point_position(struct MobyView *, s32, void *) __asm__("FUN_L00 extern u8 *FUN_L00_0026f080(void *, void *, f32, f32); extern s32 random_int_between(s32, s32) __asm__("FUN_L00_00257b90"); extern void FUN_L00_00262cf0(void *, void *, f32, f32, f32); -extern f32 FUN_L00_00209018(void *, s32); +extern f32 vector_length_xyz_cf(void *, s32) __asm__("FUN_L00_00209018"); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern void set_first_hero_easing_parameters(f32, f32) __asm__("FUN_L00_0020a1e0"); extern void FUN_L11_0023b050(f32, f32); @@ -821,7 +821,7 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { f32 sp = - hero.ground_speed * FUN_L00_00209018(swim_animation_speed_factors, 0x1E) * 5.0f; + hero.ground_speed * vector_length_xyz_cf(swim_animation_speed_factors, 0x1E) * 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -952,7 +952,7 @@ void update_hero_motion_by_state(void) { speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { f32 sp = - hero.ground_speed * FUN_L00_00209018(swim_animation_speed_factors, 0x1E) * 5.5f; + hero.ground_speed * vector_length_xyz_cf(swim_animation_speed_factors, 0x1E) * 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; diff --git a/src/overlays/l12/hero/update_hero_motion_for_current_state.c b/src/overlays/l12/hero/update_hero_motion_for_current_state.c index a35baf4dc3..d90e474af8 100644 --- a/src/overlays/l12/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l12/hero/update_hero_motion_for_current_state.c @@ -553,7 +553,7 @@ extern u8 *FUN_L00_0026f080(void *, void *, f32, f32); extern s32 random_int_between(s32, s32) __asm__("FUN_L00_00257b90"); extern void FUN_L00_00262cf0(void *, void *, f32, f32, f32); extern void build_spherical_offset(void *, f32, f32, f32) __asm__("FUN_00214db0"); -extern f32 FUN_L00_00209018(void *, s32); +extern f32 vector_length_xyz_cf(void *, s32) __asm__("FUN_L00_00209018"); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern void set_first_hero_easing_parameters(f32, f32) __asm__("FUN_L00_0020a1e0"); extern void FUN_L12_0022c6e0(f32, f32); @@ -1110,7 +1110,7 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { f32 sp = hero.ground_speed * - FUN_L00_00209018(hero_swim_speed_animation_curve, 0x1E) * 5.0f; + vector_length_xyz_cf(hero_swim_speed_animation_curve, 0x1E) * 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -1241,7 +1241,7 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { f32 sp = hero.ground_speed * - FUN_L00_00209018(hero_swim_speed_animation_curve, 0x1E) * 5.5f; + vector_length_xyz_cf(hero_swim_speed_animation_curve, 0x1E) * 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; diff --git a/src/overlays/l14/hero/update_hero_motion_by_state.c b/src/overlays/l14/hero/update_hero_motion_by_state.c index 54ca42c54a..48ce2c021f 100644 --- a/src/overlays/l14/hero/update_hero_motion_by_state.c +++ b/src/overlays/l14/hero/update_hero_motion_by_state.c @@ -425,7 +425,7 @@ extern u8 *FUN_L00_0026f080(void *, void *, f32, f32); extern s32 random_int_between(s32, s32) __asm__("FUN_L00_00257b90"); extern void FUN_L00_00262cf0(void *, void *, f32, f32, f32); extern void build_spherical_offset(void *, f32, f32, f32) __asm__("FUN_00214db0"); -extern f32 FUN_L00_00209018(void *, s32); +extern f32 vector_length_xyz_cf(void *, s32) __asm__("FUN_L00_00209018"); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern void set_first_hero_easing_parameters(f32, f32) __asm__("FUN_L00_0020a1e0"); extern void FUN_L14_0021c5c8(f32, f32); diff --git a/src/overlays/l15/hero/update_hero_motion_for_current_state.c b/src/overlays/l15/hero/update_hero_motion_for_current_state.c index e4f003c337..c5dc49e0a5 100644 --- a/src/overlays/l15/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l15/hero/update_hero_motion_for_current_state.c @@ -484,7 +484,7 @@ extern void moby_point_position(struct MobyView *, s32, void *) __asm__("FUN_L00 extern u8 *FUN_L00_0026f080(void *, void *, f32, f32); extern s32 random_int_between(s32, s32) __asm__("FUN_L00_00257b90"); extern void FUN_L00_00262cf0(void *, void *, f32, f32, f32); -extern f32 FUN_L00_00209018(void *, s32); +extern f32 vector_length_xyz_cf(void *, s32) __asm__("FUN_L00_00209018"); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern void set_first_hero_easing_parameters(f32, f32) __asm__("FUN_L00_0020a1e0"); extern void FUN_L15_00202d78(f32, f32); @@ -1002,7 +1002,7 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { f32 sp = hero.ground_speed * - FUN_L00_00209018(hero_swim_speed_by_animation_frame, 0x1E) * 5.0f; + vector_length_xyz_cf(hero_swim_speed_by_animation_frame, 0x1E) * 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -1133,7 +1133,7 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { f32 sp = hero.ground_speed * - FUN_L00_00209018(hero_swim_speed_by_animation_frame, 0x1E) * 5.5f; + vector_length_xyz_cf(hero_swim_speed_by_animation_frame, 0x1E) * 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; diff --git a/src/overlays/l16/hero/update_hero_motion_for_current_state.c b/src/overlays/l16/hero/update_hero_motion_for_current_state.c index a62aa52b2d..e63053e0ea 100644 --- a/src/overlays/l16/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l16/hero/update_hero_motion_for_current_state.c @@ -182,7 +182,7 @@ extern void moby_point_position(struct MobyView *, s32, void *) __asm__("FUN_L00 extern u8 *FUN_L00_0026f080(void *, void *, f32, f32); extern s32 random_int_between(s32, s32) __asm__("FUN_L00_00257b90"); extern void FUN_L00_00262cf0(void *, void *, f32, f32, f32); -extern f32 FUN_L00_00209018(void *, s32); +extern f32 vector_length_xyz_cf(void *, s32) __asm__("FUN_L00_00209018"); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern void set_first_hero_easing_parameters(f32, f32) __asm__("FUN_L00_0020a1e0"); extern void FUN_L16_00208038(f32, f32); @@ -727,7 +727,7 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { f32 sp = - hero.ground_speed * FUN_L00_00209018(swim_animation_speed_profile, 0x1E) * 5.0f; + hero.ground_speed * vector_length_xyz_cf(swim_animation_speed_profile, 0x1E) * 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -856,7 +856,7 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { f32 sp = - hero.ground_speed * FUN_L00_00209018(swim_animation_speed_profile, 0x1E) * 5.5f; + hero.ground_speed * vector_length_xyz_cf(swim_animation_speed_profile, 0x1E) * 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; diff --git a/src/overlays/l17/hero/update_hero_motion_for_current_state.c b/src/overlays/l17/hero/update_hero_motion_for_current_state.c index 56d94c3814..ade1987b9c 100644 --- a/src/overlays/l17/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l17/hero/update_hero_motion_for_current_state.c @@ -166,7 +166,7 @@ extern void moby_point_position(struct MobyView *, s32, void *) __asm__("FUN_L00 extern u8 *FUN_L00_0026f080(void *, void *, f32, f32); extern s32 random_int_between(s32, s32) __asm__("FUN_L00_00257b90"); extern void FUN_L00_00262cf0(void *, void *, f32, f32, f32); -extern f32 FUN_L00_00209018(void *, s32); +extern f32 vector_length_xyz_cf(void *, s32) __asm__("FUN_L00_00209018"); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern void set_first_hero_easing_parameters(f32, f32) __asm__("FUN_L00_0020a1e0"); extern void FUN_L17_00207150(f32, f32); @@ -718,7 +718,7 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { f32 sp = hero.ground_speed * - FUN_L00_00209018(l17_swim_speed_scale_by_animation_frame, 0x1E) * 5.0f; + vector_length_xyz_cf(l17_swim_speed_scale_by_animation_frame, 0x1E) * 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -844,7 +844,7 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { f32 sp = hero.ground_speed * - FUN_L00_00209018(l17_swim_speed_scale_by_animation_frame, 0x1E) * 5.5f; + vector_length_xyz_cf(l17_swim_speed_scale_by_animation_frame, 0x1E) * 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; diff --git a/src/overlays/l18/hero/update_hero_motion_for_current_state.c b/src/overlays/l18/hero/update_hero_motion_for_current_state.c index 95501585d6..f0ad661977 100644 --- a/src/overlays/l18/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l18/hero/update_hero_motion_for_current_state.c @@ -166,7 +166,7 @@ extern void moby_point_position(struct MobyView *, s32, void *) __asm__("FUN_L00 extern u8 *FUN_L00_0026f080(void *, void *, f32, f32); extern s32 random_int_between(s32, s32) __asm__("FUN_L00_00257b90"); extern void FUN_L00_00262cf0(void *, void *, f32, f32, f32); -extern f32 FUN_L00_00209018(void *, s32); +extern f32 vector_length_xyz_cf(void *, s32) __asm__("FUN_L00_00209018"); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern void set_first_hero_easing_parameters(f32, f32) __asm__("FUN_L00_0020a1e0"); extern void FUN_L18_002123f0(f32, f32); @@ -683,7 +683,7 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { f32 sp = - hero.ground_speed * FUN_L00_00209018(hero_swim_speed_scale_data, 0x1E) * 5.0f; + hero.ground_speed * vector_length_xyz_cf(hero_swim_speed_scale_data, 0x1E) * 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -815,7 +815,7 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { f32 sp = - hero.ground_speed * FUN_L00_00209018(hero_swim_speed_scale_data, 0x1E) * 5.5f; + hero.ground_speed * vector_length_xyz_cf(hero_swim_speed_scale_data, 0x1E) * 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index ad3932c13f..752d9c9203 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -2201,9 +2201,9 @@ f32 adjust_hero_animation_speed_for_target_frame(f32 target_anim_frame, /* Ported from rac1-decomp (src/overlays/shared/help_00203E98.c: func_L00_00209690), where it is exact; names translated to the US level program. */ -float FUN_L00_00209018(float *a, int n); +float vector_length_xyz_cf(float *a, int n) __asm__("FUN_L00_00209018"); -float FUN_L00_00209018(float *sample_values, int sample_count) { +float vector_length_xyz_cf(float *sample_values, int sample_count) { char sample_integral_part_scratch[16] __attribute__((aligned(16))); struct Hero *hero_base = (struct Hero *)((char *)((unsigned char *)&D_0013E533) + 0xE1D); int i = truncate_float_to_s32(hero_base->anim_frame); diff --git a/src/overlays/shared/hero/hero_update_movement.c b/src/overlays/shared/hero/hero_update_movement.c index 12c1d87be6..c4b5ac1c42 100644 --- a/src/overlays/shared/hero/hero_update_movement.c +++ b/src/overlays/shared/hero/hero_update_movement.c @@ -127,7 +127,7 @@ extern void moby_point_position(struct MobyView *, s32, void *) __asm__("FUN_L00 extern u8 *FUN_L00_0026f080(void *, void *, f32, f32); extern s32 random_int_between(s32, s32) __asm__("FUN_L00_00257b90"); extern void FUN_L00_00262cf0(void *, void *, f32, f32, f32); -extern f32 FUN_L00_00209018(void *, s32); +extern f32 vector_length_xyz_cf(void *, s32) __asm__("FUN_L00_00209018"); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern void set_first_hero_easing_parameters(f32, f32) __asm__("FUN_L00_0020a1e0"); extern void set_fourth_hero_easing_parameters(f32, f32) __asm__("FUN_L00_0020a228"); @@ -683,7 +683,7 @@ void hero_update_movement(void) { &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { f32 sp = hero.ground_speed * - FUN_L00_00209018(l00_swim_speed_scale_by_animation_frame, 0x1E) * 5.0f; + vector_length_xyz_cf(l00_swim_speed_scale_by_animation_frame, 0x1E) * 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -808,7 +808,7 @@ void hero_update_movement(void) { speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { f32 sp = hero.ground_speed * - FUN_L00_00209018(l00_swim_speed_scale_by_animation_frame, 0x1E) * 5.5f; + vector_length_xyz_cf(l00_swim_speed_scale_by_animation_frame, 0x1E) * 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; From 44bb7a96d569aed1b11692748b59a48b6a0071e4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:15:46 +0000 Subject: [PATCH 0008/1502] decomp: clarify names in jet_group_flag D_L13_0015FFE0 -> l13_moby_scan_inclusive_end: In the bound source src/overlays/l13/mobys/fighter_jet.c (SHA-256 7fde235c32fe2216015bec2fe6ebddc50adbf3cf43065bdd17c3173f0821f76c), jet_group_flag starts moby at moby_base and scans while D_L13_0015FFE0 >= moby, advancing by 0x100. Retail 0x00265178-0x00265184 loads 0x0015FFE0 and rejects an initial slot above it; 0x002651a4-0x002651b4 reloads that bound, advances v1 by 0x100, and loops when v1 is not above the bound. Slot fields at +0xA6 and +0x20 identify the scanned objects as mobys. Thus this level-13 pointer is the inclusive moby scan endpoint; no allocator or population semantics are assumed. --- src/overlays/l13/mobys/fighter_jet.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l13/mobys/fighter_jet.c b/src/overlays/l13/mobys/fighter_jet.c index 4e0baed8f2..3adac16769 100644 --- a/src/overlays/l13/mobys/fighter_jet.c +++ b/src/overlays/l13/mobys/fighter_jet.c @@ -113,20 +113,20 @@ short D_L13_00161418 = 0x7f00; /* Sets the state of every live moby of class id whose state is not negative. */ /* Ported from rac1-decomp (src/overlays/l13_gemlik/mobyutil_00266128.c: func_L13_00266128), where it is exact; names translated to the US level program. */ -extern char *D_L13_0015FFE0; +extern char *l13_moby_scan_inclusive_end __asm__("D_L13_0015FFE0"); void jet_group_flag(int id, int state) __asm__("FUN_L13_00265170"); void jet_group_flag(int id, int state) { char *moby = (char *)moby_base; - if ((unsigned long)D_L13_0015FFE0 >= (unsigned long)moby) { + if ((unsigned long)l13_moby_scan_inclusive_end >= (unsigned long)moby) { do { if (MOBY(moby)->oclass == id) { if (moby[0x20] >= 0) moby[0x20] = state; } moby += 0x100; - } while ((unsigned long)D_L13_0015FFE0 >= (unsigned long)moby); + } while ((unsigned long)l13_moby_scan_inclusive_end >= (unsigned long)moby); } } @@ -141,7 +141,7 @@ void jet_group_switch(short *ids, int copy_data_pointer) { char *moby; - for (moby = (char *)moby_base; moby <= D_L13_0015FFE0; moby += 0x100) { + for (moby = (char *)moby_base; moby <= l13_moby_scan_inclusive_end; moby += 0x100) { int id_index; for (id_index = 0; ids[id_index] != 0 && ids[id_index] < 0x800 && id_index < 0xE0; id_index++) { From 1d310aee702a1c5b81e935f177f0855137553f98 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:15:46 +0000 Subject: [PATCH 0009/1502] decomp: clarify names in vo_buf_get_tag buf -> picture_queue: In vo_buf_get_tag, struct VoBuf *buf is checked with vo_buf_is_empty and owns tag/write/count/size. Retail 0x0023d2e8 preserves the argument in s0; 0x0023d2f4, 0x0023d2fc and 0x0023d304 load write/count/size at offsets 8/12/16. Instructions 0x0023d308-0x0023d320 compute (write-count+size)%size; 0x0023d31c loads the tag array at offset 4, and 0x0023d324-0x0023d328 scale the index by 0x138c0 and add that array. Together with the source's oldest-picture comment, this proves the argument represents the picture queue whose oldest pending tag is returned. --- src/movies/decoder/video_output/vo_buf_get_tag.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/movies/decoder/video_output/vo_buf_get_tag.c b/src/movies/decoder/video_output/vo_buf_get_tag.c index 90c76a12c6..79b32ce320 100644 --- a/src/movies/decoder/video_output/vo_buf_get_tag.c +++ b/src/movies/decoder/video_output/vo_buf_get_tag.c @@ -4,9 +4,9 @@ struct VoTag *vo_buf_get_tag(struct VoBuf *buf) __asm__("FUN_0023d2d8"); /* The oldest picture not yet shown. */ -struct VoTag *vo_buf_get_tag(struct VoBuf *buf) { - if (vo_buf_is_empty(buf) != 0) { +struct VoTag *vo_buf_get_tag(struct VoBuf *picture_queue) { + if (vo_buf_is_empty(picture_queue) != 0) { return 0; } - return buf->tag + (buf->write - buf->count + buf->size) % buf->size; + return picture_queue->tag + (picture_queue->write - picture_queue->count + picture_queue->size) % picture_queue->size; } From e37fe6a558d36e44d88641e321a1f90df2a2f0ee Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:15:46 +0000 Subject: [PATCH 0010/1502] decomp: clarify names in queue_language_zero_movie a -> queued_movie_sector: In queue_language_zero_movie, s32 a receives disc_table.unk1A50[i].sector or unk1A28[i].sector. Retail loads v1 at 0x0029952c (+0x1a50) or 0x00299544 (+0x1a28), then moves v1 to a0 at 0x00299548 for prepare_movie_playback at 0x0029954c. Original Ghidra uVar2 follows this same first-argument path. The established callee's sector parameter is stored at 0x00161048 for queued movie playback. b -> queued_movie_size: In queue_language_zero_movie, s32 b receives disc_table.unk1A50[i].size or unk1A28[i].size. Retail loads a1 at 0x00299524 (+0x1a54) or 0x00299540 (+0x1a2c), preserving it as the second argument of prepare_movie_playback at 0x0029954c. Original Ghidra uVar1 follows this same second-argument path. The established callee's size parameter is stored at 0x0016104c for queued movie playback. --- .../shared/cutscenes/update_cutscene_playback.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/cutscenes/update_cutscene_playback.c b/src/overlays/shared/cutscenes/update_cutscene_playback.c index fd86cb5853..1a7658c5e1 100644 --- a/src/overlays/shared/cutscenes/update_cutscene_playback.c +++ b/src/overlays/shared/cutscenes/update_cutscene_playback.c @@ -846,17 +846,17 @@ void queue_scene_movie_with_game_language(s32 i) { void queue_language_zero_movie(s32 i) __asm__("FUN_L00_002994f8"); void queue_language_zero_movie(s32 i) { - s32 a, b; + s32 queued_movie_sector, queued_movie_size; if (i < 0) return; if (D_0015ED80) { - a = disc_table.unk1A50[i].sector; - b = disc_table.unk1A50[i].size; + queued_movie_sector = disc_table.unk1A50[i].sector; + queued_movie_size = disc_table.unk1A50[i].size; } else { - a = disc_table.unk1A28[i].sector; - b = disc_table.unk1A28[i].size; + queued_movie_sector = disc_table.unk1A28[i].sector; + queued_movie_size = disc_table.unk1A28[i].size; } - prepare_movie_playback(a, b, 0); + prepare_movie_playback(queued_movie_sector, queued_movie_size, 0); } /* Passes movie i (the alt table while D_0015ED80 is set) and the language to FUN_L00_002995d0. */ From 31dcad84b6de942c2c35cc9565f892406f277ae2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:17:57 +0000 Subject: [PATCH 0011/1502] decomp: clarify names in update_moby_camera_control D_L02_0015EF50 -> l02_moby_record_table: Retail 0x002fc2b8 loads the pointer stored at 0x0015ef50 into a1; 0x002fc2b0 loads the signed record index at moby+0x84, 0x002fc2bc multiplies it by 32, 0x002fc2c4 adds the table base, and 0x002fc2cc loads the record's +0x1c camera-control pointer. The supplied authoritative C repeats this lookup in update_moby_camera_control, apply_moby_camera_control and the activation test, and reads a heading from record+0x18. This proves a moby-indexed record table base, with l02 distinguishing its overlay binding. --- .../shared/camera/moby_controlled_camera.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/camera/moby_controlled_camera.c b/src/overlays/shared/camera/moby_controlled_camera.c index b48e50b6a3..8c01d8f173 100644 --- a/src/overlays/shared/camera/moby_controlled_camera.c +++ b/src/overlays/shared/camera/moby_controlled_camera.c @@ -50,7 +50,7 @@ set_follow_camera_angle_blend_from_position(float, float, void *) __asm__("FUN_L extern char *D_L02_001B0AB0[]; extern char *D_L02_00167400_d __asm__("D_L02_00167400") NOT_SDA; -extern char *D_L02_0015EF50; +extern char *l02_moby_record_table __asm__("D_L02_0015EF50"); extern char *D_L02_001674DC NOT_SDA; extern char D_L02_00167410[] NOT_SDA; extern LevelCamera l02_camera_lui __asm__("D_L02_00167280") NOT_SDA; @@ -73,7 +73,7 @@ int test_moby_camera_control_activation(char *moby) __asm__("FUN_L02_002fb648"); int test_moby_camera_control_activation(char *moby) { char *special = D_L02_001674DC; MobyCameraControl *camera_control_entry = - (MobyCameraControl *)(*(char **)(D_L02_0015EF50 + *(short *)(moby + 0x84) * 32 + 0x1c)); + (MobyCameraControl *)(*(char **)(l02_moby_record_table + *(short *)(moby + 0x84) * 32 + 0x1c)); char *target = camera_control_entry->target; int *activation_path_record; int hero_containment_result; @@ -146,7 +146,7 @@ int test_moby_camera_target_angle_limits(char *moby, float residual_angle_limit_ float dot3; float den; - char *moby_record_table = D_L02_0015EF50; + char *moby_record_table = l02_moby_record_table; char *target_moby; moby_camera_control_entry = *(char **)(moby_record_table + *(short *)(moby + 0x84) * 32 + 0x1C); @@ -192,7 +192,7 @@ void apply_moby_camera_control(char *moby) __asm__("FUN_L02_002fb9c8"); void apply_moby_camera_control(char *moby) { MobyCameraControl *moby_camera_control_record = - (MobyCameraControl *)(*(char **)(D_L02_0015EF50 + *(short *)(moby + 0x84) * 32 + 0x1c)); + (MobyCameraControl *)(*(char **)(l02_moby_record_table + *(short *)(moby + 0x84) * 32 + 0x1c)); char *target; unsigned short *group; int id; @@ -279,7 +279,7 @@ void apply_moby_camera_control(char *moby) { angle = fast_arc_tan(*(float *)D_L02_00167400_d, *(float *)(D_L02_00167400_d + 4)); if (moby_camera_control_record->unk20 < 2) moby_camera_control_record->unk40 = - *(float *)(D_L02_0015EF50 + *(short *)(moby + 0x84) * 32 + 0x18); + *(float *)(l02_moby_record_table + *(short *)(moby + 0x84) * 32 + 0x18); else if (absolute_float(controller_state.analog[0]) >= 0.3f || absolute_float(controller_state.analog[1]) >= 0.3f) moby_camera_control_record->unk40 = angle; @@ -288,7 +288,7 @@ void apply_moby_camera_control(char *moby) { fast_add_rotations(heading, 3.1415927f); } if (moby_camera_control_record->unk3C == 4) { - heading = *(float *)(D_L02_0015EF50 + *(short *)(moby + 0x84) * 32 + 0x18); + heading = *(float *)(l02_moby_record_table + *(short *)(moby + 0x84) * 32 + 0x18); angle = fast_arc_tan(*(float *)D_L02_00167400_d, *(float *)(D_L02_00167400_d + 4)); if (fast_difference_between_rotations(heading, angle) > 1.5707964f) heading = fast_add_rotations(heading, 3.1415927f); @@ -451,7 +451,7 @@ int update_moby_camera_control(char *moby) __asm__("FUN_L02_002fc298"); int update_moby_camera_control(char *moby) { char *moby_camera_control_data = - *(char **)(D_L02_0015EF50 + *(short *)(moby + 0x84) * 32 + 0x1C); + *(char **)(l02_moby_record_table + *(short *)(moby + 0x84) * 32 + 0x1C); if (*(short *)(D_L02_00167400_lui + 0x86) == 0 && *(short *)(moby_camera_control_data + 0x20) >= 0) apply_moby_camera_control(moby); From 354eb4e1e8b9aa04ff313bb522543419672943e9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:18:04 +0000 Subject: [PATCH 0012/1502] decomp: clarify names in advance_moby_along_path D_L14_00161A30 -> l14_racer_path_follow_speed: The authoritative source declares this SDA object as float and passes D_L14_00161A30 * frame_time as the traversal distance to sample_path. Retail 0x002d71ac loads this scalar into f0; 0x002d71bc loads frame_time into f12; 0x002d71c8 multiplies them before the call at 0x002d71d8 to 0x00265b88 (FUN_L00_0025d808). The same call receives moby position at +0x10 and mutable path segment/offset at pvars +0x64/+0x68. Supplied helper findings establish traversal by this distance. The checked caller invokes advance_moby_along_path(racer_moby) in RACER_STATE_FOLLOW_PATH, proving racer path-follow speed without claiming precise units. --- src/overlays/l14/mobys/racer_path_and_weapon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/racer_path_and_weapon.c b/src/overlays/l14/mobys/racer_path_and_weapon.c index b34a958862..78086d18b7 100644 --- a/src/overlays/l14/mobys/racer_path_and_weapon.c +++ b/src/overlays/l14/mobys/racer_path_and_weapon.c @@ -526,7 +526,7 @@ void update_racer_path_and_weapon(struct Moby *racer_moby) { } /* Ported from rac1-decomp (src/overlays/l14_oltanis/vendor_002ACCC0.c: func_L14_002D84A8), where it is exact; names translated to the US level program. */ -extern float D_L14_00161A30 __attribute__((sda)); +extern float l14_racer_path_follow_speed __asm__("D_L14_00161A30") __attribute__((sda)); void advance_moby_along_path(struct Moby *moby) __asm__("FUN_L14_002d7198"); void advance_moby_along_path(struct Moby *moby) { @@ -537,7 +537,7 @@ void advance_moby_along_path(struct Moby *moby) { &path_tracking_state->unk64, &path_tracking_state->unk68, 0, - D_L14_00161A30 * frame_time); + l14_racer_path_follow_speed * frame_time); } /* Draws the racer's two glow quads, at its lamp (0xE0) and its tail (0x200), turned to face the camera. */ From 465e2117e56488a279211a1f4af1f727188f049e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:18:04 +0000 Subject: [PATCH 0013/1502] decomp: clarify names in find_moby_hit a -> hit_slot_address: In the authoritative source src/overlays/shared/mobys/find_moby_hit.c (SHA-256 788dea0cb55c595c5a9c2664e96384863d98c9622013eb256b16cd4c063cd9d4), u8 *a = owner_moby + 0xA4 is dereferenced through load_u8_0025a420 to obtain i and test the 0xFF sentinel. Retail 0x0025a420 loads this byte; 0x0025a428 tests 0xFF; 0x0025a434 shifts the loaded slot by 6 to select moby_hits at 0x00178100. The original Ghidra decompilation shows the same byte lookup and 0x40-byte stride. The embedded record_moby_hit producer stores i into owner_moby->hit_slot, proving that a addresses the hit-slot byte. --- src/overlays/shared/mobys/find_moby_hit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/mobys/find_moby_hit.c b/src/overlays/shared/mobys/find_moby_hit.c index 25eb5766ae..9d17e4e86c 100644 --- a/src/overlays/shared/mobys/find_moby_hit.c +++ b/src/overlays/shared/mobys/find_moby_hit.c @@ -381,9 +381,9 @@ MobyHit *find_moby_hit(u8 *p, s32 mask, s32 flag) __asm__("FUN_L00_0025a420"); MobyHit *find_moby_hit(u8 *owner_moby, s32 mask, s32 flag) { MobyHit *hit_record; - u8 *a = owner_moby + 0xA4; - u8 i = load_u8_0025a420(a); - if (load_u8_0025a420(a) == 0xFF) + u8 *hit_slot_address = owner_moby + 0xA4; + u8 i = load_u8_0025a420(hit_slot_address); + if (load_u8_0025a420(hit_slot_address) == 0xFF) return 0; hit_record = &moby_hits[i]; if (hit_record->owner != owner_moby) From 875aa205e18dedde832d088f2371b8a7a21b11d7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:18:13 +0000 Subject: [PATCH 0014/1502] decomp: clarify names in queue_dialogue_message D_L00_00179118 -> l00_dialogue_message_text_buffer: Retail 0x00263d70 and 0x00263d7c construct 0x00179118 in s0; 0x00263d80 passes it as a0 to the copy at 0x00263d84, while 0x00263d88 supplies the message lookup return as a1. The authoritative source declares this binding extern u8[] and queue_dialogue_message copies get_help_message_text(message_id) into it, then stores message_duration_frames. Adjacent queue_formatted_dialogue_message also uses this same array as sprintf destination for the help message and format argument. This proves a dialogue message text buffer; l00 qualifies the assigned overlay binding. --- src/overlays/shared/mobys/select_auto_aim_target_moby.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/mobys/select_auto_aim_target_moby.c b/src/overlays/shared/mobys/select_auto_aim_target_moby.c index c3cb3f3cb1..60a4ae2b00 100644 --- a/src/overlays/shared/mobys/select_auto_aim_target_moby.c +++ b/src/overlays/shared/mobys/select_auto_aim_target_moby.c @@ -439,7 +439,7 @@ void draw_trail(void *first_spawn_position, } extern int D_L00_0015F640; -extern u8 D_L00_00179118[]; +extern u8 l00_dialogue_message_text_buffer[] __asm__("D_L00_00179118"); int get_help_message_text(int) __asm__("FUN_001fdd10"); void FUN_001165b8_00263d40(char *, int) __asm__("FUN_001165b8"); /* Calls strcpy with D_L00_00179118 and get_help_message_text(a); stores b (default 0xB4 frames). */ @@ -448,7 +448,7 @@ void queue_dialogue_message(int a, int b) __asm__("FUN_L00_00263d40"); void queue_dialogue_message(int message_id, int message_duration_frames) { if (message_duration_frames == -1) message_duration_frames = scale_game_frames(0xB4); - FUN_001165b8_00263d40(D_L00_00179118, get_help_message_text(message_id)); + FUN_001165b8_00263d40(l00_dialogue_message_text_buffer, get_help_message_text(message_id)); D_L00_0015F640 = message_duration_frames; } @@ -463,7 +463,7 @@ void queue_formatted_dialogue_message(s32 help_message_selector, s32 message_duration_frames) { if (message_duration_frames == -1) message_duration_frames = scale_game_frames(0xB4); - sprintf(D_L00_00179118, get_help_message_text(help_message_selector), format_argument); + sprintf(l00_dialogue_message_text_buffer, get_help_message_text(help_message_selector), format_argument); D_L00_0015F640 = message_duration_frames; } From 787d3d388f226a2f9a5ca81c0efe0c3f9adc6f9f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:20:19 +0000 Subject: [PATCH 0015/1502] decomp: clarify names in transition_moby_group_state_1_to_2 D_L06_0015FFD8 -> level_mobys_q: Retail 0x002f96c4-0x002f96c8 loads the pointer stored at 0x0015ffd8 into a0. At 0x002f96c0 and 0x002f96cc-0x002f96d4 a group-list halfword is masked with 0x7fff, shifted left 8, and added to that pointer, selecting a 0x100-byte moby record; 0x002f96d8-0x002f96e0 reads and conditionally writes its state at +0x20. Original Ghidra expresses the same base as iRam0015ffd8. The authoritative C declares extern char *D_L06_0015FFD8 and uses it identically; its other consumer compute_alien_snapper_target_gap_angle uses the same index*256 base and accesses positions at +0x10/+0x14. Reuse supplied existing name level_mobys_q for this identical assembler label, preserving the pointer type and assembler binding. --- src/overlays/l06/mobys/alien_snapper.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l06/mobys/alien_snapper.c b/src/overlays/l06/mobys/alien_snapper.c index e847df38eb..77b2dffe06 100644 --- a/src/overlays/l06/mobys/alien_snapper.c +++ b/src/overlays/l06/mobys/alien_snapper.c @@ -25,7 +25,7 @@ void transition_moby_group_state_1_to_2(char *group_source_moby) __asm__("FUN_L0 /* angle from a moby to its owner, clamped to the gaps between obstacles in its list */ /* Ported from rac1-decomp (src/overlays/l06_blarg/vendor_002B5990.c: func_L06_002FAB28), where it is exact; names translated to the US level program. */ -extern char *D_L06_0015FFD8; +extern char *level_mobys_q __asm__("D_L06_0015FFD8"); extern char D_0013E533[]; extern short *D_L06_001ABFC0_p[] __asm__("D_L06_001ABFC0"); extern short alien_snapper_gap_angle_limit_degrees_gp __asm__("D_L06_00161ED8") @@ -847,7 +847,7 @@ void transition_moby_group_state_1_to_2(char *group_source_moby) { if (table != 0) { short *moby_index_cursor = table; do { - char *moby = (char *)(((*moby_index_cursor & 0x7FFF) << 8) + (int)D_L06_0015FFD8); + char *moby = (char *)(((*moby_index_cursor & 0x7FFF) << 8) + (int)level_mobys_q); if ((unsigned char)moby[0x20] == 1) { moby[0x20] = 2; } @@ -881,12 +881,12 @@ float compute_alien_snapper_target_gap_angle(char *snapper_moby) { } do { int listed_moby_index = *(unsigned short *)moby_index_cursor & 0x7FFF; - char *listed_moby = (char *)(listed_moby_index * 256 + (int)D_L06_0015FFD8); + char *listed_moby = (char *)(listed_moby_index * 256 + (int)level_mobys_q); if ((unsigned char)listed_moby[0x20] == 8 || fast_vec_dist(listed_moby + 0x10, target_moby + 0x10) < owner_to_self_distance) { - float d = fast_arc_tan(*(float *)(D_L06_0015FFD8 + listed_moby_index * 256 + 0x10) - + float d = fast_arc_tan(*(float *)(level_mobys_q + listed_moby_index * 256 + 0x10) - *(float *)(target_moby + 0x10), - *(float *)(D_L06_0015FFD8 + listed_moby_index * 256 + 0x14) - + *(float *)(level_mobys_q + listed_moby_index * 256 + 0x14) - *(float *)(target_moby + 0x14)); float listed_moby_angle_offset_radians = fast_subtract_rotations(d, owner_to_self_angle_radians); From 9fc810e4b1d7bb6b28f3a673d8cc790d93122c28 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:21:44 +0000 Subject: [PATCH 0016/1502] decomp: clarify names in vo_buf_create buf -> buffer_descriptor: In authoritative src/movies/decoder/video_output/vo_buf_create.c (SHA-256 2894efe6065f7421d9899725d294c5d64360a4e2ed41ae80b7d41432921b63a6), buf is struct VoBuf*: its data/tag/size fields receive the other arguments and count/write are reset. Original Ghidra param_1[0..4] agrees with retail stores at 0x0023d190..0x0023d1a0 to a0+0xc, +0, +4, +0x10 and +8. At 0x0023d1b8, a0+4 supplies the tag base for zero stores at 0x138c0 strides. This proves an address/count buffer descriptor, rather than the payload buffer itself. --- src/movies/decoder/video_output/vo_buf_create.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/movies/decoder/video_output/vo_buf_create.c b/src/movies/decoder/video_output/vo_buf_create.c index 79a16fbed6..eaaf2fb606 100644 --- a/src/movies/decoder/video_output/vo_buf_create.c +++ b/src/movies/decoder/video_output/vo_buf_create.c @@ -6,16 +6,16 @@ void vo_buf_create(struct VoBuf *buf, struct VoTag *tag, s32 size) __asm__("FUN_0023d190"); -void vo_buf_create(struct VoBuf *buf, struct VoData *data, struct VoTag *tag, s32 size) { +void vo_buf_create(struct VoBuf *buffer_descriptor, struct VoData *data, struct VoTag *tag, s32 size) { s32 i; - buf->count = 0; - buf->data = data; - buf->tag = tag; - buf->size = size; - buf->write = 0; + buffer_descriptor->count = 0; + buffer_descriptor->data = data; + buffer_descriptor->tag = tag; + buffer_descriptor->size = size; + buffer_descriptor->write = 0; for (i = 0; i < size; i++) { - buf->tag[i].status = 0; + buffer_descriptor->tag[i].status = 0; } } From 57a93b2312bf65037ca51ecc78b958afde6243af Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:33:31 +0000 Subject: [PATCH 0017/1502] overlay: name step_mover_2e3f20 --- src/overlays/l02/mobys/constructorbot.c | 6 +++--- src/overlays/l03/mobys/kerwan_path_enemy.c | 8 ++++---- src/overlays/l03/mobys/mine_layer.c | 4 ++-- src/overlays/l03/mobys/robot_dog.c | 4 ++-- src/overlays/l05/mobys/extermitank.c | 6 +++--- src/overlays/l07/mobys/snagglebeast.c | 4 ++-- src/overlays/l08/mobys/blarg_bombthrower.c | 8 ++++---- src/overlays/shared/enemies/blarg_paratrooper.c | 6 +++--- src/overlays/shared/enemies/sandmouse.c | 4 ++-- src/overlays/shared/math/interpolation/spring_turn.c | 4 ++-- src/overlays/shared/weapons/doom_bot.c | 4 ++-- 11 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/overlays/l02/mobys/constructorbot.c b/src/overlays/l02/mobys/constructorbot.c index cb5dd725c9..f2031187fe 100644 --- a/src/overlays/l02/mobys/constructorbot.c +++ b/src/overlays/l02/mobys/constructorbot.c @@ -85,7 +85,7 @@ int D_L02_00161A94 = 0x78; extern float constructorbot_wake_spray_planar_magnitude_max_gp __asm__("D_L02_00161A98") __attribute__((sda)); extern float approach_value(float *p, float target, float maxstep) __asm__("FUN_00213ed8"); -extern int FUN_L00_00259028(char *m, char *p, float *pos, char *v); +extern int step_mover_2e3f20(char *m, char *p, float *pos, char *v) __asm__("FUN_L00_00259028"); extern s32 rand(void); extern void *FUN_L00_00263fd8(char *src, int cls, @@ -274,7 +274,7 @@ void constructorbot_update(struct Moby *moby) { } break; case L02_BOT_MOVE_TO_POST: - if (FUN_L00_00259028((char *)moby, + if (step_mover_2e3f20((char *)moby, bot_private_vars->walk, (float *)&l02_cuboids[bot_private_vars->post].pos, (char *)bot_private_vars->velocity) == 4) { @@ -285,7 +285,7 @@ void constructorbot_update(struct Moby *moby) { } break; case L02_BOT_WANDER: - if (FUN_L00_00259028((char *)moby, + if (step_mover_2e3f20((char *)moby, bot_private_vars->walk, bot_private_vars->wander, (char *)bot_private_vars->velocity) & diff --git a/src/overlays/l03/mobys/kerwan_path_enemy.c b/src/overlays/l03/mobys/kerwan_path_enemy.c index b1a6395cfe..d660fe70c3 100644 --- a/src/overlays/l03/mobys/kerwan_path_enemy.c +++ b/src/overlays/l03/mobys/kerwan_path_enemy.c @@ -263,7 +263,7 @@ extern Moby2C8398 *D_L03_0015FFD8_m __asm__("D_L03_0015FFD8"); int D_L03_001618F4_i __asm__("D_L03_001618F4") = 0; extern int coll_sphere(float, void *, int, void *) __asm__("FUN_L00_001f0d60"); extern int is_value_within_interpolated_window(char *, float) __asm__("FUN_00214cc8"); -extern int FUN_L00_0025df68_cf(char *m, char *p, float *pos, char *v) __asm__("FUN_L00_00259028"); +extern int step_mover_2e3f20(char *m, char *p, float *pos, char *v) __asm__("FUN_L00_00259028"); extern int fast_subtract_rotations_cf(void *) __asm__("FUN_L00_001fefc8"); extern int probe_ground_height_cf(int unused, char *m, char *a, void *b, char *c, void *d) __asm__("FUN_L00_00260400"); extern short D_L03_001618F4 __attribute__((sda)); @@ -800,7 +800,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { break; } } - if (!(FUN_L00_0025df68_cf((char *)m, + if (!(step_mover_2e3f20((char *)m, (char *)&moby_data->mv, (float *)(pf->path + 0x10 + pf->idx * 0x10), (char *)moby_data->v40) & @@ -858,7 +858,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { if (pf->idx < seg) { pf->idx = seg; } - if (!(FUN_L00_0025df68_cf((char *)m, + if (!(step_mover_2e3f20((char *)m, (char *)&moby_data->mv, (float *)(pf->path + 0x10 + pf->idx * 0x10), (char *)moby_data->v40) & @@ -891,7 +891,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { if (moby_data->i298 < seg) { moby_data->i298 = seg; } - if (!(FUN_L00_0025df68_cf((char *)m, + if (!(step_mover_2e3f20((char *)m, (char *)&moby_data->mv, (float *)(path + 0x10 + moby_data->i298 * 0x10), (char *)moby_data->v40) & diff --git a/src/overlays/l03/mobys/mine_layer.c b/src/overlays/l03/mobys/mine_layer.c index 111212c9ab..397bf3aafc 100644 --- a/src/overlays/l03/mobys/mine_layer.c +++ b/src/overlays/l03/mobys/mine_layer.c @@ -92,7 +92,7 @@ char *spawn_mine_layer_projectile(char *p, void *pos, float *dir) __asm__( extern void FUN_L01_0026d930(void *); extern void blend_moby_animation(struct Moby *, int, int, int) __asm__("FUN_00212f90"); extern void FUN_L00_00258278(f32, f32, f32, f32, struct Moby *, void *); -extern void FUN_L00_00259028(struct Moby *, void *, void *, void *); +extern void step_mover_2e3f20(struct Moby *, void *, void *, void *) __asm__("FUN_L00_00259028"); extern void trooper_play_sound(int, int, struct Moby *, int) __asm__("FUN_L00_0028dc90"); extern int step_moby_motion(struct Moby *, void *) __asm__("FUN_L00_0025c698"); extern void spawn_explosion(struct Moby *, @@ -211,7 +211,7 @@ void mine_layer_update(struct Moby *mine_layer_moby) { case MINE_LAYER_PATROL_AND_FIRE: pt = &mine_layer_vars->patrol; patrol_point_index = pt->idx; - FUN_L00_00259028(mine_layer_moby, + step_mover_2e3f20(mine_layer_moby, mine_layer_vars->walk, &pt->path->points[patrol_point_index], mine_layer_vars->effect); diff --git a/src/overlays/l03/mobys/robot_dog.c b/src/overlays/l03/mobys/robot_dog.c index 59a51c14ba..3b467e94e6 100644 --- a/src/overlays/l03/mobys/robot_dog.c +++ b/src/overlays/l03/mobys/robot_dog.c @@ -104,7 +104,7 @@ extern float D_L03_0015F580_macro[] __asm__("D_L03_0015F580") MACRO_ADDR; extern float FUN_L04_001f1978(float); extern int rand(void) __asm__("FUN_001160d8"); extern int FUN_L00_00258b50(void *, void *, void *, void *, float); -extern int FUN_L00_00259028(char *m, char *p, char *pos, char *v); +extern int step_mover_2e3f20(char *m, char *p, char *pos, char *v) __asm__("FUN_L00_00259028"); extern int FUN_L00_002dc9f0(void *, void *); extern int select_moby_target_with_hero_fallback(char *, char *, float) __asm__("FUN_L03_0024e830"); extern void FUN_L00_00257470(void *, int, int); @@ -305,7 +305,7 @@ void robot_dog_update(char *moby) { if (robot_dog_state->i278 < seg) { robot_dog_state->i278 = seg; } - if (FUN_L00_00259028(moby, + if (step_mover_2e3f20(moby, (char *)&robot_dog_state->i180, (char *)path + (robot_dog_state->i278 * 0x10 + 0x10), (char *)robot_dog_state->v40) & diff --git a/src/overlays/l05/mobys/extermitank.c b/src/overlays/l05/mobys/extermitank.c index 3e43117965..260b1e13a9 100644 --- a/src/overlays/l05/mobys/extermitank.c +++ b/src/overlays/l05/mobys/extermitank.c @@ -33,7 +33,7 @@ extern int collision_line(void *, void *, int, void *, void *) __asm__("FUN_00 extern float D_0015ED6C_gp __asm__("D_0015ED6C") MACRO_ADDR; extern float step_angle_toward_target(float *, int, float, float) __asm__("FUN_L00_0025bc00"); extern int frame_number_gp __asm__("D_L05_0015F5CC") MACRO_ADDR; -extern int FUN_L00_00259028(char *m, char *p, float *pos, char *v); +extern int step_mover_2e3f20(char *m, char *p, float *pos, char *v) __asm__("FUN_L00_00259028"); extern int FUN_L00_00259740(void *, void *, int); extern s32 spawn_spark_c2(void *, void *, void *, s32, s32, s32, s32, s32, s32) __asm__("func_00218888"); @@ -263,7 +263,7 @@ void extermitank_update(unsigned char *moby) { if (dir >= 0) last = n - 1; idx = (extermitank_vars->unkC0 + n + dir) % n; - FUN_L00_00259028((char *)moby, + step_mover_2e3f20((char *)moby, &extermitank_vars->unk70, (float *)(path + (idx * 16 + 0x10)), extermitank_vars->unk40); @@ -326,7 +326,7 @@ void extermitank_update(unsigned char *moby) { if (dir >= 0) last = n - 1; idx = (extermitank_vars->unkC0 + n + dir) % n; - FUN_L00_00259028((char *)moby, + step_mover_2e3f20((char *)moby, &extermitank_vars->unk70, (float *)(path + (idx * 16 + 0x10)), extermitank_vars->unk40); diff --git a/src/overlays/l07/mobys/snagglebeast.c b/src/overlays/l07/mobys/snagglebeast.c index fa130dacd2..85a0beedf7 100644 --- a/src/overlays/l07/mobys/snagglebeast.c +++ b/src/overlays/l07/mobys/snagglebeast.c @@ -652,7 +652,7 @@ struct ChaserTarget { extern s32 level_frame_count_lui __asm__("D_L07_0015F5CC"); extern float D_0015ED6C; extern struct ChaserTarget D_L07_00173EC0; -extern int FUN_L00_00259028(struct Moby *, void *, int, void *); +extern int step_mover_2e3f20(struct Moby *, void *, int, void *) __asm__("FUN_L00_00259028"); extern int probe_vertical_ground_collision(void *, struct Moby *, int, float, float) __asm__("FUN_L00_002583f0"); int update_snagglebeast_chase_movement(struct Moby *chaser_moby, struct ChaserVars *chaser_vars, @@ -674,7 +674,7 @@ int update_snagglebeast_chase_movement( path = D_L07_001B0530[chaser_vars->path]; if (range < goal_distance) { navigation_result = - FUN_L00_00259028(chaser_moby, chaser_vars->nav, mode, chaser_vars->navOut); + step_mover_2e3f20(chaser_moby, chaser_vars->nav, mode, chaser_vars->navOut); if (navigation_result == 2) { fast_vec_sub( position_delta, diff --git a/src/overlays/l08/mobys/blarg_bombthrower.c b/src/overlays/l08/mobys/blarg_bombthrower.c index 432d560211..fd2955e440 100644 --- a/src/overlays/l08/mobys/blarg_bombthrower.c +++ b/src/overlays/l08/mobys/blarg_bombthrower.c @@ -105,7 +105,7 @@ extern float FUN_L00_0025abf0(void *, void *, void *, float, float); extern int D_L08_001619AC_gp __asm__("D_L08_001619AC") __attribute__((sda)); extern int l08_bombthrower_fade_interpolation_divisor_gp __asm__("D_L08_001619D0") __attribute__((sda)); -extern int FUN_L00_00259028(char *m, char *p, float *pos, char *v); +extern int step_mover_2e3f20(char *m, char *p, float *pos, char *v) __asm__("FUN_L00_00259028"); extern int select_nearest_xy_moby_with_hero_fallback(void *, float, void *) __asm__("FUN_L08_0026a3d0"); extern void FUN_L00_0025a120(void *); @@ -328,7 +328,7 @@ void blarg_bombthrower_update(struct Moby *moby) { bombthrower_vars->i134 = scale_game_frames(0xF0); break; case BOMBTHROWER_STATE_APPROACH_WAYPOINT: - FUN_L00_00259028((char *)moby, + step_mover_2e3f20((char *)moby, bombthrower_vars->blkD0, (float *)&bombthrower_vars->waypoint->pos, (char *)bombthrower_vars->v40); @@ -370,7 +370,7 @@ void blarg_bombthrower_update(struct Moby *moby) { } break; case BOMBTHROWER_STATE_MOVE_ONTO_WAYPOINT: - FUN_L00_00259028((char *)moby, + step_mover_2e3f20((char *)moby, bombthrower_vars->blkD0, (float *)&bombthrower_vars->waypoint->pos, (char *)bombthrower_vars->v40); @@ -425,7 +425,7 @@ void blarg_bombthrower_update(struct Moby *moby) { point[2] = 0.0f; fast_vec_add(point, point, &bombthrower_vars->waypoint->pos); if (0.2f < vector_distance_xy(&moby->pos, point)) { - FUN_L00_00259028( + step_mover_2e3f20( (char *)moby, bombthrower_vars->blkD0, point, (char *)bombthrower_vars->v40); } if (moby->anim_flags & 2) { diff --git a/src/overlays/shared/enemies/blarg_paratrooper.c b/src/overlays/shared/enemies/blarg_paratrooper.c index fdb44c7c85..9baf5f6ba7 100644 --- a/src/overlays/shared/enemies/blarg_paratrooper.c +++ b/src/overlays/shared/enemies/blarg_paratrooper.c @@ -137,7 +137,7 @@ extern void FUN_L00_00263ac8_c(float, void *, int, void *) __asm__("FUN_L00_002 extern void FUN_L00_0025a120_c(void *) __asm__("FUN_L00_0025a120"); extern void debug_print(char *, int) __asm__("FUN_001e93b0"); extern void FUN_L01_0026d930_c(void *) __asm__("FUN_L01_0026d930"); -extern void FUN_L00_00259028_c(void *, void *, void *, void *) __asm__("FUN_L00_00259028"); +extern void step_mover_2e3f20(void *, void *, void *, void *) __asm__("FUN_L00_00259028"); extern void FUN_L00_0025f730(void *, float); extern void FUN_L00_00258830_c(void *, void *, float, float, float, int) __asm__("FUN_L00_00258830"); @@ -288,7 +288,7 @@ void blarg_paratrooper_update(char *moby) { paratrooper_private_state->f1F4 = index + 2 * paratrooper_private_state->f20C; } } - FUN_L00_00259028_c(moby, + step_mover_2e3f20(moby, (char *)paratrooper_private_state + 0xD0, path + 0x10 + paratrooper_private_state->f1F4 * 16, pos); @@ -310,7 +310,7 @@ void blarg_paratrooper_update(char *moby) { paratrooper_private_state->fE0 = 0.0f; (*(unsigned char *)((char *)(moby) + 0x20)) = 3; } else { - FUN_L00_00259028_c(moby, + step_mover_2e3f20(moby, (char *)paratrooper_private_state + 0xD0, ((char *)l08_paths[paratrooper_private_state->f1D4]) + 0x10 + paratrooper_private_state->f1F4 * 16, diff --git a/src/overlays/shared/enemies/sandmouse.c b/src/overlays/shared/enemies/sandmouse.c index aad8140528..3099707c5f 100644 --- a/src/overlays/shared/enemies/sandmouse.c +++ b/src/overlays/shared/enemies/sandmouse.c @@ -491,7 +491,7 @@ extern char D_L01_0020BA30[] NOT_SDA; extern float fast_vec_dist(void *, void *); extern int debug_print() __asm__("FUN_001e93b0"); extern int FUN_L00_00257b90(int, int); -extern int FUN_L00_00259028(void *, void *, void *, void *); +extern int step_mover_2e3f20(void *, void *, void *, void *) __asm__("FUN_L00_00259028"); extern s32 collision_line(void *, void *, s32, void *, s32); extern s32 rand(void); extern short sandmouse_follow_duration_frames_gp __asm__("D_L01_00162098") __attribute__((sda)); @@ -744,7 +744,7 @@ void sandmouse_update(Moby *sandmouse_moby) { frame_time_sq * 3.1415927f, frame_time * 11.519173f); sandmouse_vars->vel.f[2] = 0; - movement_result_flags = FUN_L00_00259028( + movement_result_flags = step_mover_2e3f20( sandmouse_moby, &D_L01_001DEB38_lui, sandmouse_vars, &sandmouse_vars->vel); } if ((movement_result_flags & 6) != 0 || diff --git a/src/overlays/shared/math/interpolation/spring_turn.c b/src/overlays/shared/math/interpolation/spring_turn.c index 0709e7b915..e0ef1bce4f 100644 --- a/src/overlays/shared/math/interpolation/spring_turn.c +++ b/src/overlays/shared/math/interpolation/spring_turn.c @@ -577,8 +577,8 @@ s32 FUN_L00_00258b50(Obj *moby, void approach_w(unsigned char *, float *, float, float, float, float) __asm__("FUN_L00_00258278"); int move_w(unsigned char *, char *, float *, void *, float) __asm__("FUN_L00_00258b50"); -int FUN_L00_00259028(unsigned char *m, char *c, float *tgt, void *out); -int FUN_L00_00259028(unsigned char *moby, +int step_mover_2e3f20(unsigned char *m, char *c, float *tgt, void *out) __asm__("FUN_L00_00259028"); +int step_mover_2e3f20(unsigned char *moby, char *movement_control, float *target_position, diff --git a/src/overlays/shared/weapons/doom_bot.c b/src/overlays/shared/weapons/doom_bot.c index b955a70784..b712f13c3c 100644 --- a/src/overlays/shared/weapons/doom_bot.c +++ b/src/overlays/shared/weapons/doom_bot.c @@ -120,7 +120,7 @@ extern int try_start_moby_hop(void *, void *, void *, int) __asm__("FUN_L00_00 extern void initialize_moby_hop_trajectory(void *, void *, void *) __asm__("FUN_L00_002bf8b0"); extern int compute_moby_state_from_vertical_probe(void *) __asm__("FUN_L00_002bfec8"); extern int update_arc_motion(void *, void *) __asm__("FUN_L00_0025b440"); -extern int FUN_L00_00259028(void *, void *, void *, void *); +extern int step_mover_2e3f20(void *, void *, void *, void *) __asm__("FUN_L00_00259028"); extern void fast_vec_scale(void *, void *, f32) __asm__("FUN_001f9a68"); extern CollisionHit coll_hit __asm__("D_L00_00173E40") NOT_SDA; @@ -488,7 +488,7 @@ void doom_bot_update(struct Moby *moby) { (coll_hit.moby && ((struct Moby *)coll_hit.moby)->pclass && ((struct Moby *)coll_hit.moby)->pclass->type == 5)) { z = moby->pos.z; - move_flags = FUN_L00_00259028( + move_flags = step_mover_2e3f20( moby, &((DoomBotParams *)&hero)->damage, doom_bot_vars, &doom_bot_vars->velocity); if (absolute_float(moby->pos.z - z) > 1.0f) { moby->pos.z = z; From 933ad00b4296babd2d1147259c699216aa70e16f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:33:36 +0000 Subject: [PATCH 0018/1502] overlay: name spawn_effect --- src/overlays/l02/mobys/sand_shark.c | 4 ++-- src/overlays/l08/mobys/bomb.c | 4 ++-- src/overlays/shared/hero/hero_idle_sequence.c | 4 ++-- .../rendering/effects/update_three_phase_effect_particle.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l02/mobys/sand_shark.c b/src/overlays/l02/mobys/sand_shark.c index 1197d353b4..919cdf5c6c 100644 --- a/src/overlays/l02/mobys/sand_shark.c +++ b/src/overlays/l02/mobys/sand_shark.c @@ -240,7 +240,7 @@ extern void extern int step_moby_motion(void *, void *) __asm__("FUN_L00_0025c698"); extern void FUN_L00_00263ac8_e50(void *, int, void *, float) __asm__("FUN_L00_00263ac8"); extern void -FUN_L00_00269958_e50(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); +spawn_effect(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); extern int FUN_L00_002dc9f0_e50(void *, void *) __asm__("FUN_L00_002dc9f0"); extern void FUN_L01_0026d930_e50(void *) __asm__("FUN_L01_0026d930"); extern void emit_sand_shark_dust_burst(void *) __asm__("FUN_L02_002d3dd0"); @@ -842,7 +842,7 @@ void sand_shark_update(struct Moby *moby) { fast_vec_add(&position_or_offset_scratch, &target_or_particle_vector, &moby->pos); fast_vec_scale(&target_or_particle_vector, &target_or_particle_vector, D_0015ED6C * 5.0f); life = scale_game_frames(random_int_between(0x14, 0x28)); - FUN_L00_00269958_e50(&moby->pos, + spawn_effect(&moby->pos, &target_or_particle_vector, D_L02_001619E4, D_L02_001619E8, diff --git a/src/overlays/l08/mobys/bomb.c b/src/overlays/l08/mobys/bomb.c index 77cd306f1f..b88934010a 100644 --- a/src/overlays/l08/mobys/bomb.c +++ b/src/overlays/l08/mobys/bomb.c @@ -77,7 +77,7 @@ extern void spawn_explosion(void *, int, int) __asm__("FUN_L00_0025e450"); extern void -FUN_L00_00269958_c(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); +spawn_effect(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); extern float D_L08_0015F580_macro[] __asm__("D_L08_0015F580") MACRO_ADDR; void moby_248_update(char *moby) __asm__("FUN_L08_002d23f0"); extern float D_0015ED6C; @@ -155,7 +155,7 @@ void moby_248_update(char *moby) { *(v128_36F8 *)normalized_direction = *(v128_36F8 *)random_direction; fast_vec_normalize(normalized_direction, normalized_direction, D_0015ED6C); selected_table_entry = (int *)table_or_bounce_scratch.b + random_integer_below(4); - FUN_L00_00269958_c((moby + 0x10), + spawn_effect((moby + 0x10), normalized_direction, *selected_table_entry, 0x4FFF, diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index 752d9c9203..289d9a0f50 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -2639,7 +2639,7 @@ void emit_hero_surface_effect_burst(s32 puffs, s32 debris, s32 flash) { } void spawn_color_decaying_effect_particle(void *, void *, int) __asm__("FUN_L00_0026d598"); -void FUN_L00_00269958(void *, void *, int, int, int, int, int, int); +void spawn_effect(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); extern char D_0013F7EE[] NOT_SDA; void emit_hero_timed_effects(void) __asm__("FUN_L00_00209ec8"); @@ -2690,7 +2690,7 @@ void emit_hero_timed_effects(void) { theta = random_angle_radians(); phi = random_angle_radians(); build_spherical_offset(pt, spherical_offset_scale, theta, phi); - FUN_L00_00269958( + spawn_effect( hero_position_copy, pt, col, 0x70F0, life, small_effect_sample, large_effect_sample, 1); } frame_count = random_int_between(scale_game_frames(3), scale_game_frames(7)); diff --git a/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c b/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c index a2e43c7337..2f8fc4362f 100644 --- a/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c +++ b/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c @@ -199,8 +199,8 @@ void update_drifting_effect_particle_with_distance_fade(struct EffectParticle *p unsigned char *FUN_L00_002678b8_00269958(int) __asm__("FUN_L00_002678b8"); int FUN_001160d8_00269958(void) __asm__("FUN_001160d8"); extern unsigned char *D_L00_001B2090 NOT_SDA; -void FUN_L00_00269958(u128 *a, u128 *b, int c, int d, int n, int s1, int s2, int flag); -void FUN_L00_00269958(u128 *spawn_position, +void spawn_effect(u128 *a, u128 *b, int c, int d, int n, int s1, int s2, int flag) __asm__("FUN_L00_00269958"); +void spawn_effect(u128 *spawn_position, u128 *initial_velocity, int initial_color, int color_endpoint, From 9691bac6d201777eeb903de4f1522f5945ff1494 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:33:40 +0000 Subject: [PATCH 0019/1502] overlay: name update_path_flythrough_camera --- src/overlays/l10/level_class_tables.c | 4 ++-- src/overlays/l13/level_class_tables.c | 4 ++-- src/overlays/l14/level_class_tables.c | 4 ++-- src/overlays/l15/level_class_tables.c | 4 ++-- src/overlays/shared/camera/path_flythrough_camera.c | 4 +++- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/overlays/l10/level_class_tables.c b/src/overlays/l10/level_class_tables.c index 8a60bad711..50a6c6e77e 100644 --- a/src/overlays/l10/level_class_tables.c +++ b/src/overlays/l10/level_class_tables.c @@ -9,7 +9,7 @@ void FUN_L00_002caf40(); void FUN_L00_002ea7a0(); void FUN_L00_002ed230(); -void FUN_L10_002f5f18(); +void update_path_flythrough_camera() __asm__("FUN_L10_002f5f18"); void background_ship_2_update() __asm__("FUN_L02_002ece18"); void blarg_ship_rocket_update() __asm__("FUN_L10_002cc2e8"); void blarg_ship_update() __asm__("FUN_L10_002e4a88"); @@ -369,7 +369,7 @@ struct CameraType level_camera_types[9] __asm__("D_L10_001DDE80") __attribute__( {17, FUN_L00_002ed230, noop_main_callback, noop_main_callback, noop_main_callback}, {19, evaluate_descriptor_eligibility, initialize_path_camera, - FUN_L10_002f5f18, noop_main_callback }, + update_path_flythrough_camera, noop_main_callback }, {23, volume_camera_check, noop_main_callback, noop_main_callback, noop_main_callback}, {-1, 0, 0, 0, 0}, }; diff --git a/src/overlays/l13/level_class_tables.c b/src/overlays/l13/level_class_tables.c index a85e0ff10a..c400f3aa10 100644 --- a/src/overlays/l13/level_class_tables.c +++ b/src/overlays/l13/level_class_tables.c @@ -8,7 +8,7 @@ void FUN_L00_002caf40(); void FUN_L00_002ea7a0(); -void FUN_L10_002f5f18(); +void update_path_flythrough_camera() __asm__("FUN_L10_002f5f18"); void ammocrate_update() __asm__("FUN_L13_002e1cc8"); void asteroid_update() __asm__("FUN_L13_002e1638"); void attached_rocket_update() __asm__("FUN_L13_00305a58"); @@ -383,7 +383,7 @@ struct CameraType level_camera_types[8] __asm__("D_L13_001F6200") __attribute__( update_target_tracking_camera, conditionally_set_camera_state_three }, {19, evaluate_descriptor_eligibility, initialize_path_camera, - FUN_L10_002f5f18, noop_main_callback }, + update_path_flythrough_camera, noop_main_callback }, {23, volume_camera_check, noop_main_callback, noop_main_callback, noop_main_callback}, {-1, 0, 0, 0, 0}, }; diff --git a/src/overlays/l14/level_class_tables.c b/src/overlays/l14/level_class_tables.c index 317c860d6c..c40fea5294 100644 --- a/src/overlays/l14/level_class_tables.c +++ b/src/overlays/l14/level_class_tables.c @@ -9,7 +9,7 @@ void FUN_L00_002caf40(); void FUN_L00_002ea7a0(); void FUN_L00_002ed230(); -void FUN_L10_002f5f18(); +void update_path_flythrough_camera() __asm__("FUN_L10_002f5f18"); void audio_stream_callback_keeper_update() __asm__("FUN_L14_00303370"); void beam_slots_update() __asm__("FUN_L14_003039e0"); void blarg_heavy_interceptor_update() __asm__("FUN_L14_002ac618"); @@ -352,7 +352,7 @@ struct CameraType level_camera_types[10] __asm__("D_L14_001FDA00") __attribute__ {17, FUN_L00_002ed230, noop_main_callback, noop_main_callback, noop_main_callback}, {19, evaluate_descriptor_eligibility, initialize_path_camera, - FUN_L10_002f5f18, noop_main_callback }, + update_path_flythrough_camera, noop_main_callback }, {20, check_path_camera_priority, setup_path_camera, update_path_camera, noop_main_callback}, {21, check_path_key_camera_priority, initialize_path_key_camera, diff --git a/src/overlays/l15/level_class_tables.c b/src/overlays/l15/level_class_tables.c index a1bcedc11a..0e0537acfb 100644 --- a/src/overlays/l15/level_class_tables.c +++ b/src/overlays/l15/level_class_tables.c @@ -9,7 +9,7 @@ void FUN_L00_002caf40(); void FUN_L00_002ea7a0(); void FUN_L00_002ed230(); -void FUN_L10_002f5f18(); +void update_path_flythrough_camera() __asm__("FUN_L10_002f5f18"); void beam_slots_update() __asm__("FUN_L14_003039e0"); void billboard_projectile_update() __asm__("FUN_L01_002c7530"); void blarg_commander_update() __asm__("FUN_L12_00308918"); @@ -364,7 +364,7 @@ struct CameraType level_camera_types[10] __asm__("D_L15_001E3F00") __attribute__ {17, FUN_L00_002ed230, noop_main_callback, noop_main_callback, noop_main_callback}, {19, evaluate_descriptor_eligibility, initialize_path_camera, - FUN_L10_002f5f18, noop_main_callback }, + update_path_flythrough_camera, noop_main_callback }, {22, dispatch_moby_follow_camera_update, noop_main_callback, noop_main_callback, noop_main_callback }, diff --git a/src/overlays/shared/camera/path_flythrough_camera.c b/src/overlays/shared/camera/path_flythrough_camera.c index fc2e9ee485..7d95a95d01 100644 --- a/src/overlays/shared/camera/path_flythrough_camera.c +++ b/src/overlays/shared/camera/path_flythrough_camera.c @@ -196,7 +196,9 @@ extern float D_L10_00167358 NOT_SDA; extern float D_0013F5E0_5f18[] __asm__("D_0013F5E0"); extern void debug_point_5f18(void *, float) __asm__("FUN_001e93e8"); -void FUN_L10_002f5f18(struct UpdateCam *cam) { +void update_path_flythrough_camera(struct UpdateCam *cam) __asm__("FUN_L10_002f5f18"); + +void update_path_flythrough_camera(struct UpdateCam *cam) { float dir[4]; float offset[4]; float point[4]; From 95cea9e3255e104299925e561926426b7d20ce03 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:35:45 +0000 Subject: [PATCH 0020/1502] decomp: clarify names in draw_hud_bolt_exclamation_panel D_L00_0015F7F0_gp -> l00_hud_panel_visibility_counter_limit_gp: The authoritative extern s32 binds explicitly to assembler label D_L00_0015F7F0. In draw_hud_bolt_exclamation_panel, retail 0x0023a35c and 0x0023a3b0 load the same s32 at -0x7410(gp); conversion calls at 0x0023a360/0x0023a3b4 provide denominators for HUD +0x70 and +0x71 at 0x0023a368/0x0023a3bc. Original Ghidra independently shows both divisions by uGpffff8bf0. Each ratio is clamped to [0,1]; the first scales panel alpha and horizontal opening, and the second scales icon/text fade. The same bound declaration in source update_hud_panel_visibility caps increments of bytes +0x70 then +0x71; update_health_hud_animation_and_visibility also uses it as their cap. Thus it is the HUD panel visibility counter limit, shared by these local consumers, rather than a bolt-only parameter. Preserve the exact assembler binding, s32 type and sda attribute. --- .../shared/ui/hud/draw_hud_item_selector_panel.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c index b7cbe63df7..4ab75946f0 100644 --- a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c +++ b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c @@ -921,7 +921,7 @@ typedef struct { short unk6; } HudCounter; -extern s32 D_L00_0015F7F0_gp __asm__("D_L00_0015F7F0") __attribute__((sda)); +extern s32 l00_hud_panel_visibility_counter_limit_gp __asm__("D_L00_0015F7F0") __attribute__((sda)); void update_health_hud_animation_and_visibility(HudElem *hud_element) __asm__("FUN_L00_00239630"); @@ -970,9 +970,9 @@ void update_health_hud_animation_and_visibility(HudElem *hud_element) { hud_element->unk74 = hud_element->unk78; } if (hud_element->unk7C >= scale_game_frames(5)) { - if (*(int *)&D_L00_0015F7F0_gp > visibility_counters[0]) { + if (*(int *)&l00_hud_panel_visibility_counter_limit_gp > visibility_counters[0]) { visibility_counters[0]++; - } else if (visibility_counters[1] < *(int *)&D_L00_0015F7F0_gp) { + } else if (visibility_counters[1] < *(int *)&l00_hud_panel_visibility_counter_limit_gp) { visibility_counters[1]++; } } else { @@ -1052,13 +1052,13 @@ s32 draw_health_hud_panel(Hud *hud_element) { if (visibility_counters[0] == 0) goto out; ratio_x = convert_integer_to_float(visibility_counters[0]) / - convert_integer_to_float(D_L00_0015F7F0_gp); + convert_integer_to_float(l00_hud_panel_visibility_counter_limit_gp); if (1.0f < ratio_x) ratio_x = 1.0f; else if (ratio_x < 0.0f) ratio_x = 0.0f; ratio_y = convert_integer_to_float(visibility_counters[1]) / - convert_integer_to_float(D_L00_0015F7F0_gp); + convert_integer_to_float(l00_hud_panel_visibility_counter_limit_gp); if (1.0f < ratio_y) ratio_y = 1.0f; else if (ratio_y < 0.0f) @@ -1329,7 +1329,7 @@ void update_hud_panel_visibility(u8 *hud_element) { u8 *visibility_counters = hud_element + 0x70; if (D_00141398) { s32 scaled_duration_frames = scale_game_frames(10); - s32 visibility_counter_limit = D_L00_0015F7F0_gp; + s32 visibility_counter_limit = l00_hud_panel_visibility_counter_limit_gp; *(s32 *)(hud_element + 0x7C) = scaled_duration_frames; if (hud_element[0x70] < visibility_counter_limit) { hud_element[0x70]++; @@ -1390,13 +1390,13 @@ s32 draw_hud_bolt_exclamation_panel(Hud *hud_element) { return hud_element->ret; open = convert_integer_to_float(visibility_counters[0]) / - convert_integer_to_float(D_L00_0015F7F0_gp); + convert_integer_to_float(l00_hud_panel_visibility_counter_limit_gp); if (1.0f < open) open = 1.0f; else if (open < 0.0f) open = 0.0f; text = convert_integer_to_float(visibility_counters[1]) / - convert_integer_to_float(D_L00_0015F7F0_gp); + convert_integer_to_float(l00_hud_panel_visibility_counter_limit_gp); if (1.0f < text) text = 1.0f; else if (text < 0.0f) From 15be4696d52ad39a23ea1ed81fa079a2aa8c70c8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:35:46 +0000 Subject: [PATCH 0021/1502] decomp: clarify names in hero_set_state a -> requested_state: a -> requested_state: In authoritative src/overlays/l05/hero/hero_set_state.c (SHA-256 cdc417fc6caf3f63ce29de94647e3d8f26552a9144a1b044083b881cea225001), the int parameter is checked by state admission guards, assigned to p->state.current, and used by switch(a) to initialize the entered state. Original retail Ghidra assigns param_1 to iRam001413d4 and dispatches switch(param_1). Retail 0x0024cf08 saves a0 in s1; 0x0024d018/0x0024d040 preserve the previous current state, 0x0024d048 stores s1 at Hero+0x2084, and 0x0024d0d8-0x0024d0f8 dispatches that same s1. Thus requested_state identifies the incoming state ID rather than control_mode or vehicle_mode. --- src/overlays/l05/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l05/hero/hero_set_state.c b/src/overlays/l05/hero/hero_set_state.c index 76114beba0..3db9fa3622 100644 --- a/src/overlays/l05/hero/hero_set_state.c +++ b/src/overlays/l05/hero/hero_set_state.c @@ -81,13 +81,13 @@ extern void draw_hud_timer(void) __asm__("FUN_L05_00266710"); extern int hero_set_state(int, int) __asm__("FUN_L05_0024cee8"); extern char level05_hero_water_surface_jump_velocity_keys[] __asm__("D_L05_0017C3C0"); -int hero_set_state(int a, int b) { +int hero_set_state(int requested_state, int b) { int saved_state_step; char *moby; int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((D_L05_0015F5C4 == 2 || D_L05_0015F5C4 == 6) && b != 2) @@ -95,8 +95,8 @@ int hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -109,7 +109,7 @@ int hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -134,7 +134,7 @@ int hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -1129,7 +1129,7 @@ int hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From cf3d2b69d85196f635f81f8efbca4d9d7781d817 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:35:46 +0000 Subject: [PATCH 0022/1502] decomp: clarify names in read_buf_begin_put ptr -> put_destination_out: In read_buf_begin_put, u8 **ptr receives buf->data + buf->put only when buf->size - buf->count is nonzero. Retail 0x0023b97c loads the put offset from a0+0x50000, 0x0023b980 adds buffer base a0, and 0x0023b984 stores that byte destination through a1, proving this parameter outputs the put destination. --- src/movies/decoder/buffers/read_buf_begin_put.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/movies/decoder/buffers/read_buf_begin_put.c b/src/movies/decoder/buffers/read_buf_begin_put.c index 065c2f6d34..1f8b6b2b7a 100644 --- a/src/movies/decoder/buffers/read_buf_begin_put.c +++ b/src/movies/decoder/buffers/read_buf_begin_put.c @@ -2,11 +2,11 @@ s32 read_buf_begin_put(struct ReadBuf *buf, u8 **ptr) __asm__("func_0023B960"); -s32 read_buf_begin_put(struct ReadBuf *buf, u8 **ptr) { +s32 read_buf_begin_put(struct ReadBuf *buf, u8 **put_destination_out) { s32 free = buf->size - buf->count; if (free != 0) { - *ptr = buf->data + buf->put; + *put_destination_out = buf->data + buf->put; } return free; } From 1633d257499ceccf7ac0d7539e56aa79e2492cb6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:35:54 +0000 Subject: [PATCH 0023/1502] decomp: clarify names in spawn_giant_clank_missile D_L00_001613C4 -> l00_missile_spawn_scale_multiplier: The assigned extern float D_L00_001613C4 is the retail SDA operand loaded at 0x002a976c. Instructions 0x002a9768-0x002a9774 multiply the created missile's scale at moby+0x2c by this scalar, storing at 0x002a9788; the final scale doubling is separate at 0x002a996c-0x002a9974. Preserve its exact assembler label and SDA type. a -> fallback_yaw: Retail 0x002a9738 saves f12 at sp+0x20; 0x002a97d0 passes its address as select_auto_aim_target_moby yaw output, and 0x002a9880 stores it at missile data+0x2c. The supplied same-file update reads that yaw0 field when no live target can supply an aim direction. b -> fallback_pitch: Retail 0x002a973c saves f13 at sp+0x24; 0x002a97d4 passes its address as the auto-aim pitch output and 0x002a988c stores it at data+0x30. The current same-file update uses that pitch0 field as its fallback pitch. c -> target_height_offset: Retail 0x002a9744 saves f14 at sp+0x28, passed as the auto-aim height output at 0x002a97dc. At 0x002a98a4-0x002a98b8 it is added to the copied target position Z and retained at missile data+0x1c (zoff in the existing update layout). d -> missile_spawn_data: Retail 0x002a9778 loads s0 from spawned missile+0x78, its private-data pointer. Stores through s0 initialize owner +0x10, lifetime +0x14, target +0x18, height offset +0x1c, fallback angles +0x2c/+0x30 and speed +0x34, matching the existing D_29E8A0 update layout. e -> target_aim_bounds: Retail 0x002a982c-0x002a9834 obtains this pointer by calling get_moby_target_info on s2, the selected target. Its +0x1e flag is ORed with 0x80 and +0xb/+0xc configure prediction and speed. The supplied auto-aim context identifies the same helper return as MobyBound aim_bounds. m -> spawned_missile: Retail 0x002a972c-0x002a9748 creates class 0x100 and retains its return in s1. The current established spawn_giant_clank_missile function initializes this moby's position, rotations, private data and collision state, calls update_entity, then returns the same s1 at 0x002a9978. p -> auto_aim_position: Retail 0x002a97b0 copies the full input position quadword from s3, stores it at sp+0x10 at 0x002a97c8 and passes its address as a1 at 0x002a97c4 to select_auto_aim_target_moby. This local holds the position used by the automatic targeting query. r -> velocity_inheritance_frame_count: Retail 0x002a98bc-0x002a9904 compares length of D_0013F490 with frame scale times 0.1, scales either 60 or 1 game frames and writes the same count to data+0x3c and +0x3e. The existing update decrements f3C and scales that same velocity vector by f3C/f3E, proving the count controls inherited velocity fading. t -> aim_direction_or_collision_start: Retail 0x002a9794-0x002a97ac builds a spherical aim vector at sp and passes it as a2 at 0x002a97cc. Later 0x002a9908-0x002a9928 reuses that same stack vector for owner position with only Z replaced by spawn-position Z, then passes it as the collision-line start at 0x002a992c. tgt -> target_moby: Retail s2 preserves a2 at 0x002a9714, receives select_auto_aim_target_moby's return at 0x002a97e0 when absent, and is stored at data+0x18 at 0x002a9828. Its moby position at +0x10 is copied at 0x002a9898-0x002a98a0 to seed missile target tracking. --- .../shared/vehicles/giant_clank_missile.c | 118 +++++++++--------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/src/overlays/shared/vehicles/giant_clank_missile.c b/src/overlays/shared/vehicles/giant_clank_missile.c index bd04e08665..4891ac6a3c 100644 --- a/src/overlays/shared/vehicles/giant_clank_missile.c +++ b/src/overlays/shared/vehicles/giant_clank_missile.c @@ -46,7 +46,7 @@ extern char *select_auto_aim_target_moby( void *, void *, void *, float *, float *, float *, float) __asm__("FUN_L00_002630c8"); extern char D_0013F490[]; extern void *D_001413D0; -extern float D_L00_001613C4 __attribute__((sda)); +extern float l00_missile_spawn_scale_multiplier __asm__("D_L00_001613C4") __attribute__((sda)); extern short D_L00_001B0770[]; extern void append_unique_moby_index(void *, short *, int) __asm__("FUN_L00_0025f780"); @@ -64,75 +64,75 @@ char *spawn_giant_clank_missile(void *owner, char *spawn_giant_clank_missile( - void *owner, void *pos, float a, float b, float c, char *tgt, float rz, float ry) { - char *m; - char *d; - BoltVector t; - BoltVector p; - m = (char *)create_moby(0x100); - if (m != 0) { - ((unsigned char *)m)[0x30] = 0xFF; - m[0x31] = 1; - m[0x20] = 0; - *(float *)(m + 0x2C) *= D_L00_001613C4; - *(short *)(m + 0x32) = 0xFF; - d = *(char **)(m + 0x78); - *(float *)(m + 0x48) = rz; - *(float *)(m + 0x44) = ry; - if (tgt == 0) { - build_spherical_offset(&t, D_0015ED6C * 20.0f, rz, ry); - p.q = *(Q_2aa998 *)pos; - tgt = select_auto_aim_target_moby(owner, &p, &t, &a, &b, &c, 0.34906584f); + void *owner, void *pos, float fallback_yaw, float fallback_pitch, float target_height_offset, char *target_moby, float rz, float ry) { + char *spawned_missile; + char *missile_spawn_data; + BoltVector aim_direction_or_collision_start; + BoltVector auto_aim_position; + spawned_missile = (char *)create_moby(0x100); + if (spawned_missile != 0) { + ((unsigned char *)spawned_missile)[0x30] = 0xFF; + spawned_missile[0x31] = 1; + spawned_missile[0x20] = 0; + *(float *)(spawned_missile + 0x2C) *= l00_missile_spawn_scale_multiplier; + *(short *)(spawned_missile + 0x32) = 0xFF; + missile_spawn_data = *(char **)(spawned_missile + 0x78); + *(float *)(spawned_missile + 0x48) = rz; + *(float *)(spawned_missile + 0x44) = ry; + if (target_moby == 0) { + build_spherical_offset(&aim_direction_or_collision_start, D_0015ED6C * 20.0f, rz, ry); + auto_aim_position.q = *(Q_2aa998 *)pos; + target_moby = select_auto_aim_target_moby(owner, &auto_aim_position, &aim_direction_or_collision_start, &fallback_yaw, &fallback_pitch, &target_height_offset, 0.34906584f); } - *(void **)(d + 0x10) = owner; - qcopy(m + 0x10, pos); - *(float *)(d + 0x34) = D_0015ED6C * 100.0f; - *(int *)(d + 0x38) = 1; - *(int *)(d + 0x24) = 0; - *(int *)(d + 0x28) = 0; - *(int *)(d + 0x20) = 0; - *(char **)(d + 0x18) = tgt; - if (tgt != 0) { - unsigned char *e = (unsigned char *)get_moby_target_info(tgt); - if (e != 0) { - *(unsigned short *)(e + 0x1E) |= 0x80; - if (e[0xB] != 0) - *(int *)(d + 0x38) = 0; - if (e[0xC] != 0) - *(float *)(d + 0x34) = (float)e[0xC] * D_0015ED6C; + *(void **)(missile_spawn_data + 0x10) = owner; + qcopy(spawned_missile + 0x10, pos); + *(float *)(missile_spawn_data + 0x34) = D_0015ED6C * 100.0f; + *(int *)(missile_spawn_data + 0x38) = 1; + *(int *)(missile_spawn_data + 0x24) = 0; + *(int *)(missile_spawn_data + 0x28) = 0; + *(int *)(missile_spawn_data + 0x20) = 0; + *(char **)(missile_spawn_data + 0x18) = target_moby; + if (target_moby != 0) { + unsigned char *target_aim_bounds = (unsigned char *)get_moby_target_info(target_moby); + if (target_aim_bounds != 0) { + *(unsigned short *)(target_aim_bounds + 0x1E) |= 0x80; + if (target_aim_bounds[0xB] != 0) + *(int *)(missile_spawn_data + 0x38) = 0; + if (target_aim_bounds[0xC] != 0) + *(float *)(missile_spawn_data + 0x34) = (float)target_aim_bounds[0xC] * D_0015ED6C; } } - *(float *)(d + 0x2C) = a; - *(float *)(d + 0x30) = b; - *(int *)(d + 0x14) = scale_game_frames(0x96); - if (tgt != 0) { - qcopy(d, tgt + 0x10); - *(float *)(d + 8) += c; - *(float *)(d + 0x1C) = c; + *(float *)(missile_spawn_data + 0x2C) = fallback_yaw; + *(float *)(missile_spawn_data + 0x30) = fallback_pitch; + *(int *)(missile_spawn_data + 0x14) = scale_game_frames(0x96); + if (target_moby != 0) { + qcopy(missile_spawn_data, target_moby + 0x10); + *(float *)(missile_spawn_data + 8) += target_height_offset; + *(float *)(missile_spawn_data + 0x1C) = target_height_offset; } { - int r; + int velocity_inheritance_frame_count; if (fast_vec_length((float *)(D_0013F490)) > D_0015ED6C * 0.1f) { - r = scale_game_frames(0x3C); - *(short *)(d + 0x3E) = r; - *(short *)(d + 0x3C) = r; + velocity_inheritance_frame_count = scale_game_frames(0x3C); + *(short *)(missile_spawn_data + 0x3E) = velocity_inheritance_frame_count; + *(short *)(missile_spawn_data + 0x3C) = velocity_inheritance_frame_count; } else { - r = scale_game_frames(1); - *(short *)(d + 0x3E) = r; - *(short *)(d + 0x3C) = r; + velocity_inheritance_frame_count = scale_game_frames(1); + *(short *)(missile_spawn_data + 0x3E) = velocity_inheritance_frame_count; + *(short *)(missile_spawn_data + 0x3C) = velocity_inheritance_frame_count; } } - t.q = ((BoltOwner *)owner)->position.q; - t.f[2] = ((float *)pos)[2]; - if (FUN_001efa68(&t, pos, 0, *(int *)(((char *)&D_001413D0)), 0) != 0) { - m[0xBC] = 1; - qcopy(m + 0x10, &D_L00_00173E60); + aim_direction_or_collision_start.q = ((BoltOwner *)owner)->position.q; + aim_direction_or_collision_start.f[2] = ((float *)pos)[2]; + if (FUN_001efa68(&aim_direction_or_collision_start, pos, 0, *(int *)(((char *)&D_001413D0)), 0) != 0) { + spawned_missile[0xBC] = 1; + qcopy(spawned_missile + 0x10, &D_L00_00173E60); } - update_entity(m); - append_unique_moby_index(m, D_L00_001B0770, 0x1F); - *(float *)(m + 0x2C) += *(float *)(m + 0x2C); + update_entity(spawned_missile); + append_unique_moby_index(spawned_missile, D_L00_001B0770, 0x1F); + *(float *)(spawned_missile + 0x2C) += *(float *)(spawned_missile + 0x2C); } - return m; + return spawned_missile; } short D_L01_001B0BF0 NOT_SDA = 0; From 55f669b7fb1ab1426d5f3b9bfd35b02e2986c237 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:35:54 +0000 Subject: [PATCH 0024/1502] decomp: clarify names in read_buf_end_get buf -> read_source: In the SHA-bound read_buf_end_get source, this struct ReadBuf pointer supplies count and receives count minus taken. Retail 0x0023ba20-28 adds 0x50000 to a0 and loads its count at +4; 0x0023ba30-34 clamps the requested amount against that count, and 0x0023ba38/40 subtracts and stores the remainder through the same pointer. Together with the established read_buf_end_get name, this identifies the read source whose buffered count is consumed. --- src/movies/decoder/buffers/read_buf_end_get.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/movies/decoder/buffers/read_buf_end_get.c b/src/movies/decoder/buffers/read_buf_end_get.c index f20e98f31e..bf6a81a3e8 100644 --- a/src/movies/decoder/buffers/read_buf_end_get.c +++ b/src/movies/decoder/buffers/read_buf_end_get.c @@ -2,16 +2,16 @@ s32 read_buf_end_get(struct ReadBuf *buf, s32 size) __asm__("GetStateTableWord"); -s32 read_buf_end_get(struct ReadBuf *buf, s32 size) { +s32 read_buf_end_get(struct ReadBuf *read_source, s32 size) { s32 taken; s32 remaining_count; - taken = buf->count; + taken = read_source->count; remaining_count = taken; if (size < taken) { taken = size; } remaining_count -= taken; - buf->count = remaining_count; + read_source->count = remaining_count; return taken; } From dbb0857ad0c0dfa4760ce14b711f65c1ba0b14e9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:16:11 +0000 Subject: [PATCH 0025/1502] decomp: name the axis rotation quaternion builder Use build_axis_rotation_quaternion for FUN_L00_001fff28 and the old rotation_2D5FA8 alias. Preserve the original assembler symbol, handwritten implementation and prototype types. Retail 0x001fff30 and 0x001fff40 call the sine/cosine helpers. The square-root/division sequence builds the quaternion components, 0x001fffb8 selects X/Y/Z, and 0x001fffd4/0x001fffe4 store the output quadword. build_quaternion_from_axis_rotations calls it for axes 0, 1 and 2 before quaternion multiplication. --- include/rnc/overlay/shared/math/vu0_vector_ops.h | 2 +- src/overlays/l02/mobys/rocket_door1.c | 14 +++++++------- src/overlays/l04/mobys/big_axebot.c | 8 ++++---- src/overlays/l04/mobys/leg_walker.c | 6 +++--- src/overlays/l04/mobys/snow_plow.c | 10 +++++----- src/overlays/l04/mobys/woodcut_bot.c | 6 +++--- src/overlays/l05/mobys/extermitank.c | 10 +++++----- src/overlays/l05/mobys/triggered_motion.c | 6 +++--- src/overlays/l07/mobys/bombomatic.c | 4 ++-- src/overlays/l08/mobys/bomber_tank.c | 4 ++-- src/overlays/l09/mobys/shuttle.c | 4 ++-- src/overlays/l09/mobys/turret.c | 4 ++-- src/overlays/l11/mobys/pokitaru_boat.c | 4 ++-- src/overlays/l12/mobys/hoven_turret.c | 4 ++-- src/overlays/l14/mobys/blarg_heavy_interceptor.c | 10 +++++----- src/overlays/l14/mobys/minibomber.c | 8 ++++---- src/overlays/l14/mobys/racer_path_and_weapon.c | 6 +++--- src/overlays/l14/mobys/shuttle.c | 4 ++-- src/overlays/l15/mobys/helicopter.c | 10 +++++----- src/overlays/l18/mobys/rocket_tank.c | 6 +++--- src/overlays/shared/enemies/blarg_helicopter.c | 8 ++++---- src/overlays/shared/enemies/plasmabot.c | 8 ++++---- src/overlays/shared/enemies/walker_update_gait.c | 6 +++--- src/overlays/shared/hero/set_hero_animation.c | 2 +- src/overlays/shared/mobys/find_moby_hit.c | 8 ++++---- src/overlays/shared/props/lamp.c | 4 ++-- src/overlays/shared/vendor/vendor.c | 8 ++++---- src/overlays/shared/vendor/vendor_orb.c | 4 ++-- src/overlays/shared/weapons/visibomb_missile.c | 4 ++-- 29 files changed, 91 insertions(+), 91 deletions(-) diff --git a/include/rnc/overlay/shared/math/vu0_vector_ops.h b/include/rnc/overlay/shared/math/vu0_vector_ops.h index 0b474060b1..4b7455eae0 100644 --- a/include/rnc/overlay/shared/math/vu0_vector_ops.h +++ b/include/rnc/overlay/shared/math/vu0_vector_ops.h @@ -6,6 +6,6 @@ s32 fast_subtract_rotations_cf(void *) __asm__("FUN_L00_001fefc8"); void add_vectors(void *, void *, void *) __asm__("FUN_L00_001ff290"); void reflect_vector(void *, void *, void *) __asm__("FUN_L00_001ff660"); -void rotation_2D5FA8(void *, s32, f32) __asm__("FUN_L00_001fff28"); +void build_axis_rotation_quaternion(void *, s32, f32) __asm__("FUN_L00_001fff28"); #endif /* LOMBYTE_RNC_OVERLAY_SHARED_MATH_VU0_VECTOR_OPS_H */ diff --git a/src/overlays/l02/mobys/rocket_door1.c b/src/overlays/l02/mobys/rocket_door1.c index d80db47541..6ce29e4f66 100644 --- a/src/overlays/l02/mobys/rocket_door1.c +++ b/src/overlays/l02/mobys/rocket_door1.c @@ -23,7 +23,7 @@ typedef struct { extern s32 D_0015ED84; extern u8 D_0014C050[][16]; -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern float approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); @@ -63,14 +63,14 @@ void rocket_door1_update(struct Moby *moby) { } else { moby->state = 1; moby->flags |= 0x100; - FUN_L00_001fff28(&qx, 0, door_vars->goal.f[0] * 0.017453292f); - FUN_L00_001fff28(&qy, 1, door_vars->goal.f[1] * 0.017453292f); - FUN_L00_001fff28(&qz, 2, door_vars->goal.f[2] * 0.017453292f); + build_axis_rotation_quaternion(&qx, 0, door_vars->goal.f[0] * 0.017453292f); + build_axis_rotation_quaternion(&qy, 1, door_vars->goal.f[1] * 0.017453292f); + build_axis_rotation_quaternion(&qz, 2, door_vars->goal.f[2] * 0.017453292f); multiply_quaternions(&qxy, &qx, &qy); multiply_quaternions(&door_vars->goal, &qxy, &qz); - FUN_L00_001fff28(&qx, 0, moby->rot.x); - FUN_L00_001fff28(&qy, 1, moby->rot.y); - FUN_L00_001fff28(&qz, 2, moby->rot.z); + build_axis_rotation_quaternion(&qx, 0, moby->rot.x); + build_axis_rotation_quaternion(&qy, 1, moby->rot.y); + build_axis_rotation_quaternion(&qz, 2, moby->rot.z); multiply_quaternions(&rxy, &qx, &qy); multiply_quaternions(&door_vars->start, &rxy, &qz); } diff --git a/src/overlays/l04/mobys/big_axebot.c b/src/overlays/l04/mobys/big_axebot.c index 2e325b77c8..900efa8e5e 100644 --- a/src/overlays/l04/mobys/big_axebot.c +++ b/src/overlays/l04/mobys/big_axebot.c @@ -256,7 +256,7 @@ extern void * FUN_L00_00263fd8(char *, int, float *, void *, int, int, float, float *, float *, float *); void *spawn_big_axebot_axe(char *source_moby, char *spawn_position) __asm__("FUN_L04_002d34d8"); extern void *random_integer_below_cf(void *, int, unsigned int) __asm__("FUN_001153fc"); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern void FUN_L00_00257470(void *, int, int); extern void leg_walker_update(void *, void *, float, float, float) __asm__("FUN_L04_00295778"); extern void FUN_L00_0025a120(void *); @@ -901,8 +901,8 @@ void big_axebot_update(M_B7B0 *moby) { } data->f408 *= 0.96f; fast_dec_timer(&data->f448); - FUN_L00_001fff28(vector_quaternion_scratch, 1, data->f408); - FUN_L00_001fff28(data->m120.q, 2, 0.0f); + build_axis_rotation_quaternion(vector_quaternion_scratch, 1, data->f408); + build_axis_rotation_quaternion(data->m120.q, 2, 0.0f); multiply_quaternions(data->m120.q, data->m120.q, vector_quaternion_scratch); if (moby->state != 8) { data->f401 = moby->state; @@ -934,7 +934,7 @@ void big_axebot_update(M_B7B0 *moby) { data->f428 = fast_add_rotations(data->f428, fast_subtract_rotations(moby->rot[2], rot)); build_moby_bone_transform((char *)moby, 0xC, (char *)bone_transform); matrix_to_euler(bone_transform, bone_euler_angles); - FUN_L00_001fff28(q, 2, fast_subtract_rotations(target_yaw, data->f428)); + build_axis_rotation_quaternion(q, 2, fast_subtract_rotations(target_yaw, data->f428)); data->f428 = target_yaw; multiply_quaternions(data->m160.q, data->m160.q, q); } diff --git a/src/overlays/l04/mobys/leg_walker.c b/src/overlays/l04/mobys/leg_walker.c index 4e1f6f14f8..b9cfe02cc8 100644 --- a/src/overlays/l04/mobys/leg_walker.c +++ b/src/overlays/l04/mobys/leg_walker.c @@ -347,11 +347,11 @@ void FUN_L04_00292d48(struct Moby *moby, LegRig *rig, int flags) { rig->legs[i].yaw = fast_add_rotations(rig->legs[i].upper_turn, base_yaw); rig->legs[i].yaw = fast_add_rotations(rig->legs[i].lower_turn, rig->legs[i].yaw); if (rig->legs[i].manip_b.attached) - rotation_2D5FA8(rig->legs[i].manip_b.rot, 2, rig->legs[i].upper_turn); + build_axis_rotation_quaternion(rig->legs[i].manip_b.rot, 2, rig->legs[i].upper_turn); if (rig->legs[i].manip_a.attached) { - rotation_2D5FA8(rig->legs[i].manip_a.rot, 2, rig->legs[i].lower_turn); + build_axis_rotation_quaternion(rig->legs[i].manip_a.rot, 2, rig->legs[i].lower_turn); if (flags & mask) { - rotation_2D5FA8(tilt, 0, -moby->rot.x); + build_axis_rotation_quaternion(tilt, 0, -moby->rot.x); multiply_quaternions(rig->legs[i].manip_a.rot, rig->legs[i].manip_a.rot, tilt); } } diff --git a/src/overlays/l04/mobys/snow_plow.c b/src/overlays/l04/mobys/snow_plow.c index 1368d05c30..a296e3e0c2 100644 --- a/src/overlays/l04/mobys/snow_plow.c +++ b/src/overlays/l04/mobys/snow_plow.c @@ -29,7 +29,7 @@ extern int snow_plow_hit_count_gp __asm__("D_L04_0015EDF8") __attribute__((sda) extern void debug_print() __asm__("FUN_001e93b0"); extern void FUN_L00_00258278(void *, float, void *, float, float, float); extern void attach_manipulator(char *, int, void *) __asm__("FUN_0020cb10"); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern void advance_moby_animation(void *) __asm__("FUN_0020d580"); extern void update_entity(void *) __asm__("FUN_L00_00250df8"); extern void refresh_moby_spatial_bounds_from_basis(void *) __asm__("FUN_0020e098"); @@ -275,7 +275,7 @@ void snow_plow_update(struct Moby *moby) { case SNOW_PLOW_CLASS_OFFSET_WITH_QUARTER_TURN_LINKED_MOBY: snow_plow_vars->unk140 = fast_add_rotations(snow_plow_vars->unk140, frame_time * 12.566371f); - FUN_L00_001fff28(&snow_plow_vars->unk190, 0, snow_plow_vars->unk140); + build_axis_rotation_quaternion(&snow_plow_vars->unk190, 0, snow_plow_vars->unk140); break; case SNOW_PLOW_CLASS_OFFSET_WITH_HIT_SPHERE_QUERY_AND_TARGET_VOICE: case SNOW_PLOW_CLASS_OFFSET_WITH_HIT_SPHERE_QUERY_WITHOUT_TARGET_VOICE: @@ -285,16 +285,16 @@ void snow_plow_update(struct Moby *moby) { case SNOW_PLOW_CLASS_OFFSET_WITH_TARGET_VOICE_SELECTOR_ZERO: snow_plow_vars->unk140 = fast_add_rotations(snow_plow_vars->unk140, frame_time * 12.566371f); - FUN_L00_001fff28(&snow_plow_vars->unk190, 2, snow_plow_vars->unk140); + build_axis_rotation_quaternion(&snow_plow_vars->unk190, 2, snow_plow_vars->unk140); break; case SNOW_PLOW_CLASS_OFFSET_WITH_TWO_ROTATING_MANIPULATORS: case SNOW_PLOW_CLASS_OFFSET_WITH_TWO_POINT_CART_BURST: snow_plow_vars->unk140 = fast_add_rotations(snow_plow_vars->unk140, frame_time * 12.566371f); - FUN_L00_001fff28(&snow_plow_vars->unk190, 2, snow_plow_vars->unk140); + build_axis_rotation_quaternion(&snow_plow_vars->unk190, 2, snow_plow_vars->unk140); snow_plow_vars->unk144 = fast_add_rotations(snow_plow_vars->unk144, frame_time * 12.566371f); - FUN_L00_001fff28(&snow_plow_vars->unk1D0, 2, snow_plow_vars->unk144); + build_axis_rotation_quaternion(&snow_plow_vars->unk1D0, 2, snow_plow_vars->unk144); break; } } diff --git a/src/overlays/l04/mobys/woodcut_bot.c b/src/overlays/l04/mobys/woodcut_bot.c index 967b748c5e..8b96ec0746 100644 --- a/src/overlays/l04/mobys/woodcut_bot.c +++ b/src/overlays/l04/mobys/woodcut_bot.c @@ -172,7 +172,7 @@ void emit_woodcut_bot_death_effects(void *moby) { extern float D_L04_0015F580[] MACRO_ADDR; extern void attach_manipulator(char *, int, void *) __asm__("FUN_0020cb10"); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern void collect_mobies_in_sphere(void *, float, int, void *, void *) __asm__("FUN_L00_001f2868"); extern void FUN_L00_00263fd8(void *, int, void *, void *, int, int, float, void *, void *, void *); @@ -969,8 +969,8 @@ void woodcut_bot_update(WBMoby *m) { FUN_L00_00258490(m, pos, recoil_scratch, 1, 0.25f, 1.0f, 0.75f, 0.87266463f); } d->f3C8 *= 0.96f; - FUN_L00_001fff28(recoil_scratch, 1, d->f3C8); - FUN_L00_001fff28(d->f130, 2, 0.0f); + build_axis_rotation_quaternion(recoil_scratch, 1, d->f3C8); + build_axis_rotation_quaternion(d->f130, 2, 0.0f); multiply_quaternions(d->f130, d->f130, recoil_scratch); if (m->state != 9) d->f3C1 = m->state; diff --git a/src/overlays/l05/mobys/extermitank.c b/src/overlays/l05/mobys/extermitank.c index 260b1e13a9..6398c00886 100644 --- a/src/overlays/l05/mobys/extermitank.c +++ b/src/overlays/l05/mobys/extermitank.c @@ -78,7 +78,7 @@ extern float extermitank_secondary_particle_vector_a_spread_degrees_gp __asm__(" __attribute__((sda)); extern short D_L05_00161B78 __attribute__((sda)); extern float D_L05_00161B7C __attribute__((sda)); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern void mark_moby_for_removal_c3(void *) __asm__("func_0020C828"); void handle_extermitank_hits_and_sync_children(char *moby) __asm__("FUN_L05_00305178"); void process_extermitank_particle_hits(char *m) __asm__("FUN_L05_00305898"); @@ -307,8 +307,8 @@ void extermitank_update(unsigned char *moby) { step_angle_toward_target( &extermitank_vars->unk198, 0, 0.0f, D_0015ED6C_gp * 1.5707964f); } - FUN_L00_001fff28(extermitank_vars->unk140, 1, extermitank_vars->unk198); - FUN_L00_001fff28(extermitank_vars->unk100, + build_axis_rotation_quaternion(extermitank_vars->unk140, 1, extermitank_vars->unk198); + build_axis_rotation_quaternion(extermitank_vars->unk100, 2, fast_subtract_rotations(extermitank_vars->unk194, MOBY(moby)->rot.z)); break; @@ -480,8 +480,8 @@ void extermitank_update(unsigned char *moby) { step_angle_toward_target( &extermitank_vars->unk198, 0, 0.08726646f, D_0015ED6C_gp * 1.5707964f); } - FUN_L00_001fff28(extermitank_vars->unk140, 1, extermitank_vars->unk198); - FUN_L00_001fff28(extermitank_vars->unk100, + build_axis_rotation_quaternion(extermitank_vars->unk140, 1, extermitank_vars->unk198); + build_axis_rotation_quaternion(extermitank_vars->unk100, 2, fast_subtract_rotations(extermitank_vars->unk194, MOBY(moby)->rot.z)); break; diff --git a/src/overlays/l05/mobys/triggered_motion.c b/src/overlays/l05/mobys/triggered_motion.c index 2ab18feebf..3dee6b3c5c 100644 --- a/src/overlays/l05/mobys/triggered_motion.c +++ b/src/overlays/l05/mobys/triggered_motion.c @@ -14,7 +14,7 @@ extern float advance_accelerated_scalar(float, float, float, float, float *, float *) __asm__("FUN_00213f38"); extern float FUN_L00_0025be00(float *, float *, float, float, float, float); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern char *D_001413D0_lui __asm__("D_001413D0") NOT_SDA; void triggered_motion_update(char *moby) __asm__("FUN_L05_00316258"); @@ -68,7 +68,7 @@ void triggered_motion_update(char *moby) { } else { MOBY(moby)->state = 1; motion_and_manipulator_vars->unk60 = 0.5934119f; - FUN_L00_001fff28(&motion_and_manipulator_vars->unk20, 0, 0.5934119f); + build_axis_rotation_quaternion(&motion_and_manipulator_vars->unk20, 0, 0.5934119f); } *(long long *)(moby + 0x38) = *(long long *)(D_001413D0_lui + 0x38); break; @@ -121,7 +121,7 @@ void triggered_motion_update(char *moby) { MOBY(moby)->state = 3; } } - FUN_L00_001fff28( + build_axis_rotation_quaternion( &motion_and_manipulator_vars->unk20, 0, motion_and_manipulator_vars->unk60); } break; case MOBY_MOVE_TO_OFFSET_POSITION: diff --git a/src/overlays/l07/mobys/bombomatic.c b/src/overlays/l07/mobys/bombomatic.c index abfa1e13ce..5e88cd3465 100644 --- a/src/overlays/l07/mobys/bombomatic.c +++ b/src/overlays/l07/mobys/bombomatic.c @@ -80,7 +80,7 @@ extern float FUN_L00_0025abf0(void *, void *, void *, float, float) extern int D_L07_0015F5CC MACRO_ADDR; extern void * FUN_L00_00263fd8(char *, int, float *, void *, int, int, float, float *, float *, float *); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern void FUN_L00_0024f7c8(void *, int, void *); extern void FUN_L00_00257470(void *, int, int); extern void FUN_L00_0025a120(void *); @@ -424,6 +424,6 @@ void bombomatic_update(char *moby) { float f = D_0015ED6C_gp * 17.80235863f; float g = fast_add_rotations(moby_data->unkC0, f); moby_data->unkC0 = g; - FUN_L00_001fff28(&moby_data->unk80, 2, g); + build_axis_rotation_quaternion(&moby_data->unk80, 2, g); } } diff --git a/src/overlays/l08/mobys/bomber_tank.c b/src/overlays/l08/mobys/bomber_tank.c index 5aebfd6276..0ccf05731c 100644 --- a/src/overlays/l08/mobys/bomber_tank.c +++ b/src/overlays/l08/mobys/bomber_tank.c @@ -709,8 +709,8 @@ void update_bomber_tank_damage_and_aim(Moby *moby) { D_0015ED70 * 12.566371f, D_0015ED6C_lui * 9.424778f); } - rotation_2D5FA8(burst_position_or_aim_scratch, 1, bomber_tank_damage_and_aim_vars->pitch); - rotation_2D5FA8(bomber_tank_damage_and_aim_vars->f110, 2, bomber_tank_damage_and_aim_vars->yaw); + build_axis_rotation_quaternion(burst_position_or_aim_scratch, 1, bomber_tank_damage_and_aim_vars->pitch); + build_axis_rotation_quaternion(bomber_tank_damage_and_aim_vars->f110, 2, bomber_tank_damage_and_aim_vars->yaw); multiply_quaternions(bomber_tank_damage_and_aim_vars->f110, burst_position_or_aim_scratch, bomber_tank_damage_and_aim_vars->f110); diff --git a/src/overlays/l09/mobys/shuttle.c b/src/overlays/l09/mobys/shuttle.c index 3c72403cf6..6d9145d5ab 100644 --- a/src/overlays/l09/mobys/shuttle.c +++ b/src/overlays/l09/mobys/shuttle.c @@ -20,7 +20,7 @@ extern char D_0013E550[]; #include "rnc/mobys/moby.h" extern int D_L09_0015F5CC; -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern void update_moby_vertical_oscillation(float, float, char *, float *, float *) __asm__("FUN_L00_00262b00"); extern void update_moby_rotation_oscillation(void *, char *, char *, float, float, float) __asm__("FUN_L00_00262b80"); @@ -308,7 +308,7 @@ int advance_shuttle_along_path(struct Moby *moby) { shuttle_path_state->yaw_offset = 0.0f; shuttle_path_state->spin = fast_add_rotations(shuttle_path_state->spin, shuttle_path_state->speed); - FUN_L00_001fff28(shuttle_path_state->unk70, 0, shuttle_path_state->spin); + build_axis_rotation_quaternion(shuttle_path_state->unk70, 0, shuttle_path_state->spin); if (vector_distance_xy(&moby->pos, &path->node[path->count - 1]) > 8.0f && vector_distance_xy(&moby->pos, &path->node[0]) > 8.0f && !random_integer_below(7)) { qcopy(&puff, &moby->pos); diff --git a/src/overlays/l09/mobys/turret.c b/src/overlays/l09/mobys/turret.c index c3d6cffa64..d4c2eb13fc 100644 --- a/src/overlays/l09/mobys/turret.c +++ b/src/overlays/l09/mobys/turret.c @@ -85,7 +85,7 @@ extern void FUN_L00_0026dd20(void *, void *, int, int, float); extern void divide_vector_xyz(void *, void *, float) __asm__("FUN_L00_001ff378"); extern void suck_draw_reticle(void *, int, void *, int, int, int, float, float, float) __asm__("FUN_L00_001edf60"); extern float compute_interpolated_record_value(void *) __asm__("FUN_0020c9e0"); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); void turret_update(struct Moby *moby) __asm__("FUN_L09_00304c80"); /* Moby class 1201 */ @@ -249,7 +249,7 @@ void turret_update(struct Moby *moby) { } turret_vars->yaw_speed *= 0.97f; turret_vars->pitch_speed *= 0.97f; - FUN_L00_001fff28(&turret_vars->aim, 1, -turret_vars->pitch); + build_axis_rotation_quaternion(&turret_vars->aim, 1, -turret_vars->pitch); if (controller_state.held & 0x20) { if (controller_state.pressed & 0x20) { blend_moby_animation(moby, turret_vars->barrel == 0 ? 4 : 3, 0, 1); diff --git a/src/overlays/l11/mobys/pokitaru_boat.c b/src/overlays/l11/mobys/pokitaru_boat.c index cc06c2e0cc..dd8d293bf5 100644 --- a/src/overlays/l11/mobys/pokitaru_boat.c +++ b/src/overlays/l11/mobys/pokitaru_boat.c @@ -313,7 +313,7 @@ void pokitaru_boat_update(struct Moby *moby) { update_entity_matrix(boat_vars->ctl60, delta, start_rot, &moby->rot); } -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern void FUN_L00_0026f080(float *, float *, float, float); struct PartA500 { @@ -351,7 +351,7 @@ void update_pokitaru_boat_joint_effects(struct Moby *moby) { step = frame_time * 2.6179938f; if (((u8 *)moby_vars)[i * 0x40 + 0x101]) { moby_vars->angle[i] = fast_add_rotations(moby_vars->angle[i], step); - FUN_L00_001fff28(moby_vars->parts[i].joint, 0, moby_vars->angle[i]); + build_axis_rotation_quaternion(moby_vars->parts[i].joint, 0, moby_vars->angle[i]); } } if (vector_distance_xy(&moby->pos, camera_pos_b358) > 38.0f) diff --git a/src/overlays/l12/mobys/hoven_turret.c b/src/overlays/l12/mobys/hoven_turret.c index 250a5fa55a..3c23e09fdc 100644 --- a/src/overlays/l12/mobys/hoven_turret.c +++ b/src/overlays/l12/mobys/hoven_turret.c @@ -159,7 +159,7 @@ extern int D_L12_00161F20 MACRO_ADDR; extern int D_L12_00161F24 MACRO_ADDR; extern int random_int_between(int, int) __asm__("FUN_L00_00257b90"); extern int hero_set_state(int, int) __asm__("FUN_L12_002400d0"); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern void hero_respawn(void) __asm__("FUN_L00_00211250"); extern void set_race_camera(void *, void *, int, int) __asm__("FUN_L00_00216f90"); extern void moby_point_position(void *, int, void *) __asm__("FUN_L00_0024f7c8"); @@ -406,7 +406,7 @@ void hoven_turret_update(struct Moby *moby) { if (hoven_turret_state->f74 < hoven_turret_pitch_min) { hoven_turret_state->f74 = hoven_turret_pitch_min; } - FUN_L00_001fff28(hoven_turret_state->f10, 1, -hoven_turret_state->f74); + build_axis_rotation_quaternion(hoven_turret_state->f10, 1, -hoven_turret_state->f74); if (moby->anim_flags & 2) { blend_moby_animation(moby, 5, 0, 1); } diff --git a/src/overlays/l14/mobys/blarg_heavy_interceptor.c b/src/overlays/l14/mobys/blarg_heavy_interceptor.c index eb2211d383..b1791248d3 100644 --- a/src/overlays/l14/mobys/blarg_heavy_interceptor.c +++ b/src/overlays/l14/mobys/blarg_heavy_interceptor.c @@ -105,7 +105,7 @@ extern int FUN_L00_001f2868_c618(float, void *, int, void *, void *) __asm__("FU extern int FUN_001efa68_c618(void *, void *, int, int, int) __asm__("FUN_001efa68"); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern f32 ease_c618(f32 *pos, f32 target, f32 *vel, f32, f32, f32) __asm__("FUN_L00_0025b8c0"); @@ -484,8 +484,8 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { if (absolute_float(moby_vars->unk1B0[3]) < 0.0001f) { moby_vars->unk1B0[3] = 0.0f; } - FUN_L00_001fff28(moby_vars->unkF0, 2, moby_vars->unk1B0[3]); - FUN_L00_001fff28(moby_vars->unk130, 1, moby_vars->unk1C0[0]); + build_axis_rotation_quaternion(moby_vars->unkF0, 2, moby_vars->unk1B0[3]); + build_axis_rotation_quaternion(moby_vars->unk130, 1, moby_vars->unk1C0[0]); } if (try_retract_turret_group(moby_vars->turret_group)) { LevelPath *p = l14_paths[moby_vars->patrol_path]; @@ -1782,10 +1782,10 @@ int update_blarg_heavy_interceptor_aim_transforms(struct Moby *moby, int flag) { 1.0f); rotation_angle = fast_subtract_rotations( fast_arc_tan(half_span_vector[0], half_span_vector[1]), moby->rot.z); - FUN_L00_001fff28(blarg_heavy_interceptor_private_vars->unkF0, 2, rotation_angle); + build_axis_rotation_quaternion(blarg_heavy_interceptor_private_vars->unkF0, 2, rotation_angle); blarg_heavy_interceptor_private_vars->unk1B0[3] = rotation_angle; rotation_angle = -fast_arc_tan(vector_length_xy(half_span_vector), half_span_vector[2]); - FUN_L00_001fff28(blarg_heavy_interceptor_private_vars->unk130, 1, rotation_angle); + build_axis_rotation_quaternion(blarg_heavy_interceptor_private_vars->unk130, 1, rotation_angle); blarg_heavy_interceptor_private_vars->unk1C0[0] = rotation_angle; qcopy(blarg_heavy_interceptor_private_vars->unk90, blarg_heavy_interceptor_private_vars->unk170); diff --git a/src/overlays/l14/mobys/minibomber.c b/src/overlays/l14/mobys/minibomber.c index 3c7684b6b7..6dd05618a5 100644 --- a/src/overlays/l14/mobys/minibomber.c +++ b/src/overlays/l14/mobys/minibomber.c @@ -28,7 +28,7 @@ extern void FUN_L00_0025a120(void *); extern void fill_transfer_words(void *, int, int) __asm__("FUN_001f97e8"); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern char D_L14_001674C0[]; @@ -465,7 +465,7 @@ void minibomber_update(Moby_2B5938 *moby) { d->f104, (float)d->f102 / convert_integer_to_float(scale_game_frames(minibomber_aim_return_duration_frames))); - FUN_L00_001fff28(d->f120, 2, blended_aim_angle); + build_axis_rotation_quaternion(d->f120, 2, blended_aim_angle); if (vector_distance_xy(moby->pos, d->fB0->pos) < minibomber_path_traversal_trigger_distance) { if (d->f10C == 0) { @@ -545,7 +545,7 @@ void minibomber_update(Moby_2B5938 *moby) { d->f104, (float)d->f102 / convert_integer_to_float(scale_game_frames(minibomber_bomb_aim_duration_frames))); - FUN_L00_001fff28(d->f120, 2, blended_aim_angle); + build_axis_rotation_quaternion(d->f120, 2, blended_aim_angle); if (moby->f53 == 2) { moby->state = 4; d->f102 = scale_game_frames(minibomber_aim_return_duration_frames); @@ -560,7 +560,7 @@ void minibomber_update(Moby_2B5938 *moby) { if (is_value_within_interpolated_window(moby, 3.0f) != 0) { PathNode *q; n = (float)scale_game_frames(minibomber_bomb_flight_duration_frames); - FUN_L00_001fff28(d->f120, 2, d->f104); + build_axis_rotation_quaternion(d->f120, 2, d->f104); moby_point_position(moby, 1, v); fast_vec_sub(v + 4, ((PathNode *)l14_paths[d->fD8]) + (d->f100 + 1), v); v[6] = 0.0f; diff --git a/src/overlays/l14/mobys/racer_path_and_weapon.c b/src/overlays/l14/mobys/racer_path_and_weapon.c index 78086d18b7..4d832b245e 100644 --- a/src/overlays/l14/mobys/racer_path_and_weapon.c +++ b/src/overlays/l14/mobys/racer_path_and_weapon.c @@ -275,7 +275,7 @@ int D_L14_00161A3C = 0x8c; extern char D_L14_001809C0[]; extern char D_L14_0015F580_macro[] __asm__("D_L14_0015F580") MACRO_ADDR; extern void vendor_spring(void *, void *, float, float, float, float) __asm__("FUN_L00_0025b8c0"); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern void register_beam_slot(struct Moby *, int, int) __asm__("FUN_L00_002e1f28"); extern int set_beam_origin_transform_and_endpoint(struct Moby *, void *, void *) __asm__("FUN_L00_002e2190"); @@ -406,7 +406,7 @@ void update_racer_path_and_weapon(struct Moby *racer_moby) { } turn = (turn - 0.0f) * blend + 0.0f; } - FUN_L00_001fff28(&moby_data->unk150, 2, turn); + build_axis_rotation_quaternion(&moby_data->unk150, 2, turn); moby_point_position(racer_moby, 4, &joint_transform_and_aim_vectors[2]); *(u128_67e8 *)&joint_transform_and_aim_vectors[3] = 0; joint_transform_and_aim_vectors[3].z = 1.0f; @@ -522,7 +522,7 @@ void update_racer_path_and_weapon(struct Moby *racer_moby) { } else if (target_yaw_offset < -1.2217305f) { target_yaw_offset = -1.2217305f; } - FUN_L00_001fff28(&moby_data->unk110, 2, target_yaw_offset); + build_axis_rotation_quaternion(&moby_data->unk110, 2, target_yaw_offset); } /* Ported from rac1-decomp (src/overlays/l14_oltanis/vendor_002ACCC0.c: func_L14_002D84A8), where it is exact; names translated to the US level program. */ diff --git a/src/overlays/l14/mobys/shuttle.c b/src/overlays/l14/mobys/shuttle.c index 7c430d9ff1..562035c3d0 100644 --- a/src/overlays/l14/mobys/shuttle.c +++ b/src/overlays/l14/mobys/shuttle.c @@ -57,7 +57,7 @@ extern f32 shuttle_horizontal_rider_correction_limit_scale_gp __asm__("D_L14_001 extern void debug_print(const char *, short) __asm__("FUN_001e93b0"); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); void shuttle_update(struct Moby *m) __asm__("FUN_L14_002e7bd8"); @@ -132,7 +132,7 @@ void shuttle_update(struct Moby *shuttle_moby) { (voice_is_playing(shuttle_moby, shuttle_vars->sound) == 0 && shuttle_vars->sound == -1)) shuttle_vars->sound = allocate_voice_for_target_entry(0, 4, shuttle_moby); shuttle_vars->angle = fast_add_rotations(shuttle_vars->angle, 0.17453292f); - FUN_L00_001fff28(shuttle_vars->wobble, 0, shuttle_vars->angle); + build_axis_rotation_quaternion(shuttle_vars->wobble, 0, shuttle_vars->angle); fast_vec_sub(&delta, &shuttle_moby->pos, &previous_shuttle_position); update_entity_matrix(shuttle_vars->spring, &delta, &rot, &shuttle_moby->rot); if (hero.state.control_mode == 13 && hero.grapple_target == rider) { diff --git a/src/overlays/l15/mobys/helicopter.c b/src/overlays/l15/mobys/helicopter.c index b6224fdc77..efa8d32571 100644 --- a/src/overlays/l15/mobys/helicopter.c +++ b/src/overlays/l15/mobys/helicopter.c @@ -374,7 +374,7 @@ extern struct Moby *spawn_homing_spark_projectile( extern void FUN_L00_0025a120(void *); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern int point_in_path_xy(void *, void *, int) __asm__("FUN_L00_00259740"); @@ -838,10 +838,10 @@ void helicopter_update(struct Moby *moby) { frame_time_sq * 3.1415927f, frame_time_sq * 6.2831855f, frame_time * 1.5707964f); - FUN_L00_001fff28(helicopter_instance_vars->turret_yaw_joint + 0x10, + build_axis_rotation_quaternion(helicopter_instance_vars->turret_yaw_joint + 0x10, 2, helicopter_instance_vars->turret_yaw); - FUN_L00_001fff28(helicopter_instance_vars->turret_pitch_joint + 0x10, + build_axis_rotation_quaternion(helicopter_instance_vars->turret_pitch_joint + 0x10, 2, helicopter_instance_vars->turret_pitch); helicopter_instance_vars->shot = 0; @@ -867,10 +867,10 @@ void helicopter_update(struct Moby *moby) { frame_time_sq * 3.1415927f, frame_time_sq * 6.2831855f, frame_time * 1.5707964f); - FUN_L00_001fff28(helicopter_instance_vars->turret_yaw_joint + 0x10, + build_axis_rotation_quaternion(helicopter_instance_vars->turret_yaw_joint + 0x10, 2, helicopter_instance_vars->turret_yaw); - FUN_L00_001fff28(helicopter_instance_vars->turret_pitch_joint + 0x10, + build_axis_rotation_quaternion(helicopter_instance_vars->turret_pitch_joint + 0x10, 2, helicopter_instance_vars->turret_pitch); } diff --git a/src/overlays/l18/mobys/rocket_tank.c b/src/overlays/l18/mobys/rocket_tank.c index cc98d671e9..3c8814073f 100644 --- a/src/overlays/l18/mobys/rocket_tank.c +++ b/src/overlays/l18/mobys/rocket_tank.c @@ -241,7 +241,7 @@ extern void *FUN_L00_00257470_cf(char *src, float *v10, float *v11, float *v12) __asm__("FUN_L00_00263fd8"); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern void trooper_anim_update(void *, short *) __asm__("FUN_L00_0025d458"); extern void mark_moby_for_removal_cf(void *, int, int) __asm__("FUN_L00_00257470"); extern void func_L00_0025F4A8_alt(void *, @@ -388,8 +388,8 @@ void update_rocket_tank_damage_and_aim(void *mv) { frame_time_sq * 12.566371f, frame_time * 9.424778f); } - FUN_L00_001fff28(explosion_and_aim_scratch, 1, *(float *)(tank_data + 0x118)); - FUN_L00_001fff28( + build_axis_rotation_quaternion(explosion_and_aim_scratch, 1, *(float *)(tank_data + 0x118)); + build_axis_rotation_quaternion( tank_data + 0xD0, 2, fast_subtract_rotations(*(float *)(tank_data + 0x110), *(float *)(moby_bytes + 0x48))); diff --git a/src/overlays/shared/enemies/blarg_helicopter.c b/src/overlays/shared/enemies/blarg_helicopter.c index 6127af81d0..f9d514b5bc 100644 --- a/src/overlays/shared/enemies/blarg_helicopter.c +++ b/src/overlays/shared/enemies/blarg_helicopter.c @@ -450,8 +450,8 @@ void blarg_helicopter_update(HMob49 *moby) { D_0015ED70 * 3.1415927f, D_0015ED70 * 6.2831855f, D_0015ED6C * 1.5707964f); - rotation_2D5FA8(data->gun_yaw_matrix + 4, 2, data->gun_yaw); - rotation_2D5FA8(data->gun_pitch_matrix + 4, 2, data->gun_pitch); + build_axis_rotation_quaternion(data->gun_yaw_matrix + 4, 2, data->gun_yaw); + build_axis_rotation_quaternion(data->gun_pitch_matrix + 4, 2, data->gun_pitch); data->projectile = 0; } else { moby_point_position(moby, 0, helicopter_update_scratch.movement); @@ -480,8 +480,8 @@ void blarg_helicopter_update(HMob49 *moby) { D_0015ED70 * 3.1415927f, D_0015ED70 * 6.2831855f, D_0015ED6C * 1.5707964f); - rotation_2D5FA8(data->gun_yaw_matrix + 4, 2, data->gun_yaw); - rotation_2D5FA8(data->gun_pitch_matrix + 4, 2, data->gun_pitch); + build_axis_rotation_quaternion(data->gun_yaw_matrix + 4, 2, data->gun_yaw); + build_axis_rotation_quaternion(data->gun_pitch_matrix + 4, 2, data->gun_pitch); } if (point > 0 && point < route->path->count - 1) { float node_distance = vector_distance_xy(&route->path->points[point], diff --git a/src/overlays/shared/enemies/plasmabot.c b/src/overlays/shared/enemies/plasmabot.c index ff549d47eb..d44e4e9ad7 100644 --- a/src/overlays/shared/enemies/plasmabot.c +++ b/src/overlays/shared/enemies/plasmabot.c @@ -188,7 +188,7 @@ void scale_and_apply_plasmabot_planar_velocity(char *moby) { /* steers the pitch angle of a moby toward a target and updates the joint */ /* Ported from rac1-decomp (src/overlays/shared/vendor_002B2A28.c: func_L14_002B4A00), where it is exact; names translated to the US level program. */ -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); void update_plasmabot_aim_joint_rotation(char *moby, float x) __asm__("FUN_L14_002b37b0"); @@ -210,7 +210,7 @@ void update_plasmabot_aim_joint_rotation(char *moby, float x) { k, frame_time * 6.2831854820251465f); } - FUN_L00_001fff28(&moby_vars->unk130, 2, *(float *)&moby_vars->unk270); + build_axis_rotation_quaternion(&moby_vars->unk130, 2, *(float *)&moby_vars->unk270); } /* Ported from rac1-decomp (src/overlays/shared/vendor_002B2A28.c: func_L14_002B4AE0), where it is exact; names translated to the US level program. */ @@ -1257,7 +1257,7 @@ float update_plasmabot_aim_quaternion(char *moby, int flag, float target_angle) yaw_easing_coefficient, frame_time * 6.2831854820251465f); } - FUN_L00_001fff28(&state->unk170, 2, state->unk268); + build_axis_rotation_quaternion(&state->unk170, 2, state->unk268); if (flag) { float owner_aim_position[4]; float owner_aim_offset[4]; @@ -1281,7 +1281,7 @@ float update_plasmabot_aim_quaternion(char *moby, int flag, float target_angle) frame_time_sq * 12.566370964050293f, frame_time * 6.2831854820251465f); cp = pitch_quaternion; - FUN_L00_001fff28(cp, 1, *(float *)&state->unk280); + build_axis_rotation_quaternion(cp, 1, *(float *)&state->unk280); multiply_quaternions(&state->unk170, &state->unk170, cp); } return fast_difference_between_rotations(turn, state->unk268); diff --git a/src/overlays/shared/enemies/walker_update_gait.c b/src/overlays/shared/enemies/walker_update_gait.c index acd6d5c52f..cea7984e92 100644 --- a/src/overlays/shared/enemies/walker_update_gait.c +++ b/src/overlays/shared/enemies/walker_update_gait.c @@ -47,7 +47,7 @@ int walker_gait_mask(float *gait_record, float interval_value) { return result_mask; } -void FUN_L00_001fff28(void *, s32, f32); +void build_axis_rotation_quaternion(void *, s32, f32) __asm__("FUN_L00_001fff28"); void reset_walker_gait_helpers(u8 *gait_data) __asm__("FUN_L00_002a1538"); void reset_walker_gait_helpers(u8 *gait_data) { @@ -57,9 +57,9 @@ void reset_walker_gait_helpers(u8 *gait_data) { for (i = 0; i < 2; i++) { u8 *gait_region_base = gait_data + i * 0xB0; if (gait_region_base[0x161] != 0) - FUN_L00_001fff28(gait_helper_record_base + i * 0xB0, 2, 0.0f); + build_axis_rotation_quaternion(gait_helper_record_base + i * 0xB0, 2, 0.0f); if (gait_region_base[0x121] != 0) - FUN_L00_001fff28(gait_helper_record_130_base + i * 0xB0, 2, 0.0f); + build_axis_rotation_quaternion(gait_helper_record_130_base + i * 0xB0, 2, 0.0f); *(s32 *)(gait_region_base + 0x104) = 0; *(s32 *)(gait_region_base + 0xFC) = 0; } diff --git a/src/overlays/shared/hero/set_hero_animation.c b/src/overlays/shared/hero/set_hero_animation.c index dd3d05ab59..aee32b6f86 100644 --- a/src/overlays/shared/hero/set_hero_animation.c +++ b/src/overlays/shared/hero/set_hero_animation.c @@ -1747,7 +1747,7 @@ void animate_hero_slot4_and_slot5_visuals(void) { if (!hero.unk1D90.attached) attach_manipulator(slot5_moby, 0, &hero.unk1D90); else - rotation_2D5FA8(&hero.unk1D90.quat, 0, hero.unk22F0); + build_axis_rotation_quaternion(&hero.unk1D90.quat, 0, hero.unk22F0); } } } diff --git a/src/overlays/shared/mobys/find_moby_hit.c b/src/overlays/shared/mobys/find_moby_hit.c index 9d17e4e86c..a856079b1d 100644 --- a/src/overlays/shared/mobys/find_moby_hit.c +++ b/src/overlays/shared/mobys/find_moby_hit.c @@ -293,16 +293,16 @@ typedef struct { int a[4]; } Vk __attribute__((aligned(16))); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); void build_quaternion_from_axis_rotations(void *output_quaternion, float *axis_rotation_angles) __asm__("FUN_L00_00259f50"); void build_quaternion_from_axis_rotations(void *output_quaternion, float *axis_rotation_angles) { Vk z_axis_quaternion, y_axis_quaternion, x_axis_quaternion; - FUN_L00_001fff28(&x_axis_quaternion, 0, axis_rotation_angles[0]); - FUN_L00_001fff28(&y_axis_quaternion, 1, axis_rotation_angles[1]); - FUN_L00_001fff28(&z_axis_quaternion, 2, axis_rotation_angles[2]); + build_axis_rotation_quaternion(&x_axis_quaternion, 0, axis_rotation_angles[0]); + build_axis_rotation_quaternion(&y_axis_quaternion, 1, axis_rotation_angles[1]); + build_axis_rotation_quaternion(&z_axis_quaternion, 2, axis_rotation_angles[2]); multiply_quaternions(output_quaternion, &x_axis_quaternion, &y_axis_quaternion); multiply_quaternions(output_quaternion, output_quaternion, &z_axis_quaternion); } diff --git a/src/overlays/shared/props/lamp.c b/src/overlays/shared/props/lamp.c index 879c7ac62a..d1d34ec741 100644 --- a/src/overlays/shared/props/lamp.c +++ b/src/overlays/shared/props/lamp.c @@ -32,7 +32,7 @@ typedef struct { extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); -extern void FUN_L00_001fff28(void *, int, float); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); void draw_moby_wobble_quads(struct Moby *moby) __asm__("FUN_L05_0030c220"); extern void draw_moby_wobble_quads(struct Moby *m) __asm__("FUN_L05_0030c220"); @@ -92,7 +92,7 @@ void moby_wobble_update(unsigned char *moby) { MOBY(moby)->rot.z = fast_add_rotations(wobble_vars->unk40, fast_sin(wobble_phase) * k); wobble_phase = fast_add_rotations(wobble_vars->unk48, wobble_vars->unk50); wobble_vars->unk48 = wobble_phase; - FUN_L00_001fff28(&wobble_vars->unk10, 1, fast_sin(wobble_phase) * k + k); + build_axis_rotation_quaternion(&wobble_vars->unk10, 1, fast_sin(wobble_phase) * k + k); break; } } diff --git a/src/overlays/shared/vendor/vendor.c b/src/overlays/shared/vendor/vendor.c index c494c70c34..8ef248e878 100644 --- a/src/overlays/shared/vendor/vendor.c +++ b/src/overlays/shared/vendor/vendor.c @@ -344,8 +344,8 @@ void vendor_update(P_2a57a8 *vendor_moby) { q->mC->h34 &= 0xFFFE; } add_draw_callback(FUN_L00_002a5040_2a57a8, vendor_moby); - rotation_2D5FA8((u8 *)q + 0x20, 2, vendor_manipulator_rotation_phase); - rotation_2D5FA8((u8 *)q + 0x60, 2, vendor_manipulator_counter_rotation_phase); + build_axis_rotation_quaternion((u8 *)q + 0x20, 2, vendor_manipulator_rotation_phase); + build_axis_rotation_quaternion((u8 *)q + 0x60, 2, vendor_manipulator_counter_rotation_phase); vendor_manipulator_rotation_phase = fast_add_rotations(vendor_manipulator_rotation_phase, 0.01f); vendor_manipulator_counter_rotation_phase = @@ -367,8 +367,8 @@ void vendor_update(P_2a57a8 *vendor_moby) { add_draw_callback(FUN_L00_002a5040_2a57a8, vendor_moby); interaction_allowed = 1; help_message_allowed = 1; - rotation_2D5FA8((u8 *)q + 0x20, 2, vendor_manipulator_rotation_phase); - rotation_2D5FA8((u8 *)q + 0x60, 2, vendor_manipulator_counter_rotation_phase); + build_axis_rotation_quaternion((u8 *)q + 0x20, 2, vendor_manipulator_rotation_phase); + build_axis_rotation_quaternion((u8 *)q + 0x60, 2, vendor_manipulator_counter_rotation_phase); vendor_manipulator_rotation_phase = fast_add_rotations(vendor_manipulator_rotation_phase, 0.01f); vendor_manipulator_counter_rotation_phase = diff --git a/src/overlays/shared/vendor/vendor_orb.c b/src/overlays/shared/vendor/vendor_orb.c index 50e755e6e3..bcc9914fcf 100644 --- a/src/overlays/shared/vendor/vendor_orb.c +++ b/src/overlays/shared/vendor/vendor_orb.c @@ -8,7 +8,7 @@ #include "rnc/math/random.h" #include "rnc/mobys/attach_manipulator.h" -void FUN_L00_001fff28(char *, int, float); +void build_axis_rotation_quaternion(char *, int, float) __asm__("FUN_L00_001fff28"); float vendor_orb_rotation_rate_degrees_gp __asm__("D_L00_00161BB0") = 45.0f; @@ -53,7 +53,7 @@ void vendor_orb_update(unsigned char *moby) { MOBY(moby)->rot.z = fast_add_rotations(MOBY(moby)->rot.z, rotation_step_radians); *(float *)(manipulator + 0x40) = fast_add_rotations(*(float *)(manipulator + 0x40), rotation_step_radians * -2.0f); - FUN_L00_001fff28(manipulator + 0x10, 2, *(float *)(manipulator + 0x40)); + build_axis_rotation_quaternion(manipulator + 0x10, 2, *(float *)(manipulator + 0x40)); break; } } diff --git a/src/overlays/shared/weapons/visibomb_missile.c b/src/overlays/shared/weapons/visibomb_missile.c index d16f0bb5e2..970f6a5269 100644 --- a/src/overlays/shared/weapons/visibomb_missile.c +++ b/src/overlays/shared/weapons/visibomb_missile.c @@ -933,12 +933,12 @@ void visibomb_missile_update(struct Moby *missile_moby) { func_L00_002B6E90_2b6140(missile_moby, missile_vars); { struct Moby *skip = missile_moby; - rotation_2D5FA8(&missile_vars->f24->pos, + build_axis_rotation_quaternion(&missile_vars->f24->pos, 1, -(missile_vars->f1C * 0.5f + absolute_float(missile_vars->f18 / 3.0f) + (missile_vars->f18 - missile_moby->rot.x) * 1.1f) * 0.7f); - rotation_2D5FA8(&missile_vars->f28->pos, + build_axis_rotation_quaternion(&missile_vars->f28->pos, 1, -(missile_vars->f1C * 0.5f + absolute_float(missile_vars->f18 / 3.0f) - (missile_vars->f18 - missile_moby->rot.x) * 1.1f) * From 9344a954fbc687ba965bedb4bd933dc88aa6ab1c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:51:06 +0000 Subject: [PATCH 0026/1502] decomp: clarify names in vo_buf_inc_count buf -> video_output_buffer: In the authoritative src/movies/decoder/video_output/vo_buf_inc_count.c snapshot (SHA-256 a081f715fda233c62ec98fa76b4449ae297e71c8229e0c63cdb6ced5cb33db39), buf has type struct VoBuf *. Retail 0x0023d220 preserves a0 in s0; 0x0023d224-0x0023d240 select tag[write] using offsets +8 and +4 and stride 0x138c0, then store status 2 (source VO_TAG_FILLED). 0x0023d244-0x0023d250 increment its +0xc count, and 0x0023d25c-0x0023d26c advance +8 write modulo +0x10 size. These match the established video output buffer operation and prove this parameter is the video output ring container. --- src/movies/decoder/video_output/vo_buf_inc_count.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/movies/decoder/video_output/vo_buf_inc_count.c b/src/movies/decoder/video_output/vo_buf_inc_count.c index a746710854..c6513460ae 100644 --- a/src/movies/decoder/video_output/vo_buf_inc_count.c +++ b/src/movies/decoder/video_output/vo_buf_inc_count.c @@ -5,11 +5,11 @@ extern s32 DIntr(void); void vo_buf_inc_count(struct VoBuf *buf) __asm__("FUN_0023d210"); -void vo_buf_inc_count(struct VoBuf *buf) { +void vo_buf_inc_count(struct VoBuf *video_output_buffer) { DIntr(); - buf->tag[buf->write].status = VO_TAG_FILLED; - buf->count++; - buf->write = (buf->write + 1) % buf->size; + video_output_buffer->tag[video_output_buffer->write].status = VO_TAG_FILLED; + video_output_buffer->count++; + video_output_buffer->write = (video_output_buffer->write + 1) % video_output_buffer->size; EnableInterrupts(); } From 192b79d02fc8a9ee24dd7eda9415ea20c992c471 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:56:24 +0000 Subject: [PATCH 0027/1502] decomp: clarify names in rumble_by_distance D_L07_00166E40 -> debris_far_point: The supplied identical-assembler-label context explicitly lists debris_far_point for D_L07_00166E40. Retail 0x003120dc/0x003120e8 forms address 0x00166e40 in s0, and 0x003120e4/0x003120f0/0x003120f4 passes moby+0x10 and that point to the distance helper, matching fast_vec_dist(moby + 0x10, D_L07_00166E40) in the bound source snapshot. Retail 0x00312124 derives point-0x140, with stores at 0x00312138 and 0x00312140 to 0x00166e68 and 0x00166e60: duration 20 and ((80-min(distance,80))/80)*0.1 rumble strength. Reuse the supplied same-label spelling exactly while preserving its extern char array type and assembler identity. --- src/overlays/l07/mobys/snagglebeast_effects.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l07/mobys/snagglebeast_effects.c b/src/overlays/l07/mobys/snagglebeast_effects.c index 25999c4aaa..1e14191330 100644 --- a/src/overlays/l07/mobys/snagglebeast_effects.c +++ b/src/overlays/l07/mobys/snagglebeast_effects.c @@ -15,7 +15,7 @@ #include "rnc/overlay/shared/rendering/effects/spawn_explosion.h" /* Ported from rac1-decomp (src/overlays/l07_umbris/vendor_002CE470.c: func_L07_0030E820), where it is exact; names translated to the US level program. */ -extern char D_L07_00166E40[]; +extern char debris_far_point[] __asm__("D_L07_00166E40"); extern void moby_point_position(void *, int, void *) __asm__("FUN_L00_0024f7c8"); /* Ported from rac1-decomp (src/overlays/l07_umbris/vendor_002CE470.c: func_L07_003134B8), where it is exact; names translated to the US level program. */ @@ -150,11 +150,11 @@ void configure_timed_point_light(float radius, } void rumble_by_distance(char *moby) { - float distance = fast_vec_dist(moby + 0x10, D_L07_00166E40); + float distance = fast_vec_dist(moby + 0x10, debris_far_point); char *state; if (distance > 80.0f) distance = 80.0f; - state = D_L07_00166E40 - 0x140; + state = debris_far_point - 0x140; *(int *)(state + 0x168) = 0x14; *(float *)(state + 0x160) = ((80.0f - distance) / 80.0f) * 0.1f; } From 5e334b73de06e18fc915a49282b68c880cf2d098 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:56:33 +0000 Subject: [PATCH 0028/1502] decomp: clarify names in draw_hud_radial_selector_panel D_L00_0015F780_gp -> l00_hud_selector_fade_counter_limit_gp: Authoritative source src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c SHA-256 efb82c4808a205a7e5c0c818fc3df30779f47466ae4b18e7d1ea7d87d583b5dd binds this int SDA extern to D_L00_0015F780. Original retail 0x00238fd0 loads element byte +0x70, 0x00238fd4 loads the scalar at gp-0x7480, and 0x00238fe0 divides the converted counter by it, clamping the fade to [0,1]. At 0x00239024/0x00239028/0x00239034 the same scalar normalizes byte +0x71. The first fade supplies frame alpha at 0x002390e0; the two fades multiply for label colors at 0x002394f0. Both supplied selector update functions cap their +0x70 and +0x71 counters against this exact C binding. Thus it is the selector fade counter limit, shared by opening and selected-label fading, rather than an alpha value or pulse period. --- .../ui/hud/draw_hud_item_selector_panel.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c index 4ab75946f0..60f7f41f35 100644 --- a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c +++ b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c @@ -204,7 +204,7 @@ typedef struct { extern int D_L00_0017E504 NOT_SDA; extern int D_L00_0015FA90; -extern int D_L00_0015F780_gp __asm__("D_L00_0015F780") __attribute__((sda)); +extern int l00_hud_selector_fade_counter_limit_gp __asm__("D_L00_0015F780") __attribute__((sda)); extern int saved_hud_selector_slot_index_gp __asm__("D_L00_0015FA9C") __attribute__((sda)); extern Ent **D_L00_0015FAC0_c __asm__("D_L00_0015FAC0"); extern int D_L00_0017DC38 NOT_SDA; @@ -343,7 +343,7 @@ void update_hud_item_selector_selection_and_visibility(Obj *hud_element) { } if (hud_element->w74 != previous_selected_slot_index) counters[1] = 0; - else if (counters[1] < D_L00_0015F780_gp) + else if (counters[1] < l00_hud_selector_fade_counter_limit_gp) counters[1]++; if (!(((s32)controller_state.held_unmasked) & 0x10)) { int sel = hud_element->w74; @@ -368,7 +368,7 @@ void update_hud_item_selector_selection_and_visibility(Obj *hud_element) { } if (counters[0]) counters[0]--; - } else if (counters[0] < D_L00_0015F780_gp) + } else if (counters[0] < l00_hud_selector_fade_counter_limit_gp) counters[0]++; if (counters[0] == 0) { { @@ -435,12 +435,12 @@ int draw_hud_item_selector_panel(HudElem *rec) { unsigned char *counters = rec->cnt; char formatted[80]; - open = convert_integer_to_float(counters[0]) / convert_integer_to_float(D_L00_0015F780_gp); + open = convert_integer_to_float(counters[0]) / convert_integer_to_float(l00_hud_selector_fade_counter_limit_gp); if (1.0f < open) open = 1.0f; else if (open < 0.0f) open = 0.0f; - fade = convert_integer_to_float(counters[1]) / convert_integer_to_float(D_L00_0015F780_gp); + fade = convert_integer_to_float(counters[1]) / convert_integer_to_float(l00_hud_selector_fade_counter_limit_gp); if (1.0f < fade) fade = 1.0f; else if (fade < 0.0f) @@ -684,7 +684,7 @@ void update_hud_radial_selector_selection_and_visibility(Obj *hud_element) { } if (hud_element->w74 != previous_slot_index) { counters[1] = 0; - } else if (counters[1] < D_L00_0015F780_gp) { + } else if (counters[1] < l00_hud_selector_fade_counter_limit_gp) { counters[1]++; } if (!(((s32)controller_state.held_unmasked) & 0x10)) { @@ -694,7 +694,7 @@ void update_hud_radial_selector_selection_and_visibility(Obj *hud_element) { D_00141610[0] = D_L00_0015FAC0_c[D_L00_0015F72C][hud_element->w74].unk18; if (counters[0] != 0) counters[0]--; - } else if (counters[0] < D_L00_0015F780_gp) { + } else if (counters[0] < l00_hud_selector_fade_counter_limit_gp) { counters[0]++; } if (counters[0] == 0) { @@ -789,7 +789,7 @@ int draw_hud_radial_selector_panel(Elem *element) { counters = element->cnt; { float frames = convert_integer_to_float(element->cnt[0]); - open_fade = frames / convert_integer_to_float(D_L00_0015F780_gp); + open_fade = frames / convert_integer_to_float(l00_hud_selector_fade_counter_limit_gp); } if (1.0f < open_fade) { open_fade = 1.0f; @@ -798,7 +798,7 @@ int draw_hud_radial_selector_panel(Elem *element) { } { float frames = convert_integer_to_float(counters[1]); - text_fade = frames / convert_integer_to_float(D_L00_0015F780_gp); + text_fade = frames / convert_integer_to_float(l00_hud_selector_fade_counter_limit_gp); } if (1.0f < text_fade) { text_fade = 1.0f; From f5bf1be91ee4056868b4117a284e6a3a616e76e0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:56:42 +0000 Subject: [PATCH 0029/1502] decomp: clarify names in activate_descriptor D_L10_0015EF50 -> l10_descriptor_table: Retail 0x002f5a50-0x002f5a54 loads the pointer stored at 0x0015EF50; 0x002f5a58 shifts the argument by five, 0x002f5a60 adds that 32-byte entry offset to the loaded base, and 0x002f5a64 loads its descriptor_record pointer at +0x1C. Stores at 0x002f5a68/0x002f5a70 then set descriptor bytes +0x38=1 and +0x39=0. The authoritative source repeats this lookup with path_camera->descriptor_index and cam->descriptor_index in initialize_path_camera/update_path_flythrough_camera, proving a descriptor table base. The l10 prefix identifies the owned overlay binding; preserve assembler label D_L10_0015EF50 and extern char * type. --- src/overlays/shared/camera/path_flythrough_camera.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/camera/path_flythrough_camera.c b/src/overlays/shared/camera/path_flythrough_camera.c index 7d95a95d01..50740f6fc9 100644 --- a/src/overlays/shared/camera/path_flythrough_camera.c +++ b/src/overlays/shared/camera/path_flythrough_camera.c @@ -18,13 +18,13 @@ #include "rnc/overlay/shared/camera/path_flythrough_camera.h" #include "rnc/overlay/shared/rendering/effects/spawn_explosion.h" -extern char *D_L10_0015EF50; +extern char *l10_descriptor_table __asm__("D_L10_0015EF50"); void activate_descriptor(int i) __asm__("FUN_L10_002f5a50"); void activate_descriptor(int i) { unsigned char *descriptor_record; - descriptor_record = *(unsigned char **)(D_L10_0015EF50 + i * 0x20 + 0x1C); + descriptor_record = *(unsigned char **)(l10_descriptor_table + i * 0x20 + 0x1C); descriptor_record[0x38] = 1; descriptor_record[0x39] = 0; } @@ -34,7 +34,7 @@ extern int point_in_path_xy(float *, float *, int) __asm__("FUN_L00_00259740"); int check_descriptor_hero_trigger(char *moby) __asm__("FUN_L10_002f5a78"); int check_descriptor_hero_trigger(char *moby) { - unsigned char *e = *(unsigned char **)(D_L10_0015EF50 + *(short *)(moby + 0x84) * 32 + 0x1C); + unsigned char *e = *(unsigned char **)(l10_descriptor_table + *(short *)(moby + 0x84) * 32 + 0x1C); if (*(int *)(e + 0x0C) >= 0) { if (is_point_inside_clip_volume(&hero.motion.pos, *(int *)(e + 0x0C))) @@ -89,7 +89,7 @@ extern VendorView_5f18 D_L10_0016CEC0; void initialize_path_camera(struct UpdateCam *path_camera) __asm__("FUN_L10_002f5b58"); void initialize_path_camera(struct UpdateCam *path_camera) { - char *rec = *(char **)(D_L10_0015EF50 + path_camera->descriptor_index * 32 + 0x1C); + char *rec = *(char **)(l10_descriptor_table + path_camera->descriptor_index * 32 + 0x1C); VendorCamRun_5f18 *run; VendorCamStops_5f18 *stops; f32 *fov; @@ -214,7 +214,7 @@ void update_path_flythrough_camera(struct UpdateCam *cam) { int i; saved = (char *)cam->saved_state; - rec = *(char **)(D_L10_0015EF50 + cam->descriptor_index * 32 + 0x1C); + rec = *(char **)(l10_descriptor_table + cam->descriptor_index * 32 + 0x1C); run = (VendorCamRun_5f18 *)(saved + 0x40); stops = (VendorCamStops_5f18 *)(saved + 0x58); @@ -353,7 +353,7 @@ int evaluate_descriptor_eligibility(char *descriptor_owner, int evaluate_descriptor_eligibility(char *descriptor_owner, char *comparison_object) { unsigned char *descriptor_record = - *(unsigned char **)(D_L10_0015EF50 + *(short *)(descriptor_owner + 0x84) * 32 + 0x1C); + *(unsigned char **)(l10_descriptor_table + *(short *)(descriptor_owner + 0x84) * 32 + 0x1C); int x; int y; if (descriptor_record[0x39] != 0) { From 0cd14560d1d3d43c453b9f89d7878dacc6d06fde Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:56:47 +0000 Subject: [PATCH 0030/1502] overlay: name move_moby_xy_with_collision_constraints --- .../shared/math/interpolation/spring_turn.h | 2 +- src/overlays/l01/mobys/water_lily.c | 3 ++- src/overlays/l04/mobys/big_axebot.c | 6 +++--- src/overlays/l04/mobys/blarg_trooper.c | 10 +++++----- src/overlays/l04/mobys/circular_saw_enemy.c | 12 +++++------ src/overlays/l04/mobys/woodcut_bot.c | 4 ++-- src/overlays/l15/mobys/ultramech_unlimited.c | 4 ++-- .../shared/math/interpolation/spring_turn.c | 6 +++++- .../mobys/update_object_wander_movement.c | 4 ++-- src/overlays/shared/weapons/mine.c | 4 ++-- .../shared/weapons/morphoray_chicken.c | 20 +++++++++---------- 11 files changed, 40 insertions(+), 35 deletions(-) diff --git a/include/rnc/overlay/shared/math/interpolation/spring_turn.h b/include/rnc/overlay/shared/math/interpolation/spring_turn.h index f05ddb6378..dfdec7efe4 100644 --- a/include/rnc/overlay/shared/math/interpolation/spring_turn.h +++ b/include/rnc/overlay/shared/math/interpolation/spring_turn.h @@ -8,7 +8,7 @@ s32 get_first_moby_in_group(void *, s32, s32, s32) __asm__("FUN_L00_002591d0"); s32 solve_quadratic_equation(f32 *, f32 *, f32, f32, f32) __asm__("FUN_L00_002595a0"); s32 get_next_moby_in_group(void *, void *, s32, s32) __asm__("FUN_L00_002592b8"); -void FUN_L00_00258490(void *, void *, void *, s32, f32, f32, f32, f32); +void move_moby_xy_with_collision_constraints(void *, void *, void *, s32, f32, f32, f32, f32) __asm__("FUN_L00_00258490"); float calculate_triangular_corrected_scalar(float *, float *, int *, diff --git a/src/overlays/l01/mobys/water_lily.c b/src/overlays/l01/mobys/water_lily.c index 952377ac63..2ac7dbdf36 100644 --- a/src/overlays/l01/mobys/water_lily.c +++ b/src/overlays/l01/mobys/water_lily.c @@ -12,6 +12,7 @@ #include "qcopy.h" #include "rnc/camera.h" #include "rnc/overlay/shared/math/interpolation/spring_turn.h" +void move_moby_xy_with_collision_constraints(void *, void *, void *, s32, f32, f32, f32, f32) __asm__("FUN_L00_00258490"); extern f32 frame_time_macro __asm__("D_0015ED6C") MACRO_ADDR; @@ -129,7 +130,7 @@ void water_lily_update(HoverMoby *water_lily) { water_lily->pos.v.y += hero.motion.pos.f[1]; } } - FUN_L00_00258490(water_lily, + move_moby_xy_with_collision_constraints(water_lily, &collision_adjusted_position, &water_lily->pos, 3, diff --git a/src/overlays/l04/mobys/big_axebot.c b/src/overlays/l04/mobys/big_axebot.c index 900efa8e5e..80644a0f21 100644 --- a/src/overlays/l04/mobys/big_axebot.c +++ b/src/overlays/l04/mobys/big_axebot.c @@ -248,7 +248,7 @@ extern int FUN_L00_001fefc8(void *); extern int is_point_inside_clip_volume(void *point, int volume_index) __asm__("FUN_00214720"); extern int hit_reaction(void *, void *, void *, int, int *, float *, int, int) __asm__("FUN_L00_0025a478"); -extern int FUN_L04_00295de8_cf(void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); +extern int move_moby_xy_with_collision_constraints(void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); extern int step_moby_motion(void *, void *) __asm__("FUN_L00_0025c698"); extern int allocate_voice_for_target_entry(int, int, char *); extern int mark_moby_for_removal_cf() __asm__("FUN_L04_002ba470"); @@ -649,7 +649,7 @@ void big_axebot_update(M_B7B0 *moby) { vector_quaternion_scratch[1] = fast_sin(moby->rot[2]) * (frame_time * 6.0f); vector_quaternion_scratch[2] = 0.0f; fast_vec_add(vector_quaternion_scratch, vector_quaternion_scratch, moby->pos); - FUN_L04_00295de8_cf( + move_moby_xy_with_collision_constraints( moby, moby->pos, vector_quaternion_scratch, 1, 0.25f, 1.5f, 0.75f, 0.87266463f); break; } @@ -896,7 +896,7 @@ void big_axebot_update(M_B7B0 *moby) { if (data->f420 == 0.0f) { data->f42C += -3.4f / (scale_time(7.0f) * scale_time(7.0f)); } - FUN_L04_00295de8_cf( + move_moby_xy_with_collision_constraints( moby, moby->pos, vector_quaternion_scratch, 1, 0.25f, 1.5f, 0.75f, 0.87266463f); } data->f408 *= 0.96f; diff --git a/src/overlays/l04/mobys/blarg_trooper.c b/src/overlays/l04/mobys/blarg_trooper.c index 5cac8271cc..63aad39590 100644 --- a/src/overlays/l04/mobys/blarg_trooper.c +++ b/src/overlays/l04/mobys/blarg_trooper.c @@ -149,7 +149,7 @@ extern void record_moby_hit(void *, void *) __asm__("FUN_L00_00259a88"); extern void update_joint_animation(char *, char *, int, float, float) __asm__("FUN_L00_002628d8"); extern void spawn_blarg_trooper_projectile(void *, void *, void *, int) __asm__("FUN_L04_002aee30"); void destroy_blarg_trooper(struct Moby *arg) __asm__("FUN_L04_002c4808"); -extern int func_L00_002594C8_o(void *, void *, void *, float, float, float, float, int) __asm__("FUN_L00_00258490"); +extern int move_moby_xy_with_collision_constraints(void *, void *, void *, float, float, float, float, int) __asm__("FUN_L00_00258490"); void blarg_trooper_update(struct Moby *moby) __asm__("FUN_L04_002c4850"); @@ -496,7 +496,7 @@ void blarg_trooper_update(struct Moby *moby) { update_scratch.w.p.v70[1] = fast_sin(moby->rot.z) * (frame_time * 2.5f); update_scratch.w.p.v70[2] = 0.0f; fast_vec_add(update_scratch.w.p.v70, update_scratch.w.p.v70, pos); - func_L00_002594C8_o(moby, pos, update_scratch.w.p.v70, 0.5f, 1.0f, 0.5f, 0.5235988f, 0); + move_moby_xy_with_collision_constraints(moby, pos, update_scratch.w.p.v70, 0.5f, 1.0f, 0.5f, 0.5235988f, 0); } break; case BLARG_TROOPER_STATE_RUN_TO_TARGET_OR_PATH_POINT: @@ -518,7 +518,7 @@ void blarg_trooper_update(struct Moby *moby) { update_scratch.w.p.v70[2] = 0.0f; fast_vec_add(update_scratch.w.p.v70, update_scratch.w.p.v70, pos); qcopy(update_scratch.w.p.v80, pos); - if (func_L00_002594C8_o(moby, + if (move_moby_xy_with_collision_constraints(moby, update_scratch.w.p.v80, update_scratch.w.p.v70, 0.5f, @@ -581,7 +581,7 @@ void blarg_trooper_update(struct Moby *moby) { update_scratch.w.p.v70[1] = fast_sin(moby->rot.z) * (frame_time * 6.0f); update_scratch.w.p.v70[2] = 0.0f; fast_vec_add(update_scratch.w.p.v70, update_scratch.w.p.v70, pos); - func_L00_002594C8_o( + move_moby_xy_with_collision_constraints( moby, pos, update_scratch.w.p.v70, 0.5f, 1.0f, 0.5f, 0.5235988f, 0); } } @@ -743,7 +743,7 @@ void blarg_trooper_update(struct Moby *moby) { fast_vec_add(update_scratch.w.p.v70, update_scratch.w.p.v70, pos); blarg_trooper_pvars->unkF4 = blarg_trooper_pvars->unkF4 + -2.0f / (scale_time(15.0f) * scale_time(15.0f)); - func_L00_002594C8_o(moby, pos, update_scratch.w.p.v70, 0.5f, 1.0f, 0.5f, 0.5235988f, 1); + move_moby_xy_with_collision_constraints(moby, pos, update_scratch.w.p.v70, 0.5f, 1.0f, 0.5f, 0.5235988f, 1); } if (moby->anim_flags & 2) { *(unsigned short *)&blarg_trooper_pvars->path_selector ^= 1; diff --git a/src/overlays/l04/mobys/circular_saw_enemy.c b/src/overlays/l04/mobys/circular_saw_enemy.c index 5a0f633215..74e0c5fc08 100644 --- a/src/overlays/l04/mobys/circular_saw_enemy.c +++ b/src/overlays/l04/mobys/circular_saw_enemy.c @@ -466,7 +466,7 @@ I4_35F0 D_L04_00161890 = { extern float fast_cos(float); extern float fast_sin(float); extern int collect_mobies_in_sphere(void *, int, void *, void *, float) __asm__("FUN_L00_001f2868"); -extern int FUN_L00_00258490(void *, void *, void *, int, float, float, float, float); +extern int move_moby_xy_with_collision_constraints(void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); extern int FUN_L00_002dc9f0(void *, void *); short D_L04_00161878 = 0x101; extern void FUN_L01_0026d930(char *p); @@ -981,7 +981,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { v[2] = 0.0f; fast_vec_add(v, v, moby->pos); data->f13C += -10.0f / (scale_time(15.0f) * scale_time(15.0f)); - FUN_L00_00258490(moby, moby->pos, v, 1, 0.25f, 0.57f, 0.5f, 0.5235988f); + move_moby_xy_with_collision_constraints(moby, moby->pos, v, 1, 0.25f, 0.57f, 0.5f, 0.5235988f); } } if (moby->state == 9) { @@ -999,7 +999,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { v[2] = 0.0f; fast_vec_add(v, v, moby->pos); qcopy(np, moby->pos); - FUN_L00_00258490(moby, np, v, 0, 0.25f, 0.57f, 0.5f, 0.5235988f); + move_moby_xy_with_collision_constraints(moby, np, v, 0, 0.25f, 0.57f, 0.5f, 0.5235988f); if (data->f138 == -1 || point_in_path_xy(np, ((P_35F0 *)l04_paths[data->f138])->pts, @@ -1042,7 +1042,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { anim = 0; } qcopy(np, moby->pos); - moved = FUN_L00_00258490(moby, np, v, 0, 0.25f, 0.57f, 0.5f, 0.5235988f); + moved = move_moby_xy_with_collision_constraints(moby, np, v, 0, 0.25f, 0.57f, 0.5f, 0.5235988f); if (data->f138 == -1 || point_in_path_xy(np, ((P_35F0 *)l04_paths[data->f138])->pts, @@ -1071,7 +1071,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { v[2] = 0.0f; fast_vec_add(v, v, moby->pos); qcopy(np, moby->pos); - FUN_L00_00258490(moby, np, v, 0, 0.25f, 1.25f, 0.5f, 0.5235988f); + move_moby_xy_with_collision_constraints(moby, np, v, 0, 0.25f, 1.25f, 0.5f, 0.5235988f); if (data->f138 == -1 || point_in_path_xy(np, ((P_35F0 *)l04_paths[data->f138])->pts, @@ -1084,7 +1084,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { V4_35F0 v; { qcopy(v, moby->pos); - FUN_L00_00258490(moby, moby->pos, v, 0, 0.25f, 0.57f, 0.5f, 0.5235988f); + move_moby_xy_with_collision_constraints(moby, moby->pos, v, 0, 0.25f, 0.57f, 0.5f, 0.5235988f); } } data->f78 += frame_time_sq * 9.8f; diff --git a/src/overlays/l04/mobys/woodcut_bot.c b/src/overlays/l04/mobys/woodcut_bot.c index 8b96ec0746..c76cf898a4 100644 --- a/src/overlays/l04/mobys/woodcut_bot.c +++ b/src/overlays/l04/mobys/woodcut_bot.c @@ -299,7 +299,7 @@ extern void *memset(void *, int, unsigned int); extern void coll_line_fix(void *, void *, int, void *, void *) __asm__("FUN_001efa68"); extern void add_vectors(void *, void *, void *) __asm__("FUN_L00_001ff290"); extern void FUN_L00_00257470(void *, int, int); -extern void FUN_L00_00258490(void *, void *, void *, int, float, float, float, float); +extern void move_moby_xy_with_collision_constraints(void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); extern void FUN_L00_0025a120(void *); extern void trooper_knockback_arc(void *, float *, void *, void *) __asm__("FUN_L00_0025ab48"); extern void @@ -966,7 +966,7 @@ void woodcut_bot_update(WBMoby *m) { recoil_scratch[2] = 0.0f; fast_vec_add(recoil_scratch, recoil_scratch, pos); d->f3E4 += -2.0f / (scale_time(15.0f) * scale_time(15.0f)); - FUN_L00_00258490(m, pos, recoil_scratch, 1, 0.25f, 1.0f, 0.75f, 0.87266463f); + move_moby_xy_with_collision_constraints(m, pos, recoil_scratch, 1, 0.25f, 1.0f, 0.75f, 0.87266463f); } d->f3C8 *= 0.96f; build_axis_rotation_quaternion(recoil_scratch, 1, d->f3C8); diff --git a/src/overlays/l15/mobys/ultramech_unlimited.c b/src/overlays/l15/mobys/ultramech_unlimited.c index 838b44c025..32370da575 100644 --- a/src/overlays/l15/mobys/ultramech_unlimited.c +++ b/src/overlays/l15/mobys/ultramech_unlimited.c @@ -213,7 +213,7 @@ extern float approach_angle(void *, float, void *, float, float, float) __asm__( extern float compute_ultramech_flocking_steering_point(void *, void *, float) __asm__("FUN_L15_002cf110"); -extern int FUN_L00_00258490(void *, void *, void *, int, float, float, float, float); +extern int move_moby_xy_with_collision_constraints(void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); extern int sweep_hit_segment(void *a, void *b, void *c, void *d, void *e, void *f, int n) __asm__("FUN_L00_00259d08"); @@ -681,7 +681,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { normalize_vector_xyz( &position_or_motion_vector, &position_or_motion_vector, frame_time * 6.5f); add_vectors(&vector_arithmetic_result, &position_or_motion_vector, &ultramech_moby->pos); - if (!FUN_L00_00258490(ultramech_moby, + if (!move_moby_xy_with_collision_constraints(ultramech_moby, &vector_or_hit_descriptor, &position_or_motion_vector, 1, diff --git a/src/overlays/shared/math/interpolation/spring_turn.c b/src/overlays/shared/math/interpolation/spring_turn.c index e0ef1bce4f..cbe4e79f97 100644 --- a/src/overlays/shared/math/interpolation/spring_turn.c +++ b/src/overlays/shared/math/interpolation/spring_turn.c @@ -192,7 +192,11 @@ extern float allocate_voice_for_target_entry_cf(void *) __asm__("FUN_L00_0025971 extern int FUN_001efa68_258490(void *, void *, int, void *, int) __asm__("FUN_001efa68"); extern int FUN_L00_001f0d60_258490(void *, float, int, void *) __asm__("FUN_L00_001f0d60"); -int FUN_L00_00258490( +int move_moby_xy_with_collision_constraints( + + void *ign, V_258490 *to, V_258490 *pos, int flags, float h, float r, float lim, float slope) __asm__("FUN_L00_00258490"); + +int move_moby_xy_with_collision_constraints( void *ign, V_258490 *to, V_258490 *pos, int flags, float h, float r, float lim, float slope) { V_258490 d; diff --git a/src/overlays/shared/mobys/update_object_wander_movement.c b/src/overlays/shared/mobys/update_object_wander_movement.c index 027f73435e..f5c892759d 100644 --- a/src/overlays/shared/mobys/update_object_wander_movement.c +++ b/src/overlays/shared/mobys/update_object_wander_movement.c @@ -12,7 +12,7 @@ #include "rnc/overlay/shared/mobys/find_moby_hit.h" void step_angle_toward_target(void *, s32, f32, f32) __asm__("FUN_L00_0025bc00"); -s32 FUN_L00_00258490_261630(void *, void *, void *, s32, f32, f32, f32, f32) __asm__("FUN_L00_00258490"); +s32 move_moby_xy_with_collision_constraints(void *, void *, void *, s32, f32, f32, f32, f32) __asm__("FUN_L00_00258490"); void update_object_wander_movement(u8 *moving_object, u8 *movement_state, f32 a, @@ -47,7 +47,7 @@ void update_object_wander_movement(u8 *moving_object, fast_cos(*(f32 *)(moving_object + 0x48)) * *(f32 *)(movement_state + 0x14); ((f32 *)proposed_position)[1] += fast_sin(*(f32 *)(moving_object + 0x48)) * *(f32 *)(movement_state + 0x14); - movement_unconstrained = FUN_L00_00258490_261630(moving_object, + movement_unconstrained = move_moby_xy_with_collision_constraints(moving_object, pos, proposed_position, 0, diff --git a/src/overlays/shared/weapons/mine.c b/src/overlays/shared/weapons/mine.c index 45f5f581b5..5da59b02e4 100644 --- a/src/overlays/shared/weapons/mine.c +++ b/src/overlays/shared/weapons/mine.c @@ -62,7 +62,7 @@ extern int FUN_L00_001f0d60(float, void *, int, void *); extern int collect_mobies_in_sphere(void *, int, void *, void *, float) __asm__("FUN_L00_001f2868"); extern int hud_counter_update(int, int, float) __asm__("FUN_L00_002371e0"); extern int FUN_L00_00257b90(int, int); -extern int FUN_L00_00258490(void *, void *, void *, float, float, float, float, int); +extern int move_moby_xy_with_collision_constraints(void *, void *, void *, float, float, float, float, int) __asm__("FUN_L00_00258490"); extern int FUN_L00_00260400(void *, void *, void *, void *, void *, void *); extern int random_integer_below_cf(void *, void *, float, float) __asm__("FUN_L00_0026f080"); extern int voice_is_playing(void *, int) __asm__("FUN_L00_0028d8c0"); @@ -1063,7 +1063,7 @@ void mine_update(M910 *mine_moby) { fast_vec_normalize(t, t, 0.75f); fast_vec_add(r, &((M910 *)hero.moby)->pos, t); *(OvlQuad *)n = *(OvlQuad *)r; - FUN_L00_00258490( + move_moby_xy_with_collision_constraints( mine_moby, &mine_moby->pos, n, 0.4f, 0.25f, 0.25f, 0.5235988f, 0); } } else { diff --git a/src/overlays/shared/weapons/morphoray_chicken.c b/src/overlays/shared/weapons/morphoray_chicken.c index 375024ee68..28e6c74ead 100644 --- a/src/overlays/shared/weapons/morphoray_chicken.c +++ b/src/overlays/shared/weapons/morphoray_chicken.c @@ -174,7 +174,7 @@ void spawn_explosion(char *m, extern void send_blast_hits(void *, void *, void *, int, int, int, int, int, float, float, float) __asm__("FUN_L00_0025a9f8"); unsigned char *spawn_feather_moby(int unused, void *pos, float *vel) __asm__("FUN_L00_002cbf68"); -extern int FUN_L00_00258490(void *, void *, void *, int, float, float, float, float); +extern int move_moby_xy_with_collision_constraints(void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); extern void FUN_L00_00258278(void *, float *, float, float, float, float); extern float FUN_L00_00259710(void *); extern int FUN_L00_002dc9f0(void *, void *); @@ -549,7 +549,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { ahead.y = fast_sin(chicken_moby->rot.z) * frame_time * size; ahead.z = 0.0f; fast_vec_add(&ahead, &ahead, &next_pos); - path_clear = FUN_L00_00258490( + path_clear = move_moby_xy_with_collision_constraints( chicken_moby, &next_pos, &ahead, 0, size * 0.2f, size * 0.5f, speed, 0.2617994f); if (path_clear != 0 || (fast_difference_between_rotations(chicken_moby->rot.z, @@ -566,12 +566,12 @@ void morphoray_chicken_update(Moby *chicken_moby) { } else if (vector_distance_xy(&chicken_moby->pos, &hero.motion.pos) < size * 5.0f && 0.5235988f < fast_difference_between_rotations(flee_angle, chicken_moby->rot.z)) { - FUN_L00_00258490( + move_moby_xy_with_collision_constraints( chicken_moby, &next_pos, &next_pos, 0, size * 0.2f, size * 0.5f, speed, 0.2617994f); chicken_moby->state = 2; blend_moby_animation(chicken_moby, 3, 0, scale_game_frames(10)); } else { - FUN_L00_00258490( + move_moby_xy_with_collision_constraints( chicken_moby, &next_pos, &next_pos, 0, size * 0.2f, size * 0.5f, speed, 0.2617994f); } break; @@ -582,7 +582,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { frame_time_sq * 0.7853982f, frame_time_sq * 1.5707964f, frame_time * 0.7853982f); - FUN_L00_00258490( + move_moby_xy_with_collision_constraints( chicken_moby, &next_pos, &next_pos, 0, size * 0.2f, size * 0.5f, speed, 0.2617994f); if (fast_dec_timer_s16(&chicken_vars->flee_timer) != 0 && vector_distance_xy(&chicken_moby->pos, &hero.motion.pos) < size * 5.0f) { @@ -612,7 +612,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { random_int_between(scale_game_frames(0x3C), scale_game_frames(0xB4)); blend_moby_animation( chicken_moby, random_integer_below(2) == 0, 0, scale_game_frames(5)); - FUN_L00_00258490( + move_moby_xy_with_collision_constraints( chicken_moby, &next_pos, &next_pos, 0, size * 0.2f, size * 0.5f, speed, 0.2617994f); } else if (vector_distance_xy(&chicken_moby->pos, &hero.motion.pos) < size * 3.0f) { FUN_L00_00258278(chicken_moby, @@ -625,7 +625,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { ahead.y = fast_sin(chicken_moby->rot.z) * (frame_time + frame_time); ahead.z = 0.0f; fast_vec_add(&ahead, &ahead, &next_pos); - path_clear = FUN_L00_00258490( + path_clear = move_moby_xy_with_collision_constraints( chicken_moby, &next_pos, &ahead, 0, size * 0.2f, size * 0.5f, speed, 0.2617994f); if (path_clear == 0 && (1.5707964f < fast_difference_between_rotations( @@ -653,7 +653,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { ahead.y = fast_sin(chicken_moby->rot.z) * frame_time * size; ahead.z = 0.0f; fast_vec_add(&ahead, &ahead, &next_pos); - path_clear = FUN_L00_00258490( + path_clear = move_moby_xy_with_collision_constraints( chicken_moby, &next_pos, &ahead, 0, size * 0.2f, size * 0.5f, speed, 0.2617994f); if (path_clear == 0 && (1.5707964f < fast_difference_between_rotations( @@ -682,7 +682,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { ahead.y = fast_sin(chicken_moby->rot.z) * frame_time * size; ahead.z = 0.0f; fast_vec_add(&ahead, &ahead, &next_pos); - path_clear = FUN_L00_00258490( + path_clear = move_moby_xy_with_collision_constraints( chicken_moby, &next_pos, &ahead, 0, size * 0.2f, size * 0.5f, speed, 0.2617994f); if (path_clear == 0 && (1.5707964f < fast_difference_between_rotations( @@ -710,7 +710,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { ahead.y = fast_sin(chicken_moby->rot.z) * (frame_time + frame_time) * size; ahead.z = 0.0f; fast_vec_add(&ahead, &ahead, &next_pos); - path_clear = FUN_L00_00258490( + path_clear = move_moby_xy_with_collision_constraints( chicken_moby, &next_pos, &ahead, 0, size * 0.2f, size * 0.5f, speed, 0.2617994f); if (path_clear == 0 && (1.5707964f < fast_difference_between_rotations( From ffe36d0a39526aa1da92b37945ce025dbba28d30 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:56:52 +0000 Subject: [PATCH 0031/1502] overlay: name spawn_particle_alt_9768 --- src/overlays/shared/enemies/bomber_jet_projectile.c | 4 ++-- src/overlays/shared/rendering/effects/spawn_explosion.c | 4 ++-- .../rendering/effects/update_three_phase_effect_particle.c | 4 ++-- src/overlays/shared/vehicles/giant_clank_missile.c | 4 ++-- src/overlays/shared/weapons/gold_devastator_missile.c | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/shared/enemies/bomber_jet_projectile.c b/src/overlays/shared/enemies/bomber_jet_projectile.c index d77d966071..cf4ac2e397 100644 --- a/src/overlays/shared/enemies/bomber_jet_projectile.c +++ b/src/overlays/shared/enemies/bomber_jet_projectile.c @@ -54,7 +54,7 @@ typedef struct { extern int collect_mobies_in_sphere(float, void *, int, void *, void *) __asm__("FUN_L00_001f2868"); extern int spawn_glow_particle(void *, void *, void *, float, int, int, int, int, int) __asm__("FUN_L00_002ac910"); extern void spawn_effect(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); -extern void FUN_L00_0026a4c8(void *, void *, int, int, int, float); +extern void spawn_particle_alt_9768(void *, void *, int, int, int, float) __asm__("FUN_L00_0026a4c8"); extern void spawn_particle(void *, void *, int, int, float, int, int, int, int, float) __asm__("FUN_L00_0026a9f0"); extern void spawn_shrinking_effect_particle_with_gravity_and_secondary_spawns( void *, void *, int, int, float, int, int, int, int) __asm__("FUN_L00_0026bb70"); @@ -257,7 +257,7 @@ void explosive_projectile_update(struct Moby *moby) { fast_vec_normalize(&flash_emission_vector, &flash_emission_vector, size_scale * (random_float_between(0.0f, 3.0f) * D_0015ED6C)); - FUN_L00_0026a4c8( + spawn_particle_alt_9768( &(*(Vec_2F7E08 *)&moby->pos), &flash_emission_vector, start_colors.c[random_integer_below(6)], diff --git a/src/overlays/shared/rendering/effects/spawn_explosion.c b/src/overlays/shared/rendering/effects/spawn_explosion.c index 801e4ad462..4f47f2bbbe 100644 --- a/src/overlays/shared/rendering/effects/spawn_explosion.c +++ b/src/overlays/shared/rendering/effects/spawn_explosion.c @@ -613,7 +613,7 @@ extern void *spawn_shrinking_effect_particle_with_gravity_and_secondary_spawns( extern void *spawn_debris(void *, void *, int, int, int) __asm__("FUN_L00_002af450"); extern void spawn_particle(void *, void *, int, int, float, int, int, int, int, float) __asm__("FUN_L00_0026a9f0"); extern void -func_L00_0026B368_25e450(void *, void *, int, int, int, float) __asm__("FUN_L00_0026a4c8"); +spawn_particle_alt_9768(void *, void *, int, int, int, float) __asm__("FUN_L00_0026a4c8"); extern int spawn_glow_particle(void *, void *, void *, float, int, int, int, int, int) __asm__("FUN_L00_002ac910"); extern void mine_camera_blast(void *, void *, int, int) __asm__("FUN_L00_002d3838"); @@ -830,7 +830,7 @@ void spawn_explosion(char *owner_moby, fF * (random_float_between(0.0f, 3.0f) * frame_time_macro)); first_packed_color = swap_packed_color_channels(c0.v[random_integer_below(6)], flag); second_packed_color = swap_packed_color_channels(c1.v[random_integer_below(6)], flag); - func_L00_0026B368_25e450( + spawn_particle_alt_9768( explosion_position, &randomized_particle_vector, first_packed_color, diff --git a/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c b/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c index 2f8fc4362f..1f07b4efda 100644 --- a/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c +++ b/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c @@ -501,8 +501,8 @@ void update_colliding_effect_particle(struct EffectParticle *particle) { extern unsigned char *D_L00_001B20A0_0026a4c8 __asm__("D_L00_001B20A0") __attribute__((section(".data"))); unsigned char *FUN_L00_002678b8_0026a4c8(int) __asm__("FUN_L00_002678b8"); -void FUN_L00_0026a4c8(u128 *a, u128 *b, int c, int d, int n, float f); -void FUN_L00_0026a4c8(u128 *spawn_position, +void spawn_particle_alt_9768(u128 *a, u128 *b, int c, int d, int n, float f) __asm__("FUN_L00_0026a4c8"); +void spawn_particle_alt_9768(u128 *spawn_position, u128 *initial_velocity, int initial_color, int final_color, diff --git a/src/overlays/shared/vehicles/giant_clank_missile.c b/src/overlays/shared/vehicles/giant_clank_missile.c index 4891ac6a3c..cf15e22e91 100644 --- a/src/overlays/shared/vehicles/giant_clank_missile.c +++ b/src/overlays/shared/vehicles/giant_clank_missile.c @@ -260,7 +260,7 @@ extern void FUN_L00_001ffd48(void *, void *, float); extern void FUN_L00_001ffe20(void *, void *, void *); extern void FUN_L00_0025a9f8(void *, void *, void *, int, int, int, int, int, float, float, float); extern void mine_spawn_drops(void *, void *) __asm__("FUN_L00_0025f800"); -extern void FUN_L00_0026a4c8(void *pos, void *vel, int color, int tag, int life, float size); +extern void spawn_particle_alt_9768(void *pos, void *vel, int color, int tag, int life, float size) __asm__("FUN_L00_0026a4c8"); extern void spawn_particle(void *, void *, int, int, float, int, int, float, int, int) __asm__("FUN_L00_0026a9f0"); extern void spawn_burst(void *, void *, int, int, int, int, float) __asm__("FUN_L00_0026cbb0"); extern void FUN_L00_002ac910(char *, char *, int, int, float, int, int, int, int); @@ -699,7 +699,7 @@ void giant_clank_missile_update(M_29E8A0 *missile_moby) { { int *p1 = &c1.c[random_integer_below(6)]; int *p2 = &c2.c[random_integer_below(6)]; - FUN_L00_0026a4c8( + spawn_particle_alt_9768( missile_moby->pos, burst_particle_velocity, *p1, diff --git a/src/overlays/shared/weapons/gold_devastator_missile.c b/src/overlays/shared/weapons/gold_devastator_missile.c index a93872b03e..71b8264bcf 100644 --- a/src/overlays/shared/weapons/gold_devastator_missile.c +++ b/src/overlays/shared/weapons/gold_devastator_missile.c @@ -174,7 +174,7 @@ extern void FUN_L00_001ff290_c(void *, void *, void *) __asm__("FUN_L00_001ff290 extern int collision1688(void *, void *, int, void *, void *) __asm__("FUN_001efa68"); extern void FUN_L00_001ffd48_c(void *, void *, float) __asm__("FUN_L00_001ffd48"); extern void FUN_L00_001ffe20_c(void *, void *, void *) __asm__("FUN_L00_001ffe20"); -extern void FUN_L00_0026a4c8_c(void *, void *, int, int, float, int) __asm__("FUN_L00_0026a4c8"); +extern void spawn_particle_alt_9768(void *, void *, int, int, float, int) __asm__("FUN_L00_0026a4c8"); extern E D_0013E520; extern char *active_mobies[] __asm__("D_L00_001ABA00"); @@ -1028,7 +1028,7 @@ void gold_devastator_missile_update(M910 *missile_moby) { debris_scale = size * 200000.0f; life = random_int_between(scale_game_frames(20), scale_game_frames(35)) - particle_reduction * 10; - FUN_L00_0026a4c8_c((&missile_moby->pos), &v, c, f, debris_scale, life); + spawn_particle_alt_9768((&missile_moby->pos), &v, c, f, debris_scale, life); } if (D_L00_0015F5D0 < 0.95f && distance > 9.0f) { int c = 127, f = 127; From 6b82b65d78c91b8111347019dba3d737813a14b5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:58:48 +0000 Subject: [PATCH 0032/1502] overlay: name spawn_shuttle_explosion_effect --- src/overlays/l06/mobys/shuttle.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/overlays/l06/mobys/shuttle.c b/src/overlays/l06/mobys/shuttle.c index a7dc21d43a..7c176650bc 100644 --- a/src/overlays/l06/mobys/shuttle.c +++ b/src/overlays/l06/mobys/shuttle.c @@ -671,7 +671,9 @@ int update_shuttle_path_ride(char *moby, int path) { return ride->progress == 1.0f; } -void FUN_L06_00303748(float scale, char *moby, char *pos, char *push, int count) { +void spawn_shuttle_explosion_effect(float scale, char *moby, char *pos, char *push, int count) __asm__("FUN_L06_00303748"); + +void spawn_shuttle_explosion_effect(float scale, char *moby, char *pos, char *push, int count) { float position[4], direction[4], velocity[4], acceleration[4]; Colors first_colors, second_colors; int i; @@ -779,7 +781,7 @@ void break_apart_shuttle_linked_mobys(struct Moby *moby) { do { id = *list & 0x7FFF; random_vector(push, 1.0f, 2.0f); - FUN_L06_00303748( + spawn_shuttle_explosion_effect( 30.0f, moby, &((struct Moby *)(D_L06_0015FFD8_03b68 + (id << 8)))->pos, push, 1); fast_vec_add(middle, middle, &((struct Moby *)(D_L06_0015FFD8_03b68 + (id << 8)))->pos); count++; From 5e1470dcab3d0e3939ffb72dfca7485fa489f33c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:58:48 +0000 Subject: [PATCH 0033/1502] decomp: clarify names in queue_scene_movie_with_game_language a -> scene_movie_sector: Authoritative source SHA-256 4960804ab36eefa6256e87e49d855ceb749973671f2d0fc211638ef1032f275f assigns s32 a from disc_table.unk18A0[i].sector or unk1808[i].sector. Retail 0x00299494/0x002994ac loads that record word into a3; 0x002994e8 moves a3 into a0 for prepare_movie_playback at 0x002995d0. Original Ghidra uVar2 likewise flows from 0x139420 or 0x139388 plus i*8 to the first argument, whose established source name is sector. b -> scene_movie_size: In the bound authoritative source, s32 b receives disc_table.unk18A0[i].size or unk1808[i].size and is the second argument to prepare_movie_playback(a,b,game_language). Retail 0x0029948c/0x002994a8 loads the record's +4 word into a1, preserved through the 0x002994e4 call to 0x002995d0. Original Ghidra uVar1 is loaded from 0x139424 or 0x13938c plus i*8 and passed second; the established callee parameter is size. --- .../shared/cutscenes/update_cutscene_playback.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/cutscenes/update_cutscene_playback.c b/src/overlays/shared/cutscenes/update_cutscene_playback.c index 1a7658c5e1..8736939043 100644 --- a/src/overlays/shared/cutscenes/update_cutscene_playback.c +++ b/src/overlays/shared/cutscenes/update_cutscene_playback.c @@ -823,22 +823,22 @@ void hero_respawn() __asm__("FUN_L00_00211250"); void queue_scene_movie_with_game_language(s32 i) __asm__("FUN_L00_00299460"); void queue_scene_movie_with_game_language(s32 i) { - s32 a, b; + s32 scene_movie_sector, scene_movie_size; struct Hero *hero_ptr; if (i < 0) return; if (D_0015ED80) { - a = disc_table.unk18A0[i].sector; - b = disc_table.unk18A0[i].size; + scene_movie_sector = disc_table.unk18A0[i].sector; + scene_movie_size = disc_table.unk18A0[i].size; } else { - a = disc_table.unk1808[i].sector; - b = disc_table.unk1808[i].size; + scene_movie_sector = disc_table.unk1808[i].sector; + scene_movie_size = disc_table.unk1808[i].size; } hero_ptr = &hero; if (hero_ptr->health.hp == 0) { hero_respawn(); } else if (hero_ptr->fall_fade_pending == 0) { - prepare_movie_playback(a, b, game_language); + prepare_movie_playback(scene_movie_sector, scene_movie_size, game_language); } } From eeaf581ade21dfa5025c0b88d098a30e722258ff Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:58:55 +0000 Subject: [PATCH 0034/1502] overlay: name spawn_bomber_jet_beam --- src/overlays/l01/mobys/bomber_jet.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/bomber_jet.c b/src/overlays/l01/mobys/bomber_jet.c index 2ecfbde38d..405aefec11 100644 --- a/src/overlays/l01/mobys/bomber_jet.c +++ b/src/overlays/l01/mobys/bomber_jet.c @@ -81,7 +81,9 @@ typedef struct { extern void update_entity() __asm__("FUN_L00_00250df8"); extern void spawn_source_attached_fading_effect_particle(void *, u32, s32, s32, f32) __asm__("FUN_L00_0026daa0"); -BeamMoby *FUN_L01_002f68a0(void *owner, u128 *pos, u128 *dir, u128 *color, s32 kind) { +BeamMoby *spawn_bomber_jet_beam(void *owner, u128 *pos, u128 *dir, u128 *color, s32 kind) __asm__("FUN_L01_002f68a0"); + +BeamMoby *spawn_bomber_jet_beam(void *owner, u128 *pos, u128 *dir, u128 *color, s32 kind) { Vec4 position_copy; Vec4 direction_copy; Vec4 target_position_copy; From 891b0a47fab1fa161f52c91a271b0858550bc3f5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:58:55 +0000 Subject: [PATCH 0035/1502] decomp: clarify names in pad_pressed_within n -> requested_lookback_frames: In the SHA-256-bound source pad_pressed_within takes s32 n and clamps history_search_limit to n. Retail param_2/a1 is compared with hist_count at 0x00266d6c-0x00266d74; the selected bound plus one controls loop termination at 0x00266dec-0x00266df0. The scan walks backward through pressed_history modulo 30 at 0x00266da8-0x00266dc4 and writes scan distance minus one as press age at 0x00266dd8-0x00266ddc. Supplied callers pass scale_game_frames(7) and scale_game_frames(0x12) as this second argument, proving a requested lookback measured in frames. --- src/overlays/shared/input/pad_pressed_within.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/input/pad_pressed_within.c b/src/overlays/shared/input/pad_pressed_within.c index b00d98e7da..f3f45930bb 100644 --- a/src/overlays/shared/input/pad_pressed_within.c +++ b/src/overlays/shared/input/pad_pressed_within.c @@ -5,11 +5,11 @@ u32 pad_pressed_within(u32 mask, s32 n, s32 *out) __asm__("FUN_L00_00266d60"); -u32 pad_pressed_within(u32 mask, s32 n, s32 *press_age_frames_out) { +u32 pad_pressed_within(u32 mask, s32 requested_lookback_frames, s32 *press_age_frames_out) { s32 history_search_limit = controller_state.hist_count; s32 i; - if (history_search_limit >= n) - history_search_limit = n; + if (history_search_limit >= requested_lookback_frames) + history_search_limit = requested_lookback_frames; for (i = 1; i < history_search_limit + 1; i++) { s32 k = (controller_state.hist_idx - i + 30) % 30; if (controller_state.pressed_history[k] & mask) { From e013ef2b0d8947171ef9297cc2f4c5ad46e0fedb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:01:03 +0000 Subject: [PATCH 0036/1502] decomp: clarify names in ocean_umbris_update D_L07_00166E40 -> debris_far_point: Retail 0x0030d49c-0x0030d4a4 forms address 0x00166e40 in a0 and calls the established is_point_inside_clip_volume; 0x0030d498 and the 0x0030d4a8 delay slot load the volume index from the moby's pvars into a1. The authoritative C passes D_L07_00166E40 as that helper's point argument. The supplied helper subtracts this point from the clip-volume origin and transforms it for bounds checks. A zero return gates draw-callback registration at 0x0030d4ac-0x0030d4c0. Reuse exactly debris_far_point, the supplied existing name for this identical assembler label, preserving the char array declaration and binding. --- src/overlays/l07/mobys/ocean_umbris.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l07/mobys/ocean_umbris.c b/src/overlays/l07/mobys/ocean_umbris.c index 077fb8028b..c107b886bf 100644 --- a/src/overlays/l07/mobys/ocean_umbris.c +++ b/src/overlays/l07/mobys/ocean_umbris.c @@ -8,7 +8,7 @@ #include "rnc/runtime/callbacks/add_draw_callback.h" /* Ported from rac1-decomp (src/overlays/l07_umbris/vendor_002CE470.c: func_L07_0030E820), where it is exact; names translated to the US level program. */ -extern char D_L07_00166E40[]; +extern char debris_far_point[] __asm__("D_L07_00166E40"); extern void l07_moby_draw_callback(void) __asm__("FUN_L07_0030d420"); extern char ocean_umbris_scaled_table[] __asm__("D_L07_00208560"); extern void prepare_scaled_table_with_byte_128(void *, float) __asm__("FUN_L02_002a40d0"); @@ -27,7 +27,7 @@ void ocean_umbris_update(unsigned char *moby) { MOBY(moby)->update_dist = 0xFF; break; case OCEAN_UMBRIS_QUEUE_DRAW_OUTSIDE_CLIP_VOLUME: - if (!is_point_inside_clip_volume(D_L07_00166E40, *((int *)MOBY(moby)->pvars))) { + if (!is_point_inside_clip_volume(debris_far_point, *((int *)MOBY(moby)->pvars))) { add_draw_callback((void *)l07_moby_draw_callback, moby); } break; From 1f1a1ca4042da9ba8ab679f2ddd144a192edcffb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:01:03 +0000 Subject: [PATCH 0037/1502] decomp: clarify names in start_indexed_disc_stream a -> sector: Authoritative source assigns a from disc_table.unk1A10[i].sector or unk19F8[i].sector. Retail 0x00298c9c/0x00298cb4 loads that first pair word into a3; 0x00298cf0 moves it into a0 for the 0x00298cec call to prepare_movie_playback, whose established first parameter is sector. b -> stream_size: Authoritative source assigns b from disc_table.unk1A10[i].size or unk19F8[i].size. Retail 0x00298c94/0x00298cb0 loads the second pair word into a1, retained as the second argument at 0x00298cec. Supplied prepare_movie_playback(s32 sector, s32 size, s32 language) stores this size in D_L00_0016104C_macro. --- .../shared/streaming/start_indexed_disc_stream.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/streaming/start_indexed_disc_stream.c b/src/overlays/shared/streaming/start_indexed_disc_stream.c index 5747204717..383816bc73 100644 --- a/src/overlays/shared/streaming/start_indexed_disc_stream.c +++ b/src/overlays/shared/streaming/start_indexed_disc_stream.c @@ -11,21 +11,21 @@ void hero_respawn() __asm__("FUN_L00_00211250"); void start_indexed_disc_stream(s32 i) __asm__("FUN_L02_00298c68"); void start_indexed_disc_stream(s32 i) { - s32 a, b; + s32 sector, stream_size; struct Hero *hero_ptr; if (i < 0) return; if (pal_mode) { - a = disc_table.unk1A10[i].sector; - b = disc_table.unk1A10[i].size; + sector = disc_table.unk1A10[i].sector; + stream_size = disc_table.unk1A10[i].size; } else { - a = disc_table.unk19F8[i].sector; - b = disc_table.unk19F8[i].size; + sector = disc_table.unk19F8[i].sector; + stream_size = disc_table.unk19F8[i].size; } hero_ptr = &hero; if (hero_ptr->health.hp == 0) { hero_respawn(); } else if (hero_ptr->fall_fade_pending == 0) { - prepare_movie_playback(a, b, game_language); + prepare_movie_playback(sector, stream_size, game_language); } } From 13ba6ad365b26b54744a10373f9a48047bcddd46 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:01:03 +0000 Subject: [PATCH 0038/1502] decomp: clarify names in spawn_qwarks_starfighter_shield owner -> shielded_starfighter: The established spawn_qwarks_starfighter_shield name and class-0x160 source comment identify the shield's starfighter. Retail 0x002e8440 saves incoming a0 in s1; 0x002e8478 and 0x002e8488-0x002e848c copy its +0x10 position to the newly allocated shield moby, and 0x002e8490 stores s1 in that shield's pvars[0]. The supplied update function later tests this retained moby's removal state to fade the shield, supporting shielded_starfighter. --- src/overlays/l13/mobys/qwarks_starfighter_shield.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l13/mobys/qwarks_starfighter_shield.c b/src/overlays/l13/mobys/qwarks_starfighter_shield.c index cadb04995f..b2e3bbfc24 100644 --- a/src/overlays/l13/mobys/qwarks_starfighter_shield.c +++ b/src/overlays/l13/mobys/qwarks_starfighter_shield.c @@ -14,7 +14,7 @@ extern char *create_moby(int); char *spawn_qwarks_starfighter_shield(char *owner) __asm__("FUN_L13_002e8438"); -char *spawn_qwarks_starfighter_shield(char *owner) { +char *spawn_qwarks_starfighter_shield(char *shielded_starfighter) { char *moby = create_moby(0x160); if (moby != 0) { char *spawned_moby_vars; @@ -24,8 +24,8 @@ char *spawn_qwarks_starfighter_shield(char *owner) { spawned_moby_vars = ((char *)MOBY(moby)->pvars); moby[0x20] = 0; moby[0xBC] = 0; - qcopy(moby + 0x10, owner + 0x10); - *(char **)spawned_moby_vars = owner; + qcopy(moby + 0x10, shielded_starfighter + 0x10); + *(char **)spawned_moby_vars = shielded_starfighter; *(int *)(spawned_moby_vars + 4) = 0; MOBY(moby)->flags |= 0x200; update_entity(moby); From 29d676bc49a02ed5d6afb9246e24fc86a74886e4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:01:13 +0000 Subject: [PATCH 0039/1502] decomp: clarify names in attach_cutscene_fixed_scale_manipulator D_L01_0016CCE0 -> fx_cutscene: The authoritative source declares this exact label as MobyList. Retail 0x002fb500 forms 0x0016CCE0, 0x002fb504 reads its signed count at +0x44, and 0x002fb52c/0x002fb530 traverse its moby pointers at +0x178. At 0x002fb534-0x002fb540 each moby's +0xA6 type selects 0x398/0x1BF; 0x002fb55c attaches the shared manipulator and 0x002fb564-0x002fb56c set scale to 2.1 under cutscene_mode==2. Supplied existing_names establishes fx_cutscene for the identical assembler label; reuse that spelling exactly, preserving the MobyList type and assembler binding. --- src/overlays/shared/cutscenes/cutscene_trigger.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/cutscenes/cutscene_trigger.c b/src/overlays/shared/cutscenes/cutscene_trigger.c index a888167ac7..acca839f0d 100644 --- a/src/overlays/shared/cutscenes/cutscene_trigger.c +++ b/src/overlays/shared/cutscenes/cutscene_trigger.c @@ -60,7 +60,7 @@ extern int debug_print(void *, int, int) __asm__("FUN_001e93b0"); extern s32 D_0015ED84; extern u8 D_0015EDB0; -extern MobyList D_L01_0016CCE0; +extern MobyList fx_cutscene __asm__("D_L01_0016CCE0"); extern Effect D_L01_0017C8C0; extern char cutscene_camera_init_position_error_format[] __asm__("D_L01_0020B550"); extern int D_0015ED84; /* no foreign declaration */ @@ -74,11 +74,11 @@ void attach_cutscene_fixed_scale_manipulator(void) { s32 i; if (cutscene_mode == 2 && D_0015EDB0 != 0) { - for (i = 0; i < D_L01_0016CCE0.count; i++) { - int moby_type = D_L01_0016CCE0.list[i]->type; + for (i = 0; i < fx_cutscene.count; i++) { + int moby_type = fx_cutscene.list[i]->type; if ((moby_type == 0x398 || moby_type == 0x1BF) && D_L01_0017C8C0.active == 0) { - attach_manipulator(D_L01_0016CCE0.list[i], 0, &D_L01_0017C8C0); + attach_manipulator(fx_cutscene.list[i], 0, &D_L01_0017C8C0); D_L01_0017C8C0.z = D_L01_0017C8C0.y = D_L01_0017C8C0.x = 2.1f; } } From f31940dbb01e71799cb5088b315904c7080d2494 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:01:25 +0000 Subject: [PATCH 0040/1502] decomp: clarify names in update_gold_bolt_visuals D_L01_00161F14_gp -> l01_gold_bolt_bobbing_height_offset_gp: The f32 bound to D_L01_00161F14 is loaded at 0x003083c0 (-0x4cec(gp)), added at 0x003083cc to saved home Z from pvars+0x18, then combined with the sine term and stored to moby position.z at 0x003083dc. Original Ghidra fGpffffb314 and authoritative C both show home.z + this constant + amplitude*sin(rot.w), proving the fixed bobbing height offset. D_L01_00161F18_gp -> l01_gold_bolt_bobbing_amplitude_gp: The f32 bound to D_L01_00161F18 is loaded at 0x003083c8 (-0x4ce8(gp)) and multiplied at 0x003083d4 by fast_sin(moby->rot.w), whose call is at 0x003083b8. This product is added to home Z plus fixed offset at 0x003083d8 and stored to position.z at 0x003083dc. Original Ghidra fGpffffb318 and source confirm it scales the vertical bobbing sine, proving amplitude. D_L01_00161F2C_gp -> l01_gold_bolt_bobbing_phase_degrees_per_second_gp: The f32 bound to D_L01_00161F2C is loaded at 0x00308408 (-0x4cd4(gp)), multiplied by 0.017453292 (DEG_TO_RAD) at 0x00308420 and frame_time from D_0015ED6C at 0x00308430. fast_add_rotations at 0x0030842c adds that increment to moby->rot.w, stored at 0x00308434. That same rot.w feeds the vertical bobbing sine at 0x003083bc. Original Ghidra and source prove a degrees-per-second bobbing phase rate, rather than an X/Y/Z spin rate. --- src/overlays/shared/pickups/gold_bolt.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/shared/pickups/gold_bolt.c b/src/overlays/shared/pickups/gold_bolt.c index c23a25044d..a765f16a35 100644 --- a/src/overlays/shared/pickups/gold_bolt.c +++ b/src/overlays/shared/pickups/gold_bolt.c @@ -81,9 +81,9 @@ extern s32 current_level_index_macro __asm__("D_0015ED84"); extern s32 D_L01_0015F640; extern s32 cutscene_active __asm__("D_L01_0015F404"); extern f32 D_L01_00161F10_gp __asm__("D_L01_00161F10") __attribute__((sda)); -extern f32 D_L01_00161F14_gp __asm__("D_L01_00161F14") __attribute__((sda)); -extern f32 D_L01_00161F18_gp __asm__("D_L01_00161F18") __attribute__((sda)); -extern f32 D_L01_00161F2C_gp __asm__("D_L01_00161F2C") __attribute__((sda)); +extern f32 l01_gold_bolt_bobbing_height_offset_gp __asm__("D_L01_00161F14") __attribute__((sda)); +extern f32 l01_gold_bolt_bobbing_amplitude_gp __asm__("D_L01_00161F18") __attribute__((sda)); +extern f32 l01_gold_bolt_bobbing_phase_degrees_per_second_gp __asm__("D_L01_00161F2C") __attribute__((sda)); extern s32 D_L01_00161F50_gp __asm__("D_L01_00161F50") __attribute__((sda)); extern f32 gold_bolt_spin_x_degrees_per_second_gp __asm__("D_L01_00161F20") __attribute__((sda)); extern f32 gold_bolt_spin_y_degrees_per_second_gp __asm__("D_L01_00161F24") __attribute__((sda)); @@ -504,8 +504,8 @@ void gold_bolt_update(struct Moby *moby) { return; case GOLD_BOLT_WAIT_FOR_PICKUP: moby->scale = moby->pclass->scale * D_L01_00161F10_gp; - moby->pos.z = gold_bolt_instance_vars->home.z + D_L01_00161F14_gp + - D_L01_00161F18_gp * fast_sin(moby->rot.w); + moby->pos.z = gold_bolt_instance_vars->home.z + l01_gold_bolt_bobbing_height_offset_gp + + l01_gold_bolt_bobbing_amplitude_gp * fast_sin(moby->rot.w); moby->rot.x = fast_add_rotations( moby->rot.x, gold_bolt_spin_x_degrees_per_second_gp * 0.017453292f * frame_time_macro); moby->rot.y = fast_add_rotations( @@ -513,7 +513,7 @@ void gold_bolt_update(struct Moby *moby) { moby->rot.z = fast_add_rotations( moby->rot.z, gold_bolt_spin_z_degrees_per_second_gp * 0.017453292f * frame_time_macro); moby->rot.w = - fast_add_rotations(moby->rot.w, D_L01_00161F2C_gp * 0.017453292f * frame_time_macro); + fast_add_rotations(moby->rot.w, l01_gold_bolt_bobbing_phase_degrees_per_second_gp * 0.017453292f * frame_time_macro); FUN_L01_00308550_f(moby); if (!random_integer_below(D_L01_00161F50_gp)) { FUN_L01_003089f0_f(moby); @@ -627,13 +627,13 @@ void update_gold_bolt_visuals(struct Moby *moby) { moby->scale = moby->pclass->scale * *(float *)&D_L01_00161F10_gp; if (moby->state == 1) { bobbing_sine = fast_sin(moby->rot.w); - moby->pos.z = *(float *)(gold_bolt_visual_vars + 0x18) + *(float *)&D_L01_00161F14_gp + - *(float *)&D_L01_00161F18_gp * bobbing_sine; + moby->pos.z = *(float *)(gold_bolt_visual_vars + 0x18) + *(float *)&l01_gold_bolt_bobbing_height_offset_gp + + *(float *)&l01_gold_bolt_bobbing_amplitude_gp * bobbing_sine; moby->rot.x = fast_add_rotations(moby->rot.x, *(float *)(gold_bolt_visual_vars + 0x68)); moby->rot.y = fast_add_rotations(moby->rot.y, *(float *)(gold_bolt_visual_vars + 0x64)); updated_rotation_z = fast_add_rotations(moby->rot.z, *(float *)(gold_bolt_visual_vars + 0x60)); - k = *(float *)&D_L01_00161F2C_gp * DEG_TO_RAD * frame_time; + k = *(float *)&l01_gold_bolt_bobbing_phase_degrees_per_second_gp * DEG_TO_RAD * frame_time; moby->rot.z = updated_rotation_z; moby->rot.w = fast_add_rotations(moby->rot.w, k); } From a5d65153aa48080f30acc8e00156986f697dcc28 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:01:34 +0000 Subject: [PATCH 0041/1502] decomp: clarify names in draw_tresspasser_puzzle_textured_quads D_L02_00161B1C_gp -> l02_tresspasser_puzzle_texture_index_offset: Retail 0x002daee0 loads D_L02_00161B1C through lw a0,-0x50e4(gp); 0x002daee8 adds 0x28 and 0x002daf14 calls the established get_effect_texture accessor. Its returned texture is moved into a3 at 0x002daf1c and passed to the quad emitter at 0x002daf2c. Original Ghidra independently shows func_0x0020a180(iGpffffaf1c + 0x28). The authoritative C also uses this identical assembler-bound int in get_effect_texture(D_L02_00161B1C_gp + 0x29) in draw_tresspasser_puzzle_arrow, and initializes it from pad_puzzle_state->iEC in tresspasser_pad_update. These uses prove an additive puzzle texture-index offset, not a texture handle or packed TEX0 value. Preserve assembler label D_L02_00161B1C, int type and SDA attribute. --- src/overlays/shared/props/trespasser_pad.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/props/trespasser_pad.c b/src/overlays/shared/props/trespasser_pad.c index 1ec4e67ef4..3fcf986816 100644 --- a/src/overlays/shared/props/trespasser_pad.c +++ b/src/overlays/shared/props/trespasser_pad.c @@ -111,7 +111,7 @@ extern float frame_time_macro __asm__("D_0015ED6C") MACRO_ADDR; extern int D_L02_0017EB08_lui __asm__("D_L02_0017EB08") NOT_SDA; extern Idle D_L02_00179A10; extern int D_L02_001BADE0_2D9F08[] __asm__("D_L02_001BAAD0"); -extern int D_L02_00161B1C_gp __asm__("D_L02_00161B1C") __attribute__((sda)); +extern int l02_tresspasser_puzzle_texture_index_offset __asm__("D_L02_00161B1C") __attribute__((sda)); extern int D_L02_00161AA8_gp __asm__("D_L02_00161AA8") __attribute__((sda)); extern int D_L02_00161AA4_gp __asm__("D_L02_00161AA4") __attribute__((sda)); extern int D_L02_00161AA0_gp __asm__("D_L02_00161AA0") __attribute__((sda)); @@ -263,7 +263,7 @@ void tresspasser_pad_update(Moby *moby) { D_L02_001D33B0[3][0] = -17.0f; D_L02_001D33B0[3][1] = -17.0f; D_L02_001D33B0[0][0] = 17.0f; - D_L02_00161B1C_gp = pad_puzzle_state->iEC; + l02_tresspasser_puzzle_texture_index_offset = pad_puzzle_state->iEC; if (moby->mission != 0xFF) { if (D_L02_001BBB40_2D9F08.collected[(short)moby->save_id] != 0 || (((int *)((char *)D_0014C190_257218 + @@ -990,7 +990,7 @@ void draw_tresspasser_puzzle_arrow( xy[2] += truncate_float_to_s32(M[2][1] * 16.0f); xy[3] += truncate_float_to_s32(M[3][0] * 16.0f) << 16; xy[3] += truncate_float_to_s32(M[3][1] * 16.0f); - texture_tex0 = get_effect_texture(D_L02_00161B1C_gp + 0x29); + texture_tex0 = get_effect_texture(l02_tresspasser_puzzle_texture_index_offset + 0x29); FUN_L02_0020bc88(xy, uv, col, texture_tex0, 1); FUN_L02_0020bc88(xy, uv, col, texture_tex0, 1); } @@ -1134,7 +1134,7 @@ void draw_tresspasser_puzzle_textured_quads(void) { vertex_uvs, vertex_colors, /* Fakematch: retail uses only the low word of the texture; the cast keeps it. */ - ((int (*)(int))get_effect_texture)(D_L02_00161B1C_gp + 0x28), + ((int (*)(int))get_effect_texture)(l02_tresspasser_puzzle_texture_index_offset + 0x28), 1); } } From af9f504fb42d05acfe1e2fb279d541f0cc660a81 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:08:31 +0000 Subject: [PATCH 0042/1502] decomp: clarify names in update_listener_emitter D_L01_00167240 -> camera_pos: Supplied identical-label context establishes camera_pos for D_L01_00167240. In update_listener_emitter, retail 0031a098/0031a0a0 forms 0x00167240 in t0; 0031a0ac loads its 16-byte position vector and 0031a0b0 copies it into voice_positions + voice_slot_index*0x70. Original Ghidra copies uRam00167240/48/4c to 0x13e5e0 plus the same slot stride; current C expresses this as qcopy. Retail 0031a0d4 also reads +0x254 through this same binding to gate listener-following playback. Reuse the supplied identical assembler-label name camera_pos exactly, preserving its char array declaration and assembler identity. --- src/overlays/shared/audio/emitters/listener_emitter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/audio/emitters/listener_emitter.c b/src/overlays/shared/audio/emitters/listener_emitter.c index e6ea98fad5..f83de8e4cd 100644 --- a/src/overlays/shared/audio/emitters/listener_emitter.c +++ b/src/overlays/shared/audio/emitters/listener_emitter.c @@ -5,7 +5,7 @@ #include "rnc/audio/voice_alloc.h" #include "rnc/overlay/shared/audio/voices/play_voice.h" -extern char D_L01_00167240[]; +extern char camera_pos[] __asm__("D_L01_00167240"); void update_listener_emitter(int sound_owner) __asm__("FUN_L01_0031a078"); @@ -14,10 +14,10 @@ void update_listener_emitter(int sound_owner) { int voice_slot_index = *(int *)(sound_data + 4); char *voice_slot; int flag; - qcopy(voice_positions + voice_slot_index * 0x70, D_L01_00167240); + qcopy(voice_positions + voice_slot_index * 0x70, camera_pos); voice_slot = voice_positions - 0x90 + voice_slot_index * 0x70; flag = *(int *)(voice_slot + 0x8C) == sound_owner && *(unsigned char *)(voice_slot + 0x74) != 0; - if (*(int *)(D_L01_00167240 + 0x254) != 0) { + if (*(int *)(camera_pos + 0x254) != 0) { if (!flag) { *(int *)(sound_data + 4) = play_voice(*(int *)sound_data, 0x15, sound_owner, 0x400); } From 37fd456c7725ae9d57700b70db298e3650bb5980 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:08:31 +0000 Subject: [PATCH 0043/1502] decomp: clarify names in initialize_morphoray_private_state m -> morphoray_private_state: In source snapshot src/overlays/l14/mobys/morphoray.c SHA-256 5db553232aa2f548e7a2541317ff21c7b4ba3a3aae63885d1068365c0fa6e5db, m is a MorphorayPrivateState pointer cast from moby->pvars. Retail 0x00305a54 loads s1 from 0x78(a0), matching Ghidra iVar1 = *(int *)(param_1 + 0x78). Instructions 0x00305a58..0x00305a80 initialize four random floats at private offsets 0x20..0x2c; 0x00305ab0..0x00305abc store constants at 0x30..0x3c; 0x00305ac0..0x00305ad8 initialize scaled frame values at 0x40..0x4c; 0x00305aec..0x00305af8 initialize 0x50..0x5c. The established function and MORPHORAY_INITIALIZE caller identify this as the morphoray private-state block. --- src/overlays/l14/mobys/morphoray_pickup.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l14/mobys/morphoray_pickup.c b/src/overlays/l14/mobys/morphoray_pickup.c index f701146d9c..53df0096ea 100644 --- a/src/overlays/l14/mobys/morphoray_pickup.c +++ b/src/overlays/l14/mobys/morphoray_pickup.c @@ -127,20 +127,20 @@ typedef struct { } MorphorayPrivateState; void initialize_morphoray_private_state(struct Moby *moby) { - MorphorayPrivateState *m = (MorphorayPrivateState *)moby->pvars; + MorphorayPrivateState *morphoray_private_state = (MorphorayPrivateState *)moby->pvars; s32 i; for (i = 0; i < 4; i++) - m->r[i] = random_integer_below(0xFF); - m->a[0] = -1.0f; - m->a[1] = -2.25f; - m->a[2] = 1.25f; - m->a[3] = 2.5f; + morphoray_private_state->r[i] = random_integer_below(0xFF); + morphoray_private_state->a[0] = -1.0f; + morphoray_private_state->a[1] = -2.25f; + morphoray_private_state->a[2] = 1.25f; + morphoray_private_state->a[3] = 2.5f; for (i = 0; i < 4; i++) - m->c[i] = scale_game_frames(i * 0x40 + 0x3F); - m->x40 = 2.0f; - m->x44 = 2.5f; - m->x4c = 2.0f; - m->x48 = 2.5f; + morphoray_private_state->c[i] = scale_game_frames(i * 0x40 + 0x3F); + morphoray_private_state->x40 = 2.0f; + morphoray_private_state->x44 = 2.5f; + morphoray_private_state->x4c = 2.0f; + morphoray_private_state->x48 = 2.5f; } typedef struct { From 2b28f21758faf7416f8b4eb812dbdda842c1b0a1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:10:38 +0000 Subject: [PATCH 0044/1502] decomp: clarify names in emit_render_batches_with_pair_offset D_L11_00217758 -> l11_distance_faded_effect_uv_offsets: In the authoritative source snapshot SHA-256 0d7c556b326afeb7981aef93abe75ac981ceac17a8e8be474d136faeebab4b5d, this extern PairB array supplies &D_L11_00217758[pair_index] alongside render_batch_pair_sources[i], whose 17 entries point to f32 distance_faded_effect_batch_uvs_N[][2] MeshUv streams. Retail 0x0031e6e4 loads base 0x00217758, 0x0031e6ec multiplies pair_index by eight, and 0x0031e718 passes the selected pair as a3 to 0x002739c0 at 0x0031e720. Checked helper instructions 0x002739c0..0x002739e0 load the eight-byte pair into vf11 and repeat its two components; 0x00273a08/0x00273a20 add it to source pairs and 0x00273a0c/0x00273a28 store the offset UV stream at 0x00217770. The assigned function then supplies that stream to the render call at 0x0031e744 for each batch. The same source initializes both components of entries 0..2 to zero. This proves a level-11 distance-faded-effect UV offset array without changing its declared integer-pair storage. --- src/overlays/l11/mobys/distance_faded_scroll_effect.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l11/mobys/distance_faded_scroll_effect.c b/src/overlays/l11/mobys/distance_faded_scroll_effect.c index aa598bc67c..de44710622 100644 --- a/src/overlays/l11/mobys/distance_faded_scroll_effect.c +++ b/src/overlays/l11/mobys/distance_faded_scroll_effect.c @@ -29,7 +29,7 @@ typedef struct { int a, b; } PairB; -extern PairB D_L11_00217758[]; +extern PairB l11_distance_faded_effect_uv_offsets[] __asm__("D_L11_00217758"); extern PairB D_L11_00162618[] MACRO_ADDR; /* The 17-batch set (emit_render_batches_with_pair_offset, loop of 0x11) and the 9-batch @@ -5887,7 +5887,7 @@ void emit_render_batches_with_pair_offset(int pair_index) { FUN_L08_00258090(D_L11_00217770, render_batch_pair_sources[i], distance_faded_effect_batch_vertex_counts[i], - &D_L11_00217758[pair_index]); + &l11_distance_faded_effect_uv_offsets[pair_index]); FUN_L00_001fde98(distance_faded_effect_batch_vertex_counts[i], render_batch_triplet_sources[i], distance_faded_effect_batch_color_tables[i], @@ -6046,8 +6046,8 @@ void distance_faded_effect_update(struct Moby *moby) { } moby->state = 1; for (i = 0; i < 3; i++) { - D_L11_00217758[i].a = 0; - D_L11_00217758[i].b = 0; + l11_distance_faded_effect_uv_offsets[i].a = 0; + l11_distance_faded_effect_uv_offsets[i].b = 0; distance_faded_effect_sine_phases[0] = 0; distance_faded_effect_sine_phases[1] = 0; } From 8257c751207ba7c1b21325cbbeb8ea3a9d2b91bf Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:10:48 +0000 Subject: [PATCH 0045/1502] decomp: clarify names in update_blarg_heavy_interceptor_patrol_aim_point D_L14_001613A0_gp -> l14_blarg_heavy_interceptor_path_easing_error_gain: Retail 0x002ae73c/0x002ae75c/0x002ae778 loads gp-0x5860 (source assembler binding D_L14_001613A0) into f13 for easing calls at 0x002ae74c/0x002ae768/0x002ae784. Source supplies it after sampled XYZ targets for current aim coordinates +0x170/+0x174/+0x178 and velocities +0x180/+0x184/+0x188. Checked helper 0x00263c40 passes f13 unchanged while replacing f12 with target-current at 0x00263c70..0x00263c78, then adds updated velocity to current. This matches supplied vendor_spring's error_gain argument. The same global eases physical patrol path position and rejoin aim position in the owned source, establishing a shared path easing error gain, rather than an aim-only constant. D_L14_001613A4_gp -> l14_blarg_heavy_interceptor_path_easing_damping_coefficient: Retail 0x002ae744/0x002ae764/0x002ae780 loads gp-0x585c (source assembler binding D_L14_001613A4) into f14 for the three XYZ easing calls, immediately after the f13 error gain. Checked helper 0x00263c40 forwards f14 unchanged with target-minus-current to velocity update at 0x00263c74, then adds velocity to current at 0x00263c7c..0x00263c8c. Its argument flow and remaining-error snap test match supplied vendor_spring, where this coefficient is damping_coefficient. Owned source also uses this binding with physical path positions and fixed 0.005f gain during rejoin, proving shared path easing damping rather than an aim-only role. --- .../l14/mobys/blarg_heavy_interceptor.c | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/overlays/l14/mobys/blarg_heavy_interceptor.c b/src/overlays/l14/mobys/blarg_heavy_interceptor.c index b1791248d3..9c39c5eaa1 100644 --- a/src/overlays/l14/mobys/blarg_heavy_interceptor.c +++ b/src/overlays/l14/mobys/blarg_heavy_interceptor.c @@ -542,19 +542,19 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { vector_scratch[0], &moby_vars->unk190[1], 0.005f, - D_L14_001613A4_gp, + l14_blarg_heavy_interceptor_path_easing_damping_coefficient, 0.0f); ease_c618(&moby->pos.y, vector_scratch[1], &moby_vars->unk190[2], 0.005f, - D_L14_001613A4_gp, + l14_blarg_heavy_interceptor_path_easing_damping_coefficient, 0.0f); ease_c618(&moby->pos.z, vector_scratch[2], &moby_vars->unk190[3], 0.005f, - D_L14_001613A4_gp, + l14_blarg_heavy_interceptor_path_easing_damping_coefficient, 0.0f); update_blarg_heavy_interceptor_aim_transforms(moby, 0); if (fast_vec_dist(&moby->pos, vector_scratch) < 0.5f) { @@ -569,20 +569,20 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { ease_c618(moby_vars->unk170, vector_scratch[0], moby_vars->unk180, - D_L14_001613A0_gp, - D_L14_001613A4_gp, + l14_blarg_heavy_interceptor_path_easing_error_gain, + l14_blarg_heavy_interceptor_path_easing_damping_coefficient, 0.0f); ease_c618(&moby_vars->unk170[1], vector_scratch[1], &moby_vars->unk180[1], - D_L14_001613A0_gp, - D_L14_001613A4_gp, + l14_blarg_heavy_interceptor_path_easing_error_gain, + l14_blarg_heavy_interceptor_path_easing_damping_coefficient, 0.0f); ease_c618(&moby_vars->unk170[2], vector_scratch[2], &moby_vars->unk180[2], - D_L14_001613A0_gp, - D_L14_001613A4_gp, + l14_blarg_heavy_interceptor_path_easing_error_gain, + l14_blarg_heavy_interceptor_path_easing_damping_coefficient, 0.0f); break; } @@ -1532,20 +1532,20 @@ void update_blarg_heavy_interceptor_patrol_aim_point(struct Moby *moby) { FUN_L00_0025b8c0_c(interceptor_instance_vars->unk170, interceptor_instance_vars->unk180, path_target_position[0], - *(float *)&D_L14_001613A0_gp, - *(float *)&D_L14_001613A4_gp, + *(float *)&l14_blarg_heavy_interceptor_path_easing_error_gain, + *(float *)&l14_blarg_heavy_interceptor_path_easing_damping_coefficient, 0.0f); FUN_L00_0025b8c0_c(&interceptor_instance_vars->unk170[1], &interceptor_instance_vars->unk180[1], path_target_position[1], - *(float *)&D_L14_001613A0_gp, - *(float *)&D_L14_001613A4_gp, + *(float *)&l14_blarg_heavy_interceptor_path_easing_error_gain, + *(float *)&l14_blarg_heavy_interceptor_path_easing_damping_coefficient, 0.0f); FUN_L00_0025b8c0_c(&interceptor_instance_vars->unk170[2], &interceptor_instance_vars->unk180[2], path_target_position[2], - *(float *)&D_L14_001613A0_gp, - *(float *)&D_L14_001613A4_gp, + *(float *)&l14_blarg_heavy_interceptor_path_easing_error_gain, + *(float *)&l14_blarg_heavy_interceptor_path_easing_damping_coefficient, 0.0f); if (interceptor_instance_vars->rejoin_path_loop == 0) { if (r != 0) { @@ -1588,20 +1588,20 @@ void update_blarg_heavy_interceptor_patrol_path_position(struct Moby *moby) { FUN_L00_0025b8c0_c(&moby->pos.x, &heavy_interceptor_vars->unk190[1], destination_path_target_position[0], - *(float *)&D_L14_001613A0_gp, - *(float *)&D_L14_001613A4_gp, + *(float *)&l14_blarg_heavy_interceptor_path_easing_error_gain, + *(float *)&l14_blarg_heavy_interceptor_path_easing_damping_coefficient, 0.0f); FUN_L00_0025b8c0_c(&moby->pos.y, &heavy_interceptor_vars->unk190[2], destination_path_target_position[1], - *(float *)&D_L14_001613A0_gp, - *(float *)&D_L14_001613A4_gp, + *(float *)&l14_blarg_heavy_interceptor_path_easing_error_gain, + *(float *)&l14_blarg_heavy_interceptor_path_easing_damping_coefficient, 0.0f); FUN_L00_0025b8c0_c(&moby->pos.z, &heavy_interceptor_vars->unk190[3], destination_path_target_position[2], - *(float *)&D_L14_001613A0_gp, - *(float *)&D_L14_001613A4_gp, + *(float *)&l14_blarg_heavy_interceptor_path_easing_error_gain, + *(float *)&l14_blarg_heavy_interceptor_path_easing_damping_coefficient, 0.0f); } From 955cf78b60fbffa84f7a1d47306c2c39b595862d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:10:56 +0000 Subject: [PATCH 0046/1502] decomp: clarify names in activate_listed_spark_emitters D_L06_0015FFD8 -> level_mobys_q: Authoritative spark_emitter.c (SHA-256 132ac53814c2ed674069cbf9929a791d3e4a23e00589c8eb5d7606d1de0ede9e) declares extern char *D_L06_0015FFD8 and resolves moby = D_L06_0015FFD8 + ((*(unsigned short *)moby_index_entry & 0x7FFF) << 8). Original Ghidra agrees: iRam0015ffd8 + (*puVar4 & 0x7fff) * 0x100. Retail 0x00309294-0x003092A4 loads the pointer from 0x0015FFD8, masks and scales the index, and adds it to produce s0; 0x003092A8 and 0x003092B4 read the resulting moby's class +0xA6 and state +0x20, while 0x003092C0 and 0x00309300 access position +0x10 and private data +0x78. This proves the moby-array pointer role. level_mobys_q is the supplied existing name for this exact assembler label. --- src/overlays/l06/mobys/spark_emitter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l06/mobys/spark_emitter.c b/src/overlays/l06/mobys/spark_emitter.c index a878dc4d84..db42e6da7e 100644 --- a/src/overlays/l06/mobys/spark_emitter.c +++ b/src/overlays/l06/mobys/spark_emitter.c @@ -247,7 +247,7 @@ void spark_emitter_update(struct Moby *emitter) { /* finds the mobys of type 0x5E8 in state 1 in a level list and starts those within range */ /* Ported from rac1-decomp (src/overlays/l06_blarg/vendor_002FE5D0.c: func_L06_0030A680), where it is exact; names translated to the US level program. */ -extern char *D_L06_0015FFD8; +extern char *level_mobys_q __asm__("D_L06_0015FFD8"); extern short *D_L06_001ABFC0[]; void activate_listed_spark_emitters(int moby_list_index) __asm__("FUN_L06_00309240"); @@ -260,7 +260,7 @@ void activate_listed_spark_emitters(int moby_list_index) { if (D_L06_001ABFC0[moby_list_index] != 0) { moby_index_entry = D_L06_001ABFC0[moby_list_index]; do { - moby = D_L06_0015FFD8 + ((*(unsigned short *)moby_index_entry & 0x7FFF) << 8); + moby = level_mobys_q + ((*(unsigned short *)moby_index_entry & 0x7FFF) << 8); if (MOBY(moby)->oclass == 0x5E8 && (unsigned char)moby[0x20] == 1) { qcopy(position_test_vector, moby + 0x10); position_test_vector[3] = 0.25f; From e003d638428d789326448fc32ebafe212ab5afb9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:12:32 +0000 Subject: [PATCH 0047/1502] decomp: clarify names in path_sample_at_distance dist -> path_distance: Retail 0x0026236c saves this float in f21; 0x00262378 divides it by spacing in f20 before truncation at 0x00262398 to select the path segment. At 0x002623f4-0x00262400 it subtracts segment_index * spacing to produce the within-segment distance. The source path_sample_at_distance and supplied advancing-particle caller establish distance along the path, rather than a generic distance. out -> sampled_position: Retail 0x0026239c saves the fourth pointer in s1. Endpoint branches copy path->points[*seg_out] into it at 0x002623e0-0x002623e8; the interior branch writes the segment-scaled vector plus the current path point at 0x00262438-0x00262458. The supplied update_timed_sphere_probed_particle caller passes particle_position as this argument, proving it receives the sampled path position. tmp -> sampling_intermediate: The Vec4 local maps to the stack vector at sp: 0x002623f8 and 0x00262418 pass it as the destination for next path point minus current point, then 0x00262420-0x0026242c copy it into the output. At 0x0026243c-0x00262450 the same stack vector receives scaled displacement plus the current path point, and 0x00262454-0x00262458 copy that final position to output. It is the reused vector intermediate for path sampling, not exclusively a direction or position. --- .../mobys/test_path_segment_strict_crossing.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/shared/mobys/test_path_segment_strict_crossing.c b/src/overlays/shared/mobys/test_path_segment_strict_crossing.c index fc08ff4afb..00c2491ac8 100644 --- a/src/overlays/shared/mobys/test_path_segment_strict_crossing.c +++ b/src/overlays/shared/mobys/test_path_segment_strict_crossing.c @@ -345,30 +345,30 @@ void path_sample_at_distance(PointPath *path, f32 spacing) __asm__("FUN_L00_00262360"); void path_sample_at_distance( - PointPath *path, s32 *seg_out, f32 *along, Vec4 *out, f32 dist, f32 spacing) { - Vec4 tmp; + PointPath *path, s32 *seg_out, f32 *along, Vec4 *sampled_position, f32 path_distance, f32 spacing) { + Vec4 sampling_intermediate; s32 seg; - seg = truncate_float_to_s32(dist / spacing); + seg = truncate_float_to_s32(path_distance / spacing); *seg_out = seg; if (seg >= path->count - 1) { *seg_out = path->count - 1; *along = 0.0f; - out->q = (path->points + *seg_out)->q; + sampled_position->q = (path->points + *seg_out)->q; return; } if (seg < 0) { *seg_out = 0; *along = 0.0f; - out->q = (path->points + *seg_out)->q; + sampled_position->q = (path->points + *seg_out)->q; return; } - *along = dist - convert_integer_to_float(seg) * spacing; - fast_vec_sub(&tmp, &path->points[*seg_out + 1], &path->points[*seg_out]); - out->q = tmp.q; - fast_vec_normalize(out, out, *along); - fast_vec_add(&tmp, out, &path->points[*seg_out]); - out->q = tmp.q; + *along = path_distance - convert_integer_to_float(seg) * spacing; + fast_vec_sub(&sampling_intermediate, &path->points[*seg_out + 1], &path->points[*seg_out]); + sampled_position->q = sampling_intermediate.q; + fast_vec_normalize(sampled_position, sampled_position, *along); + fast_vec_add(&sampling_intermediate, sampled_position, &path->points[*seg_out]); + sampled_position->q = sampling_intermediate.q; } /* Ported from rac1-decomp (src/overlays/shared/mobyutil_00261B00.c: func_L00_002634F8), where it is exact; names translated to the US level program. */ From a1dda96b51ef5df17b8a8ea558dc653d0a5c6afc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:12:33 +0000 Subject: [PATCH 0048/1502] decomp: clarify names in score_gadgebot_target_candidate b -> candidate_moby: Retail 0x002f2154 saves a1 (Ghidra param_2, source b) in s2. At 0x002f216c s2+0x10 supplies the second position to vector_distance_xy; 0x002f2184-0x002f21d0 subtract the scoring moby's XY from this candidate's XY, and 0x002f21f4 reads its +0x31 flag. The supplied assign_gadgebot_attack_targets caller passes candidate as argument 1 and stores the returned score alongside that same candidate in CANDIDATES. r -> candidate_score: Source r corresponds to retail f21 / Ghidra fVar1: 0x002f2180 initializes it from vector_distance_xy, 0x002f21f0-0x002f2204 add heading differences weighted by 10 and 3, 0x002f2208 adds the candidate flag penalty, and 0x002f2224 adds 100 for target_kind 9. It is returned in f0 at 0x002f2214 or 0x002f2228. The caller compares this returned score with CANDIDATE_SCORES and inserts candidates in ascending ranking order, proving an accumulated candidate score rather than merely distance. --- src/overlays/shared/enemies/gadgebot.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/overlays/shared/enemies/gadgebot.c b/src/overlays/shared/enemies/gadgebot.c index 21d262c97f..e60027de6e 100644 --- a/src/overlays/shared/enemies/gadgebot.c +++ b/src/overlays/shared/enemies/gadgebot.c @@ -1150,25 +1150,25 @@ float score_gadgebot_target_candidate(char *moby, char *b, int target_kind) __asm__("FUN_L06_002f2148"); -float score_gadgebot_target_candidate(char *moby, char *b, int target_kind) { - float r = vector_distance_xy(&MOBY(moby)->pos, b + 0x10); +float score_gadgebot_target_candidate(char *moby, char *candidate_moby, int target_kind) { + float candidate_score = vector_distance_xy(&MOBY(moby)->pos, candidate_moby + 0x10); float t = fast_difference_between_rotations(l06_camera.yaw, - fast_arc_tan(*(float *)(b + 0x10) - MOBY(moby)->pos.x, - *(float *)(b + 0x14) - MOBY(moby)->pos.y)); + fast_arc_tan(*(float *)(candidate_moby + 0x10) - MOBY(moby)->pos.x, + *(float *)(candidate_moby + 0x14) - MOBY(moby)->pos.y)); float u = fast_difference_between_rotations(MOBY(moby)->rot.z, - fast_arc_tan(*(float *)(b + 0x10) - MOBY(moby)->pos.x, - *(float *)(b + 0x14) - MOBY(moby)->pos.y)); - r = r + u * 10.0f; - r = r + t * 3.0f; - if (((unsigned char *)b)[0x31] == 0) { - r += 10.0f; + fast_arc_tan(*(float *)(candidate_moby + 0x10) - MOBY(moby)->pos.x, + *(float *)(candidate_moby + 0x14) - MOBY(moby)->pos.y)); + candidate_score = candidate_score + u * 10.0f; + candidate_score = candidate_score + t * 3.0f; + if (((unsigned char *)candidate_moby)[0x31] == 0) { + candidate_score += 10.0f; } if (target_kind == 9) { - r += 100.0f; + candidate_score += 100.0f; } - return r; + return candidate_score; } /* Shared level-06/10 routine: gathers candidate mobies, scores them against the target list and writes the slot tables. */ From b84cdb6dea77bc5a11e7144867b447407dfd0a46 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:12:33 +0000 Subject: [PATCH 0049/1502] decomp: clarify names in check_descriptor_hero_trigger e -> trigger_descriptor_record: In the authoritative source snapshot src/overlays/shared/camera/path_flythrough_camera.c (SHA-256 093a7325c92e9e3affb8d5d50e77111bb81bdd08905c089f20f8d11504017e54), e is an unsigned char pointer loaded from l10_descriptor_table + *(short *)(moby+0x84)*32 + 0x1C. Retail 0x002f5a88-0x002f5a94 performs that exact lookup into a0 (Ghidra iVar1). Reads at 0x002f5a98, 0x002f5aa0, 0x002f5abc and 0x002f5ad8 obtain the volume, cylinder, sphere and XY-path indices used to test hero.motion.pos; 0x002f5b2c and 0x002f5b38 read its fallback flags +0x38/+0x39. Thus it is the descriptor record consumed by check_descriptor_hero_trigger, consistent with the same lookup named descriptor_record in evaluate_descriptor_eligibility. --- .../shared/camera/path_flythrough_camera.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/shared/camera/path_flythrough_camera.c b/src/overlays/shared/camera/path_flythrough_camera.c index 50740f6fc9..1bf2b5b760 100644 --- a/src/overlays/shared/camera/path_flythrough_camera.c +++ b/src/overlays/shared/camera/path_flythrough_camera.c @@ -34,24 +34,24 @@ extern int point_in_path_xy(float *, float *, int) __asm__("FUN_L00_00259740"); int check_descriptor_hero_trigger(char *moby) __asm__("FUN_L10_002f5a78"); int check_descriptor_hero_trigger(char *moby) { - unsigned char *e = *(unsigned char **)(l10_descriptor_table + *(short *)(moby + 0x84) * 32 + 0x1C); + unsigned char *trigger_descriptor_record = *(unsigned char **)(l10_descriptor_table + *(short *)(moby + 0x84) * 32 + 0x1C); - if (*(int *)(e + 0x0C) >= 0) { - if (is_point_inside_clip_volume(&hero.motion.pos, *(int *)(e + 0x0C))) + if (*(int *)(trigger_descriptor_record + 0x0C) >= 0) { + if (is_point_inside_clip_volume(&hero.motion.pos, *(int *)(trigger_descriptor_record + 0x0C))) return 1; - } else if (*(int *)(e + 0x10) >= 0) { - if (test_point_in_transformed_unit_cylinder(&hero.motion.pos, *(int *)(e + 0x10))) + } else if (*(int *)(trigger_descriptor_record + 0x10) >= 0) { + if (test_point_in_transformed_unit_cylinder(&hero.motion.pos, *(int *)(trigger_descriptor_record + 0x10))) return 1; - } else if (*(int *)(e + 0x08) >= 0) { - if (test_point_in_transformed_unit_sphere((float *)(&hero.motion.pos), *(int *)(e + 0x08))) + } else if (*(int *)(trigger_descriptor_record + 0x08) >= 0) { + if (test_point_in_transformed_unit_sphere((float *)(&hero.motion.pos), *(int *)(trigger_descriptor_record + 0x08))) return 1; - } else if (*(int *)(e + 0x14) >= 0) { - int i = *(int *)(e + 0x14); + } else if (*(int *)(trigger_descriptor_record + 0x14) >= 0) { + int i = *(int *)(trigger_descriptor_record + 0x14); if (point_in_path_xy((float *)(&hero.motion.pos), (float *)(((char *)l10_paths[i]) + 0x10), *(int *)l10_paths[i])) return 1; - } else if (e[0x38] != 0 && e[0x39] == 0) { + } else if (trigger_descriptor_record[0x38] != 0 && trigger_descriptor_record[0x39] == 0) { return 1; } return 0; From ff491125f655bca6eac3bfd48d463d10bde5606a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:12:42 +0000 Subject: [PATCH 0050/1502] decomp: clarify names in update_moby_target_heading_and_conditional_movement D_L11_001622FC_gp -> l11_puffoid_horizontal_speed_limit: Authoritative puffoid.c SHA-256 97bf3925dd40b63e7dd9de6d714766c1a22e0e40cf303ec90109a162187b74da declares float bound to D_L11_001622FC. Retail 00316028-00316034 loads frame_time and this global, multiplies them and stores pvars+1A4. At 00316060/00316070 pvars+180 is passed as movement_control to placed helper 0027e9f8, so +1A4 is control+24. Checked helper 0027ea5c/0027ea6c loads control+24 into f21 with factor 1.0 supplied by root; 0027eacc-0027eaf4 clamps control+10 between negative and positive f21. Instructions 0027eb1c-0027eb40 multiply cosine/sine of heading by control+10 to construct XY movement. Supplied spring_turn.c context agrees. The other source consumer update_puffoid_damage_and_path_goal also writes this same global times frame_time to pvars+1A4. Thus it is the puffoid horizontal speed limit before frame scaling, not merely a compiler GP access alias. --- src/overlays/l11/mobys/puffoid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l11/mobys/puffoid.c b/src/overlays/l11/mobys/puffoid.c index d28af0c774..f8a65b9377 100644 --- a/src/overlays/l11/mobys/puffoid.c +++ b/src/overlays/l11/mobys/puffoid.c @@ -673,7 +673,7 @@ extern float puffoid_death_knockback_vertical_scale_gp __asm__("D_L11_001622DC") #include "rnc/overlay/l11/mobys/puffoid_data/update_puffoid_damage_and_path_goal.h" -extern float D_L11_001622FC_gp __asm__("D_L11_001622FC") __attribute__((sda)); +extern float l11_puffoid_horizontal_speed_limit __asm__("D_L11_001622FC") __attribute__((sda)); /* Private variables of the moby FUN_L11_00315968 updates (only the fields it uses). */ struct L11PatrolVars { @@ -761,7 +761,7 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { char *path; moby->scale = moby->pclass->scale * D_L11_001622CC; - patrol_vars->unk1A4 = D_L11_001622FC_gp * frame_time; + patrol_vars->unk1A4 = l11_puffoid_horizontal_speed_limit * frame_time; if (patrol_vars->carrier != -1 && moby->state != 0xB && moby->state != 9 && moby->state != 0x12 && moby->state != 0x11 && moby->state != 0 && moby->state != 0xC && moby->state != 0xD) { @@ -927,7 +927,7 @@ void update_moby_target_heading_and_conditional_movement(char *moby, float *targ target_heading_or_record_value = compute_interpolated_record_value(moby); if (MOBY(moby)->seq == MOBY(moby)->prev_seq && 8.0f < target_heading_or_record_value && target_heading_or_record_value < 22.0f) { - *(float *)(moby_vars + 0x1A4) = D_L11_001622FC_gp * frame_time; + *(float *)(moby_vars + 0x1A4) = l11_puffoid_horizontal_speed_limit * frame_time; planar_heading_vector[0] = fast_cos(MOBY(moby)->rot.z) * 2.0f; planar_heading_vector[1] = fast_sin(MOBY(moby)->rot.z) * 2.0f; *(int *)&planar_heading_vector[2] = 0; From e1f25ce9947d2554e8b7e0343381f71f076ff2bd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:12:42 +0000 Subject: [PATCH 0051/1502] decomp: clarify names in spawn_nearby_effect f -> hit_damage: In the authoritative spawn_nearby_effect C, f is compared with existing_hit->damage and assigned to hit_record->damage. Retail f12 is compared against the linked record's +0x2C float by lwc1/c.lt.S at 0x00259c38-0x00259c44, returning when the incoming damage is lower; swc1 f12,0x2c(s1) at 0x00259c64 stores it in the new hit record. Original Ghidra param_1 likewise supplies DAT_0017812c plus the selected record offset. This proves the incoming hit_damage role. --- src/overlays/shared/mobys/find_moby_hit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/mobys/find_moby_hit.c b/src/overlays/shared/mobys/find_moby_hit.c index a856079b1d..1f55da00c2 100644 --- a/src/overlays/shared/mobys/find_moby_hit.c +++ b/src/overlays/shared/mobys/find_moby_hit.c @@ -231,18 +231,18 @@ void spawn_nearby_effect(unsigned char *owner_moby, u128 *hit_vector_source, u128 *direction_vector, - float f) { + float hit_damage) { int i = D_L00_00173E40.idx; MobyHit *hit_record; if (MOBY(owner_moby)->hit_slot != 0xFF) { MobyHit *existing_hit = &moby_hits[MOBY(owner_moby)->hit_slot]; - if (existing_hit->owner == owner_moby && f < existing_hit->damage) + if (existing_hit->owner == owner_moby && hit_damage < existing_hit->damage) return; } hit_record = &moby_hits[i]; hit_record->source_moby = (u8 *)x; hit_record->flags = y; - hit_record->damage = f; + hit_record->damage = hit_damage; hit_record->owner = owner_moby; hit_record->unk38 = 0; if (fast_vec_length(direction_vector) > 0.0001f) { From b2d7a8860c957b0580161d4e9e744c3dac31dad8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:12:51 +0000 Subject: [PATCH 0052/1502] decomp: clarify names in spawn_fading_ring_effect D_L07_00166E40 -> debris_far_point: Retail 0030dc38/0030dc40 forms level-07 address 0x00166e40, and 0030dc48 passes it in a1 to the distance call at 0030dc6c with spawned moby+0x10 in a0. Original Ghidra shows the same reference-position operand; authoritative C calls vector_distance_xy and derives distance-response stores from it. Reuse debris_far_point exactly as supplied in existing_names for this identical assembler label, preserving its extern char array declaration and assembler identity. b -> texture_index: Retail 0030dbc4 saves a2 in s3 and 0030dc5c stores it at spawned pvars+0x18; original Ghidra puVar1[6]=param_8 agrees. Authoritative draw_fading_ring_effect passes that exact +0x18 integer to get_effect_texture to populate the ring draw packet texture at +0x78, proving the texture-selection index. f0 -> initial_radius: Retail 0030dbec preserves f12 in f21; 0030dc58 and 0030dc60 store it at pvars+8 and +0, matching original Ghidra puVar1[2]=param_1 and *puVar1=param_1. Authoritative update_fading_ring_effect advances +8 by spawn_speed and computes radius_progress=(+8 - +0)/(+4 - +0); draw uses +8 as radius. Thus +0 is the initial radius and +8 its initial current copy. f1 -> terminal_radius: Retail 0030dbe4 preserves f13 in f22 and 0030dc44 writes pvars+4, matching original Ghidra puVar1[1]=param_2. In authoritative update_fading_ring_effect, radius_progress=(current radius at +8 - initial at +0)/(this +4 endpoint - initial at +0), and progress>=1 removes the ring. This argument is therefore the terminal radius. f2 -> ring_height: Retail 0030dbdc saves f14 into f23 and 0030dc4c stores it at pvars+0x10, matching original Ghidra puVar1[4]=param_3. Authoritative draw_fading_ring_effect multiplies this field by (1-band*0.5) and adds it to moby pos.z for the upper ring vertices while lower vertices use pos.z; register_fading_ring_hit also uses 0.3 times this field as a height allowance. It controls ring height. --- src/overlays/l07/mobys/fading_ring_effect.c | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l07/mobys/fading_ring_effect.c b/src/overlays/l07/mobys/fading_ring_effect.c index 1e600f948e..851655943d 100644 --- a/src/overlays/l07/mobys/fading_ring_effect.c +++ b/src/overlays/l07/mobys/fading_ring_effect.c @@ -14,7 +14,7 @@ extern char *create_moby(int) __asm__("FUN_0020c4f8"); extern void update_entity(void *) __asm__("FUN_L00_00250df8"); /* Ported from rac1-decomp (src/overlays/l07_umbris/vendor_002CE470.c: func_L07_0030E820), where it is exact; names translated to the US level program. */ -extern char D_L07_00166E40[]; +extern char debris_far_point[] __asm__("D_L07_00166E40"); /* Slows and steers a moby toward another when it is below and close in height. */ /* Ported from rac1-decomp (src/overlays/l07_umbris/vendor_002CE470.c: func_L07_0030F4C0), where it is exact; names translated to the US level program. */ @@ -59,10 +59,10 @@ extern void draw_geometry_quad(void *, int, int) __asm__("func_001F7D30"); unsigned char *spawn_fading_ring_effect(int spawning_moby, void *spawn_position, - int b, - float f0, - float f1, - float f2, + int texture_index, + float initial_radius, + float terminal_radius, + float ring_height, float spawn_speed, float f4) { @@ -77,15 +77,15 @@ unsigned char *spawn_fading_ring_effect(int spawning_moby, MOBY(moby)->visible = 1; qcopy(moby + 0x10, spawn_position); *(int *)(spawned_moby_vars + 0x14) = spawning_moby; - *(float *)(spawned_moby_vars + 4) = f1; - *(float *)(spawned_moby_vars + 0x10) = f2; + *(float *)(spawned_moby_vars + 4) = terminal_radius; + *(float *)(spawned_moby_vars + 0x10) = ring_height; *(float *)(spawned_moby_vars + 0xC) = spawn_speed; - *(float *)spawned_moby_vars = f0; - *(float *)(spawned_moby_vars + 8) = f0; - *(int *)(spawned_moby_vars + 0x18) = b; + *(float *)spawned_moby_vars = initial_radius; + *(float *)(spawned_moby_vars + 8) = initial_radius; + *(int *)(spawned_moby_vars + 0x18) = texture_index; *(float *)(spawned_moby_vars + 0x1C) = f4; MOBY(moby)->flags |= 0x200; - distance_reference_position = D_L07_00166E40; + distance_reference_position = debris_far_point; distance_response_state = distance_reference_position - 0x140; *(float *)(distance_response_state + 0x160) = 0.3f - vector_distance_xy(moby + 0x10, distance_reference_position) / 100.0f; From 8ba1f675da0db3b4c71fc635ae50d0a2dc87389c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:13:00 +0000 Subject: [PATCH 0053/1502] decomp: clarify names in update_metropolis_train_idle_motion D_L03_001E2410 -> l03_train_engine_no_cars_warning_format: Checked level-03 bytes at 0x001e2410 decode to 'train engine has no cars! Deleting moby instance %d\n'. Retail 0x00292d68-70 tests locomotive pvars +0xA0 against -1; on that no-car branch, 0x00292e2c loads the diagnostic instance from +0xB8, 0x00292e30-38 passes 0x001e2410 as the debug-print format, and 0x00292e3c-40 removes the locomotive. The authoritative source declares this object as extern char[] and also uses it in the same no-car branch of update_metropolis_train_motion. The l03 qualifier preserves overlay ownership; retain assembler identity D_L03_001E2410. --- src/overlays/l03/mobys/metropolis_train_locomotive.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l03/mobys/metropolis_train_locomotive.c b/src/overlays/l03/mobys/metropolis_train_locomotive.c index 1b9ea52cf2..20cc1d1ed6 100644 --- a/src/overlays/l03/mobys/metropolis_train_locomotive.c +++ b/src/overlays/l03/mobys/metropolis_train_locomotive.c @@ -101,7 +101,7 @@ void place_metropolis_train(struct Moby *moby, float *pos, float heading) { } extern char *D_L03_0015FFD8_292890 __asm__("D_L03_0015FFD8"); -extern char D_L03_001E2410[]; +extern char l03_train_engine_no_cars_warning_format[] __asm__("D_L03_001E2410"); extern float spring_turn(float *vel, float cur, float target, float k, float d, float max) __asm__("FUN_L00_00258110"); extern void debug_print(void *, int) __asm__("FUN_001e93b0"); extern void gunship_update(char *) __asm__("FUN_L01_002f5168"); @@ -240,7 +240,7 @@ void update_metropolis_train_motion(char *moby) { fast_vec_sub(delta, moby + 0x10, old_pos); update_entity_matrix(locomotive_state->motion, delta, old_rot, moby + 0x40); } else { - debug_print(D_L03_001E2410, locomotive_state->iB8); + debug_print(l03_train_engine_no_cars_warning_format, locomotive_state->iB8); mark_moby_for_removal(moby); return; } @@ -290,7 +290,7 @@ void update_metropolis_train_idle_motion(struct Moby *moby) { fast_vec_sub(dp, &moby->pos, old_pos); update_entity_matrix(motion, dp, old_rot, &moby->rot); } else { - debug_print(D_L03_001E2410, *(int *)(locomotive_pvars + 0xB8)); + debug_print(l03_train_engine_no_cars_warning_format, *(int *)(locomotive_pvars + 0xB8)); mark_moby_for_removal(moby); return; } From 27bf71ca98c0a52584e2bec9dcb163150a729978 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:13:10 +0000 Subject: [PATCH 0054/1502] decomp: clarify names in stop_suck_cannon_suction_effect D_L00_001E5F30 -> l00_suck_beam_previous_segment_positions: Retail 0x002df0dc loads the particle segment index; 0x002df0e0 selects 0x001e5f30, 0x002df0e4 multiplies the index by 16, and 0x002df0ec/0x002df0f0 subtract indexed 0x001e5f40 from indexed 0x001e5f30. Since these bases differ by one 16-byte position, the latter operand supplies the preceding spatial segment endpoint. The length and scaling at 0x002df0f4-0x002df110 and addition at 0x002df124 locate a point along that segment. Source suck_beam_build writes position i at 0x001e5f40+i*16 by adding the step to 0x001e5f30+i*16 for i=1..9; suck_beam_update explicitly binds that indexed address as previous and updates anchor from previous+motion. This proves preceding beam segment positions via a biased base, rather than previous-frame storage. --- src/overlays/shared/weapons/suckcannon.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/shared/weapons/suckcannon.c b/src/overlays/shared/weapons/suckcannon.c index cecdd74703..321ccf5a45 100644 --- a/src/overlays/shared/weapons/suckcannon.c +++ b/src/overlays/shared/weapons/suckcannon.c @@ -604,7 +604,7 @@ extern E04 D_L00_001E4C80[]; extern char D_L00_00161B60[] MACRO_ADDR; extern char D_L00_00161B70[] MACRO_ADDR; extern char D_L00_00166FD0[]; -extern char D_L00_001E5F30[]; +extern char l00_suck_beam_previous_segment_positions[] __asm__("D_L00_001E5F30"); extern char D_L00_001E5F40[]; extern float D_L00_00161B80 MACRO_ADDR; extern float D_L00_00161B84 MACRO_ADDR; @@ -2867,7 +2867,7 @@ void suck_beam_build(char *cannon_moby, char *suction_origin) { D_L00_001E6008[0] = 0; for (i = 1; i < 10; i++) { fast_vec_add(D_L00_001E5F40 + i * 0x10, - D_L00_001E5F30 + i * 0x10, + l00_suck_beam_previous_segment_positions + i * 0x10, (char *)beam_initialization_vectors + 0x30); D_L00_001E6008[i] = 0; } @@ -2994,7 +2994,7 @@ void suck_beam_update(void *moby, void *position) { int i; for (i = 1; i < 10; i++) { anchor = (V41 *)(D_L00_001E5F40 + i * 16); - previous = (V41 *)(D_L00_001E5F30 + i * 16); + previous = (V41 *)(l00_suck_beam_previous_segment_positions + i * 16); fast_vec_sub(&tmp_a, anchor, previous); qcopy(&tmp_b, &step); fast_vec_cross(&tmp_c, &tmp_b, &tmp_a); @@ -3105,7 +3105,7 @@ void suck_beam_update(void *moby, void *position) { } if (D_L00_001E4C80_lui[i].p) { fast_vec_sub(&tmp_a, - D_L00_001E5F30 + D_L00_001E4C80_lui[i].idx * 16, + l00_suck_beam_previous_segment_positions + D_L00_001E4C80_lui[i].idx * 16, D_L00_001E5F40 + D_L00_001E4C80_lui[i].idx * 16); length = fast_vec_length(&tmp_a); D_L00_001E4C80_lui[i].f += D_L00_001E4C80_lui[i].speed; @@ -3118,7 +3118,7 @@ void suck_beam_update(void *moby, void *position) { } else { D_L00_001E4C80_lui[i].f -= length; fast_vec_sub(&tmp_a, - D_L00_001E5F30 + D_L00_001E4C80_lui[i].idx * 16, + l00_suck_beam_previous_segment_positions + D_L00_001E4C80_lui[i].idx * 16, D_L00_001E5F40 + D_L00_001E4C80_lui[i].idx * 16); length = fast_vec_length(&tmp_a); } @@ -3156,7 +3156,7 @@ void suck_beam_update(void *moby, void *position) { fast_vec_sub(&tmp_c, (char *)((V41 *)D_L00_001E5EE0) + D_L00_001E4C80_lui[i].idx * 320 + j * 16, - D_L00_001E5F30 + D_L00_001E4C80_lui[i].idx * 16); + l00_suck_beam_previous_segment_positions + D_L00_001E4C80_lui[i].idx * 16); interpolate_vector(&motion, &tmp_b, &tmp_c, amount); j = (j + 19) % 20; fast_vec_sub(&tmp_d, @@ -3166,7 +3166,7 @@ void suck_beam_update(void *moby, void *position) { fast_vec_sub(&tmp_e, (char *)((V41 *)D_L00_001E5EE0) + D_L00_001E4C80_lui[i].idx * 320 + j * 16, - D_L00_001E5F30 + D_L00_001E4C80_lui[i].idx * 16); + l00_suck_beam_previous_segment_positions + D_L00_001E4C80_lui[i].idx * 16); interpolate_vector(&interp, &tmp_d, &tmp_e, amount); interpolate_vector(&motion, &motion, &interp, D_L00_001E4C80_lui[i].phase); D_L00_001E4C80_lui[i].phase += D_L00_001E4C80_lui[i].phase_step; @@ -3215,7 +3215,7 @@ void stop_suck_cannon_suction_effect(int callback_context) { if (p != 0) { D_L00_001E4C80[i].p = 0; fast_vec_sub(segment_offset, - D_L00_001E5F30 + D_L00_001E4C80[i].idx * 16, + l00_suck_beam_previous_segment_positions + D_L00_001E4C80[i].idx * 16, D_L00_001E5F40 + D_L00_001E4C80[i].idx * 16); segment_length = vector_length_xyz(segment_offset); scale_vector_xyz(segment_offset, segment_offset, D_L00_001E4C80[i].f / segment_length); From 2df424c3e1ba7c740ee884a5e797ecffd7ffa3ea Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:15:08 +0000 Subject: [PATCH 0055/1502] decomp: clarify names in sceMcChdir ret -> chdir_request_status: In the bound source src/sdk/storage/memory_card/sce_mc_chdir.c (SHA-256 d8120ea376e2eec9f03a85212f425a6328427a2091478da1b9496b9cb6785d58), s32 ret starts at -0xC8 and is returned when PollSema fails. Retail 0x0012411c branches on negative PollSema v0 with -0xC8 loaded at 0x00124120. After sceSifCallRpc at 0x001241a8, its v0 is saved in s0 at 0x001241b0 and returned via v0 at 0x001241d0; source assigns this rpc_dispatch_status to ret. Original Ghidra iVar1 confirms these gating and dispatch return paths. The supplied mode-1 RPC source and caller's zero test support immediate chdir request status, rather than asynchronous completion. --- src/sdk/storage/memory_card/sce_mc_chdir.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sdk/storage/memory_card/sce_mc_chdir.c b/src/sdk/storage/memory_card/sce_mc_chdir.c index b8889f53c3..f8c08d421e 100644 --- a/src/sdk/storage/memory_card/sce_mc_chdir.c +++ b/src/sdk/storage/memory_card/sce_mc_chdir.c @@ -22,12 +22,12 @@ extern s32 strncpy(s8 *, s8 *, s32); s32 sceMcChdir(s32 port, s32 slot, s8 *path, s32 pwd) { s32 rpc_dispatch_status; - s32 ret; + s32 chdir_request_status; if (mc_rpc_client.serve == 0) { return -0x64; } - ret = -0xC8; + chdir_request_status = -0xC8; if (PollSema(mc_sema) >= 0) { if ((path == NULL) || (*path == 0)) { SignalSema(mc_sema); @@ -53,9 +53,9 @@ s32 sceMcChdir(s32 port, s32 slot, s8 *path, s32 pwd) { } else { SignalSema(mc_sema); } - ret = rpc_dispatch_status; + chdir_request_status = rpc_dispatch_status; /* Duplicate return node #10. Try simplifying control flow for better match */ - return ret; + return chdir_request_status; } - return ret; + return chdir_request_status; } From cd26293dc1b4c206a8c353d619f43824fd917af8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:15:09 +0000 Subject: [PATCH 0056/1502] decomp: clarify names in sceMcGetDir ret -> request_status: Source initializes ret to -0xC8 before PollSema and returns it if acquisition fails, matching retail 0x00123f54-0x00123f58. After command-0xD sceSifCallRpc at 0x00123fe0, the return is saved in s0 at 0x00123fe8 and returned at 0x00124008; source copies rpc_submission_status into ret. Original Ghidra iVar1 has the same failure/submission return flow. Mode 1 RPC and callers waiting on sceMcSync show this is immediate request status rather than the later directory-entry count. --- src/sdk/storage/memory_card/sce_mc_get_dir.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sdk/storage/memory_card/sce_mc_get_dir.c b/src/sdk/storage/memory_card/sce_mc_get_dir.c index be8a478c60..a741b16f90 100644 --- a/src/sdk/storage/memory_card/sce_mc_get_dir.c +++ b/src/sdk/storage/memory_card/sce_mc_get_dir.c @@ -22,13 +22,13 @@ extern s32 strncpy(s8 *, s8 *, s32); s32 sceMcGetDir(s32 port, s32 slot, s8 *name, s32 mode, s32 maxent, s32 table) { s32 rpc_submission_status; - s32 ret; + s32 request_status; register s32 path_arg = slot; if (mc_rpc_client.serve == 0) { return -0x64; } - ret = -0xC8; + request_status = -0xC8; if (PollSema(mc_sema) >= 0) { if ((name == NULL) || (*name == 0)) { SignalSema(mc_sema); @@ -51,9 +51,9 @@ s32 sceMcGetDir(s32 port, s32 slot, s8 *name, s32 mode, s32 maxent, s32 table) { } else { SignalSema(mc_sema); } - ret = rpc_submission_status; + request_status = rpc_submission_status; /* Duplicate return node #12. Try simplifying control flow for better match */ - return ret; + return request_status; } - return ret; + return request_status; } From 15dc3684a98b5b94e6d8d8c684f6c6e2e8f09ed3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:15:18 +0000 Subject: [PATCH 0057/1502] decomp: clarify names in update_drek_boss_hero_follow_movement D_L18_0016234C_gp -> l18_drek_boss_hero_follow_target_distance: Retail 0x002f6a14 loads gp-0x48B4 (D_L18_0016234C) into f3; 0x002f6a20 subtracts it from the XY distance between moby+0x10 and the computed follow target, and 0x002f6a38 divides by the same scalar. At 0x002f6a40-0x002f6a44 this normalized distance error adjusts hero planar speed before the movement-speed clamp and call at 0x002f6a78. Thus this is the target distance at which follow-speed correction is zero. The authoritative C uses *(float *)&D_L18_0016234C_gp in both subtraction and division; preserve its declared short type and assembler label. D_L18_00162378_gp -> l18_drek_boss_hero_follow_default_radius: Retail 0x002f6990-0x002f69a8 subtracts the selected arena-node position from hero position and 0x002f69b8 clears Z. In the non-0xF control-mode branch, 0x002f69d0 loads gp-0x4888 (D_L18_00162378) and 0x002f69d4 passes it to the supplied vector-length clamp FUN_L00_0025f730. Node position is added back at 0x002f69f8, proving this scalar caps the default planar follow-target radius around that node. Source also uses this same scalar plus 5.8 in the follow-state exit test and plus 2.0 in follow-action eligibility; preserve its declared short type and assembler label. --- src/overlays/l18/mobys/drek_final_boss_robot.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l18/mobys/drek_final_boss_robot.c b/src/overlays/l18/mobys/drek_final_boss_robot.c index 70393dae1d..f82464d78b 100644 --- a/src/overlays/l18/mobys/drek_final_boss_robot.c +++ b/src/overlays/l18/mobys/drek_final_boss_robot.c @@ -329,7 +329,7 @@ extern int launch_first_idle_group_class_0772_moby(int idx, extern int count_group_gadgebots_not_in_state_8(int idx) __asm__("FUN_L18_002fc7e0"); extern int random_integer_below(int) __asm__("FUN_00213260"); extern s32 allocate_voice_for_target_entry(s32, s32, void *) __asm__("func_0022DA68"); -extern short D_L18_00162378_gp __asm__("D_L18_00162378") __attribute__((sda)); +extern short l18_drek_boss_hero_follow_default_radius __asm__("D_L18_00162378") __attribute__((sda)); extern short l18_drek_boss_scene_2_started_gp __asm__("D_L18_00162360") __attribute__((sda)); extern short D_L18_00162390 __attribute__((sda)); extern short l18_drek_boss_paired_transition_duration_frames_gp __asm__("D_L18_00162394") @@ -1470,7 +1470,7 @@ void drek_final_boss_robot_update(BossMoby *moby) { } if (vector_distance_xy(hero.motion.pos.f, D_L18_001600EC + boss_data->f250[2] * 0x80 + 0x30) > - *(float *)&D_L18_00162378_gp + 5.8f) { + *(float *)&l18_drek_boss_hero_follow_default_radius + 5.8f) { fire = 1; } if (fire) { @@ -2158,7 +2158,7 @@ int advance_drek_boss_planar_position_toward_target(char *moby, /* Moves a moby's follow distance toward a target, clamped to a range, then applies it. */ /* Ported from rac1-decomp (src/overlays/l18_veldin2/vendor_002F2AE0.c: func_L18_002F7DC0), where it is exact; names translated to the US level program. */ -extern short D_L18_0016234C_gp __asm__("D_L18_0016234C") __attribute__((sda)); +extern short l18_drek_boss_hero_follow_target_distance __asm__("D_L18_0016234C") __attribute__((sda)); extern void FUN_L00_0025f730(void *a, float x); int advance_drek_boss_planar_position_toward_target(char *moby, float arg, @@ -2180,15 +2180,15 @@ void update_drek_boss_hero_follow_movement(struct Moby *moby) { FUN_L00_0025f730(follow_target_position, *(float *)&drek_boss_hero_follow_mode_0f_radius_gp); } else { - FUN_L00_0025f730(follow_target_position, *(float *)&D_L18_00162378_gp); + FUN_L00_0025f730(follow_target_position, *(float *)&l18_drek_boss_hero_follow_default_radius); } fast_vec_add(follow_target_position, follow_target_position, D_L18_001600EC + (*(int *)(moby_vars + 0x344) << 7) + 0x30); follow_speed_limit = hero.motion.speed_xy; follow_speed_limit += - (vector_distance_xy(&moby->pos, follow_target_position) - *(float *)&D_L18_0016234C_gp) / - *(float *)&D_L18_0016234C_gp * (frame_time * 4.75f); + (vector_distance_xy(&moby->pos, follow_target_position) - *(float *)&l18_drek_boss_hero_follow_target_distance) / + *(float *)&l18_drek_boss_hero_follow_target_distance * (frame_time * 4.75f); hi = frame_time * 20.0f; lo = frame_time * 4.75f; if (follow_speed_limit > hi) { @@ -2445,7 +2445,7 @@ int select_drek_boss_next_action(struct Moby *moby) { float d = vector_distance_xy(D_0013E533 + 0xE9D, D_L18_001600EC + *(int *)(boss_action_vars + 0x25C) * 128 + 0x30); - if (*(float *)&D_L18_00162378_gp + 2.0f < d) + if (*(float *)&l18_drek_boss_hero_follow_default_radius + 2.0f < d) ok = 0; } } From 19f5254091052ef3df8d255faf97dd18fa48118e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:15:26 +0000 Subject: [PATCH 0058/1502] decomp: clarify names in create_missing_hero_item_slot_animations D_L00_0015F6A0_gp -> l00_hero_item_animation_slot_ids: Bound source src/overlays/shared/hero/hero_switch_item.c SHA-256 c9afac21edd732464867bed8c1d383164a0e95b028045ec2db43353138d035bd declares s32[2] bound to D_L00_0015F6A0. Retail 0x0020e3f8 shifts the item animation slot index s3 by two; 0x0020e3fc-0x0020e408 computes gp-0x7560+i*4 and loads the table element into a1 for allocate_moby_animation_slot at 0x0020e40c. Its return is stored in hero.held_item_anim_blend[i] at 0x0020e420; the loop is bounded to two at 0x0020e464. Original Ghidra independently shows the same indexed gp table as allocator argument two. Supplied allocator C stores that argument in selected_slot->id and uses it to select the animation record. The same source table also allocates hero.item_slot_blends[i] and held-item blends in start_equipped_item_animation. Thus these are per-item-animation-slot allocator IDs, distinct from the item definition animation passed in a2 at 0x0020e440. The l00 qualifier preserves ownership of this exact assembler binding. --- src/overlays/shared/hero/hero_switch_item.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 435792e02e..17bbc3f08e 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -766,7 +766,7 @@ void update_hero_condition_animation(void) { } } -extern s32 D_L00_0015F6A0_gp[2] __asm__("D_L00_0015F6A0") __attribute__((sda)); +extern s32 l00_hero_item_animation_slot_ids[2] __asm__("D_L00_0015F6A0") __attribute__((sda)); extern u8 D_L00_00197BC0_lui[] __asm__("D_L00_00197BC0") NOT_SDA; extern char *D_L00_00197300[]; extern u8 D_L00_0017CA80[] NOT_SDA; @@ -820,7 +820,7 @@ void update_hero_item_slot_blends(void) { struct Hero *h = &hero; if (hero.item_slot_blends[i] == 0) { u8 *allocated_item_slot_blend = - allocate_moby_animation_slot((u8 *)h->moby, D_L00_0015F6A0_gp[i]); + allocate_moby_animation_slot((u8 *)h->moby, l00_hero_item_animation_slot_ids[i]); hero.item_slot_blends[i] = allocated_item_slot_blend; *(f32 *)(allocated_item_slot_blend + 8) = 0.0f; *(u8 **)(hero.item_slot_blends[i] + 0x18) = @@ -1009,7 +1009,7 @@ void create_missing_hero_item_slot_animations(s32 suppress_slot_animation_creati break; { slot_animation_object = - allocate_moby_animation_slot((u8 *)hero.moby, D_L00_0015F6A0_gp[i]); + allocate_moby_animation_slot((u8 *)hero.moby, l00_hero_item_animation_slot_ids[i]); hero.held_item_anim_blend[i] = slot_animation_object; if (slot_animation_object) { hero.unkD14 = 0; @@ -1062,7 +1062,7 @@ void start_equipped_item_animation(void) { if (hero.held_item_anim_blend[i] != 0) { release_moby_animation_slot((u8 *)hero.moby, &hero.held_item_anim_blend[i]); } - slot_animation_object = allocate_moby_animation_slot((u8 *)hero.moby, D_L00_0015F6A0_gp[i]); + slot_animation_object = allocate_moby_animation_slot((u8 *)hero.moby, l00_hero_item_animation_slot_ids[i]); hero.held_item_anim_blend[i] = slot_animation_object; if (slot_animation_object != 0) { hero.item_hold_anim = slot_animation_id; From e3c38f0e48f04b690623a6982f34fc8e5a6677f4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:15:35 +0000 Subject: [PATCH 0059/1502] decomp: clarify names in render_drek_fight_missile_group_effects D_L18_00162238_gp -> l18_drek_missile_group_effects_disabled: Retail 0x002f06c4 loads the int at gp-0x49c8 (source assembler binding D_L18_00162238); 0x002f06e4 branches on nonzero directly to the epilogue at 0x002f081c, bypassing all class-0x54B group traversal, effect quad draws at 0x002f07dc/0x002f07f4 and phase writeback at 0x002f080c. Original retail decompilation expresses this as if (iGpffffb638 == 0). The authoritative C also tests the identical declaration at entry to draw_drek_fight_missile_group_trails and returns on nonzero. Together these reads prove a shared group-effects disable gate, with level-18 ownership. Preserve int type, SDA attribute and assembler label D_L18_00162238. --- src/overlays/l18/mobys/drek_fight_missile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l18/mobys/drek_fight_missile.c b/src/overlays/l18/mobys/drek_fight_missile.c index d0334dc585..683a4696b5 100644 --- a/src/overlays/l18/mobys/drek_fight_missile.c +++ b/src/overlays/l18/mobys/drek_fight_missile.c @@ -374,7 +374,7 @@ void select_drek_fight_missile_wander_target(struct Moby *moby, *(int *)(missile_private_vars + 0x160) = scale_game_frames(180); } -extern int D_L18_00162238_gp __asm__("D_L18_00162238") __attribute__((sda)); +extern int l18_drek_missile_group_effects_disabled __asm__("D_L18_00162238") __attribute__((sda)); #include "rnc/overlay/l18/mobys/drek_fight_missile_globals.h" @@ -413,7 +413,7 @@ void draw_drek_fight_missile_group_trails(struct Moby *moby) { int trail_segment_index; int trail_segment_start_slot; - if (D_L18_00162238_gp != 0) { + if (l18_drek_missile_group_effects_disabled != 0) { return; } for (i = 0; i < 16; i++) { @@ -495,7 +495,7 @@ void render_drek_fight_missile_group_effects(struct Moby *group_moby) { float moving_phase_step; float wait_to_explode_phase_step; int phase_blended_color; - if (D_L18_00162238_gp != 0) { + if (l18_drek_missile_group_effects_disabled != 0) { return; } group_entry = D_L18_001AC240_c7[group_moby->group]; From 32f34576b20b4122e0cc78cf1ed12faf2d555719 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:15:43 +0000 Subject: [PATCH 0060/1502] decomp: clarify names in setup_menu_display_text D_001602A4_gp -> setup_menu_moby_camera_y_offset: Source snapshot SHA-256 566e268f474350ee2d5da5e6a2288103bee67bffe1391c08f8b22c0ec852b172 declares this as const float bound to D_001602A4. Retail 0x0021efb8 loads the constant into f2; 0x0021efcc loads preview_camera+0x144 (the second of three position components), 0x0021efd0 adds f2, and 0x0021efd4 stores the sum at menu_moby_list+0x14. The neighboring +0x10/+0x18 stores likewise use the camera's first/third components, and 0x0021eff0 passes the menu+0x44 pointer to draw_moby_list. Original Ghidra independently shows g_flActiveCameraPosition[1] + fVar2, with fVar2 loaded from _DAT_001602a4. This proves a camera-relative Y offset for the setup menu moby positioning. --- src/ui/menus/system/setup_menu_display_text.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/menus/system/setup_menu_display_text.c b/src/ui/menus/system/setup_menu_display_text.c index 424a5e16a5..bab66e5a74 100644 --- a/src/ui/menus/system/setup_menu_display_text.c +++ b/src/ui/menus/system/setup_menu_display_text.c @@ -27,7 +27,7 @@ int setup_menu_display_text(struct MenuScreen *menu) { int count; preview_moby->pos.x = camera->position.f[0] + 8.0f; - preview_moby->pos.y = camera->position.f[1] + D_001602A4_gp; + preview_moby->pos.y = camera->position.f[1] + setup_menu_moby_camera_y_offset; preview_moby->pos.z = camera->position.f[2] - 0.1f; if (menu->data.preview.moby != 0) { draw_moby_list(menu->data.preview.moby, 1); From 1739510f5d4a1511a536825610285314bc21c7ed Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:18:02 +0000 Subject: [PATCH 0061/1502] decomp: clarify names in draw_electric_water_bolt_effect D_L15_00161C3C_gp -> l15_electric_water_first_bolt_path_first_pass_alpha: Retail 0x002d8770 loads this binding into a1 for the 0x001d3750 twenty-point path draw at 0x002d8798. Supplied draw_beam_and_arc_two_pass_quads names this parameter first_pass_alpha and shifts it by 24 into every first-pass vertex color. D_L15_00161C44_gp -> l15_electric_water_first_bolt_path_second_pass_alpha: Retail 0x002d8778 loads this binding into a2 for the 0x001d3750 twenty-point path draw at 0x002d8798. Supplied draw_beam_and_arc_two_pass_quads names this parameter second_pass_alpha and shifts it by 24 into every second-pass vertex color. D_L15_00161C54_gp -> l15_electric_water_bolt_draw_wrapped_accumulator: Retail 0x002d8720 reads this scalar as float; 0x002d873c subtracts the frame-scaled decrement and 0x002d8754 stores it back. At <= -8.0, 0x002d8764-0x002d8768 adds 8.0 and stores it again. This proves a wrapped accumulator in the bolt draw callback without inferring texture or UV purpose. D_L15_00161C58_gp -> l15_electric_water_bolt_draw_accumulator_decrement_rate: Retail 0x002d8710 reads this binding as float, 0x002d871c reads frame_scale from 0x0015ed60, and 0x002d8724 multiplies them. At 0x002d873c that product is subtracted from the stored accumulator at 0x00161c54, proving the frame-scaled accumulator decrement rate. D_L15_00161C6C_gp -> l15_electric_water_second_bolt_path_first_pass_alpha: Retail 0x002d87a0 loads this binding into a1 and 0x002d87a4 selects 0x001d3890, the second twenty-point bolt path, for the draw at 0x002d87b8. Supplied helper source shifts first_pass_alpha by 24 into first-pass vertex colors. D_L15_00161C70_gp -> l15_electric_water_second_bolt_path_second_pass_alpha: Retail 0x002d87a8 loads this binding into a2 for the second twenty-point path at 0x001d3890, drawn at 0x002d87b8. Supplied helper source shifts second_pass_alpha by 24 into all second-pass vertex colors. --- src/overlays/shared/props/electric_water.c | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/overlays/shared/props/electric_water.c b/src/overlays/shared/props/electric_water.c index a3ba7f5dfd..c7034b672c 100644 --- a/src/overlays/shared/props/electric_water.c +++ b/src/overlays/shared/props/electric_water.c @@ -1031,15 +1031,15 @@ extern float frame_scale __asm__("D_0015ED60"); extern char D_L15_001D3750_8710[] __asm__("D_L15_001D3750"); extern char D_L15_001D3BB0_8710[] __asm__("D_L15_001D3BB0"); extern int D_L15_00161CC8_8710 __asm__("D_L15_00161CC8"); -extern short D_L15_00161C58_gp __asm__("D_L15_00161C58") __attribute__((sda)); -extern short D_L15_00161C54_gp __asm__("D_L15_00161C54") __attribute__((sda)); -extern short D_L15_00161C3C_gp __asm__("D_L15_00161C3C") __attribute__((sda)); -extern short D_L15_00161C44_gp __asm__("D_L15_00161C44") __attribute__((sda)); +extern short l15_electric_water_bolt_draw_accumulator_decrement_rate __asm__("D_L15_00161C58") __attribute__((sda)); +extern short l15_electric_water_bolt_draw_wrapped_accumulator __asm__("D_L15_00161C54") __attribute__((sda)); +extern short l15_electric_water_first_bolt_path_first_pass_alpha __asm__("D_L15_00161C3C") __attribute__((sda)); +extern short l15_electric_water_first_bolt_path_second_pass_alpha __asm__("D_L15_00161C44") __attribute__((sda)); extern short D_L15_00161C64_gp __asm__("D_L15_00161C64") __attribute__((sda)); extern short D_L15_00161C68_gp __asm__("D_L15_00161C68") __attribute__((sda)); extern short D_L15_00161C9C_gp __asm__("D_L15_00161C9C") __attribute__((sda)); -extern short D_L15_00161C6C_gp __asm__("D_L15_00161C6C") __attribute__((sda)); -extern short D_L15_00161C70_gp __asm__("D_L15_00161C70") __attribute__((sda)); +extern short l15_electric_water_second_bolt_path_first_pass_alpha __asm__("D_L15_00161C6C") __attribute__((sda)); +extern short l15_electric_water_second_bolt_path_second_pass_alpha __asm__("D_L15_00161C70") __attribute__((sda)); extern short D_L15_00161C74_gp __asm__("D_L15_00161C74") __attribute__((sda)); extern short D_L15_00161C78_gp __asm__("D_L15_00161C78") __attribute__((sda)); extern short D_L15_00161CA0_gp __asm__("D_L15_00161CA0") __attribute__((sda)); @@ -1047,21 +1047,21 @@ extern void draw_beam_and_arc_two_pass_quads(char *, int, int, int, float, floa extern void FUN_L15_002d8e48_8710(char *) __asm__("FUN_L15_002d8e48"); #define F(x) (*(float *)&(x)) void draw_electric_water_bolt_effect(char *moby) { - float decremented_accumulator = F(D_L15_00161C54_gp) - F(D_L15_00161C58_gp) * frame_scale; - F(D_L15_00161C54_gp) = decremented_accumulator; + float decremented_accumulator = F(l15_electric_water_bolt_draw_wrapped_accumulator) - F(l15_electric_water_bolt_draw_accumulator_decrement_rate) * frame_scale; + F(l15_electric_water_bolt_draw_wrapped_accumulator) = decremented_accumulator; if (decremented_accumulator <= -8.0f) { - F(D_L15_00161C54_gp) = decremented_accumulator + 8.0f; + F(l15_electric_water_bolt_draw_wrapped_accumulator) = decremented_accumulator + 8.0f; } draw_beam_and_arc_two_pass_quads(D_L15_001D3750_8710, - W(D_L15_00161C3C_gp), - W(D_L15_00161C44_gp), + W(l15_electric_water_first_bolt_path_first_pass_alpha), + W(l15_electric_water_first_bolt_path_second_pass_alpha), 0x14, F(D_L15_00161C64_gp), F(D_L15_00161C68_gp), F(D_L15_00161C9C_gp)); draw_beam_and_arc_two_pass_quads(D_L15_001D3750_8710 + 0x140, - W(D_L15_00161C6C_gp), - W(D_L15_00161C70_gp), + W(l15_electric_water_second_bolt_path_first_pass_alpha), + W(l15_electric_water_second_bolt_path_second_pass_alpha), 0x14, F(D_L15_00161C74_gp), F(D_L15_00161C78_gp), From 8dd2715b03193299b18204c622df0e421f26b9b8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:18:12 +0000 Subject: [PATCH 0062/1502] decomp: clarify names in update_alien_snapper_spawner D_L06_0015FFD8 -> level_mobys_q: Retail 0x002fdb50 loads the selected list halfword; 0x002fdb58-0x002fdb5c loads the integer at 0x0015ffd8. At 0x002fdb60-0x002fdb64 the list value is masked with 0x7fff and shifted left 8, then 0x002fdb6c adds the stored address to form a0 for activate_state_15_moby_at_position (0x002e9d10). Original Ghidra likewise shows iRam0015ffd8 + (*puVar8 & 0x7fff) * 0x100. The authoritative C reproduces this moby lookup. Thus this is the level moby-array address; level_mobys_q is the supplied existing name for the identical assembler binding. --- src/overlays/l06/mobys/alien_snapper_spawner.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l06/mobys/alien_snapper_spawner.c b/src/overlays/l06/mobys/alien_snapper_spawner.c index d6b91328eb..e9a616657f 100644 --- a/src/overlays/l06/mobys/alien_snapper_spawner.c +++ b/src/overlays/l06/mobys/alien_snapper_spawner.c @@ -11,7 +11,7 @@ /* Trigger moby: waits for the hero in its zone, plays its open animation, then launches a listed moby. */ /* Ported from rac1-decomp (src/overlays/l06_blarg/vendor_002FE5D0.c: func_L06_002FEE60), where it is exact; names translated to the US level program. */ -extern int D_L06_0015FFD8; +extern int level_mobys_q __asm__("D_L06_0015FFD8"); extern short *D_L06_001ABFC0[]; extern void blend_moby_animation(void *, int, int, int) __asm__("FUN_00212f90"); void alien_snapper_spawner_update(char *moby) __asm__("FUN_L06_002fda30"); @@ -54,7 +54,7 @@ void alien_snapper_spawner_update(char *moby) { char *pos = moby + 0x10; do { if (activate_state_15_moby_at_position( - D_L06_0015FFD8 + ((*(unsigned short *)moby_list_entry & 0x7FFF) << 8), + level_mobys_q + ((*(unsigned short *)moby_list_entry & 0x7FFF) << 8), pos)) { found = 1.0f; break; From 3a949ca54a6d7f8a4a3e3fdf4e043a4d2efc460b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:18:12 +0000 Subject: [PATCH 0063/1502] decomp: clarify names in print_moby_class_sizes n -> moby_class_record_count: Retail 0x00241794 saves a1 in s3; 0x002417b4 guards collection for positive count and 0x00241840 compares the collected-record index against s3. The sort comparison loop uses the same bound at 0x002418b8, and 0x002418cc..0x00241908 copies it to a decrementing countdown for printing class ID/size pairs. Thus this int is the number of moby class records processed and printed, regardless of the caller header-field ambiguity. record -> moby_class_record_cursor: Retail 0x0024179c saves a0 in s2; 0x002417d0 loads the class ID at +4, 0x002417e0 loads the class start at +0, and 0x002417fc..0x0024180c subtract it from the next nonzero start at +0x20 or +0x40. At 0x00241848 s2 advances by 0x20. The checked caller supplies the same moby class table traversed in 0x20-byte steps for register_moby_class, proving this is its advancing class record cursor. --- .../shared/world/load_level_gameplay.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/shared/world/load_level_gameplay.c b/src/overlays/shared/world/load_level_gameplay.c index bb05a788b6..0e6f4b200b 100644 --- a/src/overlays/shared/world/load_level_gameplay.c +++ b/src/overlays/shared/world/load_level_gameplay.c @@ -83,20 +83,20 @@ extern int fptodp(float) __asm__("FUN_00120478"); void print_moby_class_sizes(int *record, int n) __asm__("FUN_L00_00241788"); -void print_moby_class_sizes(int *record, int n) { +void print_moby_class_sizes(int *moby_class_record_cursor, int moby_class_record_count) { MobyClassSize entries[512]; int i, j, k, done; - for (i = 0; i < n; i++, record += 8) { - entries[i].class_id = (float)record[1]; - if (record[0] == 0) { + for (i = 0; i < moby_class_record_count; i++, moby_class_record_cursor += 8) { + entries[i].class_id = (float)moby_class_record_cursor[1]; + if (moby_class_record_cursor[0] == 0) { entries[i].size = 0; } else { - if (record[8] != 0) { - entries[i].size = convert_integer_to_float(record[8] - record[0]) * 0.0009765625f; + if (moby_class_record_cursor[8] != 0) { + entries[i].size = convert_integer_to_float(moby_class_record_cursor[8] - moby_class_record_cursor[0]) * 0.0009765625f; } else { entries[i].size = - convert_integer_to_float(record[0x10] - record[0]) * 0.0009765625f; + convert_integer_to_float(moby_class_record_cursor[0x10] - moby_class_record_cursor[0]) * 0.0009765625f; } entries[i + 1].class_id = -1.0f; entries[i + 1].size = 0; @@ -104,7 +104,7 @@ void print_moby_class_sizes(int *record, int n) { } do { done = 1; - for (j = 0; j < n; j++) { + for (j = 0; j < moby_class_record_count; j++) { if (entries[j].size < entries[j + 1].size) { float class_id = entries[j].class_id; float size = entries[j].size; @@ -116,7 +116,7 @@ void print_moby_class_sizes(int *record, int n) { } } } while (!done); - for (k = 0; k < n; k++) { + for (k = 0; k < moby_class_record_count; k++) { int class_id = truncate_float_to_s32(entries[k].class_id); debug_print(moby_class_size_format, class_id, fptodp(entries[k].size)); } From 524a16e67580bf27493d43f19191740eb524b81b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:18:12 +0000 Subject: [PATCH 0064/1502] decomp: clarify names in movie_exit_to_gameplay buf -> gs_image_transfer_descriptor: In the authoritative SHA-256 8b60484bc7d13ce2ee2def750232116d064dc211e707cc8ffea2a81894748143 source, buf is a 16-byte-aligned char[0x70]. Retail Ghidra represents it as auStack_e0[112]. At 0x00299850/0x00299870 and 0x002998b8/0x002998d8 its stack address is argument 0 to 0x00122518, alongside the shifted GS address, format arguments and 128x128 or 64x64 dimensions. At 0x00299888/0x0029988c and 0x002998f0/0x002998f4 the same stack address is argument 0 to 0x001227d8 while s1 supplies the separate image-data address as argument 1, followed by sceGsSyncPath. This repeated setup/execution pattern proves the array is the GS image-transfer descriptor, reused for each block. --- .../shared/cutscenes/update_cutscene_playback.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/cutscenes/update_cutscene_playback.c b/src/overlays/shared/cutscenes/update_cutscene_playback.c index 8736939043..4f32fbd3f1 100644 --- a/src/overlays/shared/cutscenes/update_cutscene_playback.c +++ b/src/overlays/shared/cutscenes/update_cutscene_playback.c @@ -963,7 +963,7 @@ void count_vsync(void) __asm__("FUN_0012f1c8"); void movie_exit_to_gameplay(void) __asm__("FUN_L00_002997c8"); void movie_exit_to_gameplay(void) { - char buf[0x70] __attribute__((aligned(16))); + char gs_image_transfer_descriptor[0x70] __attribute__((aligned(16))); s32 large_count, small_count, gs_address, source, i, j; struct ActiveSceneTrigger *active; D_L00_0015F5D8 = 1; @@ -976,22 +976,22 @@ void movie_exit_to_gameplay(void) { small_count = D_0015ED80 != 0 ? 0xE : 0x11; i = 0; while (i < large_count) { - FUN_00122518_2997c8(buf, gs_address >> 8, 2, 1, 0, 0, 0x80, 0x80); + FUN_00122518_2997c8(gs_image_transfer_descriptor, gs_address >> 8, 2, 1, 0, 0, 0x80, 0x80); i++; gs_address += 0x10000; flush_cache(0); - FUN_001227d8_2997c8(buf, source); + FUN_001227d8_2997c8(gs_image_transfer_descriptor, source); source += 0xC000; sceGsSyncPath(0, 0); } gs_address = D_0015EE78_macro[0]; j = 0; while (j < small_count) { - FUN_00122518_2997c8(buf, gs_address >> 8, 1, 0, 0, 0, 0x40, 0x40); + FUN_00122518_2997c8(gs_image_transfer_descriptor, gs_address >> 8, 1, 0, 0, 0, 0x40, 0x40); j++; gs_address += 0x4000; flush_cache(0); - FUN_001227d8_2997c8(buf, source); + FUN_001227d8_2997c8(gs_image_transfer_descriptor, source); source += 0x4000; sceGsSyncPath(0, 0); } From badc4a818b4ec8b6ae7ee9b93760e1923f3f1127 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:18:22 +0000 Subject: [PATCH 0065/1502] decomp: clarify names in follow_camera_approach D_L00_00161CDC_gp -> l00_follow_camera_collision_probe_step_growth_factor: Retail 0x002e5fac loads this float via gp-0x4F24, then 0x002e5fc8 stores it at camera state+0x1D0+0x44. The supplied resolve_follow_camera_orbit_path_collisions source increments probe radius/step spd by collision_state[0x44]*collision_state[0x3C] each iteration before moving the probe. The supplied vehicle override assigns follow_camera_vehicle_collision_probe_step_growth_factor_gp to this same +0x44 field, confirming the role as the default step growth factor. D_L00_00161CE0_gp -> l00_follow_camera_collision_probe_count: Retail 0x002e5fb8 loads this float via gp-0x4F20 and 0x002e5fd4 writes camera state+0x1D0+0x40. The supplied resolve_follow_camera_orbit_path_collisions loops while i < truncate_float_to_s32(collision_state[0x40]-1.0f), advancing and checking successive orbit probes. This proves the stored default controls the collision probe count, rather than a distance or damping coefficient. D_L00_00161CE4_gp -> l00_follow_camera_collision_probe_scale: Retail 0x002e5fb4 loads this float via gp-0x4F1C and 0x002e5fd0 stores camera state+0x1D0+0x3C. Supplied endpoint collision source computes probe radius as minimum_distance + state[0x214]*state[0x20C]*(state[0x210]-1), where 0x20C is this field. Orbit path probing also multiplies state+0x3C into each step increase; the supplied vehicle override assigns follow_camera_vehicle_collision_probe_scale_gp to the identical +0x3C field. Together these establish the default collision probe scale. --- .../shared/camera/follow_camera_setup.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/shared/camera/follow_camera_setup.c b/src/overlays/shared/camera/follow_camera_setup.c index 5fd5944b33..abf3f1e753 100644 --- a/src/overlays/shared/camera/follow_camera_setup.c +++ b/src/overlays/shared/camera/follow_camera_setup.c @@ -24,9 +24,9 @@ extern float D_L00_0015EF44_macro __asm__("D_L00_0015EF44") MACRO_ADDR; extern unsigned char *D_L00_00168FC0_lui __asm__("D_L00_00168FC0") NOT_SDA; extern int D_L00_0015EF60_macro __asm__("D_L00_0015EF60") MACRO_ADDR; extern float D_L00_00161CA0_gp __asm__("D_L00_00161CA0") __attribute__((sda)); -extern float D_L00_00161CDC_gp __asm__("D_L00_00161CDC") __attribute__((sda)); -extern float D_L00_00161CE0_gp __asm__("D_L00_00161CE0") __attribute__((sda)); -extern float D_L00_00161CE4_gp __asm__("D_L00_00161CE4") __attribute__((sda)); +extern float l00_follow_camera_collision_probe_step_growth_factor __asm__("D_L00_00161CDC") __attribute__((sda)); +extern float l00_follow_camera_collision_probe_count __asm__("D_L00_00161CE0") __attribute__((sda)); +extern float l00_follow_camera_collision_probe_scale __asm__("D_L00_00161CE4") __attribute__((sda)); extern float D_L00_00161D1C_gp __asm__("D_L00_00161D1C") __attribute__((sda)); typedef struct { @@ -163,9 +163,9 @@ void follow_camera_approach(unsigned char *moby) { ((CamTarget *)target)->unkE8 = 0.2f; ((CamTarget *)target)->unkD6 = 0; spring_reset = (CamSpring *)(*(unsigned char **)(moby + 0x70) + 0x1D0); - spring_reset->unk44 = D_L00_00161CDC_gp; - spring_reset->unk3C = D_L00_00161CE4_gp; - spring_reset->unk40 = D_L00_00161CE0_gp; + spring_reset->unk44 = l00_follow_camera_collision_probe_step_growth_factor; + spring_reset->unk3C = l00_follow_camera_collision_probe_scale; + spring_reset->unk40 = l00_follow_camera_collision_probe_count; spring_reset->unk48 = D_L00_0015EF60_macro; reset = *(unsigned char **)(moby + 0x70) + 0x220; ((CamEnd *)reset)->unkC = D_L00_00161D1C_gp; @@ -866,9 +866,9 @@ void follow_camera_setup(Moby_2E8210 *camera_moby) { g->h38 = 0; g->i4C = 0; g->h34 = r; - g->f44 = D_L00_00161CDC_gp; - g->f3C = D_L00_00161CE4_gp; - g->f40 = D_L00_00161CE0_gp; + g->f44 = l00_follow_camera_collision_probe_step_growth_factor; + g->f3C = l00_follow_camera_collision_probe_scale; + g->f40 = l00_follow_camera_collision_probe_count; g->i48 = D_L00_0015EF60; clear_u64_value(camera_state_base->g.v10); From d65411e8d5fc112d8b99e5ec649b3184528f2efa Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:18:30 +0000 Subject: [PATCH 0066/1502] decomp: clarify names in pause_all_sounds D_001D0398 -> help_history_selected_index: Authoritative src/audio/voices/pause_all_sounds.c snapshot SHA-256 a7e84a56cc7857452c39e123c5f5fd249f31535f074ac1129895c1024986b229 declares extern s32 D_001D0398[] with explicit role comment 'help_history_list list.selected'. Its only use here resets element [0] after update_mission_list. Original Ghidra shows DAT_001d0398 = 0; retail 0x00218f1c forms 0x001d0000 and 0x00218f24 stores zero at +0x398 in the update_skill_point_and_gold_weapon_menu_entries call delay slot. This proves the named help-history selection is reset on pause entry; preserves the extern array type and exact assembler identity. --- src/audio/voices/pause_all_sounds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/audio/voices/pause_all_sounds.c b/src/audio/voices/pause_all_sounds.c index 3165f6326f..4e53d957b6 100644 --- a/src/audio/voices/pause_all_sounds.c +++ b/src/audio/voices/pause_all_sounds.c @@ -30,7 +30,7 @@ extern s32 D_00141660[]; extern u8 D_0014161B NOT_SDA; extern s32 D_0015EEA0_macro __asm__("D_0015EEA0") MACRO_ADDR; extern s32 alternate_animation_sequence_macro __asm__("D_0015EE20") MACRO_ADDR; -extern s32 D_001D0398[]; /* help_history_list list.selected */ +extern s32 help_history_selected_index[] __asm__("D_001D0398"); /* help_history_list list.selected */ extern void update_skill_point_and_gold_weapon_menu_entries() __asm__("func_00226E58"); @@ -93,7 +93,7 @@ void pause_all_sounds(s32 mode) { } } update_mission_list(); - D_001D0398[0] = 0; + help_history_selected_index[0] = 0; update_skill_point_and_gold_weapon_menu_entries(); { struct MenuSystem *g = &menu_system; From 78f6a74da9379fc42e6e7bcef1cd30afaa01155f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:20:48 +0000 Subject: [PATCH 0067/1502] decomp: clarify names in resolve_camera_movement_collisions o -> camera_record_at_entry: Bound source src/overlays/shared/camera/init_camera_system.c SHA-256 e62f71192ddbfd2ea174141b096bbfb489a1ddec04d735c2e2981d596b73f239 initializes char *o from l00_camera_lui.unk180 at function entry. Retail 0x001ed6c0 establishes camera-system base 0x00166c80 and 0x001ed6e0 loads a0 from +0x180; 0x001ed6e4-0x001ed700 copies this record's +0x64/+0x68/+0x6c movement origin. 0x001ed704 checks its short +0x8A and 0x001ed71c/0x001ed730 clears that flag before returning. Original Ghidra uses DAT_00166e00 for these same record-relative accesses. Source init_camera_system assigns this +0x180 slot from find_camera_record_by_id(0), proving camera-record identity. Later retail 0x001ed7d8 reloads the slot, corresponding to the separate existing current_camera_record local; camera_record_at_entry accurately distinguishes the initial capture. --- src/overlays/shared/camera/init_camera_system.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/camera/init_camera_system.c b/src/overlays/shared/camera/init_camera_system.c index d215e8ccd5..be64ec9d36 100644 --- a/src/overlays/shared/camera/init_camera_system.c +++ b/src/overlays/shared/camera/init_camera_system.c @@ -336,19 +336,19 @@ void resolve_camera_movement_collisions(OvlQuad *camera_pos void resolve_camera_movement_collisions(OvlQuad *camera_position, float collision_radius) { OvlQuad step_delta[1]; float camera_movement_origin_snapshot[4] __attribute__((aligned(16))); - char *o = (char *)l00_camera_lui.unk180; - float *camera_movement_origin = (float *)(o + 0x64); + char *camera_record_at_entry = (char *)l00_camera_lui.unk180; + float *camera_movement_origin = (float *)(camera_record_at_entry + 0x64); int step_count, i, j; camera_movement_origin_snapshot[0] = camera_movement_origin[0]; camera_movement_origin_snapshot[1] = camera_movement_origin[1]; camera_movement_origin_snapshot[2] = camera_movement_origin[2]; ((int *)camera_movement_origin_snapshot)[3] = 0; - if (*(short *)(o + 0x8A) != 0) { + if (*(short *)(camera_record_at_entry + 0x8A) != 0) { if (D_L00_0016C06C == 0) { qcopy(&l00_camera_lui.pos, camera_position); } - *(short *)(o + 0x8A) = 0; + *(short *)(camera_record_at_entry + 0x8A) = 0; return; } fast_vec_sub(step_delta, camera_position, camera_movement_origin_snapshot); From 46b079837534baa17eeff220dcf4b15d18126d4c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:20:57 +0000 Subject: [PATCH 0068/1502] decomp: clarify names in draw_moby_offset_textured_quad D_L01_00167240 -> camera_pos: Retail 0030c094-0030c09c adds moby position +0x10 to the summed scaled +0xc0/+0xe0 offsets, producing the quad reference point at sp+0x100. At 0030c0a4/0030c0b4 a1 is formed as 0x00167240; 0030c0a8 supplies that point as a2 and 0030c0b0 calls vector subtraction into sp+0xd0. The difference is normalized at 0030c0c0, crossed into the facing basis at 0030c0d8/0030c0fc and used to transform all four corners at 0030c154. The original decompilation shows the same subtraction from 0x167240 and the source uses D_L01_00167240 in fast_vec_sub. Supplied identical-assembler-label existing_names proves the shared spelling camera_pos, which is reused exactly. --- src/overlays/shared/enemies/plasmabot_death_debris.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/plasmabot_death_debris.c b/src/overlays/shared/enemies/plasmabot_death_debris.c index f51715f734..d7de1045ce 100644 --- a/src/overlays/shared/enemies/plasmabot_death_debris.c +++ b/src/overlays/shared/enemies/plasmabot_death_debris.c @@ -220,7 +220,7 @@ typedef struct { } GlowQuad_bfa8; extern GlowVec_bfa8 l01_moby_offset_quad_source_corners[4] __asm__("D_L01_0020B9D0"); -extern char D_L01_00167240[]; +extern char camera_pos[] __asm__("D_L01_00167240"); extern GlowVec_bfa8 D_0013F5E0[]; extern f32 moby_quad_c0_offset_scale_gp __asm__("D_L01_00162064") __attribute__((sda)); @@ -273,7 +273,7 @@ void draw_moby_offset_textured_quad(char *moby) { fast_vec_add(&local.basis.offset, &local.basis.offset, &local.basis.partial); basis_axis_or_source_corner = &local.basis.mat0; fast_vec_add(&local.basis.point, &local.basis.offset, &MOBY(moby)->pos); - fast_vec_sub(basis_axis_or_source_corner, D_L01_00167240, &local.basis.point); + fast_vec_sub(basis_axis_or_source_corner, camera_pos, &local.basis.point); fast_vec_normalize(basis_axis_or_source_corner, basis_axis_or_source_corner, one); basis_axis_or_quad_corner = &local.basis.mat1; fast_vec_cross(basis_axis_or_quad_corner, basis_axis_or_source_corner, D_0013F5E0); From 9897c3cfda855b0c702a516c8336c0991781e786 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:21:06 +0000 Subject: [PATCH 0069/1502] decomp: clarify names in draw_fighter_jet_radar_contact_icon D_0015EDB4 -> draw_map51: Authoritative fighter_jet.c snapshot SHA-256 4253438f7fde588b84b76ae39a42647b7105f64479a9d10faf5396aa2948087e declares unsigned char D_0015EDB4[4] and tests byte zero to choose side=-1 versus +1. Original retail Ghidra tests cRam0015edb4; retail 0x002eaba4-0x002eaba8 loads that byte, 0x002eabb4-0x002eabc0 selects the sign, and 0x002eabc4-0x002eabc8 multiplies radar_offset[0] before x conversion. The x coordinate feeds the quad via 0x002eac78 and 0x002eaca4. Reuse the supplied existing name draw_map51 for this identical assembler label, preserving type, four-byte extent and assembler identity. --- src/overlays/l17/mobys/fighter_jet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l17/mobys/fighter_jet.c b/src/overlays/l17/mobys/fighter_jet.c index f798a14a58..c3a93d4924 100644 --- a/src/overlays/l17/mobys/fighter_jet.c +++ b/src/overlays/l17/mobys/fighter_jet.c @@ -119,7 +119,7 @@ typedef struct { extern IconEC5D0 l17_fighter_jet_radar_contact_icon_definitions[] __asm__("D_L17_001D9B38"); extern unsigned char frame_size[] __asm__("D_0013E504"); -extern unsigned char D_0015EDB4[4]; +extern unsigned char draw_map51[4] __asm__("D_0015EDB4"); extern void draw_textured_quad(s32, s32, s32, s32, s32, s32, s32, s32, s64, s64) __asm__("func_001F5450"); @@ -152,7 +152,7 @@ void draw_fighter_jet_radar_contact_icon( fast_vec_scale(radar_offset, radar_offset, 0.0714285746f); radar_distance = fast_vec_length(radar_offset); side = 1.0f; - if (D_0015EDB4[0] != 0) { + if (draw_map51[0] != 0) { side = -1.0f; } x = truncate_float_to_s32(side * radar_offset[0]); From 51177f19af622ca31ff8c13ffc8164c53db0067a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:21:15 +0000 Subject: [PATCH 0070/1502] decomp: clarify names in draw_beam_barrier_segments D_L06_00161E0C -> l06_beam_barrier_transform_scale: Authoritative source passes this float to set_scale_matrix(yaw_matrix, ...), then multiplies the moby Euler base_matrix by that scale matrix. Retail 0x002f6e28 loads it into f12, 0x002f6e2c calls the scale helper, and 0x002f6e34-0x002f6e40 composes the base transform. That base transforms segment rotations and offsets at 0x002f6ef0-0x002f6f14. The supplied burst case also uses this same scalar for its barrier base transform. D_L06_001DAFD0 -> l06_beam_barrier_segment_local_offsets: Retail 0x002f6ed4 initializes s3 to 0x001dafd0; 0x002f6f04-0x002f6f14 passes each 16-byte record to transform_vector with the scaled moby base matrix and advances s3 by 0x10. 0x002f6f18-0x002f6f28 adds moby+0x10 position into the segment matrix translation. Source offset_src follows exactly this nine-iteration flow, proving these are segment offsets in the barrier local frame; the burst case uses the same per-segment transformed positions. D_L06_001DB060 -> l06_beam_barrier_segment_euler_rotations: Retail 0x002f6ed0 initializes s4 to 0x001db060; 0x002f6ee0-0x002f6eec passes each record to the same Euler rotation matrix helper used for moby+0x40 at 0x002f6dfc-0x002f6e1c, then advances by 0x10. 0x002f6ef0-0x002f6f00 composes each resulting matrix with the barrier base transform in the nine-segment loop. Source rotation = D_L06_001DB060 and euler_rotation_matrix(matrix, rotation) corroborate the segment Euler rotation role. --- src/overlays/l06/mobys/beam_barrier.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/l06/mobys/beam_barrier.c b/src/overlays/l06/mobys/beam_barrier.c index e0ce819da7..95279d233c 100644 --- a/src/overlays/l06/mobys/beam_barrier.c +++ b/src/overlays/l06/mobys/beam_barrier.c @@ -46,13 +46,13 @@ extern int help_request(int, int) __asm__("FUN_L00_00203908"); typedef struct GbMoby GbMoby; extern GbMoby *D_L06_001745D8 NOT_SDA; -extern float D_L06_001DAFD0[]; -extern float D_L06_001DB060[]; +extern float l06_beam_barrier_segment_local_offsets[] __asm__("D_L06_001DAFD0"); +extern float l06_beam_barrier_segment_euler_rotations[] __asm__("D_L06_001DB060"); extern int D_L06_00161E40[] MACRO_ADDR; extern int D_L06_00161E50; extern int D_L06_00161E54; extern f32 D_L06_00161E08 __attribute__((sda)); -extern float D_L06_00161E0C __attribute__((sda)); +extern float l06_beam_barrier_transform_scale __asm__("D_L06_00161E0C") __attribute__((sda)); float beam_barrier_collision_z_offset_gp __asm__("D_L06_00161E18") = 2.25f; extern int beam_barrier_burst_color_from_gp __asm__("D_L06_00161E1C") __attribute__((sda)); int beam_barrier_burst_color_to_gp __asm__("D_L06_00161E20") = 0x80802080; /* RGBA, 0xAABBGGRR */ @@ -289,7 +289,7 @@ void beam_barrier_update(struct Moby *moby) { int spark; int segment_offset; euler_rotation_matrix(work.matrix, &moby->rot); - set_scale_matrix(work.shared.local, D_L06_00161E0C); + set_scale_matrix(work.shared.local, l06_beam_barrier_transform_scale); segment = 0; pos = (float *)&moby->pos; multiply_matrix(work.matrix, work.matrix, work.shared.local); @@ -297,10 +297,10 @@ void beam_barrier_update(struct Moby *moby) { do { segment_offset = segment * 16; spark = 19; - euler_rotation_matrix(work.shared.local, (char *)D_L06_001DB060 + segment_offset); + euler_rotation_matrix(work.shared.local, (char *)l06_beam_barrier_segment_euler_rotations + segment_offset); next_segment = segment + 1; multiply_matrix(work.shared.local, work.matrix, work.shared.local); - transform_vector(work.point, (char *)D_L06_001DAFD0 + segment_offset, work.matrix); + transform_vector(work.point, (char *)l06_beam_barrier_segment_local_offsets + segment_offset, work.matrix); fast_vec_add(work.shared.collision.delta, work.point, pos); work.shared.collision.delta[3] = 1.0f; do { @@ -381,7 +381,7 @@ void draw_beam_barrier_segments(char *moby) { int j; euler_rotation_matrix(base_matrix, moby + 0x40); - set_scale_matrix(yaw_matrix, D_L06_00161E0C); + set_scale_matrix(yaw_matrix, l06_beam_barrier_transform_scale); multiply_matrix(base_matrix, base_matrix, yaw_matrix); vu1_add_g_sregister(6, get_effect_texture(14)); vu1_add_g_sregister(0x14, 0xFF9000000260L); @@ -393,8 +393,8 @@ void draw_beam_barrier_segments(char *moby) { font_queue_vu_state(); first_matrix = segment_matrix[0]; segment_params = beam_segment_draw_params; - rotation = D_L06_001DB060; - offset_src = D_L06_001DAFD0; + rotation = l06_beam_barrier_segment_euler_rotations; + offset_src = l06_beam_barrier_segment_local_offsets; translation = segment_matrix[0] + 12; matrix = first_matrix; for (i = 8; i >= 0; i--) { From 0531ba95a98cd3bc44a8f11e691e581226c5679b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:21:25 +0000 Subject: [PATCH 0071/1502] decomp: clarify names in update_electric_beam D_L14_001620B8_gp -> l14_electric_beam_pending_pulse_count: Authoritative src/overlays/shared/props/electric_beam.c SHA-256 c1b7011314a33712e0b7d23f8da744c84f4fa46f8bb5e406f84274dcbff95536 declares this int bound to D_L14_001620B8. Retail 0x003016b4 loads gp-0x4b48; 0x003016b8 tests nonzero and 0x003016c0-0x003016c4 requires pulse lifetime pvars+0x12 to be zero. 0x003016cc subtracts one and 0x003016d8 stores it while 0x003016d4 calls established start_electric_beam_pulse on the same moby. Thus this is a count of pending counter-triggered pulses; its external producer/event is unresolved. D_L14_001620CC_gp -> l14_electric_beam_update_disabled: The authoritative source declares this int with assembler binding D_L14_001620CC and returns when it is nonzero. Original retail Ghidra wraps the remaining beam update in iGpffffb4cc == 0. Retail 0x00301620 reads gp-0x4b34, and 0x00301624 branches to epilogue 0x003017e4 on nonzero after the culling check but before state dispatch 0x0030162c. This skips initialization/pulse processing, damage, animation and draw callback registration. Therefore the scalar disables this beam update; its producer and intended external purpose are unknown. --- src/overlays/shared/props/electric_beam.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/props/electric_beam.c b/src/overlays/shared/props/electric_beam.c index 176fe76370..2496cfcde2 100644 --- a/src/overlays/shared/props/electric_beam.c +++ b/src/overlays/shared/props/electric_beam.c @@ -43,8 +43,8 @@ extern void draw_electric_beam(char *) __asm__("FUN_L14_00301fa8"); void apply_electric_beam_damage(char *self) __asm__("FUN_L14_00302538"); extern void apply_electric_beam_damage(char *) __asm__("FUN_L14_00302538"); -extern int D_L14_001620CC_gp __asm__("D_L14_001620CC") __attribute__((sda)); -extern int D_L14_001620B8_gp __asm__("D_L14_001620B8") __attribute__((sda)); +extern int l14_electric_beam_update_disabled __asm__("D_L14_001620CC") __attribute__((sda)); +extern int l14_electric_beam_pending_pulse_count __asm__("D_L14_001620B8") __attribute__((sda)); extern int D_L14_001620D0_gp __asm__("D_L14_001620D0") __attribute__((sda)); extern s32 D_L14_001620C8_gp __asm__("D_L14_001620C8") __attribute__((sda)); extern int D_L14_001620D4_gp __asm__("D_L14_001620D4") __attribute__((sda)); @@ -71,7 +71,7 @@ void electric_beam_update(unsigned char *moby) { return; } } - if (D_L14_001620CC_gp != 0) { + if (l14_electric_beam_update_disabled != 0) { return; } beam_state = MOBY(moby)->state; @@ -85,9 +85,9 @@ void electric_beam_update(unsigned char *moby) { beam_vars->sA = 1; break; case BEAM_STATE_COUNTER_TRIGGERED_PULSES: - if (D_L14_001620B8_gp != 0) { + if (l14_electric_beam_pending_pulse_count != 0) { if (beam_vars->s12 == 0) { - D_L14_001620B8_gp = D_L14_001620B8_gp - 1; + l14_electric_beam_pending_pulse_count = l14_electric_beam_pending_pulse_count - 1; start_electric_beam_pulse((char *)moby); } } From 87d0900aaab8cc5b9b7eda158854e5c2690d3114 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:21:26 +0000 Subject: [PATCH 0072/1502] decomp: clarify names in advance_moby_animation_blend a -> animation_state: Retail 0x0024f1a0 saves a1 in s0; accesses through it own progress +0x24, step +0x28, animation/frame indices +0x20..+0x23 and frame pointers +0x38/+0x3C. The bound C and initialize_moby_animation_blend establish this as the animation blend state. f -> unscaled_frame_remainder: Retail 0x0024f2d8-0x0024f300 subtracts 1.0 from progress and divides by the old +0x2C factor. The bound float f holds that remainder before 0x0024f314-0x0024f328 multiplies it by the newly selected frame factor and stores scaled progress. g -> frame_progress_scale: Retail 0x0024f2e4-0x0024f310 indexes animation +0x22 and frame +0x20 to load the frame record's first float. At 0x0024f314-0x0024f328 this bound C g scales the unscaled remainder and is stored at +0x2C, also used to scale the next progress increment at 0x0024f1d0. o2 -> animation_table_byte_offset: The bound C assigns o2=state[0x22]*4. Retail 0x0024f2e4-0x0024f304 loads +0x22, shifts left two and adds it to the +0x14 table owner before loading the animation pointer at +0x48. The separate +0x20 offset then selects a frame at +0x1C. s -> unscaled_frame_step: The bound C caches float state+0x28 in s. Retail 0x0024f1a8 and 0x0024f1d0-0x0024f1e4 multiply it by the +0x2C frame factor and add to +0x24 progress; its sign controls forward stepping. Initialization sets +0x28 to 1 separately from +0x2C=1/step_divisor, proving step before frame scaling. t -> advanced_frame_progress: The bound C computes t from state+0x24 plus s times state+0x2C. Retail 0x0024f1d0-0x0024f1e4 multiplies, adds and stores that progress; 0x0024f1f8-0x0024f234 tests the same value around 1.0 before snapping to the frame boundary. u -> next_frame_remap_flag: The bound C caches state[7] in u. Retail 0x0024f258-0x0024f288 copies it to current flag +6 and conditionally promotes next-frame data +0x3C to +0x38. At 0x0024f37c-0x0024f3c0 +7 chooses helper 0x0024f440 versus a direct frame pointer. The supplied helper C selects frame table +0x18 and scatters entries by mapping bytes into the destination packet, proving next-frame remapping. --- .../mobys/allocate_moby_animation_slot.c | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/overlays/shared/mobys/allocate_moby_animation_slot.c b/src/overlays/shared/mobys/allocate_moby_animation_slot.c index 25720591ea..41f769f995 100644 --- a/src/overlays/shared/mobys/allocate_moby_animation_slot.c +++ b/src/overlays/shared/mobys/allocate_moby_animation_slot.c @@ -193,67 +193,67 @@ extern void FUN_L00_00252990(void *); void advance_moby_animation_blend(void *unused, unsigned char *a) __asm__("FUN_L00_0024f190"); -void advance_moby_animation_blend(void *unused, unsigned char *a) { - float s = *(float *)(a + 0x28); - a[5] = 0; - if (s != 0.0f && *(float *)(a + 0x2C) != 0.0f) { - float t = *(float *)(a + 0x24) + s * *(float *)(a + 0x2C); - *(float *)(a + 0x24) = t; - if (s > 0.0f) { - if (t > 0.99f && t < 1.01f) { - *(float *)(a + 0x24) = 1.0f; +void advance_moby_animation_blend(void *unused, unsigned char *animation_state) { + float unscaled_frame_step = *(float *)(animation_state + 0x28); + animation_state[5] = 0; + if (unscaled_frame_step != 0.0f && *(float *)(animation_state + 0x2C) != 0.0f) { + float advanced_frame_progress = *(float *)(animation_state + 0x24) + unscaled_frame_step * *(float *)(animation_state + 0x2C); + *(float *)(animation_state + 0x24) = advanced_frame_progress; + if (unscaled_frame_step > 0.0f) { + if (advanced_frame_progress > 0.99f && advanced_frame_progress < 1.01f) { + *(float *)(animation_state + 0x24) = 1.0f; } - if (*(float *)(a + 0x24) >= 1.0f) { - int u = a[7]; + if (*(float *)(animation_state + 0x24) >= 1.0f) { + int next_frame_remap_flag = animation_state[7]; do { - int o, p, o2; - a[6] = u; - a[5] |= 1; - a[0x20] = a[0x21]; - if ((unsigned char)u) { - *(int *)(a + 0x38) = *(int *)(a + 0x3C); + int o, p, animation_table_byte_offset; + animation_state[6] = next_frame_remap_flag; + animation_state[5] |= 1; + animation_state[0x20] = animation_state[0x21]; + if ((unsigned char)next_frame_remap_flag) { + *(int *)(animation_state + 0x38) = *(int *)(animation_state + 0x3C); } - a[0x22] = a[0x23]; - a[0x21]++; - o = a[0x23] * 4; - if (a[0x21] >= - *(unsigned char *)(*(int *)(*(unsigned char **)(a + 0x14) + o + 0x48) + + animation_state[0x22] = animation_state[0x23]; + animation_state[0x21]++; + o = animation_state[0x23] * 4; + if (animation_state[0x21] >= + *(unsigned char *)(*(int *)(*(unsigned char **)(animation_state + 0x14) + o + 0x48) + 0x10)) { - a[0x21] = 0; - a[5] |= 2; + animation_state[0x21] = 0; + animation_state[5] |= 2; } { - float f = (*(float *)(a + 0x24) - 1.0f) / *(float *)(a + 0x2C); - float g; - o2 = a[0x22] * 4; - p = a[0x20] * 4; - *(float *)(a + 0x24) = f; - g = **(float **)(*(int *)(*(unsigned char **)(a + 0x14) + o2 + 0x48) + p + + float unscaled_frame_remainder = (*(float *)(animation_state + 0x24) - 1.0f) / *(float *)(animation_state + 0x2C); + float frame_progress_scale; + animation_table_byte_offset = animation_state[0x22] * 4; + p = animation_state[0x20] * 4; + *(float *)(animation_state + 0x24) = unscaled_frame_remainder; + frame_progress_scale = **(float **)(*(int *)(*(unsigned char **)(animation_state + 0x14) + animation_table_byte_offset + 0x48) + p + 0x1C); - *(float *)(a + 0x2C) = g; - *(float *)(a + 0x24) = f * g; + *(float *)(animation_state + 0x2C) = frame_progress_scale; + *(float *)(animation_state + 0x24) = unscaled_frame_remainder * frame_progress_scale; } - } while (*(float *)(a + 0x24) >= 1.0f); + } while (*(float *)(animation_state + 0x24) >= 1.0f); } } } - if (a[6]) { - FUN_L00_0024f440(a, a[0x22], a[0x20], *(int *)(a + 0x38)); + if (animation_state[6]) { + FUN_L00_0024f440(animation_state, animation_state[0x22], animation_state[0x20], *(int *)(animation_state + 0x38)); } else { - int o = a[0x22] * 4; - int p = a[0x20] * 4; - *(int *)(a + 0x38) = - *(int *)(*(int *)(*(unsigned char **)(a + 0x14) + o + 0x48) + p + 0x1C); + int o = animation_state[0x22] * 4; + int p = animation_state[0x20] * 4; + *(int *)(animation_state + 0x38) = + *(int *)(*(int *)(*(unsigned char **)(animation_state + 0x14) + o + 0x48) + p + 0x1C); } - if (a[7]) { - FUN_L00_0024f440(a, a[0x23], a[0x21], *(int *)(a + 0x3C)); + if (animation_state[7]) { + FUN_L00_0024f440(animation_state, animation_state[0x23], animation_state[0x21], *(int *)(animation_state + 0x3C)); } else { - int o = a[0x23] * 4; - int p = a[0x21] * 4; - *(int *)(a + 0x3C) = - *(int *)(*(int *)(*(unsigned char **)(a + 0x14) + o + 0x48) + p + 0x1C); + int o = animation_state[0x23] * 4; + int p = animation_state[0x21] * 4; + *(int *)(animation_state + 0x3C) = + *(int *)(*(int *)(*(unsigned char **)(animation_state + 0x14) + o + 0x48) + p + 0x1C); } - FUN_L00_00252990(a); + FUN_L00_00252990(animation_state); } typedef struct { From 0e0fd5015862166889e32965f1962b916c5b3a6f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:27:21 +0000 Subject: [PATCH 0073/1502] decomp: clarify names in update_billboard_projectile D_L01_00167240 -> camera_pos: Retail 002c7544-002c756c constructs address 0x00167240 and passes it with moby+0x10 to vector_distance_xy. After the pointer adjustment at 002c7570, 002c7574 reads its Z and 002c759c-002c75ac read its Y/X, subtracting moby position to compute facing angles stored at moby+0x44/+0x48. Original Ghidra shows fRam00167240/44/48 in those same differences. Authoritative C binds char *camera to this array in update_billboard_projectile, and the issued identical-assembler-label existing_names explicitly supplies camera_pos; reuse that exact spelling while retaining the raw assembler binding and array type. --- src/overlays/shared/enemies/billboard_projectile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/billboard_projectile.c b/src/overlays/shared/enemies/billboard_projectile.c index c9489bf5eb..104e1bab7f 100644 --- a/src/overlays/shared/enemies/billboard_projectile.c +++ b/src/overlays/shared/enemies/billboard_projectile.c @@ -13,7 +13,7 @@ #include "rnc/overlay/shared/rendering/effects/spawn_type_10_particle.h" #include "rnc/overlay/shared/rendering/effects/update_three_phase_effect_particle.h" -extern char D_L01_00167240[]; +extern char camera_pos[] __asm__("D_L01_00167240"); extern char D_L01_001742E0[]; extern float D_L01_001742C0[]; @@ -36,7 +36,7 @@ void spawn_collision_particle_bursts(void) { float spawn_position[4]; float base_angle, b; int i; - fast_vec_sub(offset_vector, D_L01_00167240, D_L01_001742E0); + fast_vec_sub(offset_vector, camera_pos, D_L01_001742E0); base_angle = -fast_arc_tan(vector_length_xy(offset_vector), offset_vector[2]); fast_arc_tan(offset_vector[0], offset_vector[1]); for (i = 19; i >= 0; i--) { @@ -76,7 +76,7 @@ void billboard_projectile_update(char *moby) { TIMED_REMOVAL = 2 }; int *motion_lifetime_vars = ((int *)MOBY(moby)->pvars); - char *camera = D_L01_00167240; + char *camera = camera_pos; char hit[0x30]; float normal[4]; float distance; From dc879bf3d75d1b4ce5108d3fce5b336f1c432d27 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:31:36 +0000 Subject: [PATCH 0074/1502] decomp: clarify names in draw_moby_vector_streams D_L06_001FE890 -> l06_vector_stream_copy_rotations: Authoritative source src/overlays/l06/mobys/switchable_beam_barrier.c (SHA-256 7897ae311b33a37230efddc809a59fd136a020b195f6dc37ce6fbc8a9e159b70) declares extern float D_L06_001FE890[]. In draw_moby_vector_streams, tp starts at this array and supplies euler_rotation_matrix(mp,tp) for four copy transforms, advancing by four floats each iteration. Original retail Ghidra sets iVar6=0x1fe890, passes it to func_0x00217b10 and adds 0x10. Retail 0x00305278/0x00305284 materializes 0x001fe890 in s2; 0x00305290-0x0030529c passes s2 as the Euler input and advances it 16 bytes; 0x003052a0-0x003052ac multiplies the resulting matrix by the moby's rotation/scale, and 0x003052dc-0x003052f4 limits construction to four transforms. The same source array supplies euler_rotation_matrix(u.m.b,&D_L06_001FE890[i*4]) in the four-copy burst loop, corroborating per-copy rotations. --- src/overlays/l06/mobys/switchable_beam_barrier.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l06/mobys/switchable_beam_barrier.c b/src/overlays/l06/mobys/switchable_beam_barrier.c index a475ac1fe2..cc6177453e 100644 --- a/src/overlays/l06/mobys/switchable_beam_barrier.c +++ b/src/overlays/l06/mobys/switchable_beam_barrier.c @@ -36,7 +36,7 @@ extern float D_0015ED6C; #include "rnc/overlay/l06/mobys/switchable_beam_barrier_data/update_switchable_beam_barrier_3.h" -extern float D_L06_001FE890[]; +extern float l06_vector_stream_copy_rotations[] __asm__("D_L06_001FE890"); extern int D_L06_00162234; extern int D_L06_00162238; extern float D_L06_001621F8 __attribute__((sda)); @@ -175,7 +175,7 @@ void switchable_beam_barrier_update(char *moby) { set_scale_matrix(u.m.b, D_L06_00162208); multiply_matrix(u.m.a, u.m.a, u.m.b); for (i = 0; i < 4; i++) { - euler_rotation_matrix(u.m.b, &D_L06_001FE890[i * 4]); + euler_rotation_matrix(u.m.b, &l06_vector_stream_copy_rotations[i * 4]); multiply_matrix(u.m.b, u.m.a, u.m.b); fast_vec_add(u.m.b + 12, u.m.b + 12, moby + 0x10); u.m.b[14] += (float)i * 1.7f + 0.6f; @@ -298,7 +298,7 @@ void draw_moby_vector_streams(char *moby) { transform_matrix_base = copy_transform_matrices[0]; sp = shared_helper_arguments; pp = copy_transform_matrices[0] + 12; - tp = D_L06_001FE890; + tp = l06_vector_stream_copy_rotations; mp = transform_matrix_base; for (i = 0; i < 4; i++) { euler_rotation_matrix(mp, tp); From 1a0299149c7216c3717f330e386fe2a08698f9a0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:33:18 +0000 Subject: [PATCH 0075/1502] decomp: clarify names in update_birdbot_projectile D_L01_00167240 -> camera_pos: In source snapshot a4e74589c85e13be548cffa142cd40e216944d82701803e9199b5b79e94eac94, vector_distance_xy(pos, D_L01_00167240) > 64.0f removes the projectile. Retail 0x002fa59c and 0x002fa5a8 construct a1=0x00167240, while 0x002fa5a0 passes projectile+0x10 in a0 to the distance helper at 0x002fa5a4; 0x002fa5ac-0x002fa5c0 compare the return against 64.0f and branch to removal at 0x002fa694. Original Ghidra likewise calls func_0x00221398(puVar6,0x167240). The supplied existing_names explicitly identifies camera_pos for this identical assembler label, so reuse that spelling for the camera-position distance reference, preserving the extern u8 array type and assembler identity. --- src/overlays/l01/mobys/birdbot_projectile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l01/mobys/birdbot_projectile.c b/src/overlays/l01/mobys/birdbot_projectile.c index a3db3c5b97..f1c3d21086 100644 --- a/src/overlays/l01/mobys/birdbot_projectile.c +++ b/src/overlays/l01/mobys/birdbot_projectile.c @@ -225,7 +225,7 @@ typedef struct { extern f32 scale_time(f32) __asm__("FUN_001f96b0"); extern s32 collision_line(void *, void *, s32, void *, void *) __asm__("FUN_001efa68"); extern s32 probe_world_sphere(f32, void *, s32, void *, void *) __asm__("FUN_L00_001f2868"); -extern u8 D_L01_00167240[]; +extern u8 camera_pos[] __asm__("D_L01_00167240"); extern u128 D_L01_001742E0; void birdbot_projectile_update(DropMoby *) __asm__("FUN_L01_002fa4c0"); @@ -256,7 +256,7 @@ void birdbot_projectile_update(DropMoby *projectile) { ((f32 *)&projectile_vars->vel)[2] -= (scaled_ten * zero + one) * 2.0f / scaled_ten_product; fast_vec_add(pos, pos, &projectile_vars->vel); if (projectile->pos.f[0] < zero || projectile->pos.f[1] < zero || projectile->pos.f[2] < zero || - vector_distance_xy(pos, D_L01_00167240) > 64.0f) { + vector_distance_xy(pos, camera_pos) > 64.0f) { mark_moby_for_removal(projectile); return; } From 83149304ef127dcb4a26d009fa4e0961adeb81ee Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:33:26 +0000 Subject: [PATCH 0076/1502] decomp: clarify names in draw_ship_radar_moby_icon D_0015EDB4 -> draw_map51: Retail 0x00311810-0x00311814 loads unsigned byte 0x0015EDB4. At 0x00311818-0x0031182c zero selects +1.0 and nonzero selects -1.0; 0x00311834 multiplies that sign by radar_offset.x before integer conversion. Original retail Ghidra cRam0015edb4 and current C unsigned char D_0015EDB4[4] with D_0015EDB4[0] agree. Reuse supplied existing name draw_map51 for this identical assembler label; preserve its type, array dimensions and assembler identity. --- src/overlays/l11/mobys/jet_fighter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l11/mobys/jet_fighter.c b/src/overlays/l11/mobys/jet_fighter.c index 767554bc3d..3607b840df 100644 --- a/src/overlays/l11/mobys/jet_fighter.c +++ b/src/overlays/l11/mobys/jet_fighter.c @@ -62,7 +62,7 @@ typedef struct { extern IconEC5D0 l11_ship_radar_icon_definitions[] __asm__("D_L11_001F1058"); extern s64 get_effect_texture(s32) __asm__("func_001F44B8"); extern unsigned char frame_size[] __asm__("D_0013E504"); -extern unsigned char D_0015EDB4[4]; +extern unsigned char draw_map51[4] __asm__("D_0015EDB4"); extern void draw_textured_quad(s32, s32, s32, s32, s32, s32, s32, s32, s64, s64) __asm__("func_001F5450"); @@ -99,7 +99,7 @@ void draw_ship_radar_moby_icon( fast_vec_scale(radar_offset, radar_offset, 0.142857149f); radar_distance = fast_vec_length(radar_offset); side = 1.0f; - if (D_0015EDB4[0] != 0) { + if (draw_map51[0] != 0) { side = -1.0f; } x = truncate_float_to_s32(side * radar_offset[0]); From 7f74eeffbd50663b4928e6aa2e8516ce6bb72e1e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:33:34 +0000 Subject: [PATCH 0077/1502] decomp: clarify names in emit_gated_moby_joint_effects D_L13_001D3478 -> l13_starfighter_attachment_slot_indices_by_command: Retail 0x002e8934/0x002e893c binds s8 to 0x001D3478. At 0x002e8a2c-0x002e8a44 the source moby's command byte at +0xBC is checked for zero, decremented, multiplied by four, and used to load a table word. 0x002e8a38 and 0x002e8a48 compare that word with joint_effect_gate_slot_indices[i], whose word indexes emission_gate_data + 0xC4 at 0x002e8978-0x002e8988. Original Ghidra confirms the command-minus-one lookup. The authoritative same-file process_moby_attachment_damage uses D_L13_001D3478[moby->bBC - 1] as the child_slot_index argument to detach_moby_joint_attachment; that helper indexes parent_data + 0xC4 by child_slot_index*4, clears the selected child pointer and launches that attachment. Thus entries are attachment slot indices selected by command, also used to gate effects. The l13 qualifier preserves overlay ownership; the assembler label and int array declaration remain unchanged. --- src/overlays/l13/mobys/qwarks_starfighter.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l13/mobys/qwarks_starfighter.c b/src/overlays/l13/mobys/qwarks_starfighter.c index 0b6af3e419..e22f52b135 100644 --- a/src/overlays/l13/mobys/qwarks_starfighter.c +++ b/src/overlays/l13/mobys/qwarks_starfighter.c @@ -143,7 +143,7 @@ int queue_starfighter_voice_line(void *unused, return 0; } -extern int D_L13_001D3478[] __asm__("D_L13_001D3478"); +extern int l13_starfighter_attachment_slot_indices_by_command[] __asm__("D_L13_001D3478"); typedef struct { char pad[0xC4]; @@ -179,7 +179,7 @@ void emit_gated_moby_joint_effects(struct Moby *source_moby, char *emission_gate -100, 1); } else if (source_moby->command == 0 || - D_L13_001D3478[source_moby->command - 1] != + l13_starfighter_attachment_slot_indices_by_command[source_moby->command - 1] != joint_effect_gate_slot_indices[i] || random_integer_below(9) == 0) { effect_frame_count = scale_game_frames(random_int_between(0xF, 0x16)); @@ -774,7 +774,7 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { v->f118 = 0; } } else if (dd->health < hi) { - int tv = D_L13_001D3478[moby->bBC - 1]; + int tv = l13_starfighter_attachment_slot_indices_by_command[moby->bBC - 1]; if (tv != -1) { allocate_voice_for_target_entry(7, 0, moby); @@ -805,7 +805,7 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { mode = 2; if (moby->bBC == 7) { for (j = moby->bBC - 1; j < 10; j++) { - func_L13_002EAAB8_2EAE80(moby, moby_data, D_L13_001D3478[j]); + func_L13_002EAAB8_2EAE80(moby, moby_data, l13_starfighter_attachment_slot_indices_by_command[j]); } allocate_voice_for_target_entry(7, 0, moby); } @@ -866,7 +866,7 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { v->f118 = 0; } } else if (dd->health < hi) { - int tv = D_L13_001D3478[moby->bBC - 1]; + int tv = l13_starfighter_attachment_slot_indices_by_command[moby->bBC - 1]; if (tv != -1) { func_L13_002EAAB8_2EAE80(moby, moby_data, tv); @@ -897,7 +897,7 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { mode = 2; if (moby->bBC == 7) { for (k = moby->bBC - 1; k < 10; k++) { - func_L13_002EAAB8_2EAE80(moby, moby_data, D_L13_001D3478[k]); + func_L13_002EAAB8_2EAE80(moby, moby_data, l13_starfighter_attachment_slot_indices_by_command[k]); } allocate_voice_for_target_entry(7, 0, moby); } From 864dbc983b79748184ea9a60af86cbbda0c56d4c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:35:09 +0000 Subject: [PATCH 0078/1502] decomp: clarify names in FUN_L00_00261b48 a -> segment_start: Retail saves a1 in s4 at 0x00261b5c and uses it as the subtrahend for end-start at 0x00261b7c-0x00261b9c and each path point at 0x00261c0c and 0x00261c58. It is the first interpolation endpoint at 0x00261d20; callers pass the moby position. b -> segment_end: Retail saves a2 in s7 at 0x00261b54, passes it as the minuend of end-start at 0x00261b84-0x00261b9c, and as the second interpolation endpoint at 0x00261d24. Supplied callers pass the projected landing or trajectory position. c -> adjusted_endpoint: Retail preserves a3 in s8 at 0x00261b74 and passes it as the output of the final lerp at 0x00261d1c-0x00261d2c, using the smallest retained crossing fraction or one. Callers consume path_point/adjusted_position to compute corrected bolt velocity. cur -> current_path_point_slot: Source assigns cur=u, subtracts segment start from each successive path point into cur, transforms cur in place, and copies cur into prev. Retail s0 holds sp+0x40 from 0x00261c40, is the subtraction/transform destination at 0x00261c54-0x00261c70, and the quad source at 0x00261cfc. idx -> segment_path_index: At 0x00261bf4-0x00261c08 the first argument is multiplied by four and added to table 0x001b04b0 to load the SegmentPath pointer. Source uses idx for that table's count and points; spawn_randomized_bolt_drop passes its path_index. prev -> previous_path_point_slot: Source assigns prev=t and only uses prev as the destination of qcopy(prev,cur). Retail s5 is assigned sp+0x30 at 0x00261c14, and 0x00261d00 stores the current transformed quad through s5 to retain it as the previous path point for the next edge. t -> previous_path_point_in_basis: Retail 0x00261bfc-0x00261c2c fills sp+0x30 from path point zero minus segment start and transforms it using the direction basis. Source t supplies the previous endpoint coordinates for the crossing formula; 0x00261cfc-0x00261d00 replaces it with the current transformed quad each iteration. w -> perpendicular_xy_axis: Source clears w then sets w[0]=v[1], w[1]=-v[0] after flattening and normalizing end-start. Retail 0x00261bcc-0x00261bec clears sp+0x10 and stores direction Y and negated direction X there, forming the perpendicular XY basis axis. --- .../mobys/test_path_segment_strict_crossing.c | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/overlays/shared/mobys/test_path_segment_strict_crossing.c b/src/overlays/shared/mobys/test_path_segment_strict_crossing.c index 00c2491ac8..dd9cceda73 100644 --- a/src/overlays/shared/mobys/test_path_segment_strict_crossing.c +++ b/src/overlays/shared/mobys/test_path_segment_strict_crossing.c @@ -110,52 +110,52 @@ typedef struct { int FUN_L00_00261b48(int idx, void *a, void *b, void *c); -int FUN_L00_00261b48(int idx, void *a, void *b, void *c) { - float v[4], w[4], z[4], t[4], u[4]; +int FUN_L00_00261b48(int segment_path_index, void *segment_start, void *segment_end, void *adjusted_endpoint) { + float v[4], perpendicular_xy_axis[4], z[4], previous_path_point_in_basis[4], u[4]; float best; float zero; int found = 0; int i = 1; int offset; - float *prev; - float *cur; - fast_vec_sub(v, b, a); + float *previous_path_point_slot; + float *current_path_point_slot; + fast_vec_sub(v, segment_end, segment_start); v[2] = 0; fast_vec_normalize(v, v, 1.0f / fast_vec_length(v)); - clear_u64_value(w); - w[0] = v[1]; - w[1] = -v[0]; + clear_u64_value(perpendicular_xy_axis); + perpendicular_xy_axis[0] = v[1]; + perpendicular_xy_axis[1] = -v[0]; clear_u64_value(z); z[2] = 1.0f; best = 1.0f; - fast_vec_sub(t, (char *)((SegmentPath **)D_L00_001B04B0_261968)[idx] + 0x10, a); - transform_vector_by_basis(t, t, v); - prev = t; - cur = u; - if (i < ((SegmentPath **)D_L00_001B04B0_261968)[idx]->count) { + fast_vec_sub(previous_path_point_in_basis, (char *)((SegmentPath **)D_L00_001B04B0_261968)[segment_path_index] + 0x10, segment_start); + transform_vector_by_basis(previous_path_point_in_basis, previous_path_point_in_basis, v); + previous_path_point_slot = previous_path_point_in_basis; + current_path_point_slot = u; + if (i < ((SegmentPath **)D_L00_001B04B0_261968)[segment_path_index]->count) { offset = 0x20; zero = 0.0f; do { - fast_vec_sub(cur, (char *)((SegmentPath **)D_L00_001B04B0_261968)[idx] + offset, a); - transform_vector_by_basis(cur, cur, v); - if (t[3] != zero || u[3] != zero) { - if (u[1] * t[1] < 0.0f) { - float x = (t[0] - u[0]) / (t[1] - u[1]) * -u[1] + u[0]; + fast_vec_sub(current_path_point_slot, (char *)((SegmentPath **)D_L00_001B04B0_261968)[segment_path_index] + offset, segment_start); + transform_vector_by_basis(current_path_point_slot, current_path_point_slot, v); + if (previous_path_point_in_basis[3] != zero || u[3] != zero) { + if (u[1] * previous_path_point_in_basis[1] < 0.0f) { + float x = (previous_path_point_in_basis[0] - u[0]) / (previous_path_point_in_basis[1] - u[1]) * -u[1] + u[0]; if (x > 0.0f && x < best) { best = x; found = 1; - qcopy(prev, cur); + qcopy(previous_path_point_slot, current_path_point_slot); goto next; } } } - qcopy(prev, cur); + qcopy(previous_path_point_slot, current_path_point_slot); next: i++; offset += 0x10; - } while (i < ((SegmentPath **)D_L00_001B04B0_261968)[idx]->count); + } while (i < ((SegmentPath **)D_L00_001B04B0_261968)[segment_path_index]->count); } - lerp_vector(c, a, b, best); + lerp_vector(adjusted_endpoint, segment_start, segment_end, best); return found; } From 9b435fb75e30a309f33fc189c6f1fd9e5f1f9178 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:35:09 +0000 Subject: [PATCH 0079/1502] decomp: clarify names in FUN_L00_00257218_u3 idx -> pickup_candidate_index: Authoritative C initializes idx to -1 and increments it while traversing D_0015EDD0_macro in both random selection branches. Retail s0 is set to -1 at 0x00257330, incremented at 0x00257368/0x002573ac or 0x002573f4/0x00257428, and added to the candidate-list address 0x0015EDD0 before byte loads at 0x00257370-0x00257378 and 0x002573f8-0x00257400. The final indexed byte, masked to six bits, supplies the pickup item type; this is a candidate-list position rather than an item ID. m -> drop_source_moby: The prepared crate_drop_bolts caller passes crate_moby as the first argument, then spawns the returned number of pickups at crate_moby + 0x10. In retail 0x00257244-0x00257280 the first argument is null-checked and its halfword at +0xB2 selects the level object bit that gates item reselection. This is the source Moby for the drops, matching Moby257218 *m in the authoritative C. out -> pickup_item_type: Retail 0x0025722c saves the second argument in s1; 0x00257238-0x0025723c reads its existing item ID to decide whether selection is needed. At 0x002573b0-0x002573bc and 0x0025742c-0x00257438 a candidate byte masked with 0x3F (or fallback 10) is stored through that pointer. The prepared caller passes &drop_type_or_skip_spawn and then supplies the updated value to spawn_on_path as the pickup type; it is an input/output item type, not the returned drop count. --- .../mobys/evaluate_moby_animation_pose.c | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/overlays/shared/mobys/evaluate_moby_animation_pose.c b/src/overlays/shared/mobys/evaluate_moby_animation_pose.c index f4b2f0f848..240a217455 100644 --- a/src/overlays/shared/mobys/evaluate_moby_animation_pose.c +++ b/src/overlays/shared/mobys/evaluate_moby_animation_pose.c @@ -38,13 +38,13 @@ extern Item257218 D_L00_001C40B0[] NOT_SDA; int FUN_L00_00257218_u3(Moby257218 *, int *) __asm__("FUN_L00_00257218"); /* Picks the weapon whose ammo a pickup gives (*out), preferring owned weapons that are not full, and returns how many pickups to drop (1 or 2). */ -int FUN_L00_00257218_u3(Moby257218 *m, int *out) { - int i, idx, x; +int FUN_L00_00257218_u3(Moby257218 *drop_source_moby, int *pickup_item_type) { + int i, pickup_candidate_index, x; int not_full = 0, owned = 0, with_max = 0; int drops = 1; - if (*out <= 0 || - (m != 0 && (D_0014C190[D_0015ED84][(s16)m->uid >> 5] >> (m->uid & 0x1F)) & 1)) { + if (*pickup_item_type <= 0 || + (drop_source_moby != 0 && (D_0014C190[D_0015ED84][(s16)drop_source_moby->uid >> 5] >> (drop_source_moby->uid & 0x1F)) & 1)) { for (i = 0; i < 12 && D_0015EDD0_macro[i] != 0xFF; i++) { x = D_0015EDD0_macro[i] & 0x3F; if (item_available[x]) { @@ -55,29 +55,29 @@ int FUN_L00_00257218_u3(Moby257218 *m, int *out) { ((Item257218 *)(x * 0x18 + (u8 *)D_L00_001C40B0))->max_ammo; } } - idx = -1; + pickup_candidate_index = -1; if (not_full) { i = random_integer_below(not_full); while (i >= 0) { - idx++; - x = D_0015EDD0_macro[idx] & 0x3F; + pickup_candidate_index++; + x = D_0015EDD0_macro[pickup_candidate_index] & 0x3F; if (item_available[x]) i -= ((Item257218 *)(x * 0x18 + (u8 *)D_L00_001C40B0))->max_ammo > weapon_ammo_counts[x]; } - *out = D_0015EDD0_macro[idx] & 0x3F; + *pickup_item_type = D_0015EDD0_macro[pickup_candidate_index] & 0x3F; } else if (owned) { i = random_integer_below(with_max); while (i >= 0) { - idx++; - x = D_0015EDD0_macro[idx] & 0x3F; + pickup_candidate_index++; + x = D_0015EDD0_macro[pickup_candidate_index] & 0x3F; if (item_available[x] && ((Item257218 *)(x * 0x18 + (u8 *)D_L00_001C40B0))->max_ammo) i--; } - *out = D_0015EDD0_macro[idx] & 0x3F; + *pickup_item_type = D_0015EDD0_macro[pickup_candidate_index] & 0x3F; } else { - *out = 10; + *pickup_item_type = 10; } } if (random_integer_below(5) == 0) From bad15752d4a556431a7db0629541a9a8a4be0e2e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:35:18 +0000 Subject: [PATCH 0080/1502] decomp: clarify names in update_path_spark_effect D_L10_00178380 -> nearby_mobys: Authoritative C declares a struct Moby * array and passes it with the collect_mobies_in_sphere return count to send_blast_hits. Checked level-10 collector 0x001e5ed0 initializes s6 to 0x00178380 at 0x001e5f50..0x001e5f54, appends candidate Moby pointers with sw t8,0(s6) and increments s6 by four at 0x001e64a8..0x001e64ac and 0x001e66b0..0x001e66b4, terminates the array at 0x001e66c0, and returns (end-start)/4 at 0x001e6768..0x001e676c. Assigned retail caller collects at 0x002dd5dc, forms the same array address in a2 at 0x002dd5e8/0x002dd5fc, moves returned count to a3 at 0x002dd608, and calls send_blast_hits at 0x002dd624. nearby_mobys is the supplied existing spelling for this identical assembler label. --- src/overlays/l10/mobys/path_spark_effect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/path_spark_effect.c b/src/overlays/l10/mobys/path_spark_effect.c index 903fa5874a..cec39e5e72 100644 --- a/src/overlays/l10/mobys/path_spark_effect.c +++ b/src/overlays/l10/mobys/path_spark_effect.c @@ -12,7 +12,7 @@ #include "rnc/overlay/shared/math/quad.h" #include "rnc/overlay/shared/mobys/test_path_segment_strict_crossing.h" -extern struct Moby *D_L10_00178380[]; +extern struct Moby *nearby_mobys[] __asm__("D_L10_00178380"); extern int collect_mobies_in_sphere(void *, float, int, void *, void *) __asm__("FUN_L00_001f2868"); /* Advances an effect, scales its size over its lifetime and emits hits. */ /* Ported from rac1-decomp (src/overlays/l10_orxon/vendor_00296BD8.c: func_L10_002DE798), where it is exact; names translated to the US level program. */ @@ -75,7 +75,7 @@ void path_spark_effect_update(char *moby) { *(OvlQuad *)blast_hit_position = *(OvlQuad *)&MOBY(moby)->pos; send_blast_hits(effect_data->unk10, blast_hit_position, - D_L10_00178380, + nearby_mobys, count, 0, 0x810001, From 7692dcec7d933b049c9e96fcae28a7455e0094e4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:35:25 +0000 Subject: [PATCH 0081/1502] decomp: clarify names in update_gold_bolt_glow_rings D_L01_00167240 -> camera_pos: Retail 0x00308610/0x00308620 constructs address 0x00167240 in a1 for fast_vec_sub at 0x0030861c, with the glow origin at sp+0x10 as a2 and output at sp. Original Ghidra likewise calls func_0x002211b8(auStack_e0,0x167240,auStack_d0). Bound C subtracts glow_origin_position from this extern char array, normalizes the displacement by -0.3, adds the origin and emits particles along that axis at 0x0030877c, advancing it at 0x0030878c. Supplied existing_names explicitly maps this identical assembler label to camera_pos; reuse that proven spelling exactly and preserve the assembler identity. --- src/overlays/shared/pickups/gold_bolt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/pickups/gold_bolt.c b/src/overlays/shared/pickups/gold_bolt.c index a765f16a35..796e94d877 100644 --- a/src/overlays/shared/pickups/gold_bolt.c +++ b/src/overlays/shared/pickups/gold_bolt.c @@ -71,7 +71,7 @@ extern void spawn_moving_hero_relative_alpha_fade_particle( void *, void *, int, int, int, int, float) __asm__("FUN_L00_002730e0"); extern s32 D_0015ED84; -extern char D_L01_00167240[]; +extern char camera_pos[] __asm__("D_L01_00167240"); extern int D_0015ED84; /* no foreign declaration */ extern int cutscene_active __asm__("D_L01_0015F404"); extern u8 D_0014BEC0[]; @@ -683,7 +683,7 @@ void update_gold_bolt_glow_rings(struct Moby *moby) { if (1.0f < scale) scale = 1.0f; } - fast_vec_sub(glow_particle_position, D_L01_00167240, glow_origin_position); + fast_vec_sub(glow_particle_position, camera_pos, glow_origin_position); fast_vec_normalize(glow_particle_position, glow_particle_position, -0.3f); fast_vec_normalize(step, glow_particle_position, 0.1f); fast_vec_add(glow_particle_position, glow_particle_position, glow_origin_position); From 1a29ab348ef49339c90e6cbb07bd9813fb69afd0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:35:26 +0000 Subject: [PATCH 0082/1502] decomp: clarify names in hud_draw_gauge_frame e -> gauge_element: In hud_draw_gauge_frame, retail 0x00237860 retains a0 in s3; 0x00237888-0x002378a0 load its +0x50/+0x54 position and store scale dimensions at +0x58/+0x5c. The same record supplies +0x74 bar count, +0x08 divisor and the final icon ID at 0x00237a84. This proves the parameter is the gauge HUD element being drawn. st -> gauge_height_numerator: Source st = D_L00_0015F764 * 0xEA0 feeds bh = (e->unk74 * st) / (e->unk08 << 8). Retail 0x0023796c/0x0023797c multiply vertical scale by 0xEA0; 0x002379a0 multiplies that numerator by count and 0x002379c8 divides by capacity shifted eight before subtracting from the bar's lower y. The first rectangle uses the same scale*0xEA0 divided by 256 at 0x0023794c-0x00237954, proving this is the full gauge-height numerator. --- .../ui/hud/draw_hud_item_selector_panel.c | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c index 60f7f41f35..4a5fb183e8 100644 --- a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c +++ b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c @@ -71,58 +71,58 @@ extern void append_screen_rect_packet(s32, s32, s32, s32, u64, s32) __asm__("fun int hud_draw_gauge_frame(HudElem_237840 *e) __asm__("FUN_L00_00237840"); -int hud_draw_gauge_frame(HudElem_237840 *e) { +int hud_draw_gauge_frame(HudElem_237840 *gauge_element) { int pos[2]; int left, top, right, bottom, w, h, bh, step, i; { int ww = D_L00_0015F760; - pos[0] = e->unk50; - pos[1] = e->unk54; - e->w = ww; + pos[0] = gauge_element->unk50; + pos[1] = gauge_element->unk54; + gauge_element->w = ww; { int *src = (int *)&(*(short *)&D_L00_0015F764); - int *dst = &e->h; + int *dst = &gauge_element->h; __builtin_memcpy(dst, src, 4); } } - hud_screen_position(e, &pos[0], &pos[1]); - apply_hud_slide_offset(e, &pos[0], &pos[1], e->unk6C, 0); + hud_screen_position(gauge_element, &pos[0], &pos[1]); + apply_hud_slide_offset(gauge_element, &pos[0], &pos[1], gauge_element->unk6C, 0); w = D_L00_0015F760 * 0xD0; h = D_L00_0015F764 * 0xA0; bh = D_L00_0015F760 * 0x260; bottom = D_L00_0015F764 * 0xEA0; - left = (pos[0] + e->unk48) << 4; - top = (pos[1] + e->unk4A) << 4; + left = (pos[0] + gauge_element->unk48) << 4; + top = (pos[1] + gauge_element->unk4A) << 4; left += w / 64; top += h / 256; right = left + bh / 64; bottom = top + bottom / 256; append_screen_rect_packet(left, top, right, bottom, 0x80000000, 1); { - int st = D_L00_0015F764 * 0xEA0; + int gauge_height_numerator = D_L00_0015F764 * 0xEA0; h = D_L00_0015F764; - top = (pos[1] + e->unk4A) << 4; + top = (pos[1] + gauge_element->unk4A) << 4; top += (h * 0xF40) / 256; - bh = (e->unk74 * st) / (e->unk08 << 8); + bh = (gauge_element->unk74 * gauge_height_numerator) / (gauge_element->unk08 << 8); append_screen_rect_packet(left, top, right, top - bh, 0x80829E00, 1); } i = 1; - if (i < e->unk74) + if (i < gauge_element->unk74) do { int hh = D_L00_0015F764; - top = (pos[1] + e->unk4A) << 4; + top = (pos[1] + gauge_element->unk4A) << 4; top += (hh * 0xF40) / 256; step = D_L00_0015F764 * 0xEA0; - step = i * step / (e->unk08 << 8); + step = i * step / (gauge_element->unk08 << 8); i++; top -= step; top -= 16; append_screen_rect_packet(left, top, right, top + 32, 0x80000000, 1); - } while (i < e->unk74); - w = get_icon_frame(*(int *)e, 0); + } while (i < gauge_element->unk74); + w = get_icon_frame(*(int *)gauge_element, 0); draw_rotated_hud_sprite( - w, pos[0] + e->unk48, pos[1] + e->unk4A, D_L00_0015F760, D_L00_0015F764, 0x80); - return e->w; + w, pos[0] + gauge_element->unk48, pos[1] + gauge_element->unk4A, D_L00_0015F760, D_L00_0015F764, 0x80); + return gauge_element->w; } typedef struct { From 841e787f44d020ad80aefe3fd4c7485ce4b79167 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:35:34 +0000 Subject: [PATCH 0083/1502] decomp: clarify names in door_left_update D_L01_00167240 -> camera_pos: In source DOOR_OPEN, vector_distance_xy(door_vars, D_L01_00167240) must exceed door_vars->radius * 1.1f along with the hero-position distance before closing. Retail 0x002fee90 loads a1 high half 0x16 and 0x002fee9c adds 0x7240 for the distance call at 0x002fee98; 0x002feea0-0x002feeb0 compares that distance to radius*1.1. Original Ghidra likewise passes 0x167240 as the second position target. The supplied naming context explicitly identifies camera_pos as the existing proven name for this identical assembler label; reuse it exactly, preserving the u8 array declaration and assembler identity. --- src/overlays/l01/mobys/door_left.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l01/mobys/door_left.c b/src/overlays/l01/mobys/door_left.c index 4c181547aa..2df788eed7 100644 --- a/src/overlays/l01/mobys/door_left.c +++ b/src/overlays/l01/mobys/door_left.c @@ -6,7 +6,7 @@ extern s32 FUN_0022da68(s32, s32, void *); extern f32 scale_time(f32) __asm__("FUN_001f96b0"); -extern u8 D_L01_00167240[]; +extern u8 camera_pos[] __asm__("D_L01_00167240"); #include "qcopy.h" @@ -73,7 +73,7 @@ void door_left_update(HoverMoby *door_moby) { case DOOR_OPEN: k = 1.1f; if (vector_distance_xy(door_vars, &hero.motion.pos) > door_vars->radius * k && - vector_distance_xy(door_vars, D_L01_00167240) > door_vars->radius * k) { + vector_distance_xy(door_vars, camera_pos) > door_vars->radius * k) { door_moby->state = 4; if (door_moby->oclass == 0x300) { FUN_0022da68(0, 0, door_moby); From cdad478afff162e8bcd53b4f700752bd4688f0ec Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:35:42 +0000 Subject: [PATCH 0084/1502] decomp: clarify names in fighter_jet_update D_L01_00167240 -> camera_pos: Retail 0x002f4484 sets s3=moby+0x10; 0x002f4488-0x002f4494 passes address 0x00167240 as a1 and the moby position as a0 to the distance helper. Ghidra shows func_0x00221360(iVar3+0x10,0x167240), matching fast_vec_dist(moby+0x10,D_L01_00167240) in the SHA-bound source. The returned distance enters the scale interpolation at 0x002f44c0, then scales the moby and path speed at 0x002f44ec-0x002f4504. Supplied identical-label existing_names and retail annotation identify this operand as camera_pos; reuse that exact spelling and preserve the char-array declaration and assembler identity. --- src/overlays/l01/mobys/fighter_jet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l01/mobys/fighter_jet.c b/src/overlays/l01/mobys/fighter_jet.c index e821e7e079..acc786908c 100644 --- a/src/overlays/l01/mobys/fighter_jet.c +++ b/src/overlays/l01/mobys/fighter_jet.c @@ -36,7 +36,7 @@ extern void spawn_explosion(void *, /* Ported from rac1-decomp (src/overlays/l01_novalis/vendor_002BA898.c: func_L01_002F5800), where it is exact; names translated to the US level program. */ -extern char D_L01_00167240[]; +extern char camera_pos[] __asm__("D_L01_00167240"); extern short fighter_jet_minimum_distance_scale_gp __asm__("D_L01_00161AF4") __attribute__((sda)); extern short fighter_jet_minimum_scale_camera_distance_gp __asm__("D_L01_00161AF8") __attribute__((sda)); @@ -78,7 +78,7 @@ void fighter_jet_update(char *moby) { *(float *)(fighter_jet_vars + 0x174) = *(float *)(fighter_jet_vars + 0xFC); } { - float camera_distance = fast_vec_dist(moby + 0x10, D_L01_00167240); + float camera_distance = fast_vec_dist(moby + 0x10, camera_pos); float min_scale = *(float *)&fighter_jet_minimum_distance_scale_gp; float near_dist = *(float *)&fighter_jet_full_scale_camera_distance_gp; float slope = -((1.0f - min_scale) / From 3f78367fb025d3d55b845b326bb5601d4ad00a64 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:35:42 +0000 Subject: [PATCH 0085/1502] decomp: clarify names in grant_inventory_item t -> item_slot: In the authoritative src/overlays/shared/game/unlock_planet.c snapshot (SHA-256 4cf603e930a4ba21c8ed4ceba08bc6adf654329aa01f7cc092e9e29afe07e634), int t is assigned item_defs_lui[id].slot. Retail 0x002609b0-0x002609bc computes 0x00179ac0 + id*0x4c and loads its word at +8 into v1, corroborated by the original Ghidra (&DAT_00179ac8)[param_1*0x13] load. Comparisons at 0x002609c0, 0x002609d4 and 0x002609e8 test this slot against 0, 3 and 2 to route id into 0x00141408, 0x00141414 and 0x00141410. Thus item_slot describes the loaded ItemDef slot, without assigning unproven category names. --- src/overlays/shared/game/unlock_planet.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/game/unlock_planet.c b/src/overlays/shared/game/unlock_planet.c index c1dd42487c..0e2254e7f3 100644 --- a/src/overlays/shared/game/unlock_planet.c +++ b/src/overlays/shared/game/unlock_planet.c @@ -440,12 +440,12 @@ void grant_inventory_item(int id, int flag) { } } if (flag != 0) { - int t = item_defs_lui[id].slot; - if (t == 0) { + int item_slot = item_defs_lui[id].slot; + if (item_slot == 0) { D_00141408 = id; - } else if (t == 3) { + } else if (item_slot == 3) { D_00141414 = id; - } else if (t == 2) { + } else if (item_slot == 2) { D_00141410 = id; } } From 0ebda63327ee7016062c570c187cf28ada7168cb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:40:26 +0000 Subject: [PATCH 0086/1502] decomp: clarify names in update_drek_fight_missile_wander_movement D_L18_00162214_gp -> l18_drek_missile_wander_horizontal_speed_gp: Retail 0x002f0198 and 0x002f01c4 load the same float at gp-0x49ec (source assembler binding D_L18_00162214). At 0x002f01a0-0x002f01b4 and 0x002f01d0-0x002f01dc it is multiplied by frame_time and cosine/sine of moby yaw, then added to moby+0x10/+0x14 (position X/Y). The original Ghidra fGpffffb614 expressions and authoritative update_drek_fight_missile_wander_movement source agree: it is horizontal wander speed. The source WANDER-to-DIVE transition also stores these same cosine/sine times speed times frame_time components at pvars+0x130/+0x134, retaining wander motion for dive interpolation. Preserve extern short, SDA attribute and assembler label D_L18_00162214. --- src/overlays/l18/mobys/drek_fight_missile.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l18/mobys/drek_fight_missile.c b/src/overlays/l18/mobys/drek_fight_missile.c index 683a4696b5..2361a69d51 100644 --- a/src/overlays/l18/mobys/drek_fight_missile.c +++ b/src/overlays/l18/mobys/drek_fight_missile.c @@ -163,9 +163,9 @@ void drek_fight_missile_update(struct Moby *moby) { } moby->state = 3; missile_vars->unk130[0] = - fast_cos(moby->rot.z) * (*(float *)&D_L18_00162214_gp * frame_time); + fast_cos(moby->rot.z) * (*(float *)&l18_drek_missile_wander_horizontal_speed_gp * frame_time); missile_vars->unk130[1] = - fast_sin(moby->rot.z) * (*(float *)&D_L18_00162214_gp * frame_time); + fast_sin(moby->rot.z) * (*(float *)&l18_drek_missile_wander_horizontal_speed_gp * frame_time); missile_vars->unk130[2] = missile_vars->unk144; missile_vars->unk14C = 0; break; @@ -310,8 +310,8 @@ int update_drek_fight_missile_wander_movement(char *moby, float *wander_target_p *(float *)(missile_vars + 0x150), *(float *)(missile_vars + 0x150), *(float *)(missile_vars + 0x154)); - MOBY(moby)->pos.x += fast_cos(MOBY(moby)->rot.z) * (*(float *)&D_L18_00162214_gp * frame_time); - MOBY(moby)->pos.y += fast_sin(MOBY(moby)->rot.z) * (*(float *)&D_L18_00162214_gp * frame_time); + MOBY(moby)->pos.x += fast_cos(MOBY(moby)->rot.z) * (*(float *)&l18_drek_missile_wander_horizontal_speed_gp * frame_time); + MOBY(moby)->pos.y += fast_sin(MOBY(moby)->rot.z) * (*(float *)&l18_drek_missile_wander_horizontal_speed_gp * frame_time); FUN_00213f38_c((float *)&MOBY(moby)->pos.z, (float *)(missile_vars + 0x144), wander_target_position[2], From 00830a2ea1fac5b715d735184491c56d4a43f1ad Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:40:36 +0000 Subject: [PATCH 0087/1502] decomp: clarify names in update_bubble_motion_and_scale D_L11_00162414 -> l11_bubble_shrink_effect_randomization_scale: Authoritative bubble.c SHA-256 97c1e269aaaa81bf6de20d15a00fd5e2ffdf149fc4d96ca9f53f2795262ac619 passes *(float *)&D_L11_00162414 as the shrinking-state effect spawner's third argument. Retail 0031acb8 loads gp-0x47ec into f12 before jal 00294450 at 0031acc4. Checked level-11 helper instructions save f12 in f20 at 00294474, generate a random factor with 0.75f and 1.25f arguments at 002944b0-002944d0, multiply that result by f20 at 002944d8, and store it at 002944f0 to effect+0x20+0xc. This matches supplied FUN_L00_0026f080 C particle_data[3] = random_float_between(0.75f, 1.25f) * x, proving the bubble shrink effect randomization scale without assigning an unsupported rendered property. --- src/overlays/l11/mobys/bubble.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l11/mobys/bubble.c b/src/overlays/l11/mobys/bubble.c index 3609ad208d..0edbafb6cb 100644 --- a/src/overlays/l11/mobys/bubble.c +++ b/src/overlays/l11/mobys/bubble.c @@ -46,7 +46,7 @@ extern short bubble_horizontal_deceleration_gp __asm__("D_L11_00162408") __attri extern short bubble_surface_crossing_velocity_scale_gp __asm__("D_L11_0016240C") __attribute__((sda)); extern short bubble_spark_spawn_random_limit_gp __asm__("D_L11_00162410") __attribute__((sda)); -extern short D_L11_00162414 __attribute__((sda)); +extern short l11_bubble_shrink_effect_randomization_scale __asm__("D_L11_00162414") __attribute__((sda)); extern short bubble_shrink_effect_color_range_start_gp __asm__("D_L11_00162418") __attribute__((sda)); extern short bubble_shrink_effect_color_range_end_gp __asm__("D_L11_0016241C") __attribute__((sda)); @@ -103,7 +103,7 @@ void bubble_update(struct Moby *bubble_moby) { randomized_effect_vector[2] = absolute_float(randomized_effect_vector[2]); spawned_effect = func_L00_0026FF20_p(&bubble_moby->pos, randomized_effect_vector, - *(float *)&D_L11_00162414, + *(float *)&l11_bubble_shrink_effect_randomization_scale, *bubble_vars->unk24); if (spawned_effect != 0) { *(int *)(spawned_effect + 4) = From 24a4e34f1712624539014ae5cc6d405b59059ff7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:40:45 +0000 Subject: [PATCH 0088/1502] decomp: clarify names in spawn_floating_platform_sparks D_L18_00161A6C_gp -> l18_floating_platform_spark_second_vector_length_base_rate_gp: In the authoritative floating_platform.c snapshot SHA-256 2d280fa05b6e89880b2178d82b4f23cecb5513e3574c2c5d83f04de0cd946e10, this sole listed global is reinterpreted as float and multiplied by (random_float_between(-relative_variation_limit, relative_variation_limit)+1.0f) and frame_time for fast_vec_normalize(second_spark_vector, first_spark_vector, length). Retail 0x002d8a0c-0x002d8a18 produces that relative factor; 0x002d8a1c loads the global from -0x5194(gp), 0x002d8a30 multiplies it by the factor, and 0x002d8a34/0x002d8a38 calls the vector helper with the frame-time-scaled length. s6=sp+0x40 is the destination and s4=sp+0x30 is the source. Original Ghidra likewise shows fGpffffae6c*(fVar7+1.0)*fRam0015ed6c constructing auStack_e0 from auStack_f0. The later independent Z subtraction at 0x002d8a44-0x002d8a60 bounds this name to the second vector's base length rate. --- src/overlays/l18/mobys/floating_platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/floating_platform.c b/src/overlays/l18/mobys/floating_platform.c index 7ca81bfd98..54199233a4 100644 --- a/src/overlays/l18/mobys/floating_platform.c +++ b/src/overlays/l18/mobys/floating_platform.c @@ -268,7 +268,7 @@ spawn_spark(void *, void *, void *, int, int, int, int, int, int) __asm__("FUN_0 extern int FUN_001fa6e0(int, int, float); extern short floating_platform_spark_first_vector_length_base_rate_gp __asm__("D_L18_00161A68") __attribute__((sda)); -extern short D_L18_00161A6C_gp __asm__("D_L18_00161A6C") __attribute__((sda)); +extern short l18_floating_platform_spark_second_vector_length_base_rate_gp __asm__("D_L18_00161A6C") __attribute__((sda)); extern short floating_platform_spark_second_vector_downward_z_rate_gp __asm__("D_L18_00161A70") __attribute__((sda)); extern short @@ -348,7 +348,7 @@ void spawn_floating_platform_sparks(struct Moby *moby) { fast_vec_normalize( second_spark_vector, first_spark_vector, - (*(float *)&(D_L18_00161A6C_gp)) * + (*(float *)&(l18_floating_platform_spark_second_vector_length_base_rate_gp)) * (random_float_between( -(*(float *)&( floating_platform_spark_vector_length_relative_variation_limit_gp)), From 8cc37383ab26eb47140a18af0dd4da42533c29b7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:44:46 +0000 Subject: [PATCH 0089/1502] decomp: clarify names in emit_moby_particles D_L10_00161E74 -> l10_toxic_crab_particle_group_count: Retail 0x002e3a90 loads gp-0x4d8c once and saves it at sp+0x58; 0x002e3d90..0x002e3d9c compares the outer iteration against it. Each iteration constructs a shared emission position and velocity for the inner particle group. D_L10_00161E78 -> l10_toxic_crab_particles_per_group: Retail 0x002e3c50 loads gp-0x4d88 to gate the inner loop; 0x002e3d80..0x002e3d88 rereads it and compares the counter incremented at 0x002e3c90. Each inner iteration calls spawn_spark once at 0x002e3d78. D_L10_00161E7C -> l10_toxic_crab_particle_group_position_jitter: Retail 0x002e3b34..0x002e3b38 passes gp-0x4d84 to the checked random xyz offset helper immediately after copying the moby position and before the inner particle loop; source uses D_L10_00161E7C for that bound. D_L10_00161E80 -> l10_toxic_crab_particle_position_jitter: Retail 0x002e3ca4 loads gp-0x4d80 and 0x002e3cb0 calls the xyz offset helper on sp+0x10 within each spark iteration. Source adds this random bound cumulatively to pos. D_L10_00161E84 -> l10_toxic_crab_particle_adjusted_velocity_jitter: Retail 0x002e3cb8 loads gp-0x4d7c, multiplies it by D_0015ED6C at 0x002e3ccc, and calls the random xyz offset helper on the adjusted velocity at sp+0x30, before passing it to spawn_spark. D_L10_00161E88 -> l10_toxic_crab_particle_speed_lower_bound: Retail 0x002e3b4c loads gp-0x4d78 into f12 for random_float_between at 0x002e3b54; the returned speed feeds both cos and sin horizontal velocity products at 0x002e3bb4..0x002e3bec. This is the first, lower-bound parameter. D_L10_00161E8C -> l10_toxic_crab_particle_speed_upper_bound: Retail 0x002e3b58 loads gp-0x4d74 into f13 as the second bound of random_float_between at 0x002e3b54; its sampled speed supplies both horizontal velocity components in 0x002e3bb4..0x002e3bec. D_L10_00161E90 -> l10_toxic_crab_particle_rise_lower_bound: Retail 0x002e3b5c loads gp-0x4d70 as the first random_float_between bound; the sample retained in f21 is scaled by D_0015ED6C and stored as velocity z at 0x002e3bd4..0x002e3bf0. D_L10_00161E94 -> l10_toxic_crab_particle_rise_upper_bound: Retail 0x002e3b68 loads gp-0x4d6c as the second random_float_between bound; the returned rise is optionally reduced for state 11, then multiplied by D_0015ED6C to form velocity z at 0x002e3bd4. D_L10_00161E98 -> l10_toxic_crab_particle_vertical_velocity_drop_scale: Retail 0x002e3c2c loads gp-0x4d68; 0x002e3c4c..0x002e3c58 multiplies it by D_0015ED70 and float(scale_game_frames(D_L10_00161EB8)), then subtracts that product from copied velocity z. The name describes this proven drop coefficient. D_L10_00161EA4 -> l10_toxic_crab_particle_start_color_a: Retail 0x002e3cdc loads gp-0x4d5c as the first color input to tween helper 0x001f3900 at 0x002e3ce4. Its output in s3 becomes start_color, passed in a3 at 0x002e3d58; checked spark helper stores it at particle+4 and +0x28. D_L10_00161EA8 -> l10_toxic_crab_particle_end_color_a: Retail 0x002e3d08 loads gp-0x4d58 as the first color input to the second tween at 0x002e3d04; its output in s2 becomes end_color and is passed in t0 at 0x002e3d60. Checked spark helper stores it at particle+0x2c. D_L10_00161EAC -> l10_toxic_crab_particle_start_color_b: Retail 0x002e3ce8 loads gp-0x4d54 as the second color input to the first tween at 0x002e3ce4. The independent random 0..1 factor selects between this and D_L10_00161EA4 for the source start_color passed to spawn_spark. D_L10_00161EB0 -> l10_toxic_crab_particle_end_color_b: Retail 0x002e3cfc loads gp-0x4d50 as the second color input to the second tween at 0x002e3d04. The random 0..1 factor interpolates this with D_L10_00161EA8 to form source end_color, passed to spawn_spark in t0. D_L10_00161EB4 -> l10_toxic_crab_particle_life_frames: Retail 0x002e3d0c..0x002e3d14 passes gp-0x4d4c through scale_game_frames; output saved in s1 is the source life passed in t1 at 0x002e3d64. Checked spark helper stores that timing value at particle+0xa and +0x30. D_L10_00161EB8 -> l10_toxic_crab_particle_fade_frames: Retail 0x002e3d18..0x002e3d20 scales gp-0x4d48 into source fade, passed in t2 at 0x002e3d68 and stored at particle+0x32 by the checked spark helper. The same scaled interval also weights the copied velocity z drop at 0x002e3c24..0x002e3c58. D_L10_00161EBC -> l10_toxic_crab_particle_random_duration_base: Retail 0x002e3d24..0x002e3d40 converts gp-0x4d44 int to float and samples between base*0.5 and base*2.5. It then applies scale_time and truncation before passing the duration in t3; checked spark helper stores it at particle+0x34. accel -> adjusted_particle_velocity: Retail 0x002e3c10..0x002e3c18 copies the velocity quadword to sp+0x30; 0x002e3c2c..0x002e3c60 subtracts a duration-scaled vertical term, and 0x002e3cc8 jitters xyz before passing it as the third spark argument. This proves adjusted velocity construction, not a pure acceleration vector. src -> moby_position_source: Retail 0x002e3b04 forms moby+0x10 and stores it at sp+0x60; 0x002e3b28..0x002e3b30 copies that position quadword to the emission position. Source assigns src=&moby->pos. vars -> particle_moby_data: Retail 0x002e3ae0 reads moby+0x78 (pvars), saved at sp+0x54; 0x002e3bd0..0x002e3bf4 uses its +0x70 motion vector, half-scaled and added to emitted particle velocity. vel -> particle_velocity: Retail 0x002e3ba0..0x002e3bf8 forms xyz from cos/sin(angle)*speed and rise, then 0x002e3c08 adds half the moby motion in xy. This vector at sp+0x20 is the second spawn_spark argument at 0x002e3d74. --- src/overlays/l10/mobys/toxic_crab.c | 94 ++++++++++++++--------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/src/overlays/l10/mobys/toxic_crab.c b/src/overlays/l10/mobys/toxic_crab.c index bddbea3c42..67d252a471 100644 --- a/src/overlays/l10/mobys/toxic_crab.c +++ b/src/overlays/l10/mobys/toxic_crab.c @@ -833,25 +833,25 @@ void toxic_crab_update(Moby2E30F8 *m) { } } -extern int D_L10_00161E74 __attribute__((sda)); -extern int D_L10_00161E78 __attribute__((sda)); -extern float D_L10_00161E7C __attribute__((sda)); -extern float D_L10_00161E80 __attribute__((sda)); -extern float D_L10_00161E84 __attribute__((sda)); -extern float D_L10_00161E88 __attribute__((sda)); -extern float D_L10_00161E8C __attribute__((sda)); -extern float D_L10_00161E90 __attribute__((sda)); -extern float D_L10_00161E94 __attribute__((sda)); -extern float D_L10_00161E98 __attribute__((sda)); +extern int l10_toxic_crab_particle_group_count __asm__("D_L10_00161E74") __attribute__((sda)); +extern int l10_toxic_crab_particles_per_group __asm__("D_L10_00161E78") __attribute__((sda)); +extern float l10_toxic_crab_particle_group_position_jitter __asm__("D_L10_00161E7C") __attribute__((sda)); +extern float l10_toxic_crab_particle_position_jitter __asm__("D_L10_00161E80") __attribute__((sda)); +extern float l10_toxic_crab_particle_adjusted_velocity_jitter __asm__("D_L10_00161E84") __attribute__((sda)); +extern float l10_toxic_crab_particle_speed_lower_bound __asm__("D_L10_00161E88") __attribute__((sda)); +extern float l10_toxic_crab_particle_speed_upper_bound __asm__("D_L10_00161E8C") __attribute__((sda)); +extern float l10_toxic_crab_particle_rise_lower_bound __asm__("D_L10_00161E90") __attribute__((sda)); +extern float l10_toxic_crab_particle_rise_upper_bound __asm__("D_L10_00161E94") __attribute__((sda)); +extern float l10_toxic_crab_particle_vertical_velocity_drop_scale __asm__("D_L10_00161E98") __attribute__((sda)); extern float D_L10_00161E9C __attribute__((sda)); extern float D_L10_00161EA0 __attribute__((sda)); -extern int D_L10_00161EA4 __attribute__((sda)); -extern int D_L10_00161EA8 __attribute__((sda)); -extern int D_L10_00161EAC __attribute__((sda)); -extern int D_L10_00161EB0 __attribute__((sda)); -extern int D_L10_00161EB4 __attribute__((sda)); -extern int D_L10_00161EB8 __attribute__((sda)); -extern int D_L10_00161EBC __attribute__((sda)); +extern int l10_toxic_crab_particle_start_color_a __asm__("D_L10_00161EA4") __attribute__((sda)); +extern int l10_toxic_crab_particle_end_color_a __asm__("D_L10_00161EA8") __attribute__((sda)); +extern int l10_toxic_crab_particle_start_color_b __asm__("D_L10_00161EAC") __attribute__((sda)); +extern int l10_toxic_crab_particle_end_color_b __asm__("D_L10_00161EB0") __attribute__((sda)); +extern int l10_toxic_crab_particle_life_frames __asm__("D_L10_00161EB4") __attribute__((sda)); +extern int l10_toxic_crab_particle_fade_frames __asm__("D_L10_00161EB8") __attribute__((sda)); +extern int l10_toxic_crab_particle_random_duration_base __asm__("D_L10_00161EBC") __attribute__((sda)); extern void add_random_offset_to_vector_xyz(void *, float) __asm__("FUN_L00_0025f8e0"); extern int fast_tween_color_3a90(int, int, float) __asm__("FUN_001fa6e0"); @@ -859,13 +859,13 @@ void emit_moby_particles(struct Moby *moby) __asm__("FUN_L10_002e3a90"); void emit_moby_particles(struct Moby *moby) { float pos[4]; - float vel[4]; - float accel[4]; + float particle_velocity[4]; + float adjusted_particle_velocity[4]; float push[4]; - char *vars; + char *particle_moby_data; int count; float *pos_ptr; - void *src; + void *moby_position_source; int i; int j; float angle; @@ -878,46 +878,46 @@ void emit_moby_particles(struct Moby *moby) { int life; int fade; - count = D_L10_00161E74; - vars = (char *)moby->pvars; + count = l10_toxic_crab_particle_group_count; + particle_moby_data = (char *)moby->pvars; for (i = 0; i < count; i++) { pos_ptr = pos; - src = &moby->pos; - qcopy_nc(pos, src); - add_random_offset_to_vector_xyz(pos_ptr, D_L10_00161E7C); + moby_position_source = &moby->pos; + qcopy_nc(pos, moby_position_source); + add_random_offset_to_vector_xyz(pos_ptr, l10_toxic_crab_particle_group_position_jitter); pos[2] += 0.55f; angle = random_angle_radians(); - speed = random_float_between(D_L10_00161E88, D_L10_00161E8C); - rise = random_float_between(D_L10_00161E90, D_L10_00161E94); + speed = random_float_between(l10_toxic_crab_particle_speed_lower_bound, l10_toxic_crab_particle_speed_upper_bound); + rise = random_float_between(l10_toxic_crab_particle_rise_lower_bound, l10_toxic_crab_particle_rise_upper_bound); if (*((u8 *)moby + 0x20) == 11) { speed *= 0.55f; rise *= 0.55f; pos[2] -= 0.2f; } - vel[0] = fast_cos(angle) * (speed * D_0015ED6C); - vel[1] = fast_sin(angle) * (speed * D_0015ED6C); - vel[2] = 0.0f + rise * D_0015ED6C; - fast_vec_scale(push, vars + 0x70, 0.5f); + particle_velocity[0] = fast_cos(angle) * (speed * D_0015ED6C); + particle_velocity[1] = fast_sin(angle) * (speed * D_0015ED6C); + particle_velocity[2] = 0.0f + rise * D_0015ED6C; + fast_vec_scale(push, particle_moby_data + 0x70, 0.5f); push[2] = 0.0f; - fast_vec_add(vel, vel, push); - qcopy(accel, vel); - accel[2] -= D_L10_00161E98 * D_0015ED70 * (float)scale_game_frames(D_L10_00161EB8); - for (j = 0; j < D_L10_00161E78; j++) { + fast_vec_add(particle_velocity, particle_velocity, push); + qcopy(adjusted_particle_velocity, particle_velocity); + adjusted_particle_velocity[2] -= l10_toxic_crab_particle_vertical_velocity_drop_scale * D_0015ED70 * (float)scale_game_frames(l10_toxic_crab_particle_fade_frames); + for (j = 0; j < l10_toxic_crab_particles_per_group; j++) { size = random_float_between(0.5f, 1.5f); - vel[3] = size * D_L10_00161E9C; - accel[3] = size * D_L10_00161EA0; - add_random_offset_to_vector_xyz(pos, D_L10_00161E80); - add_random_offset_to_vector_xyz(accel, D_L10_00161E84 * D_0015ED6C); + particle_velocity[3] = size * D_L10_00161E9C; + adjusted_particle_velocity[3] = size * D_L10_00161EA0; + add_random_offset_to_vector_xyz(pos, l10_toxic_crab_particle_position_jitter); + add_random_offset_to_vector_xyz(adjusted_particle_velocity, l10_toxic_crab_particle_adjusted_velocity_jitter * D_0015ED6C); start_color = fast_tween_color_3a90( - D_L10_00161EA4, D_L10_00161EAC, random_float_between(0.0f, 1.0f)); + l10_toxic_crab_particle_start_color_a, l10_toxic_crab_particle_start_color_b, random_float_between(0.0f, 1.0f)); end_color = fast_tween_color_3a90( - D_L10_00161EA8, D_L10_00161EB0, random_float_between(0.0f, 1.0f)); - life = scale_game_frames(D_L10_00161EB4); - fade = scale_game_frames(D_L10_00161EB8); - time_base = (float)D_L10_00161EBC; + l10_toxic_crab_particle_end_color_a, l10_toxic_crab_particle_end_color_b, random_float_between(0.0f, 1.0f)); + life = scale_game_frames(l10_toxic_crab_particle_life_frames); + fade = scale_game_frames(l10_toxic_crab_particle_fade_frames); + time_base = (float)l10_toxic_crab_particle_random_duration_base; spawn_spark(pos, - vel, - accel, + particle_velocity, + adjusted_particle_velocity, start_color, end_color, life, From 285b3a22f123e8ff68703071e319848cec243fb2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:44:57 +0000 Subject: [PATCH 0090/1502] decomp: clarify names in spawn_turret_rocket D_L08_00161D08_gp -> l08_turret_rocket_spark_first_frame_count_base: With retail GP 0x166c00, 0x002e80d0 loads signed integer bits from 0x00161d08; 0x002e80d4 converts to float and 0x002e80d8-0x002e80ec randomizes between this base and 1.2 times it, scales frames through 0x00211a20 and truncates. The result reaches t1 at 0x002e814c for spawn_spark 0x00273228. Helper 0x0027324c preserves t1 in s6 and 0x00273330/0x002733b4 store it to particle+0x0a/+0x30. Source agrees through particle_frame_count in both spawn and trail emission. Name asserts first base frame count only; preserve assembler D_L08_00161D08. D_L08_00161D0C_gp -> l08_turret_rocket_spark_second_frame_count_base: Retail 0x002e80f0 loads GP-0x4ef4 = 0x00161d0c as integer bits, 0x002e80f4 converts them and 0x002e80fc-0x002e8110 randomizes from this base to 1.2 times it, frame-scales and truncates. The result passes in t2 at 0x002e8154 to spark helper 0x00273228. Helper 0x0027327c saves t2; 0x002733b8-0x002733bc stores it to particle+0x32, between the first and third count fields. Source particle_second_frame_count confirms this use in creation and trail emission. Preserve assembler D_L08_00161D0C; no phase semantics asserted. D_L08_00161D10_gp -> l08_turret_rocket_spark_third_frame_count_base: Retail 0x002e8114 loads GP-0x4ef0 = 0x00161d10 as integer bits, 0x002e8118 converts them and 0x002e8128-0x002e813c randomizes from this base to 1.5 times it, frame-scales through 0x00211a20 and truncates through 0x00212dd0. Result passes in t3 at 0x002e8158. Spark helper 0x00273244 saves t3 in s7 and 0x002733a8 stores it to particle+0x34, the third adjacent count field. Source particle_third_frame_count agrees in creation and trail emission. Preserve assembler D_L08_00161D10; phase meaning remains uncertain. --- src/overlays/shared/weapons/turret_rocket.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/weapons/turret_rocket.c b/src/overlays/shared/weapons/turret_rocket.c index 540cf61e05..2751948213 100644 --- a/src/overlays/shared/weapons/turret_rocket.c +++ b/src/overlays/shared/weapons/turret_rocket.c @@ -151,13 +151,13 @@ char *spawn_turret_rocket(int firing_moby, float *position, float *rotation, int 1, 20000.0f); particle_frame_count = truncate_float_to_s32(FUN_L08_00211a20(random_float_between( - (float)D_L08_00161D08_gp, (float)D_L08_00161D08_gp * 1.2f))); + (float)l08_turret_rocket_spark_first_frame_count_base, (float)l08_turret_rocket_spark_first_frame_count_base * 1.2f))); particle_second_frame_count = truncate_float_to_s32(FUN_L08_00211a20(random_float_between( - (float)D_L08_00161D0C_gp, (float)D_L08_00161D0C_gp * 1.2f))); + (float)l08_turret_rocket_spark_second_frame_count_base, (float)l08_turret_rocket_spark_second_frame_count_base * 1.2f))); particle_third_frame_count = truncate_float_to_s32(FUN_L08_00211a20(random_float_between( - (float)D_L08_00161D10_gp, (float)D_L08_00161D10_gp * 1.5f))); + (float)l08_turret_rocket_spark_third_frame_count_base, (float)l08_turret_rocket_spark_third_frame_count_base * 1.5f))); spawn_spark(&MOBY(moby)->pos, velocity_ptr, offset_ptr, @@ -221,11 +221,11 @@ void turret_rocket_update(char *moby) { offset[3] = homing_projectile_trail_secondary_motion_w_gp; i++; particle_frame_count = truncate_float_to_s32(scale_game_frames_002e8210( - random_float_between((float)D_L08_00161D08_gp, (float)D_L08_00161D08_gp * 1.2f))); + random_float_between((float)l08_turret_rocket_spark_first_frame_count_base, (float)l08_turret_rocket_spark_first_frame_count_base * 1.2f))); particle_second_frame_count = truncate_float_to_s32(scale_game_frames_002e8210( - random_float_between((float)D_L08_00161D0C_gp, (float)D_L08_00161D0C_gp * 1.2f))); + random_float_between((float)l08_turret_rocket_spark_second_frame_count_base, (float)l08_turret_rocket_spark_second_frame_count_base * 1.2f))); particle_third_frame_count = truncate_float_to_s32(scale_game_frames_002e8210( - random_float_between((float)D_L08_00161D10_gp, (float)D_L08_00161D10_gp * 1.5f))); + random_float_between((float)l08_turret_rocket_spark_third_frame_count_base, (float)l08_turret_rocket_spark_third_frame_count_base * 1.5f))); spawn_spark(position, velocity, offset, From 0de7ad9f8f7cee7efc282b17088e30e3ac9bab69 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:48:13 +0000 Subject: [PATCH 0091/1502] decomp: clarify names in effect_slots_fire D_L02_001600D0 -> l02_effect_particle_travel_step_limit: Retail 0x00264f6c and 0x00264f88 load this float at gp-0x6b30 and multiply by frame_time into f15 for advance_accelerated_scalar. Checked helper 0x0025dff8 saves f15, then 0x0025e08c..0x0025e098 caps the computed target step with it before updating the second output pointer. Source second output travel_step sets the adjusted particle motion vector length at 0x00264f9c..0x00264fa8, proving a frame-scaled travel-step limit. D_L02_001600D4 -> l02_effect_alternate_particle_count: Retail 0x00264fc4 loads this int at gp-0x6b2c into s4, replaces it with 1 when travel < 4 at 0x00264fc8, and adds it to the emission bound. The comparison i < s4 at 0x00265060..0x00265078 passes flag 1 to spawn_spinning_and_fading_effect_particle. Supplied helper source labels flag-bit-0 initialization alternate, proving this configured alternate particle count. D_L02_001600D8 -> l02_effect_default_particle_count: Retail 0x00264fb4 loads gp-0x6b28 and 0x00264fcc adds the alternate first_count to form the loop bound. Source n receives this int, with the remaining n iterations after first_count passing flag 0 at 0x00265060..0x00265078; supplied particle helper source uses its default initialization for that flag-clear path. D_L02_001600DC -> l02_effect_particle_full_travel_spread: Retail 0x00264ffc loads this float at gp-0x6b24; 0x0026500c..0x0026501c computes ((DC - E0) * (travel / distance) + E0) * frame_time as the random_vector upper argument. Source adds that random offset to adjusted and passes it as initial particle velocity, so DC is the spread endpoint when travel equals nominal distance. D_L02_001600E0 -> l02_effect_particle_zero_travel_spread: Retail 0x00264ff4 loads this float at gp-0x6b20, subtracts it from DC at 0x0026500c and adds it back at 0x00265014 after multiplying by travel/distance. The result times frame_time bounds the randomized initial-velocity offset. Thus E0 is the zero-travel endpoint of the particle spread interpolation, not necessarily a minimum or maximum. n -> default_particle_count: Source assigns n from D_L02_001600D8 and uses n + first_count as the emission loop bound. Retail 0x00264fb4 loads gp-0x6b28, 0x00264fcc adds the alternate count s4, and 0x00265060..0x00265078 selects flag 0 for iterations beyond first_count, proving this is the default (flag-clear) particle count. sp2 -> color_particle_spawn_delay: At retail 0x00265108..0x0026512c the random 10..30 float is scaled by helper 0x0020ff48, converted at 0x002112b8 and stored as the slots+0x1c timer. Source sp2 carries that random then scaled timer reload in the branch which spawns spawn_color_decaying_effect_particle. --- .../shared/weapons/effect_slots_fire.c | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/overlays/shared/weapons/effect_slots_fire.c b/src/overlays/shared/weapons/effect_slots_fire.c index 69226cd5c6..b552eeb157 100644 --- a/src/overlays/shared/weapons/effect_slots_fire.c +++ b/src/overlays/shared/weapons/effect_slots_fire.c @@ -43,11 +43,11 @@ extern float D_L02_00174460[]; extern float FUN_L04_001f1978(float); extern float fast_vec_dist(void *, void *); extern int D_L02_0015F5CC MACRO_ADDR; -extern float D_L02_001600D0 __attribute__((sda)); -extern int D_L02_001600D4 __attribute__((sda)); -extern int D_L02_001600D8 __attribute__((sda)); -extern float D_L02_001600DC __attribute__((sda)); -extern float D_L02_001600E0 __attribute__((sda)); +extern float l02_effect_particle_travel_step_limit __asm__("D_L02_001600D0") __attribute__((sda)); +extern int l02_effect_alternate_particle_count __asm__("D_L02_001600D4") __attribute__((sda)); +extern int l02_effect_default_particle_count __asm__("D_L02_001600D8") __attribute__((sda)); +extern float l02_effect_particle_full_travel_spread __asm__("D_L02_001600DC") __attribute__((sda)); +extern float l02_effect_particle_zero_travel_spread __asm__("D_L02_001600E0") __attribute__((sda)); void effect_slots_fire(char *slots, float *position, @@ -64,7 +64,7 @@ void effect_slots_fire(char *slots, float *position, float *direction, float dis float speed = 0.0f; float travel; float acceleration; - int n; + int default_particle_count; int first_count; int i; int save_shot; @@ -91,17 +91,17 @@ void effect_slots_fire(char *slots, float *position, float *direction, float dis travel, 1.0f, acceleration * 48.0f, - (D_L02_001600D0)*frame_time_macro); + (l02_effect_particle_travel_step_limit)*frame_time_macro); ((float (*)(void *, void *, float))fast_vec_normalize)(adjusted, adjusted, travel_step); - n = (D_L02_001600D8); - first_count = (D_L02_001600D4); + default_particle_count = (l02_effect_default_particle_count); + first_count = (l02_effect_alternate_particle_count); if (travel < 4.0f) first_count = 1; - for (i = 0; i < n + first_count; i++) { + for (i = 0; i < default_particle_count + first_count; i++) { random_vector( offset, 0.0f, - (((D_L02_001600DC) - (D_L02_001600E0)) * (travel / distance) + (D_L02_001600E0)) * + (((l02_effect_particle_full_travel_spread) - (l02_effect_particle_zero_travel_spread)) * (travel / distance) + (l02_effect_particle_zero_travel_spread)) * frame_time_macro); fast_vec_add(offset, offset, adjusted); fast_vec_scale(velocity, adjusted, random_float_between(0.0f, 1.0f)); @@ -122,9 +122,9 @@ void effect_slots_fire(char *slots, float *position, float *direction, float dis } } if (fast_dec_timer_s16(slots + 0x1c)) { - float sp2 = random_float_between(10.0f, 30.0f); - sp2 = FUN_L04_001f1978(sp2); - ((Slots *)slots)->timer = truncate_float_to_s32(sp2); + float color_particle_spawn_delay = random_float_between(10.0f, 30.0f); + color_particle_spawn_delay = FUN_L04_001f1978(color_particle_spawn_delay); + ((Slots *)slots)->timer = truncate_float_to_s32(color_particle_spawn_delay); random_vector(offset, 0.0f, frame_time_macro + frame_time_macro); fast_vec_scale(velocity, adjusted, random_float_between(0.5f, 0.1f)); fast_vec_add(velocity, velocity, offset); From 06af98150fe12b8ba5dd9cd437dab05bae1b5d89 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:50:54 +0000 Subject: [PATCH 0092/1502] decomp: clarify names in move_moby_with_step_collision g -> ground_normal_angle_or_hit_height: In the bound source SHA-256 805b38d98652520dca453df80365230ae6f41253f2428046879976ae5f712aaa, g first receives fast_arc_tan(collision normal Z, normal XY length), corresponding to retail 0x00258a14-0x00258a28 and Ghidra fVar11, and is compared with 0.5 at 0x00258a38. It is then reassigned collision-result offset +0x28 at 0x00258a48, the ground hit height used in (hit height - probe reference height) * 0.3 to adjust moby Z at 0x00258a5c-0x00258a78. The combined name preserves both proven reuse phases. result -> movement_collision_result_flags: Source result corresponds to retail s6, initialized to zero at 0x00258850. A forward line hit sets it to 1 at 0x00258930; sphere collision resolution ORs bit 1 at 0x002589a0. A successful downward ground query with positive collision-result +0x1c ORs 2 at 0x00258a1c, and normal elevation angle >0.5 ORs 4 at 0x00258a44. It is returned through v0 at 0x00258a8c. Ghidra uVar7/uVar8 confirms this is an accumulated movement collision bitmask rather than a scalar calculation. --- .../shared/math/interpolation/spring_turn.c | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/overlays/shared/math/interpolation/spring_turn.c b/src/overlays/shared/math/interpolation/spring_turn.c index cbe4e79f97..9ef4ddd938 100644 --- a/src/overlays/shared/math/interpolation/spring_turn.c +++ b/src/overlays/shared/math/interpolation/spring_turn.c @@ -321,7 +321,7 @@ int move_moby_with_step_collision(char *moby, Vs raised_position; Vs probe_end; Vs scaled_displacement; - int result = 0; + int movement_collision_result_flags = 0; int coll_flags = (flags * 2) & 0x20; char *movement_position = &MOBY(moby)->pos; int i; @@ -337,7 +337,7 @@ int move_moby_with_step_collision(char *moby, probe_end.a[2] += step_height; if (collision_line(&raised_position, &probe_end, coll_flags, (int)moby, 0)) { fast_vec_sub(movement_position, (char *)&D_94C8_60, &scaled_displacement); - result = 1; + movement_collision_result_flags = 1; MOBY(moby)->pos.z -= step_height; } } @@ -346,7 +346,7 @@ int move_moby_with_step_collision(char *moby, raised_position.a[2] += step_height; if (func_L00_001F10E0_l(&raised_position, radius, coll_flags | 4, moby)) { qcopy(collision_position, &coll_hit_position); - result |= 1; + movement_collision_result_flags |= 1; MOBY(moby)->pos.z -= step_height; } else { break; @@ -359,21 +359,21 @@ int move_moby_with_step_collision(char *moby, probe_end.a[2] = radius - 0.05f; if (collision_line(&raised_position, &probe_end, coll_flags | 2, (int)moby, 0)) { if (D_L00_00173E40[7] > 0) { - float g; - result |= 2; - g = fast_arc_tan(*(float *)((char *)D_L00_00173E40 + 0x48), + float ground_normal_angle_or_hit_height; + movement_collision_result_flags |= 2; + ground_normal_angle_or_hit_height = fast_arc_tan(*(float *)((char *)D_L00_00173E40 + 0x48), vector_length_xy((char *)D_L00_00173E40 + 0x40)); - if (g > 0.5f) { - result |= 4; + if (ground_normal_angle_or_hit_height > 0.5f) { + movement_collision_result_flags |= 4; } - g = *(float *)((char *)D_L00_00173E40 + 0x28); - if (radius < g) { - MOBY(moby)->pos.z += (g - radius) * 0.3f; + ground_normal_angle_or_hit_height = *(float *)((char *)D_L00_00173E40 + 0x28); + if (radius < ground_normal_angle_or_hit_height) { + MOBY(moby)->pos.z += (ground_normal_angle_or_hit_height - radius) * 0.3f; } } } fast_vec_sub(velocity, collision_position, &original_position); - return result; + return movement_collision_result_flags; } /* move_moby_with_step_collision as this caller passes it: the moby and velocity as ints. */ From e94d9a8ff058281bd91be146080503002453459f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:50:54 +0000 Subject: [PATCH 0093/1502] decomp: clarify names in push_point_from_path entry -> path_table_slot: Source declares SegmentPath **entry and assigns &l05_paths[path_index]. Retail 0x00304100-0x0030410c computes s4 = 0x001b0930 + path_index*4 and dereferences it for segment endpoints; 0x00304158, 0x00304234 and 0x0030427c reload the same table slot after helpers. This is the address of the selected path pointer, not a point or segment record. out -> adjusted_position_output: Source binds PathVec *out = output and uses it only in if(found) qcopy(out, &working). Retail saves incoming a2 at 0x003040a8, restores input z at 0x00304290-0x00304294, then 0x003042c8-0x003042d8 tests the adjustment flag and copies the 16-byte working position to that saved pointer only when set. Caller move_extermibot_along_path supplies &moby->pos as this output. --- src/overlays/l05/mobys/extermibot.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/l05/mobys/extermibot.c b/src/overlays/l05/mobys/extermibot.c index 01080f5f39..6c4fce829b 100644 --- a/src/overlays/l05/mobys/extermibot.c +++ b/src/overlays/l05/mobys/extermibot.c @@ -1104,7 +1104,7 @@ f32 push_point_from_path(s32 path_index, f32 push_point_from_path(s32 path_index, void *input, void *output, f32 distance) { PathVec *point = input; - PathVec *out = output; + PathVec *adjusted_position_output = output; PathVec difference; PathVec scaled_difference; PathVec working; @@ -1112,7 +1112,7 @@ f32 push_point_from_path(s32 path_index, void *input, void *output, f32 distance PathVec scaled_segment; PathVec cross; PathVec scaled_cross; - SegmentPath **entry; + SegmentPath **path_table_slot; s32 i; s32 found; f32 best = 512.0f; @@ -1120,12 +1120,12 @@ f32 push_point_from_path(s32 path_index, void *input, void *output, f32 distance found = 0; qcopy_nc(&working, point); for (i = 0; i < ((SegmentPath *)l05_paths[path_index])->count - 1; i++) { - entry = ((SegmentPath **)&l05_paths[path_index]); - if ((*entry)->points[i].f[3] == 0.0f && (*entry)->points[i + 1].f[3] == 0.0f) + path_table_slot = ((SegmentPath **)&l05_paths[path_index]); + if ((*path_table_slot)->points[i].f[3] == 0.0f && (*path_table_slot)->points[i + 1].f[3] == 0.0f) continue; - func_001F9BF0_3054B0(&difference, &working, &(*entry)->points[i]); + func_001F9BF0_3054B0(&difference, &working, &(*path_table_slot)->points[i]); difference.i[2] = 0; - func_001F9BF0_3054B0(&segment, &(*entry)->points[i + 1], &(*entry)->points[i]); + func_001F9BF0_3054B0(&segment, &(*path_table_slot)->points[i + 1], &(*path_table_slot)->points[i]); segment.i[2] = 0; func_L00_001FF4B0_3054B0(&scaled_segment, &segment, 1.0f); func_001F9CA0_3054B0(&cross, &difference, &scaled_segment); @@ -1144,7 +1144,7 @@ f32 push_point_from_path(s32 path_index, void *input, void *output, f32 distance continue; found = 1; func_L00_001FF4B0_3054B0(&scaled_difference, &difference, distance); - func_001F9BD8_3054B0(&working, &scaled_difference, &(*entry)->points[i]); + func_001F9BD8_3054B0(&working, &scaled_difference, &(*path_table_slot)->points[i]); working.f[2] = point->f[2]; } else { found = 1; @@ -1152,12 +1152,12 @@ f32 push_point_from_path(s32 path_index, void *input, void *output, f32 distance func_001F9BF0_3054B0(&scaled_difference, &difference, &scaled_cross); func_L00_001FF4B0_3054B0(&scaled_difference, &scaled_difference, distance); func_001F9BD8_3054B0(&scaled_difference, &scaled_difference, &scaled_cross); - func_001F9BD8_3054B0(&working, &scaled_difference, &(*entry)->points[i]); + func_001F9BD8_3054B0(&working, &scaled_difference, &(*path_table_slot)->points[i]); working.f[2] = point->f[2]; } } } if (found) - qcopy(out, &working); + qcopy(adjusted_position_output, &working); return best; } From 82af9baf6966641158855fa300adb750c79c1237 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:50:54 +0000 Subject: [PATCH 0094/1502] decomp: clarify names in update_fog_zone c -> saved_volume_blend_color: In FOG_ZONE_INITIALIZE, retail 0x0030e318..0x0030e350 loads globals 0x00161200..0x00161203 and packs their bytes at shifts 0/8/16/24. The delay-slot store at 0x0030e358 saves this packed color at fog_zone_vars+0x30. At 0x0030e4b0..0x0030e4b8 that saved value is the first fast_tween_color endpoint, paired with the preset at +0x34 and weighted by volume-space hero x. Thus this scoped c is the saved volume-blend color endpoint. --- src/overlays/l05/mobys/fog_zone.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l05/mobys/fog_zone.c b/src/overlays/l05/mobys/fog_zone.c index 9a5e2a5d66..da0c398cfd 100644 --- a/src/overlays/l05/mobys/fog_zone.c +++ b/src/overlays/l05/mobys/fog_zone.c @@ -88,12 +88,12 @@ void fog_zone_update(struct Moby *moby) { fog_zone_vars->preset_fog_448 = 0; fog_zone_vars->preset_fog_454 = 0; { - int c = l05_volume_blended_color_low_byte + + int saved_volume_blend_color = l05_volume_blended_color_low_byte + (l05_volume_blended_color_lower_middle_byte << 8) + (l05_volume_blended_color_upper_middle_byte << 16) + (l05_volume_blended_color_high_byte << 24); fog_zone_vars->unk34 = 0x40408070; - fog_zone_vars->unk30 = c; + fog_zone_vars->unk30 = saved_volume_blend_color; } moby->state = 1; break; From 5cad25333cb479c33a0884ced30a3e20e5e9af9f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:50:54 +0000 Subject: [PATCH 0095/1502] decomp: clarify names in update_path_walker next -> candidate_path_parameter: Retail 0x002e7900-0x002e7908 computes f20 as linked walker parameter minus random gap, or 0x002e7914-0x002e7928 advances current parameter by rate times frame_time. After negative wrap by period at 0x002e7934-0x002e7948, f20 drives sample_camera_path at 0x002e7950-0x002e7960 and is stored into walker_data->parameter at 0x002e79b0 only when the trial sphere check returns -1. old -> walker_previous_position: Retail 0x002e7740-0x002e7748 copies the 16-byte vector from walker_moby+0x10 to sp+0 before path sampling updates that position at 0x002e77a8-0x002e77b0. At 0x002e79f8-0x002e79fc this saved vector is passed to emit_path_walker_particle; the supplied helper uses it as previous_position to calculate movement distance. other -> linked_walker_data: Retail 0x002e775c loads walker_data->owner at offset 0x10, then 0x002e77a4 loads that moby's pvars at +0x78 into s3. Its parameter at +4 forms the wrapped spacing gap at 0x002e77f8-0x002e781c; its target_speed and speed are exchanged/approached at 0x002e7834-0x002e7894. The supplied initializer assigns owner links between group walkers, proving linked walker data. --- src/overlays/l16/mobys/path_walker.c | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/overlays/l16/mobys/path_walker.c b/src/overlays/l16/mobys/path_walker.c index 45dec03206..2a4129b1e7 100644 --- a/src/overlays/l16/mobys/path_walker.c +++ b/src/overlays/l16/mobys/path_walker.c @@ -86,7 +86,7 @@ void path_walker_update(unsigned char *walker_moby) { PATH_WALKER_INITIALIZE_GROUP = 0, PATH_WALKER_FOLLOW_PATH = 1 }; - float old[4], rotation[4], trial[4]; + float walker_previous_position[4], rotation[4], trial[4]; char *path; L16WalkerData_c *walker_data; int playing = 0; @@ -100,7 +100,7 @@ void path_walker_update(unsigned char *walker_moby) { playing = 1; } } else { - qcopy(old, walker_moby + 0x10); + qcopy(walker_previous_position, walker_moby + 0x10); } switch (walker_moby[0x20]) { case PATH_WALKER_INITIALIZE_GROUP: @@ -111,8 +111,8 @@ void path_walker_update(unsigned char *walker_moby) { initialize_path_walker_group(walker_moby); break; case PATH_WALKER_FOLLOW_PATH: { - L16WalkerData_c *other = *(L16WalkerData_c **)(walker_data->owner + 0x78); - float gap, step, next, height, acceleration; + L16WalkerData_c *linked_walker_data = *(L16WalkerData_c **)(walker_data->owner + 0x78); + float gap, step, candidate_path_parameter, height, acceleration; /* `playing` again, in a variable of case 1's own. The logic does not need it: tested directly, `playing` is one value from the top of the function to the test, the compiler ranks it below `path` and gives them $s5 and $s4, the reverse of retail. The narrowing copy ends that value @@ -130,46 +130,46 @@ void path_walker_update(unsigned char *walker_moby) { MOBY(walker_moby)->pos.z += walker_data->height_step; walker_data->parameter += walker_data->speed; approach_value(&walker_data->speed, walker_data->target_speed, acceleration); - gap = other->parameter - walker_data->parameter; + gap = linked_walker_data->parameter - walker_data->parameter; if (gap < 0.0f) { gap += walker_data->period; } if (gap < path_walker_gap_range_start_gp && - walker_data->target_speed > other->target_speed) { + walker_data->target_speed > linked_walker_data->target_speed) { float saved = walker_data->target_speed; - float theirs = other->target_speed; + float theirs = linked_walker_data->target_speed; - other->target_speed = saved; + linked_walker_data->target_speed = saved; walker_data->target_speed = theirs; } if (gap < 1.5f) { step = frame_time_sq * 50.0f; approach_value(&walker_data->speed, walker_data->target_speed, step); - approach_value(&other->speed, other->target_speed, step); + approach_value(&linked_walker_data->speed, linked_walker_data->target_speed, step); } if (walker_moby[0x31] == 0 && blocked == 0) { if (gap > path_walker_gap_range_end_gp + 1.0f) { height = random_float_between(path_walker_height_range_start_gp, path_walker_height_range_end_gp); if (walker_data->owner[0x31] != 0 && walker_data->countdown != 0) { - next = other->parameter - random_float_between(path_walker_gap_range_start_gp, + candidate_path_parameter = linked_walker_data->parameter - random_float_between(path_walker_gap_range_start_gp, path_walker_gap_range_end_gp); walker_data->countdown--; } else { - next = walker_data->parameter + + candidate_path_parameter = walker_data->parameter + path_walker_reposition_advance_rate_gp * frame_time; } - if (next < 0.0f) { - next += walker_data->period; + if (candidate_path_parameter < 0.0f) { + candidate_path_parameter += walker_data->period; } - sample_camera_path(path, next, 0, trial, rotation, 1); + sample_camera_path(path, candidate_path_parameter, 0, trial, rotation, 1); trial[2] += height; trial[3] = 2.0f; if (fast_bsphere_check((char *)trial, (float)path_walker_draw_distance_gp) == -1) { float random = random_float_between(path_walker_speed_range_start_gp, path_walker_speed_range_end_gp); - walker_data->parameter = next; + walker_data->parameter = candidate_path_parameter; walker_data->height_step = height; walker_data->target_speed = random * frame_time; } @@ -184,7 +184,7 @@ void path_walker_update(unsigned char *walker_moby) { } } if (((unsigned short)MOBY(walker_moby)->oclass) & 1) { - emit_path_walker_particle(walker_moby, old); + emit_path_walker_particle(walker_moby, walker_previous_position); } } From 0f8d7ac2ef98db044f14f0b27db5c55aa43ccb41 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:50:54 +0000 Subject: [PATCH 0096/1502] decomp: clarify names in initialize_path_key_camera cam -> path_key_camera_object: The struct UpdateCam pointer in initialize_path_key_camera is retained from a0 in s4 at retail 0x00315a00. Its descriptor_index (+0x84, 0x00315a30-0x00315a40) selects the descriptor whose +0x34/+0x38/+0x3c paths populate the three rail-distance tables. Loads from this same object's saved_state (+0x70, 0x00315bb8/0x00315bec/0x00315c28) initialize key-camera state and parameters; its position (+0x30) is the placement destination at 0x00315c60-0x00315c74 and its basis at +0/+0x10/+0x20 is constructed at 0x00315cb4-0x00315ce8. Original Ghidra param_1/iVar7 agrees with this source data flow. The proposed name adds the proven path/key camera specialization rather than only expanding cam. --- src/overlays/l14/path_key_camera.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l14/path_key_camera.c b/src/overlays/l14/path_key_camera.c index 98979c70c8..15ea516e6d 100644 --- a/src/overlays/l14/path_key_camera.c +++ b/src/overlays/l14/path_key_camera.c @@ -35,12 +35,12 @@ compute_position_from_spherical_offset(void *, void *, void *) __asm__("FUN_L00_ void initialize_path_key_camera(struct UpdateCam *cam) __asm__("FUN_L14_003159d8"); -void initialize_path_key_camera(struct UpdateCam *cam) { +void initialize_path_key_camera(struct UpdateCam *path_key_camera_object) { float camera_placement_parameters[4]; float pad[4]; /* unused; keeps the frame layout */ float hero_look_direction[4]; float up[4]; - char *rec = *(char **)(l14_camera_preset_rows + cam->descriptor_index * 32 + 0x1C); + char *rec = *(char **)(l14_camera_preset_rows + path_key_camera_object->descriptor_index * 32 + 0x1C); char *path; LevelSpline *path_record_table; char *camera_saved_state; @@ -79,7 +79,7 @@ void initialize_path_key_camera(struct UpdateCam *cam) { sum += *(float *)(path + i * 16 + 0x1C); } path_key_camera_rail_distances[2][i] = sum; - camera_saved_state = cam->saved_state; + camera_saved_state = path_key_camera_object->saved_state; *(int *)(camera_saved_state + 0x88) = 1; camera_state_block = (int *)(camera_saved_state + 0x88); camera_state_block[1] = 0; @@ -87,13 +87,13 @@ void initialize_path_key_camera(struct UpdateCam *cam) { camera_state_block[3] = 0; camera_state_block[4] = 0; D_L14_001624A8 = 1.0f; - camera_parameters = (float *)((char *)cam->saved_state + 0x60); + camera_parameters = (float *)((char *)path_key_camera_object->saved_state + 0x60); camera_parameters[0] = D_L14_001F6488_59d8[0] * 0.017453292f; camera_parameters[1] = D_L14_001F6488_59d8[1] * 0.017453292f; camera_parameters[2] = D_L14_001F6488_59d8[2]; camera_parameters[3] = D_L14_001F6488_59d8[3] * 0.017453292f; camera_parameters[4] = D_L14_001F6488_59d8[4] * 0.017453292f; - camera_parameter_state_block = (int *)((char *)cam->saved_state + 0x74); + camera_parameter_state_block = (int *)((char *)path_key_camera_object->saved_state + 0x74); *camera_parameter_state_block = 0; camera_parameter_state_block[1] = 0; camera_parameter_state_block[2] = 0; @@ -103,14 +103,14 @@ void initialize_path_key_camera(struct UpdateCam *cam) { camera_placement_parameters[1] = camera_parameters[1]; camera_placement_parameters[0] = hero_heading_radians; camera_placement_parameters[2] = camera_parameters[2]; - compute_position_from_spherical_offset(&cam->pos, camera_placement_parameters, &hero.motion); - fast_vec_sub(hero_look_direction, &hero.motion, &cam->pos); + compute_position_from_spherical_offset(&path_key_camera_object->pos, camera_placement_parameters, &hero.motion); + fast_vec_sub(hero_look_direction, &hero.motion, &path_key_camera_object->pos); fast_vec_scale(up, &hero.gravity_dir, -1.5f); fast_vec_add(hero_look_direction, hero_look_direction, up); - fast_vec_normalize(&cam->m0, hero_look_direction, 1.0f); - fast_vec_cross(&cam->m1, &cam->m0, up); - fast_vec_normalize(&cam->m1, &cam->m1, 1.0f); - fast_vec_cross(&cam->m2, &cam->m1, &cam->m0); + fast_vec_normalize(&path_key_camera_object->m0, hero_look_direction, 1.0f); + fast_vec_cross(&path_key_camera_object->m1, &path_key_camera_object->m0, up); + fast_vec_normalize(&path_key_camera_object->m1, &path_key_camera_object->m1, 1.0f); + fast_vec_cross(&path_key_camera_object->m2, &path_key_camera_object->m1, &path_key_camera_object->m0); /* give every key without a duration (+0x44) the default 10000 */ camera_key_default_cursor = (int *)&D_L14_001F6488_59d8[0x11]; for (j = 38; j >= 0; j--) { From c5b4c0ad497852e0b2a731cc3fa0196247953a26 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:50:54 +0000 Subject: [PATCH 0097/1502] decomp: clarify names in floor_button_update entry -> path_key_cursor: Source assigns l05_paths[list]+i*16 to this cursor in both loops. Retail 0x0030c6d8-0x0030c6fc and 0x0030c8c8-0x0030c8ec load the selected path table, add the index shifted by four, compare the float at cursor+0x1C with the button private key at +4, and clear that key when equal. The name describes traversal of path keys without asserting that the biased cursor is the actual record start. switch_0_case_0 -> FLOOR_BUTTON_STATE_INITIALIZE: Selector is moby->state: retail 0x0030c5c4-0x0030c5c8 branches on zero at moby+0x20 to 0x0030c5e4. That branch initializes a random pulse angle at private+0xC, lowers moby z by 0.35, checks saved activation and eligibility, and always writes state 1 or 2 (0x0030c69c and 0x0030c734). This establishes a one-time floor-button initialization state, independent of all supplied Hero enum domains. switch_0_case_1 -> FLOOR_BUTTON_STATE_WAIT_FOR_PRESS: Retail 0x0030c5d0-0x0030c5d4 compares this same moby state with 1 and branches to 0x0030c738. It advances the pulse angle and glow, then 0x0030c7d4-0x0030c7e4 waits for hero.ground_moby to equal this button and hero.air_frames.s to be zero. On grounded contact it records activation flags, writes state 2 at 0x0030c880, plays voice and clears matching path keys. This proves waiting for the hero to press the floor button. vars -> floor_button_private_state: Retail 0x0030c5cc loads s1 from moby+0x78, the source pvars field. This floor_button_update-owned block supplies the path-table selector at +0, matching float key at +4 (0x0030c6e0), eligibility option at +8 (0x0030c660), and mutable pulse angle at +0xC (0x0030c5ec, 0x0030c74c-0x0030c760), proving private configuration and runtime state for the floor button. --- src/overlays/shared/props/floor_button.c | 40 +++++++++++++----------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/overlays/shared/props/floor_button.c b/src/overlays/shared/props/floor_button.c index 6f612b187c..6f302231a9 100644 --- a/src/overlays/shared/props/floor_button.c +++ b/src/overlays/shared/props/floor_button.c @@ -26,36 +26,40 @@ void floor_button_update(struct Moby *moby) __asm__("FUN_L05_0030c5b0"); /* Moby class 830 */ void floor_button_update(struct Moby *moby) { - s32 *vars = (s32 *)moby->pvars; + enum { + FLOOR_BUTTON_STATE_INITIALIZE = 0, + FLOOR_BUTTON_STATE_WAIT_FOR_PRESS = 1 + }; + s32 *floor_button_private_state = (s32 *)moby->pvars; s16 id; s32 i; s32 list; - char *entry; + char *path_key_cursor; f32 angle; s32 color; u32 shade; u32 high; switch (moby->state) { - case 0: - *(f32 *)(vars + 3) = random_angle_radians(); + case FLOOR_BUTTON_STATE_INITIALIZE: + *(f32 *)(floor_button_private_state + 3) = random_angle_radians(); moby->pos.z -= 0.35f; id = (s16)moby->save_id; if (D_L05_001BB6B0.collected[id] != 0 || (D_0014C190_257218[current_level_index][id >> 5] >> (moby->save_id & 31) & 1) != 0 || - (vars[2] != 0 && D_0014C050[moby->mission + current_level_index * 16] == 0xFF)) { + (floor_button_private_state[2] != 0 && D_0014C050[moby->mission + current_level_index * 16] == 0xFF)) { moby->command = 2; moby->glow_color = 0x80208020; moby->state = 2; - list = vars[0]; + list = floor_button_private_state[0]; if (list != -1) { i = 0; if (*(s32 *)l05_paths[list] > 0) { do { - entry = ((char *)l05_paths[list]) + i * 16; - if (*(f32 *)(entry + 0x1C) == ((f32 *)vars)[1]) - *(s32 *)(entry + 0x1C) = 0; - list = vars[0]; + path_key_cursor = ((char *)l05_paths[list]) + i * 16; + if (*(f32 *)(path_key_cursor + 0x1C) == ((f32 *)floor_button_private_state)[1]) + *(s32 *)(path_key_cursor + 0x1C) = 0; + list = floor_button_private_state[0]; i++; } while (i < *(s32 *)l05_paths[list]); } @@ -64,9 +68,9 @@ void floor_button_update(struct Moby *moby) { moby->state = 1; } break; - case 1: - angle = fast_add_rotations(*(f32 *)(vars + 3), frame_time * 6.2831855f); - *(f32 *)(vars + 3) = angle; + case FLOOR_BUTTON_STATE_WAIT_FOR_PRESS: + angle = fast_add_rotations(*(f32 *)(floor_button_private_state + 3), frame_time * 6.2831855f); + *(f32 *)(floor_button_private_state + 3) = angle; color = truncate_float_to_s32((fast_sin(angle) * 4.0f - 3.0f) * 128.0f); if (color > 0x80) color = 0x80; @@ -86,15 +90,15 @@ void floor_button_update(struct Moby *moby) { moby->command = 1; moby->glow_color = 0x80208020; allocate_voice_for_target_entry(0, 0, moby); - list = vars[0]; + list = floor_button_private_state[0]; if (list != -1) { i = 0; if (*(s32 *)l05_paths[list] > 0) { do { - entry = ((char *)l05_paths[list]) + i * 16; - if (*(f32 *)(entry + 0x1C) == ((f32 *)vars)[1]) - *(s32 *)(entry + 0x1C) = 0; - list = vars[0]; + path_key_cursor = ((char *)l05_paths[list]) + i * 16; + if (*(f32 *)(path_key_cursor + 0x1C) == ((f32 *)floor_button_private_state)[1]) + *(s32 *)(path_key_cursor + 0x1C) = 0; + list = floor_button_private_state[0]; i++; } while (i < *(s32 *)l05_paths[list]); } From 8e83344f1788a48f1da1b714540eb3ae1cfddafd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:51:11 +0000 Subject: [PATCH 0098/1502] decomp: clarify names in spawn_hoven_anklebiter_death_sparks D_L12_00161844 -> l12_anklebiter_spark_burst_origin_jitter: Retail 0x002e3160-0x002e3170 copies the moby position and loads gp-0x53bc as the bound for add_random_offset_to_vector_xyz before the inner emission loop. Source binds this load to D_L12_00161844; it jitters each outer burst's origin. D_L12_00161848 -> l12_anklebiter_spark_position_jitter: Retail 0x002e32d0-0x002e32e8 passes sp+0x10 (pos) and gp-0x53b8 to add_random_offset_to_vector_xyz on every inner-loop emission. Source binds that float to D_L12_00161848, proving the per-spark position jitter bound. D_L12_0016184C -> l12_anklebiter_spark_velocity_jitter_scale: Retail 0x002e32f0-0x002e3304 multiplies gp-0x53b4 by D_0015ED6C and uses it as the XYZ random-offset bound for sp+0x30, the copied gravity-adjusted spark velocity. Source binds this scale to D_L12_0016184C. D_L12_00161850 -> l12_anklebiter_spark_horizontal_speed_range_start: Retail 0x002e3184-0x002e3190 passes gp-0x53b0 as the first bound of random_float_between; the result in f20 feeds both cos and sin horizontal components at 0x002e31ec-0x002e3230. Source binds this first horizontal speed bound to D_L12_00161850. D_L12_00161854 -> l12_anklebiter_spark_horizontal_speed_range_end: Retail 0x002e318c-0x002e3190 passes gp-0x53ac as the second random_float_between bound; the resulting f20 scales the horizontal cos/sin velocity components. Source binds this second horizontal speed bound to D_L12_00161854; no numeric ordering is assumed. D_L12_00161858 -> l12_anklebiter_spark_vertical_speed_range_start: Retail 0x002e3194-0x002e31a0 loads gp-0x53a8 as the first random_float_between bound, retains its result in f21, and multiplies it by D_0015ED6C for velocity Z at 0x002e3208-0x002e3228. Source binds this vertical speed bound to D_L12_00161858. D_L12_0016185C -> l12_anklebiter_spark_vertical_speed_range_end: Retail 0x002e319c-0x002e31b4 loads gp-0x53a4 as the second random_float_between bound and saves the result in f21; 0x002e3208-0x002e3228 converts that rise to velocity Z. Source binds this second vertical speed bound to D_L12_0016185C. D_L12_00161860 -> l12_anklebiter_spark_downward_velocity_scale: Retail 0x002e3264-0x002e3298 loads gp-0x53a0, multiplies it by D_0015ED70 and the scaled fade frame count, then subtracts that product from the copied velocity's Z. Source binds this downward velocity adjustment scale to D_L12_00161860. D_L12_00161884 -> l12_anklebiter_spark_random_time_base: Retail 0x002e335c-0x002e3388 converts gp-0x537c from integer to float, uses 0.5 and 2.5 multiples as random_float_between bounds, then applies scale_time and truncation for spawn_spark's eighth argument. Checked helper 0x00281b10 stores that argument as a halfword at particle+0x34. Source binds the random time base to D_L12_00161884; its exact downstream time-field meaning is not asserted. accel -> gravity_adjusted_spark_velocity: Retail 0x002e3248-0x002e3250 copies the launch velocity quadword into sp+0x30. At 0x002e3264-0x002e3298 its Z is reduced by D_L12_00161860*D_0015ED70*scale_game_frames(D_L12_00161880), then XYZ is jittered at 0x002e32f0-0x002e3304 and passed as spawn_spark argument three. The name describes its proven derivation without asserting downstream acceleration semantics. src -> moby_position_source: Retail 0x002e3124-0x002e314c forms moby+0x10, stores that pointer at sp+0x5c, then 0x002e3160-0x002e3168 copies its quadword into pos. Source assigns src=&moby->pos; it is specifically the source moby position. vars -> spark_moby_vars: Retail 0x002e30e4-0x002e30e8 saves moby+0x78 (pvars) at sp+0x54; 0x002e3204-0x002e322c adds 0x120 and scales that vector by 0.5 before its horizontal contribution is added to spark velocity. This is the emitting anklebiter's private variables. vel -> spark_launch_velocity: Retail 0x002e31d8-0x002e3230 builds XYZ from cos/sin(angle)*speed*frame_time and rise*frame_time; 0x002e3234-0x002e3244 adds the flattened half-pvars vector. It is passed as spawn_spark's second argument at 0x002e33ac, identifying the launch velocity rather than a generic vector. --- src/overlays/l12/mobys/hoven_anklebiter.c | 66 +++++++++++------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/overlays/l12/mobys/hoven_anklebiter.c b/src/overlays/l12/mobys/hoven_anklebiter.c index 493f9aa0ec..b66378d3f8 100644 --- a/src/overlays/l12/mobys/hoven_anklebiter.c +++ b/src/overlays/l12/mobys/hoven_anklebiter.c @@ -717,14 +717,14 @@ int move_hoven_anklebiter_toward_heading(struct Moby *moby, float speed) { int D_L12_0016183C = 0xa; int D_L12_00161840 = 8; -extern float D_L12_00161844 __attribute__((sda)); -extern float D_L12_00161848 __attribute__((sda)); -extern float D_L12_0016184C __attribute__((sda)); -extern float D_L12_00161850 __attribute__((sda)); -extern float D_L12_00161854 __attribute__((sda)); -extern float D_L12_00161858 __attribute__((sda)); -extern float D_L12_0016185C __attribute__((sda)); -extern float D_L12_00161860 __attribute__((sda)); +extern float l12_anklebiter_spark_burst_origin_jitter __asm__("D_L12_00161844") __attribute__((sda)); +extern float l12_anklebiter_spark_position_jitter __asm__("D_L12_00161848") __attribute__((sda)); +extern float l12_anklebiter_spark_velocity_jitter_scale __asm__("D_L12_0016184C") __attribute__((sda)); +extern float l12_anklebiter_spark_horizontal_speed_range_start __asm__("D_L12_00161850") __attribute__((sda)); +extern float l12_anklebiter_spark_horizontal_speed_range_end __asm__("D_L12_00161854") __attribute__((sda)); +extern float l12_anklebiter_spark_vertical_speed_range_start __asm__("D_L12_00161858") __attribute__((sda)); +extern float l12_anklebiter_spark_vertical_speed_range_end __asm__("D_L12_0016185C") __attribute__((sda)); +extern float l12_anklebiter_spark_downward_velocity_scale __asm__("D_L12_00161860") __attribute__((sda)); extern float D_L12_00161864 __attribute__((sda)); extern float D_L12_00161868 __attribute__((sda)); int D_L12_0016186C = 0x8000eeee; @@ -733,7 +733,7 @@ int D_L12_00161874 = 0x8000ff90; int D_L12_00161878 = 0xffee; int D_L12_0016187C = 0xa; int D_L12_00161880 = 0x1e; -extern int D_L12_00161884 __attribute__((sda)); +extern int l12_anklebiter_spark_random_time_base __asm__("D_L12_00161884") __attribute__((sda)); extern void add_random_offset_to_vector_xyz(void *, float) __asm__("FUN_L00_0025f8e0"); extern float scale_time(float) __asm__("FUN_001f96b0"); extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); @@ -743,13 +743,13 @@ void spawn_hoven_anklebiter_death_sparks(struct Moby *moby) __asm__("FUN_L12_002 void spawn_hoven_anklebiter_death_sparks(struct Moby *moby) { float pos[4]; - float vel[4]; - float accel[4]; + float spark_launch_velocity[4]; + float gravity_adjusted_spark_velocity[4]; float push[4]; - char *vars; + char *spark_moby_vars; int count; float *pos_ptr; - void *src; + void *moby_position_source; int i; int j; float angle; @@ -763,47 +763,47 @@ void spawn_hoven_anklebiter_death_sparks(struct Moby *moby) { int fade; count = D_L12_0016183C; - vars = (char *)moby->pvars; + spark_moby_vars = (char *)moby->pvars; if (moby->state == 15) count = truncate_float_to_s32((float)count * 1.5f); for (i = 0; i < count; i++) { pos_ptr = pos; - src = &moby->pos; - qcopy_nc(pos, src); - add_random_offset_to_vector_xyz(pos_ptr, D_L12_00161844); + moby_position_source = &moby->pos; + qcopy_nc(pos, moby_position_source); + add_random_offset_to_vector_xyz(pos_ptr, l12_anklebiter_spark_burst_origin_jitter); pos[2] += 0.55f; angle = random_angle_radians(); - speed = random_float_between(D_L12_00161850, D_L12_00161854); - rise = random_float_between(D_L12_00161858, D_L12_0016185C); + speed = random_float_between(l12_anklebiter_spark_horizontal_speed_range_start, l12_anklebiter_spark_horizontal_speed_range_end); + rise = random_float_between(l12_anklebiter_spark_vertical_speed_range_start, l12_anklebiter_spark_vertical_speed_range_end); if (moby->state == 15) { speed *= 0.55f; rise *= 0.55f; pos[2] -= 0.2f; } - vel[0] = fast_cos(angle) * (speed * D_0015ED6C); - vel[1] = fast_sin(angle) * (speed * D_0015ED6C); - vel[2] = 0.0f + rise * D_0015ED6C; - fast_vec_scale(push, vars + 0x120, 0.5f); + spark_launch_velocity[0] = fast_cos(angle) * (speed * D_0015ED6C); + spark_launch_velocity[1] = fast_sin(angle) * (speed * D_0015ED6C); + spark_launch_velocity[2] = 0.0f + rise * D_0015ED6C; + fast_vec_scale(push, spark_moby_vars + 0x120, 0.5f); push[2] = 0.0f; - fast_vec_add(vel, vel, push); - qcopy(accel, vel); - accel[2] -= D_L12_00161860 * D_0015ED70 * (float)scale_game_frames(D_L12_00161880); + fast_vec_add(spark_launch_velocity, spark_launch_velocity, push); + qcopy(gravity_adjusted_spark_velocity, spark_launch_velocity); + gravity_adjusted_spark_velocity[2] -= l12_anklebiter_spark_downward_velocity_scale * D_0015ED70 * (float)scale_game_frames(D_L12_00161880); for (j = 0; j < D_L12_00161840; j++) { size = random_float_between(0.5f, 1.5f); - vel[3] = size * D_L12_00161864; - accel[3] = size * D_L12_00161868; - add_random_offset_to_vector_xyz(pos, D_L12_00161848); - add_random_offset_to_vector_xyz(accel, D_L12_0016184C * D_0015ED6C); + spark_launch_velocity[3] = size * D_L12_00161864; + gravity_adjusted_spark_velocity[3] = size * D_L12_00161868; + add_random_offset_to_vector_xyz(pos, l12_anklebiter_spark_position_jitter); + add_random_offset_to_vector_xyz(gravity_adjusted_spark_velocity, l12_anklebiter_spark_velocity_jitter_scale * D_0015ED6C); start_color = fast_tween_color(D_L12_0016186C, D_L12_00161874, random_float_between(0.0f, 1.0f)); end_color = fast_tween_color(D_L12_00161870, D_L12_00161878, random_float_between(0.0f, 1.0f)); life = scale_game_frames(D_L12_0016187C); fade = scale_game_frames(D_L12_00161880); - time_base = (float)D_L12_00161884; + time_base = (float)l12_anklebiter_spark_random_time_base; spawn_spark(pos, - vel, - accel, + spark_launch_velocity, + gravity_adjusted_spark_velocity, start_color, end_color, life, From 713df3e4942fd24b46b63524178a226d407c7d97 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:51:19 +0000 Subject: [PATCH 0099/1502] decomp: clarify names in update_box_emitter D_L01_00167240 -> camera_pos: Retail 0x0031992c and 0x00319934 form address 0x00167240 in a1; 0x00319950 supplies moby+0x40 in a2 and 0x0031997c calls the vector subtraction. The authoritative source expresses fast_vec_sub(&delta, D_L01_00167240, moby + 0x40). Retail 0x00319998 transforms this relative position into the box basis; 0x003199c0-0x003199d4 tests its length, and 0x003199e4-0x00319b24 clamps its components and computes positional volume. This proves the listener-position role, consistent with the supplied existing identical-assembler-label name camera_pos. --- src/overlays/shared/audio/emitters/box_emitter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/audio/emitters/box_emitter.c b/src/overlays/shared/audio/emitters/box_emitter.c index 14efa9501a..d7e2a00bc5 100644 --- a/src/overlays/shared/audio/emitters/box_emitter.c +++ b/src/overlays/shared/audio/emitters/box_emitter.c @@ -11,7 +11,7 @@ #include "rnc/overlay/shared/vendor/vendor_volume.h" #include "rnc/math/random.h" -extern char D_L01_00167240[]; +extern char camera_pos[] __asm__("D_L01_00167240"); extern char *D_L00_0015F5F4; extern char D_0013E550[]; @@ -27,7 +27,7 @@ void update_box_emitter(char *moby) { float box_length, listener_length; radius.f[2] = radius.f[1] = radius.f[0] = MOBY(moby)->bsphere.w; - fast_vec_sub(&delta, D_L01_00167240, moby + 0x40); + fast_vec_sub(&delta, camera_pos, moby + 0x40); delta.f[3] = 0.0f; transform_vector_by_basis(&box_size, &delta, moby + 0x50); transform_vector_by_basis(&listener, &radius, moby + 0x50); From 7a7ef28bd627f486fed089b6ee5d065868624ecf Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:53:37 +0000 Subject: [PATCH 0100/1502] decomp: clarify names in suck_beam_build D_L00_00161B54 -> l00_suck_beam_step_blend_elapsed_frames: Assigned retail suck_beam_build at 0x002ddef4 clears gp-0x50ac, rendered uGpffffaf54=0 in the original decompilation and D_L00_00161B54=0 in the SHA-bound C. In the authoritative suck_beam_update caller, this int is divided by convert_integer_to_float(scale_game_frames(60)) to form beam_step_blend_fraction, incremented once, and used to interpolate start/end XYZ into step. At the scaled 60-frame threshold it copies the target offset to the starting offset, generates a new target and resets the counter to zero. This proves elapsed frames in the beam step blend interval; l00 qualifies the exact D_L00_00161B54 binding. --- src/overlays/shared/weapons/suckcannon.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/weapons/suckcannon.c b/src/overlays/shared/weapons/suckcannon.c index 321ccf5a45..81992131c2 100644 --- a/src/overlays/shared/weapons/suckcannon.c +++ b/src/overlays/shared/weapons/suckcannon.c @@ -610,7 +610,7 @@ extern float D_L00_00161B80 MACRO_ADDR; extern float D_L00_00161B84 MACRO_ADDR; extern int suck_beam_reset_pending __asm__("D_L00_00161B40") __attribute__((sda)); extern int suck_beam_particles_reset_pending __asm__("D_L00_00161B44") __attribute__((sda)); -extern int D_L00_00161B54 __attribute__((sda)); +extern int l00_suck_beam_step_blend_elapsed_frames __asm__("D_L00_00161B54") __attribute__((sda)); extern int suck_beam_wave_phase __asm__("D_L00_00161B58") __attribute__((sda)); extern short D_L00_001E6008[]; extern V41 l00_suck_beam_ring_source_offsets[] __asm__("D_L00_001E4B40"); @@ -2887,7 +2887,7 @@ void suck_beam_build(char *cannon_moby, char *suction_origin) { D_L00_00161B80 = initial_random_angle; } suck_beam_texture_v_step = 0.006f; - D_L00_00161B54 = 0; + l00_suck_beam_step_blend_elapsed_frames = 0; suck_beam_wave_phase = 0; if (suck_beam_particles_reset_pending != 0) { suck_beam_particles_reset_pending = 0; @@ -2955,12 +2955,12 @@ void suck_beam_update(void *moby, void *position) { transform_vector_by_basis(&end, &(*(V41 *)D_L00_00161B70), orientation); fast_vec_add(&end, &end, &step); beam_step_blend_fraction = - (float)D_L00_00161B54 / convert_integer_to_float(scale_game_frames(60)); - D_L00_00161B54++; + (float)l00_suck_beam_step_blend_elapsed_frames / convert_integer_to_float(scale_game_frames(60)); + l00_suck_beam_step_blend_elapsed_frames++; step.f.x = start.f.x + (end.f.x - start.f.x) * beam_step_blend_fraction; step.f.y = start.f.y + (end.f.y - start.f.y) * beam_step_blend_fraction; step.f.z = start.f.z + (end.f.z - start.f.z) * beam_step_blend_fraction; - if (D_L00_00161B54 >= scale_game_frames(60)) { + if (l00_suck_beam_step_blend_elapsed_frames >= scale_game_frames(60)) { qcopy(&(*(V41 *)D_L00_00161B60), &(*(V41 *)D_L00_00161B70)); fast_vec_normalize(&axis, orientation, D_L00_00161B84); tmp_a.q = 0; @@ -2973,7 +2973,7 @@ void suck_beam_update(void *moby, void *position) { fast_add_rotations(D_L00_00161B80, random_float_between(45.0f, 315.0f) * 0.0174532924f); build_look_at_matrix(&(*(V41 *)D_L00_00161B70), &tmp_a, angle, &tmp_b); D_L00_00161B80 = angle; - D_L00_00161B54 = 0; + l00_suck_beam_step_blend_elapsed_frames = 0; } (*(float *)&suck_beam_wave_phase_gp) = fast_add_rotations((*(float *)&suck_beam_wave_phase_gp), 0.1f); From 15a4e74b99b9b1819fc9dc0c14d93bcf2d048c79 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:53:47 +0000 Subject: [PATCH 0101/1502] decomp: clarify names in animate_beam_barrier_strands D_L06_00161E08 -> l06_beam_barrier_strand_length: Retail 0x002f70ac loads the scalar at gp-0x4df8 (D_L06_00161E08); 0x002f70b4-0x002f70d0 divides it by 30 into f21, while 0x002f70c4-0x002f70d8 multiplies it by 0.5 and negates it into f20. At 0x002f7138 f20 is stored into each strand point's Y component in D_L06_001DB0F0; 0x002f714c advances it by f21 through the 30-point initialization loop. Thus this f32 is the nominal strand length governing longitudinal spacing and initial half-length offset. The supplied update_beam_barrier source additionally uses D_L06_00161E08 * 0.5f as the symmetric displacement bound for sparks along the segment's transformed Y direction. --- src/overlays/l06/mobys/beam_barrier.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l06/mobys/beam_barrier.c b/src/overlays/l06/mobys/beam_barrier.c index 95279d233c..e722aa34a1 100644 --- a/src/overlays/l06/mobys/beam_barrier.c +++ b/src/overlays/l06/mobys/beam_barrier.c @@ -51,7 +51,7 @@ extern float l06_beam_barrier_segment_euler_rotations[] __asm__ extern int D_L06_00161E40[] MACRO_ADDR; extern int D_L06_00161E50; extern int D_L06_00161E54; -extern f32 D_L06_00161E08 __attribute__((sda)); +extern f32 l06_beam_barrier_strand_length __asm__("D_L06_00161E08") __attribute__((sda)); extern float l06_beam_barrier_transform_scale __asm__("D_L06_00161E0C") __attribute__((sda)); float beam_barrier_collision_z_offset_gp __asm__("D_L06_00161E18") = 2.25f; extern int beam_barrier_burst_color_from_gp __asm__("D_L06_00161E1C") __attribute__((sda)); @@ -304,7 +304,7 @@ void beam_barrier_update(struct Moby *moby) { fast_vec_add(work.shared.collision.delta, work.point, pos); work.shared.collision.delta[3] = 1.0f; do { - radius = randf_sym(0.0f, D_L06_00161E08 * 0.5f); + radius = randf_sym(0.0f, l06_beam_barrier_strand_length * 0.5f); fast_vec_normalize(work.offset, column, radius); fast_vec_add(work.offset, work.offset, work.shared.collision.delta); blend = random_float_between(0.0f, 1.0f); @@ -462,8 +462,8 @@ void animate_beam_barrier_strands(struct Moby *moby) { if (phase > 1.0f) { D_L06_00161DFC = phase - 1.0f; } - step = D_L06_00161E08 / 30.0f; - y = -(D_L06_00161E08 * 0.5f); + step = l06_beam_barrier_strand_length / 30.0f; + y = -(l06_beam_barrier_strand_length * 0.5f); for (i = 0; i < 4; i++) { if (D_L06_00161E40[i] == 0) { for (k = 0; k < 30; k++) { From dfc037ff1c215e8336b6f771ae4539f28a160ef9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:53:57 +0000 Subject: [PATCH 0102/1502] decomp: clarify names in homing_spark_draw D_L18_00161F08 -> l18_homing_spark_quad_texture_ids: Source indexes four int-width values starting at D_L18_00161F08 and passes each to get_effect_texture_c, storing its return in pkt[i].b. Retail 0x002ea3d0-0x002ea408 adds quad_index*4 to gp-0x4cf8, loads the ID and calls the texture helper; 0x002ea440 stores its returned texture state in that quad packet. data -> homing_spark_private_vars: Source initializes data from MOBY(moby)->pvars; retail 0x002ea234-0x002ea23c saves the pointer loaded at moby+0x78. Reads at private offsets +0x24, +0x2c and +0x30 supply quad scale/color interpolation and the two rotating quad angles. m -> quad_transform_matrices: The float m[4][4][4] receives four euler_rotation_matrix outputs at retail stack offsets 0x250, 0x290, 0x2d0 and 0x310. Selected basis rows are scaled and each fourth row receives moby position; 0x002ea524-0x002ea560 passes each matrix with its corresponding quad packet to the draw helper. p -> quad_packet: Source assigns p=&pkt[i] in the four-quad loop and writes its texture result, fixed state, combined state and zero header fields. Retail 0x002ea40c-0x002ea480 computes the 0x90-byte packet stride and writes the corresponding fields at offsets 0x78, 0x80, 0x88 and 0x70. rot -> quad_euler_angles: Retail 0x002ea238 clears the stack vector at sp+0x240, 0x002ea264 and 0x002ea29c store camera-relative angles in its components, and 0x002ea308/0x002ea358 replace its first component with private rotation angles. Source passes this vector to euler_rotation_matrix for each quad. --- .../l18/mobys/drek_boss_electric_ball.c | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/overlays/l18/mobys/drek_boss_electric_ball.c b/src/overlays/l18/mobys/drek_boss_electric_ball.c index 58646119f5..bd3f471ca1 100644 --- a/src/overlays/l18/mobys/drek_boss_electric_ball.c +++ b/src/overlays/l18/mobys/drek_boss_electric_ball.c @@ -206,59 +206,59 @@ extern int D_L18_00161EE8 __attribute__((sda)); extern int D_L18_00161EEC __attribute__((sda)); extern int D_L18_00161EF0 __attribute__((sda)); extern int D_L18_00161EF8 __attribute__((sda)); -extern int D_L18_00161F08 __attribute__((sda)); +extern int l18_homing_spark_quad_texture_ids __asm__("D_L18_00161F08") __attribute__((sda)); extern void fast_draw_quad_real(void *, void *, int) __asm__("FUN_001f7d30"); void homing_spark_draw(char *moby) __asm__("FUN_L18_002ea1f8"); void homing_spark_draw(char *moby) { Pkt pkt[4]; - float rot[4]; - float m[4][4][4]; - char *data = ((char *)MOBY(moby)->pvars); + float quad_euler_angles[4]; + float quad_transform_matrices[4][4][4]; + char *homing_spark_private_vars = ((char *)MOBY(moby)->pvars); - clear_u64_value(rot); - rot[2] = fast_arc_tan(l18_camera_lui.pos.f[0] - MOBY(moby)->pos.x, + clear_u64_value(quad_euler_angles); + quad_euler_angles[2] = fast_arc_tan(l18_camera_lui.pos.f[0] - MOBY(moby)->pos.x, l18_camera_lui.pos.f[1] - MOBY(moby)->pos.y); - rot[1] = -fast_arc_tan(vector_distance_xy(moby + 0x10, &l18_camera_lui.pos.f[0]), + quad_euler_angles[1] = -fast_arc_tan(vector_distance_xy(moby + 0x10, &l18_camera_lui.pos.f[0]), l18_camera_lui.pos.f[2] - MOBY(moby)->pos.z); - euler_rotation_matrix(m[0][0], rot); - euler_rotation_matrix(m[1][0], rot); - fast_vec_scale(m[1][1], m[1][1], *(float *)(data + 0x24)); - fast_vec_scale(m[1][2], m[1][2], *(float *)(data + 0x24)); - qcopy(m[0][3], moby + 0x10); - qcopy(m[1][3], moby + 0x10); - rot[0] = *(float *)(data + 0x2C); - euler_rotation_matrix(m[2][0], rot); - fast_vec_scale(m[2][1], m[2][1], *(float *)(data + 0x24)); - fast_vec_scale(m[2][2], m[2][2], *(float *)(data + 0x24)); - qcopy(m[2][3], moby + 0x10); - rot[0] = *(float *)(data + 0x30); - euler_rotation_matrix(m[3][0], rot); - fast_vec_scale(m[3][1], m[3][1], *(float *)(data + 0x24)); - fast_vec_scale(m[3][2], m[3][2], *(float *)(data + 0x24)); - qcopy(m[3][3], moby + 0x10); + euler_rotation_matrix(quad_transform_matrices[0][0], quad_euler_angles); + euler_rotation_matrix(quad_transform_matrices[1][0], quad_euler_angles); + fast_vec_scale(quad_transform_matrices[1][1], quad_transform_matrices[1][1], *(float *)(homing_spark_private_vars + 0x24)); + fast_vec_scale(quad_transform_matrices[1][2], quad_transform_matrices[1][2], *(float *)(homing_spark_private_vars + 0x24)); + qcopy(quad_transform_matrices[0][3], moby + 0x10); + qcopy(quad_transform_matrices[1][3], moby + 0x10); + quad_euler_angles[0] = *(float *)(homing_spark_private_vars + 0x2C); + euler_rotation_matrix(quad_transform_matrices[2][0], quad_euler_angles); + fast_vec_scale(quad_transform_matrices[2][1], quad_transform_matrices[2][1], *(float *)(homing_spark_private_vars + 0x24)); + fast_vec_scale(quad_transform_matrices[2][2], quad_transform_matrices[2][2], *(float *)(homing_spark_private_vars + 0x24)); + qcopy(quad_transform_matrices[2][3], moby + 0x10); + quad_euler_angles[0] = *(float *)(homing_spark_private_vars + 0x30); + euler_rotation_matrix(quad_transform_matrices[3][0], quad_euler_angles); + fast_vec_scale(quad_transform_matrices[3][1], quad_transform_matrices[3][1], *(float *)(homing_spark_private_vars + 0x24)); + fast_vec_scale(quad_transform_matrices[3][2], quad_transform_matrices[3][2], *(float *)(homing_spark_private_vars + 0x24)); + qcopy(quad_transform_matrices[3][3], moby + 0x10); { int i; int j; - Pkt *p; + Pkt *quad_packet; for (i = 0; i < 4; i++) { { long r = - ((long (*)(int))get_effect_texture_c)(((int *)&(*(short *)&D_L18_00161F08))[i]); - p = &pkt[i]; - p->b = r; + ((long (*)(int))get_effect_texture_c)(((int *)&(*(short *)&l18_homing_spark_quad_texture_ids))[i]); + quad_packet = &pkt[i]; + quad_packet->b = r; } - p->c = 0xFF9000000260; - p->d = (D_L18_00161EE4) | (long)(D_L18_00161EE8) << 2 | (long)(D_L18_00161EEC) << 4 | + quad_packet->c = 0xFF9000000260; + quad_packet->d = (D_L18_00161EE4) | (long)(D_L18_00161EE8) << 2 | (long)(D_L18_00161EEC) << 4 | (long)(D_L18_00161EF0) << 6 | 0x8000L << 24; - p->a = 0; + quad_packet->a = 0; for (j = 0; j < 4; j++) { pkt[i].uv[j][0] = homing_spark_quad_uvs[j][0]; pkt[i].uv[j][1] = homing_spark_quad_uvs[j][1]; if (i == 0) { pkt[0].color[j] = fast_tween_color_c( - D_L18_00161EF8 & 0xFFFFFF, D_L18_00161EF8, *(float *)(data + 0x24)); + D_L18_00161EF8 & 0xFFFFFF, D_L18_00161EF8, *(float *)(homing_spark_private_vars + 0x24)); } else { pkt[i].color[j] = ((int *)&(*(short *)&D_L18_00161EF8))[i]; } @@ -266,10 +266,10 @@ void homing_spark_draw(char *moby) { } } } - fast_draw_quad_real(&pkt[0], m[0], 0); - fast_draw_quad_real(&pkt[1], m[1], 0); - fast_draw_quad_real(&pkt[2], m[2], 0); - fast_draw_quad_real(&pkt[3], m[3], 0); + fast_draw_quad_real(&pkt[0], quad_transform_matrices[0], 0); + fast_draw_quad_real(&pkt[1], quad_transform_matrices[1], 0); + fast_draw_quad_real(&pkt[2], quad_transform_matrices[2], 0); + fast_draw_quad_real(&pkt[3], quad_transform_matrices[3], 0); } extern float random_float_between(float, float) __asm__("FUN_002132a8"); From 4b9b3358c1a2cb267a94f639d52069f1109d75db Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:54:07 +0000 Subject: [PATCH 0103/1502] decomp: clarify names in hoverboard_update D_L05_0016190C -> l05_hoverboard_effect_initial_color: Retail 0x002f8a3c loads gp-0x52f4 (D_L05_0016190C) into a2 for spawn_effect at 0x002f8a58; 0x002f8aec repeats that load for spawn_burst at 0x002f8b0c. In the bound C these are the third arguments. Supplied spawn_effect stores initial_color at particle+4 and particle_data[4]; supplied burst implementation likewise stores initial_color at particle+4 and particle_data+0x10. Thus this L05 binding supplies the initial particle color. D_L05_00161910 -> l05_hoverboard_effect_color_endpoint: Retail 0x002f8a44, 0x002f8aa4 and 0x002f8af4 load gp-0x52f0 (D_L05_00161910) into a3 for the two spawn_effect calls and spawn_burst. The bound C passes this global as their fourth argument, including when initial color is literal 0x5032f0d2. Supplied spawn_effect stores color_endpoint in particle_data[5]; supplied burst stores final_color at particle_data+0x14. These independent paths prove its shared particle color endpoint role in this L05 binding. --- src/overlays/shared/vehicles/hoverboard.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/vehicles/hoverboard.c b/src/overlays/shared/vehicles/hoverboard.c index 00a0969968..5f343e5b90 100644 --- a/src/overlays/shared/vehicles/hoverboard.c +++ b/src/overlays/shared/vehicles/hoverboard.c @@ -22,8 +22,8 @@ extern unsigned short D_00141938 NOT_SDA; extern unsigned short D_00141C60 NOT_SDA; extern int D_L05_0015F6A8; -extern int D_L05_0016190C __attribute__((sda)); -extern int D_L05_00161910 __attribute__((sda)); +extern int l05_hoverboard_effect_initial_color __asm__("D_L05_0016190C") __attribute__((sda)); +extern int l05_hoverboard_effect_color_endpoint __asm__("D_L05_00161910") __attribute__((sda)); void hoverboard_update(unsigned char *moby) __asm__("FUN_L05_002f87a8"); @@ -96,19 +96,19 @@ void hoverboard_update(unsigned char *moby) { if ((unsigned char)MOBY(moby)->command == 0) { int size = random_int_between(scale_game_frames(10), scale_game_frames(13)); spawn_effect( - position, effect_position, D_L05_0016190C, D_L05_00161910, size, 15, 15, 1); + position, effect_position, l05_hoverboard_effect_initial_color, l05_hoverboard_effect_color_endpoint, size, 15, 15, 1); MOBY(moby)->command = 0; return; } fast_vec_scale(second_position, delta, 0.920f); { int size = random_int_between(scale_game_frames(15), scale_game_frames(18)); - spawn_effect(position, second_position, 0x5032f0d2, D_L05_00161910, size, 30, 20, 1); + spawn_effect(position, second_position, 0x5032f0d2, l05_hoverboard_effect_color_endpoint, size, 30, 20, 1); } { int size = random_int_between(scale_game_frames(8), scale_game_frames(17)); FUN_L00_0026cbb0( - position, effect_position, D_L05_0016190C, D_L05_00161910, size, 1, 15000.0f); + position, effect_position, l05_hoverboard_effect_initial_color, l05_hoverboard_effect_color_endpoint, size, 1, 15000.0f); } } MOBY(moby)->command = 0; From 3b09fa2ae3fc32f520cf99ff0136c3dc0fca3fe2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:54:15 +0000 Subject: [PATCH 0104/1502] decomp: clarify names in initialize_path_camera D_L10_0016CEC0 -> l10_camera_view: Retail 002f5c24/002f5c2c constructs base 0x0016CEC0 and 002f5c34 loads float +0xB0 (0x0016CF70). 002f5c3c..002f5c58 passes 1.0f and that field to fast_arc_tan, doubles the angle and saves it as stops->fov_end. Original decompilation expresses the same load as uRam0016cf70. The authoritative VendorView_5f18 declaration identifies this field as tan_half_fov; supplied update_path_flythrough_camera writes sin(half FOV)/cos(half FOV) back to this same object's field during restoration and interpolation, then calls update_view_context(). Thus this is camera view state, with l10 qualifying the assigned overlay binding; preserve assembler label D_L10_0016CEC0 and the exact declared type. --- src/overlays/shared/camera/path_flythrough_camera.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/camera/path_flythrough_camera.c b/src/overlays/shared/camera/path_flythrough_camera.c index 1bf2b5b760..d190c0aa99 100644 --- a/src/overlays/shared/camera/path_flythrough_camera.c +++ b/src/overlays/shared/camera/path_flythrough_camera.c @@ -84,7 +84,7 @@ extern struct { char *source; } D_L10_00167100; -extern VendorView_5f18 D_L10_0016CEC0; +extern VendorView_5f18 l10_camera_view __asm__("D_L10_0016CEC0"); void initialize_path_camera(struct UpdateCam *path_camera) __asm__("FUN_L10_002f5b58"); @@ -117,7 +117,7 @@ void initialize_path_camera(struct UpdateCam *path_camera) { pos = &path_camera->pos; m1 = (Vec4f *)&path_camera->m1; m2 = (Vec4f *)&path_camera->m2; - stops->fov_end = fast_arc_tan(1.0f, D_L10_0016CEC0.tan_half_fov) * 2.0f; + stops->fov_end = fast_arc_tan(1.0f, l10_camera_view.tan_half_fov) * 2.0f; if (*(int *)(rec + 0x20) >= 0) { char *path = ((char *)l10_paths[*(int *)(rec + 0x20)]); int i = 0; @@ -256,7 +256,7 @@ void update_path_flythrough_camera(struct UpdateCam *cam) { run->started = 3; D_L10_0015F3FC = 1.0f; ang = stops->fov_end * 0.5f; - D_L10_0016CEC0.tan_half_fov = fast_sin(ang) / fast_cos(ang); + l10_camera_view.tan_half_fov = fast_sin(ang) / fast_cos(ang); update_view_context(); *(u8 *)(rec + 0x39) = 1; D_L10_00167358 = 0.05f; @@ -308,7 +308,7 @@ void update_path_flythrough_camera(struct UpdateCam *cam) { total += *(float *)(path + (after * 16 + 0x1C)); ang = cosine_interpolate(stops->fov[i], stops->fov[i + 1], sum / total) * 0.017453292f * 0.5f; - D_L10_0016CEC0.tan_half_fov = fast_sin(ang) / fast_cos(ang); + l10_camera_view.tan_half_fov = fast_sin(ang) / fast_cos(ang); update_view_context(); } } From c6a56aa748462a0d633370dbbdb362771afbc001 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:54:24 +0000 Subject: [PATCH 0105/1502] decomp: clarify names in update_floating_mine D_L17_00161D2C -> l17_bobbing_vertical_amplitude: Retail 0x002dc56c loads this binding into f12, the first float argument of update_moby_vertical_oscillation called at 0x002dc578; original Ghidra passes uGpffffb12c in that same position. The authoritative source reinterprets D_L17_00161D2C as float for this argument. Supplied helper C computes sine_offset = fast_sin(*phase_angle) * x, stores it through previous_sine_offset, and adds it to moby->pos.z after subtracting the previous offset. Thus this binding is the vertical bobbing amplitude, independently of its unknown stored numeric value. Level qualifier identifies the owned L17 assembler binding. --- src/overlays/l17/mobys/floating_mine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l17/mobys/floating_mine.c b/src/overlays/l17/mobys/floating_mine.c index 2a8eb24d0c..40578684f5 100644 --- a/src/overlays/l17/mobys/floating_mine.c +++ b/src/overlays/l17/mobys/floating_mine.c @@ -41,7 +41,7 @@ extern void spawn_explosion(void *, int, int, int) __asm__("FUN_L00_0025e450"); -extern short D_L17_00161D2C __attribute__((sda)); +extern short l17_bobbing_vertical_amplitude __asm__("D_L17_00161D2C") __attribute__((sda)); extern short fleet_bobbing_phase_rate_degrees __asm__("D_L17_00161D30") __attribute__((sda)); extern void update_moby_vertical_oscillation(float, float, char *, float *, float *) __asm__("FUN_L00_00262b00"); extern int func_L00_001F2BE8_alt(float, void *, int, void *, void *) __asm__("FUN_L00_001f2868"); @@ -100,7 +100,7 @@ void floating_mine_update(struct Moby *moby) { moby->state = 1; break; case BOBBING_UPDATE_AND_CHECK_CONTACT: - update_moby_vertical_oscillation(*(float *)&D_L17_00161D2C, + update_moby_vertical_oscillation(*(float *)&l17_bobbing_vertical_amplitude, *(float *)&fleet_bobbing_phase_rate_degrees * DEG_TO_RAD * frame_time, moby, From 98d0e6e1d25793567c3643622d6860e2f6f04a0c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:54:24 +0000 Subject: [PATCH 0106/1502] decomp: clarify names in update_burning_debris s -> initial_particle_scalar: Authoritative burning_debris.c (SHA-256 a5a0996b9a6563b8717c5cde6b6f8ad32fdff2ecae9fbd8c5c33d44972f7bfa5) assigns s from random_float_between(0.5,1.5)*210000 and later random_float_between(40000,100000). Retail 0x0030bd38/0x0030bd5c passes the first through f20 to f12 at spawn_burst call 0x0030bd78; checked level-01 helper 0x00281c10 saves f12 at 0x00281c4c and stores it to allocated particle+0xC at 0x00281c98, also retaining its initial copy at +0x3C at 0x00281cc8. Retail 0x0030bdb8/0x0030bde8 passes the second through f20 to f15 at spawn_puff call 0x0030be00; checked helper 0x00282060 saves f15 to f22 at 0x0028209c and stores it to allocated particle+0xC at 0x00282104. Supplied original Ghidra decompilation agrees with both call flows, and supplied FUN_L00_0026cbb0 context names this role initial_particle_scalar. Thus both live ranges initialize a particle scalar, with physical meaning/units intentionally unspecified. --- src/overlays/l01/mobys/burning_debris.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l01/mobys/burning_debris.c b/src/overlays/l01/mobys/burning_debris.c index 2f61ffdea0..ebd3a8502c 100644 --- a/src/overlays/l01/mobys/burning_debris.c +++ b/src/overlays/l01/mobys/burning_debris.c @@ -69,7 +69,7 @@ void burning_debris_update(struct Moby *moby) { s32 grey_intensity; s32 alpha; s32 grey; - f32 s; + f32 initial_particle_scalar; u8 *puff; u8 *puff_data; @@ -128,12 +128,12 @@ void burning_debris_update(struct Moby *moby) { mark_moby_for_removal(moby); return; } - s = random_float_between(0.5f, 1.5f) * 210000.0f; + initial_particle_scalar = random_float_between(0.5f, 1.5f) * 210000.0f; spawn_burst(&moby->pos, &D_L01_0015F580, 0x4F007FFF, 0x1FFFFFFF, - s, + initial_particle_scalar, random_int_between(scale_game_frames(10), scale_game_frames(20)), 1); alpha = 0x60000000; @@ -142,7 +142,7 @@ void burning_debris_update(struct Moby *moby) { if (random_integer_below(2)) { signed_puff_variation = -signed_puff_variation; } - s = random_float_between(40000.0f, 100000.0f); + initial_particle_scalar = random_float_between(40000.0f, 100000.0f); grey_intensity = random_int_between(0x30, 0xFF); grey = (grey_intensity << 8) | alpha; puff = spawn_puff(&moby->pos, @@ -151,7 +151,7 @@ void burning_debris_update(struct Moby *moby) { 1.0f, signed_puff_variation, &D_L01_0015F580, - s, + initial_particle_scalar, grey_intensity | ((grey_intensity << 16) | grey)); if (puff != NULL) { puff[3] = 0x44; From 76a38419d304b5c413e1a44f7d80223601c073f8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:56:44 +0000 Subject: [PATCH 0107/1502] decomp: clarify names in process_horny_toad_hit_reaction D_L00_00161970_gp -> l00_horny_toad_knockback_gravity: Retail 0x002d524c/0x002d5260/0x002d5298 loads this scalar, multiplies by frame_time squared and stores toad_vars+0x80 (motion state+0x10). Checked sibling step_moby_motion at 0x0025c6d4-0x0025c6e8 subtracts that field from vertical displacement state+8 each update; 0x0025cde0-0x0025ce34 also uses it to reduce grounded motion toward zero. This proves the knockback gravity/deceleration coefficient, rather than an X force. D_L00_00161974_gp -> l00_horny_toad_knockback_horizontal_deceleration: Retail 0x002d5254/0x002d5268/0x002d52ac multiplies this scalar by frame_time squared and writes toad_vars+0x84, motion state+0x14. Checked step_moby_motion 0x0025c704-0x0025c738 obtains XY magnitude, passes state+0x14 as the approach_value step toward state+0x4c (or zero when grounded), then rescales the XY vector. It is the horizontal knockback deceleration coefficient. D_L00_00161978_gp -> l00_horny_toad_knockback_horizontal_speed: Retail 0x002d525c/0x002d5270/0x002d52b0 scales this global by frame_time into toad_vars+0x88 (knockback state+0x18). The supplied trooper_knockback_arc scales this XY magnitude by hit-vector XY length when applicable. Checked trooper_start_knockback 0x0025c594-0x0025c5d8 multiplies state+0x18 by cosine/sine of the hit angle into motion X/Y. Thus the global supplies horizontal knockback speed. D_L00_0016197C_gp -> l00_horny_toad_knockback_vertical_speed: Retail 0x002d5264/0x002d5278/0x002d52b4 scales this global by frame_time into toad_vars+0x8c (knockback state+0x1c). The supplied trooper_knockback_arc scales this Z magnitude by the hit-vector Z when applicable. Checked trooper_start_knockback 0x0025c5b0/0x0025c5cc copies state+0x1c into vertical motion state+8; step_moby_motion 0x0025c73c-0x0025c750 also uses it as the vertical-motion ceiling. This proves vertical knockback speed. --- src/overlays/shared/enemies/horny_toad.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/shared/enemies/horny_toad.c b/src/overlays/shared/enemies/horny_toad.c index b7760cf8d4..7e8cc98c15 100644 --- a/src/overlays/shared/enemies/horny_toad.c +++ b/src/overlays/shared/enemies/horny_toad.c @@ -137,10 +137,10 @@ extern float horny_toad_target_animation_start_index_gp __asm__("D_L00_00161984" extern short D_L00_00161960 __attribute__((sda)); extern s32 D_L00_0015F5C4_2d5160 __asm__("D_L00_0015F5C4"); -extern f32 D_L00_00161970_gp __asm__("D_L00_00161970") __attribute__((sda)); -extern f32 D_L00_00161974_gp __asm__("D_L00_00161974") __attribute__((sda)); -extern f32 D_L00_00161978_gp __asm__("D_L00_00161978") __attribute__((sda)); -extern f32 D_L00_0016197C_gp __asm__("D_L00_0016197C") __attribute__((sda)); +extern f32 l00_horny_toad_knockback_gravity __asm__("D_L00_00161970") __attribute__((sda)); +extern f32 l00_horny_toad_knockback_horizontal_deceleration __asm__("D_L00_00161974") __attribute__((sda)); +extern f32 l00_horny_toad_knockback_horizontal_speed __asm__("D_L00_00161978") __attribute__((sda)); +extern f32 l00_horny_toad_knockback_vertical_speed __asm__("D_L00_0016197C") __attribute__((sda)); extern f32 D_L00_00161988_gp __asm__("D_L00_00161988") __attribute__((sda)); extern f32 D_L00_0016198C_gp __asm__("D_L00_0016198C") __attribute__((sda)); extern unsigned char *D_L00_001B04B0_2d5160[] __asm__("D_L00_001B04B0"); @@ -491,10 +491,10 @@ void process_horny_toad_hit_reaction(unsigned char *toad_moby) { register f32 frame_time_reg __asm__("$f4") = frame_time; register f32 knockback_scale __asm__("$f4"); register f32 frame_time_sq_reg __asm__("$f0") = D_0015ED70; - forceX = D_L00_00161970_gp * frame_time_sq_reg; - forceY = D_L00_00161974_gp * frame_time_sq_reg; - forceZ = D_L00_00161978_gp * frame_time_reg; - forceW = D_L00_0016197C_gp * frame_time_reg; + forceX = l00_horny_toad_knockback_gravity * frame_time_sq_reg; + forceY = l00_horny_toad_knockback_horizontal_deceleration * frame_time_sq_reg; + forceZ = l00_horny_toad_knockback_horizontal_speed * frame_time_reg; + forceW = l00_horny_toad_knockback_vertical_speed * frame_time_reg; health = *(f32 *)(toad_vars + 0x20) - damage; toad_vars[0xAD] = 0; duration = frame_time + frame_time; From 6cf8fde1bbf0745288647f5e72751670a1c1edc4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:56:52 +0000 Subject: [PATCH 0108/1502] decomp: clarify names in update_drek_boss_state_dependent_scalars D_L18_001623DC_gp -> l18_drek_boss_second_scalar_near_node_follow_target_gp: Authoritative source src/overlays/l18/mobys/drek_final_boss_robot.c SHA-256 76f829e5c846d17f84f9f2dccaa3d8c71b85992319bd3b48813e768b4bd8ee2a declares this float with assembler label D_L18_001623DC. In boss_state 0x13's fallback, vector_distance_xy compares the hero position to the arena node at D_L18_001600EC + boss_data[0x344]*0x80 +0x30; only distance <28 selects this global as y. Retail 0x002f73e4-0x002f7408 computes that distance, 0x002f741c-0x002f7424 tests <28, and the branch delay slot at 0x002f7434 loads gp-0x4824 into f22. Retail 0x002f7644 moves f22 to the target argument f12, while 0x002f7638/0x002f764c supply selected_scalar_record+0x38 and boss_data+0x37c to the second accelerated update at 0x002f7660. Original Ghidra fGpffffb7dc -> fVar14 and the second final call corroborate this target role. --- src/overlays/l18/mobys/drek_final_boss_robot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/drek_final_boss_robot.c b/src/overlays/l18/mobys/drek_final_boss_robot.c index f82464d78b..37365b7606 100644 --- a/src/overlays/l18/mobys/drek_final_boss_robot.c +++ b/src/overlays/l18/mobys/drek_final_boss_robot.c @@ -2492,7 +2492,7 @@ extern short l18_drek_boss_scalar_acceleration_and_braking_gp __asm__("D_L18_001 #include "rnc/overlay/l18/mobys/drek_final_boss_robot_data/update_drek_boss_state_dependent_scalars_3.h" -extern float D_L18_001623DC_gp __asm__("D_L18_001623DC") __attribute__((sda)); +extern float l18_drek_boss_second_scalar_near_node_follow_target_gp __asm__("D_L18_001623DC") __attribute__((sda)); #include "rnc/overlay/l18/mobys/drek_final_boss_robot_data/update_drek_boss_state_dependent_scalars_2.h" @@ -2559,7 +2559,7 @@ void update_drek_boss_state_dependent_scalars(char *moby) { D_L18_001600EC + (*(int *)(boss_data + 0x344) << 7) + 0x30) < 28.0f) { x = drek_boss_first_scalar_near_node_follow_target_gp; - y = D_L18_001623DC_gp; + y = l18_drek_boss_second_scalar_near_node_follow_target_gp; } } } else if (boss_state == 9 || boss_state == 6) { From 3c27265da613f729c58ffda5d3804f1c40f6b3d1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:57:01 +0000 Subject: [PATCH 0109/1502] decomp: clarify names in update_alien_snapper_hit_response_and_targeting D_L06_00161ED0 -> l06_alien_snapper_base_targeting_radius: Authoritative alien_snapper.c snapshot SHA-256 568ddaaa938ce805bf2963091f1925ba5ae66af40b5c0159df417ca355f476b5 declares this float and uses it as the base pvars+0x1A0 targeting distance. Original retail Ghidra fGpffffb2d0 agrees with retail 0x002f957c loading gp-0x4d30, 0x002f9580-0x002f958c adding 6.0 when pvars+0x1AC is nonzero, and 0x002f9598-0x002f95d0 storing the base or state-1 overrides into +0x1A0. At 0x002f95e8-0x002f9610 that distance is passed in f12 to the route search with output +0x120 and route data indexed by +0x1B0. At 0x002f961c-0x002f9634 it bounds XY distance from home +0x170 to the selected point +0x120, setting target status +0x164 to 2 when exceeded. Supplied alien_snapper_update also compares this same global directly with hero XY distance before entering approach state 8, corroborating a base targeting radius. Preserve the exact assembler binding D_L06_00161ED0, float type, SDA attribute and stored bytes. --- src/overlays/l06/mobys/alien_snapper.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l06/mobys/alien_snapper.c b/src/overlays/l06/mobys/alien_snapper.c index 77b2dffe06..470ee56752 100644 --- a/src/overlays/l06/mobys/alien_snapper.c +++ b/src/overlays/l06/mobys/alien_snapper.c @@ -133,7 +133,7 @@ extern float D_L06_00161EB0 __attribute__((sda)); extern float D_L06_00161EB4 __attribute__((sda)); extern float D_L06_00161EC4 __attribute__((sda)); extern float D_L06_00161EC8 __attribute__((sda)); -extern float D_L06_00161ED0 __attribute__((sda)); +extern float l06_alien_snapper_base_targeting_radius __asm__("D_L06_00161ED0") __attribute__((sda)); extern float D_L06_00161ED4 __attribute__((sda)); extern int D_L06_00161EDC __attribute__((sda)); extern int D_L06_00161EE0 __attribute__((sda)); @@ -316,7 +316,7 @@ void alien_snapper_update(Moby *moby) { if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 0); } - vars->f1A0 = D_L06_00161ED0; + vars->f1A0 = l06_alien_snapper_base_targeting_radius; } break; case 1: @@ -338,7 +338,7 @@ void alien_snapper_update(Moby *moby) { } } } else if (moby->anim_flags & 2) { - if (vector_distance_xy(&moby->pos, ((char *)&D_0013F3D0)) < D_L06_00161ED0) { + if (vector_distance_xy(&moby->pos, ((char *)&D_0013F3D0)) < l06_alien_snapper_base_targeting_radius) { moby->state = 8; vars->angle_jitter = random_float_between(vars->jitter_degrees * 0.017453292f, -(vars->jitter_degrees * 0.017453292f)); @@ -814,7 +814,7 @@ void update_alien_snapper_hit_response_and_targeting(Moby *moby) { D_L06_00161EE8, D_L06_00161EEC, (fast_sin(snapper_vars->f1C8) + 1.0f) * 0.5f); if (snapper_vars->f1AC != 0) { - snapper_vars->f1A0 = D_L06_00161ED0 + 6.0f; + snapper_vars->f1A0 = l06_alien_snapper_base_targeting_radius + 6.0f; } else if (moby->state == 1) { if (moby == ((Moby *)hero.unk240) || moby == ((Moby *)hero.coll_hit_moby)) { snapper_vars->f1A0 = 6.0f; @@ -822,7 +822,7 @@ void update_alien_snapper_hit_response_and_targeting(Moby *moby) { snapper_vars->f1A0 = 0.0f; } } else { - snapper_vars->f1A0 = D_L06_00161ED0; + snapper_vars->f1A0 = l06_alien_snapper_base_targeting_radius; } if (activate_effect_l08(snapper_vars->f1A0, From a6c00629a00794174488fc735c76d0f5dafa6861 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:57:12 +0000 Subject: [PATCH 0110/1502] decomp: clarify names in open_vendor_menu D_L00_00161E18 -> l00_vendor_close_pending: Retail open_vendor_menu at 0029a7b8-0029a7bc clears s32 00161E18, also explicitly cleared in original Ghidra. In the authoritative same-file update_vendor_menu source, cancel button 0x10 sets this global to 1 and vendor_close_delay_frames_remaining to 8. While it equals 1, that delay decrements until the menu enters closing state 2; nonzero also gates further selection/purchase input. This proves delayed vendor close pending. D_L00_00161E20 -> l00_vendor_opening_countdown_active: Retail 0029a7c0-0029a7c4 clears s32 00161E20, matching original Ghidra and authoritative open_vendor_menu C. The supplied update_vendor_menu source sets it to 1 when opening state 0 transitions to open state 1, together with vendor_opening_countdown_frames=8. Its only supplied subsequent branch decrements that countdown while this flag is 1, then clears the flag when the countdown reaches zero, proving opening countdown active. D_L00_00161E30 -> l00_vendor_previous_pressed_buttons: Retail 0029a7c8-0029a7cc clears s32 00161E30 on entry, as original Ghidra also shows. Authoritative update_vendor_menu assigns controller_state.pressed_unmasked to it after update_vendor_purchase each frame. Both update functions accept pressed button masks 0x2000/0x8000/0x40/0x10 only when corresponding bits in this stored mask are absent. This proves it stores the previous update's pressed buttons for vendor input suppression. --- src/overlays/shared/vendor/vendor_menu.c | 40 ++++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/overlays/shared/vendor/vendor_menu.c b/src/overlays/shared/vendor/vendor_menu.c index e5b55b0f83..38254a251e 100644 --- a/src/overlays/shared/vendor/vendor_menu.c +++ b/src/overlays/shared/vendor/vendor_menu.c @@ -331,10 +331,10 @@ typedef struct { extern VendorMenu vendor_menu __asm__("D_L00_001CA4C0"); extern VendorSlot vendor_slots[4] __asm__("D_L00_00165E80"); -extern s32 D_L00_00161E18; -extern s32 D_L00_00161E20; +extern s32 l00_vendor_close_pending __asm__("D_L00_00161E18"); +extern s32 l00_vendor_opening_countdown_active __asm__("D_L00_00161E20"); extern s32 D_L00_00161E24_29a6b0 __asm__("D_L00_00161E24"); -extern s32 D_L00_00161E30; +extern s32 l00_vendor_previous_pressed_buttons __asm__("D_L00_00161E30"); extern s32 D_L00_00161E34; extern unsigned char D_0013F350[]; extern Vec4 D_L00_00180260_29a6b0 __asm__("D_L00_00180260"); @@ -392,9 +392,9 @@ void open_vendor_menu(void *vendor_moby_arg) { vendor_menu.unk44 = 0; vendor_menu.purchased_item = vendor_menu.title_text = vendor_menu.item_text = -1; vendor_menu.cursor = 0; - D_L00_00161E18 = 0; - D_L00_00161E20 = 0; - D_L00_00161E30 = 0; + l00_vendor_close_pending = 0; + l00_vendor_opening_countdown_active = 0; + l00_vendor_previous_pressed_buttons = 0; vendor_menu.purchase_state = 0; D_L00_00161E34 = 0; D_L00_00161E24_29a6b0 = 0; @@ -981,7 +981,7 @@ void update_vendor_purchase(void) { } } if (controller_state.pressed_unmasked & 0x10) { - if (!(D_L00_00161E30 & 0x10)) { + if (!(l00_vendor_previous_pressed_buttons & 0x10)) { vendor_menu.purchase_state = 3; vendor_purchase_confirmed_gp = 0; blend_moby_animation(&vendor_menu.menu_mobys[4], @@ -993,7 +993,7 @@ void update_vendor_purchase(void) { } } if (controller_state.pressed_unmasked & 0x40) { - if (!(D_L00_00161E30 & 0x40)) { + if (!(l00_vendor_previous_pressed_buttons & 0x40)) { vendor_menu.purchase_state = 3; vendor_purchase_confirmed_gp = 1; blend_moby_animation(&vendor_menu.menu_mobys[4], @@ -1186,7 +1186,7 @@ void update_vendor_menu(void) { vendor_menu.frames = 0; FUN_00212f90(vendor_menu.vendor_moby, 3, 0, 8); vendor_menu.vendor_moby->f58 = 1.0f; - D_L00_00161E20 = 1; + l00_vendor_opening_countdown_active = 1; vendor_opening_countdown_frames = 8; allocate_voice_for_target_entry(4, 0, vendor_menu.vendor_moby); } @@ -1339,9 +1339,9 @@ void update_vendor_menu(void) { &vendor_menu.menu_mobys[3].pos, &position_contribution_scratch); vendor_menu.frames++; - if (vendor_menu.purchase_state == 0 && D_L00_00161E18 == 0) { + if (vendor_menu.purchase_state == 0 && l00_vendor_close_pending == 0) { if (vendor_menu.row_count < 8) { - if ((controller_state.pressed_unmasked & 0x2000) && !(D_L00_00161E30 & 0x2000)) { + if ((controller_state.pressed_unmasked & 0x2000) && !(l00_vendor_previous_pressed_buttons & 0x2000)) { if (vendor_menu.cursor < vendor_menu.row_count - 1) { D_L00_00161E38 = 1; handle_vendor_auxiliary_moby_event(0); @@ -1364,7 +1364,7 @@ void update_vendor_menu(void) { } } } - if ((controller_state.pressed_unmasked & 0x8000) && !(D_L00_00161E30 & 0x8000)) { + if ((controller_state.pressed_unmasked & 0x8000) && !(l00_vendor_previous_pressed_buttons & 0x8000)) { if (vendor_menu.cursor > 0) { D_L00_00161E38 = 1; handle_vendor_auxiliary_moby_event(0); @@ -1388,7 +1388,7 @@ void update_vendor_menu(void) { } } } else { - if ((controller_state.pressed_unmasked & 0x2000) && !(D_L00_00161E30 & 0x2000)) { + if ((controller_state.pressed_unmasked & 0x2000) && !(l00_vendor_previous_pressed_buttons & 0x2000)) { if (vendor_menu.scroll <= 0x38) { D_L00_00161E38 = 1; vendor_menu.scroll += 0x38; @@ -1416,7 +1416,7 @@ void update_vendor_menu(void) { } } } - if ((controller_state.pressed_unmasked & 0x8000) && !(D_L00_00161E30 & 0x8000)) { + if ((controller_state.pressed_unmasked & 0x8000) && !(l00_vendor_previous_pressed_buttons & 0x8000)) { if (vendor_menu.scroll >= -0x38) { D_L00_00161E38 = 1; vendor_menu.scroll -= 0x38; @@ -1445,27 +1445,27 @@ void update_vendor_menu(void) { } } } - if ((controller_state.pressed_unmasked & 0x40) && !(D_L00_00161E30 & 0x40) && + if ((controller_state.pressed_unmasked & 0x40) && !(l00_vendor_previous_pressed_buttons & 0x40) && CUR_ITEM.state == 0) { vendor_menu.purchase_state = 1; allocate_voice_for_target_entry(0, 0, vendor_menu.vendor_moby); } if ((controller_state.pressed_unmasked & 0x10) && D_L00_0016118C == 0) { vendor_close_delay_frames_remaining = 8; - D_L00_00161E18 = 1; + l00_vendor_close_pending = 1; allocate_voice_for_target_entry(5, 0, vendor_menu.vendor_moby); } } update_vendor_purchase(); - D_L00_00161E30 = controller_state.pressed_unmasked; - if (D_L00_00161E20 == 1) { + l00_vendor_previous_pressed_buttons = controller_state.pressed_unmasked; + if (l00_vendor_opening_countdown_active == 1) { if (vendor_opening_countdown_frames == 0) { - D_L00_00161E20 = 0; + l00_vendor_opening_countdown_active = 0; } else { vendor_opening_countdown_frames--; } } - if (D_L00_00161E18 == 1) { + if (l00_vendor_close_pending == 1) { if (--vendor_close_delay_frames_remaining == 0) { D_L00_0015F5D8 = 1; select_level_vu_chain(); From aa36639f5c293b1a14ff4db29527596498490f60 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:57:12 +0000 Subject: [PATCH 0111/1502] decomp: clarify names in update_linked_spark_emitter e -> emitter_voice_slot: In the authoritative linked_spark_emitter.c snapshot (SHA-256 75541c60373378012443b452df35a0359adaf1d7b3e357ba5e93cb83e750dd10), Voice *e is voice_pool + moby[0xBC] * 0x70. Retail 0x002a2d50 loads that slot byte; 0x002a2d64-0x002a2d74 multiplies by 0x70 and adds 0x0013e550. Instructions 0x002a2d78-0x002a2d88 check owner at +0x88 against the emitter and active at +0x74. Failure calls allocate_voice_for_target_entry(0,4,moby) at 0x002a2d90-0x002a2d9c and stores the replacement slot at moby+0xBC (0x002a2da0). Original Ghidra shows the same indexed pool ownership/activity checks; supplied voice-release context independently identifies these as voice-slot fields. --- src/overlays/shared/props/linked_spark_emitter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/props/linked_spark_emitter.c b/src/overlays/shared/props/linked_spark_emitter.c index 7fbc7aa6f8..f102faf406 100644 --- a/src/overlays/shared/props/linked_spark_emitter.c +++ b/src/overlays/shared/props/linked_spark_emitter.c @@ -105,10 +105,10 @@ void linked_spark_emitter_update(unsigned char *moby) { visited52[(unsigned char)MOBY(moby)->mission + (D_0015ED84 << 4)] == 0xFF) { mark_moby_killed_and_release_owned_voice(moby); } else { - Voice *e = (Voice *)((unsigned char *)&voice_pool + MOBY(moby)->command * 0x70); + Voice *emitter_voice_slot = (Voice *)((unsigned char *)&voice_pool + MOBY(moby)->command * 0x70); float lo, hi, z, one; int i; - if (e->owner != (char *)moby || e->active == 0) { + if (emitter_voice_slot->owner != (char *)moby || emitter_voice_slot->active == 0) { MOBY(moby)->command = allocate_voice_for_target_entry(0, 4, moby); } fast_vec_sub(V, D_0013F420, &MOBY(moby)->pos); From 3e1ef84eade3a0a0d2f770faf819213b834a49b6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:57:23 +0000 Subject: [PATCH 0112/1502] decomp: clarify names in draw_target_beam D_00151878_gp -> scoutbot_target_beam_vertex_0_color: Retail 0x002d38d0 loads GP-0x5388 into v1 and 0x002d3900 stores it at sp+0x40. The original decompilation copies uGpffffac78 into uStack_170; the authoritative Packet_002d3878 layout and C assignment identify this exact D_00151878 assembler binding as pk.color[0] for the target beam quad. D_0015187C_gp -> scoutbot_target_beam_vertex_1_color: Retail 0x002d38c8 loads GP-0x5384 into a1 and 0x002d38f8 stores it at sp+0x44. The original decompilation copies uGpffffac7c into uStack_16c; Packet_002d3878 and the C assignment prove the exact D_0015187C binding supplies pk.color[1] in the target beam quad. D_00151880_gp -> scoutbot_target_beam_vertex_2_color: Retail 0x002d38e0 loads GP-0x5380 into a3 and 0x002d3910 stores it at sp+0x48. The original decompilation copies uGpffffac80 into uStack_168; Packet_002d3878 and the C assignment prove the exact D_00151880 binding supplies pk.color[2] in the target beam quad. D_00151884_gp -> scoutbot_target_beam_vertex_3_color: Retail 0x002d38e8 loads GP-0x537c into t0 and 0x002d3914 stores it at sp+0x4c. The original decompilation copies uGpffffac84 into uStack_164; Packet_002d3878 and the C assignment prove the exact D_00151884 binding supplies pk.color[3] in the target beam quad. data -> scoutbot_private_vars: Retail 0x002d38bc loads s5 from moby+0x78 (moby->pvars), matching data in C and iVar6 in the original decompilation. Loads at 0x002d3950/0x002d3978 use its +0x218 current_target, and 0x002d3a10 onward read its +0x1d0/+0x1e0 glow vectors, proving scoutbot private instance variables. pos -> beam_origin_position: Retail 0x002d3904/0x002d390c/0x002d3940 calls moby_point_position(moby,2,sp+0xd0), the C pos binding. At 0x002d3950-0x002d3964 that position is subtracted from current_target->pos; 0x002d3980-0x002d3990 subtracts its original Z, and 0x002d39ec-0x002d39f4 copies it to the matrix translation. This is the beam origin position. --- src/overlays/shared/enemies/scoutbot.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/shared/enemies/scoutbot.c b/src/overlays/shared/enemies/scoutbot.c index c38f68e7d1..864cff7699 100644 --- a/src/overlays/shared/enemies/scoutbot.c +++ b/src/overlays/shared/enemies/scoutbot.c @@ -453,9 +453,9 @@ void update_scoutbot_health_and_target(struct Moby *moby) { } void draw_target_beam(struct Moby *moby) { - ScoutbotVars *data = (ScoutbotVars *)moby->pvars; + ScoutbotVars *scoutbot_private_vars = (ScoutbotVars *)moby->pvars; Packet_002d3878 pk; - Vec_002d3878 matrix[3], direction, pos, delta, angles; + Vec_002d3878 matrix[3], direction, beam_origin_position, delta, angles; float length; u64 tag; Vec_002d3878 *points; @@ -464,10 +464,10 @@ void draw_target_beam(struct Moby *moby) { float *vertex; int i; tag = get_effect_texture(14); - pk.color[0] = D_00151878_gp; - pk.color[1] = D_0015187C_gp; - pk.color[2] = D_00151880_gp; - pk.color[3] = D_00151884_gp; + pk.color[0] = scoutbot_target_beam_vertex_0_color; + pk.color[1] = scoutbot_target_beam_vertex_1_color; + pk.color[2] = scoutbot_target_beam_vertex_2_color; + pk.color[3] = scoutbot_target_beam_vertex_3_color; pk.tag[1] = tag; pk.tag[2] = 0xff9000000260ULL; pk.tag[0] = 5; @@ -480,17 +480,17 @@ void draw_target_beam(struct Moby *moby) { pk.uv[5] = 1.0f; pk.uv[6] = 1.0f; pk.uv[7] = 1.0f; - moby_point_position(moby, 2, &pos); - fast_vec_sub(&delta, data->unk218 + 0x10, &pos); + moby_point_position(moby, 2, &beam_origin_position); + fast_vec_sub(&delta, data->unk218 + 0x10, &beam_origin_position); scale_vector_002d3878(3.0f, &delta); - delta.v[2] = (*(float *)(data->unk218 + 0x18) + 0.25f) - pos.v[2]; + delta.v[2] = (*(float *)(data->unk218 + 0x18) + 0.25f) - beam_origin_position.v[2]; delta.v[3] = 1.0f; length = fast_vec_length(&delta); clear_u64_value(&angles); angles.v[1] = -fast_arc_tan(vector_length_xy(&delta), delta.v[2]); angles.v[2] = fast_arc_tan(delta.v[0], delta.v[1]); euler_rotation_matrix(matrix, &angles); - qcopy(&direction, &pos); + qcopy(&direction, &beam_origin_position); direction.v[3] = 1.0f; clear_u64_value(&pk.vertices[0]); From bb2ad1d4dad34b5ce8b33dedea57233861aaee6b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:59:47 +0000 Subject: [PATCH 0113/1502] decomp: clarify names in draw_hud_segment_meter D_L06_0015F8E8 -> l06_hud_segment_meter_center_x: Retail 0x002497a0 loads this s32 via -0x7318(gp). At 0x00249868..0x00249874, segments*16 is subtracted to obtain start_x; each segment is 32 pixels wide and x advances by 32 at 0x002498b0. The loaded coordinate therefore centers the complete segments*32 span. The source explicitly caches this binding as center_x. D_L06_0015F8F0 -> l06_hud_segment_meter_last_segment_fill_scale: Retail 0x002498f8..0x00249908 computes step=1/segments and limit=(segments-1)*step and branches on limit l06_hud_segment_meter_first_segment_fill_scale: Retail 0x00249920..0x00249938 checks fill meter_state: Retail 0x00249768 retains a0 in s4. Reads at 0x002497bc and 0x002497e0 use byte +0x70 to gate drawing and derive opacity; 0x002498b8..0x002498e0 use signed +0x74 divided by converted +8 for fill. 0x00249a8c returns word +0x58. This is the state consumed by draw_hud_segment_meter, without asserting a concrete structure or gameplay quantity. --- .../shared/ui/hud/draw_hud_segment_meter.c | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/overlays/shared/ui/hud/draw_hud_segment_meter.c b/src/overlays/shared/ui/hud/draw_hud_segment_meter.c index 817d9b3755..32bf30fc1a 100644 --- a/src/overlays/shared/ui/hud/draw_hud_segment_meter.c +++ b/src/overlays/shared/ui/hud/draw_hud_segment_meter.c @@ -11,20 +11,20 @@ #include "rnc/ui/hud.h" extern s32 frame_size __asm__("D_0013E504") NOT_SDA; -extern s32 D_L06_0015F8E8 __attribute__((sda)); -extern f32 D_L06_0015F8F0 __attribute__((sda)); -extern f32 D_L06_0015F8F4 __attribute__((sda)); +extern s32 l06_hud_segment_meter_center_x __asm__("D_L06_0015F8E8") __attribute__((sda)); +extern f32 l06_hud_segment_meter_last_segment_fill_scale __asm__("D_L06_0015F8F0") __attribute__((sda)); +extern f32 l06_hud_segment_meter_first_segment_fill_scale __asm__("D_L06_0015F8F4") __attribute__((sda)); extern s32 fast_tween_color(s32, s32, f32) __asm__("FUN_001fa6e0"); s32 draw_hud_segment_meter(u8 *p) __asm__("FUN_L06_00249738"); -s32 draw_hud_segment_meter(u8 *p) { +s32 draw_hud_segment_meter(u8 *meter_state) { s32 y; s32 ntsc_y; s32 level; s32 segments = 3; s32 x, start_x, inner, i, color, remaining, tile_count, k; - s32 center_x = D_L06_0015F8E8; + s32 center_x = l06_hud_segment_meter_center_x; f32 alpha, scaled_alpha, fill, step, limit; /* Fakematch: computing this row before the default one gives retail's order. */ @@ -37,15 +37,15 @@ s32 draw_hud_segment_meter(u8 *p) { segments = 6; if (level == 18) segments = 7; - if (p[0x70] == 0) - return *(s32 *)(p + 0x58); + if (meter_state[0x70] == 0) + return *(s32 *)(meter_state + 0x58); { if (level == 13) { y = 18; if (pal_mode != 0) y = 10; } - alpha = convert_integer_to_float(p[0x70]) * 0.125f; + alpha = convert_integer_to_float(meter_state[0x70]) * 0.125f; if (alpha > 1.0f) alpha = 1.0f; else if (alpha < 0.0f) @@ -62,17 +62,17 @@ s32 draw_hud_segment_meter(u8 *p) { } x = 0; color = 0x800000ff; - if (*(s32 *)(p + 0x74) != 0) { - fill = (f32) * (s32 *)(p + 0x74) / convert_integer_to_float(*(s32 *)(p + 8)); + if (*(s32 *)(meter_state + 0x74) != 0) { + fill = (f32) * (s32 *)(meter_state + 0x74) / convert_integer_to_float(*(s32 *)(meter_state + 8)); step = 1.0f / convert_integer_to_float(segments); limit = remaining * step; if (limit < fill) { fill -= limit; - fill *= D_L06_0015F8F0; + fill *= l06_hud_segment_meter_last_segment_fill_scale; fill += limit; } else if (fill < step) { fill -= step; - fill *= D_L06_0015F8F4; + fill *= l06_hud_segment_meter_first_segment_fill_scale; fill += step; } x = truncate_float_to_s32((f32)(segments << 5) * fill); @@ -97,7 +97,7 @@ s32 draw_hud_segment_meter(u8 *p) { draw_hud_sprite(get_icon_frame(0x7562, 4), segments, y - 8, 48, 48, i); draw_hud_sprite(get_icon_frame(0x7562, 0), segments, y - 8, 48, 48, i); } - return *(s32 *)(p + 0x58); + return *(s32 *)(meter_state + 0x58); } s32 D_L07_0015F8E8 = 0x114; From 722412e9ceef88d62ad5133852d35e1c6f90e20a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:00:00 +0000 Subject: [PATCH 0114/1502] decomp: clarify names in thruster_pack_lock_update D_L11_001BAFD0 -> l11_thruster_pack_lock_activation_state: Retail 0x0030ef54-0x0030ef74 loads moby+0xB0, rejects 0xFF, sign-extends UID from moby+0xB2, forms base 0x001BAFD0 and stores group+2 at base+0x454+UID. This follows the hero ground-moby, item, air-frame and state 0x22 activation checks at 0x0030ef08-0x0030ef48. The authoritative C represents this as LvState.collected[UID], recording activation before the lock enters state 2 and lowers its height. D_L11_001BBC30 -> l11_thruster_pack_lock_restore_state: Retail initialization 0x0030ee70-0x0030ee8c forms base 0x001BBC30 and reads its byte at +0x454+signed moby UID. A nonzero byte selects state 2 and height minus 1.5 at 0x0030eec4-0x0030eee8, restoring an activated lock instead of entering active state 1. Retail 0x0030ef78-0x0030efc4 conditionally stores group+2 to the same UID byte after group/visited checks; the authoritative C binds both accesses to this LvState.collected object. --- src/overlays/shared/props/thruster_pack_lock.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/props/thruster_pack_lock.c b/src/overlays/shared/props/thruster_pack_lock.c index 877a7d2624..cfeb82f875 100644 --- a/src/overlays/shared/props/thruster_pack_lock.c +++ b/src/overlays/shared/props/thruster_pack_lock.c @@ -88,8 +88,8 @@ extern s32 allocate_voice_for_target_entry() __asm__("func_0022DA68"); extern unsigned char D_0013F350[]; s32 FUN_L00_00203908(s32 a, s32 b); extern unsigned char D_0014171B_3102C8[] __asm__("D_0013F350"); -extern LvState D_L11_001BBC30; -extern LvState D_L11_001BAFD0; +extern LvState l11_thruster_pack_lock_restore_state __asm__("D_L11_001BBC30"); +extern LvState l11_thruster_pack_lock_activation_state __asm__("D_L11_001BAFD0"); extern unsigned char D_L11_0015FD08_3102C8[] __asm__("D_L11_0015FC88"); void thruster_pack_lock_update(Lock *moby) __asm__("FUN_L11_0030ee00"); @@ -109,7 +109,7 @@ void thruster_pack_lock_update(Lock *moby) { ((Stats *)(D_00141968_r))->best = 0; *(unsigned short *)(vars + 0x3E) |= 8; if (level == 0xB && moby->bB0 != 0xFF) { - if (D_L11_001BBC30.collected[(short)moby->uid] != 0 || + if (l11_thruster_pack_lock_restore_state.collected[(short)moby->uid] != 0 || ((*(int *)(D_0014C190_r + (((short)moby->uid >> 5) * 4 + (level << 8))) >> (moby->uid & 0x1F)) & 1)) { @@ -129,13 +129,13 @@ void thruster_pack_lock_update(Lock *moby) { if (current_level_index == 0xB && moby->bB0 != 0xFF) { int group; int group_index; - D_L11_001BAFD0.collected[(short)moby->uid] = moby->bB0 + 2; + l11_thruster_pack_lock_activation_state.collected[(short)moby->uid] = moby->bB0 + 2; group = moby->bB0; group_index = group & 0xFF; if (group == 0xFF || (D_L11_0015FD08_3102C8[group_index] != 0xFF && (visited52)[group_index + (current_level_index << 4)] == 0xFF)) { - D_L11_001BBC30.collected[(short)moby->uid] = group + 2; + l11_thruster_pack_lock_restore_state.collected[(short)moby->uid] = group + 2; } } moby->state = 2; From ecfab5a956c72cd19d83a91e447088f03d9edb61 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:00:00 +0000 Subject: [PATCH 0115/1502] decomp: clarify names in gadgebot_update switch_0_case_7 -> GADGEBOT_SUCK_CANNON_SUCTION: Retail 0x002fbbbc dispatches the gadgebot Moby byte state at +0x20, not hero.state.current. The authoritative source update_moby_suck_cannon_state (FUN_L18_002fcbb0) calls process_moby_suck_cannon_suction, writes moby->state=7 for nonzero suction_result, and restores state 2 when that result is zero and current state is 7. Case 7 in original retail decompilation and 0x002fbd3c-0x002fbd58 passes this Moby and pvars+0x70 to checked helper 0x002e6d80, then on nonzero completion writes state 2 and clears pvars+0x138. This establishes the gadgebot suction state in its own local domain, independent of equal-valued HERO_STATE_JUMP. --- src/overlays/l18/mobys/gadgebot.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/gadgebot.c b/src/overlays/l18/mobys/gadgebot.c index 70e4724a1a..7dd611551b 100644 --- a/src/overlays/l18/mobys/gadgebot.c +++ b/src/overlays/l18/mobys/gadgebot.c @@ -79,7 +79,8 @@ void gadgebot_update(unsigned char *moby) { GADGEBOT_APPROACH_TARGET = 3, GADGEBOT_FACE_TARGET = 4, GADGEBOT_DEATH_FALL = 5, - GADGEBOT_EXPLODE = 6 + GADGEBOT_EXPLODE = 6, + GADGEBOT_SUCK_CANNON_SUCTION = 7 }; char position_scratch[16]; unsigned char *moby_vars = ((unsigned char *)MOBY(moby)->pvars); @@ -132,7 +133,7 @@ void gadgebot_update(unsigned char *moby) { } break; } - case 7: + case GADGEBOT_SUCK_CANNON_SUCTION: if (FUN_L00_002dc9f0(moby, moby_vars + 0x70)) { MOBY(moby)->state = 2; *(short *)(moby_vars + 0x138) = 0; From 487b610d1be3a9400e8eaf9c921838cf9021c628 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:00:00 +0000 Subject: [PATCH 0116/1502] decomp: clarify names in tresspasser_update data -> gadget_pickup_state: Retail 0x002ea23c loads s2 from moby+0x78, matching data=(char *)moby->pvars. In the gadget pickup handler, 0x002ea4d4/0x002ea4e0 pass this private block's +0x40/+0x44 fields to advance_accelerated_scalar; 0x002ea5c4..0x002ea630 repeatedly read +0x40 as the position and rotation interpolation fraction. This is the gadget pickup's persistent private state, not an arbitrary data buffer. switch_0_case_0 -> GADGET_PICKUP_STATE_INITIALIZE: Retail 0x002ea24c reads the moby state byte +0x20 for dispatch. Case 0 at 0x002ea294 initializes collectible sprite state, tests items_acquired for the class-selected inventory index at 0x002ea2a8, probes ground and initializes orientation/height, then writes state 1 at 0x002ea2fc; an already-owned pickup is removed. This is pickup initialization. switch_0_case_1 -> GADGET_PICKUP_STATE_WAIT_FOR_PLAYER: In the same moby+0x20 state domain, case 1 at 0x002ea30c rotates the pickup and updates its sprite effect. 0x002ea350..0x002ea398 require player XY distance below 1 and absolute Z separation below 2 before hiding the pickup, disabling collision, storing state 3 at 0x002ea3b0 and starting scene 2 or 4. It waits for player proximity. switch_0_case_3 -> GADGET_PICKUP_STATE_GRANT_ITEM: Case 3 at 0x002ea3e4 first waits while level_game_mode equals 2, then 0x002ea410/0x002ea420/0x002ea434 call grant_inventory_item with the class-selected 0x16 or 0x1A inventory index. The ordinary pickup is saved and removed at 0x002ea4a4..0x002ea4b0; class 0x3ED instead enters state 4 after dialogue/help and camera setup. Granting the acquired item is this state handler's common action. switch_0_case_4 -> GADGET_PICKUP_STATE_CAMERA_SEQUENCE: Case 4 at 0x002ea4bc advances private state fields +0x40/+0x44 toward interpolation completion; 0x002ea5d0 interpolates two fixed camera positions and 0x002ea5dc..0x002ea630 interpolates rotations. 0x002ea66c/0x002ea674 set camera position/rotation. On the approached scalar reaching 1, 0x002ea73c restores camera mode, 0x002ea744 ends the mount and 0x002ea754 writes state 5. These operations prove the scripted camera sequence state. switch_0_case_5 -> GADGET_PICKUP_STATE_SAVE_AND_REMOVE: The camera-sequence exit writes 5 to moby+0x20 at 0x002ea754. Case 5 at 0x002ea758..0x002ea790 approaches D_L02_0015F3FC toward zero and waits until equality; 0x002ea79c calls memcard_save_data(0,-1), then 0x002ea7a4 marks this pickup moby for removal. This is the terminal save-and-remove state, without assuming what the scalar renders. --- src/overlays/shared/pickups/gadget_pickup.c | 35 ++++++++++++--------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/overlays/shared/pickups/gadget_pickup.c b/src/overlays/shared/pickups/gadget_pickup.c index b8f58e8853..b4b562be12 100644 --- a/src/overlays/shared/pickups/gadget_pickup.c +++ b/src/overlays/shared/pickups/gadget_pickup.c @@ -65,17 +65,24 @@ void tresspasser_update(struct Moby *moby) __asm__("FUN_L02_002ea210"); /* Moby classes 1005, 1016 */ void tresspasser_update(struct Moby *moby) { - char *data; + enum { + GADGET_PICKUP_STATE_INITIALIZE = 0, + GADGET_PICKUP_STATE_WAIT_FOR_PLAYER = 1, + GADGET_PICKUP_STATE_GRANT_ITEM = 3, + GADGET_PICKUP_STATE_CAMERA_SEQUENCE = 4, + GADGET_PICKUP_STATE_SAVE_AND_REMOVE = 5 + }; + char *gadget_pickup_state; int which; int frames; float angle; float ground_offset; - data = (char *)moby->pvars; + gadget_pickup_state = (char *)moby->pvars; frames = scale_game_frames(60); angle = 3.14159274f / (float)frames; which = moby->oclass == 0x3ED ? 0x1A : 0x16; switch (moby->state) { - case 0: + case GADGET_PICKUP_STATE_INITIALIZE: FUN_L02_002ea7d0_c(moby); ground_offset = 0.2f; if (items_acquired[which] == 0) { @@ -88,7 +95,7 @@ void tresspasser_update(struct Moby *moby) { } mark_moby_for_removal(moby); return; - case 1: + case GADGET_PICKUP_STATE_WAIT_FOR_PLAYER: moby->rot.z = fast_add_rotations(moby->rot.z, angle); FUN_L02_002ea8b0_c(moby); if (D_L02_0015F5CC % 10 != 0) @@ -107,7 +114,7 @@ void tresspasser_update(struct Moby *moby) { } } return; - case 3: + case GADGET_PICKUP_STATE_GRANT_ITEM: if (level_game_mode == 2) return; if (D_001413F4 != 0) { @@ -132,7 +139,7 @@ void tresspasser_update(struct Moby *moby) { memcard_save_data(0, -1); mark_moby_for_removal(moby); return; - case 4: { + case GADGET_PICKUP_STATE_CAMERA_SEQUENCE: { float a[4] __attribute__((aligned(16))), b[4] __attribute__((aligned(16))), c[4] __attribute__((aligned(16))), d[4] __attribute__((aligned(16))); float position[4] __attribute__((aligned(16))); @@ -158,20 +165,20 @@ void tresspasser_update(struct Moby *moby) { D_0015ED70 * 0.15f, D_0015ED70 * 0.15f, D_0015ED6C * 0.15f, - data + 0x40, - data + 0x44); - lerp_vector(position, (void *)a, (void *)b, *(float *)(data + 0x40)); + gadget_pickup_state + 0x40, + gadget_pickup_state + 0x44); + lerp_vector(position, (void *)a, (void *)b, *(float *)(gadget_pickup_state + 0x40)); output[2] = - fast_add_rotations(fast_subtract_rotations(d[2], c[2]) * *(float *)(data + 0x40), c[2]); + fast_add_rotations(fast_subtract_rotations(d[2], c[2]) * *(float *)(gadget_pickup_state + 0x40), c[2]); output[1] = - fast_add_rotations(fast_subtract_rotations(d[1], c[1]) * *(float *)(data + 0x40), c[1]); + fast_add_rotations(fast_subtract_rotations(d[1], c[1]) * *(float *)(gadget_pickup_state + 0x40), c[1]); output[0] = - fast_add_rotations(fast_subtract_rotations(d[0], c[0]) * *(float *)(data + 0x40), c[0]); + fast_add_rotations(fast_subtract_rotations(d[0], c[0]) * *(float *)(gadget_pickup_state + 0x40), c[0]); if (D_L02_00167400 && *(short *)(D_L02_00167400 + 0x86) != 5) jet_mount(position, output, 1, 0, 0); set_camera_position(position); set_camera_rotation(output); - if (D_L02_00179A10.i0 == 0 && D_L02_00179A10.i24 == -1 && 0.2f < *(float *)(data + 0x40)) { + if (D_L02_00179A10.i0 == 0 && D_L02_00179A10.i24 == -1 && 0.2f < *(float *)(gadget_pickup_state + 0x40)) { approach_value(1.0f, frame_time * 4.0f, &D_L02_0015F3FC); } else { approach_value(0.0f, D_0015ED6C * 4.0f, &D_L02_0015F3FC); @@ -183,7 +190,7 @@ void tresspasser_update(struct Moby *moby) { moby->state = 5; return; } - case 5: + case GADGET_PICKUP_STATE_SAVE_AND_REMOVE: approach_value(0.0f, D_0015ED6C * 4.0f, &D_L02_0015F3FC); if (D_L02_0015F3FC == 0.0f) { memcard_save_data(0, -1); From b3ddacf097059543210dbb1b772d0558b5709459 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:00:13 +0000 Subject: [PATCH 0117/1502] decomp: clarify names in update_blarg_paratrooper_damage_and_state D_L08_00162180 -> l08_paratrooper_model_scale_multiplier: Retail 0x00302508 loads this float at gp-0x4a80; 0x0030250c loads the moby's pclass+0x24 model scale. Their product at 0x00302514 is stored to moby+0x2c at 0x00302524, exactly the source Moby.scale assignment. This proves a paratrooper model-scale multiplier owned by level 08. D_L08_0016218C -> l08_paratrooper_recovery_knockback_xy_speed: At 0x003026f0 this float is loaded from gp-0x4a74, multiplied by frame_time and stored at private-state+0x88 (0x0030271c) for reactions 3 through 8. trooper_knockback_arc receives that address as its xy_scaled_value, then trooper_start_knockback receives private-state+0x70 and the moby enters recovery state 10. Checked helper 0x00266a84-0x00266ac8 consumes motion+0x18 (= private-state+0x88) as the magnitude for the two horizontal components at motion+0 and +4. D_L08_00162190 -> l08_paratrooper_death_knockback_z_speed: Retail 0x003027b0 loads gp-0x4a70, multiplies by frame_time at 0x003027c0, and stores to private-state+0x8c at 0x003027fc in the branch entering death state 11. This address is trooper_knockback_arc's z_scaled_value. Checked start helper 0x00266aa0/0x00266abc copies motion+0x1c (= private-state+0x8c) to motion+8, the vertical component alongside horizontal components +0/+4. D_L08_00162194 -> l08_paratrooper_death_knockback_xy_speed: Retail 0x003027ac loads gp-0x4a6c, multiplies it by frame_time at 0x003027bc and stores it to private-state+0x88 at 0x003027ec. The reaction 1/2 branch passes this through trooper_knockback_arc's xy_scaled_value, starts knockback, and stores death state 11 at 0x00302864. Checked start helper 0x00266a84-0x00266ac8 uses motion+0x18 (= private-state+0x88) to form horizontal components at motion+0 and +4. data -> paratrooper_instance_state: At 0x00302500 retail loads s1 from moby+0x78, matching data = (char *)MOBY(moby)->pvars in the authoritative source. All later s1-relative accesses are this paratrooper instance's health (+0x20), attached moby (+0x1f8), animation (+0x60), motion (+0x70), and tracked target (+0x160). It is the instance private state, not hit-descriptor data. switch_0_case_1 -> PARATROOPER_HIT_REACTION_LETHAL: The selector is resolve_moby_hit_response's return overridden after health subtraction: 0x0030264c-0x0030265c subtracts damage from private-state+0x20 and tests health <= 0; 0x00302674 forces the reaction to 1 on that condition. This case shares death knockback setup, stores moby state 11 at 0x00302864, and invokes the bolt-drop helper at 0x0030287c. It is a lethal hit reaction, not a HeroStateId. --- .../shared/enemies/blarg_paratrooper.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/shared/enemies/blarg_paratrooper.c b/src/overlays/shared/enemies/blarg_paratrooper.c index 9baf5f6ba7..28e884af1b 100644 --- a/src/overlays/shared/enemies/blarg_paratrooper.c +++ b/src/overlays/shared/enemies/blarg_paratrooper.c @@ -155,11 +155,11 @@ extern void trooper_anim_update(void *, void *) __asm__("FUN_L00_0025d458"); extern void trooper_anim_finish(void *, void *) __asm__("FUN_L00_0025d538"); extern int activate_effect_l08(void *, void *, float, int, int, void *, int) __asm__("FUN_L00_0025ff38"); -extern float D_L08_00162180 __attribute__((sda)); +extern float l08_paratrooper_model_scale_multiplier __asm__("D_L08_00162180") __attribute__((sda)); extern float D_L08_00162184 __attribute__((sda)); -extern float D_L08_0016218C __attribute__((sda)); -extern float D_L08_00162190 __attribute__((sda)); -extern float D_L08_00162194 __attribute__((sda)); +extern float l08_paratrooper_recovery_knockback_xy_speed __asm__("D_L08_0016218C") __attribute__((sda)); +extern float l08_paratrooper_death_knockback_z_speed __asm__("D_L08_00162190") __attribute__((sda)); +extern float l08_paratrooper_death_knockback_xy_speed __asm__("D_L08_00162194") __attribute__((sda)); extern float D_L08_001621B0 __attribute__((sda)); /* Paratrooper: initializes its path and steering, patrols, attacks its target, @@ -601,7 +601,7 @@ void blarg_paratrooper_update(char *moby) { /* Ported from rac1-decomp (src/overlays/shared/vendor_002D3DF8.c: func_L08_00303998), where it is exact; names translated to the US level program. */ void update_blarg_paratrooper_damage_and_state(char *moby) { - Paratrooper302618 *data; + enum { PARATROOPER_HIT_REACTION_LETHAL = 1 } ;Paratrooper302618 *data; char *target, *child, *attached, *chased; float pos[4] __attribute__((aligned(16))); float matrix[16] __attribute__((aligned(16))); @@ -609,12 +609,12 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { int hit_state, reaction, turn, state; float angle, distance, height, dx, dy; - data = (Paratrooper302618 *)MOBY(moby)->pvars; + paratrooper_instance_state = (Paratrooper302618 *)MOBY(moby)->pvars; if (MOBY(moby)->state == 0) return; { float timer_scale = D_L08_001621B0 * frame_time; - ((Moby *)moby)->scale = *(float *)(((char *)MOBY(moby)->pclass) + 0x24) * D_L08_00162180; + ((Moby *)moby)->scale = *(float *)(((char *)MOBY(moby)->pclass) + 0x24) * l08_paratrooper_model_scale_multiplier; data->unkF4 = timer_scale; } @@ -677,7 +677,7 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { case 6: case 7: case 8: { - float pose_scale = D_L08_0016218C * frame_time; + float pose_scale = l08_paratrooper_recovery_knockback_xy_speed * frame_time; float timer_scale = frame_time * 3.0f; data->unk88 = pose_scale; data->unk8C = timer_scale; @@ -698,12 +698,12 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { MOBY(moby)->state = 10; data->unk67 = 0x78; break; - case 1: + case PARATROOPER_HIT_REACTION_LETHAL: case 2: { float push_limit = 16.0f; float pose_rate = D_L08_00162184; - float timer_rate = D_L08_00162194; - float angle_rate = D_L08_00162190; + float timer_rate = l08_paratrooper_death_knockback_xy_speed; + float angle_rate = l08_paratrooper_death_knockback_z_speed; float step, pose_scale, timer_scale, angle_scale; ((Moby *)moby)->flags &= 0xefff; step = frame_time; From 469498248198ce750f2754c23f9d275f64c0c71c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:00:14 +0000 Subject: [PATCH 0118/1502] decomp: clarify names in leg_walker_update entry -> animation_record_cursor: The source declares entry as LegRigAnim **, initializes it from rig->anims via fallback, tests (*entry)->id against moby->seq, and selects *entry for animation-rate scaling. Retail 0x00295cd8 sets s1 to rig+0x70, 0x00295cf0 copies that array cursor to s0, 0x00295cf8/0x00295cfc dereference the record and its id, and 0x00295d00 compares the current sequence. At 0x00295d8c the cursor advances four bytes, bounded to 13 records at 0x00295d90; 0x00295d64 selects that record and 0x00295d6c reads its rate at +8. The original Ghidra puVar9 loop confirms the same role. old -> previous_mode: In the SHA-256-bound leg_walker_update source, old snapshots rig->mode before rig->mode = mode and feeds changed = (mode ^ old) & mode. Retail 0x00295a48 loads the previous byte from 0xb6(s2), 0x00295a50 stores the new mode, and 0x00295a54/0x00295a5c XOR and AND those values to detect newly enabled mode bits. The original Ghidra bVar1 and uVar7 data flow agrees. --- src/overlays/l04/mobys/leg_walker.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l04/mobys/leg_walker.c b/src/overlays/l04/mobys/leg_walker.c index b9cfe02cc8..9bca9b3b3c 100644 --- a/src/overlays/l04/mobys/leg_walker.c +++ b/src/overlays/l04/mobys/leg_walker.c @@ -468,10 +468,10 @@ s32 leg_walker_update(struct Moby *moby, LegRig *rig, f32 speed, f32 heading, f3 fast_vec_add(pos, pos, &shift); { f32 max_step = rig->unkC4; - s32 old = rig->mode; + s32 previous_mode = rig->mode; rig->mode = mode; - changed = (mode ^ old) & mode; + changed = (mode ^ previous_mode) & mode; if (max_step < step) step = max_step; } @@ -521,19 +521,19 @@ s32 leg_walker_update(struct Moby *moby, LegRig *rig, f32 speed, f32 heading, f3 moby->anim_speed = 1.0f; if (rig->unkB7 != 0) { LegRigAnim **fallback = rig->anims; - LegRigAnim **entry; + LegRigAnim **animation_record_cursor; s32 seq = moby->seq; f32 min_turn = 0.09239978f; - for (i = 0, entry = fallback; i < 13; i++) { - if ((*entry)->id == seq) { + for (i = 0, animation_record_cursor = fallback; i < 13; i++) { + if ((*animation_record_cursor)->id == seq) { LegRigAnim *anim; f32 rate; if (!(rig->speed < frame_time * 0.19f) || !(min_turn < fast_difference_between_rotations(moby->rot.z, heading)) || !(speed < (rate = frame_time * 0.19f))) { - anim = *entry; + anim = *animation_record_cursor; rate = rig->speed; } else { anim = *fallback; @@ -541,7 +541,7 @@ s32 leg_walker_update(struct Moby *moby, LegRig *rig, f32 speed, f32 heading, f3 moby->anim_speed = frame_scale_inv * absolute_float(rate / anim->rate); break; } - entry++; + animation_record_cursor++; fallback++; } } From 1ce378190ddb4fa3d40825e38a15354731921056 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:02:32 +0000 Subject: [PATCH 0119/1502] decomp: clarify names in break_apart_shuttle_linked_mobys D_L06_0016210C -> l06_shuttle_projected_sprite_start_color: In authoritative src/overlays/l06/mobys/shuttle.c SHA-256 0fb7fea4149e18c5f0f9ed33abfe14c8a02fec29da622e8f3dff698de905949e, this int supplies spawn_timed_projected_sprite_effect's established start_color parameter, both here and in shuttle_update. Retail 0x00303bec loads gp-0x4af4 into a2 before call 0x00303bf8; original Ghidra corroborates uGpffffb50c as the third argument. Checked level-06 helper 0x0030bf04 saves a2 in s5 and 0x0030bf70 stores it at class-0x076a pvars+8, exactly matching the supplied helper C start_color assignment. D_L06_00162110 -> l06_shuttle_projected_sprite_end_color: The authoritative shuttle.c snapshot passes this int as spawn_timed_projected_sprite_effect's established end_color parameter at both uses. Retail 0x00303bf4 loads gp-0x4af0 into a3 for call 0x00303bf8; original Ghidra records uGpffffb510 as the fourth argument. Checked level-06 helper 0x0030bf0c retains a3 in s4 and 0x0030bf64 stores it to the newly created class-0x076a moby's pvars+0xC, matching the supplied helper C end_color assignment. The level-qualified name reflects this overlay-owned binding. --- src/overlays/l06/mobys/shuttle.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l06/mobys/shuttle.c b/src/overlays/l06/mobys/shuttle.c index 7c176650bc..89c23972ec 100644 --- a/src/overlays/l06/mobys/shuttle.c +++ b/src/overlays/l06/mobys/shuttle.c @@ -136,8 +136,8 @@ int shuttle_forced_return_requested_gp __asm__("D_L06_00162100") = 0; #include "rnc/overlay/l06/mobys/shuttle_data/shuttle_update.h" -extern int D_L06_0016210C __attribute__((sda)); -extern int D_L06_00162110 __attribute__((sda)); +extern int l06_shuttle_projected_sprite_start_color __asm__("D_L06_0016210C") __attribute__((sda)); +extern int l06_shuttle_projected_sprite_end_color __asm__("D_L06_00162110") __attribute__((sda)); extern unsigned char D_0013D4D5[] NOT_SDA; /* Update of moby class 1109 (shuttle): waits at one of three camera points, takes the hero's choice of destination, flies there through a cutscene and hands over to the level's travel sequence. */ @@ -273,8 +273,8 @@ void shuttle_update(struct Moby *moby) { *(u128_302578 *)b = *(u128_302578 *)((char *)&hero.motion.pos + 0x50); spawn_timed_projected_sprite_effect((char *)b, scale_game_frames(class_076a_moby_rate_input_frames_gp), - D_L06_0016210C, - D_L06_00162110); + l06_shuttle_projected_sprite_start_color, + l06_shuttle_projected_sprite_end_color); } switch (moby->state) { case INITIALIZE_SHUTTLE: @@ -772,8 +772,8 @@ void break_apart_shuttle_linked_mobys(struct Moby *moby) { center[2] = 173.07f; spawn_timed_projected_sprite_effect(center, scale_game_frames(class_076a_moby_rate_input_frames_gp), - D_L06_0016210C, - D_L06_00162110); + l06_shuttle_projected_sprite_start_color, + l06_shuttle_projected_sprite_end_color); largest = 0.0f; clear_u64_value(middle); list = D_L06_001ABFC0_03b68[*(int *)(shuttle_linkage_vars + 0xCC)]; From 4bec5b9829ab49e334dd9ff7ffad010c00124e0b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:02:45 +0000 Subject: [PATCH 0120/1502] decomp: clarify names in pool_splash D_L00_00161218 -> l00_pool_height_write_bank_index: In the authoritative pool_splash C this s32 indexes tile->heights for the final height store and every neighbour copy. Retail 0x002a41d0 loads gp-0x59e8, 0x002a41dc multiplies it by bank stride 0x5c0, and 0x002a41ec stores the computed height into that bank. Retail 0x002a4134-0x002a4154 also reads that same bank for the magnitude-preserving mode. D_L00_00161220 -> l00_pool_height_additive_read_bank_index: In pool_splash's nonzero-mode branch, tile->heights[D_L00_00161220][row][col] is added to height. Retail 0x002a40f4 loads gp-0x59e0; the nonzero branch reaches 0x002a41b0, multiplies this s32 by 0x5c0, loads the cell at 0x002a41c8, and adds it at 0x002a41cc before storing through the separate write-bank index. D_L00_001CA880 -> l00_pool_height_grid_layout: The authoritative HeightGridLayout declaration supplies origin_x, origin_z, cell_width and cell_height to pool_splash. Retail 0x002a3f4c-0x002a3f84 addresses 0x001ca880, adds offsets +8/+0xc to tile coordinates, and divides coordinate differences by +0x10/+0x14. The same spacing fields advance sampled columns at 0x002a4494-0x002a44ac and rows at 0x002a44b0-0x002a44c0. --- .../shared/vendor/draw_vendor_purchase_text.c | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/overlays/shared/vendor/draw_vendor_purchase_text.c b/src/overlays/shared/vendor/draw_vendor_purchase_text.c index efa7068fe3..15e348258a 100644 --- a/src/overlays/shared/vendor/draw_vendor_purchase_text.c +++ b/src/overlays/shared/vendor/draw_vendor_purchase_text.c @@ -131,9 +131,9 @@ typedef struct { f32 origin_x, origin_z, cell_width, cell_height; } HeightGridLayout; -extern HeightGridLayout D_L00_001CA880; -extern s32 D_L00_00161218 __attribute__((sda)); -extern s32 D_L00_00161220 __attribute__((sda)); +extern HeightGridLayout l00_pool_height_grid_layout __asm__("D_L00_001CA880"); +extern s32 l00_pool_height_write_bank_index __asm__("D_L00_00161218") __attribute__((sda)); +extern s32 l00_pool_height_additive_read_bank_index __asm__("D_L00_00161220") __attribute__((sda)); /* Splash on the pool height tiles: raises the heights around (x, z) and copies the edges into the neighbour tiles. */ void pool_splash(HeightTile *tile, @@ -152,9 +152,9 @@ void pool_splash( int i; for (i = 0; i < count; i++) { - float tile_z = tile->z + D_L00_001CA880.origin_z; - float cell_z = (z - tile_z) / D_L00_001CA880.cell_height; - float cell_x = (x - (tile->x + D_L00_001CA880.origin_x)) / D_L00_001CA880.cell_width; + float tile_z = tile->z + l00_pool_height_grid_layout.origin_z; + float cell_z = (z - tile_z) / l00_pool_height_grid_layout.cell_height; + float cell_x = (x - (tile->x + l00_pool_height_grid_layout.origin_x)) / l00_pool_height_grid_layout.cell_width; int row_first, row_last, col_first, col_last; float row_z; @@ -170,11 +170,11 @@ void pool_splash( col_last = 15; if (col_first < 0) col_first = 0; - row_z = tile_z + D_L00_001CA880.cell_height * (float)row_first; + row_z = tile_z + l00_pool_height_grid_layout.cell_height * (float)row_first; for (row = row_first; row <= row_last; row++) { float col_x = - (tile->x + D_L00_001CA880.origin_x) + D_L00_001CA880.cell_width * (float)col_first; + (tile->x + l00_pool_height_grid_layout.origin_x) + l00_pool_height_grid_layout.cell_width * (float)col_first; int col; for (col = col_first; col <= col_last; col++) { @@ -188,14 +188,14 @@ void pool_splash( } if (mode == 0) { float magnitude = absolute_float(height); - if (magnitude < absolute_float(tile->heights[D_L00_00161218][row][col])) { - height = tile->heights[D_L00_00161218][row][col]; + if (magnitude < absolute_float(tile->heights[l00_pool_height_write_bank_index][row][col])) { + height = tile->heights[l00_pool_height_write_bank_index][row][col]; } } else { - height += tile->heights[D_L00_00161220][row][col]; + height += tile->heights[l00_pool_height_additive_read_bank_index][row][col]; } { - int cur = D_L00_00161218; + int cur = l00_pool_height_write_bank_index; tile->heights[cur][row][col] = height; if (row < 2 && tile->neighbours[0] != 0xFF) { @@ -209,51 +209,51 @@ void pool_splash( } if (col < 2 && tile->neighbours[1] != 0xFF) { if (col == 0) { - tiles[tile->neighbours[1]].heights[D_L00_00161218][19][row] = - tile->heights[D_L00_00161218][row][0]; + tiles[tile->neighbours[1]].heights[l00_pool_height_write_bank_index][19][row] = + tile->heights[l00_pool_height_write_bank_index][row][0]; } else { - tiles[tile->neighbours[1]].heights[D_L00_00161218][21][row] = - tile->heights[D_L00_00161218][row][col]; + tiles[tile->neighbours[1]].heights[l00_pool_height_write_bank_index][21][row] = + tile->heights[l00_pool_height_write_bank_index][row][col]; } } if (row == 15 && tile->neighbours[2] != 0xFF) { - int cur = D_L00_00161218; + int cur = l00_pool_height_write_bank_index; tiles[tile->neighbours[2]].heights[cur][16][col] = tile->heights[cur][row][col]; } if (col == 15 && tile->neighbours[3] != 0xFF) { - int cur = D_L00_00161218; + int cur = l00_pool_height_write_bank_index; tiles[tile->neighbours[3]].heights[cur][17][row] = tile->heights[cur][row][col]; } if (tile->neighbours[4] != 0xFF) { if (col == 0 && row == 0) { - int cur = D_L00_00161218; + int cur = l00_pool_height_write_bank_index; tiles[tile->neighbours[4]].heights[cur][22][3] = tile->heights[cur][row][col]; } if (col == 1 && row == 0) { - int cur = D_L00_00161218; + int cur = l00_pool_height_write_bank_index; tiles[tile->neighbours[4]].heights[cur][22][4] = tile->heights[cur][0][1]; } if (col == 0 && row == 1) { - int cur = D_L00_00161218; + int cur = l00_pool_height_write_bank_index; tiles[tile->neighbours[4]].heights[cur][22][5] = tile->heights[cur][1][0]; } } if (tile->neighbours[5] != 0xFF && col == 15 && row == 0) { - int cur = D_L00_00161218; + int cur = l00_pool_height_write_bank_index; tiles[tile->neighbours[5]].heights[cur][22][2] = tile->heights[cur][0][15]; } if (tile->neighbours[6] != 0xFF && col == 0 && row == 15) { - int cur = D_L00_00161218; + int cur = l00_pool_height_write_bank_index; tiles[tile->neighbours[6]].heights[cur][22][1] = tile->heights[cur][15][0]; } if (tile->neighbours[7] != 0xFF && col == 15 && row == 15) { - int cur = D_L00_00161218; + int cur = l00_pool_height_write_bank_index; tiles[tile->neighbours[7]].heights[cur][22][0] = tile->heights[cur][15][15]; } - col_x += D_L00_001CA880.cell_width; + col_x += l00_pool_height_grid_layout.cell_width; } - row_z += D_L00_001CA880.cell_height; + row_z += l00_pool_height_grid_layout.cell_height; } tile++; } From 33003abe4e68875c9b5f2b9a2b9b7a4e7b6f9478 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:02:56 +0000 Subject: [PATCH 0121/1502] decomp: clarify names in update_switchable_beam_barrier D_L06_0015FFD8 -> level_mobys_q: Retail 0x00304ae0 loads linked index from pvars+0xF10; 0x00304ae8-0x00304aec loads the pointer stored at 0x0015FFD8, then 0x00304af0-0x00304af4 shifts the index by 8 and adds it to that pointer. Reads at 0x00304af8 and 0x00304b04 inspect moby class +0xA6 (0x463) and state +0x20. The bound C WAIT_FOR_LINKED_MOBY branch exactly expresses D_L06_0015FFD8 + (vector_stream_vars->f10 << 8). This proves an indexed level moby array pointer with 0x100-byte records. level_mobys_q is the supplied existing name for this exact assembler label and is reused unchanged. --- src/overlays/l06/mobys/switchable_beam_barrier.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l06/mobys/switchable_beam_barrier.c b/src/overlays/l06/mobys/switchable_beam_barrier.c index cc6177453e..bc4d454de4 100644 --- a/src/overlays/l06/mobys/switchable_beam_barrier.c +++ b/src/overlays/l06/mobys/switchable_beam_barrier.c @@ -14,7 +14,7 @@ extern float D_L06_00167540[]; -extern char *D_L06_0015FFD8 __asm__("D_L06_0015FFD8"); +extern char *level_mobys_q __asm__("D_L06_0015FFD8"); extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); @@ -93,7 +93,7 @@ void switchable_beam_barrier_update(char *moby) { } break; case WAIT_FOR_LINKED_MOBY: { - char *e = D_L06_0015FFD8 + (vector_stream_vars->f10 << 8); + char *e = level_mobys_q + (vector_stream_vars->f10 << 8); if (*(short *)(e + 0xA6) == 0x463 && (unsigned char)e[0x20] < 3) { return; } @@ -151,7 +151,7 @@ void switchable_beam_barrier_update(char *moby) { add_draw_callback((int)draw_moby_vector_streams, moby); } if (vector_stream_vars->f14 >= 0 && - *(unsigned char *)(D_L06_0015FFD8 + 0xBC + (vector_stream_vars->f14 << 8)) != 0) { + *(unsigned char *)(level_mobys_q + 0xBC + (vector_stream_vars->f14 << 8)) != 0) { int voice_slot_index; MOBY(moby)->collision = 0; MOBY(moby)->state = 3; From e4946fda10c12019cdf8300bff29590b6996d45f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:03:06 +0000 Subject: [PATCH 0122/1502] decomp: clarify names in hero_pick_help_mode D_L05_0015F698 -> l05_hoverboard_trick_landing_frame_thresholds: The assigned extern int D_L05_0015F698 is indexed through its address by hero.air_pose_index. Retail 0x002556dc-0x002556ec restricts animation IDs to 0x69..0x6c; 0x002556f4-0x0025570c loads the pose byte at hero+0x88f, multiplies by four, reads the integer threshold from gp-0x7568 and converts it to float. 0x00255710-0x00255724 compares hero.anim_frame (hero+0xaa8) against it and requests state 0x6d when below threshold, after the descending velocity gate at 0x00255658-0x0025566c. This proves trick-pose-indexed landing frame thresholds without changing the scalar declaration or assembler identity. next -> previous_path_point_index: In hero_pick_help_mode, next receives offset_path_index(hero.race_path, index, -1, 1). Retail 0x002554d4-0x002554e8 passes the selected point in a1, -1 in a2 and wrap=1 in a3, retaining the returned index. The supplied offset_path_index implementation proves this is the wrapped previous point, not the next point; 0x00255508-0x00255514 multiplies it by 16 to read that point's Z. other -> previous_path_point_height: Source initializes other from path->p[next].z, where next is offset_path_index(race_path,index,-1,1). Retail 0x00255508-0x00255518 reads the returned predecessor point's float at path + index*16 + 0x18 and the selected point's Z. At 0x0025551c-0x0025552c it selects their minimum for comparison with hero position Z at 0x0025554c-0x00255554. Thus other is specifically the previous path point's height. --- .../shared/hero/process_hero_primary_item_input.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/hero/process_hero_primary_item_input.c b/src/overlays/shared/hero/process_hero_primary_item_input.c index 731870bbcd..24f6807cf9 100644 --- a/src/overlays/shared/hero/process_hero_primary_item_input.c +++ b/src/overlays/shared/hero/process_hero_primary_item_input.c @@ -1813,7 +1813,7 @@ extern s32 current_level_index __asm__("D_0015ED84") __attribute__((sda)); extern float frame_time __asm__("D_0015ED6C") MACRO_ADDR; extern void fast_vec_normalize(void *, void *, float) __asm__("FUN_001f9bf8"); extern int offset_path_index(void *, int, int, int) __asm__("FUN_L00_0025d7a0"); -extern int D_L05_0015F698 __attribute__((sda)); +extern int l05_hoverboard_trick_landing_frame_thresholds __asm__("D_L05_0015F698") __attribute__((sda)); int hero_pick_help_mode(void) __asm__("FUN_L05_00255208"); @@ -1881,18 +1881,18 @@ int hero_pick_help_mode(void) { if ((&hero)->race_path != 0) { int index = select_point_index_by_distance(&(&hero)->motion.pos, (&hero)->race_path, 0.0f); - int next = offset_path_index((&hero)->race_path, index, -1, 1); + int previous_path_point_index = offset_path_index((&hero)->race_path, index, -1, 1); (&hero)->wrong_way_path_point = index; if (*(int *)0x0015ED84 == 5) { Path *path = (Path *)(&hero)->race_path; float height = path->p[index].z; - float other = path->p[next].z; + float previous_path_point_height = path->p[previous_path_point_index].z; float distance; float minimum; - if (height < other) + if (height < previous_path_point_height) minimum = height; else - minimum = other; + minimum = previous_path_point_height; distance = vector_distance_xy(&(&hero)->motion.pos, &path->p[index]); if (0.5f < minimum - (&hero)->motion.pos.f[2] && 4.0f < distance) { state = 0x6D; @@ -1934,7 +1934,7 @@ int hero_pick_help_mode(void) { goto change_state; } if ((unsigned)(*((unsigned char *)(&hero)->moby + 0x53) - 0x69) < 4 && - (&hero)->anim_frame < (float)(&D_L05_0015F698)[(&hero)->air_pose_index]) { + (&hero)->anim_frame < (float)(&l05_hoverboard_trick_landing_frame_thresholds)[(&hero)->air_pose_index]) { state = 0x6D; goto change_state; } From 40825255718f6e8ebc28a7a180631a419eeca851 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:03:15 +0000 Subject: [PATCH 0123/1502] decomp: clarify names in sentrybot_alarm_update D_L15_00161AB4 -> l15_sentrybot_alarm_effect_update_stamp: Retail 0x002cb518 initializes the level-15 global 0x00161AB4 to zero. At 0x002cba78-0x002cba90 it compares that cached integer to 0x0015F5CC, skips the shared effect update when equal, otherwise copies the compared integer into 0x00161AB4 and calls update_sentrybot_alarm_effect. This proves a cached effect-update stamp, without assuming the external stamp's units. data -> alarm_state: Retail 0x002cb4f0 loads s2 from moby+0x78, the source MOBY(moby)->pvars. Its words hold alarm mode (0), group index (1), active flag (2), release countdown (3), reload (4), pulse phase (5) and duration countdown (6); 0x002cb930 passes word 1 to activate_first_inactive_group_moby and 0x002cb97c clears the active flag. switch_0_case_0 -> SENTRYBOT_ALARM_STATE_INITIALIZE: The selector is moby+0x20 (0x002cb4e4), not a Hero field. Case 0 at 0x002cb510-0x002cb568 clears the shared alarm stamp/active/effect globals and selects initial state 6 with animation 4 for mode 2, or state 3 with animation 2 otherwise; it performs alarm initialization. switch_0_case_1 -> SENTRYBOT_ALARM_STATE_STANDBY_PULSE: For moby+0x20 case 1, 0x002cb574-0x002cb5d4 interpolates glow color from the stored sine phase and advances phase by frame_time*2pi. At 0x002cb5cc a zero alarm active flag goes directly to the shared update; when active and permitted, 0x002cb5d8-0x002cb620 leaves for states 6 or 5. This is the standby pulsing state awaiting activation. switch_0_case_5 -> SENTRYBOT_ALARM_STATE_ACTIVE_PULSE: Moby-state case 5 at 0x002cb738-0x002cb7c8 maintains animation 0 and pulses glow between 0x801414dc and 0x8004048c using phase advanced by frame_time*4pi. At 0x002cb7cc-0x002cb834 the alarm duration countdown expires (or gating mode equals 2), calls set_sentrybot_alarm_duration(moby,0), clears the alarm active flag, and enters state 10. This proves the active alarm pulse state. switch_0_case_8 -> SENTRYBOT_ALARM_STATE_RELEASE_GROUP_MOBYS: Moby-state case 8 at 0x002cb8a4-0x002cb948 checks XY hero distance under 16, the release countdown, and a line collision from moby position raised by one. It then passes pvars word 1 and moby position to activate_first_inactive_group_moby at 0x002cb934 and reloads the release countdown only on success. At 0x002cb94c-0x002cb984 alarm-duration expiry stops the alarm and exits to state 9, proving this state's conditional group-moby release role. --- src/overlays/shared/enemies/sentrybot_alarm.c | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/overlays/shared/enemies/sentrybot_alarm.c b/src/overlays/shared/enemies/sentrybot_alarm.c index 66fe1f1aaa..f6b0ee5932 100644 --- a/src/overlays/shared/enemies/sentrybot_alarm.c +++ b/src/overlays/shared/enemies/sentrybot_alarm.c @@ -36,7 +36,7 @@ extern int D_0015ED84; extern int interpolate_color_2a3138(float, int, int) __asm__("FUN_001fa6e0"); -extern int D_L15_00161AB4 __attribute__((sda)); +extern int l15_sentrybot_alarm_effect_update_stamp __asm__("D_L15_00161AB4") __attribute__((sda)); extern int D_L15_00161AB8 __attribute__((sda)); extern short D_L15_00161ABC_gp __asm__("D_L15_00161ABC") __attribute__((sda)); void update_sentrybot_alarm_effect(void *moby) __asm__("FUN_L15_002cbc30"); @@ -90,15 +90,15 @@ void sentrybot_alarm_update(unsigned char *moby) __asm__("FUN_L15_002cb4c8"); /* Moby class 408 */ void sentrybot_alarm_update(unsigned char *moby) { - float position[4]; + enum { SENTRYBOT_ALARM_STATE_INITIALIZE = 0 , SENTRYBOT_ALARM_STATE_STANDBY_PULSE = 1 , SENTRYBOT_ALARM_STATE_ACTIVE_PULSE = 5 , SENTRYBOT_ALARM_STATE_RELEASE_GROUP_MOBYS = 8 } ;float position[4]; float step; int color; int mode; - int *data = ((int *)MOBY(moby)->pvars); + int *alarm_state = ((int *)MOBY(moby)->pvars); switch (MOBY(moby)->state) { - case 0: - mode = data[0]; - D_L15_00161AB4 = 0; + case SENTRYBOT_ALARM_STATE_INITIALIZE: + mode = alarm_state[0]; + l15_sentrybot_alarm_effect_update_stamp = 0; D_L15_00161AB8 = 0; *(int *)&D_L15_00161ABC_gp = 0; if (mode == 2) { @@ -111,16 +111,16 @@ void sentrybot_alarm_update(unsigned char *moby) { blend_moby_animation(moby, 2, 0, 0); } break; - case 1: + case SENTRYBOT_ALARM_STATE_STANDBY_PULSE: color = interpolate_color_2a3138( - (fast_sin(*(float *)(data + 5)) + 1.0f) * 0.5f, 0x801414bc, 0x801414dc); + (fast_sin(*(float *)(alarm_state + 5)) + 1.0f) * 0.5f, 0x801414bc, 0x801414dc); step = frame_time; MOBY(moby)->glow_color = color; - *(float *)(data + 5) = fast_add_rotations(*(float *)(data + 5), step * 6.2831855f); - if (data[2] == 0) + *(float *)(alarm_state + 5) = fast_add_rotations(*(float *)(alarm_state + 5), step * 6.2831855f); + if (alarm_state[2] == 0) goto update; if (D_L15_0015F5C4 != 2) { - if (data[0] == 1) { + if (alarm_state[0] == 1) { MOBY(moby)->state = 6; if (MOBY(moby)->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(30)); @@ -137,7 +137,7 @@ void sentrybot_alarm_update(unsigned char *moby) { } break; case 3: - if (data[2] == 0) + if (alarm_state[2] == 0) goto update; if (D_L15_0015F5C4 != 2) { MOBY(moby)->state = 4; @@ -147,9 +147,9 @@ void sentrybot_alarm_update(unsigned char *moby) { break; case 4: if (MOBY(moby)->anim_flags & 2) { - if (data[2] == 0 || D_L15_0015F5C4 == 2) + if (alarm_state[2] == 0 || D_L15_0015F5C4 == 2) goto stop_animation; - if (data[0] == 1) { + if (alarm_state[0] == 1) { MOBY(moby)->state = 7; if (MOBY(moby)->prev_seq != 5) blend_moby_animation(moby, 5, 0, scale_game_frames(10)); @@ -165,24 +165,24 @@ void sentrybot_alarm_update(unsigned char *moby) { blend_moby_animation(moby, 8, 0, scale_game_frames(10)); MOBY(moby)->state = 10; break; - case 5: + case SENTRYBOT_ALARM_STATE_ACTIVE_PULSE: if ((MOBY(moby)->anim_flags & 2) && MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); color = interpolate_color_2a3138( - (fast_sin(*(float *)(data + 5)) + 1.0f) * 0.5f, 0x801414dc, 0x8004048c); + (fast_sin(*(float *)(alarm_state + 5)) + 1.0f) * 0.5f, 0x801414dc, 0x8004048c); step = frame_time; MOBY(moby)->glow_color = color; - *(float *)(data + 5) = fast_add_rotations(*(float *)(data + 5), step * 12.566371f); - if (fast_dec_timer(data + 6) || D_L15_0015F5C4 == 2) { + *(float *)(alarm_state + 5) = fast_add_rotations(*(float *)(alarm_state + 5), step * 12.566371f); + if (fast_dec_timer(alarm_state + 6) || D_L15_0015F5C4 == 2) { set_sentrybot_alarm_duration((char *)moby, 0); - data[2] = 0; + alarm_state[2] = 0; if (MOBY(moby)->prev_seq != 8) blend_moby_animation(moby, 8, 0, scale_game_frames(10)); MOBY(moby)->state = 10; } break; case 6: - if (data[2] == 0) + if (alarm_state[2] == 0) goto update; MOBY(moby)->state = 7; if (MOBY(moby)->prev_seq != 5) @@ -195,20 +195,20 @@ void sentrybot_alarm_update(unsigned char *moby) { blend_moby_animation(moby, 6, 0, scale_game_frames(10)); } break; - case 8: { + case SENTRYBOT_ALARM_STATE_RELEASE_GROUP_MOBYS: { float *pos = (float *)&MOBY(moby)->pos; float *hero_pos = hero.motion.pos.f; if (vector_distance_xy(pos, hero_pos) < 16.0f && D_L15_0015F5C4 != 2 && - fast_dec_timer(data + 3)) { + fast_dec_timer(alarm_state + 3)) { qcopy(position, pos); position[2] += 1.0f; if (collision_line(position, hero_pos + 20, 2, 0, 0) == 0 && - activate_first_inactive_group_moby(data[1], pos)) - data[3] = data[4]; + activate_first_inactive_group_moby(alarm_state[1], pos)) + alarm_state[3] = alarm_state[4]; } - if (fast_dec_timer(data + 6) || D_L15_0015F5C4 == 2) { + if (fast_dec_timer(alarm_state + 6) || D_L15_0015F5C4 == 2) { set_sentrybot_alarm_duration((char *)moby, 0); - data[2] = 0; + alarm_state[2] = 0; MOBY(moby)->state = 9; if (MOBY(moby)->prev_seq != 7) blend_moby_animation(moby, 7, 0, scale_game_frames(10)); @@ -217,7 +217,7 @@ void sentrybot_alarm_update(unsigned char *moby) { } case 9: if (MOBY(moby)->anim_flags & 2) { - if (data[0] == 2) { + if (alarm_state[0] == 2) { MOBY(moby)->state = 6; if (MOBY(moby)->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); @@ -236,11 +236,11 @@ void sentrybot_alarm_update(unsigned char *moby) { } break; } - if (data[2] != 0) + if (alarm_state[2] != 0) D_L15_00161AB8 = 1; update: - if (D_L15_00161AB4 != D_L15_0015F5CC) { - D_L15_00161AB4 = D_L15_0015F5CC; + if (l15_sentrybot_alarm_effect_update_stamp != D_L15_0015F5CC) { + l15_sentrybot_alarm_effect_update_stamp = D_L15_0015F5CC; update_sentrybot_alarm_effect(moby); D_L15_00161AB8 = 0; } From bc491f0aa10416cc897ede8a57f556d490fcc6b2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:03:24 +0000 Subject: [PATCH 0124/1502] decomp: clarify names in process_amoeboid_hits_and_update_targeting D_L01_001619A0_gp -> l01_smaller_amoeboid_knockback_xy_scale: Retail GP=0x166c00: lwc1 at 0x002eeef4 and 0x002eefd4 reads gp-0x5260, physical D_L01_001619A0. Each value is multiplied by absolute frame_time at 0x002eef04/0x002eefe4 and stored to the activated smaller amoeboid pvars+0x78 at 0x002eef28/0x002ef008. That address is a2 to trooper_knockback_arc at 0x002eef40/0x002ef020. Supplied helper C identifies this argument as xy_scaled_value, multiplied by vector_length_xy for the marked-vector case. The resulting motion block pvars+0x60 is passed to trooper_start_knockback. Authoritative C and original Ghidra agree; the name claims the initial XY knockback scale, without asserting physical units. D_L01_001619A4_gp -> l01_smaller_amoeboid_knockback_z_scale: Retail GP=0x166c00: lwc1 at 0x002eeefc and 0x002eefdc reads gp-0x525c, physical D_L01_001619A4. Each value is multiplied by absolute frame_time at 0x002eef0c/0x002eefec and stored to the activated smaller amoeboid pvars+0x7C at 0x002eef34/0x002ef014. That address is a3 to trooper_knockback_arc at 0x002eef40/0x002ef020. Supplied helper C identifies this argument as z_scaled_value and multiplies it by input_vector_copy.f[2] for the marked-vector case. The motion block pvars+0x60 then feeds trooper_start_knockback. Authoritative C and original Ghidra agree; the name asserts the initial Z knockback scale only. --- src/overlays/shared/enemies/large_amoeboid.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/enemies/large_amoeboid.c b/src/overlays/shared/enemies/large_amoeboid.c index 4f24519436..6fb068f440 100644 --- a/src/overlays/shared/enemies/large_amoeboid.c +++ b/src/overlays/shared/enemies/large_amoeboid.c @@ -745,8 +745,8 @@ void process_amoeboid_hits_and_update_targeting(char *moby) { k = frame_time_macro; seven = 7.0f; *(float *)(q + 0x88) = moby_vars->size_scale * size_multiplier; - *(float *)(q + 0x78) = D_L01_001619A0_gp * k; - *(float *)(q + 0x7C) = D_L01_001619A4_gp * k; + *(float *)(q + 0x78) = l01_smaller_amoeboid_knockback_xy_scale * k; + *(float *)(q + 0x7C) = l01_smaller_amoeboid_knockback_z_scale * k; *(int *)(q + 0x84) = *(int *)(q + 0x84) | 4; *(float *)(q + 0xB0) = seven; *(float *)(q + 0xB4) = 13.0f; @@ -768,8 +768,8 @@ void process_amoeboid_hits_and_update_targeting(char *moby) { k = frame_time_macro; seven = 7.0f; *(float *)(q + 0x88) = moby_vars->size_scale * size_multiplier; - *(float *)(q + 0x78) = D_L01_001619A0_gp * k; - *(float *)(q + 0x7C) = D_L01_001619A4_gp * k; + *(float *)(q + 0x78) = l01_smaller_amoeboid_knockback_xy_scale * k; + *(float *)(q + 0x7C) = l01_smaller_amoeboid_knockback_z_scale * k; *(int *)(q + 0x84) = *(int *)(q + 0x84) | 4; *(float *)(q + 0xB0) = seven; *(float *)(q + 0xB4) = 13.0f; From 6e56e5eb53dc93057df1e410b3129cb328bc78d7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:05:27 +0000 Subject: [PATCH 0125/1502] decomp: clarify names in underwater_ring_update first -> voice_delay_limit: After allocate_voice_for_target_entry(0,0x31,moby), retail 0x002e5ccc..0x002e5d1c scales 45 frames into s1, compares it against scaled 5 plus timer divided by scaled 40, and stores scaled 45 to delay if the sum exceeds it. This scalar caps the delay between these voice allocations. other -> child_ring_vars: In case 0, retail 0x002e5a88..0x002e5ab0 excludes the current moby, checks enumerated child oclass 0x4b9, then loads its +0x78 pvars and writes the current ring as parent, initialized=1 and the shared distance. This pointer is the enumerated child ring's private variables. second -> voice_delay_base: Retail 0x002e5cd8..0x002e5d04 scales 5 into s0 and adds timer/scaled(40) before comparison with the scaled-45 limit. The alternate branch at 0x002e5d20..0x002e5d50 repeats this sum and stores it to delay. This scalar is the base term for the voice-delay calculation. switch_0_case_0 -> UNDERWATER_RING_STATE_INITIALIZE: Selector is the ring moby state byte at +0x20 (0x002e5a00). Case 0 at 0x002e5a28..0x002e5b10 initializes group parent links and distance when needed, clears timer/delay/count/trigger/flash fields, colors the ring black, and writes state 1. Its proven role is initialization. switch_0_case_1 -> UNDERWATER_RING_STATE_READY: Initialization and reset write state 1 at 0x002e5b10 and 0x002e5d78. In the shared proximity branch, 0x002e5bb0..0x002e5be8 tests the parent state for 1 and starts its timer while changing it to 2. State 1 therefore waits ready for the first qualifying ring crossing. switch_0_case_2 -> UNDERWATER_RING_STATE_TIMED_CHALLENGE: Retail 0x002e5bc4..0x002e5be8 writes parent state 2 and initializes its challenge timer on the first crossing. The explicit state-2 check at 0x002e5c24..0x002e5c78 gates completed-member counting and timer decrement; expiry requests group reset at 0x002e5c9c..0x002e5ca4. This is the active timed challenge state. switch_0_case_3 -> UNDERWATER_RING_STATE_RESET: On challenge timer expiry, retail 0x002e5c78..0x002e5ca4 clears progress and sends group state 3 through set_moby_list_state, whose supplied source writes each member's state byte. Case 3 at 0x002e5d54..0x002e5d78 colors black, clears trigger/count and returns to ready state 1. switch_0_case_4 -> UNDERWATER_RING_STATE_COMPLETED: Retail 0x002e5c34..0x002e5c74 selects group/state 4 when child_count reaches notified_count; 0x002e5b14..0x002e5b9c also accepts saved completion when enabled. Case 4 at 0x002e5d7c..0x002e5e48 flashes green/white and ORs this ring's save_id bit into both save-bit arrays, proving completed state. vars -> ring_vars: Retail 0x002e598c loads s2 from this ring moby's pvars at +0x78. The source VendorVars pointer accesses this ring's timer, triggered flag, parent link, proximity distance and flash state throughout underwater_ring_update; ring_vars identifies its owning ring. --- src/overlays/shared/props/underwater_ring.c | 105 +++++++++++--------- 1 file changed, 56 insertions(+), 49 deletions(-) diff --git a/src/overlays/shared/props/underwater_ring.c b/src/overlays/shared/props/underwater_ring.c index b2c9395d2e..5a7c280f6f 100644 --- a/src/overlays/shared/props/underwater_ring.c +++ b/src/overlays/shared/props/underwater_ring.c @@ -38,20 +38,27 @@ void underwater_ring_update(struct Moby *moby) __asm__("FUN_L15_002e5958"); /* Moby class 1209 */ void underwater_ring_update(struct Moby *moby) { - VendorVars *vars = (VendorVars *)moby->pvars; + enum { + UNDERWATER_RING_STATE_INITIALIZE = 0, + UNDERWATER_RING_STATE_READY = 1, + UNDERWATER_RING_STATE_TIMED_CHALLENGE = 2, + UNDERWATER_RING_STATE_RESET = 3, + UNDERWATER_RING_STATE_COMPLETED = 4 + }; + VendorVars *ring_vars = (VendorVars *)moby->pvars; u8 delta[16]; u8 matrix[64]; struct Moby *child; u16 save_id; u8 *save_byte; - s32 first; - s32 second; + s32 voice_delay_limit; + s32 voice_delay_base; s32 divisor; s32 near_parent = 0; if ((u8)(moby->state - 1) < 2) { fast_vec_sub(delta, &moby->pos, D_0013F3D0); - if (fast_vec_length(delta) < vars->distance) { + if (fast_vec_length(delta) < ring_vars->distance) { transpose_rotation_matrix(matrix, &moby->rot_row0); transform_vector(delta, delta, matrix); if (*(f32 *)(delta + 4) < 0.2f) @@ -59,34 +66,34 @@ void underwater_ring_update(struct Moby *moby) { } } switch (moby->state) { - case 0: - if (vars->initialized == 0) { + case UNDERWATER_RING_STATE_INITIALIZE: + if (ring_vars->initialized == 0) { moby_point_position(moby, 0, delta); - vars->distance = fast_vec_dist(&moby->pos, delta); - vars->notified_count = 0; - vars->parent = moby; + ring_vars->distance = fast_vec_dist(&moby->pos, delta); + ring_vars->notified_count = 0; + ring_vars->parent = moby; get_first_moby_in_group(&child, moby->group, 0, 0); while (child != 0) { if (child != moby && child->oclass == 0x4b9) { - VendorVars *other = (VendorVars *)child->pvars; - other->parent = moby; - other->initialized = 1; - other->distance = vars->distance; + VendorVars *child_ring_vars = (VendorVars *)child->pvars; + child_ring_vars->parent = moby; + child_ring_vars->initialized = 1; + child_ring_vars->distance = ring_vars->distance; } - vars->notified_count++; + ring_vars->notified_count++; get_next_moby_in_group(&child, child, 0, 0); } } - vars->timer = 0; - vars->delay = 0; - vars->child_count = 0; - vars->triggered = 0; - vars->flash_timer = 0; + ring_vars->timer = 0; + ring_vars->delay = 0; + ring_vars->child_count = 0; + ring_vars->triggered = 0; + ring_vars->flash_timer = 0; set_moby_color(moby, 0, 0, 0); moby->state = 1; break; - case 1: - case 2: + case UNDERWATER_RING_STATE_READY: + case UNDERWATER_RING_STATE_TIMED_CHALLENGE: save_id = moby->save_id; save_byte = (u8 *)&l15_save_state; save_byte -= -(s16)save_id; @@ -95,74 +102,74 @@ void underwater_ring_update(struct Moby *moby) { (u8 *)D_0014C190)) >> (save_id & 31)) & 1) != 0) { - if (vars->enabled != 0) { + if (ring_vars->enabled != 0) { set_moby_list_state(moby->group, 4); - vars->timer = vars->restart_timer; + ring_vars->timer = ring_vars->restart_timer; moby->state = 4; break; } } - if (vars->triggered == 0 && near_parent) { - struct Moby *parent = vars->parent; + if (ring_vars->triggered == 0 && near_parent) { + struct Moby *parent = ring_vars->parent; VendorVars *parent_vars = (VendorVars *)parent->pvars; if (parent->state == 1) { - vars->child_count = 0; + ring_vars->child_count = 0; parent->state = 2; parent_vars->timer = - parent_vars->frame_count < 1 ? 900 : scale_game_frames(vars->frame_count); + parent_vars->frame_count < 1 ? 900 : scale_game_frames(ring_vars->frame_count); } parent_vars->child_count++; allocate_voice_for_target_entry(3, 0x31, moby); set_moby_color(moby, 0, 0xff, 0); - vars->triggered = 1; + ring_vars->triggered = 1; } if (moby->state == 2) { - if (vars->child_count >= vars->notified_count) { + if (ring_vars->child_count >= ring_vars->notified_count) { set_moby_list_state(moby->group, 4); allocate_voice_for_target_entry(1, 0x31, moby); - vars->timer = vars->restart_timer; + ring_vars->timer = ring_vars->restart_timer; moby->state = 4; break; } else { - if (fast_dec_timer_s16(&vars->timer) != 0) { - vars->child_count = 0; - vars->triggered = 0; + if (fast_dec_timer_s16(&ring_vars->timer) != 0) { + ring_vars->child_count = 0; + ring_vars->triggered = 0; allocate_voice_for_target_entry(2, 0x31, moby); set_moby_list_state(moby->group, 3); - } else if (fast_dec_timer_s16(&vars->delay) != 0) { + } else if (fast_dec_timer_s16(&ring_vars->delay) != 0) { allocate_voice_for_target_entry(0, 0x31, moby); - first = scale_game_frames(0x2d); - second = scale_game_frames(5); + voice_delay_limit = scale_game_frames(0x2d); + voice_delay_base = scale_game_frames(5); divisor = scale_game_frames(0x28); - if (first < second + vars->timer / divisor) - vars->delay = scale_game_frames(0x2d); + if (voice_delay_limit < voice_delay_base + ring_vars->timer / divisor) + ring_vars->delay = scale_game_frames(0x2d); else { s32 delay = scale_game_frames(5); s32 delay_divisor = scale_game_frames(0x28); - delay_divisor = delay + vars->timer / delay_divisor; - vars->delay = delay_divisor; + delay_divisor = delay + ring_vars->timer / delay_divisor; + ring_vars->delay = delay_divisor; } } } } break; - case 3: + case UNDERWATER_RING_STATE_RESET: set_moby_color(moby, 0, 0, 0); - vars->child_count = 0; - vars->triggered = 0; + ring_vars->child_count = 0; + ring_vars->triggered = 0; moby->state = 1; break; - case 4: { + case UNDERWATER_RING_STATE_COMPLETED: { u16 save_id; u32 *bits; - if (fast_dec_timer_s16(&vars->flash_timer) != 0) { - vars->flash_timer = scale_game_frames(0x14); - if (vars->flash_color != 0) { + if (fast_dec_timer_s16(&ring_vars->flash_timer) != 0) { + ring_vars->flash_timer = scale_game_frames(0x14); + if (ring_vars->flash_color != 0) { set_moby_color(moby, 0, 0xff, 0); - vars->flash_color = 0; + ring_vars->flash_color = 0; } else { set_moby_color(moby, 0xff, 0xff, 0xff); - vars->flash_color = 1; + ring_vars->flash_color = 1; } } save_id = moby->save_id; From 0c1d0390674d309ff02b21b9985bdcdfcab20cc4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:05:38 +0000 Subject: [PATCH 0126/1502] decomp: clarify names in bombomatic_update D_L07_00166E40 -> debris_far_point: Authoritative extern char D_L07_00166E40[] is passed as the second point to fast_vec_dist(moby+0x10,...) and vector_distance_xy. Retail 0x0030d524..0x0030d530 forms address 0x00166e40 for the 27-unit comparison; 0x0030d878..0x0030d888 forms that identical address and 0x0030d88c..0x0030d8d8 tests XY distance against 90 and 40 to gate class-0x372 launches. Original Ghidra uses literal 0x166e40 in these same distance calls. Supplied naming_file_globals.existing_names binds debris_far_point to this exact assembler label, so reuse that proven shared spelling exactly. Bounded level-07 data read confirms initialized bytes at 0x00166e40; no object extent or producer is inferred. --- src/overlays/l07/mobys/bombomatic.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l07/mobys/bombomatic.c b/src/overlays/l07/mobys/bombomatic.c index 5e88cd3465..fe90637e37 100644 --- a/src/overlays/l07/mobys/bombomatic.c +++ b/src/overlays/l07/mobys/bombomatic.c @@ -23,7 +23,7 @@ char *spawn_bombomatic_projectile(char *spawn_position, short burst_index) __asm__("FUN_L07_0030ba90"); /* Ported from rac1-decomp (src/overlays/l07_umbris/vendor_002CE470.c: func_L07_0030E820), where it is exact; names translated to the US level program. */ -extern char D_L07_00166E40[]; +extern char debris_far_point[] __asm__("D_L07_00166E40"); extern int allocate_voice_for_target_entry(int, int, void *) __asm__("FUN_0022da68"); extern void mark_moby_for_removal(void *) __asm__("FUN_0020c828"); extern int resolve_moby_hit_response(void *, void *, void *, int, int *, float *, int, int); @@ -222,7 +222,7 @@ void bombomatic_update(char *moby) { } moby_data = (BombomaticVars *)MOBY(moby)->pvars; if (((unsigned char *)moby)[0x31] != 0) { - if (fast_vec_dist(moby + 0x10, D_L07_00166E40) < 27.0f) { + if (fast_vec_dist(moby + 0x10, debris_far_point) < 27.0f) { FUN_L00_0025a120(moby); MOBY(moby)->shadow_range = 0x15; } @@ -364,9 +364,9 @@ void bombomatic_update(char *moby) { if (fast_dec_timer_s16(&moby_data->timer_B8) != 0) { moby_data->timer_B8 = scale_game_frames(7); if (((unsigned char *)moby)[0x31] == 0) { - if (!(vector_distance_xy(moby + 0x10, D_L07_00166E40) < 90.0f && + if (!(vector_distance_xy(moby + 0x10, debris_far_point) < 90.0f && (moby_data->unkC4 & 1) != 0)) { - if (!(vector_distance_xy(moby + 0x10, D_L07_00166E40) < 40.0f)) { + if (!(vector_distance_xy(moby + 0x10, debris_far_point) < 40.0f)) { goto eeE4; } } From 74d4d9a78d4bd87af281644ff04e6a3228234122 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:05:38 +0000 Subject: [PATCH 0127/1502] decomp: clarify names in magnet_elevator_update t -> remaining_camera_blend_ratio: Authoritative source SHA-256 a5d15a2e386af27603f1de6ebece3118d5087e095179015370e97b4ea5bd0092 declares float t as (1-current progress)/(1-previous progress). Retail 0x002ee434 saves pvars+0x70 before advancement; 0x002ee458-0x002ee474 computes the remaining-progress ratio in f20. Original Ghidra case 1 fVar6 matches. Retail 0x002ee498-0x002ee4b4 scales the camera position offset by it, and 0x002ee4c4/0x002ee4e0 weights the angular differences by the same ratio. t -> pulse_color_green_alpha_bits: In the shared WAIT_AT_FIRST_STOP/WAIT_AT_SECOND_STOP block, the authoritative source declares int t = (i << 8) | 0x80000000 and combines it with (i << 16) and i into the moby color at +0x90. Retail 0x002ee718-0x002ee768 derives and clamps the pulse intensity to 0x20..0x80; 0x002ee76c-0x002ee774 forms this binding in v1 from the green byte shifted by 8 and alpha bits 0x80000000. Retail 0x002ee778-0x002ee78c adds the red and blue bytes and stores the packed color. Original Ghidra case 6/7 shows the identical packed-color expression. --- src/overlays/l17/mobys/magnet_elevator.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l17/mobys/magnet_elevator.c b/src/overlays/l17/mobys/magnet_elevator.c index ee79a9c41a..85e4a1c130 100644 --- a/src/overlays/l17/mobys/magnet_elevator.c +++ b/src/overlays/l17/mobys/magnet_elevator.c @@ -121,23 +121,23 @@ void magnet_elevator_update(struct Moby *moby) { frame_time_sq * 4.0f, frame_time * 4.0f); if ((*(float *)((char *)(state) + (0x70))) < 1.0f) { - float t = (1.0f - (*(float *)((char *)(state) + (0x70)))) / + float remaining_camera_blend_ratio = (1.0f - (*(float *)((char *)(state) + (0x70)))) / (1.0f - previous_camera_blend_progress); char *camera_pose_base; FUN_L17_002ee9c0_c(moby, (char *)camera_position, (char *)camera_rotation); fast_vec_sub(camera_position_offset, D_L17_001676C0, camera_position); camera_pose_base = D_L17_001676C0 - 0x140; - fast_vec_scale(camera_position_offset, camera_position_offset, t); + fast_vec_scale(camera_position_offset, camera_position_offset, remaining_camera_blend_ratio); fast_vec_add(camera_position, camera_position, camera_position_offset); camera_rotation[1] = fast_add_rotations( fast_subtract_rotations((*(float *)((char *)(camera_pose_base) + (0x154))), camera_rotation[1]) * - t, + remaining_camera_blend_ratio, camera_rotation[1]); camera_rotation[2] = fast_add_rotations( fast_subtract_rotations((*(float *)((char *)(camera_pose_base) + (0x158))), camera_rotation[2]) * - t, + remaining_camera_blend_ratio, camera_rotation[2]); set_camera_position(camera_position); set_camera_rotation(camera_rotation); @@ -225,8 +225,8 @@ void magnet_elevator_update(struct Moby *moby) { i = 0x20; } { - int t = (i << 8) | 0x80000000; - W(moby, 0x90) = (i << 16) | t | i; + int pulse_color_green_alpha_bits = (i << 8) | 0x80000000; + W(moby, 0x90) = (i << 16) | pulse_color_green_alpha_bits | i; } hero_state = (char *)((char *)&hero); if (H(hero_state, 0x308) != 0 || W(state, 0x7C) == 0) { From bb1054b0b385ac2dbc78515d5b53624030ac1862 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:05:38 +0000 Subject: [PATCH 0128/1502] decomp: clarify names in vo_buf_reset buf -> video_output_buffer: The authoritative src/movies/decoder/video_output/vo_buf_reset.c (SHA-256 28cf0d46190ac9f73901e48829a852d12b2ae9715e3effd0475fb609ca609625) types buf as struct VoBuf * in vo_buf_reset, with the recovered voBufReset__FP5VoBuf alias. Retail Ghidra uses its sole argument as the object address; 0x0023d1e8 sw zero,0xc(a0) and 0x0023d1ec sw zero,0x8(a0) correspond to clearing buf->count and buf->write. The video_output unit and VoBuf reset identity establish this as the video-output buffer whose state is reset, rather than an untyped byte buffer. --- src/movies/decoder/video_output/vo_buf_reset.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/movies/decoder/video_output/vo_buf_reset.c b/src/movies/decoder/video_output/vo_buf_reset.c index 3555991e93..008e119850 100644 --- a/src/movies/decoder/video_output/vo_buf_reset.c +++ b/src/movies/decoder/video_output/vo_buf_reset.c @@ -3,9 +3,9 @@ void vo_buf_reset(struct VoBuf *buf) __asm__("func_0023D1E8"); -void vo_buf_reset(struct VoBuf *buf) { - buf->count = 0; - buf->write = 0; +void vo_buf_reset(struct VoBuf *video_output_buffer) { + video_output_buffer->count = 0; + video_output_buffer->write = 0; } /* Recovered original symbol name. */ From 42b80eb70920e570607fcea73cf93569e0336fc9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:05:39 +0000 Subject: [PATCH 0129/1502] decomp: clarify names in vo_buf_is_empty buf -> video_output_buffer: The authoritative source declares struct VoBuf *buf in vo_buf_is_empty in movies/decoder/video_output and returns buf->count == 0. Retail Ghidra reads *(int *)(param_1 + 0xc); lw v0,0xc(a0) at 0x0023d2c8 and sltiu v0,v0,0x1 at 0x0023d2d0 prove this argument is the video-output buffer object whose count is tested, rather than a pointer to payload bytes. --- src/movies/decoder/video_output/vo_buf_is_empty.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/movies/decoder/video_output/vo_buf_is_empty.c b/src/movies/decoder/video_output/vo_buf_is_empty.c index f21f49cf99..0aea032261 100644 --- a/src/movies/decoder/video_output/vo_buf_is_empty.c +++ b/src/movies/decoder/video_output/vo_buf_is_empty.c @@ -3,6 +3,6 @@ s32 vo_buf_is_empty(struct VoBuf *buf) __asm__("func_0023D2C8"); -s32 vo_buf_is_empty(struct VoBuf *buf) { - return buf->count == 0; +s32 vo_buf_is_empty(struct VoBuf *video_output_buffer) { + return video_output_buffer->count == 0; } From 2ee5d55b9733140ef1edc685fb9e205ce971b5b9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:05:39 +0000 Subject: [PATCH 0130/1502] decomp: clarify names in vo_buf_is_full buf -> video_output_buffer: The authoritative vo_buf_is_full source (src/movies/decoder/video_output/vo_buf_is_full.c, SHA-256 0f05f351401db1c40a75ef06bdfd76fbeeef5a9137da5acd10b27318758e0cd9) declares this parameter as struct VoBuf * and returns buf->count == buf->size. Retail Ghidra reads param_1+0xc and param_1+0x10; instructions at 0x0023d1f8 and 0x0023d1fc load those fields from a0, followed by xor and sltiu to return equality. Together the established video-output function/module and typed occupancy predicate identify a video_output_buffer, adding its subsystem role rather than merely expanding buf. --- src/movies/decoder/video_output/vo_buf_is_full.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/movies/decoder/video_output/vo_buf_is_full.c b/src/movies/decoder/video_output/vo_buf_is_full.c index 6a7074c1de..3a833a04f1 100644 --- a/src/movies/decoder/video_output/vo_buf_is_full.c +++ b/src/movies/decoder/video_output/vo_buf_is_full.c @@ -3,6 +3,6 @@ s32 vo_buf_is_full(struct VoBuf *buf) __asm__("func_0023D1F8"); -s32 vo_buf_is_full(struct VoBuf *buf) { - return buf->count == buf->size; +s32 vo_buf_is_full(struct VoBuf *video_output_buffer) { + return video_output_buffer->count == video_output_buffer->size; } From a8e696c3853b7811d97636af32ae5ced28d71982 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:07:35 +0000 Subject: [PATCH 0131/1502] decomp: clarify names in vo_buf_delete buf -> video_output_buffer: The authoritative src/movies/decoder/video_output/vo_buf_delete.c declares vo_buf_delete(struct VoBuf *buf), with original alias voBufDelete__FP5VoBuf. Retail caller 0x0023aa68 loads the object owner from 0x0016120c at 0x0023aa94 and passes owner + 0xd9168 in a0 at 0x0023aaa0/0x0023aaa4 during MPEG cleanup. These establish the video-output buffer object; the target's 0x0023d1e0 jr ra and 0x0023d1e4 nop make no access or mutation claims. --- src/movies/decoder/video_output/vo_buf_delete.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/movies/decoder/video_output/vo_buf_delete.c b/src/movies/decoder/video_output/vo_buf_delete.c index 9ae05ee47b..0232b8165e 100644 --- a/src/movies/decoder/video_output/vo_buf_delete.c +++ b/src/movies/decoder/video_output/vo_buf_delete.c @@ -3,7 +3,7 @@ void vo_buf_delete(struct VoBuf *buf) __asm__("func_0023D1E0"); -void vo_buf_delete(struct VoBuf *buf) { +void vo_buf_delete(struct VoBuf *video_output_buffer) { } /* Recovered original symbol name. */ From 31d87ffd131edffaee4f20963a632e641ed22d9c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:07:35 +0000 Subject: [PATCH 0132/1502] decomp: clarify names in read_buf_create b -> buffer_to_initialize: In the SHA-256-bound read_buf_create source, b is assigned buf (struct ReadBuf *) and is the target of size = READ_BUF_SIZE, put = 0, and count = 0. Retail 0x0023b940 loads 0x50000; 0x0023b944 adds it to incoming a0; stores at 0x0023b948, 0x0023b94c and 0x0023b954 initialize offsets +0x50008, +0x50004 and +0x50000 of that supplied object. Thus this alias denotes the buffer to initialize. --- src/movies/decoder/buffers/read_buf_create.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/movies/decoder/buffers/read_buf_create.c b/src/movies/decoder/buffers/read_buf_create.c index 7a44d8a009..de1d2d80d8 100644 --- a/src/movies/decoder/buffers/read_buf_create.c +++ b/src/movies/decoder/buffers/read_buf_create.c @@ -3,11 +3,11 @@ void read_buf_create(struct ReadBuf *buf) __asm__("func_0023B940"); void read_buf_create(struct ReadBuf *buf) { - struct ReadBuf *b = buf; + struct ReadBuf *buffer_to_initialize = buf; - b->size = READ_BUF_SIZE; - b->put = 0; - b->count = 0; + buffer_to_initialize->size = READ_BUF_SIZE; + buffer_to_initialize->put = 0; + buffer_to_initialize->count = 0; } /* Recovered original symbol name. */ From e4ec1254b0b45af1673615d4a477d3985a4eec30 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:07:35 +0000 Subject: [PATCH 0133/1502] decomp: clarify names in set_second_hero_easing_parameters a -> easing_acceleration: In the authoritative C, float a is assigned directly to destination[1].accel with destination = hero_eases. Retail 0x0020a1f8/0x0020a1fc constructs 0x0017a680, and 0x0020a208 stores first float argument f12 at +0x154 (0x0017a7d4); original Ghidra likewise assigns param_1 to DAT_0017a7d4. This proves the acceleration input for the second HeroEase. b -> easing_max_speed: In the authoritative C, float b is assigned directly to destination[1].max_speed with destination = hero_eases. Retail 0x0020a200 stores second float argument f13 at base 0x0017a680 + 0x158 (0x0017a7d8); original Ghidra likewise assigns param_2 to DAT_0017a7d8. The supplied movement caller passes 0.009f and 0.22f and separately sets other HeroEase max_speed fields to 0.22f, consistent with the maximum-speed input. --- .../shared/hero/set_second_hero_easing_parameters.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/hero/set_second_hero_easing_parameters.c b/src/overlays/shared/hero/set_second_hero_easing_parameters.c index 0a3667eed6..179f04291d 100644 --- a/src/overlays/shared/hero/set_second_hero_easing_parameters.c +++ b/src/overlays/shared/hero/set_second_hero_easing_parameters.c @@ -7,10 +7,10 @@ extern struct HeroEase hero_eases[] __asm__("D_L00_0017A680"); /* Sets the accel and max_speed of one hero ease. */ void set_second_hero_easing_parameters(float a, float b) __asm__("FUN_L00_0020a1f8"); -void set_second_hero_easing_parameters(float a, float b) { +void set_second_hero_easing_parameters(float easing_acceleration, float easing_max_speed) { struct HeroEase *destination = hero_eases; - destination[1].accel = a; - destination[1].max_speed = b; + destination[1].accel = easing_acceleration; + destination[1].max_speed = easing_max_speed; } extern struct HeroEase hero_eases[] __asm__("D_L00_0017A680"); From c24b26553ebf25850817a96d6c64efe9fdb975f8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:07:35 +0000 Subject: [PATCH 0134/1502] decomp: clarify names in ground_attached_update other -> later_group_member: Retail 0x002d0488..0x002d0494 initializes sp+0x48 with get_next_moby_in_group after the outer moby; 0x002d04c8..0x002d04e0 advances that same cursor. Source other is this M_2cfcb8 pointer, filtered by the crate predicate before its pos is passed with moby->pos to fast_vec_dist at 0x002d04b8..0x002d04c4. It traverses later members of the same group. src1 -> ungrouped_crate_position: In the group==0xFF single-object branch, source src1 is assigned &moby->pos. Retail 0x002cfddc computes moby+0x10, then 0x002cfdec..0x002cfdfc loads that position twice into the two probe vectors; the upper Z is raised by 0.5 and lower Z set to 0.1 before the collision call at 0x002cfe30. src2 -> group_crate_probe_position: Source src2=&moby->pos occurs in the first group traversal after the class-range predicate succeeds. Retail 0x002cfff8..0x002d000c computes the current group moby+0x10 and copies it into both probe vectors, followed by the Z adjustments and collision call at 0x002d0044. The pointer supplies the grouped crate's probe position. src3 -> stacked_crate_position: After the collision moby is accepted as a same-group crate, source src3=&moby->pos is the destination of qcopy from below->pos and both destination/input of the following vector addition. Retail 0x002d00ec..0x002d0114 stores the below link at vars+0xA4, computes current moby+0x10 in a0, copies below moby+0x10 there, then adds below+0xE0 to that position. src4 -> stack_base_probe_position: Source src4=&member->pos is used only after the second group pass accepts a crate with vars->pA4==0, making it a stack base with no below crate. Retail 0x002d01bc..0x002d01dc checks vars+0xA4 for zero, computes member+0x10 and copies its position into the second pair of probe vectors; 0x002d01e0..0x002d0220 raises the upper Z by height*0.5 and probes before traversing next_member upward. --- src/overlays/shared/pickups/crate.c | 38 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/overlays/shared/pickups/crate.c b/src/overlays/shared/pickups/crate.c index 400354e4e9..596d60245a 100644 --- a/src/overlays/shared/pickups/crate.c +++ b/src/overlays/shared/pickups/crate.c @@ -658,10 +658,10 @@ void ground_attached_update(M_2cfcb8 *moby) { V_2cfcb8 probe_up; V_2cfcb8 probe_down; M_2cfcb8 *member; - M_2cfcb8 *other; + M_2cfcb8 *later_group_member; Vars *vars; Vars *below_vars; - V_2cfcb8 *src1, *src2, *src3, *src4; + V_2cfcb8 *ungrouped_crate_position, *group_crate_probe_position, *stacked_crate_position, *stack_base_probe_position; R_2cfcb8 *route; s32 group, flags_before, i, member_flags; M_2cfcb8 *below; @@ -683,9 +683,9 @@ void ground_attached_update(M_2cfcb8 *moby) { vars->hC4 = moby->hA8; vars->height = 1.0f; vars->flags = flags_before | 1; - src1 = &moby->pos; - qcopy(&probe_top, src1); - qcopy(&probe_bottom, src1); + ungrouped_crate_position = &moby->pos; + qcopy(&probe_top, ungrouped_crate_position); + qcopy(&probe_bottom, ungrouped_crate_position); probe_top.z += 0.5f; probe_bottom.z = 0.1f; if (FUN_001efa68_2cfcb8(&probe_top, &probe_bottom, 2, 0, 0) == 0) { @@ -732,9 +732,9 @@ void ground_attached_update(M_2cfcb8 *moby) { vars->hC4 = moby->hA8; vars->height = 1.0f; vars->flags = member_flags | 1; - src2 = &moby->pos; - qcopy(&probe_top, src2); - qcopy(&probe_bottom, src2); + group_crate_probe_position = &moby->pos; + qcopy(&probe_top, group_crate_probe_position); + qcopy(&probe_bottom, group_crate_probe_position); probe_top.z += 0.5f; probe_bottom.z = 0.1f; if (FUN_001efa68_2cfcb8(&probe_top, &probe_bottom, 2, 0, 0) == 0) { @@ -756,10 +756,10 @@ void ground_attached_update(M_2cfcb8 *moby) { } else if (is_moby_in_class_range_500_to_540( (*(H_2cfcb8 *)&D_L00_00173E40).moby) != 0) { vars->pA4 = (*(H_2cfcb8 *)&D_L00_00173E40).moby; - src3 = &moby->pos; + stacked_crate_position = &moby->pos; below = (*(H_2cfcb8 *)&D_L00_00173E40).moby; - qcopy(src3, &below->pos); - FUN_001f9a10_2cfcb8(src3, src3, (u8 *)below + 0xE0); + qcopy(stacked_crate_position, &below->pos); + FUN_001f9a10_2cfcb8(stacked_crate_position, stacked_crate_position, (u8 *)below + 0xE0); vars = (*(H_2cfcb8 *)&D_L00_00173E40).moby->vars; if (is_moby_in_class_range_500_to_540(moby) != 0) { vars->next_member = moby; @@ -782,9 +782,9 @@ void ground_attached_update(M_2cfcb8 *moby) { while (member != 0) { vars = member->vars; if (is_moby_in_class_range_500_to_540(member) != 0 && vars->pA4 == 0) { - src4 = &member->pos; - qcopy(&probe_up, src4); - qcopy(&probe_down, src4); + stack_base_probe_position = &member->pos; + qcopy(&probe_up, stack_base_probe_position); + qcopy(&probe_down, stack_base_probe_position); probe_up.z += vars->height * 0.5f; probe_down.z = 0.1f; if (FUN_001efa68_2cfcb8(&probe_up, &probe_down, 2, moby, 0) != 0) { @@ -852,12 +852,12 @@ void ground_attached_update(M_2cfcb8 *moby) { get_first_moby_in_group(&moby, group, 0, 0); while (moby != 0) { if (is_moby_in_class_range_500_to_540(moby) != 0) { - get_next_moby_in_group(&other, moby, 0, 0); - while (other != 0) { - if (is_moby_in_class_range_500_to_540(other) != 0) { - fast_vec_dist(&moby->pos, &other->pos); + get_next_moby_in_group(&later_group_member, moby, 0, 0); + while (later_group_member != 0) { + if (is_moby_in_class_range_500_to_540(later_group_member) != 0) { + fast_vec_dist(&moby->pos, &later_group_member->pos); } - get_next_moby_in_group(&other, other, 0, 0); + get_next_moby_in_group(&later_group_member, later_group_member, 0, 0); } } get_next_moby_in_group(&moby, moby, 0, 0); From 02b5e5e95ffaca8d070d3b4aa7fb21af3ba2bfe2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:07:48 +0000 Subject: [PATCH 0135/1502] decomp: clarify names in tresspasser_pad_update D_L02_00161AA0_gp -> l02_tresspasser_pad_tool_equipped_glow_color: In WAIT_FOR_TOOL_ACTIVATION, retail 0x002d8c00-0x002d8c10 first requires hero ground_moby == this pad and air_frames == 0. At 0x002d8c38-0x002d8c50 a nonnull item moby and item_id 0x1A select lw v0,-0x5160(gp), bound to D_L02_00161AA0. The shared sw at 0x002d8c68 writes moby+0x90, the authoritative source's moby->glow_color. Thus this int is the tool-equipped pad glow color. D_L02_00161AA4_gp -> l02_tresspasser_pad_without_tool_glow_color: Within the grounded-on-this-pad branch, retail 0x002d8c3c branches on a null held item moby and 0x002d8c48 branches on item_id != 0x1A. Both select lw v0,-0x515c(gp) at 0x002d8c4c/0x002d8c5c, bound to D_L02_00161AA4, then sw v0,0x90(s3) at 0x002d8c68. The supplied C identifies this destination as moby->glow_color, proving the pad glow color used without the required tool. D_L02_00161AA8_gp -> l02_tresspasser_pad_no_ground_contact_glow_color: Retail 0x002d8c04 branches when hero ground_moby differs from s3 (the pad); 0x002d8c10 branches when hero air_frames is nonzero. The paths load -0x5158(gp) at 0x002d8c14 or 0x002d8d1c, bound to D_L02_00161AA8, reset pvars+0x12 and store to pad+0x90 at 0x002d8d28. The authoritative source labels +0x90 moby->glow_color, proving the glow color for failure of grounded contact with this pad. --- src/overlays/shared/props/trespasser_pad.c | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/overlays/shared/props/trespasser_pad.c b/src/overlays/shared/props/trespasser_pad.c index 3fcf986816..9604e8dd50 100644 --- a/src/overlays/shared/props/trespasser_pad.c +++ b/src/overlays/shared/props/trespasser_pad.c @@ -100,22 +100,22 @@ extern void func_L02_002DA728_2D9F08(Moby *) __asm__("FUN_L02_002d92f0"); extern void func_L02_002D9D48_2D9F08(void *, void *, Moby *) __asm__("FUN_L02_002d8910"); extern float advance_accelerated_scalar(float *, float *, float, float, float, float) __asm__("FUN_00213f38"); -extern void func_L02_002DA820_2D9F08(void) __asm__("FUN_L02_002d93e8"); -extern void func_L00_0025E590_2D9F08(Moby *, Data *) __asm__("FUN_L00_0025d538"); -extern float D_L02_001D33B0[4][4]; -extern Lvl D_L02_001BBB40_2D9F08 __asm__("D_L02_001BB830"); -extern int current_level_index_macro __asm__("D_0015ED84") MACRO_ADDR; -extern Vec_2D9F08 D_L02_00167440_2D9F08[] __asm__("D_L02_001673C0"); -extern float frame_time_sq_macro __asm__("D_0015ED70") MACRO_ADDR; -extern float frame_time_macro __asm__("D_0015ED6C") MACRO_ADDR; -extern int D_L02_0017EB08_lui __asm__("D_L02_0017EB08") NOT_SDA; -extern Idle D_L02_00179A10; -extern int D_L02_001BADE0_2D9F08[] __asm__("D_L02_001BAAD0"); -extern int l02_tresspasser_puzzle_texture_index_offset __asm__("D_L02_00161B1C") __attribute__((sda)); -extern int D_L02_00161AA8_gp __asm__("D_L02_00161AA8") __attribute__((sda)); -extern int D_L02_00161AA4_gp __asm__("D_L02_00161AA4") __attribute__((sda)); -extern int D_L02_00161AA0_gp __asm__("D_L02_00161AA0") __attribute__((sda)); -extern char D_0013E633_2D9F08[] __asm__("D_0013E533"); +extern void func_L02_002DA820_2D9F08(void) __asm__("FUN_L02_002d93e8"); +extern void func_L00_0025E590_2D9F08(Moby *, Data *) __asm__("FUN_L00_0025d538"); +extern float D_L02_001D33B0[4][4]; +extern Lvl D_L02_001BBB40_2D9F08 __asm__("D_L02_001BB830"); +extern int current_level_index_macro __asm__("D_0015ED84") MACRO_ADDR; +extern Vec_2D9F08 D_L02_00167440_2D9F08[] __asm__("D_L02_001673C0"); +extern float frame_time_sq_macro __asm__("D_0015ED70") MACRO_ADDR; +extern float frame_time_macro __asm__("D_0015ED6C") MACRO_ADDR; +extern int D_L02_0017EB08_lui __asm__("D_L02_0017EB08") NOT_SDA; +extern Idle D_L02_00179A10; +extern int D_L02_001BADE0_2D9F08[] __asm__("D_L02_001BAAD0"); +extern int l02_tresspasser_puzzle_texture_index_offset __asm__("D_L02_00161B1C") __attribute__((sda)); +extern int l02_tresspasser_pad_no_ground_contact_glow_color __asm__("D_L02_00161AA8") __attribute__((sda)); +extern int l02_tresspasser_pad_without_tool_glow_color __asm__("D_L02_00161AA4") __attribute__((sda)); +extern int l02_tresspasser_pad_tool_equipped_glow_color __asm__("D_L02_00161AA0") __attribute__((sda)); +extern char D_0013E633_2D9F08[] __asm__("D_0013E533"); extern void func_L00_002607A8_d92f0(void *a, float x) __asm__("FUN_L00_0025f730"); @@ -285,10 +285,10 @@ void tresspasser_pad_update(Moby *moby) { } if (((Hero *)(D_0013E633_2D9F08 + 0xE1D))->items[0].moby != 0 && ((Hero *)(D_0013E633_2D9F08 + 0xE1D))->items[0].item_id == 0x1A) { - moby->glow_color = D_L02_00161AA0_gp; + moby->glow_color = l02_tresspasser_pad_tool_equipped_glow_color; holding_tool = 1; } else { - moby->glow_color = D_L02_00161AA4_gp; + moby->glow_color = l02_tresspasser_pad_without_tool_glow_color; holding_tool = 0; } if (holding_tool && @@ -307,7 +307,7 @@ void tresspasser_pad_update(Moby *moby) { } } else { pad_puzzle_state->h12 = 0; - moby->glow_color = D_L02_00161AA8_gp; + moby->glow_color = l02_tresspasser_pad_no_ground_contact_glow_color; } break; case TRESSPASSER_PAD_STATE_ACTIVE_PUZZLE: From 089ff2dac0cf198f1383d0b03bb1d15dfff34f2f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:07:58 +0000 Subject: [PATCH 0136/1502] decomp: clarify names in update_beam_barrier D_L06_0015FFD8 -> level_mobys_q: Retail 0x002f6a44..0x002f6a48 loads the pointer at 0x0015ffd8 into a3. At 0x002f6a68..0x002f6a78 each nonnegative BarrierVars.links index is shifted left 8, added to that pointer, and read at +0xa6 as moby class; 0x002f6a80 and 0x002f6a84 read command +0xbc and state +0x20. The authoritative C assigns this global to moby_table and casts moby_table + index * 256 to struct Moby *. Thus it is the level moby table pointer. Reuse supplied existing_names spelling level_mobys_q for this identical assembler label; preserve extern char * type and assembler identity. --- src/overlays/l06/mobys/beam_barrier.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l06/mobys/beam_barrier.c b/src/overlays/l06/mobys/beam_barrier.c index e722aa34a1..571bcce97d 100644 --- a/src/overlays/l06/mobys/beam_barrier.c +++ b/src/overlays/l06/mobys/beam_barrier.c @@ -16,7 +16,7 @@ extern void allocate_voice_for_target_entry(int, int, int) __asm__("FUN_0022da68 /* angle from a moby to its owner, clamped to the gaps between obstacles in its list */ /* Ported from rac1-decomp (src/overlays/l06_blarg/vendor_002B5990.c: func_L06_002FAB28), where it is exact; names translated to the US level program. */ -extern char *D_L06_0015FFD8; +extern char *level_mobys_q __asm__("D_L06_0015FFD8"); #include "qcopy.h" @@ -238,7 +238,7 @@ void beam_barrier_update(struct Moby *moby) { { int all_done = 1; int count_usage = 1; - char *moby_table = D_L06_0015FFD8; + char *moby_table = level_mobys_q; int link; for (link = 0; link < 4; link++) { int index = beam_barrier_control_vars->links[link]; From e99d47f1e3c3a63fd8b5de657d9f10b659da44d5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:10:11 +0000 Subject: [PATCH 0137/1502] decomp: clarify names in set_first_hero_easing_parameters a -> easing_acceleration: Retail 0x0020a1e0/0x0020a1e4 forms hero_eases base 0x0017a680; 0x0020a1f0 stores incoming f12 at +0xA4 (0x0017a724). Original Ghidra assigns DAT_0017a724 = param_1. The authoritative C assigns a directly to destination_record->accel; update_hero_easing_record supplies this field as the spring acceleration input, scaled by frame_scale_sq for rotations. b -> easing_max_speed: Retail 0x0020a1e8 stores incoming f13 at hero_eases base +0xA8 (0x0017a728). Original Ghidra assigns DAT_0017a728 = param_2. The authoritative C assigns b directly to destination_record->max_speed; update_hero_easing_record passes that field after accel to spring_angle and vendor_spring, establishing the easing maximum-speed parameter. --- src/overlays/shared/hero/hero_idle_sequence.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index 289d9a0f50..4a2acdf316 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -2710,10 +2710,10 @@ extern struct HeroEase hero_eases[] __asm__("D_L00_0017A680"); /* Sets the accel and max_speed of the first hero ease. */ void set_first_hero_easing_parameters(float a, float b) __asm__("FUN_L00_0020a1e0"); -void set_first_hero_easing_parameters(float a, float b) { +void set_first_hero_easing_parameters(float easing_acceleration, float easing_max_speed) { struct HeroEase *destination_record = hero_eases; - destination_record->accel = a; - destination_record->max_speed = b; + destination_record->accel = easing_acceleration; + destination_record->max_speed = easing_max_speed; } typedef struct V0020a240 { From 2a4862c8d1103bc6e6c59cabb2279d0750648048 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:10:11 +0000 Subject: [PATCH 0138/1502] decomp: clarify names in tesla_claw_update st -> firing_start_stats: In TESLA_CLAW_STATE_WAIT_FOR_FIRE, st is the Stats pointer at D_0014161B + 0x65, used only after a pressed fire button, unlocked item use and active firing. Retail 002b8f78-002b8f9c selects base 0x00141680 in s1 and increments its unsigned-short uses at +0x98 with saturation; 002b8fa8-002b8fec updates longest at +0x9a from scaled frames / 600; 002b8ff8-002b9014 ORs current-level and high bits into levels at +0x9c. The branch then starts the equipped-item animation and writes Moby firing state 3 at 002b9010-002b901c/002b917c, proving this is the firing-start statistics record. --- src/overlays/shared/weapons/tesla_claw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/weapons/tesla_claw.c b/src/overlays/shared/weapons/tesla_claw.c index d7bc8908a0..78ac51dcdf 100644 --- a/src/overlays/shared/weapons/tesla_claw.c +++ b/src/overlays/shared/weapons/tesla_claw.c @@ -687,12 +687,12 @@ void tesla_claw_update(struct Moby *tesla_claw_moby) { if ((controller_state.pressed & (player_hero = &hero)->items[0].button_mask) && !player_hero->item_use_locked) { if (active) { - Stats *st = (Stats *)(D_0014161B + 0x65); - if (st->uses < 65535) - st->uses++; - if (scale_game_frames(D_0015EEA4) / 600 > st->longest) - st->longest = scale_game_frames(D_0015EEA4) / 600; - st->levels = (st->levels | (1 << current_level_index)) | 0x80000000; + Stats *firing_start_stats = (Stats *)(D_0014161B + 0x65); + if (firing_start_stats->uses < 65535) + firing_start_stats->uses++; + if (scale_game_frames(D_0015EEA4) / 600 > firing_start_stats->longest) + firing_start_stats->longest = scale_game_frames(D_0015EEA4) / 600; + firing_start_stats->levels = (firing_start_stats->levels | (1 << current_level_index)) | 0x80000000; start_equipped_item_animation(); tesla_claw_moby->state = 3; } else { From 55b6c35ca715fe3cf433626ecfced25e4baf239e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:12:42 +0000 Subject: [PATCH 0139/1502] decomp: clarify names in update_beam_ring_rail_and_pulse_effects D_L00_001616F4_gp -> l00_beam_target_bend_after_node_index: Retail 0x002bd37c-0x002bd3e0 loads this int (gp-0x550c), tests configured index < current node i, and only with a nonnull target blends aim toward target position minus beam_nodes[i]. C uses the identical D_L00_001616F4_gp < i gate, proving the exclusive node threshold for target bending. D_L00_001616F8_gp -> l00_beam_rail_wave_phase_increment: Retail 0x002bd100-0x002bd128 adds the float loaded from gp-0x5508 to phase at 0x001617D0 and normalizes the angle. At 0x002bd5b4-0x002bd618 that phase drives sine/cosine offsets transformed into the two rail paths. C confirms one phase increment per update, without frame scaling. D_L00_001616FC_gp -> l00_beam_rail_wave_phase_step_per_node: Retail 0x002bd5ac-0x002bd5c8 converts the current beam node index to float, multiplies it by gp-0x5504 and adds phase 0x001617D0 before angle normalization. Sine/cosine at 0x002bd5d0-0x002bd618 then construct rail offsets; C confirms this is the rail wave angular step per node. D_L00_00161708_gp -> l00_beam_ring_start_radius: Retail 0x002bd4bc-0x002bd4d8 computes gp-0x54f8 + (gp-0x54f4 - gp-0x54f8) * node progress and normalizes the side vector to that length. The ring loop at 0x002bd4f8-0x002bd538 rotates this vector and adds the node position. C proves this float is the ring radius interpolation start. D_L00_0016170C_gp -> l00_beam_ring_end_radius: Retail 0x002bd4c4-0x002bd4d8 subtracts the start radius from gp-0x54f4, multiplies by node progress, and adds the start before setting side-vector length. The twenty ring samples at 0x002bd518-0x002bd538 rotate that side about the segment, proving the ring radius interpolation endpoint. D_L00_0016172C_gp -> l00_beam_rail_wave_start_amplitude: Retail 0x002bd594-0x002bd5b0 interpolates from gp-0x54d4 toward gp-0x54d0 by node progress. At 0x002bd5d0-0x002bd618 this length multiplies sine and cosine for wave_offset.y/z, transformed into both beam rails. C names the intermediate wave_width, proving the wave amplitude start. D_L00_00161730_gp -> l00_beam_rail_wave_end_amplitude: Retail 0x002bd59c-0x002bd5b0 uses gp-0x54d0 as the endpoint in start + (end - start) * node progress. The interpolated float scales the sine/cosine rail offsets at 0x002bd5d8-0x002bd618. C confirms this is the rail wave amplitude endpoint, not a phase or travel speed. D_L00_00161734_gp -> l00_beam_origin_particle_speed: Retail 0x002bd7ec-0x002bd804 multiplies gp-0x54cc by frame_scale and normalizes the first beam segment to that length. Two angular rotations preserve it before passing the vector to origin particle emission at 0x002bd938/0x002bd97c. At 0x002bd8e0-0x002bd904 the same scaled speed divides beam_length * 1.2 to calculate particle lifetime; C agrees. D_L00_0016173C_gp -> l00_beam_origin_particle_angular_spread: Retail 0x002bd884-0x002bd8dc passes gp-0x54c4 twice to signed random float sampling around zero; the samples are angles for two rotations of the origin particle velocity about the fixed axis and its cross-product axis. C uses randf_sym(0.0f, D_L00_0016173C_gp) for both rotations, proving the angular spread parameter. D_L00_00161740_gp -> l00_beam_origin_particle_basis_offset_length: Retail 0x002bd818-0x002bd840 normalizes moby+0xD0 to gp-0x54c0 length and adds that vector to beam node zero. This point is supplied to both particle emissions at 0x002bd938/0x002bd97c. C confirms the configured signed basis offset length for the origin particle spawn position. D_L00_00161748_gp -> l00_beam_pulse_travel_speed: Retail 0x002bda60-0x002bda98 multiplies gp-0x54b8 by frame delta 0x0015ED6C and adds it to per-pulse travelled distance at 0x001617F8. That distance selects/interpolates beam nodes at 0x002bdaf4-0x002bdbb4, and the increment also moves pulses beyond the path. C proves the pulse travel speed. D_L00_0016174C_gp -> l00_beam_pulse_lifetime_frames: Retail 0x002bd1dc-0x002bd20c passes gp-0x54b4 through frame scaling and stores it in the newly activated pulse's timer array at 0x001617D8. At 0x002bda20-0x002bda34 timer expiry clears that pulse's active flag. C confirms this int is the configured pulse lifetime in frames. D_L00_00161750_gp -> l00_beam_pulse_alpha_fade_remaining_frames_threshold: Retail 0x002bda38-0x002bda5c compares the remaining pulse timer at 0x001617D8 with gp-0x54b0. Below this int threshold it subtracts the alpha decrement from 0x001617E8. C draw_beam_pulse_quads converts that same array to the vertex alpha byte, proving the remaining-frame alpha-fade threshold. D_L00_00161758_gp -> l00_beam_pulse_end_corner_scale: Retail 0x002bdaa4-0x002bdacc interpolates gp-0x54a4 + (gp-0x54a8 - gp-0x54a4) * capped travelled/default_length into per-pulse 0x00161808. In the supplied C draw_beam_pulse_quads multiplies template corners by this same array before transforming them. This proves gp-0x54a8 is the pulse corner scale at travel ratio one. D_L00_0016175C_gp -> l00_beam_pulse_start_corner_scale: Retail 0x002bd1f4-0x002bd21c initializes new pulse scale 0x00161808 from gp-0x54a4; 0x002bdaa4-0x002bdacc also uses it as the start of scale interpolation by capped travelled/default_length. Supplied C draw_beam_pulse_quads uses 0x00161808 to scale template corners, proving the pulse start corner scale. D_L00_00161768_gp -> l00_beam_pulse_alpha_decrement_per_update: Retail 0x002bda44-0x002bda5c subtracts float gp-0x5498 from the pulse array at 0x001617E8 when the remaining timer is below the fade threshold. Supplied C draw_beam_pulse_quads truncates this array and shifts it by 24 into all vertex colors, proving an alpha decrement applied per eligible update, without frame scaling. --- src/overlays/shared/weapons/morphoray.c | 68 ++++++++++++------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/overlays/shared/weapons/morphoray.c b/src/overlays/shared/weapons/morphoray.c index 3fbf2847a9..4351191651 100644 --- a/src/overlays/shared/weapons/morphoray.c +++ b/src/overlays/shared/weapons/morphoray.c @@ -232,23 +232,23 @@ extern float D_L00_001616DC_gp __asm__("D_L00_001616DC") __attrib extern int D_L00_00161818; extern int D_L00_00161824; extern float D_L00_001616F0_gp __asm__("D_L00_001616F0") __attribute__((sda)); -extern int D_L00_001616F4_gp __asm__("D_L00_001616F4") __attribute__((sda)); -extern float D_L00_001616F8_gp __asm__("D_L00_001616F8") __attribute__((sda)); -extern float D_L00_001616FC_gp __asm__("D_L00_001616FC") __attribute__((sda)); +extern int l00_beam_target_bend_after_node_index __asm__("D_L00_001616F4") __attribute__((sda)); +extern float l00_beam_rail_wave_phase_increment __asm__("D_L00_001616F8") __attribute__((sda)); +extern float l00_beam_rail_wave_phase_step_per_node __asm__("D_L00_001616FC") __attribute__((sda)); extern float D_L00_00161704_gp __asm__("D_L00_00161704") __attribute__((sda)); -extern float D_L00_00161708_gp __asm__("D_L00_00161708") __attribute__((sda)); -extern float D_L00_0016170C_gp __asm__("D_L00_0016170C") __attribute__((sda)); -extern float D_L00_0016172C_gp __asm__("D_L00_0016172C") __attribute__((sda)); -extern float D_L00_00161730_gp __asm__("D_L00_00161730") __attribute__((sda)); -extern float D_L00_00161734_gp __asm__("D_L00_00161734") __attribute__((sda)); -extern float D_L00_0016173C_gp __asm__("D_L00_0016173C") __attribute__((sda)); -extern float D_L00_00161740_gp __asm__("D_L00_00161740") __attribute__((sda)); -extern float D_L00_00161748_gp __asm__("D_L00_00161748") __attribute__((sda)); -extern int D_L00_0016174C_gp __asm__("D_L00_0016174C") __attribute__((sda)); -extern int D_L00_00161750_gp __asm__("D_L00_00161750") __attribute__((sda)); -extern float D_L00_00161758_gp __asm__("D_L00_00161758") __attribute__((sda)); -extern float D_L00_0016175C_gp __asm__("D_L00_0016175C") __attribute__((sda)); -extern float D_L00_00161768_gp __asm__("D_L00_00161768") __attribute__((sda)); +extern float l00_beam_ring_start_radius __asm__("D_L00_00161708") __attribute__((sda)); +extern float l00_beam_ring_end_radius __asm__("D_L00_0016170C") __attribute__((sda)); +extern float l00_beam_rail_wave_start_amplitude __asm__("D_L00_0016172C") __attribute__((sda)); +extern float l00_beam_rail_wave_end_amplitude __asm__("D_L00_00161730") __attribute__((sda)); +extern float l00_beam_origin_particle_speed __asm__("D_L00_00161734") __attribute__((sda)); +extern float l00_beam_origin_particle_angular_spread __asm__("D_L00_0016173C") __attribute__((sda)); +extern float l00_beam_origin_particle_basis_offset_length __asm__("D_L00_00161740") __attribute__((sda)); +extern float l00_beam_pulse_travel_speed __asm__("D_L00_00161748") __attribute__((sda)); +extern int l00_beam_pulse_lifetime_frames __asm__("D_L00_0016174C") __attribute__((sda)); +extern int l00_beam_pulse_alpha_fade_remaining_frames_threshold __asm__("D_L00_00161750") __attribute__((sda)); +extern float l00_beam_pulse_end_corner_scale __asm__("D_L00_00161758") __attribute__((sda)); +extern float l00_beam_pulse_start_corner_scale __asm__("D_L00_0016175C") __attribute__((sda)); +extern float l00_beam_pulse_alpha_decrement_per_update __asm__("D_L00_00161768") __attribute__((sda)); extern signed char D_L00_00161763_macro[] __asm__("D_L00_00161763") MACRO_ADDR; extern float D_L00_001617CC_macro __asm__("D_L00_001617CC") MACRO_ADDR; extern int D_L00_00161824_macro __asm__("D_L00_00161824") MACRO_ADDR; @@ -1752,7 +1752,7 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { wave_offset.w = 1.0f; wave_offset.x = 0.0f; func_L00_002BE2A0_2BE3A8(); - D_L00_001617D0 = normalize_angle(D_L00_001617D0 + D_L00_001616F8_gp); + D_L00_001617D0 = normalize_angle(D_L00_001617D0 + l00_beam_rail_wave_phase_increment); build_spherical_offset( &aim, D_L00_001617CC_macro, beam_effect_state->f48, beam_effect_state->f4C); if (beam_effect_state->target != 0 && @@ -1786,7 +1786,7 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { func_001F9BF0_2BE3A8(&segment, &beam_nodes[i], &beam_nodes[i - 1]); progress = func_001FA888_2BE3A8(i) * D_L00_001616F0_gp; factor = progress * -0.49999997f + 0.9f; - if (D_L00_001616F4_gp < i && beam_effect_state->target != 0) { + if (l00_beam_target_bend_after_node_index < i && beam_effect_state->target != 0) { func_001F9BF0_2BE3A8(&point, &beam_effect_state->target->pos, &beam_nodes[i]); func_L00_001FF4B0_2BE3A8(&point, &point, D_L00_001617CC_macro); func_001F9C08_2BE3A8(&aim, &aim, &point, 0.2f); @@ -1803,8 +1803,8 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { func_001F9CA0_2BE3A8(&side, &beam_segment_direction, D_0013F5E0_r); func_L00_001FF4B0_2BE3A8(&side, &side, - D_L00_00161708_gp + - (D_L00_0016170C_gp - D_L00_00161708_gp) * progress); + l00_beam_ring_start_radius + + (l00_beam_ring_end_radius - l00_beam_ring_start_radius) * progress); { Vec_2BE3A8 ring; Vec_2BE3A8 fwd; @@ -1824,10 +1824,10 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { func_L00_001FF4B0_2BE3A8(&fwd, &beam_segment_direction, 1.0f); func_L00_001FF4B0_2BE3A8(&out, &side, 1.0f); func_001F9CA0_2BE3A8(&up, &out, &fwd); - wave_width = D_L00_0016172C_gp; - wave_width = wave_width + (D_L00_00161730_gp - wave_width) * progress; + wave_width = l00_beam_rail_wave_start_amplitude; + wave_width = wave_width + (l00_beam_rail_wave_end_amplitude - wave_width) * progress; factor = - normalize_angle(D_L00_001617D0 + D_L00_001616FC_gp * func_001FA888_2BE3A8(i)); + normalize_angle(D_L00_001617D0 + l00_beam_rail_wave_phase_step_per_node * func_001FA888_2BE3A8(i)); wave_offset.y = wave_width * func_001F9FA8_2BE3A8(factor); wave_width = wave_width * func_001F9F90_2BE3A8(factor); wave_offset.z = wave_width; @@ -1889,9 +1889,9 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { } func_001F9BF0_2BE3A8(&beam_segment_direction, &beam_nodes[1], &beam_nodes[0]); func_L00_001FF4B0_2BE3A8( - &beam_segment_direction, &beam_segment_direction, D_L00_00161734_gp * frame_scale); + &beam_segment_direction, &beam_segment_direction, l00_beam_origin_particle_speed * frame_scale); if (random_integer_below(2) == 0) { - func_L00_001FF4B0_2BE3A8(&side, &moby->rot_row1, D_L00_00161740_gp); + func_L00_001FF4B0_2BE3A8(&side, &moby->rot_row1, l00_beam_origin_particle_basis_offset_length); func_001F9BD8_2BE3A8(&point, &beam_nodes[0], &side); { Tab colors; @@ -1900,13 +1900,13 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { colors = l00_beam_origin_particle_color_palette; color = colors.c[random_integer_below(5)]; - wave_width = randf_sym(0.0f, D_L00_0016173C_gp); + wave_width = randf_sym(0.0f, l00_beam_origin_particle_angular_spread); build_look_at_matrix( - &out, &beam_segment_direction, D_0013F5E0_r, randf_sym(0.0f, D_L00_0016173C_gp)); + &out, &beam_segment_direction, D_0013F5E0_r, randf_sym(0.0f, l00_beam_origin_particle_angular_spread)); func_001F9CA0_2BE3A8(&up, &beam_segment_direction, D_0013F5E0_r); build_look_at_matrix(&out, &out, &up, wave_width); node_index = - func_001FA898_2BE3A8(beam_length * 1.2f / (D_L00_00161734_gp * frame_scale)); + func_001FA898_2BE3A8(beam_length * 1.2f / (l00_beam_origin_particle_speed * frame_scale)); if (beam_effect_state->target != 0) { node_index = node_index * 3; } @@ -1935,9 +1935,9 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { for (slot = 0; slot < 3; slot++) { if (D_L00_001618E8_2BE3A8[slot] == 0) { D_L00_001618E8_2BE3A8[slot] = 1; - D_L00_001617D8_macro[slot] = func_001F9850_2BE3A8(D_L00_0016174C_gp); + D_L00_001617D8_macro[slot] = func_001F9850_2BE3A8(l00_beam_pulse_lifetime_frames); D_L00_001617F8_macro[slot] = 0.0f; - D_L00_001618D8_2BE3A8[slot] = D_L00_0016175C_gp; + D_L00_001618D8_2BE3A8[slot] = l00_beam_pulse_start_corner_scale; D_L00_001618B8_2BE3A8[slot] = func_001FA888_2BE3A8(D_L00_00161763_macro[0]); qcopy(&beam_pulse_positions[slot], beam_effect_state); func_001F9BF0_2BE3A8(&side, &beam_nodes[1], &beam_nodes[0]); @@ -1962,10 +1962,10 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { D_L00_001618E8_2BE3A8[pulse] = 0; continue; } - if (D_L00_001617D8_macro[pulse] < D_L00_00161750_gp) { - D_L00_001618B8_2BE3A8[pulse] = D_L00_001618B8_2BE3A8[pulse] - D_L00_00161768_gp; + if (D_L00_001617D8_macro[pulse] < l00_beam_pulse_alpha_fade_remaining_frames_threshold) { + D_L00_001618B8_2BE3A8[pulse] = D_L00_001618B8_2BE3A8[pulse] - l00_beam_pulse_alpha_decrement_per_update; } - dt = D_L00_00161748_gp * D_0015ED6C_gp; + dt = l00_beam_pulse_travel_speed * D_0015ED6C_gp; travelled = D_L00_001617F8_macro[pulse] + dt; max_length = D_L00_001616DC_gp; ratio = travelled / max_length; @@ -1974,7 +1974,7 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { ratio = 1.0f; } D_L00_001618D8_2BE3A8[pulse] = - D_L00_0016175C_gp + (D_L00_00161758_gp - D_L00_0016175C_gp) * ratio; + l00_beam_pulse_start_corner_scale + (l00_beam_pulse_end_corner_scale - l00_beam_pulse_start_corner_scale) * ratio; if (max_length <= travelled) { func_001F9C30_2BE3A8(&side, &beam_pulse_directions[pulse], dt); func_001F9BD8_2BE3A8(&beam_pulse_positions[pulse], &beam_pulse_positions[pulse], &side); From b528b7dc025967dd04487b6d01c314607b629c93 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:12:42 +0000 Subject: [PATCH 0140/1502] decomp: clarify names in update_giant_clank_charged_blast p -> offset_particle: Authoritative source SHA-256 c42a768a83a0eee63adb59db98c44d9da515dda1321fd9ef6ca7fdf791e550bd declares this Part29FF90 pointer in the eight-iteration loop. Retail 0x0029f638 writes a random spherical offset to sp+0x10; 0x0029f650-0x0029f660 passes that storage to spawn_mode_controlled_rotating_alpha_fade_particle. Its return is moved to s0 at 0x0029f664, checked for null at 0x0029f668, and receives a float at +0xC at 0x0029f694. Original Ghidra lVar14 follows this same spawn/check/store flow, proving a spawned particle using the offset input. p -> blast_center_particle: The second Part29FF90 pointer in the authoritative source receives spawn_mode_controlled_rotating_alpha_fade_particle(moby->pos, D_L15_0015F580, 0x7F, moby) in the twelve-iteration loop. Retail s6 is moby+0x10 at 0x0029f3a4-0x0029f3a8; 0x0029f6c8 passes it as a0 to the spawn at 0x0029f6dc. Return s0 at 0x0029f6e4 is null checked, then +0xC and +0xA and the +0x20 subrecord are initialized through 0x0029f764. Original Ghidra lVar14/iVar9 corroborates the spawned particle based at the blast moby's position. --- .../vehicles/giant_clank_charged_blast.c | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/overlays/shared/vehicles/giant_clank_charged_blast.c b/src/overlays/shared/vehicles/giant_clank_charged_blast.c index 1e314bb9c3..9a7f75b01b 100644 --- a/src/overlays/shared/vehicles/giant_clank_charged_blast.c +++ b/src/overlays/shared/vehicles/giant_clank_charged_blast.c @@ -419,16 +419,16 @@ void giant_clank_charged_blast_update(Moby29FF90 *moby) { int i; for (i = 0; i < 8; i++) { - Part29FF90 *p; + Part29FF90 *offset_particle; random_spherical_offset( random_effect_vector, r * D_0015ED6C, r * 2.0f * D_0015ED6C); random_spherical_offset(effect_vector_scratch, 0.0f, r * 0.5f); add_vectors(temporary_position, effect_vector_scratch, moby->pos); - p = (Part29FF90 *)spawn_mode_controlled_rotating_alpha_fade_particle( + offset_particle = (Part29FF90 *)spawn_mode_controlled_rotating_alpha_fade_particle( effect_vector_scratch, random_effect_vector, 0x7F, moby); - if (p != 0) { - p->fC = random_float_between(6000.0f, 32000.0f) * r * 0.4f; + if (offset_particle != 0) { + offset_particle->fC = random_float_between(6000.0f, 32000.0f) * r * 0.4f; } } } @@ -436,20 +436,20 @@ void giant_clank_charged_blast_update(Moby29FF90 *moby) { int i; for (i = 0; i < 12; i++) { - Part29FF90 *p = (Part29FF90 *)spawn_mode_controlled_rotating_alpha_fade_particle( + Part29FF90 *blast_center_particle = (Part29FF90 *)spawn_mode_controlled_rotating_alpha_fade_particle( moby->pos, D_L15_0015F580, 0x7F, moby); - if (p != 0) { - PartSub29FF90 *particle_subrecord = &p->sub; + if (blast_center_particle != 0) { + PartSub29FF90 *particle_subrecord = &blast_center_particle->sub; if (i == 2 && random_integer_below(8) == 0) { - p->fC = 180000.0f; + blast_center_particle->fC = 180000.0f; } else { - p->fC = random_float_between(80000.0f, 120000.0f); + blast_center_particle->fC = random_float_between(80000.0f, 120000.0f); } - p->fC = p->fC * r; - p->fA = scale_game_frames(2); - particle_subrecord->f10 = 1.0f / convert_integer_to_float(p->fA); + blast_center_particle->fC = blast_center_particle->fC * r; + blast_center_particle->fA = scale_game_frames(2); + particle_subrecord->f10 = 1.0f / convert_integer_to_float(blast_center_particle->fA); particle_subrecord->f18 = 0x7F7F7F; particle_subrecord->f16 = 3; } From fb86c37902d29f58a22e13482185e802d66d4e5c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:19:10 +0000 Subject: [PATCH 0141/1502] decomp: clarify names in update_explosive_projectile D_L01_00167240 -> camera_pos: Authoritative bomber_jet_projectile.c SHA-256 4f3090fff4a32122a5819b01ca7cb2cf322fc1072baafcc0ab596065f0ea2761 declares this extern char array and passes it to fast_vec_dist with moby->pos, producing camera_distance and view_distance. Retail 0x002f6d68-0x002f6d78 constructs address 0x00167240 in a0 for distance helper 0x00221360; 0x002f6e50-0x002f6e58 passes the same address in a1 with projectile position in a0. The first distance in f26 gates extra glow effects at 100.0 (0x002f7380-0x002f7394); the second controls burst count and near-view fade (0x002f6e74-0x002f6ebc). Retail 0x002f7698-0x002f76a0 also passes this position to is_point_inside_clip_volume with the linked target volume. Supplied existing_names identifies camera_pos for this identical assembler label, so reuse that exact spelling while preserving the label and declaration type. --- src/overlays/shared/enemies/bomber_jet_projectile.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/enemies/bomber_jet_projectile.c b/src/overlays/shared/enemies/bomber_jet_projectile.c index cf4ac2e397..40193cdbea 100644 --- a/src/overlays/shared/enemies/bomber_jet_projectile.c +++ b/src/overlays/shared/enemies/bomber_jet_projectile.c @@ -64,7 +64,7 @@ extern Cols l01_explosive_projectile_secondary_color_palette __asm__("D_L01_0020 extern struct Moby *D_L01_001742D8 NOT_SDA; extern char *ents_macro __asm__("D_L01_0015FFD8") MACRO_ADDR; extern char D_0013E533[]; -extern char D_L01_00167240[]; +extern char camera_pos[] __asm__("D_L01_00167240"); extern float D_0015ED6C MACRO_ADDR; extern float D_L01_0015F5D0 MACRO_ADDR; extern int cutscene_active_macro __asm__("D_L01_0015F404") MACRO_ADDR; @@ -173,7 +173,7 @@ void explosive_projectile_update(struct Moby *moby) { } if (moby->state != 0) { size_scale = 8.0f; - camera_distance = fast_vec_dist(D_L01_00167240, &(*(Vec_2F7E08 *)&moby->pos)); + camera_distance = fast_vec_dist(camera_pos, &(*(Vec_2F7E08 *)&moby->pos)); if (cutscene_active_macro != 0) { size_scale = 4.0f; } @@ -199,7 +199,7 @@ void explosive_projectile_update(struct Moby *moby) { } } } - view_distance = fast_vec_dist(&(*(Vec_2F7E08 *)&moby->pos), D_L01_00167240); + view_distance = fast_vec_dist(&(*(Vec_2F7E08 *)&moby->pos), camera_pos); max_rings = 5; if (cutscene_active_macro != 0) { max_rings = 2; @@ -393,7 +393,7 @@ void explosive_projectile_update(struct Moby *moby) { (*(void **)&((struct Moby *)ents_macro)[projectile_vars->ids[link]].pvars); if (target->h4 == 0 && target->timer == 0 && is_point_inside_clip_volume(((char *)&D_0013F3D0), target->vol) != 0 && - is_point_inside_clip_volume(D_L01_00167240, target->vol) != 0) { + is_point_inside_clip_volume(camera_pos, target->vol) != 0) { target->timer = scale_game_frames(random_int_between(0x3C, 0xB4)); } } From c11d58559dc6a712723bf3a7d44ee373c1d41c41 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:21:35 +0000 Subject: [PATCH 0142/1502] decomp: clarify names in infobot_update D_L00_001B04B0 -> toad_paths: Authoritative C declares extern Path *D_L00_001B04B0[]. Retail 002d5f08..002d5f14 forms 0x001b04b0 + slots[i]*4 and loads a path pointer; 002d5f18..002d5f64 reads its count and stores adjacent-point distances into start-point w at +0x1c with 16-byte strides. 002d6298..002d62c4 selects slots[seg] from this table for the existing path-motion helper. 002d6468..002d64c8 selects infobot->path from the same table for nearest-path search; 002d6814..002d6830 and 002d690c..002d693c use that path's final point for orbit positioning and proximity. Original Ghidra expresses these reads as (&DAT_001b04b0)[index]. Supplied identical-assembler-label existing_names proves the established spelling toad_paths, which is reused exactly. --- src/overlays/shared/pickups/infobot.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/shared/pickups/infobot.c b/src/overlays/shared/pickups/infobot.c index c207e25cc2..5bda12090e 100644 --- a/src/overlays/shared/pickups/infobot.c +++ b/src/overlays/shared/pickups/infobot.c @@ -149,7 +149,7 @@ extern float FUN_001f9bf8_2d5988(void *, void *, f32) __asm__("FUN_001f9bf8"); extern float FUN_001f9dc8_2d5988(f32) __asm__("FUN_001f9dc8"); extern float FUN_001f9de0_2d5988(f32) __asm__("FUN_001f9de0"); -extern Path *D_L00_001B04B0[]; +extern Path *toad_paths[] __asm__("D_L00_001B04B0"); extern Player D_0013F3D0; extern Camera D_0013F350; extern f32 D_0015ED6C; @@ -372,9 +372,9 @@ void infobot_update(struct Moby *moby) { if (infobot->slots[i] == -1) { continue; } - measure_path(D_L00_001B04B0[infobot->slots[i]]); + measure_path(toad_paths[infobot->slots[i]]); } - MPOS(moby)->q = D_L00_001B04B0[infobot->slots[0]]->pts[0].q; + MPOS(moby)->q = toad_paths[infobot->slots[0]]->pts[0].q; infobot->seg = 0; moby->state = 3; break; @@ -441,7 +441,7 @@ void infobot_update(struct Moby *moby) { } break; case INFOBOT_FOLLOW_SLOT_PATH: - FUN_L00_002d5988_2d5de8(moby, D_L00_001B04B0[infobot->slots[infobot->seg]], 3); + FUN_L00_002d5988_2d5de8(moby, toad_paths[infobot->slots[infobot->seg]], 3); FUN_L00_002d6cd0_2d5de8(moby); if (moby->state != 4) { infobot->seg++; @@ -472,14 +472,14 @@ void infobot_update(struct Moby *moby) { } moby->state = 6; infobot->attach = -1; - MPOS(moby)->q = D_L00_001B04B0[infobot->path]->pts[0].q; + MPOS(moby)->q = toad_paths[infobot->path]->pts[0].q; moby->rot.z = fast_arc_tan( - D_L00_001B04B0[infobot->path]->pts[1].v.x - D_L00_001B04B0[infobot->path]->pts[0].v.x, - D_L00_001B04B0[infobot->path]->pts[1].v.y - D_L00_001B04B0[infobot->path]->pts[0].v.y); - measure_path(D_L00_001B04B0[infobot->path]); + toad_paths[infobot->path]->pts[1].v.x - toad_paths[infobot->path]->pts[0].v.x, + toad_paths[infobot->path]->pts[1].v.y - toad_paths[infobot->path]->pts[0].v.y); + measure_path(toad_paths[infobot->path]); break; case INFOBOT_FOLLOW_PATH: - path = D_L00_001B04B0[infobot->path]; + path = toad_paths[infobot->path]; pos = (Vec *)&moby->pos; FUN_L00_002d6cd0_2d5de8(moby); FUN_L00_0025df68(path, pos, &point, &segment, &fraction, 0, 999.0f, 5.0f, 0.0f); @@ -541,7 +541,7 @@ void infobot_update(struct Moby *moby) { &infobot->spin[0]); break; case INFOBOT_ORBIT_PATH_ENDPOINT: { - Path *orbit_path = D_L00_001B04B0[infobot->path]; + Path *orbit_path = toad_paths[infobot->path]; FUN_L00_002d6cd0_2d5de8(moby); infobot->sway = infobot->sway + D_0015ED6C; if (1.0f < infobot->sway) { From 701b35cfa69fab3b3145d7c9a0bf623f0c684a49 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:21:45 +0000 Subject: [PATCH 0143/1502] decomp: clarify names in planetbuster_maximus_part_update D_L12_00161F34 -> l12_planetbuster_maximus_proximity_fire_counter: D_L12_00161F34 -> l12_planetbuster_maximus_proximity_fire_counter. In the authoritative source, PLANETBUSTER_POST_PATH_GUN_UPDATE increments this int before updating the guns; original retail decompilation iGpffffb334 and instructions 003071d0/003071e8/003071f0 confirm load, increment and store at gp-0x4ccc. Checked gun helper evidence 483057108fc14466b5473d67ee9a1396 confirms 003057d8..00305824 compares it against scale_game_frames(0x4B0) and enables the proximity firing branch when XY distance <80 and absolute Z separation <4. Retail 00305828..00305860 resets the same scalar when XY distance >90 or Z separation >7. Retail 00305cf8..00305d0c presets it to scale_game_frames(0xFA0) on the source's hit branch when D_L12_00161F00 is zero. This proves a proximity-fire gating counter, not a projectile cooldown. --- src/overlays/l12/mobys/planetbuster_maximus_part.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l12/mobys/planetbuster_maximus_part.c b/src/overlays/l12/mobys/planetbuster_maximus_part.c index 5fb63c50c9..74379cc46f 100644 --- a/src/overlays/l12/mobys/planetbuster_maximus_part.c +++ b/src/overlays/l12/mobys/planetbuster_maximus_part.c @@ -63,7 +63,7 @@ extern float spring_angle(void *, float, void *, int, float, float, float) __asm__("FUN_L00_0025bc98"); extern int D_L12_00161F20 MACRO_ADDR; extern int D_L12_00161F24 MACRO_ADDR; -extern int D_L12_00161F34 __attribute__((sda)); +extern int l12_planetbuster_maximus_proximity_fire_counter __asm__("D_L12_00161F34") __attribute__((sda)); extern int planetbuster_maximus_gun_part_slots[] __asm__("D_L12_001FB670"); extern int D_L12_001FB688[]; extern int FUN_L00_001fefc8(void *); @@ -157,13 +157,13 @@ void update_planetbuster_maximus_guns(char *moby) { hp = (float *)(((char *)&hero) + 0x80); owner_to_hero_distance_xy = vector_distance_xy(moby + 0x10, hp); dz = absolute_float(hp[2] - MOBY(moby)->pos.z); - if (scale_game_frames(0x4B0) < D_L12_00161F34) { + if (scale_game_frames(0x4B0) < l12_planetbuster_maximus_proximity_fire_counter) { if (owner_to_hero_distance_xy < 80.0f && dz < 4.0f) { flag = 1; } } if (owner_to_hero_distance_xy > 90.0f || dz > 7.0f) { - D_L12_00161F34 = 0; + l12_planetbuster_maximus_proximity_fire_counter = 0; } if ((D_L12_00161F00_gp != 0 || flag) && md->f80 > 0.0f) { fast_dec_timer_s16(&md->h98); @@ -280,7 +280,7 @@ void update_planetbuster_maximus_guns(char *moby) { } } if (D_L12_00161F00_gp == 0) { - D_L12_00161F34 = scale_game_frames(0xFA0); + l12_planetbuster_maximus_proximity_fire_counter = scale_game_frames(0xFA0); goto done; } md->w84 = scale_game_frames(0x14); @@ -862,7 +862,7 @@ void planetbuster_maximus_part_update(char *moby) { break; } case PLANETBUSTER_POST_PATH_GUN_UPDATE: - D_L12_00161F34++; + l12_planetbuster_maximus_proximity_fire_counter++; spring_angle(moby + 0x48, 3.0543261f, &moby_data->unk5F4, From 53aa63db113846b7676284c399d5573eceae6822 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:24:06 +0000 Subject: [PATCH 0144/1502] decomp: clarify names in set_third_hero_easing_parameters a -> hero_ease_acceleration: In authoritative source SHA-256 4c41b506099b7036c36a37de21e171e342e03e658ab840a37ff197355e0a9306, set_third_hero_easing_parameters assigns float a directly to destination[2].accel, with destination = hero_eases. Retail 0x0020a210/0x0020a214 constructs 0x0017a680 and 0x0020a220 stores first float argument f12 at +0x204 (0x0017a884); original decompilation agrees DAT_0017a884 = param_1. This proves the hero ease acceleration parameter. b -> hero_ease_max_speed: In the authoritative source, set_third_hero_easing_parameters assigns float b directly to destination[2].max_speed, with destination = hero_eases. Retail 0x0020a218 stores second float argument f13 at base 0x0017a680 +0x208 (0x0017a888); original decompilation agrees DAT_0017a888 = param_2. Caller update_hero_target_tracking supplies frame_scale_sq * 0.3f as this second argument, consistent with a configurable third-ease maximum speed. --- .../shared/hero/set_second_hero_easing_parameters.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/hero/set_second_hero_easing_parameters.c b/src/overlays/shared/hero/set_second_hero_easing_parameters.c index 179f04291d..e2db6104f3 100644 --- a/src/overlays/shared/hero/set_second_hero_easing_parameters.c +++ b/src/overlays/shared/hero/set_second_hero_easing_parameters.c @@ -17,10 +17,10 @@ extern struct HeroEase hero_eases[] __asm__("D_L00_0017A680"); /* Sets the accel and max_speed of one hero ease. */ void set_third_hero_easing_parameters(float a, float b) __asm__("FUN_L00_0020a210"); -void set_third_hero_easing_parameters(float a, float b) { +void set_third_hero_easing_parameters(float hero_ease_acceleration, float hero_ease_max_speed) { struct HeroEase *destination = hero_eases; - destination[2].accel = a; - destination[2].max_speed = b; + destination[2].accel = hero_ease_acceleration; + destination[2].max_speed = hero_ease_max_speed; } extern struct HeroEase hero_eases[] __asm__("D_L00_0017A680"); From 46854de655f51ebb1b51272415aa16d5922338ec Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:24:16 +0000 Subject: [PATCH 0145/1502] decomp: clarify names in gunship_follow_path D_L01_00167240 -> camera_pos: The supplied naming_file_globals.existing_names maps this identical assembler label D_L01_00167240 to camera_pos. Current C uses the char array as the second position in fast_vec_dist(&moby->pos, D_L01_00167240). Original Ghidra shows distance(param_1+0x10,0x167240). Retail 002f53c0 loads high half 0x16 into a1, 002f53c4 passes moby+0x10 in a0, and 002f53c8/002f53cc calls the vector-distance helper with a1=00167240; 002f53d0..002f53f8 gates voice allocation on distance below 30.0. Reuse the supplied canonical same-label camera position name while preserving char-array type and assembler identity. --- src/overlays/shared/vehicles/gunship.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/vehicles/gunship.c b/src/overlays/shared/vehicles/gunship.c index 39c71ee842..71b7463ff8 100644 --- a/src/overlays/shared/vehicles/gunship.c +++ b/src/overlays/shared/vehicles/gunship.c @@ -97,7 +97,7 @@ typedef struct { u16 kind; } HitInfo; -extern char D_L01_00167240[]; +extern char camera_pos[] __asm__("D_L01_00167240"); extern int D_0015ED84; extern void FUN_0022da68(int, int, char *); @@ -264,7 +264,7 @@ void gunship_update(struct Moby *moby) { if (v->unk138 != -1) { if (!fast_dec_timer_s16(&v->unk138)) break; - if (fast_vec_dist(&moby->pos, D_L01_00167240) < 30.0f) + if (fast_vec_dist(&moby->pos, camera_pos) < 30.0f) allocate_voice_for_target_entry(1, 0, moby); } v->unk138 = scale_game_frames(random_int_between(v->unk13C, v->unk13C + v->unk13E)); From e3b9316c34d7eea8835c07ef9c3a6d5c9adcd9fd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:24:25 +0000 Subject: [PATCH 0146/1502] decomp: clarify names in bolt_crank_update D_L01_00167240 -> camera_pos: Retail 002e0f90/002e0f9c constructs s0=0x00167240; 002e0fa4 passes s0+0x10 in a1 and 002e0fb4 passes s0 in a0 to jet_mount at 002e0fb0. Exact source uses this global and global+0x10 for that camera mount, immediately followed by set_camera_rotation and set_camera_position from crank->camera_point. Supplied naming_context explicitly establishes camera_pos as an existing spelling for this identical assembler data label, so reuse that name without inferring a new layout or synonym. --- src/overlays/shared/props/bolt_crank.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/props/bolt_crank.c b/src/overlays/shared/props/bolt_crank.c index 97d65dc411..8cb5c32de7 100644 --- a/src/overlays/shared/props/bolt_crank.c +++ b/src/overlays/shared/props/bolt_crank.c @@ -46,7 +46,7 @@ typedef struct { f32 rest_height; /* 0x3C */ } BoltCrankVars; -extern char D_L01_00167240[]; +extern char camera_pos[] __asm__("D_L01_00167240"); extern int D_0015ED84; extern unsigned char menu_item_enabled_1_lui __asm__("D_0013D395") NOT_SDA; @@ -166,8 +166,8 @@ void bolt_crank_update(struct Moby *moby) { goto done; } l01_hero_set_state(HERO_STATE_CRANK, 1); - jet_mount(D_L01_00167240, - D_L01_00167240 + 0x10, + jet_mount(camera_pos, + camera_pos + 0x10, 3, scale_game_frames(0xB4), 0); From ec5d91a94116f0625024583ec9fa1c6b5973b006 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:24:35 +0000 Subject: [PATCH 0147/1502] decomp: clarify names in frog_update D_L06_00161C10 -> l06_frog_updates_disabled: The listed level-06 int is read at retail 0x002e867c (gp-0x4ff0); 0x002e86b0 branches directly to the epilogue when nonzero, before all frog health, target, initialization and movement processing. Thus its proven local role is disabling frog updates; the source uses exactly this nonzero early-return gate. D_L06_00161C14 -> l06_frog_frame_slot_assignment_count: Retail 0x002e87dc..0x002e880c reads this level-06 int, assigns its signed remainder modulo eight to frog vars+0x20a, and writes back count+1 during initialization. Source RespawnVars names +0x20a frame_slot, and update_frog_health_respawn_and_target compares it with level_frame_count%8 to stagger target selection. data -> frog_instance_vars: Authoritative frog.c assigns data from MOBY(moby)->pvars. Retail 0x002e86b4 loads s4 from moby+0x78; s4 then owns target+0x1c0, motion+0x120, path+0x1f8 and saved home+0x210 throughout frog_update. This is the frog instance's variable block. dist -> home_distance_xy: In case 4, retail 0x002e8ba8..0x002e8bc4 copies the final path point into vars+0x210 and vars+0x230. At 0x002e8bc8..0x002e8bd8 vector_distance_xy(moby+0x10,vars+0x210) supplies dist, divided by scaled 30 frames at 0x002e8c08 to launch motion toward that saved home point. switch_0_case_0 -> FROG_STATE_INITIALIZE: The selector is this frog Moby's state byte at moby+0x20 (retail 0x002e87b0..0x002e87d4), not a HeroStateId or another mode domain. Case 0 at 0x002e87dc..0x002e89d8 assigns the frame slot, saves position/rotation, initializes path index and motion fields, optionally creates the child, and selects a subsequent state. These one-time setup operations establish initialization. switch_0_case_1 -> FROG_STATE_WAIT_WITH_CHILD: The selector is this frog Moby's state byte at moby+0x20 (retail 0x002e87b0..0x002e87d4), not a HeroStateId or another mode domain. Initialization stores state 1 and creates the child at 0x002e88e8..0x002e88fc. Its handler 0x002e89dc..0x002e8a24 waits until target XY distance is below four, clears flags, destroys that child, and enters wandering state 8. switch_0_case_10 -> FROG_STATE_BLINKING_APPROACH_TARGET: The selector is this frog Moby's state byte at moby+0x20 (retail 0x002e87b0..0x002e87d4), not a HeroStateId or another mode domain. Retail 0x002e904c..0x002e9108 repeats target-heading approach movement. This variant is entered when vars+0x1e8 is nonzero (0x002e8ee0..0x002e8f10), the source RespawnVars blink_timer field. It returns home when that timer expires at 0x002e9148..0x002e9158 and can pause or attack. switch_0_case_11 -> FROG_STATE_APPROACH_PAUSE: The selector is this frog Moby's state byte at moby+0x20 (retail 0x002e87b0..0x002e87d4), not a HeroStateId or another mode domain. State 10 enters 11 and selects animation 6 after the successful path query and near-point test at 0x002e9110..0x002e9188. Case 11 at 0x002e91dc..0x002e9200 performs no movement; it waits for animation flag bit 2, then resumes approach state 10 with animation 4. switch_0_case_12 -> FROG_STATE_ATTACK: The selector is this frog Moby's state byte at moby+0x20 (retail 0x002e87b0..0x002e87d4), not a HeroStateId or another mode domain. Target approach enters state 12 below two units and selects animation 5 at 0x002e8fd8..0x002e9028. Handler 0x002e9204..0x002e9334 faces the target and, during animation frames 10 through 15, doubles forward movement and calls collect_mobies_in_sphere_at_moby_point. On animation completion with target beyond two it resumes approach. switch_0_case_13 -> FROG_STATE_RETURN_HOME: The selector is this frog Moby's state byte at moby+0x20 (retail 0x002e87b0..0x002e87d4), not a HeroStateId or another mode domain. At 0x002e937c..0x002e93ec the handler faces saved home vars+0x210 minus current position and moves toward it. At 0x002e93f0..0x002e9424 distance below two restores wander state 8; other branches resume target approach when target mode or blink conditions permit. switch_0_case_16 -> FROG_STATE_SUCK_CANNON_HELD: The selector is this frog Moby's state byte at moby+0x20 (retail 0x002e87b0..0x002e87d4), not a HeroStateId or another mode domain. Supplied authoritative sibling source update_moby_grab_state enters moby->state 0x10 when process_moby_suck_cannon_suction holds this frog; storage and cancellation methods also preserve the previous state and enter 0x10. Assigned handler 0x002e947c..0x002e94b8 uses the motion record and returns to wander state 8 when its helper completes. switch_0_case_3 -> FROG_STATE_WAIT_TO_FOLLOW_PATH: The selector is this frog Moby's state byte at moby+0x20 (retail 0x002e87b0..0x002e87d4), not a HeroStateId or another mode domain. Initialization chooses state 3 only for nonnegative path ID at 0x002e8984..0x002e8998. Handler 0x002e8a30..0x002e8a90 faces the target without moving, then enters path-following state 4 when the reference position comes within vars+0x24c. switch_0_case_4 -> FROG_STATE_FOLLOW_PATH: The selector is this frog Moby's state byte at moby+0x20 (retail 0x002e87b0..0x002e87d4), not a HeroStateId or another mode domain. Retail 0x002e8a9c..0x002e8acc reads the indexed path point using vars+0x1f8 and signed point index +0x208. The handler faces and moves toward it, increments that index at 0x002e8b9c..0x002e8ba4, or launches motion to the last point after reaching the final walking segment. switch_0_case_5 -> FROG_STATE_JUMP_TO_HOME: The selector is this frog Moby's state byte at moby+0x20 (retail 0x002e87b0..0x002e87d4), not a HeroStateId or another mode domain. At 0x002e8ba8..0x002e8c64, the last path point becomes saved home vars+0x210; XY distance/30-frame duration and negative acceleration feed trajectory setup and trooper_start_knockback, then state 5 is stored. Handler 0x002e8c68..0x002e8ca0 aligns to that motion and waits for landing before state 7. switch_0_case_7 -> FROG_STATE_LANDING_ANIMATION: The selector is this frog Moby's state byte at moby+0x20 (retail 0x002e87b0..0x002e87d4), not a HeroStateId or another mode domain. Both motion handlers enter state 7 at 0x002e8cc4..0x002e8d08 when step_moby_motion returns bit 1, select sequence 3, and snap Z to ground height. Case 7 at 0x002e8d34..0x002e8d58 waits for animation flag bit 2 then returns to wandering state 8. switch_0_case_8 -> FROG_STATE_WANDER: The selector is this frog Moby's state byte at moby+0x20 (retail 0x002e87b0..0x002e87d4), not a HeroStateId or another mode domain. Handler 0x002e8d5c..0x002e8e9c chooses random angle/radius offsets about saved home vars+0x210, writes destination +0x230, sets a randomized timer, faces and moves toward that point. It can then select target-approach states 9 or 10. switch_0_case_9 -> FROG_STATE_APPROACH_TARGET: The selector is this frog Moby's state byte at moby+0x20 (retail 0x002e87b0..0x002e87d4), not a HeroStateId or another mode domain. At 0x002e8f38..0x002e8fd4 the handler computes target-minus-frog heading plus randomized angular offset, faces that heading and moves forward. Target XY distance below two selects attack state 12; target mode 2 selects return-home state 13 at 0x002e9034..0x002e9048. --- src/overlays/shared/enemies/frog.c | 48 +++++++++++++++--------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/overlays/shared/enemies/frog.c b/src/overlays/shared/enemies/frog.c index 9ae5ecdf99..bfa0847532 100644 --- a/src/overlays/shared/enemies/frog.c +++ b/src/overlays/shared/enemies/frog.c @@ -184,8 +184,8 @@ extern float D_0015ED70 MACRO_ADDR; extern int *D_L06_001B0C30[]; extern int D_L06_0015F5C4 MACRO_ADDR; extern int D_L06_0015FDF8 MACRO_ADDR; -extern int D_L06_00161C10 __attribute__((sda)); -extern int D_L06_00161C14 __attribute__((sda)); +extern int l06_frog_updates_disabled __asm__("D_L06_00161C10") __attribute__((sda)); +extern int l06_frog_frame_slot_assignment_count __asm__("D_L06_00161C14") __attribute__((sda)); extern short D_L06_00161BF0[1] __attribute__((sda)); extern char D_0013F3D0[]; extern f32 D_L06_0015F580[] MACRO_ADDR; @@ -245,16 +245,16 @@ void frog_update(unsigned char *moby) __asm__("FUN_L06_002e8678"); /* Moby class 827 */ void frog_update(unsigned char *moby) { - float A[4] __attribute__((aligned(16))); + enum { FROG_STATE_INITIALIZE = 0 , FROG_STATE_WAIT_WITH_CHILD = 1 , FROG_STATE_WAIT_TO_FOLLOW_PATH = 3 , FROG_STATE_FOLLOW_PATH = 4 , FROG_STATE_JUMP_TO_HOME = 5 , FROG_STATE_LANDING_ANIMATION = 7 , FROG_STATE_WANDER = 8 , FROG_STATE_APPROACH_TARGET = 9 , FROG_STATE_BLINKING_APPROACH_TARGET = 10 , FROG_STATE_APPROACH_PAUSE = 11 , FROG_STATE_ATTACK = 12 , FROG_STATE_RETURN_HOME = 13 , FROG_STATE_SUCK_CANNON_HELD = 16 } ;float A[4] __attribute__((aligned(16))); float B[4] __attribute__((aligned(16))); float C[4] __attribute__((aligned(16))); float D[4] __attribute__((aligned(16))); - FrogVars *data; + FrogVars *frog_instance_vars; unsigned char *target; int mode; - data = (FrogVars *)MOBY(moby)->pvars; - if (D_L06_00161C10 != 0) { + frog_instance_vars = (FrogVars *)MOBY(moby)->pvars; + if (l06_frog_updates_disabled != 0) { return; } mode = D_L06_0015F5C4; @@ -282,12 +282,12 @@ void frog_update(unsigned char *moby) { } target = data->unk1C0; switch (MOBY(moby)->state) { - case 0: { + case FROG_STATE_INITIALIZE: { float wait; - int spawn_count = D_L06_00161C14; + int spawn_count = l06_frog_frame_slot_assignment_count; int divisor = data->unk240; data->unk20A = spawn_count % 8; - D_L06_00161C14 = spawn_count + 1; + l06_frog_frame_slot_assignment_count = spawn_count + 1; if (divisor != 0) { MOBY(moby)->unkB4 = MOBY(moby)->unkB4 / divisor; } @@ -347,7 +347,7 @@ void frog_update(unsigned char *moby) { } break; } - case 1: + case FROG_STATE_WAIT_WITH_CHILD: if (vector_distance_xy(&MOBY(moby)->pos, target + 0x10) < 4.0f) { MOBY(moby)->flags &= 0xFFBE; destroy_frog_child_moby(moby); @@ -356,7 +356,7 @@ void frog_update(unsigned char *moby) { blend_moby_animation(moby, 4, 0, scale_game_frames(5)); } break; - case 3: + case FROG_STATE_WAIT_TO_FOLLOW_PATH: fast_vec_sub(A, target + 0x10, &MOBY(moby)->pos); probe_frog_local_z_collision((char *)moby); blend_frog_rotation_to_facing_frame((char *)moby, (float *)D_L06_00174600, A); @@ -366,7 +366,7 @@ void frog_update(unsigned char *moby) { blend_moby_animation(moby, 4, 0, scale_game_frames(5)); } break; - case 4: { + case FROG_STATE_FOLLOW_PATH: { int *path; int point_count; qcopy(B, (char *)D_L06_001B0C30[data->path_index] + data->path_point * 16 + 0x10); @@ -378,7 +378,7 @@ void frog_update(unsigned char *moby) { transform_vector_by_basis(A, A, moby + 0xC0); if (vector_length_xy(A) < 0.5f) { float return_speed; - float dist; + float home_distance_xy; path = D_L06_001B0C30[data->path_index]; point_count = *path; if (data->path_point < point_count - 2) { @@ -387,8 +387,8 @@ void frog_update(unsigned char *moby) { } qcopy(&data->unk210, (char *)path + point_count * 16); qcopy(&data->unk230, &data->unk210); - dist = vector_distance_xy(&MOBY(moby)->pos, &data->unk210); - return_speed = dist / (float)scale_game_frames(30); + home_distance_xy = vector_distance_xy(&MOBY(moby)->pos, &data->unk210); + return_speed = home_distance_xy / (float)scale_game_frames(30); data->unk138 = return_speed; data->unk13C = FUN_L00_0025abf0(&MOBY(moby)->pos, &data->unk210, 0, return_speed, -data->unk130); @@ -405,7 +405,7 @@ void frog_update(unsigned char *moby) { } break; } - case 5: + case FROG_STATE_JUMP_TO_HOME: set_vector_unit_z(A); blend_frog_rotation_to_facing_frame((char *)moby, A, (float *)(&data->motion)); if (step_moby_motion(moby, &data->motion) & 1) { @@ -431,14 +431,14 @@ void frog_update(unsigned char *moby) { } break; } - case 7: + case FROG_STATE_LANDING_ANIMATION: if (MOBY(moby)->anim_flags & 2) { MOBY(moby)->state = 8; if (MOBY(moby)->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(5)); } break; - case 8: + case FROG_STATE_WANDER: if (MOBY(moby)->visible != 0) { if (fast_vec_dist(&MOBY(moby)->pos, &data->unk230) < 0.05f || fast_dec_timer((int *)(&data->unk1FC)) != 0) { @@ -473,7 +473,7 @@ void frog_update(unsigned char *moby) { blend_moby_animation(moby, 4, 0, 0); } break; - case 9: { + case FROG_STATE_APPROACH_TARGET: { float angle = fast_add_rotations(fast_arc_tan(*(float *)(target + 0x10) - MOBY(moby)->pos.x, *(float *)(target + 0x14) - MOBY(moby)->pos.y), @@ -494,7 +494,7 @@ void frog_update(unsigned char *moby) { } break; } - case 10: { + case FROG_STATE_BLINKING_APPROACH_TARGET: { int near; float angle = fast_add_rotations(fast_arc_tan(*(float *)(target + 0x10) - MOBY(moby)->pos.x, @@ -526,14 +526,14 @@ void frog_update(unsigned char *moby) { } break; } - case 11: + case FROG_STATE_APPROACH_PAUSE: if (MOBY(moby)->anim_flags & 2) { MOBY(moby)->state = 0xA; if (MOBY(moby)->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(20)); } break; - case 12: { + case FROG_STATE_ATTACK: { float wait; B[0] = fast_cos(fast_arc_tan(*(float *)(target + 0x10) - MOBY(moby)->pos.x, *(float *)(target + 0x14) - MOBY(moby)->pos.y)); @@ -557,7 +557,7 @@ void frog_update(unsigned char *moby) { } break; } - case 13: + case FROG_STATE_RETURN_HOME: fast_vec_sub(B, &data->unk210, &MOBY(moby)->pos); probe_frog_local_z_collision((char *)moby); blend_frog_rotation_to_facing_frame((char *)moby, (float *)D_L06_00174600, B); @@ -573,7 +573,7 @@ void frog_update(unsigned char *moby) { MOBY(moby)->state = 0xA; } break; - case 16: + case FROG_STATE_SUCK_CANNON_HELD: if (FUN_L00_002dc9f0(moby, &data->motion) != 0) { MOBY(moby)->state = 8; if (MOBY(moby)->prev_seq != 0) From 3c917de1848d2d41a632f83b589a1976014054d7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:24:45 +0000 Subject: [PATCH 0148/1502] decomp: clarify names in large_amoeboid_update D_L01_00167240 -> camera_pos: Authoritative large_amoeboid.c SHA-256 0e3ed8f0c8661a7191b6daa4227e74ba0cd4c077380eacf16a9e7cae5c394f65 passes this extern char array to fast_vec_dist(moby+0x10, D_L01_00167240). Retail 002edd10..002edd1c constructs 0x00167240 as a1 and moby+0x10 as a0 for the vector-distance call; 002edd20..002edd34 compares the returned distance with 28.0f. Supplied existing_names identifies camera_pos for this identical assembler label; reuse that spelling exactly. This function reads the position through the distance helper and does not write it. --- src/overlays/shared/enemies/large_amoeboid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/large_amoeboid.c b/src/overlays/shared/enemies/large_amoeboid.c index 6fb068f440..c8f611de7b 100644 --- a/src/overlays/shared/enemies/large_amoeboid.c +++ b/src/overlays/shared/enemies/large_amoeboid.c @@ -103,7 +103,7 @@ typedef struct { char pA8[0x58]; } Ent; -extern char D_L01_00167240[]; +extern char camera_pos[] __asm__("D_L01_00167240"); float absolute_float(float input) __asm__("func_001F99C0"); extern void FUN_0020c828(void *); extern int func_L00_001EFFF0_t(void *, void *, int, void *, void *) __asm__("FUN_001efa68"); @@ -257,7 +257,7 @@ void large_amoeboid_update(unsigned char *moby) { return; } FUN_L00_00263ac8(2.9f, moby, 0, &large_amoeboid_vars->unk270); - if (MOBY(moby)->visible != 0 && fast_vec_dist(&MOBY(moby)->pos, D_L01_00167240) < 28.0f) { + if (MOBY(moby)->visible != 0 && fast_vec_dist(&MOBY(moby)->pos, camera_pos) < 28.0f) { FUN_L00_0025a120(moby); MOBY(moby)->shadow_range = 0x16; } From 6587a9418e5e3fd7d2c1bb07d2d7cfa5ab7796a7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:24:45 +0000 Subject: [PATCH 0149/1502] decomp: clarify names in hero_set_state a -> requested_state: Authoritative src/overlays/l02/hero/hero_set_state.c (SHA-256 3ff9bbe03bab038fbf802479907caab05e65d389d04d2bfe0f1acdfd8088b04f) assigns a to p->state.current and dispatches switch(a) using HERO_STATE_* labels. Retail 0x0022b748 saves incoming a0 in s1, 0x0022b888 stores s1 to hero+0x2084, and 0x0022b918..0x0022b938 bounds/indexes the state jump table with s1. Original Ghidra param_1 is likewise stored to iRam001413d4 and switched; supplied callers request HERO_STATE_HURT, HERO_STATE_IDLE and HERO_STATE_RUN through this first argument. Entry rejection tests precede assignment, proving requested_state rather than a saved previous state or control mode. --- src/overlays/l02/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l02/hero/hero_set_state.c b/src/overlays/l02/hero/hero_set_state.c index 7df557eb61..b14ac9ee32 100644 --- a/src/overlays/l02/hero/hero_set_state.c +++ b/src/overlays/l02/hero/hero_set_state.c @@ -69,13 +69,13 @@ extern void blend_moby_animation(void *, int, int, int) __asm__("FUN_00212f90"); extern int hero_set_state(int, int) __asm__("FUN_L02_0022b728"); extern char level02_hero_transform_trail_jump_velocity_keys[] __asm__("D_L02_0017C520"); -int hero_set_state(int a, int b) { +int hero_set_state(int requested_state, int b) { int saved_state_step; char *moby; int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((level_game_mode == 2 || level_game_mode == 6) && b != 2) @@ -83,8 +83,8 @@ int hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -97,7 +97,7 @@ int hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -122,7 +122,7 @@ int hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -705,7 +705,7 @@ int hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 3c2d1170a83343b8b94345bd95c1a982beb58805 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:24:45 +0000 Subject: [PATCH 0150/1502] decomp: clarify names in ultramech_unlimited_update n -> next_particle_batch_index: Authoritative src/overlays/l15/mobys/ultramech_unlimited.c SHA-256 8a8a4a6d5a95893d85d92004a8535124fd862a1295a7c6714590e607f2fc9501 declares n in the moving particle block: for (i = 0; i < 10; i = n) assigns n = i + 1 before the inner j=2..5 loop that calls moby_point_position and spawn_effect_particle_with_target_scalar. Retail 0x002d0d30 initializes the outer index in v1 to zero, 0x002d0d38 saves v1+1 in s5, 0x002d0e80-0x002d0e84 controls the inner joint loop, and 0x002d0e8c-0x002d0e98 restores v1 from s5, tests it against 10 and computes the following saved increment. Original Ghidra's outer iVar22 loop agrees. Thus n is the saved next particle-batch index, not a particle count or joint index. --- src/overlays/l15/mobys/ultramech_unlimited.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l15/mobys/ultramech_unlimited.c b/src/overlays/l15/mobys/ultramech_unlimited.c index 32370da575..db018a3cdb 100644 --- a/src/overlays/l15/mobys/ultramech_unlimited.c +++ b/src/overlays/l15/mobys/ultramech_unlimited.c @@ -876,10 +876,10 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { if (moving) { int i; int j; - int n; + int next_particle_batch_index; spawn: - for (i = 0; i < 10; i = n) { - n = i + 1; + for (i = 0; i < 10; i = next_particle_batch_index) { + next_particle_batch_index = i + 1; for (j = 2; j < 6; j++) { int k; position_or_motion_vector.q = 0; From aefb408c7d723610eedc3c54e3038af6275283d8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:27:05 +0000 Subject: [PATCH 0151/1502] decomp: clarify names in alien_snapper_update D_L06_00161EC4 -> l06_alien_snapper_bite_approach_radius: Retail gp-0x4d3c caps target-relative movement-goal radius at 0x002f84d0-0x002f84e4 and 0x002f87e8-0x002f87fc. The same threshold stops approach acceleration at 0x002f8718 and gates entry to bite state 11 at 0x002f8630 and 0x002f8908. D_L06_00161EC8 -> l06_alien_snapper_max_home_distance: At 0x002f88c4-0x002f88dc fast_vec_dist compares moby position against pvars+0x170 home and gp-0x4d38; exceeding this value branches to 0x002f88f8, setting state 12, whose handler moves toward home. D_L06_00161ED4 -> l06_alien_snapper_retreat_distance_limit: In retreat state 13, 0x002f8c28-0x002f8c40 computes the distance between moby and target and compares gp-0x4d2c. Exceeding this limit, or timer expiry, ends retreat and sets bite state 11 at 0x002f8c50. D_L06_00161EDC -> l06_alien_snapper_retreat_bite_override_enabled: Retail 0x002f8c5c-0x002f8c64 tests gp-0x4d24 when retreat enters bite state 11. Nonzero selects a five-frame animation blend with configurable start frame from gp-0x4d20; zero selects fixed frame 10 with a ten-frame blend. D_L06_00161EE0 -> l06_alien_snapper_retreat_bite_start_frame: At 0x002f8c84 gp-0x4d20 is loaded into a2 for blend_moby_animation at 0x002f8c90, with animation 4 in a1. This is the configured starting frame for the override transition from retreat state 13 to bite state 11. ang -> target_gap_angle_radians: At 0x002f84ec and 0x002f8808 the value returned by FUN_L06_002f96f8 is saved in f20, passed to cosine/sine and used to construct a target-relative goal. The supplied compute_alien_snapper_target_gap_angle source proves it is the obstacle-gap heading around the target in radians. buf -> bite_query_position: Retail 0x002f8a48-0x002f8a5c and 0x002f8fa4-0x002f8fb8 pass sp+0x40 as the position-query output; the same address is the attack query position at 0x002f8aa8/0x002f9004 and collision_line's first endpoint at 0x002f900c-0x002f901c. No exact bone identity is asserted. dist -> target_goal_radius: At 0x002f84c4-0x002f84e4 and 0x002f87dc-0x002f87fc the XY distance from moby to target is clamped to D_L06_00161EC4; f21 then multiplies cosine and sine before target position is added, proving the target-centered movement-goal radius. switch_0_case_0 -> ALIEN_SNAPPER_STATE_INITIALIZE: Selector is this alien snapper's Moby.state byte, loaded at 0x002f7e20 and dispatched at 0x002f7e2c-0x002f7e4c; it is not a HeroStateId or animation selector. 0x002f7e54-0x002f8020 initializes movement, speed, flags, home and timers, then selects an initial behavior state from the snapper configuration. switch_0_case_11 -> ALIEN_SNAPPER_STATE_BITE_TARGET: Selector is this alien snapper's Moby.state byte, loaded at 0x002f7e20 and dispatched at 0x002f7e2c-0x002f7e4c; it is not a HeroStateId or animation selector. 0x002f8980-0x002f8ab0 faces the target and, during interpolated animation values between 1 and 8, builds SnapperBite_91A8 direction/push data and runs the attack query; animation completion returns to approach state 8. switch_0_case_12 -> ALIEN_SNAPPER_STATE_RETURN_HOME: Selector is this alien snapper's Moby.state byte, loaded at 0x002f7e20 and dispatched at 0x002f7e2c-0x002f7e4c; it is not a HeroStateId or animation selector. 0x002f8cd4-0x002f8df4 turns toward pvars+0x170 home, performs movement and leaves when home distance is below 1. Supplied sibling calls this same moby state SNAPPER_RETURN_HOME. switch_0_case_13 -> ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET: Selector is this alien snapper's Moby.state byte, loaded at 0x002f7e20 and dispatched at 0x002f7e2c-0x002f7e4c; it is not a HeroStateId or animation selector. 0x002f8aec-0x002f8c50 increases speed to three times base speed and temporarily uses target-facing angle plus pi for movement, then restores yaw. Timer or target-distance limit ends retreat. Supplied sibling calls this state SNAPPER_RETREAT_FROM_TARGET. switch_0_case_14 -> ALIEN_SNAPPER_STATE_HIT_KNOCKBACK: Selector is this alien snapper's Moby.state byte, loaded at 0x002f7e20 and dispatched at 0x002f7e2c-0x002f7e4c; it is not a HeroStateId or animation selector. The supplied update_alien_snapper_hit_response_and_targeting source assigns moby state 14 for nonlethal hit reactions and starts motion mode 9. Retail handler 0x002f906c-0x002f90f4 waits for motion flags 0x41 and starts retreat if still inside the path. switch_0_case_15 -> ALIEN_SNAPPER_STATE_FACE_HERO: Selector is this alien snapper's Moby.state byte, loaded at 0x002f7e20 and dispatched at 0x002f7e2c-0x002f7e4c; it is not a HeroStateId or animation selector. 0x002f8e10-0x002f8eb0 approaches yaw toward hero position D_0013F350+0x80 and waits until XY distance is below 4 before setting state 16 and attack animation 4. switch_0_case_16 -> ALIEN_SNAPPER_STATE_BITE_HERO: Selector is this alien snapper's Moby.state byte, loaded at 0x002f7e20 and dispatched at 0x002f7e2c-0x002f7e4c; it is not a HeroStateId or animation selector. 0x002f8ecc-0x002f9020 turns toward the hero and runs the bite attack query plus collision_line during animation values 1 through 8; completion at 0x002f902c returns to hero-facing state 15. switch_0_case_17 -> ALIEN_SNAPPER_STATE_DEATH_MOTION: Selector is this alien snapper's Moby.state byte, loaded at 0x002f7e20 and dispatched at 0x002f7e2c-0x002f7e4c; it is not a HeroStateId or animation selector. Supplied hit-response source sets state 17 on lethal reactions and starts motion mode 10. Retail 0x002f9118-0x002f91ac waits for motion flag 0x40 to spawn break fragments and remove the moby, with removal also below z=2. switch_0_case_3 -> ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER: Selector is this alien snapper's Moby.state byte, loaded at 0x002f7e20 and dispatched at 0x002f7e2c-0x002f7e4c; it is not a HeroStateId or animation selector. 0x002f81b8-0x002f81e4 tests pvars+0x1c0 clip volume and is_point_inside_clip_volume for the hero position; only success advances state to 4. switch_0_case_7 -> ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH: Selector is this alien snapper's Moby.state byte, loaded at 0x002f7e20 and dispatched at 0x002f7e2c-0x002f7e4c; it is not a HeroStateId or animation selector. 0x002f86a4-0x002f86d4 decrements pvars+0x1a8 timer and, only on expiry, selects state 8 and randomizes angle jitter before approach animation 1. switch_0_case_8 -> ALIEN_SNAPPER_STATE_APPROACH_TARGET: Selector is this alien snapper's Moby.state byte, loaded at 0x002f7e20 and dispatched at 0x002f7e2c-0x002f7e4c; it is not a HeroStateId or animation selector. 0x002f8700-0x002f8964 turns toward the target, adjusts speed according to target distance, and constructs a target-relative movement goal. Home-distance excess selects return state 12, and close targets can select bite state 11. Supplied targeting sibling identifies this same state as SNAPPER_APPROACH_TARGET. switch_0_case_9 -> ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET: Selector is this alien snapper's Moby.state byte, loaded at 0x002f7e20 and dispatched at 0x002f7e2c-0x002f7e4c; it is not a HeroStateId or animation selector. 0x002f842c-0x002f8668 constructs a gap-angle goal around the target, moves toward it, and checks a path point for reach_distance. Supplied hit-response/targeting source identifies this same moby state as SNAPPER_REPOSITION_AROUND_TARGET. vars -> snapper_behavior: Retail 0x002f7db0 loads s4 from moby+0x78; subsequent s4+0x160 target, +0x170 home, +0x1a8 timer and +0xf4 speed accesses match SnapperVars_91A8. This pointer owns this snapper's persistent behavior and movement state. --- src/overlays/l06/mobys/alien_snapper.c | 266 ++++++++++++------------- 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/src/overlays/l06/mobys/alien_snapper.c b/src/overlays/l06/mobys/alien_snapper.c index 470ee56752..50ba1f1376 100644 --- a/src/overlays/l06/mobys/alien_snapper.c +++ b/src/overlays/l06/mobys/alien_snapper.c @@ -131,12 +131,12 @@ extern float D_0015ED70; extern float scale_time(float) __asm__("FUN_001f96b0"); extern float D_L06_00161EB0 __attribute__((sda)); extern float D_L06_00161EB4 __attribute__((sda)); -extern float D_L06_00161EC4 __attribute__((sda)); -extern float D_L06_00161EC8 __attribute__((sda)); +extern float l06_alien_snapper_bite_approach_radius __asm__("D_L06_00161EC4") __attribute__((sda)); +extern float l06_alien_snapper_max_home_distance __asm__("D_L06_00161EC8") __attribute__((sda)); extern float l06_alien_snapper_base_targeting_radius __asm__("D_L06_00161ED0") __attribute__((sda)); -extern float D_L06_00161ED4 __attribute__((sda)); -extern int D_L06_00161EDC __attribute__((sda)); -extern int D_L06_00161EE0 __attribute__((sda)); +extern float l06_alien_snapper_retreat_distance_limit __asm__("D_L06_00161ED4") __attribute__((sda)); +extern int l06_alien_snapper_retreat_bite_override_enabled __asm__("D_L06_00161EDC") __attribute__((sda)); +extern int l06_alien_snapper_retreat_bite_start_frame __asm__("D_L06_00161EE0") __attribute__((sda)); void update_alien_snapper_hit_response_and_targeting(Moby *moby) __asm__("FUN_L06_002f91e8"); extern char D_0013F3D0[]; extern void update_alien_snapper_hit_response_and_targeting(Moby *) __asm__("FUN_L06_002f91e8"); @@ -246,10 +246,10 @@ approach_angle(f32 *angle, f32 target, f32 *vel, f32, f32, f32) __asm__("FUN_L00 /* Moby class 1048 */ void alien_snapper_update(Moby *moby) { - SnapperVars_91A8 *vars = (SnapperVars_91A8 *)moby->pvars; + enum { ALIEN_SNAPPER_STATE_INITIALIZE = 0 , ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER = 3 , ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH = 7 , ALIEN_SNAPPER_STATE_APPROACH_TARGET = 8 , ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET = 9 , ALIEN_SNAPPER_STATE_BITE_TARGET = 11 , ALIEN_SNAPPER_STATE_RETURN_HOME = 12 , ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET = 13 , ALIEN_SNAPPER_STATE_HIT_KNOCKBACK = 14 , ALIEN_SNAPPER_STATE_FACE_HERO = 15 , ALIEN_SNAPPER_STATE_BITE_HERO = 16 , ALIEN_SNAPPER_STATE_DEATH_MOTION = 17 } ;SnapperVars_91A8 *snapper_behavior = (SnapperVars_91A8 *)moby->pvars; Moby *target; - float dist; - float ang; + float target_goal_radius; + float target_gap_angle_radians; float saved_rot; int start_frame; union { @@ -261,50 +261,50 @@ void alien_snapper_update(Moby *moby) { float path_point[4]; } m; } scratch; - float buf[4]; + float bite_query_position[4]; update_alien_snapper_hit_response_and_targeting(moby); - func_L00_00264B40_91A8(2.3f, moby, 1, vars->f1E0); + func_L00_00264B40_91A8(2.3f, moby, 1, snapper_behavior->f1E0); if (moby->visible != 0 && fast_vec_dist(&moby->pos, D_L06_00167540_macro) < 27.0f) { func_L00_0025B178_91A8(moby); moby->shadow_range = 0x15; } - target = vars->target; + target = snapper_behavior->target; moby->scale = moby->pclass->scale * D_L06_00161EB0; switch (moby->state) { - case 0: - vars->f28 = 3; - vars->f29 = 1; - vars->f20 = 4.0f; - vars->f24 = 4; - vars->f58 = truncate_float_to_s32(10.0f); - vars->f5A = truncate_float_to_s32(14.0f); + case ALIEN_SNAPPER_STATE_INITIALIZE: + snapper_behavior->f28 = 3; + snapper_behavior->f29 = 1; + snapper_behavior->f20 = 4.0f; + snapper_behavior->f24 = 4; + snapper_behavior->f58 = truncate_float_to_s32(10.0f); + snapper_behavior->f5A = truncate_float_to_s32(14.0f); moby->flags |= 0x5000; - qcopy(&vars->home, &moby->pos); - vars->reach_distance = random_float_between(0.0f, 1.0f); - func_L01_0026E8E0_91A8(&vars->movement); - vars->fDC = 2.0f; - vars->fD8 = 2.0f; - vars->movement = truncate_float_to_s32(D_L06_00161EB0 * 1024.0f); - vars->fD4 = D_L06_00161EB0; - vars->speed = vars->base_speed * frame_time; - vars->f90 = truncate_float_to_s32(768.0f); - vars->f98 = 0.75f; - vars->f80 = D_L06_00161EB4 * D_0015ED70; - vars->fAD = 0; - vars->f84 = 0.0005f; - vars->f94 = 9; - vars->f1C8 = random_angle_radians(); - if (vars->f1CC != 0) { + qcopy(&snapper_behavior->home, &moby->pos); + snapper_behavior->reach_distance = random_float_between(0.0f, 1.0f); + func_L01_0026E8E0_91A8(&snapper_behavior->movement); + snapper_behavior->fDC = 2.0f; + snapper_behavior->fD8 = 2.0f; + snapper_behavior->movement = truncate_float_to_s32(D_L06_00161EB0 * 1024.0f); + snapper_behavior->fD4 = D_L06_00161EB0; + snapper_behavior->speed = snapper_behavior->base_speed * frame_time; + snapper_behavior->f90 = truncate_float_to_s32(768.0f); + snapper_behavior->f98 = 0.75f; + snapper_behavior->f80 = D_L06_00161EB4 * D_0015ED70; + snapper_behavior->fAD = 0; + snapper_behavior->f84 = 0.0005f; + snapper_behavior->f94 = 9; + snapper_behavior->f1C8 = random_angle_radians(); + if (snapper_behavior->f1CC != 0) { moby->state = 0xF; if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, 0); } - } else if (vars->clip_volume >= 0) { + } else if (snapper_behavior->clip_volume >= 0) { moby->state = 3; - } else if (vars->f1B4 != 0) { + } else if (snapper_behavior->f1B4 != 0) { moby->state = 2; - vars->timer = scale_game_frames(1); + snapper_behavior->timer = scale_game_frames(1); if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 0); } @@ -316,13 +316,13 @@ void alien_snapper_update(Moby *moby) { if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 0); } - vars->f1A0 = l06_alien_snapper_base_targeting_radius; + snapper_behavior->f1A0 = l06_alien_snapper_base_targeting_radius; } break; case 1: - if (vars->f164 != 2) { + if (snapper_behavior->f164 != 2) { moby->state = 2; - vars->timer = scale_game_frames(1); + snapper_behavior->timer = scale_game_frames(1); if (moby->group != 0xFF) { func_L06_002FAAC8_91A8(moby); } @@ -330,9 +330,9 @@ void alien_snapper_update(Moby *moby) { break; case 2: if (moby->prev_seq == 0) { - if (vars->timer == 0) { - vars->timer = truncate_float_to_s32(scale_time(random_float_between(0.0f, 20.0f))); - } else if (fast_dec_timer(&vars->timer) != 0) { + if (snapper_behavior->timer == 0) { + snapper_behavior->timer = truncate_float_to_s32(scale_time(random_float_between(0.0f, 20.0f))); + } else if (fast_dec_timer(&snapper_behavior->timer) != 0) { if (moby->prev_seq != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } @@ -340,8 +340,8 @@ void alien_snapper_update(Moby *moby) { } else if (moby->anim_flags & 2) { if (vector_distance_xy(&moby->pos, ((char *)&D_0013F3D0)) < l06_alien_snapper_base_targeting_radius) { moby->state = 8; - vars->angle_jitter = random_float_between(vars->jitter_degrees * 0.017453292f, - -(vars->jitter_degrees * 0.017453292f)); + snapper_behavior->angle_jitter = random_float_between(snapper_behavior->jitter_degrees * 0.017453292f, + -(snapper_behavior->jitter_degrees * 0.017453292f)); if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -356,9 +356,9 @@ void alien_snapper_update(Moby *moby) { } } break; - case 3: - if (vars->clip_volume >= 0) { - if (is_point_inside_clip_volume(((char *)&D_0013F3D0), vars->clip_volume) != 0) { + case ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER: + if (snapper_behavior->clip_volume >= 0) { + if (is_point_inside_clip_volume(((char *)&D_0013F3D0), snapper_behavior->clip_volume) != 0) { moby->state = 4; if (moby->prev_seq != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(5)); @@ -374,20 +374,20 @@ void alien_snapper_update(Moby *moby) { break; case 6: moby->state = 5; - qcopy(&vars->home, &l06_cuboids[vars->node].pos); - vars->return_speed = - vector_distance_xy(&moby->pos, &vars->home) / (float)scale_game_frames(60); - vars->f8C = func_L00_0025BC48_91A8( - &moby->pos, &vars->home, 0, vars->return_speed, -vars->f80); - vars->f94 = 5; - vars->fAD = 3; + qcopy(&snapper_behavior->home, &l06_cuboids[snapper_behavior->node].pos); + snapper_behavior->return_speed = + vector_distance_xy(&moby->pos, &snapper_behavior->home) / (float)scale_game_frames(60); + snapper_behavior->f8C = func_L00_0025BC48_91A8( + &moby->pos, &snapper_behavior->home, 0, snapper_behavior->return_speed, -snapper_behavior->f80); + snapper_behavior->f94 = 5; + snapper_behavior->fAD = 3; func_L00_0025D5B0_91A8( moby, - vars->f70, + snapper_behavior->f70, 7, 1, 0, - fast_arc_tan(vars->home.x - moby->pos.x, vars->home.y - moby->pos.y)); + fast_arc_tan(snapper_behavior->home.x - moby->pos.x, snapper_behavior->home.y - moby->pos.y)); if (moby->prev_seq != 7) { blend_moby_animation(moby, 7, 0, 5); } @@ -396,7 +396,7 @@ void alien_snapper_update(Moby *moby) { } break; case 5: - if (func_L00_0025D6F0_91A8(moby, vars->f70) & 1) { + if (func_L00_0025D6F0_91A8(moby, snapper_behavior->f70) & 1) { moby->state = 6; if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, 5); @@ -405,40 +405,40 @@ void alien_snapper_update(Moby *moby) { break; case 6: func_L00_002592B0_91A8(moby, - fast_arc_tan(vars->goal_x - moby->pos.x, vars->goal_y - moby->pos.y), - &vars->turn_speed, + fast_arc_tan(snapper_behavior->goal_x - moby->pos.x, snapper_behavior->goal_y - moby->pos.y), + &snapper_behavior->turn_speed, 0.05f, 0.3f, frame_time * 6.2831855f); - if (vars->f164 != 2) { + if (snapper_behavior->f164 != 2) { moby->state = 7; - vars->timer = truncate_float_to_s32(random_float_between(0.0f, (float)vars->timer_max)); - } else if (vars->f1AC != 0) { + snapper_behavior->timer = truncate_float_to_s32(random_float_between(0.0f, (float)snapper_behavior->timer_max)); + } else if (snapper_behavior->f1AC != 0) { moby->state = 9; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } } break; - case 9: { + case ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET: { int near; - approach_value(&vars->speed, vars->base_speed * frame_time, D_0015ED70 * 6.0f); + approach_value(&snapper_behavior->speed, snapper_behavior->base_speed * frame_time, D_0015ED70 * 6.0f); func_L00_002592B0_91A8( moby, fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y), - &vars->turn_speed, + &snapper_behavior->turn_speed, 0.05f, 0.3f, frame_time * 6.2831855f); - dist = vector_distance_xy(&moby->pos, &target->pos); - if (D_L06_00161EC4 < dist) { - dist = D_L06_00161EC4; + target_goal_radius = vector_distance_xy(&moby->pos, &target->pos); + if (l06_alien_snapper_bite_approach_radius < target_goal_radius) { + target_goal_radius = l06_alien_snapper_bite_approach_radius; } - ang = func_L06_002FAB28_91A8(moby); + target_gap_angle_radians = func_L06_002FAB28_91A8(moby); near = 0; - scratch.m.goal[0] = fast_cos(ang) * dist; - scratch.m.goal[1] = fast_sin(ang) * dist; + scratch.m.goal[0] = fast_cos(target_gap_angle_radians) * target_goal_radius; + scratch.m.goal[1] = fast_sin(target_gap_angle_radians) * target_goal_radius; scratch.m.goal[2] = 0.0f; fast_vec_add(scratch.m.goal, scratch.m.goal, &target->pos); saved_rot = moby->rot.z; @@ -447,21 +447,21 @@ void alien_snapper_update(Moby *moby) { scratch.m.dir[0] = fast_cos(moby->rot.z) * 2.0f; scratch.m.dir[1] = fast_sin(moby->rot.z) * 2.0f; scratch.m.dir[2] = 0.0f; - func_L00_00259B88_91A8(moby, &vars->movement, scratch.m.dir, scratch.m.out, 1.0f); + func_L00_00259B88_91A8(moby, &snapper_behavior->movement, scratch.m.dir, scratch.m.out, 1.0f); moby->rot.z = saved_rot; - func_L00_00262DF0_91A8(0.5f, vars->path, &moby->pos, &moby->pos); - if (FUN_L00_00261b48(vars->path, &moby->pos, &target->pos, scratch.m.path_point) != 0 && - fast_vec_dist(&moby->pos, scratch.m.path_point) < vars->reach_distance) { + func_L00_00262DF0_91A8(0.5f, snapper_behavior->path, &moby->pos, &moby->pos); + if (FUN_L00_00261b48(snapper_behavior->path, &moby->pos, &target->pos, scratch.m.path_point) != 0 && + fast_vec_dist(&moby->pos, scratch.m.path_point) < snapper_behavior->reach_distance) { near = 1; } - if (vars->f1AC == 0) { + if (snapper_behavior->f1AC == 0) { moby->state = 0xC; } else if (near) { moby->state = 0xA; if (moby->prev_seq != 5) { blend_moby_animation(moby, 5, 0, scale_game_frames(10)); } - } else if (vector_distance_xy(&moby->pos, &target->pos) < D_L06_00161EC4) { + } else if (vector_distance_xy(&moby->pos, &target->pos) < l06_alien_snapper_bite_approach_radius) { moby->state = 0xB; if (moby->prev_seq != 4) { blend_moby_animation(moby, 4, 0, scale_game_frames(10)); @@ -477,36 +477,36 @@ void alien_snapper_update(Moby *moby) { } } break; - case 7: - if (fast_dec_timer(&vars->timer) != 0) { + case ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH: + if (fast_dec_timer(&snapper_behavior->timer) != 0) { moby->state = 8; - vars->angle_jitter = random_float_between(vars->jitter_degrees * 0.017453292f, - -(vars->jitter_degrees * 0.017453292f)); + snapper_behavior->angle_jitter = random_float_between(snapper_behavior->jitter_degrees * 0.017453292f, + -(snapper_behavior->jitter_degrees * 0.017453292f)); if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } } break; - case 8: { - if (D_L06_00161EC4 < vector_distance_xy(&moby->pos, &target->pos)) { - approach_value(&vars->speed, vars->base_speed * frame_time, D_0015ED70 * 6.0f); + case ALIEN_SNAPPER_STATE_APPROACH_TARGET: { + if (l06_alien_snapper_bite_approach_radius < vector_distance_xy(&moby->pos, &target->pos)) { + approach_value(&snapper_behavior->speed, snapper_behavior->base_speed * frame_time, D_0015ED70 * 6.0f); } else { - approach_value(&vars->speed, 0.0f, D_0015ED70 * 20.0f); + approach_value(&snapper_behavior->speed, 0.0f, D_0015ED70 * 20.0f); } func_L00_002592B0_91A8( moby, fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y), - &vars->turn_speed, + &snapper_behavior->turn_speed, 0.05f, 0.3f, frame_time * 6.2831855f); - dist = vector_distance_xy(&moby->pos, &target->pos); - if (D_L06_00161EC4 < dist) { - dist = D_L06_00161EC4; + target_goal_radius = vector_distance_xy(&moby->pos, &target->pos); + if (l06_alien_snapper_bite_approach_radius < target_goal_radius) { + target_goal_radius = l06_alien_snapper_bite_approach_radius; } - ang = func_L06_002FAB28_91A8(moby); - scratch.m.goal[0] = fast_cos(ang) * dist; - scratch.m.goal[1] = fast_sin(ang) * dist; + target_gap_angle_radians = func_L06_002FAB28_91A8(moby); + scratch.m.goal[0] = fast_cos(target_gap_angle_radians) * target_goal_radius; + scratch.m.goal[1] = fast_sin(target_gap_angle_radians) * target_goal_radius; scratch.m.goal[2] = 0.0f; fast_vec_add(scratch.m.goal, scratch.m.goal, &target->pos); saved_rot = moby->rot.z; @@ -515,12 +515,12 @@ void alien_snapper_update(Moby *moby) { scratch.m.dir[0] = fast_cos(moby->rot.z) * 2.0f; scratch.m.dir[1] = fast_sin(moby->rot.z) * 2.0f; scratch.m.dir[2] = 0.0f; - func_L00_00259B88_91A8(moby, &vars->movement, scratch.m.dir, scratch.m.out, 1.0f); + func_L00_00259B88_91A8(moby, &snapper_behavior->movement, scratch.m.dir, scratch.m.out, 1.0f); moby->rot.z = saved_rot; - func_L00_00262DF0_91A8(0.5f, vars->path, &moby->pos, &moby->pos); - if (D_L06_00161EC8 < fast_vec_dist(&moby->pos, &vars->home) || vars->f164 == 2) { + func_L00_00262DF0_91A8(0.5f, snapper_behavior->path, &moby->pos, &moby->pos); + if (l06_alien_snapper_max_home_distance < fast_vec_dist(&moby->pos, &snapper_behavior->home) || snapper_behavior->f164 == 2) { moby->state = 0xC; - } else if (vector_distance_xy(&moby->pos, &target->pos) < D_L06_00161EC4) { + } else if (vector_distance_xy(&moby->pos, &target->pos) < l06_alien_snapper_bite_approach_radius) { if (absolute_float(target->pos.z - moby->pos.z) < 1.0f) { char *hero = ((char *)&D_0013F350); @@ -534,11 +534,11 @@ void alien_snapper_update(Moby *moby) { } break; } - case 11: + case ALIEN_SNAPPER_STATE_BITE_TARGET: func_L00_002592B0_91A8( moby, fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y), - &vars->turn_speed, + &snapper_behavior->turn_speed, 0.05f, 0.3f, frame_time * 6.2831855f); @@ -547,7 +547,7 @@ void alien_snapper_update(Moby *moby) { scratch.bite.push[0] = fast_cos(moby->rot.z) * 0.2f; scratch.bite.push[1] = fast_sin(moby->rot.z) * 0.2f; scratch.bite.push[2] = 0.0f; - func_L00_00250800_91A8(moby, 0, buf); + func_L00_00250800_91A8(moby, 0, bite_query_position); scratch.bite.moby = moby; scratch.bite.f14 = 1; scratch.bite.f20 = 1; @@ -555,7 +555,7 @@ void alien_snapper_update(Moby *moby) { scratch.bite.dir[0] = fast_cos(moby->rot.z); scratch.bite.dir[1] = fast_sin(moby->rot.z); scratch.bite.dir[2] = 0.0f; - func_L00_001F2BE8_91A8(0.5f, buf, 0, moby, &scratch.bite); + func_L00_001F2BE8_91A8(0.5f, bite_query_position, 0, moby, &scratch.bite); } else if (moby->anim_flags & 2) { moby->state = 8; if (moby->prev_seq != 1) { @@ -563,12 +563,12 @@ void alien_snapper_update(Moby *moby) { } } break; - case 13: { - approach_value(&vars->speed, vars->base_speed * 3.0f * frame_time, D_0015ED70 * 20.0f); + case ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET: { + approach_value(&snapper_behavior->speed, snapper_behavior->base_speed * 3.0f * frame_time, D_0015ED70 * 20.0f); func_L00_002592B0_91A8( moby, fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y), - &vars->turn_speed, + &snapper_behavior->turn_speed, 0.05f, 0.3f, frame_time * 6.2831855f); @@ -578,16 +578,16 @@ void alien_snapper_update(Moby *moby) { scratch.m.dir[0] = fast_cos(moby->rot.z) * 2.0f; scratch.m.dir[1] = fast_sin(moby->rot.z) * 2.0f; scratch.m.dir[2] = 0.0f; - func_L00_00259B88_91A8(moby, &vars->movement, scratch.m.dir, scratch.m.out, 1.0f); + func_L00_00259B88_91A8(moby, &snapper_behavior->movement, scratch.m.dir, scratch.m.out, 1.0f); moby->rot.z = saved_rot; - func_L00_00262DF0_91A8(0.5f, vars->path, &moby->pos, &moby->pos); - if (fast_dec_timer(&vars->timer) != 0 || - D_L06_00161ED4 < fast_vec_dist(&moby->pos, &target->pos)) { + func_L00_00262DF0_91A8(0.5f, snapper_behavior->path, &moby->pos, &moby->pos); + if (fast_dec_timer(&snapper_behavior->timer) != 0 || + l06_alien_snapper_retreat_distance_limit < fast_vec_dist(&moby->pos, &target->pos)) { moby->state = 0xB; - vars->speed = frame_time * 5.0f; - if (D_L06_00161EDC != 0) { + snapper_behavior->speed = frame_time * 5.0f; + if (l06_alien_snapper_retreat_bite_override_enabled != 0) { if (moby->prev_seq != 4) { - blend_moby_animation(moby, 4, D_L06_00161EE0, scale_game_frames(5)); + blend_moby_animation(moby, 4, l06_alien_snapper_retreat_bite_start_frame, scale_game_frames(5)); } } else { if (moby->prev_seq != 4) { @@ -597,25 +597,25 @@ void alien_snapper_update(Moby *moby) { } break; } - case 12: { - approach_value(&vars->speed, vars->base_speed * frame_time, D_0015ED70 * 6.0f); + case ALIEN_SNAPPER_STATE_RETURN_HOME: { + approach_value(&snapper_behavior->speed, snapper_behavior->base_speed * frame_time, D_0015ED70 * 6.0f); func_L00_002592B0_91A8(moby, - fast_arc_tan(vars->home.x - moby->pos.x, vars->home.y - moby->pos.y), - &vars->turn_speed, + fast_arc_tan(snapper_behavior->home.x - moby->pos.x, snapper_behavior->home.y - moby->pos.y), + &snapper_behavior->turn_speed, 0.05f, 0.3f, frame_time * 6.2831855f); scratch.m.dir[0] = fast_cos(moby->rot.z) * 2.0f; scratch.m.dir[1] = fast_sin(moby->rot.z) * 2.0f; scratch.m.dir[2] = 0.0f; - func_L00_00259B88_91A8(moby, &vars->movement, scratch.m.dir, scratch.m.out, 1.0f); - func_L00_00262DF0_b91A8(vars->path, &moby->pos, &moby->pos, 0.5f); - if (fast_vec_dist(&moby->pos, &vars->home) < 1.0f) { + func_L00_00259B88_91A8(moby, &snapper_behavior->movement, scratch.m.dir, scratch.m.out, 1.0f); + func_L00_00262DF0_b91A8(snapper_behavior->path, &moby->pos, &moby->pos, 0.5f); + if (fast_vec_dist(&moby->pos, &snapper_behavior->home) < 1.0f) { moby->state = 6; if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(20)); } - } else if (vars->f164 != 2) { + } else if (snapper_behavior->f164 != 2) { moby->state = 8; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(20)); @@ -623,13 +623,13 @@ void alien_snapper_update(Moby *moby) { } break; } - case 15: { + case ALIEN_SNAPPER_STATE_FACE_HERO: { char *hero = ((char *)&D_0013F350); approach_angle(&moby->rot.z, fast_arc_tan(*(float *)(hero + 0x80) - moby->pos.x, *(float *)(hero + 0x84) - moby->pos.y), - &vars->turn_speed, + &snapper_behavior->turn_speed, D_0015ED70 * 6.2831855f, D_0015ED70 * 6.2831855f, frame_time * 12.566371f); @@ -641,13 +641,13 @@ void alien_snapper_update(Moby *moby) { } break; } - case 16: { + case ALIEN_SNAPPER_STATE_BITE_HERO: { char *hero = ((char *)&D_0013F350); approach_angle(&moby->rot.z, fast_arc_tan(*(float *)(hero + 0x80) - moby->pos.x, *(float *)(hero + 0x84) - moby->pos.y), - &vars->turn_speed, + &snapper_behavior->turn_speed, D_0015ED70 * 6.2831855f, D_0015ED70 * 6.2831855f, frame_time * 12.566371f); @@ -656,7 +656,7 @@ void alien_snapper_update(Moby *moby) { scratch.bite.push[0] = fast_cos(moby->rot.z) * 0.2f; scratch.bite.push[1] = fast_sin(moby->rot.z) * 0.2f; scratch.bite.push[2] = 0.0f; - func_L00_00250800_91A8(moby, 0, buf); + func_L00_00250800_91A8(moby, 0, bite_query_position); scratch.bite.moby = moby; scratch.bite.f14 = 1; scratch.bite.f20 = 1; @@ -664,8 +664,8 @@ void alien_snapper_update(Moby *moby) { scratch.bite.dir[0] = fast_cos(moby->rot.z); scratch.bite.dir[1] = fast_sin(moby->rot.z); scratch.bite.dir[2] = 0.0f; - func_L00_001F2BE8_91A8(0.5f, buf, 0, moby, &scratch.bite); - collision_line(buf, &moby->pos, 0, moby, &scratch.bite); + func_L00_001F2BE8_91A8(0.5f, bite_query_position, 0, moby, &scratch.bite); + collision_line(bite_query_position, &moby->pos, 0, moby, &scratch.bite); } else if (moby->anim_flags & 2) { moby->state = 0xF; if (moby->prev_seq != 2) { @@ -674,9 +674,9 @@ void alien_snapper_update(Moby *moby) { } break; } - case 14: - if (func_L00_0025D6F0_91A8(moby, vars->f70) & 0x41) { - int *route = D_L06_001B0C30_macro[vars->path]; + case ALIEN_SNAPPER_STATE_HIT_KNOCKBACK: + if (func_L00_0025D6F0_91A8(moby, snapper_behavior->f70) & 0x41) { + int *route = D_L06_001B0C30_macro[snapper_behavior->path]; if (point_in_path_xy(&moby->pos, route + 4, *route) == 0) { mark_moby_for_removal(moby); @@ -687,12 +687,12 @@ void alien_snapper_update(Moby *moby) { if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(20)); } - vars->timer = scale_game_frames(30); + snapper_behavior->timer = scale_game_frames(30); } - func_L00_00262DF0_91A8(0.5f, vars->path, &moby->pos, &moby->pos); + func_L00_00262DF0_91A8(0.5f, snapper_behavior->path, &moby->pos, &moby->pos); break; - case 17: - if (func_L00_0025D6F0_91A8(moby, vars->f70) & 0x40) { + case ALIEN_SNAPPER_STATE_DEATH_MOTION: + if (func_L00_0025D6F0_91A8(moby, snapper_behavior->f70) & 0x40) { qcopy(scratch.m.dir, &moby->pos); func_L00_00260460_91A8(moby, scratch.m.dir, -1, 1.5f, 10.0f); spawn_moby_break_fragments(moby, 0x6A0, 2, 0x69F, 1, 5, 2); From 779cb0cc7aa9c535e77fcaa8ad8a5fa4ac8a8dcd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:27:14 +0000 Subject: [PATCH 0152/1502] decomp: clarify names in puffoid_update D_L11_001622F0 -> l11_puffoid_jump_gravity: The listed extern float binds gp-0x4910. Retail 00314760-00314788 and 00315028-00315050 multiply it by frame_time_sq and subtract from pvars+0x48, the Z component of jump velocity integrated into position. Launch setup at 00314700-00314740 and 00314fa0-00314fd0 negates the same scaled coefficient for jump_speed_4318. Original Ghidra and authoritative C prove its downward jump acceleration role for both home and carrier jumps. ang -> path_point_heading: Retail 00315454-00315480 copies the indexed current path point into pos; 003154c4-003154e0 computes fast_arc_tan(pos.x minus moby.x, pos.y minus moby.y). 00315508-00315518 passes that heading to approach_angle for moby yaw. Original Ghidra case 0x13 and authoritative C establish the current path point as this binding's direction. ang -> target_facing_heading: Retail 00314ac0 loads target from pvars+0x210; 00314ac4-00314adc subtracts moby XY from target XY and calls fast_arc_tan. 00314af8-00314b14 supplies the result to approach_angle for moby yaw at +0x48. Original Ghidra case 10 and authoritative C prove this binding is the heading used to face the target. ang -> home_jump_heading: Retail 00314600-00314630 computes fast_arc_tan(path+0x20.x minus moby+0x10.x, path+0x20.y minus moby+0x10.y); 00314634-00314674 feeds that angle to approach_angle at moby+0x48. Authoritative C initializes home from this same second path point in mode 1, so this binding is the heading toward the home jump destination. --- src/overlays/l11/mobys/puffoid.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l11/mobys/puffoid.c b/src/overlays/l11/mobys/puffoid.c index f8a65b9377..d58087a9f4 100644 --- a/src/overlays/l11/mobys/puffoid.c +++ b/src/overlays/l11/mobys/puffoid.c @@ -81,7 +81,7 @@ extern float D_L11_001622CC __attribute__((sda)); #include "rnc/overlay/l11/mobys/puffoid_data/puffoid_update.h" -extern float D_L11_001622F0 __attribute__((sda)); +extern float l11_puffoid_jump_gravity __asm__("D_L11_001622F0") __attribute__((sda)); extern void update_puffoid_damage_and_path_goal(struct Moby *) __asm__("FUN_L11_00315968"); extern void update_moby_target_heading_and_conditional_movement( char *moby, float *target_position) __asm__("FUN_L11_00315f58"); @@ -200,11 +200,11 @@ void puffoid_update(struct Moby *moby) { break; case PUFFOID_STATE_WAIT_FOR_HOME_JUMP: { char *path = (char *)l11_paths[puffoid_vars->path]; - float ang = fast_arc_tan(*(float *)(path + 0x20) - moby->pos.x, + float home_jump_heading = fast_arc_tan(*(float *)(path + 0x20) - moby->pos.x, *(float *)(path + 0x24) - moby->pos.y); approach_angle(&moby->rot.z, &puffoid_vars->unk250, - ang, + home_jump_heading, frame_time_sq * 8.726646f, frame_time_sq * 8.726646f, frame_time * 12.566371f); @@ -222,14 +222,14 @@ void puffoid_update(struct Moby *moby) { (char *)l11_paths[puffoid_vars->path] + 0x20, 0, puffoid_jump_horizontal_speed_gp * frame_time, - -(D_L11_001622F0 * frame_time_sq)); + -(l11_puffoid_jump_gravity * frame_time_sq)); } break; } case PUFFOID_STATE_JUMP_HOME: case PUFFOID_STATE_JUMP_THEN_WAIT_FOR_HOME_JUMP: fast_vec_add(&moby->pos, &moby->pos, puffoid_vars->vel); - puffoid_vars->vel[2] -= D_L11_001622F0 * frame_time_sq; + puffoid_vars->vel[2] -= l11_puffoid_jump_gravity * frame_time_sq; if (puffoid_vars->vel[2] < 0.0f) { float h; qcopy(pos, &moby->pos); @@ -310,11 +310,11 @@ void puffoid_update(struct Moby *moby) { fast_vec_add(pos, pos, &moby->pos); if (test_path_segment_strict_crossing(puffoid_vars->unk230, &moby->pos, pos)) { float *rz = &moby->rot.z; - float ang = fast_arc_tan(puffoid_vars->target->pos.x - moby->pos.x, + float target_facing_heading = fast_arc_tan(puffoid_vars->target->pos.x - moby->pos.x, puffoid_vars->target->pos.y - moby->pos.y); approach_angle(rz, &puffoid_vars->unk250, - ang, + target_facing_heading, frame_time_sq * 12.566371f, frame_time_sq * 12.566371f, frame_time * 12.566371f); @@ -438,7 +438,7 @@ void puffoid_update(struct Moby *moby) { dest, 0, puffoid_jump_horizontal_speed_gp * frame_time, - -(D_L11_001622F0 * frame_time_sq)); + -(l11_puffoid_jump_gravity * frame_time_sq)); moby->rot.z = fast_arc_tan(puffoid_vars->vel[0], puffoid_vars->vel[1]); } } @@ -449,7 +449,7 @@ void puffoid_update(struct Moby *moby) { (char *)((struct Moby *)(D_L11_0015FFD8_4318 + (puffoid_vars->carrier << 8)))->pvars; fast_vec_add(&moby->pos, &moby->pos, puffoid_vars->vel); fast_vec_add(&moby->pos, &moby->pos, cv + 0x70); - puffoid_vars->vel[2] -= D_L11_001622F0 * frame_time_sq; + puffoid_vars->vel[2] -= l11_puffoid_jump_gravity * frame_time_sq; if (puffoid_vars->vel[2] < 0.0f) { qcopy(pos, &moby->pos); pos[2] += 1.0f; @@ -577,10 +577,10 @@ void puffoid_update(struct Moby *moby) { } { float *rz = &moby->rot.z; - float ang = fast_arc_tan(pos[0] - moby->pos.x, pos[1] - moby->pos.y); + float path_point_heading = fast_arc_tan(pos[0] - moby->pos.x, pos[1] - moby->pos.y); approach_angle(rz, &puffoid_vars->unk250, - ang, + path_point_heading, frame_time_sq * 12.566371f, frame_time_sq * 12.566371f, frame_time * 12.566371f); From 1dce735c7b9ba0332ea9f50620248e5f5d7da0d4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:27:14 +0000 Subject: [PATCH 0153/1502] decomp: clarify names in bomb_update p0 -> spark_primary_color: Source interpolates bomb_spark_primary_color_start/end into p0. Retail 0x002adea0-0x002adeb0 retains that tweened packed color in s3; 0x002adf6c moves s3 to a3, the first color passed to spawn_spark at 0x002adfa4. --- src/overlays/shared/weapons/bomb_glove_bomb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/weapons/bomb_glove_bomb.c b/src/overlays/shared/weapons/bomb_glove_bomb.c index b2e8b434c9..75ab9c1953 100644 --- a/src/overlays/shared/weapons/bomb_glove_bomb.c +++ b/src/overlays/shared/weapons/bomb_glove_bomb.c @@ -1153,7 +1153,7 @@ void bomb_update(BombMoby *bomb_moby) { Vec_2adb30 spark_velocity; Vec_2adb30 v2; Vec_2adb30 random_velocity_offset; - int p0; + int spark_primary_color; int spark_secondary_color; int spark_random_frame_count; int spark_vertical_offset_scale; @@ -1168,7 +1168,7 @@ void bomb_update(BombMoby *bomb_moby) { random_float_between(*(float *)&D_L00_0016140C, *(float *)&D_L00_00161410); v2.f[3] = random_float_between(*(float *)&D_L00_00161414, *(float *)&D_L00_00161418); - p0 = fast_tween_color(*(int *)&bomb_spark_primary_color_start, + spark_primary_color = fast_tween_color(*(int *)&bomb_spark_primary_color_start, *(int *)&bomb_spark_primary_color_end, random_float_between(0.0f, 1.0f)); spark_secondary_color = @@ -1194,7 +1194,7 @@ void bomb_update(BombMoby *bomb_moby) { spawn_spark(&bomb_moby->pos, &spark_velocity, &v2, - p0, + spark_primary_color, spark_secondary_color, spark_random_frame_count, spark_vertical_offset_scale, From 10afbcd723feb67087b362ad6dd0154f1f290807 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:27:14 +0000 Subject: [PATCH 0154/1502] decomp: clarify names in hero_set_state a -> requested_state: In src/overlays/l03/hero/hero_set_state.c (SHA-256 1c7c73a1fd7f8b2a3021d93ad9896c2700ea3f5a3902245852f6daca3367b854), int a is assigned to p->state.current and selects switch(a), including state admission checks. Retail 0x00216668 moves a0 into s1; 0x002167a8 stores s1 at Hero+0x2084, distinct from control_mode at +0x208c; 0x00216838-0x00216858 bounds-checks and dispatches that same s1. Original Ghidra assigns iRam001413d4=param_1 and switches on param_1. This proves the requested hero state rather than a pointer, animation ID or control mode. --- src/overlays/l03/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l03/hero/hero_set_state.c b/src/overlays/l03/hero/hero_set_state.c index 389fff64df..616b8c6e00 100644 --- a/src/overlays/l03/hero/hero_set_state.c +++ b/src/overlays/l03/hero/hero_set_state.c @@ -68,13 +68,13 @@ extern int hero_set_state(int, int) __asm__("FUN_L03_00216648"); extern char level03_hero_trail_jump_velocity_keys[] __asm__("D_L03_0017C020"); extern char level03_hero_water_surface_jump_velocity_keys[] __asm__("D_L03_0017C060"); -int hero_set_state(int a, int b) { +int hero_set_state(int requested_state, int b) { int previous_state_step; char *moby; int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((D_L03_0015F5C4 == 2 || D_L03_0015F5C4 == 6) && b != 2) @@ -82,8 +82,8 @@ int hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -96,7 +96,7 @@ int hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -121,7 +121,7 @@ int hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -960,7 +960,7 @@ int hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 1cabc3d1fce015cdceb6a17294c5a038e2098b65 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:27:26 +0000 Subject: [PATCH 0155/1502] decomp: clarify names in alien_queen_update D_L06_00161EF4 -> l06_alien_queen_movement_speed: Retail 0x002fa158..0x002fa17c multiplies this float by frame_time as the target for speed at pvars+0xE8; 0x002fa19c..0x002fa1c0 negates it for retreat. 0x002fa6c8..0x002fa6e4 also uses it as the normalized return-home displacement magnitude. D_L06_00161F00 -> l06_alien_queen_attack_distance: Retail 0x002fa148..0x002fa154 compares this threshold with queen-to-target XY distance to approach when farther away. At 0x002fa258..0x002fa2b4, distance below the same threshold plus heading alignment enters state 9, followed by state-10 hit queries. D_L06_00161F04 -> l06_alien_queen_retreat_distance: Retail 0x002fa188..0x002fa1c0 compares target XY distance against this float; when closer than it, the queen approaches negative movement speed at pvars+0xE8, moving opposite the normalized target-minus-queen vector. D_L06_00161F08 -> l06_alien_queen_attack_heading_tolerance_degrees: Retail 0x002fa280..0x002fa298 multiplies this float by 0.017453292 (degrees to radians) and compares it against the queen-to-target rotation difference. Passing that and attack distance tests enters windup state 9 at 0x002fa2b4. buf -> hit_query_position: At 0x002fa470 s0 is stack+0x40; calls 0x002fa484..0x002fa578 fill it for indices 0..6, and each following hit query uses it as a0. Checked helper 0x0025e488 scales/transforms the indexed vector and adds moby+0x10 at 0x0025e4ec..0x0025e4f4, proving a world position. data -> alien_queen_update_vars: Retail 0x002f9a60 loads s3 from moby+0x78 (Moby.pvars). All data-relative accesses use this queen-owned block: health +0x20, saved home +0xC0, movement +0xE8 and state timers +0x120/+0x12C. switch_0_case_0 -> ALIEN_QUEEN_STATE_INITIALIZE: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. 0x002f9b30..0x002f9c84 initializes health 30, timers, home position, path midpoint, collision/flags and list states, then writes queen state 1. switch_0_case_1 -> ALIEN_QUEEN_STATE_WAIT_TO_START_INTRO: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. 0x002f9c88..0x002f9d58 waits on pvars+0xB4, target+0xA6 and a ten-frame timer, then enables linked objects, writes state 2, selects animation 8 and calls start_alien_queen_intro at 0x002fb148. switch_0_case_10 -> ALIEN_QUEEN_STATE_ATTACK_HIT_QUERIES: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. Retail 0x002fa3b8..0x002fa594 gates on interpolated animation value between 1 and 8 and issues seven indexed world-position hit queries, with radii 0.5 for indices 0..4 and 1.1 for 5..6. Completion restores the saved state byte. switch_0_case_12 -> ALIEN_QUEEN_STATE_TIMED_ORBIT: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. Retail 0x002fa2d8..0x002fa330 calls established orbit movement, decrements pvars+0x120, and on expiry resets the timer and selects state 11 with animation 6. State 8 enters it after its longer timer expires. switch_0_case_13 -> ALIEN_QUEEN_STATE_RETURN_HOME: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. Retail 0x002fa5f4..0x002fa70c turns toward pvars+0xC0, copied from initial position at 0x002f9b94..0x002f9b98, then moves along the flattened home-minus-position vector. It exits at distance below one or mode change. switch_0_case_14 -> ALIEN_QUEEN_STATE_DEATH: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. Supplied update_alien_queen_hit_response_and_recovery enters state 14 on lethal hit response or death flag. Retail 0x002fa758..0x002fa8f4 handles completion, break fragments, collision disabling, reward flag and transition to state 15. switch_0_case_15 -> ALIEN_QUEEN_STATE_POST_DEATH: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. Retail state 14 writes state 15 after disabling queen collision and interaction. Branch 0x002fa900..0x002fa988 scans at most 48 records for kind 0x12, signals its associated object, and removes the queen when level_game_mode is 2. switch_0_case_2 -> ALIEN_QUEEN_STATE_INTRO: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. 0x002f9d64..0x002f9ea8 integrates vertical motion, handles landing animations, calls update_alien_queen_intro_camera (0x002fb2a8) and on completion sets state 7 and calls finish_alien_queen_intro (0x002fb4b0). switch_0_case_3 -> ALIEN_QUEEN_STATE_FIRST_RECOVERY_CAMERA: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. 0x002f9eb4..0x002f9f2c activates raised frogs after animation 6 and waits for update_alien_queen_first_recovery_camera at 0x002fb668. Supplied hit/recovery source enters state 3 at the higher health recovery threshold. switch_0_case_4 -> ALIEN_QUEEN_STATE_FROG_RECOVERY_ORBIT: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. 0x002f9fbc..0x002fa01c activates listed raised frogs, falls through to orbit movement at 0x002fbc88, and exits to state 8 when check_all_listed_frog_states_fe_fd_or_10 succeeds. State 3 enters this branch after first recovery camera completion. switch_0_case_5 -> ALIEN_QUEEN_STATE_SECOND_RECOVERY_CAMERA: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. Supplied hit/recovery source selects state 5 at the lower health recovery threshold and initializes the recovery camera. Retail 0x002f9f38..0x002f9fb0 clears moby list state 18 and waits on the distinct camera helper 0x002fba28 before state 6. switch_0_case_6 -> ALIEN_QUEEN_STATE_GROUP_RECOVERY_ORBIT: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. Retail 0x002f9fc4 calls established orbit movement 0x002fbc88; 0x002f9ff4..0x002fa01c waits for count_active_moby_group_members(pvars+0xF4,-1) to become zero before entering approach state 8. Entered from second recovery state 5. switch_0_case_7 -> ALIEN_QUEEN_STATE_WAIT_TO_APPROACH_TARGET: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. Retail 0x002fa04c..0x002fa080 waits while pvars+0xB4 equals 2; otherwise writes state 8 and requests animation 3. State 8 then turns and moves relative to target+0x10. switch_0_case_8 -> ALIEN_QUEEN_STATE_APPROACH_TARGET: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. Retail 0x002fa084..0x002fa230 computes target distance and heading, approaches heading and signed speed, normalizes target-minus-position, adds the displacement and resolves path clearance; aligned close targets trigger state 9. switch_0_case_9 -> ALIEN_QUEEN_STATE_ATTACK_WINDUP: Selector is the queen Moby state byte: retail 0x002f9b08 loads moby+0x20 and dispatches the sixteen-way table, not a hero enum domain. Retail 0x002fa274..0x002fa2d4 enters this state only within target distance and heading limits with animation 4. Branch 0x002fa334..0x002fa3b4 damps turning and waits for animation completion before state 10 and animation 5 hit queries. --- src/overlays/l06/mobys/alien_queen.c | 82 ++++++++++++++-------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/overlays/l06/mobys/alien_queen.c b/src/overlays/l06/mobys/alien_queen.c index d620094604..8956b67db9 100644 --- a/src/overlays/l06/mobys/alien_queen.c +++ b/src/overlays/l06/mobys/alien_queen.c @@ -117,11 +117,11 @@ typedef struct { extern char D_L06_001678D0[]; extern int D_L06_0016A010[]; extern short D_L06_00161EF0 __attribute__((sda)); -extern short D_L06_00161EF4 __attribute__((sda)); +extern short l06_alien_queen_movement_speed __asm__("D_L06_00161EF4") __attribute__((sda)); f32 alien_queen_movement_acceleration_gp __asm__("D_L06_00161EFC") = 8.0f; -extern short D_L06_00161F00 __attribute__((sda)); -extern short D_L06_00161F04 __attribute__((sda)); -extern short D_L06_00161F08 __attribute__((sda)); +extern short l06_alien_queen_attack_distance __asm__("D_L06_00161F00") __attribute__((sda)); +extern short l06_alien_queen_retreat_distance __asm__("D_L06_00161F04") __attribute__((sda)); +extern short l06_alien_queen_attack_heading_tolerance_degrees __asm__("D_L06_00161F08") __attribute__((sda)); extern void FUN_L06_002fa9c0_c(void *) __asm__("FUN_L06_002fa9c0"); void set_moby_list_state_18(int idx) __asm__("FUN_L06_002f9948"); void FUN_L06_002fb870(char *arg); @@ -388,7 +388,7 @@ typedef struct AlienQueenVars { /* Moby class 1051 */ void alien_queen_update(unsigned char *moby) { - AlienQueenVars *data = (AlienQueenVars *)MOBY(moby)->pvars; + enum { ALIEN_QUEEN_STATE_INITIALIZE = 0 , ALIEN_QUEEN_STATE_WAIT_TO_START_INTRO = 1 , ALIEN_QUEEN_STATE_INTRO = 2 , ALIEN_QUEEN_STATE_FIRST_RECOVERY_CAMERA = 3 , ALIEN_QUEEN_STATE_FROG_RECOVERY_ORBIT = 4 , ALIEN_QUEEN_STATE_SECOND_RECOVERY_CAMERA = 5 , ALIEN_QUEEN_STATE_GROUP_RECOVERY_ORBIT = 6 , ALIEN_QUEEN_STATE_WAIT_TO_APPROACH_TARGET = 7 , ALIEN_QUEEN_STATE_APPROACH_TARGET = 8 , ALIEN_QUEEN_STATE_ATTACK_WINDUP = 9 , ALIEN_QUEEN_STATE_ATTACK_HIT_QUERIES = 10 , ALIEN_QUEEN_STATE_TIMED_ORBIT = 12 , ALIEN_QUEEN_STATE_RETURN_HOME = 13 , ALIEN_QUEEN_STATE_DEATH = 14 , ALIEN_QUEEN_STATE_POST_DEATH = 15 } ;AlienQueenVars *alien_queen_update_vars = (AlienQueenVars *)MOBY(moby)->pvars; char *target; float step[4]; @@ -409,7 +409,7 @@ void alien_queen_update(unsigned char *moby) { 0x1EF); } switch ((unsigned char)moby[0x20]) { - case 0: { + case ALIEN_QUEEN_STATE_INITIALIZE: { int *path; data->health = 30.0f; data->max_health = 0x1E; @@ -439,7 +439,7 @@ void alien_queen_update(unsigned char *moby) { moby[0x20] = 1; break; } - case 1: + case ALIEN_QUEEN_STATE_WAIT_TO_START_INTRO: if (data->unkB4 == 2) return; if (*(short *)(target + 0xA6) != 0) @@ -463,7 +463,7 @@ void alien_queen_update(unsigned char *moby) { } func_L06_002FC578_q(moby); return; - case 2: { + case ALIEN_QUEEN_STATE_INTRO: { float gravity = frame_time_sq * 30.0f; MOBY(moby)->pos.z = MOBY(moby)->pos.z + data->z_velocity; data->z_velocity = data->z_velocity - gravity; @@ -490,7 +490,7 @@ void alien_queen_update(unsigned char *moby) { } break; } - case 3: + case ALIEN_QUEEN_STATE_FIRST_RECOVERY_CAMERA: if ((unsigned char)moby[0x53] == 6 && MOBY(moby)->anim_time == 0.0f && (moby[0x70] & 2)) { blend_moby_animation(moby, 1, 0, scale_game_frames(0x14)); func_L06_002FC4C0_q(moby); @@ -501,7 +501,7 @@ void alien_queen_update(unsigned char *moby) { return; } break; - case 5: + case ALIEN_QUEEN_STATE_SECOND_RECOVERY_CAMERA: if ((unsigned char)moby[0x53] == 6 && MOBY(moby)->anim_time == 0.0f && (moby[0x70] & 2)) { blend_moby_animation(moby, 1, 0, scale_game_frames(0x14)); clear_moby_list_state_18(data->state18_list); @@ -511,9 +511,9 @@ void alien_queen_update(unsigned char *moby) { FUN_L06_002fbc30(moby); } break; - case 4: + case ALIEN_QUEEN_STATE_FROG_RECOVERY_ORBIT: func_L06_002FC4C0_q(moby); - case 6: + case ALIEN_QUEEN_STATE_GROUP_RECOVERY_ORBIT: func_L06_002FD0B8_q(moby); if (((unsigned char)moby[0x20] == 4 && check_all_listed_frog_states_fe_fd_or_10(data->frog_list) != 0) || @@ -526,7 +526,7 @@ void alien_queen_update(unsigned char *moby) { } } return; - case 7: + case ALIEN_QUEEN_STATE_WAIT_TO_APPROACH_TARGET: if (data->unkB4 == 2) break; moby[0x20] = 8; @@ -534,7 +534,7 @@ void alien_queen_update(unsigned char *moby) { break; blend_moby_animation(moby, 3, 0, scale_game_frames(0x14)); return; - case 8: { + case ALIEN_QUEEN_STATE_APPROACH_TARGET: { float dist = vector_distance_xy(moby + 0x10, target + 0x10); float turn = fast_difference_between_rotations( MOBY(moby)->rot.z, @@ -547,13 +547,13 @@ void alien_queen_update(unsigned char *moby) { frame_time_sq * 6.2831855f, frame_time_sq * 6.2831855f, frame_time * 3.1415927f); - if (turn < 0.7853982f && *(float *)&D_L06_00161F00 < dist) { + if (turn < 0.7853982f && *(float *)&l06_alien_queen_attack_distance < dist) { approach_value(&data->unkE8, - *(float *)&D_L06_00161EF4 * frame_time, + *(float *)&l06_alien_queen_movement_speed * frame_time, alien_queen_movement_acceleration_gp * frame_time_sq); - } else if (dist < *(float *)&D_L06_00161F04) { + } else if (dist < *(float *)&l06_alien_queen_retreat_distance) { approach_value(&data->unkE8, - -(*(float *)&D_L06_00161EF4 * frame_time), + -(*(float *)&l06_alien_queen_movement_speed * frame_time), alien_queen_movement_acceleration_gp * frame_time_sq); } else { approach_value(&data->unkE8, 0.0f, frame_time_sq * 8.0f); @@ -572,7 +572,7 @@ void alien_queen_update(unsigned char *moby) { moby[0x20] = 0xC; break; } - if (dist < *(float *)&D_L06_00161F00 && turn < *(float *)&D_L06_00161F08 * 0.017453292f) { + if (dist < *(float *)&l06_alien_queen_attack_distance && turn < *(float *)&l06_alien_queen_attack_heading_tolerance_degrees * 0.017453292f) { moby[0x20] = 9; moby[0xBC] = 7; if ((unsigned char)moby[0x53] != 4) { @@ -582,7 +582,7 @@ void alien_queen_update(unsigned char *moby) { } break; } - case 12: + case ALIEN_QUEEN_STATE_TIMED_ORBIT: func_L06_002FD0B8_q(moby); if (fast_dec_timer(&data->timer_120) != 0) { data->timer_120 = scale_game_frames(0x4B0); @@ -593,7 +593,7 @@ void alien_queen_update(unsigned char *moby) { } } return; - case 9: + case ALIEN_QUEEN_STATE_ATTACK_WINDUP: fast_dec_timer(&data->timer_120); approach_angle((float *)&MOBY(moby)->rot.z, MOBY(moby)->rot.z, @@ -609,9 +609,9 @@ void alien_queen_update(unsigned char *moby) { } } break; - case 10: { + case ALIEN_QUEEN_STATE_ATTACK_HIT_QUERIES: { QueenProbe probe; - float buf[4]; + float hit_query_position[4]; fast_dec_timer(&data->timer_120); if (1.0f < compute_interpolated_record_value(moby) && compute_interpolated_record_value(moby) < 8.0f) { @@ -625,20 +625,20 @@ void alien_queen_update(unsigned char *moby) { probe.dir[0] = fast_cos(MOBY(moby)->rot.z); probe.dir[1] = fast_sin(MOBY(moby)->rot.z); probe.dir[2] = 0.0f; - func_L00_00250800_q(moby, 0, buf); - func_L00_001F2BE8_q(buf, 0.5f, 0, moby, &probe); - func_L00_00250800_q(moby, 1, buf); - func_L00_001F2BE8_q(buf, 0.5f, 0, moby, &probe); - func_L00_00250800_q(moby, 2, buf); - func_L00_001F2BE8_q(buf, 0.5f, 0, moby, &probe); - func_L00_00250800_q(moby, 3, buf); - func_L00_001F2BE8_q(buf, 0.5f, 0, moby, &probe); - func_L00_00250800_q(moby, 4, buf); - func_L00_001F2BE8_q(buf, 0.5f, 0, moby, &probe); - func_L00_00250800_q(moby, 5, buf); - func_L00_001F2BE8_q(buf, 1.1f, 0, moby, &probe); - func_L00_00250800_q(moby, 6, buf); - func_L00_001F2BE8_q(buf, 1.1f, 0, moby, &probe); + func_L00_00250800_q(moby, 0, hit_query_position); + func_L00_001F2BE8_q(hit_query_position, 0.5f, 0, moby, &probe); + func_L00_00250800_q(moby, 1, hit_query_position); + func_L00_001F2BE8_q(hit_query_position, 0.5f, 0, moby, &probe); + func_L00_00250800_q(moby, 2, hit_query_position); + func_L00_001F2BE8_q(hit_query_position, 0.5f, 0, moby, &probe); + func_L00_00250800_q(moby, 3, hit_query_position); + func_L00_001F2BE8_q(hit_query_position, 0.5f, 0, moby, &probe); + func_L00_00250800_q(moby, 4, hit_query_position); + func_L00_001F2BE8_q(hit_query_position, 0.5f, 0, moby, &probe); + func_L00_00250800_q(moby, 5, hit_query_position); + func_L00_001F2BE8_q(hit_query_position, 1.1f, 0, moby, &probe); + func_L00_00250800_q(moby, 6, hit_query_position); + func_L00_001F2BE8_q(hit_query_position, 1.1f, 0, moby, &probe); return; } if (moby[0x70] & 2) { @@ -657,7 +657,7 @@ void alien_queen_update(unsigned char *moby) { } } return; - case 13: { + case ALIEN_QUEEN_STATE_RETURN_HOME: { char *pos = (char *)moby + 0x10; char *home = data->unkC0; float dist = vector_distance_xy(pos, home); @@ -674,7 +674,7 @@ void alien_queen_update(unsigned char *moby) { if (turn < 0.7853982f) { fast_vec_sub(step, home, pos); step[2] = 0.0f; - fast_vec_normalize(step, step, *(float *)&D_L06_00161EF4 * frame_time); + fast_vec_normalize(step, step, *(float *)&l06_alien_queen_movement_speed * frame_time); fast_vec_add(pos, pos, step); func_L00_00262DF0_q(data->path, pos, 1.0f, pos); } @@ -691,7 +691,7 @@ void alien_queen_update(unsigned char *moby) { } break; } - case 14: { + case ALIEN_QUEEN_STATE_DEATH: { unsigned char *flag; menu_item_enabled_19_lui[4] = 1; data->unk110 = 0; @@ -734,7 +734,7 @@ void alien_queen_update(unsigned char *moby) { queue_dialogue_message(0x53D6, -1); return; } - case 15: { + case ALIEN_QUEEN_STATE_POST_DEATH: { int i; char *other = 0; for (i = 0; i < 0x30; i++) { From 44705fe4e84a03e30e7931dba9ffa5a92818d4e5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:27:26 +0000 Subject: [PATCH 0156/1502] decomp: clarify names in hero_set_state a -> requested_state: Authoritative hero_set_state(int a,int b) assigns a to p->state.current and switches on a. Original retail Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Retail 0x0022ff78 moves a0 into s1; 0x002300b8 stores s1 at hero+0x2084 (state.current); 0x00230148-0x00230168 bounds and dispatches that same request. Guards at 0x0022ffb4-0x0022ffc8 and 0x00230018-0x00230078 may refuse it; 0x002316fc tests requested jump variants. Supplied callers pass HERO_STATE_HURT or HERO_STATE_SLIP as the first argument, corroborating its request-state domain. --- src/overlays/l14/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l14/hero/hero_set_state.c b/src/overlays/l14/hero/hero_set_state.c index 684d2aca61..3156780a77 100644 --- a/src/overlays/l14/hero/hero_set_state.c +++ b/src/overlays/l14/hero/hero_set_state.c @@ -64,14 +64,14 @@ extern void clear_moby_transform_history(void *o) __asm__("FUN_L00_00262840"); extern int hero_set_state(int, int) __asm__("FUN_L14_0022ff58"); extern char level14_transform_trail_jump_velocity_keys[] __asm__("D_L14_0017C620"); -int hero_set_state(int a, int b) { +int hero_set_state(int requested_state, int b) { int saved_state_step; char *moby; int old20A7; float grind_direction_or_jump_reference_position[4]; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((D_L14_0015F5C4 == 2 || D_L14_0015F5C4 == 6) && b != 2) @@ -79,8 +79,8 @@ int hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -93,7 +93,7 @@ int hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -118,7 +118,7 @@ int hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -775,7 +775,7 @@ int hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From c3b2054fa55197ab044ba5157507e09e57f60f54 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:27:27 +0000 Subject: [PATCH 0157/1502] decomp: clarify names in hero_set_state a -> requested_state: Authoritative hero_set_state(int a, int b) assigns a to p->state.current and dispatches switch(a). Original retail Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Retail 0x002356c0 preserves a0 in s1, 0x00235804 stores s1 to hero+0x2084 (state.current), and 0x00235894-0x002358b4 indexes the requested-state jump table with s1. This is the requested hero state, distinct from control_mode at +0x208c. --- src/overlays/l06/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l06/hero/hero_set_state.c b/src/overlays/l06/hero/hero_set_state.c index e066e67e77..eaf39504ff 100644 --- a/src/overlays/l06/hero/hero_set_state.c +++ b/src/overlays/l06/hero/hero_set_state.c @@ -69,7 +69,7 @@ extern void clear_moby_transform_history(char *o) __asm__("FUN_L00_00262840"); extern int hero_set_state(int, int) __asm__("FUN_L06_002356a0"); extern char level06_hero_transform_trail_jump_velocity_keys[] __asm__("D_L06_0017C6A0"); -int hero_set_state(int a, int b) { +int hero_set_state(int requested_state, int b) { int saved_state_step; char *moby; int old20A7; @@ -79,7 +79,7 @@ int hero_set_state(int a, int b) { } d; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((D_L06_0015F5C4 == 2 || D_L06_0015F5C4 == 6) && b != 2) @@ -87,8 +87,8 @@ int hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -101,7 +101,7 @@ int hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -126,7 +126,7 @@ int hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -748,7 +748,7 @@ int hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From ca29223f4daad7990710975bc506323b4ff20b54 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:27:27 +0000 Subject: [PATCH 0158/1502] decomp: clarify names in snagglebeast_update d1 -> hero_to_sample_distance: Retail 00316f54..00316f78 samples the instance+0x18C path into start at sp+0xB0. 00316f7c..00316f90 calls vector_distance_xy with hero position 0013f3d0 and that sampled point and saves its return in f20. 00316f9c..00316fa8 repeats sampling while this distance is below 8.0f; the separate moby distance is tested against 12.0f. d1 -> hero_to_first_paired_path_point_distance: Retail 0031683c..00316868 selects the path from instance+0x1A0 and calls vector_distance_xy with hero position 0013f3d0 and path+0x30, saving the return in f20. 0031687c..0031688c compares the hero distance to path+0x40 against it, then selects the farther paired point. This scoped d1 is the distance to the first of these paired path points. d1 -> hero_to_linked_cuboid_distance: Retail 003162d0..003162ec loads linked_moby_vars from linked_mobys[k]'s +0x78 and its cuboid index at +0x28. At 003162f0..00316314 vector_distance_xy receives hero position 0013f3d0 and l07_cuboids[index]+0x30; its return is saved in f20 and compared at 00316334 with the paired linked cuboid distance, matching this scoped d1. --- src/overlays/l07/mobys/snagglebeast.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l07/mobys/snagglebeast.c b/src/overlays/l07/mobys/snagglebeast.c index 85a0beedf7..83d1ff18bf 100644 --- a/src/overlays/l07/mobys/snagglebeast.c +++ b/src/overlays/l07/mobys/snagglebeast.c @@ -1761,14 +1761,14 @@ void snagglebeast_update(unsigned char *moby) { 0x78); if (*(int *)(linked_moby_vars + 0x28) != -1 && *(int *)(paired_linked_moby_vars + 0x28) != -1) { - float d1 = vector_distance_xy( + float hero_to_linked_cuboid_distance = vector_distance_xy( ((char *)&hero) + 0x80, (char *)l07_cuboids + (*(int *)(linked_moby_vars + 0x28) << 7) + 0x30); int sel; if (vector_distance_xy(((char *)&hero) + 0x80, (char *)l07_cuboids + (*(int *)(paired_linked_moby_vars + 0x28) << 7) + - 0x30) < d1) { + 0x30) < hero_to_linked_cuboid_distance) { sel = *(int *)(paired_linked_moby_vars + 0x28); k = k2; } else { @@ -1880,12 +1880,12 @@ void snagglebeast_update(unsigned char *moby) { snagglebeast_instance_state->navigation_mask &= 0xFD; break; case SNAGGLEBEAST_PATH_SELECT_FARTHER_PAIRED_POINT: { - float d1 = vector_distance_xy( + float hero_to_first_paired_path_point_distance = vector_distance_xy( ((char *)&hero) + 0x80, D_L07_001B0530[snagglebeast_instance_state->path_1A0] + 0x30); if (vector_distance_xy(((char *)&hero) + 0x80, D_L07_001B0530[snagglebeast_instance_state->path_1A0] + - 0x40) < d1) { + 0x40) < hero_to_first_paired_path_point_distance) { qcopy(snagglebeast_instance_state->unk120, D_L07_001B0530[snagglebeast_instance_state->path_1A0] + 0x30); } else { @@ -2057,7 +2057,7 @@ void snagglebeast_update(unsigned char *moby) { char *path = D_L07_001B0530[snagglebeast_instance_state->measured_path]; int pidx = 0; float pfrac = 0.0f; - float d1; + float hero_to_sample_distance; float moby_to_sample_distance; pidx = select_point_index_by_distance(((char *)&hero) + 0x80, path, 0.0f); @@ -2069,9 +2069,9 @@ void snagglebeast_update(unsigned char *moby) { &pfrac, snagglebeast_instance_state->unk1AC, 1); - d1 = vector_distance_xy(((char *)&hero) + 0x80, &start); + hero_to_sample_distance = vector_distance_xy(((char *)&hero) + 0x80, &start); moby_to_sample_distance = vector_distance_xy(moby + 0x10, &start); - } while (d1 < 8.0f || moby_to_sample_distance < 12.0f); + } while (hero_to_sample_distance < 8.0f || moby_to_sample_distance < 12.0f); add_random_xy_offset((float *)&start, 0.5f); fast_vec_sub(&direction, &start, ((char *)&hero) + 0x80); zv = start.f[2]; From f02fbb5359b26e47dfdfb9ca1c0722da5cc82ba2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:30:52 +0000 Subject: [PATCH 0159/1502] decomp: clarify names in l01_hero_set_state a -> requested_state: Authoritative C l01_hero_set_state(int a,int b) assigns p->state.current=a and dispatches switch(a); the vehicle-entry caller passes initial_state as argument one. Retail 0x0023cfb8 moves a0 to s1, 0x0023d0f0 preserves the former current state at hero+0x2090, and 0x0023d0f8 stores s1 to current at +0x2084. 0x0023d188-0x0023d1a8 bounds and dispatches s1 through the state jump table. Original Ghidra likewise assigns iRam001413d4=param_1 and switches on param_1. Entry refusal gates show this is the requested state, which need not be accepted. --- src/overlays/l01/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l01/hero/hero_set_state.c b/src/overlays/l01/hero/hero_set_state.c index f21ab013e6..761dffdf6e 100644 --- a/src/overlays/l01/hero/hero_set_state.c +++ b/src/overlays/l01/hero/hero_set_state.c @@ -68,13 +68,13 @@ extern int l01_hero_set_state(int, int) __asm__("FUN_L01_0023cf98"); extern char level_01_transform_trail_jump_velocity_keys[] __asm__("D_L01_0017C3A0"); extern char level_01_water_surface_jump_velocity_keys[] __asm__("D_L01_0017C3E0"); -int l01_hero_set_state(int a, int b) { +int l01_hero_set_state(int requested_state, int b) { int saved_state_step; char *moby; int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((cutscene_mode == 2 || cutscene_mode == 6) && b != 2) @@ -82,8 +82,8 @@ int l01_hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -96,7 +96,7 @@ int l01_hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -121,7 +121,7 @@ int l01_hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -812,7 +812,7 @@ int l01_hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 4c4fdff2936d5157e8a4bc77dd1d110b80776613 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:31:08 +0000 Subject: [PATCH 0160/1502] decomp: clarify names in darter_update D_L10_00161DFC -> l10_darter_attack_distance: Retail 0x002e0b28 loads gp-0x4e04 and compares target XY distance before state 8; 0x002e10b0 compares it to 3D distance before state 10, and 0x002e1234 compares 3D distance before state 11. Source binds these reads to this float, proving a shared darter attack-distance threshold. D_L10_00161E04 -> l10_darter_min_wander_height_offset: Retail 0x002e0680 and 0x002e0860 load gp-0x4dfc as random_float_between's lower bound. Its return becomes stack Z at 0x002e0698/0x002e0878 and is added to home to form the wandering goal at 0x002e06a0/0x002e0880. D_L10_00161E08 -> l10_darter_max_wander_height_offset: Retail 0x002e0684 and 0x002e0864 load gp-0x4df8 as the upper random bound for the Z offset subsequently added to home at 0x002e06a0 and 0x002e0880, proving the maximum wandering height offset. D_L10_00161E0C -> l10_darter_bob_amplitude: Retail 0x002e0268-0x002e0280 multiplies cos(private+0x19c) by gp-0x4df4 and subtracts it from position Z; 0x002e1768-0x002e1780 adds the same product after phase advancement. This float scales vertical bob displacement. D_L10_00161E10 -> l10_darter_bob_period_seconds: At retail 0x002e1718-0x002e1760, gp-0x4df0 is multiplied by 60, passed through scale_time and truncation, and divides 360 degrees before radians conversion and addition to bob_angle. It therefore specifies the bob cycle period in seconds. D_L10_00161E14 -> l10_darter_max_height_offset: Retail 0x002e0400-0x002e0418 supplies zero and gp-0x4dec to random_float_between and stores the return at private+0x1a0. At 0x002e101c-0x002e1034 this height_offset is subtracted from cuboid Z minus moby Z, proving its maximum random height offset role. D_L10_00161E18 -> l10_darter_height_change_interval_seconds: Retail 0x002e040c-0x002e0444 multiplies gp-0x4de8 by 60, scales time, multiplies by a random 0.75-1.25 factor, truncates and stores private+0x1a4. Case 9 decrements that timer at 0x002e0fac and regenerates the height offset and timer upon expiry. lim -> ground_height: In case 7, retail 0x002e09dc calls the source-bound probe_ground_height with moby position and 0.5f; 0x002e09e4 retains f0 in f3. At 0x002e0a40-0x002e0a50 this return clamps the destination Z upward before velocity subtraction. scratch -> vector_and_collision_scratch: Retail stack sp+0 holds random goal offsets at 0x002e0678-0x002e06a4, a copied target position at 0x002e09ec-0x002e0a60, and joint-position output at 0x002e0cf0. The same array's sp+0x20 region holds the collision record at 0x002e0ca0-0x002e0d30; case 11 uses sp+0x10 for that record. Thus the array is shared vector and collision scratch storage. switch_0_case_0 -> DARTER_STATE_INITIALIZE: Retail 0x002e02ac-0x002e0338 initializes private scalars, copies moby position into home and goal, randomizes bob_angle and dispatches private+0x174 spawn_kind. Selector is darter moby+0x20 at 0x002e0284, not hero state. switch_0_case_10 -> DARTER_STATE_CUBOID_APPROACH_TARGET: Retail 0x002e10f4-0x002e1230 turns toward target, moves horizontally at frame_time*4 and clamps Z movement toward indexed cuboid Z. Reaching attack distance and cuboid height within 1 selects state 11; lost targeting returns to cuboid patrol state 9. switch_0_case_11 -> DARTER_STATE_CUBOID_CHARGE_ATTACK: Retail 0x002e12d8-0x002e1418 turns rapidly toward target and moves at frame_time*6 while maintaining cuboid Z. 0x002e1424-0x002e1478 builds an attack collision record and sphere query; proximity or animation end transitions to cuboid return-home state 12. switch_0_case_12 -> DARTER_STATE_CUBOID_RETURN_HOME: Retail 0x002e1514-0x002e161c steers toward home, moves at frame_time*4 and adjusts Z toward cuboid Z. At XY distance below 2, 0x002e1630-0x002e1664 selects patrol state 9 and sets command cooldown to scale_game_frames(120). switch_0_case_13 -> DARTER_STATE_DYING: Retail 0x002e16b4-0x002e16fc advances knockback motion then records removal, spawns an explosion and removes the moby. Supplied hit-reaction source sets state 13 on lethal damage, initializes knockback and selects animation 4. Bob updates explicitly exclude this state. switch_0_case_2 -> DARTER_STATE_RISE_TO_HOME_HEIGHT: Retail 0x002e0460-0x002e04bc advances moby Z toward home Z+2 with private velocity Z; the zero return branches to store state 3 at 0x002e0ef4. This branch implements rising to the home flight height. switch_0_case_3 -> DARTER_STATE_WANDER: Retail 0x002e04c8-0x002e06fc turns toward private goal, accelerates movement toward it, picks random offsets around home on collision, and enters timed waiting state 4 when within 0.1. This is home-centered wandering. switch_0_case_4 -> DARTER_STATE_WAIT_BETWEEN_WANDER_GOALS: Retail 0x002e0810 decrements private+0x198 wait timer; expiry generates a random goal offset around home at 0x002e0820-0x002e0884 and returns to state 3. Target availability can interrupt this wait. switch_0_case_5 -> DARTER_STATE_RETURN_HOME: Retail 0x002e0dc0-0x002e0e18 aims at home XY, 0x002e0e48-0x002e0ebc clamps vertical motion toward home Z+2, and 0x002e0ecc-0x002e0ef8 resumes wandering within XY distance 2. States 7 and 8 transition here after the attack. switch_0_case_6 -> DARTER_STATE_ATTACK_WINDUP: Retail 0x002e0890-0x002e08e8 turns toward target while animation 1 (selected on entry at 0x002e0768-0x002e077c) completes; animation flag 2 triggers state 7 and random signed side_angle at 0x002e08ec-0x002e0960. This is the windup before the diving approach. switch_0_case_7 -> DARTER_STATE_DIVE_TOWARD_TARGET: Retail 0x002e0964-0x002e0ad8 steers toward target with side_angle, computes a downward-biased target Z clamped above ground and moves at frame_time*10. At 0x002e0aec it pitches along velocity, then close range triggers attack state 8 or return-home state 5. switch_0_case_8 -> DARTER_STATE_DIVE_ATTACK: Retail 0x002e0bd0-0x002e0c78 faces the target and pitches toward private+0xe0; at animation threshold 20 it builds collision data and performs sphere and line hit queries (0x002e0c84-0x002e0d30). Animation completion returns to home state 5. Entry from dive state 7 clears velocity. switch_0_case_9 -> DARTER_STATE_CUBOID_PATROL: Retail 0x002e0efc-0x002e1090 flies while turning toward home and maintains cuboid Z minus a randomized timed height_offset. Spawn kind 2 enters this state at 0x002e03c8; a valid distant target triggers cuboid approach state 10. switch_1_case_0 -> DARTER_SPAWN_HOME_WANDER: The nested selector is private+0x174 at retail 0x002e032c, source spawn_kind. Its zero branch 0x002e0368-0x002e0388 enters wandering state 3 and raises position Z by 2 above captured home, selecting flight animation 3. switch_1_case_1 -> DARTER_SPAWN_REMOVE: The private+0x174 spawn_kind comparison at retail 0x002e0334 sends value 1 directly to 0x002e16f8, which calls mark_moby_for_removal then returns. The source nested switch confirms this removal-only spawn behavior. switch_1_case_2 -> DARTER_SPAWN_CUBOID_PATROL: The private+0x174 comparison at retail 0x002e0358 dispatches value 2 to 0x002e0394: it sets state 9 at 0x002e03c8, loads indexed cuboid Z into position at 0x002e03e8-0x002e03fc and initializes the randomized height offset and timer. vars -> darter_vars: Retail 0x002e01e4 loads s3 from moby+0x78 (pvars); 0x002e01f4 reads its target at +0x100. Subsequent +0x120 velocity, +0x130 home, +0x140 goal and +0x19c bob phase accesses prove this is the darter's per-instance private variables. --- src/overlays/l10/mobys/darter.c | 378 +++++++++++++++++--------------- 1 file changed, 199 insertions(+), 179 deletions(-) diff --git a/src/overlays/l10/mobys/darter.c b/src/overlays/l10/mobys/darter.c index c9d0d12f91..4d1b724b11 100644 --- a/src/overlays/l10/mobys/darter.c +++ b/src/overlays/l10/mobys/darter.c @@ -98,13 +98,13 @@ typedef struct Vars_2e01a8 { char a270[4]; } Vars_2e01a8; -extern float D_L10_00161DFC __attribute__((sda)); -extern float D_L10_00161E04 __attribute__((sda)); -extern float D_L10_00161E08 __attribute__((sda)); -extern float D_L10_00161E0C __attribute__((sda)); -extern float D_L10_00161E10 __attribute__((sda)); -extern float D_L10_00161E14 __attribute__((sda)); -extern float D_L10_00161E18 __attribute__((sda)); +extern float l10_darter_attack_distance __asm__("D_L10_00161DFC") __attribute__((sda)); +extern float l10_darter_min_wander_height_offset __asm__("D_L10_00161E04") __attribute__((sda)); +extern float l10_darter_max_wander_height_offset __asm__("D_L10_00161E08") __attribute__((sda)); +extern float l10_darter_bob_amplitude __asm__("D_L10_00161E0C") __attribute__((sda)); +extern float l10_darter_bob_period_seconds __asm__("D_L10_00161E10") __attribute__((sda)); +extern float l10_darter_max_height_offset __asm__("D_L10_00161E14") __attribute__((sda)); +extern float l10_darter_height_change_interval_seconds __asm__("D_L10_00161E18") __attribute__((sda)); extern float D_L10_00161E1C __attribute__((sda)); extern float D_L10_00161E20 __attribute__((sda)); extern int coll_sphere_mobys(float, void *, int, void *, void *) __asm__("FUN_L00_001f2868"); @@ -124,54 +124,74 @@ void darter_update(Moby *moby) __asm__("FUN_L10_002e01a8"); /* Moby class 1199 */ void darter_update(Moby *moby) { - float scratch[20]; - Vars_2e01a8 *vars = (Vars_2e01a8 *)moby->pvars; + enum { + DARTER_STATE_INITIALIZE = 0, + DARTER_STATE_RISE_TO_HOME_HEIGHT = 2, + DARTER_STATE_WANDER = 3, + DARTER_STATE_WAIT_BETWEEN_WANDER_GOALS = 4, + DARTER_STATE_RETURN_HOME = 5, + DARTER_STATE_ATTACK_WINDUP = 6, + DARTER_STATE_DIVE_TOWARD_TARGET = 7, + DARTER_STATE_DIVE_ATTACK = 8, + DARTER_STATE_CUBOID_PATROL = 9, + DARTER_STATE_CUBOID_APPROACH_TARGET = 10, + DARTER_STATE_CUBOID_CHARGE_ATTACK = 11, + DARTER_STATE_CUBOID_RETURN_HOME = 12, + DARTER_STATE_DYING = 13 + }; + enum { + DARTER_SPAWN_HOME_WANDER = 0, + DARTER_SPAWN_REMOVE = 1, + DARTER_SPAWN_CUBOID_PATROL = 2 + }; + float vector_and_collision_scratch[20]; + Vars_2e01a8 *darter_vars = (Vars_2e01a8 *)moby->pvars; Moby *target; update_darter_hit_reactions_and_targeting(moby); - target = vars->target; - func_L00_00264B40_2E0630(2.5f, moby, 1, vars->a270); + target = darter_vars->target; + func_L00_00264B40_2E0630(2.5f, moby, 1, darter_vars->a270); if (moby->visible != 0 && fast_vec_dist(&moby->pos, &D_L10_00167240) < 29.0f) { func_L00_0025B178_2E0630(moby); moby->shadow_range = 0x17; } moby->anim_speed = 1.0f; if (moby->state != 0 && moby->state != 13) { - moby->pos.z = moby->pos.z - D_L10_00161E0C * fast_cos(vars->bob_angle); + moby->pos.z = moby->pos.z - l10_darter_bob_amplitude * fast_cos(darter_vars->bob_angle); } switch (moby->state) { - case 0: - vars->f30 = 0.25f; - vars->f20 = 1.0f; - vars->h24 = 1; - vars->b28 = 0; - vars->b29 = 1; + case DARTER_STATE_INITIALIZE: + darter_vars->f30 = 0.25f; + darter_vars->f20 = 1.0f; + darter_vars->h24 = 1; + darter_vars->b28 = 0; + darter_vars->b29 = 1; moby->flags |= 0x1000; - qcopy(&vars->home, &moby->pos); - qcopy(&vars->goal, &vars->home); - vars->bob_angle = random_angle_radians(); - vars->turn_speed = 0.0f; - vars->b58 = truncate_float_to_s32(D_L10_00161E1C); - vars->b5A = truncate_float_to_s32(D_L10_00161E20 * 8.0f); - switch (vars->spawn_kind) { - case 0: + qcopy(&darter_vars->home, &moby->pos); + qcopy(&darter_vars->goal, &darter_vars->home); + darter_vars->bob_angle = random_angle_radians(); + darter_vars->turn_speed = 0.0f; + darter_vars->b58 = truncate_float_to_s32(D_L10_00161E1C); + darter_vars->b5A = truncate_float_to_s32(D_L10_00161E20 * 8.0f); + switch (darter_vars->spawn_kind) { + case DARTER_SPAWN_HOME_WANDER: moby->state = 3; moby->pos.z = moby->pos.z + 2.0f; if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); break; - case 1: + case DARTER_SPAWN_REMOVE: mark_moby_for_removal(moby); return; - case 2: - scratch[0] = fast_cos(random_angle_radians()) * 10.0f; - scratch[1] = fast_sin(random_angle_radians()) * 10.0f; + case DARTER_SPAWN_CUBOID_PATROL: + vector_and_collision_scratch[0] = fast_cos(random_angle_radians()) * 10.0f; + vector_and_collision_scratch[1] = fast_sin(random_angle_radians()) * 10.0f; moby->state = 9; - scratch[2] = 0.0f; - moby->pos.z = l10_cuboids[vars->f194].pos.z; - add_vectors(&scratch[4], &moby->pos, scratch); - vars->height_offset = random_float_between(0.0f, D_L10_00161E14); - vars->height_timer = truncate_float_to_s32(scale_time(D_L10_00161E18 * 60.0f) * + vector_and_collision_scratch[2] = 0.0f; + moby->pos.z = l10_cuboids[darter_vars->f194].pos.z; + add_vectors(&vector_and_collision_scratch[4], &moby->pos, vector_and_collision_scratch); + darter_vars->height_offset = random_float_between(0.0f, l10_darter_max_height_offset); + darter_vars->height_timer = truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * random_float_between(0.75f, 1.25f)); if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); @@ -180,35 +200,35 @@ void darter_update(Moby *moby) { break; case 1: break; - case 2: + case DARTER_STATE_RISE_TO_HOME_HEIGHT: moby->anim_speed = 4.0f; if (advance_accelerated_scalar(&moby->pos.z, - vars->home.z + 2.0f, - &vars->velocity.z, + darter_vars->home.z + 2.0f, + &darter_vars->velocity.z, D_0015ED70 * 18.0f, D_0015ED70 * 18.0f, frame_time * 6.0f) == 0.0f) { moby->state = 3; } break; - case 3: { + case DARTER_STATE_WANDER: { float dist; float travelled; float speed; float zero; moby->anim_speed = 4.0f; - speed = fast_vec_length(&vars->velocity); - dist = fast_vec_dist(&vars->goal, &moby->pos); + speed = fast_vec_length(&darter_vars->velocity); + dist = fast_vec_dist(&darter_vars->goal, &moby->pos); travelled = 0.0f; func_L00_0025CE58_2E0630( &moby->rot.z, - fast_arc_tan(vars->goal.x - moby->pos.x, vars->goal.y - moby->pos.y), - &vars->turn_speed, + fast_arc_tan(darter_vars->goal.x - moby->pos.x, darter_vars->goal.y - moby->pos.y), + &darter_vars->turn_speed, D_0015ED70 * 25.132742f, D_0015ED70 * 25.132742f, frame_time * 50.265484f); if (fast_difference_between_rotations( - fast_arc_tan(vars->goal.x - moby->pos.x, vars->goal.y - moby->pos.y), moby->rot.z) < + fast_arc_tan(darter_vars->goal.x - moby->pos.x, darter_vars->goal.y - moby->pos.y), moby->rot.z) < 0.78539819f) { advance_accelerated_scalar(&travelled, dist, @@ -216,26 +236,26 @@ void darter_update(Moby *moby) { D_0015ED70 * 20.0f, D_0015ED70 * 20.0f, frame_time * 20.0f); - fast_vec_sub(&vars->velocity, &vars->goal, &moby->pos); - func_L00_002607A8_2E0630(&vars->velocity, speed); + fast_vec_sub(&darter_vars->velocity, &darter_vars->goal, &moby->pos); + func_L00_002607A8_2E0630(&darter_vars->velocity, speed); } else { - clear_u64_value(&vars->velocity); + clear_u64_value(&darter_vars->velocity); } zero = 0.0f; - if (func_L00_00259B08_2E0630(moby, &vars->velocity, 0.5f, 0x200, zero, 0) == 1) { + if (func_L00_00259B08_2E0630(moby, &darter_vars->velocity, 0.5f, 0x200, zero, 0) == 1) { float radius = random_float_between(4.0f, 6.0f); float angle = random_angle_radians(); - scratch[0] = fast_cos(angle) * radius; - scratch[1] = fast_sin(angle) * radius; - scratch[2] = zero; - scratch[2] = random_float_between(D_L10_00161E04, D_L10_00161E08); - fast_vec_add(&vars->goal, scratch, &vars->home); + vector_and_collision_scratch[0] = fast_cos(angle) * radius; + vector_and_collision_scratch[1] = fast_sin(angle) * radius; + vector_and_collision_scratch[2] = zero; + vector_and_collision_scratch[2] = random_float_between(l10_darter_min_wander_height_offset, l10_darter_max_wander_height_offset); + fast_vec_add(&darter_vars->goal, vector_and_collision_scratch, &darter_vars->home); } else if (dist < 0.1f) { moby->state = 4; - vars->wait = + darter_vars->wait = scale_game_frames(truncate_float_to_s32(random_float_between(30.0f, 90.0f))); } - if (vars->f104 == 2) + if (darter_vars->f104 == 2) break; if (!(3.0f < vector_distance_xy(&moby->pos, &target->pos))) break; @@ -248,9 +268,9 @@ void darter_update(Moby *moby) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); break; } - case 4: + case DARTER_STATE_WAIT_BETWEEN_WANDER_GOALS: moby->anim_speed = 4.0f; - if (vars->f104 != 2 && 3.0f < vector_distance_xy(&moby->pos, &target->pos) && + if (darter_vars->f104 != 2 && 3.0f < vector_distance_xy(&moby->pos, &target->pos) && FUN_L00_001fefc8(&moby->command) != 0) { if (moby->group != 0xFF) FUN_L10_002e1cb0_2e01a8((unsigned char *)moby); @@ -259,23 +279,23 @@ void darter_update(Moby *moby) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); break; } - if (fast_dec_timer(&vars->wait) == 0) + if (fast_dec_timer(&darter_vars->wait) == 0) break; { float radius = random_float_between(4.0f, 6.0f); float angle = random_angle_radians(); - scratch[0] = fast_cos(angle) * radius; - scratch[1] = fast_sin(angle) * radius; - scratch[2] = 0.0f; - scratch[2] = random_float_between(D_L10_00161E04, D_L10_00161E08); - fast_vec_add(&vars->goal, scratch, &vars->home); + vector_and_collision_scratch[0] = fast_cos(angle) * radius; + vector_and_collision_scratch[1] = fast_sin(angle) * radius; + vector_and_collision_scratch[2] = 0.0f; + vector_and_collision_scratch[2] = random_float_between(l10_darter_min_wander_height_offset, l10_darter_max_wander_height_offset); + fast_vec_add(&darter_vars->goal, vector_and_collision_scratch, &darter_vars->home); moby->state = 3; } break; - case 6: + case DARTER_STATE_ATTACK_WINDUP: approach_w(moby, fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y), - &vars->turn_speed, + &darter_vars->turn_speed, 0.02f, 0.3f, frame_time * 6.2831855f); @@ -285,51 +305,51 @@ void darter_update(Moby *moby) { if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); if (random_integer_below(0xFF) & 1) { - vars->side_angle = 0.2617994f; + darter_vars->side_angle = 0.2617994f; } else { - vars->side_angle = -0.2617994f; + darter_vars->side_angle = -0.2617994f; } break; - case 7: { - float lim; + case DARTER_STATE_DIVE_TOWARD_TARGET: { + float ground_height; approach_w(moby, fast_add_rotations( fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y), - vars->side_angle), - &vars->turn_speed, + darter_vars->side_angle), + &darter_vars->turn_speed, 0.02f, 0.3f, frame_time * 6.2831855f); - lim = probe_ground_height(&moby->pos, 0, 0.5f); - qcopy(scratch, &target->pos); - if (scratch[2] < moby->pos.z) { - scratch[2] = scratch[2] - (moby->pos.z - scratch[2]) * 4.0f; + ground_height = probe_ground_height(&moby->pos, 0, 0.5f); + qcopy(vector_and_collision_scratch, &target->pos); + if (vector_and_collision_scratch[2] < moby->pos.z) { + vector_and_collision_scratch[2] = vector_and_collision_scratch[2] - (moby->pos.z - vector_and_collision_scratch[2]) * 4.0f; } else { - scratch[2] = moby->pos.z; + vector_and_collision_scratch[2] = moby->pos.z; } - scratch[2] = scratch[2] + 0.5f; - if (scratch[2] < lim) - scratch[2] = lim; - fast_vec_sub(&vars->velocity, scratch, &moby->pos); - fast_vec_normalize(&vars->velocity, &vars->velocity, frame_time * 10.0f); - vars->velocity.x = fast_cos(moby->rot.z) * vector_length_xy(&vars->velocity); - vars->velocity.y = fast_sin(moby->rot.z) * vector_length_xy(&vars->velocity); - func_L00_00259B08_2E0630(moby, &vars->velocity, 0.5f, 0x200, 0.0f, 0); + vector_and_collision_scratch[2] = vector_and_collision_scratch[2] + 0.5f; + if (vector_and_collision_scratch[2] < ground_height) + vector_and_collision_scratch[2] = ground_height; + fast_vec_sub(&darter_vars->velocity, vector_and_collision_scratch, &moby->pos); + fast_vec_normalize(&darter_vars->velocity, &darter_vars->velocity, frame_time * 10.0f); + darter_vars->velocity.x = fast_cos(moby->rot.z) * vector_length_xy(&darter_vars->velocity); + darter_vars->velocity.y = fast_sin(moby->rot.z) * vector_length_xy(&darter_vars->velocity); + func_L00_00259B08_2E0630(moby, &darter_vars->velocity, 0.5f, 0x200, 0.0f, 0); func_L00_0025CC58_2E0630(&moby->rot.y, 0, - -fast_arc_tan(vector_length_xy(&vars->velocity), vars->velocity.z), + -fast_arc_tan(vector_length_xy(&darter_vars->velocity), darter_vars->velocity.z), frame_time * 6.2831855f); - if (vector_distance_xy(&moby->pos, &target->pos) < D_L10_00161DFC) { + if (vector_distance_xy(&moby->pos, &target->pos) < l10_darter_attack_distance) { if (absolute_float(moby->pos.z - ((Hero_2e01a8 *)((char *)&hero))->motion.pos.f[2]) < 2.0f) { allocate_voice_for_target_entry(0, 0, moby); moby->state = 8; - clear_u64_value(&vars->velocity); + clear_u64_value(&darter_vars->velocity); if (moby->prev_seq != 2) blend_moby_animation(moby, 2, 4, scale_game_frames(5)); break; } - } else if (vars->f104 != 2) { + } else if (darter_vars->f104 != 2) { break; } if (moby->prev_seq != 3) @@ -337,96 +357,96 @@ void darter_update(Moby *moby) { moby->state = 5; break; } - case 8: + case DARTER_STATE_DIVE_ATTACK: approach_w(moby, fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y), - &vars->turn_speed, + &darter_vars->turn_speed, 0.02f, 0.3f, frame_time * 6.2831855f); func_L00_0025CC58_2E0630( &moby->rot.y, 0, - -fast_arc_tan(vector_distance_xy(&moby->pos, &vars->vE0), vars->vE0.z - moby->pos.z), + -fast_arc_tan(vector_distance_xy(&moby->pos, &darter_vars->vE0), darter_vars->vE0.z - moby->pos.z), frame_time * 12.566371f); if (is_value_within_interpolated_window((char *)moby, 20.0f)) { float one = 1.0f; - *(int *)&scratch[13] = 1; - *(int *)&scratch[16] = 1; - *(Moby **)&scratch[12] = moby; - scratch[15] = one; - scratch[8] = fast_cos(moby->rot.z); - scratch[9] = fast_sin(moby->rot.z); - ((unsigned char *)scratch)[0x39] = 1; - scratch[10] = one; - scratch[11] = 5627.9248f; - *(short *)((char *)scratch + 0x3A) = moby->oclass; - ((unsigned char *)scratch)[0x38] = 0; - FUN_L00_0024f7c8(moby, 0, scratch); - coll_sphere_mobys(0.4f, scratch, 0, moby, &scratch[8]); - collision_line(&moby->pos, scratch, 9, moby, &scratch[8]); + *(int *)&vector_and_collision_scratch[13] = 1; + *(int *)&vector_and_collision_scratch[16] = 1; + *(Moby **)&vector_and_collision_scratch[12] = moby; + vector_and_collision_scratch[15] = one; + vector_and_collision_scratch[8] = fast_cos(moby->rot.z); + vector_and_collision_scratch[9] = fast_sin(moby->rot.z); + ((unsigned char *)vector_and_collision_scratch)[0x39] = 1; + vector_and_collision_scratch[10] = one; + vector_and_collision_scratch[11] = 5627.9248f; + *(short *)((char *)vector_and_collision_scratch + 0x3A) = moby->oclass; + ((unsigned char *)vector_and_collision_scratch)[0x38] = 0; + FUN_L00_0024f7c8(moby, 0, vector_and_collision_scratch); + coll_sphere_mobys(0.4f, vector_and_collision_scratch, 0, moby, &vector_and_collision_scratch[8]); + collision_line(&moby->pos, vector_and_collision_scratch, 9, moby, &vector_and_collision_scratch[8]); } - if (vars->f104 != 2 && (moby->anim_flags & 2) == 0) + if (darter_vars->f104 != 2 && (moby->anim_flags & 2) == 0) break; if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(0x14)); moby->state = 5; break; - case 5: { + case DARTER_STATE_RETURN_HOME: { float zero = 0.0f; float climb; func_L00_0025CC58_2E0630(&moby->rot.y, 0, zero, frame_time * 12.566371f); approach_w(moby, - fast_arc_tan(vars->home.x - moby->pos.x, vars->home.y - moby->pos.y), - &vars->turn_speed, + fast_arc_tan(darter_vars->home.x - moby->pos.x, darter_vars->home.y - moby->pos.y), + &darter_vars->turn_speed, 0.02f, 0.3f, frame_time * 6.2831855f); - vars->velocity.x = fast_cos(moby->rot.z) * (frame_time * 6.0f); - vars->velocity.y = fast_sin(moby->rot.z) * (frame_time * 6.0f); - vars->velocity.z = zero; - climb = vars->home.z + 2.0f - moby->pos.z; + darter_vars->velocity.x = fast_cos(moby->rot.z) * (frame_time * 6.0f); + darter_vars->velocity.y = fast_sin(moby->rot.z) * (frame_time * 6.0f); + darter_vars->velocity.z = zero; + climb = darter_vars->home.z + 2.0f - moby->pos.z; if (frame_time * 6.0f < climb) { climb = frame_time * 6.0f; } else if (climb < frame_time * -6.0f) { climb = frame_time * -6.0f; } - vars->velocity.z = climb; - func_L00_00259B08_2E0630(moby, &vars->velocity, 0.5f, 0x200, 0.0f, 0); - if (vector_distance_xy(&moby->pos, &vars->home) < 2.0f) + darter_vars->velocity.z = climb; + func_L00_00259B08_2E0630(moby, &darter_vars->velocity, 0.5f, 0x200, 0.0f, 0); + if (vector_distance_xy(&moby->pos, &darter_vars->home) < 2.0f) moby->state = 3; break; } - case 9: { + case DARTER_STATE_CUBOID_PATROL: { float dist = fast_vec_dist(&moby->pos, &target->pos); float climb; approach_w(moby, - fast_arc_tan(vars->home.x - moby->pos.x, vars->home.y - moby->pos.y), - &vars->turn_speed, + fast_arc_tan(darter_vars->home.x - moby->pos.x, darter_vars->home.y - moby->pos.y), + &darter_vars->turn_speed, 0.02f, 0.3f, frame_time * 0.78539819f); - vars->velocity.x = fast_cos(moby->rot.z) * (frame_time * 4.0f); - vars->velocity.y = fast_sin(moby->rot.z) * (frame_time * 4.0f); - vars->velocity.z = 0.0f; - if (fast_dec_timer(&vars->height_timer)) { - vars->height_offset = random_float_between(0.0f, D_L10_00161E14); - vars->height_timer = truncate_float_to_s32(scale_time(D_L10_00161E18 * 60.0f) * + darter_vars->velocity.x = fast_cos(moby->rot.z) * (frame_time * 4.0f); + darter_vars->velocity.y = fast_sin(moby->rot.z) * (frame_time * 4.0f); + darter_vars->velocity.z = 0.0f; + if (fast_dec_timer(&darter_vars->height_timer)) { + darter_vars->height_offset = random_float_between(0.0f, l10_darter_max_height_offset); + darter_vars->height_timer = truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * random_float_between(0.75f, 1.25f)); } - climb = l10_cuboids[vars->f194].pos.z - moby->pos.z - vars->height_offset; + climb = l10_cuboids[darter_vars->f194].pos.z - moby->pos.z - darter_vars->height_offset; if (frame_time + frame_time < climb) { climb = frame_time + frame_time; } else if (climb < frame_time * -2.0f) { climb = frame_time * -2.0f; } - vars->velocity.z = climb; - func_L00_00259B08_2E0630(moby, &vars->velocity, 0.5f, 0x200, 0.0f, 0); - if (vars->f104 == 2) + darter_vars->velocity.z = climb; + func_L00_00259B08_2E0630(moby, &darter_vars->velocity, 0.5f, 0x200, 0.0f, 0); + if (darter_vars->f104 == 2) break; if (FUN_L00_001fefc8(&moby->command) == 0) break; - if (!(D_L10_00161DFC < dist)) + if (!(l10_darter_attack_distance < dist)) break; if (moby->group != 0xFF) FUN_L10_002e1cb0_2e01a8((unsigned char *)moby); @@ -435,45 +455,45 @@ void darter_update(Moby *moby) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); break; } - case 10: { + case DARTER_STATE_CUBOID_APPROACH_TARGET: { float dist = fast_vec_dist(&moby->pos, &target->pos); float climb; if (moby->group != 0xFF) FUN_L10_002e1cb0_2e01a8((unsigned char *)moby); approach_w(moby, fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y), - &vars->turn_speed, + &darter_vars->turn_speed, 0.02f, 0.3f, frame_time * 1.5707964f); - vars->velocity.x = fast_cos(moby->rot.z) * (frame_time * 4.0f); - vars->velocity.y = fast_sin(moby->rot.z) * (frame_time * 4.0f); - vars->velocity.z = 0.0f; - climb = l10_cuboids[vars->f194].pos.z - moby->pos.z; + darter_vars->velocity.x = fast_cos(moby->rot.z) * (frame_time * 4.0f); + darter_vars->velocity.y = fast_sin(moby->rot.z) * (frame_time * 4.0f); + darter_vars->velocity.z = 0.0f; + climb = l10_cuboids[darter_vars->f194].pos.z - moby->pos.z; if (frame_time * 4.0f < climb) { climb = frame_time * 4.0f; } else if (climb < frame_time * -4.0f) { climb = frame_time * -4.0f; } - vars->velocity.z = climb; - func_L00_00259B08_2E0630(moby, &vars->velocity, 0.5f, 0x200, 0.0f, 0); - if (dist < D_L10_00161DFC && - absolute_float(l10_cuboids[vars->f194].pos.z - moby->pos.z) < 1.0f) { + darter_vars->velocity.z = climb; + func_L00_00259B08_2E0630(moby, &darter_vars->velocity, 0.5f, 0x200, 0.0f, 0); + if (dist < l10_darter_attack_distance && + absolute_float(l10_cuboids[darter_vars->f194].pos.z - moby->pos.z) < 1.0f) { allocate_voice_for_target_entry(0, 0, moby); moby->state = 11; if (moby->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(2)); break; } - if (vars->f104 != 2) + if (darter_vars->f104 != 2) break; moby->state = 9; - vars->height_offset = random_float_between(0.0f, D_L10_00161E14); - vars->height_timer = truncate_float_to_s32(scale_time(D_L10_00161E18 * 60.0f) * + darter_vars->height_offset = random_float_between(0.0f, l10_darter_max_height_offset); + darter_vars->height_timer = truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * random_float_between(0.75f, 1.25f)); break; } - case 11: { + case DARTER_STATE_CUBOID_CHARGE_ATTACK: { float climb; float zero; float one; @@ -481,30 +501,30 @@ void darter_update(Moby *moby) { FUN_L10_002e1cb0_2e01a8((unsigned char *)moby); approach_w(moby, fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y), - &vars->turn_speed, + &darter_vars->turn_speed, 0.02f, 0.3f, frame_time * 6.2831855f); - vars->velocity.x = fast_cos(moby->rot.z) * (frame_time * 6.0f); - vars->velocity.y = fast_sin(moby->rot.z) * (frame_time * 6.0f); - vars->velocity.z = 0.0f; - climb = l10_cuboids[vars->f194].pos.z - moby->pos.z; + darter_vars->velocity.x = fast_cos(moby->rot.z) * (frame_time * 6.0f); + darter_vars->velocity.y = fast_sin(moby->rot.z) * (frame_time * 6.0f); + darter_vars->velocity.z = 0.0f; + climb = l10_cuboids[darter_vars->f194].pos.z - moby->pos.z; if (frame_time * 3.0f < climb) { climb = frame_time * 3.0f; } else if (climb < frame_time * -3.0f) { climb = frame_time * -3.0f; } - vars->velocity.z = climb; + darter_vars->velocity.z = climb; zero = 0.0f; - func_L00_00259B08_2E0630(moby, &vars->velocity, 0.5f, 0x200, zero, 0); + func_L00_00259B08_2E0630(moby, &darter_vars->velocity, 0.5f, 0x200, zero, 0); one = 1.0f; - *(int *)&scratch[9] = 0x10001; - *(int *)&scratch[12] = 1; - *(Moby **)&scratch[8] = moby; - scratch[11] = one; - clear_u64_value(&scratch[4]); - FUN_L00_0024f7c8(moby, 0, scratch); - coll_sphere_mobys(0.2f, scratch, 0, moby, &scratch[4]); + *(int *)&vector_and_collision_scratch[9] = 0x10001; + *(int *)&vector_and_collision_scratch[12] = 1; + *(Moby **)&vector_and_collision_scratch[8] = moby; + vector_and_collision_scratch[11] = one; + clear_u64_value(&vector_and_collision_scratch[4]); + FUN_L00_0024f7c8(moby, 0, vector_and_collision_scratch); + coll_sphere_mobys(0.2f, vector_and_collision_scratch, 0, moby, &vector_and_collision_scratch[4]); if (fast_vec_dist(&moby->pos, &target->pos) < one || *(int *)(((char *)&hero) + 0x208C) == 7 || (moby->anim_flags & 2)) { moby->state = 12; @@ -512,44 +532,44 @@ void darter_update(Moby *moby) { blend_moby_animation(moby, 3, 0, scale_game_frames(2)); break; } - if (vars->f104 != 2) + if (darter_vars->f104 != 2) break; moby->state = 9; - vars->height_offset = random_float_between(zero, D_L10_00161E14); - vars->height_timer = truncate_float_to_s32(scale_time(D_L10_00161E18 * 60.0f) * + darter_vars->height_offset = random_float_between(zero, l10_darter_max_height_offset); + darter_vars->height_timer = truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * random_float_between(0.75f, 1.25f)); break; } - case 12: { + case DARTER_STATE_CUBOID_RETURN_HOME: { float climb; approach_w(moby, - fast_arc_tan(vars->home.x - moby->pos.x, vars->home.y - moby->pos.y), - &vars->turn_speed, + fast_arc_tan(darter_vars->home.x - moby->pos.x, darter_vars->home.y - moby->pos.y), + &darter_vars->turn_speed, 0.02f, 0.3f, frame_time * 1.0471976f); - vars->velocity.x = fast_cos(moby->rot.z) * (frame_time * 4.0f); - vars->velocity.y = fast_sin(moby->rot.z) * (frame_time * 4.0f); - vars->velocity.z = 0.0f; - climb = l10_cuboids[vars->f194].pos.z - moby->pos.z; + darter_vars->velocity.x = fast_cos(moby->rot.z) * (frame_time * 4.0f); + darter_vars->velocity.y = fast_sin(moby->rot.z) * (frame_time * 4.0f); + darter_vars->velocity.z = 0.0f; + climb = l10_cuboids[darter_vars->f194].pos.z - moby->pos.z; if (frame_time * 3.0f < climb) { climb = frame_time * 3.0f; } else if (climb < frame_time * -3.0f) { climb = frame_time * -3.0f; } - vars->velocity.z = climb; - add_vectors(scratch, &moby->pos, &vars->velocity); - if (vector_distance_xy(&moby->pos, &vars->home) < 2.0f) { + darter_vars->velocity.z = climb; + add_vectors(vector_and_collision_scratch, &moby->pos, &darter_vars->velocity); + if (vector_distance_xy(&moby->pos, &darter_vars->home) < 2.0f) { moby->state = 9; moby->command = scale_game_frames(0x78); - vars->height_offset = random_float_between(0.0f, D_L10_00161E14); - vars->height_timer = truncate_float_to_s32(scale_time(D_L10_00161E18 * 60.0f) * + darter_vars->height_offset = random_float_between(0.0f, l10_darter_max_height_offset); + darter_vars->height_timer = truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * random_float_between(0.75f, 1.25f)); } break; } - case 13: - if ((step_moby_motion(moby, vars->a60) & 1) == 0) + case DARTER_STATE_DYING: + if ((step_moby_motion(moby, darter_vars->a60) & 1) == 0) break; mark_moby_for_removal_cf(moby, 0x200, -1); spawn_color_swapped_explosion_burst(moby, &moby->pos, -1, 0.5f, 10.0f); @@ -557,11 +577,11 @@ void darter_update(Moby *moby) { return; } if (moby->state != 0 && moby->state != 13) { - vars->bob_angle = fast_add_rotations( - vars->bob_angle, - 360.0f / (float)truncate_float_to_s32(scale_time(D_L10_00161E10 * 60.0f)) * + darter_vars->bob_angle = fast_add_rotations( + darter_vars->bob_angle, + 360.0f / (float)truncate_float_to_s32(scale_time(l10_darter_bob_period_seconds * 60.0f)) * 0.017453292f); - moby->pos.z = moby->pos.z + D_L10_00161E0C * fast_cos(vars->bob_angle); + moby->pos.z = moby->pos.z + l10_darter_bob_amplitude * fast_cos(darter_vars->bob_angle); } } From b5d9a156e6480e4944a8aa67314da1ab1e8e0680 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:34:15 +0000 Subject: [PATCH 0161/1502] decomp: clarify names in hero_set_state a -> requested_state: In authoritative hero_set_state C, a is assigned to p->state.current and selects switch(a). Retail 0x0024db70 saves incoming a0 in s1; 0x0024dc80/0x0024dca8 preserve the former current state in prev, 0x0024dcb0 stores s1 to Hero+0x2084 (state.current), and 0x0024dd40-0x0024dd60 bounds and dispatches s1 through the state jump table. Original Ghidra likewise assigns param_1 to iRam001413d4 and switches on param_1. Supplied callers request HERO_STATE_DYING and HERO_STATE_SINK through this first argument. Therefore requested_state describes the requested state ID, including refused requests. --- src/overlays/l11/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l11/hero/hero_set_state.c b/src/overlays/l11/hero/hero_set_state.c index dc0aab7422..cb0cfb3cbc 100644 --- a/src/overlays/l11/hero/hero_set_state.c +++ b/src/overlays/l11/hero/hero_set_state.c @@ -65,13 +65,13 @@ extern int hero_set_state(int, int) __asm__("FUN_L11_0024db50"); extern char level_11_water_surface_jump_velocity_keys[] __asm__("D_L11_0017C960"); extern char level_11_trail_jump_velocity_keys[] __asm__("D_L11_0017C920"); -int hero_set_state(int a, int b) { +int hero_set_state(int requested_state, int b) { int previous_state_step; char *moby; int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((D_L11_0015F5C4 == 2 || D_L11_0015F5C4 == 6) && b != 2) @@ -79,8 +79,8 @@ int hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -93,7 +93,7 @@ int hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -118,7 +118,7 @@ int hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -939,7 +939,7 @@ int hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From d42a984d180c4b969660acb2219939ea5865de8f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:37:02 +0000 Subject: [PATCH 0162/1502] decomp: clarify names in hero_set_state a -> requested_state: Authoritative hero_set_state source (SHA-256 121dc523e5e08f85e3110134ccef68c4d100bcfc9671503ca7a997eccc18a3df) assigns p->state.current = a, switches on a, and uses a for requested jump-state checks. Retail 0x002400f0 saves incoming a0 to s1; 0x00240200 loads the old current state, 0x00240228 saves it to prev, and 0x00240230 stores s1 into Hero+0x2084 (state.current). 0x002402c0..0x002402e0 dispatches using s1. Original Ghidra agrees: iRam001413d4 = param_1; switch(param_1). Supplied caller requests HERO_STATE_DYING or HERO_STATE_SINK as the first argument. Thus this is the requested hero state, distinct from control mode and state step. --- src/overlays/l12/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l12/hero/hero_set_state.c b/src/overlays/l12/hero/hero_set_state.c index 6b2cfbf87e..934ce3475c 100644 --- a/src/overlays/l12/hero/hero_set_state.c +++ b/src/overlays/l12/hero/hero_set_state.c @@ -66,13 +66,13 @@ extern int hero_set_state(int, int) __asm__("FUN_L12_002400d0"); extern char level12_transform_trail_jump_velocity_key_profile[] __asm__("D_L12_0017C3A0"); extern char level12_water_surface_jump_velocity_key_profile[] __asm__("D_L12_0017C3E0"); -int hero_set_state(int a, int b) { +int hero_set_state(int requested_state, int b) { int previous_state_step; char *moby; int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((D_L12_0015F5C4 == 2 || D_L12_0015F5C4 == 6) && b != 2) @@ -80,8 +80,8 @@ int hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -94,7 +94,7 @@ int hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -119,7 +119,7 @@ int hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -973,7 +973,7 @@ int hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 3fef51d4121a8109cb714264337d82b986d71ce5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:37:02 +0000 Subject: [PATCH 0163/1502] decomp: clarify names in hero_set_state a -> requested_state: Authoritative C src/overlays/l08/hero/hero_set_state.c SHA-256 88b5ea1fa2901952d427a64a725b0c1dd2fd646c8fba87553cef4e7d309d7927 assigns int a to p->state.current and dispatches switch(a). Original retail Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Retail 0x00230b58 preserves a0 in s1; 0x00230c68/0x00230c90 saves the prior current state, 0x00230c98 stores s1 at hero+0x2084, and 0x00230d28..0x00230d48 bounds and dispatches s1. Recursive calls at 0x00231d50..0x00231d58 request idle (0,0), and 0x00231f0c..0x00231f14 requests slip (0x79,1). Thus requested_state distinguishes the requested selector from prior state and control mode. --- src/overlays/l08/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l08/hero/hero_set_state.c b/src/overlays/l08/hero/hero_set_state.c index b19e34f4d9..4815d6e32d 100644 --- a/src/overlays/l08/hero/hero_set_state.c +++ b/src/overlays/l08/hero/hero_set_state.c @@ -68,14 +68,14 @@ extern int hero_set_state(int, int) __asm__("FUN_L08_00230b38"); extern char hero_water_surface_jump_velocity_keys[] __asm__("D_L08_0017C760"); extern char hero_transform_trail_jump_velocity_keys[] __asm__("D_L08_0017C720"); -int hero_set_state(int a, int b) { +int hero_set_state(int requested_state, int b) { int previous_state_step; char *moby; int old20A7; float grind_vector_scratch[4]; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((level_game_mode == 2 || level_game_mode == 6) && b != 2) @@ -83,8 +83,8 @@ int hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -97,7 +97,7 @@ int hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -122,7 +122,7 @@ int hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -1002,7 +1002,7 @@ int hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 04e2a5fc3fd919386c64fdcf73e526d647fe4e2f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:37:02 +0000 Subject: [PATCH 0164/1502] decomp: clarify names in hero_set_state a -> requested_state: In authoritative C, int a is checked against allowed state IDs, assigned to p->state.current, and used by switch(a). Original Ghidra likewise assigns param_1 to iRam001413d4 and dispatches switch(param_1). Retail 0x00216c58 moves a0 into s1; 0x00216d98 stores s1 to hero+0x2084 (state.current); 0x00216e28..0x00216e48 bounds and indexes the state jump table with s1. The refusal gate at 0x00216c94..0x00216ca8 confirms it is a requested transition, not an unconditional final state. --- src/overlays/l15/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l15/hero/hero_set_state.c b/src/overlays/l15/hero/hero_set_state.c index 393c7ebf60..136ccb21fb 100644 --- a/src/overlays/l15/hero/hero_set_state.c +++ b/src/overlays/l15/hero/hero_set_state.c @@ -68,13 +68,13 @@ extern int hero_set_state(int, int) __asm__("FUN_L15_00216c38"); extern char hero_trail_jump_velocity_keys[] __asm__("D_L15_0017C520"); extern char hero_deep_water_jump_velocity_keys[] __asm__("D_L15_0017C560"); -int hero_set_state(int a, int b) { +int hero_set_state(int requested_state, int b) { int saved_state_step; char *moby; int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((D_L15_0015F5C4 == 2 || D_L15_0015F5C4 == 6) && b != 2) @@ -82,8 +82,8 @@ int hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -96,7 +96,7 @@ int hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -121,7 +121,7 @@ int hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -903,7 +903,7 @@ int hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From a8f5a3584a3dff32c3c213462a5decdce1807435 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:37:03 +0000 Subject: [PATCH 0165/1502] decomp: clarify names in hero_set_state a -> requested_state: Authoritative src/overlays/l16/hero/hero_set_state.c SHA-256 8ee03afc5113b2a05484011ab6f8c3be3ef51546c042f71870405be71b3fabbf assigns a to p->state.current and dispatches switch(a). Retail 0x0021e3b8 saves a0 in s1; 0x0021e4f0 saves the old current state to prev, 0x0021e4f8 stores s1 to hero+0x2084 (current), and 0x0021e588-0x0021e5a8 indexes the state-entry jump table with s1. Original Ghidra confirms iRam001413d4 = param_1 and switch(param_1); named caller update_hero_state_transitions supplies HERO_STATE_DYING. Thus the int is the requested state ID, distinct from control modes and animation IDs. --- src/overlays/l16/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l16/hero/hero_set_state.c b/src/overlays/l16/hero/hero_set_state.c index 921b18e374..590903f736 100644 --- a/src/overlays/l16/hero/hero_set_state.c +++ b/src/overlays/l16/hero/hero_set_state.c @@ -82,14 +82,14 @@ extern int hero_set_state(int, int) __asm__("FUN_L16_0021e398"); extern char level16_hero_jump_velocity_keys[] __asm__("D_L16_0017C380"); extern char level16_hero_water_surface_jump_velocity_keys[] __asm__("D_L16_0017C3C0"); -int hero_set_state(int a, int b) { +int hero_set_state(int requested_state, int b) { int saved_state_step; char *moby; int old20A7; float vec[4]; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((D_L16_0015F5C4 == 2 || D_L16_0015F5C4 == 6) && b != 2) @@ -97,8 +97,8 @@ int hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -111,7 +111,7 @@ int hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -136,7 +136,7 @@ int hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -1185,7 +1185,7 @@ int hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 352ccf4130d885b908427c6e4f5d18058063f84c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:37:03 +0000 Subject: [PATCH 0166/1502] decomp: clarify names in hero_set_state a -> requested_state: Authoritative hero_set_state(int a,int b) copies a into p->state.current before switch(a). Original Ghidra param_1 likewise becomes iRam001413d4 and selects the switch. Retail 0x00222418 retains a0 in s1; 0x00222558 stores s1 to hero+0x2084, while 0x002225f8 scales s1 to index the state dispatch table. Supplied set_hero_idle_state_for_vehicle_mode and try_start_hero_jump pass explicit state requests as the first argument. Thus requested_state identifies the incoming state request, including requests refused by admission guards or jump lock. --- src/overlays/shared/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/hero/hero_set_state.c b/src/overlays/shared/hero/hero_set_state.c index 7778f53819..540ddc5c0d 100644 --- a/src/overlays/shared/hero/hero_set_state.c +++ b/src/overlays/shared/hero/hero_set_state.c @@ -675,7 +675,7 @@ extern void fast_vec_normalize(void *, void *, float) __asm__("FUN_001f9bf8"); extern int hero_set_state(int, int) __asm__("FUN_L00_002223f8"); extern char hero_velocity_profile_jump_keys[] __asm__("D_L00_0017BF20"); -int hero_set_state(int a, int b) { +int hero_set_state(int requested_state, int b) { int previous_state_step; char *moby; int old20A7; @@ -686,7 +686,7 @@ int hero_set_state(int a, int b) { V4_222B80 sampled_path_position; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((D_L00_0015F5C4 == 2 || D_L00_0015F5C4 == 6) && b != 2) @@ -694,8 +694,8 @@ int hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -708,7 +708,7 @@ int hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -733,7 +733,7 @@ int hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -1696,7 +1696,7 @@ int hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 1c7a816b51ba125edc2161316c1343ce07b00d61 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:37:03 +0000 Subject: [PATCH 0167/1502] decomp: clarify names in hero_set_state a -> requested_state: Authoritative hero_set_state assigns a to p->state.current and dispatches switch(a); original retail Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Retail 0x0021e550 saves incoming a0 in s1, 0x0021e690 stores s1 to hero+0x2084 (state.current), and 0x0021e720..0x0021e740 bounds-checks and indexes the state dispatch table with s1. Refusal checks at 0x0021e58c and 0x0021e5f0..0x0021e648 test this incoming state before acceptance. Thus this parameter is the requested hero state, distinct from control_mode and vehicle_mode. --- src/overlays/l17/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l17/hero/hero_set_state.c b/src/overlays/l17/hero/hero_set_state.c index ff89ae6ec7..afe72108e2 100644 --- a/src/overlays/l17/hero/hero_set_state.c +++ b/src/overlays/l17/hero/hero_set_state.c @@ -92,7 +92,7 @@ extern int hero_set_state(int, int) __asm__("FUN_L17_0021e530"); extern char level17_hero_water_surface_jump_velocity_keys[] __asm__("D_L17_0017C860"); extern char level17_hero_trail_jump_velocity_keys[] __asm__("D_L17_0017C820"); -int hero_set_state(int a, int b) { +int hero_set_state(int requested_state, int b) { int previous_state_step; char *moby; int old20A7; @@ -103,7 +103,7 @@ int hero_set_state(int a, int b) { V4_21ED38 sampled_path_position; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((D_L17_0015F5C4 == 2 || D_L17_0015F5C4 == 6) && b != 2) @@ -111,8 +111,8 @@ int hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -125,7 +125,7 @@ int hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -150,7 +150,7 @@ int hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -1106,7 +1106,7 @@ int hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 4da1176114342d098349db30447b3e3b4b62527d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:37:03 +0000 Subject: [PATCH 0168/1502] decomp: clarify names in set_fourth_hero_easing_parameters a -> ease_acceleration: Authoritative source SHA-256 3dc55c8ca4ead41f0075aa31d9cba662f6c674e84022ed62352b51398d0f8b73 assigns float a directly to destination[3].accel. Retail 0x0020a228/0x0020a22c forms hero_eases base 0x0017a680; 0x0020a238 stores first float argument f12 at +0x2b4 (0x0017a934). Original Ghidra likewise assigns param_1 to DAT_0017a934, proving this is the fourth ease acceleration. b -> ease_max_speed: Authoritative source assigns float b directly to destination[3].max_speed. Retail 0x0020a230 stores second float argument f13 at hero_eases base 0x0017a680 +0x2b8 (0x0017a938). Original Ghidra likewise assigns param_2 to DAT_0017a938. The supplied hero_update_movement call set_fourth_hero_easing_parameters(0.02f, 0.2f) agrees with the established acceleration/max_speed pair. --- .../shared/hero/set_second_hero_easing_parameters.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/hero/set_second_hero_easing_parameters.c b/src/overlays/shared/hero/set_second_hero_easing_parameters.c index e2db6104f3..411e59ed4d 100644 --- a/src/overlays/shared/hero/set_second_hero_easing_parameters.c +++ b/src/overlays/shared/hero/set_second_hero_easing_parameters.c @@ -27,10 +27,10 @@ extern struct HeroEase hero_eases[] __asm__("D_L00_0017A680"); /* Sets the accel and max_speed of one hero ease. */ void set_fourth_hero_easing_parameters(float a, float b) __asm__("FUN_L00_0020a228"); -void set_fourth_hero_easing_parameters(float a, float b) { +void set_fourth_hero_easing_parameters(float ease_acceleration, float ease_max_speed) { struct HeroEase *destination = hero_eases; - destination[3].accel = a; - destination[3].max_speed = b; + destination[3].accel = ease_acceleration; + destination[3].max_speed = ease_max_speed; } extern int D_0013F350_002321a8[] __asm__("D_0013F350"); From 1a5f06c6034fe3afc6f65008f2d80f8ecc1bad6a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:39:06 +0000 Subject: [PATCH 0169/1502] decomp: clarify names in hero_set_state a -> requested_state: Authoritative src/overlays/l18/hero/hero_set_state.c SHA-256 8850d5f647c5bd18bb2fe29cba2114adfc9ff38407e11d0219648b3e7d3bae9f assigns p->state.current = a after saving the previous state and dispatches switch(a). Original retail Ghidra assigns iRam001413d4 = param_1 and switches on param_1. Retail 0x00227df0 preserves argument a0 in s1; 0x00227f00 loads the old current state, 0x00227f28 saves it to hero+0x2090, and 0x00227f30 writes s1 to hero+0x2084. Instructions 0x00227fc0-0x00227fe0 range-check and index the state jump table with s1. Supplied callers request HERO_STATE_HURT, HERO_STATE_SLIP and other state IDs as the first argument. Thus this int is the requested hero state, distinct from the control mode and previous state. --- src/overlays/l18/hero/hero_set_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l18/hero/hero_set_state.c b/src/overlays/l18/hero/hero_set_state.c index 5bc1be4005..5276b2b7c3 100644 --- a/src/overlays/l18/hero/hero_set_state.c +++ b/src/overlays/l18/hero/hero_set_state.c @@ -69,14 +69,14 @@ extern int hero_set_state(int, int) __asm__("FUN_L18_00227dd0"); extern char hero_trail_jump_velocity_key_profile[] __asm__("D_L18_0017C920"); extern char hero_water_surface_jump_velocity_key_profile[] __asm__("D_L18_0017C960"); -int hero_set_state(int a, int b) { +int hero_set_state(int requested_state, int b) { int previous_state_step; char *moby; int old20A7; float grind_direction_or_jump_probe_position[4]; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (a != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) return 0; } if ((D_L18_0015F5C4 == 2 || D_L18_0015F5C4 == 6) && b != 2) @@ -84,8 +84,8 @@ int hero_set_state(int a, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - a != 6 && a != 0x3D && a != 0x47 && a != 0x57 && a != 0x62 && a != 0x77 && a != 0x7B && - a != 0x7C && a != 0x7F && a != 0x6A && a != 0x80 && a != 0x82) + requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && + requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) return 0; } { @@ -98,7 +98,7 @@ int hero_set_state(int a, int b) { p->state.prev_timer = p->state_timer; p->state.prev = p->state.current; p->state.prev_control_mode = p->state.control_mode; - p->state.current = a; + p->state.current = requested_state; p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; @@ -123,7 +123,7 @@ int hero_set_state(int a, int b) { create_missing_hero_item_slot_animations(p->state.prev, p->state.current); p->rand_timer.range = 0; } - switch (a) { + switch (requested_state) { case HERO_STATE_IDLE: { struct Hero *p = &hero; p->state.control_mode = 0; @@ -1002,7 +1002,7 @@ int hero_set_state(int a, int b) { return 0; } p->state.control_mode = 4; - if (a >= 0x29 && a <= 0x2A) { + if (requested_state >= 0x29 && requested_state <= 0x2A) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From babc9930fbf6d3778096d713a47415da71bbc7e4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:39:07 +0000 Subject: [PATCH 0170/1502] decomp: clarify names in update_hero_motion_for_current_state e -> landing_voice_slot: In the hero_slot_item_id(3)==2 landing branch, this struct VoiceSlot pointer indexes voice_pool using hero.voice_slot4 * 0x70. Retail 0x00214480-0x002144c0 compares slot+0x88 to hero.moby, tests slot+0x74 and releases that same indexed slot; original Ghidra case 8 confirms the selection. e -> alternate_landing_voice_slot: In the alternate landing branch (hero_slot_item_id(3)!=2), this struct VoiceSlot pointer indexes voice_pool using hero.unk2224 * 0x70. Retail 0x002144e8-0x00214528 checks slot+0x88 against hero.moby and slot+0x74 before releasing hero.unk2224; original Ghidra case 8 confirms the alternate selection. e -> swim_voice_slot: The struct VoiceSlot pointer is formed from voice_pool plus hero.pack_swim_voice * 0x70. Retail 0x0020f794-0x0020f7d0 computes that slot, compares its +0x88 pointer to hero.moby and tests +0x74 before release_voice_slot(idx); original Ghidra case 0x33/0x34/0x35 confirms this flow. --- .../l03/hero/update_hero_motion_for_current_state.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l03/hero/update_hero_motion_for_current_state.c b/src/overlays/l03/hero/update_hero_motion_for_current_state.c index 452da57a01..6566aca017 100644 --- a/src/overlays/l03/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l03/hero/update_hero_motion_for_current_state.c @@ -514,8 +514,8 @@ void update_hero_motion_for_current_state(void) { } else { s32 idx = hero.pack_swim_voice; if (idx != -1) { - struct VoiceSlot *e = (struct VoiceSlot *)(((u8 *)&voice_pool) + idx * 0x70); - if (e->pm88 == MV(hero.moby) && e->b74 != 0) { + struct VoiceSlot *swim_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + idx * 0x70); + if (swim_voice_slot->pm88 == MV(hero.moby) && swim_voice_slot->b74 != 0) { release_voice_slot(idx); } } @@ -2078,9 +2078,9 @@ void update_hero_motion_for_current_state(void) { f32 sp; if (hero_slot_item_id(3) == 2) { if (hero.voice_slot4 != -1) { - struct VoiceSlot *e = + struct VoiceSlot *landing_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + hero.voice_slot4 * 0x70); - if (e->pm88 == MV(hero.moby) && e->b74 != 0) { + if (landing_voice_slot->pm88 == MV(hero.moby) && landing_voice_slot->b74 != 0) { release_voice_slot(hero.voice_slot4); } } @@ -2088,9 +2088,9 @@ void update_hero_motion_for_current_state(void) { release_voice_slot_cf(3, MV(hero.moby), 2); } else { if (hero.unk2224 != -1) { - struct VoiceSlot *e = + struct VoiceSlot *alternate_landing_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + hero.unk2224 * 0x70); - if (e->pm88 == MV(hero.moby) && e->b74 != 0) { + if (alternate_landing_voice_slot->pm88 == MV(hero.moby) && alternate_landing_voice_slot->b74 != 0) { release_voice_slot(hero.unk2224); } } From ae05e1f3354d2bc979406dfc9a3465b32c35716f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:39:07 +0000 Subject: [PATCH 0171/1502] decomp: clarify names in update_hero_motion_for_current_state e -> grind_voice_slot: Source forms struct VoiceSlot *e from voice_pool + hero.grind_voice * 0x70, checks owner against hero.moby and b74 before releasing that voice. Retail 002310d8-00231114 loads hero+2218, multiplies by 0x70, checks slot+88 and +74, and releases the same index; original Ghidra cases 0x28/29/2a/2b/42 confirm this flow. e -> rail_ahead_pitch: Source samples rail_spline 0.3 ahead using copied segment/fraction and computes e = fast_arc_tan(XY distance from rail_point, sampled Z minus rail_point Z). Retail 00231de0-00231e38 performs that sampling and atan2 into f5; 00231e3c-00231f34 uses its sign and angular thresholds for slope speed adjustment and grind pose. Original Ghidra corroborates the signed sampled-rail inclination. e -> landing_item_voice_slot: In HERO_STATE_LAND, the hero_slot_item_id(3)==2 branch forms e from voice_pool + hero.voice_slot4*0x70, checks hero ownership and nonzero b74, and releases the same slot before the item-associated release call (3,hero.moby,2). Retail 00232adc-00232b4c and original Ghidra case 8 corroborate index load +2228, 0x70 stride, owner/state checks and release. e -> landing_entry4_voice_slot: The alternate HERO_STATE_LAND branch forms e from voice_pool + hero.unk2224*0x70 and uses it solely for owner and nonzero b74 checks before release_voice_slot(hero.unk2224), then clears the index and calls release_voice_slot_cf(4,hero.moby,0x12). Retail 00232b58-00232bb4 loads +2224, checks slot+88/+74 and releases the same index; original Ghidra case 8 agrees. --- .../update_hero_motion_for_current_state.c | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/overlays/l06/hero/update_hero_motion_for_current_state.c b/src/overlays/l06/hero/update_hero_motion_for_current_state.c index d86c137fbe..cdbfdd398c 100644 --- a/src/overlays/l06/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l06/hero/update_hero_motion_for_current_state.c @@ -2031,9 +2031,9 @@ void update_hero_motion_for_current_state(void) { release_voice_slot_cf(0, (struct MobyView *)hero.moby, 0); } else { if (hero.grind_voice != -1) { - struct VoiceSlot *e = + struct VoiceSlot *grind_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + hero.grind_voice * 0x70); - if (e->pm88 == (struct MobyView *)hero.moby && e->b74 != 0) { + if (grind_voice_slot->pm88 == (struct MobyView *)hero.moby && grind_voice_slot->b74 != 0) { release_voice_slot(hero.grind_voice); } } @@ -2297,7 +2297,7 @@ void update_hero_motion_for_current_state(void) { } else { f32 grind_base_speed_target = D_0015ED6C_c * 12.0f; f32 tt; - f32 e; + f32 rail_ahead_pitch; f32 sp; s32 si; f32 sf; @@ -2343,20 +2343,20 @@ void update_hero_motion_for_current_state(void) { &sf, 0.3f, hero.rail_spline_loops); - e = fast_arc_tan(vector_distance_xy(&hero.rail_point, &vector_or_descriptor_scratch), + rail_ahead_pitch = fast_arc_tan(vector_distance_xy(&hero.rail_point, &vector_or_descriptor_scratch), vector_or_descriptor_scratch.f[2] - hero.rail_point.f[2]); - if (e > 0.0f) { - sp = e * 1.9098593f * (D_0015ED6C_c * -2.5f); - if (e > 0.2617994f && hero.grind_pose != 2 && hero.grind_pose != 3) { + if (rail_ahead_pitch > 0.0f) { + sp = rail_ahead_pitch * 1.9098593f * (D_0015ED6C_c * -2.5f); + if (rail_ahead_pitch > 0.2617994f && hero.grind_pose != 2 && hero.grind_pose != 3) { hero.grind_pose = 0; - } else if (e < 0.13962634f && hero.grind_pose == 0) { + } else if (rail_ahead_pitch < 0.13962634f && hero.grind_pose == 0) { hero.grind_pose = -1; } } else { - sp = -e * 2.864789f * (D_0015ED6C_c * 8.0f); - if (e < -0.19198622f && hero.grind_pose != 2 && hero.grind_pose != 3) { + sp = -rail_ahead_pitch * 2.864789f * (D_0015ED6C_c * 8.0f); + if (rail_ahead_pitch < -0.19198622f && hero.grind_pose != 2 && hero.grind_pose != 3) { hero.grind_pose = 1; - } else if (e > -0.12217305f && hero.grind_pose == 1) { + } else if (rail_ahead_pitch > -0.12217305f && hero.grind_pose == 1) { hero.grind_pose = -1; } } @@ -2618,9 +2618,9 @@ void update_hero_motion_for_current_state(void) { f32 sp; if (hero_slot_item_id(3) == 2) { if (hero.voice_slot4 != -1) { - struct VoiceSlot *e = + struct VoiceSlot *landing_item_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + hero.voice_slot4 * 0x70); - if (e->pm88 == (struct MobyView *)hero.moby && e->b74 != 0) { + if (landing_item_voice_slot->pm88 == (struct MobyView *)hero.moby && landing_item_voice_slot->b74 != 0) { release_voice_slot(hero.voice_slot4); } } @@ -2628,9 +2628,9 @@ void update_hero_motion_for_current_state(void) { release_voice_slot_cf(3, (struct MobyView *)hero.moby, 2); } else { if (hero.unk2224 != -1) { - struct VoiceSlot *e = + struct VoiceSlot *landing_entry4_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + hero.unk2224 * 0x70); - if (e->pm88 == (struct MobyView *)hero.moby && e->b74 != 0) { + if (landing_entry4_voice_slot->pm88 == (struct MobyView *)hero.moby && landing_entry4_voice_slot->b74 != 0) { release_voice_slot(hero.unk2224); } } From 8d97f46237343ed7c8cba33cf8dd4f5bc0554305 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:40:53 +0000 Subject: [PATCH 0172/1502] decomp: clarify names in update_giant_clank_missile a -> velocity_inheritance_frames_remaining: Bound source src/overlays/shared/vehicles/giant_clank_missile.c SHA-256 29123a1bfcffecb13b77a5a78acfdbe93fedabafde278b410fccb7222853758c converts missile_data->f3C after decrement, divides it by converted f3E, and scales D_0013F490 into up. The supplied spawn function initializes both fields to the same inheritance frame count. Retail 0x0029d7cc-0x0029d7e8 decrements +0x3c, converts its signed halfword into f20, converts +0x3e, and divides f20 by that result; 0x0029d7f4 applies this ratio to the inherited vector. Original Ghidra fVar19/fVar20 agrees. a -> intercept_quadratic_coefficient: In the target-leading block the authoritative C sets a = missile_data->speed * missile_data->speed - FUN_L00_001ff430(dv), then uses it in sqrt(b*b-a*4*c) and both intercept-time denominators a+a. Original Ghidra fVar20 has the same coefficient flow. Retail 0x0029d96c-0x0029d988 squares speed and subtracts the target-displacement squared length into f21; 0x0029d9a4-0x0029d9b8 uses it in the discriminant and doubles it for the two root divisions. This is the squared-time coefficient of the interception equation. b -> velocity_inheritance_frames_total: The authoritative source converts missile_data->f3E to this float denominator for a/b when scaling the inherited D_0013F490 vector. The supplied spawn function initializes f3E alongside countdown f3C to the same scaled frame count; only f3C is decremented here. Retail 0x0029d7dc-0x0029d7e8 loads signed data+0x3e, converts it, and divides the converted remaining +0x3c count by it before the vector-scale call at 0x0029d7f4. Original Ghidra fVar20 is that denominator. b -> intercept_linear_coefficient: The authoritative C computes b = -2*(dv[0]*delta[0]+dv[1]*delta[1]+dv[2]*delta[2]), squares it in the discriminant, and negates it in both intercept-time numerators. Retail 0x0029d948-0x0029d990 accumulates this dot product in f20 and multiplies by -2; 0x0029d9a0 squares it, and 0x0029d9b4-0x0029d9c0 negates it then adds/subtracts the discriminant root. Original Ghidra fVar24 agrees. This is the linear-time coefficient of the target-motion interception quadratic. --- .../shared/vehicles/giant_clank_missile.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/shared/vehicles/giant_clank_missile.c b/src/overlays/shared/vehicles/giant_clank_missile.c index cf15e22e91..a05dc277e9 100644 --- a/src/overlays/shared/vehicles/giant_clank_missile.c +++ b/src/overlays/shared/vehicles/giant_clank_missile.c @@ -305,9 +305,9 @@ void giant_clank_missile_update(M_29E8A0 *missile_moby) { missile_data->speed + (missile_data->speed_end - missile_data->speed) / 10.0f * D_0015ED64; fast_dec_timer_s16(&missile_data->f3C); { - float a = convert_integer_to_float(missile_data->f3C); - float b = convert_integer_to_float(missile_data->f3E); - fast_vec_scale(up, ((char *)&D_0013F490), a / b); + float velocity_inheritance_frames_remaining = convert_integer_to_float(missile_data->f3C); + float velocity_inheritance_frames_total = convert_integer_to_float(missile_data->f3E); + fast_vec_scale(up, ((char *)&D_0013F490), velocity_inheritance_frames_remaining / velocity_inheritance_frames_total); } { float delta[4]; @@ -336,18 +336,18 @@ void giant_clank_missile_update(M_29E8A0 *missile_moby) { tp[2] = tp[2] + missile_data->zoff; fast_vec_sub(delta, tp, missile_moby->pos); if (missile_data->f38 != 0) { - float a, b, c, intercept_time_plus_root, intercept_time_minus_root, + float intercept_quadratic_coefficient, intercept_linear_coefficient, c, intercept_time_plus_root, intercept_time_minus_root, discriminant_sqrt; fast_vec_sub(dv, tp, missile_data->v); FUN_L00_001ff2c0(ip, dv, up); qcopy(missile_data->v, tp); c = FUN_L00_001ff430(dv); - b = (dv[0] * delta[0] + dv[1] * delta[1] + dv[2] * delta[2]) * -2.0f; - a = missile_data->speed * missile_data->speed - c; + intercept_linear_coefficient = (dv[0] * delta[0] + dv[1] * delta[1] + dv[2] * delta[2]) * -2.0f; + intercept_quadratic_coefficient = missile_data->speed * missile_data->speed - c; c = -FUN_L00_001ff430(delta); - discriminant_sqrt = square_root(b * b - a * 4.0f * c); - intercept_time_plus_root = (-b + discriminant_sqrt) / (a + a); - intercept_time_minus_root = (-b - discriminant_sqrt) / (a + a); + discriminant_sqrt = square_root(intercept_linear_coefficient * intercept_linear_coefficient - intercept_quadratic_coefficient * 4.0f * c); + intercept_time_plus_root = (-intercept_linear_coefficient + discriminant_sqrt) / (intercept_quadratic_coefficient + intercept_quadratic_coefficient); + intercept_time_minus_root = (-intercept_linear_coefficient - discriminant_sqrt) / (intercept_quadratic_coefficient + intercept_quadratic_coefficient); if (intercept_time_plus_root > 0.0f && intercept_time_minus_root > 0.0f) { if (intercept_time_minus_root < intercept_time_plus_root) intercept_time = intercept_time_plus_root; From 29437a57852ab3c2524f0e4e6587d80a6d07951f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:40:53 +0000 Subject: [PATCH 0173/1502] decomp: clarify names in update_hero_motion_by_state e -> grind_voice_slot: In the grouped grind case, this VoiceSlot pointer is voice_pool + hero.grind_voice * 0x70. Retail 0x0022c418-0x0022c454 loads the grind voice index, multiplies by 0x70, checks slot+0x88 against hero.moby and slot+0x74 before releasing that index; original Ghidra case 0x28/0x29/0x2a/0x2b/0x42 agrees. e -> rail_lookahead_slope_angle: This f32 receives fast_arc_tan(horizontal distance from hero.rail_point to the path sample, sample Z minus rail_point Z), after sample_path advances a copy of the rail segment/fraction by 0.3. Retail 0x0022d120-0x0022d178 computes this angle in f5; 0x0022d17c-0x0022d2ac uses its sign and angular thresholds for slope speed adjustment and grind pose, matching original Ghidra. e -> landing_voice_slot: In HERO_STATE_LAND when hero_slot_item_id(3)==2, this VoiceSlot pointer is voice_pool + hero.voice_slot4 * 0x70. Retail 0x0022dde4-0x0022de24 checks the index at hero+0x2228, slot ownership at +0x88 and activity byte +0x74 before release_voice_slot; original Ghidra case 8 corroborates the same indexed voice-pool entry. e -> alternate_landing_voice_slot: In the alternate HERO_STATE_LAND branch, this VoiceSlot pointer is voice_pool + hero.unk2224 * 0x70. Retail 0x0022de4c-0x0022de8c loads hero+0x2224, derives the pool entry with stride 0x70, checks entry+0x88 against hero.moby and byte +0x74 before releasing the same index. Original Ghidra case 8 shows this separate alternative voice-slot release. --- .../l14/hero/update_hero_motion_by_state.c | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/overlays/l14/hero/update_hero_motion_by_state.c b/src/overlays/l14/hero/update_hero_motion_by_state.c index 48ce2c021f..9dfb42bb3e 100644 --- a/src/overlays/l14/hero/update_hero_motion_by_state.c +++ b/src/overlays/l14/hero/update_hero_motion_by_state.c @@ -1643,9 +1643,9 @@ void update_hero_motion_by_state(void) { release_voice_slot_cf(0, MV(hero.moby), 0); } else { if (hero.grind_voice != -1) { - struct VoiceSlot *e = + struct VoiceSlot *grind_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + hero.grind_voice * 0x70); - if (e->pm88 == MV(hero.moby) && e->b74 != 0) { + if (grind_voice_slot->pm88 == MV(hero.moby) && grind_voice_slot->b74 != 0) { release_voice_slot(hero.grind_voice); } } @@ -1906,7 +1906,7 @@ void update_hero_motion_by_state(void) { } else { f32 base_grind_speed_target = frame_time * 12.0f; f32 tt; - f32 e; + f32 rail_lookahead_slope_angle; f32 sp; s32 si; f32 sf; @@ -1952,21 +1952,21 @@ void update_hero_motion_by_state(void) { &sf, 0.3f, hero.rail_spline_loops); - e = fast_arc_tan( + rail_lookahead_slope_angle = fast_arc_tan( vector_distance_xy(&hero.rail_point, &vector_and_hit_descriptor_scratch), vector_and_hit_descriptor_scratch.f[2] - hero.rail_point.f[2]); - if (e > 0.0f) { - sp = e * 1.9098593f * (frame_time * -2.5f); - if (e > 0.2617994f && hero.grind_pose != 2 && hero.grind_pose != 3) { + if (rail_lookahead_slope_angle > 0.0f) { + sp = rail_lookahead_slope_angle * 1.9098593f * (frame_time * -2.5f); + if (rail_lookahead_slope_angle > 0.2617994f && hero.grind_pose != 2 && hero.grind_pose != 3) { hero.grind_pose = 0; - } else if (e < 0.13962634f && hero.grind_pose == 0) { + } else if (rail_lookahead_slope_angle < 0.13962634f && hero.grind_pose == 0) { hero.grind_pose = -1; } } else { - sp = -e * 2.864789f * (frame_time * 8.0f); - if (e < -0.19198622f && hero.grind_pose != 2 && hero.grind_pose != 3) { + sp = -rail_lookahead_slope_angle * 2.864789f * (frame_time * 8.0f); + if (rail_lookahead_slope_angle < -0.19198622f && hero.grind_pose != 2 && hero.grind_pose != 3) { hero.grind_pose = 1; - } else if (e > -0.12217305f && hero.grind_pose == 1) { + } else if (rail_lookahead_slope_angle > -0.12217305f && hero.grind_pose == 1) { hero.grind_pose = -1; } } @@ -2226,9 +2226,9 @@ void update_hero_motion_by_state(void) { f32 sp; if (hero_slot_item_id(3) == 2) { if (hero.voice_slot4 != -1) { - struct VoiceSlot *e = + struct VoiceSlot *landing_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + hero.voice_slot4 * 0x70); - if (e->pm88 == MV(hero.moby) && e->b74 != 0) { + if (landing_voice_slot->pm88 == MV(hero.moby) && landing_voice_slot->b74 != 0) { release_voice_slot(hero.voice_slot4); } } @@ -2236,9 +2236,9 @@ void update_hero_motion_by_state(void) { release_voice_slot_cf(3, MV(hero.moby), 2); } else { if (hero.unk2224 != -1) { - struct VoiceSlot *e = + struct VoiceSlot *alternate_landing_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + hero.unk2224 * 0x70); - if (e->pm88 == MV(hero.moby) && e->b74 != 0) { + if (alternate_landing_voice_slot->pm88 == MV(hero.moby) && alternate_landing_voice_slot->b74 != 0) { release_voice_slot(hero.unk2224); } } From 1dcead59ae53977e7f649dafbcb24c8f743c9987 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:44:27 +0000 Subject: [PATCH 0174/1502] decomp: clarify names in hud_draw_gauge_frame pos -> screen_position: In the bound C, int pos[2] receives gauge_element->unk50/unk54, is passed by component address to hud_screen_position and apply_hud_slide_offset, then supplies the rectangle and sprite coordinates. Retail 0x00237888-0x00237894 copies record +0x50/+0x54 to stack +0/+4; 0x0023789c and 0x002378b4 pass those addresses to the coordinate helpers. At 0x0023790c-0x00237924 and 0x00237aa0-0x00237ab8 the adjusted pair is combined with +0x48/+0x4A for drawing. The supplied hud_screen_position implementation adjusts x/y using dimensions and alignment flags, proving this is the mutable screen-position pair. --- .../ui/hud/draw_hud_item_selector_panel.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c index 4a5fb183e8..33bf659d50 100644 --- a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c +++ b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c @@ -72,12 +72,12 @@ extern void append_screen_rect_packet(s32, s32, s32, s32, u64, s32) __asm__("fun int hud_draw_gauge_frame(HudElem_237840 *e) __asm__("FUN_L00_00237840"); int hud_draw_gauge_frame(HudElem_237840 *gauge_element) { - int pos[2]; + int screen_position[2]; int left, top, right, bottom, w, h, bh, step, i; { int ww = D_L00_0015F760; - pos[0] = gauge_element->unk50; - pos[1] = gauge_element->unk54; + screen_position[0] = gauge_element->unk50; + screen_position[1] = gauge_element->unk54; gauge_element->w = ww; { int *src = (int *)&(*(short *)&D_L00_0015F764); @@ -85,14 +85,14 @@ int hud_draw_gauge_frame(HudElem_237840 *gauge_element) { __builtin_memcpy(dst, src, 4); } } - hud_screen_position(gauge_element, &pos[0], &pos[1]); - apply_hud_slide_offset(gauge_element, &pos[0], &pos[1], gauge_element->unk6C, 0); + hud_screen_position(gauge_element, &screen_position[0], &screen_position[1]); + apply_hud_slide_offset(gauge_element, &screen_position[0], &screen_position[1], gauge_element->unk6C, 0); w = D_L00_0015F760 * 0xD0; h = D_L00_0015F764 * 0xA0; bh = D_L00_0015F760 * 0x260; bottom = D_L00_0015F764 * 0xEA0; - left = (pos[0] + gauge_element->unk48) << 4; - top = (pos[1] + gauge_element->unk4A) << 4; + left = (screen_position[0] + gauge_element->unk48) << 4; + top = (screen_position[1] + gauge_element->unk4A) << 4; left += w / 64; top += h / 256; right = left + bh / 64; @@ -101,7 +101,7 @@ int hud_draw_gauge_frame(HudElem_237840 *gauge_element) { { int gauge_height_numerator = D_L00_0015F764 * 0xEA0; h = D_L00_0015F764; - top = (pos[1] + gauge_element->unk4A) << 4; + top = (screen_position[1] + gauge_element->unk4A) << 4; top += (h * 0xF40) / 256; bh = (gauge_element->unk74 * gauge_height_numerator) / (gauge_element->unk08 << 8); append_screen_rect_packet(left, top, right, top - bh, 0x80829E00, 1); @@ -110,7 +110,7 @@ int hud_draw_gauge_frame(HudElem_237840 *gauge_element) { if (i < gauge_element->unk74) do { int hh = D_L00_0015F764; - top = (pos[1] + gauge_element->unk4A) << 4; + top = (screen_position[1] + gauge_element->unk4A) << 4; top += (hh * 0xF40) / 256; step = D_L00_0015F764 * 0xEA0; step = i * step / (gauge_element->unk08 << 8); @@ -121,7 +121,7 @@ int hud_draw_gauge_frame(HudElem_237840 *gauge_element) { } while (i < gauge_element->unk74); w = get_icon_frame(*(int *)gauge_element, 0); draw_rotated_hud_sprite( - w, pos[0] + gauge_element->unk48, pos[1] + gauge_element->unk4A, D_L00_0015F760, D_L00_0015F764, 0x80); + w, screen_position[0] + gauge_element->unk48, screen_position[1] + gauge_element->unk4A, D_L00_0015F760, D_L00_0015F764, 0x80); return gauge_element->w; } From c304022e96c8023f5c213ad2f4f50d2e3124eef3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:47:57 +0000 Subject: [PATCH 0175/1502] decomp: clarify names in floor_button_update D_L05_001BB6B0 -> l05_mission_gated_moby_save_flags: The authoritative declaration is extern SaveFlags D_L05_001BB6B0, whose collected bytes begin at +0x454. Retail 0x0030c600 forms base 0x001BB6B0; 0x0030c608-0x0030c620 sign-extends moby->save_id (+0xB2) and reads collected[id], with a nonzero byte selecting disabled state 2 at 0x0030c690. On grounded hero contact the separate 0x001BAA50 object is always written at 0x0030c808, while this object is written only after the mission (+0xB0) equals 0xFF or the mission lookup and current-level slot checks at 0x0030c810-0x0030c848 permit it. 0x0030c850-0x0030c864 stores mission+2 into 0x001BB6B0+0x454+save_id. This proves mission-gated moby save flags; l05 qualifies the assigned overlay binding. --- src/overlays/shared/props/floor_button.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/props/floor_button.c b/src/overlays/shared/props/floor_button.c index 6f302231a9..9b2c1ef5a2 100644 --- a/src/overlays/shared/props/floor_button.c +++ b/src/overlays/shared/props/floor_button.c @@ -16,7 +16,7 @@ typedef struct { u8 collected[1]; } SaveFlags; -extern SaveFlags D_L05_001BB6B0; +extern SaveFlags l05_mission_gated_moby_save_flags __asm__("D_L05_001BB6B0"); extern SaveFlags l05_moby_save_flags __asm__("D_L05_001BAA50"); extern unsigned char D_L05_0015FC88[] MACRO_ADDR; @@ -45,7 +45,7 @@ void floor_button_update(struct Moby *moby) { *(f32 *)(floor_button_private_state + 3) = random_angle_radians(); moby->pos.z -= 0.35f; id = (s16)moby->save_id; - if (D_L05_001BB6B0.collected[id] != 0 || + if (l05_mission_gated_moby_save_flags.collected[id] != 0 || (D_0014C190_257218[current_level_index][id >> 5] >> (moby->save_id & 31) & 1) != 0 || (floor_button_private_state[2] != 0 && D_0014C050[moby->mission + current_level_index * 16] == 0xFF)) { moby->command = 2; @@ -84,7 +84,7 @@ void floor_button_update(struct Moby *moby) { if (moby->mission == 0xFF || (D_L05_0015FC88[moby->mission] != 0xFF && D_0014C050[moby->mission + current_level_index * 16] == 0xFF)) { - D_L05_001BB6B0.collected[(s16)moby->save_id] = moby->mission + 2; + l05_mission_gated_moby_save_flags.collected[(s16)moby->save_id] = moby->mission + 2; } moby->state = 2; moby->command = 1; From 25f927de0dc8eecbb93b4bc618f0ce1121c7fda1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:47:57 +0000 Subject: [PATCH 0176/1502] decomp: clarify names in move_moby_xy_with_collision_constraints a -> line_probe_start: Retail 0x002585a4-0x002585bc builds sp+0x20 as current position plus a vector whose Z is h; 0x002585d8-0x002585e8 passes this vector as the first endpoint of the collision line. ang -> sphere_contact_angle: Retail 0x002586f0-0x00258708 computes fast_arc_tan of XY distance to the sphere contact position and contact Z minus proposed Z. 0x00258718 compares that angle with slope to decide whether to copy the corrected collision position. b -> line_probe_end: Retail 0x002585c0-0x002585d0 builds sp+0x30 by adding the radius-scaled movement direction to the raised line start; 0x002585dc-0x002585e8 passes it as the second collision-line endpoint. c -> line_collision_result: Retail 0x002585f8 binds s0 to D_L00_00173E40 after the collision-line call, tests result+0x1c, and reads/updates its normal at +0x40 through +0x48 for wall sliding at 0x00258608-0x00258684. d -> movement_displacement: Retail 0x00258570-0x0025857c subtracts current position s4 from proposed position s1 into sp; 0x00258638-0x00258684 removes its inward horizontal normal component before adding it back to current position. h -> collision_height_offset: Retail 0x002584fc-0x00258518 adds f21 to proposed Z around the ground probe then subtracts it; 0x002585a8-0x002585bc also uses it as the vertical offset of the line start. The wander caller names this argument collision_height_offset. lim -> ground_height_difference_limit: Retail 0x00258520-0x00258528 and 0x0025877c-0x00258784 compare f24 against absolute ground-probe height minus current position Z. The supplied wander caller labels this argument ground_height_difference_limit. m2 -> line_collision_flag_bit_2: Retail 0x002584b4 saves flags & 2 in s5; 0x002585e0 ORs it with 0x24 and passes it as the line-collision flags. This names the demonstrated bit use without assuming its engine meaning. n -> line_probe_displacement: Retail 0x0025858c-0x0025859c normalizes movement displacement into sp+0x10 to radius times 1.2; 0x002585c0-0x002585d0 adds that vector to the raised line start to produce the line end. pos -> proposed_position: Retail s1 receives a2 at 0x002584c4, is probed and collision-corrected, and supplies X/Y committed to s4 at 0x002587d8/0x002587e8. The wander caller passes its proposed_position vector in this argument. q40 -> sphere_collision_result: Retail 0x002586ac-0x002586b4 computes s3 as D_L00_00173E60 minus 0x20, the D_L00_00173E40 result base. After sphere checks, +0x28 supplies contact Z and +0x18 controls correction at 0x002586f8-0x00258710. q60 -> sphere_contact_position: Retail 0x002586ac sets s5 to D_L00_00173E60; 0x002586f0-0x002586f4 uses it in XY distance from proposed position, while result-base+0x28 supplies the corresponding contact Z to the angle calculation. r -> collision_radius: Retail f22 scales the line-probe displacement by 1.2 at 0x00258598-0x0025859c and is passed as the sphere radius at 0x002586d0-0x002586e0; source also adds r to h to place the sphere center above the position. t -> sphere_probe_center: Retail 0x002586c0-0x002586e4 copies proposed position to sp+0x50, raises its Z by h+r, and passes that vector with radius r to FUN_L00_001f0d60 for each of up to six sphere checks. --- .../shared/math/interpolation/spring_turn.c | 96 +++++++++---------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/src/overlays/shared/math/interpolation/spring_turn.c b/src/overlays/shared/math/interpolation/spring_turn.c index 9ef4ddd938..f2847b12f2 100644 --- a/src/overlays/shared/math/interpolation/spring_turn.c +++ b/src/overlays/shared/math/interpolation/spring_turn.c @@ -198,91 +198,91 @@ int move_moby_xy_with_collision_constraints( int move_moby_xy_with_collision_constraints( - void *ign, V_258490 *to, V_258490 *pos, int flags, float h, float r, float lim, float slope) { - V_258490 d; - V_258490 n; - V_258490 a; - V_258490 b; + void *ign, V_258490 *to, V_258490 *proposed_position, int flags, float collision_height_offset, float collision_radius, float ground_height_difference_limit, float slope) { + V_258490 movement_displacement; + V_258490 line_probe_displacement; + V_258490 line_probe_start; + V_258490 line_probe_end; V_258490 up; - V_258490 t; + V_258490 sphere_probe_center; int ok; int i; - int m2; + int line_collision_flag_bit_2; float gz; float zz; - float ang; - unsigned char *c; + float sphere_contact_angle; + unsigned char *line_collision_result; float *nrm; - unsigned char *q60; - unsigned char *q40; + unsigned char *sphere_contact_position; + unsigned char *sphere_collision_result; ok = 1; - m2 = flags & 2; - pos->f[2] += h; - gz = allocate_voice_for_target_entry_cf(pos); - pos->f[2] -= h; - if (lim < absolute_float(gz - to->f[2])) { + line_collision_flag_bit_2 = flags & 2; + proposed_position->f[2] += collision_height_offset; + gz = allocate_voice_for_target_entry_cf(proposed_position); + proposed_position->f[2] -= collision_height_offset; + if (ground_height_difference_limit < absolute_float(gz - to->f[2])) { if ((((flags ^ 1) & 1) && gz < to->f[2]) || to->f[2] < gz) { - qcopy(pos, to); + qcopy(proposed_position, to); ok = 0; } } - fast_vec_sub(&d, pos, to); - fast_vec_normalize(&n, &d, r * 1.2f); + fast_vec_sub(&movement_displacement, proposed_position, to); + fast_vec_normalize(&line_probe_displacement, &movement_displacement, collision_radius * 1.2f); up.q = 0; - up.f[2] = h; - fast_vec_add(&a, to, &up); - fast_vec_add(&b, &a, &n); - if (ok && FUN_001efa68_258490(&a, &b, m2 | 0x24, ign, 0)) { - c = D_L00_00173E40_258490; - if (*(int *)(c + 0x1C) > 0) { - nrm = (float *)(c + 0x40); - if (slope <= fast_arc_tan(*(float *)(c + 0x48), vector_length_xy(nrm))) { - *(int *)(c + 0x48) = 0; + up.f[2] = collision_height_offset; + fast_vec_add(&line_probe_start, to, &up); + fast_vec_add(&line_probe_end, &line_probe_start, &line_probe_displacement); + if (ok && FUN_001efa68_258490(&line_probe_start, &line_probe_end, line_collision_flag_bit_2 | 0x24, ign, 0)) { + line_collision_result = D_L00_00173E40_258490; + if (*(int *)(line_collision_result + 0x1C) > 0) { + nrm = (float *)(line_collision_result + 0x40); + if (slope <= fast_arc_tan(*(float *)(line_collision_result + 0x48), vector_length_xy(nrm))) { + *(int *)(line_collision_result + 0x48) = 0; sceVu0Normalize(nrm, nrm); { - float k = -d.f[0] * *(float *)(c + 0x40) - d.f[1] * *(float *)(c + 0x44); + float k = -movement_displacement.f[0] * *(float *)(line_collision_result + 0x40) - movement_displacement.f[1] * *(float *)(line_collision_result + 0x44); if (0.0f < k) { fast_vec_scale(nrm, nrm, k); ok = 0; - fast_vec_add(&d, &d, nrm); + fast_vec_add(&movement_displacement, &movement_displacement, nrm); } } } - fast_vec_add(pos, to, &d); + fast_vec_add(proposed_position, to, &movement_displacement); } } if (!(flags & 2)) { - zz = h + r; - q60 = (unsigned char *)&D_L00_00173E60_lui; - q40 = q60 - 0x20; + zz = collision_height_offset + collision_radius; + sphere_contact_position = (unsigned char *)&D_L00_00173E60_lui; + sphere_collision_result = sphere_contact_position - 0x20; i = 0; do { - qcopy(&t, pos); - t.f[2] += zz; - if (!FUN_L00_001f0d60_258490(&t, r, 0x24, ign)) { + qcopy(&sphere_probe_center, proposed_position); + sphere_probe_center.f[2] += zz; + if (!FUN_L00_001f0d60_258490(&sphere_probe_center, collision_radius, 0x24, ign)) { break; } - ang = fast_arc_tan(vector_distance_xy(pos, q60), *(float *)(q40 + 0x28) - pos->f[2]); - if (*(int *)(q40 + 0x18) != 0 || slope < ang) { - qcopy(pos, &coll_hit_position); + sphere_contact_angle = fast_arc_tan(vector_distance_xy(proposed_position, sphere_contact_position), *(float *)(sphere_collision_result + 0x28) - proposed_position->f[2]); + if (*(int *)(sphere_collision_result + 0x18) != 0 || slope < sphere_contact_angle) { + qcopy(proposed_position, &coll_hit_position); ok = 0; - pos->f[2] -= zz; + proposed_position->f[2] -= zz; } i++; } while (i < 6); } - pos->f[2] += h; - gz = allocate_voice_for_target_entry_cf(pos); - pos->f[2] -= h; - if (lim < absolute_float(gz - to->f[2])) { + proposed_position->f[2] += collision_height_offset; + gz = allocate_voice_for_target_entry_cf(proposed_position); + proposed_position->f[2] -= collision_height_offset; + if (ground_height_difference_limit < absolute_float(gz - to->f[2])) { if ((((flags ^ 1) & 1) && gz < to->f[2]) || to->f[2] < gz) { - qcopy(pos, to); + qcopy(proposed_position, to); ok = 0; } } - to->f[0] = pos->f[0]; - to->f[1] = pos->f[1]; + to->f[0] = proposed_position->f[0]; + to->f[1] = proposed_position->f[1]; return ok; } From cbce3007011b4d7c8bb56b031b9261f13a721153 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:51:16 +0000 Subject: [PATCH 0177/1502] decomp: clarify names in sentrybot_update o -> linked_alarm_moby: The first o in SENTRYBOT_ALERT_IDLE resolves instance data+0x128 as a moby-array index when hero state is 0x65. Retail 0x0029920c-0x00299238 and original Ghidra case 0xc form the pointer using index*0x100, inspect its pvars+8, then pass it as a0 to set_sentrybot_alarm_duration with -1. o -> linked_alarm_moby: The second o in SENTRYBOT_ALERT_IDLE is the data+0x128 linked moby resolved after timer data+0x156 expires. Retail 0x002992a4-0x002992dc and original Ghidra LAB_00299278 form index*0x100 plus moby array, inspect pvars+8 and pass the resulting pointer to set_sentrybot_alarm_duration with scale_game_frames(0x1e). o -> linked_alarm_moby: In SENTRYBOT_PATROL_MOVE_FAST, source resolves data+0x128 to a char * moby and passes it to set_sentrybot_alarm_duration with scale_game_frames(0x1e). Original Ghidra case 0xd shares LAB_00299278; retail 0x002992a4-0x002992dc shifts that index by 8, adds the moby array, checks pvars+8 and supplies the resulting s0 as the alarm helper's a0. o -> linked_alarm_moby: Before the state switch, retail 0x00297b98-0x00297ba8 loads instance data+0x128, shifts the index by 8 and adds the moby array. 0x00297bac-0x00297bc0 tests this moby's pvars+8 and passes the resolved pointer to set_sentrybot_alarm_duration with 0xb4. Original Ghidra iVar12 and authoritative char *o agree. --- src/overlays/shared/enemies/sentrybot.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/overlays/shared/enemies/sentrybot.c b/src/overlays/shared/enemies/sentrybot.c index 6a4ad0f9f7..abd2245e25 100644 --- a/src/overlays/shared/enemies/sentrybot.c +++ b/src/overlays/shared/enemies/sentrybot.c @@ -337,9 +337,9 @@ void sentrybot_update(unsigned char *moby) { fast_dec_timer_s16(&sentrybot_instance_data->attention_timer); if (sentrybot_instance_data->alert_timer != 0 && sentrybot_instance_data->alarm_moby_index != -1) { - char *o = (char *)((sentrybot_instance_data->alarm_moby_index << 8) + (int)l15_moby_array); - if (*(int *)(*(char **)(o + 0x78) + 8) != 0) - set_sentrybot_alarm_duration(o, 0xB4); + char *linked_alarm_moby = (char *)((sentrybot_instance_data->alarm_moby_index << 8) + (int)l15_moby_array); + if (*(int *)(*(char **)(linked_alarm_moby + 0x78) + 8) != 0) + set_sentrybot_alarm_duration(linked_alarm_moby, 0xB4); } if (MOBY(moby)->command == 0) sentrybot_instance_data->unk15F = 0; @@ -706,10 +706,10 @@ void sentrybot_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 0xD) blend_moby_animation(moby, 0xD, 0, scale_game_frames(10)); if (sentrybot_instance_data->alarm_moby_index != -1) { - char *o = (char *)((sentrybot_instance_data->alarm_moby_index << 8) + + char *linked_alarm_moby = (char *)((sentrybot_instance_data->alarm_moby_index << 8) + (int)l15_moby_array); - if (*(int *)(*(char **)(o + 0x78) + 8) != 0) - set_sentrybot_alarm_duration(o, scale_game_frames(0x1E)); + if (*(int *)(*(char **)(linked_alarm_moby + 0x78) + 8) != 0) + set_sentrybot_alarm_duration(linked_alarm_moby, scale_game_frames(0x1E)); } } break; @@ -1024,10 +1024,10 @@ void sentrybot_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 0xD) blend_moby_animation(moby, 0xD, 0, scale_game_frames(10)); if (sentrybot_instance_data->alarm_moby_index != -1) { - char *o = (char *)((sentrybot_instance_data->alarm_moby_index << 8) + + char *linked_alarm_moby = (char *)((sentrybot_instance_data->alarm_moby_index << 8) + (int)l15_moby_array); - if (*(int *)(*(char **)(o + 0x78) + 8) != 0) - set_sentrybot_alarm_duration(o, -1); + if (*(int *)(*(char **)(linked_alarm_moby + 0x78) + 8) != 0) + set_sentrybot_alarm_duration(linked_alarm_moby, -1); } } else { int mode = sentrybot_instance_data->unk114; @@ -1042,10 +1042,10 @@ void sentrybot_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 0xD) blend_moby_animation(moby, 0xD, 0, scale_game_frames(10)); if (sentrybot_instance_data->alarm_moby_index != -1) { - char *o = (char *)((sentrybot_instance_data->alarm_moby_index << 8) + + char *linked_alarm_moby = (char *)((sentrybot_instance_data->alarm_moby_index << 8) + (int)l15_moby_array); - if (*(int *)(*(char **)(o + 0x78) + 8) != 0) - set_sentrybot_alarm_duration(o, scale_game_frames(0x1E)); + if (*(int *)(*(char **)(linked_alarm_moby + 0x78) + 8) != 0) + set_sentrybot_alarm_duration(linked_alarm_moby, scale_game_frames(0x1E)); } } else if (sentrybot_instance_data->has_line_of_sight != 0) { if (mode != 2 && sentrybot_instance_data->unk15B == 0) { From 58930e3674b324f73d694a4bcb5cb64dc1b8b78e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:54:57 +0000 Subject: [PATCH 0178/1502] decomp: clarify names in process_horny_toad_hit_reaction D_L00_00161988_gp -> l00_horny_toad_knockback_landing_animation_frame: Assigned retail 0x002d530c/0x002d531c copies D_L00_00161988 to toad_vars+0xC4 = motion state+0x54. Checked caller 0x002d5020 passes toad_vars+0x70 to step_moby_motion 0x0025c698. In descending phase (state+0x3E==1, selected at 0x0025c9c4-0x0025c9cc; entered on negative Z velocity at 0x0025ce9c-0x0025ceb8), 0x0025ca60-0x0025ca78 stops animation speed at moby+0x58 when this frame target is reached. Otherwise 0x0025ca7c-0x0025caf8 estimates time to ground from gravity, vertical velocity and height; 0x0025cb04-0x0025cb60 divides target minus current animation position by that time to approach animation speed. Current position helper 0x0024edc8 reads animation records at moby+0x68/+0x6C, converts their signed +4 frame values by 1/16 and incorporates moby+0x54 interpolation. Thus this is the landing animation frame target, not an animation speed or rate. D_L00_0016198C_gp -> l00_horny_toad_knockback_apex_animation_frame: Assigned retail 0x002d5304/0x002d5314 copies D_L00_0016198C to toad_vars+0xC0 = motion state+0x50. Checked common caller 0x002d5020 passes this motion state to step_moby_motion 0x0025c698. While motion phase+0x3E is zero (0x0025c9dc), 0x0025c9fc-0x0025ca24 computes the absolute Z-velocity/gravity ratio, the remaining ascent time to the apex. At 0x0025ca28-0x0025ca3c the helper's current animation position is subtracted from motion+0x50 and divided by that ascent time; the positive quotient drives moby animation speed+0x58 via 0x0025cb54-0x0025cb64. Phase switches from zero to one when Z velocity becomes negative at 0x0025ce9c-0x0025ceb8. Current-position helper 0x0024edc8 reads animation records+4 with 1/16 scaling and moby interpolation+0x54. This proves an animation frame target for the knockback apex. --- src/overlays/shared/enemies/horny_toad.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/enemies/horny_toad.c b/src/overlays/shared/enemies/horny_toad.c index 7e8cc98c15..b368164099 100644 --- a/src/overlays/shared/enemies/horny_toad.c +++ b/src/overlays/shared/enemies/horny_toad.c @@ -141,8 +141,8 @@ extern f32 l00_horny_toad_knockback_gravity __asm__("D_L00_00161970") extern f32 l00_horny_toad_knockback_horizontal_deceleration __asm__("D_L00_00161974") __attribute__((sda)); extern f32 l00_horny_toad_knockback_horizontal_speed __asm__("D_L00_00161978") __attribute__((sda)); extern f32 l00_horny_toad_knockback_vertical_speed __asm__("D_L00_0016197C") __attribute__((sda)); -extern f32 D_L00_00161988_gp __asm__("D_L00_00161988") __attribute__((sda)); -extern f32 D_L00_0016198C_gp __asm__("D_L00_0016198C") __attribute__((sda)); +extern f32 l00_horny_toad_knockback_landing_animation_frame __asm__("D_L00_00161988") __attribute__((sda)); +extern f32 l00_horny_toad_knockback_apex_animation_frame __asm__("D_L00_0016198C") __attribute__((sda)); extern unsigned char *D_L00_001B04B0_2d5160[] __asm__("D_L00_001B04B0"); extern void hit_reaction(void *, void *, void *, s32, s32 *, f32 *, s32, s32) __asm__("FUN_L00_0025a478"); @@ -513,8 +513,8 @@ void process_horny_toad_hit_reaction(unsigned char *toad_moby) { trooper_knockback_arc(hit_knockback_vector, &angle, toad_vars + 0x88, toad_vars + 0x8C); trooper_start_knockback( toad_moby, toad_vars + 0x70, angle, FUN_L00_00257b50_2d5160(2) + 6, 1, 0); - reactionC0 = D_L00_0016198C_gp; - reactionC4 = D_L00_00161988_gp; + reactionC0 = l00_horny_toad_knockback_apex_animation_frame; + reactionC4 = l00_horny_toad_knockback_landing_animation_frame; *(f32 *)(toad_vars + 0xC0) = reactionC0; *(f32 *)(toad_vars + 0xC4) = reactionC4; MOBY(toad_moby)->state = 12; From 322735bd6c61f4eecfe8a89d949b97e7c0737ec1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:55:11 +0000 Subject: [PATCH 0179/1502] decomp: clarify names in homing_spark_draw D_L18_00161EE4 -> l18_homing_spark_blend_minuend_selector: Retail 0x002ea438 reads D_L18_00161EE4 via gp-0x4d1c; 0x002ea444-0x002ea470 ORs it unshifted into each quad's packet+0x88, the ALPHA A field selecting the color minuend in (A-B)*C+D. The checked level-18 draw helper at 0x00206420 loads packet+0x88 and 0x00206424-0x0020643c emits it as an A+D write to GS register 0x42 (ALPHA). This identifies the packed A/B/C/D alpha-blend selectors, rather than arbitrary draw flags. D_L18_00161EE8 -> l18_homing_spark_blend_subtrahend_selector: Retail 0x002ea418 reads D_L18_00161EE8 via gp-0x4d18 and 0x002ea428 shifts it left 2 before the OR/store at 0x002ea444-0x002ea470. This supplies ALPHA B, the color subtrahend selector in (A-B)*C+D. The checked level-18 draw helper at 0x00206420 loads packet+0x88 and 0x00206424-0x0020643c emits it as an A+D write to GS register 0x42 (ALPHA). This identifies the packed A/B/C/D alpha-blend selectors, rather than arbitrary draw flags. D_L18_00161EEC -> l18_homing_spark_blend_alpha_factor_selector: Retail 0x002ea424 reads D_L18_00161EEC via gp-0x4d14 and 0x002ea434 shifts it left 4 before the OR/store at 0x002ea44c-0x002ea470. This supplies ALPHA C, the alpha multiplication-factor selector in (A-B)*C+D. The checked level-18 draw helper at 0x00206420 loads packet+0x88 and 0x00206424-0x0020643c emits it as an A+D write to GS register 0x42 (ALPHA). This identifies the packed A/B/C/D alpha-blend selectors, rather than arbitrary draw flags. D_L18_00161EF0 -> l18_homing_spark_blend_addend_selector: Retail 0x002ea420 reads D_L18_00161EF0 via gp-0x4d10 and 0x002ea42c shifts it left 6 before the OR/store at 0x002ea464-0x002ea470. This supplies ALPHA D, the color addend selector in (A-B)*C+D. The checked level-18 draw helper at 0x00206420 loads packet+0x88 and 0x00206424-0x0020643c emits it as an A+D write to GS register 0x42 (ALPHA). This identifies the packed A/B/C/D alpha-blend selectors, rather than arbitrary draw flags. --- src/overlays/l18/mobys/drek_boss_electric_ball.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l18/mobys/drek_boss_electric_ball.c b/src/overlays/l18/mobys/drek_boss_electric_ball.c index bd3f471ca1..b732da847a 100644 --- a/src/overlays/l18/mobys/drek_boss_electric_ball.c +++ b/src/overlays/l18/mobys/drek_boss_electric_ball.c @@ -201,10 +201,10 @@ float homing_spark_quad_vertices[4][4][4] __asm__("D_L18_001D9B70") = { extern s32 fast_tween_color_c(s32, s32, f32) __asm__("func_001FA6E0"); extern s64 get_effect_texture_c(s32) __asm__("func_001F44B8"); -extern int D_L18_00161EE4 __attribute__((sda)); -extern int D_L18_00161EE8 __attribute__((sda)); -extern int D_L18_00161EEC __attribute__((sda)); -extern int D_L18_00161EF0 __attribute__((sda)); +extern int l18_homing_spark_blend_minuend_selector __asm__("D_L18_00161EE4") __attribute__((sda)); +extern int l18_homing_spark_blend_subtrahend_selector __asm__("D_L18_00161EE8") __attribute__((sda)); +extern int l18_homing_spark_blend_alpha_factor_selector __asm__("D_L18_00161EEC") __attribute__((sda)); +extern int l18_homing_spark_blend_addend_selector __asm__("D_L18_00161EF0") __attribute__((sda)); extern int D_L18_00161EF8 __attribute__((sda)); extern int l18_homing_spark_quad_texture_ids __asm__("D_L18_00161F08") __attribute__((sda)); extern void fast_draw_quad_real(void *, void *, int) __asm__("FUN_001f7d30"); @@ -250,8 +250,8 @@ void homing_spark_draw(char *moby) { quad_packet->b = r; } quad_packet->c = 0xFF9000000260; - quad_packet->d = (D_L18_00161EE4) | (long)(D_L18_00161EE8) << 2 | (long)(D_L18_00161EEC) << 4 | - (long)(D_L18_00161EF0) << 6 | 0x8000L << 24; + quad_packet->d = (l18_homing_spark_blend_minuend_selector) | (long)(l18_homing_spark_blend_subtrahend_selector) << 2 | (long)(l18_homing_spark_blend_alpha_factor_selector) << 4 | + (long)(l18_homing_spark_blend_addend_selector) << 6 | 0x8000L << 24; quad_packet->a = 0; for (j = 0; j < 4; j++) { pkt[i].uv[j][0] = homing_spark_quad_uvs[j][0]; From 27946f09a1a6b9ab755d0d9eaac649aac58344c2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:55:11 +0000 Subject: [PATCH 0180/1502] decomp: clarify names in read_buf_create buf -> read_buffer_to_initialize: In the authoritative read_buf_create source (SHA-256 d44cc18d5bdd009b591f358c7d7f44ad3df0ac70741aec48ae5233abb2663608), this struct ReadBuf pointer is assigned directly to buffer_to_initialize, which receives size = READ_BUF_SIZE, put = 0 and count = 0. Retail 0x0023b944 adds 0x50000 to incoming a0; stores at 0x0023b948, 0x0023b94c and 0x0023b954 write 0x50000, zero and zero at original argument +0x50008, +0x50004 and +0x50000. Thus the parameter is the read buffer to initialize, not an allocation size or a payload cursor. --- src/movies/decoder/buffers/read_buf_create.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/movies/decoder/buffers/read_buf_create.c b/src/movies/decoder/buffers/read_buf_create.c index de1d2d80d8..270651ec7c 100644 --- a/src/movies/decoder/buffers/read_buf_create.c +++ b/src/movies/decoder/buffers/read_buf_create.c @@ -2,8 +2,8 @@ void read_buf_create(struct ReadBuf *buf) __asm__("func_0023B940"); -void read_buf_create(struct ReadBuf *buf) { - struct ReadBuf *buffer_to_initialize = buf; +void read_buf_create(struct ReadBuf *read_buffer_to_initialize) { + struct ReadBuf *buffer_to_initialize = read_buffer_to_initialize; buffer_to_initialize->size = READ_BUF_SIZE; buffer_to_initialize->put = 0; From c356a7f0f15393820c45498d5c49526c6355321c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:55:12 +0000 Subject: [PATCH 0181/1502] decomp: clarify names in update_blarg_paratrooper_damage_and_state switch_0_case_11 -> PARATROOPER_HIT_REACTION_NONE: At level-08 00302624 resolve_moby_hit_response returns the reaction selector. Checked helper 002649a8 branches at 00264ab8 on the hit-descriptor pointer s4; its null path stores hit status 1 at 00264adc, zeroes damage through t1 at 00264ae0-00264ae8, and returns literal 11 at 00264af0. Suppression paths 00264e3c-00264e6c also select s1=11 when response flags are absent, with damage cleared at 00264e78/00264e88 and s1 returned at 00264ef0. The assigned source case 11 shares the empty break body with case 0, consistent with no reaction. This is a hit-response domain, not a hero-state ID. --- src/overlays/shared/enemies/blarg_paratrooper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/blarg_paratrooper.c b/src/overlays/shared/enemies/blarg_paratrooper.c index 28e884af1b..58ebdc38b4 100644 --- a/src/overlays/shared/enemies/blarg_paratrooper.c +++ b/src/overlays/shared/enemies/blarg_paratrooper.c @@ -601,7 +601,7 @@ void blarg_paratrooper_update(char *moby) { /* Ported from rac1-decomp (src/overlays/shared/vendor_002D3DF8.c: func_L08_00303998), where it is exact; names translated to the US level program. */ void update_blarg_paratrooper_damage_and_state(char *moby) { - enum { PARATROOPER_HIT_REACTION_LETHAL = 1 } ;Paratrooper302618 *data; + enum { PARATROOPER_HIT_REACTION_LETHAL = 1 , PARATROOPER_HIT_REACTION_NONE = 11} ;Paratrooper302618 *data; char *target, *child, *attached, *chased; float pos[4] __attribute__((aligned(16))); float matrix[16] __attribute__((aligned(16))); @@ -665,7 +665,7 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { if ((unsigned)reaction < 12) { switch (reaction) { case 0: - case 11: + case PARATROOPER_HIT_REACTION_NONE: break; case 9: case 10: From 76715dd764b71265141c51ff810e0ead5be6e536 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:55:23 +0000 Subject: [PATCH 0182/1502] decomp: clarify names in update_path_flythrough_camera D_L10_0015F3FC -> l10_path_camera_transition_amount: Retail 0x002f5f84-0x002f5fac and 0x002f610c-0x002f6134 load this float, add 0.05 and compare against 1. Startup clamps it to 1 at 0x002f5fe4 before setting run->started=1 and initializing the camera pose; completion clamps it to 1 at 0x002f614c before restoring ending FOV and camera transition_state=4. Continuing traversal subtracts 0.05 and clamps to zero at 0x002f61cc-0x002f61f8. These reads/writes establish a normalized camera transition amount without asserting a particular visual fade consumer. Preserve its existing far/gp access binding. D_L10_0015F404 -> l10_path_flythrough_active: Retail 0x002f5fc4 loads integer 1 and 0x002f5ff0 stores it to 0x0015f404 immediately before run->started becomes 1 and the start-path position is copied to cam->pos. Retail 0x002f6198 clears the same scalar after ending FOV restoration, descriptor completion at +0x39, and camera transition_state=4. The flag therefore brackets the active flythrough interval in this function; no external consumer behavior is claimed. D_L10_00167450 -> l10_path_camera_anchor_offset_basis: Retail 0x002f600c-0x002f604c copies descriptor+0x2c/+0x30/+0x34 into a vector with w=0 and passes address 0x00167450 as the third argument to transform_vector_by_basis. The transformed offset is added to the selected anchor moby's position at 0x002f6054-0x002f6060, then camera position is subtracted to produce aim. The continuing anchor branch repeats the same flow at 0x002f646c-0x002f64cc. This proves its use as the basis for the camera's anchor offset, without claiming whose transform supplies it. --- .../shared/camera/path_flythrough_camera.c | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/overlays/shared/camera/path_flythrough_camera.c b/src/overlays/shared/camera/path_flythrough_camera.c index d190c0aa99..cd5cf0e394 100644 --- a/src/overlays/shared/camera/path_flythrough_camera.c +++ b/src/overlays/shared/camera/path_flythrough_camera.c @@ -189,9 +189,9 @@ void initialize_path_camera(struct UpdateCam *path_camera) { } extern char *D_L10_0015FFD8_5f18 __asm__("D_L10_0015FFD8"); -extern f32 D_L10_0015F3FC; -extern s32 D_L10_0015F404; -extern char D_L10_00167450[]; +extern f32 l10_path_camera_transition_amount __asm__("D_L10_0015F3FC"); +extern s32 l10_path_flythrough_active __asm__("D_L10_0015F404"); +extern char l10_path_camera_anchor_offset_basis[] __asm__("D_L10_00167450"); extern float D_L10_00167358 NOT_SDA; extern float D_0013F5E0_5f18[] __asm__("D_0013F5E0"); extern void debug_point_5f18(void *, float) __asm__("FUN_001e93e8"); @@ -219,12 +219,12 @@ void update_path_flythrough_camera(struct UpdateCam *cam) { stops = (VendorCamStops_5f18 *)(saved + 0x58); if (run->started == 0) { - D_L10_0015F3FC += 0.05f; - if (D_L10_0015F3FC >= 1.0f) { + l10_path_camera_transition_amount += 0.05f; + if (l10_path_camera_transition_amount >= 1.0f) { char *start_path = ((char *)l10_paths[*(int *)(rec + 0x20)]); char *look_path = ((char *)l10_paths[*(int *)(rec + 0x24)]); - D_L10_0015F3FC = 1.0f; - D_L10_0015F404 = 1; + l10_path_camera_transition_amount = 1.0f; + l10_path_flythrough_active = 1; run->started = 1; qcopy(&cam->pos, start_path + 0x10); if (*(int *)(rec + 0x28) >= 0) { @@ -235,7 +235,7 @@ void update_path_flythrough_camera(struct UpdateCam *cam) { offset[1] = ofs[1]; offset[2] = ofs[2]; offset[3] = 0.0f; - transform_vector_by_basis(offset, offset, D_L10_00167450); + transform_vector_by_basis(offset, offset, l10_path_camera_anchor_offset_basis); fast_vec_add(point, &anchor->pos, offset); fast_vec_sub(dir, point, &cam->pos); } else { @@ -250,18 +250,18 @@ void update_path_flythrough_camera(struct UpdateCam *cam) { return; } if (run->started == 2) { - D_L10_0015F3FC += 0.05f; - if (D_L10_0015F3FC >= 1.0f) { + l10_path_camera_transition_amount += 0.05f; + if (l10_path_camera_transition_amount >= 1.0f) { float ang; run->started = 3; - D_L10_0015F3FC = 1.0f; + l10_path_camera_transition_amount = 1.0f; ang = stops->fov_end * 0.5f; l10_camera_view.tan_half_fov = fast_sin(ang) / fast_cos(ang); update_view_context(); *(u8 *)(rec + 0x39) = 1; D_L10_00167358 = 0.05f; cam->transition_state = 4; - D_L10_0015F404 = 0; + l10_path_flythrough_active = 0; if (*(int *)(rec + 0x4C) == 0) hero_set_state(0, 1); } @@ -270,9 +270,9 @@ void update_path_flythrough_camera(struct UpdateCam *cam) { } else if (run->started == 3) { return; } else { - D_L10_0015F3FC -= 0.05f; - if (D_L10_0015F3FC < 0.0f) - D_L10_0015F3FC = 0.0f; + l10_path_camera_transition_amount -= 0.05f; + if (l10_path_camera_transition_amount < 0.0f) + l10_path_camera_transition_amount = 0.0f; } path = ((char *)l10_paths[*(int *)(rec + 0x20)]); qcopy(dir, &cam->pos); @@ -320,7 +320,7 @@ void update_path_flythrough_camera(struct UpdateCam *cam) { point[1] = ofs[1]; point[2] = ofs[2]; point[3] = 0.0f; - transform_vector_by_basis(point, point, D_L10_00167450); + transform_vector_by_basis(point, point, l10_path_camera_anchor_offset_basis); fast_vec_add(look_point, &anchor->pos, point); fast_vec_sub(offset, look_point, &cam->pos); } else { From f81800ec911c3b64e1146fe9ef461d0094e5b911 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:55:23 +0000 Subject: [PATCH 0183/1502] decomp: clarify names in bomb_update c1 -> blast_effect_primary_palette: In the bound source, the first c1 is a Colors6 initialized from l00_bomb_blast_effect_primary_palette. Retail 0x002ae968-0x002ae998 copies six packed colors from 0x001e9920 to sp+0x110; 0x002ae9d4-0x002ae9f4 selects an index below six and swaps channels. The selected color is retained in s3 at 0x002aea00 and passed as first color a2 at 0x002aea74 to the blast-effect helper called at 0x002aea98 with bomb position and blast_velocity. c1 -> shrinking_particle_secondary_color: In the bound source, the second c1 is an int from mine_blend_color(0, half-intensity packed RGB, random weight 0.5 to 1.0), used immediately after shrinking_particle_primary_color in spawn_shrinking_effect_particle_with_gravity_and_secondary_spawns. Retail 0x002af09c-0x002af0b8 computes this packed color and retains it in s1; 0x002af1a4 moves s1 into a3 before call 0x002af1c4, while the primary color is a2 at 0x002af19c. Secondary describes argument ordering only. --- src/overlays/shared/weapons/bomb_glove_bomb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/weapons/bomb_glove_bomb.c b/src/overlays/shared/weapons/bomb_glove_bomb.c index 75ab9c1953..112d0d20a1 100644 --- a/src/overlays/shared/weapons/bomb_glove_bomb.c +++ b/src/overlays/shared/weapons/bomb_glove_bomb.c @@ -1412,13 +1412,13 @@ void bomb_update(BombMoby *bomb_moby) { for (i = 0; i < blast_effect_count; i++) { float spd = s * random_float_between(8.0f, 10.0f) * frame_time_macro - g * frame_time_macro; - Colors6 c1 = l00_bomb_blast_effect_primary_palette; + Colors6 blast_effect_primary_palette = l00_bomb_blast_effect_primary_palette; Colors6 blast_effect_secondary_palette = l00_bomb_blast_effect_secondary_palette; FUN_L00_0026a9f0_2adb30( &bomb_moby->pos, &blast_velocity, - swap_packed_color_channels(c1.c[random_integer_below(6)], + swap_packed_color_channels(blast_effect_primary_palette.c[random_integer_below(6)], (unsigned char)item_text_variant[0xA]), swap_packed_color_channels( blast_effect_secondary_palette.c[random_integer_below(6)], @@ -1586,7 +1586,7 @@ void bomb_update(BombMoby *bomb_moby) { hud_counter_update(0x7F << 24, (0x7F << 24) | (cb << 16) | (cg << 8) | cr, random_float_between(0.25f, 1.0f)); - int c1 = + int shrinking_particle_secondary_color = hud_counter_update(0, ((cb / 2) << 16) | ((cg / 2) << 8) | (cr / 2), random_float_between(0.5f, 1.0f)); @@ -1611,7 +1611,7 @@ void bomb_update(BombMoby *bomb_moby) { &v2, &particle_work_vector, shrinking_particle_primary_color, - c1, + shrinking_particle_secondary_color, sz, life, 1, From 77362265e7c3c09064ad0906ae3e2ebaf5a87196 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:55:23 +0000 Subject: [PATCH 0184/1502] decomp: clarify names in frog_update switch_0_case_6 -> FROG_STATE_AIRBORNE_MOTION: The selector is this frog's Moby state byte: retail 0x002e87b0 loads 0x20(s3) and 0x002e87c4..0x002e87d4 dispatches it. Case 6 at 0x002e8ca4..0x002e8cb8 calls established step_moby_motion(moby,pvars+0x120) and tests contact bit 1. On contact, 0x002e8cc4..0x002e8d08 writes frog state 7 (existing FROG_STATE_LANDING_ANIMATION), selects animation 3, and snaps position Z using probe_ground_height. Otherwise motion continues on later updates unless masks 0x120 cause removal at 0x002e8d0c..0x002e8d28. The helper's checked retail 0x0026bb84..0x0026bbe8 tests upward ground normal and downward motion before setting returned bit 1. This proves airborne motion with landing handling without claiming the launch cause; it is a frog-specific domain, not HERO_STATE_FALL. --- src/overlays/shared/enemies/frog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/frog.c b/src/overlays/shared/enemies/frog.c index bfa0847532..9a7f2f77c0 100644 --- a/src/overlays/shared/enemies/frog.c +++ b/src/overlays/shared/enemies/frog.c @@ -245,7 +245,7 @@ void frog_update(unsigned char *moby) __asm__("FUN_L06_002e8678"); /* Moby class 827 */ void frog_update(unsigned char *moby) { - enum { FROG_STATE_INITIALIZE = 0 , FROG_STATE_WAIT_WITH_CHILD = 1 , FROG_STATE_WAIT_TO_FOLLOW_PATH = 3 , FROG_STATE_FOLLOW_PATH = 4 , FROG_STATE_JUMP_TO_HOME = 5 , FROG_STATE_LANDING_ANIMATION = 7 , FROG_STATE_WANDER = 8 , FROG_STATE_APPROACH_TARGET = 9 , FROG_STATE_BLINKING_APPROACH_TARGET = 10 , FROG_STATE_APPROACH_PAUSE = 11 , FROG_STATE_ATTACK = 12 , FROG_STATE_RETURN_HOME = 13 , FROG_STATE_SUCK_CANNON_HELD = 16 } ;float A[4] __attribute__((aligned(16))); + enum { FROG_STATE_INITIALIZE = 0 , FROG_STATE_WAIT_WITH_CHILD = 1 , FROG_STATE_WAIT_TO_FOLLOW_PATH = 3 , FROG_STATE_FOLLOW_PATH = 4 , FROG_STATE_JUMP_TO_HOME = 5 , FROG_STATE_AIRBORNE_MOTION = 6, FROG_STATE_LANDING_ANIMATION = 7 , FROG_STATE_WANDER = 8 , FROG_STATE_APPROACH_TARGET = 9 , FROG_STATE_BLINKING_APPROACH_TARGET = 10 , FROG_STATE_APPROACH_PAUSE = 11 , FROG_STATE_ATTACK = 12 , FROG_STATE_RETURN_HOME = 13 , FROG_STATE_SUCK_CANNON_HELD = 16 } ;float A[4] __attribute__((aligned(16))); float B[4] __attribute__((aligned(16))); float C[4] __attribute__((aligned(16))); float D[4] __attribute__((aligned(16))); @@ -416,7 +416,7 @@ void frog_update(unsigned char *moby) { MOBY(moby)->pos.z = probe_ground_height(&MOBY(moby)->pos, 0, 0.5f); } break; - case 6: { + case FROG_STATE_AIRBORNE_MOTION: { int hit = step_moby_motion(moby, &data->motion); if (hit & 1) { MOBY(moby)->state = 7; From 91008b1c59b1a343355874aa45176c4660309e32 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:57:53 +0000 Subject: [PATCH 0185/1502] decomp: clarify names in spawn_giant_clank_missile owner -> firing_moby: Retail 0x002a9704 preserves a0 in s4; 0x002a97e4 stores s4 in missile pvars+0x10, the owner field read by update_giant_clank_missile to exclude its firing moby from hits. At 0x002a97b4 it is the ignore argument to select_auto_aim_target_moby, and 0x002a9908 reads its position at +0x10 for the launch collision segment. The supplied hero_update_movement caller passes hero.moby while firing two class-0x100 missiles. pos -> spawn_position: Retail 0x002a970c preserves a1 in s3; 0x002a97ec-0x002a97f0 copy its full position quadword into the new class-0x100 moby's +0x10 position. 0x002a97b0-0x002a97c8 also copy it for the auto-aim origin, while 0x002a9910 and 0x002a9914 use its Z and pointer for the launch collision endpoint. The supplied caller constructs this position with moby_point_position and a 1.4-unit heading offset before calling spawn_giant_clank_missile. --- .../shared/vehicles/giant_clank_missile.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/shared/vehicles/giant_clank_missile.c b/src/overlays/shared/vehicles/giant_clank_missile.c index a05dc277e9..d3ebdc784a 100644 --- a/src/overlays/shared/vehicles/giant_clank_missile.c +++ b/src/overlays/shared/vehicles/giant_clank_missile.c @@ -64,7 +64,7 @@ char *spawn_giant_clank_missile(void *owner, char *spawn_giant_clank_missile( - void *owner, void *pos, float fallback_yaw, float fallback_pitch, float target_height_offset, char *target_moby, float rz, float ry) { + void *firing_moby, void *spawn_position, float fallback_yaw, float fallback_pitch, float target_height_offset, char *target_moby, float rz, float ry) { char *spawned_missile; char *missile_spawn_data; BoltVector aim_direction_or_collision_start; @@ -81,11 +81,11 @@ char *spawn_giant_clank_missile( *(float *)(spawned_missile + 0x44) = ry; if (target_moby == 0) { build_spherical_offset(&aim_direction_or_collision_start, D_0015ED6C * 20.0f, rz, ry); - auto_aim_position.q = *(Q_2aa998 *)pos; - target_moby = select_auto_aim_target_moby(owner, &auto_aim_position, &aim_direction_or_collision_start, &fallback_yaw, &fallback_pitch, &target_height_offset, 0.34906584f); + auto_aim_position.q = *(Q_2aa998 *)spawn_position; + target_moby = select_auto_aim_target_moby(firing_moby, &auto_aim_position, &aim_direction_or_collision_start, &fallback_yaw, &fallback_pitch, &target_height_offset, 0.34906584f); } - *(void **)(missile_spawn_data + 0x10) = owner; - qcopy(spawned_missile + 0x10, pos); + *(void **)(missile_spawn_data + 0x10) = firing_moby; + qcopy(spawned_missile + 0x10, spawn_position); *(float *)(missile_spawn_data + 0x34) = D_0015ED6C * 100.0f; *(int *)(missile_spawn_data + 0x38) = 1; *(int *)(missile_spawn_data + 0x24) = 0; @@ -122,9 +122,9 @@ char *spawn_giant_clank_missile( *(short *)(missile_spawn_data + 0x3C) = velocity_inheritance_frame_count; } } - aim_direction_or_collision_start.q = ((BoltOwner *)owner)->position.q; - aim_direction_or_collision_start.f[2] = ((float *)pos)[2]; - if (FUN_001efa68(&aim_direction_or_collision_start, pos, 0, *(int *)(((char *)&D_001413D0)), 0) != 0) { + aim_direction_or_collision_start.q = ((BoltOwner *)firing_moby)->position.q; + aim_direction_or_collision_start.f[2] = ((float *)spawn_position)[2]; + if (FUN_001efa68(&aim_direction_or_collision_start, spawn_position, 0, *(int *)(((char *)&D_001413D0)), 0) != 0) { spawned_missile[0xBC] = 1; qcopy(spawned_missile + 0x10, &D_L00_00173E60); } From e36a3852b38bc87a1b5dc4026771848bc30a2e40 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:58:20 +0000 Subject: [PATCH 0186/1502] decomp: clarify names in spawn_shuttle_explosion_effect D_L06_00162114 -> l06_shuttle_explosion_spark_velocity_scale_random_bound_a: At 0x00303970-0x00303990, gp=0x00166c00 maps -0x4aec to 0x00162114. This float is the first random_float_between endpoint; the sample times frame_time scales the push-biased direction into velocity xyz (sp+0x30) passed to spawn_spark. D_L06_00162118 -> l06_shuttle_explosion_spark_velocity_scale_random_bound_b: At 0x00303970-0x00303990, the float at gp-0x4ae8 (0x00162118) is the second random_float_between endpoint. Its sample times frame_time scales the push-biased direction into velocity xyz passed as spawn_spark argument two. D_L06_0016211C -> l06_shuttle_explosion_spark_velocity_w_random_bound_a: Retail 0x003039d8 loads gp-0x4ae4 (0x0016211c) as the first random float endpoint; 0x003039e4 multiplies the sample by scale and 0x003039f4 stores it at sp+0x3c, velocity[3] in the supplied C. D_L06_00162120 -> l06_shuttle_explosion_spark_velocity_w_random_bound_b: Retail 0x003039e0 loads gp-0x4ae0 (0x00162120) as the second random float endpoint; the sample is multiplied by scale and stored at sp+0x3c at 0x003039f4, exactly velocity[3] passed to spawn_spark. D_L06_00162124 -> l06_shuttle_explosion_spark_acceleration_scale_random_bound_a: Retail 0x003039b4-0x003039d4 loads 0x00162124 (gp-0x4adc) as the first random endpoint. Its sample times frame_time scales a freshly randomized push-biased direction into acceleration xyz at sp+0x40. D_L06_00162128 -> l06_shuttle_explosion_spark_acceleration_scale_random_bound_b: Retail 0x003039b4-0x003039d4 loads 0x00162128 (gp-0x4ad8) as the second random endpoint. The sampled factor times frame_time produces acceleration xyz, the third vector argument to spawn_spark at 0x00303b08. D_L06_0016212C -> l06_shuttle_explosion_spark_acceleration_w_random_bound_a: At 0x003039e8 the float at gp-0x4ad4 (0x0016212c) supplies the first random endpoint; 0x003039f8 multiplies the sample by scale and 0x00303a08 stores acceleration[3] at sp+0x4c. D_L06_00162130 -> l06_shuttle_explosion_spark_acceleration_w_random_bound_b: At 0x003039ec the float at gp-0x4ad0 (0x00162130) supplies the second random endpoint. The scale-multiplied result is stored at sp+0x4c by 0x00303a08, the acceleration vector w component. D_L06_00162134 -> l06_shuttle_explosion_spark_first_color_blend_a: At 0x00303a0c-0x00303a1c, gp-0x4acc maps to 0x00162134, the first integer endpoint of fast_tween_color with a random 0..1 fraction. Its blended color travels through s3 into spawn_spark argument four at 0x00303adc. D_L06_00162138 -> l06_shuttle_explosion_spark_first_color_blend_b: At 0x00303a18 the int at gp-0x4ac8 (0x00162138) is the second fast_tween_color endpoint. The random blend is retained in s3 and passed as the first spark color at 0x00303adc/0x00303b08. D_L06_0016213C -> l06_shuttle_explosion_spark_second_color_blend_a: Retail 0x00303a2c loads gp-0x4ac4 (0x0016213c) as the first endpoint of the second fast_tween_color call. The blended result is saved in s2 at 0x00303a40 and forwarded as spawn_spark argument five. D_L06_00162140 -> l06_shuttle_explosion_spark_second_color_blend_b: Retail 0x00303a38 loads gp-0x4ac0 (0x00162140) as the second endpoint of the second random color blend. The result in s2 becomes t0 at 0x00303ae4, the second spawn_spark color. D_L06_00162144 -> l06_shuttle_explosion_spark_timing_random_min_frames: Retail 0x00303a3c-0x00303a74 loads the int at gp-0x4abc (0x00162144), converts it and twice itself to float random endpoints, then scale_time and truncation produce spawn_spark argument six. The name records the unscaled timing lower endpoint, not an unverified particle phase. D_L06_00162148 -> l06_shuttle_explosion_spark_timing_base_a_frames: Retail 0x00303a78-0x00303aa4 converts gp-0x4ab8 (0x00162148) from int to float, samples between that base and base*1.2, then applies scale_time and truncation. The result in s0 is spawn_spark argument seven, the first of the remaining two timing bases. D_L06_0016214C -> l06_shuttle_explosion_spark_timing_base_b_frames: Retail 0x00303aa8-0x00303ad4 converts gp-0x4ab4 (0x0016214c) to float, samples between base*0.8 and base, then applies scale_time and truncation. It becomes spawn_spark argument eight, the second of the remaining two timing bases. --- src/overlays/l06/mobys/shuttle.c | 48 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/overlays/l06/mobys/shuttle.c b/src/overlays/l06/mobys/shuttle.c index 89c23972ec..564b8fe937 100644 --- a/src/overlays/l06/mobys/shuttle.c +++ b/src/overlays/l06/mobys/shuttle.c @@ -192,21 +192,21 @@ Colors D_L06_00201948 = { {0x4f008fff, 0x4f008fff, 0x4f007fff, 0x4f006fff, 0x2fffffff, 0x2fffffff} }; -extern float D_L06_00162114 __attribute__((sda)); -extern float D_L06_00162118 __attribute__((sda)); -extern float D_L06_0016211C __attribute__((sda)); -extern float D_L06_00162120 __attribute__((sda)); -extern float D_L06_00162124 __attribute__((sda)); -extern float D_L06_00162128 __attribute__((sda)); -extern float D_L06_0016212C __attribute__((sda)); -extern float D_L06_00162130 __attribute__((sda)); -extern int D_L06_00162134 __attribute__((sda)); -extern int D_L06_00162138 __attribute__((sda)); -extern int D_L06_0016213C __attribute__((sda)); -extern int D_L06_00162140 __attribute__((sda)); -extern int D_L06_00162144 __attribute__((sda)); -extern int D_L06_00162148 __attribute__((sda)); -extern int D_L06_0016214C __attribute__((sda)); +extern float l06_shuttle_explosion_spark_velocity_scale_random_bound_a __asm__("D_L06_00162114") __attribute__((sda)); +extern float l06_shuttle_explosion_spark_velocity_scale_random_bound_b __asm__("D_L06_00162118") __attribute__((sda)); +extern float l06_shuttle_explosion_spark_velocity_w_random_bound_a __asm__("D_L06_0016211C") __attribute__((sda)); +extern float l06_shuttle_explosion_spark_velocity_w_random_bound_b __asm__("D_L06_00162120") __attribute__((sda)); +extern float l06_shuttle_explosion_spark_acceleration_scale_random_bound_a __asm__("D_L06_00162124") __attribute__((sda)); +extern float l06_shuttle_explosion_spark_acceleration_scale_random_bound_b __asm__("D_L06_00162128") __attribute__((sda)); +extern float l06_shuttle_explosion_spark_acceleration_w_random_bound_a __asm__("D_L06_0016212C") __attribute__((sda)); +extern float l06_shuttle_explosion_spark_acceleration_w_random_bound_b __asm__("D_L06_00162130") __attribute__((sda)); +extern int l06_shuttle_explosion_spark_first_color_blend_a __asm__("D_L06_00162134") __attribute__((sda)); +extern int l06_shuttle_explosion_spark_first_color_blend_b __asm__("D_L06_00162138") __attribute__((sda)); +extern int l06_shuttle_explosion_spark_second_color_blend_a __asm__("D_L06_0016213C") __attribute__((sda)); +extern int l06_shuttle_explosion_spark_second_color_blend_b __asm__("D_L06_00162140") __attribute__((sda)); +extern int l06_shuttle_explosion_spark_timing_random_min_frames __asm__("D_L06_00162144") __attribute__((sda)); +extern int l06_shuttle_explosion_spark_timing_base_a_frames __asm__("D_L06_00162148") __attribute__((sda)); +extern int l06_shuttle_explosion_spark_timing_base_b_frames __asm__("D_L06_0016214C") __attribute__((sda)); extern int D_L06_00162150 __attribute__((sda)); extern int D_L06_00162154 __attribute__((sda)); extern int D_L06_00162158 __attribute__((sda)); @@ -721,22 +721,22 @@ void spawn_shuttle_explosion_effect(float scale, char *moby, char *pos, char *pu random_vector(direction, 0.0f, 0.9f); fast_vec_add(direction, direction, push); fast_vec_scale( - velocity, direction, random_float_between(D_L06_00162114, D_L06_00162118) * frame_time); + velocity, direction, random_float_between(l06_shuttle_explosion_spark_velocity_scale_random_bound_a, l06_shuttle_explosion_spark_velocity_scale_random_bound_b) * frame_time); random_vector(direction, 0.0f, 0.9f); fast_vec_add(direction, direction, push); fast_vec_scale(acceleration, direction, - random_float_between(D_L06_00162124, D_L06_00162128) * frame_time); - velocity[3] = random_float_between(D_L06_0016211C, D_L06_00162120) * scale; - acceleration[3] = random_float_between(D_L06_0016212C, D_L06_00162130) * scale; - color1 = fast_tween_color(D_L06_00162134, D_L06_00162138, random_float_between(0.0f, 1.0f)); - color2 = fast_tween_color(D_L06_0016213C, D_L06_00162140, random_float_between(0.0f, 1.0f)); + random_float_between(l06_shuttle_explosion_spark_acceleration_scale_random_bound_a, l06_shuttle_explosion_spark_acceleration_scale_random_bound_b) * frame_time); + velocity[3] = random_float_between(l06_shuttle_explosion_spark_velocity_w_random_bound_a, l06_shuttle_explosion_spark_velocity_w_random_bound_b) * scale; + acceleration[3] = random_float_between(l06_shuttle_explosion_spark_acceleration_w_random_bound_a, l06_shuttle_explosion_spark_acceleration_w_random_bound_b) * scale; + color1 = fast_tween_color(l06_shuttle_explosion_spark_first_color_blend_a, l06_shuttle_explosion_spark_first_color_blend_b, random_float_between(0.0f, 1.0f)); + color2 = fast_tween_color(l06_shuttle_explosion_spark_second_color_blend_a, l06_shuttle_explosion_spark_second_color_blend_b, random_float_between(0.0f, 1.0f)); life = truncate_float_to_s32( - scale_time(random_float_between((float)D_L06_00162144, (float)(D_L06_00162144 << 1)))); + scale_time(random_float_between((float)l06_shuttle_explosion_spark_timing_random_min_frames, (float)(l06_shuttle_explosion_spark_timing_random_min_frames << 1)))); size = truncate_float_to_s32( - scale_time(random_float_between((float)D_L06_00162148, (float)D_L06_00162148 * 1.2f))); + scale_time(random_float_between((float)l06_shuttle_explosion_spark_timing_base_a_frames, (float)l06_shuttle_explosion_spark_timing_base_a_frames * 1.2f))); fade = truncate_float_to_s32( - scale_time(random_float_between((float)D_L06_0016214C * 0.8f, (float)D_L06_0016214C))); + scale_time(random_float_between((float)l06_shuttle_explosion_spark_timing_base_b_frames * 0.8f, (float)l06_shuttle_explosion_spark_timing_base_b_frames))); spawn_spark(position, velocity, acceleration, From e327cef429f6c503897c82e40e7d1830a70b15d6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:58:31 +0000 Subject: [PATCH 0187/1502] decomp: clarify names in alien_snapper_update D_L06_00161EB4 -> l06_alien_snapper_gravity: At 0x002f7f24..0x002f7f58 the SDA float is multiplied by D_0015ED70 and stored at pvars+0x80. Motion receives pvars+0x70, so this is motion+0x10; checked helper 0x0026b4e4..0x0026b4f8 subtracts it from vertical velocity at motion+8 each update. At 0x002f829c..0x002f82b8 its negation is passed as acceleration to 0x00269a00, whose 0x00269a68..0x00269a90 solves initial vertical velocity from endpoint z difference, half acceleration times flight time squared, and flight time. It is the level-06 snapper downward acceleration magnitude, with time scaling applied at initialization. switch_0_case_1 -> ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION: Selector is snapper Moby.state loaded at 0x002f7e20, not a Hero enum or animation ID. At 0x002f8024..0x002f8058 state 1 waits while pvars+0x164 equals 2, then enters state 2, sets a one-frame timer and propagates activation through transition_moby_group_state_1_to_2. Supplied group helper also changes listed mobys from state 1 to 2. This proves a wait for individual or group activation without assigning an animation identity. switch_0_case_10 -> ALIEN_SNAPPER_STATE_WAIT_FOR_REPOSITION_ANIMATION: At 0x002f85ac..0x002f8620 reposition state 9 checks a path-derived point against reach_distance, enters Moby.state 10 and selects animation 5. State 10 at 0x002f866c..0x002f86a0 waits for anim_flags bit 2, then restores reposition state 9 and animation 1 with a 20-frame blend. Thus this state waits for the animation interrupting reposition movement; no visual animation meaning is assumed. switch_0_case_2 -> ALIEN_SNAPPER_STATE_ACTIVATION_SEQUENCE: Moby.state 2 follows activation from state 1 at 0x002f8034 and initialization at 0x002f7fc8. Its 0x002f8064..0x002f81ac behavior delays while animation 0 runs, starts animation 3 on timer expiry, then on animation completion checks hero XY range. It selects approach state 8 with jitter and animation 1, or waiting/facing state 6 with animation 2. Name describes this activation sequence without claiming the visual meaning of animation 3. switch_0_case_4 -> ALIEN_SNAPPER_STATE_PREPARE_HOME_NODE_JUMP: State 4 is entered by the clip-volume trigger at 0x002f81d4..0x002f81fc. At 0x002f8200..0x002f8240 it waits for animation completion and advances animation 3 to 6. Once 6 finishes, 0x002f8244..0x002f8304 copies the configured cuboid node position into home, computes travel speed for 60 scaled frames, solves ballistic initial z velocity using negative gravity via 0x00269a00, starts motion toward that node and enters state 5. These operations prove preparation for the home-node jump. switch_0_case_5 -> ALIEN_SNAPPER_STATE_JUMP_TO_HOME_NODE: Entered at 0x002f824c only after home is set to configured node position and ballistic motion initialized at 0x002f8268..0x002f8304. State 5 at 0x002f8320..0x002f8358 updates that motion and switches to state 6/animation 2 when flag 1 is returned. Checked motion helper subtracts gravity from z velocity at 0x0026b4e4..0x0026b4f8, adds velocity to moby position at 0x0026b9dc..0x0026ba00 and sets flag 1 on a supporting ground contact at 0x0026bb98..0x0026bbe8. This is the jump toward the configured home node. switch_0_case_6 -> ALIEN_SNAPPER_STATE_FACE_GOAL_AND_WAIT: At 0x002f8364..0x002f83bc state 6 computes atan2 from pvars goal_x/goal_y minus moby XY and updates yaw with turn_speed; it performs no translation. At 0x002f83c0..0x002f8428 it waits or enters approach-delay state 7 with a randomized timer, or reposition state 9 when pvars+0x1ac is nonzero. Entries from state 2, completed home-node motion and return-home use animation 2. Facing the stored goal while waiting is directly established. switch_1_case_6 -> ALIEN_SNAPPER_ANIM_HOME_NODE_JUMP_WINDUP: The inner selector is moby->prev_seq at 0x002f8210..0x002f821c, a snapper animation domain separate from Moby.state and HeroStateId. In state 4, completion of sequence 3 selects sequence 6 at 0x002f822c..0x002f8240. Completion of sequence 6 immediately launches the ballistic home-node movement at 0x002f8244..0x002f8304 and switches to in-flight animation 7. This establishes sequence 6 as the home-node jump windup without assuming a particular pose. --- src/overlays/l06/mobys/alien_snapper.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l06/mobys/alien_snapper.c b/src/overlays/l06/mobys/alien_snapper.c index 50ba1f1376..d966a300ec 100644 --- a/src/overlays/l06/mobys/alien_snapper.c +++ b/src/overlays/l06/mobys/alien_snapper.c @@ -130,7 +130,7 @@ typedef struct { extern float D_0015ED70; extern float scale_time(float) __asm__("FUN_001f96b0"); extern float D_L06_00161EB0 __attribute__((sda)); -extern float D_L06_00161EB4 __attribute__((sda)); +extern float l06_alien_snapper_gravity __asm__("D_L06_00161EB4") __attribute__((sda)); extern float l06_alien_snapper_bite_approach_radius __asm__("D_L06_00161EC4") __attribute__((sda)); extern float l06_alien_snapper_max_home_distance __asm__("D_L06_00161EC8") __attribute__((sda)); extern float l06_alien_snapper_base_targeting_radius __asm__("D_L06_00161ED0") __attribute__((sda)); @@ -246,7 +246,7 @@ approach_angle(f32 *angle, f32 target, f32 *vel, f32, f32, f32) __asm__("FUN_L00 /* Moby class 1048 */ void alien_snapper_update(Moby *moby) { - enum { ALIEN_SNAPPER_STATE_INITIALIZE = 0 , ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER = 3 , ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH = 7 , ALIEN_SNAPPER_STATE_APPROACH_TARGET = 8 , ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET = 9 , ALIEN_SNAPPER_STATE_BITE_TARGET = 11 , ALIEN_SNAPPER_STATE_RETURN_HOME = 12 , ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET = 13 , ALIEN_SNAPPER_STATE_HIT_KNOCKBACK = 14 , ALIEN_SNAPPER_STATE_FACE_HERO = 15 , ALIEN_SNAPPER_STATE_BITE_HERO = 16 , ALIEN_SNAPPER_STATE_DEATH_MOTION = 17 } ;SnapperVars_91A8 *snapper_behavior = (SnapperVars_91A8 *)moby->pvars; + enum { ALIEN_SNAPPER_STATE_INITIALIZE = 0 , ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION = 1 , ALIEN_SNAPPER_STATE_ACTIVATION_SEQUENCE = 2 ,ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER = 3 , ALIEN_SNAPPER_STATE_PREPARE_HOME_NODE_JUMP = 4 , ALIEN_SNAPPER_STATE_JUMP_TO_HOME_NODE = 5 , ALIEN_SNAPPER_STATE_FACE_GOAL_AND_WAIT = 6, ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH = 7 , ALIEN_SNAPPER_STATE_APPROACH_TARGET = 8 , ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET = 9 , ALIEN_SNAPPER_STATE_WAIT_FOR_REPOSITION_ANIMATION = 10, ALIEN_SNAPPER_STATE_BITE_TARGET = 11 , ALIEN_SNAPPER_STATE_RETURN_HOME = 12 , ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET = 13 , ALIEN_SNAPPER_STATE_HIT_KNOCKBACK = 14 , ALIEN_SNAPPER_STATE_FACE_HERO = 15 , ALIEN_SNAPPER_STATE_BITE_HERO = 16 , ALIEN_SNAPPER_STATE_DEATH_MOTION = 17 } ; enum { ALIEN_SNAPPER_ANIM_HOME_NODE_JUMP_WINDUP = 6} ;SnapperVars_91A8 *snapper_behavior = (SnapperVars_91A8 *)moby->pvars; Moby *target; float target_goal_radius; float target_gap_angle_radians; @@ -290,7 +290,7 @@ void alien_snapper_update(Moby *moby) { snapper_behavior->speed = snapper_behavior->base_speed * frame_time; snapper_behavior->f90 = truncate_float_to_s32(768.0f); snapper_behavior->f98 = 0.75f; - snapper_behavior->f80 = D_L06_00161EB4 * D_0015ED70; + snapper_behavior->f80 = l06_alien_snapper_gravity * D_0015ED70; snapper_behavior->fAD = 0; snapper_behavior->f84 = 0.0005f; snapper_behavior->f94 = 9; @@ -319,7 +319,7 @@ void alien_snapper_update(Moby *moby) { snapper_behavior->f1A0 = l06_alien_snapper_base_targeting_radius; } break; - case 1: + case ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION: if (snapper_behavior->f164 != 2) { moby->state = 2; snapper_behavior->timer = scale_game_frames(1); @@ -328,7 +328,7 @@ void alien_snapper_update(Moby *moby) { } } break; - case 2: + case ALIEN_SNAPPER_STATE_ACTIVATION_SEQUENCE: if (moby->prev_seq == 0) { if (snapper_behavior->timer == 0) { snapper_behavior->timer = truncate_float_to_s32(scale_time(random_float_between(0.0f, 20.0f))); @@ -366,13 +366,13 @@ void alien_snapper_update(Moby *moby) { } } break; - case 4: + case ALIEN_SNAPPER_STATE_PREPARE_HOME_NODE_JUMP: if (moby->anim_flags & 2) { switch (moby->prev_seq) { case 3: blend_moby_animation(moby, 6, 0, scale_game_frames(5)); break; - case 6: + case ALIEN_SNAPPER_ANIM_HOME_NODE_JUMP_WINDUP: moby->state = 5; qcopy(&snapper_behavior->home, &l06_cuboids[snapper_behavior->node].pos); snapper_behavior->return_speed = @@ -395,7 +395,7 @@ void alien_snapper_update(Moby *moby) { } } break; - case 5: + case ALIEN_SNAPPER_STATE_JUMP_TO_HOME_NODE: if (func_L00_0025D6F0_91A8(moby, snapper_behavior->f70) & 1) { moby->state = 6; if (moby->prev_seq != 2) { @@ -403,7 +403,7 @@ void alien_snapper_update(Moby *moby) { } } break; - case 6: + case ALIEN_SNAPPER_STATE_FACE_GOAL_AND_WAIT: func_L00_002592B0_91A8(moby, fast_arc_tan(snapper_behavior->goal_x - moby->pos.x, snapper_behavior->goal_y - moby->pos.y), &snapper_behavior->turn_speed, @@ -469,7 +469,7 @@ void alien_snapper_update(Moby *moby) { } break; } - case 10: + case ALIEN_SNAPPER_STATE_WAIT_FOR_REPOSITION_ANIMATION: if (moby->anim_flags & 2) { moby->state = 9; if (moby->prev_seq != 1) { From eb929379a3a89e5f1b16b027a338a0ba1a43c1b2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:58:31 +0000 Subject: [PATCH 0188/1502] decomp: clarify names in alien_queen_update other -> post_death_scan_record: In the source's POST_DEATH case this pointer is D_L06_001678D0 + i*0xA0 for nonzero D_L06_0016A010[i]. Retail 002fa900..002fa94c scans at most 48 records, saves the current record in a0 at 002fa940, tests its short +0x86 against 0x12, and passes that same record to 00316330 at 002fa950. The checked helper reads its +0x84 index and sets a referenced object's +0x50 word to 1. This is the current post-death scan record, not another moby. switch_0_case_11 -> ALIEN_QUEEN_STATE_WAIT_FOR_ORBIT_ANIMATION_END: Selector is the queen moby's state byte +0x20 (002f9b08), not HeroStateId. Timed orbit at 002fa2d8 calls orbit movement, then timer expiration writes state 11 at 002fa308, saved return state 7 at +0xBC, and requests animation 6 at 002fa330. Case 11 at 002fa5c8..002fa5ec waits for animation flag +0x70 bit 2, restores +0xBC into state +0x20, and blends animation 1. Thus this is the wait for the timed-orbit exit animation to finish; no identity with HERO_STATE_HIGH_JUMP is supported. --- src/overlays/l06/mobys/alien_queen.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l06/mobys/alien_queen.c b/src/overlays/l06/mobys/alien_queen.c index 8956b67db9..2ea8fec3f4 100644 --- a/src/overlays/l06/mobys/alien_queen.c +++ b/src/overlays/l06/mobys/alien_queen.c @@ -388,7 +388,7 @@ typedef struct AlienQueenVars { /* Moby class 1051 */ void alien_queen_update(unsigned char *moby) { - enum { ALIEN_QUEEN_STATE_INITIALIZE = 0 , ALIEN_QUEEN_STATE_WAIT_TO_START_INTRO = 1 , ALIEN_QUEEN_STATE_INTRO = 2 , ALIEN_QUEEN_STATE_FIRST_RECOVERY_CAMERA = 3 , ALIEN_QUEEN_STATE_FROG_RECOVERY_ORBIT = 4 , ALIEN_QUEEN_STATE_SECOND_RECOVERY_CAMERA = 5 , ALIEN_QUEEN_STATE_GROUP_RECOVERY_ORBIT = 6 , ALIEN_QUEEN_STATE_WAIT_TO_APPROACH_TARGET = 7 , ALIEN_QUEEN_STATE_APPROACH_TARGET = 8 , ALIEN_QUEEN_STATE_ATTACK_WINDUP = 9 , ALIEN_QUEEN_STATE_ATTACK_HIT_QUERIES = 10 , ALIEN_QUEEN_STATE_TIMED_ORBIT = 12 , ALIEN_QUEEN_STATE_RETURN_HOME = 13 , ALIEN_QUEEN_STATE_DEATH = 14 , ALIEN_QUEEN_STATE_POST_DEATH = 15 } ;AlienQueenVars *alien_queen_update_vars = (AlienQueenVars *)MOBY(moby)->pvars; + enum { ALIEN_QUEEN_STATE_INITIALIZE = 0 , ALIEN_QUEEN_STATE_WAIT_TO_START_INTRO = 1 , ALIEN_QUEEN_STATE_INTRO = 2 , ALIEN_QUEEN_STATE_FIRST_RECOVERY_CAMERA = 3 , ALIEN_QUEEN_STATE_FROG_RECOVERY_ORBIT = 4 , ALIEN_QUEEN_STATE_SECOND_RECOVERY_CAMERA = 5 , ALIEN_QUEEN_STATE_GROUP_RECOVERY_ORBIT = 6 , ALIEN_QUEEN_STATE_WAIT_TO_APPROACH_TARGET = 7 , ALIEN_QUEEN_STATE_APPROACH_TARGET = 8 , ALIEN_QUEEN_STATE_ATTACK_WINDUP = 9 , ALIEN_QUEEN_STATE_ATTACK_HIT_QUERIES = 10 , ALIEN_QUEEN_STATE_WAIT_FOR_ORBIT_ANIMATION_END = 11, ALIEN_QUEEN_STATE_TIMED_ORBIT = 12 , ALIEN_QUEEN_STATE_RETURN_HOME = 13 , ALIEN_QUEEN_STATE_DEATH = 14 , ALIEN_QUEEN_STATE_POST_DEATH = 15 } ;AlienQueenVars *alien_queen_update_vars = (AlienQueenVars *)MOBY(moby)->pvars; char *target; float step[4]; @@ -649,7 +649,7 @@ void alien_queen_update(unsigned char *moby) { } return; } - case 11: + case ALIEN_QUEEN_STATE_WAIT_FOR_ORBIT_ANIMATION_END: if (moby[0x70] & 2) { moby[0x20] = moby[0xBC]; if ((unsigned char)moby[0x53] != 1) { @@ -736,12 +736,12 @@ void alien_queen_update(unsigned char *moby) { } case ALIEN_QUEEN_STATE_POST_DEATH: { int i; - char *other = 0; + char *post_death_scan_record = 0; for (i = 0; i < 0x30; i++) { if (D_L06_0016A010[i] != 0) { - other = D_L06_001678D0 + i * 0xA0; - if (*(short *)(other + 0x86) == 0x12) { - release_moby_camera_control(other); + post_death_scan_record = D_L06_001678D0 + i * 0xA0; + if (*(short *)(post_death_scan_record + 0x86) == 0x12) { + release_moby_camera_control(post_death_scan_record); break; } } From e5c5e1055c29472d2bd67256f9403336fd7dab8c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:00:22 +0000 Subject: [PATCH 0189/1502] decomp: clarify names in update_spawner_bomb switch_0_case_0 -> SPAWNER_BOMB_STATE_MOVING: The selector is moby->state: retail lbu v1,0x20(s2) at 0x002c4770 and zero dispatch at 0x002c478c reach 0x002c47ac. This branch adds the runtime motion vector to position (0x002c47ac..0x002c47e8), reflects and scales it after line/sphere collisions, and applies gravity at 0x002c4d6c..0x002c4d74. Low motion after a qualifying collision sets state 1 at 0x002c4958/0x002c4b40; timer expiry can instead set state 2 at 0x002c4ce8. MOVING describes this bomb-specific state without assuming every update is airborne. switch_0_case_1 -> SPAWNER_BOMB_STATE_SPAWN_CHILD: Retail 0x002c4774..0x002c4778 compares the moby state byte against 1 and branches to 0x002c4d94. At 0x002c4d94..0x002c4dc4 it probes ground height and places the bomb 0.2 above it, then 0x002c4dd0 calls established revive_spawner_pooled_child (0x002bec60) with the spawner from runtime+0x10 and copied bomb position. It stores the returned child at runtime+0x18 at 0x002c4dd8 and immediately sets state 2 at 0x002c4ddc..0x002c4de4. switch_0_case_2 -> SPAWNER_BOMB_STATE_SHRINKING: Retail state dispatch at 0x002c479c compares the same moby->state byte with 2 and enters 0x002c4de8. Instructions 0x002c4df4..0x002c4e04 subtract bomb scale times frame_scale*0.05 from bomb scale. Runtime+0x18 supplies an optional child whose scale grows toward class scale only when runtime+0x1c bit 4 is set (0x002c4e08..0x002c4e3c). The small-bomb threshold and child completion tests at 0x002c4e40..0x002c4ee0 lead to removal at 0x002c4f4c, proving SHRINKING without requiring a non-null child. vars -> bomb_runtime: Retail 0x002c4754 loads s3 from moby+0x78 (pvars), matching vars=(float *)moby->pvars. This aggregate supplies motion to fast_vec_add at 0x002c47ac..0x002c47e8 and gravity at 0x002c4d6c..0x002c4d74, the spawner pointer at +0x10 to revive_spawner_pooled_child at 0x002c4dd0..0x002c4dd4, the returned child at +0x18 (0x002c4dd8), growth flags at +0x1c (0x002c4e14..0x002c4e18), and timers at +0x14/+0x20. Thus it is the bomb's runtime block, not solely a velocity vector. --- .../shared/enemies/bomb_spawner_bomb.c | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/overlays/shared/enemies/bomb_spawner_bomb.c b/src/overlays/shared/enemies/bomb_spawner_bomb.c index c8bb837a29..3366f68023 100644 --- a/src/overlays/shared/enemies/bomb_spawner_bomb.c +++ b/src/overlays/shared/enemies/bomb_spawner_bomb.c @@ -188,7 +188,7 @@ void bomb_spawner_bomb_update(struct Moby *moby) __asm__("FUN_L03_002c4718"); /* Drifts and bounces off walls (state 0), lands and spawns its child moby (1), then shrinks while the child grows (2). */ /* Moby class 545 */ void bomb_spawner_bomb_update(struct Moby *moby) { - float *vars; + enum { SPAWNER_BOMB_STATE_MOVING = 0 , SPAWNER_BOMB_STATE_SPAWN_CHILD = 1 , SPAWNER_BOMB_STATE_SHRINKING = 2 } ;float *bomb_runtime; Vec4 *pos; struct Moby *other; Vec4 old_pos; @@ -200,54 +200,54 @@ void bomb_spawner_bomb_update(struct Moby *moby) { if (moby == NULL) return; - vars = (float *)moby->pvars; - if (vars == NULL) + bomb_runtime = (float *)moby->pvars; + if (bomb_runtime == NULL) return; pos = (Vec4 *)&moby->pos; - fast_dec_timer(vars + 8); + fast_dec_timer(bomb_runtime + 8); qcopy(&old_pos, pos); switch (moby->state) { - case 0: { + case SPAWNER_BOMB_STATE_MOVING: { moby->scale += (moby->pclass->scale - moby->scale) * (frame_scale * 0.05f); - fast_vec_add(pos, pos, vars); - fast_vec_normalize(&next_pos, vars, 0.2f); + fast_vec_add(pos, pos, bomb_runtime); + fast_vec_normalize(&next_pos, bomb_runtime, 0.2f); fast_vec_add(&next_pos, &next_pos, pos); old_disable = moby->collision_disable; old_collision = moby->collision; - old_owner_disable = (*(struct Moby **)(vars + 4))->collision_disable; - old_owner_collision = (*(struct Moby **)(vars + 4))->collision; + old_owner_disable = (*(struct Moby **)(bomb_runtime + 4))->collision_disable; + old_owner_collision = (*(struct Moby **)(bomb_runtime + 4))->collision; moby->collision_disable = -1; - (*(struct Moby **)(vars + 4))->collision_disable = -1; + (*(struct Moby **)(bomb_runtime + 4))->collision_disable = -1; moby->collision = 0; - (*(struct Moby **)(vars + 4))->collision = 0; + (*(struct Moby **)(bomb_runtime + 4))->collision = 0; if (collision_line(&old_pos, &next_pos, 4, moby, 0)) { fast_vec_sub(&next_pos, &D_L03_00173F40.point, &next_pos); fast_vec_normalize(&next_pos, &next_pos, 0.215f); fast_vec_add(pos, pos, &next_pos); if (D_L03_00173F40.moby == 0) { - reflect_vector(vars, vars, &D_L03_00173F40.normal_x); + reflect_vector(bomb_runtime, bomb_runtime, &D_L03_00173F40.normal_x); angle = vector_length_xy(&D_L03_00173F40.normal_x); if (fast_arc_tan(D_L03_00173F40.normal_z, angle) < 0.6981317f && collision_hit_material() == -1) { - fast_vec_scale(vars, vars, 0.5f); - if (fast_vec_length(vars) < 0.025f) { + fast_vec_scale(bomb_runtime, bomb_runtime, 0.5f); + if (fast_vec_length(bomb_runtime) < 0.025f) { moby->state = 1; goto first_collision_timer; } } } else if (((struct Moby *)D_L03_00173F40.moby)->oclass != 0x221) { - reflect_vector(vars, vars, &D_L03_00173F40.normal_x); + reflect_vector(bomb_runtime, bomb_runtime, &D_L03_00173F40.normal_x); angle = vector_length_xy(&D_L03_00173F40.normal_x); if (fast_arc_tan(D_L03_00173F40.normal_z, angle) < 0.6981317f && collision_hit_material() == -1) - fast_vec_scale(vars, vars, 1.2f); + fast_vec_scale(bomb_runtime, bomb_runtime, 1.2f); } else { - vars[2] *= FUN_002132a8(0.9f, 1.1f); + bomb_runtime[2] *= FUN_002132a8(0.9f, 1.1f); } first_collision_timer: - if (*(int *)(vars + 8) == 0) { + if (*(int *)(bomb_runtime + 8) == 0) { FUN_0022da68(0, 0, moby); - *(int *)(vars + 8) = 12; + *(int *)(bomb_runtime + 8) = 12; } } if (coll_sphere(0.2f, (Vec4 *)&moby->pos, 4, moby)) { @@ -255,26 +255,26 @@ void bomb_spawner_bomb_update(struct Moby *moby) { fast_vec_normalize(&next_pos, &next_pos, 0.015f); fast_vec_add((Vec4 *)&moby->pos, &D_L03_00173F40.pad30, &next_pos); if (D_L03_00173F40.moby == 0) { - reflect_vector(vars, vars, &D_L03_00173F40.normal_x); + reflect_vector(bomb_runtime, bomb_runtime, &D_L03_00173F40.normal_x); angle = vector_length_xy(&D_L03_00173F40.normal_x); if (fast_arc_tan(D_L03_00173F40.normal_z, angle) < 0.6981317f && collision_hit_material() == -1) { - fast_vec_scale(vars, vars, 0.5f); - if (fast_vec_length(vars) < 0.025f) + fast_vec_scale(bomb_runtime, bomb_runtime, 0.5f); + if (fast_vec_length(bomb_runtime) < 0.025f) moby->state = 1; } } else if (((struct Moby *)D_L03_00173F40.moby)->oclass != 0x221) { - reflect_vector(vars, vars, &D_L03_00173F40.normal_x); + reflect_vector(bomb_runtime, bomb_runtime, &D_L03_00173F40.normal_x); angle = vector_length_xy(&D_L03_00173F40.normal_x); if (fast_arc_tan(D_L03_00173F40.normal_z, angle) < 0.6981317f && collision_hit_material() == -1) - fast_vec_scale(vars, vars, 1.2f); + fast_vec_scale(bomb_runtime, bomb_runtime, 1.2f); } else { - vars[2] *= FUN_002132a8(0.9f, 1.1f); + bomb_runtime[2] *= FUN_002132a8(0.9f, 1.1f); } - if (*(int *)(vars + 8) == 0) { + if (*(int *)(bomb_runtime + 8) == 0) { FUN_0022da68(0, 0, moby); - *(int *)(vars + 8) = 12; + *(int *)(bomb_runtime + 8) = 12; } } for (other = D_L03_0015FFE4; other != NULL; other = other->next) { @@ -288,41 +288,41 @@ void bomb_spawner_bomb_update(struct Moby *moby) { fast_vec_add((Vec4 *)&moby->pos, (Vec4 *)&moby->pos, &delta); } } - if (fast_dec_timer_s16(vars + 5)) + if (fast_dec_timer_s16(bomb_runtime + 5)) moby->state = 2; - moby->rot.x = normalize_angle(vars[0]); - moby->rot.y = normalize_angle(vars[1]); + moby->rot.x = normalize_angle(bomb_runtime[0]); + moby->rot.y = normalize_angle(bomb_runtime[1]); moby->collision_disable = old_disable; - (*(struct Moby **)(vars + 4))->collision_disable = old_owner_disable; + (*(struct Moby **)(bomb_runtime + 4))->collision_disable = old_owner_disable; moby->collision = old_collision; - (*(struct Moby **)(vars + 4))->collision = old_owner_collision; - vars[2] -= frame_time_sq * 9.8f; + (*(struct Moby **)(bomb_runtime + 4))->collision = old_owner_collision; + bomb_runtime[2] -= frame_time_sq * 9.8f; moby->rot.x += frame_scale * 0.01f; moby->rot.y += frame_scale * 0.02f; break; } - case 1: { + case SPAWNER_BOMB_STATE_SPAWN_CHILD: { float height = probe_ground_height(pos, 0, 0.5f); moby->pos.w = 0.0f; moby->pos.z = height + 0.2f; next_pos.q = *(u128 *)pos; - *(struct Moby **)(vars + 6) = - revive_spawner_pooled_child(*(struct Moby **)(vars + 4), &next_pos, -1); + *(struct Moby **)(bomb_runtime + 6) = + revive_spawner_pooled_child(*(struct Moby **)(bomb_runtime + 4), &next_pos, -1); moby->state = 2; break; } - case 2: { + case SPAWNER_BOMB_STATE_SHRINKING: { struct Moby *other; float rate = frame_scale * 0.05f; moby->scale -= moby->scale * rate; - other = *(struct Moby **)(vars + 6); - if (other != NULL && (*(int *)(vars + 7) & 4)) + other = *(struct Moby **)(bomb_runtime + 6); + if (other != NULL && (*(int *)(bomb_runtime + 7) & 4)) other->scale += (other->pclass->scale - other->scale) * rate; if (moby->scale < moby->pclass->scale * (frame_scale * 0.05f)) { moby->scale = 0.0001f; - other = *(struct Moby **)(vars + 6); + other = *(struct Moby **)(bomb_runtime + 6); if (other == NULL || other->state == 0xfe || other->state == 0xfd || - !(*(int *)(vars + 7) & 4) || other->pclass->scale - 0.01f <= other->scale) + !(*(int *)(bomb_runtime + 7) & 4) || other->pclass->scale - 0.01f <= other->scale) goto remove_moby; } } From 6c3fae240d122cc9417ac57474b575b0cb69ff0d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:00:22 +0000 Subject: [PATCH 0190/1502] decomp: clarify names in hud_draw_gauge_frame dst -> gauge_height_destination: In the bound C snapshot dst is &gauge_element->h and is the destination of the four-byte memcpy from D_L00_0015F764. Retail 0x002378a0 stores the loaded scale word at record +0x5c, immediately before hud_screen_position. The supplied hud_screen_position source reads rec->h and subtracts h>>1 from y for alignment, proving this destination is the gauge element height field rather than an unspecified buffer. src -> vertical_scale_source: In the bound C snapshot src points at D_L00_0015F764 and supplies exactly four bytes to gauge_element->h. Retail 0x00237880 loads that global through gp-0x749c and 0x002378a0 stores its full word at record +0x5c. The same global supplies vertical rectangle dimensions at 0x002378c4-0x00237954 and sprite vertical scale at 0x00237ab0-0x00237ab8, proving vertical_scale_source beyond a generic copy source. --- src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c index 33bf659d50..ea26c24b7f 100644 --- a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c +++ b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c @@ -80,9 +80,9 @@ int hud_draw_gauge_frame(HudElem_237840 *gauge_element) { screen_position[1] = gauge_element->unk54; gauge_element->w = ww; { - int *src = (int *)&(*(short *)&D_L00_0015F764); - int *dst = &gauge_element->h; - __builtin_memcpy(dst, src, 4); + int *vertical_scale_source = (int *)&(*(short *)&D_L00_0015F764); + int *gauge_height_destination = &gauge_element->h; + __builtin_memcpy(gauge_height_destination, vertical_scale_source, 4); } } hud_screen_position(gauge_element, &screen_position[0], &screen_position[1]); From 3fd6c1d59911b2f197ef66d1e146c74463953a24 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:00:23 +0000 Subject: [PATCH 0191/1502] decomp: clarify names in proceed_audio result -> audio_send_result: Authoritative proceed_audio.c assigns the s32 result solely from audio_dec_send(&movie_player->audio_dec) and returns it unchanged. Retail 0x0023abb8 calls 0x0023aef0 with the decoder address formed from DAT_0016120c + 0xd9100 at 0x0023abbc; 0x0023abc0-0x0023abc8 restore and return without modifying v0. This proves the local holds the audio send call's forwarded return value, without assigning status or count semantics. --- src/movies/player/proceed_audio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/movies/player/proceed_audio.c b/src/movies/player/proceed_audio.c index 253ed00f4b..32a0249e1d 100644 --- a/src/movies/player/proceed_audio.c +++ b/src/movies/player/proceed_audio.c @@ -8,9 +8,9 @@ extern s32 audio_dec_send() __asm__("func_0023AEF0"); s32 proceed_audio(void) __asm__("FUN_0023aba0"); s32 proceed_audio(void) { - s32 result; - result = audio_dec_send(&movie_player->audio_dec); - return result; + s32 audio_send_result; + audio_send_result = audio_dec_send(&movie_player->audio_dec); + return audio_send_result; } extern s32 func_0023ABA0(void) __attribute__((alias("FUN_0023aba0"))); From 7d236551035289ae868b99ae6b6e4b6ae096054d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:00:23 +0000 Subject: [PATCH 0192/1502] decomp: clarify names in enable_dmac result -> dmac_enable_result: In src/sdk/kernel/enable_dmac.c (SHA-256 f4bcb5a4f43ff65a53ccb8b764991e998c15c06c8d3c336e41376b96693b2e21), signed s32 result receives only _EnableDmac(channel_index). Retail jal 0x00118800 at 0x00119190 produces v0, saved to s1 at 0x00119198. Moves at 0x001191a4 and 0x001191b0 return that saved value across the optional EnableInterrupts call at 0x001191a8. Original Ghidra iVar1 has the same producer and return data flow; dmac_enable_result distinguishes this retained return from the interrupt helper returns. --- src/sdk/kernel/enable_dmac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sdk/kernel/enable_dmac.c b/src/sdk/kernel/enable_dmac.c index 16e9d29f71..1b8543ef4d 100644 --- a/src/sdk/kernel/enable_dmac.c +++ b/src/sdk/kernel/enable_dmac.c @@ -9,19 +9,19 @@ s32 enable_dmac(s32 channel_index) __asm__("FUN_00119160"); s32 enable_dmac(s32 channel_index) { u32 status; - s32 result; + s32 dmac_enable_result; status = CpuReadStatus(); status &= 0x10000; if (status != 0) { DIntr(); } - result = _EnableDmac(channel_index); + dmac_enable_result = _EnableDmac(channel_index); CpuSync(); if (status != 0) { EnableInterrupts(); } - return result; + return dmac_enable_result; } /* Recovered original symbol name. */ From cb3064eb10a752075af9d6ad67c10fc0a2ee274b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:00:28 +0000 Subject: [PATCH 0193/1502] overlay: name get_morphoray_chicken_slot_record --- include/rnc/overlay/shared/weapons.h | 2 +- src/overlays/l00/level_class_tables.c | 3 ++- src/overlays/l01/level_class_tables.c | 4 ++-- src/overlays/l02/level_class_tables.c | 4 ++-- src/overlays/l03/level_class_tables.c | 3 ++- src/overlays/l04/level_class_tables.c | 3 ++- src/overlays/l05/level_class_tables.c | 3 ++- src/overlays/l06/level_class_tables.c | 3 ++- src/overlays/l07/level_class_tables.c | 4 ++-- src/overlays/l08/level_class_tables.c | 3 ++- src/overlays/l09/level_class_tables.c | 3 ++- src/overlays/l10/level_class_tables.c | 4 ++-- src/overlays/l11/level_class_tables.c | 4 ++-- src/overlays/l12/level_class_tables.c | 3 ++- src/overlays/l13/level_class_tables.c | 4 ++-- src/overlays/l14/level_class_tables.c | 4 ++-- src/overlays/l15/level_class_tables.c | 4 ++-- src/overlays/l16/level_class_tables.c | 3 ++- src/overlays/l17/level_class_tables.c | 3 ++- src/overlays/l18/level_class_tables.c | 3 ++- src/overlays/shared/weapons/morphoray_chicken.c | 4 +++- 21 files changed, 42 insertions(+), 29 deletions(-) diff --git a/include/rnc/overlay/shared/weapons.h b/include/rnc/overlay/shared/weapons.h index 6542875a5c..2b5c37c2eb 100644 --- a/include/rnc/overlay/shared/weapons.h +++ b/include/rnc/overlay/shared/weapons.h @@ -26,7 +26,7 @@ void linked_moby_states_update(unsigned char *) __asm__("FUN_L00_002b3 void metal_detector_update(struct Moby *) __asm__("FUN_L00_002d2ee8"); void mine_glove_update(struct Moby *) __asm__("FUN_L00_002c1ad0"); void morphoray_update() __asm__("FUN_L00_002bc7e8"); -s32 FUN_L00_002caf40(s32); +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); int cancel_suck_cannon_suction_and_set_moby_state_5(struct Moby *) __asm__("FUN_L00_002caf10"); int launch_suck_cannon_projectile_and_update_moby_state(struct Moby *, int, diff --git a/src/overlays/l00/level_class_tables.c b/src/overlays/l00/level_class_tables.c index a794a6ce65..a8b81d9db1 100644 --- a/src/overlays/l00/level_class_tables.c +++ b/src/overlays/l00/level_class_tables.c @@ -17,6 +17,7 @@ #include "rnc/overlay/shared/vehicles.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" @@ -50,7 +51,7 @@ void *D_L00_001EA7D4[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; void *D_L00_001EA7EC[6] diff --git a/src/overlays/l01/level_class_tables.c b/src/overlays/l01/level_class_tables.c index 57e65ffe8f..303af41250 100644 --- a/src/overlays/l01/level_class_tables.c +++ b/src/overlays/l01/level_class_tables.c @@ -6,7 +6,7 @@ #include "rnc/camera/update_cam.h" #include "rnc/mobys/moby_class_tables.h" -void FUN_L00_002caf40(); +void get_morphoray_chicken_slot_record() __asm__("FUN_L00_002caf40"); void FUN_L00_002ea7a0(); void FUN_L00_002ed230(); void agnogg_ship_front_update() __asm__("FUN_L01_002fad68"); @@ -174,7 +174,7 @@ void *D_L01_0020C3C4[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; void *D_L01_0020C3DC[6] diff --git a/src/overlays/l02/level_class_tables.c b/src/overlays/l02/level_class_tables.c index 859e6cb7ff..363266eda2 100644 --- a/src/overlays/l02/level_class_tables.c +++ b/src/overlays/l02/level_class_tables.c @@ -6,7 +6,7 @@ #include "rnc/camera/update_cam.h" #include "rnc/mobys/moby_class_tables.h" -void FUN_L00_002caf40(); +void get_morphoray_chicken_slot_record() __asm__("FUN_L00_002caf40"); void FUN_L00_002ea7a0(); void FUN_L00_002ed230(); void background_ship_1_update() __asm__("FUN_L02_002ec4b8"); @@ -146,7 +146,7 @@ void *D_L02_001FB6C4[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; void *D_L02_001FB6DC[6] diff --git a/src/overlays/l03/level_class_tables.c b/src/overlays/l03/level_class_tables.c index 6531f9a699..e684c12245 100644 --- a/src/overlays/l03/level_class_tables.c +++ b/src/overlays/l03/level_class_tables.c @@ -22,6 +22,7 @@ #include "rnc/overlay/shared/ui/hud/hud_keep_visible.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" @@ -57,7 +58,7 @@ void *D_L03_001E4114[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; struct MobyClassUpdate moby_classes[181] __asm__("D_L03_001E3880") diff --git a/src/overlays/l04/level_class_tables.c b/src/overlays/l04/level_class_tables.c index 5b4f32efad..62bc1a17de 100644 --- a/src/overlays/l04/level_class_tables.c +++ b/src/overlays/l04/level_class_tables.c @@ -17,6 +17,7 @@ #include "rnc/overlay/shared/ui/hud/hud_keep_visible.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" @@ -50,7 +51,7 @@ void *D_L04_001DD104[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; void *D_L04_001DD11C[6] diff --git a/src/overlays/l05/level_class_tables.c b/src/overlays/l05/level_class_tables.c index c8d52bf94d..577385bda1 100644 --- a/src/overlays/l05/level_class_tables.c +++ b/src/overlays/l05/level_class_tables.c @@ -18,6 +18,7 @@ #include "rnc/overlay/shared/vehicles.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" @@ -52,7 +53,7 @@ void *D_L05_002193D0[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; void *D_L05_002193E8[6] diff --git a/src/overlays/l06/level_class_tables.c b/src/overlays/l06/level_class_tables.c index c6106728d9..4c8caa4da0 100644 --- a/src/overlays/l06/level_class_tables.c +++ b/src/overlays/l06/level_class_tables.c @@ -20,6 +20,7 @@ #include "rnc/overlay/shared/ui/hud/hud_keep_visible.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" @@ -53,7 +54,7 @@ void *D_L06_0020239C[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; void *D_L06_002023B4[6] diff --git a/src/overlays/l07/level_class_tables.c b/src/overlays/l07/level_class_tables.c index 7a4c013628..f76d0a6d24 100644 --- a/src/overlays/l07/level_class_tables.c +++ b/src/overlays/l07/level_class_tables.c @@ -6,7 +6,7 @@ #include "rnc/camera/update_cam.h" #include "rnc/mobys/moby_class_tables.h" -void FUN_L00_002caf40(); +void get_morphoray_chicken_slot_record() __asm__("FUN_L00_002caf40"); void FUN_L00_002ea7a0(); void blarg_helicopter_update() __asm__("FUN_L03_002cca00"); void blaster_update() __asm__("FUN_L00_002b49a8"); @@ -147,7 +147,7 @@ void *D_L07_002125DC[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; struct MobyClassUpdate moby_classes[187] __asm__("D_L07_00211D00") diff --git a/src/overlays/l08/level_class_tables.c b/src/overlays/l08/level_class_tables.c index 287e8b0f5b..58d24a7228 100644 --- a/src/overlays/l08/level_class_tables.c +++ b/src/overlays/l08/level_class_tables.c @@ -19,6 +19,7 @@ #include "rnc/overlay/shared/ui/hud/hud_keep_visible.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" @@ -59,7 +60,7 @@ void *D_L08_001FD218[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; struct MobyClassUpdate moby_classes[190] __asm__("D_L08_001FC900") diff --git a/src/overlays/l09/level_class_tables.c b/src/overlays/l09/level_class_tables.c index 90a21bae16..dba32b9024 100644 --- a/src/overlays/l09/level_class_tables.c +++ b/src/overlays/l09/level_class_tables.c @@ -17,6 +17,7 @@ #include "rnc/overlay/shared/vehicles.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" @@ -57,7 +58,7 @@ void *D_L09_00209B18[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; struct MobyClassUpdate moby_classes[158] __asm__("D_L09_00209380") diff --git a/src/overlays/l10/level_class_tables.c b/src/overlays/l10/level_class_tables.c index 50a6c6e77e..7f53cf4bb5 100644 --- a/src/overlays/l10/level_class_tables.c +++ b/src/overlays/l10/level_class_tables.c @@ -6,7 +6,7 @@ #include "rnc/camera/update_cam.h" #include "rnc/mobys/moby_class_tables.h" -void FUN_L00_002caf40(); +void get_morphoray_chicken_slot_record() __asm__("FUN_L00_002caf40"); void FUN_L00_002ea7a0(); void FUN_L00_002ed230(); void update_path_flythrough_camera() __asm__("FUN_L10_002f5f18"); @@ -163,7 +163,7 @@ void *D_L10_001DDE40[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; void *D_L10_001DDE58[6] diff --git a/src/overlays/l11/level_class_tables.c b/src/overlays/l11/level_class_tables.c index 16889999bd..b9aa616272 100644 --- a/src/overlays/l11/level_class_tables.c +++ b/src/overlays/l11/level_class_tables.c @@ -6,7 +6,7 @@ #include "rnc/camera/update_cam.h" #include "rnc/mobys/moby_class_tables.h" -void FUN_L00_002caf40(); +void get_morphoray_chicken_slot_record() __asm__("FUN_L00_002caf40"); void FUN_L00_002ea7a0(); void FUN_L00_002ed230(); void ammocrate_update() __asm__("FUN_L11_0030f728"); @@ -152,7 +152,7 @@ void *D_L11_0021BFF0[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; void *D_L11_0021C008[6] diff --git a/src/overlays/l12/level_class_tables.c b/src/overlays/l12/level_class_tables.c index de3335d2bf..dd9a8d1999 100644 --- a/src/overlays/l12/level_class_tables.c +++ b/src/overlays/l12/level_class_tables.c @@ -19,6 +19,7 @@ #include "rnc/overlay/shared/ui/hud/hud_keep_visible.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" @@ -61,7 +62,7 @@ void *D_L12_0020D240[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; struct MobyClassUpdate moby_classes[140] __asm__("D_L12_0020CB80") diff --git a/src/overlays/l13/level_class_tables.c b/src/overlays/l13/level_class_tables.c index c400f3aa10..9cc3df6b4a 100644 --- a/src/overlays/l13/level_class_tables.c +++ b/src/overlays/l13/level_class_tables.c @@ -6,7 +6,7 @@ #include "rnc/camera/update_cam.h" #include "rnc/mobys/moby_class_tables.h" -void FUN_L00_002caf40(); +void get_morphoray_chicken_slot_record() __asm__("FUN_L00_002caf40"); void FUN_L00_002ea7a0(); void update_path_flythrough_camera() __asm__("FUN_L10_002f5f18"); void ammocrate_update() __asm__("FUN_L13_002e1cc8"); @@ -172,7 +172,7 @@ void *D_L13_001F618C[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; struct MobyClassUpdate moby_classes[189] __asm__("D_L13_001F5880") diff --git a/src/overlays/l14/level_class_tables.c b/src/overlays/l14/level_class_tables.c index c40fea5294..bd8ee7c3a4 100644 --- a/src/overlays/l14/level_class_tables.c +++ b/src/overlays/l14/level_class_tables.c @@ -6,7 +6,7 @@ #include "rnc/camera/update_cam.h" #include "rnc/mobys/moby_class_tables.h" -void FUN_L00_002caf40(); +void get_morphoray_chicken_slot_record() __asm__("FUN_L00_002caf40"); void FUN_L00_002ea7a0(); void FUN_L00_002ed230(); void update_path_flythrough_camera() __asm__("FUN_L10_002f5f18"); @@ -175,7 +175,7 @@ void *D_L14_001FD9E8[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; struct MobyClassUpdate moby_classes[154] __asm__("D_L14_001FD280") diff --git a/src/overlays/l15/level_class_tables.c b/src/overlays/l15/level_class_tables.c index 0e0537acfb..0a521b1880 100644 --- a/src/overlays/l15/level_class_tables.c +++ b/src/overlays/l15/level_class_tables.c @@ -6,7 +6,7 @@ #include "rnc/camera/update_cam.h" #include "rnc/mobys/moby_class_tables.h" -void FUN_L00_002caf40(); +void get_morphoray_chicken_slot_record() __asm__("FUN_L00_002caf40"); void FUN_L00_002ea7a0(); void FUN_L00_002ed230(); void update_path_flythrough_camera() __asm__("FUN_L10_002f5f18"); @@ -170,7 +170,7 @@ void *D_L15_001E3EB4[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; struct MobyClassUpdate moby_classes[171] __asm__("D_L15_001E3680") diff --git a/src/overlays/l16/level_class_tables.c b/src/overlays/l16/level_class_tables.c index c03a9c82eb..e9060aa13b 100644 --- a/src/overlays/l16/level_class_tables.c +++ b/src/overlays/l16/level_class_tables.c @@ -20,6 +20,7 @@ #include "rnc/overlay/shared/vehicles.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" @@ -54,7 +55,7 @@ void *D_L16_001E9038[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; void *D_L16_001E9050[6] __attribute__((section("lvl.vtbl"))) = {moby_hold_state_if_grabbed, diff --git a/src/overlays/l17/level_class_tables.c b/src/overlays/l17/level_class_tables.c index 4a65e5b12c..0d5abc6cee 100644 --- a/src/overlays/l17/level_class_tables.c +++ b/src/overlays/l17/level_class_tables.c @@ -18,6 +18,7 @@ #include "rnc/overlay/shared/vehicles.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" @@ -51,7 +52,7 @@ void *D_L17_001E783C[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; void *D_L17_001E7854[6] diff --git a/src/overlays/l18/level_class_tables.c b/src/overlays/l18/level_class_tables.c index ab29117b6e..fd33650535 100644 --- a/src/overlays/l18/level_class_tables.c +++ b/src/overlays/l18/level_class_tables.c @@ -19,6 +19,7 @@ #include "rnc/overlay/shared/vehicles.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" @@ -52,7 +53,7 @@ void *D_L18_001F3480[6] moby_set_state_from_check, launch_suck_cannon_projectile_and_update_moby_state, cancel_suck_cannon_suction_and_set_moby_state_5, - FUN_L00_002caf40, + get_morphoray_chicken_slot_record, hud_counter_update}; void *D_L18_001F3498[6] __attribute__((section("lvl.vtbl"))) = {update_moby_state_pause, diff --git a/src/overlays/shared/weapons/morphoray_chicken.c b/src/overlays/shared/weapons/morphoray_chicken.c index 28e6c74ead..356ef26f3d 100644 --- a/src/overlays/shared/weapons/morphoray_chicken.c +++ b/src/overlays/shared/weapons/morphoray_chicken.c @@ -866,7 +866,9 @@ int cancel_suck_cannon_suction_and_set_moby_state_5(struct Moby *moby) { /* Returns the word at +0x14 of the moby data, or 0 when either pointer is null. */ -s32 FUN_L00_002caf40(s32 moby_address) { +s32 get_morphoray_chicken_slot_record(s32 moby_address) __asm__("FUN_L00_002caf40"); + +s32 get_morphoray_chicken_slot_record(s32 moby_address) { s32 moby_vars_address; if (moby_address != 0) { moby_vars_address = *(s32 *)((u8 *)moby_address + 0x78); From e0d26c957e6466e71a4aba6d4b8290b26d0a4fa6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:02:38 +0000 Subject: [PATCH 0194/1502] decomp: clarify names in reset_graphics value -> saved_gs_texture_allocation_start: In source src/rendering/frame/reset_graphics.c (SHA-256 5fa5ea821164a8cdda6cfa50e075dd2a746527099717bfb6f0baa0d87d15d09d), s32 value receives D_0015EE78[0] after vu1_init_chain and supplies D_0015EE78_gp after set_pal_mode. Retail 0x001f2230 loads that global (g_dwGsTextureAllocationStart in the prepared Ghidra) into callee-saved s0; s0 survives jal set_pal_mode at 0x001f2234 and is stored at 0x001f2240 in the second vu1_init_chain call's delay slot. Thus the local saves the GS texture allocation start across the mode call. --- src/rendering/frame/reset_graphics.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rendering/frame/reset_graphics.c b/src/rendering/frame/reset_graphics.c index e3bddbfbcb..8a87ba1ed4 100644 --- a/src/rendering/frame/reset_graphics.c +++ b/src/rendering/frame/reset_graphics.c @@ -19,7 +19,7 @@ extern s32 dmac_vif1_disable() __asm__("func_00233D90"); void reset_graphics(void) __asm__("FUN_001f21c0"); void reset_graphics(void) { - s32 value; + s32 saved_gs_texture_allocation_start; /* The volatile flag store stays out of the call's delay slot, and the do-while keeps the D_0015EE78 load after vu1_init_chain, as retail. */ @@ -33,11 +33,11 @@ void reset_graphics(void) { /* Fakematch: see the note at the top of the function. */ do { vu1_init_chain(); - value = D_0015EE78[0]; + saved_gs_texture_allocation_start = D_0015EE78[0]; } while (0); render_packet_cursor.addr = 0; set_pal_mode(); - D_0015EE78_gp = value; + D_0015EE78_gp = saved_gs_texture_allocation_start; vu1_init_chain(); dmac_vif1_enable(); } From 9cf0fb828f706c813aecab9ef49e161b534d4d2f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:02:38 +0000 Subject: [PATCH 0195/1502] decomp: clarify names in cvt value -> number_to_format: In cvt, f64 value is copied into value_bits for sign inspection and supplied to _dtoa_r to produce digits. Retail 0x00118370 saves the second argument in s2; 0x001183b0-0x001183d4 tests its upper-word sign and replaces negative input with 0 minus that number while recording '-'. At 0x001183e0 it is forwarded as the numeric argument to _dtoa_r (call 0x001183f0). Zero comparisons at 0x00118434-0x00118440 and 0x00118458-0x00118468 govern decimal-point adjustment and zero padding. Original Ghidra param_2 has the same data flow. This proves its role as the number to format rather than the format flags, precision, or returned digits. --- src/sdk/libc/stdio/cvt.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sdk/libc/stdio/cvt.c b/src/sdk/libc/stdio/cvt.c index 16b46ea3e9..811fdf497d 100644 --- a/src/sdk/libc/stdio/cvt.c +++ b/src/sdk/libc/stdio/cvt.c @@ -34,7 +34,7 @@ typedef union { #define ALT 0x001 static s8 *cvt(struct _reent *reentrancy_state, - f64 value, + f64 number_to_format, s32 ndigits, s32 flags, s8 *sign, @@ -54,23 +54,23 @@ static s8 *cvt(struct _reent *reentrancy_state, } mode = 2; } - value_bits.d = value; + value_bits.d = number_to_format; if (word0(value_bits) & Sign_bit) { - value = -value; + number_to_format = -number_to_format; *sign = '-'; } else { *sign = '\000'; } - digits = _dtoa_r(reentrancy_state, value, mode, ndigits, decpt, &dsgn, &rve); + digits = _dtoa_r(reentrancy_state, number_to_format, mode, ndigits, decpt, &dsgn, &rve); if ((ch != 'g' && ch != 'G') || (flags & ALT)) { bp = digits + ndigits; if (ch == 'f') { - if (*digits == '0' && value) { + if (*digits == '0' && number_to_format) { *decpt = -ndigits + 1; } bp += *decpt; } - if (value == 0) { + if (number_to_format == 0) { rve = bp; } while (rve < bp) { From ecff30c98107b2d07fa124723beec8f3cc44e9e8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:02:38 +0000 Subject: [PATCH 0196/1502] decomp: clarify names in _decMB0 result -> decode_success: Authoritative _decMB0 C (SHA-256 07424ed676ed54ffacf633b4553b7ccb0164e22c50d23a39bc1a913c5404fdec) initializes result to 0 before the forward/backward slice_error gates and returns that value on either failure; only the completion path assigns 1. Retail 0x00127e64/0x00127e68 and 0x00127ef0/0x00127ef4 branch to the epilogue with v0=0 on decode error; 0x00128020, 0x00128030 and 0x00128074 supply v0=1 on success. Original Ghidra likewise returns zero for dwDecodeError and one at completion. Supplied _slice0 treats _decMB0==0 as a decode failure. Thus this int represents decode success, not decoded macroblock data. --- src/sdk/mpeg/macroblock/_decMB0.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sdk/mpeg/macroblock/_decMB0.c b/src/sdk/mpeg/macroblock/_decMB0.c index d65335e343..fcea4a6867 100644 --- a/src/sdk/mpeg/macroblock/_decMB0.c +++ b/src/sdk/mpeg/macroblock/_decMB0.c @@ -42,7 +42,7 @@ int _decMB0(struct MpegDecoder *decoder, int field_in_frame; int dct_type; int motion_flag; - int result; + int decode_success; int coded; *((int *)0x10002010) = ((*((int *)0x10002010)) & 0xF8FFFFFF) | (decoder->picture_coding_type << 0x18); @@ -114,7 +114,7 @@ int _decMB0(struct MpegDecoder *decoder, decoder->full_pel_forward_vector); } } - result = 0; + decode_success = 0; if (decoder->slice_error == 0) { if ((*mb_type) & 4) { if (decoder->mpeg2 != 0) { @@ -141,7 +141,7 @@ int _decMB0(struct MpegDecoder *decoder, decoder->full_pel_backward_vector); } } - result = 0; + decode_success = 0; if (decoder->slice_error == 0) { type = *mb_type; coded = type & 3; @@ -181,9 +181,9 @@ int _decMB0(struct MpegDecoder *decoder, motion_vector_state->unk8 = 0; } coding_type = decoder->picture_coding_type; - result = 1; + decode_success = 1; if (coding_type == 2) { - result = 1; + decode_success = 1; if (!((*mb_type) & 9)) { motion_vector_state->unk0 = (motion_vector_state->unk4 = @@ -194,12 +194,12 @@ int _decMB0(struct MpegDecoder *decoder, *motion_type = 1; *motion_field_select_output = decoder->picture_structure == 2; } - result = 1; + decode_success = 1; } } - return result; + return decode_success; } - return result; + return decode_success; } - return result; + return decode_success; } From 5e345d1a3c5c5fd67ea53f89bbb4f73d243937d2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:02:38 +0000 Subject: [PATCH 0197/1502] decomp: clarify names in update_path_flythrough_camera dir -> initial_aim_or_previous_position: In the supplied C, float dir[4] receives target minus cam->pos in startup and is normalized into cam->m0. Retail 0x002f6064-0x002f6088 writes that subtraction to sp, and 0x002f60b0-0x002f60bc normalizes sp into the camera basis. Startup then returns. On the continuing path, 0x002f6208-0x002f621c copies the camera position at s6+0x30 to the same sp buffer before sample_path at 0x002f6240 changes that position. At 0x002f6448-0x002f645c, fast_vec_dist(sp, camera position) is added to run->dist. Original Ghidra likewise shows uStack_120 as the initial aim and later the saved position passed to the distance helper. Thus the binding is initial aim on startup or previous position during traversal. --- src/overlays/shared/camera/path_flythrough_camera.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/camera/path_flythrough_camera.c b/src/overlays/shared/camera/path_flythrough_camera.c index cd5cf0e394..1d09458eba 100644 --- a/src/overlays/shared/camera/path_flythrough_camera.c +++ b/src/overlays/shared/camera/path_flythrough_camera.c @@ -199,7 +199,7 @@ extern void debug_point_5f18(void *, float) __asm__("FUN_001e93e void update_path_flythrough_camera(struct UpdateCam *cam) __asm__("FUN_L10_002f5f18"); void update_path_flythrough_camera(struct UpdateCam *cam) { - float dir[4]; + float initial_aim_or_previous_position[4]; float offset[4]; float point[4]; float look_point[4]; @@ -237,12 +237,12 @@ void update_path_flythrough_camera(struct UpdateCam *cam) { offset[3] = 0.0f; transform_vector_by_basis(offset, offset, l10_path_camera_anchor_offset_basis); fast_vec_add(point, &anchor->pos, offset); - fast_vec_sub(dir, point, &cam->pos); + fast_vec_sub(initial_aim_or_previous_position, point, &cam->pos); } else { - fast_vec_sub(dir, look_path + 0x10, &cam->pos); + fast_vec_sub(initial_aim_or_previous_position, look_path + 0x10, &cam->pos); } fast_vec_scale(offset, D_0013F5E0_5f18, -1.0f); - fast_vec_normalize(&cam->m0, dir, 1.0f); + fast_vec_normalize(&cam->m0, initial_aim_or_previous_position, 1.0f); fast_vec_cross(&cam->m1, &cam->m0, offset); fast_vec_normalize(&cam->m1, &cam->m1, 1.0f); fast_vec_cross(&cam->m2, &cam->m1, &cam->m0); @@ -275,7 +275,7 @@ void update_path_flythrough_camera(struct UpdateCam *cam) { l10_path_camera_transition_amount = 0.0f; } path = ((char *)l10_paths[*(int *)(rec + 0x20)]); - qcopy(dir, &cam->pos); + qcopy(initial_aim_or_previous_position, &cam->pos); done = FUN_L00_0025d808( path, &cam->pos.x, &run->seg, &run->t, 0, *(float *)(rec + 0x3C) * frame_time); if (run->timer != 0) { @@ -312,7 +312,7 @@ void update_path_flythrough_camera(struct UpdateCam *cam) { update_view_context(); } } - run->dist += fast_vec_dist(dir, &cam->pos); + run->dist += fast_vec_dist(initial_aim_or_previous_position, &cam->pos); if (*(int *)(rec + 0x28) >= 0) { struct Moby *anchor = (struct Moby *)(D_L10_0015FFD8_5f18 + *(int *)(rec + 0x28) * 256); float *ofs = (float *)(rec + 0x2C); From dd5eb38ae1e177eae58cfc34a55b7af6c9be0b8b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:04:34 +0000 Subject: [PATCH 0198/1502] decomp: clarify names in srand value -> seed: In the authoritative srand.c snapshot (SHA-256 dd2c79a8d8dceefed023eaadb94d4642eefe05e8836ddc1abbf755a27136c74c), int value is assigned directly to _impure_ptr->_rand_next. Retail 0x001160cc loads PTR_DAT_0012f76c and 0x001160d4 stores incoming a0 at offset 0x58, exactly matching the original Ghidra param_1 store. The established srand function and update_sky_effects caller's srand(0x3039) before rand() establish that this argument is the random seed. --- src/sdk/libc/stdlib/srand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdk/libc/stdlib/srand.c b/src/sdk/libc/stdlib/srand.c index 3fccc1c69e..8dc692ca37 100644 --- a/src/sdk/libc/stdlib/srand.c +++ b/src/sdk/libc/stdlib/srand.c @@ -4,6 +4,6 @@ void srand(int value) __asm__("func_001160C8"); -void srand(int value) { - _impure_ptr->_rand_next = value; +void srand(int seed) { + _impure_ptr->_rand_next = seed; } From c3a17d786eb7fef90020a2fdf277f2e0e3a12300 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:04:34 +0000 Subject: [PATCH 0199/1502] decomp: clarify names in decoy_glove_aim_throw value -> aim_slope_or_extension_scale: Retail 0x002d23fc-0x002d2438 computes launch XY length, loads launch Z from sp+0xa8, and divides Z by XY length or 0.01 into f20: source value = rise / length (or 0.01). At 0x002d24a0 and 0x002d24cc this slope enters 1-value and vertical=value*distance. In the no-hit branch 0x002d2580-0x002d25c4 the same f20 is overwritten with 5.0 and multiplies all three aim displacement components before addition of camera position, matching source value=5.0 and its use as the aim extension scale. --- src/overlays/shared/weapons/decoy_glove.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/shared/weapons/decoy_glove.c b/src/overlays/shared/weapons/decoy_glove.c index 6dfd3447db..6103f35b56 100644 --- a/src/overlays/shared/weapons/decoy_glove.c +++ b/src/overlays/shared/weapons/decoy_glove.c @@ -103,7 +103,7 @@ void decoy_glove_aim_throw(int collision_arg, Moby_2D3608 *carrier, float *posit Vec_2D3608 direction, aim, launch, origin_copy, endpoint; Moby_2D3608 *target; float *output; - float value, distance, heading, vertical, pitch, length, fall_time; + float aim_slope_or_extension_scale, distance, heading, vertical, pitch, length, fall_time; int hit; float range; float *anchor_ptr = anchor; @@ -153,15 +153,15 @@ void decoy_glove_aim_throw(int collision_arg, Moby_2D3608 *carrier, float *posit { float rise = launch[2]; if (length != 0.0f) { - value = rise / length; + aim_slope_or_extension_scale = rise / length; } else { - value = rise / 0.00999999978f; + aim_slope_or_extension_scale = rise / 0.00999999978f; } } fall_time = square_root(D_0015ED70 * 9.0f * ((controller_state.held & 5) ? 3.5f : 2.5f) * 0.5f); - distance = (fall_time + fall_time) * fall_time * (1.0f - value) / (D_0015ED70 * 9.0f); - vertical = value * distance; + distance = (fall_time + fall_time) * fall_time * (1.0f - aim_slope_or_extension_scale) / (D_0015ED70 * 9.0f); + vertical = aim_slope_or_extension_scale * distance; if (0.0f < distance) { launch[0] = func_001F9F90_2D3608(heading) * distance; launch[1] = func_001F9FA8_2D3608(heading) * distance; @@ -175,10 +175,10 @@ void decoy_glove_aim_throw(int collision_arg, Moby_2D3608 *carrier, float *posit heading = fast_arc_tan(aim[0] - anchor_ptr[0], aim[1] - anchor_ptr[1]); } if (hit == 0) { - value = 5.0f; - aim[0] = func_001F9F90_2D3608(heading) * distance * value; - aim[1] = func_001F9FA8_2D3608(heading) * distance * value; - aim[2] = vertical * value; + aim_slope_or_extension_scale = 5.0f; + aim[0] = func_001F9F90_2D3608(heading) * distance * aim_slope_or_extension_scale; + aim[1] = func_001F9FA8_2D3608(heading) * distance * aim_slope_or_extension_scale; + aim[2] = vertical * aim_slope_or_extension_scale; fast_vec_add(aim, aim, g_debug_camera.position); } } From 161e66d279ef30ed072448710ffc489f921fe9c1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:04:35 +0000 Subject: [PATCH 0200/1502] decomp: clarify names in update_blarg_paratrooper_damage_and_state switch_0_case_2 -> PARATROOPER_HIT_REACTION_DEATH_KNOCKBACK: The selector is the resolve_moby_hit_response return at retail 0x00302624, retained through 0x00302670 unless class/health overrides apply. The original Ghidra switch and bound source place reaction 2 with lethal reaction 1 at 0x00302794. This branch initializes horizontal/vertical knockback at instance+0x88/+0x8c, calls trooper_start_knockback at 0x00302854 with animation 12, writes moby state 11 at 0x00302864, and drops bolts at 0x0030287c. The caller source identifies moby state 11 as death effects and removal. Thus DEATH_KNOCKBACK names its proven reaction action without claiming that reaction 2 itself means depleted health or a particular weapon. --- src/overlays/shared/enemies/blarg_paratrooper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/blarg_paratrooper.c b/src/overlays/shared/enemies/blarg_paratrooper.c index 58ebdc38b4..5fab765e5b 100644 --- a/src/overlays/shared/enemies/blarg_paratrooper.c +++ b/src/overlays/shared/enemies/blarg_paratrooper.c @@ -601,7 +601,7 @@ void blarg_paratrooper_update(char *moby) { /* Ported from rac1-decomp (src/overlays/shared/vendor_002D3DF8.c: func_L08_00303998), where it is exact; names translated to the US level program. */ void update_blarg_paratrooper_damage_and_state(char *moby) { - enum { PARATROOPER_HIT_REACTION_LETHAL = 1 , PARATROOPER_HIT_REACTION_NONE = 11} ;Paratrooper302618 *data; + enum { PARATROOPER_HIT_REACTION_LETHAL = 1 , PARATROOPER_HIT_REACTION_DEATH_KNOCKBACK = 2, PARATROOPER_HIT_REACTION_NONE = 11} ;Paratrooper302618 *data; char *target, *child, *attached, *chased; float pos[4] __attribute__((aligned(16))); float matrix[16] __attribute__((aligned(16))); @@ -699,7 +699,7 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { data->unk67 = 0x78; break; case PARATROOPER_HIT_REACTION_LETHAL: - case 2: { + case PARATROOPER_HIT_REACTION_DEATH_KNOCKBACK: { float push_limit = 16.0f; float pose_rate = D_L08_00162184; float timer_rate = l08_paratrooper_death_knockback_xy_speed; From c590c01a8d1ced6a638767a0b9531f1aa98f969f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:06:45 +0000 Subject: [PATCH 0201/1502] decomp: clarify names in update_unfolding_column_piece switch_0_case_2 -> UNFOLDING_COLUMN_PIECE_RELEASE: Authoritative src/overlays/l14/mobys/unfolding_column_piece.c snapshot SHA-256 7be557e8e5dafe1f42f30a0485beb1c017a58a1ed224aa7b19cb77d6df9e39db explicitly states that unfolding_column releases its piece at state 2. Selector is this piece moby's state: retail 003061dc reads byte +0x20, 003061e4/e8 compares with 2, 003061ec loads its pvars at +0x78; 0030621c/24 writes short pvars +0x3E = 5, and 00306220/2c advances the same moby's state to 3. Original Ghidra decompilation independently confirms both stores. This names the documented release entry only, not the unknown pvars field or later lifecycle. --- src/overlays/l14/mobys/unfolding_column_piece.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/unfolding_column_piece.c b/src/overlays/l14/mobys/unfolding_column_piece.c index 9d4ca356f7..cf4949db3e 100644 --- a/src/overlays/l14/mobys/unfolding_column_piece.c +++ b/src/overlays/l14/mobys/unfolding_column_piece.c @@ -7,7 +7,8 @@ void unfolding_column_piece_update(void *updated_moby) __asm__("FUN_L14_003061d8 /* Moby class 1397 */ void unfolding_column_piece_update(void *updated_moby) { enum { - MOBY_PVARS_INITIALIZE = 0 + MOBY_PVARS_INITIALIZE = 0, + UNFOLDING_COLUMN_PIECE_RELEASE = 2 }; struct Moby *moby = updated_moby; char *moby_pvars; @@ -20,7 +21,7 @@ void unfolding_column_piece_update(void *updated_moby) { *(short *)(moby_pvars + 0x3E) = 0; moby->state = 1; break; - case 2: + case UNFOLDING_COLUMN_PIECE_RELEASE: *(short *)(((char *)moby->pvars) + 0x3E) = 5; moby->state = 3; break; From 35e658e9f364072776faa85421fd4718a69462d2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:06:45 +0000 Subject: [PATCH 0202/1502] decomp: clarify names in set_batalia_cannon_platform_mode switch_0_case_0 -> CANNON_PLATFORM_CANNON_DESTROYED: In authoritative update_batalia_cannon, the health == 0 branch selects the moby indexed by cannon_control_vars->platform_index, ends the mount, positions the hero beside that platform and calls set_batalia_cannon_platform_mode(node, 0). The function comment explicitly identifies mode 0 as cannon destroyed. Original retail a1==0 branch at 00306b40 targets 00306b7c, then sb at 00306b80 writes payload+8=1 and sh at 00306b88 writes payload+0x36=4, agreeing with the source case. switch_0_case_1 -> CANNON_PLATFORM_TARGETS_CLEARED: In authoritative update_batalia_cannon, the loop counts signed-negative states of four indexed targets; CANNON_ALL_INDEXED_TARGETS_INACTIVE (4) ends mounting and calls set_batalia_cannon_platform_mode(node, 1) on the platform_index moby. The function comment identifies mode 1 as targets cleared. Original retail compares a1 with 1 at 00306b64, then 00306b70 writes payload+8=1 and 00306b78 writes payload+0x36=3, matching that source case. --- src/overlays/l08/mobys/batalia_cannon.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l08/mobys/batalia_cannon.c b/src/overlays/l08/mobys/batalia_cannon.c index 64cf4a06c3..40ace09f83 100644 --- a/src/overlays/l08/mobys/batalia_cannon.c +++ b/src/overlays/l08/mobys/batalia_cannon.c @@ -1191,16 +1191,20 @@ void request_batalia_cannon_mount(struct Moby *command_target_moby) { /* Puts the cannon's platform moby back in state 1, leaving with mode 3 (targets cleared, mode 1) * or 4 (cannon destroyed, mode 0); mode -1 respawns the hero instead. */ void set_batalia_cannon_platform_mode(u8 *platform, s32 mode) { + enum { + CANNON_PLATFORM_CANNON_DESTROYED = 0, + CANNON_PLATFORM_TARGETS_CLEARED = 1 + }; u8 *payload; platform[0x20] = 1; payload = *(u8 **)(platform + 0x78); switch (mode) { - case 1: + case CANNON_PLATFORM_TARGETS_CLEARED: payload[8] = 1; *(s16 *)(payload + 0x36) = 3; break; - case 0: + case CANNON_PLATFORM_CANNON_DESTROYED: payload[8] = 1; *(s16 *)(payload + 0x36) = 4; break; From 0deeb0e9a1c4e576894c29a8ccfea49aa4888477 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:06:55 +0000 Subject: [PATCH 0203/1502] decomp: clarify names in spawn_shuttle_explosion_effect D_L06_00162154 -> l06_shuttle_explosion_spark_table_index: With gp=0x00166c00, retail 0x00303ae0 loads D_L06_00162154 from gp-0x4aac; 0x00303af0 adds the shifted D_L06_00162158 and 0x00303af8 places this ninth spawn_spark argument on the stack before 0x00303b08. Checked level-06 helper 0x00277efc loads it into s1. At 0x00277f78-0x00277f94, s1 & 0xffff is multiplied by four to index the pointer table at 0x001b2800, whose pointed-to first byte initializes particle+2. This proves the unshifted global supplies the spark table index. D_L06_00162158 -> l06_shuttle_explosion_spark_alternate_mode_flag: Retail 0x00303ad8 loads D_L06_00162158 from gp-0x4aa8; 0x00303ae8 shifts it left 16 bits and 0x00303af0-0x00303af8 packs it into spawn_spark's ninth argument. In the checked level-06 helper, particle+3 is initialized to 0x44 at 0x00277f2c/0x00277f48. Instructions 0x00277f88-0x00277f98 test packed bit 0x10000; when set, 0x00277fa0-0x00277fa4 replace that mode byte with 0x48. Thus this global supplies the alternate particle mode flag; no specific visual behavior is inferred. --- src/overlays/l06/mobys/shuttle.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l06/mobys/shuttle.c b/src/overlays/l06/mobys/shuttle.c index 564b8fe937..730e83d4d7 100644 --- a/src/overlays/l06/mobys/shuttle.c +++ b/src/overlays/l06/mobys/shuttle.c @@ -208,8 +208,8 @@ extern int l06_shuttle_explosion_spark_timing_random_min_frames __asm__("D_L06 extern int l06_shuttle_explosion_spark_timing_base_a_frames __asm__("D_L06_00162148") __attribute__((sda)); extern int l06_shuttle_explosion_spark_timing_base_b_frames __asm__("D_L06_0016214C") __attribute__((sda)); extern int D_L06_00162150 __attribute__((sda)); -extern int D_L06_00162154 __attribute__((sda)); -extern int D_L06_00162158 __attribute__((sda)); +extern int l06_shuttle_explosion_spark_table_index __asm__("D_L06_00162154") __attribute__((sda)); +extern int l06_shuttle_explosion_spark_alternate_mode_flag __asm__("D_L06_00162158") __attribute__((sda)); extern void random_vector(void *, float, float) __asm__("FUN_L00_00257d78"); extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); extern u8 * @@ -745,7 +745,7 @@ void spawn_shuttle_explosion_effect(float scale, char *moby, char *pos, char *pu life, size, fade, - D_L06_00162154 + (D_L06_00162158 << 16)); + l06_shuttle_explosion_spark_table_index + (l06_shuttle_explosion_spark_alternate_mode_flag << 16)); } } From 84689ab1d11fe672be368951e17f1f17a8b5e35f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:07:05 +0000 Subject: [PATCH 0204/1502] decomp: clarify names in alien_queen_update D_L06_001678D0 -> l06_post_death_scan_records: In alien_queen_update state POST_DEATH, retail 002fa904..002fa950 starts a2 at 001678D0, advances it by 0xA0 per index and bounds the scan at 0x30. Each eligible record is read at signed-short offset +0x86 and passed as a0 to 00316330 when that field equals 0x12. The helper at 00316330..00316358 also reads +0x84 to select a referenced object and writes 1 to its +0x50. This proves the array supplies records for the post-death scan without asserting a subsystem or structure type. D_L06_0016A010 -> l06_post_death_scan_record_gates: Retail 002fa900..002fa948 initializes v1 to 0016A010 and advances it by four bytes in parallel with 001678D0's 0xA0-stride records. At 002fa938 it loads the word, and 002fa93c skips the corresponding record when zero; otherwise 002fa944 reads that record's +0x86. Source expresses exactly D_L06_0016A010[i] != 0 before selecting the record. Thus each word gates eligibility for the corresponding post-death scan record; its storage representation and broader subsystem are not inferred. --- src/overlays/l06/mobys/alien_queen.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l06/mobys/alien_queen.c b/src/overlays/l06/mobys/alien_queen.c index 2ea8fec3f4..e58f8c1ffc 100644 --- a/src/overlays/l06/mobys/alien_queen.c +++ b/src/overlays/l06/mobys/alien_queen.c @@ -114,8 +114,8 @@ typedef struct { int count; } QueenProbe; -extern char D_L06_001678D0[]; -extern int D_L06_0016A010[]; +extern char l06_post_death_scan_records[] __asm__("D_L06_001678D0"); +extern int l06_post_death_scan_record_gates[] __asm__("D_L06_0016A010"); extern short D_L06_00161EF0 __attribute__((sda)); extern short l06_alien_queen_movement_speed __asm__("D_L06_00161EF4") __attribute__((sda)); f32 alien_queen_movement_acceleration_gp __asm__("D_L06_00161EFC") = 8.0f; @@ -738,8 +738,8 @@ void alien_queen_update(unsigned char *moby) { int i; char *post_death_scan_record = 0; for (i = 0; i < 0x30; i++) { - if (D_L06_0016A010[i] != 0) { - post_death_scan_record = D_L06_001678D0 + i * 0xA0; + if (l06_post_death_scan_record_gates[i] != 0) { + post_death_scan_record = l06_post_death_scan_records + i * 0xA0; if (*(short *)(post_death_scan_record + 0x86) == 0x12) { release_moby_camera_control(post_death_scan_record); break; From 3270a3026543af4f98bf52f7ba51323b9630d4b5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:08:47 +0000 Subject: [PATCH 0205/1502] decomp: clarify names in select_hero_condition_animation_id switch_0_case_3 -> HERO_CONDITION_ANIMATION_ITEM_SWITCH: Authoritative hero_switch_item.c snapshot SHA-256 c322c7e580bcec1a01e0d2583bac60a8957d5b23d9b04b2c5cf69268f1bc59ae: hero_switch_item's changed branch calls set_hero_condition_animation_timer_for_item with the selected item; that function writes hero.unk22CE = 3 and hero.unk1DC = scale_game_frames(0x46) for its listed items. Checked retail caller 0x0020daf0 tests lh +0x1dc(s0), then 0x0020dafc loads lh a0,+0x22ce(s0) and 0x0020db00 calls the assigned function. Assigned retail 0x0020da34/38 compares selector against 3 and 0x0020da58/5c returns 0x75. Caller retains this animation ID in s2, compares animation-object byte +0x23 at 0x0020dcc0, and passes s2 as a2 to blend initialization at 0x0020dce4. Thus this case denotes the condition-animation selection installed by the item-switch timer, independent of hero state/control/vehicle IDs. --- src/overlays/shared/hero/hero_switch_item.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 17bbc3f08e..4735b88294 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -669,12 +669,15 @@ char *find_best_hero_heading_target(float range_limit, s32 select_hero_condition_animation_id(s32 animation_selector) __asm__("FUN_L00_0020da10"); s32 select_hero_condition_animation_id(s32 animation_selector) { + enum { + HERO_CONDITION_ANIMATION_ITEM_SWITCH = 3 + }; switch (animation_selector) { case 1: return 0x79; case 2: return 0x77; - case 3: + case HERO_CONDITION_ANIMATION_ITEM_SWITCH: return 0x75; } return 0; From e6221f428aec27bd2d06ffa79c47363ab0c6ecea Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:11:32 +0000 Subject: [PATCH 0206/1502] decomp: clarify names in update_blarg_paratrooper_damage_and_state switch_0_case_3 -> PARATROOPER_HIT_REACTION_RECOVERY_KNOCKBACK: The selector is the hit-response return from 0x00302624, with source-moby class 0x47 forcing reaction 3 at 0x00302648-0x00302670 unless health <= 0 forces lethal 1 at 0x00302674. Case 3 shares the retail branch at 0x003026e8: it sets scaled XY/Z knockback at instance+0x88/+0x8c, computes the away-from-hit-moby heading at 0x00302724-0x00302740, calls trooper_knockback_arc at 0x0030275c and trooper_start_knockback with animation 8 at 0x00302778, then writes moby state 10 at 0x00302788. The supplied blarg_paratrooper_update names state 10 PARATROOPER_STATE_KNOCKBACK_RECOVERY and resumes attack behavior upon landing. This proves a recovery-knockback action, without assigning an unproved weapon category or borrowing HeroStateId constants. --- src/overlays/shared/enemies/blarg_paratrooper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/blarg_paratrooper.c b/src/overlays/shared/enemies/blarg_paratrooper.c index 5fab765e5b..8793e9a920 100644 --- a/src/overlays/shared/enemies/blarg_paratrooper.c +++ b/src/overlays/shared/enemies/blarg_paratrooper.c @@ -601,7 +601,7 @@ void blarg_paratrooper_update(char *moby) { /* Ported from rac1-decomp (src/overlays/shared/vendor_002D3DF8.c: func_L08_00303998), where it is exact; names translated to the US level program. */ void update_blarg_paratrooper_damage_and_state(char *moby) { - enum { PARATROOPER_HIT_REACTION_LETHAL = 1 , PARATROOPER_HIT_REACTION_DEATH_KNOCKBACK = 2, PARATROOPER_HIT_REACTION_NONE = 11} ;Paratrooper302618 *data; + enum { PARATROOPER_HIT_REACTION_LETHAL = 1 , PARATROOPER_HIT_REACTION_DEATH_KNOCKBACK = 2, PARATROOPER_HIT_REACTION_RECOVERY_KNOCKBACK = 3, PARATROOPER_HIT_REACTION_NONE = 11} ;Paratrooper302618 *data; char *target, *child, *attached, *chased; float pos[4] __attribute__((aligned(16))); float matrix[16] __attribute__((aligned(16))); @@ -671,7 +671,7 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { case 10: data->unk67 = 0xfa; break; - case 3: + case PARATROOPER_HIT_REACTION_RECOVERY_KNOCKBACK: case 4: case 5: case 6: From 76f33d558237d2551f531eab17b279850b43f818 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:11:32 +0000 Subject: [PATCH 0207/1502] decomp: clarify names in request_taxi_destination_help_message switch_0_case_0 -> TAXI_DESTINATION_FIRST_STOP: Assigned retail 0x002e4ce0/0x002e4ce4 reads moby->pvars+0xAE; case 0 requests help 0x3e89 at 0x002e4d10. Checked taxi_update calls departure setup then this function at 0x002e4500/0x002e4508. Departure setup 0x002e4a6c..0x002e4abc maps current second stop (pvars+0xAC == 1) to destination 0. Initializer 0x002e4938..0x002e4984 establishes a three-entry stop list at +0x80 indexed 0..2; destination lookup 0x002e46d8..0x002e4718 uses +0xAE to select that same list's arrival pose. Thus 0 means destination first stop, as distinct from moby state or Hero enums. switch_0_case_1 -> TAXI_DESTINATION_SECOND_STOP: Retail selector at 0x002e4ce4 is the signed destination halfword +0xAE; case 1 requests 0x3e8a at 0x002e4d24. Checked departure helper 0x002e4a6c..0x002e4ad4 assigns +0xAE = 1 when departing current stop 0 or 2. Initializer 0x002e4938..0x002e4984 identifies current stops by a three-entry placement list at +0x80. Caller 0x002e46d8..0x002e4718 indexes that same list by +0xAE for arrival position/direction. Therefore 1 identifies the second stop as destination, not a state or control mode. switch_0_case_2 -> TAXI_DESTINATION_THIRD_STOP: Retail 0x002e4ce4 switches on pvars+0xAE and case 2 requests 0x139a at 0x002e4d38. Caller 0x002e46d8..0x002e4718 uses this exact halfword as the index into the stop placement list at +0x80 for the destination pose. Initializer 0x002e4914, 0x002e4938 and 0x002e4948..0x002e4984 iterates indices 0,1,2 over that list and stores the nearby stop index at +0xAC; 0x002e499c..0x002e49a4 explicitly recognizes stop 2. Authoritative prepare_taxi_departure_path names current index 2 TAXI_DEPART_FROM_THIRD_STOP, checked by branch 0x002e4a90. Thus selector 2 denotes the third stop in this list, without claiming a recovered location name or that the checked helper currently assigns it as a destination. --- src/overlays/l16/mobys/taxi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/overlays/l16/mobys/taxi.c b/src/overlays/l16/mobys/taxi.c index d9a89f5a32..1df667d0b3 100644 --- a/src/overlays/l16/mobys/taxi.c +++ b/src/overlays/l16/mobys/taxi.c @@ -411,14 +411,19 @@ int advance_taxi_path(struct Moby *moby) { void request_taxi_destination_help_message(struct Moby *moby) __asm__("FUN_L16_002e4cd8"); void request_taxi_destination_help_message(struct Moby *moby) { + enum { + TAXI_DESTINATION_FIRST_STOP = 0, + TAXI_DESTINATION_SECOND_STOP = 1, + TAXI_DESTINATION_THIRD_STOP = 2 + }; switch (*(short *)((char *)moby->pvars + 0xae)) { - case 0: + case TAXI_DESTINATION_FIRST_STOP: try_set_help_message(8, 0x3e89); break; - case 1: + case TAXI_DESTINATION_SECOND_STOP: try_set_help_message(8, 0x3e8a); break; - case 2: + case TAXI_DESTINATION_THIRD_STOP: try_set_help_message(8, 0x139A); break; case 3: From 308aa2be108b47a16eda89866a0c00b444cfc96e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:13:53 +0000 Subject: [PATCH 0208/1502] decomp: clarify names in spawn_shuttle_explosion_effect pos -> explosion_origin: The supplied break_apart_shuttle_linked_mobys caller passes the linked piece's Moby.pos as this char * argument. Retail 0x0030376c saves the incoming position pointer a1 at sp+0x90; cart_burst at 0x003037a4 receives it unchanged, and 0x003038cc loads it as spawn_particle's position argument for the call at 0x003038e0. Retail 0x00303938 generates a random offset at sp+0x10, then 0x00303944 loads this same pointer into a2 and 0x00303948 adds it to that offset. The resulting local position goes to spawn_spark at 0x00303b00-0x00303b08. Thus explosion_origin identifies the common spatial anchor rather than merely expanding pos. --- src/overlays/l06/mobys/shuttle.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l06/mobys/shuttle.c b/src/overlays/l06/mobys/shuttle.c index 730e83d4d7..978ea35012 100644 --- a/src/overlays/l06/mobys/shuttle.c +++ b/src/overlays/l06/mobys/shuttle.c @@ -673,12 +673,12 @@ int update_shuttle_path_ride(char *moby, int path) { void spawn_shuttle_explosion_effect(float scale, char *moby, char *pos, char *push, int count) __asm__("FUN_L06_00303748"); -void spawn_shuttle_explosion_effect(float scale, char *moby, char *pos, char *push, int count) { +void spawn_shuttle_explosion_effect(float scale, char *moby, char *explosion_origin, char *push, int count) { float position[4], direction[4], velocity[4], acceleration[4]; Colors first_colors, second_colors; int i; float strength; - cart_burst(moby, pos, -1, 2.0f, 13.0f); + cart_burst(moby, explosion_origin, -1, 2.0f, 13.0f); first_colors = D_L06_00201948; second_colors = D_L06_00201960; { @@ -701,7 +701,7 @@ void spawn_shuttle_explosion_effect(float scale, char *moby, char *pos, char *pu high = scale_game_frames(30); second_time = random_int_between(low, high); } - spawn_particle(pos, + spawn_particle(explosion_origin, push, *first_color, *second_color, @@ -717,7 +717,7 @@ void spawn_shuttle_explosion_effect(float scale, char *moby, char *pos, char *pu int color1, color2, life, size, fade; i++; random_vector(position, 0.0f, 1.0f); - fast_vec_add(position, position, pos); + fast_vec_add(position, position, explosion_origin); random_vector(direction, 0.0f, 0.9f); fast_vec_add(direction, direction, push); fast_vec_scale( From 5cc59e2fc34ef1c77bc747050291a19b8c9c4777 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:30:58 +0000 Subject: [PATCH 0209/1502] decomp: clarify names in circular_saw_enemy_update switch_1_case_9 -> CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED: Authoritative circular_saw_enemy.c SHA-256 b35558a20101e95affd5af6b155e4c5daae9ba97fcda99b2c593e03c1c141c4b shows launch_circular_saw_enemy_from_suck_cannon calling launch_suck_cannon_projectile and setting this same moby's state to 9 on success, returning it to IDLE on cessation. Assigned retail 002c28d0-002c28f0 dispatches moby+0x20, not a hero state or hit result. Original retail Ghidra case 9 and instructions 002c3750-002c3768 delegate to 002ded80 with moby and pvars+0xc0 and restore INITIALIZE on nonzero return; 002c3864-002c386c exits while state 9 remains, bypassing ordinary movement and gravity. Bounded checked helper export dfce3bafd80e488bad719f96547e0c64 shows 002deddc acquiring a moby record and 002dedf0-002dee24 dispatching its short at +0x68, consistent with the supplied suck-cannon record/launch method. These producer and consumer flows prove suck-cannon control; exact internal phases are not asserted. --- src/overlays/l04/mobys/circular_saw_enemy.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/overlays/l04/mobys/circular_saw_enemy.c b/src/overlays/l04/mobys/circular_saw_enemy.c index 74e0c5fc08..d0b74ec705 100644 --- a/src/overlays/l04/mobys/circular_saw_enemy.c +++ b/src/overlays/l04/mobys/circular_saw_enemy.c @@ -489,7 +489,8 @@ void circular_saw_enemy_update(M_35F0 *moby) { CIRCULAR_SAW_STATE_POINT_ATTACK = 5, CIRCULAR_SAW_STATE_HIT_RECOVERY = 6, CIRCULAR_SAW_STATE_MELEE_ATTACK = 7, - CIRCULAR_SAW_STATE_DYING = 8 + CIRCULAR_SAW_STATE_DYING = 8, + CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED = 9 }; enum { CIRCULAR_SAW_HIT_REACTION_NONE = 0, @@ -966,7 +967,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { return; } break; - case 9: + case CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED: if (FUN_L00_002dc9f0(moby, data->fC0) != 0) { moby->state = 0; data->f1E8 = 0; From 5df3f0a0e6cc8a24a9b858924ccd4d74b74322f6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:40:34 +0000 Subject: [PATCH 0210/1502] decomp: clarify names in sentrybot_alarm_update switch_0_case_10 -> SENTRYBOT_ALARM_STATE_ALARM_STOP_TRANSITION: Retail 002cb7f0-002cb834 enters state 10 with animation 8 when active pulse ends; the state-4 cancellation path 002cb72c-002cb734 shares this animation/state change without clearing pvars+8. At 002cba2c-002cba64 state 10 waits for moby+0x70 bit 2, then enters standby-return state 2 with animation 1. Thus the name describes the stop transition, not a guarantee that the active flag is cleared. switch_0_case_2 -> SENTRYBOT_ALARM_STATE_STANDBY_RETURN_TRANSITION: Retail 002cba2c-002cba64 enters state 2 with animation 1 from state 10. At 002cb624-002cb658, state 2 waits for moby+0x70 bit 2, then writes state 3 and blends animation 2. State 3 is the alarm-trigger waiting state, proving this is the return transition to standby. switch_0_case_3 -> SENTRYBOT_ALARM_STATE_WAIT_FOR_ALARM_TRIGGER: Retail initialization 002cb548-002cb568 selects state 3 and animation 2 for non-mode-2 alarms. At 002cb65c-002cb698 this state waits on pvars+8 (alarm_state[2]); when set and the external mode permits, it enters state 4 with animation 3. set_sentrybot_alarm_duration establishes pvars+8 as duration_frames != 0. switch_0_case_4 -> SENTRYBOT_ALARM_STATE_ALARM_START_TRANSITION: Retail 002cb65c-002cb698 enters state 4 after an alarm trigger, blending animation 3. At 002cb69c-002cb734 it waits for moby+0x70 bit 2 before choosing active pulse state 5 or group-release start state 7; a withdrawn trigger or external mode 2 instead takes the stop-animation path. This proves the common alarm-start transition without assigning a physical animation motion. switch_0_case_6 -> SENTRYBOT_ALARM_STATE_WAIT_FOR_GROUP_RELEASE_TRIGGER: Retail 002cb510-002cb544 initializes mode-2 alarms into state 6 with animation 4. At 002cb838-002cb868 state 6 waits for pvars+8, then enters state 7 with animation 5; state 7 leads to the established RELEASE_GROUP_MOBYS state 8. State 9 also returns mode-2 alarms here at 002cb9c0-002cb9f4. switch_0_case_7 -> SENTRYBOT_ALARM_STATE_GROUP_RELEASE_START_TRANSITION: Retail 002cb838-002cb868 and 002cb6cc-002cb6f4 enter state 7 with animation 5. At 002cb86c-002cb8a0 it waits for moby+0x70 bit 2, then writes state 8 and blends animation 6. State 8 performs the checked activate_first_inactive_group_moby call at 002cb930-002cb948, proving the start transition for group release. switch_0_case_9 -> SENTRYBOT_ALARM_STATE_GROUP_RELEASE_STOP_TRANSITION: Retail 002cb94c-002cb9ac stops the group-release duration, clears pvars+8, and enters state 9 with animation 7. At 002cb9b0-002cba20 this state waits for moby+0x70 bit 2, then returns mode-2 alarms to trigger-wait state 6 or enters common stop state 10. This proves the group-release stop transition. --- src/overlays/shared/enemies/sentrybot_alarm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/shared/enemies/sentrybot_alarm.c b/src/overlays/shared/enemies/sentrybot_alarm.c index f6b0ee5932..1c4020d574 100644 --- a/src/overlays/shared/enemies/sentrybot_alarm.c +++ b/src/overlays/shared/enemies/sentrybot_alarm.c @@ -90,7 +90,7 @@ void sentrybot_alarm_update(unsigned char *moby) __asm__("FUN_L15_002cb4c8"); /* Moby class 408 */ void sentrybot_alarm_update(unsigned char *moby) { - enum { SENTRYBOT_ALARM_STATE_INITIALIZE = 0 , SENTRYBOT_ALARM_STATE_STANDBY_PULSE = 1 , SENTRYBOT_ALARM_STATE_ACTIVE_PULSE = 5 , SENTRYBOT_ALARM_STATE_RELEASE_GROUP_MOBYS = 8 } ;float position[4]; + enum { SENTRYBOT_ALARM_STATE_INITIALIZE = 0 , SENTRYBOT_ALARM_STATE_STANDBY_PULSE = 1 , SENTRYBOT_ALARM_STATE_STANDBY_RETURN_TRANSITION = 2 , SENTRYBOT_ALARM_STATE_WAIT_FOR_ALARM_TRIGGER = 3 , SENTRYBOT_ALARM_STATE_ALARM_START_TRANSITION = 4 ,SENTRYBOT_ALARM_STATE_ACTIVE_PULSE = 5 , SENTRYBOT_ALARM_STATE_WAIT_FOR_GROUP_RELEASE_TRIGGER = 6 , SENTRYBOT_ALARM_STATE_GROUP_RELEASE_START_TRANSITION = 7 ,SENTRYBOT_ALARM_STATE_RELEASE_GROUP_MOBYS = 8 , SENTRYBOT_ALARM_STATE_GROUP_RELEASE_STOP_TRANSITION = 9 , SENTRYBOT_ALARM_STATE_ALARM_STOP_TRANSITION = 10} ;float position[4]; float step; int color; int mode; @@ -129,14 +129,14 @@ void sentrybot_alarm_update(unsigned char *moby) { } } break; - case 2: + case SENTRYBOT_ALARM_STATE_STANDBY_RETURN_TRANSITION: if (MOBY(moby)->anim_flags & 2) { MOBY(moby)->state = 3; if (MOBY(moby)->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(10)); } break; - case 3: + case SENTRYBOT_ALARM_STATE_WAIT_FOR_ALARM_TRIGGER: if (alarm_state[2] == 0) goto update; if (D_L15_0015F5C4 != 2) { @@ -145,7 +145,7 @@ void sentrybot_alarm_update(unsigned char *moby) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } break; - case 4: + case SENTRYBOT_ALARM_STATE_ALARM_START_TRANSITION: if (MOBY(moby)->anim_flags & 2) { if (alarm_state[2] == 0 || D_L15_0015F5C4 == 2) goto stop_animation; @@ -181,14 +181,14 @@ void sentrybot_alarm_update(unsigned char *moby) { MOBY(moby)->state = 10; } break; - case 6: + case SENTRYBOT_ALARM_STATE_WAIT_FOR_GROUP_RELEASE_TRIGGER: if (alarm_state[2] == 0) goto update; MOBY(moby)->state = 7; if (MOBY(moby)->prev_seq != 5) blend_moby_animation(moby, 5, 0, scale_game_frames(10)); break; - case 7: + case SENTRYBOT_ALARM_STATE_GROUP_RELEASE_START_TRANSITION: if (MOBY(moby)->anim_flags & 2) { MOBY(moby)->state = 8; if (MOBY(moby)->prev_seq != 6) @@ -215,7 +215,7 @@ void sentrybot_alarm_update(unsigned char *moby) { } break; } - case 9: + case SENTRYBOT_ALARM_STATE_GROUP_RELEASE_STOP_TRANSITION: if (MOBY(moby)->anim_flags & 2) { if (alarm_state[0] == 2) { MOBY(moby)->state = 6; @@ -228,7 +228,7 @@ void sentrybot_alarm_update(unsigned char *moby) { } } break; - case 10: + case SENTRYBOT_ALARM_STATE_ALARM_STOP_TRANSITION: if (MOBY(moby)->anim_flags & 2) { MOBY(moby)->state = 2; if (MOBY(moby)->prev_seq != 1) From d3854c12b6ef20db2b75b410034b0710b6cd2be7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 03:43:19 +0000 Subject: [PATCH 0211/1502] decomp: clarify names in alien_snapper_update switch_1_case_3 -> ALIEN_SNAPPER_ANIM_ACTIVATION: In the SHA-bound alien_snapper_update source, ALIEN_SNAPPER_STATE_ACTIVATION_SEQUENCE starts animation 3 after the initial sequence-0 delay, then completion chooses approach or face-goal/wait. Retail 0x002f80a0-0x002f80d0 decrements the activation timer, reads Moby+0x53 and requests sequence 3 through blend at 0x002f905c; 0x002f80d4-0x002f8168 gates subsequent active-state selection on animation completion bit 2. The clip trigger also requests sequence 3 at 0x002f81d8-0x002f81fc. In prepare-home-node-jump, 0x002f8200-0x002f8240 tests completion, dispatches Moby+0x53 == 3 and blends to sequence 6 (the established jump windup). Thus 3 is the activation animation shared by ordinary activation and clip-triggered pre-jump activation, not a HeroStateId or Moby.state constant. --- src/overlays/l06/mobys/alien_snapper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l06/mobys/alien_snapper.c b/src/overlays/l06/mobys/alien_snapper.c index d966a300ec..dbcc5f20ff 100644 --- a/src/overlays/l06/mobys/alien_snapper.c +++ b/src/overlays/l06/mobys/alien_snapper.c @@ -246,7 +246,7 @@ approach_angle(f32 *angle, f32 target, f32 *vel, f32, f32, f32) __asm__("FUN_L00 /* Moby class 1048 */ void alien_snapper_update(Moby *moby) { - enum { ALIEN_SNAPPER_STATE_INITIALIZE = 0 , ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION = 1 , ALIEN_SNAPPER_STATE_ACTIVATION_SEQUENCE = 2 ,ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER = 3 , ALIEN_SNAPPER_STATE_PREPARE_HOME_NODE_JUMP = 4 , ALIEN_SNAPPER_STATE_JUMP_TO_HOME_NODE = 5 , ALIEN_SNAPPER_STATE_FACE_GOAL_AND_WAIT = 6, ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH = 7 , ALIEN_SNAPPER_STATE_APPROACH_TARGET = 8 , ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET = 9 , ALIEN_SNAPPER_STATE_WAIT_FOR_REPOSITION_ANIMATION = 10, ALIEN_SNAPPER_STATE_BITE_TARGET = 11 , ALIEN_SNAPPER_STATE_RETURN_HOME = 12 , ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET = 13 , ALIEN_SNAPPER_STATE_HIT_KNOCKBACK = 14 , ALIEN_SNAPPER_STATE_FACE_HERO = 15 , ALIEN_SNAPPER_STATE_BITE_HERO = 16 , ALIEN_SNAPPER_STATE_DEATH_MOTION = 17 } ; enum { ALIEN_SNAPPER_ANIM_HOME_NODE_JUMP_WINDUP = 6} ;SnapperVars_91A8 *snapper_behavior = (SnapperVars_91A8 *)moby->pvars; + enum { ALIEN_SNAPPER_STATE_INITIALIZE = 0 , ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION = 1 , ALIEN_SNAPPER_STATE_ACTIVATION_SEQUENCE = 2 ,ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER = 3 , ALIEN_SNAPPER_STATE_PREPARE_HOME_NODE_JUMP = 4 , ALIEN_SNAPPER_STATE_JUMP_TO_HOME_NODE = 5 , ALIEN_SNAPPER_STATE_FACE_GOAL_AND_WAIT = 6, ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH = 7 , ALIEN_SNAPPER_STATE_APPROACH_TARGET = 8 , ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET = 9 , ALIEN_SNAPPER_STATE_WAIT_FOR_REPOSITION_ANIMATION = 10, ALIEN_SNAPPER_STATE_BITE_TARGET = 11 , ALIEN_SNAPPER_STATE_RETURN_HOME = 12 , ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET = 13 , ALIEN_SNAPPER_STATE_HIT_KNOCKBACK = 14 , ALIEN_SNAPPER_STATE_FACE_HERO = 15 , ALIEN_SNAPPER_STATE_BITE_HERO = 16 , ALIEN_SNAPPER_STATE_DEATH_MOTION = 17 } ; enum { ALIEN_SNAPPER_ANIM_ACTIVATION = 3 ,ALIEN_SNAPPER_ANIM_HOME_NODE_JUMP_WINDUP = 6} ;SnapperVars_91A8 *snapper_behavior = (SnapperVars_91A8 *)moby->pvars; Moby *target; float target_goal_radius; float target_gap_angle_radians; @@ -369,7 +369,7 @@ void alien_snapper_update(Moby *moby) { case ALIEN_SNAPPER_STATE_PREPARE_HOME_NODE_JUMP: if (moby->anim_flags & 2) { switch (moby->prev_seq) { - case 3: + case ALIEN_SNAPPER_ANIM_ACTIVATION: blend_moby_animation(moby, 6, 0, scale_game_frames(5)); break; case ALIEN_SNAPPER_ANIM_HOME_NODE_JUMP_WINDUP: From 24504e41f3070a95686ad772d58eddf3362a0480 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 11:38:06 +0000 Subject: [PATCH 0212/1502] decomp: reuse moby state enums and name angle helper calls --- include/rnc/overlay/l18/drek_boss_states.h | 31 ++++++++++++++++ src/overlays/l05/mobys/amoeboid.c | 4 +-- src/overlays/l05/mobys/extermibot.c | 17 +++++---- src/overlays/l05/mobys/rising_gate.c | 4 +-- src/overlays/l05/mobys/triggered_motion.c | 28 +++++++-------- src/overlays/l06/mobys/hangar_door.c | 4 +-- .../l18/mobys/drek_final_boss_robot.c | 36 ++++--------------- .../shared/vehicles/fighter_jet_rocket.c | 1 - 8 files changed, 67 insertions(+), 58 deletions(-) create mode 100644 include/rnc/overlay/l18/drek_boss_states.h diff --git a/include/rnc/overlay/l18/drek_boss_states.h b/include/rnc/overlay/l18/drek_boss_states.h new file mode 100644 index 0000000000..a9b485876b --- /dev/null +++ b/include/rnc/overlay/l18/drek_boss_states.h @@ -0,0 +1,31 @@ +#ifndef LOMBYTE_RNC_OVERLAY_L18_DREK_BOSS_STATES_H +#define LOMBYTE_RNC_OVERLAY_L18_DREK_BOSS_STATES_H + +/* Moby state IDs shared by the final boss update and its supporting handlers. */ +enum { + DREK_BOSS_INITIALIZE = 0, + DREK_BOSS_WAIT_FOR_ENCOUNTER_TRIGGER = 1, + DREK_BOSS_CIRCLE_AND_FIRE_AT_HERO = 2, + DREK_BOSS_WAIT_TO_RESTORE_SAVED_TRANSFORM = 3, + DREK_BOSS_WAIT_FOR_GROUNDED_HERO_TO_START_SCENE = 4, + DREK_BOSS_INITIALIZE_PAIRED_TRANSFORM_TRANSITION = 5, + DREK_BOSS_WAIT_FOR_SCENE = 7, + DREK_BOSS_WAIT_FOR_PAIRED_TRANSFORM_TRANSITION = 8, + DREK_BOSS_APPROACH_PATH_START = 9, + DREK_BOSS_FOLLOW_PATH_AND_FIRE_AT_MOBYS = 10, + DREK_BOSS_FINISH_PATH_AND_WAIT_FOR_HERO = 0xB, + DREK_BOSS_SELECT_NEXT_ACTION = 0xC, + DREK_BOSS_LAUNCH_FORWARD_WITH_LATERAL_OFFSET = 0xD, + DREK_BOSS_ACTION_REPOSITION_AND_AIM = 0xE, + DREK_BOSS_TARGET_GROUND_POINTS = 0xF, + DREK_BOSS_TARGET_RANDOM_ARENA_POINTS = 0x10, + DREK_BOSS_TARGET_SIDE_GROUND_POINTS = 0x11, + DREK_BOSS_APPROACH_AIM_NODE = 0x12, + DREK_BOSS_FOLLOW_HERO = 0x13, + DREK_BOSS_ACTIVATE_MISSILE_GROUP = 0x14, + DREK_BOSS_APPROACH_SELECTED_MOBY = 0x15, + DREK_BOSS_DEATH_EXPLOSIONS = 0x1A, + DREK_BOSS_RUN_ENDING_SEQUENCE = 0x1B +}; + +#endif /* LOMBYTE_RNC_OVERLAY_L18_DREK_BOSS_STATES_H */ diff --git a/src/overlays/l05/mobys/amoeboid.c b/src/overlays/l05/mobys/amoeboid.c index 3072548bb4..8d3aa91c4e 100644 --- a/src/overlays/l05/mobys/amoeboid.c +++ b/src/overlays/l05/mobys/amoeboid.c @@ -14,7 +14,7 @@ extern float fast_cos(float); extern float fast_sin(float); /* Ported from rac1-decomp (src/overlays/l05_rilgar/vendor_002D28D0.c: func_L05_002DBF10), where it is exact; names translated to the US level program. */ -extern float FUN_L00_0025be00(float *, float *, float, float, float, float); +extern float approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); extern int FUN_L00_00258b50(void *, void *, void *, void *, float); extern void FUN_L01_0026d930(char *p); extern void handle_amoeboid_hits(unsigned char *m) __asm__("FUN_L05_002daf58"); @@ -75,7 +75,7 @@ void amoeboid_update(struct Moby *moby) { char *path_node_base = ((char *)l05_paths[moby_data->path_B0]) + moby_data->unkB4 * 16; float yaw = fast_arc_tan(*(float *)(path_node_base + 0x10) - moby->pos.x, *(float *)(path_node_base + 0x14) - moby->pos.y); - FUN_L00_0025be00(&moby->rot.z, + approach_angle(&moby->rot.z, &moby_data->unkBC, yaw, frame_time_sq * 1.0471976f, diff --git a/src/overlays/l05/mobys/extermibot.c b/src/overlays/l05/mobys/extermibot.c index 6c4fce829b..1b1b3f0cd3 100644 --- a/src/overlays/l05/mobys/extermibot.c +++ b/src/overlays/l05/mobys/extermibot.c @@ -20,7 +20,7 @@ extern float random_angle_radians(void) __asm__("FUN_00213308"); extern float D_0015ED6C; extern float D_0015ED70; float absolute_float(float input) __asm__("func_001F99C0"); -extern float FUN_L00_0025be00(float *, float *, float, float, float, float); +extern float approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); extern int FUN_L00_00258b50(void *, void *, void *, void *, float); extern void FUN_L01_0026d930(char *p); /* Extermibot update: wakes from its dormant pose, walks its path, closes in on the target and strikes it, bursts into sparks between strikes, and dies on a hit. */ @@ -263,7 +263,7 @@ void extermibot_update(unsigned char *moby) { moby_position = moby + 0x10; yaw = fast_arc_tan(moby_data->goal[0] - MOBY(moby)->pos.x, moby_data->goal[1] - MOBY(moby)->pos.y); - FUN_L00_0025be00(moby_yaw_ptr, + approach_angle(moby_yaw_ptr, &moby_data->yaw_vel, yaw, D_0015ED70 * 6.2831855f, @@ -300,7 +300,7 @@ void extermibot_update(unsigned char *moby) { approach_value(&moby_data->speed, D_0015ED6C * 6.0f, D_0015ED70 * 6.0f); yaw = fast_arc_tan(MOBY(target_moby)->pos.x - MOBY(moby)->pos.x, MOBY(target_moby)->pos.y - MOBY(moby)->pos.y); - FUN_L00_0025be00(moby_yaw_ptr, + approach_angle(moby_yaw_ptr, &moby_data->yaw_vel, yaw, D_0015ED70 * 6.2831855f, @@ -400,7 +400,7 @@ void extermibot_update(unsigned char *moby) { moby_yaw_ptr = (float *)&MOBY(moby)->rot.z; yaw = fast_arc_tan(MOBY(target_moby)->pos.x - MOBY(moby)->pos.x, MOBY(target_moby)->pos.y - MOBY(moby)->pos.y); - FUN_L00_0025be00(moby_yaw_ptr, + approach_angle(moby_yaw_ptr, &moby_data->yaw_vel, yaw, D_0015ED70 * 12.566371f, @@ -950,7 +950,10 @@ extern f32 D_L05_00161A98_gp __asm__("D_L05_00161A98") __attribute__((sda)); extern f32 fast_difference_between_rotations(f32, f32) __asm__("FUN_001fa688"); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern f32 -approach_angle(f32 *angle, f32 target, f32 *vel, f32, f32, f32) __asm__("FUN_L00_0025be00"); +approach_angle(f32 *angle, f32 *vel, f32 target, f32, f32, f32) __asm__("FUN_L00_0025be00"); + +/* This handler uses the retail target-before-velocity C call view. */ +typedef f32 (*ApproachAngleTargetFirst)(f32 *, f32, f32 *, f32, f32, f32); extern s32 test_extermibot_offset_path_clearance(char *moby, float *goal, float s) __asm__("FUN_L05_00303e50"); @@ -984,14 +987,14 @@ void move_extermibot_along_path(struct Moby *moby, s32 destination_position, f32 (char *)moby, (float *)&goal, D_L05_00161A98_gp * 0.4f)) { offset_heading = fast_add_rotations(fast_arc_tan(goal.x - moby->pos.x, goal.y - moby->pos.y), side); - approach_angle(&moby->rot.z, + ((ApproachAngleTargetFirst)approach_angle)(&moby->rot.z, offset_heading, &walker_vars->yaw_vel, frame_time_sq * 12.566371f, frame_time_sq * 12.566371f, frame_time * 25.132742f); } else { - approach_angle(&moby->rot.z, + ((ApproachAngleTargetFirst)approach_angle)(&moby->rot.z, fast_arc_tan(goal.x - moby->pos.x, goal.y - moby->pos.y), &walker_vars->yaw_vel, frame_time_sq * 12.566371f, diff --git a/src/overlays/l05/mobys/rising_gate.c b/src/overlays/l05/mobys/rising_gate.c index f5880bb45e..45bf52017d 100644 --- a/src/overlays/l05/mobys/rising_gate.c +++ b/src/overlays/l05/mobys/rising_gate.c @@ -26,7 +26,7 @@ float gate_swing_max_speed_gp __asm__("D_L05_00161E94") = 1.44e+03f; extern int gate_mobys_314eb0 __asm__("D_L05_0015FFD8"); extern float advance_accelerated_scalar(float, float, float, float, float *, float *) __asm__("FUN_00213f38"); -extern float FUN_L00_0025be00(float *, float *, float, float, float, float); +extern float approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); /* Gate: waits for its trigger moby, then rises to topZ and swings its yaw back to 0, with sounds per class. */ void rising_gate_update(struct Moby *gate_moby) __asm__("FUN_L05_00314eb0"); @@ -73,7 +73,7 @@ void rising_gate_update(struct Moby *gate_moby) { allocate_voice_for_target_entry(0, 0, gate_moby); } if (fast_dec_timer(&gate_vars->swingTimer)) { - FUN_L00_0025be00(&gate_moby->rot.y, + approach_angle(&gate_moby->rot.y, &gate_vars->swingSpeed, 0.0f, gate_swing_acceleration_gp * 0.017453292f * frame_time_sq, diff --git a/src/overlays/l05/mobys/triggered_motion.c b/src/overlays/l05/mobys/triggered_motion.c index 3dee6b3c5c..ddea5dedc6 100644 --- a/src/overlays/l05/mobys/triggered_motion.c +++ b/src/overlays/l05/mobys/triggered_motion.c @@ -12,7 +12,7 @@ extern int allocate_voice_for_target_entry() __asm__("FUN_0022da68"); extern short D_L05_0015FFD8 __asm__("D_L05_0015FFD8"); extern float advance_accelerated_scalar(float, float, float, float, float *, float *) __asm__("FUN_00213f38"); -extern float FUN_L00_0025be00(float *, float *, float, float, float, float); +extern float approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern char *D_001413D0_lui __asm__("D_001413D0") NOT_SDA; @@ -59,14 +59,14 @@ void triggered_motion_update(char *moby) { attach_manipulator(moby, 0, &motion_and_manipulator_vars->manipulator_10); if (motion_and_manipulator_vars->unk54 != 0) { motion_and_manipulator_vars->unk60 = 0.0f; - MOBY(moby)->state = 2; + MOBY(moby)->state = MOBY_WAIT_TO_RETURN_TO_SAVED_POSITION; if (motion_and_manipulator_vars->unk50 != 0) fast_vec_scale(target, moby + 0xD0, 2.0f); else fast_vec_scale(target, moby + 0xD0, -2.0f); fast_vec_add(moby + 0x10, moby + 0x10, target); } else { - MOBY(moby)->state = 1; + MOBY(moby)->state = MOBY_WAIT_FOR_TRIGGER; motion_and_manipulator_vars->unk60 = 0.5934119f; build_axis_rotation_quaternion(&motion_and_manipulator_vars->unk20, 0, 0.5934119f); } @@ -78,28 +78,28 @@ void triggered_motion_update(char *moby) { ((u8 *)*(int *)&D_L05_0015FFD8)[motion_and_manipulator_vars->unk58 * 256 + 0xBC]; if (trigger == 0) return; - if (MOBY(moby)->state == 2 && trigger != 2) { - MOBY(moby)->state = 4; + if (MOBY(moby)->state == MOBY_WAIT_TO_RETURN_TO_SAVED_POSITION && trigger != 2) { + MOBY(moby)->state = MOBY_RETURN_TO_SAVED_POSITION; break; } - if (MOBY(moby)->state != 1) + if (MOBY(moby)->state != MOBY_WAIT_FOR_TRIGGER) return; allocate_voice_for_target_entry(0, 0, moby); - MOBY(moby)->state = 6; + MOBY(moby)->state = MOBY_SETTLE_AT_ZERO_MANIPULATOR_ANGLE; return; } case MOBY_SETTLE_AT_UPPER_MANIPULATOR_ANGLE: case MOBY_SETTLE_AT_ZERO_MANIPULATOR_ANGLE: { float end; float approach; - if (MOBY(moby)->state == 5) { + if (MOBY(moby)->state == MOBY_SETTLE_AT_UPPER_MANIPULATOR_ANGLE) { end = 0.5934119f; approach = 1.1868238f; } else { end = 0.0f; approach = -0.5934119f; } - FUN_L00_0025be00(&motion_and_manipulator_vars->unk60, + approach_angle(&motion_and_manipulator_vars->unk60, &motion_and_manipulator_vars->unk64, approach, frame_time_sq * 4.1887903f, @@ -115,10 +115,10 @@ void triggered_motion_update(char *moby) { MOBY(moby)->command = 1; motion_and_manipulator_vars->unk64 *= -0.33f; } else if (motion_and_manipulator_vars->unk60 == end) { - if (MOBY(moby)->state == 5) + if (MOBY(moby)->state == MOBY_SETTLE_AT_UPPER_MANIPULATOR_ANGLE) MOBY(moby)->state = 7; else - MOBY(moby)->state = 3; + MOBY(moby)->state = MOBY_MOVE_TO_OFFSET_POSITION; } } build_axis_rotation_quaternion( @@ -126,7 +126,7 @@ void triggered_motion_update(char *moby) { } break; case MOBY_MOVE_TO_OFFSET_POSITION: case MOBY_RETURN_TO_SAVED_POSITION: - if (MOBY(moby)->state == 3) { + if (MOBY(moby)->state == MOBY_MOVE_TO_OFFSET_POSITION) { fast_vec_scale(target, moby + 0xD0, -1.9f); fast_vec_add(target, motion_and_manipulator_vars, target); } else { @@ -145,12 +145,12 @@ void triggered_motion_update(char *moby) { fast_vec_add(moby + 0x10, moby + 0x10, delta); if (!(fast_vec_dist(moby + 0x10, target) < 0.0001f)) return; - if (MOBY(moby)->state == 3) { + if (MOBY(moby)->state == MOBY_MOVE_TO_OFFSET_POSITION) { allocate_voice_for_target_entry(1, 0, moby); MOBY(moby)->state = 7; return; } - MOBY(moby)->state = 5; + MOBY(moby)->state = MOBY_SETTLE_AT_UPPER_MANIPULATOR_ANGLE; break; } } diff --git a/src/overlays/l06/mobys/hangar_door.c b/src/overlays/l06/mobys/hangar_door.c index f0a012d363..34f2683022 100644 --- a/src/overlays/l06/mobys/hangar_door.c +++ b/src/overlays/l06/mobys/hangar_door.c @@ -11,7 +11,7 @@ /* Ported from rac1-decomp (src/overlays/l06_blarg/vendor_002B5990.c: func_L06_002B5990), where it is exact; names translated to the US level program. */ #include "rnc/overlay/shared/world/cuboid.h" -extern float FUN_L00_0025be00(float *, float *, float, float, float, float); +extern float approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); extern int D_L06_0015F5C4; void hangar_door_update(char *m) __asm__("FUN_L06_002b4770"); @@ -58,7 +58,7 @@ void hangar_door_update(char *door_moby) { door_data->unk10 = 0; } if (door_data->unk18 != door_data->unk14) { - FUN_L00_0025be00(&door_data->unk18, + approach_angle(&door_data->unk18, &door_data->unk8, door_data->unk14, frame_time_sq * 1.5707964f, diff --git a/src/overlays/l18/mobys/drek_final_boss_robot.c b/src/overlays/l18/mobys/drek_final_boss_robot.c index 37365b7606..fd27142eb4 100644 --- a/src/overlays/l18/mobys/drek_final_boss_robot.c +++ b/src/overlays/l18/mobys/drek_final_boss_robot.c @@ -1,5 +1,6 @@ /* Level 18 drek_final_boss_robot: the final boss fight. */ #include "types.h" +#include "rnc/overlay/l18/drek_boss_states.h" #include "rnc/overlay/shared/camera/level_camera.h" #include "rnc/audio/voice_pool.h" @@ -427,31 +428,6 @@ void spawn_drek_boss_firing_effects(char *moby, void *effect_position) __asm__(" /* Moby class 1422 */ void drek_final_boss_robot_update(BossMoby *moby) { - enum { - DREK_BOSS_INITIALIZE = 0, - DREK_BOSS_WAIT_FOR_ENCOUNTER_TRIGGER = 1, - DREK_BOSS_CIRCLE_AND_FIRE_AT_HERO = 2, - DREK_BOSS_WAIT_TO_RESTORE_SAVED_TRANSFORM = 3, - DREK_BOSS_WAIT_FOR_GROUNDED_HERO_TO_START_SCENE = 4, - DREK_BOSS_INITIALIZE_PAIRED_TRANSFORM_TRANSITION = 5, - DREK_BOSS_WAIT_FOR_SCENE = 7, - DREK_BOSS_WAIT_FOR_PAIRED_TRANSFORM_TRANSITION = 8, - DREK_BOSS_APPROACH_PATH_START = 9, - DREK_BOSS_FOLLOW_PATH_AND_FIRE_AT_MOBYS = 10, - DREK_BOSS_FINISH_PATH_AND_WAIT_FOR_HERO = 0xB, - DREK_BOSS_SELECT_NEXT_ACTION = 0xC, - DREK_BOSS_LAUNCH_FORWARD_WITH_LATERAL_OFFSET = 0xD, - DREK_BOSS_ACTION_REPOSITION_AND_AIM = 0xE, - DREK_BOSS_TARGET_GROUND_POINTS = 0xF, - DREK_BOSS_TARGET_RANDOM_ARENA_POINTS = 0x10, - DREK_BOSS_TARGET_SIDE_GROUND_POINTS = 0x11, - DREK_BOSS_APPROACH_AIM_NODE = 0x12, - DREK_BOSS_FOLLOW_HERO = 0x13, - DREK_BOSS_ACTIVATE_MISSILE_GROUP = 0x14, - DREK_BOSS_APPROACH_SELECTED_MOBY = 0x15, - DREK_BOSS_DEATH_EXPLOSIONS = 0x1A, - DREK_BOSS_RUN_ENDING_SEQUENCE = 0x1B - }; enum { DREK_BOSS_PHASE_FIRST_ARENA_PATH = 0, DREK_BOSS_PHASE_SECOND_ARENA_PATH = 1, @@ -1891,7 +1867,7 @@ void update_drek_boss_damage_and_phase_transitions(char *moby) { } if (step != 0.0f) { float unclamped_health; - if (MOBY(moby)->state == 2) { + if (MOBY(moby)->state == DREK_BOSS_CIRCLE_AND_FIRE_AT_HERO) { if (hit_record != 0 && (*(int *)(hit_record + 0x24) & 0x80000) && MOBY(moby)->prev_seq != 0xE) { blend_moby_animation(moby, 0xE, 5, 1); @@ -2246,7 +2222,7 @@ void update_drek_boss_arena_circling_movement(struct Moby *moby) { else if (circling_goal_angle < -0.17453292f) circling_goal_angle = -0.17453292f; circling_goal_angle = fast_add_rotations(circling_goal_angle, self_ang); - if (moby->state == 2) { + if (moby->state == DREK_BOSS_CIRCLE_AND_FIRE_AT_HERO) { goal.f[0] = fast_cos(circling_goal_angle) * drek_boss_circle_and_fire_radius_gp; goal.f[1] = fast_sin(circling_goal_angle) * drek_boss_circle_and_fire_radius_gp; goal.f[2] = 0.0f; @@ -2265,12 +2241,12 @@ void update_drek_boss_arena_circling_movement(struct Moby *moby) { far = drek_boss_circling_base_far_hero_distance_gp; slow = drek_boss_circling_default_far_hero_speed_gp; fast = drek_boss_circling_default_near_hero_speed_gp; - if (moby->state == 0xD) { + if (moby->state == DREK_BOSS_LAUNCH_FORWARD_WITH_LATERAL_OFFSET) { slow = 2.0f; fast = 5.5f; near *= 0.5f; far *= 0.5f; - } else if (moby->state == 0xF) { + } else if (moby->state == DREK_BOSS_TARGET_GROUND_POINTS) { slow = 6.0f; near *= 1.5f; fast = 10.0f; @@ -2598,7 +2574,7 @@ void update_drek_boss_state_dependent_scalars(char *moby) { set_animation_parameter(*(int *)(boss_data + 0x368), 0); *(int *)(boss_data + 0x368) = -1; } - if (MOBY(moby)->state >= 2) { + if (MOBY(moby)->state >= DREK_BOSS_CIRCLE_AND_FIRE_AT_HERO) { if (*(int *)(boss_data + 0x3ec) != 0 || D_L18_001623A0_gp != 0) { char *follow_camera_gate_record; follow_camera_gate_source = (char *)&l18_camera; diff --git a/src/overlays/shared/vehicles/fighter_jet_rocket.c b/src/overlays/shared/vehicles/fighter_jet_rocket.c index da77fdf641..de41bb590e 100644 --- a/src/overlays/shared/vehicles/fighter_jet_rocket.c +++ b/src/overlays/shared/vehicles/fighter_jet_rocket.c @@ -114,7 +114,6 @@ typedef struct Tex { extern float D_0015ED6C; extern int collision_line() __asm__("FUN_001efa68"); extern int FUN_L00_0024f7c8(); -float FUN_L00_0025be00(float *cur, float *vel, float target, float lim, float accel, float maxv); unsigned char *spawn_particle(void *pos, float *vec, int s, From ac688939356527fd7c6dab991a69735372db50da Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 12:07:17 +0000 Subject: [PATCH 0213/1502] overlay: name spawn_timed_hero_relative_particle --- .../overlay/shared/rendering/effects/particles.h | 2 +- src/overlays/l04/mobys/suck_cannon.c | 3 ++- src/overlays/l11/mobys/energy_sphere.c | 4 ++-- src/overlays/l14/mobys/morphoray_pickup.c | 4 ++-- src/overlays/l16/mobys/spinning_sprite_effect.c | 3 ++- src/overlays/shared/enemies/blarg_ship_rocket.c | 4 ++-- src/overlays/shared/pickups/gadget_pickup.c | 4 ++-- src/overlays/shared/pickups/gold_bolt.c | 4 ++-- src/overlays/shared/pickups/infobot.c | 3 ++- src/overlays/shared/pickups/nanotech_ball.c | 6 +++--- src/overlays/shared/pickups/pilots_helmet.c | 3 ++- src/overlays/shared/props/energy_sphere_holder.c | 3 ++- src/overlays/shared/rendering/effects/particles.c | 14 ++++++++++++-- 13 files changed, 36 insertions(+), 21 deletions(-) diff --git a/include/rnc/overlay/shared/rendering/effects/particles.h b/include/rnc/overlay/shared/rendering/effects/particles.h index a6e59e759b..c256e2d9d5 100644 --- a/include/rnc/overlay/shared/rendering/effects/particles.h +++ b/include/rnc/overlay/shared/rendering/effects/particles.h @@ -14,7 +14,7 @@ void *spawn_mode_controlled_rotating_alpha_fade_particle(void *, struct EmberParticle; struct EffectParticle; -unsigned char *FUN_L00_00272f68(u128 *, int, unsigned char, int, int, int, int, float); +unsigned char *spawn_timed_hero_relative_particle(u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); unsigned char *spawn_color_tween_emitter_particle(void *, unsigned char, unsigned char, diff --git a/src/overlays/l04/mobys/suck_cannon.c b/src/overlays/l04/mobys/suck_cannon.c index 5cb49061c9..663d52460e 100644 --- a/src/overlays/l04/mobys/suck_cannon.c +++ b/src/overlays/l04/mobys/suck_cannon.c @@ -13,6 +13,7 @@ #include "rnc/overlay/shared/world/level_labels.h" #include "rnc/overlay/shared/game/unlock_planet.h" #include "rnc/overlay/shared/rendering/effects/particles.h" +unsigned char *spawn_timed_hero_relative_particle(u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); #include "rnc/save/memcard_save_data.h" /* Warp portal: spins, opens once the hero is near, then warps to the exit moby. */ @@ -141,7 +142,7 @@ void update_suck_cannon_particles(char *moby) { timer_progress = timer_progress / (float)scale_game_frames(0xFF); col = fast_tween_color(0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - timer_progress)); if (D_L04_0015F5C4 != 2) - FUN_L00_00272f68(d, + spawn_timed_hero_relative_particle(d, col, truncate_float_to_s32(sprite_data->a[i]) & 0xFF, 0x35, diff --git a/src/overlays/l11/mobys/energy_sphere.c b/src/overlays/l11/mobys/energy_sphere.c index b3fadbe410..e6b5c8927c 100644 --- a/src/overlays/l11/mobys/energy_sphere.c +++ b/src/overlays/l11/mobys/energy_sphere.c @@ -225,7 +225,7 @@ void spawn_moby_radial_spark(struct Moby *source_moby) { extern float D_L11_001677C0_lui[] __asm__("D_L11_001677C0") NOT_SDA; extern int FUN_001fa6e0_q(int, int, float) __asm__("FUN_001fa6e0"); -extern unsigned char *FUN_L00_00272f68_q(float f, +extern unsigned char *spawn_timed_hero_relative_particle(float f, void *pos, int a1, unsigned char a2, @@ -257,7 +257,7 @@ void spawn_energy_sphere_particles(struct Moby *moby) { unsigned char updated_effect_byte; effect_byte_cursor[0] += effect_byte_cursor[4]; updated_effect_byte = truncate_float_to_s32((float)effect_byte_cursor[0]); - FUN_L00_00272f68_q(*(float *)(energy_sphere_vars + 0x1C) * + spawn_timed_hero_relative_particle(*(float *)(energy_sphere_vars + 0x1C) * convert_integer_to_float(effect_byte_cursor[8]) * 0.025f, effect_position, a, diff --git a/src/overlays/l14/mobys/morphoray_pickup.c b/src/overlays/l14/mobys/morphoray_pickup.c index 53df0096ea..dcdde375dd 100644 --- a/src/overlays/l14/mobys/morphoray_pickup.c +++ b/src/overlays/l14/mobys/morphoray_pickup.c @@ -156,7 +156,7 @@ typedef struct { extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); extern unsigned char * -FUN_L00_00272f68(float f, void *pos, int b, unsigned char a2, int idx, int flag, int s, int mode); +spawn_timed_hero_relative_particle(float f, void *pos, int b, unsigned char a2, int idx, int flag, int s, int mode) __asm__("FUN_L00_00272f68"); void update_morphoray_particles(struct Moby *morphoray_moby) { float particle_position_and_step[8]; @@ -191,7 +191,7 @@ void update_morphoray_particles(struct Moby *morphoray_moby) { elapsed_timer_fraction = elapsed_timer_fraction / (float)scale_game_frames(255); c = fast_tween_color(0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - elapsed_timer_fraction)); k = truncate_float_to_s32(*a++); - FUN_L00_00272f68(effect_data->c[j], particle_position_and_step, c, k, 0x35, 1, 2, 0); + spawn_timed_hero_relative_particle(effect_data->c[j], particle_position_and_step, c, k, 0x35, 1, 2, 0); j++; fast_vec_add( particle_position_and_step, particle_position_and_step, &particle_position_and_step[4]); diff --git a/src/overlays/l16/mobys/spinning_sprite_effect.c b/src/overlays/l16/mobys/spinning_sprite_effect.c index e1083dc78b..f3e310b216 100644 --- a/src/overlays/l16/mobys/spinning_sprite_effect.c +++ b/src/overlays/l16/mobys/spinning_sprite_effect.c @@ -16,6 +16,7 @@ #include "rnc/world/collision/collision_line.h" #include "rnc/math/random.h" #include "rnc/overlay/shared/rendering/effects/particles.h" +unsigned char *spawn_timed_hero_relative_particle(u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); #include "rnc/world/collision/ground_probe.h" /* updates the moby: initialises in state 0, then runs its motion in state 1 */ /* Ported from rac1-decomp (src/overlays/l16_kalebo3/vendor_002A50F0.c: func_L16_002CA848), where it is exact; names translated to the US level program. */ @@ -123,7 +124,7 @@ void draw_spinning_sprite_effect_sprites(struct Moby *moby) { elapsed_cycle_fraction = elapsed_cycle_fraction / (float)scale_game_frames(0xFF); col = fast_tween_color(0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - elapsed_cycle_fraction)); - FUN_L00_00272f68(d, + spawn_timed_hero_relative_particle(d, col, truncate_float_to_s32(sprite_data->a[i]) & 0xFF, 0x35, diff --git a/src/overlays/shared/enemies/blarg_ship_rocket.c b/src/overlays/shared/enemies/blarg_ship_rocket.c index 879edd34bf..9d5ad5c831 100644 --- a/src/overlays/shared/enemies/blarg_ship_rocket.c +++ b/src/overlays/shared/enemies/blarg_ship_rocket.c @@ -23,7 +23,7 @@ typedef struct { } L10SpriteData; extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); -extern unsigned char *func_L00_00273E08_298940( +extern unsigned char *spawn_timed_hero_relative_particle( void *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); void emit_moby_sprite_particles(char *moby) __asm__("FUN_L10_00298940"); @@ -54,7 +54,7 @@ void emit_moby_sprite_particles(char *moby) { color_blend_offset = convert_integer_to_float(scale_game_frames(0xFF) - sprite_data->c[i]); color_blend_offset = color_blend_offset / (float)scale_game_frames(0xFF); col = fast_tween_color(0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - color_blend_offset)); - func_L00_00273E08_298940(d, + spawn_timed_hero_relative_particle(d, col, truncate_float_to_s32(sprite_data->a[i]) & 0xFF, 0x35, diff --git a/src/overlays/shared/pickups/gadget_pickup.c b/src/overlays/shared/pickups/gadget_pickup.c index b4b562be12..8f66522471 100644 --- a/src/overlays/shared/pickups/gadget_pickup.c +++ b/src/overlays/shared/pickups/gadget_pickup.c @@ -57,7 +57,7 @@ extern float D_0015ED6C; extern float D_L02_0015F3FC; extern int func_001FA8A8_2ebce8_ea8b0(int, int, float) __asm__("FUN_001fa6e0"); -extern unsigned char *func_L00_00273E08_ea8b0( +extern unsigned char *spawn_timed_hero_relative_particle( void *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); extern char D_L02_00167440_ea8b0[] __asm__("D_L02_001673C0"); @@ -258,7 +258,7 @@ void update_collectible_sprite_effect(char *moby) { timer_elapsed_fraction = timer_elapsed_fraction / (float)scale_game_frames(0xFF); col = func_001FA8A8_2ebce8_ea8b0( 0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - timer_elapsed_fraction)); - func_L00_00273E08_ea8b0(d, + spawn_timed_hero_relative_particle(d, col, truncate_float_to_s32(sprite_data->a[i]) & 0xFF, 0x35, diff --git a/src/overlays/shared/pickups/gold_bolt.c b/src/overlays/shared/pickups/gold_bolt.c index 796e94d877..3da2b14641 100644 --- a/src/overlays/shared/pickups/gold_bolt.c +++ b/src/overlays/shared/pickups/gold_bolt.c @@ -66,7 +66,7 @@ extern void FUN_L01_003089f0_f(struct Moby *) __asm__("FUN_L01_003089f void update_gold_bolt_glow_rings(struct Moby *m) __asm__("FUN_L01_00308550"); extern void FUN_L01_003089f0_u(char *) __asm__("FUN_L01_003089f0"); extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); -extern unsigned char *FUN_L00_00272f68(void *, int, unsigned char, int, int, int, int, float); +extern unsigned char *spawn_timed_hero_relative_particle(void *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); extern void spawn_moving_hero_relative_alpha_fade_particle( void *, void *, int, int, int, int, float) __asm__("FUN_L00_002730e0"); @@ -709,7 +709,7 @@ void update_gold_bolt_glow_rings(struct Moby *moby) { packed_color = fast_tween_color(gold_bolt_glow_ring_tween_start_color_gp, gold_bolt_glow_ring_tween_end_color_gp, absolute_float(0.5f - pulse_progress)); - FUN_L00_00272f68(glow_particle_position, + spawn_timed_hero_relative_particle(glow_particle_position, packed_color, truncate_float_to_s32(ring_rotations[i]), gold_bolt_glow_ring_particle_texture_index_gp, diff --git a/src/overlays/shared/pickups/infobot.c b/src/overlays/shared/pickups/infobot.c index 5bda12090e..fcf4b2b4fc 100644 --- a/src/overlays/shared/pickups/infobot.c +++ b/src/overlays/shared/pickups/infobot.c @@ -18,6 +18,7 @@ #include "rnc/mobys/moby_spawn.h" #include "rnc/overlay/shared/game/unlock_planet.h" #include "rnc/overlay/shared/rendering/effects/particles.h" +unsigned char *spawn_timed_hero_relative_particle(u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); #include "rnc/save/memcard_save_data.h" typedef struct Moby Moby; @@ -694,7 +695,7 @@ void update_infobot_particle_effect(char *moby) { f = f / (float)scale_game_frames(0xFF); col = fast_tween_color(0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - f)); if (D_15F5C4_2d6cd0 != 2) { - FUN_L00_00272f68(d, + spawn_timed_hero_relative_particle(d, col, truncate_float_to_s32(infobot_particle_state->a[i]) & 0xFF, 0x35, diff --git a/src/overlays/shared/pickups/nanotech_ball.c b/src/overlays/shared/pickups/nanotech_ball.c index 8102f015f0..e6c0799890 100644 --- a/src/overlays/shared/pickups/nanotech_ball.c +++ b/src/overlays/shared/pickups/nanotech_ball.c @@ -190,7 +190,7 @@ void spawn_moving_hero_relative_alpha_fade_particle( void *, Vec4_002d8418 *, int, int, int, int, float) __asm__("FUN_L00_002730e0"); s32 FUN_001f96f8_2d8510(s32) __asm__("FUN_001f96f8"); s32 FUN_001fa6e0_2d8510(s32, s32, f32) __asm__("FUN_001fa6e0"); -u8 *FUN_L00_00272f68_2d8510(void *, s32, u8, s32, s32, s32, s32, f32) __asm__("FUN_L00_00272f68"); +u8 *spawn_timed_hero_relative_particle(void *, s32, u8, s32, s32, s32, s32, f32) __asm__("FUN_L00_00272f68"); void FUN_001f9bf8_002d8850(void *, void *, float) __asm__("FUN_001f9bf8"); void draw_nanotech_ball(Moby *moby) __asm__("FUN_L00_002d9810"); extern int func_001F9850_2D9EA0(int) __asm__("FUN_001f96f8"); @@ -1170,7 +1170,7 @@ s32 update_nanotech_ball_collection_effects(M_2d8510 *moby) { << 24; c = al | (c & 0xFFFFFF); effect_position.z = z + nanotech_ball_collection_particle_z_offsets[i]; - effect_record = FUN_L00_00272f68_2d8510(&effect_position, + effect_record = spawn_timed_hero_relative_particle(&effect_position, c, truncate_float_to_s32(effect_data->f60[i]), nanotech_ball_collection_particle_byte_source_index, @@ -1182,7 +1182,7 @@ s32 update_nanotech_ball_collection_effects(M_2d8510 *moby) { if (effect_record) effect_record[2] = *D_L00_001B2080_lui.pF8; effect_record = - FUN_L00_00272f68_2d8510(&effect_position, + spawn_timed_hero_relative_particle(&effect_position, al | 0xFFFFFF, truncate_float_to_s32(effect_data->f60[i]), nanotech_ball_collection_particle_byte_source_index, diff --git a/src/overlays/shared/pickups/pilots_helmet.c b/src/overlays/shared/pickups/pilots_helmet.c index 35237aafc2..8a06656635 100644 --- a/src/overlays/shared/pickups/pilots_helmet.c +++ b/src/overlays/shared/pickups/pilots_helmet.c @@ -17,6 +17,7 @@ #include "rnc/overlay/shared/game/unlock_planet.h" #include "rnc/overlay/shared/pickups/infobot.h" #include "rnc/overlay/shared/rendering/effects/particles.h" +unsigned char *spawn_timed_hero_relative_particle(u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); #include "rnc/save/memcard_save_data.h" typedef struct { @@ -198,7 +199,7 @@ void emit_moby_color_cycling_particles(unsigned char *moby) { color_cycle_progress = convert_integer_to_float(scale_game_frames(0xff) - moby_data->t[j]); color_cycle_progress = color_cycle_progress / (float)scale_game_frames(0xff); c = fast_tween_color(0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - color_cycle_progress)); - FUN_L00_00272f68(sprite_position_and_step, + spawn_timed_hero_relative_particle(sprite_position_and_step, c, truncate_float_to_s32(*a++), 0x35, diff --git a/src/overlays/shared/props/energy_sphere_holder.c b/src/overlays/shared/props/energy_sphere_holder.c index d3b9438243..a59ea1ed6c 100644 --- a/src/overlays/shared/props/energy_sphere_holder.c +++ b/src/overlays/shared/props/energy_sphere_holder.c @@ -12,6 +12,7 @@ #include "rnc/overlay/shared/props/energy_sphere_holder_data/update_energy_sphere_holder_beam_effects.h" #include "rnc/overlay/shared/props.h" #include "rnc/overlay/shared/rendering/effects/particles.h" +unsigned char *spawn_timed_hero_relative_particle(u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); typedef struct { float ph[4]; @@ -157,7 +158,7 @@ void update_energy_sphere_holder_beam_effects(char *moby) { beam_sprite_color = fast_tween_color(energy_sphere_holder_beam_color_start_gp, energy_sphere_holder_beam_color_end_gp, absolute_float(0.5f - timer_progress)); - FUN_L00_00272f68(beam_sprite_position, + spawn_timed_hero_relative_particle(beam_sprite_position, beam_sprite_color, truncate_float_to_s32(beam->ph[i]), energy_sphere_holder_beam_texture_index_gp, diff --git a/src/overlays/shared/rendering/effects/particles.c b/src/overlays/shared/rendering/effects/particles.c index c3714b6774..8a309acd31 100644 --- a/src/overlays/shared/rendering/effects/particles.c +++ b/src/overlays/shared/rendering/effects/particles.c @@ -915,9 +915,19 @@ void update_color_tween_emitter_particle(struct EffectParticle *particle) { } extern unsigned char *D_L00_001B2080_lui[] __asm__("D_L00_001B2080") NOT_SDA; +unsigned char *spawn_timed_hero_relative_particle(u128 *position, + int packed_color, + unsigned char initial_rotation, + int particle_texture_index, + int flag, + int lifetime_frames, + int mode, + + float size_scale) __asm__("FUN_L00_00272f68"); + unsigned char * -FUN_L00_00272f68(u128 *a, int c, unsigned char b, int idx, int flag, int n, int mode, float f); -unsigned char *FUN_L00_00272f68(u128 *position, +spawn_timed_hero_relative_particle(u128 *a, int c, unsigned char b, int idx, int flag, int n, int mode, float f); +unsigned char *spawn_timed_hero_relative_particle(u128 *position, int packed_color, unsigned char initial_rotation, int particle_texture_index, From dcd3365df7bb23388d661cc704bc0113d8cd5b28 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:40:03 +0000 Subject: [PATCH 0214/1502] decomp: clarify names in disable_intc domain_0_value_0 -> EE_INTERRUPT_ENABLE_CLEAR: Retail 0x0011903c reads COP0 Status into s0; 0x00119040-0x00119044 mask it with 0x10000. The zero branch at 0x00119048 skips DIntr at 0x00119050 when the saved interrupt-enable bit is clear. Source status is exactly this masked bit, so the first status != 0 comparison tests against EE_INTERRUPT_ENABLE_CLEAR, not a cause ID or normalized Boolean. domain_1_value_0 -> EE_INTERRUPT_ENABLE_CLEAR: Retail 0x00119068 tests the same s0 saved from COP0 Status and masked with 0x10000 at 0x0011903c-0x00119044; s0 is unchanged across _DisableIntc and SYNC. Its zero branch skips EnableInterrupts at 0x00119070. Thus the second status != 0 compares the identical saved interrupt-enable mask against EE_INTERRUPT_ENABLE_CLEAR, restoring interrupts only if that bit was set. --- src/sdk/kernel/disable_intc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sdk/kernel/disable_intc.c b/src/sdk/kernel/disable_intc.c index 9daaec49cf..8bc5223ff1 100644 --- a/src/sdk/kernel/disable_intc.c +++ b/src/sdk/kernel/disable_intc.c @@ -8,17 +8,20 @@ extern s32 DIntr(); s32 disable_intc(s32 intc_cause) __asm__("FUN_00119028"); s32 disable_intc(s32 intc_cause) { + enum { + EE_INTERRUPT_ENABLE_CLEAR = 0 + }; u32 status; s32 result; status = CpuReadStatus(); status &= 0x10000; - if (status != 0) { + if (status != EE_INTERRUPT_ENABLE_CLEAR) { DIntr(); } result = _DisableIntc(intc_cause); CpuSync(); - if (status != 0) { + if (status != EE_INTERRUPT_ENABLE_CLEAR) { EnableInterrupts(); } return result; From 1905975819ce5c5f12ff55905a2c15c026f391af Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:43:50 +0000 Subject: [PATCH 0215/1502] decomp: clarify names in clank_cutscene_trigger_update domain_0_value_1 -> CLANK_TRIGGER_POLL_DIALOGUE: Retail 0x002d9de0 preserves the moby in s1; 0x002d9e18 reads its state byte at +0x20 and 0x002d9e20 dispatches state 1 to the dialogue-poll branch at 0x002d9ec0, which calls update_npc_dialogue at 0x002d9efc. Initialization stores 1 into that identical state byte at 0x002d9eb4. Thus this assignment enters the existing local CLANK_TRIGGER_POLL_DIALOGUE enum member, not a hero or control mode. domain_1_value_2 -> CLANK_TRIGGER_WAIT_TO_REPOLL_DIALOGUE: Retail 0x002d9efc calls update_npc_dialogue; the nonzero-return path at 0x002d9f04-0x002d9f14 stores 2 into the same moby state byte +0x20 read at 0x002d9e18. State-2 dispatch at 0x002d9e40 reaches 0x002d9f50, which waits until D_L00_0015F5C4 differs from 2 before restoring state 1. This exactly reuses the existing local CLANK_TRIGGER_WAIT_TO_REPOLL_DIALOGUE member. domain_2_value_1 -> CLANK_TRIGGER_POLL_DIALOGUE: In state 2, retail 0x002d9f54 loads D_L00_0015F5C4 and 0x002d9f58-0x002d9f5c conditionally stores s2=1 to moby+0x20 when that global differs from 2. The same byte is dispatched at 0x002d9e18-0x002d9e20, where 1 selects the branch calling update_npc_dialogue at 0x002d9efc. This assignment therefore resumes existing CLANK_TRIGGER_POLL_DIALOGUE in the same local enum domain. --- src/overlays/l00/mobys/clank_cutscene_trigger.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l00/mobys/clank_cutscene_trigger.c b/src/overlays/l00/mobys/clank_cutscene_trigger.c index dfb14b913f..50ca1dd7f1 100644 --- a/src/overlays/l00/mobys/clank_cutscene_trigger.c +++ b/src/overlays/l00/mobys/clank_cutscene_trigger.c @@ -324,7 +324,7 @@ void clank_cutscene_trigger_update(DoorMoby *moby) { } alternate_item_available[8] = 1; moby->alpha = 0xFF; - moby->state = 1; + moby->state = CLANK_TRIGGER_POLL_DIALOGUE; break; case CLANK_TRIGGER_POLL_DIALOGUE: if (vars->unk56 != 0) { @@ -335,7 +335,7 @@ void clank_cutscene_trigger_update(DoorMoby *moby) { } } if (update_npc_dialogue(moby, vars->unk20) != 0) { - moby->state = 2; + moby->state = CLANK_TRIGGER_WAIT_TO_REPOLL_DIALOGUE; vars->unk2C = 3.0f; } if (vars->unk24 >= 4 && D_L00_0015F5C4 != 6) { @@ -344,7 +344,7 @@ void clank_cutscene_trigger_update(DoorMoby *moby) { break; case CLANK_TRIGGER_WAIT_TO_REPOLL_DIALOGUE: if (D_L00_0015F5C4 != 2) { - moby->state = 1; + moby->state = CLANK_TRIGGER_POLL_DIALOGUE; } break; } From 8fd22088aeee3c27b4327983f8cb0f8470d944ef Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:43:51 +0000 Subject: [PATCH 0216/1502] decomp: clarify names in handle_vendor_auxiliary_moby_event domain_2_value_11 -> VENDOR_AUXILIARY_STATE_SELECTION_REACTION: Authoritative update_vendor_menu calls VENDOR_SELECTION_CHANGED during accepted row navigation. Retail 0029b524 dispatches event 0 to 0029b544; 0029b514 obtains the auxiliary moby from vendor_menu+0x24. After state eligibility, random and cooldown gates, 0029b594-0029b5d8 selects/stores the reaction variant, sets vendor_auxiliary_reaction_started and queues its dialogue ID. 0029b5cc loads 11 and 0029b5e0 writes that value to this moby's state byte +0x20. Original Ghidra confirms this selection reaction entry; it is a vendor auxiliary state, not HeroStateId. domain_3_value_10 -> VENDOR_AUXILIARY_STATE_READY_REACTION: Authoritative update_vendor_menu initializes auxiliary class 0xC at vendor_menu+0x24 after asset loading, then calls VENDOR_AUXILIARY_MOBY_READY. Retail 0029b510 dispatches event 1 to 0029b5e4. 0029b5e4-0029b618 selects/stores a reaction variant, sets vendor_auxiliary_reaction_started and queues its dialogue ID; 0029b61c-0029b634 blends auxiliary animation sequence 1 when necessary. 0029b638 loads 10 and 0029b640 writes it to the same auxiliary moby's state byte +0x20. Original Ghidra confirms the ready reaction entry, separate from the hero state domain. --- src/overlays/shared/vendor/vendor_menu.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/vendor/vendor_menu.c b/src/overlays/shared/vendor/vendor_menu.c index 38254a251e..941bddfb41 100644 --- a/src/overlays/shared/vendor/vendor_menu.c +++ b/src/overlays/shared/vendor/vendor_menu.c @@ -672,6 +672,10 @@ void handle_vendor_auxiliary_moby_event(int vendor_event) { VENDOR_ITEM_PURCHASE = 2, VENDOR_AMMO_PURCHASE = 3 }; + enum { + VENDOR_AUXILIARY_STATE_READY_REACTION = 10, + VENDOR_AUXILIARY_STATE_SELECTION_REACTION = 0xB + }; char *vendor_state_base; struct Moby *auxiliary_moby; int auxiliary_moby_state; @@ -696,7 +700,7 @@ void handle_vendor_auxiliary_moby_event(int vendor_event) { D_L00_00161194 = 0; *(int *)(queued_dialogue_id) = (selection_variant_index * 3 + 2) * 6 + *(int *)(vendor_state_base + 0x38) + 10000; - auxiliary_moby->state = 0xB; + auxiliary_moby->state = VENDOR_AUXILIARY_STATE_SELECTION_REACTION; } } } @@ -710,7 +714,7 @@ void handle_vendor_auxiliary_moby_event(int vendor_event) { ready_variant_index * 0x12 + *(int *)(vendor_state_base + 0x38) + 10000; if (auxiliary_moby->prev_seq != vendor_event) blend_moby_animation(auxiliary_moby, 1, 0, 10); - auxiliary_moby->state = 10; + auxiliary_moby->state = VENDOR_AUXILIARY_STATE_READY_REACTION; break; case VENDOR_ITEM_PURCHASE: case VENDOR_AMMO_PURCHASE: From d79d059e40326736e881e3c5d054ec34b69a0ba4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:43:51 +0000 Subject: [PATCH 0217/1502] decomp: clarify names in initialize_vendor_screen domain_0_value_5 -> CUTSCENE_MODE_VENDOR_SCREEN: Rename domain_0_value_5 to CUTSCENE_MODE_VENDOR_SCREEN. Authoritative initialize_vendor_screen source (src/overlays/shared/vendor/initialize_vendor_screen.c, SHA-256 cb4c73111394648c7bbb7facb25f93224913263ae34b7cc780a6b44857a25d96) assigns cutscene_mode = 5. Original retail decompilation assigns uRam0015f5c4 = 5; instructions 0x002AEAF0 li v0,5 and 0x002AEAF8/0x002AEAFC store that value to 0x0015F5C4, the exact assembler binding of cutscene_mode. This occurs beside screen-state 3 initialization (0x002AEAF4), vendor_moby retention at screen+0x28 (0x002AEB0C), and vendor-relative camera setup (0x002AEB30-0x002AEB90). Supplied gold_weapon_case_update calls initialize_vendor_screen after purchase and waits in GOLD_WEAPON_CASE_WAIT_FOR_CUTSCENE_END for cutscene_mode == 0. Thus 5 identifies the vendor-screen cutscene mode, not a moby state or music-stream state. --- src/overlays/shared/vendor/initialize_vendor_screen.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/vendor/initialize_vendor_screen.c b/src/overlays/shared/vendor/initialize_vendor_screen.c index 972260a799..e2f37e262e 100644 --- a/src/overlays/shared/vendor/initialize_vendor_screen.c +++ b/src/overlays/shared/vendor/initialize_vendor_screen.c @@ -53,6 +53,9 @@ extern short D_L01_0015F400 __attribute__((sda)); void initialize_vendor_screen(char *vendor_moby, int lvl) __asm__("FUN_L01_002aea70"); void initialize_vendor_screen(char *vendor_moby, int lvl) { + enum { + CUTSCENE_MODE_VENDOR_SCREEN = 5 + }; struct Hero *hero_state = &hero; char *vendor_screen_state = vendor_screen_state_storage; char *relocated_address_block = fx_cutscene; @@ -69,7 +72,7 @@ void initialize_vendor_screen(char *vendor_moby, int lvl) { D_L01_0015F5D8 = 1; fill_transfer_words(vendor_screen_state, 0, 0x220); *(int *)vendor_screen_state_storage = 3; - cutscene_mode = 5; + cutscene_mode = CUTSCENE_MODE_VENDOR_SCREEN; *(int *)(vendor_screen_state + 4) = 0; *(char **)(vendor_screen_state + 0x28) = vendor_moby; sc = vendor_screen_state + 0xC0; From be41a9e999aa83cf39be0222f6475226dd518c0a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:43:52 +0000 Subject: [PATCH 0218/1502] decomp: clarify names in update_help_hints domain_0_value_0 -> HELP_HINTS_STATE_UNINITIALIZED: Retail 0x002e09a8 loads the HelpMoby object's +0x20 state byte and 0x002e09ac skips initialization when nonzero. Only the zero branch writes alpha=0xFF at +0x30 (0x002e09bc) and state=1 (0x002e09c0). Original Ghidra and the bound current source agree: zero denotes this help controller awaiting its initialization. domain_1_value_1 -> HELP_HINTS_STATE_INITIALIZED: Retail 0x002e09b4 loads 1 and 0x002e09c0 stores it to the same HelpMoby +0x20 state byte after setting alpha=0xFF at 0x002e09bc. The entry test at 0x002e09a8-0x002e09ac skips those writes for nonzero state. Thus 1 is the marker produced by completing this controller initialization; source and original Ghidra show the same transition. --- src/overlays/l00/mobys/help_hints.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l00/mobys/help_hints.c b/src/overlays/l00/mobys/help_hints.c index a1f6dc852f..f70a674841 100644 --- a/src/overlays/l00/mobys/help_hints.c +++ b/src/overlays/l00/mobys/help_hints.c @@ -27,15 +27,15 @@ void help_hints_update(HelpMoby *moby) __asm__("FUN_L00_002e0988"); /* Moby class 1413 */ void help_hints_update(HelpMoby *moby) { - s32 *vars; + enum { HELP_HINTS_STATE_UNINITIALIZED = 0 , HELP_HINTS_STATE_INITIALIZED = 1 } ;s32 *vars; s32 *target_index_ptr; s32 i; HelpTarget *target_moby; struct Hero *hero_ptr; vars = moby->vars; - if (moby->state == 0) { - moby->state = 1; + if (moby->state == HELP_HINTS_STATE_UNINITIALIZED) { + moby->state = HELP_HINTS_STATE_INITIALIZED; moby->alpha = 0xFF; } if (D_00141968[0x18 / 2] == 0) { From 65e5ebeca0682d9adb81a3c217421dc3a14c243d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:43:52 +0000 Subject: [PATCH 0219/1502] decomp: clarify names in remove_giant_clank_charged_blast domain_0_value_0 -> GIANT_CLANK_CHARGED_BLAST_CHARGING: Retail 0x002a9bf0-0x002a9bf8 checks the tracked Moby's +0xA6 class against 0x5F3; 0x002a9c00 loads that same Moby's +0x20 state byte and 0x002a9c04 returns when nonzero. Authoritative source creation initializes the class-0x5F3 blast state byte to zero. The supplied update_giant_clank_charged_blast operates on the same charged-blast class and +0x20 state field, explicitly defines CHARGING=0 and EXPANDING_BLAST=1, accumulates charge, particles and light in CHARGING, then assigns state 1 when charging ends. Thus this comparison selects the blast's charging state, not hero idle or a vehicle control mode. The qualified name distinguishes this function-local constant from the existing update-local CHARGING binding. --- src/overlays/shared/vehicles/giant_clank_charged_blast.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/vehicles/giant_clank_charged_blast.c b/src/overlays/shared/vehicles/giant_clank_charged_blast.c index 9a7f75b01b..7fe23e5d8f 100644 --- a/src/overlays/shared/vehicles/giant_clank_charged_blast.c +++ b/src/overlays/shared/vehicles/giant_clank_charged_blast.c @@ -85,12 +85,15 @@ void set_giant_clank_charged_blast_position(void *unused_creation_arg, OvlQuad * void remove_giant_clank_charged_blast(void) __asm__("FUN_L00_002a9be0"); void remove_giant_clank_charged_blast(void) { + enum { + GIANT_CLANK_CHARGED_BLAST_CHARGING = 0 + }; struct Moby *tracked_moby = *(char **)&D_L00_001613C8_gp; if (tracked_moby != 0) { if (tracked_moby->oclass == 0x5F3) { char *tracked_moby_vars; int point_light_slot_index; - if (tracked_moby->state != 0) + if (tracked_moby->state != GIANT_CLANK_CHARGED_BLAST_CHARGING) return; tracked_moby_vars = ((char *)tracked_moby->pvars); D_L00_0015F320 = 0; From 049f89b097291d5530e1a0ee7b2e5449dec1a411 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:43:53 +0000 Subject: [PATCH 0220/1502] decomp: clarify names in hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. 0x0024cf44-0x0024cf58 admits request 100 with argument two while death control mode is active; its existing named destination cancels item animation at 0x00251100-0x00251138. domain_10_value_106 -> HERO_STATE_DROWN: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. 0x0024cff0-0x0024cff4 permits request 0x6A; named DROWN entry 0x0024d9c0-0x0024d9e8 sets death mode and clears health, with swimming duration statistics. domain_11_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. 0x0024cff8-0x0024cffc permits request 0x80; named destination 0x0024d2e4-0x0024d31c clears health and limits retained motion. domain_12_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. 0x0024d000-0x0024d004 permits request 0x82; named destination 0x0024db68-0x0024db90 clears health and initializes death control mode. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x0024d028 loads vehicle_mode at Hero+0x20A4 and 0x0024d054 branches on zero, guarding collision/flag resets and trail clearing. Authoritative source uses p->vehicle_mode and original Ghidra uses cRam001413f4 for the same load. This proves HeroVehicleMode in include/rnc/hero/hero_state.h; reuse its canonical member, without mixing state IDs or control modes. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x0024d134-0x0024d144 loads vehicle_mode at +0x20A4 and dispatches nonzero modes to request_hero_idle_state_for_vehicle_mode. Authoritative source uses p->vehicle_mode and original Ghidra uses cRam001413f4 for the same load. This proves HeroVehicleMode in include/rnc/hero/hero_state.h; reuse its canonical member, without mixing state IDs or control modes. domain_16_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x0024e4c8-0x0024e4dc loads vehicle_mode at +0x20A4; zero permits cancel_hero_item_animation in APPROACH_TARGET_POSE. Authoritative source uses p->vehicle_mode and original Ghidra uses cRam001413f4 for the same load. This proves HeroVehicleMode in include/rnc/hero/hero_state.h; reuse its canonical member, without mixing state IDs or control modes. domain_18_value_1 -> HERO_VEHICLE_MODE_CLANK: 0x0024e4e8 loads vehicle_mode at +0x20A4; 0x0024e510 compares it with s1=1 and selects animation 2 at 0x0024e518-0x0024e530. Authoritative source uses p->vehicle_mode and original Ghidra uses cRam001413f4 for the same load. This proves HeroVehicleMode in include/rnc/hero/hero_state.h; reuse its canonical member, without mixing state IDs or control modes. domain_19_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x0024e534 tests the same vehicle_mode loaded at 0x0024e4e8 against zero before step-indexed on-foot animation selection. Authoritative source uses p->vehicle_mode and original Ghidra uses cRam001413f4 for the same load. This proves HeroVehicleMode in include/rnc/hero/hero_state.h; reuse its canonical member, without mixing state IDs or control modes. domain_1_value_6 -> HERO_STATE_FALL: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. 0x0024cfa8-0x0024cfac permits this request through the zero-health filter; named FALL entry at 0x0024eed8-0x0024ef18 initializes falling gravity. domain_20_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x0024ef1c-0x0024ef30 loads vehicle_mode at +0x20A4 and allocates the fatal-fall voice only on zero. Authoritative source uses p->vehicle_mode and original Ghidra uses cRam001413f4 for the same load. This proves HeroVehicleMode in include/rnc/hero/hero_state.h; reuse its canonical member, without mixing state IDs or control modes. domain_22_value_41 -> HERO_STATE_GRIND_JUMP: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. Source tests requested_state >= 0x29 in the shared jump entry. Retail 0x0024f14c-0x0024f16c subtracts 0x29 and tests a two-value range to select flags 3. domain_23_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. Source tests requested_state <= 0x2A in the shared jump entry. Retail 0x0024f14c-0x0024f16c subtracts 0x29 and tests a two-value range to select flags 3. domain_2_value_61 -> HERO_STATE_DYING: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. 0x0024cfb0-0x0024cfb4 permits this request; the named DYING destination at 0x0024d2a0-0x0024d2e0 initializes death control mode and animation. domain_3_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. 0x0024cfb8-0x0024cfbc compares the requested state against 0x47 in the zero-health admission filter; reuse the supplied canonical member of the proven state domain. domain_4_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. 0x0024cfc0-0x0024cfc4 permits request 0x57; named entry 0x00250d9c-0x00250ddc sets death control mode and vehicle animation 3. domain_5_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. 0x0024cfc8-0x0024cfcc compares the requested state against 0x62 in the zero-health admission filter; reuse the supplied canonical member of the proven state domain. domain_6_value_119 -> HERO_STATE_FATAL_FALL: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. 0x0024cfd0-0x0024cfd4 permits request 0x77; named FALL/FATAL_FALL entry tests this same current state at 0x0024ef00-0x0024ef18 and initializes tumble values. domain_7_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. 0x0024cfd8-0x0024cfdc permits request 0x7B; its named destination 0x00250af0-0x00250b50 initializes control mode 0x19, collision delay and animation. domain_8_value_124 -> HERO_STATE_DEATH_DESCENT: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. 0x0024cfe0-0x0024cfe4 permits request 0x7C; named DEATH_DESCENT entry 0x00250bc4-0x00250bec saves ground height and clears health. domain_9_value_127 -> HERO_STATE_SINK: Requested a0 is saved in s1 at 0x0024cf08 and stored to hero.state.current at Hero+0x2084 by 0x0024d048; original Ghidra assigns param_1 to iRam001413d4. This proves the shared HeroStateId domain in include/rnc/hero/hero_state.h, distinct from control_mode +0x208C and vehicle_mode +0x20A4. 0x0024cfe8-0x0024cfec permits request 0x7F; named SINK entry 0x0024d344-0x0024d3c4 initializes vertical offset toward the water surface and clears health. --- src/overlays/l05/hero/hero_set_state.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l05/hero/hero_set_state.c b/src/overlays/l05/hero/hero_set_state.c index 3db9fa3622..eb488ba203 100644 --- a/src/overlays/l05/hero/hero_set_state.c +++ b/src/overlays/l05/hero/hero_set_state.c @@ -87,7 +87,7 @@ int hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L05_0015F5C4 == 2 || D_L05_0015F5C4 == 6) && b != 2) @@ -95,8 +95,8 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -113,7 +113,7 @@ int hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -141,7 +141,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); return 1; } @@ -752,14 +752,14 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation( p->state.step + 3, D_L05_0015F6E8[p->state.step], (float)scale_game_frames(8)); } @@ -1044,7 +1044,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -1129,7 +1129,7 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 0b9740174895d26f1fbd99dc4e343325654e1b85 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:43:54 +0000 Subject: [PATCH 0221/1502] decomp: clarify names in update_gadgebot_glow_effects domain_0_value_3 -> GADGEBOT_FOLLOW_HERO: Retail 0x002f38d8 saves the caller moby in s4, 0x002f3904 loads its state byte +0x20, and 0x002f390c-0x002f392c compares 3 to select tint 0x3228AA28. Authoritative gadgebot_update passes this same moby to update_gadgebot_glow_effects and defines GADGEBOT_FOLLOW_HERO=3; its matching state branch follows hero.motion.pos using follow_path and movement control. This is the gadgebot moby state domain, not HeroStateId. domain_2_value_5 -> GADGEBOT_SEEK_AND_ATTACK_TARGET: Retail 0x002f3904 loads gadgebot moby state +0x20, then 0x002f3920/0x002f3930 compares 5 and selects 0x322828AA at 0x002f3940-0x002f3948. The authoritative same-moby caller gadgebot_update defines GADGEBOT_SEEK_AND_ATTACK_TARGET=5 and its state branch assigns attack targets, approaches target->pos and records strike hits. Reuse that established gadgebot state member. domain_3_value_9 -> GADGEBOT_UPDATE_KNOCKBACK: Retail state byte from moby+0x20 at 0x002f3904 is compared with 9 at 0x002f3934-0x002f3938 to share tint 0x322828AA. Authoritative caller gadgebot_update defines GADGEBOT_UPDATE_KNOCKBACK=9 and its branch calls step_moby_motion on gadgebot_vars->unk80 before restoring position and state. Supplied handle_gadgebot_hit_knockback initializes knockback and writes this moby's state byte to 9. This is a gadgebot state, not HERO_STATE_RUN_JUMP. domain_4_value_7 -> GADGEBOT_SEEK_INTERACTION_TARGET: Retail 0x002f394c xori v1,v1,7 and 0x002f3954 movz select tint 0x32AA2828 for the same gadgebot state byte loaded at +0x20. Authoritative same-moby caller gadgebot_update defines GADGEBOT_SEEK_INTERACTION_TARGET=7; that state searches with select_nearest_gadgebot_interaction_target then approaches the selected target. The separate substate switch uses moby->sub, proving this comparison is the outer gadgebot state rather than a probe or hero state. --- src/overlays/shared/enemies/gadgebot.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/gadgebot.c b/src/overlays/shared/enemies/gadgebot.c index e60027de6e..23970213cb 100644 --- a/src/overlays/shared/enemies/gadgebot.c +++ b/src/overlays/shared/enemies/gadgebot.c @@ -1675,6 +1675,12 @@ void draw_gadgebot_group_glow_effects(char *group_reference_moby) { } void update_gadgebot_glow_effects(char *moby) { + enum { + GADGEBOT_FOLLOW_HERO = 3, + GADGEBOT_SEEK_AND_ATTACK_TARGET = 5, + GADGEBOT_SEEK_INTERACTION_TARGET = 7, + GADGEBOT_UPDATE_KNOCKBACK = 9 + }; char *moby_vars; int tint; int i; @@ -1686,11 +1692,11 @@ void update_gadgebot_glow_effects(char *moby) { } moby_vars = ((char *)MOBY(moby)->pvars); tint = 0x3228AAAA; - if (MOBY(moby)->state == 3 || MOBY(moby)->state == 6) { + if (MOBY(moby)->state == GADGEBOT_FOLLOW_HERO || MOBY(moby)->state == 6) { tint = 0x3228AA28; - } else if (MOBY(moby)->state == 5 || MOBY(moby)->state == 9) { + } else if (MOBY(moby)->state == GADGEBOT_SEEK_AND_ATTACK_TARGET || MOBY(moby)->state == GADGEBOT_UPDATE_KNOCKBACK) { tint = 0x322828AA; - } else if (MOBY(moby)->state == 7) { + } else if (MOBY(moby)->state == GADGEBOT_SEEK_INTERACTION_TARGET) { tint = 0x32AA2828; } From f5d0b380efa38efbb339c406a9ddbce7806a8f88 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:43:54 +0000 Subject: [PATCH 0222/1502] decomp: clarify names in drain_cover_update domain_0_value_2 -> DRAIN_COVER_RISE: Retail 0x0030e860 loads moby+0x20 and 0x0030e864 compares it with 2 before the voice branch. The same byte is reloaded at 0x0030e8ec and selects the five-state dispatch at 0x0030e8fc-0x0030e920. Authoritative source already defines DRAIN_COVER_RISE=2 for this exact moby->state selector; its case integrates upward Z velocity at 0x0030ed90-0x0030edcc. Reuse that member as the >= threshold. domain_1_value_1 -> DRAIN_COVER_WAIT_TO_RISE: Retail initialization at 0x0030e928-0x0030e930 stores 1 into moby+0x20, the exact byte dispatched at 0x0030e8ec-0x0030e920. It sets the wait timer at 0x0030e934-0x0030e940. The existing source case DRAIN_COVER_WAIT_TO_RISE=1 checks hero proximity and timer at 0x0030ea14-0x0030ea60 before initiating rise, proving this assignment enters that canonical local state. domain_2_value_2 -> DRAIN_COVER_RISE: After proximity and timer succeed, retail 0x0030ea58-0x0030ea60 stores 2 to moby+0x20, the same selector byte as the source switch. 0x0030ea5c-0x0030ea94 clears velocity and computes positive Z launch velocity from sqrt(2*rise_height*gravity). Existing DRAIN_COVER_RISE=2 handles velocity integration and gravity at 0x0030ed90-0x0030edcc, proving the assignment's exact existing enum domain and member. domain_3_value_3 -> DRAIN_COVER_HOVER: Retail 0x0030edbc-0x0030edcc tests updated Z velocity <=0 at the rise apex; 0x0030edd0-0x0030edd4 then stores 3 into the same moby+0x20 switch byte and initializes hover target and timer at 0x0030edd8-0x0030edf8. Existing DRAIN_COVER_HOVER=3 uses accelerated Z approach and alternating target at 0x0030ee28-0x0030eeb4. Reuse its canonical member for this transition. domain_4_value_4 -> DRAIN_COVER_FALL_TO_HOME: Retail 0x0030eebc-0x0030eee0 decrements the hover timer and stores 4 to moby+0x20 when it expires. That same selector dispatches the existing DRAIN_COVER_FALL_TO_HOME=4 case, which integrates velocity, subtracts gravity and compares cover Z against saved home Z at 0x0030ef64-0x0030efa8. Thus this assignment enters the already named fall-to-home state. domain_5_value_1 -> DRAIN_COVER_WAIT_TO_RISE: Retail 0x0030ef9c-0x0030efa8 detects cover Z below saved home Z; 0x0030efc0-0x0030efcc stores 1 into the moby+0x20 selector byte, resets timer at 0x0030efd0 and restores saved home at 0x0030efd4-0x0030efdc. This returns to the same existing DRAIN_COVER_WAIT_TO_RISE=1 case that checks proximity and timer before launch at 0x0030ea14-0x0030ea60. --- src/overlays/l05/mobys/drain_cover.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l05/mobys/drain_cover.c b/src/overlays/l05/mobys/drain_cover.c index b7ebc6435a..1fedc2de87 100644 --- a/src/overlays/l05/mobys/drain_cover.c +++ b/src/overlays/l05/mobys/drain_cover.c @@ -211,7 +211,7 @@ void drain_cover_update(DrainCoverMoby *moby) { qcopy(old_position, moby->pos); qcopy(old_rotation, moby->rot); - if (moby->state >= 2) { + if (moby->state >= DRAIN_COVER_RISE) { if (voice_is_playing(moby, drain_cover_data->sound) == 0) { drain_cover_data->sound = allocate_voice_for_target_entry(0, 4, moby); } @@ -228,7 +228,7 @@ void drain_cover_update(DrainCoverMoby *moby) { } switch (moby->state) { case DRAIN_COVER_INITIALIZE: - moby->state = 1; + moby->state = DRAIN_COVER_WAIT_TO_RISE; drain_cover_data->timer = scale_game_frames(0x78); drain_cover_data->sound = 0xFF; qcopy(drain_cover_data->home, moby->pos); @@ -245,7 +245,7 @@ void drain_cover_update(DrainCoverMoby *moby) { update_drain_cover_tilt((char *)moby, 0.0f, 8.0f); if (D_L05_0015F5C4 == 0 && vector_distance_xy(moby->pos, D_0013F3D0) < 24.0f && fast_dec_timer(&drain_cover_data->timer) != 0) { - moby->state = 2; + moby->state = DRAIN_COVER_RISE; clear_u64_value(drain_cover_data->vel); drain_cover_data->vel[2] = square_root(drain_cover_data->f80 * 2.0f * (l05_drain_cover_gravity * frame_time_sq)); @@ -314,7 +314,7 @@ void drain_cover_update(DrainCoverMoby *moby) { drain_cover_data->vel[2] = drain_cover_data->vel[2] - l05_drain_cover_gravity * frame_time_sq; if (drain_cover_data->vel[2] <= 0.0f) { - moby->state = 3; + moby->state = DRAIN_COVER_HOVER; drain_cover_data->home[3] = drain_cover_data->f84 - 0.5f; drain_cover_data->timer = truncate_float_to_s32(scale_time(drain_cover_data->f88)); } @@ -336,7 +336,7 @@ void drain_cover_update(DrainCoverMoby *moby) { } } if (fast_dec_timer(&drain_cover_data->timer) != 0) { - moby->state = 4; + moby->state = DRAIN_COVER_FALL_TO_HOME; } break; case DRAIN_COVER_FALL_TO_HOME: @@ -354,7 +354,7 @@ void drain_cover_update(DrainCoverMoby *moby) { drain_cover_data->vel[2] - l05_drain_cover_gravity * frame_time_sq; if (moby->pos[2] < drain_cover_data->home[2]) { allocate_voice_for_target_entry(1, 0, moby); - moby->state = 1; + moby->state = DRAIN_COVER_WAIT_TO_RISE; drain_cover_data->timer = scale_game_frames(0x78); qcopy(moby->pos, drain_cover_data->home); drain_cover_data->f98 = random_angle_radians(); From cf5d445a797899720d8558159ee0d660f5b38463 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:46:49 +0000 Subject: [PATCH 0223/1502] decomp: clarify names in update_oil_tanker_link_effects_and_destruction domain_0_value_2 -> TANKER_LINK_HIDDEN_AFTER_BURST: This is the oil-tanker link's own moby->state domain: retail 0x00318214 loads byte +0x20 and dispatches states 0/1. State 1 calls cart_burst at 0x0031833c and spawns fragments 0x785/0x786/0x787 at 0x003183cc/0x00318408/0x00318444. Retail 0x00318450-0x00318460 then stores 2 to that same state byte, clears visibility at +0x31 and sets flag bit 1. Source matches this ordering and dispatch has no handler for state 2, proving the bounded hidden-after-burst name without borrowing unrelated Hero enums. --- src/overlays/l11/mobys/oil_tanker_link.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/oil_tanker_link.c b/src/overlays/l11/mobys/oil_tanker_link.c index fb885ebe65..28fbbd104b 100644 --- a/src/overlays/l11/mobys/oil_tanker_link.c +++ b/src/overlays/l11/mobys/oil_tanker_link.c @@ -60,6 +60,9 @@ void oil_tanker_link_update(struct Moby *moby) { TANKER_LINK_EMIT_EFFECT_AND_SAVE_POSITION = 0, TANKER_LINK_BURST_AND_HIDE = 1 }; + enum { + TANKER_LINK_HIDDEN_AFTER_BURST = 2 + }; char *link_vars = (char *)moby->pvars; float effect_scratch_vector[4]; float effect_motion_vector[4]; @@ -131,7 +134,7 @@ void oil_tanker_link_update(struct Moby *moby) { dv, frame_time_sq * 12.0f, dv); - moby->state = 2; + moby->state = TANKER_LINK_HIDDEN_AFTER_BURST; moby->visible = 0; moby->flags |= 1; break; From cc338774d6454b253ca866255bcb61a08f466db7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:46:49 +0000 Subject: [PATCH 0224/1502] decomp: clarify names in spawn_rocket domain_0_value_1 -> ROCKET_STATE_FLYING: Retail 0x002ecd2c-38 creates class 0x199 and retains the returned rocket in s1; 0x002ecd40 loads a1=1 and 0x002ecd60 stores it to moby state at 0x31(s1), matching original Ghidra *(undefined1 *)(iVar6 + 0x31) = 1. The same bound rocket.c defines ROCKET_STATE_FLYING = 1 in rocket_update, whose selector is this rocket moby's state. That branch adds the pvars velocity to position, emits smoke, checks collisions and lifetime, and transitions to ROCKET_STATE_DETONATE. spawn_rocket initializes that velocity and lifetime before update_entity(moby), proving this assignment enters the existing rocket flying state, independently of unrelated hero enum values. --- src/overlays/l12/mobys/rocket.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l12/mobys/rocket.c b/src/overlays/l12/mobys/rocket.c index 83113a4f48..a761259dcf 100644 --- a/src/overlays/l12/mobys/rocket.c +++ b/src/overlays/l12/mobys/rocket.c @@ -42,6 +42,9 @@ char *spawn_rocket(char *initial_velocity, float nominal_speed, float f2) { + enum { + ROCKET_STATE_FLYING = 1 + }; struct Moby *moby = (struct Moby *)create_moby(0x199); if (moby != 0) { char *rocket_vars; @@ -50,7 +53,7 @@ char *spawn_rocket(char *initial_velocity, moby->update_dist = 0xFF; moby->draw_dist = 0x7E; moby->visible = 1; - moby->state = 1; + moby->state = ROCKET_STATE_FLYING; qcopy(&moby->pos, pos); qcopy(rocket_vars, initial_velocity); moby->rot.z = fast_arc_tan(*(float *)rocket_vars, *(float *)(rocket_vars + 4)); From 3eff55353845fc6f238f4c24b88a393c061490b7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:46:49 +0000 Subject: [PATCH 0225/1502] decomp: clarify names in sceCdInit domain_0_value_255 -> CD_INIT_REPLY_BYPASS_VERSION_CHECK: Retail 0x00121068-0x00121078 loads the signed reply word at receive_buffer+0xC through the uncached alias into a2. After setting compatibility_result (s0) to 1 at 0x00121088, 0x0012108c-0x00121090 compares that reply to 0xFF and branches directly to 0x001210ec, bypassing both signed version-component /256 comparisons at 0x001210b0-0x001210e8. Authoritative C expresses the same empty 0xFF branch; the name states only this proven bypass behavior in the init-reply domain. domain_1_value_254 -> CD_INIT_REPLY_ENABLE_DEBUG: Retail 0x00121078 loads reply_status from the init RPC response at offset 0xC. The comparison against 0xFE at 0x00121098-0x0012109c selects the store of s0=1 to D_001312D0 (cd_debug) at 0x001210ac and bypasses version checks. The same cd_debug scalar gates bind-error printing at 0x00120f98-0x00120fa8 and exit printing at 0x0012110c-0x0012111c. Authoritative C explicitly performs cd_debug = compatibility_result in this reply branch, proving the enable-debug role. --- src/sdk/storage/cdvd/sceCdInit.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/sdk/storage/cdvd/sceCdInit.c b/src/sdk/storage/cdvd/sceCdInit.c index 1b33eef810..684c3694d5 100644 --- a/src/sdk/storage/cdvd/sceCdInit.c +++ b/src/sdk/storage/cdvd/sceCdInit.c @@ -37,6 +37,10 @@ int sceCdInit(int init_mode) { enum { CD_INIT_SHUTDOWN = 5 }; + enum { + CD_INIT_REPLY_ENABLE_DEBUG = 0xFE, + CD_INIT_REPLY_BYPASS_VERSION_CHECK = 0xFF + }; int compatibility_result; int bind_result; int delay; @@ -108,8 +112,8 @@ int sceCdInit(int init_mode) { second_version = *(s32 *)((u32)(receive_buffer + 8) | 0x20000000); reply_status = *(s32 *)((u32)(receive_buffer + 0xC) | 0x20000000); compatibility_result = 1; - if (reply_status == 0xFF) { - } else if (reply_status == 0xFE) { + if (reply_status == CD_INIT_REPLY_BYPASS_VERSION_CHECK) { + } else if (reply_status == CD_INIT_REPLY_ENABLE_DEBUG) { cd_debug = compatibility_result; } else { if (first_version / 256 < 2 || second_version / 256 < 2) { From 10bc58cdd26e9a629b9f532ccac4eaa29cc9a15e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:46:49 +0000 Subject: [PATCH 0226/1502] decomp: clarify names in update_fog_zone domain_0_value_1 -> FOG_ZONE_WAIT_TO_APPLY_PRESET: The initialization path saves current settings and establishes preset/color endpoints at retail 0x0030e284..0x0030e358, then reaches 0x0030e430, storing s3=1 into this same moby's +0x20 state byte. Retail 0x0030e24c..0x0030e254 reads that byte and dispatches value 1 to 0x0030e35c, where hero entry into pvars+0x2c applies the preset. This proves reuse of existing local FOG_ZONE_WAIT_TO_APPLY_PRESET, not a hero enum. domain_1_value_2 -> FOG_ZONE_WAIT_TO_RESTORE_SAVED_SETTINGS: Retail 0x0030e35c..0x0030e3c0 tests hero membership in pvars+0x2c and copies preset bytes/floats into the fog globals. At 0x0030e36c a0 is set to 2 and 0x0030e3c8 stores it to moby+0x20. The same byte dispatches value 2 at 0x0030e274 to 0x0030e3cc, where entry into pvars+0x28 restores the saved initialization snapshot. This is the existing local FOG_ZONE_WAIT_TO_RESTORE_SAVED_SETTINGS domain member. domain_2_value_1 -> FOG_ZONE_WAIT_TO_APPLY_PRESET: Retail state-2 path 0x0030e3cc..0x0030e42c tests pvars+0x28 and restores saved bytes/floats to the fog globals. At 0x0030e430 it stores s3=1 into moby+0x20, the state byte read at 0x0030e24c and dispatched at 0x0030e254 to the preset-application path 0x0030e35c. The restore thus returns to the existing local FOG_ZONE_WAIT_TO_APPLY_PRESET member. --- src/overlays/l05/mobys/fog_zone.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l05/mobys/fog_zone.c b/src/overlays/l05/mobys/fog_zone.c index da0c398cfd..395d5a38a2 100644 --- a/src/overlays/l05/mobys/fog_zone.c +++ b/src/overlays/l05/mobys/fog_zone.c @@ -95,7 +95,7 @@ void fog_zone_update(struct Moby *moby) { fog_zone_vars->unk34 = 0x40408070; fog_zone_vars->unk30 = saved_volume_blend_color; } - moby->state = 1; + moby->state = FOG_ZONE_WAIT_TO_APPLY_PRESET; break; case FOG_ZONE_WAIT_TO_APPLY_PRESET: if (is_point_inside_clip_volume(&hero.motion.pos, fog_zone_vars->clip_volume_2C)) { @@ -112,7 +112,7 @@ void fog_zone_update(struct Moby *moby) { D_L05_0015F450 = fog_450; D_L05_0015F454 = fog_454; } - moby->state = 2; + moby->state = FOG_ZONE_WAIT_TO_RESTORE_SAVED_SETTINGS; } break; case FOG_ZONE_WAIT_TO_RESTORE_SAVED_SETTINGS: @@ -130,7 +130,7 @@ void fog_zone_update(struct Moby *moby) { D_L05_0015F450 = fog_450; D_L05_0015F454 = fog_454; } - moby->state = 1; + moby->state = FOG_ZONE_WAIT_TO_APPLY_PRESET; } break; } From 374eb7a42cefbd7144b1ed16cc4824ce973d4e87 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:46:49 +0000 Subject: [PATCH 0227/1502] decomp: clarify names in hero_frame_update domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 00228040..0022804c forms hero base 0013f350, loads its vehicle_mode byte at +0x20a4 and returns on zero. This is the exact field used by the source's enter_hero_vehicle_mode_and_set_moby and exit_hero_vehicle_mode_and_restore_moby, which stores zero while restoring the original hero moby. The same source already uses HERO_VEHICLE_MODE_ON_FOOT for hero.vehicle_mode in hit-response and collision-dimension switches; thus reuse the supplied HeroVehicleMode member, not a HeroStateId member. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 00228054..00228068 calls delayed voice and easing updates, then reloads the same hero +0x20a4 vehicle_mode byte and returns on zero before update_hero_vehicle_moby. Source binds both reads to hero.vehicle_mode; restoring the original hero moby writes zero to this field, and existing hit-response/collision-dimension switches use canonical HeroVehicleMode member HERO_VEHICLE_MODE_ON_FOOT for this same selector and value. --- src/overlays/shared/hero/hero_frame_update.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index 49c4af1228..1843f9c494 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -113,11 +113,11 @@ void hero_frame_update(void) { hero_update(); update_hero_ground_material_effects(); update_hero_state_machine(); - if (hero.vehicle_mode == 0) + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) return; update_hero_delayed_voice_requests(); update_hero_easing_records(); - if (hero.vehicle_mode == 0) + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) return; update_hero_vehicle_moby(); update_hero_scalar_pulse(); From 215c015c02076186659ee9cee905ceef066356e6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:46:49 +0000 Subject: [PATCH 0228/1502] decomp: clarify names in update_jitter_strand_grid domain_0_value_1 -> JITTER_STRAND_GRID_STATE_UPDATE: Retail 0x002dcc9c reads moby state at t2+0x20; 0x002dcca4 loads 1 and 0x002dcca8 dispatches that same state byte to 0x002dcd70, the phase/timer/vector update branch named JITTER_STRAND_GRID_STATE_UPDATE in the authoritative local enum. After timer initialization, 0x002dcd64 loads 1 and 0x002dcd6c stores it to the identical t2+0x20 byte. Thus the listed moby->state = 1 assignment enters this existing update state and must reuse its local constant. --- src/overlays/l10/mobys/jitter_strand_grid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l10/mobys/jitter_strand_grid.c b/src/overlays/l10/mobys/jitter_strand_grid.c index 16cdc75286..3b0f0ee449 100644 --- a/src/overlays/l10/mobys/jitter_strand_grid.c +++ b/src/overlays/l10/mobys/jitter_strand_grid.c @@ -58,7 +58,7 @@ void jitter_strand_grid_update(struct Moby *moby) { jitter_strand_grid_vars->timers[3][i] = start + 34; } } - moby->state = 1; + moby->state = JITTER_STRAND_GRID_STATE_UPDATE; break; case JITTER_STRAND_GRID_STATE_UPDATE: { int group, strand_column, row; From 93a18c8d0e9693b0884c19ed9aae01fb18b9e1b8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:46:49 +0000 Subject: [PATCH 0229/1502] decomp: clarify names in update_floating_mine domain_1_value_1 -> BOBBING_UPDATE_AND_CHECK_CONTACT: The authoritative C switches on moby->state and already declares BOBBING_UPDATE_AND_CHECK_CONTACT = 1 for the oscillation/contact case. Original Ghidra reads param_1+0x20 and dispatches value 1 to that branch. Retail 0x002dc50c-0x002dc518 reads this same state byte and branches to 0x002dc544 for 1; initialization at 0x002dc528-0x002dc540 sets random phase at pvars+0x60, clears prior offset at +0x64, loads 1 at 0x002dc534 and stores it to that same byte at 0x002dc540. Thus moby->state = 1 enters the already named oscillation/contact state, proving reuse of this local canonical member. --- src/overlays/l17/mobys/floating_mine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l17/mobys/floating_mine.c b/src/overlays/l17/mobys/floating_mine.c index 40578684f5..73f4ff0479 100644 --- a/src/overlays/l17/mobys/floating_mine.c +++ b/src/overlays/l17/mobys/floating_mine.c @@ -97,7 +97,7 @@ void floating_mine_update(struct Moby *moby) { case BOBBING_INITIALIZE: *(float *)(bobbing_moby_vars + 0x60) = random_angle_radians(); *(int *)(bobbing_moby_vars + 0x64) = 0; - moby->state = 1; + moby->state = BOBBING_UPDATE_AND_CHECK_CONTACT; break; case BOBBING_UPDATE_AND_CHECK_CONTACT: update_moby_vertical_oscillation(*(float *)&l17_bobbing_vertical_amplitude, From 85247f8347a2b4fa8022ca7da368afcb68442220 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:48:57 +0000 Subject: [PATCH 0230/1502] decomp: clarify names in update_mine domain_0_value_5 -> STATE_INACTIVE: Original retail 0x002d5984 loads 5 and 0x002d59a4 stores it at moby+0x20 after clearing collision at 0x002d598c and setting inactive flags at 0x002d5994. The same byte is the switch selector at 0x002d5948; values >=5 bypass all update branches at 0x002d594c-0x002d5950. Supplied mine.c launcher selects class-0x238 instances in state 5 and activates them into ballistic state 1; detonation and hide_moby_and_disable_collision also enter 5 and disable collision. This proves the mine's inactive state, unrelated to HeroStateId. domain_1_value_2 -> STATE_POST_FLIGHT_SETTLING: Retail 0x002d59ec loads 2 and 0x002d59f4 writes moby+0x20 after clamping ballistic position Z at 0x002d59f0. This is the exact byte selected by switch at 0x002d5948, whose existing local case STATE_POST_FLIGHT_SETTLING=2 approaches pvars+0x188 to zero at 0x002d5a18-0x002d5a84 while moving pitch/position. Reuse that established mine-state member for this transition. domain_2_value_3 -> STATE_APPROACH_NEARBY_TARGET: Original retail 0x002d5a80-0x002d5a8c checks that settling pvars+0x188 reached zero, then 0x002d5a9c/0x002d5abc loads 3 and 0x002d5acc stores it at moby+0x20. That same selector has existing local STATE_APPROACH_NEARBY_TARGET=3, whose branch at 0x002d5b24-0x002d5c44 selects a nearby target, computes target-minus-position and applies bounded steering/movement. Reuse the existing member for entry into this phase. domain_3_value_3 -> STATE_APPROACH_NEARBY_TARGET: In established STATE_WAIT_TO_RESUME_APPROACH, retail 0x002d5cb8 calls the helper with moby and pvars+0x110. On nonzero return 0x002d5cc4 loads 3, 0x002d5cc8 writes moby+0x20 and 0x002d5ccc clears pvars+0xC8. This exact selector byte drives existing local case STATE_APPROACH_NEARBY_TARGET=3, so the assignment resumes the named approach branch rather than a hero-state or helper substate. --- src/overlays/l18/mobys/mine.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/overlays/l18/mobys/mine.c b/src/overlays/l18/mobys/mine.c index 01e4d68539..f86645256f 100644 --- a/src/overlays/l18/mobys/mine.c +++ b/src/overlays/l18/mobys/mine.c @@ -43,6 +43,9 @@ void moby_568_update(struct Moby *moby) { STATE_APPROACH_NEARBY_TARGET = 3, STATE_WAIT_TO_RESUME_APPROACH = 4 }; + enum { + STATE_INACTIVE = 5 + }; char *class_238_update_private_vars = (char *)moby->pvars; float settling_displacement_or_steering_increment[4]; update_mine_detonation(moby); @@ -52,14 +55,14 @@ void moby_568_update(struct Moby *moby) { moby->flags = (moby->flags | 0x41) & 0xEFFF; *(void **)(class_238_update_private_vars + 0xD0) = &D_L18_00161988; *(float *)(class_238_update_private_vars + 0x30) = 0.05f; - moby->state = 5; + moby->state = STATE_INACTIVE; break; case STATE_BALLISTIC_FLIGHT: fast_vec_add(&moby->pos, &moby->pos, class_238_update_private_vars + 0x180); *(float *)(class_238_update_private_vars + 0x188) -= frame_time_sq * 10.0f; if (moby->pos.z < *(float *)(class_238_update_private_vars + 0x178)) { moby->pos.z = *(float *)(class_238_update_private_vars + 0x178); - moby->state = 2; + moby->state = STATE_POST_FLIGHT_SETTLING; *(float *)(class_238_update_private_vars + 0x188) = -(D_L18_00161994 * 2.0f * frame_time); } @@ -80,7 +83,7 @@ void moby_568_update(struct Moby *moby) { if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(12)); } - moby->state = 3; + moby->state = STATE_APPROACH_NEARBY_TARGET; moby->hit_slot = 0xFF; } break; @@ -141,7 +144,7 @@ void moby_568_update(struct Moby *moby) { break; case STATE_WAIT_TO_RESUME_APPROACH: if (FUN_L00_002dc9f0(moby, class_238_update_private_vars + 0x110)) { - moby->state = 3; + moby->state = STATE_APPROACH_NEARBY_TARGET; *(short *)(class_238_update_private_vars + 0xC8) = 0; } break; From 792458229cebf9ef6d27f9fd3638062c8709da0c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:48:58 +0000 Subject: [PATCH 0231/1502] decomp: clarify names in initialize_pause_menu domain_2_value_34 -> PAUSE_MENU_STATE_EXIT_GUARDED: Retail 00276404..00276424 handles entry 0x21, stores 1 at GameState+0x124, selects l00_pause_menu_exit_guarded_page_owner (001B71F0), and stores 0x22 at 001B9CF0. Supplied process_active_menu_object_actions permits input-driven exit results only when unk124==0. This is the pause-menu exit-guarded state, not HeroStateId; pending_owner can subsequently replace this initial selection. domain_3_value_2 -> SCENE_STATE_DEFAULT: Authoritative source update_pause_menu already declares SCENE_STATE_DEFAULT=2 and switches directly on the identical D_L00_001B9CF0.state field. Retail 00276448/00276454 loads 2 and 0027645c stores it to 001B9CF0; fallback selects l00_pause_menu_default_page_owner at 00276458, while entry 0x2D selects a different owner but shares this state. Reuse the established scene-state member; no hero-state equivalence is inferred. domain_4_value_2 -> SCENE_STATE_DEFAULT: Authoritative source update_pause_menu already declares SCENE_STATE_DEFAULT=2 and switches directly on the identical D_L00_001B9CF0.state field. Retail 00276448/00276454 loads 2 and 0027645c stores it to 001B9CF0; fallback selects l00_pause_menu_default_page_owner at 00276458, while entry 0x2D selects a different owner but shares this state. Reuse the established scene-state member; no hero-state equivalence is inferred. domain_7_value_0 -> PAUSE_MENU_PENDING_STATE_CLEARED: Retail 0027646c..00276498 gates restoration on pending_owner at GameState+0xF0, loads pending_state from +0xF4 and stores it as current scene state at 001B9CF0. After consumption, 002764c4/002764c8 clear +0xF4 and +0xF0 together. Zero here denotes the cleared pending-state storage, not current scene state zero or HERO_STATE_IDLE; retain it in a separate pending-state domain. --- .../shared/ui/menus/initialize_pause_menu.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/ui/menus/initialize_pause_menu.c b/src/overlays/shared/ui/menus/initialize_pause_menu.c index 7a6db104f4..75383e3b15 100644 --- a/src/overlays/shared/ui/menus/initialize_pause_menu.c +++ b/src/overlays/shared/ui/menus/initialize_pause_menu.c @@ -193,6 +193,11 @@ extern void FUN_L00_002df638(Ent *); /* Ported from rac1-decomp (src/overlays/shared/pause_00277208.c: func_L00_00277208). */ void initialize_pause_menu(void) { + enum { + PAUSE_MENU_PENDING_STATE_CLEARED = 0, + SCENE_STATE_DEFAULT = 2, + PAUSE_MENU_STATE_EXIT_GUARDED = 0x22 + }; struct GameState *state = &D_L00_001B9CF0; Own *page; s32 small_buffers = 0; @@ -216,7 +221,7 @@ void initialize_pause_menu(void) { state->unk8 = page; small_buffers = 1; } else if (state_id == 0x21) { - D_L00_001B9CF0.state = 0x22; + D_L00_001B9CF0.state = PAUSE_MENU_STATE_EXIT_GUARDED; page = &l00_pause_menu_exit_guarded_page_owner; state->owner = page; state->unk8 = page; @@ -227,12 +232,12 @@ void initialize_pause_menu(void) { state->unk8 = page; } else if (state_id == 0x2D) { page = &D_L00_001B86C8; - D_L00_001B9CF0.state = 2; + D_L00_001B9CF0.state = SCENE_STATE_DEFAULT; state->owner = page; state->unk8 = page; } else { page = &l00_pause_menu_default_page_owner; - D_L00_001B9CF0.state = 2; + D_L00_001B9CF0.state = SCENE_STATE_DEFAULT; state->owner = page; state->unk8 = page; } @@ -249,7 +254,7 @@ void initialize_pause_menu(void) { D_L00_001841F0.w224 = (s32)D_L00_001B9CF0.unkE4; } D_L00_001B9CF0.pending_owner = 0; - D_L00_001B9CF0.pending_state = 0; + D_L00_001B9CF0.pending_state = PAUSE_MENU_PENDING_STATE_CLEARED; } { From acafe62f8782c1b58c3c193f695211c15162ea63 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:50:50 +0000 Subject: [PATCH 0232/1502] decomp: clarify names in spawn_morphoray_chicken domain_0_value_1 -> CHICKEN_STATE_IDLE: Retail 0x002c935c-0x002c9374 allocates class 0x10E into s1; 0x002c9534/0x002c953c writes 1 to that same moby's state byte +0x20. Supplied source update_morphoray_chicken consumes the chicken moby's same state field, defines CHICKEN_STATE_IDLE = 1 and handles idle animation plus hero-distance-triggered fleeing under that case. Its initialization likewise sets state 1 and the same flee/sound/health fields initialized here, proving this exact chicken state domain rather than a hero or control enum. domain_3_value_5 -> CHICKEN_STATE_EMIT_FEATHERS: Retail 0x002c9644-0x002c9654 loads the previous circular-slot moby and proves its class is 0x10E before 0x002c965c loads state byte +0x20; 0x002c9670-0x002c968c compares that byte with 5 and zeros the new chicken's health/clears flag 0x20. Supplied source update_morphoray_chicken defines CHICKEN_STATE_EMIT_FEATHERS = 5 on the same class's state selector; that branch spawns feather mobys with spherical offsets and velocities. Reuse this established same-domain constant without inferring hero or request-state equivalence. --- src/overlays/shared/weapons/morphoray_chicken.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/morphoray_chicken.c b/src/overlays/shared/weapons/morphoray_chicken.c index 356ef26f3d..84b9717036 100644 --- a/src/overlays/shared/weapons/morphoray_chicken.c +++ b/src/overlays/shared/weapons/morphoray_chicken.c @@ -233,6 +233,10 @@ void reset_morphoray_chicken_slot_defaults(char *morphoray_chicken_slot_record) struct Moby *spawn_morphoray_chicken(State *source_state) __asm__("FUN_L00_002c9348"); struct Moby *spawn_morphoray_chicken(State *source_state) { + enum { + CHICKEN_STATE_IDLE = 1, + CHICKEN_STATE_EMIT_FEATHERS = 5 + }; struct Moby *spawned_moby; Sub *moby_vars; Loc loc; @@ -285,7 +289,7 @@ struct Moby *spawn_morphoray_chicken(State *source_state) { } spawned_moby->collision = ((Part *)spawned_moby->pclass)->unk10; allocate_voice_for_target_entry(1, 0, spawned_moby); - spawned_moby->state = 1; + spawned_moby->state = CHICKEN_STATE_IDLE; moby_vars->unk66 = 0; moby_vars->unk64 = FUN_L00_00257b90(scale_game_frames(0x78), scale_game_frames(0x12C)); ground_height_pitch_and_variant_scratch = convert_integer_to_float(D_0013E520[0x15]); @@ -312,7 +316,7 @@ struct Moby *spawn_morphoray_chicken(State *source_state) { previous_slot_moby = D_L00_001DD100[D_L00_00161854]; if (previous_slot_moby != NULL && previous_slot_moby->oclass == 0x10E && previous_slot_moby->state != 0xFE && previous_slot_moby->state != 0xFD) { - if (previous_slot_moby->state == 5) { + if (previous_slot_moby->state == CHICKEN_STATE_EMIT_FEATHERS) { moby_vars->unk78 = yaw_cosine_scratch; spawned_moby->flags &= ~0x20; } else if (!moby_vars->unk74) { From fbb1319a1c48b565c90ca427d31aa6915f01ae79 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:50:50 +0000 Subject: [PATCH 0233/1502] decomp: clarify names in tresspasser_update domain_0_value_1 -> GADGET_PICKUP_STATE_WAIT_FOR_PLAYER: Retail 0x002ea24c reads the dispatch selector at moby+0x20; 0x002ea2e0/0x002ea2fc stores 1 to that identical byte after ground setup. The authoritative local enum already names its case GADGET_PICKUP_STATE_WAIT_FOR_PLAYER, whose path rotates the pickup and tests player proximity at 0x002ea30c..0x002ea398. domain_1_value_3 -> GADGET_PICKUP_STATE_GRANT_ITEM: Retail 0x002ea39c loads 3 and 0x002ea3b0 writes it to moby+0x20 after successful player-distance checks, while hiding the pickup and clearing collision. This is the same byte read for dispatch at 0x002ea24c. The existing GADGET_PICKUP_STATE_GRANT_ITEM case invokes grant_inventory_item through retail 0x002ea410/0x002ea420/0x002ea434. domain_3_value_4 -> GADGET_PICKUP_STATE_CAMERA_SEQUENCE: Retail 0x002ea47c loads 4 and 0x002ea48c stores it to moby+0x20 after item grant, dialogue/help requests and scalar initialization, immediately before set_race_camera at 0x002ea494. The identical dispatch byte selects existing GADGET_PICKUP_STATE_CAMERA_SEQUENCE, which interpolates camera position and rotation and then restores the camera. domain_4_value_5 -> GADGET_PICKUP_STATE_SAVE_AND_REMOVE: Retail 0x002ea73c restores the camera, 0x002ea744 ends the mount, and 0x002ea74c/0x002ea754 writes 5 to the same moby+0x20 dispatch byte. Existing local GADGET_PICKUP_STATE_SAVE_AND_REMOVE handles that value: 0x002ea758..0x002ea790 approaches the scalar to zero, followed by save and removal calls at 0x002ea79c/0x002ea7a4. --- src/overlays/shared/pickups/gadget_pickup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/pickups/gadget_pickup.c b/src/overlays/shared/pickups/gadget_pickup.c index 8f66522471..cd83610a4b 100644 --- a/src/overlays/shared/pickups/gadget_pickup.c +++ b/src/overlays/shared/pickups/gadget_pickup.c @@ -90,7 +90,7 @@ void tresspasser_update(struct Moby *moby) { *(float *)((char *)moby + 0x40) = 1.57079637f; *(float *)((char *)moby + 0x44) = 3.14159274f; moby->pos.z = D_L02_00174468 + ground_offset; - moby->state = 1; + moby->state = GADGET_PICKUP_STATE_WAIT_FOR_PLAYER; return; } mark_moby_for_removal(moby); @@ -103,7 +103,7 @@ void tresspasser_update(struct Moby *moby) { if (!(vector_distance_xy(&moby->pos, D_0013F3D0) < 1.0f)) return; if (absolute_float(moby->pos.z - *(float *)(D_0013F3D0 + 8)) < 2.0f) { - moby->state = 3; + moby->state = GADGET_PICKUP_STATE_GRANT_ITEM; moby->flags |= 1; moby->visible = 0; moby->collision = 0; @@ -132,7 +132,7 @@ void tresspasser_update(struct Moby *moby) { clear_active_help_record(); help_request(0x7D9, 0x13); D_L02_0015F3FC = 1.0f; - moby->state = 4; + moby->state = GADGET_PICKUP_STATE_CAMERA_SEQUENCE; set_race_camera(D_0013F3D0, D_0013F3D0 + 16, 0x72, 1); return; } @@ -187,7 +187,7 @@ void tresspasser_update(struct Moby *moby) { return; set_race_camera(D_0013F3D0, D_0013F3D0 + 16, 0, 0); jet_end_mount(0); - moby->state = 5; + moby->state = GADGET_PICKUP_STATE_SAVE_AND_REMOVE; return; } case GADGET_PICKUP_STATE_SAVE_AND_REMOVE: From 8efefe629e25c0f940695c13f3efb601e2d06f2b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:53:23 +0000 Subject: [PATCH 0234/1502] decomp: clarify names in update_level_12_water_tile domain_0_value_1 -> SLOT_INITIALIZE_NEIGHBORS_AND_HEIGHT: The selector is this water tile moby's state byte: retail 002bf174 loads +0x20(s3), and 002bf178 dispatches value 1 to 002bf454. Initialization ends at 002bf448/450 by storing 1 to that identical byte. The next state calls initialize_level_12_slot_grid_neighbors with pvars[3] at 002bf454..45c and captures moby Z at pvars+0x10 at 002bf470. Authoritative C already names this same selector's case 1 SLOT_INITIALIZE_NEIGHBORS_AND_HEIGHT; reuse that member for the transition assignment. domain_1_value_2 -> SLOT_UPDATE_HEIGHT_AND_MOTION: Retail 002bf460/468 stores 2 to moby state +0x20(s3) after the neighbor initialization call; 002bf174/19c dispatches that same byte value 2 to 002bf474. This branch consumes command bit 4, increases the height target by 5 at 002bf480..494, and advances moby Z using the captured target at 002bf4a4..4dc. Authoritative C already names case 2 of this identical selector SLOT_UPDATE_HEIGHT_AND_MOTION; reuse that local member for the transition assignment. --- src/overlays/l12/mobys/water_tile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l12/mobys/water_tile.c b/src/overlays/l12/mobys/water_tile.c index 9271750606..a6f47af78e 100644 --- a/src/overlays/l12/mobys/water_tile.c +++ b/src/overlays/l12/mobys/water_tile.c @@ -124,12 +124,12 @@ void level_12_water_tile_update(struct Moby *moby) { ((L12Slot *)D_L12_001CBF40_c)[water_tile_vars[3]].visibility = 0xffff; pool_bind_tile(D_L12_001CBF40_c + water_tile_vars[3] * 0x1190, D_L12_001CBE00_c + water_tile_vars[3] * 16); - moby->state = 1; + moby->state = SLOT_INITIALIZE_NEIGHBORS_AND_HEIGHT; break; case SLOT_INITIALIZE_NEIGHBORS_AND_HEIGHT: next_water_tile_index_gp = 0; initialize_level_12_slot_grid_neighbors(water_tile_vars[3]); - moby->state = 2; + moby->state = SLOT_UPDATE_HEIGHT_AND_MOTION; *(float *)(water_tile_vars + 4) = moby->pos.z; break; case SLOT_UPDATE_HEIGHT_AND_MOTION: From d8e7ff91a1ed435aa03f6f3949b9b4da26467504 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:53:23 +0000 Subject: [PATCH 0235/1502] decomp: clarify names in update_gemlik_bobbing_pool_tile domain_0_value_1 -> BOBBING_PLATFORM_UPDATE: The bound source switches on moby->state with local BOBBING_PLATFORM_UPDATE = 1. Retail 00309f18 loads Moby +0x20, and 00309f20-00309f24 compares that byte with 1 to enter 0030a1e4, which computes cosine-interpolated platform height and advances its phase. Initialization ends with li v0,1 at 0030a1d4 and sb v0,0x20(s5) at 0030a1e0, storing into the identical Moby state byte. Thus the listed assignment domain_0_value_1 selects the existing BOBBING_PLATFORM_UPDATE branch and should reuse that local member. --- src/overlays/l13/mobys/gemlik_bobbing_pool_tile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/gemlik_bobbing_pool_tile.c b/src/overlays/l13/mobys/gemlik_bobbing_pool_tile.c index 5adacc4a58..2a34af1f6a 100644 --- a/src/overlays/l13/mobys/gemlik_bobbing_pool_tile.c +++ b/src/overlays/l13/mobys/gemlik_bobbing_pool_tile.c @@ -295,7 +295,7 @@ void gemlik_bobbing_pool_tile_update(struct Moby *moby) { initialize_gemlik_pool_tile_neighbors(tile_index); } moby->draw_dist = 0; - moby->state = 1; + moby->state = BOBBING_PLATFORM_UPDATE; break; } case BOBBING_PLATFORM_UPDATE: { From 1d80f7f5b8cdb852300e543a6efaad2531173370 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:53:23 +0000 Subject: [PATCH 0236/1502] decomp: clarify names in update_wind_control domain_0_value_0 -> WIND_CONTROL_STATE_UNINITIALIZED: Retail 0x002eafa8 loads the wind-control Moby state byte at s2+0x20, and 0x002eafac skips to normal update at 0x002eb0e4 when nonzero. Only zero enters the configuration checks, dimension/timer setup and 48-spark initialization at 0x002eafbc-0x002eb0dc. This proves the zero comparison is the wind-control initialization gate, matching wind_control_moby->state == 0 in the bound source. domain_1_value_1 -> WIND_CONTROL_STATE_INITIALIZED: Retail 0x002eafb4 loads 1 and 0x002eafb8 stores it to the same wind-control Moby state byte at s2+0x20 before one-time validation and spark initialization. On subsequent calls the nonzero branch at 0x002eafac bypasses that block to 0x002eb0e4. Thus this assignment consumes the initialization gate; invalid cuboid indices instead call removal and return at 0x002eb004-0x002eb018. --- src/overlays/l14/mobys/wind_control.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l14/mobys/wind_control.c b/src/overlays/l14/mobys/wind_control.c index cb92cf0e2a..d8ee062c3b 100644 --- a/src/overlays/l14/mobys/wind_control.c +++ b/src/overlays/l14/mobys/wind_control.c @@ -73,14 +73,14 @@ void wind_control_update(struct Moby *wind_control_moby) __asm__("FUN_L14_002eaf /* Moby class 610 */ void wind_control_update(struct Moby *wind_control_moby) { - L14WindVars *wind_vars = (L14WindVars *)wind_control_moby->pvars; + enum { WIND_CONTROL_STATE_UNINITIALIZED = 0 , WIND_CONTROL_STATE_INITIALIZED = 1 } ;L14WindVars *wind_vars = (L14WindVars *)wind_control_moby->pvars; float wind_direction_or_push_delta[4]; char *pos; struct Hero *hero_base; int i; - if (wind_control_moby->state == 0) { - wind_control_moby->state = 1; + if (wind_control_moby->state == WIND_CONTROL_STATE_UNINITIALIZED) { + wind_control_moby->state = WIND_CONTROL_STATE_INITIALIZED; if (wind_vars->clip_push < 0) { debug_print(D_L14_001FC980, wind_control_moby->save_id); mark_moby_for_removal(wind_control_moby); From af97ae7b14a470642dc14a34033649a21cc51a1e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:53:24 +0000 Subject: [PATCH 0237/1502] decomp: clarify names in update_drek_boss_ring_projectile domain_0_value_1 -> STATE_GROUND_IMPACT_DELAY: The selector is this projectile's moby->state: retail 0x002db4c4 reads byte moby+0x20 and 0x002db4c8 dispatches value 1 to 0x002db814. Ground contact at 0x002db78c-0x002db7a8 writes 1 to that identical byte, clamps Z and initializes pvars+0x2c countdown at 0x002db7b0-0x002db7b8. The value-1 handler decrements that countdown at 0x002db868-0x002db870 before ring entry. This proves reuse of existing local STATE_GROUND_IMPACT_DELAY = 1 for the assignment. domain_1_value_2 -> STATE_EXPANDING_RING: Retail 0x002db888 stores s0=2 to moby+0x20 after the ground-impact countdown expires, then initializes pvars+0x24 to 0.5 and hides the projectile. The same byte is read at 0x002db4c4 and value 2 dispatches at 0x002db4e8 to 0x002db8a8: it increments the ring radius, calls process_expanding_ring_collisions and queues draw_expanding_projectile_ring at 0x002db8b8-0x002db8cc. Source uses existing local STATE_EXPANDING_RING = 2 for this same selector, proving that member for the assignment. domain_2_value_3 -> STATE_REMOVE: Retail 0x002db8d0-0x002db8ec compares pvars+0x24 ring radius against pvars+0x28 and writes 3 to moby+0x20 when the radius exceeds the limit. Retail 0x002db4c4 reads this identical state byte and 0x002db4f0 dispatches 3 to 0x002db8f0, whose only action is mark_moby_for_removal. Existing local STATE_REMOVE = 3 labels that branch in authoritative source, proving reuse for the assignment. --- src/overlays/l18/mobys/drek_boss_ring_projectile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l18/mobys/drek_boss_ring_projectile.c b/src/overlays/l18/mobys/drek_boss_ring_projectile.c index 9385cac78c..dd7f3c91ea 100644 --- a/src/overlays/l18/mobys/drek_boss_ring_projectile.c +++ b/src/overlays/l18/mobys/drek_boss_ring_projectile.c @@ -151,7 +151,7 @@ void drek_boss_ring_projectile_update(struct Moby *moby) { { float ground_height = probe_ground_height(&moby->pos, 0, 0.5f); if (moby->pos.z - 0.333f < ground_height) { - moby->state = 1; + moby->state = STATE_GROUND_IMPACT_DELAY; moby->pos.z = ground_height + 0.333f; *(int *)(moby_vars + 11) = scale_game_frames(1); } @@ -171,7 +171,7 @@ void drek_boss_ring_projectile_update(struct Moby *moby) { (fast_sin(moby_vars[12]) + 1.0f) * 0.5f); if (fast_dec_timer((int *)(moby_vars + 11))) { trooper_play_sound(0xF, 0, (int)moby, 0x58E); - moby->state = 2; + moby->state = STATE_EXPANDING_RING; moby_vars[9] = 0.5f; moby->collision = 0; moby->visible = 0; @@ -183,7 +183,7 @@ void drek_boss_ring_projectile_update(struct Moby *moby) { process_expanding_ring_collisions(moby); add_draw_callback(draw_expanding_projectile_ring, moby); if (moby_vars[9] > moby_vars[10]) { - moby->state = 3; + moby->state = STATE_REMOVE; } break; case STATE_REMOVE: From b6401f21185fd67c0982828da2b391bca16b3e6e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 13:58:50 +0000 Subject: [PATCH 0238/1502] decomp: clarify names in update_jitter_strand_grid D_L10_00161D54 -> l10_jitter_strand_random_vector_time_scale: The owned source declares this as an SDA float and uses it only as random_vector(&jitter[row][strand_column], 0.0f, D_L10_00161D54 * frame_time). Retail 0x002dce94 loads it from -0x4eac(gp) into f2; 0x002dcea4 loads frame_time into f13; 0x002dceb0 multiplies f2*f13 into f13; 0x002dceb8 clears f12, and 0x002dcec8 calls 0x0024a7f0 with the scratch vector destination in a0. This occurs for twenty regenerated rows and the resulting scratch vectors are averaged into strand velocities at 0x002dcf0c..0x002dcf44. These operations prove a frame-time scale supplied for random-vector generation, without needing to claim a downstream amplitude or speed. The l10 qualifier identifies this overlay-owned assembler binding. --- src/overlays/l10/mobys/jitter_strand_grid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/jitter_strand_grid.c b/src/overlays/l10/mobys/jitter_strand_grid.c index 3b0f0ee449..fc5a1724ca 100644 --- a/src/overlays/l10/mobys/jitter_strand_grid.c +++ b/src/overlays/l10/mobys/jitter_strand_grid.c @@ -18,7 +18,7 @@ extern s32 D_L10_00161D68; extern int D_L10_00161D64; extern int D_L10_00161D68; -extern float D_L10_00161D54 __attribute__((sda)); +extern float l10_jitter_strand_random_vector_time_scale __asm__("D_L10_00161D54") __attribute__((sda)); float jitter_strand_row_y_span_gp __asm__("D_L10_00161D58") = 2.5f; float jitter_strand_phase_advance_rate_gp __asm__("D_L10_00161D5C") = 2.0f; @@ -76,7 +76,7 @@ void jitter_strand_grid_update(struct Moby *moby) { jitter_strand_row_y_span_gp * 0.5f; jitter_strand_grid_vars->pos[group][row][strand_column].f[3] = 1.0f; random_vector( - &jitter[row][strand_column], 0.0f, D_L10_00161D54 * frame_time); + &jitter[row][strand_column], 0.0f, l10_jitter_strand_random_vector_time_scale * frame_time); } for (row = 1; row < 19; row++) { fast_vec_add(&jitter_strand_grid_vars->vel[group][row][strand_column], From c39588c7f00b6dbb80e7c35ef1f122b4e7c9e016 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:00:56 +0000 Subject: [PATCH 0239/1502] decomp: clarify names in update_view_context domain_0_value_0 -> FALSE: The selector is the scalar PAL enable flag pal_mode (original retail Ghidra g_nPalVideoMode), not a pointer or state ID. Retail 0x001f2d9c-0x001f2da0 loads it from 0x0015ed80; beq v0,zero at 0x001f2dcc selects 0.775 at 0x001f2dec-0x001f2df4 when disabled, while the nonzero path selects 0.756 at 0x001f2dd4-0x001f2ddc. 0x001f2e00-0x001f2e08 applies that factor to the horizontal FOV to set vertical FOV. The authoritative source expresses the same boolean enable test as pal_mode != 0. Reuse supplied existing FALSE=0 for that flag's false operand; no video-standard enumerator or pointer NULL meaning is asserted. --- src/rendering/view/update_view_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/view/update_view_context.c b/src/rendering/view/update_view_context.c index bc0ede8dad..cedafbe352 100644 --- a/src/rendering/view/update_view_context.c +++ b/src/rendering/view/update_view_context.c @@ -80,7 +80,7 @@ void update_view_context(void) { depth_scale = -8388080.0f; depth_bias = 8388112.0f; - if (pal_mode != 0) { + if (pal_mode != FALSE) { view_context.fov.f[1] = view_context.fov.f[0] * 0.756f; } else { view_context.fov.f[1] = view_context.fov.f[0] * 0.775f; From a3091e9f0bf43f58025f04b6a2728499124ff6da Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:00:57 +0000 Subject: [PATCH 0240/1502] decomp: clarify names in open_vendor_menu domain_1_value_1 -> VENDOR_MENU_MODE_SPAWNED_VENDOR: Retail 0029a700 branches around create_moby(0xB) when the supplied moby is nonnull; only the null-input creation path stores 1 into vendor_menu.mode at +0x40 (0029a774-0029a77c). The initial fill clears this field. Source close_vendor_menu removes the moby only in this nonzero mode, confirming ownership of a spawned vendor. domain_2_value_0 -> VENDOR_PURCHASE_INACTIVE: Retail 0029a7d0 clears vendor_menu +0x5c, identified by the authoritative C as purchase_state. In the supplied update_vendor_purchase consumer, purchase_state == 0 immediately returns; confirmation input starts state 1 and completion restores 0. Thus this is the inactive purchase state, separate from menu state. domain_3_value_0 -> VENDOR_MENU_MODE_EXISTING_VENDOR: Retail 0029a7f4-0029a7fc reads the same vendor_menu.mode at +0x40 for row filtering via build_vendor_menu_rows. Retail 0029a6e4 clears the menu; 0029a700 skips creation for a nonnull supplied vendor, whereas only create_moby's null-input path writes mode 1 at 0029a77c. Therefore zero denotes use of the existing supplied vendor. Source close_vendor_menu preserves this moby and removes only the spawned-mode moby. domain_4_value_0 -> VENDOR_MENU_OPENING: Retail 0029a908 stores zero at 001ca4c0, the same vendor_menu.state field dispatched by supplied update_vendor_menu. Its established enum names zero VENDOR_MENU_OPENING; that branch advances frames, fades in and transitions to VENDOR_MENU_OPEN. This initializes that exact menu-state domain, not hero or moby state. domain_5_value_0 -> VENDOR_MENU_MODE_EXISTING_VENDOR: Retail 0029a92c-0029a93c reads the same vendor_menu.mode at +0x40 for fade_to_black for the existing vendor. Retail 0029a6e4 clears the menu; 0029a700 skips creation for a nonnull supplied vendor, whereas only create_moby's null-input path writes mode 1 at 0029a77c. Therefore zero denotes use of the existing supplied vendor. Source close_vendor_menu preserves this moby and removes only the spawned-mode moby. domain_6_value_0 -> VENDOR_MENU_MODE_EXISTING_VENDOR: Retail 0029a988-0029a9b0 reads the same vendor_menu.mode at +0x40 for selection of vendor animation 3 versus 2. Retail 0029a6e4 clears the menu; 0029a700 skips creation for a nonnull supplied vendor, whereas only create_moby's null-input path writes mode 1 at 0029a77c. Therefore zero denotes use of the existing supplied vendor. Source close_vendor_menu preserves this moby and removes only the spawned-mode moby. domain_7_value_0 -> VENDOR_MENU_MODE_EXISTING_VENDOR: Retail 0029a9d4-0029aa50 reads the same vendor_menu.mode at +0x40 for camera eye and look setup around the existing vendor. Retail 0029a6e4 clears the menu; 0029a700 skips creation for a nonnull supplied vendor, whereas only create_moby's null-input path writes mode 1 at 0029a77c. Therefore zero denotes use of the existing supplied vendor. Source close_vendor_menu preserves this moby and removes only the spawned-mode moby. --- src/overlays/shared/vendor/vendor_menu.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/vendor/vendor_menu.c b/src/overlays/shared/vendor/vendor_menu.c index 941bddfb41..053ba8b799 100644 --- a/src/overlays/shared/vendor/vendor_menu.c +++ b/src/overlays/shared/vendor/vendor_menu.c @@ -362,6 +362,12 @@ extern f32 frame_scale_macro __asm__("D_0015ED60") MACRO_ADDR; void open_vendor_menu(void *) __asm__("FUN_L00_0029a6b0"); void open_vendor_menu(void *vendor_moby_arg) { + enum { + VENDOR_PURCHASE_INACTIVE = 0, + VENDOR_MENU_MODE_EXISTING_VENDOR = 0, + VENDOR_MENU_OPENING = 0, + VENDOR_MENU_MODE_SPAWNED_VENDOR = 1 + }; VendorMoby_29a6b0 *vendor_moby = vendor_moby_arg; s32 i; Vec4 *vector_destination_cursor; @@ -384,7 +390,7 @@ void open_vendor_menu(void *vendor_moby_arg) { vendor_moby->rot.f[2] = 3.1415927f; update_entity(vendor_moby); vendor_moby->state = 3; - vendor_menu.mode = 1; + vendor_menu.mode = VENDOR_MENU_MODE_SPAWNED_VENDOR; } if ((vendor_menu.timer = game_language_macro - 1) < 0) { vendor_menu.timer = 0; @@ -395,13 +401,13 @@ void open_vendor_menu(void *vendor_moby_arg) { l00_vendor_close_pending = 0; l00_vendor_opening_countdown_active = 0; l00_vendor_previous_pressed_buttons = 0; - vendor_menu.purchase_state = 0; + vendor_menu.purchase_state = VENDOR_PURCHASE_INACTIVE; D_L00_00161E34 = 0; D_L00_00161E24_29a6b0 = 0; snd_pause_all_sounds_in_group(0x1D); FUN_00216050_29a6b0(0); snd_flush_sound_commands(); - build_vendor_menu_rows(vendor_menu.mode != 0); + build_vendor_menu_rows(vendor_menu.mode != VENDOR_MENU_MODE_EXISTING_VENDOR); half = vendor_menu.row_count; sel = half / 2; if (half < 3) @@ -430,13 +436,13 @@ void open_vendor_menu(void *vendor_moby_arg) { (D_L00_001C40B0 + item)->hE); } D_L00_0015F5D8 = 1; - vendor_menu.state = 0; + vendor_menu.state = VENDOR_MENU_OPENING; vendor_menu.unk10 = D_L00_00173E00[2] + 0x60000; vendor_menu.unk14 = (struct VendorMoby *)(D_L00_00173E00[1] + 0x60000); vendor_menu.unk08 = 0; vendor_menu.vendor_moby = (struct VendorMoby *)vendor_moby; allocate_voice_for_target_entry(3, 0, vendor_moby); - if (vendor_menu.mode == 0) { + if (vendor_menu.mode == VENDOR_MENU_MODE_EXISTING_VENDOR) { fade_to_black(4); } clear_active_help_record(); @@ -447,13 +453,13 @@ void open_vendor_menu(void *vendor_moby_arg) { D_0013F350[0x20AC] = 1; D_0013F350[0x20A5] = 1; FUN_L00_00232fe8_29a6b0(); - if (vendor_menu.mode != 0) { + if (vendor_menu.mode != VENDOR_MENU_MODE_EXISTING_VENDOR) { set_moby_animation(vendor_moby, 3, 0); } else { set_moby_animation(vendor_moby, 2, 0); } vendor_moby->f58 = frame_scale_macro * 0.5f; - if (vendor_menu.mode == 0) { + if (vendor_menu.mode == VENDOR_MENU_MODE_EXISTING_VENDOR) { transform_vector_by_basis(&vendor_menu.eye, &vendor_camera_eye_local_offset_x_gp, ((char *)vendor_menu.vendor_moby) + 0xC0); From 7bbb2da0ef12e73b4d7f62276e94f723952f838b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:00:57 +0000 Subject: [PATCH 0241/1502] decomp: clarify names in update_water_tile domain_0_value_1 -> WATER_TILE_STATE_FIND_NEIGHBORS: Retail 0x0030e388 loads 1 and 0x0030e390 stores it to moby+0x20 after pool_bind_tile at 0x0030e380. The same object's state byte is loaded at 0x0030e0bc; value 1 dispatches at 0x0030e0c0 to 0x0030e394, which calls populate_water_tile_neighbor_indices at 0x0030e398. Authoritative C already names this exact selector's case WATER_TILE_STATE_FIND_NEIGHBORS=1, proving reuse for its initialization transition. domain_1_value_2 -> WATER_TILE_STATE_APPROACH_UPPER_HEIGHT: Retail neighbor-discovery branch calls 0x0030e730 at 0x0030e398, then loads 2 at 0x0030e3a0 and stores it to the same moby+0x20 state field at 0x0030e3a8. State dispatch 0x0030e0e4 selects 0x0030e4ac for 2; its gated height helper receives moby+0x18 and target 137.0f at 0x0030e4d4-0x0030e508. Authoritative C already names this exact state case WATER_TILE_STATE_APPROACH_UPPER_HEIGHT=2, so this assignment reuses that member. --- src/overlays/l11/mobys/water_tile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l11/mobys/water_tile.c b/src/overlays/l11/mobys/water_tile.c index 38a7476e4f..66e4e09138 100644 --- a/src/overlays/l11/mobys/water_tile.c +++ b/src/overlays/l11/mobys/water_tile.c @@ -138,12 +138,12 @@ void water_tile_update(struct Moby *water_tile_moby) { l11_water_grids[water_tile_vars[1]].visible_subtiles = 0xFFFF; pool_bind_tile(&l11_water_grids[water_tile_vars[1]], water_tile_binding_records[water_tile_vars[1]]); - water_tile_moby->state = 1; + water_tile_moby->state = WATER_TILE_STATE_FIND_NEIGHBORS; break; case WATER_TILE_STATE_FIND_NEIGHBORS: D_L11_00161F64 = 0; populate_water_tile_neighbor_indices(water_tile_vars[1]); - water_tile_moby->state = 2; + water_tile_moby->state = WATER_TILE_STATE_APPROACH_UPPER_HEIGHT; break; case WATER_TILE_STATE_APPROACH_LOWER_HEIGHT: if (water_tile_moby->command & 4) { From e1da418d2a78e776a5f9815d7bd7ee87b505ad47 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:00:57 +0000 Subject: [PATCH 0242/1502] decomp: clarify names in spawn_morphoray_chicken domain_0_value_254 -> MOBY_STATE_SPAWN_POOL_REMOVAL: Assigned retail 0x002c9650-0x002c9664 checks class 0x10E, loads previous_slot_moby state at +0x20, and excludes 0xFE. The checked level-00 mark_moby_for_removal helper 0x0024eb68 compares the same moby pointer against [0x0015ffdc] at 0x0024eb78, selects FE for pointers at or above that boundary at 0x0024eb8c, and writes it to +0x20 at 0x0024eb90. Checked create_moby 0x0024e838 loads that identical boundary as the spawn pool start at 0x0024e850, scans 0x100-byte entries through [0x0015ffe0], and accepts state FE or FF after the +0x38 deadline at 0x0024e870-0x0024e88c. Thus FE is specifically the spawn-pool removal state, not a chicken behavior state. domain_1_value_253 -> MOBY_STATE_NON_SPAWN_POOL_REMOVAL: Assigned retail 0x002c965c loads previous_slot_moby state from +0x20 and 0x002c9668-0x002c966c excludes FD. The checked level-00 removal helper called by this function at 0x002c95e0 compares its moby pointer unsigned against [0x0015ffdc] at 0x0024eb78 and selects FD only for a pointer below that boundary at 0x0024eb84-0x0024eb88, writing +0x20 at 0x0024eb90. Checked create_moby 0x0024e838 proves the same [0x0015ffdc] is the start of its allocation pool (0x0024e850-0x0024e858); its scan advances upward in 0x100-byte mobys and accepts only FE/FF. FD therefore marks removal outside this spawn pool; static or level ownership is not asserted. --- src/overlays/shared/weapons/morphoray_chicken.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/morphoray_chicken.c b/src/overlays/shared/weapons/morphoray_chicken.c index 84b9717036..475e54887b 100644 --- a/src/overlays/shared/weapons/morphoray_chicken.c +++ b/src/overlays/shared/weapons/morphoray_chicken.c @@ -237,6 +237,10 @@ struct Moby *spawn_morphoray_chicken(State *source_state) { CHICKEN_STATE_IDLE = 1, CHICKEN_STATE_EMIT_FEATHERS = 5 }; + enum { + MOBY_STATE_NON_SPAWN_POOL_REMOVAL = 0xFD, + MOBY_STATE_SPAWN_POOL_REMOVAL = 0xFE + }; struct Moby *spawned_moby; Sub *moby_vars; Loc loc; @@ -315,7 +319,7 @@ struct Moby *spawn_morphoray_chicken(State *source_state) { fill_transfer_words(moby_vars, 0, 0x20); previous_slot_moby = D_L00_001DD100[D_L00_00161854]; if (previous_slot_moby != NULL && previous_slot_moby->oclass == 0x10E && - previous_slot_moby->state != 0xFE && previous_slot_moby->state != 0xFD) { + previous_slot_moby->state != MOBY_STATE_SPAWN_POOL_REMOVAL && previous_slot_moby->state != MOBY_STATE_NON_SPAWN_POOL_REMOVAL) { if (previous_slot_moby->state == CHICKEN_STATE_EMIT_FEATHERS) { moby_vars->unk78 = yaw_cosine_scratch; spawned_moby->flags &= ~0x20; From d1f364a27ad723b73b8cd0e91772240520ac3517 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:03:44 +0000 Subject: [PATCH 0243/1502] decomp: clarify names in initialize_pause_menu D_L00_001B6088 -> l00_pause_menu_level_transition_on_action_page_owner: This is pause-menu GameState.state, not HeroStateId: initialize_pause_menu retail 002763e8..00276400 installs Own 001B6088 and writes state 15. Checked descriptor bytes at +0x3C contain 15; update_pause_menu 00276f6c..00276f70 restores this owner field into the same scene-state selector. Caller retail 002771d0..002771f0 maps a nonzero page-object action result in states 15/16 to request 2 at GameState+0xC; 00276d08..00276d3c handles request 2 by calling prepare_target_level_transition with 001841F0+0x224. Thus 15 is a scene state whose page action requests level transition, without inferring a page title. Retail 002763f0/002763f8 and 00276464 install this exact Own descriptor as pending/current page; owner IDs feed fourteen moby animations at 002768a8..002768d4. The name describes its checked scene-state action policy, not a user-facing menu title. domain_10_value_15 -> PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION: This is pause-menu GameState.state, not HeroStateId: initialize_pause_menu retail 002763e8..00276400 installs Own 001B6088 and writes state 15. Checked descriptor bytes at +0x3C contain 15; update_pause_menu 00276f6c..00276f70 restores this owner field into the same scene-state selector. Caller retail 002771d0..002771f0 maps a nonzero page-object action result in states 15/16 to request 2 at GameState+0xC; 00276d08..00276d3c handles request 2 by calling prepare_target_level_transition with 001841F0+0x224. Thus 15 is a scene state whose page action requests level transition, without inferring a page title. The current-state comparison at 00276730..00276734 selects texture reservations for this state. domain_1_value_15 -> PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION: This is pause-menu GameState.state, not HeroStateId: initialize_pause_menu retail 002763e8..00276400 installs Own 001B6088 and writes state 15. Checked descriptor bytes at +0x3C contain 15; update_pause_menu 00276f6c..00276f70 restores this owner field into the same scene-state selector. Caller retail 002771d0..002771f0 maps a nonzero page-object action result in states 15/16 to request 2 at GameState+0xC; 00276d08..00276d3c handles request 2 by calling prepare_target_level_transition with 001841F0+0x224. Thus 15 is a scene state whose page action requests level transition, without inferring a page title. The listed assignment is the state-14 entry branch's store at 002763f4. domain_3_value_15 -> PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION: This is pause-menu GameState.state, not HeroStateId: initialize_pause_menu retail 002763e8..00276400 installs Own 001B6088 and writes state 15. Checked descriptor bytes at +0x3C contain 15; update_pause_menu 00276f6c..00276f70 restores this owner field into the same scene-state selector. Caller retail 002771d0..002771f0 maps a nonzero page-object action result in states 15/16 to request 2 at GameState+0xC; 00276d08..00276d3c handles request 2 by calling prepare_target_level_transition with 001841F0+0x224. Thus 15 is a scene state whose page action requests level transition, without inferring a page title. The pending_state local is loaded from GameState+0xF4 at 00276480 and written into current scene state at 00276498 before comparison at 0027649c..002764a0, so it carries the same scene-state ID. domain_5_value_15 -> PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION: This is pause-menu GameState.state, not HeroStateId: initialize_pause_menu retail 002763e8..00276400 installs Own 001B6088 and writes state 15. Checked descriptor bytes at +0x3C contain 15; update_pause_menu 00276f6c..00276f70 restores this owner field into the same scene-state selector. Caller retail 002771d0..002771f0 maps a nonzero page-object action result in states 15/16 to request 2 at GameState+0xC; 00276d08..00276d3c handles request 2 by calling prepare_target_level_transition with 001841F0+0x224. Thus 15 is a scene state whose page action requests level transition, without inferring a page title. The current-state comparison at 002766a4..002766a8 chooses render archive transfer for this state. domain_7_value_15 -> PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION: This is pause-menu GameState.state, not HeroStateId: initialize_pause_menu retail 002763e8..00276400 installs Own 001B6088 and writes state 15. Checked descriptor bytes at +0x3C contain 15; update_pause_menu 00276f6c..00276f70 restores this owner field into the same scene-state selector. Caller retail 002771d0..002771f0 maps a nonzero page-object action result in states 15/16 to request 2 at GameState+0xC; 00276d08..00276d3c handles request 2 by calling prepare_target_level_transition with 001841F0+0x224. Thus 15 is a scene state whose page action requests level transition, without inferring a page title. The current-state comparison at 002766cc..002766d0 chooses decompression mode 1 for this state. --- .../shared/ui/menus/initialize_pause_menu.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/ui/menus/initialize_pause_menu.c b/src/overlays/shared/ui/menus/initialize_pause_menu.c index 75383e3b15..1c95d656df 100644 --- a/src/overlays/shared/ui/menus/initialize_pause_menu.c +++ b/src/overlays/shared/ui/menus/initialize_pause_menu.c @@ -165,7 +165,7 @@ extern void queue_movie_with_game_language(void *) __asm__("FUN_L00_00299560"); extern void start_slideshow(void) __asm__("FUN_L00_00299a68"); extern Own l00_pause_menu_default_page_owner __asm__("D_L00_001B2588"); extern Own D_L00_001B3518; -extern Own D_L00_001B6088; +extern Own l00_pause_menu_level_transition_on_action_page_owner __asm__("D_L00_001B6088"); extern Own l00_pause_menu_state_preserving_entry_page_owner __asm__("D_L00_001B6B38"); extern Own D_L00_001B86C8; @@ -198,6 +198,9 @@ void initialize_pause_menu(void) { SCENE_STATE_DEFAULT = 2, PAUSE_MENU_STATE_EXIT_GUARDED = 0x22 }; + enum { + PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION = 15 + }; struct GameState *state = &D_L00_001B9CF0; Own *page; s32 small_buffers = 0; @@ -215,8 +218,8 @@ void initialize_pause_menu(void) { state->unk8 = page; small_buffers = 1; } else if (state_id == 14) { - D_L00_001B9CF0.state = 15; - page = &D_L00_001B6088; + D_L00_001B9CF0.state = PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION; + page = &l00_pause_menu_level_transition_on_action_page_owner; state->owner = page; state->unk8 = page; small_buffers = 1; @@ -249,7 +252,7 @@ void initialize_pause_menu(void) { D_L00_001B9CF0.unk8 = D_L00_001B9CF0.pending_owner; pending_state = D_L00_001B9CF0.pending_state; D_L00_001B9CF0.state = pending_state; - if (pending_state == 11 || pending_state == 15) { + if (pending_state == 11 || pending_state == PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION) { small_buffers = 1; D_L00_001841F0.w224 = (s32)D_L00_001B9CF0.unkE4; } @@ -319,11 +322,11 @@ void initialize_pause_menu(void) { D_L00_0015F578 = 0x2000; vu1_init_chain(); - if (D_L00_001B9CF0.state == 11 || D_L00_001B9CF0.state == 15) { + if (D_L00_001B9CF0.state == 11 || D_L00_001B9CF0.state == PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION) { initialize_render_archive_transfer(); } apply_group_entry_adjustment(0); - if (D_L00_001B9CF0.state == 11 || D_L00_001B9CF0.state == 15 || D_L00_001B9CF0.state == 0x12) { + if (D_L00_001B9CF0.state == 11 || D_L00_001B9CF0.state == PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION || D_L00_001B9CF0.state == 0x12) { decompress_and_relocate_selected_groups(1); } else { decompress_and_relocate_selected_groups(0); @@ -331,7 +334,7 @@ void initialize_pause_menu(void) { transfer_draw_buffer_chunks(D_L00_001B9CF0.unk10, draw_buffer_address, frame_size << 11); texture_start = gs_texture_allocation_start; D_L00_001B9CF0.saved_texture_start = texture_start; - if (D_L00_001B9CF0.state == 11 || D_L00_001B9CF0.state == 15) { + if (D_L00_001B9CF0.state == 11 || D_L00_001B9CF0.state == PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION) { D_L00_001841F0.unk240 = texture_start; texture_region_end = texture_start + 0x40000; D_L00_001841F0.unk244 = texture_region_end; From 0c5684416ad7e5a6c86d234dc9e510939646e596 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:03:44 +0000 Subject: [PATCH 0244/1502] decomp: clarify names in red_button_update domain_0_value_1 -> IDLE_AFTER_INITIALIZATION: Retail 00304104-0030410c writes 1 to moby+0x20 after rotation/update-distance initialization. This is the same byte read by dispatch at 003040bc; authoritative source switches on moby->state and its existing IDLE_AFTER_INITIALIZATION=1 branch only breaks. Reuse the local state-domain member. domain_1_value_3 -> WAIT_FOR_NEARBY_HELP_TRIGGER: Retail 003041fc-00304214 writes 3 to the dispatched moby+0x20 byte when rotation progress reaches 1. Its branch at 00304234-00304288 tests hero distance below 3.7, the help-message result and mask 0x10. Source already names that same moby->state case WAIT_FOR_NEARBY_HELP_TRIGGER=3. domain_2_value_4 -> WAIT_CAMERA_START_DELAY: Retail 003042a4-003042b8 stores 4 at moby+0x20 and starts pvars+0x40 with scale_game_frames(30). Branch 003042bc decrements that timer before mounting the camera. Both assignment and existing WAIT_CAMERA_START_DELAY=4 case use the identical moby->state selector domain. domain_3_value_5 -> RAISE_CAMERA_AND_TRIGGER_LISTED_EFFECTS: Retail 003042f8-0030430c assigns 5 at moby+0x20 and clears progress/velocity after the start delay. The dispatched branch 00304414-00304538 advances progress, raises camera z by t*18 and emits effects on crossed listed cut thresholds. Source already names this exact state RAISE_CAMERA_AND_TRIGGER_LISTED_EFFECTS=5. domain_4_value_6 -> HOLD_OFFSET_CAMERA_UNTIL_PROGRESS_COMPLETE: Retail 00304594-003045a0 stores 6 to the same moby+0x20 state byte at t>=1.075. Branch 00304674-00304730 advances t toward 2 while holding cut2 position offset by y-2.5,z+1 and setting rotation. Source already names this same state HOLD_OFFSET_CAMERA_UNTIL_PROGRESS_COMPLETE=6. --- src/overlays/l06/mobys/red_button.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l06/mobys/red_button.c b/src/overlays/l06/mobys/red_button.c index 763ec68474..1ffd699435 100644 --- a/src/overlays/l06/mobys/red_button.c +++ b/src/overlays/l06/mobys/red_button.c @@ -114,7 +114,7 @@ void red_button_update(struct Moby *moby) { case INITIALIZE_RED_BUTTON: moby->update_dist = 0xFF; moby->rot.x = fast_subtract_rotations(moby->rot.x, 0.78539819f); - moby->state = 1; + moby->state = IDLE_AFTER_INITIALIZATION; red_button_vars->f48 = -1; break; case IDLE_AFTER_INITIALIZATION: @@ -136,7 +136,7 @@ void red_button_update(struct Moby *moby) { update_moby_304098(&D_L06_0015FFD8_304098[red_button_vars->moby1]); update_moby_304098(&D_L06_0015FFD8_304098[red_button_vars->moby2]); if (1.0f <= red_button_vars->t) { - moby->state = 3; + moby->state = WAIT_FOR_NEARBY_HELP_TRIGGER; allocate_voice_for_target_entry(1, 0, moby); D_0013D3AA = 1; } @@ -148,7 +148,7 @@ void red_button_update(struct Moby *moby) { if ((*(int *)(D_0013A5E0 + 0x2504) & 0x10) && help_message_available) { allocate_voice_for_target_entry(2, 0, moby); remove_help_message_for_selector(4); - moby->state = 4; + moby->state = WAIT_CAMERA_START_DELAY; red_button_vars->timer = scale_game_frames(0x1E); } } @@ -157,7 +157,7 @@ void red_button_update(struct Moby *moby) { if (fast_dec_timer(&red_button_vars->timer)) { qcopy_nc(&camera_position, &l06_cuboids[red_button_vars->cut].pos); qcopy(&camera_rotation, &l06_cuboids[red_button_vars->cut].rot); - moby->state = 5; + moby->state = RAISE_CAMERA_AND_TRIGGER_LISTED_EFFECTS; red_button_vars->t = 0.0f; red_button_vars->vel = 0.0f; fade_to_black(scale_game_frames(0xF)); @@ -216,7 +216,7 @@ void red_button_update(struct Moby *moby) { 0x72, 0); fade_to_black(scale_game_frames(10)); - moby->state = 6; + moby->state = HOLD_OFFSET_CAMERA_UNTIL_PROGRESS_COMPLETE; jet_end_mount(3); qcopy(&next_position, &l06_cuboids[red_button_vars->cut2].pos); next_position.z = next_position.z + 1.0f; From a6d489fed8726e6f07e18b65dcee4e806b5c8ac2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:03:44 +0000 Subject: [PATCH 0245/1502] decomp: clarify names in initialize_level_runtime domain_2_value_4 -> LEVEL_SCENE_MODE_EARLY_PROGRESSION: Retail 0x00231450..0x00231484 tests current_level_index at D_0015ED84: mode 4 is forced for level 0, or level 1 when level_available[3] at 0x0013DD43 is zero. Otherwise 0x00231424..0x00231438 retains a random mode in 0..3. The same scene_mode field at level_render_state+0x58 is read at 0x002314ec, scaled by four at 0x00231500 and added to header->scenes at 0x00231504; 0x00231510..0x00231560 relocates the selected scene chunk table. Thus 4 denotes the scene-table mode for early progression, not the unrelated render state value 4 or scene_state value 2. The name describes its proven progression-based selection without claiming scene contents. --- src/game/initialize_level_runtime.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/game/initialize_level_runtime.c b/src/game/initialize_level_runtime.c index e2e6019c53..9621560897 100644 --- a/src/game/initialize_level_runtime.c +++ b/src/game/initialize_level_runtime.c @@ -149,6 +149,9 @@ extern void store_sound_bank_handle_callback() __asm__("func_0022DD78"); extern s32 snd_flush_sound_commands(void) __asm__("func_0012DC80"); void initialize_level_runtime(void) { + enum { + LEVEL_SCENE_MODE_EARLY_PROGRESSION = 4 + }; s64 texture_packet[4]; LevelHeader *header; s32 data_base; @@ -276,7 +279,7 @@ void initialize_level_runtime(void) { level_render_state.history_count = 0; qcopy(&D_001604F0, &D_001604E0); if (current_level_index == 0 || (current_level_index == 1 && level_available[3] == 0)) { - level_render_state.scene_mode = 4; + level_render_state.scene_mode = LEVEL_SCENE_MODE_EARLY_PROGRESSION; level_render_state.scene_state = 2; } fill_transfer_words(&render_sequence, 0, 0x1C0); From b39ea6cfd0f28eec4d23a5c2a062ce43816e5d6e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:03:44 +0000 Subject: [PATCH 0246/1502] decomp: clarify names in codebot_slot_update domain_0_value_0 -> CODEBOT_SLOT_INITIALIZE: Retail 002ec070 loads the same moby+0x20 state byte dispatched at 002ec0cc-002ec0ec; 002ec074 skips displacement when it is zero. The authoritative switch names this exact selector's zero member CODEBOT_SLOT_INITIALIZE, whose branch restores save state or hides 24 lists. domain_1_value_4 -> CODEBOT_SLOT_COMPLETED: Retail 002ec10c-002ec158 tests signed save-ID flags and banked save bits, then stores 4 to moby+0x20 when already persisted. That is the exact byte dispatched by the switch whose established member is CODEBOT_SLOT_COMPLETED=4; branch 002ec4ac maintains the completed effect. domain_2_value_1 -> CODEBOT_SLOT_WAIT_FOR_PROXIMITY: Retail 002ec15c-002ec16c clears the flag and writes 1 to the same moby+0x20 state dispatched by the switch. Its established CODEBOT_SLOT_WAIT_FOR_PROXIMITY branch at 002ec1a0-002ec1f8 checks item/mode guards and distance below 3 before advancing. domain_3_value_2 -> CODEBOT_SLOT_WAIT_TO_CREATE_EFFECT: Retail 002ec1e8-002ec1f8 calls the slot helper and stores 2 to moby+0x20. The same state selector's established CODEBOT_SLOT_WAIT_TO_CREATE_EFFECT=2 branch at 002ec1fc-002ec204 polls the spawn gate; success creates the effect at 002ec2a0, proving direct state-domain identity. domain_4_value_3 -> CODEBOT_SLOT_ANIMATE_EFFECT: Retail 002ec2a0-002ec2b0 creates and retains the effect and clears its phase; 002ec340-002ec360 shows the first list and writes 3 to moby+0x20. The exact same switch field's established CODEBOT_SLOT_ANIMATE_EFFECT branch advances phase and writes effect position at 002ec364-002ec428. domain_5_value_4 -> CODEBOT_SLOT_COMPLETED: Retail 002ec42c-002ec4a0 sets the signed save-ID-selected banked and global save bits after the effect offset falls below 0.5, then 002ec4a8 stores 4 to moby+0x20. The same field is the switch selector with established CODEBOT_SLOT_COMPLETED=4, also restored from those save bits during initialization. --- src/overlays/l15/mobys/codebot_slot.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l15/mobys/codebot_slot.c b/src/overlays/l15/mobys/codebot_slot.c index 2212befd90..c0ac492fcc 100644 --- a/src/overlays/l15/mobys/codebot_slot.c +++ b/src/overlays/l15/mobys/codebot_slot.c @@ -136,7 +136,7 @@ void codebot_slot_update(struct Moby *moby) { float angle; char *effect; if (codebot_slot_private_data[3] != -1) { - if (moby->state != 0) { + if (moby->state != CODEBOT_SLOT_INITIALIZE) { fast_vec_sub(position_rotation_work_vector, (char *)l15_moby_array + codebot_slot_private_data[3] * 0x100 + 0x10, codebot_slot_private_data + 4); @@ -156,11 +156,11 @@ void codebot_slot_update(struct Moby *moby) { (char *)l15_banked_moby_save_bits) >> (moby->save_id & 31) & 1) != 0)) { - moby->state = 4; + moby->state = CODEBOT_SLOT_COMPLETED; break; } D_L15_00184AAC = 0; - moby->state = 1; + moby->state = CODEBOT_SLOT_WAIT_FOR_PROXIMITY; for (i = 0; i < 24; i++) { if (codebot_slot_private_data[i + 8] != -1) set_moby_list_visibility(codebot_slot_private_data[i + 8], 0); @@ -171,7 +171,7 @@ void codebot_slot_update(struct Moby *moby) { if (alternate_item_available[2] != 0 && vector_distance_xy(D_0013F3D0, &moby->pos) < 3.0f && *((unsigned char *)D_0013F3D0 + 0x2024) == 0) { FUN_L15_002f78b8(codebot_slot_private_data[0]); - moby->state = 2; + moby->state = CODEBOT_SLOT_WAIT_TO_CREATE_EFFECT; } break; case CODEBOT_SLOT_WAIT_TO_CREATE_EFFECT: @@ -196,7 +196,7 @@ void codebot_slot_update(struct Moby *moby) { set_race_camera(position_work_vector, position_rotation_work_vector, 0x72, 0); if (codebot_slot_private_data[8] != -1) set_moby_list_visibility(codebot_slot_private_data[8], 1); - moby->state = 3; + moby->state = CODEBOT_SLOT_ANIMATE_EFFECT; } break; case CODEBOT_SLOT_ANIMATE_EFFECT: @@ -223,7 +223,7 @@ void codebot_slot_update(struct Moby *moby) { unsigned int *bits = &D_L15_001BAAD0[(short)moby->save_id >> 5]; *bits |= 1u << (moby->save_id & 31); } - moby->state = 4; + moby->state = CODEBOT_SLOT_COMPLETED; } } break; From 08c83eaf4773cbcb4e6ce1b7fe072dd7530b71e1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:05:58 +0000 Subject: [PATCH 0247/1502] decomp: clarify names in generate_random_points_from_shape_entries domain_0_value_2 -> SHAPE_INDEXED_CENTER_SPHERE: The scan selector is the same HitShape low byte extracted from entry flags at 0025ad70-0025ad84. Within the grouped sphere cases 0/1/2, slti at 0025adc8 compares that selector to 2: the true path copies the inline center at entry+0x10, while the false path at 0025adf8-0025ae28 reads the indexed scratchpad center and adds the inline offset. This is exactly the existing local HitShape member SHAPE_INDEXED_CENTER_SPHERE=2 used by this switch, not an unrelated equal-valued constant. domain_1_value_2 -> SHAPE_INDEXED_CENTER_SPHERE: Weighted selection retrieves an entry from the scan's entries array at 0025b05c-0025b060 and loads its shape type byte at 0025b064. In the same grouped HitShape sphere cases, slti at 0025b08c compares type to 2. Below it the center is copied inline (0025b094-0025b0bc); otherwise entry+4 indexes the scratchpad center and entry+0x10 supplies an added offset (0025b0c0-0025b0f0), with entry+0xc radius. Thus the operand is the existing local SHAPE_INDEXED_CENTER_SPHERE member in this exact selector domain. --- src/overlays/shared/mobys/find_moby_hit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/mobys/find_moby_hit.c b/src/overlays/shared/mobys/find_moby_hit.c index 1f55da00c2..add6bd3cfc 100644 --- a/src/overlays/shared/mobys/find_moby_hit.c +++ b/src/overlays/shared/mobys/find_moby_hit.c @@ -639,7 +639,7 @@ int generate_random_points_from_shape_entries( case SHAPE_INLINE_CENTER_SPHERE: case 1: case SHAPE_INDEXED_CENTER_SPHERE: { - if (type < 2) { + if (type < SHAPE_INDEXED_CENTER_SPHERE) { qcopy(&shape_anchor, (void *)((entry + 0x10))); scale_vector(*(float *)(entity + 0x2c) * 0.0009765625f, &shape_anchor, @@ -709,7 +709,7 @@ int generate_random_points_from_shape_entries( case 1: case SHAPE_INDEXED_CENTER_SPHERE: { float radius, extent; - if (type < 2) { + if (type < SHAPE_INDEXED_CENTER_SPHERE) { qcopy(&shape_anchor, (void *)((entry + 0x10))); FUN_001f9a68_25aca0(*(float *)(entity + 0x2c), &shape_anchor, &shape_anchor); extent = shape_anchor.f[3] * *(float *)(entity + 0x2c); From c14314a68e02751bc3158c2e8f754a3ab1b0054b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:05:58 +0000 Subject: [PATCH 0248/1502] decomp: clarify names in hero_update_hop_velocity domain_0_value_10 -> HERO_STATE_PACK_JUMP: Authoritative source (SHA-256 0bd36091d56bb3a84fd312d922293b48665c12ece127a329d4bcc62ca0901149) assigns state = hero.state.current. Retail 0x00223468/0x00223478 loads hero base 0x0013f350 plus 0x2084 into a0; original decompilation identifies this same selector as iRam001413d4. Thus this is the HeroStateId current-state domain in include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), not control_mode at +0x208c. Retail 0x0022345c/0x0022347c compares this selector to 10; 0x0022349c-0x002234bc builds the scaled move impulse, copies +0x920 to momentum +0x150 and copies flat speed +0x164 to ground speed +0x194. Reuse the canonical domain member HERO_STATE_PACK_JUMP = 10. domain_1_value_16 -> HERO_STATE_PACK_LONG_JUMP: Authoritative source (SHA-256 0bd36091d56bb3a84fd312d922293b48665c12ece127a329d4bcc62ca0901149) assigns state = hero.state.current. Retail 0x00223468/0x00223478 loads hero base 0x0013f350 plus 0x2084 into a0; original decompilation identifies this same selector as iRam001413d4. Thus this is the HeroStateId current-state domain in include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), not control_mode at +0x208c. Retail 0x002234c0-0x002234c4 compares the same selector to 16. 0x00223504-0x00223534 selects long_jump_speed (+0x3f4) before the timer threshold and frame_time*3.5 afterward; 0x00223554-0x00223580 adjusts speed and constructs forward velocity. Reuse canonical HERO_STATE_PACK_LONG_JUMP = 16. domain_2_value_28 -> HERO_STATE_LEDGE_JUMP: Authoritative source (SHA-256 0bd36091d56bb3a84fd312d922293b48665c12ece127a329d4bcc62ca0901149) assigns state = hero.state.current. Retail 0x00223468/0x00223478 loads hero base 0x0013f350 plus 0x2084 into a0; original decompilation identifies this same selector as iRam001413d4. Thus this is the HeroStateId current-state domain in include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), not control_mode at +0x208c. Retail 0x002234c8/0x0022358c compares the same selector to 28. 0x00223604-0x00223698 gates changes to ledge_jump_speed (+0x45c) by animation frames 13 through 30; 0x002236a0-0x002236c8 forms XY velocity from that speed and yaw. Reuse canonical HERO_STATE_LEDGE_JUMP = 28. domain_3_value_11 -> HERO_STATE_HIGH_JUMP: Authoritative source (SHA-256 0bd36091d56bb3a84fd312d922293b48665c12ece127a329d4bcc62ca0901149) assigns state = hero.state.current. Retail 0x00223468/0x00223478 loads hero base 0x0013f350 plus 0x2084 into a0; original decompilation identifies this same selector as iRam001413d4. Thus this is the HeroStateId current-state domain in include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), not control_mode at +0x208c. Retail 0x00223590 and 0x002236cc implements unsigned (current_state-11)<2 for states 11 and 12; 0x0022373c-0x00223744 reloads exactly +0x2084 and distinguishes 11 for apex/landing-dependent high_jump_drift_speed updates. Source already uses HERO_STATE_HIGH_JUMP in that nested comparison, establishing the same canonical member for the outer 11. domain_4_value_12 -> HERO_STATE_STORED_HEADING_JUMP: Authoritative source (SHA-256 0bd36091d56bb3a84fd312d922293b48665c12ece127a329d4bcc62ca0901149) assigns state = hero.state.current. Retail 0x00223468/0x00223478 loads hero base 0x0013f350 plus 0x2084 into a0; original decompilation identifies this same selector as iRam001413d4. Thus this is the HeroStateId current-state domain in include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), not control_mode at +0x208c. Retail 0x00223590/0x002236cc groups current states 11 and 12. 0x0022370c-0x0022371c copies takeoff_yaw (+0x43c) to move_yaw (+0x180); 0x002237cc-0x00223834 builds drift velocity and takeoff-heading additions. State 12 skips the state-11-only drift update at 0x00223744. Reuse canonical HeroStateId member HERO_STATE_STORED_HEADING_JUMP = 12. domain_5_value_17 -> HERO_STATE_REPEATABLE_JUMP: Authoritative source (SHA-256 0bd36091d56bb3a84fd312d922293b48665c12ece127a329d4bcc62ca0901149) assigns state = hero.state.current. Retail 0x00223468/0x00223478 loads hero base 0x0013f350 plus 0x2084 into a0; original decompilation identifies this same selector as iRam001413d4. Thus this is the HeroStateId current-state domain in include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), not control_mode at +0x208c. Retail 0x00223878-0x0022387c compares the same current-state selector to 17. 0x00223884-0x00223898 restores move_yaw and move_dir from hero+0x470; 0x002238f4-0x002239a0 waits nine scaled frames then constructs velocity at frame_time*4.9 in world or gravity-relative form. Reuse canonical HeroStateId member HERO_STATE_REPEATABLE_JUMP = 17. domain_6_value_45 -> HERO_STATE_ITEM_RELEASE_FALL: Authoritative source (SHA-256 0bd36091d56bb3a84fd312d922293b48665c12ece127a329d4bcc62ca0901149) assigns state = hero.state.current. Retail 0x00223468/0x00223478 loads hero base 0x0013f350 plus 0x2084 into a0; original decompilation identifies this same selector as iRam001413d4. Thus this is the HeroStateId current-state domain in include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), not control_mode at +0x208c. Retail 0x00223880 loads 45 and 0x002239b4 compares the same current-state selector against it. 0x002239bc-0x00223a34 springs a copy of yaw toward move_yaw and applies only the yaw delta through fixed-pivot rotation; default movement impulse and air acceleration follow. Reuse canonical HeroStateId member HERO_STATE_ITEM_RELEASE_FALL = 45; this movement handler need not reestablish the full release-state lifecycle. --- .../shared/hero/process_hero_item_action_input.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/hero/process_hero_item_action_input.c b/src/overlays/shared/hero/process_hero_item_action_input.c index 6859049518..61fb2cb68f 100644 --- a/src/overlays/shared/hero/process_hero_item_action_input.c +++ b/src/overlays/shared/hero/process_hero_item_action_input.c @@ -239,11 +239,11 @@ void hero_update_hop_velocity(void) { s32 state; state = hero.state.current; - if (state == 10) { + if (state == HERO_STATE_PACK_JUMP) { build_scaled_hero_move_impulse(0.7f, ED6C * 0.0f); qcopy(&hero.motion.momentum, &hero.move_impulse); hero.ground_speed = hero.motion.flat_speed; - } else if (state == 16) { + } else if (state == HERO_STATE_PACK_LONG_JUMP) { if (scale_game_frames(0x36) < hero.state_timer) { approach_value(ED70 * 25.0f, ED70 * 7.0f, &hero.jump_gravity); } @@ -255,7 +255,7 @@ void hero_update_hop_velocity(void) { speed_step(ED70 * 44.0f, ED70 * 45.0f); set_gravity_relative_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, 0.0f); add_hero_forward_offset(&hero.motion.velocity, &hero.motion.velocity, hero.ground_speed); - } else if (state == 0x1C) { + } else if (state == HERO_STATE_LEDGE_JUMP) { if (scale_game_frames(0x28) < hero.state_timer) { turn_to(0, ED64 * 0.04f, ED64 * 0.2f, ED6C * 15.009831f); air_accel(ED70 * 20.0f); @@ -269,7 +269,7 @@ void hero_update_hop_velocity(void) { } hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * hero.ledge_jump_speed; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * hero.ledge_jump_speed; - } else if (state == 11 || state == 12) { + } else if (state == HERO_STATE_HIGH_JUMP || state == HERO_STATE_STORED_HEADING_JUMP) { hero.motion.move_yaw = hero.takeoff_yaw; turn_to(0, ED64 * 0.04f, ED64 * 0.2f, ED6C * 6.981317f); if (hero.unk450 != 3) { @@ -292,7 +292,7 @@ void hero_update_hop_velocity(void) { hero.motion.velocity.f[1] += fast_sin(hero.takeoff_yaw) * a; build_scaled_hero_move_impulse(0.7f, ED6C * 0.0f); qcopy(&hero.motion.momentum, &hero.move_impulse); - } else if (state == 0x11) { + } else if (state == HERO_STATE_REPEATABLE_JUMP) { hero.motion.move_yaw = hero.unk470.f[3]; qcopy(&hero.motion.move_dir, &hero.unk470); if (scale_game_frames(9) < hero.state_timer) { @@ -311,7 +311,7 @@ void hero_update_hop_velocity(void) { } hero.ground_speed = hero.motion.flat_speed; } else { - if (state == 0x2D) { + if (state == HERO_STATE_ITEM_RELEASE_FALL) { x = hero.motion.rot.f[2]; hero.motion.yaw_error = spring_angle(&x, &hero.motion.yaw_rate, From f0f6f6489dbbc718eb70799645da2bd373ebad6d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:05:58 +0000 Subject: [PATCH 0249/1502] decomp: clarify names in water_update domain_0_value_3 -> WATER_WAIT_FOR_HERO_IN_VOLUME: Retail 0030c7fc-0030c808 stores 3 to s2+0x20, the byte read by the switch at 0030c564. Its case at 0030ca38-0030ca5c tests the hero position against water_data->volume. This is the existing local WATER_WAIT_FOR_HERO_IN_VOLUME domain member. domain_1_value_1 -> WATER_APPROACH_HIGH_HEIGHT: Retail 0030c84c-0030c854 stores 1 to s2+0x20, the switch selector byte at 0030c564. Original Ghidra case 1 and instructions 0030c954-0030c998 approach the height at s3+0, water_data->hi. Reuse the existing WATER_APPROACH_HIGH_HEIGHT member. domain_2_value_2 -> WATER_APPROACH_LOW_HEIGHT: Retail 0030c858-0030c860 stores 2 to s2+0x20, the switch selector byte at 0030c564. Original Ghidra case 2 and instructions 0030c8b8-0030c8fc select s3+4, water_data->lo, as the approach target. Reuse WATER_APPROACH_LOW_HEIGHT. domain_3_value_5 -> WATER_TIMED_RISE: Retail 0030ca68-0030ca8c waits for the timer, reloads it with scaled 0x708 and stores 5 to the same s2+0x20 switch selector. Case 5 at 0030ca90-0030cac8 raises height by delta*0.32 and decrements that timer. This proves existing WATER_TIMED_RISE. domain_4_value_6 -> WATER_RISE_TO_HEIGHT_54: Retail 0030cabc-0030cac8 stores 6 to the s2+0x20 switch selector when the rise timer expires. Case 6 at 0030cacc-0030cb0c raises height by delta*0.42 and compares against 54.0 before transition. Reuse existing WATER_RISE_TO_HEIGHT_54. domain_5_value_7 -> WATER_REMOVE_ABOVE_HIGH_HEIGHT: Retail 0030caf4-0030cb0c stores 7 to the s2+0x20 switch selector on reaching height 54. Case 7 at 0030cb10-0030cb44 compares height against s3+0 (water_data->hi), clears grid visibility and calls removal when exceeded. Reuse WATER_REMOVE_ABOVE_HIGH_HEIGHT. domain_6_value_3 -> WATER_WAIT_FOR_HERO_IN_VOLUME: Source compares water_moby->state >= 3 as the lower bound of its 3..7 visibility gate. Retail 0030cbd4-0030cbe0 reads the identical s2+0x20 switch byte and implements the interval by subtracting 3 and testing unsigned <5. Thus the bound is the existing WATER_WAIT_FOR_HERO_IN_VOLUME member, not a hero state or control mode. domain_7_value_7 -> WATER_REMOVE_ABOVE_HIGH_HEIGHT: Source compares water_moby->state <= 7 as the upper bound of its 3..7 visibility gate. Retail 0030cbd4-0030cbe0 reads the identical s2+0x20 switch byte and implements that interval with unsigned (state-3)<5. The upper endpoint is the same existing WATER_REMOVE_ABOVE_HIGH_HEIGHT member used by case 7. --- src/overlays/l07/mobys/water.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l07/mobys/water.c b/src/overlays/l07/mobys/water.c index 72b69a3d4b..32da774253 100644 --- a/src/overlays/l07/mobys/water.c +++ b/src/overlays/l07/mobys/water.c @@ -222,15 +222,15 @@ void water_update(Moby_30D8E8 *water_moby) { } } if (water_data->fC != 0) { - water_moby->state = 3; + water_moby->state = WATER_WAIT_FOR_HERO_IN_VOLUME; water_data->timer = scale_game_frames(0x3C); if (water_moby->pos[2] < water_data->lo) { l07_water_grids[water_data->idx].visible_subtiles = 0; } } else if (water_data->f8 != 0) { - water_moby->state = 1; + water_moby->state = WATER_APPROACH_HIGH_HEIGHT; } else { - water_moby->state = 2; + water_moby->state = WATER_APPROACH_LOW_HEIGHT; } break; case WATER_APPROACH_LOW_HEIGHT: @@ -277,19 +277,19 @@ void water_update(Moby_30D8E8 *water_moby) { case WATER_WAIT_BEFORE_RISING: if (fast_dec_timer(&water_data->timer)) { water_data->timer = scale_game_frames(0x708); - water_moby->state = 5; + water_moby->state = WATER_TIMED_RISE; } break; case WATER_TIMED_RISE: water_moby->pos[2] += D_0015ED6C * 0.32f; if (fast_dec_timer(&water_data->timer)) { - water_moby->state = 6; + water_moby->state = WATER_RISE_TO_HEIGHT_54; } break; case WATER_RISE_TO_HEIGHT_54: water_moby->pos[2] += D_0015ED6C * 0.42f; if (water_moby->pos[2] >= 54.0f) { - water_moby->state = 7; + water_moby->state = WATER_REMOVE_ABOVE_HIGH_HEIGHT; } break; case WATER_REMOVE_ABOVE_HIGH_HEIGHT: @@ -311,7 +311,7 @@ void water_update(Moby_30D8E8 *water_moby) { l07_water_grids[water_data->idx].z = water_moby->pos[2]; on = 0.0f; if (water_moby->f94 != 0 && FUN_L01_00275690_2cd2b0(water_moby, 48.0f) != -1) { - if (!(water_moby->state >= 3 && water_moby->state <= 7) || + if (!(water_moby->state >= WATER_WAIT_FOR_HERO_IN_VOLUME && water_moby->state <= WATER_REMOVE_ABOVE_HIGH_HEIGHT) || (water_moby->pos[2] > water_data->lo && water_moby->pos[2] < water_data->hi)) { on = 1.0f; } From 5f6a5511e551a226744da9e152c6ff7990bbe2be Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:05:59 +0000 Subject: [PATCH 0250/1502] decomp: clarify names in ultramech_scientist_update domain_0_value_9 -> ULTRAMECH_SCIENTIST_DISABLED: Retail 0x002ec7f4-0x002ec818 reads this moby's +0x20 state, compares 9, clears update_dist at +0x30 and collision at +0x94, sets flags 0x41 and returns. This proves a disabled scientist state in the same selector domain as the local scientist enum. domain_11_value_3 -> ULTRAMECH_SCIENTIST_WAIT_FOR_PRE_SCENE_CONDITIONS: Retail 0x002eca7c-0x002ecab4 takes the zero signed-short path, optionally invokes the path helper, then writes 3 into this moby's +0x20 state. Existing case 3 in the switch on that same byte waits for pre-scene conditions at 0x002ecac0-0x002ecb68. domain_12_value_9 -> ULTRAMECH_SCIENTIST_DISABLED: Retail 0x002eca7c-0x002eca84 takes the nonzero pvars+4 branch to 0x002ecab8-0x002ecabc and stores 9 in this moby's +0x20 state. The same state byte is compared at 0x002ec7f4-0x002ec818 to clear update distance and collision, set flags and return. domain_15_value_4 -> ULTRAMECH_SCIENTIST_WAIT_FOR_PRE_SCENE_DELAY: Retail 0x002ecb54-0x002ecb68 writes 4 to this moby's +0x20 state and initializes pvars+0x15C with scale_game_frames(120). Existing case ULTRAMECH_SCIENTIST_WAIT_FOR_PRE_SCENE_DELAY is selected by the same state byte and decrements that timer at 0x002ecb6c-0x002ecb80. domain_16_value_5 -> ULTRAMECH_SCIENTIST_START_FIRST_SCENE: After the pre-scene timer and camera setup, retail 0x002ecc2c-0x002ecc34 stores 5 into this moby's +0x20 state. Existing case ULTRAMECH_SCIENTIST_START_FIRST_SCENE is selected by that same byte and calls start_scene(1) at 0x002ecc38-0x002ecc3c. domain_17_value_6 -> ULTRAMECH_SCIENTIST_WAIT_FOR_FIRST_SCENE: Retail 0x002ecc38-0x002ecc54 calls start_scene(1) then stores 6 into this moby's +0x20 state. Existing case ULTRAMECH_SCIENTIST_WAIT_FOR_FIRST_SCENE switches on that exact byte and waits on the scene mode gate before proceeding at 0x002ecc58-0x002ecc88. domain_18_value_7 -> ULTRAMECH_SCIENTIST_START_SECOND_SCENE_AND_SAVE: Retail 0x002ecc58-0x002ecc88 waits out mode 2, queues the scene movie and writes 7 into this moby's +0x20 state. Existing case ULTRAMECH_SCIENTIST_START_SECOND_SCENE_AND_SAVE is selected by that same byte; its branch calls start_scene(2), then performs the unconditional save at 0x002ecc8c-0x002eccd0. domain_19_value_8 -> ULTRAMECH_SCIENTIST_SAVE_AND_DISABLE: Retail 0x002ecca8-0x002eccb4 calls start_scene(2) and writes 8 into this moby's +0x20 state before continuing into save. Existing case ULTRAMECH_SCIENTIST_SAVE_AND_DISABLE selects the same state byte and saves then writes disabled state 9 at 0x002eccb8-0x002eccd0. domain_1_value_1 -> ULTRAMECH_SCIENTIST_WAIT_FOR_DIALOGUE: Retail 0x002ec890-0x002ec8b8 stores 1 into this moby's state byte +0x20 while initializing NPC dialogue. The same byte selects existing case ULTRAMECH_SCIENTIST_WAIT_FOR_DIALOGUE, whose clip-volume and dialogue-update gates are at 0x002ec96c-0x002ec9c8. domain_20_value_9 -> ULTRAMECH_SCIENTIST_DISABLED: In existing START_SECOND_SCENE_AND_SAVE, retail 0x002ecc98 branches directly to save when mode is 2; either path reaches 0x002eccbc-0x002eccd0 and stores 9 into this moby's +0x20 state. Entry handling for that exact byte at 0x002ec7f4-0x002ec818 disables updates and collision. domain_21_value_9 -> ULTRAMECH_SCIENTIST_DISABLED: Existing SAVE_AND_DISABLE reaches retail save call 0x002eccbc then stores 9 to this moby's +0x20 state at 0x002eccd0. The entry comparison of the same byte at 0x002ec7f4-0x002ec818 clears update distance and collision, sets flags 0x41 and returns. domain_2_value_9 -> ULTRAMECH_SCIENTIST_DISABLED: Initialization's level-availability gate at 0x002ec8f0-0x002ec8fc branches to 0x002ecab8-0x002ecabc storing 9 into this moby's +0x20 state. The entry comparison at 0x002ec7f4-0x002ec818 disables updates and collision for that exact same state byte. domain_3_value_3 -> ULTRAMECH_SCIENTIST_WAIT_FOR_PRE_SCENE_CONDITIONS: Retail 0x002ec900-0x002ec904 writes 3 into this moby's state byte +0x20 before mission-list cleanup. This is the same byte switched at 0x002ec854; existing case 3 waits for player mode and both group-count gates before starting the pre-scene delay at 0x002ecac0-0x002ecb68. domain_8_value_2 -> ULTRAMECH_SCIENTIST_RESUME_AFTER_DIALOGUE: Retail 0x002ec9b4-0x002ec9e0 gates on successful NPC dialogue, pauses anim_speed and writes 2 to this moby's +0x20 state. Existing case ULTRAMECH_SCIENTIST_RESUME_AFTER_DIALOGUE reads that same state domain and restores animation at 0x002eca4c-0x002eca78. --- src/overlays/l15/mobys/ultramech_scientist.c | 30 ++++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/overlays/l15/mobys/ultramech_scientist.c b/src/overlays/l15/mobys/ultramech_scientist.c index 4722917e82..5cf8dc59ce 100644 --- a/src/overlays/l15/mobys/ultramech_scientist.c +++ b/src/overlays/l15/mobys/ultramech_scientist.c @@ -114,7 +114,7 @@ void ultramech_scientist_update(struct Moby *moby) { ULTRAMECH_SCIENTIST_WAIT_FOR_FIRST_SCENE = 6, ULTRAMECH_SCIENTIST_START_SECOND_SCENE_AND_SAVE = 7, ULTRAMECH_SCIENTIST_SAVE_AND_DISABLE = 8 - }; + } ; enum { ULTRAMECH_SCIENTIST_DISABLED = 9}; UltramechScientistVars *ultramech_scientist_private_data; char *hero_pos; struct Moby *moby_list_cursor; @@ -134,7 +134,7 @@ void ultramech_scientist_update(struct Moby *moby) { 0x41; } } - if (moby->state == 9) { + if (moby->state == ULTRAMECH_SCIENTIST_DISABLED) { moby->update_dist = 0; moby->collision = 0; moby->flags |= 0x41; @@ -151,7 +151,7 @@ void ultramech_scientist_update(struct Moby *moby) { switch (moby->state) { case ULTRAMECH_SCIENTIST_INITIALIZE: - moby->state = 1; + moby->state = ULTRAMECH_SCIENTIST_WAIT_FOR_DIALOGUE; moby->update_dist = 0xFF; ultramech_scientist_private_data->unkC = 20.0f; initialize_npc_dialogue(moby, ultramech_scientist_private_data); @@ -160,10 +160,10 @@ void ultramech_scientist_update(struct Moby *moby) { break; } if (level_available[16] != 0) { - moby->state = 9; + moby->state = ULTRAMECH_SCIENTIST_DISABLED; break; } - moby->state = 3; + moby->state = ULTRAMECH_SCIENTIST_WAIT_FOR_PRE_SCENE_CONDITIONS; moby_list_cursor = (struct Moby *)D_L15_0015FFE4; if (moby_list_cursor == 0) { break; @@ -206,7 +206,7 @@ void ultramech_scientist_update(struct Moby *moby) { } jet_clear_persistent(ultramech_scientist_private_data->unk280); moby->anim_speed = 0.0f; - moby->state = 2; + moby->state = ULTRAMECH_SCIENTIST_RESUME_AFTER_DIALOGUE; moby_list_cursor = (struct Moby *)D_L15_0015FFE4; if (moby_list_cursor == 0) { break; @@ -245,9 +245,9 @@ void ultramech_scientist_update(struct Moby *moby) { FUN_L00_00284e50(paths + (ultramech_scientist_private_data->unk150 << 7) + 0x30, paths + (ultramech_scientist_private_data->unk150 << 7) + 0x70); } - moby->state = 3; + moby->state = ULTRAMECH_SCIENTIST_WAIT_FOR_PRE_SCENE_CONDITIONS; } else { - moby->state = 9; + moby->state = ULTRAMECH_SCIENTIST_DISABLED; } break; case ULTRAMECH_SCIENTIST_WAIT_FOR_PRE_SCENE_CONDITIONS: { @@ -275,7 +275,7 @@ void ultramech_scientist_update(struct Moby *moby) { if (count_active_moby_group_members(ultramech_scientist_private_data->unk148, 0x40) != 0) { break; } - moby->state = 4; + moby->state = ULTRAMECH_SCIENTIST_WAIT_FOR_PRE_SCENE_DELAY; ultramech_scientist_private_data->timer_15C = scale_game_frames(120); break; case ULTRAMECH_SCIENTIST_WAIT_FOR_PRE_SCENE_DELAY: @@ -302,31 +302,31 @@ void ultramech_scientist_update(struct Moby *moby) { FUN_L00_00284e50(paths_again + (ultramech_scientist_private_data->unk154 << 7) + 0x30, paths_again + (ultramech_scientist_private_data->unk154 << 7) + 0x70); } - moby->state = 5; + moby->state = ULTRAMECH_SCIENTIST_START_FIRST_SCENE; break; case ULTRAMECH_SCIENTIST_START_FIRST_SCENE: start_scene(1); - moby->state = 6; + moby->state = ULTRAMECH_SCIENTIST_WAIT_FOR_FIRST_SCENE; break; case ULTRAMECH_SCIENTIST_WAIT_FOR_FIRST_SCENE: if (D_L15_0015F5C4 == 2) { break; } queue_scene_movie_with_game_language(0x10); - moby->state = 7; + moby->state = ULTRAMECH_SCIENTIST_START_SECOND_SCENE_AND_SAVE; break; case ULTRAMECH_SCIENTIST_START_SECOND_SCENE_AND_SAVE: if (D_L15_0015F5C4 != 2) { queue_planet_unlock_message(0x10); start_scene(2); - moby->state = 8; + moby->state = ULTRAMECH_SCIENTIST_SAVE_AND_DISABLE; } memcard_save_data(0, -1); - moby->state = 9; + moby->state = ULTRAMECH_SCIENTIST_DISABLED; break; case ULTRAMECH_SCIENTIST_SAVE_AND_DISABLE: memcard_save_data(0, -1); - moby->state = 9; + moby->state = ULTRAMECH_SCIENTIST_DISABLED; break; default: break; From 7c16a6112310f393fc01945903b77f10a3fc39cc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:09:11 +0000 Subject: [PATCH 0251/1502] decomp: clarify names in update_bomber_tank domain_0_value_11 -> BOMBER_TANK_STATE_WAIT_FOR_TRIGGER: Retail 002d4528-002d4538 tests pvars+0x140 then stores 11 to owner+0x20; dispatcher 002d4380-002d4384 reads that same state byte and selects 002d4974, which waits for the indexed trigger moby's pvars float to equal 1. Reuse the existing local state enum member. domain_12_value_6 -> BOMBER_TANK_STATE_FOLLOW_PATH: The scatter/activate branch 002d4a20 calls scatter at 002d4a30 and restores part positions, flags and collisions through 002d4ad4. Retail 002d4ae4-002d4afc then stores 6 to owner+0x20 when mode is not 2, selecting the existing follow-path case that calls the path mover. domain_1_value_14 -> BOMBER_TANK_STATE_SCATTER_GROUP_AND_ACTIVATE: Retail 002d4594-002d45b0 selects the linked-group initialization branch and stores 14 to owner+0x20, the dispatcher state byte. Its existing case at 002d4a20 calls scatter_bomber_tank_linked_debris and restores owner/part collision before entering follow-path state; reuse the existing member. domain_2_value_6 -> BOMBER_TANK_STATE_FOLLOW_PATH: Retail 002d4608 removes linked debris, 002d4610-002d4634 copies the configured path's starting position, and 002d4638-002d4640 stores 6 to owner+0x20. The same byte is dispatched at 002d4380/002d43b8 to the path-follow branch 002d4748. Reuse the existing local enum member. domain_3_value_6 -> BOMBER_TANK_STATE_FOLLOW_PATH: Retail 002d466c-002d4690 copies the configured path position and 002d4694-002d469c stores 6 to owner+0x20, followed by movement animation 1. That byte is the moby->state selector whose existing case 6 calls advance_bomber_tank_along_path at 002d474c. domain_5_value_3 -> BOMBER_TANK_STATE_FOLLOW_PATH_AND_FIRE: Retail 002d4754-002d4780 checks mode and target distance below 20, then 002d47b0-002d47b8 stores 3 to owner+0x20. Dispatcher 002d4398 selects 002d47e4 for this same byte; that branch advances the path and spawns bombs at animation crossings 4/10. Reuse the existing member. domain_7_value_6 -> BOMBER_TANK_STATE_FOLLOW_PATH: Retail 002d47f0-002d4820 exits firing on mode 2 or target distance above 22; 002d4830 stores 6 to owner+0x20 and requests animation 1. The selector is the same state byte read at 002d4380, with existing case 6 following the configured path at 002d4748-002d4750. domain_9_value_6 -> BOMBER_TANK_STATE_FOLLOW_PATH: The wait-for-trigger branch 002d4974-002d499c checks the indexed moby's pvars float, restores positions, flags and collisions, then joins 002d4ae4-002d4afc to store 6 to owner+0x20 when mode is not 2. This is the dispatcher state byte; reuse its existing follow-path enum member. --- src/overlays/l08/mobys/bomber_tank.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l08/mobys/bomber_tank.c b/src/overlays/l08/mobys/bomber_tank.c index 0ccf05731c..d1c37ea028 100644 --- a/src/overlays/l08/mobys/bomber_tank.c +++ b/src/overlays/l08/mobys/bomber_tank.c @@ -193,7 +193,7 @@ void bomber_tank_update(Moby *moby) { moby->flags |= 0x1000; bomber_tank_update_vars->unk16C = frame_time + frame_time; if (bomber_tank_update_vars->trigger_moby > 0) { - moby->state = 11; + moby->state = BOMBER_TANK_STATE_WAIT_FOR_TRIGGER; moby->flags = (moby->flags & 0xEFFF) | 0x41; bomber_tank_update_vars->part_a->flags |= 0x41; bomber_tank_update_vars->part_b->flags |= 0x41; @@ -204,7 +204,7 @@ void bomber_tank_update(Moby *moby) { blend_moby_animation(moby, 0, 0, 0); } else if (bomber_tank_update_vars->unk144 > 0) { if (D_0013D3B6 == 0) { - moby->state = 14; + moby->state = BOMBER_TANK_STATE_SCATTER_GROUP_AND_ACTIVATE; moby->flags |= 0x41; bomber_tank_update_vars->part_a->flags |= 0x41; bomber_tank_update_vars->part_b->flags |= 0x41; @@ -216,13 +216,13 @@ void bomber_tank_update(Moby *moby) { } else { remove_bomber_tank_linked_debris(moby); qcopy(&moby->pos, (char *)l08_paths[bomber_tank_update_vars->path] + 0x10); - moby->state = 6; + moby->state = BOMBER_TANK_STATE_FOLLOW_PATH; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, 0); } } else { qcopy(&moby->pos, (char *)l08_paths[bomber_tank_update_vars->path] + 0x10); - moby->state = 6; + moby->state = BOMBER_TANK_STATE_FOLLOW_PATH; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, 0); } @@ -247,7 +247,7 @@ void bomber_tank_update(Moby *moby) { if (D_00141C38 == 0 && D_0013D4CB == 0) { help_request(0x1F44, 0x5A); } - moby->state = 3; + moby->state = BOMBER_TANK_STATE_FOLLOW_PATH_AND_FIRE; if (moby->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(10)); } @@ -256,7 +256,7 @@ void bomber_tank_update(Moby *moby) { advance_bomber_tank_along_path(moby, bomber_tank_update_vars->path); if (bomber_tank_update_vars->mode == 2 || vector_distance_xy(&moby->pos, &target->pos) > 22.0f) { - moby->state = 6; + moby->state = BOMBER_TANK_STATE_FOLLOW_PATH; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -297,7 +297,7 @@ void bomber_tank_update(Moby *moby) { bomber_tank_update_vars->part_b->pclass->collision; moby->flags |= 0x1000; if (bomber_tank_update_vars->mode != 2) { - moby->state = 6; + moby->state = BOMBER_TANK_STATE_FOLLOW_PATH; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -323,7 +323,7 @@ void bomber_tank_update(Moby *moby) { bomber_tank_update_vars->part_b->pclass->collision; moby->flags |= 0x1000; if (bomber_tank_update_vars->mode != 2) { - moby->state = 6; + moby->state = BOMBER_TANK_STATE_FOLLOW_PATH; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } From 6e3d8140c6e19db7572aa92fa225ede156a08a1c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:09:11 +0000 Subject: [PATCH 0252/1502] decomp: clarify names in update_hero_hoverboard_race_progress domain_0_value_0 -> RACE_RESPAWN_GATE_WAITING: Retail 0x00254980 initializes race_respawn_request_active to 1, and 0x00254988 clears the separate gp-0x757c race_respawn_gate_state to zero. The comparison at 0x00254994-0x0025499c then skips respawn while this initial value persists. Thus zero is the waiting gate state of the newly initialized respawn request, independent of hero current-state IDs. domain_1_value_1 -> RACE_RESPAWN_GATE_READY: Retail 0x00254994 loads gp-0x757c, the same race_respawn_gate_state cleared at 0x00254988; 0x0025499c branches away unless it equals 1. Equality allows clearing off_course_reset_pending, compute_hero_hoverboard_respawn_transform at 0x002549b0, timer reset and set_race_camera at 0x002549d0. Value 1 therefore means this respawn gate is ready to execute the reset. domain_2_value_0 -> FALSE: Source declares pal_mode as the integer PAL flag bound to D_0015ED80 and tests pal_mode != 0. Retail 0x00254d2c loads that exact binding and 0x00254d30 takes the default 0x1644 threshold when zero; nonzero selects the PAL-dependent 0x1680 threshold. Existing FALSE=0 expresses the proven false flag test without assigning this selector to a hero state or vehicle enum. --- .../shared/hero/process_hero_primary_item_input.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/hero/process_hero_primary_item_input.c b/src/overlays/shared/hero/process_hero_primary_item_input.c index 24f6807cf9..33eb457a75 100644 --- a/src/overlays/shared/hero/process_hero_primary_item_input.c +++ b/src/overlays/shared/hero/process_hero_primary_item_input.c @@ -1543,6 +1543,10 @@ extern s32 current_bolt_count_macro __asm__("D_0015ED98") MACRO_ADDR; void update_hero_hoverboard_race_progress(void) __asm__("FUN_L05_00254608"); void update_hero_hoverboard_race_progress(void) { + enum { + RACE_RESPAWN_GATE_WAITING = 0, + RACE_RESPAWN_GATE_READY = 1 + }; float world_position_scratch[4] __attribute__((aligned(16))); float course_point_or_respawn_rotation[4] __attribute__((aligned(16))); Data *race_pvars; @@ -1634,11 +1638,11 @@ void update_hero_hoverboard_race_progress(void) { if (hero.off_course_frames > FUN_001f96f8_254608(0xB4)) { if (race_respawn_request_active == 0) { race_respawn_request_active = 1; - race_respawn_gate_state = 0; + race_respawn_gate_state = RACE_RESPAWN_GATE_WAITING; D_L05_0015F67C = frame_scale * 0.08f; } hero.off_course_reset_pending = 1; - if (race_respawn_gate_state == 1) { + if (race_respawn_gate_state == RACE_RESPAWN_GATE_READY) { hero.off_course_reset_pending = 0; compute_hero_hoverboard_respawn_transform(world_position_scratch, course_point_or_respawn_rotation); @@ -1717,7 +1721,7 @@ void update_hero_hoverboard_race_progress(void) { if (D_0015ED84_lui == 5) { int fast_finish_threshold_frames; - if (pal_mode != 0) { + if (pal_mode != FALSE) { fast_finish_threshold_frames = FUN_001f96f8_254608(0x1680); } else { fast_finish_threshold_frames = FUN_001f96f8_254608(0x1644); From bceb03fdc7c721f8103a11d780e927bb94926eda Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:09:11 +0000 Subject: [PATCH 0253/1502] decomp: clarify names in pyrocitor_update domain_0_value_1 -> PYROCITOR_STATE_WAIT_FOR_READY: Retail 002b7844 loads this weapon moby's state byte at s5+0x20; 002b7884-002b7890 initializes light/voice to -1 and stores 1 into that same byte. Its dispatch at 002b7848-002b784c reaches 002b7894, which waits for animation seq 1. This is the exact selector already labeled PYROCITOR_STATE_WAIT_FOR_READY=1 in the function-local enum. domain_1_value_2 -> PYROCITOR_STATE_READY: Retail 002b7894-002b78a4 tests weapon animation byte s5+0x52 for 1 and writes 2 to s5+0x20, the same byte loaded for switch dispatch at 002b7844. Dispatch 002b786c reaches 002b7920, the source PYROCITOR_STATE_READY=2 case that waits for held fire input and ammo before firing. domain_2_value_3 -> PYROCITOR_STATE_FIRING: Retail 002b79e8-002b7a10 tests held item input, use lock and get_ammo; 002b7a14-002b7a1c stores 3 into the weapon state byte s5+0x20 and starts equipped item animation. The same selector dispatches value 3 at 002b7874 to 002b7a9c, source PYROCITOR_STATE_FIRING=3, which emits flame particles and consumes ammo. domain_3_value_3 -> PYROCITOR_STATE_FIRING: Retail 002b7ad4 reloads weapon state byte s5+0x20 and 002b7ad8 compares it to s0, the value 3 retained from the firing dispatch at 002b7844/002b7874. The successful branch updates the firing light offset/color at 002b7af0-002b7be4. It tests the exact same moby->state domain already named PYROCITOR_STATE_FIRING=3. domain_7_value_2 -> PYROCITOR_STATE_READY: Retail 002b8100-002b814c checks ammo, firing timer expiry and held fire/use lock; when firing cannot continue it writes 2 into s5+0x20 and calls cancel_hero_item_animation, then releases the firing voice. This is the same weapon state selector loaded at 002b7844 and dispatched to the established PYROCITOR_STATE_READY=2 branch at 002b7920. --- src/overlays/shared/weapons/pyrocitor.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/weapons/pyrocitor.c b/src/overlays/shared/weapons/pyrocitor.c index 55ff660c9a..cc472e2ca0 100644 --- a/src/overlays/shared/weapons/pyrocitor.c +++ b/src/overlays/shared/weapons/pyrocitor.c @@ -544,11 +544,11 @@ void pyrocitor_update(struct Moby *moby) { case PYROCITOR_STATE_INITIALIZE: pyrocitor_vars->light = -1; pyrocitor_vars->voice = -1; - moby->state = 1; + moby->state = PYROCITOR_STATE_WAIT_FOR_READY; break; case PYROCITOR_STATE_WAIT_FOR_READY: if (moby->seq == 1) - moby->state = 2; + moby->state = PYROCITOR_STATE_READY; if (moby->seq != 0) break; if (compute_interpolated_record_value(moby) > 10.0f && @@ -580,7 +580,7 @@ void pyrocitor_update(struct Moby *moby) { /* Fakematch: the second pad name rebuilds the address for these button tests. */ if ((controller_state_lui.held & hero.items[0].button_mask) && !hero.item_use_locked && get_ammo(-1)) { - moby->state = 3; + moby->state = PYROCITOR_STATE_FIRING; start_equipped_item_animation(); pyrocitor_vars->timer = scale_game_frames(10); if (pyrocitor_vars->light == -1) @@ -592,7 +592,7 @@ void pyrocitor_update(struct Moby *moby) { case PYROCITOR_STATE_FIRING: if (!voice_is_playing(moby, pyrocitor_vars->voice)) pyrocitor_vars->voice = FUN_0022da68(1, 4, moby); - if (pyrocitor_vars->light != -1 && moby->state == 3) { + if (pyrocitor_vars->light != -1 && moby->state == PYROCITOR_STATE_FIRING) { light_offset_and_flame_velocity.q = 0; light_offset_and_flame_velocity.f.x = 2.0f; light_offset_and_flame_velocity.f.z = 2.0f; @@ -714,7 +714,7 @@ void pyrocitor_update(struct Moby *moby) { if ((controller_state.held & hero.items[0].button_mask) && !hero.item_use_locked && ready) break; - moby->state = 2; + moby->state = PYROCITOR_STATE_READY; cancel_hero_item_animation(); firing_voice_slot_index = pyrocitor_vars->voice; if (firing_voice_slot_index != -1) { From a7ec2dd5c14705051ddc0dc83866c265f1250236 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:11:29 +0000 Subject: [PATCH 0254/1502] decomp: clarify names in update_player_ship_flight domain_0_value_7 -> JET_FIGHTER_STATE_WAIT_FOR_RESPAWN: Retail 0x00312fe0 spawns the collision explosion; 0x00312fec loads 7 and 0x00312ffc stores it to 0x20(s3), the ship moby state. 0x00312ff0 hides the ship and 0x00313000..0x0031300c sets private-data+0xF8 to scale_game_frames(90), supplying the respawn countdown. The selector is ship_moby->state, the same Moby passed by jet_fighter_update with its pvars to update_player_ship_flight. Authoritative C jet_fighter_update declares JET_FIGHTER_STATE_WAIT_FOR_RESPAWN = 7 and handles that member by decrementing ship_vars->iF8 then calling hero_respawn. Checked caller evidence c8cef31c31c146d08269d77a7a0fdea0 confirms a0 is preserved in s4 at 0x0031329c, its pvars are loaded into s3 at 0x003132c0, and 0x00312838 is a direct callee. Thus reuse the existing jet-fighter state member, with function-local scope as needed. domain_1_value_7 -> JET_FIGHTER_STATE_WAIT_FOR_RESPAWN: Retail 0x003130d4..0x003130e8 subtracts collision damage from hero.ship_hp and tests for negative health. The fatal branch spawns an explosion at 0x003131b4, loads 7 at 0x003131bc and stores it to ship moby state +0x20 at 0x003131c0. This writes the identical ship state handled by the caller's respawn branch. The selector is ship_moby->state, the same Moby passed by jet_fighter_update with its pvars to update_player_ship_flight. Authoritative C jet_fighter_update declares JET_FIGHTER_STATE_WAIT_FOR_RESPAWN = 7 and handles that member by decrementing ship_vars->iF8 then calling hero_respawn. Checked caller evidence c8cef31c31c146d08269d77a7a0fdea0 confirms a0 is preserved in s4 at 0x0031329c, its pvars are loaded into s3 at 0x003132c0, and 0x00312838 is a direct callee. Thus reuse the existing jet-fighter state member, with function-local scope as needed. --- src/overlays/l11/mobys/jet_fighter.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l11/mobys/jet_fighter.c b/src/overlays/l11/mobys/jet_fighter.c index 3607b840df..53e58668ad 100644 --- a/src/overlays/l11/mobys/jet_fighter.c +++ b/src/overlays/l11/mobys/jet_fighter.c @@ -859,6 +859,9 @@ void update_player_ship_flight(struct Moby *ship_moby, ShipVars_2838 *ship_vars) __asm__("FUN_L11_00312838"); void update_player_ship_flight(struct Moby *ship_moby, ShipVars_2838 *ship_vars) { + enum { + JET_FIGHTER_STATE_WAIT_FOR_RESPAWN = 7 + }; W4_2838 ship_position_before_movement; W4_2838 death_explosion_velocity; UQ_2838 up; @@ -1106,7 +1109,7 @@ void update_player_ship_flight(struct Moby *ship_moby, ShipVars_2838 *ship_vars) -1, 0); ship_moby->visible = 0; - ship_moby->state = 7; + ship_moby->state = JET_FIGHTER_STATE_WAIT_FOR_RESPAWN; ship_moby->flags |= 1; ship_vars->iF8 = scale_game_frames(0x5A); } else { @@ -1159,7 +1162,7 @@ void update_player_ship_flight(struct Moby *ship_moby, ShipVars_2838 *ship_vars) 1, -1, 0); - ship_moby->state = 7; + ship_moby->state = JET_FIGHTER_STATE_WAIT_FOR_RESPAWN; } ship_vars->iDC = D_L11_0016214C; } From e1f794196e066cf175b254df39eed28fb999e0a6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:11:30 +0000 Subject: [PATCH 0255/1502] decomp: clarify names in update_giant_clank_charged_blast domain_0_value_1 -> EXPANDING_BLAST: Authoritative giant_clank_charged_blast.c SHA-256 da26fd57e80dc0e19d1769f0c792d776506192d1686899c2bf626b6ba3754414 declares EXPANDING_BLAST=1 for switch(moby->state). Retail 0x0029edfc loads that state from moby+0x20; 0x0029ee08-0x0029ee10 compares it with 1 and dispatches to 0x0029f2b8. Release initializes velocity at 0x0029f260-0x0029f2a8, loads 1 at 0x0029f298, stores it to the identical moby+0x20 field at 0x0029f2ac and clears elapsed data+0x14 at 0x0029f2b4. The destination branch increments elapsed and computes growing radius at 0x0029f2b8-0x0029f300, then collects targets and sends blast hits at 0x0029f450-0x0029f4a4. Original Ghidra corroborates *(undefined1 *)(iVar8+0x20)=1 and its state-1 branch. Thus the assignment must reuse the existing local EXPANDING_BLAST constant. --- src/overlays/shared/vehicles/giant_clank_charged_blast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/vehicles/giant_clank_charged_blast.c b/src/overlays/shared/vehicles/giant_clank_charged_blast.c index 7fe23e5d8f..88eb93e5f2 100644 --- a/src/overlays/shared/vehicles/giant_clank_charged_blast.c +++ b/src/overlays/shared/vehicles/giant_clank_charged_blast.c @@ -363,7 +363,7 @@ void giant_clank_charged_blast_update(Moby29FF90 *moby) { moby_data->vel[0] = fast_cos(((Hero29FF90 *)&hero)->f98) * (D_0015ED6C * 40.0f); moby_data->vel[1] = fast_sin(((Hero29FF90 *)&hero)->f98) * (D_0015ED6C * 40.0f); moby_data->vel[2] = 0.0f; - moby->state = 1; + moby->state = EXPANDING_BLAST; moby_data->f14 = 0; } break; From 825bbec4348e181ea78fb093d3967939ba5dddb0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:13:58 +0000 Subject: [PATCH 0256/1502] decomp: clarify names in fred_update domain_0_value_1 -> UPDATE_FRED_DIALOGUE: Retail 0x003011e8 loads 1 and 0x00301200 stores it to s2+0x20 after installing the Scrawny Scientist dialogue name and while calling initialize_npc_dialogue. The same byte is loaded at 0x003010ec for the Fred state switch; its existing UPDATE_FRED_DIALOGUE=1 case calls update_npc_dialogue at 0x0030126c. domain_1_value_2 -> HANDLE_FRED_DIALOGUE_RESULT: Retail 0x0030126c calls update_npc_dialogue, and its successful return leads to loading 2 at 0x00301278 and storing it to s2+0x20 at 0x0030127c. This is the same Fred state selector loaded at 0x003010ec. Existing HANDLE_FRED_DIALOGUE_RESULT=2 handles pvars+4 at 0x0030134c-0x00301388. domain_2_value_1 -> UPDATE_FRED_DIALOGUE: In the existing HANDLE_FRED_DIALOGUE_RESULT case, retail 0x00301350 tests pvars+4 below 2, clears persistent state and changes linked mobys, then 0x0030137c-0x00301380 stores 1 to s2+0x20. That byte drives this function's Fred switch at 0x003010ec; UPDATE_FRED_DIALOGUE=1 resumes NPC dialogue updates. domain_3_value_3 -> INTERPOLATE_FRED_CUTSCENE_CAMERA: Retail 0x003013dc zeroes camera progress pvars+0x178, 0x00301444 starts the camera mount and 0x0030145c sets the race camera. Then 0x00301480-0x00301484 stores 3 to the same s2+0x20 switch selector. Existing INTERPOLATE_FRED_CUTSCENE_CAMERA=3 advances that progress and applies interpolated position/rotation at 0x00301670-0x00301678. domain_4_value_4 -> RAMP_FRED_POST_CUTSCENE_SCALAR_TO_ZERO: Retail 0x0030174c resets the race camera and 0x00301754 ends the mount, then 0x0030175c-0x00301764 stores 4 to the Fred state byte s2+0x20 read by the switch. Existing RAMP_FRED_POST_CUTSCENE_SCALAR_TO_ZERO=4 at 0x00301768-0x003017ac approaches 0x0015f3fc toward zero and advances only on equality. domain_5_value_5 -> WAIT_FOR_FRED_REMOVAL_TRIGGER: Retail 0x00301788 approaches scalar 0x0015f3fc toward zero; 0x00301798 tests equality and 0x003017a4-0x003017ac stores 5 to the Fred switch byte s2+0x20. Existing WAIT_FOR_FRED_REMOVAL_TRIGGER=5 at 0x003017b0 waits for hero control_mode 15, updates linked mobys and calls removal at 0x003017dc. --- src/overlays/l06/mobys/fred.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l06/mobys/fred.c b/src/overlays/l06/mobys/fred.c index 48a037455f..8c1b10edca 100644 --- a/src/overlays/l06/mobys/fred.c +++ b/src/overlays/l06/mobys/fred.c @@ -145,7 +145,7 @@ void fred_update(struct Moby *moby) { fred_vars->f174 = scale_game_frames(0x2D); set_moby_and_links_to_states_8_and_9(D_L06_0015FFD8_301070 + (fred_vars->f160 << 8)); fred_vars->f20 = D_L06_00201880; - moby->state = 1; + moby->state = UPDATE_FRED_DIALOGUE; initialize_npc_dialogue(moby, fred_vars); break; case UPDATE_FRED_DIALOGUE: @@ -158,7 +158,7 @@ void fred_update(struct Moby *moby) { if (check_all_listed_frog_states_fe_fd_or_10(fred_vars->f170) != 0) { if (fast_dec_timer_s16(&fred_vars->f174) != 0 && update_npc_dialogue(moby, fred_vars) != 0) { - moby->state = 2; + moby->state = HANDLE_FRED_DIALOGUE_RESULT; if (fred_vars->f176 != 0) { Vec_301070 t; fast_vec_normalize(t, ((char *)&moby->rot_row0), 2.0f); @@ -182,7 +182,7 @@ void fred_update(struct Moby *moby) { jet_clear_persistent(moby->mission); set_moby_and_links_to_states_4_and_5(D_L06_0015FFD8_301070 + (fred_vars->f164 << 8)); - moby->state = 1; + moby->state = UPDATE_FRED_DIALOGUE; } if (fred_vars->f4 == 2) { grant_inventory_item(0x1D, 1); @@ -206,7 +206,7 @@ void fred_update(struct Moby *moby) { set_race_camera(&hero.motion.pos, &hero.motion.rot, 0x72, 1); set_moby_and_links_to_states_8_and_9(D_L06_0015FFD8_301070 + (fred_vars->f164 << 8)); - moby->state = 3; + moby->state = INTERPOLATE_FRED_CUTSCENE_CAMERA; moby->visible = 0; moby->flags |= 1; *(int *)&moby->collision = 0; @@ -275,7 +275,7 @@ void fred_update(struct Moby *moby) { if (D_L06_0015F3FC_macro == 1.0f) { set_race_camera(&hero.motion.pos, &hero.motion.rot, 0, 0); jet_end_mount(0); - moby->state = 4; + moby->state = RAMP_FRED_POST_CUTSCENE_SCALAR_TO_ZERO; } } break; @@ -283,7 +283,7 @@ void fred_update(struct Moby *moby) { case RAMP_FRED_POST_CUTSCENE_SCALAR_TO_ZERO: approach_value(&D_L06_0015F3FC_macro, 0.0f, frame_time_macro * 4.0f); if (D_L06_0015F3FC_macro == 0.0f) { - moby->state = 5; + moby->state = WAIT_FOR_FRED_REMOVAL_TRIGGER; } break; case WAIT_FOR_FRED_REMOVAL_TRIGGER: From 83d9c8e2b1490154ee1aa353e4c69bcfa64b7b5e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:13:59 +0000 Subject: [PATCH 0257/1502] decomp: clarify names in update_pause_menu domain_0_value_20 -> PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION: The selector is pause-menu GameState.state at 0x001b9cf0, not hero state. Retail 0x00276c60-0x00276c88 tests 20 and waits for the scene delay and CD read; 0x00276ca4-0x00276cf0 restores saved camera vectors/FOV, selects gameplay moby context 0 and resource tables, and updates fog. 0x00276d18-0x00276ea4 dispatches the queued level/movie/scene/slideshow action and resumes audio. Authoritative source close_pause_menu assigns 20 after releasing the menu. domain_11_value_35 -> PAUSE_MENU_STATE_PRESERVE_STATE_ENTRY: Retail 0x00276ee0-0x00276eec tests pause-menu state 35 and initializes the menu. The bounded original initializer at 0x00276368 confirms the 35 branch chooses owner 0x001b6b38 without overwriting the state, unlike branches that install 2,11,15 or34. Source binds that record as l00_pause_menu_state_preserving_entry_page_owner. The assigned retail also exempts this same selector value from self-transition animation-direction inversion at 0x002770a4-0x002770b0. domain_12_value_1 -> PAUSE_MENU_STATE_PAGE_TRANSITION: Retail 0x00276f30-0x00276f54 compares pause-menu state at 0x001b9cf0 with 1 and decrements its transition countdown. At zero, 0x00276f58-0x00276f70 installs pending page owner from scene+8 into scene+4 and restores that owner's +0x3c state; callbacks then activate its objects. This is the same state assigned after setting page animations at 0x00277178. domain_13_value_35 -> PAUSE_MENU_STATE_PRESERVE_STATE_ENTRY: This is the same pause-menu scene state 35 tested for initialization at 0x00276ee0-0x00276eec. Original initializer retail/decompilation selects the source-named l00_pause_menu_state_preserving_entry_page_owner (0x001b6b38) while preserving state 35. Retail 0x002770a4-0x002770b0 reads that identical scene selector and suppresses animation-direction flag inversion when it equals 35; reuse the entry-state member rather than an unrelated HeroStateId member. domain_14_value_1 -> PAUSE_MENU_STATE_PAGE_TRANSITION: Retail 0x002770d8-0x00277164 configures the 14 page mobys' forward/reverse animations. 0x0027716c-0x00277184 assigns state 1, sets a 12-frame delay, saves the outgoing owner at scene+0xd0 and clears current owner. The matching state-1 branch at 0x00276f38-0x00276f70 completes the delayed pending-page installation. domain_7_value_14 -> PAUSE_MENU_STATE_LEVEL_TRANSITION_ENTRY: Retail 0x00276ec0-0x00276ec4 compares the pause-menu state selector with 14 and reaches initialize_pause_menu at 0x00276eec. The bounded original initializer retail/decompilation at 0x00276368 confirms state 14 becomes 15 and selects owner 0x001b6088. Authoritative source binds that exact owner as l00_pause_menu_level_transition_on_action_page_owner and already names state 15 PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION; 14 is its entry state. domain_9_value_33 -> PAUSE_MENU_STATE_EXIT_GUARDED_ENTRY: Retail 0x00276ed0-0x00276ed4 tests pause-menu state 33 and calls initialize_pause_menu at 0x00276eec. Bounded original initializer retail/decompilation confirms 33 selects owner 0x001b71f0, sets scene+0x124 to 1 and changes state to 34. Authoritative source names that owner l00_pause_menu_exit_guarded_page_owner and state 34 PAUSE_MENU_STATE_EXIT_GUARDED; its process_active_menu_object_actions gates exit inputs on scene+0x124. Thus 33 is the guarded page's entry state. --- .../shared/ui/menus/initialize_pause_menu.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/ui/menus/initialize_pause_menu.c b/src/overlays/shared/ui/menus/initialize_pause_menu.c index 1c95d656df..b94328ee49 100644 --- a/src/overlays/shared/ui/menus/initialize_pause_menu.c +++ b/src/overlays/shared/ui/menus/initialize_pause_menu.c @@ -488,6 +488,13 @@ void update_pause_menu(void) { enum { SCENE_STATE_DEFAULT = 2 }; + enum { + PAUSE_MENU_STATE_PAGE_TRANSITION = 1, + PAUSE_MENU_STATE_LEVEL_TRANSITION_ENTRY = 0xE, + PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION = 0x14, + PAUSE_MENU_STATE_EXIT_GUARDED_ENTRY = 0x21, + PAUSE_MENU_STATE_PRESERVE_STATE_ENTRY = 0x23 + }; Own *owner; Own *u8p; Mth *active_callback_object; @@ -509,7 +516,7 @@ void update_pause_menu(void) { D_L00_0015F5AC = 1; break; } - if (D_L00_001B9CF0.state == 0x14) { + if (D_L00_001B9CF0.state == PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION) { if (D_L00_001B9CF0.unk14 != 0) { D_L00_001B9CF0.unk14 = D_L00_001B9CF0.unk14 - 1; if (D_L00_001B9CF0.unk14 != 0) { @@ -584,8 +591,8 @@ void update_pause_menu(void) { return; } scene_state = D_L00_001B9CF0.state; - if (scene_state == 0 || scene_state == 0xA || scene_state == 0xE || scene_state == 0x11 || - scene_state == 0x21 || scene_state == 0x2D || scene_state == 0x23) { + if (scene_state == 0 || scene_state == 0xA || scene_state == PAUSE_MENU_STATE_LEVEL_TRANSITION_ENTRY || scene_state == 0x11 || + scene_state == PAUSE_MENU_STATE_EXIT_GUARDED_ENTRY || scene_state == 0x2D || scene_state == PAUSE_MENU_STATE_PRESERVE_STATE_ENTRY) { initialize_pause_menu(); } if ((mode_freeze_flags & 1) && !(level_timer < 8)) { @@ -593,7 +600,7 @@ void update_pause_menu(void) { return; } process_unlock_code_input(); - if (D_L00_001B9CF0.state == 1) { + if (D_L00_001B9CF0.state == PAUSE_MENU_STATE_PAGE_TRANSITION) { D_L00_001B9CF0.unk14 = (D_L00_001B9CF0.unk14 < 1) ? 0 : D_L00_001B9CF0.unk14 - 1; if (D_L00_001B9CF0.unk14 == 0) { u8p = D_L00_001B9CF0.unk8; @@ -626,7 +633,7 @@ void update_pause_menu(void) { D_L00_001B9CF0.owner != &D_L00_001B7DD0 && D_L00_001B9CF0.owner != &D_L00_001B80E0 && D_L00_001B9CF0.owner != &l00_pause_menu_self_transition_animation_guard_page_owner && D_L00_001B9CF0.owner != &D_L00_001B78F0 && D_L00_001B9CF0.owner != &D_L00_001B6820) { - if (D_L00_001B9CF0.state != 0x23) { + if (D_L00_001B9CF0.state != PAUSE_MENU_STATE_PRESERVE_STATE_ENTRY) { flag = flag ^ 1; } } @@ -645,7 +652,7 @@ void update_pause_menu(void) { l00_pause_menu_page_mobys[j]->anim_speed = 1.0f; } } - D_L00_001B9CF0.state = 1; + D_L00_001B9CF0.state = PAUSE_MENU_STATE_PAGE_TRANSITION; D_L00_001B9CF0.unk14 = 12; D_L00_001B9CF0.unkD0 = D_L00_001B9CF0.owner; D_L00_001B9CF0.owner = 0; From b2e030d6510ced08a01427170bee325651383075 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:13:59 +0000 Subject: [PATCH 0258/1502] decomp: clarify names in horny_toad_update domain_0_value_3 -> HORNY_TOAD_WAIT_TO_FOLLOW_PATH: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d47ec-002d4818 copies first path point to this Moby and writes 3 to s1+0x20; case 3 at 002d49b8-002d49d4 waits then enters FOLLOW_PATH. domain_10_value_6 -> HORNY_TOAD_APPROACH_AND_FACE_TARGET: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4a68-002d4a80 writes 6 to Moby+0x20 after the path movement branch; case 6 at 002d4b88-002d4be8 moves toward pvars+0x180 and checks heading to target +0x1c0. domain_11_value_6 -> HORNY_TOAD_APPROACH_AND_FACE_TARGET: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4b1c-002d4b60 leaves roaming when +0x1c4 differs from 2 and writes 6 to Moby+0x20; case 6 at 002d4b88-002d4be8 approaches the selected point and checks target heading. domain_12_value_7 -> HORNY_TOAD_PLAY_TARGET_ANIMATION: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4b88-002d4c04 checks selected-point distance and target heading then writes 7 to Moby+0x20 and selects animation 5; case 7 at 002d4c74-002d4d84 processes its animation window and completion. domain_13_value_8 -> HORNY_TOAD_RETURN_HOME: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4c38-002d4c58 writes 8 to this Moby+0x20 when +0x1c4 equals 2 during approach; case 8 at 002d4da0-002d4dc8 moves toward saved home +0x1d0. domain_14_value_8 -> HORNY_TOAD_RETURN_HOME: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4cc4-002d4cf0 tests animation completion and +0x1c4 then writes 8 to this Moby+0x20; case 8 at 002d4da0-002d4dc8 moves toward the saved home vector. domain_15_value_6 -> HORNY_TOAD_APPROACH_AND_FACE_TARGET: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4d0c-002d4d84 checks target distance above 1.5 or heading error above 0.17453292 and writes 6 to this Moby+0x20; existing case 6 repeats selected-point approach and target-facing checks. domain_16_value_5 -> HORNY_TOAD_ROAM: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4da0-002d4dcc moves toward home and on distance below 1.5 branches to 002d4fe8-002d4ff4 with value 5 for Moby+0x20; existing case 5 invokes wander movement around +0x240. domain_17_value_6 -> HORNY_TOAD_APPROACH_AND_FACE_TARGET: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4dd0-002d4dec tests +0x1c4 while returning home and writes 6 to this Moby+0x20; case 6 at 002d4b88-002d4be8 approaches +0x180 and checks heading to target. domain_18_value_6 -> HORNY_TOAD_APPROACH_AND_FACE_TARGET: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4f54-002d4f78 tests animation flag 2 and +0x1c4 then writes 6 to this Moby+0x20; case 6 at 002d4b88-002d4be8 performs selected-point movement and target heading checks. domain_19_value_8 -> HORNY_TOAD_RETURN_HOME: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4f94-002d4fb0 checks expiration of pvars+0x276 and writes 8 to this Moby+0x20; case 8 at 002d4da0-002d4dc8 moves toward home +0x1d0. domain_1_value_1 -> HORNY_TOAD_FACE_FOLLOW_MOBY: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d481c-002d483c validates follow_moby and writes 1 to s1+0x20; case 1 at 002d4884-002d4900 resolves that moby and approaches its XY heading. domain_20_value_5 -> HORNY_TOAD_ROAM: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4fcc-002d4ff4 advances pvars+0x70 with step_moby_motion, tests mask 0x140 and writes 5 to this Moby+0x20; existing case 5 at 002d4a9c-002d4b18 selects roaming animation and wander movement. domain_21_value_11 -> HORNY_TOAD_RECOVER_FROM_REACTION: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d5070-002d507c reads this Moby+0x20 and excludes range 11..12 from ordinary ground settling; same selector case 11 at 002d4fcc-002d5010 advances reaction +0x70 and returns to ROAM on mask 0x140. domain_22_value_12 -> HORNY_TOAD_DYING: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d5070-002d507c reads this Moby+0x20 and excludes 11..12 from ground settling; same selector case 12 at 002d501c-002d5064 advances reaction then plays final sound/effect and removes the Moby. domain_23_value_9 -> HORNY_TOAD_RUN_MOVEMENT_SEQUENCE: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d5084-002d5088 compares the same Moby+0x20 state against 9 to bypass ground settling; case 9 at 002d4864-002d4880 runs helper 002dc9f0 on pvars+0x70 and returns to ROAM on completion. domain_24_value_4 -> HORNY_TOAD_FOLLOW_PATH: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d50c4-002d50cc reads this Moby+0x20 and excludes state 4 from point/path clearance; same selector case 4 at 002d49f0-002d4a64 moves through indexed path points and advances path_point. domain_2_value_5 -> HORNY_TOAD_ROAM: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d47c8-002d47cc branches on negative path to 002d4858-002d4860, writing 5 to this Moby+0x20; case 5 calls wander movement at 002d4b14 with saved initial position +0x240. domain_3_value_5 -> HORNY_TOAD_ROAM: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4864-002d4878 calls movement-sequence helper with pvars+0x70 and writes 5 to this Moby+0x20 on completion; case 5 at 002d4a9c-002d4b18 varies animation and wanders. domain_6_value_8 -> HORNY_TOAD_RETURN_HOME: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4898-002d48ac rejects the followed moby and 002d4910-002d4920 writes 8 to s1+0x20; case 8 at 002d4da0-002d4dc8 moves toward saved home pvars+0x1d0. domain_7_value_1 -> HORNY_TOAD_FACE_FOLLOW_MOBY: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d493c-002d4980 moves to indexed path point and checks distance below 1; 002d498c-002d499c writes 1 to this Moby+0x20, selecting the same field dispatched to follow-moby facing case 1. domain_8_value_4 -> HORNY_TOAD_FOLLOW_PATH: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d49b8-002d49d4 exits the wait when pvars+0x1c4 differs from 2 and writes 4 to Moby+0x20; case 4 at 002d49f0-002d4a64 traverses path points and increments +0x274. domain_9_value_5 -> HORNY_TOAD_ROAM: SHA-bound horny_toad.c and original prepared retail Ghidra agree: retail dispatch 002d469c reads s1+0x20, the same moby->state field used by the existing local HORNY_TOAD enum. 002d4a44-002d4a54 detects final path point and branches to 002d4fe4-002d4ff4 to write 5 to Moby+0x20; existing case 5 wanders about saved initial position at 002d4b04-002d4b18. --- src/overlays/shared/enemies/horny_toad.c | 42 ++++++++++++------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/overlays/shared/enemies/horny_toad.c b/src/overlays/shared/enemies/horny_toad.c index b368164099..888cb51d2d 100644 --- a/src/overlays/shared/enemies/horny_toad.c +++ b/src/overlays/shared/enemies/horny_toad.c @@ -233,10 +233,10 @@ void horny_toad_update(Moby *moby) { ToadPath *path = toad_paths[horny_toad_vars->path]; qcopy(horny_toad_vars->home, path->pts[path->count - 1]); qcopy((*(ToadVec *)&moby->pos), path->pts[0]); - moby->state = 3; + moby->state = HORNY_TOAD_WAIT_TO_FOLLOW_PATH; } else if (horny_toad_vars->follow_moby >= 0) { qcopy(horny_toad_vars->home, (*(ToadVec *)&moby->pos)); - moby->state = 1; + moby->state = HORNY_TOAD_FACE_FOLLOW_MOBY; if (moby->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(10)); } else { @@ -244,13 +244,13 @@ void horny_toad_update(Moby *moby) { return; } } else { - moby->state = 5; + moby->state = HORNY_TOAD_ROAM; } break; } case HORNY_TOAD_RUN_MOVEMENT_SEQUENCE: if (FUN_L00_002dc9f0_2d4610(moby, horny_toad_vars->unk70) != 0) { - moby->state = 5; + moby->state = HORNY_TOAD_ROAM; horny_toad_vars->unk138 = 0; } break; @@ -266,7 +266,7 @@ void horny_toad_update(Moby *moby) { frame_time_sq * 12.566371f, frame_time * 12.566371f); } else { - moby->state = 8; + moby->state = HORNY_TOAD_RETURN_HOME; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); } @@ -277,14 +277,14 @@ void horny_toad_update(Moby *moby) { (unsigned char *)moby, toad_paths[horny_toad_vars->path]->pts[horny_toad_vars->path_point], 0.5f) < 1.0f) { - moby->state = 1; + moby->state = HORNY_TOAD_FACE_FOLLOW_MOBY; if (moby->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(10)); } break; case HORNY_TOAD_WAIT_TO_FOLLOW_PATH: if (horny_toad_vars->unk1C4 != 2) { - moby->state = 4; + moby->state = HORNY_TOAD_FOLLOW_PATH; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); } @@ -296,12 +296,12 @@ void horny_toad_update(Moby *moby) { if (horny_toad_vars->path_point < path->count - 1) { horny_toad_vars->path_point++; } else { - moby->state = 5; + moby->state = HORNY_TOAD_ROAM; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } } else if (horny_toad_vars->unk1C4 != 2) { - moby->state = 6; + moby->state = HORNY_TOAD_APPROACH_AND_FACE_TARGET; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); } @@ -317,7 +317,7 @@ void horny_toad_update(Moby *moby) { update_object_wander_movement((char *)moby, (char *)horny_toad_vars->unk240, 0.5f, 0.5f); if (horny_toad_vars->unk1C4 != 2) { horny_toad_vars->unk1FC = random_float_between(-20.0f, 20.0f) * 0.017453292f; - moby->state = 6; + moby->state = HORNY_TOAD_APPROACH_AND_FACE_TARGET; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); } @@ -330,14 +330,14 @@ void horny_toad_update(Moby *moby) { fast_arc_tan((*(ToadVec *)&target->pos)[0] - (*(ToadVec *)&moby->pos)[0], (*(ToadVec *)&target->pos)[1] - (*(ToadVec *)&moby->pos)[1])) < 0.17453292f) { - moby->state = 7; + moby->state = HORNY_TOAD_PLAY_TARGET_ANIMATION; if (moby->prev_seq != 5) blend_moby_animation(moby, 5, (int)horny_toad_target_animation_start_index_gp, scale_game_frames(10)); } else if (horny_toad_vars->unk1C4 == 2) { - moby->state = 8; + moby->state = HORNY_TOAD_RETURN_HOME; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); } @@ -347,7 +347,7 @@ void horny_toad_update(Moby *moby) { collect_mobies_in_sphere_at_moby_point(moby, 0.333f, 1.0f, 1.0f, 0, 1, 0, 1, 0); } else if (moby->anim_flags & 2) { if (horny_toad_vars->unk1C4 == 2) { - moby->state = 8; + moby->state = HORNY_TOAD_RETURN_HOME; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); } else if (vector_distance_xy((*(ToadVec *)&moby->pos), (*(ToadVec *)&target->pos)) > @@ -357,7 +357,7 @@ void horny_toad_update(Moby *moby) { fast_arc_tan((*(ToadVec *)&target->pos)[0] - (*(ToadVec *)&moby->pos)[0], (*(ToadVec *)&target->pos)[1] - (*(ToadVec *)&moby->pos)[1])) > 0.17453292f) { - moby->state = 6; + moby->state = HORNY_TOAD_APPROACH_AND_FACE_TARGET; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); } @@ -366,11 +366,11 @@ void horny_toad_update(Moby *moby) { case HORNY_TOAD_RETURN_HOME: if (move_horny_toad_toward_position((unsigned char *)moby, horny_toad_vars->home, 0.5f) < 1.5f) { - moby->state = 5; + moby->state = HORNY_TOAD_ROAM; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } else if (horny_toad_vars->unk1C4 != 2) { - moby->state = 6; + moby->state = HORNY_TOAD_APPROACH_AND_FACE_TARGET; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); } @@ -409,11 +409,11 @@ void horny_toad_update(Moby *moby) { } if (moby->anim_flags & 2) { if (horny_toad_vars->unk1C4 != 2) { - moby->state = 6; + moby->state = HORNY_TOAD_APPROACH_AND_FACE_TARGET; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); } else if (horny_toad_vars->unk276 == 0) { - moby->state = 8; + moby->state = HORNY_TOAD_RETURN_HOME; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(20)); } @@ -422,7 +422,7 @@ void horny_toad_update(Moby *moby) { } case HORNY_TOAD_RECOVER_FROM_REACTION: if (step_moby_motion(moby, horny_toad_vars->unk70) & 0x140) { - moby->state = 5; + moby->state = HORNY_TOAD_ROAM; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -436,11 +436,11 @@ void horny_toad_update(Moby *moby) { } break; } - if (moby->state != 11 && moby->state != 12 && moby->state != 9) { + if (moby->state != HORNY_TOAD_RECOVER_FROM_REACTION && moby->state != HORNY_TOAD_DYING && moby->state != HORNY_TOAD_RUN_MOVEMENT_SEQUENCE) { approach_value(probe_ground_height((*(ToadVec *)&moby->pos), 0, 0.5f), frame_time * 7.0f, &(*(ToadVec *)&moby->pos)[2]); - if (moby->state != 4) { + if (moby->state != HORNY_TOAD_FOLLOW_PATH) { resolve_point_path_segment_xy_clearance( horny_toad_vars->unk1E0, 0.25f, (*(ToadVec *)&moby->pos), (*(ToadVec *)&moby->pos)); } From 90aa63b41b4f74f05117567efdff83acc7866689 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:13:59 +0000 Subject: [PATCH 0259/1502] decomp: clarify names in red_button_update domain_0_value_7 -> IDLE_AFTER_CAMERA_SEQUENCE: The exact selector is the red-button moby's state byte: 003040bc loads moby+0x20, and 003040c0-003040c4 returns directly via 00304790 for any state >=7. In HOLD_OFFSET_CAMERA_UNTIL_PROGRESS_COMPLETE, 00304724-00304740 tests pvars+0x2c >=2.0 and writes 7 to that same state byte. The completion path 00304744-0030478c sets timer2, restores the cut2 position/rotation through set_race_camera, calls jet_end_mount(3), and activates the linked moby. Thus subsequent updates idle after this camera sequence. This local behavior does not require inferring an external lifecycle or borrowing another enum domain. --- src/overlays/l06/mobys/red_button.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l06/mobys/red_button.c b/src/overlays/l06/mobys/red_button.c index 1ffd699435..8dfa11ccdd 100644 --- a/src/overlays/l06/mobys/red_button.c +++ b/src/overlays/l06/mobys/red_button.c @@ -98,6 +98,9 @@ void red_button_update(struct Moby *moby) { RAISE_CAMERA_AND_TRIGGER_LISTED_EFFECTS = 5, HOLD_OFFSET_CAMERA_UNTIL_PROGRESS_COMPLETE = 6 }; + enum { + IDLE_AFTER_CAMERA_SEQUENCE = 7 + }; Data_304098 *red_button_vars = *(struct Data_304098 **)&moby->pvars; Vector_304098 camera_position; Vector_304098 camera_rotation; @@ -246,7 +249,7 @@ void red_button_update(struct Moby *moby) { set_camera_position(&camera_rotation); set_camera_rotation(&camera_position); if (2.0f <= red_button_vars->t) { - moby->state = 7; + moby->state = IDLE_AFTER_CAMERA_SEQUENCE; red_button_vars->timer2 = scale_game_frames(0xE10); set_race_camera(&l06_cuboids[red_button_vars->cut2].pos, &l06_cuboids[red_button_vars->cut2].rot, From 00eccf99c0f2983e9bf089b50d8b72066ea91e70 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:16:21 +0000 Subject: [PATCH 0260/1502] decomp: clarify names in update_airship_part domain_0_value_1 -> AIRSHIP_PART_STATE_WAIT_FOR_BREAKUP_COMMAND: Retail 002c28b4-002c28bc stores 1 into the same Moby+0x20 byte dispatched at 002c270c-002c272c. Source initialization computes the joint offset then reaches the existing WAIT_FOR_BREAKUP_COMMAND case; that case follows parent command and waits for command 1 before initializing the breakup gate. domain_1_value_2 -> AIRSHIP_PART_STATE_WAIT_FOR_BREAKUP_GATE: Retail 002c29e4-002c29ec loads Moby+0x20 and compares it to 2, the same field used by the source switch and its existing WAIT_FOR_BREAKUP_GATE member. This branch updates hull rotation and tests the pvars+0x2A timer helper before entering established BEGIN_BREAKUP state 3. domain_2_value_3 -> AIRSHIP_PART_STATE_BEGIN_BREAKUP: Retail 002c2a2c-002c2a40 tests the pvars+0x2A helper and stores 3 into Moby+0x20 on completion. The identical byte selects the source's existing BEGIN_BREAKUP case, whose retail body at 002c2ab0-002c2d08 initializes detached velocity, tumble and acceleration and disables collision. domain_3_value_2 -> AIRSHIP_PART_STATE_WAIT_FOR_BREAKUP_GATE: Retail 002c2a44-002c2aac handles command 1, initializes pvars+0x2A with a converted random delay, propagates update distance, and stores 2 into Moby+0x20. This is the switch selector byte and the existing WAIT_FOR_BREAKUP_GATE case then tests that timer before entering breakup. domain_4_value_4 -> AIRSHIP_PART_STATE_FALLING_WITH_EFFECTS: Retail 002c2cfc-002c2d08 stores 4 into Moby+0x20 after breakup motion initialization and collision clearing. This same selector dispatches to 002c2d0c, which integrates falling position and tumble and emits particles and low-altitude sparks, matching the existing FALLING_WITH_EFFECTS enum member. domain_5_value_5 -> AIRSHIP_PART_STATE_FALLING_AFTER_DAMPING: Retail 002c30d8-002c312c scales velocity by 0.45 and angular increments by 0.9, then stores 5 into the Moby+0x20 switch selector. Retail 002c3130-002c3218 continues falling and bounds removal, matching the existing FALLING_AFTER_DAMPING member in this function's local enum. --- src/overlays/l09/mobys/airship_part.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l09/mobys/airship_part.c b/src/overlays/l09/mobys/airship_part.c index 0c8e6ed071..156a046d94 100644 --- a/src/overlays/l09/mobys/airship_part.c +++ b/src/overlays/l09/mobys/airship_part.c @@ -234,7 +234,7 @@ void airship_part_update(struct Moby *moby) { joint_offset_scale = moby->scale * 0.0009765625f; get_moby_joint_matrices(moby, 1, &joint, transform_and_effect_scratch.m); fast_vec_scale(part_vars->off, transform_and_effect_scratch.m[3], joint_offset_scale); - moby->state = 1; + moby->state = AIRSHIP_PART_STATE_WAIT_FOR_BREAKUP_COMMAND; break; } case AIRSHIP_PART_STATE_WAIT_FOR_BREAKUP_COMMAND: @@ -267,7 +267,7 @@ void airship_part_update(struct Moby *moby) { moby->flags |= part_vars->parent->flags & 1; moby->command = part_vars->parent->command; } - if (moby->state == 2) { + if (moby->state == AIRSHIP_PART_STATE_WAIT_FOR_BREAKUP_GATE) { if (moby->oclass == 0x4A0) { moby->rot.x = fast_add_rotations(moby->rot.x, @@ -275,7 +275,7 @@ void airship_part_update(struct Moby *moby) { 0.017453292f * frame_time); } if (fast_dec_timer_s16(&part_vars->h2A) != 0) { - moby->state = 3; + moby->state = AIRSHIP_PART_STATE_BEGIN_BREAKUP; } } else if (moby->command == 1) { int i; @@ -288,7 +288,7 @@ void airship_part_update(struct Moby *moby) { part_vars->parts[i]->update_dist = 0xFF; } } - moby->state = 2; + moby->state = AIRSHIP_PART_STATE_WAIT_FOR_BREAKUP_GATE; } break; } @@ -338,7 +338,7 @@ void airship_part_update(struct Moby *moby) { airship_part_downward_acceleration_override_range_end_gp * frame_time_sq_macro); } moby->collision = 0; - moby->state = 4; + moby->state = AIRSHIP_PART_STATE_FALLING_WITH_EFFECTS; break; } case AIRSHIP_PART_STATE_FALLING_WITH_EFFECTS: @@ -401,7 +401,7 @@ void airship_part_update(struct Moby *moby) { part_vars->f20 *= 0.9f; part_vars->f24 *= 0.9f; allocate_voice_for_target_entry(0, 0, (int)moby); - moby->state = 5; + moby->state = AIRSHIP_PART_STATE_FALLING_AFTER_DAMPING; } break; case AIRSHIP_PART_STATE_FALLING_AFTER_DAMPING: From 97c7aff9f29d8af5cc3c68f846bbe27934983632 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:18:29 +0000 Subject: [PATCH 0261/1502] decomp: clarify names in nanotech_ball_update domain_0_value_1 -> NANOTECH_BALL_STATE_FOLLOW_OWNER: At 0x002d8a60-0x002d8a64 retail writes 1 to the same moby+0x20 byte dispatched at 0x002d8a30. Initialization falls through to owner-position copies at 0x002d8d9c-0x002d8dd8, matching the existing local FOLLOW_OWNER case. domain_10_value_1 -> HERO_VEHICLE_MODE_CLANK: Source player=&hero compares player->vehicle_mode while clamping collected health. Retail 0x002d9514-0x002d9548 reads hero+0x20a4 (0x001413f4), tests 1 and selects cap 4 before hp increment/clamp. The exact same vehicle field uses canonical HeroVehicleMode member HERO_VEHICLE_MODE_CLANK, separate from nanotech state IDs. domain_2_value_2 -> NANOTECH_BALL_STATE_DETACHED_PICKUP: At 0x002d8ddc-0x002d8df4 a negative owner state or self ownership writes 2 to moby+0x20, the switch selector. Existing local DETACHED_PICKUP case updates its own position and grounding at 0x002d8e14-0x002d8e48. domain_3_value_2 -> NANOTECH_BALL_STATE_DETACHED_PICKUP: At 0x002d8e00-0x002d8e0c retail compares moby+0x20 with 2 to gate own-position grounding and slot scale animation. It is the identical selector and value of the existing NANOTECH_BALL_STATE_DETACHED_PICKUP case. domain_4_value_1 -> HERO_VEHICLE_MODE_CLANK: Source player is &hero and selector is player->vehicle_mode. Retail 0x002d8ea0 forms hero base 0x0013f350, then 0x002d8eac-0x002d8ec4 reads byte +0x20a4 (0x001413f4) and compares with 1 to select health cap 4. This is the HeroVehicleMode field, whose canonical member is HERO_VEHICLE_MODE_CLANK=1, not the moby state domain. domain_5_value_1 -> NANOTECH_BALL_STATE_FOLLOW_OWNER: At 0x002d8eb4-0x002d8ec0 retail reads the dispatched moby+0x20 byte and excludes 1 from pickup entry. Existing FOLLOW_OWNER case copies the owner's position; this check prevents collecting while still attached to that owner. domain_6_value_3 -> NANOTECH_BALL_STATE_COLLECTING: At 0x002d8f24-0x002d8f5c proximity and clear-line tests gate writing 3 to moby+0x20, followed by collection timer and per-slot curve setup. The same selector's existing COLLECTING case interpolates slots and awards health at 0x002d950c-0x002d9584. domain_7_value_2 -> NANOTECH_BALL_STATE_DETACHED_PICKUP: At 0x002d9278-0x002d9290 retail compares moby+0x20 with 2 and chooses either this moby or its owner for particle ownership. This is the same nanotech switch selector as the existing DETACHED_PICKUP case, not a particle-mode selector. domain_8_value_1 -> HERO_VEHICLE_MODE_CLANK: Source player=&hero compares player->vehicle_mode. Retail 0x002d93bc-0x002d93dc reads hero base 0x0013f350 +0x20a4 (0x001413f4), compares with 1 and selects maximum health 4 for the full-health timer check. It is the HeroVehicleMode selector with canonical HERO_VEHICLE_MODE_CLANK=1. domain_9_value_4 -> NANOTECH_BALL_STATE_BASIS_ONLY: At 0x002d944c-0x002d9494 collection expiry clears slots and writes 4 to the dispatched moby+0x20 byte for the retained leader. Existing BASIS_ONLY case at 0x002d97bc-0x002d97d0 only refreshes the shared slot offsets when this moby is leader. --- src/overlays/shared/pickups/nanotech_ball.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/shared/pickups/nanotech_ball.c b/src/overlays/shared/pickups/nanotech_ball.c index e6c0799890..193ff994c0 100644 --- a/src/overlays/shared/pickups/nanotech_ball.c +++ b/src/overlays/shared/pickups/nanotech_ball.c @@ -1262,7 +1262,7 @@ void nanotech_ball_update(Moby *moby) { case NANOTECH_BALL_STATE_INITIALIZE: { Moby *owner; int i; - moby->state = 1; + moby->state = NANOTECH_BALL_STATE_FOLLOW_OWNER; moby->flags |= 0x41; moby->collision = 0; moby->command = 0; @@ -1325,12 +1325,12 @@ void nanotech_ball_update(Moby *moby) { qcopy(&nanotech_ball_state->pos, &owner->pos); nanotech_ball_state->pos.z += 0.5f; if ((signed char)owner->state < 0 || owner == moby) { - moby->state = 2; + moby->state = NANOTECH_BALL_STATE_DETACHED_PICKUP; nanotech_ball_state->f50 = 0; } } case NANOTECH_BALL_STATE_DETACHED_PICKUP: - if (moby->state == 2) { + if (moby->state == NANOTECH_BALL_STATE_DETACHED_PICKUP) { int i; qcopy(&nanotech_ball_state->pos, &moby->pos); nanotech_ball_state->pos.z += 0.5f; @@ -1348,9 +1348,9 @@ void nanotech_ball_update(Moby *moby) { { Hero *player = &hero; int max_hp = hero_max_health; - if (player->vehicle_mode == 1) + if (player->vehicle_mode == HERO_VEHICLE_MODE_CLANK) max_hp = 4; - if (moby->state != 1 && D_L00_0015F63C != 0 && + if (moby->state != NANOTECH_BALL_STATE_FOLLOW_OWNER && D_L00_0015F63C != 0 && ((D_2D9EA0 *)D_L00_0015F63C->pvars) != 0 && player->health.hp != 0 && (player->health.hp + ((D_2D9EA0 *)D_L00_0015F63C->pvars)->f7C < max_hp || (nanotech_ball_invulnerability_pickup_enabled != 0 && @@ -1358,7 +1358,7 @@ void nanotech_ball_update(Moby *moby) { fast_vec_dist(&moby->pos, &player->motion.pos) < 10.0f && func_L00_002D9E30_2D9EA0(moby)) { int i; - moby->state = 3; + moby->state = NANOTECH_BALL_STATE_COLLECTING; ((D_2D9EA0 *)D_L00_0015F63C->pvars)->f7C++; if (nanotech_ball_invulnerability_pickup_enabled != 0) player->invulnerable_frames = func_001F9850_2D9EA0(0x258); @@ -1448,7 +1448,7 @@ void nanotech_ball_update(Moby *moby) { ext->b.x = part->pos.x - moby->pos.x; ext->b.y = part->pos.y - moby->pos.y; ext->b.z = part->pos.z - moby->pos.z; - if (moby->state == 2) + if (moby->state == NANOTECH_BALL_STATE_DETACHED_PICKUP) ext->u.s.owner = moby; else ext->u.s.owner = nanotech_ball_state->owner; @@ -1487,7 +1487,7 @@ void nanotech_ball_update(Moby *moby) { { Hero *player = &hero; int max_hp = hero_max_health; - if (player->vehicle_mode == 1) + if (player->vehicle_mode == HERO_VEHICLE_MODE_CLANK) max_hp = 4; if (player->health.hp == max_hp && player->invulnerable_frames != 0 && nanotech_ball_invulnerability_pickup_enabled != 0) { @@ -1510,7 +1510,7 @@ void nanotech_ball_update(Moby *moby) { } } if (D_L00_0015F63C == moby) - moby->state = 4; + moby->state = NANOTECH_BALL_STATE_BASIS_ONLY; else mark_moby_for_removal(moby); } else { @@ -1528,7 +1528,7 @@ void nanotech_ball_update(Moby *moby) { if (nanotech_ball_state->h56 == 0) { Hero *player = &hero; int max_hp = hero_max_health; - if (player->vehicle_mode == 1) + if (player->vehicle_mode == HERO_VEHICLE_MODE_CLANK) max_hp = 4; if (player->health.hp != 0) { int new_hp = player->health.hp + 1; From 00ebc664aab67b6d43bdc8afea8d0d14aa4bac1f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:20:26 +0000 Subject: [PATCH 0262/1502] decomp: clarify names in hoven_turret_update domain_0_value_6 -> HOVEN_TURRET_STATE_INACTIVE: Retail 00303550 retains the moby in s3; 00303590 reads its state byte at +0x20 for dispatch. After the unavailable mission-entry test, 003035f0/003035f8 stores 6 to that same byte. The source's same-selector case HOVEN_TURRET_STATE_INACTIVE=6 only maintains animation 0 at 003041c0-003041d4, proving reuse of the existing turret constant. domain_1_value_3 -> HOVEN_TURRET_STATE_WAIT_FOR_BOARDING: Retail 00303600 attaches the manipulator, then 00303608/00303610 stores 3 to s3+0x20, the same moby state byte read for dispatch at 00303590. Its existing HOVEN_TURRET_STATE_WAIT_FOR_BOARDING case performs proximity and grounded-frame checks before jet_mount at 00303818; reuse that established local enum member. domain_2_value_4 -> HOVEN_TURRET_STATE_MANNED: Retail 00303818 mounts the hero, 00303840 sets the hero state and 00303848 updates the turret camera; 0030385c/00303880 then stores 4 to s3+0x20. This is the exact byte dispatched at 00303590 and named HOVEN_TURRET_STATE_MANNED=4 by the source switch, whose branch handles aiming, firing and damage. domain_3_value_7 -> HOVEN_TURRET_STATE_DESTRUCTION_EFFECTS: Retail 00303994 tests turret health at s2+0x8c against zero, initializes the destruction timer at 003039b0, then 003039b4/003039bc stores 7 to the dispatched moby state byte s3+0x20. The existing HOVEN_TURRET_STATE_DESTRUCTION_EFFECTS=7 branch registers the fade at 00304018 and emits timed explosions at 00304130. domain_4_value_5 -> HOVEN_TURRET_STATE_START_SCENE: Retail 00303a40-00303ab4 clears mission persistence, queues the movie/unlock and sets the camera; 00303abc/00303ac4 stores 5 to s3+0x20, the switch state byte. The source already names its case HOVEN_TURRET_STATE_START_SCENE=5; that branch calls start_scene(1) at 00304184 before advancing, so reuse the same local state constant. domain_5_value_8 -> HOVEN_TURRET_STATE_SAVE_DATA: Retail 00304184 calls the source's established start_scene(1), then 0030418c/00304194 stores 8 to s3+0x20, the same state byte dispatched at 00303590. The existing source case HOVEN_TURRET_STATE_SAVE_DATA=8 calls the memcard-save binding with (0,-1) at 003041ac and advances to inactive, proving this assignment's domain and canonical member. domain_6_value_6 -> HOVEN_TURRET_STATE_INACTIVE: Retail 003041ac requests the source's save-data operation with (0,-1), then 003041b4/003041bc stores 6 to s3+0x20. That exact state byte is the selector at 00303590, and the source already defines HOVEN_TURRET_STATE_INACTIVE=6 for its animation-0 maintenance branch at 003041c0-003041d4. Reuse the existing turret enum, not equal-valued hero states. --- src/overlays/l12/mobys/hoven_turret.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l12/mobys/hoven_turret.c b/src/overlays/l12/mobys/hoven_turret.c index 3c23e09fdc..55f3ffae8a 100644 --- a/src/overlays/l12/mobys/hoven_turret.c +++ b/src/overlays/l12/mobys/hoven_turret.c @@ -222,10 +222,10 @@ void hoven_turret_update(struct Moby *moby) { D_L12_00161F00 = 0; D_L12_00161F04 = 0; if (visited52[moby->mission + (current_level_index << 4)] == 0xFF) { - moby->state = 6; + moby->state = HOVEN_TURRET_STATE_INACTIVE; } else { attach_manipulator(moby, 0, hoven_turret_state); - moby->state = 3; + moby->state = HOVEN_TURRET_STATE_WAIT_FOR_BOARDING; hoven_turret_state->f84 = 0xC8; moby->rot.y = 0.0f; hoven_turret_state->f70 = scale_game_frames(0x1E); @@ -284,7 +284,7 @@ void hoven_turret_update(struct Moby *moby) { hoven_turret_state->f8C = 200.0f; moby->hit_slot = 0xFF; D_L12_00161F20++; - moby->state = 4; + moby->state = HOVEN_TURRET_STATE_MANNED; } } break; @@ -317,7 +317,7 @@ void hoven_turret_update(struct Moby *moby) { if (hoven_turret_state->f8C <= 0.0f) { D_L12_00161F04 = 1; hoven_turret_state->fAC = scale_game_frames(0x78); - moby->state = 7; + moby->state = HOVEN_TURRET_STATE_DESTRUCTION_EFFECTS; break; } } @@ -352,7 +352,7 @@ void hoven_turret_update(struct Moby *moby) { D_L12_00161F00 = 0; set_race_camera(cpos, crot, 0, 1); } - moby->state = 5; + moby->state = HOVEN_TURRET_STATE_START_SCENE; break; } } @@ -527,13 +527,13 @@ void hoven_turret_update(struct Moby *moby) { case HOVEN_TURRET_STATE_START_SCENE: if (D_L12_0015F5C4_macro != 2) { start_scene(1); - moby->state = 8; + moby->state = HOVEN_TURRET_STATE_SAVE_DATA; } break; case HOVEN_TURRET_STATE_SAVE_DATA: if (D_L12_0015F5C4_macro != 2) { func_0020BFC8_304920(0, -1); - moby->state = 6; + moby->state = HOVEN_TURRET_STATE_INACTIVE; } break; case HOVEN_TURRET_STATE_INACTIVE: From 4170cd426fc1a0dbb03413b40e5228ea376a27ad Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:20:26 +0000 Subject: [PATCH 0263/1502] decomp: clarify names in scoutbot_update domain_0_value_1 -> SCOUTBOT_STATE_IDLE: Retail 002d2ccc stores s4=1 into moby+0x20 after initialization and animation 0; the same byte is dispatched at 002d2b9c/002d2bb8 to the existing SCOUTBOT_STATE_IDLE case, proving the local scoutbot state domain. domain_11_value_4 -> SCOUTBOT_STATE_ATTACK: Retail 002d363c reloads moby+0x20, the same state byte used by dispatch 002d2b9c. Comparison 002d3658-002d365c selects the attack glow color for value 4, matching the existing SCOUTBOT_STATE_ATTACK member and its charge/firing body. domain_12_value_6 -> SCOUTBOT_STATE_WAIT_FOR_VOICE: Retail 002d363c reloads moby+0x20 and 002d3664-002d3668 compares it with 6 to share the attack glow color. It is the identical state byte dispatched at 002d2bf4 to existing SCOUTBOT_STATE_WAIT_FOR_VOICE, which polls the saved voice handle. domain_1_value_2 -> SCOUTBOT_STATE_APPROACH_TARGET: Retail idle branch 002d2d5c-002d2d88 restores approach hover values and animation 2, then 002d3548 stores s0=2 into moby+0x20. Dispatch 002d2bd8 sends that byte to 002d2f38, the existing SCOUTBOT_STATE_APPROACH_TARGET case. domain_2_value_7 -> SCOUTBOT_STATE_MOVE_TO_WANDER_GOAL: Retail 002d2ddc-002d2de8 computes home plus a random planar offset into pvars+0x1f0; 002d2e0c-002d2e14 writes 7 to moby+0x20. Dispatch 002d2c08 enters the existing SCOUTBOT_STATE_MOVE_TO_WANDER_GOAL body using that goal. domain_3_value_1 -> SCOUTBOT_STATE_IDLE: Retail 002d2eec-002d2f08 tests arrival within 0.5 of wander_goal; animation 0 is selected at 002d2f24, and 002d2f2c-002d2f34 stores 1 to moby+0x20, the same selector dispatched to existing SCOUTBOT_STATE_IDLE. domain_4_value_6 -> SCOUTBOT_STATE_WAIT_FOR_VOICE: Retail 002d3068 allocates a voice after target proximity checks, 002d3070 saves its handle at pvars+0x214, and 002d3074-002d307c stores 6 to moby+0x20. The existing SCOUTBOT_STATE_WAIT_FOR_VOICE case consumes that handle at 002d3510-002d351c. domain_5_value_3 -> SCOUTBOT_STATE_RETURN_HOME: Retail 002d3084-002d30c8 checks target distance from home limits; on excess the branch restores hover values and reaches 002d34b4-002d34bc, storing 3 in moby+0x20. Existing SCOUTBOT_STATE_RETURN_HOME dispatch at 002d2be0 enters steering toward pvars+0x1c0. domain_6_value_1 -> SCOUTBOT_STATE_IDLE: Retail home-arrival checks 002d31f0-002d323c and animation 0 selection 002d3258 lead to 002d3264 storing s4=1 to moby+0x20. This is the exact same selector and value dispatched at 002d2bb8 to existing SCOUTBOT_STATE_IDLE. domain_7_value_3 -> SCOUTBOT_STATE_RETURN_HOME: Retail attack completion at 002d33ac-002d34bc restores hover parameters, selects movement animation 2, and writes 3 to moby+0x20. Dispatch 002d2be0 routes this same byte to the existing SCOUTBOT_STATE_RETURN_HOME body steering toward home. domain_8_value_4 -> SCOUTBOT_STATE_ATTACK: Retail 002d3514-002d351c waits until the saved voice stops; 002d3530-002d353c selects animation 3 and 002d3548 writes s0=4 into moby+0x20. Dispatch 002d2ba4 routes 4 to existing SCOUTBOT_STATE_ATTACK with charge and firing behavior. --- src/overlays/shared/enemies/scoutbot.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/shared/enemies/scoutbot.c b/src/overlays/shared/enemies/scoutbot.c index 864cff7699..378febab64 100644 --- a/src/overlays/shared/enemies/scoutbot.c +++ b/src/overlays/shared/enemies/scoutbot.c @@ -218,7 +218,7 @@ void scoutbot_update(Moby *moby) { if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 0); } - moby->state = 1; + moby->state = SCOUTBOT_STATE_IDLE; qcopy(scoutbot_instance_vars->home, &moby->pos); if (probe_ground_height(&moby->pos, 0, 0.5f) > moby->pos.z - 10.0f) { scoutbot_instance_vars->home[2] = probe_ground_height(&moby->pos, 0, 0.5f); @@ -237,7 +237,7 @@ void scoutbot_update(Moby *moby) { if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, 6); } - moby->state = 2; + moby->state = SCOUTBOT_STATE_APPROACH_TARGET; } else if (moby->anim_flags & 2) { float heading = random_angle_radians(); float radius = random_float_between(0.0f, 3.0f); @@ -249,7 +249,7 @@ void scoutbot_update(Moby *moby) { if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, 6); } - moby->state = 7; + moby->state = SCOUTBOT_STATE_MOVE_TO_WANDER_GOAL; } break; case SCOUTBOT_STATE_MOVE_TO_WANDER_GOAL: { @@ -265,7 +265,7 @@ void scoutbot_update(Moby *moby) { if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 3); } - moby->state = 1; + moby->state = SCOUTBOT_STATE_IDLE; } break; } @@ -280,7 +280,7 @@ void scoutbot_update(Moby *moby) { if (vector_distance_xy(&moby->pos, &scoutbot_instance_vars->current_target->pos) < 3.0f && absolute_float(scoutbot_instance_vars->current_target->pos.z - moby->pos.z) < 2.0f) { scoutbot_instance_vars->voice = allocate_voice_for_target_entry(0, 0, moby); - moby->state = 6; + moby->state = SCOUTBOT_STATE_WAIT_FOR_VOICE; } else if (vector_distance_xy(target_pos, scoutbot_instance_vars->home) > 15.0f || absolute_float(scoutbot_instance_vars->home[2] - target_pos[2]) > 4.0f) { scoutbot_instance_vars->f200 = 4.0f; @@ -288,7 +288,7 @@ void scoutbot_update(Moby *moby) { if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, 6); } - moby->state = 3; + moby->state = SCOUTBOT_STATE_RETURN_HOME; } break; } @@ -308,7 +308,7 @@ void scoutbot_update(Moby *moby) { if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 3); } - moby->state = 1; + moby->state = SCOUTBOT_STATE_IDLE; } break; } @@ -348,7 +348,7 @@ void scoutbot_update(Moby *moby) { if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, 3); } - moby->state = 3; + moby->state = SCOUTBOT_STATE_RETURN_HOME; } break; } @@ -360,7 +360,7 @@ void scoutbot_update(Moby *moby) { if (moby->prev_seq != 3) { blend_moby_animation(moby, 3, 0, 3); } - moby->state = 4; + moby->state = SCOUTBOT_STATE_ATTACK; } break; } @@ -403,7 +403,7 @@ void scoutbot_update(Moby *moby) { if (moby->state != 5 && (signed char)moby->state >= 0) { int col = 0x7F20FF20; - if (moby->state == 4 || moby->state == 6) { + if (moby->state == SCOUTBOT_STATE_ATTACK || moby->state == SCOUTBOT_STATE_WAIT_FOR_VOICE) { col = 0x7F2828A0; } moby->glow_color = colorlerp_3DF8(moby->glow_color, col, 0.1f); From 54348e05d1119f0a6faf1e6b27fbeec6613236f6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:20:26 +0000 Subject: [PATCH 0264/1502] decomp: clarify names in update_bomber_tank domain_0_value_2 -> BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM: Retail 002d4754-002d4758 reads pvars+0xF4 and skips the distance test/entry into firing state 3 when equal to 2; 002d474c still advances the path. Checked aim-helper 002d5378-002d5380 selects 002d549c for this same mode field, centering yaw/pitch instead of tracking the target. domain_1_value_2 -> BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM: Retail 002d47f0-002d47f4 compares the same pvars+0xF4 mode with 2 and branches to 002d4820-002d4830 to leave firing state 3 for path state 6. Aim-helper 002d5378-002d5380 and 002d549c-002d550c centers yaw/pitch for this mode. This is a control-mode constant, separate from moby->state. domain_2_value_2 -> BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM: The trigger branch restores position, flags and collisions at 002d49ac-002d4ad4, then shared tail 002d4ae4-002d4ae8 tests pvars+0xF4 against 2 and inhibits entry into path state 6 at 002d4afc. This same mode selects centered rather than target-directed aim at helper 002d5380/002d549c. domain_3_value_2 -> BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM: Retail scatter/activation branch 002d4a24-002d4a28 tests pvars+0xF4 against 2 and skips the linked-group scatter at 002d4a30 and following activation work when equal. Checked aim-helper 002d5378-002d5380 uses this identical mode field/value to select centered yaw/pitch. domain_4_value_2 -> BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM: The source's inner scatter-activation mode comparison corresponds to the shared retail tail 002d4ae4-002d4ae8: pvars+0xF4 equal to 2 skips state-6 entry and animation blend at 002d4afc-002d4b18. Outer guard 002d4a24-002d4a28 uses the same mode. Helper 002d5380 selects centered rather than target-directed aim for it. --- src/overlays/l08/mobys/bomber_tank.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/overlays/l08/mobys/bomber_tank.c b/src/overlays/l08/mobys/bomber_tank.c index d1c37ea028..37d07082b3 100644 --- a/src/overlays/l08/mobys/bomber_tank.c +++ b/src/overlays/l08/mobys/bomber_tank.c @@ -138,6 +138,9 @@ void bomber_tank_update(Moby *moby) { BOMBER_TANK_STATE_SCATTER_GROUP_AND_ACTIVATE = 14, BOMBER_TANK_STATE_DAMAGED_FOLLOW_PATH = 99 }; + enum { + BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM = 2 + }; float old_pos[4]; float old_rot[4]; float velocity[4]; @@ -242,7 +245,7 @@ void bomber_tank_update(Moby *moby) { break; case BOMBER_TANK_STATE_FOLLOW_PATH: advance_bomber_tank_along_path(moby, bomber_tank_update_vars->path); - if (bomber_tank_update_vars->mode != 2 && + if (bomber_tank_update_vars->mode != BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM && vector_distance_xy(&moby->pos, &target->pos) < 20.0f) { if (D_00141C38 == 0 && D_0013D4CB == 0) { help_request(0x1F44, 0x5A); @@ -254,7 +257,7 @@ void bomber_tank_update(Moby *moby) { break; case BOMBER_TANK_STATE_FOLLOW_PATH_AND_FIRE: advance_bomber_tank_along_path(moby, bomber_tank_update_vars->path); - if (bomber_tank_update_vars->mode == 2 || + if (bomber_tank_update_vars->mode == BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM || vector_distance_xy(&moby->pos, &target->pos) > 22.0f) { moby->state = BOMBER_TANK_STATE_FOLLOW_PATH; if (moby->prev_seq != 1) @@ -296,7 +299,7 @@ void bomber_tank_update(Moby *moby) { bomber_tank_update_vars->part_b->collision = bomber_tank_update_vars->part_b->pclass->collision; moby->flags |= 0x1000; - if (bomber_tank_update_vars->mode != 2) { + if (bomber_tank_update_vars->mode != BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM) { moby->state = BOMBER_TANK_STATE_FOLLOW_PATH; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); @@ -304,7 +307,7 @@ void bomber_tank_update(Moby *moby) { } break; case BOMBER_TANK_STATE_SCATTER_GROUP_AND_ACTIVATE: - if (bomber_tank_update_vars->mode != 2) { + if (bomber_tank_update_vars->mode != BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM) { unsigned char *event_flags; scatter_bomber_tank_linked_debris((char *)moby); event_flags = (unsigned char *)D_0013D388; @@ -322,7 +325,7 @@ void bomber_tank_update(Moby *moby) { bomber_tank_update_vars->part_b->collision = bomber_tank_update_vars->part_b->pclass->collision; moby->flags |= 0x1000; - if (bomber_tank_update_vars->mode != 2) { + if (bomber_tank_update_vars->mode != BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM) { moby->state = BOMBER_TANK_STATE_FOLLOW_PATH; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); From fe269bfd50421143dfe35afb688cf4da3d655c8a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:20:27 +0000 Subject: [PATCH 0265/1502] decomp: clarify names in blarg_bombthrower_update domain_0_value_3 -> BOMBTHROWER_STATE_WAIT_TO_THROW: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. 0x002dac7c..0x002dac98 compares actor+0x20 with 3 to change flag 0x400. The same state dispatches to target-facing wait behavior at 0x002db2d0..0x002db3e8, already named WAIT_TO_THROW. domain_10_value_5 -> BOMBTHROWER_STATE_THROW_BOMB: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. When throw-position movement completes and target/camera tests permit, 0x002db5b8..0x002db5dc requests animation 3 and stores 5 to actor+0x20. Existing THROW_BOMB case checks frame 19 and spawns a bomb at 0x002db77c. domain_11_value_1 -> BOMBTHROWER_STATE_APPROACH_WAYPOINT: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. After THROW_BOMB animation flag bit 2, 0x002db7e0..0x002db7fc stores state 1 to actor+0x20, requests animation 4 as needed and resets pvars+0x134. It returns to the existing waypoint-approach case. domain_12_value_93 -> BOMBTHROWER_STATE_FALL_RECOVERY: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. WAIT_FOR_FALL_RECOVERY tests actor animation flag bit 2, requests animation 7 and writes 93 at 0x002db854..0x002db85c. That enters the already named FALL_RECOVERY case sharing step_moby_motion at 0x002db860. domain_13_value_1 -> BOMBTHROWER_STATE_APPROACH_WAYPOINT: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. After motion result bit 0x40, 0x002db878..0x002db8a0 selects/reserves a waypoint, requests animation 4, then 0x002db8c4..0x002db8d4 writes state 1 and resets the approach timer. This resumes existing APPROACH_WAYPOINT. domain_14_value_100 -> BOMBTHROWER_STATE_FADE_OUT: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. In DYING, motion result bit 0x40 gates 0x002db914..0x002db938, which writes 100 to actor+0x20, stops animation, clears collision and initializes alpha interpolation operands. The early state-100 branch at 0x002dacac..0x002dacfc interpolates alpha toward zero. domain_1_value_100 -> BOMBTHROWER_STATE_FADE_OUT: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. 0x002dac9c..0x002daca4 compares actor+0x20 with 100. On equality 0x002dacac..0x002dacfc computes start_alpha + (-start_alpha)*fraction and stores actor alpha at +0x23, then emits puffs and returns. This proves the descriptive fade-out state. domain_2_value_99 -> BOMBTHROWER_STATE_DYING: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. 0x002dad4c loads 99 and 0x002dad50..0x002dad54 excludes the actor's state 99 from damage handling. This is the existing DYING switch member, entered on non-positive health and processed at 0x002db900. domain_3_value_90 -> BOMBTHROWER_STATE_DAMAGE_KNOCKBACK: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. After surviving damage of at least one, 0x002dae3c calls knockback setup; 0x002dae58..0x002dae6c stores 90 to actor+0x20. That dispatches to existing DAMAGE_KNOCKBACK, sharing motion recovery at 0x002db860. domain_4_value_99 -> BOMBTHROWER_STATE_DYING: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. The non-positive-health branch calls death knockback at 0x002daf00 and explosion handling at 0x002daf28, then stores s1=99 to actor+0x20 at 0x002daf38. This enters the existing DYING case at 0x002db900. domain_5_value_1 -> BOMBTHROWER_STATE_APPROACH_WAYPOINT: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. Initialization selects and reserves pvars+0x120 waypoint at 0x002db058..0x002db06c, then stores state 1 at 0x002db09c. Existing APPROACH_WAYPOINT case moves toward that waypoint at 0x002db0a0..0x002db0b4. domain_6_value_6 -> BOMBTHROWER_STATE_MOVE_ONTO_WAYPOINT: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. After waypoint distance and heading checks and target distance >6, 0x002db174..0x002db17c stores state 6. Existing MOVE_ONTO_WAYPOINT case continues movement then copies waypoint position at 0x002db1f8..0x002db26c. domain_7_value_3 -> BOMBTHROWER_STATE_WAIT_TO_THROW: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. After waypoint-position copy and animation change, 0x002db28c..0x002db290 stores 3 to actor+0x20, sets heading toward the target and a throw timer. This enters the existing WAIT_TO_THROW case at 0x002db2d0. domain_8_value_4 -> BOMBTHROWER_STATE_MOVE_TO_THROW_POSITION: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. The WAIT_TO_THROW branch requests animation 2 then stores 4 to actor+0x20 at 0x002db438..0x002db43c. Existing MOVE_TO_THROW_POSITION case constructs waypoint plus two units along yaw and moves there at 0x002db458..0x002db4d0. domain_9_value_1 -> BOMBTHROWER_STATE_APPROACH_WAYPOINT: The selector is this bombthrower actor's state byte: s2 retains a0 at 0x002dac00, and the switch loads +0x20(s2) at 0x002daf90. The authoritative C switches on this same moby->state, so its existing BOMBTHROWER_STATE members apply; hero state/mode enums do not. In MOVE_TO_THROW_POSITION, 0x002db55c..0x002db580 selects/reserves a replacement waypoint with null fallback; 0x002db58c or shared 0x002db09c stores 1, followed by timer reset. This resumes existing APPROACH_WAYPOINT. --- src/overlays/l08/mobys/blarg_bombthrower.c | 33 ++++++++++++---------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/overlays/l08/mobys/blarg_bombthrower.c b/src/overlays/l08/mobys/blarg_bombthrower.c index fd2955e440..928020efe6 100644 --- a/src/overlays/l08/mobys/blarg_bombthrower.c +++ b/src/overlays/l08/mobys/blarg_bombthrower.c @@ -206,6 +206,9 @@ void blarg_bombthrower_update(struct Moby *moby) { BOMBTHROWER_STATE_FALL_RECOVERY = 0x5D, BOMBTHROWER_STATE_DYING = 0x63 }; + enum { + BOMBTHROWER_STATE_FADE_OUT = 100 + }; Data_DBF68 *bombthrower_vars = (Data_DBF68 *)moby->pvars; Look search; float point[4]; @@ -225,12 +228,12 @@ void blarg_bombthrower_update(struct Moby *moby) { moby->shadow_range = 0x17; } } - if (moby->state == 3) { + if (moby->state == BOMBTHROWER_STATE_WAIT_TO_THROW) { moby->flags &= 0xFBFF; } else { moby->flags |= 0x400; } - if (moby->state == 100) { + if (moby->state == BOMBTHROWER_STATE_FADE_OUT) { float duration = convert_integer_to_float(l08_bombthrower_fade_interpolation_divisor_gp); int start_alpha = bombthrower_vars->s132; moby->alpha = truncate_float_to_s32( @@ -243,7 +246,7 @@ void blarg_bombthrower_update(struct Moby *moby) { } resolve_moby_hit_response( moby, find_moby_hit(moby, 0x330000, 0), &bombthrower_vars->health, 0, &hit, &damage, 0, 4); - if (hit != 1 && moby->state != 0x63) { + if (hit != 1 && moby->state != BOMBTHROWER_STATE_DYING) { moby->flags |= 0x1000; bombthrower_vars->health -= damage; if (0.0f < bombthrower_vars->health) { @@ -268,7 +271,7 @@ void blarg_bombthrower_update(struct Moby *moby) { bombthrower_vars->fC0 = 6.0f; bombthrower_vars->fC4 = 10.0f; bombthrower_vars->tint = 0x78; - moby->state = 0x5A; + moby->state = BOMBTHROWER_STATE_DAMAGE_KNOCKBACK; } } else { char *hero_bytes; @@ -291,7 +294,7 @@ void blarg_bombthrower_update(struct Moby *moby) { bombthrower_vars->fC4 = 10.0f; explode_2D5FA8_c(moby, 0, -1); bombthrower_vars->tint = 0xFA; - moby->state = 0x63; + moby->state = BOMBTHROWER_STATE_DYING; moby->flags &= 0xEFFF; bombthrower_vars->waypoint->command = 0; } @@ -324,7 +327,7 @@ void blarg_bombthrower_update(struct Moby *moby) { if (moby->prev_seq != 4) { FUN_00212f90(moby, 4, 0, 0); } - moby->state = 1; + moby->state = BOMBTHROWER_STATE_APPROACH_WAYPOINT; bombthrower_vars->i134 = scale_game_frames(0xF0); break; case BOMBTHROWER_STATE_APPROACH_WAYPOINT: @@ -341,7 +344,7 @@ void blarg_bombthrower_update(struct Moby *moby) { if (moby->prev_seq != 5) { FUN_00212f90(moby, 5, 0, 10); } - moby->state = 6; + moby->state = BOMBTHROWER_STATE_MOVE_ONTO_WAYPOINT; break; } bombthrower_vars->i134 = scale_game_frames(0xF0); @@ -381,7 +384,7 @@ void blarg_bombthrower_update(struct Moby *moby) { if (moby->prev_seq != 1) { FUN_00212f90(moby, 1, 0, 10); } - moby->state = 3; + moby->state = BOMBTHROWER_STATE_WAIT_TO_THROW; moby->flags &= 0xEFFF; moby->rot.z = fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y); bombthrower_vars->i128 = scale_game_frames(0x78); @@ -414,7 +417,7 @@ void blarg_bombthrower_update(struct Moby *moby) { if (moby->prev_seq != 2) { FUN_00212f90(moby, 2, 0, scale_game_frames(7)); } - moby->state = 4; + moby->state = BOMBTHROWER_STATE_MOVE_TO_THROW_POSITION; moby->flags |= 0x1000; moby->collision = moby->pclass->collision; break; @@ -446,13 +449,13 @@ void blarg_bombthrower_update(struct Moby *moby) { if (moby->prev_seq != 4) { FUN_00212f90(moby, 4, 0, scale_game_frames(7)); } - moby->state = 1; + moby->state = BOMBTHROWER_STATE_APPROACH_WAYPOINT; bombthrower_vars->i134 = scale_game_frames(0xF0); } else { if (moby->prev_seq != 3) { FUN_00212f90(moby, 3, 0, scale_game_frames(6)); } - moby->state = 5; + moby->state = BOMBTHROWER_STATE_THROW_BOMB; } } break; @@ -498,7 +501,7 @@ void blarg_bombthrower_update(struct Moby *moby) { break; } if (moby->anim_flags & 2) { - moby->state = 1; + moby->state = BOMBTHROWER_STATE_APPROACH_WAYPOINT; if (moby->prev_seq != 4) { FUN_00212f90(moby, 4, 0, 3); } @@ -510,7 +513,7 @@ void blarg_bombthrower_update(struct Moby *moby) { if (moby->prev_seq != 7) { FUN_00212f90(moby, 7, 0, 3); } - moby->state = 0x5D; + moby->state = BOMBTHROWER_STATE_FALL_RECOVERY; } break; case BOMBTHROWER_STATE_DAMAGE_KNOCKBACK: @@ -528,7 +531,7 @@ void blarg_bombthrower_update(struct Moby *moby) { if (moby->prev_seq != 4) { FUN_00212f90(moby, 4, 0, 10); } - moby->state = 1; + moby->state = BOMBTHROWER_STATE_APPROACH_WAYPOINT; bombthrower_vars->i134 = scale_game_frames(0xF0); } if (moby->pos.z < 5.0f) { @@ -539,7 +542,7 @@ void blarg_bombthrower_update(struct Moby *moby) { case BOMBTHROWER_STATE_DYING: if (step_moby_motion(moby, bombthrower_vars->blk70) & 0x40) { moby->anim_speed = 0.0f; - moby->state = 100; + moby->state = BOMBTHROWER_STATE_FADE_OUT; moby->collision = 0; bombthrower_vars->s132 = 0x28; bombthrower_vars->s130 = l08_bombthrower_fade_interpolation_divisor_gp; From 34bbdcf0bee1305b8b1d19536680bd8b09ba9e13 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:20:49 +0000 Subject: [PATCH 0266/1502] decomp: clarify names in update_player_ship_flight D_L11_0016209C -> l11_jet_fighter_horizontal_steering_spring_error_gain: Authoritative C passes D_L11_0016209C as vendor_spring error_gain while updating ship_vars+0x6c/+0x90 toward bounded horizontal_steering_input. Retail 0x00312aec/0x00312af4 loads this pair into f13/f14 before call 0x00312af8 to checked 0x00281760. Supplied vendor_spring source forwards error_gain with target_value - *current_value to advance_damped_scalar_velocity; checked 0x00281790..0x00281798 likewise forms target-current in f12 and forwards f13. This proves this binding's consumer and established error_gain role. D_L11_001620A0 -> l11_jet_fighter_horizontal_steering_spring_damping_coefficient: Authoritative C passes D_L11_001620A0 as vendor_spring damping_coefficient for ship_vars+0x6c/+0x90 toward bounded horizontal_steering_input. Retail 0x00312aec/0x00312af4 loads this pair into f13/f14 before 0x00312af8 calls checked 0x00281760. Supplied vendor_spring source explicitly forwards damping_coefficient to advance_damped_scalar_velocity; checked 0x0028177c..0x00281798 forwards f14 and the velocity pointer, then 0x0028179c..0x002817ac adds the updated velocity to the current value. Role follows the supplied established helper source; no exact damping equation or units are inferred. D_L11_001620AC -> l11_jet_fighter_vertical_steering_spring_error_gain: Authoritative C passes D_L11_001620AC as vendor_spring error_gain while updating ship_vars+0x70/+0x94 toward bounded vertical_steering_input. Retail 0x00312b08/0x00312b10 loads this pair into f13/f14 before call 0x00312b14 to checked 0x00281760. Supplied vendor_spring source forwards error_gain with target_value - *current_value to advance_damped_scalar_velocity; checked 0x00281790..0x00281798 likewise forms target-current in f12 and forwards f13. This proves this binding's consumer and established error_gain role. D_L11_001620B0 -> l11_jet_fighter_vertical_steering_spring_damping_coefficient: Authoritative C passes D_L11_001620B0 as vendor_spring damping_coefficient for ship_vars+0x70/+0x94 toward bounded vertical_steering_input. Retail 0x00312b08/0x00312b10 loads this pair into f13/f14 before 0x00312b14 calls checked 0x00281760. Supplied vendor_spring source explicitly forwards damping_coefficient to advance_damped_scalar_velocity; checked 0x0028177c..0x00281798 forwards f14 and the velocity pointer, then 0x0028179c..0x002817ac adds the updated velocity to the current value. Role follows the supplied established helper source; no exact damping equation or units are inferred. D_L11_00162104 -> l11_jet_fighter_camera_local_x_spring_error_gain: Authoritative C passes D_L11_00162104 as vendor_spring error_gain while updating ship_vars+0xb4/+0xc8 toward selected camera_offset_targets component 0. Retail 0x00312ce0/0x00312ce8 loads this pair into f13/f14 before call 0x00312cf0 to checked 0x00281760. Supplied vendor_spring source forwards error_gain with target_value - *current_value to advance_damped_scalar_velocity; checked 0x00281790..0x00281798 likewise forms target-current in f12 and forwards f13. This proves this binding's consumer and established error_gain role. D_L11_00162108 -> l11_jet_fighter_camera_local_x_spring_damping_coefficient: Authoritative C passes D_L11_00162108 as vendor_spring damping_coefficient for ship_vars+0xb4/+0xc8 toward selected camera_offset_targets component 0. Retail 0x00312ce0/0x00312ce8 loads this pair into f13/f14 before 0x00312cf0 calls checked 0x00281760. Supplied vendor_spring source explicitly forwards damping_coefficient to advance_damped_scalar_velocity; checked 0x0028177c..0x00281798 forwards f14 and the velocity pointer, then 0x0028179c..0x002817ac adds the updated velocity to the current value. Role follows the supplied established helper source; no exact damping equation or units are inferred. D_L11_00162110 -> l11_jet_fighter_camera_local_y_spring_error_gain: Authoritative C passes D_L11_00162110 as vendor_spring error_gain while updating ship_vars+0xb8/+0xcc toward selected camera_offset_targets component 1. Retail 0x00312d00/0x00312d0c loads this pair into f13/f14 before call 0x00312d18 to checked 0x00281760. Supplied vendor_spring source forwards error_gain with target_value - *current_value to advance_damped_scalar_velocity; checked 0x00281790..0x00281798 likewise forms target-current in f12 and forwards f13. This proves this binding's consumer and established error_gain role. D_L11_00162114 -> l11_jet_fighter_camera_local_y_spring_damping_coefficient: Authoritative C passes D_L11_00162114 as vendor_spring damping_coefficient for ship_vars+0xb8/+0xcc toward selected camera_offset_targets component 1. Retail 0x00312d00/0x00312d0c loads this pair into f13/f14 before 0x00312d18 calls checked 0x00281760. Supplied vendor_spring source explicitly forwards damping_coefficient to advance_damped_scalar_velocity; checked 0x0028177c..0x00281798 forwards f14 and the velocity pointer, then 0x0028179c..0x002817ac adds the updated velocity to the current value. Role follows the supplied established helper source; no exact damping equation or units are inferred. D_L11_0016211C -> l11_jet_fighter_camera_local_z_spring_error_gain: Authoritative C passes D_L11_0016211C as vendor_spring error_gain while updating ship_vars+0xbc/+0xd0 toward selected camera_offset_targets component 2. Retail 0x00312d3c/0x00312d28 loads this pair into f13/f14 before call 0x00312d40 to checked 0x00281760. Supplied vendor_spring source forwards error_gain with target_value - *current_value to advance_damped_scalar_velocity; checked 0x00281790..0x00281798 likewise forms target-current in f12 and forwards f13. This proves this binding's consumer and established error_gain role. D_L11_00162120 -> l11_jet_fighter_camera_local_z_spring_damping_coefficient: Authoritative C passes D_L11_00162120 as vendor_spring damping_coefficient for ship_vars+0xbc/+0xd0 toward selected camera_offset_targets component 2. Retail 0x00312d3c/0x00312d28 loads this pair into f13/f14 before 0x00312d40 calls checked 0x00281760. Supplied vendor_spring source explicitly forwards damping_coefficient to advance_damped_scalar_velocity; checked 0x0028177c..0x00281798 forwards f14 and the velocity pointer, then 0x0028179c..0x002817ac adds the updated velocity to the current value. Role follows the supplied established helper source; no exact damping equation or units are inferred. --- src/overlays/l11/mobys/jet_fighter.c | 40 ++++++++++++++-------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/overlays/l11/mobys/jet_fighter.c b/src/overlays/l11/mobys/jet_fighter.c index 53e58668ad..4c2043c2ba 100644 --- a/src/overlays/l11/mobys/jet_fighter.c +++ b/src/overlays/l11/mobys/jet_fighter.c @@ -771,13 +771,13 @@ extern float D_L11_0016204C __attribute__((sda)); extern float D_L11_0016207C __attribute__((sda)); extern float D_L11_00162080 __attribute__((sda)); extern float D_L11_0016208C __attribute__((sda)); -extern float D_L11_0016209C __attribute__((sda)); -extern float D_L11_001620A0 __attribute__((sda)); +extern float l11_jet_fighter_horizontal_steering_spring_error_gain __asm__("D_L11_0016209C") __attribute__((sda)); +extern float l11_jet_fighter_horizontal_steering_spring_damping_coefficient __asm__("D_L11_001620A0") __attribute__((sda)); #include "rnc/overlay/l11/mobys/jet_fighter_data/update_player_ship_flight_10.h" -extern float D_L11_001620AC __attribute__((sda)); -extern float D_L11_001620B0 __attribute__((sda)); +extern float l11_jet_fighter_vertical_steering_spring_error_gain __asm__("D_L11_001620AC") __attribute__((sda)); +extern float l11_jet_fighter_vertical_steering_spring_damping_coefficient __asm__("D_L11_001620B0") __attribute__((sda)); #include "rnc/overlay/l11/mobys/jet_fighter_data/update_player_ship_flight_9.h" @@ -801,18 +801,18 @@ extern float D_L11_001620FC __attribute__((sda)); #include "rnc/overlay/l11/mobys/jet_fighter_data/update_player_ship_flight_5.h" -extern float D_L11_00162104 __attribute__((sda)); -extern float D_L11_00162108 __attribute__((sda)); +extern float l11_jet_fighter_camera_local_x_spring_error_gain __asm__("D_L11_00162104") __attribute__((sda)); +extern float l11_jet_fighter_camera_local_x_spring_damping_coefficient __asm__("D_L11_00162108") __attribute__((sda)); #include "rnc/overlay/l11/mobys/jet_fighter_data/update_player_ship_flight_4.h" -extern float D_L11_00162110 __attribute__((sda)); -extern float D_L11_00162114 __attribute__((sda)); +extern float l11_jet_fighter_camera_local_y_spring_error_gain __asm__("D_L11_00162110") __attribute__((sda)); +extern float l11_jet_fighter_camera_local_y_spring_damping_coefficient __asm__("D_L11_00162114") __attribute__((sda)); #include "rnc/overlay/l11/mobys/jet_fighter_data/update_player_ship_flight_3.h" -extern float D_L11_0016211C __attribute__((sda)); -extern float D_L11_00162120 __attribute__((sda)); +extern float l11_jet_fighter_camera_local_z_spring_error_gain __asm__("D_L11_0016211C") __attribute__((sda)); +extern float l11_jet_fighter_camera_local_z_spring_damping_coefficient __asm__("D_L11_00162120") __attribute__((sda)); #include "rnc/overlay/l11/mobys/jet_fighter_data/update_player_ship_flight_2.h" @@ -954,14 +954,14 @@ void update_player_ship_flight(struct Moby *ship_moby, ShipVars_2838 *ship_vars) vendor_spring(&ship_vars->f6C, &ship_vars->f90, horizontal_steering_input, - D_L11_0016209C, - D_L11_001620A0, + l11_jet_fighter_horizontal_steering_spring_error_gain, + l11_jet_fighter_horizontal_steering_spring_damping_coefficient, ka); vendor_spring(&ship_vars->f70, &ship_vars->f94, vertical_steering_input, - D_L11_001620AC, - D_L11_001620B0, + l11_jet_fighter_vertical_steering_spring_error_gain, + l11_jet_fighter_vertical_steering_spring_damping_coefficient, kb); spring_angle(&ship_vars->f30, &ship_vars->f98, @@ -1014,20 +1014,20 @@ void update_player_ship_flight(struct Moby *ship_moby, ShipVars_2838 *ship_vars) vendor_spring(&ship_vars->fB4, &ship_vars->fC8, camera_offset_targets.e[ship_vars->sel].v[0], - D_L11_00162104, - D_L11_00162108, + l11_jet_fighter_camera_local_x_spring_error_gain, + l11_jet_fighter_camera_local_x_spring_damping_coefficient, jet_fighter_camera_local_x_snap_threshold_scale_gp); vendor_spring(&ship_vars->fB8, &ship_vars->fCC, camera_offset_targets.e[ship_vars->sel].v[1], - D_L11_00162110, - D_L11_00162114, + l11_jet_fighter_camera_local_y_spring_error_gain, + l11_jet_fighter_camera_local_y_spring_damping_coefficient, jet_fighter_camera_local_y_snap_threshold_scale_gp); vendor_spring(&ship_vars->fBC, &ship_vars->fD0, camera_offset_targets.e[ship_vars->sel].v[2], - D_L11_0016211C, - D_L11_00162120, + l11_jet_fighter_camera_local_z_spring_error_gain, + l11_jet_fighter_camera_local_z_spring_damping_coefficient, jet_fighter_camera_local_z_snap_threshold_scale_gp); camera_local_offset[0] = ship_vars->fB4; camera_local_offset[1] = ship_vars->fB8; From e6f2b541a79a19b97b011df541a5f142e786f908 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:20:49 +0000 Subject: [PATCH 0267/1502] decomp: clarify names in fighter_jet_update domain_0_value_7 -> FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY: Retail 0x002ed060-0x002ed074 excludes state byte moby+0x20 value 7 from hit processing; the same selector dispatches death delay at 0x002eda2c, decrements hit_timer and respawns before resetting state to initialize. domain_10_value_5 -> FIGHTER_JET_STATE_DISMOUNT: Retail 0x002ed8d0-0x002ed8e4 tests hero ship_flags bit 1 then writes 5 to moby+0x20. Case 5 at 0x002ed8e8 ends mounting, restores the home transform, releases voices and returns to wait-for-boarding. domain_11_value_1 -> FIGHTER_JET_STATE_WAIT_FOR_BOARDING: Retail 0x002eda18-0x002eda28 stores state 1 after the dismount path restores the ship home transform and releases voices. Case 1 on this same moby selector waits for boarding distance/help/input, matching the local enum. domain_12_value_0 -> FIGHTER_JET_STATE_INITIALIZE: Retail 0x002eda50-0x002edb34 respawns the hero, restores home transform, releases voices and stores zero to moby+0x20. Its existing case 0 initializes FOV/home transforms and palette state, proving reuse of INITIALIZE. domain_13_value_9 -> FIGHTER_JET_STATE_FADE_THEN_REMOVE: Retail 0x002edb38-0x002eddb0 completes victory exit, places jet/hero and releases voices before writing 9 to moby+0x20. Case 9 fades vars+0x130 down to zero then removes the moby, matching the existing member. domain_14_value_4 -> FIGHTER_JET_STATE_PILOTED_FLIGHT: Retail 0x002ede90-0x002edec0 compares the fighter-jet state byte +0x20 with 4 then copies ship position/rotation to the hero. This directly shares the selector with existing PILOTED_FLIGHT case 4 running the flight update. domain_16_value_4 -> FIGHTER_JET_STATE_PILOTED_FLIGHT: Retail 0x002edec4-0x002eded8 tests unsigned(state-3)<2 for particle emission, represented in authoritative C as state==3 || state==4. The value-4 operand is the same moby+0x20 selector as existing PILOTED_FLIGHT; no meaning for 3 is inferred. domain_1_value_1 -> FIGHTER_JET_STATE_WAIT_FOR_BOARDING: Retail 0x002ed060-0x002ed074 excludes moby+0x20 value 1 from hits. This exact selector's case 1 at 0x002ed4e0 tests hero distance, help and input for boarding, matching the existing local enum. domain_2_value_2 -> FIGHTER_JET_STATE_BOARDING_FADE: Retail 0x002ed070-0x002ed074 excludes moby state 2 from hits; case 2 at 0x002ed5a4 fades vars+0x130 to one before mounting and initializing hero ship fields, establishing the existing boarding-fade member. domain_3_value_4 -> FIGHTER_JET_STATE_PILOTED_FLIGHT: Retail 0x002ed098-0x002ed09c tests the fighter-jet moby state byte +0x20 for 4 before applying hit damage to hero ship HP; this is the same selector as existing PILOTED_FLIGHT case, which runs flight and synchronizes the hero. domain_4_value_7 -> FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY: Retail 0x002ed1c8-0x002ed210 handles lethal damage: clears ship HP, stores 7 to moby+0x20 and starts hit_timer. The matching case decrements that timer then calls hero_respawn, proving the existing death-delay member. domain_5_value_1 -> FIGHTER_JET_STATE_WAIT_FOR_BOARDING: Retail 0x002ed310-0x002ed318 initializes moby+0x20 to 1 while saving home transform and FOV; the same state selector's case 1 waits on hero distance/help/input before boarding, matching the existing local enum. domain_6_value_9 -> FIGHTER_JET_STATE_FADE_THEN_REMOVE: Retail 0x002ed470-0x002ed4a4 sets moby+0x20 to 9 when its persistent visited entry is 0xff. The same selector's case 9 at 0x002eddb4 fades vars+0x130 to zero then removes the moby, matching the existing member. domain_7_value_2 -> FIGHTER_JET_STATE_BOARDING_FADE: Retail 0x002ed524-0x002ed53c writes 2 to the fighter-jet state after distance/help/input authorize boarding. Case 2 then approaches fade to one and mounts the hero, matching existing FIGHTER_JET_STATE_BOARDING_FADE. domain_8_value_4 -> FIGHTER_JET_STATE_PILOTED_FLIGHT: Retail 0x002ed5e0-0x002ed7f8 initializes hero ship fields, mounts the ship, runs flight and stores 4 to moby+0x20. Its existing case 4 continues update_fighter_jet_flight and the common tail synchronizes hero transform. domain_9_value_8 -> FIGHTER_JET_STATE_VICTORY_EXIT: Retail 0x002ed86c-0x002ed884 sets moby+0x20 to 8 when vars+0xe8 is exhausted and starts timerF8. Case 8 continues flight, fades out and uses strings at 0x001e6e00/0x001e6e38 explicitly describing victory placements. --- src/overlays/l17/mobys/fighter_jet.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/overlays/l17/mobys/fighter_jet.c b/src/overlays/l17/mobys/fighter_jet.c index c3a93d4924..45fc89d842 100644 --- a/src/overlays/l17/mobys/fighter_jet.c +++ b/src/overlays/l17/mobys/fighter_jet.c @@ -1762,9 +1762,9 @@ void fighter_jet_update(ShipMoby *moby) { if (moby != 0) { ship_vars = (ShipVars *)moby->vars; fast_dec_timer(&ship_vars->timerDC); - if (moby->state != 7 && moby->state != 1 && moby->state != 2) { + if (moby->state != FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY && moby->state != FIGHTER_JET_STATE_WAIT_FOR_BOARDING && moby->state != FIGHTER_JET_STATE_BOARDING_FADE) { hit = (ShipHit *)find_moby_hit(moby, 0x30001, 0); - if (hit != 0 && moby->state == 4) { + if (hit != 0 && moby->state == FIGHTER_JET_STATE_PILOTED_FLIGHT) { struct Hero *g = &hero; if (hit->damage < g->ship_hp) { g->ship_hp -= hit->damage; @@ -1799,7 +1799,7 @@ void fighter_jet_update(ShipMoby *moby) { s->shake_frames = scale_game_frames(5); } g->ship_hp = 0.0f; - moby->state = 7; + moby->state = FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY; ship_vars->hit_timer = scale_game_frames(30); g->motion.pos.f[2] += 0.2f; ((ShipCamera *)g->moby)->unk98 = 0; @@ -1837,7 +1837,7 @@ void fighter_jet_update(ShipMoby *moby) { } switch (moby->state) { case FIGHTER_JET_STATE_INITIALIZE: - moby->state = 1; + moby->state = FIGHTER_JET_STATE_WAIT_FOR_BOARDING; ship_vars->b60 = 0; moby->scale = *(float *)(moby->pclass + 0x24); ship_vars->f20 = ship_vars->rot[0]; @@ -1862,7 +1862,7 @@ void fighter_jet_update(ShipMoby *moby) { ship_vars->timerF8 = 1; ship_vars->iE8 = 1; if (moby->bB0 != 0xFF && visited52[moby->bB0 + current_level_index * 16] == 0xFF) { - moby->state = 9; + moby->state = FIGHTER_JET_STATE_FADE_THEN_REMOVE; } if (ship_vars->i11C > 0) { jet_group_state(ship_vars->i11C, 0, 0, 0); @@ -1877,7 +1877,7 @@ void fighter_jet_update(ShipMoby *moby) { FUN_00215130(7, 0x53E4) != 0 && (pad_pressed_words[0] & 0x10); if (board) { remove_help_message_for_selector(7); - moby->state = 2; + moby->state = FIGHTER_JET_STATE_BOARDING_FADE; ship_vars->i124 = -1; } else if (ship_vars->fade != 0.0f) { FUN_00213ed8(&ship_vars->fade, 0.0f, frame_time * 4.0f); @@ -1948,7 +1948,7 @@ void fighter_jet_update(ShipMoby *moby) { jet_camera_mode(); D_L17_0015F608 = 2; update_fighter_jet_flight((FighterJetMoby *)moby, (FighterJetVars *)ship_vars); - moby->state = 4; + moby->state = FIGHTER_JET_STATE_PILOTED_FLIGHT; } break; case FIGHTER_JET_STATE_PILOTED_FLIGHT: @@ -1962,7 +1962,7 @@ void fighter_jet_update(ShipMoby *moby) { update_fighter_jet_flight((FighterJetMoby *)moby, (FighterJetVars *)ship_vars); if (ship_vars->iE8 <= 0) { ship_vars->timerF8 = D_L17_00162178; - moby->state = 8; + moby->state = FIGHTER_JET_STATE_VICTORY_EXIT; } if (ship_vars->fade != 0.0f) { FUN_00213ed8(&ship_vars->fade, 0.0f, frame_time * 4.0f); @@ -1971,7 +1971,7 @@ void fighter_jet_update(ShipMoby *moby) { { struct Hero *g = &hero; if (g->ship_flags & 1) { - moby->state = 5; + moby->state = FIGHTER_JET_STATE_DISMOUNT; } } break; @@ -2006,7 +2006,7 @@ void fighter_jet_update(ShipMoby *moby) { } } ship_vars->voice2 = -1; - moby->state = 1; + moby->state = FIGHTER_JET_STATE_WAIT_FOR_BOARDING; ship_vars->fade = 0.99f; fighter_jet_transition_fade_value = 0.99f; break; @@ -2040,7 +2040,7 @@ void fighter_jet_update(ShipMoby *moby) { } } ship_vars->voice2 = -1; - moby->state = 0; + moby->state = FIGHTER_JET_STATE_INITIALIZE; } break; case FIGHTER_JET_STATE_VICTORY_EXIT: @@ -2102,7 +2102,7 @@ void fighter_jet_update(ShipMoby *moby) { } ship_vars->voice2 = -1; jet_reset_camera((&hero.motion.pos), &hero.motion.rot); - moby->state = 9; + moby->state = FIGHTER_JET_STATE_FADE_THEN_REMOVE; } break; case 10: @@ -2134,11 +2134,11 @@ void fighter_jet_update(ShipMoby *moby) { if (moby->pos[2] > 1008.0f) { moby->pos[2] = 1008.0f; } - if (moby->state == 4) { + if (moby->state == FIGHTER_JET_STATE_PILOTED_FLIGHT) { qcopy_nc((&hero.motion.pos), moby->pos); qcopy_nc(&hero.motion.rot, ship_vars->rot); } - if (moby->state == 3 || moby->state == 4) { + if (moby->state == 3 || moby->state == FIGHTER_JET_STATE_PILOTED_FLIGHT) { emit_type_74_particles_from_moby_joints(moby, ship_vars); } } From 5e82fb5aa4904fbb2beed7450a4f75fb2c9587bd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:20:49 +0000 Subject: [PATCH 0268/1502] decomp: clarify names in electric_water_update domain_0_value_0 -> ELECTRIC_WATER_INITIALIZE: Retail 002d6854..002d685c reads the assigned controller moby's state at s5+0x20 and bypasses active-volume cleanup when zero. The same field dispatches zero to initialization at 002d6948/002d697c, matching the existing local ELECTRIC_WATER_INITIALIZE member. domain_10_value_1 -> ELECTRIC_WATER_ON: After switch-disabled timer/reset-volume conditions and linked-switch reset, retail 002d76ec..002d7720 initializes controller on_timer, resets off_timer/shock_count and stores 1 to s5+0x20. This is the controller's existing ELECTRIC_WATER_ON state; the earlier 002d76d4 write addresses a linked switch and is outside this proposal. domain_1_value_1 -> ELECTRIC_WATER_ON: Initialization sets on_timer at 002d6ab0, clears shock_count and invalidates handles, then 002d6ac8..002d6ad0 stores 1 to controller s5+0x20. Dispatch 002d6934..002d6938 sends this exact field/value to the on-timer, flicker and shock path, the existing ELECTRIC_WATER_ON case. domain_2_value_2 -> ELECTRIC_WATER_OFF: After controller on_timer expiry at 002d6aec..002d6af4, retail initializes off_timer at 002d6b14 and stores 2 to s5+0x20 at 002d6b18..002d6b1c. The same field dispatches 2 to 002d7170, the existing ELECTRIC_WATER_OFF shared sound/switch path. domain_3_value_2 -> ELECTRIC_WATER_OFF: Retail 002d6bac..002d6bb4 reloads the controller state from s5+0x20 and compares it with 2 after on_timer may have expired. The equal branch dims lamps to 0x40; this tests the same off phase dispatched as ELECTRIC_WATER_OFF at 002d695c..002d6960. domain_4_value_2 -> ELECTRIC_WATER_OFF: Retail 002d710c..002d7114 tests controller s5+0x20 against 2 after the hero hit, restoring saved fog at 002d711c..002d716c when equal. This is the on-to-off transition remainder, using the exact state field and value of the existing ELECTRIC_WATER_OFF dispatch. domain_5_value_1 -> ELECTRIC_WATER_ON: Retail 002d7300..002d7308 reads controller state at s5+0x20 and compares 1 to gate the second hum voice at 002d7310..002d7334. The same controller field/value dispatches to the ELECTRIC_WATER_ON path at 002d6934..002d6938; no linked-switch or hero state is involved. domain_6_value_2 -> ELECTRIC_WATER_OFF: Retail 002d7338..002d734c decrements controller off_timer at pvars+0x12 and tests s5+0x20 == 2 before reinitializing on_timer and restoring state 1. This is the exact controller field dispatched to existing ELECTRIC_WATER_OFF, not the linked switch's separate state. domain_7_value_1 -> ELECTRIC_WATER_ON: Retail 002d7350..002d7384 reloads the configured on duration into on_timer, resets off_timer and shock_count, and stores 1 into controller s5+0x20 after off_timer expiry. Dispatch of that field/value at 002d6938 proves reuse of existing ELECTRIC_WATER_ON. domain_8_value_3 -> ELECTRIC_WATER_SWITCH_DISABLED: Source first switch-activation arm and retail 002d73bc..002d7410 test linked class 0x33e state 2, set the controller's off_timer from pvars+0x18, and store s3=3 into controller s5+0x20. Controller dispatch 002d6968..002d696c reaches countdown and cleanup case ELECTRIC_WATER_SWITCH_DISABLED; linked switch state 2 remains separate. domain_9_value_3 -> ELECTRIC_WATER_SWITCH_DISABLED: Source alternate linked-turn-trigger arm joins retail 002d73e4..002d7410: successful trigger loads off_seconds, sets off_timer and stores 3 to controller s5+0x20, clearing armed at 002d7434. That same controller state dispatches to existing ELECTRIC_WATER_SWITCH_DISABLED at 002d696c, independently of the trigger return value. --- src/overlays/shared/props/electric_water.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/shared/props/electric_water.c b/src/overlays/shared/props/electric_water.c index c7034b672c..0612397593 100644 --- a/src/overlays/shared/props/electric_water.c +++ b/src/overlays/shared/props/electric_water.c @@ -133,7 +133,7 @@ void electric_water_update(struct Moby *moby) { unsigned short save_id; float distance, theta, phi, radius; - if (moby->state != 0 && + if (moby->state != ELECTRIC_WATER_INITIALIZE && is_point_inside_clip_volume(D_0013F3D0, electric_water_controller_vars->active_area) == 0) { if (electric_water_controller_vars->owner != 0) { if (electric_water_controller_vars->voice0 != -1) { @@ -196,7 +196,7 @@ void electric_water_update(struct Moby *moby) { electric_water_controller_vars->off_timer = scale_game_frames(200); electric_water_controller_vars->shock_count = 0; electric_water_controller_vars->light = -1; - moby->state = 1; + moby->state = ELECTRIC_WATER_ON; electric_water_controller_vars->voice0 = -1; electric_water_controller_vars->voice1 = -1; break; @@ -207,7 +207,7 @@ void electric_water_update(struct Moby *moby) { if (fast_dec_timer_s16(&electric_water_controller_vars->on_timer) != 0) { electric_water_controller_vars->off_timer = truncate_float_to_s32(scale_time(electric_water_off_duration_seconds_gp * 60.0f)); - moby->state = 2; + moby->state = ELECTRIC_WATER_OFF; if (electric_water_controller_vars->owner != 0) { if (electric_water_controller_vars->voice1 != -1) { VoicePoolWindow *voice = @@ -229,7 +229,7 @@ void electric_water_update(struct Moby *moby) { break; } } - if (moby->state == 2) { + if (moby->state == ELECTRIC_WATER_OFF) { for (dim_lamp = 0; dim_lamp < 3; dim_lamp++) { if (electric_water_controller_vars->lamps[dim_lamp] != -1) { set_moby_color(&l15_moby_array[electric_water_controller_vars->lamps[dim_lamp]], @@ -378,7 +378,7 @@ void electric_water_update(struct Moby *moby) { hit.v[3] = 5627.9248f; hit.unk18 = 0; record_moby_hit(hero.moby, &hit); - if (moby->state == 2) { + if (moby->state == ELECTRIC_WATER_OFF) { D_L15_0015F448 = electric_water_controller_vars->saved_fog[0]; D_L15_0015F44C = electric_water_controller_vars->saved_fog[1]; D_L15_0015F450 = electric_water_controller_vars->saved_fog[2]; @@ -440,18 +440,18 @@ void electric_water_update(struct Moby *moby) { electric_water_controller_vars->voice0 = trooper_play_sound(0, 5, electric_water_controller_vars->owner, 0x28F); } - if (moby->state == 1 && voice_is_playing(electric_water_controller_vars->owner, + if (moby->state == ELECTRIC_WATER_ON && voice_is_playing(electric_water_controller_vars->owner, electric_water_controller_vars->voice1) == 0) { electric_water_controller_vars->voice1 = trooper_play_sound(1, 5, electric_water_controller_vars->owner, 0x28F); } if (fast_dec_timer_s16(&electric_water_controller_vars->off_timer) != 0 && - moby->state == 2) { + moby->state == ELECTRIC_WATER_OFF) { electric_water_controller_vars->on_timer = truncate_float_to_s32(scale_time(electric_water_on_duration_seconds_gp * 60.0f)); electric_water_controller_vars->off_timer = scale_game_frames(200); electric_water_controller_vars->shock_count = 0; - moby->state = 1; + moby->state = ELECTRIC_WATER_ON; } for (sw = 0; sw < 4; sw++) { /* Fakematch: the press action is written in both arms so CSE keeps the second sw load. */ @@ -460,7 +460,7 @@ void electric_water_update(struct Moby *moby) { l15_moby_array[electric_water_controller_vars->switches[sw]].state == 2) { electric_water_controller_vars->off_timer = truncate_float_to_s32( scale_time(electric_water_controller_vars->off_seconds * 60.0f)); - moby->state = 3; + moby->state = ELECTRIC_WATER_SWITCH_DISABLED; trooper_play_sound( 2, 0, &l15_moby_array[electric_water_controller_vars->switches[sw]], 0x28F); electric_water_controller_vars->armed = 0; @@ -469,7 +469,7 @@ void electric_water_update(struct Moby *moby) { &l15_moby_array[electric_water_controller_vars->switches[sw]]) != 0) { electric_water_controller_vars->off_timer = truncate_float_to_s32( scale_time(electric_water_controller_vars->off_seconds * 60.0f)); - moby->state = 3; + moby->state = ELECTRIC_WATER_SWITCH_DISABLED; trooper_play_sound( 2, 0, &l15_moby_array[electric_water_controller_vars->switches[sw]], 0x28F); electric_water_controller_vars->armed = 0; @@ -561,7 +561,7 @@ void electric_water_update(struct Moby *moby) { truncate_float_to_s32(scale_time(electric_water_on_duration_seconds_gp * 60.0f)); electric_water_controller_vars->off_timer = scale_game_frames(200); electric_water_controller_vars->shock_count = 0; - moby->state = 1; + moby->state = ELECTRIC_WATER_ON; break; } From 701717c7ef98f0bd551c7a01546a95ae372a4870 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:23:32 +0000 Subject: [PATCH 0269/1502] decomp: clarify names in sandmouse_update domain_0_value_5 -> SANDMOUSE_STATE_FOLLOW_HERO_AND_FIRE: 0030df7c..0030df84 loads sandmouse Moby +0x20 and compares it with 5 to select own-position versus hero-position aiming. The same byte selects switch cases at 0030e08c..0030e0ac; local enum names case 5 FOLLOW_HERO_AND_FIRE. domain_10_value_7 -> SANDMOUSE_STATE_RESET: 0030ebec..0030ec20 on fade timer completion restores alpha, copies saved position and clears velocity before writing 7 to sandmouse +0x20. This enters the established RESET case of the same local state switch. domain_11_value_1 -> SANDMOUSE_STATE_WAIT_FOR_ACTIVATION: 0030ee78..0030ee98 writes linked command 1 at linked +0xbc and separately writes 1 to sandmouse state +0x20, then hides the sandmouse. The latter belongs to established local WAIT_FOR_ACTIVATION, not a linked command domain. domain_12_value_2 -> SANDMOUSE_STATE_WAIT_FOR_LINK: 0030ee9c..0030eea4 reloads sandmouse state +0x20 and compares it against 2 to gate jet animation and particles. The same byte drives the local switch, whose value 2 is canonically WAIT_FOR_LINK; this names the range boundary. domain_1_value_3 -> SANDMOUSE_STATE_MOVE_TO_GOAL: 0030e020..0030e028 compares the same sandmouse Moby state byte +0x20 against 3 before manipulator/billboard updates. The local switch on this exact field names state 3 MOVE_TO_GOAL; this is a range boundary in that domain. domain_2_value_1 -> SANDMOUSE_STATE_WAIT_FOR_ACTIVATION: 0030e2d8..0030e2e4 stores 1 at sandmouse Moby +0x20 after initialization, then 0030ee98 hides it. The same byte drives the local switch whose established case 1 is WAIT_FOR_ACTIVATION. domain_3_value_2 -> SANDMOUSE_STATE_WAIT_FOR_LINK: 0030e548..0030e570 writes linked command 5 at linked +0xbc separately, then writes 2 at sandmouse +0x20. This latter byte selects the established WAIT_FOR_LINK case, which tests linked state before moving on. domain_4_value_3 -> SANDMOUSE_STATE_MOVE_TO_GOAL: 0030e574..0030e5a4 absent-link activation reveals the sandmouse and selects value 3 for the store at 0030e668..0030e66c to its state +0x20. This is the same field as established local case MOVE_TO_GOAL. domain_5_value_3 -> SANDMOUSE_STATE_MOVE_TO_GOAL: 0030e5c4..0030e608 tests linked Moby state 5, then writes 3 at sandmouse +0x20 and clears its timer. Only the destination sandmouse state is renamed, reusing the established MOVE_TO_GOAL case. domain_6_value_3 -> SANDMOUSE_STATE_MOVE_TO_GOAL: 0030e610..0030e66c clears the timer, reveals the sandmouse and optionally allocates voice on the absent-link path before storing 3 to sandmouse +0x20. Its switch names that same state MOVE_TO_GOAL. domain_7_value_4 -> SANDMOUSE_STATE_BEGIN_FOLLOW_HERO_AND_FIRE: 0030e7cc..0030e844 tests movement flags or goal proximity, clears velocity, writes 4 to sandmouse state +0x20 and sets a timer. This enters the established local case BEGIN_FOLLOW_HERO_AND_FIRE. domain_8_value_5 -> SANDMOUSE_STATE_FOLLOW_HERO_AND_FIRE: 0030e900..0030e940 calls the hero helper, clears flags and writes 5 to sandmouse Moby state +0x20. This is the same selector as local case FOLLOW_HERO_AND_FIRE, whose branch calls follow and projectile helpers. domain_9_value_6 -> SANDMOUSE_STATE_FADE_OUT: 0030eb04..0030eb68 clears velocity, initializes the fade timer, releases voice and stores 6 to sandmouse state +0x20. The local switch names this exact selector value FADE_OUT, reducing alpha and emitting particles. --- src/overlays/shared/enemies/sandmouse.c | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/overlays/shared/enemies/sandmouse.c b/src/overlays/shared/enemies/sandmouse.c index 3099707c5f..e682ad5c0f 100644 --- a/src/overlays/shared/enemies/sandmouse.c +++ b/src/overlays/shared/enemies/sandmouse.c @@ -547,7 +547,7 @@ void sandmouse_update(Moby *sandmouse_moby) { if (sandmouse_vars == 0) return; if (sandmouse_vars->link != -1) { - if (sandmouse_moby->state >= 5) { + if (sandmouse_moby->state >= SANDMOUSE_STATE_FOLLOW_HERO_AND_FIRE) { *(f32 *)LNK(sandmouse_vars->link)->pvars = fast_arc_tan(sandmouse_moby->pos.x - LNK(sandmouse_vars->link)->pos.x, sandmouse_moby->pos.y - LNK(sandmouse_vars->link)->pos.y); @@ -561,7 +561,7 @@ void sandmouse_update(Moby *sandmouse_moby) { LNK(sandmouse_vars->link)->collision = 0; } } - if (sandmouse_moby->state >= 3) { + if (sandmouse_moby->state >= SANDMOUSE_STATE_MOVE_TO_GOAL) { if (big_head_cheat_enabled != 0) { if (*((u8 *)sandmouse_vars + 0x91) == 0) { attach_manipulator(sandmouse_moby, 5, (u8 *)sandmouse_vars + 0x90); @@ -620,7 +620,7 @@ void sandmouse_update(Moby *sandmouse_moby) { D_L01_001DEB38_lui.unk44 = frame_time * 11.519173f; D_L01_001DEB38_lui.unk48 = scale_game_frames(4); D_L01_001DEB38_lui.unk28 = 3.1415927f; - sandmouse_moby->state = 1; + sandmouse_moby->state = SANDMOUSE_STATE_WAIT_FOR_ACTIVATION; sandmouse_moby->draw_dist = 0; break; case SANDMOUSE_STATE_WAIT_FOR_ACTIVATION: @@ -682,13 +682,13 @@ void sandmouse_update(Moby *sandmouse_moby) { set_hero_animation((float)scale_game_frames(6), 0, 0); if (sandmouse_vars->link != -1) { LNK(sandmouse_vars->link)->command = 5; - sandmouse_moby->state = 2; + sandmouse_moby->state = SANDMOUSE_STATE_WAIT_FOR_LINK; } else { sandmouse_moby->draw_dist = 0xFF; if (sandmouse_moby->prev_seq != 0) { blend_moby_animation(sandmouse_moby, 0, 0, scale_game_frames(10)); } - sandmouse_moby->state = 3; + sandmouse_moby->state = SANDMOUSE_STATE_MOVE_TO_GOAL; } } } @@ -699,7 +699,7 @@ void sandmouse_update(Moby *sandmouse_moby) { if (sandmouse_moby->prev_seq != 0) { blend_moby_animation(sandmouse_moby, 0, 0, scale_game_frames(10)); } - sandmouse_moby->state = 3; + sandmouse_moby->state = SANDMOUSE_STATE_MOVE_TO_GOAL; sandmouse_vars->timer = 0; sandmouse_moby->draw_dist = 0xFF; } @@ -713,7 +713,7 @@ void sandmouse_update(Moby *sandmouse_moby) { sandmouse_vars->slot = allocate_voice_for_target_entry(1, 4, (struct VoiceTarget *)sandmouse_moby); } - sandmouse_moby->state = 3; + sandmouse_moby->state = SANDMOUSE_STATE_MOVE_TO_GOAL; } break; case SANDMOUSE_STATE_MOVE_TO_GOAL: { @@ -753,7 +753,7 @@ void sandmouse_update(Moby *sandmouse_moby) { blend_moby_animation(sandmouse_moby, 2, 0, scale_game_frames(10)); } qzero(&sandmouse_vars->vel); - sandmouse_moby->state = 4; + sandmouse_moby->state = SANDMOUSE_STATE_BEGIN_FOLLOW_HERO_AND_FIRE; sandmouse_vars->timer = scale_game_frames(0x78); } if (sandmouse_moby->anim_flags & 2) { @@ -778,7 +778,7 @@ void sandmouse_update(Moby *sandmouse_moby) { if (sandmouse_vars->link != -1) { LNK(sandmouse_vars->link)->flags &= 0xFFBE; } - sandmouse_moby->state = 5; + sandmouse_moby->state = SANDMOUSE_STATE_FOLLOW_HERO_AND_FIRE; break; case SANDMOUSE_STATE_FOLLOW_HERO_AND_FIRE: { char *v = VOICE(sandmouse_vars->slot); @@ -821,7 +821,7 @@ void sandmouse_update(Moby *sandmouse_moby) { } sandmouse_vars->slot = -1; allocate_voice_for_target_entry(2, 0, (struct VoiceTarget *)sandmouse_moby); - sandmouse_moby->state = 6; + sandmouse_moby->state = SANDMOUSE_STATE_FADE_OUT; if (sandmouse_vars->link != -1) { LNK(sandmouse_vars->link)->command = 5; } @@ -842,7 +842,7 @@ void sandmouse_update(Moby *sandmouse_moby) { qcopy(&sandmouse_moby->pos, &sandmouse_vars->a30); qcopy(sandmouse_vars, &sandmouse_vars->a30); qzero(&sandmouse_vars->vel); - sandmouse_moby->state = 7; + sandmouse_moby->state = SANDMOUSE_STATE_RESET; sandmouse_moby->flags &= 0xFDFF; } else { Vec4 pos; @@ -905,13 +905,13 @@ void sandmouse_update(Moby *sandmouse_moby) { blend_moby_animation(sandmouse_moby, 0, 0, scale_game_frames(6)); } LNK(sandmouse_vars->link)->command = 1; - sandmouse_moby->state = 1; + sandmouse_moby->state = SANDMOUSE_STATE_WAIT_FOR_ACTIVATION; sandmouse_moby->draw_dist = 0; break; case 8: break; } - if (sandmouse_moby->state >= 2) { + if (sandmouse_moby->state >= SANDMOUSE_STATE_WAIT_FOR_LINK) { jet_animate(sandmouse_moby, 0.3f); ((void (*)(void *, void *))emit_sandmouse_particles)(sandmouse_moby, sandmouse_vars); } From 76b9b954fb624954259b13bc784893b15aad9c26 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:23:33 +0000 Subject: [PATCH 0270/1502] decomp: clarify names in mine_update domain_0_value_0 -> MINE_STATE_OWNER_ATTACHED: Authoritative mine.c SHA-256 6703a24669f18c981a3cfe8fdb760c91fc8393bdbf0f82a0d55e730f3119fda1 and original Ghidra agree: state byte mine+0x20 is tested against zero at 0x002aa784-0x002aa788, 0x002aa7c0-0x002aa7c4 and 0x002aa7d8-0x002aa7dc. The same byte at 0x002aa890-0x002aa894 selects the owner-bone attachment path: 0x002aa8e4-0x002aa90c composes owner bone zero with the mine attachment rotation and copies into mine+0xc0, then returns without free motion. Thus zero is the owner-attached mine state, not hero idle. domain_10_value_1 -> MINE_DEBRIS_FIXED_LIFETIME: The source comparison kind==1 uses the very same kind selected by random_integer_below(4) and dispatched by switch(kind), whose case 1 is already MINE_DEBRIS_FIXED_LIFETIME. Retail 0x002ac338-0x002ac348 saves the selector in s0; 0x002ac418 tests s0 against 1 to choose radius upper bound 0.5 rather than 0.25. The unchanged s0 is dispatched at 0x002ac4c0 to 0x002ac578, where 0x002ac5c0-0x002ac5e4 requests fixed 180 scaled frames for mine_debris. Reuse the existing canonical member for this identical selector. domain_1_value_0 -> MINE_STATE_OWNER_ATTACHED: Authoritative mine.c SHA-256 6703a24669f18c981a3cfe8fdb760c91fc8393bdbf0f82a0d55e730f3119fda1 and original Ghidra agree: state byte mine+0x20 is tested against zero at 0x002aa784-0x002aa788, 0x002aa7c0-0x002aa7c4 and 0x002aa7d8-0x002aa7dc. The same byte at 0x002aa890-0x002aa894 selects the owner-bone attachment path: 0x002aa8e4-0x002aa90c composes owner bone zero with the mine attachment rotation and copies into mine+0xc0, then returns without free motion. Thus zero is the owner-attached mine state, not hero idle. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The supplied source explicitly reads hero.vehicle_mode, the selector owned by shared HeroVehicleMode in include/rnc/hero/hero_state.h. Retail 0x002aa734 establishes hero at 0x0013f350; 0x002aa7cc loads its byte +0x20a4, 0x002aa7d0 tests zero, and nonzero removes an owner-attached mine. This is the hero vehicle selector, separate from mine+0x20 and hero state IDs; reuse canonical HERO_VEHICLE_MODE_ON_FOOT=0. domain_3_value_0 -> MINE_STATE_OWNER_ATTACHED: Authoritative mine.c SHA-256 6703a24669f18c981a3cfe8fdb760c91fc8393bdbf0f82a0d55e730f3119fda1 and original Ghidra agree: state byte mine+0x20 is tested against zero at 0x002aa784-0x002aa788, 0x002aa7c0-0x002aa7c4 and 0x002aa7d8-0x002aa7dc. The same byte at 0x002aa890-0x002aa894 selects the owner-bone attachment path: 0x002aa8e4-0x002aa90c composes owner bone zero with the mine attachment rotation and copies into mine+0xc0, then returns without free motion. Thus zero is the owner-attached mine state, not hero idle. domain_4_value_1 -> MINE_STATE_FREE_MOTION: Source and original Ghidra show mine state at mine+0x20 as a separate mine domain. Retail 0x002ab2f0-0x002ab354, 0x002ab3c8-0x002ab424 and 0x002ab460-0x002ab4c4 reset that byte to 1 when surface attachment cannot be maintained, ground is too far below, or the homing target is invalid. These paths clear vertical velocity, release the voice and restart the 120-frame timer; the assignment clears attachment bit 4 and homing bit 0x10. At 0x002aa944-0x002aa98c, a nonzero mine state lacking bit 4 integrates velocity and applies gravity. Thus exact state 1 is MINE_STATE_FREE_MOTION. The collision comparison at 0x002aad4c-0x002aad80 avoids repositioning this exact free-motion state; this is not HERO_STATE_LOOK. domain_5_value_1 -> MINE_STATE_FREE_MOTION: Source and original Ghidra show mine state at mine+0x20 as a separate mine domain. Retail 0x002ab2f0-0x002ab354, 0x002ab3c8-0x002ab424 and 0x002ab460-0x002ab4c4 reset that byte to 1 when surface attachment cannot be maintained, ground is too far below, or the homing target is invalid. These paths clear vertical velocity, release the voice and restart the 120-frame timer; the assignment clears attachment bit 4 and homing bit 0x10. At 0x002aa944-0x002aa98c, a nonzero mine state lacking bit 4 integrates velocity and applies gravity. Thus exact state 1 is MINE_STATE_FREE_MOTION. The collision comparison at 0x002aad4c-0x002aad80 avoids repositioning this exact free-motion state; this is not HERO_STATE_LOOK. domain_6_value_1 -> MINE_STATE_FREE_MOTION: Source and original Ghidra show mine state at mine+0x20 as a separate mine domain. Retail 0x002ab2f0-0x002ab354, 0x002ab3c8-0x002ab424 and 0x002ab460-0x002ab4c4 reset that byte to 1 when surface attachment cannot be maintained, ground is too far below, or the homing target is invalid. These paths clear vertical velocity, release the voice and restart the 120-frame timer; the assignment clears attachment bit 4 and homing bit 0x10. At 0x002aa944-0x002aa98c, a nonzero mine state lacking bit 4 integrates velocity and applies gravity. Thus exact state 1 is MINE_STATE_FREE_MOTION. The collision comparison at 0x002aad4c-0x002aad80 avoids repositioning this exact free-motion state; this is not HERO_STATE_LOOK. domain_7_value_1 -> MINE_STATE_FREE_MOTION: Source and original Ghidra show mine state at mine+0x20 as a separate mine domain. Retail 0x002ab2f0-0x002ab354, 0x002ab3c8-0x002ab424 and 0x002ab460-0x002ab4c4 reset that byte to 1 when surface attachment cannot be maintained, ground is too far below, or the homing target is invalid. These paths clear vertical velocity, release the voice and restart the 120-frame timer; the assignment clears attachment bit 4 and homing bit 0x10. At 0x002aa944-0x002aa98c, a nonzero mine state lacking bit 4 integrates velocity and applies gravity. Thus exact state 1 is MINE_STATE_FREE_MOTION. The collision comparison at 0x002aad4c-0x002aad80 avoids repositioning this exact free-motion state; this is not HERO_STATE_LOOK. domain_8_value_1 -> MINE_HOMING_RISE_PHASE: Source mode is loaded from v->h52, not mine_moby->state. Retail 0x002ab5ac loads private-data+0x52 and compares 1 at 0x002ab5b4. At 0x002ab5bc-0x002ab5e4 it adds frame_scale*0.05 to mine+0x18. Timer expiry at 0x002ab5f0-0x002ab604 reloads seven scaled frames and stores phase 2. Target acquisition initializes phase 1 at 0x002abb0c-0x002abb20. This proves a rising phase of the homing vertical movement. domain_9_value_2 -> MINE_HOMING_FALL_PHASE: Source mode is the snapshot of private-data v->h52; retail 0x002ab5ac loads +0x52 and 0x002ab608 selects value 2. At 0x002ab610-0x002ab638 this branch subtracts frame_scale*0.05 from mine position Z at +0x18. Timer expiry clears +0x52 at 0x002ab63c-0x002ab640. It follows the rising phase's timed transition at 0x002ab5f0-0x002ab604, proving the homing fall phase in a separate domain from mine state. --- src/overlays/shared/weapons/mine.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/overlays/shared/weapons/mine.c b/src/overlays/shared/weapons/mine.c index 5da59b02e4..63e34d1d02 100644 --- a/src/overlays/shared/weapons/mine.c +++ b/src/overlays/shared/weapons/mine.c @@ -619,6 +619,12 @@ void mine_update(M910 *mine_moby) { MINE_DEBRIS_SHORT_LIVED = 2, MINE_DEBRIS_SPHERICAL_VELOCITY = 3 }; + enum { + MINE_STATE_OWNER_ATTACHED = 0, + MINE_STATE_FREE_MOTION = 1, + MINE_HOMING_RISE_PHASE = 1, + MINE_HOMING_FALL_PHASE = 2 + }; B910 camera_blast_parameters = l00_mine_camera_blast_parameters; B910 alternate_camera_blast_parameters = l00_mine_alternate_camera_blast_parameters; U910 collision_response_velocity; @@ -635,17 +641,17 @@ void mine_update(M910 *mine_moby) { up.f[2] = 1.0f; collision_response_velocity.q = mine_pre_motion_position.q; v = mine_moby->v; - if ((hero.unk20A5 != 0 || hero.unk20AF != 0) && mine_moby->state == 0) { + if ((hero.unk20A5 != 0 || hero.unk20AF != 0) && mine_moby->state == MINE_STATE_OWNER_ATTACHED) { mine_moby->flags |= 0x41; } else { mine_moby->flags &= 0xFFBE; } if ((hero.items[0].moby == 0 || ((M910 *)hero.items[0].moby)->cls != 0xBE) && - mine_moby->state == 0) { + mine_moby->state == MINE_STATE_OWNER_ATTACHED) { mark_moby_for_removal(mine_moby); return; } - if (hero.vehicle_mode != 0 && mine_moby->state == 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && mine_moby->state == MINE_STATE_OWNER_ATTACHED) { mark_moby_for_removal(mine_moby); return; } @@ -775,7 +781,7 @@ void mine_update(M910 *mine_moby) { coll_hit.moby->cls != mine_moby->cls && coll_hit.moby != hero.moby && coll_hit.moby != v->owner) { mine_moby->bBC = 1; - if (mine_moby->state != 1) { + if (mine_moby->state != MINE_STATE_FREE_MOTION) { qcopy(&mine_moby->pos, &coll_hit.pos); mine_moby->pos.f[2] = probe_ground_height(&mine_moby->pos, 0, 0.5f); } @@ -890,7 +896,7 @@ void mine_update(M910 *mine_moby) { if (hd == 0) { int s; - mine_moby->state = 1; + mine_moby->state = MINE_STATE_FREE_MOTION; s = v->i68; if (s != -1) { char *tab = ((char *)&voice_pool); @@ -917,7 +923,7 @@ void mine_update(M910 *mine_moby) { } else { int s; - mine_moby->state = 1; + mine_moby->state = MINE_STATE_FREE_MOTION; s = v->i68; if (s != -1) { char *tab = ((char *)&voice_pool); @@ -938,7 +944,7 @@ void mine_update(M910 *mine_moby) { (mine_moby->state & 0x10)) { int s; - mine_moby->state = 1; + mine_moby->state = MINE_STATE_FREE_MOTION; s = v->i68; if (s != -1) { char *tab = ((char *)&voice_pool); @@ -982,13 +988,13 @@ void mine_update(M910 *mine_moby) { v->f40 = max_homing_step; } mode = v->h52; - if (mode == 1) { + if (mode == MINE_HOMING_RISE_PHASE) { mine_moby->pos.f[2] += frame_scale * 0.05f; if (fast_dec_timer(&v->i48) != 0) { v->i48 = scale_game_frames(7); v->h52 = 2; } - } else if (mode == 2) { + } else if (mode == MINE_HOMING_FALL_PHASE) { mine_moby->pos.f[2] -= frame_scale * 0.05f; if (fast_dec_timer(&v->i48) != 0) { v->h52 = 0; @@ -1316,7 +1322,7 @@ void mine_update(M910 *mine_moby) { r[1] = random_float_between(frame_time * -0.5f, frame_time * 0.5f) * sc; r[2] = random_float_between(frame_time * 4.0f, tbl[kind]) * sc; *(OvlQuad *)n = *(OvlQuad *)r; - rr = random_float_between(0.0f, kind == 1 ? 0.5f : 0.25f) * sc; + rr = random_float_between(0.0f, kind == MINE_DEBRIS_FIXED_LIFETIME ? 0.5f : 0.25f) * sc; ang = random_angle_radians(); r[0] = fast_cos(ang) * rr; r[1] = fast_sin(ang) * rr; From 9ec24414527f550b021f712c0b51f1c54fbef3f8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:23:33 +0000 Subject: [PATCH 0271/1502] decomp: clarify names in horny_toad_update domain_0_value_254 -> MOBY_STATE_MARKED_FOR_REMOVAL: Assigned retail 002d4884-002d4894 resolves followed_moby from moby_table with stride 0x100; 002d48a0-002d48a4 reads that Moby's state at +0x20 and rejects 0xFE. Checked direct helper mark_moby_for_removal (request 264e597784a24d1090e7a4060b94dbf2) uses a0 as the Moby, selects 0xFE at 0024eb8c and stores it to the identical +0x20 state field at 0024eb90. Assigned terminal path 002d501c-002d5064 ends by calling that established removal helper. Thus this constant denotes a Moby marked for removal, not the horny-toad DYING=12 animation state. The alternate 0xFD marker's distinct subtype is left unresolved. --- src/overlays/shared/enemies/horny_toad.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/horny_toad.c b/src/overlays/shared/enemies/horny_toad.c index 888cb51d2d..47920e0cfc 100644 --- a/src/overlays/shared/enemies/horny_toad.c +++ b/src/overlays/shared/enemies/horny_toad.c @@ -190,6 +190,9 @@ void horny_toad_update(Moby *moby) { HORNY_TOAD_RECOVER_FROM_REACTION = 11, HORNY_TOAD_DYING = 12 }; + enum { + MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE + }; ToadVars *horny_toad_vars; Moby *target; ToadVec reference_point_or_movement_endpoint; @@ -256,7 +259,7 @@ void horny_toad_update(Moby *moby) { break; case HORNY_TOAD_FACE_FOLLOW_MOBY: { Moby *followed_moby = (Moby *)(moby_table + (horny_toad_vars->follow_moby << 8)); - if (followed_moby != 0 && followed_moby->state != 0xFE && followed_moby->state != 0xFD) { + if (followed_moby != 0 && followed_moby->state != MOBY_STATE_MARKED_FOR_REMOVAL && followed_moby->state != 0xFD) { approach_angle( &moby->rot.z, fast_arc_tan((*(ToadVec *)&followed_moby->pos)[0] - (*(ToadVec *)&moby->pos)[0], From 2922ec5649749ee6cf35c5cb0fc5579419814051 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:25:39 +0000 Subject: [PATCH 0272/1502] decomp: clarify names in transport_pod_update domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 002de41c establishes hero base 0x0013f350, checks hero.ground_moby at +0x2fc (002de424) and air_frames at +0x30e (002de430), then loads the byte at +0x20a4 = 0x001413f4 (002de43c) and rejects nonzero at 002de440. Authoritative C identifies exactly this byte as hero.vehicle_mode == 0. Thus the selector belongs to supplied HeroVehicleMode, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT; the grounded on-foot rider then starts the pose/camera request. This is not the hero current-state selector. domain_1_value_2 -> HERO_TARGET_POSE_STATUS_READY: Retail 002de630 calls get_hero_target_pose_status at checked level-02 helper 00237430; 002de638-002de640 compares its returned v0 with 2. Helper instructions 00237434-00237474 map hero state 0x65/0x66 to pending return 1, state 0x67 to return 2, and all others to 0. At 002de650 the value-2 branch enters established departure-rail state 7 and at 002de664-002de66c requests hero state 0x72. Thus 2 is the target-pose ready status permitting departure, not a HeroStateId member. domain_2_value_0 -> HERO_TARGET_POSE_STATUS_INACTIVE: Checked helper 00237430 returns 0 at 00237470-00237474 for hero states outside 0x65/0x66/0x67; these states instead produce pending 1 or ready 2. Retail caller 002de678 tests that same returned status against zero: zero calls jet_end_mount(2) at 002de680-002de684 and selects established rider-leave state 13 at 002de690-002de694. Nonzero pending status instead waits on ride_timer. Thus zero means the requested target-pose sequence is inactive, not HERO_STATE_IDLE or a vehicle mode. --- src/overlays/l02/mobys/transport_pod.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l02/mobys/transport_pod.c b/src/overlays/l02/mobys/transport_pod.c index 22abfc49b2..24a07c7dbe 100644 --- a/src/overlays/l02/mobys/transport_pod.c +++ b/src/overlays/l02/mobys/transport_pod.c @@ -110,7 +110,7 @@ void transport_pod_update(unsigned char *moby) { TRANSPORT_POD_POSITION_RAILS_FROM_CONFIGURED_OFFSETS = 15, TRANSPORT_POD_CYCLE_RAILS_TO_SPLIT_HEIGHTS = 16, TRANSPORT_POD_CYCLE_RAILS_TO_SHARED_LOWER_HEIGHT = 17 - }; + } ; enum { HERO_TARGET_POSE_STATUS_INACTIVE = 0 , HERO_TARGET_POSE_STATUS_READY = 2}; Varsdc88 *transport_pod_vars = ((Varsdc88 *)MOBY(moby)->pvars); int i; int *path; @@ -259,7 +259,7 @@ void transport_pod_update(unsigned char *moby) { MOBY(moby)->state = 3; allocate_voice_for_target_entry(1, 0, moby); } else if ((unsigned char *)hero.ground_moby == (struct Moby *)moby && - hero.air_frames.s == 0 && hero.vehicle_mode == 0) { + hero.air_frames.s == 0 && hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { qcopy(&camera_target_or_hero_position_or_rotation, moby + 0x10); camera_target_or_hero_position_or_rotation.f[2] += 2.0f; if (MOBY(moby)->command == 0) { @@ -321,11 +321,11 @@ void transport_pod_update(unsigned char *moby) { break; case TRANSPORT_POD_WAIT_FOR_RIDER_READY_FOR_DEPARTURE: { int rider_readiness_status = get_hero_target_pose_status(); - if (rider_readiness_status == 2) { + if (rider_readiness_status == HERO_TARGET_POSE_STATUS_READY) { MOBY(moby)->state = 7; allocate_voice_for_target_entry(2, 0, moby); hero_set_state(0x72, 0); - } else if (rider_readiness_status == 0) { + } else if (rider_readiness_status == HERO_TARGET_POSE_STATUS_INACTIVE) { jet_end_mount(2); MOBY(moby)->state = 0xD; } else if (fast_dec_timer(&transport_pod_vars->ride_timer)) { From 1c6b50171d47d141e00fc821e6f53706fe754016 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:25:39 +0000 Subject: [PATCH 0273/1502] decomp: clarify names in sharkigator_update domain_0_value_0 -> WALKER_TARGET_HERO: Retail 0030f740..0030f784 copies the hero moby from 0013f3d0+0x2000 and four hero vectors into the WalkerTarget at sp+0x20, then stores zero at sp+0x64 (target.kind). Current C selects this branch when hero XY distance is below 30; this is the hero target kind, a separate domain from sharkigator state zero. domain_10_value_255 -> SHARKIGATOR_WATER_GAP_TRANSITION_NONE: Retail 00310ca4..00310cb0 tests next_state in s5 against 0xFF and bypasses transition application on equality. Retail 0030f7ec..0030f814 replaces s5 from the water-gap transition-state table only on a changed classifier result; 00310cb4..00310cd0 blends the paired sequence and writes s5 to moby+0x20 only for a non-sentinel value. Thus 255 means no water-gap transition, not an active moby state. domain_1_value_2 -> WALKER_TARGET_NONE: Retail 0030f788..0030f7b0 clears target.moby at sp+0x60 and all four target vectors, then stores 2 at sp+0x64 (target.kind) when the hero is outside the 30-unit range. The original Ghidra and authoritative C agree this record has no target; 2 is not SHARKIGATOR_SWIM_WANDER here. domain_2_value_255 -> SHARKIGATOR_WATER_GAP_TRANSITION_NONE: Retail 0030f7e0 initializes s5 (next_state) to 0xFF. Retail 0030f7ec..0030f814 replaces s5 from the water-gap transition-state table only on a changed classifier result; 00310cb4..00310cd0 blends the paired sequence and writes s5 to moby+0x20 only for a non-sentinel value. Thus 255 means no water-gap transition, not an active moby state. domain_3_value_255 -> SHARKIGATOR_WATER_GAP_TRANSITION_NONE: Retail 0030fc7c..0030fc88 tests next_state in s5 against 0xFF and bypasses transition application on equality. Retail 0030f7ec..0030f814 replaces s5 from the water-gap transition-state table only on a changed classifier result; 00310cb4..00310cd0 blends the paired sequence and writes s5 to moby+0x20 only for a non-sentinel value. Thus 255 means no water-gap transition, not an active moby state. domain_4_value_255 -> SHARKIGATOR_WATER_GAP_TRANSITION_NONE: Retail 0030ff44..0030ff50 tests next_state in s5 against 0xFF and bypasses transition application on equality. Retail 0030f7ec..0030f814 replaces s5 from the water-gap transition-state table only on a changed classifier result; 00310cb4..00310cd0 blends the paired sequence and writes s5 to moby+0x20 only for a non-sentinel value. Thus 255 means no water-gap transition, not an active moby state. domain_5_value_255 -> SHARKIGATOR_WATER_GAP_TRANSITION_NONE: Retail 00310188..00310194 tests next_state in s5 against 0xFF and bypasses transition application on equality. Retail 0030f7ec..0030f814 replaces s5 from the water-gap transition-state table only on a changed classifier result; 00310cb4..00310cd0 blends the paired sequence and writes s5 to moby+0x20 only for a non-sentinel value. Thus 255 means no water-gap transition, not an active moby state. domain_6_value_255 -> SHARKIGATOR_WATER_GAP_TRANSITION_NONE: Retail 003104d8..003104e4 tests next_state in s5 against 0xFF and bypasses transition application on equality. Retail 0030f7ec..0030f814 replaces s5 from the water-gap transition-state table only on a changed classifier result; 00310cb4..00310cd0 blends the paired sequence and writes s5 to moby+0x20 only for a non-sentinel value. Thus 255 means no water-gap transition, not an active moby state. domain_7_value_255 -> SHARKIGATOR_WATER_GAP_TRANSITION_NONE: Retail 003105fc..00310608 tests next_state in s5 against 0xFF and bypasses transition application on equality. Retail 0030f7ec..0030f814 replaces s5 from the water-gap transition-state table only on a changed classifier result; 00310cb4..00310cd0 blends the paired sequence and writes s5 to moby+0x20 only for a non-sentinel value. Thus 255 means no water-gap transition, not an active moby state. domain_8_value_255 -> SHARKIGATOR_WATER_GAP_TRANSITION_NONE: Retail 0031082c..00310838 tests next_state in s5 against 0xFF and bypasses transition application on equality. Retail 0030f7ec..0030f814 replaces s5 from the water-gap transition-state table only on a changed classifier result; 00310cb4..00310cd0 blends the paired sequence and writes s5 to moby+0x20 only for a non-sentinel value. Thus 255 means no water-gap transition, not an active moby state. domain_9_value_255 -> SHARKIGATOR_WATER_GAP_TRANSITION_NONE: Retail 00310aa8..00310ab4 tests next_state in s5 against 0xFF and bypasses transition application on equality. Retail 0030f7ec..0030f814 replaces s5 from the water-gap transition-state table only on a changed classifier result; 00310cb4..00310cd0 blends the paired sequence and writes s5 to moby+0x20 only for a non-sentinel value. Thus 255 means no water-gap transition, not an active moby state. --- src/overlays/l07/mobys/sharkigator.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/overlays/l07/mobys/sharkigator.c b/src/overlays/l07/mobys/sharkigator.c index 0d4b4f9b16..02d85c46fe 100644 --- a/src/overlays/l07/mobys/sharkigator.c +++ b/src/overlays/l07/mobys/sharkigator.c @@ -780,6 +780,11 @@ void sharkigator_update(unsigned char *moby) { SHARKIGATOR_DAMPED_GRAVITY_RECOVERY = 16, SHARKIGATOR_DAMPED_RECOVERY = 17 }; + enum { + WALKER_TARGET_HERO = 0, + WALKER_TARGET_NONE = 2, + SHARKIGATOR_WATER_GAP_TRANSITION_NONE = 0xFF + }; char *sharkigator_instance_vars; struct WalkerTarget target; float point[4]; @@ -829,14 +834,14 @@ void sharkigator_update(unsigned char *moby) { qcopy(&target.q10, hero + 0x10); qcopy(&target.q20, hero + 0x40); qcopy(&target.q30, hero + 0x50); - target.kind = 0; + target.kind = WALKER_TARGET_HERO; } else { target.moby = 0; qzero(&target.pos); qzero(&target.q10); qzero(&target.q30); qzero(&target.q20); - target.kind = 2; + target.kind = WALKER_TARGET_NONE; } } if (*(int *)(sharkigator_instance_vars + 0x110) != 0) { @@ -844,7 +849,7 @@ void sharkigator_update(unsigned char *moby) { FUN_L00_00259740(moby + 0x10, path + 0x10, *(int *)path); } old_command = moby[0xBC]; - next_state = 0xFF; + next_state = SHARKIGATOR_WATER_GAP_TRANSITION_NONE; next_sequence = 0xFF; moby[0xBC] = classify_sharkigator_water_height_gap((char *)moby, sharkigator_instance_vars); command = moby[0xBC]; @@ -935,7 +940,7 @@ void sharkigator_update(unsigned char *moby) { frame_time_sq * 15.0f, frame_time_sq * 50.0f, frame_time * 8.0f); - if (next_state != 0xFF) { + if (next_state != SHARKIGATOR_WATER_GAP_TRANSITION_NONE) { if (moby[0x53] != next_sequence) { blend_moby_animation(moby, next_sequence, 0, 6); } @@ -1007,7 +1012,7 @@ void sharkigator_update(unsigned char *moby) { frame_time_sq * 15.0f, frame_time_sq * 50.0f, frame_time * 8.0f); - if (next_state != 0xFF) { + if (next_state != SHARKIGATOR_WATER_GAP_TRANSITION_NONE) { if (moby[0x53] != next_sequence) { blend_moby_animation(moby, next_sequence, 0, 6); } @@ -1078,7 +1083,7 @@ void sharkigator_update(unsigned char *moby) { } moby[0x20] = 2; } - if (next_state != 0xFF) { + if (next_state != SHARKIGATOR_WATER_GAP_TRANSITION_NONE) { if (moby[0x53] != next_sequence) { blend_moby_animation(moby, next_sequence, 0, 6); } @@ -1171,7 +1176,7 @@ void sharkigator_update(unsigned char *moby) { if ((moby[0x70] & 2) && moby[0x53] != 1) { blend_moby_animation(moby, 1, 0, 10); } - if (next_state != 0xFF) { + if (next_state != SHARKIGATOR_WATER_GAP_TRANSITION_NONE) { if (moby[0x53] != next_sequence) { blend_moby_animation(moby, next_sequence, 0, 6); } @@ -1202,7 +1207,7 @@ void sharkigator_update(unsigned char *moby) { fast_vec_scale( sharkigator_instance_vars + 0xD0, sharkigator_instance_vars + 0xD0, 0.5f); } - if (next_state != 0xFF) { + if (next_state != SHARKIGATOR_WATER_GAP_TRANSITION_NONE) { if (moby[0x53] != next_sequence) { blend_moby_animation(moby, next_sequence, 0, 6); } @@ -1263,7 +1268,7 @@ void sharkigator_update(unsigned char *moby) { fast_vec_scale( sharkigator_instance_vars + 0xD0, sharkigator_instance_vars + 0xD0, 0.5f); } - if (next_state != 0xFF) { + if (next_state != SHARKIGATOR_WATER_GAP_TRANSITION_NONE) { if (moby[0x53] != next_sequence) { blend_moby_animation(moby, next_sequence, 0, 6); } @@ -1331,7 +1336,7 @@ void sharkigator_update(unsigned char *moby) { *(int *)(sharkigator_instance_vars + 0x134) = rand() % 200 + 300; moby[0x20] = 8; } - if (next_state != 0xFF) { + if (next_state != SHARKIGATOR_WATER_GAP_TRANSITION_NONE) { if (moby[0x53] != next_sequence) { blend_moby_animation(moby, next_sequence, 0, 6); } @@ -1399,7 +1404,7 @@ void sharkigator_update(unsigned char *moby) { F(sharkigator_instance_vars, 0xD8) -= frame_time * 9.8f; move_moby_with_collision_integer_radius( (int)moby, (int)(sharkigator_instance_vars + 0xD0), 0x400, 0x10, 1.0f, 0.0f); - if (next_state != 0xFF) { + if (next_state != SHARKIGATOR_WATER_GAP_TRANSITION_NONE) { if (moby[0x53] != next_sequence) { blend_moby_animation(moby, next_sequence, 0, 6); } From 4c15bbc1abaec37359a1aa921d114d9da5e9c406 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:25:39 +0000 Subject: [PATCH 0274/1502] decomp: clarify names in update_batalia_cannon domain_0_value_4 -> CANNON_UNMOUNTED_IDLE: Retail 0x002e0420 tests cannon health at s4+0x58; zero health calls jet_end_mount at 0x002e0438 and stores 4 into the assigned cannon s5+0x20 at 0x002e0448. This is the same moby->state selector whose existing CANNON_UNMOUNTED_IDLE branch bypasses mounted processing at 0x002e0788. domain_1_value_4 -> CANNON_UNMOUNTED_IDLE: Retail manual dismount clears hero interaction, calls hero_set_state(0,1) at 0x002e0578 and jet_end_mount at 0x002e05e4, then stores 4 into cannon s5+0x20 at 0x002e060c. Source assigns moby->state in this exit path, sharing the existing CANNON_UNMOUNTED_IDLE switch domain. domain_2_value_5 -> CANNON_MOUNTED_CONTROL: Retail 0x002e0610 loads state from cannon s5+0x20, 0x002e0614 loads 5 and 0x002e0618 skips jet_mount if already equal. Otherwise 0x002e0634 mounts using this cannon's position and rotation. This compares the same moby->state consumed by existing CANNON_MOUNTED_CONTROL, not hero state or command. domain_3_value_5 -> CANNON_MOUNTED_CONTROL: Retail 0x002e0614 establishes s0=5 and 0x002e063c stores s0 into cannon s5+0x20 after optional jet_mount. Dispatch at 0x002e07a8 selects mounted aim/fire/wave processing at 0x002e08c8. Source moby->state assignment therefore reuses its existing CANNON_MOUNTED_CONTROL member. domain_4_value_4 -> CANNON_UNMOUNTED_IDLE: In the cannon initialization branch, retail dispatch 0x002e0784 sets a0=4 and 0x002e07c8 stores it into s5+0x20 before initializing health, visual and timers. The identical cannon state field dispatches state 4 directly to attachment maintenance at 0x002e0788, matching existing CANNON_UNMOUNTED_IDLE. domain_5_value_4 -> CANNON_UNMOUNTED_IDLE: The all-indexed-targets-inactive completion branch calls jet_end_mount at 0x002e11e0, sets v1=4 at 0x002e11e8 and stores it into cannon s5+0x20 at 0x002e11f0, then returns the hero to the platform. This moby->state is the outer cannon domain, so reuse CANNON_UNMOUNTED_IDLE rather than the equal-valued target-count constant. --- src/overlays/l08/mobys/batalia_cannon.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l08/mobys/batalia_cannon.c b/src/overlays/l08/mobys/batalia_cannon.c index 40ace09f83..1e65b9fc01 100644 --- a/src/overlays/l08/mobys/batalia_cannon.c +++ b/src/overlays/l08/mobys/batalia_cannon.c @@ -754,7 +754,7 @@ void batalia_cannon_update(Moby *moby) { (*(float(*)[4]) & moby->rot)[1] = 0.0f; moby->command = 2; jet_end_mount(0); - moby->state = 4; + moby->state = CANNON_UNMOUNTED_IDLE; node = (Moby *)(D_L08_0015FFD8 + (cannon_control_vars->platform_index << 8)); qcopy(direction, (*(float(*)[4]) & node->rot)); direction[2] = fast_add_rotations(direction[2], 3.1415927f); @@ -782,15 +782,15 @@ void batalia_cannon_update(Moby *moby) { func_L00_00217718_2E16A0(work, direction, 0, 1); jet_end_mount(0); hero.motion.rot.f[2] = fast_add_rotations(hero.motion.rot.f[2], 3.1415927f); - moby->state = 4; + moby->state = CANNON_UNMOUNTED_IDLE; } else { int *indices; int count; - if (moby->state != 5) { + if (moby->state != CANNON_MOUNTED_CONTROL) { cannon_control_vars->camera_timer = 2; jet_mount((*(float(*)[4]) & moby->pos), (*(float(*)[4]) & moby->rot), 1, 0, 0); } - moby->state = 5; + moby->state = CANNON_MOUNTED_CONTROL; { int waiting = 2, activated = 3; indices = cannon_control_vars->indices; @@ -819,7 +819,7 @@ void batalia_cannon_update(Moby *moby) { Moby *node; int *indices; int count; - moby->state = 4; + moby->state = CANNON_UNMOUNTED_IDLE; cannon_control_vars->health = 200; cannon_control_vars->range = 10.0f; node = create_moby(0x710); @@ -1048,7 +1048,7 @@ void batalia_cannon_update(Moby *moby) { (*(float(*)[4]) & moby->rot)[1] = 0.0f; moby->command = 2; jet_end_mount(0); - moby->state = 4; + moby->state = CANNON_UNMOUNTED_IDLE; node = (Moby *)(D_L08_0015FFD8 + (cannon_control_vars->platform_index << 8)); qcopy(muzzle, (*(float(*)[4]) & node->rot)); From 7ea8ee11bd39d84b08472df3a32f366d9fbbb734 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:25:40 +0000 Subject: [PATCH 0275/1502] decomp: clarify names in darter_update domain_0_value_0 -> DARTER_STATE_INITIALIZE: Retail 0x002e0250-0x002e0264 reads moby+0x20 and skips bob removal for state 0; the same byte selects the initialization branch at 0x002e02ac, named DARTER_STATE_INITIALIZE in the supplied C. domain_10_value_8 -> DARTER_STATE_DIVE_ATTACK: Retail 0x002e0b28-0x002e0b80 tests attack range and vertical separation, stores 8 to moby+0x20 and clears velocity; case 8 performs animation-window attack collision queries, matching existing DARTER_STATE_DIVE_ATTACK. domain_11_value_5 -> DARTER_STATE_RETURN_HOME: Retail case 7 exits through 0x002e0d58-0x002e0d88, storing 5 to moby+0x20 after restoring flight animation; case 5 steers toward pvars+0x130 home and climbs toward home Z+2, existing DARTER_STATE_RETURN_HOME. domain_12_value_5 -> DARTER_STATE_RETURN_HOME: Retail case 8 checks target status and animation completion at 0x002e0d34-0x002e0d58 then stores 5 at 0x002e0d88 into the state selector moby+0x20; case 5 is the existing home-return movement DARTER_STATE_RETURN_HOME. domain_13_value_3 -> DARTER_STATE_WANDER: Retail 0x002e0ecc-0x002e0ef8 tests XY distance to pvars+0x130 home below 2 and writes 3 to moby+0x20; case 3 resumes movement toward its wander goal, existing DARTER_STATE_WANDER. domain_14_value_10 -> DARTER_STATE_CUBOID_APPROACH_TARGET: Retail 0x002e1094-0x002e10e8 gates target availability, command timer and distance then writes 10 to moby+0x20; case 10 faces and approaches target at cuboid height, existing DARTER_STATE_CUBOID_APPROACH_TARGET. domain_15_value_11 -> DARTER_STATE_CUBOID_CHARGE_ATTACK: Retail 0x002e1234-0x002e129c checks attack distance and cuboid-height error below 1 then writes 11 to moby+0x20; case 11 uses faster target-directed movement and sphere attack collision, existing DARTER_STATE_CUBOID_CHARGE_ATTACK. domain_16_value_9 -> DARTER_STATE_CUBOID_PATROL: Retail 0x002e12b8-0x002e12d4 detects target-selection status 2 and writes 9 to moby+0x20 before resetting height variation at 0x002e166c; case 9 is existing DARTER_STATE_CUBOID_PATROL. domain_17_value_12 -> DARTER_STATE_CUBOID_RETURN_HOME: Retail 0x002e1488-0x002e14c8 exits the charge on close range, hero condition or animation flag and writes 12 to moby+0x20; case 12 steers toward home at cuboid height, existing DARTER_STATE_CUBOID_RETURN_HOME. domain_18_value_9 -> DARTER_STATE_CUBOID_PATROL: Retail 0x002e14f4-0x002e1510 detects target status 2 during charge and writes 9 to moby+0x20 before resetting timed height variation; the same selector dispatches existing DARTER_STATE_CUBOID_PATROL. domain_19_value_9 -> DARTER_STATE_CUBOID_PATROL: Retail 0x002e1630-0x002e1664 tests XY home distance below 2, writes 9 to moby+0x20 and resets command delay; case 9 resumes home-oriented cuboid patrol, existing DARTER_STATE_CUBOID_PATROL. domain_1_value_13 -> DARTER_STATE_DYING: Retail 0x002e025c-0x002e0264 compares the switch selector byte moby+0x20 with 13 before bob removal; its case at 0x002e16b4 performs death motion, explosion and removal, matching existing DARTER_STATE_DYING. domain_20_value_0 -> DARTER_STATE_INITIALIZE: Retail 0x002e1708-0x002e170c reloads moby+0x20, the switch selector, and skips bob advancement when zero; that value selects the existing initialization branch DARTER_STATE_INITIALIZE. domain_21_value_13 -> DARTER_STATE_DYING: Retail 0x002e1710-0x002e1714 compares the same moby+0x20 state selector to 13 and skips bob advancement; case 13 at 0x002e16b4 handles death motion and removal, existing DARTER_STATE_DYING. domain_2_value_3 -> DARTER_STATE_WANDER: Retail 0x002e0368-0x002e0388 writes 3 to moby+0x20 after home-wander spawn initialization and raises Z by 2; this is the same selector whose case 3 moves toward the home-relative goal, already DARTER_STATE_WANDER. domain_3_value_9 -> DARTER_STATE_CUBOID_PATROL: Retail 0x002e03c4-0x002e03fc writes 9 to moby+0x20 for cuboid spawn and sets Z from cuboid position; case 9 uses home heading and timed height offsets, already named DARTER_STATE_CUBOID_PATROL. domain_4_value_3 -> DARTER_STATE_WANDER: Retail 0x002e04ac-0x002e04c0 tests completion of accelerated rise toward home Z+2 and branches to 0x002e0ef4-0x002e0ef8 storing 3 to the same moby+0x20 switch selector: existing DARTER_STATE_WANDER. domain_5_value_4 -> DARTER_STATE_WAIT_BETWEEN_WANDER_GOALS: Retail 0x002e06b0-0x002e06f8 tests goal distance below 0.1, stores 4 at moby+0x20 and initializes the wait timer at pvars+0x198; case 4 decrements that timer, matching DARTER_STATE_WAIT_BETWEEN_WANDER_GOALS. domain_6_value_6 -> DARTER_STATE_ATTACK_WINDUP: Retail 0x002e0730-0x002e077c gates on the command timer, writes 6 to moby+0x20 and selects animation 1; case 6 turns toward the target and waits for animation completion, existing DARTER_STATE_ATTACK_WINDUP. domain_7_value_6 -> DARTER_STATE_ATTACK_WINDUP: Retail 0x002e07c0-0x002e080c transitions from waiting to state 6 via moby+0x20 and animation 1; this exact byte drives case 6 target-facing windup, already named DARTER_STATE_ATTACK_WINDUP. domain_8_value_3 -> DARTER_STATE_WANDER: Retail 0x002e0810-0x002e088c waits for pvars+0x198, creates a random home-relative goal and branches to the state-3 store at 0x002e0ef8; the selector is moby+0x20, whose goal-moving case is DARTER_STATE_WANDER. domain_9_value_7 -> DARTER_STATE_DIVE_TOWARD_TARGET: Retail 0x002e08ec-0x002e0908 tests animation flag 2 and stores 7 to moby+0x20; case 7 computes target-directed velocity with ground-height flooring, existing DARTER_STATE_DIVE_TOWARD_TARGET. --- src/overlays/l10/mobys/darter.c | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/overlays/l10/mobys/darter.c b/src/overlays/l10/mobys/darter.c index 4d1b724b11..3083338d6a 100644 --- a/src/overlays/l10/mobys/darter.c +++ b/src/overlays/l10/mobys/darter.c @@ -156,7 +156,7 @@ void darter_update(Moby *moby) { moby->shadow_range = 0x17; } moby->anim_speed = 1.0f; - if (moby->state != 0 && moby->state != 13) { + if (moby->state != DARTER_STATE_INITIALIZE && moby->state != DARTER_STATE_DYING) { moby->pos.z = moby->pos.z - l10_darter_bob_amplitude * fast_cos(darter_vars->bob_angle); } switch (moby->state) { @@ -175,7 +175,7 @@ void darter_update(Moby *moby) { darter_vars->b5A = truncate_float_to_s32(D_L10_00161E20 * 8.0f); switch (darter_vars->spawn_kind) { case DARTER_SPAWN_HOME_WANDER: - moby->state = 3; + moby->state = DARTER_STATE_WANDER; moby->pos.z = moby->pos.z + 2.0f; if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); @@ -186,7 +186,7 @@ void darter_update(Moby *moby) { case DARTER_SPAWN_CUBOID_PATROL: vector_and_collision_scratch[0] = fast_cos(random_angle_radians()) * 10.0f; vector_and_collision_scratch[1] = fast_sin(random_angle_radians()) * 10.0f; - moby->state = 9; + moby->state = DARTER_STATE_CUBOID_PATROL; vector_and_collision_scratch[2] = 0.0f; moby->pos.z = l10_cuboids[darter_vars->f194].pos.z; add_vectors(&vector_and_collision_scratch[4], &moby->pos, vector_and_collision_scratch); @@ -208,7 +208,7 @@ void darter_update(Moby *moby) { D_0015ED70 * 18.0f, D_0015ED70 * 18.0f, frame_time * 6.0f) == 0.0f) { - moby->state = 3; + moby->state = DARTER_STATE_WANDER; } break; case DARTER_STATE_WANDER: { @@ -251,7 +251,7 @@ void darter_update(Moby *moby) { vector_and_collision_scratch[2] = random_float_between(l10_darter_min_wander_height_offset, l10_darter_max_wander_height_offset); fast_vec_add(&darter_vars->goal, vector_and_collision_scratch, &darter_vars->home); } else if (dist < 0.1f) { - moby->state = 4; + moby->state = DARTER_STATE_WAIT_BETWEEN_WANDER_GOALS; darter_vars->wait = scale_game_frames(truncate_float_to_s32(random_float_between(30.0f, 90.0f))); } @@ -263,7 +263,7 @@ void darter_update(Moby *moby) { break; if (moby->group != 0xFF) FUN_L10_002e1cb0_2e01a8((unsigned char *)moby); - moby->state = 6; + moby->state = DARTER_STATE_ATTACK_WINDUP; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); break; @@ -274,7 +274,7 @@ void darter_update(Moby *moby) { FUN_L00_001fefc8(&moby->command) != 0) { if (moby->group != 0xFF) FUN_L10_002e1cb0_2e01a8((unsigned char *)moby); - moby->state = 6; + moby->state = DARTER_STATE_ATTACK_WINDUP; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); break; @@ -289,7 +289,7 @@ void darter_update(Moby *moby) { vector_and_collision_scratch[2] = 0.0f; vector_and_collision_scratch[2] = random_float_between(l10_darter_min_wander_height_offset, l10_darter_max_wander_height_offset); fast_vec_add(&darter_vars->goal, vector_and_collision_scratch, &darter_vars->home); - moby->state = 3; + moby->state = DARTER_STATE_WANDER; } break; case DARTER_STATE_ATTACK_WINDUP: @@ -301,7 +301,7 @@ void darter_update(Moby *moby) { frame_time * 6.2831855f); if ((moby->anim_flags & 2) == 0) break; - moby->state = 7; + moby->state = DARTER_STATE_DIVE_TOWARD_TARGET; if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); if (random_integer_below(0xFF) & 1) { @@ -343,7 +343,7 @@ void darter_update(Moby *moby) { if (absolute_float(moby->pos.z - ((Hero_2e01a8 *)((char *)&hero))->motion.pos.f[2]) < 2.0f) { allocate_voice_for_target_entry(0, 0, moby); - moby->state = 8; + moby->state = DARTER_STATE_DIVE_ATTACK; clear_u64_value(&darter_vars->velocity); if (moby->prev_seq != 2) blend_moby_animation(moby, 2, 4, scale_game_frames(5)); @@ -354,7 +354,7 @@ void darter_update(Moby *moby) { } if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(0x14)); - moby->state = 5; + moby->state = DARTER_STATE_RETURN_HOME; break; } case DARTER_STATE_DIVE_ATTACK: @@ -390,7 +390,7 @@ void darter_update(Moby *moby) { break; if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(0x14)); - moby->state = 5; + moby->state = DARTER_STATE_RETURN_HOME; break; case DARTER_STATE_RETURN_HOME: { float zero = 0.0f; @@ -414,7 +414,7 @@ void darter_update(Moby *moby) { darter_vars->velocity.z = climb; func_L00_00259B08_2E0630(moby, &darter_vars->velocity, 0.5f, 0x200, 0.0f, 0); if (vector_distance_xy(&moby->pos, &darter_vars->home) < 2.0f) - moby->state = 3; + moby->state = DARTER_STATE_WANDER; break; } case DARTER_STATE_CUBOID_PATROL: { @@ -450,7 +450,7 @@ void darter_update(Moby *moby) { break; if (moby->group != 0xFF) FUN_L10_002e1cb0_2e01a8((unsigned char *)moby); - moby->state = 10; + moby->state = DARTER_STATE_CUBOID_APPROACH_TARGET; if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); break; @@ -480,14 +480,14 @@ void darter_update(Moby *moby) { if (dist < l10_darter_attack_distance && absolute_float(l10_cuboids[darter_vars->f194].pos.z - moby->pos.z) < 1.0f) { allocate_voice_for_target_entry(0, 0, moby); - moby->state = 11; + moby->state = DARTER_STATE_CUBOID_CHARGE_ATTACK; if (moby->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(2)); break; } if (darter_vars->f104 != 2) break; - moby->state = 9; + moby->state = DARTER_STATE_CUBOID_PATROL; darter_vars->height_offset = random_float_between(0.0f, l10_darter_max_height_offset); darter_vars->height_timer = truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * random_float_between(0.75f, 1.25f)); @@ -527,14 +527,14 @@ void darter_update(Moby *moby) { coll_sphere_mobys(0.2f, vector_and_collision_scratch, 0, moby, &vector_and_collision_scratch[4]); if (fast_vec_dist(&moby->pos, &target->pos) < one || *(int *)(((char *)&hero) + 0x208C) == 7 || (moby->anim_flags & 2)) { - moby->state = 12; + moby->state = DARTER_STATE_CUBOID_RETURN_HOME; if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(2)); break; } if (darter_vars->f104 != 2) break; - moby->state = 9; + moby->state = DARTER_STATE_CUBOID_PATROL; darter_vars->height_offset = random_float_between(zero, l10_darter_max_height_offset); darter_vars->height_timer = truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * random_float_between(0.75f, 1.25f)); @@ -560,7 +560,7 @@ void darter_update(Moby *moby) { darter_vars->velocity.z = climb; add_vectors(vector_and_collision_scratch, &moby->pos, &darter_vars->velocity); if (vector_distance_xy(&moby->pos, &darter_vars->home) < 2.0f) { - moby->state = 9; + moby->state = DARTER_STATE_CUBOID_PATROL; moby->command = scale_game_frames(0x78); darter_vars->height_offset = random_float_between(0.0f, l10_darter_max_height_offset); darter_vars->height_timer = truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * @@ -576,7 +576,7 @@ void darter_update(Moby *moby) { mark_moby_for_removal(moby); return; } - if (moby->state != 0 && moby->state != 13) { + if (moby->state != DARTER_STATE_INITIALIZE && moby->state != DARTER_STATE_DYING) { darter_vars->bob_angle = fast_add_rotations( darter_vars->bob_angle, 360.0f / (float)truncate_float_to_s32(scale_time(l10_darter_bob_period_seconds * 60.0f)) * From 385e9834f9fc0a6d0b5c592f2c540ad0c8af5b9d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:25:40 +0000 Subject: [PATCH 0276/1502] decomp: clarify names in fighter_jet_update domain_0_value_1 -> FIGHTER_JET_STATE_WAIT_FOR_ENTRY: Retail 0x002bb0c0 loads craft+0x20 into v1; 0x002bb0d8-0x002bb0dc excludes 1 from hit processing. Source initial_state is copied directly from jet_moby->state, the selector of existing WAIT_FOR_ENTRY case. domain_10_value_5 -> FIGHTER_JET_STATE_EXIT_PLAYER: Retail 0x002bbafc-0x002bbb10 tests player+0x160F bit 1 and writes 5 to craft+0x20. Same field selects existing EXIT_PLAYER branch, detaching hero and restoring spawn transforms at 0x002bbb38 onward. domain_11_value_8 -> FIGHTER_JET_STATE_FORCED_EXIT: Retail 0x002bbb14-0x002bbb34 tests energy at data+0xE8, sets wait timer and writes 8 to craft+0x20. Existing FORCED_EXIT case uses that exact selector and detaches hero, restores escape transforms and schedules deletion. domain_12_value_1 -> FIGHTER_JET_STATE_WAIT_FOR_ENTRY: Retail normal exit restores craft/group state and voices then writes 1 to craft+0x20 at 0x002bbd04-0x002bbd18. This exact selector returns to existing WAIT_FOR_ENTRY case, which accepts entry volume or player input. domain_13_value_7 -> FIGHTER_JET_STATE_WAIT_FOR_DEATH_RESET: Retail death-sound branch releases voices then writes 7 to craft+0x20 at 0x002bbdac-0x002bbdb8. The same selector chooses existing WAIT_FOR_DEATH_RESET case, gating respawn/reset on death timer and music transition. domain_14_value_0 -> FIGHTER_JET_STATE_INITIALIZE: Retail death-reset branch respawns hero, restores craft transforms and releases voices, then stores zero to craft+0x20 at 0x002bbeb8. This field selects existing INITIALIZE case, which saves transforms and prepares palette/groups. domain_15_value_9 -> FIGHTER_JET_STATE_DELETE: Retail forced exit resets camera at 0x002bc0dc then writes 9 to craft+0x20 at 0x002bc0e4-0x002bc0ec. Same field selects existing DELETE case calling mark_moby_for_removal at 0x002bc0f0. domain_16_value_4 -> FIGHTER_JET_STATE_FLIGHT: Retail 0x002bc190 loads craft+0x20 and 0x002bc194-0x002bc19c compares it to 4 before copying craft position/angles to hero. Source state directly copies jet_moby->state, the existing FLIGHT case selector. domain_17_value_8 -> FIGHTER_JET_STATE_FORCED_EXIT: Retail 0x002bc190 loads craft+0x20; 0x002bc1d8-0x002bc1dc compares the same value with 8 to enable joint particles. Source state directly copies the existing fighter-jet state selector, whose 8 member is FORCED_EXIT. domain_1_value_2 -> FIGHTER_JET_STATE_MOUNT_PLAYER: Retail 0x002bb0c0 loads craft+0x20; 0x002bb0e0-0x002bb0e4 excludes 2 from hit processing. Source initial_state directly copies the same jet_moby->state selecting existing MOUNT_PLAYER case, whose branch mounts the hero. domain_2_value_4 -> FIGHTER_JET_STATE_FLIGHT: Retail 0x002bb104-0x002bb10c compares 4 with craft+0x20 before applying damage. This is the identical selector of existing FLIGHT case, which calls update_fighter_jet_flight at 0x002bbaf4. domain_3_value_6 -> FIGHTER_JET_STATE_STOP_DEATH_SOUNDS: After fatal damage, explosion and death timer setup, retail 0x002bb370-0x002bb374 writes 6 to craft+0x20. That exact field selects existing STOP_DEATH_SOUNDS case, releasing engine/weapon voices before advancing to 7. domain_5_value_1 -> FIGHTER_JET_STATE_WAIT_FOR_ENTRY: Retail initialization 0x002bb3dc-0x002bb3e4 writes 1 to craft+0x20. Same field dispatches the existing WAIT_FOR_ENTRY case at 0x002bb5fc, which tests persistence, entry volume and nearby player input. domain_6_value_9 -> FIGHTER_JET_STATE_DELETE: Retail 0x002bb548-0x002bb57c reads the persistence byte and writes 9 to craft+0x20 when it is 0xFF. This exact selector has existing DELETE case, calling removal at 0x002bc0f0. domain_7_value_9 -> FIGHTER_JET_STATE_DELETE: Retail wait-for-entry persistence check 0x002bb5fc-0x002bb63c writes 9 to craft+0x20 for completed persistence. The same field selects existing DELETE branch that marks the craft for removal at 0x002bc0f0. domain_8_value_2 -> FIGHTER_JET_STATE_MOUNT_PLAYER: Retail successful entry 0x002bb6cc-0x002bb738 prepares angles/energy then writes 2 to craft+0x20. That same selector chooses existing MOUNT_PLAYER case, which mounts hero and initializes craft health/ammo. domain_9_value_4 -> FIGHTER_JET_STATE_FLIGHT: Retail mount completion calls flight update at 0x002bba20 then writes 4 to craft+0x20 at 0x002bba3c-0x002bba44. This is the existing FLIGHT case selector, whose branch continues flight update. --- src/overlays/l13/mobys/fighter_jet.c | 34 ++++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/overlays/l13/mobys/fighter_jet.c b/src/overlays/l13/mobys/fighter_jet.c index 3adac16769..3defad8c37 100644 --- a/src/overlays/l13/mobys/fighter_jet.c +++ b/src/overlays/l13/mobys/fighter_jet.c @@ -1782,10 +1782,10 @@ void fighter_jet_update(Jet *jet_moby) { jet_data->hit_class = 0; fast_dec_timer((int *)&jet_data->timer); initial_state = jet_moby->state; - if ((unsigned int)(initial_state - 6) >= 2 && (unsigned char)initial_state != 1 && - (unsigned char)initial_state != 2) { + if ((unsigned int)(initial_state - 6) >= 2 && (unsigned char)initial_state != FIGHTER_JET_STATE_WAIT_FOR_ENTRY && + (unsigned char)initial_state != FIGHTER_JET_STATE_MOUNT_PLAYER) { JetHit *hit = (JetHit *)find_moby_hit(jet_moby, 0x30001, 0); - if (hit && jet_moby->state == 4) { + if (hit && jet_moby->state == FIGHTER_JET_STATE_FLIGHT) { if (((JetPlayer *)(&hero))->health > hit->damage) { ((JetPlayer *)(&hero))->health -= hit->damage; if (hit->source && (unsigned int)(hit->source->class_id - 0x52) < 2) @@ -1839,7 +1839,7 @@ void fighter_jet_update(Jet *jet_moby) { 0); jet_moby->animation = 0; jet_data->death_timer = scale_game_frames(240); - jet_moby->state = 6; + jet_moby->state = FIGHTER_JET_STATE_STOP_DEATH_SOUNDS; } } } @@ -1854,7 +1854,7 @@ void fighter_jet_update(Jet *jet_moby) { JetTexture *texture_table; unsigned int palette_data; int texture_index, initialized; - jet_moby->state = 1; + jet_moby->state = FIGHTER_JET_STATE_WAIT_FOR_ENTRY; jet_data->animation_frame = 0; jet_moby->scale = jet_moby->model->scale; *(float *)((char *)jet_data + 0x20) = jet_data->angles[0]; @@ -1883,7 +1883,7 @@ void fighter_jet_update(Jet *jet_moby) { jet_data->energy = 1; if (jet_moby->persistent != 0xFF && (visited52)[jet_moby->persistent + (persistence_table_row_index << 4)] == 0xFF) - jet_moby->state = 9; + jet_moby->state = FIGHTER_JET_STATE_DELETE; if (jet_data->group_a > 0) jet_group_state(jet_data->group_a, 0, 0, 0); if (jet_data->group_b > 0) @@ -1899,7 +1899,7 @@ void fighter_jet_update(Jet *jet_moby) { short enter = 0; if (jet_moby->persistent != 0xFF && (visited52)[jet_moby->persistent + (persistence_table_row_index << 4)] == 0xFF) - jet_moby->state = 9; + jet_moby->state = FIGHTER_JET_STATE_DELETE; else if (jet_data->trigger != -1 && is_point_inside_clip_volume(D_0013F3D0, jet_data->trigger)) { jet_data->blend = 0.99f; @@ -1924,7 +1924,7 @@ void fighter_jet_update(Jet *jet_moby) { qcopy(jet_data->angles, jet_moby->rotation); jet_data->wait_timer = 1; jet_data->energy = 1; - jet_moby->state = 2; + jet_moby->state = FIGHTER_JET_STATE_MOUNT_PLAYER; jet_data->lock_index = -1; } else if (jet_data->blend != 0.0f) { approach_value(&jet_data->blend, 0.0f, frame_time * 4.0f); @@ -2002,7 +2002,7 @@ void fighter_jet_update(Jet *jet_moby) { update_fighter_jet_flight(jet_moby, jet_data); jet_camera_mode(); request_music_track(2, 4); - jet_moby->state = 4; + jet_moby->state = FIGHTER_JET_STATE_FLIGHT; } break; case FIGHTER_JET_STATE_FLIGHT: { @@ -2020,10 +2020,10 @@ void fighter_jet_update(Jet *jet_moby) { } update_fighter_jet_flight(jet_moby, jet_data); if (((JetPlayer *)(&hero))->pad160F & 1) - jet_moby->state = 5; + jet_moby->state = FIGHTER_JET_STATE_EXIT_PLAYER; if (jet_data->energy <= 0) { jet_data->wait_timer = scale_game_frames(1200); - jet_moby->state = 8; + jet_moby->state = FIGHTER_JET_STATE_FORCED_EXIT; } break; } @@ -2070,7 +2070,7 @@ void fighter_jet_update(Jet *jet_moby) { request_music_track(0, 5); jet_data->blend = 0.99f; D_L13_0015F3FC = 0.99f; - jet_moby->state = 1; + jet_moby->state = FIGHTER_JET_STATE_WAIT_FOR_ENTRY; break; case FIGHTER_JET_STATE_STOP_DEATH_SOUNDS: D_L13_0015F608 = 2; @@ -2091,7 +2091,7 @@ void fighter_jet_update(Jet *jet_moby) { } jet_data->weapon_sound = -1; } - jet_moby->state = 7; + jet_moby->state = FIGHTER_JET_STATE_WAIT_FOR_DEATH_RESET; break; case FIGHTER_JET_STATE_WAIT_FOR_DEATH_RESET: { struct MusicStreamState *transition; @@ -2123,7 +2123,7 @@ void fighter_jet_update(Jet *jet_moby) { } jet_data->weapon_sound = -1; } - jet_moby->state = 0; + jet_moby->state = FIGHTER_JET_STATE_INITIALIZE; } } } @@ -2181,7 +2181,7 @@ void fighter_jet_update(Jet *jet_moby) { jet_data->weapon_sound = -1; } jet_reset_camera((char *)&hero + 0x80, (char *)&hero + 0x90); - jet_moby->state = 9; + jet_moby->state = FIGHTER_JET_STATE_DELETE; break; case FIGHTER_JET_STATE_DELETE: mark_moby_for_removal(jet_moby); @@ -2204,10 +2204,10 @@ void fighter_jet_update(Jet *jet_moby) { if (jet_moby->position[2] > 1008.0f) jet_moby->position[2] = 1008.0f; state = jet_moby->state; - if ((unsigned char)state == 4) { + if ((unsigned char)state == FIGHTER_JET_STATE_FLIGHT) { qcopy_nc((char *)&hero + 0x80, jet_moby->position); qcopy_nc((char *)&hero + 0x90, jet_data->angles); } - if ((unsigned int)(state - 3) < 2 || (unsigned char)state == 8) + if ((unsigned int)(state - 3) < 2 || (unsigned char)state == FIGHTER_JET_STATE_FORCED_EXIT) spawn_fighter_jet_joint_particles(jet_moby, (char *)jet_data); } From bb4e72330b4e348d832c4c893935ddb2898adaad Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:27:59 +0000 Subject: [PATCH 0277/1502] decomp: clarify names in load_level_gameplay domain_0_value_0 -> FALSE: The bound source tests pal_mode != 0 to choose the alternate regional disc sectors. Retail 0x00241990-0x002419cc loads pal_mode at 0x0015ED80 and branches on zero to the ordinary sound_archive sector/size pair, while nonzero selects sound_archive_alt. Original Ghidra iRam0015ed80 == 0 agrees. This is the false/disabled PAL flag value, so reuse supplied FALSE=0 without claiming all nonzero encodings. domain_1_value_0 -> FALSE: The same pal_mode flag at 0x0015ED80 is read at retail 0x00241a3c-0x00241a44. Zero selects the branch that calls set_video_timing(0) when frame_scale differs from 1.0 (0x00241a78-0x00241a98); nonzero selects set_video_timing(1) at 0x00241a68-0x00241a6c. Source pal_mode != 0 and original Ghidra agree, proving the supplied FALSE=0 represents PAL mode disabled in this comparison too. domain_3_value_0 -> OCCLUSION_MODE_DISABLED: The bound field is g_debug_menu.occlusion_mode, corresponding to retail DAT_0016c074. Retail 0x0024379c-0x002437b0 enters the no-occlusion branch when occlusion data or hdr->f8C is absent. That branch prints the checked no occlusion message (0x00243b50-0x00243b58), replaces moby/tie/tfrag mappings with fallback 0x7F80, and stores zero at 0x00243c0c-0x00243c14. Original Ghidra DAT_0016c074 = 0 and source agree, proving this assignment selects disabled occlusion. --- src/overlays/shared/world/load_level_gameplay.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/world/load_level_gameplay.c b/src/overlays/shared/world/load_level_gameplay.c index 0e6f4b200b..89f11c381e 100644 --- a/src/overlays/shared/world/load_level_gameplay.c +++ b/src/overlays/shared/world/load_level_gameplay.c @@ -501,6 +501,9 @@ extern s32 pal_mode __asm__("D_0015ED80") MACRO_ADDR; extern s32 game_language __asm__("D_0015ED88") MACRO_ADDR; char *load_level_gameplay(int skip_gameplay_read) { + enum { + OCCLUSION_MODE_DISABLED = 0 + }; LevelHeader *hdr; char *mem; float *ship; @@ -511,7 +514,7 @@ char *load_level_gameplay(int skip_gameplay_read) { hdr = D_L00_00173E00.f4; mem = D_L00_00173E00.f18; if (skip_gameplay_read == 0) { - if (pal_mode != 0) { + if (pal_mode != FALSE) { read_disc_sectors_and_wait( mem, disc_table.sound_archive_alt.sector, disc_table.sound_archive_alt.size); } else { @@ -527,7 +530,7 @@ char *load_level_gameplay(int skip_gameplay_read) { FillTransferWords(&l00_camera, 0, 0x3A0); FillTransferWords(D_L00_0018EB40, 0, 0x180); srand(0x4D2); - if (pal_mode != 0) { + if (pal_mode != FALSE) { if (frame_scale == 1.0f) { set_video_timing(1); } @@ -1632,7 +1635,7 @@ char *load_level_gameplay(int skip_gameplay_read) { for (i = 0; i < D_L00_00160F50; i++) { D_L00_00160F4C[i].f3A = 0x7F80; } - g_debug_menu.occlusion_mode = 0; + g_debug_menu.occlusion_mode = OCCLUSION_MODE_DISABLED; } reset_draw_globals(); initialize_hero(); From 0eb6aa49b6ad072ff870fb30b57bc97d113373a2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:28:00 +0000 Subject: [PATCH 0278/1502] decomp: clarify names in hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: 0x0021e3f4-0x0021e404 permits request 100 with override 2 while dying; named case 100 cancels item animation and installs idle animation at 0x0022286c-0x002228a4. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_10_value_106 -> HERO_STATE_DROWN: 0x0021e4a0-0x0021e4a4 admits 0x6A; named DROWN entry at 0x0021ee68-0x0021f00c zeros health and updates water-related usage statistics. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_11_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: 0x0021e4a8-0x0021e4ac admits 0x80; named entry at 0x0021e78c-0x0021e7e8 zeros health and limits momentum by frame_time*3.5. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_12_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: 0x0021e4b0-0x0021e4b4 admits 0x82; named entry at 0x0021f010-0x0021f05c zeros health and sets dying control mode 0x14. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021e4d8-0x0021e528: zero vehicle mode enables normal collision, item/tilt flags and trail reset. Original Ghidra tests cRam001413f4, the same hero+0x20A4 byte loaded at 0x0021e4d8 and identified as Hero.vehicle_mode in authoritative C. This is exactly the supplied HeroVehicleMode domain, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021e5e4-0x0021e600: nonzero vehicle mode routes idle to request_hero_idle_state_for_vehicle_mode. Original Ghidra tests cRam001413f4, the same hero+0x20A4 byte loaded at 0x0021e4d8 and identified as Hero.vehicle_mode in authoritative C. This is exactly the supplied HeroVehicleMode domain, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT. domain_16_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021f9c8-0x0021f9dc: zero vehicle mode cancels the hero item animation during approach entry. Original Ghidra tests cRam001413f4, the same hero+0x20A4 byte loaded at 0x0021e4d8 and identified as Hero.vehicle_mode in authoritative C. This is exactly the supplied HeroVehicleMode domain, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT. domain_18_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0021fa10-0x0021fa30 compares the hero+0x20A4 vehicle_mode byte against 1 and selects animation 2 for approach entry. Original Ghidra tests cRam001413f4 == 1; authoritative C uses p->vehicle_mode. This is the supplied shared HeroVehicleMode domain whose canonical member 1 is HERO_VEHICLE_MODE_CLANK, independently of state IDs and control modes. domain_19_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021fa34-0x0021fa68: zero vehicle mode selects the on-foot step-based animation sequence. Original Ghidra tests cRam001413f4, the same hero+0x20A4 byte loaded at 0x0021e4d8 and identified as Hero.vehicle_mode in authoritative C. This is exactly the supplied HeroVehicleMode domain, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT. domain_1_value_6 -> HERO_STATE_FALL: 0x0021e458-0x0021e45c admits request 6; named FALL entry at 0x002205d4-0x00220738 initializes falling gravity and velocity. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_20_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00220618-0x00220630: zero vehicle mode allocates the fatal-fall entry voice. Original Ghidra tests cRam001413f4, the same hero+0x20A4 byte loaded at 0x0021e4d8 and identified as Hero.vehicle_mode in authoritative C. This is exactly the supplied HeroVehicleMode domain, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT. domain_22_value_41 -> HERO_STATE_GRIND_JUMP: 0x00220848-0x00220868 tests the request range 0x29..0x2A for grind bookkeeping; named GRIND_JUMP setup at 0x00220b98-0x00220cfc installs grind control and launch profile. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_23_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: 0x00220848-0x00220868 tests the request range 0x29..0x2A; named GRIND_RAIL_TRANSFER setup at 0x00220d00-0x00220d90 installs grind control and its launch profile, with direction-selected animation at 0x0022168c-0x002216f8. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_2_value_61 -> HERO_STATE_DYING: 0x0021e460-0x0021e464 admits 0x3D; named DYING entry at 0x0021e748-0x0021e788 sets dying control mode 0x14 and animation 0x45. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_3_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: 0x0021e468-0x0021e46c admits 0x47 in the zero-health request filter; supplied HeroStateId canonically defines this request as VEHICLE_MODE_1_DYING. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_4_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: 0x0021e470-0x0021e474 admits 0x57; named entry at 0x00222494-0x002224d4 sets dying control mode, copies momentum and selects vehicle animation 3. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_5_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: 0x0021e478-0x0021e47c admits 0x62 in the zero-health request filter; supplied HeroStateId canonically defines this request as VEHICLE_MODE_2_DYING. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_6_value_119 -> HERO_STATE_FATAL_FALL: 0x0021e480-0x0021e484 admits 0x77; named FALL/FATAL_FALL entry at 0x002205d4-0x00220678 initializes fall gravity and fatal-fall tumble targets. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_7_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: 0x0021e488-0x0021e48c admits 0x7B; supplied ground-material caller requests 0x7B after collision material 0xB, and the shared HeroStateId gives its canonical respawn-wait member. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_8_value_124 -> HERO_STATE_DEATH_DESCENT: 0x0021e490-0x0021e494 admits 0x7C in the zero-health request filter; shared HeroStateId canonically defines request 124 as DEATH_DESCENT. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. domain_9_value_127 -> HERO_STATE_SINK: 0x0021e498-0x0021e49c admits 0x7F; named SINK entry at 0x0021e7ec-0x0021e888 zeros health and initializes submerged height and downward motion. Retail 0x0021e3b8 saves a0 in s1 and 0x0021e4f8 stores s1 at hero+0x2084 (state.current); original Ghidra assigns param_1 to iRam001413d4 and switches on param_1. Thus requested_state belongs to the supplied shared HeroStateId, not the control-mode or vehicle-mode domains. --- src/overlays/l16/hero/hero_set_state.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l16/hero/hero_set_state.c b/src/overlays/l16/hero/hero_set_state.c index 590903f736..e256051af0 100644 --- a/src/overlays/l16/hero/hero_set_state.c +++ b/src/overlays/l16/hero/hero_set_state.c @@ -89,7 +89,7 @@ int hero_set_state(int requested_state, int b) { float vec[4]; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L16_0015F5C4 == 2 || D_L16_0015F5C4 == 6) && b != 2) @@ -97,8 +97,8 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -115,7 +115,7 @@ int hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -143,7 +143,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); return 1; } @@ -757,14 +757,14 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation( p->state.step + 3, D_L16_0015F6E8[p->state.step], (float)scale_game_frames(8)); } @@ -1100,7 +1100,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -1185,7 +1185,7 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 2c3d49e21e316451550e90e1b49b850209bf65d7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:30:08 +0000 Subject: [PATCH 0279/1502] decomp: clarify names in update_hero_state_transitions domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x00230a84-0x00230aa0 permits item-use-lock bypass when lbu hero+0x20a4 equals 1. The authoritative source identifies the selector as hero.vehicle_mode, distinct from hero.state.current/control_mode. Original Ghidra cRam001413f4 and retail byte loads at hero+0x20a4 confirm the same field; reuse the supplied HeroVehicleMode canonical member in include/rnc/hero/hero_state.h. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x00230aac-0x00230ac8 permits item-selection-lock bypass when lbu hero+0x20a4 equals 1. The authoritative source identifies the selector as hero.vehicle_mode, distinct from hero.state.current/control_mode. Original Ghidra cRam001413f4 and retail byte loads at hero+0x20a4 confirm the same field; reuse the supplied HeroVehicleMode canonical member in include/rnc/hero/hero_state.h. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00230ad4-0x00230ae0 accepts zero from hero+0x20a4 before the selector HUD queue block. The authoritative source identifies the selector as hero.vehicle_mode, distinct from hero.state.current/control_mode. Original Ghidra cRam001413f4 and retail byte loads at hero+0x20a4 confirm the same field; reuse the supplied HeroVehicleMode canonical member in include/rnc/hero/hero_state.h. domain_4_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x00230d20-0x00230d38 excludes hero+0x20a4 equal to 2 from the fatal-fall state request. The authoritative source identifies the selector as hero.vehicle_mode, distinct from hero.state.current/control_mode. Original Ghidra cRam001413f4 and retail byte loads at hero+0x20a4 confirm the same field; reuse the supplied HeroVehicleMode canonical member in include/rnc/hero/hero_state.h. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002315f4-0x00231610 requires zero vehicle selector before ordinary LOOK equipment animation selection. The authoritative source identifies the selector as hero.vehicle_mode, distinct from hero.state.current/control_mode. Original Ghidra cRam001413f4 and retail byte loads at hero+0x20a4 confirm the same field; reuse the supplied HeroVehicleMode canonical member in include/rnc/hero/hero_state.h. domain_6_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002316e0-0x002316f4 calls request_hero_idle_state_for_vehicle_mode when hero+0x20a4 is nonzero, bypassing ordinary crouch/idle exits. The authoritative source identifies the selector as hero.vehicle_mode, distinct from hero.state.current/control_mode. Original Ghidra cRam001413f4 and retail byte loads at hero+0x20a4 confirm the same field; reuse the supplied HeroVehicleMode canonical member in include/rnc/hero/hero_state.h. domain_7_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00231f70-0x00231f98 checks hero+0x20a4 nonzero before vehicle stopping-at-target handling; source tests hero.vehicle_mode != 0. The authoritative source identifies the selector as hero.vehicle_mode, distinct from hero.state.current/control_mode. Original Ghidra cRam001413f4 and retail byte loads at hero+0x20a4 confirm the same field; reuse the supplied HeroVehicleMode canonical member in include/rnc/hero/hero_state.h. domain_8_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00234f8c-0x00234fa8 requires zero hero+0x20a4 before LOOK_RELEASE_WAIT equipment animation selection. The authoritative source identifies the selector as hero.vehicle_mode, distinct from hero.state.current/control_mode. Original Ghidra cRam001413f4 and retail byte loads at hero+0x20a4 confirm the same field; reuse the supplied HeroVehicleMode canonical member in include/rnc/hero/hero_state.h. --- src/overlays/l02/hero/hero_set_state.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l02/hero/hero_set_state.c b/src/overlays/l02/hero/hero_set_state.c index b14ac9ee32..6617006d06 100644 --- a/src/overlays/l02/hero/hero_set_state.c +++ b/src/overlays/l02/hero/hero_set_state.c @@ -1861,9 +1861,9 @@ void update_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && item_selector_hud_inhibit == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.vehicle_mode == 0 || hero.vehicle_mode == 3)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; if (hero.quick_swap_tap_window != 0) { @@ -1926,7 +1926,7 @@ void update_hero_state_transitions(void) { } } if (fatal_fall_height_threshold > hero.motion.pos.f[2] && hero.ground_distance > 2.0f && - hero.vehicle_mode != 2 && hero.state.current != 0x77) { + hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { hero_set_state(0x77, 1); } else { switch (hero.state.current) { @@ -2182,7 +2182,7 @@ void update_hero_state_transitions(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { @@ -2209,7 +2209,7 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); break; } @@ -2442,7 +2442,7 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; @@ -3591,7 +3591,7 @@ void update_hero_state_transitions(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { From 4015c5ccdfe2231bb0b6c50d5b07d0253cbd2290 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:30:09 +0000 Subject: [PATCH 0280/1502] decomp: clarify names in hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: Retail 0x2356fc-0x235700 compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE=100 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. This comparison is a transition admission check in the same state domain as the symbolic entry cases. domain_10_value_106 -> HERO_STATE_DROWN: Retail 0x2357a8-0x2357ac compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_DROWN=106 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. This comparison is a transition admission check in the same state domain as the symbolic entry cases. domain_11_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: Retail 0x2357b0-0x2357b4 compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_DYING_SPEED_LIMITED=128 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. This comparison is a transition admission check in the same state domain as the symbolic entry cases. domain_12_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: Retail 0x2357b8-0x2357bc compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_DYING_ZERO_HEALTH=130 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. This comparison is a transition admission check in the same state domain as the symbolic entry cases. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x2357ec-0x235838 tests the byte loaded from hero+0x20a4 for initial collision/trail and item-lock reset. Authoritative C identifies this exact field as p->vehicle_mode or q->vehicle_mode; supplied process_hero_hit_response switches the same Hero.vehicle_mode field using HERO_VEHICLE_MODE_ON_FOOT and HERO_VEHICLE_MODE_CLANK. This proves the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical HERO_VEHICLE_MODE_ON_FOOT=0, not a state or gravity constant. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x2358f0-0x235900 tests the byte loaded from hero+0x20a4 for idle redirection for non-on-foot modes. Authoritative C identifies this exact field as p->vehicle_mode or q->vehicle_mode; supplied process_hero_hit_response switches the same Hero.vehicle_mode field using HERO_VEHICLE_MODE_ON_FOOT and HERO_VEHICLE_MODE_CLANK. This proves the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical HERO_VEHICLE_MODE_ON_FOOT=0, not a state or gravity constant. domain_16_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x235ed0-0x235ee4 tests the byte loaded from hero+0x20a4 for item-animation cancellation. Authoritative C identifies this exact field as p->vehicle_mode or q->vehicle_mode; supplied process_hero_hit_response switches the same Hero.vehicle_mode field using HERO_VEHICLE_MODE_ON_FOOT and HERO_VEHICLE_MODE_CLANK. This proves the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical HERO_VEHICLE_MODE_ON_FOOT=0, not a state or gravity constant. domain_18_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x235ef0-0x235f38 tests the byte loaded from hero+0x20a4 for approach animation selection. Authoritative C identifies this exact field as p->vehicle_mode or q->vehicle_mode; supplied process_hero_hit_response switches the same Hero.vehicle_mode field using HERO_VEHICLE_MODE_ON_FOOT and HERO_VEHICLE_MODE_CLANK. This proves the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical HERO_VEHICLE_MODE_CLANK=1, not a state or gravity constant. domain_19_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x235f3c-0x235f74 tests the byte loaded from hero+0x20a4 for ordinary locomotion animation selection. Authoritative C identifies this exact field as p->vehicle_mode or q->vehicle_mode; supplied process_hero_hit_response switches the same Hero.vehicle_mode field using HERO_VEHICLE_MODE_ON_FOOT and HERO_VEHICLE_MODE_CLANK. This proves the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical HERO_VEHICLE_MODE_ON_FOOT=0, not a state or gravity constant. domain_1_value_6 -> HERO_STATE_FALL: Retail 0x235760-0x235764 compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_FALL=6 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. This comparison is a transition admission check in the same state domain as the symbolic entry cases. domain_20_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x236ab8-0x236ad0 tests the byte loaded from hero+0x20a4 for fatal-fall voice allocation. Authoritative C identifies this exact field as p->vehicle_mode or q->vehicle_mode; supplied process_hero_hit_response switches the same Hero.vehicle_mode field using HERO_VEHICLE_MODE_ON_FOOT and HERO_VEHICLE_MODE_CLANK. This proves the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical HERO_VEHICLE_MODE_ON_FOOT=0, not a state or gravity constant. domain_21_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x236b44-0x236b74 tests the byte loaded from hero+0x20a4 for fall animation selection. Authoritative C identifies this exact field as p->vehicle_mode or q->vehicle_mode; supplied process_hero_hit_response switches the same Hero.vehicle_mode field using HERO_VEHICLE_MODE_ON_FOOT and HERO_VEHICLE_MODE_CLANK. This proves the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical HERO_VEHICLE_MODE_CLANK=1, not a state or gravity constant. domain_23_value_41 -> HERO_STATE_GRIND_JUMP: Retail 0x236d14-0x236d34 compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_GRIND_JUMP=41 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. The paired range selects rail-jump setup +0x2284=3 for the two canonical grind jump/transfer states. domain_24_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: Retail 0x236d14-0x236d34 compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_GRIND_RAIL_TRANSFER=42 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. The paired range selects rail-jump setup +0x2284=3 for the two canonical grind jump/transfer states. domain_2_value_61 -> HERO_STATE_DYING: Retail 0x235768-0x23576c compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_DYING=61 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. This comparison is a transition admission check in the same state domain as the symbolic entry cases. domain_3_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: Retail 0x235770-0x235774 compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_VEHICLE_MODE_1_DYING=71 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. This comparison is a transition admission check in the same state domain as the symbolic entry cases. domain_4_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: Retail 0x235778-0x23577c compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_VEHICLE_MODE_3_DYING=87 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. This comparison is a transition admission check in the same state domain as the symbolic entry cases. domain_5_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: Retail 0x235780-0x235784 compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_VEHICLE_MODE_2_DYING=98 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. This comparison is a transition admission check in the same state domain as the symbolic entry cases. domain_6_value_119 -> HERO_STATE_FATAL_FALL: Retail 0x235788-0x23578c compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_FATAL_FALL=119 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. This comparison is a transition admission check in the same state domain as the symbolic entry cases. domain_7_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: Retail 0x235790-0x235794 compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT=123 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. This comparison is a transition admission check in the same state domain as the symbolic entry cases. domain_8_value_124 -> HERO_STATE_DEATH_DESCENT: Retail 0x235798-0x23579c compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_DEATH_DESCENT=124 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. This comparison is a transition admission check in the same state domain as the symbolic entry cases. domain_9_value_127 -> HERO_STATE_SINK: Retail 0x2357a0-0x2357a4 compares the requested-state register s1. Retail 0x2356c0 preserves a0 in s1, 0x235804 stores s1 into hero.state.current (+0x2084), and 0x235894-0x2358b4 dispatches that same state ID. Authoritative C agrees; reuse canonical HERO_STATE_SINK=127 from the supplied HeroStateId enum in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. This comparison is a transition admission check in the same state domain as the symbolic entry cases. --- src/overlays/l06/hero/hero_set_state.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l06/hero/hero_set_state.c b/src/overlays/l06/hero/hero_set_state.c index eaf39504ff..1072633f56 100644 --- a/src/overlays/l06/hero/hero_set_state.c +++ b/src/overlays/l06/hero/hero_set_state.c @@ -79,7 +79,7 @@ int hero_set_state(int requested_state, int b) { } d; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L06_0015F5C4 == 2 || D_L06_0015F5C4 == 6) && b != 2) @@ -87,8 +87,8 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -105,7 +105,7 @@ int hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -133,7 +133,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { enter_hero_idle_state_for_current_vehicle_mode(); return 1; } @@ -322,14 +322,14 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation( p->state.step + 3, D_L06_0015F6D8[p->state.step], (float)scale_game_frames(8)); } @@ -659,7 +659,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -672,7 +672,7 @@ int hero_set_state(int requested_state, int b) { q->state.step = 0; qcopy(&q->motion.velocity, &q->motion.resolved_velocity); if (b) { - if (q->vehicle_mode == 1) { + if (q->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(4, 0, (float)scale_game_frames(8)); return 1; } @@ -748,7 +748,7 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 0e29d08a1002f46c653a62407c7d029a28206128 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:32:50 +0000 Subject: [PATCH 0281/1502] decomp: clarify names in hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). 0x0021e588..0x0021e59c tests requested state 100 and b=2 to permit entry from death control mode; original Ghidra and source show this refusal exception. domain_10_value_106 -> HERO_STATE_DROWN: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). 0x0021e634..0x0021e638 admits requested state 0x6A; named DROWN entry 0x0021f048..0x0021f070 sets death control and zero health. domain_11_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). 0x0021e63c..0x0021e640 admits requested state 0x80; its named entry 0x0021e96c..0x0021e9a4 clears health and limits saved motion to frame_time*3.5. domain_12_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). 0x0021e644..0x0021e648 admits requested state 0x82; its named entry 0x0021f1f0..0x0021f218 sets death control, clears health and saves motion. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares HeroVehicleMode members ON_FOOT=0 and CLANK=1. Source p/q points to &hero, and vehicle_mode is the byte at +0x20A4, read by original Ghidra as cRam001413f4. This field is separate from current-state +0x2084 and control-mode +0x208C; reuse its canonical mode member. 0x0021e678 loads +0x20A4 and 0x0021e69c tests zero before resetting moby collision, item selection and transform history. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares HeroVehicleMode members ON_FOOT=0 and CLANK=1. Source p/q points to &hero, and vehicle_mode is the byte at +0x20A4, read by original Ghidra as cRam001413f4. This field is separate from current-state +0x2084 and control-mode +0x208C; reuse its canonical mode member. 0x0021e77c..0x0021e788 tests +0x20A4 for nonzero and routes non-foot modes to enter_hero_idle_state_for_current_vehicle_mode. domain_16_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares HeroVehicleMode members ON_FOOT=0 and CLANK=1. Source p/q points to &hero, and vehicle_mode is the byte at +0x20A4, read by original Ghidra as cRam001413f4. This field is separate from current-state +0x2084 and control-mode +0x208C; reuse its canonical mode member. 0x0021f744..0x0021f758 reads +0x20A4 and cancels item animation only for zero during approach-target entry. domain_18_value_1 -> HERO_VEHICLE_MODE_CLANK: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares HeroVehicleMode members ON_FOOT=0 and CLANK=1. Source p/q points to &hero, and vehicle_mode is the byte at +0x20A4, read by original Ghidra as cRam001413f4. This field is separate from current-state +0x2084 and control-mode +0x208C; reuse its canonical mode member. 0x0021f764 reads +0x20A4; 0x0021f78c compares it against s1=1 and selects mode-specific animation 2 at 0x0021f794..0x0021f7ac. domain_19_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares HeroVehicleMode members ON_FOOT=0 and CLANK=1. Source p/q points to &hero, and vehicle_mode is the byte at +0x20A4, read by original Ghidra as cRam001413f4. This field is separate from current-state +0x2084 and control-mode +0x208C; reuse its canonical mode member. 0x0021f7b0 tests the +0x20A4 byte against zero; zero selects state.step+3 and the on-foot run-animation table at 0x0021f7b8..0x0021f7e8. domain_1_value_6 -> HERO_STATE_FALL: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). 0x0021e5ec..0x0021e5f0 permits requested state 6 through the zero-health gate; named FALL shares fall motion setup at 0x00220450. domain_20_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares HeroVehicleMode members ON_FOOT=0 and CLANK=1. Source p/q points to &hero, and vehicle_mode is the byte at +0x20A4, read by original Ghidra as cRam001413f4. This field is separate from current-state +0x2084 and control-mode +0x208C; reuse its canonical mode member. 0x00220494..0x002204ac tests +0x20A4 against zero to allocate and save the on-foot fatal-fall voice. domain_21_value_1 -> HERO_VEHICLE_MODE_CLANK: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares HeroVehicleMode members ON_FOOT=0 and CLANK=1. Source p/q points to &hero, and vehicle_mode is the byte at +0x20A4, read by original Ghidra as cRam001413f4. This field is separate from current-state +0x2084 and control-mode +0x208C; reuse its canonical mode member. 0x0022051c initializes s1=1; 0x00220520..0x00220524 loads +0x20A4 and compares to s1, selecting mode-specific fall animation 4 at 0x0022052c..0x00220548. domain_23_value_41 -> HERO_STATE_GRIND_JUMP: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). Source compares requested_state>=0x29 as the lower endpoint of the grind-jump pair. Retail 0x002206f0..0x00220708 subtracts 0x29 from s1 and checks unsigned <2 to select entry workspace 3. Named GRIND_JUMP and GRIND_RAIL_TRANSFER share this jump entry. domain_24_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). Source compares requested_state<=0x2A as the upper endpoint of the grind-jump pair. Retail 0x002206f0..0x00220708 subtracts 0x29 from s1 and checks unsigned <2. The supplied canonical member identifies the second state of this proven HeroStateId interval. domain_2_value_61 -> HERO_STATE_DYING: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). 0x0021e5f4..0x0021e5f8 permits requested state 0x3D through the health gate; its named DYING branch sets death control at 0x0021e928..0x0021e944. domain_3_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). 0x0021e5fc..0x0021e600 permits requested state 0x47; its named branch at 0x00222b30..0x00222b50 clears health and sets death control. Reuse the state member, not a vehicle-mode enum. domain_4_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). 0x0021e604..0x0021e608 permits requested state 0x57; its named branch at 0x00222e20..0x00222e3c sets death control and saves motion. domain_5_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). 0x0021e60c..0x0021e610 compares the same requested-state s1 with 0x62 and admits it through the health gate. Reuse the canonical shared state identity; no vehicle-mode identity is inferred from this number. domain_6_value_119 -> HERO_STATE_FATAL_FALL: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). 0x0021e614..0x0021e618 admits requested state 0x77; named FATAL_FALL shares FALL entry and adds on-foot voice and tumble initialization at 0x00220478..0x002204f4. domain_7_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). 0x0021e61c..0x0021e620 admits requested state 0x7B; its named entry 0x00222744..0x00222788 initializes control mode 0x19 and collision-off timer 10000. domain_8_value_124 -> HERO_STATE_DEATH_DESCENT: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). 0x0021e624..0x0021e628 admits requested state 0x7C; named entry 0x002227a8..0x00222840 saves ground height and clears health, or recursively enters DYING in level 6. domain_9_value_127 -> HERO_STATE_SINK: The supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) declares this canonical HeroStateId member. Source requested_state and original Ghidra param_1 are the same selector: retail 0x0021e550 saves a0 in s1, 0x0021e690 stores s1 to hero.state.current (+0x2084), and 0x0021e720..0x0021e740 dispatches it. This is distinct from control_mode (+0x208C) and vehicle_mode (+0x20A4). 0x0021e62c..0x0021e630 admits requested state 0x7F; named SINK entry at 0x0021e9cc..0x0021ea4c initializes downward motion relative to water height and clears health. --- src/overlays/l17/hero/hero_set_state.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l17/hero/hero_set_state.c b/src/overlays/l17/hero/hero_set_state.c index afe72108e2..1d4cb339d5 100644 --- a/src/overlays/l17/hero/hero_set_state.c +++ b/src/overlays/l17/hero/hero_set_state.c @@ -103,7 +103,7 @@ int hero_set_state(int requested_state, int b) { V4_21ED38 sampled_path_position; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L17_0015F5C4 == 2 || D_L17_0015F5C4 == 6) && b != 2) @@ -111,8 +111,8 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -129,7 +129,7 @@ int hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -157,7 +157,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { enter_hero_idle_state_for_current_vehicle_mode(); return 1; } @@ -635,14 +635,14 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation( p->state.step + 3, D_L17_0015F6D8[p->state.step], (float)scale_game_frames(8)); } @@ -1017,7 +1017,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -1030,7 +1030,7 @@ int hero_set_state(int requested_state, int b) { q->state.step = 0; qcopy(&q->motion.velocity, &q->motion.resolved_velocity); if (b) { - if (q->vehicle_mode == 1) { + if (q->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(4, 0, (float)scale_game_frames(8)); return 1; } @@ -1106,7 +1106,7 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From e244848c7a2124db024a8dd1c317563e2e051527 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:34:50 +0000 Subject: [PATCH 0282/1502] decomp: clarify names in jet_fighter_update domain_0_value_7 -> JET_FIGHTER_STATE_WAIT_FOR_RESPAWN: Retail 003132c4-003132d8 compares the state byte at moby/s4+0x20 with 7 to skip hit processing. The same byte selects the existing JET_FIGHTER_STATE_WAIT_FOR_RESPAWN switch arm; 00313bf8-00313c14 decrements pvars+0xF8 and calls hero_respawn, proving the same domain and member. domain_10_value_5 -> JET_FIGHTER_STATE_DISMOUNT: Retail 00313a98-00313aac tests hero.ship_flags bit 1 then stores 5 to the same moby+0x20 selector. Existing DISMOUNT case 00313ab0-00313bf4 ends the mount, restores ship home pose and hero exit camera, releases voices and returns to waiting state 1. domain_11_value_1 -> JET_FIGHTER_STATE_WAIT_FOR_BOARDING: Retail 00313be4-00313be8 stores 1 into moby+0x20 after the DISMOUNT arm restores home pose, ends mount and releases ship voices. This same field selects the existing WAIT_FOR_BOARDING arm that waits on proximity and boarding input at 003136c4-00313800. domain_12_value_9 -> JET_FIGHTER_STATE_INACTIVE: Retail delayed-exit arm zeros visibility/collision and sets flags bit 1 at 00313cac-00313cc0, restores destination poses and clears persistence, then stores 9 to moby+0x20 at 00313d94-00313d98. The exact selector already names 9 JET_FIGHTER_STATE_INACTIVE. domain_13_value_4 -> JET_FIGHTER_STATE_FLIGHT: Retail 00313e70-00313e78 compares the moby+0x20 switch selector to 4, then copies ship position and pvars flight angles to hero at 00313e80-00313ea0. It is the same existing FLIGHT member whose switch arm invokes update_player_ship_flight at 00313a18. domain_15_value_4 -> JET_FIGHTER_STATE_FLIGHT: Source tests moby->state == 3 || moby->state == 4 before particles/engine voice. Retail 00313ea4-00313eac implements the pair by unsigned state-minus-3 < 2. Value 4 is the exact same moby+0x20 selector's existing FLIGHT member; no meaning is inferred for adjacent value 3. domain_1_value_1 -> JET_FIGHTER_STATE_WAIT_FOR_BOARDING: Retail 003132dc-003132e0 excludes state byte moby+0x20 value 1 from hit processing. Its existing WAIT_FOR_BOARDING arm at 003136c4-00313800 tests hero proximity, item availability and boarding input before setting that same byte to 2, so reuse the local canonical member. domain_2_value_2 -> JET_FIGHTER_STATE_BOARD: Retail 003132e4-003132e8 excludes moby+0x20 value 2 from hit processing. This is the same selector as the existing BOARD switch arm, which fades at 00313818-00313850 then mounts the hero and initializes ship flight at 003138cc-003139c0. domain_3_value_4 -> JET_FIGHTER_STATE_FLIGHT: Retail 00313308-00313310 requires the moby state byte +0x20 to equal 4 before applying ship damage. Existing FLIGHT case reads that same selector and invokes update_player_ship_flight at 00313a18-00313a1c; 00313e70-00313ea0 also copies the ship pose to hero in state 4. domain_4_value_7 -> JET_FIGHTER_STATE_WAIT_FOR_RESPAWN: On fatal ship damage, retail 00313410 zeros hero ship HP and 00313418 stores 7 into moby+0x20. The existing WAIT_FOR_RESPAWN arm for that exact selector decrements pvars+0xF8 then calls hero_respawn at 00313bf8-00313c14, proving the canonical member. domain_5_value_1 -> JET_FIGHTER_STATE_WAIT_FOR_BOARDING: Retail INITIALIZE arm 00313528-00313534 stores 1 into the same moby+0x20 byte used by the switch. The existing WAIT_FOR_BOARDING arm 003136c4-00313800 checks distance, boarding prerequisite and input, so this initializes that canonical waiting state. domain_6_value_9 -> JET_FIGHTER_STATE_INACTIVE: Retail initialization 00313698-003136c0 detects the mission record sentinel, stores 9 to moby+0x20, zeros collision/visibility and sets flags bit 1. This exact switch selector already has JET_FIGHTER_STATE_INACTIVE at 9; its 00313d9c-00313ddc arm only eases the remaining fade. domain_7_value_2 -> JET_FIGHTER_STATE_BOARD: Retail 003137d8-00313800 checks boarding prerequisite and input, then stores 2 to moby+0x20. The existing BOARD arm on this exact field fades to 1 and assigns hero.ship_moby, ammunition, health and flight state at 00313818-003139c0. domain_8_value_4 -> JET_FIGHTER_STATE_FLIGHT: Retail 003138cc stores 4 to moby+0x20 after boarding fade completes, and 003138d4 assigns this moby to hero.ship_moby before initializing ship health/ammo and flight speed. The same switch field has the existing FLIGHT arm calling the flight updater at 00313a18. domain_9_value_8 -> JET_FIGHTER_STATE_DELAYED_EXIT: Retail 00313a78-00313a90 tests signed pvars+0xE8 <= 0, stores the exit delay to +0xF8 and sets moby+0x20 to 8. Existing DELAYED_EXIT arm 00313c20-00313d98 continues flight, waits on this timer, fades and dismounts before entering inactive state 9. --- src/overlays/l11/mobys/jet_fighter.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/overlays/l11/mobys/jet_fighter.c b/src/overlays/l11/mobys/jet_fighter.c index 4c2043c2ba..35c30f1ebf 100644 --- a/src/overlays/l11/mobys/jet_fighter.c +++ b/src/overlays/l11/mobys/jet_fighter.c @@ -1256,9 +1256,9 @@ void jet_fighter_update(struct Moby *moby) { if (moby != 0) { ship_vars = (ShipVars_2838 *)moby->pvars; fast_dec_timer(&ship_vars->iDC); - if (moby->state != 7 && moby->state != 1 && moby->state != 2) { + if (moby->state != JET_FIGHTER_STATE_WAIT_FOR_RESPAWN && moby->state != JET_FIGHTER_STATE_WAIT_FOR_BOARDING && moby->state != JET_FIGHTER_STATE_BOARD) { hit = find_moby_hit(moby, 0x30001, 0); - if (hit != 0 && moby->state == 4) { + if (hit != 0 && moby->state == JET_FIGHTER_STATE_FLIGHT) { struct Hero *g = &hero; if (hit->damage < g->ship_hp) { g->ship_hp -= hit->damage; @@ -1288,7 +1288,7 @@ void jet_fighter_update(struct Moby *moby) { build_spherical_offset( ship_velocity_scratch, ship_vars->speed, ship_vars->f38, -ship_vars->f34); g->ship_hp = 0.0f; - moby->state = 7; + moby->state = JET_FIGHTER_STATE_WAIT_FOR_RESPAWN; ship_vars->s62 = 0xB4; g->motion.pos.f[2] += 0.2f; g->moby->collision_disable = 0; @@ -1326,7 +1326,7 @@ void jet_fighter_update(struct Moby *moby) { } switch (moby->state) { case JET_FIGHTER_STATE_INITIALIZE: - moby->state = 1; + moby->state = JET_FIGHTER_STATE_WAIT_FOR_BOARDING; ship_vars->sel = 0; moby->scale = moby->pclass->scale; ship_vars->f20 = ship_vars->f30; @@ -1348,7 +1348,7 @@ void jet_fighter_update(struct Moby *moby) { ship_vars->sE8 = 1; ship_vars->fade = 0.0f; if (moby->mission != 0xFF && D_0014C050[current_level_index][moby->mission] == 0xFF) { - moby->state = 9; + moby->state = JET_FIGHTER_STATE_INACTIVE; moby->collision = 0; moby->flags |= 1; moby->visible = 0; @@ -1372,7 +1372,7 @@ void jet_fighter_update(struct Moby *moby) { } } if (item_available[7] != 0 && (((u32)pad_pressed_lui) & 0x10)) { - moby->state = 2; + moby->state = JET_FIGHTER_STATE_BOARD; ship_vars->i118 = -1; } } else { @@ -1400,7 +1400,7 @@ void jet_fighter_update(struct Moby *moby) { help_request(0x2AFC, 0x55); } g = &hero; - moby->state = 4; + moby->state = JET_FIGHTER_STATE_FLIGHT; g->ship_moby = moby; g->ship_oclass = moby->oclass; g->ship_ammo = l11_jet_fighter_initial_ammo; @@ -1452,10 +1452,10 @@ void jet_fighter_update(struct Moby *moby) { } if (ship_vars->sE8 <= 0) { ship_vars->iF8 = D_L11_00162168; - moby->state = 8; + moby->state = JET_FIGHTER_STATE_DELAYED_EXIT; } if (hero.ship_flags & 1) { - moby->state = 5; + moby->state = JET_FIGHTER_STATE_DISMOUNT; } break; case JET_FIGHTER_STATE_DISMOUNT: { @@ -1491,7 +1491,7 @@ void jet_fighter_update(struct Moby *moby) { } } ship_vars->voice2 = -1; - moby->state = 1; + moby->state = JET_FIGHTER_STATE_WAIT_FOR_BOARDING; ship_vars->fade = 0.99f; D_L11_0015F3FC = 0.99f; break; @@ -1539,7 +1539,7 @@ void jet_fighter_update(struct Moby *moby) { if (moby->mission != 0xFF) { jet_clear_persistent(moby->mission); } - moby->state = 9; + moby->state = JET_FIGHTER_STATE_INACTIVE; } } break; @@ -1570,11 +1570,11 @@ void jet_fighter_update(struct Moby *moby) { if (moby->pos.z > 1008.0f) { moby->pos.z = 1008.0f; } - if (moby->state == 4) { + if (moby->state == JET_FIGHTER_STATE_FLIGHT) { qcopy_nc(&hero.motion.pos, &moby->pos); qcopy_nc(&hero.motion.rot, &ship_vars->f30); } - if (moby->state == 3 || moby->state == 4) { + if (moby->state == 3 || moby->state == JET_FIGHTER_STATE_FLIGHT) { emit_type_74_particles_from_moby_joints(moby, ship_vars); if (voice_is_playing(moby, ship_vars->voice) == 0) { ship_vars->voice = allocate_voice_for_target_entry(0, 4, moby); From f74367f79b09066ebf1475cfb5faf8ab689c9db5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:37:41 +0000 Subject: [PATCH 0283/1502] decomp: clarify names in hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: 0x00222450-0x00222460 compares request 0x64 in the dying admission guard; source already uses this canonical member on its request switch. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_10_value_106 -> HERO_STATE_DROWN: 0x002224fc-0x00222500 admits request 0x6A; canonical source DROWN at 0x00222f10-0x002230b4 clears health and selects drowning animation. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_11_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: 0x00222504-0x00222508 admits request 0x80; canonical source branch 0x00222834-0x00222890 clears health and limits inherited momentum. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_12_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: 0x0022250c-0x00222510 admits request 0x82; canonical source branch 0x002230b8-0x00223104 clears health and enters death mode. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x00222540 loads hero+0x20A4; 0x00222564 tests zero before resetting on-foot collision/trail flags. Source maps the loaded byte to Hero.vehicle_mode; original retail Ghidra uses cRam001413f4 for the same tests. Supplied set_hero_idle_state_for_vehicle_mode switches this field with canonical HeroVehicleMode members ON_FOOT=0 and CLANK=1, establishing this exact separate selector domain. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x00222644-0x00222650 loads hero+0x20A4 and delegates nonzero modes to set_hero_idle_state_for_vehicle_mode; zero continues ordinary idle. Source maps the loaded byte to Hero.vehicle_mode; original retail Ghidra uses cRam001413f4 for the same tests. Supplied set_hero_idle_state_for_vehicle_mode switches this field with canonical HeroVehicleMode members ON_FOOT=0 and CLANK=1, establishing this exact separate selector domain. domain_16_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x0022360c-0x00223620 loads hero+0x20A4 and cancels item animation only when this vehicle selector is zero. Source maps the loaded byte to Hero.vehicle_mode; original retail Ghidra uses cRam001413f4 for the same tests. Supplied set_hero_idle_state_for_vehicle_mode switches this field with canonical HeroVehicleMode members ON_FOOT=0 and CLANK=1, establishing this exact separate selector domain. domain_18_value_1 -> HERO_VEHICLE_MODE_CLANK: 0x0022362c-0x00223674 reloads hero+0x20A4 and selects animation 2 for mode 1, matching the supplied idle-mode caller's canonical CLANK arm. Source maps the loaded byte to Hero.vehicle_mode; original retail Ghidra uses cRam001413f4 for the same tests. Supplied set_hero_idle_state_for_vehicle_mode switches this field with canonical HeroVehicleMode members ON_FOOT=0 and CLANK=1, establishing this exact separate selector domain. domain_19_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x00223678 tests the same hero+0x20A4 selector for zero before choosing on-foot speed-step animations. Source maps the loaded byte to Hero.vehicle_mode; original retail Ghidra uses cRam001413f4 for the same tests. Supplied set_hero_idle_state_for_vehicle_mode switches this field with canonical HeroVehicleMode members ON_FOOT=0 and CLANK=1, establishing this exact separate selector domain. domain_1_value_6 -> HERO_STATE_FALL: 0x002224b4-0x002224b8 admits request 6 with zero health; source dispatches this same request under canonical HERO_STATE_FALL. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_20_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x0022435c-0x00224374 tests hero+0x20A4 for zero before fatal-fall entry voice allocation. Source maps the loaded byte to Hero.vehicle_mode; original retail Ghidra uses cRam001413f4 for the same tests. Supplied set_hero_idle_state_for_vehicle_mode switches this field with canonical HeroVehicleMode members ON_FOOT=0 and CLANK=1, establishing this exact separate selector domain. domain_21_value_1 -> HERO_VEHICLE_MODE_CLANK: 0x002243e8-0x00224418 loads hero+0x20A4 and selects animation 4 for vehicle mode 1 during fall entry. Source maps the loaded byte to Hero.vehicle_mode; original retail Ghidra uses cRam001413f4 for the same tests. Supplied set_hero_idle_state_for_vehicle_mode switches this field with canonical HeroVehicleMode members ON_FOOT=0 and CLANK=1, establishing this exact separate selector domain. domain_23_value_41 -> HERO_STATE_GRIND_JUMP: 0x002245b8-0x002245d0 checks the two-request interval beginning 0x29; source already includes canonical GRIND_JUMP in this shared jump dispatch. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_24_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: 0x002245b8-0x002245d0 implements requested_state 0x29..0x2A; source already includes canonical GRIND_RAIL_TRANSFER in this same jump dispatch. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_2_value_61 -> HERO_STATE_DYING: 0x002224bc-0x002224c0 admits request 0x3D; source canonical DYING branch at 0x002227f0 enters death control mode. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_3_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: 0x002224c4-0x002224c8 admits request 0x47; source canonical mode-1 dying branch 0x00226b10-0x00226b54 clears health and sets death mode. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_4_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: 0x002224cc-0x002224d0 admits request 0x57; canonical source mode-3 dying branch 0x002270dc-0x0022711c sets death mode and inherits momentum. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_5_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: 0x002224d4-0x002224d8 admits request 0x62; canonical source mode-2 dying branch 0x00226eac-0x00226eec sets death mode and inherits momentum. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_6_value_119 -> HERO_STATE_FATAL_FALL: 0x002224dc-0x002224e0 admits request 0x77; canonical source FATAL_FALL shares fall setup and initializes tumble targets at 0x00224318-0x002243bc. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_7_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: 0x002224e4-0x002224e8 admits request 0x7B; source uses this canonical shared state member for entry 0x00226724-0x00226784. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_8_value_124 -> HERO_STATE_DEATH_DESCENT: 0x002224ec-0x002224f0 admits request 0x7C; canonical source DEATH_DESCENT at 0x00226788-0x00226844 captures ground height or redirects to DYING. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_9_value_127 -> HERO_STATE_SINK: 0x002224f4-0x002224f8 admits request 0x7F; canonical source SINK at 0x00222894-0x00222930 clears health and targets below water surface. requested_state is the first int argument retained in s1 at 0x00222418, stored to hero.state.current (+0x2084) at 0x00222558 and dispatched at 0x002225f8. Named idle/jump callers and the existing source switch establish the shared HeroStateId domain in include/rnc/hero/hero_state.h. --- src/overlays/shared/hero/hero_set_state.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/shared/hero/hero_set_state.c b/src/overlays/shared/hero/hero_set_state.c index 540ddc5c0d..d118b97fcf 100644 --- a/src/overlays/shared/hero/hero_set_state.c +++ b/src/overlays/shared/hero/hero_set_state.c @@ -686,7 +686,7 @@ int hero_set_state(int requested_state, int b) { V4_222B80 sampled_path_position; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L00_0015F5C4 == 2 || D_L00_0015F5C4 == 6) && b != 2) @@ -694,8 +694,8 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -712,7 +712,7 @@ int hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -740,7 +740,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { set_hero_idle_state_for_vehicle_mode(); return 1; } @@ -1219,14 +1219,14 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation(p->state.step + 3, ((int *)&hero_run_start_frame_by_speed_step)[p->state.step], (float)scale_game_frames(8)); @@ -1607,7 +1607,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -1620,7 +1620,7 @@ int hero_set_state(int requested_state, int b) { q->state.step = 0; qcopy(&q->motion.velocity, &q->motion.resolved_velocity); if (b) { - if (q->vehicle_mode == 1) { + if (q->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(4, 0, (float)scale_game_frames(8)); return 1; } @@ -1696,7 +1696,7 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From feb3c0ba7196414791d0db7cae9debb1772466e6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:39:31 +0000 Subject: [PATCH 0284/1502] decomp: clarify names in update_hero_motion_for_current_state domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: The C tests hero.gravity_mode in CROUCH_SWING. Retail 0x00212358 loads byte hero+0x20B3 and 0x0021235c branches on nonzero before target-heading update. Original Ghidra tests cRam00141403 == 0. This is the supplied HeroGravityMode selector, separate from current state at hero+0x2084; reuse canonical WORLD_DOWN=0. domain_10_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00214fb8 branches when the approach-pose vehicle byte is nonzero; zero enters step-dependent on-foot steering at 0x00214fc0-0x00215018. Original Ghidra identifies the same cRam001413f4 zero comparison. Authoritative C maps it to hero.vehicle_mode, supporting canonical HeroVehicleMode ON_FOOT=0. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00215020 reloads hero+0x20A4 and 0x00215024 skips pose adjustment for nonzero, while zero calls 0x0020d4e0 at 0x0021502c. Original Ghidra corroborates cRam001413f4==0. This exact storage is hero.vehicle_mode in current C and belongs to supplied HeroVehicleMode; reuse ON_FOOT. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021507c-0x00215080 loads hero+0x20A4 and bypasses horizontal-velocity clipping for nonzero; zero calls clipping with argument 1 at 0x00215088-0x0021508c. Original Ghidra corroborates cRam001413f4==0. Source identifies the byte as hero.vehicle_mode, proving canonical HeroVehicleMode ON_FOOT. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: tb is D_L03_0017BD28[hero.attack_record]. Retail 0x00212480-0x0021249c forms its 0x2C-byte row and 0x002124e4-0x002124e8 tests kind at row+4 against zero, selecting spacing 0.75. The same row+4 drives the already named frame-gated-forward switch at 0x002125d8-0x0021264c. Original Ghidra confirms the same table field; reuse HeroComboKind member. domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x002124e4 loads attack-record row+4, and 0x00212514 compares it with 1 to choose spacing 0.6. This is precisely tb->kind from the attack_record*0x2C row, also dispatched at 0x002125dc-0x00212650 into staged speeds 5.7/4.5/3.0. Original Ghidra confirms the shared selector; reuse canonical HeroComboKind member. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: The heading-locked/target branch reloads the same attack-record kind at row+4 (0x00212774) and compares it to 1 at 0x00212778-0x0021277c before yaw-dependent animation-speed adjustment. Original Ghidra uses *(int *)(iVar7+0x17bd2c), identical to the named movement-profile switch selector. Reuse HeroComboKind STAGED_FORWARD_DECELERATION. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x0021281c-0x00212820 compares the reloaded attack-record row+4 kind to 1; 0x00212828-0x00212850 disables heading updates after animation frame 7. Original Ghidra confirms the same field as the staged-forward-deceleration switch. tb points to the indexed 0x2C attack row, proving the supplied HeroComboKind domain. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: In the jump group retail 0x00214c04 loads byte hero+0x20A4 and branches on nonzero at 0x00214c08, calling pose adjustment only for zero. Original Ghidra tests cRam001413f4 == 0. Authoritative C identifies this field as hero.vehicle_mode, the supplied HeroVehicleMode domain, so reuse ON_FOOT=0 rather than a current-state constant. domain_7_value_1 -> HERO_VEHICLE_MODE_CLANK: In APPROACH_TARGET_POSE retail 0x00214ec4 loads hero+0x20A4, compares 3 first, then compares 1 at 0x00214ee0 and selects frame_time*0.9 at 0x00214ee8-0x00214f08. Original Ghidra tests cRam001413f4==1. Source binds this exact byte to hero.vehicle_mode, proving the supplied HeroVehicleMode domain and canonical CLANK=1. domain_9_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x00214f2c loads hero+0x20A4 for approach-pose steering; after the mode-3 branch, 0x00214f78 compares the same byte with 1 and selects turning parameters through 0x00215008. Original Ghidra tests cRam001413f4==1. This is hero.vehicle_mode in the supplied HeroVehicleMode domain; reuse canonical CLANK. --- .../update_hero_motion_for_current_state.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l03/hero/update_hero_motion_for_current_state.c b/src/overlays/l03/hero/update_hero_motion_for_current_state.c index 6566aca017..ad964ea7c4 100644 --- a/src/overlays/l03/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l03/hero/update_hero_motion_for_current_state.c @@ -1380,7 +1380,7 @@ void update_hero_motion_for_current_state(void) { if (hero.anim_changing == 0 && hero.anim_frame > 6.0f) { ok = 0; } - if (ok && hero.gravity_mode == 0) { + if (ok && hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1419,11 +1419,11 @@ void update_hero_motion_for_current_state(void) { if (d < 0.0f) { d = 0.0f; } - if (tb->kind == 0) { + if (tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { attack_spacing_offset = 0.75f; tol = 0.8f; mx = 4.0f; - } else if (tb->kind == 1) { + } else if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { attack_spacing_offset = 0.6f; tol = 1.7f; mx = 4.0f; @@ -1468,7 +1468,7 @@ void update_hero_motion_for_current_state(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || MV(hero.melee_target) != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1478,7 +1478,7 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2247,7 +2247,7 @@ void update_hero_motion_for_current_state(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -2316,7 +2316,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = frame_time * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = frame_time * 0.9f; } } else { @@ -2327,21 +2327,21 @@ void update_hero_motion_for_current_state(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to(0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, frame_time * 9.948377f); } else { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } speed_step(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { From bf0a183905a3e0098736f8f2e80597c831b04c9d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:41:33 +0000 Subject: [PATCH 0285/1502] decomp: clarify names in update_hero_motion_by_state domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Retail 0x0022ad70 loads hero+0x20B3, the source hero.gravity_mode, and 0x0022ad74 bypasses target-heading update when nonzero. Original Ghidra cRam00141403 matches this field. This is the supplied HeroGravityMode selector, not hero.state.current (+0x2084); reuse its canonical WORLD_DOWN member for zero. domain_10_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0022e8c0 compares hero+0x20A4 mode byte with zero before the on-foot step-dependent turning branch; 0x0022e8c8 separately loads state.step at +0x2088. Original Ghidra and source distinguish these selectors. The mode field is the same HeroVehicleMode field used by the supplied named switches; reuse ON_FOOT for zero. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0022e928 reloads hero+0x20A4 and 0x0022e92c bypasses adjust_hero_pose_targets_from_motion at 0x0022e934 when nonzero. Original Ghidra cRam001413f4 and source hero.vehicle_mode agree with the supplied HeroVehicleMode domain and its canonical ON_FOOT member, separate from state.current and step. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0022e984 loads hero+0x20A4; 0x0022e988 bypasses clip_hero_horizontal_velocity(1) at 0x0022e990 when nonzero. Source hero.vehicle_mode and original Ghidra cRam001413f4 identify the same mode byte used by supplied named HeroVehicleMode switches. Reuse canonical ON_FOOT for zero. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: Retail 0x0022afe4-0x0022b000 indexes D_L14_0017C328 by hero.attack_record (+0xA60) with stride 0x2C; 0x0022b048 loads row+4 and tests zero to select spacing 0.75. Source tb points to that attack-record row and its same kind selector already switches on HeroComboKind members. Original Ghidra agrees; reuse canonical kind zero. domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x0022b048-0x0022b0a4 compares the attack-record row+4 against one and chooses spacing 0.6. The row comes from attack_record*0x2C at 0x0022afe4-0x0022b000; source tb->kind is also the selector of the existing HeroComboKind switch. Its one branch at 0x0022b1b4-0x0022b248 stages forward speed by animation frame, proving the canonical domain. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source tb is &D_L14_0017C328[hero.attack_record], so tb->kind belongs to the existing HeroComboKind switch domain. Retail 0x0022b2c0-0x0022b2e0 reloads row+4 and compares one before target-yaw-dependent animation speed adjustment at 0x0022b2e8-0x0022b320. Original Ghidra iVar6==1 agrees; reuse the canonical staged forward deceleration member. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x0022b2d4 loads attack-record row+4; 0x0022b380-0x0022b3b4 compares it with one and disables heading updates after animation frame 7 when animation is stable. Source uses the identical tb->kind selector as its already named HeroComboKind switch, whose one branch stages forward deceleration. Original Ghidra corroborates this separate kind domain. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0022e514 loads byte hero+0x20A4 and 0x0022e518 skips pose adjustment when nonzero. Original Ghidra cRam001413f4 and source hero.vehicle_mode agree. The same field is switched with HERO_VEHICLE_MODE_ON_FOOT in supplied process_hero_hit_reaction and update_hero_smoothed_parameters, proving HeroVehicleMode domain independently of current-state IDs. domain_7_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0022e7cc loads hero+0x20A4; 0x0022e7d4 sets comparison value one and 0x0022e7e8 tests it before selecting target speed frame_time*0.9. Original Ghidra cRam001413f4 agrees with source hero.vehicle_mode, the same field used by supplied HeroVehicleMode switches. Reuse canonical HERO_VEHICLE_MODE_CLANK, not a hero-state member. domain_9_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0022e834 loads hero+0x20A4, 0x0022e83c sets one, and 0x0022e880 compares that mode before selecting turn rates 0.03/0.3/7.8539815. Original Ghidra cRam001413f4 matches source hero.vehicle_mode. Supplied HeroVehicleMode establishes CLANK as canonical one in this exact field domain. --- .../l14/hero/update_hero_motion_by_state.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l14/hero/update_hero_motion_by_state.c b/src/overlays/l14/hero/update_hero_motion_by_state.c index 9dfb42bb3e..e097c93716 100644 --- a/src/overlays/l14/hero/update_hero_motion_by_state.c +++ b/src/overlays/l14/hero/update_hero_motion_by_state.c @@ -1178,7 +1178,7 @@ void update_hero_motion_by_state(void) { if (hero.anim_changing == 0 && hero.anim_frame > 6.0f) { ok = 0; } - if (ok && hero.gravity_mode == 0) { + if (ok && hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1236,11 +1236,11 @@ void update_hero_motion_by_state(void) { if (d < 0.0f) { d = 0.0f; } - if (tb->kind == 0) { + if (tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { attack_spacing_offset = 0.75f; tol = 0.8f; mx = 4.0f; - } else if (tb->kind == 1) { + } else if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { attack_spacing_offset = 0.6f; tol = 1.7f; mx = 4.0f; @@ -1285,7 +1285,7 @@ void update_hero_motion_by_state(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || MV(hero.melee_target) != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1295,7 +1295,7 @@ void update_hero_motion_by_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2384,7 +2384,7 @@ void update_hero_motion_by_state(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -2452,7 +2452,7 @@ void update_hero_motion_by_state(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = D_0015ED6C_a * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = D_0015ED6C_a * 0.9f; } } else { @@ -2463,21 +2463,21 @@ void update_hero_motion_by_state(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to(0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, frame_time * 9.948377f); } else { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } speed_step(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { From 842ad7311bf884491b88fff818b5fe83b7389cc7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:41:34 +0000 Subject: [PATCH 0286/1502] decomp: clarify names in update_hero_motion_by_state domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Current C tests hero.gravity_mode in CROUCH_SWING. Retail 0x0024a038 loads byte hero+0x20B3 and 0x0024a03c skips heading adjustment when nonzero; original Ghidra tests cRam00141403 == 0. This is the gravity selector, distinct from vehicle byte +0x20A4 and state +0x2084, so reuse canonical HeroGravityMode.HERO_GRAVITY_WORLD_DOWN=0 from include/rnc/hero/hero_state.h. domain_10_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Current C tests hero.vehicle_mode == 0 before choosing step-dependent on-foot target-pose turning. Retail 0x0024c4c0 branches on the mode byte loaded from hero+0x20A4; zero reaches the step comparison at 0x0024c4c8 and turning alternatives. Original Ghidra tests cRam001413F4 == 0. Reuse the supplied HeroVehicleMode.ON_FOOT=0 for this proven shared selector. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Current C tests hero.vehicle_mode == 0 before pose adjustment in APPROACH_TARGET_POSE. Retail 0x0024c528 reloads byte hero+0x20A4 and 0x0024c52c-0x0024c538 calls adjust_hero_pose_targets_from_motion only for zero. Original Ghidra confirms cRam001413F4 == 0. This is the same proven HeroVehicleMode selector as speed and turning, so reuse canonical ON_FOOT=0. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Current C tests hero.vehicle_mode == 0 before clip_hero_horizontal_velocity(1) in APPROACH_TARGET_POSE. Retail 0x0024c584-0x0024c594 loads byte hero+0x20A4 and calls 0x00242380 with a0=1 only for zero; original Ghidra confirms cRam001413F4 == 0. Reuse canonical HeroVehicleMode.ON_FOOT=0; the mode byte is distinct from hero.state.current and hero.gravity_mode. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: Current C tb is &D_L11_0017C628[hero.attack_record]. Retail 0x0024a160-0x0024a17c computes row stride 0x2C; 0x0024a1c4-0x0024a1f0 tests row+4 == 0 and selects spacing 0.75. Original Ghidra uses the same row+4 at 0x17C62C, also selecting forward advance below frame 18 at 0x0024a2f0-0x0024a32c. This proves the supplied HeroComboKind domain and its canonical FRAME_GATED_FORWARD_ADVANCE member. domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: The same attack_record-indexed row (stride 0x2C, retail 0x0024a160-0x0024a17c) supplies tb->kind at row+4. Retail 0x0024a1f4-0x0024a220 compares it to 1 and selects spacing 0.6; original Ghidra confirms. The same selector's frame windows choose 5.7, 4.5, then 3.0 forward speed at 0x0024a330-0x0024a3c4, proving canonical HeroComboKind.STAGED_FORWARD_DECELERATION. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Current C tests tb->kind == 1 before target-yaw animation-speed adjustment. Retail 0x0024a454-0x0024a45c loads the same attack-record row+4 and compares to 1; 0x0024a464-0x0024a49c adjusts animation speed for positive yaw difference. Original Ghidra confirms the row+0x17C62C data flow. Reuse canonical HeroComboKind.STAGED_FORWARD_DECELERATION, established by this selector's staged speed path at 0x0024a330-0x0024a3c4. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Current C tests tb->kind == 1 with unchanged animation and frame >7 to inhibit heading updates. Retail 0x0024a450 loads row+4; 0x0024a4fc-0x0024a530 compares it to 1 and gates on hero+0xA9C and +0xAA8. Original Ghidra uses the same attack_record-indexed kind field. This is the same HeroComboKind selector as the staged 5.7/4.5/3.0 forward-speed branch, so reuse its canonical STAGED_FORWARD_DECELERATION member. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Current C jump path tests hero.vehicle_mode == 0 before adjust_hero_pose_targets_from_motion. Retail 0x0024c118-0x0024c128 loads byte hero+0x20A4 and calls 0x002450F0 only for zero; original Ghidra tests cRam001413F4 == 0. The same byte drives mode-dependent target-pose speed/turning at 0x0024c3cc and 0x0024c434, proving the supplied HeroVehicleMode domain; reuse ON_FOOT=0. domain_7_value_1 -> HERO_VEHICLE_MODE_CLANK: Current C APPROACH_TARGET_POSE tests hero.vehicle_mode == 1 and sets target speed frame_time*0.9. Retail 0x0024c3cc-0x0024c410 loads hero+0x20A4, first compares to 3 then 1 and selects 0.9; original Ghidra tests cRam001413F4 == 1. This byte is the supplied HeroVehicleMode selector, separate from current-state and gravity selectors, so reuse canonical CLANK=1. domain_9_value_1 -> HERO_VEHICLE_MODE_CLANK: Current C tests hero.vehicle_mode == 1 for target-pose turning. Retail 0x0024c434 loads hero+0x20A4 and 0x0024c480 compares it with 1, choosing turn parameters 0.03, 0.3 and frame_time*7.8539815. Original Ghidra confirms cRam001413F4 == 1. This is the same HeroVehicleMode byte as the preceding 0.9-speed branch, so reuse canonical CLANK=1. --- .../l11/hero/update_hero_motion_by_state.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l11/hero/update_hero_motion_by_state.c b/src/overlays/l11/hero/update_hero_motion_by_state.c index e399d981f9..1b9dcea7ca 100644 --- a/src/overlays/l11/hero/update_hero_motion_by_state.c +++ b/src/overlays/l11/hero/update_hero_motion_by_state.c @@ -1449,7 +1449,7 @@ void update_hero_motion_by_state(void) { if (hero.anim_changing == 0 && hero.anim_frame > 6.0f) { ok = 0; } - if (ok && hero.gravity_mode == 0) { + if (ok && hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1488,11 +1488,11 @@ void update_hero_motion_by_state(void) { if (d < 0.0f) { d = 0.0f; } - if (tb->kind == 0) { + if (tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { attack_spacing_offset = 0.75f; tol = 0.8f; mx = 4.0f; - } else if (tb->kind == 1) { + } else if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { attack_spacing_offset = 0.6f; tol = 1.7f; mx = 4.0f; @@ -1537,7 +1537,7 @@ void update_hero_motion_by_state(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || MV(hero.melee_target) != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1547,7 +1547,7 @@ void update_hero_motion_by_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2152,7 +2152,7 @@ void update_hero_motion_by_state(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -2221,7 +2221,7 @@ void update_hero_motion_by_state(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = frame_time * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = frame_time * 0.9f; } } else { @@ -2232,21 +2232,21 @@ void update_hero_motion_by_state(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to(0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, frame_time * 9.948377f); } else { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } speed_step(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { From ce9596083ada044dcf6acb41af3691c7f7793e00 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:41:35 +0000 Subject: [PATCH 0287/1502] decomp: clarify names in update_hero_motion_for_current_state domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: In HERO_STATE_CROUCH_SWING, retail 0x0023bebc-0x0023beec loads hero base 0x0013F350 plus 0x20B3 and permits update_hero_target_heading only when that byte is zero. Authoritative C identifies the field as hero.gravity_mode, distinct from current state and vehicle mode. The same snapshot's update_hero_ground_contact_and_gravity switches on this field: HERO_GRAVITY_WORLD_DOWN sets gravity_dir.z=-1.0, whereas the other modes use ground normal or reference point. This binds the comparison to supplied HeroGravityMode and its canonical zero member. domain_10_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0023ea40 tests v1, loaded from hero+0x20A4 at 0x0023e9b4, against zero before selecting on-foot step-dependent turning or stick-scaled turning. C explicitly identifies this selector as hero.vehicle_mode and the same snapshot already uses HERO_VEHICLE_MODE_ON_FOOT in a switch on this field. Supplied HeroVehicleMode declares that canonical zero member; the selector is separate from state step tested at 0x0023ea48. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0023eaa4-0x0023eac0 reloads hero+0x20A4 and invokes adjust_hero_pose_targets_from_motion only when that byte is zero. Original Ghidra tests cRam001413f4; authoritative C binds this exact comparison to hero.vehicle_mode. Supplied HeroVehicleMode declares HERO_VEHICLE_MODE_ON_FOOT=0, also used by the snapshot's smoothing switch on the same field. This proves canonical vehicle-domain reuse. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0023eb04-0x0023eb18 loads hero+0x20A4 and calls clip_hero_horizontal_velocity(1) only when zero, before the independent airborne test at hero+0x30E. Original Ghidra tests cRam001413f4 and C identifies it as hero.vehicle_mode. Supplied HeroVehicleMode and the existing same-field smoothing switch identify zero as HERO_VEHICLE_MODE_ON_FOOT; no hero-state or gravity enum is substituted. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: Retail 0x0023c134-0x0023c150 forms s1 from attack_record at hero+0xA60 times 0x2C plus table 0x0017C0A8; 0x0023c198-0x0023c1c4 loads row+4 and tests zero to select target distance offset 0.75. C names this exact row field tb->kind and switches on the same field using HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE. Retail 0x0023c2c4-0x0023c300 confirms kind zero enables forward target speed only below animation frame 18. This is the supplied HeroComboKind domain, not a hero-state ID. domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x0023c134-0x0023c150 computes the attack_record-indexed 0x2C-byte row at 0x0017C0A8. At 0x0023c198-0x0023c1f4 row+4 is compared with one and selects target distance offset 0.6. C binds this to tb->kind, whose same-field switch already names kind one HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION. Retail 0x0023c304-0x0023c398 corroborates staged speeds 5.7, 4.5 and 3.0 as animation frames advance. Reuse the canonical supplied HeroComboKind member. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x0023c428-0x0023c470 reloads the same attack_record table row's +4 kind, compares it with one, and conditionally adjusts animation speed from attack-heading difference. Row provenance is 0x0023c134-0x0023c150, stride 0x2C and table 0x0017C0A8. C identifies this comparison as tb->kind and its existing same-field switch names one HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION, matching the staged speed body at 0x0023c304-0x0023c398. Thus this comparison belongs to HeroComboKind. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x0023c420-0x0023c508 loads row+4 into v0, compares it to one, and disables heading updates when animation is stable and frame exceeds seven. The row comes from attack_record*0x2C+0x0017C0A8 at 0x0023c134-0x0023c150. Authoritative C calls this field tb->kind; its existing switch uses HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION for the identical field value and staged forward-speed behavior at 0x0023c304-0x0023c398. Reuse that canonical HeroComboKind member. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0023e690-0x0023e6a4 loads byte hero+0x20A4 and calls adjust_hero_pose_targets_from_motion only when zero. Authoritative C identifies that byte as hero.vehicle_mode and the supplied HeroVehicleMode domain declares HERO_VEHICLE_MODE_ON_FOOT=0. The same snapshot's smoothing function switches on hero.vehicle_mode using that canonical member. This is the vehicle selector, separate from hero.state.current at +0x2084 and step at +0x2088. domain_7_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0023e944-0x0023e990 loads byte hero+0x20A4, first tests mode three, then compares against one at 0x0023e968 and scales approach-target speed by 0.9. Original Ghidra identifies the same byte as cRam001413f4. Authoritative C binds this exact load to hero.vehicle_mode; supplied HeroVehicleMode canonically declares HERO_VEHICLE_MODE_CLANK=1. Reuse that vehicle-domain member, without conflating current-state IDs or inferring mode three. domain_9_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0023e9b0-0x0023ea3c loads hero+0x20A4 and compares against one at 0x0023ea00 after testing three, selecting turning coefficients 0.03/0.3 and maximum step frame_time*7.8539815. Original Ghidra uses cRam001413f4 for the same selector. C names it hero.vehicle_mode, proving supplied HeroVehicleMode rather than HeroStateId. Its canonical member for one is HERO_VEHICLE_MODE_CLANK. --- .../update_hero_motion_for_current_state.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l12/hero/update_hero_motion_for_current_state.c b/src/overlays/l12/hero/update_hero_motion_for_current_state.c index d90e474af8..77919b88c6 100644 --- a/src/overlays/l12/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l12/hero/update_hero_motion_for_current_state.c @@ -1759,7 +1759,7 @@ void update_hero_motion_for_current_state(void) { if (hero.anim_changing == 0 && hero.anim_frame > 6.0f) { ok = 0; } - if (ok && hero.gravity_mode == 0) { + if (ok && hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1817,11 +1817,11 @@ void update_hero_motion_for_current_state(void) { if (d < 0.0f) { d = 0.0f; } - if (tb->kind == 0) { + if (tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { combo_target_distance_offset = 0.75f; tol = 0.8f; mx = 4.0f; - } else if (tb->kind == 1) { + } else if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { combo_target_distance_offset = 0.6f; tol = 1.7f; mx = 4.0f; @@ -1866,7 +1866,7 @@ void update_hero_motion_for_current_state(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || MV(hero.melee_target) != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1876,7 +1876,7 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2608,7 +2608,7 @@ void update_hero_motion_for_current_state(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -2677,7 +2677,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = D_0015ED6C_a * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = D_0015ED6C_a * 0.9f; } } else { @@ -2688,21 +2688,21 @@ void update_hero_motion_for_current_state(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to(0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, frame_time * 9.948377f); } else { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } speed_step(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { From dc84d6012f7c976765eab6a1e70fb46671b7d96e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:43:50 +0000 Subject: [PATCH 0288/1502] decomp: clarify names in update_hero_motion_for_current_state domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: In HERO_STATE_CROUCH_SWING, retail 0x0022b8f8 loads byte hero+0x20B3 and 0x0022b8fc skips heading update when nonzero. Original Ghidra cRam00141403 and embedded C hero.gravity_mode identify this exact separate HeroGravityMode selector; the supplied shared header defines WORLD_DOWN=0, distinct from current state +0x2084 and vehicle mode +0x20A4. domain_10_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0022f4a0 branches away when the vehicle byte loaded from hero+0x20A4 is nonzero, then selects step-dependent turning or stick-scale turning for zero at 0x0022f4a8-0x0022f500. Embedded C hero.vehicle_mode and original cRam001413F4 identify the exact supplied HeroVehicleMode domain, so reuse ON_FOOT=0. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0022f508 reloads hero+0x20A4 and 0x0022f50c-0x0022f518 gates adjust_hero_pose_targets_from_motion on zero. Embedded target-pose code tests hero.vehicle_mode and original Ghidra tests cRam001413F4, proving the same separate HeroVehicleMode selector whose established ON_FOOT member is zero. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0022f564 loads hero+0x20A4; 0x0022f568 skips the call at 0x0022f570 when nonzero. That call is embedded clip_hero_horizontal_velocity(1) under hero.vehicle_mode==0. Original Ghidra cRam001413F4 confirms the selector, so reuse supplied HeroVehicleMode ON_FOOT=0 rather than any equal-valued state ID. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: Retail 0x0022ba20-0x0022ba3c indexes D_L08_0017C428 by hero.attack_record with stride 0x2C; 0x0022ba84-0x0022bab0 tests row+4==0 and chooses distance offset 0.75. Embedded C binds this row to tb; the same tb->kind switch already uses the supplied HeroComboKind member for frame-gated forward advance (retail 0x0022bbb0-0x0022bbec). domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x0022ba84 loads attack-record row+4; 0x0022bab4-0x0022bae0 compares it with 1 and chooses distance offset 0.6. Original Ghidra reads row index*0x2C+0x17C42C; embedded tb->kind is the same selector already switched on HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION, whose speed stages appear at 0x0022bbf0-0x0022bc84. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x0022bd14-0x0022bd1c reloads the same attack-record row+4 and compares with 1 before yaw-error-dependent animation-speed adjustment at 0x0022bd24-0x0022bd5c. Source tb points to D_L08_0017C428[hero.attack_record]; this is the exact HeroComboKind domain already named by the adjacent switch, not a hero-state ID. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Original Ghidra tests *(int *)(row+0x17C42C)==1 with animation conditions to suppress heading updates. Retail 0x0022bdbc-0x0022bdf0 compares the same row+4 value to 1, checks animation changing and frame>7; embedded C uses tb->kind, the same HeroComboKind selector as the named staged forward deceleration switch case. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0022f0f8 loads byte hero+0x20A4 and 0x0022f0fc-0x0022f108 calls adjust_hero_pose_targets_from_motion only for zero. Original Ghidra cRam001413F4 and embedded hero.vehicle_mode bind this byte to the supplied HeroVehicleMode domain (ON_FOOT=0), independently of hero.state.current at +0x2084. domain_7_value_1 -> HERO_VEHICLE_MODE_CLANK: In target-pose approach, retail 0x0022f3ac loads hero+0x20A4; 0x0022f3b4/0x0022f3c8 compares that byte to 1 and 0x0022f3d0-0x0022f3f0 selects target speed frame_time*0.9. Embedded hero.vehicle_mode and original Ghidra cRam001413F4 prove this is the supplied HeroVehicleMode selector, whose canonical member CLANK=1. domain_9_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0022f414 loads byte hero+0x20A4; 0x0022f41c sets comparison value 1 and 0x0022f460 selects the frame_time*7.8539815 turning profile for it. Source and original Ghidra identify the same hero.vehicle_mode/cRam001413F4 selector used for speed selection, belonging to supplied HeroVehicleMode with canonical CLANK=1. --- .../update_hero_motion_for_current_state.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l08/hero/update_hero_motion_for_current_state.c b/src/overlays/l08/hero/update_hero_motion_for_current_state.c index c2eedee649..ff07dfa06f 100644 --- a/src/overlays/l08/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l08/hero/update_hero_motion_for_current_state.c @@ -1444,7 +1444,7 @@ void update_hero_motion_for_current_state(void) { if (hero.anim_changing == 0 && hero.anim_frame > 6.0f) { ok = 0; } - if (ok && hero.gravity_mode == 0) { + if (ok && hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1483,11 +1483,11 @@ void update_hero_motion_for_current_state(void) { if (d < 0.0f) { d = 0.0f; } - if (tb->kind == 0) { + if (tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { attack_target_distance_offset = 0.75f; tol = 0.8f; mx = 4.0f; - } else if (tb->kind == 1) { + } else if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { attack_target_distance_offset = 0.6f; tol = 1.7f; mx = 4.0f; @@ -1532,7 +1532,7 @@ void update_hero_motion_for_current_state(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || MV(hero.melee_target) != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1542,7 +1542,7 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2678,7 +2678,7 @@ void update_hero_motion_for_current_state(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -2747,7 +2747,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = D_0015ED6C_a * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = D_0015ED6C_a * 0.9f; } } else { @@ -2758,21 +2758,21 @@ void update_hero_motion_for_current_state(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to(0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, frame_time * 9.948377f); } else { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } speed_step(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { From 6af36d5560f0fc8679f2d3f7303943d6b9f88469 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:43:51 +0000 Subject: [PATCH 0289/1502] decomp: clarify names in update_hero_state_transitions domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: The authoritative C maps hero.vehicle_mode to the unsigned byte at hero+0x20A4; original Ghidra names the same byte cRam001413f4. Retail loads this byte separately from hero.state.current (+0x2084), step (+0x2088) and control_mode (+0x208C), binding the comparisons to the supplied shared HeroVehicleMode enum in include/rnc/hero/hero_state.h rather than any state/input domain. Retail 0x002271FC-0x00227218 tests item_use_locked then loads +0x20A4 at 0x00227208 and compares with 1 at 0x0022720C to bypass that item-use gate. Reuse canonical CLANK=1 in this proven vehicle domain. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: The authoritative C maps hero.vehicle_mode to the unsigned byte at hero+0x20A4; original Ghidra names the same byte cRam001413f4. Retail loads this byte separately from hero.state.current (+0x2084), step (+0x2088) and control_mode (+0x208C), binding the comparisons to the supplied shared HeroVehicleMode enum in include/rnc/hero/hero_state.h rather than any state/input domain. Retail 0x00227224-0x00227240 tests item_select_blocked then loads +0x20A4 at 0x00227230 and compares with 1 at 0x00227234 to bypass that selection gate. Reuse canonical CLANK=1. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative C maps hero.vehicle_mode to the unsigned byte at hero+0x20A4; original Ghidra names the same byte cRam001413f4. Retail loads this byte separately from hero.state.current (+0x2084), step (+0x2088) and control_mode (+0x208C), binding the comparisons to the supplied shared HeroVehicleMode enum in include/rnc/hero/hero_state.h rather than any state/input domain. Retail 0x0022724C loads +0x20A4 and 0x00227250 branches on zero to permit item selector setup, otherwise checking the separate mode 3. This is the canonical ON_FOOT=0 vehicle mode. domain_4_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: The authoritative C maps hero.vehicle_mode to the unsigned byte at hero+0x20A4; original Ghidra names the same byte cRam001413f4. Retail loads this byte separately from hero.state.current (+0x2084), step (+0x2088) and control_mode (+0x208C), binding the comparisons to the supplied shared HeroVehicleMode enum in include/rnc/hero/hero_state.h rather than any state/input domain. Retail 0x00227494-0x002274A0 sets comparison operand 2, loads the vehicle byte at +0x20A4 and excludes that mode from the low-Z fatal-fall transition. Reuse canonical GIANT_CLANK=2 from the proven vehicle domain. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative C maps hero.vehicle_mode to the unsigned byte at hero+0x20A4; original Ghidra names the same byte cRam001413f4. Retail loads this byte separately from hero.state.current (+0x2084), step (+0x2088) and control_mode (+0x208C), binding the comparisons to the supplied shared HeroVehicleMode enum in include/rnc/hero/hero_state.h rather than any state/input domain. Original Ghidra case 1 checks cRam001413f4 == zero; retail 0x002283E8-0x002283EC loads +0x20A4 and bypasses the look-state item animation choices when nonzero. Source names the same selector hero.vehicle_mode; reuse canonical ON_FOOT=0. domain_6_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative C maps hero.vehicle_mode to the unsigned byte at hero+0x20A4; original Ghidra names the same byte cRam001413f4. Retail loads this byte separately from hero.state.current (+0x2084), step (+0x2088) and control_mode (+0x208C), binding the comparisons to the supplied shared HeroVehicleMode enum in include/rnc/hero/hero_state.h rather than any state/input domain. Retail 0x002284D4-0x002284E4 loads +0x20A4; nonzero routes to request_hero_idle_state_for_vehicle_mode, while zero continues the on-foot crouch/idle exits. Original Ghidra case 1 agrees. Reuse canonical ON_FOOT=0 for this != comparison. domain_7_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative C maps hero.vehicle_mode to the unsigned byte at hero+0x20A4; original Ghidra names the same byte cRam001413f4. Retail loads this byte separately from hero.state.current (+0x2084), step (+0x2088) and control_mode (+0x208C), binding the comparisons to the supplied shared HeroVehicleMode enum in include/rnc/hero/hero_state.h rather than any state/input domain. Retail 0x00228EA8-0x00228EDC loads +0x20A4 and skips the target-position braking transition when zero; nonzero with sufficient speed requests state 0x66. Original Ghidra case 0x65 and C agree this is the vehicle selector. Reuse canonical ON_FOOT=0. domain_8_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative C maps hero.vehicle_mode to the unsigned byte at hero+0x20A4; original Ghidra names the same byte cRam001413f4. Retail loads this byte separately from hero.state.current (+0x2084), step (+0x2088) and control_mode (+0x208C), binding the comparisons to the supplied shared HeroVehicleMode enum in include/rnc/hero/hero_state.h rather than any state/input domain. Retail 0x0022D4E0-0x0022D4E4 loads +0x20A4 and skips the look-release-wait item animation choices when nonzero. Original Ghidra case 0x1E checks cRam001413f4 == zero. Reuse canonical ON_FOOT=0. --- .../l16/hero/update_hero_state_transitions.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l16/hero/update_hero_state_transitions.c b/src/overlays/l16/hero/update_hero_state_transitions.c index fd2b1a8c50..d79d64867c 100644 --- a/src/overlays/l16/hero/update_hero_state_transitions.c +++ b/src/overlays/l16/hero/update_hero_state_transitions.c @@ -196,9 +196,9 @@ void update_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L16_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.vehicle_mode == 0 || hero.vehicle_mode == 3)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; if (hero.quick_swap_tap_window != 0) { @@ -260,7 +260,7 @@ void update_hero_state_transitions(void) { } } if (D_L16_0015F638 > hero.motion.pos.f[2] && hero.ground_distance > 2.0f && - hero.vehicle_mode != 2 && hero.state.current != 0x77) { + hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { hero_set_state(0x77, 1); } else { switch (hero.state.current) { @@ -662,7 +662,7 @@ void update_hero_state_transitions(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { @@ -689,7 +689,7 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); break; } @@ -952,7 +952,7 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; @@ -2666,7 +2666,7 @@ void update_hero_state_transitions(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { From 21e0455e7ac550599e0ac34fb063f2a05ad52f1c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:43:51 +0000 Subject: [PATCH 0290/1502] decomp: clarify names in update_arc_motion domain_0_value_1 -> INTEGRATE_ARC_MOTION: Retail a1 is retained in s0 at 0x25b458; 0x25b4e4 stores 1 to s0+0x2f, the identical byte loaded for dispatch at 0x25b45c. Dispatch of 1 reaches 0x25b4e8 and builds/adds XYZ displacement at 0x25b504-0x25b540. Thus the assignment selects the existing INTEGRATE_ARC_MOTION member of this exact local switch domain. domain_1_value_2 -> DESCEND_TO_GROUND: Retail 0x25b5cc-0x25b5d0 loads 2 and branches to the store at 0x25b67c into s0+0x2f, the same arc phase byte dispatched at 0x25b45c. Dispatch of 2 at 0x25b484 reaches 0x25b5d4, integrates Z, queries ground and clamps Z at 0x25b624. This reuses the existing DESCEND_TO_GROUND member for that selector, not the separate moby state domain. domain_2_value_3 -> WAIT_AFTER_GROUND_CLAMP: Retail 0x25b620 loads 3; after object Z is clamped to the ground-query result at 0x25b624, 0x25b62c stores 3 into s0+0x2f. This is the exact dispatch byte at 0x25b45c, and dispatch of 3 at 0x25b488-0x25b490 reaches the flag wait at 0x25b670. Reuse existing WAIT_AFTER_GROUND_CLAMP in the same local arc-state enum. domain_3_value_4 -> ARC_MOTION_FINISHED: Retail 0x25b66c-0x25b67c tests object+0x70 bit 2 and writes 4 to s0+0x2f, the arc selector returned at 0x25b680. Dispatch recognizes only 0-3; with 4, 0x25b48c-0x25b498 returns unchanged without motion. Supplied doom_bot_update caller leaves DOOM_BOT_EXECUTE_JUMP when update_arc_motion returns 4. Therefore 4 ends this arc-motion protocol, without claiming ground contact; phase 2 can fall through to this test before clamping. --- src/overlays/shared/mobys/find_moby_hit.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/mobys/find_moby_hit.c b/src/overlays/shared/mobys/find_moby_hit.c index add6bd3cfc..5cbaa33e23 100644 --- a/src/overlays/shared/mobys/find_moby_hit.c +++ b/src/overlays/shared/mobys/find_moby_hit.c @@ -834,6 +834,9 @@ int update_arc_motion(O_25b440 *moving_object, S_25b440 *arc_motion_state) { DESCEND_TO_GROUND = 2, WAIT_AFTER_GROUND_CLAMP = 3 }; + enum { + ARC_MOTION_FINISHED = 4 + }; float motion_displacement[4]; float prediction_time; float ground_height; @@ -848,7 +851,7 @@ int update_arc_motion(O_25b440 *moving_object, S_25b440 *arc_motion_state) { } if (moving_object->b70 & 2) { blend_moby_animation(moving_object, arc_motion_state->b2D, 0, 10); - arc_motion_state->state = 1; + arc_motion_state->state = INTEGRATE_ARC_MOTION; } case INTEGRATE_ARC_MOTION: approach_w(moving_object, @@ -869,7 +872,7 @@ int update_arc_motion(O_25b440 *moving_object, S_25b440 *arc_motion_state) { (arc_motion_state->f10 * prediction_time - arc_motion_state->f1C * 0.5f * prediction_time * prediction_time)) { blend_moby_animation(moving_object, arc_motion_state->b2E, 0, 10); - arc_motion_state->state = 2; + arc_motion_state->state = DESCEND_TO_GROUND; } } break; @@ -879,7 +882,7 @@ int update_arc_motion(O_25b440 *moving_object, S_25b440 *arc_motion_state) { ground_height = probe_ground_height(moving_object->pos, 0, 0.5f); if (moving_object->z <= ground_height) { moving_object->z = ground_height; - arc_motion_state->state = 3; + arc_motion_state->state = WAIT_AFTER_GROUND_CLAMP; } else { motion_displacement[0] = FUN_001f9dc8_25b440(arc_motion_state->f18) * arc_motion_state->f14; @@ -890,7 +893,7 @@ int update_arc_motion(O_25b440 *moving_object, S_25b440 *arc_motion_state) { } case WAIT_AFTER_GROUND_CLAMP: if (moving_object->b70 & 2) { - arc_motion_state->state = 4; + arc_motion_state->state = ARC_MOTION_FINISHED; } break; } From f62763e0e55809f2e88fb0ba8a94266ebb6eeeaa Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:43:53 +0000 Subject: [PATCH 0291/1502] decomp: clarify names in hero_update_movement domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: The CROUCH_SWING branch compares hero.gravity_mode, the gravity selector assigned by resolve_hero_gravity_mode in supplied hero_update. Retail 0x0021afc0 loads hero+0x20b3 and 0x0021afc4 bypasses target-heading adjustment when nonzero; original Ghidra tests cRam00141403 == 0 in this same branch. This proves HeroGravityMode, whose canonical zero member is HERO_GRAVITY_WORLD_DOWN. domain_10_value_1 -> HERO_VEHICLE_MODE_CLANK: The authoritative source compares hero.vehicle_mode, not the main hero-state selector. Retail 0x0021f500-0x0021f53c tests one from byte hero+0x20a4 and selects approach-target turning with frame-time factor 7.8539815; original Ghidra uses cRam001413f4 == 1 for this branch. This binds the comparison to the supplied shared HeroVehicleMode domain, whose canonical one member is HERO_VEHICLE_MODE_CLANK. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative source compares hero.vehicle_mode, distinct from hero.state.current and state.step. Retail 0x0021f540-0x0021f59c loads byte hero+0x20a4, tests zero and selects ordinary step-dependent or stick-scaled turning; original Ghidra tests cRam001413f4 == 0 at this point. This is the supplied shared HeroVehicleMode selector, so reuse its canonical zero member HERO_VEHICLE_MODE_ON_FOOT. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative source compares hero.vehicle_mode, distinct from hero.state.current and state.step. Retail 0x0021f5a8-0x0021f5b8 loads byte hero+0x20a4, tests zero and calls adjust_hero_pose_targets_from_motion; original Ghidra tests cRam001413f4 == 0 at this point. This is the supplied shared HeroVehicleMode selector, so reuse its canonical zero member HERO_VEHICLE_MODE_ON_FOOT. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative source compares hero.vehicle_mode, distinct from hero.state.current and state.step. Retail 0x0021f604-0x0021f614 loads byte hero+0x20a4, tests zero and enables clip_hero_velocity_against_probed_surfaces; original Ghidra tests cRam001413f4 == 0 at this point. This is the supplied shared HeroVehicleMode selector, so reuse its canonical zero member HERO_VEHICLE_MODE_ON_FOOT. domain_14_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: Source tb is &attack_records[hero.attack_record], a HeroTableRow2C; retail 0x0021f898-0x0021f8cc reads row+4 and tests zero, which allows early forward advance before animation frame 5.5. Original Ghidra uses DAT_0017bc2c plus record_index*0x2c. This is precisely the shared HeroComboKind field, also used by the source's named kind switch; reuse its canonical zero member. domain_15_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source tb is &attack_records[hero.attack_record]; retail 0x0021f8a0-0x0021f8cc tests one in the record's +4 kind field and permits early forward advance before frame 5.5. Original Ghidra identifies the same DAT_0017bc2c + record_index*0x2c field. The WRENCH_COMBO named switch uses this exact selector for staged 5.7/4.5/3.0 forward speeds at 0x0021b404-0x0021b498, proving shared HeroComboKind and its canonical member. domain_16_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source tb is &attack_records[hero.attack_record]; retail 0x0021f92c-0x0021f948 tests one in the record's +4 kind field and selects point index zero instead of two for the paired-point sound. Original Ghidra identifies the same DAT_0017bc2c + record_index*0x2c field. The WRENCH_COMBO named switch uses this exact selector for staged 5.7/4.5/3.0 forward speeds at 0x0021b404-0x0021b498, proving shared HeroComboKind and its canonical member. domain_17_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source tb is &attack_records[hero.attack_record]; retail 0x0021f9f4-0x0021fa3c tests one in the record's +4 kind field and gates positive attack-target yaw error animation-speed adjustment. Original Ghidra identifies the same DAT_0017bc2c + record_index*0x2c field. The WRENCH_COMBO named switch uses this exact selector for staged 5.7/4.5/3.0 forward speeds at 0x0021b404-0x0021b498, proving shared HeroComboKind and its canonical member. domain_18_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source tb is &attack_records[hero.attack_record]; retail 0x0021fa9c-0x0021fad4 tests one in the record's +4 kind field and disables target-heading update after animation frame 7. Original Ghidra identifies the same DAT_0017bc2c + record_index*0x2c field. The WRENCH_COMBO named switch uses this exact selector for staged 5.7/4.5/3.0 forward speeds at 0x0021b404-0x0021b498, proving shared HeroComboKind and its canonical member. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: Source tb is &attack_records[hero.attack_record], a HeroTableRow2C; retail 0x0021b298-0x0021b2c4 reads row+4 and tests zero, which selects 0.75 spacing, 0.8 tolerance and 4.0 speed cap. Original Ghidra uses DAT_0017bc2c plus record_index*0x2c. This is precisely the shared HeroComboKind field, also used by the source's named kind switch; reuse its canonical zero member. domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source tb is &attack_records[hero.attack_record]; retail 0x0021b2c8-0x0021b2f4 tests one in the record's +4 kind field and selects 0.6 spacing, 1.7 tolerance and 4.0 cap. Original Ghidra identifies the same DAT_0017bc2c + record_index*0x2c field. The WRENCH_COMBO named switch uses this exact selector for staged 5.7/4.5/3.0 forward speeds at 0x0021b404-0x0021b498, proving shared HeroComboKind and its canonical member. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source tb is &attack_records[hero.attack_record]; retail 0x0021b528-0x0021b570 tests one in the record's +4 kind field and gates positive attack-target yaw error animation-speed adjustment. Original Ghidra identifies the same DAT_0017bc2c + record_index*0x2c field. The WRENCH_COMBO named switch uses this exact selector for staged 5.7/4.5/3.0 forward speeds at 0x0021b404-0x0021b498, proving shared HeroComboKind and its canonical member. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source tb is &attack_records[hero.attack_record]; retail 0x0021b5d0-0x0021b608 tests one in the record's +4 kind field and disables target-heading update after animation frame 7. Original Ghidra identifies the same DAT_0017bc2c + record_index*0x2c field. The WRENCH_COMBO named switch uses this exact selector for staged 5.7/4.5/3.0 forward speeds at 0x0021b404-0x0021b498, proving shared HeroComboKind and its canonical member. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative source compares hero.vehicle_mode, distinct from hero.state.current and state.step. Retail 0x0021f12c-0x0021f13c loads byte hero+0x20a4, tests zero and calls adjust_hero_pose_targets_from_motion; original Ghidra tests cRam001413f4 == 0 at this point. This is the supplied shared HeroVehicleMode selector, so reuse its canonical zero member HERO_VEHICLE_MODE_ON_FOOT. domain_6_value_1 -> HERO_VEHICLE_MODE_CLANK: The authoritative source compares hero.vehicle_mode, not the main hero-state selector. Retail 0x0021f140-0x0021f154 tests one from byte hero+0x20a4 and calls update_hero_motion_response_parameters; original Ghidra uses cRam001413f4 == 1 for this branch. This binds the comparison to the supplied shared HeroVehicleMode domain, whose canonical one member is HERO_VEHICLE_MODE_CLANK. domain_8_value_1 -> HERO_VEHICLE_MODE_CLANK: The authoritative source compares hero.vehicle_mode, not the main hero-state selector. Retail 0x0021f468-0x0021f490 tests one from byte hero+0x20a4 and scales approach-target speed by 0.9; original Ghidra uses cRam001413f4 == 1 for this branch. This binds the comparison to the supplied shared HeroVehicleMode domain, whose canonical one member is HERO_VEHICLE_MODE_CLANK. --- .../shared/hero/hero_update_movement.c | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/overlays/shared/hero/hero_update_movement.c b/src/overlays/shared/hero/hero_update_movement.c index c4b5ac1c42..faafa43f51 100644 --- a/src/overlays/shared/hero/hero_update_movement.c +++ b/src/overlays/shared/hero/hero_update_movement.c @@ -1312,7 +1312,7 @@ void hero_update_movement(void) { if (hero.anim_changing == 0 && hero.anim_frame > 6.0f) { ok = 0; } - if (ok && hero.gravity_mode == 0) { + if (ok && hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1373,11 +1373,11 @@ void hero_update_movement(void) { if (d < 0.0f) { d = 0.0f; } - if (tb->kind == 0) { + if (tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { off = 0.75f; tol = 0.8f; mx = 4.0f; - } else if (tb->kind == 1) { + } else if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { off = 0.6f; tol = 1.7f; mx = 4.0f; @@ -1422,7 +1422,7 @@ void hero_update_movement(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || (struct MobyView *)hero.melee_target != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1432,7 +1432,7 @@ void hero_update_movement(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2663,10 +2663,10 @@ void hero_update_movement(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } - if (hero.vehicle_mode == 1) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { update_hero_motion_response_parameters(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -2735,7 +2735,7 @@ void hero_update_movement(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = D_0015ED6C_a * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = D_0015ED6C_a * 0.9f; } } else { @@ -2746,21 +2746,21 @@ void hero_update_movement(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to(0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, frame_time * 9.948377f); } else { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } speed_step(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { clip_hero_velocity_against_probed_surfaces(1); } if (hero.air_frames.s != 0) { @@ -2835,12 +2835,12 @@ void hero_update_movement(void) { s32 ok; tb = &attack_records[hero.attack_record]; hero.target_speed = 0.0f; - if ((tb->kind == 0 ? 1 : tb->kind == 1) && hero.anim_frame < 5.5f) { + if ((tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE ? 1 : tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) && hero.anim_frame < 5.5f) { hero.target_speed = frame_time * 3.5f; } if (hero.anim_changing == 0 && (f32)tb->f1C <= hero.anim_frame && hero.anim_frame <= (f32)tb->f20) { - s32 k = tb->kind == 1 ? 0 : 2; + s32 k = tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION ? 0 : 2; moby_point_position((struct MobyView *)hero.moby, k, &v10); moby_point_position((struct MobyView *)hero.moby, k | 1, &v20); fast_vec_add(&v0, &v10, &v20); @@ -2850,7 +2850,7 @@ void hero_update_movement(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || (struct MobyView *)hero.melee_target != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -2860,7 +2860,7 @@ void hero_update_movement(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { From d8049152bd393433ef97839b8feca0935ef8c291 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:45:50 +0000 Subject: [PATCH 0292/1502] decomp: clarify names in update_hero_motion_for_current_state domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: C tests hero.gravity_mode in the untargeted CROUCH_SWING heading gate. Retail 0x00211ff0-0x00212020 loads the byte at hero+0x20B3 and permits update_hero_target_heading only when zero. This is the gravity_mode selector, distinct from vehicle_mode at +0x20A4 and state.current at +0x2084; reuse the supplied HeroGravityMode canonical WORLD_DOWN member. domain_10_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: C tests hero.vehicle_mode for zero before choosing on-foot turning in APPROACH_TARGET_POSE. Retail 0x00214818-0x00214878 branches on the same +0x20A4 byte, then selects step-dependent turn_to or turn_hero_toward_move_direction_with_stick_scale. Same selector as mode-specific speed at 0x00214724; reuse canonical HeroVehicleMode ON_FOOT. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00214880-0x00214898 reloads vehicle-mode byte hero+0x20A4 and calls adjust_hero_pose_targets_from_motion only when zero. C selector is hero.vehicle_mode, shared with preceding mode-specific turning and speed branches. This proves the supplied HeroVehicleMode domain and supports canonical ON_FOOT rather than an unrelated zero-valued state constant. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002148dc-0x002148ec checks hero+0x20A4 for zero before calling adjust_hero_planar_velocity_from_probes(1). C names that byte hero.vehicle_mode and the preceding speed/turn branches read the same field. Reuse supplied HeroVehicleMode canonical ON_FOOT member, keeping it separate from current-state and control selectors. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: C tb is &D_L15_0017C228[hero.attack_record]. Retail 0x00212118-0x00212134 forms that 0x2C-stride row and 0x0021217c-0x002121a8 tests its +4 kind against zero for target spacing. The same +4 selector dispatches at 0x00212270-0x00212288 to frame<18 forward target-speed advancement. This proves the attack-record kind domain described by HeroComboKind in hero_tables.h, so reuse its canonical member. domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: C tb points to the attack_record-selected 0x2C table row; retail 0x0021217c-0x002121d8 compares its +4 kind with one and chooses spacing 0.6, tolerance 1.7 and limit 4.0. The identical selector at 0x00212270-0x002123c8 implements staged forward target speeds 5.7, 4.5 and 3.0. Reuse canonical HeroComboKind member from the supplied shared attack-record domain. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x0021240c-0x00212454 reloads +4 of the same attack_record table row formed at 0x00212118-0x00212134, compares kind with one, then slows animation for a positive heading delta. It is the same kind used by staged forward speeds at 0x002122e8-0x002123c8, not a hero state or attack_record index. Reuse the supplied canonical HeroComboKind member. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x002124b4-0x002124e8 compares +4 of tb with one, then clears the heading-update gate when animation is stable and frame exceeds seven. tb remains the 0x2C-stride hero.attack_record row formed at 0x00212118-0x00212134; the same kind drives staged forward speed reduction at 0x002122e8-0x002123c8. Reuse canonical HeroComboKind member. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: In the shared jump handler C checks hero.vehicle_mode before pose adjustment. Retail 0x0021446c-0x0021447c reads hero+0x20A4 and calls adjust_hero_pose_targets_from_motion only for zero. The same field selects mode-specific speeds/turning at 0x00214724 and 0x0021478c, proving the HeroVehicleMode domain rather than state.current. Reuse its supplied canonical ON_FOOT member. domain_7_value_1 -> HERO_VEHICLE_MODE_CLANK: C APPROACH_TARGET_POSE compares hero.vehicle_mode with one to select frame_time*0.9 target speed. Retail 0x00214724-0x00214768 loads hero+0x20A4, distinguishes three from one and stores that speed. This is the same vehicle-mode byte used for on-foot pose/probe gates, not state.current or control_mode; reuse supplied HeroVehicleMode canonical CLANK member. domain_9_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x00214788-0x00214814 loads hero+0x20A4 and compares it with one before choosing turn_to coefficients 0.03, 0.3 and frame_time*7.8539815. C identifies this selector as hero.vehicle_mode, also used by the speed comparison at 0x00214740. It belongs to supplied HeroVehicleMode; reuse canonical CLANK member. --- .../update_hero_motion_for_current_state.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l15/hero/update_hero_motion_for_current_state.c b/src/overlays/l15/hero/update_hero_motion_for_current_state.c index c5dc49e0a5..a3018ca2ef 100644 --- a/src/overlays/l15/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l15/hero/update_hero_motion_for_current_state.c @@ -1620,7 +1620,7 @@ void update_hero_motion_for_current_state(void) { if (hero.anim_changing == 0 && hero.anim_frame > 6.0f) { ok = 0; } - if (ok && hero.gravity_mode == 0) { + if (ok && hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1662,11 +1662,11 @@ void update_hero_motion_for_current_state(void) { if (d < 0.0f) { d = 0.0f; } - if (tb->kind == 0) { + if (tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { off = 0.75f; tol = 0.8f; mx = 4.0f; - } else if (tb->kind == 1) { + } else if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { off = 0.6f; tol = 1.7f; mx = 4.0f; @@ -1711,7 +1711,7 @@ void update_hero_motion_for_current_state(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || (struct MobyView *)hero.melee_target != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1721,7 +1721,7 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2403,7 +2403,7 @@ void update_hero_motion_for_current_state(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -2471,7 +2471,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = frame_time * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = frame_time * 0.9f; } } else { @@ -2482,21 +2482,21 @@ void update_hero_motion_for_current_state(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to(0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, frame_time * 9.948377f); } else { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } speed_step(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_planar_velocity_from_probes(1); } if (hero.air_frames.s != 0) { From 566beb843de3f4f0789e3e31c59ce670b134bb70 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:45:50 +0000 Subject: [PATCH 0293/1502] decomp: clarify names in television_update domain_0_value_1 -> TELEVISION_UPDATE_BOBBING: The assigned source already declares TELEVISION_UPDATE_BOBBING = 1 for switch(moby->state). Retail 00318bb8 loads that same state byte at moby+0x20; 00318bcc-00318bd0 compares it with 1 and branches to the bobbing update at 00318bfc. Initialization at 00318be0 loads 1 and 00318be8 writes it to the identical moby+0x20 byte, then seeds phase and base height at 00318bec-00318bf8. The target branch advances phase and updates pos.z with saved height plus sine at 00318c3c-00318c5c. Thus the assignment enters the existing named state in the same selector domain. --- src/overlays/l05/mobys/television.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l05/mobys/television.c b/src/overlays/l05/mobys/television.c index b9b276b37d..85ba7cc4e4 100644 --- a/src/overlays/l05/mobys/television.c +++ b/src/overlays/l05/mobys/television.c @@ -25,7 +25,7 @@ void television_update(struct Moby *moby) { moby->scale = moby->pclass->scale * *(float *)&television_scale_multiplier_gp; switch (moby->state) { case TELEVISION_INITIALIZE: - moby->state = 1; + moby->state = TELEVISION_UPDATE_BOBBING; *(float *)television_bobbing_state = random_angle_radians(); *(float *)(television_bobbing_state + 4) = moby->pos.z; break; From ccc76f4ab8258ebaf886d2afcd342e1c180b74ec Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:45:50 +0000 Subject: [PATCH 0294/1502] decomp: clarify names in update_hero_glow_and_extra_manipulators domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Authoritative src/overlays/shared/hero/hero_idle_sequence.c snapshot SHA-256 2ab42a7706595427c1b5634c98891a2cb7138afe1ab39fdbe2ad6f5a3a24cef9 sets manip_owner=&hero and compares manip_owner->vehicle_mode != 0. Retail 00205C90/00205C98 forms hero base 0013F350 in s2; 00205CA0 loads byte +20A4 and 00205CA4 branches to return when nonzero, allowing timed extra manipulators only for zero. The original Ghidra decompilation likewise gates the timer/attachment block with bRam001413f4 == 0 (0013F350+20A4). Earlier 00205A74-00205A98 reads the identical selector to select hero.moby for vehicle modes 1/2. coordinate_hero_frame_update routes nonzero hero.vehicle_mode to update_hero_in_vehicle_mode, confirming this is the vehicle selector, separate from current-state/control fields. include/rnc/hero/hero_state.h defines the canonical HeroVehicleMode member HERO_VEHICLE_MODE_ON_FOOT=0; reuse that exact-domain member. --- src/overlays/shared/hero/hero_idle_sequence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index 4a2acdf316..e1930cec7f 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -501,7 +501,7 @@ void update_hero_glow_and_extra_manipulators(void) { } moby->glow_color = (alpha << 24) | (blue << 16) | (green << 8) | red; manip_owner = &hero; - if (manip_owner->vehicle_mode != 0) + if (manip_owner->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) return; if (fast_dec_timer_s16(&HERO_EXTRA->delay) && moby->prev_seq == 1) { min_delay = scale_game_frames(50); From 755a7c1be6e7c6a4966bcb439c1eabca9b4313b2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:45:51 +0000 Subject: [PATCH 0295/1502] decomp: clarify names in emit_beam_trail_particles domain_0_value_8 -> HERO_STATE_LAND: Authoritative source SHA-256 22a149510b44524e6d39bed68ff1bd0e8e4fccf1461a6d47a23234ebb4c46e15 assigns hero_state = hero.state.current. Retail 0x002b4034 loads v1 from hero base s6+0x2084; 0x002b4040 xori v0,v1,8 and 0x002b4044 movz select trail_sample_limit=2. Original retail decompilation likewise tests iRam001413d4 == 8. This is the same current-state field tested with existing HERO_STATE_LAND earlier at 0x002b3f30..0x002b3f34. Thus the selector belongs to shared HeroStateId in include/rnc/hero/hero_state.h, whose canonical value 8 is HERO_STATE_LAND. domain_1_value_129 -> HERO_STATE_DELAYED_JUMP_OR_R1_REPEAT_EXIT_WAIT: Source assigns hero_state directly from hero.state.current. Retail 0x002b4034 loads this current-state field from s6+0x2084; 0x002b4048 xori v1,v1,0x81 and 0x002b404c movz select trail_sample_limit=1, so 0x002b4050 skips additional interpolated puff samples. Original retail decompilation confirms iRam001413d4 == 0x81 selects bound 1. The value is a hero current-state ID, not beam_moby->state or a control selector, and therefore reuses shared HeroStateId member HERO_STATE_DELAYED_JUMP_OR_R1_REPEAT_EXIT_WAIT=129 from the supplied include/rnc/hero/hero_state.h domain. --- src/overlays/shared/weapons/thruster_pack_flame.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/thruster_pack_flame.c b/src/overlays/shared/weapons/thruster_pack_flame.c index d935a37f30..46155c9513 100644 --- a/src/overlays/shared/weapons/thruster_pack_flame.c +++ b/src/overlays/shared/weapons/thruster_pack_flame.c @@ -818,9 +818,9 @@ void emit_beam_trail_particles(X *x) { fast_vec_sub(&previous_position_delta, &trail_state->v10, &emission_position); hero_state = hero.state.current; trail_sample_limit = 4; - if (hero_state == 8) + if (hero_state == HERO_STATE_LAND) trail_sample_limit = 2; - if (hero_state == 0x81) + if (hero_state == HERO_STATE_DELAYED_JUMP_OR_R1_REPEAT_EXIT_WAIT) trail_sample_limit = 1; for (i = 1; i < trail_sample_limit; i++) { fast_vec_normalize( From 15309f8eec3623b5d54b9b758f66f8e7d5555a5e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:45:51 +0000 Subject: [PATCH 0296/1502] decomp: clarify names in predict_mine_impact domain_0_value_0 -> MINE_STATE_OWNER_ATTACHED: Authoritative src/overlays/shared/weapons/mine.c SHA-256 071410638c5b30a532702f30fc139a8b1bceae99fb158ba4e6b988ca9c5b3971 defines MINE_STATE_OWNER_ATTACHED=0 in mine_update. That caller passes mine_moby itself as argument two in every predict_mine_impact call. In retail, incoming a1 is preserved in s4 at 0x002aa2c0; lbu v0,0x20(s4) at 0x002aa318 and bne v0,zero at 0x002aa31c select between the hero-relative launch position (0x002aa324-0x002aa3bc) and active mine position/countdown (0x002aa424-0x002aa448). Original Ghidra likewise tests param_2+0x20 for zero. The same supplied caller state-zero branch builds the owner bone attachment transform, and its named MINE_STATE_OWNER_ATTACHED checks remove the mine when the mine-glove owner or on-foot requirement is absent. Thus the selector is the same mine object's state domain and the existing canonical member applies, rather than any equal-valued hero enum. --- src/overlays/shared/weapons/mine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/mine.c b/src/overlays/shared/weapons/mine.c index 63e34d1d02..fd0cd0ab56 100644 --- a/src/overlays/shared/weapons/mine.c +++ b/src/overlays/shared/weapons/mine.c @@ -512,7 +512,7 @@ void initialize_moby_motion_at_position(V_2aa008 *requested_position, int predict_mine_impact(char *trajectory_state, char *moby, int mode) __asm__("FUN_L00_002aa2a8"); int predict_mine_impact(char *trajectory_state, char *moby, int mode) { - float trajectory_position[4]; + enum { MINE_STATE_OWNER_ATTACHED = 0 } ;float trajectory_position[4]; float B[4]; float C[4]; float box[4]; @@ -525,7 +525,7 @@ int predict_mine_impact(char *trajectory_state, char *moby, int mode) { if (D_L00_0015F5C4_c != 0) return 0; qcopy(C, &MOBY(moby)->pos); - if (MOBY(moby)->state == 0) { + if (MOBY(moby)->state == MINE_STATE_OWNER_ATTACHED) { trajectory_position[0] = fast_cos(fast_add_rotations( -0.36196801f, From 34aaef25cd29b7c532657420255be85cfed59674 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:45:51 +0000 Subject: [PATCH 0297/1502] decomp: clarify names in update_crate_stack_motion domain_0_value_0 -> CRATE_STATE_INITIALIZE: Retail 0x002d151c loads the current crate state byte at s2+0x20, and 0x002d1520 skips motion when zero. The supplied crate_update passes this same moby to update_crate_stack_motion, gates that call on moby->state != 0, and names switch(moby->state) value 0 CRATE_STATE_INITIALIZE; its branch initializes collision/link state and advances to state 1. Thus this is the crate initialization state, not a hero mode or null pointer. domain_1_value_1 -> CRATE_STATE_BREAKABLE: Retail 0x002d18f0-0x002d18f8 compares the same current crate state byte s2+0x20 against 1 after class 0x1F9 and collision-speed checks. This byte is also read at 0x002d15bc-0x002d15c0 for the existing CRATE_STATE_BREAKABLE switch branch leading to break_crate. Reuse that established same-selector member for the pre-impact comparison. domain_2_value_5 -> CRATE_STATE_IMPACT_TRIGGERED: Retail 0x002d1900-0x002d190c clears byte s2+0xBC and writes 5 to the current crate state byte s2+0x20 after collision above frame_time*0.5 and class 0x1F9 in state 1. The identical state byte selects existing CRATE_STATE_IMPACT_TRIGGERED=5 at 0x002d15c8-0x002d15cc. Reuse that member for this impact transition. domain_3_value_1 -> CRATE_STATE_BREAKABLE: Retail 0x002d18ec/0x002d18fc loads a0 from crate vars+0xA4, the below-crate link traversed at 0x002d1480-0x002d1494. After verifying linked moby class 0x1F9, 0x002d1924-0x002d192c reads that moby's +0x20 state byte and compares it to 1. This is the same crate-state field and class domain as the current-crate comparison and existing CRATE_STATE_BREAKABLE branch. domain_4_value_5 -> CRATE_STATE_IMPACT_TRIGGERED: Retail 0x002d1934-0x002d1940 writes 5 to the below crate's state byte a0+0x20 and clears its +0xBC byte after its class 0x1F9/state 1 checks. a0 comes from current crate vars+0xA4. This mirrors the current-crate impact transition at 0x002d1900-0x002d190c and uses the same state selector as existing CRATE_STATE_IMPACT_TRIGGERED=5. --- src/overlays/shared/pickups/crate.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/pickups/crate.c b/src/overlays/shared/pickups/crate.c index 596d60245a..f1925f84de 100644 --- a/src/overlays/shared/pickups/crate.c +++ b/src/overlays/shared/pickups/crate.c @@ -1234,6 +1234,9 @@ void update_crate_stack_motion(M2d1428 *moby) { CRATE_STATE_BREAKABLE = 1, CRATE_STATE_IMPACT_TRIGGERED = 5 }; + enum { + CRATE_STATE_INITIALIZE = 0 + }; O2d1428 *vars; M2d1428 *chain_cursor, *parent_moby, *next; V2d1428 collision_start, collision_end, landing_position, hero_local_offset, @@ -1262,7 +1265,7 @@ void update_crate_stack_motion(M2d1428 *moby) { if (vars->flags & 2) return; vars->iB4 = D_L00_0015F5CC; - if (moby->state == 0) + if (moby->state == CRATE_STATE_INITIALIZE) continue; fast_vec_sub(&hero_local_offset, &hero.motion.pos, &moby->pos); transform_vector_by_basis(&hero_local_offset, &hero_local_offset, moby->vC0); @@ -1328,12 +1331,12 @@ void update_crate_stack_motion(M2d1428 *moby) { if (hit != 0) { acceleration_scale_or_speed = fast_vec_length(&vars->vel); if (frame_time * 0.5f < acceleration_scale_or_speed) { - if (moby->oclass == 0x1F9 && moby->state == 1) { + if (moby->oclass == 0x1F9 && moby->state == CRATE_STATE_BREAKABLE) { moby->bBC = 0; - moby->state = 5; + moby->state = CRATE_STATE_IMPACT_TRIGGERED; } else if ((parent_moby = vars->parent) != 0 && parent_moby->oclass == 0x1F9 && - parent_moby->state == 1) { - parent_moby->state = 5; + parent_moby->state == CRATE_STATE_BREAKABLE) { + parent_moby->state = CRATE_STATE_IMPACT_TRIGGERED; vars->parent->bBC = 0; } } From 11cdd93851655113c67981f86b80c88beaaee94c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:48:02 +0000 Subject: [PATCH 0298/1502] decomp: clarify names in bolt_update domain_0_value_3 -> BOLT_IDLE: In bolt_update, a0 is preserved as s5 at 002a5df0; the state selector is lbu v1,0x20(s5) at 002a5e4c. Initialization loads 3 at 002a5e78 and stores it to that exact field at 002a5e8c. Current C already defines BOLT_IDLE=3 for this same selector. Retail case 3 at 002a6548 checks hero reach and updates grounded pose and glints, proving the initialized next state is the existing bolt idle phase. domain_1_value_2 -> BOLT_SETTLING: The falling branch applies gravity and collision tests, then after both inclination checks loads 2 at 002a6374 and stores it to bolt state +0x20(s5) at 002a638c. It initializes vars+0x56/+0x57 hop counters at 002a63a0-002a63a4. The same state selector at 002a5e4c dispatches retail case 2 to grounded-position interpolation and quaternion blending at 002a6408-002a64f8. This is exactly the current C local member BOLT_SETTLING=2, not a hero or control domain. domain_2_value_3 -> BOLT_IDLE: Retail case 2 decrements vars hop_left at +0x57 and tests for zero at 002a64fc-002a650c; completion loads 3 at 002a6510 and stores it to the same bolt state +0x20(s5) at 002a6528. Current C defines BOLT_IDLE=3 on the switch reading that field, whose case 3 performs grounded idle/glint updates and hero reach tests at 002a6548-002a67cc. Thus settling completion enters the canonical existing bolt idle member. --- src/overlays/shared/pickups/bolt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/pickups/bolt.c b/src/overlays/shared/pickups/bolt.c index 3258a7e48c..8ce7c93691 100644 --- a/src/overlays/shared/pickups/bolt.c +++ b/src/overlays/shared/pickups/bolt.c @@ -211,7 +211,7 @@ void bolt_update(Bolt *bolt_moby) { } switch (bolt_moby->state) { case BOLT_INITIALIZE: - bolt_moby->state = 3; + bolt_moby->state = BOLT_IDLE; bolt_moby->unk73 = 0x14; bolt_moby->flags |= 0x100; bolt_moby->unk30 = 0x20; @@ -312,7 +312,7 @@ void bolt_update(Bolt *bolt_moby) { settling_inclination_limit)) { return; } - bolt_moby->state = 2; + bolt_moby->state = BOLT_SETTLING; v->hop_frames = v->hop_left = truncate_float_to_s32(scale_time(random_float_between(30.0f, 40.0f))); if (D_L00_00173E40.moby != 0 && FUN_L00_002603d0((void *)D_L00_00173E40.moby) != 0) { @@ -341,7 +341,7 @@ void bolt_update(Bolt *bolt_moby) { if (--v->hop_left != 0) { return; } - bolt_moby->state = 3; + bolt_moby->state = BOLT_IDLE; v->hop_frames = v->hop_left = truncate_float_to_s32(scale_time(random_float_between(10.0f, 20.0f))); return; From a7c746642c09941e9bae75a3a0875648f99c8181 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:48:02 +0000 Subject: [PATCH 0299/1502] decomp: clarify names in update_falling_asteroid domain_0_value_0 -> FALLING_ASTEROID_STATE_FALLING: Input a0 is retained in s6 at 0x002eaeb4; retail 0x002eafec-0x002eaff0 reads the Moby state byte at s6+0x20 and branches away when nonzero. The zero path performs the collision probe at 0x002eb0c4 or target-height crossing at 0x002eb3c4-0x002eb3f0, emits impact particles/debris and advances that same state at 0x002eb690-0x002eb69c. Current C asteroid_update routes mode 1 to update_falling_asteroid, establishing this as its pre-impact falling state, separate from pvars mode. domain_1_value_3 -> FALLING_ASTEROID_IMPACT_REMOVAL_STATE: Retail 0x002eb6a0-0x002eb6ac increments the nonzero Moby state byte at s6+0x20 after the impact transition at 0x002eb690-0x002eb69c. When target height is not 25 (branch at 0x002eb6b0-0x002eb6bc), the handler emits three residual particles at 0x002eb798-0x002eb914. Retail 0x002eb918-0x002eb920 then compares that same state unsigned against 3 and calls removal with s6 at 0x002eb928-0x002eb92c when state >= 3. Thus 3 is the post-impact removal threshold for this branch; the height-25 branch uses a separate timed threshold. --- src/overlays/l09/mobys/asteroid.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l09/mobys/asteroid.c b/src/overlays/l09/mobys/asteroid.c index d90d856188..7f5607d56c 100644 --- a/src/overlays/l09/mobys/asteroid.c +++ b/src/overlays/l09/mobys/asteroid.c @@ -333,6 +333,10 @@ void update_fading_asteroid_debris(unsigned char *moby) { } void update_falling_asteroid(Moby *falling_rock) { + enum { + FALLING_ASTEROID_STATE_FALLING = 0, + FALLING_ASTEROID_IMPACT_REMOVAL_STATE = 3 + }; float movement_step[4]; float collision_probe_offset[4]; float position_or_movement_step[4]; @@ -358,7 +362,7 @@ void update_falling_asteroid(Moby *falling_rock) { updated_rotation_x = fast_add_rotations(falling_rock->rot.x, moby_vars->f40); falling_rock->rot.x = updated_rotation_x; falling_rock->rot.y = fast_add_rotations(updated_rotation_x, moby_vars->f44); - if (falling_rock->state == 0) { + if (falling_rock->state == FALLING_ASTEROID_STATE_FALLING) { if (moby_vars->pos[2] < 100.0f && moby_vars->pos[0] < 500.0f && moby_vars->pos[1] < 500.0f) { position_or_movement_step[0] = random_float_between(-5.0f, 5.0f); @@ -568,7 +572,7 @@ void update_falling_asteroid(Moby *falling_rock) { 1200000.0f, sc); } - if (falling_rock->state >= 3) { + if (falling_rock->state >= FALLING_ASTEROID_IMPACT_REMOVAL_STATE) { mark_moby_for_removal(falling_rock); } } From 304ad0ee33b98a2ef5d32bd228b31d33191d15a3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:48:02 +0000 Subject: [PATCH 0300/1502] decomp: clarify names in wrench_update domain_10_value_10 -> WRENCH_THROW_OUTBOUND: Retail 002a913c-002a9144 reads wrench s3+20 and tests 10 before adding hero velocity and direction-scaled speed, then decelerating speed toward zero. C tests the same wrench_moby->state used by the existing WRENCH_THROW_OUTBOUND=10 switch member; it is not hero state 10. domain_11_value_11 -> WRENCH_THROW_RETURNING: Retail 002a91e8-002a9200 tests outbound speed for zero and writes 11 to byte +20 of wrench s3. This is the same wrench_moby->state selector as existing WRENCH_THROW_RETURNING=11; its return branch at 002a9210-002a92f0 moves toward return position 001403c0. domain_12_value_0 -> WRENCH_NORMAL: Retail 002a938c-002a9404 handles arrival, clears throw history and hero thrown flag, then stores zero to wrench s3+20. C assigns wrench_moby->state=0 at this point. The same selector already has WRENCH_NORMAL=0 for ordinary aim, animation and melee-sweep processing, proving reuse. domain_13_value_10 -> WRENCH_THROW_OUTBOUND: Retail 002a94b0-002a94c4 loads wrench state byte +20, compares with 10 after a collision, and spawns impact effects before reversing into return behavior. This is the existing WRENCH_THROW_OUTBOUND switch domain and member, also tested for outbound movement at 002a913c-002a9144. domain_14_value_11 -> WRENCH_THROW_RETURNING: Retail 002a94c8-002a94e4 halves outbound speed after impact and writes 11 into wrench state byte s3+20. It transitions the same selector to existing WRENCH_THROW_RETURNING, whose branch accelerates toward 001403c0 and clears the throw on arrival; no hero-state constant is involved. domain_15_value_11 -> WRENCH_THROW_RETURNING: Retail 002a94e8-002a950c loads wrench state byte +20 and compares with 11 to choose the negative direction-vector offset -0.37 instead of 1.2 for hit geometry. This is the identical wrench_moby->state selector and existing WRENCH_THROW_RETURNING=11 case used by return movement. domain_2_value_1 -> HERO_STATE_LOOK: Retail 002a855c loads s4 from hero base 0013f350 +2084, then 002a8560 compares it with 1 before the camera reticle/aim ray path. The supplied C assigns player_state=player->state. hero.h binds hero to D_0013F350 and HeroState.current to +2084, proving the HeroStateId domain and its canonical HERO_STATE_LOOK member. domain_3_value_19 -> HERO_STATE_WRENCH_COMBO: Retail 002a8750-002a875c constructs hero base 0013f350, loads current state from +2084 into a0 and compares with 0x13, bypassing the default-animation reset. C current_state=wrench_hero()->state reads that same word; hero.h identifies it as HeroState.current, so shared HeroStateId member HERO_STATE_WRENCH_COMBO applies. domain_4_value_33 -> HERO_STATE_WAIT_FOR_ANIMATION_THEN_IDLE: Retail 002a8758 loads hero+2084 into a0; 002a8760-002a8764 compares that unchanged current-state value with 0x21 to preserve attack animation. hero.h binds D_0013F350+2084 to HeroState.current, matching C current_state, so this is canonical HeroStateId member HERO_STATE_WAIT_FOR_ANIMATION_THEN_IDLE. domain_5_value_43 -> HERO_STATE_GRIND_ATTACK: Retail 002a8758 reads hero+2084, and 002a8768-002a876c compares this current-state word with 0x2b. The same state allows melee processing at 002a882c-002a8834. hero.h identifies this exact global and offset as HeroState.current; therefore the existing HeroStateId member HERO_STATE_GRIND_ATTACK applies. domain_6_value_112 -> HERO_STATE_ATTACK_RECORD_FRAME_EXIT_WAIT: Retail 002a8758 reads current state at D_0013F350+2084, then 002a8770-002a8774 compares it with 0x70 in the animation-preservation gate. This matches C current_state=wrench_hero()->state and hero.h HeroState.current at +2084, proving the shared domain and canonical HERO_STATE_ATTACK_RECORD_FRAME_EXIT_WAIT member. domain_7_value_20 -> HERO_STATE_WRENCH_SLAM: Retail 002a8758 reads hero current state at +2084; 002a8778-002a877c compares it with 0x14. The same field/value gates the frame-27 impact ray at 002a8c90-002a8d30. hero.h maps this word to HeroState.current, establishing canonical HeroStateId member HERO_STATE_WRENCH_SLAM. domain_9_value_10 -> WRENCH_THROW_OUTBOUND: Retail 002a9020 loads byte +20 of the incoming wrench pointer retained in s3, and 002a9014/002a9024 compares it with 10 before starting the throw sound. It is the identical wrench_moby->state selector of the existing WRENCH_THROW_OUTBOUND case, whose movement decelerates along direction at 002a914c-002a9200. --- src/overlays/shared/weapons/wrench.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/shared/weapons/wrench.c b/src/overlays/shared/weapons/wrench.c index 1f2597d126..ba4a1d50fe 100644 --- a/src/overlays/shared/weapons/wrench.c +++ b/src/overlays/shared/weapons/wrench.c @@ -645,7 +645,7 @@ void wrench_update(WrenchMoby *wrench_moby) { float difference, yaw; wrench_moby->parent = player->moby; player_state = player->state; - if (player_state == 1) { + if (player_state == HERO_STATE_LOOK) { if (pad_held_words[0] & 0xA) draw_target_reticle( (int)wrench_moby, 0xFF917267, 1.0f, 0.0f, 0, 0x25, -1, 90.0f, 4); @@ -684,8 +684,8 @@ void wrench_update(WrenchMoby *wrench_moby) { FUN_L00_002a7c70_c((char *)wrench_moby); { int current_state = wrench_hero()->state; - if (current_state != 19 && current_state != 33 && current_state != 43 && - current_state != 112 && current_state != 20) { + if (current_state != HERO_STATE_WRENCH_COMBO && current_state != HERO_STATE_WAIT_FOR_ANIMATION_THEN_IDLE && current_state != HERO_STATE_GRIND_ATTACK && + current_state != HERO_STATE_ATTACK_RECORD_FRAME_EXIT_WAIT && current_state != HERO_STATE_WRENCH_SLAM) { int current = wrench_moby->current_animation; if ((unsigned int)current >= 3 && wrench_moby->current_animation < 6) blend_moby_animation(wrench_moby, 1, 0, scale_game_frames(4)); @@ -898,7 +898,7 @@ void wrench_update(WrenchMoby *wrench_moby) { update_moby_transform_history(control, 0); wrench_moby->parent = control_player->moby; control_player->wrench_state = 2; - if (wrench_moby->state == 10 && control_player->thrown_sound == -1) + if (wrench_moby->state == WRENCH_THROW_OUTBOUND && control_player->thrown_sound == -1) control_player->thrown_sound = allocate_voice_for_target_entry(14, 4, control_player->moby); } @@ -917,7 +917,7 @@ void wrench_update(WrenchMoby *wrench_moby) { } } qcopy(wrench_collision_scratch.v[0], position); - if (wrench_moby->state == 10) { + if (wrench_moby->state == WRENCH_THROW_OUTBOUND) { qcopy(wrench_collision_scratch.v[1], hero_velocity()); fast_vec_scale(wrench_collision_scratch.v[1], wrench_collision_scratch.v[1], 0.7f); fast_vec_add(position, position, wrench_collision_scratch.v[1]); @@ -927,7 +927,7 @@ void wrench_update(WrenchMoby *wrench_moby) { wrench_vars->acceleration += frame_time_cube * 170.0f; approach_value(&wrench_vars->speed, 0.0f, wrench_vars->acceleration); if (wrench_vars->speed == 0.0f) - wrench_moby->state = 11; + wrench_moby->state = WRENCH_THROW_RETURNING; } else { int arrived = 0; float length, steps; @@ -973,7 +973,7 @@ void wrench_update(WrenchMoby *wrench_moby) { wrench_hero()->thrown_sound = -1; clear_moby_transform_history((char *)wrench_hero() + 0x17B0); wrench_hero()->thrown = 0; - wrench_moby->state = 0; + wrench_moby->state = WRENCH_NORMAL; } } collided = 0; @@ -988,14 +988,14 @@ void wrench_update(WrenchMoby *wrench_moby) { wrench_hero()->attack_cooldown = 1; allocate_voice_for_target_entry(2, 0, wrench_moby); } - if (wrench_moby->state == 10) { + if (wrench_moby->state == WRENCH_THROW_OUTBOUND) { spawn_wrench_impact_effects((char *)wrench_moby); wrench_vars->speed *= 0.5f; - wrench_moby->state = 11; + wrench_moby->state = WRENCH_THROW_RETURNING; } } radius = 1.2f; - if (wrench_moby->state == 11) + if (wrench_moby->state == WRENCH_THROW_RETURNING) radius = -0.37f; fast_vec_normalize(wrench_collision_scratch.v[4], wrench_vars->direction, radius); make_hit_descriptor(wrench_collision_scratch.v[1], From 71d4ad6040630b6338783a205c258ab38c5fc36b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:50:00 +0000 Subject: [PATCH 0301/1502] decomp: clarify names in compute_moby_state_from_vertical_probe domain_0_value_11 -> DOOM_BOT_DETONATE: Retail 0x002bfedc loads the moby's +0x20 state into s0; class-5 hit branch 0x002bff58/0x002bff5c replaces s0 with 11 and 0x002bff94 returns it. Caller src/overlays/shared/weapons/doom_bot.c binds compute_moby_state_from_vertical_probe to FUN_L00_002bfec8 at line 121 and stores its return into moby->state at Contact, lines 668-670. The same caller's state enum declares DOOM_BOT_DETONATE=11 at line 171; its case at line 562 calls spawn_explosion, send_blast_hits and mark_moby_for_removal. Thus this is the doom-bot state domain, not HeroStateId or collision materials. domain_1_value_11 -> DOOM_BOT_DETONATE: Retail material dispatch 0x002bff60..0x002bff90 replaces the same s0 moby state loaded from input+0x20 at 0x002bfedc with 11; 0x002bff94 returns it. doom_bot.c explicitly binds this helper to FUN_L00_002bfec8 and assigns its return to moby->state at Contact. Its enum declares DOOM_BOT_DETONATE=11 (line 171), and case DOOM_BOT_DETONATE at line 562 produces the explosion, sends blast hits and removes the moby. This assignment therefore reuses that canonical state name; it does not name or equate the material selector values. --- src/overlays/shared/weapons/doom_bot_movement.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/doom_bot_movement.c b/src/overlays/shared/weapons/doom_bot_movement.c index 0c17767724..f5b7bcb0c9 100644 --- a/src/overlays/shared/weapons/doom_bot_movement.c +++ b/src/overlays/shared/weapons/doom_bot_movement.c @@ -668,6 +668,9 @@ int compute_moby_state_from_vertical_probe(unsigned char *moby) { enum { COLLISION_MATERIAL_WATER = 0 }; + enum { + DOOM_BOT_DETONATE = 11 + }; Vec4 lower_probe_point, upper_probe_point; int resulting_moby_state = MOBY(moby)->state; qcopy(&lower_probe_point, &MOBY(moby)->pos); @@ -678,7 +681,7 @@ int compute_moby_state_from_vertical_probe(unsigned char *moby) { char *hit_moby = (char *)coll_hit_moby; if (hit_moby && ((char *)MOBY(hit_moby)->pclass) && *(short *)(((char *)MOBY(hit_moby)->pclass) + 0x46) == 5) { - resulting_moby_state = 11; + resulting_moby_state = DOOM_BOT_DETONATE; } else { switch (collision_hit_material()) { case COLLISION_MATERIAL_WATER: @@ -688,7 +691,7 @@ int compute_moby_state_from_vertical_probe(unsigned char *moby) { case 11: case 12: case 13: - resulting_moby_state = 11; + resulting_moby_state = DOOM_BOT_DETONATE; break; } } From 051214ca944ed9ea0f1c606f306dd02cca006612 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:50:01 +0000 Subject: [PATCH 0302/1502] decomp: clarify names in update_attached_rocket domain_0_value_1 -> ATTACHED_ROCKET_STATE_ATTACHED: Authoritative src/overlays/l13/mobys/attached_rocket.c SHA-256 5a7c165688f0e46c143f96c45155dc2ba28d87b5a418c080e26125535d918c66: create_attached_rocket sets moby[0x20]=1 after storing its attachment source at pvars+0x20 and joint at +0x26; launch_attached_rocket sets moby->state=0 after installing displacement and enabling collision. Retail update 0x00305aa8-0x00305ab0 loads moby state at +0x20 and branches on value 1. That branch loads the source at 0x00305ab8, copies source rotation and matrix rows at 0x00305ae8-0x00305b08, then follows its joint through moby_point_position at 0x00305b0c-0x00305b14 before skipping flight movement. This proves the rocket-specific attached state, not a boolean TRUE or a source-moby state. --- src/overlays/l13/mobys/attached_rocket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l13/mobys/attached_rocket.c b/src/overlays/l13/mobys/attached_rocket.c index a8cd8c8964..f5d9ff1211 100644 --- a/src/overlays/l13/mobys/attached_rocket.c +++ b/src/overlays/l13/mobys/attached_rocket.c @@ -113,7 +113,7 @@ void spawn_attached_rocket_explosion(struct Moby *moby) __asm__("FUN_L13_003060b /* Moby class 1233 */ void attached_rocket_update(struct Moby *moby) { - AttachedRocketVars *attached_rocket_vars = (AttachedRocketVars *)moby->pvars; + enum { ATTACHED_ROCKET_STATE_ATTACHED = 1 } ;AttachedRocketVars *attached_rocket_vars = (AttachedRocketVars *)moby->pvars; struct Moby *source; struct Moby *target; struct { @@ -130,7 +130,7 @@ void attached_rocket_update(struct Moby *moby) { float other_distance; qcopy(&work.old_pos, &moby->pos); - if (moby->state == 1) { + if (moby->state == ATTACHED_ROCKET_STATE_ATTACHED) { source = attached_rocket_vars->unk20; if (source == 0 || source->oclass != 0x65 || source->state == 0xfe || source->state == 0xfd) goto remove; From 39a6274c75d1f601fc228aec44fc63fc84be8239 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:50:01 +0000 Subject: [PATCH 0303/1502] decomp: clarify names in audio_dec_send domain_0_value_0 -> AUDIO_DEC_SEND_DISABLED: In the authoritative audio_dec_send(struct AudioDec *dec) snapshot, the selector is dec->state. Retail 0x0023aef4 loads that word at offset 0(a0); 0x0023aef8 branches on zero directly to the epilogue at 0x0023af08, bypassing jal send_adpcm at 0x0023af00. Original Ghidra likewise guards FUN_0023afc0 with *param_1 != 0. The checked caller passes DAT_0016120c + 0xd9100 in a0 at 0x0023abb8/0x0023abbc. Supplied send_adpcm context switches on the same AudioDec.state for ADPCM buffer handling. Thus zero specifically disables dispatch from audio_dec_send; the name makes no claim about initialization or shutdown. --- src/audio/decoder/audio_dec_send.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/decoder/audio_dec_send.c b/src/audio/decoder/audio_dec_send.c index a3a1fe1dfa..33ffa535c3 100644 --- a/src/audio/decoder/audio_dec_send.c +++ b/src/audio/decoder/audio_dec_send.c @@ -5,7 +5,10 @@ extern s32 send_adpcm() __asm__("FUN_0023afc0"); void audio_dec_send(struct AudioDec *dec) __asm__("FUN_0023aef0"); void audio_dec_send(struct AudioDec *dec) { - if (dec->state != 0) { + enum { + AUDIO_DEC_SEND_DISABLED = 0 + }; + if (dec->state != AUDIO_DEC_SEND_DISABLED) { send_adpcm(); } } From 4ac61288f978e772ff4747927a4ac601605691d5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:50:01 +0000 Subject: [PATCH 0304/1502] decomp: clarify names in draw_hud_bolt_exclamation_panel domain_1_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x0023a2dc/0x0023a2e4 forms a1=0x0013f350, the exact hero assembler binding in include/rnc/hero/hero.h. At 0x0023a324 lbu v1,0x20a4(a1) reads the u8 Hero.vehicle_mode field, distinct from the current-state lw at +0x2084 at 0x0023a338. Instructions 0x0023a32c-0x0023a330 compare that byte with 2 and branch to 0x0023a608 to return HUD+0x58 without rendering. Original Ghidra agrees via cRam001413f4 != '\x02', and the authoritative C has hero.vehicle_mode == 2. This proves the selector is the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h, whose canonical value-2 member is HERO_VEHICLE_MODE_GIANT_CLANK; reuse it rather than any equal-valued state or gravity member. --- src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c index ea26c24b7f..a9569052de 100644 --- a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c +++ b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c @@ -1381,7 +1381,7 @@ s32 draw_hud_bolt_exclamation_panel(Hud *hud_element) { y = alternate_y; } x = hud_element->x; - if (hero.vehicle_mode == 2) + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) return hud_element->ret; if (hero.state.current == 50) return hud_element->ret; From 494147babd48293ac09b7c28946f08a835462fc1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:50:01 +0000 Subject: [PATCH 0305/1502] decomp: clarify names in get_red_button_sequence_status domain_0_value_7 -> RED_BUTTON_STATE_SEQUENCE_COMPLETE: At 0x003047f8 lbu v1,0x20(a0) reads the linked red-button Moby state; 0x003047fc loads 7 and 0x00304800 branches on equality to the return-2 path at 0x00304810/0x00304814. The supplied original Ghidra plate records red_button_update (0x00304098) entering 7 on sequence completion. In the authoritative C, update_countdown_sequence WAIT_FOR_LINKED_SEQUENCE_COMPLETION waits for this function to return 2 before advancing to its camera path and music. Together these establish red-button sequence completion, distinct from the unrelated HERO_STATE_JUMP value 7. --- src/overlays/l06/mobys/countdown_sequence.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l06/mobys/countdown_sequence.c b/src/overlays/l06/mobys/countdown_sequence.c index e5e820442e..07ebc6d2e0 100644 --- a/src/overlays/l06/mobys/countdown_sequence.c +++ b/src/overlays/l06/mobys/countdown_sequence.c @@ -422,9 +422,12 @@ void begin_red_button_rotation(char *moby) { } s32 get_red_button_sequence_status(const u8 *moby) { + enum { + RED_BUTTON_STATE_SEQUENCE_COMPLETE = 7 + }; u32 state = moby[0x20]; - if (state == 7) { + if (state == RED_BUTTON_STATE_SEQUENCE_COMPLETE) { return 2; } if (state > 3) { From 3c6c3c3d5ef73b1a0340896c0d171ddd206d61c7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:50:01 +0000 Subject: [PATCH 0306/1502] decomp: clarify names in classify_moby_state_two_or_three domain_0_value_2 -> CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP: Retail 0x002dfba0 lbu v1,0x20(a0) loads the Moby state byte and 0x002dfba4-0x002dfba8 compares it with 2, returning 1 at 0x002dfbbc. The supplied drek_final_boss_robot_update caller passes boss_data->f334 to both this classifier and get_camera_transition_progress. In the authoritative camera_transition.c snapshot (SHA-256 5413bcd2a62f89ed23ff3bd9144b66417a07db4e7ec430cfb230c6972504d6dd), start_camera_transition sets moby->state=2; update_camera_transition names that same Moby state STATE_PRE_TRANSITION_RAMP_UP and approaches pvars+0x6C toward 1 before entering state 3 or 4. This establishes the camera-transition state meaning, separate from equal-valued hero constants. domain_1_value_3 -> CAMERA_TRANSITION_STATE_INTERPOLATE_TRANSITION: Retail 0x002dfbac xori v1,v1,3 and 0x002dfbb4 movn v0,zero,v1 leave classification 2 exactly for Moby state byte 3 after excluding state 2. The supplied boss caller tests classification 2 on boss_data->f334, the same pointer supplied to get_camera_transition_progress. The authoritative camera_transition.c names state 3 STATE_INTERPOLATE_TRANSITION: update_camera_transition advances pvars+0x60, lerps position and rotations using that progress, and enters state 5 on completion; get_camera_transition_progress reads the same private-data progress offset +0x60. Thus this comparison denotes camera-transition interpolation, not HERO_STATE_STOP. --- src/overlays/l18/mobys/camera_transition.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l18/mobys/camera_transition.c b/src/overlays/l18/mobys/camera_transition.c index d83d568499..9b4cb4fc66 100644 --- a/src/overlays/l18/mobys/camera_transition.c +++ b/src/overlays/l18/mobys/camera_transition.c @@ -284,13 +284,13 @@ float get_camera_transition_progress(Level18VendorFloatMoby *moby) { s32 classify_moby_state_two_or_three(const u8 *moby) __asm__("FUN_L18_002dfba0"); s32 classify_moby_state_two_or_three(const u8 *moby) { - u32 state = MOBY(moby)->state; + enum { CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP = 2 , CAMERA_TRANSITION_STATE_INTERPOLATE_TRANSITION = 3 } ;u32 state = MOBY(moby)->state; s32 state_classification = 2; - if (state == 2) { + if (state == CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP) { return 1; } - if (state != 3) { + if (state != CAMERA_TRANSITION_STATE_INTERPOLATE_TRANSITION) { state_classification = 0; } return state_classification; From 8b3868b7341c96c56842e2dc1f72419e56f692a2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:52:27 +0000 Subject: [PATCH 0307/1502] decomp: clarify names in predict_mine_impact domain_0_value_0 -> MINE_PREDICTION_REQUIRE_LINKED_MOBY_HIT: Incoming mode is held in s5 by retail 0x002aa2b8. The zero test at 0x002aa3e4 skips adding hero displacement (+0x100) to launch velocity. The same mode zero at 0x002aa57c requires coll_hit_moby and a nonzero 0x002603d0 return (0x002aa588-0x002aa59c) before accepting prediction. Checked helper 0x002603d0-0x002603fc implements supplied get_moby_pvars_link: test moby flags+0x34 bit 0x20, load pvars+0x78, return pvars+8. Caller mine_update tries mode zero on a ground moby with this link before falling back to mode two. Thus both zero tokens identify the same require-linked-moby-hit prediction mode. domain_1_value_0 -> MINE_PREDICTION_REQUIRE_LINKED_MOBY_HIT: Retail 0x002aa57c compares the unchanged third argument in s5 against zero; only zero checks collision moby at 0x00173e58 for null (0x002aa588-0x002aa590), then requires helper 0x002603d0 to return nonzero at 0x002aa594-0x002aa59c. The bounded helper listing proves the return is the moby's pvars+8 link after flags bit 0x20, exactly supplied get_moby_pvars_link. Original Ghidra param_3==0 and current source agree. This is the same control selector and zero value as domain_0_value_0, so reuse its canonical member. domain_2_value_2 -> MINE_PREDICTION_HIDE_LINKED_MOBY_HIT_MARKER: Retail 0x002aa5a0 loads 2 and 0x002aa5a4 compares it to incoming mode s5. For mode two, a nonnull collision moby at 0x002aa5b0 and a nonzero private-variable-link accessor result at 0x002aa5bc-0x002aa5c4 skip add_draw_callback at 0x002aa5d4; all other outcomes queue the established draw_mine_predicted_impact_marker callback 0x002a9c50. Prediction output and success still proceed at 0x002aa5e0-0x002aa634. The checked helper returns moby pvars+8 after flags bit 0x20, proving linked-moby-hit marker suppression without assuming platform or state-enum meanings. --- src/overlays/shared/weapons/mine.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/weapons/mine.c b/src/overlays/shared/weapons/mine.c index fd0cd0ab56..72e3ffb3c4 100644 --- a/src/overlays/shared/weapons/mine.c +++ b/src/overlays/shared/weapons/mine.c @@ -512,7 +512,7 @@ void initialize_moby_motion_at_position(V_2aa008 *requested_position, int predict_mine_impact(char *trajectory_state, char *moby, int mode) __asm__("FUN_L00_002aa2a8"); int predict_mine_impact(char *trajectory_state, char *moby, int mode) { - enum { MINE_STATE_OWNER_ATTACHED = 0 } ;float trajectory_position[4]; + enum { MINE_STATE_OWNER_ATTACHED = 0 } ; enum { MINE_PREDICTION_REQUIRE_LINKED_MOBY_HIT = 0 , MINE_PREDICTION_HIDE_LINKED_MOBY_HIT_MARKER = 2} ;float trajectory_position[4]; float B[4]; float C[4]; float box[4]; @@ -541,7 +541,7 @@ int predict_mine_impact(char *trajectory_state, char *moby, int mode) { trajectory_position[2] = trajectory_position[2] + 0.49082f; qcopy(B, trajectory_state); if (*(int *)(hero_state + 0x2FC) != 0 && - FUN_L00_002603d0_u((void *)*(int *)(hero_state + 0x2FC)) != 0 && mode != 0) { + FUN_L00_002603d0_u((void *)*(int *)(hero_state + 0x2FC)) != 0 && mode != MINE_PREDICTION_REQUIRE_LINKED_MOBY_HIT) { fast_vec_add(B, B, hero_state + 0x100); } x = scale_game_frames(0x78); @@ -585,13 +585,13 @@ int predict_mine_impact(char *trajectory_state, char *moby, int mode) { } } if (x != 0) { - if (mode == 0) { + if (mode == MINE_PREDICTION_REQUIRE_LINKED_MOBY_HIT) { if (coll_hit_moby == 0) return 0; if (FUN_L00_002603d0_u(coll_hit_moby) == 0) return 0; } - if (mode != 2 || coll_hit_moby == 0 || FUN_L00_002603d0_u(coll_hit_moby) == 0) { + if (mode != MINE_PREDICTION_HIDE_LINKED_MOBY_HIT_MARKER || coll_hit_moby == 0 || FUN_L00_002603d0_u(coll_hit_moby) == 0) { add_draw_callback(FUN_L00_002a9c50_c, moby); } { From 0fb1e30f8c7417846da2e48d66fd7f9faf1df417 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:52:27 +0000 Subject: [PATCH 0308/1502] decomp: clarify names in hero_update_movement t198 -> jump_timer_or_trail_mode: In the source shared jump-state block, t198 first snapshots hero.state_timer and compares it with jump_timer_threshold to capture takeoff_pos and select pre-takeoff movement. Retail 0x0021ec3c loads hero+0x198 into a2, 0x0021ec40 loads +0x420, 0x0021ec44 compares equality and 0x0021ec68 tests timer Date: Sat, 31 Oct 2026 14:55:20 +0000 Subject: [PATCH 0309/1502] decomp: clarify names in break_crate domain_9_value_3 -> CRATE_STATE_BROKEN: Retail 002d09cc preserves incoming crate moby a0 in s5; 002d1038 loads v1=3 and 002d1048 stores it to byte +0x20(s5), after debris generation and clearing +0x94. This is precisely moby->state in the authoritative M2d1428 view. Checked caller 0x002cf218 passes the same moby to break_crate and switches on byte moby+0x20; its original decompilation case 3 runs the class-0x1F9 burst, then either removes the broken moby or disables it and enters respawn state 6. The snapshot's same caller names this state CRATE_STATE_BROKEN=3. Thus this assignment enters that exact crate-state domain, independent of oclass-minus-500 and HeroStateId. --- src/overlays/shared/pickups/crate.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/pickups/crate.c b/src/overlays/shared/pickups/crate.c index f1925f84de..4ee983a16d 100644 --- a/src/overlays/shared/pickups/crate.c +++ b/src/overlays/shared/pickups/crate.c @@ -1017,6 +1017,9 @@ void break_crate(M2d1428 *moby, s32 hit, s32 source) { CRATE_VARIANT_FINAL_DAMAGE_STAGE = 10, CRATE_VARIANT_CONDITIONAL_RESPAWN_START = 11 }; + enum { + CRATE_STATE_BROKEN = 3 + }; u8 *vars = (u8 *)moby->vars; V2d09b8 position, away, rotation, basis[3], launch, spawn_pos, spin; s32 kind; @@ -1169,7 +1172,7 @@ void break_crate(M2d1428 *moby, s32 hit, s32 source) { } } *(u32 *)((u8 *)broken_crate_moby + 0x94) = 0; - moby->state = 3; + moby->state = CRATE_STATE_BROKEN; *(u16 *)((u8 *)moby + 0x34) |= 1; moby->bBC = FUN_001fef20_2d09b8(15); if (hit) { From 4940712f00923364157f545bd22bcdc984ce788d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:57:44 +0000 Subject: [PATCH 0310/1502] decomp: clarify names in draw_hud_bolt_exclamation_panel domain_0_value_0 -> FALSE: Retail 0x0023a31c/0x0023a320 loads s32 D_0015ED80 into a2; 0x0023a328 movz s5,v0,a2 selects frame_size-50 precisely when that flag is zero, otherwise retaining frame_size-42. Original Ghidra agrees (iRam0015ed80 == 0). include/rnc/globals.h:21 binds pal_mode to D_0015ED80. src/runtime/set_video_timing.c:17-30 normalizes pal_mode_enabled to pal_mode=0 or pal_mode=1, proving a Boolean PAL-enabled flag; src/rendering/view/update_view_context.c:83 already tests the identical pal_mode selector against FALSE. include/types.h:33 defines FALSE as 0. Reusing FALSE expresses PAL disabled without inventing a video-mode domain or borrowing an unrelated Hero enum. --- src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c index a9569052de..780a9b2f0d 100644 --- a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c +++ b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c @@ -1377,7 +1377,7 @@ s32 draw_hud_bolt_exclamation_panel(Hud *hud_element) { s32 panel_y = frame_size - 42; s32 alternate_y = frame_size - 50; y = panel_y; - if (*(volatile s32 *)&pal_mode == 0) + if (*(volatile s32 *)&pal_mode == FALSE) y = alternate_y; } x = hud_element->x; From 8aac9bc63e594f3293ede949e0c22768d14f823d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:57:45 +0000 Subject: [PATCH 0311/1502] decomp: clarify names in wrench_update domain_2_value_2 -> HERO_WRENCH_STATUS_THROWN: Retail 002a8528-002a854c reads incoming wrench moby byte +0x20 and dispatches only states 10/11 to 002a8ffc. At 002a9000-002a9008, s0 = 0x00140b00 - 0x17b0 = 0x0013f350, the same WrenchHero pointer returned by wrench_hero(). Instructions 002a9010 and 002a901c load 2 and store it to hero+0x10ac, matching control_player->wrench_state = 2. This path updates thrown-wrench transform history, moves outbound with decaying speed at 002a913c-002a9200, or accelerates toward the return point at 002a9204-002a92f0. Therefore 2 marks hero wrench status for a thrown update in either phase, separately from the moby state IDs 10/11 and hero current state at +0x2084. --- src/overlays/shared/weapons/wrench.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/wrench.c b/src/overlays/shared/weapons/wrench.c index ba4a1d50fe..88acfae661 100644 --- a/src/overlays/shared/weapons/wrench.c +++ b/src/overlays/shared/weapons/wrench.c @@ -628,6 +628,9 @@ void wrench_update(WrenchMoby *wrench_moby) { WRENCH_THROW_OUTBOUND = 10, WRENCH_THROW_RETURNING = 11 }; + enum { + HERO_WRENCH_STATUS_THROWN = 2 + }; WrenchVars *wrench_vars = wrench_moby->data; WrenchScratch wrench_collision_scratch; WrenchHero *player = wrench_hero(); @@ -897,7 +900,7 @@ void wrench_update(WrenchMoby *wrench_moby) { WrenchHero *control_player = (WrenchHero *)(control - 0x17B0); update_moby_transform_history(control, 0); wrench_moby->parent = control_player->moby; - control_player->wrench_state = 2; + control_player->wrench_state = HERO_WRENCH_STATUS_THROWN; if (wrench_moby->state == WRENCH_THROW_OUTBOUND && control_player->thrown_sound == -1) control_player->thrown_sound = allocate_voice_for_target_entry(14, 4, control_player->moby); From 66fc53f00459693dd54ee99e126e8c4a3e5750e2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:57:45 +0000 Subject: [PATCH 0312/1502] decomp: clarify names in update_attached_rocket domain_0_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x00305ab8 loads source from rocket pvars+0x20; lbu at 0x00305ad0 reads its Moby.state (+0x20), and 0x00305ad4 branches to rocket removal on 0xFE. Checked level-13 removal helper 0x0025a800-0x0025a818 writes 0xFE to that same state field when moby >= the boundary; supplied mark_moby_for_removal source identifies the boundary as moby_instance_end. This names the proven removal marker and boundary, without inferring a respawn lifecycle. domain_1_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x00305ad0 reads source->state (+0x20), and 0x00305ad8-0x00305adc compares it with 0xFD and removes the attached rocket. Checked removal helper 0x0025a800 uses unsigned moby < boundary; 0x0025a80c-0x0025a810 selects 0xFD and 0x0025a818 stores it to Moby.state. Supplied mark_moby_for_removal identifies this boundary as moby_instance_end, proving this distinct below-boundary removal marker. domain_2_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: After following the attachment joint, retail 0x00305b24 reloads the source from pvars+0x20, 0x00305b30 reads source Moby.state, and 0x00305b34 excludes the same 0xFE marker before propagating flags bit 0. The same s4 constant was initialized at 0x00305acc. Checked helper 0x0025a800-0x0025a818 and supplied mark_moby_for_removal source prove 0xFE is the removal marker selected for moby >= moby_instance_end; reuse the first occurrence's member. domain_3_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x00305b24-0x00305b3c reloads source, reads its Moby.state at +0x20 and excludes 0xFD before inheriting source flags. Register s1 holds the same 0xFD initialized at 0x00305ad8. Checked helper 0x0025a800-0x0025a818 stores 0xFD to Moby.state specifically on the unsigned below-boundary branch; supplied mark_moby_for_removal identifies the boundary as moby_instance_end. Reuse the same canonical removal marker as the earlier comparison. --- src/overlays/l13/mobys/attached_rocket.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l13/mobys/attached_rocket.c b/src/overlays/l13/mobys/attached_rocket.c index f5d9ff1211..ce9879aa64 100644 --- a/src/overlays/l13/mobys/attached_rocket.c +++ b/src/overlays/l13/mobys/attached_rocket.c @@ -113,7 +113,7 @@ void spawn_attached_rocket_explosion(struct Moby *moby) __asm__("FUN_L13_003060b /* Moby class 1233 */ void attached_rocket_update(struct Moby *moby) { - enum { ATTACHED_ROCKET_STATE_ATTACHED = 1 } ;AttachedRocketVars *attached_rocket_vars = (AttachedRocketVars *)moby->pvars; + enum { ATTACHED_ROCKET_STATE_ATTACHED = 1 } ; enum { MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xfd , MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xfe} ;AttachedRocketVars *attached_rocket_vars = (AttachedRocketVars *)moby->pvars; struct Moby *source; struct Moby *target; struct { @@ -132,7 +132,7 @@ void attached_rocket_update(struct Moby *moby) { qcopy(&work.old_pos, &moby->pos); if (moby->state == ATTACHED_ROCKET_STATE_ATTACHED) { source = attached_rocket_vars->unk20; - if (source == 0 || source->oclass != 0x65 || source->state == 0xfe || source->state == 0xfd) + if (source == 0 || source->oclass != 0x65 || source->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || source->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) goto remove; qcopy(&moby->rot, &source->rot); *(OvlQuad *)&moby->rot_row0 = *(OvlQuad *)&source->rot_row0; @@ -142,7 +142,7 @@ void attached_rocket_update(struct Moby *moby) { qcopy(&attached_rocket_vars->unk10, &moby->pos); { struct Moby *source = attached_rocket_vars->unk20; - if (source != 0 && source->state != 0xfe && source->state != 0xfd && + if (source != 0 && source->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && source->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && (source->flags & 1)) moby->flags |= 1; else From a7157b46bca25c1ee45c026a3d8c1bd581704721 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:59:31 +0000 Subject: [PATCH 0313/1502] decomp: clarify names in update_inert_moby domain_0_value_0 -> INERT_MOBY_STATE_UNINITIALIZED: The owned update_inert_moby source tests moby->state == 0. Retail 002f7ab0 loads byte +0x20 and 002f7ab4 skips all initialization when nonzero. Only the zero state enters the block that sets state 1, ORs flags +0x34 with 3 and clears substate +0x31 (002f7abc-002f7acc). Thus zero denotes the pre-initialization state for this callback. domain_1_value_1 -> INERT_MOBY_STATE_INITIALIZED: Retail 002f7ab8 loads 1 and 002f7ac0 stores it to the same moby state byte +0x20 tested at 002f7ab0-002f7ab4. The block also ORs flags with 3 and clears substate; subsequent calls with this state skip the block and return. The owned source and original decompilation agree, proving 1 is this inert moby's completed-initialization marker. --- src/overlays/l18/mobys/inert_moby.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/inert_moby.c b/src/overlays/l18/mobys/inert_moby.c index b214d6fc64..70b69303cf 100644 --- a/src/overlays/l18/mobys/inert_moby.c +++ b/src/overlays/l18/mobys/inert_moby.c @@ -49,8 +49,8 @@ void inert_moby_update(Level18VendorMobyShort *moby) __asm__("FUN_L18_002f7ab0") /* Moby class 1432 */ void inert_moby_update(Level18VendorMobyShort *moby) { - if (moby->state == 0) { - moby->state = 1; + enum { INERT_MOBY_STATE_UNINITIALIZED = 0 , INERT_MOBY_STATE_INITIALIZED = 1 } ;if (moby->state == INERT_MOBY_STATE_UNINITIALIZED) { + moby->state = INERT_MOBY_STATE_INITIALIZED; moby->flags |= 3; moby->substate = 0; } From 10e2eb619bd1ae05dee01b557ec4fb8a05963735 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:59:31 +0000 Subject: [PATCH 0314/1502] decomp: clarify names in cancel_suck_cannon_suction_and_set_state_12 domain_0_value_12 -> ROBOT_DOG_STATE_RECOVER_THEN_REINITIALIZE: Retail 0x002f0050 saves incoming moby a0 in s0; 0x002f0054 loads v1=12 and 0x002f005c stores it to byte +0x20(s0), matching moby->state in the SHA-bound robot_dog.c snapshot. That file's robot_dog_update switches on this same Moby state byte and already labels 12 ROBOT_DOG_STATE_RECOVER_THEN_REINITIALIZE: it calls FUN_L00_002dc9f0(robot_dog_moby, robot_dog_vars->a120), then on success sets state to 0 (ROBOT_DOG_STATE_INITIALIZE) and clears sC8. This is the object's RobotDogState domain, not the hero domain or the separate suction_record+0x68 substate. The original Ghidra decompilation independently confirms the call followed by the +0x20 byte assignment. --- src/overlays/l17/mobys/robot_dog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l17/mobys/robot_dog.c b/src/overlays/l17/mobys/robot_dog.c index aa7f563bf9..63538f88e7 100644 --- a/src/overlays/l17/mobys/robot_dog.c +++ b/src/overlays/l17/mobys/robot_dog.c @@ -727,7 +727,7 @@ int cancel_suck_cannon_suction_and_set_state_12(struct Moby *moby) __asm__("FUN_ int cancel_suck_cannon_suction_and_set_state_12(struct Moby *moby) { int helper_result = cancel_suck_cannon_suction(moby); - moby->state = 0xc; + moby->state = ROBOT_DOG_STATE_RECOVER_THEN_REINITIALIZE; return helper_result; } From fc0f5a74570a0f65b9cb97a37bfa418a4d49c1f5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:59:32 +0000 Subject: [PATCH 0315/1502] decomp: clarify names in hero_update_movement v0 -> movement_and_hit_descriptor_scratch: The unique function-scope Vec4 v0 is reused storage, not a persistent position: retail sp+0x0 is zeroed and set to unit X then transformed into hero.move_dir at 0x00217ab4-0x00217acc; receives target position at 0x00219a18-0x00219a28; receives a target direction transformed for swing pose at 0x00219fd0-0x0021a0b4; receives hero rotation for spring updates at 0x0021e438-0x0021e4bc. In HELD_ITEM_ATTACK, make_hit_descriptor writes this same sp buffer at 0x0021baa8-0x0021bac4, and sphere queries consume it via a3=sp at 0x0021bb28-0x0021bb3c and subsequent queries. Authoritative C and original Ghidra fStack_200 agree. The combined name preserves all these vector and descriptor lifetimes. --- .../shared/hero/hero_update_movement.c | 218 +++++++++--------- 1 file changed, 109 insertions(+), 109 deletions(-) diff --git a/src/overlays/shared/hero/hero_update_movement.c b/src/overlays/shared/hero/hero_update_movement.c index ab20ef787a..2a86cdc75f 100644 --- a/src/overlays/shared/hero/hero_update_movement.c +++ b/src/overlays/shared/hero/hero_update_movement.c @@ -235,7 +235,7 @@ void hero_update_movement(void) { s32 sub = hero.state.step; s32 anim = moby->b53; f32 speed; - Vec4 v0; + Vec4 movement_and_hit_descriptor_scratch; Vec4 v10; Vec4 v20; Vec4 movement_vector_scratch; @@ -270,9 +270,9 @@ void hero_update_movement(void) { stick_target(1.0f, 0); if (hero.state.current == HERO_STATE_LOOK || hero.state.current == 0x1E) { if (hero.unk20A5 != 0) { - v0.q = 0; - v0.f[0] = 1.0f; - transform_vector_by_basis(&hero.motion.move_dir, &v0, &D_L00_00166DD8[0x1F8]); + movement_and_hit_descriptor_scratch.q = 0; + movement_and_hit_descriptor_scratch.f[0] = 1.0f; + transform_vector_by_basis(&hero.motion.move_dir, &movement_and_hit_descriptor_scratch, &D_L00_00166DD8[0x1F8]); hero.motion.move_yaw = *(f32 *)D_L00_00166DD8; turn_to(0, frame_scale_sq, frame_scale_sq * 0.0f, frame_time * 174.53293f); if (D_L00_0015F688 > 0 && fast_dec_timer(&D_L00_0015F688) != 0) { @@ -627,16 +627,16 @@ void hero_update_movement(void) { s32 lo2; s32 hi2; pl = &hero_b; - moby_point_position((struct MobyView *)pl->moby, 4, &v0); + moby_point_position((struct MobyView *)pl->moby, 4, &movement_and_hit_descriptor_scratch); v20.q = 0; v20.f[0] = 0.4f; transform_vector_by_basis(&v20, &v20, &((struct MobyView *)pl->moby)->vC0); - fast_vec_add(&v0, &v0, &v20); + fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &v20); qcopy(&v10, &hero_b.motion.displacement); fast_vec_normalize(&v20, &v20, frame_time * 1.5f); fast_vec_add(&v10, &v10, &v20); v10.f[2] += frame_time * 2.0f; - FUN_L00_0026f080(&v0, &v10, 25200.0f, -1.0f); + FUN_L00_0026f080(&movement_and_hit_descriptor_scratch, &v10, 25200.0f, -1.0f); if (random_integer_below(100) < 40.0f) { lo2 = scale_game_frames(4); hi2 = 11; @@ -651,14 +651,14 @@ void hero_update_movement(void) { if (gm != NULL && gm->hA6 == 0x261) { s32 i; for (i = 0; i < 4; i++) { - moby_point_position(gm, i % 2, &v0); + moby_point_position(gm, i % 2, &movement_and_hit_descriptor_scratch); v20.q = 0; v20.f[0] = -0.15f; transform_vector_by_basis(&v20, &v20, &((struct MobyView *)hero.moby)->vC0); - fast_vec_add(&v0, &v0, &v20); - v0.f[0] += random_float_between(0.0f, 0.03f); - v0.f[1] += random_float_between(0.0f, 0.03f); - v0.f[2] += random_float_between(0.0f, 0.03f); + fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &v20); + movement_and_hit_descriptor_scratch.f[0] += random_float_between(0.0f, 0.03f); + movement_and_hit_descriptor_scratch.f[1] += random_float_between(0.0f, 0.03f); + movement_and_hit_descriptor_scratch.f[2] += random_float_between(0.0f, 0.03f); qcopy(&v10, &hero.motion.displacement); FUN_L00_00262cf0(&v10, &v10, @@ -668,7 +668,7 @@ void hero_update_movement(void) { hero.pack_particle_timer = truncate_float_to_s32((frame_time * 7.0f - hero.ground_speed) / (frame_time * 7.0f) * scale_game_frames(5)); - FUN_L00_0026f080(&v0, &v10, random_float_between(6300.0f, 9450.0f), -1.0f); + FUN_L00_0026f080(&movement_and_hit_descriptor_scratch, &v10, random_float_between(6300.0f, 9450.0f), -1.0f); } } } @@ -750,16 +750,16 @@ void hero_update_movement(void) { fast_vec_normalize(&hero.motion.momentum, &hero.motion.momentum, len); qcopy(&hero.motion.velocity, &hero.motion.momentum); if (fast_dec_timer(&hero.puff_timer) == 2) { - moby_point_position((struct MobyView *)hero.moby, 4, &v0); + moby_point_position((struct MobyView *)hero.moby, 4, &movement_and_hit_descriptor_scratch); v20.q = 0; v20.f[0] = 0.4f; transform_vector_by_basis(&v20, &v20, &((struct MobyView *)hero.moby)->vC0); - fast_vec_add(&v0, &v0, &v20); + fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &v20); qcopy(&v10, &hero.motion.displacement); fast_vec_normalize(&v20, &v20, frame_time * 1.5f); fast_vec_add(&v10, &v10, &v20); v10.f[2] += frame_time * 2.0f; - FUN_L00_0026f080(&v0, &v10, 25200.0f, -1.0f); + FUN_L00_0026f080(&movement_and_hit_descriptor_scratch, &v10, 25200.0f, -1.0f); if (scale_game_frames(40) > hero.state_timer) { hero.puff_timer = random_int_between(scale_game_frames(2), scale_game_frames(5)) + hero.state_timer / 5; @@ -833,9 +833,9 @@ void hero_update_movement(void) { ((struct MobyView *)hero.ground_moby)->hA6 == 0x155) { f32 d; f32 ground_moby_yaw_step_limit; - clear_u64_value(&v0); - fast_vec_add(&v0, &v0, &((struct MobyView *)hero.ground_moby)->u10.v10); - fast_vec_sub(&hero.motion.velocity, &v0, &hero.motion.pos); + clear_u64_value(&movement_and_hit_descriptor_scratch); + fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &((struct MobyView *)hero.ground_moby)->u10.v10); + fast_vec_sub(&hero.motion.velocity, &movement_and_hit_descriptor_scratch, &hero.motion.pos); FUN_L00_0025f730(&hero.motion.velocity, frame_time * 2.0f); d = fast_subtract_rotations(((struct MobyView *)hero.ground_moby)->u40.f48.v, hero.motion.rot.f[2]); @@ -901,8 +901,8 @@ void hero_update_movement(void) { case HERO_STATE_APPROACH_TARGET_MOBY: { f32 hit; f32 hit2; - qcopy(&v0, &((struct MobyView *)hero.grapple_target)->u10.v10); - hero.unk970 = fast_vec_dist(&hero.motion.pos, &v0); + qcopy(&movement_and_hit_descriptor_scratch, &((struct MobyView *)hero.grapple_target)->u10.v10); + hero.unk970 = fast_vec_dist(&hero.motion.pos, &movement_and_hit_descriptor_scratch); hero.target_arrival_frames = scale_game_frames(60); if (hero.grapple_pull_speed > 0.0f) { hero.target_arrival_frames = hero.unk970 / hero.motion.speed_xy; @@ -931,8 +931,8 @@ void hero_update_movement(void) { if (hero.grapple_pull_ending != 0) { step_angle_toward_target(&hero.motion.rot.f[1], 0, 0.0f, frame_time * 3.8397243f); } else { - f32 an = fast_add_rotations(-fast_arc_tan(vector_distance_xy(&hero.motion.pos, &v0), - v0.f[2] - hero.motion.pos.f[2]), + f32 an = fast_add_rotations(-fast_arc_tan(vector_distance_xy(&hero.motion.pos, &movement_and_hit_descriptor_scratch), + movement_and_hit_descriptor_scratch.f[2] - hero.motion.pos.f[2]), 1.5707964f); step_angle_toward_target(&hero.motion.rot.f[1], 0, an, frame_time * 6.4577184f); } @@ -953,12 +953,12 @@ void hero_update_movement(void) { qcopy(&hero.motion.velocity, &hero.motion.displacement); fast_vec_scale(&hero.motion.velocity, &hero.motion.velocity, 0.9f); hero.motion.velocity.f[2] -= frame_time_sq * 15.0f; - qcopy(&v0, &((struct MobyView *)hero.grapple_target)->u10.v10); - hero.unk970 = fast_vec_dist(&hero.motion.pos, &v0); + qcopy(&movement_and_hit_descriptor_scratch, &((struct MobyView *)hero.grapple_target)->u10.v10); + hero.unk970 = fast_vec_dist(&hero.motion.pos, &movement_and_hit_descriptor_scratch); fast_vec_add(&v10, &hero.motion.pos, &hero.motion.velocity); - fast_vec_sub(&movement_vector_scratch, &v10, &v0); + fast_vec_sub(&movement_vector_scratch, &v10, &movement_and_hit_descriptor_scratch); fast_vec_normalize(&movement_vector_scratch, &movement_vector_scratch, hero.tether_radius); - fast_vec_add(&v20, &v0, &movement_vector_scratch); + fast_vec_add(&v20, &movement_and_hit_descriptor_scratch, &movement_vector_scratch); fast_vec_sub(&hero.motion.velocity, &v20, &hero.motion.pos); break; } @@ -987,18 +987,18 @@ void hero_update_movement(void) { } hero.motion.move_yaw = hero.swing_yaw; turn_to(0, frame_scale_sq * 0.02f, frame_scale_sq * 0.3f, frame_time * 4.712389f); - fast_vec_sub(&v0, &((struct MobyView *)hero.swing_target_moby)->u10.v10, &hero.motion.pos); - fast_vec_normalize(&v0, &v0, 1.0f); - if (v0.f[2] < 0.23f) { - v0.f[2] = 0.23f; + fast_vec_sub(&movement_and_hit_descriptor_scratch, &((struct MobyView *)hero.swing_target_moby)->u10.v10, &hero.motion.pos); + fast_vec_normalize(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, 1.0f); + if (movement_and_hit_descriptor_scratch.f[2] < 0.23f) { + movement_and_hit_descriptor_scratch.f[2] = 0.23f; } clear_u64_value(&v20); v20.f[2] = hero.motion.rot.f[2]; euler_rotation_matrix(matrix_vector_scratch, &v20); transpose_rotation_matrix(transposed_yaw_matrix, matrix_vector_scratch); - transform_vector(&v0, &v0, transposed_yaw_matrix); - v10.f[0] = -fast_arc_tan(square_root(v0.f[0] * v0.f[0] + v0.f[2] * v0.f[2]), v0.f[1]); - v10.f[1] = fast_arc_tan(v0.f[2], v0.f[0]); + transform_vector(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, transposed_yaw_matrix); + v10.f[0] = -fast_arc_tan(square_root(movement_and_hit_descriptor_scratch.f[0] * movement_and_hit_descriptor_scratch.f[0] + movement_and_hit_descriptor_scratch.f[2] * movement_and_hit_descriptor_scratch.f[2]), movement_and_hit_descriptor_scratch.f[1]); + v10.f[1] = fast_arc_tan(movement_and_hit_descriptor_scratch.f[2], movement_and_hit_descriptor_scratch.f[0]); spring_angle(&hero.motion.rot.f[1], v10.f[1], &hero.motion.rot_spring_vel.f[1], @@ -1172,14 +1172,14 @@ void hero_update_movement(void) { } } if (hero.past_apex != 0.0f && hero.air_frames.s != 0) { - qcopy(&v0, &hero.motion.pos); - v0.f[2] -= 0.5f; + qcopy(&movement_and_hit_descriptor_scratch, &hero.motion.pos); + movement_and_hit_descriptor_scratch.f[2] -= 0.5f; matrix_vector_scratch[0].f[0] = fast_cos(hero.motion.rot.f[2]); matrix_vector_scratch[0].f[1] = fast_sin(hero.motion.rot.f[2]); matrix_vector_scratch[0].f[2] = 0.0f; make_hit_descriptor( &v10, (struct MobyView *)hero.moby, 0x30000, 1.0f, &matrix_vector_scratch[0]); - collect_mobies_in_sphere(0.8f, &v0, 0x10, (struct MobyView *)hero.moby, &v10); + collect_mobies_in_sphere(0.8f, &movement_and_hit_descriptor_scratch, 0x10, (struct MobyView *)hero.moby, &v10); } if (hero.past_apex != 0.0f && hero.air_frames.s == 0) { if (hero.rise_fall_land_frames == 0) { @@ -1247,8 +1247,8 @@ void hero_update_movement(void) { fall_start_frame = scale_game_frames(14); if (hero.anim_changing == 0 && hero.anim_frame > 23.5f && hero.motion.displacement.f[2] < 0.0f && hero.air_frames.s != 0) { - qcopy(&v0, &hero.motion.pos); - offset_hero_position_against_gravity(&v0, &v0, -0.5f); + qcopy(&movement_and_hit_descriptor_scratch, &hero.motion.pos); + offset_hero_position_against_gravity(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, -0.5f); matrix_vector_scratch[0].f[0] = fast_cos(hero.motion.rot.f[2]) * 2.0f; matrix_vector_scratch[0].f[1] = fast_sin(hero.motion.rot.f[2]) * 2.0f; matrix_vector_scratch[0].f[2] = 0.0f; @@ -1258,7 +1258,7 @@ void hero_update_movement(void) { ((u8 *)&v20)[9] = 1; ((s16 *)&v20)[5] = 0x47; ((u8 *)&v20)[8] = 0; - collect_mobies_in_sphere(0.4f, &v0, 0x10, (struct MobyView *)hero.moby, &v10); + collect_mobies_in_sphere(0.4f, &movement_and_hit_descriptor_scratch, 0x10, (struct MobyView *)hero.moby, &v10); } test_hero_animation_frame_window(27.0f); if (hero.state_timer < rise_end_frame) { @@ -1518,9 +1518,9 @@ void hero_update_movement(void) { movement_vector_scratch.f[1] = fast_sin(hero.motion.rot.f[2]) * 2.0f; movement_vector_scratch.f[2] = 1.3f; make_hit_descriptor( - &v0, (struct MobyView *)hero.moby, 0x30000, 3.0f, &movement_vector_scratch); + &movement_and_hit_descriptor_scratch, (struct MobyView *)hero.moby, 0x30000, 3.0f, &movement_vector_scratch); ((u8 *)&v10)[9] = 3; - v0.f[3] = 5627.925f; + movement_and_hit_descriptor_scratch.f[3] = 5627.925f; ((u8 *)&v10)[8] = 0; a = hero.motion.rot.f[2]; ((s16 *)&v10)[5] = o->hA6; @@ -1530,7 +1530,7 @@ void hero_update_movement(void) { fast_vec_add( &matrix_vector_scratch[0], &matrix_vector_scratch[0], &hero.motion.pos); emit_filtered_entry_sparkles( - o, collect_mobies_in_sphere(0.8f, &matrix_vector_scratch[0], 0, o, &v0)); + o, collect_mobies_in_sphere(0.8f, &matrix_vector_scratch[0], 0, o, &movement_and_hit_descriptor_scratch)); a = fast_add_rotations(hero.motion.rot.f[2], -0.87266463f); matrix_vector_scratch[0].f[0] = fast_cos(a) * 0.8f; matrix_vector_scratch[0].f[1] = fast_sin(a) * 0.8f; @@ -1540,7 +1540,7 @@ void hero_update_movement(void) { emit_filtered_entry_sparkles( o, collect_mobies_in_sphere( - 0.8f, &matrix_vector_scratch[0], 0, (struct MobyView *)hero.moby, &v0)); + 0.8f, &matrix_vector_scratch[0], 0, (struct MobyView *)hero.moby, &movement_and_hit_descriptor_scratch)); a = fast_add_rotations(hero.motion.rot.f[2], 0.87266463f); matrix_vector_scratch[0].f[0] = fast_cos(a) * 0.8f; matrix_vector_scratch[0].f[1] = fast_sin(a) * 0.8f; @@ -1548,7 +1548,7 @@ void hero_update_movement(void) { fast_vec_add( &matrix_vector_scratch[0], &matrix_vector_scratch[0], &hero.motion.pos); emit_filtered_entry_sparkles( - o, collect_mobies_in_sphere(0.8f, &matrix_vector_scratch[0], 0, o, &v0)); + o, collect_mobies_in_sphere(0.8f, &matrix_vector_scratch[0], 0, o, &movement_and_hit_descriptor_scratch)); } } if (scale_game_frames(10) < hero.state_timer) { @@ -1585,8 +1585,8 @@ void hero_update_movement(void) { f32 a; f32 f; update_hero_target_speed_from_stick(); - transform_vector(&v0, &hero_b.motion.move_dir, (Vec4 *)hero_b.inv_rot_matrix); - a = absolute_float(fast_arc_tan(v0.f[0], v0.f[1])); + transform_vector(&movement_and_hit_descriptor_scratch, &hero_b.motion.move_dir, (Vec4 *)hero_b.inv_rot_matrix); + a = absolute_float(fast_arc_tan(movement_and_hit_descriptor_scratch.f[0], movement_and_hit_descriptor_scratch.f[1])); if (a > 0.69813168f) { f32 x0 = hero.target_speed; f32 x1 = hero.ground_speed; @@ -1653,8 +1653,8 @@ void hero_update_movement(void) { if (hero.unk930 > 0.0f) { Vec4 *move_impulse_ptr = &hero.move_impulse; build_scaled_hero_move_impulse(0.7f, 0.0f); - v0.q = hero.move_impulse.q; - hero.target_speed += forward_component(&v0); + movement_and_hit_descriptor_scratch.q = hero.move_impulse.q; + hero.target_speed += forward_component(&movement_and_hit_descriptor_scratch); if (hero.target_speed < frame_time * 0.7f) { hero.target_speed = frame_time * 0.7f; } @@ -1777,15 +1777,15 @@ void hero_update_movement(void) { } if (current_level_index != 0xF) { emit_hero_randomized_motion_effects(4, 2); - v0.f[0] = hero.motion.pos.f[0] + random_float_between(-0.25f, 0.25f); - v0.f[1] = hero.motion.pos.f[1] + random_float_between(-0.25f, 0.25f); - v0.f[2] = hero.motion.pos.f[2] + random_float_between(-0.1f, 0.4f); + movement_and_hit_descriptor_scratch.f[0] = hero.motion.pos.f[0] + random_float_between(-0.25f, 0.25f); + movement_and_hit_descriptor_scratch.f[1] = hero.motion.pos.f[1] + random_float_between(-0.25f, 0.25f); + movement_and_hit_descriptor_scratch.f[2] = hero.motion.pos.f[2] + random_float_between(-0.1f, 0.4f); fast_vec_scale(&v10, &hero.motion.displacement, 0.9f); v10.f[0] += random_float_between(frame_time * -0.7f, frame_time * 0.7f); v10.f[1] += random_float_between(frame_time * -0.7f, frame_time * 0.7f); v10.f[2] += random_float_between(frame_time, frame_time * 2.0f); spawn_random_alpha_rotated_particle( - &v0, &v10, random_float_between(37800.0f, 75600.0f)); + &movement_and_hit_descriptor_scratch, &v10, random_float_between(37800.0f, 75600.0f)); } f = fast_vec_length(&hero.motion.platform_delta); if (f > frame_time * 0.5f) { @@ -1859,7 +1859,7 @@ void hero_update_movement(void) { if (hero.state.current == HERO_STATE_GRIND || hero.state.current == 0x2B) { f32 yaw_angle; f32 rr; - qcopy(&v0, &hero.motion.pos); + qcopy(&movement_and_hit_descriptor_scratch, &hero.motion.pos); yaw_angle = fast_add_rotations(hero.rail_dir_yaw, randf_sym(0.0f, 0.5235988f)); rr = random_float_between(frame_time * 4.0f, frame_time * 7.0f); v10.f[0] = fast_cos(yaw_angle) * rr; @@ -1867,7 +1867,7 @@ void hero_update_movement(void) { v10.f[2] = 0.0f; v10.f[2] = random_float_between(frame_time * 3.0f, frame_time * 5.0f); v10.f[3] = -(frame_time_sq * 30.0f); - spawn_color_decaying_effect_particle(&v0, &v10, 0); + spawn_color_decaying_effect_particle(&movement_and_hit_descriptor_scratch, &v10, 0); } t = hero.items[0].item_id; has = item_defs[t].slot_anim_count != 0; @@ -1924,7 +1924,7 @@ void hero_update_movement(void) { r = hero.unk5CC * (f32)hero.grind_direction; } sample_path((void *)hero.rail_spline, - &v0, + &movement_and_hit_descriptor_scratch, &hero.rail_segment, &hero.rail_seg_frac, r, @@ -2024,7 +2024,7 @@ void hero_update_movement(void) { hero.rail_segment, hero.grind_direction, hero.rail_spline_loops); - fast_vec_sub(&v20, (Vec4 *)hero.rail_spline + (idx + 1), &v0); + fast_vec_sub(&v20, (Vec4 *)hero.rail_spline + (idx + 1), &movement_and_hit_descriptor_scratch); if (fast_vec_length(&v20) < 0.001f) { if (hero.rail_segment == idx) { hero.rail_off_frames = scale_game_frames(1); @@ -2050,13 +2050,13 @@ void hero_update_movement(void) { } if (hero.rail_switching != 0 && hero.rail_transfer_frames <= scale_game_frames(48)) { f32 previous_path_blend_fraction; - fast_vec_sub(&v20, &v0, &v10); + fast_vec_sub(&v20, &movement_and_hit_descriptor_scratch, &v10); hero.rail_transfer_frames++; fast_vec_scale( &v20, &v20, (f32)hero.rail_transfer_frames / (f32)scale_game_frames(48)); previous_path_blend_fraction = (f32)(hero.rail_transfer_frames - 1) / (f32)scale_game_frames(48); - fast_vec_sub(&movement_vector_scratch, &v0, &v10); + fast_vec_sub(&movement_vector_scratch, &movement_and_hit_descriptor_scratch, &v10); fast_vec_scale(&movement_vector_scratch, &movement_vector_scratch, previous_path_blend_fraction); @@ -2065,7 +2065,7 @@ void hero_update_movement(void) { fast_vec_sub(&v20, &movement_vector_scratch, &hero.motion.pos); hero.motion.velocity.f[0] = v20.f[0]; hero.motion.velocity.f[1] = v20.f[1]; - fast_vec_sub(&v20, &v0, &hero.rail_point); + fast_vec_sub(&v20, &movement_and_hit_descriptor_scratch, &hero.rail_point); hero.motion.pos.f[2] += v20.f[2]; if (hero.motion.pos.f[2] < hero.rail_point.f[2]) { if (hero.rail_transfer_frames <= scale_game_frames(48) && @@ -2074,7 +2074,7 @@ void hero_update_movement(void) { } } } else { - fast_vec_sub(&v20, &v0, &hero.rail_point); + fast_vec_sub(&v20, &movement_and_hit_descriptor_scratch, &hero.rail_point); hero.motion.velocity.f[0] = v20.f[0]; hero.motion.velocity.f[1] = v20.f[1]; hero.motion.pos.f[2] += v20.f[2]; @@ -2167,7 +2167,7 @@ void hero_update_movement(void) { if (hero.unk574 < 0.0f) { hero.unk574 = 0.0f; } - fast_vec_sub(&hero.motion.velocity, &v0, &hero.rail_point); + fast_vec_sub(&hero.motion.velocity, &movement_and_hit_descriptor_scratch, &hero.rail_point); fast_vec_sub(&v20, &hero.rail_point, &hero.motion.pos); { f32 mx = frame_time * 7.0f; @@ -2211,13 +2211,13 @@ void hero_update_movement(void) { case HERO_STATE_FOLLOW_PATH: { s32 idx; s32 n; - compute_hero_fixed_offset_world_position(&v0); + compute_hero_fixed_offset_world_position(&movement_and_hit_descriptor_scratch); if (((struct MobyView *)hero.moby)->b53 == 0x66) { release_voice_slot_cf(0, (struct MobyView *)hero.moby, 0); if (D_L00_0015F5CC & 1) { f32 a; f32 r; - qcopy(&v10, &v0); + qcopy(&v10, &movement_and_hit_descriptor_scratch); fast_vec_scale(&v20, &hero.motion.displacement, 0.4f); a = fast_add_rotations(hero.grab_rail_yaw, randf_sym(0.0f, 0.5235988f)); r = random_float_between(frame_time * 0.0f, frame_time * 4.0f); @@ -2229,7 +2229,7 @@ void hero_update_movement(void) { } } FUN_L00_0025df68(hero.follow_path_spline, - &v0, + &movement_and_hit_descriptor_scratch, &hero.grab_rail_point, &hero.follow_path_segment, &hero.rail_candidate_frac, @@ -2266,7 +2266,7 @@ void hero_update_movement(void) { turn_to(0, frame_scale_sq * 0.018f, frame_scale_sq * 0.2f, frame_time * 6.4577184f); approach_value(&hero.follow_path_speed, frame_time * 14.0f, frame_time_sq * 9.0f); fast_vec_sub(&hero.motion.velocity, &v10, &hero.grab_rail_point); - fast_vec_sub(&v20, &hero.grab_rail_point, &v0); + fast_vec_sub(&v20, &hero.grab_rail_point, &movement_and_hit_descriptor_scratch); { f32 fl; f32 len; @@ -2333,7 +2333,7 @@ void hero_update_movement(void) { if (hero.ledge_found == 0) { break; } - qcopy(&v0, &hero.ledge_hang_pos); + qcopy(&movement_and_hit_descriptor_scratch, &hero.ledge_hang_pos); a = fast_add_rotations(hero.ledge_normal_yaw, 3.1415927f); qcopy(&hero.motion.pos, &movement_vector_scratch); check_ledge_grab(); @@ -2347,7 +2347,7 @@ void hero_update_movement(void) { break; } a = fast_add_rotations(fast_subtract_rotations(a, b) * 0.5f, a); - fast_vec_add(&matrix_vector_scratch[1], &v0, &v10); + fast_vec_add(&matrix_vector_scratch[1], &movement_and_hit_descriptor_scratch, &v10); fast_vec_scale(&matrix_vector_scratch[1], &matrix_vector_scratch[1], 0.5f); hero.motion.move_yaw = a; turn_to(0, frame_scale_sq * 0.04f, frame_scale_sq * 0.2f, frame_time * 6.2831855f); @@ -2374,15 +2374,15 @@ void hero_update_movement(void) { if (hero.ground_distance > 4.0f) { t = 0.43633232f; } - qcopy(&v0, &hero.motion.rot); - spring_angle(&v0.f[1], + qcopy(&movement_and_hit_descriptor_scratch, &hero.motion.rot); + spring_angle(&movement_and_hit_descriptor_scratch.f[1], t, &hero.motion.rot_spring_vel.f[1], 0, frame_scale_sq * 0.02f, frame_scale_sq * 0.3f, frame_time * 2.6179938f); - spring_angle(&v0.f[0], + spring_angle(&movement_and_hit_descriptor_scratch.f[0], 0.0f, &hero.motion.rot_spring_vel.f[0], 0, @@ -2627,12 +2627,12 @@ void hero_update_movement(void) { frame_time_sq * 53.0f * (f32)hero.state_timer); } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { - qcopy(&v0, &hero.motion.pos); - FUN_L00_00233810(&v0, &v0, 0.5f); - qcopy(&v10, &v0); + qcopy(&movement_and_hit_descriptor_scratch, &hero.motion.pos); + FUN_L00_00233810(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, 0.5f); + qcopy(&v10, &movement_and_hit_descriptor_scratch); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; v10.f[1] += fast_sin(hero.motion.rot.f[2]) * 0.85f; - if (collision_line(&v0, &v10, 4, (struct MobyView *)hero.moby, 0) != 0) { + if (collision_line(&movement_and_hit_descriptor_scratch, &v10, 4, (struct MobyView *)hero.moby, 0) != 0) { hero.jump_blocked_ahead = 1; } } @@ -2676,8 +2676,8 @@ void hero_update_movement(void) { if (hero.state.current == HERO_STATE_PACK_LONG_JUMP && scale_game_frames(8) < hero.state_timer && hero.anim_frame < 28.0f) { s32 n; - transform_hero_local_offset_to_world(&v0, 0.8f, 0.0f, 0.3f); - n = collect_mobies_in_sphere(0.9f, &v0, 0, (struct MobyView *)hero.moby, NULL); + transform_hero_local_offset_to_world(&movement_and_hit_descriptor_scratch, 0.8f, 0.0f, 0.3f); + n = collect_mobies_in_sphere(0.9f, &movement_and_hit_descriptor_scratch, 0, (struct MobyView *)hero.moby, NULL); if (n != 0) { s32 i; fast_vec_scale(&v10, &hero.motion.displacement, 7.0f); @@ -2721,12 +2721,12 @@ void hero_update_movement(void) { case HERO_STATE_APPROACH_TARGET_POSE: { f32 l; f32 k; - fast_vec_sub(&v0, &hero.target_pose, &hero.motion.pos); - hero.motion.move_yaw = fast_arc_tan(v0.f[0], v0.f[1]); - l = vector_length_xy(&v0); + fast_vec_sub(&movement_and_hit_descriptor_scratch, &hero.target_pose, &hero.motion.pos); + hero.motion.move_yaw = fast_arc_tan(movement_and_hit_descriptor_scratch.f[0], movement_and_hit_descriptor_scratch.f[1]); + l = vector_length_xy(&movement_and_hit_descriptor_scratch); if (l > 0.2f) { hero.stick_magnitude = 1.0f; - hero.motion.move_yaw = fast_arc_tan(v0.f[0], v0.f[1]); + hero.motion.move_yaw = fast_arc_tan(movement_and_hit_descriptor_scratch.f[0], movement_and_hit_descriptor_scratch.f[1]); hero.target_speed = l; if (l < D_L00_0017BDB8.x0C) { hero.target_speed = D_L00_0017BDB8.x08 * frame_time; @@ -2773,8 +2773,8 @@ void hero_update_movement(void) { break; } case HERO_STATE_BRAKE_AT_TARGET_POSITION: - fast_vec_sub(&v0, &hero.target_pose, &hero.motion.pos); - if (fast_vec_dot(&v0, &hero.motion.momentum) < 0.0f) { + fast_vec_sub(&movement_and_hit_descriptor_scratch, &hero.target_pose, &hero.motion.pos); + if (fast_vec_dot(&movement_and_hit_descriptor_scratch, &hero.motion.momentum) < 0.0f) { clear_u64_value(&hero.motion.momentum); } clear_u64_value(&hero.motion.velocity); @@ -2843,10 +2843,10 @@ void hero_update_movement(void) { s32 k = tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION ? 0 : 2; moby_point_position((struct MobyView *)hero.moby, k, &v10); moby_point_position((struct MobyView *)hero.moby, k | 1, &v20); - fast_vec_add(&v0, &v10, &v20); - fast_vec_scale(&v0, &v0, 0.5f); + fast_vec_add(&movement_and_hit_descriptor_scratch, &v10, &v20); + fast_vec_scale(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, 0.5f); play_entity_sound( - (struct MobyView *)hero.moby, 0.25f, &v0, 0x10000, 1.0f, 1.0f, 0, 1, 0); + (struct MobyView *)hero.moby, 0.25f, &movement_and_hit_descriptor_scratch, 0x10000, 1.0f, 1.0f, 0, 1, 0); } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || (struct MobyView *)hero.melee_target != NULL) { @@ -2991,7 +2991,7 @@ void hero_update_movement(void) { if (hero.ledge_found == 0) { break; } - qcopy(&v0, &hero.ledge_hang_pos); + qcopy(&movement_and_hit_descriptor_scratch, &hero.ledge_hang_pos); a = fast_add_rotations(hero.ledge_normal_yaw, 3.1415927f); qcopy(&hero.motion.pos, &movement_vector_scratch); check_ledge_grab(); @@ -3005,7 +3005,7 @@ void hero_update_movement(void) { break; } a = fast_add_rotations(fast_subtract_rotations(a, b) * 0.5f, a); - fast_vec_add(&matrix_vector_scratch[1], &v0, &v10); + fast_vec_add(&matrix_vector_scratch[1], &movement_and_hit_descriptor_scratch, &v10); fast_vec_scale(&matrix_vector_scratch[1], &matrix_vector_scratch[1], 0.5f); hero.motion.move_yaw = a; turn_to(0, frame_scale_sq * 0.04f, frame_scale_sq * 0.2f, frame_time * 6.2831855f); @@ -3056,25 +3056,25 @@ void hero_update_movement(void) { switch (hero.attack_record) { case HERO_ATTACK_RECORD_POINT_3_STRIKE: if (hero.anim_frame > 7.0f && hero.anim_frame < 14.0f) { - moby_point_position((struct MobyView *)hero.moby, 3, &v0); - collect_mobies_in_sphere(2.0f, &v0, 0x10, (struct MobyView *)hero.moby, &v10); + moby_point_position((struct MobyView *)hero.moby, 3, &movement_and_hit_descriptor_scratch); + collect_mobies_in_sphere(2.0f, &movement_and_hit_descriptor_scratch, 0x10, (struct MobyView *)hero.moby, &v10); } break; case HERO_ATTACK_RECORD_POINT_4_STRIKE: if (hero.anim_frame > 7.0f && hero.anim_frame < 14.0f) { - moby_point_position((struct MobyView *)hero.moby, 4, &v0); - collect_mobies_in_sphere(2.0f, &v0, 0x10, (struct MobyView *)hero.moby, &v10); + moby_point_position((struct MobyView *)hero.moby, 4, &movement_and_hit_descriptor_scratch); + collect_mobies_in_sphere(2.0f, &movement_and_hit_descriptor_scratch, 0x10, (struct MobyView *)hero.moby, &v10); } break; case HERO_ATTACK_RECORD_PAIRED_POINT_STRIKE: if (hero.anim_frame > 14.0f && hero.anim_frame < 21.0f) { f32 sphere_radius = 2.0f; - moby_point_position((struct MobyView *)hero.moby, 3, &v0); + moby_point_position((struct MobyView *)hero.moby, 3, &movement_and_hit_descriptor_scratch); collect_mobies_in_sphere( - sphere_radius, &v0, 0x10, (struct MobyView *)hero.moby, &v10); + sphere_radius, &movement_and_hit_descriptor_scratch, 0x10, (struct MobyView *)hero.moby, &v10); sphere_radius = 0.0f; - moby_point_position((struct MobyView *)hero.moby, 4, &v0); - collect_mobies_in_sphere(2.0f, &v0, 0x10, (struct MobyView *)hero.moby, &v10); + moby_point_position((struct MobyView *)hero.moby, 4, &movement_and_hit_descriptor_scratch); + collect_mobies_in_sphere(2.0f, &movement_and_hit_descriptor_scratch, 0x10, (struct MobyView *)hero.moby, &v10); } break; } @@ -3130,10 +3130,10 @@ void hero_update_movement(void) { if (hero.anim_frame > 22.0f && hero.anim_frame < 55.0f) { hero.anim_speed = 1.0f; } else if (hero.anim_changing == 0 && hero.anim_frame <= 22.0f) { - fast_vec_normalize(&v0, &hero, 3.0f); - v0.f[2] += 5.0f; - add_vectors(&v10, &v0, &moby->u10.v10); - set_giant_clank_charged_blast_position(moby, &v0); + fast_vec_normalize(&movement_and_hit_descriptor_scratch, &hero, 3.0f); + movement_and_hit_descriptor_scratch.f[2] += 5.0f; + add_vectors(&v10, &movement_and_hit_descriptor_scratch, &moby->u10.v10); + set_giant_clank_charged_blast_position(moby, &movement_and_hit_descriptor_scratch); hero.anim_speed = 0.5f; } } @@ -3159,11 +3159,11 @@ void hero_update_movement(void) { f32 effect_pitch = z; z = 1.0f; for (i = 0; i < 2; i++) { - moby_point_position((struct MobyView *)hero.moby, i + 3, &v0); - v0.f[0] += fast_cos(hero.motion.rot.f[2]) * 1.4f; - v0.f[1] += fast_sin(hero.motion.rot.f[2]) * 1.4f; + moby_point_position((struct MobyView *)hero.moby, i + 3, &movement_and_hit_descriptor_scratch); + movement_and_hit_descriptor_scratch.f[0] += fast_cos(hero.motion.rot.f[2]) * 1.4f; + movement_and_hit_descriptor_scratch.f[1] += fast_sin(hero.motion.rot.f[2]) * 1.4f; spawn_giant_clank_missile((struct MobyView *)hero.moby, - &v0, + &movement_and_hit_descriptor_scratch, hero.motion.rot.f[2], effect_pitch, 0, @@ -3183,9 +3183,9 @@ void hero_update_movement(void) { } case HERO_STATE_VEHICLE_MODE_2_FALL: stick_target(frame_time * 6.0f, 0); - qcopy(&v0, &hero.motion.pos); - v0.f[2] -= 1.0f; - play_entity_sound((struct MobyView *)hero.moby, 3.5f, &v0, 0x30000, 40.0f, 1.0f, 0, 1, 0); + qcopy(&movement_and_hit_descriptor_scratch, &hero.motion.pos); + movement_and_hit_descriptor_scratch.f[2] -= 1.0f; + play_entity_sound((struct MobyView *)hero.moby, 3.5f, &movement_and_hit_descriptor_scratch, 0x30000, 40.0f, 1.0f, 0, 1, 0); if (hero.move_lock_timer == 0) { hero_move_state_velocity(); } @@ -3203,9 +3203,9 @@ void hero_update_movement(void) { d = fast_difference_between_rotations(hero.motion.rot.f[2], hero.motion.move_yaw); for (i = 0; i < 3; i++) { transform_hero_polar_offset_to_world( - &v0, 1.8f, fast_add_rotations(-0.7853982f, (f32)i * 0.7853982f), 1.4f); + &movement_and_hit_descriptor_scratch, 1.8f, fast_add_rotations(-0.7853982f, (f32)i * 0.7853982f), 1.4f); play_entity_sound( - (struct MobyView *)hero.moby, 2.7f, &v0, 0x30000, 40.0f, 1.0f, 0, 1, 0); + (struct MobyView *)hero.moby, 2.7f, &movement_and_hit_descriptor_scratch, 0x30000, 40.0f, 1.0f, 0, 1, 0); } if (test_hero_animation_frame_window(30.0f) != 0 || test_hero_animation_frame_window(0.0f) != 0) { From 985a3423029b875dd9fb25ae6f43f3061a8cd868 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:59:32 +0000 Subject: [PATCH 0316/1502] decomp: clarify names in cancel_suck_cannon_suction_and_set_state_14 domain_0_value_14 -> LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION: Retail 0x002efba8 preserves incoming moby a0 in s0 across cancel_suck_cannon_suction at jal 0x002efba4; li v1,0xe at 0x002efbac and sb v1,0x20(s0) at 0x002efbb4 write Moby.state, as original Ghidra param_1 +0x20 confirms. The authoritative large_amoeboid.c snapshot (SHA-256 623a66637b65cd2794b548138049cc3412aff8c264739353a4859c1565e35126) dispatches large_amoeboid_update on the same Moby byte +0x20 and already names state 14 LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION. That branch calls FUN_L00_002dc9f0(moby, pvars+0x60), resets state to 1 upon completion and clears pvars+0x128. The same source's process_amoeboid_suck_cannon_suction enters Moby.state 14 on accepted suction and leaves it when suction stops. Thus this assignment enters that existing amoeboid state domain, distinct from the helper's suction_record +0x68 substate. --- src/overlays/shared/enemies/large_amoeboid.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/large_amoeboid.c b/src/overlays/shared/enemies/large_amoeboid.c index c8f611de7b..fadbff94b2 100644 --- a/src/overlays/shared/enemies/large_amoeboid.c +++ b/src/overlays/shared/enemies/large_amoeboid.c @@ -1123,8 +1123,11 @@ extern int cancel_suck_cannon_suction(void *) __asm__("FUN_L00_002dbe20"); int cancel_suck_cannon_suction_and_set_state_14(struct Moby *moby) __asm__("FUN_L01_002efb98"); int cancel_suck_cannon_suction_and_set_state_14(struct Moby *moby) { + enum { + LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION = 0xe + }; int helper_result = cancel_suck_cannon_suction(moby); - moby->state = 0xe; + moby->state = LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION; return helper_result; } From b6406be552219600c30ac5cb66d9e342de17f9c3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:59:32 +0000 Subject: [PATCH 0317/1502] decomp: clarify names in activate_grindrail_button domain_0_value_2 -> GRINDRAIL_BUTTON_ACTIVATED: In the SHA-256-bound grindrail_button.c snapshot, activate_grindrail_button assigns moby->state=2. Retail 0x002e56f4 loads 2 and 0x002e56fc stores it at +0x20 of the same moby passed by grindrail_button_update at 0x002e55f8 after alignment checks and 0x002e5628 after find_moby_hit succeeds. Caller retail 0x002e54c0..0x002e54d8 reads this exact +0x20 selector, handles 0 initialization and 1 activation checks, and branches other states directly to glow updates at 0x002e5650. The activation helper also resets the pvars glow phase at 0x002e56f8 and sets command +0xbc at 0x002e5704. Thus 2 denotes the activated grindrail button state, separate from hero state/gravity/vehicle domains. --- src/overlays/l16/mobys/grindrail_button.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/grindrail_button.c b/src/overlays/l16/mobys/grindrail_button.c index 26ec4f3d25..92c332b325 100644 --- a/src/overlays/l16/mobys/grindrail_button.c +++ b/src/overlays/l16/mobys/grindrail_button.c @@ -125,7 +125,10 @@ typedef struct { void activate_grindrail_button(Level16VendorTurnMoby *moby) __asm__("FUN_L16_002e56e0"); void activate_grindrail_button(Level16VendorTurnMoby *moby) { + enum { + GRINDRAIL_BUTTON_ACTIVATED = 2 + }; moby->data->value = -3.1415925f; moby->active = 1; - moby->state = 2; + moby->state = GRINDRAIL_BUTTON_ACTIVATED; } From 86729146ab7177826ec398707d8a302b5eb462c5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:01:15 +0000 Subject: [PATCH 0318/1502] decomp: clarify names in save_card_state_format_pending domain_0_value_3 -> MEMCARD_REQUEST_FORMAT: Retail 0x00208af8/0x00208afc constructs memory_card_state at 0x0013d290; 0x00208b00 loads its +0xdc pending_state and 0x00208b04 tests whether it is negative. On that path, 0x00208b0c loads 3, 0x00208b10 clears +0xe0 pending_card, and 0x00208b14 stores 3 to +0xdc. Original Ghidra likewise assigns g_nPendingMemoryCardOperationState = 3. The authoritative source identifies this exact field as MemoryCardState.pending_state in save_card_state_format_pending. The supplied include/rnc/save/memory_card_state.h domain declaration explicitly places state/pending_state in MemoryCardOperation, whose canonical value 3 is MEMCARD_REQUEST_FORMAT, rather than any per-operation substep enum. --- src/ui/menus/save_data/save_card_state_format_pending.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/menus/save_data/save_card_state_format_pending.c b/src/ui/menus/save_data/save_card_state_format_pending.c index 6723158f76..b5f41b60b6 100644 --- a/src/ui/menus/save_data/save_card_state_format_pending.c +++ b/src/ui/menus/save_data/save_card_state_format_pending.c @@ -10,7 +10,7 @@ void save_card_state_format_pending(void) { card_state->card[0].sync_result = 0; if (pending < 0) { card_state->pending_card = 0; - card_state->pending_state = 3; + card_state->pending_state = MEMCARD_REQUEST_FORMAT; } mode_freeze_state = 8; } From b264139234cd3939337b0c4d0ebfe7a259d05d55 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:03:13 +0000 Subject: [PATCH 0319/1502] decomp: clarify names in enter_main_menu domain_0_value_3 -> GAME_MODE_MAIN_MENU: Retail 0x00218f78 loads a1 with 3 and 0x00218f84 stores it at 0x0015f604, identified by the authoritative source as game_mode. The original Ghidra decompilation agrees (g_nGameStage = 3). In the supplied update_gameplay_frame caller excerpt, CROSS/START in game_mode 0 invokes enter_main_menu, and game_mode == 3 fades the intro overlays and calls update_menu_system plus sound_update. These data flows prove the main-menu game mode independently of menu_system.state 0x2D. --- src/ui/menus/system/enter_main_menu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/menus/system/enter_main_menu.c b/src/ui/menus/system/enter_main_menu.c index 08dd8e7c3c..246b18c8f7 100644 --- a/src/ui/menus/system/enter_main_menu.c +++ b/src/ui/menus/system/enter_main_menu.c @@ -3,9 +3,12 @@ #include "rnc/globals.h" void enter_main_menu(void) { + enum { + GAME_MODE_MAIN_MENU = 3 + }; menu_system.close_request = 0; menu_system.unk10 = 0; - game_mode = 3; + game_mode = GAME_MODE_MAIN_MENU; menu_system.state = 0x2D; menu_system.update_count = 0; } From 3d495db8804b7c30224b7eacd8dccd526f5afd2b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:03:14 +0000 Subject: [PATCH 0320/1502] decomp: clarify names in set_pause_action_list domain_0_value_0 -> PAUSE_ACTION_LIST_MODE_NO_VIDEO: Authoritative source src/ui/menus/pause/set_pause_action_list.c (SHA-256 c4b0ae1a54a1ed02f6fb5df08ff155f8c31371f7a8cb6e095019de13a3ac4405) selects title_options_items_no_video when pause_action_list_mode equals 0. Retail 0x0021a1b4 loads the selector, 0x0021a1b8 branches on zero to 0x0021a1cc, which forms 0x001d4840; 0x0021a1d0 stores that list at destination+0x34. The nonzero branch forms 0x001d4810, corresponding to title_options_items_with_video. Thus zero identifies the no-video action-list mode, independent of unrelated equal-valued constants. --- src/ui/menus/pause/set_pause_action_list.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/menus/pause/set_pause_action_list.c b/src/ui/menus/pause/set_pause_action_list.c index 850efb7722..4289fbd3c9 100644 --- a/src/ui/menus/pause/set_pause_action_list.c +++ b/src/ui/menus/pause/set_pause_action_list.c @@ -7,7 +7,10 @@ int set_pause_action_list(int *p) __asm__("FUN_0021a1b0"); #include "rnc/ui/menus/menu_pages.h" int set_pause_action_list(int *destination) { - if (pause_action_list_mode != 0) { + enum { + PAUSE_ACTION_LIST_MODE_NO_VIDEO = 0 + }; + if (pause_action_list_mode != PAUSE_ACTION_LIST_MODE_NO_VIDEO) { destination[0xD] = (int)title_options_items_with_video; } else { destination[0xD] = (int)title_options_items_no_video; From 6366d5ff8bc2995bd476e44df1c150ac4f82ad42 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:03:14 +0000 Subject: [PATCH 0321/1502] decomp: clarify names in sceMcMkdir domain_0_value_0 -> MC_MKDIR_REQUEST_ACCEPTED: Retail 0x001236e0 calls sceMcOpen with a3=0x40, 0x001236e8 preserves its return in a0, and 0x001236ec skips the MC_FUNC_MKDIR store at 0x001236fc for nonzero status. The supplied sceMcOpen source returns sceSifCallRpc submission status after its precondition checks, setting mc_current_func only on zero. The caller's MEMCARD_CREATE_REQUEST_MKDIR advances on zero, then separately handles MC.result in MEMCARD_CREATE_PROCESS_MKDIR_RESULT. Thus this zero comparison means the mkdir request was accepted, not that directory creation has completed. --- src/sdk/storage/memory_card/sce_mc_mkdir.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/storage/memory_card/sce_mc_mkdir.c b/src/sdk/storage/memory_card/sce_mc_mkdir.c index 064b218d49..11ad1b2d1d 100644 --- a/src/sdk/storage/memory_card/sce_mc_mkdir.c +++ b/src/sdk/storage/memory_card/sce_mc_mkdir.c @@ -3,9 +3,12 @@ #include "rnc/sdk/storage/memory_card.h" s32 sceMcMkdir(s32 port, s32 slot, const char *name) { + enum { + MC_MKDIR_REQUEST_ACCEPTED = 0 + }; s32 mkdir_request_status = sceMcOpen(port, slot, name, 0x40); - if (mkdir_request_status == 0) { + if (mkdir_request_status == MC_MKDIR_REQUEST_ACCEPTED) { mc_current_func = MC_FUNC_MKDIR; } return mkdir_request_status; From bdb83e5eef7a64a3b2939e8dd9702a6d0f13c715 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:05:00 +0000 Subject: [PATCH 0322/1502] decomp: clarify names in __i2b domain_0_value_1 -> BIGINT_SINGLE_WORD_COUNT: Retail __i2b at 0x00115828 stores the saved scalar at allocation +0x14 and 0x00115834 stores 1 at +0x10. Checked _pow5mult caller 0x00115adc initializes the cached bigint with 625, then passes that exact pointer to multiplication at 0x00115b08/0x00115b2c. Multiplication loads +0x10 at 0x00115868/0x0011586c, scales the counts by four at 0x001158c4/0x001158cc to bound word arrays starting +0x14, and trims zero high words at 0x00115a30..0x00115a40 before storing the resulting count to +0x10. Thus this assignment initializes exactly one used 32-bit bigint word. --- src/sdk/libc/mprec/__i2b.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/libc/mprec/__i2b.c b/src/sdk/libc/mprec/__i2b.c index f52b19cc0e..11bb98a69b 100644 --- a/src/sdk/libc/mprec/__i2b.c +++ b/src/sdk/libc/mprec/__i2b.c @@ -11,8 +11,11 @@ Object *_Balloc(Object *object, int index) __asm__("func_001154D0"); Object *__i2b(Object *unused, Object *object) __asm__("func_00115808"); Object *__i2b(Object *unused, Object *initial_bigint_value) { + enum { + BIGINT_SINGLE_WORD_COUNT = 1 + }; Object *allocated_bigint = _Balloc(unused, 1); allocated_bigint->value = (int)initial_bigint_value; - allocated_bigint->state = 1; + allocated_bigint->state = BIGINT_SINGLE_WORD_COUNT; return allocated_bigint; } From d8c8092515a3435bccd7ca9900fb932beee0d557 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:05:00 +0000 Subject: [PATCH 0323/1502] decomp: clarify names in wrench_update domain_0_value_0 -> HERO_WRENCH_STATUS_NONE: Retail 002a84ec sets s1=0013f350, the current source wrench_hero() pointer. The delay-slot sb zero,0x10ac(s1) at 002a8524 clears player->wrench_state unconditionally before state dispatch, including the mode-3 exit. The same exact byte is written through s0=00140b00-17b0=0013f350 at 002a9008/002a901c with 2, already named HERO_WRENCH_STATUS_THROWN, only in the established moby outbound/returning branches. Thus zero is the absence/cleared value of this hero wrench-update status domain; it is not WRENCH_NORMAL or HERO_STATE_IDLE. --- src/overlays/shared/weapons/wrench.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/wrench.c b/src/overlays/shared/weapons/wrench.c index 88acfae661..e45c96c012 100644 --- a/src/overlays/shared/weapons/wrench.c +++ b/src/overlays/shared/weapons/wrench.c @@ -631,10 +631,13 @@ void wrench_update(WrenchMoby *wrench_moby) { enum { HERO_WRENCH_STATUS_THROWN = 2 }; + enum { + HERO_WRENCH_STATUS_NONE = 0 + }; WrenchVars *wrench_vars = wrench_moby->data; WrenchScratch wrench_collision_scratch; WrenchHero *player = wrench_hero(); - player->wrench_state = 0; + player->wrench_state = HERO_WRENCH_STATUS_NONE; if (player->mode == 3) return; switch (wrench_moby->state) { From 9e3ee469a482f695f771722445a88aeeca64d7c7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:05:00 +0000 Subject: [PATCH 0324/1502] decomp: clarify names in break_crate domain_0_value_348 -> CRATE_DEBRIS_MISSION_THRESHOLD_GATED_BASE: Retail selector 002d0c40-002d0c6c reads moby+0xA6 minus 500; established CRATE_VARIANT_MISSION_THRESHOLD_GATED selects 0x15C at 002d0c74-002d0c7c. In original target decompilation and authoritative source, kind is stored at sp+0xD8, loaded into t0 at 002d0e94 and passed to established spawn_crate_debris at 002d0eb0; second loop passes kind+1 at 002d101c-002d1024. Checked helper 002af8b0 moves t0 to allocation argument a0 at 002af8f4-002af8fc and initializes returned moby position/rotation and launch velocity at 002af950-002af970. This names a debris selection base by its source variant, without a material or contents claim. domain_2_value_354 -> CRATE_DEBRIS_DAMAGE_FLAG_GATED_BASE: Retail selector 002d0c40-002d0c6c reads moby+0xA6 minus 500; established CRATE_VARIANT_DAMAGE_FLAG_GATED selects 0x162 at 002d0c8c-002d0c94. In original target decompilation and authoritative source, kind is stored at sp+0xD8, loaded into t0 at 002d0e94 and passed to established spawn_crate_debris at 002d0eb0; second loop passes kind+1 at 002d101c-002d1024. Checked helper 002af8b0 moves t0 to allocation argument a0 at 002af8f4-002af8fc and initializes returned moby position/rotation and launch velocity at 002af950-002af970. This names a debris selection base by its source variant, without a material or contents claim. domain_3_value_357 -> CRATE_DEBRIS_OPTIONAL_TURN_OR_RESPAWN_BASE: Original target switch and authoritative source share the 0x165 assignment between established CRATE_VARIANT_OPTIONAL_QUARTER_TURN and CRATE_VARIANT_CONDITIONAL_RESPAWN_START; retail 002d0c98-002d0c9c branches to store 002d0cd4. This name records that shared source-variant association only. In original target decompilation and authoritative source, kind is stored at sp+0xD8, loaded into t0 at 002d0e94 and passed to established spawn_crate_debris at 002d0eb0; second loop passes kind+1 at 002d101c-002d1024. Checked helper 002af8b0 moves t0 to allocation argument a0 at 002af8f4-002af8fc and initializes returned moby position/rotation and launch velocity at 002af950-002af970. This names a debris selection base by its source variant, without a material or contents claim. domain_5_value_363 -> CRATE_DEBRIS_IMPACT_TRIGGERED_BASE: Retail selector 002d0c40-002d0c6c reads moby+0xA6 minus 500; established CRATE_VARIANT_IMPACT_TRIGGERED selects 0x16B at 002d0cac-002d0cb4. In original target decompilation and authoritative source, kind is stored at sp+0xD8, loaded into t0 at 002d0e94 and passed to established spawn_crate_debris at 002d0eb0; second loop passes kind+1 at 002d101c-002d1024. Checked helper 002af8b0 moves t0 to allocation argument a0 at 002af8f4-002af8fc and initializes returned moby position/rotation and launch velocity at 002af950-002af970. This names a debris selection base by its source variant, without a material or contents claim. domain_6_value_366 -> CRATE_DEBRIS_CLASS_OVERRIDE_BREAK_SOUND_BASE: Retail selector 002d0c40-002d0c6c reads moby+0xA6 minus 500; established CRATE_VARIANT_CLASS_OVERRIDE_BREAK_SOUND selects 0x16E at 002d0cb8-002d0cc0. The name associates debris with that variant and does not imply debris produces the sound. In original target decompilation and authoritative source, kind is stored at sp+0xD8, loaded into t0 at 002d0e94 and passed to established spawn_crate_debris at 002d0eb0; second loop passes kind+1 at 002d101c-002d1024. Checked helper 002af8b0 moves t0 to allocation argument a0 at 002af8f4-002af8fc and initializes returned moby position/rotation and launch velocity at 002af950-002af970. This names a debris selection base by its source variant, without a material or contents claim. domain_7_value_369 -> CRATE_DEBRIS_DAMAGE_STAGE_BASE: Original target decompilation and source group established INITIAL, SECOND, PENULTIMATE and FINAL_DAMAGE_STAGE variants into the 0x171 assignment; retail 002d0cc4-002d0ccc stores that shared selection. This names the debris shared by the damage-stage variants. In original target decompilation and authoritative source, kind is stored at sp+0xD8, loaded into t0 at 002d0e94 and passed to established spawn_crate_debris at 002d0eb0; second loop passes kind+1 at 002d101c-002d1024. Checked helper 002af8b0 moves t0 to allocation argument a0 at 002af8f4-002af8fc and initializes returned moby position/rotation and launch velocity at 002af950-002af970. This names a debris selection base by its source variant, without a material or contents claim. domain_8_value_149 -> CRATE_DEBRIS_FALLBACK_BASE: Original target decompilation and authoritative source assign 0x95 in the switch default. Retail 002d0c50-002d0c54 sends selectors outside 0..11 to 002d0cd0-002d0cd4, loading and storing 0x95. This proves the fallback debris selection. In original target decompilation and authoritative source, kind is stored at sp+0xD8, loaded into t0 at 002d0e94 and passed to established spawn_crate_debris at 002d0eb0; second loop passes kind+1 at 002d101c-002d1024. Checked helper 002af8b0 moves t0 to allocation argument a0 at 002af8f4-002af8fc and initializes returned moby position/rotation and launch velocity at 002af950-002af970. This names a debris selection base by its source variant, without a material or contents claim. --- src/overlays/shared/pickups/crate.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/pickups/crate.c b/src/overlays/shared/pickups/crate.c index 4ee983a16d..86b5dc03d6 100644 --- a/src/overlays/shared/pickups/crate.c +++ b/src/overlays/shared/pickups/crate.c @@ -1020,6 +1020,15 @@ void break_crate(M2d1428 *moby, s32 hit, s32 source) { enum { CRATE_STATE_BROKEN = 3 }; + enum { + CRATE_DEBRIS_FALLBACK_BASE = 0x95, + CRATE_DEBRIS_MISSION_THRESHOLD_GATED_BASE = 0x15C, + CRATE_DEBRIS_DAMAGE_FLAG_GATED_BASE = 0x162, + CRATE_DEBRIS_OPTIONAL_TURN_OR_RESPAWN_BASE = 0x165, + CRATE_DEBRIS_IMPACT_TRIGGERED_BASE = 0x16B, + CRATE_DEBRIS_CLASS_OVERRIDE_BREAK_SOUND_BASE = 0x16E, + CRATE_DEBRIS_DAMAGE_STAGE_BASE = 0x171 + }; u8 *vars = (u8 *)moby->vars; V2d09b8 position, away, rotation, basis[3], launch, spawn_pos, spin; s32 kind; @@ -1071,7 +1080,7 @@ void break_crate(M2d1428 *moby, s32 hit, s32 source) { fast_vec_sub(&away, &moby->pos, (*(u8 **)D_001413D0) + 0x10); switch ((s16)((u16)moby->oclass - 500)) { case CRATE_VARIANT_MISSION_THRESHOLD_GATED: - kind = 0x15C; + kind = CRATE_DEBRIS_MISSION_THRESHOLD_GATED_BASE; break; case 3: kind = 0x15F; @@ -1079,29 +1088,29 @@ void break_crate(M2d1428 *moby, s32 hit, s32 source) { case CRATE_VARIANT_DAMAGE_FLAG_GATED: if (!angle) { } - kind = 0x162; + kind = CRATE_DEBRIS_DAMAGE_FLAG_GATED_BASE; break; case CRATE_VARIANT_OPTIONAL_QUARTER_TURN: case CRATE_VARIANT_CONDITIONAL_RESPAWN_START: - kind = 0x165; + kind = CRATE_DEBRIS_OPTIONAL_TURN_OR_RESPAWN_BASE; break; case 4: kind = 0x168; break; case CRATE_VARIANT_IMPACT_TRIGGERED: - kind = 0x16B; + kind = CRATE_DEBRIS_IMPACT_TRIGGERED_BASE; break; case CRATE_VARIANT_CLASS_OVERRIDE_BREAK_SOUND: - kind = 0x16E; + kind = CRATE_DEBRIS_CLASS_OVERRIDE_BREAK_SOUND_BASE; break; case CRATE_VARIANT_INITIAL_DAMAGE_STAGE: case CRATE_VARIANT_SECOND_DAMAGE_STAGE: case CRATE_VARIANT_PENULTIMATE_DAMAGE_STAGE: case CRATE_VARIANT_FINAL_DAMAGE_STAGE: - kind = 0x171; + kind = CRATE_DEBRIS_DAMAGE_STAGE_BASE; break; default: - kind = 0x95; + kind = CRATE_DEBRIS_FALLBACK_BASE; break; } if (D_L00_0015FFBC >= 201) { From c692e1dd01ef4f2f48f5f50bd4e0ff98f40b0a0c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:05:00 +0000 Subject: [PATCH 0325/1502] decomp: clarify names in cancel_moby_suction_and_save_state domain_0_value_16 -> FROG_STATE_SUCK_CANNON_HELD: Retail 0x002ea7dc loads previous_state from moby+0x20, 0x002ea7e0 loads 16, and 0x002ea7e4 skips saving when already equal; 0x002ea7ec writes that state and 0x002ea7f0 saves the previous state at +0xBC. The authoritative frog.c frog_update switches on the same moby[0x20] and explicitly declares FROG_STATE_SUCK_CANNON_HELD=16, whose branch invokes FUN_L00_002dc9f0 before releasing to state 8. Adjacent update_moby_grab_state and update_moby_suck_cannon_storage_state both place the same moby state byte in 16 during suction/storage and restore 8 on release. This proves the frog state domain and existing semantic member; equal-valued HERO_STATE_PACK_LONG_JUMP belongs to a different domain. --- src/overlays/shared/enemies/frog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/frog.c b/src/overlays/shared/enemies/frog.c index 9a7f2f77c0..3f5860276b 100644 --- a/src/overlays/shared/enemies/frog.c +++ b/src/overlays/shared/enemies/frog.c @@ -978,11 +978,11 @@ int update_moby_suck_cannon_storage_state(unsigned char *moby) { s32 cancel_moby_suction_and_save_state(unsigned char *moby) __asm__("FUN_L06_002ea7c8"); s32 cancel_moby_suction_and_save_state(unsigned char *moby) { - u8 previous_state; + enum { FROG_STATE_SUCK_CANNON_HELD = 0x10 } ;u8 previous_state; s32 helper_result; helper_result = cancel_suck_cannon_suction(moby); previous_state = MOBY(moby)->state; - if (previous_state != 0x10) { + if (previous_state != FROG_STATE_SUCK_CANNON_HELD) { MOBY(moby)->command = previous_state; MOBY(moby)->state = 0x10; } From 01139c5fab20030a9400a5aadb386e806843dc84 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:05:00 +0000 Subject: [PATCH 0326/1502] decomp: clarify names in request_floating_platform_sink domain_0_value_1 -> STATE_WAIT_FOR_TILT_REQUEST: Retail 0x002d8858 loads the Moby state byte at a0+0x20; 0x002d885c-0x002d8860 compares it with 1 and returns unchanged. The supplied class-0x24B Moby caller subsequently requests tilt. In the authoritative source floating_platform_update switches on the same moby->state domain and names 1 STATE_WAIT_FOR_TILT_REQUEST; request_floating_platform_tilt accepts state 1 and changes it to tilt-delay state 3. domain_1_value_2 -> STATE_WAIT_FOR_SINK_REQUEST: Retail 0x002d8868-0x002d886c compares the same state byte loaded from a0+0x20 with 2 before the sink transition. The supplied caller passes a class-0x24B platform Moby. The authoritative floating_platform_update uses this same Moby state domain and names 2 STATE_WAIT_FOR_SINK_REQUEST; that waiting branch performs no transition until this request helper stores 5. domain_2_value_5 -> STATE_SINKING: Retail 0x002d8874 loads 5 and 0x002d8878 stores it to the same Moby state byte at a0+0x20 only when its previous state is 2. The authoritative floating_platform_update names this current-state domain member STATE_SINKING=5 and its branch accelerates the vertical sink velocity, lowers the platform height and eventually removes the Moby. This proves the store requests the sinking state. --- src/overlays/l18/mobys/floating_platform.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/overlays/l18/mobys/floating_platform.c b/src/overlays/l18/mobys/floating_platform.c index 54199233a4..d8458c279c 100644 --- a/src/overlays/l18/mobys/floating_platform.c +++ b/src/overlays/l18/mobys/floating_platform.c @@ -229,11 +229,16 @@ typedef struct { int request_floating_platform_sink(Level18State *platform_moby) __asm__("FUN_L18_002d8858"); int request_floating_platform_sink(Level18State *platform_moby) { - if (platform_moby->state == 1) { + enum { + STATE_WAIT_FOR_TILT_REQUEST = 1, + STATE_WAIT_FOR_SINK_REQUEST = 2, + STATE_SINKING = 5 + }; + if (platform_moby->state == STATE_WAIT_FOR_TILT_REQUEST) { return 1; } - if (platform_moby->state == 2) { - platform_moby->state = 5; + if (platform_moby->state == STATE_WAIT_FOR_SINK_REQUEST) { + platform_moby->state = STATE_SINKING; } return 0; } From b2debb38fcaf93570c44f481cf48f6462e340f72 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:05:01 +0000 Subject: [PATCH 0327/1502] decomp: clarify names in is_moby_in_bob_target_exclusion_state domain_0_value_20 -> PUFFOID_STATE_WAIT_TO_RESUME_COMMAND: Retail 0x00316128 loads Moby+0x20 and 0x0031612c compares 20. Caller 0x002d2524..0x002d2530 passes this Moby only for class 0x4DE. In the bound puffoid.c snapshot, puffoid_update names state 20 PUFFOID_STATE_WAIT_TO_RESUME_COMMAND and its branch restores moby->command when unkC8 and the motion helper permit; suction callbacks park the same state field at 20 while saving its prior state. domain_1_value_11 -> PUFFOID_STATE_DEATH_KNOCKBACK: Retail 0x00316134..0x00316138 compares the loaded Moby state byte with 11; caller 0x002d2524..0x002d2530 restricts the predicate to class 0x4DE. The authoritative puffoid_update enum names 11 PUFFOID_STATE_DEATH_KNOCKBACK. Its branch waits for knockback hit flags then explodes/removes the Moby; update_puffoid_damage_and_path_goal assigns 11 on death after starting knockback when state <12. domain_2_value_18 -> PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK: Retail 0x0031613c..0x00316140 compares the same Moby+0x20 byte with 18. Caller 0x002d2524..0x002d2530 proves class 0x4DE. In the supplied source puffoid_update names 18 PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK and follows the carrier before testing knockback flags and exploding/removing the Moby; the death reaction assigns 18 after starting knockback for states >=12. domain_3_value_12 -> PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP: Retail 0x00316144..0x00316148 compares the Moby+0x20 state byte with 12. Caller 0x002d2524..0x002d2530 restricts the argument to class 0x4DE. The source enum names 12 PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP; initialization selects it for a carrier index >=0, and that branch waits for target/group/carrier-relative conditions before computing a carrier-relative jump destination and assigning state 13. --- src/overlays/l11/mobys/puffoid.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/puffoid.c b/src/overlays/l11/mobys/puffoid.c index d58087a9f4..574fe6f5be 100644 --- a/src/overlays/l11/mobys/puffoid.c +++ b/src/overlays/l11/mobys/puffoid.c @@ -971,8 +971,14 @@ short count_group_puffoids_in_states_13_to_17(struct Moby *group_source_moby) { s32 is_moby_in_bob_target_exclusion_state(const u8 *moby) __asm__("FUN_L11_00316128"); s32 is_moby_in_bob_target_exclusion_state(const u8 *moby) { + enum { + PUFFOID_STATE_DEATH_KNOCKBACK = 0xB, + PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP = 0xC, + PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK = 0x12, + PUFFOID_STATE_WAIT_TO_RESUME_COMMAND = 0x14 + }; u32 moby_state = moby[0x20]; - if (moby_state == 0x14 || moby_state == 0xB || moby_state == 0x12 || moby_state == 0xC) { + if (moby_state == PUFFOID_STATE_WAIT_TO_RESUME_COMMAND || moby_state == PUFFOID_STATE_DEATH_KNOCKBACK || moby_state == PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK || moby_state == PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP) { return 1; } return 0; From 5e2e016a737635fa9e3f6c2054eb597c9f28ebec Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:07:18 +0000 Subject: [PATCH 0328/1502] decomp: clarify names in scePad2Init domain_0_value_0 -> PAD2_SOCKET_INACTIVE: Authoritative scePad2Init assigns zero to pad2_socket_record->state. Original retail Ghidra maps that offset-zero field to Pad2SocketRecord.nActive. Retail 0x00124a50/0x00124a58 loads socket base 0x0015b540, 0x00124a60 clears nActive, and 0x00124a6c-0x00124a74 advances 0x330 through base+0x3300. Thus initialization marks all sixteen socket records inactive; the name is grounded in the field meaning and initialization data flow, not numeric equality. --- src/sdk/input/sce_pad2_init.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/input/sce_pad2_init.c b/src/sdk/input/sce_pad2_init.c index a7a54cdac6..cb114d3029 100644 --- a/src/sdk/input/sce_pad2_init.c +++ b/src/sdk/input/sce_pad2_init.c @@ -10,12 +10,15 @@ extern u32 pad2_initialized[] __asm__("D_00132DD0"); extern u8 D_0015B540[]; s32 scePad2Init(void) { + enum { + PAD2_SOCKET_INACTIVE = 0 + }; struct Pad2StateEntry *pad2_socket_record; pad2_initialized[0] = 1; pad2_socket_record = (struct Pad2StateEntry *)D_0015B540; do { - pad2_socket_record->state = 0; + pad2_socket_record->state = PAD2_SOCKET_INACTIVE; pad2_socket_record->request = 0; pad2_socket_record->result = 0; pad2_socket_record = (struct Pad2StateEntry *)((u8 *)pad2_socket_record + 0x330); From 1da4421a79fbe93c0a6281d7443627af40ecb503 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:07:18 +0000 Subject: [PATCH 0329/1502] decomp: clarify names in request_audio_stream_break domain_0_value_0 -> MUSIC_STREAM_READ_INACTIVE: The authoritative source reads music_stream_state.read_state. Retail 0x002166fc loads the signed halfword at shared state +8; 0x00216700 branches directly to the epilogue when zero, skipping the cancellation call at 0x00216708 and break_requested store at 0x00216714. Original Ghidra identifies this field as g_cdReadState.nActive and describes the zero path as an inactive request. Supplied leave_map_screen likewise separates read_state == 0 cleanup from read_state != 0 cancellation. Thus zero denotes an inactive stream read, without assigning meanings to nonzero states. --- src/audio/streaming/request_audio_stream_break.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/streaming/request_audio_stream_break.c b/src/audio/streaming/request_audio_stream_break.c index 34f885f6cb..28a609c6f5 100644 --- a/src/audio/streaming/request_audio_stream_break.c +++ b/src/audio/streaming/request_audio_stream_break.c @@ -7,7 +7,10 @@ extern s32 snd_stream_safe_cd_break() __asm__("func_0012EEA8"); void request_audio_stream_break(s32 unused_parameter) __asm__("FUN_002166e8"); void request_audio_stream_break(s32 unused_parameter) { - if (music_stream_state.read_state != 0) { + enum { + MUSIC_STREAM_READ_INACTIVE = 0 + }; + if (music_stream_state.read_state != MUSIC_STREAM_READ_INACTIVE) { snd_stream_safe_cd_break(); music_stream_state.break_requested = 1; } From 5b76310792a603f112a89a3f6fc316255784933f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:07:18 +0000 Subject: [PATCH 0330/1502] decomp: clarify names in finish_audio_stream_read domain_0_value_0 -> MUSIC_STREAM_READ_IDLE: Retail 0x0021695c accepts callback_value 1; 0x00216968 points s0 at shared music stream state 0x001516d0 and 0x00216970 clears its halfword read_state at +8 before querying CD error. If the query returns zero, 0x00216974 exits with read_state 0. The prepared original decompilation identifies this as clearing the shared active read state on completion, proving the idle read-state role. domain_1_value_2 -> MUSIC_STREAM_READ_RETRY_PENDING: After completion clears the same read_state halfword at 0x001516d8, retail 0x0021696c calls snd_stream_safe_cd_get_error (0x0012eef0). A nonzero return falls through 0x00216978 and 0x0021697c to store 2. The prepared original retail decompilation explicitly records that the parent scheduler observes state 2 and retries the retained sector, count and destination, proving a pending read retry rather than a callback-event value. --- src/audio/streaming/finish_audio_stream_read.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/audio/streaming/finish_audio_stream_read.c b/src/audio/streaming/finish_audio_stream_read.c index 46b204b961..eb2f00cf6e 100644 --- a/src/audio/streaming/finish_audio_stream_read.c +++ b/src/audio/streaming/finish_audio_stream_read.c @@ -7,10 +7,14 @@ extern s32 snd_stream_safe_cd_get_error() __asm__("func_0012EEF0"); void finish_audio_stream_read(s32 callback_value) __asm__("FUN_00216950"); void finish_audio_stream_read(s32 callback_value) { + enum { + MUSIC_STREAM_READ_IDLE = 0, + MUSIC_STREAM_READ_RETRY_PENDING = 2 + }; if (callback_value == 1) { - music_stream_state.read_state = 0; + music_stream_state.read_state = MUSIC_STREAM_READ_IDLE; if (snd_stream_safe_cd_get_error() != 0) { - music_stream_state.read_state = 2; + music_stream_state.read_state = MUSIC_STREAM_READ_RETRY_PENDING; } } } From 9467372ca8740e342794965ddee28fd66e3c4d9a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:07:18 +0000 Subject: [PATCH 0331/1502] decomp: clarify names in set_moby_state_two_data_and_timer domain_0_value_2 -> ENERGY_SPHERE_MOVE_AND_DETONATE: Retail 0x00318e9c loads 2 and 0x00318ea8 stores it to the input moby's state byte +0x20; original Ghidra agrees. At 0x00318eac the private storage pointer is loaded from +0x78, 0x00318eb0-0x00318eb4 copy movement_step into its base, and 0x00318ec0 writes the scaled 60-frame timer at private +0x20. The authoritative energy_sphere.c source (SHA-256 74aa23bf0ca842610fe0c2af0a7c07370437917776f0130eceeb2211cf644697) names this same moby state ENERGY_SPHERE_MOVE_AND_DETONATE in energy_sphere_update: its state selector reads moby[0x20], its state-2 branch adds that private vector to sphere position, tests the private +0x20 timer and collisions, then spawns an explosion and removes the sphere. The supplied psytcopus_update firing caller passes its held projectile and a frame_time * 30.0f forward vector here, confirming entry into that sphere movement state, rather than a Hero state or control selector. --- src/overlays/l11/mobys/energy_sphere.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/energy_sphere.c b/src/overlays/l11/mobys/energy_sphere.c index e6b5c8927c..b72d92fc57 100644 --- a/src/overlays/l11/mobys/energy_sphere.c +++ b/src/overlays/l11/mobys/energy_sphere.c @@ -169,8 +169,11 @@ void set_moby_position_and_refresh_removal_timer(struct Moby *moby, void *new_po void set_moby_state_two_data_and_timer(struct Moby *moby, void *src) __asm__("FUN_L11_00318e98"); void set_moby_state_two_data_and_timer(struct Moby *moby, void *movement_step) { + enum { + ENERGY_SPHERE_MOVE_AND_DETONATE = 2 + }; char *moby_vars; - moby->state = 2; + moby->state = ENERGY_SPHERE_MOVE_AND_DETONATE; moby_vars = (char *)moby->pvars; qcopy(moby_vars, movement_step); *(int *)(moby_vars + 0x20) = scale_game_frames(0x3C); From b36926a30d9a30f92a76e029b59b8e17b53b9245 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:09:34 +0000 Subject: [PATCH 0332/1502] decomp: clarify names in is_robot_dog_in_state_5 domain_2_value_5 -> ROBOT_DOG_FOLLOW_PATH: Retail 0x002c5b80 loads moby state at +0x20, 0x002c5b94 checks class +0xA6 against 0x23D, and 0x002c5ba0-0x002c5ba8 returns true for state 5. The SHA-bound source robot_dog_update switches on the same moby byte +0x20 and already defines ROBOT_DOG_FOLLOW_PATH = 5. That branch selects l03_paths[i270], finds a segment, advances i278 and calls step_mover_2e3f20 toward successive path points, exiting when the path finishes. Thus this predicate tests the same robot-dog path-following state, not a request or control domain. --- src/overlays/l03/mobys/robot_dog.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l03/mobys/robot_dog.c b/src/overlays/l03/mobys/robot_dog.c index 3b467e94e6..447930a36d 100644 --- a/src/overlays/l03/mobys/robot_dog.c +++ b/src/overlays/l03/mobys/robot_dog.c @@ -22,8 +22,11 @@ int is_robot_dog_in_state_5(struct Moby *moby) __asm__("FUN_L03_002c5b78"); int is_robot_dog_in_state_5(struct Moby *moby) { + enum { + ROBOT_DOG_FOLLOW_PATH = 5 + }; if (moby && moby->state != 0xFE && moby->state != 0xFD && moby->oclass == 0x23D && - moby->state == 5) { + moby->state == ROBOT_DOG_FOLLOW_PATH) { return 1; } return 0; From edea67eaead4a2b66fa7b07d2a2879abad736d4b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:09:35 +0000 Subject: [PATCH 0333/1502] decomp: clarify names in reset_drek_boss_falling_moby_group domain_0_value_1 -> FALLING_MOBY_GROUP_AWAIT_ACTIVATION: Retail 0x002f1cd4 checks moby class +0xA6 against 0x565; 0x002f1ce0..0x002f1ce4 writes 1 to that moby's state byte +0x20, then clears transform progress +0x330 and debris accumulator +0x344. In the authoritative source, activate_drek_boss_class_0565_moby at 0x002f1c38 accepts exactly class 0x565 with state 1 and changes it to state 2, the updater's MOBY_APPROACH_TARGET_TRANSFORM state. Initialization also enters state 1 after capturing linked transforms. Thus this assignment resets the falling linked group to the state awaiting activation, within the moby state domain rather than any hero enum. --- src/overlays/l18/mobys/falling_moby_group.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l18/mobys/falling_moby_group.c b/src/overlays/l18/mobys/falling_moby_group.c index 3ccabf9cfb..10afb715b1 100644 --- a/src/overlays/l18/mobys/falling_moby_group.c +++ b/src/overlays/l18/mobys/falling_moby_group.c @@ -287,9 +287,12 @@ typedef struct L18VD_1cc8 { void reset_drek_boss_falling_moby_group(L18VM_1cc8 *moby) __asm__("FUN_L18_002f1cc8"); void reset_drek_boss_falling_moby_group(L18VM_1cc8 *moby) { + enum { + FALLING_MOBY_GROUP_AWAIT_ACTIVATION = 1 + }; L18VD_1cc8 *data = moby->data; if (moby->class_id == 0x565) { - moby->state = 1; + moby->state = FALLING_MOBY_GROUP_AWAIT_ACTIVATION; data->field330 = 0; data->field344 = 0; } From f74aca8be48a47da0c6f6b41f8203244627a4e5a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:09:35 +0000 Subject: [PATCH 0334/1502] decomp: clarify names in hero_update_movement v20 -> spatial_and_hit_descriptor_scratch: Rename the unique function-local Vec4 v20 to spatial_and_hit_descriptor_scratch. The authoritative source and original retail Ghidra identify its storage as sp+0x20 (Ghidra fStack_1e0 and following words). Retail 0x00218aa0-0x00218ac8 constructs/transforms a local-X effect offset there and adds it to an emission position; 0x00219c78-0x00219cf4 constructs an offset world position used to derive grapple velocity. At 0x0021a030-0x0021a058 it is cleared, receives hero yaw in its Z component and supplies Euler-matrix input. At 0x0021ce3c-0x0021ce74 it receives hero position and a sampled rail position; 0x0021e160-0x0021e23c saves/restores hero position around ledge probes. The same storage holds hit-descriptor fields at 0x0021ad2c-0x0021ad3c and 0x0022038c-0x0022039c, and receives make_hit_descriptor output consumed by collect_mobies_in_sphere at 0x0021db98-0x0021dbec. The combined name records these proven spatial and descriptor lifetimes without claiming a single persistent gameplay vector. --- .../shared/hero/hero_update_movement.c | 182 +++++++++--------- 1 file changed, 91 insertions(+), 91 deletions(-) diff --git a/src/overlays/shared/hero/hero_update_movement.c b/src/overlays/shared/hero/hero_update_movement.c index 2a86cdc75f..b12f117122 100644 --- a/src/overlays/shared/hero/hero_update_movement.c +++ b/src/overlays/shared/hero/hero_update_movement.c @@ -237,7 +237,7 @@ void hero_update_movement(void) { f32 speed; Vec4 movement_and_hit_descriptor_scratch; Vec4 v10; - Vec4 v20; + Vec4 spatial_and_hit_descriptor_scratch; Vec4 movement_vector_scratch; Vec4 matrix_vector_scratch[4]; Vec4 transposed_yaw_matrix[4]; @@ -628,13 +628,13 @@ void hero_update_movement(void) { s32 hi2; pl = &hero_b; moby_point_position((struct MobyView *)pl->moby, 4, &movement_and_hit_descriptor_scratch); - v20.q = 0; - v20.f[0] = 0.4f; - transform_vector_by_basis(&v20, &v20, &((struct MobyView *)pl->moby)->vC0); - fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &v20); + spatial_and_hit_descriptor_scratch.q = 0; + spatial_and_hit_descriptor_scratch.f[0] = 0.4f; + transform_vector_by_basis(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, &((struct MobyView *)pl->moby)->vC0); + fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch); qcopy(&v10, &hero_b.motion.displacement); - fast_vec_normalize(&v20, &v20, frame_time * 1.5f); - fast_vec_add(&v10, &v10, &v20); + fast_vec_normalize(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, frame_time * 1.5f); + fast_vec_add(&v10, &v10, &spatial_and_hit_descriptor_scratch); v10.f[2] += frame_time * 2.0f; FUN_L00_0026f080(&movement_and_hit_descriptor_scratch, &v10, 25200.0f, -1.0f); if (random_integer_below(100) < 40.0f) { @@ -652,10 +652,10 @@ void hero_update_movement(void) { s32 i; for (i = 0; i < 4; i++) { moby_point_position(gm, i % 2, &movement_and_hit_descriptor_scratch); - v20.q = 0; - v20.f[0] = -0.15f; - transform_vector_by_basis(&v20, &v20, &((struct MobyView *)hero.moby)->vC0); - fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &v20); + spatial_and_hit_descriptor_scratch.q = 0; + spatial_and_hit_descriptor_scratch.f[0] = -0.15f; + transform_vector_by_basis(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, &((struct MobyView *)hero.moby)->vC0); + fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch); movement_and_hit_descriptor_scratch.f[0] += random_float_between(0.0f, 0.03f); movement_and_hit_descriptor_scratch.f[1] += random_float_between(0.0f, 0.03f); movement_and_hit_descriptor_scratch.f[2] += random_float_between(0.0f, 0.03f); @@ -751,13 +751,13 @@ void hero_update_movement(void) { qcopy(&hero.motion.velocity, &hero.motion.momentum); if (fast_dec_timer(&hero.puff_timer) == 2) { moby_point_position((struct MobyView *)hero.moby, 4, &movement_and_hit_descriptor_scratch); - v20.q = 0; - v20.f[0] = 0.4f; - transform_vector_by_basis(&v20, &v20, &((struct MobyView *)hero.moby)->vC0); - fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &v20); + spatial_and_hit_descriptor_scratch.q = 0; + spatial_and_hit_descriptor_scratch.f[0] = 0.4f; + transform_vector_by_basis(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, &((struct MobyView *)hero.moby)->vC0); + fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch); qcopy(&v10, &hero.motion.displacement); - fast_vec_normalize(&v20, &v20, frame_time * 1.5f); - fast_vec_add(&v10, &v10, &v20); + fast_vec_normalize(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, frame_time * 1.5f); + fast_vec_add(&v10, &v10, &spatial_and_hit_descriptor_scratch); v10.f[2] += frame_time * 2.0f; FUN_L00_0026f080(&movement_and_hit_descriptor_scratch, &v10, 25200.0f, -1.0f); if (scale_game_frames(40) > hero.state_timer) { @@ -936,11 +936,11 @@ void hero_update_movement(void) { 1.5707964f); step_angle_toward_target(&hero.motion.rot.f[1], 0, an, frame_time * 6.4577184f); } - v20.f[0] = fast_cos(fast_add_rotations(hero.motion.rot.f[2], -1.5707964f)) * -0.57f; - v20.f[1] = fast_sin(fast_add_rotations(hero.motion.rot.f[2], -1.5707964f)) * -0.57f; - v20.f[2] = 0.0f; - fast_vec_add(&v20, &v20, &hero.motion.pos); - fast_vec_sub(&v10, &((struct MobyView *)hero.grapple_target)->u10.v10, &v20); + spatial_and_hit_descriptor_scratch.f[0] = fast_cos(fast_add_rotations(hero.motion.rot.f[2], -1.5707964f)) * -0.57f; + spatial_and_hit_descriptor_scratch.f[1] = fast_sin(fast_add_rotations(hero.motion.rot.f[2], -1.5707964f)) * -0.57f; + spatial_and_hit_descriptor_scratch.f[2] = 0.0f; + fast_vec_add(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, &hero.motion.pos); + fast_vec_sub(&v10, &((struct MobyView *)hero.grapple_target)->u10.v10, &spatial_and_hit_descriptor_scratch); fast_vec_normalize(&hero.motion.velocity, &v10, hero.grapple_pull_speed); if (scale_game_frames(30) > hero.target_arrival_frames) { f32 t = scale_game_frames(30) - hero.target_arrival_frames; @@ -958,8 +958,8 @@ void hero_update_movement(void) { fast_vec_add(&v10, &hero.motion.pos, &hero.motion.velocity); fast_vec_sub(&movement_vector_scratch, &v10, &movement_and_hit_descriptor_scratch); fast_vec_normalize(&movement_vector_scratch, &movement_vector_scratch, hero.tether_radius); - fast_vec_add(&v20, &movement_and_hit_descriptor_scratch, &movement_vector_scratch); - fast_vec_sub(&hero.motion.velocity, &v20, &hero.motion.pos); + fast_vec_add(&spatial_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &movement_vector_scratch); + fast_vec_sub(&hero.motion.velocity, &spatial_and_hit_descriptor_scratch, &hero.motion.pos); break; } case HERO_STATE_GRAPPLE_SWING_ENTRY: { @@ -992,9 +992,9 @@ void hero_update_movement(void) { if (movement_and_hit_descriptor_scratch.f[2] < 0.23f) { movement_and_hit_descriptor_scratch.f[2] = 0.23f; } - clear_u64_value(&v20); - v20.f[2] = hero.motion.rot.f[2]; - euler_rotation_matrix(matrix_vector_scratch, &v20); + clear_u64_value(&spatial_and_hit_descriptor_scratch); + spatial_and_hit_descriptor_scratch.f[2] = hero.motion.rot.f[2]; + euler_rotation_matrix(matrix_vector_scratch, &spatial_and_hit_descriptor_scratch); transpose_rotation_matrix(transposed_yaw_matrix, matrix_vector_scratch); transform_vector(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, transposed_yaw_matrix); v10.f[0] = -fast_arc_tan(square_root(movement_and_hit_descriptor_scratch.f[0] * movement_and_hit_descriptor_scratch.f[0] + movement_and_hit_descriptor_scratch.f[2] * movement_and_hit_descriptor_scratch.f[2]), movement_and_hit_descriptor_scratch.f[1]); @@ -1255,9 +1255,9 @@ void hero_update_movement(void) { make_hit_descriptor( &v10, (struct MobyView *)hero.moby, 0x10000, 2.0f, &matrix_vector_scratch[0]); v10.f[3] = 5627.925f; - ((u8 *)&v20)[9] = 1; - ((s16 *)&v20)[5] = 0x47; - ((u8 *)&v20)[8] = 0; + ((u8 *)&spatial_and_hit_descriptor_scratch)[9] = 1; + ((s16 *)&spatial_and_hit_descriptor_scratch)[5] = 0x47; + ((u8 *)&spatial_and_hit_descriptor_scratch)[8] = 0; collect_mobies_in_sphere(0.4f, &movement_and_hit_descriptor_scratch, 0x10, (struct MobyView *)hero.moby, &v10); } test_hero_animation_frame_window(27.0f); @@ -1942,10 +1942,10 @@ void hero_update_movement(void) { s32 si; f32 sf; f32 q = scale_time(30.0f) * hero.motion.speed_xy; - qcopy(&v20, &hero.motion.pos); + qcopy(&spatial_and_hit_descriptor_scratch, &hero.motion.pos); si = hero.rail_segment; sf = hero.rail_seg_frac; - h = sample_path((void *)hero.rail_spline, &v20, &si, &sf, q, hero.rail_spline_loops); + h = sample_path((void *)hero.rail_spline, &spatial_and_hit_descriptor_scratch, &si, &sf, q, hero.rail_spline_loops); qcopy(&movement_vector_scratch, &hero.motion.pos); si = hero.rail_segment; sf = hero.rail_seg_frac; @@ -1958,8 +1958,8 @@ void hero_update_movement(void) { hero.rail_spline_loops != 0) { f32 a = fast_subtract_rotations(hero.rail_dir_yaw, - fast_arc_tan(movement_vector_scratch.f[0] - v20.f[0], - movement_vector_scratch.f[1] - v20.f[1])) * + fast_arc_tan(movement_vector_scratch.f[0] - spatial_and_hit_descriptor_scratch.f[0], + movement_vector_scratch.f[1] - spatial_and_hit_descriptor_scratch.f[1])) * 0.37f; if (a > 0.7853982f) { a = 0.7853982f; @@ -1988,9 +1988,9 @@ void hero_update_movement(void) { f32 a; f32 k; fast_vec_sub( - &v20, &((struct MobyView *)hero.grind_look_moby)->u10.v10, &hero.motion.pos); - transform_vector_by_basis(&v20, &v20, (Vec4 *)hero.inv_rot_matrix); - a = fast_arc_tan(v20.f[0], v20.f[1]); + &spatial_and_hit_descriptor_scratch, &((struct MobyView *)hero.grind_look_moby)->u10.v10, &hero.motion.pos); + transform_vector_by_basis(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, (Vec4 *)hero.inv_rot_matrix); + a = fast_arc_tan(spatial_and_hit_descriptor_scratch.f[0], spatial_and_hit_descriptor_scratch.f[1]); if (((struct MobyView *)hero.moby)->b52 == 0x31) { a = fast_subtract_rotations(a, 1.5707964f); hero_eases[3].rot_target.f[2] = a * 0.3f; @@ -2024,15 +2024,15 @@ void hero_update_movement(void) { hero.rail_segment, hero.grind_direction, hero.rail_spline_loops); - fast_vec_sub(&v20, (Vec4 *)hero.rail_spline + (idx + 1), &movement_and_hit_descriptor_scratch); - if (fast_vec_length(&v20) < 0.001f) { + fast_vec_sub(&spatial_and_hit_descriptor_scratch, (Vec4 *)hero.rail_spline + (idx + 1), &movement_and_hit_descriptor_scratch); + if (fast_vec_length(&spatial_and_hit_descriptor_scratch) < 0.001f) { if (hero.rail_segment == idx) { hero.rail_off_frames = scale_game_frames(1); break; } } else { - hero.rail_dir_yaw = fast_arc_tan(v20.f[0], v20.f[1]); - hero.rail_pitch = fast_arc_tan(vector_length_xy(&v20), v20.f[2]); + hero.rail_dir_yaw = fast_arc_tan(spatial_and_hit_descriptor_scratch.f[0], spatial_and_hit_descriptor_scratch.f[1]); + hero.rail_pitch = fast_arc_tan(vector_length_xy(&spatial_and_hit_descriptor_scratch), spatial_and_hit_descriptor_scratch.f[2]); } hero.motion.move_yaw = fast_add_rotations(hero.rail_dir_yaw, hero.grind_yaw_offset); turn_to(0, frame_scale_sq * 0.015f, frame_scale_sq * 0.15f, frame_time * 6.2831855f); @@ -2050,23 +2050,23 @@ void hero_update_movement(void) { } if (hero.rail_switching != 0 && hero.rail_transfer_frames <= scale_game_frames(48)) { f32 previous_path_blend_fraction; - fast_vec_sub(&v20, &movement_and_hit_descriptor_scratch, &v10); + fast_vec_sub(&spatial_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &v10); hero.rail_transfer_frames++; fast_vec_scale( - &v20, &v20, (f32)hero.rail_transfer_frames / (f32)scale_game_frames(48)); + &spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, (f32)hero.rail_transfer_frames / (f32)scale_game_frames(48)); previous_path_blend_fraction = (f32)(hero.rail_transfer_frames - 1) / (f32)scale_game_frames(48); fast_vec_sub(&movement_vector_scratch, &movement_and_hit_descriptor_scratch, &v10); fast_vec_scale(&movement_vector_scratch, &movement_vector_scratch, previous_path_blend_fraction); - hero.motion.pos.f[2] += v20.f[2] - movement_vector_scratch.f[2]; - fast_vec_add(&movement_vector_scratch, &v10, &v20); - fast_vec_sub(&v20, &movement_vector_scratch, &hero.motion.pos); - hero.motion.velocity.f[0] = v20.f[0]; - hero.motion.velocity.f[1] = v20.f[1]; - fast_vec_sub(&v20, &movement_and_hit_descriptor_scratch, &hero.rail_point); - hero.motion.pos.f[2] += v20.f[2]; + hero.motion.pos.f[2] += spatial_and_hit_descriptor_scratch.f[2] - movement_vector_scratch.f[2]; + fast_vec_add(&movement_vector_scratch, &v10, &spatial_and_hit_descriptor_scratch); + fast_vec_sub(&spatial_and_hit_descriptor_scratch, &movement_vector_scratch, &hero.motion.pos); + hero.motion.velocity.f[0] = spatial_and_hit_descriptor_scratch.f[0]; + hero.motion.velocity.f[1] = spatial_and_hit_descriptor_scratch.f[1]; + fast_vec_sub(&spatial_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &hero.rail_point); + hero.motion.pos.f[2] += spatial_and_hit_descriptor_scratch.f[2]; if (hero.motion.pos.f[2] < hero.rail_point.f[2]) { if (hero.rail_transfer_frames <= scale_game_frames(48) && hero.motion.pos.f[2] < hero.rail_point.f[2]) { @@ -2074,10 +2074,10 @@ void hero_update_movement(void) { } } } else { - fast_vec_sub(&v20, &movement_and_hit_descriptor_scratch, &hero.rail_point); - hero.motion.velocity.f[0] = v20.f[0]; - hero.motion.velocity.f[1] = v20.f[1]; - hero.motion.pos.f[2] += v20.f[2]; + fast_vec_sub(&spatial_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &hero.rail_point); + hero.motion.velocity.f[0] = spatial_and_hit_descriptor_scratch.f[0]; + hero.motion.velocity.f[1] = spatial_and_hit_descriptor_scratch.f[1]; + hero.motion.pos.f[2] += spatial_and_hit_descriptor_scratch.f[2]; fast_vec_sub(&movement_vector_scratch, &hero.rail_point, &hero.motion.pos); movement_vector_scratch.f[2] = 0.0f; if (fast_vec_length(&movement_vector_scratch) > frame_time) { @@ -2133,10 +2133,10 @@ void hero_update_movement(void) { approach_value(&hero.grind_base_speed, grind_base_speed_target, frame_time_sq * 15.0f); si = hero.rail_segment; sf = hero.rail_seg_frac; - qcopy(&v20, &hero.motion.pos); - sample_path((void *)hero.rail_spline, &v20, &si, &sf, 0.3f, hero.rail_spline_loops); - e = fast_arc_tan(vector_distance_xy(&hero.rail_point, &v20), - v20.f[2] - hero.rail_point.f[2]); + qcopy(&spatial_and_hit_descriptor_scratch, &hero.motion.pos); + sample_path((void *)hero.rail_spline, &spatial_and_hit_descriptor_scratch, &si, &sf, 0.3f, hero.rail_spline_loops); + e = fast_arc_tan(vector_distance_xy(&hero.rail_point, &spatial_and_hit_descriptor_scratch), + spatial_and_hit_descriptor_scratch.f[2] - hero.rail_point.f[2]); if (e > 0.0f) { sp = e * 1.9098593f * (frame_time * -2.5f); if (e > 0.2617994f && hero.grind_pose != 2 && hero.grind_pose != 3) { @@ -2168,26 +2168,26 @@ void hero_update_movement(void) { hero.unk574 = 0.0f; } fast_vec_sub(&hero.motion.velocity, &movement_and_hit_descriptor_scratch, &hero.rail_point); - fast_vec_sub(&v20, &hero.rail_point, &hero.motion.pos); + fast_vec_sub(&spatial_and_hit_descriptor_scratch, &hero.rail_point, &hero.motion.pos); { f32 mx = frame_time * 7.0f; f32 fl; f32 len; - fl = -fast_vec_length(&v20); + fl = -fast_vec_length(&spatial_and_hit_descriptor_scratch); vendor_spring(&fl, &hero.rail_snap_dist, 0.0f, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, mx); - len = fast_vec_length(&v20); + len = fast_vec_length(&spatial_and_hit_descriptor_scratch); if (len < hero.rail_snap_dist) { hero.rail_snap_dist = len; } if (hero.rail_snap_dist < len) { - fast_vec_normalize(&v20, &v20, hero.rail_snap_dist); + fast_vec_normalize(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, hero.rail_snap_dist); } - fast_vec_add(&hero.motion.pos, &hero.motion.pos, &v20); + fast_vec_add(&hero.motion.pos, &hero.motion.pos, &spatial_and_hit_descriptor_scratch); } if (hero.motion.pos.f[2] < hero.rail_point.f[2] && hero.ground_distance < 1.0f && hero.motion.pos.f[2] < hero.rail_point.f[2]) { @@ -2200,11 +2200,11 @@ void hero_update_movement(void) { matrix_vector_scratch[1].f[1] = fast_sin(a); matrix_vector_scratch[1].f[2] = 0.0f; make_hit_descriptor( - &v20, (struct MobyView *)hero.moby, 0x10000, 1.0f, &matrix_vector_scratch[1]); + &spatial_and_hit_descriptor_scratch, (struct MobyView *)hero.moby, 0x10000, 1.0f, &matrix_vector_scratch[1]); qcopy(&matrix_vector_scratch[2], &hero.motion.pos); matrix_vector_scratch[2].f[2] += 0.6f; collect_mobies_in_sphere( - 1.0f, &matrix_vector_scratch[2], 0x10, (struct MobyView *)hero.moby, &v20); + 1.0f, &matrix_vector_scratch[2], 0x10, (struct MobyView *)hero.moby, &spatial_and_hit_descriptor_scratch); } break; } @@ -2218,14 +2218,14 @@ void hero_update_movement(void) { f32 a; f32 r; qcopy(&v10, &movement_and_hit_descriptor_scratch); - fast_vec_scale(&v20, &hero.motion.displacement, 0.4f); + fast_vec_scale(&spatial_and_hit_descriptor_scratch, &hero.motion.displacement, 0.4f); a = fast_add_rotations(hero.grab_rail_yaw, randf_sym(0.0f, 0.5235988f)); r = random_float_between(frame_time * 0.0f, frame_time * 4.0f); - v20.f[0] += fast_cos(a) * r; - v20.f[1] += fast_sin(a) * r; - v20.f[2] = random_float_between(frame_time * 3.0f, frame_time * 5.0f); - v20.f[3] = -(frame_time_sq * 35.0f); - spawn_color_decaying_effect_particle(&v10, &v20, 0); + spatial_and_hit_descriptor_scratch.f[0] += fast_cos(a) * r; + spatial_and_hit_descriptor_scratch.f[1] += fast_sin(a) * r; + spatial_and_hit_descriptor_scratch.f[2] = random_float_between(frame_time * 3.0f, frame_time * 5.0f); + spatial_and_hit_descriptor_scratch.f[3] = -(frame_time_sq * 35.0f); + spawn_color_decaying_effect_particle(&v10, &spatial_and_hit_descriptor_scratch, 0); } } FUN_L00_0025df68(hero.follow_path_spline, @@ -2252,39 +2252,39 @@ void hero_update_movement(void) { hero.rail_candidate_kind); idx = offset_path_index( hero.follow_path_spline, hero.follow_path_segment, 1, hero.rail_candidate_kind); - fast_vec_sub(&v20, (Vec4 *)hero.follow_path_spline + (idx + 1), &v10); - if (fast_vec_length(&v20) < 0.001f) { + fast_vec_sub(&spatial_and_hit_descriptor_scratch, (Vec4 *)hero.follow_path_spline + (idx + 1), &v10); + if (fast_vec_length(&spatial_and_hit_descriptor_scratch) < 0.001f) { if (hero.follow_path_segment == idx) { hero.follow_path_end_frames = scale_game_frames(1); break; } } else { - hero.grab_rail_yaw = fast_arc_tan(v20.f[0], v20.f[1]); - hero.follow_path_pitch = fast_arc_tan(vector_length_xy(&v20), v20.f[2]); + hero.grab_rail_yaw = fast_arc_tan(spatial_and_hit_descriptor_scratch.f[0], spatial_and_hit_descriptor_scratch.f[1]); + hero.follow_path_pitch = fast_arc_tan(vector_length_xy(&spatial_and_hit_descriptor_scratch), spatial_and_hit_descriptor_scratch.f[2]); } hero.motion.move_yaw = hero.grab_rail_yaw; turn_to(0, frame_scale_sq * 0.018f, frame_scale_sq * 0.2f, frame_time * 6.4577184f); approach_value(&hero.follow_path_speed, frame_time * 14.0f, frame_time_sq * 9.0f); fast_vec_sub(&hero.motion.velocity, &v10, &hero.grab_rail_point); - fast_vec_sub(&v20, &hero.grab_rail_point, &movement_and_hit_descriptor_scratch); + fast_vec_sub(&spatial_and_hit_descriptor_scratch, &hero.grab_rail_point, &movement_and_hit_descriptor_scratch); { f32 fl; f32 len; - fl = -fast_vec_length(&v20); + fl = -fast_vec_length(&spatial_and_hit_descriptor_scratch); vendor_spring(&fl, &hero.unk618.f, 0.0f, frame_scale_sq * 0.05f, frame_scale_sq * 0.3f, frame_time * 10.0f); - len = fast_vec_length(&v20); + len = fast_vec_length(&spatial_and_hit_descriptor_scratch); if (len < hero.unk618.f) { hero.unk618.f = len; } if (hero.unk618.f < len) { - fast_vec_normalize(&v20, &v20, hero.unk618.f); + fast_vec_normalize(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, hero.unk618.f); } - fast_vec_add(&hero.motion.pos, &hero.motion.pos, &v20); + fast_vec_add(&hero.motion.pos, &hero.motion.pos, &spatial_and_hit_descriptor_scratch); } break; } @@ -2314,7 +2314,7 @@ void hero_update_movement(void) { hero.motion.velocity.f[0] = 0.0f; hero.motion.velocity.f[1] = 0.0f; hero.motion.velocity.f[2] = 0.0f; - qcopy(&v20, &hero.motion.pos); + qcopy(&spatial_and_hit_descriptor_scratch, &hero.motion.pos); if (hero.state.current == 0x1A) { matrix_vector_scratch[0].f[0] = fast_cos(fast_add_rotations(hero.motion.rot.f[2], 1.5707964f)) * 0.3f; @@ -2328,7 +2328,7 @@ void hero_update_movement(void) { fast_sin(fast_add_rotations(hero.motion.rot.f[2], -1.5707964f)) * 0.3f; matrix_vector_scratch[0].f[2] = 0.0f; } - fast_vec_add(&movement_vector_scratch, &v20, &matrix_vector_scratch[0]); + fast_vec_add(&movement_vector_scratch, &spatial_and_hit_descriptor_scratch, &matrix_vector_scratch[0]); check_ledge_grab(); if (hero.ledge_found == 0) { break; @@ -2337,7 +2337,7 @@ void hero_update_movement(void) { a = fast_add_rotations(hero.ledge_normal_yaw, 3.1415927f); qcopy(&hero.motion.pos, &movement_vector_scratch); check_ledge_grab(); - qcopy(&hero.motion.pos, &v20); + qcopy(&hero.motion.pos, &spatial_and_hit_descriptor_scratch); if (hero.ledge_found == 0) { break; } @@ -2842,8 +2842,8 @@ void hero_update_movement(void) { hero.anim_frame <= (f32)tb->f20) { s32 k = tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION ? 0 : 2; moby_point_position((struct MobyView *)hero.moby, k, &v10); - moby_point_position((struct MobyView *)hero.moby, k | 1, &v20); - fast_vec_add(&movement_and_hit_descriptor_scratch, &v10, &v20); + moby_point_position((struct MobyView *)hero.moby, k | 1, &spatial_and_hit_descriptor_scratch); + fast_vec_add(&movement_and_hit_descriptor_scratch, &v10, &spatial_and_hit_descriptor_scratch); fast_vec_scale(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, 0.5f); play_entity_sound( (struct MobyView *)hero.moby, 0.25f, &movement_and_hit_descriptor_scratch, 0x10000, 1.0f, 1.0f, 0, 1, 0); @@ -2972,7 +2972,7 @@ void hero_update_movement(void) { hero.anim_speed = 1.3f; hero.motion.velocity.f[1] = 0.0f; hero.motion.velocity.f[2] = 0.0f; - qcopy(&v20, &hero.motion.pos); + qcopy(&spatial_and_hit_descriptor_scratch, &hero.motion.pos); if (hero.state.current == 0x4D) { matrix_vector_scratch[0].f[0] = fast_cos(fast_add_rotations(hero.motion.rot.f[2], 1.5707964f)) * 0.3f; @@ -2986,7 +2986,7 @@ void hero_update_movement(void) { fast_sin(fast_add_rotations(hero.motion.rot.f[2], -1.5707964f)) * 0.3f; matrix_vector_scratch[0].f[2] = 0.0f; } - fast_vec_add(&movement_vector_scratch, &v20, &matrix_vector_scratch[0]); + fast_vec_add(&movement_vector_scratch, &spatial_and_hit_descriptor_scratch, &matrix_vector_scratch[0]); check_ledge_grab(); if (hero.ledge_found == 0) { break; @@ -2995,7 +2995,7 @@ void hero_update_movement(void) { a = fast_add_rotations(hero.ledge_normal_yaw, 3.1415927f); qcopy(&hero.motion.pos, &movement_vector_scratch); check_ledge_grab(); - qcopy(&hero.motion.pos, &v20); + qcopy(&hero.motion.pos, &spatial_and_hit_descriptor_scratch); if (hero.ledge_found == 0) { break; } @@ -3050,9 +3050,9 @@ void hero_update_movement(void) { &v10, (struct MobyView *)hero.moby, 0xB0000, 4.0f, &matrix_vector_scratch[0]); v10.f[2] = 1.0f; v10.f[3] = 5627.925f; - ((u8 *)&v20)[8] = 7; - ((u8 *)&v20)[9] = 1; - ((s16 *)&v20)[5] = ((struct MobyView *)hero.moby)->hA6; + ((u8 *)&spatial_and_hit_descriptor_scratch)[8] = 7; + ((u8 *)&spatial_and_hit_descriptor_scratch)[9] = 1; + ((s16 *)&spatial_and_hit_descriptor_scratch)[5] = ((struct MobyView *)hero.moby)->hA6; switch (hero.attack_record) { case HERO_ATTACK_RECORD_POINT_3_STRIKE: if (hero.anim_frame > 7.0f && hero.anim_frame < 14.0f) { From 2de939c9a066b373600d812abe09b2d45efa3eaf Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:09:35 +0000 Subject: [PATCH 0335/1502] decomp: clarify names in trigger_pokitaru_paired_rotation domain_0_value_1 -> POKITARU_PAIRED_ROTATION_WAITING: Retail 0x002cb990 checks input oclass at +0xA6 against 0x41, then 0x002cb9a0..0x002cb9a8 checks that same moby's state byte at +0x20 equals 1 before permitting trigger_pokitaru_paired_rotation to advance it. The supplied original retail plate explicitly identifies state 1 as waiting; resort-owner completion callers pass the distinct indexed target from pvars+0x104, proving this is the paired rotation target domain rather than ResortOwnerState or any Hero enum. domain_1_value_2 -> POKITARU_PAIRED_ROTATION_ROTATING: Retail 0x002cb9b0 loads 2 and 0x002cb9b8 stores it to the class-0x41 input Moby.state at +0x20; 0x002cb9bc loads the optional partner from pvars+8 and 0x002cb9c4 stores the same state to that partner. The original supplied retail plate states that existing FUN_L11_002cb810 creates this partner and drives opposite signed yaw offsets in state 2, establishing rotating as the meaning in this paired-rotation moby domain, independent of the caller's resort-owner state and Hero enums. --- src/overlays/l11/mobys/resort_owner.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l11/mobys/resort_owner.c b/src/overlays/l11/mobys/resort_owner.c index 9932f8e638..8300dc5c2e 100644 --- a/src/overlays/l11/mobys/resort_owner.c +++ b/src/overlays/l11/mobys/resort_owner.c @@ -92,11 +92,11 @@ typedef struct ResortOwnerVars { } ResortOwnerVars; void trigger_pokitaru_paired_rotation(struct Moby *moby) { - ResortOwnerVars *state = (ResortOwnerVars *)moby->pvars; - if (moby->oclass == 0x41 && moby->state == 1) { + enum { POKITARU_PAIRED_ROTATION_WAITING = 1 , POKITARU_PAIRED_ROTATION_ROTATING = 2 } ;ResortOwnerVars *state = (ResortOwnerVars *)moby->pvars; + if (moby->oclass == 0x41 && moby->state == POKITARU_PAIRED_ROTATION_WAITING) { char *child; D_0013D3E2[0] = moby->state; - moby->state = 2; + moby->state = POKITARU_PAIRED_ROTATION_ROTATING; child = state->unk8; if (child) child[0x20] = 2; From 0b7f9d59b199e28fe034fc54519fa25a790bda40 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:09:35 +0000 Subject: [PATCH 0336/1502] decomp: clarify names in is_kerwan_path_enemy_in_state_9 domain_2_value_9 -> ENEMY_FOLLOW_ALTERNATE_PATH: Retail 0x002c6d60 loads the Moby state byte at +0x20; 0x002c6d74-0x002c6d78 restrict the object to class 0x23E, and 0x002c6d80-0x002c6d88 test that same state for 9. The authoritative kerwan_path_enemy.c snapshot (SHA-256 37dfea2f432c5deda0f3162bcb89251e5593f5abfad49f120faf6756e7b0cf8f) defines ENEMY_FOLLOW_ALTERNATE_PATH = 9 in update_kerwan_path_enemy's switch on the same Moby state field. Its activation branch sets state 9 when i290 selects an alternate path, resets i298, and selects locomotion. That case loads l03_paths[moby_data->i290], advances i298 through path nodes using step_mover_2e3f20, then clears i290 and leaves the state at path completion. This is the enemy state domain, not HeroStateId. --- src/overlays/l03/mobys/kerwan_path_enemy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l03/mobys/kerwan_path_enemy.c b/src/overlays/l03/mobys/kerwan_path_enemy.c index d660fe70c3..086f353306 100644 --- a/src/overlays/l03/mobys/kerwan_path_enemy.c +++ b/src/overlays/l03/mobys/kerwan_path_enemy.c @@ -362,8 +362,11 @@ void axis_angle_rotation_to_euler(AxisAngleQuad *axis, AxisAngleQuad *point, flo int is_kerwan_path_enemy_in_state_9(struct Moby *moby) __asm__("FUN_L03_002c6d58"); int is_kerwan_path_enemy_in_state_9(struct Moby *moby) { + enum { + ENEMY_FOLLOW_ALTERNATE_PATH = 0x9 + }; if (moby && moby->state != 0xFE && moby->state != 0xFD && moby->oclass == 0x23e && - moby->state == 0x9) { + moby->state == ENEMY_FOLLOW_ALTERNATE_PATH) { return 1; } return 0; From bdc4a198f1dee133e853006668e1341574c4e5a7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:11:33 +0000 Subject: [PATCH 0337/1502] decomp: clarify names in save_card_state_check_save domain_0_value_2 -> MEMCARD_DISPATCH_PENDING_OPERATION: Retail 0x00208bc0/0x00208bc8 forms memory_card_state at 0x0013d290; 0x00208bcc loads +0xd4 and 0x00208bd0 compares it with 2. The bound source identifies +0xd4 as MemoryCardState.state, and retail Ghidra names it g_nMemoryCardOperationState. The supplied memory_card_state.h enum-domain declaration explicitly assigns state/pending_state to MemoryCardOperation, whose canonical member for 2 is MEMCARD_DISPATCH_PENDING_OPERATION; this is not a per-operation substep. domain_2_value_7 -> MEMCARD_REQUEST_CHDIR: Retail 0x00208bd8 loads pending operation at memory_card_state +0xdc, 0x00208bdc requires it to be negative, then 0x00208be0 and 0x00208be8 store 7 to that same field; 0x00208bec selects pending_card 0 at +0xe0. Source maps +0xdc to MemoryCardState.pending_state and original Ghidra calls it g_nPendingMemoryCardOperationState. The supplied header context places pending_state in MemoryCardOperation, where 7 is the established MEMCARD_REQUEST_CHDIR, rather than an equal-valued read/create substep. --- src/ui/menus/save_data/save_card_state_check_save.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/menus/save_data/save_card_state_check_save.c b/src/ui/menus/save_data/save_card_state_check_save.c index 55e8899224..3e02470322 100644 --- a/src/ui/menus/save_data/save_card_state_check_save.c +++ b/src/ui/menus/save_data/save_card_state_check_save.c @@ -7,8 +7,8 @@ void save_card_state_check_save(void) __asm__("FUN_00208bc0"); void save_card_state_check_save(void) { struct MemoryCardState *card_state = &memory_card_state; - if (card_state->state == 2 && card_state->pending_state < 0) { - card_state->pending_state = 7; + if (card_state->state == MEMCARD_DISPATCH_PENDING_OPERATION && card_state->pending_state < 0) { + card_state->pending_state = MEMCARD_REQUEST_CHDIR; card_state->pending_card = 0; mode_freeze_state = 0xB; } From 0ad1fd0b486cb3c083ddaba342f0ed9376caa886 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:11:33 +0000 Subject: [PATCH 0338/1502] decomp: clarify names in save_card_state_create_save_pending domain_0_value_2 -> MEMCARD_DISPATCH_PENDING_OPERATION: Retail 0x00208d28 forms a1=0x0013d290; 0x00208d2c loads its +0xd4 operation state and 0x00208d30 compares it with 2. Original Ghidra identifies g_nMemoryCardOperationState, while the bound source identifies MemoryCardState.state. The supplied memory_card_state.h domain context explicitly assigns state/pending_state to MemoryCardOperation, whose canonical member for 2 is MEMCARD_DISPATCH_PENDING_OPERATION, independently of the substep enums. domain_2_value_9 -> MEMCARD_BEGIN_CREATE_SAVE_DIRECTORY: Retail 0x00208d38 loads pending operation state at 0x0013d290+0xdc, 0x00208d3c requires it to be negative, and 0x00208d40/0x00208d48 store 9 to that same field; +0xe0 pending_card is cleared next. Original Ghidra calls the field g_nPendingMemoryCardOperationState; source binds it to MemoryCardState.pending_state in save_card_state_create_save_pending. The supplied shared header explicitly places pending_state in MemoryCardOperation, whose canonical value 9 is MEMCARD_BEGIN_CREATE_SAVE_DIRECTORY, rather than the unrelated create substep value 9. --- src/ui/menus/save_data/save_card_state_create_save_pending.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/menus/save_data/save_card_state_create_save_pending.c b/src/ui/menus/save_data/save_card_state_create_save_pending.c index 5d53c7d912..25e5f6cecd 100644 --- a/src/ui/menus/save_data/save_card_state_create_save_pending.c +++ b/src/ui/menus/save_data/save_card_state_create_save_pending.c @@ -6,8 +6,8 @@ void save_card_state_create_save_pending(void) __asm__("FUN_00208d20"); void save_card_state_create_save_pending(void) { struct MemoryCardState *card_state = &memory_card_state; - if (card_state->state == 2 && card_state->pending_state < 0) { - card_state->pending_state = 9; + if (card_state->state == MEMCARD_DISPATCH_PENDING_OPERATION && card_state->pending_state < 0) { + card_state->pending_state = MEMCARD_BEGIN_CREATE_SAVE_DIRECTORY; card_state->pending_card = 0; mode_freeze_state = 0xF; } From 64de4eb1b15104aa9de16dc0ea85f0becf068c7d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:11:33 +0000 Subject: [PATCH 0339/1502] decomp: clarify names in audio_dec_reset domain_0_value_0 -> AUDIO_DEC_STATE_RESET: In the SHA-256-bound audio_dec_reset source, dec is struct AudioDec* and dec->state = 0 follows snd_reset_movie_sound(). Retail 0x0023ad20 preserves a0 in s0, 0x0023ad24 stores zero at offset 0x5c (state), and 0x0023ad28-0x0023ad40 clear decoder counters and positions. Original Ghidra likewise writes param_1[0x17] = 0 after shutdown_mpeg_audio_rpc_driver(). The read_mpeg caller invokes audio_dec_reset(&movie_player->audio_dec) after end_display(), proving this is the decoder state established by reset. --- src/audio/decoder/audio_dec_reset.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/decoder/audio_dec_reset.c b/src/audio/decoder/audio_dec_reset.c index dec9bd089d..c52f9bf426 100644 --- a/src/audio/decoder/audio_dec_reset.c +++ b/src/audio/decoder/audio_dec_reset.c @@ -5,8 +5,11 @@ extern s32 snd_reset_movie_sound() __asm__("func_0012F0A8"); void audio_dec_reset(struct AudioDec *dec) __asm__("FUN_0023ad10"); void audio_dec_reset(struct AudioDec *dec) { + enum { + AUDIO_DEC_STATE_RESET = 0 + }; snd_reset_movie_sound(); - dec->state = 0; + dec->state = AUDIO_DEC_STATE_RESET; dec->hdrCount = 0; dec->put = 0; dec->count = 0; From 0773c28041660c46df3e64f31ab62b2cb127ea2f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:11:34 +0000 Subject: [PATCH 0340/1502] decomp: clarify names in request_target_reposition domain_0_value_1 -> TARGET_REPOSITION_STATE_REQUESTABLE: Retail 0x002e0de4 loads 1 into v1; 0x002e0df4 reads the target moby's unsigned state byte at s0+0x20 and 0x002e0df8 rejects any other state. Only this gate permits allocate_voice_for_target_entry(0,0,moby) and the reposition-request state write. The supplied update_chicken_relocator calls this function on its linked target, proving a target reposition request gate rather than a hero or voice-slot domain. domain_1_value_7 -> TARGET_REPOSITION_STATE_REQUESTED: After requesting target sound entry 0 at retail 0x002e0e08, 0x002e0e10 loads 7 and 0x002e0e14 stores it into the same target moby state byte at s0+0x20. The supplied get_target_reposition_status reads that byte, treats states 7/8 as pending, and reports readiness only in state 8 with pvars+0x34 > 0.2; update_chicken_relocator polls it before repositioning its linked chicken. Thus 7 is the target state entered by the reposition request. --- src/overlays/l16/mobys/chicken_relocator.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l16/mobys/chicken_relocator.c b/src/overlays/l16/mobys/chicken_relocator.c index 58c09b8b55..b11d3ddb57 100644 --- a/src/overlays/l16/mobys/chicken_relocator.c +++ b/src/overlays/l16/mobys/chicken_relocator.c @@ -154,10 +154,14 @@ int is_moby_in_state_6(Level16VendorMoby *moby) { void request_target_reposition(struct Moby *moby) __asm__("FUN_L16_002e0de0"); void request_target_reposition(struct Moby *moby) { - int state = 1; + enum { + TARGET_REPOSITION_STATE_REQUESTABLE = 1, + TARGET_REPOSITION_STATE_REQUESTED = 7 + }; + int state = TARGET_REPOSITION_STATE_REQUESTABLE; if (moby->state == state) { allocate_voice_for_target_entry(0, 0, moby); - state = 7; + state = TARGET_REPOSITION_STATE_REQUESTED; moby->state = state; } } From 3f240e18bd79fc71a1000c8a3ce1cb53055247cf Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:13:31 +0000 Subject: [PATCH 0341/1502] decomp: clarify names in music_transition_start_callback domain_0_value_0 -> NULL: In source snapshot src/audio/streaming/music_callbacks/music_transition_start_callback.c (SHA-256 795261870e7685166da06ec21b986567975b2bfacb247fd9c448b15fa0d45835), channel_state is a short pointer obtained from channel_state_address. Retail 0x00216a80-0x00216a88 narrows a1 and branches on a1==zero before the store through a1 at 0x00216a94. Original Ghidra explicitly checks pState != (DialogueChannelState *)0x0. Thus this listed zero denotes a null pointer and matches the existing NULL constant, rather than a numeric channel phase. --- .../streaming/music_callbacks/music_transition_start_callback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/streaming/music_callbacks/music_transition_start_callback.c b/src/audio/streaming/music_callbacks/music_transition_start_callback.c index 8766d91afd..32dae6bc5e 100644 --- a/src/audio/streaming/music_callbacks/music_transition_start_callback.c +++ b/src/audio/streaming/music_callbacks/music_transition_start_callback.c @@ -6,7 +6,7 @@ void music_transition_start_callback(int handle, long context) __asm__("FUN_0021 void music_transition_start_callback(int handle, long channel_state_address) { short *channel_state = (short *)(int)channel_state_address; - if (channel_state != 0) { + if (channel_state != NULL) { *(int *)channel_state = handle; if (handle != 0) { short previous_state = channel_state[5]; From 91778a3fc225502d928126b7455c3620b34af1c7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:13:32 +0000 Subject: [PATCH 0342/1502] decomp: clarify names in poll_moby_state_and_rearm domain_0_value_3 -> THRUSTER_PACK_LOCK_RED_STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT: Retail 002d8050-002d8058 compares the incoming Moby state byte at +0x20 against 3. The authoritative same-file thruster_pack_lock_red_update names this state STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT and handles it with advance_accelerated_scalar toward saved height + approach offset. Its grounded-hero wait branch and end_thruster_pack_lock_red_wait both set this same Moby state to 3. Poll resets it to 1 and reports completion; this is the red-lock state domain, not HeroStateId. domain_1_value_1 -> THRUSTER_PACK_LOCK_RED_STATE_APPROACH_CONFIGURED_HEIGHT: Retail 002d8060 and 002d806c write 1 back to the incoming Moby state byte at +0x20 after observing state 3. In the authoritative same-file thruster_pack_lock_red_update, STATE_APPROACH_CONFIGURED_HEIGHT = 1 drives moby->pos.z toward saved height + l18_thruster_pack_lock_red_approach_height_offset. The initialized configured lock also enters state 1, proving the rearm target is its configured-height approach state rather than a hero mode. domain_2_value_2 -> THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER: Retail 002d8070-002d8088 compares the same incoming Moby state byte against 2 and returns -1 only when its pvars+0x6c timer is zero. The authoritative same-file request_thruster_pack_lock_red_wait sets moby->state = 2 and stores wait_duration_frames at that exact private offset. thruster_pack_lock_red_update names state 2 STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER, decrements that timer, and transitions to 3 when hero.air_frames.s == 0, hero.ground_moby == moby and hero.state.current == 0x22. Thus this is the lock wait state, not the hero's own state enum. --- src/overlays/l18/mobys/thruster_pack_lock_red.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/overlays/l18/mobys/thruster_pack_lock_red.c b/src/overlays/l18/mobys/thruster_pack_lock_red.c index e56003c88f..ed0f118148 100644 --- a/src/overlays/l18/mobys/thruster_pack_lock_red.c +++ b/src/overlays/l18/mobys/thruster_pack_lock_red.c @@ -193,12 +193,17 @@ void end_thruster_pack_lock_red_wait(struct Moby *moby) { int poll_moby_state_and_rearm(struct Moby *moby) __asm__("FUN_L18_002d8050"); int poll_moby_state_and_rearm(struct Moby *moby) { + enum { + THRUSTER_PACK_LOCK_RED_STATE_APPROACH_CONFIGURED_HEIGHT = 1, + THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER = 2, + THRUSTER_PACK_LOCK_RED_STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT = 3 + }; int *moby_private_vars = (int *)moby->pvars; - if (moby->state == 3) { - moby->state = 1; + if (moby->state == THRUSTER_PACK_LOCK_RED_STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT) { + moby->state = THRUSTER_PACK_LOCK_RED_STATE_APPROACH_CONFIGURED_HEIGHT; return 1; } - if (moby->state == 2 && moby_private_vars[0x6C / 4] == 0) { + if (moby->state == THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER && moby_private_vars[0x6C / 4] == 0) { return -1; } return 0; From 1397cbdf89b08ee1acd0619ecadf55be2d9e11e3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:13:32 +0000 Subject: [PATCH 0343/1502] decomp: clarify names in request_floating_platform_tilt domain_0_value_1 -> STATE_WAIT_FOR_TILT_REQUEST: Retail 0x002d8888 lbu v1,0x20(a0) reads platform_moby->state and 0x002d888c-0x002d8890 accepts only value 1. Original Ghidra likewise tests *(char *)(param_1+0x20) against 1. In the authoritative source floating_platform_update switches on the same Moby state field and already names 1 STATE_WAIT_FOR_TILT_REQUEST; this branch idles until this tilt request changes it. request_floating_platform_sink independently uses that same platform state name. The supplied boss caller passes an in-range platform to request_floating_platform_tilt, proving the platform domain rather than any hero domain. domain_1_value_3 -> STATE_TILT_DELAY: Retail 0x002d88a0 loads 3 and 0x002d88a8 stores it to the same platform_moby state byte at +0x20; 0x002d88b4 stores tilt_delay_frames to its pvars+0x7C. Original Ghidra confirms the state assignment and private-data stores. The authoritative same-file floating_platform_update defines STATE_TILT_DELAY=3 for this exact platform state selector and decrements pvars+0x7C in that case before setting tilt rate and transitioning to state 4. The supplied boss caller initializes this delay with scale_game_frames(0x3C), supporting reuse of the established platform constant. --- src/overlays/l18/mobys/floating_platform.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/floating_platform.c b/src/overlays/l18/mobys/floating_platform.c index d8458c279c..b06f4caa7b 100644 --- a/src/overlays/l18/mobys/floating_platform.c +++ b/src/overlays/l18/mobys/floating_platform.c @@ -252,9 +252,13 @@ int request_floating_platform_tilt(struct Moby *platform_moby, int tilt_delay_frames, int scaled_frame_count) { + enum { + STATE_WAIT_FOR_TILT_REQUEST = 1, + STATE_TILT_DELAY = 3 + }; int *platform_vars = (int *)platform_moby->pvars; - if (platform_moby->state == 1) { - platform_moby->state = 3; + if (platform_moby->state == STATE_WAIT_FOR_TILT_REQUEST) { + platform_moby->state = STATE_TILT_DELAY; platform_vars[0x7C / 4] = tilt_delay_frames; platform_vars[0x78 / 4] = scaled_frame_count; return 1; From e2202353fdadf2dde082095b873debd324747ce4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:13:32 +0000 Subject: [PATCH 0344/1502] decomp: clarify names in store_hoven_anklebiter_in_suck_cannon domain_0_value_8 -> ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME: At 0x002e1768 the incoming Hoven anklebiter Moby is retained in s0; 0x002e1778 loads its state byte at +0x20 and 0x002e177c-0x002e1780 compare it with 8 after store_moby_in_suck_cannon returns zero. The supplied same-class update_hoven_anklebiter switches on moby->state and already names 8 ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME, whose branch runs controlled motion then transitions to return-home state 6. This is the anklebiter state domain, not HeroStateId. domain_1_value_1 -> ANKLEBITER_IDLE: Retail 0x002e1788 loads 1 and 0x002e178c writes it to the preserved anklebiter Moby state byte +0x20 only when storage returned zero and the prior state was 8. The authoritative source's update_hoven_anklebiter switches on this same-class moby->state, explicitly defines ANKLEBITER_IDLE = 1 and implements idle wandering and target acquisition there; its return-home branch also resets state to 1. Reuse that existing anklebiter state name. domain_2_value_8 -> ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME: The helper result is moved from v0 to a0 at 0x002e176c; the nonzero branch at 0x002e1770 uses li v0,8 in the delay slot and stores that byte to the same anklebiter's state +0x20 at 0x002e178c. Thus this assignment enters the exact same state tested by domain_0_value_8. The supplied update_hoven_anklebiter enum and state switch canonically name it ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME; reuse the member for both tokens. --- src/overlays/l12/mobys/hoven_anklebiter.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l12/mobys/hoven_anklebiter.c b/src/overlays/l12/mobys/hoven_anklebiter.c index b66378d3f8..c8a892c801 100644 --- a/src/overlays/l12/mobys/hoven_anklebiter.c +++ b/src/overlays/l12/mobys/hoven_anklebiter.c @@ -51,12 +51,16 @@ extern int store_moby_in_suck_cannon(void *) __asm__("FUN_L00_002dbb20"); int store_hoven_anklebiter_in_suck_cannon(struct Moby *a) __asm__("FUN_L12_002e1758"); int store_hoven_anklebiter_in_suck_cannon(struct Moby *carried_moby) { + enum { + ANKLEBITER_IDLE = 1, + ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME = 0x8 + }; int suck_cannon_store_result = store_moby_in_suck_cannon(carried_moby); if (suck_cannon_store_result == 0) { - if (carried_moby->state == 0x8) - carried_moby->state = 1; + if (carried_moby->state == ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME) + carried_moby->state = ANKLEBITER_IDLE; } else { - carried_moby->state = 0x8; + carried_moby->state = ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME; } return suck_cannon_store_result; } From 04c24fe6b9a268f380fbf50c30d6e9cab9ee5877 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:15:18 +0000 Subject: [PATCH 0345/1502] decomp: clarify names in process_suck_cannon_suction_and_update_moby_state domain_0_value_9 -> MOBY_STATE_SUCK_CANNON_ACTIVE: The authoritative horny_toad.c snapshot (SHA-256 788bb449a2bd97cd3b3c683ec33702a9398e72da29893e561692ab2977339e25) compares MOBY(moby)->state with 9 after process_moby_suck_cannon_suction returns zero. Retail 0x002d56ec calls that helper; 0x002d56f8 branches on its unchanged return; 0x002d56fc/0x002d5714 store 9 at moby+0x20 on nonzero, while 0x002d5700-0x002d5714 change only previous state 9 to 5 on zero. Checked helper evidence 396030f914974bfa8999e0f31cd6b54b proves returns 1/2/3 for its suction processing and storage branches (0x002dba20, 0x002dba48, 0x002dba50), and zero for missing/invalid/finished processing (0x002dbafc). Its selector is the separate suction record halfword +0x68, not moby state +0x20. Thus 9 is the wrapper's active Suck Cannon handling state, including stored objects; no relationship to HeroStateId is implied. --- src/overlays/shared/enemies/horny_toad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/horny_toad.c b/src/overlays/shared/enemies/horny_toad.c index 47920e0cfc..495b5e3342 100644 --- a/src/overlays/shared/enemies/horny_toad.c +++ b/src/overlays/shared/enemies/horny_toad.c @@ -626,9 +626,9 @@ extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); int process_suck_cannon_suction_and_update_moby_state(char *a) __asm__("FUN_L00_002d56e0"); int process_suck_cannon_suction_and_update_moby_state(char *moby) { - int suction_result = process_moby_suck_cannon_suction(moby); + enum { MOBY_STATE_SUCK_CANNON_ACTIVE = 0x9 } ;int suction_result = process_moby_suck_cannon_suction(moby); if (suction_result == 0) { - if (MOBY(moby)->state == 0x9) + if (MOBY(moby)->state == MOBY_STATE_SUCK_CANNON_ACTIVE) MOBY(moby)->state = 0x5; } else { MOBY(moby)->state = 0x9; From ebab0e017decdddc6ffabdc907a56e88ec59b761 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:15:18 +0000 Subject: [PATCH 0346/1502] decomp: clarify names in moby_hold_state_if_found domain_0_value_14 -> LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION: Retail 0x002efb18 loads the incoming Moby current-state byte at s0+0x20 and 0x002efb1c/0x002efb20 compare it with 14 after store_moby_in_suck_cannon returns zero. The authoritative large_amoeboid.c groups this callback under amoeboid suck-cannon methods; large_amoeboid_update switches on this same Moby state field and already names 14 LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION, whose branch processes suck-cannon interaction and returns to state 1. Neighboring suction and cancellation callbacks also assign 14 to this same field. This is the current-state domain, not the helper's separate suction-record state. domain_1_value_1 -> LARGE_AMOEBOID_TRY_ACQUIRE_TARGET_PATH: Retail 0x002efb28 loads 1 and 0x002efb2c writes it to incoming Moby state +0x20 only when the store helper returns zero and the previous state was 14. In this authoritative amoeboid-method compilation unit, large_amoeboid_update already names current state 1 LARGE_AMOEBOID_TRY_ACQUIRE_TARGET_PATH and that case invokes follow_path to acquire the target path. Its suck-cannon interaction case likewise restores the same state 1. The selector is the Moby current-state byte, not the helper return boolean; TRUE is not the appropriate domain constant. domain_2_value_14 -> LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION: Retail 0x002efb10 branches on the nonzero store_moby_in_suck_cannon return, with 14 loaded in the delay slot at 0x002efb14 and stored to s0+0x20 at 0x002efb2c. This callback belongs to the authoritative source's amoeboid suck-cannon methods and uses the same Moby current-state field switched on by large_amoeboid_update, where 14 is already LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION. The neighboring process_amoeboid_suck_cannon_suction and cancellation callback also enter that state. Reuse the same domain member as the comparison rather than inventing a separate storage-success state. --- src/overlays/shared/enemies/large_amoeboid.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/large_amoeboid.c b/src/overlays/shared/enemies/large_amoeboid.c index fadbff94b2..939f7024ec 100644 --- a/src/overlays/shared/enemies/large_amoeboid.c +++ b/src/overlays/shared/enemies/large_amoeboid.c @@ -1107,12 +1107,16 @@ extern int store_moby_in_suck_cannon(void *) __asm__("FUN_L00_002dbb20"); int moby_hold_state_if_found(struct Moby *a) __asm__("FUN_L01_002efaf8"); int moby_hold_state_if_found(struct Moby *target_moby) { + enum { + LARGE_AMOEBOID_TRY_ACQUIRE_TARGET_PATH = 1, + LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION = 0xe + }; int suck_cannon_store_result = store_moby_in_suck_cannon(target_moby); if (suck_cannon_store_result == 0) { - if (target_moby->state == 0xe) - target_moby->state = 1; + if (target_moby->state == LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION) + target_moby->state = LARGE_AMOEBOID_TRY_ACQUIRE_TARGET_PATH; } else { - target_moby->state = 0xe; + target_moby->state = LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION; } return suck_cannon_store_result; } From 99e8f417ffbf55f9cdc788a2a09e28d7bdb48560 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:15:18 +0000 Subject: [PATCH 0347/1502] decomp: clarify names in moby_hold_state_if_grabbed domain_0_value_7 -> GROUND_ENEMY_STATE_RECOVER_TO_IDLE: Retail 0x002f1c98 loads the incoming moby's state byte at +0x20 and 0x002f1c9c-0x002f1ca0 compares it with 7 after the suction helper returns zero. The same source's update_ground_melee_enemy switches on Moby->state with GROUND_ENEMY_STATE_RECOVER_TO_IDLE=7, whose recover_2E39E0 branch transitions to idle 1; this is an enemy Moby state, not HeroStateId. domain_1_value_1 -> GROUND_ENEMY_STATE_IDLE: Retail 0x002f1ca8 loads 1 and 0x002f1cac stores it to the same moby's +0x20 state only when suction returns zero and prior state is 7. Authoritative update_ground_melee_enemy declares GROUND_ENEMY_STATE_IDLE=1 and its GROUND_ENEMY_STATE_RECOVER_TO_IDLE branch likewise assigns state 1 on successful recovery. domain_2_value_7 -> GROUND_ENEMY_STATE_RECOVER_TO_IDLE: Retail 0x002f1c90 branches on a nonzero suction result with delay-slot v0=7 at 0x002f1c94, storing it to the incoming Moby state byte at 0x002f1cac. This is the same field/value tested on release, and authoritative update_ground_melee_enemy names state 7 GROUND_ENEMY_STATE_RECOVER_TO_IDLE and executes recovery before returning to idle. --- src/overlays/shared/enemies/ground_melee_enemy.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/ground_melee_enemy.c b/src/overlays/shared/enemies/ground_melee_enemy.c index 27a97ea414..ae02a73274 100644 --- a/src/overlays/shared/enemies/ground_melee_enemy.c +++ b/src/overlays/shared/enemies/ground_melee_enemy.c @@ -160,12 +160,16 @@ extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); int moby_hold_state_if_grabbed(struct Moby *a) __asm__("FUN_L01_002f1c78"); int moby_hold_state_if_grabbed(struct Moby *suction_moby) { + enum { + GROUND_ENEMY_STATE_IDLE = 1, + GROUND_ENEMY_STATE_RECOVER_TO_IDLE = 0x7 + }; int suction_result = process_moby_suck_cannon_suction(suction_moby); if (suction_result == 0) { - if (suction_moby->state == 0x7) - suction_moby->state = 1; + if (suction_moby->state == GROUND_ENEMY_STATE_RECOVER_TO_IDLE) + suction_moby->state = GROUND_ENEMY_STATE_IDLE; } else { - suction_moby->state = 0x7; + suction_moby->state = GROUND_ENEMY_STATE_RECOVER_TO_IDLE; } return suction_result; } From 2e0f4ec605774ca4a35017c6fb6c7eb38ac3c514 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:15:18 +0000 Subject: [PATCH 0348/1502] decomp: clarify names in moby_hold_state_while_active domain_0_value_4 -> STATE_WAIT_TO_RESUME_APPROACH: Source mine.c update_mine defines STATE_WAIT_TO_RESUME_APPROACH=4 on the same moby->state selector and resumes STATE_APPROACH_NEARBY_TARGET when its wait completes. Assigned retail 0x002d61a8 branches on store_moby_in_suck_cannon's result, loads 4 at 0x002d61ac and stores it to the moby state byte +0x20 at 0x002d61c4. The adjacent suction pause handler saves state 3 into command and enters state 4, tying this literal to that established mine wait state, not HeroStateId or voice slots. domain_1_value_4 -> STATE_WAIT_TO_RESUME_APPROACH: Retail 0x002d61b0 loads moby state at +0x20, 0x002d61b4 loads 4 and 0x002d61b8 compares them. On equality 0x002d61c0 loads the saved command byte at +0xBC and 0x002d61c4 restores state. This compares the same temporary mine wait state assigned on cannon success; update_mine already names value 4 STATE_WAIT_TO_RESUME_APPROACH, with resumption to approach state 3. --- src/overlays/l18/mobys/mine.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/mine.c b/src/overlays/l18/mobys/mine.c index f86645256f..168746f7a2 100644 --- a/src/overlays/l18/mobys/mine.c +++ b/src/overlays/l18/mobys/mine.c @@ -404,10 +404,13 @@ extern int store_moby_in_suck_cannon(struct Moby *) __asm__("FUN_L00_002dbb20"); int moby_hold_state_while_active(struct Moby *moby) __asm__("FUN_L18_002d6190"); int moby_hold_state_while_active(struct Moby *moby) { + enum { + STATE_WAIT_TO_RESUME_APPROACH = 4 + }; int active = store_moby_in_suck_cannon(moby); if (active != 0) { - moby->state = 4; - } else if (moby->state == 4) { + moby->state = STATE_WAIT_TO_RESUME_APPROACH; + } else if (moby->state == STATE_WAIT_TO_RESUME_APPROACH) { moby->state = moby->command; } return active; From 5a733a691353cc86164aec5cf484e4a51f17e764 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:15:19 +0000 Subject: [PATCH 0349/1502] decomp: clarify names in update_moby_suck_cannon_state domain_0_value_7 -> GADGEBOT_SUCK_CANNON_SUCTION: Retail 0x002fcbc0 retains the incoming Moby in s0; 0x002fcbd0 loads its byte state at +0x20 and 0x002fcbd4-0x002fcbd8 compares it to 7 after the suction processor returns zero. In the authoritative gadgebot.c, gadgebot_update switches on that same Moby byte at +0x20 and explicitly names 7 GADGEBOT_SUCK_CANNON_SUCTION; that branch processes suction and restores 2 on release. This is the gadgebot state domain, not HeroStateId. domain_1_value_2 -> GADGEBOT_WAIT_TO_APPROACH: Retail 0x002fcbe0 loads 2 and 0x002fcbe4 writes it to the retained Moby's state byte +0x20 only when suction returns zero and its previous state was 7. The authoritative gadgebot_update uses the same state byte and explicitly names 2 GADGEBOT_WAIT_TO_APPROACH; its suction branch likewise restores 2, and its state-2 branch waits on target distance before transitioning to GADGEBOT_APPROACH_TARGET. Thus this is a gadgebot state, not hero run, gravity or vehicle mode. domain_2_value_7 -> GADGEBOT_SUCK_CANNON_SUCTION: Retail 0x002fcbbc calls the checked suction processor; 0x002fcbc4-0x002fcbcc tests its result and loads 7, then 0x002fcbe4 stores 7 in the retained Moby's byte +0x20 for nonzero results. Authoritative gadgebot_update dispatches that same Moby.state byte and explicitly names state 7 GADGEBOT_SUCK_CANNON_SUCTION, whose branch updates suction. Reuse the same domain member for this assignment and the state-7 comparison. --- src/overlays/l18/mobys/gadgebot.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l18/mobys/gadgebot.c b/src/overlays/l18/mobys/gadgebot.c index 7dd611551b..5620790963 100644 --- a/src/overlays/l18/mobys/gadgebot.c +++ b/src/overlays/l18/mobys/gadgebot.c @@ -641,12 +641,16 @@ int update_moby_suck_cannon_state(struct Moby *a) __asm__("FUN_L18_002fcbb0"); /* Method: holds the gadgebot in state 7 while the suck cannon pulls it, and puts it back to state 2 when it lets go. */ int update_moby_suck_cannon_state(struct Moby *moby) { + enum { + GADGEBOT_WAIT_TO_APPROACH = 0x2, + GADGEBOT_SUCK_CANNON_SUCTION = 0x7 + }; int suction_result = process_moby_suck_cannon_suction(moby); if (suction_result == 0) { - if (moby->state == 0x7) - moby->state = 0x2; + if (moby->state == GADGEBOT_SUCK_CANNON_SUCTION) + moby->state = GADGEBOT_WAIT_TO_APPROACH; } else { - moby->state = 0x7; + moby->state = GADGEBOT_SUCK_CANNON_SUCTION; } return suction_result; } From 32447862d90e128a7f93c3610740c41a7a239c98 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:17:23 +0000 Subject: [PATCH 0350/1502] decomp: clarify names in update_moby_suck_cannon_state domain_0_value_9 -> MOBY_STATE_SUCK_CANNON_SUCTION_ACTIVE: The selector is moby->state, proven by lbu v1,0x20(s0) at 0x002d61e0 after incoming moby is saved at 0x002d61d0. Comparison with 9 at 0x002d61e4-0x002d61e8 gates restoration to 1 only after the established process_moby_suck_cannon_suction call returns zero. Conversely its nonzero stage result selects the same 9 store. Checked helper 0x002e6568 uses a separate suction-record state at +0x68, returns nonzero 1/2/3 for suction processing (0x002e6690, 0x002e66b8, 0x002e66c0, 0x002e6760), and zero on rejection at 0x002e676c. Thus 9 is the moby state marking active suction, not a suction-record stage ID. domain_2_value_9 -> MOBY_STATE_SUCK_CANNON_SUCTION_ACTIVE: At 0x002d61cc the wrapper calls established process_moby_suck_cannon_suction (level-02 0x002e6568); 0x002d61d4 preserves its return in a0, and bne at 0x002d61d8 with li v0,9 in its delay slot goes to sb v0,0x20(s0) at 0x002d61f4 for every nonzero result. The original C identifies +0x20 as moby->state. Supplied recovered helper C names aligning, rising, pulled-in and stored suction stages; checked instructions return nonzero stage codes at 0x002e6690/0x002e66b8/0x002e66c0/0x002e6760, and zero at 0x002e676c on rejection. This assignment therefore marks active suck-cannon suction and must reuse the name of the state-9 comparison. --- src/overlays/shared/mobys/suck_cannon_methods.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/mobys/suck_cannon_methods.c b/src/overlays/shared/mobys/suck_cannon_methods.c index 7919007926..e83b3a78f3 100644 --- a/src/overlays/shared/mobys/suck_cannon_methods.c +++ b/src/overlays/shared/mobys/suck_cannon_methods.c @@ -46,12 +46,15 @@ extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); int update_moby_suck_cannon_state(struct Moby *a) __asm__("FUN_L02_002d61c0"); int update_moby_suck_cannon_state(struct Moby *moby) { + enum { + MOBY_STATE_SUCK_CANNON_SUCTION_ACTIVE = 0x9 + }; int suction_result = process_moby_suck_cannon_suction(moby); if (suction_result == 0) { - if (moby->state == 0x9) + if (moby->state == MOBY_STATE_SUCK_CANNON_SUCTION_ACTIVE) moby->state = 1; } else { - moby->state = 0x9; + moby->state = MOBY_STATE_SUCK_CANNON_SUCTION_ACTIVE; } return suction_result; } From 852de9a3226d1dfd7b746c402275dae79be851a4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:17:23 +0000 Subject: [PATCH 0351/1502] decomp: clarify names in moby_update_draw_only domain_0_value_1 -> MOBY_DRAW_ONLY_STATE_ENQUEUE_DRAW_CALLBACK: In the authoritative source (SHA-256 9e28809053d8070a8eaf8ef8935a87203b6c6f43e88fc1c41f50bae3a6e08c34), this assignment and the already named case select the same moby->state field. Retail 0x002e9dfc loads byte +0x20; zero branches to 0x002e9e18, where li v0,1 and sb v0,0x20(a1) at 0x002e9e20 store its next state. The comparison against 1 at 0x002e9e08 branches to 0x002e9e24-0x002e9e2c, which queues draw_level16_reflection_mesh_batch (0x002e9ce0) with moby preserved in a1. Thus the assignment enters the same local state already named MOBY_DRAW_ONLY_STATE_ENQUEUE_DRAW_CALLBACK, rather than an unrelated equal-valued domain. --- src/overlays/shared/mobys/draw_only_moby_update.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/mobys/draw_only_moby_update.c b/src/overlays/shared/mobys/draw_only_moby_update.c index 76d17cc3d5..f267f69693 100644 --- a/src/overlays/shared/mobys/draw_only_moby_update.c +++ b/src/overlays/shared/mobys/draw_only_moby_update.c @@ -15,7 +15,7 @@ void draw_only_moby_update(struct Moby *moby) { }; switch (moby->state) { case MOBY_DRAW_ONLY_STATE_INITIALIZE: - moby->state = 1; + moby->state = MOBY_DRAW_ONLY_STATE_ENQUEUE_DRAW_CALLBACK; break; case MOBY_DRAW_ONLY_STATE_ENQUEUE_DRAW_CALLBACK: add_draw_callback((int)draw_level16_reflection_mesh_batch, (int)moby); From c56b56d8eeaac2820bc53f30cd324d0341b0c274 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:17:23 +0000 Subject: [PATCH 0352/1502] decomp: clarify names in music_primary_replace_callback domain_0_value_0 -> NULL: The source declares short *channel_state = (short *)(int)channel_state_address and guards every dereference with channel_state != 0. Retail 0x00216ad0/0x00216ad4 sign-normalizes a1, and 0x00216ad8 branches to the return at 0x00216b1c when a1 is zero. The original Ghidra decompilation explicitly compares pState against (DialogueChannelState *)0x0 before accessing playback fields. This proves pointer absence and supports existing NULL rather than FALSE. --- .../streaming/music_callbacks/music_primary_replace_callback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/streaming/music_callbacks/music_primary_replace_callback.c b/src/audio/streaming/music_callbacks/music_primary_replace_callback.c index 8cfa95f54d..7da9c8864b 100644 --- a/src/audio/streaming/music_callbacks/music_primary_replace_callback.c +++ b/src/audio/streaming/music_callbacks/music_primary_replace_callback.c @@ -6,7 +6,7 @@ void music_primary_replace_callback(int result, long context) __asm__("FUN_00216 void music_primary_replace_callback(int callback_result, long channel_state_address) { short *channel_state = (short *)(int)channel_state_address; - if (channel_state != 0) { + if (channel_state != NULL) { if (callback_result < 0) { *(int *)channel_state = callback_result; } From dd1566e0074336ca0698dbceddabd184579a882a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:17:23 +0000 Subject: [PATCH 0353/1502] decomp: clarify names in tick_space_transition domain_0_value_0 -> FALSE: The authoritative source tests pal_mode != 0 before substituting old_value + 0xB. Retail 0x00226e3c loads this flag and 0x00226e40 branches to return when zero, skipping the adjusted counter store at 0x00226e4c. Original Ghidra iGpffff8180 != 0 agrees. This proves a boolean false/disabled test, matching existing FALSE=0 rather than a pointer NULL or an inferred state ID. --- src/game/transitions/tick_space_transition.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/transitions/tick_space_transition.c b/src/game/transitions/tick_space_transition.c index bd12328b82..1110cb2d19 100644 --- a/src/game/transitions/tick_space_transition.c +++ b/src/game/transitions/tick_space_transition.c @@ -15,7 +15,7 @@ void tick_space_transition(void) { fifty = 50; new_value = old_value + 1; D_0015EE24 = new_value; - if (((new_value % fifty) == 0) && (pal_mode != 0)) { + if (((new_value % fifty) == 0) && (pal_mode != FALSE)) { D_0015EE24 = old_value + 0xB; } } From 05f0bf44f11f7f2b7201caaf372abfdaf0d4159c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:19:20 +0000 Subject: [PATCH 0354/1502] decomp: clarify names in hero_is_in_special_state domain_0_value_106 -> HERO_STATE_DROWN: Retail 0020d568/0020d56c constructs hero base 0013f350; 0020d584 loads +2084 (001413d4), which the bound source assigns from hero_state->state.current to current_state. The 0x6a equality at 0020d580/0020d588 returns 1. This is the HeroStateId current-state domain, whose shared include/rnc/hero/hero_state.h canonical member HERO_STATE_DROWN is 106, rather than the distinct +208c control-mode selector. domain_1_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: Retail 0020d584 loads hero +2084 into v1, proven by the source current_state = hero_state->state.current and original Ghidra iRam001413d4. Instructions 0020d58c/0020d590 compare this current-state word with 0x82 and branch to return 1. The supplied shared HeroStateId domain canonically defines this state as HERO_STATE_DYING_ZERO_HEALTH = 130; the comparison does not consume control_mode. domain_2_value_118 -> HERO_STATE_HURT_WITH_DISPLACEMENT_VELOCITY: Source current_state receives hero_state->state.current; retail 0020d584 loads the corresponding hero +2084 word, then 0020d594/0020d598 tests it against 0x76 for return 1. This proves the selector is the shared HeroStateId current-state domain, where HERO_STATE_HURT_WITH_DISPLACEMENT_VELOCITY is canonical member 118. The supplied hero_check_damage source also passes 0x76 to hero_set_state before applying knockback to velocity and displacement. domain_3_value_117 -> HERO_STATE_WATER_SURFACE_HURT: Retail 0020d584 loads hero +2084, matching source hero_state->state.current and original Ghidra iRam001413d4. At 0020d59c/0020d5a0, inequality with 0x75 returns 0 while equality falls through to return 1. Therefore this token is in shared HeroStateId, whose canonical member is HERO_STATE_WATER_SURFACE_HURT = 117. Supplied hero_check_damage also requests state 0x75 through hero_set_state for control_mode 0x12 damage. --- src/overlays/shared/hero/hero_switch_item.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 4735b88294..62cc745832 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -456,16 +456,16 @@ s32 hero_is_in_special_state(void) { goto one; } current_state = hero_state->state.current; - if (current_state == 0x6A) { + if (current_state == HERO_STATE_DROWN) { goto one; } - if (current_state == 0x82) { + if (current_state == HERO_STATE_DYING_ZERO_HEALTH) { goto one; } - if (current_state == 0x76) { + if (current_state == HERO_STATE_HURT_WITH_DISPLACEMENT_VELOCITY) { goto one; } - if (current_state != 0x75) { + if (current_state != HERO_STATE_WATER_SURFACE_HURT) { goto zero; } one: From f50ab6dd83092a959e02ec30654e59265603d534 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:19:20 +0000 Subject: [PATCH 0355/1502] decomp: clarify names in hide_teleporter_and_children domain_0_value_0 -> TELEPORTER_VISIBILITY_HIDDEN: Authoritative source binds moby->state to L01Moby byte +0x31. Retail 0x003097f8 is sb zero,0x31(a0), and 0x00309824 clears the same byte in each nullable child from pvars+0x14. The prepared retail decompilation identifies these as visibility clears. The authoritative inverse show_teleporter_and_children writes parent_moby->visible = 1 and child +0x31 = 1 while clearing flags bit 0; hide sets that flag. Thus zero means hidden visibility, not TELEPORTER_INITIALIZE or a Hero enum member. --- src/overlays/shared/props/teleporter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/props/teleporter.c b/src/overlays/shared/props/teleporter.c index 1a05ddd22e..d4424f95b3 100644 --- a/src/overlays/shared/props/teleporter.c +++ b/src/overlays/shared/props/teleporter.c @@ -578,11 +578,14 @@ void draw_moby_radius_ring(char *moby) { void hide_teleporter_and_children(L01Moby *moby) __asm__("FUN_L01_003097e8"); void hide_teleporter_and_children(L01Moby *moby) { + enum { + TELEPORTER_VISIBILITY_HIDDEN = 0 + }; L01Moby **slots = moby->data->slots; int i; moby->field94 = 0; moby->flags |= 1; - moby->state = 0; + moby->state = TELEPORTER_VISIBILITY_HIDDEN; for (i = 2; i >= 0; i--, slots++) { if (*slots != 0) { (*slots)->flags |= 1; From d84a74ae178845f74d4fb2fe4a51e099d8dc39b4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:19:21 +0000 Subject: [PATCH 0356/1502] decomp: clarify names in moby_set_state_from_check domain_0_value_5 -> CHICKEN_STATE_EMIT_FEATHERS: Retail 0x002cadd0 preserves the incoming moby in s0; 0x002cade0 loads its state byte at +0x20 and 0x002cade4/0x002cade8 compare it with 5 after the suction helper returns zero. This is the morphoray_chicken class callback's Moby.state, the same field switched by update_morphoray_chicken, whose existing CHICKEN_STATE_EMIT_FEATHERS=5 branch emits feather mobys while processing the suck-cannon behavior. Reuse that class-local state name, not the separate suction-record +0x68 dispatch or hero domain. domain_1_value_1 -> CHICKEN_STATE_IDLE: Retail 0x002cadf0 loads 1 and 0x002cadf4 stores it into the saved incoming moby's +0x20 state byte only when suction_result is zero and its previous state is 5. The authoritative chicken owner source initializes the spawned class 0x10E moby's same state field to CHICKEN_STATE_IDLE=1 and update_morphoray_chicken dispatches that state into idle animation and proximity-triggered movement. This reset therefore reuses the established chicken idle state rather than any equal-valued hero mode. domain_2_value_5 -> CHICKEN_STATE_EMIT_FEATHERS: Retail 0x002cadd8 branches on the suction helper's nonzero result to 0x002cadf4; its delay slot at 0x002caddc supplies 5, stored into +0x20 of the incoming Moby preserved in s0. This assignment targets exactly the same chicken state field as the 5 comparison at 0x002cade0/0x002cade8. The authoritative update_morphoray_chicken names its state-5 branch CHICKEN_STATE_EMIT_FEATHERS and that branch spawns feather mobys, so both 5 tokens reuse that existing class state name. --- src/overlays/shared/weapons/morphoray_chicken.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/weapons/morphoray_chicken.c b/src/overlays/shared/weapons/morphoray_chicken.c index 475e54887b..8cabf9f513 100644 --- a/src/overlays/shared/weapons/morphoray_chicken.c +++ b/src/overlays/shared/weapons/morphoray_chicken.c @@ -823,12 +823,16 @@ void morphoray_chicken_update(Moby *chicken_moby) { int moby_set_state_from_check(struct Moby *a) __asm__("FUN_L00_002cadc0"); int moby_set_state_from_check(struct Moby *checked_moby) { + enum { + CHICKEN_STATE_IDLE = 1, + CHICKEN_STATE_EMIT_FEATHERS = 5 + }; int suction_result = process_moby_suck_cannon_suction(checked_moby); if (suction_result == 0) { - if (checked_moby->state == 5) - checked_moby->state = 1; + if (checked_moby->state == CHICKEN_STATE_EMIT_FEATHERS) + checked_moby->state = CHICKEN_STATE_IDLE; } else { - checked_moby->state = 5; + checked_moby->state = CHICKEN_STATE_EMIT_FEATHERS; } return suction_result; } From 7ca96c8d3d02fd4de979ee5a05fc459ac2d236c0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:19:21 +0000 Subject: [PATCH 0357/1502] decomp: clarify names in ClearMpegReferenceBuffer domain_0_value_0 -> MPEG_REF_IMAGE_STATUS_CLEARED: ClearMpegReferenceBuffer loads decoder->ref_images[0] at retail 0x0012babc, null-guards the descriptor, then sw zero,0x28(v0) at 0x0012bac4 clears its status word. Source identifies +0x28 as MpegRefImage.status; original Ghidra calls this dwRuntimeStatus and describes clearing it. All six assignments select this same descriptor-status domain, proving the cleared status value without assuming free/invalid semantics. domain_1_value_0 -> MPEG_REF_IMAGE_STATUS_CLEARED: ClearMpegReferenceBuffer loads decoder->ref_images[4] at retail 0x0012bac8, null-guards the descriptor, then sw zero,0x28(v0) at 0x0012bad0 clears its status word. Source identifies +0x28 as MpegRefImage.status; original Ghidra calls this dwRuntimeStatus and describes clearing it. All six assignments select this same descriptor-status domain, proving the cleared status value without assuming free/invalid semantics. domain_2_value_0 -> MPEG_REF_IMAGE_STATUS_CLEARED: ClearMpegReferenceBuffer loads decoder->ref_images[8] at retail 0x0012bad4, null-guards the descriptor, then sw zero,0x28(v0) at 0x0012badc clears its status word. Source identifies +0x28 as MpegRefImage.status; original Ghidra calls this dwRuntimeStatus and describes clearing it. All six assignments select this same descriptor-status domain, proving the cleared status value without assuming free/invalid semantics. domain_3_value_0 -> MPEG_REF_IMAGE_STATUS_CLEARED: ClearMpegReferenceBuffer loads decoder->ref_images[1] at retail 0x0012bae0, null-guards the descriptor, then sw zero,0x28(v0) at 0x0012bae8 clears its status word. Source identifies +0x28 as MpegRefImage.status; original Ghidra calls this dwRuntimeStatus and describes clearing it. All six assignments select this same descriptor-status domain, proving the cleared status value without assuming free/invalid semantics. domain_4_value_0 -> MPEG_REF_IMAGE_STATUS_CLEARED: ClearMpegReferenceBuffer loads decoder->ref_images[5] at retail 0x0012baec, null-guards the descriptor, then sw zero,0x28(v0) at 0x0012baf4 clears its status word. Source identifies +0x28 as MpegRefImage.status; original Ghidra calls this dwRuntimeStatus and describes clearing it. All six assignments select this same descriptor-status domain, proving the cleared status value without assuming free/invalid semantics. domain_5_value_0 -> MPEG_REF_IMAGE_STATUS_CLEARED: ClearMpegReferenceBuffer loads decoder->ref_images[9] at retail 0x0012baf8, null-guards the descriptor, then sw zero,0x28(v0) at 0x0012bb00 clears its status word. Source identifies +0x28 as MpegRefImage.status; original Ghidra calls this dwRuntimeStatus and describes clearing it. All six assignments select this same descriptor-status domain, proving the cleared status value without assuming free/invalid semantics. --- src/sdk/ipu/clear_mpeg_reference_buffer.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/sdk/ipu/clear_mpeg_reference_buffer.c b/src/sdk/ipu/clear_mpeg_reference_buffer.c index b19a90c3f2..cc8875d6eb 100644 --- a/src/sdk/ipu/clear_mpeg_reference_buffer.c +++ b/src/sdk/ipu/clear_mpeg_reference_buffer.c @@ -5,32 +5,35 @@ int ClearMpegReferenceBuffer(struct sceMpeg *mp) __asm__("ClearMpegReferenceBuff /* Zero status of reference images 0, 4, 8, 1, 5, 9. */ int ClearMpegReferenceBuffer(struct sceMpeg *mp) { + enum { + MPEG_REF_IMAGE_STATUS_CLEARED = 0 + }; struct MpegDecoder *decoder = mp->sys; struct MpegRefImage *reference_image; reference_image = decoder->ref_images[0]; if (reference_image != 0) { - reference_image->status = 0; + reference_image->status = MPEG_REF_IMAGE_STATUS_CLEARED; } reference_image = decoder->ref_images[4]; if (reference_image != 0) { - reference_image->status = 0; + reference_image->status = MPEG_REF_IMAGE_STATUS_CLEARED; } reference_image = decoder->ref_images[8]; if (reference_image != 0) { - reference_image->status = 0; + reference_image->status = MPEG_REF_IMAGE_STATUS_CLEARED; } reference_image = decoder->ref_images[1]; if (reference_image != 0) { - reference_image->status = 0; + reference_image->status = MPEG_REF_IMAGE_STATUS_CLEARED; } reference_image = decoder->ref_images[5]; if (reference_image != 0) { - reference_image->status = 0; + reference_image->status = MPEG_REF_IMAGE_STATUS_CLEARED; } reference_image = decoder->ref_images[9]; if (reference_image != 0) { - reference_image->status = 0; + reference_image->status = MPEG_REF_IMAGE_STATUS_CLEARED; } return 1; } From f6e1994cd2dfc68ebf081f40475723c13f1132d2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:19:21 +0000 Subject: [PATCH 0358/1502] decomp: clarify names in audio_dec_start domain_0_value_2 -> AUDIO_DEC_STATE_STARTED: In authoritative src/audio/decoder/audio_dec_start.c (SHA-256 76803fe936faead794551b206144ac22ec53ca17191620b22b6708c1461c3d7d), established audio_dec_start calls snd_start_movie_sound with dec->iopBuff, rounded iopBuffSize, iopZero, rate and channels, then assigns dec->state = 2. Original Ghidra likewise calls start_mpeg_audio_rpc_driver then writes *param_1 = 2. Retail 0x0023acc8 preserves the AudioDec pointer in s0; 0x0023acf0 calls 0x0012f108; 0x0023acf8 loads 2 and 0x0023ad00 stores it at offset 0 of that same AudioDec. This proves the decoder's post-start state, named AUDIO_DEC_STATE_STARTED, rather than a control or request argument. --- src/audio/decoder/audio_dec_start.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/decoder/audio_dec_start.c b/src/audio/decoder/audio_dec_start.c index 923df9c409..49817395c2 100644 --- a/src/audio/decoder/audio_dec_start.c +++ b/src/audio/decoder/audio_dec_start.c @@ -5,6 +5,9 @@ extern s32 snd_start_movie_sound() __asm__("func_0012F108"); void audio_dec_start(struct AudioDec *dec) __asm__("FUN_0023acb8"); void audio_dec_start(struct AudioDec *dec) { + enum { + AUDIO_DEC_STATE_STARTED = 2 + }; s32 buff_size; s32 channel_count; s32 four; @@ -18,7 +21,7 @@ void audio_dec_start(struct AudioDec *dec) { dec->iopZero, dec->hdr.rate, channel_count); - dec->state = 2; + dec->state = AUDIO_DEC_STATE_STARTED; /* Fakematch: GCC removes both stores, but the read-modify-write sequence gives hdr.ch retail's register. */ dec->hdr.ch++; From 572688404968080308b696971b82aaee1b0373d5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:21:24 +0000 Subject: [PATCH 0359/1502] decomp: clarify names in update_level_effects domain_0_value_1 -> DRAW_CALLBACK_ENQUEUE: Retail 00307a8c reads moby->state at +0x20; 00307a98 branches on state 1 to 00307abc-00307ac4, which queues callback 00307a28 with moby retained in a1 by 00307a84. Initialization loads 1 at 00307aa8 and stores it to the same +0x20 selector at 00307ab8. The authoritative source already names that selector's case 1 DRAW_CALLBACK_ENQUEUE and calls add_draw_callback there, so the assignment reuses this existing local enum member. --- src/overlays/l14/mobys/level_effects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/level_effects.c b/src/overlays/l14/mobys/level_effects.c index de374c3dbf..db017d6078 100644 --- a/src/overlays/l14/mobys/level_effects.c +++ b/src/overlays/l14/mobys/level_effects.c @@ -37,7 +37,7 @@ void level_effects_update(struct Moby *moby) { }; switch (moby->state) { case DRAW_CALLBACK_INITIALIZE: - moby->state = 1; + moby->state = DRAW_CALLBACK_ENQUEUE; moby->update_dist = 0xFF; break; case DRAW_CALLBACK_ENQUEUE: From 55357b780c13f8e9745419c400fae65d0e8a5e70 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:21:24 +0000 Subject: [PATCH 0360/1502] decomp: clarify names in cancel_hoven_anklebiter_suck_cannon_suction domain_0_value_9 -> ANKLEBITER_DORMANT: Retail 0x002e1810 loads the same moby state byte at +0x20 retained from the incoming moby at 0x002e1808; 0x002e1814..0x002e1818 compares it with 9 and suppresses the wrapper state write. The authoritative hoven_anklebiter.c update_hoven_anklebiter names this moby->state domain's 9 ANKLEBITER_DORMANT. Initialization selects 9 for data->sleep, disables collision, and chooses animation 12; the dormant branch waits for proximity/group activation before entering 13. Thus this comparison is the anklebiter dormant state, not HERO_STATE_RUN_JUMP. domain_1_value_11 -> ANKLEBITER_WAIT_FOR_LEAP_TRIGGER: Retail 0x002e181c loads 11 and 0x002e1820 compares the moby state byte loaded at 0x002e1810, returning zero without a state write for this value. In authoritative hoven_anklebiter.c, update_hoven_anklebiter declares 11 as ANKLEBITER_WAIT_FOR_LEAP_TRIGGER in its moby->state enum. Its branch faces data->home and waits for target range or proximity == 2 before computing the leap trajectory and setting state 12. The wrapper accesses that anklebiter current-state domain, not the equal-valued hero high-jump domain. domain_2_value_8 -> ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME: Retail 0x002e1824 loads 8 and 0x002e1834 stores it to the incoming moby's state byte at +0x20, after cancel_suck_cannon_suction and unless current state is 9 or 11. The authoritative source names this same anklebiter state value ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME in both store_hoven_anklebiter_in_suck_cannon and update_hoven_anklebiter. The update branch runs func_L00_002DDEA0_2E2EF0(moby, data->fall), then sets state 6 (ANKLEBITER_RETURN_HOME) and clears return_timer and stuck when completed. This proves the existing anklebiter name for this assignment; HERO_STATE_LAND is unrelated. --- src/overlays/l12/mobys/hoven_anklebiter.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/overlays/l12/mobys/hoven_anklebiter.c b/src/overlays/l12/mobys/hoven_anklebiter.c index c8a892c801..e5d42f8148 100644 --- a/src/overlays/l12/mobys/hoven_anklebiter.c +++ b/src/overlays/l12/mobys/hoven_anklebiter.c @@ -71,11 +71,16 @@ int store_hoven_anklebiter_in_suck_cannon(struct Moby *carried_moby) { int cancel_hoven_anklebiter_suck_cannon_suction(struct Moby *moby) __asm__("FUN_L12_002e17f8"); int cancel_hoven_anklebiter_suck_cannon_suction(struct Moby *moby) { + enum { + ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME = 8, + ANKLEBITER_DORMANT = 9, + ANKLEBITER_WAIT_FOR_LEAP_TRIGGER = 11 + }; int was_stored_in_suck_cannon = cancel_suck_cannon_suction(moby); - if (moby->state == 9 || moby->state == 11) { + if (moby->state == ANKLEBITER_DORMANT || moby->state == ANKLEBITER_WAIT_FOR_LEAP_TRIGGER) { return 0; } - moby->state = 8; + moby->state = ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME; return was_stored_in_suck_cannon; } From f1fc7d16a311c78edc42aa430b565bfd19e8eba2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:21:24 +0000 Subject: [PATCH 0361/1502] decomp: clarify names in end_hydrodisplacer_interaction domain_0_value_4 -> HYDRODISPLACER_CAMERA_TRANSITION: Retail 0x002e0344 loads 4, 0x002e034c reads the argument moby's state byte at +0x20, and 0x002e0350 gates cleanup on equality. The authoritative hydrodisplacer_update source passes this same moby to end_hydrodisplacer_interaction, switches on moby->state, and already names state 4 HYDRODISPLACER_CAMERA_TRANSITION. That branch sets camera position/rotation, activates hydrodisplacer_camera_active and interpolates the camera; this helper clears that flag at 0x002e035c and calls jet_end_mount(3) at 0x002e0364. This proves the hydrodisplacer moby-state domain and camera-transition meaning independently of the unrelated hero state value 4. --- src/overlays/shared/props/hydrodisplacer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/props/hydrodisplacer.c b/src/overlays/shared/props/hydrodisplacer.c index 307c26187b..f948809d50 100644 --- a/src/overlays/shared/props/hydrodisplacer.c +++ b/src/overlays/shared/props/hydrodisplacer.c @@ -381,7 +381,10 @@ s32 test_hydrodisplacer_activation_flag(void) { /* Moby state 4: clears two globals, calls 002eac18(3); control mode 0x13: calls 002223f8(0, 1). */ void end_hydrodisplacer_interaction(char *moby) { - if (MOBY(moby)->state == 4) { + enum { + HYDRODISPLACER_CAMERA_TRANSITION = 4 + }; + if (MOBY(moby)->state == HYDRODISPLACER_CAMERA_TRANSITION) { hydrodisplacer_camera_active = 0; *(int *)&D_L00_0015F3FC = 0; jet_end_mount(3); From bfc80ecc1f419d4c26a29ce03741a7d76fee9e51 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:21:24 +0000 Subject: [PATCH 0362/1502] decomp: clarify names in mark_moby_for_removal domain_0_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: In mark_moby_for_removal, source moby->state selects 0xFD only when moby < moby_instance_end. Retail 0x0020c838 performs the unsigned pointer comparison, 0x0020c848 loads 0xFD on the below-boundary branch, and 0x0020c850 stores it to lifecycle byte +0x20. Both branches schedule world_update_time + 2 at +0x38 and update spatial membership, proving this is the below-instance-end removal state. domain_1_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: In mark_moby_for_removal, source moby->state selects 0xFE in the else branch of moby < moby_instance_end. Retail 0x0020c838/0x0020c83c branches on the unsigned comparison being false to 0x0020c84c, which loads 0xFE before the lifecycle-byte store at 0x0020c850. The common delayed lifetime stamp and spatial update prove removal, with only the at-or-above-instance-end partition established. --- src/mobys/mark_moby_for_removal.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mobys/mark_moby_for_removal.c b/src/mobys/mark_moby_for_removal.c index 87b4d16df1..b5099f1d91 100644 --- a/src/mobys/mark_moby_for_removal.c +++ b/src/mobys/mark_moby_for_removal.c @@ -10,10 +10,14 @@ extern void update_moby_grids(struct Moby *, u32) __asm__("func_0020DC20 void mark_moby_for_removal(struct Moby *moby) __asm__("FUN_0020c828"); void mark_moby_for_removal(struct Moby *moby) { + enum { + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE + }; if (moby < moby_instance_end) { - moby->state = 0xFD; + moby->state = MOBY_STATE_REMOVAL_BELOW_INSTANCE_END; } else { - moby->state = 0xFE; + moby->state = MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END; } moby->spawn_frame = world_update_time + 2; update_moby_grids(moby, 0x80807F7F); From 29020e366da3a3ddd1fb786a38e2eaaf07921d7f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:21:24 +0000 Subject: [PATCH 0363/1502] decomp: clarify names in save_card_state_formatting domain_0_value_2 -> MEMCARD_DISPATCH_PENDING_OPERATION: Retail 0x00208b30 forms a1 = 0x0013d290 (&memory_card_state); 0x00208b34 loads offset 0xd4, identified by the authoritative struct access as card_state->state, and 0x00208b2c/0x00208b38 compare it against 2. Original Ghidra names this load g_nMemoryCardOperationState. The supplied memory_card_state.h domain explicitly places MemoryCardState.state/pending_state in MemoryCardOperation, whose canonical value 2 is MEMCARD_DISPATCH_PENDING_OPERATION. This proves domain membership independently of the numeric coincidence with unrelated substep enums. --- src/ui/menus/save_data/save_card_state_formatting.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/menus/save_data/save_card_state_formatting.c b/src/ui/menus/save_data/save_card_state_formatting.c index c0492ac003..2e94b3b4e3 100644 --- a/src/ui/menus/save_data/save_card_state_formatting.c +++ b/src/ui/menus/save_data/save_card_state_formatting.c @@ -7,7 +7,7 @@ void save_card_state_formatting(void) __asm__("FUN_00208b28"); void save_card_state_formatting(void) { struct MemoryCardState *card_state = &memory_card_state; - if (card_state->state == 2 && card_state->pending_state < 0) { + if (card_state->state == MEMCARD_DISPATCH_PENDING_OPERATION && card_state->pending_state < 0) { if (card_state->err != 0) { mode_freeze_state = 0x11; mode_freeze_flags |= 0x40; From bf1d26e77948382aa74330bfaa6600f9abe104f5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:21:24 +0000 Subject: [PATCH 0364/1502] decomp: clarify names in get_hero_easing_moby_by_kind domain_4_value_1 -> HERO_EASE_KIND_SLOT_THREE_SECONDARY_MOBY: Retail caller 0x00205188/0x0020518c loads HeroEase.kind from record+0xa2 into a0; the returned v0 is preserved in s1 and passed as the manipulator moby at 0x0020532c and 0x00205474. Retail 0x0020513c-0x0020514c selects [0x001404D4] for kind 1. The existing source binding hero_slot_three_secondary_moby and supplied copy_hero_color_to_item_mobys establish hero base 0x0013F350, item stride 0x50 and secondary-moby offset 0x1094: 0x0013F350+0x1094+3*0x50=0x001404D4. This identifies an easing target kind, not a hero state or vehicle mode. domain_5_value_5 -> HERO_EASE_KIND_SLOT_ZERO_PRIMARY_MOBY: Retail 0x00205140 loads 5, and 0x00205150 branches on a0==5 to the 0x00205164 load returning [0x001403E0]. Caller 0x0020518c supplies record+0xa2 (HeroEase.kind), then uses the returned moby for manipulator attach/detach at 0x00205474/0x0020532c. In the authoritative source copy_hero_color_to_item_mobys, hero base is 0x0013F350 and primary item mobys occupy hero+i*0x50+0x1090, with secondary at +0x1094. Thus 0x001403E0=0x0013F350+0x1090 is item slot 0's primary moby. The name states the proven easing target role only. --- src/overlays/shared/hero/hero_idle_sequence.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index e1930cec7f..99e14bd28d 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -155,13 +155,17 @@ extern s32 D_001403E0[]; int get_hero_easing_moby_by_kind(int ease_kind) __asm__("FUN_L00_00205110"); int get_hero_easing_moby_by_kind(int ease_kind) { + enum { + HERO_EASE_KIND_SLOT_THREE_SECONDARY_MOBY = 1, + HERO_EASE_KIND_SLOT_ZERO_PRIMARY_MOBY = 5 + }; if (ease_kind == 0 || ease_kind == 2 || ease_kind == 3 || ease_kind == 4) { return D_001413D0[0]; } - if (ease_kind == 1) { + if (ease_kind == HERO_EASE_KIND_SLOT_THREE_SECONDARY_MOBY) { return hero_slot_three_secondary_moby[0]; } - if (ease_kind == 5) { + if (ease_kind == HERO_EASE_KIND_SLOT_ZERO_PRIMARY_MOBY) { return D_001403E0[0]; } return 0; From 58151034e675c077b7df14db30349086305bb49e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:21:24 +0000 Subject: [PATCH 0365/1502] decomp: clarify names in spawn_thruster_pack_flame domain_0_value_0 -> STATE_INITIALIZE: Retail 0x002b4148/414c creates class 0xA7; its nullable return is held in a1 at 0x002b4150, and 0x002b4180 stores zero to that object's state byte at +0x20. The bound source identifies this as spawn_thruster_pack_flame. In the same source, update_thruster_pack_flame casts its object to O_4198 whose state is also +0x20 and switches on that byte with STATE_INITIALIZE = 0. That branch performs one-time f18 += 0.5, u30 = 0xFF and u34 |= 1 setup and advances to state 1 (STATE_WAIT_FOR_BEAM). Thus this assignment selects the existing flame initialization state, rather than any hero enum's zero member. --- src/overlays/shared/weapons/thruster_pack_flame.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/thruster_pack_flame.c b/src/overlays/shared/weapons/thruster_pack_flame.c index 46155c9513..34b07ddb13 100644 --- a/src/overlays/shared/weapons/thruster_pack_flame.c +++ b/src/overlays/shared/weapons/thruster_pack_flame.c @@ -847,6 +847,9 @@ void emit_beam_trail_particles(X *x) { char *spawn_thruster_pack_flame(int instance_index) __asm__("FUN_L00_002b4138"); char *spawn_thruster_pack_flame(int instance_index) { + enum { + STATE_INITIALIZE = 0 + }; char *spawned_moby = create_moby(0xA7); if (spawned_moby != 0) { int *moby_vars = ((int *)MOBY(spawned_moby)->pvars); @@ -857,7 +860,7 @@ char *spawn_thruster_pack_flame(int instance_index) { MOBY(spawned_moby)->update_dist = 0xFF; MOBY(spawned_moby)->draw_dist = 0x7E; MOBY(spawned_moby)->visible = 0; - MOBY(spawned_moby)->state = 0; + MOBY(spawned_moby)->state = STATE_INITIALIZE; } return spawned_moby; } From 1a179bb6eb021d36e807d220277047cbf3e95367 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:21:24 +0000 Subject: [PATCH 0366/1502] decomp: clarify names in get_target_reposition_status domain_0_value_7 -> TARGET_REPOSITION_STATE_REQUESTED: Retail get_target_reposition_status 0x002e0e28 loads the target state byte at +0x20 and 0x002e0e2c..0x002e0e34 accepts states 7/8. Checked caller 0x002e8970 computes the target in s3 from the moby array and passes that identical target to request_target_reposition at 0x002e8a4c..0x002e8a54 and this query at 0x002e8a74..0x002e8a78. The checked request sibling 0x002e0de0 tests +0x20 against 1 at 0x002e0df4..0x002e0df8, then writes 7 to that same target field at 0x002e0e10..0x002e0e14. The authoritative source already names this assigned state TARGET_REPOSITION_STATE_REQUESTED in request_target_reposition; therefore the query comparison belongs to that same target-moby state domain, rather than HeroStateId or voice slots. --- src/overlays/l16/mobys/chicken_relocator.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/chicken_relocator.c b/src/overlays/l16/mobys/chicken_relocator.c index b11d3ddb57..e6358b97b8 100644 --- a/src/overlays/l16/mobys/chicken_relocator.c +++ b/src/overlays/l16/mobys/chicken_relocator.c @@ -171,9 +171,12 @@ void request_target_reposition(struct Moby *moby) { int get_target_reposition_status(char *moby_or_private_data) __asm__("FUN_L16_002e0e28"); int get_target_reposition_status(char *moby_or_private_data) { + enum { + TARGET_REPOSITION_STATE_REQUESTED = 7 + }; unsigned char moby_state = moby_or_private_data[0x20]; moby_or_private_data = *(char **)(moby_or_private_data + 0x78); - if (moby_state == 7 || moby_state == 8) { + if (moby_state == TARGET_REPOSITION_STATE_REQUESTED || moby_state == 8) { if (moby_state == 8 && *(float *)(moby_or_private_data + 0x34) > 0.2f) { return 2; } From 58749b82f023d4e636220e0fb4de3e7e0b58c993 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:23:21 +0000 Subject: [PATCH 0367/1502] decomp: clarify names in music_primary_preseek_callback domain_0_value_1 -> MUSIC_STREAM_STATE_PRESEEK_PENDING: Checked helper 0x00215b68 uses base 0x001516d0; 0x00215bdc stores 1 at base+0x3e, the state halfword at callback record 0x00151704+0xa. At 0x00215c0c it stores pending handle -1, registers callback 0x00216a20 at 0x00215c04 with record address at 0x00215c1c, then queues the request at 0x00215c28. Assigned callback 0x00216a3c-0x00216a44 compares that same state to 1 before accepting the nonzero handle. This proves the pending preseek state in the established music naming domain. domain_1_value_2 -> MUSIC_STREAM_STATE_PRESEEK_HANDLE_RECEIVED: Assigned retail 0x00216a34 branches to retry only for zero handle; delay-slot 0x00216a38 stores the returned handle at record offset 0. With nonzero handle, 0x00216a3c-0x00216a44 requires the state at offset 0xa to equal pending state 1, then 0x00216a4c-0x00216a54 writes 2 to that same field. Helper 0x00215bdc/0x00215c0c initializes this record with state 1 and handle -1 before queueing the callback. State 2 therefore records receipt of the preseek handle; no playback-start claim is needed. --- .../music_callbacks/music_primary_preseek_callback.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/audio/streaming/music_callbacks/music_primary_preseek_callback.c b/src/audio/streaming/music_callbacks/music_primary_preseek_callback.c index d3e1bfa357..3597b30d9d 100644 --- a/src/audio/streaming/music_callbacks/music_primary_preseek_callback.c +++ b/src/audio/streaming/music_callbacks/music_primary_preseek_callback.c @@ -5,13 +5,17 @@ extern void music_preseek_track(s32, s32, s32) __asm__("func_00215B68"); void music_primary_preseek_callback(u32 handle, s64 context) __asm__("FUN_00216a20"); void music_primary_preseek_callback(u32 handle, s64 stream_channel_address) { + enum { + MUSIC_STREAM_STATE_PRESEEK_PENDING = 1, + MUSIC_STREAM_STATE_PRESEEK_HANDLE_RECEIVED = 2 + }; struct MusicStreamChannel *channel = (struct MusicStreamChannel *)(s32)stream_channel_address; if (channel != 0) { channel->handle = handle; if (handle != 0) { - if (channel->state == 1) { - channel->state = 2; + if (channel->state == MUSIC_STREAM_STATE_PRESEEK_PENDING) { + channel->state = MUSIC_STREAM_STATE_PRESEEK_HANDLE_RECEIVED; } } else { music_preseek_track(music_stream_state.primary.track, From dc684bd133edb862452ee4676ff34580ed050867 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:23:21 +0000 Subject: [PATCH 0368/1502] decomp: clarify names in music_secondary_start_callback domain_0_value_1 -> MUSIC_CHANNEL_START_PENDING: Caller 0x00215970 writes 1 to 0x0015172a at 0x00215ab4, stores pending handle -1 at 0x00151720 (0x00215adc), then queues the request at 0x00215af8 with callback 0x002169c0 and callback record 0x00151720. Thus record offset 0xA is start-pending state. The assigned callback loads this exact offset at 0x002169dc and compares it with 1 at 0x002169e0-0x002169e4 only after receiving a nonzero handle. domain_1_value_2 -> MUSIC_CHANNEL_START_ACKNOWLEDGED: At 0x002169d8 the callback stores the returned start handle at record offset 0. The zero-handle branch at 0x002169d4 instead retries through 0x00215970 at 0x00216a08. Only a nonzero handle with the pending state 1 reaches 0x002169ec-0x002169f4, writing 2 to the same record's state at offset 0xA. This proves start acknowledgement, without asserting audible playback. --- .../music_callbacks/music_secondary_start_callback.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/audio/streaming/music_callbacks/music_secondary_start_callback.c b/src/audio/streaming/music_callbacks/music_secondary_start_callback.c index 850dbdc9ad..152bf79269 100644 --- a/src/audio/streaming/music_callbacks/music_secondary_start_callback.c +++ b/src/audio/streaming/music_callbacks/music_secondary_start_callback.c @@ -5,13 +5,17 @@ extern void music_start_track_by_id(s32, s32, s32) __asm__("func_00215970"); void music_secondary_start_callback(u32 handle, s64 context) __asm__("FUN_002169c0"); void music_secondary_start_callback(u32 handle, s64 channel_context) { + enum { + MUSIC_CHANNEL_START_PENDING = 1, + MUSIC_CHANNEL_START_ACKNOWLEDGED = 2 + }; struct MusicStreamChannel *channel = (struct MusicStreamChannel *)(s32)channel_context; if (channel != 0) { channel->handle = handle; if (handle != 0) { - if (channel->state == 1) { - channel->state = 2; + if (channel->state == MUSIC_CHANNEL_START_PENDING) { + channel->state = MUSIC_CHANNEL_START_ACKNOWLEDGED; } } else { music_start_track_by_id(music_stream_state.secondary.track, From 3b6b4198c038bf1fc561b3b9a24944b0494953a8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:23:21 +0000 Subject: [PATCH 0369/1502] decomp: clarify names in moby_park_state_on_find domain_0_value_20 -> PUFFOID_STATE_WAIT_TO_RESUME_COMMAND: Retail 00316230 loads suction_moby state from +0x20 and 00316234 compares it with 20 before saving the prior state at +0xBC (00316244). The authoritative puffoid_update switch on this same Moby state names 20 PUFFOID_STATE_WAIT_TO_RESUME_COMMAND and restores moby->command in that branch; this is the puffoid state domain. domain_1_value_20 -> PUFFOID_STATE_WAIT_TO_RESUME_COMMAND: Retail 0031623c writes 20 to the same suction_moby state byte at +0x20 while 00316244 saves its prior state to command at +0xBC. The authoritative puffoid_update state-20 branch is PUFFOID_STATE_WAIT_TO_RESUME_COMMAND and resumes command, proving reuse of that puffoid state member for this assignment. domain_2_value_20 -> PUFFOID_STATE_WAIT_TO_RESUME_COMMAND: Retail 00316248-00316250 tests the suction_moby state at +0x20 against 20 on zero helper return; 00316258-0031625c then restores command from +0xBC. This is the same state named PUFFOID_STATE_WAIT_TO_RESUME_COMMAND by the authoritative puffoid_update switch, whose state-20 branch also restores moby->command. --- src/overlays/l11/mobys/puffoid.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/l11/mobys/puffoid.c b/src/overlays/l11/mobys/puffoid.c index 574fe6f5be..7582488221 100644 --- a/src/overlays/l11/mobys/puffoid.c +++ b/src/overlays/l11/mobys/puffoid.c @@ -1015,14 +1015,17 @@ extern void *store_moby_in_suck_cannon(void *) __asm__("FUN_L00_002dbb20"); void *moby_park_state_on_find(struct Moby *arg) __asm__("FUN_L11_00316210"); void *moby_park_state_on_find(struct Moby *suction_moby) { + enum { + PUFFOID_STATE_WAIT_TO_RESUME_COMMAND = 0x14 + }; void *found = store_moby_in_suck_cannon(suction_moby); if (found != 0) { unsigned char state = suction_moby->state; - if (state != 0x14) { + if (state != PUFFOID_STATE_WAIT_TO_RESUME_COMMAND) { suction_moby->command = state; - suction_moby->state = 0x14; + suction_moby->state = PUFFOID_STATE_WAIT_TO_RESUME_COMMAND; } - } else if (suction_moby->state == 0x14) { + } else if (suction_moby->state == PUFFOID_STATE_WAIT_TO_RESUME_COMMAND) { suction_moby->state = suction_moby->command; } return found; From f3f6397d71a16a9ad8e810742bba6d832beec905 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:23:22 +0000 Subject: [PATCH 0370/1502] decomp: clarify names in ripple_strips_moby_update domain_0_value_0 -> RIPPLE_STRIPS_STATE_INITIALIZE: The authoritative ripple_strips_moby_update source compares moby->state with 0. Retail 0x002eb0b0 loads byte +0x20 and 0x002eb0b4 branches for nonzero; the zero path at 0x002eb0bc-0x002eb0c8 calls the source-bound set_moby_color with RGB 0x40, then 0x002eb0cc-0x002eb0d4 stores state 1. Thus zero selects ripple-strip initialization. domain_1_value_1 -> RIPPLE_STRIPS_STATE_DRAW_READY: Retail 0x002eb0cc loads 1 and 0x002eb0d4 stores it to the same moby state byte +0x20 after set_moby_color. On the next update, 0x002eb0b0-0x002eb0b4 selects the nonzero path, which at 0x002eb0d8-0x002eb0e0 registers draw_moby_radial_ripple_mesh_buffers with this moby, then clears draw_dist and sets flags bit 0. State 1 therefore marks this ripple moby ready for draw registration. --- src/overlays/shared/props/ripple_strips.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/props/ripple_strips.c b/src/overlays/shared/props/ripple_strips.c index 76a677899e..603dce660f 100644 --- a/src/overlays/shared/props/ripple_strips.c +++ b/src/overlays/shared/props/ripple_strips.c @@ -11,9 +11,13 @@ void ripple_strips_moby_update(struct Moby *moby) __asm__("FUN_L15_002eb0a0"); /* Moby classes 1405-1409, 1426, 1565, 1567 */ void ripple_strips_moby_update(struct Moby *moby) { - if (moby->state == 0) { + enum { + RIPPLE_STRIPS_STATE_INITIALIZE = 0, + RIPPLE_STRIPS_STATE_DRAW_READY = 1 + }; + if (moby->state == RIPPLE_STRIPS_STATE_INITIALIZE) { set_moby_color(moby, 0x40, 0x40, 0x40); - moby->state = 1; + moby->state = RIPPLE_STRIPS_STATE_DRAW_READY; } else { add_draw_callback((void *)draw_moby_radial_ripple_mesh_buffers, moby); moby->draw_dist = 0; From f62cb7321544cd1597cca3c807eed007199b7df9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:25:09 +0000 Subject: [PATCH 0371/1502] decomp: clarify names in activate_waiting_moby_group_members domain_0_value_1 -> MOBY_GROUP_MEMBER_WAITING_FOR_ACTIVATION: Retail 0x002e0138-0x002e0158 selects moby_group_member_lists using input moby group byte +0x21. At 0x002e0168-0x002e017c, each masked 15-bit member index resolves a Moby using the array base and 0x100 stride. The lbu at 0x002e0180 reads listed_entity->state (+0x20); 0x002e0160 and 0x002e0184 compare it with 1, and only that waiting state is changed to 2 at 0x002e0188. This is the established activate_waiting_moby_group_members operation. The supplied screamer_update source independently names its state 1 SCREAMER_STATE_WAIT_FOR_ACTIVATION and transitions it to 2 to begin activation. Use a helper-local group-member waiting name without asserting that every member shares the screamer-specific state-2 lifecycle. --- src/overlays/l10/mobys/screamer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l10/mobys/screamer.c b/src/overlays/l10/mobys/screamer.c index 56d76e1007..39fd5737b9 100644 --- a/src/overlays/l10/mobys/screamer.c +++ b/src/overlays/l10/mobys/screamer.c @@ -488,6 +488,9 @@ void update_screamer_hit_reactions_and_targeting(struct Moby *moby) { extern short *moby_group_member_lists[] __asm__("D_L10_001ABCC0"); void activate_waiting_moby_group_members(struct Moby *moby) { + enum { + MOBY_GROUP_MEMBER_WAITING_FOR_ACTIVATION = 1 + }; short *group_entry; if (moby->group != 0xFF) { group_entry = moby_group_member_lists[moby->group]; @@ -497,7 +500,7 @@ void activate_waiting_moby_group_members(struct Moby *moby) { struct Moby *listed_entity = (struct Moby *)((*(unsigned short *)group_entry & 0x7FFF) * 256 + (int)moby_array_base); - if (listed_entity->state == 1) + if (listed_entity->state == MOBY_GROUP_MEMBER_WAITING_FOR_ACTIVATION) listed_entity->state = 2; } while (*group_entry++ >= 0); } From 12aa49a699ecbc11d54848628d207faa3deb9058 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:25:09 +0000 Subject: [PATCH 0372/1502] decomp: clarify names in hide_moby_and_clear_collision domain_0_value_8 -> GADGEBOT_IDLE: Retail 0x002fcd04 loads 8 and 0x002fcd10-0x002fcd14 stores it to incoming Moby +0x20 (moby->state). Retail 0x002fcd44 clears visible +0x31, 0x002fcd4c clears collision +0x94, and 0x002fcd48-0x002fcd58 sets flag 1 and clears 0x1000. The authoritative gadgebot.c snapshot (SHA-256 32712673e72274a67b1dc956cd691d3d670d069261ad55fbfbee5ab72eb3a696) calls this method a return to idle state 8. Its launch_first_idle_group_class_0772_moby checks oclass 0x772 and state 8, restores collision/flags and sets state 1 (GADGEBOT_LAUNCH_FLIGHT). gadgebot_update initializes to 8 and has active cases 0..7; the damage/glow updater returns immediately for state 8. Together these identify the inactive reusable gadgebot idle state, independently of the unrelated hero state value 8. --- src/overlays/l18/mobys/gadgebot.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l18/mobys/gadgebot.c b/src/overlays/l18/mobys/gadgebot.c index 5620790963..f2d2ca5a97 100644 --- a/src/overlays/l18/mobys/gadgebot.c +++ b/src/overlays/l18/mobys/gadgebot.c @@ -659,8 +659,11 @@ void hide_moby_and_clear_collision(struct Moby *moby) __asm__("FUN_L18_002fcd00" /* Method: sends the gadgebot back to its idle state 8, hidden and without collision. */ void hide_moby_and_clear_collision(struct Moby *moby) { + enum { + GADGEBOT_IDLE = 0x8 + }; unsigned short flags; - moby->state = 0x8; + moby->state = GADGEBOT_IDLE; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } From f1a77b0dce3403906447cc99f61c8ae3dd666eec Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:25:09 +0000 Subject: [PATCH 0373/1502] decomp: clarify names in hide_moby_and_disable_collision domain_0_value_5 -> STATE_INACTIVE: Retail 0x002d6284 loads 5 and 0x002d6294 stores it to the incoming Moby's state byte at +0x20; 0x002d62c4 clears visibility at +0x31 and 0x002d62cc clears collision at +0x94. The authoritative mine.c update_mine uses STATE_INACTIVE = 5 for this same moby->state domain after disabling collision, while launch_class_238_moby_from_list selects class-0x238 instances in state 5 and reactivates them by setting state 1, visibility 1 and restoring collision. Thus the name denotes inactivity rather than a control/request mode. --- src/overlays/l18/mobys/mine.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l18/mobys/mine.c b/src/overlays/l18/mobys/mine.c index 168746f7a2..a7cd93b413 100644 --- a/src/overlays/l18/mobys/mine.c +++ b/src/overlays/l18/mobys/mine.c @@ -421,8 +421,11 @@ int moby_hold_state_while_active(struct Moby *moby) { void hide_moby_and_disable_collision(struct Moby *moby) __asm__("FUN_L18_002d6280"); void hide_moby_and_disable_collision(struct Moby *moby) { + enum { + STATE_INACTIVE = 5 + }; unsigned short flags; - moby->state = 5; + moby->state = STATE_INACTIVE; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } From 187fa5cfc4f52a6ee1447d65115e5ca933206109 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:26:55 +0000 Subject: [PATCH 0374/1502] decomp: clarify names in enable_intc domain_0_value_0 -> EE_INTERRUPT_ENABLE_BIT_CLEAR: Retail 0x001190a4 reads COP0 Status into s0; 0x001190a8/0x001190ac mask it with 0x10000. At 0x001190b0 a zero saved bit skips DIntr at 0x001190b8. Thus source status != 0 tests against the cleared saved interrupt-enable bit. domain_1_value_0 -> EE_INTERRUPT_ENABLE_BIT_CLEAR: Retail s0 retains the Status & 0x10000 mask from 0x001190a4-0x001190ac across _EnableIntc and SYNC. At 0x001190d0 zero skips EnableInterrupts at 0x001190d8. This second status != 0 uses the same cleared saved interrupt-enable bit sentinel. --- src/sdk/kernel/enable_intc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sdk/kernel/enable_intc.c b/src/sdk/kernel/enable_intc.c index c96e8c1d79..ef1e7968ec 100644 --- a/src/sdk/kernel/enable_intc.c +++ b/src/sdk/kernel/enable_intc.c @@ -8,17 +8,20 @@ extern s32 DIntr(); s32 enable_intc(s32 cause_index) __asm__("FUN_00119090"); s32 enable_intc(s32 cause_index) { + enum { + EE_INTERRUPT_ENABLE_BIT_CLEAR = 0 + }; u32 status; s32 intc_enable_result; status = CpuReadStatus(); status &= 0x10000; - if (status != 0) { + if (status != EE_INTERRUPT_ENABLE_BIT_CLEAR) { DIntr(); } intc_enable_result = _EnableIntc(cause_index); CpuSync(); - if (status != 0) { + if (status != EE_INTERRUPT_ENABLE_BIT_CLEAR) { EnableInterrupts(); } return intc_enable_result; From 7bb5d2752d7c6f0d726beb354cc66507c6f9aa4d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:26:56 +0000 Subject: [PATCH 0375/1502] decomp: clarify names in disable_dmac domain_0_value_0 -> EE_INTERRUPT_ENABLE_CLEAR: Source status = CpuReadStatus(); status &= 0x10000 matches retail mfc0 at 0x0011910c and and at 0x00119114. The beq s0,zero at 0x00119118 skips DIntr when saved bit 16 is clear; hence zero denotes EE_INTERRUPT_ENABLE_CLEAR in this masked-status domain. domain_1_value_0 -> EE_INTERRUPT_ENABLE_CLEAR: Retail s0 retains the COP0 Status bit-16 mask computed at 0x0011910c-0x00119114. The second beq s0,zero at 0x00119138 skips EnableInterrupts at 0x00119140 when that saved enable bit was clear. This is the same masked-status domain and zero meaning as the first comparison. --- src/sdk/kernel/disable_dmac.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sdk/kernel/disable_dmac.c b/src/sdk/kernel/disable_dmac.c index e517b4272c..01e0a22b8f 100644 --- a/src/sdk/kernel/disable_dmac.c +++ b/src/sdk/kernel/disable_dmac.c @@ -8,17 +8,20 @@ extern s32 DIntr(); s32 disable_dmac(s32 channel_index) __asm__("FUN_001190f8"); s32 disable_dmac(s32 channel_index) { + enum { + EE_INTERRUPT_ENABLE_CLEAR = 0 + }; u32 status; s32 dmac_disable_result; status = CpuReadStatus(); status &= 0x10000; - if (status != 0) { + if (status != EE_INTERRUPT_ENABLE_CLEAR) { DIntr(); } dmac_disable_result = _DisableDmac(channel_index); CpuSync(); - if (status != 0) { + if (status != EE_INTERRUPT_ENABLE_CLEAR) { EnableInterrupts(); } return dmac_disable_result; From 3c3494bd23422ec9e06c7281ee60cb635e232dca Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:26:56 +0000 Subject: [PATCH 0376/1502] decomp: clarify names in turn_to domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Retail 0x00211e34/0x00211e44 constructs hero at 0x0013f350; 0x00211e4c loads byte +0x20b3 (hero_state->gravity_mode), and 0x00211e50 branches on zero to the direct world-yaw spring at 0x00211e68, using rot.z +0x98 and move_yaw +0x180. Nonzero calls transformed-movement turning at 0x00211e58. The authoritative source's update_hero_ground_contact_and_surface_slopes switches on this same hero.gravity_mode field: HERO_GRAVITY_WORLD_DOWN sets gravity_dir.z=-1.0f, while other members derive gravity from ground normal/reference point. This establishes the exact HeroGravityMode domain, whose shared header member HERO_GRAVITY_WORLD_DOWN equals 0; reuse that canonical member for this comparison. --- src/overlays/shared/hero/hero_switch_item.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 62cc745832..5c0be4af32 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -2995,7 +2995,7 @@ void turn_to(int a, float x, float y, float z) __asm__("FUN_L00_00211e30"); void turn_to(int rotation_direction, float x, float y, float z) { struct Hero *hero_state = &hero; - if (hero_state->gravity_mode != 0) { + if (hero_state->gravity_mode != HERO_GRAVITY_WORLD_DOWN) { turn_hero_toward_transformed_move_direction(rotation_direction, x, y, z); } else { hero_state->motion.yaw_error = spring_angle(&hero_state->motion.rot.f[2], From f0ef5ae8aea3031945f95a87962fac4aff0fe254 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:28:55 +0000 Subject: [PATCH 0377/1502] decomp: clarify names in sceCdSyncS domain_0_value_0 -> CD_SYNC_S_WAIT: In the bound source src/sdk/storage/cdvd/sceCdSyncS.c (SHA-256 8131e7dc43efa0e14d0ed02dceb544a0cddc8164c01c52b51364fd0b7e1d5c93), mode == 0 selects the waiting path. Retail 0x00120cd8 branches to the single-poll path only for nonzero a0. The zero path prints 'S cmd wait\n' at 0x00120cf0 when debugging, checks the S-command RPC client at 0x00132d08 via 0x00120d08, and loops from 0x00120d10 through a 0x3c delay at 0x00120d00 while busy. SceSifCheckStatRpc returns one for a pending packet and zero for idle. Thus zero specifically selects waiting until the S-command client is idle; nonzero callers cd_check_scmd and sceCdDiskReady use one poll to detect busy. --- src/sdk/storage/cdvd/sceCdSyncS.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/storage/cdvd/sceCdSyncS.c b/src/sdk/storage/cdvd/sceCdSyncS.c index b17a75d36d..9b478e9343 100644 --- a/src/sdk/storage/cdvd/sceCdSyncS.c +++ b/src/sdk/storage/cdvd/sceCdSyncS.c @@ -8,7 +8,10 @@ extern u8 cd_s_command_wait_message[] __asm__("D_00152F00"); s32 sceCdSyncS(s32 mode) { - if (mode == 0) { + enum { + CD_SYNC_S_WAIT = 0 + }; + if (mode == CD_SYNC_S_WAIT) { if (cd_debug > 0) { scePrintf(cd_s_command_wait_message); } From ca6c890ed5686989a776c46bc377e97e7b38a073 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:28:55 +0000 Subject: [PATCH 0378/1502] decomp: clarify names in request_thruster_pack_lock_red_wait domain_0_value_2 -> THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER: Retail 0x002d7f78 saves the Moby pointer in s0; 0x002d7f80/84 compares its state byte +0x20 to 2 and 0x002d7f8c stores that same state before 0x002d7f90 writes wait_duration_frames to pvars+0x6c. In the authoritative source thruster_pack_lock_red_update switches on this same moby->state: STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER=2 waits for hero.air_frames.s==0, hero.ground_moby==moby and hero.state.current==0x22, then enters 3 and releases the voice; otherwise it ticks pvars+0x6c. poll_moby_state_and_rearm already names this same lock state THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER. The supplied boss caller passes scale_game_frames(0x708) to this wait request. domain_1_value_2 -> THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER: Retail 0x002d7f78 saves the Moby pointer in s0; 0x002d7f80/84 compares its state byte +0x20 to 2 and 0x002d7f8c stores that same state before 0x002d7f90 writes wait_duration_frames to pvars+0x6c. In the authoritative source thruster_pack_lock_red_update switches on this same moby->state: STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER=2 waits for hero.air_frames.s==0, hero.ground_moby==moby and hero.state.current==0x22, then enters 3 and releases the voice; otherwise it ticks pvars+0x6c. poll_moby_state_and_rearm already names this same lock state THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER. The supplied boss caller passes scale_game_frames(0x708) to this wait request. --- src/overlays/l18/mobys/thruster_pack_lock_red.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/thruster_pack_lock_red.c b/src/overlays/l18/mobys/thruster_pack_lock_red.c index ed0f118148..ec80c94fb4 100644 --- a/src/overlays/l18/mobys/thruster_pack_lock_red.c +++ b/src/overlays/l18/mobys/thruster_pack_lock_red.c @@ -159,9 +159,12 @@ s32 allocate_voice_for_group_entry(s32 group_entry_index, void request_thruster_pack_lock_red_wait(struct Moby *moby, int value) __asm__("FUN_L18_002d7f68"); void request_thruster_pack_lock_red_wait(struct Moby *moby, int wait_duration_frames) { + enum { + THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER = 2 + }; char *red_lock_vars = (char *)moby->pvars; - if (moby->state != 2) { - moby->state = 2; + if (moby->state != THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER) { + moby->state = THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER; *(int *)(red_lock_vars + 0x6C) = wait_duration_frames; } if (!voice_is_playing(moby, *(int *)(red_lock_vars + 0x70))) { From f6e7db1c476e13cb645f5579f7dad7dd8a0a1a83 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:28:55 +0000 Subject: [PATCH 0379/1502] decomp: clarify names in update_cutscene_camera_target domain_0_value_1 -> UPDATE_CUTSCENE_CAMERA_TARGET: Authoritative source src/overlays/l13/mobys/cutscene_camera_target.c (SHA-256 3463ad8a0a84d766987464d9b292ae6fd82777548a6cf1ff9d1c0793ac4fb383) already declares UPDATE_CUTSCENE_CAMERA_TARGET = 1 for switch (moby->state). Retail 0030be18 loads 1 and 0030be1c stores it to the same moby state byte at +0x20 read by 0030bdf8; 0030be00/0030be04 compare that byte with 1 and select the target-helper dispatch branch at 0030be28. Original Ghidra likewise assigns 1 at param_1+0x20 and tests that same field for 1. Thus the initialization assignment enters the already named state and must reuse its existing constant. --- src/overlays/l13/mobys/cutscene_camera_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/cutscene_camera_target.c b/src/overlays/l13/mobys/cutscene_camera_target.c index af99719429..d4e2f47ad2 100644 --- a/src/overlays/l13/mobys/cutscene_camera_target.c +++ b/src/overlays/l13/mobys/cutscene_camera_target.c @@ -26,7 +26,7 @@ void cutscene_camera_target_update(struct Moby *moby) { switch (moby->state) { case INITIALIZE_UPDATE_DISTANCE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = UPDATE_CUTSCENE_CAMERA_TARGET; break; case UPDATE_CUTSCENE_CAMERA_TARGET: if (D_L13_0015F5C4 == 2 && l13_cutscene_target_effect_controller.state == 2) { From 20b2883a20742cec9e54a2281188dbcbd232f2c4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:30:41 +0000 Subject: [PATCH 0380/1502] decomp: clarify names in music_remaining_time_callback domain_0_value_1 -> MUSIC_CROSSFADE_AWAITING_REMAINING_TIME: Authoritative source music_remaining_time_callback tests music_state->crossfade_state != 1 before accepting a nonzero remaining_time. Retail 0x00216be8 loads the signed halfword at music_stream_state+0x20, 0x00216bec requires 1, and 0x00216bf4 rejects zero measurement. Only then does 0x00216c00 advance the same phase to 2 and initialize timing. Thus phase 1 is awaiting the eligible remaining-time callback result, not Boolean TRUE. domain_1_value_2 -> MUSIC_CROSSFADE_TIMING_INITIALIZED: In the authoritative source, crossfade_state = 2 accompanies crossfade_remaining_time = channel->remaining_time and crossfade_interval = channel->remaining_time / 4. Retail 0x00216bf8 loads 2, 0x00216c00 stores it to music_stream_state+0x20, 0x00216c08 copies channel+0x18 into global+0x24, and 0x00216c10-0x00216c20 compute the signed quarter and store global+0x28. This establishes the timing-initialized phase on callback completion. --- .../music_callbacks/music_remaining_time_callback.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/audio/streaming/music_callbacks/music_remaining_time_callback.c b/src/audio/streaming/music_callbacks/music_remaining_time_callback.c index dca2f8c472..8191e0c675 100644 --- a/src/audio/streaming/music_callbacks/music_remaining_time_callback.c +++ b/src/audio/streaming/music_callbacks/music_remaining_time_callback.c @@ -8,6 +8,10 @@ void music_remaining_time_callback(int remaining_time, long context) __asm__("FU enabled on the channel and crossfade_state 1, moves crossfade_state to 2 and copies the time (and a quarter of it) into the crossfade fields. */ void music_remaining_time_callback(int remaining_time, long channel_context) { + enum { + MUSIC_CROSSFADE_AWAITING_REMAINING_TIME = 1, + MUSIC_CROSSFADE_TIMING_INITIALIZED = 2 + }; struct MusicStreamChannel *channel = (struct MusicStreamChannel *)(int)channel_context; struct MusicStreamState *music_state; if (channel == 0) { @@ -18,13 +22,13 @@ void music_remaining_time_callback(int remaining_time, long channel_context) { return; } music_state = &music_stream_state; - if (music_state->crossfade_state != 1) { + if (music_state->crossfade_state != MUSIC_CROSSFADE_AWAITING_REMAINING_TIME) { return; } if (remaining_time == 0) { return; } - music_state->crossfade_state = 2; + music_state->crossfade_state = MUSIC_CROSSFADE_TIMING_INITIALIZED; music_state->crossfade_remaining_time = channel->remaining_time; music_state->crossfade_interval = channel->remaining_time / 4; } From 786b373fd80afc244d3b197310fb9114b5745dfe Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:30:41 +0000 Subject: [PATCH 0381/1502] decomp: clarify names in UpdateTempTrackData domain_0_value_3 -> MPEG_PICTURE_CODING_TYPE_B: PictureHeader reads the 10-bit temporal_reference then stores the next 3-bit picture coding type at decoder offset +0x150; its additional forward-vector fields for types 2/3 and backward-vector fields for type 3 identify the MPEG B-picture coding type. Retail UpdateTempTrackData 0x00129090 loads +0x150, 0x00129094 loads 3, and 0x00129098 branches to 0x001290c0, bypassing the first-picture marker update for B pictures. The supplied original Ghidra decompilation and plate explicitly describe the complementary path as non-B. This proves the selector domain and B-picture meaning rather than relying on numeric equality alone. --- src/sdk/mpeg/picture/update_temp_track_data.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/mpeg/picture/update_temp_track_data.c b/src/sdk/mpeg/picture/update_temp_track_data.c index 4b17aa7088..e47a325fa1 100644 --- a/src/sdk/mpeg/picture/update_temp_track_data.c +++ b/src/sdk/mpeg/picture/update_temp_track_data.c @@ -2,13 +2,16 @@ #include "rnc/sdk/libmpeg.h" void UpdateTempTrackData(struct MpegDecoder *decoder, s32 delta) { + enum { + MPEG_PICTURE_CODING_TYPE_B = 3 + }; s32 reference; s32 current; s32 step; s32 wrapped; wrapped = 0; step = 0; - if ((decoder->picture_coding_type != 3) && (delta != 0)) { + if ((decoder->picture_coding_type != MPEG_PICTURE_CODING_TYPE_B) && (delta != 0)) { if (delta < 0) { wrapped = decoder->unk854 == 0; } From e28e6104e9e984c66e969314dd8cf93864f7ca52 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:30:42 +0000 Subject: [PATCH 0382/1502] decomp: clarify names in force_help_message domain_0_value_0 -> HELP_MESSAGE_REQUEST_REJECTED: Retail jal 0x00215130 at 0x002151ec returns the s32 help_message_status; bne v0,zero at 0x002151f4 preserves nonzero outcomes and enters forced replacement only on zero. Supplied try_set_help_message returns 0 precisely when D_0015F5D4 is nonzero and differs from help_message_selector, without updating message state. Thus this comparison tests a rejected normal help-message request, not a boolean or pointer. domain_1_value_3 -> HELP_MESSAGE_REQUEST_FORCED: Original Ghidra assigns lVar2=3 only after the zero-result branch of FUN_00215130. Retail stores the requested selector s1 to D_0015F5D4 at 0x0021521c, writes 2 to D_0015F5D0 at 0x00215224, and stores message_id s0 to D_00161288 at 0x0021522c before li v0,3 at 0x00215230. This return status reports the forced replacement performed by force_help_message after the normal request was rejected. --- src/ui/help/force_help_message.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ui/help/force_help_message.c b/src/ui/help/force_help_message.c index cece000399..fa6d354934 100644 --- a/src/ui/help/force_help_message.c +++ b/src/ui/help/force_help_message.c @@ -8,17 +8,21 @@ extern s32 try_set_help_message() __asm__("FUN_00215130"); s32 force_help_message(s32 owner, s32 message_id) __asm__("FUN_002151d8"); s32 force_help_message(s32 help_message_selector, s32 message_id) { + enum { + HELP_MESSAGE_REQUEST_REJECTED = 0, + HELP_MESSAGE_REQUEST_FORCED = 3 + }; s32 help_message_status; help_message_status = try_set_help_message(); - if (help_message_status == 0) { + if (help_message_status == HELP_MESSAGE_REQUEST_REJECTED) { if (message_id != 0) { copy_text_to_shared_buffer(get_help_message_text(message_id)); } D_0015F5D4 = help_message_selector; D_0015F5D0 = 2; D_00161288 = message_id; - help_message_status = 3; + help_message_status = HELP_MESSAGE_REQUEST_FORCED; } return help_message_status; } From b466a4204edf1f09e3fb7cd9a5f31a2eaf98c201 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:32:24 +0000 Subject: [PATCH 0383/1502] decomp: clarify names in ocean_aridia_update domain_0_value_1 -> OCEAN_ARIDIA_REGISTER_DRAW_CALLBACK: In the authoritative ocean_aridia_update snapshot (SHA-256 0e6058586bc1ec02a03bd5155875b98016625768f6250711bfba637411f94a4d), the assignment moby->state = 1 targets the exact selector of the existing OCEAN_ARIDIA_REGISTER_DRAW_CALLBACK = 1 case. Retail 0x002ea1a8 reads state at +0x20; 0x002ea1b4 branches on 1 to 0x002ea1ec, which passes draw_aridia_ocean_parts (0x002ea048) and the same moby to the source-established add_draw_callback operation. Initialization loads 1 at 0x002ea1d8 and stores it to that same +0x20 at 0x002ea1e8. This proves reuse of the local state-domain member rather than numeric equivalence alone. --- src/overlays/l02/mobys/ocean_aridia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l02/mobys/ocean_aridia.c b/src/overlays/l02/mobys/ocean_aridia.c index 9a7da82974..ef13c557a2 100644 --- a/src/overlays/l02/mobys/ocean_aridia.c +++ b/src/overlays/l02/mobys/ocean_aridia.c @@ -132,7 +132,7 @@ void ocean_aridia_update(struct Moby *moby) { switch (moby->state) { case OCEAN_ARIDIA_INITIALIZE: prepare_scaled_table_on_stack(0.16666667f); - moby->state = 1; + moby->state = OCEAN_ARIDIA_REGISTER_DRAW_CALLBACK; moby->update_dist = 0xFF; break; case OCEAN_ARIDIA_REGISTER_DRAW_CALLBACK: From bc3fb7a02b898e2fcc03a1f7fb7ecb074e10579a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:32:25 +0000 Subject: [PATCH 0384/1502] decomp: clarify names in PowerOffCB domain_0_value_0 -> FALSE: DIntr at 0x0011d660 reads COP0 Status, masks bit 16 at 0x0011d668, and normalizes the original bit with sltu a0,zero,v1 at 0x0011d670. Its return paths at 0x0011d698 and 0x0011d6a4 return that Boolean (zero when previously disabled). PowerOffCB saves this return in s0 at 0x001209cc and tests s0 against zero at 0x001209e0, skipping EnableInterrupts at 0x001209e8 when false. Thus existing FALSE, rather than pointer NULL, belongs to this Boolean comparison domain. --- src/sdk/storage/cdvd/PowerOffCB.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdk/storage/cdvd/PowerOffCB.c b/src/sdk/storage/cdvd/PowerOffCB.c index 00abc2a214..0b4522a340 100644 --- a/src/sdk/storage/cdvd/PowerOffCB.c +++ b/src/sdk/storage/cdvd/PowerOffCB.c @@ -13,7 +13,7 @@ s32 PowerOffCB(void) { D_001312E4[0] = 1; interrupt_state = DIntr(); sceSifAddCmdHandler(0x80000012, D_00120960, 0); - if (interrupt_state != 0) { + if (interrupt_state != FALSE) { EnableInterrupts(); } D_001312E4[0] = 0; From 8182745575b4ec7e73e56bd2e4df704f82ceffe8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:34:13 +0000 Subject: [PATCH 0385/1502] decomp: clarify names in save_card_state_creating_save domain_0_value_2 -> MEMCARD_DISPATCH_PENDING_OPERATION: Retail 0x00208d60/0x00208d68 forms memory_card_state at 0x0013d290; 0x00208d6c loads +0xd4 (card_state->state) and 0x00208d64/0x00208d70 compares it with 2. Original Ghidra names this storage g_nMemoryCardOperationState. The authoritative source binds card_state to struct MemoryCardState, and the supplied memory_card_state.h domain context explicitly assigns state/pending_state to MemoryCardOperation, whose canonical member at 2 is MEMCARD_DISPATCH_PENDING_OPERATION, rather than any per-operation substep. domain_3_value_7 -> MEMCARD_REQUEST_CHDIR: Retail 0x00208d78 loads memory_card_state+0xdc and 0x00208d7c requires the signed pending operation to be negative; on the error-free branch, 0x00208d8c loads 7 and 0x00208db4 stores it back to +0xdc. Original Ghidra identifies that storage as g_nPendingMemoryCardOperationState; authoritative C identifies it as card_state->pending_state. The supplied MemoryCardOperation declaration context explicitly owns pending_state and names operation 7 MEMCARD_REQUEST_CHDIR. This queues that canonical operation, not create/read/update substep 7. --- src/ui/menus/save_data/save_card_state_creating_save.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/menus/save_data/save_card_state_creating_save.c b/src/ui/menus/save_data/save_card_state_creating_save.c index 23a7b14119..9d7b0b4138 100644 --- a/src/ui/menus/save_data/save_card_state_creating_save.c +++ b/src/ui/menus/save_data/save_card_state_creating_save.c @@ -7,13 +7,13 @@ void save_card_state_creating_save(void) __asm__("FUN_00208d60"); void save_card_state_creating_save(void) { struct MemoryCardState *card_state = &memory_card_state; - if (card_state->state == 2 && card_state->pending_state < 0) { + if (card_state->state == MEMCARD_DISPATCH_PENDING_OPERATION && card_state->pending_state < 0) { if (card_state->err != 0) { mode_freeze_state = 0x12; mode_freeze_flags |= 0x40; return; } - card_state->pending_state = 7; + card_state->pending_state = MEMCARD_REQUEST_CHDIR; card_state->active_card = 0; card_state->card[0].save_index = 0; card_state->pending_card = 0; From 4713974935df7ec81d6315b28230daa1ab0ac049 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:34:13 +0000 Subject: [PATCH 0386/1502] decomp: clarify names in save_card_state_saving domain_0_value_3 -> MEMCARD_REQUEST_FORMAT: Retail 0x00208f38 loads memory_card_state+0xd4, identified as g_nMemoryCardOperationState in the original Ghidra decompilation; 0x00208f3c compares it with 3. The authoritative C identifies this field as memory_card_state.state, and the supplied memory_card_state.h declaration explicitly assigns state/pending_state to MemoryCardOperation, whose canonical value 3 is MEMCARD_REQUEST_FORMAT. Reuse that member for this less-than boundary. domain_1_value_0 -> MEMCARD_QUERY_INFO: Retail 0x00208f48 loads memory_card_state+0xdc, identified as g_nPendingMemoryCardOperationState by original Ghidra; 0x00208f4c exits on nonnegative values, implementing pending_state < 0. The supplied header explicitly places pending_state in MemoryCardOperation with canonical zero member MEMCARD_QUERY_INFO. Reuse that zero-valued operation-domain boundary without asserting a meaning for the negative sentinel. --- src/ui/menus/save_data/save_card_state_saving.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/menus/save_data/save_card_state_saving.c b/src/ui/menus/save_data/save_card_state_saving.c index 9136eb5984..5488bb7931 100644 --- a/src/ui/menus/save_data/save_card_state_saving.c +++ b/src/ui/menus/save_data/save_card_state_saving.c @@ -16,7 +16,7 @@ void save_card_state_saving(void) __asm__("FUN_00208f28"); void save_card_state_saving(void) { s32 flags; - if ((memory_card_state.state < 3) && (memory_card_state.pending_state < 0)) { + if ((memory_card_state.state < MEMCARD_REQUEST_FORMAT) && (memory_card_state.pending_state < MEMCARD_QUERY_INFO)) { if (memory_card_state.err != 0) { mode_freeze_init(3, 0); mode_freeze_state = 0x15; From 30fb31b74de3e82eb25c661925e7e283fc76689b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:34:14 +0000 Subject: [PATCH 0387/1502] decomp: clarify names in process_amoeboid_suck_cannon_suction domain_0_value_8 -> LARGE_AMOEBOID_PROCESS_KNOCKBACK: Retail 0x002efab4 loads the current moby state byte from 0x20(s0); 0x002efab8-0x002efac8 compare it to 8 and reject suction while in that state. The same source large_amoeboid_update switches on moby[0x20], names case 8 LARGE_AMOEBOID_PROCESS_KNOCKBACK, and steps knockback motion via step_moby_motion(moby, large_amoeboid_vars + 0x60). Hit processing also initializes trooper knockback and assigns spawned[0x20] = 8. Thus this is that current-state member, not suction-record state 8. domain_1_value_14 -> LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION: Retail 0x002efa94 calls the established suction helper; after a nonzero result, class 0x362 and exclusion of current state 8, 0x002efac0 loads 14 and 0x002efae0 stores it into the same moby state byte at 0x20(s0). large_amoeboid_update switches on that byte and already names case 14 LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION, whose branch invokes FUN_L00_002dc9f0 on this moby. The adjacent store/cancel suction wrappers use this same named current-state member. domain_2_value_14 -> LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION: On the zero suction-helper result path, retail 0x002efacc loads 0x20(s0), 0x002efad0 loads 14, and 0x002efad4 compares them before restoring state 1. This reads the identical current-state byte written to 14 at 0x002efae0 on accepted suction. The supplied large_amoeboid_update case and adjacent moby_hold_state_if_found wrapper name that same moby state LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION; comparison and assignment therefore reuse the same member. domain_3_value_1 -> LARGE_AMOEBOID_TRY_ACQUIRE_TARGET_PATH: Retail 0x002efadc loads 1 and 0x002efae0 stores it to moby current state 0x20(s0), only when the suction helper returns zero and that state was 14. The supplied large_amoeboid_update switch on moby[0x20] already names case 1 LARGE_AMOEBOID_TRY_ACQUIRE_TARGET_PATH and calls follow_path toward the stored target before choosing movement/path states. The adjacent moby_hold_state_if_found wrapper uses precisely this named state for the equivalent return from Suck Cannon interaction; TRUE is not this domain. --- src/overlays/shared/enemies/large_amoeboid.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/enemies/large_amoeboid.c b/src/overlays/shared/enemies/large_amoeboid.c index 939f7024ec..61ae1b86b5 100644 --- a/src/overlays/shared/enemies/large_amoeboid.c +++ b/src/overlays/shared/enemies/large_amoeboid.c @@ -1085,17 +1085,22 @@ void spawn_amoeboid_burst_sparks(unsigned char *moby, f32 *mode) { int process_amoeboid_suck_cannon_suction(struct Moby *moby) __asm__("FUN_L01_002efa88"); int process_amoeboid_suck_cannon_suction(struct Moby *moby) { + enum { + LARGE_AMOEBOID_TRY_ACQUIRE_TARGET_PATH = 1, + LARGE_AMOEBOID_PROCESS_KNOCKBACK = 8, + LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION = 0xE + }; int suction_result = process_moby_suck_cannon_suction(moby); if (suction_result != 0) { if (moby->oclass != 0x362) { return 0; - } else if (moby->state == 8) { + } else if (moby->state == LARGE_AMOEBOID_PROCESS_KNOCKBACK) { return 0; } else { - moby->state = 0xE; + moby->state = LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION; } - } else if (moby->state == 0xE) { - moby->state = 1; + } else if (moby->state == LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION) { + moby->state = LARGE_AMOEBOID_TRY_ACQUIRE_TARGET_PATH; } return suction_result; } From aa4fce79f07c21429e78eb10406708378d1b9205 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:36:20 +0000 Subject: [PATCH 0388/1502] decomp: clarify names in update_blarg_turret_target_and_state domain_0_value_3 -> BLARG_TURRET_STATE_TRACK_TARGET: Retail 0x002b48e8 preserves the input moby in s0; 0x002b48f0 loads its state byte at +0x20 and 0x002b48dc/0x002b48fc compare it to 3. Equality selects 22.0 at 0x002b4904-0x002b4908 instead of 20.0 before target selection at 0x002b4910. The supplied blarg_turret_update passes turret_moby to this exact helper before switching on that same turret's state. Its existing BLARG_TURRET_STATE_TRACK_TARGET=3 branch aims at target_moby, fires the turret, and exits to WAIT_FOR_TARGET beyond 22.0; WAIT_FOR_TARGET enters state 3 within 20.0. Thus the comparison belongs to the established turret tracking state, not the unrelated HERO_STATE_STOP=3. --- src/overlays/l13/mobys/blarg_turret.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/blarg_turret.c b/src/overlays/l13/mobys/blarg_turret.c index f43486cd17..f1adafa321 100644 --- a/src/overlays/l13/mobys/blarg_turret.c +++ b/src/overlays/l13/mobys/blarg_turret.c @@ -300,9 +300,12 @@ extern int select_moby_combat_target(void *, void *, float) __asm__("FUN_L00_002 void update_blarg_turret_target_and_state(struct Moby *moby) __asm__("FUN_L13_002b48d8"); void update_blarg_turret_target_and_state(struct Moby *moby) { + enum { + BLARG_TURRET_STATE_TRACK_TARGET = 3 + }; char *turret_vars = (char *)moby->pvars; float distance; - if (moby->state == 3) + if (moby->state == BLARG_TURRET_STATE_TRACK_TARGET) distance = 22.0f; else distance = 20.0f; From 9bd602855729d71997d97e2fa41fb215c476be2f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:36:20 +0000 Subject: [PATCH 0389/1502] decomp: clarify names in read_disc_sectors_and_wait domain_0_value_0 -> CD_READ_STATE_IDLE: In the authoritative source, start_audio_stream_read accepts a new request only when music_stream_state.read_state == 0 and sets that same field to 1 after snd_stream_safe_cd_read succeeds. Retail 0x0021684c loads the signed halfword at 0x001516d8 and 0x00216850 exits when it is zero. Thus the initial != 0 comparison means a CD read is not idle; zero names the idle request state, not a generic boolean or pointer. domain_1_value_0 -> CD_READ_STATE_IDLE: Retail 0x00216880 reloads the signed halfword at offset 8 of the saved music_stream_state address and 0x00216884 repeats the service loop while nonzero. The original Ghidra decompilation likewise waits while g_cdReadState.nActive != 0. The supplied starter permits a new CD read only at read_state == 0 and sets read_state = 1 upon acceptance, proving the terminating zero is the same CD_READ_STATE_IDLE domain member as the initial guard. --- src/audio/streaming/read_disc_sectors_and_wait.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/audio/streaming/read_disc_sectors_and_wait.c b/src/audio/streaming/read_disc_sectors_and_wait.c index 86d4494379..eb5cb96ceb 100644 --- a/src/audio/streaming/read_disc_sectors_and_wait.c +++ b/src/audio/streaming/read_disc_sectors_and_wait.c @@ -12,16 +12,19 @@ extern s32 start_audio_stream_read(s32 dst, s32 sector, s32 sector_count) __asm_ s32 read_disc_sectors_and_wait(s32 dst, s32 sector, s32 sector_count) __asm__("FUN_00216828"); s32 read_disc_sectors_and_wait(s32 cd_read_destination, s32 sector, s32 sector_count) { + enum { + CD_READ_STATE_IDLE = 0 + }; s32 read_byte_count = start_audio_stream_read(cd_read_destination, sector, sector_count); - if (read_byte_count != 0 && music_stream_state.read_state != 0) { + if (read_byte_count != 0 && music_stream_state.read_state != CD_READ_STATE_IDLE) { do { sceGsSyncV(0); music_update(); snd_reset_state_and_flush_commands(); snd_flush_sound_commands(); snd_hold_command_batches(); - } while (music_stream_state.read_state != 0); + } while (music_stream_state.read_state != CD_READ_STATE_IDLE); } return read_byte_count; } From 85a39e9ac102702765f630fda04d4ab4762dec75 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:36:20 +0000 Subject: [PATCH 0390/1502] decomp: clarify names in try_activate_pokitaru_gate domain_0_value_1 -> POKITARU_GATE_READY_FOR_ACTIVATION: Authoritative resort_owner.c SHA-256 071ef9fdc294a3ec0ca9b20885647b50d62fe9fa3d0e131f397561336ee5abd4: update_resort_owner_state_actions selects gates at pvars+0xF0 and passes gate_moby to try_activate_pokitaru_gate. Retail 0x0030a484 loads 1; 0x0030a490 reads argument Moby.state at +0x20; 0x0030a494 rejects other states. The original decompilation confirms the same guard. Retail 0x0030a4a4-0x0030a4b4 then requires hero.ground_moby == argument and zero hero.air_frames.s. At 0x0030a4c8 it changes that gate's state to 2, optionally blends animation 0, and returns success at 0x0030a4e8. Thus 1 identifies the gate state ready for this activation, not any equal-valued HeroStateId, vehicle mode, path leg, or resort-owner state. --- src/overlays/l11/mobys/resort_owner.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/resort_owner.c b/src/overlays/l11/mobys/resort_owner.c index 8300dc5c2e..9c4020e54c 100644 --- a/src/overlays/l11/mobys/resort_owner.c +++ b/src/overlays/l11/mobys/resort_owner.c @@ -893,8 +893,11 @@ void update_resort_owner_look_tracking(WatcherMoby *moby) { /* Ported from rac1-decomp (src/overlays/l11_pokitaru/vendor_002CC828.c: func_L11_0030B850), where it is exact; names translated to the US level program. */ int try_activate_pokitaru_gate(struct Moby *moby) { + enum { + POKITARU_GATE_READY_FOR_ACTIVATION = 1 + }; char *current; - if (moby->state != 1) + if (moby->state != POKITARU_GATE_READY_FOR_ACTIVATION) return 0; current = (char *)hero.ground_moby; if (current != (char *)moby || hero.air_frames.s) From d230bac11af43e659c40e02ddb779d6f831fe5ec Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:36:20 +0000 Subject: [PATCH 0391/1502] decomp: clarify names in update_audio_stream_callback_keeper domain_0_value_1 -> MOBY_STATE_REGISTER_DRAW_CALLBACK: The authoritative source switches on moby->state and already names its value-1 case MOBY_STATE_REGISTER_DRAW_CALLBACK, whose body calls add_draw_callback(register_audio_stream_callback, moby). Retail 0x00303380 reads the state byte at s0+0x20, 0x00303388-0x0030338c compares it with 1 and branches to 0x003033cc-0x003033d8 to enqueue callback 0x00303350 with the same moby. Initialization loads 1 at 0x003033b8 and stores it to that identical state byte at 0x003033c8. Thus the assigned literal denotes the already named callback-registration state, not a separate control domain. --- src/overlays/l14/mobys/audio_stream_callback_keeper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/audio_stream_callback_keeper.c b/src/overlays/l14/mobys/audio_stream_callback_keeper.c index ffea530c82..ba4fa4b220 100644 --- a/src/overlays/l14/mobys/audio_stream_callback_keeper.c +++ b/src/overlays/l14/mobys/audio_stream_callback_keeper.c @@ -24,7 +24,7 @@ void audio_stream_callback_keeper_update(struct Moby *moby) { case MOBY_STATE_INITIALIZE: prepare_scaled_float_table_with_target_byte( l14_scaled_table_setup_target, 0x40, 0.6666667f); - moby->state = 1; + moby->state = MOBY_STATE_REGISTER_DRAW_CALLBACK; moby->update_dist = 0xFF; break; case MOBY_STATE_REGISTER_DRAW_CALLBACK: From c34b1c18517ee281dc21c143d8ffcefa10c89ff4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:38:15 +0000 Subject: [PATCH 0392/1502] decomp: clarify names in handle_sand_shark_suck_cannon_storage domain_0_value_9 -> SAND_SHARK_SUCK_CANNON_INTERACTION: Retail 0x002d6220 preserves the sand-shark moby argument in s0; after store_moby_in_suck_cannon returns nonzero (0x002d621c-0x002d6228), 0x002d6234 stores 9 to its byte +0x20, the source moby->state. The authoritative same-class sand_shark_update switches on that field and already names 9 SAND_SHARK_SUCK_CANNON_INTERACTION, whose branch invokes the cannon interaction helper before returning to state 1. This is the sand-shark state domain, not HeroStateId. domain_1_value_9 -> SAND_SHARK_SUCK_CANNON_INTERACTION: Retail 0x002d6260 reads byte +0x20 of the original sand-shark moby, and 0x002d6264-0x002d6268 compares it with 9 when the storage helper returns zero. It is exactly the state assigned at 0x002d6234 and the moby->state selector in sand_shark_update, whose existing same-domain member SAND_SHARK_SUCK_CANNON_INTERACTION equals 9. Both assignment and comparison must use this same member. domain_2_value_1 -> SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET: Retail 0x002d6270-0x002d6274 writes 1 to the original sand-shark moby's state byte +0x20 only when the failed storage call finds state 9. In the authoritative sand_shark_update, this same moby->state selector already names 1 SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET; that branch enters state 18, whose ground-alignment branch then enters state 23 and returns toward the stored home with height offset. The state-9 update branch likewise returns this field to 1. Thus the existing sand-shark member identifies the destination state independently of unrelated hero constants. --- src/overlays/l02/mobys/sand_shark.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l02/mobys/sand_shark.c b/src/overlays/l02/mobys/sand_shark.c index 919cdf5c6c..ca0411290c 100644 --- a/src/overlays/l02/mobys/sand_shark.c +++ b/src/overlays/l02/mobys/sand_shark.c @@ -1352,18 +1352,22 @@ extern void *store_moby_in_suck_cannon(void *) __asm__("FUN_L00_002dbb20"); void *handle_sand_shark_suck_cannon_storage(struct Moby *moby) __asm__("FUN_L02_002d6210"); void *handle_sand_shark_suck_cannon_storage(struct Moby *moby) { + enum { + SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET = 1, + SAND_SHARK_SUCK_CANNON_INTERACTION = 9 + }; void *helper_result = store_moby_in_suck_cannon(moby); if (helper_result) { int spawner_moby_index; - moby->state = 9; + moby->state = SAND_SHARK_SUCK_CANNON_INTERACTION; spawner_moby_index = *(int *)((char *)moby->pvars + 0x288); if (spawner_moby_index >= 0) { char *spawner_vars = *(char **)(*(int *)&D_L02_0015FFD8_c + spawner_moby_index * 256 + 0x78); (*(int *)(spawner_vars + 0x14C))--; } - } else if (moby->state == 9) { - moby->state = 1; + } else if (moby->state == SAND_SHARK_SUCK_CANNON_INTERACTION) { + moby->state = SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET; } return helper_result; } From 478082326079566f7c266cfbd36f74055def564d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:38:15 +0000 Subject: [PATCH 0393/1502] decomp: clarify names in refresh_plasmabot_hatch_reset_delay domain_0_value_0 -> HATCH_WAIT_ACTIVATION: Retail 0x002d9880-0x002d9898 resolves the indexed hatch Moby and tests its state byte at +0x20 against zero; original Ghidra cVar1 reads that byte. The authoritative source plasmabot_hatch_update switches on the same Moby state, explicitly naming 0 HATCH_WAIT_ACTIVATION and waiting for the activation flag and gate condition. This is the hatch state domain, not a hero state. domain_1_value_5 -> HATCH_WAIT_ANIMATION_BEFORE_RESET_DELAY: Retail 0x002d98a0-0x002d98b4 stores 5 into the indexed hatch Moby state byte at +0x20 and starts animation 1. The authoritative plasmabot_hatch_update names state 5 HATCH_WAIT_ANIMATION_BEFORE_RESET_DELAY: animation completion advances it to 6 and animation 2. The shared Moby state field and matching animation transition prove reuse of that hatch-domain member. domain_2_value_6 -> HATCH_WAIT_RESET_DELAY: Retail 0x002d98c0-0x002d98c4 tests the entry Moby state byte against 6; 0x002d98d4 returns this predicate. At 0x002d98c8-0x002d98d0 the function refreshes pvars+8 with scale_game_frames(60). The authoritative plasmabot_hatch_update explicitly names state 6 HATCH_WAIT_RESET_DELAY and decrements that same pvars+8 timer before starting reset animation 3 and state 7. --- src/overlays/shared/enemies/plasmabot_hatch.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/plasmabot_hatch.c b/src/overlays/shared/enemies/plasmabot_hatch.c index 53d9dcb12f..abd2fe9919 100644 --- a/src/overlays/shared/enemies/plasmabot_hatch.c +++ b/src/overlays/shared/enemies/plasmabot_hatch.c @@ -103,14 +103,19 @@ typedef struct { int refresh_plasmabot_hatch_reset_delay(int i) __asm__("FUN_L14_002d9870"); int refresh_plasmabot_hatch_reset_delay(int i) { + enum { + HATCH_WAIT_ACTIVATION = 0, + HATCH_WAIT_ANIMATION_BEFORE_RESET_DELAY = 5, + HATCH_WAIT_RESET_DELAY = 6 + }; struct Moby *moby = (unsigned char *)(D_L14_ffd0_e_macro[2] + i * 256); int *hatch_vars = ((int *)moby->pvars); int hatch_reset_delay_active = 0; - if (moby->state == 0) { - moby->state = 5; + if (moby->state == HATCH_WAIT_ACTIVATION) { + moby->state = HATCH_WAIT_ANIMATION_BEFORE_RESET_DELAY; set_moby_animation(moby, 1, 0); } else { - hatch_reset_delay_active = moby->state == 6; + hatch_reset_delay_active = moby->state == HATCH_WAIT_RESET_DELAY; } hatch_vars[2] = scale_game_frames(0x3C); return hatch_reset_delay_active; From 4f1920139222c52afd9b950a274af1cc9063575f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:38:15 +0000 Subject: [PATCH 0394/1502] decomp: clarify names in SyncDCache domain_0_value_0 -> INTERRUPT_ENABLE_BIT_CLEAR: At 0x00118fa4 retail reads COP0 Status into s0, then masks it with 0x10000 at 0x00118fa8-0x00118fac. The zero branch at 0x00118fb0 skips DIntr at 0x00118fb8. Thus source status != 0 tests the saved interrupt-enable bit against its clear value. domain_1_value_0 -> INTERRUPT_ENABLE_BIT_CLEAR: The saved s0 remains the COP0 Status & 0x10000 value across _sceSDC at 0x00118fcc. At 0x00118fd4 its zero branch skips the EnableInterrupts tail call at 0x00118fe8. This second status != 0 uses the same saved interrupt-enable-bit domain and clear value as the first comparison. --- src/sdk/kernel/SyncDCache.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sdk/kernel/SyncDCache.c b/src/sdk/kernel/SyncDCache.c index ac3028c599..7a9ffad31a 100644 --- a/src/sdk/kernel/SyncDCache.c +++ b/src/sdk/kernel/SyncDCache.c @@ -8,15 +8,18 @@ extern s32 DIntr(); void SyncDCache(s32 range_start_address, s32 range_end_address) __asm__("FUN_00118f88"); void SyncDCache(s32 range_start_address, s32 range_end_address) { + enum { + INTERRUPT_ENABLE_BIT_CLEAR = 0 + }; u32 status; status = CpuReadStatus(); status &= 0x10000; - if (status != 0) { + if (status != INTERRUPT_ENABLE_BIT_CLEAR) { DIntr(); } _sceSDC(range_start_address & 0xFFFFFFC0, range_end_address & 0xFFFFFFC0); - if (status != 0) { + if (status != INTERRUPT_ENABLE_BIT_CLEAR) { EnableInterrupts(); } } From cf9bb4626f68353b09d30bcb6a775f9f5ee83fff Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:40:12 +0000 Subject: [PATCH 0395/1502] decomp: clarify names in update_moby_draw_callback domain_0_value_1 -> DRAW_CALLBACK_REGISTER: Retail 0x002dc9c0 loads state byte +0x20 from s0 (moby), and 0x002dc9cc compares that byte with 1 to enter 0x002dca0c-0x002dca18, which passes callback 0x002dc990 and the same moby to add_draw_callback. Initialization loads 1 at 0x002dc9f8 and stores it into the identical state byte at 0x002dca08. The authoritative source already labels that same switch(moby->state) branch DRAW_CALLBACK_REGISTER = 1, proving that the assignment reuses this exact local state domain and member. --- src/overlays/shared/mobys/moby_draw_callback_update.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/mobys/moby_draw_callback_update.c b/src/overlays/shared/mobys/moby_draw_callback_update.c index 77433dab4a..ce4f201956 100644 --- a/src/overlays/shared/mobys/moby_draw_callback_update.c +++ b/src/overlays/shared/mobys/moby_draw_callback_update.c @@ -22,7 +22,7 @@ void moby_draw_callback_update(struct Moby *moby) { case DRAW_CALLBACK_INITIALIZE: prepare_scaled_float_table_with_target_byte( l03_draw_callback_setup_byte_target, 0x20, 0.6666667f); - moby->state = 1; + moby->state = DRAW_CALLBACK_REGISTER; moby->update_dist = 0xFF; break; case DRAW_CALLBACK_REGISTER: From aefbb3edaf8063430e151fdde269a52744749bb6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:40:12 +0000 Subject: [PATCH 0396/1502] decomp: clarify names in sceVibGetProfile domain_1_value_0 -> DBC_RECEIVE_ERROR_THRESHOLD: Retail jal at 0x0012513c calls sceDbcReceiveData; bgezl v0 at 0x00125144 loads profile_byte_count from 0(sp) at 0x00125148 only for nonnegative status. Negative status bypasses this load and returns unchanged. Thus source receive_status < 0 uses zero as the exclusive upper boundary for propagated receive errors. The supplied helper also returns negative state->unk8C unchanged; this is a receive-status domain, not Boolean FALSE or a NULL pointer. --- src/sdk/input/sce_vib_get_profile.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/input/sce_vib_get_profile.c b/src/sdk/input/sce_vib_get_profile.c index 08df65fb1e..38563e51a5 100644 --- a/src/sdk/input/sce_vib_get_profile.c +++ b/src/sdk/input/sce_vib_get_profile.c @@ -16,6 +16,9 @@ typedef union { extern s32 sceDbcReceiveData(s32 port, DbcCommand cmd, void *buf, void *data); s32 sceVibGetProfile(s32 port, u8 *profile) { + enum { + DBC_RECEIVE_ERROR_THRESHOLD = 0 + }; DbcCommand cmd; s32 profile_byte_count; s32 receive_status; @@ -25,7 +28,7 @@ s32 sceVibGetProfile(s32 port, u8 *profile) { cmd.cmd = 3; cmd.ver = 1; receive_status = sceDbcReceiveData(port, cmd, &profile_byte_count, profile); - if (receive_status < 0) { + if (receive_status < DBC_RECEIVE_ERROR_THRESHOLD) { return receive_status; } return profile_byte_count; From 72141e515c97379b912a75586acb841520f1d815 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:40:12 +0000 Subject: [PATCH 0397/1502] decomp: clarify names in sync_hero_slot3_animation_speed domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0023212c/0x00232138 forms &hero (0x0013f350) in s0; 0x0023213c loads the vehicle_mode byte at hero+0x20a4 and 0x00232140 branches out when nonzero. The authoritative C maps this exact load to hero_slot3_animation_speed_state->vehicle_mode, proving the HeroVehicleMode selector rather than state.current or gravity_mode. Supplied include/rnc/hero/hero_state.h domain declares HERO_VEHICLE_MODE_ON_FOOT=0 in HeroVehicleMode. Only this zero mode proceeds to items[3].state and animation mapping, then 0x00232180-0x00232198 copy hero.anim_speed to the slot-3 mobys. The same source set_hero_animation gates slot-3 animation blending with vehicle_mode==0, corroborating the domain-specific guard. --- src/overlays/shared/hero/set_hero_animation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/set_hero_animation.c b/src/overlays/shared/hero/set_hero_animation.c index aee32b6f86..559a7d6ead 100644 --- a/src/overlays/shared/hero/set_hero_animation.c +++ b/src/overlays/shared/hero/set_hero_animation.c @@ -227,7 +227,7 @@ void sync_hero_slot3_animation_speed(void) { struct Hero *hero_slot3_animation_speed_state = &hero; int mapped_animation_ids[2]; - if (hero_slot3_animation_speed_state->vehicle_mode != 0) { + if (hero_slot3_animation_speed_state->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { return; } if (hero_slot3_animation_speed_state->items[3].state != 2) { From 60326fe3ee1e3f8c88f2f659969d8bd1b566760c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:40:12 +0000 Subject: [PATCH 0398/1502] decomp: clarify names in check_listed_plasmabots_not_starting_path_traversal domain_0_value_2 -> PLASMABOT_START_PATH_TRAVERSAL: Retail 0x002b39e8-0x002b39f4 resolves each encoded list index into a 0x100-byte moby; 0x002b39f8 checks oclass +0xA6 against 0x1C, and 0x002b3a04-0x002b3a08 compares that same moby's state byte +0x20 to 2 and returns false. The SHA-bound supplied plasmabot.c update_plasmabot switches on this same +0x20 state field and explicitly names 2 PLASMABOT_START_PATH_TRAVERSAL. Its wait-state caller invokes this predicate before activation and setting state 2 with animation 1; the named state then follows the path after interpolated progress >=3 and transitions to forward traversal state 3 on animation completion. This establishes the plasmabot state domain rather than any Hero or control-mode domain. --- src/overlays/shared/enemies/plasmabot.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/plasmabot.c b/src/overlays/shared/enemies/plasmabot.c index d44e4e9ad7..a0b7a9d3ee 100644 --- a/src/overlays/shared/enemies/plasmabot.c +++ b/src/overlays/shared/enemies/plasmabot.c @@ -1316,13 +1316,16 @@ extern char *D_L14_0015FFD8; int check_listed_plasmabots_not_starting_path_traversal(unsigned char *source_moby) __asm__("FUN_L14_002b39a0"); int check_listed_plasmabots_not_starting_path_traversal(unsigned char *source_moby) { + enum { + PLASMABOT_START_PATH_TRAVERSAL = 2 + }; unsigned short *moby_list_entry; if (*(volatile unsigned char *)(source_moby + 0x21) == 0xFF || (moby_list_entry = (unsigned short *)D_L14_001ABF40[MOBY(source_moby)->group]) == 0) return 1; do { char *moby = D_L14_0015FFD8 + ((*moby_list_entry & 0x7FFF) << 8); - if (MOBY(moby)->oclass == 0x1C && MOBY(moby)->state == 2) + if (MOBY(moby)->oclass == 0x1C && MOBY(moby)->state == PLASMABOT_START_PATH_TRAVERSAL) return 0; } while ((short)*moby_list_entry++ >= 0); return 1; From bf744f24b525bef21c2b4b950ce80688c26b2ddd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:40:12 +0000 Subject: [PATCH 0399/1502] decomp: clarify names in enemy_stun_update domain_0_value_12 -> ROBOT_DOG_STATE_RECOVER_THEN_REINITIALIZE: Retail 0x002efebc preserves the moby argument in s0; the nonzero suction-status branch writes 0xC to byte +0x20 at 0x002efed0. The authoritative source identifies this byte as the same robot-dog state selected by robot_dog_update, whose existing ROBOT_DOG_STATE_RECOVER_THEN_REINITIALIZE case invokes recovery and returns the dog to initialization. The adjacent cancellation helper also assigns that canonical member to moby->state. domain_1_value_12 -> ROBOT_DOG_STATE_RECOVER_THEN_REINITIALIZE: Retail 0x002efed4 loads the same robot-dog state byte +0x20 and 0x002efed8-0x002efedc compare it with 0xC after suction returns zero. This tests the exact state written by the suction-active branch, in the RobotDogState domain established by robot_dog_update and the adjacent cancellation helper; reuse its existing ROBOT_DOG_STATE_RECOVER_THEN_REINITIALIZE member. domain_2_value_6 -> ROBOT_DOG_STATE_WAIT_FOR_CHASE_TRIGGER: Retail 0x002efee4 loads 6 and 0x002efef4 writes it to the same moby state byte +0x20 when suction ends from state 12; 0x002efee8-0x002eff10 ensure animation 7. In the authoritative robot_dog_update, ROBOT_DOG_STATE_WAIT_FOR_CHASE_TRIGGER selects this same byte value 6, waits for the chase/path trigger, and uses animation 7. This is the existing RobotDogState member, not HERO_STATE_FALL. --- src/overlays/l17/mobys/robot_dog.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l17/mobys/robot_dog.c b/src/overlays/l17/mobys/robot_dog.c index 63538f88e7..4b15bce3de 100644 --- a/src/overlays/l17/mobys/robot_dog.c +++ b/src/overlays/l17/mobys/robot_dog.c @@ -710,9 +710,9 @@ int enemy_stun_update(struct Moby *moby) __asm__("FUN_L17_002efea8"); int enemy_stun_update(struct Moby *moby) { int suction_status = process_moby_suck_cannon_suction(moby); if (suction_status) { - moby->state = 12; - } else if (moby->state == 12) { - moby->state = 6; + moby->state = ROBOT_DOG_STATE_RECOVER_THEN_REINITIALIZE; + } else if (moby->state == ROBOT_DOG_STATE_RECOVER_THEN_REINITIALIZE) { + moby->state = ROBOT_DOG_STATE_WAIT_FOR_CHASE_TRIGGER; if (moby->prev_seq != 7) { int animation_blend_frames = scale_game_frames(10); blend_moby_animation(moby, 7, 0, animation_blend_frames); From ba93258ab1fd81d605924dc76717bf4e69afc6ab Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:42:09 +0000 Subject: [PATCH 0400/1502] decomp: clarify names in update_minibomber_target domain_0_value_0 -> MINIBOMBER_STATE_INITIALIZE: Retail 0x002b553c loads the moby state byte from a0+0x20 and 0x002b5540 skips target selection when it equals zero. The supplied minibomber_update passes this same moby to FUN_L14_002b5530 before switching on moby->state; its existing MINIBOMBER_STATE_INITIALIZE = 0 case validates intro/bound/bomb/exit paths, copies the initial position, initializes manipulators and advances moby->state to 1. Thus this comparison belongs to the same minibomber current-state domain and can reuse its established INITIALIZE member. domain_1_value_9 -> MINIBOMBER_STATE_DESTROY: Retail 0x002b553c loads a0+0x20, then 0x002b5548 loads 9 and 0x002b554c skips target selection for that state. The supplied minibomber_update passes the same moby into FUN_L14_002b5530 and switches on its offset-0x20 state with existing MINIBOMBER_STATE_DESTROY = 9; that case emits destruction effects, releases the owned voice and calls mark_moby_for_removal. process_minibomber_hit_reactions also assigns 9 on lethal/destroy reactions. This proves the same minibomber current-state domain, rather than a numerically coincident control or request mode. --- src/overlays/l14/mobys/minibomber.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/minibomber.c b/src/overlays/l14/mobys/minibomber.c index 6dd05618a5..553dcf0616 100644 --- a/src/overlays/l14/mobys/minibomber.c +++ b/src/overlays/l14/mobys/minibomber.c @@ -769,8 +769,12 @@ extern int FUN_L00_0025ff38(float a, char *m, char *b, int c, int d, int *e, int void update_minibomber_target(struct Moby *moby) __asm__("FUN_L14_002b5530"); void update_minibomber_target(struct Moby *moby) { + enum { + MINIBOMBER_STATE_INITIALIZE = 0, + MINIBOMBER_STATE_DESTROY = 9 + }; char *minibomber_private_vars = (char *)moby->pvars; - if (moby->state != 0 && moby->state != 9) { + if (moby->state != MINIBOMBER_STATE_INITIALIZE && moby->state != MINIBOMBER_STATE_DESTROY) { int *bound_path = ((int *)l14_paths[*(int *)(minibomber_private_vars + 0xD4)]); FUN_L00_0025ff38( 255.0f, moby, minibomber_private_vars + 0x70, 0, 0, bound_path + 4, *bound_path); From 3e01593c73f7ee9cfdbebc159c2df8263fe553e8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:42:09 +0000 Subject: [PATCH 0401/1502] decomp: clarify names in end_thruster_pack_lock_red_wait domain_0_value_2 -> THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER: Retail 0x002d7fd4 preserves the input moby in a2; 0x002d7fe4-0x002d7fe8 loads its +0x20 state byte and compares it with 2. Original Ghidra shows the same param_1+0x20 gate. The supplied request_thruster_pack_lock_red_wait sets this same moby state to its named THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER member and initializes pvars+0x6C countdown. The same-file update case STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER approaches the waiting height and tests hero.air_frames.s == 0, hero.ground_moby == moby and hero.state.current == 0x22. The polling function independently names this moby state 2 identically. This proves the red-lock moby domain, not the unrelated hero state 2. domain_1_value_3 -> THRUSTER_PACK_LOCK_RED_STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT: Retail 0x002d7ff0 loads 3 and 0x002d7ff8 stores it to the same input moby's +0x20 state after the state-2 gate; original Ghidra confirms this assignment precedes saved voice cleanup. Supplied thruster_pack_lock_red_update groups state 3, named STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT, with state 1 to call advance_accelerated_scalar toward saved initial height plus l18_thruster_pack_lock_red_approach_height_offset. The supplied poll_moby_state_and_rearm names state 3 THRUSTER_PACK_LOCK_RED_STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT and consumes it as completion before rearming state 1. Thus this assignment enters the red-lock post-wait approach phase. --- src/overlays/l18/mobys/thruster_pack_lock_red.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/thruster_pack_lock_red.c b/src/overlays/l18/mobys/thruster_pack_lock_red.c index ec80c94fb4..8c5a2579f0 100644 --- a/src/overlays/l18/mobys/thruster_pack_lock_red.c +++ b/src/overlays/l18/mobys/thruster_pack_lock_red.c @@ -176,10 +176,14 @@ void request_thruster_pack_lock_red_wait(struct Moby *moby, int wait_duration_fr void end_thruster_pack_lock_red_wait(struct Moby *moby) __asm__("FUN_L18_002d7fd0"); void end_thruster_pack_lock_red_wait(struct Moby *moby) { + enum { + THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER = 2, + THRUSTER_PACK_LOCK_RED_STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT = 3 + }; int *red_lock_private_vars = (int *)moby->pvars; - if (moby->state == 2) { + if (moby->state == THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER) { int voice_slot_index; - moby->state = 3; + moby->state = THRUSTER_PACK_LOCK_RED_STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT; voice_slot_index = red_lock_private_vars[0x70 / 4]; if (voice_slot_index != -1) { unsigned char *voice_slot_entry = From 6d7ffe969fa2075827526ea30f42045ee7f0987d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:42:09 +0000 Subject: [PATCH 0402/1502] decomp: clarify names in synchronize_lift_group_height domain_0_value_1402 -> MOBY_CLASS_LIFT: Authoritative lift.c (SHA-256 cc9dfe7ec9a01d433ad98b1b40c998ee274537b7554414f0714ad99e546fb27b) explicitly identifies level-18 class 0x57a as a lift. Retail 0x002f25c0 loads 0x57a, 0x002f25e4 reads the group Moby's signed kind at +0xa6, and 0x002f25e8 compares them. Only this class follows pvars at +0x78 and its instance index at +0x1c to update the 0x1190-stride lift height record at +8 (0x002f25f0-0x002f2604). The source lift initialization assigns that same pvars +0x1c from next_lift_instance_index_gp, and the lift height-approach caller supplies lift_moby. Thus the literal denotes the lift Moby class, rather than a state or control value. --- src/overlays/l18/mobys/lift.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l18/mobys/lift.c b/src/overlays/l18/mobys/lift.c index b1e6580e53..9c6ae04a26 100644 --- a/src/overlays/l18/mobys/lift.c +++ b/src/overlays/l18/mobys/lift.c @@ -183,6 +183,9 @@ extern E l18_lift_height_records[] __asm__("D_L18_001DB500"); extern short *D_L18_001AC240_c[] __asm__("D_L18_001AC240"); void synchronize_lift_group_height(void *source_moby) { + enum { + MOBY_CLASS_LIFT = 0x57A + }; unsigned char *source_moby_bytes = source_moby; short *group_entry = D_L18_001AC240_c[source_moby_bytes[0x21]]; E *height_records = l18_lift_height_records; @@ -190,7 +193,7 @@ void synchronize_lift_group_height(void *source_moby) { Mx *group_moby = (Mx *)(((*(unsigned short *)group_entry & 0x7FFF) << 8) + (int)D_L18_0015FFD8); group_moby->f = *(float *)(source_moby_bytes + 0x18); - if (group_moby->kind == 0x57A) { + if (group_moby->kind == MOBY_CLASS_LIFT) { height_records[group_moby->l->idx].f = *(float *)(source_moby_bytes + 0x18); } } while (*group_entry++ >= 0); From d091de4b5b2a494809760c6a96abbf8aa82e1431 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:43:53 +0000 Subject: [PATCH 0403/1502] decomp: clarify names in enter_scoutbot_return_home_state domain_0_value_3 -> SCOUTBOT_STATE_RETURN_HOME: Retail 0x002d4068 retains the supplied Moby in s0; 0x002d4074 loads 3 and 0x002d408c stores it to s0+0x20, the authoritative C moby->state. The assigned enter_scoutbot_return_home_state then sets private +0x200=4.0f and +0x208=0.5f at 0x002d4090/94 and selects animation 2. In the same SHA-bound scoutbot.c, scoutbot_update switches on the same scoutbot moby->state and declares SCOUTBOT_STATE_RETURN_HOME=3; that case computes heading from saved home minus moby position, accelerates toward home, restores the identical two floats, and returns to idle upon arrival. This proves the scoutbot state member, rather than the unrelated equal-valued HERO_STATE_STOP. --- src/overlays/shared/enemies/scoutbot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/scoutbot.c b/src/overlays/shared/enemies/scoutbot.c index 378febab64..f5b4aebfc3 100644 --- a/src/overlays/shared/enemies/scoutbot.c +++ b/src/overlays/shared/enemies/scoutbot.c @@ -644,9 +644,9 @@ void update_scoutbot_movement(struct Moby *moby) { void *enter_scoutbot_return_home_state(struct Moby *moby) __asm__("FUN_L08_002d4050"); void *enter_scoutbot_return_home_state(struct Moby *moby) { - void *suction_cancel_status = cancel_suck_cannon_suction(moby); + enum { SCOUTBOT_STATE_RETURN_HOME = 3 } ;void *suction_cancel_status = cancel_suck_cannon_suction(moby); ScoutbotVars *scoutbot_data = (ScoutbotVars *)moby->pvars; - moby->state = 3; + moby->state = SCOUTBOT_STATE_RETURN_HOME; scoutbot_data->unk200 = 4.0f; scoutbot_data->unk208 = 0.5f; if ((unsigned char)((char)moby->prev_seq) != 2) { From 3e2824c9801875c60d1639ce358ccd5faea4f633 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:43:53 +0000 Subject: [PATCH 0404/1502] decomp: clarify names in count_active_moby_group_members domain_0_value_0 -> MIN_ACTIVE_MOBY_STATE: Authoritative source src/overlays/shared/mobys/count_active_moby_group_members.c (SHA-256 b18c2f1f3e39ca2d5d7117da063574a74d32558607da9861212ddb7ca6c10c7e) compares signed char moby->state >= 0 before counting. Retail 0x0026e040-0x0026e050 resolves a group member using its masked index and 0x100-byte stride. At 0x0026e054 lb reads its signed state at +0x20; 0x0026e058 bltzl skips counting every negative state. Nonnegative states reach the exclusion test at 0x0026e060-0x0026e06c and increments at 0x0026e064/0x0026e074. Original Ghidra likewise tests *(char *)(iVar2 + 0x20) < '\0'. Thus zero is the minimum state eligible for count_active_moby_group_members, not a claimed initialization state. Supplied update_countdown_sequence passes -1 to disable exclusion and waits for this active-member count to vanish; beehive_update excludes state 0xC. These distinguish the signed activity boundary from the separate exclusion argument. --- src/overlays/shared/mobys/count_active_moby_group_members.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/mobys/count_active_moby_group_members.c b/src/overlays/shared/mobys/count_active_moby_group_members.c index 462e32effa..c382efc519 100644 --- a/src/overlays/shared/mobys/count_active_moby_group_members.c +++ b/src/overlays/shared/mobys/count_active_moby_group_members.c @@ -36,6 +36,9 @@ extern O_26e008 *D_L01_0015FFD8_26e008 __asm__("D_L01_0015FFD8"); int count_active_moby_group_members(int i, int st) __asm__("FUN_L01_0026e008"); int count_active_moby_group_members(int i, int excluded_moby_state) { + enum { + MIN_ACTIVE_MOBY_STATE = 0 + }; unsigned short *moby_index_entry; int qualifying_moby_count = 0; O_26e008 *moby; @@ -46,7 +49,7 @@ int count_active_moby_group_members(int i, int excluded_moby_state) { moby_index_entry = D_L01_001ABCC0_lui[i]; do { moby = (O_26e008 *)(((*moby_index_entry & 0x7FFF) << 8) + (int)D_L01_0015FFD8_26e008); - if (moby->state >= 0 && + if (moby->state >= MIN_ACTIVE_MOBY_STATE && (excluded_moby_state == -1 || (unsigned char)moby->state != excluded_moby_state)) { qualifying_moby_count++; } From e64c42b9c3ee107589cacc822ad6e0c80d3e5767 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:43:53 +0000 Subject: [PATCH 0405/1502] decomp: clarify names in receiveDataFromIPU domain_0_value_0 -> FALSE: The selector saved_interrupt_state is DIntr's return from the call at 0x0012a13c. In helper 0x0011d660, instructions 0x0011d660-0x0011d670 read and mask entry Status bit 16 and use sltu to normalize it to Boolean a0. The clear-bit path at 0x0011d69c-0x0011d6a4 returns zero; the enabled path preserves a0=1 across DI and returns it at 0x0011d698. At 0x0012a184 the zero return skips EnableInterrupts, while nonzero reaches 0x0012a194. Thus this is a Boolean comparison, and existing FALSE=0 fits its proven domain; NULL is inappropriate for this scalar interrupt-enable predicate. --- src/sdk/ipu/receive_data_from_ipu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdk/ipu/receive_data_from_ipu.c b/src/sdk/ipu/receive_data_from_ipu.c index 4e0d0077c2..5fdad1155c 100644 --- a/src/sdk/ipu/receive_data_from_ipu.c +++ b/src/sdk/ipu/receive_data_from_ipu.c @@ -10,7 +10,7 @@ void receiveDataFromIPU(s32 destination_address, s32 byte_count) { *(volatile u32 *)0x1000B010 = (destination_address & 0x0FFFFFFF) | 0x80000000; *(volatile u32 *)0x1000B020 = byte_count >> 4; *(volatile u32 *)0x1000B000 = 0x100; - if (saved_interrupt_state != 0) { + if (saved_interrupt_state != FALSE) { EnableInterrupts(0x100); } } From 8586bd1ac9d95b5fd1afcaaa18dcc2b4c1eadd72 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:43:53 +0000 Subject: [PATCH 0406/1502] decomp: clarify names in update_effects_draw_trigger domain_0_value_1 -> DRAW_CALLBACK_CHECK_VOLUME_AND_REGISTER: In the SHA-256-bound effects_draw_trigger.c snapshot, this assignment writes moby->state, the exact selector whose existing local enum case DRAW_CALLBACK_CHECK_VOLUME_AND_REGISTER equals 1. Retail 0x002e7238 loads 1 into v1 and 0x002e7248 stores it at s0+0x20; 0x002e7218 reads that same byte, and 0x002e7224-0x002e7228 compares it to 1 and branches to 0x002e724c. That branch loads the pvars+0xC clip-volume index, bypasses testing for -1 or requires a nonzero clip-volume result, then registers draw_level_12_effects with the moby at 0x002e7274-0x002e727c. Thus the assignment enters the already named check-volume-and-register state, rather than any unrelated hero enum. --- src/overlays/l12/mobys/effects_draw_trigger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l12/mobys/effects_draw_trigger.c b/src/overlays/l12/mobys/effects_draw_trigger.c index 406f8e8fd9..815f091d41 100644 --- a/src/overlays/l12/mobys/effects_draw_trigger.c +++ b/src/overlays/l12/mobys/effects_draw_trigger.c @@ -27,7 +27,7 @@ void effects_draw_trigger_update(struct Moby *moby) { char *draw_callback_vars = (char *)moby->pvars; switch (moby->state) { case DRAW_CALLBACK_INITIALIZE: - moby->state = 1; + moby->state = DRAW_CALLBACK_CHECK_VOLUME_AND_REGISTER; moby->update_dist = 0xFF; break; case DRAW_CALLBACK_CHECK_VOLUME_AND_REGISTER: { From 2bb823453a0aa7b00b6f7622cc55e045f5958b99 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:43:53 +0000 Subject: [PATCH 0407/1502] decomp: clarify names in update_wall_button_blocker domain_0_value_0 -> WALL_BUTTON_BLOCKER_STATE_UNINITIALIZED: In update_wall_button_blocker, retail 0x002e3700 loads moby state at +0x20 and 0x002e3704 skips all initialization when nonzero. Only state zero reaches the two in-place rot_row1/rot_row2 normalizations using pvars[0/1]*0.25 at 0x002e370c..0x002e3738, followed by state=1, flags|0x101 and update_entity. Thus zero identifies the blocker's not-yet-initialized state; this is the moby's own initialization domain, not a hero enum. domain_1_value_1 -> WALL_BUTTON_BLOCKER_STATE_INITIALIZED: After both rotation rows have been normalized to pvars-derived lengths at 0x002e3720..0x002e3738, retail 0x002e3740 loads 1 and 0x002e3744 stores it to the same moby state byte +0x20 tested at 0x002e3700. The nonzero branch at 0x002e3704 then bypasses this work on subsequent updates. One therefore marks completed blocker initialization; flags|0x101 and update_entity follow at 0x002e374c..0x002e3754. --- src/overlays/l16/mobys/wall_button_blocker.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l16/mobys/wall_button_blocker.c b/src/overlays/l16/mobys/wall_button_blocker.c index 26ff5c2e17..ac926529ab 100644 --- a/src/overlays/l16/mobys/wall_button_blocker.c +++ b/src/overlays/l16/mobys/wall_button_blocker.c @@ -44,11 +44,11 @@ void wall_button_blocker_update(struct Moby *moby) __asm__("FUN_L16_002e36e8"); /* Moby class 1387 */ void wall_button_blocker_update(struct Moby *moby) { - float *rotation_scale_data = (float *)moby->pvars; - if (moby->state == 0) { + enum { WALL_BUTTON_BLOCKER_STATE_UNINITIALIZED = 0 , WALL_BUTTON_BLOCKER_STATE_INITIALIZED = 1 } ;float *rotation_scale_data = (float *)moby->pvars; + if (moby->state == WALL_BUTTON_BLOCKER_STATE_UNINITIALIZED) { fast_vec_normalize(&moby->rot_row1, &moby->rot_row1, rotation_scale_data[0] * 0.25f); fast_vec_normalize(&moby->rot_row2, &moby->rot_row2, rotation_scale_data[1] * 0.25f); - moby->state = 1; + moby->state = WALL_BUTTON_BLOCKER_STATE_INITIALIZED; moby->flags |= 0x101; update_entity(moby); } From b5a3369dab42fc5977aafbf4d471e3e362ba13dd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:45:41 +0000 Subject: [PATCH 0408/1502] decomp: clarify names in update_hud_counter_cap_and_visibility domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Authoritative source SHA-256 2c732c6e5b214abcba69f8ed91645c3e468336af7b13cbd3c45027b7a171036d compares hero.vehicle_mode to 0. Retail 002377ec forms hero base 0x0013f350; 002377fc loads its byte at +0x20a4 (0x001413f4), and 00237800 branches on nonzero after the item-ID-9 test at 002377f0-002377f4. Zero permits scale_game_frames(0x78)+30 to reach HUD +0x7c at 00237828, while nonzero takes the timer-cap path. This directly matches the source vehicle_mode selector and the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT; no HeroStateId or gravity-domain member is used. --- src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c index 780a9b2f0d..c48b2ba0f3 100644 --- a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c +++ b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c @@ -34,7 +34,7 @@ void update_hud_counter_cap_and_visibility(char *hud_element) { *(int *)(hud_element + 8) = 10; else *(int *)(hud_element + 8) = 5; - if (hero.items[0].item_id == 9 && hero.vehicle_mode == 0) { + if (hero.items[0].item_id == 9 && hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { *(int *)(hud_element + 0x7C) = scale_game_frames(0x78) + 30; } else if (*(int *)(hud_element + 0x7C) > 30) { *(int *)(hud_element + 0x7C) = 30; From 5f5c8d80962ce6079646bdaaaf38bf61e22c3289 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:45:41 +0000 Subject: [PATCH 0409/1502] decomp: clarify names in prepare_sand_shark_for_relaunch_or_remove domain_0_value_26 -> SAND_SHARK_INACTIVE_WAIT_FOR_RELAUNCH: Retail 0x002d634c retains the input sand shark in s0; 0x002d6358 loads its pvars from +0x78. After selecting a class-0x29C group partner at 0x002d6354 and storing it at pvars+0x27C (0x002d6360), 0x002d6364 loads 26 and 0x002d636c stores it to this same moby's state byte +0x20. Instructions 0x002d6374-0x002d6398 stop animation, copy home at pvars+0x220 to position, disable collision and subtract 10 Z. The authoritative source's sand_shark_update switches on moby->state and already declares SAND_SHARK_INACTIVE_WAIT_FOR_RELAUNCH = 26; that case refreshes the same pvars+0x27C partner and removes the shark only if none exists. Its death/fade paths enter 26 with the same home parking and collision disabling. This proves the same sand shark state domain and reuses its established member, not the unrelated HeroStateId member. --- src/overlays/l02/mobys/sand_shark.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l02/mobys/sand_shark.c b/src/overlays/l02/mobys/sand_shark.c index ca0411290c..be7b0442fe 100644 --- a/src/overlays/l02/mobys/sand_shark.c +++ b/src/overlays/l02/mobys/sand_shark.c @@ -1377,11 +1377,14 @@ void *handle_sand_shark_suck_cannon_storage(struct Moby *moby) { void prepare_sand_shark_for_relaunch_or_remove(struct Moby *moby) __asm__("FUN_L02_002d6340"); void prepare_sand_shark_for_relaunch_or_remove(struct Moby *moby) { + enum { + SAND_SHARK_INACTIVE_WAIT_FOR_RELAUNCH = 0x1A + }; char *sand_shark_private_vars = (char *)moby->pvars; int selected_class_29c_moby = select_group_class_29c_moby(moby); *(int *)(sand_shark_private_vars + 0x27C) = selected_class_29c_moby; if (selected_class_29c_moby != 0) { - moby->state = 0x1A; + moby->state = SAND_SHARK_INACTIVE_WAIT_FOR_RELAUNCH; moby->anim_speed = 0; qcopy(&moby->pos, sand_shark_private_vars + 0x220); moby->collision = 0; From a4bdceeadacca82d78e99f0d68079890a0519bc8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:47:32 +0000 Subject: [PATCH 0410/1502] decomp: clarify names in update_moby_state_pause domain_0_value_4 -> STATE_WAIT_TO_RESUME_APPROACH: current_state is loaded directly from moby->state (+0x20) at retail 0x002d6130; 0x002d6144 compares it with 4 after restricting it to 3/4. The same mine.c update_mine switch names this exact moby state 4 STATE_WAIT_TO_RESUME_APPROACH and transitions it to STATE_APPROACH_NEARBY_TARGET when its wait check succeeds. This comparison avoids overwriting the saved resume state when already waiting; it is not HERO_STATE_CROUCH or VOICE_SLOT_STOP_REQUESTED. domain_1_value_4 -> STATE_WAIT_TO_RESUME_APPROACH: Retail 0x002d6140 loads 4 and 0x002d614c stores it to this mine's moby state byte +0x20, while 0x002d6154 saves the previous state to command +0xBC. Retail 0x002d6170-0x002d6174 restores that saved state after the helper clears. The authoritative mine.c update_mine and moby_hold_state_while_active already call this same moby->state value STATE_WAIT_TO_RESUME_APPROACH, proving the mine state domain and canonical meaning. --- src/overlays/l18/mobys/mine.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/mine.c b/src/overlays/l18/mobys/mine.c index a7cd93b413..08c604f55d 100644 --- a/src/overlays/l18/mobys/mine.c +++ b/src/overlays/l18/mobys/mine.c @@ -373,15 +373,18 @@ extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); int update_moby_state_pause(struct Moby *moby) __asm__("FUN_L18_002d6108"); int update_moby_state_pause(struct Moby *moby) { + enum { + STATE_WAIT_TO_RESUME_APPROACH = 4 + }; char *moby_vars = (char *)moby->pvars; int state_pause_result = process_moby_suck_cannon_suction(moby); if (state_pause_result != 0) { unsigned char current_state = moby->state; if ((unsigned)(current_state - 3) < 2) { state_pause_result = 2; - if (current_state != 4) { + if (current_state != STATE_WAIT_TO_RESUME_APPROACH) { moby->command = current_state; - moby->state = 4; + moby->state = STATE_WAIT_TO_RESUME_APPROACH; } } else { *(short *)(moby_vars + 0xC8) = 0; From 2261ccc1bd6dc07c6094aa1373f39b94c25df58f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:47:32 +0000 Subject: [PATCH 0411/1502] decomp: clarify names in _outputFrame domain_0_value_3 -> MPEG_PICTURE_CODING_TYPE_B: Authoritative src/sdk/video/mpeg/ref_images/outputframe.c SHA-256 b55ffe0177799daeadfd32f9eea42a7efb3df0e3018ac9a7834581ecf47c2893 identifies the selector as MpegDecoder.picture_coding_type. Retail 0x001294e4 loads decoder+0x150 and 0x001294e8 compares it with 3: equality selects +0x1c4 for frame display, otherwise +0x1b8. Checked caller 0x0012be00 passes the same decoder to reference updater 0x00129550 at 0x0012be50/74 and _outputFrame at 0x0012be94. Updater 0x00129560/74 tests the same +0x150 against 3: equality uses the separate +0x1c4/+0x1d4/+0x1e4 image set (0x00129584-0x001295a4), bypassing reference-buffer rotation at 0x00129690-0x001296bc used for other coding types. This is the MPEG B-picture coding domain and its non-reference picture buffer path, supporting MPEG_PICTURE_CODING_TYPE_B rather than a state or picture-structure constant. domain_1_value_3 -> MPEG_PICTURE_CODING_TYPE_B: The second authoritative source comparison uses the exact same MpegDecoder.picture_coding_type selector as domain_0_value_3. Retail 0x001294e4 loads decoder+0x150; after the field branch at 0x001294e0, 0x00129508 compares that coding type against 3. Equality loads +0x1d4 and +0x1e4 at 0x00129510/18 for _dispRefImageField (0x00129524), otherwise +0x1c8 and +0x1d8. Checked sibling updater 0x00129550, sharing caller 0x0012be00, tests +0x150 at 0x00129560/74 and assigns the +0x1c4/+0x1d4/+0x1e4 separate image set for coding type 3, bypassing the reference-buffer rotation at 0x00129690-0x001296bc. Both comparisons therefore use the same MPEG B-picture coding value and should reuse MPEG_PICTURE_CODING_TYPE_B; the separate picture_structure == 3 is outside this proposal. --- src/sdk/mpeg/ref_images/outputframe.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sdk/mpeg/ref_images/outputframe.c b/src/sdk/mpeg/ref_images/outputframe.c index 76ddce1269..5608a42407 100644 --- a/src/sdk/mpeg/ref_images/outputframe.c +++ b/src/sdk/mpeg/ref_images/outputframe.c @@ -10,20 +10,23 @@ extern s32 _dispRefImageField(struct MpegDecoder *mpeg, s32 arg3); void _outputFrame(struct MpegDecoder *mpeg, s32 frame_counter, s32 output_enabled) { + enum { + MPEG_PICTURE_CODING_TYPE_B = 3 + }; struct MpegRefImage *frame_image; struct MpegRefImage *top_field; struct MpegRefImage *bottom_field; if (output_enabled != 0) { if (mpeg->picture_structure == 3) { - if (mpeg->picture_coding_type == 3) { + if (mpeg->picture_coding_type == MPEG_PICTURE_CODING_TYPE_B) { frame_image = mpeg->ref_images[3]; } else { frame_image = mpeg->ref_images[0]; } _dispRefImage(mpeg, frame_image, frame_counter - 1); } else { - if (mpeg->picture_coding_type == 3) { + if (mpeg->picture_coding_type == MPEG_PICTURE_CODING_TYPE_B) { top_field = mpeg->ref_images[7]; bottom_field = mpeg->ref_images[11]; } else { From ec56184843a2023bb4dc392ad1a2121c1394567b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:47:32 +0000 Subject: [PATCH 0412/1502] decomp: clarify names in update_visible_mobys domain_0_value_0 -> MOBY_MIN_UPDATABLE_STATE: In source src/mobys/update_visible_mobys.c (SHA-256 82eab9de4d612efd5811a1611fc8ad63090acba3cd778a2e325d21df5e3f26e1), (s8)moby->state >= 0 gates all per-moby work. Retail 0x00212e48 loads the signed state byte at +0x20; 0x00212e50 branches on negative to the next-link path at 0x00212ea4, bypassing animation at 0x00212e68, callback at 0x00212e80 and bounds refresh at 0x00212e98. Thus zero is the minimum signed state admitted to this update pass, not a boolean or pointer null value. --- src/mobys/update_visible_mobys.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mobys/update_visible_mobys.c b/src/mobys/update_visible_mobys.c index 472248bbf8..d3eea080d5 100644 --- a/src/mobys/update_visible_mobys.c +++ b/src/mobys/update_visible_mobys.c @@ -17,12 +17,15 @@ void update_visible_mobys(void) __asm__("FUN_00212e28"); * bounds refresh can change flags or the list link, so each field is read at * its point of use. */ void update_visible_mobys(void) { + enum { + MOBY_MIN_UPDATABLE_STATE = 0 + }; struct Moby *moby; visible_moby_list = build_resident_visibility_list(); moby = visible_moby_list; while (moby != 0) { - if ((s8)moby->state >= 0) { + if ((s8)moby->state >= MOBY_MIN_UPDATABLE_STATE) { if (!(moby->flags & MOBY_SKIP_ANIMATION)) { advance_moby_animation(moby); } From a734a6b235c96af6b81048c5797bd32c2dd24893 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:47:33 +0000 Subject: [PATCH 0413/1502] decomp: clarify names in resolve_hero_gravity_mode domain_0_value_63 -> HERO_STATE_DIRECTION_LIMITED_GROUND_MOVE: Retail 0x00233444/4c forms &hero (0x0013F350), then 0x0023345c loads a0 from hero+0x2084, the snapshot's hero.state.current. The 0x3f comparison at 0x00233454/60 branches to mode override 1 at 0x002334b4. Original Ghidra compares iRam001413d4 with 0x3f. This proves the HeroStateId selector domain; reuse its canonical HERO_STATE_DIRECTION_LIMITED_GROUND_MOVE=63 member. domain_1_value_113 -> HERO_STATE_ANIMATION_FRAME_EXIT_WAIT: Retail 0x0023345c loads hero.state.current at hero+0x2084 into a0; no intervening write changes a0 before li v0,0x71 at 0x00233468 and beq at 0x0023346c. The matching branch forces return mode 1 at 0x002334b4. Original Ghidra uses the same iRam001413d4 current-state read. Thus the canonical HeroStateId member HERO_STATE_ANIMATION_FRAME_EXIT_WAIT=113 applies. domain_2_value_112 -> HERO_STATE_ATTACK_RECORD_FRAME_EXIT_WAIT: The snapshot state local is hero.state.current, corresponding to lw a0,0x2084(a1) at 0x0023345c after a1=&hero. Retail li v0,0x70 at 0x00233470 and beql at 0x00233474 compare this unchanged current state and set s1=1 in the delay slot. Original Ghidra likewise returns 1 for iRam001413d4==0x70. Reuse canonical HeroStateId HERO_STATE_ATTACK_RECORD_FRAME_EXIT_WAIT=112. domain_3_value_0 -> HERO_STATE_IDLE: Retail bne a0,zero at 0x00233494 tests the same current-state value loaded from hero+0x2084 at 0x0023345c, after the magnet-ground and global-byte gates. Only the zero current-state path compares hero+0x30e air frames against scale_game_frames(4) and may force mode 1. Snapshot and original Ghidra confirm state==0, establishing HeroStateId HERO_STATE_IDLE=0 rather than a gravity or vehicle mode constant. --- src/overlays/shared/hero/set_hero_animation.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/set_hero_animation.c b/src/overlays/shared/hero/set_hero_animation.c index 559a7d6ead..71deac0d4e 100644 --- a/src/overlays/shared/hero/set_hero_animation.c +++ b/src/overlays/shared/hero/set_hero_animation.c @@ -920,8 +920,8 @@ int resolve_hero_gravity_mode(void) { int state = hero_gravity_mode_state->state.current; int return_value = hero_gravity_mode_state->unk308; - if (state == 0x3F || state == 0x71 || state == 0x70 || - (hero_gravity_mode_state->on_magnet_ground != 0 && D_0013D4DC[0] != 0 && state == 0 && + if (state == HERO_STATE_DIRECTION_LIMITED_GROUND_MOVE || state == HERO_STATE_ANIMATION_FRAME_EXIT_WAIT || state == HERO_STATE_ATTACK_RECORD_FRAME_EXIT_WAIT || + (hero_gravity_mode_state->on_magnet_ground != 0 && D_0013D4DC[0] != 0 && state == HERO_STATE_IDLE && hero_gravity_mode_state->air_frames.s < scale_game_frames(4))) { return_value = 1; } From 4aed2d2f6881d031c0eacf781e7c5bdced958f0d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:47:33 +0000 Subject: [PATCH 0414/1502] decomp: clarify names in help_request domain_0_value_0 -> HELP_STATE_INACTIVE: Retail 0x00203910 loads the state word at 0x00179410 and 0x00203920 rejects requests when it is nonzero. Only zero proceeds to the separate current-message and music guards, then stores the help-record index/current message at 0x00203978/0x00203980 and pushes history. The authoritative source's clear_active_help_record tests the same word for nonzero activity and resets it to zero while clearing the current record, proving zero is the inactive help state rather than a hero/control mode. --- src/overlays/shared/ui/help/help_request.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/ui/help/help_request.c b/src/overlays/shared/ui/help/help_request.c index 7a1596298c..1709fa2e5c 100644 --- a/src/overlays/shared/ui/help/help_request.c +++ b/src/overlays/shared/ui/help/help_request.c @@ -25,8 +25,11 @@ extern P00203908 D_00141968_00203908[] __asm__("D_00141968"); s32 help_request(s32 a, s32 b) __asm__("FUN_L00_00203908"); s32 help_request(s32 message_id, s32 help_record_index) { + enum { + HELP_STATE_INACTIVE = 0 + }; S00203908 *help_state_ptr = &D_L00_00179410_00203908; - if (help_state_ptr->state == 0 && help_state_ptr->cur == -1 && + if (help_state_ptr->state == HELP_STATE_INACTIVE && help_state_ptr->cur == -1 && music_stream_state.secondary.handle == 0 && music_stream_state.queued_secondary_track == help_state_ptr->cur && D_00141968_00203908[help_record_index].id != 0xFFFF) { From f6e53181106e302435d370d199ae4b988ef33f59 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:47:33 +0000 Subject: [PATCH 0415/1502] decomp: clarify names in count_group_puffoids_in_states_13_to_17 domain_0_value_13 -> PUFFOID_STATE_CARRIER_JUMP: Retail 0x003160dc computes a group-listed Moby address; 0x003160e0-0x003160e4 filters its oclass at +0xA6 to 0x4DE, then 0x003160ec reads that same Moby's state byte at +0x20 and 0x003160f0 compares against 13. Thus the selector is the Puffoid current-state domain, not HeroStateId. In the bound puffoid.c, puffoid_update names state 13 PUFFOID_STATE_CARRIER_JUMP; its wait-for-carrier-jump branch assigns 0xD after computing the carrier-relative landing destination and jump velocity. The state-13 handler applies jump velocity and carrier displacement and transitions to carrier idle on landing. Reuse that established member for the inclusive lower bound. domain_1_value_18 -> PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK: Retail 0x003160e0-0x003160ec checks class 0x4DE and loads that listed Puffoid Moby's current state at +0x20. At 0x003160fc-0x0031610c, only states below 18 increment the count. The bound puffoid_update enum names state 18 PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK; its handler follows the carrier, processes knockback motion, then spawns an explosion and removes the Moby on completion. update_puffoid_damage_and_path_goal assigns 0x12 in its death-response branch for carrier-domain states. This establishes the Puffoid state domain independently of equal-valued Hero constants and proves the canonical name for this exclusive upper bound. --- src/overlays/l11/mobys/puffoid.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l11/mobys/puffoid.c b/src/overlays/l11/mobys/puffoid.c index 7582488221..be613c7b2f 100644 --- a/src/overlays/l11/mobys/puffoid.c +++ b/src/overlays/l11/mobys/puffoid.c @@ -942,6 +942,10 @@ extern short *D_L11_001AC240[]; short count_group_puffoids_in_states_13_to_17(struct Moby *self) __asm__("FUN_L11_00316090"); short count_group_puffoids_in_states_13_to_17(struct Moby *group_source_moby) { + enum { + PUFFOID_STATE_CARRIER_JUMP = 13, + PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK = 18 + }; unsigned short *moby_list_entry; short matching_moby_count; char *level_moby_array_base; @@ -957,8 +961,8 @@ short count_group_puffoids_in_states_13_to_17(struct Moby *group_source_moby) { struct Moby *moby = (struct Moby *)(level_moby_array_base + ((*moby_list_entry & 0x7FFF) << 8)); if (moby->oclass == 0x4DE) { - if (moby->state >= 13) { - if (moby->state < 18) + if (moby->state >= PUFFOID_STATE_CARRIER_JUMP) { + if (moby->state < PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK) matching_moby_count++; } } From e897803092eeb097548b0108b7cdae63b3772607 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:49:28 +0000 Subject: [PATCH 0416/1502] decomp: clarify names in activate_drek_boss_class_0565_moby domain_0_value_1 -> FALLING_MOBY_GROUP_AWAIT_ACTIVATION: Retail 0x002f1c50-0x002f1c64 checks class +0xA6 == 0x565 and moby state byte +0x20 == 1 before activation. The authoritative source reset_drek_boss_falling_moby_group sets this same class's state to existing FALLING_MOBY_GROUP_AWAIT_ACTIVATION = 1 and clears progress; update_linked_moby_group_transform_and_fall initializes state 1. This is the waiting state consumed by this activation helper, not a hero enum. domain_1_value_2 -> MOBY_APPROACH_TARGET_TRANSFORM: Retail 0x002f1c9c-0x002f1ca4 stores 2 into the same class-0x565 moby state byte +0x20 after optional transform-bound marking. The authoritative same-class update_linked_moby_group_transform_and_fall already names its state-2 case MOBY_APPROACH_TARGET_TRANSFORM: it advances progress f330 toward 2.0 and lerps moby position/rotation toward the indexed target transform. The activation assignment enters that existing state domain and behavior. --- src/overlays/l18/mobys/falling_moby_group.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/falling_moby_group.c b/src/overlays/l18/mobys/falling_moby_group.c index 10afb715b1..3087292269 100644 --- a/src/overlays/l18/mobys/falling_moby_group.c +++ b/src/overlays/l18/mobys/falling_moby_group.c @@ -251,14 +251,18 @@ extern void mark_block_entries_within_transform_xy_bounds(int, int) __asm__("FUN void activate_drek_boss_class_0565_moby(struct Moby *moby) __asm__("FUN_L18_002f1c38"); void activate_drek_boss_class_0565_moby(struct Moby *moby) { + enum { + FALLING_MOBY_GROUP_AWAIT_ACTIVATION = 1, + MOBY_APPROACH_TARGET_TRANSFORM = 2 + }; char *state = (char *)moby->pvars; - if (moby->oclass == 0x565 && moby->state == 1) { + if (moby->oclass == 0x565 && moby->state == FALLING_MOBY_GROUP_AWAIT_ACTIVATION) { if (*(int *)(state + 0xC) != -1) { mark_block_entries_within_transform_xy_bounds(0x802, *(int *)(state + 0xC)); mark_block_entries_within_transform_xy_bounds(0x908, *(int *)(state + 0xC)); mark_block_entries_within_transform_xy_bounds(0x954, *(int *)(state + 0xC)); } - moby->state = 2; + moby->state = MOBY_APPROACH_TARGET_TRANSFORM; set_group_child_carrier_byte_bc(moby->group, 1); } } From 0d1dee2d8e0c4c542cdeb9f5a2d0161a37576565 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:49:28 +0000 Subject: [PATCH 0417/1502] decomp: clarify names in refresh_moby_position_and_activate domain_0_value_0 -> STATE_TIMED_REMOVAL_WAIT: Retail 0x002ea1b8 loads the same Moby state byte at +0x20 and 0x002ea1bc gates activation on zero; original Ghidra tests *(char *)(param_2+0x20)==0. The authoritative source's electric-ball updater switches on MOBY(moby)->state and names 0 STATE_TIMED_REMOVAL_WAIT, decrementing the pvars+0x28 timer before removal. This assigned function refreshes that exact pvars+0x28 timer at 0x002ea1ac. The checked boss caller passes its electric-ball handle boss_data->f33C to this activation function, proving the electric-ball state domain rather than any hero domain. domain_1_value_1 -> STATE_TRAVEL_TO_TARGET: Retail 0x002ea1c4-0x002ea1c8 writes 1 to the Moby state byte at +0x20, then clears pvars+0x28 and copies the a2 target quad into pvars at 0x002ea1cc-0x002ea1d4, also present in original Ghidra. The authoritative electric-ball updater names this same moby->state value 1 STATE_TRAVEL_TO_TARGET and subtracts the Moby position from the vector at pvars base, moves toward it and explodes on arrival. The supplied boss caller activates boss_data->f33C with a target vector and active=1, tying this transition and the updater to the same electric-ball state domain. --- src/overlays/l18/mobys/drek_boss_electric_ball.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/drek_boss_electric_ball.c b/src/overlays/l18/mobys/drek_boss_electric_ball.c index b732da847a..faab9603ae 100644 --- a/src/overlays/l18/mobys/drek_boss_electric_ball.c +++ b/src/overlays/l18/mobys/drek_boss_electric_ball.c @@ -145,12 +145,16 @@ void refresh_moby_position_and_activate(struct Moby *moby, void refresh_moby_position_and_activate( struct Moby *moby, void *moby_position, void *position, int active, float speed) { + enum { + STATE_TIMED_REMOVAL_WAIT = 0, + STATE_TRAVEL_TO_TARGET = 1 + }; char *refreshed_moby_private_vars = (char *)moby->pvars; qcopy(&moby->pos, moby_position); *(int *)(refreshed_moby_private_vars + 0x28) = scale_game_frames(5); *(float *)(refreshed_moby_private_vars + 0x24) = speed; - if (active && moby->state == 0) { - moby->state = 1; + if (active && moby->state == STATE_TIMED_REMOVAL_WAIT) { + moby->state = STATE_TRAVEL_TO_TARGET; *(int *)(refreshed_moby_private_vars + 0x28) = 0; qcopy(refreshed_moby_private_vars, position); } From 6d65fb03d9a5d8fd6dba2009d6b8cb415bdf737b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:49:28 +0000 Subject: [PATCH 0418/1502] decomp: clarify names in sceDmaPause domain_0_value_0 -> FALSE: The source state = DIntr() corresponds to jal 0x0011d660 at 0x00123360 and move a3,v0 at 0x00123368. Helper 0x0011d660 reads COP0 Status, masks bit 16 at 0x0011d668, and sltu a0,zero,v1 at 0x0011d670 produces the Boolean prior-enable flag; it returns that saved flag at 0x0011d698 or explicit zero at 0x0011d69c..0x0011d6a4. The caller's beq a3,zero at 0x001233c0 skips EnableInterrupts at 0x001233c8 when the Boolean is false. Thus the listed state != 0 comparison belongs to the Boolean domain and can reuse existing FALSE=0, rather than NULL or a device-state enum. --- src/sdk/dma/sce_dma_pause.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdk/dma/sce_dma_pause.c b/src/sdk/dma/sce_dma_pause.c index 9081690a2c..d9427879f4 100644 --- a/src/sdk/dma/sce_dma_pause.c +++ b/src/sdk/dma/sce_dma_pause.c @@ -20,7 +20,7 @@ s32 sceDmaPause(volatile u32 *chcr) { masked = chan & 0xFFFFFEFF; *chcr = masked; *(volatile u32 *)0x1000F590 = ctrl; - if (state != 0) { + if (state != FALSE) { EnableInterrupts(masked, dstat, ctrl, state); } return chan; From b089d28335d6b019bc3ab842613be7de0ad9c58e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:49:28 +0000 Subject: [PATCH 0419/1502] decomp: clarify names in update_cutscene_camera_target domain_0_value_1 -> MOBY_CONDITIONAL_CAMERA_TARGET_UPDATE: In the bound source snapshot, initialization assigns 1 to moby->state, the identical selector whose existing case MOBY_CONDITIONAL_CAMERA_TARGET_UPDATE equals 1. Retail 00309354 loads this byte from a0+0x20; 00309374 loads 1 and 00309378 stores it to that same byte. Retail 0030935c/00309360 dispatches state 1 to 00309384, whose gates at 00309388-003093c0 conditionally reach cutscene_set_camera_target at 003093c8. The original Ghidra decompilation likewise stores 1 at param_1+0x20 and tests that same field for 1 before the gated call. This proves reuse of the established member in the same state domain, rather than identifying a separate control value. --- src/overlays/l06/mobys/cutscene_camera_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l06/mobys/cutscene_camera_target.c b/src/overlays/l06/mobys/cutscene_camera_target.c index 7c01203c8b..50b6a6deae 100644 --- a/src/overlays/l06/mobys/cutscene_camera_target.c +++ b/src/overlays/l06/mobys/cutscene_camera_target.c @@ -23,7 +23,7 @@ void cutscene_camera_target_update(struct Moby *moby) { switch (moby->state) { case MOBY_INITIALIZE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = MOBY_CONDITIONAL_CAMERA_TARGET_UPDATE; break; case MOBY_CONDITIONAL_CAMERA_TARGET_UPDATE: if (D_L06_0015F5C4 == 2) { From af4d6b28c0894350325ce41047d864a4512124fd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:49:29 +0000 Subject: [PATCH 0420/1502] decomp: clarify names in update_cutscene_camera_target domain_0_value_1 -> DISPATCH_PHASE_SELECTED_MOBY: Retail 003094a8 loads the moby's unsigned state byte at +0x20; 003094b0/003094b4 compare that byte to 1 and dispatch to 003094d8. Initialization at 003094c8/003094cc writes 1 to that identical byte. The authoritative C already names this same switch selector's case 1 DISPATCH_PHASE_SELECTED_MOBY, whose branch gates on D_L12_0015F5C4 and dispatches the phase-selected moby at 00309524/00309528. Thus the assignment enters that existing local state domain and must reuse its canonical member. --- src/overlays/l12/mobys/cutscene_camera_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l12/mobys/cutscene_camera_target.c b/src/overlays/l12/mobys/cutscene_camera_target.c index b4adeee019..95b65a1fab 100644 --- a/src/overlays/l12/mobys/cutscene_camera_target.c +++ b/src/overlays/l12/mobys/cutscene_camera_target.c @@ -46,7 +46,7 @@ void cutscene_camera_target_update(struct Moby *moby) { switch (moby->state) { case INITIALIZE_UPDATE_DISTANCE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = DISPATCH_PHASE_SELECTED_MOBY; break; case DISPATCH_PHASE_SELECTED_MOBY: if (D_L12_0015F5C4 == 2) { From 7a2798dad80ad19968660231a5d636170741aa30 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:49:29 +0000 Subject: [PATCH 0421/1502] decomp: clarify names in queue_preview_animation domain_0_value_0 -> PREVIEW_REQUEST_INITIAL: Authoritative queue_preview_animation source (SHA-256 b2b6b24febaa2779276f1c59d4029725e26d9d5d092e0b33ead395041d823db1) assigns request->status = 0 only on successful append. Retail 0x002265dc loads the queue count, 0x002265e4/0x002265e8 rejects count >= 8, 0x002265f8 multiplies the old count by the 0x38-byte request stride, 0x00226604 increments the count, and 0x00226614 forms the new slot at 0x001d5ec0. Retail 0x00226618..0x00226660 stores the request fields, with 0x00226658 sw zero,0(v1) initializing its status. Thus zero is the initial status of an appended preview request; it is not trigger_mode, which is separately stored at +8 at 0x0022661c. Supplied original retail Ghidra agrees and identifies initial/follow-up calls from load_hand_gadget at 0x00224a8c and 0x00224adc. INITIAL deliberately claims only this directly proven initialization role. --- src/ui/menus/item_preview/queue_preview_animation.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/menus/item_preview/queue_preview_animation.c b/src/ui/menus/item_preview/queue_preview_animation.c index bf37be36b5..9eeaf3b83e 100644 --- a/src/ui/menus/item_preview/queue_preview_animation.c +++ b/src/ui/menus/item_preview/queue_preview_animation.c @@ -30,6 +30,9 @@ s32 queue_preview_animation(s32 animation_id, s32 resource_first, s32 resource_count) { + enum { + PREVIEW_REQUEST_INITIAL = 0 + }; PreviewAnimationRequest *request; s32 request_index; @@ -39,7 +42,7 @@ s32 queue_preview_animation(s32 animation_id, } preview_request_count = request_index + 1; request = &preview_animation_requests[request_index]; - request->status = 0; + request->status = PREVIEW_REQUEST_INITIAL; request->animation_id = animation_id; request->trigger_mode = trigger_mode; request->delay_frames = delay_frames; From 91d15255aa7568649a2061de50ee57787a696b4d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:51:28 +0000 Subject: [PATCH 0422/1502] decomp: clarify names in snd_stream_safe_cd_sync domain_0_value_1 -> SND_CD_SYNC_NONBLOCKING: Retail 0x0012ee1c preserves the input mode in s0. After 0x0012ee40-0x0012ee48 tests whether sound_read_work.read_active is zero, 0x0012ee50 compares s0 with 1 and 0x0012ee58-0x0012ee5c returns 1 immediately when busy. Other modes reach the service/FlushCache/recheck loop at 0x0012ee70-0x0012ee88. The supplied sceCdSync source also treats nonzero mode as a busy poll, while mode 0 waits; load_audio_bank_by_location calls this wrapper with 0 before resolving bank references. This proves value 1 is the nonblocking CD synchronization mode, rather than a boolean readiness constant. --- src/audio/streaming/safe_cd/snd_stream_safe_cd_sync.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/streaming/safe_cd/snd_stream_safe_cd_sync.c b/src/audio/streaming/safe_cd/snd_stream_safe_cd_sync.c index 13119d9638..1950675f50 100644 --- a/src/audio/streaming/safe_cd/snd_stream_safe_cd_sync.c +++ b/src/audio/streaming/safe_cd/snd_stream_safe_cd_sync.c @@ -10,6 +10,9 @@ extern void snd_flush_sound_commands(void) __asm__("func_0012DC80"); s32 snd_stream_safe_cd_sync(s32 mode) __asm__("FUN_0012ee08"); s32 snd_stream_safe_cd_sync(s32 mode) { + enum { + SND_CD_SYNC_NONBLOCKING = 1 + }; s32 ready; s32 next_ready; if (snd_cd_stream_active == 0) { @@ -19,7 +22,7 @@ s32 snd_stream_safe_cd_sync(s32 mode) { ready = sound_read_work.read_active == 0; snd_cd_stream_end_pending = ready; if (ready != 1) { - if (mode == 1) { + if (mode == SND_CD_SYNC_NONBLOCKING) { return 1; } if (ready == 0) { From 7b502aae9c8702d2077a8d85e125dd397dd9ecb0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:51:28 +0000 Subject: [PATCH 0423/1502] decomp: clarify names in start_audio_stream_read domain_0_value_0 -> CD_READ_STATE_IDLE: Retail 0x002167b0 loads the halfword at music_stream_state+0x8, and 0x002167b4 rejects any nonzero state before the CD submission at 0x002167cc. The authoritative source identifies this field as read_state. Supplied music_update clears this same field to 0 after snd_stream_safe_cd_sync(1) reports completion, and clears it before retrying a pending request. Thus 0 denotes the idle CD-read request state, not a generic boolean. domain_1_value_1 -> CD_READ_STATE_ACTIVE: Retail 0x002167d4 branches to the diagnostic/trap path if the CD submission returns zero; its delay slot at 0x002167d8 loads 1. Only the successful submission path reaches 0x002167e0, which stores that 1 to the same read_state halfword at state+0x8 while retaining destination, sector and sector_count at +0x14, +0xc and +0x10. The entry guard then rejects this nonzero state. This proves 1 is the active submitted CD-read request state. --- src/audio/streaming/start_audio_stream_read.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/audio/streaming/start_audio_stream_read.c b/src/audio/streaming/start_audio_stream_read.c index 537a4f85e8..3f0578b7ab 100644 --- a/src/audio/streaming/start_audio_stream_read.c +++ b/src/audio/streaming/start_audio_stream_read.c @@ -8,11 +8,15 @@ extern s32 snd_stream_safe_cd_read() __asm__("func_0012ED58"); s32 start_audio_stream_read(s32 dst, s32 sector, s32 sector_count) __asm__("FUN_00216788"); s32 start_audio_stream_read(s32 read_destination, s32 sector, s32 sector_count) { - if ((music_stream_state.read_state == 0) && (sector_count != 0)) { + enum { + CD_READ_STATE_IDLE = 0, + CD_READ_STATE_ACTIVE = 1 + }; + if ((music_stream_state.read_state == CD_READ_STATE_IDLE) && (sector_count != 0)) { if (snd_stream_safe_cd_read( sector, sector_count, read_destination, &music_stream_state.cd_mode) != 0) { music_stream_state.read_dst = read_destination; - music_stream_state.read_state = 1; + music_stream_state.read_state = CD_READ_STATE_ACTIVE; music_stream_state.read_sector = sector; music_stream_state.read_sector_count = sector_count; return sector_count << 0xB; From b757b50c0d09ac597421190aa1e11a2f9abb4f7c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:51:28 +0000 Subject: [PATCH 0424/1502] decomp: clarify names in start_memory_card_save domain_0_value_0 -> MEMCARD_QUERY_INFO: Retail 0x00226adc loads memory_card_state+0xdc (pending_state); 0x00226ae0 bgez skips enqueueing when that pending operation is nonnegative. Original Ghidra names the same storage g_nPendingMemoryCardOperationState. The supplied memory_card_state.h declaration context explicitly assigns state/pending_state to MemoryCardOperation, whose canonical zero member is MEMCARD_QUERY_INFO. Here it supplies the lower boundary of valid operations, not a query request. domain_1_value_19 -> MEMCARD_BEGIN_WRITE_FULL_SAVE: After memcard_make_whole_save(save_data) at 0x00226aac, retail stores the save buffer at memory_card_state+0xec and checks pending operation +0xdc. If negative, 0x00226ae8 loads 0x13, 0x00226aec selects pending card zero, and 0x00226af0 stores 0x13 into that pending operation. The caller saving_data_menu2 invokes start_memory_card_save then waits for pending_state to become negative. Header context proves this field uses MemoryCardOperation; its canonical 19 member MEMCARD_BEGIN_WRITE_FULL_SAVE matches this enqueue of a complete-save write, rather than the unrelated create-step 19. --- src/ui/menus/save_data/start_memory_card_save.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/menus/save_data/start_memory_card_save.c b/src/ui/menus/save_data/start_memory_card_save.c index 4c8826c287..29d466bb59 100644 --- a/src/ui/menus/save_data/start_memory_card_save.c +++ b/src/ui/menus/save_data/start_memory_card_save.c @@ -20,8 +20,8 @@ void start_memory_card_save(s32 save_data, s32 slot) { *(s32 *)((u8 *)&memory_card_state + slot * 0x1C + 0x20) = 0; memory_card_state.unkF4 = 1; memory_card_state.buf = save_data; - if (memory_card_state.pending_state < 0) { + if (memory_card_state.pending_state < MEMCARD_QUERY_INFO) { memory_card_state.pending_card = 0; - memory_card_state.pending_state = 0x13; + memory_card_state.pending_state = MEMCARD_BEGIN_WRITE_FULL_SAVE; } } From 3dceb55e5c8b8060bb631ee067db57dec3f4c3df Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:51:29 +0000 Subject: [PATCH 0425/1502] decomp: clarify names in begin_sand_shark_return_home_if_outside_path domain_0_value_18 -> SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET: Retail 0x002d63d4 preserves the same moby argument; 0x002d63f8 tests its position at +0x10 against the configured path, and outside (zero) at 0x002d6400 leads to li 0x12 at 0x002d6408 and sb to moby state +0x20 at 0x002d6414. The supplied original Ghidra decompilation confirms this assignment. The supplied sand_shark_update caller passes this same moby after approach movement and switches on moby->state. Its established member SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET=18 shares the ground-alignment handler with 17: add sand_shark_height_offset_gp, probe ground, clamp to home height, approach that height, then the non-17 branch enters state 23 (SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET), whose destination is pvars->home. This proves the sand shark state domain and the existing member's applicability, independently of equal-valued hero states. --- src/overlays/l02/mobys/sand_shark.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l02/mobys/sand_shark.c b/src/overlays/l02/mobys/sand_shark.c index be7b0442fe..960d04d35b 100644 --- a/src/overlays/l02/mobys/sand_shark.c +++ b/src/overlays/l02/mobys/sand_shark.c @@ -1403,10 +1403,13 @@ extern int point_in_path_xy(void *, void *, int) __asm__("FUN_L00_00259740"); void begin_sand_shark_return_home_if_outside_path(struct Moby *moby) __asm__("FUN_L02_002d63c0"); void begin_sand_shark_return_home_if_outside_path(struct Moby *moby) { + enum { + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET = 0x12 + }; char *sand_shark_instance_vars = (char *)moby->pvars; char *configured_path = D_L02_001B0AB0[*(int *)(sand_shark_instance_vars + 0x290)]; if (point_in_path_xy(&moby->pos, configured_path + 0x10, *(int *)configured_path) == 0) { - moby->state = 0x12; + moby->state = SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET; if (moby->prev_seq) { blend_moby_animation(moby, 0, 0, scale_game_frames(20)); } From 7bf0638004c02cc3aa52b10b7f2d0aa6cda047d9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:51:29 +0000 Subject: [PATCH 0426/1502] decomp: clarify names in update_cutscene_camera_target domain_0_value_1 -> MODE_SLOT_STATE_DISPATCH_SELECTED_SLOT: Retail 0x002e53a8 reads the Moby state byte at a0+0x20. The zero-state branch writes 1 back to that same byte at 0x002e53c8-0x002e53cc and sets update_dist at +0x30. On subsequent updates 0x002e53b0-0x002e53b4 compares this same state byte to 1 and branches into the slot-dispatch path 0x002e53d8-0x002e542c. The authoritative function already labels that same switch(moby->state) branch MODE_SLOT_STATE_DISPATCH_SELECTED_SLOT = 1, proving the assignment enters this existing named state rather than the distinct mission-mode domain. --- src/overlays/l04/mobys/cutscene_camera_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l04/mobys/cutscene_camera_target.c b/src/overlays/l04/mobys/cutscene_camera_target.c index 220c606128..33c7d70b60 100644 --- a/src/overlays/l04/mobys/cutscene_camera_target.c +++ b/src/overlays/l04/mobys/cutscene_camera_target.c @@ -29,7 +29,7 @@ void cutscene_camera_target_update(struct Moby *moby) { switch (moby->state) { case MODE_SLOT_STATE_INITIALIZE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = MODE_SLOT_STATE_DISPATCH_SELECTED_SLOT; break; case MODE_SLOT_STATE_DISPATCH_SELECTED_SLOT: if (D_L04_0015F5C4 == 2) { From 190578af09e3bfc3563d53d7d95309f1d564d332 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:51:29 +0000 Subject: [PATCH 0427/1502] decomp: clarify names in sceCdSync domain_0_value_0 -> CD_SYNC_BLOCKING: The selector is sceCdSync's mode parameter, tested by retail 0x00120c3c (bne a0,zero,0x00120c94). Zero falls through to the blocking path: 0x00120c70 checks cd_read_pending, 0x00120c7c calls SceSifCheckStatRpc with cd_ncmd_client, and either pending result branches to 0x00120c68 to delay 0x3c ticks before retrying. Only when both clear does 0x00120c88 return zero. Nonzero mode instead performs one busy check at 0x00120c94-0x00120cb8. The supplied original Ghidra decompilation identifies zero as blocking; cd_check_ncmd uses sceCdSync(1) as a one-shot busy test. Thus zero specifically names the CD synchronization blocking mode, rather than a boolean or pointer constant. --- src/sdk/storage/cdvd/scecdsync.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/storage/cdvd/scecdsync.c b/src/sdk/storage/cdvd/scecdsync.c index fb725b1362..fe78be4be0 100644 --- a/src/sdk/storage/cdvd/scecdsync.c +++ b/src/sdk/storage/cdvd/scecdsync.c @@ -7,7 +7,10 @@ extern u8 cd_sync_wait_debug_message[] __asm__("D_00152EF0"); s32 sceCdSync(s32 mode) { - if (mode == 0) { + enum { + CD_SYNC_BLOCKING = 0 + }; + if (mode == CD_SYNC_BLOCKING) { if (cd_debug > 0) { scePrintf(cd_sync_wait_debug_message); } From 90a0de94af8606fca790bd70686758488ddeaff4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:51:29 +0000 Subject: [PATCH 0428/1502] decomp: clarify names in process_hoven_anklebiter_suck_cannon_suction domain_0_value_9 -> ANKLEBITER_DORMANT: Retail 0x002e16d0 loads the moby's state byte at +0x20 and 0x002e16d4 rejects 9. The authoritative same-class update_hoven_anklebiter enum names 9 ANKLEBITER_DORMANT; initialization assigns 9 when data->sleep is set, disables collision, and its dormant branch activates into 13. This is the anklebiter state domain, not HeroStateId. domain_1_value_11 -> ANKLEBITER_WAIT_FOR_LEAP_TRIGGER: Retail 0x002e16d8-0x002e16dc compares the same moby +0x20 state byte with 11 and rejects suction. The supplied update_hoven_anklebiter defines 11 as ANKLEBITER_WAIT_FOR_LEAP_TRIGGER; that branch faces home and waits for target range or proximity 2 before setting up a leap and state 12. domain_2_value_13 -> ANKLEBITER_ACTIVATE_FROM_DORMANCY: Retail 0x002e16e0-0x002e16e4 rejects state 13 from the same +0x20 state byte. The supplied same-class update handler names 13 ANKLEBITER_ACTIVATE_FROM_DORMANCY; dormant state 9 enters it with animation 7 and sparks, and its branch restores collision before transitioning to pursuit when animation completes. domain_3_value_8 -> ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME: Retail 0x002e16f4 calls the established suction processor with this moby, preserves its result in s1, and on nonzero result loads 8 at 0x002e1720 and stores it to moby +0x20 at 0x002e1738. The supplied same-class store/cancel callbacks and update handler name this exact state ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME; the update branch services controlled motion then enters return-home state 6. domain_4_value_8 -> ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME: When the suction result is zero, retail 0x002e1724-0x002e172c reloads moby +0x20 and tests for 8 before restoring 1. This compares the same state assigned by the active branch, so it reuses ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME, already established for state 8 in the authoritative anklebiter store/cancel callbacks and update handler. domain_5_value_1 -> ANKLEBITER_IDLE: Retail 0x002e1734 loads 1 and 0x002e1738 stores it to moby +0x20 only when suction returns zero and the prior state is 8. The authoritative same-class store callback performs the identical release transition with ANKLEBITER_IDLE = 1, and update_hoven_anklebiter names and implements state 1 as idle wandering and target detection. --- src/overlays/l12/mobys/hoven_anklebiter.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/overlays/l12/mobys/hoven_anklebiter.c b/src/overlays/l12/mobys/hoven_anklebiter.c index e5d42f8148..4af367ec8f 100644 --- a/src/overlays/l12/mobys/hoven_anklebiter.c +++ b/src/overlays/l12/mobys/hoven_anklebiter.c @@ -31,16 +31,23 @@ extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); int process_hoven_anklebiter_suck_cannon_suction(struct Moby *moby) __asm__("FUN_L12_002e16b8"); int process_hoven_anklebiter_suck_cannon_suction(struct Moby *moby) { + enum { + ANKLEBITER_IDLE = 1, + ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME = 8, + ANKLEBITER_DORMANT = 9, + ANKLEBITER_WAIT_FOR_LEAP_TRIGGER = 11, + ANKLEBITER_ACTIVATE_FROM_DORMANCY = 13 + }; int active; - if (moby->state == 9 || moby->state == 11 || moby->state == 13) + if (moby->state == ANKLEBITER_DORMANT || moby->state == ANKLEBITER_WAIT_FOR_LEAP_TRIGGER || moby->state == ANKLEBITER_ACTIVATE_FROM_DORMANCY) return 0; active = process_moby_suck_cannon_suction(moby); if (active) { if (moby->group != 0xFF) FUN_L01_0026e090(moby->group, 1); - moby->state = 8; - } else if (moby->state == 8) { - moby->state = 1; + moby->state = ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME; + } else if (moby->state == ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME) { + moby->state = ANKLEBITER_IDLE; } return active; } From 57df4ee72e73f8700aaf69fa30ab648283ad7e7f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:51:29 +0000 Subject: [PATCH 0429/1502] decomp: clarify names in gadgetron_sign_update domain_0_value_1 -> GADGETRON_SIGN_ROTATE: Source snapshot src/overlays/l16/mobys/gadgetron_sign.c (SHA-256 d72eb219c23da72254593a4adbad1bbf75b54143929b120a6814e74e57589635) declares GADGETRON_SIGN_ROTATE = 1 and uses it for switch(moby->state). Retail 0x002e8918 loads 1 and 0x002e8920 stores it to offset 0x20 of the same moby pointer read at 0x002e88e0. The comparison at 0x002e88ec dispatches that value to 0x002e8938-0x002e8958, which updates rot.z via fast_add_rotations with frame_time * -0.2617994. Original Ghidra confirms the same state-byte write and rotation branch; this assignment therefore enters the existing GADGETRON_SIGN_ROTATE state. --- src/overlays/l16/mobys/gadgetron_sign.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/gadgetron_sign.c b/src/overlays/l16/mobys/gadgetron_sign.c index 8935362214..f53acfcf6d 100644 --- a/src/overlays/l16/mobys/gadgetron_sign.c +++ b/src/overlays/l16/mobys/gadgetron_sign.c @@ -53,7 +53,7 @@ void gadgetron_sign_update(struct Moby *moby) { float size = moby->scale * 4.0f; int ff = 0xFF; int twohundred = 0x200; - moby->state = 1; + moby->state = GADGETRON_SIGN_ROTATE; moby->update_dist = ff; moby->draw_dist = twohundred; moby->pos.z = 160.0f; From e4f3473ee3459a99e457d80a5fe79627188215d2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:53:19 +0000 Subject: [PATCH 0430/1502] decomp: clarify names in copy_pokitaru_pvar_to_hero domain_0_value_1 -> MOBY_COPY_PVAR_TO_HERO: Retail 002f335c loads moby->state from a1+0x20; 002f3368/002f336c dispatch value 1 to 002f33ac. Initialization loads v1=1 at 002f3380 and stores it to the same a1+0x20 field at 002f338c. That destination state executes the guarded pvar halfword copy at 002f33dc/002f33e0. The authoritative C already names this exact switch case MOBY_COPY_PVAR_TO_HERO=1, proving reuse for the assignment in the same selector domain. --- src/overlays/l11/mobys/hero_path_constraint_trigger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/hero_path_constraint_trigger.c b/src/overlays/l11/mobys/hero_path_constraint_trigger.c index 9824aaa05d..89f7803aa2 100644 --- a/src/overlays/l11/mobys/hero_path_constraint_trigger.c +++ b/src/overlays/l11/mobys/hero_path_constraint_trigger.c @@ -19,7 +19,7 @@ void hero_path_constraint_trigger_update(struct Moby *moby) { switch (moby->state) { case MOBY_INITIALIZE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = MOBY_COPY_PVAR_TO_HERO; if (*(int *)state == -1) mark_moby_for_removal(moby); break; From db2b5592916d9bac0e51c8724ae7745243d76f2e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:53:19 +0000 Subject: [PATCH 0431/1502] decomp: clarify names in update_moby_translation_delta_matrix domain_0_value_0 -> MOBY_TRANSLATION_DELTA_STATE_INITIALIZE: The selector is MOBY(moby)->state: retail 0x002d35d4 loads the byte at moby+0x20 and 0x002d35d8 skips the branch when nonzero. On zero, 0x002d35e8-0x002d35fc initialize pvars+0x20/+0x24/+0x28/+0x3e and copy the hero field; 0x002d3600-0x002d3604 then store state 1. Thus zero selects initialization in update_moby_translation_delta_matrix, rather than a Boolean or pointer domain. --- src/overlays/l04/mobys/translation_delta_matrix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l04/mobys/translation_delta_matrix.c b/src/overlays/l04/mobys/translation_delta_matrix.c index 701d7c3d07..0eb221df20 100644 --- a/src/overlays/l04/mobys/translation_delta_matrix.c +++ b/src/overlays/l04/mobys/translation_delta_matrix.c @@ -14,12 +14,12 @@ void translation_delta_matrix_update(char *moby) __asm__("FUN_L04_002d3580"); /* Moby class 584 */ void translation_delta_matrix_update(char *moby) { - char *moby_vars = ((char *)MOBY(moby)->pvars); + enum { MOBY_TRANSLATION_DELTA_STATE_INITIALIZE = 0 } ;char *moby_vars = ((char *)MOBY(moby)->pvars); float position_delta[4]; fast_vec_sub(position_delta, moby + 0x10, moby_vars + 0xA0); update_entity_matrix(moby_vars + 0x60, position_delta, moby + 0x40, moby + 0x40); qcopy(moby_vars + 0xA0, moby + 0x10); - if (MOBY(moby)->state == 0) { + if (MOBY(moby)->state == MOBY_TRANSLATION_DELTA_STATE_INITIALIZE) { *(int *)(moby_vars + 0x20) = 0; *(short *)(moby_vars + 0x24) = 0; moby_vars[0x28] = 4; From bc09836e84525f26cf6626b95b18183c6b9cb5f2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:53:19 +0000 Subject: [PATCH 0432/1502] decomp: clarify names in update_cutscene_camera_target domain_0_value_1 -> MOBY_GUARDED_TABLE_CALL: The authoritative source switches on moby->state and already labels its value-1 branch MOBY_GUARDED_TABLE_CALL. Retail 0x002f2e80 loads the same state byte at a0+0x20; 0x002f2e88 and 0x002f2e8c select the value-1 branch at 0x002f2eb0. The initialization branch loads 1 at 0x002f2ea0 and stores it to that identical state byte at 0x002f2ea4. Original Ghidra likewise writes state 1 in the zero-state branch and tests that same field against 1 for the guarded call. Thus this assignment enters the existing enum member's exact selector domain, rather than an unrelated equal-valued control mode. --- src/overlays/l17/mobys/cutscene_camera_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l17/mobys/cutscene_camera_target.c b/src/overlays/l17/mobys/cutscene_camera_target.c index 837e590da0..fbccc91dfc 100644 --- a/src/overlays/l17/mobys/cutscene_camera_target.c +++ b/src/overlays/l17/mobys/cutscene_camera_target.c @@ -24,7 +24,7 @@ void cutscene_camera_target_update(struct Moby *moby) { switch (moby->state) { case MOBY_UPDATE_DISTANCE_INITIALIZE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = MOBY_GUARDED_TABLE_CALL; break; case MOBY_GUARDED_TABLE_CALL: if (D_L17_0015F5C4 == 2) { From 8ef8e302479d9bd5186b6e442f80e6b0543a07eb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:54:59 +0000 Subject: [PATCH 0433/1502] decomp: clarify names in sceMpegInit domain_0_value_0 -> FALSE: sceMpegInit calls DIntr at 0x0012b738 and tests its unchanged v0 against zero at 0x0012b7a4, skipping EnableInterrupts at 0x0012b7ac when false. Checked helper 0x0011d660 reads COP0 Status, masks 0x10000 at 0x0011d668, normalizes that prior bit with sltu a0,zero,v1 at 0x0011d670, and returns saved a0 at 0x0011d698 or explicit zero at 0x0011d69c..0x0011d6a4. Thus state is a boolean indicating interrupts were previously enabled; existing FALSE=0 is the canonical boolean zero, rather than NULL or an unrelated state ID. --- src/sdk/mpeg/api/sce_mpeg_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdk/mpeg/api/sce_mpeg_init.c b/src/sdk/mpeg/api/sce_mpeg_init.c index 14651b78ec..3be684fd01 100644 --- a/src/sdk/mpeg/api/sce_mpeg_init.c +++ b/src/sdk/mpeg/api/sce_mpeg_init.c @@ -11,7 +11,7 @@ void sceMpegInit(void) { *(volatile u32 *)0x1000B000 &= 0xFFFFFEFF; *(volatile u32 *)0x1000B400 &= 0xFFFFFEFF; *(volatile u32 *)0x1000F590 = *(volatile u32 *)0x1000F520 & 0xFFFEFFFF; - if (state != 0) { + if (state != FALSE) { EnableInterrupts(); } *(volatile u32 *)0x1000B020 = 0; From de381cea098edda59e22569652b41272bd774f36 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:54:59 +0000 Subject: [PATCH 0434/1502] decomp: clarify names in update_audio_stream_until_idle domain_0_value_0 -> AUDIO_STREAM_READ_IDLE: At retail 0x002168c4 the signed halfword at 0x001516d8 (music_stream_state.read_state in the bound C snapshot) is loaded; 0x002168c8 branches directly to the return path when it is zero, skipping all read-service cycles. Original Ghidra tests g_cdReadState.nActive here. transition_load_wad calls this function with 1 after start_audio_stream_read and before decompress_wad, proving zero is the read-idle state. domain_1_value_0 -> AUDIO_STREAM_READ_IDLE: Retail 0x00216900 reloads the same signed read-state halfword at 0x001516d8 after music_update and the three sound service calls; 0x00216904 repeats the wait/service loop only while nonzero. Thus zero terminates waiting as the same idle state tested at 0x002168c8. The bound C do/while uses music_stream_state.read_state, and original Ghidra loops on g_cdReadState.nActive != 0. --- src/audio/streaming/update_audio_stream_until_idle.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/audio/streaming/update_audio_stream_until_idle.c b/src/audio/streaming/update_audio_stream_until_idle.c index 5b2e61c2ef..6e195dbb9b 100644 --- a/src/audio/streaming/update_audio_stream_until_idle.c +++ b/src/audio/streaming/update_audio_stream_until_idle.c @@ -10,15 +10,18 @@ extern s32 music_update() __asm__("func_00216290"); s16 update_audio_stream_until_idle(s32 wait_for_completion) __asm__("FUN_002168a8"); s16 update_audio_stream_until_idle(s32 wait_for_completion) { + enum { + AUDIO_STREAM_READ_IDLE = 0 + }; if (wait_for_completion != 0) { - if (music_stream_state.read_state != 0) { + if (music_stream_state.read_state != AUDIO_STREAM_READ_IDLE) { do { sceGsSyncV(0); music_update(); snd_reset_state_and_flush_commands(); snd_flush_sound_commands(); snd_hold_command_batches(); - } while (music_stream_state.read_state != 0); + } while (music_stream_state.read_state != AUDIO_STREAM_READ_IDLE); } } else { music_update(); From fd7cc90d760bfa9c7e497308ab9b163927a4c485 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:56:46 +0000 Subject: [PATCH 0435/1502] decomp: clarify names in launch_sand_shark domain_0_value_27 -> SAND_SHARK_LAUNCHED: Retail 0x002d611c loads 27 and 0x002d6154 stores it to moby+0x20, the source moby->state field, in established launch_sand_shark. Retail 0x002d6178..0x002d6188 copies the supplied launch position to moby+0x10 and launch velocity to pvars+0x40; 0x002d618c..0x002d6198 derives yaw from velocity XY. The supplied sand_shark_nest_update caller selects an inactive group sand shark, raises nest position by 1.5 Z, constructs XY launch speed 2*frame factor and upward speed 6*frame factor, then passes these to launch_sand_shark (retail caller call at 0x002dcde8 per prepared Ghidra annotation). Thus 27 names the launched sand shark moby state, not the nest's state or a control mode. --- src/overlays/l02/mobys/sand_shark_nest.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l02/mobys/sand_shark_nest.c b/src/overlays/l02/mobys/sand_shark_nest.c index 142905f17f..19c523f0cd 100644 --- a/src/overlays/l02/mobys/sand_shark_nest.c +++ b/src/overlays/l02/mobys/sand_shark_nest.c @@ -33,8 +33,11 @@ void launch_sand_shark(struct Moby *moby, float *direction) __asm__("FUN_L02_002d6118"); void launch_sand_shark(struct Moby *moby, void *position, float *direction) { + enum { + SAND_SHARK_LAUNCHED = 0x1B + }; char *sand_shark_vars = (char *)moby->pvars; - moby->state = 0x1B; + moby->state = SAND_SHARK_LAUNCHED; moby->flags &= 0xFFBE; if (moby->prev_seq != 0xB) { blend_moby_animation(moby, 0xB, 0, 1); From 5cc693d08bed86fb7b385fa5a9b77471fa0871c0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:58:33 +0000 Subject: [PATCH 0436/1502] decomp: clarify names in check_path_camera_priority domain_1_value_0 -> HERO_STATE_IDLE: Retail 0x003159a0 loads the signed camera descriptor+0x44 requirement into a1; 0x003159a4 bypasses it when negative. Otherwise 0x003159ac loads 0x001413d4, identified as hero.state.current by the authoritative source, and 0x003159b0 requires equality with a1. Thus required_hero_state belongs to HeroStateId, not control/vehicle/gravity modes. The supplied include/rnc/hero/hero_state.h HeroStateId domain canonically defines HERO_STATE_IDLE=0, which is the existing >=0 boundary; reuse preserves its signed lower-bound behavior. --- src/overlays/l14/path_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l14/path_camera.c b/src/overlays/l14/path_camera.c index 6469fafa94..b892296770 100644 --- a/src/overlays/l14/path_camera.c +++ b/src/overlays/l14/path_camera.c @@ -304,7 +304,7 @@ int check_path_camera_priority(char *camera, char *control_mode_gate_object) { if (required_control_mode >= 0 && hero.state.control_mode != required_control_mode) return 0; required_hero_state = *(int *)(rec + 0x44); - if (required_hero_state >= 0 && hero.state.current != required_hero_state) + if (required_hero_state >= HERO_STATE_IDLE && hero.state.current != required_hero_state) return 0; return 1; } From 6ca98c35f401738f19ec4176c1df20c88a5b0f6a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:58:33 +0000 Subject: [PATCH 0437/1502] decomp: clarify names in launch_suck_cannon_projectile_and_sync_moby_state domain_0_value_7 -> MOBY_STATE_SUCK_CANNON_LAUNCHED: The authoritative function launch_suck_cannon_projectile_and_sync_moby_state calls launch_suck_cannon_projectile. Retail 002f1d24 preserves incoming Moby a0 in s2; 002f1d58 calls launch helper 003044a0; 002f1d60 preserves its return in s0. At 002f1d64 a nonzero return branches to 002f1d7c with 7 loaded at 002f1d68, writing the Moby state byte at +0x20. The supplied launch helper returns 0 on missing/invalid projectile record and returns 2 after configuring projectile launch velocity, target and record state. Thus 7 represents the Moby's suck-cannon-launched state. On launch failure, 002f1d6c-002f1d7c restores 1 only if that same Moby state byte is 7, corroborating its launch-specific role; this is not record+0x68 state 6 or a control mode. --- src/overlays/shared/mobys/suck_cannon_methods.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/mobys/suck_cannon_methods.c b/src/overlays/shared/mobys/suck_cannon_methods.c index e83b3a78f3..cd1558262a 100644 --- a/src/overlays/shared/mobys/suck_cannon_methods.c +++ b/src/overlays/shared/mobys/suck_cannon_methods.c @@ -24,11 +24,14 @@ int launch_suck_cannon_projectile_and_sync_moby_state(struct Moby *moby, int position_source_moby, float position_z_offset) { + enum { + MOBY_STATE_SUCK_CANNON_LAUNCHED = 7 + }; char *callback_record = get_moby_suck_cannon_record(moby); int projectile_launch_result = launch_suck_cannon_projectile( moby, launch_data_source, position_source_moby, position_z_offset); if (projectile_launch_result != 0) { - moby->state = 7; + moby->state = MOBY_STATE_SUCK_CANNON_LAUNCHED; } else if ((unsigned char)((char)moby->state) == 7) { moby->state = 1; } From 1cc19084c881be08ae987ce0fd18ea38d784b872 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:58:33 +0000 Subject: [PATCH 0438/1502] decomp: clarify names in activate_teleporter_and_record_state domain_0_value_1 -> TELEPORTER_WAIT_FOR_USE: Retail 0x00308b48 loads 1 into t0; after reading group at moby+0x21 (0x00308bac), the 0xFF branch stores t0 to this same moby's state byte +0x20 at 0x00308bb4. Original Ghidra confirms this direct assignment. The authoritative teleporter_update source calls activate_teleporter_and_record_state(moby) on this teleporter and switches on the same moby->state, explicitly declaring TELEPORTER_WAIT_FOR_USE = 1. Its TELEPORTER_ENTER_WAIT_FOR_USE branch assigns 1 then falls into TELEPORTER_WAIT_FOR_USE, which checks hero ground contact and use input before assigning prepare-transfer state 2. Thus this assignment selects the established teleporter wait-for-use state; it is not a Hero state or a group-control domain inference. --- src/overlays/shared/props/teleporter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/props/teleporter.c b/src/overlays/shared/props/teleporter.c index d4424f95b3..76d4d8ded1 100644 --- a/src/overlays/shared/props/teleporter.c +++ b/src/overlays/shared/props/teleporter.c @@ -232,6 +232,9 @@ float D_L18_001621D0 = 1.0f; void activate_teleporter_and_record_state(struct Moby *moby) __asm__("FUN_L01_00308b28"); void activate_teleporter_and_record_state(struct Moby *moby) { + enum { + TELEPORTER_WAIT_FOR_USE = 1 + }; int level_bitset_byte_offset = D_0015ED84 << 8; unsigned char moby_group_index; *(int *)((u8 *)D_0014C190 + (((short)moby->save_id >> 5) * 4 + level_bitset_byte_offset)) |= @@ -241,7 +244,7 @@ void activate_teleporter_and_record_state(struct Moby *moby) { if (moby_group_index != 0xFF) set_moby_list_state((char *)moby_group_index, 1); else - moby->state = 1; + moby->state = TELEPORTER_WAIT_FOR_USE; } /* Ported from rac1-decomp (src/overlays/shared/vendor_002F7700.c: func_L01_00309FB0). */ From 136700aed2e4d1c655a55207942833cae6b3e854 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:58:33 +0000 Subject: [PATCH 0439/1502] decomp: clarify names in update_camera_blend domain_0_value_0 -> CAMERA_TRANSITION_PHASE_IDLE: Source SHA-256 c85417dfe945a26d59b614b857920ac35406232e7bc3972c6a7ba83378403d58 binds this token to *(short *)camera_transition_state = 0. Retail 0x001ed2c0 sets s1=0x001871b0, and 0x001ed2f0 skips cleanup while the selected solver returns zero. Only completion reaches sh zero,0(s1) at 0x001ed348, after conditional publication of all four target vectors. The supplied original Ghidra identifies this halfword as g_nCameraTransitionPhase and describes retaining pending controls until completion and then clearing the pending halfword. Supplied update_camera also clears the same halfword when resetting camera control for game_mode_macro==5. These reset/completion paths establish zero as the idle (no pending transition phase) value; sb zero,2(s1) separately clears the solver selector and is not the proposed token. --- src/camera/update_camera_blend.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/camera/update_camera_blend.c b/src/camera/update_camera_blend.c index 156aadb933..82e5588e7b 100644 --- a/src/camera/update_camera_blend.c +++ b/src/camera/update_camera_blend.c @@ -15,7 +15,7 @@ extern int step_camera_blend(void *, struct CameraBlend *) __asm__("func_001ECAF void update_camera_blend(char *to_cam) __asm__("FUN_001ed2b0"); void update_camera_blend(char *to_cam) { - struct CameraTransition *transition = &cam_trans_state; + enum { CAMERA_TRANSITION_PHASE_IDLE = 0 } ;struct CameraTransition *transition = &cam_trans_state; int transition_complete; if (transition->kind == 0) { @@ -30,7 +30,7 @@ void update_camera_blend(char *to_cam) { qcopy(camera_rows + 0x20, to_cam + 0x20); qcopy(camera_rows - 0x210, to_cam + 0x30); } - transition->mode = 0; + transition->mode = CAMERA_TRANSITION_PHASE_IDLE; transition->kind = 0; } } From 4d3df8414e3c83aa1fbfb3d6a09df053147a7fbf Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:58:33 +0000 Subject: [PATCH 0440/1502] decomp: clarify names in launch_circular_saw_enemy_from_suck_cannon domain_0_value_9 -> CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED: Retail 0x002c40dc preserves moby a0 in s2. The launch helper result saved at 0x002c4118 drives bne at 0x002c411c; li 9 at 0x002c4120 and sb at 0x002c4138 assign moby+0x20. In the authoritative same-class circular_saw_enemy_update source, this exact moby state domain already defines CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED=9: that case delegates to FUN_L00_002dc9f0(moby,data->fC0), and state 9 bypasses ordinary movement. launch_suck_cannon_projectile context writes launch record state 5/6 and returns 2 on success, establishing suck-cannon control rather than a hero state. domain_1_value_9 -> CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED: Retail lbu at 0x002c4124 reads +0x20 from s2 (moby a0 retained at 0x002c40dc); li 9 at 0x002c4128 and bnel at 0x002c412c test the very same state assigned on launch success at 0x002c4138. The authoritative circular_saw_enemy_update enum identifies this circular-saw moby state as CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED=9 and routes it through the suck-cannon update instead of ordinary movement. Reuse the same member for the comparison and assignment; record+0x68 and hero state domains are distinct. domain_2_value_1 -> CIRCULAR_SAW_STATE_IDLE: When launch helper returns zero and moby+0x20 equals 9, retail 0x002c4134 loads 1 and 0x002c4138 stores it into moby+0x20, owned by a0 preserved in s2 at 0x002c40dc. The same-class circular_saw_enemy_update source already defines CIRCULAR_SAW_STATE_IDLE=1 for its switch(moby->state). Its idle case performs update_object_wander_movement and waits for target detection before chase/melee transitions; hit recovery, jump completion and melee completion also return to state 1. This is the saw's idle state, not HERO_STATE_LOOK despite equal values. --- src/overlays/l04/mobys/circular_saw_enemy.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l04/mobys/circular_saw_enemy.c b/src/overlays/l04/mobys/circular_saw_enemy.c index d0b74ec705..bfd63fd354 100644 --- a/src/overlays/l04/mobys/circular_saw_enemy.c +++ b/src/overlays/l04/mobys/circular_saw_enemy.c @@ -1141,13 +1141,17 @@ int launch_circular_saw_enemy_from_suck_cannon(struct Moby *moby, int launch_position_source, float launch_position_offset) { + enum { + CIRCULAR_SAW_STATE_IDLE = 1, + CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED = 0x9 + }; char *moby_callback_result = get_moby_suck_cannon_record(moby); int hit_processing_result = launch_suck_cannon_projectile( moby, input_quad_address, launch_position_source, launch_position_offset); if (hit_processing_result != 0) { - moby->state = 0x9; - } else if ((unsigned char)moby->state == 0x9) { - moby->state = 1; + moby->state = CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED; + } else if ((unsigned char)moby->state == CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED) { + moby->state = CIRCULAR_SAW_STATE_IDLE; } if (*(short *)(moby_callback_result + 0x68) == 6) { allocate_voice_for_target_entry(1, 0, moby); From 6e0b8454334989dfc5ca62abf9831c3381066c03 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:58:33 +0000 Subject: [PATCH 0441/1502] decomp: clarify names in process_puffoid_suck_cannon_suction domain_0_value_2 -> PUFFOID_STATE_IDLE: Retail 0x00316180 reads the Puffoid moby's state byte at +0x20, and 0x0031617c/0x00316188 tests 2. The bound puffoid_update switches on this same moby->state and declares PUFFOID_STATE_IDLE=2; its branch selects chase or home wandering. This is the Puffoid state domain, not HeroStateId. domain_10_value_20 -> PUFFOID_STATE_WAIT_TO_RESUME_COMMAND: Retail 0x003161e4..0x003161ec tests the Puffoid state byte against 20 when suction returns zero; 0x003161f4/0x003161f8 restores command from +0xBC to +0x20. This is the same PUFFOID_STATE_WAIT_TO_RESUME_COMMAND=20 already named in puffoid_update and the adjacent storage callback. domain_1_value_4 -> PUFFOID_STATE_CHASE_TARGET: Retail 0x00316190/0x00316194 compares the +0x20 Puffoid state with 4. In the supplied puffoid_update, the same state selector names 4 PUFFOID_STATE_CHASE_TARGET and moves toward target->pos or enters spray attack on proximity. domain_2_value_5 -> PUFFOID_STATE_SPRAY_ATTACK: Retail 0x00316198/0x0031619c compares the Puffoid +0x20 state with 5. The supplied puffoid_update defines PUFFOID_STATE_SPRAY_ATTACK=5 for this same selector; that branch faces the target, plays the spray sound and returns to chase when distant. domain_3_value_6 -> PUFFOID_STATE_RETURN_HOME: Retail 0x003161a0/0x003161a4 tests the Puffoid state byte at +0x20 against 6. The same selector in puffoid_update declares PUFFOID_STATE_RETURN_HOME=6; that case moves toward puffoid_vars->home and enters idle on arrival. domain_4_value_14 -> PUFFOID_STATE_CARRIER_IDLE: Retail 0x003161a8/0x003161ac compares the Puffoid moby state at +0x20 with 14. The supplied puffoid_update names that state PUFFOID_STATE_CARRIER_IDLE and follows the carrier before optionally entering carrier chase; its carrier-jump landing assigns 0xE. domain_5_value_15 -> PUFFOID_STATE_CARRIER_CHASE_TARGET: Retail 0x003161b0/0x003161b4 compares the Puffoid +0x20 state with 15. The same state domain in puffoid_update declares PUFFOID_STATE_CARRIER_CHASE_TARGET=15; the case follows the carrier and moves toward target->pos, entering carrier spray at close range. domain_6_value_16 -> PUFFOID_STATE_CARRIER_SPRAY_ATTACK: Retail 0x003161b8/0x003161bc compares the Puffoid +0x20 state with 16. The supplied puffoid_update declares PUFFOID_STATE_CARRIER_SPRAY_ATTACK=16 on that selector; the branch follows the carrier, faces the target and plays the spray sound. domain_7_value_20 -> PUFFOID_STATE_WAIT_TO_RESUME_COMMAND: Retail 0x003161c0/0x003161c4 accepts Puffoid state 20 during nonzero suction. The supplied puffoid_update defines PUFFOID_STATE_WAIT_TO_RESUME_COMMAND=20 for this moby->state domain and its case restores moby->command. The adjacent suction-storage callback uses the same named state. domain_8_value_20 -> PUFFOID_STATE_WAIT_TO_RESUME_COMMAND: Retail 0x003161cc/0x003161d0 skips resaving when the Puffoid is already in state 20. Otherwise +0x20 is set to 20 and the prior state saved at +0xBC. This matches the existing PUFFOID_STATE_WAIT_TO_RESUME_COMMAND=20 case in puffoid_update, which restores command. domain_9_value_20 -> PUFFOID_STATE_WAIT_TO_RESUME_COMMAND: Retail 0x003161cc loads 20 and 0x003161d8 stores it to the Puffoid state at +0x20, with the old state saved to command at +0xBC by 0x003161e0. The same state field in puffoid_update names 20 PUFFOID_STATE_WAIT_TO_RESUME_COMMAND and restores command from that state. --- src/overlays/l11/mobys/puffoid.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/overlays/l11/mobys/puffoid.c b/src/overlays/l11/mobys/puffoid.c index be613c7b2f..8a88b3ce46 100644 --- a/src/overlays/l11/mobys/puffoid.c +++ b/src/overlays/l11/mobys/puffoid.c @@ -994,19 +994,29 @@ extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); int process_puffoid_suck_cannon_suction(struct Moby *moby) __asm__("FUN_L11_00316160"); int process_puffoid_suck_cannon_suction(struct Moby *moby) { + enum { + PUFFOID_STATE_IDLE = 2, + PUFFOID_STATE_CHASE_TARGET = 4, + PUFFOID_STATE_SPRAY_ATTACK = 5, + PUFFOID_STATE_RETURN_HOME = 6, + PUFFOID_STATE_CARRIER_IDLE = 0xE, + PUFFOID_STATE_CARRIER_CHASE_TARGET = 0xF, + PUFFOID_STATE_CARRIER_SPRAY_ATTACK = 0x10, + PUFFOID_STATE_WAIT_TO_RESUME_COMMAND = 0x14 + }; int grab_check_result = process_moby_suck_cannon_suction(moby); if (grab_check_result != 0) { - if (moby->state == 2 || moby->state == 4 || moby->state == 5 || moby->state == 6 || - moby->state == 0xE || moby->state == 0xF || moby->state == 0x10 || - moby->state == 0x14) { - if (moby->state != 0x14) { + if (moby->state == PUFFOID_STATE_IDLE || moby->state == PUFFOID_STATE_CHASE_TARGET || moby->state == PUFFOID_STATE_SPRAY_ATTACK || moby->state == PUFFOID_STATE_RETURN_HOME || + moby->state == PUFFOID_STATE_CARRIER_IDLE || moby->state == PUFFOID_STATE_CARRIER_CHASE_TARGET || moby->state == PUFFOID_STATE_CARRIER_SPRAY_ATTACK || + moby->state == PUFFOID_STATE_WAIT_TO_RESUME_COMMAND) { + if (moby->state != PUFFOID_STATE_WAIT_TO_RESUME_COMMAND) { moby->command = moby->state; - moby->state = 0x14; + moby->state = PUFFOID_STATE_WAIT_TO_RESUME_COMMAND; } } else { grab_check_result = 0; } - } else if (moby->state == 0x14) { + } else if (moby->state == PUFFOID_STATE_WAIT_TO_RESUME_COMMAND) { moby->state = moby->command; } return grab_check_result; From 59e07c02135e839f3bff260dfa32b71180510589 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:58:33 +0000 Subject: [PATCH 0442/1502] decomp: clarify names in launch_suck_cannon_projectile_and_update_moby_state domain_0_value_5 -> CHICKEN_STATE_EMIT_FEATHERS: Retail 0x002cae6c saves incoming moby in s2; 0x002caeac branches on the launch result and 0x002caeb0/0x002caec8 stores 5 to that moby's state byte +0x20 on success. The authoritative morphoray_chicken.c identifies these as chicken Suck Cannon methods; adjacent moby_set_state_from_check uses CHICKEN_STATE_EMIT_FEATHERS for the same moby-state transition on suction success. update_morphoray_chicken names state 5 CHICKEN_STATE_EMIT_FEATHERS and that branch builds feather positions/velocities and calls spawn_feather_moby. This reuses that established chicken moby-state meaning, not the separate record+0x68 launch mode. domain_1_value_1 -> CHICKEN_STATE_IDLE: Retail 0x002caeb4 loads state byte +0x20 from the incoming moby saved in s2; 0x002caebc checks 5 and 0x002caec4/0x002caec8 writes 1 when launch failed and the previous state was 5. The authoritative source's adjacent chicken suction wrapper names this same reset transition CHICKEN_STATE_EMIT_FEATHERS to CHICKEN_STATE_IDLE. spawn_morphoray_chicken initializes the created class 0x10E moby's state to CHICKEN_STATE_IDLE, while update_morphoray_chicken uses that state for idle animations before transitioning to turn/flee states. Thus 1 belongs to the chicken moby-state domain, not any equal-valued Hero mode. --- src/overlays/shared/weapons/morphoray_chicken.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/morphoray_chicken.c b/src/overlays/shared/weapons/morphoray_chicken.c index 8cabf9f513..11184db405 100644 --- a/src/overlays/shared/weapons/morphoray_chicken.c +++ b/src/overlays/shared/weapons/morphoray_chicken.c @@ -850,13 +850,17 @@ int launch_suck_cannon_projectile_and_update_moby_state(struct Moby *moby, int target_moby, float target_height_offset) { + enum { + CHICKEN_STATE_IDLE = 1, + CHICKEN_STATE_EMIT_FEATHERS = 5 + }; char *class_callback_data = get_moby_suck_cannon_record(moby); int projectile_launch_result = launch_suck_cannon_projectile( moby, launch_vector_address, target_moby, target_height_offset); if (projectile_launch_result != 0) { - moby->state = 5; + moby->state = CHICKEN_STATE_EMIT_FEATHERS; } else if ((unsigned char)((char)moby->state) == 5) { - moby->state = 1; + moby->state = CHICKEN_STATE_IDLE; } if (*(short *)(class_callback_data + 0x68) == 6) { allocate_voice_for_target_entry(1, 0, moby); From 48d6a8643dc4991e5778d018d8c9be9914149888 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:00:33 +0000 Subject: [PATCH 0443/1502] decomp: clarify names in prepare_save_game domain_0_value_0 -> MEMCARD_QUERY_INFO: The authoritative source binds card_state to &memory_card_state. Retail 0x002269c4/0x002269d8 forms that base as 0x0013d290; 0x00226a30 loads +0xdc and 0x00226a40 uses bgez to skip queueing when pending_state is nonnegative. Original Ghidra names this same storage g_nPendingMemoryCardOperationState. The supplied memory_card_state.h context explicitly assigns state/pending_state to MemoryCardOperation, whose canonical zero is MEMCARD_QUERY_INFO. Reuse that member as the zero boundary in pending_state < 0, without implying a query request. domain_1_value_19 -> MEMCARD_BEGIN_WRITE_FULL_SAVE: Retail 0x00226a28 calls memcard_make_whole_save with the saved first argument, 0x00226a38 stores its buffer at memory_card_state +0xec, and 0x00226a3c stores the requested save slot at +0x14. If pending_state at +0xdc is negative, 0x00226a48 loads 0x13 and 0x00226a50 stores it to that pending operation field, with pending_card cleared at 0x00226a4c. The supplied MemoryCardOperation declaration explicitly owns state/pending_state and names 19 MEMCARD_BEGIN_WRITE_FULL_SAVE; saving_data_menu calls this function to start its save. This is an operation request, not create-step 19. --- src/ui/menus/save_data/prepare_save_game.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/menus/save_data/prepare_save_game.c b/src/ui/menus/save_data/prepare_save_game.c index bfd2ab3092..bfd1c6dbce 100644 --- a/src/ui/menus/save_data/prepare_save_game.c +++ b/src/ui/menus/save_data/prepare_save_game.c @@ -29,9 +29,9 @@ void prepare_save_game(int save_data, int slot) { card_state->buf = (void *)save_data; card_state->card[0].save_index = slot; card_state->active_card = 0; - if (card_state->pending_state < 0) { + if (card_state->pending_state < MEMCARD_QUERY_INFO) { card_state->pending_card = 0; - card_state->pending_state = 0x13; + card_state->pending_state = MEMCARD_BEGIN_WRITE_FULL_SAVE; } } From 33d0461ae90a71e62ba194a9312b980b8da5a35e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:00:33 +0000 Subject: [PATCH 0444/1502] decomp: clarify names in veldin_ship_update domain_0_value_0 -> VELDIN_SHIP_STATE_UNINITIALIZED: Selector is moby->state, the ship state byte at +0x20: retail 0x002d1e90-0x002d1e98 enters only when it is zero. The one-time branch at 0x002d1e9c-0x002d1ea8 writes state 1, sets +0xBC and clears the ship vars +0x40 timer. This proves state 0 is the uninitialized ship state, not a boolean or visibility selector. domain_1_value_1 -> VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING: Retail 0x002d1e9c and 0x002d1ea4 assign 1 to the same ship state byte +0x20 after detecting zero; 0x002d1f14-0x002d1f1c registers veldin_ship_draw at 0x002d19b0. Authoritative naming_source veldin_ship_draw tests moby->state == 1 to force reflection calculation regardless of camera proximity, directly initializes ship_reflection_uvs without blending, then changes state from 1 to 2 after the vertex loop. Thus 1 denotes pending reflection initialization, not merely visibility or a control mode. --- src/overlays/shared/vehicles/veldin_ship.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/vehicles/veldin_ship.c b/src/overlays/shared/vehicles/veldin_ship.c index 4a7212beed..45fa3d147f 100644 --- a/src/overlays/shared/vehicles/veldin_ship.c +++ b/src/overlays/shared/vehicles/veldin_ship.c @@ -145,9 +145,13 @@ void veldin_ship_update(M2d1e80 *m) __asm__("FUN_L00_002d1e80"); /* Moby class 530 */ void veldin_ship_update(M2d1e80 *moby) { + enum { + VELDIN_SHIP_STATE_UNINITIALIZED = 0, + VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING = 1 + }; s32 *ship_vars = moby->vars; - if (moby->state == 0) { - moby->state = 1; + if (moby->state == VELDIN_SHIP_STATE_UNINITIALIZED) { + moby->state = VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING; moby->bc = 1; ship_vars[0x10] = 0; } From faa406aab4701aaea585e0a4eb56ae34e9cba337 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:00:34 +0000 Subject: [PATCH 0445/1502] decomp: clarify names in audio_dec_end_put domain_0_value_0 -> AUDIO_DEC_STATE_HEADER_PENDING: Retail 0x0023ae2c-0x0023ae30 tests AudioDec.state at offset 0 against zero; only that phase enters header handling. At 0x0023ae48-0x0023ae68, hdrCount at offset 0x30 receives min(40-hdrCount, byte_count), and 0x0023ae78 removes those header bytes before payload ring accounting. Thus zero denotes pending header handling. domain_1_value_1 -> AUDIO_DEC_STATE_HEADER_HANDLED: Retail 0x0023ae5c-0x0023ae70 updates hdrCount and assigns 1 to AudioDec.state only when the accumulated count reaches 40. The consumed portion is subtracted at 0x0023ae78 before advancing put/count/totalBytes. This assignment marks header handling completed, without asserting playback readiness. domain_2_value_1 -> AUDIO_DEC_STATE_HEADER_HANDLED: Retail 0x0023ae38-0x0023ae40 compares strType at offset 4 with 4 and branches to 0x0023ae7c-0x0023ae80, which assigns the same state 1 while bypassing header counting and subtraction. It joins payload accounting at 0x0023ae84, proving HEADER_HANDLED includes the header-bypass path and belongs to the same AudioDec.state domain as the other assignment. --- src/audio/decoder/audio_dec_end_put.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/audio/decoder/audio_dec_end_put.c b/src/audio/decoder/audio_dec_end_put.c index 9360bf677d..59ac5830ed 100644 --- a/src/audio/decoder/audio_dec_end_put.c +++ b/src/audio/decoder/audio_dec_end_put.c @@ -4,20 +4,24 @@ void audio_dec_end_put(struct AudioDec *ad, s32 n) __asm__("FUN_0023ae28"); void audio_dec_end_put(struct AudioDec *ad, s32 byte_count) { + enum { + AUDIO_DEC_STATE_HEADER_PENDING = 0, + AUDIO_DEC_STATE_HEADER_HANDLED = 1 + }; s32 k; s32 room; - if (ad->state == 0) { + if (ad->state == AUDIO_DEC_STATE_HEADER_PENDING) { if (ad->strType != 4) { room = 40 - ad->hdrCount; k = room < byte_count ? room : byte_count; ad->hdrCount += k; if (ad->hdrCount >= 40) { - ad->state = 1; + ad->state = AUDIO_DEC_STATE_HEADER_HANDLED; } byte_count -= k; } else { - ad->state = 1; + ad->state = AUDIO_DEC_STATE_HEADER_HANDLED; } } ad->size = ad->size / 1024 * 1024; From 0c69dd5d2aa268913af33ee3c7969423ef09c55a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:02:28 +0000 Subject: [PATCH 0446/1502] decomp: clarify names in audio_dec_create domain_0_value_0 -> AUDIO_DEC_STATE_INITIAL: The authoritative audio_dec_create source (src/audio/decoder/audio_dec_create.c, SHA-256 e69c9e499fe8ff27cd990d07bf1148e0c539298faa377a49687ec3fe90fa0817) assigns dec->state = 0 while clearing hdrCount, put, count and transfer counters. Retail 0x0023abe0 preserves the decoder argument in s0 and 0x0023ac1c stores zero to 0(s0), matching original Ghidra *param_1 = 0. This is an unconditional constructor assignment before snd_init_movie_sound at 0x0023ac5c and before either success/failure return. Supplied init_all passes &movie_player->audio_dec to this constructor. These data flows prove zero is the initial AudioDec state; the name asserts no narrower playback phase. FALSE and NULL do not describe this state domain. --- src/audio/decoder/audio_dec_create.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/decoder/audio_dec_create.c b/src/audio/decoder/audio_dec_create.c index 0b5b3dcbce..a9b8cde1b2 100644 --- a/src/audio/decoder/audio_dec_create.c +++ b/src/audio/decoder/audio_dec_create.c @@ -15,6 +15,9 @@ s32 audio_dec_create(struct AudioDec *dec, s32 buffer_size, s32 globals_address) { + enum { + AUDIO_DEC_STATE_INITIAL = 0 + }; s32 movie_handle; s32 three; s32 four; @@ -24,7 +27,7 @@ s32 audio_dec_create(struct AudioDec *dec, dec->size = buffer_size; three = 3; dec->strType = three; - dec->state = 0; + dec->state = AUDIO_DEC_STATE_INITIAL; dec->hdrCount = 0; dec->put = 0; dec->count = 0; From a46497bac2d8382200290ff78ad0bc91cc669719 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:02:28 +0000 Subject: [PATCH 0447/1502] decomp: clarify names in hero_idle_sequence domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Authoritative source src/overlays/shared/hero/hero_idle_sequence.c (SHA-256 12f6988e9a41b8e8e8484437c966d58aabcf4c04e2ab5a6b74283c104921a66a) assigns vehicle_mode from (&hero)->vehicle_mode. Retail 0x00205000..0x00205018 constructs hero base 0x0013F350 and lbu a1,+0x20A4, matching original Ghidra bRam001413f4. li v1,2 at 0x00205014 and beq at 0x0020501C send this vehicle mode to the zero return at 0x002050A8. The selector is therefore the HeroVehicleMode field, whose supplied include/rnc/hero/hero_state.h enum canonically names 2 HERO_VEHICLE_MODE_GIANT_CLANK, rather than the separate HeroStateId or gravity domains. domain_2_value_1 -> HERO_VEHICLE_MODE_CLANK: The source vehicle_mode selector is read directly from hero.vehicle_mode; retail lbu a1,+0x20A4 at 0x00205018 reads hero+0x20A4 (0x001413F4), agreeing with original Ghidra bRam001413f4. slti at 0x00205020 and li v0,1 in the 0x00205028 delay slot select the comparison against 1 for modes below 3; beq at 0x00205030 rejects that mode via 0x002050A8. This proves the exact HeroVehicleMode selector domain, whose supplied shared enum in include/rnc/hero/hero_state.h canonically names 1 HERO_VEHICLE_MODE_CLANK. No equivalence to current-state ID 1 is inferred. --- src/overlays/shared/hero/hero_idle_sequence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index 99e14bd28d..7753a1cb60 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -93,7 +93,7 @@ int hero_idle_sequence(int a) __asm__("FUN_L00_00205000"); int hero_idle_sequence(int allow_item_idle_sequence) { struct Hero *vehicle_mode_owner = &hero; int vehicle_mode = vehicle_mode_owner->vehicle_mode; - if (vehicle_mode == 2 || (vehicle_mode < 3 ? vehicle_mode == 1 : vehicle_mode == 3)) { + if (vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK || (vehicle_mode < 3 ? vehicle_mode == HERO_VEHICLE_MODE_CLANK : vehicle_mode == 3)) { return 0; } { From cc43e5f51de997651cbfc1b0bfb4b0e32938e761 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:02:28 +0000 Subject: [PATCH 0448/1502] decomp: clarify names in draw_mobys_setup domain_0_value_6 -> FONT_STATE_MOBY_DRAW: Retail 0x0020d294 loads v0=6 and 0x0020d2a0 stores it to 0x0015f620, the authoritative C selector font_state. This occurs in established draw_mobys_setup between vu1_add_data_ref and loading moby_draw_vu0_micro_program at 0x0020d2a4. Checked caller 0x0020d460 calls setup at 0x0020d468 before rendering the resident object pool at 0x0020d49c and cleanup at 0x0020d4cc; the supplied draw_vendor_screen similarly calls setup before draw_moby_list. Thus 6 identifies the selector value for moby drawing. The name uses this selector's own domain, not a moby object-state enum. --- src/rendering/mobys/draw_mobys_setup.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rendering/mobys/draw_mobys_setup.c b/src/rendering/mobys/draw_mobys_setup.c index f25980ab31..fcbcfffd6e 100644 --- a/src/rendering/mobys/draw_mobys_setup.c +++ b/src/rendering/mobys/draw_mobys_setup.c @@ -16,10 +16,13 @@ extern void vu1_add_data_ref() __asm__("func_00233830"); void draw_mobys_setup(void) __asm__("FUN_0020d278"); void draw_mobys_setup(void) { + enum { + FONT_STATE_MOBY_DRAW = 6 + }; register s32 current; register s32 callbackArg; vu1_add_data_ref(D_0010FAA0, D_0010FA90[0]); - font_state = 6; + font_state = FONT_STATE_MOBY_DRAW; vu0_load_micro_program(moby_draw_vu0_micro_program); vu1_add_g_sregister(0x47, 0x5360B); current = render_packet_cursor.addr; From fdf67a83dcb19731e723c9ad082b1ae663533bd5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:02:29 +0000 Subject: [PATCH 0449/1502] decomp: clarify names in try_start_hero_weapon_fire_state domain_0_value_0 -> HERO_STATE_IDLE: Retail 0x002276C4/0x002276D0 constructs hero base 0x0013F350; 0x002276D4 loads its +0x2084 current-state slot into v1 and 0x002276E8 tests v1 against zero after admitting states 2/3. Original Ghidra tests the same iRam001413d4 against zero. Supplied typed hero_set_state writes requested_state to hero.state.current and switches on HeroStateId members, with HERO_STATE_IDLE setting idle control mode and idle animation. The supplied shared include/rnc/hero/hero_state.h HeroStateId declares HERO_STATE_IDLE=0; caller hero_update_transitions also compares hero.state.current to HERO_STATE_IDLE. Thus current_state belongs to HeroStateId, rather than control_mode (+0x208C), vehicle_mode, or a probe domain, and this comparison should reuse HERO_STATE_IDLE. --- src/overlays/shared/hero/hero_set_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_set_state.c b/src/overlays/shared/hero/hero_set_state.c index d118b97fcf..fbcb10de21 100644 --- a/src/overlays/shared/hero/hero_set_state.c +++ b/src/overlays/shared/hero/hero_set_state.c @@ -3037,7 +3037,7 @@ int try_start_hero_weapon_fire_state(void) __asm__("FUN_L00_002276c0"); int try_start_hero_weapon_fire_state(void) { struct Hero *hero_base = (struct Hero *)((char *)D_0013E533 + 0xE1D); int current_state = hero_base->state.current; - if ((unsigned)(current_state - 2) < 2 || current_state == 0) { + if ((unsigned)(current_state - 2) < 2 || current_state == HERO_STATE_IDLE) { if (hero_base->item_anim_active != 0) { if (hero_base->item_anim_frames < scale_game_frames(6)) { if (hero_base->stick_magnitude < 0.7f) { From f2916acb4a5a4ebea4f1695c0bb369be3090fd2d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:04:26 +0000 Subject: [PATCH 0450/1502] decomp: clarify names in start_cutscene_chunk_read domain_0_value_0 -> FALSE: Retail 0x002451cc loads pal_mode from 0x0015ed80 and 0x002451d4 branches on equality to zero. Zero selects the standard sector boundary table at 0x0013a67c; nonzero selects sectors_alt at 0x0013a798. The authoritative source already uses pal_mode != FALSE in load_level_gameplay for the same standard/alternate disc-table selection and video timing flag. Thus FALSE is the established boolean constant for this exact selector, rather than an unrelated equal-valued state member. --- src/overlays/shared/world/load_level_gameplay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/world/load_level_gameplay.c b/src/overlays/shared/world/load_level_gameplay.c index 89f11c381e..f31fe86fab 100644 --- a/src/overlays/shared/world/load_level_gameplay.c +++ b/src/overlays/shared/world/load_level_gameplay.c @@ -2155,7 +2155,7 @@ s32 start_cutscene_chunk_read(s32 i) { s32 start; s32 size; - if (pal_mode != 0) { + if (pal_mode != FALSE) { size = disc_table.sector_lists[D_L00_0016C860.list].sectors_alt[i + 1] - disc_table.sector_lists[D_L00_0016C860.list].sectors_alt[i]; start = disc_table.sector_lists[D_L00_0016C860.list].sectors_alt[i]; From fd1019719f9d0e4fc3016efee7bb331fba784e98 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:04:26 +0000 Subject: [PATCH 0451/1502] decomp: clarify names in update_poison_vessel_spawner domain_0_value_1 -> WAIT_FOR_SPAWN_TIMER: Retail 0x002eabec loads moby+0x20 and 0x002eabf8-0x002eabfc dispatches value 1 to 0x002eac40, matching the source case WAIT_FOR_SPAWN_TIMER. After storing the initialized countdown at pvars+0 (0x002eac28), 0x002eac30 loads 1 and 0x002eac3c stores it to that same moby+0x20 state byte. The destination branch decrements the countdown at 0x002eac40-0x002eac48 and on expiry reloads it and spawns at 0x002eac6c-0x002eac74. Thus the assignment enters the existing WAIT_FOR_SPAWN_TIMER member of this exact local domain. --- src/overlays/l15/mobys/poison_vessel_spawner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l15/mobys/poison_vessel_spawner.c b/src/overlays/l15/mobys/poison_vessel_spawner.c index a0411ec027..eb5d03fdb6 100644 --- a/src/overlays/l15/mobys/poison_vessel_spawner.c +++ b/src/overlays/l15/mobys/poison_vessel_spawner.c @@ -21,7 +21,7 @@ void poison_vessel_spawner_update(struct Moby *moby) { case INITIALIZE_SPAWN_TIMER: spawn_timer_data[0] = truncate_float_to_s32( multiply_global_factor_ed64(*(float *)(spawn_timer_data + 1) * 60.0f)); - moby->state = 1; + moby->state = WAIT_FOR_SPAWN_TIMER; moby->update_dist = 0xFF; break; case WAIT_FOR_SPAWN_TIMER: From 8ca448b5703ff661645c1bcdfd40a2d6e5362023 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:04:27 +0000 Subject: [PATCH 0452/1502] decomp: clarify names in start_oil_tanker_link_destruction domain_0_value_1 -> OIL_TANKER_LINK_DESTRUCTION: In the authoritative start_oil_tanker_link_destruction source, selector link_moby->state is the actual Moby state byte. Retail 0x00318494 loads 1 and 0x003184b0 stores it to Moby +0x20; 0x003184c8 clears collision at +0x94. The same entry computes current-minus-saved position into pvars+0x10 and stores randomized scaled angular values at +0x20/+0x24 (0x00318508, 0x0031852c). Checked caller 0x00317c98 gates on accumulated damage and health, decrements the live count at 0x00317da0..0x00317da8, then passes links[count] at 0x00317db0..0x00317db4. These operations establish entry to destruction for the removed oil-tanker link, independently of unrelated equal-valued hero constants. --- src/overlays/l11/mobys/oil_tanker_front.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/oil_tanker_front.c b/src/overlays/l11/mobys/oil_tanker_front.c index 77c5e146bf..6c6ce1b9e9 100644 --- a/src/overlays/l11/mobys/oil_tanker_front.c +++ b/src/overlays/l11/mobys/oil_tanker_front.c @@ -472,8 +472,11 @@ void distribute_group_blarg_ships_along_path(struct Moby *moby, int table_index) /* Ported from rac1-decomp (src/overlays/l11_pokitaru/vendor_00312BD8.c: func_L11_003198F8), where it is exact; names translated to the US level program. */ void start_oil_tanker_link_destruction(struct Moby *link_moby) { + enum { + OIL_TANKER_LINK_DESTRUCTION = 1 + }; char *link_vars = (char *)link_moby->pvars; - link_moby->state = 1; + link_moby->state = OIL_TANKER_LINK_DESTRUCTION; link_moby->collision = 0; fast_vec_sub(link_vars + 0x10, &link_moby->pos, link_vars); *(float *)(link_vars + 0x20) = From 58749d6f37b8fa38b224a5378e8db9fecd1f74f1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:04:27 +0000 Subject: [PATCH 0453/1502] decomp: clarify names in can_release_linked_robot_dog domain_0_value_254 -> MOBY_STATE_PENDING_REMOVAL: Retail predicate 0x002c6cbc loads Moby state at +0x20 and 0x002c6cc0..0x002c6cc4 rejects 0xFE. Checked common caller robot_dog_update calls this predicate at 0x002c5fa8/0x002c63dc and its source-named mark_moby_for_removal at 0x002c699c after death/fall cleanup. That removal helper at 0x0023d6fc loads 0xFE and at 0x0023d700 stores it to the same Moby+0x20 state byte, then records a global counter plus two at +0x38 (0x0023d708..0x0023d720), proving the pending-removal sentinel role. This does not equate partner states 10/13 with the caller's unrelated class-state enum. --- src/overlays/l03/mobys/robot_dog.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l03/mobys/robot_dog.c b/src/overlays/l03/mobys/robot_dog.c index 447930a36d..85aac72477 100644 --- a/src/overlays/l03/mobys/robot_dog.c +++ b/src/overlays/l03/mobys/robot_dog.c @@ -544,13 +544,16 @@ void update_robot_dog_hit_reaction(struct Moby *moby) { /* Ported from rac1-decomp (src/overlays/l03_kerwan/vendor_00293720.c: func_L03_002C8068), where it is exact; names translated to the US level program. */ int can_release_linked_robot_dog(struct Moby *moby) { + enum { + MOBY_STATE_PENDING_REMOVAL = 0xFE + }; unsigned char state; char *partner_pvars; partner_pvars = (char *)moby->pvars; if (!moby) return 0; state = moby->state; - if (state == 0xFE) + if (state == MOBY_STATE_PENDING_REMOVAL) return 0; if (state == 0xFD) return 0; From 8ac53383f271007b13f3b0c3584e5b80117a6685 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:06:17 +0000 Subject: [PATCH 0454/1502] decomp: clarify names in update_cutscene_camera_target domain_0_value_1 -> DISPATCH_MODE_SELECTED_SLOT: The authoritative source switches on moby->state and already names its value-1 case DISPATCH_MODE_SELECTED_SLOT. Retail 002edb28 reads byte +0x20 from the incoming moby; 002edb30/002edb34 compare that same state to 1 and enter mode-selected slot dispatch at 002edb58. Initialization loads 1 at 002edb48 and stores it to the same +0x20 byte at 002edb4c, matching original Ghidra's *(param_1+0x20)=1. Thus the assignment enters the existing named case in the exact same selector domain, rather than a numerically similar mission mode. --- src/overlays/l15/mobys/cutscene_camera_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l15/mobys/cutscene_camera_target.c b/src/overlays/l15/mobys/cutscene_camera_target.c index cc9b070f99..d67360aa86 100644 --- a/src/overlays/l15/mobys/cutscene_camera_target.c +++ b/src/overlays/l15/mobys/cutscene_camera_target.c @@ -26,7 +26,7 @@ void cutscene_camera_target_update(struct Moby *moby) { switch (moby->state) { case INITIALIZE_UPDATE_DISTANCE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = DISPATCH_MODE_SELECTED_SLOT; break; case DISPATCH_MODE_SELECTED_SLOT: if (D_L15_0015F5C4 == 2) { From 41e0746c7fd00ddd046f8bbda9d0b5624cfb3886 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:06:17 +0000 Subject: [PATCH 0455/1502] decomp: clarify names in _skipMB0 domain_3_value_1 -> MPEG_PICTURE_CODING_TYPE_I: The selector is decoder->picture_coding_type, loaded from offset 0x150 at retail 0x00127bb8 and compared with 1 at 0x00127bbc-0x00127bc0. Only that branch calls _Error at 0x00127bcc with address 0x00153868, whose original retail Ghidra string is 'skiped macroblock in I picure is not allowed', then clears the success return at 0x00127bd4. This directly identifies coding type 1 as I-picture, rather than a Boolean or an output motion mode. --- src/sdk/mpeg/macroblock/skip_mb0.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/mpeg/macroblock/skip_mb0.c b/src/sdk/mpeg/macroblock/skip_mb0.c index 7cbfae8315..fd5e8a3d84 100644 --- a/src/sdk/mpeg/macroblock/skip_mb0.c +++ b/src/sdk/mpeg/macroblock/skip_mb0.c @@ -22,6 +22,9 @@ s32 _skipMB0(struct MpegDecoder *decoder, struct MpegMotionRef *motion_reference, s32 *flags) { + enum { + MPEG_PICTURE_CODING_TYPE_I = 1 + }; s32 buf_offset; s32 bottom_field; s32 ok; @@ -44,7 +47,7 @@ s32 _skipMB0(struct MpegDecoder *decoder, motion_reference->unk4 = bottom_field; motion_reference->unk0 = bottom_field; } - if (decoder->picture_coding_type == 1) { + if (decoder->picture_coding_type == MPEG_PICTURE_CODING_TYPE_I) { _Error(decoder, skipped_macroblock_in_i_picture_error_message); ok = 0; } From b9aeb0114ce28192ce21aaafa960c9ddbb4573ee Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:06:17 +0000 Subject: [PATCH 0456/1502] decomp: clarify names in leave_map_screen domain_0_value_0 -> MUSIC_STREAM_READ_INACTIVE: The authoritative leave_map_screen source compares music_stream_state.read_state == 0. Retail 0x0021bdb8 loads the halfword at 0x001516d8 and 0x0021bdbc skips the selection cleanup when nonzero; original Ghidra calls it g_cdReadState.nActive. The supplied request_audio_stream_break source uses MUSIC_STREAM_READ_INACTIVE = 0 for this exact music_stream_state.read_state field, establishing the same read-state domain. domain_1_value_0 -> MUSIC_STREAM_READ_INACTIVE: The second comparison is music_stream_state.read_state != 0. Retail 0x0021be00 reloads the same halfword at 0x001516d8; 0x0021be04 skips cancellation when zero, while 0x0021be1c calls request_audio_stream_break if pending_buffer is nonzero. That supplied helper compares the same read_state field against MUSIC_STREAM_READ_INACTIVE = 0 before breaking the stream, proving reuse of the established inactive member. --- src/ui/map/leave_map_screen.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ui/map/leave_map_screen.c b/src/ui/map/leave_map_screen.c index 189fc22ec3..0d73e4c949 100644 --- a/src/ui/map/leave_map_screen.c +++ b/src/ui/map/leave_map_screen.c @@ -8,14 +8,17 @@ extern void request_audio_stream_break() __asm__("FUN_002166e8"); s32 leave_map_screen(void) __asm__("FUN_0021bda0"); s32 leave_map_screen(void) { - if (music_stream_state.read_state == 0) { + enum { + MUSIC_STREAM_READ_INACTIVE = 0 + }; + if (music_stream_state.read_state == MUSIC_STREAM_READ_INACTIVE) { if (level_map_selection.sel != -1) { menu_system.pending_buffer = 0; level_map_selection.slot_id[level_map_selection.sel] ^= 0x1000; level_map_selection.sel = -1; } } - if (music_stream_state.read_state != 0) { + if (music_stream_state.read_state != MUSIC_STREAM_READ_INACTIVE) { if (menu_system.pending_buffer != 0) { request_audio_stream_break(); menu_system.pending_buffer = 0; From ef95d4bbdc804a2013f16ae17e6d0d3d3f60276b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:06:17 +0000 Subject: [PATCH 0457/1502] decomp: clarify names in update_tilting_platform domain_0_value_0 -> TILTING_PLATFORM_STATE_UNINITIALIZED: Source selector is moby->state, confirmed by retail lbu v1,0x20(a2) at 0x002de21c and bne v1,zero at 0x002de220. Only zero enters the initialization block: state becomes one at 0x002de24c, command is cleared, flags gain 0x100, position Z rises 0.35, pvars+0x70 and spring storage +0x60 are cleared, and rotation is reset through 0x002de270. Thus zero denotes this tilting platform's uninitialized state, not a hero-domain enum member. domain_1_value_1 -> TILTING_PLATFORM_STATE_INITIALIZED: Retail li v1,1 at 0x002de22c feeds sb v1,0x20(a2) at 0x002de24c, the same moby->state byte tested for zero at 0x002de21c-0x002de220. This write occurs inside the initialization block that establishes flags, Z offset, timer, spring storage and rotation before joining the ordinary tilt and matrix calls at 0x002de284 and 0x002de29c. One therefore records completed initialization and skips that reset on subsequent calls; no active/idle or hero-state semantics are claimed. --- src/overlays/l14/mobys/platform.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l14/mobys/platform.c b/src/overlays/l14/mobys/platform.c index 6eb51a4842..1dc2fe0d35 100644 --- a/src/overlays/l14/mobys/platform.c +++ b/src/overlays/l14/mobys/platform.c @@ -54,13 +54,13 @@ typedef struct TiltingPlatformVars { /* Moby class 309 */ void tilting_platform_update(struct Moby *moby) { - TiltingPlatformVars *tilting_platform_state = (TiltingPlatformVars *)moby->pvars; + enum { TILTING_PLATFORM_STATE_UNINITIALIZED = 0 , TILTING_PLATFORM_STATE_INITIALIZED = 1 } ;TiltingPlatformVars *tilting_platform_state = (TiltingPlatformVars *)moby->pvars; void *rotation; u128 old_rotation; qcopy(&old_rotation, &moby->rot); - if (moby->state == 0) { - moby->state = 1; + if (moby->state == TILTING_PLATFORM_STATE_UNINITIALIZED) { + moby->state = TILTING_PLATFORM_STATE_INITIALIZED; moby->command = 0; moby->flags |= 0x100; moby->pos.z += 0.35f; From 0729038278d7f52eeec15334e35dc2e9f600ee86 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:06:17 +0000 Subject: [PATCH 0458/1502] decomp: clarify names in draw_menu_stream_image domain_0_value_4 -> MENU_STREAM_IMAGE_MIN_DRAW_STATE: In authoritative draw_menu_stream_image source (SHA-256 5cc4f3721b42e0a83dc033a1316025d6fa9dcef16da60103896338d76414d07a), screen->state < 4 returns zero before any rendering. Retail 0x002207a4 loads screen+0x44, 0x002207a8 compares signed state against 4, and 0x002207ac branches to return zero when below that threshold. Otherwise 0x002207c0 through 0x00220830 sets up paging, loads screen+0x48/+0x4c textures, draws both 256-by-256 halves and finishes paging. Thus 4 is the minimum drawing state for this screen, with no claim about its lifecycle semantics or a shared enum. --- src/ui/menus/stream_image/draw_menu_stream_image.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/menus/stream_image/draw_menu_stream_image.c b/src/ui/menus/stream_image/draw_menu_stream_image.c index 83846fd094..4712aa9a5a 100644 --- a/src/ui/menus/stream_image/draw_menu_stream_image.c +++ b/src/ui/menus/stream_image/draw_menu_stream_image.c @@ -14,9 +14,12 @@ extern s64 load_texture_file() __asm__("func_00204CF0"); s32 draw_menu_stream_image(struct MenuStreamImageScreen *screen) __asm__("FUN_00220790"); s32 draw_menu_stream_image(struct MenuStreamImageScreen *screen) { + enum { + MENU_STREAM_IMAGE_MIN_DRAW_STATE = 4 + }; s64 modulate_color; - if (screen->state < 4) { + if (screen->state < MENU_STREAM_IMAGE_MIN_DRAW_STATE) { return 0; } modulate_color = (s64)0x80808080; From 726bf7585a08551fa68f6b4b951d4787866f1e6f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:06:17 +0000 Subject: [PATCH 0459/1502] decomp: clarify names in update_moby_grab_state domain_0_value_8 -> FROG_STATE_WANDER: Retail 0x002ea604-0x002ea614 reads moby+0x20 and accepts states 8 and 9. In the authoritative frog.c snapshot, frog_update dispatches this same moby state byte as FROG_STATE_WANDER=8, selecting random goals around the stored home position and walking toward them. domain_1_value_9 -> FROG_STATE_APPROACH_TARGET: Retail 0x002ea604-0x002ea614 accepts byte state 9 in the range test. The same frog.c owner dispatches moby[0x20] under FROG_STATE_APPROACH_TARGET=9, computes facing from target position, moves toward it and enters attack when within 2 units. domain_2_value_12 -> FROG_STATE_ATTACK: Retail 0x002ea620-0x002ea624 compares the moby state byte against 12. In the supplied frog_update state domain FROG_STATE_ATTACK=12 faces the target, advances during animation frames 10 through 15 and collects hit candidates in a sphere. domain_3_value_13 -> FROG_STATE_RETURN_HOME: Retail 0x002ea628-0x002ea62c compares the same moby state byte with 13. The authoritative frog_update labels 13 FROG_STATE_RETURN_HOME and subtracts current position from the saved home at frog_instance_vars+0x210, moving toward home and returning to wander nearby. domain_4_value_16 -> FROG_STATE_SUCK_CANNON_HELD: Retail 0x002ea630-0x002ea640 accepts state 16 without reentering it after nonzero suction-helper results. The authoritative frog_update names byte state 16 FROG_STATE_SUCK_CANNON_HELD; its branch processes the held moby and returns it to state 8 on completion. domain_5_value_16 -> FROG_STATE_SUCK_CANNON_HELD: Retail 0x002ea63c-0x002ea650 skips saving the previous state when moby+0x20 already equals 16; otherwise it saves the previous state at +0xBC and enters 16 after accepted suction. This is the same frog state byte dispatched as FROG_STATE_SUCK_CANNON_HELD in frog_update. domain_6_value_16 -> FROG_STATE_SUCK_CANNON_HELD: Retail 0x002ea648 stores 16 to moby+0x20 and 0x002ea650 saves the prior state to +0xBC after accepted nonzero process_moby_suck_cannon_suction results. The source frog_update dispatches that exact byte and value as FROG_STATE_SUCK_CANNON_HELD, rather than a Hero state or suction record substate. domain_7_value_16 -> FROG_STATE_SUCK_CANNON_HELD: Retail 0x002ea654-0x002ea66c tests moby+0x20 for 16 on zero suction result and releases it to 8. The authoritative frog_update uses FROG_STATE_SUCK_CANNON_HELD=16 for this moby state byte, with its own completion branch also restoring 8 and animation 0. domain_8_value_8 -> FROG_STATE_WANDER: Retail 0x002ea660-0x002ea66c writes 8 to moby+0x20 when suction releases held state 16. The supplied frog_update defines this byte domain's state 8 as FROG_STATE_WANDER, whose behavior selects random destinations around home; its held-state completion also restores 8. --- src/overlays/shared/enemies/frog.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/enemies/frog.c b/src/overlays/shared/enemies/frog.c index 3f5860276b..8ce22a03a5 100644 --- a/src/overlays/shared/enemies/frog.c +++ b/src/overlays/shared/enemies/frog.c @@ -936,19 +936,26 @@ void spawn_moby_death_effect_burst(char *moby) { int update_moby_grab_state(struct Moby *moby) __asm__("FUN_L06_002ea5e0"); int update_moby_grab_state(struct Moby *moby) { + enum { + FROG_STATE_WANDER = 8, + FROG_STATE_APPROACH_TARGET = 9, + FROG_STATE_ATTACK = 0xC, + FROG_STATE_RETURN_HOME = 0xD, + FROG_STATE_SUCK_CANNON_HELD = 0x10 + }; int grab_check_result = process_moby_suck_cannon_suction(moby); if (grab_check_result != 0) { - if (moby->state == 8 || moby->state == 9 || moby->state == 0xC || moby->state == 0xD || - moby->state == 0x10) { - if (moby->state != 0x10) { + if (moby->state == FROG_STATE_WANDER || moby->state == FROG_STATE_APPROACH_TARGET || moby->state == FROG_STATE_ATTACK || moby->state == FROG_STATE_RETURN_HOME || + moby->state == FROG_STATE_SUCK_CANNON_HELD) { + if (moby->state != FROG_STATE_SUCK_CANNON_HELD) { moby->command = moby->state; - moby->state = 0x10; + moby->state = FROG_STATE_SUCK_CANNON_HELD; } } else { grab_check_result = 0; } - } else if (moby->state == 0x10) { - moby->state = 8; + } else if (moby->state == FROG_STATE_SUCK_CANNON_HELD) { + moby->state = FROG_STATE_WANDER; if (moby->prev_seq != 0) { blend_moby_animation((MobyAnim *)moby, 0, 0, scale_game_frames(10)); } From 4343740e89979c897199941cf88fbbcb35f75390 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:08:05 +0000 Subject: [PATCH 0460/1502] decomp: clarify names in enter_menu_help_text domain_0_value_0 -> CD_READ_STATE_IDLE: Authoritative source src/ui/menus/widgets/enter_menu_help_text.c (SHA-256 5ac8638044aaaff6732676096f9f5e09fbb732b316685ef07d97819e0cf04adb) compares music_stream_state.read_state with 0 before start_audio_stream_read. Retail 0x0021d264-0x0021d270 loads signed halfword [0x001516d0+8] and skips the read when nonzero; 0x0021d28c calls 0x00216788 only for zero. Supplied start_audio_stream_read source tests this same field against CD_READ_STATE_IDLE=0, starts snd_stream_safe_cd_read, then assigns CD_READ_STATE_ACTIVE=1 after success. Thus this comparison uses the CD-read idle state, independently of unrelated zero-valued constants. --- src/ui/menus/widgets/enter_menu_help_text.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/menus/widgets/enter_menu_help_text.c b/src/ui/menus/widgets/enter_menu_help_text.c index cb3acf17c8..e74884dfd8 100644 --- a/src/ui/menus/widgets/enter_menu_help_text.c +++ b/src/ui/menus/widgets/enter_menu_help_text.c @@ -17,7 +17,7 @@ extern s32 start_audio_stream_read(s32, s32, s32) __asm__("FUN_00216788"); s32 enter_menu_help_text(struct MenuScreen *menu) __asm__("FUN_0021d1f8"); s32 enter_menu_help_text(struct MenuScreen *menu) { - s32 i; + enum { CD_READ_STATE_IDLE = 0 } ;s32 i; struct MenuSystem *menu_system_state; initialize_menu_stream_buffers(1); @@ -31,7 +31,7 @@ s32 enter_menu_help_text(struct MenuScreen *menu) { } } menu->data.help.load_state = 0; - if (music_stream_state.read_state == 0) { + if (music_stream_state.read_state == CD_READ_STATE_IDLE) { if (start_audio_stream_read(help_text_read_destination[0], disc_table.help_text.sector, disc_table.help_text.size) != 0) { From 8af63841c1c37a75f1c628775a2426a98da70c91 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:08:05 +0000 Subject: [PATCH 0461/1502] decomp: clarify names in _clearEach domain_0_value_0 -> FALSE: At 0x0012c228 _clearEach calls DIntr (0x0011d660); its return v0 survives to beq v0,zero at 0x0012c288, which skips EnableInterrupts at 0x0012c290. The helper reads Status & 0x10000 at 0x0011d660-0x0011d668, normalizes the prior enable bit with sltu a0,zero,v1 at 0x0011d670, and returns that Boolean at 0x0011d698 or explicit zero at 0x0011d69c-0x0011d6a4. Thus the source state != 0 compares the prior-interrupt-enabled Boolean against false, proving reuse of existing FALSE=0 rather than a pointer NULL or unrelated state enum. --- src/sdk/mpeg/picture/_clearEach.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdk/mpeg/picture/_clearEach.c b/src/sdk/mpeg/picture/_clearEach.c index fef2ae1cb5..7bb0b835d8 100644 --- a/src/sdk/mpeg/picture/_clearEach.c +++ b/src/sdk/mpeg/picture/_clearEach.c @@ -19,7 +19,7 @@ void _clearEach(u8 *ctx) { *(volatile u32 *)0x1000D400 = 0; *(volatile u32 *)0x1000F590 = *(volatile u32 *)0x1000F520 & 0xFFFEFFFF; - if (state != 0) + if (state != FALSE) EnableInterrupts(); *(volatile u32 *)0x1000B020 = 0; From ae2f48513f1e6e6c32b22d7042eb17be8ba62c6c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:08:05 +0000 Subject: [PATCH 0462/1502] decomp: clarify names in set_class_mobys_flags_and_collision domain_0_value_0 -> MOBY_STATE_MIN_LIVE: Retail 0x00253ab0-0x00253ab8 filters class_id at moby+0xa6; 0x00253ac0 loads the signed state byte at moby+0x20 and 0x00253ac4 bltzl skips every negative state before any flags, active byte or collision update. The original decompilation expresses -1 < *(char *)(uVar4+0x20), and authoritative C expresses moby->state >= 0. Its helper comment explicitly describes updates to every live moby of one class. Thus zero is the minimum live-state bound for this helper, supporting MOBY_STATE_MIN_LIVE without asserting a class-specific state name. --- src/overlays/l17/mobys/fighter_jet.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l17/mobys/fighter_jet.c b/src/overlays/l17/mobys/fighter_jet.c index 45fc89d842..dac12db0a5 100644 --- a/src/overlays/l17/mobys/fighter_jet.c +++ b/src/overlays/l17/mobys/fighter_jet.c @@ -75,9 +75,12 @@ void set_class_mobys_flags_and_collision(int class_id, int collision) __asm__("FUN_L17_00253a90"); void set_class_mobys_flags_and_collision(int class_id, int flag2, int flag1, int collision) { + enum { + MOBY_STATE_MIN_LIVE = 0 + }; Level17Moby *moby; for (moby = (Level17Moby *)D_L17_0015FFD8; moby <= l17_moby_array_last; moby++) { - if (moby->class_id == class_id && moby->state >= 0) { + if (moby->class_id == class_id && moby->state >= MOBY_STATE_MIN_LIVE) { if (flag2 != -1) { if (flag2 != 0) moby->flags &= ~2; From a3fb82f45c5ac0676ec31dfec6448711ff5cfcf6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:08:05 +0000 Subject: [PATCH 0463/1502] decomp: clarify names in launch_attached_rocket domain_0_value_0 -> ATTACHED_ROCKET_STATE_FLIGHT: Retail 003059A4 saves the rocket Moby in s0; 00305A14 sb zero,0x20(s0) writes its state, matching moby->state = 0 in authoritative source b1f449a4ed50f0a05a473ce6b5e37ce1877a60aada64492917429162d0959b73. Launch saves joint-derived origin at pvars+0x10 (003059FC-00305A00), velocity at pvars+0 (00305A04-00305A08), and restores class collision at 00305A28-00305A30. The same source's constructor sets attached state 1; update_attached_rocket treats ATTACHED_ROCKET_STATE_ATTACHED=1 as source-joint following, while the non-attached path advances moby->pos by pvars velocity, checks distance limits and line collision, and explodes/removes the rocket. The prepared Ghidra plate also records checked caller 002C25B8 launching target-directed velocity at 002C2A68/002C2AA4 and creating replacement attached rockets. Together this proves zero is the rocket flight state, not a control/request value. --- src/overlays/l13/mobys/attached_rocket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l13/mobys/attached_rocket.c b/src/overlays/l13/mobys/attached_rocket.c index ce9879aa64..89922a3513 100644 --- a/src/overlays/l13/mobys/attached_rocket.c +++ b/src/overlays/l13/mobys/attached_rocket.c @@ -64,7 +64,7 @@ void launch_attached_rocket(struct Moby *moby, int distance_reference_moby, float max_travel_distance) { - AttachedRocketVars *moby_vars = (AttachedRocketVars *)moby->pvars; + enum { ATTACHED_ROCKET_STATE_FLIGHT = 0 } ;AttachedRocketVars *moby_vars = (AttachedRocketVars *)moby->pvars; char *source_moby = (char *)moby_vars->unk20; char *mp; moby_vars->unk28 = max_travel_distance; @@ -77,7 +77,7 @@ void launch_attached_rocket(struct Moby *moby, qcopy(&moby_vars->unk10, mp); qcopy(moby_vars, pos); moby_vars->unk2C = distance_reference_moby; - moby->state = 0; + moby->state = ATTACHED_ROCKET_STATE_FLIGHT; moby->flags &= 0xFFFE; moby->collision = moby->pclass->collision; update_entity(moby); From b2210ba36b2cbafb55a5450c0dec3fd28a066c78 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:10:02 +0000 Subject: [PATCH 0464/1502] decomp: clarify names in pool_bubble domain_0_value_72 -> POOL_BUBBLE_PARTICLE_KIND: Retail 0x00287b7c loads 0x48 into v1 and 0x00287b88 stores it to s0+3, the authoritative Particle.kind field of the create_part(0x38) object returned by established pool_bubble. Original Ghidra independently shows *(undefined1 *)(iVar9 + 3) = 0x48. The checked caller update_pool_tiles_and_effects invokes pool_bubble for bubble_position along the pool path; the authoritative sibling pool_bubbles also assigns 0x48 to Particle.kind. Thus the name describes the kind used for pool-bubble particles, without claiming a global exclusive kind or renderer behavior. --- src/overlays/l01/mobys/pool_bubbles.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/pool_bubbles.c b/src/overlays/l01/mobys/pool_bubbles.c index 3a390a4af4..b70ced8882 100644 --- a/src/overlays/l01/mobys/pool_bubbles.c +++ b/src/overlays/l01/mobys/pool_bubbles.c @@ -34,6 +34,9 @@ extern u8 *pool_bubble_texture_table[] __asm__("D_L01_001B25E0"); Particle *pool_bubble(u128 *pos, u128 *vel, f32 f) __asm__("FUN_L01_00287b00"); Particle *pool_bubble(u128 *pos, u128 *motion_position_source, f32 scale) { + enum { + POOL_BUBBLE_PARTICLE_KIND = 0x48 + }; Particle *particle; s32 gray_channel; u32 col; @@ -45,7 +48,7 @@ Particle *pool_bubble(u128 *pos, u128 *motion_position_source, f32 scale) { col = (gray_channel << 8) | 0x40000000; particle->color = (gray_channel << 16) | col | gray_channel; particle->alpha = truncate_float_to_s32(4.0f) + 0x20; - particle->kind = 0x48; + particle->kind = POOL_BUBBLE_PARTICLE_KIND; particle->active = 0; particle->tex = *pool_bubble_texture_table[0]; particle->scale = scale; From 218b1cb5402d806f03623cce8a91c9545e0afb2c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:10:02 +0000 Subject: [PATCH 0465/1502] decomp: clarify names in update_cutscene_camera_target domain_0_value_1 -> LEVEL_MODE_STATE_DISPATCH: The authoritative source switches on moby->state with existing LEVEL_MODE_STATE_DISPATCH = 1. Retail 0x002eace0 reads the same byte at a0+0x20; 0x002eace8-0x002eacec compare it with 1 and enter dispatch at 0x002ead10. Initialization at 0x002ead00-0x002ead04 loads 1 and stores it to that exact a0+0x20 state byte. Original Ghidra independently shows the state=1 store and state==1 dispatch guard. This is the same Moby state domain and canonical existing member, rather than the unrelated level-mode field at 0x0016cd10. --- src/overlays/l10/mobys/cutscene_camera_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l10/mobys/cutscene_camera_target.c b/src/overlays/l10/mobys/cutscene_camera_target.c index 9ed0284796..0a41e5b7c4 100644 --- a/src/overlays/l10/mobys/cutscene_camera_target.c +++ b/src/overlays/l10/mobys/cutscene_camera_target.c @@ -28,7 +28,7 @@ void cutscene_camera_target_update(struct Moby *moby) { switch (moby->state) { case LEVEL_MODE_STATE_INITIALIZE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = LEVEL_MODE_STATE_DISPATCH; break; case LEVEL_MODE_STATE_DISPATCH: if (D_L10_0015F5C4_vendor == 2) { From dae99e951c2bc6dd15d3ba973e123633b97797a9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:10:02 +0000 Subject: [PATCH 0466/1502] decomp: clarify names in audio_dec_begin_put domain_0_value_0 -> AUDIO_DEC_STATE_HEADER_PENDING: In the bound source src/audio/decoder/audio_dec_begin_put.c (SHA-256 5eedb80699b5e00c5f650130324fd33f27a669fa7bcbdb81f70a29da61677354), selector dec->state is the word loaded at retail 0x0023ad5c and tested at 0x0023ad60. Zero routes non-type-4 input to hdr+hdrCount and 0x28-hdrCount at 0x0023ad78-0x0023ad94, ahead of the data span; nonzero uses ring put/count. Checked caller 0x0023b728 calls begin_put at 0x0023b7a4 and sibling 0x0023ae28 at 0x0023b7e0 with the same decoder and copied count. That sibling tests the same state word at 0x0023ae2c-0x0023ae30, consumes min(copied_count,0x28-hdrCount) and updates hdrCount at 0x0023ae48-0x0023ae68, then stores state=1 at 0x0023ae6c-0x0023ae70 when the 40-byte header is complete. Type 4 skips collection and stores 1 at 0x0023ae7c-0x0023ae80. Thus zero denotes the header-pending phase, including its type-4 bypass, rather than a Boolean or pointer domain. --- src/audio/decoder/audio_dec_begin_put.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/decoder/audio_dec_begin_put.c b/src/audio/decoder/audio_dec_begin_put.c index f679fca03d..c0a8bee47f 100644 --- a/src/audio/decoder/audio_dec_begin_put.c +++ b/src/audio/decoder/audio_dec_begin_put.c @@ -10,9 +10,12 @@ void audio_dec_begin_put(struct AudioDec *dec, void **second_destination, s32 *size2) { + enum { + AUDIO_DEC_STATE_HEADER_PENDING = 0 + }; s32 writable_byte_count; - if (dec->state == 0) { + if (dec->state == AUDIO_DEC_STATE_HEADER_PENDING) { if (dec->strType != 4) { *first_destination = ((u8 *)&dec->hdr + dec->hdrCount); *size1 = 0x28 - dec->hdrCount; From e37c1f1284afabae6ea574b05c01ee35ea224ad6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:10:02 +0000 Subject: [PATCH 0467/1502] decomp: clarify names in maintain_emitter_sound_voice domain_0_value_0 -> RED_SHIP_INITIALIZE: Retail 0x0029c9e4 loads the current Moby state byte at +0x20; 0x0029c9e8..0x0029c9f4 handles zero by setting v0=-1, saved at pvars+0x150 by 0x0029ca8c. Checked caller keeps the moby in s3 (0x0029dbc0), passes it in a0 at 0x0029dd1c to this helper at 0x0029dd20, then loads the same +0x20 at 0x0029dd30 and branches on zero at 0x0029dd44 to 0x0029dd6c. That branch initializes spline path state, rotation and position (0x0029df04..0x0029e11c), then sets state 1 or 3 (0x0029e120..0x0029e140). Authoritative caller C names this exact selector branch RED_SHIP_INITIALIZE=0. This is current-state initialization, not the unrelated zero-valued FALSE, NULL or VOICE_SLOT_FREE domains. --- src/overlays/l03/mobys/red_ship_1.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l03/mobys/red_ship_1.c b/src/overlays/l03/mobys/red_ship_1.c index 3b5da05ad0..31362cbad0 100644 --- a/src/overlays/l03/mobys/red_ship_1.c +++ b/src/overlays/l03/mobys/red_ship_1.c @@ -61,8 +61,11 @@ void add_moby_rotation_based_offsets(struct Moby *moby, float *position) { void maintain_emitter_sound_voice(struct Moby *moby) __asm__("FUN_L03_0029c9d0"); void maintain_emitter_sound_voice(struct Moby *moby) { + enum { + RED_SHIP_INITIALIZE = 0 + }; char *emitter_pvars = (char *)moby->pvars; - if (moby->state == 0) { + if (moby->state == RED_SHIP_INITIALIZE) { *(int *)(emitter_pvars + 0x150) = -1; return; } From b6efba8a5de364cf74c8a6e83913f1531d92f1d3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:10:02 +0000 Subject: [PATCH 0468/1502] decomp: clarify names in update_blarg_heavy_interceptor_oscillation_and_patrol_heading domain_0_value_1 -> INTERCEPTOR_STATE_PATROL_AND_SCAN: Retail 0x002aea18 preserves the input Moby in s1; 0x002aea54 loads its state byte at +0x20, 0x002aea58 loads 1, and 0x002aea5c skips heading changes unless equal. The authoritative caller update_blarg_heavy_interceptor switches on this same moby->state and already declares INTERCEPTOR_STATE_PATROL_AND_SCAN = 1. That branch passes the same moby to this helper after update_blarg_heavy_interceptor_patrol_aim_point and update_blarg_heavy_interceptor_patrol_path_position, then scans for a target. Retail 0x002aea64-0x002aeabc implements the gated heading countdown, randomly signed offset and heading spring. Therefore this is the interceptor patrol-and-scan state, not a Hero mode or a control selector. --- src/overlays/l14/mobys/blarg_heavy_interceptor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/blarg_heavy_interceptor.c b/src/overlays/l14/mobys/blarg_heavy_interceptor.c index 9c39c5eaa1..10a684f610 100644 --- a/src/overlays/l14/mobys/blarg_heavy_interceptor.c +++ b/src/overlays/l14/mobys/blarg_heavy_interceptor.c @@ -1698,7 +1698,7 @@ update_moby_rotation_oscillation(u8 *, u8 *, u8 *, f32, f32, f32) __asm__("FUN_L void update_blarg_heavy_interceptor_oscillation_and_patrol_heading(struct Moby *moby) __asm__("FUN_L14_002aea08"); void update_blarg_heavy_interceptor_oscillation_and_patrol_heading(struct Moby *moby) { - BlargHeavyInterceptorVars *interceptor_private_vars = (BlargHeavyInterceptorVars *)moby->pvars; + enum { INTERCEPTOR_STATE_PATROL_AND_SCAN = 1 } ;BlargHeavyInterceptorVars *interceptor_private_vars = (BlargHeavyInterceptorVars *)moby->pvars; f32 heading_offset; update_moby_vertical_oscillation( blarg_heavy_interceptor_vertical_oscillation_amplitude_gp, @@ -1713,7 +1713,7 @@ void update_blarg_heavy_interceptor_oscillation_and_patrol_heading(struct Moby * blarg_heavy_interceptor_rotation_oscillation_amplitude_gp, blarg_heavy_interceptor_rotation_oscillation_first_phase_increment_gp, blarg_heavy_interceptor_rotation_oscillation_second_phase_increment_gp); - if (moby->state == 1) { + if (moby->state == INTERCEPTOR_STATE_PATROL_AND_SCAN) { if (fast_dec_timer_s16((s16 *)&interceptor_private_vars->unk1B0[1])) { *(s16 *)&interceptor_private_vars->unk1B0[1] = scale_game_frames(blarg_heavy_interceptor_patrol_heading_change_interval_frames_gp); From 7b95fe251c08b69c166c971ef99bdead9aa77a7a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:10:02 +0000 Subject: [PATCH 0469/1502] decomp: clarify names in start_blarg_elite_commando_return_to_initial_position domain_0_value_10 -> COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM: Retail 0x002d3df8 preserves a0 as s0; 0x002d3de4 loads 10 and 0x002d3e04-0x002d3e08 compares it to the Moby state byte at s0+0x20. Original Ghidra shows the same byte comparison. The authoritative source (SHA-256 97f4c64d1fbfb4d0c62ce8bdb8dbadb98a02a9c4e67759bfa3d849c3b2ba03e9) dispatches that same commando state byte in blarg_elite_commando_update and already names 10 COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM: its branch transforms pvars+0x2C0 by parent pvars+0x2D0's basis, adds the parent's position and inherits parent rotation. Thus reuse the existing commando-domain member, not HERO_STATE_PACK_JUMP. domain_1_value_1 -> COMMANDO_STATE_RETURN_TO_INITIAL_POSITION: Retail 0x002d3e10 loads 1 and 0x002d3e20 stores it to s0+0x20, the same commando Moby state byte tested against 10. Original Ghidra confirms this assignment. Retail 0x002d3e6c stores the countdown at pvars+0x2DC and 0x002d3e78-0x002d3e98 saves position and initializes movement. In the authoritative source, blarg_elite_commando_update dispatches this byte and already names state 1 COMMANDO_STATE_RETURN_TO_INITIAL_POSITION; that branch decrements the same +0x2DC countdown, steers toward the saved initial position at +0x2B0, and transitions to idle on arrival. The armed_transport_update excerpt calls this function on a passenger with scale_game_frames(90), supporting this transition role. --- src/overlays/shared/enemies/blarg_elite_commando.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/blarg_elite_commando.c b/src/overlays/shared/enemies/blarg_elite_commando.c index 3068c65005..e739bc9f72 100644 --- a/src/overlays/shared/enemies/blarg_elite_commando.c +++ b/src/overlays/shared/enemies/blarg_elite_commando.c @@ -681,9 +681,9 @@ void start_blarg_elite_commando_return_to_initial_position( void start_blarg_elite_commando_return_to_initial_position(struct Moby *moby, int return_countdown_ticks) { - L16DamageData *commando_data = (L16DamageData *)moby->pvars; - if (moby->state == 10) { - moby->state = 1; + enum { COMMANDO_STATE_RETURN_TO_INITIAL_POSITION = 1 , COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM = 10 } ;L16DamageData *commando_data = (L16DamageData *)moby->pvars; + if (moby->state == COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM) { + moby->state = COMMANDO_STATE_RETURN_TO_INITIAL_POSITION; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(0x14)); } From 926d620bba5c2ac66cfbd7e7918af8c4ee1d0b89 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:10:02 +0000 Subject: [PATCH 0470/1502] decomp: clarify names in update_breakable_prop domain_0_value_1 -> HIT_RESPONSE_STATE_WAIT_FOR_HIT: Retail 0x002eb800 reads byte +0x20 of the same moby saved in s0; 0x002eb81c selects its zero initialization state and 0x002eb840 stores 1 back to +0x20. The next update's comparison at 0x002eb808 selects the hit-testing branch for that state. Thus the assignment targets exactly the existing local switch domain moby->state and its canonical HIT_RESPONSE_STATE_WAIT_FOR_HIT = 1 member. domain_1_value_2 -> HIT_RESPONSE_STATE_RESPOND_AND_REMOVE: Retail 0x002eb844 checks the find_moby_hit return, 0x002eb84c loads its +0x2C float and 0x002eb858 tests positivity; 0x002eb86c loads 2 and 0x002eb874 stores it into the same moby state byte +0x20 read at 0x002eb800. Dispatch at 0x002eb82c takes state 2 to voice allocation, bolt spawning, class 0x741 placement spawning and removal (0x002eb878-0x002eb8a0), proving reuse of existing local HIT_RESPONSE_STATE_RESPOND_AND_REMOVE = 2. --- src/overlays/l10/mobys/breakable_prop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/breakable_prop.c b/src/overlays/l10/mobys/breakable_prop.c index 4b94081b72..14d9549a15 100644 --- a/src/overlays/l10/mobys/breakable_prop.c +++ b/src/overlays/l10/mobys/breakable_prop.c @@ -22,7 +22,7 @@ void breakable_prop_update(struct Moby *moby) { char *hit_result = find_moby_hit(moby, 0x10000, 0); switch (moby->state) { case HIT_RESPONSE_STATE_INITIALIZE: - moby->state = 1; + moby->state = HIT_RESPONSE_STATE_WAIT_FOR_HIT; break; case HIT_RESPONSE_STATE_WAIT_FOR_HIT: if (hit_result != 0) { @@ -30,7 +30,7 @@ void breakable_prop_update(struct Moby *moby) { ok = 1; } if (ok != 0) - moby->state = 2; + moby->state = HIT_RESPONSE_STATE_RESPOND_AND_REMOVE; break; case HIT_RESPONSE_STATE_RESPOND_AND_REMOVE: allocate_voice_for_target_entry(0, 0, (int)moby); From dbc57fe168541c48b24a0d4c9e69388746da0a8b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:12:08 +0000 Subject: [PATCH 0471/1502] decomp: clarify names in _setDefaultQM domain_0_value_2 -> MPEG_CALLBACK_BEFORE_DEFAULT_MATRIX_LOAD: In the bound setdefaultqm.c snapshot, callback.type = 2 is dispatched before all IPU waits and matrix-load operations. Retail 0x0012c854 loads 2, 0x0012c880 stores it at sp, and 0x0012c87c dispatches that event via decoder->mpeg (loaded at 0x0012c878). The dispatcher indexes callbacks->entries[event->type]. The subsequent 0x0012c8c0/0x0012c8d0/0x0012c8dc DMA writes transfer four quadwords from the caller-selected default matrix, followed by the IQ command. _sequenceHeader supplies the default intra/non-intra matrices at calls 0x0012c454 and 0x0012c4a0. This proves the callback's before-default-matrix-load role, without inferring its handler effects. domain_1_value_3 -> MPEG_CALLBACK_AFTER_DEFAULT_MATRIX_LOAD: Retail 0x0012c8f4 submits the caller's IQ command after the four-quadword matrix DMA setup; 0x0012c8fc waits for IPU idle. Only afterward does 0x0012c908 load 3 and 0x0012c90c store that type in the same stack callback event, dispatched at 0x0012c910 through decoder->mpeg. The bound C likewise assigns callback.type = 3 after _sendIpuCommand and the final _waitIpuIdle. _sequenceHeader calls this routine with default intra/non-intra quantizer matrices. This proves the after-default-matrix-load callback role, without asserting what the selected handler does. --- src/sdk/mpeg/headers/setdefaultqm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/sdk/mpeg/headers/setdefaultqm.c b/src/sdk/mpeg/headers/setdefaultqm.c index 4394728de5..942e861fb4 100644 --- a/src/sdk/mpeg/headers/setdefaultqm.c +++ b/src/sdk/mpeg/headers/setdefaultqm.c @@ -8,10 +8,14 @@ extern s32 DIntr(void); void _setDefaultQM(struct MpegDecoder *decoder, s32 command, u32 matrix) { + enum { + MPEG_CALLBACK_BEFORE_DEFAULT_MATRIX_LOAD = 2, + MPEG_CALLBACK_AFTER_DEFAULT_MATRIX_LOAD = 3 + }; s32 interrupts_enabled; struct sceMpegCbData callback; - callback.type = 2; + callback.type = MPEG_CALLBACK_BEFORE_DEFAULT_MATRIX_LOAD; _dispatchMpegCallback(decoder->mpeg, &callback); _waitIpuIdle(decoder); *IPU_CMD = 0; @@ -25,6 +29,6 @@ void _setDefaultQM(struct MpegDecoder *decoder, s32 command, u32 matrix) { } SendIpuCommand(decoder, command); _waitIpuIdle(decoder); - callback.type = 3; + callback.type = MPEG_CALLBACK_AFTER_DEFAULT_MATRIX_LOAD; _dispatchMpegCallback(decoder->mpeg, &callback); } From 70e5dc23d8a7f4be48a3a8c39c0874ab095c9f91 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:12:08 +0000 Subject: [PATCH 0472/1502] decomp: clarify names in play_level_transition_movie domain_0_value_0 -> PAL_MODE_NTSC: The source snapshot src/game/transitions/play_level_transition_movie.c (SHA-256 3aeca0b729a6f2f7357e84053fd64708f89a7fe61925b592c73d55ac52ebf7b0) tests pal_mode != 0. Retail 0x00231610 loads this selector from 0x0015ed80; beq at 0x00231618 sends zero to 0x00231640, where 0x00231654/0x00231658 read the indexed descriptors at 0x001394bc/0x001394b8. The supplied original Ghidra decompilation identifies this zero branch as g_pNtscLevelMovieDescriptors and the nonzero branch as g_pPalLevelMovieDescriptors. Thus zero denotes the NTSC selection specifically within the pal_mode domain, supporting PAL_MODE_NTSC rather than an unrelated equal-valued constant. --- src/game/transitions/play_level_transition_movie.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/game/transitions/play_level_transition_movie.c b/src/game/transitions/play_level_transition_movie.c index 89f922c324..6298d51e1a 100644 --- a/src/game/transitions/play_level_transition_movie.c +++ b/src/game/transitions/play_level_transition_movie.c @@ -12,11 +12,14 @@ extern void fade_to_black(s32) __asm__("func_001F4A58"); void play_level_transition_movie(s32 movie_index) __asm__("FUN_00231608"); void play_level_transition_movie(s32 movie_index) { + enum { + PAL_MODE_NTSC = 0 + }; s32 stream_size; s32 stream_start; s32 archive_base; - if (pal_mode != 0) { + if (pal_mode != PAL_MODE_NTSC) { stream_start = disc_table.movies_alt[movie_index].sector; stream_size = disc_table.movies_alt[movie_index].size; } else { From 3990c79341d598f2bb3f3626afe4c273ffe7d085 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:12:08 +0000 Subject: [PATCH 0473/1502] decomp: clarify names in cave_door_update domain_0_value_1 -> CAVE_DOOR_STATE_UPDATE_ROTATION: Retail 0x002f4360 loads cave_door_moby state from +0x20; 0x002f436c-0x002f4370 compares that byte with 1 and selects rotation update at 0x002f43ac. Initialization at 0x002f4380-0x002f43a0 saves initial rotation and converts speed to radians; 0x002f4384 loads 1 and 0x002f43a8 stores it to the same +0x20 state byte. The authoritative C already names that same selector's case 1 CAVE_DOOR_STATE_UPDATE_ROTATION, whose branch computes and stores rot.x at 0x002f4408. Therefore the assignment reuses the exact existing state-domain member, not TRUE or an unrelated equal-valued constant. --- src/overlays/l01/mobys/cave_door.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/cave_door.c b/src/overlays/l01/mobys/cave_door.c index a5719048ae..397b1da1a1 100644 --- a/src/overlays/l01/mobys/cave_door.c +++ b/src/overlays/l01/mobys/cave_door.c @@ -33,7 +33,7 @@ void cave_door_update(struct Moby *cave_door_moby) { case CAVE_DOOR_STATE_INITIALIZE: cave_door_vars->angle = cave_door_moby->rot.x; cave_door_vars->speed = cave_door_vars->speed * DEG_TO_RAD; - cave_door_moby->state = 1; + cave_door_moby->state = CAVE_DOOR_STATE_UPDATE_ROTATION; break; case CAVE_DOOR_STATE_UPDATE_ROTATION: if (cave_door_vars->target != -1) { From 6a8422a03adc6288b79a77cc0214af37a5ef4b16 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:12:08 +0000 Subject: [PATCH 0474/1502] decomp: clarify names in set_planar_vel domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Retail 0x002120fc establishes s0=&hero (0x0013f350); lbu v0,0x20b3(s0) at 0x00212114 reads hero.gravity_mode and beq v0,zero at 0x00212118 selects the spherical constructor at 0x00212180-0x0021218c using world yaw and ground_pitch. Original Ghidra tests cRam00141403 == '\0' for that same path; nonzero instead rotates a flat speed vector with the hero moby's rotation. Supplied source update_hero_ground_contact_and_surface_slopes switches on this exact hero.gravity_mode field and uses HERO_GRAVITY_WORLD_DOWN to set gravity_dir.z=-1. Thus the selector belongs to shared enum HeroGravityMode (include/rnc/hero/hero_state.h), whose canonical zero member is HERO_GRAVITY_WORLD_DOWN; turn_to already compares the same field against this member. --- src/overlays/shared/hero/hero_switch_item.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 5c0be4af32..b4f6bec912 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -3101,7 +3101,7 @@ void set_planar_vel(float radians) { } ground_speed = hero_state->ground_speed; - if (hero_state->gravity_mode != 0) { + if (hero_state->gravity_mode != HERO_GRAVITY_WORLD_DOWN) { float matrix[16]; float velocity_vector[4]; From eefc91118d1b1e530f288ed65b250beac18568f5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:14:00 +0000 Subject: [PATCH 0475/1502] decomp: clarify names in apply_cutscene_big_head_cheat domain_0_value_2 -> CUTSCENE_MODE_PLAYING: Retail 0x002fac88 loads cutscene_mode at 0x0015f5c4; 0x002fac90/0x002facac require 2 before the big-head attachment loop. Checked caller 0x002fad84 invokes this function. Its start_scene(3) call at 0x002fb22c enters state 6, whose 0x002fb244-0x002fb24c load the identical mode address and return while it equals 2; after it changes, scene/movie progression resumes. start_scene(4) at 0x002fb27c enters state 8, which likewise waits at 0x002fb294-0x002fb29c while mode equals 2 before unlock_planet(3). These retail branches and the supplied caller source prove scene playback mode, independently of moby state IDs. --- src/overlays/l01/mobys/agnogg_ship_front.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/agnogg_ship_front.c b/src/overlays/l01/mobys/agnogg_ship_front.c index 5f020c0ae3..917319b63d 100644 --- a/src/overlays/l01/mobys/agnogg_ship_front.c +++ b/src/overlays/l01/mobys/agnogg_ship_front.c @@ -45,9 +45,12 @@ extern MobyList fx_cutscene __asm__("D_L01_0016CCE0"); void apply_cutscene_big_head_cheat(void) __asm__("FUN_L01_002fac80"); void apply_cutscene_big_head_cheat(void) { + enum { + CUTSCENE_MODE_PLAYING = 2 + }; s32 i; - if (cutscene_mode == 2 && big_head_cheat_enabled != 0) { + if (cutscene_mode == CUTSCENE_MODE_PLAYING && big_head_cheat_enabled != 0) { for (i = 0; i < fx_cutscene.count; i++) { if (fx_cutscene.list[i]->type == 0x32B && D_L01_0017C8C0.active == 0) { attach_manipulator(fx_cutscene.list[i], 0, &D_L01_0017C8C0); From 3173b5510778d9829d83a6de835303f58e4d70db Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:14:00 +0000 Subject: [PATCH 0476/1502] decomp: clarify names in update_shattering_prop domain_0_value_1 -> HIT_RESPONSE_STATE_WAIT_FOR_HIT: The source switches on moby->state with existing HIT_RESPONSE_STATE_WAIT_FOR_HIT = 1. Retail 0x002eb710 reads byte +0x20(s0), 0x002eb718 dispatches value 1 to the nonnull hit-record/positive +0x2C test, and initialization stores 1 to that identical byte at 0x002eb750. Original Ghidra confirms the same param_1 +0x20 read/write, proving this assignment enters the existing wait-for-hit state domain. domain_1_value_2 -> HIT_RESPONSE_STATE_RESPOND_AND_REMOVE: Retail 0x002eb754-0x002eb778 checks the hit lookup result and positive float +0x2C, then 0x002eb77c/0x002eb784 stores 2 to +0x20(s0), the same state byte read at 0x002eb710. Dispatch at 0x002eb73c sends state 2 to response calls 0x002eb790/0x002eb798/0x002eb7b8 and removal 0x002eb7c0. Original Ghidra and the source's existing HIT_RESPONSE_STATE_RESPOND_AND_REMOVE = 2 case establish this exact local enum domain. --- src/overlays/l10/mobys/shattering_prop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/shattering_prop.c b/src/overlays/l10/mobys/shattering_prop.c index f865d6bd6b..c9d1c4ed56 100644 --- a/src/overlays/l10/mobys/shattering_prop.c +++ b/src/overlays/l10/mobys/shattering_prop.c @@ -23,13 +23,13 @@ void shattering_prop_update(struct Moby *moby) { char *hit_record = find_moby_hit(moby, 0x10000, 0); switch (moby->state) { case HIT_RESPONSE_STATE_INITIALIZE: - moby->state = 1; + moby->state = HIT_RESPONSE_STATE_WAIT_FOR_HIT; break; case HIT_RESPONSE_STATE_WAIT_FOR_HIT: if (hit_record != 0 && *(float *)(hit_record + 0x2C) > 0.0f) hit = 1; if (hit) - moby->state = 2; + moby->state = HIT_RESPONSE_STATE_RESPOND_AND_REMOVE; break; case HIT_RESPONSE_STATE_RESPOND_AND_REMOVE: allocate_voice_for_target_entry(0, 0, (int)moby); From d9563025b0d629d1a3bfeeeb5d747ca6bfc021c6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:14:00 +0000 Subject: [PATCH 0477/1502] decomp: clarify names in update_spinning_sprite_effect domain_0_value_1 -> MOBY_STATE_SPIN_AND_DRAW_SPRITES: Retail 0x002c9498 loads state from 0x20(s0), and 0x002c94a0-0x002c94a4 compare that same byte with 1 to enter 0x002c9524. Initialization loads v0=1 at 0x002c9510 and stores it back to 0x20(s0) at 0x002c9520. Thus this assignment enters the exact same moby->state domain already named by the local enum MOBY_STATE_SPIN_AND_DRAW_SPRITES=1. Its branch updates rot.z at 0x002c9538-0x002c9544 and calls the supplied four-sprite drawing helper at 0x002c9548, proving reuse of the established member. --- src/overlays/l16/mobys/spinning_sprite_effect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/spinning_sprite_effect.c b/src/overlays/l16/mobys/spinning_sprite_effect.c index f3e310b216..e71f09b683 100644 --- a/src/overlays/l16/mobys/spinning_sprite_effect.c +++ b/src/overlays/l16/mobys/spinning_sprite_effect.c @@ -46,7 +46,7 @@ void spinning_sprite_effect_update(struct Moby *moby) { if (vertical_distance_to_ground < 1.0f) { moby->pos.z = ground_height + 0.9f; } - moby->state = 1; + moby->state = MOBY_STATE_SPIN_AND_DRAW_SPRITES; break; } case MOBY_STATE_SPIN_AND_DRAW_SPRITES: From 5074e23106491f2bc0349e5379b4b81db91bf196 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:15:57 +0000 Subject: [PATCH 0478/1502] decomp: clarify names in update_target_tracking_camera domain_0_value_44 -> HERO_STATE_GRAPPLE_SWING_ENTRY: The bound source snapshot (SHA-256 6244c3eaac8fb1044850d5e6f7f5a8825b8867064ade134ebc46736d10d3431d) sets b=&hero and hero_state=b->state.current. Retail 0x002ec6c4/0x002ec6cc forms hero base 0x0013F350; 0x002ec6e8 loads its current-state field +0x2084, and 0x002ec6dc/0x002ec6ec compares that loaded state with 44. Original Ghidra likewise tests iRam001413d4 == 0x2c. Thus this is the shared HeroStateId selector, whose canonical member in supplied include/rnc/hero/hero_state.h is HERO_STATE_GRAPPLE_SWING_ENTRY=44. The selected branch loads hero+0x994 (swing_target_moby) at 0x002ec700 and compares it with the saved camera target at 0x002ec71c, consistent with the canonical swing state. --- src/overlays/shared/camera/target_tracking_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/camera/target_tracking_camera.c b/src/overlays/shared/camera/target_tracking_camera.c index 1b61a454fc..6c55570f89 100644 --- a/src/overlays/shared/camera/target_tracking_camera.c +++ b/src/overlays/shared/camera/target_tracking_camera.c @@ -323,7 +323,7 @@ void update_target_tracking_camera(char *camera_object) { int hero_state = b->state.current; char *camera_position; int x, y; - if (hero_state == 0x2C) { + if (hero_state == HERO_STATE_GRAPPLE_SWING_ENTRY) { camera_position = camera_object + 0x30; x = *(int *)(camera_target_state + 8); y = ((int)b->swing_target_moby); From 140dfdb921ca73bef99251fb955f93bd3c6f1682 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:15:57 +0000 Subject: [PATCH 0479/1502] decomp: clarify names in update_moby_visibility_and_half_turn domain_0_value_1 -> WAIT_TO_HIDE_AND_TURN: The selector is moby->state, loaded from +0x20 at 0x002fa658. State 0 stores 1 to that same byte at 0x002fa690; dispatch of 1 at 0x002fa65c enters the global-gated hide/half-turn branch at 0x002fa694. This is exactly the existing local enum member WAIT_TO_HIDE_AND_TURN, not a global control value. domain_1_value_2 -> HIDDEN_WAIT_TO_SHOW: At 0x002fa6c0 visible (+0x31) is cleared, flag bit 0 is set, and rot.x receives a half-turn. At 0x002fa6e0 the validated value 2 is stored to moby->state (+0x20). Dispatch of that same state at 0x002fa67c enters 0x002fa6ec, which waits until the global differs from 2 before restoring visibility. This proves reuse of existing HIDDEN_WAIT_TO_SHOW in the same local state domain. domain_2_value_3 -> VISIBLE_RESTORED: In the HIDDEN_WAIT_TO_SHOW branch, 0x002fa6f4 skips restoration while the global equals 2. Otherwise 0x002fa6f8/0x002fa700 store 3 to moby->state (+0x20), 0x002fa708 restores visible (+0x31) to 1, and 0x002fa704/0x002fa70c clear flag bit 0. State 3 therefore records restored visibility; this name makes no claim about rotation reversal or external transitions. --- src/overlays/l18/mobys/hidden_deplanetizer_gun.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/l18/mobys/hidden_deplanetizer_gun.c b/src/overlays/l18/mobys/hidden_deplanetizer_gun.c index ae9616ffa5..b684988897 100644 --- a/src/overlays/l18/mobys/hidden_deplanetizer_gun.c +++ b/src/overlays/l18/mobys/hidden_deplanetizer_gun.c @@ -21,22 +21,25 @@ void hidden_deplanetizer_gun_update(struct Moby *moby) { WAIT_TO_HIDE_AND_TURN = 1, HIDDEN_WAIT_TO_SHOW = 2 }; + enum { + VISIBLE_RESTORED = 3 + }; switch (moby->state) { case INITIALIZE_STATE_MACHINE: - moby->state = 1; + moby->state = WAIT_TO_HIDE_AND_TURN; break; case WAIT_TO_HIDE_AND_TURN: if (D_L18_0015F5C4 == 2 && D_L18_0016D290_lui == 3) { moby->flags |= 1; moby->visible = 0; moby->rot.x = fast_add_rotations(moby->rot.x, 3.1415927f); - moby->state = 2; + moby->state = HIDDEN_WAIT_TO_SHOW; } break; case HIDDEN_WAIT_TO_SHOW: if (D_L18_0015F5C4 != 2) { unsigned short fl = moby->flags; - moby->state = 3; + moby->state = VISIBLE_RESTORED; fl &= 0xFFFE; moby->visible = 1; moby->flags = fl; From d4ca4a13e9c855e727788ea17ff762f1755addea Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:15:57 +0000 Subject: [PATCH 0480/1502] decomp: clarify names in start_camera_transition domain_0_value_2 -> CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP: Retail 0x002dfb08 loads 2 and 0x002dfb18 stores that byte to the first argument's +0x20 moby state; original Ghidra confirms *(undefined1 *)(param_1 + 0x20) = 2. The same moby's pvars are initialized with start/target positions and rotations at 0x002dfac0-0x002dfb04 and transition timing at 0x002dfb30-0x002dfb64. Supplied update_camera_transition switches on moby->state and names case 2 STATE_PRE_TRANSITION_RAMP_UP: it approaches pvars+0x6C to 1, then installs camera setup and advances to interpolation state 3 or 4. Supplied classify_moby_state_two_or_three already names the same camera-transition state CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP = 2, with callers applying it to boss_data->f334, the same object passed to start_camera_transition. Reuse this established member for the state assignment; equal-valued Hero constants belong to unrelated domains. --- src/overlays/l18/mobys/camera_transition.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/camera_transition.c b/src/overlays/l18/mobys/camera_transition.c index 9b4cb4fc66..753df30dc6 100644 --- a/src/overlays/l18/mobys/camera_transition.c +++ b/src/overlays/l18/mobys/camera_transition.c @@ -243,7 +243,7 @@ void start_camera_transition(struct Moby *moby, int transition_delay_frames, int transition_mode) { - BossCameraTransitionVars *position_rotation_transition_vars = + enum { CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP = 2 } ;BossCameraTransitionVars *position_rotation_transition_vars = (BossCameraTransitionVars *)moby->pvars; *(int *)&position_rotation_transition_vars->unk60 = 0; position_rotation_transition_vars->unk64 = 0; @@ -252,7 +252,7 @@ void start_camera_transition(struct Moby *moby, qcopy(&position_rotation_transition_vars->unk20, transition_start_rotation); qcopy(position_rotation_transition_vars->unk30, transition_target_rotation); qcopy(&position_rotation_transition_vars->unk40, transition_setup_vector); - moby->state = 2; + moby->state = CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP; position_rotation_transition_vars->unk68 = frame_time_sq * 0.333f; position_rotation_transition_vars->unk70 = 1.0f / (float)scale_game_frames(invulnerability_duration_frames); From 4baeedd9807fea42b6c9a3b842d0e82307ed2bc7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:15:57 +0000 Subject: [PATCH 0481/1502] decomp: clarify names in close_menu_system domain_0_value_20 -> MENU_SYSTEM_STATE_FINALIZE_CLOSE: The authoritative close_menu_system source (SHA-256 c872fa17e3dc6ee5e406b738e07953155182a0d2fe19ef0c0f19193a5751a841) binds this assignment to menu_system.state. Retail 0x0021927c/0x00219288 writes 20 to 0x001d5bf0 after screen leave callbacks, clearing current, restoring texture allocation and deleting all 14 panel mobys; 0x00219284/0x0021928c sets its timer to 2. Checked caller 0x002192a8 reads that identical state address at 0x002192ec and selects 20 at 0x002192f0-0x002192f4. This branch decrements the timer at 0x002192fc-0x0021930c, waits for inactive disc I/O at 0x00219314-0x00219318, then calls 0x002335a0 and publish_camera_environment and clears menu activity/flags at 0x00219338-0x00219358. This proves a menu close finalization phase rather than a moby or control-mode domain. --- src/ui/menus/system/close_menu_system.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/menus/system/close_menu_system.c b/src/ui/menus/system/close_menu_system.c index 1a414967e5..9e7e950080 100644 --- a/src/ui/menus/system/close_menu_system.c +++ b/src/ui/menus/system/close_menu_system.c @@ -8,6 +8,9 @@ void close_menu_system(void) __asm__("FUN_002191b8"); void close_menu_system(void) { + enum { + MENU_SYSTEM_STATE_FINALIZE_CLOSE = 20 + }; s32 i; s32 j; struct MenuScreen *screen; @@ -28,7 +31,7 @@ void close_menu_system(void) { for (j = 0; j < 14; j++) { panel_slots[j] = (void *)delete_moby(panel_slots[j]); } - menu_system.state = 20; + menu_system.state = MENU_SYSTEM_STATE_FINALIZE_CLOSE; menu_system.timer = 2; } From d3b07ce11dba950843148776b3bade7a10a206c5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:17:55 +0000 Subject: [PATCH 0482/1502] decomp: clarify names in update_group_clear_trigger domain_0_value_1 -> MOBY_UPDATE_CUTSCENE_TARGET: Authoritative source src/overlays/l14/mobys/group_clear_trigger.c SHA-256 89a0bda1b6142cfa5f27aca2b02c3deaa93c96b8ccdc42494c588a0e815d78bf switches on moby->state and already defines MOBY_UPDATE_CUTSCENE_TARGET = 1 for that exact selector. Retail 0x0030884c loads 1 and 0x00308850 stores it to moby +0x20, the same byte loaded at 0x0030882c and compared with 1 at 0x00308838 to select 0x0030885c. The original Ghidra decompilation confirms this zero-state-to-one transition. The selected branch gates on mode 2 and scene-minus-3 below 3 before the checked cutscene_set_camera_target call at 0x00308898. Thus this assignment reuses the existing member of the identical state domain, rather than a numerically equal boolean or another subsystem enum. --- src/overlays/l14/mobys/group_clear_trigger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/group_clear_trigger.c b/src/overlays/l14/mobys/group_clear_trigger.c index f7e97227be..ed0bcffa4c 100644 --- a/src/overlays/l14/mobys/group_clear_trigger.c +++ b/src/overlays/l14/mobys/group_clear_trigger.c @@ -36,7 +36,7 @@ void group_clear_trigger_update(struct Moby *moby) { switch (moby->state) { case MOBY_UPDATE_DISTANCE_INITIALIZE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = MOBY_UPDATE_CUTSCENE_TARGET; break; case MOBY_UPDATE_CUTSCENE_TARGET: if (D_L14_0015F5C4 == 2) { From 9f4e310a41728822fdce5293d3f35c5940006157 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:17:56 +0000 Subject: [PATCH 0483/1502] decomp: clarify names in spawn_mode_controlled_alpha_fade_particle domain_0_value_2 -> PARTICLE_MODE_PARENT_RELATIVE_ALPHA_FADE: Retail 0x00273724 retains a2 in s2; 0x0027379c stores its original value at particle+0x22 before 0x002737a0 compares s2 against 2. The authoritative update_mode_controlled_alpha_fade_particle reads that same short: mode 2 sets all three position coordinates from the parent pointer at +0x24 plus offsets at +0x30/+0x34/+0x38, then subtracts the +0x20 alpha decrement. Thus 2 names the parent-relative alpha-fade mode, even though this spawn comparison also maps larger values to texture zero. domain_1_value_0 -> PARTICLE_MODE_STATIONARY_ALPHA_FADE: Original Ghidra and retail 0x0027379c preserve the incoming particle mode at +0x22; 0x002737a0-0x002737b4 replace only the working table index with zero when mode >=2, then load D_L00_001B2178[index] into particle+2. The supplied updater uses the retained mode: mode 1 returns, mode 2 updates parent-relative position, and mode 0 reaches alpha subtraction/freeing with no position update. Zero therefore denotes the stationary alpha-fade mode whose texture is also reused by mode 2. --- src/overlays/shared/rendering/effects/particles.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/rendering/effects/particles.c b/src/overlays/shared/rendering/effects/particles.c index 8a309acd31..b39145d8ee 100644 --- a/src/overlays/shared/rendering/effects/particles.c +++ b/src/overlays/shared/rendering/effects/particles.c @@ -1176,6 +1176,10 @@ unsigned char *spawn_mode_controlled_alpha_fade_particle(void *position, int alpha_fade_divisor, int particle_mode) { + enum { + PARTICLE_MODE_STATIONARY_ALPHA_FADE = 0, + PARTICLE_MODE_PARENT_RELATIVE_ALPHA_FADE = 2 + }; unsigned char *particle = create_part(0x3E); if (particle != 0) { unsigned char *particle_data = particle + 0x20; @@ -1187,8 +1191,8 @@ unsigned char *spawn_mode_controlled_alpha_fade_particle(void *position, *(float *)(particle + 0xC) = 30000.0f; particle[8] = random_integer_below(0xFF); *(short *)(particle_data + 2) = particle_mode; - if (particle_mode >= 2) - particle_mode = 0; + if (particle_mode >= PARTICLE_MODE_PARENT_RELATIVE_ALPHA_FADE) + particle_mode = PARTICLE_MODE_STATIONARY_ALPHA_FADE; particle[2] = D_L00_001B2178[particle_mode]; *(short *)(particle + 0x20) = truncate_float_to_s32(127.0f / convert_integer_to_float(alpha_fade_divisor)); From 74d15c503732d2cce9c2fb594dcf8115c1ec1ae7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:17:56 +0000 Subject: [PATCH 0484/1502] decomp: clarify names in process_spawner_hit_record domain_1_value_2 -> SPAWNER_STATE_EXPLODE: Retail 0x0030a9fc saves the moby argument in s0; 0x0030aa94 loads 2 and 0x0030aa9c stores it to s0+0x20 after the remaining amount becomes nonpositive. Original Ghidra likewise writes param_1+0x20 = 2. The authoritative spawner_update passes this same moby to process_spawner_hit_record and then switches on its byte at +0x20; its established SPAWNER_STATE_EXPLODE = 2 branch emits explosion/debris effects and calls mark_moby_for_removal. This is the same spawner state domain, independently of the unrelated record_processing_status >= 2 comparison. --- src/overlays/shared/enemies/spawner.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/spawner.c b/src/overlays/shared/enemies/spawner.c index b59d5d89b3..e773a15fa5 100644 --- a/src/overlays/shared/enemies/spawner.c +++ b/src/overlays/shared/enemies/spawner.c @@ -87,6 +87,9 @@ extern f32 frame_time_sq_macro __asm__("D_0015ED70") MACRO_ADDR; void process_spawner_hit_record(struct Moby *moby, char *spawner_vars) __asm__("FUN_L09_0030a9e8"); void process_spawner_hit_record(struct Moby *moby, char *spawner_vars) { + enum { + SPAWNER_STATE_EXPLODE = 2 + }; char *moby_record; int record_processing_status; float remaining_value; @@ -102,7 +105,7 @@ void process_spawner_hit_record(struct Moby *moby, char *spawner_vars) { FUN_L00_0025d458_c(moby, spawner_vars + 0x60); } else { FUN_L00_00257470_c(moby, 0, -1); - moby->state = 2; + moby->state = SPAWNER_STATE_EXPLODE; spawner_vars[0x67] = 0x78; FUN_L00_0025d458_c(moby, spawner_vars + 0x60); } From c898177578d6609a4d625c4f740203cf87f067c9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:17:56 +0000 Subject: [PATCH 0485/1502] decomp: clarify names in pipe_update domain_0_value_1 -> PIPE_WAIT_FOR_HIT: In source pipe_update, the assignment pipe_moby->state = 1 targets the exact selector of case PIPE_WAIT_FOR_HIT = 1. Retail loads that byte at 0x002e79c8 from s0+0x20; the state-zero branch stores 1 to the same byte at 0x002e7a08. On the next update, comparison at 0x002e79d0 dispatches value 1 to 0x002e7a0c, which waits for a non-null hit lookup result and a positive float at +0x2C. This proves reuse of the existing PIPE_WAIT_FOR_HIT member rather than an unrelated numeric constant. domain_1_value_2 -> PIPE_REMOVE: Source assigns pipe_moby->state = 2 in PIPE_WAIT_FOR_HIT after its hit test and defines case PIPE_REMOVE = 2 on that same state selector. Retail 0x002e7a34 loads 2 and 0x002e7a3c stores it to s0+0x20, the byte read by dispatch at 0x002e79c8. Comparison 0x002e79f4 sends state 2 to 0x002e7a40, whose voice, bolts, fragments and placement-spawn calls culminate in mark_moby_for_removal at 0x002e7a84. This proves the existing PIPE_REMOVE state member. --- src/overlays/l04/mobys/pipe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l04/mobys/pipe.c b/src/overlays/l04/mobys/pipe.c index 5bfbfa8f46..79a89511fe 100644 --- a/src/overlays/l04/mobys/pipe.c +++ b/src/overlays/l04/mobys/pipe.c @@ -25,13 +25,13 @@ void pipe_update(struct Moby *pipe_moby) { struct Moby *hit_moby = find_moby_hit(pipe_moby, 0x10000, 0); switch (pipe_moby->state) { case PIPE_INITIALIZE: - pipe_moby->state = 1; + pipe_moby->state = PIPE_WAIT_FOR_HIT; break; case PIPE_WAIT_FOR_HIT: if (hit_moby != 0 && hit_moby->scale > 0.0f) hit = 1; if (hit) - pipe_moby->state = 2; + pipe_moby->state = PIPE_REMOVE; break; case PIPE_REMOVE: allocate_voice_for_target_entry(0, 0, (int)pipe_moby); From d2a006b0b3ae67d1d07d1e228ae25c7d2360b442 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:17:56 +0000 Subject: [PATCH 0486/1502] decomp: clarify names in mark_moby_killed_and_release_owned_voice domain_0_value_2 -> MOBY_KILLED: The authoritative sentrybot.c snapshot (SHA-256 9a0a1c5bd777640cb86d1c6f9cfaba3dd6c8ce7b1cbcdab19e77a0df5f6f4d81) assigns moby->state=2 at the end of mark_moby_killed_and_release_owned_voice. Retail 0x002a35f0 clears collision at +0x94; 0x002a35f8-0x002a3608 records mission+2 by save_id in the killed table, with the conditional secondary record at 0x002a3664. Retail 0x002a368c-0x002a36a8 releases an active voice only when its owner is this moby, then 0x002a36b0-0x002a36b8 stores 2 to state +0x20 and 0xFF to command +0xBC. The supplied sentrybot_update caller invokes this on linked mobys during deactivation and death cleanup and clears their saved indices; update_linked_spark_emitter tests the linked moby's state==2 to enter its shutdown path. These data flows prove MOBY_KILLED for this assignment, independently of unrelated hero enum values. --- src/overlays/shared/enemies/sentrybot.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/sentrybot.c b/src/overlays/shared/enemies/sentrybot.c index abd2245e25..1a10833d32 100644 --- a/src/overlays/shared/enemies/sentrybot.c +++ b/src/overlays/shared/enemies/sentrybot.c @@ -1768,6 +1768,9 @@ void draw_sentrybot_effect_quads(char *moby) { /* Marks the moby as killed in the level's spawn tables and releases the voice slot it still owns. */ void mark_moby_killed_and_release_owned_voice(int addr) { + enum { + MOBY_KILLED = 2 + }; struct Moby *moby = (struct Moby *)addr; s32 slot; moby->collision = 0; @@ -1785,7 +1788,7 @@ void mark_moby_killed_and_release_owned_voice(int addr) { } } moby->command = 0xFF; - moby->state = 2; + moby->state = MOBY_KILLED; } /* Ported from rac1-decomp (src/overlays/shared/vendor_00298BB8.c: func_L15_002CCE50), where it is exact; names translated to the US level program. */ From 507d7f7e403f3bafc46ec24e2427b741eeb7497e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:17:56 +0000 Subject: [PATCH 0487/1502] decomp: clarify names in create_moby domain_0_value_254 -> MOBY_STATE_REUSE_THRESHOLD: Retail 0x0020c528 loads the selected Moby slot's state byte at +0x20; 0x0020c530 sltiu against 0xFE and 0x0020c534 skip every lower state. States at or above this threshold proceed through the timestamp eligibility check at 0x0020c540-0x0020c54c, then initialization at 0x0020c560, sidecar clearing at 0x0020c594 and return of the allocated slot at 0x0020c5b8. Thus 0xFE is the state reuse threshold in create_moby, without asserting a broader lifecycle name. The direct initializer clears the 0x100-byte record at 0x0020c60c with zero in a1 at 0x0020c610, consistent with converting the eligible slot into an initialized object. --- src/mobys/create_moby.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mobys/create_moby.c b/src/mobys/create_moby.c index 3902b1ec25..371aadadc5 100644 --- a/src/mobys/create_moby.c +++ b/src/mobys/create_moby.c @@ -16,10 +16,13 @@ extern void init_moby_instance(struct Moby *, s32) __asm__("func_0020C5F struct Moby *create_moby(s32 oclass) __asm__("FUN_0020c4f8"); struct Moby *create_moby(s32 oclass) { + enum { + MOBY_STATE_REUSE_THRESHOLD = 0xFE + }; struct Moby *moby_slot; for (moby_slot = moby_instance_end; moby_slot < moby_instance_perm_end; moby_slot++) { - if (moby_slot->state >= 0xFE && moby_slot->spawn_frame <= (u32)world_update_time) { + if (moby_slot->state >= MOBY_STATE_REUSE_THRESHOLD && moby_slot->spawn_frame <= (u32)world_update_time) { if (moby_slot->state == 0xFF) { moby_slot[1].state = 0xFF; } From fea4f127f79690029390dd2a5eefc31e78418a69 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:17:56 +0000 Subject: [PATCH 0488/1502] decomp: clarify names in update_shattering_prop domain_0_value_1 -> MOBY_STATE_WAIT_FOR_HIT: Retail 0030bc20 reads the dispatch byte at 0x20(s0); 0030bc24 loads 1 and 0030bc28 dispatches that state to the hit-wait branch at 0030bc64. The initialize branch at 0030bc3c/0030bc5c stores that same 1 to 0x20(s0) at 0030bc60. Thus source moby->state = 1 enters the existing local MOBY_STATE_WAIT_FOR_HIT case on the identical field, rather than an unrelated control domain. domain_1_value_2 -> MOBY_STATE_REMOVE: Retail 0030bc64-0030bc84 tests the find_moby_hit return for nonnull and float +0x2C > 0; 0030bc88-0030bc94 then loads 2 and stores it to the same state byte 0x20(s0) read at 0030bc20. Dispatch 0030bc38/0030bc4c sends state 2 to 0030bc98-0030bce0, ending in mark_moby_for_removal. This source moby->state = 2 therefore enters the existing local MOBY_STATE_REMOVE case. --- src/overlays/l08/mobys/shattering_prop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l08/mobys/shattering_prop.c b/src/overlays/l08/mobys/shattering_prop.c index 58c81067f2..7c70033e8b 100644 --- a/src/overlays/l08/mobys/shattering_prop.c +++ b/src/overlays/l08/mobys/shattering_prop.c @@ -23,13 +23,13 @@ void shattering_prop_update(struct Moby *moby) { char *hit_result = find_moby_hit(moby, 0x10000, 0); switch (moby->state) { case MOBY_STATE_INITIALIZE: - moby->state = 1; + moby->state = MOBY_STATE_WAIT_FOR_HIT; break; case MOBY_STATE_WAIT_FOR_HIT: if (hit_result != 0 && *(float *)(hit_result + 0x2C) > 0.0f) hit = 1; if (hit) - moby->state = 2; + moby->state = MOBY_STATE_REMOVE; break; case MOBY_STATE_REMOVE: allocate_voice_for_target_entry(0, 0, (int)moby); From 8e9fe5529f3d54c7e78b2859dc829976628a3049 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:17:56 +0000 Subject: [PATCH 0489/1502] decomp: clarify names in lamp_update domain_0_value_1 -> LAMP_STATE_WAIT_FOR_HIT: Authoritative lamp.c SHA-256 55354cac363ebb52669c591e6b9a6d52d04225737addb72350447da86f9b0494 assigns 1 to lamp_moby->state in LAMP_STATE_INITIALIZE and declares LAMP_STATE_WAIT_FOR_HIT = 1 for the same selector. Retail lbu v1,0x20(s0) at 0x0030a698 reads that state; the zero branch stores a0=1 to exactly 0x20(s0) at 0x0030a6d8. The state-1 branch at 0x0030a6a0/0x0030a6dc waits for the non-null hit result with positive float +0x2c. Original Ghidra likewise writes 1 to iVar4+0x20 on state zero. This is direct same-field transition evidence, not numeric equivalence across domains. domain_1_value_2 -> LAMP_STATE_REMOVAL_SEQUENCE: Authoritative lamp.c assigns 2 to lamp_moby->state after a qualifying hit and declares LAMP_STATE_REMOVAL_SEQUENCE = 2 for the very same switch selector. Retail at 0x0030a6dc tests the hit pointer, 0x0030a6e4/0x0030a6f0 tests its positive float +0x2c, and 0x0030a704/0x0030a70c stores 2 to 0x20(s0), the state field read at 0x0030a698. The state-2 dispatch at 0x0030a6c4 leads to voice/effect/spawn calls at 0x0030a718 through 0x0030a74c and mark_moby_for_removal at 0x0030a754. Original Ghidra confirms the same assignment and state-2 sequence. Reuse the existing local enum member for this proven same-field transition. --- src/overlays/l09/mobys/lamp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l09/mobys/lamp.c b/src/overlays/l09/mobys/lamp.c index a8d747fd88..e151bfd4bb 100644 --- a/src/overlays/l09/mobys/lamp.c +++ b/src/overlays/l09/mobys/lamp.c @@ -25,13 +25,13 @@ void lamp_update(struct Moby *lamp_moby) { struct Moby *hit_moby = find_moby_hit(lamp_moby, 0x10000, 0); switch (lamp_moby->state) { case LAMP_STATE_INITIALIZE: - lamp_moby->state = 1; + lamp_moby->state = LAMP_STATE_WAIT_FOR_HIT; break; case LAMP_STATE_WAIT_FOR_HIT: if (hit_moby != 0 && hit_moby->scale > 0.0f) hit = 1; if (hit) - lamp_moby->state = 2; + lamp_moby->state = LAMP_STATE_REMOVAL_SEQUENCE; break; case LAMP_STATE_REMOVAL_SEQUENCE: allocate_voice_for_target_entry(0, 0, (int)lamp_moby); From b47165aceb426beee618970855cff96f121a09c4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:19:48 +0000 Subject: [PATCH 0490/1502] decomp: clarify names in remove_bomber_tank_linked_debris domain_0_value_127 -> LINKED_MOBY_ACTIVE_STATE_LIMIT: In the authoritative bomber_tank.c snapshot (SHA-256 d2e3f578476cc7bbeab6814feb7e87b751e64c046711fa997f9a070a7ea467fb), the function comment identifies removal of active linked mobys. Retail 0x002d64d0 loads the current linked Moby state byte at +0x20 and 0x002d64d4 compares it unsigned against 0x7f; 0x002d64d8 skips removal eligibility when the comparison fails. Eligible non-self members of classes 0x24c..0x256 or 0x1d8 are passed to removal at 0x002d64fc/0x002d6518. Checked helper evidence request 87fe189c558141d49501899ec1aa08b7 proves 0x00259088/0x0025908c select 0xfd/0xfe and 0x00259090 stores that removal state to the same +0x20 byte. Thus this token is an exclusive active-state limit in the Moby state domain, not a particular tank state or the removal state itself. --- src/overlays/l08/mobys/bomber_tank.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/bomber_tank.c b/src/overlays/l08/mobys/bomber_tank.c index 37d07082b3..b885eba221 100644 --- a/src/overlays/l08/mobys/bomber_tank.c +++ b/src/overlays/l08/mobys/bomber_tank.c @@ -1167,6 +1167,9 @@ void scatter_bomber_tank_linked_debris(struct Moby *moby) { /* Remove active mobys of the selected classes from this moby's linked group. */ void remove_bomber_tank_linked_debris(struct Moby *moby) { + enum { + LINKED_MOBY_ACTIVE_STATE_LIMIT = 0x7f + }; short *list = D_L08_001AC040[(((struct Moby *)D_L08_0015FFD8) + *(s32 *)(moby->pvars + 0x144))->group]; struct Moby *linked_group_moby; @@ -1176,7 +1179,7 @@ void remove_bomber_tank_linked_debris(struct Moby *moby) { index = *list & 0x7fff; linked_group_moby = (struct Moby *)D_L08_0015FFD8 + index; while (1) { - if (linked_group_moby->state < 0x7f && linked_group_moby != moby) { + if (linked_group_moby->state < LINKED_MOBY_ACTIVE_STATE_LIMIT && linked_group_moby != moby) { u16 class_id = linked_group_moby->oclass; if ((u32)(class_id - 0x24c) < 0xb) { mark_moby_for_removal(linked_group_moby); From 22e1f826b0c8043e4f2704ae3ce59f60d9f0f8f5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:19:48 +0000 Subject: [PATCH 0491/1502] decomp: clarify names in lightpost_update domain_0_value_1 -> LIGHTPOST_WAIT_FOR_HIT: Source lightpost_update switches on lightpost_moby->state, with local LIGHTPOST_WAIT_FOR_HIT = 1. Retail 002e2964 retains the moby in s0 and 002e2968 loads its state at +0x20. The zero-state branch at 002e2984 reaches 002e29a8, storing a0=1 (loaded at 002e296c) into the identical +0x20 field. Retail 002e2970 routes that state value to 002e29ac, which waits for a non-null hit result and positive float +0x2C. Thus this assignment enters the existing LIGHTPOST_WAIT_FOR_HIT case, rather than a separate control domain. domain_1_value_2 -> LIGHTPOST_REMOVE: Source assigns 2 to lightpost_moby->state in LIGHTPOST_WAIT_FOR_HIT and the same selector has local LIGHTPOST_REMOVE = 2. Retail 002e29ac-002e29cc checks the hit-result pointer and positive float +0x2C; 002e29d0-002e29dc then loads 2 and stores it to the moby's state at +0x20. Retail 002e2994 dispatches that same state value to 002e29e0, executing audio/effect/spawn calls and mark_moby_for_removal at 002e2a24-002e2a28. This proves reuse of the existing LIGHTPOST_REMOVE enum member. --- src/overlays/l03/mobys/lightpost.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l03/mobys/lightpost.c b/src/overlays/l03/mobys/lightpost.c index 849bb4a9fd..522320a1a9 100644 --- a/src/overlays/l03/mobys/lightpost.c +++ b/src/overlays/l03/mobys/lightpost.c @@ -25,13 +25,13 @@ void lightpost_update(struct Moby *lightpost_moby) { char *hit_result = find_moby_hit(lightpost_moby, 0x10000, 0); switch (lightpost_moby->state) { case LIGHTPOST_INITIALIZE: - lightpost_moby->state = 1; + lightpost_moby->state = LIGHTPOST_WAIT_FOR_HIT; break; case LIGHTPOST_WAIT_FOR_HIT: if (hit_result != 0 && *(float *)(hit_result + 0x2C) > 0.0f) hit = 1; if (hit) - lightpost_moby->state = 2; + lightpost_moby->state = LIGHTPOST_REMOVE; break; case LIGHTPOST_REMOVE: allocate_voice_for_target_entry(0, 0, (int)lightpost_moby); From ffe35cc1105b65ba8b22023baba478a785c7e0d4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:21:38 +0000 Subject: [PATCH 0492/1502] decomp: clarify names in update_bolt_counter_hud_animation_and_visibility domain_0_value_1 -> BOLT_COUNTER_HUD_STATE_CLOSING: In update_bolt_counter_hud_animation_and_visibility, retail 0x00239d68-0x00239d74 branches when HUD +0x7c is below scale_game_frames(5), loading 1; 0x00239db0 stores it to this HUD element's +0x6c state. Instructions 0x00239db4-0x00239dd8 then decrement text visibility +0x71 first and panel opening +0x70 second. Only when both are zero does 0x00239ddc-0x00239de0 replace that state with -6. The authoritative draw_bolt_counter_hud_panel uses these same bytes for text fade and panel opening, proving this assignment denotes the bolt HUD closing phase. This selector is HUD-owned state, not any supplied hero enum domain. --- src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c index c48b2ba0f3..04e1bb93f8 100644 --- a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c +++ b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c @@ -1185,6 +1185,9 @@ extern s32 bolt_text_fade_steps_gp __asm__("D_L00_0015F828") __attribute__((sda) void update_bolt_counter_hud_animation_and_visibility(T00239d00 *hud_element) __asm__("FUN_L00_00239d00"); void update_bolt_counter_hud_animation_and_visibility(T00239d00 *hud_element) { + enum { + BOLT_COUNTER_HUD_STATE_CLOSING = 1 + }; u8 *visibility_counters = &hud_element->a; s32 icon_cycle_period = 60; s32 bolt_count_snapshot; @@ -1201,7 +1204,7 @@ void update_bolt_counter_hud_animation_and_visibility(T00239d00 *hud_element) { visibility_counters[1]++; } } else { - hud_element->state = 1; + hud_element->state = BOLT_COUNTER_HUD_STATE_CLOSING; if (visibility_counters[1] != 0) { visibility_counters[1]--; } else if (hud_element->a != 0) { From 7fe9cd7c79819f02645169de78ad13384bbe7a5a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:21:38 +0000 Subject: [PATCH 0493/1502] decomp: clarify names in load_scene_chunks_with_fade domain_0_value_0 -> PAL_MODE_DISABLED: The authoritative source compares the established global pal_mode with zero. Retail 0x002454d0 loads that selector and 0x002454d8 branches on nonzero to 0x00245518. The zero fallthrough loads sector/count from disc_table offsets 0x1530/0x1534 at 0x00245500/0x0024550c, while nonzero loads the alternative PAL pair 0x15a0/0x15a4 at 0x00245538/0x0024553c. Both feed start_audio_stream_read; therefore zero denotes disabled PAL table selection, without asserting NTSC or any particular nonzero encoding. --- src/overlays/shared/streaming/load_scene_chunks_with_fade.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/streaming/load_scene_chunks_with_fade.c b/src/overlays/shared/streaming/load_scene_chunks_with_fade.c index 020ca8ff67..a956e6ec32 100644 --- a/src/overlays/shared/streaming/load_scene_chunks_with_fade.c +++ b/src/overlays/shared/streaming/load_scene_chunks_with_fade.c @@ -17,9 +17,12 @@ void start_audio_stream_read(void *, s32, s32) __asm__("FUN_00216788"); void load_scene_chunks_with_fade(s32 i) __asm__("FUN_L00_002454c8"); void load_scene_chunks_with_fade(s32 i) { + enum { + PAL_MODE_DISABLED = 0 + }; s32 pointer_index; s32 *offset_entry; - if (pal_mode == 0) { + if (pal_mode == PAL_MODE_DISABLED) { start_audio_stream_read( D_L00_0016C860.buf, disc_table.unk1530[i].sector, disc_table.unk1530[i].size); } else { From 4fb1db76bb517d6a02d88b605fe3f3522d0df2f4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:21:38 +0000 Subject: [PATCH 0494/1502] decomp: clarify names in white_flower_update domain_0_value_1 -> WHITE_FLOWER_WAIT_FOR_HIT: The source switches on moby->state and already names its value-1 case WHITE_FLOWER_WAIT_FOR_HIT. Retail lbu at 0x002f1f80 reads +0x20(s0); the zero-state branch stores 1 to that exact byte at 0x002f1fc0. The value-1 branch at 0x002f1fc4 checks the find_moby_hit return and its positive +0x2C float. Thus this assignment enters the same established wait-for-hit domain member. domain_1_value_2 -> WHITE_FLOWER_REMOVE: The source's WHITE_FLOWER_WAIT_FOR_HIT case writes moby->state = 2 after a non-null hit record with positive +0x2C float. Retail 0x002f1fec loads 2 and 0x002f1ff4 stores it to +0x20(s0), the byte read for dispatch at 0x002f1f80. The value-2 branch at 0x002f1fac targets 0x002f1ff8, runs voice/bolt/fragment/placement calls, then mark_moby_for_removal at 0x002f203c. This is the existing local enum member WHITE_FLOWER_REMOVE. --- src/overlays/shared/props/white_flower.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/props/white_flower.c b/src/overlays/shared/props/white_flower.c index 31d971b923..c283d1751c 100644 --- a/src/overlays/shared/props/white_flower.c +++ b/src/overlays/shared/props/white_flower.c @@ -26,13 +26,13 @@ void white_flower_update(struct Moby *moby) { char *hit_record = find_moby_hit(moby, 0x10000, 0); switch (moby->state) { case WHITE_FLOWER_INITIALIZE: - moby->state = 1; + moby->state = WHITE_FLOWER_WAIT_FOR_HIT; break; case WHITE_FLOWER_WAIT_FOR_HIT: if (hit_record != 0 && *(float *)(hit_record + 0x2C) > 0.0f) hit = 1; if (hit) - moby->state = 2; + moby->state = WHITE_FLOWER_REMOVE; break; case WHITE_FLOWER_REMOVE: allocate_voice_for_target_entry(0, 0, (int)moby); From 4d02000e95e12914230778369b35706544100a17 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:21:38 +0000 Subject: [PATCH 0495/1502] decomp: clarify names in lamp_update domain_0_value_1 -> LAMP_STATE_WAIT_FOR_HIT: Source assigns 1 to lamp_moby->state in LAMP_STATE_INITIALIZE and dispatches the same field under existing LAMP_STATE_WAIT_FOR_HIT = 1. Retail lbu v1,0x20(s0) at 0x0031d7f8 selects the state; li a0,1 at 0x0031d7fc and sb a0,0x20(s0) at 0x0031d838 implement that assignment. The state-1 branch at 0x0031d83c checks the find_moby_hit result and its positive +0x2C float before transition, proving reuse of this exact lamp state domain. domain_1_value_2 -> LAMP_STATE_REMOVE: Source assigns 2 to lamp_moby->state after the hit check in LAMP_STATE_WAIT_FOR_HIT and already dispatches that field under LAMP_STATE_REMOVE = 2. Retail 0x0031d860 tests the hit flag, 0x0031d864 loads 2, and 0x0031d86c stores it to the same +0x20(s0) state byte read at 0x0031d7f8. State 2 branches at 0x0031d824 to the removal helper sequence 0x0031d870-0x0031d8b8, ending in mark_moby_for_removal. This proves the existing enum member belongs to this assignment's domain. --- src/overlays/l11/mobys/lamp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l11/mobys/lamp.c b/src/overlays/l11/mobys/lamp.c index 4a53295af6..fc31cecff9 100644 --- a/src/overlays/l11/mobys/lamp.c +++ b/src/overlays/l11/mobys/lamp.c @@ -24,13 +24,13 @@ void lamp_update(struct Moby *lamp_moby) { char *hit_result = find_moby_hit(lamp_moby, 0x10000, 0); switch (lamp_moby->state) { case LAMP_STATE_INITIALIZE: - lamp_moby->state = 1; + lamp_moby->state = LAMP_STATE_WAIT_FOR_HIT; break; case LAMP_STATE_WAIT_FOR_HIT: if (hit_result != 0 && *(float *)(hit_result + 0x2C) > 0.0f) hit = 1; if (hit) - lamp_moby->state = 2; + lamp_moby->state = LAMP_STATE_REMOVE; break; case LAMP_STATE_REMOVE: allocate_voice_for_target_entry(0, 0, (int)lamp_moby); From fb4140a90cc0673a461235987917d463e3031d04 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:21:38 +0000 Subject: [PATCH 0496/1502] decomp: clarify names in lamp_update domain_0_value_1 -> LAMP_STATE_WAIT_FOR_HIT: Authoritative lamp.c SHA-256 1ad7997ee3cd881ac2822422ac415a3b676b870763b6bf5abb4961a7f46dd544 assigns 1 to lamp_moby->state in LAMP_STATE_INITIALIZE. Retail 0030b6e8 reads state at +0x20(s0); 0030b6ec loads 1, 0030b6f0 dispatches that state to the hit-wait branch, and 0030b728 writes the same 1 to +0x20(s0) on initialization. Thus this assignment targets the exact existing local enum member LAMP_STATE_WAIT_FOR_HIT, whose branch null-checks the find_moby_hit result and tests its +0x2c float. domain_1_value_2 -> LAMP_STATE_REMOVE: In the authoritative source, the successful hit test in LAMP_STATE_WAIT_FOR_HIT assigns 2 to lamp_moby->state, the selector of the existing local enum switch. Retail 0030b734-0030b74c tests the hit object's +0x2c float; 0030b754 loads 2 and 0030b75c stores it at +0x20(s0). Retail 0030b700/0030b714 dispatch that same state value 2 to 0030b760-0030b7a8, which performs sound, bolt/fragment/placement spawning and mark_moby_for_removal on the lamp. This proves reuse of existing LAMP_STATE_REMOVE. --- src/overlays/l12/mobys/lamp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l12/mobys/lamp.c b/src/overlays/l12/mobys/lamp.c index 0c4560da7a..a1ca40c953 100644 --- a/src/overlays/l12/mobys/lamp.c +++ b/src/overlays/l12/mobys/lamp.c @@ -25,13 +25,13 @@ void lamp_update(struct Moby *lamp_moby) { struct Moby *hit_moby = find_moby_hit(lamp_moby, 0x10000, 0); switch (lamp_moby->state) { case LAMP_STATE_INITIALIZE: - lamp_moby->state = 1; + lamp_moby->state = LAMP_STATE_WAIT_FOR_HIT; break; case LAMP_STATE_WAIT_FOR_HIT: if (hit_moby != 0 && hit_moby->scale > 0.0f) hit = 1; if (hit) - lamp_moby->state = 2; + lamp_moby->state = LAMP_STATE_REMOVE; break; case LAMP_STATE_REMOVE: allocate_voice_for_target_entry(0, 0, (int)lamp_moby); From 8b55e2f3d9adae644a6bb993f365b3faae150ba9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:21:38 +0000 Subject: [PATCH 0497/1502] decomp: clarify names in test_dummy_door_update domain_0_value_1 -> TEST_DUMMY_DOOR_STATE_UPDATE_HEIGHT: The authoritative C initializes moby->state to literal 1 inside TEST_DUMMY_DOOR_STATE_INITIALIZE, while its existing enum defines TEST_DUMMY_DOOR_STATE_UPDATE_HEIGHT = 1 for the same switch(moby->state). Retail 0x002d5ccc loads the state byte at s0+0x20; 0x002d5cf0-0x002d5cf4 writes 1 to that exact byte. The comparison at 0x002d5cd8-0x002d5cdc dispatches that value to 0x002d5d00, whose timer-driven saved/offset height selection and scalar advancement at 0x002d5d60-0x002d5d98 implement the existing height-update case. Original Ghidra likewise writes byte +0x20 = 1 then dispatches byte +0x20 == 1 to the height updater. This proves reuse of the local door-state enum, without borrowing unrelated equal-valued hero constants. --- src/overlays/l16/mobys/test_dummy_door.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/test_dummy_door.c b/src/overlays/l16/mobys/test_dummy_door.c index 9b97856548..be45c54df9 100644 --- a/src/overlays/l16/mobys/test_dummy_door.c +++ b/src/overlays/l16/mobys/test_dummy_door.c @@ -41,7 +41,7 @@ void test_dummy_door_update(struct Moby *moby) { char *test_dummy_door_motion_data = (char *)moby->pvars; switch (moby->state) { case TEST_DUMMY_DOOR_STATE_INITIALIZE: - moby->state = 1; + moby->state = TEST_DUMMY_DOOR_STATE_UPDATE_HEIGHT; *(float *)test_dummy_door_motion_data = moby->pos.z; break; case TEST_DUMMY_DOOR_STATE_UPDATE_HEIGHT: { From 0a63aacb3039a8ef994e9b11566309f8910c6fe2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:21:38 +0000 Subject: [PATCH 0498/1502] decomp: clarify names in spawn_blarg_turret_child domain_0_value_0 -> BLARG_GUNNER_STATE_INITIALIZE: Retail 0x002b496c-0x002b4974 creates class 0x24 and retains the new moby in s0; 0x002b49c0 (sb zero,0x20(s0)) sets that new child's current state, separate from the command store at +0xbc at 0x002b49c4. The authoritative src/overlays/l13/mobys/blarg_gunner.c identifies this class and its blarg_gunner_update switches on moby->state with existing BLARG_GUNNER_STATE_INITIALIZE = 0; that branch initializes pvars +0x29/+0x5a/+0x58 and advances the gunner state to 1. Thus the assignment selects the child's established initialization state, not the parent's turret domain. --- src/overlays/l13/mobys/blarg_gunner.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/blarg_gunner.c b/src/overlays/l13/mobys/blarg_gunner.c index 3bab8a52dd..1913645121 100644 --- a/src/overlays/l13/mobys/blarg_gunner.c +++ b/src/overlays/l13/mobys/blarg_gunner.c @@ -64,6 +64,9 @@ extern void copy_hero_moby_field_38(struct Moby *moby) __asm__("FUN_L00_0025d1b8 struct Moby *spawn_blarg_turret_child(struct Moby *parent) __asm__("FUN_L13_002b4958"); struct Moby *spawn_blarg_turret_child(struct Moby *parent) { + enum { + BLARG_GUNNER_STATE_INITIALIZE = 0 + }; struct Moby *child_moby; Vars *child_vars; @@ -77,7 +80,7 @@ struct Moby *spawn_blarg_turret_child(struct Moby *parent) { child_moby->draw_dist = child_vars->parent->draw_dist; child_moby->visible = 1; child_moby->flags |= 0x20; - child_moby->state = 0; + child_moby->state = BLARG_GUNNER_STATE_INITIALIZE; child_moby->command = 0; qcopy(&child_moby->pos, &child_vars->parent->pos); child_moby->scale = child_moby->pclass->scale * parent->scale / parent->pclass->scale; From 439b2ef12001e4bf3a682e2b640dcae27f149556 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:23:35 +0000 Subject: [PATCH 0499/1502] decomp: clarify names in initialize_taxi_stop_from_position domain_0_value_1 -> TAXI_STATE_WAIT_AT_STOP: Retail 0x002f1050 preserves the input moby in s3; 0x002f10cc loads 1 into v1 and 0x002f10d4 stores it to byte +0x20 of that same moby, matching source moby->state. The supplied taxi_update switches on this same field and declares TAXI_STATE_WAIT_AT_STOP=1; its INITIALIZE branch passes moby directly to initialize_taxi_stop_from_position. That initializer selects a configured stop and caches position/rotation (0x002f10fc-0x002f1114), then taxi_update's WAIT_AT_STOP branch waits for the grounded hero and a departure request. This is the taxi current-state domain, independent of stop indices and Hero enums. --- src/overlays/l14/mobys/taxi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/taxi.c b/src/overlays/l14/mobys/taxi.c index 6f8cd5ab80..9e972316f5 100644 --- a/src/overlays/l14/mobys/taxi.c +++ b/src/overlays/l14/mobys/taxi.c @@ -381,6 +381,9 @@ struct L14PickVars { }; void initialize_taxi_stop_from_position(struct Moby *moby) { + enum { + TAXI_STATE_WAIT_AT_STOP = 1 + }; struct L14PickVars *taxi_vars = (struct L14PickVars *)moby->pvars; int i; taxi_vars->picked = -1; @@ -390,7 +393,7 @@ void initialize_taxi_stop_from_position(struct Moby *moby) { break; } } - moby->state = 1; + moby->state = TAXI_STATE_WAIT_AT_STOP; { int k = taxi_vars->points[taxi_vars->picked]; LevelCuboid *taxi_stops = l14_cuboids; From cfdb6d21cc4788cc7002298610225190ddb83566 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:23:36 +0000 Subject: [PATCH 0500/1502] decomp: clarify names in follow_camera_transition domain_0_value_3 -> CAM_ATTACH_BLEND_TO_PROJECT_HERO_FOCUS_VELOCITY: Retail 0x002e5750-0x002e5754 loads the camera saved-state pointer at owner +0x70 and forms attach_state = saved_state +0x40. The byte at attach_state +0xC4 (saved_state +0x104) is passed as a3 to compute_follow_camera_target_position at 0x002e578c-0x002e5794, then reloaded into v1 at 0x002e579c for these comparisons. The authoritative helper source switches that same argument using CameraAttachMode members, proving this selector's shared domain independently of numeric coincidence. 0x002e57a0-0x002e57a4 compares v1 with 3; the target helper names this mode CAM_ATTACH_BLEND_TO_PROJECT_HERO_FOCUS_VELOCITY and adds input_offset to stored_focus_position. Each selected comparison reaches 0x002e57cc, blending position stiffness and damping by the timer-derived weight before interpolation at 0x002e5808. domain_1_value_5 -> CAM_ATTACH_BLEND_FOCUS_VELOCITY_WITH_HOLD_TRANSITION: Retail 0x002e5750-0x002e5754 loads the camera saved-state pointer at owner +0x70 and forms attach_state = saved_state +0x40. The byte at attach_state +0xC4 (saved_state +0x104) is passed as a3 to compute_follow_camera_target_position at 0x002e578c-0x002e5794, then reloaded into v1 at 0x002e579c for these comparisons. The authoritative helper source switches that same argument using CameraAttachMode members, proving this selector's shared domain independently of numeric coincidence. 0x002e57a8-0x002e57ac compares v1 with 5; the target helper names this mode CAM_ATTACH_BLEND_FOCUS_VELOCITY_WITH_HOLD_TRANSITION and adds input_offset to stored_focus_position. Each selected comparison reaches 0x002e57cc, blending position stiffness and damping by the timer-derived weight before interpolation at 0x002e5808. domain_2_value_6 -> CAM_ATTACH_BLEND_OUT_FOCUS_VELOCITY: Retail 0x002e5750-0x002e5754 loads the camera saved-state pointer at owner +0x70 and forms attach_state = saved_state +0x40. The byte at attach_state +0xC4 (saved_state +0x104) is passed as a3 to compute_follow_camera_target_position at 0x002e578c-0x002e5794, then reloaded into v1 at 0x002e579c for these comparisons. The authoritative helper source switches that same argument using CameraAttachMode members, proving this selector's shared domain independently of numeric coincidence. 0x002e57b0-0x002e57b4 compares v1 with 6; the target helper names this mode CAM_ATTACH_BLEND_OUT_FOCUS_VELOCITY and adds input_offset to stored_focus_position. Each selected comparison reaches 0x002e57cc, blending position stiffness and damping by the timer-derived weight before interpolation at 0x002e5808. domain_3_value_7 -> CAM_ATTACH_BLEND_BACK_FOCUS_VELOCITY: Retail 0x002e5750-0x002e5754 loads the camera saved-state pointer at owner +0x70 and forms attach_state = saved_state +0x40. The byte at attach_state +0xC4 (saved_state +0x104) is passed as a3 to compute_follow_camera_target_position at 0x002e578c-0x002e5794, then reloaded into v1 at 0x002e579c for these comparisons. The authoritative helper source switches that same argument using CameraAttachMode members, proving this selector's shared domain independently of numeric coincidence. 0x002e57b8-0x002e57bc compares v1 with 7; the target helper names this mode CAM_ATTACH_BLEND_BACK_FOCUS_VELOCITY and adds input_offset to stored_focus_position. Each selected comparison reaches 0x002e57cc, blending position stiffness and damping by the timer-derived weight before interpolation at 0x002e5808. domain_4_value_1 -> CAM_ATTACH_HERO_POSITION_BASE: Retail 0x002e5750-0x002e5754 loads the camera saved-state pointer at owner +0x70 and forms attach_state = saved_state +0x40. The byte at attach_state +0xC4 (saved_state +0x104) is passed as a3 to compute_follow_camera_target_position at 0x002e578c-0x002e5794, then reloaded into v1 at 0x002e579c for these comparisons. The authoritative helper source switches that same argument using CameraAttachMode members, proving this selector's shared domain independently of numeric coincidence. 0x002e57c0-0x002e57c4 compares v1 with 1; the target helper names this mode CAM_ATTACH_HERO_POSITION_BASE and calls follow_camera_hero_target before adding input_offset. Each selected comparison reaches 0x002e57cc, blending position stiffness and damping by the timer-derived weight before interpolation at 0x002e5808. --- src/overlays/shared/camera/follow_camera_springs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/camera/follow_camera_springs.c b/src/overlays/shared/camera/follow_camera_springs.c index 11111a7cbf..2ebf8f36a1 100644 --- a/src/overlays/shared/camera/follow_camera_springs.c +++ b/src/overlays/shared/camera/follow_camera_springs.c @@ -1299,8 +1299,8 @@ void follow_camera_transition(O002e5730 *camera, void *input_offset) { compute_follow_camera_target_position( camera, input_offset, &target_position, attach_state->xc4); attach_mode = attach_state->xc4; - if (attach_mode == 3 || attach_mode == 5 || attach_mode == 6 || attach_mode == 7 || - attach_mode == 1) { + if (attach_mode == CAM_ATTACH_BLEND_TO_PROJECT_HERO_FOCUS_VELOCITY || attach_mode == CAM_ATTACH_BLEND_FOCUS_VELOCITY_WITH_HOLD_TRANSITION || attach_mode == CAM_ATTACH_BLEND_OUT_FOCUS_VELOCITY || attach_mode == CAM_ATTACH_BLEND_BACK_FOCUS_VELOCITY || + attach_mode == CAM_ATTACH_HERO_POSITION_BASE) { x = follow_camera_position_transition_end_stiffness_gp + (follow_camera_position_default_stiffness_gp - follow_camera_position_transition_end_stiffness_gp) * From c6df8a425071e853292dd07c8e5c956763caf85c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:23:36 +0000 Subject: [PATCH 0501/1502] decomp: clarify names in update_breakable_prop domain_0_value_1 -> MOBY_STATE_CHECK_HIT_FOR_REMOVAL: The source assigns 1 to moby->state in MOBY_STATE_INITIALIZE, and the same selector already has case MOBY_STATE_CHECK_HIT_FOR_REMOVAL = 1. Retail lbu at 0x002d6760 reads +0x20(s0); 0x002d6764 loads 1, 0x002d6768 dispatches that value to the hit check, while the zero-state path stores that same 1 to +0x20 at 0x002d67a0. Original Ghidra confirms the 0->1 transition. This is the local moby state domain, unrelated to the supplied hero enums. domain_1_value_2 -> MOBY_STATE_REMOVE_WITH_EFFECTS: The source assigns 2 to moby->state after the non-null hit and positive +0x2C predicate; its same-selector case MOBY_STATE_REMOVE_WITH_EFFECTS already equals 2. Retail 0x002d67cc loads 2 and 0x002d67d4 stores it to +0x20(s0), the byte read at 0x002d6760. The value-2 dispatch at 0x002d678c enters voice/effect/fragment calls at 0x002d67d8..0x002d681c and removal at 0x002d6820. Original Ghidra confirms this state transition and removal branch. --- src/overlays/l16/mobys/breakable_prop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l16/mobys/breakable_prop.c b/src/overlays/l16/mobys/breakable_prop.c index 0825752012..57905ff09f 100644 --- a/src/overlays/l16/mobys/breakable_prop.c +++ b/src/overlays/l16/mobys/breakable_prop.c @@ -36,13 +36,13 @@ void breakable_prop_update(struct Moby *moby) { char *hit_record = find_moby_hit(moby, 0x10000, 0); switch (moby->state) { case MOBY_STATE_INITIALIZE: - moby->state = 1; + moby->state = MOBY_STATE_CHECK_HIT_FOR_REMOVAL; break; case MOBY_STATE_CHECK_HIT_FOR_REMOVAL: if (hit_record != 0 && 0.0f < *(float *)(hit_record + 0x2C)) flag = 1; if (flag) - moby->state = 2; + moby->state = MOBY_STATE_REMOVE_WITH_EFFECTS; break; case MOBY_STATE_REMOVE_WITH_EFFECTS: allocate_voice_for_target_entry(0, 0, moby); From 1e2319b5230699884ffa8c4139edbdaf36d8d0dd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:25:26 +0000 Subject: [PATCH 0502/1502] decomp: clarify names in garage_door_update domain_0_value_1 -> GARAGE_DOOR_RISING: The authoritative C switch selects door_moby->state and already labels value 1 GARAGE_DOOR_RISING. Retail 0x002dca38 reads state +0x20, 0x002dca3c dispatches value 1 to 0x002dcad4, and 0x002dcae8-ec increases the same object's Z by frame_time. The collection-flag success path stores 1 to that identical +0x20 state byte at 0x002dcad0, proving this assignment enters the existing rising state. domain_1_value_2 -> GARAGE_DOOR_RAISED: The authoritative C already labels value 2 of switch(door_moby->state) GARAGE_DOOR_RAISED. Retail 0x002dcaf0-f8 compares saved pvars Z+4 against the increased door Z; when reached, 0x002dcb04/0c stores 2 to the same +0x20 state byte read at 0x002dca38. Dispatch at 0x002dca60 sends state 2 to 0x002dcb10-20, which holds Z at saved Z+4. Thus this assignment enters the existing raised state. --- src/overlays/shared/props/garage_door.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/props/garage_door.c b/src/overlays/shared/props/garage_door.c index 2bdb1afb03..21a5aec258 100644 --- a/src/overlays/shared/props/garage_door.c +++ b/src/overlays/shared/props/garage_door.c @@ -40,12 +40,12 @@ void garage_door_update(struct Moby *door_moby) { 1)) return; } - door_moby->state = 1; + door_moby->state = GARAGE_DOOR_RISING; return; case GARAGE_DOOR_RISING: door_moby->pos.z += frame_time; if (target->f[2] + 4.0f <= door_moby->pos.z) - door_moby->state = 2; + door_moby->state = GARAGE_DOOR_RAISED; return; case GARAGE_DOOR_RAISED: door_moby->pos.z = target->f[2] + 4.0f; From 00d9174c9c6bc47c26627767a860fc2de1d919db Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:25:26 +0000 Subject: [PATCH 0503/1502] decomp: clarify names in volume_camera_swing_check domain_1_value_1 -> SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END: Retail 0x002ed248-0x002ed254 obtains descriptor params from the incoming camera record; 0x002ed294-0x002ed2b4 compares params+0x2c with 1 and checks timer+0x2e. Thus this is a swing-camera type, not a hero state. Authoritative volume_camera_swing source groups type 1 with 7 and 10 for follow_camera_start_slide; helper retail 0x002ed1b0-0x002ed1f8 confirms the type tests and calls 0x002e8648 and up-spring setter. Source and helper Ghidra show types 1/7/9 skip set_follow_camera_angle_blend_from_direction when at_end is true, whereas type 10 continues that call. RELEASE_ANGLE_AT_END means release the per-frame angle-blend application at the endpoint. domain_2_value_10 -> SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END: Retail 0x002ed2a4-0x002ed2b4 tests 10 against the same descriptor-owned params+0x2c selector and gates initial activation on timer. Direct helper evidence request d92c2acaa7034b6aa56e49c6bb7c421c confirms type 10 shares the slide path: 0x002ed1bc-0x002ed1d4 compares 10 then calls 0x002e8648, named follow_camera_start_slide in the authoritative source. The source condition (type != 1 && type != 7 && type != 9) || at_end == 0 and matching helper Ghidra prove type 10 keeps applying set_follow_camera_angle_blend_from_direction at the endpoint; this distinguishes it from type 1 without guessing the meaning of its separate mode 0x14d assignment. --- src/overlays/shared/camera/swing_volume_camera.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/camera/swing_volume_camera.c b/src/overlays/shared/camera/swing_volume_camera.c index 3a3f06f6ad..479f603bbf 100644 --- a/src/overlays/shared/camera/swing_volume_camera.c +++ b/src/overlays/shared/camera/swing_volume_camera.c @@ -350,12 +350,16 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { s32 volume_camera_swing_check(struct UpdateCam *cam) __asm__("FUN_L00_002ed230"); s32 volume_camera_swing_check(struct UpdateCam *swing_camera_record) { + enum { + SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END = 1, + SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END = 10 + }; SwingCameraParams *params = camera_descriptors[swing_camera_record->descriptor_index].params; if (params->l_buttons_end == 1 && params->done != 0) return 0; if (params->type == 11 && D_001413F4 != 2) return 0; - if ((params->type == 1 || params->type == 10) && params->timer == 0) { + if ((params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END) && params->timer == 0) { struct Hero *hero_data = &hero; if (hero_data->frames_off_ground.s != 0) { if (current_level_index != 14) From a1bdc034d5ae17425fb3e7a1e7a63d6682d93a7a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:25:26 +0000 Subject: [PATCH 0504/1502] decomp: clarify names in _pictureData0 domain_2_value_2 -> DECODE_STATUS_ABORT_PICTURE: Retail 0x00127790 calls _waitBdecOut; 0x00127798-0x001277a0 writes status 2 when it returns zero. Status 2 bypasses final _doMC at 0x001277cc, reaches _Error with '= Skip to the next picture =' at 0x001277e8-0x001277f8, and returns failure. Supplied _slice0 also returns 2 on BDEC, macroblock skip, motion compensation or excess-macroblock failures. This proves aborting the current picture, without asserting a single underlying error cause. domain_3_value_0 -> DECODE_STATUS_SUCCESS: Retail _slice0 return is held in s0 at 0x00127774. At 0x001277cc zero permits final _doMC, and 0x001277ac/0x001277fc converts zero into the returned success boolean. Supplied _slice0 returns zero after mbx reaches nmb; _decPicture marks the reference decoded only on this boolean. Thus decode_status zero is DECODE_STATUS_SUCCESS, not boolean FALSE. domain_5_value_2 -> DECODE_STATUS_ABORT_PICTURE: Retail 0x00127790 calls _waitBdecOut; 0x00127798-0x001277a0 writes status 2 when it returns zero. Status 2 bypasses final _doMC at 0x001277cc, reaches _Error with '= Skip to the next picture =' at 0x001277e8-0x001277f8, and returns failure. Supplied _slice0 also returns 2 on BDEC, macroblock skip, motion compensation or excess-macroblock failures. This proves aborting the current picture, without asserting a single underlying error cause. domain_6_value_0 -> DECODE_STATUS_SUCCESS: Retail _slice0 return is held in s0 at 0x00127774. At 0x001277cc zero permits final _doMC, and 0x001277ac/0x001277fc converts zero into the returned success boolean. Supplied _slice0 returns zero after mbx reaches nmb; _decPicture marks the reference decoded only on this boolean. Thus decode_status zero is DECODE_STATUS_SUCCESS, not boolean FALSE. --- src/sdk/mpeg/picture/_pictureData0.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/sdk/mpeg/picture/_pictureData0.c b/src/sdk/mpeg/picture/_pictureData0.c index ff7601a18a..1108e43099 100644 --- a/src/sdk/mpeg/picture/_pictureData0.c +++ b/src/sdk/mpeg/picture/_pictureData0.c @@ -17,6 +17,10 @@ typedef struct { extern char skip_to_next_picture_error_message[] __asm__("D_001537E0"); s32 _pictureData0(MpegDec *decoder) { + enum { + DECODE_STATUS_SUCCESS = 0, + DECODE_STATUS_ABORT_PICTURE = 2 + }; s32 decode_status; s32 mbs; @@ -31,15 +35,15 @@ s32 _pictureData0(MpegDec *decoder) { } while (decode_status == 1 || decode_status == 3); _waitIpuIdle(decoder); if (_waitBdecOut(decoder) == 0) { - decode_status = 2; + decode_status = DECODE_STATUS_ABORT_PICTURE; } while ((*(volatile u32 *)0x1000D400 >> 8) & 1) { } - if (decode_status == 0) { + if (decode_status == DECODE_STATUS_SUCCESS) { _doMC(decoder, decoder->unk810 == 0); } - if (decode_status == 1 || decode_status == 2) { + if (decode_status == 1 || decode_status == DECODE_STATUS_ABORT_PICTURE) { _Error(decoder, skip_to_next_picture_error_message); } - return decode_status == 0; + return decode_status == DECODE_STATUS_SUCCESS; } From b0e82c4c491b1548d01a2989dc4a3a7e10fb5ae6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:25:26 +0000 Subject: [PATCH 0505/1502] decomp: clarify names in update_homing_mine_spawner_target domain_0_value_0 -> HOMING_MINE_SPAWNER_CLEAR_LINKED_MOBYS: Retail 0x00307ac4 preserves the spawner argument in s1; 0x00307ad4 loads its Moby state byte at +0x20, and 0x00307ad8 skips target updates when it is zero. The authoritative source caller homing_mine_spawner_update passes that same spawner directly to this function, then switches on spawner->state. Its established zero member HOMING_MINE_SPAWNER_CLEAR_LINKED_MOBYS removes valid linked mobys from the twelve slots and advances spawner->state to 1. Thus this comparison excludes that exact linked-moby clearing state; it is not a HeroStateId, control mode or target-selection status. --- src/overlays/l12/mobys/homing_mine_spawner.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l12/mobys/homing_mine_spawner.c b/src/overlays/l12/mobys/homing_mine_spawner.c index 9e4aae5bd7..e889e090c5 100644 --- a/src/overlays/l12/mobys/homing_mine_spawner.c +++ b/src/overlays/l12/mobys/homing_mine_spawner.c @@ -173,9 +173,9 @@ extern char D_0013E533[]; extern int select_moby_combat_target(char *, char *, float) __asm__("FUN_L00_0025fcb8"); void update_homing_mine_spawner_target(struct Moby *spawner) { - HomingMineSpawnerVars *spawner_data = (HomingMineSpawnerVars *)spawner->pvars; + enum { HOMING_MINE_SPAWNER_CLEAR_LINKED_MOBYS = 0 } ;HomingMineSpawnerVars *spawner_data = (HomingMineSpawnerVars *)spawner->pvars; char *pad; - if (spawner->state != 0) { + if (spawner->state != HOMING_MINE_SPAWNER_CLEAR_LINKED_MOBYS) { if (spawner_data->unk38 != 0) { spawner_data->timer_FE = scale_game_frames(0xB4); } From 51d9d747bbb6822614dab44e72cbcd1c9f142f3c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:25:26 +0000 Subject: [PATCH 0506/1502] decomp: clarify names in update_minibomber_oscillation domain_0_value_0 -> MINIBOMBER_STATE_INITIALIZE: Retail 0x002b5440 loads the input moby's current state byte at +0x20; 0x002b5448 returns for zero. Authoritative C passes this same minibomber from minibomber_update into this helper and switches on moby->state, where MINIBOMBER_STATE_INITIALIZE=0 validates paths, initializes spring fields and advances to wait state. Thus this comparison uses that exact current-state domain. domain_1_value_9 -> MINIBOMBER_STATE_DESTROY: Retail 0x002b5440 loads moby+0x20 and 0x002b5450/0x002b5454 compares it with 9 to skip oscillation. The authoritative minibomber_update calls this helper on the same moby and names state 9 MINIBOMBER_STATE_DESTROY; its branch emits destruction effects, releases its voice and marks the moby for removal. Hit reactions also assign 9 on lethal damage, proving the same current-state role. domain_2_value_1 -> MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH: Retail 0x002b5458 loads 1 and 0x002b545c returns when the state byte loaded from moby+0x20 equals it. In the authoritative same-moby caller minibomber_update, MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH=1 is entered after initialization or completed retracing; its branch waits for d->fB4 != 2 before assigning follow-path state 2 and initializing path following. This is current state, not the separate fB4 control value. domain_3_value_7 -> MINIBOMBER_STATE_TRAVERSE_PATH: Retail 0x002b5470/0x002b5474 compares the moby+0x20 current state with 7; the matching branch scales spring_target by 1.5 at 0x002b5488 and skips vertical oscillation. Authoritative minibomber_update calls this helper with the same moby and defines MINIBOMBER_STATE_TRAVERSE_PATH=7; that branch advances along l14_paths[d->fDC], reverses direction via f10C and returns to hold state on completion. This proves canonical current-state domain membership. --- src/overlays/l14/mobys/minibomber.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/minibomber.c b/src/overlays/l14/mobys/minibomber.c index 553dcf0616..6045a26027 100644 --- a/src/overlays/l14/mobys/minibomber.c +++ b/src/overlays/l14/mobys/minibomber.c @@ -728,14 +728,20 @@ extern short minibomber_rotation_oscillation_second_phase_increment_gp __asm__(" void update_minibomber_oscillation(struct Moby *moby) __asm__("FUN_L14_002b5428"); void update_minibomber_oscillation(struct Moby *moby) { + enum { + MINIBOMBER_STATE_INITIALIZE = 0, + MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH = 1, + MINIBOMBER_STATE_TRAVERSE_PATH = 7, + MINIBOMBER_STATE_DESTROY = 9 + }; int raw = moby->state; unsigned char state = raw; char *minibomber_instance_vars = (char *)moby->pvars; float spring_target; - if (state == 0 || state == 9 || state == 1) + if (state == MINIBOMBER_STATE_INITIALIZE || state == MINIBOMBER_STATE_DESTROY || state == MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH) return; spring_target = *(float *)&D_L14_00161540_gp; - if ((raw >= 2 && raw <= 3) || state == 7) { + if ((raw >= 2 && raw <= 3) || state == MINIBOMBER_STATE_TRAVERSE_PATH) { spring_target = spring_target * 1.5f; } else { FUN_L00_0025b8c0_c((float *)(minibomber_instance_vars + 0x168), From a631450e0ac802da8bdf0a415273b2c354da4ad7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:27:10 +0000 Subject: [PATCH 0507/1502] decomp: clarify names in link_and_update_all_mobys domain_0_value_255 -> MOBY_TABLE_END_STATE: The selector is the struct Moby state byte at +0x20. Retail 0x00264764 loads moby_table, 0x00264768 reads that byte, and 0x00264750/0x0026476c compare it with 0xFF and exit the scan. The loop advances by the 0x100-byte Moby stride at 0x002647a8, reloads state at 0x002647ac, and continues only while it differs from 0xFF at 0x002647b0. This proves a table-end state sentinel, not an inferred gameplay lifecycle state. --- src/overlays/shared/mobys/link_and_update_all_mobys.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/mobys/link_and_update_all_mobys.c b/src/overlays/shared/mobys/link_and_update_all_mobys.c index e86e1d3330..11cdadab11 100644 --- a/src/overlays/shared/mobys/link_and_update_all_mobys.c +++ b/src/overlays/shared/mobys/link_and_update_all_mobys.c @@ -14,6 +14,9 @@ extern void FUN_L00_00250480(struct Moby *moby); void link_and_update_all_mobys(void) __asm__("FUN_L00_00264740"); void link_and_update_all_mobys(void) { + enum { + MOBY_TABLE_END_STATE = 0xFF + }; struct Moby *moby; struct Moby *last; struct Moby *current; @@ -22,7 +25,7 @@ void link_and_update_all_mobys(void) { suck_moby_list = 0; moby = (struct Moby *)moby_table; last = 0; - while (moby->state != 0xFF) { + while (moby->state != MOBY_TABLE_END_STATE) { if (!(moby->state & 0x80) && !(moby->flags & 2)) { if (last != 0) { last->next = moby; From 11199bc2015827cb9fb57ecd1d9335d0171956d0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:27:10 +0000 Subject: [PATCH 0508/1502] decomp: clarify names in enter_hero_vehicle_mode_and_set_moby domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0023135C preserves a0 in s1; 0x002313B8 stores s1 into hero+0x20A4, identifying the argument as the hero vehicle_mode selector, distinct from initial_state in s3 passed to hero_set_state at 0x00231424-0x0023142C. Retail 0x00231408-0x0023140C compares that same s1 against 1, guarding the +0x22A8/+0x22AC/+0x22B0 transfers. Authoritative source uses this byte for vehicle-mode dispatch and the inverse clears it on mode exit; supplied callers pass vehicle mode separately from initial state and active moby. Thus the selector belongs to HeroVehicleMode in include/rnc/hero/hero_state.h, whose existing canonical member HERO_VEHICLE_MODE_CLANK equals 1; reuse it without inferring field meanings or mixing HeroStateId/GravityMode domains. --- src/overlays/shared/hero/hero_frame_update.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index 1843f9c494..8e0ce87d7a 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -755,7 +755,7 @@ void enter_hero_vehicle_mode_and_set_moby(int vehicle_mode, int initial_state, i FUN_L00_00257024(((void *)hero_state_base->moby)); apply_hero_and_item_scale_sequence(); hero_state_base->unk22CC = initial_state; - if (vehicle_mode == 1) { + if (vehicle_mode == HERO_VEHICLE_MODE_CLANK) { *(unsigned short *)&hero_state_base->health.unk22B0 = *(unsigned short *)&hero_state_base->health; hero_state_base->health.hp = hero_state_base->health.vehicle_mode_hp; From b5392942c2ea37239f87204ba883146fd0fcf1f5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:27:10 +0000 Subject: [PATCH 0509/1502] decomp: clarify names in metropolis_train_carriage_update domain_0_value_0 -> METROPOLIS_TRAIN_CARRIAGE_STATE_INITIALIZE: The authoritative metropolis_train_carriage_update source compares moby->state with 0. Original retail Ghidra reads the byte at moby+0x20; 0x00295430 loads it and 0x00295440 branches past initialization when nonzero. The zero branch clears pvars+0x60/+0x64 and initializes +0x68/+0x7E at 0x00295454-0x00295464, computes the joint-zero distance into +0xC4 at 0x00295468-0x0029547C, seeds saved position/rotation at +0xA0/+0xB0 at 0x00295480-0x0029548C, and initializes +0x5C and update/draw distances at 0x00295490-0x002954A0. This establishes the carriage state as initialization; it is not a helper control value or boolean. No shared enum domain is supplied, so the proposed constant is carriage-specific. --- src/overlays/l03/mobys/metropolis_train_carriage.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l03/mobys/metropolis_train_carriage.c b/src/overlays/l03/mobys/metropolis_train_carriage.c index 8aab7dd5fe..7d8b532611 100644 --- a/src/overlays/l03/mobys/metropolis_train_carriage.c +++ b/src/overlays/l03/mobys/metropolis_train_carriage.c @@ -33,7 +33,7 @@ typedef struct MetropolisTrainCarriageVars { /* Moby class 1210 */ void metropolis_train_carriage_update(struct Moby *moby) { - float position_delta[4]; + enum { METROPOLIS_TRAIN_CARRIAGE_STATE_INITIALIZE = 0 } ;float position_delta[4]; float joint_zero_world_position[4]; MetropolisTrainCarriageVars *carriage_pvars; char *current_position; @@ -46,7 +46,7 @@ void metropolis_train_carriage_update(struct Moby *moby) { previous_position = &carriage_pvars->unkA0; previous_rotation = &carriage_pvars->unkB0; current_rotation = &moby->rot; - if (moby->state == 0) { + if (moby->state == METROPOLIS_TRAIN_CARRIAGE_STATE_INITIALIZE) { carriage_pvars->unk60 = 0; carriage_pvars->unk64 = 0; carriage_pvars->unk68 = 4; From 137388d937826b99b85c7c2f54f38455a2f967dd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:28:45 +0000 Subject: [PATCH 0510/1502] decomp: clarify names in _nextHeader domain_0_value_5 -> MPEG_CALLBACK_TIMESTAMP: In _nextHeader, retail 0x00128b5c loads 5; 0x00128c10 stores it as the event type at sp+0. After _pictureHeader, 0x00128c14 and 0x00128c1c initialize the s64 DTS/PTS payload at sp+0x10/+8 to -1; 0x00128c18 dispatches this event using decoder callback context +0x858. At 0x00128c20-0x00128c2c the callback-updated values are copied to decoder DTS/PTS +0x830/+0x828. The authoritative MpegCbTimeStamp type identifies those payload fields, and supplied _dispatchMpegCallback indexes callbacks->entries[event->type], proving 5 is a timestamp callback event selector, distinct from the MPEG start-code switch domain. --- src/sdk/mpeg/headers/next_header.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/mpeg/headers/next_header.c b/src/sdk/mpeg/headers/next_header.c index 0c0dfc5c90..93da1c5857 100644 --- a/src/sdk/mpeg/headers/next_header.c +++ b/src/sdk/mpeg/headers/next_header.c @@ -30,6 +30,9 @@ s32 _nextHeader(MpegDec *decoder) { MPEG_SEQUENCE_END_CODE = 0x1B7, MPEG_GROUP_START_CODE = 0x1B8 }; + enum { + MPEG_CALLBACK_TIMESTAMP = 5 + }; MpegCbTimeStamp cb; u32 code; @@ -45,7 +48,7 @@ s32 _nextHeader(MpegDec *decoder) { break; case MPEG_PICTURE_START_CODE: _pictureHeader(decoder); - cb.type = 5; + cb.type = MPEG_CALLBACK_TIMESTAMP; cb.pts = -1; cb.dts = -1; _dispatchMpegCallback(decoder->cbData, &cb); From 18ff61127d44404f88977379b230298818c163da Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:28:45 +0000 Subject: [PATCH 0511/1502] decomp: clarify names in load_chunks_with_optional_fade domain_0_value_0 -> PAL_MODE_DISABLED: Retail 0x00245614-0x00245628 loads pal_mode at 0x0015ed80 and branches to 0x00245668 when nonzero. The zero path 0x00245630-0x0024565c reads sector/count from disc_table.unk12E8; the nonzero path uses unk1338. Authoritative source binds this exact comparison to pal_mode and the adjacent load_scene_chunks_with_fade already defines PAL_MODE_DISABLED = 0 for this same selector and its paired disc tables. This proves disabled PAL mode rather than a CD-read or moby state. --- src/overlays/shared/streaming/load_scene_chunks_with_fade.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/streaming/load_scene_chunks_with_fade.c b/src/overlays/shared/streaming/load_scene_chunks_with_fade.c index a956e6ec32..55bc0ce153 100644 --- a/src/overlays/shared/streaming/load_scene_chunks_with_fade.c +++ b/src/overlays/shared/streaming/load_scene_chunks_with_fade.c @@ -56,9 +56,12 @@ void load_chunks_with_optional_fade(s32 i, s32 fade_frame_count) __asm__("FUN_L0 void load_chunks_with_optional_fade(s32 i, s32 p) __asm__("FUN_L00_00245610"); void load_chunks_with_optional_fade(s32 i, s32 fade_frame_count) { + enum { + PAL_MODE_DISABLED = 0 + }; s32 pointer_index; s32 *offset_entry; - if (pal_mode == 0) { + if (pal_mode == PAL_MODE_DISABLED) { start_audio_stream_read( H245610.buf, disc_table.unk12E8[i].sector, disc_table.unk12E8[i].size); } else { From 0326bc86479ba65585a189fa075cd52140809f02 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:30:48 +0000 Subject: [PATCH 0512/1502] decomp: clarify names in update_hero_aligned_camera_position domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Authoritative source initializes hero_data=&hero and vehicle_mode=hero_data->vehicle_mode. Retail 0x002e9cd4/0x002e9cdc establishes Hero base 0x0013F350; 0x002e9cf4 loads its vehicle_mode byte at +0x20A4, and 0x002e9cf8-0x002e9cfc compares that same byte to 2. The equal branch at 0x002e9d08-0x002e9d18 scales the hero up axis by 9.5 for camera height. This proves the selector is the supplied HeroVehicleMode domain, whose canonical value 2 in include/rnc/hero/hero_state.h is HERO_VEHICLE_MODE_GIANT_CLANK. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Source vehicle_mode is read directly from hero_data->vehicle_mode with hero_data=&hero. Retail 0x002e9cf4 loads Hero+0x20A4 into v1; the delay slot at 0x002e9d00 sets v0=1 and 0x002e9d24 compares the unchanged vehicle-mode byte against it. The equal branch scales the normalized hero up axis by 1.2 or 0.9 at 0x002e9d3c-0x002e9d68. Thus this comparison belongs to the supplied HeroVehicleMode domain, whose canonical value 1 in include/rnc/hero/hero_state.h is HERO_VEHICLE_MODE_CLANK. --- src/overlays/shared/camera/hero_aligned_camera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/camera/hero_aligned_camera.c b/src/overlays/shared/camera/hero_aligned_camera.c index 4b96c7aa7f..95e9499ebe 100644 --- a/src/overlays/shared/camera/hero_aligned_camera.c +++ b/src/overlays/shared/camera/hero_aligned_camera.c @@ -244,9 +244,9 @@ void update_hero_aligned_camera_position(char *camera_object) { int vehicle_mode; FUN_001f9bf8_002e9cc0(normalized_hero_up_axis, ((char *)hero_data->moby) + 0xE0, 1.0f); vehicle_mode = hero_data->vehicle_mode; - if (vehicle_mode == 2) { + if (vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { FUN_001f9a68_002e9cc0(camera_height_offset, normalized_hero_up_axis, 9.5f); - } else if (vehicle_mode == 1) { + } else if (vehicle_mode == HERO_VEHICLE_MODE_CLANK) { if (D_0015EDB3_002e9cc0) { FUN_001f9a68_002e9cc0(camera_height_offset, normalized_hero_up_axis, 1.2f); } else { From 4a9b70d6c3adee2435bca535ff0f5881317598ec Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:30:48 +0000 Subject: [PATCH 0513/1502] decomp: clarify names in pool_bubbles domain_0_value_72 -> POOL_BUBBLE_PARTICLE_KIND: In established pool_bubbles, retail 0x00287cf8 loads 0x48 into v1 and 0x00287d04 stores it at s1+3, exactly Particle.kind in the authoritative source. The allocator result s1 is initialized with bubble position, pool_bubbles_texture_table, life and motion, and returned at 0x00287d68. The checked caller spawns this object at bubble_position in the pool. Adjacent pool_bubble uses the identical Particle.kind field and already names 0x48 POOL_BUBBLE_PARTICLE_KIND; this is the same particle-kind domain, not create_part's distinct 0x39 allocation selector. --- src/overlays/l01/mobys/pool_bubbles.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/pool_bubbles.c b/src/overlays/l01/mobys/pool_bubbles.c index b70ced8882..aa1d433e5b 100644 --- a/src/overlays/l01/mobys/pool_bubbles.c +++ b/src/overlays/l01/mobys/pool_bubbles.c @@ -63,6 +63,9 @@ extern u8 *pool_bubbles_texture_table[] __asm__("D_L01_001B25E4"); Particle *pool_bubbles(u128 *pos, u128 *dir, f32 scale, f32 speed) __asm__("FUN_L01_00287c80"); Particle *pool_bubbles(u128 *pos, u128 *motion_position_source, f32 scale, f32 speed) { + enum { + POOL_BUBBLE_PARTICLE_KIND = 0x48 + }; Particle *particle; PartMotion *m; f32 random_spin; @@ -73,7 +76,7 @@ Particle *pool_bubbles(u128 *pos, u128 *motion_position_source, f32 scale, f32 s m = &particle->m; particle->color = (random_integer_below(0x10) << 25) | 0x808080; particle->alpha = truncate_float_to_s32(12.0f) + 0x20; - particle->kind = 0x48; + particle->kind = POOL_BUBBLE_PARTICLE_KIND; particle->active = 1; particle->tex = *pool_bubbles_texture_table[0]; particle->life = 0x80; From 0d60e9da59bfbfb102905f6845f509ae657e061d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:30:48 +0000 Subject: [PATCH 0514/1502] decomp: clarify names in tall_shroom_update domain_0_value_1 -> TALL_SHROOM_STATE_WAIT_FOR_HIT: The source assignment shroom_moby->state = 1 in TALL_SHROOM_STATE_INITIALIZE writes the exact byte read by switch(shroom_moby->state). Retail lbu at 0x0030d110 reads +0x20(s0), li a0,1 at 0x0030d114 supplies the initialization store sb a0,+0x20(s0) at 0x0030d150, and the equality branch at 0x0030d118 dispatches that value to the nonnull hit and positive +0x2c float test at 0x0030d154-0x0030d178. This is the existing local enum member TALL_SHROOM_STATE_WAIT_FOR_HIT, not a separate control domain. domain_1_value_2 -> TALL_SHROOM_STATE_REMOVE_WITH_EFFECTS: The source assigns shroom_moby->state = 2 only after a nonnull hit with hit->f2c > 0.0f. Retail li v0,2 at 0x0030d17c and sb v0,+0x20(s0) at 0x0030d184 write the same state byte read at 0x0030d110. The state-2 branch at 0x0030d13c leads to voice allocation, bolt and fragment spawns, replacement placement spawn and removal at 0x0030d188-0x0030d1e4. Thus this assignment reuses the existing local enum member TALL_SHROOM_STATE_REMOVE_WITH_EFFECTS in the same selector domain. --- src/overlays/l01/mobys/tall_shroom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l01/mobys/tall_shroom.c b/src/overlays/l01/mobys/tall_shroom.c index ffd5a8ddea..21352ec1a2 100644 --- a/src/overlays/l01/mobys/tall_shroom.c +++ b/src/overlays/l01/mobys/tall_shroom.c @@ -38,14 +38,14 @@ void tall_shroom_update(TriggerMoby *shroom_moby) { hit = find_moby_hit(shroom_moby, 0x10000, 0); switch (shroom_moby->state) { case TALL_SHROOM_STATE_INITIALIZE: - shroom_moby->state = 1; + shroom_moby->state = TALL_SHROOM_STATE_WAIT_FOR_HIT; break; case TALL_SHROOM_STATE_WAIT_FOR_HIT: if (hit != 0 && hit->f2c > 0.0f) { flag = 1; } if (flag) { - shroom_moby->state = 2; + shroom_moby->state = TALL_SHROOM_STATE_REMOVE_WITH_EFFECTS; } break; case TALL_SHROOM_STATE_REMOVE_WITH_EFFECTS: From 98ccf6b53eafc92a4f1d515b7906aa9b30379e37 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:32:35 +0000 Subject: [PATCH 0515/1502] decomp: clarify names in box_update domain_0_value_1 -> BOX_UPDATE_TRANSFORM: The authoritative box.c snapshot (SHA-256 6d43262fd78924cd97a0e23c6b8107cf0e5586dde7141b2c91c88f37ca2e8743) switches on MOBY(moby)->state and already defines BOX_UPDATE_TRANSFORM = 1 for its transform-update branch. Retail 0x0030bfb8 loads that same byte at moby+0x20; 0x0030bfc4-0x0030bfc8 compares it with 1 and branches to 0x0030c018, where old position/rotation are saved and transform_attachment_pose is called at 0x0030c058. In initialization, 0x0030bfd8 sets s0=1, the pose conversion occurs at 0x0030c008, and 0x0030c014 stores s0 to that exact selector byte at 0x20(s1). The original Ghidra decompilation likewise assigns 1 to iVar3+0x20 after pose conversion and tests that same byte for 1 before the transform-update branch. Thus this assignment belongs to the existing local state domain and reuses BOX_UPDATE_TRANSFORM, rather than the unrelated equal-valued TRUE. --- src/overlays/l05/mobys/box.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l05/mobys/box.c b/src/overlays/l05/mobys/box.c index f6a23326df..8cd4e49ce1 100644 --- a/src/overlays/l05/mobys/box.c +++ b/src/overlays/l05/mobys/box.c @@ -32,7 +32,7 @@ void box_update(char *moby) { moby + 0x40, moby_data + 0x60, moby_data + 0x70); - MOBY(moby)->state = 1; + MOBY(moby)->state = BOX_UPDATE_TRANSFORM; } break; case BOX_UPDATE_TRANSFORM: From ff024d86fccce316e6759fa569890d471a4b0b7e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:32:35 +0000 Subject: [PATCH 0516/1502] decomp: clarify names in restore_hero_from_vehicle_mode domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x00227d10 establishes &hero (0x0013F350); 0x00227d14 loads its +0x20A4 vehicle_mode byte and 0x00227d18 compares against 1 loaded at 0x00227d04. The guarded branch saves vehicle HP, restores saved HP, and removes the two attachments at +0x1620/+0x1624. Original Ghidra cRam001413f4 == 1 matches this data flow. The authoritative source already switches hero_context->vehicle_mode using HERO_VEHICLE_MODE_CLANK in get_hero_help_value; the supplied HeroVehicleMode domain defines that canonical member as 1. This is the same vehicle selector, not HeroStateId or a control mode. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00227d60 establishes &hero and 0x00227d6c stores zero to +0x20A4, the same vehicle_mode byte compared at 0x00227d14. Original Ghidra assigns cRam001413f4 = 0. The following restoration loads saved hero moby at +0xA88 into hero.moby (+0x2080), copies hero.motion.pos to it at 0x00227d9c-0x00227db0, and normally requests idle. The authoritative source's enter_hero_idle_state_for_current_vehicle_mode selects the same byte (D_0013E533+0x2EC1 = 0x001413F4) with HERO_VEHICLE_MODE_ON_FOOT and requests HERO_STATE_IDLE. The supplied shared HeroVehicleMode enum canonically defines this member as 0. --- .../shared/hero/update_hero_vehicle_attachments_and_effects.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c b/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c index dac099492e..3f53b1b064 100644 --- a/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c +++ b/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c @@ -370,7 +370,7 @@ void restore_hero_from_vehicle_mode(void) __asm__("FUN_L06_00227cf8"); void restore_hero_from_vehicle_mode(void) { struct Hero *hero_context = &hero; unsigned char *flag_clear_target; - if (hero_context->vehicle_mode == 1) { + if (hero_context->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero_context->health.vehicle_mode_hp = hero_context->health.hp; hero_context->health.hp = hero_context->health.unk22B0; if (hero_context->unk1620) { @@ -385,7 +385,7 @@ void restore_hero_from_vehicle_mode(void) { { struct Hero *hero_restore_context = &hero; reset_hero_easing_records(); - hero_restore_context->vehicle_mode = 0; + hero_restore_context->vehicle_mode = HERO_VEHICLE_MODE_ON_FOOT; flag_clear_target = hero_restore_context->unkA84; if (flag_clear_target) { *(u16 *)(flag_clear_target + 0x34) &= ~6; From 332db2d0ca7bc976e0ba5ed7533fdc2e2480c385 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:32:36 +0000 Subject: [PATCH 0517/1502] decomp: clarify names in update_cutscene_camera_target domain_0_value_1 -> MOBY_ACTIVE: Retail 0030850c loads 1 and 00308510 stores it to moby state byte +0x20 during initialization; 003084ec reads that identical byte and 003084f4-003084f8 dispatch value 1 to the active update body at 0030851c. The authoritative C already names that same selector's case 1 MOBY_ACTIVE. Original retail decompilation likewise writes state=1 and tests the same field for 1, proving reuse of the existing local state-domain member. --- src/overlays/l08/mobys/cutscene_camera_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/cutscene_camera_target.c b/src/overlays/l08/mobys/cutscene_camera_target.c index b3a70d9f47..9f972d0581 100644 --- a/src/overlays/l08/mobys/cutscene_camera_target.c +++ b/src/overlays/l08/mobys/cutscene_camera_target.c @@ -36,7 +36,7 @@ void cutscene_camera_target_update(struct Moby *moby) { switch (moby->state) { case MOBY_INITIALIZE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = MOBY_ACTIVE; break; case MOBY_ACTIVE: if (level_game_mode == 2) { From 4a0de66a9044b265249cc979ee18000b515d1ab7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:32:36 +0000 Subject: [PATCH 0518/1502] decomp: clarify names in update_pokitaru_pickup domain_0_value_1 -> PICKUP_IDLE: Retail 0x002cb674 loads s1=1; 0x002cb6e4 stores s1 at moby+0x20 during initialization. The same state byte is read at 0x002cb680 and compared with s1 at 0x002cb684, branching directly to epilogue 0x002cb770. Original Ghidra likewise writes 1 to iVar2+0x20 and skips work when that byte equals 1. Authoritative C names this same selector's value 1 PICKUP_IDLE and its case only breaks, proving this assignment should reuse that existing local enum member rather than any unrelated hero-domain constant. --- src/overlays/l11/mobys/pokitaru_pickup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/pokitaru_pickup.c b/src/overlays/l11/mobys/pokitaru_pickup.c index 6eac5d3371..99bcf8ffd1 100644 --- a/src/overlays/l11/mobys/pokitaru_pickup.c +++ b/src/overlays/l11/mobys/pokitaru_pickup.c @@ -32,7 +32,7 @@ void pokitaru_pickup_update(struct Moby *moby) { } else { moby->pos.z += 0.75f; moby->flags |= 1; - moby->state = 1; + moby->state = PICKUP_IDLE; } break; case PICKUP_IDLE: From ae04606d9c04bca92e381d8a15127f51f7552308 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:32:36 +0000 Subject: [PATCH 0519/1502] decomp: clarify names in conveyor_belt_update domain_0_value_3 -> CONVEYOR_BELT_UPDATE_FRAME_OFFSET: Retail 002e73ec loads moby->state from 0x20(s2), and 002e73f4-002e73f8 compare that byte to 3 to enter 002e7430, the source's existing CONVEYOR_BELT_UPDATE_FRAME_OFFSET case. Initialization loads 3 into v1 at 002e7418 and stores it back to the identical 0x20(s2) byte at 002e742c. The target branch writes cos/sin(rot.z+pi/2)*frame_time*2.5 to pvars+0x40/+0x44 and zero to +0x48 before update_entity_matrix, proving that this assignment transitions into the already named frame-offset update state, rather than an unrelated numeric domain. --- src/overlays/l15/mobys/conveyor_belt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l15/mobys/conveyor_belt.c b/src/overlays/l15/mobys/conveyor_belt.c index edbb351571..be1af223b7 100644 --- a/src/overlays/l15/mobys/conveyor_belt.c +++ b/src/overlays/l15/mobys/conveyor_belt.c @@ -23,7 +23,7 @@ void conveyor_belt_update(struct Moby *moby) { char *frame_offset = conveyor_belt_private_data + 0x40; clear_u64_value(frame_offset); *(int *)(conveyor_belt_private_data + 0x9C) |= 4; - moby->state = 3; + moby->state = CONVEYOR_BELT_UPDATE_FRAME_OFFSET; break; } case CONVEYOR_BELT_UPDATE_FRAME_OFFSET: From 01a1b5bb9ff0360aa5f146e9c689b63abb4ff3a1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:32:36 +0000 Subject: [PATCH 0520/1502] decomp: clarify names in ease_minibomber_position_and_heading domain_0_value_4 -> MINIBOMBER_STATE_HOLD_AT_PATH_END: Retail 0x002b58a0 loads the unsigned moby state byte at +0x20; 0x002b58a4-0x002b58ac implements the lower bound 4 of states 4 through 6. The authoritative source Moby_2B5938 defines state at +0x20, and minibomber_update passes this same moby to ease_minibomber_position_and_heading before switching on moby->state. Its existing enum defines MINIBOMBER_STATE_HOLD_AT_PATH_END=4. On path completion it copies the endpoint into d->f180, sets target heading d->f17C and easing gains, and assigns state 4; the named case holds there pending traversal or bombing. Thus this comparison uses that exact minibomber current-state domain. domain_1_value_6 -> MINIBOMBER_STATE_RELEASE_BOMB: Retail 0x002b58a0 loads moby+0x20, and subtract-4/sltiu-3 at 0x002b58a4-0x002b58a8 accepts current states 4 through 6, proving the source upper bound 6 tests the moby state. The authoritative minibomber_update passes the same moby into this easing function and switches on its +0x20 state, with existing enum MINIBOMBER_STATE_RELEASE_BOMB=6. The aim case assigns state 6 and starts animation 1; the named release case checks animation position 3.0, computes the bomb trajectory, spawns the bomb, emits release effects and advances the bomb-point index. This establishes the canonical state name for this upper-bound token. --- src/overlays/l14/mobys/minibomber.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/minibomber.c b/src/overlays/l14/mobys/minibomber.c index 6045a26027..6b1d268b95 100644 --- a/src/overlays/l14/mobys/minibomber.c +++ b/src/overlays/l14/mobys/minibomber.c @@ -891,9 +891,9 @@ void ease_minibomber_position_and_heading(char *moby, float heading_velocity_damping, float heading_velocity_limit) { - int minibomber_private_vars_base; + enum { MINIBOMBER_STATE_HOLD_AT_PATH_END = 4 , MINIBOMBER_STATE_RELEASE_BOMB = 6 } ;int minibomber_private_vars_base; int moby_state = MOBY(moby)->state & 0xFF; - if ((moby_state >= 4 && moby_state <= 6) || moby_state == 8) { + if ((moby_state >= MINIBOMBER_STATE_HOLD_AT_PATH_END && moby_state <= MINIBOMBER_STATE_RELEASE_BOMB) || moby_state == 8) { minibomber_private_vars_base = *(int *)(moby + 0x78); vendor_spring((float *)&MOBY(moby)->pos, (float *)(minibomber_private_vars_base + 0xF0), From aed46aa29d441d805f7e81011d60d124024d79cf Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:32:36 +0000 Subject: [PATCH 0521/1502] decomp: clarify names in refresh_camera_control_flags domain_0_value_180 -> CAMERA_TRACKING_BASE_CONTROL_MASK: Retail 0x001ed9cc loads 0xB4 into a3 and 0x001ed9e8 stores it to cam_coll_mode before selector branches. At 0x001eda54 the retained tracking->control_selector loaded from offset 0xC0 is ORed with 0xB4 and published at 0x001eda5c. This proves 0xB4 is the common base control mask combined with the tracking selector, consistent with the supplied original Ghidra description. domain_5_value_180 -> CAMERA_TRACKING_BASE_CONTROL_MASK: Retail base-condition branch 0x001eda3c-0x001eda50 clears the tracking control selector at offset 0xC0 and publishes a3, previously loaded with 0xB4 at 0x001ed9cc, to cam_coll_mode. The alternate retained-selector branch ORs that selector with the same 0xB4 at 0x001eda54, proving this assignment uses the same base tracking control mask. --- src/camera/refresh_camera_control_flags.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/camera/refresh_camera_control_flags.c b/src/camera/refresh_camera_control_flags.c index 5952577363..6b6c05c812 100644 --- a/src/camera/refresh_camera_control_flags.c +++ b/src/camera/refresh_camera_control_flags.c @@ -20,6 +20,9 @@ extern struct CameraTrackingControl cam_coll_state __asm__("D_001870D0"); void refresh_camera_control_flags(void) __asm__("FUN_001ed940"); void refresh_camera_control_flags(void) { + enum { + CAMERA_TRACKING_BASE_CONTROL_MASK = 0xB4 + }; struct CameraTrackingControl *tracking; tracking = &cam_coll_state; @@ -32,7 +35,7 @@ void refresh_camera_control_flags(void) { } cam_coll_flag_prev = cam_coll_flag; cam_coll_flag |= 0x80; - cam_coll_mode = 0xB4; + cam_coll_mode = CAMERA_TRACKING_BASE_CONTROL_MASK; if (hero.selector_1 != 0) { tracking->control_selector = 0x100; cam_coll_mode = 0x1B4; @@ -47,7 +50,7 @@ void refresh_camera_control_flags(void) { cam_coll_mode = 0xDB4; } else if (hero.base_condition != 0) { tracking->control_selector = 0; - cam_coll_mode = 0xB4; + cam_coll_mode = CAMERA_TRACKING_BASE_CONTROL_MASK; } else { cam_coll_mode = tracking->control_selector | 0xB4; } From 342adb21c12a0401be2f817999671de0667a28f8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:34:27 +0000 Subject: [PATCH 0522/1502] decomp: clarify names in update_linked_pair_ribbons domain_0_value_1 -> MOBY_STATE_UPDATE_DRAW_AND_SOUND: Retail 0x002cf4d0 loads moby->state from +0x20; 0x002cf4d8-0x002cf4dc compares it with 1 and enters 0x002cf50c. After initializing linked pairs via 0x002cf4f8, 0x002cf500-0x002cf508 writes 1 to that identical +0x20 field. The destination branch gates draw callback registration at 0x002cf524 and voice maintenance/release at 0x002cf52c-0x002cf5a8. The authoritative C already names that same selector's case 1 MOBY_STATE_UPDATE_DRAW_AND_SOUND, so reuse this exact local member for the assignment. --- src/overlays/l16/mobys/linked_pair_ribbons.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/linked_pair_ribbons.c b/src/overlays/l16/mobys/linked_pair_ribbons.c index 2592a513bd..2b2b6df38d 100644 --- a/src/overlays/l16/mobys/linked_pair_ribbons.c +++ b/src/overlays/l16/mobys/linked_pair_ribbons.c @@ -42,7 +42,7 @@ void linked_pair_ribbons_update(struct Moby *moby) { case MOBY_STATE_INITIALIZE_LINKED_PAIRS: if (linked_pair_effect_data[0] == 0) { func_L16_002D0990_2D0870(moby); - moby->state = 1; + moby->state = MOBY_STATE_UPDATE_DRAW_AND_SOUND; } break; case MOBY_STATE_UPDATE_DRAW_AND_SOUND: From 8fa361ed78eb2d5c070a1546db1a1205e102d3d0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:34:28 +0000 Subject: [PATCH 0523/1502] decomp: clarify names in set_video_timing domain_0_value_0 -> FALSE: In set_video_timing, pal_mode_enabled == 0 selects the retail fallthrough from 0x00214970. The sw zero at 0x002149d4 stores 0 to 0x0015ed80, identified as pal_mode in source and g_nPalVideoMode in Ghidra. This branch writes approximately 1/60-second timing and unit frame scales: PAL is disabled, so the existing Boolean FALSE=0 fits the proven enable-flag domain. domain_1_value_1 -> TRUE: Retail bne a0,zero at 0x00214970 selects 0x002149f0 for a nonzero pal_mode_enabled. Its delay-slot li v0,1 at 0x00214974 supplies the sw v0 at 0x00214a4c to 0x0015ed80 (source pal_mode, Ghidra g_nPalVideoMode). The branch installs approximately 1/50-second timing and frame scale 1.2, proving the stored value enables PAL; existing Boolean TRUE=1 fits this normalized enable flag. --- src/runtime/set_video_timing.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/set_video_timing.c b/src/runtime/set_video_timing.c index e8f209a89e..5023f90398 100644 --- a/src/runtime/set_video_timing.c +++ b/src/runtime/set_video_timing.c @@ -16,7 +16,7 @@ extern f32 frame_time_cube_macro __asm__("D_0015ED74") MACRO_ADDR; void set_video_timing(s32 pal_mode_enabled) { if (pal_mode_enabled == 0) { - pal_mode = 0; + pal_mode = FALSE; frame_scale_macro = 1.0f; frame_scale_sq_macro = 1.0f; frame_scale_inv_macro = 1.0f; @@ -27,7 +27,7 @@ void set_video_timing(s32 pal_mode_enabled) { frame_delta_time = 0.016666668f; return; } - pal_mode = 1; + pal_mode = TRUE; frame_scale_macro = 1.2f; frame_scale_sq_macro = 1.44f; frame_scale_inv_macro = 0.8333333f; From 7f1b44a95bbc6edd70998546a4837d17dc895d89 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:34:28 +0000 Subject: [PATCH 0524/1502] decomp: clarify names in record_moby_context_bytes domain_0_value_1 -> MOBY_CONTEXT_MODE_MOBY_RELATIVE: In the authoritative source (SHA-256 3c0190e296592c99ac503472ff1aa2db360ed4abb953c7fcc402b36438fd3a4d), mode == 1 selects key = source - context_moby. Original retail Ghidra keeps param_3 as the subtraction base only for param_4 == 1. Instructions 0x0029b0ac and 0x0029b0d0 compare saved a3/s1 with 1; 0x0029b0dc subtracts context a2 from source t1. Other modes instead load the +0x78 halfword at 0x0029b0f4 before subtracting. At 0x0029b0fc-0x0029b100 the difference becomes a signed 16-bit key, matched at 0x0029b120 and stored at 0x0029b180. The supplied agnogg_ship_front_update calls pass &moby.fBC as source, the same moby as context, and mode 1, consistent with a Moby-relative field offset. This is an offset-base mode, not a Moby state or generic boolean. --- src/overlays/shared/mobys/record_moby_context_bytes.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/mobys/record_moby_context_bytes.c b/src/overlays/shared/mobys/record_moby_context_bytes.c index c03542fa29..ddc2ab7e6b 100644 --- a/src/overlays/shared/mobys/record_moby_context_bytes.c +++ b/src/overlays/shared/mobys/record_moby_context_bytes.c @@ -29,13 +29,16 @@ void record_moby_context_bytes(char *source, void record_moby_context_bytes( char *source, int byte_count, char *context_moby, int mode, Table *entry_table) { + enum { + MOBY_CONTEXT_MODE_MOBY_RELATIVE = 1 + }; short v20 = ((short)MOBY(context_moby)->save_id); short v19 = MOBY(context_moby)->oclass; short key; int i; Entry *e; Entry *ne; - if (mode == 1) { + if (mode == MOBY_CONTEXT_MODE_MOBY_RELATIVE) { key = source - context_moby; } else { key = (int)source - *(unsigned short *)(context_moby + 0x78); From c0f5f69b6854e055364607f846be39dd1056b332 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:34:28 +0000 Subject: [PATCH 0525/1502] decomp: clarify names in update_cutscene_joint_trail domain_0_value_1 -> UPDATE_TRAIL_EFFECT: In the authoritative source, moby->state is both the switch selector and assignment destination, and the same local enum already defines UPDATE_TRAIL_EFFECT = 1. Retail 0x002fad38 reads byte +0x20 of incoming a0; 0x002fad40/0x002fad44 dispatch value 1 to the trail-update branch at 0x002fad68. Initialization at 0x002fad58/0x002fad5c stores 1 to that identical +0x20 byte. The branch obtains joint positions at 0x002faddc/0x002fadf0 and draws the trail at 0x002fae2c, proving this assignment enters the existing UPDATE_TRAIL_EFFECT state rather than a separate control domain. --- src/overlays/l18/mobys/cutscene_joint_trail.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l18/mobys/cutscene_joint_trail.c b/src/overlays/l18/mobys/cutscene_joint_trail.c index 2189f809ad..087ea49d68 100644 --- a/src/overlays/l18/mobys/cutscene_joint_trail.c +++ b/src/overlays/l18/mobys/cutscene_joint_trail.c @@ -46,7 +46,7 @@ void cutscene_joint_trail_update(CutsceneJointTrailMoby *moby) { switch (moby->state) { case INITIALIZE_TRAIL_EFFECT: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = UPDATE_TRAIL_EFFECT; break; case UPDATE_TRAIL_EFFECT: if (D_L18_0015F5C4 == 2) { From df824da24247be95f9ebcef607cc38f1b65eef2c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:36:27 +0000 Subject: [PATCH 0526/1502] decomp: clarify names in activate_smaller_amoeboid domain_0_value_12 -> LARGE_AMOEBOID_DORMANT: Retail 0x002ef3c4 loads 12 and 0x002ef3d8-0x002ef3dc compares it with the candidate Moby state byte at +0x20, proving the amoeboid current-state domain rather than a control mode. The original decompilation likewise requires candidate +0x20 == 12 before copying fields. Authoritative large_amoeboid_update assigns state 12 when activation-volume index pvars+0x25c is -1, clears collision and visibility, lowers Z by 20 and returns immediately on subsequent state-12 updates. This function selects that dormant next-smaller-class candidate, restores collision at 0x002ef424-0x002ef428, sets visible at 0x002ef41c, copies source transforms and invokes update_entity; the damage caller then assigns returned children state 8 for knockback. Together these establish LARGE_AMOEBOID_DORMANT without relying on numeric equivalence to another enum. --- src/overlays/shared/enemies/large_amoeboid.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/large_amoeboid.c b/src/overlays/shared/enemies/large_amoeboid.c index 61ae1b86b5..bad97a9a80 100644 --- a/src/overlays/shared/enemies/large_amoeboid.c +++ b/src/overlays/shared/enemies/large_amoeboid.c @@ -859,6 +859,9 @@ void process_amoeboid_hits_and_update_targeting(char *moby) { } char *activate_smaller_amoeboid(void *source_moby) { + enum { + LARGE_AMOEBOID_DORMANT = 12 + }; struct Moby *source_amoeboid = source_moby; short *list; char *entities; @@ -891,7 +894,7 @@ char *activate_smaller_amoeboid(void *source_moby) { group_index_or_list_entry = index; index &= 0x7FFF; smaller_amoeboid = (struct Moby *)(entities + (index << 8)); - if (smaller_amoeboid->state != 12 || smaller_amoeboid->oclass != next_class) + if (smaller_amoeboid->state != LARGE_AMOEBOID_DORMANT || smaller_amoeboid->oclass != next_class) goto advance; { /* Retail reads both pvars pointers and update_dist before writing the entity. */ From d1978dba12cb79414a50952ee4fd9e13ab6ab9b1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:36:27 +0000 Subject: [PATCH 0527/1502] decomp: clarify names in update_hero_clip_volume_outputs domain_0_value_1 -> MOBY_CHECK_HERO_VOLUME: Authoritative source src/overlays/l05/mobys/hero_clip_volume_outputs.c (SHA-256 fa09ca0cc51f7660eb2eccca4fc6c8c0afbded354ec78d563bef04f1c0568774) loads state from moby->state and already names its value-1 switch arm MOBY_CHECK_HERO_VOLUME. Retail 0x00318a7c loads that byte at moby+0x20, 0x00318aa0 loads 1 and 0x00318aa8 stores it to the identical byte during initialization. On subsequent updates 0x00318a88..0x00318a8c dispatches value 1 to 0x00318ac0, where 0x00318ac4..0x00318ad0 passes the first pvars word and hero position to the volume test. Original Ghidra likewise writes param_1+0x20=1 and tests that same byte for 1. Therefore the assignment enters the existing local moby check state, rather than any hero state, gravity or vehicle enum. --- src/overlays/l05/mobys/hero_clip_volume_outputs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l05/mobys/hero_clip_volume_outputs.c b/src/overlays/l05/mobys/hero_clip_volume_outputs.c index 0fd1f3da0f..957b64d0fb 100644 --- a/src/overlays/l05/mobys/hero_clip_volume_outputs.c +++ b/src/overlays/l05/mobys/hero_clip_volume_outputs.c @@ -30,7 +30,7 @@ void hero_clip_volume_outputs_update(struct Moby *moby) { switch (state) { case MOBY_INITIALIZE: - moby->state = 1; + moby->state = MOBY_CHECK_HERO_VOLUME; moby->flags |= 1; moby->update_dist = 0xFF; moby->collision = 0; From aad60a3570c930644c3c8f6833447fd145843242 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:36:27 +0000 Subject: [PATCH 0528/1502] decomp: clarify names in bombthrower_grass_update domain_0_value_0 -> BOMBTHROWER_GRASS_STATE_LAUNCH_TIMER_UNINITIALIZED: The selector is this bombthrower moby's state byte at +0x20, not a hero selector. Retail 0x002d8c24-0x002d8c28 tests it against zero and skips initialization when nonzero. For zero, 0x002d8c30-0x002d8c44 generates and scales a randomized frame count and writes it to pvars+0 (launch_timer), then 0x002d8c48-0x002d8c4c stores state 1. Authoritative C and original Ghidra show the same initialize-on-zero branch, proving the launch timer uninitialized role. domain_1_value_1 -> BOMBTHROWER_GRASS_STATE_LAUNCH_TIMER_INITIALIZED: Retail 0x002d8c44 first stores the scaled randomized frame countdown into launch_timer at pvars+0, then 0x002d8c48 loads 1 and 0x002d8c4c writes it to the same moby state byte tested at 0x002d8c24-0x002d8c28. This marks completed launch-timer initialization and bypasses its initialization branch on subsequent updates. The shared path calls the timer helper at 0x002d8c50 and rearms the countdown after projectile spawn at 0x002d8cf0-0x002d8d04. Source and original Ghidra agree; no hero enum equivalence is inferred. --- src/overlays/l10/mobys/bombthrower_grass.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/bombthrower_grass.c b/src/overlays/l10/mobys/bombthrower_grass.c index abba7dd8d9..97781d1be4 100644 --- a/src/overlays/l10/mobys/bombthrower_grass.c +++ b/src/overlays/l10/mobys/bombthrower_grass.c @@ -77,13 +77,17 @@ int spawn_bombthrower_grass_projectile(int firing_moby, /* Moby class 939 */ void bombthrower_grass_update(struct Moby *moby) { + enum { + BOMBTHROWER_GRASS_STATE_LAUNCH_TIMER_UNINITIALIZED = 0, + BOMBTHROWER_GRASS_STATE_LAUNCH_TIMER_INITIALIZED = 1 + }; char *launch_timer = (char *)moby->pvars; float launch_offset[4]; float launch_position[4]; - if (moby->state == 0) { + if (moby->state == BOMBTHROWER_GRASS_STATE_LAUNCH_TIMER_UNINITIALIZED) { *(int *)launch_timer = scale_game_frames(random_int_between(D_L10_00161BF0, D_L10_00161BF4)); - moby->state = 1; + moby->state = BOMBTHROWER_GRASS_STATE_LAUNCH_TIMER_INITIALIZED; } if (fast_dec_timer((int *)launch_timer)) { float x = bombthrower_grass_yaw_offset_limit_degrees_gp; From 3bf294ec511a08885227799699b913fcbdf318ee Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:38:10 +0000 Subject: [PATCH 0529/1502] decomp: clarify names in update_lift domain_0_value_1 -> POSITION_FOLLOW_DRIVER: The authoritative source switches on MOBY(moby)->state with POSITION_FOLLOW_DRIVER=1. Retail 0x002ea3ac loads this byte from s0+0x20; 0x002ea3b0 branches on 1 to the driver-follow block at 0x002ea3f4. After saving the baseline at 0x002ea3e4-0x002ea3e8, 0x002ea3f0 writes 1 to the identical s0+0x20 byte. Original Ghidra decompilation confirms this transition, proving reuse of the existing local enum member. domain_2_value_2 -> POSITION_APPROACH_TARGET: The authoritative source names case 2 of MOBY(moby)->state POSITION_APPROACH_TARGET. Retail 0x002ea448 loads 2 and 0x002ea450 stores it to s0+0x20, the same byte read by the selector at 0x002ea3ac. Retail 0x002ea3d4 selects the state-2 block at 0x002ea490, which passes the configured pvars+0 target and s0+0x18 position to the approach helper at 0x002ea4a8. Original Ghidra decompilation confirms the assignment and target approach, proving reuse of this existing enum member. --- src/overlays/l08/mobys/lift.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l08/mobys/lift.c b/src/overlays/l08/mobys/lift.c index 2ff4ba6442..2f961739be 100644 --- a/src/overlays/l08/mobys/lift.c +++ b/src/overlays/l08/mobys/lift.c @@ -26,7 +26,7 @@ void lift_update(char *moby) { switch (MOBY(moby)->state) { case POSITION_BASELINE_INITIALIZE: *(float *)(position_vars + 4) = MOBY(moby)->pos.z; - MOBY(moby)->state = 1; + MOBY(moby)->state = POSITION_FOLLOW_DRIVER; break; case POSITION_FOLLOW_DRIVER: i = *(int *)(position_vars + 8); @@ -38,7 +38,7 @@ void lift_update(char *moby) { break; menu_item_enabled_41 = 1; allocate_voice_for_target_entry(0, 0, moby); - MOBY(moby)->state = 2; + MOBY(moby)->state = POSITION_APPROACH_TARGET; } else { approach_value(moby + 0x18, (*(float *)position_vars - *(float *)(position_vars + 4)) * From 68a8e4089b75550eea12d82507c1fce0eb0d722a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:38:10 +0000 Subject: [PATCH 0530/1502] decomp: clarify names in compute_lift_mount_transform domain_0_value_2 -> LIFT_MOVE_TO_TOP: Retail 0x0030ad8c loads the lift Moby state byte at +0x20; 0x0030ad90 tests it against 2 before 0x0030ad9c tests parity. The authoritative lift.c update_lift switches on this same moby->state and defines LIFT_MOVE_TO_TOP = 2. Its state-2 branch chooses lift_vars->top as the accelerated Z target, and the caller passes that lift Moby directly to compute_lift_mount_transform. Thus this lower bound belongs to the lift state domain and can reuse LIFT_MOVE_TO_TOP; it is unrelated to the equal-valued hero enums or the separate command byte at +0xbc. --- src/overlays/l13/mobys/lift.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/lift.c b/src/overlays/l13/mobys/lift.c index d5c08c0f4e..908e6026bb 100644 --- a/src/overlays/l13/mobys/lift.c +++ b/src/overlays/l13/mobys/lift.c @@ -207,11 +207,14 @@ void lift_update(struct Moby *moby) { } void compute_lift_mount_transform(struct Moby *moby, float *mount_position, float *mount_rotation) { + enum { + LIFT_MOVE_TO_TOP = 2 + }; float mount_offset_angle, k; char *mount_facing_target_base; clear_u64_value(mount_rotation); k = 2.25f; - if ((moby->command >= 2 && (moby->command & 1)) || (moby->state >= 2 && (moby->state & 1))) { + if ((moby->command >= 2 && (moby->command & 1)) || (moby->state >= LIFT_MOVE_TO_TOP && (moby->state & 1))) { mount_offset_angle = -1.5707964f; mount_rotation[0] = moby->rot.y; } else { From 1728d3344e7a5e4c0fb5aaa398ad79337991a61e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:38:10 +0000 Subject: [PATCH 0531/1502] decomp: clarify names in update_hoverboard_girl_cutscene_instances domain_0_value_2 -> GAME_MODE_CUTSCENE: The authoritative source binds game_mode to D_L05_0015F5C4. Original retail Ghidra and 0x00316994-0x003169c4 load that global and return unless it equals 2. In the established update_hoverboard_girl_cutscene_instances function, 0x00316a10-0x00316a1c selects registry instances matching the incoming girl's class; 0x00316a40-0x00316a58 attaches the head manipulator and 0x00316a68-0x00316a70 applies the reference girl's animation state to those instances. Checked caller 0x00316ab8 calls this function at 0x00316af0; source dialogue completion calls begin_dialogue_camera_transition then waits to resume dialogue until game_mode != 2, confirmed by transition call 0x00316bfc, state-3 store 0x00316c08 and mode comparison 0x00316e3c-0x00316e48. Its 0x003172e4-0x003172f8 loads the same global and skips normal girl joint updates specifically in mode 2. Together these establish the cutscene game-mode selector, distinct from all supplied hero enum domains. --- src/overlays/l05/mobys/hoverboard_girl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l05/mobys/hoverboard_girl.c b/src/overlays/l05/mobys/hoverboard_girl.c index 70fce8cf4e..6ef08b95ff 100644 --- a/src/overlays/l05/mobys/hoverboard_girl.c +++ b/src/overlays/l05/mobys/hoverboard_girl.c @@ -164,9 +164,12 @@ extern unsigned char D_L05_0017C8A0[]; * of the girl's class. */ /* Ported from rac1-decomp (src/overlays/l05_rilgar/vendor_0030EB68.c: func_L05_00317E58), where it is exact; names translated to the US level program. */ void update_hoverboard_girl_cutscene_instances(HoverboardGirlMoby *girl) { + enum { + GAME_MODE_CUTSCENE = 2 + }; char *reference_moby = (char *)girl; - if (game_mode == 2 && (D_0015EDB0[0] != 0 || breast_growth_count_gp != 0)) { + if (game_mode == GAME_MODE_CUTSCENE && (D_0015EDB0[0] != 0 || breast_growth_count_gp != 0)) { int i; for (i = 0; i < D_L05_0016CC60.count; i++) { char *moby = D_L05_0016CC60.mobys[i]; From ca579b8e18bd55d5cd056fd6ab9cfdfbdae0f958 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:38:10 +0000 Subject: [PATCH 0532/1502] decomp: clarify names in process_dreks_fleet_turret_hits domain_0_value_0 -> FLEET_TURRET_INITIALIZE: Retail 0x002cbc1c preserves the turret argument in s0 and 0x002cbc28-0x002cbc2c reads its Moby state at +0x20 and skips hit processing when zero. The supplied dreks_fleet_turret_update passes this exact turret_moby to this helper before switching on the same turret_moby->state, where existing FLEET_TURRET_INITIALIZE=0 initializes pvars and group placement. Thus the comparison belongs to that turret state domain. domain_2_value_4 -> FLEET_TURRET_DESTROY: Retail 0x002cbcac-0x002cbcb0 reads state at +0x20 of the same turret argument and skips depletion work when it equals 4. The authoritative caller passes turret_moby directly then switches on turret_moby->state; its existing FLEET_TURRET_DESTROY=4 branch spawns effects, calls cart_burst and marks this moby for removal. This is the identical turret state domain, not a hero state or hit-reaction status. domain_3_value_11 -> FLEET_TURRET_NOT_DEPLETED: Retail 0x002cbcb4 initializes the local depletion status to 0xB. At 0x002cbcc4-0x002cbcd8 the helper float is subtracted from pvars+0x20, the remainder is stored, and status is replaced with 1 only when remainder <=0. The initial 0xB therefore denotes the local not-depleted outcome, distinguished from the depleted value tested at 0x002cbcdc; it is not a Moby state. domain_4_value_1 -> FLEET_TURRET_DEPLETED: Retail 0x002cbcc4 subtracts the helper float output from pvars+0x20, 0x002cbcc8 tests the remainder <=0, and 0x002cbcd8 assigns local status 1 on that outcome. The comparison at 0x002cbcdc then gates the turret destruction-state store at 0x002cbce8. Thus this assignment names the local depleted result, without claiming the scalar is health or a timer. domain_5_value_1 -> FLEET_TURRET_DEPLETED: The source depletion_status comparison corresponds to retail 0x002cbcdc, where status 1 selects the block storing turret state 4 at 0x002cbce8 and clearing flag 0x1000. This status is assigned 1 at 0x002cbcd8 only after the remainder <=0 test at 0x002cbcc8, so the comparison must reuse FLEET_TURRET_DEPLETED from that same local depletion domain. domain_6_value_4 -> FLEET_TURRET_DESTROY: Retail 0x002cbce8 stores byte 4 into +0x20 of s0, the original turret Moby retained at 0x002cbc1c, after local depletion. The supplied dreks_fleet_turret_update invokes this helper on turret_moby before dispatching the identical field, with established FLEET_TURRET_DESTROY=4 performing effects and removal. The assignment and earlier state-4 comparison therefore reuse that canonical turret state member. --- src/overlays/l17/mobys/dreks_fleet_turret.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/overlays/l17/mobys/dreks_fleet_turret.c b/src/overlays/l17/mobys/dreks_fleet_turret.c index f9710c7e1e..173ca094b0 100644 --- a/src/overlays/l17/mobys/dreks_fleet_turret.c +++ b/src/overlays/l17/mobys/dreks_fleet_turret.c @@ -295,6 +295,12 @@ void dreks_fleet_turret_update(struct Moby *turret_moby) { void process_dreks_fleet_turret_hits(struct Moby *turret_moby) __asm__("FUN_L17_002cbc10"); void process_dreks_fleet_turret_hits(struct Moby *turret_moby) { + enum { + FLEET_TURRET_INITIALIZE = 0, + FLEET_TURRET_DEPLETED = 1, + FLEET_TURRET_DESTROY = 4, + FLEET_TURRET_NOT_DEPLETED = 0xB + }; char *turret_vars; char *hit_animation_state; char *hit_record; @@ -302,7 +308,7 @@ void process_dreks_fleet_turret_hits(struct Moby *turret_moby) { float fv; int depletion_status; turret_vars = ((char *)turret_moby->pvars); - if (turret_moby->state != 0) { + if (turret_moby->state != FLEET_TURRET_INITIALIZE) { fv = 0.0f; hit_record = find_moby_hit(turret_moby, 0x330000, 0); if (hit_record != 0) { @@ -317,14 +323,14 @@ void process_dreks_fleet_turret_hits(struct Moby *turret_moby) { hit_animation_state = turret_vars + 0x60; hit_reaction( turret_moby, hit_record, turret_vars + 0x20, 0, &hit_reaction_status, &fv, 0, 4); - if (hit_reaction_status != 1 && turret_moby->state != 4) { + if (hit_reaction_status != 1 && turret_moby->state != FLEET_TURRET_DESTROY) { float remaining_value = *(float *)(turret_vars + 0x20) - fv; *(float *)(turret_vars + 0x20) = remaining_value; - depletion_status = 0xB; + depletion_status = FLEET_TURRET_NOT_DEPLETED; if (remaining_value <= 0.0f) - depletion_status = 1; - if (depletion_status == 1) { - turret_moby->state = 4; + depletion_status = FLEET_TURRET_DEPLETED; + if (depletion_status == FLEET_TURRET_DEPLETED) { + turret_moby->state = FLEET_TURRET_DESTROY; turret_moby->flags &= 0xEFFF; } *(unsigned char *)(turret_vars + 0x67) = 0xF0; From 13796d643e602320becc51ac55b78d783e7be4ab Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:38:10 +0000 Subject: [PATCH 0533/1502] decomp: clarify names in update_shattering_prop domain_0_value_1 -> HIT_EFFECT_WAIT_FOR_HIT: Source local enum already defines HIT_EFFECT_WAIT_FOR_HIT=1 for switch(moby->state). Retail 0x002f5280 reads byte +0x20 from the incoming Moby retained in s0; 0x002f529c selects initial state zero and 0x002f52c0 stores 1 to that identical byte. The next update branches on state 1 at 0x002f5288 to 0x002f52c4, which waits for a nonnull find_moby_hit result and positive +0x2C float. Thus this assignment enters the existing wait-for-hit member of the same local state domain. domain_1_value_2 -> HIT_EFFECT_EMIT_AND_REMOVE: Source local enum defines HIT_EFFECT_EMIT_AND_REMOVE=2 for switch(moby->state). Retail 0x002f52c4-0x002f52e4 checks the hit result and positive float at +0x2C; 0x002f52ec loads 2 and 0x002f52f4 stores it into the same Moby +0x20 state read at 0x002f5280. State 2 branches at 0x002f52ac to 0x002f52f8; this path emits fragment groups through 0x002f5338/0x002f5358, spawns placement class 0x752 at 0x002f5364, and marks the Moby for removal at 0x002f536c. This transition therefore reuses the established emit-and-remove member. --- src/overlays/l17/mobys/shattering_prop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l17/mobys/shattering_prop.c b/src/overlays/l17/mobys/shattering_prop.c index 1a5501b362..038e018f7d 100644 --- a/src/overlays/l17/mobys/shattering_prop.c +++ b/src/overlays/l17/mobys/shattering_prop.c @@ -25,13 +25,13 @@ void shattering_prop_update(struct Moby *moby) { char *hit_result = find_moby_hit(moby, 0x10000, 0); switch (moby->state) { case HIT_EFFECT_INITIALIZE: - moby->state = 1; + moby->state = HIT_EFFECT_WAIT_FOR_HIT; break; case HIT_EFFECT_WAIT_FOR_HIT: if (hit_result && *(float *)(hit_result + 0x2C) > 0.0f) flag = 1; if (flag) - moby->state = 2; + moby->state = HIT_EFFECT_EMIT_AND_REMOVE; break; case HIT_EFFECT_EMIT_AND_REMOVE: FUN_0022da68(0, 0, (int)moby); From 114912e9e7a4c008d84b34e6fd71150cd9d33263 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:38:10 +0000 Subject: [PATCH 0534/1502] decomp: clarify names in initialize_hero_aligned_camera_pose domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x002e9de4/0x002e9dec forms &hero (0x0013F350); 0x002e9e04 loads its +0x20A4 vehicle_mode byte, and 0x002e9e08-0x002e9e0c compares it to 2. Original Ghidra cRam001413f4 == 2 selects scale 9.5 at 0x002e9e18-0x002e9e28. Authoritative C's neighboring update_hero_aligned_camera_position reads the identical hero.vehicle_mode field and uses HERO_VEHICLE_MODE_GIANT_CLANK for the identical 9.5 up-axis scale. Thus the selector belongs to the supplied shared HeroVehicleMode enum in include/rnc/hero/hero_state.h, whose canonical member has value 2. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x002e9e04 reads +0x20A4 from &hero into v1; after the mode-2 branch, 0x002e9e10 loads 1 and 0x002e9e34 compares that same v1 byte. Original Ghidra cRam001413f4 == 1 selects scale 0.9 at 0x002e9e3c-0x002e9e50. Authoritative C identifies this byte as hero_state->vehicle_mode; neighboring update_hero_aligned_camera_position uses HERO_VEHICLE_MODE_CLANK for that same field and its 0.9 scale branch. This proves the shared HeroVehicleMode selector domain and supports reuse of its canonical value-1 member, rather than equal-valued state or gravity constants. --- src/overlays/shared/camera/hero_aligned_camera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/camera/hero_aligned_camera.c b/src/overlays/shared/camera/hero_aligned_camera.c index 95e9499ebe..2207e59976 100644 --- a/src/overlays/shared/camera/hero_aligned_camera.c +++ b/src/overlays/shared/camera/hero_aligned_camera.c @@ -267,9 +267,9 @@ void initialize_hero_aligned_camera_pose(char *camera_object) { u128 scaled_hero_up_axis; struct Hero *hero_state = &hero; FUN_001f9bf8_2e9dd0(&hero_up_axis, ((char *)hero_state->moby) + 0xE0, 1.0f); - if (hero_state->vehicle_mode == 2) { + if (hero_state->vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { FUN_001f9a68_2e9dd0(&scaled_hero_up_axis, &hero_up_axis, 9.5f); - } else if (hero_state->vehicle_mode == 1) { + } else if (hero_state->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { FUN_001f9a68_2e9dd0(&scaled_hero_up_axis, &hero_up_axis, 0.9f); } else { FUN_001f9a68_2e9dd0(&scaled_hero_up_axis, &hero_up_axis, 1.6f); From 1976b98d244f3b9552c56abe4b527e892859acc7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:38:10 +0000 Subject: [PATCH 0535/1502] decomp: clarify names in spawn_gold_bolt_particles domain_0_value_1 -> GOLD_BOLT_WAIT_FOR_PICKUP: Retail 0x00308a0c loads the caller Moby state byte at +0x20; 0x003089f4 and 0x00308a10 compare it with 1. Original Ghidra confirms *(char *)(param_1+0x20)==1 selects scaled moby position instead of moby_point_position. Authoritative source gold_bolt_update defines GOLD_BOLT_WAIT_FOR_PICKUP=1 in its switch on this same moby->state and passes that moby to FUN_L01_003089f0_f in the waiting branch. Initialization assigns state 1 after home/rotation setup, while the waiting branch animates the pickup and tests hero proximity before transitioning to pickup cutscene state 2. Thus this selector belongs to the gold-bolt Moby state domain, and reuses its existing semantic member. --- src/overlays/shared/pickups/gold_bolt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/pickups/gold_bolt.c b/src/overlays/shared/pickups/gold_bolt.c index 3da2b14641..32372d2478 100644 --- a/src/overlays/shared/pickups/gold_bolt.c +++ b/src/overlays/shared/pickups/gold_bolt.c @@ -783,6 +783,9 @@ void update_gold_bolt_pickup_camera(struct Moby *moby) { void spawn_gold_bolt_particles(struct Moby *moby) __asm__("FUN_L01_003089f0"); void spawn_gold_bolt_particles(struct Moby *moby) { + enum { + GOLD_BOLT_WAIT_FOR_PICKUP = 1 + }; float v[4]; float particle_velocity[4]; float u[4]; @@ -790,7 +793,7 @@ void spawn_gold_bolt_particles(struct Moby *moby) { int i; int particle_lifetime; int loop_particle_lifetime; - if (moby->state == 1) { + if (moby->state == GOLD_BOLT_WAIT_FOR_PICKUP) { fast_vec_scale(v, moby, 0.0009765625f); } else { moby_point_position(moby, 0, v); From 7e4c761f580954b61c070479d478c11fbb432996 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:38:10 +0000 Subject: [PATCH 0536/1502] decomp: clarify names in check_memory_card domain_0_value_2 -> MEMCARD_TYPE_SUPPORTED_FOR_STARTUP: Authoritative src/save/check_memory_card.c SHA-256 0cffae00ec68e9764445381741f7ea53d71310fa2f74f4d829aee9d0535394bd passes &card_type as sceMcGetInfo's third argument. Retail 0x00209170 sets a2=sp for that output; after sceMcSync completes, 0x002091f8 loads sp+0, 0x002091fc loads 2, and 0x00209200 branches on inequality to return notice 1 at 0x0020927c (delay slot 0x00209204). Only equality proceeds to the format test and directory/free-space checks. The original Ghidra decompilation independently has iStack_60 != 2 returning 1; startlevel uses that return as the startup memory-card notice. Thus this constant is the supported card type for the startup check, not an operation/substep ID. Bounded helper evidence at 0x00123d68 confirms the third argument is retained as the asynchronous information output pointer at 0x00159a28; no hardware-specific identity is inferred. --- src/save/check_memory_card.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/save/check_memory_card.c b/src/save/check_memory_card.c index 37a0a1432e..ab5004e5d8 100644 --- a/src/save/check_memory_card.c +++ b/src/save/check_memory_card.c @@ -17,6 +17,9 @@ extern u8 memory_card_info_sync_outputs[] __asm__("D_0013D348"); s32 check_memory_card(void) __asm__("FUN_00209168"); s32 check_memory_card(void) { + enum { + MEMCARD_TYPE_SUPPORTED_FOR_STARTUP = 2 + }; s32 card_type; s32 free_blocks; s32 format; @@ -41,7 +44,7 @@ s32 check_memory_card(void) { if (card_state->unkBC == -2) { return 0; } - if (card_type != 2) { + if (card_type != MEMCARD_TYPE_SUPPORTED_FOR_STARTUP) { return 1; } if (format == 0) { From 6a19160ca5f42a00973ba657a731329ed71837b9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:40:16 +0000 Subject: [PATCH 0537/1502] decomp: clarify names in link_localized_display_text domain_0_value_1 -> HELP_STATE_DISPLAY_START_DELAY: Retail 0x001fdd60 loads 1 into a1 and 0x001fdd80 stores it at 0x001996d0, confirmed as DAT_001996d0 = 1 in the original Ghidra decompilation and D_001996D0.state = 1 in the SHA-bound C. The supplied update_help_state source switches on this identical D_001996D0.state field and already names value 1 HELP_STATE_DISPLAY_START_DELAY; its idle branch calls link_localized_display_text after selecting a valid message. The assigned function renders that message at 0x001fde08 and initializes its box extents, entering this established display-start state. This proves the same state domain rather than merely matching a numeric value. --- src/ui/text/link_localized_display_text.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/text/link_localized_display_text.c b/src/ui/text/link_localized_display_text.c index 63bbe1c487..da3e9ef5f4 100644 --- a/src/ui/text/link_localized_display_text.c +++ b/src/ui/text/link_localized_display_text.c @@ -18,7 +18,7 @@ void link_localized_display_text(void) __asm__("FUN_001fdd58"); void link_localized_display_text(void) { /* win is unsigned (lhu) but w/h are signed: the narrowing gives the sll 16 / sra 17 shift-by-one retail has instead of a plain sra. */ - u16 win[16]; + enum { HELP_STATE_DISPLAY_START_DELAY = 1 } ;u16 win[16]; HelpState *box; void *text; s32 screenY; @@ -26,7 +26,7 @@ void link_localized_display_text(void) { short measured_text_width, rendered_text_height; s32 hHalf5; - help_state.state = 1; + help_state.state = HELP_STATE_DISPLAY_START_DELAY; help_state.timer = 0; if (D_0015EE1D != 0 || D_0015EE1C != 0) { allocate_voice_for_bank_entry(0, 1, 0); From bdf82299aad65014a9d730ffbe8f9d52c56bb85e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:40:16 +0000 Subject: [PATCH 0538/1502] decomp: clarify names in update_beam_slot_controller domain_0_value_1 -> SLOT_CONTROLLER_STATE_PROCESS_SLOTS: The authoritative source switches on slot_controller->state with existing member SLOT_CONTROLLER_STATE_PROCESS_SLOTS = 1. Retail 0x002e1e18-0x002e1e24 reads +0x20 and routes value 1 to the three-slot processing loop; 0x002e1e64 and 0x002e1e74 write that same value to +0x20 after initialization. This assignment belongs to exactly the existing controller-state domain. domain_2_value_4 -> BEAM_SLOT_STATE_PENDING_RELEASE: Retail 0x002e1e98 loads beam_slot_state[i] from array 0x00161bf8; 0x002e1ea0-0x002e1eb0 tests value 4 and calls release_beam_slot(i) at 0x002e20f8. After an effects dispatch at 0x002e1ec8, 0x002e1ed0 writes 4 back to that same slot. Thus this per-slot value marks a slot pending release on its next controller visit; supplied release_beam_slot C clears its state/id and releases endpoint lights. domain_3_value_0 -> BEAM_SLOT_STATE_INACTIVE: Retail 0x002e1e48 clears each beam_slot_state entry at 0x00161bf8 during controller initialization. The slot-state load at 0x002e1e98 reaches the zero test at 0x002e1ebc, which skips dispatch and release for zero. Supplied release_beam_slot C also resets beam_slot_state[i] and beam_slot_id[i] to zero while releasing endpoint lights, establishing zero as the inactive per-slot state. --- src/overlays/l00/mobys/beam_slot_controller.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l00/mobys/beam_slot_controller.c b/src/overlays/l00/mobys/beam_slot_controller.c index 9a3c987c8c..ebda9723c4 100644 --- a/src/overlays/l00/mobys/beam_slot_controller.c +++ b/src/overlays/l00/mobys/beam_slot_controller.c @@ -22,6 +22,10 @@ void beam_slot_controller_update(SlotMoby *slot_controller) { SLOT_CONTROLLER_STATE_INITIALIZE = 0, SLOT_CONTROLLER_STATE_PROCESS_SLOTS = 1 }; + enum { + BEAM_SLOT_STATE_INACTIVE = 0, + BEAM_SLOT_STATE_PENDING_RELEASE = 4 + }; s32 i; s32 j; s32 dispatched_slot_count; @@ -33,7 +37,7 @@ void beam_slot_controller_update(SlotMoby *slot_controller) { beam_slot_state[j] = 0; beam_slot_id[j] = 0; } - slot_controller->state = 1; + slot_controller->state = SLOT_CONTROLLER_STATE_PROCESS_SLOTS; slot_controller->alpha = 0xFF; break; case SLOT_CONTROLLER_STATE_PROCESS_SLOTS: @@ -41,9 +45,9 @@ void beam_slot_controller_update(SlotMoby *slot_controller) { for (i = 0; i < 3; i++) { slot_state = beam_slot_state[i]; if (slot_state == 1) { - } else if (slot_state == 4) { + } else if (slot_state == BEAM_SLOT_STATE_PENDING_RELEASE) { release_beam_slot(i); - } else if (slot_state != 0) { + } else if (slot_state != BEAM_SLOT_STATE_INACTIVE) { dispatched_slot_count++; update_slot_panes_and_effects(beam_slot_id[i], i); beam_slot_state[i] = 4; From 512595276dc2c952a5d5693f934e75dd2632aefa Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:40:16 +0000 Subject: [PATCH 0539/1502] decomp: clarify names in spawn_debris domain_0_value_0 -> BURNING_DEBRIS_STATE_INITIAL: Authoritative burning_debris.c snapshot SHA-256 fb8009777ac30d69bf530f83dce7a328e7b4eccb576773a0e5d491d23f626805 assigns spawned_moby->state = 0 inside the successful create_moby(0x5E6) path. Retail 0x0030be94/98 requests that class, 0x0030bea0 retains its result in s1, and 0x0030bea4 null-checks it. At 0x0030bef0, sb zero,0x20(s1) initializes this new moby's state; position/rotation, scale, vector, spin and lifetime are also initialized before the first update_entity call at 0x0030bf7c/80. Original Ghidra likewise stores zero to iVar8+0x20 on this allocation path. Thus this value is the burning debris initial state, without inferring any later lifecycle or another class's state domain. --- src/overlays/l01/mobys/burning_debris.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/burning_debris.c b/src/overlays/l01/mobys/burning_debris.c index ebd3a8502c..2b4eb995a8 100644 --- a/src/overlays/l01/mobys/burning_debris.c +++ b/src/overlays/l01/mobys/burning_debris.c @@ -194,6 +194,9 @@ DebrisMoby *spawn_debris(DebrisMoby *parent_moby, f32 scale) __asm__("FUN_L01_0030be70"); DebrisMoby *spawn_debris(DebrisMoby *parent_moby, void *debris_vector_source, f32 scale) { + enum { + BURNING_DEBRIS_STATE_INITIAL = 0 + }; DebrisMoby *spawned_moby; DebrisVars *debris_vars; @@ -203,7 +206,7 @@ DebrisMoby *spawn_debris(DebrisMoby *parent_moby, void *debris_vector_source, f3 debris_vars->parent = parent_moby; qcopy(&spawned_moby->pos, &parent_moby->pos); spawned_moby->rot = parent_moby->rot; - spawned_moby->state = 0; + spawned_moby->state = BURNING_DEBRIS_STATE_INITIAL; spawned_moby->b30 = 0xFF; spawned_moby->h32 = 0xFF; spawned_moby->b31 = 1; From eb503628cd533f54e7e3cf374d64d3950ba7041d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:40:17 +0000 Subject: [PATCH 0540/1502] decomp: clarify names in update_breakaway_prop domain_0_value_1 -> HIT_EFFECT_WAIT_FOR_HIT: The authoritative source switches on moby->state and already labels state 1 HIT_EFFECT_WAIT_FOR_HIT. Retail lbu at 0x002f53b0 reads +0x20(s0); state 0 reaches sb a0,+0x20(s0) at 0x002f53f0 with a0=1 from 0x002f53b4. Original Ghidra likewise writes 1 to iVar4+0x20. This is the exact same selector storage; the next state-1 branch waits for a non-null hit result with positive float +0x2C. domain_1_value_2 -> HIT_EFFECT_EMIT_AND_REMOVE: The source already labels moby->state 2 HIT_EFFECT_EMIT_AND_REMOVE. Retail 0x002f53f4-0x002f5414 gates on non-null find_moby_hit result and positive float +0x2C, then loads 2 at 0x002f541c and stores it into +0x20(s0) at 0x002f5424, the same state byte read at 0x002f53b0. Original Ghidra confirms this assignment. The state-2 branch calls fragment/placement helpers at 0x002f547c, 0x002f549c and 0x002f54a8, then removal at 0x002f54b0, proving reuse of the existing local enum member. --- src/overlays/l17/mobys/breakaway_prop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l17/mobys/breakaway_prop.c b/src/overlays/l17/mobys/breakaway_prop.c index c960d8a23b..349b1c22e8 100644 --- a/src/overlays/l17/mobys/breakaway_prop.c +++ b/src/overlays/l17/mobys/breakaway_prop.c @@ -37,7 +37,7 @@ void breakaway_prop_update(struct Moby *moby) { char *hit_result = find_moby_hit(moby, 0x10000, 0); switch (moby->state) { case HIT_EFFECT_INITIALIZE: - moby->state = 1; + moby->state = HIT_EFFECT_WAIT_FOR_HIT; break; case HIT_EFFECT_WAIT_FOR_HIT: if (hit_result) { @@ -45,7 +45,7 @@ void breakaway_prop_update(struct Moby *moby) { flag = 1; } if (flag) - moby->state = 2; + moby->state = HIT_EFFECT_EMIT_AND_REMOVE; break; case HIT_EFFECT_EMIT_AND_REMOVE: allocate_voice_for_target_entry(0, 0, (int)moby); From 73d6a2abe75da9ad0be3f94048120a8e33db0f6e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:40:17 +0000 Subject: [PATCH 0541/1502] decomp: clarify names in update_level01_environment_map_uv_scroll domain_0_value_1 -> UV_SCROLL_STATE_UPDATE_AND_QUEUE_DRAW: In the authoritative source snapshot (SHA-256 faf9ac7278c85215816d74b2f56e4ff894145eabb8295094c0ba1767bb6b1bd7), moby->state is both the switch selector and the assignment target. Retail 0x0030f214 loads its byte at a1+0x20; 0x0030f21c/0x0030f220 test it against 1 and branch to 0x0030f24c. Initialization clears UV offsets at 0x0030f234/0x0030f240, loads 1 at 0x0030f238, and stores it to that same byte at 0x0030f248. The selected state-1 path adds frame_delta_time*0.025 to both UV offsets, wraps them, and queues draw callback 0x0030f0e0 at 0x0030f324-0x0030f328. This directly reuses the local enum member already naming the identical selector's case, UV_SCROLL_STATE_UPDATE_AND_QUEUE_DRAW, rather than the unrelated equal-valued TRUE. --- src/overlays/l01/mobys/environment_mapped_meshes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/environment_mapped_meshes.c b/src/overlays/l01/mobys/environment_mapped_meshes.c index 9893632f56..c368dff231 100644 --- a/src/overlays/l01/mobys/environment_mapped_meshes.c +++ b/src/overlays/l01/mobys/environment_mapped_meshes.c @@ -1415,7 +1415,7 @@ void environment_map_scroll_update(ScrollMoby *moby) { case UV_SCROLL_STATE_INITIALIZE: level01_environment_map_uv_scroll_offsets[0] = 0.0f; level01_environment_map_uv_scroll_offsets[1] = 0.0f; - moby->state = 1; + moby->state = UV_SCROLL_STATE_UPDATE_AND_QUEUE_DRAW; break; case UV_SCROLL_STATE_UPDATE_AND_QUEUE_DRAW: uv_scroll_delta = frame_delta_time * 0.025f; From 14fed0155b8e78492c255c2c94370ca7ed6a5287 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:40:17 +0000 Subject: [PATCH 0542/1502] decomp: clarify names in advance_audio_stream_state domain_0_value_0 -> CD_READ_STATE_IDLE: Retail 0x002206a4 loads the signed halfword at 0x001516d8, and 0x002206a8 skips the first read when it is nonzero before the call at 0x002206d4. The authoritative source identifies this field as music_stream_state.read_state; supplied start_audio_stream_read tests this exact field against CD_READ_STATE_IDLE=0 before starting a CD read and sets it ACTIVE on success. domain_1_value_0 -> CD_READ_STATE_IDLE: Retail 0x002206f4 loads the same read-state halfword at 0x001516d8; 0x002206f8 skips advancement when nonzero, while zero selects 2 at 0x00220704 and stores it to stream+0x44. This is the first-read wait completion check. Supplied start_audio_stream_read establishes CD_READ_STATE_IDLE=0 for the exact music_stream_state.read_state field. domain_2_value_0 -> CD_READ_STATE_IDLE: Retail 0x00220714 loads the same signed halfword at 0x001516d8 and 0x00220718 blocks the second read on nonzero before the call at 0x00220744. Source maps it to music_stream_state.read_state, which supplied start_audio_stream_read explicitly compares with CD_READ_STATE_IDLE=0 before initiating a CD read and sets ACTIVE after acceptance. domain_3_value_0 -> CD_READ_STATE_IDLE: Retail 0x00220764 reads the same halfword at 0x001516d8; 0x00220768 returns on nonzero, while zero permits state 4 to be stored to stream+0x44 at 0x00220774. It is the second-read wait completion condition. Supplied start_audio_stream_read already names zero CD_READ_STATE_IDLE in comparisons of this exact music_stream_state.read_state field. --- src/audio/streaming/advance_audio_stream_state.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/audio/streaming/advance_audio_stream_state.c b/src/audio/streaming/advance_audio_stream_state.c index 815018ebd0..54f7e37dc3 100644 --- a/src/audio/streaming/advance_audio_stream_state.c +++ b/src/audio/streaming/advance_audio_stream_state.c @@ -34,10 +34,13 @@ s32 advance_audio_stream_state(struct AudioStream *stream) { AUDIO_STREAM_START_SECOND_READ = 2, AUDIO_STREAM_WAIT_SECOND_READ = 3 }; + enum { + CD_READ_STATE_IDLE = 0 + }; switch (stream->unk44) { case AUDIO_STREAM_START_FIRST_READ: - if (stream->unk48 == 0 || music_stream_state.read_state != 0) { + if (stream->unk48 == 0 || music_stream_state.read_state != CD_READ_STATE_IDLE) { break; } if (disc_table.unk2C8[game_language].size == 0) { @@ -52,12 +55,12 @@ s32 advance_audio_stream_state(struct AudioStream *stream) { } break; case AUDIO_STREAM_WAIT_FIRST_READ: - if (music_stream_state.read_state == 0) { + if (music_stream_state.read_state == CD_READ_STATE_IDLE) { stream->unk44 = 2; } break; case AUDIO_STREAM_START_SECOND_READ: - if (stream->unk4C == 0 || music_stream_state.read_state != 0) { + if (stream->unk4C == 0 || music_stream_state.read_state != CD_READ_STATE_IDLE) { break; } if (disc_table.unk2F8[game_language].size == 0) { @@ -72,7 +75,7 @@ s32 advance_audio_stream_state(struct AudioStream *stream) { } break; case AUDIO_STREAM_WAIT_SECOND_READ: - if (music_stream_state.read_state == 0) { + if (music_stream_state.read_state == CD_READ_STATE_IDLE) { stream->unk44 = 4; } break; From 2dfb6c7334232e53fbf549764d287f89c3407b4d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:42:28 +0000 Subject: [PATCH 0543/1502] decomp: clarify names in red_orb_update domain_0_value_1 -> RED_ORB_STATE_PULSE_COLOR: Retail 0x002df510 reads the moby state byte at s2+0x20; 0x002df51c-0x002df520 compares that byte to 1 and enters the pulse branch at 0x002df558. The initialize branch converts the stored phase to radians at 0x002df530-0x002df54c, then stores 1 into that identical state byte at 0x002df534/0x002df554. Source state is copied from moby->state and its value-1 case already uses RED_ORB_STATE_PULSE_COLOR; that branch advances phase, computes sine and tweens color (0x002df558-0x002df618). Thus the assignment enters precisely the existing local enum domain and member, rather than an unrelated equal-valued control constant. --- src/overlays/shared/props/red_orb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/props/red_orb.c b/src/overlays/shared/props/red_orb.c index 74ccbc3f38..f1dd0299ad 100644 --- a/src/overlays/shared/props/red_orb.c +++ b/src/overlays/shared/props/red_orb.c @@ -101,7 +101,7 @@ void red_orb_update(struct Moby *moby) { switch (state) { case RED_ORB_STATE_INITIALIZE_PHASE: *(float *)orb_data = *(float *)orb_data * DEG_TO_RAD; - moby->state = 1; + moby->state = RED_ORB_STATE_PULSE_COLOR; break; case RED_ORB_STATE_PULSE_COLOR: pulse_phase_or_sine = fast_add_rotations( From fb57fc2ba161b5e5bdf96f4b9578b3724236709e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:42:28 +0000 Subject: [PATCH 0544/1502] decomp: clarify names in update_weapon_hud_state domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Source snapshot SHA-256 48ceddbb8caa43d719db59f9c4255cabcf61d60321a6f43b32490f81799a4c2f assigns mode directly from hero_state->vehicle_mode. Retail 0x0023add8 forms &hero=0x0013f350; 0x0023ade8 loads a1 from hero+0x20a4 (vehicle_mode), and a1 remains that selector through li v0,2 at 0x0023ae60 and bne a1,v0 at 0x0023ae64. Thus this is HeroVehicleMode, not HeroStateId or HeroGravityMode. Supplied include/rnc/hero/hero_state.h enum-domain evidence defines its canonical value 2 as HERO_VEHICLE_MODE_GIANT_CLANK. The equality branch queues a cropped gauge for &hero_state->vehicle_hp with limit 200 at 0x0023aeac-0x0023aeb4, corroborating the vehicle HUD domain. --- src/overlays/shared/ui/hud/draw_weapon_ammo_hud_panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/ui/hud/draw_weapon_ammo_hud_panel.c b/src/overlays/shared/ui/hud/draw_weapon_ammo_hud_panel.c index 4630645fee..dc2fc4b471 100644 --- a/src/overlays/shared/ui/hud/draw_weapon_ammo_hud_panel.c +++ b/src/overlays/shared/ui/hud/draw_weapon_ammo_hud_panel.c @@ -262,7 +262,7 @@ void update_weapon_hud_state(void) { draw_weapon_ammo_hud_panel, &weapon_ammo_counts[weapon_item_id], D_L00_001C40B0[weapon_item_id].hE); - } else if (k = -1, mode == 2) { + } else if (k = -1, mode == HERO_VEHICLE_MODE_GIANT_CLANK) { if (D_L00_0015F970 != k) { set_animation_parameter(D_L00_0015F970, 0); D_L00_0015F970 = k; From ca7ec3e768569889e18ad927d91327888586afcd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:42:28 +0000 Subject: [PATCH 0545/1502] decomp: clarify names in jet_end_mount domain_0_value_0 -> JET_END_MOUNT_REPOSITION_BEHIND_HERO: The selector is the int mode argument retained in s0 at retail 0x002eac30 and compared with zero at 0x002eac48. Its zero branch builds a rotation matrix from hero.motion.rot (0x0013f3e0) at 0x002eac50-74, copies that basis into the follow camera, computes a -1.0 backward offset and 1.2 up offset at 0x002eac78-a4, and adds both to hero.motion.pos (0x0013f3d0) into camera+0x30 at 0x002eaca8-c4. Original Ghidra shows the same auStack_a0/auStack_b0/auStack_c0 data flow. The supplied birdbot caller invokes jet_end_mount(0) when its mounted cutscene ends, alongside restoring HERO_STATE_IDLE and clearing cutscene_active. Thus this request repositions the camera behind the hero; it is not a hero state enum value. --- src/overlays/shared/camera/scripted_camera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/camera/scripted_camera.c b/src/overlays/shared/camera/scripted_camera.c index 8013871544..8df91b46cf 100644 --- a/src/overlays/shared/camera/scripted_camera.c +++ b/src/overlays/shared/camera/scripted_camera.c @@ -126,10 +126,10 @@ void jet_mount(V_2eaaa0 *pa, V_2eaaa0 *pb, s32 mode, s32 transition_duration_fra void jet_end_mount(int mode) __asm__("FUN_L00_002eac18"); void jet_end_mount(int mode) { - LevelCamera *camera_globals = &l00_camera_lui; + enum { JET_END_MOUNT_REPOSITION_BEHIND_HERO = 0 } ;LevelCamera *camera_globals = &l00_camera_lui; char *current_follow_camera = ((char *)camera_globals->unk180); initialize_camera_record_handoff_defaults(); - if (mode == 0) { + if (mode == JET_END_MOUNT_REPOSITION_BEHIND_HERO) { float camera_up_offset[4] __attribute__((aligned(16))); float camera_backward_offset[4] __attribute__((aligned(16))); float hero_rotation_matrix[16] __attribute__((aligned(16))); From 65823cbfbc3b8906754924633bca60e770fff9d8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:42:28 +0000 Subject: [PATCH 0546/1502] decomp: clarify names in draw_number domain_0_value_255 -> DRAW_NUMBER_KIND_FROM_FLAGS: Authoritative source src/overlays/shared/rendering/effects/spawn_type_10_particle.c SHA-256 57fe5aaac00cc739b9aff2eac502c51f11b3211a792fb6573f15fe7c08a9a57c compares unsigned char kind to 0xFF. Original retail Ghidra tests param_8 == -1. Retail 0x002857a0 masks kind into s2, and 0x002857dc-0x002857e0 compare it with 255. On equality, 0x002857f8-0x0028580c derive particle+9 from flags>>5 and converted 4.0f; 0x002857fc and 0x00285808-0x00285824 choose particle+3 as 0x48 or 0x44 using flags bit zero. On inequality, 0x00285828-0x0028582c copy flags and kind directly to those bytes. Thus this sentinel selects kind/header settings derived from flags. Supplied compute_sampled_spline_path_lengths uses 0xff in all three draw_number call sites. --- .../shared/rendering/effects/spawn_type_10_particle.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/rendering/effects/spawn_type_10_particle.c b/src/overlays/shared/rendering/effects/spawn_type_10_particle.c index 2f0c73ff43..8c362b85d5 100644 --- a/src/overlays/shared/rendering/effects/spawn_type_10_particle.c +++ b/src/overlays/shared/rendering/effects/spawn_type_10_particle.c @@ -98,12 +98,15 @@ char *draw_number(float scale, short particle_lifetime, unsigned char kind) { + enum { + DRAW_NUMBER_KIND_FROM_FLAGS = 0xFF + }; char *particle = create_part(0x29); if (particle != 0) { int *tail = (int *)(particle + 0x20); qcopy(particle + 0x10, particle_spawn_position); *(int *)(particle + 4) = particle_color; - if (kind == 0xFF) { + if (kind == DRAW_NUMBER_KIND_FROM_FLAGS) { particle[9] = (flags >> 5) * 16 + truncate_float_to_s32(4.0f); if (flags & 1) { particle[3] = 0x48; From 685aa4bede116b4e7cf1f0d080cdfaf9982d8968 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:44:22 +0000 Subject: [PATCH 0547/1502] decomp: clarify names in scePad2CreateSocket domain_0_value_1 -> DBC_SOCKET_TYPE_PAD2: The bound C source defines DbcSocketParam.type at offset 4. In the established scePad2CreateSocket, retail 0x00124b20 loads 1 and 0x00124b24 stores it at sp+4, then 0x00124b28/0x00124b38 pass that request to sceDbcCreateSocket, with two Pad2 banks at addr and addr+0x80. The helper at 0x00124748/0x0012474c copies request offset 4 unchanged into RPC offset 4 before RPC 0x80000901 at 0x001247b0. The init_pads caller uses the resulting socket for controller_state. This proves the assigned value identifies the Pad2 DBC socket type, separately from option bit 1 at 0x00124b2c and the active flag at 0x00124b6c. --- src/sdk/input/sce_pad2_create_socket.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/input/sce_pad2_create_socket.c b/src/sdk/input/sce_pad2_create_socket.c index 842683dcca..d3c0e667b2 100644 --- a/src/sdk/input/sce_pad2_create_socket.c +++ b/src/sdk/input/sce_pad2_create_socket.c @@ -42,6 +42,9 @@ extern void *memset(void *, s32, u32); extern void *memcpy(void *, const void *, u32); s32 scePad2CreateSocket(Pad2SocketParam *param, void *addr) { + enum { + DBC_SOCKET_TYPE_PAD2 = 1 + }; DbcSocketParam dbc; Pad2Side *side; s32 socket; @@ -63,7 +66,7 @@ s32 scePad2CreateSocket(Pad2SocketParam *param, void *addr) { dbc.number = 0; dbc.name[0] = 0; } - dbc.type = 1; + dbc.type = DBC_SOCKET_TYPE_PAD2; dbc.option |= 1; socket = sceDbcCreateSocket(&dbc, addr, (u8 *)addr + 128); if (socket < 0) { From 81817bedfe591afe4979b521eb3c1385c8faf1a1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:44:22 +0000 Subject: [PATCH 0548/1502] decomp: clarify names in tresspasser_door2_update domain_0_value_1 -> TRESSPASSER_DOOR2_WAIT_FOR_LINKED_MOBY: Retail 0x002e0154 loads this moby's state from +0x20 and 0x002e0158 dispatches state 1 to 0x002e01a0, which resolves the pvars+0x10 linked moby and waits for its state 4. After saving the starting position at 0x002e018c-0x002e0194, 0x002e019c writes 1 to the same moby+0x20 field. Thus this assignment enters the existing TRESSPASSER_DOOR2_WAIT_FOR_LINKED_MOBY case in the exact same selector domain. domain_1_value_2 -> TRESSPASSER_DOOR2_SLIDE_TO_OFFSET_POSITION: Retail 0x002e01cc-0x002e01e0 checks the linked moby's state 4 and selects 2 for the store to this moby's +0x20 state at 0x002e0264. The same field is loaded at 0x002e0154; state 2 branches at 0x002e017c to 0x002e01e4, constructing the saved start position plus a -2-length rot_row1 offset and moving toward it. This assignment therefore enters the existing TRESSPASSER_DOOR2_SLIDE_TO_OFFSET_POSITION case, rather than naming the linked moby's separate state domain. domain_2_value_3 -> TRESSPASSER_DOOR2_SLIDE_STOPPED: In the slide case, retail 0x002e0210-0x002e0240 forms destination minus current position, limits the movement step and adds it to moby->pos. 0x002e0244-0x002e025c tests that step's length against zero; only on zero does 0x002e0260-0x002e0264 store state 3 to this moby's +0x20. The entry dispatch at 0x002e0154-0x002e0188 handles only states 0, 1 and 2, so state 3 stops further sliding in this updater. SLIDE_STOPPED describes this observed behavior without asserting a gameplay lifecycle or target reached. --- src/overlays/l02/mobys/tresspasser_door2.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/l02/mobys/tresspasser_door2.c b/src/overlays/l02/mobys/tresspasser_door2.c index a612d57533..7d77133b64 100644 --- a/src/overlays/l02/mobys/tresspasser_door2.c +++ b/src/overlays/l02/mobys/tresspasser_door2.c @@ -23,11 +23,14 @@ void tresspasser_door2_update(struct Moby *moby) { TRESSPASSER_DOOR2_WAIT_FOR_LINKED_MOBY = 1, TRESSPASSER_DOOR2_SLIDE_TO_OFFSET_POSITION = 2 }; + enum { + TRESSPASSER_DOOR2_SLIDE_STOPPED = 3 + }; char *tresspasser_door2_vars = (char *)moby->pvars; switch (moby->state) { case TRESSPASSER_DOOR2_CAPTURE_START_POSITION: qcopy(tresspasser_door2_vars, &moby->pos); - moby->state = 1; + moby->state = TRESSPASSER_DOOR2_WAIT_FOR_LINKED_MOBY; break; case TRESSPASSER_DOOR2_WAIT_FOR_LINKED_MOBY: { int id = *(int *)(tresspasser_door2_vars + 0x10); @@ -36,7 +39,7 @@ void tresspasser_door2_update(struct Moby *moby) { int linked_moby_class = MOBY(linked_moby)->oclass; if (linked_moby_class == 0x267 || linked_moby_class == 0x23F) { if (((unsigned char *)linked_moby)[0x20] == 4) - moby->state = 2; + moby->state = TRESSPASSER_DOOR2_SLIDE_TO_OFFSET_POSITION; } } break; @@ -51,7 +54,7 @@ void tresspasser_door2_update(struct Moby *moby) { FUN_L00_0025f730(movement_step, D_0015ED6C + D_0015ED6C); fast_vec_add(pos, pos, movement_step); if (fast_vec_length(movement_step) == 0.0f) - moby->state = 3; + moby->state = TRESSPASSER_DOOR2_SLIDE_STOPPED; break; } } From 0aa6b4b307245d9a1c1167a5cbc40f3045fe6480 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:44:22 +0000 Subject: [PATCH 0549/1502] decomp: clarify names in ocean_rilgar_update domain_0_value_1 -> OCEAN_RILGAR_UPDATE_BOBBING: The authoritative ocean_rilgar.c snapshot (SHA-256 1c565b2ed01b753ea821508c997901d2034466a2ce02797c3275a5ea090f9ef1) switches on moby->state and already declares OCEAN_RILGAR_UPDATE_BOBBING=1 for that same selector. Retail 0x00316120 loads the state byte from s0+0x20; 0x0031612c branches on 1 to 0x00316164. Initialization loads v1=1 at 0x00316150 and stores it to the identical s0+0x20 byte at 0x00316160, proving that the assignment selects this existing local enum member. The selected branch computes frame-driven sine bobbing, stores height at 0x00211b28 (0x0031622c-0x00316234), and queues the ocean draw callback with the same moby (0x00316238-0x00316244). --- src/overlays/l05/mobys/ocean_rilgar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l05/mobys/ocean_rilgar.c b/src/overlays/l05/mobys/ocean_rilgar.c index f2a98c86bc..04122995ff 100644 --- a/src/overlays/l05/mobys/ocean_rilgar.c +++ b/src/overlays/l05/mobys/ocean_rilgar.c @@ -45,7 +45,7 @@ void ocean_rilgar_update(struct Moby *moby) { switch ((unsigned char)((char)moby->state)) { case OCEAN_RILGAR_INITIALIZE: prepare_scaled_table_with_byte_128(D_L05_00211B20, 1.0f); - moby->state = 1; + moby->state = OCEAN_RILGAR_UPDATE_BOBBING; ((unsigned char *)moby)[0x30] = 0xFF; break; case OCEAN_RILGAR_UPDATE_BOBBING: From 7df84adf7aba2a1a5ac6a089f9f72cbcd4949bc0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:44:22 +0000 Subject: [PATCH 0550/1502] decomp: clarify names in spawn_rocket domain_0_value_1 -> ROCKET_STATE_APPROACH_TARGET_OFFSET: Retail 0x002de414/0x002de418 creates class 0x1B3; 0x002de488 loads 1 and 0x002de4a8 stores it at that moby's +0x20 state byte, independently of visibility at +0x31. Original Ghidra likewise writes *(undefined1 *)(iVar6 + 0x20)=1. Retail 0x002de42c loads its pvars, 0x002de4d8/0x002de4e0/0x002de4e4 initializes pitch/yaw/target at +0x40/+0x44/+0x4C and 0x002de4e8..0x002de4ec copies velocity at +0x20. Authoritative rocket.c defines these exact fields in D46 and update_rocket switches on the same M46 state byte at +0x20, with established member ROCKET_STATE_APPROACH_TARGET_OFFSET=1. That branch uses target->position + Z 5, applies stored roll/yaw/pitch to the target offset, corrects stored velocity toward it, and transitions to state 2 when angular differences align. Thus this assignment selects the rocket approach-target-offset state, not boolean TRUE or a control/request domain. --- src/overlays/l08/mobys/rocket.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/rocket.c b/src/overlays/l08/mobys/rocket.c index ef1728f670..00d76215cc 100644 --- a/src/overlays/l08/mobys/rocket.c +++ b/src/overlays/l08/mobys/rocket.c @@ -556,6 +556,9 @@ typedef struct RocketVars { } RocketVars; struct Moby *spawn_rocket(void *pos, struct Moby *target, void *velocity, float pitch, float yaw) { + enum { + ROCKET_STATE_APPROACH_TARGET_OFFSET = 1 + }; struct Moby *moby = create_moby(0x1B3); RocketVars *projectile_vars; float *reference; @@ -576,7 +579,7 @@ struct Moby *spawn_rocket(void *pos, struct Moby *target, void *velocity, float scale *= rocket_scale_multiplier_gp; moby->update_dist = 0xFF; moby->visible = 1; - *(volatile u8 *)&moby->state = 1; + *(volatile u8 *)&moby->state = ROCKET_STATE_APPROACH_TARGET_OFFSET; moby->draw_dist = 0xFF; moby->scale = scale; set_moby_color(moby, rocket_color_red_gp, rocket_color_green_gp, rocket_color_blue_gp); From 8deb81e89f5697be4a2a4ef4d67ba83f93074d51 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:44:22 +0000 Subject: [PATCH 0551/1502] decomp: clarify names in update_tracked_group_watcher domain_0_value_0 -> TRACKED_GROUP_WATCHER_STATE_INITIALIZE_TRACKING: The selector is this watcher moby's state byte: lbu at 0x0030be68 reads a0+0x20 and 0x0030be6c selects the zero branch. At 0x0030bea0-0x0030bedc this branch walks eight IDs from pvars+0x10 and initializes saved classes at pvars+0x30 from moby+0xA6, or -1 for missing/removing mobys. Thus state 0 initializes tracking. domain_1_value_1 -> TRACKED_GROUP_WATCHER_STATE_MONITOR_TRACKED_MOBYS: At 0x0030be74 and 0x0030be7c, literal 1 is stored to this watcher moby's state byte a0+0x20 during snapshot initialization. The same byte is compared with 1 at 0x0030bef8-0x0030befc, entering 0x0030bf28-0x0030bf98, which validates tracked IDs and saved classes, counts surviving entries and removes the watcher below its threshold. This assignment enters the monitoring state. domain_2_value_2 -> TRACKED_GROUP_WATCHER_STATE_ZERO_THRESHOLD_IDLE: After initializing saved classes, 0x0030bee0 loads pvars[0]; 0x0030bee4 skips the state change when this threshold is nonzero. Otherwise 0x0030beec-0x0030bef4 stores 2 into this watcher moby's state byte at +0x20. On subsequent updates, state 2 passes neither the zero initialization branch nor the state-1 monitoring branch (0x0030bef8-0x0030befc) and returns, establishing zero-threshold idle behavior within this function. domain_3_value_1 -> TRACKED_GROUP_WATCHER_STATE_MONITOR_TRACKED_MOBYS: The state byte loaded from this moby+0x20 at 0x0030be68 is compared with 1 at 0x0030bef8-0x0030befc. That branch checks eight IDs, saved classes at pvars+0x30, current moby classes at +0xA6 and removal bytes 0xFD/0xFE, counts valid entries and calls the checked removal helper when count < pvars[0] at 0x0030bf88-0x0030bf98. It is the same monitoring state assigned at 0x0030be7c. --- src/overlays/l13/mobys/tracked_group_watcher.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l13/mobys/tracked_group_watcher.c b/src/overlays/l13/mobys/tracked_group_watcher.c index d5953985ae..0d647cdb4d 100644 --- a/src/overlays/l13/mobys/tracked_group_watcher.c +++ b/src/overlays/l13/mobys/tracked_group_watcher.c @@ -8,13 +8,13 @@ void tracked_group_watcher_update(struct Moby *moby) __asm__("FUN_L13_0030be60") /* Moby class 1577 */ void tracked_group_watcher_update(struct Moby *moby) { - int *moby_vars = (int *)moby->pvars; - if (moby->state == 0) { + enum { TRACKED_GROUP_WATCHER_STATE_INITIALIZE_TRACKING = 0 , TRACKED_GROUP_WATCHER_STATE_MONITOR_TRACKED_MOBYS = 1 , TRACKED_GROUP_WATCHER_STATE_ZERO_THRESHOLD_IDLE = 2 } ;int *moby_vars = (int *)moby->pvars; + if (moby->state == TRACKED_GROUP_WATCHER_STATE_INITIALIZE_TRACKING) { int *ids = moby_vars + 4; int *cls = moby_vars + 12; char *base; int i; - moby->state = 1; + moby->state = TRACKED_GROUP_WATCHER_STATE_MONITOR_TRACKED_MOBYS; base = (char *)moby_base; for (i = 0; i < 8; i++) { unsigned char *o = (unsigned char *)(base + (ids[i] << 8)); @@ -24,8 +24,8 @@ void tracked_group_watcher_update(struct Moby *moby) { cls[i] = -1; } if (moby_vars[0] == 0) - moby->state = 2; - } else if (moby->state == 1) { + moby->state = TRACKED_GROUP_WATCHER_STATE_ZERO_THRESHOLD_IDLE; + } else if (moby->state == TRACKED_GROUP_WATCHER_STATE_MONITOR_TRACKED_MOBYS) { int *ids = moby_vars + 4; int *cls = moby_vars + 12; char *base = (char *)moby_base; From de3e32cd7993ee4e6a7c303609283275cde6f254 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:44:22 +0000 Subject: [PATCH 0552/1502] decomp: clarify names in update_floating_platform_tilt_and_bob domain_0_value_5 -> STATE_SINKING: Retail 0x002d8734-0x002d873c reads the platform moby byte at +0x20 and compares it with 5, selecting the +/-0.5235988 rotation clamp. Caller retail 0x002d86cc-0x002d86d0 passes the same platform pointer; 0x002d84a0-0x002d84a4 and 0x002d84e4-0x002d84ec assign 5 on grounded-hero/proximity triggers. Its sinking branch subtracts acceleration from pvars+0x70 at 0x002d85f4-0x002d8600 and adds that displacement to baseline Z at 0x002d8604-0x002d8620. Authoritative floating_platform_update already names this same moby->state domain member STATE_SINKING = 5. domain_1_value_4 -> STATE_WAIT_FOR_SINK_TRIGGER: Retail 0x002d8734 loads platform moby+0x20; 0x002d8778-0x002d877c compares that same byte with 4, selecting +/-0.08726646 tilt limits. The caller passes this identical moby at 0x002d86cc-0x002d86d0, sets its +0x20 to 4 after computing the tilt increment at 0x002d8420-0x002d843c, then checks hero grounding/proximity at 0x002d8480-0x002d84ec to transition it to sinking state 5. Authoritative floating_platform_update already calls this domain member STATE_WAIT_FOR_SINK_TRIGGER = 4; HERO_STATE_CROUCH and VOICE_SLOT_STOP_REQUESTED are unrelated domains. --- src/overlays/l18/mobys/floating_platform.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/floating_platform.c b/src/overlays/l18/mobys/floating_platform.c index b06f4caa7b..eab66e15e0 100644 --- a/src/overlays/l18/mobys/floating_platform.c +++ b/src/overlays/l18/mobys/floating_platform.c @@ -188,17 +188,21 @@ extern float floating_platform_bob_amplitude_gp __asm__("D_L18_00161A48") __attr extern float floating_platform_bob_phase_rate_gp __asm__("D_L18_00161A4C") __attribute__((sda)); void update_floating_platform_tilt_and_bob(struct Moby *moby) { + enum { + STATE_WAIT_FOR_SINK_TRIGGER = 4, + STATE_SINKING = 5 + }; char *floating_platform_private_vars = (char *)moby->pvars; float unclamped_rotation_y = fast_add_rotations(moby->rot.y, *(float *)(floating_platform_private_vars + 0x6C)); moby->rot.y = unclamped_rotation_y; - if (moby->state == 5) { + if (moby->state == STATE_SINKING) { if (unclamped_rotation_y > 0.5235988f) { moby->rot.y = 0.5235988f; } else if (unclamped_rotation_y < -0.5235988f) { moby->rot.y = -0.5235988f; } - } else if (moby->state == 4) { + } else if (moby->state == STATE_WAIT_FOR_SINK_TRIGGER) { if (unclamped_rotation_y > 0.08726646f) { moby->rot.y = 0.08726646f; } else if (unclamped_rotation_y < -0.08726646f) { From 796ac95aa57e92ef1f126e63640d14b633ab6d11 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:46:16 +0000 Subject: [PATCH 0553/1502] decomp: clarify names in exit_hero_vehicle_mode domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x00210b48 forms &hero (0x0013F350); 0x00210b50 loads its byte +0x20A4 and 0x00210b3c/0x00210b54 compare it with 1. This is source hero_state->vehicle_mode, the same field assigned from mode in enter_hero_vehicle_mode, whose switch already uses HeroVehicleMode member HERO_VEHICLE_MODE_CLANK. Entry saves ordinary health and loads vehicle_mode_hp; exit 0x00210b5c-0x00210b70 performs the inverse health transfer. Reuse the established vehicle-mode member, independently of current-state/control-mode IDs. domain_1_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x00210b98 rebuilds the same &hero base and 0x00210ba0 loads byte +0x20A4; 0x00210b9c/0x00210ba4 compare this vehicle_mode with 2 before clearing animation parameter +0x1634 at 0x00210bac-0x00210bc0. Source enter_hero_vehicle_mode assigns mode to that same field and already selects HERO_VEHICLE_MODE_GIANT_CLANK to initialize vehicle_hp=200. The source hero_check_damage switch also uses that member for vehicle_hp and giant-Clank blast cleanup. This proves the shared HeroVehicleMode domain and canonical member. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00210bc8 rebuilds &hero and 0x00210bd4 stores zero to byte +0x20A4, the same vehicle_mode field tested above and set by enter_hero_vehicle_mode. Exit detaches the vehicle reference at +0xA84, restores the saved +0xA88 moby to hero.moby at 0x00210c04-0x00210c0c and copies hero position at 0x00210c14-0x00210c18. Source update_hero_collision_capsule_dimensions and hero_check_damage already switch on hero.vehicle_mode using HERO_VEHICLE_MODE_ON_FOOT for 0. Reuse that canonical HeroVehicleMode member for the restored mode. --- src/overlays/shared/hero/hero_switch_item.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index b4f6bec912..3aa59433f3 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -2372,7 +2372,7 @@ void exit_hero_vehicle_mode(void) __asm__("FUN_L00_00210b30"); void exit_hero_vehicle_mode(void) { struct Hero *hero_state = &hero; unsigned char *vehicle_moby; - if (hero_state->vehicle_mode == 1) { + if (hero_state->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero_state->health.vehicle_mode_hp = hero_state->health.hp; hero_state->health.hp = hero_state->health.unk22B0; if (hero_state->unk1620) { @@ -2386,7 +2386,7 @@ void exit_hero_vehicle_mode(void) { } { struct Hero *vehicle_animation_owner = &hero; - if (vehicle_animation_owner->vehicle_mode == 2 && vehicle_animation_owner->unk1634 != -1) { + if (vehicle_animation_owner->vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && vehicle_animation_owner->unk1634 != -1) { set_animation_parameter(vehicle_animation_owner->unk1634, 0); vehicle_animation_owner->unk1634 = -1; } @@ -2394,7 +2394,7 @@ void exit_hero_vehicle_mode(void) { } { struct Hero *vehicle_exit_owner = &hero; - vehicle_exit_owner->vehicle_mode = 0; + vehicle_exit_owner->vehicle_mode = HERO_VEHICLE_MODE_ON_FOOT; vehicle_moby = vehicle_exit_owner->unkA84; if (vehicle_moby) { MOBY(vehicle_moby)->flags &= ~6; From 391af5c8a1b817f1d2ea8626091777962d878efd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:46:16 +0000 Subject: [PATCH 0554/1502] decomp: clarify names in set_up_vis_gif_viewer domain_0_value_0 -> FIRST_REGULAR_MATERIAL_INDEX: The authoritative source src/rendering/packets/set_up_vis_gif_viewer.c (SHA-256 4e6e902db2ce71adcd25794b9217918beeaacc04def9badccf69e866db034099) tests mode >= 0. Caller prepare_resident_class_render_data passes material_index as this sixth argument after optional slot-material remapping. Original Ghidra calls it lMaterialIndex and indexes g_abResidentRenderMaterialTemplates. Retail 0x00202fd0 preserves this argument in t4; 0x00202fd4..0x00203018 computes a 24-byte template stride and loads its three words. The bltz at 0x00203014 separates negative fallback indices from regular indices beginning at zero. The regular path masks template draw bits at 0x00203028, packs the index at bit 24 at 0x00203050..0x0020305c and copies template texture words at 0x00203064/0x0020306c. Thus zero is the first regular material index, not a boolean or null pointer. --- src/rendering/packets/set_up_vis_gif_viewer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rendering/packets/set_up_vis_gif_viewer.c b/src/rendering/packets/set_up_vis_gif_viewer.c index 6f2fb7dcd6..94e07e7172 100644 --- a/src/rendering/packets/set_up_vis_gif_viewer.c +++ b/src/rendering/packets/set_up_vis_gif_viewer.c @@ -16,6 +16,9 @@ void set_up_vis_gif_viewer(u64 *packet_destination, s32 material_control_shift2, s32 mode) { + enum { + FIRST_REGULAR_MATERIAL_INDEX = 0 + }; u64 template_texture_state0; s64 template_draw_control_bits; u64 template_texture_state1; @@ -24,7 +27,7 @@ void set_up_vis_gif_viewer(u64 *packet_destination, template_texture_state0 = resident_material_templates[mode * 3]; template_draw_control_bits = resident_material_templates[mode * 3 + 1]; template_texture_state1 = resident_material_templates[mode * 3 + 2]; - if (mode >= 0) { + if (mode >= FIRST_REGULAR_MATERIAL_INDEX) { packet_destination[0] = (0x20 | (template_draw_control_bits & 0x1C)) | ((u64)prim << 6) | ((u64)(u32)draw_control_high_word << 32); packet_destination += 2; From 4389c7c75b6dd4e1f43716dfebca8d26c76517d2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:46:16 +0000 Subject: [PATCH 0555/1502] decomp: clarify names in process_linked_switch_damage domain_0_value_2 -> HIT_PROCESSING_DAMAGE_THRESHOLD: Assigned retail 0x002e4350 passes the stack status output to hit_reaction; 0x002e4390-0x002e4398 compares that output against 2 and skips hit damage below it. At or above this threshold, 0x002e43a0 loads hit_record+0x2C damage, then clears depleted health or subtracts damage at 0x002e43e4-0x002e43f0. Checked level-13 helper 0x00266510 saves this fifth-argument pointer in s3; 0x00266558 initializes status 0, 0x00266630-0x00266634 sets 1 for no hit, and 0x00266870-0x002668c8 writes statuses 2/3/4. Suppression sets 1 at 0x002669d4-0x002669d8. The return code instead travels through s1/v0 at 0x00266a48, proving that equal-valued HIT_REACTION_REMOVE belongs to a different domain. --- src/overlays/l13/mobys/linked_switch_group.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/linked_switch_group.c b/src/overlays/l13/mobys/linked_switch_group.c index 40c3b48e91..ee47ddcd6e 100644 --- a/src/overlays/l13/mobys/linked_switch_group.c +++ b/src/overlays/l13/mobys/linked_switch_group.c @@ -37,6 +37,9 @@ int process_linked_switch_damage(struct Moby *moby, char *moby_data, float *heal HIT_REACTION_HIGH_INTERPOLATION_TARGET_ALTERNATE = 10, HIT_REACTION_NO_HIT = 11 }; + enum { + HIT_PROCESSING_DAMAGE_THRESHOLD = 2 + }; char *hit_record = find_moby_hit(moby, 0x330000, 0); int hit_processing_status; int health_depleted = 0; @@ -62,7 +65,7 @@ int process_linked_switch_damage(struct Moby *moby, char *moby_data, float *heal break; } color_animation_state = moby_data + 0x60; - if (hit_processing_status >= 2) { + if (hit_processing_status >= HIT_PROCESSING_DAMAGE_THRESHOLD) { float damage_amount = *(float *)(hit_record + 0x2C); unsigned short fl; if (*health <= damage_amount) { From a153567c0c2525efd9ab44eaa0f801887b39f75f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:46:16 +0000 Subject: [PATCH 0556/1502] decomp: clarify names in activate_first_inactive_group_moby domain_0_value_1 -> GROUP_MOBY_STATE_INACTIVE: Authoritative source src/overlays/shared/enemies/sentrybot_alarm.c SHA-256 9722834a476df467407c2e3e45e11612317f42ae0deeda5308f70d0085f9eeb5 loads state from listed_moby[0x20]. Retail 0x002a28b0-0x002a28bc resolves the group entry to a moby-pool object using the masked 15-bit index and 0x100 stride. At 0x002a28c0-0x002a28c4 its +0x20 byte is compared with 1; nonmatching members are skipped. The matching member becomes state 2 at 0x002a28cc-0x002a28d8, has animation reset, flags enabled and collision restored at 0x002a28dc-0x002a2920, receives its activation timer and supplied position at 0x002a2930-0x002a2968, and faces the hero before success is returned. Together with the established activate_first_inactive_group_moby name and the supplied sentrybot_alarm_update group-release caller, this proves the tested state denotes an inactive group member eligible for activation. Equal-valued Hero constants have no matching selector domain. --- src/overlays/shared/enemies/sentrybot_alarm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/sentrybot_alarm.c b/src/overlays/shared/enemies/sentrybot_alarm.c index 1c4020d574..cbc4bcb1d5 100644 --- a/src/overlays/shared/enemies/sentrybot_alarm.c +++ b/src/overlays/shared/enemies/sentrybot_alarm.c @@ -55,13 +55,13 @@ extern short sentrybot_alarm_voice_owner_gp __asm__("D_L15_00161AC8") __attribut int activate_first_inactive_group_moby(int moby_group_index, void *pos) __asm__("FUN_L15_002a2868"); int activate_first_inactive_group_moby(int moby_group_index, void *pos) { - short *group_moby_entry = (short *)D_L15_001ABE40[moby_group_index]; + enum { GROUP_MOBY_STATE_INACTIVE = 1 } ;short *group_moby_entry = (short *)D_L15_001ABE40[moby_group_index]; struct Hero *hero_data = &hero; do { unsigned char *listed_moby = (unsigned char *)l15_moby_array + ((*(unsigned short *)group_moby_entry & 0x7FFF) << 8); unsigned char state = MOBY(listed_moby)->state; - if (state == 1) { + if (state == GROUP_MOBY_STATE_INACTIVE) { char *activated_moby_data; MOBY(listed_moby)->state = 2; if (MOBY(listed_moby)->prev_seq != 0) From 1e0d865cebcf6535cea743954025b4e2959f97cc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:46:16 +0000 Subject: [PATCH 0557/1502] decomp: clarify names in update_beam_slots domain_0_value_1 -> BEAM_SLOT_STATE_REGISTERED: In the SHA-bound beam_slots.c source, register_beam_slot fills the owner ID, resets phases/lights, then assigns beam_slot_state[j] = 1; set_beam_origin_transform_and_endpoint advances 1 to 2 on initial endpoint submission. In the assigned retail controller, 0x00303a88 loads the slot-state array word and 0x00303a8c compares it with 1; 0x00303a94-0x00303aac only clears this registered slot when the associated object's signed state byte +0x20 is negative. This selector is the per-beam slot state, not the outer moby state or any Hero domain. domain_1_value_4 -> BEAM_SLOT_STATE_PENDING_RELEASE: Retail 0x00303ab0 compares the loaded slot state with 4, and 0x00303ab8 calls release_beam_slot with the slot index. After update_slot_panes_and_effects at 0x00303ad4, 0x00303adc stores 4 back to this same slot word. The SHA-bound source's set_beam_origin_transform_and_endpoint changes slot state 4 to 3 when refreshed, so 4 specifically marks a processed slot pending release unless refreshed before its next controller pass. release_beam_slot clears state/id and releases endpoint lights. domain_2_value_0 -> BEAM_SLOT_STATE_UNUSED: Retail 0x00303ac8 skips the per-slot effects update when the loaded slot state is zero; initialization at 0x00303a38-0x00303a50 clears all three state/object pairs, and dead registered objects clear both words at 0x00303aa4-0x00303aac. In the SHA-bound source, release_beam_slot and release_beam_slot_by_id clear both beam_slot_state and beam_slot_id to zero; register_beam_slot selects an empty ID entry and assigns state 1. Thus zero is the unused beam-slot state, independent of the controller's outer initialization state. --- src/overlays/shared/rendering/effects/beam_slots.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/rendering/effects/beam_slots.c b/src/overlays/shared/rendering/effects/beam_slots.c index 202a158d7b..8c04749224 100644 --- a/src/overlays/shared/rendering/effects/beam_slots.c +++ b/src/overlays/shared/rendering/effects/beam_slots.c @@ -35,6 +35,11 @@ void beam_slots_update(unsigned char *moby) { SLOT_UPDATE_STATE_INITIALIZE = 0, SLOT_UPDATE_STATE_PROCESS_SLOTS = 1 }; + enum { + BEAM_SLOT_STATE_UNUSED = 0, + BEAM_SLOT_STATE_REGISTERED = 1, + BEAM_SLOT_STATE_PENDING_RELEASE = 4 + }; int i; int j; int started_slot_count; @@ -53,14 +58,14 @@ void beam_slots_update(unsigned char *moby) { started_slot_count = 0; for (i = 0; i < 3; i++) { slot_state = D_L14_00162148[i]; - if (slot_state == 1) { + if (slot_state == BEAM_SLOT_STATE_REGISTERED) { if (((signed char *)D_L14_001621D8[i])[0x20] < 0) { D_L14_00162148[i] = 0; D_L14_001621D8[i] = 0; } - } else if (slot_state == 4) { + } else if (slot_state == BEAM_SLOT_STATE_PENDING_RELEASE) { release_beam_slot(i); - } else if (slot_state != 0) { + } else if (slot_state != BEAM_SLOT_STATE_UNUSED) { started_slot_count++; update_slot_panes_and_effects(D_L14_001621D8[i], i); D_L14_00162148[i] = 4; From ef59e17f93752f96ace621c3780825cfe65ea2af Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:46:16 +0000 Subject: [PATCH 0558/1502] decomp: clarify names in update_owner_linked_moby_state domain_2_value_3 -> LINKED_MOBY_STATE_FADE_OUT: Retail 00310064-00310068 loads this moby's state byte at s0+0x20 and compares it unsigned against 3 before forced removal. The same byte is loaded at 00310078 for the switch. Its existing local member LINKED_MOBY_STATE_FADE_OUT=3 names the branch at 00310124-00310130 decrementing alpha, so the comparison uses that exact state boundary. domain_3_value_4 -> LINKED_MOBY_STATE_REMOVE: When the pvars+0x70 owner is null or has either tested invalid state, retail 00310070-00310074 stores 4 into this moby's state byte at s0+0x20. The subsequent switch reads that same byte; its existing LINKED_MOBY_STATE_REMOVE=4 branch at 00310160 calls mark_moby_for_removal on s0. domain_4_value_1 -> LINKED_MOBY_STATE_WAIT_FOR_ANIMATION_FLAG: Retail 003100a0-003100c4 checks sequence 1, optionally blends that sequence, and stores 1 at s0+0x20. This is the same current-moby state used by the switch, whose existing LINKED_MOBY_STATE_WAIT_FOR_ANIMATION_FLAG=1 branch at 003100c8-003100e4 waits for anim_flags bit 2 before advancing. domain_5_value_2 -> LINKED_MOBY_STATE_HANDLE_HITS: Retail 003100c8-003100dc tests this moby's animation flag bit 2 and stores 2 into its state byte s0+0x20, clearing hit_slot at 003100e4. The switch on this identical byte has existing LINKED_MOBY_STATE_HANDLE_HITS=2; its 003100e8 call invokes handle_owner_linked_moby_hits, corroborated by the supplied damage-processing helper source. domain_6_value_4 -> LINKED_MOBY_STATE_REMOVE: In the existing LINKED_MOBY_STATE_FADE_OUT branch, retail 00310124-00310130 decreases alpha and 00310134-00310150 compares the interpolated value against 13.5. On exceeding it, 00310154-0031015c stores 4 into the same s0+0x20 state byte selected by the switch. Existing LINKED_MOBY_STATE_REMOVE=4 dispatches to mark_moby_for_removal at 00310160. --- src/overlays/l11/mobys/owner_linked_moby.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l11/mobys/owner_linked_moby.c b/src/overlays/l11/mobys/owner_linked_moby.c index 44e08b6c0d..a70b599677 100644 --- a/src/overlays/l11/mobys/owner_linked_moby.c +++ b/src/overlays/l11/mobys/owner_linked_moby.c @@ -106,8 +106,8 @@ void owner_linked_moby_update(struct Moby *moby) { char *health_ptr = &owner_linked_moby_vars->unk20; struct Moby *owner_moby = owner_linked_moby_vars->unk70; if (owner_moby == 0 || owner_moby->state == 0xFE || owner_moby->state == 0xFD) { - if (moby->state < 3) { - moby->state = 4; + if (moby->state < LINKED_MOBY_STATE_FADE_OUT) { + moby->state = LINKED_MOBY_STATE_REMOVE; } } switch (moby->state) { @@ -115,12 +115,12 @@ void owner_linked_moby_update(struct Moby *moby) { if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, 0xF); } - moby->state = 1; + moby->state = LINKED_MOBY_STATE_WAIT_FOR_ANIMATION_FLAG; break; case LINKED_MOBY_STATE_WAIT_FOR_ANIMATION_FLAG: if (moby->anim_flags & 2) { moby->hit_slot = 0xFF; - moby->state = 2; + moby->state = LINKED_MOBY_STATE_HANDLE_HITS; } break; case LINKED_MOBY_STATE_HANDLE_HITS: @@ -134,7 +134,7 @@ void owner_linked_moby_update(struct Moby *moby) { moby->alpha--; } if (compute_interpolated_record_value(moby) > 13.5f) { - moby->state = 4; + moby->state = LINKED_MOBY_STATE_REMOVE; } break; case LINKED_MOBY_STATE_REMOVE: From fdc93a4b1a09ac274e2e47c8c8b1edf8b5b53878 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:48:34 +0000 Subject: [PATCH 0559/1502] decomp: clarify names in compute_elevator_camera_pose domain_0_value_2 -> ELEVATOR_STATE_MOVE_TO_TOP: Retail 0x002b40b8 loads the moby's state byte at +0x20, 0x002b40bc compares it against 2, and 0x002b40c4/0x002b40c8 test state parity to choose camera azimuth +/- pi/2. The authoritative elevator.c snapshot (SHA-256 7493e8d1519e146a1c987421881cfe73bb73fea5c528e8c75ed7e28fdfb5bde4) names the same moby->state switch member ELEVATOR_STATE_MOVE_TO_TOP = 2 in elevator_update. Its movement branch selects elevator_vars->top when moby->state == 2, advances moby->pos.z toward that target, and transitions to the top exit state on arrival. That updater passes this same moby into compute_elevator_camera_pose for blending and travel. Thus the listed lower-bound literal belongs to the elevator state domain and reuses its established value-2 member, not any Hero state/gravity/vehicle constant or the separate moby->command domain. --- src/overlays/l13/mobys/elevator.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/elevator.c b/src/overlays/l13/mobys/elevator.c index 26bd3148ff..b7c1850c88 100644 --- a/src/overlays/l13/mobys/elevator.c +++ b/src/overlays/l13/mobys/elevator.c @@ -234,11 +234,14 @@ void compute_elevator_camera_pose(struct Moby *moby, float *camera_position, float *camera_rotation) { + enum { + ELEVATOR_STATE_MOVE_TO_TOP = 2 + }; float camera_offset_azimuth = moby->rot.z; float horizontal_offset_radius = 2.5f; float z = 1.5f; unsigned char *x; - if ((moby->command >= 2 && (moby->command & 1)) || (moby->state >= 2 && (moby->state & 1))) { + if ((moby->command >= 2 && (moby->command & 1)) || (moby->state >= ELEVATOR_STATE_MOVE_TO_TOP && (moby->state & 1))) { camera_offset_azimuth = fast_subtract_rotations(camera_offset_azimuth, 1.5707964f); } else { camera_offset_azimuth = fast_add_rotations(camera_offset_azimuth, 1.5707964f); From 734b0be9596a4a5db0ec1b99848080c74ba7cb88 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:48:34 +0000 Subject: [PATCH 0560/1502] decomp: clarify names in spawn_rocket_explosion domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: In the authoritative exact rocket.c snapshot, the selector is hero.vehicle_mode, a separate vehicle-mode field, rather than hero.state.current or a gravity selector. Original retail Ghidra reads cRam001413f4 == '\x02'. Retail 0x002d5708 forms 0x00140000, 0x002d5710 loads the byte at 0x001413f4, and 0x002d570c/0x002d5714 compares it against 2, skipping the additional call at 0x002d5740 unless equal after the nonzero hit_radius gate at 0x002d56f8-0x002d5700. This source/retail data flow establishes the HeroVehicleMode domain. The supplied include/rnc/hero/hero_state.h HeroVehicleMode declaration (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d) provides the canonical member HERO_VEHICLE_MODE_GIANT_CLANK = 2 for this exact selector domain. --- src/overlays/l18/mobys/rocket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l18/mobys/rocket.c b/src/overlays/l18/mobys/rocket.c index 15cbf2e654..7e5cda4f10 100644 --- a/src/overlays/l18/mobys/rocket.c +++ b/src/overlays/l18/mobys/rocket.c @@ -291,7 +291,7 @@ void spawn_rocket_explosion(void *moby_object, void *movement_step) { -1, 0); if (hit_radius != 0.0f) { - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { play_entity_sound( (int)moby, 2.0f, moby + 0x10, 2, rocket_explosion_hit_priority_gp, 1.0f, 0, 1, 0); } From 89da1e01985564518f75cd2ee667348300184e93 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:50:20 +0000 Subject: [PATCH 0561/1502] decomp: clarify names in initialize_menu_stream_buffers domain_0_value_0 -> MENU_STREAM_MODE_SINGLE_PRIMARY_BUFFER: The source snapshot src/ui/menus/stream_buffers/initialize_menu_stream_buffers.c (SHA-256 a7ce26a2e9e121574fce04872b924ef023ceef7323d8e9c239b24dd9e0bcb19d) compares mode with zero. Retail 0x00225acc branches on nonzero a0; the zero path at 0x00225ad4-0x00225ae0 sets primary count to 1 and secondary/large counts to 0. The primary loop at 0x00225b18-0x00225b30 writes the address loaded from menu_system +0x108 with flags zero. Secondary and large loops are skipped; 0x00225bf0-0x00225c08 clears the remaining four of five descriptors. Original Ghidra decompilation independently shows uVar5=1, iVar9=0 and uVar8=uVar5+(mode!=0), proving this is the single-primary-buffer mode. Supplied callers initialize_menu_preview_scene and reset_menu_graphics_buffers pass 1, consistent with the alternative five-descriptor layout; no higher-level purpose is inferred. --- src/ui/menus/stream_buffers/initialize_menu_stream_buffers.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/menus/stream_buffers/initialize_menu_stream_buffers.c b/src/ui/menus/stream_buffers/initialize_menu_stream_buffers.c index 8576cbc331..9c1dd584b8 100644 --- a/src/ui/menus/stream_buffers/initialize_menu_stream_buffers.c +++ b/src/ui/menus/stream_buffers/initialize_menu_stream_buffers.c @@ -10,6 +10,9 @@ void initialize_menu_stream_buffers(s32 mode) __asm__("FUN_00225ac0"); * the first two groups and 0x4F000 for the final group. The flag word * is one only for the final group. */ void initialize_menu_stream_buffers(s32 mode) { + enum { + MENU_STREAM_MODE_SINGLE_PRIMARY_BUFFER = 0 + }; s32 secondary_address; s32 primary_address; s32 primary_count; @@ -22,7 +25,7 @@ void initialize_menu_stream_buffers(s32 mode) { primary_address = menu_system.help_text_buffer; secondary_address = menu_system.unk10C; - if (mode == 0) { + if (mode == MENU_STREAM_MODE_SINGLE_PRIMARY_BUFFER) { primary_count = 1; secondary_count = 0; large_count = 0; From 965e160172e8010019a0aab34f13620eb4981ba4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:50:20 +0000 Subject: [PATCH 0562/1502] decomp: clarify names in collect_moby_and_clear_path_keys domain_0_value_1 -> PICKUP_MOBY_AVAILABLE: Retail 0x002d5844 loads the incoming moby's state at +0x20; 0x002d5848 returns unless it equals 1. The established collect_moby_and_clear_path_keys function then records its save_id in killed tables (0x002d5850-0x002d58c8). Supplied horny_toad_update calls it only for the nearby class-0x33E pickup target and clears pickup_moby afterward. This proves state 1 is the pickup's available-for-collection state, separate from Hero and toad states. domain_1_value_2 -> PICKUP_MOBY_COLLECTED: After accepting the pickup in state 1 and recording spawn persistence, retail 0x002d58d0 loads 2 and 0x002d58e4 stores it to the same moby's state +0x20. Adjacent instructions set command 1 and green glow (0x002d58dc, 0x002d58ec), call collection audio, and clear its matching path keys at 0x002d5930-0x002d594c. The established collection function and pickup caller establish state 2 as the collected state of this pickup, not a Hero enum member. --- src/overlays/shared/enemies/horny_toad.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/horny_toad.c b/src/overlays/shared/enemies/horny_toad.c index 495b5e3342..d791ca5faa 100644 --- a/src/overlays/shared/enemies/horny_toad.c +++ b/src/overlays/shared/enemies/horny_toad.c @@ -667,9 +667,13 @@ s32 get_moby_private_data_d0_address(T6 *moby) { void collect_moby_and_clear_path_keys(struct Moby *moby) __asm__("FUN_L00_002d5830"); void collect_moby_and_clear_path_keys(struct Moby *moby) { + enum { + PICKUP_MOBY_AVAILABLE = 1, + PICKUP_MOBY_COLLECTED = 2 + }; KeyVars *key_vars = (KeyVars *)moby->pvars; s32 i; - if (moby->state != 1) { + if (moby->state != PICKUP_MOBY_AVAILABLE) { return; } D_L00_001BA5D0.killed[(s16)moby->save_id] = moby->mission + 2; @@ -677,7 +681,7 @@ void collect_moby_and_clear_path_keys(struct Moby *moby) { D_0014C050[current_level_index][moby->mission] == 0xFF)) { D_L00_001BB230.killed[(s16)moby->save_id] = moby->mission + 2; } - moby->state = 2; + moby->state = PICKUP_MOBY_COLLECTED; moby->command = 1; moby->glow_color = 0x80208020; allocate_voice_for_target_entry(0, 0, moby); From e106cab5850ddab6b04f02e549e5dba8db8f402e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:50:20 +0000 Subject: [PATCH 0563/1502] decomp: clarify names in update_hero_tilt domain_0_value_1 -> HERO_TILT_APPLY_REFERENCE_ORIENTATION: Retail 0x002165c4 loads 1 into v1; 0x002165dc loads hero+0x20B3 into a0 and 0x002165e0-0x002165e4 conditionally replaces a0 when hero+0x1F8 is nonzero. This is the same effective_tilt_mode switched by the existing local HERO_TILT_* enum, whose member HERO_TILT_APPLY_REFERENCE_ORIENTATION is 1. Retail 0x002166dc-0x002166ec routes that effective value to apply_hero_reference_tilt. Reuse this branch-action member, without equating the forced value with the stored gravity selector. domain_1_value_119 -> HERO_STATE_FATAL_FALL: Authoritative C loads current_hero_state from hero_state->state.current. Retail 0x002165bc/0x002165cc constructs hero base 0x0013F350 and 0x002165f0 loads current state from +0x2084 into a0. Retail 0x00216620/0x00216624 compares that same a0 with 0x77 and exits before tilt smoothing. This is HeroStateId, distinct from control_mode loaded at +0x208C into v1. Supplied include/rnc/hero/hero_state.h HeroStateId defines canonical HERO_STATE_FATAL_FALL=119; reuse it in this current-state comparison. domain_2_value_49 -> HERO_STATE_VOICE_SLOT_CLEANUP_IDLE_EXIT: Retail 0x002165f0 loads hero+0x2084 into a0, corresponding to authoritative hero_state->state.current and current_hero_state. The load remains live through 0x00216628/0x0021662c, where comparison with 0x31 exits before zero-target rotation smoothing. The separate control selector is loaded from +0x208C into v1 at 0x00216604. Thus this comparison belongs to shared HeroStateId, whose supplied canonical member HERO_STATE_VOICE_SLOT_CLEANUP_IDLE_EXIT=49 names this state. domain_3_value_45 -> HERO_STATE_ITEM_RELEASE_FALL: Authoritative current_hero_state is assigned hero_state->state.current; retail 0x002165f0 reads this field at hero+0x2084 into a0. Retail 0x00216630/0x00216634 compares the unchanged current-state a0 against 0x2D and returns before calls 0x00216698/0x002166cc. It does not compare the +0x208C control selector in v1. This proves the shared HeroStateId domain; supplied header enum defines its canonical HERO_STATE_ITEM_RELEASE_FALL=45, which this exclusion should reuse. domain_4_value_44 -> HERO_STATE_GRAPPLE_SWING_ENTRY: Retail 0x002165f0 loads a0 from hero+0x2084, matching authoritative hero_state->state.current. Retail 0x00216638/0x0021663c compares this current-state value against 0x2C and exits without return-to-zero spring updates. Control_mode is separately loaded from +0x208C into v1 at 0x00216604, proving this is the current HeroStateId domain. Supplied include/rnc/hero/hero_state.h declares canonical HERO_STATE_GRAPPLE_SWING_ENTRY=44 in HeroStateId; reuse that established state member. --- src/overlays/shared/hero/hero_move_state_velocity.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/hero/hero_move_state_velocity.c b/src/overlays/shared/hero/hero_move_state_velocity.c index b6391004cd..10fb3e280a 100644 --- a/src/overlays/shared/hero/hero_move_state_velocity.c +++ b/src/overlays/shared/hero/hero_move_state_velocity.c @@ -653,7 +653,7 @@ void update_hero_tilt(void) { int effective_tilt_mode, current_hero_state, k; effective_tilt_mode = hero_state->gravity_mode; if (hero_state->unk1F8) { - effective_tilt_mode = 1; + effective_tilt_mode = HERO_TILT_APPLY_REFERENCE_ORIENTATION; } switch (effective_tilt_mode) { case HERO_TILT_RETURN_TO_ZERO: @@ -665,8 +665,8 @@ void update_hero_tilt(void) { if (k == 0x11 || k == 0x15 || k == 0x16) { return; } - if (current_hero_state == 0x77 || current_hero_state == 0x31 || - current_hero_state == 0x2D || current_hero_state == 0x2C) { + if (current_hero_state == HERO_STATE_FATAL_FALL || current_hero_state == HERO_STATE_VOICE_SLOT_CLEANUP_IDLE_EXIT || + current_hero_state == HERO_STATE_ITEM_RELEASE_FALL || current_hero_state == HERO_STATE_GRAPPLE_SWING_ENTRY) { return; } tilt_targets[0] = 0.0f; From 7b2f042841d580cf3b2a078980c023dae6cba4a8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:50:20 +0000 Subject: [PATCH 0564/1502] decomp: clarify names in process_machinegun_turret_hit_reactions domain_0_value_6 -> TURRET_STATE_DESTROY: Retail 0x002b43d4 loads the same moby's state byte at +0x20 and 0x002b43d8-0x002b43dc compares it with 6 to skip further damage processing. Authoritative machinegun_turret_update calls this handler before switching on MOBY(moby)->state, where its existing TURRET_STATE_DESTROY=6 branch spawns an explosion and marks that turret for removal. Thus this is the turret destruction-state guard, not a hit_reaction result or HeroStateId. domain_1_value_6 -> TURRET_STATE_DESTROY: Original retail Ghidra maps lethal/destroy hit results 1/2 to 0x002b4440; 0x002b4444 loads 6 and 0x002b444c stores it to the same moby's state byte at +0x20, then clears flag 0x1000 and calls the kill bookkeeping helper. The authoritative caller machinegun_turret_update invokes this handler before dispatching that exact state field, and its established TURRET_STATE_DESTROY=6 branch spawns an explosion and removes the turret. Reuse the turret-state name for this assignment. --- src/overlays/l14/mobys/machinegun_turret.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l14/mobys/machinegun_turret.c b/src/overlays/l14/mobys/machinegun_turret.c index db377ad20e..ee879ac668 100644 --- a/src/overlays/l14/mobys/machinegun_turret.c +++ b/src/overlays/l14/mobys/machinegun_turret.c @@ -510,7 +510,7 @@ void process_machinegun_turret_hit_reactions(struct Moby *moby) { HIT_REACTION_ANIMATE_WITH_LOW_RED_FLASH = 9, HIT_REACTION_LOW_RED_FLASH_AND_HIT_ANIMATION = 10, HIT_REACTION_NONE = 11 - }; + } ; enum { TURRET_STATE_DESTROY = 6}; MachinegunTurretVars *moby_vars = (MachinegunTurretVars *)moby->pvars; int loc0; float damage_amount = 0.0f; @@ -526,7 +526,7 @@ void process_machinegun_turret_hit_reactions(struct Moby *moby) { } } k = hit_reaction(moby, hit_record, &moby_vars->health, 0, &loc0, &damage_amount, 0, 4); - if (loc0 != 1 && moby->state != 6) { + if (loc0 != 1 && moby->state != TURRET_STATE_DESTROY) { remaining_health = moby_vars->health - damage_amount; moby_vars->health = remaining_health; if (remaining_health <= 0.0f) @@ -549,7 +549,7 @@ void process_machinegun_turret_hit_reactions(struct Moby *moby) { break; case HIT_REACTION_LETHAL: case HIT_REACTION_DESTROY: - moby->state = 6; + moby->state = TURRET_STATE_DESTROY; moby->flags &= 0xEFFF; moby_vars->unk67 = 0xF0; FUN_L00_00257470(moby, 0, -1); From 89fdeaca3017b398aa59847d632d64bf78f20677 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:50:21 +0000 Subject: [PATCH 0565/1502] decomp: clarify names in process_blarg_heavy_interceptor_hit_reactions domain_1_value_7 -> INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL: Retail 0x002ad91c-0x002ad924 reads unsigned moby byte +0x20 and excludes values >=7. The same moby is processed before the caller update_blarg_heavy_interceptor switches on moby->state. Its established INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL=7 initializes the fatal launch/timer then advances to death-fall state 9. Thus this threshold is that interceptor state boundary, not reaction result 7 or hero state 7. domain_2_value_1 -> INTERCEPTOR_STATE_PATROL_AND_SCAN: Retail 0x002ad948-0x002ad958 tests byte +0x20 of the original moby against 1 before writing state 2. Authoritative caller update_blarg_heavy_interceptor invokes this handler on the same moby before its state switch, whose established INTERCEPTOR_STATE_PATROL_AND_SCAN=1 updates patrol aim/path and scans for a target. This is the same interceptor current-state field. domain_3_value_2 -> INTERCEPTOR_STATE_ALERT_GROUP: Retail 0x002ad954-0x002ad958 writes 2 to moby+0x20 when the previous state is patrol 1. The authoritative caller invokes this hit handler before switching on that same moby->state; established INTERCEPTOR_STATE_ALERT_GROUP=2 releases the patrol voice, calls activate_waiting_turrets_in_group, and advances to target tracking. This assignment enters that group-alert state. domain_5_value_7 -> INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL: Original retail Ghidra groups reaction results 1 and 2 at the death branch. Retail 0x002ad9c0-0x002ad9c4 writes 7 to moby+0x20, then clears flag 0x1000 and calls cleanup. The authoritative update_blarg_heavy_interceptor caller switches on the same moby->state immediately after this handler, and established INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL=7 initializes fatal launch motion and timer before advancing to state 9. --- src/overlays/l14/mobys/blarg_heavy_interceptor.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l14/mobys/blarg_heavy_interceptor.c b/src/overlays/l14/mobys/blarg_heavy_interceptor.c index 10a684f610..6c958fee42 100644 --- a/src/overlays/l14/mobys/blarg_heavy_interceptor.c +++ b/src/overlays/l14/mobys/blarg_heavy_interceptor.c @@ -788,7 +788,7 @@ void process_blarg_heavy_interceptor_hit_reactions(struct Moby *moby) { HIT_REACTION_ANIMATE_WITH_LOW_RED_FLASH = 9, HIT_REACTION_LOW_RED_FLASH_AND_HIT_ANIMATION = 10, HIT_REACTION_NONE = 11 - }; + } ; enum { INTERCEPTOR_STATE_PATROL_AND_SCAN = 1 , INTERCEPTOR_STATE_ALERT_GROUP = 2 , INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL = 7}; BlargHeavyInterceptorVars *blarg_heavy_interceptor_vars = (BlargHeavyInterceptorVars *)moby->pvars; int hit_reaction_status; @@ -803,13 +803,13 @@ void process_blarg_heavy_interceptor_hit_reactions(struct Moby *moby) { &damage_amount, 0, 4); - if (hit_reaction_status != 1 && moby->state < 7) { + if (hit_reaction_status != 1 && moby->state < INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL) { float remaining_health = blarg_heavy_interceptor_vars->health - damage_amount; blarg_heavy_interceptor_vars->health = remaining_health; if (remaining_health <= 0.0f) hit_reaction_result = 1; - if (moby->state == 1) - moby->state = 2; + if (moby->state == INTERCEPTOR_STATE_PATROL_AND_SCAN) + moby->state = INTERCEPTOR_STATE_ALERT_GROUP; if (hit_reaction_status == 3) moby->command = 1; switch (hit_reaction_result) { @@ -829,7 +829,7 @@ void process_blarg_heavy_interceptor_hit_reactions(struct Moby *moby) { break; case HIT_REACTION_LETHAL: case HIT_REACTION_DEATH_FALL: - moby->state = 7; + moby->state = INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL; moby->flags &= 0xEFFF; FUN_L00_00257470(moby, 0, -1); break; From 3f3850cbe2f3120c6d4daabb450cf85628717ee0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:52:09 +0000 Subject: [PATCH 0566/1502] decomp: clarify names in update_moby_scene_visibility_and_height_reflection domain_0_value_1 -> MOBY_WAIT_FOR_SCENE_TRIGGER: Source SHA-256 de74c3fb0d7afc969c1671d92925df19ba5eb4d0db8fd9b538cdad2e77a855ea assigns moby->state = 1 in MOBY_INITIALIZE. Retail 002f7aec loads 1 into a0 and 002f7b24 stores it at s0+0x20, the same byte loaded at 002f7af0 and dispatched as state 1 at 002f7af4 to 002f7b28. Initialization falls through to that branch, proving reuse of existing MOBY_WAIT_FOR_SCENE_TRIGGER rather than a distinct numeric domain. domain_1_value_2 -> MOBY_WAIT_FOR_SCENE_END: The source trigger branch writes moby->state = 2. Retail 002f7b84 loads 2 and 002f7b88 stores it at s0+0x20; 002f7b90 clears substate and 002f7b98 sets flags bit 0. The identical state byte is dispatched for value 2 at 002f7b14 to 002f7b9c, corresponding to the existing MOBY_WAIT_FOR_SCENE_END case, which retains this state until scene mode exits. This proves the assignment uses that local enum domain. domain_2_value_1 -> MOBY_WAIT_FOR_SCENE_TRIGGER: In source MOBY_WAIT_FOR_SCENE_END, scene-mode exit writes moby->state = 1. Retail 002f7c0c skips the exit while mode equals 2; otherwise 002f7c10 loads 1 and 002f7c18 stores it at s0+0x20, followed by substate 1 and flags bit 0 clearing. This is the same state byte tested at 002f7af0-002f7af4, where 1 selects the existing MOBY_WAIT_FOR_SCENE_TRIGGER branch. The assignment therefore restores that canonical local enum member. --- src/overlays/l18/mobys/deplanetizer_gun.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l18/mobys/deplanetizer_gun.c b/src/overlays/l18/mobys/deplanetizer_gun.c index aa07498766..0568ea232b 100644 --- a/src/overlays/l18/mobys/deplanetizer_gun.c +++ b/src/overlays/l18/mobys/deplanetizer_gun.c @@ -37,11 +37,11 @@ void deplanetizer_gun_update(DeplanetizerGunSceneMoby *moby) { }; switch (moby->state) { case MOBY_INITIALIZE: - moby->state = 1; + moby->state = MOBY_WAIT_FOR_SCENE_TRIGGER; case MOBY_WAIT_FOR_SCENE_TRIGGER: if ((D_L18_0015F5C4 == 2 && D_L18_0016D290_lui == 3) || (game_frame < 5 && D_L18_001623A0_gp != 0 && moby->f40 == 0.0f)) { - moby->state = 2; + moby->state = MOBY_WAIT_FOR_SCENE_END; moby->flags |= 1; moby->substate = 0; } @@ -55,7 +55,7 @@ void deplanetizer_gun_update(DeplanetizerGunSceneMoby *moby) { } if (D_L18_0015F5C4 != 2) { moby->substate = 1; - moby->state = 1; + moby->state = MOBY_WAIT_FOR_SCENE_TRIGGER; moby->flags &= 0xFFFE; } break; From 00cbd1501399be1fd6c4680a606e499687fed056 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:52:09 +0000 Subject: [PATCH 0567/1502] decomp: clarify names in music_stop domain_0_value_0 -> MUSIC_CROSSFADE_IDLE: The authoritative source assigns 0 to music_stream_state.crossfade_state only after snd_stop_all_streams(), draining snd_flush_sound_commands() to zero, and snd_stream_safe_check_cd_idle(1). Retail 0x00215fc4 calls stop-all, 0x00215fd0-0x00215fe4 drains commands, and 0x00216040 stores zero to state+0x20 while clearing all three stream handles and both pending track requests. Original Ghidra likewise clears g_nDialogueCrossfadePhase in this shutdown reset. Thus this selector's zero denotes idle crossfading after music stops, independently of unrelated zero-valued flags. --- src/audio/music/music_stop.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/music/music_stop.c b/src/audio/music/music_stop.c index 9235a63927..5a104e3ebf 100644 --- a/src/audio/music/music_stop.c +++ b/src/audio/music/music_stop.c @@ -8,6 +8,9 @@ extern s32 snd_stream_safe_check_cd_idle() __asm__("func_0012ED30"); void music_stop(void) __asm__("FUN_00215ee8"); void music_stop(void) { + enum { + MUSIC_CROSSFADE_IDLE = 0 + }; s32 requested_track; if (music_stream_state.primary.handle == 0xFFFFFFFF) { @@ -42,7 +45,7 @@ void music_stop(void) { music_stream_state.transition.state = 0; music_stream_state.transition.flags = 0; music_stream_state.transition.handle = 0; - music_stream_state.crossfade_state = 0; + music_stream_state.crossfade_state = MUSIC_CROSSFADE_IDLE; music_stream_state.requested_track = -1; music_stream_state.requested_transition_track = -1; } From fb33505560bcac568fe175f545e68c793fc5496d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:52:09 +0000 Subject: [PATCH 0568/1502] decomp: clarify names in select_drek_boss_next_action domain_0_value_13 -> DREK_BOSS_LAUNCH_FORWARD_WITH_LATERAL_OFFSET: The SHA-bound source ecbe c8c6 (full SHA ecbec8c651eb3fb97e2fd64da85b0a528a9c7a0f3dd8f2cc42836dee38319f00) and original retail Ghidra identify state as the returned boss action in s1 (return 0x002f71fc), compared to boss pvars+0x350 at 0x002f7150..0x002f7174. The authoritative drek_final_boss_robot_update dispatches that return and records completed actions at f350; this proves the Drek boss action domain, separate from random choice indices and HeroStateId. Retail 0x002f7118/0x002f711c maps choice 0 to 13. Caller enters boss state 13, adds forward basis fC0 to lateral basis fD0 scaled by randomized f3BC, normalizes the emission direction and passes it to spawn_drek_boss_ring_projectile; completion saves 13 at f350. domain_1_value_14 -> DREK_BOSS_ACTION_REPOSITION_AND_AIM: The SHA-bound source ecbe c8c6 (full SHA ecbec8c651eb3fb97e2fd64da85b0a528a9c7a0f3dd8f2cc42836dee38319f00) and original retail Ghidra identify state as the returned boss action in s1 (return 0x002f71fc), compared to boss pvars+0x350 at 0x002f7150..0x002f7174. The authoritative drek_final_boss_robot_update dispatches that return and records completed actions at f350; this proves the Drek boss action domain, separate from random choice indices and HeroStateId. Retail 0x002f7120/0x002f7124 maps choice 1 to returned action 14. Caller case DREK_BOSS_ACTION_REPOSITION_AND_AIM first enters approach-node state 18 and chooses f3A8; reaching it enters 14, captures target f320 and aims at it. Completion explicitly saves 14 at f350, proving this action code despite the staged entry. domain_2_value_15 -> DREK_BOSS_TARGET_GROUND_POINTS: The SHA-bound source ecbe c8c6 (full SHA ecbec8c651eb3fb97e2fd64da85b0a528a9c7a0f3dd8f2cc42836dee38319f00) and original retail Ghidra identify state as the returned boss action in s1 (return 0x002f71fc), compared to boss pvars+0x350 at 0x002f7150..0x002f7174. The authoritative drek_final_boss_robot_update dispatches that return and records completed actions at f350; this proves the Drek boss action domain, separate from random choice indices and HeroStateId. Retail 0x002f7128/0x002f712c maps choice 2 to 15. Caller dispatch enters state 15; its named handler selects target positions with optional XY offsets, probes ground height and launches toward the point, then saves 15 at f350. domain_3_value_16 -> DREK_BOSS_TARGET_RANDOM_ARENA_POINTS: The SHA-bound source ecbe c8c6 (full SHA ecbec8c651eb3fb97e2fd64da85b0a528a9c7a0f3dd8f2cc42836dee38319f00) and original retail Ghidra identify state as the returned boss action in s1 (return 0x002f71fc), compared to boss pvars+0x350 at 0x002f7150..0x002f7174. The authoritative drek_final_boss_robot_update dispatches that return and records completed actions at f350; this proves the Drek boss action domain, separate from random choice indices and HeroStateId. Retail 0x002f7130/0x002f7134 maps choice 3 to 16. Caller default enters state 16; its named handler chooses random angle and radius 3..29 around the arena node, probes ground height and launches toward that point, then saves 16 at f350. domain_4_value_17 -> DREK_BOSS_TARGET_SIDE_GROUND_POINTS: The SHA-bound source ecbe c8c6 (full SHA ecbec8c651eb3fb97e2fd64da85b0a528a9c7a0f3dd8f2cc42836dee38319f00) and original retail Ghidra identify state as the returned boss action in s1 (return 0x002f71fc), compared to boss pvars+0x350 at 0x002f7150..0x002f7174. The authoritative drek_final_boss_robot_update dispatches that return and records completed actions at f350; this proves the Drek boss action domain, separate from random choice indices and HeroStateId. Retail 0x002f7138/0x002f713c maps choice 4 to 17. Caller dispatch enters state 17; its named handler scales lateral basis fD0 by +4.3 or -4.3, adds boss position, probes ground height and launches at these side points, saving 17 at f350. domain_5_value_19 -> DREK_BOSS_FOLLOW_HERO: The SHA-bound source ecbe c8c6 (full SHA ecbec8c651eb3fb97e2fd64da85b0a528a9c7a0f3dd8f2cc42836dee38319f00) and original retail Ghidra identify state as the returned boss action in s1 (return 0x002f71fc), compared to boss pvars+0x350 at 0x002f7150..0x002f7174. The authoritative drek_final_boss_robot_update dispatches that return and records completed actions at f350; this proves the Drek boss action domain, separate from random choice indices and HeroStateId. Retail 0x002f7140 maps choice 5 to 19. Caller DREK_BOSS_FOLLOW_HERO enters state 19, whose handler invokes update_drek_boss_hero_follow_movement and records completed action 19 at f350. The helper derives its destination and speed from hero position and movement. domain_6_value_19 -> DREK_BOSS_FOLLOW_HERO: The SHA-bound source ecbe c8c6 (full SHA ecbec8c651eb3fb97e2fd64da85b0a528a9c7a0f3dd8f2cc42836dee38319f00) and original retail Ghidra identify state as the returned boss action in s1 (return 0x002f71fc), compared to boss pvars+0x350 at 0x002f7150..0x002f7174. The authoritative drek_final_boss_robot_update dispatches that return and records completed actions at f350; this proves the Drek boss action domain, separate from random choice indices and HeroStateId. Retail 0x002f7160..0x002f7178 compares the same candidate s1 against 19 and gates it using pvars+0x364; 0x002f7184..0x002f71cc also rejects it beyond the follow radius plus 2. This is the same returned follow action assigned at 0x002f7140 and dispatched by caller DREK_BOSS_FOLLOW_HERO. domain_7_value_17 -> DREK_BOSS_TARGET_SIDE_GROUND_POINTS: The SHA-bound source ecbe c8c6 (full SHA ecbec8c651eb3fb97e2fd64da85b0a528a9c7a0f3dd8f2cc42836dee38319f00) and original retail Ghidra identify state as the returned boss action in s1 (return 0x002f71fc), compared to boss pvars+0x350 at 0x002f7150..0x002f7174. The authoritative drek_final_boss_robot_update dispatches that return and records completed actions at f350; this proves the Drek boss action domain, separate from random choice indices and HeroStateId. Retail 0x002f71d0..0x002f71e4 compares candidate s1 against 17 and rejects it when the completed action at pvars+0x350 is 14. It is the same side-ground-points candidate assigned at 0x002f713c and dispatched by caller DREK_BOSS_TARGET_SIDE_GROUND_POINTS; this comparison must reuse that canonical member. --- src/overlays/l18/mobys/drek_final_boss_robot.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l18/mobys/drek_final_boss_robot.c b/src/overlays/l18/mobys/drek_final_boss_robot.c index fd27142eb4..273e7fadbd 100644 --- a/src/overlays/l18/mobys/drek_final_boss_robot.c +++ b/src/overlays/l18/mobys/drek_final_boss_robot.c @@ -2392,29 +2392,29 @@ int select_drek_boss_next_action(struct Moby *moby) { boss_action_choice_index = random_integer_below(6); switch (boss_action_choice_index) { case BOSS_ACTION_CHOICE_LAUNCH_FORWARD_WITH_LATERAL_OFFSET: - state = 0xD; + state = DREK_BOSS_LAUNCH_FORWARD_WITH_LATERAL_OFFSET; break; case BOSS_ACTION_CHOICE_REPOSITION_AND_AIM: - state = 0xE; + state = DREK_BOSS_ACTION_REPOSITION_AND_AIM; break; case BOSS_ACTION_CHOICE_TARGET_GROUND_POINTS: - state = 0xF; + state = DREK_BOSS_TARGET_GROUND_POINTS; break; case BOSS_ACTION_CHOICE_TARGET_RANDOM_ARENA_POINTS: - state = 0x10; + state = DREK_BOSS_TARGET_RANDOM_ARENA_POINTS; break; case BOSS_ACTION_CHOICE_TARGET_SIDE_GROUND_POINTS: - state = 0x11; + state = DREK_BOSS_TARGET_SIDE_GROUND_POINTS; break; case BOSS_ACTION_CHOICE_FOLLOW_HERO: - state = 0x13; + state = DREK_BOSS_FOLLOW_HERO; break; } ok = *(short *)((char *)drek_boss_action_eligibility_by_phase + boss_action_choice_index * 2 + *(int *)(boss_action_vars + 0x34C) * 12); if (state == *(int *)(boss_action_vars + 0x350)) ok = 0; - if (state == 0x13) { + if (state == DREK_BOSS_FOLLOW_HERO) { if (*(int *)(boss_action_vars + 0x364) != 0) { ok = 0; } else { @@ -2425,7 +2425,7 @@ int select_drek_boss_next_action(struct Moby *moby) { ok = 0; } } - if (state == 0x11) { + if (state == DREK_BOSS_TARGET_SIDE_GROUND_POINTS) { if (*(int *)(boss_action_vars + 0x350) == 0xE) ok = 0; } From 231d2f89208aa28ade8bba138d24976238c7b50a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:54:08 +0000 Subject: [PATCH 0569/1502] decomp: clarify names in beehive_update domain_0_value_1 -> BEEHIVE_TRY_SPAWN_CLONE: Retail 0x003021c4 retains beehive_moby in s2; 0x003021d8 reads its state byte at +0x20. The zero-state branch loads 1 at 0x003021f8 and stores it to that same byte at 0x00302200. On subsequent calls 0x003021e4-0x003021e8 tests that same byte against 1 and enters the source-group/count gated cloning branch at 0x00302204. The bound C already names this exact selector's case 1 BEEHIVE_TRY_SPAWN_CLONE, so its initialization assignment must reuse that member rather than an unrelated equal-valued Hero constant. --- src/overlays/l01/mobys/beehive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/beehive.c b/src/overlays/l01/mobys/beehive.c index af18f33ee3..a2e9907c56 100644 --- a/src/overlays/l01/mobys/beehive.c +++ b/src/overlays/l01/mobys/beehive.c @@ -104,7 +104,7 @@ void beehive_update(SpawnerMoby *beehive_moby) { switch (beehive_moby->state) { case BEEHIVE_INITIALIZE: - beehive_moby->state = 1; + beehive_moby->state = BEEHIVE_TRY_SPAWN_CLONE; break; case BEEHIVE_TRY_SPAWN_CLONE: if (beehive_vars->src_id < 0) { From e95ffaf7d643c9f4509857fc6a5cd4160ff814b9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:54:09 +0000 Subject: [PATCH 0570/1502] decomp: clarify names in tresspasser_door1_update domain_0_value_1 -> TRESSPASSER_DOOR1_WAIT_FOR_LINKED_MOBY: Retail 0x002dffe4 loads this moby's state byte from 0x20(s2), and 0x002dffe8 dispatches value 1 to 0x002e0030. After capturing pos into pvars at 0x002e001c-0x002e0024, 0x002e002c stores 1 into that same state byte. Its destination branch waits for the pvars+0x10 indexed linked moby to reach state 4, exactly the existing local enum member TRESSPASSER_DOOR1_WAIT_FOR_LINKED_MOBY. domain_1_value_2 -> TRESSPASSER_DOOR1_SLIDE_TO_OFFSET_POSITION: Retail 0x002e006c-0x002e0074 stores 2 into this moby's 0x20 state byte after the linked-moby condition succeeds. The same state loaded at 0x002dffe4 dispatches value 2 via 0x002e000c to 0x002e008c, which constructs captured position plus length-2 rot_row1 offset and advances pos by capped displacement. This proves reuse of the existing same-selector enum member TRESSPASSER_DOOR1_SLIDE_TO_OFFSET_POSITION. domain_2_value_3 -> TRESSPASSER_DOOR1_SLIDE_COMPLETE: Within the proven moby->state domain, retail 0x002e00b4-0x002e00e8 computes destination minus position, caps the movement step and adds it to position. At 0x002e00ec-0x002e0104 its length is compared to zero; only on zero does 0x002e0118-0x002e011c store 3 into the same 0x20(s2) state byte. State 3 has no further update branch in this function, proving completion of the slide without assuming open/closed gameplay semantics. --- src/overlays/l02/mobys/tresspasser_door1.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/l02/mobys/tresspasser_door1.c b/src/overlays/l02/mobys/tresspasser_door1.c index 61c3a2fdf0..f615e24613 100644 --- a/src/overlays/l02/mobys/tresspasser_door1.c +++ b/src/overlays/l02/mobys/tresspasser_door1.c @@ -27,13 +27,16 @@ void tresspasser_door1_update(struct Moby *moby) { TRESSPASSER_DOOR1_WAIT_FOR_LINKED_MOBY = 1, TRESSPASSER_DOOR1_SLIDE_TO_OFFSET_POSITION = 2 }; + enum { + TRESSPASSER_DOOR1_SLIDE_COMPLETE = 3 + }; char *door_vars = (char *)moby->pvars; float destination_position[4]; float movement_step[4]; switch (moby->state) { case TRESSPASSER_DOOR1_CAPTURE_START_POSITION: qcopy(door_vars, &moby->pos); - moby->state = 1; + moby->state = TRESSPASSER_DOOR1_WAIT_FOR_LINKED_MOBY; break; case TRESSPASSER_DOOR1_WAIT_FOR_LINKED_MOBY: if (*(int *)(door_vars + 0x10) >= 0) { @@ -42,7 +45,7 @@ void tresspasser_door1_update(struct Moby *moby) { short c = *(short *)(o + 0xA6); if (c == 0x267 || c == 0x23F) { if (o[0x20] == 4) { - moby->state = 2; + moby->state = TRESSPASSER_DOOR1_SLIDE_TO_OFFSET_POSITION; FUN_0022da68(0, 0, (int)moby); } } @@ -56,7 +59,7 @@ void tresspasser_door1_update(struct Moby *moby) { fast_vec_add(&moby->pos, &moby->pos, movement_step); if (fast_vec_length(movement_step) == 0.0f) { FUN_0022da68(1, 0, (int)moby); - moby->state = 3; + moby->state = TRESSPASSER_DOOR1_SLIDE_COMPLETE; } break; } From a5c0430f6d09051b5ce9799151f1ee5a6f099772 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:54:09 +0000 Subject: [PATCH 0571/1502] decomp: clarify names in update_triggered_moby_yaw domain_0_value_1 -> MOBY_WAIT_FOR_TRIGGER: Retail 0x003166b8 loads moby state from s0+0x20 and 0x003166bc branches on 1 to the trigger test at 0x00316750. Initialization stores that same 1 to s0+0x20 at 0x003166f8/0x00316708, then falls through to test the indexed trigger byte at 0x00316764. The source already names this exact selector's case 1 MOBY_WAIT_FOR_TRIGGER, proving reuse for the assignment. domain_1_value_2 -> MOBY_APPROACH_SAVED_YAW_OFFSET: Retail 0x00316764-0x00316784 tests the indexed trigger byte, calls the voice helper, and stores 2 into the same moby state byte at s0+0x20. Dispatch 0x003166e0 sends state 2 to 0x00316788, where saved yaw at s1+0xC is offset by +/-0.6981317 and passed to approach_angle for yaw s0+0x48. The source's case 2 already uses MOBY_APPROACH_SAVED_YAW_OFFSET in this exact domain. --- src/overlays/l05/mobys/triggered_moby_yaw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l05/mobys/triggered_moby_yaw.c b/src/overlays/l05/mobys/triggered_moby_yaw.c index 11067bf087..e8e271dcbd 100644 --- a/src/overlays/l05/mobys/triggered_moby_yaw.c +++ b/src/overlays/l05/mobys/triggered_moby_yaw.c @@ -25,7 +25,7 @@ void triggered_moby_yaw_update(struct Moby *moby) { case MOBY_INITIALIZE_YAW: if (yaw_control_vars[0] != 0) moby->flags |= 0x8000; - moby->state = 1; + moby->state = MOBY_WAIT_FOR_TRIGGER; *(float *)&yaw_control_vars[3] = moby->rot.z; if (yaw_control_vars[0] != 0) moby->rot.z = fast_subtract_rotations(moby->rot.z, 1.5707964f); @@ -35,7 +35,7 @@ void triggered_moby_yaw_update(struct Moby *moby) { case MOBY_WAIT_FOR_TRIGGER: if (((unsigned char *)*(int *)&D_L05_0015FFD8)[yaw_control_vars[2] * 256 + 0xBC] != 0) { allocate_voice_for_target_entry(0, 0, moby); - moby->state = 2; + moby->state = MOBY_APPROACH_SAVED_YAW_OFFSET; } break; case MOBY_APPROACH_SAVED_YAW_OFFSET: { From 65d885d1fd54cbc77d9624a40390f1ba871e09d4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:54:09 +0000 Subject: [PATCH 0572/1502] decomp: clarify names in update_link_triggered_moby_turn domain_0_value_1 -> LINKED_TURN_STATE_WAIT_FOR_LINK: Retail 0x0030f2c4 loads this moby's state byte at s0+0x20, the same byte written with 1 at 0x0030f308 during initialization. The next update branches on 1 at 0x0030f2c8 to the linked-moby trigger poll at 0x0030f314-0x0030f32c. This is the exact domain of the existing LINKED_TURN_STATE_WAIT_FOR_LINK switch member. domain_1_value_2 -> LINKED_TURN_STATE_ROTATE_TO_TARGET: Retail 0x0030f344 loads 2 and 0x0030f350 stores it into the same s0+0x20 state byte read at 0x0030f2c4. Dispatch compares that byte with 2 at 0x0030f2ec and enters 0x0030f388, computing the saved angle plus 1.0471976 and approaching it at 0x0030f3d8. Reuse the existing local LINKED_TURN_STATE_ROTATE_TO_TARGET member. domain_2_value_3 -> LINKED_TURN_STATE_COMPLETE: The early-frame triggered path loads 3 at 0x0030f33c and writes the moby's state byte at 0x0030f374, then computes saved initial rot.z plus 1.0471976 at 0x0030f378 and stores that target directly into rot.z at 0x0030f384. Thus this assignment marks the turn complete by snapping to target. State 3 has no update branch in this function and is also reached by animated completion. domain_3_value_3 -> LINKED_TURN_STATE_COMPLETE: After approach_angle updates rot.z at s0+0x48 toward the saved angle plus 1.0471976, retail 0x0030f3e8 compares its return with zero; only equality reaches the store of 3 into s0+0x20 at 0x0030f3f8. This is the completed-turn state, shared with the early-frame path that writes the target rotation directly. Dispatch handles only 0, 1 and 2, so completed turns receive no further action here. --- src/overlays/l11/mobys/link_triggered_moby_turn.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/overlays/l11/mobys/link_triggered_moby_turn.c b/src/overlays/l11/mobys/link_triggered_moby_turn.c index 1f25bb6d1e..939c29019a 100644 --- a/src/overlays/l11/mobys/link_triggered_moby_turn.c +++ b/src/overlays/l11/mobys/link_triggered_moby_turn.c @@ -28,6 +28,9 @@ void link_triggered_moby_turn_update(struct Moby *turning_moby) { LINKED_TURN_STATE_WAIT_FOR_LINK = 1, LINKED_TURN_STATE_ROTATE_TO_TARGET = 2 }; + enum { + LINKED_TURN_STATE_COMPLETE = 3 + }; int entry_state = turning_moby->state; float *private_data = (float *)turning_moby->pvars; float target_angle; @@ -35,17 +38,17 @@ void link_triggered_moby_turn_update(struct Moby *turning_moby) { switch (entry_state) { case LINKED_TURN_STATE_INITIALIZE: turning_moby->update_dist = 0xFF; - turning_moby->state = 1; + turning_moby->state = LINKED_TURN_STATE_WAIT_FOR_LINK; private_data[2] = turning_moby->rot.z; break; case LINKED_TURN_STATE_WAIT_FOR_LINK: if (test_linked_moby_turn_trigger(D_L11_0015FFD8_t + (*(int *)private_data << 8))) { if (level_frame >= 11) { D_0013D3E3_t[0] = entry_state; - turning_moby->state = 2; + turning_moby->state = LINKED_TURN_STATE_ROTATE_TO_TARGET; allocate_voice_for_target_entry(0, 0, turning_moby); } else { - turning_moby->state = 3; + turning_moby->state = LINKED_TURN_STATE_COMPLETE; turning_moby->rot.z = fast_add_rotations(private_data[2], 1.0471976f); } } @@ -59,7 +62,7 @@ void link_triggered_moby_turn_update(struct Moby *turning_moby) { turn_acceleration_step, turn_acceleration_step, frame_time * 0.7853982f) == 0.0f) { - turning_moby->state = 3; + turning_moby->state = LINKED_TURN_STATE_COMPLETE; } break; } From 3f8ce3dd8544eed78a806c9f989e226517c26a7e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:54:09 +0000 Subject: [PATCH 0573/1502] decomp: clarify names in advance_bolt_thief_path domain_0_value_5 -> BOLT_THIEF_FOLLOW_OTHER_PATH: Authoritative source src/overlays/l16/mobys/bolt_thief.c SHA-256 323f468f4a3de448a80e80359508a88f61fbc25a04bc0770a4d5e86b7e7a42e5 defines BOLT_THIEF_FOLLOW_OTHER_PATH = 5 in bolt_thief_update and passes that same moby to advance_bolt_thief_path in that case. Assigned retail 0x002e3fd4 loads moby+0x20, 0x002e3fac/0x002e3fdc compare it with 5, and 0x002e3fe8 selects pvars+0xDC (source other_path) instead of +0xD8 before sampling at 0x002e4010. Original Ghidra shows this same state-byte test and path selection. Bounded caller evidence eec69cec26464a18929020bb637ab075 confirms the same moby is retained in s1 (0x002e37ac), state 5 is stored to +0x20 at 0x002e3cc0-0x002e3cc8 with traversal reset at 0x002e3cdc/0x002e3ce4, and the other-path branch calls the assigned helper at 0x002e3ce8 with a0=s1 in its delay slot. Nonzero completion resets that same state byte to 2 at 0x002e3cf0-0x002e3cfc. This is the current moby state domain, distinct from mode at pvars+0xFC. --- src/overlays/l16/mobys/bolt_thief.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/bolt_thief.c b/src/overlays/l16/mobys/bolt_thief.c index cf00ddae12..347e1f4443 100644 --- a/src/overlays/l16/mobys/bolt_thief.c +++ b/src/overlays/l16/mobys/bolt_thief.c @@ -345,13 +345,16 @@ extern int FUN_L00_0025d808_path54(char *, float *, float *, float *, int, float) __asm__("FUN_L00_0025d808"); int advance_bolt_thief_path(struct Moby *moby) { + enum { + BOLT_THIEF_FOLLOW_OTHER_PATH = 5 + }; float pos[4]; float delta[4]; char *bolt_thief_path_data = (char *)moby->pvars; float scaled_frame_time = bolt_thief_path_speed_gp * frame_time; int path_sample_result; char *path; - if (moby->state == 5) + if (moby->state == BOLT_THIEF_FOLLOW_OTHER_PATH) path = D_L16_001B0930[*(int *)(bolt_thief_path_data + 0xDC)]; else path = D_L16_001B0930[*(int *)(bolt_thief_path_data + 0xD8)]; From 7c8a0e7584bcd66b6451dadcd28b439804a2c2d8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:55:55 +0000 Subject: [PATCH 0574/1502] decomp: clarify names in _getpic domain_0_value_0 -> MPEG_DECODE_SCAN_NEXT_HEADER: In source SHA-256 7d60209eed6f01a590bf792df83fcc1ddaf4263687a2a42c79440ae8adcb2422, status=0 initializes the _decodeOrSkip result/control variable. Retail 0x0012bca4 clears s2; 0x0012bce4 loads -1 and 0x0012bce8 branches directly to dispatch only when s2 equals -1. Initial zero therefore falls through to _nextHeader at 0x0012bcf0. Later _decodeOrSkip returns replace s2 (retail offsets 228,264,300), confirming this is a decode-result domain distinct from the s3 picture-coding selector. The proposed constant names permission to scan the next header, without asserting a success result. --- src/sdk/mpeg/picture/_getpic.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/mpeg/picture/_getpic.c b/src/sdk/mpeg/picture/_getpic.c index 20c30d2129..85c8062a9d 100644 --- a/src/sdk/mpeg/picture/_getpic.c +++ b/src/sdk/mpeg/picture/_getpic.c @@ -15,13 +15,16 @@ s32 _getpic(struct sceMpeg *mpeg) { MPEG_BIDIRECTIONAL_PICTURE = 3, MPEG_DC_INTRA_PICTURE = 4 }; + enum { + MPEG_DECODE_SCAN_NEXT_HEADER = 0 + }; s32 image_addr; s32 status; u32 start_code; struct MpegDecoder *decoder; start_code = 1; - status = 0; + status = MPEG_DECODE_SCAN_NEXT_HEADER; decoder = mpeg->sys; image_addr = decoder->unkD8; decoder->is_end = 0; From 7f5138a561a0176389af0f11375005f3d63f5042 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:55:55 +0000 Subject: [PATCH 0575/1502] decomp: clarify names in jet_mount domain_0_value_2 -> JET_MOUNT_COSINE_POSE_TRANSITION: Retail 0x002eaab4 retains a2 in s6; 0x002eab88 stores s6 into camera_record+0x88 and 0x002eab80-0x002eab84 compares that selector with 2, branching directly to duration/countdown initialization at 0x002eabd8-0x002eabe0. Original retail decompilation agrees. In the authoritative scripted_camera.c snapshot (SHA-256 391fb09fefa855fd721949e79712c10129818a2db11356fdcbed3602dfda9b35), update_camera_pose_from_targets reads the same record+0x88 byte; its t==2 branch decrements state+0xE0 and uses elapsed/total frames for interpolate_vector_xyz_cosine_eased and interpolate_wrapped_rotations_cosine_eased. This proves a camera cosine pose transition mode, separate from all supplied hero enums. domain_1_value_3 -> JET_MOUNT_SPHERICAL_TRANSITION: Retail 0x002eab88 writes the a2/s6 selector to camera_record+0x88; 0x002eab8c-0x002eab90 selects 3. That branch restores saved camera position/rotation at 0x002eaba8-0x002eabb4, sets transition coefficients at 0x002eaba0/0x002eaba4, and calls compute_spherical_offset_from_positions with state+0xFC at 0x002eabd0-0x002eabd4 before initializing frame counters. Original retail decompilation agrees. The authoritative source update_camera_pose_from_targets reads that same mode byte; its t==3 branch computes target spherical offsets relative to hero.motion.pos, interpolates azimuth/elevation/distance and reconstructs position with compute_position_from_spherical_offset. The supplied bolt_crank_update caller requests mode 3 with a scaled frame duration. This proves a scripted-camera spherical transition, not HERO_STATE_STOP or any other hero selector. --- src/overlays/shared/camera/scripted_camera.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/camera/scripted_camera.c b/src/overlays/shared/camera/scripted_camera.c index 8df91b46cf..0275d475f7 100644 --- a/src/overlays/shared/camera/scripted_camera.c +++ b/src/overlays/shared/camera/scripted_camera.c @@ -86,6 +86,10 @@ void set_camera_5_track_acceleration_yz(float camera_track_accel_y, float camera void jet_mount(V_2eaaa0 *pa, V_2eaaa0 *pb, s32 mode, s32 w, s32 x) __asm__("FUN_L00_002eaaa0"); void jet_mount(V_2eaaa0 *pa, V_2eaaa0 *pb, s32 mode, s32 transition_duration_frames, s32 x) { + enum { + JET_MOUNT_COSINE_POSE_TRANSITION = 2, + JET_MOUNT_SPHERICAL_TRANSITION = 3 + }; u8 *camera_record = find_camera_record_by_id(5); V_2eaaa0 requested_position, requested_rotation, saved_camera_position, saved_camera_rotation; u8 *camera_state; @@ -108,8 +112,8 @@ void jet_mount(V_2eaaa0 *pa, V_2eaaa0 *pb, s32 mode, s32 transition_duration_fra qcopy(camera_state + 0x90, &requested_rotation); *(s32 *)(transition_state + 0x40) = x; camera_record[0x88] = mode; - if (mode != 2) { - if (mode != 3) + if (mode != JET_MOUNT_COSINE_POSE_TRANSITION) { + if (mode != JET_MOUNT_SPHERICAL_TRANSITION) return; *(f32 *)(transition_state + 0x44) = 1.0f; *(f32 *)(transition_state + 0x48) = 0.0f; From c1c1a0a12f08bc40ae64e6d392163f5b89f50498 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:55:56 +0000 Subject: [PATCH 0576/1502] decomp: clarify names in update_trespasser_barrier domain_0_value_1 -> GLOW_ACTIVE: Retail 0x002f1e7c loads 1 into a0 and 0x002f1ec4 stores it to 0x20(s0) during initialization, alongside alpha 1.0 at pvars+0x0c. The same byte is read at 0x002f1e84 and equality with 1 branches at 0x002f1e88 to 0x002f1ed0, which queues draw_trespasser_barrier_quads and maintains its voice. The authoritative source already names that exact moby->state switch branch GLOW_ACTIVE=1, proving reuse for this assignment. domain_1_value_2 -> GLOW_FADE_OUT: Retail 0x002f1f40 loads 2 and 0x002f1f48 stores it to 0x20(s0) after the linked class-0x267 state check, while clearing collision and releasing the owned voice. The same state byte read at 0x002f1e84 is compared with 2 at 0x002f1eac and branches to 0x002f1fa8-0x002f1fbc, approaching pvars+0x0c toward zero with twice frame time. The supplied draw source identifies this scalar as max_alpha, and the authoritative source already names this exact switch branch GLOW_FADE_OUT=2. --- src/overlays/l18/mobys/trespasser_barrier.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/trespasser_barrier.c b/src/overlays/l18/mobys/trespasser_barrier.c index 92fd496fec..9c1bda1f0b 100644 --- a/src/overlays/l18/mobys/trespasser_barrier.c +++ b/src/overlays/l18/mobys/trespasser_barrier.c @@ -57,7 +57,7 @@ void trespasser_barrier_update(struct Moby *moby) { int *moby_vars = (int *)moby->pvars; switch (moby->state) { case GLOW_INITIALIZE: - moby->state = 1; + moby->state = GLOW_ACTIVE; ((float *)moby_vars)[3] = 1.0f; break; case GLOW_ACTIVE: @@ -69,7 +69,7 @@ void trespasser_barrier_update(struct Moby *moby) { unsigned char *linked_moby = D_L18_0015FFD8 + (moby_vars[0] << 8); if (MOBY(linked_moby)->oclass == 0x267 && linked_moby[0x20] >= 3) { moby->collision = 0; - moby->state = 2; + moby->state = GLOW_FADE_OUT; if (voice_is_playing(moby, moby_vars[1]) != 0) { int i = moby_vars[1]; if (i != -1) { From 5596151d3b5b8a9d6004e619abbdd9a115c10ed1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:55:56 +0000 Subject: [PATCH 0577/1502] decomp: clarify names in launch_first_idle_group_class_0772_moby domain_0_value_8 -> GADGEBOT_IDLE: Retail 0x002fc6c8-0x002fc6dc first checks oclass 0x772 at moby+0xa6 and then compares that same moby's state byte at +0x20 with 8; original Ghidra iVar7 confirms this object identity. The authoritative source's hide_moby_and_clear_collision uses GADGEBOT_IDLE=8 on moby->state while disabling visibility and collision. gadgebot_update initialization and explosion cleanup likewise set 8 with collision disabled. This launch helper selects that inactive reusable gadgebot before restoring collision and flags, proving the same gadgebot idle state domain. domain_1_value_1 -> GADGEBOT_LAUNCH_FLIGHT: Retail 0x002fc714-0x002fc720 stores 1 into the selected class-0x772 moby's state byte at +0x20, after copying its launch position. Retail 0x002fc724-0x002fc790 then initializes pvars velocity at +0x1d0 and ballistic Z speed at +0x1d8. Original Ghidra shows the same state store and velocity setup. In the authoritative source gadgebot_update switches on moby[0x20], with existing GADGEBOT_LAUNCH_FLIGHT=1 consuming those exact velocity offsets, applying gravity and transitioning on ground contact. This establishes the existing gadgebot flight constant rather than any hero enum. --- src/overlays/l18/mobys/gadgebot.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/gadgebot.c b/src/overlays/l18/mobys/gadgebot.c index f2d2ca5a97..df5cf766eb 100644 --- a/src/overlays/l18/mobys/gadgebot.c +++ b/src/overlays/l18/mobys/gadgebot.c @@ -471,6 +471,10 @@ int launch_first_idle_group_class_0772_moby(int group, float speed) __asm__("FUN_L18_002fc668"); int launch_first_idle_group_class_0772_moby(int group, void *from, void *to, float speed) { + enum { + GADGEBOT_LAUNCH_FLIGHT = 1, + GADGEBOT_IDLE = 8 + }; unsigned short *group_moby_entry = (unsigned short *)D_L18_001AC240[group]; struct Moby *table; struct Moby *moby; @@ -481,13 +485,13 @@ int launch_first_idle_group_class_0772_moby(int group, void *from, void *to, flo for (;;) { moby = &table[*group_moby_entry & 0x7FFF]; if (moby->oclass == 0x772) { - if (moby->state == 8) { + if (moby->state == GADGEBOT_IDLE) { LaunchedMobyVars *launched_moby_vars = (LaunchedMobyVars *)moby->pvars; moby->flags &= ~0x41; moby->collision = moby->pclass->collision; moby->flags |= 0x1000; qcopy(&moby->pos, from); - moby->state = 1; + moby->state = GADGEBOT_LAUNCH_FLIGHT; launched_moby_vars->unk1F4 = 1.0f; fast_vec_sub(launched_moby_vars->velocity, to, from); launched_moby_vars->velocity[2] = 0.0f; From 55c44f9066212b3565300a5c1e8fce1a4136da72 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:55:56 +0000 Subject: [PATCH 0578/1502] decomp: clarify names in update_pokitaru_paired_rotation domain_0_value_1 -> ROTATION_WAIT_FOR_TRIGGER: Authoritative source src/overlays/l11/mobys/pokitaru_paired_rotation.c (SHA-256 8067f7d5e289e48558e236caf40015ac958ddd16b28b7a416996b57822325bc1) already defines ROTATION_WAIT_FOR_TRIGGER=1 in this function's local state enum. Retail 0x002cb828 reads the selector byte at moby+0x20, 0x002cb82c returns for value 1, and initialization at 0x002cb864 writes 1 to that identical byte. Thus this assignment enters the existing named wait state in the same exact selector domain; no unrelated equal-valued header constant is applicable. domain_1_value_3 -> ROTATION_OFFSET_REACHED: Retail 0x002cb850 dispatches moby+0x20 value 2 to ROTATION_APPROACH_OFFSET. Instructions 0x002cb8f4-0x002cb918 compute saved rot.z at pvars+4 plus/minus 0.20769417, then 0x002cb93c-0x002cb958 call approach_angle with destination moby+0x48 (rot.z) and that target. At 0x002cb964-0x002cb974, only a zero approach result stores 3 into the same moby+0x20 selector. The original retail decompilation and authoritative C both show this conditional transition after approaching the rotation offset, proving the resulting state denotes offset reached. --- src/overlays/l11/mobys/pokitaru_paired_rotation.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l11/mobys/pokitaru_paired_rotation.c b/src/overlays/l11/mobys/pokitaru_paired_rotation.c index dfe5ab5f3c..000b1b636b 100644 --- a/src/overlays/l11/mobys/pokitaru_paired_rotation.c +++ b/src/overlays/l11/mobys/pokitaru_paired_rotation.c @@ -24,11 +24,14 @@ void pokitaru_paired_rotation_update(struct Moby *moby) { ROTATION_WAIT_FOR_TRIGGER = 1, ROTATION_APPROACH_OFFSET = 2 }; + enum { + ROTATION_OFFSET_REACHED = 3 + }; char *paired_rotation_vars = (char *)moby->pvars; int state = (unsigned char)MOBY(moby)->state; switch (state) { case ROTATION_INITIALIZE: - MOBY(moby)->state = 1; + MOBY(moby)->state = ROTATION_WAIT_FOR_TRIGGER; *(float *)(paired_rotation_vars + 4) = moby->rot.z; if ((moby->flags & 0x8000) == 0) { char *partner_moby = create_moby(0x41); @@ -56,7 +59,7 @@ void pokitaru_paired_rotation_update(struct Moby *moby) { frame_time_sq * 0.34906584f, frame_time_sq * 0.34906584f, frame_time * 0.7853982f) == 0.0f) - MOBY(moby)->state = 3; + MOBY(moby)->state = ROTATION_OFFSET_REACHED; break; } } From 8acd802911d519a5a3b250034e5f0dbcc8a207ca Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:55:56 +0000 Subject: [PATCH 0579/1502] decomp: clarify names in spawn_poison_vessel_fragment domain_0_value_0 -> POISON_VESSEL_FRAGMENT_MODE_REDUCED_SCALE: Fourth argument a3 is preserved in s5 at retail 0x0030c14c. The bne s5,zero at 0x0030c220 skips 0x0030c228-0x0030c248 for nonzero modes; only mode zero multiplies moby scale (+0x2C) by random_float_between(0.5,0.75). The reduced scale is saved to private vars +0x1C at 0x0030c264 before the shared 2..5 enlargement. Original Ghidra param_4 == 0 and authoritative C effect_mode == 0 agree. Checked level-13 caller 0x003073c8 passes a3=0 in the delay slot at 0x003075cc for its first fragment group, and a3=1 at 0x003076ec/0x003077ec for the other groups. The same selector is stored as the mode byte at moby+0xBC (0x0030c270), establishing an effect-mode domain rather than a current-state domain. No shared enum domain is supplied. --- src/overlays/l13/mobys/poison_vessel_fragment.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/poison_vessel_fragment.c b/src/overlays/l13/mobys/poison_vessel_fragment.c index 21db7b9d04..80a3d714c4 100644 --- a/src/overlays/l13/mobys/poison_vessel_fragment.c +++ b/src/overlays/l13/mobys/poison_vessel_fragment.c @@ -34,6 +34,9 @@ char *spawn_poison_vessel_fragment(void *position, int duration_frames, int effect_mode) { + enum { + POISON_VESSEL_FRAGMENT_MODE_REDUCED_SCALE = 0 + }; unsigned char *moby = (unsigned char *)create_moby(0x662); if (moby != 0) { char *effect_moby_vars; @@ -54,7 +57,7 @@ char *spawn_poison_vessel_fragment(void *position, random_float_between(dd * 6.2831855f, dd * 12.566371f); *(short *)(effect_moby_vars + 0x18) = duration_frames; *(short *)(effect_moby_vars + 0x1A) = duration_frames; - if (effect_mode == 0) { + if (effect_mode == POISON_VESSEL_FRAGMENT_MODE_REDUCED_SCALE) { MOBY(moby)->scale = MOBY(moby)->scale * random_float_between(0.5f, 0.75f); } *(float *)(effect_moby_vars + 0x1C) = MOBY(moby)->scale; From 6df3963789a0ba4b8ef10eccf297ebc777ffe521 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:57:51 +0000 Subject: [PATCH 0580/1502] decomp: clarify names in update_cutscene_joint_trails domain_0_value_1 -> JOINT_TRAIL_EMIT: In the authoritative source, moby->state is the selector of cases JOINT_TRAIL_INITIALIZE=0 and JOINT_TRAIL_EMIT=1. Retail 0x002e7e18 loads its byte at a0+0x20; 0x002e7e20-24 dispatches value 1 to 0x002e7e48. Initialization at 0x002e7e38-3c stores 1 to that exact byte, so the assignment enters the existing JOINT_TRAIL_EMIT state. That branch queries joints 6/4 and 7/5 and emits trails via calls at 0x002e7ee0 and 0x002e7f58. Original Ghidra likewise shows the +0x20 assignment and value-1 emission guard; this is the same local state domain, not a hero or Boolean domain. --- src/overlays/l16/mobys/cutscene_joint_trails.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/cutscene_joint_trails.c b/src/overlays/l16/mobys/cutscene_joint_trails.c index 84eb7e1477..842dfdbbeb 100644 --- a/src/overlays/l16/mobys/cutscene_joint_trails.c +++ b/src/overlays/l16/mobys/cutscene_joint_trails.c @@ -61,7 +61,7 @@ void cutscene_joint_trails_update(struct Moby *moby) { switch (moby->state) { case JOINT_TRAIL_INITIALIZE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = JOINT_TRAIL_EMIT; break; case JOINT_TRAIL_EMIT: if (D_L16_0015F5C4 == 2) { From bddb3ca20031ca3e6c1b5c6bf406ccab11dfb62f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:57:52 +0000 Subject: [PATCH 0581/1502] decomp: clarify names in try_retract_turret_group domain_0_value_5 -> TURRET_STATE_RETRACTING: Retail 0x002b4550-0x002b4574 masks the group member index, selects a 0x100-byte moby, and loads its current-state byte at +0x20 for comparison to 5. In the second pass, 0x002b45c8-0x002b45e8 selects state-3 members, starts animation 4 and writes 5 to that same state field; 0x002b45ec-0x002b4638 initializes retract frames, inverse duration, animation speed and saved heading. The established try_retract_turret_group name, authoritative retracting_moby/turret_vars data flow, and supplied original Ghidra plate identifying state-5 retract interpolation prove the retraction state. It is not the interceptor caller's equal-valued return-path state. domain_1_value_1 -> TURRET_STATE_WAITING: Retail 0x002b4570 loads the selected group member's current moby state byte +0x20; 0x002b454c and 0x002b457c compare it with 1, allowing this member through the readiness scan. In the authoritative source, activate_waiting_turrets_in_group traverses the same D_L14_001ABF40 group table with the same 0x7FFF mask and 0x100 moby stride, selects listed_moby[0x20] == 1, and sets its pvars+0x88 activation field to 1. is_turret_group_activated_or_empty reads that field, and the interceptor alert-group branch calls the waiting-turret activation helper. This establishes state 1 as the waiting turret state, independently of unrelated hero enum values. --- src/overlays/l14/mobys/blarg_heavy_interceptor.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/blarg_heavy_interceptor.c b/src/overlays/l14/mobys/blarg_heavy_interceptor.c index 6c958fee42..ed89730b6b 100644 --- a/src/overlays/l14/mobys/blarg_heavy_interceptor.c +++ b/src/overlays/l14/mobys/blarg_heavy_interceptor.c @@ -1948,6 +1948,10 @@ extern int FUN_001f96f8_b45(int) __asm__("FUN_001f96f8"); extern float FUN_001fa6c0_b45(short) __asm__("FUN_001fa6c0"); int try_retract_turret_group(int index) { + enum { + TURRET_STATE_WAITING = 1, + TURRET_STATE_RETRACTING = 5 + }; short *list_entry = D_L14_001ABF40_b45[index]; unsigned char *moby_array_start; unsigned char *checked_moby; @@ -1966,7 +1970,7 @@ int try_retract_turret_group(int index) { checked_moby = moby_array_start + (moby_index_or_state << 8); if ((((unsigned char *)MOBY(checked_moby)->pvars))[0x8B] == 0) { moby_index_or_state = checked_moby[0x20]; - if (moby_index_or_state != 5 && moby_index_or_state != 1) { + if (moby_index_or_state != TURRET_STATE_RETRACTING && moby_index_or_state != TURRET_STATE_WAITING) { return 0; } } From be4cef745ce0853e72e8e96175aa647d32bc3701 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:57:52 +0000 Subject: [PATCH 0582/1502] decomp: clarify names in sceMcGetInfo domain_0_value_0 -> NULL: Callers check_memory_card and memcard_update_state pass &card_type and &CARD.type as argument three. Retail 0x00123d8c preserves a2 in s3, 0x00123dec tests s3 against zero to select the type-request flag at request offset 0x14, and 0x00123e50 saves the same address to D_00159A28. Thus this zero denotes an absent output address, matching existing NULL, not a card-type numeric enum or FALSE boolean. --- src/sdk/storage/memory_card/sce_mc_get_info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdk/storage/memory_card/sce_mc_get_info.c b/src/sdk/storage/memory_card/sce_mc_get_info.c index cf283fa8c3..85b4c49422 100644 --- a/src/sdk/storage/memory_card/sce_mc_get_info.c +++ b/src/sdk/storage/memory_card/sce_mc_get_info.c @@ -36,7 +36,7 @@ s32 sceMcGetInfo(s32 port, s32 slot, s32 type, s32 free_blocks, s32 format) { D_00159A80.unk4 = port; D_00159A80.unk8 = slot; D_00159A80.unk1C = D_00159F00; - if (type != 0) { + if (type != NULL) { D_00159A80.unk14 = 1; } else { D_00159A80.unk14 = 0; From 7f3474873fdb763e383a8a9ccb2c305a41aa9d8e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:59:44 +0000 Subject: [PATCH 0583/1502] decomp: clarify names in update_camera domain_0_value_0 -> CAMERA_TRANSITION_PHASE_IDLE: Retail 0x001edad8-0x001edae0 constructs address 0x001871B0 and stores a zero halfword, followed by clearing the separate alternate-transition byte at +2 (0x001edae4). The authoritative update_camera source maps this halfword to *(short *)cam_trans_state. Supplied update_camera_blend aliases camera_transition_state = cam_trans_state and, when transition_complete != 0 after stepping the blend, writes CAMERA_TRANSITION_PHASE_IDLE (explicit value 0) to precisely that same short and clears byte +2. Original retail decompilation identifies the assigned halfword as g_nCameraTransitionPhase. Thus this is the established idle transition phase in the same storage domain, not a boolean or unrelated equal-valued state. --- src/camera/update_camera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/camera/update_camera.c b/src/camera/update_camera.c index 87b25ca3b9..e2714f90d6 100644 --- a/src/camera/update_camera.c +++ b/src/camera/update_camera.c @@ -30,7 +30,7 @@ void update_camera(void) __asm__("FUN_001edaa8"); extern s32 game_mode_macro __asm__("D_0015F604") MACRO_ADDR; void update_camera(void) { - struct PreviewCamera *camera; + enum { CAMERA_TRANSITION_PHASE_IDLE = 0 } ;struct PreviewCamera *camera; struct UpdateCam *target; char *camera_shake_base; float rotation_matrix[16]; @@ -39,7 +39,7 @@ void update_camera(void) { if (text_screen_active[0] != 0) { return; } - cam_trans_state.mode = 0; + cam_trans_state.mode = CAMERA_TRANSITION_PHASE_IDLE; cam_trans_state.kind = 0; } camera = &preview_camera; From 1ab1de6a685fa7c8393c27ad5db5f75ed648beab Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:59:44 +0000 Subject: [PATCH 0584/1502] decomp: clarify names in draw_screen_effect domain_0_value_0 -> BACKGROUND_ALPHA_STATE_SKIP_WRITE: Retail 0x001f4fe4 loads the background record's u64 ALPHA_2 state from configuration +0x8. At 0x001f4fe8 a zero value branches to 0x001f500c, bypassing the masked register-0x42 write at 0x001f5000. The source background_alpha_state != 0 comparison implements that precise write-suppression sentinel; background color drawing is gated separately. domain_1_value_0 -> FIRST_STRIPE_ALPHA_STATE_SKIP_WRITE: Retail 0x001f5050 loads firstStripe.qwAlphaState from configuration +0x18. The zero branch at 0x001f5054 targets 0x001f5064, bypassing the 0xFF000000FF-masked GS register-0x42 write at 0x001f505c. Thus zero in the source first_stripe_alpha_state comparison specifically skips the first stripe's ALPHA_2 write, independently of its rectangle color gate. domain_2_value_0 -> SECOND_STRIPE_ALPHA_STATE_SKIP_WRITE: Retail 0x001f50ac loads secondStripe.qwAlphaState from configuration +0x28 after the first stripe span advance. At 0x001f50b0 zero branches to 0x001f50c4, bypassing masking at 0x001f50b8 and the register-0x42 write at 0x001f50bc. The source second_stripe_alpha_state != 0 comparison therefore uses zero as the sentinel to skip this record's ALPHA_2 write. --- src/rendering/effects/draw_screen_effect.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/rendering/effects/draw_screen_effect.c b/src/rendering/effects/draw_screen_effect.c index 6f9807fe25..54abe40c10 100644 --- a/src/rendering/effects/draw_screen_effect.c +++ b/src/rendering/effects/draw_screen_effect.c @@ -20,6 +20,11 @@ extern void draw_rect_overlay(s32, s32, s32, s32, u64) __asm__("func_ void draw_screen_effect(void) __asm__("FUN_001f4fb8"); void draw_screen_effect(void) { + enum { + BACKGROUND_ALPHA_STATE_SKIP_WRITE = 0, + FIRST_STRIPE_ALPHA_STATE_SKIP_WRITE = 0, + SECOND_STRIPE_ALPHA_STATE_SKIP_WRITE = 0 + }; s32 i; s16 height; u64 mask; @@ -33,7 +38,7 @@ void draw_screen_effect(void) { i = 0; height = fs_aa_buffer.display_height; background_alpha_state = screen_color_effect_now->enable; - if (background_alpha_state != 0) { + if (background_alpha_state != BACKGROUND_ALPHA_STATE_SKIP_WRITE) { vu1_add_g_sregister(0x42, background_alpha_state & 0xFF000000FFULL); } background_color = screen_color_effect_now->color; @@ -45,7 +50,7 @@ void draw_screen_effect(void) { mask = 0xFF000000FFULL; do { first_stripe_alpha_state = screen_color_effect_now->unk18; - if (first_stripe_alpha_state != 0) { + if (first_stripe_alpha_state != FIRST_STRIPE_ALPHA_STATE_SKIP_WRITE) { vu1_add_g_sregister(0x42, first_stripe_alpha_state & mask); } first_stripe_color = screen_color_effect_now->unk14; @@ -60,7 +65,7 @@ void draw_screen_effect(void) { } i = i + screen_color_effect_now->unk10; second_stripe_alpha_state = screen_color_effect_now->unk28; - if (second_stripe_alpha_state != 0) { + if (second_stripe_alpha_state != SECOND_STRIPE_ALPHA_STATE_SKIP_WRITE) { vu1_add_g_sregister(0x42, second_stripe_alpha_state & mask); } second_stripe_color = screen_color_effect_now->unk24; From 7d547b6cdd89257afdff3ac97020445f19782ab3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:01:42 +0000 Subject: [PATCH 0585/1502] decomp: clarify names in draw_menu_selection_text domain_0_value_3 -> MEMCARD_REQUEST_FORMAT: Authoritative source SHA-256 9c8fe1f9014d48e05a26f9cfa9f64efe057a5f5a857d276a2634f649dbd5c9b9 binds card_state to &memory_card_state. Retail 0x00222da4/0x00222db4 constructs that object's 0x0013d290 address; 0x00222de4 loads its +0xd4 state and 0x00222de8 compares it with signed threshold 3 before skipping text drawing. Original Ghidra identifies this as g_nMemoryCardOperationState < 3. The supplied memory_card_state.h declaration context explicitly assigns MemoryCardState.state and pending_state to MemoryCardOperation, whose canonical member MEMCARD_REQUEST_FORMAT has value 3; independent substep enums do not own this field. domain_1_value_0 -> MEMCARD_QUERY_INFO: The same retail memory-card object in s0 supplies the +0xdc pending-state load at 0x00222df4; bgez at 0x00222df8 skips drawing unless that signed pending operation is below zero. Original Ghidra calls this g_nPendingMemoryCardOperationState < 0, matching card_state->pending_state in the authoritative source. The supplied memory_card_state.h context explicitly places pending_state in MemoryCardOperation together with state, and MEMCARD_QUERY_INFO is that domain's canonical zero member. This names the comparison boundary without changing its less-than operator or claiming the negative sentinel is a query request. --- src/ui/menus/widgets/draw_menu_selection_text.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/menus/widgets/draw_menu_selection_text.c b/src/ui/menus/widgets/draw_menu_selection_text.c index 04a95ce947..760b652681 100644 --- a/src/ui/menus/widgets/draw_menu_selection_text.c +++ b/src/ui/menus/widgets/draw_menu_selection_text.c @@ -27,7 +27,7 @@ s32 draw_menu_selection_text(struct MenuScreen *menu) { *((s32 *)((((u8 *)card_state) - (-(menu_system.current->focus->data.save.slot * 0x1C))) + 0x20)); setup_gif_paging(0); - if (((card_state->state < 3) && (card_state->pending_state < 0)) && + if (((card_state->state < MEMCARD_REQUEST_FORMAT) && (card_state->pending_state < MEMCARD_QUERY_INFO)) && (card_state->card[0].type == 2)) { if (entry_index == (-1)) { height = menu->height; From a9e57a2ac489ec7c23a8a1701edded2e83dc4f03 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:01:42 +0000 Subject: [PATCH 0586/1502] decomp: clarify names in update_hero_trigger_volume_monitor domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source assigns hero_ptr = &hero and compares hero_ptr->vehicle_mode != 0. Retail 0x002f79ec computes hero position 0x0013f3d0; 0x002f79fc subtracts 0x80 to recover hero base 0x0013f350, and 0x002f7a00 loads its vehicle_mode byte at +0x20a4 (0x001413f4, cRam001413f4 in original Ghidra). The zero branch at 0x002f7a04 goes to the current-state test/request at 0x002f7a2c-0x002f7a38; nonzero calls frame scaling, fade and respawn at 0x002f7a0c-0x002f7a1c. Thus this is the HeroVehicleMode selector, whose existing canonical zero member in include/rnc/hero/hero_state.h is HERO_VEHICLE_MODE_ON_FOOT, rather than HeroStateId, gravity or monitor state. --- src/overlays/shared/props/respawn_volume.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/props/respawn_volume.c b/src/overlays/shared/props/respawn_volume.c index 4cb3118219..d606f35a0d 100644 --- a/src/overlays/shared/props/respawn_volume.c +++ b/src/overlays/shared/props/respawn_volume.c @@ -49,7 +49,7 @@ void respawn_volume_update(char *moby) { for (i = 0; i < 32; i++) { if (list[i] >= 0 && is_point_inside_clip_volume(&hero.motion.pos, list[i])) { struct Hero *hero_ptr = &hero; - if (hero_ptr->vehicle_mode != 0) { + if (hero_ptr->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { fade_to_black(scale_game_frames(10)); hero_respawn(); } else if (hero_ptr->state.current != 0x77) { From 7716a7bb306cccaf0ab844242b20fa17a9097831 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:01:42 +0000 Subject: [PATCH 0587/1502] decomp: clarify names in classify_resort_owner_target_proximity domain_0_value_0 -> RESORT_OWNER_TARGET_MIN_LIVE_STATE: Authoritative src/overlays/l11/mobys/resort_owner.c (SHA-256 92f81ac0f41ba36f02c7b23319faa39cf74e00681f0e27682e41d17455b526f1) compares (signed char)target_group_moby->state >= 0. Retail 0x002d2500-0x002d2514 resolves a group-list member by masking its index with 0x7fff, scaling by 0x100, and adding D_L11_0015FFD8. At 0x002d2518 lb loads that moby's state at +0x20; 0x002d251c bltzl skips negative states to the list advance. Only nonnegative states reach the class/exclusion test at 0x002d2524-0x002d2538 and found/distance classification at 0x002d254c-0x002d2568. Original Ghidra independently shows the signed char negative-state skip; the supplied C comment describes live mobys. Thus zero is the minimum live-target state accepted by this scan, without assigning it any specific class lifecycle meaning or borrowing an unrelated zero-valued enum member. --- src/overlays/l11/mobys/resort_owner.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/resort_owner.c b/src/overlays/l11/mobys/resort_owner.c index 9c4020e54c..30e2371a9d 100644 --- a/src/overlays/l11/mobys/resort_owner.c +++ b/src/overlays/l11/mobys/resort_owner.c @@ -740,6 +740,9 @@ extern s32 D_L11_0015FFF4; /* 2 when a live moby of the current target groups is within 10 units, 1 when one is alive, else 0. */ int classify_resort_owner_target_proximity(struct Moby *moby) { + enum { + RESORT_OWNER_TARGET_MIN_LIVE_STATE = 0 + }; struct TargetSets *target_sets = (struct TargetSets *)moby->pvars; int found = 0; int i; @@ -756,7 +759,7 @@ int classify_resort_owner_target_proximity(struct Moby *moby) { do { int offset = (*group_moby_entry & 0x7fff) << 8; struct Moby *target_group_moby = (struct Moby *)(offset + D_L11_0015FFD8); - if ((signed char)target_group_moby->state >= 0) { + if ((signed char)target_group_moby->state >= RESORT_OWNER_TARGET_MIN_LIVE_STATE) { if (target_group_moby->oclass != 0x4de || is_moby_in_bob_target_exclusion_state((const u8 *)target_group_moby) == 0) { found = 1; From 888ac711e6e64dc79fae5e69c94e4fdde4940f04 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:01:42 +0000 Subject: [PATCH 0588/1502] decomp: clarify names in bolt_grabber_update domain_0_value_1 -> BOLT_GRABBER_WAIT_FOR_PROXIMITY: Retail 002ea770 retains the moby in s0; 002ea774 loads s1=1 and 002ea804 stores it to state byte +0x20. The same byte is loaded at 002ea790 and value 1 dispatches at 002ea798 to 002ea814: particles then moby-to-hero distance testing against 3.0 at 002ea820-002ea840. This is exactly the source's existing BOLT_GRABBER_WAIT_FOR_PROXIMITY case and local enum, establishing the same selector domain. domain_1_value_2 -> BOLT_GRABBER_FINALIZE_AND_SAVE: After the proximity test and start_scene(5), retail 002ea85c loads 2 and 002ea864 writes the same moby state byte +0x20 read at 002ea790. Dispatch 002ea7bc sends state 2 to 002ea868; 002ea878-002ea8a4 queues dialogue, scales timing, grants inventory item 0x22 and calls memcard_save_data(0,-1). The authoritative source already names this exact switch domain's value 2 BOLT_GRABBER_FINALIZE_AND_SAVE. domain_2_value_3 -> BOLT_GRABBER_REMOVE: Retail 002ea8a8 loads 3 after memcard_save_data and 002ea8b0 stores it to the moby's state byte +0x20. That same byte is read at 002ea790; 002ea7c4 dispatches value 3 to 002ea8b4, which passes the same moby to mark_moby_for_removal. This directly reuses existing BOLT_GRABBER_REMOVE=3 from the source's local enum for this selector. --- src/overlays/l15/mobys/bolt_grabber.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l15/mobys/bolt_grabber.c b/src/overlays/l15/mobys/bolt_grabber.c index 035361cc7b..82ed96c52e 100644 --- a/src/overlays/l15/mobys/bolt_grabber.c +++ b/src/overlays/l15/mobys/bolt_grabber.c @@ -42,7 +42,7 @@ void bolt_grabber_update(struct Moby *moby) { mark_moby_for_removal(moby); return; } - moby->state = 1; + moby->state = BOLT_GRABBER_WAIT_FOR_PROXIMITY; moby->pos.z = moby->pos.z + 1.0f; break; case BOLT_GRABBER_WAIT_FOR_PROXIMITY: @@ -50,7 +50,7 @@ void bolt_grabber_update(struct Moby *moby) { if (vector_distance_xy(&moby->pos, &hero.motion.pos) < 3.0f) { moby->flags |= 0x41; start_scene(5); - moby->state = 2; + moby->state = BOLT_GRABBER_FINALIZE_AND_SAVE; } break; case BOLT_GRABBER_FINALIZE_AND_SAVE: @@ -59,7 +59,7 @@ void bolt_grabber_update(struct Moby *moby) { D_L15_0015F640 = scale_game_frames(0xB4); grant_inventory_item(0x22, 1); memcard_save_data(0, -1); - moby->state = 3; + moby->state = BOLT_GRABBER_REMOVE; } break; case BOLT_GRABBER_REMOVE: From 0cf04671a33bccdd934d3009ccae0eb7754765bf Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:01:42 +0000 Subject: [PATCH 0589/1502] decomp: clarify names in fan_update domain_0_value_0 -> FAN_STATE_UNINITIALIZED: In the bound source src/overlays/l01/mobys/fan.c (SHA-256 8f5a319dc2fdc2f1ea00e3da8377dee130176733dce9845c041d01486a1933b9), fan_moby->state == 0 guards initialization of sway and direction. Original retail Ghidra tests *(char *)(iVar4 + 0x20) == 0; retail 0x002f9c0c loads this byte from s1 and 0x002f9c10 skips initialization when nonzero. The zero path copies the hero field, stores state 1 at 0x002f9c38, initializes sway from random_float_between(-1,1) at 0x002f9c3c-0x002f9c48 and direction from rand() & 1 at 0x002f9c44-0x002f9c58. Thus zero identifies the fan state awaiting initialization. domain_1_value_1 -> FAN_STATE_INITIALIZED: The same fan_moby->state byte at s1+0x20 is loaded at retail 0x002f9c0c and tested against zero at 0x002f9c10. Inside that zero-only initialization block, li v0,1 at 0x002f9c30 and sb v0,0x20(s1) at 0x002f9c38 record initialization; the block also initializes sway at s0+0 and direction at s0+4 before joining the regular collision and rotation update at 0x002f9c5c. Original retail Ghidra shows the corresponding byte assignment of 1. On subsequent updates this value bypasses initialization. INITIALIZED describes that demonstrated status without inferring another control or state domain. --- src/overlays/l01/mobys/fan.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l01/mobys/fan.c b/src/overlays/l01/mobys/fan.c index a36b3c0af2..7f8a815f9e 100644 --- a/src/overlays/l01/mobys/fan.c +++ b/src/overlays/l01/mobys/fan.c @@ -39,13 +39,17 @@ void fan_update(SwayMoby *m) __asm__("FUN_L01_002f9bf0"); /* Moby class 705 */ void fan_update(SwayMoby *fan_moby) { + enum { + FAN_STATE_UNINITIALIZED = 0, + FAN_STATE_INITIALIZED = 1 + }; SwayVars *sway_vars; CollQuery collision_query; sway_vars = fan_moby->pvars; - if (fan_moby->state == 0) { + if (fan_moby->state == FAN_STATE_UNINITIALIZED) { copy_hero_moby_field_38(fan_moby); - fan_moby->state = 1; + fan_moby->state = FAN_STATE_INITIALIZED; sway_vars->sway = random_float_between(-1.0f, 1.0f); sway_vars->dir = (rand() & 1) ? 1.0f : -1.0f; } From eb9855122cab5748d1ac9870f7d28f5a10f4f6b4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:01:42 +0000 Subject: [PATCH 0590/1502] decomp: clarify names in process_minibomber_hit_reactions domain_0_value_0 -> MINIBOMBER_STATE_INITIALIZE: Retail 0x002b529c preserves the incoming minibomber in s1; 0x002b52a4 loads its state byte at +0x20 and 0x002b52a8 returns for zero. Supplied minibomber_update passes this same moby directly to FUN_L14_002b5290 before switching on moby->state. Its established MINIBOMBER_STATE_INITIALIZE=0 branch validates paths, initializes position/manipulator state and advances to state 1, proving the exact selector domain and initialization meaning. domain_1_value_9 -> MINIBOMBER_STATE_DESTROY: Retail 0x002b52a4 loads incoming moby state from +0x20; 0x002b52b0-0x002b52b4 skips reactions when it equals 9. Supplied minibomber_update calls this function on the same object before its state switch, whose established MINIBOMBER_STATE_DESTROY=9 branch spawns debris/explosion, releases its voice and marks the moby for removal. This is the moby state domain, distinct from HIT_REACTION_RED_FLASH_ONLY=9. domain_2_value_9 -> MINIBOMBER_STATE_DESTROY: Retail 0x002b5340 reloads the same s1 moby's state byte at +0x20 after the hit helper; 0x002b5344-0x002b5348 skips damage/reaction dispatch when that state equals 9, matching source state !=9 guard. The supplied direct caller minibomber_update dispatches that same object's state 9 to established MINIBOMBER_STATE_DESTROY, spawning destruction effects and removing the moby. Reuse its state constant rather than the separate hit-reaction selector value 9. domain_3_value_9 -> MINIBOMBER_STATE_DESTROY: Original Ghidra groups hit-reaction results 1/2 in the terminal branch. Retail 0x002b53c8 loads 9 and 0x002b53d0 writes it to s1+0x20, the same moby state tested at entry; the branch also clears flag 0x1000 and calls terminal handling. Supplied minibomber_update calls this function before state dispatch and names state 9 MINIBOMBER_STATE_DESTROY, whose branch emits debris/explosion, releases the voice and removes the object. This proves the assignment's state domain. --- src/overlays/l14/mobys/minibomber.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l14/mobys/minibomber.c b/src/overlays/l14/mobys/minibomber.c index 6b1d268b95..fbf8894c9a 100644 --- a/src/overlays/l14/mobys/minibomber.c +++ b/src/overlays/l14/mobys/minibomber.c @@ -651,13 +651,17 @@ void process_minibomber_hit_reactions(struct Moby *hit_owner_moby) { HIT_REACTION_FLASH_RED = 10, HIT_REACTION_NONE = 11 }; + enum { + MINIBOMBER_STATE_INITIALIZE = 0, + MINIBOMBER_STATE_DESTROY = 9 + }; unsigned char *moby_vars = hit_owner_moby->pvars; int loc0; float damage_amount; char *hit_record; int k; float remaining_health; - if (hit_owner_moby->state == 0 || hit_owner_moby->state == 9) + if (hit_owner_moby->state == MINIBOMBER_STATE_INITIALIZE || hit_owner_moby->state == MINIBOMBER_STATE_DESTROY) return; hit_owner_moby->scale = hit_owner_moby->pclass->scale; damage_amount = 0.0f; @@ -671,7 +675,7 @@ void process_minibomber_hit_reactions(struct Moby *hit_owner_moby) { } k = FUN_L00_0025a478_c( hit_owner_moby, hit_record, moby_vars + 0x20, 0, &loc0, &damage_amount, 0, 4); - if (loc0 != 1 && hit_owner_moby->state != 9) { + if (loc0 != 1 && hit_owner_moby->state != MINIBOMBER_STATE_DESTROY) { remaining_health = *(float *)(moby_vars + 0x20) - damage_amount; *(float *)(moby_vars + 0x20) = remaining_health; if (remaining_health <= 0.0f) @@ -694,7 +698,7 @@ void process_minibomber_hit_reactions(struct Moby *hit_owner_moby) { break; case HIT_REACTION_LETHAL: case HIT_REACTION_DESTROY: - hit_owner_moby->state = 9; + hit_owner_moby->state = MINIBOMBER_STATE_DESTROY; hit_owner_moby->flags &= 0xEFFF; moby_vars[0x67] = 0xFA; FUN_L00_00257470(hit_owner_moby, 0, -1); From b2ae308c99a097e135782b774563cea1980f55c1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:01:42 +0000 Subject: [PATCH 0591/1502] decomp: clarify names in GetMpegPictureTimestampsAndFlags domain_0_value_2 -> MPEG_PTS_OVERRIDE_PENDING: In the bound _getPtsDtsFlags.c snapshot, state->override_state == 2 gates use of state->override_timestamp. Retail 0x00129c40-0x00129c58 loads state+0xf8, compares it with 2, and checks the signed timestamp at state+0xf0. At 0x00129c5c the nonnegative timestamp replaces the presentation timestamp through s5, followed by clearing the override. Thus this is a pending presentation-timestamp override state, separate from picture flags or decoding timestamps. domain_1_value_0 -> MPEG_PTS_OVERRIDE_INACTIVE: The same override_state field compared at retail 0x00129c40-0x00129c48 is cleared by sw zero,0xf8(s3) at 0x00129c64 immediately after copying the override presentation timestamp at 0x00129c5c. The timestamp slot is invalidated with -1 at 0x00129c60-0x00129c68. Source and original Ghidra agree that zero clears the consumed override and bypasses the state==2 application branch on subsequent calls, proving an inactive override state. --- src/sdk/mpeg/demux/_getPtsDtsFlags.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/sdk/mpeg/demux/_getPtsDtsFlags.c b/src/sdk/mpeg/demux/_getPtsDtsFlags.c index 31f7c23cc5..31d7061620 100644 --- a/src/sdk/mpeg/demux/_getPtsDtsFlags.c +++ b/src/sdk/mpeg/demux/_getPtsDtsFlags.c @@ -40,6 +40,10 @@ void GetMpegPictureTimestampsAndFlags(struct MpegTimestampState *state, s64 *decoding_timestamp, s64 *flags) { + enum { + MPEG_PTS_OVERRIDE_INACTIVE = 0, + MPEG_PTS_OVERRIDE_PENDING = 2 + }; s32 previous_timestamp; s32 timestamp_carry; s64 timestamp_step; @@ -71,11 +75,11 @@ void GetMpegPictureTimestampsAndFlags(struct MpegTimestampState *state, } else { *presentation_timestamp = picture->presentation_timestamp; } - if (state->override_state == 2) { + if (state->override_state == MPEG_PTS_OVERRIDE_PENDING) { override_timestamp = state->override_timestamp; if (override_timestamp >= 0) { *presentation_timestamp = override_timestamp; - state->override_state = 0; + state->override_state = MPEG_PTS_OVERRIDE_INACTIVE; state->override_timestamp = -1; } } From b85e1e3d2ec98962e0114c94a95e46341baee39f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:03:32 +0000 Subject: [PATCH 0592/1502] decomp: clarify names in plasmabot_hatch_update domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x002d96e4/0x002d96fc loads the byte at 0x001413f4, identified by SHA-bound source as hero.vehicle_mode, and 0x002d96ec-0x002d970c compares it with 2 before clearing hatch collision at moby+0x94. This selector is explicitly the separate HeroVehicleMode domain, whose canonical member for 2 is HERO_VEHICLE_MODE_GIANT_CLANK; it is not moby->state or HeroStateId. domain_1_value_1 -> HATCH_WAIT_ACTIVATION_DELAY: Retail 0x002d9764-0x002d9778 writes 1 to moby+0x20 and initializes pvars+8 from scaled pvars+4 after activation gates pass. The same byte is the switch selector loaded at 0x002d971c. Existing local HATCH_WAIT_ACTIVATION_DELAY=1 handles it at 0x002d977c by waiting on fast_dec_timer(pvars+8), proving reuse of that exact hatch state member. domain_2_value_2 -> HATCH_WAIT_ACTIVATION_ANIMATION: Retail 0x002d977c-0x002d9798 waits for the activation timer, writes 2 to the same moby+0x20 byte dispatched at 0x002d971c, and selects animation 1 via 0x002d9800. State 2 at 0x002d979c tests animation flag bit 2 before advancing. SHA-bound source already declares HATCH_WAIT_ACTIVATION_ANIMATION=2 for this exact selector. domain_3_value_3 -> HATCH_WAIT_ACTIVATION_GATE_CLEAR: Retail 0x002d979c-0x002d97b0 waits on animation flag bit 2 and supplies value 3 for the store to moby+0x20 at 0x002d97f8. The same state byte selects case 3 at 0x002d97b4-0x002d97c4, which waits while external s16 +0x86 equals 0x14. Existing HATCH_WAIT_ACTIVATION_GATE_CLEAR=3 names this exact switch state. domain_4_value_4 -> HATCH_IDLE_AFTER_ACTIVATION_GATE_CLEAR: Retail 0x002d97b4-0x002d97e0 detects the activation gate s16 +0x86 differing from 0x14, selects animation 0, and writes 4 to moby+0x20. This is the same switch selector; SHA-bound source declares HATCH_IDLE_AFTER_ACTIVATION_GATE_CLEAR=4 and its branch only breaks, agreeing with original Ghidra's absence of work for state 4. domain_5_value_6 -> HATCH_WAIT_RESET_DELAY: Retail 0x002d97e4-0x002d9804 waits for animation flag bit 2, writes 6 to moby+0x20, and selects animation 2. This same byte is dispatched by the switch, whose existing HATCH_WAIT_RESET_DELAY=6 branch at 0x002d9810-0x002d9818 waits on fast_dec_timer(pvars+8). The source reset-delay helper also identifies state 6 as the active reset delay. domain_6_value_7 -> HATCH_WAIT_RESET_ANIMATION: Retail 0x002d9810-0x002d9834 waits for pvars+8 timer completion, selects animation 3, and stores 7 to the dispatched state byte moby+0x20. The existing HATCH_WAIT_RESET_ANIMATION=7 branch at 0x002d9838-0x002d9854 tests animation flag bit 2 then restores state 0 and animation 0, proving this assignment uses that same local state domain. domain_7_value_0 -> HATCH_WAIT_ACTIVATION: Retail 0x002d9838-0x002d9854 waits on animation flag bit 2 then stores zero to moby+0x20 and selects animation 0. That exact byte is dispatched at 0x002d971c; its existing HATCH_WAIT_ACTIVATION=0 branch at 0x002d9744-0x002d9778 tests pvars[0] and the external gate before initializing the activation delay. Thus the reset assignment reuses the established activation state. --- src/overlays/shared/enemies/plasmabot_hatch.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/shared/enemies/plasmabot_hatch.c b/src/overlays/shared/enemies/plasmabot_hatch.c index abd2fe9919..e68424c678 100644 --- a/src/overlays/shared/enemies/plasmabot_hatch.c +++ b/src/overlays/shared/enemies/plasmabot_hatch.c @@ -28,7 +28,7 @@ void plasmabot_hatch_update(struct Moby *moby) { HATCH_WAIT_RESET_ANIMATION = 7 }; char *hatch_private_vars = (char *)moby->pvars; - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { moby->collision = 0; } else { moby->collision = moby->pclass->collision; @@ -36,45 +36,45 @@ void plasmabot_hatch_update(struct Moby *moby) { switch (moby->state) { case HATCH_WAIT_ACTIVATION: if (*(s32 *)hatch_private_vars != 0 && *(s16 *)(D_L14_00167500 + 0x86) == 0x14) { - moby->state = 1; + moby->state = HATCH_WAIT_ACTIVATION_DELAY; *(s32 *)(hatch_private_vars + 8) = scale_game_frames(*(s32 *)(hatch_private_vars + 4)); } break; case HATCH_WAIT_ACTIVATION_DELAY: if (fast_dec_timer(hatch_private_vars + 8) != 0) { - moby->state = 2; + moby->state = HATCH_WAIT_ACTIVATION_ANIMATION; set_moby_animation(moby, 1, 0); } break; case HATCH_WAIT_ACTIVATION_ANIMATION: if ((moby->anim_flags & 2) != 0) { - moby->state = 3; + moby->state = HATCH_WAIT_ACTIVATION_GATE_CLEAR; set_moby_animation(moby, 2, 0); } break; case HATCH_WAIT_ACTIVATION_GATE_CLEAR: if (*(s16 *)(D_L14_00167500 + 0x86) != 0x14) { set_moby_animation(moby, 0, 0); - moby->state = 4; + moby->state = HATCH_IDLE_AFTER_ACTIVATION_GATE_CLEAR; } break; case HATCH_IDLE_AFTER_ACTIVATION_GATE_CLEAR: break; case HATCH_WAIT_ANIMATION_BEFORE_RESET_DELAY: if ((moby->anim_flags & 2) != 0) { - moby->state = 6; + moby->state = HATCH_WAIT_RESET_DELAY; set_moby_animation(moby, 2, 0); } break; case HATCH_WAIT_RESET_DELAY: if (fast_dec_timer(hatch_private_vars + 8) != 0) { set_moby_animation(moby, 3, 0); - moby->state = 7; + moby->state = HATCH_WAIT_RESET_ANIMATION; } break; case HATCH_WAIT_RESET_ANIMATION: if ((moby->anim_flags & 2) != 0) { - moby->state = 0; + moby->state = HATCH_WAIT_ACTIVATION; set_moby_animation(moby, 0, 0); } break; From 72a5f3cd55a57a3fd9c1c684e964122e87aeb267 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:03:33 +0000 Subject: [PATCH 0593/1502] decomp: clarify names in update_scoutbot_health_and_target domain_0_value_99 -> SCOUTBOT_STATE_EXPLODE_AND_REMOVE: Authoritative scoutbot.c snapshot SHA-256 82dac319cf83373f5c2fa80d5c2b88cd376aa2e0572f0bf43547ee3ff3d9ae21: scoutbot_update passes its own moby to update_scoutbot_health_and_target, then switches on that same moby->state. Its existing local enum names 0x63 SCOUTBOT_STATE_EXPLODE_AND_REMOVE; that branch calls explode_3DF8 and mark_moby_for_removal. Retail 0x002d36f4 preserves the moby argument in s0, 0x002d3748 loads s2=0x63, and 0x002d3794 stores s2 to state byte +0x20(s0) after damage subtraction/depleted-health handling at 0x002d3758-0x002d3770 and cleanup call 0x002d378c. Original Ghidra likewise shows *(undefined1 *)(iVar5+0x20)=99. Thus this assignment enters the exact scoutbot state consumed by that established explosion/removal branch, not the unrelated equal-valued hero state. --- src/overlays/shared/enemies/scoutbot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/scoutbot.c b/src/overlays/shared/enemies/scoutbot.c index f5b4aebfc3..6f4e342501 100644 --- a/src/overlays/shared/enemies/scoutbot.c +++ b/src/overlays/shared/enemies/scoutbot.c @@ -416,7 +416,7 @@ void scoutbot_update(Moby *moby) { /* Ported from rac1-decomp (src/overlays/shared/vendor_002D3DF8.c: func_L08_002D49E8), where it is exact; names translated to the US level program. */ void update_scoutbot_health_and_target(struct Moby *moby) { - ScoutbotVars *scoutbot_pvars = (ScoutbotVars *)moby->pvars; + enum { SCOUTBOT_STATE_EXPLODE_AND_REMOVE = 0x63 } ;ScoutbotVars *scoutbot_pvars = (ScoutbotVars *)moby->pvars; int hit; float dmg; int hit_reaction_code; @@ -430,7 +430,7 @@ void update_scoutbot_health_and_target(struct Moby *moby) { if (hit_reaction_code < 12) { if (hit_reaction_code >= 0) { FUN_L00_00257470(moby, 0, -1); - moby->state = 0x63; + moby->state = SCOUTBOT_STATE_EXPLODE_AND_REMOVE; } } } From 9eefd45b30ea2507b6c42bd18186bc1df88b9cdc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:03:33 +0000 Subject: [PATCH 0594/1502] decomp: clarify names in update_chicken_relocator domain_0_value_1 -> TARGET_CYCLE_WAIT_TO_TRIGGER: Bound C initializes the countdown in TARGET_CYCLE_INITIALIZE_DELAY and assigns this same moby->state to 1. Retail 0x002e89b0 loads s4=1, 0x002e8a00 stores s4 to 0x20(s2), and 0x002e89c4-0x002e89c8 dispatches that same byte to the distance/group/countdown wait branch at 0x002e8a04. This is the existing local TARGET_CYCLE_WAIT_TO_TRIGGER domain. domain_1_value_2 -> TARGET_CYCLE_POLL_STATUS: Retail 0x002e8a44-0x002e8a54 loads 2 and stores it to this relocator's state byte 0x20(s2) when its countdown expires, while calling request_target_reposition on the distinct target s3. The outer dispatch 0x002e89ec sends state 2 to 0x002e8a74, which polls get_target_reposition_status. Bound C already names that branch TARGET_CYCLE_POLL_STATUS. domain_2_value_1 -> TARGET_CYCLE_WAIT_TO_TRIGGER: In the outer TARGET_CYCLE_POLL_STATUS branch, inactive target status returns this relocator to state 1. Retail 0x002e8a74-0x002e8a80 tests the target helper return for zero and stores s4=1 to 0x20(s2). That same state byte is dispatched at 0x002e89c4-0x002e89c8 to the established TARGET_CYCLE_WAIT_TO_TRIGGER branch, not to the separate target status enum. domain_3_value_1 -> TARGET_CYCLE_WAIT_TO_TRIGGER: On target reposition-ready status, retail 0x002e8a84-0x002e8a8c stores s4=1 into the relocator's 0x20(s2) state byte before finding and repositioning a group chicken. The original Ghidra decompilation also restores param_1+0x20 to 1 here. Bound C's outer switch on that same moby->state names value 1 TARGET_CYCLE_WAIT_TO_TRIGGER. --- src/overlays/l16/mobys/chicken_relocator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l16/mobys/chicken_relocator.c b/src/overlays/l16/mobys/chicken_relocator.c index e6358b97b8..44be6ebcb8 100644 --- a/src/overlays/l16/mobys/chicken_relocator.c +++ b/src/overlays/l16/mobys/chicken_relocator.c @@ -219,14 +219,14 @@ void chicken_relocator_update(struct Moby *moby) { target = D_L16_0015FFD8 + (target_cycle_data->unk4 << 8); switch (moby->state) { case TARGET_CYCLE_INITIALIZE_DELAY: - moby->state = 1; + moby->state = TARGET_CYCLE_WAIT_TO_TRIGGER; target_cycle_data->timer_C = scale_game_frames(random_int_between(0xB4, 0x168)); break; case TARGET_CYCLE_WAIT_TO_TRIGGER: if (vector_distance_xy(hero_position, target + 0x10) > 3.0f) { if (find_group_chicken_in_state_6(*(int *)target_cycle_data) != 0) { if (fast_dec_timer(&target_cycle_data->timer_C)) { - moby->state = 2; + moby->state = TARGET_CYCLE_POLL_STATUS; request_target_reposition(target); target_cycle_data->timer_C = scale_game_frames(random_int_between(0xB4, 0x168)); } @@ -237,10 +237,10 @@ void chicken_relocator_update(struct Moby *moby) { target_status = get_target_reposition_status(target); switch (target_status) { case TARGET_STATUS_INACTIVE: - moby->state = 1; + moby->state = TARGET_CYCLE_WAIT_TO_TRIGGER; break; case TARGET_STATUS_REPOSITION_READY: - moby->state = 1; + moby->state = TARGET_CYCLE_WAIT_TO_TRIGGER; { char *moby_to_reposition = find_group_chicken_in_state_6(*(int *)target_cycle_data); if (moby_to_reposition != 0) { From 6502a3182e963bc2cb0705d368c9252faf8a1999 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:05:13 +0000 Subject: [PATCH 0595/1502] decomp: clarify names in update_mission_list domain_0_value_0 -> MISSION_STATE_UNAVAILABLE: The selected-level mission list is loaded at 0x0020b98c-0x0020b9a0. Its 0x28-byte records carry state at +0x24. When flags bit 4 requires a visit and level_visit_state is zero, 0x0020b9dc-0x0020b9ec stores 0 to that state; only state 1 contributes to available at 0x0020ba84-0x0020bab0. Thus this is the mission-entry unavailable state. domain_1_value_0 -> MISSION_STATE_UNAVAILABLE: Retail 0x0020b9f4 calls check_mission_condition with record kind1 at +2 and value1 at +4. A false return takes 0x0020ba04-0x0020ba08 and stores 0 at the same mission-entry state +0x24 used by visit gating. The available counter at 0x0020ba90 accepts only state 1, proving this failed prerequisite yields MISSION_STATE_UNAVAILABLE. domain_2_value_1 -> MISSION_STATE_AVAILABLE: After the first condition succeeds, 0x0020ba0c checks kind2/value2 at +8/+0xc; a false return falls through to 0x0020ba1c storing s3=1 at mission state +0x24. At 0x0020ba84-0x0020bab0 the same field is compared with 1 and entries without flag 2 increment D_001A2C10.available. This establishes the available mission-entry state. domain_3_value_2 -> MISSION_STATE_BOTH_CONDITIONS_MET: At 0x0020b9fc a nonzero first check permits the second check at 0x0020ba0c using +8/+0xc. Only a nonzero second return takes 0x0020ba14 and stores s1=2 at +0x24 in its delay slot 0x0020ba18. The visit gate also must have passed. This state therefore records that both mission conditions are met; no stronger lifecycle claim is required. domain_4_value_1 -> MISSION_STATE_AVAILABLE: Retail 0x0020ba84 loads comparison constant 1, 0x0020ba88 reads the mission-entry +0x24 state, and 0x0020ba90 rejects other states. After excluding flag 2, 0x0020baa8-0x0020bab0 increments the established available count at D_001A2C10+0xc. This comparison reuses exactly the available state assigned at 0x0020ba1c. --- src/game/missions/update_mission_list.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/game/missions/update_mission_list.c b/src/game/missions/update_mission_list.c index 8f11371d05..00853a9bb0 100644 --- a/src/game/missions/update_mission_list.c +++ b/src/game/missions/update_mission_list.c @@ -31,6 +31,11 @@ extern s32 check_mission_condition(s16, s32) __asm__("func_0020BAF0"); s32 update_mission_list(void) __asm__("FUN_0020b950"); s32 update_mission_list(void) { + enum { + MISSION_STATE_UNAVAILABLE = 0, + MISSION_STATE_AVAILABLE = 1, + MISSION_STATE_BOTH_CONDITIONS_MET = 2 + }; struct MenuItem *it; struct MenuItem *items; @@ -41,13 +46,13 @@ s32 update_mission_list(void) { } for (it = items; it->id != 0; it++) { if ((it->flags & 4) && level_visit_state[level_map_selection.level] == 0) { - it->state = 0; + it->state = MISSION_STATE_UNAVAILABLE; } else if (!check_mission_condition(it->kind1, it->value1)) { - it->state = 0; + it->state = MISSION_STATE_UNAVAILABLE; } else if (!check_mission_condition(it->kind2, it->value2)) { - it->state = 1; + it->state = MISSION_STATE_AVAILABLE; } else { - it->state = 2; + it->state = MISSION_STATE_BOTH_CONDITIONS_MET; } } for (it = D_001A2C10.items; it->id != 0; it++) { @@ -57,7 +62,7 @@ s32 update_mission_list(void) { } D_001A2C10.available = 0; for (it = D_001A2C10.items; it->id != 0; it++) { - if (it->state == 1 && !(it->flags & 2)) { + if (it->state == MISSION_STATE_AVAILABLE && !(it->flags & 2)) { D_001A2C10.available++; } } From a0a544163da52ef3b2ba263a7c052dea99ad8325 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:07:10 +0000 Subject: [PATCH 0596/1502] decomp: clarify names in volume_camera_swing_active domain_1_value_4 -> SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST: Retail 0x002ec804-0x002ec820 derives SwingCameraParams from the camera record's descriptor; 0x002ec830 loads params+0x2c, and 0x002ec85c-0x002ec868 sign-extends that same type and compares it with 4. Thus this is a swing-camera parameter type, not hero state 4. At 0x002ec878-0x002ec888, hero_requested_camera_mode[0] == 3 and params+0x2e timer > 0 set s1. For each configured nonnegative volume/path, 0x002ec898, 0x002ec8c0, 0x002ec8e8, 0x002ec910 and 0x002ec938 return active when s1 is set, bypassing the membership call. This proves camera-request-dependent retention outside the volume once started. The checked caller 0x002ec988 calls this predicate at 0x002eca18 and clears the timer and current volume on false; its type 2/4 branch clamps the timer at 200 scaled frames and continues applying the angle. The semantic name is restricted to the observed request-retention role; mode 3's gameplay identity is not claimed. --- src/overlays/shared/camera/swing_volume_camera.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/camera/swing_volume_camera.c b/src/overlays/shared/camera/swing_volume_camera.c index 479f603bbf..f8f29a4c34 100644 --- a/src/overlays/shared/camera/swing_volume_camera.c +++ b/src/overlays/shared/camera/swing_volume_camera.c @@ -90,6 +90,9 @@ f32 D_L17_001677B4 NOT_SDA = 0; s32 volume_camera_swing_active(struct UpdateCam *cam) __asm__("FUN_L00_002ec7e8"); s32 volume_camera_swing_active(struct UpdateCam *swing_camera_record) { + enum { + SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST = 4 + }; SwingCameraParams *params; s32 forced = 0; u16 type; @@ -101,7 +104,7 @@ s32 volume_camera_swing_active(struct UpdateCam *swing_camera_record) { type = *(u16 *)¶ms->type; if (params->type == 2 && D_001413DC == 0x1A && params->timer > 0) { forced = 1; - } else if ((s16)type == 4 && hero_requested_camera_mode[0] == 3) { + } else if ((s16)type == SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST && hero_requested_camera_mode[0] == 3) { forced = 0 < params->timer; } if (params->clip_volume >= 0 && From c8db66f73d6a3bd36768bdbe4b99fa162cd1e586 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:07:10 +0000 Subject: [PATCH 0597/1502] decomp: clarify names in handle_sharkigator_hit domain_0_value_12 -> SHARKIGATOR_HIT_KNOCKBACK_RECOVERY: Retail 0x0030e9b4 saves the moby in s0; 0x0030ea34..0x0030ea40 starts hit knockback with its pvars+0x70 and hit_record+0x10. 0x0030ea48 loads 12 and 0x0030ea70 stores it at moby+0x20, the same current-state byte switched on in supplied sharkigator_update. That caller already names state 12 SHARKIGATOR_HIT_KNOCKBACK_RECOVERY and steps motion at pvars+0x70 until returning to idle. This is current moby state, not the hit_reaction selector or water-gap control domain. domain_1_value_13 -> SHARKIGATOR_HIT_ANIMATION_RECOVERY: Retail 0x0030ea4c..0x0030ea68 checks moby animation sequence 4 and blends (4,4,4); 0x0030ea6c loads 13 and 0x0030ea70 stores it at s0+0x20 on the original moby. Supplied sharkigator_update switches on that same current-state byte and already names 13 SHARKIGATOR_HIT_ANIMATION_RECOVERY, returning to idle when moby+0x70 bit 2 indicates animation completion. Original Ghidra agrees with the sequence branch and state store. domain_2_value_14 -> SHARKIGATOR_DEATH_FALL_AND_REMOVE: Retail 0x0030ea84..0x0030ea94 compares health with hit_record+0x2C damage. The lethal branch clears health and flag 0x1000, starts death knockback at 0x0030eab0, then loads 14 at 0x0030eadc and stores it to the original moby+0x20 at 0x0030eae4. Supplied sharkigator_update switches on this same current-state byte, already names state 14 SHARKIGATOR_DEATH_FALL_AND_REMOVE, steps pvars+0x70 motion, spawns an explosion and removes the moby. Original Ghidra also guards against processing hits in state 14. --- src/overlays/l07/mobys/sharkigator.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/overlays/l07/mobys/sharkigator.c b/src/overlays/l07/mobys/sharkigator.c index 02d85c46fe..35c67949ba 100644 --- a/src/overlays/l07/mobys/sharkigator.c +++ b/src/overlays/l07/mobys/sharkigator.c @@ -420,6 +420,11 @@ void handle_sharkigator_hit(struct Moby *moby, char *x, float *hp) { SHARKIGATOR_ALTERNATE_HIT_ANIMATION_RESPONSE = 10, HIT_REACTION_NO_ANIMATION_RESPONSE = 11 }; + enum { + SHARKIGATOR_HIT_KNOCKBACK_RECOVERY = 0xC, + SHARKIGATOR_HIT_ANIMATION_RECOVERY = 0xD, + SHARKIGATOR_DEATH_FALL_AND_REMOVE = 0xE + }; char *hit_record; int hit; int hit_reaction_result; @@ -442,14 +447,14 @@ void handle_sharkigator_hit(struct Moby *moby, char *x, float *hp) { case SHARKIGATOR_LAUNCH_HIT_KNOCKBACK_RECOVERY: case SHARKIGATOR_ENTER_HIT_KNOCKBACK_RECOVERY: start_sharkigator_hit_knockback(moby, x + 0x70, hit_record + 0x10); - moby->state = 0xC; + moby->state = SHARKIGATOR_HIT_KNOCKBACK_RECOVERY; break; case SHARKIGATOR_HIT_ANIMATION_RESPONSE: case SHARKIGATOR_ALTERNATE_HIT_ANIMATION_RESPONSE: if (((unsigned char *)moby)[0x53] != 4) { blend_moby_animation(moby, 4, 4, 4); } - moby->state = 0xD; + moby->state = SHARKIGATOR_HIT_ANIMATION_RECOVERY; break; case HIT_REACTION_NO_ANIMATION_RESPONSE: break; @@ -462,7 +467,7 @@ void handle_sharkigator_hit(struct Moby *moby, char *x, float *hp) { FUN_L00_00257470(moby, 0, -1); x[0x67] = 0x78; trooper_anim_update(moby, (short *)(x + 0x60)); - moby->state = 0xE; + moby->state = SHARKIGATOR_DEATH_FALL_AND_REMOVE; } else { *hp -= *(float *)(hit_record + 0x2C); ((unsigned char *)x)[0x67] = 0xFA; From 61746a158371a4436b87c4db6bdddd8194ed2476 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:07:10 +0000 Subject: [PATCH 0598/1502] decomp: clarify names in update_jittered_quad_layers domain_0_value_1 -> QUEUE_DRAW_AND_MONITOR_LINKED_MOBY: The assignment targets moby->state, the same byte loaded at retail 003081cc (+0x20 of s0). Retail 0030822c-00308234 stores 1 after the persistence check; 003081d8-003081dc dispatches that exact value to 00308238, which queues drawing and monitors the linked moby. The source already names this exact selector's case 1 QUEUE_DRAW_AND_MONITOR_LINKED_MOBY; reuse its canonical local member. domain_1_value_2 -> DRAW_AND_MONITOR_DISABLED: Retail 003082ec-003082f8 tests the linked moby's state byte for 7. After persistence clearing and the (1,0,moby) voice request, 00308328-00308330 stores 2 to this moby's state +0x20 and clears collision +0x94. On later updates 003081cc-003081e4 dispatches only 0 or 1, returning for 2 before the draw callback, voice handling and linked-moby monitoring. Thus this state disables this function's draw and monitor processing; the source has no state-2 handler. --- src/overlays/l12/mobys/jittered_quad_layers.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l12/mobys/jittered_quad_layers.c b/src/overlays/l12/mobys/jittered_quad_layers.c index f012d2a14f..10004151a3 100644 --- a/src/overlays/l12/mobys/jittered_quad_layers.c +++ b/src/overlays/l12/mobys/jittered_quad_layers.c @@ -35,6 +35,9 @@ void jittered_quad_layers_update(struct Moby *moby) { CHECK_PERSISTENT_REMOVAL = 0, QUEUE_DRAW_AND_MONITOR_LINKED_MOBY = 1 }; + enum { + DRAW_AND_MONITOR_DISABLED = 2 + }; int moby_state_snapshot = moby->state; int vis; int *moby_data = (int *)moby->pvars; @@ -45,7 +48,7 @@ void jittered_quad_layers_update(struct Moby *moby) { mark_moby_for_removal(moby); break; } - moby->state = 1; + moby->state = QUEUE_DRAW_AND_MONITOR_LINKED_MOBY; break; case QUEUE_DRAW_AND_MONITOR_LINKED_MOBY: vis = 1; @@ -74,7 +77,7 @@ void jittered_quad_layers_update(struct Moby *moby) { } FUN_0022da68(1, 0, moby); moby->collision = 0; - moby->state = 2; + moby->state = DRAW_AND_MONITOR_DISABLED; } } break; From 7c180b72fbcf9d8247af15f1b9f5aa35758c4e45 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:07:10 +0000 Subject: [PATCH 0599/1502] decomp: clarify names in update_menu_preview_class_pose domain_0_value_0 -> PREVIEW_BINDING_STATE_RESET: The authoritative source assigns zero to moby->binding_state only in reset_bindings, derived from preview_class_records[i].normalize_basis == 0. Retail 0x00224c54-0x00224c60 computes this zero gate and 0x00224ca0 skips the reset when it is false. At 0x00224cc8 and 0x00224cd0 both binding pointers (+0x6c/+0x68) are restored to 0x001863d0; 0x00224ccc clears the +0x50 blend word, and 0x00224cd4 clears the +0x54 binding-state word. Original Ghidra identifies that latter word's bytes as primary/secondary binding indices/selectors. This proves a preview binding reset value, without assuming an animation or moby-state enum. --- src/ui/menus/item_preview/update_menu_preview_class_pose.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/menus/item_preview/update_menu_preview_class_pose.c b/src/ui/menus/item_preview/update_menu_preview_class_pose.c index 569d537155..be599f3209 100644 --- a/src/ui/menus/item_preview/update_menu_preview_class_pose.c +++ b/src/ui/menus/item_preview/update_menu_preview_class_pose.c @@ -33,7 +33,7 @@ extern void attach_manipulator(int, int, void *) __asm__("FUN_0020cb void update_menu_preview_class_pose(void *preview) __asm__("FUN_00224b70"); void update_menu_preview_class_pose(void *preview) { - PauseMoby *moby = preview; + enum { PREVIEW_BINDING_STATE_RESET = 0 } ;PauseMoby *moby = preview; struct Moby *anim = preview; f32 transform[16]; s32 source_moby_address = (s32)((struct MenuScreen *)*moby->vars)->data.preview.moby; @@ -75,7 +75,7 @@ void update_menu_preview_class_pose(void *preview) { moby->binding_blend_word = 0; moby->secondary_binding = (char *)menu_item_info; anim->anim_speed = 0; - moby->binding_state = 0; + moby->binding_state = PREVIEW_BINDING_STATE_RESET; } if (attachment_active) { attach_manipulator(source_moby_address, 0, attachment); From dce21aa16e6324522aeb0348c3269f9fc067da51 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:07:10 +0000 Subject: [PATCH 0600/1502] decomp: clarify names in dec_bs0 domain_0_value_1 -> DEC_BS0_COMPLETED: In source src/movies/decoder/dec_bs0.c (SHA-256 7502dcd6c1d68ac4ac05ee729fbd7ec939b0e7023b34b0e67451443c8da2300a), status initializes to 1 and is returned after sceMpegReset. Retail 0x0023cecc/0x0023cf00 initializes the stack return slot to 1; sceMpegIsEnd at 0x0023d008 branches to reset at 0x0023d040 when the stream ends, and 0x0023d048 reloads that slot for return. Only the abort path replaces it with -1 at 0x0023d034-0x0023d03c. Thus 1 denotes completed decoding-loop termination, independently of picture-error logging at 0x0023cf44-0x0023cf4c, and is not a VideoDecState member. --- src/movies/decoder/dec_bs0.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/movies/decoder/dec_bs0.c b/src/movies/decoder/dec_bs0.c index 5a947d5843..3ad58a17e0 100644 --- a/src/movies/decoder/dec_bs0.c +++ b/src/movies/decoder/dec_bs0.c @@ -20,8 +20,11 @@ extern char mpeg_get_picture_decode_error_message[] __asm__("D_001E8B50"); int dec_bs0(struct VideoDec *vd) __asm__("FUN_0023cec8"); int dec_bs0(struct VideoDec *vd) { + enum { + DEC_BS0_COMPLETED = 1 + }; struct VoData *voData; - int status = 1; + int status = DEC_BS0_COMPLETED; int i; while (!sceMpegIsEnd(&vd->mpeg)) { From d3034ac386923ce409ff53812f260ec69e84fbca Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:07:10 +0000 Subject: [PATCH 0601/1502] decomp: clarify names in energy_sphere_update domain_0_value_1 -> ENERGY_SPHERE_UPDATE_ROTATION: Retail 0x002f7ae4 loads the current state byte at sphere_moby+0x20; 0x002f7b5c-0x002f7b60 compares that same state with 1 and branches to rotation updates at 0x002f7bbc-0x002f7c24. Initialization loads 1 into v1 at 0x002f7b90 and stores it to the identical state byte at 0x002f7ba8, then falls through to those updates. Original Ghidra confirms the same read/store flow, and authoritative C already names case 1 ENERGY_SPHERE_UPDATE_ROTATION in this exact sphere_moby->state domain. --- src/overlays/shared/props/energy_sphere.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/props/energy_sphere.c b/src/overlays/shared/props/energy_sphere.c index a208225041..e1c42a523b 100644 --- a/src/overlays/shared/props/energy_sphere.c +++ b/src/overlays/shared/props/energy_sphere.c @@ -124,7 +124,7 @@ void energy_sphere_update(struct Moby *sphere_moby) { set_moby_color(sphere_moby, 0x80, 0x80, 0x80); sphere_moby->scale = sphere_moby->pclass->scale * D_L06_00161E80; *(char **)sphere_vars = sphere_vars + 0x20; - sphere_moby->state = 1; + sphere_moby->state = ENERGY_SPHERE_UPDATE_ROTATION; sphere_moby->flags |= 0x20; *(int *)(sphere_vars + 0x60) = -1; case ENERGY_SPHERE_UPDATE_ROTATION: { From f3a94635c4ab93b3490a5af6a82ec83d254ac853 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:09:04 +0000 Subject: [PATCH 0602/1502] decomp: clarify names in update_menu_preview_pose_and_attachments domain_0_value_0 -> MENU_PREVIEW_BINDING_SELECTION_RESET: Authoritative source assigns moby->binding_state = 0 after publishing both binding pointers. Retail 0x00224f3c/0x00224f44 installs the same table at preview +0x6C/+0x68, then 0x00224f90 executes sw zero,0x54(s1). The supplied original Ghidra maps this cleared word to bPrimary_binding_index, bSecondary_binding_index, bPrimary_binding_selector, and bSecondary_binding_selector, each assigned zero. Thus this value resets the packed binding selection; it is not inferred to be a moby state. --- .../item_preview/update_menu_preview_pose_and_attachments.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/menus/item_preview/update_menu_preview_pose_and_attachments.c b/src/ui/menus/item_preview/update_menu_preview_pose_and_attachments.c index cc092958b8..2bcf29e316 100644 --- a/src/ui/menus/item_preview/update_menu_preview_pose_and_attachments.c +++ b/src/ui/menus/item_preview/update_menu_preview_pose_and_attachments.c @@ -23,6 +23,9 @@ extern void attach_manipulator(int, int, void *) __asm__("FUN_0020cb10"); void update_menu_preview_pose_and_attachments(void *preview) __asm__("FUN_00224e18"); void update_menu_preview_pose_and_attachments(void *preview) { + enum { + MENU_PREVIEW_BINDING_SELECTION_RESET = 0 + }; PauseMoby *moby = preview; char **preview_vars = moby->vars; f32 transform[16]; @@ -79,7 +82,7 @@ void update_menu_preview_pose_and_attachments(void *preview) { first_attachment_manipulator.rotation_z = 0; } moby->binding_blend_word = 0; - moby->binding_state = 0; + moby->binding_state = MENU_PREVIEW_BINDING_SELECTION_RESET; } extern __typeof__(update_menu_preview_pose_and_attachments) func_00224E18 From 95239adad7deafbe0359f851ec76a298a19a6150 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:09:04 +0000 Subject: [PATCH 0603/1502] decomp: clarify names in try_start_kerwan_path_enemy_heading_turn domain_0_value_12 -> ENEMY_TURN_TO_HEADING: Retail 0x002c6f90 stores desired_heading (f21) to enemy pvars+0x28C; 0x002c6f94 loads 12 and 0x002c6f9c-0x002c6fa8 saves the old moby state byte from +0x20 to +0xBC while writing 12 to +0x20. Original Ghidra shows the same stores. The supplied update_kerwan_path_enemy passes this same enemy m into the helper, switches on m->state, and defines ENEMY_TURN_TO_HEADING = 12. Its corresponding branch approaches moby_data->f28C, tests yaw convergence, and resumes saved movement state or idle. Thus this is the enemy heading-turn state, not HeroStateId or an animation/control selector. --- src/overlays/l03/mobys/kerwan_path_enemy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l03/mobys/kerwan_path_enemy.c b/src/overlays/l03/mobys/kerwan_path_enemy.c index 086f353306..1170e4fe59 100644 --- a/src/overlays/l03/mobys/kerwan_path_enemy.c +++ b/src/overlays/l03/mobys/kerwan_path_enemy.c @@ -43,7 +43,7 @@ int try_start_kerwan_path_enemy_heading_turn(float desired_heading, struct Moby *moby, struct Moby *target) { - KerwanPathEnemyVars *enemy_pvars = (KerwanPathEnemyVars *)moby->pvars; + enum { ENEMY_TURN_TO_HEADING = 0xC } ;KerwanPathEnemyVars *enemy_pvars = (KerwanPathEnemyVars *)moby->pvars; int linked_moby_index; float heading_delta; unsigned char previous_state; @@ -72,7 +72,7 @@ int try_start_kerwan_path_enemy_heading_turn(float desired_heading, } enemy_pvars->unk28C = desired_heading; previous_state = moby->state; - moby->state = 0xC; + moby->state = ENEMY_TURN_TO_HEADING; moby->command = previous_state; return 1; } From 88f95691286c1e13d088c183a7b56ae4a5985dfc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:09:05 +0000 Subject: [PATCH 0604/1502] decomp: clarify names in codebot_update domain_0_value_1 -> CODEBOT_CHECK_HERO_PROXIMITY: Retail 0x002ebd90 preserves the moby pointer in s0; 0x002ebdd0 loads its state byte at +0x20 and 0x002ebdd8 dispatches value 1 to 0x002ebe54. Initialization stores 1 into that identical byte at 0x002ebe44. The destination branch updates sprites and compares moby+0x10 against hero position with distance <3.0 at 0x002ebe60-0x002ebe84. This is the existing CODEBOT_CHECK_HERO_PROXIMITY case in the authoritative switch, proving the assignment shares that exact local enum domain. domain_1_value_2 -> CODEBOT_RECORD_COLLECTION: Retail 0x002ebeac/0x002ebeb4 stores 2 to s0+0x20 after the proximity branch calls start_scene(1). The same byte is loaded at 0x002ebdd0 and value 2 dispatches at 0x002ebdfc to 0x002ebeb8. That branch queues dialogue, sets persistent collection bytes at 0x002ebeec and 0x002ebef4, and calls memcard_save_data at 0x002ebefc; initialization reads the same collection byte at 0x002ebe20. The source already names this exact moby->state case CODEBOT_RECORD_COLLECTION, so reuse that member for its incoming assignment. domain_2_value_3 -> CODEBOT_REMOVE: Retail 0x002ebee8 loads 3 and 0x002ebf00 stores it to the moby state byte s0+0x20 during collection recording. The next update loads this same byte at 0x002ebdd0; 0x002ebe00/0x002ebe04 dispatch value 3 to 0x002ebf0c, which only calls mark_moby_for_removal with s0. This is the existing CODEBOT_REMOVE case of the same moby->state switch, proving reuse of that local enum member. --- src/overlays/shared/pickups/codebot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/pickups/codebot.c b/src/overlays/shared/pickups/codebot.c index 240629c3ea..4222fe82e0 100644 --- a/src/overlays/shared/pickups/codebot.c +++ b/src/overlays/shared/pickups/codebot.c @@ -61,7 +61,7 @@ void codebot_update(struct Moby *moby) { if (alternate_item_available[2] != 0) { mark_moby_for_removal(moby); } else { - moby->state = 1; + moby->state = CODEBOT_CHECK_HERO_PROXIMITY; moby->pos.z += 1.0f; } break; @@ -71,7 +71,7 @@ void codebot_update(struct Moby *moby) { if (hero.state.current != 0x32) { moby->flags |= 0x41; start_scene(1); - moby->state = 2; + moby->state = CODEBOT_RECORD_COLLECTION; } } break; @@ -82,7 +82,7 @@ void codebot_update(struct Moby *moby) { collection_flags = alternate_item_available; collection_flags[2] = 1; collection_flags[0x78] = 1; - moby->state = 3; + moby->state = CODEBOT_REMOVE; memcard_save_data(0, -1); } break; From 2b240b6f15cb8d9fdbee92f45e959d6154aed4cc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:09:05 +0000 Subject: [PATCH 0605/1502] decomp: clarify names in process_blarg_space_fighter_damage domain_0_value_3 -> FIGHTER_EMIT_DESTRUCTION_EFFECTS: Retail 0x002c380c loads this fighter moby's state byte at +0x20; 0x002c37e4/0x002c3810 compares it with 3 to skip further hit processing. Checked caller request 31cf24f3b7874f158dbedd91f14a1948 shows the same moby in s5 passed at 0x002c4684..0x002c4690, with its +0x20 state dispatched at 0x002c449c..0x002c44bc. Authoritative update_blarg_space_fighter names this exact state FIGHTER_EMIT_DESTRUCTION_EFFECTS=3 and emits effects/pickups before advancing to state 4. This is the fighter state domain, not HeroStateId or the hit_reaction return domain. domain_1_value_2 -> HIT_PROCESSING_DAMAGE_THRESHOLD: Retail 0x002c3838 passes sp+0x10 as hit_reaction's fifth output argument; 0x002c3878..0x002c3880 tests that output against 2, skipping all health comparison/subtraction and hit displacement when below it. Thus 2 is the inclusive damage-processing threshold. Checked helper request 45a5026fc11440f781b853d879d83b70 confirms t0 saved as s3 at 0x00266510, status zero initialization at 0x00266558, status 1 on the null-hit path at 0x00266634 and suppressed damage at 0x002669d4..0x002669e0, and normal classification status 2 written through s3 at 0x002668c0..0x002668c8. Other classification paths write 3/4, so the threshold name preserves the >= semantics without conflating status and return enums. domain_2_value_3 -> FIGHTER_EMIT_DESTRUCTION_EFFECTS: Retail 0x002c3888..0x002c3898 compares remaining fighter health against hit_record+0x2c; the exhausted-health path zeros health at 0x002c38a0, clears flag 0x1000 and writes 3 to this moby's +0x20 state at 0x002c38c0..0x002c38c8. Checked caller request 31cf24f3b7874f158dbedd91f14a1948 confirms this is the moby passed at 0x002c468c and whose state byte drives the caller switch. Authoritative update_blarg_space_fighter establishes FIGHTER_EMIT_DESTRUCTION_EFFECTS=3 for that same selector and handles it by releasing the voice, emitting destruction effects and spawning pickups before state 4. Reuse the same state name as the initial exclusion guard. --- src/overlays/l13/mobys/blarg_space_fighter.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l13/mobys/blarg_space_fighter.c b/src/overlays/l13/mobys/blarg_space_fighter.c index 8b9f1d0727..3b8214f1c4 100644 --- a/src/overlays/l13/mobys/blarg_space_fighter.c +++ b/src/overlays/l13/mobys/blarg_space_fighter.c @@ -83,7 +83,11 @@ void process_blarg_space_fighter_damage(struct Moby *moby, unsigned char *moby_d HIT_REACTION_HIGH_INTERPOLATION_TARGET_ALTERNATE = 10, HIT_REACTION_NO_HIT = 11 }; - if (moby->state != 3) { + enum { + HIT_PROCESSING_DAMAGE_THRESHOLD = 2, + FIGHTER_EMIT_DESTRUCTION_EFFECTS = 3 + }; + if (moby->state != FIGHTER_EMIT_DESTRUCTION_EFFECTS) { int hit_processing_status; float hit_position_offset[4]; char *hit_record = find_moby_hit(moby, 0x330000, 0); @@ -104,13 +108,13 @@ void process_blarg_space_fighter_damage(struct Moby *moby, unsigned char *moby_d case HIT_REACTION_NO_HIT: break; } - if (hit_processing_status >= 2) { + if (hit_processing_status >= HIT_PROCESSING_DAMAGE_THRESHOLD) { if (*fp <= *(float *)(hit_record + 0x2C)) { *fp = 0; moby->flags &= 0xEFFF; moby_data[0x67] = 0x78; trooper_anim_update(moby, (short *)(moby_data + 0x60)); - moby->state = 3; + moby->state = FIGHTER_EMIT_DESTRUCTION_EFFECTS; } else { *fp = *fp - *(float *)(hit_record + 0x2C); moby_data[0x67] = 0xFA; From 24a3022763ef21cf0e257350592c52b01662f317 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:09:05 +0000 Subject: [PATCH 0606/1502] decomp: clarify names in update_bolt_thief_path_movement domain_0_value_5 -> BOLT_THIEF_STATE_FOLLOW_SECONDARY_PATH: The authoritative source (SHA-256 9e00318adfa60421b07bfed1fcd88b62484c1a4a84668f2118069771474e3eb0) defines BOLT_THIEF_STATE_FOLLOW_SECONDARY_PATH=5 in bolt_thief_update. Retail 0x002feaf4 loads the current moby state byte at +0x20; 0x002feaf8-0x002feb04 compare it with 5 and select pvars+0xDC, otherwise +0xD8, before indexing l14_paths and sampling at 0x002feb28. Original Ghidra confirms the same byte comparison and path selection. Checked caller 0x002fe2a0 preserves its moby in s1, dispatches on that same +0x20 byte at 0x002fe428-0x002fe450, writes 5 to it at 0x002fe7a8 after settling and resets sampler progress at 0x002fe7bc/0x002fe7c4. Its secondary-path branch calls this function with the same moby at 0x002fe7c8/0x002fe7cc; completion returns to state 2 and resets to the primary path at 0x002fe7dc-0x002fe82c. Thus this is the same bolt-thief current-state domain and canonical secondary-path member, not the separate mode field at pvars+0xFC. --- src/overlays/l14/mobys/bolt_thief.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/bolt_thief.c b/src/overlays/l14/mobys/bolt_thief.c index 48a9913dae..0b89fcd150 100644 --- a/src/overlays/l14/mobys/bolt_thief.c +++ b/src/overlays/l14/mobys/bolt_thief.c @@ -334,7 +334,7 @@ typedef struct BoltThiefVars { } BoltThiefVars; int update_bolt_thief_path_movement(struct Moby *moby) { - float pos[4]; + enum { BOLT_THIEF_STATE_FOLLOW_SECONDARY_PATH = 5 } ;float pos[4]; float delta[4]; BoltThiefVars *bolt_thief_state = (BoltThiefVars *)moby->pvars; float path_sample_step = bolt_thief_default_path_sample_rate_gp * frame_time; @@ -344,7 +344,7 @@ int update_bolt_thief_path_movement(struct Moby *moby) { path_sample_step = frame_time * 20.0f; if (bolt_thief_state->unkF8 != 0.0f) path_sample_step = bolt_thief_state->unkF8 * frame_time; - if (moby->state == 5) + if (moby->state == BOLT_THIEF_STATE_FOLLOW_SECONDARY_PATH) path = ((char *)l14_paths[bolt_thief_state->path_DC]); else path = ((char *)l14_paths[bolt_thief_state->path_D8]); From c4e1efe8f475daec89ddf9defcdc54a17a1f2f0b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:09:05 +0000 Subject: [PATCH 0607/1502] decomp: clarify names in PrepareMpegPictureFieldTransfers domain_0_value_1 -> MPEG_PICTURE_STATUS_OUTPUT_READY: Retail a1 is preserved in s2 at 0x00129e3c; 0x00129f10 loads its MpegPictureBuffer status at +0x28 and 0x00129f14 requires equality to 1. Together with the second field status and _isOutSizeOK this admits the doubled-height copy/CSC path at 0x00129f28-0x00129f6c and FinishMpegReferenceImage at 0x00129f88. Thus this value is the paired picture's ready-for-output status in this function, without claiming a decode lifecycle. domain_1_value_1 -> MPEG_PICTURE_STATUS_OUTPUT_READY: Retail a2 is preserved in s5 at 0x00129e18; 0x00129f1c loads the same MpegPictureBuffer status field +0x28 for the second image. 0x00129f20 compares it with v1, already established as 1 by the first field check. Only both output-ready statuses allow copy/CSC and finalization. The supplied _outputFrame passes paired ref_images[4]/[8] or [7]/[11], proving these selectors share the picture-buffer status domain. --- src/sdk/mpeg/ref_images/disprefimagefield.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sdk/mpeg/ref_images/disprefimagefield.c b/src/sdk/mpeg/ref_images/disprefimagefield.c index 63982dc4b9..44d188fb88 100644 --- a/src/sdk/mpeg/ref_images/disprefimagefield.c +++ b/src/sdk/mpeg/ref_images/disprefimagefield.c @@ -76,6 +76,9 @@ void PrepareMpegPictureFieldTransfers(struct MpegFieldTransferState *state, struct MpegPictureBuffer *first_field_ref_image, struct MpegPictureBuffer *second_field_ref_image) { + enum { + MPEG_PICTURE_STATUS_OUTPUT_READY = 1 + }; s64 first_flags, second_flags; s32 timestamp; s32 second_timestamp; @@ -126,8 +129,8 @@ void PrepareMpegPictureFieldTransfers(struct MpegFieldTransferState *state, state->horizontal_offset1 = secondary->horizontal_offset1; state->vertical_offset0 = primary->vertical_offset0; state->vertical_offset1 = secondary->vertical_offset1; - if (_isOutSizeOK(state, first_field_ref_image) && first_field_ref_image->status == 1 && - second_field_ref_image->status == 1) { + if (_isOutSizeOK(state, first_field_ref_image) && first_field_ref_image->status == MPEG_PICTURE_STATUS_OUTPUT_READY && + second_field_ref_image->status == MPEG_PICTURE_STATUS_OUTPUT_READY) { first_field_ref_image->macroblock_height *= 2; if (state->decoder_initialized) _csc_storeRefImage(state, first_field_ref_image); From 1b0f059e7201b2f96f52c0e3ef3d04287aeae692 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:10:59 +0000 Subject: [PATCH 0608/1502] decomp: clarify names in sandshark_egg_update domain_0_value_2 -> SANDSHARK_EGG_HANDOFF_TO_LINKED_MOBY: Retail 002e0290 retains the input moby in s0; 002e02a8 reads its current state byte at +0x20. After step_moby_motion at 002e02d4, 002e02dc tests return bit 1, 002e02e4 loads 2 and 002e02e8 stores it to the same +0x20 state byte. Retail 002e02b4-002e02b8 dispatches that same state value 2 to 002e03c0, where pvars+0x60 provides the linked moby. 002e03c4-002e03d0 copies the egg position to it; initialization and update follow, then 002e0418 removes the egg. The original Ghidra decompilation corroborates these identical state-field reads and write. The authoritative C already names that switch branch SANDSHARK_EGG_HANDOFF_TO_LINKED_MOBY=2, proving reuse within this exact local moby->state domain rather than merely numeric equivalence. --- src/overlays/l02/mobys/sandshark_egg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l02/mobys/sandshark_egg.c b/src/overlays/l02/mobys/sandshark_egg.c index 7561d06bb3..e7bf3f32d3 100644 --- a/src/overlays/l02/mobys/sandshark_egg.c +++ b/src/overlays/l02/mobys/sandshark_egg.c @@ -44,7 +44,7 @@ void sandshark_egg_update(struct Moby *moby) { case SANDSHARK_EGG_FALL_UNTIL_LANDING: clear_u64_value(u); if (step_moby_motion(moby, egg_vars) & 1) { - moby->state = 2; + moby->state = SANDSHARK_EGG_HANDOFF_TO_LINKED_MOBY; } vp = v; i = 2; From 80acc4b02e10e211de2d5029aa81c1bd1de27734 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:10:59 +0000 Subject: [PATCH 0609/1502] decomp: clarify names in grindrail_barrier_update domain_0_value_1 -> GRINDRAIL_BARRIER_STATE_COLLISION_ENABLED: The initialization assignment writes barrier_moby->state, the exact selector of the existing local enum switch. Retail s1 retains the moby at 0x002e5714; 0x002e571c loads s0=1 and 0x002e576c stores it to state +0x20. The same value dispatches to the enabled branch at 0x002e5730-0x002e5734 and is restored with class collision at 0x002e58a0-0x002e58ac, proving reuse of GRINDRAIL_BARRIER_STATE_COLLISION_ENABLED. domain_1_value_2 -> GRINDRAIL_BARRIER_STATE_COLLISION_DISABLED: This assignment targets barrier_moby->state, the same selector already using the local collision-state enum. Retail 0x002e5874 loads 2, 0x002e5878 clears moby collision at +0x94, and 0x002e587c stores 2 to state +0x20 after the release predicate succeeds. Dispatch of state 2 reaches 0x002e5890, whose inverse predicate restores class collision. This proves the existing GRINDRAIL_BARRIER_STATE_COLLISION_DISABLED member. domain_2_value_1 -> GRINDRAIL_BARRIER_STATE_COLLISION_ENABLED: Within the existing COLLISION_DISABLED branch, the false release predicate at 0x002e5890-0x002e5898 permits 0x002e58a0 to store s0=1 to the same moby state byte +0x20 read by dispatch. Retail 0x002e58a4-0x002e58ac then loads pclass +0x10 and restores collision +0x94. This directly proves reuse of the switch's existing GRINDRAIL_BARRIER_STATE_COLLISION_ENABLED member. --- src/overlays/shared/props/grindrail_barrier.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/props/grindrail_barrier.c b/src/overlays/shared/props/grindrail_barrier.c index 4680f66cdf..0327d7f7c3 100644 --- a/src/overlays/shared/props/grindrail_barrier.c +++ b/src/overlays/shared/props/grindrail_barrier.c @@ -86,7 +86,7 @@ void grindrail_barrier_update(struct Moby *barrier_moby) { float *cardinal_angles; switch (barrier_moby->state) { case GRINDRAIL_BARRIER_STATE_INITIALIZE: - barrier_moby->state = 1; + barrier_moby->state = GRINDRAIL_BARRIER_STATE_COLLISION_ENABLED; barrier_moby->update_dist = 0xFF; break; case GRINDRAIL_BARRIER_STATE_COLLISION_ENABLED: @@ -111,13 +111,13 @@ void grindrail_barrier_update(struct Moby *barrier_moby) { if (barrier_data->unk20 != -1 && check_grindrail_barrier_release_condition(barrier_data->unk20)) { barrier_moby->collision = 0; - barrier_moby->state = 2; + barrier_moby->state = GRINDRAIL_BARRIER_STATE_COLLISION_DISABLED; group_trigger_nearest(barrier_data->unk20); } break; case GRINDRAIL_BARRIER_STATE_COLLISION_DISABLED: if (!check_grindrail_barrier_release_condition(barrier_data->unk20)) { - barrier_moby->state = 1; + barrier_moby->state = GRINDRAIL_BARRIER_STATE_COLLISION_ENABLED; barrier_moby->collision = barrier_moby->pclass->collision; } break; From 335def4b534219d47044030d8498f965d43293c7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:13:05 +0000 Subject: [PATCH 0610/1502] decomp: clarify names in start_level domain_0_value_0 -> VIDEO_MODE_NTSC: Retail 0x001e94ac-0x001e94b4 loads pal_mode at 0x0015ed80 and branches on zero to 0x001e94d8. That branch loads the normal start_movies descriptor at offsets 0x1a78/0x1a7c; the nonzero path uses start_movies_alt at 0x1a98/0x1a9c. The original Ghidra decompilation explicitly identifies the zero branch as the NTSC descriptor table and nonzero as PAL. Thus this zero comparison denotes NTSC video mode. domain_1_value_3 -> MEMCARD_REQUEST_FORMAT: Source binds ld to &memory_card_state and compares ld->state < 3 before memcard_update_state. Retail 0x001e9584 forms 0x0013d290; 0x001e9588 loads its +0xd4 operation-state word, 0x001e958c compares it with 3, and 0x001e9590 repeats service at 0x001e9578 otherwise. Original Ghidra identifies this as g_nMemoryCardOperationState. Supplied include/rnc/save/memory_card_state.h domain context explicitly assigns MemoryCardState.state to MemoryCardOperation, whose canonical member at 3 is MEMCARD_REQUEST_FORMAT. Reuse that operation boundary, not a per-operation step enum. domain_2_value_0 -> MEMCARD_QUERY_INFO: Source binds ld to &memory_card_state and tests ld->pending_state < 0 as the second condition for leaving the memory-card service loop. Retail 0x001e9598 loads +0xdc from the same 0x0013d290 record and 0x001e959c branches back to memcard_update_state when nonnegative. Original Ghidra identifies this word as g_nPendingMemoryCardOperationState. Supplied shared header context explicitly places pending_state in MemoryCardOperation, where MEMCARD_QUERY_INFO is the canonical zero member. This names the lower operation-domain boundary while retaining the original signed comparison and negative sentinel behavior. --- src/game/start_level.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/game/start_level.c b/src/game/start_level.c index eb4b10a0cd..ded1dfea95 100644 --- a/src/game/start_level.c +++ b/src/game/start_level.c @@ -32,6 +32,9 @@ void start_level(int level) __asm__("FUN_001e9488"); extern s32 game_mode_macro __asm__("D_0015F604") MACRO_ADDR; void start_level(int level) { + enum { + VIDEO_MODE_NTSC = 0 + }; int movie_size_bytes; int movie_start_sector; int movie_work_area_base; @@ -39,7 +42,7 @@ void start_level(int level) { if (level < 0) { return; } - if (pal_mode != 0) { + if (pal_mode != VIDEO_MODE_NTSC) { movie_start_sector = disc_table.start_movies_alt[level].sector; movie_size_bytes = disc_table.start_movies_alt[level].size; } else { @@ -59,7 +62,7 @@ void start_level(int level) { snd_stream_safe_cd_sync(0); for (;;) { struct MemoryCardState *ld = &memory_card_state; - if (ld->state < 3 && ld->pending_state < 0) { + if (ld->state < MEMCARD_REQUEST_FORMAT && ld->pending_state < MEMCARD_QUERY_INFO) { break; } memcard_update_state(); From b507df508d85d1d3311fd7232567ef5375c83b56 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:13:06 +0000 Subject: [PATCH 0611/1502] decomp: clarify names in handle_owner_linked_moby_hits domain_0_value_4 -> LINKED_MOBY_STATE_REMOVE: Retail 0030fe6c saves the recipient moby in s2; 0030fe7c-0030fe80 tests its +0x20 state against 4 and skips hit processing. Checked caller 00310034 preserves the identical a0 moby in s0 and passes it at 003100e8-003100ec. Authoritative same-file update_owner_linked_moby_state names this selector's 4 LINKED_MOBY_STATE_REMOVE and calls mark_moby_for_removal; checked caller 00310154-00310164 stores 4 to that +0x20 field and executes the removal helper. This is the linked-moby state domain, not a Hero or hit-reaction domain. domain_2_value_3 -> LINKED_MOBY_STATE_FADE_OUT: Retail lethal-hit path 0030ff20-0030ff38 compares health with hit damage and clears health; 0030ff9c-0030ffa4 writes 3 specifically to recipient s2+0x20. Checked caller 003100e8-003100ec passes the same moby, whose +0x20 selects the state switch at 00310078-00310098. Authoritative same-file update_owner_linked_moby_state explicitly names state 3 LINKED_MOBY_STATE_FADE_OUT: its branch decrements alpha, checks interpolated value >13.5, then enters REMOVE=4. Checked instructions 00310124-0031015c confirm that alpha decrement and transition to 4. Reuse this established selector-domain member. --- src/overlays/l11/mobys/owner_linked_moby.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l11/mobys/owner_linked_moby.c b/src/overlays/l11/mobys/owner_linked_moby.c index a70b599677..d5148bee06 100644 --- a/src/overlays/l11/mobys/owner_linked_moby.c +++ b/src/overlays/l11/mobys/owner_linked_moby.c @@ -36,9 +36,13 @@ void handle_owner_linked_moby_hits(struct Moby *moby, unsigned char *private_dat HIT_REACTION_KNOCKBACK_AND_CANCEL_PROJECTILE = 4, HIT_REACTION_NO_RESPONSE = 11 }; + enum { + LINKED_MOBY_STATE_FADE_OUT = 3, + LINKED_MOBY_STATE_REMOVE = 4 + }; int hit_status; char *hit_record; - if (moby->state != 4) { + if (moby->state != LINKED_MOBY_STATE_REMOVE) { hit_record = find_moby_hit(moby, 0x330000, 0); if (hit_record != 0) { print_fe50(D_L11_0021B530, moby->oclass, fptodp(*(float *)(hit_record + 0x2C))); @@ -68,7 +72,7 @@ void handle_owner_linked_moby_hits(struct Moby *moby, unsigned char *private_dat if (owner_moby != 0 && owner_moby[0x20] != 0xFE && owner_moby[0x20] != 0xFD) { owner_moby[0x20] = 3; } - moby->state = 3; + moby->state = LINKED_MOBY_STATE_FADE_OUT; } else { *health -= *(float *)(hit_record + 0x2C); private_data[0x67] = 0xFA; From 34fef42462e71cef4be99e449f185dfe2c407709 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:13:06 +0000 Subject: [PATCH 0612/1502] decomp: clarify names in update_timed_effect_emitter domain_0_value_1 -> MOBY_STATE_ACTIVE_WITH_SOUND: In the SHA-bound source, this assignment writes moby->state, the exact selector whose existing local case MOBY_STATE_ACTIVE_WITH_SOUND equals 1. Retail 0x002c7a40 reads byte +0x20(s3); 0x002c7a4c-0x002c7a50 dispatch value 1 to 0x002c7a88. Waiting timer expiry reloads pvars+0xC from +4 and stores 1 to that same byte at 0x002c7a74-0x002c7a84. The target branch emits three particles at 0x002c7b08/0x002c7b2c/0x002c7b50 and maintains sound at 0x002c7b58-0x002c7b7c, proving reuse of the existing active-with-sound member. domain_1_value_0 -> MOBY_STATE_WAIT_FOR_ACTIVATION: The source assignment writes moby->state, the same switch selector whose existing local member MOBY_STATE_WAIT_FOR_ACTIVATION equals 0. Retail 0x002c7a40-0x002c7a44 dispatch that byte's zero value to 0x002c7a60, where the voice index is invalidated and the countdown is ticked before activation. Active timer expiry at 0x002c7b80-0x002c7b98 reloads pvars+0xC from +8 and stores zero to the same +0x20(s3) state byte, then releases an owned active voice at 0x002c7b9c-0x002c7bdc. This returns to the established waiting phase. --- src/overlays/l10/mobys/timed_effect_emitter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/timed_effect_emitter.c b/src/overlays/l10/mobys/timed_effect_emitter.c index 6266864e9f..f2fa4925e1 100644 --- a/src/overlays/l10/mobys/timed_effect_emitter.c +++ b/src/overlays/l10/mobys/timed_effect_emitter.c @@ -47,7 +47,7 @@ void timed_effect_emitter_update(struct Moby *moby) { emitter_vars->voice = -1; if (fast_dec_timer(&emitter_vars->timer_C)) { emitter_vars->timer_C = emitter_vars->unk4; - moby->state = 1; + moby->state = MOBY_STATE_ACTIVE_WITH_SOUND; } break; case MOBY_STATE_ACTIVE_WITH_SOUND: @@ -71,7 +71,7 @@ void timed_effect_emitter_update(struct Moby *moby) { if (fast_dec_timer(&emitter_vars->timer_C)) { int k; emitter_vars->timer_C = emitter_vars->unk8; - moby->state = 0; + moby->state = MOBY_STATE_WAIT_FOR_ACTIVATION; k = emitter_vars->voice; if (k != -1) { unsigned char *voice_entry = (unsigned char *)&voice_pool + k * 0x70; From dd75160f1989b78156fd8cbfb3eac6959f262b1b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:13:06 +0000 Subject: [PATCH 0613/1502] decomp: clarify names in conveyor_belt_update domain_0_value_2 -> CONVEYOR_BELT_STATE_APPROACH_NEGATED_SPEED: The initialization assignment is retail 0x002c98f0 li v0,2 followed by 0x002c9900 sb v0,0x20(s0), after validating pvars+0x60. The same Moby state byte is read at 0x002c9894 and dispatched by 0x002c98bc to 0x002c9910 for state 2. At 0x002c991c-0x002c9920 the base-speed/time product is explicitly negated and approached into pvars+0x6C. Thus this assignment enters the existing local CONVEYOR_BELT_STATE_APPROACH_NEGATED_SPEED domain member, not any Hero enum. domain_1_value_2 -> CONVEYOR_BELT_STATE_APPROACH_NEGATED_SPEED: In the base-speed branch, retail 0x002c99fc loads the pvars+0x64 clip-volume index and 0x002c9a00 tests hero position. On a nonzero result, 0x002c9a0c loads 2 and 0x002c9a10 stores it to the same Moby state byte +0x20 read by the dispatch at 0x002c9894/0x002c98bc. State 2 reaches 0x002c9910-0x002c9920, explicitly negating the base-speed/time product. Reuse the existing local CONVEYOR_BELT_STATE_APPROACH_NEGATED_SPEED member for this transition. --- src/overlays/l16/mobys/conveyor_belt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l16/mobys/conveyor_belt.c b/src/overlays/l16/mobys/conveyor_belt.c index f11b469d61..b714afa36b 100644 --- a/src/overlays/l16/mobys/conveyor_belt.c +++ b/src/overlays/l16/mobys/conveyor_belt.c @@ -68,7 +68,7 @@ void conveyor_belt_update(struct Moby *moby) { if (conveyor_data->unk60 == -1) { moby->flags |= 2; } else { - moby->state = 2; + moby->state = CONVEYOR_BELT_STATE_APPROACH_NEGATED_SPEED; } conveyor_data->unk74 = -1; break; @@ -91,7 +91,7 @@ void conveyor_belt_update(struct Moby *moby) { update_conveyor_group_motion_transforms(moby->group, conveyor_motion_vector); } if (is_point_inside_clip_volume(&hero.motion.pos, conveyor_data->clip_volume_64)) - moby->state = 2; + moby->state = CONVEYOR_BELT_STATE_APPROACH_NEGATED_SPEED; add_draw_callback(draw_conveyor_belt_strips, moby); break; } From cfe164eb6bebf89f493284439aa02e0cc8167429 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:13:06 +0000 Subject: [PATCH 0614/1502] decomp: clarify names in set_hero_animation domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002324f4 reforms s1 as hero at 0x0013F350; 0x0023253c loads the byte at hero+0x20A4 and 0x00232540 skips blend_hero_slot3_mapped_animation_pair when nonzero. Original Ghidra tests cRam001413f4 == '\0' for the same call. The authoritative source identifies precisely this byte as hero_animation_dispatch_state->vehicle_mode, proving the HeroVehicleMode domain rather than state.current or control_mode. In the same source, sync_hero_slot3_animation_speed gates the same vehicle_mode field with HERO_VEHICLE_MODE_ON_FOOT before updating the slot3 pair. The supplied shared enum in include/rnc/hero/hero_state.h canonically names zero HERO_VEHICLE_MODE_ON_FOOT; reuse that member for this same selector. --- src/overlays/shared/hero/set_hero_animation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/set_hero_animation.c b/src/overlays/shared/hero/set_hero_animation.c index 71deac0d4e..5466f64c6d 100644 --- a/src/overlays/shared/hero/set_hero_animation.c +++ b/src/overlays/shared/hero/set_hero_animation.c @@ -491,7 +491,7 @@ void set_hero_animation(int requested_animation_id, blend_frames_or_selector = *(int *)((char *)&hero_blend_curve_frame_counts + hero_animation_dispatch_state->anim_blend_curve * 4); } - if (hero_animation_dispatch_state->vehicle_mode == 0) { + if (hero_animation_dispatch_state->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { blend_hero_slot3_mapped_animation_pair( requested_animation_id, starting_frame_index, blend_frames_or_selector); } From fef2051cbc1ab976de398976173370a5d61f3c09 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:13:06 +0000 Subject: [PATCH 0615/1502] decomp: clarify names in update_cutscene_joint_trails domain_0_value_1 -> TRAIL_STATE_UPDATE: The source's existing local enum defines TRAIL_STATE_UPDATE = 1 for switch (moby->state). Retail 0031f918 reads the selector at a0+0x20, and 0031f920-0031f924 compares that same byte to 1 before entering the trail update branch at 0031f948. Initialization at 0031f938-0031f93c loads 1 and stores it to the identical a0+0x20 field, proving the assignment enters the already named TRAIL_STATE_UPDATE state rather than an unrelated numeric domain. --- src/overlays/l07/mobys/cutscene_joint_trails.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l07/mobys/cutscene_joint_trails.c b/src/overlays/l07/mobys/cutscene_joint_trails.c index 72f7e18bfb..76f3a2ae81 100644 --- a/src/overlays/l07/mobys/cutscene_joint_trails.c +++ b/src/overlays/l07/mobys/cutscene_joint_trails.c @@ -27,7 +27,7 @@ void cutscene_joint_trails_update(struct Moby *moby) { switch (moby->state) { case TRAIL_STATE_INITIALIZE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = TRAIL_STATE_UPDATE; break; case TRAIL_STATE_UPDATE: if (scene_state == 2) { From 454777cbf4c63ab3b31404f13b8f4c95a4b0b572 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:15:02 +0000 Subject: [PATCH 0616/1502] decomp: clarify names in decompress_and_relocate_selected_groups domain_0_value_0 -> HUD_DECOMPRESS_OPTIONAL_BANK_3: The assigned C selector mode is copied from a0 to s3 at retail 0x00234ffc. beq s3,zero at 0x002350c0 enters the slot-4 path; transfer 0x00235104 and decoder 0x00235110 precede link_hud_bank with bank 3 at 0x0023511c/0x00235120. For mode 0, the unsigned (mode-1)<2 test at 0x00235128..0x00235130 rejects the bank-4 path. Banks 0 and 2 are processed independently earlier, so mode 0 selects bank 3 among the optional banks. The supplied initialize_pause_menu caller chooses mode 0 in its else path, confirming this is an explicit selection argument, not its menu state. domain_1_value_2 -> HUD_DECOMPRESS_BOTH_OPTIONAL_BANKS: Retail 0x002350c4 loads 2 and 0x002350c8 compares it with saved argument s3. Equality enters the slot-4 transfer/decode path ending with link_hud_bank(3,destination) at 0x0023511c/0x00235120. Mode 2 also satisfies unsigned(mode-1)<2 at 0x00235128..0x00235130, enabling slot-5 transfer 0x0023516c, decoder 0x00235178 and link_hud_bank(4,destination) at 0x00235184/0x00235188. Thus 2 selects both optional banks 3 and 4 in addition to independently processed banks 0 and 2, without assuming any pause-menu state equivalence. --- .../shared/ui/hud/decompress_and_relocate_selected_groups.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/ui/hud/decompress_and_relocate_selected_groups.c b/src/overlays/shared/ui/hud/decompress_and_relocate_selected_groups.c index 040eea36b1..3c948f6208 100644 --- a/src/overlays/shared/ui/hud/decompress_and_relocate_selected_groups.c +++ b/src/overlays/shared/ui/hud/decompress_and_relocate_selected_groups.c @@ -28,6 +28,10 @@ extern int D_L00_0017E520 NOT_SDA; void decompress_and_relocate_selected_groups(int mode) __asm__("FUN_L00_00234fd0"); void decompress_and_relocate_selected_groups(int mode) { + enum { + HUD_DECOMPRESS_OPTIONAL_BANK_3 = 0, + HUD_DECOMPRESS_BOTH_OPTIONAL_BANKS = 2 + }; G_234fd0 *decompression_slot_state = &D_L00_0017E4D8_lui; int decompression_destination = D_L00_001B9CF0.unk104; void *compressed_data_buffer = (void *)D_L00_001B9CF0.unk10; @@ -57,7 +61,7 @@ void decompress_and_relocate_selected_groups(int mode) { decompression_destination += slot_3_size; } } - if (mode == 0 || mode == 2) { + if (mode == HUD_DECOMPRESS_OPTIONAL_BANK_3 || mode == HUD_DECOMPRESS_BOTH_OPTIONAL_BANKS) { { int slot_4_size; if ((slot_4_size = decompression_slot_state->t->sz[4])) { From 42557ed3b25f87db1df5ae6e167027972327ac94 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:15:02 +0000 Subject: [PATCH 0617/1502] decomp: clarify names in try_collect_ammo_pickup domain_0_value_2 -> AMMO_PICKUP_COLLECTED: Bound source src/overlays/shared/pickups/weapon_ammo.c (SHA-256 811bec559edc171eb202b5eaa9772340023544c2902aba6b3cac447bf4ccdcfe) defines AMMO_PICKUP_COLLECTED = 2 in devestator_ammo_update for pickup_moby->state; that case attracts the collected pickup toward hero.motion.body_center and removes it. Assigned retail 0x002c5c10 loads this Moby's state at +0x20, compares with 2 at 0x002c5c14, and returns zero without granting ammunition when equal. Original Ghidra confirms the +0x20 check. Thus this is the existing collected ammo-pickup state, preventing repeated collection, not a hero state or control mode. domain_1_value_2 -> AMMO_PICKUP_COLLECTED: Retail 0x002c5cd0 loads 2 and 0x002c5d10 stores it into the same pickup Moby state at +0x20 after actual ammo gain is accumulated at 0x002c5cfc-0x002c5d0c. The following code increases pickup scale, clears velocity (+0x10 in pvars), and initializes rise speed (+0x24 in pvars). Original Ghidra shows the same state assignment. Supplied devestator_ammo_update performs these same collection-entry operations then handles AMMO_PICKUP_COLLECTED = 2 by moving toward the hero and removing the pickup. This proves reuse of that ammo-pickup domain member for the successful-collection assignment. --- src/overlays/shared/pickups/weapon_ammo.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/pickups/weapon_ammo.c b/src/overlays/shared/pickups/weapon_ammo.c index 70ca51fb39..2c89125abb 100644 --- a/src/overlays/shared/pickups/weapon_ammo.c +++ b/src/overlays/shared/pickups/weapon_ammo.c @@ -339,12 +339,15 @@ void devestator_ammo_update(struct Moby *pickup_moby) { int try_collect_ammo_pickup(struct Moby *pickup_moby) __asm__("FUN_L00_002c5be8"); int try_collect_ammo_pickup(struct Moby *pickup_moby) { + enum { + AMMO_PICKUP_COLLECTED = 2 + }; int *pickup_vars = ((int *)pickup_moby->pvars); int before; float excess_ammo_amount; int ammo_added; - if (pickup_moby->state == 2) { + if (pickup_moby->state == AMMO_PICKUP_COLLECTED) { fail: return 0; } @@ -362,7 +365,7 @@ int try_collect_ammo_pickup(struct Moby *pickup_moby) { -1); if (excess_ammo_amount < (float)pickup_vars[0]) { weapon_ammo_pickup_totals[pickup_vars[2]] += weapon_ammo_counts[pickup_vars[2]] - before; - pickup_moby->state = 2; + pickup_moby->state = AMMO_PICKUP_COLLECTED; pickup_moby->scale *= frame_scale * 0.200000048f + 1.0f; clear_u64_value(pickup_vars + 4); { From a84c894bfc883b32390fcb65fa50418afc6e82e1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:15:03 +0000 Subject: [PATCH 0618/1502] decomp: clarify names in update_follow_camera_orbit_after_collision domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x002e71cc-0x002e71dc forms hero base 0x0013f350 and loads its byte +0x20a4 (0x001413f4); original Ghidra compares cRam001413f4 against 2. Authoritative source binds that same load to hero.vehicle_mode. At 0x002e71d4/0x002e71e0 the equal-to-2 branch skips to 0x002e7238, bypassing frame-scaled collision retraction and timer reset at 0x002e7214-0x002e7234. Supplied include/rnc/hero/hero_state.h enum-domain evidence establishes HeroVehicleMode member HERO_VEHICLE_MODE_GIANT_CLANK = 2. This is the vehicle domain, separate from the word +0x208c control_mode load at 0x002e7248 and from HeroStateId/HeroGravityMode. --- src/overlays/shared/camera/follow_camera_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/camera/follow_camera_setup.c b/src/overlays/shared/camera/follow_camera_setup.c index abf3f1e753..5a610ff0c3 100644 --- a/src/overlays/shared/camera/follow_camera_setup.c +++ b/src/overlays/shared/camera/follow_camera_setup.c @@ -943,7 +943,7 @@ int update_follow_camera_orbit_after_collision(unsigned char *camera_moby, return sphere_collision_found; } adjusted_orbit_length = fast_vec_length(A); - if (hero.vehicle_mode != 2 && absolute_float(D_0013CA40_lui[0]) > 0.05f && + if (hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && absolute_float(D_0013CA40_lui[0]) > 0.05f && sphere_collision_found) { adjusted_orbit_length -= follow_camera_collision_retraction_rate_gp * frame_scale; *(short *)(B + 0x34) = scale_game_frames(0x884); From fb1daf8997807fa1331e41da0003ae7568a57558 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:15:03 +0000 Subject: [PATCH 0619/1502] decomp: clarify names in update_blarg_elite_commando_rocket domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Authoritative source src/overlays/shared/enemies/blarg_elite_commando_rocket.c (SHA-256 fdea200449c6c203d839427503d17bfa0cb477cc18d0e3abad92f6a6be32261d) compares hero.vehicle_mode == 2. Retail 0x0029ad28-0x0029ad34 loads the byte at 0x001413f4 and compares it against 2; original Ghidra renders cRam001413f4 == 2. On equality, random_integer_below(5) at 0x0029ad3c gates clearing f20 at 0x0029ad4c before forwarding it to make_hit_descriptor at 0x0029ad64-0x0029ad68. This is the vehicle-mode selector, not a current-state or gravity selector. The supplied include/rnc/hero/hero_state.h HeroVehicleMode domain defines canonical HERO_VEHICLE_MODE_GIANT_CLANK = 2, so that member applies to this exact comparison. --- src/overlays/shared/enemies/blarg_elite_commando_rocket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/blarg_elite_commando_rocket.c b/src/overlays/shared/enemies/blarg_elite_commando_rocket.c index 05cbfbfaa0..e24cc096a4 100644 --- a/src/overlays/shared/enemies/blarg_elite_commando_rocket.c +++ b/src/overlays/shared/enemies/blarg_elite_commando_rocket.c @@ -90,7 +90,7 @@ void blarg_elite_commando_rocket_update(unsigned char *moby) { fast_vec_add(rocket_next_position, &MOBY(moby)->pos, rocket_data); fast_vec_scale(back, rocket_data, -2.0f); fast_vec_add(back, back, &MOBY(moby)->pos); - if (hero.vehicle_mode == 2 && random_integer_below(5) != 0) + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && random_integer_below(5) != 0) collision_setup_value = 0.0f; make_hit_descriptor(col, moby, 0x10003, collision_setup_value, rocket_data); *(short *)(col + 0x1A) = MOBY(moby)->oclass; From d41c7957445d5b3aee5350c6c525aede47a5388f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:16:53 +0000 Subject: [PATCH 0620/1502] decomp: clarify names in sceSifCallRpc domain_0_value_0 -> RPC_COMPLETION_DISABLED: Retail 0x0011b2ac-0x0011b2c4 tests mode bit 0 for asynchronous operation, then tests s7 (end_func, stored to client->end_callback at 0x0011b244). Only the no-callback branch stores zero at packet offset 0x30, identified by the source and original Ghidra as completion_mode. This disables completion handling when neither a callback nor a semaphore wait is requested. domain_1_value_1 -> RPC_COMPLETION_ENABLED: Retail 0x0011b2b8 branches on nonzero s7/end_func to 0x0011b2c8, which stores one at packet offset 0x30 (completion_mode). The callback was copied to client offset 0x1c at 0x0011b244. The same packet field receives one for the synchronous semaphore consumer at 0x0011b32c, proving enabled completion handling rather than a callback-only or asynchronous-only mode. domain_2_value_1 -> RPC_COMPLETION_ENABLED: Retail 0x0011b2b0 selects the synchronous branch when mode bit 0 is clear. After CreateSema at 0x0011b30c succeeds, 0x0011b32c stores s3=1 to packet offset 0x30, the same completion_mode field as the callback branch. Successful send then executes WaitSema at 0x0011b370 and DeleteSema at 0x0011b378. Reuse RPC_COMPLETION_ENABLED because this value enables completion handling for the semaphore consumer. --- src/sdk/rpc/rpc/sce_sif_call_rpc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/sdk/rpc/rpc/sce_sif_call_rpc.c b/src/sdk/rpc/rpc/sce_sif_call_rpc.c index 1f8dc47165..aa8a80d1dd 100644 --- a/src/sdk/rpc/rpc/sce_sif_call_rpc.c +++ b/src/sdk/rpc/rpc/sce_sif_call_rpc.c @@ -54,6 +54,10 @@ s32 sceSifCallRpc(struct SifRpcClient *client, s32 end_func, s32 end_data) { + enum { + RPC_COMPLETION_DISABLED = 0, + RPC_COMPLETION_ENABLED = 1 + }; s32 semaphore_parameters[6]; struct SifRpcPacket *packet; s32 semaphore_id; @@ -92,9 +96,9 @@ s32 sceSifCallRpc(struct SifRpcClient *client, } if (mode & 1) { if (end_func == 0) { - packet->completion_mode = 0; + packet->completion_mode = RPC_COMPLETION_DISABLED; } else { - packet->completion_mode = 1; + packet->completion_mode = RPC_COMPLETION_ENABLED; } client->semaphore_id = -1; if (sceSifSendCmd(0x8000000A, packet, 0x40, send_buf, client->server_buffer, send_size) != @@ -113,7 +117,7 @@ s32 sceSifCallRpc(struct SifRpcClient *client, free_rpc_packet(packet); return -3; } - packet->completion_mode = 1; + packet->completion_mode = RPC_COMPLETION_ENABLED; if (sceSifSendCmd(0x8000000A, packet, 0x40, send_buf, client->server_buffer, send_size) == 0) { DeleteSema(client->semaphore_id); From cb5247a9685d782d40e72f81820ace8c77cd7c71 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:16:53 +0000 Subject: [PATCH 0621/1502] decomp: clarify names in _slice0 domain_0_value_0 -> SLICE_SETUP_SUCCESS: Authoritative _slice0.c (SHA-256 4388a97ee8a15fd4b1af8d52aee6381cc1d24574412e10c605291b41a3d57d12) assigns _sliceA0's return to slice_setup_status and returns it unchanged when nonzero. Retail jal 0x00127820 at 0x00127980 is followed by bne v0,zero at 0x00127988 to the return epilogue 0x00127b28. Only zero falls through to clearing slice_error at 0x00127990 and the macroblock loop at 0x00127998. Original Ghidra likewise places the entire processing loop under lVar2 == 0. Thus zero means successful slice setup, not a boolean or pointer constant. --- src/sdk/mpeg/macroblock/_slice0.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/mpeg/macroblock/_slice0.c b/src/sdk/mpeg/macroblock/_slice0.c index 6bb002ff6c..c48e5be9fc 100644 --- a/src/sdk/mpeg/macroblock/_slice0.c +++ b/src/sdk/mpeg/macroblock/_slice0.c @@ -9,6 +9,9 @@ extern u8 too_many_macroblocks_error_message[] __asm__("D_00153848"); extern s32 _motionComp0(); s32 _slice0(struct MpegDecoder *mp, s32 nmb) { + enum { + SLICE_SETUP_SUCCESS = 0 + }; s32 blk[16]; s32 mbx; s32 inc; @@ -20,7 +23,7 @@ s32 _slice0(struct MpegDecoder *mp, s32 nmb) { mbx = 0; inc = 0; slice_setup_status = _sliceA0(mp, nmb, &mbx, &inc, blk); - if (slice_setup_status != 0) { + if (slice_setup_status != SLICE_SETUP_SUCCESS) { return slice_setup_status; } mp->slice_error = 0; From c6d309e2ff1dee76caacb5a07debc60bd3813d40 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:16:53 +0000 Subject: [PATCH 0622/1502] decomp: clarify names in font_queue_vu_state domain_0_value_7 -> FONT_STATE_VU_PROGRAM_QUEUED: Retail 0x001f76bc loads s0 with 7; 0x001f76f0 loads font_state (original Ghidra g_nLastLevelDmaSection), and 0x001f76f4 skips the upload when equal. Otherwise 0x001f7704-0x001f770c calls vu1_add_data_ref with font_vu_program at 0x0010e810 and its tag count at 0x0010e800. Thus this comparison tests the cached state indicating that the font VU program reference has been queued; supplied beam and nanotech callers use this setup before mesh submission. domain_1_value_7 -> FONT_STATE_VU_PROGRAM_QUEUED: Retail 0x001f7708 queues font_vu_program through vu1_add_data_ref; 0x001f7714 then stores the same s0=7 into font_state at 0x0015f620. The guard at 0x001f76f4 skips precisely that reference when the stored value already equals 7, proving this assignment records FONT_STATE_VU_PROGRAM_QUEUED in the same cache domain as the comparison. --- src/ui/text/font/font_queue_vu_state.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ui/text/font/font_queue_vu_state.c b/src/ui/text/font/font_queue_vu_state.c index c871e27024..b34dc97ec4 100644 --- a/src/ui/text/font/font_queue_vu_state.c +++ b/src/ui/text/font/font_queue_vu_state.c @@ -14,6 +14,9 @@ extern void vu1_gs_regs_font(void) __asm__("func_00233C90"); void font_queue_vu_state(void) __asm__("FUN_001f76a0"); void font_queue_vu_state(void) { + enum { + FONT_STATE_VU_PROGRAM_QUEUED = 7 + }; f32 camera_relative_scale_matrix[4][4]; struct DmaTag *dma_packet_start; u8 *packet_write_ptr; @@ -21,9 +24,9 @@ void font_queue_vu_state(void) { set_scale_matrix(camera_relative_scale_matrix, 1024.0f); fast_vec_scale(camera_relative_scale_matrix[3], camera_position, -1024.0f); camera_relative_scale_matrix[3][3] = 1.0f; - if (font_state != 7) { + if (font_state != FONT_STATE_VU_PROGRAM_QUEUED) { vu1_add_data_ref(font_vu_program, font_vu_program_tag[0]); - font_state = 7; + font_state = FONT_STATE_VU_PROGRAM_QUEUED; } render_packet_cursor.tag->tag = 0x10000000; render_packet_cursor.tag->addr = 0; From c53d877eaeb88a6c65f6592b46b18a266ab809d3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:16:53 +0000 Subject: [PATCH 0623/1502] decomp: clarify names in apply_hero_and_item_scale_sequence domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source snapshot 28ffb19887bb98aeb78776913db444d14d114f8790820797ca94158de49fa1a8 declares G=&hero and tests G->vehicle_mode. Retail 00207a5c/00207a68 constructs hero base 0x0013f350; 00207b08 loads its byte +0x20a4 and 00207b0c skips item scaling when nonzero. Ghidra tests cRam001413f4==0 before the seven item-slot loop. coordinate_hero_frame_update dispatches nonzero vehicle_mode to update_hero_in_vehicle_mode, corroborating this as the vehicle selector. Therefore this zero is the supplied HeroVehicleMode canonical HERO_VEHICLE_MODE_ON_FOOT, not HeroStateId or gravity mode. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The inner source binding hero_state=&hero tests hero_state->vehicle_mode while capping slot-zero item_scale to 1.0. Retail 00207b1c copies the hero base from s0 to s6; 00207b54 loads byte +0x20a4(s6), and 00207b58 bypasses the cap when nonzero, followed by the 1.0moby) + 0xC0, ((unsigned char *)G->moby) + 0xC0, sequence_scale); fast_vec_scale( ((unsigned char *)G->moby) + 0xD0, ((unsigned char *)G->moby) + 0xD0, sequence_scale); - if (G->vehicle_mode == 0) { + if (G->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { for (i = 0; i < 7; i++) { for (j = 0; j < 3; j++) { struct Hero *hero_state = &hero; @@ -1556,7 +1556,7 @@ void apply_hero_and_item_scale_sequence(void) { if (j == 1) item_moby = *(unsigned char **)&hero_state->items[i].moby2; item_scale = sequence_scale; - if (i == 0 && hero_state->vehicle_mode == 0 && 1.0f < sequence_scale) + if (i == 0 && hero_state->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT && 1.0f < sequence_scale) item_scale = 1.0f; if (item_moby) { fast_vec_scale(item_moby + 0xC0, item_moby + 0xC0, item_scale); From 6523856a5fdeeac1386c97f39820eaa6f5c60d5b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:16:53 +0000 Subject: [PATCH 0624/1502] decomp: clarify names in poll_pad_device_state domain_0_value_1 -> PAD_DEVICE_READY: Retail 0x002170e4 loads PAD+0x194 as socket, 0x002170f0 calls scePad2GetState, and 0x002170f8-0x00217104 stores its return at PAD+0x19C and compares it with 1. Equality permits PAD+0x198 phase dispatch: profile queries at 0x0021713c/0x002171e0 or packet read/process at 0x00217268/0x00217278. Inequality branches to 0x00217298, clearing input and resetting PAD+0x198 at 0x002172a0. Original retail decompilation agrees. Thus 1 is the device-ready gate, distinct from PAD_INPUT_POLLING in the local phase domain. --- src/input/poll_pad_device_state.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/input/poll_pad_device_state.c b/src/input/poll_pad_device_state.c index 46f7070fe6..8a1fa50661 100644 --- a/src/input/poll_pad_device_state.c +++ b/src/input/poll_pad_device_state.c @@ -12,6 +12,9 @@ void poll_pad_device_state(struct PadState *pad_state) { PAD_INPUT_POLLING = 1, PAD_BUTTON_PROFILE_TOO_LARGE = 2 }; + enum { + PAD_DEVICE_READY = 1 + }; s32 saved_pad_value; s32 pad_device_state; s32 byte_count; @@ -25,7 +28,7 @@ void poll_pad_device_state(struct PadState *pad_state) { pad_state->prev_raw_held = saved_pad_value; pad_device_state = scePad2GetState(pad_state->socket); pad_state->device_state = pad_device_state; - if (pad_device_state == 1) { + if (pad_device_state == PAD_DEVICE_READY) { switch (pad_state->profile_state) { case PAD_PROFILE_INITIALIZATION: { byte_count = scePad2GetButtonProfile(pad_state->socket, pad_response_buffer); From 403cc823f50cbe60afa988ba612fa2776a6a8e07 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:16:53 +0000 Subject: [PATCH 0625/1502] decomp: clarify names in update_circular_saw_engine_sound domain_0_value_9 -> CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED: Retail 002c1b90 saves incoming moby a0 in s0; 002c1ba0 loads its state byte at +0x20 and 002c1b84/002c1ba4 compare it with 9, branching to owned engine-voice release at 002c1c94..002c1cdc. Original Ghidra likewise tests *(char *)(param_1+0x20)==9. SHA-bound source 4a8f68cfafbf4da28d0bedffe34041977bb245a2d0ae7b62e6b5dae078ff8b88 shows circular_saw_enemy_update passing this same moby to the sound updater and switching its state using CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED=9. launch_circular_saw_enemy_from_suck_cannon writes that canonical member to moby->state when launch_suck_cannon_projectile returns nonzero and restores IDLE when control ends. This is the circular-saw moby state domain, not the unrelated HeroStateId. --- src/overlays/l04/mobys/circular_saw_enemy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l04/mobys/circular_saw_enemy.c b/src/overlays/l04/mobys/circular_saw_enemy.c index bfd63fd354..e82b1fb0aa 100644 --- a/src/overlays/l04/mobys/circular_saw_enemy.c +++ b/src/overlays/l04/mobys/circular_saw_enemy.c @@ -49,11 +49,14 @@ void update_circular_saw_engine_sound(struct Moby *moby) { CIRCULAR_SAW_ANIM_ALERT = 6, CIRCULAR_SAW_ANIM_ATTACK = 7 }; + enum { + CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED = 9 + }; EngineSoundVars *engine_sound_vars = (EngineSoundVars *)moby->pvars; f32 volume; f32 pitch; - if (moby->state != 9) { + if (moby->state != CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED) { if (voice_is_playing((long)moby, engine_sound_vars->voice) == 0 && moby->prev_seq < 8) { engine_sound_vars->voice = allocate_voice_for_target_entry(0, 4, moby); engine_sound_vars->volume = convert_integer_to_float(0x400); From 4d8c23cf7d536b5c1848aa2c55813afa9af2a4e5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:16:53 +0000 Subject: [PATCH 0626/1502] decomp: clarify names in music_update_stream domain_11_value_2 -> MUSIC_STREAM_STATE_WAITING_FOR_BUFFER: At 0x00216234-0x00216238 only state 2 of this MusicPlaying +0xA selector proceeds to 0x0021624c, snd_is_vag_stream_buffered_cb(handle, music_channel_ready_callback, stream). The asynchronous readiness poll on a live handle establishes that this stream state waits for buffering. domain_13_value_0 -> MUSIC_STREAM_STATE_INACTIVE: The outer normalization at 0x00216260-0x00216274 writes zero into the stream's +0xA state when the +0 sound handle is zero (also for the state-7 special branch). Together with the post-stop no-handle reset at 0x00216120, this proves zero is the inactive stream state. domain_1_value_5 -> MUSIC_STREAM_STATE_STOP_REQUESTED: At 0x002160c4 the selector is loaded from the MusicPlaying state halfword at +0xA. The value-5 branch at 0x002160ec calls snd_stop_sound (0x0012e368) with the +0 handle at 0x002160fc, then writes state 6 at 0x0021610c; this identifies a pending request to stop this music stream. domain_2_value_6 -> MUSIC_STREAM_STATE_STOPPING: Retail 0x002160fc calls snd_stop_sound for the stream handle, then 0x00216104-0x0021610c stores 6 into the same state halfword at +0xA. The state-6 path at 0x00216110-0x00216120 clears state only when the stream handle is zero, establishing stopping while the handle remains live. domain_3_value_0 -> MUSIC_STREAM_STATE_INACTIVE: In the stop-requested path, retail 0x002160f4-0x002160f8 writes zero to the music-stream state halfword +0xA when its sound handle is zero. The same zero state is restored on handle absence at 0x00216120 and 0x00216274, identifying an inactive stream rather than a boolean domain. domain_4_value_6 -> MUSIC_STREAM_STATE_STOPPING: The comparison at 0x00216110 tests the +0xA music-stream state against 6, the state written immediately after snd_stop_sound at 0x0021610c. The branch checks the +0 handle and resets state to zero only without a handle (0x00216118-0x00216120), proving the stopping state. domain_5_value_0 -> MUSIC_STREAM_STATE_INACTIVE: Retail 0x00216110-0x00216120 handles state 6 after a stop request and writes zero to +0xA only when the +0 stream handle is zero. This agrees with the no-handle normalization at 0x00216268-0x00216274 and identifies inactive music-stream state. domain_9_value_2 -> MUSIC_STREAM_STATE_WAITING_FOR_BUFFER: The selector is the music-stream state loaded from +0xA. Retail 0x002161d0-0x002161d8 routes states 2/3 away from ordinary playback polling; 0x00216234-0x0021624c selects only state 2 to call snd_is_vag_stream_buffered_cb with music_channel_ready_callback and the stream as callback context, proving the waiting-for-buffer polling state. --- src/audio/music/music_update_stream.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/audio/music/music_update_stream.c b/src/audio/music/music_update_stream.c index 1c9a5a5f36..3a416b86ca 100644 --- a/src/audio/music/music_update_stream.c +++ b/src/audio/music/music_update_stream.c @@ -36,20 +36,26 @@ extern void set_sound_handle_id(int, long) __asm__("func_00216B68"); void music_update_stream(MusicPlaying *p) __asm__("FUN_002160a8"); void music_update_stream(MusicPlaying *music_stream) { + enum { + MUSIC_STREAM_STATE_INACTIVE = 0, + MUSIC_STREAM_STATE_WAITING_FOR_BUFFER = 2, + MUSIC_STREAM_STATE_STOP_REQUESTED = 5, + MUSIC_STREAM_STATE_STOPPING = 6 + }; int sound_handle; if (music_stream->state != 9 && music_stream->handle != 0 && music_stream->handle != 0xFFFFFFFF) { - if (music_stream->state == 5) { + if (music_stream->state == MUSIC_STREAM_STATE_STOP_REQUESTED) { if (music_stream->handle != 0) { snd_stop_sound(music_stream->handle); - music_stream->state = 6; + music_stream->state = MUSIC_STREAM_STATE_STOPPING; } else { - music_stream->state = 0; + music_stream->state = MUSIC_STREAM_STATE_INACTIVE; } - } else if (music_stream->state == 6) { + } else if (music_stream->state == MUSIC_STREAM_STATE_STOPPING) { if (music_stream->handle == 0) { - music_stream->state = 0; + music_stream->state = MUSIC_STREAM_STATE_INACTIVE; } } if (music_stream->handle == 0) { @@ -73,7 +79,7 @@ void music_update_stream(MusicPlaying *music_stream) { if (music_stream->state == 1 || music_stream->state == 8 || music_stream->state == 9) { return; } - if (music_stream->state != 2 && music_stream->state != 3) { + if (music_stream->state != MUSIC_STREAM_STATE_WAITING_FOR_BUFFER && music_stream->state != 3) { sound_handle = music_stream->handle; music_stream->handle = 0xFFFFFFFF; snd_get_vag_stream_time_remaining_cb( @@ -82,13 +88,13 @@ void music_update_stream(MusicPlaying *music_stream) { sound_handle, set_sound_handle_id, (long)(unsigned int)music_stream); return; } - if (music_stream->handle != 0xFFFFFFFF && music_stream->state == 2) { + if (music_stream->handle != 0xFFFFFFFF && music_stream->state == MUSIC_STREAM_STATE_WAITING_FOR_BUFFER) { snd_is_vag_stream_buffered_cb(music_stream->handle, music_channel_ready_callback, (long)(unsigned int)music_stream); } } else if (music_stream->state == 7 || music_stream->handle == 0) { - music_stream->state = 0; + music_stream->state = MUSIC_STREAM_STATE_INACTIVE; } } From d982d5be3d9c93d5260c3cd3831499138d89deef Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:16:53 +0000 Subject: [PATCH 0627/1502] decomp: clarify names in reset_leg_rig_from_animation domain_0_value_5 -> LEG_RIG_FALLBACK_GAIT_MASK: At 0x00295f1c-0x00295f24 retail loads 5 and stores it to rig+0xB6 (rig->mode), then calls rig_pick_mode at 0x00295f88 and stores its return to the same byte at 0x00295f90. Bounded helper retail 0x002927d4-0x00292808 scans the 13 rig+0x70 animation records against moby+0x52 and returns rig+0xB6 when none matches; a match instead calls the mask helper at 0x0029280c. Checked C names that operation walker_gait_mask. In checked leg_walker_update the returned mode is consumed with mode & 0xF, combined with rig->mode & 0x30 and tested bit-by-bit against six transformed joint points, proving a gait-mask domain. Thus 5 is the seeded fallback gait mask, rather than a moby-state ID; no particular gait semantics are inferred from its numeric value. --- src/overlays/l04/mobys/leg_walker.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l04/mobys/leg_walker.c b/src/overlays/l04/mobys/leg_walker.c index 9bca9b3b3c..c1b6c6ce90 100644 --- a/src/overlays/l04/mobys/leg_walker.c +++ b/src/overlays/l04/mobys/leg_walker.c @@ -569,6 +569,9 @@ extern int rig_pick_mode(struct Moby *m, LegRig *rig, float t) __asm__("FUN_L04_ void reset_leg_rig_from_animation(struct Moby *moby, LegRig *rig) __asm__("FUN_L04_00295de8"); void reset_leg_rig_from_animation(struct Moby *moby, LegRig *rig) { + enum { + LEG_RIG_FALLBACK_GAIT_MASK = 5 + }; int joints[6]; float mtx[4][4]; float animation_time; @@ -599,7 +602,7 @@ void reset_leg_rig_from_animation(struct Moby *moby, LegRig *rig) { animation_time = convert_integer_to_float(moby->prev_frame); animation_time += animation_start(moby->class_slot, moby->prev_seq); } - rig->mode = 5; + rig->mode = LEG_RIG_FALLBACK_GAIT_MASK; rig->speed = 0.0f; rig->unkB7 = 0; animation_cursor = rig->anims; From 82bd0383a66cb3ccb94237db4148ba8f3990280a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:18:38 +0000 Subject: [PATCH 0628/1502] decomp: clarify names in update_moby_spatial_trigger domain_0_value_0 -> SPATIAL_TRIGGER_STATE_UNINITIALIZED: SHA-256-bound src/overlays/shared/props/moby_state_trigger.c (81e86cfba81d3842b4ff93d1c5ee03ed8141af57e163c9c1c7970d5b4b81aeeb) tests trigger_moby->state == 0 as an alternative to containment change. Retail 0x002f5330/0x002f533c loads that object's state byte at +0x20; 0x002f5340 skips dispatch only when nonzero. Thus zero forces initial application even with unchanged command. At 0x002f5354/0x002f5358 command +0xbc becomes inside (1/0), then 0x002f535c-0x002f5374 stores command+1 into state before list and moby dispatch at 0x002f5388 and 0x002f53b4. Prepared original Ghidra decompilation shows the same gate and store, proving zero is the trigger's uninitialized state, distinct from the hero enums. --- src/overlays/shared/props/moby_state_trigger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/props/moby_state_trigger.c b/src/overlays/shared/props/moby_state_trigger.c index 6373b1843b..afbe0fc224 100644 --- a/src/overlays/shared/props/moby_state_trigger.c +++ b/src/overlays/shared/props/moby_state_trigger.c @@ -111,7 +111,7 @@ void moby_spatial_trigger_update(struct Moby *trigger_moby) __asm__("FUN_L05_002 /* Moby class 258 */ void moby_spatial_trigger_update(struct Moby *trigger_moby) { - TriggerVars *trigger_vars = (TriggerVars *)trigger_moby->pvars; + enum { SPATIAL_TRIGGER_STATE_UNINITIALIZED = 0 } ;TriggerVars *trigger_vars = (TriggerVars *)trigger_moby->pvars; Vec4 target; s32 inside; s32 i; @@ -142,7 +142,7 @@ void moby_spatial_trigger_update(struct Moby *trigger_moby) { } } if ((inside && trigger_moby->command == 0) || (!inside && trigger_moby->command != 0) || - trigger_moby->state == 0) { + trigger_moby->state == SPATIAL_TRIGGER_STATE_UNINITIALIZED) { if (inside) { trigger_moby->command = 1; } else { From 3672a5635c51836a8e73a9492cb7997f8d4c2b9f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:18:38 +0000 Subject: [PATCH 0629/1502] decomp: clarify names in update_damage_causer domain_0_value_0 -> DAMAGE_CAUSER_STATE_UNINITIALIZED: Source update_damage_causer tests moby->state == 0. Retail 0x00305a58 loads the state byte at moby+0x20 and 0x00305a5c skips initialization when nonzero; only the zero path stores state 1 at 0x00305a6c and initializes the private voice-slot sentinel to -1 at 0x00305a70. Thus zero denotes the state awaiting this initialization, not a boolean or control-mode domain. domain_1_value_1 -> DAMAGE_CAUSER_STATE_INITIALIZED: Within the moby->state == 0 initialization branch, retail 0x00305a64 loads 1 and 0x00305a6c stores it to the same moby+0x20 state byte; 0x00305a70 initializes pvars+0x14 to the -1 voice sentinel. Subsequent nonzero state reads branch past this one-time setup at 0x00305a5c. The assigned source and original decompilation agree that 1 records initialization, without proving an active/inactive gameplay mode. --- src/overlays/l09/mobys/damage_causer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l09/mobys/damage_causer.c b/src/overlays/l09/mobys/damage_causer.c index 6f92494a07..54c7dcd239 100644 --- a/src/overlays/l09/mobys/damage_causer.c +++ b/src/overlays/l09/mobys/damage_causer.c @@ -32,15 +32,15 @@ extern s32 D_L09_0015F5CC NOT_SDA; /* Moby class 1206 */ void damage_causer_update(struct Moby *moby) { - char *damage_causer_vars = (char *)moby->pvars; + enum { DAMAGE_CAUSER_STATE_UNINITIALIZED = 0 , DAMAGE_CAUSER_STATE_INITIALIZED = 1 } ;char *damage_causer_vars = (char *)moby->pvars; float sphere_query_workspace[24]; int i; float count_as_float; float start; float end; - if (moby->state == 0) { - moby->state = 1; + if (moby->state == DAMAGE_CAUSER_STATE_UNINITIALIZED) { + moby->state = DAMAGE_CAUSER_STATE_INITIALIZED; *(s32 *)(damage_causer_vars + 0x14) = -1; } if ((D_L09_0015F5CC & 7) == (((int)moby >> 8) & 7)) { From 864cc0f90f57c993b803fe2250ff977c4933a261 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:18:38 +0000 Subject: [PATCH 0630/1502] decomp: clarify names in update_quartu_cutscene_trigger domain_0_value_2 -> CUTSCENE_TRIGGER_WAIT_FOR_FIRST_SCENE: Retail 002eb4dc reads the switch selector from s0+0x20, the same moby state byte written at 002eb588 with 2 after start_scene(3) at 002eb574. Its case at 002eb59c-002eb5c0 waits on the scene gate then advances to 1. The authoritative C already names that exact selector's case 2 CUTSCENE_TRIGGER_WAIT_FOR_FIRST_SCENE; reuse its local enum member. domain_1_value_1 -> CUTSCENE_TRIGGER_START_SECOND_SCENE: Retail 002eb5b8-002eb5c0 stores 1 to s0+0x20 after the state-2 scene gate and movie-queue helper. The same byte selects the switch at 002eb4dc; case 1 at 002eb5c4-002eb5e8 starts scene 4 then stores 3. Authoritative C names this exact case CUTSCENE_TRIGGER_START_SECOND_SCENE, proving reuse for this assignment. domain_2_value_3 -> CUTSCENE_TRIGGER_FINALIZE_AND_SAVE: Retail 002eb5d8-002eb5e8 starts scene 4 and stores 3 to s0+0x20, the selector loaded at 002eb4dc. Case 3 at 002eb620-002eb678 performs the final planet/camera/message operations, requests memcard_save_data(0,-1), then stores 4. Authoritative C already names that same-selector case CUTSCENE_TRIGGER_FINALIZE_AND_SAVE; reuse it. domain_3_value_4 -> CUTSCENE_TRIGGER_COMPLETED: Retail 002eb66c requests memcard_save_data(0,-1), then 002eb674-002eb678 stores 4 to s0+0x20, the exact state byte switched on at 002eb4dc. The authoritative C case CUTSCENE_TRIGGER_COMPLETED=4 performs no further switch work. Reuse this established local-domain member; completion denotes the local sequence rather than proven save persistence. --- src/overlays/l15/mobys/quartu_cutscene_trigger.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l15/mobys/quartu_cutscene_trigger.c b/src/overlays/l15/mobys/quartu_cutscene_trigger.c index e19e96647d..61a6894bde 100644 --- a/src/overlays/l15/mobys/quartu_cutscene_trigger.c +++ b/src/overlays/l15/mobys/quartu_cutscene_trigger.c @@ -61,20 +61,20 @@ void quartu_cutscene_trigger_update(struct Moby *moby) { if (((unsigned char *)l15_moby_array)[(trigger_data->unk8 << 8) + 0x20] != 3) break; start_scene(3); - moby->state = 2; + moby->state = CUTSCENE_TRIGGER_WAIT_FOR_FIRST_SCENE; jet_clear_persistent(moby->mission); FUN_L00_00232fe8(); break; case CUTSCENE_TRIGGER_WAIT_FOR_FIRST_SCENE: if (D_L15_0015F5C4 != 2) { queue_scene_movie_with_game_language(0x11); - moby->state = 1; + moby->state = CUTSCENE_TRIGGER_START_SECOND_SCENE; } break; case CUTSCENE_TRIGGER_START_SECOND_SCENE: if (D_L15_0015F5C4 != 2) { start_scene(4); - moby->state = 3; + moby->state = CUTSCENE_TRIGGER_FINALIZE_AND_SAVE; FUN_L00_002330d0(); if (trigger_data->unk4 != -1) { char *o = D_L15_001600EC + (trigger_data->unk4 << 7); @@ -91,7 +91,7 @@ void quartu_cutscene_trigger_update(struct Moby *moby) { } queue_planet_unlock_message(0x11); memcard_save_data(0, -1); - moby->state = 4; + moby->state = CUTSCENE_TRIGGER_COMPLETED; } break; case CUTSCENE_TRIGGER_COMPLETED: From bad8d7c7081693112ad2d6136af185cfb3f2e942 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:18:38 +0000 Subject: [PATCH 0631/1502] decomp: clarify names in reset_hero_follow_camera_from_preset domain_1_value_0 -> CAMERA_ORBIT_MODE_FOLLOW: Retail 0x003297EC loads the reset camera's orbit pointer from camera+0x70; 0x00329804 stores a zero halfword at orbit+0x1C, matching CameraOrbit.mode in the SHA-256-bound current source. The same source's update_hero_follow_camera_orbit tests this field for 0 with hero.vert_ramp_launch, changes it to 1 to orbit using yaw/pitch/distance springs, and restores 0 when the launch ends. update_orbit_camera_position executes normal position-to-focus following, collision probing and position springs when this same orbit->mode is 0. Thus 0 denotes the camera's normal follow mode, separate from focus.state and all Hero state/mode domains. --- src/overlays/shared/camera/hoverboard_camera.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/camera/hoverboard_camera.c b/src/overlays/shared/camera/hoverboard_camera.c index b8dd8692d6..6761568321 100644 --- a/src/overlays/shared/camera/hoverboard_camera.c +++ b/src/overlays/shared/camera/hoverboard_camera.c @@ -243,6 +243,9 @@ extern CameraPresetRow *D_L05_0015EF50; void reset_hero_follow_camera_from_preset(Camera *camera_to_reset) __asm__("FUN_L05_003296e0"); void reset_hero_follow_camera_from_preset(Camera *camera_to_reset) { + enum { + CAMERA_ORBIT_MODE_FOLLOW = 0 + }; CameraPreset *preset = D_L05_0015EF50[camera_to_reset->preset].preset; CameraOrbit *orbit_state; CameraFocus *focus; @@ -276,7 +279,7 @@ void reset_hero_follow_camera_from_preset(Camera *camera_to_reset) { orbit->unk10 = 0.01f; orbit->unk14 = 0.2f; orbit->unk18 = 0; - orbit->mode = 0; + orbit->mode = CAMERA_ORBIT_MODE_FOLLOW; clear_u64_value(orbit); track = &camera_to_reset->orbit->track; clear_u64_value(track); From e59f27d4601cf50a39209b2e44082750a4707b9c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:20:27 +0000 Subject: [PATCH 0632/1502] decomp: clarify names in sceCdDiskReady domain_0_value_8 -> CD_DISK_READY_MODE_NEGATIVE_FAILURE_RETURN: The selector is sceCdDiskReady's s32 mode argument, retained in s2 at retail 0x001211a4 and sent as the four-byte RPC request at 0x001212d0-0x00121308. The sync-busy branch at 0x001211fc reaches semaphore release at 0x00121314, then xori a0,s2,8 at 0x00121320 and movz at 0x00121330 select -1 rather than 6. This proves the first source comparison names the disk-ready mode selecting a negative acquired-failure return; it does not establish waiting semantics. domain_1_value_8 -> CD_DISK_READY_MODE_NEGATIVE_FAILURE_RETURN: The second source comparison follows a negative sceSifCallRpc result. Retail 0x0012130c falls through to SignalSema at 0x00121318, sharing the sync-busy failure tail: 0x00121320 compares the original mode in s2 with 8, 0x00121324 loads -1, 0x00121328 loads 6, and 0x00121330 selects -1 on equality. Both source comparisons therefore use the same disk-ready request-mode constant and negative-failure-return meaning. --- src/sdk/storage/cdvd/sceCdDiskReady.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sdk/storage/cdvd/sceCdDiskReady.c b/src/sdk/storage/cdvd/sceCdDiskReady.c index 98f9aee75d..01d349f164 100644 --- a/src/sdk/storage/cdvd/sceCdDiskReady.c +++ b/src/sdk/storage/cdvd/sceCdDiskReady.c @@ -21,6 +21,9 @@ extern void sceSifWriteBackDCache(); s32 sceCdDiskReady(s32 mode) __asm__("FUN_00121190"); s32 sceCdDiskReady(s32 mode) { + enum { + CD_DISK_READY_MODE_NEGATIVE_FAILURE_RETURN = 8 + }; s32 response; s32 spin; @@ -33,7 +36,7 @@ s32 sceCdDiskReady(s32 mode) { } if (sceCdSyncS(1) != 0) { SignalSema(cd_scmd_sema); - if (mode == 8) { + if (mode == CD_DISK_READY_MODE_NEGATIVE_FAILURE_RETURN) { return -1; } return 6; @@ -62,7 +65,7 @@ s32 sceCdDiskReady(s32 mode) { if (sceSifCallRpc(&cd_disk_ready_rpc_client, 0, 0, D_001599D0, 4, cd_scmd_result, 4, 0, 0) < 0) { SignalSema(cd_scmd_sema); - if (mode == 8) { + if (mode == CD_DISK_READY_MODE_NEGATIVE_FAILURE_RETURN) { return -1; } return 6; From df4ed77d82eb64ec3c865e453ac8ca82f224b0e0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:20:27 +0000 Subject: [PATCH 0633/1502] decomp: clarify names in update_menu_option_list domain_0_value_0 -> FALSE: Authoritative source compares requested_video_mode != 0 before mode_freeze_init. Retail 0x00220f98 reads the flag byte and 0x00220f9c branches on zero; 0x00220fd0-0x00220fdc reads the same 0x0016034c byte, computes sltiu v0,v0,1 and stores the Boolean negation. This proves a Boolean false test, fitting existing FALSE rather than MenuTextAction or a state enum. domain_1_value_0 -> FALSE: Authoritative source assigns requested_video_mode = requested_video_mode == 0. Retail 0x00220fcc-0x00220fd0 loads byte 0x0016034c, 0x00220fd4 sltiu v0,v0,1 produces 1 exactly when that byte is zero, and 0x00220fdc writes it back. Original Ghidra renders this as g_bRequestedPalVideoMode == 0. Existing FALSE expresses the proven Boolean operand without inferring a video-standard enum. --- src/ui/menus/selection/update_menu_option_list.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/menus/selection/update_menu_option_list.c b/src/ui/menus/selection/update_menu_option_list.c index 0f035256de..86422f812f 100644 --- a/src/ui/menus/selection/update_menu_option_list.c +++ b/src/ui/menus/selection/update_menu_option_list.c @@ -53,12 +53,12 @@ s32 update_menu_option_list(struct MenuScreen *menu_screen) { if (controller_state.pressed_unmasked & PAD_CROSS) { allocate_voice_for_target_entry(0, 0x11, menu_screen->moby); if (menu_screen->data.options.list[menu_screen->data.options.selection].flags & 1) { - if (requested_video_mode != 0) { + if (requested_video_mode != FALSE) { mode_freeze_init(6, menu_system.current); } else { fade_to_black(4); menu_screen->data.options.fade_timer = scale_game_frames(0x10); - requested_video_mode = requested_video_mode == 0; + requested_video_mode = requested_video_mode == FALSE; } } else if (menu_screen->data.options.list[menu_screen->data.options.selection].flag != 0) { *menu_screen->data.options.list[menu_screen->data.options.selection].flag = From ed9b6f096e6cea488d319f067949746da2ba4034 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:20:27 +0000 Subject: [PATCH 0634/1502] decomp: clarify names in sceFsInit domain_0_value_0 -> FALSE: At sceFsInit 0x0011b9e0 DIntr returns the prior interrupt-enable Boolean, saved at 0x0011b9f4 and compared with zero at 0x0011ba20 before EnableInterrupts. Helper 0x0011d660 masks COP0 Status bit 16; 0x0011d670 sltu normalizes the bit to 0/1, and 0x0011d69c returns zero when already disabled. Thus this comparison's zero is established Boolean FALSE, not an RPC error status. domain_1_value_0 -> SIF_RPC_BIND_SUCCESS: sceFsInit calls sceSifBindRpc at 0x0011ba6c with mode 0, then bltz at 0x0011ba74 returns -1 on failure. The bind helper returns -1 for no packet (0x0011b034-38), -3 for semaphore failure (0x0011b084), -2 for send failure (0x0011b0c4), and exactly zero after successful synchronous WaitSema/DeleteSema (0x0011b0c8-0x0011b0dc). Hence the listed <0 threshold is the bind-success status, separate from server availability checked at 0x0011ba7c-80. domain_2_value_0 -> SIF_RPC_CALL_SUCCESS: sceFsInit invokes sceSifCallRpc function 0xff with mode 0 at 0x0011bb20; bgez at 0x0011bb28 admits reply handling, while a negative status returns 0xfffeffff. The call helper returns -1 on packet exhaustion (0x0011b224-28), -3 on semaphore creation failure (0x0011b328), -2 on send failure (0x0011b36c), and exactly zero after synchronous completion and semaphore deletion (0x0011b370-0x0011b380). Thus this comparison's zero names successful RPC call completion, not a reply payload. --- src/sdk/storage/fileio/sceFsInit.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/sdk/storage/fileio/sceFsInit.c b/src/sdk/storage/fileio/sceFsInit.c index 97ca9f338c..441be8d7f1 100644 --- a/src/sdk/storage/fileio/sceFsInit.c +++ b/src/sdk/storage/fileio/sceFsInit.c @@ -33,6 +33,10 @@ extern s32 SignalSema(); extern s32 WaitSema(); s32 sceFsInit(void) { + enum { + SIF_RPC_BIND_SUCCESS = 0, + SIF_RPC_CALL_SUCCESS = 0 + }; s32 initialization_call_status, delay; struct SifFileSlot *slot; struct UnalignedWord reply_word; @@ -44,12 +48,12 @@ s32 sceFsInit(void) { initialization_call_status = DIntr(); sceSifAddCmdHandler(0x80000011, (u32)_sceFs_Rcv_Intr, (u32)fs_receive_interrupt_handler_data); sceSifAddCmdHandler(0x80000013, (u32)invoke_sif_file_command_callback, (u32)callback_record); - if (initialization_call_status != 0) { + if (initialization_call_status != FALSE) { EnableInterrupts(); } for (;;) { initialization_call_status = sceSifBindRpc(&fio_rpc_client, 0x80000001, 0); - if (initialization_call_status < 0) { + if (initialization_call_status < SIF_RPC_BIND_SUCCESS) { return -1; } if (fio_rpc_client.serve != 0) { @@ -68,7 +72,7 @@ s32 sceFsInit(void) { fs_init_completion_buffer_addresses[1] = D_00157500 + 0x440; initialization_call_status = sceSifCallRpc( &fio_rpc_client, 0xFF, 0, fs_init_completion_buffer_addresses, 8, fio_rpc_result, 8, 0, 0); - if (initialization_call_status < 0) { + if (initialization_call_status < SIF_RPC_CALL_SUCCESS) { return (s32)0xFFFEFFFF; } *(struct UnalignedWord *)FsResetBuffer = From de124c2307f24d7e4795b54913432852e2b289d3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:20:27 +0000 Subject: [PATCH 0635/1502] decomp: clarify names in create_spark_particle domain_0_value_255 -> SPARK_MODE_FROM_KIND: Authoritative source (SHA-256 65f9327d0c08a063eab1db5c767a9d946a2e48a263222ed8ce7d446a66219178) compares the u8 mode parameter with 0xFF. Retail 0x0027e928 masks mode into s4; 0x0027e9b8-0x0027e9bc compares it with 255. On equality, 0x0027e9d4-0x0027ea00 derives record byte 9 from kind's upper bits and chooses record byte 3 as 0x48 or 0x44 from kind bit 0. Otherwise 0x0027e9c0 and 0x0027ea04 store kind and mode directly. Original Ghidra expresses the same param_14 == -1 branch. Thus this is the mode sentinel for deriving initialization from kind, without claiming specific rendering semantics. --- src/overlays/l01/mobys/create_spark_particle.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/create_spark_particle.c b/src/overlays/l01/mobys/create_spark_particle.c index b0c9292ede..37ac745365 100644 --- a/src/overlays/l01/mobys/create_spark_particle.c +++ b/src/overlays/l01/mobys/create_spark_particle.c @@ -71,6 +71,9 @@ void create_spark_particle(s32 id, f32 b, f32 size) { + enum { + SPARK_MODE_FROM_KIND = 0xFF + }; Spark *spark; SparkBody *spark_body; u128 position_snapshot = *pos; @@ -85,7 +88,7 @@ void create_spark_particle(s32 id, } spark_body = &spark->body; qcopy(&spark->pos, position_copy_source); - if (mode == 0xFF) { + if (mode == SPARK_MODE_FROM_KIND) { spark->b9 = (kind >> 5) * 16 + truncate_float_to_s32(4.0f); if (kind & 1) { spark->b3 = 0x48; From 08869f9140971a3d5ed0a6a543ea1630f302374d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:22:10 +0000 Subject: [PATCH 0636/1502] decomp: clarify names in update_path_mover_spawner domain_0_value_0 -> PATH_MOVER_SPAWNER_STATE_UNINITIALIZED: In the bound source update_path_mover_spawner tests moby->state == 0. Retail 0x002db2b0 loads the byte at moby+0x20 and 0x002db2b4 skips directly to the recurring timer path when nonzero. The zero branch validates the path, computes segment lengths (0x002db330-0x002db35c), initializes timer/voice and seeds path movers (0x002db3a8), proving the uninitialized spawner state rather than a boolean or another object's state. domain_1_value_1 -> PATH_MOVER_SPAWNER_STATE_INITIALIZED: Retail 0x002db360 clears the spawner timer, 0x002db364 loads 1 and 0x002db368 stores it to the same moby+0x20 state byte tested at 0x002db2b0. This marks the initialization branch as entered/completed on the current invocation: segment lengths are prepared, voice is reset at 0x002db370 and initial movers are seeded before recurring timer/voice maintenance. Subsequent calls with this value skip setup at 0x002db2b4, proving the initialized spawner state. --- src/overlays/l03/mobys/path_mover_spawner.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l03/mobys/path_mover_spawner.c b/src/overlays/l03/mobys/path_mover_spawner.c index 53c38d08a6..05ebe36245 100644 --- a/src/overlays/l03/mobys/path_mover_spawner.c +++ b/src/overlays/l03/mobys/path_mover_spawner.c @@ -75,12 +75,12 @@ void path_mover_spawner_update(struct RailSpawnerMoby *moby) __asm__("FUN_L03_00 /* Moby class 899 */ void path_mover_spawner_update(struct RailSpawnerMoby *moby) { - struct RailSpawnerVars *vars = moby->vars; + enum { PATH_MOVER_SPAWNER_STATE_UNINITIALIZED = 0 , PATH_MOVER_SPAWNER_STATE_INITIALIZED = 1 } ;struct RailSpawnerVars *vars = moby->vars; LevelPath *path; float spawn_distance; int i; - if (moby->state == 0) { + if (moby->state == PATH_MOVER_SPAWNER_STATE_UNINITIALIZED) { if (vars->path == -1) { debug_print(path_mover_spawner_bad_path_format, moby->uid); mark_moby_for_removal((char *)moby); @@ -91,7 +91,7 @@ void path_mover_spawner_update(struct RailSpawnerMoby *moby) { for (i = 0; i < path->count - 2; i++) path->points[i].f[3] = fast_vec_dist(&path->points[i], &path->points[i + 1]); vars->timer = 0; - moby->state = 1; + moby->state = PATH_MOVER_SPAWNER_STATE_INITIALIZED; vars->voice = -1; for (spawn_distance = 2.9f; spawn_distance < path->count * path->points[0].f[3]; spawn_distance += 2.9f) From 4cd4383f74aca35edda6506891aae572041dd906 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:22:10 +0000 Subject: [PATCH 0637/1502] decomp: clarify names in update_nearest_area_moby_selection domain_0_value_0 -> AREA_MOBY_STATE_UNINITIALIZED: Retail 0x002f2ec4 holds the input Moby in s0; 0x002f2ed4 loads its state byte at +0x20 and 0x002f2ed8 skips initialization for nonzero values. The zero branch validates pvars, sets update_dist, copies moby position into AreaVars.home at 0x002f2f00-0x002f2f04, sets flags and writes state 1 at 0x002f2f18. Thus this moby->state comparison denotes the uninitialized area moby, independently of hero state enums. domain_1_value_1 -> AREA_MOBY_STATE_INITIALIZED: Retail 0x002f2f0c loads 1 and 0x002f2f18 stores it to the same input Moby state byte at +0x20 after saving home position and setting update_dist; flags are committed at 0x002f2f20. On later updates 0x002f2ed4-0x002f2ed8 sees the nonzero state and bypasses this initialization block. The assignment therefore marks area moby initialization, not a hero state or vehicle mode. --- src/overlays/shared/pickups/buried_bolts.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/pickups/buried_bolts.c b/src/overlays/shared/pickups/buried_bolts.c index 74b7f70ffc..da2b44b719 100644 --- a/src/overlays/shared/pickups/buried_bolts.c +++ b/src/overlays/shared/pickups/buried_bolts.c @@ -32,13 +32,13 @@ void buried_bolts_update(struct Moby *moby) __asm__("FUN_L01_002f2eb8"); /* Moby class 605 */ void buried_bolts_update(struct Moby *moby) { - AreaVars *area_vars = (AreaVars *)moby->pvars; + enum { AREA_MOBY_STATE_UNINITIALIZED = 0 , AREA_MOBY_STATE_INITIALIZED = 1 } ;AreaVars *area_vars = (AreaVars *)moby->pvars; Vec4 target; s32 k; s32 *path; f32 target_distance; - if (moby->state == 0) { + if (moby->state == AREA_MOBY_STATE_UNINITIALIZED) { if (area_vars == 0) { mark_moby_for_removal(moby); return; @@ -46,7 +46,7 @@ void buried_bolts_update(struct Moby *moby) { moby->update_dist = 0xFF; qcopy(&area_vars->home, &moby->pos); moby->flags |= 0x41; - moby->state = 1; + moby->state = AREA_MOBY_STATE_INITIALIZED; if (moby->command == 0 && D_0015ED84 < 20) { k = D_0014BF10[D_L01_00161AF0 / 2 + D_0015ED84 * 16]; if (D_L01_00161AF0 & 1) { From a8899708b5271f26e4ca5da55511a29f8c499159 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:22:10 +0000 Subject: [PATCH 0638/1502] decomp: clarify names in magnetboots_update domain_0_value_1 -> MAGNETBOOTS_STATE_WAIT_FOR_HERO_PROXIMITY: Retail 0x002986a8 loads this moby's state byte at s0+0x20 and 0x002986ac dispatches value 1 to 0x00298740, the existing WAIT_FOR_HERO_PROXIMITY case with distance <3, vertical difference <2 and health checks. Initialization stores s2=1 to the identical byte at 0x0029872c. Thus this assignment enters the already named magnetboots proximity state. domain_1_value_2 -> MAGNETBOOTS_STATE_WAIT_FOR_SCENE_EXIT: Retail 0x002987bc calls the established scene-start helper with 2; 0x002987c4/0x002987cc then store 2 to this moby's state byte s0+0x20. Dispatch 0x002986d0 sends that same byte value to 0x002987d0, the authoritative existing MAGNETBOOTS_STATE_WAIT_FOR_SCENE_EXIT case, which waits while the scene gate equals 2 before granting the pickup and saving. This names the moby state assignment, not the separate scene argument or gate. domain_2_value_3 -> MAGNETBOOTS_STATE_REMOVE: After dialogue, inventory grant, optional linked-moby save position and memcard_save_data, retail 0x00298834/0x0029883c stores 3 to s0+0x20, the same moby state byte loaded at 0x002986a8. Dispatch 0x002986d8 selects 0x00298840 for value 3, whose sole action is mark_moby_for_removal on s0. This directly reuses existing MAGNETBOOTS_STATE_REMOVE in the same function/domain. --- src/overlays/l10/mobys/magnetboots.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l10/mobys/magnetboots.c b/src/overlays/l10/mobys/magnetboots.c index 16505d4552..23831de7ef 100644 --- a/src/overlays/l10/mobys/magnetboots.c +++ b/src/overlays/l10/mobys/magnetboots.c @@ -43,7 +43,7 @@ void magnetboots_update(struct Moby *moby) { mark_moby_for_removal(moby); return; } - moby->state = 1; + moby->state = MAGNETBOOTS_STATE_WAIT_FOR_HERO_PROXIMITY; moby->pos.z = moby->pos.z + 0.5f; moby->scale = moby->scale * 0.667f; break; @@ -55,7 +55,7 @@ void magnetboots_update(struct Moby *moby) { hero_ref->health.hp != 0) { moby->flags |= 0x41; start_scene(2); - moby->state = 2; + moby->state = MAGNETBOOTS_STATE_WAIT_FOR_SCENE_EXIT; } } break; @@ -69,7 +69,7 @@ void magnetboots_update(struct Moby *moby) { jet_reset_camera(linked_moby + 0x10, linked_moby + 0x40); } memcard_save_data(0, -1); - moby->state = 3; + moby->state = MAGNETBOOTS_STATE_REMOVE; } break; case MAGNETBOOTS_STATE_REMOVE: From 40da8c3e3c1472d3b6d0d3d934367485e0798ce0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:22:10 +0000 Subject: [PATCH 0639/1502] decomp: clarify names in update_unlock_sequence_controller domain_0_value_3 -> UNLOCK_SEQUENCE_COMPLETE: Retail 0x003054a0-0x003054a8 tests the save-id cleared byte and branches with v0=3 to 0x003055e8, which stores to controller s0+0x20. This is the same state selector loaded at 0x00305420, and state 3 has no active dispatch branch. An already-cleared unlock therefore enters the completed controller state. domain_1_value_3 -> UNLOCK_SEQUENCE_COMPLETE: Retail 0x003054d4-0x003054e4 tests this controller save-id's current-level unlock bit; when set it branches with v0=3 to the controller state store at 0x003055e8. This shares the terminal destination used after countdown expiry, proving COMPLETE for the already-recorded unlock path. domain_2_value_1 -> UNLOCK_SEQUENCE_WAIT_FOR_TRIGGER: Retail 0x00305418 keeps the controller in s0, 0x00305420 loads its state from +0x20, and 0x003054e8 stores 1 to that same field before save_and_lower_unlock_sequence_mobys. The dispatcher branches on 1 to 0x003054fc, which waits for the referenced trigger moby; reuse the existing local UNLOCK_SEQUENCE_WAIT_FOR_TRIGGER member. domain_3_value_2 -> UNLOCK_SEQUENCE_COUNTDOWN: After the trigger check and unlock-bit recording, retail 0x00305598 stores t0=2 to controller s0+0x20 and 0x00305594-0x003055bc initializes the scaled countdown and reciprocal. Dispatcher 0x00305448 routes controller state 2 to timer decrement at 0x003055c8 and raising at 0x003055d0; reuse existing UNLOCK_SEQUENCE_COUNTDOWN. domain_4_value_3 -> UNLOCK_SEQUENCE_COMPLETE: Retail 0x003055c8-0x003055d4 decrements the countdown and raises linked mobys. At 0x003055d8-0x003055dc a nonzero countdown returns; zero falls through 0x003055e4-0x003055e8 to store 3 in controller s0+0x20. The dispatcher handles only 0,1,2, proving the sequence has completed and enters its inactive terminal state. --- src/overlays/l14/mobys/unlock_sequence_controller.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/overlays/l14/mobys/unlock_sequence_controller.c b/src/overlays/l14/mobys/unlock_sequence_controller.c index def1b3ed5f..2099da309b 100644 --- a/src/overlays/l14/mobys/unlock_sequence_controller.c +++ b/src/overlays/l14/mobys/unlock_sequence_controller.c @@ -33,6 +33,9 @@ void unlock_sequence_controller_update(struct Moby *moby) { UNLOCK_SEQUENCE_WAIT_FOR_TRIGGER = 1, UNLOCK_SEQUENCE_COUNTDOWN = 2 }; + enum { + UNLOCK_SEQUENCE_COMPLETE = 3 + }; int *unlock_sequence_data = ((int *)moby->pvars); short id; @@ -45,14 +48,14 @@ void unlock_sequence_controller_update(struct Moby *moby) { } id = ((short)moby->save_id); if (D_L14_001BB930.cleared[id] != 0) { - moby->state = 3; + moby->state = UNLOCK_SEQUENCE_COMPLETE; return; } if (D_0014C190_257218[current_level_index][id >> 5] >> (moby->save_id & 0x1F) & 1) { - moby->state = 3; + moby->state = UNLOCK_SEQUENCE_COMPLETE; return; } - moby->state = 1; + moby->state = UNLOCK_SEQUENCE_WAIT_FOR_TRIGGER; save_and_lower_unlock_sequence_mobys((char *)moby); break; case UNLOCK_SEQUENCE_WAIT_FOR_TRIGGER: @@ -62,7 +65,7 @@ void unlock_sequence_controller_update(struct Moby *moby) { D_0014C190_257218[current_level_index][((short)moby->save_id) >> 5] |= 1 << (moby->save_id & 0x1F); D_L14_001BABD0[((short)moby->save_id) >> 5] |= 1 << (moby->save_id & 0x1F); - moby->state = 2; + moby->state = UNLOCK_SEQUENCE_COUNTDOWN; unlock_sequence_data[1] = scale_game_frames(0x78); ((float *)unlock_sequence_data)[2] = 1.0f / convert_integer_to_float(unlock_sequence_data[1]); @@ -72,7 +75,7 @@ void unlock_sequence_controller_update(struct Moby *moby) { fast_dec_timer(&unlock_sequence_data[1]); raise_unlock_sequence_mobys((char *)moby); if (unlock_sequence_data[1] == 0) { - moby->state = 3; + moby->state = UNLOCK_SEQUENCE_COMPLETE; } break; } From df0a90f2d3371aa8367105c9ecefbfe6f0019526 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:22:10 +0000 Subject: [PATCH 0640/1502] decomp: clarify names in update_pyrocitor_usage_and_cleanup domain_0_value_4 -> PYROCITOR_STATE_CLEANUP: Retail 0x002b8240 keeps the input Pyrocitor moby in s2; 0x002b8250-0x002b8260 tests its prev_seq at +0x53 and writes 4 to its state byte +0x20. The same branch then removes the pvars+0 child (0x002b8270), releases the +0x44 point light (0x002b8288), conditionally releases its owned active +0x4A voice (0x002b82b0-0x002b82c8), clears both handles and returns. Supplied pyrocitor_update passes this same moby before switching on moby->state, proving this is the Pyrocitor state domain and that the assignment enters resource cleanup. domain_1_value_3 -> PYROCITOR_STATE_FIRING: Retail 0x002b8300 loads the input Pyrocitor moby's +0x20 state byte and 0x002b8304-0x002b831c compares it with 3, incrementing pvars+0x50 once per firing update. The supplied authoritative pyrocitor_update passes that exact moby to this helper before its switch(moby->state), defines PYROCITOR_STATE_FIRING = 3, enters it when the fire button is held with ammo, and implements flame particle creation and ammo consumption in that case. Therefore this comparison reuses the existing Pyrocitor firing member, not equal-valued HERO_STATE_STOP. --- src/overlays/shared/weapons/pyrocitor.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/pyrocitor.c b/src/overlays/shared/weapons/pyrocitor.c index cc472e2ca0..461a4844eb 100644 --- a/src/overlays/shared/weapons/pyrocitor.c +++ b/src/overlays/shared/weapons/pyrocitor.c @@ -742,12 +742,16 @@ void pyrocitor_update(struct Moby *moby) { void update_pyrocitor_usage_and_cleanup(struct Moby *pyrocitor_moby) __asm__("FUN_L00_002b8230"); void update_pyrocitor_usage_and_cleanup(struct Moby *pyrocitor_moby) { + enum { + PYROCITOR_STATE_FIRING = 3, + PYROCITOR_STATE_CLEANUP = 4 + }; unsigned char *pyrocitor_vars = ((unsigned char *)pyrocitor_moby->pvars); struct UsageStats *P; unsigned char *voice; int voice_slot_or_time_stat, firing_frame_count; if (pyrocitor_moby->prev_seq == 2) { - pyrocitor_moby->state = 4; + pyrocitor_moby->state = PYROCITOR_STATE_CLEANUP; if (*(void **)pyrocitor_vars) mark_moby_for_removal(*(void **)pyrocitor_vars); if (*(short *)(pyrocitor_vars + 0x44) != -1) { @@ -768,7 +772,7 @@ void update_pyrocitor_usage_and_cleanup(struct Moby *pyrocitor_moby) { P = &usage_stats; if (P->stat[10].count) return; - if (pyrocitor_moby->state == 3) { + if (pyrocitor_moby->state == PYROCITOR_STATE_FIRING) { (*(unsigned short *)(pyrocitor_vars + 0x50))++; return; } From 7eae73806a736f568b60250b3c64971d2a7ca682 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:22:10 +0000 Subject: [PATCH 0641/1502] decomp: clarify names in update_kerwan_cutscene_effects domain_0_value_1 -> CUTSCENE_EFFECTS_UPDATE: Retail 0x002e01f0 reads owner_moby's unsigned state byte at +0x20; 0x002e01f8/0x002e01fc compare it with 1 and dispatch to the update branch at 0x002e0220. Initialization loads 1 at 0x002e0210 and stores it to that same byte at 0x002e0214. The authoritative C already names the switch case for this identical selector/value CUTSCENE_EFFECTS_UPDATE, so the assignment enters that established local state domain. --- src/overlays/l03/mobys/cutscene_effects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l03/mobys/cutscene_effects.c b/src/overlays/l03/mobys/cutscene_effects.c index dfa3697aca..a2df76612f 100644 --- a/src/overlays/l03/mobys/cutscene_effects.c +++ b/src/overlays/l03/mobys/cutscene_effects.c @@ -37,7 +37,7 @@ void kerwan_cutscene_effects_update(struct Moby *owner_moby) { switch (owner_moby->state) { case CUTSCENE_EFFECTS_INITIALIZE: owner_moby->update_dist = 0xFF; - owner_moby->state = 1; + owner_moby->state = CUTSCENE_EFFECTS_UPDATE; break; case CUTSCENE_EFFECTS_UPDATE: if (D_L03_0015F5C4 != 2) From 6f4fbdd15e65abab78b3af974e3b6b1e8cb5fc4c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:22:10 +0000 Subject: [PATCH 0642/1502] decomp: clarify names in gold_weapon_case_update domain_0_value_2 -> GOLD_WEAPON_CASE_REMOVE_WHEN_PURCHASED: Retail 002e1b38-002e1b4c assigns 2 to s1+0x20 for non-0x130 classes. The switch reads that exact byte at 002e1b10; its existing state-2 branch at 002e1c7c-002e1cb0 removes the moby when the mapped purchase flag is nonzero. Reuse the existing same-selector enum member. domain_1_value_3 -> GOLD_WEAPON_CASE_IDLE: Retail 002e1b74-002e1ba0 stores 3 to s1+0x20 when the purchase byte is nonzero or dialogue initialization returns -1. This is the same byte selected at 002e1b10; existing GOLD_WEAPON_CASE_IDLE=3 has only break in the authoritative source, matching the retail return path. domain_2_value_1 -> GOLD_WEAPON_CASE_PROCESS_SALE: Retail 002e1b84-002e1ba8 assigns 1 to s1+0x20 when dialogue initialization succeeds for an unpurchased item. The identical state byte is the switch selector; existing GOLD_WEAPON_CASE_PROCESS_SALE=1 reaches 002e1bac-002e1c48, processing dialogue result, committing purchase and deducting bolts. domain_3_value_4 -> GOLD_WEAPON_CASE_WAIT_FOR_CUTSCENE_END: Retail 002e1bc8-002e1c18 tests sale result 2, commits the purchase flag and stores 4 to s1+0x20 before initialize_vendor_screen. The switch selects this same byte. Its existing GOLD_WEAPON_CASE_WAIT_FOR_CUTSCENE_END=4 branch at 002e1c54-002e1c78 waits for cutscene_mode zero, saves and enters idle. domain_4_value_0 -> CUTSCENE_MODE_INACTIVE: This comparison belongs to cutscene_mode, not moby->state: retail 002e1c54-002e1c5c loads 0015f5c4 and returns while nonzero; only zero permits memcard_save_data and idle at 002e1c64-002e1c78. The supplied initialize_vendor_screen source sets the same global to CUTSCENE_MODE_VENDOR_SCREEN=5. Zero therefore denotes inactive cutscene mode for the established wait-for-cutscene-end branch. domain_5_value_3 -> GOLD_WEAPON_CASE_IDLE: Retail 002e1c54-002e1c78 waits for cutscene_mode zero, calls the save helper and stores 3 to s1+0x20. That is the exact byte read by the moby state switch at 002e1b10, whose existing GOLD_WEAPON_CASE_IDLE=3 body does no further processing. Reuse that canonical local member for this transition. --- src/overlays/shared/props/gold_weapon_case.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/props/gold_weapon_case.c b/src/overlays/shared/props/gold_weapon_case.c index de4afc9f74..8eac91bb4e 100644 --- a/src/overlays/shared/props/gold_weapon_case.c +++ b/src/overlays/shared/props/gold_weapon_case.c @@ -45,6 +45,9 @@ void gold_weapon_case_update(struct Moby *moby) { GOLD_WEAPON_CASE_IDLE = 3, GOLD_WEAPON_CASE_WAIT_FOR_CUTSCENE_END = 4 }; + enum { + CUTSCENE_MODE_INACTIVE = 0 + }; SaleVars *sale_vars = (SaleVars *)moby->pvars; s32 purchased_item_id; ItemPrice *price; @@ -57,12 +60,12 @@ void gold_weapon_case_update(struct Moby *moby) { switch (moby->state) { case GOLD_WEAPON_CASE_INITIALIZE: if (moby->oclass != 0x130) { - moby->state = 2; + moby->state = GOLD_WEAPON_CASE_REMOVE_WHEN_PURCHASED; } else if (item_text_variant[gold_weapon_case_item_ids_by_slot[sale_vars->slot]] != 0 || initialize_npc_dialogue(moby, sale_vars) == -1) { - moby->state = 3; + moby->state = GOLD_WEAPON_CASE_IDLE; } else { - moby->state = 1; + moby->state = GOLD_WEAPON_CASE_PROCESS_SALE; } break; case GOLD_WEAPON_CASE_PROCESS_SALE: @@ -70,7 +73,7 @@ void gold_weapon_case_update(struct Moby *moby) { FUN_L00_00266448_2e1ac0(moby, sale_vars); if (sale_vars->result == 2) { item_text_variant[gold_weapon_case_item_ids_by_slot[sale_vars->slot]] = 1; - moby->state = 4; + moby->state = GOLD_WEAPON_CASE_WAIT_FOR_CUTSCENE_END; purchased_item_id = gold_weapon_case_item_ids_by_slot[sale_vars->slot]; price = &l01_gold_weapon_case_item_prices[purchased_item_id]; current_bolt_count -= price->bolts; @@ -80,9 +83,9 @@ void gold_weapon_case_update(struct Moby *moby) { case GOLD_WEAPON_CASE_IDLE: /* sold out or done: idle */ break; case GOLD_WEAPON_CASE_WAIT_FOR_CUTSCENE_END: - if (cutscene_mode == 0) { + if (cutscene_mode == CUTSCENE_MODE_INACTIVE) { memcard_save_data(0, -1); - moby->state = 3; + moby->state = GOLD_WEAPON_CASE_IDLE; } break; case GOLD_WEAPON_CASE_REMOVE_WHEN_PURCHASED: From b1bd0f927d736219c4dfa7127ec39f7505bf609c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:23:58 +0000 Subject: [PATCH 0643/1502] decomp: clarify names in green_mushroom_update domain_0_value_1 -> GREEN_MUSHROOM_WAIT_FOR_POSITIVE_HIT: Authoritative green_mushroom.c SHA-256 1cb9d79debae8cbae6a31574853005401338ffcbc01dd308f7169973b20f855c already defines this enum member as 1 for switch(mushroom_moby->state). Retail 0x002fd9e4 reads state at s0+0x20; 0x002fd9e8 loads a0=1 and 0x002fda24 stores a0 to that identical byte in the initialize branch. Retail 0x002fd9ec dispatches state 1 to 0x002fda28, which waits for a non-null hit and positive hit+0x2C. Thus the initialization assignment enters the existing WAIT_FOR_POSITIVE_HIT state, not a separate control domain. domain_1_value_2 -> GREEN_MUSHROOM_SPAWN_PIECES_AND_REMOVE: The source enum defines GREEN_MUSHROOM_SPAWN_PIECES_AND_REMOVE=2 on switch(mushroom_moby->state). Retail 0x002fda28-0x002fda48 tests non-null hit and positive float at hit+0x2C; 0x002fda50 loads v0=2 and 0x002fda58 stores it to s0+0x20, the exact state byte read at 0x002fd9e4. State 2 dispatches via 0x002fda10 to 0x002fda5c; 0x002fdb64-0x002fdb70 spawns four class-0x719 pieces, 0x002fdb78 spawns class 0x718 and 0x002fdb80 removes the source. This assignment therefore reuses the already established member of the same local state domain. --- src/overlays/l01/mobys/green_mushroom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l01/mobys/green_mushroom.c b/src/overlays/l01/mobys/green_mushroom.c index 6c2ecda21a..713e3cde6f 100644 --- a/src/overlays/l01/mobys/green_mushroom.c +++ b/src/overlays/l01/mobys/green_mushroom.c @@ -57,14 +57,14 @@ void green_mushroom_update(SparkMoby *mushroom_moby) { hit = find_moby_hit(mushroom_moby, 0x10000, 0); switch (mushroom_moby->state) { case GREEN_MUSHROOM_INITIALIZE: - mushroom_moby->state = 1; + mushroom_moby->state = GREEN_MUSHROOM_WAIT_FOR_POSITIVE_HIT; break; case GREEN_MUSHROOM_WAIT_FOR_POSITIVE_HIT: if (hit != 0 && hit->f2c > 0.0f) { flag = 1; } if (flag) { - mushroom_moby->state = 2; + mushroom_moby->state = GREEN_MUSHROOM_SPAWN_PIECES_AND_REMOVE; } break; case GREEN_MUSHROOM_SPAWN_PIECES_AND_REMOVE: From f408cd195abe0fbb4304d446dca361a12eb80d0b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:25:38 +0000 Subject: [PATCH 0644/1502] decomp: clarify names in update_robot_dog_hit_reaction domain_0_value_21 -> ROBOT_DOG_DEATH_FALL: Retail 0x002c6ae4 loads s4=0x15; 0x002c6ae8 loads the robot dog's state byte at 0x20(s2), and 0x002c6aec skips repeated damage/knockback when equal. Caller retail 0x002c5c0c passes this same moby to this function and 0x002c5c1c then dispatches its byte +0x20. The authoritative caller source already names this selector's 21 ROBOT_DOG_DEATH_FALL; its branch steps motion and spawns debris/removes the moby, corroborated by retail 0x002c6894-0x002c69a0. This is the actual moby state, not the separate +0x144 knockback control value. domain_1_value_21 -> ROBOT_DOG_DEATH_FALL: Retail 0x002c6ae4 establishes s4=21 and 0x002c6bf4 stores s4 into 0x20(s2), immediately after starting knockback at 0x002c6bec. Caller 0x002c5c0c calls this function on s3 and 0x002c5c1c reads that same moby byte +0x20 for its switch. The bound source names case 21 ROBOT_DOG_DEATH_FALL, whose motion branch leads to debris and removal (retail 0x002c6894-0x002c69a0). Reusing that established domain name captures the transition being assigned. --- src/overlays/l03/mobys/robot_dog.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l03/mobys/robot_dog.c b/src/overlays/l03/mobys/robot_dog.c index 85aac72477..4d5b4f21ce 100644 --- a/src/overlays/l03/mobys/robot_dog.c +++ b/src/overlays/l03/mobys/robot_dog.c @@ -491,6 +491,9 @@ extern void FUN_L01_0026e090(int, int); extern void trooper_set_knockback(float *, float, float) __asm__("FUN_L03_00250a78"); void update_robot_dog_hit_reaction(struct Moby *moby) { + enum { + ROBOT_DOG_DEATH_FALL = 21 + }; float vector[4]; int hit_reaction_code; float damage; @@ -509,7 +512,7 @@ void update_robot_dog_hit_reaction(struct Moby *moby) { damage = 0.0f; hit = find_moby_hit(moby, 0x330000, 0); hit_reaction(moby, hit, robot_dog_pvars + 0x20, 0, &hit_reaction_code, &damage, 0, 4); - if (hit_reaction_code != 1 && moby->state != 21) { + if (hit_reaction_code != 1 && moby->state != ROBOT_DOG_DEATH_FALL) { char *hit_source_moby; if (moby->group != 255) FUN_L01_0026e090(moby->group, 1); @@ -535,7 +538,7 @@ void update_robot_dog_hit_reaction(struct Moby *moby) { *(OvlQuad *)vector = *(OvlQuad *)(hit + 0x10); trooper_knockback_arc(vector, &angle, robot_dog_pvars + 0x138, robot_dog_pvars + 0x13C); trooper_start_knockback(angle, moby, robot_dog_pvars + 0x120, 4, 1, 0); - moby->state = 21; + moby->state = ROBOT_DOG_DEATH_FALL; *(unsigned char *)(robot_dog_pvars + 0x117) = 240; trooper_anim_update(moby, (short *)(robot_dog_pvars + 0x110)); } From e9e82714cec7d7e629e26b2ffe26ce5326ed0260 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:25:38 +0000 Subject: [PATCH 0645/1502] decomp: clarify names in suck_cannon_update domain_0_value_1 -> SUCK_CANNON_WAIT_FOR_HERO: Retail 0x002e1a30 keeps the same moby in s0; 0x002e1a80 reads its state byte at +0x20. After initialization and the inventory absence test, 0x002e1af0 writes 1 to that same byte. Dispatch 0x002e1a84-0x002e1a88 routes 1 to 0x002e1b00, whose distance-to-hero test at 0x002e1b10-0x002e1b2c waits for distance <3. The authoritative switch already names this identical selector/value SUCK_CANNON_WAIT_FOR_HERO. domain_1_value_2 -> SUCK_CANNON_WAIT_TO_RESET_CAMERA: Retail 0x002e1b40 calls start_scene(2), then 0x002e1b48-0x002e1b50 stores 2 into s0+0x20, the same moby state byte read at 0x002e1a80 and dispatched at 0x002e1aa8 to 0x002e1b54. That branch waits on the global mode then passes the configured exit position/rotation to jet_reset_camera at 0x002e1bc0-0x002e1bc8. The authoritative switch already names this exact state SUCK_CANNON_WAIT_TO_RESET_CAMERA; the separate scene argument is untouched. domain_2_value_3 -> SUCK_CANNON_REMOVE: After the exit-camera reset or missing-exit diagnostic, retail 0x002e1bd0/0x002e1be4 loads 3 and 0x002e1bec writes it to s0+0x20. This is the same state byte read at 0x002e1a80; 0x002e1aac-0x002e1ab0 dispatches 3 to 0x002e1c00, which only calls mark_moby_for_removal. The authoritative local enum and switch already bind this state to SUCK_CANNON_REMOVE. --- src/overlays/l04/mobys/suck_cannon.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l04/mobys/suck_cannon.c b/src/overlays/l04/mobys/suck_cannon.c index 663d52460e..aced727ad0 100644 --- a/src/overlays/l04/mobys/suck_cannon.c +++ b/src/overlays/l04/mobys/suck_cannon.c @@ -64,7 +64,7 @@ void suck_cannon_update(struct Moby *moby) { mark_moby_for_removal(moby); break; } - moby->state = 1; + moby->state = SUCK_CANNON_WAIT_FOR_HERO; moby->pos.z += 1.0f; break; case SUCK_CANNON_WAIT_FOR_HERO: @@ -72,7 +72,7 @@ void suck_cannon_update(struct Moby *moby) { if (vector_distance_xy(&moby->pos, &hero.motion.pos) < 3.0f) { moby->flags |= 0x41; start_scene(2); - moby->state = 2; + moby->state = SUCK_CANNON_WAIT_TO_RESET_CAMERA; } break; case SUCK_CANNON_WAIT_TO_RESET_CAMERA: @@ -91,7 +91,7 @@ void suck_cannon_update(struct Moby *moby) { debug_print(suck_cannon_missing_segment_switch_warning_format, ((struct PortalMobyView *)moby)->uid); } - moby->state = 3; + moby->state = SUCK_CANNON_REMOVE; memcard_save_data(0, -1); break; case SUCK_CANNON_REMOVE: From 77fe82ef14086838a9a91f318a2e7fe68e8a5b59 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:25:38 +0000 Subject: [PATCH 0646/1502] decomp: clarify names in update_link_triggered_moby_motion domain_1_value_1 -> LINKED_MOTION_STATE_WAIT_FOR_LINK_TRIGGER: The input a0 is retained as s1 at 0030e98c, and its state byte at +0x20 is read at 0030e998. Retail 0030eaa0 stores 1 to this same moving_moby state after initialization. On the next update, 0030e99c routes that value to 0030eaa4, which indexes private_data+8 and waits for the linked moby's class/state or command condition. This is the exact selector already named LINKED_MOTION_STATE_WAIT_FOR_LINK_TRIGGER in the source switch. domain_3_value_2 -> LINKED_MOTION_STATE_MOVE_ALONG_LOCAL_AXIS: Retail 0030eaec-0030eaf4 stores 2 into +0x20 of s1, the same moving_moby whose state selects this function's switch. The value is stored only after the linked-moby trigger succeeds. Retail 0030e9c0 routes state 2 to 0030eb24; 0030eb4c-0030eb6c constructs displacement from moving_moby->rot_row1 and adds it to its position. This exactly reuses the existing LINKED_MOTION_STATE_MOVE_ALONG_LOCAL_AXIS member of the same selector domain. --- src/overlays/l11/mobys/link_triggered_moby_motion.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l11/mobys/link_triggered_moby_motion.c b/src/overlays/l11/mobys/link_triggered_moby_motion.c index 5fef2a6ccb..83de84ea61 100644 --- a/src/overlays/l11/mobys/link_triggered_moby_motion.c +++ b/src/overlays/l11/mobys/link_triggered_moby_motion.c @@ -69,7 +69,7 @@ void link_triggered_moby_motion_update(struct Moby *moving_moby) { moving_moby->scale = source_moby_class->scale * private_data->unkC; spawned_moby->scale = source_moby_class->scale * private_data->unkC; spawned_moby->state = 1; - moving_moby->state = 1; + moving_moby->state = LINKED_MOTION_STATE_WAIT_FOR_LINK_TRIGGER; break; case LINKED_MOTION_STATE_WAIT_FOR_LINK_TRIGGER: linked_moby = (struct Moby *)((private_data->unk8 << 8) + (int)D_L11_0015FFD8); @@ -78,7 +78,7 @@ void link_triggered_moby_motion_update(struct Moby *moving_moby) { } if (linked_moby->oclass == 0x33E && linked_moby->command != 0) { go: - moving_moby->state = 2; + moving_moby->state = LINKED_MOTION_STATE_MOVE_ALONG_LOCAL_AXIS; ((Rec57 *)(private_data->unk14 + (int)(alternate_item_available)))->f57 = 1; allocate_voice_for_target_entry(0, 0, moving_moby); } From 044bd93a3598bb8fc2a0ed9996b11c76d5998693 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:27:31 +0000 Subject: [PATCH 0647/1502] decomp: clarify names in update_qwarks_starfighter_shield domain_0_value_1 -> FADE_IN: Retail 0x002e84ec loads the switch selector from moby+0x20; 0x002e851c-0x002e852c writes 1 to that same state byte after copying class collision. The source already declares FADE_IN=1 for this exact selector; retail case 1 at 0x002e8530-0x002e859c increases pvars+4 toward 1 and derives alpha from it at 0x002e8674-0x002e868c, proving the transition enters FADE_IN. domain_1_value_2 -> WAIT_FOR_OWNER_REMOVAL: Retail 0x002e8584-0x002e859c increases and clamps the fade factor to 1, then 0x002e85a4 and 0x002e8670 store state 2 into moby+0x20, the same byte read by the switch at 0x002e84ec. Existing WAIT_FOR_OWNER_REMOVAL=2 names this selector's case: 0x002e85dc-0x002e8608 waits for pvars[0] to be null or its state to be FE/FD, consistent with supplied owner creation and removal-helper data flow. domain_2_value_3 -> FADE_OUT: Retail 0x002e85dc-0x002e8608 tests the linked owner for null or removal states FE/FD and writes 3 to moby+0x20, the switch selector read at 0x002e84ec. Existing local FADE_OUT=3 belongs to this exact selector; its branch at 0x002e860c-0x002e8668 shrinks toward class scale and subtracts the fade increment from pvars+4 toward zero, then updates alpha at 0x002e8674-0x002e868c. domain_3_value_4 -> REMOVE_MOBY: Retail 0x002e8650-0x002e8668 subtracts the fade increment and clamps pvars+4 to zero; 0x002e866c-0x002e8670 writes 4 into moby+0x20, the same switch selector loaded at 0x002e84ec. Existing local REMOVE_MOBY=4 names that selector's case, whose retail branch 0x002e8690-0x002e869c calls the checked removal helper with this moby and returns. --- src/overlays/l13/mobys/qwarks_starfighter_shield.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l13/mobys/qwarks_starfighter_shield.c b/src/overlays/l13/mobys/qwarks_starfighter_shield.c index b2e3bbfc24..99a1634769 100644 --- a/src/overlays/l13/mobys/qwarks_starfighter_shield.c +++ b/src/overlays/l13/mobys/qwarks_starfighter_shield.c @@ -53,7 +53,7 @@ void qwarks_starfighter_shield_update(struct Moby *moby) { switch (moby->state) { case INITIALIZE_COLLISION: moby->collision = moby->pclass->collision; - moby->state = 1; + moby->state = FADE_IN; break; case FADE_IN: { float fade = frame_scale * 0.02f; @@ -61,7 +61,7 @@ void qwarks_starfighter_shield_update(struct Moby *moby) { ((float *)moby_data)[1] += fade; if (((float *)moby_data)[1] >= 1.0f) { ((float *)moby_data)[1] = 1.0f; - moby->state = 2; + moby->state = WAIT_FOR_OWNER_REMOVAL; } moby->alpha = truncate_float_to_s32(((float *)moby_data)[1] * 60.0f); break; @@ -70,7 +70,7 @@ void qwarks_starfighter_shield_update(struct Moby *moby) { moby->scale += (moby->pclass->scale * 4.0f - moby->scale) * 0.1f; if (moby_data[0] == 0 || ((unsigned char *)moby_data[0])[0x20] == 0xFE || ((unsigned char *)moby_data[0])[0x20] == 0xFD) { - moby->state = 3; + moby->state = FADE_OUT; } break; case FADE_OUT: { @@ -79,7 +79,7 @@ void qwarks_starfighter_shield_update(struct Moby *moby) { ((float *)moby_data)[1] -= fade; if (((float *)moby_data)[1] <= 0.0f) { ((float *)moby_data)[1] = 0.0f; - moby->state = 4; + moby->state = REMOVE_MOBY; } moby->alpha = truncate_float_to_s32(((float *)moby_data)[1] * 60.0f); break; From 88f941d1b0d25218e076198f287df4d055646ae1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:27:31 +0000 Subject: [PATCH 0648/1502] decomp: clarify names in update_chomper_hit_reaction_and_target domain_0_value_0 -> CHOMPER_INITIALIZE: Retail 0x002e6214 preserves the supplied chomper in s1; 0x002e6228 loads its state byte at +0x20 and 0x002e622c returns when zero. Original Ghidra likewise checks *(char *)(iVar10 + 0x20) == 0. Authoritative chomper_update passes its own chomper_moby directly to this function before switching on that same state field; its established CHOMPER_INITIALIZE = 0 branch initializes the entity, saves its home position and transitions to state 1. Thus this zero is the same chomper initialization state, not a hero state or mode. domain_1_value_8 -> CHOMPER_KNOCKBACK: After a successful find_moby_hit, retail 0x002e62d8 computes the knockback arc and 0x002e62f4 starts knockback on the same s1 chomper with pvars+0x120. 0x002e6304 loads 8 and 0x002e6324 stores it to that object's state byte +0x20; original Ghidra confirms the assignment. Authoritative chomper_update calls this function on its own chomper then switches on the same state, with established CHOMPER_KNOCKBACK = 8 calling step_moby_motion on pvars+0x120 and removing the chomper after impact. These shared object and motion-record flows prove the existing chomper-domain member. --- src/overlays/l16/mobys/chomper.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l16/mobys/chomper.c b/src/overlays/l16/mobys/chomper.c index a7c40ab8ea..7d061ea327 100644 --- a/src/overlays/l16/mobys/chomper.c +++ b/src/overlays/l16/mobys/chomper.c @@ -254,6 +254,10 @@ extern void trooper_knockback_arc(void *, float *, void *, void *) __asm__("FUN extern void trooper_anim_update(void *m, short *p) __asm__("FUN_L00_0025d458"); void update_chomper_hit_reaction_and_target(void *chomper_instance) { + enum { + CHOMPER_INITIALIZE = 0, + CHOMPER_KNOCKBACK = 8 + }; L16PursuitMoby *chomper_moby = chomper_instance; L16PursuitData *pursuit_data = chomper_moby->data; char *hit; @@ -262,7 +266,7 @@ void update_chomper_hit_reaction_and_target(void *chomper_instance) { float knockback_vector_and_heading [8]; /* [0..3] where the hit came from, [4] the heading that gives */ - if (chomper_moby->state == 0) { + if (chomper_moby->state == CHOMPER_INITIALIZE) { return; } hit = find_moby_hit(chomper_moby, 0x330000, 0); @@ -289,7 +293,7 @@ void update_chomper_hit_reaction_and_target(void *chomper_instance) { chomper_moby, pursuit_data->knock, 5, 1, 0, knockback_vector_and_heading[4]); pursuit_data->f170 = 8.0f; pursuit_data->f174 = 16.0f; - chomper_moby->state = 8; + chomper_moby->state = CHOMPER_KNOCKBACK; chomper_moby->i94 = 0; pursuit_data->reaction_time = 0x78; trooper_anim_update(chomper_moby, pursuit_data->reaction); From f5136de0a8be5ee0a6b390e1b1bdbffa6707b58a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:27:31 +0000 Subject: [PATCH 0649/1502] decomp: clarify names in get_frame_texture domain_0_value_19 -> PSMT8: In the SHA-256-bound source, return_mode = 0x13 flows only into tex0_word via (u64)return_mode << 20. Retail 0x001ffbd4 loads a1=0x13; 0x001ffbdc conditionally selects the alternative; 0x001ffbec shifts a1 by 0x14 and 0x001ffbf4 ORs it into the packed texture return. Neighboring fields are image GS block at bit 0, buffer width at bit 14, dimensions at bits 26/30, and palette block at bit 37, proving the TEX0 PSM domain. PCSX2 GSRegs.h defines TEX0 TBP0:14, TBW:6, PSM:6 and GS_PSM member PSMT8=19. Thus this is the ordinary 8-bit indexed texture pixel-storage method. Primary reference: https://github.com/PCSX2/pcsx2/blob/master/pcsx2/GS/GSRegs.h . domain_1_value_27 -> PSMT8H: Source selects return_mode = 0x1B when image_page->gs_block_offset < (gs_texture_allocation_base >> 8). Retail 0x001ffbb8 loads the image block; 0x001ffbc0 shifts the allocation base by 8; 0x001ffbc8 compares them; 0x001ffbd0 loads 0x1b and 0x001ffbdc selects it. At 0x001ffbec the selected value is shifted 20 bits and ORed into the same TEX0 word as image address, buffer width, dimensions and palette block. This proves the GS TEX0 PSM domain independently of the numeric value. PCSX2 GSRegs.h defines that field at bits 20..25 and PSMT8H=27, the high-byte indexed texture format. Primary reference: https://github.com/PCSX2/pcsx2/blob/master/pcsx2/GS/GSRegs.h . --- src/rendering/texture/get_frame_texture.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/rendering/texture/get_frame_texture.c b/src/rendering/texture/get_frame_texture.c index fd94b3018b..bb1defec2b 100644 --- a/src/rendering/texture/get_frame_texture.c +++ b/src/rendering/texture/get_frame_texture.c @@ -36,6 +36,10 @@ extern struct FrameTextureTables hud_state __asm__("D_0019A3E8"); u64 get_frame_texture(s32 frame_id) __asm__("FUN_001ffa10"); u64 get_frame_texture(s32 frame_id) { + enum { + PSMT8 = 0x13, + PSMT8H = 0x1B + }; struct FrameTextureRef *frame; struct FramePalettePage *palette_page; struct FrameImagePage *image_page; @@ -115,9 +119,9 @@ u64 get_frame_texture(s32 frame_id) { if (return_shift < 0) { return_shift = 0; } - return_mode = 0x13; + return_mode = PSMT8; if (image_page->gs_block_offset < (gs_texture_allocation_base >> 8)) { - return_mode = 0x1B; + return_mode = PSMT8H; } return_shift = 1 << return_shift; tex0_word = image_page->gs_block_offset | ((u64)return_shift << 14); From 7bda647227331b42ae74e293d12559efbf973d9e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:27:32 +0000 Subject: [PATCH 0650/1502] decomp: clarify names in begin_bolt_attraction domain_0_value_4 -> BOLT_MOVE_TO_HERO: Retail 0x002a7228 preserves incoming bolt a0 in s2; 0x002a724c loads its state byte at +0x20 and 0x002a7250-0x002a725c rejects value 4. The supplied bolt_update switches on that same bolt_moby->state, names 4 BOLT_MOVE_TO_HERO, and uses vars target +0x60, speed +0x64 and attraction angles to approach collection. This is the bolt state domain, not HeroStateId. domain_1_value_3 -> BOLT_IDLE: Retail 0x002a7324-0x002a732c compares the same bolt s2+0x20 state byte with 3; 0x002a7334-0x002a736c builds a basis from bolt vars+0x10 and initializes vars+0x20 velocity. Supplied bolt_update names this same bolt-state selector's value 3 BOLT_IDLE and calls begin_bolt_attraction from its reach-distance branch. HeroStateId value 3 is a different domain. domain_2_value_4 -> BOLT_MOVE_TO_HERO: Retail 0x002a7374-0x002a7388 stores attraction yaw/pitch, zero speed and supplied target in bolt vars; 0x002a7390-0x002a73fc constructs spin from velocity and target displacement. At 0x002a7400-0x002a7408 it writes 4 to the same bolt s2+0x20 state byte and returns success. Supplied bolt_update's canonical BOLT_MOVE_TO_HERO=4 branch consumes those initialized fields for collection movement; reuse the same member as the entry guard. --- src/overlays/shared/pickups/bolt.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/pickups/bolt.c b/src/overlays/shared/pickups/bolt.c index 8ce7c93691..fdfe55ff1f 100644 --- a/src/overlays/shared/pickups/bolt.c +++ b/src/overlays/shared/pickups/bolt.c @@ -659,6 +659,10 @@ int begin_bolt_attraction(void *ov, float attraction_yaw_angle, float attraction_pitch_angle) { + enum { + BOLT_IDLE = 3, + BOLT_MOVE_TO_HERO = 4 + }; char *bolt_moby = ov; char *target_moby = tv; char *bolt_vars = ((char *)MOBY(bolt_moby)->pvars); @@ -666,7 +670,7 @@ int begin_bolt_attraction(void *ov, float k; float attraction_geometry_scratch[3][4] __attribute__((aligned(16))); - if (MOBY(bolt_moby)->state == 4) { + if (MOBY(bolt_moby)->state == BOLT_MOVE_TO_HERO) { return 0; } sound_cooldown_frames = scale_game_frames(3); @@ -681,7 +685,7 @@ int begin_bolt_attraction(void *ov, if (attraction_pitch_angle == 0.0f) attraction_pitch_angle = random_float_between(0.0f, 30.0f) * DEG_TO_RAD; } - if (MOBY(bolt_moby)->state == 3) { + if (MOBY(bolt_moby)->state == BOLT_IDLE) { euler_rotation_basis(attraction_geometry_scratch, bolt_vars + 0x10); fast_vec_normalize(bolt_vars + 0x20, attraction_geometry_scratch[2], @@ -702,7 +706,7 @@ int begin_bolt_attraction(void *ov, DEG_TO_RAD; build_quaternion_from_axis_angle(bolt_vars + 0x30, bolt_vars + 0x30, k * frame_time); } - MOBY(bolt_moby)->state = 4; + MOBY(bolt_moby)->state = BOLT_MOVE_TO_HERO; return 1; } From de838703a4bd67f7fa22d5a054acce0258836f3b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:27:32 +0000 Subject: [PATCH 0651/1502] decomp: clarify names in electric_gate_update domain_0_value_1 -> ELECTRIC_GATE_WAIT_FOR_TRIGGER: Source snapshot 914bb298890bdac6e36a53e2aac4853884c97fe4b16d2b282bb9903d472000f9 assigns 1 to MOBY(gate_moby)->state during ELECTRIC_GATE_INITIALIZE. Retail 0030dc9c loads that same +0x20 state byte; 0030dca0 dispatches value 1 to 0030dcf8, the source's ELECTRIC_GATE_WAIT_FOR_TRIGGER case. Retail 0030dc6c loads v1=1 and 0030dcdc stores v1 at +0x20, proving this assignment enters that exact existing local enum member, not an unrelated control domain. domain_1_value_2 -> ELECTRIC_GATE_TRIGGERED: Source snapshot 914bb298890bdac6e36a53e2aac4853884c97fe4b16d2b282bb9903d472000f9 assigns 2 to MOBY(gate_moby)->state after the linked moby's +0xBC trigger byte is nonzero. Retail 0030de2c-0030de30 tests that byte; 0030de44 loads v1=2, 0030de48 clears gate collision at +0x94, and 0030de50 writes v1 to gate state +0x20. The same state byte loaded at 0030dc9c dispatches value 2 via 0030dcc4 to 0030de54-0030de5c, the source's existing ELECTRIC_GATE_TRIGGERED case that keeps collision cleared. Original retail decompilation agrees, proving reuse of this local state member. --- src/overlays/l05/mobys/electric_gate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l05/mobys/electric_gate.c b/src/overlays/l05/mobys/electric_gate.c index 7b54d20044..0a14725196 100644 --- a/src/overlays/l05/mobys/electric_gate.c +++ b/src/overlays/l05/mobys/electric_gate.c @@ -45,7 +45,7 @@ void electric_gate_update(char *gate_moby) { switch (state) { case ELECTRIC_GATE_INITIALIZE: MOBY(gate_moby)->flags |= 1; - MOBY(gate_moby)->state = 1; + MOBY(gate_moby)->state = ELECTRIC_GATE_WAIT_FOR_TRIGGER; MOBY(gate_moby)->visible = 0; *electric_gate_vars->unk4 = -1; break; @@ -88,7 +88,7 @@ void electric_gate_update(char *gate_moby) { 0) { allocate_voice_for_target_entry(1, 0, gate_moby); MOBY(gate_moby)->collision = 0; - MOBY(gate_moby)->state = 2; + MOBY(gate_moby)->state = ELECTRIC_GATE_TRIGGERED; } } break; From 373385de3b84c3f0ef70bcb4d96a3647019f7f7b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:27:32 +0000 Subject: [PATCH 0652/1502] decomp: clarify names in initialize_menu_preview_scene domain_0_value_2 -> MENU_STATE_INITIAL_PAGE_TRANSITION_PENDING: Retail 0x00218fa4/0x00218fb0 stores 2 to 0x001d5bf0 (menu_system.state); 0x00218fe4/0x00218ff0 sets next/current to initial page 0x001d45c8. Checked caller 0x0021939c-0x002193a4 distinguishes transition state 1; state 2 instead reaches the nonzero next-page path at 0x00219428. That path configures page animations, then 0x00219598 sets state 1 and 0x0021959c starts its 12-tick timer. On timer completion 0x002193c4-0x002193dc installs the pending page and its state. Thus this assignment marks the initialized initial page pending the page transition, in the menu-system state domain, unrelated to equal-valued MenuTextAction members. --- src/ui/menus/initialize_menu_preview_scene.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/menus/initialize_menu_preview_scene.c b/src/ui/menus/initialize_menu_preview_scene.c index d2da0524c1..d5fd7eaeaf 100644 --- a/src/ui/menus/initialize_menu_preview_scene.c +++ b/src/ui/menus/initialize_menu_preview_scene.c @@ -52,10 +52,13 @@ extern s32 set_moby_animation() __asm__("func_00212ED8"); void initialize_menu_preview_scene(void) __asm__("FUN_00218f98"); void initialize_menu_preview_scene(void) { + enum { + MENU_STATE_INITIAL_PAGE_TRANSITION_PENDING = 2 + }; s32 i; s32 preview_workspace_start, graphics_workspace_base, help_text_buffer_start, graphics_buffer_start; - menu_system.state = 2; + menu_system.state = MENU_STATE_INITIAL_PAGE_TRANSITION_PENDING; menu_system.current = &menu_preview_initial_page; menu_system.next = &menu_preview_initial_page; menu_system.close_locked = 0; From 887f05bfd1bc449c691600ab9f5a7c176a50f03a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:29:22 +0000 Subject: [PATCH 0653/1502] decomp: clarify names in update_ballistic_effect_particle_with_contact_spawns domain_0_value_0 -> BALLISTIC_PARTICLE_MODE_NO_CONTACT_TEST: Source mode is loaded from particle_data + 0x10 (particle + 0x30), initialized by FUN_L00_0026f548 from its k argument independently of hero state. Retail 0x0026f67c-0x0026f698 compares this payload integer to zero and directly adds payload velocity to particle position with no collision or water-surface test, then joins the gravity/countdown/fade tail at 0x0026f818. Original Ghidra iVar2 == 0 has the same direct-add branch. domain_1_value_1 -> BALLISTIC_PARTICLE_MODE_LINE_CONTACT_HEIGHT_SNAPPED_SPAWN: The same particle payload mode loaded at 0x0026f67c is compared to 1 at 0x0026f6a0. Retail 0x0026f6ac-0x0026f6d4 computes position plus velocity on the stack and tests the line segment from current to next position. On contact, 0x0026f6dc-0x0026f710 conditionally invokes spawn_moving_resizing_height_snapped_alpha_fade_particle at shared hit position 0x00173e60 only when collision_hit_material returns zero, then frees the original at 0x0026f7fc. The source and original Ghidra show the same conditional secondary spawn; no material identity is inferred. domain_2_value_3 -> BALLISTIC_PARTICLE_MODE_WATER_SURFACE_CONTACT_SPAWN: Retail 0x0026f71c compares the particle payload mode to 3, then 0x0026f724-0x0026f730 advances position by velocity. At 0x0026f738-0x0026f748, particle Z is compared with the value loaded from 0x0013f640, identified by authoritative source as hero.water_surface_z. When below it, 0x0026f76c clamps particle Z to that surface, 0x0026f770 spawns at particle_position, and 0x0026f7fc frees the original. Original Ghidra shows the same fRam0013f640 comparison, assignment and spawn. This is a particle contact mode, not hero.state.current. --- .../effects/update_three_phase_effect_particle.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c b/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c index 1f07b4efda..478a8b5202 100644 --- a/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c +++ b/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c @@ -2962,14 +2962,14 @@ spawn_random_planar_drift_particle(void *, int, float, float) __asm__("FUN_L00_0 void update_ballistic_effect_particle_with_contact_spawns(struct EffectParticle *) __asm__("FUN_L00_0026f660"); void update_ballistic_effect_particle_with_contact_spawns(struct EffectParticle *particle) { - char *particle_data = particle->data; + enum { BALLISTIC_PARTICLE_MODE_NO_CONTACT_TEST = 0 , BALLISTIC_PARTICLE_MODE_LINE_CONTACT_HEIGHT_SNAPPED_SPAWN = 1 , BALLISTIC_PARTICLE_MODE_WATER_SURFACE_CONTACT_SPAWN = 3 } ;char *particle_data = particle->data; int mode = *(int *)(particle_data + 0x10); V next_position; char *particle_position; - if (mode == 0) { + if (mode == BALLISTIC_PARTICLE_MODE_NO_CONTACT_TEST) { fast_vec_add(particle->pos.f, particle->pos.f, particle_data); - } else if (mode == 1) { + } else if (mode == BALLISTIC_PARTICLE_MODE_LINE_CONTACT_HEIGHT_SNAPPED_SPAWN) { particle_position = particle->pos.f; fast_vec_add(&next_position, particle_position, particle_data); if (collision_line(particle_position, &next_position, 2, 0, 0)) { @@ -2981,7 +2981,7 @@ void update_ballistic_effect_particle_with_contact_spawns(struct EffectParticle return; } qcopy(particle_position, &next_position); - } else if (mode == 3) { + } else if (mode == BALLISTIC_PARTICLE_MODE_WATER_SURFACE_CONTACT_SPAWN) { float water_surface_z; particle_position = particle->pos.f; fast_vec_add(particle_position, particle_position, particle_data); From 545c3fdf524530059c6bc9e85478b6bffe7335cf Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:29:22 +0000 Subject: [PATCH 0654/1502] decomp: clarify names in lieutenant_update domain_0_value_3 -> LIEUTENANT_STATE_DISABLED: Retail 0x002e30e4 reads moby state from 0x20(s1), the same byte written at 0x002e324c with 3 after the persistence sentinel branch at 0x002e3148. This path clears collision at +0x94 and sets flags 0x41, matching the existing LIEUTENANT_STATE_DISABLED case at 0x002e3278-0x002e3284. Reuse the existing local member for this state assignment. domain_1_value_1 -> LIEUTENANT_STATE_UPDATE_DIALOGUE: Retail 0x002e3150 writes s2=1 to moby state +0x20 immediately before initialize_npc_dialogue at 0x002e3154. The same state byte is dispatched by 0x002e30e4-0x002e30e8 to 0x002e3164, whose alpha updates and update_npc_dialogue call match the existing local LIEUTENANT_STATE_UPDATE_DIALOGUE case. The assignment therefore reuses that exact selector-domain member. domain_2_value_2 -> LIEUTENANT_STATE_UNLOCK_PLANET_AND_DISABLE: Retail 0x002e3198 calls update_npc_dialogue and on nonzero return 0x002e31a4-0x002e31ac stores 2 to moby+0x20. Dispatch of that same byte at 0x002e3108 reaches 0x002e31b0, the existing LIEUTENANT_STATE_UNLOCK_PLANET_AND_DISABLE case: it gates on pvars phase, unlocks planet 6, sets up camera, saves and disables. Reuse its existing local enum member. domain_4_value_3 -> LIEUTENANT_STATE_DISABLED: After unlock_planet, camera activation and memcard_save_data, retail 0x002e3248-0x002e325c writes 3 to moby+0x20, clears collision and sets flags 0x41. The dispatcher reads the identical state byte at 0x002e30e4 and routes 3 at 0x002e3110 to the existing LIEUTENANT_STATE_DISABLED behavior at 0x002e3278. This assignment uses that existing local member. --- src/overlays/l04/mobys/lieutenant.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l04/mobys/lieutenant.c b/src/overlays/l04/mobys/lieutenant.c index 4a5e8a0596..ef3ee56276 100644 --- a/src/overlays/l04/mobys/lieutenant.c +++ b/src/overlays/l04/mobys/lieutenant.c @@ -72,12 +72,12 @@ void lieutenant_update(struct Moby *moby) { switch (moby->state) { case LIEUTENANT_STATE_INITIALIZE: if (D_0014C050[((struct VendorMobyView *)moby)->slot + current_level_index * 16] == 0xFF) { - moby->state = 3; + moby->state = LIEUTENANT_STATE_DISABLED; moby->flags |= 0x41; moby->collision = 0; break; } - moby->state = 1; + moby->state = LIEUTENANT_STATE_UPDATE_DIALOGUE; initialize_npc_dialogue(moby, lieutenant_dialogue_vars); break; case LIEUTENANT_STATE_UPDATE_DIALOGUE: @@ -86,7 +86,7 @@ void lieutenant_update(struct Moby *moby) { else lieutenant_dialogue_vars->alpha = 1.0f; if (update_npc_dialogue(moby, lieutenant_dialogue_vars)) - moby->state = 2; + moby->state = LIEUTENANT_STATE_UNLOCK_PLANET_AND_DISABLE; break; case LIEUTENANT_STATE_UNLOCK_PLANET_AND_DISABLE: if (lieutenant_dialogue_vars->phase == 2) { @@ -101,7 +101,7 @@ void lieutenant_update(struct Moby *moby) { qcopy(&l04_lieutenant_shop_camera.rot, rotation_ptr); l04_lieutenant_shop_camera.active = 1; memcard_save_data(0, -1); - moby->state = 3; + moby->state = LIEUTENANT_STATE_DISABLED; moby->flags |= 0x41; moby->collision = 0; break; From c4ea71825a587837bebba40fb44a1afa4dc79f79 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:29:22 +0000 Subject: [PATCH 0655/1502] decomp: clarify names in process_helicopter_hits domain_1_value_7 -> HELICOPTER_DEATH_EFFECTS: Retail 0x002c6918 retains the helicopter moby argument in s0; 0x002c6980-0x002c6984 reads its state byte at +0x20 and excludes 7. The same moby is passed by helicopter_update before switch(moby->state), whose established HELICOPTER_DEATH_EFFECTS=7 case spawns the explosion, detaches turret manipulators and enters dead reset wait. This is the helicopter state domain, not HeroStateId. domain_2_value_64 -> HELICOPTER_DEAD_WAIT_FOR_RESET: Retail 0x002c6980-0x002c698c compares the supplied helicopter moby's state byte at +0x20 against 0x40 to skip further hit processing. The caller helicopter_update switches on that same moby->state; its established HELICOPTER_DEAD_WAIT_FOR_RESET=0x40 case disables collision, clears save flags and resets to initialization when the vehicle mode changes. domain_3_value_7 -> HELICOPTER_DEATH_EFFECTS: Retail 0x002c6994-0x002c69b8 subtracts hit damage from helicopter pvars+0x20 health and stores 7 to the same moby state byte at +0x20 when health is nonpositive or reaction code is 1. Caller helicopter_update dispatches this very field to established HELICOPTER_DEATH_EFFECTS=7, which spawns the death explosion and detaches manipulators. domain_4_value_6 -> HELICOPTER_RECOIL: Retail 0x002c69f4-0x002c69fc loads 6 into s3 and compares it against the supplied helicopter moby's state byte +0x20 before applying directional rotation impulses. Caller helicopter_update dispatches the same field with established HELICOPTER_RECOIL=6; that branch decrements recoil_timer, moves backward and restores moby->command when the timer expires. domain_5_value_6 -> HELICOPTER_RECOIL: Retail 0x002c6adc stores the scaled 60-frame timer at helicopter pvars+0x16a; 0x002c6ae0-0x002c6ae8 saves the previous state to moby+0xbc and writes s3=6 to moby+0x20. Caller helicopter_update's established HELICOPTER_RECOIL=6 branch consumes recoil_timer and returns to moby->command, proving this assignment enters that helicopter state. --- src/overlays/l15/mobys/helicopter.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/l15/mobys/helicopter.c b/src/overlays/l15/mobys/helicopter.c index efa8d32571..890c8f9ad3 100644 --- a/src/overlays/l15/mobys/helicopter.c +++ b/src/overlays/l15/mobys/helicopter.c @@ -884,6 +884,11 @@ extern void trooper_anim_update(void *m, short *p) __asm__("FUN_L00_0025d458"); extern void trooper_anim_finish(void *, void *) __asm__("FUN_L00_0025d538"); void process_helicopter_hits(struct Moby *moby) { + enum { + HELICOPTER_RECOIL = 6, + HELICOPTER_DEATH_EFFECTS = 7, + HELICOPTER_DEAD_WAIT_FOR_RESET = 0x40 + }; int hit_reaction_status; float fv; int hit_reaction_code; @@ -895,15 +900,15 @@ void process_helicopter_hits(struct Moby *moby) { hit_record = find_moby_hit(moby, 0x330000, 0); hit_reaction_code = hit_reaction(moby, hit_record, helicopter_vars + 0x20, 0, &hit_reaction_status, &fv, 0, 4); - if (hit_reaction_status != 1 && moby->state != 7 && moby->state != 0x40) { + if (hit_reaction_status != 1 && moby->state != HELICOPTER_DEATH_EFFECTS && moby->state != HELICOPTER_DEAD_WAIT_FOR_RESET) { float remaining_health = *(float *)(helicopter_vars + 0x20) - fv; *(float *)(helicopter_vars + 0x20) = remaining_health; if (hit_reaction_code == 1 || remaining_health <= 0.0f) { - moby->state = 7; + moby->state = HELICOPTER_DEATH_EFFECTS; } else if (hit_reaction_code != 0xB) { *(unsigned char *)(helicopter_vars + 0x67) = 0xB4; trooper_anim_update(moby, (short *)(helicopter_vars + 0x60)); - if (*(float *)(hit_record + 0x1C) == 5627.925f && moby->state != 6) { + if (*(float *)(hit_record + 0x1C) == 5627.925f && moby->state != HELICOPTER_RECOIL) { hit_away_heading = fast_arc_tan(moby->pos.x - *(float *)(hit_record + 0), moby->pos.y - *(float *)(hit_record + 4)); relative_hit_heading = fast_subtract_rotations(hit_away_heading, moby->rot.z); @@ -920,7 +925,7 @@ void process_helicopter_hits(struct Moby *moby) { *(float *)(helicopter_vars + 0x170) = frame_time * 4.0f; *(short *)(helicopter_vars + 0x16A) = scale_game_frames(0x3C); moby->command = moby->state; - moby->state = 6; + moby->state = HELICOPTER_RECOIL; } } } From 9cba593fd001e23416bbad14c25b9179badaa27a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:31:02 +0000 Subject: [PATCH 0656/1502] decomp: clarify names in try_transition_hero_water_state domain_0_value_106 -> HERO_STATE_DROWN: Retail 0x00227850 loads a0=0x6a after the zero-air and height/pitch/displacement checks, reaching hero_set_state at 0x002278bc. The source state local is that call's requested_state, which the supplied setter writes into hero.state.current. This proves the HeroStateId domain; its canonical member HERO_STATE_DROWN is 106 in include/rnc/hero/hero_state.h. domain_1_value_6 -> HERO_STATE_FALL: Retail 0x00227898-0x002278b4 tests hero position above water_surface_z+0.4 and loads a0=6 for the shared hero_set_state call at 0x002278bc. Source state therefore denotes requested hero current state, as the supplied setter assigns requested_state to hero.state.current. The proven HeroStateId domain defines its canonical member HERO_STATE_FALL as 6. domain_2_value_53 -> HERO_STATE_SWIM_WITH_CROUCH_INPUT: Retail collision hit at 0x0022795c followed by item_available[4] and pad_held_lui mask 0x0a checks reaches 0x00227978-0x0022797c, loading a0=0x35 and branching to hero_set_state at 0x002278bc. The supplied setter writes this requested_state to hero.state.current, proving HeroStateId membership. Its canonical member for 53 is HERO_STATE_SWIM_WITH_CROUCH_INPUT. --- src/overlays/shared/hero/try_transition_hero_water_state.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/hero/try_transition_hero_water_state.c b/src/overlays/shared/hero/try_transition_hero_water_state.c index 7df9da5276..891544d62e 100644 --- a/src/overlays/shared/hero/try_transition_hero_water_state.c +++ b/src/overlays/shared/hero/try_transition_hero_water_state.c @@ -48,10 +48,10 @@ int try_transition_hero_water_state(void) { if (hero.underwater_air == 0 && (!(hero.water_surface_z - 2.0f < hero.motion.pos.f[2]) || !(hero.motion.rot.f[1] < -0.87266463f) || !(frame_time < hero.motion.displacement.f[2]))) { - state = 0x6A; + state = HERO_STATE_DROWN; } else if (hero.water_surface_z + 0.4f < hero.motion.pos.f[2]) { D_L00_00167014[0] = 0; - state = 6; + state = HERO_STATE_FALL; } else { goto collision_mode; } @@ -70,7 +70,7 @@ int try_transition_hero_water_state(void) { end.f[2] += 0.3f; if (collision_line(&start, &end, 2, hero.moby, 0)) { if (item_available[4] != 0 && (((u32)pad_held_lui) & 10) != 0) { - state = 0x35; + state = HERO_STATE_SWIM_WITH_CROUCH_INPUT; goto change_state; } /* Retail keeps this as its own call site. Through the int-returning From bf1d71c29ec30887818426c54f7059bc63ae8ea2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:31:02 +0000 Subject: [PATCH 0657/1502] decomp: clarify names in upper_door_update domain_0_value_1 -> UPPER_DOOR_WAIT_FOR_ACTIVATION: Retail 0x002e17ec retains the input moby in s0; 0x002e17f4 loads its state byte at +0x20, and 0x002e17f8 branches on state 1 to the activation checks at 0x002e183c. Initialization copies pos.z into baseZ at 0x002e182c-0x002e1830 and stores 1 into that same s0+0x20 byte at 0x002e1838. This assignment therefore enters the exact selector domain already named UPPER_DOOR_WAIT_FOR_ACTIVATION in the current function's local enum. domain_3_value_2 -> UPPER_DOOR_MOVE_VERTICAL: Retail 0x002e1918 loads 2 and 0x002e1924 stores it into the input moby's state byte s0+0x20 after activation, while 0x002e1920-0x002e192c loads the scaled 60-frame timer. The dispatch at 0x002e181c sends that same moby state 2 to 0x002e1930, whose speed call and floating-point operations update pos.z at 0x002e1944-0x002e1954. This is the identical local enum domain and member already named UPPER_DOOR_MOVE_VERTICAL. domain_4_value_3 -> UPPER_DOOR_MOVEMENT_COMPLETE: Within the input moby's state-2 vertical movement branch, retail 0x002e1950 calls the timer decrement helper using pvars+8 and 0x002e1958 skips completion when it returns zero. On expiry, 0x002e1960-0x002e19cc records the moby's save-ID bit in both level bitsets, then 0x002e19d8/0x002e19ec loads 3 and 0x002e19f0 writes it to the same input moby's state byte s0+0x20. The entry dispatch handles only states 0, 1 and 2, so state 3 ends this function's timed vertical movement. --- src/overlays/l04/mobys/upper_door.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/l04/mobys/upper_door.c b/src/overlays/l04/mobys/upper_door.c index 60209c3e99..154509b6eb 100644 --- a/src/overlays/l04/mobys/upper_door.c +++ b/src/overlays/l04/mobys/upper_door.c @@ -55,6 +55,9 @@ void upper_door_update(struct Moby *moby) { UPPER_DOOR_WAIT_FOR_ACTIVATION = 1, UPPER_DOOR_MOVE_VERTICAL = 2 }; + enum { + UPPER_DOOR_MOVEMENT_COMPLETE = 3 + }; struct RiserVars *riser_vars = (struct RiserVars *)moby->pvars; struct Moby *trigger_moby; s16 save_id_index; @@ -63,7 +66,7 @@ void upper_door_update(struct Moby *moby) { switch (moby->state) { case UPPER_DOOR_INITIALIZE: riser_vars->baseZ = moby->pos.z; - moby->state = 1; + moby->state = UPPER_DOOR_WAIT_FOR_ACTIVATION; break; case UPPER_DOOR_WAIT_FOR_ACTIVATION: id = moby->save_id; @@ -79,7 +82,7 @@ void upper_door_update(struct Moby *moby) { } if (moby->oclass == 0x44D || moby->oclass == 0x5FC) trooper_play_sound(0, 0, moby, 0x44D); - moby->state = 2; + moby->state = UPPER_DOOR_MOVE_VERTICAL; riser_vars->timer = scale_game_frames(60); break; case UPPER_DOOR_MOVE_VERTICAL: @@ -90,7 +93,7 @@ void upper_door_update(struct Moby *moby) { level_completed_save_id_bits[(s16)moby->save_id >> 5] |= 1 << (moby->save_id & 0x1F); if (moby->oclass == 0x44D) allocate_voice_for_target_entry(1, 0, moby); - moby->state = 3; + moby->state = UPPER_DOOR_MOVEMENT_COMPLETE; } break; } From c21dba128ea8fd89d7b3fcae4f423aa75c155585 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:32:44 +0000 Subject: [PATCH 0658/1502] decomp: clarify names in handle_blarg_helicopter_hits domain_1_value_5 -> BLARG_HELICOPTER_DESTROY: Retail 0x002ce250 preserves helicopter_moby in s0; 0x002ce2b8-0x002ce2bc reads its state byte at +0x20 and skips processing when it equals 5. The supplied blarg_helicopter_update passes this same moby to this handler before switching on moby->state, whose existing BLARG_HELICOPTER_DESTROY=5 branch spawns explosions and removes the moby. This is that current-state domain, not the independent hit_reaction status. domain_2_value_5 -> BLARG_HELICOPTER_DESTROY: Retail 0x002ce2c4-0x002ce2d0 subtracts hit damage from helicopter private health and stores it; hit_reaction return 1 or remaining health <=0 reaches 0x002ce2e8, storing 5 into the same s0+0x20 current-state byte. The owner blarg_helicopter_update calls this helper before its state switch and names state 5 BLARG_HELICOPTER_DESTROY, whose branch explodes and removes this moby. domain_3_value_4 -> BLARG_HELICOPTER_TIMED_REACTION: Retail 0x002ce324 loads s3=4 and 0x002ce328-0x002ce32c compares that with helicopter_moby current state at s0+0x20 to avoid reentering the reaction. The same caller passes its moby into this handler before its switch; its existing BLARG_HELICOPTER_TIMED_REACTION=4 branch decrements data->reaction_timer and restores moby->previous_state. Thus the selector is the established helicopter current-state domain. domain_4_value_4 -> BLARG_HELICOPTER_TIMED_REACTION: Retail 0x002ce404-0x002ce40c scales 60 frames and stores the reaction timer at private-data+0x206; 0x002ce41c-0x002ce428 saves current state to moby+0xBC and stores s3=4 to moby+0x20 after applying reaction tilt. Caller blarg_helicopter_update passes the same moby and switches on this byte; BLARG_HELICOPTER_TIMED_REACTION=4 decrements that timer and restores previous_state, proving the existing canonical state name. --- src/overlays/shared/enemies/blarg_helicopter.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/enemies/blarg_helicopter.c b/src/overlays/shared/enemies/blarg_helicopter.c index f9d514b5bc..0042422f9d 100644 --- a/src/overlays/shared/enemies/blarg_helicopter.c +++ b/src/overlays/shared/enemies/blarg_helicopter.c @@ -856,6 +856,10 @@ void blarg_helicopter_update(HMob49 *moby) { /* Ported from rac1-decomp (src/overlays/shared/vendor_00292AC0.c: func_L03_002CF600), where it is exact; names translated to the US level program. */ void handle_blarg_helicopter_hits(char *helicopter_moby) { + enum { + BLARG_HELICOPTER_TIMED_REACTION = 4, + BLARG_HELICOPTER_DESTROY = 5 + }; int hit_reaction_status; float fv; int hit_reaction_result; @@ -868,15 +872,15 @@ void handle_blarg_helicopter_hits(char *helicopter_moby) { hit_record = find_moby_hit(helicopter_moby, 0x330000, 0); hit_reaction_result = hit_reaction( helicopter_moby, hit_record, helicopter_data + 0x20, 0, &hit_reaction_status, &fv, 0, 4); - if (hit_reaction_status != 1 && MOBY(helicopter_moby)->state != 5) { + if (hit_reaction_status != 1 && MOBY(helicopter_moby)->state != BLARG_HELICOPTER_DESTROY) { float remaining_health = *(float *)(helicopter_data + 0x20) - fv; *(float *)(helicopter_data + 0x20) = remaining_health; if (hit_reaction_result == 1 || remaining_health <= 0.0f) { - MOBY(helicopter_moby)->state = 5; + MOBY(helicopter_moby)->state = BLARG_HELICOPTER_DESTROY; } else if (hit_reaction_result != 0xB) { *(unsigned char *)(helicopter_data + 0x67) = 0xB4; trooper_anim_update(helicopter_moby, (short *)(helicopter_data + 0x60)); - if (*(float *)(hit_record + 0x1C) == 5627.925f && MOBY(helicopter_moby)->state != 4) { + if (*(float *)(hit_record + 0x1C) == 5627.925f && MOBY(helicopter_moby)->state != BLARG_HELICOPTER_TIMED_REACTION) { reaction_heading_angle = fast_arc_tan(MOBY(helicopter_moby)->pos.x - *(float *)(hit_record + 0), MOBY(helicopter_moby)->pos.y - *(float *)(hit_record + 4)); @@ -897,7 +901,7 @@ void handle_blarg_helicopter_hits(char *helicopter_moby) { *(float *)(helicopter_data + 0x214) = frame_time * 4.0f; *(short *)(helicopter_data + 0x206) = scale_game_frames(0x3C); MOBY(helicopter_moby)->command = MOBY(helicopter_moby)->state; - MOBY(helicopter_moby)->state = 4; + MOBY(helicopter_moby)->state = BLARG_HELICOPTER_TIMED_REACTION; allocate_voice_for_target_entry(1, 0, (int)helicopter_moby); } } From f04c5746f4cd5527bb96e8bc7bda31daa70af321 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:32:44 +0000 Subject: [PATCH 0659/1502] decomp: clarify names in blarg_gunner_update domain_0_value_1 -> BLARG_GUNNER_STATE_ACTIVE: Retail 0x002b4c94 keeps the moby argument in s1; 0x002b4ca0 reads its state byte at +0x20 and 0x002b4ca4 dispatches value 1 to 0x002b4cf4. Initialization stores s3 (loaded with 1 at 0x002b4c8c) to the identical +0x20 state byte at 0x002b4ce0. Thus the assignment enters the same state already named BLARG_GUNNER_STATE_ACTIVE = 1 in this function's local enum and switch. That branch selects animations and calls process_blarg_gunner_hits at 0x002b4df0; this is the moby's current-state domain, not a boolean or the linked parent's state. --- src/overlays/l13/mobys/blarg_gunner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/blarg_gunner.c b/src/overlays/l13/mobys/blarg_gunner.c index 1913645121..347212d814 100644 --- a/src/overlays/l13/mobys/blarg_gunner.c +++ b/src/overlays/l13/mobys/blarg_gunner.c @@ -226,7 +226,7 @@ void blarg_gunner_update(struct Moby *moby) { switch (moby->state) { case BLARG_GUNNER_STATE_INITIALIZE: moby_vars[0x29] = 1; - moby->state = 1; + moby->state = BLARG_GUNNER_STATE_ACTIVE; moby_vars[0x5A] = 6; moby_vars[0x58] = 8; break; From 7d65a969b0ad578375be4c8d4acce802d4b6498d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:34:46 +0000 Subject: [PATCH 0660/1502] decomp: clarify names in emit_minibomber_exhaust_puffs domain_0_value_2 -> MINIBOMBER_STATE_FOLLOW_INTRO_OR_EXIT_PATH: Retail 0x002b5de4 retains the incoming moby in s0; 0x002b5e14 loads its state byte at +0x20 and 0x002b5e18 compares it unsigned against 2. Caller 0x002b47b0/0x002b47b4 passes the same s3 moby, whose state is also loaded at 0x002b47e8 and 0x002b521c. The authoritative caller's local enum explicitly names state 2 MINIBOMBER_STATE_FOLLOW_INTRO_OR_EXIT_PATH; that case selects intro path fD0 or exit path f150 via f10C and calls advance_minibomber_along_path. Thus this comparison uses that same current-state domain and canonical member as the lower emission threshold, not a request/control mode. domain_1_value_9 -> MINIBOMBER_STATE_DESTROY: Retail 0x002b5e14 loads incoming moby's +0x20 current-state byte; 0x002b5e24 loads 9 and 0x002b5e28 returns when equal. Caller 0x002b47b0/0x002b47b4 supplies that same moby pointer. In the authoritative source minibomber_update explicitly declares MINIBOMBER_STATE_DESTROY = 9; its case emits destruction effects, releases any owned voice slot and marks the moby for removal. Bounded caller retail 0x002b5110-0x002b5210 agrees with those effects and removal, and 0x002b521c-0x002b5230 repeats the same +0x20 state exclusion. This is the established minibomber destruction state, separate from particle tail mode. --- src/overlays/l14/mobys/minibomber.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/minibomber.c b/src/overlays/l14/mobys/minibomber.c index fbf8894c9a..36bdc9382b 100644 --- a/src/overlays/l14/mobys/minibomber.c +++ b/src/overlays/l14/mobys/minibomber.c @@ -1127,6 +1127,10 @@ void initialize_minibomber_path_following(struct Moby *moby) { void emit_minibomber_exhaust_puffs(struct Moby *moby) __asm__("FUN_L14_002b5dd8"); void emit_minibomber_exhaust_puffs(struct Moby *moby) { + enum { + MINIBOMBER_STATE_FOLLOW_INTRO_OR_EXIT_PATH = 2, + MINIBOMBER_STATE_DESTROY = 9 + }; float exhaust_position_offset[4]; float pos[4]; int i; @@ -1134,7 +1138,7 @@ void emit_minibomber_exhaust_puffs(struct Moby *moby) { int signed_puff_value; int life; float size; - if (moby->state < 2 || moby->state == 9) + if (moby->state < MINIBOMBER_STATE_FOLLOW_INTRO_OR_EXIT_PATH || moby->state == MINIBOMBER_STATE_DESTROY) return; fast_vec_scale(exhaust_position_offset, &moby->rot_row0, -1.25f); fast_vec_add(pos, &moby->pos, exhaust_position_offset); From 4868fd36b39a6abf9c5e88418dc9ded3d5222505 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:34:46 +0000 Subject: [PATCH 0661/1502] decomp: clarify names in update_cutscene_effects domain_0_value_1 -> MOBY_STATE_UPDATE: Authoritative source (SHA-256 183ec098f1c72e63bc2c8664db98783f1372aa8215a078cd0e48f1166ad620ee) reads state from moby->state and dispatches case MOBY_STATE_UPDATE = 1. Retail 0x0031ebd4 loads the byte at a0+0x20; 0x0031ebdc/0x0031ebe0 dispatch value 1 to recurring update work at 0x0031ec04. Initialization 0x0031ebf4/0x0031ebf8 writes value 1 back to that exact byte. Original Ghidra likewise assigns param_1+0x20=1 and then tests that byte for 1 on subsequent updates. Thus this assignment enters the existing local MOBY_STATE_UPDATE domain member, independently of the unrelated scene_state gate. --- src/overlays/l07/mobys/cutscene_effects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l07/mobys/cutscene_effects.c b/src/overlays/l07/mobys/cutscene_effects.c index 29c7ce9214..cb2ed7fcfa 100644 --- a/src/overlays/l07/mobys/cutscene_effects.c +++ b/src/overlays/l07/mobys/cutscene_effects.c @@ -42,7 +42,7 @@ void cutscene_effects_update(struct Moby *moby) { switch (state) { case MOBY_STATE_INITIALIZE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = MOBY_STATE_UPDATE; break; case MOBY_STATE_UPDATE: current_scene_state = scene_state; From 93cd62cb6f0ab50cf27ec227b269566e2f667a60 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:34:47 +0000 Subject: [PATCH 0662/1502] decomp: clarify names in draw_group_moby_effect_quads domain_0_value_1 -> GROUP_MOBY_STATE_INACTIVE: Retail 0x002a2a80-0x002a2a94 resolves a group entry's low 15-bit index through l15_moby_array; lbu v1,0x20(s1) at 0x002a2a98 reads that member's Moby.state, and li v0,1 / beq at 0x002a2a9c-0x002a2aa0 skips all four effect quads. This is the group-moby state domain, not a hero mode. In the authoritative same-file update_hero_seeking_group_moby, state 1 suppresses particle generation and callback registration and has no state-machine action. The s4 burst path falls through s0, which assigns state byte 1, clears byte 0x31, sets flags bit 1 and clears collision; the disabled global gate also assigns 1 and clears collision. Together these establish an inactive group-moby state, rather than just an unnamed drawing exception. --- src/overlays/shared/enemies/hero_seeking_mine.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/hero_seeking_mine.c b/src/overlays/shared/enemies/hero_seeking_mine.c index a7803ca4ab..736a170b43 100644 --- a/src/overlays/shared/enemies/hero_seeking_mine.c +++ b/src/overlays/shared/enemies/hero_seeking_mine.c @@ -190,6 +190,9 @@ void hero_seeking_mine_update(char *moby) { } void draw_group_moby_effect_quads(unsigned char *moby) { + enum { + GROUP_MOBY_STATE_INACTIVE = 1 + }; EffectQuad effect_quad; float angles[4] __attribute__((aligned(16))); float rotation[12] __attribute__((aligned(16))); @@ -219,7 +222,7 @@ void draw_group_moby_effect_quads(unsigned char *moby) { do { unsigned char *group_member_moby = (unsigned char *)((int)l15_moby_array + ((*group_moby_entry & 0x7fff) << 8)); - if (MOBY(group_member_moby)->state != 1) { + if (MOBY(group_member_moby)->state != GROUP_MOBY_STATE_INACTIVE) { clear_u64_value(angles); angles[2] = fast_arc_tan(l15_camera.pos.f[0] - MOBY(group_member_moby)->pos.x, l15_camera.pos.f[1] - MOBY(group_member_moby)->pos.y); From b1012e776d7f094affee308f542f5652d260259a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:36:34 +0000 Subject: [PATCH 0663/1502] decomp: clarify names in map_filter_l07_0 domain_0_value_0 -> FALSE: At 0x00206d48 retail clears a0 to zero for the derived special_state gate. Only the control_mode 17/18 or base_condition == 1 path replaces it with one; 0x00206d60 rejects a zero gate before the four polygon edge tests. Original Ghidra explicitly renders this binding as bool bVar1 = false. Thus the listed special_state = 0 assignment is Boolean FALSE, not a hero enum member. domain_1_value_1 -> TRUE: Retail 0x00206d38-0x00206d54 tests control_mode minus 0x11 unsigned below two, or base_condition equal to one, reaching li a0,1 at 0x00206d5c. The immediately following zero test at 0x00206d60 gates polygon checks. Original Ghidra renders the assignment as bVar1 = true, proving the listed special_state = 1 is Boolean TRUE, not the control mode or state ID itself. --- src/ui/map/map_filters.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/map/map_filters.c b/src/ui/map/map_filters.c index 446a51709b..6b6b3672e1 100644 --- a/src/ui/map/map_filters.c +++ b/src/ui/map/map_filters.c @@ -208,9 +208,9 @@ s32 map_filter_l07_0(s32 projected_x, s32 projected_y, f32 x, f32 y, f32 z) { } return 0; } else { - special_state = 0; + special_state = FALSE; if ((u32)(hero.state.control_mode - 0x11) < 2 || hero.base_condition == 1) { - special_state = 1; + special_state = TRUE; } if (special_state && point_is_clockwise(projected_x, projected_y, 0x12B, 0xB8, 0x13A, 0xF2) && From be1567e013e5f7dffb4b2b38ea3ab958e8e17a63 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:36:34 +0000 Subject: [PATCH 0664/1502] decomp: clarify names in update_rising_gate domain_0_value_1 -> GATE_WAIT_FOR_TRIGGER: Retail 0x00314f20 stores 1 at gate s0+0x20 after saving topZ at 0x00314f1c. The same byte is loaded at 0x00314ecc and value 1 branches at 0x00314ed0 to 0x00314f34, polling the indexed trigger command at +0xBC. This is the exact selector already named GATE_WAIT_FOR_TRIGGER in the authoritative C local enum. domain_1_value_2 -> GATE_RAISE_AND_SWING: Retail 0x00314f54-0x00314f5c stores 2 at gate s0+0x20 when the trigger command is 1. The state byte loaded at 0x00314ecc dispatches value 2 through 0x00314ef4 to 0x00314f80, whose separate timers drive height toward topZ and yaw toward zero. This is the same gate-state selector already named GATE_RAISE_AND_SWING in the C local enum, not the trigger command domain. domain_2_value_3 -> GATE_YAW_ALIGNED: On trigger command 2, retail 0x00314f68-0x00314f7c loads topZ, stores state 3 at gate s0+0x20, writes topZ to position +0x18 and zero to yaw +0x44. Thus this state records zero-yaw alignment, shared with the animated transition at 0x0031508c-0x003150a4. The same state byte is the function's switch selector; dispatch handles only states 0, 1 and 2. domain_3_value_3 -> GATE_YAW_ALIGNED: After the yaw approach call at retail 0x00315084, 0x0031508c-0x00315098 compares gate yaw s0+0x44 with zero f20. Only equality reaches the store of 3 to state s0+0x20 at 0x003150a4. This proves GATE_YAW_ALIGNED, the same zero-yaw state set by the immediate branch at 0x00314f70-0x00314f7c, without asserting height motion has finished. --- src/overlays/l05/mobys/rising_gate.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/overlays/l05/mobys/rising_gate.c b/src/overlays/l05/mobys/rising_gate.c index 45bf52017d..d81d289419 100644 --- a/src/overlays/l05/mobys/rising_gate.c +++ b/src/overlays/l05/mobys/rising_gate.c @@ -38,24 +38,27 @@ void rising_gate_update(struct Moby *gate_moby) { GATE_WAIT_FOR_TRIGGER = 1, GATE_RAISE_AND_SWING = 2 }; + enum { + GATE_YAW_ALIGNED = 3 + }; struct GateVars *gate_vars = (struct GateVars *)gate_moby->pvars; struct Moby *trigger_moby; switch (gate_moby->state) { case GATE_INITIALIZE: gate_vars->topZ = gate_moby->pos.z + 1.0f; - gate_moby->state = 1; + gate_moby->state = GATE_WAIT_FOR_TRIGGER; gate_moby->pos.z -= 8.0f; break; case GATE_WAIT_FOR_TRIGGER: trigger_moby = (struct Moby *)((gate_vars->trigger << 8) + gate_mobys_314eb0); if (trigger_moby->command == 1) { - gate_moby->state = 2; + gate_moby->state = GATE_RAISE_AND_SWING; break; } if (trigger_moby->command == 2) { gate_moby->pos.z = gate_vars->topZ; - gate_moby->state = 3; + gate_moby->state = GATE_YAW_ALIGNED; gate_moby->rot.y = 0.0f; } break; @@ -80,7 +83,7 @@ void rising_gate_update(struct Moby *gate_moby) { gate_swing_deceleration_gp * 0.017453292f * frame_time_sq, gate_swing_max_speed_gp * 0.017453292f * frame_time); if (gate_moby->rot.y == 0.0f) - gate_moby->state = 3; + gate_moby->state = GATE_YAW_ALIGNED; } else if (gate_vars->swingTimer == 1 && gate_moby->oclass == 0x354) { allocate_voice_for_target_entry(0, 0, gate_moby); } From 08261b2618c34cdfcbb340277c83576d0ac027cd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:36:34 +0000 Subject: [PATCH 0665/1502] decomp: clarify names in update_grindrail_gate domain_0_value_1 -> GRINDRAIL_GATE_CHECK_HERO_BOUNDS: Authoritative source SHA-256 493a7820679f3d2a34431b6d0454eb1a3ae5ccb2a9698a25d4584eaac6e5495c defines GRINDRAIL_GATE_CHECK_HERO_BOUNDS=1 in switch(gate_moby->state). Retail 0x002e501c sets s4=1 and 0x002e50fc stores it to the same +0x20 state byte read at 0x002e50c0; the value-1 branch at 0x002e50c4 targets 0x002e5108, which checks distance and transformed hero bounds. Thus initialization enters the existing bounds-check state. domain_1_value_2 -> GRINDRAIL_GATE_WAIT_FOR_COMMAND_TIMEOUT: The existing local enum defines GRINDRAIL_GATE_WAIT_FOR_COMMAND_TIMEOUT=2 for gate_moby->state. After all six local hero bounds pass, retail 0x002e51e8 loads 2, 0x002e51f0 stores it to +0x20, and 0x002e51fc writes the scaled pvars timer. The same state byte is compared with 2 at 0x002e50e8 to enter 0x002e5218, which decrements that timer and clears command on expiry. This proves reuse of the established gate timeout state. domain_2_value_1 -> GRINDRAIL_GATE_CHECK_HERO_BOUNDS: Retail 0x002e5218 calls fast_dec_timer on the pvars timer; after a nonzero result, 0x002e5228 stores s4=1 into gate_moby->state at +0x20 and 0x002e522c clears command at +0xbc. That same byte is read at 0x002e50c0 and value 1 dispatches at 0x002e50c4 to the hero-distance/local-bounds checks at 0x002e5108-0x002e51e4, matching the existing GRINDRAIL_GATE_CHECK_HERO_BOUNDS enum member. --- src/overlays/l16/mobys/grindrail_gate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l16/mobys/grindrail_gate.c b/src/overlays/l16/mobys/grindrail_gate.c index 8b25851f74..e74af932f2 100644 --- a/src/overlays/l16/mobys/grindrail_gate.c +++ b/src/overlays/l16/mobys/grindrail_gate.c @@ -41,7 +41,7 @@ void grindrail_gate_update(struct Moby *gate_moby) { D_L16_00161DE0); switch (gate_moby->state) { case GRINDRAIL_GATE_INITIALIZE: - gate_moby->state = 1; + gate_moby->state = GRINDRAIL_GATE_CHECK_HERO_BOUNDS; gate_moby->update_dist = 0xFF; break; case GRINDRAIL_GATE_CHECK_HERO_BOUNDS: @@ -57,7 +57,7 @@ void grindrail_gate_update(struct Moby *gate_moby) { grindrail_gate_local_trigger_bounds[4] < hero_offset_from_gate[2] && hero_offset_from_gate[2] < grindrail_gate_local_trigger_bounds[5]) { gate_moby->command = 1; - gate_moby->state = 2; + gate_moby->state = GRINDRAIL_GATE_WAIT_FOR_COMMAND_TIMEOUT; *(int *)command_timer = scale_game_frames(D_L16_00161DD8); func_0022ED80_6478(1, 0, gate_moby); } @@ -65,7 +65,7 @@ void grindrail_gate_update(struct Moby *gate_moby) { break; case GRINDRAIL_GATE_WAIT_FOR_COMMAND_TIMEOUT: if (fast_dec_timer((int *)command_timer)) { - gate_moby->state = 1; + gate_moby->state = GRINDRAIL_GATE_CHECK_HERO_BOUNDS; gate_moby->command = 0; } break; From f8c31287b3c383f2b258b372643cf84a606a95fc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:36:34 +0000 Subject: [PATCH 0666/1502] decomp: clarify names in update_local_bounds_command_trigger domain_0_value_1 -> GRINDRAIL_TRIGGER_CHECK_LOCAL_BOUNDS: Retail 0x002e5308 loads state from +0x20(s1); 0x002e530c dispatches state 1 to 0x002e5350 for distance and local xyz bounds checks. Initialization writes 1 to that identical state byte at 0x002e5344. Thus this assignment enters the existing GRINDRAIL_TRIGGER_CHECK_LOCAL_BOUNDS case, in the exact same local enum domain. domain_1_value_2 -> GRINDRAIL_TRIGGER_WAIT_FOR_COMMAND_TIMEOUT: After successful local bounds tests, retail 0x002e5448 asserts command at +0xbc(s1), 0x002e5444/0x002e544c writes 2 to state +0x20(s1), and 0x002e5450-0x002e545c loads the pvars timer. State 2 dispatches at 0x002e5330 to the timer test at 0x002e5460. This is the existing GRINDRAIL_TRIGGER_WAIT_FOR_COMMAND_TIMEOUT case of the same state switch. domain_2_value_1 -> GRINDRAIL_TRIGGER_CHECK_LOCAL_BOUNDS: In the state-2 path, retail 0x002e5460 calls the countdown helper on pvars and 0x002e5468 exits while incomplete. Completion writes 1 to state +0x20(s1) at 0x002e5470 and clears command at 0x002e5474. The same state byte is read at 0x002e5308 and value 1 dispatches to local bounds checking at 0x002e5350, proving reuse of GRINDRAIL_TRIGGER_CHECK_LOCAL_BOUNDS. --- src/overlays/l16/mobys/local_bounds_command_trigger.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l16/mobys/local_bounds_command_trigger.c b/src/overlays/l16/mobys/local_bounds_command_trigger.c index 8266ce3181..bafba1c051 100644 --- a/src/overlays/l16/mobys/local_bounds_command_trigger.c +++ b/src/overlays/l16/mobys/local_bounds_command_trigger.c @@ -43,7 +43,7 @@ void local_bounds_command_trigger_update(struct Moby *trigger_moby) { D_L16_00161DEC); switch (trigger_moby->state) { case GRINDRAIL_TRIGGER_INITIALIZE: - trigger_moby->state = 1; + trigger_moby->state = GRINDRAIL_TRIGGER_CHECK_LOCAL_BOUNDS; trigger_moby->update_dist = 0xFF; break; case GRINDRAIL_TRIGGER_CHECK_LOCAL_BOUNDS: @@ -63,14 +63,14 @@ void local_bounds_command_trigger_update(struct Moby *trigger_moby) { bounds_check_offset_from_trigger[2] < D_L16_001D9768[5]) { allocate_voice_for_target_entry(1, 0, trigger_moby); trigger_moby->command = 1; - trigger_moby->state = 2; + trigger_moby->state = GRINDRAIL_TRIGGER_WAIT_FOR_COMMAND_TIMEOUT; *(int *)command_timer = scale_game_frames(D_L16_00161DE4); } } break; case GRINDRAIL_TRIGGER_WAIT_FOR_COMMAND_TIMEOUT: if (fast_dec_timer((int *)command_timer)) { - trigger_moby->state = 1; + trigger_moby->state = GRINDRAIL_TRIGGER_CHECK_LOCAL_BOUNDS; trigger_moby->command = 0; } break; From c32e8f5e949e2b6b74d4ed565aaa7f69e61b5e95 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:36:35 +0000 Subject: [PATCH 0667/1502] decomp: clarify names in update_reflection_mesh domain_0_value_1 -> SINGLE_MESH_RENDER_QUEUE_CALLBACK: The authoritative update_reflection_mesh source switches on moby->state and already declares SINGLE_MESH_RENDER_QUEUE_CALLBACK = 1 for the branch calling add_draw_callback(draw_level16_visible_single_reflection_mesh, moby). Retail 0x002e93e4 loads state from +0x20(s5); 0x002e93ec-0x002e93f0 compares it with 1 and branches to 0x002e95b4, where 0x002e95b4-0x002e95c0 passes renderer 0x002e9270 and the same s5 moby to the callback helper. After sphere initialization, 0x002e95a0 loads 1 and 0x002e95a8 stores it to that exact +0x20(s5) state field. Thus this assignment selects the already named callback-queue case, rather than any unrelated hero or vehicle domain. --- src/overlays/l16/mobys/reflection_mesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/reflection_mesh.c b/src/overlays/l16/mobys/reflection_mesh.c index 312e4baf1a..59e49ca386 100644 --- a/src/overlays/l16/mobys/reflection_mesh.c +++ b/src/overlays/l16/mobys/reflection_mesh.c @@ -169,7 +169,7 @@ void reflection_mesh_update(struct Moby *moby) { single_mesh_bounding_sphere_components[3] = vertex_to_center_distance; } } - moby->state = 1; + moby->state = SINGLE_MESH_RENDER_QUEUE_CALLBACK; moby->update_dist = moby->draw_dist = 255; break; } From 00dd7cd2034eb164ddcfd6766f977d58e7417622 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:36:35 +0000 Subject: [PATCH 0668/1502] decomp: clarify names in update_reflection_mesh_trio domain_0_value_1 -> MESH_RENDER_QUEUE_CALLBACK: The supplied source switch reads moby->state and already labels its callback branch MESH_RENDER_QUEUE_CALLBACK = 1. Retail 0x002e8eb4 reads byte +0x20 from s6 (the incoming Moby), and 0x002e8ebc-0x002e8ec0 compares that byte with 1 to enter 0x002e9084. That branch passes callback 0x002e8d40 and the same Moby to add_draw_callback at 0x002e9088-0x002e9090. After initializing all three bounding spheres, 0x002e9078-0x002e9080 stores 1 to that exact same +0x20 state byte. Original retail Ghidra shows the same store and subsequent state-1 callback branch. Thus this assignment transitions into the already named function-local callback state, proving reuse of MESH_RENDER_QUEUE_CALLBACK rather than an equal-valued hero or boolean constant. --- src/overlays/l16/mobys/reflection_mesh_trio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/reflection_mesh_trio.c b/src/overlays/l16/mobys/reflection_mesh_trio.c index 4dbb82aae7..c2466f60f4 100644 --- a/src/overlays/l16/mobys/reflection_mesh_trio.c +++ b/src/overlays/l16/mobys/reflection_mesh_trio.c @@ -253,7 +253,7 @@ void reflection_mesh_trio_update(struct Moby *moby) { mesh_bounding_sphere_components[3] = vertex_to_center_distance; } } - moby->state = 1; + moby->state = MESH_RENDER_QUEUE_CALLBACK; break; } case MESH_RENDER_QUEUE_CALLBACK: From d340e5c92e027a7db351299bc5e4544eae5929ba Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:36:35 +0000 Subject: [PATCH 0669/1502] decomp: clarify names in door_half_update domain_0_value_1 -> DOOR_HALF_STATE_FOLLOW_DRIVER: Retail 0x002f4754 loads v1=1 and 0x002f4770 stores that byte into s1+0x20 after saving spawn x/y and initializing sound and prior progress. This is precisely the state byte loaded at 0x002f472c and compared with 1 at 0x002f4738-0x002f473c to enter 0x002f4774. The authoritative source switches on the same door_half_moby->state and already names that branch DOOR_HALF_STATE_FOLLOW_DRIVER=1. Its body validates the driver and interpolates door-half x/y from driver progress at 0x002f47d4-0x002f4808, proving reuse of that state member for this assignment rather than unrelated TRUE. --- src/overlays/l01/mobys/door_half.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/door_half.c b/src/overlays/l01/mobys/door_half.c index f785b179d6..d03a74b70f 100644 --- a/src/overlays/l01/mobys/door_half.c +++ b/src/overlays/l01/mobys/door_half.c @@ -66,7 +66,7 @@ void door_half_update(struct Moby *door_half_moby) { door_half_vars->start_y = door_half_moby->pos.y; door_half_vars->sound = -1; door_half_vars->last_progress = 0.0f; - door_half_moby->state = 1; + door_half_moby->state = DOOR_HALF_STATE_FOLLOW_DRIVER; break; case DOOR_HALF_STATE_FOLLOW_DRIVER: if (door_half_vars->target == -1 || door_half_vars->end_x == 0.0f || From 3b10070a63af4e9f5e257b2a23420f3fd170510b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:36:35 +0000 Subject: [PATCH 0670/1502] decomp: clarify names in piston_platform_update domain_0_value_0 -> PISTON_PLATFORM_STATE_UNINITIALIZED: Retail 0x002f95f4-0x002f95f8 tests instance byte +0x20 for zero; only that branch initializes pvars fields, saves home Z at 0x002f9624, installs home mode and a dwell timer, then stores 1 to the same state byte at 0x002f9640. Original Ghidra and bound C agree that zero selects platform initialization, independently of mode +0xBC. domain_1_value_1 -> PISTON_PLATFORM_STATE_INITIALIZED: Retail li v0,1 at 0x002f9638 and sb v0,0x20(s2) at 0x002f9640 mark completion of the setup gated by the zero state test at 0x002f95f4-0x002f95f8. The block saves home Z and configures mode/timer first; subsequent nonzero state bypasses setup. This is the initialization marker, not a movement-mode value. domain_2_value_2 -> PISTON_PLATFORM_MODE_MOVING: Retail 0x002f9698-0x002f96a4 writes 2 to instance+0xBC after the mode-0 dwell timer expires, then sets speed and duration. The same byte is the bound C switch selector with existing PISTON_PLATFORM_MODE_MOVING=2; its retail branch at 0x002f9768-0x002f9774 subtracts speed from Z each update. Reuse that exact domain member. domain_3_value_2 -> PISTON_PLATFORM_MODE_MOVING: Retail 0x002f96fc-0x002f9708 writes 2 to instance+0xBC after the mode-1 timer gate; 0x002f9728-0x002f974c sets negated travel/duration speed and duration. This is the same +0xBC switch selector whose existing PISTON_PLATFORM_MODE_MOVING=2 branch updates Z at 0x002f9768-0x002f9774, so reuse its canonical local constant. domain_4_value_0 -> PISTON_PLATFORM_MODE_WAIT_BEFORE_SUBTRACT_TRAVEL: After movement timer expiry, retail 0x002f9784-0x002f97a0 tests speed<0 and stores zero to instance+0xBC on that branch, then reloads the dwell timer at 0x002f97bc-0x002f97c4. The same +0xBC selector's existing mode-0 case waits before setting positive travel/duration speed at 0x002f968c-0x002f96e4, which the moving branch subtracts from Z. Reuse PISTON_PLATFORM_MODE_WAIT_BEFORE_SUBTRACT_TRAVEL. domain_5_value_1 -> PISTON_PLATFORM_MODE_WAIT_BEFORE_ADD_TRAVEL: Retail 0x002f9790-0x002f979c stores 1 to instance+0xBC when movement expires with speed not less than zero, and reloads the dwell timer. This is the same selector as existing mode-1 PISTON_PLATFORM_MODE_WAIT_BEFORE_ADD_TRAVEL: 0x002f96f0-0x002f974c waits then negates travel/duration speed; subtracting that speed in the moving branch adds configured travel. No physical direction is assumed. --- src/overlays/l01/mobys/piston_platform.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/overlays/l01/mobys/piston_platform.c b/src/overlays/l01/mobys/piston_platform.c index 79a7ade162..f02092ed3d 100644 --- a/src/overlays/l01/mobys/piston_platform.c +++ b/src/overlays/l01/mobys/piston_platform.c @@ -56,6 +56,10 @@ void piston_platform_update(LiftMoby *piston_platform) { PISTON_PLATFORM_MODE_WAIT_BEFORE_ADD_TRAVEL = 1, PISTON_PLATFORM_MODE_MOVING = 2 }; + enum { + PISTON_PLATFORM_STATE_UNINITIALIZED = 0, + PISTON_PLATFORM_STATE_INITIALIZED = 1 + }; LiftVars *piston_platform_vars; u128 previous_position; u128 delta; @@ -64,7 +68,7 @@ void piston_platform_update(LiftMoby *piston_platform) { piston_platform_vars = piston_platform->pvars; qcopy(&previous_position, &piston_platform->pos); fast_dec_timer_s16(&piston_platform_vars->timer); - if (piston_platform->state == 0) { + if (piston_platform->state == PISTON_PLATFORM_STATE_UNINITIALIZED) { piston_platform_vars->x28 = 4; piston_platform_vars->x3e = 0xD; piston_platform_vars->x20 = 0; @@ -72,7 +76,7 @@ void piston_platform_update(LiftMoby *piston_platform) { piston_platform_vars->home_z = ((f32 *)&piston_platform->pos)[2]; piston_platform->mode = piston_platform_vars->home_mode; piston_platform_vars->timer = scale_game_frames(0x78); - piston_platform->state = 1; + piston_platform->state = PISTON_PLATFORM_STATE_INITIALIZED; piston_platform->b30 = 0xFF; piston_platform->h32 = 0xFF; piston_platform_vars->xb4 = -1; @@ -80,7 +84,7 @@ void piston_platform_update(LiftMoby *piston_platform) { switch (piston_platform->mode) { case PISTON_PLATFORM_MODE_WAIT_BEFORE_SUBTRACT_TRAVEL: if (piston_platform_vars->timer == 0) { - piston_platform->mode = 2; + piston_platform->mode = PISTON_PLATFORM_MODE_MOVING; piston_platform_vars->speed = piston_platform_vars->travel / convert_integer_to_float( @@ -92,7 +96,7 @@ void piston_platform_update(LiftMoby *piston_platform) { break; case PISTON_PLATFORM_MODE_WAIT_BEFORE_ADD_TRAVEL: if (piston_platform_vars->timer == 0) { - piston_platform->mode = 2; + piston_platform->mode = PISTON_PLATFORM_MODE_MOVING; piston_platform_vars->speed = -(piston_platform_vars->travel / convert_integer_to_float(scale_game_frames( @@ -106,9 +110,9 @@ void piston_platform_update(LiftMoby *piston_platform) { ((f32 *)&piston_platform->pos)[2] -= piston_platform_vars->speed; if (piston_platform_vars->timer == 0) { if (piston_platform_vars->speed < 0.0f) { - piston_platform->mode = 0; + piston_platform->mode = PISTON_PLATFORM_MODE_WAIT_BEFORE_SUBTRACT_TRAVEL; } else { - piston_platform->mode = 1; + piston_platform->mode = PISTON_PLATFORM_MODE_WAIT_BEFORE_ADD_TRAVEL; } if (piston_platform->mode == piston_platform_vars->home_mode) { ((f32 *)&piston_platform->pos)[2] = piston_platform_vars->home_z; From aa7304e9ca7a158a008efcd1446e30cd373921d8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:38:20 +0000 Subject: [PATCH 0671/1502] decomp: clarify names in grindrail_button_update domain_0_value_1 -> GRINDRAIL_BUTTON_CHECK_ACTIVATION: Source assigns button_moby->state = 1 in GRINDRAIL_BUTTON_INITIALIZE_GLOW_PHASE and already labels the same selector's value-1 branch GRINDRAIL_BUTTON_CHECK_ACTIVATION. Retail 0x002e54ac retains the Moby in s0; 0x002e54c0 reads its state byte +0x20, 0x002e54cc-0x002e54d0 compares it with 1 and dispatches to 0x002e54f4. At 0x002e54e0/0x002e54e8 initialization writes 1 to that identical +0x20 byte. The target branch checks countdown-gated hero alignment and find_moby_hit, calling activation helper 0x002e56e0 at 0x002e55f8 or 0x002e5628. Original retail decompilation confirms this write and value-1 dispatch. Thus this assignment reuses the existing local grindrail-button state constant, without equating it with any hero enum. --- src/overlays/l16/mobys/grindrail_button.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/grindrail_button.c b/src/overlays/l16/mobys/grindrail_button.c index 92c332b325..205bc88eeb 100644 --- a/src/overlays/l16/mobys/grindrail_button.c +++ b/src/overlays/l16/mobys/grindrail_button.c @@ -60,7 +60,7 @@ void grindrail_button_update(struct Moby *button_moby) { float glow_blend_factor; switch (button_moby->state) { case GRINDRAIL_BUTTON_INITIALIZE_GLOW_PHASE: - button_moby->state = 1; + button_moby->state = GRINDRAIL_BUTTON_CHECK_ACTIVATION; *(float *)button_data = random_angle_radians(); break; case GRINDRAIL_BUTTON_CHECK_ACTIVATION: From 91461e9a71f64b4f64d98c2a9e8b17e5f0ca3bd3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:38:21 +0000 Subject: [PATCH 0672/1502] decomp: clarify names in forcefield_update domain_0_value_1 -> FORCEFIELD_STATE_MONITOR_LINKED_MOBY: Retail 0x002ed4c4 reads state from 0x20(s0); initialization stores 1 to that same byte at 0x002ed508. The next dispatch compares that byte to 1 at 0x002ed4c8 and enters 0x002ed548, resolving the stored linked-moby index and checking its state/save bit. This is precisely the existing local FORCEFIELD_STATE_MONITOR_LINKED_MOBY case of switch(moby->state). domain_1_value_2 -> FORCEFIELD_STATE_FADE_OUT: The linked-moby invalid/state/save-bit path at 0x002ed5bc-0x002ed5d0 resets the fade scalar at 4(s1) to 1.0 and stores 2 at 0x20(s0), the state byte read at 0x002ed4c4. Dispatch of 2 at 0x002ed4ec reaches 0x002ed610, which subtracts frame_scale*0.05 and updates alpha. It therefore reuses this selector's existing FORCEFIELD_STATE_FADE_OUT member. domain_2_value_2 -> FORCEFIELD_STATE_FADE_OUT: The missing linked-index branch from 0x002ed550 reaches 0x002ed5d4-0x002ed5ec, resets 4(s1) to 1.0 and stores 2 into the same 0x20(s0) state byte dispatched at 0x002ed4c4/0x002ed4ec. State 2 executes the scalar decrease and alpha update at 0x002ed610-0x002ed664, proving reuse of the existing FORCEFIELD_STATE_FADE_OUT case constant. domain_3_value_3 -> FORCEFIELD_STATE_REMOVE: After the state-2 fade scalar becomes negative, retail 0x002ed644-0x002ed64c stores 3 to 0x20(s0), exactly the moby->state selector read at 0x002ed4c4. The state-3 dispatch at 0x002ed4f4 reaches 0x002ed668, releases the stored slot if present and calls the moby removal helper at 0x002ed680. This matches the existing local FORCEFIELD_STATE_REMOVE member. --- src/overlays/l13/mobys/forcefield.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l13/mobys/forcefield.c b/src/overlays/l13/mobys/forcefield.c index 77e21ce7b6..ab240c60d3 100644 --- a/src/overlays/l13/mobys/forcefield.c +++ b/src/overlays/l13/mobys/forcefield.c @@ -115,7 +115,7 @@ void forcefield_update(struct Moby *moby) { int wrap_adjusted_step; switch (moby->state) { case FORCEFIELD_STATE_INITIALIZE: - moby->state = 1; + moby->state = FORCEFIELD_STATE_MONITOR_LINKED_MOBY; moby->alpha = 0x14; moby->flags |= 0xA08; forcefield_data->unkE = -1; @@ -131,11 +131,11 @@ void forcefield_update(struct Moby *moby) { (MOBY(linked_moby)->save_id & 0x1F)) & 1) { forcefield_data->unk4 = 1.0f; - moby->state = 2; + moby->state = FORCEFIELD_STATE_FADE_OUT; } } else { forcefield_data->unk4 = 1.0f; - moby->state = 2; + moby->state = FORCEFIELD_STATE_FADE_OUT; stub_printf(forcefield_missing_trigger_format, moby->oclass, ((short)moby->save_id)); } spawn_forcefield_contact_effects(moby, forcefield_data); @@ -143,7 +143,7 @@ void forcefield_update(struct Moby *moby) { case FORCEFIELD_STATE_FADE_OUT: forcefield_data->unk4 -= frame_scale * 0.05f; if (forcefield_data->unk4 < 0.0f) - moby->state = 3; + moby->state = FORCEFIELD_STATE_REMOVE; else moby->alpha = truncate_float_to_s32(forcefield_data->unk4 * 20.0f); break; From aae99477e9498dddba7179d85bc7144922a09fbe Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:38:21 +0000 Subject: [PATCH 0673/1502] decomp: clarify names in memcard_restore_data domain_0_value_1 -> RESTORE_STATUS_SIZE_MATCH: Retail 0x0020b010 loads matched entry size from +4 into v1 and 0x0020b014 loads serialized block size from +4 into a2. At 0x0020b01c their inequality branches away; the equality path loads 1 at 0x0020b024 and stores it into the matched entry status (+0xc) at 0x0020b030. The authoritative C routes this through local status into matched_entry->status, and original Ghidra writes piVar3[3] = 1 on iVar4 == iVar1. The unequal-size paths store -1 or -2 (0x0020b034-0x0020b050). Thus 1 means size match, independent of payload equality checked later at 0x0020b060. Existing TRUE=1 has no proven domain equivalence to this multi-valued restore status. --- src/save/memcard_restore_data.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/save/memcard_restore_data.c b/src/save/memcard_restore_data.c index cd3d67f746..a5af8adbb9 100644 --- a/src/save/memcard_restore_data.c +++ b/src/save/memcard_restore_data.c @@ -42,6 +42,9 @@ extern void copy_memory_aligned(void *, void *, s32) __asm__("func_001F9838"); s32 memcard_restore_data(u8 *buf, s32 slot, struct RestoreEntry *tbl) __asm__("FUN_0020af20"); s32 memcard_restore_data(u8 *save_packet, s32 slot, struct RestoreEntry *restore_entries) { + enum { + RESTORE_STATUS_SIZE_MATCH = 1 + }; struct RestoreEntry *matched_entry; s32 errors; s32 total; @@ -75,7 +78,7 @@ s32 memcard_restore_data(u8 *save_packet, s32 slot, struct RestoreEntry *restore s32 entrySize = matched_entry->size; slot_destination = matched_entry->data + slot * entrySize; if (blockSize == entrySize) { - s32 status = 1; + s32 status = RESTORE_STATUS_SIZE_MATCH; copySize = entrySize; matched_entry->status = status; } else if (blockSize < entrySize) { From afddffdd94e1f9649d1bb2f676023974b28424ca Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:40:05 +0000 Subject: [PATCH 0674/1502] decomp: clarify names in initialize_camera_transform_and_paths domain_0_value_3 -> CAMERA_PRESET_KIND_GRINDRAIL_PATH: The authoritative grindrail_camera.c snapshot explicitly describes camera type 3 as following a path beside the grind rail ridden by the hero and looking toward a point on it. Retail 0x00315e20-0x00315e30 selects CameraPreset through camera+0x84 and row+0x1c; 0x00315ee8-0x00315ef0 compares that preset's +0x30 kind field to 3. Its branch obtains the preset track_path at +0x20, finds a nearest segment at 0x00315f50, normalizes its direction and tests camera position against it at 0x00315f90-0x00315ff4. The source's update_camera_position_and_orientation_from_paths documents this path-following camera, while update_camera_mode_from_preset separately tests the same kind to select control mode 5. This proves a camera-preset kind domain, independent of HeroStateId; equal-valued HERO_STATE_STOP does not apply. --- src/overlays/shared/camera/grindrail_camera.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/camera/grindrail_camera.c b/src/overlays/shared/camera/grindrail_camera.c index 461d71693d..4edea65f37 100644 --- a/src/overlays/shared/camera/grindrail_camera.c +++ b/src/overlays/shared/camera/grindrail_camera.c @@ -541,6 +541,9 @@ extern OvlVec4 D_0013F3D0_315de0 __asm__("D_0013F3D0"); void initialize_camera_transform_and_paths(Camera *destination_camera) __asm__("FUN_L01_00315de0"); void initialize_camera_transform_and_paths(Camera *destination_camera) { + enum { + CAMERA_PRESET_KIND_GRINDRAIL_PATH = 3 + }; CameraPresetRow *rows = l01_camera_preset_rows; Camera *source_camera = D_L01_00167284; CameraPreset *camera_preset = rows[destination_camera->preset].preset; @@ -566,7 +569,7 @@ void initialize_camera_transform_and_paths(Camera *destination_camera) { } camera_preset->unk36 = 0; - if (camera_preset->kind == 3) { + if (camera_preset->kind == CAMERA_PRESET_KIND_GRINDRAIL_PATH) { CameraPath *path; s32 next; path = ((CameraPath *)l01_paths[camera_preset->track_path]); From 52190624da6179528b1866f75f2f963468c2189c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:40:05 +0000 Subject: [PATCH 0675/1502] decomp: clarify names in nanotech_upgrade_vendor_update domain_0_value_0 -> NANOTECH_VENDOR_STATE_READY: Retail 0x002e8380 loads the vendor Moby state byte at s1+0x20; 0x002e8384 branches on zero to 0x002e839c. That branch checks facing, distance, cooldown and purchase flags before offering the two upgrades, establishing the vendor ready state. domain_1_value_1 -> NANOTECH_VENDOR_STATE_FINALIZE_PURCHASE: Retail 0x002e838c compares the same vendor state byte with 1 and branches to 0x002e854c. After the mode gate this path calls memcard_save_data at 0x002e8560, queues purchase dialogue at 0x002e857c, resets the timer and returns to ready at 0x002e8598: purchase finalization. domain_2_value_1 -> NANOTECH_VENDOR_STATE_FINALIZE_PURCHASE: The source first-upgrade branch grants 5 hp and deducts 4000 bolts. Retail 0x002e8488 loads s0=1, 0x002e848c sets its purchase flag, and 0x002e84a4 joins the start_scene call at 0x002e852c; 0x002e8538 stores s0 to the vendor state at s1+0x20, selecting the save/dialogue finalization path. domain_3_value_1 -> NANOTECH_VENDOR_STATE_FINALIZE_PURCHASE: The second-upgrade retail path loads s0=1 at 0x002e850c, sets the second purchase flag, grants 8 hp and deducts 30000 bolts at 0x002e8510-0x002e8524. After start_scene(1), 0x002e8538 stores that 1 to vendor state s1+0x20, selecting the same purchase-finalization handler. domain_4_value_0 -> NANOTECH_VENDOR_STATE_READY: After saving at 0x002e8560 and queueing the purchase message at 0x002e857c, retail 0x002e858c-0x002e8594 writes the scaled 240-frame cooldown. 0x002e8598 stores zero to vendor Moby state s1+0x20, returning to the state whose branch at 0x002e8384 checks readiness for purchases. --- src/overlays/l10/mobys/nanotech_upgrade_vendor.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/overlays/l10/mobys/nanotech_upgrade_vendor.c b/src/overlays/l10/mobys/nanotech_upgrade_vendor.c index e8cce8b313..6f21d883a8 100644 --- a/src/overlays/l10/mobys/nanotech_upgrade_vendor.c +++ b/src/overlays/l10/mobys/nanotech_upgrade_vendor.c @@ -32,6 +32,10 @@ void nanotech_upgrade_vendor_update(struct Moby *moby) __asm__("FUN_L10_002e8358 /* Moby class 1326 */ void nanotech_upgrade_vendor_update(struct Moby *moby) { + enum { + NANOTECH_VENDOR_STATE_READY = 0, + NANOTECH_VENDOR_STATE_FINALIZE_PURCHASE = 1 + }; int *timer; float angle; int purchase; @@ -39,8 +43,8 @@ void nanotech_upgrade_vendor_update(struct Moby *moby) { timer = (int *)moby->pvars; fast_dec_timer(timer + 1); - if (moby->state != 0) { - if (moby->state == 1) + if (moby->state != NANOTECH_VENDOR_STATE_READY) { + if (moby->state == NANOTECH_VENDOR_STATE_FINALIZE_PURCHASE) goto state_one; return; } @@ -64,7 +68,7 @@ void nanotech_upgrade_vendor_update(struct Moby *moby) { current_bolt_count = D_0013ED98 - 4000; purchased_nanotech_health_gp = upgrade_level; start_scene(0); - moby->state = 1; + moby->state = NANOTECH_VENDOR_STATE_FINALIZE_PURCHASE; } else { try_set_help_message(1, 0x2720); return; @@ -84,7 +88,7 @@ void nanotech_upgrade_vendor_update(struct Moby *moby) { current_bolt_count = D_0013ED98 - 30000; purchased_nanotech_health_gp = upgrade_level; start_scene(1); - moby->state = 1; + moby->state = NANOTECH_VENDOR_STATE_FINALIZE_PURCHASE; } else { try_set_help_message(1, 0x2721); return; @@ -110,6 +114,6 @@ void nanotech_upgrade_vendor_update(struct Moby *moby) { queue_dialogue_message(purchase, -1); D_L10_0013F640 = 0xb4; timer[1] = scale_game_frames(0xf0); - moby->state = 0; + moby->state = NANOTECH_VENDOR_STATE_READY; } } From c579d31835d5507f31324275c468e70f37fbad10 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:40:05 +0000 Subject: [PATCH 0676/1502] decomp: clarify names in apply_hero_ground_material_response domain_0_value_2 -> HERO_GROUND_MATERIAL_MAGNETIC: Authoritative C saves hero.ground_type into previous_ground_type before clearing it; supplied update_hero_ground_contact fills this field from collision_hit_material(), proving the material selector domain rather than HeroStateId. Retail 0x00222FE8 loads that signed material into s3; 0x00223008-0x0022300C compare it with 2. After the grounded/0.3-distance test, 0x0022304C writes 1 to hero+0x12E7, the established on_magnet_ground field. Original Ghidra shows the same sVar1==2 flow. Thus this value selects magnetic ground response. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The selector is hero_state->vehicle_mode, not previous_ground_type or state.current. Retail 0x00223044 loads hero+0x20A4 and 0x00223048 compares it with zero before inspecting items[1].moby. Original Ghidra cRam001413f4=='\0' confirms that field. The supplied HeroVehicleMode domain defines HERO_VEHICLE_MODE_ON_FOOT=0, and supplied hero_set_state uses that exact member for p->vehicle_mode; same-source process_hero_hit_response and update_hero_smoothed_parameters also switch that same hero.vehicle_mode using the canonical member. domain_2_value_13 -> HERO_GROUND_MATERIAL_SINK_SURFACE: Retail 0x00223074-0x00223088 compares the saved collision material s3 with 0xD and sets hero+0x12EC (selector_13). The same flag gates the final branch at 0x00223168. Retail 0x00223180-0x002231E4 tests proximity below water_surface_z and descending displacement, then 0x002231F4-0x002231FC requests 0x7F, established HERO_STATE_SINK. Original Ghidra cRam0014063c and LAB_00223168 confirm this dependency. Supplied ground-contact source sets water_surface_z for ground_type==0xD. The name describes a material surface enabling sink entry, without claiming its substance. domain_7_value_1 -> HERO_VEHICLE_MODE_CLANK: vehicle_response_check_hero is &hero; retail 0x002230F0 reads its +0x20A4 vehicle_mode byte, and 0x002230F4 compares against a0=1 from 0x0022307C, before checking state.current at +0x2084 and requesting state 0x7D. Original Ghidra separately tests cRam001413f4=='\x01'. This is the same hero.vehicle_mode selector used by the supplied same-source hit-response and smoothing switches, whose value-1 branches already use HERO_VEHICLE_MODE_CLANK. The supplied shared HeroVehicleMode enum canonically defines that member as 1; it is not a hero state ID. --- .../l06/hero/update_hero_motion_for_current_state.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/overlays/l06/hero/update_hero_motion_for_current_state.c b/src/overlays/l06/hero/update_hero_motion_for_current_state.c index cdbfdd398c..f662e0c44d 100644 --- a/src/overlays/l06/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l06/hero/update_hero_motion_for_current_state.c @@ -34,6 +34,10 @@ float absolute_float(float input) __asm__("func_001F99C0"); void apply_hero_ground_material_response(void) __asm__("FUN_L06_00222fb8"); void apply_hero_ground_material_response(void) { + enum { + HERO_GROUND_MATERIAL_MAGNETIC = 2, + HERO_GROUND_MATERIAL_SINK_SURFACE = 0xD + }; struct Hero *hero_state = &hero; struct Hero *vehicle_response_check_hero; struct Hero *grounded_response_check_hero; @@ -47,17 +51,17 @@ void apply_hero_ground_material_response(void) { hero_state->unk308 = 0; if (previous_ground_type == -1) return; - if (previous_ground_type == 2) { + if (previous_ground_type == HERO_GROUND_MATERIAL_MAGNETIC) { if (hero_state->frames_off_ground.s == 0 || hero_state->ground_distance < 0.3f) { hero_state->on_magnet_ground = 1; - if (hero_state->vehicle_mode == 0) { + if (hero_state->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { char *item_slot_1_moby = ((char *)hero_state->items[1].moby); if (item_slot_1_moby != 0 && MOBY(item_slot_1_moby)->oclass == 0xAD) hero_state->unk308 = 1; } } } - if (previous_ground_type == 0xD) { + if (previous_ground_type == HERO_GROUND_MATERIAL_SINK_SURFACE) { struct Hero *gx = &hero; gx->selector_13 = 1; } @@ -80,7 +84,7 @@ void apply_hero_ground_material_response(void) { vehicle_response_check_hero = &hero; if (vehicle_response_check_hero->selector_1 != 0) { if (vehicle_response_check_hero->grounded_frames != 0 && - vehicle_response_check_hero->vehicle_mode == 1 && + vehicle_response_check_hero->vehicle_mode == HERO_VEHICLE_MODE_CLANK && vehicle_response_check_hero->state.current != 0x7D) { hero_set_state(0x7D, 1); return; From 9eb08a57ebeb7eab1aa562a02db8134697ba3ecb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:41:51 +0000 Subject: [PATCH 0677/1502] decomp: clarify names in update_ribbon_effect_moby domain_0_value_1 -> MOBY_STATE_UPDATE: Authoritative source src/overlays/l14/mobys/ribbon_effect.c (SHA-256 9ac787220894f15622f398ae0406fe83a5841a4b05381d8749a65eee24ec4bf1) already declares MOBY_STATE_UPDATE = 1 and uses it in switch(moby->state). Retail 0x002dee44 loads the state byte at moby+0x20; 0x002dee50-0x002dee54 tests it against 1 and branches to the recurring update at 0x002deec0. After initialize_ribbon_effect_state at 0x002deea8, 0x002deeb0-0x002deeb4 stores 1 to that exact byte. Original Ghidra likewise assigns *(undefined1 *)(param_1 + 0x20) = 1 after initialization and tests the same field for 1 before hero/proximity, sound, clip-volume and animation work. This proves reuse of the existing local MOBY_STATE_UPDATE rather than any equal-valued Hero enum or boolean. --- src/overlays/l14/mobys/ribbon_effect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/ribbon_effect.c b/src/overlays/l14/mobys/ribbon_effect.c index a4e5fe409a..adbc8e3d44 100644 --- a/src/overlays/l14/mobys/ribbon_effect.c +++ b/src/overlays/l14/mobys/ribbon_effect.c @@ -51,7 +51,7 @@ void ribbon_effect_moby_update(struct Moby *moby) { return; } initialize_ribbon_effect_state(moby); - moby->state = 1; + moby->state = MOBY_STATE_UPDATE; *(int *)(ribbon_effect_state + 0x204) = -1; break; case MOBY_STATE_UPDATE: From fe825f4530b8d246011323ad7277db0367620428 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:41:52 +0000 Subject: [PATCH 0678/1502] decomp: clarify names in update_reflection_mesh_pair domain_0_value_1 -> TWO_MESH_RENDER_QUEUE_CALLBACK: The authoritative source (SHA-256 7a198130809bd0ffb420a13925c2f0c45962f63ad50d6e146afe07c9c6f77b77) switches on moby->state and already names case 1 TWO_MESH_RENDER_QUEUE_CALLBACK. Retail 0x002e9914 loads the state byte at +0x20(s5), and 0x002e9920 dispatches value 1 to 0x002e9af0. After computing both bounding spheres, 0x002e9adc loads 1 and 0x002e9ae4 stores it to that identical +0x20(s5) byte. The value-1 branch passes callback address 0x002e97a0 and this moby at 0x002e9af0-0x002e9afc, corresponding to add_draw_callback(draw_level16_visible_textured_batches, moby). Thus the assignment enters the existing local callback-queue state; unrelated Hero enums and TRUE are not this selector's domain. --- src/overlays/l16/mobys/reflection_mesh_pair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/reflection_mesh_pair.c b/src/overlays/l16/mobys/reflection_mesh_pair.c index c6dfb97740..849f4fa649 100644 --- a/src/overlays/l16/mobys/reflection_mesh_pair.c +++ b/src/overlays/l16/mobys/reflection_mesh_pair.c @@ -180,7 +180,7 @@ void reflection_mesh_pair_update(struct Moby *moby) { two_mesh_bounding_sphere_components[3] = vertex_to_center_distance; } } - moby->state = 1; + moby->state = TWO_MESH_RENDER_QUEUE_CALLBACK; moby->update_dist = moby->draw_dist = 255; break; } From ac362211c9e4468b4a6fea237f241aa4d8642099 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:41:52 +0000 Subject: [PATCH 0679/1502] decomp: clarify names in update_reflection_mesh_trio_b domain_0_value_1 -> MESH_RENDER_QUEUE_CALLBACK: Authoritative source switches on moby->state and already names its value-1 case MESH_RENDER_QUEUE_CALLBACK, whose body calls add_draw_callback(env_map_a_draw, moby). Retail 0x002ea324 loads 1 and 0x002ea32c stores it to 0x20(s5) after sphere initialization. The same field is loaded at 0x002ea15c and compared with 1 at 0x002ea164-0x002ea168, branching to 0x002ea338-0x002ea344 to pass callback 0x002e9fe8 and the original moby to the queue helper. Original Ghidra likewise stores 1 to iVar7+0x20 and tests that field for the callback branch. Thus the assignment enters the existing local mesh-render state, not any hero or control-mode domain. --- src/overlays/l16/mobys/reflection_mesh_trio_b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/reflection_mesh_trio_b.c b/src/overlays/l16/mobys/reflection_mesh_trio_b.c index ce027bb48a..d8350bf319 100644 --- a/src/overlays/l16/mobys/reflection_mesh_trio_b.c +++ b/src/overlays/l16/mobys/reflection_mesh_trio_b.c @@ -138,7 +138,7 @@ void reflection_mesh_trio_b_update(struct Moby *moby) { current_mesh_sphere_components[3] = vertex_to_center_distance; } } - moby->state = 1; + moby->state = MESH_RENDER_QUEUE_CALLBACK; moby->update_dist = moby->draw_dist = 255; break; } From 3e48a5893fecfe56cb17b13f03abcdff3a9a5ace Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:41:52 +0000 Subject: [PATCH 0680/1502] decomp: clarify names in trooper_anim_finish domain_0_value_0 -> MOBY_COLOR_PHASE_TO_SECONDARY_COLOR: Retail 0x0025d570 loads phase +2 and 0x0025d574 tests zero after timer expiry. Nonzero restores RGB +4..+6 through set_moby_color at 0x0025d584; zero transitions to one at 0x0025d594..5a0. The same +2 selector is tested at 0x0025d5ac; its zero branch interpolates +4 toward +7, +5 toward +8, and +6 toward +9 (0x0025d5e4..67c). Thus zero is the phase toward secondary RGB, consistent with the authoritative C and original Ghidra psVar9[1] flow. domain_1_value_1 -> MOBY_COLOR_PHASE_TO_ORIGINAL_COLOR: Retail 0x0025d594 loads one and 0x0025d5a0 stores it to phase +2 when the initial timer expires, reloading the timer from scaled d1 at +0xe. The nonzero branch at 0x0025d680..760 interpolates secondary RGB +7..+9 toward original RGB +4..+6; subsequent expiry restores +4..+6 at 0x0025d57c..588. Supplied trooper_anim_update captures the original moby color into these initial RGB bytes. This proves one selects the return toward original color. domain_2_value_0 -> MOBY_COLOR_PHASE_TO_SECONDARY_COLOR: Retail 0x0025d5a8 loads phase +2, and 0x0025d5ac branches to the reverse blend only when nonzero. Zero uses scaled d0 (+0xc) and progress (duration minus timer)/duration at 0x0025d5b4..5e0, then computes r0+(r1-r0)*progress at 0x0025d5e4..610 and corresponding green/blue operations through 0x0025d67c. Original Ghidra and authoritative C agree that this zero comparison selects interpolation toward secondary RGB; it is the same domain/member as the earlier zero comparison. --- .../shared/rendering/effects/spawn_explosion.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/rendering/effects/spawn_explosion.c b/src/overlays/shared/rendering/effects/spawn_explosion.c index 4f47f2bbbe..7677eb0468 100644 --- a/src/overlays/shared/rendering/effects/spawn_explosion.c +++ b/src/overlays/shared/rendering/effects/spawn_explosion.c @@ -96,19 +96,23 @@ void set_moby_color(s32, s32, s32, s32) __asm__("FUN_L00_002502f0"); void trooper_anim_finish(s32 id, S_25d538 *s) __asm__("FUN_L00_0025d538"); void trooper_anim_finish(s32 id, S_25d538 *animation_state) { + enum { + MOBY_COLOR_PHASE_TO_SECONDARY_COLOR = 0, + MOBY_COLOR_PHASE_TO_ORIGINAL_COLOR = 1 + }; f32 phase_duration_frames, phase_progress; s32 r, g, b; if (animation_state->t == 0) return; if (fast_dec_timer_s16(animation_state)) { - if (animation_state->phase != 0) { + if (animation_state->phase != MOBY_COLOR_PHASE_TO_SECONDARY_COLOR) { set_moby_color(id, animation_state->r0, animation_state->g0, animation_state->b0); return; } - animation_state->phase = 1; + animation_state->phase = MOBY_COLOR_PHASE_TO_ORIGINAL_COLOR; animation_state->t = scale_game_frames(animation_state->d1); } - if (animation_state->phase == 0) { + if (animation_state->phase == MOBY_COLOR_PHASE_TO_SECONDARY_COLOR) { phase_duration_frames = convert_integer_to_float(scale_game_frames(animation_state->d0)); phase_progress = (phase_duration_frames - animation_state->t) / phase_duration_frames; if (animation_state->r1 != 0) From 6f4ed939974bca838596106fd7ddf9927e82f2a0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:41:52 +0000 Subject: [PATCH 0681/1502] decomp: clarify names in emit_hero_randomized_motion_effects domain_0_value_0 -> HERO_MOTION_EFFECT_RANDOMIZED_HERO_POSITION: The bound source (src/overlays/shared/hero/hero_idle_sequence.c, SHA-256 55f16d2217680e7d22f10795bd03ea001138aa6ab93a1539088f1a4849372a67) tests mode == 0 to set pos XYZ from hero.motion.pos plus independent random offsets. Retail 00209a54 copies a1 into s3 and 00209ac8 branches on s3 != zero; 00209ad0-00209b1c add random ranges [-0.1,0.1], [-0.1,0.1], [-0.5,0.1] to hero+0x80/0x84/0x88 and store at sp+0/4/8. Original Ghidra param_2 == 0 has the identical position derivation. At 00209c5c-00209c60 sp is passed as the position to FUN_0026f080. The supplied movement caller uses this mode during splash_effect_timer emission. This names the proven position-selection behavior, independently of unrelated hero state/vehicle/gravity enums. --- src/overlays/shared/hero/hero_idle_sequence.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index ac0da0a4ca..5702b6f55b 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -2551,6 +2551,9 @@ extern int random_integer_below_cf(void *, void *, float, float) __asm__("FUN_L0 void emit_hero_randomized_motion_effects(int iteration_count, int mode) __asm__("FUN_L00_00209a40"); void emit_hero_randomized_motion_effects(int iteration_count, int mode) { + enum { + HERO_MOTION_EFFECT_RANDOMIZED_HERO_POSITION = 0 + }; float pos[4]; V_209a40 randomized_displacement; int i; @@ -2560,7 +2563,7 @@ void emit_hero_randomized_motion_effects(int iteration_count, int mode) { for (i = 0; i < iteration_count; i++) { hero_state = &hero; hero_displacement_source = (V_209a40 *)&hero_state->motion.displacement; - if (mode == 0) { + if (mode == HERO_MOTION_EFFECT_RANDOMIZED_HERO_POSITION) { pos[0] = hero_state->motion.pos.f[0] + random_float_between(-0.1f, 0.1f); pos[1] = hero_state->motion.pos.f[1] + random_float_between(-0.1f, 0.1f); pos[2] = hero_state->motion.pos.f[2] + random_float_between(-0.5f, 0.1f); From cb3e1ada1cf96ea96339275b4392be147a61c84b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:43:38 +0000 Subject: [PATCH 0682/1502] decomp: clarify names in allocate_voice_slot domain_0_value_0 -> VOICE_DEFINITION_SOURCE_INACTIVE: Authoritative source src/audio/voices/allocate_voice_slot.c (SHA-256 225ef3b8c32fa6d4a32fdb86619515dc61867dbb1f1b5a6c6c91b853324def26) assigns definition->source_state == 0 to the established source_inactive binding. Retail 0x0022d81c loads the definition byte at +0x18; 0x0022d824 sltiu converts zero to true. At 0x0022d814-0x0022d840 flags bit 4 selects eligibility: clear accepts the zero/inactive category, set rejects it. Original Ghidra decompilation independently shows this same zero test and paired rejection branches. Thus the literal names the inactive VoiceDefinition source category, distinct from the separately scanned voice-slot state at 0x0022d890. --- src/audio/voices/allocate_voice_slot.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/voices/allocate_voice_slot.c b/src/audio/voices/allocate_voice_slot.c index 44fcf095d7..8e35bc7a49 100644 --- a/src/audio/voices/allocate_voice_slot.c +++ b/src/audio/voices/allocate_voice_slot.c @@ -28,6 +28,9 @@ s32 allocate_voice_slot(VoiceDefinition *, u32, VoiceMoby *, VoiceVector *, s32) s32 allocate_voice_slot( VoiceDefinition *definition, u32 flags, VoiceMoby *moby, VoiceVector *position, s32 volume) { + enum { + VOICE_DEFINITION_SOURCE_INACTIVE = 0 + }; s32 volume_offset; s32 pitch_bend_max; s32 pitch_bend_min; @@ -41,7 +44,7 @@ s32 allocate_voice_slot( VoicePoolWindow *pitch_slot; VoicePoolWindow *position_slot; - source_inactive = definition->source_state == 0; + source_inactive = definition->source_state == VOICE_DEFINITION_SOURCE_INACTIVE; if ((flags & 4) == 0) { if ((source_inactive ^ 1) != 0) { volume_or_slot_index = -1; From cdd2bd76b3fe9fc78997f32198938f34d05b41ee Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:43:38 +0000 Subject: [PATCH 0683/1502] decomp: clarify names in bridge_half_update domain_0_value_1 -> BRIDGE_HALF_WAIT_FOR_TRIGGER: Retail 0x002fb934 stores a1=1 to s0+0x20 after pivot copying and swing initialization. The same state byte is read at 0x002fb8d0 and value 1 dispatches at 0x002fb8d4 to 0x002fb938, which waits for trigger==2 or the indexed table byte==0xFF. This is exactly the source switch's existing BRIDGE_HALF_WAIT_FOR_TRIGGER domain. domain_1_value_2 -> BRIDGE_HALF_REDUCE_SWING_TO_ZERO: Retail 0x002fb974 stores a2=2 to s0+0x20 after the trigger/table condition, separately clearing trigger at s0+0xbc. The state read at 0x002fb8d0 dispatches value 2 via 0x002fb8f8 to 0x002fb988, where swing is reduced by frame_time*0.5 and clamped to zero. The same source state selector already names this member BRIDGE_HALF_REDUCE_SWING_TO_ZERO. domain_2_value_1 -> BRIDGE_HALF_WAIT_FOR_TRIGGER: After swing reaches zero, retail 0x002fba10 loads v1=1 and 0x002fba1c stores it to s0+0x20 following voice cleanup. This is the same byte read at 0x002fb8d0 whose value 1 branches to the trigger/table waiting path at 0x002fb938. Reuse the existing BRIDGE_HALF_WAIT_FOR_TRIGGER enum member for this return transition. --- src/overlays/l01/mobys/bridge_half.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l01/mobys/bridge_half.c b/src/overlays/l01/mobys/bridge_half.c index 4aed66fc43..e233a0d799 100644 --- a/src/overlays/l01/mobys/bridge_half.c +++ b/src/overlays/l01/mobys/bridge_half.c @@ -59,13 +59,13 @@ void bridge_half_update(PendulumMoby *bridge_half_moby) { case BRIDGE_HALF_INITIALIZE: qcopy(&pendulum_vars->pivot, &bridge_half_moby->pos); pendulum_vars->swing = 1.0f; - bridge_half_moby->state = 1; + bridge_half_moby->state = BRIDGE_HALF_WAIT_FOR_TRIGGER; pendulum_vars->sound = -1; break; case BRIDGE_HALF_WAIT_FOR_TRIGGER: if (bridge_half_moby->trigger == 2 || D_0014C050[bridge_half_moby->id + current_level_index * 16] == 0xFF) { - bridge_half_moby->state = 2; + bridge_half_moby->state = BRIDGE_HALF_REDUCE_SWING_TO_ZERO; bridge_half_moby->trigger = 0; } break; @@ -83,7 +83,7 @@ void bridge_half_update(PendulumMoby *bridge_half_moby) { } } pendulum_vars->sound = -1; - bridge_half_moby->state = 1; + bridge_half_moby->state = BRIDGE_HALF_WAIT_FOR_TRIGGER; } else if (!voice_is_playing(bridge_half_moby, pendulum_vars->sound)) { pendulum_vars->sound = FUN_0022da68(0, 4, bridge_half_moby); } From 721c8459a66ea5abb63d9fac60d450d0913f9ff1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:43:38 +0000 Subject: [PATCH 0684/1502] decomp: clarify names in begin_starfighter_death_sequence domain_0_value_7 -> STARFIGHTER_STATE_DEATH_FLIGHT: Retail 0x002e9804 saves the starfighter moby argument a0 in s0; 0x002e99c8 loads 7 and 0x002e99d4 stores it to that moby's current-state byte +0x20. The lethal-damage caller process_moby_attachment_damage invokes this routine when health <= incoming damage. Entry selects path slot 4 at 0x002e9844, node 0 at 0x002e9868, initializes path position/orientation, then sets speed at +0xAC and a scaled 600-frame timer at +0xF8. In the authoritative same-file update_qwarks_starfighter, switch(moby->state) names value 7 STARFIGHTER_STATE_DEATH_FLIGHT; that branch consumes these same instance fields, follows selected path without normal aiming, rolls/shrinks the starfighter, emits damage effects and advances to state 8 at the path end. This is the same starfighter current-state domain, not the hero state or voice-slot domain. --- src/overlays/l13/mobys/qwarks_starfighter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/qwarks_starfighter.c b/src/overlays/l13/mobys/qwarks_starfighter.c index e22f52b135..1bbbb33ab6 100644 --- a/src/overlays/l13/mobys/qwarks_starfighter.c +++ b/src/overlays/l13/mobys/qwarks_starfighter.c @@ -538,6 +538,9 @@ void begin_starfighter_death_sequence(struct Moby *moby, char *starfighter_moby_data, int *remaining_health) { + enum { + STARFIGHTER_STATE_DEATH_FLIGHT = 7 + }; int path_ids = (int)starfighter_moby_data + 0xB0; struct Moby *mobys; float dx; @@ -599,7 +602,7 @@ void begin_starfighter_death_sequence(struct Moby *moby, mobys[*(int *)(starfighter_moby_data + 0x134)].flags |= 1; mobys[*(int *)(starfighter_moby_data + 0x134)].visible = 0; activate_descriptor(*(int *)(starfighter_moby_data + 0x12C)); - moby->state = 7; + moby->state = STARFIGHTER_STATE_DEATH_FLIGHT; *(float *)(starfighter_moby_data + 0xAC) = D_0015ED6C * 80.0f; *(int *)(starfighter_moby_data + 0xF8) = scale_game_frames(600); queue_starfighter_voice_line(moby, (unsigned char *)starfighter_moby_data, 0x22, 1); From d7b1a3c7fb62c6541fa0f5bd37cf7482e53f7fb3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:43:38 +0000 Subject: [PATCH 0685/1502] decomp: clarify names in update_blarg_ship_hit_reactions_and_targeting domain_0_value_1 -> HIT_STATUS_SKIP_DAMAGE_AND_REACTION: Retail 002e59b0 passes sp as fifth helper argument; 002e59cc-002e59d4 reads this output and branches past health subtraction and reaction dispatch when it equals 1. Checked helper 0024cf98 retains that output in s3; 0024d0b8-0024d0d0 sets status 1 with no hit and zero damage, while 0024d45c-0024d468 sets the same status on a filtered cooldown/flags path and clears hit damage. This names the proven consumer handling, not a no-hit-only condition or moby state. domain_1_value_8 -> BLARG_SHIP_STATE_EXPLODE: Incoming moby a0 is saved in s1 at 002e5980. Retail 002e59dc-002e59e0 reads state byte at s1+0x20 and skips further hit reactions when it is 8. Authoritative blarg_ship_update passes this same ship to FUN_L10_002e5968_c before switching on ship->state at the same +0x20 layout; its existing BLARG_SHIP_STATE_EXPLODE=8 branch spawns explosions and marks the ship for removal. This is the blarg-ship state domain, not HeroStateId. domain_2_value_8 -> BLARG_SHIP_STATE_EXPLODE: Retail lethal-response branch 002e5a58-002e5a74 updates the color effect then writes 8 to incoming moby state at s1+0x20. The source caller blarg_ship_update calls this helper on the same ship before its ship->state switch, whose existing BLARG_SHIP_STATE_EXPLODE=8 case spawns the explosion and removes the moby. Reuse the same ship-domain member for this assignment and the state-8 guard. domain_3_value_7 -> BLARG_SHIP_STATE_HIT_REACTION: Retail 002e5aa4-002e5ac0 installs animation 4, reads previous state from s1+0x20, writes state 7 there, and saves previous state at s1+0xBC. Source blarg_ship_update passes this same ship to the helper before dispatching ship->state; its existing BLARG_SHIP_STATE_HIT_REACTION=7 branch waits for animation 4 completion and restores/uses pre_hit_state from ship->bBC. These paired producer/consumer operations establish the blarg-ship state domain. domain_4_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 002e5ad8-002e5aec forms hero base 0x0013f350 and reads byte +0x20A4 at 0x001413f4, comparing it with 1. Authoritative source identifies precisely this selector as hero.vehicle_mode; supplied enum domain HeroVehicleMode in include/rnc/hero/hero_state.h canonically names value 1 HERO_VEHICLE_MODE_CLANK. Equal branch 002e5af4-002e5b58 selects a hero-or-gadgebot target and checks its path volume. Reuse the exact vehicle-mode member, not equal-valued hero state or gravity constants. --- src/overlays/l10/mobys/blarg_ship.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l10/mobys/blarg_ship.c b/src/overlays/l10/mobys/blarg_ship.c index d600630db0..611032e8f4 100644 --- a/src/overlays/l10/mobys/blarg_ship.c +++ b/src/overlays/l10/mobys/blarg_ship.c @@ -486,7 +486,7 @@ void update_blarg_ship_hit_reactions_and_targeting(struct Moby *moby) { COLOR_UPDATE_WITHOUT_STATE_CHANGE_HIT_RESPONSE = 10, COLOR_EFFECT_ONLY_HIT_RESPONSE = 12, NO_REACTION_HIT_RESPONSE = 13 - }; + } ; enum { HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1 , BLARG_SHIP_STATE_HIT_REACTION = 7 , BLARG_SHIP_STATE_EXPLODE = 8}; BlargShipVars *pvars = (BlargShipVars *)moby->pvars; char *ship_hit_record = find_moby_hit(moby, 0x370000, 0); int ship_hit_processing_status; @@ -495,7 +495,7 @@ void update_blarg_ship_hit_reactions_and_targeting(struct Moby *moby) { dmg = 0.0f; hit_response_code = resolve_moby_hit_response( moby, ship_hit_record, &pvars->unk20, 5, &ship_hit_processing_status, &dmg, 0, 4); - if (ship_hit_record != 0 && ship_hit_processing_status != 1 && moby->state != 8) { + if (ship_hit_record != 0 && ship_hit_processing_status != HIT_STATUS_SKIP_DAMAGE_AND_REACTION && moby->state != BLARG_SHIP_STATE_EXPLODE) { if ((pvars->unk20 -= dmg) <= 0.0f) { hit_response_code = 1; } @@ -512,7 +512,7 @@ void update_blarg_ship_hit_reactions_and_targeting(struct Moby *moby) { case LETHAL_HIT_RESPONSE: pvars->unkC7 = 0xFA; trooper_anim_update(moby, &pvars->anim_state); - moby->state = 8; + moby->state = BLARG_SHIP_STATE_EXPLODE; break; case NO_REACTION_HIT_RESPONSE: break; @@ -522,13 +522,13 @@ void update_blarg_ship_hit_reactions_and_targeting(struct Moby *moby) { trooper_anim_update(moby, &pvars->anim_state); blend_moby_animation(moby, 4, 0, scale_game_frames(6)); moby->command = moby->state; - moby->state = 7; + moby->state = BLARG_SHIP_STATE_HIT_REACTION; break; } } moby->hit_slot = 0xFF; trooper_anim_finish(moby, &pvars->anim_state); - if (hero.vehicle_mode == 1) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { select_hero_or_gadgebot_target(101.0f, moby, &pvars->unk110); if (*(char **)&pvars->unk110 == 0) { pvars->unk114 = 2; From 2163c6d2d3aaee189db764eb1fc66ee434425c43 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:43:38 +0000 Subject: [PATCH 0686/1502] decomp: clarify names in update_moby_hit_stats_and_state domain_0_value_6 -> BLARG_SHIP_BURST_AND_DEACTIVATE: Retail 0x0031a33c reads the pvars pointer's +0x88 field; 0x0031a340-0x0031a344 selects 6 when nonzero, and 0x0031a358/0x0031a368 compares then writes that selection to the same moby's state byte +0x20, followed by animation 1 at 0x0031a380. Original Ghidra cVar8 = '\x06' and final +0x20 store agree. Supplied level-11 blarg_ship_update calls this function with moby and immediately switches on moby->state; its established enum names this exact state BLARG_SHIP_BURST_AND_DEACTIVATE = 6. Thus reuse the caller's moby-state member, not HERO_STATE_FALL. domain_1_value_2 -> BLARG_SHIP_BURST_AND_WAIT_TO_REACTIVATE: Retail 0x0031a33c-0x0031a354 selects 2 when moby pvars+0x88 is zero; 0x0031a358 compares the selection with moby+0x20 and 0x0031a368 writes it there before blending animation 1. Original Ghidra's zero iVar5 branch assigns cVar8 = '\x02' and stores it to +0x20. Supplied level-11 blarg_ship_update passes the same moby to this function before switching on moby->state, and explicitly names state 2 BLARG_SHIP_BURST_AND_WAIT_TO_REACTIVATE, sharing path/trail processing with FOLLOW_PATH. This proves the caller's moby-state domain rather than any equal-valued Hero selector. --- src/overlays/shared/props/thruster_pack_lock.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/props/thruster_pack_lock.c b/src/overlays/shared/props/thruster_pack_lock.c index cfeb82f875..bc3fe64119 100644 --- a/src/overlays/shared/props/thruster_pack_lock.c +++ b/src/overlays/shared/props/thruster_pack_lock.c @@ -738,6 +738,10 @@ extern unsigned char D_00141968[]; void update_moby_hit_stats_and_state(char *moby) __asm__("FUN_L11_0031a1c0"); void update_moby_hit_stats_and_state(char *moby) { + enum { + BLARG_SHIP_BURST_AND_WAIT_TO_REACTIVATE = 2, + BLARG_SHIP_BURST_AND_DEACTIVATE = 6 + }; char *moby_vars = ((char *)MOBY(moby)->pvars); char *hit_record = find_moby_hit(moby, 0x330000, 0); struct Hero *player_hero; @@ -771,11 +775,11 @@ void update_moby_hit_stats_and_state(char *moby) { } } if (*(int *)(moby_vars + 0x88) != 0) { - next_moby_state = 6; + next_moby_state = BLARG_SHIP_BURST_AND_DEACTIVATE; current_moby_state = ((unsigned char *)moby)[0x20]; } else { current_moby_state = ((unsigned char *)moby)[0x20]; - next_moby_state = 2; + next_moby_state = BLARG_SHIP_BURST_AND_WAIT_TO_REACTIVATE; } if (current_moby_state != next_moby_state) { MOBY(moby)->state = next_moby_state; From c3c811fb1ec163b67d138e0a8c4b2c56f9dd37fe Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:43:38 +0000 Subject: [PATCH 0687/1502] decomp: clarify names in homing_mine_spawner_update domain_0_value_1 -> HOMING_MINE_SPAWNER_WAIT_FOR_PROXIMITY: Retail 0x0030786c reads the dispatch byte at s1+0x20. After linked-moby removal, 0x003078f8 loads 1 and 0x00307a8c stores it to that same byte. Its next case at 0x003078fc-0x00307924 tests permitted XY proximity against pvars+0x70 and radius +0xF8, matching the existing local state member. domain_1_value_2 -> HOMING_MINE_SPAWNER_WAIT_FOR_PRESPAWN_ANIMATION: Retail 0x00307900 loads 2 and 0x00307924 stores it to the dispatch byte s1+0x20 on the successful proximity comparison. State 2 at 0x00307930-0x00307998 selects animation 1, waits for anim_flags & 2, then selects animation 2 before spawning, proving reuse of the existing local prespawn-animation state member. domain_2_value_3 -> HOMING_MINE_SPAWNER_SPAWN_LINKED_MOBYS: Retail 0x00307974/0x00307998 loads 3 after the prespawn animation gate, then 0x00307a8c stores it to s1+0x20, the same switch selector. State 3 at 0x0030799c-0x003079ec decrements the +0xFC timer, calls spawn_next_linked_moby at 0x003079c4 and advances the +0xF0 slot index, matching the existing local spawning member. domain_3_value_4 -> HOMING_MINE_SPAWNER_WAIT_FOR_POSTSPAWN_ANIMATION: Retail 0x003079f0-0x00307a18 detects twelve consumed slots or a -1 slot sentinel and loads 4 for the shared state store at 0x00307a8c. The same selector's state 4 at 0x00307a1c-0x00307a88 selects animation 3, waits on anim_flags & 2 and returns to animation 0, matching the existing local postspawn-animation state member. domain_4_value_5 -> HOMING_MINE_SPAWNER_SPAWN_SEQUENCE_COMPLETE: Retail 0x00307a50-0x00307a88 gates completion on anim_flags & 2, optionally selects animation 0 and loads 5; 0x00307a8c writes that value to s1+0x20, the switch selector. The authoritative source's existing state-5 member has no switch work; target updating still occurs before dispatch, so the name denotes completion of this spawn sequence only. --- src/overlays/l12/mobys/homing_mine_spawner.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l12/mobys/homing_mine_spawner.c b/src/overlays/l12/mobys/homing_mine_spawner.c index e889e090c5..d6d2e9b56a 100644 --- a/src/overlays/l12/mobys/homing_mine_spawner.c +++ b/src/overlays/l12/mobys/homing_mine_spawner.c @@ -116,12 +116,12 @@ void homing_mine_spawner_update(struct Moby *spawner) { } } } - spawner->state = 1; + spawner->state = HOMING_MINE_SPAWNER_WAIT_FOR_PROXIMITY; break; case HOMING_MINE_SPAWNER_WAIT_FOR_PROXIMITY: if (spawner_data->unkB4 != 2) { if (vector_distance_xy(&spawner->pos, &spawner_data->unk70) < spawner_data->unkF8) { - spawner->state = 2; + spawner->state = HOMING_MINE_SPAWNER_WAIT_FOR_PRESPAWN_ANIMATION; } } break; @@ -133,7 +133,7 @@ void homing_mine_spawner_update(struct Moby *spawner) { if (spawner->prev_seq != 2) { blend_moby_animation(spawner, 2, 0, scale_game_frames(2)); } - spawner->state = 3; + spawner->state = HOMING_MINE_SPAWNER_SPAWN_LINKED_MOBYS; } break; case HOMING_MINE_SPAWNER_SPAWN_LINKED_MOBYS: @@ -146,7 +146,7 @@ void homing_mine_spawner_update(struct Moby *spawner) { spawner_data->unkF0 += 1; } if (spawner_data->unkF0 == 12 || slots[spawner_data->unkF0] == -1) { - spawner->state = 4; + spawner->state = HOMING_MINE_SPAWNER_WAIT_FOR_POSTSPAWN_ANIMATION; } break; case HOMING_MINE_SPAWNER_WAIT_FOR_POSTSPAWN_ANIMATION: @@ -158,7 +158,7 @@ void homing_mine_spawner_update(struct Moby *spawner) { if (spawner->prev_seq != 0) { blend_moby_animation(spawner, 0, 0, scale_game_frames(2)); } - spawner->state = 5; + spawner->state = HOMING_MINE_SPAWNER_SPAWN_SEQUENCE_COMPLETE; } break; case HOMING_MINE_SPAWNER_SPAWN_SEQUENCE_COMPLETE: From d9be2b4bd20f1a80ef683703bb824f2b39748079 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:45:31 +0000 Subject: [PATCH 0688/1502] decomp: clarify names in select_moby_combat_target domain_0_value_0 -> COMBAT_TARGET_STATUS_DEFAULT_HERO: Source initializes selected_moby from hero_data->moby and target_selection_status to 0. Retail 0x0025fce8 clears s5 and 0x0025fd0c loads the hero Moby into s1. Unless hero exclusion or a better candidate changes the status, s5 is stored at output+0x44 and returned at 0x0025ff00. Thus 0 denotes the default hero-selection path. domain_1_value_2 -> COMBAT_TARGET_STATUS_HERO_EXCLUDED: Source clears selected_moby and assigns status 2 when hero control_mode is 0x18 or current state is 0x72. Retail branches at 0x0025fd08/0x0025fd18 reach 0x0025fd20 clearing s1 and 0x0025fd24 loading s5=2. A later alternate selection overwrites it with 1; otherwise 2 is returned/stored. The supplied Veldin caller explicitly distinguishes return 2. domain_5_value_1 -> COMBAT_TARGET_STATUS_ALTERNATE_MOBY: In the indexed candidate loop, source assigns status 1 only after the filtered candidate distance score beats best and selected_moby becomes candidate_moby. Retail 0x0025fdb0 compares f0 against f20, then 0x0025fdc0 copies candidate s0 into selected s1, 0x0025fdc4 updates best and 0x0025fdc8 loads s5=1. This is alternate-Moby selection status, not a Moby state. domain_8_value_1 -> COMBAT_TARGET_STATUS_ALTERNATE_MOBY: In the twenty-pointer candidate loop, the same target_selection_status is assigned 1 when a filtered candidate beats best. Retail 0x0025fe34 compares f0 to f20; 0x0025fe44 copies candidate s0 into selected s1, 0x0025fe48 updates best, and 0x0025fe4c loads s5=1. The common tail stores s5 at output+0x44 and returns it, proving the same alternate-Moby status as the first loop. --- src/overlays/shared/game/unlock_planet.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/game/unlock_planet.c b/src/overlays/shared/game/unlock_planet.c index 0e2254e7f3..37a7b6d410 100644 --- a/src/overlays/shared/game/unlock_planet.c +++ b/src/overlays/shared/game/unlock_planet.c @@ -30,6 +30,11 @@ int select_moby_combat_target(char *query_moby, float best) __asm__("FUN_L00_0025fcb8"); int select_moby_combat_target(char *query_moby, char *target_output, float best) { + enum { + COMBAT_TARGET_STATUS_DEFAULT_HERO = 0, + COMBAT_TARGET_STATUS_ALTERNATE_MOBY = 1, + COMBAT_TARGET_STATUS_HERO_EXCLUDED = 2 + }; struct Hero *hero_data = &hero_lui; char *selected_moby; char *candidate_moby; @@ -39,10 +44,10 @@ int select_moby_combat_target(char *query_moby, char *target_output, float best) float candidate_distance_score; selected_moby = ((char *)hero_data->moby); - target_selection_status = 0; + target_selection_status = COMBAT_TARGET_STATUS_DEFAULT_HERO; if (hero_data->state.control_mode == 0x18 || hero_data->state.current == 0x72) { selected_moby = 0; - target_selection_status = 2; + target_selection_status = COMBAT_TARGET_STATUS_HERO_EXCLUDED; } for (i = 1; i <= D_L00_001B0830_lui[0]; i++) { candidate_moby = moby_table + (D_L00_001B0830_lui[i] << 8); @@ -61,7 +66,7 @@ int select_moby_combat_target(char *query_moby, char *target_output, float best) if (candidate_distance_score < best) { selected_moby = candidate_moby; best = candidate_distance_score; - target_selection_status = 1; + target_selection_status = COMBAT_TARGET_STATUS_ALTERNATE_MOBY; } } for (j = 0; j < 20; j++) { @@ -81,7 +86,7 @@ int select_moby_combat_target(char *query_moby, char *target_output, float best) if (candidate_distance_score < best) { selected_moby = candidate_moby; best = candidate_distance_score; - target_selection_status = 1; + target_selection_status = COMBAT_TARGET_STATUS_ALTERNATE_MOBY; } } if (selected_moby != 0) { From 8b2e290fe208ae3e6c401aff73e7b662025f6888 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:47:19 +0000 Subject: [PATCH 0689/1502] decomp: clarify names in select_moby_target_with_hero_fallback domain_0_value_0 -> TARGET_SELECTION_HERO_FALLBACK: Retail 0x0024e860 initializes s5 to 0 while 0x0024e884 loads selected s1 from hero->moby at hero+0x2080. Only suppression or accepted candidates replace this status. Original Ghidra uVar12 and source target_selection_status agree; s5 is written at output+0x44 and returned at 0x0024ea78. This is the hero fallback status, without asserting a non-null hero pointer. domain_1_value_2 -> TARGET_SELECTION_HERO_FALLBACK_SUPPRESSED: Retail 0x0024e87c-0x0024e890 tests hero control_mode 0x18 or current state 0x72; the taken path clears selected s1 at 0x0024e898 and assigns s5=2 at 0x0024e89c. Source and original Ghidra confirm this disables the hero fallback while permitting later candidate selection. Unreplaced s5 is stored to output+0x44 and returned. domain_5_value_1 -> TARGET_SELECTION_CANDIDATE_SELECTED: In the indexed candidate loop, retail 0x0024e928-0x0024e940 accepts a helper result below f20, copies candidate s0 into selected s1, updates f20 and assigns status s5=1. Source target_selection_status and original Ghidra uVar12 follow this same flow to output+0x44 and the return value, proving candidate-selected status. domain_8_value_1 -> TARGET_SELECTION_CANDIDATE_SELECTED: In the 20-pointer candidate loop, retail 0x0024e9ac-0x0024e9c4 compares helper f0 below f20, copies candidate s0 into selected s1, updates f20 and assigns s5=1. It reaches the same output status store and return as the first loop; original Ghidra uVar12 and source target_selection_status prove the identical candidate-selected domain member. --- .../mobys/select_moby_target_with_hero_fallback.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/l03/mobys/select_moby_target_with_hero_fallback.c b/src/overlays/l03/mobys/select_moby_target_with_hero_fallback.c index 30efc8cd06..cfedb01980 100644 --- a/src/overlays/l03/mobys/select_moby_target_with_hero_fallback.c +++ b/src/overlays/l03/mobys/select_moby_target_with_hero_fallback.c @@ -16,6 +16,11 @@ extern struct Hero hero_lui __asm__("D_0013F350") NOT_SDA; int select_moby_target_with_hero_fallback(char *a, char *o, float best) __asm__("FUN_L03_0024e830"); int select_moby_target_with_hero_fallback(char *source_moby, char *target_output, float best) { + enum { + TARGET_SELECTION_HERO_FALLBACK = 0, + TARGET_SELECTION_CANDIDATE_SELECTED = 1, + TARGET_SELECTION_HERO_FALLBACK_SUPPRESSED = 2 + }; struct Hero *hero = &hero_lui; char *selected_moby; char *candidate_moby; @@ -25,10 +30,10 @@ int select_moby_target_with_hero_fallback(char *source_moby, char *target_output float candidate_comparison_value; selected_moby = ((char *)hero->moby); - target_selection_status = 0; + target_selection_status = TARGET_SELECTION_HERO_FALLBACK; if (hero->state.control_mode == 0x18 || hero->state.current == 0x72) { selected_moby = 0; - target_selection_status = 2; + target_selection_status = TARGET_SELECTION_HERO_FALLBACK_SUPPRESSED; } for (i = 1; i <= D_L03_001B0930[0]; i++) { candidate_moby = D_L03_0015FFD8 + (D_L03_001B0930[i] << 8); @@ -46,7 +51,7 @@ int select_moby_target_with_hero_fallback(char *source_moby, char *target_output if (candidate_comparison_value < best) { selected_moby = candidate_moby; best = candidate_comparison_value; - target_selection_status = 1; + target_selection_status = TARGET_SELECTION_CANDIDATE_SELECTED; } } for (j = 0; j < 20; j++) { @@ -65,7 +70,7 @@ int select_moby_target_with_hero_fallback(char *source_moby, char *target_output if (candidate_comparison_value < best) { selected_moby = candidate_moby; best = candidate_comparison_value; - target_selection_status = 1; + target_selection_status = TARGET_SELECTION_CANDIDATE_SELECTED; } } if (selected_moby != 0) { From d1bf8869d94209c8cc2d920159f0bcc8dc399dc8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:47:19 +0000 Subject: [PATCH 0690/1502] decomp: clarify names in start_vendor_exit_cutscene domain_0_value_3 -> VENDOR_MENU_EXIT_CUTSCENE: Retail 0x0029ad5c binds s0 to vendor_menu at 0x001ca4c0; 0x0029ad60 loads 3 and 0x0029ad80 stores it to that menu's state, followed by counter reset at 0x0029ad8c. The authoritative source binds vendor_state = &vendor_menu. Its update_vendor_menu switch on vendor_menu.state already names value 3 VENDOR_MENU_EXIT_CUTSCENE; that branch consumes the origin/basis prepared here, updates cutscene camera and mobys, and restores/closes the menu on completion. The closing branch calls start_vendor_exit_cutscene for a purchased item with a valid exit scene. This is the same vendor-menu domain, not HeroStateId or the music-stream domain. --- src/overlays/shared/vendor/vendor_menu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/vendor/vendor_menu.c b/src/overlays/shared/vendor/vendor_menu.c index 053ba8b799..597d6846d5 100644 --- a/src/overlays/shared/vendor/vendor_menu.c +++ b/src/overlays/shared/vendor/vendor_menu.c @@ -570,6 +570,9 @@ extern void sce_gs_sync_v(s32) __asm__("FUN_00122298"); void start_vendor_exit_cutscene(void) __asm__("FUN_L00_0029ad08"); void start_vendor_exit_cutscene(void) { + enum { + VENDOR_MENU_EXIT_CUTSCENE = 3 + }; VendorMenu *vendor_state; VendorMoby_29a6b0 *moby; s32 index, exit_cutscene_id, offset; @@ -584,7 +587,7 @@ void start_vendor_exit_cutscene(void) { vendor_state = &vendor_menu; D_L00_0015F5D8 = 1; ((VendorMoby_29a6b0 *)vendor_state->vendor_moby)->state = 1; - vendor_state->state = 3; + vendor_state->state = VENDOR_MENU_EXIT_CUTSCENE; vendor_state->frames = 0; cutscene_world_origin = (f32 *)((char *)vendor_state + 0xC0); transform_vector_by_basis(cutscene_world_origin, From af79df4c1453c291a04146694e7a7c53f6d594e7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:47:20 +0000 Subject: [PATCH 0691/1502] decomp: clarify names in get_target_sight domain_0_value_0 -> TARGET_SIGHT_DEFAULT_HERO: Retail 0x00288708 clears s5 to zero while 0x0028872c loads the hero moby into s1. The authoritative C initializes target_selection_status to 0 beside target_moby = hero_context->moby. Only the hero exclusion gate or a winning candidate changes this status; 0x0028891c-0x00288920 stores it at sight_out+0x44 and returns it. This is the default-hero selection status, without asserting hero pointer validity. domain_1_value_2 -> TARGET_SIGHT_HERO_EXCLUDED: Retail 0x00288724-0x00288744 tests hero control_mode 0x18 or current state 0x72, then clears s1 (the default hero target) and sets s5 to 2. The authoritative C performs target_moby = 0 and target_selection_status = 2 in that gate. Both later candidate-winning paths replace the status with 1, so surviving status 2 records hero exclusion with no selected replacement. domain_5_value_1 -> TARGET_SIGHT_CANDIDATE_SELECTED: In the first candidate loop retail 0x002887c4-0x002887e8 compares the helper result f0 with best f20; the winning branch moves candidate s0 into selected target s1, copies f0 into f20 and sets status s5 to 1. The authoritative C assigns target_moby = candidate_moby, best = candidate_metric and target_selection_status = 1 together. This proves candidate selection in the returned/output status domain. domain_8_value_1 -> TARGET_SIGHT_CANDIDATE_SELECTED: The second candidate loop uses the same s5 output status as the first: retail 0x00288848-0x0028886c compares f0 against f20, moves candidate s0 into selected s1, updates f20 and sets s5 to 1. The authoritative C repeats the same three winning-candidate assignments. Both assignments therefore reuse TARGET_SIGHT_CANDIDATE_SELECTED in the same selection-status domain, stored at +0x44 and returned at 0x00288920. --- src/overlays/l07/mobys/get_target_sight.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/l07/mobys/get_target_sight.c b/src/overlays/l07/mobys/get_target_sight.c index a90bdab3ed..9edf862780 100644 --- a/src/overlays/l07/mobys/get_target_sight.c +++ b/src/overlays/l07/mobys/get_target_sight.c @@ -16,6 +16,11 @@ extern struct Hero hero_lui __asm__("D_0013F350") NOT_SDA; int get_target_sight(char *a, char *o, float best) __asm__("FUN_L07_002886d8"); int get_target_sight(char *source_moby, char *sight_out, float best) { + enum { + TARGET_SIGHT_DEFAULT_HERO = 0, + TARGET_SIGHT_CANDIDATE_SELECTED = 1, + TARGET_SIGHT_HERO_EXCLUDED = 2 + }; struct Hero *hero_context = &hero_lui; char *target_moby; char *candidate_moby; @@ -25,10 +30,10 @@ int get_target_sight(char *source_moby, char *sight_out, float best) { float candidate_metric; target_moby = ((char *)hero_context->moby); - target_selection_status = 0; + target_selection_status = TARGET_SIGHT_DEFAULT_HERO; if (hero_context->state.control_mode == 0x18 || hero_context->state.current == 0x72) { target_moby = 0; - target_selection_status = 2; + target_selection_status = TARGET_SIGHT_HERO_EXCLUDED; } for (i = 1; i <= D_L07_001B08B0[0]; i++) { candidate_moby = level_mobys + (D_L07_001B08B0[i] << 8); @@ -46,7 +51,7 @@ int get_target_sight(char *source_moby, char *sight_out, float best) { if (candidate_metric < best) { target_moby = candidate_moby; best = candidate_metric; - target_selection_status = 1; + target_selection_status = TARGET_SIGHT_CANDIDATE_SELECTED; } } for (j = 0; j < 20; j++) { @@ -65,7 +70,7 @@ int get_target_sight(char *source_moby, char *sight_out, float best) { if (candidate_metric < best) { target_moby = candidate_moby; best = candidate_metric; - target_selection_status = 1; + target_selection_status = TARGET_SIGHT_CANDIDATE_SELECTED; } } if (target_moby != 0) { From 7ceef12cd3e9c3c0de5a829649114137c6ed2399 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:47:20 +0000 Subject: [PATCH 0692/1502] decomp: clarify names in process_blarg_helicopter_hits domain_1_value_6 -> BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET: Retail 0x002eb238 retains the helicopter argument in s0; 0x002eb2a0 loads its state byte at +0x20 and 0x002eb2a4 skips processing when it equals 6. This is the same moby passed by blarg_helicopter_update before its state switch. That source's existing BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET = 6 branch spawns the explosion and removes or resets that helicopter; this is its current-state domain, not HeroStateId. domain_2_value_6 -> BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET: Retail 0x002eb2e4 subtracts damage from helicopter pvars+0x20; reaction code 1 or health <= 0 selects 0x002eb300-0x002eb314, storing 6 to the same helicopter's state byte at s0+0x20. The supplied caller immediately dispatches that state through existing BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET = 6, which spawns an explosion and removes or resets the instance. domain_3_value_5 -> BLARG_HELICOPTER_KNOCKBACK: Retail 0x002eb350 loads 5, then 0x002eb354-0x002eb358 compares it with the helicopter state byte at s0+0x20 to avoid reentering the directional recoil path. The same argument is dispatched by blarg_helicopter_update's established BLARG_HELICOPTER_KNOCKBACK = 5 branch, which moves the helicopter backwards until pvars+0x8e expires and restores moby->command. domain_4_value_5 -> BLARG_HELICOPTER_KNOCKBACK: Retail 0x002eb434 sets helicopter recoil speed at pvars+0x94, 0x002eb438 stores a scaled 60-frame timer at +0x8e, and 0x002eb448-0x002eb454 saves the previous state to command (+0xbc) while storing 5 to state (+0x20). The caller's existing BLARG_HELICOPTER_KNOCKBACK = 5 branch consumes that exact timer/speed and restores command on expiration, proving this state-domain name. --- src/overlays/l12/mobys/blarg_helicopter.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l12/mobys/blarg_helicopter.c b/src/overlays/l12/mobys/blarg_helicopter.c index 3f1cab2666..604a4802d7 100644 --- a/src/overlays/l12/mobys/blarg_helicopter.c +++ b/src/overlays/l12/mobys/blarg_helicopter.c @@ -634,7 +634,7 @@ extern void trooper_anim_update(void *m, short *p) __asm__("FUN_L00_0025d458"); extern void trooper_anim_finish(void *, void *) __asm__("FUN_L00_0025d538"); void process_blarg_helicopter_hits(struct Moby *moby) { - int hit_processing_status; + enum { BLARG_HELICOPTER_KNOCKBACK = 5 , BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET = 6 } ;int hit_processing_status; float fv; int hit_reaction_code; BlargHelicopterVars *blarg_helicopter_hit_vars; @@ -645,7 +645,7 @@ void process_blarg_helicopter_hits(struct Moby *moby) { hit_record = find_moby_hit(moby, 0x330000, 0); hit_reaction_code = hit_reaction( moby, hit_record, &blarg_helicopter_hit_vars->health, 0, &hit_processing_status, &fv, 0, 4); - if (hit_processing_status != 1 && moby->state != 6 && + if (hit_processing_status != 1 && moby->state != BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET && *(short *)(*(char **)(hit_record + 0x20) + 0xA6) != 0xB8 && *(short *)(*(char **)(hit_record + 0x20) + 0xA6) != 0x199) { float remaining_health; @@ -655,11 +655,11 @@ void process_blarg_helicopter_hits(struct Moby *moby) { blarg_helicopter_hit_vars->health = remaining_health; if (hit_reaction_code == 1 || remaining_health <= 0.0f) { allocate_voice_for_target_entry(2, 0, moby); - moby->state = 6; + moby->state = BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET; } else if (hit_reaction_code != 0xB) { blarg_helicopter_hit_vars->unk67 = 0xB4; trooper_anim_update(moby, (short *)&blarg_helicopter_hit_vars->anim_state); - if (*(float *)(hit_record + 0x1C) == 5627.925f && moby->state != 5) { + if (*(float *)(hit_record + 0x1C) == 5627.925f && moby->state != BLARG_HELICOPTER_KNOCKBACK) { hit_to_moby_angle = fast_arc_tan(moby->pos.x - *(float *)(hit_record + 0), moby->pos.y - *(float *)(hit_record + 4)); hit_yaw_offset = fast_subtract_rotations(hit_to_moby_angle, moby->rot.z); @@ -676,7 +676,7 @@ void process_blarg_helicopter_hits(struct Moby *moby) { blarg_helicopter_hit_vars->unk94 = frame_time * 4.0f; blarg_helicopter_hit_vars->unk8E = scale_game_frames(0x3C); moby->command = moby->state; - moby->state = 5; + moby->state = BLARG_HELICOPTER_KNOCKBACK; allocate_voice_for_target_entry(1, 0, moby); } } From 0521e9bf53a9fa8e044960a91c9c06ceaf0f8302 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:47:20 +0000 Subject: [PATCH 0693/1502] decomp: clarify names in select_robosquawker_target domain_0_value_0 -> ROBOSQUAWKER_TARGET_DEFAULT_HERO: Retail 0026bd30 initializes s5 to zero and 0026bd54 loads s1 from hero.moby; source initializes selection_status=0 beside selected_object=hero->moby. Unless suppression or candidate replacement occurs, this provenance status reaches output+0x44 at 0026bef4/0026bf28/0026bf44 and the return at 0026bf48. This denotes the default hero selection policy, not a guarantee of a non-null pointer. domain_1_value_2 -> ROBOSQUAWKER_TARGET_HERO_SUPPRESSED: Retail 0026bd4c-0026bd60 tests hero control mode 0x18 and current state 0x72; the taken exclusion path clears selected pointer s1 at 0026bd68 and assigns s5=2 at 0026bd6c. Source performs selected_object=0 and selection_status=2 together. Candidate replacement can subsequently overwrite this status; 2 describes suppression of the initial hero target. domain_2_value_1 -> ROBOSQUAWKER_TARGET_CANDIDATE_SELECTED: In the indexed moby-pool loop, retail 0026bdf0-0026be00 compares the candidate helper result against the current bound; 0026be08 replaces selected pointer s1 with candidate s0, 0026be0c updates the bound and 0026be10 sets s5=1. Source likewise assigns selection_status=1 only after accepting candidate_object. The value denotes candidate selection in this output-status domain. domain_3_value_1 -> ROBOSQUAWKER_TARGET_CANDIDATE_SELECTED: In the twenty-pointer candidate loop, retail 0026be74-0026be84 compares the helper result against the bound; 0026be8c copies candidate s0 to selected pointer s1, 0026be90 updates the bound and 0026be94 sets s5=1. This is the same selection_status binding and output+0x44/return data flow as 0026be10, proving reuse of the candidate-selected member. --- src/overlays/l13/mobys/robosquawker.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/l13/mobys/robosquawker.c b/src/overlays/l13/mobys/robosquawker.c index 837e02e210..f6b5af95ee 100644 --- a/src/overlays/l13/mobys/robosquawker.c +++ b/src/overlays/l13/mobys/robosquawker.c @@ -51,6 +51,11 @@ int select_robosquawker_target(char *source_object, float best) __asm__("FUN_L13_0026bd00"); int select_robosquawker_target(char *source_object, char *selection_output, float best) { + enum { + ROBOSQUAWKER_TARGET_DEFAULT_HERO = 0, + ROBOSQUAWKER_TARGET_CANDIDATE_SELECTED = 1, + ROBOSQUAWKER_TARGET_HERO_SUPPRESSED = 2 + }; struct Hero *hero = &hero_lui; char *selected_object; char *candidate_object; @@ -60,10 +65,10 @@ int select_robosquawker_target(char *source_object, char *selection_output, floa float candidate_metric; selected_object = ((char *)hero->moby); - selection_status = 0; + selection_status = ROBOSQUAWKER_TARGET_DEFAULT_HERO; if (hero->state.control_mode == 0x18 || hero->state.current == 0x72) { selected_object = 0; - selection_status = 2; + selection_status = ROBOSQUAWKER_TARGET_HERO_SUPPRESSED; } for (i = 1; i <= D_L13_001B0B30[0]; i++) { candidate_object = (char *)moby_base + (D_L13_001B0B30[i] << 8); @@ -82,7 +87,7 @@ int select_robosquawker_target(char *source_object, char *selection_output, floa if (candidate_metric < best) { selected_object = candidate_object; best = candidate_metric; - selection_status = 1; + selection_status = ROBOSQUAWKER_TARGET_CANDIDATE_SELECTED; } } for (j = 0; j < 20; j++) { @@ -101,7 +106,7 @@ int select_robosquawker_target(char *source_object, char *selection_output, floa if (candidate_metric < best) { selected_object = candidate_object; best = candidate_metric; - selection_status = 1; + selection_status = ROBOSQUAWKER_TARGET_CANDIDATE_SELECTED; } } if (selected_object != 0) { From 391591ceb93bb69b416292dde721fe016b7bbc61 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:47:20 +0000 Subject: [PATCH 0694/1502] decomp: clarify names in find_point_ahead domain_0_value_0 -> POINT_AHEAD_HERO_FALLBACK: Source initializes selected_entity from hero->moby immediately before selection_status=0. Retail 0x00274ba8 initializes s5 to zero and 0x00274bcc loads hero moby into s1. The exclusion branch overrides both; either candidate-selection branch overrides both. Otherwise s5 is stored at target_out+0x44 and returned at 0x00274dc0, proving the default hero-fallback selection result. domain_1_value_2 -> POINT_AHEAD_NO_TARGET: Retail 0x00274be0 clears selected pointer s1 and 0x00274be4 sets selection result s5 to 2 on the hero exclusion branch. Both successful search branches replace s1 and set s5 to 1. Thus a surviving result 2 has no selected entity: 0x00274da4-0x00274dbc clears output pointer/vectors and stores s5, which 0x00274dc0 returns. This names the selection result rather than the excluded hero control/state values. domain_2_value_1 -> POINT_AHEAD_CANDIDATE_SELECTED: In the first candidate loop, retail 0x00274c70 compares helper result f0 with best f20. On improvement, 0x00274c80 copies candidate s0 into selected s1, 0x00274c84 updates best, and 0x00274c88 assigns selection result s5=1. The selected pointer is output at 0x00274d24 and s5 is stored at target_out+0x44 and returned, proving candidate-selected status. domain_3_value_1 -> POINT_AHEAD_CANDIDATE_SELECTED: The second search uses the same selection_status variable and return domain. After comparison at 0x00274cf4, 0x00274d04 copies candidate s0 to selected s1, 0x00274d08 updates best f20, and 0x00274d0c sets s5=1. This is the same candidate-selected result as the first loop; s1 supplies target_out+0x40 and s5 supplies target_out+0x44 and the return value. --- src/overlays/shared/mobys/find_point_ahead.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/mobys/find_point_ahead.c b/src/overlays/shared/mobys/find_point_ahead.c index 3c959108d6..66e53cf3f2 100644 --- a/src/overlays/shared/mobys/find_point_ahead.c +++ b/src/overlays/shared/mobys/find_point_ahead.c @@ -16,6 +16,11 @@ int find_point_ahead(char *a, char *o, float best) __asm__("FUN_L int find_point_ahead(char *source_entity, char *target_out, float best) __asm__("FUN_L01_00274b78"); int find_point_ahead(char *source_entity, char *target_out, float best) { + enum { + POINT_AHEAD_HERO_FALLBACK = 0, + POINT_AHEAD_CANDIDATE_SELECTED = 1, + POINT_AHEAD_NO_TARGET = 2 + }; struct Hero *hero = &hero_lui; char *selected_entity; char *candidate_entity; @@ -25,10 +30,10 @@ int find_point_ahead(char *source_entity, char *target_out, float best) { float candidate_metric; selected_entity = ((char *)hero->moby); - selection_status = 0; + selection_status = POINT_AHEAD_HERO_FALLBACK; if (hero->state.control_mode == 0x18 || hero->state.current == 0x72) { selected_entity = 0; - selection_status = 2; + selection_status = POINT_AHEAD_NO_TARGET; } for (i = 1; i <= D_L01_001B0CB0[0]; i++) { candidate_entity = ents + (D_L01_001B0CB0[i] << 8); @@ -47,7 +52,7 @@ int find_point_ahead(char *source_entity, char *target_out, float best) { if (candidate_metric < best) { selected_entity = candidate_entity; best = candidate_metric; - selection_status = 1; + selection_status = POINT_AHEAD_CANDIDATE_SELECTED; } } for (j = 0; j < 20; j++) { @@ -66,7 +71,7 @@ int find_point_ahead(char *source_entity, char *target_out, float best) { if (candidate_metric < best) { selected_entity = candidate_entity; best = candidate_metric; - selection_status = 1; + selection_status = POINT_AHEAD_CANDIDATE_SELECTED; } } if (selected_entity != 0) { From 1f95e78cca7bb1a9ae1589cf1eac47b7d7efdec8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:47:20 +0000 Subject: [PATCH 0695/1502] decomp: clarify names in update_moby_path_follower domain_0_value_0 -> PATH_FOLLOWER_STATE_INITIALIZE: Retail 0x0030bb90-0x0030bb94 tests this moby's state byte at +0x20 for zero; 0x0030bba4-0x0030bc30 initializes update distance, configured path segment lengths, saved segment/progress and update counter before entering state 1. Authoritative C agrees, proving the follower initialization state. domain_1_value_1 -> PATH_FOLLOWER_STATE_PROJECT_TARGET_ONTO_PATH: Retail 0x0030bc24-0x0030bc2c assigns 1 to this follower's state byte +0x20 after initialization; 0x0030bca0-0x0030bcac tests the same byte for 1. That branch calls nearest-path helper 0x00269fb0 with target+0x10 and copies its projected position to follower+0x10 at 0x0030bd24-0x0030bd34. Supplied helper C confirms nearest-path projection. domain_2_value_1 -> PATH_FOLLOWER_STATE_PROJECT_TARGET_ONTO_PATH: Retail 0x0030bc24-0x0030bc2c assigns 1 to this follower's state byte +0x20 after initialization; 0x0030bca0-0x0030bcac tests the same byte for 1. That branch calls nearest-path helper 0x00269fb0 with target+0x10 and copies its projected position to follower+0x10 at 0x0030bd24-0x0030bd34. Supplied helper C confirms nearest-path projection. domain_3_value_2 -> PATH_FOLLOWER_STATE_ADVANCE_ALONG_PATH: Retail 0x0030bd40-0x0030bd44 writes 2 to follower state +0x20 after nearest segment/progress cease increasing and the initial 30 updates have elapsed; 0x0030bd48-0x0030bd50 tests the same byte for 2. The branch calls compute_advanced_moby_path_position at 0x0030bd8c with index step 1 and frame_scale*0.25, updating follower position and saved segment. This is autonomous advancement along the configured path. domain_4_value_2 -> PATH_FOLLOWER_STATE_ADVANCE_ALONG_PATH: Retail 0x0030bd40-0x0030bd44 writes 2 to follower state +0x20 after nearest segment/progress cease increasing and the initial 30 updates have elapsed; 0x0030bd48-0x0030bd50 tests the same byte for 2. The branch calls compute_advanced_moby_path_position at 0x0030bd8c with index step 1 and frame_scale*0.25, updating follower position and saved segment. This is autonomous advancement along the configured path. domain_5_value_3 -> PATH_FOLLOWER_STATE_PATH_END_REACHED: Retail 0x0030bd58-0x0030bd68 compares the saved path segment against the configured path point count minus one. If the saved segment is at or beyond that final index, 0x0030bdb4-0x0030bdbc writes 3 to this follower's state byte +0x20 instead of advancing. Authoritative C agrees, proving a path-end-reached state without claiming removal or a gameplay completion event. --- src/overlays/l13/mobys/moby_path_follower.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l13/mobys/moby_path_follower.c b/src/overlays/l13/mobys/moby_path_follower.c index f0c829d490..f45591cb3c 100644 --- a/src/overlays/l13/mobys/moby_path_follower.c +++ b/src/overlays/l13/mobys/moby_path_follower.c @@ -17,7 +17,7 @@ void moby_path_follower_update(struct Moby *moby) __asm__("FUN_L13_0030bb70"); /* Moby class 1403 */ void moby_path_follower_update(struct Moby *moby) { - int *moby_vars = (int *)moby->pvars; + enum { PATH_FOLLOWER_STATE_INITIALIZE = 0 , PATH_FOLLOWER_STATE_PROJECT_TARGET_ONTO_PATH = 1 , PATH_FOLLOWER_STATE_ADVANCE_ALONG_PATH = 2 , PATH_FOLLOWER_STATE_PATH_END_REACHED = 3 } ;int *moby_vars = (int *)moby->pvars; char *path; char *pth; char *target_moby; @@ -25,7 +25,7 @@ void moby_path_follower_update(struct Moby *moby) { int nearest_segment_index; float nearest_segment_progress; int i; - if (moby->state == 0) { + if (moby->state == PATH_FOLLOWER_STATE_INITIALIZE) { moby->update_dist = 0xFF; if (moby_vars[1] != -1) { path = D_L13_001B07B0[moby_vars[1]]; @@ -36,7 +36,7 @@ void moby_path_follower_update(struct Moby *moby) { } moby_vars[2] = 0; moby_vars[3] = 0; - moby->state = 1; + moby->state = PATH_FOLLOWER_STATE_PROJECT_TARGET_ONTO_PATH; moby_vars[4] = 0; } if (moby_vars[0] == -1) @@ -52,7 +52,7 @@ void moby_path_follower_update(struct Moby *moby) { if (moby_vars[1] == -1) return; pth = D_L13_001B07B0[moby_vars[1]]; - if (moby->state == 1) { + if (moby->state == PATH_FOLLOWER_STATE_PROJECT_TARGET_ONTO_PATH) { FUN_L00_0025df68(pth, target_moby + 0x10, nearest_path_position, @@ -68,17 +68,17 @@ void moby_path_follower_update(struct Moby *moby) { ((float *)moby_vars)[3] = nearest_segment_progress; qcopy(&moby->pos, nearest_path_position); } else { - moby->state = 2; + moby->state = PATH_FOLLOWER_STATE_ADVANCE_ALONG_PATH; } } - if (moby->state == 2) { + if (moby->state == PATH_FOLLOWER_STATE_ADVANCE_ALONG_PATH) { if (moby_vars[2] < *(int *)pth - 1) { int k = compute_advanced_moby_path_position( moby, pth, &moby->pos, moby_vars[2], 1, frame_scale * 0.25f); moby_vars[2] = k; ((float *)moby_vars)[3] = fast_vec_dist(&moby->pos, pth + (k * 16 + 0x10)); } else { - moby->state = 3; + moby->state = PATH_FOLLOWER_STATE_PATH_END_REACHED; } } } else { From 237ff333a0ac0d57af58c7fa12f938e744118fed Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:47:20 +0000 Subject: [PATCH 0696/1502] decomp: clarify names in select_moby_by_xy_distance domain_0_value_0 -> MOBY_SELECTION_HERO_FALLBACK: Bound source initializes selected_moby from hero->moby and selection_status to 0. Retail 0x00268068 initializes s5=0 and 0x0026808c loads s1=hero.moby. Every accepted loop candidate changes s5 to 1, and the exclusion path changes it to 2, so surviving status 0 identifies retention of the initial hero fallback, as original Ghidra uVar12/iVar8 also show. domain_1_value_2 -> MOBY_SELECTION_NO_TARGET: Retail 0x002680a0 clears selected s1 and 0x002680a4 sets status s5=2 after the two hero exclusions. Either candidate acceptance overwrites status with 1 at 0x00268148 or 0x002681cc; thus retained 2 entails no selected target. 0x00268264 zeros output pointer and vectors, and 0x0026827c-0x00268280 stores/returns this status. Bound machinegun_turret_update rejects return 2 before testing the target point. domain_5_value_1 -> MOBY_SELECTION_DISTANCE_CANDIDATE: First candidate loop retail 0x00268128 calls the XY distance helper; 0x00268130 compares f0 MOBY_SELECTION_DISTANCE_CANDIDATE: Second candidate loop retail 0x002681ac calls the same XY distance helper and 0x002681b4 compares its result to best. On strict improvement 0x002681c4-0x002681cc copies candidate s0 to selected s1, updates f20 and assigns status s5=1. This is the same selection_status domain and accepted-distance-candidate outcome as the first loop, also explicit in original Ghidra and bound source. --- src/overlays/l14/mobys/machinegun_turret.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/l14/mobys/machinegun_turret.c b/src/overlays/l14/mobys/machinegun_turret.c index ee879ac668..0ce4da0f11 100644 --- a/src/overlays/l14/mobys/machinegun_turret.c +++ b/src/overlays/l14/mobys/machinegun_turret.c @@ -106,6 +106,11 @@ int select_moby_by_xy_distance(char *selection_reference, float best) __asm__("FUN_L14_00268038"); int select_moby_by_xy_distance(char *selection_reference, char *selection_output, float best) { + enum { + MOBY_SELECTION_HERO_FALLBACK = 0, + MOBY_SELECTION_DISTANCE_CANDIDATE = 1, + MOBY_SELECTION_NO_TARGET = 2 + }; struct Hero *hero = &hero_lui; char *selected_moby; char *candidate_moby; @@ -115,10 +120,10 @@ int select_moby_by_xy_distance(char *selection_reference, char *selection_output float candidate_metric; selected_moby = ((char *)hero->moby); - selection_status = 0; + selection_status = MOBY_SELECTION_HERO_FALLBACK; if (hero->state.control_mode == 0x18 || hero->state.current == 0x72) { selected_moby = 0; - selection_status = 2; + selection_status = MOBY_SELECTION_NO_TARGET; } for (i = 1; i <= D_L14_001B0F30[0]; i++) { candidate_moby = D_L14_0015FFD8 + (D_L14_001B0F30[i] << 8); @@ -136,7 +141,7 @@ int select_moby_by_xy_distance(char *selection_reference, char *selection_output if (candidate_metric < best) { selected_moby = candidate_moby; best = candidate_metric; - selection_status = 1; + selection_status = MOBY_SELECTION_DISTANCE_CANDIDATE; } } for (j = 0; j < 20; j++) { @@ -155,7 +160,7 @@ int select_moby_by_xy_distance(char *selection_reference, char *selection_output if (candidate_metric < best) { selected_moby = candidate_moby; best = candidate_metric; - selection_status = 1; + selection_status = MOBY_SELECTION_DISTANCE_CANDIDATE; } } if (selected_moby != 0) { From 8dc720c359515a930139bececb4dca3768d423dc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:49:13 +0000 Subject: [PATCH 0697/1502] decomp: clarify names in select_moby_target_goal domain_0_value_0 -> TARGET_SELECTION_DEFAULT_HERO: Retail 0x00261cb0 initializes s5/uVar12/selection_status to zero while 0x00261cd4 loads the initial selected_moby from hero.moby. Only the exclusion branch or a winning candidate changes this status; 0x00261ec4-0x00261ec8 stores it at output +0x44 and returns it. Thus zero identifies the unchanged default hero selection, even if that pointer is null. domain_1_value_2 -> TARGET_SELECTION_HERO_EXCLUDED: Retail 0x00261ccc-0x00261ce0 tests the supplied C hero control_mode and current state. On either exclusion condition, 0x00261ce8 clears selected_moby/s1 and 0x00261cec assigns selection_status/s5 = 2. It remains this status unless a candidate subsequently wins, proving an initial hero-excluded selection outcome. domain_5_value_1 -> TARGET_SELECTION_CANDIDATE: The first filtered candidate loop compares the helper result with the running bound at 0x00261d78-0x00261d80. Only a lower result reaches 0x00261d88-0x00261d90, which replaces selected_moby with candidate_moby, updates the bound, and assigns selection_status/s5 = 1. This proves candidate-selected status. domain_8_value_1 -> TARGET_SELECTION_CANDIDATE: The second filtered candidate loop compares the helper result against f20 at 0x00261dfc-0x00261e04. The winning branch at 0x00261e0c-0x00261e14 replaces selected_moby with candidate_moby, updates the bound, and assigns selection_status/s5 = 1, exactly the same candidate-selected outcome as the first loop. --- src/overlays/shared/mobys/select_moby_target_goal.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/mobys/select_moby_target_goal.c b/src/overlays/shared/mobys/select_moby_target_goal.c index 75b1994eae..4fc8bf8a5a 100644 --- a/src/overlays/shared/mobys/select_moby_target_goal.c +++ b/src/overlays/shared/mobys/select_moby_target_goal.c @@ -19,6 +19,11 @@ int select_moby_target_goal(char *comparison_source, float best) __asm__("FUN_L02_00261c80"); int select_moby_target_goal(char *comparison_source, char *output_data, float best) { + enum { + TARGET_SELECTION_DEFAULT_HERO = 0, + TARGET_SELECTION_CANDIDATE = 1, + TARGET_SELECTION_HERO_EXCLUDED = 2 + }; struct Hero *hero = &hero_lui; char *selected_moby; char *candidate_moby; @@ -28,10 +33,10 @@ int select_moby_target_goal(char *comparison_source, char *output_data, float be float candidate_metric; selected_moby = ((char *)hero->moby); - selection_status = 0; + selection_status = TARGET_SELECTION_DEFAULT_HERO; if (hero->state.control_mode == 0x18 || hero->state.current == 0x72) { selected_moby = 0; - selection_status = 2; + selection_status = TARGET_SELECTION_HERO_EXCLUDED; } for (i = 1; i <= D_L02_001B0E30[0]; i++) { candidate_moby = D_L00_0015FFD8_25fcb8 + (D_L02_001B0E30[i] << 8); @@ -49,7 +54,7 @@ int select_moby_target_goal(char *comparison_source, char *output_data, float be if (candidate_metric < best) { selected_moby = candidate_moby; best = candidate_metric; - selection_status = 1; + selection_status = TARGET_SELECTION_CANDIDATE; } } for (j = 0; j < 20; j++) { @@ -68,7 +73,7 @@ int select_moby_target_goal(char *comparison_source, char *output_data, float be if (candidate_metric < best) { selected_moby = candidate_moby; best = candidate_metric; - selection_status = 1; + selection_status = TARGET_SELECTION_CANDIDATE; } } if (selected_moby != 0) { From ac0b331bf7f1d6359e088d940cc31818b7c789db Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:49:13 +0000 Subject: [PATCH 0698/1502] decomp: clarify names in select_moby_record_by_xy_distance domain_0_value_0 -> MOBY_SELECTION_HERO_FALLBACK: Source initializes selected_moby from hero->moby and selection_status to 0. Retail loads s1 from hero+0x2080 at 0x00252e6c and initializes s5 to zero at 0x00252e48. Unless hero exclusion or a closer-candidate branch overwrites them, that original pointer and status survive to output+0x40/+0x44 and return. domain_1_value_2 -> MOBY_SELECTION_NO_TARGET: Hero exclusion branches reach 0x00252e80-0x00252e84, clearing selected pointer s1 and assigning status s5=2. Both candidate-selection branches replace this with status 1 when setting a nonnull candidate. If status 2 survives, s1 remains zero and 0x00253044-0x00253060 clears the output record and returns/stores that status. domain_5_value_1 -> MOBY_SELECTION_NEARER_CANDIDATE: In the indexed-candidate loop, the XY distance helper result f0 is tested against running bound f20 at 0x00252f10. Only its strictly-smaller branch copies candidate s0 to selected s1, updates the bound, and sets s5=1 at 0x00252f20-0x00252f28. Source selection_status has this same flow and is returned and stored at output+0x44. domain_8_value_1 -> MOBY_SELECTION_NEARER_CANDIDATE: The pointer-table loop tests candidate XY distance f0 against bound f20 at 0x00252f94. A strictly-smaller result copies candidate s0 into selected s1, updates f20, and sets s5=1 at 0x00252fa4-0x00252fac. This is the same selection_status domain and outcome as the indexed-candidate loop, so both assignments share the constant. --- .../mobys/select_moby_record_by_xy_distance.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/mobys/select_moby_record_by_xy_distance.c b/src/overlays/shared/mobys/select_moby_record_by_xy_distance.c index eef9f287d8..c580b9b302 100644 --- a/src/overlays/shared/mobys/select_moby_record_by_xy_distance.c +++ b/src/overlays/shared/mobys/select_moby_record_by_xy_distance.c @@ -16,6 +16,11 @@ extern struct Hero hero_lui __asm__("D_0013F350") NOT_SDA; int select_moby_record_by_xy_distance(char *a, char *o, float best) __asm__("FUN_L04_00252e18"); int select_moby_record_by_xy_distance(char *reference_object, char *output_record, float best) { + enum { + MOBY_SELECTION_HERO_FALLBACK = 0, + MOBY_SELECTION_NEARER_CANDIDATE = 1, + MOBY_SELECTION_NO_TARGET = 2 + }; struct Hero *hero = &hero_lui; char *selected_moby; char *candidate_moby; @@ -25,10 +30,10 @@ int select_moby_record_by_xy_distance(char *reference_object, char *output_recor float candidate_comparison_value; selected_moby = ((char *)hero->moby); - selection_status = 0; + selection_status = MOBY_SELECTION_HERO_FALLBACK; if (hero->state.control_mode == 0x18 || hero->state.current == 0x72) { selected_moby = 0; - selection_status = 2; + selection_status = MOBY_SELECTION_NO_TARGET; } for (i = 1; i <= D_L04_001B09B0[0]; i++) { candidate_moby = moby_array + (D_L04_001B09B0[i] << 8); @@ -47,7 +52,7 @@ int select_moby_record_by_xy_distance(char *reference_object, char *output_recor if (candidate_comparison_value < best) { selected_moby = candidate_moby; best = candidate_comparison_value; - selection_status = 1; + selection_status = MOBY_SELECTION_NEARER_CANDIDATE; } } for (j = 0; j < 20; j++) { @@ -67,7 +72,7 @@ int select_moby_record_by_xy_distance(char *reference_object, char *output_recor if (candidate_comparison_value < best) { selected_moby = candidate_moby; best = candidate_comparison_value; - selection_status = 1; + selection_status = MOBY_SELECTION_NEARER_CANDIDATE; } } if (selected_moby != 0) { From 9cbc791d2b7d62195d2e8bab8b9de5e30b830d9f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:49:13 +0000 Subject: [PATCH 0699/1502] decomp: clarify names in update_lift_state_and_queue_draw domain_0_value_1 -> LIFT_SELECT_INITIAL_HEIGHT: Retail 0x002f2398 stores a1=1 to s0+0x20 after initialization; 0x002f2328 reads that same state byte and 0x002f232c branches on 1 to 0x002f23ac, the existing LIFT_SELECT_INITIAL_HEIGHT case which selects pos.z from pvars+0/+4. Original Ghidra and the bound source agree. domain_1_value_2 -> LIFT_APPROACH_BASE_HEIGHT: Retail 0x002f23e4-0x002f23f4 stores 2 to the state byte s0+0x20 and initializes pos.z from pvars+0. The same state read at 0x002f2328 dispatches value 2 at 0x002f2350 to 0x002f2478, whose accelerated movement target at 0x002f24c0 is pvars+0: existing LIFT_APPROACH_BASE_HEIGHT. domain_2_value_3 -> LIFT_APPROACH_ALTERNATE_HEIGHT: Retail 0x002f23f8-0x002f2408 stores 3 to s0+0x20 and initializes pos.z from pvars+4. State dispatch 0x002f2354-0x002f235c sends 3 to 0x002f240c; its movement loads pvars+4 at 0x002f2454, matching existing LIFT_APPROACH_ALTERNATE_HEIGHT in the authoritative source and original Ghidra. domain_3_value_2 -> LIFT_APPROACH_BASE_HEIGHT: In the alternate-height case, retail 0x002f240c tests command bit 4 and 0x002f241c stores a0=2 into the same s0+0x20 state byte read by dispatch at 0x002f2328/0x002f2350. That destination case 0x002f2478 approaches pvars+0 at 0x002f24c0, proving reuse of existing LIFT_APPROACH_BASE_HEIGHT rather than a command constant. domain_4_value_3 -> LIFT_APPROACH_ALTERNATE_HEIGHT: In the base-height case, retail 0x002f2478-0x002f2488 tests command bit 8 then stores 3 into s0+0x20; 0x002f248c also sets the alternate-height request. The state dispatch for 3 reaches 0x002f240c and loads pvars+4 as its target at 0x002f2454, proving existing LIFT_APPROACH_ALTERNATE_HEIGHT. --- src/overlays/l18/mobys/lift.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l18/mobys/lift.c b/src/overlays/l18/mobys/lift.c index 9c6ae04a26..2839c8cc43 100644 --- a/src/overlays/l18/mobys/lift.c +++ b/src/overlays/l18/mobys/lift.c @@ -86,7 +86,7 @@ void lift_update(struct Moby *lift_moby) { } *(int *)(lift_vars + 0x1C) = next_lift_instance_index_gp++; lift_moby->update_dist = 0xFF; - lift_moby->state = 1; + lift_moby->state = LIFT_SELECT_INITIAL_HEIGHT; ((M_2310 *)lift_moby)->h34 |= 1; lift_moby->draw_dist = 0; lift_moby->collision = 0; @@ -98,17 +98,17 @@ void lift_update(struct Moby *lift_moby) { initial_height_selector = *(int *)(lift_vars + 8); next_lift_instance_index_gp = 0; if (initial_height_selector != 0 && D_00141400 == 0) { - lift_moby->state = 2; + lift_moby->state = LIFT_APPROACH_BASE_HEIGHT; lift_moby->pos.z = *(float *)(lift_vars + 0); } else { - lift_moby->state = 3; + lift_moby->state = LIFT_APPROACH_ALTERNATE_HEIGHT; lift_moby->pos.z = *(float *)(lift_vars + 4); } break; case LIFT_APPROACH_ALTERNATE_HEIGHT: if (lift_moby->command & 4) { lift_alternate_height_requested_gp = 0; - lift_moby->state = 2; + lift_moby->state = LIFT_APPROACH_BASE_HEIGHT; if (*(int *)(lift_vars + 8) == 0) { D_0013D406 = 1; } @@ -124,7 +124,7 @@ void lift_update(struct Moby *lift_moby) { break; case LIFT_APPROACH_BASE_HEIGHT: if (lift_moby->command & 8) { - lift_moby->state = 3; + lift_moby->state = LIFT_APPROACH_ALTERNATE_HEIGHT; lift_alternate_height_requested_gp = 1; } lift_moby->command = 2; From 1faa049ccd5aed97e70649ecba896cd5e40eb283 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:49:13 +0000 Subject: [PATCH 0700/1502] decomp: clarify names in select_nearest_xy_moby_with_hero_fallback domain_0_value_0 -> XY_SELECTION_HERO_FALLBACK: At 0x0026a400 s5 starts at zero and 0x0026a424 loads hero.moby into selected s1. Unless the hero exclusion branch clears s1 or a candidate replaces it, this status persists through the output+0x44 store and return at 0x0026a614-0x0026a618. Thus zero denotes the retained hero-fallback selection status, not a HeroStateId. domain_1_value_2 -> XY_SELECTION_HERO_FALLBACK_DISABLED: Retail 0x0026a41c-0x0026a430 tests hero control_mode 0x18 or current 0x72; 0x0026a438 clears the initial hero.moby selection and 0x0026a43c sets s5 to 2. Candidate acceptance overwrites this status with 1; otherwise the null selection zeroes output records at 0x0026a5fc-0x0026a614. Two records that hero fallback was disabled. domain_5_value_1 -> XY_SELECTION_CANDIDATE_SELECTED: In the first scan, the strict XY distance comparison at 0x0026a4c8-0x0026a4d0 accepts a candidate; 0x0026a4d8 assigns candidate s0 to selected s1, 0x0026a4dc updates the distance bound, and 0x0026a4e0 assigns status s5=1. The same status is written at output+0x44 and returned. domain_8_value_1 -> XY_SELECTION_CANDIDATE_SELECTED: In the second scan, 0x0026a54c-0x0026a554 accepts a lower XY distance; 0x0026a55c assigns candidate s0 to selected s1, 0x0026a560 updates the distance bound, and 0x0026a564 assigns status s5=1. This is the same selection_status domain and accepted-candidate meaning as the first scan. --- .../select_nearest_xy_moby_with_hero_fallback.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/mobys/select_nearest_xy_moby_with_hero_fallback.c b/src/overlays/shared/mobys/select_nearest_xy_moby_with_hero_fallback.c index 6b2fc1f26f..b6f88574dd 100644 --- a/src/overlays/shared/mobys/select_nearest_xy_moby_with_hero_fallback.c +++ b/src/overlays/shared/mobys/select_nearest_xy_moby_with_hero_fallback.c @@ -21,6 +21,11 @@ int select_nearest_xy_moby_with_hero_fallback(char *comparison_reference, char *selection_output, float best) { + enum { + XY_SELECTION_HERO_FALLBACK = 0, + XY_SELECTION_CANDIDATE_SELECTED = 1, + XY_SELECTION_HERO_FALLBACK_DISABLED = 2 + }; struct Hero *hero = &hero_lui; char *selected_moby; char *candidate_moby; @@ -30,10 +35,10 @@ int select_nearest_xy_moby_with_hero_fallback(char *comparison_reference, float candidate_metric; selected_moby = ((char *)hero->moby); - selection_status = 0; + selection_status = XY_SELECTION_HERO_FALLBACK; if (hero->state.control_mode == 0x18 || hero->state.current == 0x72) { selected_moby = 0; - selection_status = 2; + selection_status = XY_SELECTION_HERO_FALLBACK_DISABLED; } for (i = 1; i <= D_L08_001B1030[0]; i++) { candidate_moby = D_L08_0015FFD8 + (D_L08_001B1030[i] << 8); @@ -52,7 +57,7 @@ int select_nearest_xy_moby_with_hero_fallback(char *comparison_reference, if (candidate_metric < best) { selected_moby = candidate_moby; best = candidate_metric; - selection_status = 1; + selection_status = XY_SELECTION_CANDIDATE_SELECTED; } } for (j = 0; j < 20; j++) { @@ -72,7 +77,7 @@ int select_nearest_xy_moby_with_hero_fallback(char *comparison_reference, if (candidate_metric < best) { selected_moby = candidate_moby; best = candidate_metric; - selection_status = 1; + selection_status = XY_SELECTION_CANDIDATE_SELECTED; } } if (selected_moby != 0) { From ff7a657079bb37b410fc8e59d7d855428ba70f4e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:50:53 +0000 Subject: [PATCH 0701/1502] decomp: clarify names in update_phase_effect_controller domain_0_value_1 -> FLOCK_EFFECT_STATE_PROCESS_PHASE_EFFECTS: In src/overlays/l00/mobys/cutscene_effects.c (SHA-256 7567ff6e027c4c19225a460c61b2b67c82662e0eda79cffb00332982053344a8), the existing enum labels value 1 as FLOCK_EFFECT_STATE_PROCESS_PHASE_EFFECTS in switch(moby->state). Retail 0x002e3824 loads this same byte at a0+0x20; 0x002e3830 dispatches value 1 to phase processing at 0x002e3854. Initialization at 0x002e3844-0x002e3848 stores 1 into that exact byte. Thus the assignment enters the already named processing state in the same selector domain. --- src/overlays/l00/mobys/cutscene_effects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l00/mobys/cutscene_effects.c b/src/overlays/l00/mobys/cutscene_effects.c index 8f00d8fd30..75ac6e6b5f 100644 --- a/src/overlays/l00/mobys/cutscene_effects.c +++ b/src/overlays/l00/mobys/cutscene_effects.c @@ -70,7 +70,7 @@ void phase_effect_controller_update(FlockMoby *moby) { switch (moby->state) { case FLOCK_EFFECT_STATE_INITIALIZE: moby->unk30 = 0xFF; - moby->state = 1; + moby->state = FLOCK_EFFECT_STATE_PROCESS_PHASE_EFFECTS; break; case FLOCK_EFFECT_STATE_PROCESS_PHASE_EFFECTS: if ((D_L00_0015F5C4 == 2 && D_L00_0016C860.phase == 2 && From 5a3a39b8e246aa3d931c568cfdf94fe94638abc1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:50:53 +0000 Subject: [PATCH 0702/1502] decomp: clarify names in rig_probe_setup domain_0_value_2 -> RIG_PROBE_SINGLE_JOINT: The selector is the probe record byte loaded at 0x00263a90 and written through type at 0x00263a94, not moby state. Value 2 is tested at 0x00263b28; 0x00263b48-0x00263b5c loads one joint position from JOINT_POSITIONS using the signed word at probe_entry+4, then scales, rotates and translates it, with distance zero at 0x00263ba4. The unsigned <2 comparison at 0x00263aa8 uses this same type byte as the boundary for types 0/1. domain_1_value_3 -> RIG_PROBE_LOCAL_POSITION_WITH_DISTANCE: The record-byte type (lbu 0x00263a90) is compared with 3 at 0x00263ab4-0x00263ab8. This branch copies probe_entry+0x10, scales it, rotates by moby+0x40 and adds moby+0x10 (0x00263ac0-0x00263af8). Unlike types below 2, it loads the stored float at probe_entry+4 and multiplies it by scale into the distance output (0x00263b10-0x00263b24, 0x00263c7c). domain_2_value_2 -> RIG_PROBE_SINGLE_JOINT: The selector is the probe record byte loaded at 0x00263a90 and written through type at 0x00263a94, not moby state. Value 2 is tested at 0x00263b28; 0x00263b48-0x00263b5c loads one joint position from JOINT_POSITIONS using the signed word at probe_entry+4, then scales, rotates and translates it, with distance zero at 0x00263ba4. The unsigned <2 comparison at 0x00263b0c uses this same probe type boundary to distinguish zero distance for types 0/1 from the stored distance for type 3. domain_3_value_2 -> RIG_PROBE_SINGLE_JOINT: The selector is the probe record byte loaded at 0x00263a90 and written through type at 0x00263a94, not moby state. Value 2 is tested at 0x00263b28; 0x00263b48-0x00263b5c loads one joint position from JOINT_POSITIONS using the signed word at probe_entry+4, then scales, rotates and translates it, with distance zero at 0x00263ba4. domain_4_value_4 -> RIG_PROBE_JOINT_PAIR: The same record-byte selector is compared with 4 at 0x00263ba8. At 0x00263bc8-0x00263c04 signed halfword indices from probe_entry+4/+6 select two JOINT_POSITIONS vectors, each scaled into first_joint_position/second_joint_position. The lower third component selects the output position (0x00263c08-0x00263c34), and subtraction plus length computes their separation for distance (0x00263c5c-0x00263c7c). --- src/overlays/shared/mobys/rig_probe_setup.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/mobys/rig_probe_setup.c b/src/overlays/shared/mobys/rig_probe_setup.c index 854f23b319..f868bc1334 100644 --- a/src/overlays/shared/mobys/rig_probe_setup.c +++ b/src/overlays/shared/mobys/rig_probe_setup.c @@ -28,6 +28,11 @@ int rig_probe_setup( float *radius, float *distance) { + enum { + RIG_PROBE_SINGLE_JOINT = 2, + RIG_PROBE_LOCAL_POSITION_WITH_DISTANCE = 3, + RIG_PROBE_JOINT_PAIR = 4 + }; char *probe_entry; float scale; u128 matrix[4]; @@ -44,19 +49,19 @@ int rig_probe_setup( scale = MOBY(moby)->scale * 0.0009765625f; euler_rotation_matrix(matrix, moby + 0x40); - if (*type < 2 || *type == 3) { + if (*type < RIG_PROBE_SINGLE_JOINT || *type == RIG_PROBE_LOCAL_POSITION_WITH_DISTANCE) { qcopy(probe_position, probe_entry + 0x10); fast_vec_scale(probe_position, probe_position, scale); transform_vector(probe_position, probe_position, matrix); fast_vec_add(probe_position, probe_position, &MOBY(moby)->pos); *radius = probe_position[3] * scale; - if (*type < 2) { + if (*type < RIG_PROBE_SINGLE_JOINT) { *distance = 0.0f; } else { *distance = *(float *)(probe_entry + 4) * scale; } return 1; - } else if (*type == 2) { + } else if (*type == RIG_PROBE_SINGLE_JOINT) { short joint = *(short *)(*(char **)(moby + 0x94) + 2); if (joint != 0) { compute_moby_joint_matrices(moby, joint, 0); @@ -68,7 +73,7 @@ int rig_probe_setup( *radius = *(float *)(probe_entry + 0xc) * scale; *distance = 0.0f; return 1; - } else if (*type == 4) { + } else if (*type == RIG_PROBE_JOINT_PAIR) { short joint = *(short *)(*(char **)(moby + 0x94) + 2); if (joint != 0) { compute_moby_joint_matrices(moby, joint, 0); From f13bbfcdf3cbe5051c6dae8070a32c1132ae23a2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:52:30 +0000 Subject: [PATCH 0703/1502] decomp: clarify names in rocket_door1_update domain_1_value_3 -> ROCKET_DOOR1_GOAL_ROTATION_APPLIED: The selector is moby->state, the byte at s3+0x20 loaded at retail 0x002df9ac. In the mission-table 0xFF branch, 0x002dfa24-0x002dfa60 converts door_vars->goal components at s4+0x10/+0x14/+0x18 from degrees to radians and stores all three into moby->rot at s3+0x40/+0x44/+0x48. 0x002dfa28 loads 3 and 0x002dfa54 stores it to that same state byte; the delay slot at 0x002dfa60 completes the final rotation component. Thus this state records directly applied goal rotation; original Ghidra shows the identical writes. Dispatch handles only states 0, 1 and 2. domain_2_value_1 -> ROCKET_DOOR1_WAIT_FOR_COMMAND: The authoritative source already defines ROCKET_DOOR1_WAIT_FOR_COMMAND=1 in the switch on moby->state. Retail 0x002dfa68 stores a2 (loaded with 1 at 0x002df9b0) to the identical s3+0x20 state byte. Dispatch at 0x002df9b4 sends state 1 to 0x002dfb40, where the command byte at s3+0xBC must become nonzero before transition. Source and original Ghidra confirm that this assignment enters the existing wait-for-command case. domain_3_value_2 -> ROCKET_DOOR1_TURN_TO_GOAL_ROTATION: The authoritative source already defines ROCKET_DOOR1_TURN_TO_GOAL_ROTATION=2 for the same moby->state switch. Retail 0x002dfb40-0x002dfb58 checks nonzero command, stores 2 at s3+0x20 and clears interpolation progress/speed at s4+0x24/+0x20. Dispatch 0x002df9d4 routes that same state value to 0x002dfb5c-0x002dfbac, which advances progress toward 1, interpolates start/goal quaternions, and writes the moby's rotation basis. Original Ghidra follows the same state byte and data flow. --- src/overlays/l02/mobys/rocket_door1.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/l02/mobys/rocket_door1.c b/src/overlays/l02/mobys/rocket_door1.c index 6ce29e4f66..ec218fbeed 100644 --- a/src/overlays/l02/mobys/rocket_door1.c +++ b/src/overlays/l02/mobys/rocket_door1.c @@ -37,6 +37,9 @@ void rocket_door1_update(struct Moby *moby) { ROCKET_DOOR1_WAIT_FOR_COMMAND = 1, ROCKET_DOOR1_TURN_TO_GOAL_ROTATION = 2 }; + enum { + ROCKET_DOOR1_GOAL_ROTATION_APPLIED = 3 + }; Vec4 qx; Vec4 qy; Vec4 qz; @@ -59,9 +62,9 @@ void rocket_door1_update(struct Moby *moby) { moby->rot.x = door_vars->goal.f[0] * 0.017453292f; moby->rot.y = door_vars->goal.f[1] * 0.017453292f; moby->rot.z = door_vars->goal.f[2] * 0.017453292f; - moby->state = 3; + moby->state = ROCKET_DOOR1_GOAL_ROTATION_APPLIED; } else { - moby->state = 1; + moby->state = ROCKET_DOOR1_WAIT_FOR_COMMAND; moby->flags |= 0x100; build_axis_rotation_quaternion(&qx, 0, door_vars->goal.f[0] * 0.017453292f); build_axis_rotation_quaternion(&qy, 1, door_vars->goal.f[1] * 0.017453292f); @@ -77,7 +80,7 @@ void rocket_door1_update(struct Moby *moby) { break; case ROCKET_DOOR1_WAIT_FOR_COMMAND: if (moby->command != 0) { - moby->state = 2; + moby->state = ROCKET_DOOR1_TURN_TO_GOAL_ROTATION; door_vars->speed = 0.0f; door_vars->t = 0.0f; } From 64bf80fd8540d9e8e01bfbdcd44034b7031b11da Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:54:04 +0000 Subject: [PATCH 0704/1502] decomp: clarify names in update_hero_ground_material_flags domain_0_value_2 -> GROUND_MATERIAL_MAGNET: state is saved from hero.ground_type (+0x12e0) by lh s3 at 0x0022de60. Comparing s3 to 2 at 0x0022de80-0x0022de84 leads to the off-ground/distance checks and sb 1 at hero+0x12e7 (on_magnet_ground) at 0x0022dec4; the later same-material branch sets the same flag unconditionally. This is a ground-material selector, not HERO_STATE_RUN. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0022debc loads hero+0x20a4, the source's vehicle_mode, and 0x0022dec0 branches away when nonzero before checking the item moby. Thus this comparison belongs exactly to HeroVehicleMode, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT; the same source's smoothing and motion functions already use that member for hero.vehicle_mode. domain_3_value_0 -> GROUND_MATERIAL_WATER: The saved ground_type in s3 is compared with zero at 0x0022df1c; 0x0022df34-0x0022df6c computes water_surface_z-ground_z, stores water_depth and sets wading for depth between 0.25 and 0.85. The embedded ground-contact function obtains ground_type from collision_hit_material(), and its ground_type==0 branch resolves water_surface_z and tracks in_water_frames. This proves the water material domain rather than HERO_STATE_IDLE. domain_4_value_2 -> GROUND_MATERIAL_MAGNET: Retail 0x0022df80 compares the same saved ground_type s3 to 2, then 0x0022df90 stores 1 at hero+0x12e7, source field on_magnet_ground. This is the same material and same flag as 0x0022de80-0x0022dec4, so both occurrences reuse GROUND_MATERIAL_MAGNET. domain_5_value_7 -> GROUND_MATERIAL_ICE: Retail 0x0022df98 compares saved ground_type s3 with 7 and 0x0022dfa8 stores 1 at hero+0x12e2, source field on_ice_ground. Embedded motion code consumes that flag to select sliding/low-friction movement. The loaded selector is ground_type at +0x12e0, not hero.state.current, so HERO_STATE_JUMP is inapplicable. domain_6_value_13 -> GROUND_MATERIAL_SINK_TRIGGER: Retail 0x0022dfb0 compares saved ground_type s3 with 0xd and 0x0022dfc0 sets hero+0x12ec (selector_13). That same byte gates 0x0022e010-0x0022e0a4: near-surface, below-surface and downward-displacement checks call exit_hero_vehicle_mode_if_mode_three and hero_set_state(HERO_STATE_SINK,1). The name states the proven sink-trigger role without identifying an unknown physical substance. --- .../update_hero_motion_for_current_state.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/overlays/l12/hero/update_hero_motion_for_current_state.c b/src/overlays/l12/hero/update_hero_motion_for_current_state.c index 77919b88c6..1db26d33e2 100644 --- a/src/overlays/l12/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l12/hero/update_hero_motion_for_current_state.c @@ -31,6 +31,12 @@ float absolute_float(float input) __asm__("func_001F99C0"); void update_hero_ground_material_flags(void) __asm__("FUN_L12_0022de30"); void update_hero_ground_material_flags(void) { + enum { + GROUND_MATERIAL_WATER = 0, + GROUND_MATERIAL_MAGNET = 2, + GROUND_MATERIAL_ICE = 7, + GROUND_MATERIAL_SINK_TRIGGER = 0xD + }; struct Hero *hero_for_ground_flags_update = &hero; unsigned char saved; int state; @@ -43,11 +49,11 @@ void update_hero_ground_material_flags(void) { hero_for_ground_flags_update->unk308 = 0; if (state == -1) return; - if (state == 2) { + if (state == GROUND_MATERIAL_MAGNET) { if (hero_for_ground_flags_update->frames_off_ground.s == 0 || hero_for_ground_flags_update->ground_distance < 0.3f) { hero_for_ground_flags_update->on_magnet_ground = 1; - if (hero_for_ground_flags_update->vehicle_mode == 0) { + if (hero_for_ground_flags_update->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if ((s32)hero_for_ground_flags_update->items[1].moby != 0 && *(short *)((s32)hero_for_ground_flags_update->items[1].moby + 0xA6) == 0xAD) hero_for_ground_flags_update->unk308 = 1; @@ -60,7 +66,7 @@ void update_hero_ground_material_flags(void) { hero_for_surface_update->water_depth = 0.2f; hero_for_surface_update->water_surface_z = hero_for_surface_update->ground_z.f + 0.2f; } - if (state == 0) { + if (state == GROUND_MATERIAL_WATER) { struct Hero *hero_for_water_height_check = &hero; struct Hero *hero_for_base_condition_update; float water_surface_ground_z_delta = @@ -71,15 +77,15 @@ void update_hero_ground_material_flags(void) { hero_for_base_condition_update = &hero; hero_for_base_condition_update->base_condition = 1; } - if (state == 2) { + if (state == GROUND_MATERIAL_MAGNET) { struct Hero *d = &hero; d->on_magnet_ground = 1; } - if (state == 7) { + if (state == GROUND_MATERIAL_ICE) { struct Hero *d = &hero; d->on_ice_ground = 1; } - if (state == 0xD) { + if (state == GROUND_MATERIAL_SINK_TRIGGER) { struct Hero *d = &hero; d->selector_13 = 1; } From cbff577993d2479119d6e95415da39afb0f51b9c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:54:04 +0000 Subject: [PATCH 0705/1502] decomp: clarify names in draw_menu_flashing_panel domain_0_value_0 -> FALSE: Source pal_mode != 0 selects the vertical clipping bound. Retail 0x00223e84 loads the flag; 0x00223e88 branches on nonzero, retaining y < 0x1c1 from 0x00223e8c, while zero falls through to y < 0x1a1 at 0x00223e90. Original Ghidra likewise tests iGpffff8180 == 0. Thus this zero denotes the false PAL-enable flag, fitting existing boolean FALSE=0 rather than pointer NULL or a state ID. --- src/ui/menus/widgets/draw_menu_flashing_panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/menus/widgets/draw_menu_flashing_panel.c b/src/ui/menus/widgets/draw_menu_flashing_panel.c index 10af1041eb..ff83c9597b 100644 --- a/src/ui/menus/widgets/draw_menu_flashing_panel.c +++ b/src/ui/menus/widgets/draw_menu_flashing_panel.c @@ -53,7 +53,7 @@ void draw_menu_flashing_panel(struct MenuPanelOwner *panel_moby) { if (x >= 0x200 || x + width < 0) { return; } - if (!(pal_mode != 0 ? y < 0x1C1 : y < 0x1A1) || y + height < 0) { + if (!(pal_mode != FALSE ? y < 0x1C1 : y < 0x1A1) || y + height < 0) { return; } vu1_add_g_sregister(8, 0); From 3568a7c065fd44750fd58239dab91dfb43b381e5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:54:05 +0000 Subject: [PATCH 0706/1502] decomp: clarify names in resolve_hero_surface_reactions domain_0_value_2 -> HERO_GROUND_TYPE_MAGNET: The selector is saved_ground_type, loaded from hero+0x12e0 into s2 at retail 0x0021dd64 before the ground block is cleared. The comparison against 2 at 0x0021dd84-0x0021dd88 gates the grounded/distance checks and store of 1 to hero+0x12e7 at 0x0021ddc8, the source's established on_magnet_ground field. This is a ground-type domain, not HeroStateId. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021ddc0 loads hero+0x20a4 as a byte and 0x0021ddc4 branches when nonzero before the item-moby check. The bound source identifies this field as hero_data->vehicle_mode, proving the HeroVehicleMode selector domain; its zero member is the supplied canonical HERO_VEHICLE_MODE_ON_FOOT. Other supplied source consumers switch on this same hero.vehicle_mode field using that member. domain_3_value_2 -> HERO_GROUND_TYPE_MAGNET: Retail 0x0021de84 compares s2, the saved hero ground_type halfword from 0x0021dd64, against 2 and 0x0021de94 stores 1 to hero+0x12e7. The authoritative C names the destination on_magnet_ground. This repeats the earlier magnetic-ground comparison and must reuse the same ground-type member, independently of state IDs. domain_4_value_7 -> HERO_GROUND_TYPE_ICE: Retail 0x0021de98-0x0021deac compares saved ground_type in s2 against 7 and sets hero+0x12e2 to 1. The authoritative source identifies that destination as on_ice_ground, also consumed as the ice-surface condition by hero motion. The meaning follows this ground-type-to-ice-flag data flow, not the equal-valued HERO_STATE_JUMP. domain_5_value_13 -> HERO_GROUND_TYPE_SINKING_SURFACE: Retail 0x0021deb0-0x0021dec4 compares saved ground_type in s2 against 13 and sets hero+0x12ec (source selector_13). Retail 0x0021df10 tests that flag, then 0x0021df28-0x0021df84 checks water_surface_z proximity, position below that surface and descending displacement. At 0x0021df94-0x0021dfa4 it exits vehicle mode and requests established HERO_STATE_SINK (0x7f). This proves the sinking-surface reaction role without identifying the physical material. --- .../l14/hero/update_hero_motion_by_state.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/overlays/l14/hero/update_hero_motion_by_state.c b/src/overlays/l14/hero/update_hero_motion_by_state.c index e097c93716..cf7eb71ee4 100644 --- a/src/overlays/l14/hero/update_hero_motion_by_state.c +++ b/src/overlays/l14/hero/update_hero_motion_by_state.c @@ -35,6 +35,11 @@ float absolute_float(float input) __asm__("func_001F99C0"); void resolve_hero_surface_reactions(void) __asm__("FUN_L14_0021dd30"); void resolve_hero_surface_reactions(void) { + enum { + HERO_GROUND_TYPE_MAGNET = 2, + HERO_GROUND_TYPE_ICE = 7, + HERO_GROUND_TYPE_SINKING_SURFACE = 0xD + }; struct Hero *hero_ptr; struct Hero *hero_data = &hero; int keep = hero_data->ground_sound_class; @@ -46,10 +51,10 @@ void resolve_hero_surface_reactions(void) { hero_data->unk308 = 0; if (saved_ground_type == -1) return; - if (saved_ground_type == 2) { + if (saved_ground_type == HERO_GROUND_TYPE_MAGNET) { if (hero_data->frames_off_ground.s == 0 || hero_data->ground_distance < 0.3f) { hero_data->on_magnet_ground = 1; - if (hero_data->vehicle_mode == 0) { + if (hero_data->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { char *item_moby_bytes = ((char *)hero_data->items[1].moby); if (item_moby_bytes != 0 && *(short *)(item_moby_bytes + 0xA6) == 0xAD) { hero_data->unk308 = 1; @@ -72,15 +77,15 @@ void resolve_hero_surface_reactions(void) { struct Hero *q = &hero; q->selector_11 = 1; } - if (saved_ground_type == 2) { + if (saved_ground_type == HERO_GROUND_TYPE_MAGNET) { struct Hero *q = &hero; q->on_magnet_ground = 1; } - if (saved_ground_type == 7) { + if (saved_ground_type == HERO_GROUND_TYPE_ICE) { struct Hero *q = &hero; q->on_ice_ground = 1; } - if (saved_ground_type == 0xD) { + if (saved_ground_type == HERO_GROUND_TYPE_SINKING_SURFACE) { struct Hero *q = &hero; q->selector_13 = 1; } From e6d27548138ae3c3518478ce2003a7e1738890be Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:55:56 +0000 Subject: [PATCH 0707/1502] decomp: clarify names in process_gunship_part_hits domain_0_value_1 -> GUNSHIP_NON_TARGET_HIT_VOICE_ENTRY: The source and original Ghidra lVar8 map state to retail s3, passed as a0 to allocate_voice_for_target_entry at 0x002e24a4-0x002e24b4. Checked helper 0x00295ee0 preserves a0 as s1, bounds it against the target class entry count, and computes table+index*32 at 0x00295f20-0x00295f40; this is a voice-entry selector, not a moby or Hero state. Retail 0x002e22b8-0x002e22d4 assigns s3=1 for a detected hit in slots 0..6. Source spawn_gunship_parts reserves the three rows of target-class 0x1BB parts for slots 10..33; this branch is outside those target slots. domain_1_value_1 -> GUNSHIP_NON_TARGET_HIT_VOICE_ENTRY: The source and original Ghidra lVar8 map state to retail s3, passed as a0 to allocate_voice_for_target_entry at 0x002e24a4-0x002e24b4. Checked helper 0x00295ee0 preserves a0 as s1, bounds it against the target class entry count, and computes table+index*32 at 0x00295f20-0x00295f40; this is a voice-entry selector, not a moby or Hero state. Retail 0x002e22d8-0x002e22f0 assigns the same s3=1 for detected hits in slots 7..9. Source spawn_gunship_parts places the three target rows in slots 10..33; both non-target hit tiers therefore share the same voice-entry constant. domain_2_value_2 -> GUNSHIP_TARGET_HIT_VOICE_ENTRY: The source and original Ghidra lVar8 map state to retail s3, passed as a0 to allocate_voice_for_target_entry at 0x002e24a4-0x002e24b4. Checked helper 0x00295ee0 preserves a0 as s1, bounds it against the target class entry count, and computes table+index*32 at 0x00295f20-0x00295f40; this is a voice-entry selector, not a moby or Hero state. Retail 0x002e22f4-0x002e2308 adds four points, records the hit slot, and assigns s3=2 for slots 10..33. Source spawn_gunship_parts creates the three rows of eight target-class 0x1BB parts in precisely these slots, proving this entry selects their hit voice. domain_3_value_0 -> GUNSHIP_TARGETS_EXHAUSTED_VOICE_ENTRY: The source and original Ghidra lVar8 map state to retail s3, passed as a0 to allocate_voice_for_target_entry at 0x002e24a4-0x002e24b4. Checked helper 0x00295ee0 preserves a0 as s1, bounds it against the target class entry count, and computes table+index*32 at 0x00295f20-0x00295f40; this is a voice-entry selector, not a moby or Hero state. Retail 0x002e2338-0x002e2364 selects s3=0 upon reaching eight accumulated points. Both successful target-removal paths return at 0x002e2430-0x002e2434. This zero reaches the voice call only when all 24 target slots 10..33 are absent after the probe at 0x002e2478-0x002e2498, which sets parent breakup state 99 at 0x002e249c-0x002e24a0. --- src/overlays/l08/mobys/gunship.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/l08/mobys/gunship.c b/src/overlays/l08/mobys/gunship.c index 8c1a431af5..17fd7a8b58 100644 --- a/src/overlays/l08/mobys/gunship.c +++ b/src/overlays/l08/mobys/gunship.c @@ -242,6 +242,11 @@ void update_linked_moby_parts(struct Moby *moby) { } void process_gunship_part_hits(struct Moby *moby) { + enum { + GUNSHIP_TARGETS_EXHAUSTED_VOICE_ENTRY = 0, + GUNSHIP_NON_TARGET_HIT_VOICE_ENTRY = 1, + GUNSHIP_TARGET_HIT_VOICE_ENTRY = 2 + }; char *gunship_instance_vars = *(char **)((char *)moby + 0x78); char *entries = gunship_instance_vars + 0x60; char *part_entry_cursor = entries; @@ -256,18 +261,18 @@ void process_gunship_part_hits(struct Moby *moby) { if (i < 7) { if (score <= 0) { score = 1; - state = 1; + state = GUNSHIP_NON_TARGET_HIT_VOICE_ENTRY; } } else if (i < 10) { if (score < 2) { score = 2; - state = 1; + state = GUNSHIP_NON_TARGET_HIT_VOICE_ENTRY; } } else { if (score < 4) { score += 4; chosen = i; - state = 2; + state = GUNSHIP_TARGET_HIT_VOICE_ENTRY; } } (*(unsigned char **)part_entry_cursor)[0xA4] = 0xFF; @@ -275,7 +280,7 @@ void process_gunship_part_hits(struct Moby *moby) { } *(short *)(gunship_instance_vars + 0x28C) += score; if (*(short *)(gunship_instance_vars + 0x28C) >= 8) { - state = 0; + state = GUNSHIP_TARGETS_EXHAUSTED_VOICE_ENTRY; *(short *)(gunship_instance_vars + 0x28C) = *(short *)(gunship_instance_vars + 0x28C) % 8; if (chosen != 0) { int off = chosen * 16; From eed6f682e081644592aaed7ad5a522fda4f8037c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:55:56 +0000 Subject: [PATCH 0708/1502] decomp: clarify names in button_update domain_0_value_1 -> DOOR_STATE_CLOSING: The door pointer is the level moby selected by FloorPlateVars.door (retail s5 at 0x002d9324-0x002d9338), and its state byte is +0x20. This comparison is part of the 1-or-2 test at 0x002d9454-0x002d9460. The same value 1 is written at 0x002d94cc by the unpressed/unheld branch, which the authoritative source identifies as closing the door; pressing reverses that closing state to 3 at 0x002d9468. Reuse DOOR_STATE_CLOSING for the comparison and assignment. domain_2_value_3 -> DOOR_STATE_OPENING: The authoritative source describes button_update as opening its linked door while the plate is pressed or held. That branch tests the selected door state byte +0x20 for 1 or 2 at 0x002d9454-0x002d9460, then writes 3 at 0x002d9464-0x002d9468 and plays door voice entry 0 at 0x002d9478-0x002d9484. Original Ghidra likewise writes 3 to iVar5+0x20 on this branch. Thus 3 is the opening transition state of this door, not a hero state. domain_4_value_1 -> DOOR_STATE_CLOSING: When neither pressed nor linked-held, the original Ghidra and current source test door->state==4 and assign 1 before playing door voice entry 1. Retail 0x002d9420 branches to this path, 0x002d94c0-0x002d94c4 tests 4, and 0x002d94cc writes a1 (1 established at 0x002d93fc) to s5+0x20. The source's floor-plate description identifies this unpressed branch as closing the door, proving the closing transition role of state 1. --- src/overlays/l10/mobys/button.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l10/mobys/button.c b/src/overlays/l10/mobys/button.c index 31e5b7eec3..f5f5162acc 100644 --- a/src/overlays/l10/mobys/button.c +++ b/src/overlays/l10/mobys/button.c @@ -39,6 +39,10 @@ void button_update(struct Moby *m) __asm__("FUN_L10_002d92b8"); /* Moby class 1031 */ void button_update(struct Moby *moby) { + enum { + DOOR_STATE_CLOSING = 1, + DOOR_STATE_OPENING = 3 + }; FloorPlateVars *plate_vars = (FloorPlateVars *)moby->pvars; s32 pressed = 0; struct Moby *door; @@ -75,8 +79,8 @@ void button_update(struct Moby *moby) { } else { plate_vars->held = 0; } - if (door->state == 1 || door->state == 2) { - door->state = 3; + if (door->state == DOOR_STATE_CLOSING || door->state == 2) { + door->state = DOOR_STATE_OPENING; if (plate_vars->sound_timer == 0) { allocate_voice_for_target_entry(0, 0, door); allocate_voice_for_target_entry(0, 0, moby); @@ -86,7 +90,7 @@ void button_update(struct Moby *moby) { FUN_L00_002502f0_u(moby, 0x7F, 0x7F, 0x7F); } else { if (door->state == 4) { - door->state = 1; + door->state = DOOR_STATE_CLOSING; if (plate_vars->sound_timer == 0) { allocate_voice_for_target_entry(1, 0, door); allocate_voice_for_target_entry(0, 0, moby); From d4edb8cdfcf26c115c5c001fc40314427cf7c1fe Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:55:56 +0000 Subject: [PATCH 0709/1502] decomp: clarify names in advance_moby_along_selected_path domain_0_value_5 -> STARFIGHTER_STATE_TRACTOR_BEAM: Retail 0x002e9190 preserves the first moby argument in s4; 0x002e9364-0x002e936c loads its current-state byte at +0x20 and compares it to 5. The taken state-5 branch at 0x002e9374-0x002e93bc replaces path yaw/pitch with angles from moby position to hero coordinates, then 0x002e93cc calls spring steering. In authoritative source SHA-256 46a3eeef2fb5f560fab9d67fd28d26cb253c966fae51feb1b484f447bbf7a10f, update_qwarks_starfighter declares STARFIGHTER_STATE_TRACTOR_BEAM = 5 and passes its unchanged moby to advance_moby_along_selected_path within that named state branch while handling beam tracking, capture and draw_starfighter_tractor_beam. Thus the selector is that same starfighter current-state domain, not command +0xBC or another entity's state; reuse the established member name. --- src/overlays/l13/mobys/qwarks_starfighter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/qwarks_starfighter.c b/src/overlays/l13/mobys/qwarks_starfighter.c index 1bbbb33ab6..4f44e3a987 100644 --- a/src/overlays/l13/mobys/qwarks_starfighter.c +++ b/src/overlays/l13/mobys/qwarks_starfighter.c @@ -364,6 +364,9 @@ int advance_moby_along_selected_path(struct Moby *moby, int path_slot_index, int aim) { + enum { + STARFIGHTER_STATE_TRACTOR_BEAM = 5 + }; char *path = D_L13_001B07B0[*(int *)(&moby_data[path_slot_index << 2] + 0xB0)]; float distance_from_previous_node, seg, segment_distance_shortfall, steering_blend_factor, yaw, pitch; @@ -407,7 +410,7 @@ int advance_moby_along_selected_path(struct Moby *moby, yaw = fast_arc_tan(target_node_steering_vector[0], target_node_steering_vector[1]); pitch = -fast_arc_tan(vector_length_xy(target_node_steering_vector), target_node_steering_vector[2]); - if (moby->state == 5) { + if (moby->state == STARFIGHTER_STATE_TRACTOR_BEAM) { struct Hero *hero_state = &hero; yaw = fast_arc_tan(hero_state->motion.pos.f[0] - moby->pos.x, hero_state->motion.pos.f[1] - moby->pos.y); From 2aca06a847e4413f6acd1c53c36d5d7fbfb459a1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:55:56 +0000 Subject: [PATCH 0710/1502] decomp: clarify names in hero_handle_jump_press domain_0_value_11 -> HERO_STATE_HIGH_JUMP: Retail-selected a0 reaches jal 0x002223f8 at 002296e4 (a1=1); original Ghidra calls FUN_002223f8(uVar3,1). The supplied hero_set_state source binds that callee and assigns requested_state directly to hero.state.current, proving next_state is in shared HeroStateId, not a control or vehicle mode. 002296e0 loads a0=0xb after the held-mask and check_pad_press_separation success path, using get_hero_high_jump_input_window_frames. HeroStateId in include/rnc/hero/hero_state.h canonically assigns HIGH_JUMP=11. domain_1_value_10 -> HERO_STATE_PACK_JUMP: Retail-selected a0 reaches jal 0x002223f8 at 002296e4 (a1=1); original Ghidra calls FUN_002223f8(uVar3,1). The supplied hero_set_state source binds that callee and assigns requested_state directly to hero.state.current, proving next_state is in shared HeroStateId, not a control or vehicle mode. 002297e0 branches to the shared call with a0=0xa in delay slot 002297e4 after slot 3 item ID 2, enabled pack, wall clearance/pitch, stick magnitude and forward-speed tests. HeroStateId canonically assigns PACK_JUMP=10. domain_2_value_16 -> HERO_STATE_PACK_LONG_JUMP: Retail-selected a0 reaches jal 0x002223f8 at 002296e4 (a1=1); original Ghidra calls FUN_002223f8(uVar3,1). The supplied hero_set_state source binds that callee and assigns requested_state directly to hero.state.current, proving next_state is in shared HeroStateId, not a control or vehicle mode. 00229888 branches to the shared call with a0=0x10 in delay slot 0022988c after slot 3 item ID 3, enabled pack, movement/clearance tests and zero long_jump_lockout at hero+0x1b8. HeroStateId canonically assigns PACK_LONG_JUMP=16. domain_3_value_13 -> HERO_STATE_JUMP_WITH_TRANSFORM_TRAIL: Retail-selected a0 reaches jal 0x002223f8 at 002296e4 (a1=1); original Ghidra calls FUN_002223f8(uVar3,1). The supplied hero_set_state source binds that callee and assigns requested_state directly to hero.state.current, proving next_state is in shared HeroStateId, not a control or vehicle mode. 002298a8 branches to the shared call with a0=0xd in delay slot 002298ac when slot 3 returns item ID 3 and hero.pack_disabled at +0x22d8 is zero, following the long-jump attempt. HeroStateId canonically assigns JUMP_WITH_TRANSFORM_TRAIL=13. domain_4_value_15 -> HERO_STATE_JUMP_WITH_VELOCITY_KEY_PROFILE: Retail-selected a0 reaches jal 0x002223f8 at 002296e4 (a1=1); original Ghidra calls FUN_002223f8(uVar3,1). The supplied hero_set_state source binds that callee and assigns requested_state directly to hero.state.current, proving next_state is in shared HeroStateId, not a control or vehicle mode. 002298d8 branches to the shared call with a0=0xf in delay slot 002298dc when slot 3 returns item ID 2, pack_disabled is zero and byte 0013d4c2 is nonzero. HeroStateId canonically assigns JUMP_WITH_VELOCITY_KEY_PROFILE=15. --- src/overlays/shared/hero/hero_handle_jump_press.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/hero/hero_handle_jump_press.c b/src/overlays/shared/hero/hero_handle_jump_press.c index cea5e1470e..68c809210e 100644 --- a/src/overlays/shared/hero/hero_handle_jump_press.c +++ b/src/overlays/shared/hero/hero_handle_jump_press.c @@ -195,7 +195,7 @@ int hero_handle_jump_press(void) { (void *)0x1F000, input_history_window_padding + input_history_separation_limit, input_history_separation_limit)) { - next_state = 0xB; + next_state = HERO_STATE_HIGH_JUMP; found: hero_set_state(next_state, 1); return 1; @@ -207,7 +207,7 @@ int hero_handle_jump_press(void) { if (hero_slot_item_id(3) == 2 && D_0013D4C2_lui != 0 && hero.pack_disabled == 0) { if ((2.5f < hero.wall_probe_distance || hero.wall_normal_pitch < 0.7853982f) && 0.7f < hero.stick_magnitude && frame_time * 0.9f < hero.motion.forward_speed) { - next_state = 0xA; + next_state = HERO_STATE_PACK_JUMP; goto found; } } @@ -216,15 +216,15 @@ int hero_handle_jump_press(void) { frame_time * 0.9f < hero.motion.forward_speed) { if (hero.long_jump_lockout) return 1; - next_state = 0x10; + next_state = HERO_STATE_PACK_LONG_JUMP; goto found; } if (hero_slot_item_id(3) == 3 && hero.pack_disabled == 0) { - next_state = 0xD; + next_state = HERO_STATE_JUMP_WITH_TRANSFORM_TRAIL; goto found; } if (hero_slot_item_id(3) == 2 && hero.pack_disabled == 0 && D_0013D4C2_lui) { - next_state = 0xF; + next_state = HERO_STATE_JUMP_WITH_VELOCITY_KEY_PROFILE; goto found; } hero_set_state_2(7, 1); From 150ef613d8273f65ac3f0458d0046bae76f67143 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:55:56 +0000 Subject: [PATCH 0711/1502] decomp: clarify names in update_path_lightning_controller domain_0_value_0 -> PATH_LIGHTNING_STATE_INITIALIZE: Retail 0x002ed2b0-0x002ed2b4 tests the controller moby's byte at +0x20 for zero. Its branch initializes update distance at 0x002ed2e8, clears the arc initialization flag and interval at 0x002ed2ec-0x002ed2f0, and advances that same state byte to 1. Authoritative C and original Ghidra agree that this is the controller initialization state. domain_1_value_1 -> PATH_LIGHTNING_STATE_WAIT_SCENE_START: Retail 0x002ed2dc-0x002ed2e4 assigns 1 to this controller's +0x20 state byte after initialization. Reload at 0x002ed2f4 and dispatch at 0x002ed2fc enter a branch that waits for two guards to clear before calling start_scene(0) at 0x002ed328, then advances to 2. This is the same moby-state domain, not a hero state or the separate scene-control global. domain_2_value_1 -> PATH_LIGHTNING_STATE_WAIT_SCENE_START: Authoritative moby_state is loaded directly from MOBY(moby)->state, matching retail lbu s0,0x20(s6) at 0x002ed2f4. The comparison with 1 at 0x002ed2f8-0x002ed2fc selects the guard-controlled start_scene(0) call at 0x002ed328; failed guards return without advancing. Reuse the same constant as the state-1 assignment. domain_3_value_2 -> PATH_LIGHTNING_STATE_WAIT_TRACKED_MOBY_RESTORE: After start_scene(0), retail 0x002ed334-0x002ed33c stores 2 into the controller's +0x20 state byte while calling deactivate_recorded_moby. On subsequent updates the state-2 branch at 0x002ed348-0x002ed35c waits while the separate gate equals 2, then changes state and calls show_tracked_moby. Thus this controller state waits to restore the tracked moby; it does not name the separate gate's domain. domain_4_value_2 -> PATH_LIGHTNING_STATE_WAIT_TRACKED_MOBY_RESTORE: Retail 0x002ed348 compares s0, loaded from controller +0x20 at 0x002ed2f4, with 2. The branch returns while the independent gate equals s0 at 0x002ed350; otherwise 0x002ed358-0x002ed35c advances the state and calls show_tracked_moby. Authoritative C has the same waiting/restore flow. Reuse the state-2 assignment's constant without renaming the control-global comparison. domain_5_value_3 -> PATH_LIGHTNING_STATE_ACTIVE: Retail 0x002ed354-0x002ed35c writes 3 to controller +0x20 when the restore gate releases and show_tracked_moby runs. On later updates this value bypasses the state-1 and state-2 branches (0x002ed2fc, 0x002ed348) and reaches the periodic timer at 0x002ed368, endpoint selection and update_branched_lightning_arc at 0x002ed4d4. This names the active lightning-update phase of the controller. --- src/overlays/l14/mobys/path_lightning_controller.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l14/mobys/path_lightning_controller.c b/src/overlays/l14/mobys/path_lightning_controller.c index 2a4dd0db09..b12dde9ba2 100644 --- a/src/overlays/l14/mobys/path_lightning_controller.c +++ b/src/overlays/l14/mobys/path_lightning_controller.c @@ -56,20 +56,20 @@ void path_lightning_controller_update(struct Moby *moby) __asm__("FUN_L14_002ed2 /* Moby class 684 */ void path_lightning_controller_update(struct Moby *moby) { - char *moby_vars = (char *)moby->pvars; + enum { PATH_LIGHTNING_STATE_INITIALIZE = 0 , PATH_LIGHTNING_STATE_WAIT_SCENE_START = 1 , PATH_LIGHTNING_STATE_WAIT_TRACKED_MOBY_RESTORE = 2 , PATH_LIGHTNING_STATE_ACTIVE = 3 } ;char *moby_vars = (char *)moby->pvars; int visible_path_point_indices[5]; float visibility_test_point[4]; int moby_state; - if (MOBY(moby)->state == 0) { + if (MOBY(moby)->state == PATH_LIGHTNING_STATE_INITIALIZE) { if (current_level_index == 0xE) hero.pack_disabled = 1; - MOBY(moby)->state = 1; + MOBY(moby)->state = PATH_LIGHTNING_STATE_WAIT_SCENE_START; moby->update_dist = 0xFF; *(int *)&lightning_arc_initialized_gp = 0; *(int *)&lightning_arc_interval_remaining_frames_gp = 0; } moby_state = MOBY(moby)->state; - if (moby_state == 1) { + if (moby_state == PATH_LIGHTNING_STATE_WAIT_SCENE_START) { unsigned char *scene_start_guard_base; if (D_L14_0015F5C4 != 0) return; @@ -78,14 +78,14 @@ void path_lightning_controller_update(struct Moby *moby) { return; start_scene(0); scene_start_guard_base[0x68] = moby_state; - MOBY(moby)->state = 2; + MOBY(moby)->state = PATH_LIGHTNING_STATE_WAIT_TRACKED_MOBY_RESTORE; deactivate_recorded_moby(); return; } - if (moby_state == 2) { + if (moby_state == PATH_LIGHTNING_STATE_WAIT_TRACKED_MOBY_RESTORE) { if (D_L14_0015F5C4 == moby_state) return; - MOBY(moby)->state = 3; + MOBY(moby)->state = PATH_LIGHTNING_STATE_ACTIVE; show_tracked_moby(); return; } From fad1a056ec36cca2470f9c1cf3ec588bb5aba6dc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:55:57 +0000 Subject: [PATCH 0712/1502] decomp: clarify names in swingshot_hook_update domain_0_value_254 -> MOBY_STATE_MARKED_FOR_REMOVAL: The authoritative swingshot_hook_update source identifies this selector as owner_moby->state. Retail 002c7094 loads the owner from hook vars word zero; 002c70a0 validates class D0; 002c70ac loads owner +0x20 and 002c70b0 branches on FE to 002c71ec, the established mark_moby_for_removal call. Checked level-00 helper 0024eb68 (report 6ce5085f4f84c50f8b6e6bf804c9042321f41cec08d1ac8c75166910879efe23) loads FE at 0024eb8c and writes it directly to its Moby argument +0x20 at 0024eb90. This proves FE is a Moby state marking removal, not a hook animation or control-mode number. FD is another removal variant whose distinction remains unproved. --- src/overlays/shared/weapons/swingshot_hook.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/swingshot_hook.c b/src/overlays/shared/weapons/swingshot_hook.c index a40a89ba79..1870ffb68f 100644 --- a/src/overlays/shared/weapons/swingshot_hook.c +++ b/src/overlays/shared/weapons/swingshot_hook.c @@ -55,6 +55,9 @@ void swingshot_hook_update(unsigned char *hook_moby) { HOOK_SKIP_ANIMATION_TRANSITIONS = 6, HOOK_RETURN_ANIMATION = 7 }; + enum { + MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE + }; unsigned char **hook_vars; struct Moby *owner_moby; if (hook_moby == 0) @@ -63,7 +66,7 @@ void swingshot_hook_update(unsigned char *hook_moby) { if (hook_vars == 0) return; owner_moby = hook_vars[0]; - if (owner_moby == 0 || owner_moby->oclass != 0xD0 || owner_moby->state == 0xFE || + if (owner_moby == 0 || owner_moby->oclass != 0xD0 || owner_moby->state == MOBY_STATE_MARKED_FOR_REMOVAL || owner_moby->state == 0xFD || *(unsigned char **)(((unsigned char *)owner_moby->pvars) + 0x14) != hook_moby) { goto kill; From 29e3d935642cf51d249664822f3909cb7a3ae200 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:57:45 +0000 Subject: [PATCH 0713/1502] decomp: clarify names in water_lily_update domain_0_value_1 -> WATER_LILY_STATE_UPDATE_POSITION: Retail 0x002f829c loads the lily state byte at s2+0x20; 0x002f82a8-0x002f82ac compares that byte with 1 and branches to position updates at 0x002f82c8. Initialization copies position to pvars at 0x002f82a4, then 0x002f82bc-0x002f82c4 writes 1 to the identical state byte. The authoritative C already declares WATER_LILY_STATE_UPDATE_POSITION = 1 and uses it as the case for this same water_lily->state selector, whose branch springs XY, resolves collision, caps movement and adjusts surface height. Thus the assignment must reuse that existing member. --- src/overlays/l01/mobys/water_lily.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/water_lily.c b/src/overlays/l01/mobys/water_lily.c index 2ac7dbdf36..e9459c6858 100644 --- a/src/overlays/l01/mobys/water_lily.c +++ b/src/overlays/l01/mobys/water_lily.c @@ -102,7 +102,7 @@ void water_lily_update(HoverMoby *water_lily) { switch (water_lily->state) { case WATER_LILY_STATE_INITIALIZE: *(u128 *)v = previous_water_lily_position.q; - water_lily->state = 1; + water_lily->state = WATER_LILY_STATE_UPDATE_POSITION; break; case WATER_LILY_STATE_UPDATE_POSITION: spring_axis_to(&water_lily->pos.v.x, From 38a9a30e4d43ef29249ab5e9b879c4d94965a687 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:57:46 +0000 Subject: [PATCH 0714/1502] decomp: clarify names in UpdateMpegReferenceImages domain_0_value_3 -> MPEG_PICTURE_CODING_TYPE_B: The authoritative source identifies state+0x150 as coding_type, distinct from picture_structure at +0x174; retail 0x00129560/0x00129574 selects coding_type 3. This branch selects reordered pictures (+0x1c4/+0x1d4/+0x1e4), avoids the reference rotation performed at 0x00129690-0x001296bc, and requires both current and previous reference frames (or both field pairs) at 0x00129604-0x00129684. This is the bidirectionally predicted MPEG B-picture coding type, not the equal-valued FRAME picture_structure. domain_1_value_2 -> MPEG_PICTURE_CODING_TYPE_P: Retail loads coding_type from state+0x150 into t2 at 0x00129560. After excluding B pictures and rotating the references, the frame branch at 0x001296d4-0x001296ec tests this same coding_type against 2: only type 2 requires current_frame->status (+0x1b8 then +0x28) to be 1 before returning references_ready. The single prior-reference dependency identifies the predictively coded MPEG P-picture type, distinct from picture_structure BOTTOM_FIELD=2. domain_2_value_2 -> MPEG_PICTURE_CODING_TYPE_P: This is the same state+0x150 coding_type loaded at 0x00129560 and compared with 2 in the field path at 0x001296fc. Unlike the excluded B-picture two-reference path, this branch accepts the opposite selected field when force_reorder is nonzero and its status is 1 (0x00129704-0x00129714), or a ready current top/bottom field pair (0x00129718-0x00129730). It implements the field form of the same single-reference predictively coded MPEG P-picture domain as domain_1_value_2. domain_3_value_1 -> MPEG_REFERENCE_STATUS_READY: The source predicted_field selects the opposite field of the selected reference picture; retail 0x001296f0-0x00129710 selects +0x1dc or +0x1cc and reads its status at +0x28. Equality with 1 branches to 0x0012973c with t5=1. t5 is returned at 0x0012977c, and supplied callers _decodeOrSkipField/_decodeOrSkipFrame invoke _decPicture only when _updateRefImage returns nonzero. Thus status 1 explicitly denotes a reference ready for prediction. domain_4_value_0 -> MPEG_REFERENCE_STATUS_NOT_READY: Retail 0x00129740-0x00129774 selects selected_frame/top_field/bottom_field by picture_structure and 0x00129778 writes 0 to that picture's status at +0x28 before copying timestamps and picture metadata at 0x00129780-0x00129800. The same status field must equal 1 to satisfy reference-readiness checks at 0x0012960c-0x00129684 and 0x0012970c-0x00129730; zero is also written when current references are invalidated at 0x001295d8-0x001295ec. It therefore marks the selected picture not ready as a prediction reference, without asserting a more specific decode failure or allocation state. --- src/sdk/mpeg/ref_images/_updateRefImage.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/sdk/mpeg/ref_images/_updateRefImage.c b/src/sdk/mpeg/ref_images/_updateRefImage.c index 74bbacea5b..b9227a744d 100644 --- a/src/sdk/mpeg/ref_images/_updateRefImage.c +++ b/src/sdk/mpeg/ref_images/_updateRefImage.c @@ -75,6 +75,12 @@ s32 UpdateMpegReferenceImages(struct MpegReferenceState *state, s32 force_reorde MPEG_PICTURE_STRUCTURE_BOTTOM_FIELD = 2, MPEG_PICTURE_STRUCTURE_FRAME = 3 }; + enum { + MPEG_REFERENCE_STATUS_NOT_READY = 0, + MPEG_REFERENCE_STATUS_READY = 1, + MPEG_PICTURE_CODING_TYPE_P = 2, + MPEG_PICTURE_CODING_TYPE_B = 3 + }; struct MpegReferencePicture *selected_picture; s32 references_ready; s32 queue_threshold; @@ -84,7 +90,7 @@ s32 UpdateMpegReferenceImages(struct MpegReferenceState *state, s32 force_reorde selected_picture = NULL; references_ready = 0; queue_threshold = (state->picture_structure == 3) ? 2 : 4; - if (state->coding_type == 3) { + if (state->coding_type == MPEG_PICTURE_CODING_TYPE_B) { state->selected_frame = state->reordered_frame; state->selected_top_field = state->reordered_top_field; state->selected_bottom_field = state->reordered_bottom_field; @@ -133,13 +139,13 @@ s32 UpdateMpegReferenceImages(struct MpegReferenceState *state, s32 force_reorde state->selected_top_field = state->previous_top_field; state->selected_bottom_field = state->previous_bottom_field; if (state->picture_structure == 3) { - if (state->coding_type != 2 || state->current_frame->status == 1) { + if (state->coding_type != MPEG_PICTURE_CODING_TYPE_P || state->current_frame->status == 1) { references_ready = 1; } } else { predicted_field = (state->picture_structure == 1) ? state->selected_bottom_field : state->selected_top_field; - if (state->coding_type != 2 || (force_reorder != 0 && predicted_field->status == 1) || + if (state->coding_type != MPEG_PICTURE_CODING_TYPE_P || (force_reorder != 0 && predicted_field->status == MPEG_REFERENCE_STATUS_READY) || (state->current_top_field->status == 1 && state->current_bottom_field->status == 1)) { references_ready = 1; @@ -157,7 +163,7 @@ s32 UpdateMpegReferenceImages(struct MpegReferenceState *state, s32 force_reorde selected_picture = state->selected_bottom_field; break; } - selected_picture->status = 0; + selected_picture->status = MPEG_REFERENCE_STATUS_NOT_READY; selected_picture->presentation_timestamp = state->presentation_timestamp; selected_picture->coding_type = state->coding_type; selected_picture->decoding_timestamp = state->decoding_timestamp; From 741ff35e4c27cf0042713023646dd6502b84f12f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:57:46 +0000 Subject: [PATCH 0715/1502] decomp: clarify names in process_heavy_gunship_part_hits domain_0_value_99 -> HEAVY_GUNSHIP_DISPERSE_AND_REMOVE: Assigned retail 0x002e99b0-0x002e99cc searches all eight trailing slots and, when none remain, stores 0x63 at +0x20 of s6 (the input moby saved at 0x002e9774). Checked caller update_heavy_gunship saves its input in s4 at 0x002e9b80 and passes that same pointer to process_heavy_gunship_part_hits at 0x002e9e38-0x002e9e3c. It loads +0x20 at 0x002e9bd8 and dispatches 0x63 at 0x002e9c0c-0x002e9c10 to 0x002ea2ac. That branch traverses sixteen parts, computes outward drift, sets child state 1 and clears links (0x002ea2c8-0x002ea330), bursts the parent and calls mark_moby_for_removal at 0x002ea34c-0x002ea358. Authoritative C names precisely this caller case HEAVY_GUNSHIP_DISPERSE_AND_REMOVE=0x63; identical parent-pointer flow proves this assignment belongs to that same heavy-gunship current-state domain. --- src/overlays/l08/mobys/heavy_gunship.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/heavy_gunship.c b/src/overlays/l08/mobys/heavy_gunship.c index a0ec1982da..aa2ed89cc3 100644 --- a/src/overlays/l08/mobys/heavy_gunship.c +++ b/src/overlays/l08/mobys/heavy_gunship.c @@ -119,6 +119,9 @@ void spawn_heavy_gunship_parts(struct Moby *moby) { void process_heavy_gunship_part_hits(struct Moby *moby) __asm__("FUN_L08_002e9758"); void process_heavy_gunship_part_hits(struct Moby *moby) { + enum { + HEAVY_GUNSHIP_DISPERSE_AND_REMOVE = 99 + }; int selected = 0; char *linked_part_hit_vars = (char *)moby->pvars; SwarmPart *slots = (SwarmPart *)(linked_part_hit_vars + 0x60); @@ -197,7 +200,7 @@ void process_heavy_gunship_part_hits(struct Moby *moby) { } i++; } while (i < 8); - moby->state = 99; + moby->state = HEAVY_GUNSHIP_DISPERSE_AND_REMOVE; } } if (sound >= 0) From e504327f29ff88c9be318de2dd5f6582879f1cf9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:59:47 +0000 Subject: [PATCH 0716/1502] decomp: clarify names in refueling_station_update domain_0_value_1 -> REFUELING_STATION_STATE_WAIT_COMMAND: The exact selector is moby->state: retail 00303d3c reads byte +0x20(s1), and 00303d40 dispatches value 1 to 00303dc0. Initialization writes 1 to the same byte at 00303dbc after clearing the voice slot at 00303db4. That destination maintains voice playback and waits for command +0xBC == 1 at 00303e20-00303e24, matching the existing local REFUELING_STATION_STATE_WAIT_COMMAND case. domain_1_value_2 -> REFUELING_STATION_STATE_EXPLOSION_DELAY: Retail 00303e50-00303e64 initializes private timer +0x74 from scale_game_frames(10) after command 1. Retail 00303ea8-00303eac writes 2 to moby state +0x20(s1), the exact byte dispatched by 00303d3c/00303d60 to 00303eb8. That branch decrements the same timer and waits for expiration, proving reuse of the existing local REFUELING_STATION_STATE_EXPLOSION_DELAY case. domain_2_value_3 -> REFUELING_STATION_STATE_EXPLODE: After the +0x74 timer expires and linked-moby notification is attempted, retail 00303f24-00303f2c writes 3 to moby state +0x20(s1). The dispatch at 00303d3c/00303d68 reads that same state byte and selects 00303f30, which builds the explosion vector, calls spawn_explosion at 00303fa0 and removes the moby at 00303fa8. This is the existing local REFUELING_STATION_STATE_EXPLODE case. --- src/overlays/l09/mobys/refueling_station.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l09/mobys/refueling_station.c b/src/overlays/l09/mobys/refueling_station.c index 29b0f5dbab..09ec6348fd 100644 --- a/src/overlays/l09/mobys/refueling_station.c +++ b/src/overlays/l09/mobys/refueling_station.c @@ -180,7 +180,7 @@ void refueling_station_update(struct Moby *moby) { return; } station_vars->voice = -1; - moby->state = 1; + moby->state = REFUELING_STATION_STATE_WAIT_COMMAND; break; case REFUELING_STATION_STATE_WAIT_COMMAND: if ((D_L09_0015F5CC & 7) == (((int)moby >> 8) & 7)) { @@ -206,7 +206,7 @@ void refueling_station_update(struct Moby *moby) { } station_vars->voice = -1; moby->update_dist = 0xFF; - moby->state = 2; + moby->state = REFUELING_STATION_STATE_EXPLOSION_DELAY; } break; case REFUELING_STATION_STATE_EXPLOSION_DELAY: @@ -221,7 +221,7 @@ void refueling_station_update(struct Moby *moby) { o[0xBC] = 1; } } - moby->state = 3; + moby->state = REFUELING_STATION_STATE_EXPLODE; } break; case REFUELING_STATION_STATE_EXPLODE: From c902876298e3c31510a913702e632c4d869cb3c2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:59:47 +0000 Subject: [PATCH 0717/1502] decomp: clarify names in update_path_following_rocket domain_0_value_1 -> ROCKET_STATE_WAIT_FOR_TRIGGER: Retail 0x002c3d64 reads moby state byte +0x20 and 0x002c3d74 dispatches value 1 to 0x002c3e0c. Initialization stores s3=1 to that same byte at 0x002c3dfc after deriving the path increment. The destination branch waits for hero control mode 15 and a successful clip-volume check before advancing, proving reuse of the existing local ROCKET_STATE_WAIT_FOR_TRIGGER member. domain_1_value_2 -> ROCKET_STATE_FOLLOW_PATH: Retail 0x002c3e24-0x002c3e38 stores 2 to moby+0x20 only after the trigger clip-volume test succeeds. The dispatcher at 0x002c3d98 sends that same state byte value 2 to 0x002c3e44, which increments path progress and calls sample_camera_path at 0x002c3e98. This is the exact domain and behavior of existing ROCKET_STATE_FOLLOW_PATH. domain_2_value_3 -> ROCKET_STATE_WAIT_FOR_RESET: Retail 0x002c3e54-0x002c3e84 compares updated progress with path point count minus one, then stores 3 to moby+0x20 on completion. The dispatcher at 0x002c3da0 routes value 3 of that same byte to 0x002c3f28, which waits for reset conditions before resampling the path start and restoring visibility/collision. Reuse existing ROCKET_STATE_WAIT_FOR_RESET. domain_3_value_1 -> ROCKET_STATE_WAIT_FOR_TRIGGER: Retail reset sequence 0x002c3f8c-0x002c3fcc clears command and progress, samples path position at zero, restores visibility and class collision, and clears the proximity latch. At 0x002c3fd0 it stores s3=1 to moby+0x20, the same byte whose value 1 dispatches at 0x002c3d74 to the trigger-waiting branch. Thus the existing ROCKET_STATE_WAIT_FOR_TRIGGER member applies. --- src/overlays/l16/mobys/path_following_rocket.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l16/mobys/path_following_rocket.c b/src/overlays/l16/mobys/path_following_rocket.c index e54aaa9a21..a2fea6089c 100644 --- a/src/overlays/l16/mobys/path_following_rocket.c +++ b/src/overlays/l16/mobys/path_following_rocket.c @@ -60,7 +60,7 @@ void path_following_rocket_update(struct Moby *moby) { } rocket_path_data->unkC = rocket_path_data->unk8 * D_0015ED6C / fast_vec_dist(path + 0x10, path + 0x20); - moby->state = 1; + moby->state = ROCKET_STATE_WAIT_FOR_TRIGGER; moby->update_dist = 100; moby->command = 0; break; @@ -69,7 +69,7 @@ void path_following_rocket_update(struct Moby *moby) { if (player->state.control_mode != 15) break; if (is_point_inside_clip_volume(&player->motion.body_center, *(int *)rocket_path_data)) { - moby->state = 2; + moby->state = ROCKET_STATE_FOLLOW_PATH; rocket_path_data->unk16 = 0; } break; @@ -78,7 +78,7 @@ void path_following_rocket_update(struct Moby *moby) { rocket_path_data->unk10 += rocket_path_data->unkC; if ((float)(*(int *)path - 1) <= rocket_path_data->unk10) { moby->update_dist = 0xFF; - moby->state = 3; + moby->state = ROCKET_STATE_WAIT_FOR_RESET; } else { sample_camera_path( (int *)path, 0, &moby->pos, &moby->rot.x, 0, rocket_path_data->unk10); @@ -113,7 +113,7 @@ void path_following_rocket_update(struct Moby *moby) { moby->flags &= ~1; moby->collision = moby->pclass->collision; rocket_path_data->unk16 = 0; - moby->state = 1; + moby->state = ROCKET_STATE_WAIT_FOR_TRIGGER; } } break; From 211f219d427ba7f041a2e2685164dfdc6373e0c2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:59:47 +0000 Subject: [PATCH 0718/1502] decomp: clarify names in handle_sand_shark_nest_damage domain_0_value_4 -> SAND_SHARK_NEST_DEATH_KNOCKBACK: Retail 0x002dcff0 saves incoming moby a0 in s1; 0x002dd0a4 loads its state byte at s1+0x20 and 0x002dd0a8 skips further hit reaction when it equals 4. This is the same object passed by sand_shark_nest_update before its switch on moby[0x20]. That source already names state 4 SAND_SHARK_NEST_DEATH_KNOCKBACK and steps motion until flag 0x40, then decrements the spawner count, explodes and removes the nest. The guard therefore excludes this established death-knockback state, not a hit control mode. domain_1_value_3 -> SAND_SHARK_NEST_HIT_RECOVERY: Retail 0x002dd0dc-0x002dd0e4 selects the positive remaining-health path; 0x002dd15c-0x002dd164 tests damage >=1.0, and 0x002dd16c/0x002dd178 stores 3 into the incoming moby's state byte s1+0x20 before starting animation 2. sand_shark_nest_update calls this function on that same moby and switches on moby[0x20]; its existing SAND_SHARK_NEST_HIT_RECOVERY=3 branch steps motion and returns to waiting after the animation completion flag. Reuse that exact established state name. domain_2_value_4 -> SAND_SHARK_NEST_DEATH_KNOCKBACK: Retail 0x002dd0dc-0x002dd0e4 branches to 0x002dd19c when pvars+0x20 health is not positive. 0x002dd0d0 sets a3=4, and 0x002dd1cc stores it into the incoming moby's state at s1+0x20. This path clears flag 0x1000, starts stronger knockback at 0x002dd1f0-0x002dd210 and selects animation 3. The caller sand_shark_nest_update switches on the same moby[0x20] and already names state 4 SAND_SHARK_NEST_DEATH_KNOCKBACK; that branch waits for motion completion then explodes and removes the nest. --- src/overlays/l02/mobys/sand_shark_nest.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l02/mobys/sand_shark_nest.c b/src/overlays/l02/mobys/sand_shark_nest.c index 19c523f0cd..550dda5a05 100644 --- a/src/overlays/l02/mobys/sand_shark_nest.c +++ b/src/overlays/l02/mobys/sand_shark_nest.c @@ -310,6 +310,10 @@ extern int hit_reaction(void *, void *, void *, int, int *, float *, int, int) __asm__("FUN_L00_0025a478"); void handle_sand_shark_nest_damage(struct Moby *moby) { + enum { + SAND_SHARK_NEST_HIT_RECOVERY = 3, + SAND_SHARK_NEST_DEATH_KNOCKBACK = 4 + }; char *nest_vars = (char *)moby->pvars; float hit_knockback_vector[4]; int hit; @@ -329,7 +333,7 @@ void handle_sand_shark_nest_damage(struct Moby *moby) { } hit_record = find_moby_hit(moby, 0x330000, 0); hit_reaction(moby, hit_record, nest_vars + 0x20, 0, &hit, &dmg, 0, 4); - if (hit_record != 0 && hit != 1 && moby->state != 4) { + if (hit_record != 0 && hit != 1 && moby->state != SAND_SHARK_NEST_DEATH_KNOCKBACK) { if (hit == 3) { *(float *)(nest_vars + 0x20) = 0.0f; } else { @@ -348,7 +352,7 @@ void handle_sand_shark_nest_damage(struct Moby *moby) { trooper_start_knockback(k1, moby, nest_vars + 0x70, 3, 1, 0); if (1.0f <= dmg) { nest_vars[0x67] = 0x78; - moby->state = 3; + moby->state = SAND_SHARK_NEST_HIT_RECOVERY; blend_moby_animation(moby, 2, 0, 0); } else { nest_vars[0x67] = 0x78; @@ -356,7 +360,7 @@ void handle_sand_shark_nest_damage(struct Moby *moby) { } else { moby->flags &= 0xEFFF; ((unsigned char *)nest_vars)[0x67] = 0xFA; - moby->state = 4; + moby->state = SAND_SHARK_NEST_DEATH_KNOCKBACK; { float b = D_0015ED6C * 11.0f; float a = D_0015ED6C * 3.0f; From 551806b4eb8e6ff68f284be4919fcc3bbe6d44cb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:59:47 +0000 Subject: [PATCH 0719/1502] decomp: clarify names in update_test_dummy_damage_and_respawn domain_0_value_1 -> TEST_DUMMY_STATE_IDLE: Retail 0x002ce9fc retains the input moby in s1; 0x002cea14 reads its state byte +0x20 and 0x002cea18 returns for 1. The authoritative test_dummy_update passes this same moby to this helper before switching on moby[0x20], whose existing TEST_DUMMY_STATE_IDLE=1 arm does nothing. This proves the dummy state domain, not HeroStateId. domain_1_value_11 -> TEST_DUMMY_STATE_RESPAWN: Retail 0x002cea6c..0x002cea84 decrements lives and writes 11 to the input moby's state byte +0x20 when lives remain; 0x002cea88..0x002ceaa0 restores spawn position and sets a 60-frame timer. The same moby is dispatched by test_dummy_update, whose existing TEST_DUMMY_STATE_RESPAWN=11 arm settles spawn height and then resumes movement. domain_3_value_10 -> TEST_DUMMY_STATE_BURST: Retail 0x002ceb2c..0x002ceb30 compares the input moby's +0x20 state against 10 to skip further hit handling. At 0x002ceb40..0x002ceb5c depleted health selects the identical state. The caller test_dummy_update dispatches this same byte and its existing TEST_DUMMY_STATE_BURST=10 arm emits three pieces, decrements lives and selects respawn or removal. domain_4_value_11 -> TEST_DUMMY_STATE_RESPAWN: Retail 0x002ceb34..0x002ceb38 compares the input moby's +0x20 state against 11 to suppress hit processing during respawn. The write at 0x002cea84 selects this same byte before restoring spawn and timer. The caller dispatches moby[0x20] using the existing TEST_DUMMY_STATE_RESPAWN=11 arm. domain_5_value_10 -> TEST_DUMMY_STATE_BURST: Retail 0x002ceb40..0x002ceb54 subtracts hit amount from private health +0x20 and tests for nonpositive health; 0x002ceb5c writes 10 to the moby's distinct state byte +0x20. The caller passes this same moby then switches on that byte, with existing TEST_DUMMY_STATE_BURST=10 emitting burst pieces and handling exhausted lives. domain_6_value_9 -> TEST_DUMMY_STATE_TURN_AND_RESUME_SAVED_STATE: Retail 0x002ceb60..0x002ceb78 compares moby state +0x20 with 9 and saves the previous state at private +0x110 and animation at +0x114 only when not already 9. The caller's existing TEST_DUMMY_STATE_TURN_AND_RESUME_SAVED_STATE=9 arm turns using private +0x10c then restores those exact saved state/animation fields. domain_7_value_9 -> TEST_DUMMY_STATE_TURN_AND_RESUME_SAVED_STATE: Retail 0x002ceb80..0x002ceba8 computes heading toward the hero, stores it at private +0x10c and writes 9 to the input moby's state +0x20; the preceding instructions preserve state/animation at +0x110/+0x114. The same-moby caller dispatches this byte under existing TEST_DUMMY_STATE_TURN_AND_RESUME_SAVED_STATE=9 and consumes those saved fields. --- src/overlays/l16/mobys/test_dummy.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/overlays/l16/mobys/test_dummy.c b/src/overlays/l16/mobys/test_dummy.c index 514b835b13..c804ef33aa 100644 --- a/src/overlays/l16/mobys/test_dummy.c +++ b/src/overlays/l16/mobys/test_dummy.c @@ -529,6 +529,12 @@ extern void mark_moby_for_removal_c2(void *) __asm__("func_0020C828"); /* Per-frame update of a hit-point moby: handles a hit (respawn at the spawn point or removal when out of lives) and its state timers. */ void update_test_dummy_damage_and_respawn(void *moby) { + enum { + TEST_DUMMY_STATE_IDLE = 1, + TEST_DUMMY_STATE_TURN_AND_RESUME_SAVED_STATE = 9, + TEST_DUMMY_STATE_BURST = 10, + TEST_DUMMY_STATE_RESPAWN = 11 + }; L16HitMoby *hit_moby = moby; float matrix[16]; int status; @@ -536,7 +542,7 @@ void update_test_dummy_damage_and_respawn(void *moby) { L16HitData *hit_data; char *dummy_hit_record; - if (hit_moby->state == 1) { + if (hit_moby->state == TEST_DUMMY_STATE_IDLE) { return; } hit_data = hit_moby->data; @@ -548,7 +554,7 @@ void update_test_dummy_damage_and_respawn(void *moby) { hit_moby->flags &= 0xEFFF; hit_data->lives--; if (hit_data->lives != -1) { - hit_moby->state = 11; + hit_moby->state = TEST_DUMMY_STATE_RESPAWN; qcopy(hit_moby->position, hit_data->spawn); hit_data->timer = scale_game_frames(60); } else { @@ -565,12 +571,12 @@ void update_test_dummy_damage_and_respawn(void *moby) { amount = 0.0f; dummy_hit_record = find_moby_hit(hit_moby, 0x330000, 0); hit_reaction(hit_moby, dummy_hit_record, &hit_data->health, 0, &status, &amount, 0, 4); - if (status != 1 && hit_moby->state != 10 && hit_moby->state != 11) { + if (status != 1 && hit_moby->state != TEST_DUMMY_STATE_BURST && hit_moby->state != TEST_DUMMY_STATE_RESPAWN) { hit_data->health -= amount; if (hit_data->health <= 0.0f) { - hit_moby->state = 10; + hit_moby->state = TEST_DUMMY_STATE_BURST; } else { - if (hit_moby->state != 9) { + if (hit_moby->state != TEST_DUMMY_STATE_TURN_AND_RESUME_SAVED_STATE) { hit_data->next_state = hit_moby->state; hit_data->next_anim = hit_moby->animation; } @@ -580,7 +586,7 @@ void update_test_dummy_damage_and_respawn(void *moby) { hit_data->heading = fast_arc_tan(player->motion.pos.f[0] - x, player->motion.pos.f[1] - y); } - hit_moby->state = 9; + hit_moby->state = TEST_DUMMY_STATE_TURN_AND_RESUME_SAVED_STATE; /* No pointer local for the reaction record anywhere: d->reaction is written at each call and the compiler caches it itself (formed before the hit query, and formed again here with a copy after the call). It only forms it again here when this place cannot be reached along one straight path From a6831a554512ace62a0beedac7ede104cbf65c83 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:59:47 +0000 Subject: [PATCH 0720/1502] decomp: clarify names in correct_hero_ground_penetration domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Retail 0x00213000 forms &hero (0x0013F350); 0x00213008 loads its gravity_mode byte at +0x20B3 and 0x0021300C branches on zero to 0x0021313C. Original Ghidra likewise tests cRam00141403 == 0. The zero branch corrects world Z using position +0x88 and ground Z +0x2D8 at 0x00213148-0x00213158, whereas the nonzero branch uses velocity dot ground_normal and a full ground_point-position vector. The authoritative source's update_hero_ground_contact_and_surface_slopes switches on this exact hero.gravity_mode field and its HERO_GRAVITY_WORLD_DOWN case sets gravity_dir.f[2] = -1.0f; turn_to and set_planar_vel also use this canonical member for the same field. This proves HeroGravityMode domain membership, not mere numeric equality. The supplied shared enum in include/rnc/hero/hero_state.h defines HERO_GRAVITY_WORLD_DOWN = 0. --- src/overlays/shared/hero/hero_switch_item.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 3aa59433f3..214c7f8cc3 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -3516,7 +3516,7 @@ void correct_hero_ground_penetration(void) __asm__("FUN_L00_00212ff0"); void correct_hero_ground_penetration(void) { struct Hero *globals = &hero; float ground_position_correction[4]; - if (globals->gravity_mode != 0) { + if (globals->gravity_mode != HERO_GRAVITY_WORLD_DOWN) { float velocity_dot = fast_vec_dot(&globals->motion.velocity, &globals->ground_normal); float ground_dist; float ground_correction_length; From 451cac632012d2b5f545608f39304ef898707069 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:59:47 +0000 Subject: [PATCH 0721/1502] decomp: clarify names in process_shrub_part_hits domain_0_value_99 -> SHRUB_BREAK_APART_AND_REMOVE: Retail 0x002e88f4 preserves the parent argument in s6; 0x002e8b10-0x002e8b48 searches all eight fallback entries 5-12, and 0x002e8b50-0x002e8b54 stores 0x63 at parent+0x20 only after exhaustion. The original decompilation agrees. Checked caller 0x002e8efc passes its same parent s4 to this function; 0x002e8d38 reads parent+0x20 and 0x002e8d6c-0x002e8d70 dispatches 0x63 to 0x002e946c. That handler bursts and detaches remaining parts (0x002e9488-0x002e94f0), bursts the parent, then calls source-bound mark_moby_for_removal (0x002e94f4-0x002e9518). SHA-bound shrub.c already calls this same parent state SHRUB_BREAK_APART_AND_REMOVE in shrub_update; reuse that semantic spelling in the assigned function-local domain. --- src/overlays/l08/mobys/shrub.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/shrub.c b/src/overlays/l08/mobys/shrub.c index f1760cd49f..343ae943b6 100644 --- a/src/overlays/l08/mobys/shrub.c +++ b/src/overlays/l08/mobys/shrub.c @@ -104,6 +104,9 @@ void spawn_shrub_parts(char *moby) { } void process_shrub_part_hits(struct Moby *parent_moby) { + enum { + SHRUB_BREAK_APART_AND_REMOVE = 0x63 + }; char *shrub_hit_vars = ((char *)parent_moby->pvars); char *shrub_part_entry_address = shrub_hit_vars + 0x60; char **part_entry_cursor = (char **)shrub_part_entry_address; @@ -175,7 +178,7 @@ void process_shrub_part_hits(struct Moby *parent_moby) { return; } } - parent_moby->state = 0x63; + parent_moby->state = SHRUB_BREAK_APART_AND_REMOVE; } } if (hit_sound_id >= 0) From 4f402fe9222075ba19554423ff2a8dd3ccbab6bb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:59:48 +0000 Subject: [PATCH 0722/1502] decomp: clarify names in close_pause_menu domain_0_value_20 -> PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION: Retail 0x00276b04 loads 0x14 and 0x00276b0c stores it to 0x001b9cf0, the exact D_L00_001B9CF0.state word read by caller update_pause_menu at 0x00276c5c and compared against 0x14 at 0x00276c60-64. Its branch waits on +0x14 and CD activity, restores saved camera vectors at 0x00276cac-cc0, restores FOV and selects gameplay moby context at 0x00276cc4-cd4, clears menu buffers at 0x00276d0c-d1c, and dispatches the pending +0xc action (level transition, movie, scene or slideshow) at 0x00276d20-e74. The authoritative source already names this exact same selector value PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION in update_pause_menu; reuse that semantic member for this assignment. This selector is unrelated to HeroStateId. --- src/overlays/shared/ui/menus/initialize_pause_menu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/ui/menus/initialize_pause_menu.c b/src/overlays/shared/ui/menus/initialize_pause_menu.c index b94328ee49..fdc54b44c1 100644 --- a/src/overlays/shared/ui/menus/initialize_pause_menu.c +++ b/src/overlays/shared/ui/menus/initialize_pause_menu.c @@ -389,6 +389,9 @@ void initialize_pause_menu(void) { /* Closes the scene once its progress reaches 10: releases its objects, restores the hero's items and HUD bank, deletes the 14 scene mobies, shows the health and bolt HUD, enters state 0x14. */ void close_pause_menu(void) { + enum { + PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION = 0x14 + }; s32 i; s32 value; s32 handle; @@ -456,7 +459,7 @@ void close_pause_menu(void) { ¤t_bolt_count, 9999999); hud_keep_visible(handle, scale_game_frames(0xb4)); - D_L00_001B9CF0.state = 0x14; + D_L00_001B9CF0.state = PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION; D_L00_001B9CF0.unk14 = 2; { s32 value = D_L00_001B9CF0.saved_seq_count; From 9d708752c0a1c84a0a2ac91e11857f13ba2d8d3c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:01:27 +0000 Subject: [PATCH 0723/1502] decomp: clarify names in initialize_leg_rig domain_0_value_5 -> LEG_RIG_FALLBACK_GAIT_MASK: Retail 0x002923c4 preserves rig in s2; 0x00292618 loads 5 and 0x00292654 stores it to rig+0xb6, matching rig->mode. The supplied reset_leg_rig_from_animation assigns LEG_RIG_FALLBACK_GAIT_MASK=5 to this exact field before rig_pick_mode; FUN_L04_002927d0 returns rig+0xb6 when no animation record matches. leg_walker_update uses the returned mode as a contact-point bit mask, including mode & 0xF and active & bit in the six-point shift loop. Thus this initializes the same fallback gait mask, not a moby state ID. --- src/overlays/l04/mobys/leg_walker.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l04/mobys/leg_walker.c b/src/overlays/l04/mobys/leg_walker.c index c1b6c6ce90..c54a4ea65f 100644 --- a/src/overlays/l04/mobys/leg_walker.c +++ b/src/overlays/l04/mobys/leg_walker.c @@ -61,6 +61,9 @@ extern float FUN_L04_001f1978(float); void initialize_leg_rig(struct Moby *moby, LegRig *rig) __asm__("FUN_L04_002923b8"); void initialize_leg_rig(struct Moby *moby, LegRig *rig) { + enum { + LEG_RIG_FALLBACK_GAIT_MASK = 5 + }; int joints[6]; float matrix[4][4]; int i; @@ -119,7 +122,7 @@ void initialize_leg_rig(struct Moby *moby, LegRig *rig) { rig->unkD8 = 0; rig->unkE4 = 0; rig->unkEC = 0; - rig->mode = 5; + rig->mode = LEG_RIG_FALLBACK_GAIT_MASK; debug_print(rig_size_message, 0x250); } /* Ported from rac1-decomp (src/overlays/l04_eudora/vuchain_00293490.c: func_L04_00293990), where it is exact; names translated to the US level program. */ From 6304f92e54686eba2ecc39c92433d5ac91dda84c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:01:27 +0000 Subject: [PATCH 0724/1502] decomp: clarify names in amoeboid_update domain_0_value_1 -> AMOEBOID_FOLLOW_PATH: Source SHA-256 c0513078728dff5c8b21657a6eaf4835901efcb6477ef90c7d96ec8084b0cd71 declares AMOEBOID_FOLLOW_PATH=1 in the switch on moby->state. Retail 0x002dac8c sets s2=1; 0x002dace4 stores s2 to that same state byte at s0+0x20 during initialization. At 0x002daca8-0x002dacac that byte is compared with 1 to dispatch to 0x002dad88, whose path-node steering, movement and node selection through 0x002daedc implement the existing FOLLOW_PATH branch. Original Ghidra likewise writes state 1 after state 0, proving reuse of the existing amoeboid state constant. domain_1_value_1 -> AMOEBOID_FOLLOW_PATH: Retail 0x002daef0-0x002daf14 checks distance from moby position to hero against 48; when greater, 0x002daf28 stores s2=1 to s0+0x20, the very state byte read at 0x002daca8 and dispatched by 0x002dacac to path following at 0x002dad88. The adjacent 0x002daf20-0x002daf38 restores visibility and collision. Original Ghidra and SHA-bound source agree this assignment leaves AMOEBOID_WAIT_FOR_HERO_TO_LEAVE and resumes the existing AMOEBOID_FOLLOW_PATH=1 member of the same local state domain. --- src/overlays/l05/mobys/amoeboid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l05/mobys/amoeboid.c b/src/overlays/l05/mobys/amoeboid.c index 8d3aa91c4e..ad8747961c 100644 --- a/src/overlays/l05/mobys/amoeboid.c +++ b/src/overlays/l05/mobys/amoeboid.c @@ -53,7 +53,7 @@ void amoeboid_update(struct Moby *moby) { handle_amoeboid_hits(moby); switch (moby->state) { case AMOEBOID_INITIALIZE: - moby->state = 1; + moby->state = AMOEBOID_FOLLOW_PATH; moby->update_dist = 0x40; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, 0); @@ -98,7 +98,7 @@ void amoeboid_update(struct Moby *moby) { } case AMOEBOID_WAIT_FOR_HERO_TO_LEAVE: if (48.0f < vector_distance_xy(&moby->pos, &hero.motion.pos)) { - moby->state = 1; + moby->state = AMOEBOID_FOLLOW_PATH; moby->visible = 1; moby->flags &= 0xFFFE; moby->collision = moby->pclass->collision; From b2d6ff808f5fc12640aa3b89371bfb23467c8160 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:01:27 +0000 Subject: [PATCH 0725/1502] decomp: clarify names in update_path_spark_emitter domain_0_value_1 -> SPARK_STATE_TRAVERSE_PATH: Retail 0x002d8d94 loads moby+0x20 and 0x002d8da4-0x002d8da8 dispatch value 1 to path traversal at 0x002d8e30. After the timer at spark_vars+8 completes (0x002d8e10-0x002d8e1c), 0x002d8e20-0x002d8e24 writes 1 to that same moby+0x20 byte and resets path progress at 0x002d8e2c. Original Ghidra agrees. This is the same selector as the bound C local enum case SPARK_STATE_TRAVERSE_PATH, which advances progress and evaluates the path. domain_1_value_0 -> SPARK_STATE_WAIT_FOR_TIMER: Retail 0x002d8fb8-0x002d8fc4 compares the evaluated segment with path count minus one; on completion 0x002d8fcc writes zero to moby+0x20 and 0x002d8fd0-0x002d8fd8 installs the scaled 0x78 wait timer at spark_vars+8. The same byte is read by dispatch at 0x002d8d94-0x002d8d9c, where zero selects light/voice cleanup and timer waiting at 0x002d8db8-0x002d8e1c. Original Ghidra and bound C agree, proving reuse of existing SPARK_STATE_WAIT_FOR_TIMER in this local spark-state domain. --- src/overlays/l10/mobys/path_spark_emitter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/path_spark_emitter.c b/src/overlays/l10/mobys/path_spark_emitter.c index 0e83d67911..87d9eef660 100644 --- a/src/overlays/l10/mobys/path_spark_emitter.c +++ b/src/overlays/l10/mobys/path_spark_emitter.c @@ -79,7 +79,7 @@ void path_spark_emitter_update(struct Moby *moby) { } *(int *)(spark_vars + 0x10) = -1; if (func_001F9908_v(spark_vars + 8) != 0) { - moby->state = 1; + moby->state = SPARK_STATE_TRAVERSE_PATH; *(int *)(spark_vars + 4) = 0; } break; @@ -127,7 +127,7 @@ void path_spark_emitter_update(struct Moby *moby) { *(OvlQuad *)spark_path_position; } if (seg == *path - 1) { - moby->state = 0; + moby->state = SPARK_STATE_WAIT_FOR_TIMER; *(int *)(spark_vars + 8) = scale_game_frames(0x78); } break; From 6746aa221e421897fba44b3d1bb6ad3db205e69e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:03:14 +0000 Subject: [PATCH 0726/1502] decomp: clarify names in update_menu_stream_image domain_0_value_3 -> MEMCARD_REQUEST_FORMAT: Retail 0x0021fa18 forms memory-card base 0x0013d290, 0x0021fa20 loads its operation state at +0xd4, and 0x0021fa2c tests it with signed slti against 3. Original Ghidra identifies this as g_nMemoryCardOperationState < 3; the SHA-bound source maps it to memory_card_state.state. The supplied shared memory_card_state.h declaration context explicitly places state/pending_state in MemoryCardOperation, whose canonical value 3 is MEMCARD_REQUEST_FORMAT. A false comparison disables the stream at 0x0021fa74-0x0021fa7c; this is an operation boundary, not a stream-state or probe-step value. domain_1_value_0 -> MEMCARD_QUERY_INFO: Retail 0x0021fa48 loads +0xdc from the same memory-card base 0x0013d290 and 0x0021fa4c rejects nonnegative pending operations with bgez. Original Ghidra calls this g_nPendingMemoryCardOperationState < 0, matching memory_card_state.pending_state in the SHA-bound source. The supplied shared header explicitly assigns pending_state to MemoryCardOperation, whose canonical value 0 is MEMCARD_QUERY_INFO. Thus this bound is the start of that operation domain, not MEMCARD_PROBE_PROCESS_CHDIR_RESULT or a stream image state. Passing this test permits card-entry ID lookup at 0x0021fa60-0x0021fa70. --- src/ui/menus/stream_image/update_menu_stream_image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/menus/stream_image/update_menu_stream_image.c b/src/ui/menus/stream_image/update_menu_stream_image.c index ead9b73fcf..e332201a7b 100644 --- a/src/ui/menus/stream_image/update_menu_stream_image.c +++ b/src/ui/menus/stream_image/update_menu_stream_image.c @@ -56,7 +56,7 @@ s32 update_menu_stream_image(struct MenuScreen *stream) { if (selected_entry_index >= 5) { selected_entry_index = 4; } - if (memory_card_state.state < 3 && memory_card_state.pending_state < 0) { + if (memory_card_state.state < MEMCARD_REQUEST_FORMAT && memory_card_state.pending_state < MEMCARD_QUERY_INFO) { if (stream->data.stream.state == -1) { stream->data.stream.state = 0; } From 6b838c86cdee01c5bc3d664b82fe85ec32f162fc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:03:14 +0000 Subject: [PATCH 0727/1502] decomp: clarify names in loading_data_menu domain_0_value_3 -> MEMCARD_REQUEST_FORMAT: Retail 0x00223310-0x00223328 addresses memory_card_state at 0x0013d290, reads current operation at +0xd4 and pending operation at +0xdc, and permits completion only when current <3 and pending <0. The supplied shared header explicitly assigns state/pending_state to MemoryCardOperation, whose canonical value 3 is MEMCARD_REQUEST_FORMAT; this is its operation boundary, not a create/probe substep. domain_1_value_0 -> MEMCARD_QUERY_INFO: Retail 0x00223324-0x00223328 reads memory_card_state.pending_state at 0x0013d36c and rejects nonnegative queued operations before clearing card_op_pending. The supplied header places pending_state in MemoryCardOperation; canonical MEMCARD_QUERY_INFO=0 is the boundary tested by the original signed <0 comparison, not a substep or boolean. domain_4_value_3 -> MEMCARD_REQUEST_FORMAT: Retail 0x00223478-0x00223490 again reads the same memory_card_state current-operation +0xd4 and pending-operation +0xdc fields before allowing save-slot input. Shared header evidence establishes MemoryCardOperation for both fields, so current <3 reuses canonical MEMCARD_REQUEST_FORMAT=3 as the operation boundary. domain_5_value_0 -> MEMCARD_QUERY_INFO: Retail 0x0022348c-0x00223490 rejects nonnegative memory_card_state.pending_state before testing card type and accepting save-slot controls. This is the same +0xdc operation queue field subsequently assigned read-save operation 13, and the shared MemoryCardOperation domain defines its zero boundary as MEMCARD_QUERY_INFO. domain_6_value_0 -> MEMCARD_QUERY_INFO: Retail 0x0022354c-0x00223564 reads pending operation at +0xdc, branches on nonnegative, and only otherwise queues operation 13 after recording the selected save index. This proves an operation-queue sign test in the shared MemoryCardOperation domain, with canonical MEMCARD_QUERY_INFO=0 preserving its existing zero boundary. domain_7_value_13 -> MEMCARD_BEGIN_READ_SAVE: Retail 0x00223524-0x00223578 checks the selected save entry at card base+slot*0x1c+0x20, stores the selected slot at +0x14 and active_card=0 at +0xc0, then when pending_state at +0xdc is negative sets pending_card=0 at +0xe0 and pending_state=13 before setting menu card_op_pending. This queues the chosen save load in the header-proven MemoryCardOperation domain, whose canonical member is MEMCARD_BEGIN_READ_SAVE=13, not MemoryCardCreateStep's equal-valued save-open substep. --- src/ui/menus/save_data/loading_data_menu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ui/menus/save_data/loading_data_menu.c b/src/ui/menus/save_data/loading_data_menu.c index 8160bff414..20ba8e1ba3 100644 --- a/src/ui/menus/save_data/loading_data_menu.c +++ b/src/ui/menus/save_data/loading_data_menu.c @@ -44,7 +44,7 @@ s32 loading_data_menu(struct LoadMenuDescriptor *menu) { s32 scaled_volume_70; previous_save_slot = menu->selected_save_slot; if (menu_system.card_op_pending != 0) { - if ((memory_card_state.state < 3) && (memory_card_state.pending_state < 0)) { + if ((memory_card_state.state < MEMCARD_REQUEST_FORMAT) && (memory_card_state.pending_state < MEMCARD_QUERY_INFO)) { menu_system.card_op_pending = 0; if (memory_card_state.err != 0) { mode_freeze_flags |= 0x100; @@ -84,7 +84,7 @@ s32 loading_data_menu(struct LoadMenuDescriptor *menu) { menu_system.next = menu_system.current->back; return 0; } - if (((memory_card_state.state < 3) && (memory_card_state.pending_state < 0)) && + if (((memory_card_state.state < MEMCARD_REQUEST_FORMAT) && (memory_card_state.pending_state < MEMCARD_QUERY_INFO)) && (memory_card_state.card[0].type == 2)) { if (menu->flags & 1) { buttons = controller_state.raw_pressed; @@ -106,9 +106,9 @@ s32 loading_data_menu(struct LoadMenuDescriptor *menu) { allocate_voice_for_target_entry(0, 0x11, menu->sound_owner); memory_card_state.active_card = 0; memory_card_state.card[0].save_index = (s32)menu->selected_save_slot; - if (memory_card_state.pending_state < 0) { + if (memory_card_state.pending_state < MEMCARD_QUERY_INFO) { memory_card_state.pending_card = 0; - memory_card_state.pending_state = 0xD; + memory_card_state.pending_state = MEMCARD_BEGIN_READ_SAVE; } menu_system.card_op_pending = 1; menu_system.card_op_text = 0x4FB6; From 0cc906949b205fb496934a5db3a98b7108750f01 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:05:32 +0000 Subject: [PATCH 0728/1502] decomp: clarify names in update_triggered_moby_slide_and_lowering domain_0_value_1 -> MOBY_WAIT_FOR_TRIGGER: Retail 0x0030e52c loads the selector from moby+0x20. After initial pose placement, 0x0030e5e4 stores 1 to that same byte; dispatch 0x0030e530 sends state 1 to 0x0030e5e8, which waits for indexed trigger record byte +0xBC. This is exactly the existing local MOBY_WAIT_FOR_TRIGGER state, not the trigger byte's domain. domain_1_value_2 -> MOBY_SLIDE_TO_END_POINT: Retail 0x0030e5fc-0x0030e620 checks the linked record trigger, starts audio, clears motion storage and writes 2 to moby+0x20. Dispatch 0x0030e554 enters 0x0030e62c, where pose direction and origin form an endpoint, endpoint minus moby position supplies distance, and accelerated motion updates position. Reuse existing local MOBY_SLIDE_TO_END_POINT for this same state byte. domain_2_value_3 -> MOBY_LOWER_BELOW_POSE_HEIGHT: Retail 0x0030e71c-0x0030e748 tests slide displacement length against 0.01 and stores 3 to moby+0x20. The same byte's dispatch at 0x0030e55c enters 0x0030e74c, whose scalar update targets pose height at row+0x38 minus 5.9 and writes moby Z at +0x18. Reuse the existing local MOBY_LOWER_BELOW_POSE_HEIGHT state member. domain_3_value_4 -> MOBY_LOWERING_COMPLETE: Retail 0x0030e784-0x0030e7ac advances moby Z toward indexed pose height minus 5.9. At 0x0030e7b4-0x0030e7c8 the updated moby Z is compared with that same target; only when Z is below it do 0x0030e7cc-0x0030e7d0 store 4 into the selector byte moby+0x20. Thus 4 records completion of lowering; this function handles no subsequent state-4 motion. --- src/overlays/l05/mobys/triggered_slide.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l05/mobys/triggered_slide.c b/src/overlays/l05/mobys/triggered_slide.c index 0801af3278..a3dcff3d3f 100644 --- a/src/overlays/l05/mobys/triggered_slide.c +++ b/src/overlays/l05/mobys/triggered_slide.c @@ -35,7 +35,7 @@ void triggered_slide_update(char *moby) { MOBY_WAIT_FOR_TRIGGER = 1, MOBY_SLIDE_TO_END_POINT = 2, MOBY_LOWER_BELOW_POSE_HEIGHT = 3 - }; + } ; enum { MOBY_LOWERING_COMPLETE = 4}; TriggeredSlideVars *slide_and_lowering_vars = (TriggeredSlideVars *)MOBY(moby)->pvars; float slide_motion_scratch[4]; float slide_step_distance; @@ -58,14 +58,14 @@ void triggered_slide_update(char *moby) { MOBY(moby)->flags |= 0x8000; } fast_vec_add(moby + 0x10, moby + 0x10, slide_motion_scratch); - MOBY(moby)->state = 1; + MOBY(moby)->state = MOBY_WAIT_FOR_TRIGGER; break; } case MOBY_WAIT_FOR_TRIGGER: if ((*(unsigned char **)&D_L05_0015FFD8)[slide_and_lowering_vars->unk14 * 256 + 0xBC] != 0) { allocate_voice_for_target_entry(0, 0, moby); - MOBY(moby)->state = 2; + MOBY(moby)->state = MOBY_SLIDE_TO_END_POINT; clear_u64_value(slide_and_lowering_vars); } break; @@ -90,7 +90,7 @@ void triggered_slide_update(char *moby) { fast_vec_normalize(slide_and_lowering_vars, slide_motion_scratch, speed); fast_vec_add(moby + 0x10, moby + 0x10, slide_and_lowering_vars); if (fast_vec_length(slide_motion_scratch) < 0.01f) { - MOBY(moby)->state = 3; + MOBY(moby)->state = MOBY_LOWER_BELOW_POSE_HEIGHT; } break; case MOBY_LOWER_BELOW_POSE_HEIGHT: @@ -103,7 +103,7 @@ void triggered_slide_update(char *moby) { (float *)&MOBY(moby)->pos.z, &slide_and_lowering_vars->unk8); if (MOBY(moby)->pos.z < pose_entry->pos.z - 5.9f) { - MOBY(moby)->state = 4; + MOBY(moby)->state = MOBY_LOWERING_COMPLETE; } break; } From ae43eb7ad1693c7266492366a631dee6b64d132b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:05:32 +0000 Subject: [PATCH 0729/1502] decomp: clarify names in select_sandmouse_projectile_target domain_0_value_5 -> TARGET_KIND_LOCK_ON: Bound sandmouse.c SHA-256 33a59a527759b79b263f765a8ddaf6fad482ce3be1f7b3ed79b922fbe78f6b12 declares TargetClass.kind at +0x46 with comment '5 for lock-on targets'. Retail 0x0030d3c0 loads candidate pclass (+0x24); 0x0030d3cc loads its signed kind (+0x46) into s3, and 0x0030d3d0-0x0030d3d4 requires 5 before positive target-info, range and angular eligibility checks. Original Ghidra decompilation confirms this filter. 0x0030d574-0x0030d578 compares collision-hit pclass kind with that same discriminator. Selected candidates are returned at 0x0030d598 and used by try_fire_sandmouse_projectile for projectile aiming. Thus TARGET_KIND_LOCK_ON names the documented target-class domain, unrelated to moby state 5. --- src/overlays/shared/enemies/sandmouse.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/sandmouse.c b/src/overlays/shared/enemies/sandmouse.c index e682ad5c0f..129e6b2172 100644 --- a/src/overlays/shared/enemies/sandmouse.c +++ b/src/overlays/shared/enemies/sandmouse.c @@ -72,6 +72,9 @@ struct Moby *select_sandmouse_projectile_target(struct Moby *moby, f32 nearYaw, f32 nearPitch) { + enum { + TARGET_KIND_LOCK_ON = 5 + }; f32 tp[4]; struct Moby *best = 0; f32 bestScore = 1.0e9f; @@ -90,7 +93,7 @@ struct Moby *select_sandmouse_projectile_target(struct Moby *moby, if (candidate_moby == 0 || candidate_moby->pclass == 0) continue; candidate_target_kind = ((TargetClass *)candidate_moby->pclass)->kind; - if (candidate_target_kind != 5 || hp == 0 || !(0.0f < *hp)) + if (candidate_target_kind != TARGET_KIND_LOCK_ON || hp == 0 || !(0.0f < *hp)) continue; candidate_distance = fast_vec_dist(from, &candidate_moby->pos); if (!(candidate_distance < range)) From 30c1bf8f0c3fbc2abd56cb13be54cdb7ffee6874 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:05:32 +0000 Subject: [PATCH 0730/1502] decomp: clarify names in cull_and_submit_water_grid_tile domain_0_value_0 -> WATER_TILE_MODE_SKIP_CLIP_TESTS: In snapshot SHA-256 822e7c7bb43212bc91f8a11e21817ff5313755b6f531d429beb6ad2928ca5f10, mode != 0 guards all corner construction, transforms and rejection tests. Retail 0x002b8ce8 branches on zero s4 directly to 0x002b8f30, skipping 0x002b8cf0..0x002b8f2c. Caller render_water_grids chooses zero when neither packed clip mask has relevant bits. domain_1_value_1 -> WATER_TILE_MODE_TEST_FAR_CLIP: Caller render_water_grids sets mode to (far_bits & 0x2f2f2f2f) != 0; its zero branch separately selects 2 or 0. Retail 0x002b8e7c..0x002b8e80 compares s4 with 1, selecting the branch that uses packed far mask s7 to clear s4 at 0x002b8ed4. Original Ghidra param_3 == 1 and uVar6 == 0 confirm that this mode tests the far clip result in addition to near-mask rejection. domain_2_value_0 -> WATER_TILE_MODE_SKIP_CLIP_TESTS: Within the mode-1 branch, source far_bits == 0 assigns mode = 0 after corner tests. Retail 0x002b8ed4 movz s4,zero,s7 clears the same incoming culling mode precisely when the packed far mask is zero; original Ghidra uVar6 == 0 assigns param_3 = 0. This reuses the zero mode that bypasses corner clip tests, rather than a VU entry selector. domain_3_value_0 -> WATER_TILE_MODE_SKIP_CLIP_TESTS: The non-1 branch performs common near-mask rejection and clears the incoming mode before submission selection. Retail 0x002b8f28 rejects the final common plane and 0x002b8f2c sets s4 to zero in its delay slot. Source mode = 0 and original Ghidra param_3 = 0 refer to the same zero culling mode used by the entry bypass, not numeric VU entry 0xc. domain_4_value_0 -> WATER_TILE_MODE_SKIP_CLIP_TESTS: Source final mode != 0 tests the culling mode after the two possible resets, then overwrites it with 0xe or 0xc. Retail 0x002b8f44 branches on zero s4 to 0x002b8f54, selecting 0xc; nonzero selects 0xe at 0x002b8f50. This zero comparison still belongs to the incoming clip-test mode domain; only the following assignments change to the helper's VU entry domain. --- src/overlays/shared/rendering/render_water_grids.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/rendering/render_water_grids.c b/src/overlays/shared/rendering/render_water_grids.c index aebb9bb63f..8553aef76a 100644 --- a/src/overlays/shared/rendering/render_water_grids.c +++ b/src/overlays/shared/rendering/render_water_grids.c @@ -66,6 +66,10 @@ void cull_and_submit_water_grid_tile(f32 *grid_center_position, s32 mode) __asm__("FUN_L01_002b8cb0"); void cull_and_submit_water_grid_tile(f32 *grid_center_position, s32 index, s32 mode) { + enum { + WATER_TILE_MODE_SKIP_CLIP_TESTS = 0, + WATER_TILE_MODE_TEST_FAR_CLIP = 1 + }; f32 corners[4][4]; f32 near_clip[4]; f32 far_clip[4]; @@ -76,7 +80,7 @@ void cull_and_submit_water_grid_tile(f32 *grid_center_position, s32 index, s32 m u32 near_bits, far_bits; s32 i, tile_vertex_offset, row, column; - if (mode != 0) { + if (mode != WATER_TILE_MODE_SKIP_CLIP_TESTS) { row = index >> 2; column = index & 3; half_x = 0.5f * -pool_light[2]; @@ -122,7 +126,7 @@ void cull_and_submit_water_grid_tile(f32 *grid_center_position, s32 index, s32 m far_bits = (far_bits << 8) | is_vector_outside_clip(far_clip); near_bits = (near_bits << 8) | is_vector_outside_clip(near_clip); } - if (mode == 1) { + if (mode == WATER_TILE_MODE_TEST_FAR_CLIP) { if ((near_bits & 0x01010101) == 0x01010101) return; if ((near_bits & 0x02020202) == 0x02020202) @@ -132,7 +136,7 @@ void cull_and_submit_water_grid_tile(f32 *grid_center_position, s32 index, s32 m if ((near_bits & 0x08080808) == 0x08080808) return; if (far_bits == 0) - mode = 0; + mode = WATER_TILE_MODE_SKIP_CLIP_TESTS; if ((near_bits & 0x20202020) == 0x20202020) return; } else { @@ -146,11 +150,11 @@ void cull_and_submit_water_grid_tile(f32 *grid_center_position, s32 index, s32 m return; if ((near_bits & 0x20202020) == 0x20202020) return; - mode = 0; + mode = WATER_TILE_MODE_SKIP_CLIP_TESTS; } } tile_vertex_offset = (index & 3) * 4 + (index >> 2) * 0x44; - if (mode != 0) { + if (mode != WATER_TILE_MODE_SKIP_CLIP_TESTS) { mode = 0xe; } else { mode = 0xc; From e4e7c78c3b8d860dededc9ddc2d557d12d496fb3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:05:32 +0000 Subject: [PATCH 0731/1502] decomp: clarify names in draw_timed_text domain_0_value_1 -> TEXT_SEPARATOR_JOIN_WITH_HYPHEN: Bound C snapshot src/overlays/shared/ui/text/draw_timed_text.c SHA-256 7150826abd923d6abf16c1eda4fc289a6c17d672b6bc6aee35e0137731fb1869 compares timed_text_entry->separator_mode to 1. Retail 0x001fcdd4 loads signed entry field +0xe; 0x001fcdd8-0x001fcddc compare it to 1 and branch to multiline handling when unequal. In the equal branch 0x001fcdf4-0x001fce1c writes 0x20,0x2d,0x20 for a separator run, 0x001fce30-0x001fce50 skips adjacent 0x01 bytes, and 0x001fce60-0x001fce64 removes a trailing join. 0x001fce7c-0x001fce98 terminates and draws the combined buffer once. Original Ghidra decompilation shows the same +0xe comparison and space-hyphen-space stores. The unequal path draws on each separator and advances y by 26 at 0x001fcedc-0x001fcee0. Thus this selector means join with hyphen; TRUE and TEXT_ALIGN_RIGHT are different domains. --- src/overlays/shared/ui/text/draw_timed_text.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/ui/text/draw_timed_text.c b/src/overlays/shared/ui/text/draw_timed_text.c index bf6f8277ee..6defbf6b6c 100644 --- a/src/overlays/shared/ui/text/draw_timed_text.c +++ b/src/overlays/shared/ui/text/draw_timed_text.c @@ -59,6 +59,9 @@ typedef struct { void draw_timed_text(LevelTextEntry *entry, s32 frame) __asm__("FUN_L00_001fcca0"); void draw_timed_text(LevelTextEntry *timed_text_entry, s32 frame) { + enum { + TEXT_SEPARATOR_JOIN_WITH_HYPHEN = 1 + }; int start = timed_text_entry->start; int end = start + timed_text_entry->duration; float scale, alpha; @@ -91,7 +94,7 @@ void draw_timed_text(LevelTextEntry *timed_text_entry, s32 frame) { alpha = 0.0f; } source = (unsigned char *)get_help_message_text(timed_text_entry->text_id); - if (timed_text_entry->separator_mode == 1) { + if (timed_text_entry->separator_mode == TEXT_SEPARATOR_JOIN_WITH_HYPHEN) { text_write_cursor = formatted_text; joined_text: while (*source != 0) { From 437d249e73108fb51a966681398318de37b17d06 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:07:24 +0000 Subject: [PATCH 0732/1502] decomp: clarify names in morphoray_update domain_0_value_1 -> MORPHORAY_WAIT_FOR_HERO: Retail 0x0030577c loads the selector byte from moby+0x20; 0x00305764 sets s2=1 and 0x00305780 dispatches that value to 0x00305840, the source MORPHORAY_WAIT_FOR_HERO branch. Initialization saves the position at 0x00305830-0x00305834 and stores the same s2 to moby+0x20 at 0x0030583c. Original Ghidra also assigns 1 to this field after initialization. This assignment enters the existing local enum state that checks hero proximity every tenth frame, rather than any hero state or mode domain. domain_1_value_2 -> MORPHORAY_WAIT_TO_REMOVE: Retail 0x00305920-0x00305930 starts scene 6, loads v0=2 and stores it to moby+0x20. That exact byte is the selector loaded at 0x0030577c and dispatched for value 2 at 0x003057a4 to 0x00305934, matching source MORPHORAY_WAIT_TO_REMOVE. The branch sets flags 0x41 while D_L14_0015F5C4 equals the state, otherwise saves as needed, queues messages and removes the moby at 0x003059b4. Original Ghidra confirms both the assignment and the value-2 removal path. Reuse the existing local enum member for this same selector. --- src/overlays/l14/mobys/morphoray_pickup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/morphoray_pickup.c b/src/overlays/l14/mobys/morphoray_pickup.c index dcdde375dd..b8616767b9 100644 --- a/src/overlays/l14/mobys/morphoray_pickup.c +++ b/src/overlays/l14/mobys/morphoray_pickup.c @@ -70,7 +70,7 @@ void morphoray_pickup_update(struct Moby *moby) { moby->rot.y = -1.5707964f; moby->pos.z = D_L14_00174568[0] + morphoray_ground_height_offset_gp; qcopy(morphoray_pvars, moby_bytes + 0x10); - moby->state = 1; + moby->state = MORPHORAY_WAIT_FOR_HERO; break; case MORPHORAY_PICKUP_WAIT_FOR_HERO: *(f32 *)(moby_bytes + 0x48) = @@ -91,7 +91,7 @@ void morphoray_pickup_update(struct Moby *moby) { *(s32 *)(morphoray_pvars + 0x18) = 0; grant_inventory_item(0x15, 1); start_scene(6); - moby->state = 2; + moby->state = MORPHORAY_WAIT_TO_REMOVE; break; case MORPHORAY_PICKUP_WAIT_TO_REMOVE: if (D_L14_0015F5C4 != state) { From 73302c33bed12bc9423453c02d0fac2ecc514fe8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:07:24 +0000 Subject: [PATCH 0733/1502] decomp: clarify names in resolve_follow_camera_orbit_path_collisions domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: The authoritative source binds hero_state=&hero (D_0013F350) and compares hero_state->vehicle_mode != 2. Retail 0x002e7ae0/0x002e7aec forms s0=0x0013F350, reads the hero moby at +0x2080 at 0x002e7af4, then lbu v1,0x20a4(s0) at 0x002e7b60 and compares against li v0,2 at 0x002e7b68-0x002e7b6c. Equality skips the retraction increment/hold block to 0x002e7c3c. This proves the selector is the Hero vehicle_mode byte, not current state or gravity mode. Supplied include/rnc/hero/hero_state.h domain declares HeroVehicleMode::HERO_VEHICLE_MODE_GIANT_CLANK=2; the authoritative neighboring update_follow_camera_orbit_after_collision already uses that member on hero.vehicle_mode to gate the same frame-scaled collision retraction. --- src/overlays/shared/camera/follow_camera_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/camera/follow_camera_setup.c b/src/overlays/shared/camera/follow_camera_setup.c index 5a610ff0c3..52f3d5c451 100644 --- a/src/overlays/shared/camera/follow_camera_setup.c +++ b/src/overlays/shared/camera/follow_camera_setup.c @@ -1311,7 +1311,7 @@ int resolve_follow_camera_orbit_path_collisions(unsigned char *camera_moby) { accumulated_radial_adjustment_distance, spd)) { found = 1; - if (hero_state->vehicle_mode != 2 && + if (hero_state->vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && absolute_float(D_0013CA40_lui[0]) > 0.05f) { fast_vec_sub(position_delta, step, save); fast_vec_normalize(position_delta, position_delta, 1.0f); From a76384d817c26bd7cd501010e988a6bd3526e517 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:07:24 +0000 Subject: [PATCH 0734/1502] decomp: clarify names in process_asteroid_hit domain_0_value_4 -> ASTEROID_WAIT_TO_RESPAWN: Retail 0x002e1364 saves incoming asteroid moby a0 in s2; 0x002e15d0 tests blob_data+0x40 (child), and for exhausted originals 0x002e15d8..0x002e15fc writes 4 to this moby's state byte +0x20, clears collision/visibility and restores saved scale. Checked caller asteroid_update passes the same moby at 0x002e18b8..0x002e18c0 and 0x002e193c..0x002e1944, and dispatches its byte +0x20 at 0x002e166c. Authoritative source already names this asteroid selector's case 4 ASTEROID_WAIT_TO_RESPAWN; that branch and retail 0x002e1b14..0x002e1b68 test the home sphere, then restore home position, collision and visibility and transition to reset state 3. This is the asteroid state domain, not HeroStateId/HERO_STATE_CROUCH. --- src/overlays/l13/mobys/asteroid.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/asteroid.c b/src/overlays/l13/mobys/asteroid.c index 6245b8e3ba..c9e9b2590a 100644 --- a/src/overlays/l13/mobys/asteroid.c +++ b/src/overlays/l13/mobys/asteroid.c @@ -144,6 +144,9 @@ void process_asteroid_hit(struct Moby *moby, float scale_ratio) __asm__("FUN_L13_002e1348"); void process_asteroid_hit(struct Moby *moby, char *blob_data, float scale_ratio) { + enum { + ASTEROID_WAIT_TO_RESPAWN = 4 + }; float split_velocity[4]; float split_spawn_position[4]; float nearby_effect_scale = scale_ratio * 7.0f; @@ -198,7 +201,7 @@ void process_asteroid_hit(struct Moby *moby, char *blob_data, float scale_ratio) moby->collision = 0; *(short *)(blob_data + 0x4C) = scale_game_frames(0x1E); } else if (*(int *)(blob_data + 0x40) == 0) { - moby->state = 4; + moby->state = ASTEROID_WAIT_TO_RESPAWN; moby->flags |= 1; moby->collision = 0; moby->visible = 0; From 732f3fe2073fdf0398d4b1a801d766bf88d9010a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:07:25 +0000 Subject: [PATCH 0735/1502] decomp: clarify names in update_moby_joint_attachments domain_0_value_5 -> STARFIGHTER_STATE_TRACTOR_BEAM: Retail 0x002e8d3c preserves parent a0 in s1; 0x002e8e48 loads its +0x20 state byte, and 0x002e8e58-0x002e8e60 compares 5 and forces attachment_joint_index=-1. The supplied update_qwarks_starfighter passes that same moby to this function and switches its state using the established STARFIGHTER_STATE_TRACTOR_BEAM=5 member; that branch updates/draws the tractor beam and controls the hero ship. This is the parent's current starfighter state, distinct from the +0xBC command selector. domain_1_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002e8ea4 loads the attachment pointer from attachment_data+0xF0 into s0; 0x002e8eb0 loads its +0x20 Moby state and 0x002e8eac/0x002e8eb4 skips pose updates when that state is 0xFE. The same state causes replacement at 0x002e8e78-0x002e8e98 and suppresses duplicate removal at 0x002e8f94-0x002e8fa8. Supplied mark_moby_for_removal explicitly writes MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END=0xFE to moby->state for moby>=moby_instance_end; the source binds the removal call to this helper. Thus this tests the common Moby removal-state byte, not a starfighter command or request state. domain_2_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002e8ea4 loads the optional attachment Moby into s0 and 0x002e8eb0 loads its +0x20 state; 0x002e8eb8-0x002e8ebc skips pose updates for 0xFD. The same state permits replacement at 0x002e8e84-0x002e8e98 and suppresses repeated removal at 0x002e8f9c-0x002e8fa8. Supplied mark_moby_for_removal writes MOBY_STATE_REMOVAL_BELOW_INSTANCE_END=0xFD to moby->state exactly when mobycommand]; - if (parent_moby->state == 5) + if (parent_moby->state == STARFIGHTER_STATE_TRACTOR_BEAM) attachment_joint_index = -1; if (attachment_joint_index != -1) { if (*(char **)(attachment_data + 0xF0) == 0 || @@ -280,8 +285,8 @@ void update_moby_joint_attachments(struct Moby *parent_moby, char *attachment_da *(char **)(attachment_data + 0xF0) = spawn_moby_joint_attachment(parent_moby, attachment_joint_index, 0x191); attached_moby = *(char **)(attachment_data + 0xF0); - if (attached_moby != 0 && MOBY(attached_moby)->state != 0xFE && - MOBY(attached_moby)->state != 0xFD) { + if (attached_moby != 0 && MOBY(attached_moby)->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + MOBY(attached_moby)->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { moby_point_position(parent_moby, attachment_joint_index, attached_moby + 0x10); if (MOBY(attached_moby)->pos.x < 22.0f) MOBY(attached_moby)->pos.x = 22.0f; From b5ee8ae2de4a4da50775876790684a96aafcdde3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:07:25 +0000 Subject: [PATCH 0736/1502] decomp: clarify names in update_hero_surface_condition_flags domain_0_value_2 -> HERO_GROUND_TYPE_MAGNETIC: Authoritative source binds state to hero_object_ptr->ground_type. Retail 0x23c7d4 loads that signed halfword from hero +0x12E0 into s2, and 0x23c7f4-0x23c7f8 compares s2 with 2. The matching branch tests frames_off_ground (+0x30C) or ground_distance (+0x2DC) before setting on_magnet_ground at +0x12E7 (0x23c838); original Ghidra confirms the same conditional flag write. This is a magnetic ground classification, separate from hero current state. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source explicitly compares hero_object_ptr->vehicle_mode to zero. Retail 0x23c830 loads byte +0x20A4 from the established hero base and 0x23c834 skips the equipped-item check when nonzero. This exact field is the HeroVehicleMode selector, as corroborated by the supplied source's other hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT uses and hero_set_state context. Reuse the supplied canonical HeroVehicleMode member with value 0, independently of ground_type and current-state IDs. domain_3_value_0 -> HERO_GROUND_TYPE_WATER: Retail 0x23c7d4 loads ground_type (+0x12E0) into s2; 0x23c890 branches on s2 != 0. In the zero branch, 0x23c8a8-0x23c8c0 computes water_surface_z (+0x2F0) minus ground_z (+0x2D8) and stores water_depth (+0x22A4); 0x23c8b4 and 0x23c8d0 bound that depth between 0.25 and 0.85 before setting wading at 0x23c8e0. Original Ghidra and the authoritative C agree, proving the water ground classification without confusing it with HERO_STATE_IDLE. --- src/overlays/l11/hero/update_hero_motion_by_state.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l11/hero/update_hero_motion_by_state.c b/src/overlays/l11/hero/update_hero_motion_by_state.c index 1b9dcea7ca..5c7e8e70cb 100644 --- a/src/overlays/l11/hero/update_hero_motion_by_state.c +++ b/src/overlays/l11/hero/update_hero_motion_by_state.c @@ -34,6 +34,10 @@ float absolute_float(float input) __asm__("func_001F99C0"); void update_hero_surface_condition_flags(void) __asm__("FUN_L11_0023c7a0"); void update_hero_surface_condition_flags(void) { + enum { + HERO_GROUND_TYPE_WATER = 0, + HERO_GROUND_TYPE_MAGNETIC = 2 + }; struct Hero *hero_object_ptr = &hero; unsigned char saved; int state; @@ -46,10 +50,10 @@ void update_hero_surface_condition_flags(void) { hero_object_ptr->unk308 = 0; if (state == -1) return; - if (state == 2) { + if (state == HERO_GROUND_TYPE_MAGNETIC) { if (hero_object_ptr->frames_off_ground.s == 0 || hero_object_ptr->ground_distance < 0.3f) { hero_object_ptr->on_magnet_ground = 1; - if (hero_object_ptr->vehicle_mode == 0) { + if (hero_object_ptr->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (((int)hero_object_ptr->items[1].moby) != 0 && *(short *)(((int)hero_object_ptr->items[1].moby) + 0xA6) == 0xAD) hero_object_ptr->unk308 = 1; @@ -62,7 +66,7 @@ void update_hero_surface_condition_flags(void) { hero_ptr->water_depth = 0.2f; hero_ptr->water_surface_z = hero_ptr->ground_z.f + 0.2f; } - if (state == 0) { + if (state == HERO_GROUND_TYPE_WATER) { struct Hero *hero_ptr = &hero; struct Hero *base_condition_hero_ptr; float water_surface_to_ground_z_difference = From 590d5409ca75533310ba4a8dfc6ccbf11318c7f8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:07:25 +0000 Subject: [PATCH 0737/1502] decomp: clarify names in enemy_fighter_update domain_0_value_2 -> ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN: The hit guard loads moby+0x20 at 0x002fc128 and compares it to 2 at 0x002fc12c-0x002fc130. This is the same byte loaded at 0x002fc214 for the existing state switch; its case 2 reaches the respawn timer test at 0x002fc2e4. Thus the guard excludes the existing ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN state. domain_1_value_2 -> ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN: Retail 0x002fc1ac stores 2 into moby+0x20 on a hit, followed by collision clearing at 0x002fc1c4 and flags 0x41. The same byte is dispatched at 0x002fc214-0x002fc23c to case 2, whose timer gates collision and first-path-pose restoration at 0x002fc2e4-0x002fc380. This enters the existing WAIT_FOR_RESPAWN state. domain_2_value_1 -> ENEMY_FIGHTER_STATE_FOLLOW_PATH: After path validation and initialize_flight_path_state at 0x002fc2a4, retail 0x002fc2b0 stores s3=1 into moby+0x20. The state dispatcher compares that same byte against s3 at 0x002fc21c and branches to advance_enemy_fighter_along_flight_path at 0x002fc2d4, the existing ENEMY_FIGHTER_STATE_FOLLOW_PATH case. domain_3_value_1 -> ENEMY_FIGHTER_STATE_FOLLOW_PATH: After the state-2 timer expires, retail 0x002fc330 stores s3=1 into moby+0x20 while restoring collision, clearing path progress and copying the first path pose (0x002fc324-0x002fc380). The same state-byte value 1 dispatches to the flight-path advance call at 0x002fc21c/0x002fc2d4, so this resumes the existing FOLLOW_PATH state. domain_4_value_0 -> ENEMY_FIGHTER_STATE_INITIALIZE: The trailing voice guard reads moby+0x20 at 0x002fc38c and excludes zero at 0x002fc390. The dispatcher reads the identical byte at 0x002fc214 and sends zero through 0x002fc22c to path validation and initialization at 0x002fc24c-0x002fc2d0, already named ENEMY_FIGHTER_STATE_INITIALIZE in the authoritative source. domain_5_value_2 -> ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN: The trailing voice guard compares the moby+0x20 byte with 2 at 0x002fc394-0x002fc398 before voice playback/allocation. The same byte and value select the existing WAIT_FOR_RESPAWN case at 0x002fc214-0x002fc23c, reaching the timer and restoration branch at 0x002fc2e4-0x002fc380. This excludes voice allocation during respawn waiting. --- src/overlays/l14/mobys/enemy_fighter.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l14/mobys/enemy_fighter.c b/src/overlays/l14/mobys/enemy_fighter.c index 86842eb8ec..c552d9e8d3 100644 --- a/src/overlays/l14/mobys/enemy_fighter.c +++ b/src/overlays/l14/mobys/enemy_fighter.c @@ -73,7 +73,7 @@ void enemy_fighter_update(struct Moby *moby) { int path_index; char *path; moby->hit_slot = 0xff; - if (hit && moby->state != 2) { + if (hit && moby->state != ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN) { if (current_level_index == 14) { enemy_fighter_destruction_count = enemy_fighter_destruction_count + 1; if (enemy_fighter_destruction_count > 2 && D_0013D408.flag == 0) { @@ -82,7 +82,7 @@ void enemy_fighter_update(struct Moby *moby) { queue_dialogue_message(0x53d6, -1); } } - moby->state = 2; + moby->state = ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN; cart_burst(5.0f, 13.0f, moby, &moby->pos, -1); moby->collision = 0; moby->flags |= 0x41; @@ -109,7 +109,7 @@ void enemy_fighter_update(struct Moby *moby) { return; } initialize_flight_path_state(moby); - moby->state = 1; + moby->state = ENEMY_FIGHTER_STATE_FOLLOW_PATH; moby->update_dist = 0xff; moby->draw_dist = 0xff; enemy_fighter_vars->sound = -1; @@ -124,7 +124,7 @@ void enemy_fighter_update(struct Moby *moby) { moby->flags &= 0xffbe; moby->collision = moby->pclass->collision; enemy_fighter_vars->timer = scale_game_frames(enemy_fighter_respawn_delay_frames_gp); - moby->state = 1; + moby->state = ENEMY_FIGHTER_STATE_FOLLOW_PATH; enemy_fighter_vars->segment = 0; enemy_fighter_vars->along = 0; qcopy(&moby->pos, path + 0x10); @@ -136,7 +136,7 @@ void enemy_fighter_update(struct Moby *moby) { break; } spawn_enemy_fighter_exhaust(moby); - if (moby->state != 0 && moby->state != 2 && + if (moby->state != ENEMY_FIGHTER_STATE_INITIALIZE && moby->state != ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN && voice_is_playing(moby, enemy_fighter_vars->sound) == 0) enemy_fighter_vars->sound = allocate_voice_for_target_entry(0, 4, moby); } From 469f083423f69f5ea1b28bcddf568b5b371ccf46 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:07:25 +0000 Subject: [PATCH 0738/1502] decomp: clarify names in sceMpegDemuxPssRing domain_0_value_6 -> MPEG_CALLBACK_PES_PACKET: Source assigns cb.type=6 after _PES_packet fills pss_header->pes and masked stream-id matching succeeds. Retail 0x0012ad34 parses the PES header; 0x0012ad74-0x0012ad84 performs masked matching; 0x0012ace0 stores 6 to callback offset 0. 0x0012acdc-0x0012ad20 supplies PES header/data ring pointers, data length, PTS and DTS to the registered callback. Thus this cb.type value tags a parsed PES packet callback payload. domain_1_value_6 -> MPEG_CALLBACK_PES_PACKET: Source fallback branch uses the same sceMpegCbDataStr cb and copies the parsed PES header/data pointers, datalen, pts and dts before cbfunc(mp,&cb,cbdata). Retail 0x0012ad98-0x0012ada0 selects fallback when no stream table entry matched; 0x0012adb0 stores the same s8=6 at callback offset 0; 0x0012adac-0x0012adf0 constructs the same PES metadata payload and invokes the saved callback. This proves the same PES packet callback type as the matched path. --- src/sdk/mpeg/api/sce_mpeg_demux_pss_ring.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sdk/mpeg/api/sce_mpeg_demux_pss_ring.c b/src/sdk/mpeg/api/sce_mpeg_demux_pss_ring.c index 6a9a2b53d0..c521456d21 100644 --- a/src/sdk/mpeg/api/sce_mpeg_demux_pss_ring.c +++ b/src/sdk/mpeg/api/sce_mpeg_demux_pss_ring.c @@ -69,6 +69,9 @@ extern void _sysbitInit(SysBit *bs, u8 *start, u8 *bufstart, s32 bufsize); extern u8 *GetSysbitPointer(SysBit *bs, s32 pos); int sceMpegDemuxPssRing(sceMpeg *mp, u8 *start, int size, u8 *bufstart, int bufsize) { + enum { + MPEG_CALLBACK_PES_PACKET = 6 + }; SysBit bs; PssHdr hdr; SysBit *bitstream; @@ -116,7 +119,7 @@ int sceMpegDemuxPssRing(sceMpeg *mp, u8 *start, int size, u8 *bufstart, int bufs for (i = 0; i < sys->n; i++) { if (tbl[i].id == (pss_header->pes.id & tbl[i].mask)) { headerpos = pss_header->pes.header; - cb.type = 6; + cb.type = MPEG_CALLBACK_PES_PACKET; cb.header = GetSysbitPointer(bitstream, headerpos); cb.data = GetSysbitPointer(bitstream, pss_header->pes.data); cb.len = pss_header->pes.datalen; @@ -128,7 +131,7 @@ int sceMpegDemuxPssRing(sceMpeg *mp, u8 *start, int size, u8 *bufstart, int bufs } if (i == sys->n && cbfunc != 0) { headerpos = pss_header->pes.header; - cb.type = 6; + cb.type = MPEG_CALLBACK_PES_PACKET; cb.header = GetSysbitPointer(bitstream, headerpos); cb.data = GetSysbitPointer(bitstream, pss_header->pes.data); cb.len = pss_header->pes.datalen; From 13dd662698fdd640fc3233acf95444dca9df7130 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:09:12 +0000 Subject: [PATCH 0739/1502] decomp: clarify names in update_hoven_scrolling_texture_layers domain_0_value_1 -> UPDATE_SCROLL_PHASES_AND_QUEUE_DRAW: Retail 0x0030c00c reads the moby's byte at +0x20, and 0x0030c014-0x0030c018 compares that byte to 1 to enter 0x0030c10c. Initialization loads 1 at 0x0030c0bc and stores it to the identical +0x20(s0) byte at 0x0030c0c8. Original Ghidra shows the same store and subsequent state-1 branch. The authoritative C already names that same moby->state case UPDATE_SCROLL_PHASES_AND_QUEUE_DRAW = 1; its branch integrates phase rates times frame_delta_time, wraps phases at +/-1 (0x0030c140-0x0030c2b0), and queues draw_hoven_scrolling_texture_layers with this moby at 0x0030c2b4-0x0030c2bc. Thus the assignment reuses the established constant in its exact local selector domain. --- src/overlays/l12/mobys/scrolling_texture_layers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l12/mobys/scrolling_texture_layers.c b/src/overlays/l12/mobys/scrolling_texture_layers.c index 3f9f585487..e73cbfda21 100644 --- a/src/overlays/l12/mobys/scrolling_texture_layers.c +++ b/src/overlays/l12/mobys/scrolling_texture_layers.c @@ -2601,7 +2601,7 @@ void scrolling_texture_layers_update(M_bff0 *moby) { 1); hoven_scrolling_color_tables_initialized_gp = 1; } - moby->state = 1; + moby->state = UPDATE_SCROLL_PHASES_AND_QUEUE_DRAW; moby->b30 = 0xFF; moby->h32 = 0xFF; for (i = 0; i < 2; i++) { From 2ee950b4799fccc163eefcdd363023b0a8a6d519 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:09:12 +0000 Subject: [PATCH 0740/1502] decomp: clarify names in draw_hero_glow_quads domain_3_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00207DD8 forms hero base 0x0013F350 and 0x00207DDC loads its byte +0x20A4 into v1; 0x00207E30 tests that same v1 against zero. Source P aliases D_0013F350 and P.b20A4 has offset 0x20A4, identical to typed hero.vehicle_mode in the supplied idle-sequence and vehicle-update source. This establishes HeroVehicleMode, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT. This branch draws slot-three item glow and queued hero/item glow quads. domain_4_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x00207DDC loads hero+0x20A4 into v1; s1 was set to 2 at 0x00207D54 and 0x00207F04 compares v1 with s1. P.b20A4 aliases typed hero.vehicle_mode at the same hero base and offset in the supplied source, proving the HeroVehicleMode domain. Reuse canonical HERO_VEHICLE_MODE_GIANT_CLANK=2 from include/rnc/hero/hero_state.h. Branch 0x00207F0C-0x00207F54 draws the +0x1D80 point with scale 0.25 and a temporary -0.07 Z offset, matching the mode-two position producer in update_hero_in_vehicle_mode. domain_5_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail v1 retains the hero+0x20A4 byte loaded at 0x00207DDC; 0x00207F08 sets v0=1 and 0x00207F58 tests v1 against it. Authoritative P.b20A4 is the same storage as typed hero.vehicle_mode in the supplied source, proving HeroVehicleMode rather than HeroStateId. Reuse canonical HERO_VEHICLE_MODE_CLANK=1. This branch eases hero+0x162C and uses it as the +0x1D80 quad scale at 0x00208008-0x00208010; supplied vehicle-mode-one producer fills that position from moby point 7 and maintains its +0x2300 color. --- src/overlays/shared/hero/hero_idle_sequence.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index 5702b6f55b..bba99f37d7 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -1665,7 +1665,7 @@ void draw_hero_glow_quads(void) { } return; } - if (vehicle_mode == 0) { + if (vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if ((hero_slot_item_id(3) == 3 || hero_slot_item_id(3) == 2) && P.h22D8 == 0) { P.v1D80.f[2] += 0.015f; draw_offset_textured_effect_quad(&P.v1D80, 0x280000C0, 0.057f, 0.08f); @@ -1675,13 +1675,13 @@ void draw_hero_glow_quads(void) { draw_offset_textured_effect_quad(&P.v1DD0[i], P.i1E50[i], P.f1E70[i], P.f1E90[i]); return; } - if (vehicle_mode == 2) { + if (vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { P.v1D80.f[2] -= 0.07f; draw_offset_textured_effect_quad(&P.v1D80, 0x300000C0, 0.25f, 0.08f); P.v1D80.f[2] += 0.07f; return; } - if (vehicle_mode == 1) { + if (vehicle_mode == HERO_VEHICLE_MODE_CLANK) { k = 0.07f; if (P.h22FC) k = 0.101500004529953f; From b8e5abd112b5b16a90812b2a0576fc5cbf776608 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:09:12 +0000 Subject: [PATCH 0741/1502] decomp: clarify names in update_controller_linked_gate domain_0_value_1 -> GATE_STATE_OPEN: Retail 0x002f8ab0 loads this moby's +0x20 byte for switch dispatch at 0x002f8b38-0x002f8b54; the authoritative C names that selector's local enum GATE_STATE_*. This assignment stores to the identical +0x20 state byte, not the linked controller's state. At 0x002f8bb8-0x002f8bd8 initialization writes state 1 with private fraction +0x10 set to 1.0, alpha 20 and class collision restored, selecting the existing OPEN case. domain_1_value_3 -> GATE_STATE_CLOSED: Retail 0x002f8ab0 loads this moby's +0x20 byte for switch dispatch at 0x002f8b38-0x002f8b54; the authoritative C names that selector's local enum GATE_STATE_*. This assignment stores to the identical +0x20 state byte, not the linked controller's state. At 0x002f8bdc-0x002f8bec initialization writes state 3 with fraction +0x10 zero, collision zero and alpha zero, selecting the existing CLOSED case. domain_2_value_2 -> GATE_STATE_CLOSING: Retail 0x002f8ab0 loads this moby's +0x20 byte for switch dispatch at 0x002f8b38-0x002f8b54; the authoritative C names that selector's local enum GATE_STATE_*. This assignment stores to the identical +0x20 state byte, not the linked controller's state. At 0x002f8bf0-0x002f8c00 the OPEN case responds to the close-list match by clearing collision and writing state 2; that existing CLOSING case decreases fraction +0x10 toward zero. domain_3_value_4 -> GATE_STATE_OPENING: Retail 0x002f8ab0 loads this moby's +0x20 byte for switch dispatch at 0x002f8b38-0x002f8b54; the authoritative C names that selector's local enum GATE_STATE_*. This assignment stores to the identical +0x20 state byte, not the linked controller's state. At 0x002f8c04-0x002f8c18 the CLOSING case responds to the open-list match by writing state 4 and restoring class collision; the existing OPENING case increases fraction +0x10 toward one. domain_4_value_3 -> GATE_STATE_CLOSED: Retail 0x002f8ab0 loads this moby's +0x20 byte for switch dispatch at 0x002f8b38-0x002f8b54; the authoritative C names that selector's local enum GATE_STATE_*. This assignment stores to the identical +0x20 state byte, not the linked controller's state. At 0x002f8c40-0x002f8c70 the CLOSING fraction underflows zero, is clamped to zero, and state 3 is stored while collision and visibility are cleared; this selects the existing CLOSED case. domain_5_value_4 -> GATE_STATE_OPENING: Retail 0x002f8ab0 loads this moby's +0x20 byte for switch dispatch at 0x002f8b38-0x002f8b54; the authoritative C names that selector's local enum GATE_STATE_*. This assignment stores to the identical +0x20 state byte, not the linked controller's state. At 0x002f8c74-0x002f8ca0 the CLOSED case responds to the open-list match by writing state 4, restoring collision and visibility, and clearing flag bit 0; this selects the existing OPENING fraction-increment case. domain_6_value_2 -> GATE_STATE_CLOSING: Retail 0x002f8ab0 loads this moby's +0x20 byte for switch dispatch at 0x002f8b38-0x002f8b54; the authoritative C names that selector's local enum GATE_STATE_*. This assignment stores to the identical +0x20 state byte, not the linked controller's state. At 0x002f8ca4-0x002f8cb0 the OPENING case responds to the close-list match by clearing collision and writing state 2, selecting the existing CLOSING fraction-decrement case. domain_7_value_1 -> GATE_STATE_OPEN: Retail 0x002f8ab0 loads this moby's +0x20 byte for switch dispatch at 0x002f8b38-0x002f8b54; the authoritative C names that selector's local enum GATE_STATE_*. This assignment stores to the identical +0x20 state byte, not the linked controller's state. At 0x002f8cdc-0x002f8d00 the OPENING fraction exceeds one, is clamped to one, and state 1 is stored with class collision restored; this selects the existing OPEN case. --- src/overlays/l13/mobys/controller_linked_gate.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l13/mobys/controller_linked_gate.c b/src/overlays/l13/mobys/controller_linked_gate.c index fb9a9477ec..25c160f14f 100644 --- a/src/overlays/l13/mobys/controller_linked_gate.c +++ b/src/overlays/l13/mobys/controller_linked_gate.c @@ -70,12 +70,12 @@ void controller_linked_gate_update(struct Moby *moby) { moby->flags |= 0xA08; if (gate_data->unk18 == 0) { gate_data->unk10 = 1.0f; - moby->state = 1; + moby->state = GATE_STATE_OPEN; moby->collision = moby->pclass->collision; moby->alpha = 0x14; } else { gate_data->unk10 = 0.0f; - moby->state = 3; + moby->state = GATE_STATE_CLOSED; moby->collision = 0; moby->alpha = 0; } @@ -83,18 +83,18 @@ void controller_linked_gate_update(struct Moby *moby) { case GATE_STATE_OPEN: if (close) { moby->collision = 0; - moby->state = 2; + moby->state = GATE_STATE_CLOSING; } break; case GATE_STATE_CLOSING: if (open) { - moby->state = 4; + moby->state = GATE_STATE_OPENING; moby->collision = moby->pclass->collision; } gate_data->unk10 -= frame_scale * 0.05f; if (gate_data->unk10 < 0.0f) { gate_data->unk10 = 0.0f; - moby->state = 3; + moby->state = GATE_STATE_CLOSED; moby->collision = 0; moby->visible = 0; moby->flags |= 1; @@ -102,7 +102,7 @@ void controller_linked_gate_update(struct Moby *moby) { break; case GATE_STATE_CLOSED: if (open) { - moby->state = 4; + moby->state = GATE_STATE_OPENING; moby->collision = moby->pclass->collision; moby->visible = 1; moby->flags &= 0xFFFE; @@ -111,12 +111,12 @@ void controller_linked_gate_update(struct Moby *moby) { case GATE_STATE_OPENING: if (close) { moby->collision = 0; - moby->state = 2; + moby->state = GATE_STATE_CLOSING; } gate_data->unk10 += frame_scale * 0.05f; if (1.0f < gate_data->unk10) { gate_data->unk10 = 1.0f; - moby->state = 1; + moby->state = GATE_STATE_OPEN; moby->collision = moby->pclass->collision; } break; From c4de9398ba6623782111199bf48a34b4a13af056 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:09:12 +0000 Subject: [PATCH 0742/1502] decomp: clarify names in update_robot_dog_hit_reaction_and_target_detection domain_0_value_0 -> ROBOT_DOG_STATE_INITIALIZE: The authoritative robot_dog.c snapshot (SHA-256 d05b868b255d8d007963dc641c74704a712cfaa5ed6c69588a7a333ff2c584e3) defines RobotDogState for the robot-dog state byte +0x20, with ROBOT_DOG_STATE_INITIALIZE=0. robot_dog_update passes robot_dog_moby unchanged to this helper and dispatches that same +0x20 byte using this enum; its INITIALIZE branch saves home, initializes reaction/animation fields and advances to 1. Retail 0x002efa5c preserves a0 in s1; 0x002efa6c loads byte +0x20(s1), and 0x002efa70 returns when zero. Original Ghidra confirms the zero-state guard. This is the same robot-dog state domain, not a hero state, class ID or mode. domain_1_value_15 -> ROBOT_DOG_STATE_FALL_THEN_REMOVE: robot_dog_update passes the same robot_dog_moby to this helper and later switches on its +0x20 state byte; the authoritative source defines ROBOT_DOG_STATE_FALL_THEN_REMOVE=0xF in RobotDogState. That named caller branch steps motion, emits break effects and removes the moby upon landing, or removes it below z=2. Retail 0x002efb10 loads 0xF, 0x002efb14 reads +0x20(s1), and 0x002efb18 skips further knockback setup when equal. Original Ghidra confirms the state!=0xF guard. This comparison therefore reuses the canonical robot-dog FALL_THEN_REMOVE state. domain_2_value_15 -> ROBOT_DOG_STATE_FALL_THEN_REMOVE: The same moby pointer passed by robot_dog_update is retained in s1 at 0x002efa5c. After trooper_start_knockback at 0x002efc10, retail 0x002efc18 loads 0xF and 0x002efc20 stores it to +0x20(s1), then updates the reaction animation. Original Ghidra confirms *(undefined1 *)(iVar6+0x20)=0xf. The caller dispatches this exact state byte through existing RobotDogState, whose ROBOT_DOG_STATE_FALL_THEN_REMOVE=0xF branch steps falling motion and removes the moby on landing or below z=2. This assignment enters that established state and must reuse the same member as its comparison. --- src/overlays/l17/mobys/robot_dog.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l17/mobys/robot_dog.c b/src/overlays/l17/mobys/robot_dog.c index 4b15bce3de..7a83a43907 100644 --- a/src/overlays/l17/mobys/robot_dog.c +++ b/src/overlays/l17/mobys/robot_dog.c @@ -615,7 +615,7 @@ void update_robot_dog_hit_reaction_and_target_detection(void *moby_v, int clip_v float target_heading; moby_vars = moby->data; - if (moby->state == 0) { + if (moby->state == ROBOT_DOG_STATE_INITIALIZE) { return; } if (moby_vars->i38 != 0) { @@ -626,7 +626,7 @@ void update_robot_dog_hit_reaction_and_target_detection(void *moby_v, int clip_v y = 0; hit_record = (Hit_2F1558 *)find_moby_hit(moby, 0x330000, 0); hit_reaction(moby, hit_record, &moby_vars->f20, 0, &x, &y, 0, 4); - if (x != 1 && moby->state != 15) { + if (x != 1 && moby->state != ROBOT_DOG_STATE_FALL_THEN_REMOVE) { moby_vars->f20 -= y; moby_vars->f130 = frame_time_sq * 42.0f; moby_vars->f134 = frame_time_sq * 24.0f; @@ -644,7 +644,7 @@ void update_robot_dog_hit_reaction_and_target_detection(void *moby_v, int clip_v fast_arc_tan(moby_vars->f1F0 - moby->pos[0], moby_vars->f1F4 - moby->pos[1]); } trooper_start_knockback(knockback_heading, moby, moby_vars->v120, 0xB, 1, 0); - moby->state = 15; + moby->state = ROBOT_DOG_STATE_FALL_THEN_REMOVE; moby_vars->b117 = 0xF0; trooper_anim_update(moby, moby_vars->h110); } From 1af60d040d78464ae21a265a821d5b4fa8f4916f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:10:58 +0000 Subject: [PATCH 0743/1502] decomp: clarify names in update_rocket_moby domain_0_value_0 -> ROCKET_STATE_FLYING: Retail 0x002d50ac loads the rocket moby's state byte at s5+0x20 and 0x002d50b0 returns for nonzero. Its zero branch computes the target-directed flight step at 0x002d50f8-0x002d51d0, spawns rocket trail at 0x002d51d8, advances position and orientation at 0x002d51e0-0x002d523c, increments the flight counter and tests segment collision at 0x002d5240-0x002d5260, then explodes/removes on collision or end frame at 0x002d52ac-0x002d52c8. Supplied create_rocket_moby initializes moby[0x20]=0 alongside initial movement, target and frame limit. Thus zero is the rocket's flying state; the selector is the rocket Moby state rather than any supplied hero enum domain. --- src/overlays/l18/mobys/rocket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/rocket.c b/src/overlays/l18/mobys/rocket.c index 7e5cda4f10..a598b10447 100644 --- a/src/overlays/l18/mobys/rocket.c +++ b/src/overlays/l18/mobys/rocket.c @@ -48,7 +48,7 @@ void rocket_moby_update(struct Moby *moby) __asm__("FUN_L18_002d5050"); /* Moby class 564 */ void rocket_moby_update(struct Moby *moby) { - L18D *moby_vars = (L18D *)moby->pvars; + enum { ROCKET_STATE_FLYING = 0 } ;L18D *moby_vars = (L18D *)moby->pvars; float target_movement_step[4]; float movement_step[4]; float rotation_angles[4]; @@ -60,7 +60,7 @@ void rocket_moby_update(struct Moby *moby) { int movement_collision_result; if (hero.state.current == 0x72 || D_L18_0015F5C4 == 2) { mark_moby_for_removal(moby); - } else if (moby->state == 0) { + } else if (moby->state == ROCKET_STATE_FLYING) { qcopy(previous_position, &moby->pos); movement_blend_weight = convert_integer_to_float(moby_vars->c); movement_blend_weight = movement_blend_weight / convert_integer_to_float(moby_vars->lim); From 89bbb3230ef667b23c31c1b1071e5d30f0731ddc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:10:58 +0000 Subject: [PATCH 0744/1502] decomp: clarify names in set_pal_mode domain_0_value_0 -> FALSE: Retail 0x001f3514 loads the established pal_mode global (Ghidra g_nPalVideoMode), and 0x001f3518 branches on equality to zero to 0x001f356c. That zero branch selects setup_fs_aa_buffer(512,416,512,448,0,0) at 0x001f3588-0x001f35b0; the nonzero branch selects the PAL layout (512,448,512,512,4,0) at 0x001f3538-0x001f3560. Thus the source pal_mode != 0 tests whether PAL mode is enabled, and the existing FALSE=0 constant accurately names its disabled boolean value, rather than NULL or a speculative video-standard enum. --- src/movies/display/set_pal_mode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/movies/display/set_pal_mode.c b/src/movies/display/set_pal_mode.c index 8d217b21bd..43959835cd 100644 --- a/src/movies/display/set_pal_mode.c +++ b/src/movies/display/set_pal_mode.c @@ -30,7 +30,7 @@ void set_pal_mode(void) { s16 display_width; FlushCache(0); - if (pal_mode != 0) { + if (pal_mode != FALSE) { draw_buffer_address = 0x100000; depth_buffer_address = 0x1E0000; display_buffer_address = 0; From 4c709d6f2805bbaaa29e7f2b15305fef2bde64a7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:10:58 +0000 Subject: [PATCH 0745/1502] decomp: clarify names in switch_active_camera_record domain_14_value_3 -> CAMERA_DESCRIPTOR_INHERIT_TRANSFORM: Retail 0x001ec064 tests the descriptor byte against 3 and branches to 0x001ec078. Instructions 0x001ec07c..0x001ec0a8 copy four 16-byte transform vectors from previous_camera to next_camera; 0x001ec0b0 sets incoming handoff_state. Unlike descriptor 6, descriptor 3 does not itself request the additional rate configuration. domain_15_value_6 -> CAMERA_DESCRIPTOR_INHERIT_TRANSFORM_WITH_RATE_TRANSITION: Retail 0x001ec06c tests descriptor_kind 6 to enter the four-vector outgoing-to-incoming transform copy at 0x001ec07c..0x001ec0a8. The second test at 0x001ec0c8 selects 0x001ec0d0..0x001ec158, which configures both position/rotation rates from incoming duration or defaults, sets rate-based transition mode, and advances the preview transition phase. domain_16_value_2 -> CAMERA_HANDOFF_INHERITED_TRANSFORM: Retail 0x001ec07c..0x001ec0a8 copies previous_camera's position and three matrix vectors to next_camera. Immediately afterward 0x001ec0ac..0x001ec0b0 stores 2 to next_camera +0x7d, the handoff_state byte. The value marks the incoming record whose transform has been inherited from the outgoing record. domain_18_value_6 -> CAMERA_DESCRIPTOR_INHERIT_TRANSFORM_WITH_RATE_TRANSITION: Retail 0x001ec06c tests descriptor_kind 6 to enter the four-vector outgoing-to-incoming transform copy at 0x001ec07c..0x001ec0a8. The second test at 0x001ec0c8 selects 0x001ec0d0..0x001ec158, which configures both position/rotation rates from incoming duration or defaults, sets rate-based transition mode, and advances the preview transition phase. domain_19_value_0 -> CAMERA_TRANSITION_RATE_BASED: Retail 0x001ebfcc and 0x001ec0ec store zero to preview_camera +0x273 (transition_mode) on paths writing float position and rotation rates at +0x288/+0x294 from positive incoming duration or defaults. This contrasts with the separate frame-count mode at the same selector and proves a rate-based mode without equating it with descriptor or record-state values. domain_24_value_0 -> CAMERA_HANDOFF_NONE: Retail 0x001ec170 clears previous_camera +0x7d (handoff_state) together with outgoing transition_state and activation_blocked before retaining it as preview_camera.previous at 0x001ec18c. In the same function, the inherited-transform incoming handoff is explicitly marked 2 at 0x001ec0b0; zero clears that outgoing handoff indication. domain_3_value_1 -> CAMERA_DESCRIPTOR_RATE_TRANSITION: Retail 0x001ebf5c..0x001ebf68 resolves next_camera descriptor_index through a 0x20-byte table record and loads descriptor_kind at +0x1d. Tests at 0x001ebf94 and 0x001ebfa8 select 0x001ebfb0..0x001ebff4, which configure both position/rotation rates from positive incoming duration or 0.018 and select the rate-based transition mode. This is a descriptor-kind domain, not the outgoing transition-state domain. domain_4_value_5 -> CAMERA_DESCRIPTOR_FRAME_COUNT_TRANSITION: The descriptor byte loaded at retail 0x001ebf68 is tested against 5 at 0x001ebf9c and 0x001ebff8. Its branch at 0x001ec000..0x001ec030 sets preview transition_mode to 2 and configured_frames to the converted positive incoming duration or 40. These operations prove frame-count transition configuration for this descriptor kind. domain_5_value_1 -> CAMERA_DESCRIPTOR_RATE_TRANSITION: Retail 0x001ebf5c..0x001ebf68 resolves next_camera descriptor_index through a 0x20-byte table record and loads descriptor_kind at +0x1d. Tests at 0x001ebf94 and 0x001ebfa8 select 0x001ebfb0..0x001ebff4, which configure both position/rotation rates from positive incoming duration or 0.018 and select the rate-based transition mode. This is a descriptor-kind domain, not the outgoing transition-state domain. domain_6_value_0 -> CAMERA_TRANSITION_RATE_BASED: Retail 0x001ebfcc and 0x001ec0ec store zero to preview_camera +0x273 (transition_mode) on paths writing float position and rotation rates at +0x288/+0x294 from positive incoming duration or defaults. This contrasts with the separate frame-count mode at the same selector and proves a rate-based mode without equating it with descriptor or record-state values. domain_7_value_5 -> CAMERA_DESCRIPTOR_FRAME_COUNT_TRANSITION: The descriptor byte loaded at retail 0x001ebf68 is tested against 5 at 0x001ebf9c and 0x001ebff8. Its branch at 0x001ec000..0x001ec030 sets preview transition_mode to 2 and configured_frames to the converted positive incoming duration or 40. These operations prove frame-count transition configuration for this descriptor kind. domain_8_value_2 -> CAMERA_TRANSITION_FRAME_COUNT_BASED: Retail 0x001ec018 stores 2 to preview_camera +0x273, the same transition_mode selector used by the rate paths. Instructions 0x001ec01c..0x001ec030 then store the converted positive duration or default 40 into configured_frames at +0x2f4, proving a frame-count-based transition configuration. --- src/camera/switch_active_camera_record.c | 30 ++++++++++++++++-------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/camera/switch_active_camera_record.c b/src/camera/switch_active_camera_record.c index 7565689b40..e8d8058a56 100644 --- a/src/camera/switch_active_camera_record.c +++ b/src/camera/switch_active_camera_record.c @@ -50,6 +50,16 @@ void switch_active_camera_record(struct UpdateCam *next_camera) __asm__("FUN_001 extern CameraDescriptor *D_0015EF90; void switch_active_camera_record(struct UpdateCam *next_camera) { + enum { + CAMERA_TRANSITION_RATE_BASED = 0, + CAMERA_HANDOFF_NONE = 0, + CAMERA_DESCRIPTOR_RATE_TRANSITION = 1, + CAMERA_HANDOFF_INHERITED_TRANSFORM = 2, + CAMERA_TRANSITION_FRAME_COUNT_BASED = 2, + CAMERA_DESCRIPTOR_INHERIT_TRANSFORM = 3, + CAMERA_DESCRIPTOR_FRAME_COUNT_TRANSITION = 5, + CAMERA_DESCRIPTOR_INHERIT_TRANSFORM_WITH_RATE_TRANSITION = 6 + }; struct UpdateCam *previous_camera; CameraDescriptorInfo *descriptor; f32 transition_duration; @@ -68,10 +78,10 @@ void switch_active_camera_record(struct UpdateCam *next_camera) { } if (previous_transition_state == 4) { next_camera->activation_blocked = 1; - } else if (previous_transition_state == 2 || descriptor_kind == 1 || descriptor_kind == 5) { - if (descriptor_kind == 1) { + } else if (previous_transition_state == 2 || descriptor_kind == CAMERA_DESCRIPTOR_RATE_TRANSITION || descriptor_kind == CAMERA_DESCRIPTOR_FRAME_COUNT_TRANSITION) { + if (descriptor_kind == CAMERA_DESCRIPTOR_RATE_TRANSITION) { mode_one_duration = next_camera->transition_duration; - preview_camera.transition_mode = 0; + preview_camera.transition_mode = CAMERA_TRANSITION_RATE_BASED; if (mode_one_duration > 0.0f) { preview_camera.configured_position_rate = mode_one_duration; preview_camera.configured_rotation_rate = mode_one_duration; @@ -79,9 +89,9 @@ void switch_active_camera_record(struct UpdateCam *next_camera) { preview_camera.configured_position_rate = 0.018f; preview_camera.configured_rotation_rate = 0.018f; } - } else if (descriptor_kind == 5) { + } else if (descriptor_kind == CAMERA_DESCRIPTOR_FRAME_COUNT_TRANSITION) { transition_duration = next_camera->transition_duration; - preview_camera.transition_mode = 2; + preview_camera.transition_mode = CAMERA_TRANSITION_FRAME_COUNT_BASED; if (transition_duration > 0.0f) { preview_camera.configured_frames = truncate_float_to_s32(transition_duration); } else { @@ -94,15 +104,15 @@ void switch_active_camera_record(struct UpdateCam *next_camera) { preview_camera.transition_phase = 2; } } else if (previous_transition_state == 3 || previous_transition_state == 5 || - descriptor_kind == 3 || descriptor_kind == 6) { + descriptor_kind == CAMERA_DESCRIPTOR_INHERIT_TRANSFORM || descriptor_kind == CAMERA_DESCRIPTOR_INHERIT_TRANSFORM_WITH_RATE_TRANSITION) { qcopy(&next_camera->pos, &previous_camera->pos); qcopy(&next_camera->m0, &previous_camera->m0); qcopy(&next_camera->m1, &previous_camera->m1); qcopy(&next_camera->m2, &previous_camera->m2); - next_camera->handoff_state = 2; - if (previous_camera->transition_state == 5 || descriptor_kind == 6) { + next_camera->handoff_state = CAMERA_HANDOFF_INHERITED_TRANSFORM; + if (previous_camera->transition_state == 5 || descriptor_kind == CAMERA_DESCRIPTOR_INHERIT_TRANSFORM_WITH_RATE_TRANSITION) { handoff_duration = next_camera->transition_duration; - preview_camera.transition_mode = 0; + preview_camera.transition_mode = CAMERA_TRANSITION_RATE_BASED; if (handoff_duration > 0.0f) { preview_camera.configured_position_rate = handoff_duration; preview_camera.configured_rotation_rate = handoff_duration; @@ -126,7 +136,7 @@ void switch_active_camera_record(struct UpdateCam *next_camera) { position = &next_camera->pos; previous_camera->transition_state = 0; - previous_camera->handoff_state = 0; + previous_camera->handoff_state = CAMERA_HANDOFF_NONE; previous_camera->activation_blocked = 0; preview_camera.previous = previous_camera; fast_mem_copy(&camera_saved_states[1], &camera_saved_states[0], 0x280); From 176e29678358049b121c134886f33ec2e8d38a6d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:10:58 +0000 Subject: [PATCH 0746/1502] decomp: clarify names in draw_checking_memory_card_data_menu domain_1_value_3 -> MEMCARD_REQUEST_FORMAT: Retail 0x00220380 establishes a1=0x0013D290; 0x00220390 loads its +0xD4 operation state and 0x00220394 compares it with 3. The source binds this exact load to memory_card_state.state. The supplied include/rnc/save/memory_card_state.h MemoryCardOperation declaration explicitly owns state/pending_state and canonically assigns MEMCARD_REQUEST_FORMAT=3. This reuses the proven operation domain, not a stream state or per-operation substep. domain_2_value_0 -> MEMCARD_QUERY_INFO: Retail 0x002203a0 loads +0xDC from the same memory-card owner at 0x0013D290 and 0x002203a4 tests that pending operation for negativity. The source expresses this as memory_card_state.pending_state < 0. The supplied MemoryCardOperation declaration explicitly owns pending_state and establishes MEMCARD_QUERY_INFO=0, the canonical zero member used here as the lower boundary of nonnegative operation IDs. This preserves the signed comparison and does not assign meaning to the negative sentinel. --- src/ui/menus/save_data/draw_checking_memory_card_data_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/menus/save_data/draw_checking_memory_card_data_menu.c b/src/ui/menus/save_data/draw_checking_memory_card_data_menu.c index 287137f743..8d0af3a6ad 100644 --- a/src/ui/menus/save_data/draw_checking_memory_card_data_menu.c +++ b/src/ui/menus/save_data/draw_checking_memory_card_data_menu.c @@ -44,7 +44,7 @@ s32 draw_checking_memory_card_data_menu(struct MenuScreen *menu) { if (memory_card_state.card[0].type != 2) { goto done; } - if (memory_card_state.state < 3 && memory_card_state.pending_state < 0) { + if (memory_card_state.state < MEMCARD_REQUEST_FORMAT && memory_card_state.pending_state < MEMCARD_QUERY_INFO) { goto done; } setup_gif_paging(0); From 8dee6e990b0f0b6864a42239060ef51ff054ff3b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:13:19 +0000 Subject: [PATCH 0747/1502] decomp: clarify names in update_slideshow domain_0_value_0 -> SLIDESHOW_STATE_WAIT_FOR_TRANSITION: Source binds this selector to Slideshow.state at 0x0015f620, separate from Hero domains. Retail 0x00299c98-0x00299ca8 selects zero; 0x00299cb4-0x00299cdc waits until slideshow.frame reaches slideshow_frame_thresholds[slideshow.slide]-0x24, then either ends playback or enters transition. Thus zero is the wait-for-transition phase. domain_1_value_1 -> SLIDESHOW_STATE_TRANSITION: Retail 0x00299d34-0x00299d48 sets slideshow.timer=-1 and slideshow.state=1 after the frame threshold is reached and stream completion checked. The same state is tested at 0x00299d4c and owns the synchronized strided buffer copy at 0x00299d54-0x00299db0 and completion delay through timer 0x24. This is the slideshow transition phase. domain_2_value_1 -> SLIDESHOW_STATE_TRANSITION: Retail 0x00299d4c compares the previously loaded signed slideshow.state at 0x0015f620 against one. Its branch synchronizes the VU chain, copies source words to destination at 0x80-byte strides while timer<32 (0x00299d70-0x00299db0), and at timer>=36 advances the slide and queues the next read. Reuse the transition member assigned at 0x00299d48. domain_3_value_0 -> SLIDESHOW_STATE_WAIT_FOR_TRANSITION: Retail 0x00299dbc-0x00299dc0 requires transition timer>=0x24 before 0x00299e50 stores zero to slideshow.state at 0x0015f620. It resets timer, increments slide and queues the next source-buffer disc read at 0x00299e54-0x00299edc. Subsequent zero-state updates wait for the next frame threshold at 0x00299cb4-0x00299cdc; reuse the wait-for-transition member. --- .../shared/cutscenes/update_cutscene_playback.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/cutscenes/update_cutscene_playback.c b/src/overlays/shared/cutscenes/update_cutscene_playback.c index 4f32fbd3f1..fa6cadab70 100644 --- a/src/overlays/shared/cutscenes/update_cutscene_playback.c +++ b/src/overlays/shared/cutscenes/update_cutscene_playback.c @@ -1138,6 +1138,10 @@ extern void FUN_0022ca50(void); void update_slideshow(void) __asm__("FUN_L00_00299c48"); void update_slideshow(void) { + enum { + SLIDESHOW_STATE_WAIT_FOR_TRANSITION = 0, + SLIDESHOW_STATE_TRANSITION = 1 + }; s32 skip_check; s32 i; s32 *src; @@ -1153,7 +1157,7 @@ void update_slideshow(void) { if ((u8)D_0013D1D0[2] != 'A') { skip_check = 0; } - if (slideshow.state == 0) { + if (slideshow.state == SLIDESHOW_STATE_WAIT_FOR_TRANSITION) { if (slideshow.frame >= slideshow_frame_thresholds[slideshow.slide] - 0x24) { if (cd_read_active[0] != 0) { update_audio_stream_until_idle(1); @@ -1167,9 +1171,9 @@ void update_slideshow(void) { goto end_show; } slideshow.timer = -1; - slideshow.state = 1; + slideshow.state = SLIDESHOW_STATE_TRANSITION; } - } else if (slideshow.state == 1) { + } else if (slideshow.state == SLIDESHOW_STATE_TRANSITION) { vu1_sync_chain(1); if (slideshow.timer < 0x20) { src = slideshow.src; @@ -1197,7 +1201,7 @@ void update_slideshow(void) { slideshow.frame = 0x32B4; } } - slideshow.state = 0; + slideshow.state = SLIDESHOW_STATE_WAIT_FOR_TRANSITION; slideshow.timer = -1; slideshow.slide++; slide = slideshow.slide % 20; From 89122fff22c39eccfb2bb98a2783f7c466755b3a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:13:20 +0000 Subject: [PATCH 0748/1502] decomp: clarify names in emit_blarg_elite_commando_joint_sparks domain_0_value_10 -> COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM: Retail 0x002d4914 retains incoming commando Moby in s8; 0x002d495c loads 10, 0x002d4960 reads its state byte +0x20, and 0x002d4964 returns on equality. Original Ghidra likewise tests param_1+0x20 against '\n'. Checked caller 0x002d2cfc retains the same entity in s2 and passes it unchanged at 0x002d3838-0x002d383c. Its +0x20 state drives dispatch at 0x002d2d68-0x002d2d88 and receives 10 at 0x002d2f3c-0x002d2f4c. Authoritative source names this state COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM in blarg_elite_commando_update and start_blarg_elite_commando_return_to_initial_position. The corresponding retail branch 0x002d2f7c-0x002d2fd8 loads parent pointer pvars+0x2d0, transforms the saved position using parent+0xc0, adds parent+0x10, and adds parent rotation +0x48 to the saved rotation offset. These establish the commando state domain and parent-transform meaning, independently of unrelated HeroStateId value 10. --- src/overlays/shared/enemies/blarg_elite_commando.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/blarg_elite_commando.c b/src/overlays/shared/enemies/blarg_elite_commando.c index e739bc9f72..4d9b41af0c 100644 --- a/src/overlays/shared/enemies/blarg_elite_commando.c +++ b/src/overlays/shared/enemies/blarg_elite_commando.c @@ -914,9 +914,12 @@ void update_blarg_elite_commando_joint_aim(char *commando_moby) { /* Emit randomized joint particles while the moby is active. */ /* Ported from rac1-decomp (src/overlays/shared/vendor_002A1B58.c: func_L16_002D5CD0), where it is exact; names translated to the US level program. */ void emit_blarg_elite_commando_joint_sparks(char *commando_moby) { + enum { + COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM = 10 + }; float matrix[16], velocity[4], acceleration[4], scatter[4]; int i; - if (MOBY(commando_moby)->visible == 0 || MOBY(commando_moby)->state == 10) + if (MOBY(commando_moby)->visible == 0 || MOBY(commando_moby)->state == COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM) return; for (i = 0; i < 2; i++) { float speed, z; From 105def4a25f1e0514172410b2ca08b2044978ebe Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:13:20 +0000 Subject: [PATCH 0749/1502] decomp: clarify names in update_sinking_platform domain_0_value_2 -> PLATFORM_STATE_SINKING_WITH_HERO: Retail 0x00295c40 calls is_hero_on_moby; its nonzero result permits li v0,2 / sb v0,0x20(s2) at 0x00295c4c-0x00295c50. The same byte is loaded at 0x00295c60 and value 2 dispatches at 0x00295c84 to downward acceleration and z displacement at 0x00295d88-0x00295dd4. Thus this assignment belongs to the source switch(moby->state) platform domain and reuses its existing PLATFORM_STATE_SINKING_WITH_HERO member. domain_1_value_1 -> PLATFORM_STATE_BOBBING: Initialization saves original z at 0x00295cb0/0x00295cb8 and seeds oscillation phases. Retail 0x00295d14 stores s0=1 to 0x20(s2), the same moby state byte loaded at 0x00295c60; dispatch for 1 branches directly to 0x00295d18. The initialization store falls through to this same vertical and rotation oscillation sequence at 0x00295d18-0x00295d78. Reuse existing PLATFORM_STATE_BOBBING in this exact platform-state domain. domain_2_value_3 -> PLATFORM_STATE_RETURN_TO_ORIGINAL_HEIGHT: After sinking updates z, retail 0x00295dd0 calls is_hero_on_moby; zero result executes li v0,3 and sb v0,0x20(s2) at 0x00295de0-0x00295de4. This is the same state byte dispatched at 0x00295c60-0x00295c8c, where 3 selects 0x00295e18. That branch reverses/brakes vertical displacement, compares z to saved original height at pvars+0xA0 and clamps it at 0x00295edc. Reuse existing PLATFORM_STATE_RETURN_TO_ORIGINAL_HEIGHT. domain_3_value_1 -> PLATFORM_STATE_BOBBING: Retail 0x00295ec8-0x00295ed4 compares saved original height at pvars+0xA0 with updated z; on reaching it, 0x00295edc clamps z and 0x00295ed8/0x00295ee0 stores 1 to 0x20(s2). This is the exact byte loaded at 0x00295c60 whose value 1 dispatches at 0x00295c64 to vertical/rotation oscillation at 0x00295d18-0x00295d78. The completed return therefore resumes existing PLATFORM_STATE_BOBBING, not any hero-state or control-mode domain. --- src/overlays/l10/mobys/sinking_platform.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l10/mobys/sinking_platform.c b/src/overlays/l10/mobys/sinking_platform.c index f8043c5af3..bc6d6789b8 100644 --- a/src/overlays/l10/mobys/sinking_platform.c +++ b/src/overlays/l10/mobys/sinking_platform.c @@ -56,7 +56,7 @@ void sinking_platform_update(struct Moby *moby) { float position_delta[4]; *(OvlQuad *)previous_position = *(OvlQuad *)&moby->pos; if (is_hero_on_moby(moby)) - moby->state = 2; + moby->state = PLATFORM_STATE_SINKING_WITH_HERO; fast_dec_timer(&platform_vars->timer_BC); switch (moby->state) { case PLATFORM_STATE_INITIALIZE: @@ -74,7 +74,7 @@ void sinking_platform_update(struct Moby *moby) { platform_vars->unkB0 = frame_time * 1.5707964f + randf_sym(0.0f, bobbing_phase_jitter_limit); } - moby->state = 1; + moby->state = PLATFORM_STATE_BOBBING; case PLATFORM_STATE_BOBBING: *(int *)&platform_vars->unkA4 = 0; update_moby_vertical_oscillation( @@ -94,7 +94,7 @@ void sinking_platform_update(struct Moby *moby) { platform_vars->unkA4 = sinking_step_lower_bound; moby->pos.z += platform_vars->unkA4; if (is_hero_on_moby(moby) == 0) - moby->state = 3; + moby->state = PLATFORM_STATE_RETURN_TO_ORIGINAL_HEIGHT; if (platform_vars->timer_BC <= 0) { allocate_voice_for_target_entry(0, 0, (int)moby); platform_vars->timer_BC = random_int_between(0x28, 0x3C); @@ -124,7 +124,7 @@ void sinking_platform_update(struct Moby *moby) { moby->pos.z += platform_vars->unkA4; if (platform_vars->unkA0 <= moby->pos.z) { moby->pos.z = platform_vars->unkA0; - moby->state = 1; + moby->state = PLATFORM_STATE_BOBBING; } break; } From dfaa4d357e30852cbc66f6ca175677cada4943fc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:13:20 +0000 Subject: [PATCH 0750/1502] decomp: clarify names in underwater_door_update domain_0_value_1 -> DOOR_WAIT_FOR_TRIGGER: At 0x002bde4c-0x002bde58 initialization reads this door's pvars trigger and selects 1 when nonzero, storing it to this same Moby's +0x20 state at 0x002be094. Existing case DOOR_WAIT_FOR_TRIGGER consumes that state and waits on the linked Moby at 0x002bde64-0x002bde7c; this proves reuse of the local door enum. domain_1_value_4 -> DOOR_WAIT_FOR_START_VOLUME_ENTRY: Initialization selects 4 at 0x002bde5c-0x002bde60 when trigger is zero and stores it to this door's state +0x20 at 0x002be094. The same state selector's existing DOOR_WAIT_FOR_START_VOLUME_ENTRY case clears travel and tests hero position against pvars +0x18 at 0x002bdf6c-0x002bdf80. domain_2_value_2 -> DOOR_MOVE_AWAY_FROM_ORIGIN: After linked-trigger readiness and optional voice allocation, 0x002bde98-0x002bde9c selects 2 for this door's +0x20 state. Existing DOOR_MOVE_AWAY_FROM_ORIGIN is the same switch domain: 0x002bdea0-0x002bdedc advances signed travel and 0x002bdf14-0x002bdf20 writes saved origin plus heading-scaled travel to door position. domain_4_value_5 -> DOOR_WAIT_FOR_STOP_VOLUME_EXIT: After outward travel crosses the threshold, pvars trigger == -1 selects 5 at 0x002bdf58-0x002bdf68 for the same door state byte stored at 0x002be094. Existing DOOR_WAIT_FOR_STOP_VOLUME_EXIT consumes it, testing hero position against pvars stop_volume +0x1c and returning while inside at 0x002bdfa4-0x002bdfb4. domain_5_value_2 -> DOOR_MOVE_AWAY_FROM_ORIGIN: The start-volume case clears travel and requires hero entry at 0x002bdf70-0x002bdf80, then selects 2 at 0x002bdf9c-0x002bdfa0 for the same Moby state byte. That byte is the local switch selector whose existing DOOR_MOVE_AWAY_FROM_ORIGIN case advances signed travel at 0x002bded8-0x002bdedc and updates door position. domain_6_value_6 -> DOOR_RETURN_TO_ORIGIN: After the hero is outside stop_volume at 0x002bdfa8-0x002bdfb4, 0x002bdfd0-0x002bdfd4 selects 6 for this door's state +0x20. Existing DOOR_RETURN_TO_ORIGIN consumes the same selector, subtracting signed travel or clamping it to zero at 0x002be014-0x002be034 and reconstructing position from saved origin. domain_7_value_4 -> DOOR_WAIT_FOR_START_VOLUME_ENTRY: At 0x002be080-0x002be094 the return case selects and stores 4 only when signed travel reaches zero. This is the same door state byte read at 0x002bddf8/0x002bde10, whose existing DOOR_WAIT_FOR_START_VOLUME_ENTRY case resets travel and waits for hero entry into pvars start_volume at 0x002bdf6c-0x002bdf80. --- src/overlays/shared/props/underwater_door.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/props/underwater_door.c b/src/overlays/shared/props/underwater_door.c index e3ce5296c5..c81a45a588 100644 --- a/src/overlays/shared/props/underwater_door.c +++ b/src/overlays/shared/props/underwater_door.c @@ -52,17 +52,17 @@ void underwater_door_update(struct Moby *moby) { case DOOR_INITIALIZE: door_motion_data->origin.q = *(u128 *)&moby->pos; if (door_motion_data->trigger != 0) { - moby->state = 1; + moby->state = DOOR_WAIT_FOR_TRIGGER; return; } - moby->state = 4; + moby->state = DOOR_WAIT_FOR_START_VOLUME_ENTRY; return; case DOOR_WAIT_FOR_TRIGGER: if (((struct Moby *)((int)l15_moby_array + door_motion_data->trigger * 0x100))->state != 4) return; if (reversed) allocate_voice_for_target_entry(0, 0, (int)moby); - moby->state = 2; + moby->state = DOOR_MOVE_AWAY_FROM_ORIGIN; break; case DOOR_MOVE_AWAY_FROM_ORIGIN: { union { @@ -91,7 +91,7 @@ void underwater_door_update(struct Moby *moby) { moby->state = 3; return; } - moby->state = 5; + moby->state = DOOR_WAIT_FOR_STOP_VOLUME_EXIT; return; } case DOOR_WAIT_FOR_START_VOLUME_ENTRY: @@ -100,14 +100,14 @@ void underwater_door_update(struct Moby *moby) { return; if (reversed) allocate_voice_for_target_entry(0, 0, (int)moby); - moby->state = 2; + moby->state = DOOR_MOVE_AWAY_FROM_ORIGIN; break; case DOOR_WAIT_FOR_STOP_VOLUME_EXIT: if (is_point_inside_clip_volume(&hero.motion.pos, door_motion_data->stop_volume)) return; if (reversed) allocate_voice_for_target_entry(0, 0, (int)moby); - moby->state = 6; + moby->state = DOOR_RETURN_TO_ORIGIN; break; case DOOR_RETURN_TO_ORIGIN: { f32 old_travel; @@ -133,7 +133,7 @@ void underwater_door_update(struct Moby *moby) { *(u128 *)&moby->pos = updated_door_position.q; if (door_motion_data->travel != 0.0f) return; - moby->state = 4; + moby->state = DOOR_WAIT_FOR_START_VOLUME_ENTRY; break; } } From 51d1731b08e0b86924cdb7433ae15da80b5949c4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:15:23 +0000 Subject: [PATCH 0751/1502] decomp: clarify names in pilots_helmet_update domain_0_value_1 -> PILOTS_HELMET_WAIT_FOR_HERO_PROXIMITY: Bound source src/overlays/shared/pickups/pilots_helmet.c SHA-256 99600e873c15befc88754c421ac9f415baa81d6992139df28388846384edbfc6 assigns 1 to moby->state after initialization and availability filtering. Retail 0x002e03d0 loads s1=1; 0x002e047c stores s1 to +0x20(s0). That exact byte is read at 0x002e03e0 and compared with s1 at 0x002e03e4 to enter 0x002e048c, whose distance <3, height difference <2 and hero eligibility checks implement the existing PILOTS_HELMET_WAIT_FOR_HERO_PROXIMITY case. This is the local moby state domain, not HeroStateId. domain_1_value_2 -> PILOTS_HELMET_GRANT_REWARD: Source assigns 2 to moby->state after proximity/height/eligibility gating and start_scene or missing-scene diagnostic. Retail 0x002e0520/0x002e0530 loads 2 and 0x002e0538 stores it to +0x20(s0). Dispatch reads that same byte at 0x002e03e0; 0x002e0408 branches on 2 to 0x002e053c. The destination issues acquisition dialogue and grant_inventory_item(7,1) at 0x002e0558-0x002e0578, matching the existing local PILOTS_HELMET_GRANT_REWARD case. domain_2_value_3 -> PILOTS_HELMET_SAVE_AND_REMOVE: Source assigns 3 to moby->state after reward and persistent bookkeeping. Retail 0x002e0670 loads a0=3 and 0x002e0678 stores it to +0x20(s0). Dispatch reads this same state byte at 0x002e03e0 and branches on 3 at 0x002e0410 to 0x002e067c. That branch calls memcard_save_data(0,-1) at 0x002e0680 and mark_moby_for_removal on the same object at 0x002e0688-0x002e068c, exactly the existing local PILOTS_HELMET_SAVE_AND_REMOVE case; save completion is not implied. --- src/overlays/shared/pickups/pilots_helmet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/pickups/pilots_helmet.c b/src/overlays/shared/pickups/pilots_helmet.c index 8a06656635..090e8ae21c 100644 --- a/src/overlays/shared/pickups/pilots_helmet.c +++ b/src/overlays/shared/pickups/pilots_helmet.c @@ -114,7 +114,7 @@ void pilots_helmet_update(M_2e03a0_2e03a0 *moby) { mark_moby_for_removal(moby); return; } - moby->state = 1; + moby->state = PILOTS_HELMET_WAIT_FOR_HERO_PROXIMITY; moby->z += 1.0f; break; case PILOTS_HELMET_WAIT_FOR_HERO_PROXIMITY: @@ -129,7 +129,7 @@ void pilots_helmet_update(M_2e03a0_2e03a0 *moby) { start_scene(p->fa_2e03a0); else debug_print(pilots_helmet_missing_cutscene_format, moby->h); - moby->state = 2; + moby->state = PILOTS_HELMET_GRANT_REWARD; } } break; @@ -158,7 +158,7 @@ void pilots_helmet_update(M_2e03a0_2e03a0 *moby) { if (moby->b0 != 0xFF) jet_clear_persistent(moby->b0); D_00141410_2e03a0[0] = 7; - moby->state = 3; + moby->state = PILOTS_HELMET_SAVE_AND_REMOVE; break; case PILOTS_HELMET_SAVE_AND_REMOVE: memcard_save_data(0, -1); From 05a70fcb0ef2e792f98636e0216e837d7595f1f9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:15:23 +0000 Subject: [PATCH 0752/1502] decomp: clarify names in read_mpeg domain_0_value_2 -> MOVIE_SKIP_MODE_ANY_BUTTON: Source snapshot src/movies/decoder/read_mpeg.c SHA-256 3ab163575734a81fb085f7b471a8d46e912309b1c5c1f3168a67082db6e90783 assigns mode from DECODE_MODE, a volatile view of decode_mode. Retail 0x0023a4d0-0x0023a4e4 loads D_0015EED8 (Ghidra g_nMpegInputMode), bypasses skip tests for -1, then compares that same loaded mode with 2. For mode 2, 0x0023a4ec-0x0023a4f8 reads the entire pad pressed word at D_0013C940+0x1a4 and branches on any nonzero bit to 0x0023a574. This sets skipped at 0x0023a584 and calls video_dec_abort at 0x0023a588. Source pad_pressed(&pad_words,-1) confirms any newly pressed button. This is a movie skip-policy mode, not VideoDecState, pad-bit, or output-tag state. --- src/movies/decoder/read_mpeg.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/movies/decoder/read_mpeg.c b/src/movies/decoder/read_mpeg.c index dfc8217ff7..518c42a81e 100644 --- a/src/movies/decoder/read_mpeg.c +++ b/src/movies/decoder/read_mpeg.c @@ -59,6 +59,9 @@ s32 read_mpeg(struct VideoDec *video_dec, struct ReadBuf *read_buf, struct MpegCdStream *cd_stream) { + enum { + MOVIE_SKIP_MODE_ANY_BUTTON = 2 + }; u8 *write_ptr; u8 *read_ptr; s32 skipped; @@ -82,7 +85,7 @@ s32 read_mpeg(struct VideoDec *video_dec, update_primary_pad_state(); mode = DECODE_MODE; if (mode != -1) { - if ((mode == 2 && pad_pressed(&controller_state, -1)) || + if ((mode == MOVIE_SKIP_MODE_ANY_BUTTON && pad_pressed(&controller_state, -1)) || ((D_0015EEA0 != 0 || alternate_animation_sequence != 0 || DECODE_MODE != 0 || current_level_index <= 0) && pad_pressed(&controller_state, 0x800))) { From 6a2a0f2b10772ce07517fd2d529b2d51615cb041 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:15:23 +0000 Subject: [PATCH 0753/1502] decomp: clarify names in initialize_level_transition_with_audio domain_2_value_0 -> AUDIO_SELECTION_MODE_ALWAYS_FADE: Incoming audio_selection_mode is saved in s3 at 0x0028ea04 and stored at shared record +0x20 at 0x0028ea14. The zero test at 0x0028eb30 selects the path that unconditionally calls scale_game_frames(6) at 0x0028eba0-0x0028eba4 and passes its return as a1 to load_chunks_with_optional_fade at 0x0028eba8-0x0028ebb0, regardless of level-specific stream-index overrides. Supplied callee C passes this fade_frame_count to fade_to_black. The nonzero path instead suppresses the fade when shared +0x2c is nonzero (0x0028ec48-0x0028ec5c). Supplied caller prepare_level_transition_with_help_cleanup passes 0 at 0x0028ed38. This names the proven unconditional fade behavior without asserting departure/arrival or a hero-state domain. --- .../shared/game/initialize_level_transition_with_audio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/game/initialize_level_transition_with_audio.c b/src/overlays/shared/game/initialize_level_transition_with_audio.c index 5fb8f1f457..34da3737ca 100644 --- a/src/overlays/shared/game/initialize_level_transition_with_audio.c +++ b/src/overlays/shared/game/initialize_level_transition_with_audio.c @@ -116,6 +116,9 @@ int sce_gs_sync_v(int) __asm__("FUN_00122298"); void initialize_level_transition_with_audio(int audio_selection_mode) __asm__("FUN_L00_0028e9c8"); void initialize_level_transition_with_audio(int audio_selection_mode) { + enum { + AUDIO_SELECTION_MODE_ALWAYS_FADE = 0 + }; O_28e9c8 *moby; int secondary_track_index, base_audio_selection_index, audio_stream_table_index, alternate_audio_stream_table_index, shared_table_offset; @@ -142,7 +145,7 @@ void initialize_level_transition_with_audio(int audio_selection_mode) { if (!(moby->st & 0x80) && (moby->type == 0x4A || moby->type == 0xCB)) moby->flags |= 0x80; } - if (audio_selection_mode == 0) { + if (audio_selection_mode == AUDIO_SELECTION_MODE_ALWAYS_FADE) { base_audio_selection_index = D_0013E030_28e9c8.x26; audio_stream_table_index = base_audio_selection_index + 1; secondary_track_index = base_audio_selection_index + 6; From 7462efd7bd20c521e12208c5d1128bbce5df0809 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:15:24 +0000 Subject: [PATCH 0754/1502] decomp: clarify names in shuttle_update domain_2_value_2 -> SHUTTLE_STATE_WAIT_FOR_DEPARTURE: Retail 0x002dbe70 loads s1=2; after route selection at 0x002dbf20, 0x002dbf30 stores s1 to moby+0x20, the same byte read at 0x002dbe90 and dispatched at 0x002dbe94. Authoritative C switches this exact moby->state selector using existing SHUTTLE_STATE_WAIT_FOR_DEPARTURE=2. Its branch checks the riding hero and waits for departure conditions, proving reuse of that member. domain_3_value_3 -> SHUTTLE_STATE_TRAVEL: Retail 0x002dbfd4..0x002dbff4 checks departure input, air frames and mode; 0x002dbff8 loads 3 and 0x002dc000 stores it to moby+0x20. The same byte is selected at 0x002dbe90/0x002dbeb4 for the travel branch at 0x002dc014, calling advance_shuttle_path_travel at 0x002dc034. Authoritative C already declares SHUTTLE_STATE_TRAVEL=3 for this exact moby->state domain. domain_4_value_2 -> SHUTTLE_STATE_WAIT_FOR_DEPARTURE: Retail 0x002dc034 invokes advance_shuttle_path_travel; nonzero completion at 0x002dc03c invokes route selection at 0x002dc044, then 0x002dc04c stores s1=2 into moby+0x20. That exact byte feeds the switch at 0x002dbe90/0x002dbe94 and the existing SHUTTLE_STATE_WAIT_FOR_DEPARTURE=2 branch. Current helper C returns path progress==target, confirming return to waiting after travel. --- src/overlays/l08/mobys/shuttle.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l08/mobys/shuttle.c b/src/overlays/l08/mobys/shuttle.c index f6d49939cc..5aed3380dc 100644 --- a/src/overlays/l08/mobys/shuttle.c +++ b/src/overlays/l08/mobys/shuttle.c @@ -128,7 +128,7 @@ void shuttle_update(struct Moby *moby) { shuttle_vars->unk100 = -1; shuttle_vars->unkE0 = -1; select_shuttle_route_for_hero((char *)moby); - moby->state = 2; + moby->state = SHUTTLE_STATE_WAIT_FOR_DEPARTURE; moby->update_dist = 0xFF; } break; @@ -142,7 +142,7 @@ void shuttle_update(struct Moby *moby) { try_set_shuttle_departure_help_message((char *)moby); if ((pad_pressed_words[0] & 0x10) && hero.air_frames.s == 0 && D_L08_0015F594 == 10) - moby->state = 3; + moby->state = SHUTTLE_STATE_TRAVEL; } } } else { @@ -155,7 +155,7 @@ void shuttle_update(struct Moby *moby) { hero.path_constrain_pending = shuttle_vars->stop; if (advance_shuttle_path_travel((char *)moby)) { select_shuttle_route_for_hero((char *)moby); - moby->state = 2; + moby->state = SHUTTLE_STATE_WAIT_FOR_DEPARTURE; } break; } From 11b298c2d8f1681eff70ccd931b8d8c135eb97b2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:15:24 +0000 Subject: [PATCH 0755/1502] decomp: clarify names in rocket_update domain_0_value_1 -> ROCKET_STATE_IDLE: The authoritative rocket_update C declares ROCKET_STATE_IDLE = 1 in the enum used by switch (moby->state). Retail 002fdbc4 retains the moby in s1; 002fdbcc loads a0=1 and 002fdc44 stores that value to the same state byte at 0x20(s1) after index validation. Retail 002fdbe4 reads that byte and 002fdbe8 branches on 1 directly to epilogue 002fdea4. Original Ghidra likewise assigns *(param_1+0x20)=1 during initialization and returns immediately when that same field equals 1. This proves reuse of the existing rocket-state member, rather than an unrelated equal-valued TRUE constant. --- src/overlays/l14/mobys/rocket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/rocket.c b/src/overlays/l14/mobys/rocket.c index fa75ef7454..db882d710b 100644 --- a/src/overlays/l14/mobys/rocket.c +++ b/src/overlays/l14/mobys/rocket.c @@ -79,7 +79,7 @@ void rocket_update(struct Moby *moby) { mark_moby_for_removal(moby); return; } - moby->state = 1; + moby->state = ROCKET_STATE_IDLE; moby->update_dist = 0xFF; moby->pos.z += 1.5f; rocket_vars->sound = -1; From 5746904b2437495891de38c54822de29cf0df0a6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:15:24 +0000 Subject: [PATCH 0756/1502] decomp: clarify names in process_forcefield_tower_damage domain_0_value_2 -> TOWER_STATE_DESTRUCTION: Retail 0x002cece8 loads moby state byte +0x20 and 0x002cecec skips damage processing when it equals 2. Original Ghidra tests param_1+0x20 != 2. Authoritative forcefield_tower_update reads this same moby byte +0x20 and explicitly defines TOWER_STATE_DESTRUCTION=2; that branch emits tower destruction effects and marks the moby for removal. This is the tower current-state domain, not the resolve_moby_hit_response result domain. domain_1_value_2 -> TOWER_STATE_DESTRUCTION: Retail lethal branch 0x002cee08..0x002cee18 compares health with hit damage, clears health at 0x002cee3c, emits effects, releases the owned voice, then loads 2 at 0x002cef4c and stores it to moby state +0x20 at 0x002cef58. Original Ghidra confirms that assignment. Authoritative forcefield_tower_update dispatches the identical byte as TOWER_STATE_DESTRUCTION=2, performing further destruction effects and removal. Reuse the same state member as the entry guard. --- src/overlays/l13/mobys/forcefield_tower.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l13/mobys/forcefield_tower.c b/src/overlays/l13/mobys/forcefield_tower.c index c91a6087fa..11fb46fdbd 100644 --- a/src/overlays/l13/mobys/forcefield_tower.c +++ b/src/overlays/l13/mobys/forcefield_tower.c @@ -262,6 +262,9 @@ void process_forcefield_tower_damage(struct Moby *moby, unsigned char *moby_data HIT_REACTION_HIGH_INTERPOLATION_TARGET_ALTERNATE = 10, HIT_REACTION_NO_HIT = 11 }; + enum { + TOWER_STATE_DESTRUCTION = 2 + }; char *hit_record; int hit; float position[4]; @@ -269,7 +272,7 @@ void process_forcefield_tower_damage(struct Moby *moby, unsigned char *moby_data int link; VoicePoolWindow *voice_slot_record; - if (moby->state != 2) { + if (moby->state != TOWER_STATE_DESTRUCTION) { hit_record = find_moby_hit(moby, 0x330000, 0); if (hit_record != 0) { DebugPrint(D_L13_001f4980, moby->oclass, fptodp(*(float *)(hit_record + 0x2c))); @@ -342,7 +345,7 @@ void process_forcefield_tower_damage(struct Moby *moby, unsigned char *moby_data } } *(int *)(moby_data + 0x70) = -1; - moby->state = 2; + moby->state = TOWER_STATE_DESTRUCTION; } else { *health -= *(float *)(hit_record + 0x2c); moby_data[0x67] = 0xfa; From 75b085432d4b96f6404b96f6d11584dc6fed3213 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:17:19 +0000 Subject: [PATCH 0757/1502] decomp: clarify names in revive_spawner_pooled_child domain_2_value_0 -> SPAWNER_CHILD_STATE_INITIAL: Authoritative src/overlays/shared/enemies/bomb_spawner_bomb.c SHA-256 57f88aaec0279d7e8af3352a937214dfa763efced9f368f18f29c141db3e81e5 and original retail decompilation agree: a pooled candidate selected from pvars+0xE8 is revived only once. Retail 0x002bed48-0x002bed50 restores its spawn position, 0x002bed58 stores zero to that same Moby's state byte at +0x20, and 0x002bed5c clears command. Class flags/scale and animation are restored before update_entity at 0x002bee74. This proves zero is the initial state entered on pooled-child revival, without claiming a class-specific behavior. Checked helper instructions at 0x0023f968-0x0023f970 read the same state byte and skip processing for negative states, corroborating activation. The selector is the pooled child's actual Moby state, not a control/request mode. --- src/overlays/shared/enemies/bomb_spawner_bomb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/bomb_spawner_bomb.c b/src/overlays/shared/enemies/bomb_spawner_bomb.c index 3366f68023..bbe425eb94 100644 --- a/src/overlays/shared/enemies/bomb_spawner_bomb.c +++ b/src/overlays/shared/enemies/bomb_spawner_bomb.c @@ -77,6 +77,9 @@ struct Moby *revive_spawner_pooled_child(struct Moby *spawner_moby, s32 oclass) __asm__("FUN_L03_002bec60"); struct Moby *revive_spawner_pooled_child(struct Moby *spawner_moby, Vec4 *at, s32 oclass) { + enum { + SPAWNER_CHILD_STATE_INITIAL = 0 + }; Vec4 pos; Vec4 *spawn_position_source; Spawner *spawner_data; @@ -118,7 +121,7 @@ struct Moby *revive_spawner_pooled_child(struct Moby *spawner_moby, Vec4 *at, s3 found = 1; qcopy(¤t_moby->pos, spawn_position_source); current_moby->pos.w = 0.0f; - current_moby->state = 0; + current_moby->state = SPAWNER_CHILD_STATE_INITIAL; current_moby->command = 0; spawned_moby_class = (SpawnClass *)current_moby->pclass; flags = spawned_moby_class->flags; From e3c05803ae1038d5ec32f3c5919a94878c0acf0a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:17:19 +0000 Subject: [PATCH 0758/1502] decomp: clarify names in camera_transition_update domain_0_value_81 -> CAMERA_REQUEST_BYPASS_MODE_MATCH: Retail 0x002ea4cc loads requested_camera_mode from hero base 0x0013f350+0x2284. At 0x002ea4d4-0x002ea4dc it compares that request with transition_camera_record+0x86 and enters 0x002ea4f0 on equality. On inequality, 0x002ea4e4 loads 0x51 and 0x002ea4e8 branches to the exit/reset path only if the request differs from 0x51; equality falls into the identical steering-entry path. Thus 0x51 is explicitly the camera request that bypasses this mode-match requirement, independently of any HeroStateId numeric coincidence. The source preserves subsequent checked-object and active-camera whitelist/collision gates. --- src/overlays/shared/camera/hero_aligned_camera.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/camera/hero_aligned_camera.c b/src/overlays/shared/camera/hero_aligned_camera.c index 2207e59976..044d019663 100644 --- a/src/overlays/shared/camera/hero_aligned_camera.c +++ b/src/overlays/shared/camera/hero_aligned_camera.c @@ -418,6 +418,9 @@ void update_hero_aligned_camera_from_input(u8 *camera_object) { int camera_transition_update(u8 *, char *) __asm__("FUN_L00_002ea488"); int camera_transition_update(u8 *transition_camera_record, char *mode_check_object) { + enum { + CAMERA_REQUEST_BYPASS_MODE_MATCH = 0x51 + }; Q_2ea488 *q; char *active_transition_camera_record; char *r; @@ -434,7 +437,7 @@ int camera_transition_update(u8 *transition_camera_record, char *mode_check_obje g = &P; requested_camera_mode = g->i2284; if (requested_camera_mode == *(s16 *)(transition_camera_record + 0x86) || - requested_camera_mode == 0x51) { + requested_camera_mode == CAMERA_REQUEST_BYPASS_MODE_MATCH) { active_transition_camera_record = D_L00_00166E00_lui; checked_object_mode = *(s16 *)(mode_check_object + 0x86); if (checked_object_mode != 0 && checked_object_mode != 10 && checked_object_mode != 14 && From e557f5d3647cb16223dc94358ae37b346ea6dadd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:17:19 +0000 Subject: [PATCH 0759/1502] decomp: clarify names in update_grind_rail_junction domain_0_value_1 -> STATE_SELECT_NEARER_PATH: Authoritative source SHA-256 5fe93ea78a3de1bc582f091307fad8d95cb15004e33c1311822b136687947e86 declares STATE_SELECT_NEARER_PATH = 1 and uses it as a case of switch(moby->state). Retail 0x002d631c loads the same moby byte at +0x20, 0x002d6328-0x002d632c dispatches value 1 to 0x002d64e0, and 0x002d6340/0x002d634c stores 1 to that byte during initialization. Original Ghidra confirms both access the param_1+0x20 state field. The destination branch compares hero distances to both pair starts at 0x002d6544-0x002d6578 and restores only the nearer member's saved radius at 0x002d6580-0x002d65ac. Thus the assignment enters precisely the existing local STATE_SELECT_NEARER_PATH domain member. --- src/overlays/l18/mobys/grind_rail_junction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l18/mobys/grind_rail_junction.c b/src/overlays/l18/mobys/grind_rail_junction.c index 4d98717cff..02fe1cc00a 100644 --- a/src/overlays/l18/mobys/grind_rail_junction.c +++ b/src/overlays/l18/mobys/grind_rail_junction.c @@ -54,7 +54,7 @@ void grind_rail_junction_update(struct Moby *moby) { switch (moby->state) { case STATE_INITIALIZE_PATH_PAIRS: - moby->state = 1; + moby->state = STATE_SELECT_NEARER_PATH; moby->update_dist = 0xFF; pair_or_node_index = 0; do { From 65d93750e57359644b74b10d07f167e7c1e6219e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:17:20 +0000 Subject: [PATCH 0760/1502] decomp: clarify names in select_nearest_gadgebot_interaction_target domain_0_value_2 -> GADGEBOT_ABSORPTION_DISABLED: Retail 0x002f2b84-0x002f2ba0 gates the candidate+0x20 state comparison to classes 0x400/0x516 and skips target selection for state 2 (also 0x002f2a38-0x002f2a58 in the group path). The authoritative source identifies these classes as MOBY_CLASS_GADGEBOT_ABSORPTION_TRIGGER/TARGET in process_gadgebot_interaction_candidate. Checked sibling instructions 0x002f2cb4-0x002f2cec route exactly these classes to 0x002f3248; 0x002f3250-0x002f3258 reads the same candidate state byte and rejects 2. Otherwise, within one unit, 0x002f3288-0x002f32a0 enters the gadgebot's absorption state 8 and stores this candidate at vars+0x304. Thus state 2 disables absorption eligibility; no physical cause or shared Hero enum membership is inferred. --- src/overlays/shared/enemies/gadgebot.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/gadgebot.c b/src/overlays/shared/enemies/gadgebot.c index 23970213cb..bc2540688f 100644 --- a/src/overlays/shared/enemies/gadgebot.c +++ b/src/overlays/shared/enemies/gadgebot.c @@ -1363,6 +1363,9 @@ void assign_gadgebot_attack_targets(void) { } void select_nearest_gadgebot_interaction_target(void *moby_arg) { + enum { + GADGEBOT_ABSORPTION_DISABLED = 2 + }; GbMoby *moby = moby_arg; GbVars *gadgebot_vars = moby->vars; GbMoby *candidate; @@ -1400,7 +1403,7 @@ void select_nearest_gadgebot_interaction_target(void *moby_arg) { !(0.2f < absolute_float(moby->pos[2] - candidate->pos[2])) && !(1.5f < absolute_float(moby->pos[2] - candidate->pos[2]))) { if ((candidate->cls_id != 0x400 && candidate->cls_id != 0x516) || - candidate->state != 2) { + candidate->state != GADGEBOT_ABSORPTION_DISABLED) { if (candidate->cls_id != 0x515 || *(int *)candidate->vars != -1) { best = vector_distance_xy(moby->pos, candidate->pos); gadgebot_vars->target = candidate; From 9615233df1bcaa0c0d457595faa31e705326d422 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:19:22 +0000 Subject: [PATCH 0761/1502] decomp: clarify names in stick_target domain_0_value_1 -> STICK_TARGET_MODE_CARDINAL_AXIS_FILTER: In stick_target, retail 0x002118f4 preserves the mode argument a0 in s1 and 0x00211904 compares it with 1. Only this mode executes 0x0021190c-0x002119a8: absolute stick components are compared with 0.7 and 0.12, and the small perpendicular component is zeroed when the other is large. The original Ghidra param_2 == 1 branch and bound C mode == 1 implement this cardinal-axis filter. This argument is a stick-target processing selector, not hero.state.current or any supplied shared enum domain. domain_1_value_2 -> STICK_TARGET_MODE_FOUR_WAY_YAW: Retail mode is a0 saved in s1 at 0x002118f4. The comparison with 2 at 0x00211a7c-0x00211a80 selects 0x00211a88-0x00211ad8: the stick-derived move_yaw plus pi is multiplied by approximately 2/pi, rounded via +0.5 and truncation, masked with 3 at 0x00211abc, then multiplied by pi/2 and shifted by -pi. Original Ghidra param_2 == 2 and current C prove four-way yaw quantization in this separate stick-target mode domain. domain_2_value_3 -> STICK_TARGET_MODE_EIGHT_WAY_YAW: Retail 0x00211adc-0x00211ae0 compares s1 (mode argument saved from a0 at 0x002118f4) with 3. Its branch 0x00211ae8-0x00211b3c quantizes stick-derived move_yaw using (yaw + pi) * approximately 4/pi + 0.5, integer truncation, mask 7 at 0x00211b20, and multiplication by approximately pi/4 followed by -pi. The original Ghidra param_2 == 3 branch and bound source establish eight-way yaw, independently of hero state IDs. domain_3_value_4 -> STICK_TARGET_MODE_HERO_RELATIVE_YAW: Retail 0x00211b40-0x00211b44 compares s1 (the incoming mode in a0 saved at 0x002118f4) with 4. On equality, 0x00211b4c-0x00211b54 supplies move_yaw and hero offset 0x98, bound in current C to hero.motion.rot.f[2], to fast_add_rotations at 0x00211b60; other modes supply global 0x00166dd8 instead. Original Ghidra selects uRam0013f3e8 only for param_2 == 4. This proves hero-relative yaw for the stick-target selector without claiming the unresolved alternate global is camera yaw. --- src/overlays/shared/hero/hero_switch_item.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 214c7f8cc3..aa2a06ee99 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -2843,6 +2843,12 @@ extern float compute_hero_ground_aligned_heading(void) __asm__("FUN_L00_002332d0 void stick_target(float scale, int mode) __asm__("FUN_L00_002118c8"); void stick_target(float scale, int mode) { + enum { + STICK_TARGET_MODE_CARDINAL_AXIS_FILTER = 1, + STICK_TARGET_MODE_FOUR_WAY_YAW = 2, + STICK_TARGET_MODE_EIGHT_WAY_YAW = 3, + STICK_TARGET_MODE_HERO_RELATIVE_YAW = 4 + }; V_2118c8 stick_vector; V_2118c8 q; float x; @@ -2851,7 +2857,7 @@ void stick_target(float scale, int mode) { stick_vector.f[1] = hero.stick_y; stick_vector.f[0] = hero.stick_x; - if (mode == 1) { + if (mode == STICK_TARGET_MODE_CARDINAL_AXIS_FILTER) { if (absolute_float(stick_vector.f[1]) > 0.7f && absolute_float(stick_vector.f[0]) < 0.12f) { stick_vector.f[0] = 0.0f; } @@ -2876,21 +2882,21 @@ void stick_target(float scale, int mode) { return; } hero.motion.move_yaw = fast_arc_tan(-stick_vector.f[1], -stick_vector.f[0]); - if (mode == 2) { + if (mode == STICK_TARGET_MODE_FOUR_WAY_YAW) { hero.motion.move_yaw = convert_integer_to_float( truncate_float_to_s32((hero.motion.move_yaw + 3.1415927f) * 0.63662f + 0.5f) & 3) * 1.5707964f - 3.1415927f; } - if (mode == 3) { + if (mode == STICK_TARGET_MODE_EIGHT_WAY_YAW) { hero.motion.move_yaw = convert_integer_to_float( truncate_float_to_s32((hero.motion.move_yaw + 3.1415927f) * 1.27324f + 0.5f) & 7) * 0.785398f - 3.1415927f; } - if (mode == 4) { + if (mode == STICK_TARGET_MODE_HERO_RELATIVE_YAW) { hero.motion.move_yaw = fast_add_rotations(hero.motion.move_yaw, hero.motion.rot.f[2]); } else { hero.motion.move_yaw = fast_add_rotations(hero.motion.move_yaw, D_L00_00166DD8_lui); From 565dd5f8079804ab9dec5be504e0f8e70514c99c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:19:22 +0000 Subject: [PATCH 0762/1502] decomp: clarify names in launch_hero_wrench domain_0_value_1 -> HERO_STATE_LOOK: Source state is assigned directly from hero.state.current. Retail 0x00217674 establishes hero base 0x0013f350; 0x00217688 loads its current-state field +0x2084, and 0x0021767c/0x0021768c compare it with 1. Thus the selector belongs to shared HeroStateId, whose canonical member is HERO_STATE_LOOK=1, rather than gravity or vehicle mode. The branch checks the scaled 20-frame state timer and enables target/camera aim. domain_1_value_30 -> HERO_STATE_LOOK_RELEASE_WAIT: The same source state local is hero.state.current, matching the hero+0x2084 load at retail 0x00217688. Retail 0x00217694-0x00217698 compares that current-state value with 0x1e and joins the LOOK branch's scaled 20-frame timer/aim handling at 0x002176a0. This proves the shared HeroStateId domain, whose canonical member for 30 is HERO_STATE_LOOK_RELEASE_WAIT. domain_2_value_10 -> WRENCH_STATE_LAUNCH: Retail 0x00217778 loads hero.items[0].moby and 0x0021777c-0x00217784 gates launch on is_wrench_moby, whose supplied definition checks class 0x47. At 0x002177a0/0x002177b0 the accepted wrench receives byte state 10 at moby+0x20. This same entry initializes its pvars+0x40 launch direction at 0x00217800-0x00217844, converts the launch orientation into moby+0x40 at 0x002178d4-0x002178dc, sets speed to frame_time*23 at 0x00217900-0x0021790c and starts animation 6 at 0x00217938-0x00217948. This proves wrench launch-entry meaning in its own moby-state domain. --- src/overlays/shared/hero/hero_move_state_velocity.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/hero_move_state_velocity.c b/src/overlays/shared/hero/hero_move_state_velocity.c index 10fb3e280a..6e8bd20644 100644 --- a/src/overlays/shared/hero/hero_move_state_velocity.c +++ b/src/overlays/shared/hero/hero_move_state_velocity.c @@ -1246,6 +1246,9 @@ extern void create_moby_transform_history_entry(char *, int, int) __asm__("FUN_ void launch_hero_wrench(void) __asm__("FUN_L00_00217658"); void launch_hero_wrench(void) { + enum { + WRENCH_STATE_LAUNCH = 10 + }; f32 aim_origin_or_euler_angles[4]; f32 delta[4]; f32 item_rotation_matrix[12]; @@ -1260,7 +1263,7 @@ void launch_hero_wrench(void) { s32 state; state = hero.state.current; - aimed = (state == 1 || state == 0x1E) && scale_game_frames(0x14) < hero.state_timer; + aimed = (state == HERO_STATE_LOOK || state == HERO_STATE_LOOK_RELEASE_WAIT) && scale_game_frames(0x14) < hero.state_timer; if (aimed) { target = hero.items[0].moby; has_target = 0; @@ -1287,7 +1290,7 @@ void launch_hero_wrench(void) { if (aimed) { allocate_hero_voice_for_entry(0x1B, 0); } - equipped_wrench_moby->state = 10; + equipped_wrench_moby->state = WRENCH_STATE_LAUNCH; launched_item_vars = (ThrowPvars *)equipped_wrench_moby->pvars; if (hero.wall_probe_distance < 1.2f && 0.6632251f < hero.wall_normal_pitch && !hero.wall_probe_moby_in_class_range) { From a17c4591546e5b22adcdd32632075ec0293df7a6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:19:22 +0000 Subject: [PATCH 0763/1502] decomp: clarify names in update_swing_gate domain_1_value_0 -> SWING_GATE_STATE_INITIALIZE: Authoritative update_swing_gate tests moby->state == 0. Retail 0x002ea54c-0x002ea570 loads the byte at moby+0x20, branches on zero, stores state 1, copies moby+0x10 position into SwingGateVars.home at pvars+0x10, and returns. Original Ghidra shows the same one-time home-position initialization, proving this gate-specific initialization state. domain_2_value_1 -> SWING_GATE_STATE_FOLLOW_DRIVER: Retail 0x002ea558-0x002ea56c assigns 1 to the same moby+0x20 state byte while saving home. At 0x002ea578 only state 1 enters the update path. Retail 0x002ea518 reads driver pvars progress; 0x002ea580-0x002ea5e0 interpolates gate yaw from it and 0x002ea710-0x002ea738 updates position. Authoritative C and original Ghidra agree that state 1 follows driver progress, even while progress is stationary. domain_3_value_1 -> SWING_GATE_STATE_FOLLOW_DRIVER: The C guard moby->state != 1 returns before driver-based yaw and position updates. Retail 0x002ea54c loads moby+0x20 and 0x002ea578 compares that byte with 1, exiting for other nonzero states. The accepted branch interpolates degree endpoints by driver progress at 0x002ea580-0x002ea5e0 and updates position at 0x002ea710-0x002ea738. This is the same FOLLOW_DRIVER state assigned during initialization. domain_4_value_2 -> SWING_GATE_STATE_OPEN_LATCHED: Authoritative C enters this assignment only when progress == 1.0f and moby->oclass == 0x1D4. Retail 0x002ea73c-0x002ea784 confirms the progress and class checks, sets the indexed completion flag byte, and writes 2 to moby+0x20; 0x002ea788-0x002ea7b8 plays the completion entry and releases movement audio. The 0x002ea578 state-1 guard excludes this state from subsequent driver following, proving a gate-open latched state rather than a moving state. --- src/overlays/l08/mobys/swing_gate.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l08/mobys/swing_gate.c b/src/overlays/l08/mobys/swing_gate.c index e9116fb4b5..7844e11c3a 100644 --- a/src/overlays/l08/mobys/swing_gate.c +++ b/src/overlays/l08/mobys/swing_gate.c @@ -40,7 +40,7 @@ void swing_gate_update(struct Moby *moby) __asm__("FUN_L08_002ea4c0"); /* Moby classes 468, 469 */ void swing_gate_update(struct Moby *moby) { - SwingGateVars *swing_gate_vars = (SwingGateVars *)moby->pvars; + enum { SWING_GATE_STATE_INITIALIZE = 0 , SWING_GATE_STATE_FOLLOW_DRIVER = 1 , SWING_GATE_STATE_OPEN_LATCHED = 2 } ;SwingGateVars *swing_gate_vars = (SwingGateVars *)moby->pvars; f32 progress = *(f32 *)D_L08_0015FFD8[swing_gate_vars->driver].pvars; Vec4 gate_rotation_matrix[4]; Vec4 gate_position_offset; @@ -55,12 +55,12 @@ void swing_gate_update(struct Moby *moby) { moby->visible = 1; moby->flags &= ~1; } - if (moby->state == 0) { - moby->state = 1; + if (moby->state == SWING_GATE_STATE_INITIALIZE) { + moby->state = SWING_GATE_STATE_FOLLOW_DRIVER; qcopy(&swing_gate_vars->home, &moby->pos); return; } - if (moby->state != 1) + if (moby->state != SWING_GATE_STATE_FOLLOW_DRIVER) return; yaw = fast_subtract_rotations(swing_gate_vars->open_deg * DEG_TO_RAD, swing_gate_vars->shut_deg * DEG_TO_RAD); @@ -96,7 +96,7 @@ void swing_gate_update(struct Moby *moby) { fast_vec_add(&moby->pos, &swing_gate_vars->home, &gate_position_offset); if (progress == 1.0f && moby->oclass == 0x1D4) { D_0013D388[swing_gate_vars->flag + 0x30] = 1; - moby->state = 2; + moby->state = SWING_GATE_STATE_OPEN_LATCHED; allocate_voice_for_target_entry(1, 0, moby); if (moby->oclass == 0x1D4 && voice_is_playing(moby, swing_gate_vars->voice)) release_voice_slot(swing_gate_vars->voice); From def2ff35a05f0f87039a6fe6a29a12aa66a97946 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:19:22 +0000 Subject: [PATCH 0764/1502] decomp: clarify names in update_swinging_door domain_0_value_0 -> SWINGING_DOOR_INITIALIZE: Retail 0x002a3bec-0x002a3bf0 reads the door argument s3+0x20 and skips volume checks when zero. The same byte selects the switch at 0x002a3ce4-0x002a3d08; its zero branch initializes closed yaw and swing at 0x002a3d10-0x002a3d64. This is the existing local SWINGING_DOOR_INITIALIZE domain, not the linked trigger state. domain_1_value_1 -> SWINGING_DOOR_CLOSED: Retail 0x002a3d50-0x002a3d64 clears door swing, stores the initial closed yaw, and writes 1 to the door argument s3+0x20. That same byte selects the existing SWINGING_DOOR_CLOSED branch, which resets swing and restores closed_yaw at 0x002a3d68-0x002a3d74. domain_2_value_2 -> SWINGING_DOOR_OPENING: In the closed branch retail 0x002a3d70-0x002a3d7c tests the opening request s5 and loads 2; 0x002a3dfc-0x002a3e00 writes it to the same door s3+0x20 used by the state switch. Its existing SWINGING_DOOR_OPENING branch advances swing toward the configured angle at 0x002a3d80-0x002a3dd0. domain_3_value_3 -> SWINGING_DOOR_OPEN: Retail 0x002a3db0-0x002a3dd0 compares opening swing with the configured angular endpoint, clamps swing to that endpoint, then writes 3 to door s3+0x20. The existing SWINGING_DOOR_OPEN branch at 0x002a3df4 waits for the closing request, proving this assignment enters the same open state. domain_4_value_4 -> SWINGING_DOOR_CLOSING: Retail 0x002a3df4-0x002a3e00 tests closing request s4 in the open branch and stores 4 to door s3+0x20. The same selector's existing SWINGING_DOOR_CLOSING branch at 0x002a3e18-0x002a3e6c reverses the angular increment and clamps swing to zero. domain_5_value_1 -> SWINGING_DOOR_CLOSED: Retail 0x002a3e4c-0x002a3e6c in the closing branch compares updated swing with zero, clamps it to zero, and writes 1 to door s3+0x20. This is the same field and value as the existing SWINGING_DOOR_CLOSED switch case, which restores the stored closed yaw. domain_6_value_2 -> SWINGING_DOOR_OPENING: Retail 0x002a3e88-0x002a3e94 tests opening request s5 while closing and writes 2 to door s3+0x20 when requested. This reenters the same existing SWINGING_DOOR_OPENING branch as the closed-to-opening transition at 0x002a3d7c/0x002a3e00, permitting reversal before closure. --- src/overlays/l15/mobys/swinging_door.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l15/mobys/swinging_door.c b/src/overlays/l15/mobys/swinging_door.c index e9912d5df9..cb44638c16 100644 --- a/src/overlays/l15/mobys/swinging_door.c +++ b/src/overlays/l15/mobys/swinging_door.c @@ -50,7 +50,7 @@ void swinging_door_update(struct Moby *moby) { f32 yaw; if (door_vars->trigger == -1) { - if (moby->state != 0) { + if (moby->state != SWINGING_DOOR_INITIALIZE) { if (is_point_inside_clip_volume(&hero.motion.pos, door_vars->open_volume) || is_point_inside_clip_volume(D_L15_001673C0, door_vars->open_volume)) { open = 1; @@ -92,13 +92,13 @@ void swinging_door_update(struct Moby *moby) { door_vars->swing = 0.0f; door_vars->closed_yaw = yaw; moby->rot.z = yaw; - moby->state = 1; + moby->state = SWINGING_DOOR_CLOSED; break; case SWINGING_DOOR_CLOSED: door_vars->swing = 0.0f; moby->rot.z = door_vars->closed_yaw; if (open) { - moby->state = 2; + moby->state = SWINGING_DOOR_OPENING; door_vars->sound = allocate_voice_for_target_entry(0, 0, (int)moby); } break; @@ -110,7 +110,7 @@ void swinging_door_update(struct Moby *moby) { limit = swinging_door_swing_angle_degrees_gp * DEG_TO_RAD; if (door_vars->swing < limit) { door_vars->swing = limit; - moby->state = 3; + moby->state = SWINGING_DOOR_OPEN; } step = door_vars->swing; if (door_vars->reverse) { @@ -120,7 +120,7 @@ void swinging_door_update(struct Moby *moby) { break; case SWINGING_DOOR_OPEN: if (close) { - moby->state = 4; + moby->state = SWINGING_DOOR_CLOSING; door_vars->sound = allocate_voice_for_target_entry(0, 0, (int)moby); } break; @@ -131,7 +131,7 @@ void swinging_door_update(struct Moby *moby) { swinging_door_swing_duration_gp * DEG_TO_RAD * frame_time)); if (0.0f < door_vars->swing) { door_vars->swing = 0.0f; - moby->state = 1; + moby->state = SWINGING_DOOR_CLOSED; } step = door_vars->swing; if (door_vars->reverse) { @@ -139,7 +139,7 @@ void swinging_door_update(struct Moby *moby) { } moby->rot.z = fast_add_rotations(door_vars->closed_yaw, step); if (open) { - moby->state = 2; + moby->state = SWINGING_DOOR_OPENING; } break; } From 4f7e06c36f87ace3305d02e81658603074b5416d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:19:23 +0000 Subject: [PATCH 0765/1502] decomp: clarify names in update_armed_transport_damage_and_targeting domain_1_value_8 -> ARMED_TRANSPORT_STATE_DYING: Retail 0x002e2c7c loads the same transport moby's state byte at s2+0x20 and 0x002e2c80 skips further damage when it equals 8. The supplied armed_transport_update calls this function on transport_moby before switching on MOBY(transport_moby)->state, whose existing ARMED_TRANSPORT_STATE_DYING=8 branch lowers altitude, advances the death timer and explodes/removes this transport. This is that exact transport state domain. domain_2_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Authoritative C identifies this selector as hero.vehicle_mode, separate from hero state and gravity selectors. Original retail 0x002e2ca8 loads the hero mode byte at 0x001413f4 and 0x002e2cac compares it with 2 before testing hit.amount >= 2.0 and forcing the fatal response. The supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h canonically defines HERO_VEHICLE_MODE_GIANT_CLANK=2 for this exact selector. domain_3_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x002e2d50 again loads the byte at 0x001413f4 and 0x002e2d54 skips sound entry 2 when that mode equals 2; authoritative C maps this second comparison to hero.vehicle_mode != 2. This is the same HeroVehicleMode selector as the earlier damage comparison, so reuse its canonical HERO_VEHICLE_MODE_GIANT_CLANK=2 member, not a hero-state or response-code constant. domain_4_value_8 -> ARMED_TRANSPORT_STATE_DYING: Retail 0x002e2d64-0x002e2d90 removes the transport's passenger mobys, then 0x002e2d94/0x002e2da0 stores 8 to the owning transport state byte at s2+0x20, and 0x002e2d9c/0x002e2da8 initializes its scaled 90-frame death timer at pvars+0x160. The supplied armed_transport_update dispatches that same moby's state with existing ARMED_TRANSPORT_STATE_DYING=8, consuming that timer before explosion/removal. Reuse the same name as the damage exclusion comparison. --- src/overlays/shared/enemies/armed_transport.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/enemies/armed_transport.c b/src/overlays/shared/enemies/armed_transport.c index 95ab718d3e..1597917758 100644 --- a/src/overlays/shared/enemies/armed_transport.c +++ b/src/overlays/shared/enemies/armed_transport.c @@ -443,7 +443,7 @@ void armed_transport_update(char *transport_moby) { /* Update interaction ownership, damage responses and pursuit tracking. */ void update_armed_transport_damage_and_targeting(struct Moby *transport_moby) { - L16Hit_e hit; + enum { ARMED_TRANSPORT_STATE_DYING = 8 } ;L16Hit_e hit; ArmedTransportVars *transport_data = (ArmedTransportVars *)transport_moby->pvars; float zero; char *hit_record; @@ -466,9 +466,9 @@ void update_armed_transport_damage_and_targeting(struct Moby *transport_moby) { hit_record = find_moby_hit(transport_moby, 0x330000, 0); response = hit_reaction( transport_moby, hit_record, &transport_data->health, 0, &hit.status, &hit.amount, 0, 4); - if (hit.status != 1 && transport_moby->state != 8) { + if (hit.status != 1 && transport_moby->state != ARMED_TRANSPORT_STATE_DYING) { transport_data->health -= hit.amount; - if (transport_data->health <= zero || (hero.vehicle_mode == 2 && hit.amount >= 2.0f)) + if (transport_data->health <= zero || (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && hit.amount >= 2.0f)) response = 1; if (response > 0) { if (response >= 3) { @@ -479,7 +479,7 @@ void update_armed_transport_damage_and_targeting(struct Moby *transport_moby) { } } else { FUN_0022da68_i(3, 0, transport_moby); - if (hero.vehicle_mode != 2) + if (hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK) FUN_0022da68_i(2, 0, transport_moby); { int *child = (int *)(&transport_data->unkC0), count = 3; @@ -490,7 +490,7 @@ void update_armed_transport_damage_and_targeting(struct Moby *transport_moby) { child++; } while (--count >= 0); } - transport_moby->state = 8; + transport_moby->state = ARMED_TRANSPORT_STATE_DYING; transport_data->unk160 = scale_game_frames(90); transport_data->unk67 = 120; } From 77b78e12267f3b397140772ac6105f969e24383b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:19:23 +0000 Subject: [PATCH 0766/1502] decomp: clarify names in update_fleet_backdrop_animation domain_0_value_0 -> FLEET_BACKDROP_STATE_UNINITIALIZED: Retail 0x002f38dc loads the backdrop moby's byte state from s3+0x20; 0x002f38e0 branches to ongoing animation when nonzero. The zero path initializes five UV angles at 0x002f38f4-0x002f3930, copies the position, builds geometry anchors through 0x002f39cc, and returns without registering drawing. The source's moby->state == 0 thus selects the uninitialized backdrop state, independently of the hero state field read earlier. domain_1_value_1 -> FLEET_BACKDROP_STATE_INITIALIZED: Retail 0x002f38e8 loads 1 and 0x002f38f0 stores it to the same backdrop moby state byte at s3+0x20 before the one-time angle and geometry setup. Subsequent calls branch at 0x002f38e0 to 0x002f39d0, updating color blends, UV rotations and scrolling offsets, then registering draw_fleet_backdrop_quads at 0x002f3b38. This assignment marks that initialization has been entered so later calls run the initialized animation path. --- src/overlays/l17/mobys/fleet_backdrop.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l17/mobys/fleet_backdrop.c b/src/overlays/l17/mobys/fleet_backdrop.c index bd24afcde9..8e8c54398f 100644 --- a/src/overlays/l17/mobys/fleet_backdrop.c +++ b/src/overlays/l17/mobys/fleet_backdrop.c @@ -198,7 +198,7 @@ void fleet_backdrop_animation_update(struct Moby *moby) __asm__("FUN_L17_002f384 /* Moby class 1772 */ void fleet_backdrop_animation_update(struct Moby *moby) { - FleetBackdropAnimationVars *moby_pvars = (FleetBackdropAnimationVars *)moby->pvars; + enum { FLEET_BACKDROP_STATE_UNINITIALIZED = 0 , FLEET_BACKDROP_STATE_INITIALIZED = 1 } ;FleetBackdropAnimationVars *moby_pvars = (FleetBackdropAnimationVars *)moby->pvars; float offset_accumulator[4]; float pvar_angle_offset[4]; float vector_sum[4]; @@ -215,8 +215,8 @@ void fleet_backdrop_animation_update(struct Moby *moby) { D_L17_0015F638 = 10.0f; } done: - if (moby->state == 0) { - moby->state = 1; + if (moby->state == FLEET_BACKDROP_STATE_UNINITIALIZED) { + moby->state = FLEET_BACKDROP_STATE_INITIALIZED; for (i = 0; i < 5; i++) { backdrop_quad_uv_rotation_angles[i] = (float)i * 25.0f; } From ebfd1d64a738896c2e5a36002e768e8abdec2ce7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:19:23 +0000 Subject: [PATCH 0767/1502] decomp: clarify names in update_armed_transport_rocket domain_0_value_0 -> ARMED_TRANSPORT_ROCKET_STATE_FLYING: The bound source src/overlays/shared/enemies/armed_transport_rocket.c SHA-256 87aa3a243530d595ca795f3b68fee7459902f33386151506c39178736d2613c1 selects MOBY(rocket_moby)->state, not a hero state or control mode. Retail 0x002a0b18 loads the byte at rocket+0x20 and 0x002a0b1c returns for nonzero; original Ghidra likewise gates the entire flight body on cVar1 == 0. The zero branch emits the rocket trail, steers toward its target (0x002a0b38-0x002a0be8), computes movement and collision (0x002a0c28-0x002a0c98), and copies the next position at 0x002a0d8c-0x002a0d90 or explodes/removes on impact. The supplied spawn function initializes this same rocket state byte to zero. Thus zero is this rocket's flying state; it is unrelated to HERO_STATE_IDLE. domain_1_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: The authoritative source identifies the selector as hero.vehicle_mode. Original Ghidra compares cRam001413f4 against 2, and retail 0x002a0cc0-0x002a0cc8 loads that global byte at 0x001413f4 and compares it to 2 before the extra impact sound at 0x002a0cf8. This is the HeroVehicleMode domain supplied from include/rnc/hero/hero_state.h, whose canonical member HERO_VEHICLE_MODE_GIANT_CLANK has value 2. Reuse follows the actual vehicle_mode selector, not numerical agreement with HERO_STATE_RUN or HERO_GRAVITY_TOWARD_REFERENCE_POINT. --- src/overlays/shared/enemies/armed_transport_rocket.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/armed_transport_rocket.c b/src/overlays/shared/enemies/armed_transport_rocket.c index 650280132b..d38dafaf09 100644 --- a/src/overlays/shared/enemies/armed_transport_rocket.c +++ b/src/overlays/shared/enemies/armed_transport_rocket.c @@ -55,7 +55,7 @@ void armed_transport_rocket_update(char *m) __asm__("FUN_L16_002a0a98"); /* Moby class 50 */ void armed_transport_rocket_update(char *rocket_moby) { - float desired[4], next_position[4], delta[4], blend[4]; + enum { ARMED_TRANSPORT_ROCKET_STATE_FLYING = 0 } ;float desired[4], next_position[4], delta[4], blend[4]; char *rocket_data = ((char *)MOBY(rocket_moby)->pvars); void *remaining; float yaw, pitch; @@ -64,7 +64,7 @@ void armed_transport_rocket_update(char *rocket_moby) { *(int *)(rocket_data + 0x34) = 1; trooper_play_sound(5, 0, (int)rocket_moby, 0x54C); } - if (MOBY(rocket_moby)->state != 0) + if (MOBY(rocket_moby)->state != ARMED_TRANSPORT_ROCKET_STATE_FLYING) return; spawn_rocket_trail_spark(rocket_moby); fast_vec_sub(delta, rocket_data + 0x10, &MOBY(rocket_moby)->pos); @@ -92,7 +92,7 @@ void armed_transport_rocket_update(char *rocket_moby) { remaining = delta; if (collision_line(&MOBY(rocket_moby)->pos, next_position, 0, rocket_moby, 0) != 0 || fast_vec_length(remaining) < *(float *)(rocket_data + 0x24)) { - if (hero.vehicle_mode == 2) + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) play_entity_sound( (int)rocket_moby, 2.0f, &MOBY(rocket_moby)->pos, 3, 2.0f, 1.0f, 0, 1, 0); trooper_play_sound(4, 0, (int)rocket_moby, 0x54C); From e51ec3f9ab66791d268798e1a22ad6ff669e54f0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:21:17 +0000 Subject: [PATCH 0768/1502] decomp: clarify names in render_level_frame domain_2_value_3 -> MEMCARD_REQUEST_FORMAT: Retail 0x0022f400-0x0022f410 forms 0x0013d290, loads its +0xd4 current operation field, and tests signed < 3 to select the overlay. Original Ghidra identifies g_nMemoryCardOperationState; the SHA-bound C maps this exact test to memory_card_state.state >= 3. The shared memory_card_state.h declaration context explicitly assigns state/pending_state to MemoryCardOperation, whose canonical member MEMCARD_REQUEST_FORMAT is 3. Preserve the >= threshold and reuse that operation member, rather than any unrelated substep with value 3. domain_3_value_0 -> MEMCARD_QUERY_INFO: Retail 0x0022f418 loads +0xdc from the same 0x0013d290 memory-card object and 0x0022f41c branches away on a negative pending operation, otherwise drawing the fixed and rotating overlay. Original Ghidra calls this g_nPendingMemoryCardOperationState; the SHA-bound source maps it to memory_card_state.pending_state >= 0. The shared header explicitly assigns pending_state to MemoryCardOperation with canonical MEMCARD_QUERY_INFO = 0, establishing the domain independently of equal-valued probe/create/read substeps. Preserve the signed >= comparison. --- src/rendering/frame/render_level_frame.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/frame/render_level_frame.c b/src/rendering/frame/render_level_frame.c index be852bfbcf..6dd558318a 100644 --- a/src/rendering/frame/render_level_frame.c +++ b/src/rendering/frame/render_level_frame.c @@ -90,7 +90,7 @@ void render_level_frame(void) { if ((current_level_index != 0) && ((current_level_index != 1) || (level_available[3] != 0))) { render_environment_mapped_object(D_0018CC98[0]); } - if ((memory_card_state.state >= 3) || (memory_card_state.pending_state >= 0)) { + if ((memory_card_state.state >= MEMCARD_REQUEST_FORMAT) || (memory_card_state.pending_state >= MEMCARD_QUERY_INFO)) { vu1_add_g_sregister(0x47, 0x3004B); quad_extent = 272.0f; texture = get_effect_texture(2); From 2d6ed474dcf1bd9f85c6f6aa8657d83154659ce2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:21:17 +0000 Subject: [PATCH 0769/1502] decomp: clarify names in update_pokitaru_boat_joint_effects domain_0_value_1 -> POKITARU_BOAT_WAIT_FOR_ACTIVATION: The authoritative pokitaru_boat_update source passes its unchanged moby to update_pokitaru_boat_joint_effects before switching on that same moby->state; its local enum names value 1 POKITARU_BOAT_WAIT_FOR_ACTIVATION, whose branch waits for boat_vars->flag_b8 before changing state to 5. This is the boat Moby state domain, not any Hero enum. At retail 0x0030a594-0x0030a5a0, lbu v0,0x20(s2) compares against s6=1 and selects the slower frame_time*2.6179938 joint rotation step. domain_1_value_1 -> POKITARU_BOAT_WAIT_FOR_ACTIVATION: The authoritative pokitaru_boat_update source passes its unchanged moby to update_pokitaru_boat_joint_effects before switching on that same moby->state; its local enum names value 1 POKITARU_BOAT_WAIT_FOR_ACTIVATION, whose branch waits for boat_vars->flag_b8 before changing state to 5. This is the boat Moby state domain, not any Hero enum. At retail 0x0030a614-0x0030a630, lbu v1,0x20(s2) compares against 1 and skips effect spawning on odd level_frame values. domain_2_value_1 -> POKITARU_BOAT_WAIT_FOR_ACTIVATION: The authoritative pokitaru_boat_update source passes its unchanged moby to update_pokitaru_boat_joint_effects before switching on that same moby->state; its local enum names value 1 POKITARU_BOAT_WAIT_FOR_ACTIVATION, whose branch waits for boat_vars->flag_b8 before changing state to 5. This is the boat Moby state domain, not any Hero enum. At retail 0x0030a678-0x0030a68c, lbu v0,0x20(s2), xori by 1 and movz select one effect per joint for this state, otherwise two. domain_3_value_1 -> POKITARU_BOAT_WAIT_FOR_ACTIVATION: The authoritative pokitaru_boat_update source passes its unchanged moby to update_pokitaru_boat_joint_effects before switching on that same moby->state; its local enum names value 1 POKITARU_BOAT_WAIT_FOR_ACTIVATION, whose branch waits for boat_vars->flag_b8 before changing state to 5. This is the boat Moby state domain, not any Hero enum. At retail 0x0030a738-0x0030a754, lbu v0,0x20(s2) compares against s3=1 and multiplies the initial XY motion magnitude by 0.4. --- src/overlays/l11/mobys/pokitaru_boat.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/overlays/l11/mobys/pokitaru_boat.c b/src/overlays/l11/mobys/pokitaru_boat.c index dd8d293bf5..a41db7bcfc 100644 --- a/src/overlays/l11/mobys/pokitaru_boat.c +++ b/src/overlays/l11/mobys/pokitaru_boat.c @@ -330,6 +330,9 @@ struct DataA500 { }; void update_pokitaru_boat_joint_effects(struct Moby *moby) { + enum { + POKITARU_BOAT_WAIT_FOR_ACTIVATION = 1 + }; struct DataA500 *moby_vars = (struct DataA500 *)moby->pvars; float joint_world_position[4]; float pos[4]; @@ -347,7 +350,7 @@ void update_pokitaru_boat_joint_effects(struct Moby *moby) { if (!((u8 *)moby_vars)[i * 0x40 + 0x101]) attach_manipulator(moby, i, &moby_vars->parts[i]); step = frame_time * 12.217304f; - if (moby->state == 1) + if (moby->state == POKITARU_BOAT_WAIT_FOR_ACTIVATION) step = frame_time * 2.6179938f; if (((u8 *)moby_vars)[i * 0x40 + 0x101]) { moby_vars->angle[i] = fast_add_rotations(moby_vars->angle[i], step); @@ -356,20 +359,20 @@ void update_pokitaru_boat_joint_effects(struct Moby *moby) { } if (vector_distance_xy(&moby->pos, camera_pos_b358) > 38.0f) return; - if (moby->state == 1 && (level_frame & 1)) + if (moby->state == POKITARU_BOAT_WAIT_FOR_ACTIVATION && (level_frame & 1)) return; if (!(moby->pos.z < 224.5f)) return; for (j = 0; j < 4; j++) { moby_point_position(moby, j, joint_world_position); - iterations_per_joint = moby->state == 1 ? 1 : 2; + iterations_per_joint = moby->state == POKITARU_BOAT_WAIT_FOR_ACTIVATION ? 1 : 2; for (k = 0; k < iterations_per_joint; k++) { pos[0] = joint_world_position[0] + randf_sym(0.0f, 0.3f); pos[1] = joint_world_position[1] + randf_sym(0.0f, 0.3f); pos[2] = joint_world_position[2] + randf_sym(0.0f, 0.3f); heading = fast_add_rotations(moby->rot.z, randf_sym(0.0f, 0.122173049f) + 3.1415927f); speed = random_float_between(2.0f, 5.0f) * frame_time; - if (moby->state == 1) + if (moby->state == POKITARU_BOAT_WAIT_FOR_ACTIVATION) speed *= 0.4f; initial_velocity[0] = fast_cos(heading) * speed; initial_velocity[1] = fast_sin(heading) * speed; From cae2b8a521c07e6323685b46693c79668853f3f9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:21:18 +0000 Subject: [PATCH 0770/1502] decomp: clarify names in giant_clank_pad_update domain_0_value_2 -> GIANT_CLANK_PAD_CHECK_ACTIVATION: The authoritative C assigns moby->state in the arm-activation branch. Retail 0x002ed088 loads this same Moby +0x20 selector; 0x002ed138..0x002ed140 writes 2 there. The next invocation dispatches 2 at 0x002ed0b0 to activation checking at 0x002ed144, already named GIANT_CLANK_PAD_CHECK_ACTIVATION in the local enum. domain_1_value_2 -> GIANT_CLANK_PAD_CHECK_ACTIVATION: This is the second C spelling of the arm-activation store to moby->state, whose existing fakematch branches represent retail 0x002ed138..0x002ed140 writing 2 to Moby +0x20. Retail dispatch at 0x002ed0b0 routes that selector value to 0x002ed144, the existing GIANT_CLANK_PAD_CHECK_ACTIVATION branch. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002ed180 loads the byte at hero +0x20a4 (0x001413f4), identified by current C as hero.vehicle_mode, and 0x002ed184 tests it against zero before help 0x3aa4. Supplied enter_hero_vehicle_mode context writes its mode parameter to that exact field. It therefore belongs to the supplied HeroVehicleMode domain, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT. domain_3_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x002ed180 loads hero +0x20a4, and 0x002ed1a0 tests that same byte against 2 before the level gate and help 0x3aa5. Current C identifies the field as hero.vehicle_mode; supplied enter_hero_vehicle_mode context stores the mode parameter there and handles HERO_VEHICLE_MODE_GIANT_CLANK. The shared HeroVehicleMode enum canonically names 2 HERO_VEHICLE_MODE_GIANT_CLANK. domain_4_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x002ed1e8..0x002ed1f0 compares hero +0x20a4 with 2, then the level-15 path hides the linked Moby and calls restore_saved_hero_moby_and_clear_vehicle_mode at 0x002ed230. Current C and supplied enter_hero_vehicle_mode context bind +0x20a4 to vehicle_mode, proving the shared HeroVehicleMode domain and its canonical HERO_VEHICLE_MODE_GIANT_CLANK member. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002ed274..0x002ed278 loads hero +0x20a4 and returns if nonzero. The zero path activates the linked Moby and calls enter_hero_vehicle_mode with mode 2 at 0x002ed2ec..0x002ed304. Current C identifies the selector as hero.vehicle_mode and supplied helper context stores mode in this field, proving HeroVehicleMode rather than HeroStateId; zero is its canonical HERO_VEHICLE_MODE_ON_FOOT. --- src/overlays/shared/vehicles/giant_clank_pad.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/vehicles/giant_clank_pad.c b/src/overlays/shared/vehicles/giant_clank_pad.c index 0d55e8dea8..92a8d56d31 100644 --- a/src/overlays/shared/vehicles/giant_clank_pad.c +++ b/src/overlays/shared/vehicles/giant_clank_pad.c @@ -56,23 +56,23 @@ void giant_clank_pad_update(struct Moby *moby) { case GIANT_CLANK_PAD_ARM_ACTIVATION: /* Fakematch: the second store gives retail's register for moby. */ if (moby) - moby->state = 2; + moby->state = GIANT_CLANK_PAD_CHECK_ACTIVATION; else - moby->state = 2; + moby->state = GIANT_CLANK_PAD_CHECK_ACTIVATION; return; case GIANT_CLANK_PAD_CHECK_ACTIVATION: if (hero.ground_moby == moby && hero.air_frames.s == 0 && D_L15_0015F5C4 != 2 && hero.state.current != 0x1d) { - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { try_set_help_message(4, 0x3aa4); - } else if (hero.vehicle_mode == 2 && current_level_index != 0x12) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && current_level_index != 0x12) { try_set_help_message(4, 0x3aa5); } if (!(((u32)pad_pressed_lui) & 0x10)) return; if (D_L15_0015F594 != 4) return; - if (hero.vehicle_mode == 2 && current_level_index == 0xf) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && current_level_index == 0xf) { pad = l15_moby_array; pad += *(int *)((u8 *)linked + 0x60); pad->flags |= 1; @@ -86,7 +86,7 @@ void giant_clank_pad_update(struct Moby *moby) { request_music_track(0, 5); return; } - if (hero.vehicle_mode != 0) + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) return; pad = l15_moby_array; pad += *(int *)((u8 *)linked + 0x60); From 136bd2889d99662d5e6d08036184f0da46eb6945 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:21:18 +0000 Subject: [PATCH 0771/1502] decomp: clarify names in transition_default_draw domain_2_value_4 -> GAME_MODE_DIALOG: Authoritative source tests game_mode == 4 solely to invoke established draw_dialog_text(). Retail 0x001eb6ac-0x001eb6b8 loads game_mode at 0x0015f604, compares it with 4, and branches over the 0x001eb6c0 call to draw_dialog_text at 0x001fbc50 on inequality. Original retail Ghidra independently shows the same g_nGameStage == 4 guard and draw_dialog_text call. This names a game-mode selector by its proven dialog-rendering behavior, without mixing it with font_state or moby states. --- src/game/transitions/transition_default_draw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/game/transitions/transition_default_draw.c b/src/game/transitions/transition_default_draw.c index f14ed885d0..8109f06ff7 100644 --- a/src/game/transitions/transition_default_draw.c +++ b/src/game/transitions/transition_default_draw.c @@ -54,6 +54,9 @@ extern s32 light_ties() __asm__("func_00237370"); void transition_default_draw(s32 *unused_parameter) __asm__("FUN_001eb410"); void transition_default_draw(s32 *unused_parameter) { + enum { + GAME_MODE_DIALOG = 4 + }; s32 language_overlay_index; if (level_sky_effect_data == 0 || level_sky_effect_data->unk4 != 0) { @@ -132,7 +135,7 @@ void transition_default_draw(s32 *unused_parameter) { } vu0_load_micro_program(D_00100AE0); FlushCache(0); - if (game_mode == 4) { + if (game_mode == GAME_MODE_DIALOG) { draw_dialog_text(); } vu1_sync_chain(2); From 88f696ce84693c5d3071d36fbc42b4a13c30c4c2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:23:04 +0000 Subject: [PATCH 0772/1502] decomp: clarify names in update_fading_debris_particle_with_landing_spawn domain_0_value_3 -> DEBRIS_KIND_UPWARD_ACCELERATING: SHA-bound C 705d50526eb50bb6883156d7df8ae3884b2ac8d9187b1259fa5a857e51317cb8 identifies particle_data->kind at particle+0x3A. Original retail decompilation corroborates the comparison sVar2 == 3 and kind-indexed gravity. Retail 0x0026c0b0/0x0026c0e8 computes -(D_0015ED70*0.24), stored as table element 3 at 0x0026c114 and copied to sp+0x1C. At 0x0026c280-0x0026c298 the signed kind indexes this table and its element is subtracted from vertical velocity at particle+0x28; kind 3 therefore supplies upward acceleration. The same field is compared with 3 at 0x0026c104/0x0026c138 for the additional lifetime tick. At 0x0026c378/0x0026c37c the landing path calls mine_debris with kind 3; supplied mine_debris C stores that argument at particle_data+0x1A and initializes velocity from initial_velocity. This proves the debris-kind domain independently of the equal-valued, unrelated HERO_STATE_STOP constant. --- .../rendering/effects/update_three_phase_effect_particle.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c b/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c index 478a8b5202..fc458fe953 100644 --- a/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c +++ b/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c @@ -1351,6 +1351,9 @@ extern int hud_counter_update(int, int, float) __asm__("FUN_L00_002371e0"); void update_fading_debris_particle_with_landing_spawn(Part *particle) __asm__("FUN_L00_0026c088"); void update_fading_debris_particle_with_landing_spawn(Part *particle) { + enum { + DEBRIS_KIND_UPWARD_ACCELERATING = 3 + }; float saved[4]; float grav[4] = { D_0015ED70 * 4.8f, D_0015ED70 * 24.5f, D_0015ED70 * 9.8f, -(D_0015ED70 * 0.24f)}; @@ -1358,7 +1361,7 @@ void update_fading_debris_particle_with_landing_spawn(Part *particle) { int alpha, spawn_lifetime, k; float reference_distance_or_spawn_size; - if (particle_data->kind == 3 && D_L00_0015F5D0 > 0.95f) + if (particle_data->kind == DEBRIS_KIND_UPWARD_ACCELERATING && D_L00_0015F5D0 > 0.95f) fast_dec_timer_s16(&particle->timer); if (fast_dec_timer_s16(&particle->timer)) { free_effect_particle(particle); From b97fc952648e4903d42d7e49f3163176e23b1d53 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:23:05 +0000 Subject: [PATCH 0773/1502] decomp: clarify names in spawn_bolt_by_value domain_0_value_1 -> BOLT_FALLING: Retail 002a74ac-002a7510 allocates bolt classes 0xD..0x10 into s1; 002a7570 loads t0=1 and 002a759c stores that byte at s1+0x20, the authoritative spawned_bolt->state. The same snapshot's bolt_update names state 1 BOLT_FALLING and applies gravity to vars->vel.z, adds velocity to position, rotates by the spin quaternion and transitions on ground collision to BOLT_SETTLING. Spawn initializes that velocity at 002a7620-002a762c and spin at 002a76bc-002a76d4, proving the same bolt state domain rather than an equal-valued hero/control mode. --- src/overlays/shared/pickups/bolt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/pickups/bolt.c b/src/overlays/shared/pickups/bolt.c index fdfe55ff1f..00c108b741 100644 --- a/src/overlays/shared/pickups/bolt.c +++ b/src/overlays/shared/pickups/bolt.c @@ -739,6 +739,9 @@ struct Moby *spawn_bolt_by_value( BOLT_VALUE_TWENTY = 20, BOLT_VALUE_FIFTY = 50 }; + enum { + BOLT_FALLING = 1 + }; f32 spin_axis[4] __attribute__((aligned(16))); f32 bolt_to_source_offset[4] __attribute__((aligned(16))); struct Moby *spawned_bolt; @@ -783,7 +786,7 @@ struct Moby *spawn_bolt_by_value( spawned_bolt->update_dist = 0x40; spawned_bolt->draw_dist = 0x40; spawned_bolt->visible = 1; - spawned_bolt->state = 1; + spawned_bolt->state = BOLT_FALLING; spawned_bolt->scale = spawned_bolt->pclass->scale * scale; euler_rotation_basis(&spawned_bolt->rot_row0, &spawned_bolt->rot); if ((bolt_source->flags & 0x20) && (color = *(u8 **)(bolt_source->pvars + 0xC)) != 0) From e521a485a153a7bc0db95ec484327661b8a1f243 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:24:47 +0000 Subject: [PATCH 0774/1502] decomp: clarify names in move_extermibot_along_path domain_0_value_2 -> EXTERMIBOT_TARGET_PATH_UNAVAILABLE: Retail 0x00303b48 loads pvars into s2. At 0x00303b60-0x00303b78 follow_path receives pvars+0x2C0 path IDs, +0x2C4 path index, moby+0x10 start, incoming destination and +0x280 goal output. The bne at 0x00303b7c skips the store on success; only zero return executes li v0,2 at 0x00303b84 and sw v0,0x164(s2) at 0x00303b88. Supplied follow_path returns zero when obstruction has no reachable goal and returns one for a direct or computed goal. Supplied extermibot_update stops FOLLOW_TARGET and selects RETURN_TO_START when this same pvars+0x164 equals 2; its idle path check also stores 2 on failure. This is target-path unavailability, not moby state 2 (stored separately at moby+0x20). --- src/overlays/l05/mobys/extermibot.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l05/mobys/extermibot.c b/src/overlays/l05/mobys/extermibot.c index 1b1b3f0cd3..ccbedbf070 100644 --- a/src/overlays/l05/mobys/extermibot.c +++ b/src/overlays/l05/mobys/extermibot.c @@ -965,6 +965,9 @@ extern f32 FUN_L05_00304058_u(s32, void *, void *, f32) __asm__("FUN_L05_0030405 void move_extermibot_along_path(struct Moby *moby, s32 node, f32 side) __asm__("FUN_L05_00303b08"); void move_extermibot_along_path(struct Moby *moby, s32 destination_position, f32 side) { + enum { + EXTERMIBOT_TARGET_PATH_UNAVAILABLE = 2 + }; PathWalkerVars *walker_vars = (PathWalkerVars *)moby->pvars; Vec4f facing_direction, movement_displacement, goal; f32 offset_heading; @@ -978,7 +981,7 @@ void move_extermibot_along_path(struct Moby *moby, s32 destination_position, f32 destination_position, &walker_vars->goal, D_L05_00161A98_gp * 0.4f) == 0) - walker_vars->mode = 2; + walker_vars->mode = EXTERMIBOT_TARGET_PATH_UNAVAILABLE; } qcopy(&goal, &walker_vars->goal); distance_to_goal = vector_distance_xy(&moby->pos, &goal); From d61a1942c25999b7a5b18becf3ce39312517d6ea Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:24:47 +0000 Subject: [PATCH 0775/1502] decomp: clarify names in update_hero_ground_material_effects domain_0_value_2 -> GROUND_MATERIAL_MAGNETIC: Retail 0x0022cd7c loads hero+0x12e0 into s2, matching saved_ground_type from hero.ground_type; supplied update_hero_ground_contact_and_gravity assigns this field from collision_hit_material(). At 0x0022cd9c-0x0022cda0 s2 is compared with 2, and after grounded/proximity checks the delay-slot store at 0x0022cde0 sets hero.on_magnet_ground at +0x12e7. This proves a magnetic ground material, independently of HeroStateId. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0022cdd8 loads the byte at hero+0x20a4, the source hero_ptr->vehicle_mode; 0x0022cddc branches when it is nonzero, restricting the item-slot moby check to mode zero. This is the exact HeroVehicleMode selector, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT. The supplied hero_frame_update and process_hero_hit_response already use that member for hero.vehicle_mode. domain_3_value_0 -> GROUND_MATERIAL_WATER: Retail 0x0022ce38 tests saved material s2 against zero. At 0x0022ce50-0x0022ce68 it computes water_surface_z (+0x2f0) minus ground_z (+0x2d8), storing water_depth (+0x22a4); 0x0022ce78-0x0022ce88 enables wading between depths 0.25 and 0.85. Supplied update_hero_ground_contact_and_gravity sets ground_type from collision_hit_material(), and for material zero resolves water_surface_z and tracks in_water_frames. This proves the water material domain rather than idle state or vehicle mode. --- src/overlays/shared/hero/hero_frame_update.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index 8e0ce87d7a..a7dc5ad76e 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -330,6 +330,10 @@ extern int l01_hero_set_state(int, int) __asm__("FUN_L01_0023cf98"); extern void exit_hero_vehicle_mode_if_mode_three(void) __asm__("FUN_L00_0020b930"); void update_hero_ground_material_effects(void) { + enum { + GROUND_MATERIAL_WATER = 0, + GROUND_MATERIAL_MAGNETIC = 2 + }; struct Hero *hero_ptr = &hero; int saved_ground_type; int x; @@ -342,10 +346,10 @@ void update_hero_ground_material_effects(void) { hero_ptr->unk308 = 0; if (saved_ground_type == -1) return; - if (saved_ground_type == 2) { + if (saved_ground_type == GROUND_MATERIAL_MAGNETIC) { if (hero_ptr->frames_off_ground.s == 0 || hero_ptr->ground_distance < 0.3f) { hero_ptr->on_magnet_ground = 1; - if (hero_ptr->vehicle_mode == 0) { + if (hero_ptr->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { char *item_slot_1_moby = (char *)hero_ptr->items[1].moby; if (item_slot_1_moby != 0 && MOBY(item_slot_1_moby)->oclass == 0xAD) hero_ptr->unk308 = 1; @@ -358,7 +362,7 @@ void update_hero_ground_material_effects(void) { q->water_depth = 0.2f; q->water_surface_z = q->ground_z.f + 0.2f; } - if (saved_ground_type == 0) { + if (saved_ground_type == GROUND_MATERIAL_WATER) { struct Hero *q = &hero; q->water_depth = q->water_surface_z - q->ground_z.f; if (q->water_depth < 0.85f) { From e5feddc63fce81dc95bd393da41fbff5a15d7644 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:24:47 +0000 Subject: [PATCH 0776/1502] decomp: clarify names in gate_1_update domain_0_value_1 -> GATE_STATE_CLOSED: Retail 0x002e966c loads moby state from +0x20 and dispatches the same field that the authoritative C switches over using GateState members. Initialization saves rot.y at 0x002e9718-0x002e971c and stores 1 at 0x002e9724, entering the existing GATE_STATE_CLOSED branch that waits for clip-volume activation. domain_1_value_3 -> GATE_STATE_OPEN: Initialization's already-cleared or saved-open path reaches 0x002e9790, applies -1.3962634 to gate yaw at 0x002e979c-0x002e97a8, then writes 3 to the same moby +0x20 state at 0x002e97b0. This is the GateState domain switched by this function, whose canonical GATE_STATE_OPEN branch handles the opened gate. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative typed C identifies this selector as hero.vehicle_mode, separately from moby->state. Retail 0x002e9728-0x002e9734 forms hero base 0x0013F350 and loads its byte at +0x20A4 (0x001414F4), branching to immediate opening when nonzero. The supplied HeroVehicleMode domain defines this same field's zero member as HERO_VEHICLE_MODE_ON_FOOT; no GateState or HeroStateId equivalence is used. domain_3_value_3 -> GATE_STATE_OPEN: In GATE_STATE_CLOSED, the vehicle-mode or saved-bit bypass joins retail 0x002e9790-0x002e97b0, immediately applying the full opening yaw and storing 3 to moby +0x20. The destination is the same field dispatched at 0x002e966c, already bound by the C switch to shared GateState and GATE_STATE_OPEN. domain_4_value_2 -> GATE_STATE_OPENING: After activation and save-bit writes, retail 0x002e9870-0x002e9888 computes and stores the opening countdown at pvars +8, then 0x002e988c-0x002e9894 stores state 2 into moby +0x20. The dispatcher sends 2 to 0x002e9898, the existing GATE_STATE_OPENING branch that incrementally rotates and decrements this timer. domain_5_value_3 -> GATE_STATE_OPEN: Retail state-2 handler at 0x002e9898-0x002e98c0 applies incremental negative gate yaw, then calls the timer helper on pvars +8 at 0x002e98c4-0x002e98c8. Upon completion it stores 3 at 0x002e98d8 to the same moby state used by the shared GateState switch, completing the transition to canonical GATE_STATE_OPEN. domain_6_value_0 -> GATE_STATE_INITIALIZE: The open-state reset path at retail 0x002e9950-0x002e9964 reverses the full opening rotation when the save bit clears, then writes zero to moby +0x20 at 0x002e9968. The dispatcher at 0x002e9684 sends that value back to 0x002e96ac, the authoritative C's existing GATE_STATE_INITIALIZE branch in the shared GateState domain. --- src/overlays/l10/mobys/gate_1.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l10/mobys/gate_1.c b/src/overlays/l10/mobys/gate_1.c index 697109bd36..88ec3260fb 100644 --- a/src/overlays/l10/mobys/gate_1.c +++ b/src/overlays/l10/mobys/gate_1.c @@ -45,15 +45,15 @@ void gate_1_update(struct Moby *moby) { ((D_0014C190_257218[current_level_index][(short)save_id >> 5] >> (save_id & 31)) & 1) == 0) { gate_control->home_yaw = moby->rot.y; - moby->state = 1; + moby->state = GATE_STATE_CLOSED; return; } } moby->rot.y = fast_add_rotations(moby->rot.y, -1.3962634f); - moby->state = 3; + moby->state = GATE_STATE_OPEN; return; case GATE_STATE_CLOSED: - if (hero.vehicle_mode != 0) + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) goto open; save_id = moby->save_id; if (l10_save_state.cleared[(short)save_id] != 0 || @@ -61,7 +61,7 @@ void gate_1_update(struct Moby *moby) { 0) { open: moby->rot.y = fast_add_rotations(moby->rot.y, -1.3962634f); - moby->state = 3; + moby->state = GATE_STATE_OPEN; return; } if (is_point_inside_clip_volume(&hero.motion.pos, gate_control->clip_volume) == 0 && @@ -76,12 +76,12 @@ void gate_1_update(struct Moby *moby) { if (is_point_inside_clip_volume(&hero.motion.pos, gate_control->clip_volume)) activate_descriptor(gate_control->sound); gate_control->timer = truncate_float_to_s32(FUN_L04_001f1978(90.0f)); - moby->state = 2; + moby->state = GATE_STATE_OPENING; return; case GATE_STATE_OPENING: moby->rot.y = fast_add_rotations(moby->rot.y, -1.3962634f / FUN_L04_001f1978(90.0f)); if (fast_dec_timer(&gate_control->timer)) - moby->state = 3; + moby->state = GATE_STATE_OPEN; return; case GATE_STATE_OPEN: if (D_001413F4_e9648[0] != 0) @@ -93,7 +93,7 @@ void gate_1_update(struct Moby *moby) { 1) == 0) return; moby->rot.y = fast_add_rotations(moby->rot.y, 1.3962634f); - moby->state = 0; + moby->state = GATE_STATE_INITIALIZE; return; } } From bf5d8ac0570515632b13d68ad96a5c0b8491b282 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:24:47 +0000 Subject: [PATCH 0777/1502] decomp: clarify names in apply_taunter_to_nearby_mobies domain_0_value_0 -> NULL: The authoritative C declares state as u8 *, assigns FUN_L00_0025c338_b6bc8(taunter_candidate_moby), and tests state != 0 before accessing state+0x18. Retail 0x002b6c58 calls the helper, 0x002b6c60 moves its pointer return into s2, and 0x002b6c64 branches on s2 == zero to skip the candidate. Subsequent lw at 0x002b6dd0 and sw at 0x002b6df4 use 0x18(s2). Original Ghidra lVar3 likewise guards the record access. Thus zero denotes the absent record pointer, matching the supplied existing NULL constant. --- src/overlays/shared/weapons/taunter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/taunter.c b/src/overlays/shared/weapons/taunter.c index a8e89e12b7..887477f52e 100644 --- a/src/overlays/shared/weapons/taunter.c +++ b/src/overlays/shared/weapons/taunter.c @@ -378,7 +378,7 @@ s32 apply_taunter_to_nearby_mobies(Moby *taunter_moby, f32 radius) { do { state = FUN_L00_0025c338_b6bc8(taunter_candidate_moby); } while (0); - if (state != 0) { + if (state != NULL) { /* Fakematch: &hero through the motion label keeps retail's &hero + 0x98 load below. */ player = (struct Hero *)(D_0013F3D0 - 0x80); distance = vector_distance_xy(&pos, (u8 *)taunter_candidate_moby + 0x10); From da6dd5b8552945a26b2a2c44b58487543356422e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:26:33 +0000 Subject: [PATCH 0778/1502] decomp: clarify names in rocket_launcher_update domain_0_value_1 -> ROCKET_LAUNCHER_TURN_AND_FIRE: Retail 0x002df400 loads Moby+0x20 for state dispatch and 0x002df404 branches on 1 to 0x002df47c, which approaches target yaw and fires after convergence. The timer-expiry path sets a random target yaw at 0x002df45c and stores 1 to that same state byte at 0x002df464. This assignment therefore uses the existing local enum member ROCKET_LAUNCHER_TURN_AND_FIRE. domain_1_value_2 -> ROCKET_LAUNCHER_WAIT_FOR_POST_SHOT_ANIMATION: Retail 0x002df580 loads 2 and 0x002df588 stores it to Moby+0x20 immediately before selecting shot animation 1 and creating the projectile at 0x002df664. Dispatch 0x002df424 sends state 2 to 0x002df674, where glow interpolation and the animation flag test at 0x002df6b8-0x002df6c0 wait for completion. It is the same selector as the existing ROCKET_LAUNCHER_WAIT_FOR_POST_SHOT_ANIMATION case. domain_2_value_0 -> ROCKET_LAUNCHER_WAIT_BETWEEN_SHOTS: Retail 0x002df6b8-0x002df6e0 checks animation completion and returns to animation 0; 0x002df6f8 stores zero to Moby+0x20 and 0x002df70c initializes the pvars+0x08 random wait timer. State dispatch at 0x002df414 sends zero to the timer decrement at 0x002df434-0x002df438. This assignment belongs to the existing ROCKET_LAUNCHER_WAIT_BETWEEN_SHOTS case on the identical state byte. --- src/overlays/l02/mobys/rocket_launcher.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l02/mobys/rocket_launcher.c b/src/overlays/l02/mobys/rocket_launcher.c index 1e9c45d618..717c94fa82 100644 --- a/src/overlays/l02/mobys/rocket_launcher.c +++ b/src/overlays/l02/mobys/rocket_launcher.c @@ -103,7 +103,7 @@ void rocket_launcher_update(struct Moby *moby) { case ROCKET_LAUNCHER_WAIT_BETWEEN_SHOTS: if (fast_dec_timer_s16(&rocket_launcher_vars->wait_timer)) { rocket_launcher_vars->target_yaw = random_float_between(0.0f, 3.14159f); - moby->state = 1; + moby->state = ROCKET_LAUNCHER_TURN_AND_FIRE; allocate_voice_for_target_entry(4, 0, moby); } break; @@ -130,7 +130,7 @@ void rocket_launcher_update(struct Moby *moby) { rocket_launcher_vars->voice = -1; allocate_voice_for_target_entry(3, 0, moby); rocket_launcher_vars->recoil = rocket_launcher_shot_sound_initial_distance_gp; - moby->state = 2; + moby->state = ROCKET_LAUNCHER_WAIT_FOR_POST_SHOT_ANIMATION; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, 1); moby_point_position(moby, 1, &muzzle); @@ -169,7 +169,7 @@ void rocket_launcher_update(struct Moby *moby) { if (moby->anim_flags & 2) { if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, 1); - moby->state = 0; + moby->state = ROCKET_LAUNCHER_WAIT_BETWEEN_SHOTS; rocket_launcher_vars->wait_timer = truncate_float_to_s32(scale_time(random_float_between(60.0f, 180.0f))); } From 2cb3399505f71372d22fccf0e81a894f6261d1a7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:26:33 +0000 Subject: [PATCH 0779/1502] decomp: clarify names in eudora_bridge_update domain_0_value_1 -> EUDORA_BRIDGE_STATE_FOLLOW_LINKED_SWITCH: Authoritative source switches on moby->state with existing member EUDORA_BRIDGE_STATE_FOLLOW_LINKED_SWITCH=1. Retail lbu at 0x002c6890 reads s0+0x20, dispatch 0x002c6894-0x002c6898 sends state 1 to 0x002c6970. Initialization stores that same 1 from s2 to s0+0x20 at 0x002c68e4. Destination branch resolves linked moby index, checks class 0x118, and copies linked pvars travel into anim_time at 0x002c6970-0x002c69b0; this proves reuse of the existing state member rather than unrelated TRUE. domain_1_value_2 -> EUDORA_BRIDGE_STATE_RELEASE_MOVEMENT_VOICE: Authoritative source switches on moby->state with existing member EUDORA_BRIDGE_STATE_RELEASE_MOVEMENT_VOICE=2. Retail 0x002c6ae0-0x002c6ae8 stores 2 into the same s0+0x20 byte read by dispatch 0x002c6890; dispatch 0x002c68b8 selects 0x002c6b3c for 2. Assignment follows linked travel==1.0 and class restoration to 0x1B0. Destination tests pvars+4 voice, validates slot owner/state, releases at 0x002c6b84 and clears handle at 0x002c6b90, proving reuse of the existing movement-voice-release state. --- src/overlays/l04/mobys/eudora_bridge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l04/mobys/eudora_bridge.c b/src/overlays/l04/mobys/eudora_bridge.c index c8963205aa..6ce8a0b31d 100644 --- a/src/overlays/l04/mobys/eudora_bridge.c +++ b/src/overlays/l04/mobys/eudora_bridge.c @@ -54,7 +54,7 @@ void eudora_bridge_update(struct Moby *moby) { switch (moby->state) { case EUDORA_BRIDGE_STATE_INITIALIZE: blend_moby_animation(moby, 1, 0, scale_game_frames(300)); - moby->state = 1; + moby->state = EUDORA_BRIDGE_STATE_FOLLOW_LINKED_SWITCH; moby->anim_speed = 0; switch_follower_vars->voice = -1; if (moby->oclass == 0x1B0) { @@ -100,7 +100,7 @@ void eudora_bridge_update(struct Moby *moby) { moby->unk72 = ((MobyClassHeader *)moby->pclass)->unkE; moby->collision = ((MobyClassHeader *)moby->pclass)->unk10; refresh_moby_spatial_bounds_from_basis(moby); - moby->state = 2; + moby->state = EUDORA_BRIDGE_STATE_RELEASE_MOVEMENT_VOICE; } } else if (!voice_is_playing(moby, switch_follower_vars->voice)) { switch_follower_vars->voice = allocate_voice_for_target_entry(0, 4, moby); From be09bb03659afcef1f3228ff0facb3f42644a233 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:26:33 +0000 Subject: [PATCH 0780/1502] decomp: clarify names in apply_hero_ground_type_effects domain_0_value_2 -> HERO_GROUND_TYPE_MAGNET: Retail 0x0021d9f4 loads hero+0x12e0 (ground_type) into s2 before reset. At 0x0021da14-0x0021da58 saved type 2 gates the near-ground test and writes 1 to hero+0x12e7, the source field on_magnet_ground. This selector is ground_type, not HeroStateId. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021da50 loads the byte at hero+0x20a4 and 0x0021da54 skips the item-moby check when nonzero. The authoritative source maps this exact load to hero_ptr->vehicle_mode. Thus the selector is the supplied HeroVehicleMode domain, whose canonical value 0 is HERO_VEHICLE_MODE_ON_FOOT. domain_2_value_14 -> HERO_GROUND_TYPE_FIXED_SHALLOW_WATER: Retail 0x0021da84 compares saved ground_type s2 with 14. At 0x0021da98-0x0021daac it reads ground_z, sets base_condition, stores water_depth=0.2 and water_surface_z=ground_z+0.2. The source confirms these field roles; the name describes the fixed shallow-water treatment without claiming a material identity. domain_3_value_0 -> HERO_GROUND_TYPE_WATER: Retail 0x0021dab0 tests the saved ground_type s2 against zero; 0x0021dac8-0x0021dae0 calculates water_surface_z-ground_z and stores water_depth. At 0x0021dad4-0x0021db00 it enables wading for depth between 0.25 and 0.85, and sets base_condition at 0x0021db0c. This proves water ground treatment, independently of state or vehicle value zero. domain_5_value_2 -> HERO_GROUND_TYPE_MAGNET: The same saved ground_type in retail s2 is compared with 2 at 0x0021db98; 0x0021dba8 writes 1 to hero+0x12e7 (on_magnet_ground). This is the same ground-type domain and meaning as the earlier type-2 comparison, so reuse its member. domain_7_value_13 -> HERO_GROUND_TYPE_SINK_TRIGGER: Retail 0x0021dbc8 compares saved ground_type s2 with 13 and 0x0021dbd8 sets hero+0x12ec (selector_13). That same flag gates 0x0021dc68 onward: water-surface proximity, positive immersion and negative displacement-Z tests lead to hero_set_state(0x7f,1) at 0x0021dcf8, identified as HERO_STATE_SINK in the authoritative source. The name asserts only this ground type's sink-trigger role. --- .../update_hero_motion_for_current_state.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/overlays/l08/hero/update_hero_motion_for_current_state.c b/src/overlays/l08/hero/update_hero_motion_for_current_state.c index ff07dfa06f..619fc29626 100644 --- a/src/overlays/l08/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l08/hero/update_hero_motion_for_current_state.c @@ -35,6 +35,12 @@ float absolute_float(float input) __asm__("func_001F99C0"); void apply_hero_ground_type_effects(void) __asm__("FUN_L08_0021d9c0"); void apply_hero_ground_type_effects(void) { + enum { + HERO_GROUND_TYPE_WATER = 0, + HERO_GROUND_TYPE_MAGNET = 2, + HERO_GROUND_TYPE_SINK_TRIGGER = 0xD, + HERO_GROUND_TYPE_FIXED_SHALLOW_WATER = 0xE + }; struct Hero *hero_ptr = &hero; int saved_ground_type; int x; @@ -47,23 +53,23 @@ void apply_hero_ground_type_effects(void) { hero_ptr->unk308 = 0; if (saved_ground_type == -1) return; - if (saved_ground_type == 2) { + if (saved_ground_type == HERO_GROUND_TYPE_MAGNET) { if (hero_ptr->frames_off_ground.s == 0 || hero_ptr->ground_distance < 0.3f) { hero_ptr->on_magnet_ground = 1; - if (hero_ptr->vehicle_mode == 0) { + if (hero_ptr->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { char *item_moby = ((char *)hero_ptr->items[1].moby); if (item_moby != 0 && MOBY(item_moby)->oclass == 0xAD) hero_ptr->unk308 = 1; } } } - if (saved_ground_type == 0xE) { + if (saved_ground_type == HERO_GROUND_TYPE_FIXED_SHALLOW_WATER) { struct Hero *q = &hero; q->base_condition = 1; q->water_depth = 0.2f; q->water_surface_z = q->ground_z.f + 0.2f; } - if (saved_ground_type == 0) { + if (saved_ground_type == HERO_GROUND_TYPE_WATER) { struct Hero *q = &hero; q->water_depth = q->water_surface_z - q->ground_z.f; if (q->water_depth < 0.85f) { @@ -88,7 +94,7 @@ void apply_hero_ground_type_effects(void) { struct Hero *q = &hero; *(char *)&q->selector_11 = 1; } - if (saved_ground_type == 2) { + if (saved_ground_type == HERO_GROUND_TYPE_MAGNET) { struct Hero *q = &hero; *(char *)&q->on_magnet_ground = 1; } @@ -96,7 +102,7 @@ void apply_hero_ground_type_effects(void) { struct Hero *q = &hero; *(char *)&q->selector_4 = 1; } - if (saved_ground_type == 0xD) { + if (saved_ground_type == HERO_GROUND_TYPE_SINK_TRIGGER) { struct Hero *q = &hero; *(char *)&q->selector_13 = 1; } From 54199a2940b39db7f8a8ff8bcb2910c9137b6a9c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:26:33 +0000 Subject: [PATCH 0781/1502] decomp: clarify names in service_level_archive_load domain_0_value_0 -> FALSE: In the bound source LOAD_SHARED_ARCHIVE tests pal_mode != 0. Retail 0x00204524-0x00204554 loads D_0015ED80 and branches on zero: zero reads standard sound_archive.size at disc_table+0x2974, nonzero reads sound_archive_alt.size at +0x297C. Original Ghidra identifies this selector as g_nPalVideoMode. Thus zero is the disabled PAL predicate, matching the supplied existing FALSE=0 constant, rather than an archive-load stage. domain_1_value_0 -> FALSE: In the bound source LOAD_SOUND_ARCHIVE tests the same pal_mode != 0 predicate. Retail 0x00204610-0x00204654 loads D_0015ED80 and branches on zero: zero submits the standard sector/count at disc_table+0x2970/+0x2974, nonzero submits the alternate extent at +0x2978/+0x297C. Original Ghidra names this g_nPalVideoMode. Reuse existing FALSE=0 for the disabled PAL predicate, consistent with the stage-0 allocation choice. --- src/game/service_level_archive_load.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/service_level_archive_load.c b/src/game/service_level_archive_load.c index f4f47ab8fe..cc8420d32e 100644 --- a/src/game/service_level_archive_load.c +++ b/src/game/service_level_archive_load.c @@ -87,7 +87,7 @@ s32 service_level_archive_load(void) { stage = (s16)D_0015EE48; switch (stage) { case LOAD_SHARED_ARCHIVE: - if (pal_mode != 0) { + if (pal_mode != FALSE) { sound_aligned_bytes = ((disc_table.sound_archive_alt.size << 11) + 0xFFF) & 0xFFFFF000; } else { sound_aligned_bytes = ((disc_table.sound_archive.size << 11) + 0xFFF) & 0xFFFFF000; @@ -115,7 +115,7 @@ s32 service_level_archive_load(void) { D_0015EE48 = D_0015EE48 + 1; break; case LOAD_SOUND_ARCHIVE: - if (pal_mode != 0) { + if (pal_mode != FALSE) { submit_audio_stream_io_request(sound_archive_base, disc_table.sound_archive_alt.sector, disc_table.sound_archive_alt.size); From cdec6c71aeea9956252e6c8ff5f4d42c3e325b08 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:26:33 +0000 Subject: [PATCH 0782/1502] decomp: clarify names in update_batalia_textured_effect domain_0_value_1 -> MOBY_ACTIVE: SHA-bound source 54a4641bcc665cebdc83474c75f770336179b44d3299ec063cde4bf004afd78e declares MOBY_ACTIVE = 1 and uses it for switch (moby->state). Retail 0x003097bc preserves the moby in s1; 0x003097d0 reads its state byte at s1+0x20 and 0x003097d8/0x003097dc dispatch value 1 to 0x00309978. Initialization loads 1 at 0x00309898 (or the guarded setup path) and stores that value to the identical s1+0x20 byte at 0x003098a0. Original Ghidra likewise assigns *(param_1+0x20)=1 after RGBA setup and selects the culling/distance/scroll/draw-callback branch when that byte equals 1. This proves reuse of the existing MOBY_ACTIVE state member, rather than the unrelated equal-valued TRUE. --- src/overlays/l08/mobys/batalia_textured_effect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/batalia_textured_effect.c b/src/overlays/l08/mobys/batalia_textured_effect.c index 6caf935e22..5fac1c94ce 100644 --- a/src/overlays/l08/mobys/batalia_textured_effect.c +++ b/src/overlays/l08/mobys/batalia_textured_effect.c @@ -252,7 +252,7 @@ void batalia_textured_effect_update(struct Moby *moby) { 1); batalia_rgba_tables_initialized = 1; } - moby->state = 1; + moby->state = MOBY_ACTIVE; for (i = 0; i < 3; i++) { D_L08_001F8548[i].a = 0; D_L08_001F8548[i].b = 0; From 311ac6618b8046d53faf2fc0d7cb50694c20385f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:26:33 +0000 Subject: [PATCH 0783/1502] decomp: clarify names in escalator_update domain_1_value_1 -> ESCALATOR_STATE_TIMED_NEGATIVE_YAW_MOTION: The moby+0x20 state loaded at 0x002dc6e4 dispatches value 1 to 0x002dc764. This timed branch decrements pvars+0xa0, accelerates or brakes the velocity magnitude, and multiplies both cos(yaw) and sin(yaw) by the negated magnitude (0x002dc7cc-0x002dc858). It changes to state 2 when braking reaches zero at 0x002dc7b4-0x002dc7c8. Negative direction means relative to the yaw unit vector, not a world direction. domain_2_value_2 -> ESCALATOR_STATE_TIMED_POSITIVE_YAW_MOTION: The moby+0x20 selector is tested against 2 at 0x002dc708 and enters 0x002dc878. This branch uses the same pvars+0xa0 timer and magnitude acceleration/braking but multiplies cos(yaw) and sin(yaw) by the unnegated speed at 0x002dc8dc-0x002dc964. After braking reaches zero it writes state 1 at 0x002dc8d8. Thus 2 is timed positive motion relative to the yaw unit vector; the <2 dispatch boundary uses this same state-domain member. domain_3_value_0 -> ESCALATOR_STATE_INITIALIZE: The selector is the escalator moby state byte loaded at 0x002dc6e4 from moby+0x20. Its zero branch at 0x002dc6f8 enters 0x002dc720: clears pvars+0x40 velocity, loads the scaled direction countdown into +0xa0, sets bit 4 at +0x9c, and selects the initial active state at 0x002dc758/0x002dc760. This is initialization, not a null-pointer or boolean domain. domain_4_value_2 -> ESCALATOR_STATE_TIMED_POSITIVE_YAW_MOTION: The moby+0x20 selector is tested against 2 at 0x002dc708 and enters 0x002dc878. This branch uses the same pvars+0xa0 timer and magnitude acceleration/braking but multiplies cos(yaw) and sin(yaw) by the unnegated speed at 0x002dc8dc-0x002dc964. After braking reaches zero it writes state 1 at 0x002dc8d8. Thus 2 is timed positive motion relative to the yaw unit vector; the <2 dispatch boundary uses this same state-domain member. domain_5_value_3 -> ESCALATOR_STATE_CONSTANT_SPEED_MOTION: The moby+0x20 selector value 3 is tested at 0x002dc710 and enters 0x002dc988. Unlike states 1 and 2, this branch does not decrement the countdown or accelerate/brake: it directly sets XY velocity to cos/sin(yaw) times -(escalator_target_speed_gp * frame_time), zeroes Z, and reaches the matrix update. Initialization chooses this same state at 0x002dc758 when pvars+0xa4 is nonzero. domain_6_value_3 -> ESCALATOR_STATE_CONSTANT_SPEED_MOTION: The moby+0x20 selector value 3 is tested at 0x002dc710 and enters 0x002dc988. Unlike states 1 and 2, this branch does not decrement the countdown or accelerate/brake: it directly sets XY velocity to cos/sin(yaw) times -(escalator_target_speed_gp * frame_time), zeroes Z, and reaches the matrix update. Initialization chooses this same state at 0x002dc758 when pvars+0xa4 is nonzero. domain_7_value_1 -> ESCALATOR_STATE_TIMED_NEGATIVE_YAW_MOTION: The moby+0x20 state loaded at 0x002dc6e4 dispatches value 1 to 0x002dc764. This timed branch decrements pvars+0xa0, accelerates or brakes the velocity magnitude, and multiplies both cos(yaw) and sin(yaw) by the negated magnitude (0x002dc7cc-0x002dc858). It changes to state 2 when braking reaches zero at 0x002dc7b4-0x002dc7c8. Negative direction means relative to the yaw unit vector, not a world direction. Initialization writes this member at 0x002dc760 when pvars+0xa4 is zero. domain_8_value_2 -> ESCALATOR_STATE_TIMED_POSITIVE_YAW_MOTION: The moby+0x20 selector is tested against 2 at 0x002dc708 and enters 0x002dc878. This branch uses the same pvars+0xa0 timer and magnitude acceleration/braking but multiplies cos(yaw) and sin(yaw) by the unnegated speed at 0x002dc8dc-0x002dc964. After braking reaches zero it writes state 1 at 0x002dc8d8. Thus 2 is timed positive motion relative to the yaw unit vector; the <2 dispatch boundary uses this same state-domain member. The state-1 brake completion writes this member at 0x002dc7c8. domain_9_value_1 -> ESCALATOR_STATE_TIMED_NEGATIVE_YAW_MOTION: The moby+0x20 state loaded at 0x002dc6e4 dispatches value 1 to 0x002dc764. This timed branch decrements pvars+0xa0, accelerates or brakes the velocity magnitude, and multiplies both cos(yaw) and sin(yaw) by the negated magnitude (0x002dc7cc-0x002dc858). It changes to state 2 when braking reaches zero at 0x002dc7b4-0x002dc7c8. Negative direction means relative to the yaw unit vector, not a world direction. The state-2 brake completion writes this member at 0x002dc8d8. --- src/overlays/shared/props/escalator.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/shared/props/escalator.c b/src/overlays/shared/props/escalator.c index 3d99ccb2b3..378aed762f 100644 --- a/src/overlays/shared/props/escalator.c +++ b/src/overlays/shared/props/escalator.c @@ -27,7 +27,7 @@ void escalator_update(char *moby) __asm__("FUN_L02_002dc6b0"); /* Moby classes 296, 652, 653 */ void escalator_update(char *moby) { - EscalatorVars *escalator_motion_state = (EscalatorVars *)MOBY(moby)->pvars; + enum { ESCALATOR_STATE_INITIALIZE = 0 , ESCALATOR_STATE_TIMED_NEGATIVE_YAW_MOTION = 1 , ESCALATOR_STATE_TIMED_POSITIVE_YAW_MOTION = 2 , ESCALATOR_STATE_CONSTANT_SPEED_MOTION = 3 } ;EscalatorVars *escalator_motion_state = (EscalatorVars *)MOBY(moby)->pvars; float limit; float y; int state; @@ -35,16 +35,16 @@ void escalator_update(char *moby) { if (escalator_motion_state == 0) return; state = MOBY(moby)->state; - if (state == 1) + if (state == ESCALATOR_STATE_TIMED_NEGATIVE_YAW_MOTION) goto state1; - if (state < 2) { - if (state == 0) + if (state < ESCALATOR_STATE_TIMED_POSITIVE_YAW_MOTION) { + if (state == ESCALATOR_STATE_INITIALIZE) goto state0; goto move; } - if (state == 2) + if (state == ESCALATOR_STATE_TIMED_POSITIVE_YAW_MOTION) goto state2; - if (state == 3) + if (state == ESCALATOR_STATE_CONSTANT_SPEED_MOTION) goto state3; goto move; state0: @@ -52,9 +52,9 @@ void escalator_update(char *moby) { escalator_motion_state->unkA0 = scale_game_frames(escalator_direction_timer_frames_gp); escalator_motion_state->unk9C |= 4; if (escalator_motion_state->unkA4 != 0) - MOBY(moby)->state = 3; + MOBY(moby)->state = ESCALATOR_STATE_CONSTANT_SPEED_MOTION; else - MOBY(moby)->state = 1; + MOBY(moby)->state = ESCALATOR_STATE_TIMED_NEGATIVE_YAW_MOTION; goto move; state1: { float speed; @@ -65,7 +65,7 @@ state1: { escalator_acceleration_gp * frame_time_sq; if (speed <= 0.0f) { escalator_motion_state->unkA0 = scale_game_frames(escalator_direction_timer_frames_gp); - MOBY(moby)->state = 2; + MOBY(moby)->state = ESCALATOR_STATE_TIMED_POSITIVE_YAW_MOTION; } else { escalator_motion_state->unk40 = fast_cos(MOBY(moby)->rot.z) * -speed; y = fast_sin(MOBY(moby)->rot.z) * -speed; @@ -94,7 +94,7 @@ state2: { escalator_acceleration_gp * frame_time_sq; if (speed <= 0.0f) { escalator_motion_state->unkA0 = scale_game_frames(escalator_direction_timer_frames_gp); - MOBY(moby)->state = 1; + MOBY(moby)->state = ESCALATOR_STATE_TIMED_NEGATIVE_YAW_MOTION; } else { escalator_motion_state->unk40 = fast_cos(MOBY(moby)->rot.z) * speed; escalator_motion_state->unk44 = fast_sin(MOBY(moby)->rot.z) * speed; From 72a81bcd7680cc9dd123af18985a3c790b023b20 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:26:34 +0000 Subject: [PATCH 0784/1502] decomp: clarify names in update_pyrocitor_flame_effect_slots domain_0_value_10 -> PYROCITOR_FLAME_SUBTYPE_SPARK_BURST: In authoritative src/overlays/shared/weapons/pyrocitor.c SHA-256 bd860cc25bd6eca9fe066f4a55336e79442ab55f52e58a7f9d7717d011232561, sub_type is read from flame_effect+0xA after the tracked type-0xC live-effect check. Retail 0x002b8580 loads that signed halfword into s0; 0x002b8584-0x002b8588 compares it to 10. Equality enters the loop bounded by pyrocitor_spark_burst_count_gp at 0x002b8590 and 0x002b8710-0x002b8718, generating spark vectors, positions, colors and frame counts and calling spawn_spark at 0x002b8708 once per iteration. Original Ghidra confirms the same halfword comparison and repeated spark call. This proves the spark-burst subtype behavior, independently of unrelated hero-state constants with equal values. --- src/overlays/shared/weapons/pyrocitor.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/pyrocitor.c b/src/overlays/shared/weapons/pyrocitor.c index 461a4844eb..f2946de49c 100644 --- a/src/overlays/shared/weapons/pyrocitor.c +++ b/src/overlays/shared/weapons/pyrocitor.c @@ -800,6 +800,9 @@ void update_pyrocitor_usage_and_cleanup(struct Moby *pyrocitor_moby) { void update_pyrocitor_flame_effect_slots(char *moby) __asm__("FUN_L00_002b8438"); void update_pyrocitor_flame_effect_slots(char *moby) { + enum { + PYROCITOR_FLAME_SUBTYPE_SPARK_BURST = 10 + }; float hit_direction_vector[4]; char hit_descriptor[0x30]; char qv[16]; @@ -832,7 +835,7 @@ void update_pyrocitor_flame_effect_slots(char *moby) { collect_mobies_in_sphere( (flame_effect + 0x10), hit_sphere_radius, 0, moby, hit_descriptor); sub_type = *(short *)(flame_effect + 0xA); - if (sub_type == 10) { + if (sub_type == PYROCITOR_FLAME_SUBTYPE_SPARK_BURST) { int j; for (j = 0; j < *(int *)&pyrocitor_spark_burst_count_gp; j++) { int spark_initial_color; From 43c682711bdf069c648965c66105f622459bb4c6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:28:33 +0000 Subject: [PATCH 0785/1502] decomp: clarify names in update_gameplay_frame domain_1_value_3 -> GAME_MODE_MAIN_MENU: The supplied enter_main_menu source defines GAME_MODE_MAIN_MENU = 3 and assigns it directly to game_mode, proving the exact selector domain rather than numerical equivalence. Assigned retail 0x001eb250-0x001eb25c loads D_0015F604 (game_mode) and prepares 3; 0x001eb364 compares that same loaded value with 3. Its matching branch fades intro-overlay alphas and calls update_menu_system at 0x001eb3b4. The zero-mode branch calls enter_main_menu at 0x001eb354 after the controller mask test, corroborating the transition to this menu mode. --- src/game/update_gameplay_frame.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/game/update_gameplay_frame.c b/src/game/update_gameplay_frame.c index da27dea9b6..8e7a8e0209 100644 --- a/src/game/update_gameplay_frame.c +++ b/src/game/update_gameplay_frame.c @@ -64,6 +64,9 @@ extern void sound_update(void) __asm__("func_0022CA50"); void update_gameplay_frame(void) __asm__("FUN_001eb0a8"); void update_gameplay_frame(void) { + enum { + GAME_MODE_MAIN_MENU = 3 + }; Vec4 first_position; Vec4 next_position; RenderSequenceActor *actor; @@ -133,7 +136,7 @@ void update_gameplay_frame(void) { enter_main_menu(); } sound_update(); - } else if (game_mode == 3) { + } else if (game_mode == GAME_MODE_MAIN_MENU) { intro_overlay_timer = scale_game_frames(0x3C); if ((intro_overlay_alpha -= 0x10) < 0) { intro_overlay_alpha = 0; From a7857eb900c4fcc144dc39d8515eab92db374601 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:28:33 +0000 Subject: [PATCH 0786/1502] decomp: clarify names in update_qwarks_starfighter_part domain_2_value_1 -> PART_STATE_SYNC_PARENT_SCALE: Retail 002ece0c keeps the part moby in s1; 002ece50 loads its state byte at s1+0x20 for switch dispatch. In initialize, 002ece94/002ece9c stores 1 to that identical state byte. The authoritative source already declares PART_STATE_SYNC_PARENT_SCALE=1 in this function's moby->state switch; retail 002eceac-002ecedc implements that case by computing parent-relative scale and copying the parent's spawn_frame. This assignment therefore uses the existing member of the exact same part-state domain. domain_3_value_4 -> PART_STATE_BURST_AND_REMOVE: After the sphere collision and class exclusions, retail 002ecfa8-002ecfb0 reflects the part velocity, then 002ecfb4/002ecfb8 stores 4 to s1+0x20. This is the same part moby state byte loaded for dispatch at 002ece50. The authoritative source already declares PART_STATE_BURST_AND_REMOVE=4 in that exact switch domain. Its retail branch 002ed0cc-002ed138 calls the explosion helper followed by removal, proving reuse of this established member for the collision transition. --- src/overlays/l13/mobys/qwarks_starfighter_part.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l13/mobys/qwarks_starfighter_part.c b/src/overlays/l13/mobys/qwarks_starfighter_part.c index 241847fce6..86ada02465 100644 --- a/src/overlays/l13/mobys/qwarks_starfighter_part.c +++ b/src/overlays/l13/mobys/qwarks_starfighter_part.c @@ -63,7 +63,7 @@ void qwarks_starfighter_part_update(struct Moby *moby) { moby->flags = moby->flags | (starfighter_part_vars->parent->flags & 3); switch (moby->state) { case PART_STATE_INITIALIZE: - moby->state = 1; + moby->state = PART_STATE_SYNC_PARENT_SCALE; qzero(&starfighter_part_vars->unk20); break; case PART_STATE_SYNC_PARENT_SCALE: @@ -86,7 +86,7 @@ void qwarks_starfighter_part_update(struct Moby *moby) { hit->oclass != 0x18C && hit->oclass != 0x18F && hit->oclass != 0x190)) { reflect_vector( &starfighter_part_vars->vel, &starfighter_part_vars->vel, coll + 0x40); - moby->state = 4; + moby->state = PART_STATE_BURST_AND_REMOVE; } } moby->rot.x = fast_add_rotations(moby->rot.x, starfighter_part_vars->spin[0]); From d3b5a2956f18b14df49a8da73dc662cfdd98bc8a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:28:33 +0000 Subject: [PATCH 0787/1502] decomp: clarify names in button_update domain_0_value_2 -> BUTTON_ACTIVATED: Retail 0x00306b8c reads moby+0x20 as the same button state selector tested for 0 and 1 at 0x00306b90/0x00306b9c. Saved cleared-byte/save-bit or mission-gate satisfaction branches to 0x00306c58; 0x00306c64 writes state 2, 0x00306c68 sets fixed green glow 0x80208020 and the subsequent loop clears matching path tags. This restores the same activated state reached by standing on the button at 0x00306e40; it is a button state, not a command or hero enum. domain_1_value_1 -> BUTTON_WAIT_FOR_HERO_TO_STAND: Retail 0x00306cf4 loads 1 and 0x00306cfc stores it to moby+0x20 when initialization finds no satisfied saved/mission condition. That exact byte is read at 0x00306b8c and compared with 1 at 0x00306b9c to enter 0x00306d00, the existing BUTTON_WAIT_FOR_HERO_TO_STAND case. Its pulse update waits for hero.ground_moby == moby and zero air_frames at 0x00306d9c-0x00306dac, proving reuse of the existing local enum member. domain_2_value_2 -> BUTTON_ACTIVATED: After hero.ground_moby == moby and zero air_frames at 0x00306d9c-0x00306dac, retail 0x00306e08 and 0x00306e3c record the button save bits. 0x00306dfc loads 2 into t3 and 0x00306e40 stores it to the button state byte at moby+0x20, with command 1 at +0xbc, fixed green glow at +0x90, voice allocation and matching path-tag clearing. The entry dispatch handles only states 0 and 1, so this is the activated state that stops the waiting pulse/contact behavior, identical to the restored activation at 0x00306c64. --- src/overlays/l14/mobys/button.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/l14/mobys/button.c b/src/overlays/l14/mobys/button.c index 2915271761..26f9952756 100644 --- a/src/overlays/l14/mobys/button.c +++ b/src/overlays/l14/mobys/button.c @@ -25,6 +25,9 @@ void button_update(struct Moby *moby) { BUTTON_INITIALIZE = 0, BUTTON_WAIT_FOR_HERO_TO_STAND = 1 }; + enum { + BUTTON_ACTIVATED = 2 + }; s32 *button_pvars = (s32 *)moby->pvars; s16 id; s32 i; @@ -46,7 +49,7 @@ void button_update(struct Moby *moby) { D_0014C050[moby->mission + current_level_index * 16] == 0xFF)) { moby->command = 2; moby->glow_color = 0x80208020; - moby->state = 2; + moby->state = BUTTON_ACTIVATED; list = button_pvars[0]; if (list != -1) { i = 0; @@ -61,7 +64,7 @@ void button_update(struct Moby *moby) { } } } else { - moby->state = 1; + moby->state = BUTTON_WAIT_FOR_HERO_TO_STAND; } break; case BUTTON_WAIT_FOR_HERO_TO_STAND: @@ -79,7 +82,7 @@ void button_update(struct Moby *moby) { id = (s16)moby->save_id; D_0014C190_257218[current_level_index][id >> 5] |= 1 << (moby->save_id & 31); D_L14_001BABD0[(s16)moby->save_id >> 5] |= 1 << (moby->save_id & 31); - moby->state = 2; + moby->state = BUTTON_ACTIVATED; moby->command = 1; moby->glow_color = 0x80208020; allocate_voice_for_target_entry(0, 0, moby); From 9a9baf7351a7681f9ee6ae61d1b4c23474e72ff1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:28:33 +0000 Subject: [PATCH 0788/1502] decomp: clarify names in update_test_dummy_challenge domain_0_value_5 -> SCENE_STATE_HIDDEN_WAIT_FOR_TRIGGER: Retail 0x002d5f6c-0x002d5f84 writes 5 to +0x20(s2) when scene_data->hidden is -1 and clears collision/visibility. The switch reads that same byte at 0x002d5f10; case 5 at 0x002d618c-0x002d61c0 waits for the trigger volume before activating groups. This is the existing local SCENE_STATE_HIDDEN_WAIT_FOR_TRIGGER domain. domain_1_value_1 -> SCENE_STATE_WAIT_FOR_TRIGGER: Retail 0x002d5f64 and 0x002d5f8c write 1 to +0x20(s2) on the non-hidden initialization path. The selector reads the same moby state byte at 0x002d5f10, and case 1 at 0x002d5fa0-0x002d5fb4 returns until the configured trigger contains the player, matching existing SCENE_STATE_WAIT_FOR_TRIGGER. domain_2_value_2 -> SCENE_STATE_WAIT_TO_HIDE: Retail 0x002d5fbc-0x002d5fcc initializes the scaled 60-frame timer and writes 2 to the switch's +0x20(s2) state byte after trigger entry. Case 2 at 0x002d6024-0x002d6050 waits for that timer, then clears visibility and sets flags bit 0. Reuse the existing local SCENE_STATE_WAIT_TO_HIDE member. domain_3_value_3 -> SCENE_STATE_WAIT_FOR_LINKED_MOBYS_AND_TIMER: Retail 0x002d6030-0x002d6058 writes 3 to the same +0x20(s2) selector, reloads the timer, hides the moby and activates scene_data->path. Case 3 tests count_active_moby_group_members(path,-1) at 0x002d609c-0x002d60a8 and then the timer at 0x002d60b0-0x002d60b8. This matches existing SCENE_STATE_WAIT_FOR_LINKED_MOBYS_AND_TIMER. domain_4_value_4 -> SCENE_STATE_COMPLETE: Retail 0x002d60c4-0x002d60d0 writes 4 to +0x20(s2) after linked-group count and timer finish; 0x002d6150-0x002d6164 sets the configured objective completion byte. The same selector's existing case SCENE_STATE_COMPLETE=4 is empty. Reuse that local member for this normal-path terminal assignment. domain_5_value_6 -> SCENE_STATE_HIDDEN_WAIT_FOR_LINKED_MOBYS: Retail case 5 activates the configured helper and test-dummy groups at 0x002d61a4-0x002d61b4, then writes 6 to +0x20(s2) at 0x002d61b8-0x002d61c0. Case 6 waits for count_active_moby_group_members(path,-1) to become zero at 0x002d61f4-0x002d6200. This is the existing same-selector SCENE_STATE_HIDDEN_WAIT_FOR_LINKED_MOBYS member. domain_6_value_4 -> SCENE_STATE_COMPLETE: Retail 0x002d6208-0x002d6210 writes 4 to the switch's +0x20(s2) byte after the hidden path's linked-group count reaches zero. It then sets the objective completion byte at 0x002d6230-0x002d6244. This enters the same empty terminal case SCENE_STATE_COMPLETE=4 used by the normal completion path. --- src/overlays/l16/mobys/test_dummy_challenge.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l16/mobys/test_dummy_challenge.c b/src/overlays/l16/mobys/test_dummy_challenge.c index 44a5ef2a96..89b81f20f2 100644 --- a/src/overlays/l16/mobys/test_dummy_challenge.c +++ b/src/overlays/l16/mobys/test_dummy_challenge.c @@ -73,12 +73,12 @@ void test_dummy_challenge_update(struct Moby *moby) { return; } if (scene_data->hidden == -1) { - moby->state = 5; + moby->state = SCENE_STATE_HIDDEN_WAIT_FOR_TRIGGER; moby->flags |= 1; moby->visible = 0; moby->collision = 0; } else { - moby->state = 1; + moby->state = SCENE_STATE_WAIT_FOR_TRIGGER; set_class_0287_group_activation_and_find_nearest(scene_data->helper, 1); } break; @@ -87,7 +87,7 @@ void test_dummy_challenge_update(struct Moby *moby) { if (!is_point_inside_clip_volume(player, scene_data->trigger)) break; scene_data->timer_q = scale_game_frames(60); - moby->state = 2; + moby->state = SCENE_STATE_WAIT_TO_HIDE; if (scene_data->camera >= 0) *(unsigned short *)(player + 0x225A) = *(unsigned short *)&scene_data->camera; jet_mount(D_L16_001671C0_lui, D_L16_001671C0_lui + 0x10, 1, 0, 0); @@ -98,7 +98,7 @@ void test_dummy_challenge_update(struct Moby *moby) { if (scene_data->camera >= 0) *(unsigned short *)(D_0014162A_lui) = *(unsigned short *)&scene_data->camera; if (fast_dec_timer(&scene_data->timer_q)) { - moby->state = 3; + moby->state = SCENE_STATE_WAIT_FOR_LINKED_MOBYS_AND_TIMER; scene_data->timer_q = scale_game_frames(60); moby->visible = 0; moby->flags |= 1; @@ -116,7 +116,7 @@ void test_dummy_challenge_update(struct Moby *moby) { if (!fast_dec_timer(&scene_data->timer_q)) break; moby->visible = 1; - moby->state = 4; + moby->state = SCENE_STATE_COMPLETE; moby->flags &= 0xFFFE; jet_end_mount(3); set_race_camera(D_L16_001600EC + (scene_data->pose << 7) + 0x30, @@ -144,7 +144,7 @@ void test_dummy_challenge_update(struct Moby *moby) { if (is_point_inside_clip_volume(D_0013F3D0, scene_data->trigger)) { activate_class_0287_group_and_find_nearest(scene_data->helper, 0); activate_test_dummy_group(scene_data->path); - moby->state = 6; + moby->state = SCENE_STATE_HIDDEN_WAIT_FOR_LINKED_MOBYS; } break; case SCENE_STATE_HIDDEN_WAIT_FOR_LINKED_MOBYS: { @@ -152,7 +152,7 @@ void test_dummy_challenge_update(struct Moby *moby) { if (is_point_inside_clip_volume(player, scene_data->trigger) && scene_data->camera >= 0) *(unsigned short *)(player + 0x225A) = *(unsigned short *)&scene_data->camera; if (!count_active_moby_group_members(scene_data->path, -1)) { - moby->state = 4; + moby->state = SCENE_STATE_COMPLETE; helper = set_class_0287_group_activation_and_find_nearest(scene_data->helper, 0); if (helper) allocate_voice_for_target_entry(1, 0, helper); From fe802261802fadd6d2392a2360ea3f4a254c6acd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:28:34 +0000 Subject: [PATCH 0789/1502] decomp: clarify names in update_streamed_moby_animation domain_0_value_1 -> ANIMATION_STREAM_FINISH_READ: Retail 00225778 branches on start_audio_stream_read's return; success stores 1 at stream +0x34 at 00225784. The same field is loaded at 00225708 and value 1 dispatches to 002257a8, which waits for CD completion and decompresses the read. This is the existing local ANIMATION_STREAM_FINISH_READ domain. domain_1_value_3 -> ANIMATION_STREAM_READ_FAILED: Retail 00225770 calls the read-start helper; 00225778 branches to 0022579c only when its return is zero. That path loads 3 and stores it to stream state +0x34 at 002257a4. The dispatch at 00225708-00225738 handles only 0/1/2, so this is the stream read-failure state, not a Moby phase. domain_2_value_2 -> ANIMATION_STREAM_UPDATE_MOBY: After decompression and relocation of all three animation tables at 002257cc-00225830, retail loads 2 at 00225834 and stores it to stream +0x34 at 00225844. Dispatch of that same field at 0022572c enters 0022586c, loads the owned Moby at +0x44, and updates its phase machine: existing ANIMATION_STREAM_UPDATE_MOBY. domain_3_value_1 -> STREAMED_MOBY_WAIT_FIRST_ANIMATION_COMPLETION: Retail 0022586c loads stream->moby; the selector is byte +0x20, also read at 002259a0 and compared against 1 at 002259a4 after transition_flags bit 2 is set. This is the same inner phase domain whose existing case 1 is STREAMED_MOBY_WAIT_FIRST_ANIMATION_COMPLETION; only that phase advances to phase 2 rather than restart wait. domain_4_value_6 -> STREAMED_MOBY_WAIT_SEQUENCE_RESTART: Retail 00225994-002259b0 waits for transition flag bit 2 and writes 6 to the owned Moby byte +0x20 for completion phases other than 1. That same byte drives the inner switch; its existing case 6 waits scaled 240 frames at 002259dc-00225a1c before restarting, proving reuse of STREAMED_MOBY_WAIT_SEQUENCE_RESTART. domain_5_value_0 -> STREAMED_MOBY_WAIT_DIALOGUE_FOR_FIRST_ANIMATION: Retail initializes owned Moby byte +0x20 to 0 at 00225850 when alternate_animation_sequence is zero, and repeats that reset at 00225a38 after the restart timer. The same byte is the inner switch selector at 00225870; case 0 queues dialogue 60000 plus language column then blends animation 1 at 002258a4-00225960. Reuse its existing first-animation dialogue-wait member. domain_6_value_4 -> STREAMED_MOBY_WAIT_DIALOGUE_FOR_THIRD_ANIMATION: Retail assigns 4 to owned Moby byte +0x20 at 00225858-0022585c and 00225a30-00225a3c for alternate_animation_sequence. This same selector's existing case 4 computes animation_index=4>>1, queues its dialogue, then blends animation_index+1=3 at 002258b4-00225960. It therefore reuses STREAMED_MOBY_WAIT_DIALOGUE_FOR_THIRD_ANIMATION. --- .../update_streamed_moby_animation.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/ui/menus/streamed_moby/update_streamed_moby_animation.c b/src/ui/menus/streamed_moby/update_streamed_moby_animation.c index 57d8191cca..a5aeb6fb72 100644 --- a/src/ui/menus/streamed_moby/update_streamed_moby_animation.c +++ b/src/ui/menus/streamed_moby/update_streamed_moby_animation.c @@ -66,6 +66,9 @@ s32 update_streamed_moby_animation(MobyAnimationStream *stream) { STREAMED_MOBY_WAIT_THIRD_ANIMATION_COMPLETION = 5, STREAMED_MOBY_WAIT_SEQUENCE_RESTART = 6 }; + enum { + ANIMATION_STREAM_READ_FAILED = 3 + }; StreamedAnimationMoby *moby; AnimationTableHeader *header; StreamedClassResource **class_resource; @@ -87,12 +90,12 @@ s32 update_streamed_moby_animation(MobyAnimationStream *stream) { disc_table.animation_table.sector, disc_table.animation_table.size) != 0) { stream->read_offset = table_index; - stream->state = 1; + stream->state = ANIMATION_STREAM_FINISH_READ; animation_asset_read_active[0] = 1; mark_menu_stream_buffer_read_active(stream->buffer); return 0; } - stream->state = 3; + stream->state = ANIMATION_STREAM_READ_FAILED; break; case ANIMATION_STREAM_FINISH_READ: /* Decompress the completed read and relocate three animation tables. */ @@ -111,7 +114,7 @@ s32 update_streamed_moby_animation(MobyAnimationStream *stream) { (*class_resource)->animation_tables[k + 1] = animation_table; relocate_asset_entry_pointers(*class_resource, k + 1); } - stream->state = 2; + stream->state = ANIMATION_STREAM_UPDATE_MOBY; if (alternate_animation_sequence == 0) { stream->moby->moby_state = 0; } else { @@ -157,10 +160,10 @@ s32 update_streamed_moby_animation(MobyAnimationStream *stream) { moby->animation_frame_counter = 1; } if (moby->transition_flags & 2) { - if (moby->moby_state == 1) { + if (moby->moby_state == STREAMED_MOBY_WAIT_FIRST_ANIMATION_COMPLETION) { moby->moby_state = moby->moby_state + 1; } else { - moby->moby_state = 6; + moby->moby_state = STREAMED_MOBY_WAIT_SEQUENCE_RESTART; } moby->animation_frame_counter = 0; blend_moby_animation(moby, 0, 0, scale_game_frames(0x18)); @@ -176,9 +179,9 @@ s32 update_streamed_moby_animation(MobyAnimationStream *stream) { return 0; } if (alternate_animation_sequence == 0) { - moby->moby_state = 0; + moby->moby_state = STREAMED_MOBY_WAIT_DIALOGUE_FOR_FIRST_ANIMATION; } else { - moby->moby_state = 4; + moby->moby_state = STREAMED_MOBY_WAIT_DIALOGUE_FOR_THIRD_ANIMATION; } moby->animation_frame_counter = 0; break; From bf9858f1b49c97212f96758a9f1d66fcb165cf8c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:30:31 +0000 Subject: [PATCH 0790/1502] decomp: clarify names in update_layered_mesh_effect domain_0_value_1 -> DRAW_ELEMENTS_UPDATE: Retail 0x002f1554 saves moby in s1; 0x002f1568 loads its state byte at +0x20, and 0x002f1570/0x002f1574 compare that byte with 1 and branch to recurring update at 0x002f1718. Initialization stores 1 to the very same +0x20 byte at 0x002f1638-0x002f1640, as original Ghidra confirms with *(undefined1 *)((int)param_1 + 0x20) = 1. The bound source already declares DRAW_ELEMENTS_UPDATE = 1 and uses it for this same moby->state switch branch, which culls, advances animation, updates fade and queues draw_layered_mesh_effect at 0x002f1884-0x002f1890. Therefore reuse that existing local state member for the initialization-to-update assignment. --- src/overlays/l08/mobys/layered_mesh_effect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/layered_mesh_effect.c b/src/overlays/l08/mobys/layered_mesh_effect.c index efb992869f..06db3e6611 100644 --- a/src/overlays/l08/mobys/layered_mesh_effect.c +++ b/src/overlays/l08/mobys/layered_mesh_effect.c @@ -123,7 +123,7 @@ void layered_mesh_effect_update(struct Moby *moby) { 1); *(int *)&layered_mesh_rgba_tables_initialized = 1; } - moby->state = 1; + moby->state = DRAW_ELEMENTS_UPDATE; for (i = 0; i < 3; i++) { D_L08_001E8348[i].a = 0; D_L08_001E8348[i].b = 0; From 17406abb1935e103342bc0d9fe69c9df3143fa55 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:30:31 +0000 Subject: [PATCH 0791/1502] decomp: clarify names in sceGsSetDefDispEnv domain_0_value_0 -> GS_FRAME_MODE_FIELD: In the bound source, this selector is GsVideoModeState.nSFrame_mode, distinct from wMode and nSInterlace. Retail 0x00121b8c loads state+4, 0x00121b90 tests zero, and 0x00121b98 selects 1 instead of 3 for SMODE2 at output+8 (0x00121b9c): the field/frame bit is clear for zero. Both interlaced DISPLAY paths confirm zero selects height-1 rather than doubled height. domain_2_value_0 -> GS_FRAME_MODE_FIELD: The mode-2 interlaced branch tests the same state+4 nSFrame_mode selector loaded at 0x00121c00. Retail 0x00121c34 branches on zero to 0x00121d00, forming height-1; nonzero at 0x00121c3c/0x00121c48 forms height*2-1. This is the same field setting whose zero value clears the SMODE2 frame bit at 0x00121b8c-0x00121b9c, so reuse GS_FRAME_MODE_FIELD. domain_4_value_0 -> GS_FRAME_MODE_FIELD: The mode-3 interlaced path reloads nSFrame_mode from the same state+4 at 0x00121cb4 and tests it at 0x00121ce8. Zero reaches 0x00121d00 for height-1, while nonzero doubles height at 0x00121cf0 before subtracting one. The selector and SMODE2 zero-to-field mapping at 0x00121b8c-0x00121b9c are shared with the other two comparisons, proving the same GS_FRAME_MODE_FIELD member. --- src/sdk/graph/sce_gs_set_def_disp_env.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/sdk/graph/sce_gs_set_def_disp_env.c b/src/sdk/graph/sce_gs_set_def_disp_env.c index 30ecabd07b..c67523f1ae 100644 --- a/src/sdk/graph/sce_gs_set_def_disp_env.c +++ b/src/sdk/graph/sce_gs_set_def_disp_env.c @@ -27,6 +27,9 @@ void sceGsSetDefDispEnv(struct sceGsDispEnv *output, s16 horizontal_offset, s16 vertical_offset) { + enum { + GS_FRAME_MODE_FIELD = 0 + }; GsVideoModeState *state; s32 kernel_horizontal, kernel_vertical, kernel_width, kernel_height; s32 mode, scale; @@ -51,7 +54,7 @@ void sceGsSetDefDispEnv(struct sceGsDispEnv *output, output->pmode = 0x66; if (state->nSInterlace != 0) { - if (state->nSFrame_mode == 0) + if (state->nSFrame_mode == GS_FRAME_MODE_FIELD) output->smode2 = 1; else output->smode2 = 3; @@ -72,7 +75,7 @@ void sceGsSetDefDispEnv(struct sceGsDispEnv *output, scaled_horizontal = scaled_horizontal + 0x27c; scaled_horizontal = (scaled_horizontal + horizontal_offset * scale) & 0xfff; value = (u64)(s64)(scale - 1) << 23; - if (state->nSFrame_mode != 0) { + if (state->nSFrame_mode != GS_FRAME_MODE_FIELD) { display_width = (value | display_width) | ((u64)scaled_horizontal | ((u64)(s64)(height * 2 - 1) << 44)); } else { @@ -103,7 +106,7 @@ void sceGsSetDefDispEnv(struct sceGsDispEnv *output, scaled_horizontal = scaled_horizontal + 0x290; scaled_horizontal = (scaled_horizontal + horizontal_offset * scale) & 0xfff; value = (u64)(s64)(scale - 1) << 23; - if (state->nSFrame_mode != 0) { + if (state->nSFrame_mode != GS_FRAME_MODE_FIELD) { display_width = (value | display_width) | ((u64)scaled_horizontal | ((u64)(s64)(height * 2 - 1) << 44)); } else { From 68bd4e73ee4b1b9c21e4e929f90e65fd5c084411 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:32:31 +0000 Subject: [PATCH 0792/1502] decomp: clarify names in poison_vessel_update domain_1_value_1 -> POISON_VESSEL_BLASTING: Retail 00307b40 loads moby->state from +0x20 into v1; 00307b4c-00307b50 dispatches value 1 to 00307d2c. That branch computes the timed blast radius, collects targets and sends blast hits at 00307d50-00307dc8, then increments pvars+0x70 and removes the vessel at expiry. Lethal incoming damage resets that same timer at 00307c7c, spawns destruction effects, and writes 1 to the identical moby+0x20 state byte at 00307ca4-00307cac. Authoritative source already declares POISON_VESSEL_BLASTING=1 and uses it for this exact moby->state switch branch, proving domain identity and canonical-member reuse. --- src/overlays/l13/mobys/poison_vessel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/poison_vessel.c b/src/overlays/l13/mobys/poison_vessel.c index 72c12bdad1..c31b43098b 100644 --- a/src/overlays/l13/mobys/poison_vessel.c +++ b/src/overlays/l13/mobys/poison_vessel.c @@ -328,7 +328,7 @@ void poison_vessel_update(struct Moby *moby) { spawn_poison_vessel_destruction_effects(moby, poison_vessel_vars); spawn_type_52_particle_near_moby(moby); allocate_voice_for_target_entry(0, 0, (int)moby); - moby->state = 1; + moby->state = POISON_VESSEL_BLASTING; } else { *health = *health - hit->damage; poison_vessel_vars->effect_level = 0xFA; From 6dab99361420347a52890ee233fe29c018d979dc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:32:31 +0000 Subject: [PATCH 0793/1502] decomp: clarify names in update_npc_dialogue domain_0_value_1 -> MENU_CONDITION_PURCHASE_PRICE_MET: Retail 0x266610-0x266630 derives entry from trigger+0x3c and signed index at +0x36, stride 0x1c, then reads kind at +8. Value 1 at 0x266634 selects price-table indexing and current_bolt_count subtraction at 0x26663c-0x266668. The same trigger goes to process_menu_entry at 0x2664fc; helper 0x266bec-0x266c18 tests current bolts against that same table price. This proves the established contextual MENU_CONDITION_PURCHASE_PRICE_MET domain member. domain_1_value_4 -> MENU_CONDITION_ALTERNATE_ITEM_AVAILABLE: Retail 0x266630-0x266638 compares SceneEntry+8 against 1 and then 4. Kind 4 selects 0x266674-0x266684, clearing alternate_item_available at 0x13d388 indexed by entry+0xa. Direct process_menu_entry helper reads the identical trigger entries/index/stride and kind; its 0x266c60-0x266c78 tests that same indexed alternate-item byte for nonzero, matching the established MENU_CONDITION_ALTERNATE_ITEM_AVAILABLE name. domain_2_value_1 -> MENU_CONDITION_PURCHASE_PRICE_MET: The unpaid pointer is the same trigger->entries[trigger->entry] binding: retail 0x266734-0x26674c multiplies trigger+0x36 by 0x1c, adds trigger+0x3c, and loads +8. Value 1 at 0x266750 enables the bolt-counter HUD using current_bolt_count at 0x266760-0x266790. It is the identical condition domain as the payment branch at 0x266630-0x266668 and helper price comparison 0x266bec-0x266c18, so reuse MENU_CONDITION_PURCHASE_PRICE_MET. domain_3_value_6 -> MENU_CONDITION_BOLT_THRESHOLD_AND_COUNT_DIFFERENCE_MET: Retail 0x266734-0x266758 reads the current SceneEntry+8 and accepts kind 6 for the current_bolt_count HUD. This is the same entry domain passed to direct process_menu_entry helper 0x266970: helper 0x26699c-0x2669b0 uses entries+index*0x1c and 0x266a64 reads +8. Its kind-6 branch 0x266c94-0x266cd0 requires bolts >= price-record unsigned threshold at +0x14 and then helper-count >=4. The supplied process_menu_entry context already names this condition MENU_CONDITION_BOLT_THRESHOLD_AND_COUNT_DIFFERENCE_MET; reuse that established name. --- src/overlays/shared/cutscenes/update_npc_dialogue.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/cutscenes/update_npc_dialogue.c b/src/overlays/shared/cutscenes/update_npc_dialogue.c index deee7e0327..bf57f248cb 100644 --- a/src/overlays/shared/cutscenes/update_npc_dialogue.c +++ b/src/overlays/shared/cutscenes/update_npc_dialogue.c @@ -72,6 +72,11 @@ s32 update_npc_dialogue(struct Moby *moby, struct SceneTrigger *trigger) __asm__("FUN_L00_00266448"); s32 update_npc_dialogue(struct Moby *moby, struct SceneTrigger *trigger) { + enum { + MENU_CONDITION_PURCHASE_PRICE_MET = 1, + MENU_CONDITION_ALTERNATE_ITEM_AVAILABLE = 4, + MENU_CONDITION_BOLT_THRESHOLD_AND_COUNT_DIFFERENCE_MET = 6 + }; struct Hero *hero_ptr = &hero; struct SceneEntry *entry; s32 index; @@ -121,9 +126,9 @@ s32 update_npc_dialogue(struct Moby *moby, struct SceneTrigger *trigger) { entry = &trigger->entries[trigger->entry]; if (entry->flags & 8) { - if (entry->cost_kind == 1) + if (entry->cost_kind == MENU_CONDITION_PURCHASE_PRICE_MET) current_bolt_count -= D_L00_001C40B0[entry->cost_id].f0; - else if (entry->cost_kind == 4) + else if (entry->cost_kind == MENU_CONDITION_ALTERNATE_ITEM_AVAILABLE) alternate_item_available[entry->cost_id] = 0; } if (entry->scene == -1) { @@ -152,7 +157,7 @@ s32 update_npc_dialogue(struct Moby *moby, struct SceneTrigger *trigger) { /* a fresh block-local pointer (not `entry`) keeps retail's registers */ struct SceneEntry *unpaid = &trigger->entries[trigger->entry]; - if (unpaid->cost_kind == 1 || unpaid->cost_kind == 6) { + if (unpaid->cost_kind == MENU_CONDITION_PURCHASE_PRICE_MET || unpaid->cost_kind == MENU_CONDITION_BOLT_THRESHOLD_AND_COUNT_DIFFERENCE_MET) { handle = queue_animation_update(2, 0x754E, initialize_bolt_counter_hud, From a52deec68d008cfa7edc7f622d9bc721bceea6ad Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:32:32 +0000 Subject: [PATCH 0794/1502] decomp: clarify names in update_hero_animation_for_movement_speed domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 00228c30 establishes s0=&hero (0013f350); 00228c3c loads byte +0x20a4, the authoritative C vehicle_mode field, into a0. After the mode-3 comparison, 00228c64 loads 1 and 00228c68 compares that same a0. Thus source mode==1 belongs to HeroVehicleMode, whose canonical shared member HERO_VEHICLE_MODE_CLANK=1 is supplied from include/rnc/hero/hero_state.h. Its branch 00228c70..00228c9c scales motion.speed_xy (+0x160) by 90 and floors anim_speed (+0xa90) at 0.5. This is the vehicle selector, not state.current (+0x2084), state.step (+0x2088), gravity mode or combo kind. --- src/overlays/shared/hero/hero_set_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_set_state.c b/src/overlays/shared/hero/hero_set_state.c index fbcb10de21..fffaf98c6d 100644 --- a/src/overlays/shared/hero/hero_set_state.c +++ b/src/overlays/shared/hero/hero_set_state.c @@ -3697,7 +3697,7 @@ void update_hero_animation_for_movement_speed(void) { player->anim_speed = speed; if (speed < 0.7f) player->anim_speed = 0.7f; - } else if (mode == 1) { + } else if (mode == HERO_VEHICLE_MODE_CLANK) { float speed = player->motion.speed_xy * 90.0f; player->anim_speed = speed; if (speed < 0.5f) From 5ee5ff977c04aba9424e57e1e8c54dcd0aa99f68 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:32:32 +0000 Subject: [PATCH 0795/1502] decomp: clarify names in resolve_hero_position_collisions domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Retail 0x002222f4 loads the hero byte at base 0x0013f350 + 0x20b3 (0x00141403), identified by the authoritative source as hero.gravity_mode; 0x002222f8 compares it with zero. The zero path with unk1F8 clear writes capsule_bottom directly to world Z at 0x00222358-0x0022235c. The same source field is switched in update_hero_ground_contact under HERO_GRAVITY_WORLD_DOWN, assigning gravity_dir.z = -1.0f. This is the exact HeroGravityMode selector, so reuse its canonical zero member. domain_1_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: Retail 0x002222f4 loads hero.gravity_mode at 0x00141403 into v1; 0x00222308 sets v0 to 1 and 0x0022230c compares that same selector with v0, choosing the rotated collision-offset helper at 0x00222330. The authoritative source also switches this exact field in update_hero_ground_contact: HERO_GRAVITY_OPPOSITE_GROUND_NORMAL copies ground_normal and scales it by -1 for gravity_dir. Supplied helper context FUN_L00_002334d0 uses the same member for the negative ground-normal offset. Thus the comparison belongs to HeroGravityMode and reuses its canonical member. domain_2_value_0 -> HERO_GRAVITY_WORLD_DOWN: Retail 0x00222450 restores hero base 0x0013f350, 0x00222454 loads byte +0x20b3 (hero.gravity_mode), and 0x00222458 branches on zero to the capsule-height probe at 0x002223a0. The source zero branch computes capsule_top - capsule_bottom; the nonzero branch calls the alternate sphere probe. This is the same field whose ground-contact switch assigns world-down gravity_dir.z = -1 under HERO_GRAVITY_WORLD_DOWN, and the same selector tested at 0x002222f4-0x002222f8. Reuse the canonical HeroGravityMode zero member. --- src/overlays/l02/hero/update_hero_state_motion.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l02/hero/update_hero_state_motion.c b/src/overlays/l02/hero/update_hero_state_motion.c index 5b7bbaafeb..470c1b87d2 100644 --- a/src/overlays/l02/hero/update_hero_state_motion.c +++ b/src/overlays/l02/hero/update_hero_state_motion.c @@ -582,8 +582,8 @@ s32 resolve_hero_position_collisions(s32 mode) { hero.path_constrain_pending = 0; } if (hero.state.control_mode != 0x11) { - if (hero.gravity_mode != 0 || hero.unk1F8 != 0) { - if (hero.gravity_mode == 1 || hero.unk1F8 != 0) { + if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN || hero.unk1F8 != 0) { + if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0) { FUN_L00_00233810(&collision_probe_offset, &collision_probe_offset, 0.6f); } else { FUN_L00_002334d0( @@ -599,7 +599,7 @@ s32 resolve_hero_position_collisions(s32 mode) { mask = 0xD24; } for (i = 0; i < 8; i++) { - if (hero.gravity_mode != 0) { + if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN) { if (!coll1_222270(&hero.motion.pos.q, mask, hero.moby, frame_scale * 0.4f)) break; } else { From fdd246ccb5c23bc34398ebe22b62272cd78288d0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:32:32 +0000 Subject: [PATCH 0796/1502] decomp: clarify names in blarg_ship_update domain_0_value_1 -> BLARG_SHIP_HANDLE_DAMAGE: Bound source src/overlays/l13/mobys/blarg_ship.c (SHA-256 7ee57279d70c849c4ba51e3dc2c722f9427a1932a68f9438bf9cad7e16658e58) assigns 1 to moby->state in BLARG_SHIP_ENTER_DAMAGE_HANDLING. Retail 0x0030ce50 loads s3=1 and 0x0030ceb4 stores s3 to moby+0x20. The same byte is read at 0x0030ce7c and compared with s3 at 0x0030ce80 to enter hit damage comparison/subtraction and animation at 0x0030ceb8-0x0030cf0c. Original Ghidra decompilation agrees. This is the exact state selector already named BLARG_SHIP_HANDLE_DAMAGE=1, not an unrelated equal-valued control domain. domain_1_value_2 -> BLARG_SHIP_EXPLODE: Bound source assigns 2 to moby->state when pvars+0x20 is less than hit+0x2c. Retail 0x0030cec0-0x0030cec8 loads and compares those floats; 0x0030ced4 loads 2 and 0x0030cedc stores it to moby+0x20. The same state byte read at 0x0030ce7c is compared with 2 at 0x0030cea0, entering 0x0030cf18-0x0030d110, which sets destruction save bits, emits effects, spawns an explosion and removes the moby. Original Ghidra decompilation agrees. Reuse the established local switch member BLARG_SHIP_EXPLODE=2 for this exact selector. --- src/overlays/l13/mobys/blarg_ship.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l13/mobys/blarg_ship.c b/src/overlays/l13/mobys/blarg_ship.c index 29b703b5cb..9fec650888 100644 --- a/src/overlays/l13/mobys/blarg_ship.c +++ b/src/overlays/l13/mobys/blarg_ship.c @@ -73,13 +73,13 @@ void blarg_ship_update(struct Moby *moby) { resolve_moby_hit_response(moby, hit, blarg_ship_vars + 0x20, 0, hit_buffer, 0, 0, 4); switch (moby->state) { case BLARG_SHIP_ENTER_DAMAGE_HANDLING: - moby->state = 1; + moby->state = BLARG_SHIP_HANDLE_DAMAGE; break; case BLARG_SHIP_HANDLE_DAMAGE: if (hit != 0) { float cost = *(float *)((char *)hit + 0x2c); if (*(float *)(blarg_ship_vars + 0x20) < cost) { - moby->state = 2; + moby->state = BLARG_SHIP_EXPLODE; } else { ((unsigned char *)blarg_ship_vars)[0x67] = 0xfa; *(float *)(blarg_ship_vars + 0x20) -= cost; From 4b4b47a2af39c1f2ec17725dac566c191f331f6f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:32:32 +0000 Subject: [PATCH 0797/1502] decomp: clarify names in water_reservoir_update domain_0_value_0 -> WATER_RESERVOIR_STATE_INITIALIZE: Retail 0x002ec754-0x002ec758 loads moby+0x20 and branches on zero to 0x002ec774. That branch writes state 1 at 0x002ec77c, command 2 at 0x002ec784, initializes pvars angle from random_angle_radians at 0x002ec780-0x002ec790 and height to 5 at 0x002ec798. The bound C maps this field to moby->state, proving a reservoir initialization state, separate from Hero state domains. domain_1_value_1 -> WATER_RESERVOIR_STATE_ACTIVE: Retail 0x002ec760-0x002ec764 compares the same moby+0x20 state byte with 1 and branches to 0x002ec79c. This path interprets command masks 8/4 and reloads the transition timer at 0x002ec79c-0x002ec7c8, then advances the persistent reservoir angle at 0x002ec7cc-0x002ec7f4. Other nonzero states bypass this path. This proves the reservoir active update state without asserting a water-flow direction. domain_2_value_1 -> WATER_RESERVOIR_STATE_ACTIVE: Retail 0x002ec774 loads 1 and 0x002ec77c stores it into the same moby+0x20 byte compared at 0x002ec764. The store occurs in the zero-state initialization branch, before command and pvars initialization, so subsequent calls enter the proven active command/angle update path at 0x002ec79c. This assignment must reuse the ACTIVE member used by the comparison. --- src/overlays/l12/mobys/water_reservoir.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l12/mobys/water_reservoir.c b/src/overlays/l12/mobys/water_reservoir.c index 75833ce057..78af1fb49c 100644 --- a/src/overlays/l12/mobys/water_reservoir.c +++ b/src/overlays/l12/mobys/water_reservoir.c @@ -45,18 +45,22 @@ void water_reservoir_update(struct Moby *moby) __asm__("FUN_L12_002ec720"); /* Moby class 384 */ void water_reservoir_update(struct Moby *moby) { + enum { + WATER_RESERVOIR_STATE_INITIALIZE = 0, + WATER_RESERVOIR_STATE_ACTIVE = 1 + }; float *reservoir_state = (float *)moby->pvars; float pos[4], offset0[4], offset1[4], pos_offset_delta[4], offset_pair_delta[4]; float fraction, frame_scale; int scaled; - if (moby->state != 0) { + if (moby->state != WATER_RESERVOIR_STATE_INITIALIZE) { extern float D_L12_0015F3FC __attribute__((sda)); frame_scale = D_L12_0015F3FC; - if (moby->state == 1) + if (moby->state == WATER_RESERVOIR_STATE_ACTIVE) goto active; goto update; } - moby->state = 1; + moby->state = WATER_RESERVOIR_STATE_ACTIVE; moby->command = 2; reservoir_state[0] = random_angle_radians(); reservoir_state[2] = 5.0f; From a8ba68f9ce3c34421c6cf957ee6ad5494627e319 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:32:32 +0000 Subject: [PATCH 0798/1502] decomp: clarify names in apply_hero_ground_material_effects domain_0_value_2 -> GROUND_MATERIAL_MAGNET: Authoritative source saves hero.ground_type before clearing it; retail 0x002097d4 loads that short into s2. The material-2 comparison at 0x002097f4-0x002097f8 gates contact-distance checks, then 0x00209838 stores 1 at hero+0x12e7, the established on_magnet_ground field. Original Ghidra likewise sets uRam00140637 for sVar1 == 2. This is a ground-material selector, not a hero-state ID. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00209830 loads the byte at hero+0x20a4 and 0x00209834 skips the item-moby class check when it is nonzero. Authoritative source identifies exactly this load and comparison as hero_data->vehicle_mode == 0. Supplied hero_set_state context uses HERO_VEHICLE_MODE_ON_FOOT for the same Hero.vehicle_mode field, and the supplied HeroVehicleMode enum defines that canonical member as 0. This proves the vehicle-mode domain independently of ground_type. domain_3_value_0 -> GROUND_MATERIAL_WATER: Retail 0x00209890 tests saved material s2 against zero; 0x002098a8-0x002098c0 subtracts ground_z from water_surface_z and stores water_depth, and 0x002098c4-0x002098e0 sets wading for depths between 0.25 and 0.85. Original Ghidra agrees. The embedded update_hero_ground_contact source obtains ground_type from collision_hit_material(), and for ground_type == 0 resolves water_surface_z and tracks in_water_frames. These linked operations prove a water collision material rather than an idle-state or vehicle-mode zero. domain_7_value_2 -> GROUND_MATERIAL_MAGNET: The second comparison of saved ground_type against 2 at retail 0x002099a4-0x002099a8 sets hero+0x12e7 to 1 at 0x002099b8. Source identifies that byte as on_magnet_ground; original Ghidra sets the same uRam00140637 for sVar1 == 2. It shares the saved collision-material domain and meaning with the earlier material-2 contact branch. --- .../l16/hero/apply_hero_ground_material_effects.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/overlays/l16/hero/apply_hero_ground_material_effects.c b/src/overlays/l16/hero/apply_hero_ground_material_effects.c index 0844d6dd0e..089ee3b9f5 100644 --- a/src/overlays/l16/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l16/hero/apply_hero_ground_material_effects.c @@ -26,6 +26,10 @@ extern int hero_set_state(int, int) __asm__("FUN_L16_0021e398"); void apply_hero_ground_material_effects(void) __asm__("FUN_L16_002097a0"); void apply_hero_ground_material_effects(void) { + enum { + GROUND_MATERIAL_WATER = 0, + GROUND_MATERIAL_MAGNET = 2 + }; struct Hero *hero_data = &hero; int keep = hero_data->ground_sound_class; int saved_ground_type = hero_data->ground_type; @@ -37,10 +41,10 @@ void apply_hero_ground_material_effects(void) { hero_data->unk308 = 0; if (saved_ground_type == -1) return; - if (saved_ground_type == 2) { + if (saved_ground_type == GROUND_MATERIAL_MAGNET) { if (hero_data->frames_off_ground.s == 0 || hero_data->ground_distance < 0.3f) { hero_data->on_magnet_ground = 1; - if (hero_data->vehicle_mode == 0) { + if (hero_data->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { char *item_moby = (char *)hero_data->items[1].moby; if (item_moby != 0 && MOBY(item_moby)->oclass == 0xAD) hero_data->unk308 = 1; @@ -53,7 +57,7 @@ void apply_hero_ground_material_effects(void) { q->water_depth = 0.2f; q->water_surface_z = q->ground_z.f + 0.2f; } - if (saved_ground_type == 0) { + if (saved_ground_type == GROUND_MATERIAL_WATER) { struct Hero *q = &hero; float water_depth = q->water_surface_z - q->ground_z.f; q->water_depth = water_depth; @@ -90,7 +94,7 @@ void apply_hero_ground_material_effects(void) { struct Hero *q = &hero; q->unk12E9 = 1; } - if (saved_ground_type == 0x2) { + if (saved_ground_type == GROUND_MATERIAL_MAGNET) { struct Hero *q = &hero; q->on_magnet_ground = 1; } From 14d7bc49700df8ad98128b32d39c9e00a1e0029c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:34:22 +0000 Subject: [PATCH 0799/1502] decomp: clarify names in handle_mine_layer_damage domain_0_value_5 -> MINE_LAYER_KNOCKBACK_UNTIL_EXPLOSION: Retail 0x002ca820 preserves the incoming mine layer in s2; 0x002ca878 loads its byte state at +0x20 and 0x002ca87c skips damage handling when it equals 5. Supplied mine_layer_update passes this same moby to handle_mine_layer_damage, then switches on its state. Its established MINE_LAYER_KNOCKBACK_UNTIL_EXPLOSION=5 branch steps knockback and explodes/removes the moby on landing or z<5. This guard prevents further damage processing in that terminal knockback state. domain_1_value_4 -> MINE_LAYER_KNOCKBACK_AND_RECOVER: The short nonlethal damage-response branch at retail 0x002ca950 initializes pvars+0x70 knockback, starts animation 3 at 0x002ca9cc-0x002ca9d4, and loads state 4 at 0x002ca9f0 before the shared byte store to incoming moby s2+0x20 at 0x002caaa0. Supplied mine_layer_update calls this handler on the same moby and dispatches state 4 as established MINE_LAYER_KNOCKBACK_AND_RECOVER: step_moby_motion completion returns it to state 1 with idle animation. domain_2_value_4 -> MINE_LAYER_KNOCKBACK_AND_RECOVER: The long nonlethal response branch retail 0x002ca9f4-0x002caa98 initializes pvars+0x70 knockback, starts animation 4, sets limits 7.5/15.0, and loads 4 at 0x002caa88 for store to s2+0x20 at 0x002caaa0. s2 is the input mine layer, not the response selector s0. Its caller mine_layer_update switches on that same moby->state; established MINE_LAYER_KNOCKBACK_AND_RECOVER=4 steps motion then returns to state 1 on landing. domain_3_value_5 -> MINE_LAYER_KNOCKBACK_UNTIL_EXPLOSION: Health subtraction at retail 0x002ca904-0x002ca924 forces lethal response 1 at health<=0. Its 0x002caaa4 branch initializes knockback and animation 5, clears moby flag 0x1000 at 0x002cab50-0x002cab58, loads current-state value 5 at 0x002cab44 and stores to incoming moby s2+0x20 at 0x002cab60. The same-object caller's established MINE_LAYER_KNOCKBACK_UNTIL_EXPLOSION=5 branch explodes/removes it on landing or falling below z=5. --- src/overlays/l03/mobys/mine_layer.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/overlays/l03/mobys/mine_layer.c b/src/overlays/l03/mobys/mine_layer.c index 397bf3aafc..67f2aca9ae 100644 --- a/src/overlays/l03/mobys/mine_layer.c +++ b/src/overlays/l03/mobys/mine_layer.c @@ -396,6 +396,10 @@ void handle_mine_layer_damage(struct Moby *damaged_moby) { TROOPER_DAMAGE_LONG_KNOCKBACK_ALTERNATE = 5, TROOPER_DAMAGE_SHORT_KNOCKBACK_ALTERNATE = 6 }; + enum { + MINE_LAYER_KNOCKBACK_AND_RECOVER = 4, + MINE_LAYER_KNOCKBACK_UNTIL_EXPLOSION = 5 + }; TrooperVars *trooper_vars = (TrooperVars *)damaged_moby->pvars; TrooperHit *hit_record; Vec4 at; @@ -408,7 +412,7 @@ void handle_mine_layer_damage(struct Moby *damaged_moby) { hit_record = trooper_find_hit(damaged_moby, 0x330000, 0); damage_response = resolve_moby_hit_response( damaged_moby, hit_record, &trooper_vars->health, 0, &hit, &dmg, 0, 4); - if (hit != 1 && damaged_moby->state != 5) { + if (hit != 1 && damaged_moby->state != MINE_LAYER_KNOCKBACK_UNTIL_EXPLOSION) { if (hit_record->source != NULL) { if (hit_record->source != hero.items[0].moby) knockback_arc_angle = fast_arc_tan(damaged_moby->pos.x - hit_record->source->pos.x, @@ -445,7 +449,7 @@ void handle_mine_layer_damage(struct Moby *damaged_moby) { 0); trooper_vars->kb_min = 5.0f; trooper_vars->kb_max = 10.0f; - damaged_moby->state = 4; + damaged_moby->state = MINE_LAYER_KNOCKBACK_AND_RECOVER; break; case TROOPER_DAMAGE_LONG_KNOCKBACK: case TROOPER_DAMAGE_LONG_KNOCKBACK_ALTERNATE: @@ -468,7 +472,7 @@ void handle_mine_layer_damage(struct Moby *damaged_moby) { 0); trooper_vars->kb_min = 7.5f; trooper_vars->kb_max = 15.0f; - damaged_moby->state = 4; + damaged_moby->state = MINE_LAYER_KNOCKBACK_AND_RECOVER; break; case TROOPER_DAMAGE_LETHAL: trooper_vars->kb_speed = @@ -492,7 +496,7 @@ void handle_mine_layer_damage(struct Moby *damaged_moby) { trooper_vars->kb_max = 15.0f; damaged_moby->flags &= 0xEFFF; *((u8 *)trooper_vars + 0x67) = 0xFA; - damaged_moby->state = 5; + damaged_moby->state = MINE_LAYER_KNOCKBACK_UNTIL_EXPLOSION; break; } trooper_anim_update(damaged_moby, trooper_vars->anim); From a618acad4aa5fd9af42ccbd8902a247cc75a8cb9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:34:23 +0000 Subject: [PATCH 0800/1502] decomp: clarify names in find_grind_rail domain_3_value_4 -> HERO_CONTROL_MODE_JUMP: Retail 0x0020d18c loads hero+0x208c (hero.state.control_mode), separately from current-state hero+0x2084 at 0x0020d1a8. At 0x0020d1d8 mode 4 proceeds only when hero+0x41e (past_jump_apex) or hero+0x1ca (rail_catch_grace) is nonzero (0x0020d1e0-0x0020d1f0). Supplied update_hero_offset_rail_candidate tests this same mode 4 before the jump apex. Supplied update_hero_collision_capsule_dimensions explicitly handles control_mode == 4 by comparing state_timer to takeoff_frame and testing past_jump_apex, proving the jump control-mode role. This is a separate control-mode domain, not equal-valued HERO_STATE_CROUCH. --- src/overlays/shared/hero/hero_switch_item.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index aa2a06ee99..e45ad3f8bb 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -239,6 +239,9 @@ extern u8 D_0013D4DD_lui __asm__("D_0013D4DD") NOT_SDA; void find_grind_rail(void) __asm__("FUN_L00_0020cf58"); void find_grind_rail(void) { + enum { + HERO_CONTROL_MODE_JUMP = 4 + }; V_cf58 proximity_or_rail_point, proximity_or_query_position, third_proximity_point; s32 rail_owner, rail_query_integer_value, rail_kind; @@ -295,7 +298,7 @@ void find_grind_rail(void) { if ((u32)(hero.state.current - 41) < 2 && (hero.rail_off_frames != 0 || hero.rail_gap_jump != 0)) { } else { - if (control_mode != 4) + if (control_mode != HERO_CONTROL_MODE_JUMP) return; if (hero.past_jump_apex == 0 && hero.rail_catch_grace == 0) return; From 626627b6ea82e31a8ee1ae01ab88672300374290 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:34:23 +0000 Subject: [PATCH 0801/1502] decomp: clarify names in glove_of_doom_update domain_0_value_3 -> GLOVE_RELEASE_HELD_MOBY: Retail 0x002c7bf8 consumes ammunition, then 0x002c7c00-0x002c7c04 writes 3 to 0x20(s3). The same byte is read for switch dispatch at 0x002c7c24. Existing local GLOVE_RELEASE_HELD_MOBY=3 names that branch, which calls release_glove_of_doom_held_moby at 0x002c7d28 and clears held. domain_1_value_2 -> GLOVE_IDLE: Initialization tests animation flag bit 2 at 0x002c7c50-0x002c7c58 and selects 2 at 0x002c7c5c for storage to moby state byte 0x20(s3) at 0x002c7c64. This exact field is the switch selector at 0x002c7c24; existing local GLOVE_IDLE=2 names its empty state-specific branch and common held-moby maintenance tail. domain_2_value_1 -> GLOVE_WAIT_FOR_ANIMATION: When animation flag bit 2 is clear, initialization loads 1 at 0x002c7c60 and stores it to moby->state at 0x002c7c64. That same field selects existing local GLOVE_WAIT_FOR_ANIMATION=1, whose branch retests the flag at 0x002c7c68-0x002c7c7c before advancing to idle. domain_3_value_2 -> GLOVE_IDLE: In existing GLOVE_WAIT_FOR_ANIMATION, retail 0x002c7c68-0x002c7c70 tests animation flag bit 2; when set, 0x002c7c74-0x002c7c7c writes 2 to moby state byte 0x20(s3). The same byte dispatches the switch at 0x002c7c24 and its existing GLOVE_IDLE=2 branch does no state-specific work. domain_4_value_4 -> GLOVE_POST_RELEASE_WAIT: The release branch calls release_glove_of_doom_held_moby at 0x002c7d28 and clears held at 0x002c7d34, then loads 4 at 0x002c7d48 and writes it to the same switched moby state byte at 0x002c7d54 while resetting the timer. Existing local GLOVE_POST_RELEASE_WAIT=4 names the branch waiting for hero animation/state conditions to clear. domain_5_value_2 -> GLOVE_IDLE: Existing GLOVE_POST_RELEASE_WAIT checks hero current state and item animation at 0x002c7d60-0x002c7d78. Once both blockers clear, 0x002c7d80-0x002c7d8c writes 2 to 0x20(s3), the exact moby state switch selector. Existing GLOVE_IDLE=2 is the destination with no state-specific work before held synchronization or spawn. domain_6_value_6 -> GLOVE_SKIP_HELD_MOBY_SYNC_AND_SPAWN: Existing GLOVE_BEGIN_SKIP_HELD_MOBY_SYNC_AND_SPAWN maps to retail 0x002c7d88 loading 6 and 0x002c7d8c storing it to switched byte moby->state. Existing GLOVE_SKIP_HELD_MOBY_SYNC_AND_SPAWN=6 returns at switch dispatch, bypassing the common held position synchronization and ammunition-gated creation at 0x002c7d90-0x002c7dd4. --- src/overlays/shared/weapons/glove_of_doom.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/weapons/glove_of_doom.c b/src/overlays/shared/weapons/glove_of_doom.c index 8a12048f8c..6c25a27f45 100644 --- a/src/overlays/shared/weapons/glove_of_doom.c +++ b/src/overlays/shared/weapons/glove_of_doom.c @@ -320,7 +320,7 @@ void glove_of_doom_update(struct Moby *moby) { (hero.state.current == 0x23 && hero.state_timer == scale_game_frames(0x10))) { allocate_hero_voice_for_entry(0x1A, 0); use_ammo(-1, 1); - moby->state = 3; + moby->state = GLOVE_RELEASE_HELD_MOBY; } } grip.q = glove_carrier_vars->grip.q; @@ -329,13 +329,13 @@ void glove_of_doom_update(struct Moby *moby) { case GLOVE_INITIALIZE: glove_carrier_vars->held = 0; if (moby->anim_flags & 2) { - moby->state = 2; + moby->state = GLOVE_IDLE; } else { - moby->state = 1; + moby->state = GLOVE_WAIT_FOR_ANIMATION; } case GLOVE_WAIT_FOR_ANIMATION: if (moby->anim_flags & 2) { - moby->state = 2; + moby->state = GLOVE_IDLE; } break; case GLOVE_IDLE: @@ -356,16 +356,16 @@ void glove_of_doom_update(struct Moby *moby) { } else { allocate_voice_for_target_entry(0, 0, moby); } - moby->state = 4; + moby->state = GLOVE_POST_RELEASE_WAIT; glove_carrier_vars->timer = scale_game_frames(0x14); break; case GLOVE_POST_RELEASE_WAIT: if (hero.state.current != 0x23 && !hero.item_anim_active) { - moby->state = 2; + moby->state = GLOVE_IDLE; } break; case GLOVE_BEGIN_SKIP_HELD_MOBY_SYNC_AND_SPAWN: - moby->state = 6; + moby->state = GLOVE_SKIP_HELD_MOBY_SYNC_AND_SPAWN; break; case GLOVE_SKIP_HELD_MOBY_SYNC_AND_SPAWN: return; From 04df72e503bc6e28ddb319230d8a0826b3562dc5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:34:23 +0000 Subject: [PATCH 0802/1502] decomp: clarify names in oil_tanker_front_update domain_0_value_1 -> OIL_TANKER_WAIT_FOR_CAMERA_MODE: Retail 0x003173d0 loads 1 and 0x003173ec stores it to head+0x20, the same byte read at 0x00317300 and dispatched to 0x003174a4 when equal to 1. That branch checks camera_secondary_mode[0] against 0x32 at 0x003174a4-0x003174b0. The source names this same selector's existing case OIL_TANKER_WAIT_FOR_CAMERA_MODE=1; reuse it for the initialization assignment. domain_1_value_2 -> OIL_TANKER_FOLLOW_PATH_WITH_DAMAGE: After the camera 0x32 check, retail 0x003174b8 loads 2 and 0x003174c0 stores it to head+0x20, the exact state byte dispatched at 0x00317300-0x00317328. It then selects the path at chain_vars+0x60, resets point and link offsets, and joins path progression at 0x00317514. Source already names this state OIL_TANKER_FOLLOW_PATH_WITH_DAMAGE=2; reuse its member for this transition. domain_2_value_2 -> OIL_TANKER_FOLLOW_PATH_WITH_DAMAGE: Retail 0x003175f8 reloads head+0x20, 0x003175fc loads 2, and 0x00317600 skips the damage call unless equal; 0x00317608 calls process_oil_tanker_damage_and_destruction. This is the same moby->state byte and existing local enum domain as the switch case OIL_TANKER_FOLLOW_PATH_WITH_DAMAGE=2, so the comparison should reuse that canonical member. --- src/overlays/l11/mobys/oil_tanker_front.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l11/mobys/oil_tanker_front.c b/src/overlays/l11/mobys/oil_tanker_front.c index 6c6ce1b9e9..5bd6c11a68 100644 --- a/src/overlays/l11/mobys/oil_tanker_front.c +++ b/src/overlays/l11/mobys/oil_tanker_front.c @@ -95,7 +95,7 @@ void oil_tanker_front_update(struct Moby *moby) { chain_vars->sound = -1; chain_vars->point = 0; chain_vars->t = 0.0f; - moby->state = 1; + moby->state = OIL_TANKER_WAIT_FOR_CAMERA_MODE; for (i = 0; i < 8; i++) { struct Moby *link; chain_vars->links[i] = create_moby(0x4F1); @@ -117,7 +117,7 @@ void oil_tanker_front_update(struct Moby *moby) { if (camera_secondary_mode[0] == 0x32) { int i; - moby->state = 2; + moby->state = OIL_TANKER_FOLLOW_PATH_WITH_DAMAGE; chain_vars->path = (char *)l11_paths[chain_vars->path_index]; chain_vars->point = 0; for (i = 0; i < 8; i++) { @@ -143,7 +143,7 @@ void oil_tanker_front_update(struct Moby *moby) { } update_oil_tanker_front_path_pose(moby); update_oil_tanker_link_path_poses(moby); - if (moby->state == 2) { + if (moby->state == OIL_TANKER_FOLLOW_PATH_WITH_DAMAGE) { process_oil_tanker_damage_and_destruction(moby); } if (voice_is_playing(moby, chain_vars->sound) == 0) { From e14dd160db02de3371624c139ede5356a1c0be0b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:34:23 +0000 Subject: [PATCH 0803/1502] decomp: clarify names in update_oscillating_target_link domain_0_value_1 -> TARGET_TRACKING_STATE_ACTIVE: Authoritative source SHA-256 77ae6cfa4418e74508fc57ed67380f0c7bdf4a108231b24cdbc62ac9332b1b43 declares TARGET_TRACKING_STATE_ACTIVE = 1 and uses it in switch(moby->state). Retail 0x00302f40 retains the Moby in s2; 0x00302f68 loads its state byte at +0x20, and 0x00302f70/0x00302f74 dispatch value 1 to 0x00302fc8. Initialization loads v0=1 at 0x00302fb0 and stores it to the identical byte with sb v0,0x20(s2) at 0x00302fc4. The destination branch tracks target yaw/distance, advances angular phase, interpolates position, gates strip update and tests collision. Original Ghidra likewise shows the state-0 store followed by the state-1 branch on the same +0x20 field. Thus this assignment enters the already named active state, rather than a boolean or another control domain. --- src/overlays/l12/mobys/oscillating_target_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l12/mobys/oscillating_target_link.c b/src/overlays/l12/mobys/oscillating_target_link.c index 421b0e2748..0869768f61 100644 --- a/src/overlays/l12/mobys/oscillating_target_link.c +++ b/src/overlays/l12/mobys/oscillating_target_link.c @@ -289,7 +289,7 @@ void oscillating_target_link_update(Moby *moby) { oscillating_target_link_state->f2308 = 0x17; oscillating_target_link_state->f230C = 0x22; oscillating_target_link_state->f2300 = 0; - moby->state = 1; + moby->state = TARGET_TRACKING_STATE_ACTIVE; break; case TARGET_TRACKING_STATE_ACTIVE: moby->rot.z = From d90bab676545490d0123cd53f21713c2e42a9a45 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:34:23 +0000 Subject: [PATCH 0804/1502] decomp: clarify names in draw_lens_flare domain_0_value_1 -> LENS_FLARE_STATE_ACTIVE: Retail 0x001edca4 loads effect_ribbon.state from 0x00187304; 0x001edc5c sets the comparison operand to 1 and 0x001edca8 rejects any other value. Only the matching value, with target flags permitting rendering and positive intensity, reaches projection and the sixteen draw_textured_quad calls. Original Ghidra likewise gates drawing on g_nProjectedTargetOverlayActive == 1. This establishes the active rendering state of the lens flare itself. domain_1_value_0 -> LENS_FLARE_STATE_INACTIVE: Retail 0x001edcc4..0x001edcc8 exits via a zero store to the same 0x00187304 state field when the state fails the active gate or the target flag 0x80 is set. A subsequent zero state fails comparison against 1 at 0x001edca8 and cannot reach projection or sprite drawing. Original Ghidra calls this field g_nProjectedTargetOverlayActive and clears it in the unavailable-target branch, proving the inactive rendering state rather than the separate pending float at offset 8. --- src/rendering/effects/draw_lens_flare.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/rendering/effects/draw_lens_flare.c b/src/rendering/effects/draw_lens_flare.c index a54eb9242c..a6f481ce44 100644 --- a/src/rendering/effects/draw_lens_flare.c +++ b/src/rendering/effects/draw_lens_flare.c @@ -18,6 +18,10 @@ void draw_lens_flare(void) __asm__("FUN_001edc50"); void draw_lens_flare(void) { + enum { + LENS_FLARE_STATE_INACTIVE = 0, + LENS_FLARE_STATE_ACTIVE = 1 + }; f32 scr[4]; f32 ctr[4]; f32 screen_center_delta[4]; @@ -36,8 +40,8 @@ void draw_lens_flare(void) { s32 x; s32 y; - if (effect_ribbon.state != 1 || (effect_ribbon.moby->flags & 0x80)) { - effect_ribbon.state = 0; + if (effect_ribbon.state != LENS_FLARE_STATE_ACTIVE || (effect_ribbon.moby->flags & 0x80)) { + effect_ribbon.state = LENS_FLARE_STATE_INACTIVE; return; } if (effect_ribbon.intensity <= 0.0f) { From dfce889c628c1f23e0a5d6b0ff3df872ee65e6ad Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:34:23 +0000 Subject: [PATCH 0805/1502] decomp: clarify names in poison_vessel_update domain_0_value_1 -> POISON_VESSEL_FOLLOW_TARGET: Retail 002e8030 loads this vessel's state from +0x20; 002e8040 branches on 1 to the existing FOLLOW_TARGET case at 002e8160. After a valid collision, 002e80c4-002e80cc stores the collision moby into data+0x10 and writes 1 to that same vessel state byte. The following case uses data+0x10 in the follow helper at 002e81c4-002e81d8. Thus this assignment enters the exact existing POISON_VESSEL_FOLLOW_TARGET domain/member. domain_2_value_0 -> POISON_VESSEL_FREE_FLIGHT: Retail 002e81f4-002e8204 handles absent follow context by storing zero to this vessel's +0x20 state byte and clearing vertical displacement and target. The same byte is loaded at 002e8030 and its zero branch at 002e8034 enters the existing POISON_VESSEL_FREE_FLIGHT case, which applies gravity and swept collision movement at 002e8050-002e8098. This proves reuse of the existing FREE_FLIGHT member for the fallback state assignment. --- src/overlays/l15/mobys/poison_vessel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l15/mobys/poison_vessel.c b/src/overlays/l15/mobys/poison_vessel.c index 40b377d117..78c3bc4587 100644 --- a/src/overlays/l15/mobys/poison_vessel.c +++ b/src/overlays/l15/mobys/poison_vessel.c @@ -170,7 +170,7 @@ void poison_vessel_update(Moby_2E9358 *moby) { if (((Tb *)D_L15_001744C0_2E9358)->f18 != 0 && get_moby_pvars_link(((Tb *)D_L15_001744C0_2E9358)->f18) != 0) { data->target = (Moby_2E9358 *)((Tb *)D_L15_001744C0_2E9358)->f18; - moby->state = 1; + moby->state = POISON_VESSEL_FOLLOW_TARGET; data->f8 = 0.0f; moby->pos = ((Tb *)D_L15_001744C0_2E9358)->v20; } else if (((Tb *)D_L15_001744C0_2E9358)->f18 == D_001413D0_lui || @@ -203,7 +203,7 @@ void poison_vessel_update(Moby_2E9358 *moby) { } } if (follow_context == 0) { - moby->state = 0; + moby->state = POISON_VESSEL_FREE_FLIGHT; data->f8 = 0.0f; data->target = 0; } From 65cf4a4b6365868866f67c23a26edfa93cfe3aed Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:34:23 +0000 Subject: [PATCH 0806/1502] decomp: clarify names in update_blarg_space_commando_beam domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Current source selector is hero.vehicle_mode, the exact HeroVehicleMode domain supplied in include/rnc/hero/hero_state.h. Retail 002ff398..002ff3a8 loads the hero vehicle-mode byte at 001413f4 and compares it with 1; 002ff3b0..002ff3cc halves the beam horizontal step in that mode. Original decompilation agrees. Reuse canonical HERO_VEHICLE_MODE_CLANK, not equal-valued HeroStateId or HeroGravityMode members. domain_1_value_65536 -> BEAM_SEGMENT_HIT_WITH_FADING_ENDPOINT: Retail 002ff558..002ff584 admits an adjacent beam-point pair only when both weights at pvars+0x23c+16*n are >=0.6. At 002ff5b0..002ff5d4 a2 starts at 0x10000 and gains bit 1 only if both endpoint weights are >=1. Thus effective 0x10000 describes an admitted segment with at least one weight below 1. Current C caps colliding/full ending points to 0.98 and approaches subunit weights to zero (002ff4cc..002ff504), proving fading endpoints. 002ff5e8 passes this hit_type to make_hit_descriptor; checked helper 002686a0 stores a2 at descriptor+0x14. domain_2_value_65537 -> BEAM_SEGMENT_HIT_WITH_FULL_WEIGHT_ENDPOINTS: Retail 002ff5b0..002ff5d4 tests the two consecutive beam-point weights at +0x23c against 1.0 and selects 0x10001 only when both ordered comparisons pass. Current source likewise assigns hit_type=0x10001 only for both weights >=1. Initialization gives interior points unit weight; collision and frame-20 ending cap it to 0.98. 002ff5e8 passes the selected type to make_hit_descriptor, whose checked 002686a0 stores it at descriptor+0x14; 002ff618 then submits the adjacent segment and descriptor to collision_line. The name states the proven full-weight endpoint condition. --- src/overlays/shared/enemies/blarg_space_commando.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/blarg_space_commando.c b/src/overlays/shared/enemies/blarg_space_commando.c index 0a5939fa25..df7ae181e1 100644 --- a/src/overlays/shared/enemies/blarg_space_commando.c +++ b/src/overlays/shared/enemies/blarg_space_commando.c @@ -819,6 +819,10 @@ void spawn_blarg_space_commando_beam_sparks(char *moby) __asm__("FUN_L06_002ff97 extern void add_draw_callback(void *, void *) __asm__("FUN_001f4600"); void update_blarg_space_commando_beam(void *owner_moby) { + enum { + BEAM_SEGMENT_HIT_WITH_FADING_ENDPOINT = 0x10000, + BEAM_SEGMENT_HIT_WITH_FULL_WEIGHT_ENDPOINTS = 0x10001 + }; char *moby = owner_moby; FanData *beam_state = ((FanData *)MOBY(moby)->pvars); int frames; @@ -848,7 +852,7 @@ void update_blarg_space_commando_beam(void *owner_moby) { for (i = 0; i < 16; i++) { char *entry; - if (hero.vehicle_mode == 1) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { step = (beam_point_horizontal_speed_gp * frame_time) * 0.5f; } else { step = beam_point_horizontal_speed_gp * frame_time; @@ -886,9 +890,9 @@ void update_blarg_space_commando_beam(void *owner_moby) { point[1] = fast_sin(MOBY(moby)->rot.z); point[2] = 1.0f; point[3] = 5627.925f; - hit_type = 0x10000; + hit_type = BEAM_SEGMENT_HIT_WITH_FADING_ENDPOINT; if (1.0f <= *(float *)(entry + 0x23C) && 1.0f <= *(float *)(next_entry + 0x23C)) { - hit_type = 0x10001; + hit_type = BEAM_SEGMENT_HIT_WITH_FULL_WEIGHT_ENDPOINTS; } make_hit_descriptor(&shot, (struct Moby *)moby, hit_type, point, 1.0f); shot.oclass = MOBY(moby)->oclass; From 543c500c6fe11f29473e198b4f46a6315bf55818 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:36:26 +0000 Subject: [PATCH 0807/1502] decomp: clarify names in update_level11_layered_effect_and_queue_draw domain_0_value_1 -> EFFECT_UPDATE_AND_QUEUE_DRAW: Authoritative source SHA-256 55c69b95cf2cf4783c80cfd9ddb7c696c9a51143b599b48ecc009d59f822452d defines EFFECT_UPDATE_AND_QUEUE_DRAW=1 in the enum used by switch(moby->state). Retail 0x0031e314 loads byte 0x20(s2), 0x0031e31c/0x0031e320 dispatch value 1 to 0x0031e4c8, and initialization writes that same byte with 1 at 0x0031e3e8-0x0031e3f0. The target branch performs visibility/distance gates, scroll updates, and queues draw callback 0x0031db50 with the same moby at 0x0031e674-0x0031e680. Original Ghidra confirms the param_1+0x20 store and cVar1==1 branch. Thus the assignment enters the already named local effect state; unrelated HeroStateId/vehicle/gravity enums do not apply. --- src/overlays/l11/mobys/layered_scroll_effect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/layered_scroll_effect.c b/src/overlays/l11/mobys/layered_scroll_effect.c index 0c68fd89af..0814bc3189 100644 --- a/src/overlays/l11/mobys/layered_scroll_effect.c +++ b/src/overlays/l11/mobys/layered_scroll_effect.c @@ -997,7 +997,7 @@ void layered_scroll_effect_update(struct Moby *moby) { 1); layered_effect_color_tables_initialized_gp = 1; } - moby->state = 1; + moby->state = EFFECT_UPDATE_AND_QUEUE_DRAW; for (i = 0; i < 3; i++) { D_L11_001FF750[i].a = 0; D_L11_001FF750[i].b = 0; From 15c2654c85182e7bd6ae9ca2e760dc9d71585825 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:36:26 +0000 Subject: [PATCH 0808/1502] decomp: clarify names in update_thrown_bomb domain_0_value_2 -> BOMB_STATE_RESTING: Retail 0x002c5ec0 saves the bomb object in s4; 0x002c5edc reads its state byte at +0x20 and 0x002c5ee0 dispatches value 2 to the resting timer-only branch at 0x002c6130. After sphere contact, upward normal >=0.3 and low velocity length, 0x002c60a0 loads 2 and 0x002c60ac stores it to that same +0x20 byte, then +0x28 receives a scaled 90-frame fuse. This proves reuse of the existing BOMB_STATE_RESTING member of the local moby->state enum. domain_1_value_3 -> BOMB_STATE_EXPLODE: In the moving branch, retail 0x002c60b4-0x002c60b8 decrements the bomb_data timer at s3+0x28; on expiry 0x002c60c0 loads 3 and 0x002c60c8 stores it to s4+0x20. That exact state byte is read at 0x002c5edc; value 3 dispatches at 0x002c5f04-0x002c5f08 to 0x002c619c, which calls spawn_explosion at 0x002c6218 and mark_moby_for_removal at 0x002c6220. Therefore the assignment uses existing BOMB_STATE_EXPLODE. domain_2_value_3 -> BOMB_STATE_EXPLODE: In the resting branch at 0x002c6130, the timer at s3+0x28 is decremented; on expiry 0x002c613c loads 3 and 0x002c6144 writes it to s4+0x20. This is the same moby->state byte loaded at 0x002c5edc and dispatched for value 3 to 0x002c619c by 0x002c5f04-0x002c5f08. The destination branch spawns the explosion and removes the bomb at 0x002c6218-0x002c6224, proving reuse of existing BOMB_STATE_EXPLODE. --- src/overlays/l16/mobys/bomb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l16/mobys/bomb.c b/src/overlays/l16/mobys/bomb.c index 9f3b4c74d4..d2c783bbe4 100644 --- a/src/overlays/l16/mobys/bomb.c +++ b/src/overlays/l16/mobys/bomb.c @@ -119,12 +119,12 @@ void thrown_bomb_update(L16FallingMoby *moby) { qcopy(moby->position, D_L16_hitN.position); moby->position[2] += normal[2]; if (normal[2] >= 0.3f && fast_vec_length(bomb_data->velocity) < D_0015ED6C * 0.25f) { - moby->state = 2; + moby->state = BOMB_STATE_RESTING; bomb_data->timer = scale_game_frames(90); } } if (fast_dec_timer(&bomb_data->timer)) { - moby->state = 3; + moby->state = BOMB_STATE_EXPLODE; } else if (bomb_data->timer < scale_game_frames(45) && bomb_data->timer % scale_game_frames(10) == 0) { bomb_data->reaction = 250; @@ -134,7 +134,7 @@ void thrown_bomb_update(L16FallingMoby *moby) { break; case BOMB_STATE_RESTING: if (fast_dec_timer(&bomb_data->timer)) { - moby->state = 3; + moby->state = BOMB_STATE_EXPLODE; } else if (bomb_data->timer < scale_game_frames(61) && bomb_data->timer % scale_game_frames(20) == 0) { bomb_data->reaction = 250; From 47bf04eb62cbf8ad45b9e3f4cf38929432e18751 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:36:26 +0000 Subject: [PATCH 0809/1502] decomp: clarify names in update_moby_proximity_interaction domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: The authoritative C selector is hero.vehicle_mode, identifying the HeroVehicleMode domain. Original retail Ghidra compares cRam001413f4 with 1; retail 0x0028e3d0 establishes base 0x00140000, 0x0028e3d8 loads its byte at +0x13f4, and 0x0028e3d4/0x0028e3dc compare it against 1. After the separate level-index comparison against 10 at 0x0028e3c8-0x0028e3cc, equality selects moby state 0x2A, flags 0x41 and start_scene(9) at 0x0028e3e4-0x0028e3f8. The supplied include/rnc/hero/hero_state.h HeroVehicleMode domain declares canonical HERO_VEHICLE_MODE_CLANK=1; reuse is justified by the actual vehicle_mode selector, not by equal values in HeroStateId or HeroGravityMode. --- src/overlays/shared/mobys/update_moby_proximity_interaction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/mobys/update_moby_proximity_interaction.c b/src/overlays/shared/mobys/update_moby_proximity_interaction.c index 27b91de4a4..0988c02ad8 100644 --- a/src/overlays/shared/mobys/update_moby_proximity_interaction.c +++ b/src/overlays/shared/mobys/update_moby_proximity_interaction.c @@ -83,7 +83,7 @@ void update_moby_proximity_interaction(unsigned char *moby) { if (*(short *)(proximity_state_data + 0xC) != 0) { int help_message_accepted = try_set_help_message(2, 0x53E4) != 0; if ((pad_pressed_words[0] & 0x10) && help_message_accepted) { - if (current_level_index == 10 && hero.vehicle_mode == 1) { + if (current_level_index == 10 && hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { MOBY(moby)->state = 0x2A; MOBY(moby)->flags |= 0x41; start_scene(9); From 67691731e929a00c964e5059e1f82c8fc31bbd7f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:38:26 +0000 Subject: [PATCH 0810/1502] decomp: clarify names in resolve_hero_position_with_collision_queries domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Retail 0x002339c4 loads hero+0x20b3 (hero.gravity_mode); 0x002339c8 tests it against zero, and the zero path with unk1F8 clear stores capsule_bottom directly in the query vector Z at 0x00233a28-0x00233a2c. The same hero.gravity_mode selector is switched in supplied update_hero_ground_contact_and_gravity: HERO_GRAVITY_WORLD_DOWN sets gravity_dir Z to -1. This proves the HeroGravityMode domain and canonical zero member, rather than matching an unrelated zero-valued enum. domain_1_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: Retail 0x002339c4 loads hero.gravity_mode at hero+0x20b3; 0x002339cc/0x002339d8 load 1 and 0x002339dc compares that same byte with 1 before selecting the rotated offset helper at 0x00233a00. Supplied gravity helpers switch this exact hero.gravity_mode field using HeroGravityMode, and supplied update_hero_ground_contact_and_gravity maps HERO_GRAVITY_OPPOSITE_GROUND_NORMAL to negated ground_normal. The canonical member has value 1 in include/rnc/hero/hero_state.h. domain_2_value_0 -> HERO_GRAVITY_WORLD_DOWN: Retail loop 0x00233b5c reloads the identical hero+0x20b3 gravity_mode byte; 0x00233b60 branches on zero to the ordinary query path, while nonzero uses the frame_scale*0.4 sphere query at 0x00233b68-0x00233b84. The authoritative source and supplied gravity_dir switch use this exact field as HeroGravityMode, whose HERO_GRAVITY_WORLD_DOWN member sets gravity_dir=(0,0,-1) and has value 0. Reuse the same canonical member as the earlier comparison. --- src/overlays/shared/hero/hero_frame_update.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index a7dc5ad76e..c28b0df05d 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -1353,8 +1353,8 @@ s32 resolve_hero_position_with_collision_queries(s32 mode) { hero.path_constrain_pending = 0; } if (hero.state.control_mode != 0x11) { - if (hero.gravity_mode != 0 || hero.unk1F8 != 0) { - if (hero.gravity_mode == 1 || hero.unk1F8 != 0) { + if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN || hero.unk1F8 != 0) { + if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0) { FUN_L00_00233810(&collision_query_offset, &collision_query_offset, 0.6f); } else { FUN_L00_002334d0( @@ -1370,7 +1370,7 @@ s32 resolve_hero_position_with_collision_queries(s32 mode) { mask = 0xD24; } for (i = 0; i < 8; i++) { - if (hero.gravity_mode != 0) { + if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN) { if (!coll_sphere(&hero.motion.pos.q, mask, ((s32)hero.moby), frame_scale * 0.4f)) break; } else if (hero.state.control_mode == 0x11) { From 8dcbfe9349acd414887246c7d8c667471c17d7b7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:38:26 +0000 Subject: [PATCH 0811/1502] decomp: clarify names in draw_group_scenery_ship_trails domain_0_value_1 -> SCENERY_SHIP_FOLLOW_PATH: Retail 002d7b78..002d7b90 first checks member class +0xa6 == 0x4f, then loads the same member's Moby state byte +0x20 and compares it to 1. Original Ghidra has the identical nested type/state filter. Authoritative scenery_ship_update switches on MOBY(moby)->state with SCENERY_SHIP_FOLLOW_PATH = 1: that branch calls advance_scenery_ship_along_path, records three histories at pvars+0x20/+0x120/+0x220, and queues draw_group_scenery_ship_trails. This callback consumes precisely those histories and their +0x320/+0x322 count/head (002d7bd0..002d7c50), proving the same scenery-ship Moby state domain rather than a control mode or Boolean TRUE. --- src/overlays/l05/mobys/scenery_ship.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l05/mobys/scenery_ship.c b/src/overlays/l05/mobys/scenery_ship.c index dfba8f5234..e3405c14a5 100644 --- a/src/overlays/l05/mobys/scenery_ship.c +++ b/src/overlays/l05/mobys/scenery_ship.c @@ -412,6 +412,9 @@ typedef struct Moby Moby; /* Builds 16 fading glow quads, then draws three ribbons of quads for each linked moby of class 0x4F in view. */ void draw_group_scenery_ship_trails(struct Moby *moby) { + enum { + SCENERY_SHIP_FOLLOW_PATH = 1 + }; L05GlowPacket packet[16]; float matrix[8]; float center[4]; @@ -458,7 +461,7 @@ void draw_group_scenery_ship_trails(struct Moby *moby) { list = D_L05_001ABCC0_7920[(unsigned char)((char)moby->group)]; do { member = (struct Moby *)(((*list & 0x7fff) << 8) + (int)D_L05_0015FFD8); - if (member->oclass == 0x4f && member->state == 1) { + if (member->oclass == 0x4f && member->state == SCENERY_SHIP_FOLLOW_PATH) { scenery_ship_vars = (char *)member->pvars; qcopy_nc(center, &member->pos); center[3] = 20.0f; From 9d6dee48d361732bada36d1e058b87e8d2332230 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:38:26 +0000 Subject: [PATCH 0812/1502] decomp: clarify names in resolve_hero_position_collisions domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: The bound source selector is hero.gravity_mode, retail lbu v1,0x20b3(s0) at 0x0022a254 and bne against zero at 0x0022a258. With this byte zero and unk1F8 zero, 0x0022a2b8-0x0022a2bc directly sets the query offset Z to capsule_bottom. The supplied FUN_L00_002334d0 and FUN_L00_00233810 context switches on this same hero.gravity_mode field and names direct world-Z adjustment HERO_GRAVITY_WORLD_DOWN. Thus this comparison belongs to the supplied HeroGravityMode enum, whose canonical zero member is HERO_GRAVITY_WORLD_DOWN. domain_1_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: Retail 0x0022a254 loads hero.gravity_mode from byte +0x20b3; 0x0022a25c/0x0022a268 load 1 and 0x0022a26c tests that same byte against it. The selected branch calls FUN_L00_00233810 at 0x0022a290 with the query offset and 0.6f. Supplied helper source uses the identical hero.gravity_mode selector with canonical HeroGravityMode members, including HERO_GRAVITY_OPPOSITE_GROUND_NORMAL=1; supplied FUN_L00_002334d0 specifically maps that member to offset along negative ground normal. This is the gravity selector domain rather than vehicle or hero state IDs. domain_2_value_0 -> HERO_GRAVITY_WORLD_DOWN: Retail 0x0022a3e0 reloads the same hero byte +0x20b3 as the earlier gravity selection, and 0x0022a3e4 branches on zero to the ordinary collision-query path at 0x0022a2e8. Nonzero uses coll_sphere at 0x0022a404. The bound source identifies this as hero.gravity_mode, the exact selector shared with supplied gravity helper switches using HeroGravityMode. Reuse its canonical zero member HERO_GRAVITY_WORLD_DOWN, consistent with the direct world-Z offset path at 0x0022a2b8-0x0022a2bc. --- .../hero/update_hero_vehicle_attachments_and_effects.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c b/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c index 3f53b1b064..b1696ccde2 100644 --- a/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c +++ b/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c @@ -578,8 +578,8 @@ s32 resolve_hero_position_collisions(s32 mode) { hero.path_constrain_pending = 0; } if (hero.state.control_mode != 0x11) { - if (hero.gravity_mode != 0 || hero.unk1F8 != 0) { - if (hero.gravity_mode == 1 || hero.unk1F8 != 0) { + if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN || hero.unk1F8 != 0) { + if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0) { FUN_L00_00233810(&collision_query_offset, &collision_query_offset, 0.6f); } else { FUN_L00_002334d0( @@ -594,7 +594,7 @@ s32 resolve_hero_position_collisions(s32 mode) { if (hero.state.current == HERO_STATE_SINK) mask = 0xD24; for (i = 0; i < 8; i++) { - if (hero.gravity_mode != 0) { + if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN) { if (!coll_sphere(&hero.motion.pos.q, mask, hero.moby, frame_scale * 0.4f)) break; } else if (hero.state.control_mode == 0xF) { From 6c3166898947c40d096065c6e098b334b65fdd3c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:38:27 +0000 Subject: [PATCH 0813/1502] decomp: clarify names in update_level11_distance_faded_effect_and_queue_draw domain_0_value_1 -> EFFECT_UPDATE_AND_QUEUE_DRAW: Retail 0x0031f15c preserves the Moby argument in s2; 0x0031f174 loads its state byte at +0x20, and 0x0031f17c/0x0031f180 compare that exact byte to 1 and dispatch to 0x0031f330. Initialization writes 1 to the same byte with li v0,1 at 0x0031f250 and sb v0,0x20(s2) at 0x0031f258. Original Ghidra confirms the write and cVar1==1 branch. The authoritative C already names this selector's case 1 EFFECT_UPDATE_AND_QUEUE_DRAW: its branch gates visibility, updates scrolling/fade, and queues callback 0x0031e930 at 0x0031f4dc-0x0031f4e8. Thus the assignment transitions directly to that existing local state member, with no Hero/control domain equivalence inferred. --- src/overlays/l11/mobys/distance_faded_scroll_effect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/distance_faded_scroll_effect.c b/src/overlays/l11/mobys/distance_faded_scroll_effect.c index de44710622..4986f4dc81 100644 --- a/src/overlays/l11/mobys/distance_faded_scroll_effect.c +++ b/src/overlays/l11/mobys/distance_faded_scroll_effect.c @@ -6044,7 +6044,7 @@ void distance_faded_effect_update(struct Moby *moby) { 1); distance_faded_effect_color_tables_initialized_gp = 1; } - moby->state = 1; + moby->state = EFFECT_UPDATE_AND_QUEUE_DRAW; for (i = 0; i < 3; i++) { l11_distance_faded_effect_uv_offsets[i].a = 0; l11_distance_faded_effect_uv_offsets[i].b = 0; From b9fcbe72631bd7ff3992c87d253ed220a01aa36d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:38:27 +0000 Subject: [PATCH 0814/1502] decomp: clarify names in update_data_processor_linked_effect domain_0_value_1 -> MOBY_STATE_ACTIVE_WITH_SOUND: The authoritative source switches on moby->state and already declares MOBY_STATE_ACTIVE_WITH_SOUND = 1 for its case 1. Retail 0x002da44c loads 1 into v1 and 0x002da454 stores it to moby+0x20 (s3); 0x002da31c/0x002da324 reads that same byte and dispatches value 1 to 0x002da498. That branch queues the rendering callback and checks/reallocates the owned voice at 0x002da548-0x002da570. Original Ghidra likewise assigns *(undefined1 *)(param_1 + 0x20) = 1 and tests that byte for the rendering/voice branch. This is the exact same local moby-state domain, so the assignment should reuse its existing canonical member. --- src/overlays/l10/mobys/data_processor_linked_effect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l10/mobys/data_processor_linked_effect.c b/src/overlays/l10/mobys/data_processor_linked_effect.c index 0864890a6c..61ffba0128 100644 --- a/src/overlays/l10/mobys/data_processor_linked_effect.c +++ b/src/overlays/l10/mobys/data_processor_linked_effect.c @@ -100,7 +100,7 @@ void data_processor_linked_effect_update(struct Moby *moby) { float timer; float new_rotation = fast_add_rotations(moby->rot.z, 1.5707964f); moby->update_dist = 0x60; - moby->state = 1; + moby->state = MOBY_STATE_ACTIVE_WITH_SOUND; timer = data_processor_linked_effect_fade_duration_seconds_gp * 60.0f; moby->rot.z = new_rotation; linked_effect_vars->voice = -1; From cc243323978f77d4d0f00abd14c7011ebc096e64 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:38:27 +0000 Subject: [PATCH 0815/1502] decomp: clarify names in process_menu_entry domain_0_value_6 -> MENU_CONDITION_BOLT_THRESHOLD_AND_COUNT_DIFFERENCE_MET: Authoritative src/ui/menus/system/process_menu_entry.c SHA-256 53f0be690b4073d0ca4dd8bcf82f8900c3ac0ee6c95688d10e07a00224155d08 assigns kind directly from current_menu_entry->unk8, which is also the later switch selector with canonical member MENU_CONDITION_BOLT_THRESHOLD_AND_COUNT_DIFFERENCE_MET = 6. Retail 0x00216d3c loads signed entry+8 into s0 and 0x00216d30/0x00216d40 compares it against 6 for threshold help formatting. Retail 0x00216e84-0x00216e98 reloads the same field and subtracts one for dispatch; original Ghidra case 5 and retail 0x00216f6c-0x00216fa8 require current_bolt_count >= indexed u16 record+0x14 and count helper result >= 4. Thus the formatting comparison belongs to the exact existing menu-condition domain, rather than merely sharing the number 6. --- src/ui/menus/system/process_menu_entry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/menus/system/process_menu_entry.c b/src/ui/menus/system/process_menu_entry.c index 89fea862f6..3a7006eb18 100644 --- a/src/ui/menus/system/process_menu_entry.c +++ b/src/ui/menus/system/process_menu_entry.c @@ -115,7 +115,7 @@ void process_menu_entry(void *callback_context, Menu *menu, s32 follow_entry_lin } menu_entry_context[5] = current_menu_entry->unk0; kind = current_menu_entry->unk8; - if (kind == 6) { + if (kind == MENU_CONDITION_BOLT_THRESHOLD_AND_COUNT_DIFFERENCE_MET) { sfx = menu_bolt_threshold_thousands_separators; strcpy(SCRATCH, get_help_message_text(current_menu_entry->unk0)); substring_match = FindSubstring(SCRATCH, help_text_integer_placeholder); From 6bedb24004c43740ed31695dc6cb95e5c68fe446 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:38:27 +0000 Subject: [PATCH 0816/1502] decomp: clarify names in process_hoven_anklebiter_damage_and_alerts domain_0_value_9 -> ANKLEBITER_DORMANT: The authoritative snapshot src/overlays/l12/mobys/hoven_anklebiter.c (SHA-256 5769003a947dad24aca9bb0a3cbc73567cdac3585257a6dffa43ba45d4f09678) shows update_hoven_anklebiter calling this handler with the same moby before switching on moby->state, and defines the matching ANKLEBITER enum member. Retail uses s2, saved from a0 at 0x002e3534, and its state byte at +0x20; this is the anklebiter domain, not HeroStateId. Retail 0x002e356c..0x002e3574 compares that byte with 9 to bypass alert-speed processing. The caller's DORMANT case (9) waits for activation and its initialization enters 9 for sleeping anklebiters. domain_1_value_11 -> ANKLEBITER_WAIT_FOR_LEAP_TRIGGER: The authoritative snapshot src/overlays/l12/mobys/hoven_anklebiter.c (SHA-256 5769003a947dad24aca9bb0a3cbc73567cdac3585257a6dffa43ba45d4f09678) shows update_hoven_anklebiter calling this handler with the same moby before switching on moby->state, and defines the matching ANKLEBITER enum member. Retail uses s2, saved from a0 at 0x002e3534, and its state byte at +0x20; this is the anklebiter domain, not HeroStateId. Retail 0x002e3578..0x002e3580 compares the same byte with 11 to bypass alert-speed processing. The caller's WAIT_FOR_LEAP_TRIGGER case (11) faces home and waits for target proximity or trigger 2 before launching to home. domain_2_value_0 -> ANKLEBITER_INITIALIZE: The authoritative snapshot src/overlays/l12/mobys/hoven_anklebiter.c (SHA-256 5769003a947dad24aca9bb0a3cbc73567cdac3585257a6dffa43ba45d4f09678) shows update_hoven_anklebiter calling this handler with the same moby before switching on moby->state, and defines the matching ANKLEBITER enum member. Retail uses s2, saved from a0 at 0x002e3534, and its state byte at +0x20; this is the anklebiter domain, not HeroStateId. Retail 0x002e3584..0x002e3588 checks the same state byte against zero before timer/speed processing. The caller's INITIALIZE case (0) initializes health, motion, timers and chooses dormant, leap-wait or idle state. domain_3_value_9 -> ANKLEBITER_DORMANT: The authoritative snapshot src/overlays/l12/mobys/hoven_anklebiter.c (SHA-256 5769003a947dad24aca9bb0a3cbc73567cdac3585257a6dffa43ba45d4f09678) shows update_hoven_anklebiter calling this handler with the same moby before switching on moby->state, and defines the matching ANKLEBITER enum member. Retail uses s2, saved from a0 at 0x002e3534, and its state byte at +0x20; this is the anklebiter domain, not HeroStateId. Retail 0x002e35bc..0x002e35c4 excludes the same state byte equal to 9 from help-call timer processing. The caller's DORMANT case (9) waits for activation; it is the same domain and member as the earlier dormant comparison. domain_4_value_99 -> ANKLEBITER_DEATH_FALL: The authoritative snapshot src/overlays/l12/mobys/hoven_anklebiter.c (SHA-256 5769003a947dad24aca9bb0a3cbc73567cdac3585257a6dffa43ba45d4f09678) shows update_hoven_anklebiter calling this handler with the same moby before switching on moby->state, and defines the matching ANKLEBITER enum member. Retail uses s2, saved from a0 at 0x002e3534, and its state byte at +0x20; this is the anklebiter domain, not HeroStateId. Retail 0x002e36e8..0x002e36f0 excludes state 99 from new damage processing; 0x002e382c writes that same byte on lethal health. The caller's DEATH_FALL case (99) steps falling motion, then enters death effects/removal. domain_5_value_8 -> ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME: The authoritative snapshot src/overlays/l12/mobys/hoven_anklebiter.c (SHA-256 5769003a947dad24aca9bb0a3cbc73567cdac3585257a6dffa43ba45d4f09678) shows update_hoven_anklebiter calling this handler with the same moby before switching on moby->state, and defines the matching ANKLEBITER enum member. Retail uses s2, saved from a0 at 0x002e3534, and its state byte at +0x20; this is the anklebiter domain, not HeroStateId. Retail 0x002e36f4..0x002e36f8 excludes the state byte equal to 8 from damage handling. The supplied caller's CONTROLLED_MOTION_UNTIL_RETURN_HOME case (8) steps controlled motion and transitions to RETURN_HOME; supplied suck-cannon callbacks set the same moby state member. domain_6_value_99 -> ANKLEBITER_DEATH_FALL: The authoritative snapshot src/overlays/l12/mobys/hoven_anklebiter.c (SHA-256 5769003a947dad24aca9bb0a3cbc73567cdac3585257a6dffa43ba45d4f09678) shows update_hoven_anklebiter calling this handler with the same moby before switching on moby->state, and defines the matching ANKLEBITER enum member. Retail uses s2, saved from a0 at 0x002e3534, and its state byte at +0x20; this is the anklebiter domain, not HeroStateId. Retail 0x002e376c/0x002e3794 selects the lethal branch when health after damage is <=0. It starts fall animation 6 at 0x002e37f8..0x002e3804 and writes 99 to moby+0x20 at 0x002e382c. The caller dispatches 99 as DEATH_FALL and steps motion until death effects/removal. domain_7_value_7 -> ANKLEBITER_KNOCKBACK_FALL: The authoritative snapshot src/overlays/l12/mobys/hoven_anklebiter.c (SHA-256 5769003a947dad24aca9bb0a3cbc73567cdac3585257a6dffa43ba45d4f09678) shows update_hoven_anklebiter calling this handler with the same moby before switching on moby->state, and defines the matching ANKLEBITER enum member. Retail uses s2, saved from a0 at 0x002e3534, and its state byte at +0x20; this is the anklebiter domain, not HeroStateId. Retail surviving-health branch 0x002e3840..0x002e38a0 starts fall animation 14, writes 7 to moby+0x20 at 0x002e3894 and sets the stun timer. The caller dispatches state 7 as KNOCKBACK_FALL, stepping motion before state 10 recovery. --- src/overlays/l12/mobys/hoven_anklebiter.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/overlays/l12/mobys/hoven_anklebiter.c b/src/overlays/l12/mobys/hoven_anklebiter.c index 4af367ec8f..03335900ad 100644 --- a/src/overlays/l12/mobys/hoven_anklebiter.c +++ b/src/overlays/l12/mobys/hoven_anklebiter.c @@ -893,6 +893,14 @@ extern void anim_update_e3528(struct Moby *, void *) __asm__("FUN_L00_0025d538") void process_hoven_anklebiter_damage_and_alerts(struct Moby *moby) __asm__("FUN_L12_002e3528"); void process_hoven_anklebiter_damage_and_alerts(struct Moby *moby) { + enum { + ANKLEBITER_INITIALIZE = 0, + ANKLEBITER_KNOCKBACK_FALL = 7, + ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME = 8, + ANKLEBITER_DORMANT = 9, + ANKLEBITER_WAIT_FOR_LEAP_TRIGGER = 0xB, + ANKLEBITER_DEATH_FALL = 0x63 + }; AnklebiterVars *anklebiter_vars = (AnklebiterVars *)moby->pvars; Vec4 help_direction_or_hit_position; s32 hit; @@ -905,14 +913,14 @@ void process_hoven_anklebiter_damage_and_alerts(struct Moby *moby) { anklebiter_vars->reset_alert = 0; anklebiter_vars->alert_timer = scale_game_frames(0xF0); } - if (moby->state != 9 && moby->state != 0xB && moby->state != 0) { + if (moby->state != ANKLEBITER_DORMANT && moby->state != ANKLEBITER_WAIT_FOR_LEAP_TRIGGER && moby->state != ANKLEBITER_INITIALIZE) { if (fast_dec_timer(&anklebiter_vars->alert_timer)) { anklebiter_vars->speed = 12.0f; } else { anklebiter_vars->speed = 20.0f; } } - if (anklebiter_vars->call_enabled != 0 && moby->state != 9) { + if (anklebiter_vars->call_enabled != 0 && moby->state != ANKLEBITER_DORMANT) { s16 updated_call_timer = ++anklebiter_vars->call_timer; if (scale_game_frames(0x3C) * 15 < updated_call_timer && moby->visible == 0 && moby->group < 0xFF && count_active_moby_group_members(moby->group, -1) >= 4 && @@ -929,7 +937,7 @@ void process_hoven_anklebiter_damage_and_alerts(struct Moby *moby) { coll = find_hit_e3528(moby, 0x330000, 0); dmg = 0.0f; resolve_moby_hit_response(moby, coll, &anklebiter_vars->health, 0, &hit, &dmg, 0, 4); - if (coll != 0 && moby->state != 0x63 && moby->state != 8) { + if (coll != 0 && moby->state != ANKLEBITER_DEATH_FALL && moby->state != ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME) { if (moby->group != 0xFF) { FUN_L01_0026e090(moby->group, 7); } @@ -956,7 +964,7 @@ void process_hoven_anklebiter_damage_and_alerts(struct Moby *moby) { start_fall_e3528(moby, anklebiter_vars->fall, 6, 1, 0, angle); anklebiter_vars->unk170 = 11.0f; anklebiter_vars->unk174 = 18.0f; - moby->state = 0x63; + moby->state = ANKLEBITER_DEATH_FALL; anklebiter_vars->unk117 = 0x78; anim_reset_e3528(moby, anklebiter_vars->anim); } else { @@ -967,7 +975,7 @@ void process_hoven_anklebiter_damage_and_alerts(struct Moby *moby) { &anklebiter_vars->unk13C); start_fall_e3528(moby, anklebiter_vars->fall, 0xE, 1, 0, unused); anklebiter_vars->unk174 = anklebiter_vars->unk170 = -1.0f; - moby->state = 7; + moby->state = ANKLEBITER_KNOCKBACK_FALL; anklebiter_vars->unk117 = 0xFA; anklebiter_vars->stun_timer = scale_game_frames(0x3C); anim_reset_e3528(moby, anklebiter_vars->anim); From 1127d25feafc213203720e52cd9112540afe7f4f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:38:27 +0000 Subject: [PATCH 0817/1502] decomp: clarify names in update_item_preview_binding domain_1_value_3 -> ITEM_PREVIEW_TYPE_WITH_SECONDARY_MOBY: Retail 0x0021e2dc-0x0021e2e8 compares menu_item_info[item_index].item_type (+8 in each 0x4c-byte definition) with 3 and retains that predicate in s8. At 0x0021e51c-0x0021e568 it gates a second create_menu_preview_moby call, copies primary position/rotation, and stores the allocation at preview+0x48 (secondary_moby). This proves a secondary-Moby item-type category, separate from preview->state. domain_3_value_1 -> ITEM_PREVIEW_WAIT_FOR_CLASS: The source INITIALIZE case assigns preview->state=1. Retail reads that same binding field at +0x34 (0x0021e308), branches from state 0 at 0x0021e324 to 0x0021e36c-0x0021e370, and stores a0=1. The existing local enum names this selector's value 1 ITEM_PREVIEW_WAIT_FOR_CLASS, whose handler waits until selected oclass is not -1. domain_4_value_2 -> ITEM_PREVIEW_CREATE_MOBYS: In the existing ITEM_PREVIEW_WAIT_FOR_CLASS case, source assigns preview->state=2 only when oclass!=-1. Retail 0x0021e34c-0x0021e35c checks s3 against -1 then stores 2 at binding+0x34. The dispatch at 0x0021e334 routes this same state value to primary/secondary Moby creation at 0x0021e360 onward; reuse existing ITEM_PREVIEW_CREATE_MOBYS. domain_5_value_1 -> ITEM_PREVIEW_WAIT_FOR_CLASS: The source CREATE_MOBYS branch returns to preview->state=1 if selected oclass==-1. Retail 0x0021e360-0x0021e370 compares s3 with -1 and falls into the shared store of a0=1 to binding+0x34. This is exactly the existing local preview-state value ITEM_PREVIEW_WAIT_FOR_CLASS, not the independent item_type selector. domain_6_value_3 -> ITEM_PREVIEW_MONITOR_CLASS_CHANGE: After primary setup and optional secondary creation, source assigns preview->state=3. Retail 0x0021e5a4-0x0021e5ac stores 3 at binding+0x34, also reached on allocation failure. Dispatch 0x0021e33c sends state 3 to 0x0021e5b0, comparing previous versus selected class and deleting both Mobys on change. Reuse existing ITEM_PREVIEW_MONITOR_CLASS_CHANGE. domain_7_value_2 -> ITEM_PREVIEW_CREATE_MOBYS: The source MONITOR_CLASS_CHANGE case deletes both preview Mobys when previous_class!=oclass, then assigns preview->state=2. Retail 0x0021e5b0-0x0021e5d0 performs the class comparison and both deletion calls, then stores s0=2 at binding+0x34 (set at 0x0021e320). This same selector's value 2 dispatches to creation, matching existing ITEM_PREVIEW_CREATE_MOBYS. --- .../item_preview/update_item_preview_binding.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/ui/menus/item_preview/update_item_preview_binding.c b/src/ui/menus/item_preview/update_item_preview_binding.c index e45470d953..399a86ddbe 100644 --- a/src/ui/menus/item_preview/update_item_preview_binding.c +++ b/src/ui/menus/item_preview/update_item_preview_binding.c @@ -70,6 +70,9 @@ s32 update_item_preview_binding(struct ItemPreviewBinding *preview) { ITEM_PREVIEW_CREATE_MOBYS = 2, ITEM_PREVIEW_MONITOR_CLASS_CHANGE = 3 }; + enum { + ITEM_PREVIEW_TYPE_WITH_SECONDARY_MOBY = 3 + }; struct MenuScreen *grid; struct Moby *moby; struct Moby *secondary_moby; @@ -107,7 +110,7 @@ s32 update_item_preview_binding(struct ItemPreviewBinding *preview) { preview->rotation_angle = fast_add_rotations(preview->rotation_angle, 0.01f); item_type = menu_item_info[item_index].item_type; is_type2 = item_type == 2; - has_secondary_moby = item_type == 3; + has_secondary_moby = item_type == ITEM_PREVIEW_TYPE_WITH_SECONDARY_MOBY; is_type1 = item_type == 1; if (!is_type2 && !has_secondary_moby && !is_type1) { load_class = 1; @@ -118,16 +121,16 @@ s32 update_item_preview_binding(struct ItemPreviewBinding *preview) { use_alternate_x = preview->flags & 1; switch (preview->state) { case ITEM_PREVIEW_INITIALIZE: - preview->state = 1; + preview->state = ITEM_PREVIEW_WAIT_FOR_CLASS; break; case ITEM_PREVIEW_WAIT_FOR_CLASS: if (oclass != -1) { - preview->state = 2; + preview->state = ITEM_PREVIEW_CREATE_MOBYS; } break; case ITEM_PREVIEW_CREATE_MOBYS: if (oclass == -1) { - preview->state = 1; + preview->state = ITEM_PREVIEW_WAIT_FOR_CLASS; break; } if (load_class) { @@ -198,13 +201,13 @@ s32 update_item_preview_binding(struct ItemPreviewBinding *preview) { 0); } } - preview->state = 3; + preview->state = ITEM_PREVIEW_MONITOR_CLASS_CHANGE; break; case ITEM_PREVIEW_MONITOR_CLASS_CHANGE: if (previous_class != oclass) { preview->primary_moby = delete_moby(preview->primary_moby); preview->secondary_moby = delete_moby(preview->secondary_moby); - preview->state = 2; + preview->state = ITEM_PREVIEW_CREATE_MOBYS; } break; } From db648fe816906a4261372f4a52ddc2dfdd1b1d60 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:40:16 +0000 Subject: [PATCH 0818/1502] decomp: clarify names in ocean_pokitaru_update domain_0_value_0 -> OCEAN_POKITARU_STATE_UNINITIALIZED: Source ocean_pokitaru_update tests OceanMoby.state at +0x20. Retail 0x0030b388-0x0030b38c loads that byte and branches away when nonzero; the zero path at 0x0030b394-0x0030b3f0 sets state to 1, clears both wave UV pairs at 0x00161e08/0x00161e0c, copies the initial camera vector and saves ocean_vars->level before returning. Original Ghidra shows the same zero-only initialization branch, proving this ocean-specific uninitialized state. domain_1_value_1 -> OCEAN_POKITARU_STATE_INITIALIZED: Retail 0x0030b394 loads 1 into v1 and 0x0030b3a4 stores it to the same OceanMoby +0x20 byte tested at 0x0030b388. This store accompanies initialization of the two wave offsets, saved camera position and ocean level at 0x0030b3b8-0x0030b3f0. On following updates the nonzero branch enters camera displacement and gated wave/tide updates at 0x0030b3f4 onward. Source and original Ghidra agree, proving 1 is the ocean's initialized state without implying it is always drawn. --- src/overlays/shared/props/ocean_pokitaru.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/props/ocean_pokitaru.c b/src/overlays/shared/props/ocean_pokitaru.c index b0dff5824f..b9fff0e354 100644 --- a/src/overlays/shared/props/ocean_pokitaru.c +++ b/src/overlays/shared/props/ocean_pokitaru.c @@ -321,13 +321,17 @@ void ocean_pokitaru_update(OceanMoby *moby) __asm__("FUN_L11_0030b358"); /* Moby class 1111 */ void ocean_pokitaru_update(OceanMoby *moby) { + enum { + OCEAN_POKITARU_STATE_UNINITIALIZED = 0, + OCEAN_POKITARU_STATE_INITIALIZED = 1 + }; OceanVars *ocean_vars = moby->vars; float camera_displacement[4]; float camera_wave_uv_delta[4]; int k; - if (moby->state == 0) { - moby->state = 1; + if (moby->state == OCEAN_POKITARU_STATE_UNINITIALIZED) { + moby->state = OCEAN_POKITARU_STATE_INITIALIZED; moby->f30 = 0xFF; for (k = 0; k < 2; k++) { wave_offset[k].u = 0.0f; From 0fe2765274360f34f503bfd311dda4f3c125edbb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:40:17 +0000 Subject: [PATCH 0819/1502] decomp: clarify names in draw_hud_counter domain_0_value_0 -> FALSE: Authoritative hud_counter.c (SHA-256 f32e9a0a4c044d58fd0e613cb365ab5d9c023ad6140db93596510b39cde6ed38) tests pal_mode != 0 to choose bottom-0x2A instead of bottom-0x32. Retail 0x0023ce1c/0x0023ce20 loads the selector at 0x0015ed80 into a1; 0x0023ce2c and 0x0023ce30 compute those two offsets, and movn v0,v1,a1 at 0x0023ce34 selects the first only when a1 is nonzero. Original Ghidra likewise tests iRam0015ed80 != 0. Thus the listed zero is the false operand of a boolean mode test, fitting established FALSE=0 rather than the pointer constant NULL or an unproven video-mode enum. --- src/overlays/l02/hud_counter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l02/hud_counter.c b/src/overlays/l02/hud_counter.c index ce05a6b50e..6ce389193f 100644 --- a/src/overlays/l02/hud_counter.c +++ b/src/overlays/l02/hud_counter.c @@ -88,7 +88,7 @@ s32 draw_hud_counter(HudElem *hud_element) { x = D_L02_0015F948; } bottom = frame_size[0]; - y = pal_mode != 0 ? bottom - 0x2A : bottom - 0x32; + y = pal_mode != FALSE ? bottom - 0x2A : bottom - 0x32; grow = convert_integer_to_float(fade[0]) / convert_integer_to_float(hud_counter_bar_growth_divisor_gp); if (1.0f < grow) { From e7f40e06f98304b6ad9847f0ad247dac3ff52d17 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:40:17 +0000 Subject: [PATCH 0820/1502] decomp: clarify names in update_gadgebot_damage_target_and_glow domain_0_value_0 -> GADGEBOT_INITIALIZE: Retail 0x002fc128-0x002fc12c reads moby+0x20 and returns for zero. gadgebot_update passes this same moby to the helper before switching on moby[0x20], where its existing GADGEBOT_INITIALIZE=0 branch initializes pvars, animation and collision flags. domain_10_value_6 -> GADGEBOT_EXPLODE: Retail 0x002fc2d8 loads state 6 into s2 and 0x002fc310-0x002fc324 assigns it to moby+0x20 on one lethal-hit random outcome. The caller dispatches this exact byte to its existing GADGEBOT_EXPLODE=6 branch, which spawns the explosion and disables collision. domain_11_value_5 -> GADGEBOT_DEATH_FALL: Retail 0x002fc328-0x002fc3fc initializes fall parameters, derives knockback from the hit vector, starts motion at pvars+0x70 and assigns moby+0x20 state 5. The caller's existing GADGEBOT_DEATH_FALL=5 branch processes that same fall block with step_moby_motion before explosion. domain_12_value_2 -> GADGEBOT_TARGET_HERO: Retail 0x002fc460-0x002fc498 compares pvars+0x1c4 with 2, then overwrites target pvars+0x180 with hero.motion.pos or, when hero control_mode is 0xF, the indexed hero.rail_spline position. Thus this is a separate hero-derived targeting mode, not a moby state or HeroStateId. domain_1_value_8 -> GADGEBOT_IDLE: Retail 0x002fc134-0x002fc138 returns for moby state 8. The authoritative launch_first_idle_group_class_0772_moby tests this same struct Moby state against its existing GADGEBOT_IDLE=8, restores collision and visibility flags and assigns launch-flight state; hide_moby_and_clear_collision assigns GADGEBOT_IDLE. domain_2_value_7 -> GADGEBOT_SUCK_CANNON_SUCTION: Retail 0x002fc13c-0x002fc160 excludes moby+0x20 value 7 from queuing joint glows. This is the caller gadgebot_update's exact state byte, whose established GADGEBOT_SUCK_CANNON_SUCTION=7 branch invokes the suction helper; update_moby_suck_cannon_state assigns that member while suction is active. domain_3_value_4 -> GADGEBOT_FACE_TARGET: Retail 0x002fc164-0x002fc178 selects the alternate glow speed for state bytes 4 and 5. The same moby is supplied by gadgebot_update before its state switch; its established GADGEBOT_FACE_TARGET=4 branch turns toward pvars+0x180 and performs the facing animation logic. domain_4_value_5 -> GADGEBOT_DEATH_FALL: Retail 0x002fc164-0x002fc178 selects alternate glow speed for moby states 4/5. The same state byte is dispatched by gadgebot_update under existing GADGEBOT_DEATH_FALL=5, where step_moby_motion processes pvars+0x70 before the explosion branch. domain_5_value_7 -> GADGEBOT_SUCK_CANNON_SUCTION: Retail 0x002fc1e8-0x002fc1f8 exempts state 7 from the low-Z explosion assignment. The selector is the same moby+0x20 byte used by gadgebot_update's GADGEBOT_SUCK_CANNON_SUCTION=7 branch and by update_moby_suck_cannon_state while the suction helper reports active suction. domain_6_value_6 -> GADGEBOT_EXPLODE: Retail 0x002fc1f4-0x002fc1f8 assigns 6 to moby+0x20 below Z=100 unless suction is active. gadgebot_update calls this helper before dispatching that exact byte, and its existing GADGEBOT_EXPLODE=6 branch spawns the explosion and clears collision before setting idle state. domain_7_value_7 -> GADGEBOT_SUCK_CANNON_SUCTION: Retail 0x002fc238-0x002fc244 compares moby+0x20 with 7 before event-driven disabling. The same byte is the caller's established GADGEBOT_SUCK_CANNON_SUCTION=7 state; update_moby_suck_cannon_state writes it when process_moby_suck_cannon_suction returns nonzero. domain_8_value_8 -> GADGEBOT_IDLE: Retail 0x002fc244-0x002fc284 assigns state 8, blends animation to zero, clears collision and sets flags 0x41 while clearing 0x1000. This matches hide_moby_and_clear_collision's existing GADGEBOT_IDLE=8 assignment and the idle test reversed by launch_first_idle_group_class_0772_moby. domain_9_value_6 -> GADGEBOT_EXPLODE: Retail 0x002fc2d8-0x002fc2e0 excludes moby+0x20 state 6 from applying further hit damage. gadgebot_update receives this same moby and dispatches that byte under its established GADGEBOT_EXPLODE=6 branch, spawning the explosion and returning the moby to idle. --- src/overlays/l18/mobys/gadgebot.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/overlays/l18/mobys/gadgebot.c b/src/overlays/l18/mobys/gadgebot.c index df5cf766eb..a1e952837e 100644 --- a/src/overlays/l18/mobys/gadgebot.c +++ b/src/overlays/l18/mobys/gadgebot.c @@ -299,6 +299,15 @@ extern float gadgebot_glow_state_4_or_5_phase_speed_degrees_per_second_gp __asm_ /* Sentry update: spins and tints the moby, takes hits (knockback, then a fall), and follows its path toward the hero. */ void update_gadgebot_damage_target_and_glow(struct Moby *moby) { + enum { + GADGEBOT_INITIALIZE = 0, + GADGEBOT_TARGET_HERO = 2, + GADGEBOT_FACE_TARGET = 4, + GADGEBOT_DEATH_FALL = 5, + GADGEBOT_EXPLODE = 6, + GADGEBOT_SUCK_CANNON_SUCTION = 7, + GADGEBOT_IDLE = 8 + }; SentryVars_c100 *sentry_vars = (SentryVars_c100 *)moby->pvars; union { u128 q; @@ -312,28 +321,28 @@ void update_gadgebot_damage_target_and_glow(struct Moby *moby) { int reaction_value_or_path_address; /* the reaction kind, later the path */ int fall_setup_value_or_path_slot_address; /* the reaction flags, later the path's slot in the table */ - if (moby->state == 0 || moby->state == 8) { + if (moby->state == GADGEBOT_INITIALIZE || moby->state == GADGEBOT_IDLE) { return; } - if (moby->state != 7 && game_frame != gadgebot_joint_glows_last_queued_frame_gp) { + if (moby->state != GADGEBOT_SUCK_CANNON_SUCTION && game_frame != gadgebot_joint_glows_last_queued_frame_gp) { gadgebot_joint_glows_last_queued_frame_gp = game_frame; add_draw_callback(draw_group_gadgebot_joint_glows, moby); } speed = gadgebot_glow_default_phase_speed_degrees_per_second_gp; - if (moby->state == 4 || moby->state == 5) { + if (moby->state == GADGEBOT_FACE_TARGET || moby->state == GADGEBOT_DEATH_FALL) { speed = gadgebot_glow_state_4_or_5_phase_speed_degrees_per_second_gp; } sentry_vars->spin = fast_add_rotations(sentry_vars->spin, speed * DEG_TO_RAD * frame_time); moby->glow_color = fast_tween_color(gadgebot_glow_tint_start_gp, gadgebot_glow_tint_end_gp, fast_sin(sentry_vars->spin) * 0.5f + 0.5f); - if (moby->pos.z < 100.0f && moby->state != 7) { - moby->state = 6; + if (moby->pos.z < 100.0f && moby->state != GADGEBOT_SUCK_CANNON_SUCTION) { + moby->state = GADGEBOT_EXPLODE; } moby->scale = moby->pclass->scale * D_L18_001625FC; if (hero.state.current == 0x72 || D_L18_0015F5C4 == 2) { - if (moby->state != 7) { - moby->state = 8; + if (moby->state != GADGEBOT_SUCK_CANNON_SUCTION) { + moby->state = GADGEBOT_IDLE; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } @@ -345,11 +354,11 @@ void update_gadgebot_damage_target_and_glow(struct Moby *moby) { dmg = 0.0f; coll = find_moby_hit(moby, 0x330000, 0); resolve_moby_hit_response(moby, coll, &sentry_vars->health, 0, &hit, &dmg, 0, 4); - if (hit != 1 && moby->state != 6 && dmg != 0.0f) { + if (hit != 1 && moby->state != GADGEBOT_EXPLODE && dmg != 0.0f) { sentry_vars->health -= dmg; if (sentry_vars->health <= 0.0f) { if (random_integer_below(2) != 0) { - moby->state = 6; + moby->state = GADGEBOT_EXPLODE; } else { fall_setup_value_or_path_slot_address = 0x200; sentry_vars->unk90 = fall_setup_value_or_path_slot_address; @@ -369,7 +378,7 @@ void update_gadgebot_damage_target_and_glow(struct Moby *moby) { trooper_start_knockback(moby, sentry_vars->fall, 3, 1, 0, angle); sentry_vars->unkC0 = 7.5f; sentry_vars->unkC4 = 15.0f; - moby->state = 5; + moby->state = GADGEBOT_DEATH_FALL; moby->collision = 0; sentry_vars->anim_flags = 0x78; trooper_anim_update(moby, sentry_vars->anim); @@ -387,7 +396,7 @@ void update_gadgebot_damage_target_and_glow(struct Moby *moby) { 0, (int *)(reaction_value_or_path_address + 0x10), *(int *)reaction_value_or_path_address); - if (sentry_vars->target_mode == 2) { + if (sentry_vars->target_mode == GADGEBOT_TARGET_HERO) { if (hero.state.control_mode == 0xF) { int *list = (int *)hero.rail_spline; qcopy(&sentry_vars->target, (char *)list + *list * 16); From 0af5477b1a56ca001d777c19849a68bf1cf8e19d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:40:17 +0000 Subject: [PATCH 0821/1502] decomp: clarify names in clip_hero_velocity_against_probed_surfaces domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Authoritative source src/overlays/shared/hero/hero_switch_item.c SHA-256 33ca27f13f09c9c551c24600d2af02dc683aafab88a4c7cd7d8551a198326bd2 compares hero.vehicle_mode, not state.current or control_mode. Retail 0x002123c8 loads the byte at hero+0x20a4 (0x001413f4 in original Ghidra), then 0x002123cc-0x002123d0 compares it with 1; the selected branch sets probe height 0.35 and reach 0.27 at 0x002123d8-0x002123ec. In the same supplied source, enter_hero_vehicle_mode assigns mode to hero_state->vehicle_mode and switches mode using HERO_VEHICLE_MODE_CLANK; exit_hero_vehicle_mode and update_hero_collision_capsule_dimensions consume that same field with the canonical member. Thus this exact selector belongs to shared HeroVehicleMode in include/rnc/hero/hero_state.h, whose established CLANK member is 1. domain_1_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: The supplied source comparison hero.vehicle_mode == 2 maps to retail 0x002123c8 lbu v1,0x20a4(s0), 0x002123d4 li v0,2, and 0x002123f8 bne v1,v0. Original Ghidra likewise tests cRam001413f4 against 2. This branch selects height 1.5 and reach 5.0 at 0x00212400-0x0021240c. The authoritative source's enter_hero_vehicle_mode stores mode to this exact vehicle_mode field and switches mode using HERO_VEHICLE_MODE_GIANT_CLANK (initializing vehicle_hp to 200); update_hero_collision_capsule_dimensions switches the identical field using that member for giant dimensions. The shared HeroVehicleMode declaration in include/rnc/hero/hero_state.h establishes HERO_VEHICLE_MODE_GIANT_CLANK=2. This is the vehicle domain, independently of the distinct control-mode word loaded at 0x00212388. --- src/overlays/shared/hero/hero_switch_item.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index e45ad3f8bb..4a0f3210ef 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -3215,10 +3215,10 @@ void clip_hero_velocity_against_probed_surfaces(int force) { if ((u32)(hero.state.control_mode - 0x11) < 2) { primary_probe_height_offset = 0.0f; k = 0.7f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { primary_probe_height_offset = 0.35f; k = 0.27000001072883606f; - } else if (hero.vehicle_mode == 2) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { primary_probe_height_offset = 1.5f; k = 5.0f; } From b25717c550371380f07f3b429706b15b5545cbe9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:42:03 +0000 Subject: [PATCH 0822/1502] decomp: clarify names in process_hero_ground_material_effects domain_0_value_2 -> GROUND_MATERIAL_MAGNETIC: Retail 0x0021b6cc loads the saved signed ground material from Hero+0x12E0 into s2. The comparison with 2 at 0x0021b6ec-0x0021b6f0 selects the grounded/distance test and store of 1 to Hero+0x12E7 at 0x0021b730, identified in the authoritative source as on_magnet_ground. This is a ground-material selector, not a hero state. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021b728 loads the byte at Hero+0x20A4 and 0x0021b72c branches when nonzero, gating the slot-one item test. Authoritative C identifies that exact field as hero_state->vehicle_mode; the same snapshot switches on hero.vehicle_mode using HERO_VEHICLE_MODE_ON_FOOT, and the supplied HeroVehicleMode domain canonically defines this member as 0. Thus the selector belongs to the vehicle-mode domain. domain_4_value_2 -> GROUND_MATERIAL_MAGNETIC: The same saved ground material in s2, loaded from Hero+0x12E0 at 0x0021b6cc, is compared with 2 at 0x0021b7ec-0x0021b7f0. The selected block writes 1 to Hero+0x12E7 at 0x0021b800, the authoritative on_magnet_ground field. This repeats the magnetic material domain and must use the same member as the earlier comparison. domain_5_value_13 -> GROUND_MATERIAL_SINK_TRIGGER: Retail 0x0021b808 compares saved ground material s2 with 0xD and 0x0021b818 sets Hero+0x12EC. That flag gates 0x0021b864-0x0021b8f4: proximity below Hero+0x2F0 surface height and negative vertical displacement select hero_set_state(0x7F,1). The authoritative C names that destination HERO_STATE_SINK. Therefore this material triggers sinking; its physical substance is not asserted. --- src/overlays/l02/hero/update_hero_state_motion.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/overlays/l02/hero/update_hero_state_motion.c b/src/overlays/l02/hero/update_hero_state_motion.c index 470c1b87d2..fcc916581b 100644 --- a/src/overlays/l02/hero/update_hero_state_motion.c +++ b/src/overlays/l02/hero/update_hero_state_motion.c @@ -35,6 +35,10 @@ extern int hero_set_state(int, int) __asm__("FUN_L02_0022b728"); void process_hero_ground_material_effects(void) __asm__("FUN_L02_0021b698"); void process_hero_ground_material_effects(void) { + enum { + GROUND_MATERIAL_MAGNETIC = 2, + GROUND_MATERIAL_SINK_TRIGGER = 0xD + }; struct Hero *hero_state = &hero; int keep = hero_state->ground_sound_class; int saved_ground_type = hero_state->ground_type; @@ -46,10 +50,10 @@ void process_hero_ground_material_effects(void) { hero_state->unk308 = 0; if (saved_ground_type == -1) return; - if (saved_ground_type == 2) { + if (saved_ground_type == GROUND_MATERIAL_MAGNETIC) { if (hero_state->frames_off_ground.s == 0 || hero_state->ground_distance < 0.3f) { hero_state->on_magnet_ground = 1; - if (hero_state->vehicle_mode == 0) { + if (hero_state->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { char *slot_one_moby = (char *)hero_state->items[1].moby; if (slot_one_moby != 0 && *(short *)(slot_one_moby + 0xA6) == 0xAD) hero_state->unk308 = 1; @@ -77,11 +81,11 @@ void process_hero_ground_material_effects(void) { struct Hero *q = &hero; q->selector_11 = 1; } - if (saved_ground_type == 0x2) { + if (saved_ground_type == GROUND_MATERIAL_MAGNETIC) { struct Hero *q = &hero; q->on_magnet_ground = 1; } - if (saved_ground_type == 0xD) { + if (saved_ground_type == GROUND_MATERIAL_SINK_TRIGGER) { struct Hero *q = &hero; q->selector_13 = 1; } From 0f3f2325328b6e40436a6f82f993f24c864125b5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:42:03 +0000 Subject: [PATCH 0823/1502] decomp: clarify names in render_three_shell_particle_sky domain_0_value_0 -> SKY_PARTICLE_PHASE_ORBIT: The authoritative SkyParticle type byte at +0 is set to zero by sb zero,0(s1) at 0x0028ad38 for indices >=0xF0. Random halfword phases are written to +0xC/+0xE at 0x0028ad4c and 0x0028ad60. The same +0 byte is tested at 0x0028aee0-0x0028aee4; its zero branch increments both phases, masks each by 0xFFF, centers by -0x800 and converts to radians, then computes x=cos(a)*sin(b)*50, y=sin(a)*sin(b)*50 and z=cos(b)*50 through 0x0028af90, proving a phase-driven spherical orbit particle type. domain_1_value_1 -> SKY_PARTICLE_RANDOM_COLOR: At 0x0028ad90, sb s6,0(s1) assigns 1 to the same SkyParticle type byte (+0), with s6 loaded as 1 at 0x0028ad0c. This branch initializes spherical coordinates once and stores a packed base color at +0xC (0x0028ae88). The update tests that type byte at 0x0028aee0-0x0028aee4; its nonzero branch calls rand, shifts right 16, extracts masks 0x1F00/0x1F0/0x1F and adds shifted color offsets to +0xC before storing color at +4 (0x0028afb4-0x0028aff4), without updating position. Initialization supplies only types 0 and 1, proving the random-color particle type. domain_2_value_0 -> SKY_PARTICLE_PHASE_ORBIT: The comparison particle->type == 0 corresponds to lbu a0,0(s1) at 0x0028aee0 and bne a0,zero at 0x0028aee4. It reads the same +0 type byte assigned zero at 0x0028ad38. The zero branch increments phase halfwords +0xC and +0xE (0x0028aeec-0x0028af00), converts their low 12 bits to angular values, and recomputes radius-50 spherical coordinates at +0x10/+0x14/+0x18 through 0x0028af90. Therefore this comparison must reuse the initialization constant SKY_PARTICLE_PHASE_ORBIT. --- .../shared/rendering/sky/sky_particle_effects.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/rendering/sky/sky_particle_effects.c b/src/overlays/shared/rendering/sky/sky_particle_effects.c index 09411f5efc..e8d11ef5e9 100644 --- a/src/overlays/shared/rendering/sky/sky_particle_effects.c +++ b/src/overlays/shared/rendering/sky/sky_particle_effects.c @@ -464,6 +464,10 @@ extern u32 D_L00_00160500[2] __attribute__((sda)); void render_three_shell_particle_sky(void) __asm__("FUN_L00_0028ac88"); void render_three_shell_particle_sky(void) { + enum { + SKY_PARTICLE_PHASE_ORBIT = 0, + SKY_PARTICLE_RANDOM_COLOR = 1 + }; int i, j; SkyParticle *particle; f32 a, polar_angle_radians; @@ -477,7 +481,7 @@ void render_three_shell_particle_sky(void) { particle = &SKY->stars[i]; if (i >= 0xF0) { u16 *h; - particle->type = 0; + particle->type = SKY_PARTICLE_PHASE_ORBIT; h = &particle->c.h.a; h[0] = rand() >> 16; h[1] = rand() >> 16; @@ -486,7 +490,7 @@ void render_three_shell_particle_sky(void) { particle->f1C = 0.18f; particle->color = D_L00_00160500[(rand() >> 16) & 3]; } else { - particle->type = 1; + particle->type = SKY_PARTICLE_RANDOM_COLOR; particle->c.h.a = random_integer_below(0x100); { int random_high_half = rand() >> 16; @@ -520,7 +524,7 @@ void render_three_shell_particle_sky(void) { } for (j = 0; j < SKY->count; j++) { particle = &SKY->stars[j]; - if (particle->type == 0) { + if (particle->type == SKY_PARTICLE_PHASE_ORBIT) { u16 *h = &particle->c.h.a; h[0]++; h[1]++; From 9d06d63fff4d22375da663ddbb1ae393c670e705 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:42:03 +0000 Subject: [PATCH 0824/1502] decomp: clarify names in update_homing_rocket domain_0_value_2 -> ROCKET_BURST_AND_REMOVE: Collision branch retail 002d4698/002d46bc reaches li v0,2 at 002d4748 and sb v0,0x20(s4) at 002d474c. Incoming rocket_moby is s4 (002d43d8); state is loaded from the identical +0x20 at 002d43f8 and compared with 2 at 002d4404-002d4408 to enter 002d4768. That branch calls source-bound cart_burst then mark_moby_for_removal at 002d4780/002d4788. Thus this assignment selects the existing ROCKET_BURST_AND_REMOVE case of this exact rocket state domain. domain_1_value_2 -> ROCKET_BURST_AND_REMOVE: Timer branch calls fast_dec_timer on RocketVars.timer at 002d4750-002d4754; nonzero result reaches sb v0,0x20(s4) at 002d4764 with v0=2 from 002d475c. The same rocket state byte is loaded at 002d43f8 and value 2 dispatches at 002d4404-002d4408 to 002d4768, whose source-bound cart_burst and mark_moby_for_removal calls are at 002d4780/002d4788. This proves reuse of the existing ROCKET_BURST_AND_REMOVE member, rather than a separate timer/control domain. --- src/overlays/l03/mobys/homing_rocket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l03/mobys/homing_rocket.c b/src/overlays/l03/mobys/homing_rocket.c index 1a0c775ec7..34d5266b9f 100644 --- a/src/overlays/l03/mobys/homing_rocket.c +++ b/src/overlays/l03/mobys/homing_rocket.c @@ -185,10 +185,10 @@ void homing_rocket_update(struct Moby *rocket_moby) { hit.oclass = rocket_moby->oclass; record_moby_hit(level[6], &hit); } - rocket_moby->state = 2; + rocket_moby->state = ROCKET_BURST_AND_REMOVE; } if (fast_dec_timer(&rocket_vars->timer) != 0) { - rocket_moby->state = 2; + rocket_moby->state = ROCKET_BURST_AND_REMOVE; } break; case ROCKET_BURST_AND_REMOVE: From d95a07835c68926b5d9f77254647db56ab904906 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:42:03 +0000 Subject: [PATCH 0825/1502] decomp: clarify names in rocks_update domain_0_value_1 -> ROCKS_WAIT_FOR_HIT: Authoritative rocks.c (SHA-256 a66146d553d664f5d315e6e9dd7d6fb42f6c6d271f41d369efee2ec93d851d6f) declares ROCKS_WAIT_FOR_HIT = 1 and switches on moby->state. Retail 0x002e0768 loads that state byte from 0x20(s1), and 0x002e0774-0x002e0778 dispatches value 1 to 0x002e07b0, where the find_moby_hit return gates the burst. Initialization with a clear flag loads 1 at 0x002e0794 and stores it to the identical 0x20(s1) state byte at 0x002e07ac. Original Ghidra likewise assigns *(undefined1 *)(iVar8 + 0x20) = 1 and tests cVar2 == 1 with lVar5 != 0 before emitting. Thus this assignment enters the existing ROCKS_WAIT_FOR_HIT state, rather than a separate flag/control domain. --- src/overlays/l02/mobys/rocks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l02/mobys/rocks.c b/src/overlays/l02/mobys/rocks.c index 85dd4aeaf2..38bf83fb42 100644 --- a/src/overlays/l02/mobys/rocks.c +++ b/src/overlays/l02/mobys/rocks.c @@ -61,7 +61,7 @@ void rocks_update(struct Moby *moby) { if (menu_item_enabled_9) { mark_moby_for_removal(moby); } else { - moby->state = 1; + moby->state = ROCKS_WAIT_FOR_HIT; } break; case ROCKS_WAIT_FOR_HIT: From b53d156901eff0ebe3c11af103ff4520d4b8cf42 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:42:03 +0000 Subject: [PATCH 0826/1502] decomp: clarify names in apply_hero_ground_type_effects domain_0_value_2 -> HERO_GROUND_TYPE_MAGNET: The source saved_ground_type is hero.ground_type, loaded as signed halfword into s2 at retail 0x002044fc before clearing the ground block. Its comparison with 2 at 0x0020451c-0x00204520 gates the proximity test and store 1 to hero+0x12e7 at 0x00204560, identified in the authoritative C as on_magnet_ground. This proves the magnet-ground effect domain, independently of HeroStateId. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00204558 reads hero+0x20a4 and 0x0020455c branches away when nonzero before inspecting item slot one. Authoritative C identifies that exact byte as hero_state->vehicle_mode. The supplied HeroVehicleMode domain canonically defines HERO_VEHICLE_MODE_ON_FOOT=0, also used by the same snapshot's process_hero_incoming_hit switch on hero.vehicle_mode; this is a vehicle selector, not the saved ground type or current state. domain_2_value_14 -> HERO_GROUND_TYPE_FIXED_SHALLOW_WATER: Retail 0x0020458c compares the saved ground-type s2 with 14. The branch sets hero+0x12e4 and writes 0.2 to +0x22a4 and ground height at +0x2d8 plus 0.2 to +0x2f0 (0x00204594-0x002045b4). Authoritative C identifies these as base_condition, water_depth and water_surface_z respectively. This proves a fixed shallow-water ground effect of depth 0.2, not the numerically equal double-jump state. domain_3_value_0 -> HERO_GROUND_TYPE_WATER: Retail 0x002045b8 tests saved ground-type s2 against zero; 0x002045d0-0x002045e8 computes water_surface_z minus ground_z and stores water_depth, then 0x002045f8-0x00204614 sets wading for depth between 0.25 and 0.85 and base_condition. The authoritative C's water fields and wading data flow establish a water ground effect, not the equal-valued idle state or vehicle mode. --- .../l15/hero/update_hero_motion_for_current_state.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/l15/hero/update_hero_motion_for_current_state.c b/src/overlays/l15/hero/update_hero_motion_for_current_state.c index a3018ca2ef..bfc60a00d1 100644 --- a/src/overlays/l15/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l15/hero/update_hero_motion_for_current_state.c @@ -33,6 +33,11 @@ float absolute_float(float input) __asm__("func_001F99C0"); void apply_hero_ground_type_effects(void) __asm__("FUN_L15_002044c8"); void apply_hero_ground_type_effects(void) { + enum { + HERO_GROUND_TYPE_WATER = 0, + HERO_GROUND_TYPE_MAGNET = 2, + HERO_GROUND_TYPE_FIXED_SHALLOW_WATER = 0xE + }; struct Hero *hero_state = &hero; int keep = hero_state->ground_sound_class; int saved_ground_type = hero_state->ground_type; @@ -44,23 +49,23 @@ void apply_hero_ground_type_effects(void) { hero_state->unk308 = 0; if (saved_ground_type == -1) return; - if (saved_ground_type == 2) { + if (saved_ground_type == HERO_GROUND_TYPE_MAGNET) { if (hero_state->frames_off_ground.s == 0 || hero_state->ground_distance < 0.3f) { hero_state->on_magnet_ground = 1; - if (hero_state->vehicle_mode == 0) { + if (hero_state->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { char *item_slot_one_moby = ((char *)hero_state->items[1].moby); if (item_slot_one_moby != 0 && MOBY(item_slot_one_moby)->oclass == 0xAD) hero_state->unk308 = 1; } } } - if (saved_ground_type == 0xE) { + if (saved_ground_type == HERO_GROUND_TYPE_FIXED_SHALLOW_WATER) { struct Hero *q = &hero; *(char *)&q->base_condition = 1; q->water_depth = 0.2f; q->water_surface_z = q->ground_z.f + 0.2f; } - if (saved_ground_type == 0) { + if (saved_ground_type == HERO_GROUND_TYPE_WATER) { struct Hero *q = &hero; float water_depth = q->water_surface_z - q->ground_z.f; q->water_depth = water_depth; From a0a7bf6e2323c4a39ffe324ac68689b47eabfdad Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:43:57 +0000 Subject: [PATCH 0827/1502] decomp: clarify names in update_hero_seeking_group_moby domain_0_value_2 -> GROUP_MOBY_STATE_RISING: Authoritative source state comes from moby+0x20, matching retail lbu at 0x002a25a0. Equality with 2 at 0x002a25a4-0x002a25a8 enters 0x002a25e0: Z at moby+0x18 increases by twice frame time, countdown at pvars+0x68 is tested, then state becomes 3 at 0x002a2614. This proves a timed rising state of the group moby, not the hero state domain. domain_1_value_3 -> GROUP_MOBY_STATE_HERO_SEEKING: The state < 3 comparison is retail slti v0,v1,0x3 at 0x002a25ac, where v1 was loaded from this moby's +0x20. Its boundary is the same state 3 tested at 0x002a25c8, whose branch computes hero-minus-moby XY at 0x002a2654-0x002a2664 and applies yaw-scaled seeking motion at 0x002a2690-0x002a2748. Reuse the hero-seeking member for this ordering comparison in the same moby-state domain. domain_2_value_0 -> GROUP_MOBY_STATE_RESET: Source state == 0 dispatches to s0. Retail 0x002a25b8 branches on the moby+0x20 state being zero directly to 0x002a2828, bypassing burst calls. At 0x002a2830-0x002a2840 it writes inactive state 1, clears moby+0x31, sets flag bit 1 and clears collision at +0x94. Thus zero requests the explicit reset-to-inactive path, not hero idle. domain_3_value_3 -> GROUP_MOBY_STATE_HERO_SEEKING: Retail 0x002a25c8 tests the state byte from this moby's +0x20 against 3 and enters 0x002a2644. At 0x002a2654-0x002a2678 hero XY and target Z drive heading and height correction; 0x002a2690-0x002a2748 builds and applies movement scaled by group_moby_seeking_speed_gp. Proximity or timeout then selects burst state 4 at 0x002a278c. Original retail Ghidra and source s3 agree on hero-seeking behavior. domain_4_value_4 -> GROUP_MOBY_STATE_BURST: Retail 0x002a25cc-0x002a25d0 compares this moby's +0x20 state to 4 and dispatches to 0x002a27d4. This path calls source cart_burst at the moby's position (0x002a27e8-0x002a27f4) and a second effect helper at 0x002a2820 before falling into reset-to-inactive at 0x002a2828-0x002a2840. Hit detection selects this same state at 0x002a24c8 and seeking proximity/timeout at 0x002a278c. --- src/overlays/shared/enemies/hero_seeking_mine.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/enemies/hero_seeking_mine.c b/src/overlays/shared/enemies/hero_seeking_mine.c index 736a170b43..a04e0fea18 100644 --- a/src/overlays/shared/enemies/hero_seeking_mine.c +++ b/src/overlays/shared/enemies/hero_seeking_mine.c @@ -67,7 +67,7 @@ void hero_seeking_mine_update(char *moby) __asm__("FUN_L15_002a2488"); /* Moby class 77 */ void hero_seeking_mine_update(char *moby) { - float va[4]; + enum { GROUP_MOBY_STATE_RESET = 0 , GROUP_MOBY_STATE_RISING = 2 , GROUP_MOBY_STATE_HERO_SEEKING = 3 , GROUP_MOBY_STATE_BURST = 4 } ;float va[4]; float pb[4]; char *group_moby_data; char *callback_frame_stamp; @@ -120,16 +120,16 @@ void hero_seeking_mine_update(char *moby) { } } state = ((unsigned char *)moby)[0x20]; - if (state == 2) + if (state == GROUP_MOBY_STATE_RISING) goto s2; - if (state < 3) { - if (state == 0) + if (state < GROUP_MOBY_STATE_HERO_SEEKING) { + if (state == GROUP_MOBY_STATE_RESET) goto s0; return; } - if (state == 3) + if (state == GROUP_MOBY_STATE_HERO_SEEKING) goto s3; - if (state == 4) + if (state == GROUP_MOBY_STATE_BURST) goto s4; return; From 6c0c1b45b5cd96ae9d36851af8c81ecfe362710a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:43:57 +0000 Subject: [PATCH 0828/1502] decomp: clarify names in update_menu_system domain_0_value_20 -> MENU_SYSTEM_STATE_FINALIZE_CLOSE: Retail 0x002192ec-0x00219358 compares the state at menu_system base 0x001d5bf0 with 0x14, waits for timer and CD inactivity, restores level VU/fog setup, clears menu workspaces and game_mode. The supplied close_menu_system source writes MENU_SYSTEM_STATE_FINALIZE_CLOSE = 20 to this exact menu_system.state after leave callbacks and panel deletion, proving the same domain and established name. domain_4_value_1 -> MENU_SYSTEM_STATE_PAGE_TRANSITION_PENDING: Retail 0x0021939c-0x002193dc compares menu_system.state at 0x001d5bf0 with 1, decrements/clamps timer at +0x14, then on expiry promotes next (+0x8) to current (+0x4), clears next and publishes the incoming page state (+0x3c). At 0x002193e0-0x0021941c it invokes that page's screen enter callbacks. This is the pending timed page transition state, not an action or moby state. domain_5_value_1 -> MENU_SYSTEM_STATE_PAGE_TRANSITION_PENDING: Retail 0x00219588-0x002195a4 stores 1 to the same menu_system.state base 0x001d5bf0, sets timer to 12, saves current as previous (+0xd0) and clears current after configuring transition animations. The comparison at 0x0021939c-0x002193dc consumes exactly this value to wait for the timer and promote next to current, proving both tokens share the page-transition-pending member. --- src/ui/menus/system/update_menu_system.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ui/menus/system/update_menu_system.c b/src/ui/menus/system/update_menu_system.c index 8e70e922ef..0a291ee425 100644 --- a/src/ui/menus/system/update_menu_system.c +++ b/src/ui/menus/system/update_menu_system.c @@ -37,6 +37,10 @@ extern void mode_freeze_init(s32, struct MenuPage *) __asm__("func_001FBAB8"); void update_menu_system(void) __asm__("FUN_002192a8"); void update_menu_system(void) { + enum { + MENU_SYSTEM_STATE_PAGE_TRANSITION_PENDING = 1, + MENU_SYSTEM_STATE_FINALIZE_CLOSE = 0x14 + }; s32 i; s32 j; s32 k; @@ -47,7 +51,7 @@ void update_menu_system(void) { menu_system.update_count = menu_system.update_count + 1; reset_active_camera_position_and_basis(); - if (menu_system.state == 0x14) { + if (menu_system.state == MENU_SYSTEM_STATE_FINALIZE_CLOSE) { if (menu_system.timer != 0) { menu_system.timer = menu_system.timer - 1; if (menu_system.timer != 0) { @@ -75,7 +79,7 @@ void update_menu_system(void) { mode_freeze_init(3, menu_system.current); return; } - if (menu_system.state == 1) { + if (menu_system.state == MENU_SYSTEM_STATE_PAGE_TRANSITION_PENDING) { menu_system.timer = (menu_system.timer < 1) ? 0 : menu_system.timer - 1; if (menu_system.timer == 0) { struct MenuPage *incoming_page = menu_system.next; @@ -122,7 +126,7 @@ void update_menu_system(void) { ((struct Ent *)panel_slots[j])->unk58 = 1.0f; } } - menu_system.state = 1; + menu_system.state = MENU_SYSTEM_STATE_PAGE_TRANSITION_PENDING; menu_system.timer = 12; menu_system.previous = menu_system.current; menu_system.current = 0; From 6b447d1d9771106d4708b0b8a7b96a63dc0d0bc5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:43:57 +0000 Subject: [PATCH 0829/1502] decomp: clarify names in update_hero_follow_camera_orbit domain_0_value_0 -> CAMERA_ORBIT_MODE_FOLLOW: Retail 0x00329928 loads Camera+0x70 into s8, then 0x00329944-0x00329958 tests the short at orbit+0x1c for zero before launch initialization. The same CameraOrbit.mode is assigned CAMERA_ORBIT_MODE_FOLLOW=0 in reset_hero_follow_camera_from_preset; supplied update_orbit_camera_position uses zero for normal spring-follow positioning. This proves the existing camera-domain constant applies. domain_1_value_1 -> CAMERA_ORBIT_MODE_ORBITING: Retail 0x00329954-0x00329964 tests the launch flag and writes 1 to CameraOrbit.mode at s8+0x1c, then initializes yaw/pitch/distance and saved forward basis through 0x00329b8c. The same value gates reconstruction of camera position by yaw/pitch rotations and spring updates at 0x00329b94-0x00329c78, proving this is the camera orbiting mode. domain_2_value_1 -> CAMERA_ORBIT_MODE_ORBITING: Retail 0x00329b90-0x00329b98 compares the short at orbit+0x1c with 1. Its branch scales the saved forward vector by camera distance, rotates by camera yaw and pitch, adds focus into camera position at 0x00329bb4-0x00329c18 and springs the orbit coordinates through 0x00329c78. This is the same orbiting mode assigned at 0x00329964. domain_3_value_0 -> CAMERA_ORBIT_MODE_FOLLOW: Retail 0x00329c80-0x00329c90 checks the launch flag and clears the same CameraOrbit.mode short at s8+0x1c when it ends, then negates the orbit vector at 0x00329c9c. Zero is the established CAMERA_ORBIT_MODE_FOLLOW value used by preset reset, and the supplied caller selects normal follow springs and positioning when this same mode is zero. --- src/overlays/shared/camera/hoverboard_camera.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/camera/hoverboard_camera.c b/src/overlays/shared/camera/hoverboard_camera.c index 6761568321..75a5501949 100644 --- a/src/overlays/shared/camera/hoverboard_camera.c +++ b/src/overlays/shared/camera/hoverboard_camera.c @@ -314,6 +314,10 @@ extern float FUN_001ebd78(void *, float, float, float, float, float); void update_hero_follow_camera_orbit(Camera *cam) __asm__("FUN_L05_003298d8"); void update_hero_follow_camera_orbit(Camera *hero_follow_camera) { + enum { + CAMERA_ORBIT_MODE_FOLLOW = 0, + CAMERA_ORBIT_MODE_ORBITING = 1 + }; Vec4 up; Vec4 side; Vec4 fwd; @@ -332,8 +336,8 @@ void update_hero_follow_camera_orbit(Camera *hero_follow_camera) { f32 tilt; fast_vec_normalize(&up, &hero.gravity_dir, -1.0f); - if (orbit->mode == 0 && hero.vert_ramp_launch != 0) { - orbit->mode = 1; + if (orbit->mode == CAMERA_ORBIT_MODE_FOLLOW && hero.vert_ramp_launch != 0) { + orbit->mode = CAMERA_ORBIT_MODE_ORBITING; fast_vec_cross(&side, &hero.moby->rot_row2, &up); fast_vec_normalize(&side, &side, 1.0f); fast_vec_cross(&fwd, &up, &side); @@ -381,7 +385,7 @@ void update_hero_follow_camera_orbit(Camera *hero_follow_camera) { spring[8] = 0.005f; spring[11] = 0.2f; } - if (orbit->mode == 1) { + if (orbit->mode == CAMERA_ORBIT_MODE_ORBITING) { fast_vec_normalize(&side, &focus->side, hero_follow_camera->dist); build_look_at_matrix(&side, &side, &up, hero_follow_camera->yaw); fast_vec_cross(&fwd, &side, &up); @@ -395,7 +399,7 @@ void update_hero_follow_camera_orbit(Camera *hero_follow_camera) { hero_follow_camera->dist = FUN_001ebd78( &spring[5], hero_follow_camera->dist, spring[2], spring[8], spring[11], 0.0f); if (hero.vert_ramp_launch == 0) { - orbit->mode = 0; + orbit->mode = CAMERA_ORBIT_MODE_FOLLOW; fast_vec_scale(orbit, orbit, -1.0f); } } From 68d1c6f3430125ceea39d61f1f2929cae55bee96 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:43:57 +0000 Subject: [PATCH 0830/1502] decomp: clarify names in update_flying_car_path_motion domain_0_value_3 -> FLYING_CAR_WAIT_FOR_PATH_RESET: Retail 00307638 retains the supplied Moby in s2; after path completion or the low-height test (0030768C-003076B0), 003076E0-003076E4 stores 3 at that same Moby's state byte +0x20. Original Ghidra shows the same store after the burst and before collision disable, part hiding and voice release. Authoritative flying_car.c (SHA-256 afab9a3684f8351b30c82da7642ab6a54a1c2bbb3ec2eb8d2616a6f57933ee08) shows update_flying_car passing its flying_car_moby to this function in FLYING_CAR_FOLLOW_PATH, and switching on that same Moby state. Its established local enum defines FLYING_CAR_WAIT_FOR_PATH_RESET = 3; that branch waits for the reset timer, restores visibility/collision, resets path traversal and position, then resumes path-following or trigger waiting. This proves the same flying-car state domain and reset-wait meaning, independently of unrelated HERO_STATE_STOP = 3. --- src/overlays/l14/mobys/flying_car.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/flying_car.c b/src/overlays/l14/mobys/flying_car.c index 1591f61045..d0089a3c38 100644 --- a/src/overlays/l14/mobys/flying_car.c +++ b/src/overlays/l14/mobys/flying_car.c @@ -333,6 +333,9 @@ extern f32 vendor_spring(f32 *, f32 *, f32, f32, f32, f32) __asm__("FUN_L00_0025 int update_flying_car_path_motion(struct Moby *moby) __asm__("FUN_L14_00307620"); int update_flying_car_path_motion(struct Moby *moby) { + enum { + FLYING_CAR_WAIT_FOR_PATH_RESET = 3 + }; float pos[4]; float delta[4]; char *flying_car_data = (char *)moby->pvars; @@ -351,7 +354,7 @@ int update_flying_car_path_motion(struct Moby *moby) { if ((*(short *)(flying_car_data + 0x8E) == 0 && end != 0) || moby->pos.z <= flying_car_burst_height_threshold_gp) { cart_burst(moby, &moby->pos, 5.0f, 13.0f, -1); - moby->state = 3; + moby->state = FLYING_CAR_WAIT_FOR_PATH_RESET; moby->flags |= 0x41; moby->collision = 0; if (*(int *)(flying_car_data + 0xA0) >= 0) { From ab1365c21a2ea785b4ae6b5af5149f1cc1a7674a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:43:57 +0000 Subject: [PATCH 0831/1502] decomp: clarify names in platform_booster_update domain_0_value_1 -> PLATFORM_BOOSTER_STATE_FOLLOW_LEVER: The updated moby is retained in s0 at 0x002c6bc4; retail 0x002c6c40 stores s2=1 into its state byte +0x20 after animation initialization. The dispatch reads the identical s0+0x20 at 0x002c6bec and branches for 1 at 0x002c6bf4 to the linked-lever handling at 0x002c6c50. Thus this assignment enters the same domain and value already named PLATFORM_BOOSTER_STATE_FOLLOW_LEVER in the source switch. domain_2_value_2 -> PLATFORM_BOOSTER_STATE_ADVANCE_ANIMATION: Retail 0x002c6d28-0x002c6d2c writes 2 to the updated moby's s0+0x20 state byte when lever travel or the target/hero gate triggers. The same byte dispatches value 2 at 0x002c6c14 into 0x002c6da4, where 0x002c6db4-0x002c6dcc advances animation by frame_time*0.5 and clamps it to 1. This is the existing source switch member PLATFORM_BOOSTER_STATE_ADVANCE_ANIMATION, not a lever or hero domain. domain_4_value_1 -> PLATFORM_BOOSTER_STATE_FOLLOW_LEVER: Retail 0x002c6dfc-0x002c6e08 compares the linked class-0x118 moby's state with 3, then 0x002c6e10 stores s2=1 into the updated booster's s0+0x20, while 0x002c6e14-0x002c6e1c sets its animation time to inverse lever travel. That destination is the identical byte dispatched for state 1 at 0x002c6bec-0x002c6bf4, already named PLATFORM_BOOSTER_STATE_FOLLOW_LEVER in the source switch. --- src/overlays/l04/mobys/platform_booster.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l04/mobys/platform_booster.c b/src/overlays/l04/mobys/platform_booster.c index f857916a3b..50c08bd12b 100644 --- a/src/overlays/l04/mobys/platform_booster.c +++ b/src/overlays/l04/mobys/platform_booster.c @@ -58,7 +58,7 @@ void platform_booster_update(struct Moby *moby) { switch (moby->state) { case PLATFORM_BOOSTER_STATE_INITIALIZE: blend_moby_animation(moby, 1, 0, scale_game_frames(300)); - moby->state = 1; + moby->state = PLATFORM_BOOSTER_STATE_FOLLOW_LEVER; moby->anim_speed = 0; door_vars->voice = -1; break; @@ -78,7 +78,7 @@ void platform_booster_update(struct Moby *moby) { ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9 || hero.state.control_mode == 12) && hero.ground_moby == &((struct Moby *)moby_array)[door_vars->target])) { - moby->state = 2; + moby->state = PLATFORM_BOOSTER_STATE_ADVANCE_ANIMATION; } if (moby->anim_time != previous_anim_time) { if (lv->travel != 1.0f && lv->travel != 0.0f) { @@ -125,7 +125,7 @@ void platform_booster_update(struct Moby *moby) { link_vars = (LeverVars *)link->pvars; if (link->state == 3) { moby->anim_time = 1.0f - link_vars->travel; - moby->state = 1; + moby->state = PLATFORM_BOOSTER_STATE_FOLLOW_LEVER; } else { link_vars->travel = 1.0f - moby->anim_time; link_vars->spin = link_vars->travel * (link_vars->rate * 6.2831855f); From a15b8e38a982f526b68f81f1bb5caade3ded896d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:43:57 +0000 Subject: [PATCH 0832/1502] decomp: clarify names in rocket_tank_update domain_0_value_1 -> ROCKET_TANK_PATROLLING: Initialization ends with moby->state = 1 in the bound source. Retail s2 holds the same moby: 0x002f7c6c reads its +0x20 state, 0x002f7c70 dispatches state 1 to 0x002f7dfc, and initialization reaches 0x002f802c with s0=1 from 0x002f7c58. The store sb s0,0x20(s2) writes that exact switch domain. Reuse existing local ROCKET_TANK_PATROLLING=1, whose branch calls path movement at 0x002f7e00. domain_1_value_2 -> ROCKET_TANK_FIRING: The patrolling branch sets moby->state = 2 after resetting firing fields data+0x134/+0x130 and selecting animation 2. Retail 0x002f7e04 sets s0=2, 0x002f7e28/0x002f7e2c directly stores it to +0x20(s2) or reaches the common store at 0x002f802c through animation setup. The same state byte dispatches 2 at 0x002f7c90 to the firing branch 0x002f7e48, whose animation windows lead to launch calls 0x002f7fd0/0x002f7fe8. Reuse existing local ROCKET_TANK_FIRING=2. domain_2_value_1 -> ROCKET_TANK_PATROLLING: The firing branch returns to moby->state = 1 when data+0xB4 == 2. Retail 0x002f7ff4..0x002f8008 checks that private status and loads s0=1, selects animation 1 if needed, then 0x002f802c stores s0 into moby state +0x20(s2). That is exactly the byte read at 0x002f7c6c and dispatched to the established ROCKET_TANK_PATROLLING=1 branch at 0x002f7c70, so reuse that local member rather than naming the separate private-status domain. --- src/overlays/l18/mobys/rocket_tank.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l18/mobys/rocket_tank.c b/src/overlays/l18/mobys/rocket_tank.c index 3c8814073f..1b4c342e23 100644 --- a/src/overlays/l18/mobys/rocket_tank.c +++ b/src/overlays/l18/mobys/rocket_tank.c @@ -146,7 +146,7 @@ void rocket_tank_update(M1454 *moby) { if (moby->b53 != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } - moby->state = 1; + moby->state = ROCKET_TANK_PATROLLING; break; case ROCKET_TANK_PATROLLING: func_L18_002F9AB8_v(moby); @@ -156,7 +156,7 @@ void rocket_tank_update(M1454 *moby) { if (moby->b53 != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(20)); } - moby->state = 2; + moby->state = ROCKET_TANK_FIRING; } break; case ROCKET_TANK_FIRING: @@ -194,7 +194,7 @@ void rocket_tank_update(M1454 *moby) { if (moby->b53 != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(20)); } - moby->state = 1; + moby->state = ROCKET_TANK_PATROLLING; } break; } From e866efa6b63fc9083b372194417ad3049947841f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:43:58 +0000 Subject: [PATCH 0833/1502] decomp: clarify names in apply_hero_ground_type_effects domain_0_value_2 -> GROUND_TYPE_MAGNETIC: saved_ground_type is the signed Hero+0x12e0 field loaded into s2 at 0x00213b74 before reset. The comparison to 2 at 0x00213b94-0x00213b98 leads to setting Hero.on_magnet_ground (+0x12e7) at 0x00213bd8, with a proximity check and on-foot item check. This is a ground-material selector, not HeroStateId. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00213bd0 loads the byte Hero+0x20a4 and 0x00213bd4 skips the item-moby check when nonzero; authoritative C binds this load to hero_state->vehicle_mode. Therefore this selector belongs to the supplied HeroVehicleMode domain, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT. The same source snapshot uses that canonical member for switch(hero.vehicle_mode) in process_hero_hurt_response. domain_2_value_14 -> GROUND_TYPE_SHALLOW_WATER: The saved Hero.ground_type comparison against 14 at 0x00213c00-0x00213c04 enters a branch that stores 0.2 in Hero.water_depth at 0x00213c28 and ground_z+0.2 in Hero.water_surface_z at 0x00213c2c, while enabling the same base_condition as the water branch. This explicitly establishes a fixed shallow-water ground effect, separate from the HeroStateId value 14. domain_3_value_0 -> GROUND_TYPE_WATER: Retail 0x00213c30 compares saved ground_type in s2 against zero. Its branch subtracts ground_z from water_surface_z at 0x00213c48-0x00213c50, stores Hero.water_depth at 0x00213c60 and sets Hero.wading at 0x00213c80 when depth lies between 0.25 and 0.85. This proves the water ground-type role rather than the equal-valued idle state. domain_6_value_2 -> GROUND_TYPE_MAGNETIC: The same saved Hero.ground_type in s2 is compared with 2 at 0x00213d24-0x00213d28; its branch unconditionally sets Hero.on_magnet_ground (+0x12e7) to 1 at 0x00213d38. It is the same ground domain and value as the earlier magnet-ground comparison. --- .../l18/hero/apply_hero_ground_type_effects.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/overlays/l18/hero/apply_hero_ground_type_effects.c b/src/overlays/l18/hero/apply_hero_ground_type_effects.c index ef7f6823d0..b68f2eb069 100644 --- a/src/overlays/l18/hero/apply_hero_ground_type_effects.c +++ b/src/overlays/l18/hero/apply_hero_ground_type_effects.c @@ -21,6 +21,11 @@ float absolute_float(float input) __asm__("func_001F99C0"); void apply_hero_ground_type_effects(void) __asm__("FUN_L18_00213b40"); void apply_hero_ground_type_effects(void) { + enum { + GROUND_TYPE_WATER = 0, + GROUND_TYPE_MAGNETIC = 2, + GROUND_TYPE_SHALLOW_WATER = 0xE + }; struct Hero *hero_state = &hero; int keep = hero_state->ground_sound_class; int saved_ground_type = hero_state->ground_type; @@ -32,23 +37,23 @@ void apply_hero_ground_type_effects(void) { hero_state->unk308 = 0; if (saved_ground_type == -1) return; - if (saved_ground_type == 2) { + if (saved_ground_type == GROUND_TYPE_MAGNETIC) { if (hero_state->frames_off_ground.s == 0 || hero_state->ground_distance < 0.3f) { hero_state->on_magnet_ground = 1; - if (hero_state->vehicle_mode == 0) { + if (hero_state->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { char *item_moby = ((char *)hero_state->items[1].moby); if (item_moby != 0 && MOBY(item_moby)->oclass == 0xAD) hero_state->unk308 = 1; } } } - if (saved_ground_type == 0xE) { + if (saved_ground_type == GROUND_TYPE_SHALLOW_WATER) { struct Hero *q = &hero; *(char *)&q->base_condition = 1; q->water_depth = 0.2f; q->water_surface_z = q->ground_z.f + 0.2f; } - if (saved_ground_type == 0) { + if (saved_ground_type == GROUND_TYPE_WATER) { struct Hero *q = &hero; float water_depth = q->water_surface_z - q->ground_z.f; q->water_depth = water_depth; @@ -82,7 +87,7 @@ void apply_hero_ground_type_effects(void) { struct Hero *q = &hero; *(char *)&q->selector_11 = 1; } - if (saved_ground_type == 0x2) { + if (saved_ground_type == GROUND_TYPE_MAGNETIC) { struct Hero *q = &hero; *(char *)&q->on_magnet_ground = 1; } From 044b711c3b45e51735d04c1725188e4e9b2b7cb6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:43:58 +0000 Subject: [PATCH 0834/1502] decomp: clarify names in play_level_loading_slides domain_0_value_3 -> MEMCARD_REQUEST_FORMAT: Retail 0x00231c70-0x00231c7c loads the operation-state word at 0x0013d290+0xd4 and uses signed slti 3 to gate slide rendering; 0x00231f88-0x00231f94 repeats the same check after memcard_update_state at 0x00231f1c. Original Ghidra identifies this word as g_nMemoryCardOperationState; the bound source identifies it as memory_card_state.state. The supplied include/rnc/save/memory_card_state.h declaration context explicitly assigns state/pending_state to MemoryCardOperation, whose canonical member MEMCARD_REQUEST_FORMAT is 3. The caller do_space_transition waits on the complementary state >= 3 condition while servicing the same state machine, corroborating the operation threshold rather than a substep. domain_1_value_0 -> MEMCARD_QUERY_INFO: Retail 0x00231c84-0x00231c88 loads the pending operation-state word at 0x0013d290+0xdc and exits on bgez; 0x00231f9c-0x00231fa0 continues only on bltz. Original Ghidra names this g_nPendingMemoryCardOperationState and the SHA-bound source uses memory_card_state.pending_state < 0. The supplied shared header explicitly declares pending_state in MemoryCardOperation alongside state, where MEMCARD_QUERY_INFO is the canonical zero member. The caller do_space_transition waits on pending_state >= 0 while calling memcard_update_state/run_state_handler. Thus zero marks the start of the nonnegative operation domain; this substitution retains the signed negative-pending test without inventing a probe or request-substep meaning. --- src/ui/loading/play_level_loading_slides.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/loading/play_level_loading_slides.c b/src/ui/loading/play_level_loading_slides.c index e50d3fbea9..59aeba3e92 100644 --- a/src/ui/loading/play_level_loading_slides.c +++ b/src/ui/loading/play_level_loading_slides.c @@ -64,8 +64,8 @@ void play_level_loading_slides( } sceGsSyncV(0); vu1_init_chain(); - for (frame = 0; frame < duration_ticks && memory_card_state.state < 3 && - memory_card_state.pending_state < 0; + for (frame = 0; frame < duration_ticks && memory_card_state.state < MEMCARD_REQUEST_FORMAT && + memory_card_state.pending_state < MEMCARD_QUERY_INFO; frame++) { alpha = 0x80; reset_gs_registers(); From bd238a9b6acbd6c8deaa8081339008f04de2d118 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:46:06 +0000 Subject: [PATCH 0835/1502] decomp: clarify names in update_flickering_mesh_effect domain_0_value_0 -> FLICKERING_MESH_STATE_UNINITIALIZED: Retail 0x002f70f0 loads moby state byte +0x20 and 0x002f70f8 skips to 0x002f7240 if nonzero. The zero branch resets light handle +0x13b to -1 (0x002f7108), initializes particle timer +0xf8 (0x002f7110), copies position to +0x140, repairs zero texture counts, and seeds all eight noise/goal pairs at +0x90/+0xb0 (0x002f7208-0x002f7234). Original Ghidra and authoritative C both show this as the moby->state == 0 initialization guard, followed by state 1. domain_1_value_1 -> FLICKERING_MESH_STATE_INITIALIZED: Retail 0x002f7238 loads 1 and 0x002f723c stores it to the same moby state byte +0x20 tested at 0x002f70f0-0x002f70f8. This store follows completion of light-handle/timer/position setup, texture-count correction and the eight-pair noise/goal initialization loop. Original Ghidra and authoritative C agree that moby->state = 1 marks completed initialization, causing subsequent calls to bypass that setup block. It does not encode visibility, which is tested separately at +0x31. --- src/overlays/l08/mobys/flickering_mesh_effect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l08/mobys/flickering_mesh_effect.c b/src/overlays/l08/mobys/flickering_mesh_effect.c index 553e436423..9de65333f1 100644 --- a/src/overlays/l08/mobys/flickering_mesh_effect.c +++ b/src/overlays/l08/mobys/flickering_mesh_effect.c @@ -626,7 +626,7 @@ void flickering_mesh_effect_update(struct Moby *moby) __asm__("FUN_L08_002f70a0" /* Moby class 671 */ void flickering_mesh_effect_update(struct Moby *moby) { - FlickerLightVars *light_vars; + enum { FLICKERING_MESH_STATE_UNINITIALIZED = 0 , FLICKERING_MESH_STATE_INITIALIZED = 1 } ;FlickerLightVars *light_vars; Vec4 pos; f32 view, draw_fade_distance, fade; s32 hidden; @@ -641,7 +641,7 @@ void flickering_mesh_effect_update(struct Moby *moby) { return; hidden = 0; at = &moby->pos; - if (moby->state == 0) { + if (moby->state == FLICKERING_MESH_STATE_UNINITIALIZED) { light_vars->light = -1; light_vars->particle_timer = light_vars->particle_ticks; qcopy(&light_vars->light_pos, at); @@ -662,7 +662,7 @@ void flickering_mesh_effect_update(struct Moby *moby) { light_vars->noise[i] = random_float_between(light_vars->jitter, 1.0f); light_vars->goal[i] = random_float_between(light_vars->jitter, 1.0f); } - moby->state = 1; + moby->state = FLICKERING_MESH_STATE_INITIALIZED; } moby->scale = moby->pclass->scale * From 2bb3085a08fc75da9df92064014b07b74ede0900 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:46:06 +0000 Subject: [PATCH 0836/1502] decomp: clarify names in update_level14_racer domain_0_value_1 -> RACER_STATE_WAIT_FOR_RACE_START: Authoritative racer.c SHA-256 11ccab0775b16bd6880c03f4598232d172a9e518f8a81d6fe20e50614196cf1e declares this enum member as 1 in switch(racer_moby->state). Retail 0x002d5f68 reads that object's state byte +0x20; 0x002d6004-0x002d6008 writes 1 to the same byte after path initialization. Original Ghidra case 1 then waits for controller phase +0x86 == 0x14 at 0x002d6090-0x002d60a0, proving reuse of the existing same-selector member. domain_2_value_2 -> RACER_STATE_WAIT_FOR_START_DELAY: The authoritative C declares RACER_STATE_WAIT_FOR_START_DELAY=2 for the racer_moby->state switch. Original retail case 1 scales pvars delay +0x80 into timer +0x6c (0x002d60a8-0x002d60b0), then stores 2 to the same Moby state byte +0x20 at 0x002d60b4-0x002d60bc. Retail case 2 decrements that timer and returns until completion at 0x002d60c0-0x002d60c8, establishing the exact existing enum domain and member. domain_3_value_3 -> RACER_STATE_WAIT_FOR_START_ANIMATION: The C's existing RACER_STATE_WAIT_FOR_START_ANIMATION=3 labels the switch on racer_moby->state. Retail 0x002d60cc loads 3 and 0x002d60f4 stores it to that same state byte +0x20 after the delay expires, then starts animation 2 at 0x002d60f8 and sets speed 0.5 at 0x002d6110. Original Ghidra case 3 and retail 0x002d6184-0x002d61a8 wait for animation flag bit 2 with matching seq/prev_seq before transitioning, proving this existing member applies. domain_4_value_4 -> RACER_STATE_COMPLETE_START_INTERPOLATION: Authoritative C declares RACER_STATE_COMPLETE_START_INTERPOLATION=4 in the same racer_moby->state switch. Retail 0x002d6194-0x002d61a8 tests animation seq/prev_seq, loads 4 and stores it to Moby +0x20. Original Ghidra case 4 invokes FUN_L14_002d64d0 until nonzero; retail 0x002d61cc-0x002d61dc then transitions to 5. The established C helper interpolate_racer_to_path_start and this same-selector case prove reuse of the canonical local member. domain_5_value_5 -> RACER_STATE_FOLLOW_PATH: The authoritative C's RACER_STATE_FOLLOW_PATH=5 already labels the racer_moby->state switch branch calling advance_moby_along_path. Original Ghidra and retail 0x002d61cc-0x002d61dc show successful start interpolation loading 5 and writing the identical Moby state byte +0x20 read by dispatch at 0x002d5f68. Retail case 5 at 0x002d61f0 calls FUN_L14_002d7198, matching established advance_moby_along_path. This is direct same-domain reuse, not numeric equivalence to another state domain. --- src/overlays/l14/mobys/racer.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l14/mobys/racer.c b/src/overlays/l14/mobys/racer.c index b1f0f95bdb..ef1630b5af 100644 --- a/src/overlays/l14/mobys/racer.c +++ b/src/overlays/l14/mobys/racer.c @@ -131,7 +131,7 @@ void level14_racer_update(struct Moby *racer_moby) { return; } initialize_racer_path_tracking(racer_moby); - racer_moby->state = 1; + racer_moby->state = RACER_STATE_WAIT_FOR_RACE_START; racer_moby->flags = (racer_moby->flags & 0xEFFF) | 0x41; racer_moby->collision = 0; racer_vars->unkF4 = -1; @@ -146,7 +146,7 @@ void level14_racer_update(struct Moby *racer_moby) { case RACER_STATE_WAIT_FOR_RACE_START: if (race_state->phase == 0x14) { racer_vars->timer = scale_game_frames(racer_vars->delay); - racer_moby->state = 2; + racer_moby->state = RACER_STATE_WAIT_FOR_START_DELAY; } return; case RACER_STATE_WAIT_FOR_START_DELAY: @@ -154,7 +154,7 @@ void level14_racer_update(struct Moby *racer_moby) { return; racer_moby->flags = (racer_moby->flags | 0x1000) & 0xFFBE; racer_moby->collision = racer_moby->pclass->collision; - racer_moby->state = 3; + racer_moby->state = RACER_STATE_WAIT_FOR_START_ANIMATION; set_moby_animation(racer_moby, 2, 0); racer_moby->anim_speed = 0.5f; racer_vars->timer = scale_game_frames(level14_racer_start_interpolation_duration_frames_gp); @@ -164,14 +164,14 @@ void level14_racer_update(struct Moby *racer_moby) { if (compute_interpolated_record_value(racer_moby) >= 3.0f) interpolate_racer_to_path_start(racer_moby); if ((racer_moby->anim_flags & 2) && racer_moby->seq == racer_moby->prev_seq) { - racer_moby->state = 4; + racer_moby->state = RACER_STATE_COMPLETE_START_INTERPOLATION; blend_moby_animation((MobyAnim *)racer_moby, 0, 0, 10); racer_moby->anim_speed = 1.0f; } break; case RACER_STATE_COMPLETE_START_INTERPOLATION: if (interpolate_racer_to_path_start(racer_moby)) { - racer_moby->state = 5; + racer_moby->state = RACER_STATE_FOLLOW_PATH; racer_vars->timer = scale_game_frames(level14_racer_path_follow_initial_timer_frames_gp); } From 3907774faaf552e79da9f242b073416ca3668e47 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:46:07 +0000 Subject: [PATCH 0837/1502] decomp: clarify names in update_resident_dialogue_animation_state domain_0_value_12 -> RESIDENT_WAIT_TO_START_DIALOGUE_ANIMATION: Retail 0x00238014 stores 12 to the resident lifecycle byte +0x20 after preparing the variant dialogue request and animation 2. The same byte is switched at 0x00237f50; its existing case 12 waits for phase 3 and pending dialogue at 0x002381e8-0x00238220 before starting variant*3+5. This assignment therefore reuses the existing local state member. domain_1_value_3 -> RESIDENT_WAIT_TO_RESTORE_IDLE_ANIMATION: Retail 0x00238044/0x00238064 stores 3 to lifecycle byte +0x20 after the timed wait selects animation 3. That exact byte drives the switch at 0x00237f50; existing case 3 at 0x00238080 waits for completion bit +0x70 bit 1, restores animation 0 and state 0. The assigned value belongs to this established local state domain. domain_2_value_0 -> RESIDENT_IDLE_WAIT_TO_REQUEST_DIALOGUE: Retail 0x00238098/0x002380bc writes zero to lifecycle byte +0x20 after completion and restoration of animation 0. The same byte is loaded by the switch at 0x00237f50. Existing state 0 compares the idle timer with scale_game_frames(600) at 0x00237f78-0x00237f90 and prepares the dialogue request on expiry, proving reuse of the named idle state. domain_3_value_2 -> RESIDENT_TIMED_WAIT_TO_RESTORE_IDLE_ANIMATION: In source case RESIDENT_DIALOGUE_ANIMATION_AFTER_COMPLETION_WAIT, the completion branch restores animation 2, assigns resident_moby->state = 2 and clears the timer. Retail cases 4/5/6 share stores to lifecycle +0x20 at 0x00238134/0x00238154 and timer clear at 0x00238160. This is the same selector byte loaded at 0x00237f50; existing state 2 performs the timed idle restoration at 0x00238018-0x00238064. domain_4_value_2 -> RESIDENT_TIMED_WAIT_TO_RESTORE_IDLE_ANIMATION: In source case RESIDENT_DIALOGUE_ANIMATION_AFTER_START_WAIT, completion restores animation 2, writes resident_moby->state = 2 and clears its timer. Retail case 5 selects its threshold at 0x002380cc then shares lifecycle +0x20 stores 0x00238134/0x00238154 and timer clear 0x00238160. The switch loads this same byte at 0x00237f50; existing case 2 waits 600 scaled frames before idle restoration. domain_5_value_2 -> RESIDENT_TIMED_WAIT_TO_RESTORE_IDLE_ANIMATION: Source case RESIDENT_DIALOGUE_ANIMATION_WAIT_TO_RESTORE_TIMED_IDLE restores animation 2 on completion, assigns lifecycle state 2 and clears the timer. Retail case 6 selects its threshold at 0x002380dc and shares +0x20 stores at 0x00238134/0x00238154 and timer clear at 0x00238160. The byte is the switch selector at 0x00237f50, whose existing state 2 runs the timed restore path at 0x00238018. domain_6_value_4 -> RESIDENT_DIALOGUE_ANIMATION_AFTER_COMPLETION_WAIT: Retail state 10 tests completion bit +0x70 bit 1 at 0x00238198-0x002381a0, selects variant*3+4 and blends it at 0x002381ac-0x002381dc. It loads lifecycle value 4 at 0x002381c0/0x002381e4 and stores to +0x20 at 0x002382d4. That exact switch selector has existing case 4, selecting the after-completion threshold at 0x002380c0; reuse its established member. domain_7_value_5 -> RESIDENT_DIALOGUE_ANIMATION_AFTER_START_WAIT: Retail state 12 waits for dialogue phase 3 and pending at 0x002381e8-0x00238204, selects variant*3+5 and blends at 0x00238224-0x00238254. It loads 5 at 0x00238238/0x0023825c and stores lifecycle +0x20 at 0x002382d4. The same byte is switched at 0x00237f50 with existing case 5 selecting the after-start threshold at 0x002380cc, proving this canonical state member. domain_8_value_6 -> RESIDENT_DIALOGUE_ANIMATION_WAIT_TO_RESTORE_TIMED_IDLE: Retail state 11 waits for phase 3 and pending at 0x00238260-0x0023827c, selects variant*3+6 and blends at 0x0023829c-0x002382cc. It loads 6 at 0x002382b0/0x002382d0 and stores lifecycle +0x20 at 0x002382d4. Existing case 6 of this exact selector chooses the before-timed-idle-restore threshold at 0x002380dc and returns to timed idle, proving reuse of its named member. --- .../update_resident_dialogue_animation_state.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/mobys/animation/update_resident_dialogue_animation_state.c b/src/mobys/animation/update_resident_dialogue_animation_state.c index 189af9ede4..fac998151d 100644 --- a/src/mobys/animation/update_resident_dialogue_animation_state.c +++ b/src/mobys/animation/update_resident_dialogue_animation_state.c @@ -86,7 +86,7 @@ void update_resident_dialogue_animation_state(Moby *resident_moby) { if (resident_moby->anim != 2) { blend_moby_animation(resident_moby, 2, 0, scale_game_frames(0x12)); } - resident_moby->state = 12; + resident_moby->state = RESIDENT_WAIT_TO_START_DIALOGUE_ANIMATION; D_001E63C0.timer = 0; } D_001E63C0.timer++; @@ -96,7 +96,7 @@ void update_resident_dialogue_animation_state(Moby *resident_moby) { if (resident_moby->anim != 3) { blend_moby_animation(resident_moby, 3, 0, scale_game_frames(0x12)); } - resident_moby->state = 3; + resident_moby->state = RESIDENT_WAIT_TO_RESTORE_IDLE_ANIMATION; D_001E63C0.timer = 0; } D_001E63C0.timer++; @@ -106,7 +106,7 @@ void update_resident_dialogue_animation_state(Moby *resident_moby) { if (resident_moby->anim != 0) { blend_moby_animation(resident_moby, 0, 0, scale_game_frames(0x12)); } - resident_moby->state = 0; + resident_moby->state = RESIDENT_IDLE_WAIT_TO_REQUEST_DIALOGUE; } break; case RESIDENT_DIALOGUE_ANIMATION_AFTER_COMPLETION_WAIT: @@ -121,7 +121,7 @@ void update_resident_dialogue_animation_state(Moby *resident_moby) { if (resident_moby->anim != 2) { blend_moby_animation(resident_moby, 2, 0, scale_game_frames(0x12)); } - resident_moby->state = 2; + resident_moby->state = RESIDENT_TIMED_WAIT_TO_RESTORE_IDLE_ANIMATION; D_001E63C0.timer = 0; } break; @@ -137,7 +137,7 @@ void update_resident_dialogue_animation_state(Moby *resident_moby) { if (resident_moby->anim != 2) { blend_moby_animation(resident_moby, 2, 0, scale_game_frames(0x12)); } - resident_moby->state = 2; + resident_moby->state = RESIDENT_TIMED_WAIT_TO_RESTORE_IDLE_ANIMATION; D_001E63C0.timer = 0; } break; @@ -153,7 +153,7 @@ void update_resident_dialogue_animation_state(Moby *resident_moby) { if (resident_moby->anim != 2) { blend_moby_animation(resident_moby, 2, 0, scale_game_frames(0x12)); } - resident_moby->state = 2; + resident_moby->state = RESIDENT_TIMED_WAIT_TO_RESTORE_IDLE_ANIMATION; D_001E63C0.timer = 0; } break; @@ -167,7 +167,7 @@ void update_resident_dialogue_animation_state(Moby *resident_moby) { if (resident_moby->anim != target_animation) { blend_moby_animation(resident_moby, target_animation, 0, scale_game_frames(0xC)); } - resident_moby->state = 4; + resident_moby->state = RESIDENT_DIALOGUE_ANIMATION_AFTER_COMPLETION_WAIT; } break; case RESIDENT_WAIT_TO_START_DIALOGUE_ANIMATION: @@ -178,7 +178,7 @@ void update_resident_dialogue_animation_state(Moby *resident_moby) { if (resident_moby->anim != target_animation) { blend_moby_animation(resident_moby, target_animation, 0, scale_game_frames(0x12)); } - resident_moby->state = 5; + resident_moby->state = RESIDENT_DIALOGUE_ANIMATION_AFTER_START_WAIT; } break; case RESIDENT_WAIT_TO_START_DIALOGUE_ANIMATION_BEFORE_TIMED_IDLE_RESTORE: @@ -189,7 +189,7 @@ void update_resident_dialogue_animation_state(Moby *resident_moby) { if (resident_moby->anim != target_animation) { blend_moby_animation(resident_moby, target_animation, 0, scale_game_frames(0x12)); } - resident_moby->state = 6; + resident_moby->state = RESIDENT_DIALOGUE_ANIMATION_WAIT_TO_RESTORE_TIMED_IDLE; } break; } From fd7aaf8c0b71c57d6aebe55ad07860edd14742ae Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:46:07 +0000 Subject: [PATCH 0838/1502] decomp: clarify names in process_blarg_trooper_damage_and_alerts domain_0_value_0 -> BLARG_TROOPER_INITIALIZE: Retail 0x002e81ec retains the input moby in s2; 0x002e8224 loads its state byte at +0x20 and 0x002e8228 skips speed refresh when zero. The authoritative blarg_trooper_update calls this same function before switching on the same moby->state, whose existing local enum and initialization branch identify 0 as BLARG_TROOPER_INITIALIZE. domain_1_value_2 -> BLARG_TROOPER_WAIT_FOR_ACTIVATION: Retail 0x002e8254-0x002e825c compares the same input moby's +0x20 state byte with 2 to suppress help calls. The checked caller blarg_trooper_update passes that moby before its state dispatch; its existing BLARG_TROOPER_WAIT_FOR_ACTIVATION=2 branch waits for target proximity/limits or command before activating group/path movement. This proves the trooper domain independently of equal-valued Hero constants. domain_2_value_9 -> BLARG_TROOPER_DEATH_FALL: Retail 0x002e8400 loads s3=9 and 0x002e8404-0x002e8408 rejects damage when the input moby's +0x20 state already equals it. The lethal health branch later stores that same s3 at 0x002e8514. The caller dispatches the same moby->state to its existing BLARG_TROOPER_DEATH_FALL=9 branch, which steps falling motion then spawns death effects and removes the trooper. domain_3_value_9 -> BLARG_TROOPER_DEATH_FALL: Retail 0x002e8438-0x002e847c subtracts damage from health and selects the lethal branch when health <=0; after starting fall motion at 0x002e84e8, 0x002e8514 stores s3=9 into the input moby's +0x20 state. The caller's existing BLARG_TROOPER_DEATH_FALL=9 branch handles this same state with falling motion, death effects and removal, proving reuse of that canonical trooper member. domain_4_value_4 -> BLARG_TROOPER_KNOCKBACK_RECOVERY: The positive remaining-health branch at 0x002e8528-0x002e8588 starts nonlethal knockback, then 0x002e8598 loads 4 and 0x002e85b4 stores it into the input moby's state at +0x20; 0x002e85c0 sets the stun timer. The caller's existing BLARG_TROOPER_KNOCKBACK_RECOVERY=4 branch steps the same pvars+0x70 motion and transitions back to approach or shot preparation on completion. --- src/overlays/l12/mobys/blarg_trooper.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/overlays/l12/mobys/blarg_trooper.c b/src/overlays/l12/mobys/blarg_trooper.c index 5fd192f84e..d6a7ad47a2 100644 --- a/src/overlays/l12/mobys/blarg_trooper.c +++ b/src/overlays/l12/mobys/blarg_trooper.c @@ -568,6 +568,12 @@ extern void anim_update_e81e0(struct Moby *, void *) __asm__("FUN_L00_0025d538") more members, hands off inside its clip volume, and takes hits from other classes (dying, or staggering back). */ void process_blarg_trooper_damage_and_alerts(struct Moby *moby) { + enum { + BLARG_TROOPER_INITIALIZE = 0, + BLARG_TROOPER_WAIT_FOR_ACTIVATION = 2, + BLARG_TROOPER_KNOCKBACK_RECOVERY = 4, + BLARG_TROOPER_DEATH_FALL = 9 + }; BlargTrooperVars *trooper_damage_alert_vars = (BlargTrooperVars *)moby->pvars; Vec4 help_direction_or_hit_position; s32 hit; @@ -580,13 +586,13 @@ void process_blarg_trooper_damage_and_alerts(struct Moby *moby) { trooper_damage_alert_vars->reset_alert = 0; trooper_damage_alert_vars->alert_timer = scale_game_frames(0xF0); } - if (moby->state != 0) { + if (moby->state != BLARG_TROOPER_INITIALIZE) { trooper_damage_alert_vars->speed = fast_dec_timer_s16(&trooper_damage_alert_vars->alert_timer) ? trooper_damage_alert_vars->alert_speed : 20.0f; } - if (trooper_damage_alert_vars->call_enabled != 0 && moby->state != 2) { + if (trooper_damage_alert_vars->call_enabled != 0 && moby->state != BLARG_TROOPER_WAIT_FOR_ACTIVATION) { trooper_damage_alert_vars->call_timer++; if (scale_game_frames(0x3C) * 17 < trooper_damage_alert_vars->call_timer) { s32 count = 0; @@ -622,7 +628,7 @@ void process_blarg_trooper_damage_and_alerts(struct Moby *moby) { dmg = 0.0f; resolve_moby_hit_response(moby, coll, &trooper_damage_alert_vars->health, 0, &hit, &dmg, 0, 4); if (coll != 0 && coll->moby->oclass != moby->oclass && coll->moby->oclass != 0xB8 && - moby->state != 9 && dmg != 0.0f) { + moby->state != BLARG_TROOPER_DEATH_FALL && dmg != 0.0f) { if (moby->group != 0xFF) { alert_group_e81e0(moby->group, 1); } @@ -645,7 +651,7 @@ void process_blarg_trooper_damage_and_alerts(struct Moby *moby) { start_fall_e81e0(moby, trooper_damage_alert_vars->fall, 9, 1, 0, angle); trooper_damage_alert_vars->unkC0 = 10.0f; trooper_damage_alert_vars->unkC4 = 19.0f; - moby->state = 9; + moby->state = BLARG_TROOPER_DEATH_FALL; trooper_damage_alert_vars->unk67 = 0x78; anim_reset_e81e0(moby, trooper_damage_alert_vars->anim); } else { @@ -659,7 +665,7 @@ void process_blarg_trooper_damage_and_alerts(struct Moby *moby) { start_fall_e81e0(moby, trooper_damage_alert_vars->fall, 6, 1, 0, unused); trooper_damage_alert_vars->unkC0 = 4.0f; trooper_damage_alert_vars->unkC4 = 8.0f; - moby->state = 4; + moby->state = BLARG_TROOPER_KNOCKBACK_RECOVERY; trooper_damage_alert_vars->unk67 = 0xFA; trooper_damage_alert_vars->stun_timer = scale_game_frames(0x3C); anim_reset_e81e0(moby, trooper_damage_alert_vars->anim); From 3d719f1162b9ae9e4bb3228f47edf3788821fb8e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:46:07 +0000 Subject: [PATCH 0839/1502] decomp: clarify names in emit_debris_trail_particles domain_1_value_0 -> DEBRIS_STATE_FOLLOW_PATH: At retail 0x002e0588-0x002e05b0 the input debris moby's state byte +0x20 selects the zero-state emission offset. Checked caller 0x002dfd10 retains the same moby in s2, tests +0x20 at 0x002dfd38-0x002dfd3c, and for zero loads its pvars path index +0x0C, indexes the spline table and calls sample_path at 0x002dfd7c. It stores path displacement at pvars+0x18/+0x1C then calls this exact function at 0x002dfda8. This matches update_path_or_ballistic_debris in source SHA-256 c247af5c087c146fb224eeb5dd67ece8c426102e87a55827936a2b28cc9e3d52 and proves path-following debris state, unrelated to hero enums. domain_2_value_1 -> DEBRIS_STATE_BALLISTIC: Retail 0x002e0644-0x002e064c compares the same input debris moby state byte +0x20 against exactly 1, enabling planar emission jitter. Checked direct caller 0x002dfd38-0x002dfd3c routes every nonzero value, including 1, to 0x002dfe78: 0x002dfe88 adds pvars+0x30 velocity to position, 0x002dff60-0x002dff7c subtracts gravity from z velocity, and 0x002dff80-0x002dffa4 updates spin. It calls this function with the same moby at 0x002e0140. Supplied update_path_or_ballistic_debris and spawn_path_or_ballistic_debris source corroborate ballistic movement for that state. This names state 1's proven ballistic role without claiming exclusivity among nonzero states. --- src/overlays/shared/enemies/path_or_ballistic_debris.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/path_or_ballistic_debris.c b/src/overlays/shared/enemies/path_or_ballistic_debris.c index b816fd5cf3..4e7fccc426 100644 --- a/src/overlays/shared/enemies/path_or_ballistic_debris.c +++ b/src/overlays/shared/enemies/path_or_ballistic_debris.c @@ -294,6 +294,10 @@ extern Particle_2E17B8 *func_L00_0026DEA0_2E17B8( void *, float, float, float, int, void *, float, int) __asm__("FUN_L00_0026d000"); void emit_debris_trail_particles(Moby *moby) { + enum { + DEBRIS_STATE_FOLLOW_PATH = 0, + DEBRIS_STATE_BALLISTIC = 1 + }; Vec4_2E17B8 pos; Vec4_2E17B8 emission_axis_offset; Vec4_2E17B8 particle_initial_velocity; @@ -342,7 +346,7 @@ void emit_debris_trail_particles(Moby *moby) { particle_initial_velocity.f[1] = debris_motion_state->f1C; particle_initial_velocity.f[2] = 0.0f; particle_initial_velocity.f[3] = 1.0f; - if (moby->state == 0) { + if (moby->state == DEBRIS_STATE_FOLLOW_PATH) { fast_vec_normalize(&emission_axis_offset, &*(Vec4_2E17B8 *)&moby->rot_row2, 0.95f); } else { fast_vec_normalize(&emission_axis_offset, &*(Vec4_2E17B8 *)&moby->rot_row2, 1.15f); @@ -353,7 +357,7 @@ void emit_debris_trail_particles(Moby *moby) { emission_position_offset.f[1] = fast_sin(moby->rot.z) * 0.3f; emission_position_offset.f[2] = 0.0f; fast_vec_add(&pos, &pos, &emission_position_offset); - if (moby->state == 1) { + if (moby->state == DEBRIS_STATE_BALLISTIC) { pos.f[0] += randf_sym(0.0f, 0.1f); pos.f[1] += randf_sym(0.0f, 0.1f); } From 3ef4437311ef4022a5f5a600fade29598e17df68 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:47:59 +0000 Subject: [PATCH 0840/1502] decomp: clarify names in update_bolt_grounded_pose domain_0_value_3 -> BOLT_IDLE: Retail 0x002a6e00 retains the input bolt in s4; 0x002a70bc loads its state byte at +0x20, and 0x002a70c0-0x002a70c4 compares it to 3 before support-loss handling. Authoritative bolt_update in the same source declares BOLT_IDLE=3, switches on bolt_moby->state and passes that same bolt to FUN_L00_002a6de8_c from BOLT_IDLE. Its settling branch assigns BOLT_IDLE when hop_left reaches zero. The guarded retail branch checks ground_moby and hop_left, sets the bolt to falling state 1 at 0x002a7128, initializes velocity/spin and clears support at 0x002a71cc. Thus reuse the established bolt-domain BOLT_IDLE; HeroStateId/HERO_STATE_STOP does not describe this selector. --- src/overlays/shared/pickups/bolt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/pickups/bolt.c b/src/overlays/shared/pickups/bolt.c index 00c108b741..4691e4fc88 100644 --- a/src/overlays/shared/pickups/bolt.c +++ b/src/overlays/shared/pickups/bolt.c @@ -539,6 +539,9 @@ void collect_bolt(struct Moby *bolt) { void update_bolt_grounded_pose(char *moby, void *out1, void *out2) __asm__("FUN_L00_002a6de8"); void update_bolt_grounded_pose(char *moby, void *base_position_output, void *base_rotation_output) { + enum { + BOLT_IDLE = 3 + }; char *grounded_bolt_vars = ((char *)MOBY(moby)->pvars); float local_rotation_basis[12]; float base_rotation_basis[12]; @@ -616,7 +619,7 @@ void update_bolt_grounded_pose(char *moby, void *base_position_output, void *bas qcopy(base_position_output, A); if (base_rotation_output != 0) qcopy(base_rotation_output, B); - if (MOBY(moby)->state == 3) { + if (MOBY(moby)->state == BOLT_IDLE) { char *ground_moby = *(char **)(grounded_bolt_vars + 0x5C); if (ground_moby != 0 && *(unsigned char *)(grounded_bolt_vars + 0x57) == 0) { int should_detach_from_ground; From ab2d963325464356bc501eba6595403b85acbb0f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:47:59 +0000 Subject: [PATCH 0841/1502] decomp: clarify names in resolve_hero_current_position_collisions domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: At 0x0021342c-0x0021343c retail loads hero+0x20B3 (hero.gravity_mode) and tests zero before selecting the direct capsule_bottom z offset at 0x00213490-0x00213494. The same field selects HeroGravityMode in supplied FUN_L00_002334d0 and FUN_L00_00233810; their WORLD_DOWN branches operate directly on world z. Reuse the canonical HeroGravityMode member, value 0. domain_1_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: Retail 0x0021342c loads hero.gravity_mode from hero+0x20B3; 0x00213434/0x00213444 compares that same byte with 1, selecting FUN_L00_00233810 at 0x00213468. Supplied helpers switch on this identical hero.gravity_mode field, and FUN_L00_002334d0's HERO_GRAVITY_OPPOSITE_GROUND_NORMAL branch normalizes ground_normal with -k. The source ground-contact switch also negates ground_normal into gravity_dir for this member. This proves the shared HeroGravityMode domain and canonical value-1 member. domain_2_value_0 -> HERO_GRAVITY_WORLD_DOWN: Retail 0x002135f8-0x002135fc reloads hero+0x20B3, the same hero.gravity_mode byte used by the offset selection at 0x0021342c. Zero branches to ordinary world-down collision paths at 0x002134d8; nonzero uses the frame-scaled sphere at 0x0021361c. Supplied gravity helpers and the ground-contact switch use this exact field as HeroGravityMode, with WORLD_DOWN directly using z and gravity_dir.z=-1. Reuse HERO_GRAVITY_WORLD_DOWN=0. domain_3_value_15 -> HERO_COLLISION_HISTORY_FINAL_ATTEMPT_INDEX: The checked caller 0x002137a8 initializes s0=0 at 0x002137e0 and passes s0 as a0 to this function at 0x002137e8-0x002137ec. It restores a history position on failure, increments s0 at 0x00213848 and loops while s0<16 at 0x0021384c-0x00213850. Thus 15 is its final attempt index. The assigned function preserves a0 in s8 at 0x002133b8 and compares s8 with 15 at 0x00213678-0x0021367c, enabling bounded/normalized correction before returning -1. This is a retry-index domain independent of hero state and control_mode. --- src/overlays/shared/hero/hero_switch_item.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 4a0f3210ef..2a5aa6d945 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -3652,6 +3652,9 @@ extern s32 FUN_L00_001f3170(void *, f32); s32 resolve_hero_current_position_collisions(s32 mode) __asm__("FUN_L00_002133a8"); s32 resolve_hero_current_position_collisions(s32 mode) { + enum { + HERO_COLLISION_HISTORY_FINAL_ATTEMPT_INDEX = 0xF + }; V_2133a8 pre_collision_position; V_2133a8 collision_probe_offset; V_2133a8 collision_correction; @@ -3669,8 +3672,8 @@ s32 resolve_hero_current_position_collisions(s32 mode) { hero.path_constrain_pending = 0; } if (hero.state.control_mode != 0x11) { - if (hero.gravity_mode != 0 || hero.unk1F8 != 0) { - if (hero.gravity_mode == 1 || hero.unk1F8 != 0) { + if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN || hero.unk1F8 != 0) { + if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0) { FUN_L00_00233810(&collision_probe_offset, &collision_probe_offset, 0.6f); } else { FUN_L00_002334d0( @@ -3686,7 +3689,7 @@ s32 resolve_hero_current_position_collisions(s32 mode) { mask = 0xD24; } for (i = 0; i < 8; i++) { - if (hero.gravity_mode != 0) { + if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN) { if (!coll_sphere(&hero.motion.pos.q, mask, ((s32)hero.moby), frame_scale * 0.4f)) break; } else if (hero.state.control_mode == 0x11) { @@ -3721,7 +3724,7 @@ s32 resolve_hero_current_position_collisions(s32 mode) { fast_vec_sub(&collision_correction, &hero.motion.pos.q, &pre_collision_position); probe_height_or_correction_length = fast_vec_length(&collision_correction); if (hero.capsule_radius * 1.5f < probe_height_or_correction_length) { - if (mode == 0xF) { + if (mode == HERO_COLLISION_HISTORY_FINAL_ATTEMPT_INDEX) { if (512.0f < collision_correction.f[0]) collision_correction.f[0] = 512.0f; else if (collision_correction.f[0] < -512.0f) From 8793d6796ca0fd9241e606c23119e42b51564ee1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:47:59 +0000 Subject: [PATCH 0842/1502] decomp: clarify names in update_rail_lift domain_0_value_1 -> LIFT_WAIT_FOR_DEPARTURE: Retail 0x002dcdc4 stores s6=1 to 0x20(s1) after initializing endpoint position, HUD and timer. The same entity state byte is read at 0x002dcd44 and value 1 dispatches to 0x002dcdd4, the source's existing LIFT_WAIT_FOR_DEPARTURE branch handling activation, departure and recall. This assignment therefore reuses that local enum member. domain_1_value_3 -> LIFT_FOLLOW_PATH: Retail 0x002dced4 loads 3 and 0x002dcef0 stores it to the entity state byte 0x20(s1) after initial trigger/autostart activation selects the path endpoint. State dispatch at 0x002dcd70 routes this same byte value 3 to 0x002dcfe8 and rail advancement at 0x002dd01c, already named LIFT_FOLLOW_PATH in the source switch. domain_2_value_2 -> LIFT_WAIT_FOR_HERO_ANIMATION: Retail 0x002dcf7c calls the target-pose request helper, then 0x002dcf8c loads 2 and 0x002dcfa4 stores it to 0x20(s1) after toggling the lift endpoint command. The same state byte dispatches value 2 at 0x002dcd68 to 0x002dcfd0, which polls the target-pose status helper. This is the existing local LIFT_WAIT_FOR_HERO_ANIMATION state. domain_3_value_3 -> LIFT_FOLLOW_PATH: Retail 0x002dcfa8 compares the hero and lift endpoint tests; on disagreement 0x002dcfac loads 3 and 0x002dcfb4 writes it to the entity state byte 0x20(s1), toggling command and clearing ready. The identical byte is switched at 0x002dcd44-0x002dcd70, with 3 selecting rail advancement at 0x002dd01c: the existing LIFT_FOLLOW_PATH member. domain_4_value_3 -> LIFT_FOLLOW_PATH: Retail 0x002dcfd0 polls the hero target-pose status helper; when it returns zero, 0x002dcfdc loads 3 and 0x002dcfe4 stores it to entity state 0x20(s1). State 3 dispatches at 0x002dcd70 to the path-traversal branch calling 0x002d3918 at 0x002dd01c. This is a transition from the existing animation-wait state to existing LIFT_FOLLOW_PATH. domain_5_value_1 -> LIFT_WAIT_FOR_DEPARTURE: Retail 0x002dd01c advances the commanded private rail path; a nonzero completion result reaches 0x002dd02c, which stores s6=1 to entity state 0x20(s1), then sets the post-ride timer. The same state byte's value 1 dispatches at 0x002dcd48 to activation/departure/recall handling at 0x002dcdd4, the existing LIFT_WAIT_FOR_DEPARTURE enum member. --- src/overlays/l03/mobys/rail_lift.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l03/mobys/rail_lift.c b/src/overlays/l03/mobys/rail_lift.c index a3fe3c6694..03308d0553 100644 --- a/src/overlays/l03/mobys/rail_lift.c +++ b/src/overlays/l03/mobys/rail_lift.c @@ -127,7 +127,7 @@ void rail_lift_update(struct Moby *lift_moby) { qcopy(&lift_moby->pos, &(l03_paths[lift_vars->path[lift_moby->command]])->points[0]); lift_vars->hud = -1; lift_vars->timer = 0; - lift_moby->state = 1; + lift_moby->state = LIFT_WAIT_FOR_DEPARTURE; lift_moby->update_dist = 0xFF; lift_moby->draw_dist = 0xFF; break; @@ -144,7 +144,7 @@ void rail_lift_update(struct Moby *lift_moby) { lift_moby->flags &= 0xFFBE; *(u128 *)&lift_moby->pos = *(u128 *)&(l03_paths[lift_vars->path[hero_end]])->points[0]; - lift_moby->state = 3; + lift_moby->state = LIFT_FOLLOW_PATH; lift_vars->unk64 = 1; lift_vars->started = 1; lift_vars->ready = 0; @@ -162,10 +162,10 @@ void rail_lift_update(struct Moby *lift_moby) { lift_moby->command ^= 1; lift_vars->unk64 = 1; lift_vars->ready = 0; - lift_moby->state = 2; + lift_moby->state = LIFT_WAIT_FOR_HERO_ANIMATION; } } else if (hero_end != lift_end) { - lift_moby->state = 3; + lift_moby->state = LIFT_FOLLOW_PATH; lift_moby->command ^= 1; lift_vars->unk64 = 1; lift_vars->ready = 0; @@ -173,7 +173,7 @@ void rail_lift_update(struct Moby *lift_moby) { break; case LIFT_WAIT_FOR_HERO_ANIMATION: if (!get_hero_target_pose_status()) - lift_moby->state = 3; + lift_moby->state = LIFT_FOLLOW_PATH; break; case LIFT_FOLLOW_PATH: if (is_hero_on_moby(lift_moby)) { @@ -182,7 +182,7 @@ void rail_lift_update(struct Moby *lift_moby) { } if (advance_moby_along_rail_path( lift_moby, lift_vars->path[lift_moby->command], &lift_vars->snd)) { - lift_moby->state = 1; + lift_moby->state = LIFT_WAIT_FOR_DEPARTURE; lift_vars->timer = scale_game_frames(0xF); } break; From 1b21e5072fc642e3ed9b70f8a1d8a6a48a44f84b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:48:00 +0000 Subject: [PATCH 0843/1502] decomp: clarify names in update_veldin_robot_damage_and_targeting domain_0_value_0 -> VELDIN_ROBOT_STATE_INITIALIZE: Retail 0x002e1684 preserves the incoming robot as s3, and 0x002e169c-0x002e16a4 reads its state byte at +0x20 and returns for zero. The supplied caller veldin_robot_enemy_update passes this same ElectroidMoby pointer before switching on moby->state, whose existing VELDIN_ROBOT_STATE_INITIALIZE=0 case initializes spawnPos, health and path state. Thus this is the identical robot-state domain, not HeroStateId. domain_1_value_8 -> VELDIN_ROBOT_STATE_DEATH_KNOCKBACK: Retail 0x002e1728-0x002e172c tests the incoming robot's state byte at s3+0x20 against 8 and skips additional damage response. The lethal branch writes 8 to this same byte at 0x002e1838. The supplied caller switches on this exact moby->state after invoking the helper; its existing VELDIN_ROBOT_STATE_DEATH_KNOCKBACK=8 case steps motion, spawns break fragments and removes the robot. domain_2_value_8 -> VELDIN_ROBOT_STATE_DEATH_KNOCKBACK: Retail 0x002e1784-0x002e17c0 subtracts damage from health and selects the lethal branch for health <= 0. After trooper_start_knockback at 0x002e180c, 0x002e1838 stores 8 into the original robot's state at s3+0x20. The supplied caller consumes that same field in its established VELDIN_ROBOT_STATE_DEATH_KNOCKBACK=8 case, stepping motion before fragment spawning and removal. domain_3_value_7 -> VELDIN_ROBOT_STATE_DAMAGE_KNOCKBACK: The nonlethal branch at retail 0x002e1860 follows the positive-health outcome of 0x002e17a4-0x002e17c0, scales knockback and calls trooper_start_knockback at 0x002e18cc. At 0x002e18dc-0x002e18f0 it writes 7 to the original robot state byte s3+0x20. The supplied caller passes this same robot and handles that field with existing VELDIN_ROBOT_STATE_DAMAGE_KNOCKBACK=7, stepping motion then returning to face-target state. domain_4_value_1 -> VELDIN_ROBOT_STATE_WAIT_TO_FOLLOW_PATH: Retail 0x002e1928-0x002e1930 reads the original robot state s3+0x20 and compares it to 1. That branch loads toad_paths[vars->unk1B4] and supplies its count and points to follow_5968 for vars->targetPos at 0x002e1938-0x002e1970. The same pointer is passed by veldin_robot_enemy_update before its moby->state switch; its existing VELDIN_ROBOT_STATE_WAIT_TO_FOLLOW_PATH=1 case waits for unk114 before entering FOLLOW_PATH. domain_5_value_5 -> VELDIN_ROBOT_STATE_PROCESS_COLLISION_PROBES: Retail 0x002e1928 reads this robot's state byte, 0x002e1934 loads 5, and 0x002e197c skips select_moby_combat_target when that state equals 5. The supplied caller invokes this helper with the same ElectroidMoby pointer then switches on the same moby->state. Its existing VELDIN_ROBOT_STATE_PROCESS_COLLISION_PROBES=5 case aims using vars->targetPos and performs collision_line probes and beam endpoint updates, proving the shared robot-state domain. --- src/overlays/l00/mobys/veldin_robot_enemy.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l00/mobys/veldin_robot_enemy.c b/src/overlays/l00/mobys/veldin_robot_enemy.c index f7b42b6899..5e4391bc4f 100644 --- a/src/overlays/l00/mobys/veldin_robot_enemy.c +++ b/src/overlays/l00/mobys/veldin_robot_enemy.c @@ -436,7 +436,7 @@ f32 veldin_robot_knockback_xy_scale_gp __asm__("D_L00_00161BDC") = 1e+01 f32 veldin_robot_knockback_z_scale_gp __asm__("D_L00_00161BE0") = 9.5f; void update_veldin_robot_damage_and_targeting(ElectroidMoby *moby) { - ElectroidVars *vars; + enum { VELDIN_ROBOT_STATE_INITIALIZE = 0 , VELDIN_ROBOT_STATE_WAIT_TO_FOLLOW_PATH = 1 , VELDIN_ROBOT_STATE_PROCESS_COLLISION_PROBES = 5 , VELDIN_ROBOT_STATE_DAMAGE_KNOCKBACK = 7 , VELDIN_ROBOT_STATE_DEATH_KNOCKBACK = 8 } ;ElectroidVars *vars; void *anim; ElectroidHit *coll; Path *path; @@ -450,7 +450,7 @@ void update_veldin_robot_damage_and_targeting(ElectroidMoby *moby) { f32 range; vars = moby->vars; - if (moby->state == 0) { + if (moby->state == VELDIN_ROBOT_STATE_INITIALIZE) { return; } if (vars->unk38 != 0) { @@ -462,7 +462,7 @@ void update_veldin_robot_damage_and_targeting(ElectroidMoby *moby) { dmg = 0.0f; coll = find_moby_hit(moby, 0x330000, 0); hit_reaction(moby, coll, &vars->health, 0, &hit, &dmg, 0, 4); - if (hit != 1 && moby->state != 8 && dmg != 0.0f) { + if (hit != 1 && moby->state != VELDIN_ROBOT_STATE_DEATH_KNOCKBACK && dmg != 0.0f) { vars->health -= dmg; vars->unk90 = 0x200; vars->unk80 = veldin_robot_knockback_gravity_gp * frame_time_sq; @@ -481,7 +481,7 @@ void update_veldin_robot_damage_and_targeting(ElectroidMoby *moby) { trooper_start_knockback(moby, vars->unk70, 0xB, 1, 0, angle); vars->unkC0 = 7.0f; vars->unkC4 = 16.0f; - moby->state = 8; + moby->state = VELDIN_ROBOT_STATE_DEATH_KNOCKBACK; moby->unk94 = 0; vars->unk67 = 0x78; trooper_anim_update(moby, anim); @@ -494,7 +494,7 @@ void update_veldin_robot_damage_and_targeting(ElectroidMoby *moby) { trooper_start_knockback( moby, vars->unk70, 8, 1, 0, fast_arc_tan(coll->pos.f[0], coll->pos.f[1])); vars->unkC4 = vars->unkC0 = -1.0f; - moby->state = 7; + moby->state = VELDIN_ROBOT_STATE_DAMAGE_KNOCKBACK; vars->unk67 = 0xFA; vars->unk26 = scale_game_frames(0x3C); trooper_anim_update(moby, anim); @@ -503,10 +503,10 @@ void update_veldin_robot_damage_and_targeting(ElectroidMoby *moby) { } moby->unkA4 = 0xFF; trooper_anim_finish(moby, anim); - if (moby->state == 1) { + if (moby->state == VELDIN_ROBOT_STATE_WAIT_TO_FOLLOW_PATH) { path = toad_paths[vars->unk1B4]; FUN_L00_0025ff38(moby, &vars->targetPos, 0, 0, path->pts, path->count, 64.0f); - } else if (moby->state != 5) { + } else if (moby->state != VELDIN_ROBOT_STATE_PROCESS_COLLISION_PROBES) { range = veldin_robot_default_target_range_gp; if (vars->unk1DA != 0) { range = 37.0f; From 8adc819d208dacde08e4f2a153da024ccc4e835e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:48:00 +0000 Subject: [PATCH 0844/1502] decomp: clarify names in draw_four_sky_shells_with_animated_particles domain_0_value_0 -> FOUR_SHELL_PARTICLE_PHASE_ORBIT: Retail 0x00289658 stores zero to particle+0 for indices 246..255; 0x00289660-0x00289680 seeds halfwords +0xC/+0xE. The same type byte is tested at 0x00289808-0x0028980C; zero advances both phases and derives x/y/z from sine/cosine at 0x00289814-0x002898BC, proving phase-orbit particle behavior. domain_1_value_3 -> FOUR_SHELL_PARTICLE_RANDOM_COLOR: Retail 0x00289694 stores 3 at particle+0, and 0x0028976C-0x002897B4 packs a randomized base color at particle+0xC. The type-3 comparison at 0x002898D8 selects rand() high-half masks and offsets added to that stored base and written to particle color +4 at 0x002898E0-0x00289920; source and Ghidra agree. domain_2_value_0 -> FOUR_SHELL_PARTICLE_PHASE_ORBIT: The lbu of particle+0 at 0x00289808 and zero comparison at 0x0028980C select the particles initialized to zero at 0x00289658. This branch increments halfwords +0xC/+0xE, converts their masked phases to radians, and updates x/y/z through sine/cosine at 0x00289814-0x002898BC, so assignment and comparison share the phase-orbit constant. domain_3_value_3 -> FOUR_SHELL_PARTICLE_RANDOM_COLOR: Retail loads comparison value 3 at 0x00289810 and compares it to the particle type byte at 0x002898D8. The selected branch at 0x002898E0-0x00289920 adds three masked random offsets to the packed base color from particle+0xC and stores particle+4. It handles the same type assigned 3 at 0x00289694, proving the shared randomized-color constant. --- .../shared/rendering/sky/sky_particle_effects.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/rendering/sky/sky_particle_effects.c b/src/overlays/shared/rendering/sky/sky_particle_effects.c index e8d11ef5e9..24a4ac1b15 100644 --- a/src/overlays/shared/rendering/sky/sky_particle_effects.c +++ b/src/overlays/shared/rendering/sky/sky_particle_effects.c @@ -178,6 +178,10 @@ extern char D_L00_001BD7E0[] __asm__("D_L00_001BD7E0"); void draw_four_sky_shells_with_animated_particles(void) __asm__("FUN_L00_002895a0"); void draw_four_sky_shells_with_animated_particles(void) { + enum { + FOUR_SHELL_PARTICLE_PHASE_ORBIT = 0, + FOUR_SHELL_PARTICLE_RANDOM_COLOR = 3 + }; int i, j; SkyParticle *particle; f32 a, polar_angle_radians; @@ -192,7 +196,7 @@ void draw_four_sky_shells_with_animated_particles(void) { particle = &SKY->stars[i]; if (i >= 0xF6) { u16 *h; - particle->type = 0; + particle->type = FOUR_SHELL_PARTICLE_PHASE_ORBIT; h = &particle->c.h.a; h[0] = rand() >> 16; h[1] = rand() >> 16; @@ -200,7 +204,7 @@ void draw_four_sky_shells_with_animated_particles(void) { particle->b3 = 0x48; particle->f1C = 0.16f; } else { - particle->type = 3; + particle->type = FOUR_SHELL_PARTICLE_RANDOM_COLOR; particle->c.h.a = random_integer_below(0x100); { int random_high_half = rand() >> 16; @@ -235,7 +239,7 @@ void draw_four_sky_shells_with_animated_particles(void) { } for (j = 0; j < SKY->count; j++) { particle = &SKY->stars[j]; - if (particle->type == 0) { + if (particle->type == FOUR_SHELL_PARTICLE_PHASE_ORBIT) { u16 *h = &particle->c.h.a; h[0]++; h[1]++; @@ -248,7 +252,7 @@ void draw_four_sky_shells_with_animated_particles(void) { particle->color = 0x702020F0; else particle->color = 0x202020F0; - } else if (particle->type == 3) { + } else if (particle->type == FOUR_SHELL_PARTICLE_RANDOM_COLOR) { random_color_bits = rand() >> 16; { u32 u = ((random_color_bits & 0x1F00) << 10) + 0xFFDFDFE0; From ace34be55f56dd11a52649ed0daacffdc9920aa1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:48:00 +0000 Subject: [PATCH 0845/1502] decomp: clarify names in update_unfolding_column domain_0_value_1 -> UNFOLDING_COLUMN_WAIT_FOR_TRIGGER: Retail 0x00305e6c-0x00305e80 tests the pivot pointer and writes 1 to controller s4+0x20 after initialization. The same byte is loaded at 0x00305d58 and value 1 dispatches to 0x00305e84, which waits on the indexed trigger moby's state. This is exactly the supplied switch(moby->state) local member UNFOLDING_COLUMN_WAIT_FOR_TRIGGER. domain_1_value_2 -> UNFOLDING_COLUMN_UNFOLD_PIECES: Retail 0x00305e84-0x00305ea8 checks the separately indexed trigger and writes 2 to controller s4+0x20; 0x00305eac-0x00305ef8 initializes piece index 5, timer and reciprocal duration. The controller's value 2 dispatches at 0x00305d80 to 0x00305f04, interpolating each selected piece+0x44 sequentially. This matches the existing local UNFOLDING_COLUMN_UNFOLD_PIECES case on that same controller byte. domain_2_value_3 -> UNFOLDING_COLUMN_SWING_PIVOT: Retail 0x00305f64-0x00305f7c decrements the current piece index and writes 3 to controller s4+0x20 once it is negative, then initializes the pivot-swing countdown at 0x00305f80-0x00305fac. Value 3 dispatches at 0x00305d88 to 0x00305fd4; 0x00306028-0x00306098 rotates the pivot and repositions its six pieces. This is the existing local UNFOLDING_COLUMN_SWING_PIVOT case for the same moby->state selector. domain_3_value_4 -> UNFOLDING_COLUMN_COMPLETE: Retail 0x003060a0-0x003060a4 requires the pivot swing timer to expire before 0x003060ac-0x003060f4 releases any owned active voice and clears its handle. 0x003060f0-0x003060fc then writes 4 to controller s4+0x20, and 0x00306100-0x00306120 releases all six pieces by setting their separate states to 2. Controller dispatch 0x00305d58-0x00305d94 handles only states 0 through 3, so 4 marks completion of this unfolding sequence; it is unrelated to VOICE_SLOT_STOP_REQUESTED. --- src/overlays/l14/mobys/unfolding_column.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/overlays/l14/mobys/unfolding_column.c b/src/overlays/l14/mobys/unfolding_column.c index 9ecc92876b..fb5da5cf4f 100644 --- a/src/overlays/l14/mobys/unfolding_column.c +++ b/src/overlays/l14/mobys/unfolding_column.c @@ -78,6 +78,9 @@ void unfolding_column_update(UnfoldingColumnMoby *moby) { UNFOLDING_COLUMN_UNFOLD_PIECES = 2, UNFOLDING_COLUMN_SWING_PIVOT = 3 }; + enum { + UNFOLDING_COLUMN_COMPLETE = 4 + }; UnfoldingColumnVars *data = moby->data; float position_offset[4]; @@ -103,13 +106,13 @@ void unfolding_column_update(UnfoldingColumnMoby *moby) { } data->voice = -1; if (data->pivot != 0) { - moby->state = 1; + moby->state = UNFOLDING_COLUMN_WAIT_FOR_TRIGGER; } break; } case UNFOLDING_COLUMN_WAIT_FOR_TRIGGER: if (((UnfoldingColumnMoby *)(D_L14_0015FFD8_c + (data->trigger << 8)))->state == 2) { - moby->state = 2; + moby->state = UNFOLDING_COLUMN_UNFOLD_PIECES; data->cur = 5; data->timer = scale_game_frames(unfolding_column_piece_unfold_frames); data->rate = 1.0f / convert_integer_to_float(data->timer); @@ -126,7 +129,7 @@ void unfolding_column_update(UnfoldingColumnMoby *moby) { data->timer = scale_game_frames(unfolding_column_piece_unfold_frames); data->cur--; if (data->cur < 0) { - moby->state = 3; + moby->state = UNFOLDING_COLUMN_SWING_PIVOT; data->timer = scale_game_frames(unfolding_column_pivot_swing_frames); data->rate = 1.0f / convert_integer_to_float(data->timer); } else { @@ -166,7 +169,7 @@ void unfolding_column_update(UnfoldingColumnMoby *moby) { } } data->voice = -1; - moby->state = 4; + moby->state = UNFOLDING_COLUMN_COMPLETE; for (j = 0; j < 6; j++) { pieces[j]->state = 2; } From 1e475efc13c7f919001a3c1b640c73dfef155506 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:48:00 +0000 Subject: [PATCH 0846/1502] decomp: clarify names in resolve_hero_position_collisions domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Authoritative C compares hero.gravity_mode != 0. Retail 0x00240f58 loads hero+0x20b3 (0x00141403) into a0; 0x00240f90 tests that byte against zero. Original Ghidra cRam00141403 confirms the same selector. With unk1F8 zero, zero selects the direct world-Z capsule_bottom offset at 0x00240ffc-0x00241000. This is the same hero.gravity_mode used by update_hero_ground_contact's HERO_GRAVITY_WORLD_DOWN arm setting gravity_dir.z=-1 and by the supplied gravity helpers; reuse HeroGravityMode's canonical zero member. domain_1_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: Retail 0x00240f58 loads hero.gravity_mode from hero+0x20b3; 0x00240fa0 sets v0=1 and 0x00240fa4 compares that same a0 byte with v0, selecting the rotated 0.6 offset helper at 0x00240fd4. Original Ghidra tests cRam00141403=='\x01'. Authoritative source and supplied helper context bind this selector to hero.gravity_mode, whose canonical HeroGravityMode member 1 is HERO_GRAVITY_OPPOSITE_GROUND_NORMAL. In the same source update_hero_ground_contact uses this member to copy and negate ground_normal into gravity_dir, proving the exact shared domain. domain_2_value_0 -> HERO_GRAVITY_WORLD_DOWN: The loop's hero.gravity_mode != 0 is implemented at 0x0024115c by lbu v0,0x20b3(s0), with s0=hero, and 0x00241160 branches on zero to the control-mode/capsule query path. Nonzero instead reaches the frame_scale*0.4 sphere query at 0x00241180. Original Ghidra tests the same cRam00141403 byte. This is the identical hero.gravity_mode selector as the preceding offset tests and the source's named gravity switch, where HERO_GRAVITY_WORLD_DOWN sets gravity_dir.z=-1; reuse the canonical HeroGravityMode zero member. --- src/overlays/l05/hero/apply_hero_ground_material_effects.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l05/hero/apply_hero_ground_material_effects.c b/src/overlays/l05/hero/apply_hero_ground_material_effects.c index f53ccc02dc..089cb4d08d 100644 --- a/src/overlays/l05/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l05/hero/apply_hero_ground_material_effects.c @@ -393,8 +393,8 @@ s32 resolve_hero_position_collisions(s32 mode) { if (hero.state.control_mode == 0x16) { transform_hero_local_offset_to_world(&collision_query_offset, 0.0f, 0.0f, 0.7f); fast_vec_sub(&collision_query_offset, &collision_query_offset, &hero.motion.pos.q); - } else if (hero.gravity_mode != 0 || hero.unk1F8 != 0) { - if (hero.gravity_mode == 1 || hero.unk1F8 != 0 || + } else if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN || hero.unk1F8 != 0) { + if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0 || (unsigned)(hero.state.control_mode - 0x15) < 2) { FUN_L00_00233810(&collision_query_offset, &collision_query_offset, 0.6f); } else { @@ -411,7 +411,7 @@ s32 resolve_hero_position_collisions(s32 mode) { mask = 0xD24; } for (i = 0; i < 8; i++) { - if (hero.gravity_mode != 0) { + if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN) { if (!coll_sphere(&hero.motion.pos.q, mask, ((s32)hero.moby), frame_scale * 0.4f)) break; } else if (hero.state.control_mode == 0x11) { From 84fbe2d1e0939197593db26c83568b32c0a708b5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:48:00 +0000 Subject: [PATCH 0847/1502] decomp: clarify names in update_triggered_moby_motion_and_manipulator_angle domain_0_value_7 -> MOBY_MOTION_SEQUENCE_COMPLETE: Authoritative SHA-256 dc1f4983b6781044ebdc50982dec8f2b1fb5c57d2f2844de12e60b5281e95d17 C assigns this literal to MOBY(moby)->state after MOBY_SETTLE_AT_UPPER_MANIPULATOR_ANGLE reaches its endpoint following the bounce. Original retail decompilation agrees: 00316508 compares the clamped angle with f20, 00316518-00316524 selects 7 only for state 5, and 00316528 stores it to moby+0x20. Retail 00316278-00316280 reads the same state byte and skips the entire update for values >=7. Together with the other completion assignment, this proves completion of this function's motion/manipulator sequence, without assuming gameplay meaning. domain_1_value_7 -> MOBY_MOTION_SEQUENCE_COMPLETE: The SHA-bound current C and original retail decompilation assign 7 to the same MOBY(moby)->state domain after MOBY_MOVE_TO_OFFSET_POSITION reaches its vector target. Retail 00316624-00316648 tests target distance <0.0001; 00316650-00316654 confirms state 3, 0031665c-00316668 plays voice entry 1, and 0031666c-00316674 stores 7 to moby+0x20. The dispatch guard at 00316278-00316280 skips all updates for state 7. The return-to-saved-position path instead selects upper-angle settling at 00316678 and then the other assignment of this same completion state, proving a common sequence-complete meaning. --- src/overlays/l05/mobys/triggered_motion.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l05/mobys/triggered_motion.c b/src/overlays/l05/mobys/triggered_motion.c index ddea5dedc6..efaa27e20b 100644 --- a/src/overlays/l05/mobys/triggered_motion.c +++ b/src/overlays/l05/mobys/triggered_motion.c @@ -43,7 +43,7 @@ void triggered_motion_update(char *moby) { MOBY_RETURN_TO_SAVED_POSITION = 4, MOBY_SETTLE_AT_UPPER_MANIPULATOR_ANGLE = 5, MOBY_SETTLE_AT_ZERO_MANIPULATOR_ANGLE = 6 - }; + } ; enum { MOBY_MOTION_SEQUENCE_COMPLETE = 7}; TriggeredMotionVars *motion_and_manipulator_vars = (TriggeredMotionVars *)MOBY(moby)->pvars; float target[4]; float delta[4]; @@ -116,7 +116,7 @@ void triggered_motion_update(char *moby) { motion_and_manipulator_vars->unk64 *= -0.33f; } else if (motion_and_manipulator_vars->unk60 == end) { if (MOBY(moby)->state == MOBY_SETTLE_AT_UPPER_MANIPULATOR_ANGLE) - MOBY(moby)->state = 7; + MOBY(moby)->state = MOBY_MOTION_SEQUENCE_COMPLETE; else MOBY(moby)->state = MOBY_MOVE_TO_OFFSET_POSITION; } @@ -147,7 +147,7 @@ void triggered_motion_update(char *moby) { return; if (MOBY(moby)->state == MOBY_MOVE_TO_OFFSET_POSITION) { allocate_voice_for_target_entry(1, 0, moby); - MOBY(moby)->state = 7; + MOBY(moby)->state = MOBY_MOTION_SEQUENCE_COMPLETE; return; } MOBY(moby)->state = MOBY_SETTLE_AT_UPPER_MANIPULATOR_ANGLE; From c583ae1ab3d248db44d82572126d4c364635b811 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:49:49 +0000 Subject: [PATCH 0848/1502] decomp: clarify names in handle_psytcopus_hits domain_0_value_8 -> PSYTCOPUS_STATE_DEATH_KNOCKBACK: Retail 003106a4 binds the input Moby to s2; 00310770 loads its state byte at s2+0x20, and 00310774-00310778 compares it with 8 to bypass further damage/reaction setup. The same field is assigned 8 at 003109ac after death knockback setup. Bound psytcopus_update calls this handler before switching on this same psytcopus->state, with existing PSYTCOPUS_STATE_DEATH_KNOCKBACK=8 updating knockback before explosion/removal. This proves the Moby-state domain, distinct from hit_reaction and HeroStateId. domain_1_value_7 -> PSYTCOPUS_STATE_KNOCKBACK: Retail 00310898-003108ac initializes knockback using input Moby s2, pvars+0x70 and reaction 5; 003108b0 loads 7 and 003108b8 stores it to the Moby state byte s2+0x20. Original Ghidra agrees with the bound C psytcopus->state=7. In the authoritative caller psytcopus_update, the same field is switched after handle_psytcopus_hits and existing PSYTCOPUS_STATE_KNOCKBACK=7 advances that same pvars+0x70 block, recovering or removing the moby according to motion flags. This is the psytcopus state, not the hit-response selector. domain_2_value_8 -> PSYTCOPUS_STATE_DEATH_KNOCKBACK: Original retail Ghidra groups death reactions 1/2 in the branch at 003108f0. Retail 0031092c-00310930 clears flag 0x1000, 0031098c-003109a0 starts knockback reaction 6 using pvars+0x70, and 003109a4/003109ac stores 8 to the input Moby state byte s2+0x20. The bound caller psytcopus_update switches on that same psytcopus->state after this handler, with existing PSYTCOPUS_STATE_DEATH_KNOCKBACK=8 advancing knockback and then exploding/removing the moby. It is the same state tested by the earlier guard. --- src/overlays/l11/mobys/psytcopus.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l11/mobys/psytcopus.c b/src/overlays/l11/mobys/psytcopus.c index 8ab387ffe7..ee03e2bbe6 100644 --- a/src/overlays/l11/mobys/psytcopus.c +++ b/src/overlays/l11/mobys/psytcopus.c @@ -276,6 +276,10 @@ void handle_psytcopus_hits(struct Moby *psytcopus) { HIT_REACTION_HURT_WITHOUT_STATE_CHANGE = 10, HIT_REACTION_NO_RESPONSE = 11 }; + enum { + PSYTCOPUS_STATE_KNOCKBACK = 7, + PSYTCOPUS_STATE_DEATH_KNOCKBACK = 8 + }; struct PokiPathVars *psytcopus_vars = (struct PokiPathVars *)psytcopus->pvars; Vec4f projectile_and_hit_vector_scratch; int hits; @@ -304,7 +308,7 @@ void handle_psytcopus_hits(struct Moby *psytcopus) { psytcopus_hit_record = find_moby_hit(psytcopus, 0x330000, 0); hit_reaction = resolve_moby_hit_response( psytcopus, psytcopus_hit_record, &psytcopus_vars->health, 0, &hits, &damage, 0, 4); - if (hits != 1 && psytcopus->state != 8) { + if (hits != 1 && psytcopus->state != PSYTCOPUS_STATE_DEATH_KNOCKBACK) { psytcopus_vars->health -= damage; if (psytcopus_vars->health <= 0.0f) { hit_reaction = 1; @@ -343,7 +347,7 @@ void handle_psytcopus_hits(struct Moby *psytcopus) { &psytcopus_vars->unk88, &psytcopus_vars->unk8C); FUN_L00_0025c558_p(psytcopus, psytcopus_vars->unk70, 5, 1, 0, angle1); - psytcopus->state = 7; + psytcopus->state = PSYTCOPUS_STATE_KNOCKBACK; psytcopus_vars->unk67 = 0x78; if (psytcopus_vars->unk160 != 0) { FUN_L00_002371e0_p(psytcopus_vars->unk160); @@ -369,7 +373,7 @@ void handle_psytcopus_hits(struct Moby *psytcopus) { &psytcopus_vars->unk88, &psytcopus_vars->unk8C); FUN_L00_0025c558_p(psytcopus, psytcopus_vars->unk70, 6, 1, 0, angle2); - psytcopus->state = 8; + psytcopus->state = PSYTCOPUS_STATE_DEATH_KNOCKBACK; psytcopus_vars->unk67 = 0xF0; if (psytcopus_vars->unk160 != 0) { FUN_L00_002371e0_p(psytcopus_vars->unk160); From 94e40c07b6a23fbf10599547bc2b9bcf15b1313c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:49:49 +0000 Subject: [PATCH 0849/1502] decomp: clarify names in update_path_following_moby domain_0_value_2 -> MOBY_STATE_FALLING: Retail 0x002deb44 loads 2; 0x002deb48 loads the incoming moby's state byte at s2+0x20, and 0x002deb4c skips hit-triggered velocity initialization when equal. This is the same s2+0x20 selector loaded at 0x002de894 and dispatched via 0x002de8c8 to the falling branch at 0x002de9c4. That branch subtracts gravity from private velocity z at 0x002de9d0-0x002de9fc, adds velocity to position at 0x002dea38 and removes below the height threshold or on collision. The hit path seeds velocity and writes 2 to that same state byte at 0x002dec40-0x002dec44. Bound C already declares MOBY_STATE_FALLING=2 for this exact switch domain, proving canonical member reuse rather than numerical coincidence. --- src/overlays/l08/mobys/path_following_moby.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/path_following_moby.c b/src/overlays/l08/mobys/path_following_moby.c index 8e65986b59..f5e971a303 100644 --- a/src/overlays/l08/mobys/path_following_moby.c +++ b/src/overlays/l08/mobys/path_following_moby.c @@ -197,7 +197,7 @@ void path_following_moby_update(char *moby) { } else { MOBY(moby)->collision = MOBY(moby)->pclass->collision; } - if (find_moby_hit(moby, 0x10000, 0) != 0 && MOBY(moby)->state != 2) { + if (find_moby_hit(moby, 0x10000, 0) != 0 && MOBY(moby)->state != MOBY_STATE_FALLING) { if (camera_secondary_mode_lui == 0x32 && D_0013D408[0xC] == 0) { D_0013D408[0xC] = 1; allocate_voice_for_bank_entry(1, 0, 0); From 68311104dfa72fec1eee3f166de4e497ca222bf6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:49:50 +0000 Subject: [PATCH 0850/1502] decomp: clarify names in thruster_pack_lock_red_update domain_0_value_1 -> STATE_APPROACH_CONFIGURED_HEIGHT: Retail 0x002d7b80-0x002d7b88 stores 1 to moby+0x20, the exact byte read by the switch at 0x002d7b38. The authoritative local enum already names that same selector's case 1 STATE_APPROACH_CONFIGURED_HEIGHT; retail 0x002d7ba8-0x002d7be8 approaches saved z plus the configured offset. domain_1_value_4 -> STATE_WAIT_FOR_DEPRESSION_TRIGGER: Retail 0x002d7ba0-0x002d7ba4 selects 4 for the shared state store at 0x002d7f48, writing moby+0x20 read by the switch. Its existing case STATE_WAIT_FOR_DEPRESSION_TRIGGER checks grounded hero contact at 0x002d7d14-0x002d7d38, then selects 5 and lowers z by 1.5 at 0x002d7d3c-0x002d7d6c. domain_2_value_3 -> STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT: Retail 0x002d7c74-0x002d7c80 writes 3 to the switched moby+0x20 after case 2's grounded-contact checks, ending the wait and releasing its voice. The same moby-state case 3 is already STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT and shares the accelerated height approach at 0x002d7ba8-0x002d7be8. Supplied end-wait and poll/rearm source confirms this transition. domain_3_value_5 -> STATE_SETTLE_DEPRESSED_HEIGHT: Retail 0x002d7d40-0x002d7d50 stores 5 to moby+0x20 on the depression trigger and lowers z by 1.5 at 0x002d7d58-0x002d7d6c. That is the exact selector of the existing local case STATE_SETTLE_DEPRESSED_HEIGHT, whose retail 0x002d7f0c-0x002d7f48 approaches saved initial z minus 1.5. domain_4_value_6 -> STATE_DEPRESSED_HEIGHT_SETTLED: Retail 0x002d7f0c-0x002d7f2c approaches moby z toward pvars+0x64 minus 1.5 with step 0.15. At 0x002d7f38-0x002d7f48 it stores 6 to the switched moby+0x20 only when the approach return equals zero; a nonzero return exits without changing state. Original decompilation and authoritative STATE_SETTLE_DEPRESSED_HEIGHT case agree that this marks completion of depressed-height settling. --- src/overlays/l18/mobys/thruster_pack_lock_red.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l18/mobys/thruster_pack_lock_red.c b/src/overlays/l18/mobys/thruster_pack_lock_red.c index 8c5a2579f0..cfa429f6b5 100644 --- a/src/overlays/l18/mobys/thruster_pack_lock_red.c +++ b/src/overlays/l18/mobys/thruster_pack_lock_red.c @@ -56,7 +56,7 @@ void thruster_pack_lock_red_update(struct Moby *moby) { STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT = 3, STATE_WAIT_FOR_DEPRESSION_TRIGGER = 4, STATE_SETTLE_DEPRESSED_HEIGHT = 5 - }; + } ; enum { STATE_DEPRESSED_HEIGHT_SETTLED = 6}; char *thruster_pack_lock_red_private_vars = (char *)moby->pvars; int index; @@ -65,11 +65,11 @@ void thruster_pack_lock_red_update(struct Moby *moby) { *(float *)(thruster_pack_lock_red_private_vars + 0x64) = moby->pos.z; *(unsigned short *)(thruster_pack_lock_red_private_vars + 0x3E) |= 8; if (*(int *)(thruster_pack_lock_red_private_vars + 0x60) != 0) { - moby->state = 1; + moby->state = STATE_APPROACH_CONFIGURED_HEIGHT; moby->scale = moby->pclass->scale * l18_thruster_pack_lock_red_scale_multiplier; return; } - moby->state = 4; + moby->state = STATE_WAIT_FOR_DEPRESSION_TRIGGER; return; case STATE_APPROACH_CONFIGURED_HEIGHT: case STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT: @@ -91,7 +91,7 @@ void thruster_pack_lock_red_update(struct Moby *moby) { frame_time_sq * 10.0f, frame_time * 20.0f); if (hero.air_frames.s == 0 && hero.ground_moby == moby && hero.state.current == 0x22) { - moby->state = 3; + moby->state = STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT; allocate_voice_for_target_entry(0, 0, (int)moby); index = *(int *)(thruster_pack_lock_red_private_vars + 0x70); if (index != -1) { @@ -110,7 +110,7 @@ void thruster_pack_lock_red_update(struct Moby *moby) { break; case STATE_WAIT_FOR_DEPRESSION_TRIGGER: if (hero.air_frames.s == 0 && hero.ground_moby == moby && hero.state.current == 0x22) { - moby->state = 5; + moby->state = STATE_SETTLE_DEPRESSED_HEIGHT; moby->command = 1; moby->pos.z -= 1.5f; if (current_level_index == 0x12) @@ -145,7 +145,7 @@ void thruster_pack_lock_red_update(struct Moby *moby) { *(float *)(thruster_pack_lock_red_private_vars + 0x64) - 1.5f, 0.15f) != 0.0f) return; - moby->state = 6; + moby->state = STATE_DEPRESSED_HEIGHT_SETTLED; break; } } From eeac5d5f2f1b21a76b8ab88024bfdca9378a4357 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:51:37 +0000 Subject: [PATCH 0851/1502] decomp: clarify names in music_update domain_0_value_0 -> CROSSFADE_IDLE: Retail 0x0021638c-0x002163b8 loads global +0x20, the same crossfade_state selector dispatched at 0x002164a8, and allows music_transition for a requested track only when it is zero. The reset path at 0x0021663c-0x00216650 clears that same field; zero therefore denotes the idle crossfade scheduler phase. domain_1_value_3 -> CROSSFADE_WAIT_TO_PRESEEK_PRIMARY: Retail 0x00216548-0x0021655c stores 3 to global +0x20 after primary fade volume becomes nonpositive or a required stream is absent. This is the exact crossfade_state field selected at 0x002164a8; value 3 dispatches to 0x0021659c-0x002165dc, which waits for primary readiness and calls music_preseek_track. Reuse the existing same-selector enum member. domain_2_value_4 -> CROSSFADE_WAIT_TO_CONTINUE_PRIMARY: Retail 0x002165c4 calls music_preseek_track, then 0x002165d0-0x002165dc stores 4 to global +0x20 and clears requested_track. The same crossfade_state switch dispatches 4 to 0x002165e0, whose readiness tests precede snd_continue_vag_stream at 0x00216620. Reuse the existing same-domain CROSSFADE_WAIT_TO_CONTINUE_PRIMARY member. domain_3_value_5 -> CROSSFADE_WAIT_TO_RESET: Retail 0x00216620-0x00216638 calls snd_continue_vag_stream(primary.handle), stores 5 to global +0x20, and sets primary.state to 8. The same crossfade_state selector dispatches 5 to 0x0021663c-0x00216650, which waits or clears this scheduler phase to zero. Reuse the existing CROSSFADE_WAIT_TO_RESET member. domain_4_value_0 -> CROSSFADE_IDLE: Retail 0x0021663c-0x00216650 clears global +0x20 when transition.state differs from 4 or transition.crossfade_enabled is zero. This is the same crossfade_state field whose zero comparison at 0x0021638c-0x002163b8 permits new requested-track transitions. It restores the crossfade scheduler to idle, without asserting audible playback completion. domain_5_value_0 -> CD_READ_STATE_IDLE: Retail 0x00216684-0x0021669c calls snd_stream_safe_cd_sync(1), then clears global +0x8 and break_requested when sync returns zero. Helper retail 0x002167b0-0x002167e0 reads this identical +0x8 field, permits a new read only at zero, and sets it to 1 after successful submission. Supplied start_audio_stream_read source calls zero CD_READ_STATE_IDLE. domain_6_value_2 -> CD_READ_STATE_PENDING_RETRY: Retail 0x00216680 loads read_state from global +0x8 into s0; 0x002166a0-0x002166c8 tests it against 2, temporarily clears the field, calls start_audio_stream_read with retained destination/sector/count, and restores the saved state if the field remains zero. Helper 0x002167b0-0x002167e0 accepts only idle zero and writes active 1 on success. State 2 specifically requests a retained read retry. domain_7_value_0 -> CD_READ_STATE_IDLE: Retail 0x002166ac-0x002166bc loads retained read destination/sector/count and clears global +0x8 in the delay slot before calling start_audio_stream_read. Helper 0x002167b0-0x002167b4 requires this same field to equal zero before submission, confirming this assignment temporarily puts the CD read state into idle; supplied helper source names zero CD_READ_STATE_IDLE. domain_8_value_0 -> CD_READ_STATE_IDLE: Retail 0x002166c0-0x002166c8 reloads global +0x8 after start_audio_stream_read and restores saved pending state when it is still zero. Helper 0x002167b0-0x002167e0 requires zero before submission and changes it to active 1 on success. Thus this comparison tests CD_READ_STATE_IDLE, the same zero-valued domain member in supplied helper source. --- src/audio/music/music_update.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/audio/music/music_update.c b/src/audio/music/music_update.c index f3342106f5..12c069c962 100644 --- a/src/audio/music/music_update.c +++ b/src/audio/music/music_update.c @@ -28,6 +28,11 @@ void music_update(void) { CROSSFADE_WAIT_TO_CONTINUE_PRIMARY = 4, CROSSFADE_WAIT_TO_RESET = 5 }; + enum { + CROSSFADE_IDLE = 0, + CD_READ_STATE_IDLE = 0, + CD_READ_STATE_PENDING_RETRY = 2 + }; s8 requested_track; s32 fade_volume; s32 handle; @@ -55,7 +60,7 @@ void music_update(void) { } if (fast_dec_timer(&music_stream_state.retry_timer) != 0) { requested_track = music_stream_state.requested_track; - if (requested_track != -1 && music_stream_state.crossfade_state == 0) { + if (requested_track != -1 && music_stream_state.crossfade_state == CROSSFADE_IDLE) { if (music_stream_state.primary.track != requested_track) { if (music_stream_state.requested_transition_track == -1 || music_transition(requested_track, @@ -97,7 +102,7 @@ void music_update(void) { music_stream_state.transition.crossfade_enabled == 0) && music_stream_state.transition.handle == 0) || (handle = music_stream_state.primary.handle) == 0) { - music_stream_state.crossfade_state = 3; + music_stream_state.crossfade_state = CROSSFADE_WAIT_TO_PRESEEK_PRIMARY; music_stream_state.primary.state = 5; } else if (music_stream_state.primary.state != 9) { /* The callback receives the old handle; mark its slot pending before submission. */ @@ -120,7 +125,7 @@ void music_update(void) { music_stream_state.primary.flags, music_stream_state.primary.volume); music_stream_state.requested_track = -1; - music_stream_state.crossfade_state = 4; + music_stream_state.crossfade_state = CROSSFADE_WAIT_TO_CONTINUE_PRIMARY; } break; case CROSSFADE_WAIT_TO_CONTINUE_PRIMARY: @@ -132,14 +137,14 @@ void music_update(void) { music_stream_state.transition.handle == 0)) { snd_continue_vag_stream(music_stream_state.primary.handle); music_stream_state.primary.state = 8; - music_stream_state.crossfade_state = 5; + music_stream_state.crossfade_state = CROSSFADE_WAIT_TO_RESET; } } break; case CROSSFADE_WAIT_TO_RESET: if (music_stream_state.transition.state != 4 || music_stream_state.transition.crossfade_enabled == 0) { - music_stream_state.crossfade_state = 0; + music_stream_state.crossfade_state = CROSSFADE_IDLE; } break; } @@ -149,17 +154,17 @@ void music_update(void) { music_update_stream(&music_stream_state.secondary.handle); if (music_stream_state.break_requested != 0) { if (snd_stream_safe_cd_sync(1) == 0) { - music_stream_state.read_state = 0; + music_stream_state.read_state = CD_READ_STATE_IDLE; music_stream_state.break_requested = 0; } } else { pending_state = music_stream_state.read_state; - if (pending_state == 2) { - music_stream_state.read_state = 0; + if (pending_state == CD_READ_STATE_PENDING_RETRY) { + music_stream_state.read_state = CD_READ_STATE_IDLE; start_audio_stream_read(music_stream_state.read_dst, music_stream_state.read_sector, music_stream_state.read_sector_count); - if (music_stream_state.read_state == 0) { + if (music_stream_state.read_state == CD_READ_STATE_IDLE) { music_stream_state.read_state = pending_state; } } From 8e77b1f1e9bbcfd65592e22bd4afe438aef0e149 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:51:38 +0000 Subject: [PATCH 0852/1502] decomp: clarify names in draw_save_slot_list domain_0_value_3 -> MEMCARD_REQUEST_FORMAT: At 0x00223a3c..0x00223a50 retail loads g_nMemoryCardOperationState from memory_card_state +0xd4 and tests it with slti 3 before highlighting the selected save slot. The bound source maps this to memory_card_state.state < 3. The shared header explicitly assigns state/pending_state to MemoryCardOperation, whose canonical value 3 is MEMCARD_REQUEST_FORMAT, not any operation substep. domain_1_value_0 -> MEMCARD_QUERY_INFO: At 0x00223a58..0x00223a5c the retail g_nPendingMemoryCardOperationState load from +0xdc branches on nonnegative pending operations, suppressing selection highlighting. Source expresses the complement as memory_card_state.pending_state < 0. The shared header identifies pending_state as MemoryCardOperation; MEMCARD_QUERY_INFO is its canonical zero boundary, not a probe/create step. domain_2_value_3 -> MEMCARD_REQUEST_FORMAT: At 0x00223adc..0x00223ae4 the same retail current operation field +0xd4 is tested with slti 3, bypassing slot details when it is >=3. Source maps this directly to memory_card_state.state >= 3. Its shared MemoryCardOperation domain names value 3 MEMCARD_REQUEST_FORMAT, reusing the same canonical threshold as the earlier highlight test. domain_3_value_0 -> MEMCARD_QUERY_INFO: At 0x00223aec..0x00223af4 retail loads the same pending operation field +0xdc and uses bgez to skip slot-detail rendering for pending operations >=0. The source selector is memory_card_state.pending_state; the shared header proves its MemoryCardOperation domain. MEMCARD_QUERY_INFO is the existing zero member used as this nonnegative-operation boundary. --- src/ui/menus/save_data/draw_save_slot_list.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/menus/save_data/draw_save_slot_list.c b/src/ui/menus/save_data/draw_save_slot_list.c index b7edff0c1d..d696e759ce 100644 --- a/src/ui/menus/save_data/draw_save_slot_list.c +++ b/src/ui/menus/save_data/draw_save_slot_list.c @@ -54,7 +54,7 @@ s32 draw_save_slot_list(SaveMenu *menu) { inner_right = width - 3; inner_top = y - 1; inner_bottom = y + 0x31; - if (memory_card_state.state < 3 && memory_card_state.pending_state < 0 && + if (memory_card_state.state < MEMCARD_REQUEST_FORMAT && memory_card_state.pending_state < MEMCARD_QUERY_INFO && menu->selected_slot == i) { append_screen_rect_packet(0, highlight_top, width, highlight_bottom, 0x8020FFFF, 0); append_screen_rect_packet( @@ -62,7 +62,7 @@ s32 draw_save_slot_list(SaveMenu *menu) { } append_screen_rect_packet(3, inner_top, inner_right, inner_bottom, 0x80303030, 0); slot = &memory_card_state.card[0].entries[i]; - if (memory_card_state.state >= 3 || memory_card_state.pending_state >= 0 || + if (memory_card_state.state >= MEMCARD_REQUEST_FORMAT || memory_card_state.pending_state >= MEMCARD_QUERY_INFO || memory_card_state.card[0].type != 2) { y += 0x30; } else { From a3461bb0659106a83c877557894fb83a4c3debb3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:51:38 +0000 Subject: [PATCH 0853/1502] decomp: clarify names in update_moby_rotation_group domain_0_value_2 -> WAIT_FOR_TRIGGER_AND_CHILDREN: At 002f4f34 the switch reads moby+0x20; 002f4f74/002f4f8c writes 2 to that same byte after saving the base transform. Retail case 2 at 002f5094-002f5184 checks the trigger and all seven children, proving reuse of this function-local state member. domain_1_value_3 -> UPDATE_POSITION_FROM_BASE: 002f5074-002f507c assigns 3 to moby+0x20 after saving base rotation and position. The same switch byte selects case 3 at 002f51d4-002f51f0, which adds the scaled rotation-row2 vector to saved base position; reuse UPDATE_POSITION_FROM_BASE. domain_2_value_4 -> ROTATE_AND_HIDE_AFTER_TRIGGER_AND_CHILDREN: 002f5158-002f5184 requires the trigger and seven children in state 3; 002f5198-002f51a0 writes 4 to the owner's switch byte moby+0x20. Its case 4 approaches the angular target and hides the owner at 002f51fc-002f528c, matching the existing local member. domain_3_value_4 -> ROTATE_AND_HIDE_AFTER_TRIGGER_AND_CHILDREN: 002f5280 reads the same owner state byte used by the switch, and 002f5290 compares it to 4 after the angular target has been reached and visibility cleared. This distinguishes completion of the existing ROTATE_AND_HIDE_AFTER_TRIGGER_AND_CHILDREN case from case 5. domain_4_value_6 -> ROTATED_AND_HIDDEN_AFTER_TRIGGER_AND_CHILDREN: In the shared state-4/5 body, 002f5268-002f5274 requires angular offset >=1.0471976; 002f5284-002f528c sets flags bit 1 and clears visibility. 002f5290/002f5294 then selects 6 specifically for owner state 4 and 002f5328 stores it to the same switch byte: completion of rotation and hiding after trigger/children. domain_5_value_7 -> ROTATED_AND_HIDDEN: The state-4/5 body reaches 002f5288 only after its angular offset reaches 1.0471976 and clears visibility there. 002f5290-002f529c selects 7 for the other shared-body state, case 5 ROTATE_AND_HIDE, then 002f5328 stores it to moby+0x20. Thus 7 records completed rotation and hiding. domain_6_value_8 -> RESTORE_ROTATION_THEN_WAIT_FOR_TRIGGER_AND_CHILDREN: 002f52a0-002f5300 restores the angular offset toward zero; 002f5314-002f531c compares the owner's switch byte moby+0x20 with 8, and 002f5324/002f5328 returns that path to state 2. This is exactly the existing restore-then-wait local member. domain_7_value_2 -> WAIT_FOR_TRIGGER_AND_CHILDREN: When restored offset <=0 at 002f5304-002f5310, owner state 8 is tested at 002f5318-002f531c; 002f5324 loads 2 and 002f5328 writes it to the same moby+0x20 switch byte. Case 2 performs the trigger and seven-child readiness checks, proving reuse of WAIT_FOR_TRIGGER_AND_CHILDREN. domain_8_value_3 -> UPDATE_POSITION_FROM_BASE: At restored offset <=0, 002f531c-002f5320 selects 3 for the restore body path other than state 8 (case 9); 002f5328 writes the owner switch byte. Case 3 at 002f51d4-002f51f0 computes position from saved base and scaled rotation row2, proving the existing UPDATE_POSITION_FROM_BASE member. --- src/overlays/shared/props/group_rotator.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/overlays/shared/props/group_rotator.c b/src/overlays/shared/props/group_rotator.c index 7d06d0a0a7..7629e4ffd0 100644 --- a/src/overlays/shared/props/group_rotator.c +++ b/src/overlays/shared/props/group_rotator.c @@ -54,6 +54,10 @@ void moby_rotation_group_update(Moby *moby) { RESTORE_ROTATION_THEN_WAIT_FOR_TRIGGER_AND_CHILDREN = 8, RESTORE_ROTATION_THEN_UPDATE_POSITION_FROM_BASE = 9 }; + enum { + ROTATED_AND_HIDDEN_AFTER_TRIGGER_AND_CHILDREN = 6, + ROTATED_AND_HIDDEN = 7 + }; Vars *moby_vars = (Vars *)(*(void **)&moby->pvars); float position_offset[4]; int i; @@ -65,7 +69,7 @@ void moby_rotation_group_update(Moby *moby) { case SPAWN_CHILD_MOBYS: moby_vars->unk10 = (*(float(*)[4]) & moby->rot)[0]; qcopy(moby_vars->pos, (*(float(*)[4]) & moby->pos)); - moby->state = 2; + moby->state = WAIT_FOR_TRIGGER_AND_CHILDREN; for (i = 0; i < 7; i++) { moby_vars->slots[i] = create_moby(0x3FD); (*(char *)&moby_vars->slots[i]->update_dist) = 0x40; @@ -86,7 +90,7 @@ void moby_rotation_group_update(Moby *moby) { case INITIALIZE_BASE_TRANSFORM: moby_vars->unk10 = (*(float(*)[4]) & moby->rot)[0]; qcopy(moby_vars->pos, (*(float(*)[4]) & moby->pos)); - moby->state = 3; + moby->state = UPDATE_POSITION_FROM_BASE; fast_vec_normalize(position_offset, (*(float(*)[4]) & moby->rot_row2), rotation_group_position_offset_distance_gp); @@ -121,7 +125,7 @@ void moby_rotation_group_update(Moby *moby) { } if (flag) { allocate_voice_for_target_entry(0, 0, moby); - moby->state = 4; + moby->state = ROTATE_AND_HIDE_AFTER_TRIGGER_AND_CHILDREN; moby_vars->unk18 = 0; moby_vars->unk14 = 0.0f; for (k = 0; k < 7; k++) { @@ -150,10 +154,10 @@ void moby_rotation_group_update(Moby *moby) { if (moby_vars->unk14 >= 1.0471976f) { moby->flags |= 1; (*(char *)&moby->visible) = 0; - if (moby->state == 4) { - moby->state = 6; + if (moby->state == ROTATE_AND_HIDE_AFTER_TRIGGER_AND_CHILDREN) { + moby->state = ROTATED_AND_HIDDEN_AFTER_TRIGGER_AND_CHILDREN; } else { - moby->state = 7; + moby->state = ROTATED_AND_HIDDEN; } } break; @@ -169,10 +173,10 @@ void moby_rotation_group_update(Moby *moby) { (*(float(*)[4]) & moby->rot)[0] = fast_subtract_rotations(moby_vars->unk10, moby_vars->unk14); if (moby_vars->unk14 <= 0.0f) { - if (moby->state == 8) { - moby->state = 2; + if (moby->state == RESTORE_ROTATION_THEN_WAIT_FOR_TRIGGER_AND_CHILDREN) { + moby->state = WAIT_FOR_TRIGGER_AND_CHILDREN; } else { - moby->state = 3; + moby->state = UPDATE_POSITION_FROM_BASE; } } break; From 6086b03c86600969a2148c14c2eafe0c70e2d1b8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:51:38 +0000 Subject: [PATCH 0854/1502] decomp: clarify names in gate_2_update domain_0_value_3 -> GATE_STATE_OPEN: Authoritative gate_2_update source includes gate_state.h and switches entry_gate_state, captured from moby->state. Retail 0x002e99bc loads this same +0x20 byte and 0x002e99c0-0x002e99ec dispatches states 0/1/2/3, proving the shared GateState domain rather than a trigger or mode domain. Initialization computes home plus the full 1.5-unit XY opening offset, then 0x002e9ad4-0x002e9ae0 writes 3 to +0x20 and stores position; this selects the existing GATE_STATE_OPEN case. domain_1_value_1 -> GATE_STATE_CLOSED: Authoritative gate_2_update source includes gate_state.h and switches entry_gate_state, captured from moby->state. Retail 0x002e99bc loads this same +0x20 byte and 0x002e99c0-0x002e99ec dispatches states 0/1/2/3, proving the shared GateState domain rather than a trigger or mode domain. The initialization branch without saved/bypass completion sets the linked moby's flag and at 0x002e9b04 stores t0=1 into +0x20, selecting the existing GATE_STATE_CLOSED waiting branch at 0x002e9b08. domain_2_value_3 -> GATE_STATE_OPEN: Authoritative gate_2_update source includes gate_state.h and switches entry_gate_state, captured from moby->state. Retail 0x002e99bc loads this same +0x20 byte and 0x002e99c0-0x002e99ec dispatches states 0/1/2/3, proving the shared GateState domain rather than a trigger or mode domain. The closed branch's saved/bypass path loads home, writes 3 to +0x20 at 0x002e9b7c-0x002e9b80, restores position and clears the linked flag. It selects the existing canonical completed GATE_STATE_OPEN phase. domain_3_value_2 -> GATE_STATE_OPENING: Authoritative gate_2_update source includes gate_state.h and switches entry_gate_state, captured from moby->state. Retail 0x002e99bc loads this same +0x20 byte and 0x002e99c0-0x002e99ec dispatches states 0/1/2/3, proving the shared GateState domain rather than a trigger or mode domain. After recording save bits and activating the descriptor, 0x002e9c6c stores the opening countdown at vars+0x14 and 0x002e9c70-0x002e9c78 writes state 2. Dispatch sends 2 to 0x002e9c7c, the existing GATE_STATE_OPENING interpolation branch. domain_4_value_3 -> GATE_STATE_OPEN: Authoritative gate_2_update source includes gate_state.h and switches entry_gate_state, captured from moby->state. Retail 0x002e99bc loads this same +0x20 byte and 0x002e99c0-0x002e99ec dispatches states 0/1/2/3, proving the shared GateState domain rather than a trigger or mode domain. The existing GATE_STATE_OPENING branch updates position and calls the timer decrement helper at 0x002e9d54. Its nonzero completion result leads 0x002e9d60-0x002e9d68 to store 3 in +0x20, selecting GATE_STATE_OPEN. domain_5_value_0 -> GATE_STATE_INITIALIZE: Authoritative gate_2_update source includes gate_state.h and switches entry_gate_state, captured from moby->state. Retail 0x002e99bc loads this same +0x20 byte and 0x002e99c0-0x002e99ec dispatches states 0/1/2/3, proving the shared GateState domain rather than a trigger or mode domain. When the open branch's save/bypass conditions clear, 0x002e9de0-0x002e9de8 restores home and writes zero to +0x20. The next dispatch enters 0x002e99fc, which initializes f30 and captures home, matching existing GATE_STATE_INITIALIZE. --- src/overlays/l10/mobys/gate_2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l10/mobys/gate_2.c b/src/overlays/l10/mobys/gate_2.c index 87b98d35b4..e5cb4494ef 100644 --- a/src/overlays/l10/mobys/gate_2.c +++ b/src/overlays/l10/mobys/gate_2.c @@ -75,13 +75,13 @@ void gate_2_update(GateMoby *moby) { opening_offset[1] = fast_sin(fast_add_rotations(moby->rotz, 3.14159265f)) * 1.5f; opening_offset[2] = 0.0f; fast_vec_add(&opening_position, &vars->home, opening_offset); - moby->state = 3; + moby->state = GATE_STATE_OPEN; moby->pos = opening_position; } else { if (vars->door > 0) { (*(GateMoby **)&D_L10_0015FFD8_gp)[vars->door].flags |= 2; } - moby->state = 1; + moby->state = GATE_STATE_CLOSED; } break; case GATE_STATE_CLOSED: { @@ -92,7 +92,7 @@ void gate_2_update(GateMoby *moby) { (moby->uid & 0x1F)) & 1) != 0) { moby->pos = vars->home; - moby->state = 3; + moby->state = GATE_STATE_OPEN; if (vars->door > 0) { (*(GateMoby **)&D_L10_0015FFD8_gp)[vars->door].flags &= 0xFFFD; } @@ -107,7 +107,7 @@ void gate_2_update(GateMoby *moby) { activate_descriptor(vars->sound); } vars->timer = truncate_float_to_s32(FUN_L04_001f1978(90.0f)); - moby->state = 2; + moby->state = GATE_STATE_OPENING; } break; } @@ -124,7 +124,7 @@ void gate_2_update(GateMoby *moby) { fast_vec_add(&opening_position, &vars->home, opening_offset); moby->pos = opening_position; if (fast_dec_timer(&vars->timer)) { - moby->state = 3; + moby->state = GATE_STATE_OPEN; } break; case GATE_STATE_OPEN: @@ -135,7 +135,7 @@ void gate_2_update(GateMoby *moby) { 1) & 1)) { moby->pos = vars->home; - moby->state = 0; + moby->state = GATE_STATE_INITIALIZE; } break; } From 2c3a26a279d456c45e8e90e617df6ca531269e73 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:51:38 +0000 Subject: [PATCH 0855/1502] decomp: clarify names in resolve_hero_position_collisions domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Retail 0x00210be8 loads hero+0x20b3 into a0; 0x00210c20 tests it against zero, matching source hero.gravity_mode != 0. The zero arm at 0x00210c8c-0x00210c90 writes capsule_bottom directly to the Z component of collision_position_offset. The supplied gravity helpers switch on this same hero.gravity_mode field: WORLD_DOWN uses a direct Z offset, while nonworld modes transform/normalize offsets. This proves the HeroGravityMode domain and canonical zero member, rather than a state or vehicle ID. domain_1_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: The same hero+0x20b3 byte loaded at 0x00210be8 remains in a0 through 0x00210c34, which compares it with 1 and selects the 0.6f gravity-relative offset helper at 0x00210c64. Source identifies the selector as hero.gravity_mode. Supplied FUN_L00_00233810 switches on that exact field, treating HERO_GRAVITY_OPPOSITE_GROUND_NORMAL as the transformed-offset arm; FUN_L00_002334d0 and update_hero_ground_contact establish the same shared gravity domain using ground_normal and its negation. Reuse canonical HeroGravityMode member 1. domain_2_value_0 -> HERO_GRAVITY_WORLD_DOWN: Retail 0x00210e10 reloads hero+0x20b3 and 0x00210e14 branches on zero to the ordinary control-mode collision arms at 0x00210cd0; nonzero selects the frame_scale*0.4f probe at 0x00210e34. This is the same hero.gravity_mode field used for the offset selection at 0x00210be8-0x00210c90, whose zero branch applies capsule_bottom along world Z. The supplied helpers and ground-contact switch explicitly use HeroGravityMode on that same selector, proving canonical HERO_GRAVITY_WORLD_DOWN for this second zero comparison. --- src/overlays/l16/hero/apply_hero_ground_material_effects.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l16/hero/apply_hero_ground_material_effects.c b/src/overlays/l16/hero/apply_hero_ground_material_effects.c index 089ee3b9f5..de7330f1aa 100644 --- a/src/overlays/l16/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l16/hero/apply_hero_ground_material_effects.c @@ -419,8 +419,8 @@ s32 resolve_hero_position_collisions(s32 mode) { transform_hero_local_offset_to_world(&collision_position_offset, 0.0f, 0.0f, 0.7f); fast_vec_sub( &collision_position_offset, &collision_position_offset, &hero.motion.pos.q); - } else if (hero.gravity_mode != 0 || hero.unk1F8 != 0) { - if (hero.gravity_mode == 1 || hero.unk1F8 != 0 || + } else if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN || hero.unk1F8 != 0) { + if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0 || (unsigned)(hero.state.control_mode - 0x15) < 2) { FUN_L00_00233810(&collision_position_offset, &collision_position_offset, 0.6f); } else { @@ -437,7 +437,7 @@ s32 resolve_hero_position_collisions(s32 mode) { mask = 0xD24; } for (i = 0; i < 8; i++) { - if (hero.gravity_mode != 0) { + if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN) { if (!coll1_2133a8(&hero.motion.pos.q, mask, ((s32)hero.moby), frame_scale * 0.4f)) break; } else if (hero.state.control_mode == 0x11) { From fda4063a41f9774ddefa2d4d9905ce34fe139137 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:51:38 +0000 Subject: [PATCH 0856/1502] decomp: clarify names in draw_menu_item_grid domain_0_value_0 -> MENU_GRID_CELL_EQUIPPABLE_ITEM: At retail 0x0021dc34-0x0021dc58, the signed halfword cell kind at s1+4 selects item_available (0x0013d4c0) when zero, versus alternate_item_available (0x0013d388) when nonzero. The same kind retained in a1 is tested at 0x0021dc80; only zero permits the item id at s1+6 to index 0x001863d8 with stride 0x4c and load its equipment slot, then compare menu_system.equipped[slot] with that id at 0x0021dcb0-0x0021dcbc. Thus zero identifies the equippable-item cell domain. domain_1_value_0 -> MENU_GRID_CELL_EQUIPPABLE_ITEM: The second comparison is (u16)cell->kind == 0. Retail 0x0021dc3c loads that kind into a1, and 0x0021dc80 skips equipment frame processing when nonzero. The zero branch at 0x0021dc88-0x0021dccc indexes menu_grid_item_slot_records by cell->id, loads slot, and compares menu_system.equipped[slot] to that same id to select frame offset 1 unless flag 0x20 suppresses it. Both comparisons therefore name the same equippable-item cell kind. --- src/ui/menus/widgets/draw_menu_item_grid.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ui/menus/widgets/draw_menu_item_grid.c b/src/ui/menus/widgets/draw_menu_item_grid.c index 4469d59d75..178fad5db6 100644 --- a/src/ui/menus/widgets/draw_menu_item_grid.c +++ b/src/ui/menus/widgets/draw_menu_item_grid.c @@ -40,6 +40,9 @@ extern void append_screen_rect_packet(s32, s32, s32, s32, u64, s32) __asm__("fun s32 draw_menu_item_grid(struct MenuScreen *grid) __asm__("FUN_0021d948"); s32 draw_menu_item_grid(struct MenuScreen *grid) { + enum { + MENU_GRID_CELL_EQUIPPABLE_ITEM = 0 + }; Font *font; struct MenuGridCell *cell; s32 focused; @@ -107,9 +110,9 @@ s32 draw_menu_item_grid(struct MenuScreen *grid) { append_screen_rect_packet( left - 0x10, top - 0x10, right + 0x10, bottom + 0x10, panel_clear_color, 1); } - if (cell->kind == 0 ? item_available[cell->id] : alternate_item_available[cell->id]) { + if (cell->kind == MENU_GRID_CELL_EQUIPPABLE_ITEM ? item_available[cell->id] : alternate_item_available[cell->id]) { frame_offset = 0; - if ((u16)cell->kind == 0) { + if ((u16)cell->kind == MENU_GRID_CELL_EQUIPPABLE_ITEM) { id = cell->id; if (menu_system.equipped[menu_grid_item_slot_records[id].slot] == id && !(grid->data.grid.flags & 0x20)) { From 996ca892555a2f67d60caf85de18da6a11eb44b8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:51:38 +0000 Subject: [PATCH 0857/1502] decomp: clarify names in rocket_update domain_0_value_2 -> ROCKET_STATE_DETONATE: The source assigns moby->state=2 after find_moby_hit reports a hit whose source differs from rocket_state->owner. Retail 0x002ece68-0x002ece74 compares hit +0x20 with owner +0x10, branches to 0x002ed130 and stores 2 at 0x002ed134. The target byte is moby->state at +0x20 of s4, the same byte read at 0x002ece30 and compared with 2 at 0x002ece3c-0x002ece40. That dispatch enters 0x002ed138, calls explosion/burst at 0x002ed208 or 0x002ed244, then removal at 0x002ed24c; the authoritative source already names this exact state ROCKET_STATE_DETONATE=2. domain_1_value_2 -> ROCKET_STATE_DETONATE: The source assigns moby->state=2 when the owner's unsigned state is below 2 in the level/camera condition. Retail 0x002ecec8-0x002eced4 tests that owner byte and branches to the rocket state store at 0x002ed134. The owner's threshold itself remains unnamed. The target byte is moby->state at +0x20 of s4, the same byte read at 0x002ece30 and compared with 2 at 0x002ece3c-0x002ece40. That dispatch enters 0x002ed138, calls explosion/burst at 0x002ed208 or 0x002ed244, then removal at 0x002ed24c; the authoritative source already names this exact state ROCKET_STATE_DETONATE=2. domain_2_value_2 -> ROCKET_STATE_DETONATE: The source assigns moby->state=2 after collision_line or coll_sphere succeeds, following optional record_moby_hit. Retail collision calls at 0x002ed01c/0x002ed038 lead to 0x002ed048; 0x002ed118 loads 2 and 0x002ed11c stores it into 0x20(s4), including the no-target path via 0x002ed058. The target byte is moby->state at +0x20 of s4, the same byte read at 0x002ece30 and compared with 2 at 0x002ece3c-0x002ece40. That dispatch enters 0x002ed138, calls explosion/burst at 0x002ed208 or 0x002ed244, then removal at 0x002ed24c; the authoritative source already names this exact state ROCKET_STATE_DETONATE=2. domain_3_value_2 -> ROCKET_STATE_DETONATE: The source assigns moby->state=2 when fast_dec_timer(&rocket_state->timer) returns nonzero. Retail 0x002ed120-0x002ed124 passes pvars+0x14 to the timer helper; 0x002ed128 skips the store for zero, otherwise 0x002ed12c loads 2 and 0x002ed134 writes the rocket state. The target byte is moby->state at +0x20 of s4, the same byte read at 0x002ece30 and compared with 2 at 0x002ece3c-0x002ece40. That dispatch enters 0x002ed138, calls explosion/burst at 0x002ed208 or 0x002ed244, then removal at 0x002ed24c; the authoritative source already names this exact state ROCKET_STATE_DETONATE=2. --- src/overlays/l12/mobys/rocket.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l12/mobys/rocket.c b/src/overlays/l12/mobys/rocket.c index a761259dcf..8e1b850d06 100644 --- a/src/overlays/l12/mobys/rocket.c +++ b/src/overlays/l12/mobys/rocket.c @@ -133,7 +133,7 @@ void rocket_update(struct Moby *moby) { char *touch = find_moby_hit(moby, 0x230000, 0); int damage; if (touch != 0 && *(struct Moby **)(touch + 0x20) != rocket_state->owner) { - moby->state = 2; + moby->state = ROCKET_STATE_DETONATE; break; } if (current_level_index == 12 && camera_secondary_mode[0] == 50 && @@ -143,7 +143,7 @@ void rocket_update(struct Moby *moby) { return; } if (rocket_state->owner->state < 2) { - moby->state = 2; + moby->state = ROCKET_STATE_DETONATE; break; } } @@ -188,10 +188,10 @@ void rocket_update(struct Moby *moby) { hit.oclass = moby->oclass; record_moby_hit(D_L12_001742C0_lui.moby, &hit); } - moby->state = 2; + moby->state = ROCKET_STATE_DETONATE; } if (fast_dec_timer(&rocket_state->timer)) { - moby->state = 2; + moby->state = ROCKET_STATE_DETONATE; } break; } From 49d148921b4cacc3ded0286a1a37dcd2a597b844 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:51:38 +0000 Subject: [PATCH 0858/1502] decomp: clarify names in floating_platform_update domain_0_value_2 -> STATE_WAIT_FOR_SINK_REQUEST: Retail 002d8304 dispatches moby byte +20; 002d8350-002d836c writes 2 to that same byte when pvars+88 is nonzero. Source's existing local enum and case STATE_WAIT_FOR_SINK_REQUEST=2 identify this selector. Supplied request_floating_platform_sink accepts that platform state and changes it to STATE_SINKING; original Ghidra case 0 confirms this initialization branch. domain_1_value_1 -> STATE_WAIT_FOR_TILT_REQUEST: Retail 002d8370-002d8378 writes 1 to moby byte +20, the selector loaded at 002d8304, when initialization finds pvars+88 zero. The existing enum/case names this platform state STATE_WAIT_FOR_TILT_REQUEST=1; supplied request_floating_platform_tilt accepts that state, stores countdown +7c and enters STATE_TILT_DELAY. Original Ghidra case 0 confirms the write. domain_2_value_4 -> STATE_WAIT_FOR_SINK_TRIGGER: Retail 002d837c-002d8384 waits for countdown +7c; 002d8410-002d8434 computes and stores tilt increment +6c, then 002d8420/002d843c writes 4 to the same moby +20 state selector. Existing local enum/case STATE_WAIT_FOR_SINK_TRIGGER=4 tests grounded hero ownership or configured proximity before entering sinking; original Ghidra cases 3 and 4 corroborate this transition. domain_3_value_5 -> STATE_SINKING: Retail 002d8484-002d8494 tests hero ground_moby against this platform and zero air frames, then 002d84a0-002d84a4 writes 5 to moby +20 and allocates its voice. This is the same selector dispatched at 002d8304 and existing local enum/case STATE_SINKING=5. Its branch integrates downward velocity +70 into height +64 at 002d85f4-002d8620 and removes below Z=15; original Ghidra case 4 confirms the write. domain_4_value_5 -> STATE_SINKING: Retail 002d84bc-002d84e0 gates on pvars+80 and compares platform-to-hero distance to the sink trigger threshold; 002d84e4/002d84ec writes 5 to moby +20 before voice allocation. It targets the same state selector as 002d8304 and existing STATE_SINKING=5 case, whose 002d85f4-002d8620 branch accelerates down and integrates height. Original Ghidra case 4 independently confirms the proximity-triggered state-5 assignment. --- src/overlays/l18/mobys/floating_platform.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l18/mobys/floating_platform.c b/src/overlays/l18/mobys/floating_platform.c index eab66e15e0..7143450a6a 100644 --- a/src/overlays/l18/mobys/floating_platform.c +++ b/src/overlays/l18/mobys/floating_platform.c @@ -79,9 +79,9 @@ void floating_platform_update(struct Moby *moby) { *(int *)(floating_platform_update_private_vars + 0x5C) |= 1; *(float *)(floating_platform_update_private_vars + 0x74) = angle; if (*(int *)(floating_platform_update_private_vars + 0x88) != 0) { - moby->state = 2; + moby->state = STATE_WAIT_FOR_SINK_REQUEST; } else { - moby->state = 1; + moby->state = STATE_WAIT_FOR_TILT_REQUEST; } break; case STATE_TILT_DELAY: @@ -104,7 +104,7 @@ void floating_platform_update(struct Moby *moby) { rate = floating_platform_tilt_rate_degrees_config_84_zero_gp * tilt_rate_scale; } *(float *)(floating_platform_update_private_vars + 0x6C) = rate * DEG_TO_RAD * frame_time; - moby->state = 4; + moby->state = STATE_WAIT_FOR_SINK_TRIGGER; break; case STATE_WAIT_FOR_SINK_TRIGGER: if (moby->visible != 0 && @@ -115,7 +115,7 @@ void floating_platform_update(struct Moby *moby) { } if (hero.ground_moby == moby && hero.air_frames.s == 0) { *(int *)(floating_platform_update_private_vars + 0x8C) = 0; - moby->state = 5; + moby->state = STATE_SINKING; *(short *)(floating_platform_update_private_vars + 0x92) = allocate_voice_for_target_entry(1, 0, moby); } @@ -124,7 +124,7 @@ void floating_platform_update(struct Moby *moby) { } if (vector_distance_xy(&moby->pos, &hero.motion.pos) < floating_platform_sink_trigger_distance_gp) { - moby->state = 5; + moby->state = STATE_SINKING; *(short *)(floating_platform_update_private_vars + 0x92) = allocate_voice_for_target_entry(1, 0, moby); } From 184eceb488cf2b42d85637c54bde133fbb5342cd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:53:27 +0000 Subject: [PATCH 0859/1502] decomp: clarify names in taunter_update domain_2_value_0 -> TAUNTER_STATE_INITIALIZE: Retail 0x002b6f90-0x002b6fb4 tests the incoming taunter object's byte +0x20 for zero, initializes its private voice slot at vars+4 to -1, advances the object state and sets the taunter effect reset flag. Original Ghidra and authoritative C agree that this branch performs one-time taunter initialization. The selector belongs to taunter_moby, not the hero state enum. domain_4_value_2 -> TAUNTER_STATE_ACTIVE: Retail 0x002b6fb8 loads the taunter object's +0x20 state into v1; 0x002b6fe8 rejects every state other than 2 before the input/use body. The accepted branch checks item button masks at 0x002b7048-0x002b7080, allocates a voice at 0x002b7178, applies the taunter to nearby mobies at 0x002b71fc/0x002b7350 and releases its voice when use ends at 0x002b7328. C taunter_state is exactly this object-state snapshot, proving active taunter-use handling rather than a hero or type domain. --- src/overlays/shared/weapons/taunter.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/taunter.c b/src/overlays/shared/weapons/taunter.c index 887477f52e..c710087ec2 100644 --- a/src/overlays/shared/weapons/taunter.c +++ b/src/overlays/shared/weapons/taunter.c @@ -455,6 +455,10 @@ void taunter_update(Moby *m) __asm__("FUN_L00_002b6f10"); /* Moby class 175 */ void taunter_update(Moby *taunter_moby) { + enum { + TAUNTER_STATE_INITIALIZE = 0, + TAUNTER_STATE_ACTIVE = 2 + }; Vars *taunter_vars; s32 taunter_state; s32 voice_slot_index; @@ -475,7 +479,7 @@ void taunter_update(Moby *taunter_moby) { if (taunter_moby->type == 2) taunter_moby->state = 3; taunter_effect_emission_disabled = 1; - if (taunter_moby->state == 0) { + if (taunter_moby->state == TAUNTER_STATE_INITIALIZE) { taunter_vars->anim = -1; taunter_moby->state++; taunter_effect_reset_pending = 1; @@ -488,7 +492,7 @@ void taunter_update(Moby *taunter_moby) { } goto end; } - if ((u8)taunter_state != 2) + if ((u8)taunter_state != TAUNTER_STATE_ACTIVE) goto end; if (taunter_moby->type == 3 && hero.item_use_locked == 0) { taunter_effect_emission_disabled = 0; From a9afbf04351e3b989df859d9fc80974e5e8bd020 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:53:27 +0000 Subject: [PATCH 0860/1502] decomp: clarify names in update_path_or_ballistic_debris domain_0_value_0 -> DEBRIS_STATE_FOLLOW_PATH: Retail 0x002dfd38 loads moby+0x20 and 0x002dfd3c branches to ballistic integration at 0x002dfe78 only when nonzero. The zero branch loads the private path index at 0x002dfd44, selects the spline pointer at 0x002dfd58-0x002dfd60, and calls path sampling at 0x002dfd7c with moby position and private progress offsets +0x10/+0x14. It then records sampled displacement at 0x002dfd84-0x002dfdac. Original Ghidra likewise tests *(char *)(iVar4+0x20)==0 and advances the path. The bound source's emit_debris_trail_particles uses DEBRIS_STATE_FOLLOW_PATH=0 on the same moby->state domain, and the class-0x193 spawner stores mode in spawned_moby[0x20], initializing spline fields in its zero branch. This establishes the debris-specific member rather than any unrelated zero-valued Hero enum. --- src/overlays/shared/enemies/path_or_ballistic_debris.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/path_or_ballistic_debris.c b/src/overlays/shared/enemies/path_or_ballistic_debris.c index 4e7fccc426..3d685f5b67 100644 --- a/src/overlays/shared/enemies/path_or_ballistic_debris.c +++ b/src/overlays/shared/enemies/path_or_ballistic_debris.c @@ -69,14 +69,14 @@ void path_or_ballistic_debris_update(struct Moby *moby) __asm__("FUN_L14_002dfd1 /* Moby class 403 */ void path_or_ballistic_debris_update(struct Moby *moby) { - Data *debris_private_vars = (Data *)moby->pvars; + enum { DEBRIS_STATE_FOLLOW_PATH = 0 } ;Data *debris_private_vars = (Data *)moby->pvars; Vec4 probe; f32 position_offset[4]; f32 *velocity; void *points; f32 speed; - if (moby->state == 0) { + if (moby->state == DEBRIS_STATE_FOLLOW_PATH) { points = l14_splines[debris_private_vars->path].path; qcopy(&probe, &moby->pos); sample_path(points, From cc88bf3a1ec57bc8efb85d4b3a7e5b72a748395b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:53:28 +0000 Subject: [PATCH 0861/1502] decomp: clarify names in process_ultramech_hits_and_update_target domain_1_value_64 -> ULTRAMECH_DEAD_WAIT_FOR_RESET: Retail 0x002d1098 loads the caller moby's state byte at s2+0x20 and 0x002d10a0-0x002d10a4 excludes 0x40; source caches that same field in state. Supplied ultramech_unlimited_update passes this same moby and switches on its state, with established ULTRAMECH_DEAD_WAIT_FOR_RESET=0x40 disabling activity, clearing save bits and resetting when giant-Clank mode ends. This is the same Ultramech state domain, not HeroStateId. domain_2_value_2 -> ULTRAMECH_FOLLOW_ENTRY_PATH: Retail 0x002d10dc reloads the Ultramech state byte at s2+0x20; xori at 0x002d10e8 and movz at 0x002d10f0 force reaction code 9 for state 2. Supplied caller ultramech_unlimited_update switches on this identical field and names 2 ULTRAMECH_FOLLOW_ENTRY_PATH; its branch interpolates the entry path and advances moby position. Reuse that proven state-domain name, keeping reaction code 9 separate. domain_3_value_9 -> ULTRAMECH_KNOCKBACK_RECOVERY: Retail 0x002d11d8-0x002d1230 derives hit heading and initializes knockback at data+0x70, then 0x002d1248/0x002d1250 stores 9 to the Ultramech state byte at s2+0x20. Supplied caller switches on that same field with established ULTRAMECH_KNOCKBACK_RECOVERY=9 and steps this hit record until recovery before returning to movement or aiming. This assignment enters that state, distinct from reaction code 9. domain_4_value_10 -> ULTRAMECH_DEATH_EFFECTS: Original Ghidra death cases 1/2 and retail 0x002d125c-0x002d131c create the death effect and mark removal; 0x002d1300/0x002d1308 stores 10 to the moby state byte at s2+0x20. Supplied ultramech_unlimited_update uses that identical state field with ULTRAMECH_DEATH_EFFECTS=10, spawning effects and break fragments before entering 0x40. Reuse this established Ultramech state member, not a Hero or reaction constant. domain_5_value_1 -> ULTRAMECH_WAIT_FOR_ACTIVATION: Retail 0x002d1350 sets comparison value 1, 0x002d1368 loads the same Ultramech state byte at s2+0x20, and 0x002d136c branches to the data+0x174 targeting range for this state. Supplied caller switches on that exact field and names 1 ULTRAMECH_WAIT_FOR_ACTIVATION, testing activation group/volume and giant-Clank mode before beginning the entry path. This proves the state domain independently of classifier kind=1. --- src/overlays/l15/mobys/ultramech_unlimited.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/overlays/l15/mobys/ultramech_unlimited.c b/src/overlays/l15/mobys/ultramech_unlimited.c index db018a3cdb..22d94b1c08 100644 --- a/src/overlays/l15/mobys/ultramech_unlimited.c +++ b/src/overlays/l15/mobys/ultramech_unlimited.c @@ -982,6 +982,13 @@ void process_ultramech_hits_and_update_target(void *ultramech_instance) { HIT_REACTION_DAMAGE_WITHOUT_KNOCKBACK_ALTERNATE = 10, HIT_REACTION_NONE = 11 }; + enum { + ULTRAMECH_WAIT_FOR_ACTIVATION = 1, + ULTRAMECH_FOLLOW_ENTRY_PATH = 2, + ULTRAMECH_KNOCKBACK_RECOVERY = 9, + ULTRAMECH_DEATH_EFFECTS = 10, + ULTRAMECH_DEAD_WAIT_FOR_RESET = 0x40 + }; UMoby *ultramech_moby = ultramech_instance; UData *ultramech_vars = ultramech_moby->data; char *slot = 0; @@ -1019,12 +1026,12 @@ void process_ultramech_hits_and_update_target(void *ultramech_instance) { } code = FUN_00249d60(ultramech_moby, slot, &ultramech_vars->f20, 0, &kind, &impact, 0, 4); if (slot != 0) { - if (kind != 1 && (state = ultramech_moby->state) != 10 && state != 0x40 && + if (kind != 1 && (state = ultramech_moby->state) != 10 && state != ULTRAMECH_DEAD_WAIT_FOR_RESET && *(short *)(*(char **)(slot + 0x20) + 0xA6) != 0x350) { ultramech_vars->f20 -= impact; if (*(unsigned short *)(slot + 0x2A) == 0x100) code = 9; - if (ultramech_moby->state == 2) + if (ultramech_moby->state == ULTRAMECH_FOLLOW_ENTRY_PATH) code = 9; if (ultramech_vars->f20 <= 0.0f) code = 1; @@ -1074,7 +1081,7 @@ void process_ultramech_hits_and_update_target(void *ultramech_instance) { trooper_start_knockback( direction, ultramech_moby, (char *)ultramech_vars + 0x70, 8, 1, 0); trooper_play_sound(0, 0, ultramech_moby, 0x79); - ultramech_moby->state = 9; + ultramech_moby->state = ULTRAMECH_KNOCKBACK_RECOVERY; *(unsigned char *)((char *)ultramech_vars + 0x67) = 0x78; break; case HIT_REACTION_DEATH: @@ -1102,7 +1109,7 @@ void process_ultramech_hits_and_update_target(void *ultramech_instance) { hit, 0); trooper_play_sound(0, 0, ultramech_moby, 0x79); - ultramech_moby->state = 10; + ultramech_moby->state = ULTRAMECH_DEATH_EFFECTS; *(unsigned char *)((char *)ultramech_vars + 0x67) = 0xF0; mark_moby_for_removal_cf(ultramech_moby, 0x200, -1); break; @@ -1117,7 +1124,7 @@ void process_ultramech_hits_and_update_target(void *ultramech_instance) { *(float *)((char *)ultramech_moby + 0x2C) = *(float *)(ultramech_moby->cls + 0x24) * ultramech_post_hit_scale_multiplier_gp; ultramech_vars->w164 = 0; - if (ultramech_moby->state != 1) { + if (ultramech_moby->state != ULTRAMECH_WAIT_FOR_ACTIVATION) { if (ultramech_vars->w1D0 != -1) goto follow_path; ultramech_vars->f1B8 = *(float *)((char *)ultramech_vars + 0x178); From 4eb8691e7517d402e9720de919058bd335d56d43 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:55:16 +0000 Subject: [PATCH 0862/1502] decomp: clarify names in update_equalizer_ammo_spawner domain_0_value_1 -> EQUALIZER_AMMO_SPAWNER_WAIT_FOR_TRIGGER: Retail 0031d328 loads moby+0x20 and 0031d32c dispatches value 1 to 0031d484. That branch calls the clip-volume test at 0031d48c with pvars[0], returns without changing state when false, and processes the ammo list when true. Thus this moby-state member waits for its configured clip-volume trigger. domain_1_value_2 -> EQUALIZER_AMMO_SPAWNER_COMPLETE: Retail 0031d334-0031d338 returns for moby state >=2; the same byte loaded at 0031d328 is explicitly set to 2 at 0031d740-0031d744 after the sentinel ammo-list traversal. Value 2 marks completion of this spawner's list processing, even when ratio filtering caused no pickups to spawn. domain_2_value_0 -> EQUALIZER_AMMO_SPAWNER_INITIALIZE_PATH: Retail 0031d340 accepts only zero after excluding state 1 and states >=2. Its branch validates pvars[0] and pvars[1], then 0031d3b8-0031d45c clears the cached path total, computes per-segment distances and sums them before transitioning to state 1. This is the spawner path initialization state. domain_3_value_1 -> EQUALIZER_AMMO_SPAWNER_WAIT_FOR_TRIGGER: Retail 0031d474-0031d480 stores 1 into the same moby+0x20 byte read at 0031d328 after measuring the path. On subsequent dispatch value 1 reaches 0031d484-0031d494, which waits for the configured clip-volume test to succeed before processing ammo. Reuses the comparison's moby-state member. domain_4_value_2 -> EQUALIZER_AMMO_SPAWNER_COMPLETE: Retail 0031d730-0031d738 checks the ammo-list sentinel; at completion 0031d73c-0031d744 writes 2 to moby+0x20. Subsequent calls return through the >=2 guard at 0031d334-0031d338. This marks completion of list processing, not proof that any ammo was actually spawned. --- src/overlays/l07/mobys/equalizer_ammo_spawner.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l07/mobys/equalizer_ammo_spawner.c b/src/overlays/l07/mobys/equalizer_ammo_spawner.c index fa7100e256..f3c6cb82d0 100644 --- a/src/overlays/l07/mobys/equalizer_ammo_spawner.c +++ b/src/overlays/l07/mobys/equalizer_ammo_spawner.c @@ -44,13 +44,13 @@ void equalizer_ammo_spawner_update(struct Moby *moby) __asm__("FUN_L07_0031d2e0" /* Moby class 1142 */ void equalizer_ammo_spawner_update(struct Moby *moby) { - int *ammo_spawner_state = ((int *)moby->pvars); + enum { EQUALIZER_AMMO_SPAWNER_INITIALIZE_PATH = 0 , EQUALIZER_AMMO_SPAWNER_WAIT_FOR_TRIGGER = 1 , EQUALIZER_AMMO_SPAWNER_COMPLETE = 2 } ;int *ammo_spawner_state = ((int *)moby->pvars); int state = moby->state; - if (state == 1) + if (state == EQUALIZER_AMMO_SPAWNER_WAIT_FOR_TRIGGER) goto state_one; - if (state >= 2) + if (state >= EQUALIZER_AMMO_SPAWNER_COMPLETE) return; - if (state != 0) + if (state != EQUALIZER_AMMO_SPAWNER_INITIALIZE_PATH) return; { int bad = 0; @@ -76,7 +76,7 @@ void equalizer_ammo_spawner_update(struct Moby *moby) { *(float *)(ammo_spawner_state + 8) += ((L07PathNode *)(D_L07_001B0530[ammo_spawner_state[1]] + (i << 4)))[1].length; } - moby->state = 1; + moby->state = EQUALIZER_AMMO_SPAWNER_WAIT_FOR_TRIGGER; } return; state_one: { @@ -154,7 +154,7 @@ state_one: { } } } - moby->state = 2; + moby->state = EQUALIZER_AMMO_SPAWNER_COMPLETE; } } From 6ed728987753220f56eb7c4e2142d8819c8034e0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:55:16 +0000 Subject: [PATCH 0863/1502] decomp: clarify names in draw_menu_text_list domain_0_value_1 -> MENU_LIST_FONT_TEXTURE_NORMAL: Authoritative source initializes font_kind=1 alongside font_size=12 and normal_font_metrics. Retail 0x0021d4bc loads 0x001df050 and 0x0021d4d4 sets s3=1; absent size overrides, 0x0021d648-0x0021d64c passes s3 to get_effect_texture. Its returned texture reaches font_print_window at 0x0021d780-0x0021d784 together with the selected metrics. domain_1_value_3 -> MENU_LIST_FONT_TEXTURE_LARGE: Source flag 4 pairs font_kind=3 with font_size=14 and large_font_metrics. Retail 0x0021d4f8 tests bit 4; 0x0021d514-0x0021d520 sets size 14, metrics address 0x001df790 and s3=3. At 0x0021d648-0x0021d64c s3 selects get_effect_texture; that returned texture is supplied with these metrics to font_print_window. domain_2_value_2 -> MENU_LIST_FONT_TEXTURE_SMALL: Source flag 8 pairs font_kind=2 with font_size=10 and small_font_metrics. Retail 0x0021d524 tests bit 8; 0x0021d530-0x0021d53c sets size 10, metrics address 0x001df3f0 and s3=2. This overrides earlier font selection and flows through 0x0021d648-0x0021d64c into get_effect_texture, then into font_print_window alongside the small metrics. --- src/ui/menus/widgets/draw_menu_text_list.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ui/menus/widgets/draw_menu_text_list.c b/src/ui/menus/widgets/draw_menu_text_list.c index f8a04e518b..8ee62382e3 100644 --- a/src/ui/menus/widgets/draw_menu_text_list.c +++ b/src/ui/menus/widgets/draw_menu_text_list.c @@ -27,6 +27,11 @@ extern void *memset(void *, int, unsigned int); s32 draw_menu_text_list(struct MenuScreen *menu) __asm__("FUN_0021d4a8"); s32 draw_menu_text_list(struct MenuScreen *menu) { + enum { + MENU_LIST_FONT_TEXTURE_NORMAL = 1, + MENU_LIST_FONT_TEXTURE_SMALL = 2, + MENU_LIST_FONT_TEXTURE_LARGE = 3 + }; s32 font_size; s32 font_kind; s32 focused; @@ -44,17 +49,17 @@ s32 draw_menu_text_list(struct MenuScreen *menu) { s32 y; font_size = 12; - font_kind = 1; + font_kind = MENU_LIST_FONT_TEXTURE_NORMAL; font = normal_font_metrics; focused = menu_system.current->focus == menu; if (menu->data.list.flags & 4) { font_size = 14; - font_kind = 3; + font_kind = MENU_LIST_FONT_TEXTURE_LARGE; font = large_font_metrics; } if (menu->data.list.flags & 8) { font_size = 10; - font_kind = 2; + font_kind = MENU_LIST_FONT_TEXTURE_SMALL; font = small_font_metrics; } vu1_add_g_sregister(0x42, 0x44); From d85e7d8d51a3dc15a4df47b5b8e8add6b7b981c8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:55:16 +0000 Subject: [PATCH 0864/1502] decomp: clarify names in shuttle_update domain_0_value_0 -> SHUTTLE_STATE_INITIALIZE: Retail 0x002e7ce8 loads the shuttle Moby state byte at s3+0x20; 0x002e7cf4 skips initialization when nonzero. The zero branch 0x002e7cfc-0x002e7d70 copies the selected path's initial position into shuttle position, clears angle and transition state, sets sound to -1, attaches the manipulator, removes the shuttle if its rider target is absent, and captures initial height. Original Ghidra char owner+0x20 comparison and current shuttle_moby->state == 0 agree. This is shuttle initialization, unrelated to hero state IDs. domain_1_value_12345 -> SHUTTLE_RIDER_MODE_ATTACHED: Retail 0x002e7d80-0x002e7d94 compares 0x3039 with the private shuttle block's mode at s2+0x158, independently of the Moby state byte. Only this matching branch selects a joint position using anchor s2+0x154 or the shuttle position (0x002e7d9c-0x002e7dd0), builds a rotation matrix from shuttle rotation, rotates offset s2+0x160, and writes anchor plus rotated offset into the indexed rider's position at s4+0x10 (0x002e7dd8-0x002e7e04). The original decompilation and authoritative L14LiftVars mode comment corroborate attached-rider mode; this is a separate private mode domain. --- src/overlays/l14/mobys/shuttle.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/shuttle.c b/src/overlays/l14/mobys/shuttle.c index 562035c3d0..94541ccab8 100644 --- a/src/overlays/l14/mobys/shuttle.c +++ b/src/overlays/l14/mobys/shuttle.c @@ -63,6 +63,10 @@ void shuttle_update(struct Moby *m) __asm__("FUN_L14_002e7bd8"); /* Moby class 557 */ void shuttle_update(struct Moby *shuttle_moby) { + enum { + SHUTTLE_STATE_INITIALIZE = 0, + SHUTTLE_RIDER_MODE_ATTACHED = 0x3039 + }; L14LiftVars *shuttle_vars; Vec4 previous_shuttle_position; Vec4 rot; @@ -102,7 +106,7 @@ void shuttle_update(struct Moby *shuttle_moby) { } qcopy(&previous_shuttle_position, &shuttle_moby->pos); qcopy(&rot, &shuttle_moby->rot); - if (shuttle_moby->state == 0) { + if (shuttle_moby->state == SHUTTLE_STATE_INITIALIZE) { qcopy(&shuttle_moby->pos, ((char *)l14_paths[shuttle_vars->path]) + 0x10); shuttle_vars->angle = 0.0f; shuttle_vars->sound = -1; @@ -118,7 +122,7 @@ void shuttle_update(struct Moby *shuttle_moby) { } gunship_update(shuttle_moby); rider = &D_L14_0015FFD8_lift[shuttle_vars->rider]; - if (shuttle_vars->mode == 0x3039) { + if (shuttle_vars->mode == SHUTTLE_RIDER_MODE_ATTACHED) { if (shuttle_vars->anchor != -1) moby_point_position( shuttle_moby, shuttle_vars->anchor, &rider_attachment_origin_or_hero_position); From 828d76f8586a5f949bb06dfccc80ea37f8b156e1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:55:16 +0000 Subject: [PATCH 0865/1502] decomp: clarify names in spawn_enemy_fighter_exhaust domain_0_value_0 -> ENEMY_FIGHTER_STATE_INITIALIZE: Retail 0x002fc384/0x002fc388 passes the caller's unchanged Moby pointer s1 in a0; the assigned function retains it in s5 at 0x002fc3f4 and reads its current state at +0x20 (0x002fc424), returning for zero at 0x002fc428. The same caller byte selects zero's branch at 0x002fc22c, validates the flight path, calls initialize_flight_path_state at 0x002fc2a4, and stores FOLLOW_PATH=1 at 0x002fc2b0. The authoritative C names this exact domain member ENEMY_FIGHTER_STATE_INITIALIZE=0 in enemy_fighter_update; reuse that canonical member for the exhaust gate. domain_1_value_2 -> ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN: Retail caller 0x002fc384/0x002fc388 passes the same Moby pointer whose +0x20 byte the exhaust function compares against 2 at 0x002fc42c-0x002fc430. Caller stores 2 into that byte after a hit at 0x002fc194-0x002fc1ac, clears collision at 0x002fc1c4, and dispatches state 2 at 0x002fc23c to the respawn timer at 0x002fc2e4. On timer expiry it restores collision, resets path position and stores FOLLOW_PATH=1 at 0x002fc324-0x002fc344. The authoritative source names this member ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN=2; the identical pointer and field prove canonical domain reuse. --- src/overlays/l14/mobys/enemy_fighter.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/enemy_fighter.c b/src/overlays/l14/mobys/enemy_fighter.c index c552d9e8d3..3bbbb0cdb0 100644 --- a/src/overlays/l14/mobys/enemy_fighter.c +++ b/src/overlays/l14/mobys/enemy_fighter.c @@ -148,6 +148,10 @@ extern char D_L14_0015F580[] MACRO_ADDR; extern int exhaust_ftoi(float) __asm__("FUN_001fa6d0"); void spawn_enemy_fighter_exhaust(struct Moby *emitter_moby) { + enum { + ENEMY_FIGHTER_STATE_INITIALIZE = 0, + ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN = 2 + }; Vec4 step; Vec4 pos; Vec4 paired_exhaust_origin; @@ -159,7 +163,7 @@ void spawn_enemy_fighter_exhaust(struct Moby *emitter_moby) { int life; float size; - if (emitter_moby->state == 0 || emitter_moby->state == 2 || emitter_moby->visible == 0) + if (emitter_moby->state == ENEMY_FIGHTER_STATE_INITIALIZE || emitter_moby->state == ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN || emitter_moby->visible == 0) return; fast_vec_scale(&step, &emitter_moby->rot_row0, enemy_fighter_exhaust_base_row0_offset_gp); fast_vec_add(&pos, &emitter_moby->pos, &step); From b163403a9bb68f271ea36a2a1bf6fd3d25bbce76 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:55:16 +0000 Subject: [PATCH 0866/1502] decomp: clarify names in update_sliding_gate domain_0_value_1 -> GATE_WAIT_TO_OPEN: Retail 0x0029b034-0x0029b044 copies gate position to private home then stores 1 to the same s1+0x20 state byte dispatched at 0x0029b008. Existing GATE_WAIT_TO_OPEN case 1 clears travel and tests opening conditions. domain_3_value_2 -> GATE_OPENING: Retail 0x0029b118-0x0029b12c tests gate_vars open_volume and selects 2 for the s1+0x20 gate state store at 0x0029b474. The same selector's existing GATE_OPENING case 2 increases travel at 0x0029b184-0x0029b1b8. domain_4_value_2 -> GATE_OPENING: Retail 0x0029b130-0x0029b13c stores 2 to gate s1+0x20 when the trigger/save condition in s2 is true. This is the identical state byte dispatched by the existing GATE_OPENING case 2, whose handler advances gate travel. domain_5_value_5 -> GATE_OPEN_LATCHED: Retail 0x0029b1fc-0x0029b218 clamps travel to duration and invalidates sound on opening completion. The linked/locked branch 0x0029b21c-0x0029b298 sets both save-bit arrays and gate state 5, then applies the fully open position. Dispatch 0x0029b008-0x0029b010 excludes state 5 from all further updates, latching this handler's open position. domain_6_value_3 -> GATE_OPEN: Retail 0x0029b200-0x0029b218 selects 3 when opening completes without a linked trigger or lock, and 0x0029b29c stores it to gate s1+0x20. Existing GATE_OPEN case 3 at 0x0029b2f0 waits for both close-volume tests to clear. domain_7_value_4 -> GATE_CLOSING: Retail 0x0029b2f0-0x0029b324 selects gate state 4 only after both close-volume tests return zero; 0x0029b474 stores the same dispatched state byte. Existing GATE_CLOSING case 4 subtracts frame-scaled travel at 0x0029b378-0x0029b3a4. domain_8_value_1 -> GATE_WAIT_TO_OPEN: Retail 0x0029b3e8-0x0029b3f4 clears travel, invalidates sound and writes 1 to gate s1+0x20 after retraction. This returns to the same selector's existing GATE_WAIT_TO_OPEN case 1, which checks trigger/save/open-volume conditions. domain_9_value_2 -> GATE_OPENING: Retail 0x0029b44c-0x0029b474 tests open_volume during closing and stores 2 to gate s1+0x20 if either tested point is inside. This reenters the same selector's existing GATE_OPENING case 2, reversing travel toward the open endpoint. --- src/overlays/l15/mobys/sliding_gate.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/overlays/l15/mobys/sliding_gate.c b/src/overlays/l15/mobys/sliding_gate.c index c46f48f962..fa06957fea 100644 --- a/src/overlays/l15/mobys/sliding_gate.c +++ b/src/overlays/l15/mobys/sliding_gate.c @@ -47,6 +47,9 @@ void sliding_gate_update(struct Moby *gate_moby) { GATE_OPEN = 3, GATE_CLOSING = 4 }; + enum { + GATE_OPEN_LATCHED = 5 + }; MovingVars *gate_vars = (MovingVars *)gate_moby->pvars; Vec4 offset; Vec4 pos; @@ -59,7 +62,7 @@ void sliding_gate_update(struct Moby *gate_moby) { switch (gate_moby->state) { case GATE_INITIALIZE: gate_vars->home.q = *(u128 *)&gate_moby->pos; - gate_moby->state = 1; + gate_moby->state = GATE_WAIT_TO_OPEN; return; case GATE_WAIT_TO_OPEN: trigger_active = 0; @@ -87,9 +90,9 @@ void sliding_gate_update(struct Moby *gate_moby) { trigger_active = 1; } if (is_point_inside_clip_volume(D_0013F3D0, gate_vars->open_volume)) { - gate_moby->state = 2; + gate_moby->state = GATE_OPENING; } else if (trigger_active) { - gate_moby->state = 2; + gate_moby->state = GATE_OPENING; } return; case GATE_OPENING: @@ -114,9 +117,9 @@ void sliding_gate_update(struct Moby *gate_moby) { (((s16)gate_moby->save_id >> 5) * 4 + current_level_index * 0x100)); *bits |= mask; D_L15_001BAAD0[((s16)gate_moby->save_id >> 5)] |= 1U << (gate_moby->save_id & 31); - gate_moby->state = 5; + gate_moby->state = GATE_OPEN_LATCHED; } else { - gate_moby->state = 3; + gate_moby->state = GATE_OPEN; } } offset.f[0] = fast_cos(gate_moby->rot.z) * -gate_vars->travel; @@ -129,7 +132,7 @@ void sliding_gate_update(struct Moby *gate_moby) { if (is_point_inside_clip_volume(D_0013F3D0, gate_vars->close_volume) || is_point_inside_clip_volume(D_L15_001673C0, gate_vars->close_volume)) return; - gate_moby->state = 4; + gate_moby->state = GATE_CLOSING; return; case GATE_CLOSING: if (((VoiceSlot_29aff0 *)(((char *)&voice_pool) + gate_vars->sound * 0x70))->owner != @@ -145,7 +148,7 @@ void sliding_gate_update(struct Moby *gate_moby) { release_voice_slot(slot); gate_vars->travel = 0; gate_vars->sound = -1; - gate_moby->state = 1; + gate_moby->state = GATE_WAIT_TO_OPEN; } offset.f[0] = fast_cos(gate_moby->rot.z) * -gate_vars->travel; offset.f[1] = fast_sin(gate_moby->rot.z) * -gate_vars->travel; @@ -154,7 +157,7 @@ void sliding_gate_update(struct Moby *gate_moby) { *(u128 *)&gate_moby->pos = pos.q; if (is_point_inside_clip_volume(D_0013F3D0, gate_vars->open_volume) || is_point_inside_clip_volume(D_L15_001673C0, gate_vars->open_volume)) - gate_moby->state = 2; + gate_moby->state = GATE_OPENING; return; default: return; From 7114e5bb791b1c772092fff99864c7d1c5f3a563 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:55:16 +0000 Subject: [PATCH 0867/1502] decomp: clarify names in update_camera_transition domain_0_value_1 -> STATE_IDLE: Retail 0x002df650-0x002df660 initializes update distance to 0xFF and stores 1 at moby+0x20, the same byte loaded as the dispatcher selector at 0x002df624. Original Ghidra has no case-1 work and routes it through default to 0x002dfa84; authoritative C likewise has no case 1. Thus this assignment enters the idle state of this transition updater. domain_1_value_4 -> STATE_INTERPOLATE_TRANSITION_WITH_RAMP_UP: Retail 0x002df700-0x002df720 tests pvars+0x78 and stores 4 at moby+0x20 after help_request. That is the exact selector loaded at 0x002df624. Authoritative C already names its case 4 STATE_INTERPOLATE_TRANSITION_WITH_RAMP_UP; retail 0x002df870-0x002df918 interpolates endpoints and 0x002df974-0x002df998 ramps +0x6C toward 1. Reuse the existing same-domain member. domain_2_value_3 -> STATE_INTERPOLATE_TRANSITION: Retail 0x002df704-0x002df708 selects 3 when pvars+0x78 is not 1 and branches to the state-byte store at 0x002dfa80. The byte at moby+0x20 is the switch selector. Existing case STATE_INTERPOLATE_TRANSITION = 3 advances +0x60 and interpolates configured position/rotation endpoints at 0x002df730-0x002df7d0, proving this assignment reuses that exact local domain. domain_3_value_5 -> STATE_POST_TRANSITION_RAMP_DOWN: Retail 0x002df804-0x002df850 detects completed interpolation, clears camera_transition_active, restores setup, calls completion with argument 2, then selects 5 for the moby+0x20 state store at 0x002dfa80. The same selector already has STATE_POST_TRANSITION_RAMP_DOWN = 5; its retail branch 0x002dfa40-0x002dfa78 approaches pvars+0x6C toward zero. domain_4_value_5 -> STATE_POST_TRANSITION_RAMP_DOWN: Retail 0x002df98c-0x002df9e0 completes the ramp-up interpolation variant when pvars+0x6C reaches 1, clears the active flag, fixes progress to 1 and calls completion with argument 3, then selects 5 for the moby+0x20 store at 0x002dfa80. This is the same dispatcher byte and existing STATE_POST_TRANSITION_RAMP_DOWN = 5 branch, which ramps +0x6C down. domain_5_value_1 -> STATE_IDLE: Retail 0x002dfa40-0x002dfa54 checks whether pvars+0x6C remains positive in state 5. Once not positive, 0x002dfa7c-0x002dfa80 stores 1 in moby+0x20, the dispatcher selector at 0x002df624. Original Ghidra and authoritative C perform no work for state 1 and return through default, proving this is the idle destination after post-transition ramp-down. --- src/overlays/l18/mobys/camera_transition.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l18/mobys/camera_transition.c b/src/overlays/l18/mobys/camera_transition.c index 753df30dc6..a9d9f6383f 100644 --- a/src/overlays/l18/mobys/camera_transition.c +++ b/src/overlays/l18/mobys/camera_transition.c @@ -71,12 +71,12 @@ void boss_camera_transition_update(struct Moby *moby) { STATE_INTERPOLATE_TRANSITION = 3, STATE_INTERPOLATE_TRANSITION_WITH_RAMP_UP = 4, STATE_POST_TRANSITION_RAMP_DOWN = 5 - }; + } ; enum { STATE_IDLE = 1}; BossCameraTransitionVars *transition_private_vars = (BossCameraTransitionVars *)moby->pvars; float transition_scratch_vectors[12]; switch (moby->state) { case STATE_INITIALIZE: - moby->state = 1; + moby->state = STATE_IDLE; moby->update_dist = 0xFF; break; case STATE_PRE_TRANSITION_RAMP_UP: @@ -97,9 +97,9 @@ void boss_camera_transition_update(struct Moby *moby) { transition_private_vars, &transition_private_vars->unk20, 1, 0, 0); if (transition_private_vars->unk78 == 1) { help_request(0x4650, 0x85); - moby->state = 4; + moby->state = STATE_INTERPOLATE_TRANSITION_WITH_RAMP_UP; } else { - moby->state = 3; + moby->state = STATE_INTERPOLATE_TRANSITION; } } } @@ -142,7 +142,7 @@ void boss_camera_transition_update(struct Moby *moby) { FUN_L00_00216f90_q( &transition_private_vars->unk40, transition_scratch_vectors + 8, 0, 0); jet_end_mount(2); - moby->state = 5; + moby->state = STATE_POST_TRANSITION_RAMP_DOWN; } else if (*(int *)(camera_secondary_mode_lui) != 0x72) { clear_u64_value(transition_scratch_vectors + 8); transition_scratch_vectors[10] = transition_private_vars->unk4C; @@ -193,7 +193,7 @@ void boss_camera_transition_update(struct Moby *moby) { FUN_L00_00216f90_q( &transition_private_vars->unk40, transition_scratch_vectors + 8, 0, 0); jet_end_mount(3); - moby->state = 5; + moby->state = STATE_POST_TRANSITION_RAMP_DOWN; } } else if (*(int *)(camera_secondary_mode_lui) != 0x72) { clear_u64_value(transition_scratch_vectors + 8); @@ -211,7 +211,7 @@ void boss_camera_transition_update(struct Moby *moby) { approach_value(&transition_private_vars->unk6C, 0.0f, (*(float *)&frame_time) * 4.0f); D_L18_0015F3FC_d = transition_private_vars->unk6C; } else { - moby->state = 1; + moby->state = STATE_IDLE; } break; } From 9cbbc256f7fa992313f455df9aab13180df30d82 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:55:16 +0000 Subject: [PATCH 0868/1502] decomp: clarify names in drek_fight_missile_update domain_0_value_4 -> DREK_MISSILE_WAIT_TO_EXPLODE: Retail 0x002efbac loads this missile's state byte at s2+0x20 and 0x002efbb0 bypasses roll only for 4. The same byte is dispatched at 0x002efc48 into the timer/explosion branch 0x002efedc-0x002eff9c, already labeled DREK_MISSILE_WAIT_TO_EXPLODE in the source's DrekMissileState enum and switch; this is the exact same selector domain. domain_1_value_1 -> DREK_MISSILE_WAIT_FOR_ACTIVATION: Retail 0x002efd00-0x002efd18 stores state 1 at moby+0x20 after target/ground initialization, sets flags bit 1, clears collision +0x94 and visibility +0x31. The retail dispatch 0x002efc1c-0x002efc38 leaves state 1 without movement. Supplied activate_drek_fight_missiles_in_group selects class 0x54B with this same state byte equal to 1, copies the activation position, records the caller, restores visibility/collision and assigns state 2. Thus 1 waits for activation, distinct from the moving wander state 2. domain_2_value_3 -> DREK_MISSILE_DIVE: Retail 0x002efd54-0x002efd60 assigns 3 to the same moby state byte +0x20 after the wander random gate succeeds, then seeds movement at pvars+0x130/+0x134/+0x138. Dispatch 0x002efc40 routes state 3 to 0x002efdac, blending motion toward the sampled ground anchor and testing ground crossing. The authoritative source already calls this branch DREK_MISSILE_DIVE in DrekMissileState. domain_3_value_4 -> DREK_MISSILE_WAIT_TO_EXPLODE: Retail 0x002efe74-0x002efe84 compares the projected position Z against ground height pvars+0x128. On crossing, 0x002efe98-0x002efeb8 stores 4 at moby+0x20 and initializes pvars+0x160 with scale_game_frames(90). The same selector dispatches 4 to the timer/explosion branch, canonically named DREK_MISSILE_WAIT_TO_EXPLODE in the existing source enum. domain_4_value_2 -> DREK_MISSILE_WANDER: Retail 0x002efc1c loads s0=2 and dispatches the moby state byte +0x20 equal to 2 to wander steering at 0x002efd1c. After the explosion timer expires, 0x002eff34 stores that same s0=2 into the same state byte and clears trail length before explosion/reset. This returns to the established DREK_MISSILE_WANDER branch of the existing DrekMissileState enum. --- src/overlays/l18/mobys/drek_fight_missile.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l18/mobys/drek_fight_missile.c b/src/overlays/l18/mobys/drek_fight_missile.c index 2361a69d51..0a48e9deff 100644 --- a/src/overlays/l18/mobys/drek_fight_missile.c +++ b/src/overlays/l18/mobys/drek_fight_missile.c @@ -122,8 +122,8 @@ typedef struct DrekFightMissileVars { /* Moby class 1355 */ void drek_fight_missile_update(struct Moby *moby) { - DrekFightMissileVars *missile_vars = (DrekFightMissileVars *)moby->pvars; - if (moby->state != 4) { + enum { DREK_MISSILE_WAIT_FOR_ACTIVATION = 1 } ;DrekFightMissileVars *missile_vars = (DrekFightMissileVars *)moby->pvars; + if (moby->state != DREK_MISSILE_WAIT_TO_EXPLODE) { moby->rot.x = fast_add_rotations(moby->rot.x, *(float *)&l18_drek_missile_roll_rate_degrees_gp * DEG_TO_RAD * frame_time); @@ -146,7 +146,7 @@ void drek_fight_missile_update(struct Moby *moby) { missile_vars->unk128 += 5.0f; missile_vars->unk128 = probe_ground_height(&missile_vars->unk120, 0, 0.5f); select_drek_fight_missile_wander_target(moby, &missile_vars->unk110); - moby->state = 1; + moby->state = DREK_MISSILE_WAIT_FOR_ACTIVATION; moby->flags |= 1; moby->visible = 0; moby->collision = 0; @@ -161,7 +161,7 @@ void drek_fight_missile_update(struct Moby *moby) { if (random_integer_below(*(int *)&l18_drek_missile_wander_to_dive_random_bound_gp)) { return; } - moby->state = 3; + moby->state = DREK_MISSILE_DIVE; missile_vars->unk130[0] = fast_cos(moby->rot.z) * (*(float *)&l18_drek_missile_wander_horizontal_speed_gp * frame_time); missile_vars->unk130[1] = @@ -191,7 +191,7 @@ void drek_fight_missile_update(struct Moby *moby) { if (ground_check_position[2] < missile_vars->unk128) { float minimum_missile_height; func_0022ED80_2F0F78(1, 0, (int)moby); - moby->state = 4; + moby->state = DREK_MISSILE_WAIT_TO_EXPLODE; missile_vars->timer_160 = scale_game_frames(0x5A); minimum_missile_height = missile_vars->unk128 + 0.7f; if (moby->pos.z < minimum_missile_height) { @@ -209,7 +209,7 @@ void drek_fight_missile_update(struct Moby *moby) { if (fast_dec_timer(&missile_vars->timer_160)) { int i; char *pos = &moby->pos; - moby->state = 2; + moby->state = DREK_MISSILE_WANDER; missile_vars->unk164 = 0; spawn_explosion(missile_vars->unk16C, D_L18_0015F580, From 47d709c99a7f3380d797ac78b6621b5c92e46a1e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:57:02 +0000 Subject: [PATCH 0869/1502] decomp: clarify names in draw_health_hud_panel domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x00239828 forms hero base 0x0013f350; 0x0023985c loads byte hero+0x20a4 (0x001413f4), the authoritative hero.vehicle_mode field, and 0x00239838/0x00239860 compares it with 2 to skip rendering. This proves the supplied HeroVehicleMode selector domain; reuse canonical HERO_VEHICLE_MODE_GIANT_CLANK=2 from include/rnc/hero/hero_state.h, consistent with the same field and constant in draw_hud_bolt_exclamation_panel. domain_1_value_0 -> FALSE: Retail 0x00239870 loads pal_mode at gp-0x7e80; 0x00239874 branches on zero to base-Y+18 at 0x00239888-0x0023988c, while nonzero selects base-Y+10 at 0x0023987c-0x00239884. Authoritative source expresses pal_mode != 0, a boolean false test, matching the existing FALSE usage on pal_mode in draw_hud_bolt_exclamation_panel. domain_2_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0023997c reconstructs hero base 0x0013f350 and 0x00239990 loads the same byte +0x20a4 used by the early vehicle-mode gate. 0x00239980/0x002399b0 compares it with 1, then loads hero+0x22ac (hero.health.vehicle_mode_hp) into the icon-count selector at sp+0x14. The selector is explicitly hero.vehicle_mode in authoritative source, proving HeroVehicleMode and canonical HERO_VEHICLE_MODE_CLANK=1. domain_3_value_8 -> HEALTH_HUD_EIGHT_ICON_CAPACITY: Retail 0x00239998-0x002399bc stores hero_max_health or vehicle_mode_hp at sp+0x14; 0x002399c0-0x002399e4 compares that count with 8 and selects l00_health_hud_eight_capacity_icon_offsets at 0x0017e478 with two 48-wide half-panels. 0x00239b50-0x00239c80 uses that same count as the upper bound for 0x7536 health-icon drawing. Thus 8 is an eight-icon health HUD capacity, not a state ID. domain_4_value_5 -> HEALTH_HUD_FIVE_ICON_CAPACITY: Retail 0x002399fc-0x00239a20 compares the sp+0x14 health count with 5 and selects l00_health_hud_five_capacity_icon_offsets at 0x0017e460; 0x00239a08-0x00239a40 computes 32/16 half-width rows. The count originates from hero_max_health or vehicle_mode_hp at 0x00239998-0x002399bc and bounds the health-icon loop at 0x00239c74-0x00239c80. This proves five-icon health HUD capacity, separate from HeroStateId and HeroVehicleMode. --- .../shared/ui/hud/draw_hud_item_selector_panel.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c index 04e1bb93f8..c37658a0b4 100644 --- a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c +++ b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c @@ -1016,6 +1016,10 @@ extern Pt l00_health_hud_five_capacity_icon_offsets[] __asm__("D_L00_0017E460") s32 draw_health_hud_panel(Hud *hud_element) __asm__("FUN_L00_00239810"); s32 draw_health_hud_panel(Hud *hud_element) { + enum { + HEALTH_HUD_FIVE_ICON_CAPACITY = 5, + HEALTH_HUD_EIGHT_ICON_CAPACITY = 8 + }; s32 x; s32 y; s32 cnt; @@ -1038,12 +1042,12 @@ s32 draw_health_hud_panel(Hud *hud_element) { Pt *e; u8 *visibility_counters; - if (hero.vehicle_mode == 2) + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) goto out; if (hero.state.current == 0x32) goto out; x = hud_element->x; - if (pal_mode != 0) + if (pal_mode != FALSE) y = health_hud_base_y_offset + 10; else y = health_hud_base_y_offset + 0x12; @@ -1070,13 +1074,13 @@ s32 draw_health_hud_panel(Hud *hud_element) { mode = hero_max_health; if (cnt == 0) sel = 0x1E; - if (hero.vehicle_mode == 1) + if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) mode = hero.health.vehicle_mode_hp; - if (mode == 8) { + if (mode == HEALTH_HUD_EIGHT_ICON_CAPACITY) { tab = l00_health_hud_eight_capacity_icon_offsets; first_panel_half_width = truncate_float_to_s32(ratio_x * 48.0f); second_panel_half_width = truncate_float_to_s32(ratio_x * 48.0f); - } else if (mode == 5) { + } else if (mode == HEALTH_HUD_FIVE_ICON_CAPACITY) { tab = l00_health_hud_five_capacity_icon_offsets; first_panel_half_width = truncate_float_to_s32(ratio_x * 32.0f); second_panel_half_width = truncate_float_to_s32(ratio_x * 16.0f); From df67f0f80069991ba379953aa1c62c417708d1d6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:57:02 +0000 Subject: [PATCH 0870/1502] decomp: clarify names in update_bolt_thief_mine domain_0_value_1 -> FLOAT_MINE_ACTIVE: The source initializes height and spin in FLOAT_MINE_INITIALIZE before assigning moby->state = 1. Retail 0x002ff654 loads s0=1; 0x002ff738 stores s0 to moby+0x20 after spin initialization. That exact byte is loaded at 0x002ff664 and compared to 1 at 0x002ff668 to enter 0x002ff750, the existing FLOAT_MINE_ACTIVE hit/height/explosion branch. This proves reuse of the same local enum domain. domain_1_value_1 -> FLOAT_MINE_ACTIVE: In the linked initialization path, retail 0x002ff73c reads the linked object's signed state and 0x002ff740-0x002ff744 stores s0=1 to this mine's moby+0x20 when that state is negative. The selector at 0x002ff664-0x002ff668 reads this same mine byte and dispatches value 1 to the active branch at 0x002ff750. The source already names that same selector case FLOAT_MINE_ACTIVE; this is not the linked object's state domain. domain_2_value_2 -> FLOAT_MINE_WAIT_OFFSCREEN_RESPAWN: Following the explosion calls and respawn-address comparison, retail 0x002ff9c8 loads 2 and 0x002ff9d4 writes it to mine moby+0x20; 0x002ff9d0-0x002ff9e4 sets hiding flags and clears collision. The same selector byte is compared to 2 at 0x002ff68c and dispatches to 0x002ff9f8, the source's existing FLOAT_MINE_WAIT_OFFSCREEN_RESPAWN case, which checks the position sphere and restores activity/collision after the visibility result is -1. domain_3_value_1 -> FLOAT_MINE_ACTIVE: Within the existing FLOAT_MINE_WAIT_OFFSCREEN_RESPAWN case, retail 0x002ffa18-0x002ffa24 checks the sphere helper result against -1. On that path 0x002ffa30 stores s0=1 to moby+0x20, 0x002ffa34 clears the disabled flags and 0x002ffa38-0x002ffa44 restores class collision. The byte read at 0x002ff664 dispatches 1 to the same existing FLOAT_MINE_ACTIVE branch at 0x002ff750, proving the canonical local constant for reactivation. --- src/overlays/shared/enemies/bolt_thief_mine.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/enemies/bolt_thief_mine.c b/src/overlays/shared/enemies/bolt_thief_mine.c index 16820d0796..5ccec5dffc 100644 --- a/src/overlays/shared/enemies/bolt_thief_mine.c +++ b/src/overlays/shared/enemies/bolt_thief_mine.c @@ -93,9 +93,9 @@ void bolt_thief_mine_update(struct Moby *moby) { floating_mine_private_vars->spin[0] = random_float_between(0.010471975f, 0.020943951f); floating_mine_private_vars->spin[1] = random_float_between(0.006981317f, 0.013962634f); floating_mine_private_vars->spin[2] = random_float_between(0.0034906585f, 0.006981317f); - moby->state = 1; + moby->state = FLOAT_MINE_ACTIVE; } else if ((s8)floating_mine_private_vars->link->state < 0) { - moby->state = 1; + moby->state = FLOAT_MINE_ACTIVE; } break; case FLOAT_MINE_ACTIVE: { @@ -163,7 +163,7 @@ void bolt_thief_mine_update(struct Moby *moby) { -1, 0); if ((char *)moby < floating_mine_respawn_address_limit) { - moby->state = 2; + moby->state = FLOAT_MINE_WAIT_OFFSCREEN_RESPAWN; moby->flags |= 0x41; moby->hit_slot = 0xFF; moby->collision = 0; @@ -180,7 +180,7 @@ void bolt_thief_mine_update(struct Moby *moby) { qcopy(scratch.sphere, &moby->pos); scratch.sphere[3] = 3.0f; if (fast_bsphere_check(scratch.sphere, 64.0f) == -1) { - moby->state = 1; + moby->state = FLOAT_MINE_ACTIVE; moby->flags &= 0xFFBE; moby->collision = moby->pclass->collision; } From 8e87079ed062e8f064387b4ab6d10d82664d01bb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:57:02 +0000 Subject: [PATCH 0871/1502] decomp: clarify names in reset_camera_state_and_prepare_preset_paths domain_1_value_3 -> CAMERA_PRESET_KIND_GRINDRAIL_PATH: Retail 0x00314ee4-0x00314ef8 resolves the CameraPreset row into s6; 0x00314f04-0x00314f1c compares its +0x30 kind to 3 and selects focus distance 0.5. The supplied initialize_camera_transform_and_paths resolves the same preset-row domain and already names its kind==3 comparison CAMERA_PRESET_KIND_GRINDRAIL_PATH, before calling this reset. Reuse that established same-domain name. domain_3_value_2 -> CAMERA_PRESET_KIND_MAPPED_PATHS: Retail 0x00315050-0x00315064 tests CameraPreset +0x30 kind against 2 and +0x34 ready against zero. The gated block resolves track/preset/look paths and target spline at 0x00315068-0x003150b4, maps preset points onto track segments at 0x003150fc-0x00315118 and look points onto target segments at 0x0031522c-0x00315248, then stores wrapped path-length metadata. The supplied update function consumes these mapped segment ranges and lengths in its same CameraPreset.kind==2 branch to derive camera distance from hero path progress. --- src/overlays/shared/camera/grindrail_camera.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/camera/grindrail_camera.c b/src/overlays/shared/camera/grindrail_camera.c index 4edea65f37..ec082b8122 100644 --- a/src/overlays/shared/camera/grindrail_camera.c +++ b/src/overlays/shared/camera/grindrail_camera.c @@ -115,6 +115,10 @@ extern s32 FUN_L00_0025df68(void *, void *, void *, s32 *, f32 *, s void reset_camera_state_and_prepare_preset_paths(Camera *destination_camera) __asm__("FUN_L01_00314e98"); void reset_camera_state_and_prepare_preset_paths(Camera *destination_camera) { + enum { + CAMERA_PRESET_KIND_MAPPED_PATHS = 2, + CAMERA_PRESET_KIND_GRINDRAIL_PATH = 3 + }; Vec4 at; s32 seg; f32 path_fraction_or_length; @@ -132,7 +136,7 @@ void reset_camera_state_and_prepare_preset_paths(Camera *destination_camera) { focus = &destination_camera->orbit->focus; focus->dist = 1.5f; focus->state = 0; - if (preset->kind == 3) { + if (preset->kind == CAMERA_PRESET_KIND_GRINDRAIL_PATH) { focus->dist = 0.5f; } control = &destination_camera->control; @@ -169,7 +173,7 @@ void reset_camera_state_and_prepare_preset_paths(Camera *destination_camera) { blend->unk8 = 0; blend->unkC = 0; blend->unk10 = 1; - if (preset->kind == 2 && preset->ready == 0) { + if (preset->kind == CAMERA_PRESET_KIND_MAPPED_PATHS && preset->ready == 0) { track_path = ((CameraPath *)l01_paths[preset->track_path]); target_path = (CameraPath *)l01_splines[preset->target].path; preset_path = ((CameraPath *)l01_paths[preset->path]); From 5eadfe7e2880a3c2441cb483ac49678481ef2b39 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:58:46 +0000 Subject: [PATCH 0872/1502] decomp: clarify names in draw_level_selection_map domain_0_value_0 -> FALSE: The authoritative source tests pal_mode != 0 before scaling marker_y by 448/416. Retail 0x001fd8d0-0x001fd8dc loads D_0015ED80 and branches on zero to 0x001fd904, bypassing the multiplication/division at 0x001fd8e4-0x001fd900. Original Ghidra names the same selector g_nPalVideoMode and shows its nonzero test guarding that scaling. Thus zero is the false value of this PAL-mode flag, fitting the supplied existing FALSE=0 constant rather than a pointer NULL or an inferred video-standard enum. --- src/ui/map/level_selection/draw_level_selection_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/map/level_selection/draw_level_selection_map.c b/src/ui/map/level_selection/draw_level_selection_map.c index ce5d93b8ea..6cdd3aadc6 100644 --- a/src/ui/map/level_selection/draw_level_selection_map.c +++ b/src/ui/map/level_selection/draw_level_selection_map.c @@ -78,7 +78,7 @@ void draw_level_selection_map(s32 left, s32 right, s32 top, s32 bottom) { } marker_x = level_map_markers[level_index].x; marker_y = level_map_markers[level_index].y; - if (pal_mode != 0) { + if (pal_mode != FALSE) { marker_y = marker_y * 0x1C0 / 0x1A0; } if (availability == 3 || From 6e86b06078a235bc5ae75d5d8ae4f678d484d6f1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:58:46 +0000 Subject: [PATCH 0873/1502] decomp: clarify names in veldin_ship_draw domain_0_value_1 -> VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING: Retail 0x002d1ab8-0x002d1ac0 reads moby state byte +0x20 and admits state 1 to reflection updates regardless of camera proximity. The supplied veldin_ship_update source initializes this same moby state to its existing local VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING member and registers veldin_ship_draw with the same moby pointer. domain_1_value_1 -> VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING: Retail 0x002d1c0c-0x002d1c28 compares the same moby+0x20 state with 1 and bypasses previous-UV interpolation, directly initializing reflection UV pairs. This is the same state initialized by the supplied veldin_ship_update as VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING, not the separate command byte at +0xbc. domain_2_value_1 -> VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING: Retail 0x002d1c94-0x002d1cbc finishes the 102-vertex UV loop, tests moby+0x20 against state 1, then writes state 2. The test recognizes completion of the reflection initialization requested by the existing VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING state in the supplied update source. domain_3_value_2 -> VELDIN_SHIP_STATE_REFLECTION_INITIALIZED: Retail 0x002d1ca4-0x002d1cbc writes 2 to the same moby state byte +0x20 only after state 1 has forced direct reflection-UV initialization across all 102 vertices. Thus 2 records completed reflection initialization; subsequent frames recompute by proximity and timer rather than taking the state-1 initialization override. --- src/overlays/shared/vehicles/veldin_ship.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/vehicles/veldin_ship.c b/src/overlays/shared/vehicles/veldin_ship.c index 45fa3d147f..4354ac7317 100644 --- a/src/overlays/shared/vehicles/veldin_ship.c +++ b/src/overlays/shared/vehicles/veldin_ship.c @@ -69,6 +69,10 @@ extern s32 veldin_ship_visibility_selector[] __asm__("D_L00_0016C890"); void veldin_ship_draw(struct Moby *moby) __asm__("FUN_L00_002d19b0"); void veldin_ship_draw(struct Moby *moby) { + enum { + VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING = 1, + VELDIN_SHIP_STATE_REFLECTION_INITIALIZED = 2 + }; Quad_2d19b0 quad; Vec_2d19b0 normal, reflection, view; u8 *ship_render_state = ((u8 *)moby->pvars); @@ -84,7 +88,7 @@ void veldin_ship_draw(struct Moby *moby) { if (absolute_float(l00_camera.pos.f[0] - moby->pos.x) < 16.0f && absolute_float(l00_camera.pos.f[1] - moby->pos.y) < 16.0f) active = 1; - if (active || moby->state == 1) { + if (active || moby->state == VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING) { moby->command = 1; fast_dec_timer((s32 *)(ship_render_state + 0x40)); blend = convert_integer_to_float(*(s32 *)(ship_render_state + 0x40)); @@ -103,7 +107,7 @@ void veldin_ship_draw(struct Moby *moby) { reflection.z += 1.0f; reflection_projection_factor = square_root(reflection.z + reflection.z); reflection_projection_factor += reflection_projection_factor; - if (moby->state == 1 || *(s32 *)(ship_render_state + 0x40) == 0) { + if (moby->state == VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING || *(s32 *)(ship_render_state + 0x40) == 0) { ship_reflection_uvs[i][0] = reflection.x / reflection_projection_factor + 0.5f; ship_reflection_uvs[i][1] = reflection.y / reflection_projection_factor + 0.5f; } else { @@ -114,8 +118,8 @@ void veldin_ship_draw(struct Moby *moby) { ship_reflection_uvs[i][1] = x + (ship_previous_uvs[i][1] - x) * blend; } } - if (moby->state == 1) - moby->state = 2; + if (moby->state == VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING) + moby->state = VELDIN_SHIP_STATE_REFLECTION_INITIALIZED; } else { if (moby->command == 1) { moby->command = 0; From bb668c00779215c4735b29597f7e64bc4a698e09 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:00:35 +0000 Subject: [PATCH 0874/1502] decomp: clarify names in build_packet_and_draw_scaled_entries domain_0_value_1 -> TEXTURED_GRID_USE_CURRENT_VIEW_SETTINGS: Retail 002c19b8 reads 0015f458 (textured_grid_view_settings_mode); s5 is set to 1 at 002c1990. The beq at 002c19e4 skips 002c19ec-002c1a08, preserving view+218/+21c/+228/+22c instead of loading surface_draw_settings+20/+24/+28/+2c. The same selector is reread at 002c1c20 and value 1 selects view RGB at +230/+234/+238. Thus this value selects current view settings, not a moby-state or Boolean domain. domain_1_value_1 -> TEXTURED_GRID_USE_CURRENT_VIEW_SETTINGS: Retail 002c1c20 rereads the same 0015f458 settings-source selector; 002c1c48 branches past the view RGB loads when it differs from s5=1. Equality executes 002c1c50-002c1c6c, packing view+230/+234/+238 instead of surface_draw_settings bytes +30/+31/+32 for the packet. Together with 002c19e4 preserving the view fog fields for this same value, this proves reuse of TEXTURED_GRID_USE_CURRENT_VIEW_SETTINGS. --- src/overlays/l09/draw_level09_textured_surfaces.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l09/draw_level09_textured_surfaces.c b/src/overlays/l09/draw_level09_textured_surfaces.c index 5535558107..aa2d5d8406 100644 --- a/src/overlays/l09/draw_level09_textured_surfaces.c +++ b/src/overlays/l09/draw_level09_textured_surfaces.c @@ -218,6 +218,9 @@ void build_packet_and_draw_scaled_entries(void *data_ptr, int count) __asm__("FUN_L09_002c1978"); void build_packet_and_draw_scaled_entries(void *data_ptr, void *list_ptr, int count) { + enum { + TEXTURED_GRID_USE_CURRENT_VIEW_SETTINGS = 1 + }; char *surface_draw_settings = data_ptr; char *list = list_ptr; int i; @@ -240,7 +243,7 @@ void build_packet_and_draw_scaled_entries(void *data_ptr, void *list_ptr, int co saved_textured_grid_fog_far_distance = saved1; saved_textured_grid_fog_near_intensity = saved2; D_L09_00161304 = saved3; - if (textured_grid_view_settings_mode != 1) { + if (textured_grid_view_settings_mode != TEXTURED_GRID_USE_CURRENT_VIEW_SETTINGS) { current[0x218 / 4] = *(float *)(surface_draw_settings + 0x20); current[0x21c / 4] = *(float *)(surface_draw_settings + 0x24); current[0x228 / 4] = *(float *)(surface_draw_settings + 0x28); @@ -311,7 +314,7 @@ void build_packet_and_draw_scaled_entries(void *data_ptr, void *list_ptr, int co (unsigned char)surface_draw_settings[0x31] << 8 | (unsigned char)surface_draw_settings[0x32] << 16; /* Retail reads the mode after the packet cursor stores. */ - if (*(volatile int *)&textured_grid_view_settings_mode == 1) + if (*(volatile int *)&textured_grid_view_settings_mode == TEXTURED_GRID_USE_CURRENT_VIEW_SETTINGS) color = (long)(*(int *)(current + 0x230 / 4) | (*(int *)(current + 0x234 / 4) << 8) | (*(int *)(current + 0x238 / 4) << 16)); { From 6b355ad0de21bf46500ec10be376498f16831889 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:00:35 +0000 Subject: [PATCH 0875/1502] decomp: clarify names in particle_spawner_smoke_fire_update domain_0_value_1 -> PARTICLE_SPAWNER_ACTIVE: The authoritative C switches on spawner->state and already names its value-1 branch PARTICLE_SPAWNER_ACTIVE. Retail 002d6f68 loads that exact byte at +0x20(s5), 002d6f74/002d6f78 dispatch value 1 to 002d7194, and initialization at 002d6f88/002d6f90 loads 1 and stores it to the same +0x20(s5) byte. Original Ghidra likewise assigns 1 at object+0x20 in the zero-state branch and tests the same byte for 1 before culling, optional particle creation at 002d7324 and draw callback registration at 002d739c. Thus this assignment enters the established active state, using its existing local enum member rather than TRUE. --- src/overlays/shared/props/particle_spawner_smoke_fire.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/props/particle_spawner_smoke_fire.c b/src/overlays/shared/props/particle_spawner_smoke_fire.c index d3f552fd5f..d84d709aeb 100644 --- a/src/overlays/shared/props/particle_spawner_smoke_fire.c +++ b/src/overlays/shared/props/particle_spawner_smoke_fire.c @@ -155,7 +155,7 @@ void particle_spawner_smoke_fire_update(P *spawner) { switch (spawner->state) { case PARTICLE_SPAWNER_INITIALIZE: - spawner->state = 1; + spawner->state = PARTICLE_SPAWNER_ACTIVE; spawner->b30 = 0xFF; if (q->idx == -1) { mark_moby_for_removal(spawner); From ed95d9395d8c256041b67ab15b97f6ef809bb65d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:00:35 +0000 Subject: [PATCH 0876/1502] decomp: clarify names in display_update domain_0_value_0 -> BREAKABLE_STACK_STATE_UNINITIALIZED: Authoritative spawn_breakable_stack_replacement sets moby[0x20] = 0 after allocation and before update_entity. In display_update, retail 0x002edcc8 loads that same byte from s1+0x20; 0x002edccc skips the initialization store for every nonzero state. Only zero falls through to the store of 1 at 0x002edcd4, before command/cooldown processing at 0x002edcd8. This proves the initial, not-yet-initialized state role for this breakable stack. domain_1_value_1 -> BREAKABLE_STACK_STATE_INITIALIZED: Retail 0x002edccc tests the moby state byte loaded at 0x002edcc8; its delay slot 0x002edcd0 loads 1 and 0x002edcd4 stores it to the same s1+0x20 field only when the old state was zero. Supplied replacement helper initializes this field to zero at creation. The transition precedes both cooldown and hit early returns (0x002edcd8-0x002edce8), so 1 records initialization during the update rather than a hit, damage stage, or cooldown-ready condition. --- src/overlays/l09/mobys/display.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l09/mobys/display.c b/src/overlays/l09/mobys/display.c index 1c3503da58..fbebc244ef 100644 --- a/src/overlays/l09/mobys/display.c +++ b/src/overlays/l09/mobys/display.c @@ -89,6 +89,10 @@ void display_update(struct Moby *moby) { BREAKABLE_STACK_ANTEPENULTIMATE_CLASS = 0x512, BREAKABLE_STACK_PENULTIMATE_CLASS = 0x513 }; + enum { + BREAKABLE_STACK_STATE_UNINITIALIZED = 0, + BREAKABLE_STACK_STATE_INITIALIZED = 1 + }; float center[4]; float top[4]; float push[4]; @@ -107,8 +111,8 @@ void display_update(struct Moby *moby) { } replaced = 0; hit = find_moby_hit(moby, 0x40000, 0); - if (moby->state == 0) { - moby->state = 1; + if (moby->state == BREAKABLE_STACK_STATE_UNINITIALIZED) { + moby->state = BREAKABLE_STACK_STATE_INITIALIZED; } if (FUN_L00_001fefc8(&moby->command) == 0 || hit == 0) { return; From 4054a27e4e50036b34bf4599061ef38b3455b8bd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:02:22 +0000 Subject: [PATCH 0877/1502] decomp: clarify names in liftcar_platform_update domain_0_value_1 -> LIFTCAR_PLATFORM_WAIT_FOR_MISSION_GATE: Retail 0x002e22f4-0x002e22fc writes 1 to platform s3+0x20 after initialization. This is the same byte loaded by the switch at 0x002e22ac; its case 1 at 0x002e231c-0x002e2354 waits on the level/mission table sentinel. Reuse the existing local enum member for moby->state. domain_10_value_3 -> LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_ABOVE: Retail 0x002e2650-0x002e2668 writes 3 to platform s3+0x20 on completion of state 2, blending driver sequence 1. That same state byte selects wait case 3, whose 0x002e23e8-0x002e2414 tests require a rider or hero above. Reuse the existing local case-3 member. domain_11_value_5 -> LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_BELOW: Retail 0x002e264c and 0x002e2684-0x002e2698 write 5 to platform s3+0x20 on completion of state 4, blending driver sequence 3. The same field selects wait case 5 and its rider-or-hero-below branch at 0x002e23b8-0x002e23e4. Reuse the existing local case-5 member. domain_1_value_5 -> LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_BELOW: Retail 0x002e234c-0x002e2354 writes 5 to platform s3+0x20 on the mission gate sentinel. The identical state selector at 0x002e23b8-0x002e23e4 tests 5 before accepting hero z below platform z minus 5; grounded riders are also accepted. Reuse the existing case-5 local member. domain_2_value_5 -> LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_BELOW: Retail 0x002e23b4-0x002e23e4 compares platform s3+0x20 with 5 and then requires hero z below platform z minus 5. The shared wait branch also accepts a grounded rider. This is directly the switch(moby->state) case-5 domain already named by the local enum. domain_3_value_3 -> LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_ABOVE: Retail 0x002e23e8-0x002e2414 compares the platform state byte loaded from s3+0x20 with 3, then accepts hero z above platform z plus 5. Shared handling also accepts grounded riders. This is the same selector as the existing named case 3, so reuse that local member. domain_4_value_5 -> LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_BELOW: Retail 0x002e241c-0x002e2424 compares the platform state at s3+0x20 with 5 to choose animation sequence 0 and next state 2. It is the same platform state used by named switch case 5 and the hero-below test at 0x002e23b8-0x002e23e4; reuse its local member. domain_5_value_1 -> LIFTCAR_PLATFORM_WAIT_FOR_MISSION_GATE: Retail 0x002e2428-0x002e242c compares the same s3+0x20 platform state byte with 1 before selecting the state-2 path. Switch case 1 at 0x002e231c-0x002e2354 is the level/mission-table gate. Reuse that existing local member even though this comparison is in shared wait handling. domain_6_value_2 -> LIFTCAR_PLATFORM_ANIMATE_THEN_WAIT_FOR_RIDER_OR_HERO_ABOVE: Retail 0x002e2434-0x002e2448 writes 2 to the platform state byte s3+0x20 and starts driver animation 0. Shared animation completion at 0x002e2644-0x002e2668 transitions state 2 to named wait state 3. This proves reuse of the existing local animate-then-wait-above member. domain_7_value_4 -> LIFTCAR_PLATFORM_ANIMATE_THEN_WAIT_FOR_RIDER_OR_HERO_BELOW: Retail 0x002e2430 and 0x002e2458-0x002e2468 write 4 to the platform state s3+0x20 and start driver animation 2. Completion at 0x002e2684-0x002e2698 enters wait state 5. Reuse the existing local case-4 animate-then-wait-below member in this assignment. domain_8_value_2 -> LIFTCAR_PLATFORM_ANIMATE_THEN_WAIT_FOR_RIDER_OR_HERO_ABOVE: Retail 0x002e25c4-0x002e25d8 compares platform state s3+0x20 with 2 when resuming driver animation, selecting voice entry 2. This is the same state assigned at 0x002e2434-0x002e243c and tested on completion before entering wait state 3; reuse the existing local case-2 member. domain_9_value_2 -> LIFTCAR_PLATFORM_ANIMATE_THEN_WAIT_FOR_RIDER_OR_HERO_ABOVE: Retail 0x002e263c-0x002e2648 compares platform state s3+0x20 with 2 after driver animation completion and voice release. The matching path writes wait state 3 at 0x002e2650-0x002e2660. This directly identifies the existing local case-2 animate-then-wait-above member. --- src/overlays/l02/mobys/liftcar_platform.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l02/mobys/liftcar_platform.c b/src/overlays/l02/mobys/liftcar_platform.c index 0410a836e8..c58bb18247 100644 --- a/src/overlays/l02/mobys/liftcar_platform.c +++ b/src/overlays/l02/mobys/liftcar_platform.c @@ -59,12 +59,12 @@ void liftcar_platform_update(struct Moby *moby) { case LIFTCAR_PLATFORM_INITIALIZE: build_moby_bone_transform(driver, 0, joint_mtx); moby->rot.z = fast_arc_tan(joint_mtx[0], joint_mtx[1]); - moby->state = 1; + moby->state = LIFTCAR_PLATFORM_WAIT_FOR_MISSION_GATE; blend_moby_animation(driver, 3, 0, 0); break; case LIFTCAR_PLATFORM_WAIT_FOR_MISSION_GATE: if (D_0014C050[current_level_index][moby->mission] == 0xFF) { - moby->state = 5; + moby->state = LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_BELOW; } break; case LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_ABOVE: @@ -73,19 +73,19 @@ void liftcar_platform_update(struct Moby *moby) { if (hero.ground_moby == moby && hero.air_frames.s == 0 && moby->command == 0) { ride = 1; } else if (vector_distance_xy(&moby->pos, &hero.motion.pos) < 16.0f) { - if (moby->state == 5 && hero.motion.pos.f[2] < moby->pos.z - 5.0f) { + if (moby->state == LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_BELOW && hero.motion.pos.f[2] < moby->pos.z - 5.0f) { ride = 1; - } else if (moby->state == 3 && moby->pos.z + 5.0f < hero.motion.pos.f[2]) { + } else if (moby->state == LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_ABOVE && moby->pos.z + 5.0f < hero.motion.pos.f[2]) { ride = 1; } } if (ride) { - if (moby->state == 5 || moby->state == 1) { - moby->state = 2; + if (moby->state == LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_BELOW || moby->state == LIFTCAR_PLATFORM_WAIT_FOR_MISSION_GATE) { + moby->state = LIFTCAR_PLATFORM_ANIMATE_THEN_WAIT_FOR_RIDER_OR_HERO_ABOVE; set_moby_animation(driver, 0, 0); platform_vars->unkA4 = allocate_voice_for_target_entry(2, 4, driver); } else { - moby->state = 4; + moby->state = LIFTCAR_PLATFORM_ANIMATE_THEN_WAIT_FOR_RIDER_OR_HERO_BELOW; set_moby_animation(driver, 2, 0); platform_vars->unkA4 = allocate_voice_for_target_entry(0, 4, driver); } @@ -113,7 +113,7 @@ void liftcar_platform_update(struct Moby *moby) { (vector_distance_xy(&moby->pos, &hero.motion.pos) > 2.0f || moby->pos.z - 1.25f < hero.motion.pos.f[2])) { driver->anim_speed = 1.0f; - if (moby->state == 2) { + if (moby->state == LIFTCAR_PLATFORM_ANIMATE_THEN_WAIT_FOR_RIDER_OR_HERO_ABOVE) { platform_vars->unkA4 = allocate_voice_for_target_entry(2, 4, driver); } else { platform_vars->unkA4 = allocate_voice_for_target_entry(0, 4, driver); @@ -128,12 +128,12 @@ void liftcar_platform_update(struct Moby *moby) { } } platform_vars->unkA4 = -1; - if (moby->state == 2) { - moby->state = 3; + if (moby->state == LIFTCAR_PLATFORM_ANIMATE_THEN_WAIT_FOR_RIDER_OR_HERO_ABOVE) { + moby->state = LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_ABOVE; blend_moby_animation(driver, 1, 0, 0); allocate_voice_for_target_entry(3, 0, driver); } else { - moby->state = 5; + moby->state = LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_BELOW; blend_moby_animation(driver, 3, 0, 0); allocate_voice_for_target_entry(1, 0, driver); } From e06894ad45b689618bd174a2ffd643aebc144f9c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:02:22 +0000 Subject: [PATCH 0878/1502] decomp: clarify names in update_hero_relocation_trigger domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x00298f6c forms hero base 0x0013f350; 0x00298f70 loads byte +0x20a4 (hero.vehicle_mode), and 0x00298f74 compares it with s1=1 established at 0x00298e14. The equal path calls exit_hero_vehicle_mode at 0x00298f7c. The authoritative C identifies this field as hero.vehicle_mode; supplied exit_hero_vehicle_mode context tests this same field against HERO_VEHICLE_MODE_CLANK for Clank health restoration, and enter_hero_vehicle_mode assigns its mode parameter directly to that field. This function's retail 0x00298f3c-0x00298f54 enters vehicle mode 1 with the linked target. Thus this is the supplied HeroVehicleMode domain, whose canonical member HERO_VEHICLE_MODE_CLANK equals 1, rather than HeroStateId or HeroGravityMode. --- src/overlays/l10/mobys/hero_relocation_trigger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l10/mobys/hero_relocation_trigger.c b/src/overlays/l10/mobys/hero_relocation_trigger.c index e634e71274..51619dba05 100644 --- a/src/overlays/l10/mobys/hero_relocation_trigger.c +++ b/src/overlays/l10/mobys/hero_relocation_trigger.c @@ -146,7 +146,7 @@ void hero_relocation_trigger_update(struct Moby *moby) { request_music_track(2, 4); return; } - if (hero.vehicle_mode == 1) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { exit_hero_vehicle_mode(); set_race_camera(&l10_cuboids[relocation_trigger_vars->vehicle_spot].pos, &l10_cuboids[relocation_trigger_vars->vehicle_spot].rot, From f6295ccfadea5c35659cb011d1b5e005cc2e7cf4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:02:22 +0000 Subject: [PATCH 0879/1502] decomp: clarify names in bob_update domain_1_value_1 -> BOB_CHECK_DIALOGUE: Retail 0x002d0748 loads the incoming moby's state byte at s2+0x20; 0x002d074c/0x002d0750 dispatch value 1 to 0x002d07b8, the source's existing BOB_CHECK_DIALOGUE branch with region and NPC dialogue checks. In initialization, 0x002d0794 stores that same a0=1 into the same state byte when the flag is zero. Thus this assignment enters the existing Bob-local BOB_CHECK_DIALOGUE member, not a hero state. domain_2_value_2 -> BOB_WAIT_FOR_DIALOGUE_END: Retail 0x002d07d0 calls update_npc_dialogue and 0x002d07d8 tests its return; after begin_dialogue_camera_transition at 0x002d07ec, 0x002d07f4 loads 2 and 0x002d07fc stores it into s2+0x20. The same state byte is dispatched by 0x002d0770 to 0x002d0800 for value 2, the source's existing BOB_WAIT_FOR_DIALOGUE_END branch. This proves reuse of that Bob-local member. domain_3_value_1 -> BOB_CHECK_DIALOGUE: In the existing BOB_WAIT_FOR_DIALOGUE_END branch, retail 0x002d0800 retains state 2 while the dialogue global equals 2. Otherwise 0x002d0808 stores a0=1 into the same s2+0x20 state byte loaded at 0x002d0748. Value 1 dispatches at 0x002d0750 to 0x002d07b8, the existing BOB_CHECK_DIALOGUE region/dialogue checks. The assignment therefore resumes that canonical Bob-local state. --- src/overlays/l11/mobys/bob.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l11/mobys/bob.c b/src/overlays/l11/mobys/bob.c index 072b1b86aa..7451524f82 100644 --- a/src/overlays/l11/mobys/bob.c +++ b/src/overlays/l11/mobys/bob.c @@ -74,7 +74,7 @@ void bob_update(WatcherMoby *moby) { if (D_0013D4C3) { moby->state = 3; } else { - moby->state = 1; + moby->state = BOB_CHECK_DIALOGUE; } initialize_npc_dialogue(moby, moby_vars); moby_vars->f0C = 3.7f; @@ -83,13 +83,13 @@ void bob_update(WatcherMoby *moby) { if (is_point_inside_clip_volume(hero.motion.pos.f, moby_vars->region)) { if (update_npc_dialogue(moby, moby_vars)) { begin_dialogue_camera_transition(moby, 2.7f); - moby->state = 2; + moby->state = BOB_WAIT_FOR_DIALOGUE_END; } } break; case BOB_WAIT_FOR_DIALOGUE_END: if (D_L11_0015F5C4 != 2) { - moby->state = 1; + moby->state = BOB_CHECK_DIALOGUE; if (moby_vars->h04 == 2) { grant_inventory_item(3, 1); jet_reset_camera(hero.motion.pos.f, hero.motion.pos.f + 4); From b51ad243b31009767a372a86736a06fb4c22e0fd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:02:22 +0000 Subject: [PATCH 0880/1502] decomp: clarify names in update_help_hints domain_0_value_1 -> HELP_MESSAGE_STATE_CHECK_CONDITIONS: Authoritative src/overlays/l10/mobys/help_hints.c SHA-256 db9856a8f138acaaf932cde4cdedcb10218e628ba684ec4fd00c98699dfc3ded declares HELP_MESSAGE_STATE_CHECK_CONDITIONS = 1 for switch(moby->state). Retail 0x002e8608 loads that same moby's state/+0x20, 0x002e8614 dispatches state 1 to condition checks at 0x002e8638, and initialization at 0x002e8628-0x002e862c stores 1 into that exact state byte. Original Ghidra likewise assigns state 1 on state 0 and returns, then dispatches state 1 to help conditions. Thus the assignment uses the already named member of the identical selector domain. --- src/overlays/l10/mobys/help_hints.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l10/mobys/help_hints.c b/src/overlays/l10/mobys/help_hints.c index c1c718e4c7..1e72838a53 100644 --- a/src/overlays/l10/mobys/help_hints.c +++ b/src/overlays/l10/mobys/help_hints.c @@ -94,7 +94,7 @@ void help_hints_update(Moby *moby) { switch (moby->state) { case HELP_MESSAGE_STATE_INITIALIZE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = HELP_MESSAGE_STATE_CHECK_CONDITIONS; break; case HELP_MESSAGE_STATE_CHECK_CONDITIONS: if (is_point_inside_clip_volume(D_0013F3D0_r, conditional_help_config->f0) != 0 && From 53518a4597265a783aca43c3d5596617a60537c2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:02:22 +0000 Subject: [PATCH 0881/1502] decomp: clarify names in update_looping_path_mine domain_0_value_1 -> MINE_STATE_FOLLOW_PATH: Retail 0x002ec848 reads moby state byte +0x20 from s4; 0x002ec854-0x002ec858 dispatch value 1 to 0x002ec9e8. Initialization sets v0=1 at 0x002ec95c and stores it to that same byte at 0x002ec97c after copying the first path point and resetting segment/along. The target branch samples the looping path at 0x002eca40 and smooths XYZ at 0x002eca60/80/9c. Authoritative C already names this same switch branch MINE_STATE_FOLLOW_PATH=1, proving canonical reuse for moby->state=1. --- src/overlays/l14/mobys/mine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/mine.c b/src/overlays/l14/mobys/mine.c index c267a38115..713f3556a8 100644 --- a/src/overlays/l14/mobys/mine.c +++ b/src/overlays/l14/mobys/mine.c @@ -119,7 +119,7 @@ void looping_path_mine_update(struct Moby *moby) { mine_vars->along = 0; mine_vars->dir = random_integer_below(2) != 0 ? 1.0f : -1.0f; qcopy(&moby->pos, path->points[0].pos); - moby->state = 1; + moby->state = MINE_STATE_FOLLOW_PATH; mine_vars->spin[0] = random_float_between(0.05235988f, 0.10471976f); mine_vars->spin[1] = random_float_between(0.034906585f, 0.06981317f); mine_vars->spin[2] = random_float_between(0.017453292f, 0.034906585f); From 4706c4f017cf39b2dd6e91f4a1cd22e5d9bd421b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:02:22 +0000 Subject: [PATCH 0882/1502] decomp: clarify names in update_darter_hit_reactions_and_targeting domain_0_value_13 -> DARTER_STATE_DYING: Retail 0x002e1830 loads this same supplied darter moby's state byte at s2+0x20 and 0x002e1834 skips hit processing when equal to 13. The supplied darter_update invokes this helper with its own moby and switches that same moby->state; its established DARTER_STATE_DYING=13 case steps death motion then removes the moby and spawns its death burst. This proves the darter state domain, independent of equal-valued Hero constants. domain_1_value_13 -> DARTER_STATE_DYING: Retail 0x002e1890..0x002e18a8 compares remaining health at private +0x20 against hit damage +0x2c and clears health on the lethal branch; 0x002e18dc stores 13 into the owner's state byte s2+0x20, then initializes death knockback and animation 4. The supplied darter_update calls this helper on the same moby before switching moby->state, and its canonical DARTER_STATE_DYING=13 case handles motion completion, death burst and removal. Reuse the same dying member as the hit-processing guard. --- src/overlays/l10/mobys/darter.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/darter.c b/src/overlays/l10/mobys/darter.c index 3083338d6a..1f0a61db8c 100644 --- a/src/overlays/l10/mobys/darter.c +++ b/src/overlays/l10/mobys/darter.c @@ -646,6 +646,9 @@ extern void trooper_anim_update(void *m, void *p) __asm__("FUN_L00_0025d458"); #include "rnc/data_labels.h" void update_darter_hit_reactions_and_targeting(struct Moby *moby) { + enum { + DARTER_STATE_DYING = 13 + }; MobyData *class_1199_vars = ((struct MobyData *)moby->pvars); float vector_scratch[4]; float transformed_offset[4]; @@ -660,7 +663,7 @@ void update_darter_hit_reactions_and_targeting(struct Moby *moby) { class_1199_vars->f38 = 0; } fast_dec_timer(&class_1199_vars->f184); - if (moby->state != 13) { + if (moby->state != DARTER_STATE_DYING) { hit_record = find_moby_hit(moby, 0x330000, 0); resolve_moby_hit_response( moby, hit_record, &class_1199_vars->f20, 5, &hit_processing_status, 0, 0, 4); @@ -670,7 +673,7 @@ void update_darter_hit_reactions_and_targeting(struct Moby *moby) { moby->flags &= 0xEFFF; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); - moby->state = 13; + moby->state = DARTER_STATE_DYING; class_1199_vars->f70 = D_0015ED70 * 26.0f; class_1199_vars->f9D = 3; class_1199_vars->f84 = 9; From 6aaeabcd77f336ed72cd480832897f9aaa4f4fc4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:04:09 +0000 Subject: [PATCH 0883/1502] decomp: clarify names in spawn_rocket_strike_fighter_exhaust domain_0_value_0 -> ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE: Retail 0x002fd31c preserves the moby argument; 0x002fd34c-0x002fd350 tests its state byte at +0x20 against zero. Checked caller 0x002fcbb0 holds this same moby in s1 and passes it at 0x002fd294/0x002fd298. Caller dispatch 0x002fcd98 enters path/mission validation and initialization at 0x002fcdc0-0x002fcec8 for state zero. Authoritative source names that exact caller selector's case ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE = 0; reuse this fighter-domain member. domain_1_value_3 -> ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN: Retail 0x002fd354-0x002fd358 excludes 3 in the same moby+0x20 state field passed from caller s1 at 0x002fd294/0x002fd298. Caller stores 3 at 0x002fcd18 on destruction and dispatches it at 0x002fcdb0 to 0x002fd1f4, which decrements pvars+0x7c timer, restores collision/visibility, resets path progress and position, and writes state 2 at 0x002fd240. Authoritative source names this same state ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN = 3. domain_2_value_1 -> ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS: Retail 0x002fd35c-0x002fd360 excludes 1 from moby+0x20. The same object is passed by checked caller 0x002fd294/0x002fd298; its state 1 dispatch at 0x002fcd88 enters 0x002fcecc, checking three mission bytes indexed by pvars+0x98/+0x9c/+0xa0 through 0x002fcf24, then hero/target visibility conditions before writing state 2 at 0x002fd0ec. Authoritative source calls this exact state ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS = 1; reuse that established fighter-domain name. --- src/overlays/l14/mobys/rocket_strike_fighter.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/rocket_strike_fighter.c b/src/overlays/l14/mobys/rocket_strike_fighter.c index 1c0f782408..2f6bb81603 100644 --- a/src/overlays/l14/mobys/rocket_strike_fighter.c +++ b/src/overlays/l14/mobys/rocket_strike_fighter.c @@ -269,6 +269,11 @@ extern f32 rocket_strike_fighter_exhaust_grey_puff_row0_offset_gp __asm__("D_L14 #include "rnc/overlay/l14/mobys/rocket_strike_fighter_data/spawn_rocket_strike_fighter_exhaust.h" void spawn_rocket_strike_fighter_exhaust(struct Moby *moby) { + enum { + ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE = 0, + ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS = 1, + ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN = 3 + }; Vec4 step; Vec4 pos; Vec4 common_exhaust_origin; @@ -280,7 +285,7 @@ void spawn_rocket_strike_fighter_exhaust(struct Moby *moby) { int grey; float size; - if (moby->state == 0 || moby->state == 3 || moby->state == 1) + if (moby->state == ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE || moby->state == ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN || moby->state == ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS) return; fast_vec_scale(&step, &moby->rot_row0, rocket_strike_fighter_exhaust_base_row0_offset_gp); fast_vec_add(&pos, &moby->pos, &step); From 647b460491903201074ba1e454676fb2219e5ed6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:04:09 +0000 Subject: [PATCH 0884/1502] decomp: clarify names in update_vertical_gate domain_0_value_1 -> GATE_WAIT_TO_OPEN: At 0x002a371c-0x002a3730 initialization copies position to home, stores 1 at s2+0x20 and clears lock. The switch reads that same gate state byte at 0x002a36f0; its existing GATE_WAIT_TO_OPEN case resets travel and waits for activation. domain_10_value_5 -> GATE_POSITION_OVERRIDE: After closing completes, the nonnegative key sentinel check leads to a loaded 5 and state store at 0x002a3acc-0x002a3ad4, clearing the key-gate flag. Destination s2+0x20 is the gate switch selector and 5 already names GATE_POSITION_OVERRIDE in this exact function. domain_11_value_2 -> GATE_OPENING: During closing, either successful near-volume test reaches the store of 2 at gate s2+0x20 at 0x002a3b2c-0x002a3b30. This reverses motion by selecting the same switch's existing GATE_OPENING case, which adds step to travel. domain_12_value_1 -> GATE_WAIT_TO_OPEN: Override exit loads 1 at 0x002a3b70, stores it to gate s2+0x20 at 0x002a3b78, restores home Z and clears the key-gate flag. This returns the same selector to existing GATE_WAIT_TO_OPEN and its activation checks. domain_1_value_5 -> GATE_POSITION_OVERRIDE: Initialization loads 5 at 0x002a3760 and branches to the state-byte store at 0x002a383c while subtracting travel distance from gate Z. This is the same s2+0x20 selector whose existing GATE_POSITION_OVERRIDE case forces/restores Z at 0x002a3b34-0x002a3b84. domain_4_value_2 -> GATE_OPENING: After trigger state checks and the zero global guard, 0x002a37c8-0x002a37d8 writes 2 to gate s2+0x20 and sets its lock. That same switch selector dispatches existing GATE_OPENING, which increases travel at 0x002a38d4. domain_5_value_2 -> GATE_OPENING: Near-volume success and the key condition lead to 0x002a3810-0x002a3814 storing 2 at gate s2+0x20. This byte is the switch selector at 0x002a36f0, and its existing GATE_OPENING case increases travel toward the limit. domain_6_value_5 -> GATE_POSITION_OVERRIDE: The wait branch loads 5 at 0x002a3830 and writes it to s2+0x20 at 0x002a383c while setting gate Z to home Z minus travel distance. This enters the same gate switch's existing GATE_POSITION_OVERRIDE branch, which directly forces/restores Z. domain_7_value_3 -> GATE_OPEN: Opening completion releases the owned voice, clamps travel to the distance, and stores 3 to gate s2+0x20 at 0x002a3930-0x002a3938. The same selector dispatches existing GATE_OPEN, which holds position and tests volumes/lock before closing. domain_8_value_4 -> GATE_CLOSING: In the open branch, volume checks and a zero lock lead to 0x002a39cc-0x002a39d4 storing 4 at s2+0x20. This is the gate switch selector, whose existing GATE_CLOSING case subtracts movement step from travel at 0x002a3a60. domain_9_value_1 -> GATE_WAIT_TO_OPEN: Closing completion clears travel and invalidates the sound index, then stores 1 at gate s2+0x20 at 0x002a3ab4-0x002a3ac0. The same byte selects existing GATE_WAIT_TO_OPEN, which awaits trigger or near-volume activation. --- src/overlays/l15/mobys/vertical_gate.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l15/mobys/vertical_gate.c b/src/overlays/l15/mobys/vertical_gate.c index 5d948bf2aa..89f66c7660 100644 --- a/src/overlays/l15/mobys/vertical_gate.c +++ b/src/overlays/l15/mobys/vertical_gate.c @@ -75,14 +75,14 @@ void vertical_gate_update(GateMoby *gate_moby) { switch (gate_moby->state) { case GATE_INITIALIZE: *(u128 *)&gate_vars->home = *(u128 *)&gate_moby->pos; - gate_moby->state = 1; + gate_moby->state = GATE_WAIT_TO_OPEN; gate_vars->locked = 0; if (gate_vars->key != -1) { gate_moby->f30 = 0xFF; } if (D_0013DD50 != 0 && gate_vars->key != -1) { gate_moby->pos.z = gate_moby->pos.z - vertical_gate_travel_distance_gp; - gate_moby->state = 5; + gate_moby->state = GATE_POSITION_OVERRIDE; } break; case GATE_WAIT_TO_OPEN: @@ -95,20 +95,20 @@ void vertical_gate_update(GateMoby *gate_moby) { (struct Moby *)((char *)l15_moby_array + (gate_vars->trigger << 8)); if (trigger_moby == 0 || trigger_moby->state == 0xFE || trigger_moby->state == 0xFD) { if (D_L15_00161AC0 == 0) { - gate_moby->state = 2; + gate_moby->state = GATE_OPENING; gate_vars->locked = 1; } } } else { if (is_point_inside_clip_volume(D_0013F3D0_2A48B0, gate_vars->vol_near)) { if (gate_vars->key == -1 || D_0013F3D0_2A48B0[0x2024] == 2) { - gate_moby->state = 2; + gate_moby->state = GATE_OPENING; } } } if (D_0013DD50 != 0 && gate_vars->key != -1) { gate_moby->pos.z = gate_vars->home.z - vertical_gate_travel_distance_gp; - gate_moby->state = 5; + gate_moby->state = GATE_POSITION_OVERRIDE; } break; case GATE_OPENING: @@ -129,7 +129,7 @@ void vertical_gate_update(GateMoby *gate_moby) { } gate_vars->sound = -1; gate_vars->travel = vertical_gate_travel_distance_gp; - gate_moby->state = 3; + gate_moby->state = GATE_OPEN; } { float t = gate_vars->travel; @@ -155,7 +155,7 @@ void vertical_gate_update(GateMoby *gate_moby) { } } if (gate_vars->locked == 0) { - gate_moby->state = 4; + gate_moby->state = GATE_CLOSING; } break; case GATE_CLOSING: @@ -176,9 +176,9 @@ void vertical_gate_update(GateMoby *gate_moby) { } gate_vars->travel = 0; gate_vars->sound = -1; - gate_moby->state = 1; + gate_moby->state = GATE_WAIT_TO_OPEN; if (gate_vars->key != -1) { - gate_moby->state = 5; + gate_moby->state = GATE_POSITION_OVERRIDE; l15_key_gate_open_lui = 0; } } @@ -196,7 +196,7 @@ void vertical_gate_update(GateMoby *gate_moby) { } if (is_point_inside_clip_volume(D_0013F3D0_2A48B0, gate_vars->vol_near) != 0 || is_point_inside_clip_volume(D_L15_00167440_2A48B0, gate_vars->vol_near) != 0) { - gate_moby->state = 2; + gate_moby->state = GATE_OPENING; } break; case GATE_POSITION_OVERRIDE: @@ -208,7 +208,7 @@ void vertical_gate_update(GateMoby *gate_moby) { break; } gate_moby->pos.z = gate_vars->home.z; - gate_moby->state = 1; + gate_moby->state = GATE_WAIT_TO_OPEN; l15_key_gate_open_lui = 0; } break; From eb1d73a91298af4dcfb6237722c0cc6d5bc8838c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:04:09 +0000 Subject: [PATCH 0885/1502] decomp: clarify names in render_water_grids domain_0_value_2 -> WATER_GRID_MODE_TEST_NEAR_CLIP: Source SHA-256 a922145e6bf238329d03198f5ef2a86cca59b7c2dac3c3abd379eb5e5dde8665 assigns mode=2 only when far_bits & 0x2f2f2f2f is zero and near_bits intersects that mask. Retail 0x002b94ac-0x002b94c4 implements this with s3=2 and conditional zeroing. At 0x002b9610/0x002b9614 s3 is passed as a2 to cull_and_submit_water_grid_tile. Checked helper 0x002b8cc8/0x002b8ce8 retains nonzero mode; 0x002b8e80 sends mode 2 to 0x002b8ee0-0x002b8f2c, which rejects tiles wholly outside near_clip bounds and clears the mode for survivors. Thus this value requests near-clip tile tests, with no retained clipping mode after acceptance. domain_1_value_0 -> WATER_GRID_MODE_SKIP_CLIP_TESTS: In the authoritative source mode=0 is selected when neither far_bits nor near_bits intersects 0x2f2f2f2f. Original retail Ghidra shows uVar7=0 for that same condition; R5900 0x002b94bc-0x002b94c4 conditionally clears s3, passed unchanged in a2 at 0x002b9614. Checked helper 0x002b8cc8 copies a2 to s4 and 0x002b8ce8 branches directly to 0x002b8f30 when zero, bypassing corner construction and all clip tests. 0x002b8f44-0x002b8f58 then selects submission mode 0xc. This directly proves skip-clip-tests behavior, consistent with the helper's existing function-local WATER_TILE_MODE_SKIP_CLIP_TESTS=0, rather than unrelated FALSE or NULL constants. --- src/overlays/shared/rendering/render_water_grids.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/rendering/render_water_grids.c b/src/overlays/shared/rendering/render_water_grids.c index 8553aef76a..3dbbe458c8 100644 --- a/src/overlays/shared/rendering/render_water_grids.c +++ b/src/overlays/shared/rendering/render_water_grids.c @@ -224,6 +224,10 @@ void build_water_render_setup_packet(void) { void render_water_grids(f32 *water_record, s32 count) __asm__("FUN_L01_002b91c8"); void render_water_grids(f32 *water_record, s32 count) { + enum { + WATER_GRID_MODE_SKIP_CLIP_TESTS = 0, + WATER_GRID_MODE_TEST_NEAR_CLIP = 2 + }; f32 corners[4][4]; f32 near_clip[4]; f32 far_clip[4]; @@ -314,9 +318,9 @@ void render_water_grids(f32 *water_record, s32 count) { } mode = (far_bits & 0x2f2f2f2f) != 0; if (!mode) { - mode = 2; + mode = WATER_GRID_MODE_TEST_NEAR_CLIP; if (!(near_bits & 0x2f2f2f2f)) - mode = 0; + mode = WATER_GRID_MODE_SKIP_CLIP_TESTS; } mask = *(u16 *)((u8 *)water_record + 0x1e); if (*(u32 *)(water_record + 5) != cached_water_texture_id_gp || From 95600adde100012197f8c4ab7c16eb8a7fd3c39f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:04:09 +0000 Subject: [PATCH 0886/1502] decomp: clarify names in update_fleet_rotating_radial_effect domain_0_value_1 -> RING_ROTATE_AND_DRAW: Retail 0x002d7840 loads this moby's state byte at s6+0x20; 0x002d784c dispatches value 1 to 0x002d789c. Initialization loads v1=1 at 0x002d7860 and stores that same byte field at 0x002d7868. The destination branch adds pvars[1] to rotation at +0x40 (0x002d789c-0x002d78ac) and queues draw_fleet_scrolling_radial_quads at 0x002d78b0-0x002d78b8. The authoritative C already names that exact same selector's value-1 branch RING_ROTATE_AND_DRAW, proving reuse for this state assignment. --- src/overlays/l17/mobys/fleet_rotating_radial_effect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l17/mobys/fleet_rotating_radial_effect.c b/src/overlays/l17/mobys/fleet_rotating_radial_effect.c index 0eab6686d2..3a4cf96b60 100644 --- a/src/overlays/l17/mobys/fleet_rotating_radial_effect.c +++ b/src/overlays/l17/mobys/fleet_rotating_radial_effect.c @@ -86,7 +86,7 @@ void fleet_rotating_radial_effect_update(char *moby) { switch (MOBY(moby)->state) { case RING_INITIALIZE: MOBY(moby)->update_dist = 0xFF; - MOBY(moby)->state = 1; + MOBY(moby)->state = RING_ROTATE_AND_DRAW; ring_vars[1] = ring_vars[0] * *(float *)&fleet_radial_rotation_rate_degrees_factor * DEG_TO_RAD * frame_time; break; From 1864a9a3d9ca46425a389ba99389c0b248b0040a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:04:10 +0000 Subject: [PATCH 0887/1502] decomp: clarify names in update_screamer_hit_reactions_and_targeting domain_0_value_11 -> SCREAMER_STATE_DEATH_KNOCKBACK: Authoritative screamer.c (SHA-256 c2f072f291e96110038337587d380a82d41e5745ffd0a6b897a21f538a0f912d) establishes SCREAMER_STATE_DEATH_KNOCKBACK=11 in screamer_update, which calls this assigned helper first on the same moby and switches on moby->state. Retail 0x002dfca8-0x002dfcb0 reads moby+0x20 and skips hit processing for 11; lethal health-versus-damage comparison at 0x002dfcf4-0x002dfd04 leads to state 11 store at 0x002dfd88, animation 5 and trooper_start_knockback at 0x002dfe38. The caller's named state 11 steps knockback motion then removes/explodes the moby. This is the screamer state domain, not HeroStateId. domain_1_value_11 -> SCREAMER_STATE_DEATH_KNOCKBACK: Authoritative screamer.c (SHA-256 c2f072f291e96110038337587d380a82d41e5745ffd0a6b897a21f538a0f912d) establishes SCREAMER_STATE_DEATH_KNOCKBACK=11 in screamer_update, which calls this assigned helper first on the same moby and switches on moby->state. Retail 0x002dfca8-0x002dfcb0 reads moby+0x20 and skips hit processing for 11; lethal health-versus-damage comparison at 0x002dfcf4-0x002dfd04 leads to state 11 store at 0x002dfd88, animation 5 and trooper_start_knockback at 0x002dfe38. The caller's named state 11 steps knockback motion then removes/explodes the moby. This is the screamer state domain, not HeroStateId. domain_2_value_1 -> SCREAMER_STATE_WAIT_FOR_ACTIVATION: Authoritative screamer.c establishes SCREAMER_STATE_WAIT_FOR_ACTIVATION=1 in screamer_update, the caller that passes the same moby to this assigned helper before switching on moby->state. Its state 1 waits while pvars+0x104 is 2 and pvars+0x174 is nonzero, then enters wait-to-rise state 2. Assigned retail reads the same moby+0x20 byte at 0x002dfedc and compares to 1 at 0x002dfef4-0x002dfef8 for range pvars+0x188; 0x002dff14/0x002e0008-0x002e0014 select pvars+0x18C path for state 1 versus pvars+0x17C for other states. These are activation-wait checks on the screamer state selector, not hero states or target-selection return codes. domain_4_value_1 -> SCREAMER_STATE_WAIT_FOR_ACTIVATION: Authoritative screamer.c establishes SCREAMER_STATE_WAIT_FOR_ACTIVATION=1 in screamer_update, the caller that passes the same moby to this assigned helper before switching on moby->state. Its state 1 waits while pvars+0x104 is 2 and pvars+0x174 is nonzero, then enters wait-to-rise state 2. Assigned retail reads the same moby+0x20 byte at 0x002dfedc and compares to 1 at 0x002dfef4-0x002dfef8 for range pvars+0x188; 0x002dff14/0x002e0008-0x002e0014 select pvars+0x18C path for state 1 versus pvars+0x17C for other states. These are activation-wait checks on the screamer state selector, not hero states or target-selection return codes. domain_5_value_1 -> SCREAMER_STATE_WAIT_FOR_ACTIVATION: Authoritative screamer.c establishes SCREAMER_STATE_WAIT_FOR_ACTIVATION=1 in screamer_update, the caller that passes the same moby to this assigned helper before switching on moby->state. Its state 1 waits while pvars+0x104 is 2 and pvars+0x174 is nonzero, then enters wait-to-rise state 2. Assigned retail reads the same moby+0x20 byte at 0x002dfedc and compares to 1 at 0x002dfef4-0x002dfef8 for range pvars+0x188; 0x002dff14/0x002e0008-0x002e0014 select pvars+0x18C path for state 1 versus pvars+0x17C for other states. These are activation-wait checks on the screamer state selector, not hero states or target-selection return codes. --- src/overlays/l10/mobys/screamer.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/overlays/l10/mobys/screamer.c b/src/overlays/l10/mobys/screamer.c index 39fd5737b9..9cb13b4ec7 100644 --- a/src/overlays/l10/mobys/screamer.c +++ b/src/overlays/l10/mobys/screamer.c @@ -385,6 +385,10 @@ extern void trooper_anim_update(void *m, void *p) __asm__("FUN_L00_0025d458"); #include "rnc/data_labels.h" void update_screamer_hit_reactions_and_targeting(struct Moby *moby) { + enum { + SCREAMER_STATE_WAIT_FOR_ACTIVATION = 1, + SCREAMER_STATE_DEATH_KNOCKBACK = 11 + }; MobyData_2DFC38 *screamer_vars = (MobyData_2DFC38 *)moby->pvars; Hit_2DFC38 *hit_record; float relative_offset[4]; @@ -399,7 +403,7 @@ void update_screamer_hit_reactions_and_targeting(struct Moby *moby) { screamer_vars->f38 = 0; } fast_dec_timer(&screamer_vars->f184); - if (moby->state != 11) { + if (moby->state != SCREAMER_STATE_DEATH_KNOCKBACK) { hit_record = (Hit_2DFC38 *)find_moby_hit(moby, 0x330000, 0); hit_update_2DFC38( moby, hit_record, &screamer_vars->f20, 5, &hit_processing_status, 0, 0, 4); @@ -414,7 +418,7 @@ void update_screamer_hit_reactions_and_targeting(struct Moby *moby) { moby->flags &= 0xEFFF; if (moby->prev_seq != 5) blend_moby_animation(moby, 5, 0, scale_game_frames(10)); - moby->state = 11; + moby->state = SCREAMER_STATE_DEATH_KNOCKBACK; screamer_vars->f70 = D_0015ED70 * 26.0f; screamer_vars->f9D = 3; screamer_vars->f74 = 0.0005f; @@ -444,7 +448,7 @@ void update_screamer_hit_reactions_and_targeting(struct Moby *moby) { screamer_vars->f180 = 42.0f; else if (screamer_vars->f184 != 0) screamer_vars->f180 = screamer_vars->f178 + 6.0f; - else if (moby->state == 1) + else if (moby->state == SCREAMER_STATE_WAIT_FOR_ACTIVATION) screamer_vars->f180 = screamer_vars->f188; else screamer_vars->f180 = screamer_vars->f178; @@ -461,11 +465,11 @@ void update_screamer_hit_reactions_and_targeting(struct Moby *moby) { transformed_offset[2] <= -1.0f || 1.0f <= transformed_offset[2]) screamer_vars->f104 = 2; } - } else if (moby->state == 1 && screamer_vars->f18C >= 0) { + } else if (moby->state == SCREAMER_STATE_WAIT_FOR_ACTIVATION && screamer_vars->f18C >= 0) { LevelPath *path = l10_paths[screamer_vars->f18C]; target_selection_status = activate_effect_l08( screamer_vars->f180, moby, screamer_vars->fC0, 0, 0, path->points, path->count); - } else if (moby->state != 1 && screamer_vars->f17C >= 0) { + } else if (moby->state != SCREAMER_STATE_WAIT_FOR_ACTIVATION && screamer_vars->f17C >= 0) { LevelPath *path = l10_paths[screamer_vars->f17C]; target_selection_status = activate_effect_l08( screamer_vars->f180, moby, screamer_vars->fC0, 0, 0, path->points, path->count); From 030684096c1023b37eea1996b78fe51c35c1dd90 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:04:10 +0000 Subject: [PATCH 0888/1502] decomp: clarify names in follow_camera_build_view domain_0_value_0 -> VIEW_BLEND_NO_REMAINING_FRAMES: Source SHA-256 a18c715ed52a4c6c80b0a346d87447c0664e155a6928a2cd188103d82dfbb61d compares *(s16 *)view_blend_and_smoothing_state != 0. Retail 0x002e9070 sets s4=state+0x20; 0x002e9448 loads lh v0,0(s4), and 0x002e944c skips blending when zero. Otherwise 0x002e9454 decrements that timer, 0x002e9460 loads its remaining signed count for float conversion, and 0x002e9478 divides by a converted frame-scaled duration before 0x002e9484 lerps the camera view vector. Original Ghidra psVar7/sVar2 and fVar12 corroborate the countdown-to-blend flow. Thus zero means no remaining view-blend frames; FALSE and NULL do not describe this scalar countdown domain. --- src/overlays/shared/camera/follow_camera_update.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/camera/follow_camera_update.c b/src/overlays/shared/camera/follow_camera_update.c index ad67ee07b7..eb001a9f19 100644 --- a/src/overlays/shared/camera/follow_camera_update.c +++ b/src/overlays/shared/camera/follow_camera_update.c @@ -306,6 +306,9 @@ f32 D_L18_00162768[2] = {0.017453292f, 0.02268928f}; void follow_camera_build_view(u8 *p) __asm__("FUN_L00_002e9010"); void follow_camera_build_view(u8 *camera) { + enum { + VIEW_BLEND_NO_REMAINING_FRAMES = 0 + }; u8 *follow_state_block; u8 *camera_state; u8 *reloaded_camera_state; @@ -425,7 +428,7 @@ void follow_camera_build_view(u8 *camera) { FUN_001f9bf8_2e9010(camera, camera, 1.0f); } } - if (*(s16 *)view_blend_and_smoothing_state != 0) { + if (*(s16 *)view_blend_and_smoothing_state != VIEW_BLEND_NO_REMAINING_FRAMES) { fast_dec_timer_s16(view_blend_and_smoothing_state); remaining_view_blend_frames = convert_integer_to_float(*(s16 *)view_blend_and_smoothing_state); From f9294d3a612274418ce1ff7b5fdbb81f8ca80de7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:04:10 +0000 Subject: [PATCH 0889/1502] decomp: clarify names in update_thruster_pack_flame domain_0_value_1 -> STATE_WAIT_FOR_BEAM: Retail 002b41d8 loads the input moby's byte +0x20 and 002b41dc-002b41e0 compares it with 1. This is the identical byte used by the lifecycle switch at 002b4308-002b4328, whose existing local member STATE_WAIT_FOR_BEAM=1 handles waiting for activation at 002b4364-002b4388. domain_1_value_3 -> STATE_BEAM_ACTIVE: Retail 002b41c4 establishes 3 and 002b41d8-002b41e8 tests the moby byte +0x20 against 1 or 3 before computing activation. The same byte selects the existing STATE_BEAM_ACTIVE=3 branch at 002b450c, which draws the beam and emits particles at 002b45f8 while activation holds. domain_2_value_28 -> HERO_STATE_LEDGE_JUMP: Source hero_state is assigned directly from hero.state.current. Retail 002b41e4/002b41f0 loads hero+0x2084 (001413d4), and 002b4204-002b4208 compares that same loaded state to 0x1C. Thus the selector belongs to the shared HeroStateId domain, where include/rnc/hero/hero_state.h canonically declares HERO_STATE_LEDGE_JUMP=28; this is not a vehicle or gravity mode. domain_3_value_1 -> STATE_WAIT_FOR_BEAM: In STATE_INITIALIZE, retail 002b4334 loads 1 and 002b434c stores it to the same moby +0x20 byte dispatched by 002b4308-002b4328. The next update therefore enters existing STATE_WAIT_FOR_BEAM=1, whose 002b4364-002b4388 branch waits for the activation predicate. domain_4_value_2 -> STATE_BEAM_GROW: Retail 002b4388-002b4398 stores 2 to moby +0x20 when activation becomes true in the waiting branch, then initializes a scaled two-frame timer and four growth rates at 002b439c-002b4450. The same state-byte switch dispatches 2 to additive growth at 002b4454, establishing reuse of existing STATE_BEAM_GROW=2. domain_5_value_3 -> STATE_BEAM_ACTIVE: Retail 002b44b0-002b44bc tests the growth timer, then 002b44f0 stores 3 into the same moby +0x20 lifecycle selector and sets full beam scales. The existing STATE_BEAM_ACTIVE=3 branch at 002b450c-002b45fc draws and emits particles until activation ends. domain_6_value_4 -> STATE_BEAM_SHRINK: Retail 002b4528 tests activation in the active branch; when false, 002b4530-002b453c stores 4 to moby +0x20 and initializes scaled eight-frame decay rates. The identical state selector dispatches 4 to subtractive updates at 002b4608-002b4678, matching existing STATE_BEAM_SHRINK=4. domain_7_value_1 -> STATE_WAIT_FOR_BEAM: Retail 002b4608-002b461c tests the shrink timer and on completion stores 1 to moby +0x20. This is the lifecycle switch byte, so the transition returns to the existing STATE_WAIT_FOR_BEAM=1 branch at 002b4364, ready for another activation. --- src/overlays/shared/weapons/thruster_pack_flame.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/weapons/thruster_pack_flame.c b/src/overlays/shared/weapons/thruster_pack_flame.c index 34b07ddb13..fdda257547 100644 --- a/src/overlays/shared/weapons/thruster_pack_flame.c +++ b/src/overlays/shared/weapons/thruster_pack_flame.c @@ -883,10 +883,10 @@ void thruster_pack_flame_update(void *moby) { s32 lim; if (hero.items[3].item_id == 3) { - if (beam_moby->state == 1 || beam_moby->state == 3) { + if (beam_moby->state == STATE_WAIT_FOR_BEAM || beam_moby->state == STATE_BEAM_ACTIVE) { hero_state = hero.state.current; if ((u32)(hero_state - 0xB) < 4 || - (hero_state == 0x1C && + (hero_state == HERO_STATE_LEDGE_JUMP && ((u8 *)((void *)hero.moby))[0x52] == ((u8 *)((void *)hero.moby))[0x53] && hero.anim_frame >= 6.0f && hero.anim_frame <= 16.0f)) { if (!hero.past_jump_apex) @@ -911,7 +911,7 @@ void thruster_pack_flame_update(void *moby) { switch (beam_moby->state) { case STATE_INITIALIZE: beam_moby->f18 += 0.5f; - beam_moby->state = 1; + beam_moby->state = STATE_WAIT_FOR_BEAM; beam_moby->u30 = 0xFF; beam_moby->u34 |= 1; break; @@ -919,7 +919,7 @@ void thruster_pack_flame_update(void *moby) { if (hero_slot_item_id(3) != 3) { mark_moby_for_removal(beam_moby); } else if (flag != 0) { - beam_moby->state = 2; + beam_moby->state = STATE_BEAM_GROW; v->i0 = scale_game_frames(2); v->f30 = 0.0125f / scale_game_frames(2); v->f34 = 0.2f / scale_game_frames(2); @@ -939,7 +939,7 @@ void thruster_pack_flame_update(void *moby) { v->i8 = ((s32)hero.items[3].moby); add_draw_callback(FUN_L00_002b3628_4198, beam_moby); if (fast_dec_timer(v) != 0) { - beam_moby->state = 3; + beam_moby->state = STATE_BEAM_ACTIVE; v->f20 = 0.0125f; v->f24 = 0.2f; v->f28 = 0.05f; @@ -951,7 +951,7 @@ void thruster_pack_flame_update(void *moby) { v->i8 = ((s32)hero.items[3].moby); add_draw_callback(FUN_L00_002b3628_4198, beam_moby); if (flag == 0) { - beam_moby->state = 4; + beam_moby->state = STATE_BEAM_SHRINK; v->i0 = scale_game_frames(8); v->f30 = 0.0125f / scale_game_frames(8); v->f34 = 0.2f / scale_game_frames(8); @@ -964,7 +964,7 @@ void thruster_pack_flame_update(void *moby) { break; case STATE_BEAM_SHRINK: if (fast_dec_timer(v) != 0) { - beam_moby->state = 1; + beam_moby->state = STATE_WAIT_FOR_BEAM; } else { v->f20 -= v->f30; v->f24 -= v->f34; From 295d9c85198edac9cf06aeeeb78996a6ad6cd9b7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:06:09 +0000 Subject: [PATCH 0890/1502] decomp: clarify names in draw_hud_text_panel domain_0_value_0 -> FALSE: The supplied C tests pal_mode != 0 for the panel Y adjustment. Retail 00237204..0023723c loads 0015ed80 and branches on zero to the +18 path (00237250..00237254), otherwise +10 (00237244..0023724c). Original Ghidra shows the same flag test. Its second use selects 50 versus 60 frame time units, confirming a boolean PAL enable predicate; existing FALSE names its disabled zero value. domain_1_value_0 -> FALSE: The supplied C uses pal_mode != 0 ? 3000 : 3600 for elapsed-time conversion. Retail 002375fc..00237610 reloads the same 0015ed80 flag and movn selects 3000 when nonzero, retaining 3600 when zero; 00237638 divides by 60 to obtain 50/60 units per second. Original Ghidra has the same conditional. This proves zero is false for the PAL enable predicate, matching supplied existing FALSE. --- src/overlays/shared/ui/hud/hud_keep_visible.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/ui/hud/hud_keep_visible.c b/src/overlays/shared/ui/hud/hud_keep_visible.c index c6b947cf7e..cb380c384e 100644 --- a/src/overlays/shared/ui/hud/hud_keep_visible.c +++ b/src/overlays/shared/ui/hud/hud_keep_visible.c @@ -651,7 +651,7 @@ int draw_hud_text_panel(HudElem *hud_element) { int text_color; int never = 0; - if (pal_mode != 0) { + if (pal_mode != FALSE) { y = l00_hud_text_panel_base_y + 0xa; } else { y = l00_hud_text_panel_base_y + 0x12; @@ -727,7 +727,7 @@ int draw_hud_text_panel(HudElem *hud_element) { elapsed = freeze_stats_time_ref[current_level_index == 0x10]; score = freeze_stats_score_ref_a[current_level_index == 0x10]; if (elapsed != 0) { - interval = pal_mode != 0 ? 3000 : 3600; + interval = pal_mode != FALSE ? 3000 : 3600; unit = interval / 60; minutes = elapsed / interval; rest = elapsed - minutes * interval; From df34865b74822111d70d77bdb71029ea4af8e957 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:06:09 +0000 Subject: [PATCH 0891/1502] decomp: clarify names in update_sandmouse_hover_movement domain_0_value_6 -> SANDMOUSE_STATE_FADE_OUT: Retail 0030d888 retains incoming moby in s3; 0030d8c8-0030d8e0 tests its state byte at +0x20 against 6 and selects pvars+0x30 as the distance reference. Authoritative sandmouse_update passes this same sandmouse_moby to update_sandmouse_hover_movement and declares SANDMOUSE_STATE_FADE_OUT=6 on sandmouse_moby->state. Its FOLLOW_HERO_AND_FIRE exit assigns that member with the fade timer; the FADE_OUT branch reduces alpha, emits fade particles, and restores the saved a30 position before RESET. This proves the sandmouse state domain, not HeroStateId. domain_1_value_6 -> SANDMOUSE_STATE_FADE_OUT: Retail 0030db78-0030db80 loads the same incoming sandmouse moby's state byte at +0x20 and compares it with 6, gating the velocity clamp to frame_time*2.7 at 0030db88-0030dba8. The identical moby is passed from sandmouse_update, whose enum explicitly defines SANDMOUSE_STATE_FADE_OUT=6 and whose fade branch handles alpha reduction, particles and reset to saved a30. Both comparisons therefore reuse the established sandmouse state member; the command selector at +0xBC is a separate domain. --- src/overlays/shared/enemies/sandmouse.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/sandmouse.c b/src/overlays/shared/enemies/sandmouse.c index 129e6b2172..e0510e8667 100644 --- a/src/overlays/shared/enemies/sandmouse.c +++ b/src/overlays/shared/enemies/sandmouse.c @@ -289,6 +289,9 @@ void update_sandmouse_hover_movement(struct Moby *moby, struct HoverVars *hover_ HOVER_COMMAND_FACE_GOAL = 0, HOVER_COMMAND_MOVE_TO_GOAL = 2 }; + enum { + SANDMOUSE_STATE_FADE_OUT = 6 + }; Vec4 steering_correction; f32 reference_distance; f32 k; @@ -299,7 +302,7 @@ void update_sandmouse_hover_movement(struct Moby *moby, struct HoverVars *hover_ struct HoverTuning *hover_tuning; fast_vec_sub(&steering_correction, hover_vars, &moby->pos); - if (moby->state == 6) { + if (moby->state == SANDMOUSE_STATE_FADE_OUT) { reference_distance = vector_distance_xy(&moby->pos, &hover_vars->unk30); } else { reference_distance = vector_distance_xy(&moby->pos, &hero.motion.pos); @@ -349,7 +352,7 @@ void update_sandmouse_hover_movement(struct Moby *moby, struct HoverVars *hover_ } steering_correction.f[2] *= frame_scale * -0.100000024f + 1.0f; fast_vec_add(&hover_vars->vel, &hover_vars->vel, &steering_correction); - if (moby->state == 6) { + if (moby->state == SANDMOUSE_STATE_FADE_OUT) { clamp_vector_length(&hover_vars->vel, &hover_vars->vel, frame_time * 2.7f); } hover_tuning = &D_L01_001DEB38; From 205af0bbab66c367cf97f3b110873e9684191cec Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:06:09 +0000 Subject: [PATCH 0892/1502] decomp: clarify names in update_hero_timers_and_vehicle_transitions domain_0_value_0 -> CUTSCENE_MODE_INACTIVE: Authoritative C identifies this selector as the separate global cutscene_mode, declared with D_L01_0015F5C4 binding. Retail 0x0023c8dc loads its gp-relative value and 0x0023c8e0 branches past all timed vehicle entry/exit behavior when nonzero; original Ghidra confirms iGpffff89c4 == 0 gates that block. Supplied process_hero_hit_response likewise returns without applying a hit when cutscene_mode != 0, corroborating zero as the inactive cutscene mode. This is unrelated to HeroStateId or HeroVehicleMode despite equal numeric members. --- src/overlays/shared/hero/hero_frame_update.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index c28b0df05d..541f5cc32e 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -1445,6 +1445,9 @@ extern Entry70 l01_countdown_timer_records[] __asm__("D_L01_00179D70"); void update_hero_timers_and_vehicle_transitions(void) __asm__("FUN_L01_0023c710"); void update_hero_timers_and_vehicle_transitions(void) { + enum { + CUTSCENE_MODE_INACTIVE = 0 + }; Vec4 sum; Vec4 sample_delta; struct Moby *vehicle_moby; @@ -1501,7 +1504,7 @@ void update_hero_timers_and_vehicle_transitions(void) { hero.stick_held_frames++; } if (hero.vehicle_toggle_timer != 0 && fast_dec_timer_s16(&hero.vehicle_toggle_timer) != 0 && - hero.health.hp != 0 && cutscene_mode == 0) { + hero.health.hp != 0 && cutscene_mode == CUTSCENE_MODE_INACTIVE) { if (hero.vehicle_mode == 3) { exit_hero_vehicle_mode_and_restore_moby(); if (pad_pressed_within(0x80, scale_game_frames(0x12), 0)) { From 107da04ba55baf1ff325e4b685d3b095aed23c8d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:06:10 +0000 Subject: [PATCH 0893/1502] decomp: clarify names in qwark_rilgar_update domain_0_value_1 -> QWARK_RILGAR_WAIT_FOR_PLAYER_IN_REGION: The bound qwark_rilgar_update source assigns 1 to moby->state after initialization and already switches that same field using QWARK_RILGAR_WAIT_FOR_PLAYER_IN_REGION = 1. Retail 0x002dc4f4 loads state byte +0x20(s1), 0x002dc4f8-0x002dc4fc dispatches value 1 to 0x002dc5c0, which tests data+0x120 against hero position. Initialization paths load 1 at 0x002dc580 or 0x002dc594 and store it to that same byte at 0x002dc5ec. Original Ghidra confirms the shared state load/store and region-wait branch; this is the existing local enum domain, not HeroStateId. domain_1_value_2 -> QWARK_RILGAR_POST_REGION_TRIGGER: The bound source already declares QWARK_RILGAR_POST_REGION_TRIGGER = 2 as a case of this exact moby->state selector. Retail 0x002dc5c0-0x002dc5d8 checks the configured region against hero position; on success 0x002dc5e0 calls the existing helper with argument 1, then 0x002dc5e8 loads 2 and 0x002dc5ec stores it to state byte +0x20(s1). On the next dispatch 0x002dc508/0x002dc51c recognizes 2 and advances to 3. Original Ghidra shows uVar5 = 2 feeding the shared state store. The assignment therefore reuses the proven existing post-region-trigger member of this function's local state enum. --- src/overlays/shared/cutscenes/qwark_rilgar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/cutscenes/qwark_rilgar.c b/src/overlays/shared/cutscenes/qwark_rilgar.c index 4e359cc6bc..522d8175dd 100644 --- a/src/overlays/shared/cutscenes/qwark_rilgar.c +++ b/src/overlays/shared/cutscenes/qwark_rilgar.c @@ -115,13 +115,13 @@ void qwark_rilgar_update(L03WatchMoby *moby) { return; } } - moby->state = 1; + moby->state = QWARK_RILGAR_WAIT_FOR_PLAYER_IN_REGION; break; case QWARK_RILGAR_WAIT_FOR_PLAYER_IN_REGION: if (watch_data->region_a != -1 && is_point_inside_clip_volume(&hero.motion.pos, watch_data->region_a)) { set_moby_dialogue_record_value(moby, 1); - moby->state = 2; + moby->state = QWARK_RILGAR_POST_REGION_TRIGGER; } break; case QWARK_RILGAR_POST_REGION_TRIGGER: From 63226ecb8330b5b904197804963db851cee0f6ea Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:08:04 +0000 Subject: [PATCH 0894/1502] decomp: clarify names in update_child_grid_controller domain_0_value_1 -> CHILD_GRID_STATE_WAIT_LINK_COMMAND: Retail 0x0030d904 resets pvars+0x6c after creating 24 children; 0x0030d90c loads 1 and the shared store at 0x0030dcd0 writes s5+0x20. That exact byte is the switch selector at 0x0030d838. Its existing case CHILD_GRID_STATE_WAIT_LINK_COMMAND reads the linked moby's command at 0x0030d910-0x0030d928, proving reuse of the local state member. domain_1_value_2 -> CHILD_GRID_STATE_FADE_TO_POINT_POSE: Retail 0x0030d934-0x0030d948 writes 2 to s5+0x20 and initializes fade at pvars+0x78 to -1 after linked command 1. The same s5+0x20 selects the existing CHILD_GRID_STATE_FADE_TO_POINT_POSE case, which advances fade and mounts the source point at the zero crossing (0x0030d97c-0x0030da2c). This is a controller state assignment, not a name for the linked command. domain_2_value_5 -> CHILD_GRID_STATE_IDLE: Original Ghidra case 1 sets progress to 1 and selects uVar3=5 when linked command is 2. Retail 0x0030d964-0x0030d978 loads state 5 and branches to the shared byte store at 0x0030dcd0, the same +0x20 selector. Existing CHILD_GRID_STATE_IDLE has no state-specific actions and only reaches the common child pose update, proving this bypass destination. domain_3_value_3 -> CHILD_GRID_STATE_BLEND_POINT_POSES: Retail 0x0030da38-0x0030da5c tests fade >= 1, loads 3 and writes it to s5+0x20. That is the same state byte read at 0x0030d838. Existing case CHILD_GRID_STATE_BLEND_POINT_POSES advances pvars+0x6c and blends configured point positions and rotations at 0x0030da60-0x0030dbfc, proving the destination member directly. domain_4_value_4 -> CHILD_GRID_STATE_FADE_TO_HERO_POSE: Retail 0x0030dc00-0x0030dc24 tests blend progress >= 1, writes 4 to s5+0x20 and resets fade to -1. The existing switch case CHILD_GRID_STATE_FADE_TO_HERO_POSE consumes that same state byte and fade, advances it, and hands pose to hero position/rotation at the zero crossing (0x0030dc28-0x0030dca4), proving reuse of state member 4. domain_5_value_5 -> CHILD_GRID_STATE_IDLE: Retail 0x0030dcb0-0x0030dcd0 tests the hero-pose fade >= 1 and writes 5 to s5+0x20, identical to the selector loaded at 0x0030d838. Existing CHILD_GRID_STATE_IDLE is empty and reaches the shared child layout call at 0x0030dcd4; original Ghidra case 4 likewise exits through uVar3=5. This proves the final fade's idle destination. --- src/overlays/l11/mobys/child_grid_controller.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l11/mobys/child_grid_controller.c b/src/overlays/l11/mobys/child_grid_controller.c index 229e49e8a3..b6c234b274 100644 --- a/src/overlays/l11/mobys/child_grid_controller.c +++ b/src/overlays/l11/mobys/child_grid_controller.c @@ -83,19 +83,19 @@ void child_grid_controller_update(struct Moby *grid_controller) { } } grid_controller_vars->t = 0.0f; - grid_controller->state = 1; + grid_controller->state = CHILD_GRID_STATE_WAIT_LINK_COMMAND; break; case CHILD_GRID_STATE_WAIT_LINK_COMMAND: { struct Moby *link = (struct Moby *)((grid_controller_vars->link << 8) + D_L11_0015FFD8_d800); if (link->command == 1) { - grid_controller->state = 2; + grid_controller->state = CHILD_GRID_STATE_FADE_TO_POINT_POSE; grid_controller_vars->fade = -1.0f; D_L11_00161F54 = 0; allocate_voice_for_target_entry(0, 0, grid_controller); } else if (link->command == 2) { grid_controller_vars->t = 1.0f; - grid_controller->state = 5; + grid_controller->state = CHILD_GRID_STATE_IDLE; } break; } @@ -111,7 +111,7 @@ void child_grid_controller_update(struct Moby *grid_controller) { source_pose_point = (char *)((int)l11_cuboids + (grid_controller_vars->from << 7)); jet_mount(source_pose_point + 0x30, source_pose_point + 0x70, 1, 0, 0); } else if (1.0f <= grid_controller_vars->fade) { - grid_controller->state = 3; + grid_controller->state = CHILD_GRID_STATE_BLEND_POINT_POSES; } break; case CHILD_GRID_STATE_BLEND_POINT_POSES: @@ -148,7 +148,7 @@ void child_grid_controller_update(struct Moby *grid_controller) { set_camera_position(&pos); set_camera_rotation(&rot); if (1.0f <= grid_controller_vars->t) { - grid_controller->state = 4; + grid_controller->state = CHILD_GRID_STATE_FADE_TO_HERO_POSE; grid_controller_vars->fade = -1.0f; } break; @@ -160,7 +160,7 @@ void child_grid_controller_update(struct Moby *grid_controller) { set_race_camera(&hero.motion.pos, &hero.motion.rot, 0, 1); jet_end_mount(3); } else if (1.0f <= grid_controller_vars->fade) { - grid_controller->state = 5; + grid_controller->state = CHILD_GRID_STATE_IDLE; } break; case CHILD_GRID_STATE_IDLE: From adb304428fff74747e48ad49051cc3036a83d5bc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:08:04 +0000 Subject: [PATCH 0895/1502] decomp: clarify names in psytcopus_update domain_0_value_3 -> PSYTCOPUS_STATE_FACE_PLAYER: Retail 0x00310274 stores 3 to receiver s1+0x20, the same byte read by the state switch at 0x00310208. Existing local enum PSYTCOPUS_STATE_FACE_PLAYER names case 3, whose 0x003102f4-0x00310350 computes player-relative heading and approaches yaw. This initialization assignment enters that exact domain member. domain_2_value_3 -> PSYTCOPUS_STATE_FACE_PLAYER: Retail 0x003102e8 stores s0=3 to s1+0x20 on the non-path initialization branch. The switch reads this same receiver byte at 0x00310208; existing case PSYTCOPUS_STATE_FACE_PLAYER=3 computes player-relative yaw at 0x003102f4-0x00310350, so reuse that canonical local state member. domain_3_value_4 -> PSYTCOPUS_STATE_CREATE_PROJECTILE: Retail 0x00310360 loads 4 and 0x0031036c stores it to receiver state s1+0x20 after the pvars+0x114 guard. The same state selector dispatches case 4, already named PSYTCOPUS_STATE_CREATE_PROJECTILE; its animation-window-15 branch calls projectile spawning at 0x0031042c and saves the pointer at pvars+0x160. domain_4_value_5 -> PSYTCOPUS_STATE_FIRE_PROJECTILE: Retail 0x00310448 loads 5 and 0x00310458 stores it to s1+0x20 when the creation animation ends. This is the state switch byte read at 0x00310208. Existing case PSYTCOPUS_STATE_FIRE_PROJECTILE=5 launches the saved projectile via 0x0031050c with frame_time*30 forward vector and clears pvars+0x160. domain_5_value_6 -> PSYTCOPUS_STATE_ATTACK_RECOVERY: Retail 0x00310524 loads 6 and 0x00310534 writes it to receiver s1+0x20 after the firing animation completes, then blends sequence 4. Existing PSYTCOPUS_STATE_ATTACK_RECOVERY=6 labels this same state selector's branch, which waits for animation completion at 0x00310550-0x00310564 before returning to face-player state. domain_6_value_3 -> PSYTCOPUS_STATE_FACE_PLAYER: In attack recovery retail 0x0031055c loads 3 and branches through 0x00310560 to the shared state store at 0x003105b8, followed by sequence-0 blending. The stored receiver byte is the switch selector s1+0x20; existing PSYTCOPUS_STATE_FACE_PLAYER=3 labels its player-facing yaw branch, proving this recovery destination. domain_7_value_3 -> PSYTCOPUS_STATE_FACE_PLAYER: After knockback contact and a successful path containment check at 0x003105a0, retail 0x003105ac loads 3 and 0x003105b8 stores it to receiver state s1+0x20, with sequence-0 blending. This is the identical switch selector whose case 3 is already PSYTCOPUS_STATE_FACE_PLAYER and performs player-relative yaw adjustment. --- src/overlays/l11/mobys/psytcopus.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l11/mobys/psytcopus.c b/src/overlays/l11/mobys/psytcopus.c index ee03e2bbe6..ed0770a3af 100644 --- a/src/overlays/l11/mobys/psytcopus.c +++ b/src/overlays/l11/mobys/psytcopus.c @@ -140,7 +140,7 @@ void psytcopus_update(struct Moby *psytcopus) { psytcopus_vars->unk2A = 6; psytcopus_vars->unk58 = truncate_float_to_s32(8.0f); psytcopus_vars->unk5A = truncate_float_to_s32(8.0f); - psytcopus->state = 3; + psytcopus->state = PSYTCOPUS_STATE_FACE_PLAYER; if (psytcopus->prev_seq != 0) { blend_moby_animation(psytcopus, 0, 0, scale_game_frames(10)); } @@ -149,7 +149,7 @@ void psytcopus_update(struct Moby *psytcopus) { qcopy(&psytcopus->pos, (char *)(s32 *)l11_paths[psytcopus_vars->unk134] + 0x10); break; } - psytcopus->state = 3; + psytcopus->state = PSYTCOPUS_STATE_FACE_PLAYER; if (psytcopus->prev_seq != 0) { blend_moby_animation(psytcopus, 0, 0, scale_game_frames(10)); } @@ -166,7 +166,7 @@ void psytcopus_update(struct Moby *psytcopus) { frame_time * 6.2831855f); } if (psytcopus_vars->unk114 != 2) { - psytcopus->state = 4; + psytcopus->state = PSYTCOPUS_STATE_CREATE_PROJECTILE; if (psytcopus->prev_seq != 2) { blend_moby_animation(psytcopus, 2, 0, scale_game_frames(10)); } @@ -193,7 +193,7 @@ void psytcopus_update(struct Moby *psytcopus) { break; } if (psytcopus->anim_flags & 2) { - psytcopus->state = 5; + psytcopus->state = PSYTCOPUS_STATE_FIRE_PROJECTILE; if (psytcopus->prev_seq != 3) { blend_moby_animation(psytcopus, 3, 0, scale_game_frames(10)); } @@ -217,7 +217,7 @@ void psytcopus_update(struct Moby *psytcopus) { psytcopus_vars->unk160 = 0; } if (psytcopus->anim_flags & 2) { - psytcopus->state = 6; + psytcopus->state = PSYTCOPUS_STATE_ATTACK_RECOVERY; if (psytcopus->prev_seq != 4) { blend_moby_animation(psytcopus, 4, 0, scale_game_frames(10)); } @@ -225,7 +225,7 @@ void psytcopus_update(struct Moby *psytcopus) { break; case PSYTCOPUS_STATE_ATTACK_RECOVERY: if (psytcopus->anim_flags & 2) { - psytcopus->state = 3; + psytcopus->state = PSYTCOPUS_STATE_FACE_PLAYER; if (psytcopus->prev_seq != 0) { blend_moby_animation(psytcopus, 0, 0, scale_game_frames(10)); } @@ -236,7 +236,7 @@ void psytcopus_update(struct Moby *psytcopus) { if (knockback_result_flags & 0x41) { path = (s32 *)l11_paths[psytcopus_vars->unk13C]; if (FUN_L00_00259740_p(&psytcopus->pos, path + 4, *path) != 0) { - psytcopus->state = 3; + psytcopus->state = PSYTCOPUS_STATE_FACE_PLAYER; if (psytcopus->prev_seq != 0) { blend_moby_animation(psytcopus, 0, 0, scale_game_frames(10)); } From 92be2a72fcf4d8b1173baf71bfc38f49b1bed4c9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:08:04 +0000 Subject: [PATCH 0896/1502] decomp: clarify names in apply_hero_ground_material_effects domain_0_value_2 -> GROUND_MATERIAL_MAGNET: The s16 hero.ground_type snapshot is loaded into s2 at 0x00239ff4 and compared to 2 at 0x0023a014-0x0023a018. On contact or ground_distance below 0.3, 0x0023a058 sets hero.on_magnet_ground at offset 0x12e7. This proves a ground-material magnet selector, independently of the state enum. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0023a050 loads the byte at hero offset 0x20a4, identified as hero.vehicle_mode by the authoritative source; 0x0023a054 requires zero before the equipped-item check. The supplied hero_set_state context uses the same hero.vehicle_mode field with HERO_VEHICLE_MODE_ON_FOOT, and the supplied HeroVehicleMode enum defines that canonical member as zero. This is vehicle-mode data flow, not material or current-state data flow. domain_2_value_14 -> GROUND_MATERIAL_FIXED_SHALLOW_WATER: Retail 0x0023a084 compares the saved s16 ground material in s2 against 14. Instructions 0x0023a08c-0x0023a0ac store 0.2f into hero.water_depth and ground_z + 0.2f into hero.water_surface_z, setting base_condition. The source confirms this material imposes a fixed shallow water depth, unlike material zero's measured surface-to-ground depth. domain_3_value_0 -> GROUND_MATERIAL_WATER: At 0x0023a0b0 the saved ground material in s2 is tested for zero; 0x0023a0c8-0x0023a0e0 computes hero.water_surface_z minus hero.ground_z into hero.water_depth, and 0x0023a100 sets wading when depth is between 0.25 and 0.85. The supplied update_hero_ground_contact source obtains hero.ground_type from collision_hit_material and resolves water_surface_z for material zero, corroborating the water-material domain. --- .../l05/hero/apply_hero_ground_material_effects.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/overlays/l05/hero/apply_hero_ground_material_effects.c b/src/overlays/l05/hero/apply_hero_ground_material_effects.c index 089cb4d08d..26fbfd2881 100644 --- a/src/overlays/l05/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l05/hero/apply_hero_ground_material_effects.c @@ -20,6 +20,11 @@ extern int hero_set_state(int, int) __asm__("FUN_L05_0024cee8"); void apply_hero_ground_material_effects(void) __asm__("FUN_L05_00239fc0"); void apply_hero_ground_material_effects(void) { + enum { + GROUND_MATERIAL_WATER = 0, + GROUND_MATERIAL_MAGNET = 2, + GROUND_MATERIAL_FIXED_SHALLOW_WATER = 14 + }; u8 save = hero.ground_sound_class; s16 saved_ground_type = hero.ground_type; f32 water_depth; @@ -31,20 +36,20 @@ void apply_hero_ground_material_effects(void) { hero.unk308 = 0; if (saved_ground_type == -1) return; - if (saved_ground_type == 2) { + if (saved_ground_type == GROUND_MATERIAL_MAGNET) { if (hero.frames_off_ground.s == 0 || hero.ground_distance < 0.3f) { hero.on_magnet_ground = 1; - if (hero.vehicle_mode == 0 && ((u8 *)hero.items[1].moby) != 0 && + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT && ((u8 *)hero.items[1].moby) != 0 && *(s16 *)(((u8 *)hero.items[1].moby) + 0xA6) == 0xAD) hero.unk308 = 1; } } - if (saved_ground_type == 14) { + if (saved_ground_type == GROUND_MATERIAL_FIXED_SHALLOW_WATER) { hero.base_condition = 1; hero.water_depth = 0.2f; hero.water_surface_z = hero.ground_z.f + 0.2f; } - if (saved_ground_type == 0) { + if (saved_ground_type == GROUND_MATERIAL_WATER) { water_depth = hero.water_surface_z - hero.ground_z.f; hero.water_depth = water_depth; if (water_depth < 0.85f && 0.25f < water_depth) From e849b2f61d645728ba77a5d2a6d71b78939da3e7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:08:04 +0000 Subject: [PATCH 0897/1502] decomp: clarify names in qwarks_bouncer_update domain_0_value_1 -> QWARKS_BOUNCER_UPDATE_DIALOGUE: Authoritative source src/overlays/l05/mobys/qwarks_bouncer.c SHA-256 935504199e4b7ff4ff3be35597f3b65112c5da59311d2eaeb2f17fe1bcfd38a1 declares QWARKS_BOUNCER_UPDATE_DIALOGUE=1 for switch(bouncer_moby->state). Retail 003174b0 loads the selector byte from 0x20(s1); 003174b8-003174bc compares that byte with 1 and branches to 00317518, the update_npc_dialogue call. Initialization loads v1=1 at 003174dc and stores that exact value into the same selector byte at 003174f4, while initializing dialogue at 003174f0. The original Ghidra decompilation independently shows owner +0x20 assigned 1 and its ==1 branch updating dialogue. Thus the assignment reuses the established outer-state enum member, not the separate dialogue substate at 0x4(s2). --- src/overlays/l05/mobys/qwarks_bouncer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l05/mobys/qwarks_bouncer.c b/src/overlays/l05/mobys/qwarks_bouncer.c index 38c7c703ab..a5ebc98160 100644 --- a/src/overlays/l05/mobys/qwarks_bouncer.c +++ b/src/overlays/l05/mobys/qwarks_bouncer.c @@ -134,7 +134,7 @@ void qwarks_bouncer_update(WM_c *bouncer_moby) { return; } bouncer_data->ptr20 = (void *)qwarks_bouncer_dialogue_name; - bouncer_moby->state = 1; + bouncer_moby->state = QWARKS_BOUNCER_UPDATE_DIALOGUE; initialize_npc_dialogue(bouncer_moby, bouncer_data); bouncer_data->fC = 3.7f; initialize_moby_grounding(bouncer_moby); From e324e4584ab6524a1c59cccc86a0e637981807a0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:08:04 +0000 Subject: [PATCH 0898/1502] decomp: clarify names in barrier_update domain_0_value_0 -> BARRIER_STATE_UNINITIALIZED: In the authoritative barrier_update source, moby->state == 0 gates the linked-flag initialization before storing state 1. Retail 0x00308328 loads the state byte at moby+0x20; 0x0030832c skips this setup when nonzero; 0x00308334-0x00308350 clears the linked flag when its index is valid. Original Ghidra agrees. spawn_barrier_replacement also initializes the new barrier's byte +0x20 to zero before update_entity. Thus zero denotes the barrier state awaiting this initialization. domain_1_value_1 -> BARRIER_STATE_INITIALIZED: The source assigns moby->state = 1 immediately after the conditional linked-flag initialization. Retail 0x00308354 loads 1 and 0x00308358 stores it to the same moby+0x20 state byte tested at 0x00308328-0x0030832c, causing subsequent updates to bypass the initialization block. Original Ghidra shows the same state transition. The assignment proves completion of barrier initialization without implying a broader active-state lifecycle. --- src/overlays/l09/mobys/barrier.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l09/mobys/barrier.c b/src/overlays/l09/mobys/barrier.c index 6411db55cf..d5ca816448 100644 --- a/src/overlays/l09/mobys/barrier.c +++ b/src/overlays/l09/mobys/barrier.c @@ -93,6 +93,10 @@ char *spawn_barrier_replacement(struct Moby *source_moby, int spawned_moby_class /* Moby classes 1285-1288 */ void barrier_update(Moby *moby) { + enum { + BARRIER_STATE_UNINITIALIZED = 0, + BARRIER_STATE_INITIALIZED = 1 + }; BarrierData *barrier_vars = (*(BarrierData **)&moby->pvars); float origin[4], center[4], piece_pos[4], piece_velocity[4], push[4]; Hit_309688 *hit; @@ -102,10 +106,10 @@ void barrier_update(Moby *moby) { float angle; float scale; - if (moby->state == 0) { + if (moby->state == BARRIER_STATE_UNINITIALIZED) { if (barrier_vars->idx != -1) ((Flags_309688 *)(alternate_item_available + barrier_vars->idx))->f43 = 0; - moby->state = 1; + moby->state = BARRIER_STATE_INITIALIZED; } if (moby->mission != 0xFF) { int row = current_level_index * 16; From 31aee14c9ba577e7503d19205ee65c839c5d0149 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:08:04 +0000 Subject: [PATCH 0899/1502] decomp: clarify names in update_mine_group domain_0_value_1 -> ADVANCE_PATH_CHILDREN: Authoritative src/overlays/l07/mobys/mine_group.c SHA-256 8cfba59e49676957c18fec424126ab2cbf89a0ce9e7072b7f9699217ffdaa446 assigns moby->state = 1 after INITIALIZE_PATH_CHILDREN and already declares ADVANCE_PATH_CHILDREN = 1 for the same switch(moby->state). Original retail Ghidra stores 1 at moby+0x20 after child initialization. Retail 0030b3c4 loads v0=1 and 0030b3cc stores it at 0x20(s4); 0030b1b4 reads that same state byte and 0030b1c4..0030b1c8 routes value 1 to 0030b3d0. That branch iterates group children and calls sample_path with speed times frame_time at 0030b418..0030b440, proving reuse of the existing path-advancement state constant rather than the unrelated equal-valued hit-response constant. --- src/overlays/l07/mobys/mine_group.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l07/mobys/mine_group.c b/src/overlays/l07/mobys/mine_group.c index 31662074f3..198040d60c 100644 --- a/src/overlays/l07/mobys/mine_group.c +++ b/src/overlays/l07/mobys/mine_group.c @@ -356,7 +356,7 @@ void mine_group_update(struct Moby *moby) { } if (!boltcrate_pvars->unk95) moby->flags |= 1; - moby->state = 1; + moby->state = ADVANCE_PATH_CHILDREN; break; } case ADVANCE_PATH_CHILDREN: { From da7758685d2c522ac0b571e891f98522d2d225b6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:08:04 +0000 Subject: [PATCH 0900/1502] decomp: clarify names in update_umbris_scene_progression domain_0_value_0 -> SCENE_STATE_IDLE: 002f5c10-002f5c28 tests scene_state at 0x0015f5c4 against zero before leaving CONTROLLER_WAIT_FOR_SCENE_IDLE and entering initial scene startup. This is the scene lifecycle domain, not Moby.state. domain_10_value_4 -> CONTROLLER_WAIT_FOR_OPEN_VOLUME: 002f5d20-002f5d28 reloads controller s3+0x20 and compares with 4 before deleting removed_moby on departure. Same selector and value as existing CONTROLLER_WAIT_FOR_OPEN_VOLUME case. domain_11_value_2 -> SCENE_STATE_ACTIVE: 002f5d5c compares scene_state at 0x0015f5c4 with 2 to hold this controller's scene-completion transition. Checked level-07 start_scene instructions 002bf628/002bf640 explicitly set this same word to 2 during scene setup, proving a separate active-scene domain. domain_12_value_6 -> CONTROLLER_WAIT_FOR_SECOND_OPEN_SCENE: 002f5d84-002f5d90 stores 6 to controller state while calling start_scene(2); existing CONTROLLER_WAIT_FOR_SECOND_OPEN_SCENE holds until scene_state changes. domain_13_value_2 -> SCENE_STATE_ACTIVE: 002f5da8 compares scene_state at 0x0015f5c4 with 2 to hold this controller's scene-completion transition. Checked level-07 start_scene instructions 002bf628/002bf640 explicitly set this same word to 2 during scene setup, proving a separate active-scene domain. domain_14_value_7 -> CONTROLLER_CLEAR_LINKED_MOBY_FLAGS: 002f5ddc-002f5de4 stores 7 to s3+0x20 after second-open-scene completion and optional camera placement; this dispatches existing CONTROLLER_CLEAR_LINKED_MOBY_FLAGS. domain_15_value_8 -> CONTROLLER_WAIT_FOR_FINISH_VOLUME: 002f5e38-002f5e40 stores 8 to controller state after clearing linked flags and requesting music; existing CONTROLLER_WAIT_FOR_FINISH_VOLUME tests finish_volume. domain_16_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: 002f5e80-002f5e84 checks state byte +0x20 of a linked level_mobys[index] at stride 0x100, not the scene controller lifecycle. Supplied mark_moby_for_removal C assigns 0xFE when moby >= moby_instance_end; these guards detect that same removal state before finish triggering or repeated removal. domain_17_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: 002f5e88-002f5e8c checks state byte +0x20 of a linked level_mobys[index] at stride 0x100, not the scene controller lifecycle. Supplied mark_moby_for_removal C assigns 0xFD when moby < moby_instance_end; these guards detect that same removal state before finish triggering or repeated removal. domain_18_value_9 -> CONTROLLER_WAIT_FOR_FINISH_VOLUME_SCENE: 002f5ee4-002f5ef0 stores 9 to controller state after finish-volume success and calls start_scene(3), reaching existing CONTROLLER_WAIT_FOR_FINISH_VOLUME_SCENE. domain_19_value_13 -> CONTROLLER_DELETE_SELF: 002f5e9c branches on missing finish_volume to 002f5efc-002f5f00 storing 13 to controller state; existing CONTROLLER_DELETE_SELF calls removal with s3 at 002f60a4-002f60a8. domain_1_value_1 -> CONTROLLER_START_INITIAL_SCENE: 002f5c20-002f5c28 stores 1 to controller s3+0x20 after scene_state becomes idle; that exact byte dispatches the existing CONTROLLER_START_INITIAL_SCENE case at 002f5bbc. domain_20_value_12 -> CONTROLLER_CLEANUP_LINKED_MOBY: 002f5e50-002f5e58 branches on already-set finish-scene flag to 002f5f00 storing controller state 12, dispatching existing CONTROLLER_CLEANUP_LINKED_MOBY. domain_21_value_8 -> CONTROLLER_WAIT_FOR_FINISH_VOLUME: 002f5f04-002f5f0c compares controller s3+0x20 with 8 to set linked moby flags only after departure from existing CONTROLLER_WAIT_FOR_FINISH_VOLUME. domain_22_value_2 -> SCENE_STATE_ACTIVE: 002f5f44 compares scene_state at 0x0015f5c4 with 2 to hold this controller's scene-completion transition. Checked level-07 start_scene instructions 002bf628/002bf640 explicitly set this same word to 2 during scene setup, proving a separate active-scene domain. domain_23_value_10 -> CONTROLLER_WAIT_TO_START_FINAL_SCENE: 002f5f38-002f5f54 stores 10 to controller state after finish-volume scene completion and queues movie 8; existing case 10 is CONTROLLER_WAIT_TO_START_FINAL_SCENE. domain_24_value_2 -> SCENE_STATE_ACTIVE: 002f5f6c compares scene_state at 0x0015f5c4 with 2 to hold this controller's scene-completion transition. Checked level-07 start_scene instructions 002bf628/002bf640 explicitly set this same word to 2 during scene setup, proving a separate active-scene domain. domain_25_value_11 -> CONTROLLER_WAIT_FOR_FINAL_SCENE_AND_UNLOCK_PLANET: 002f5f60-002f5f7c stores 11 to controller state while starting scene 4, then falls into existing CONTROLLER_WAIT_FOR_FINAL_SCENE_AND_UNLOCK_PLANET. domain_26_value_2 -> SCENE_STATE_ACTIVE: 002f5f8c compares scene_state at 0x0015f5c4 with 2 to hold this controller's scene-completion transition. Checked level-07 start_scene instructions 002bf628/002bf640 explicitly set this same word to 2 during scene setup, proving a separate active-scene domain. domain_27_value_12 -> CONTROLLER_CLEANUP_LINKED_MOBY: 002f6050-002f6058 stores 12 to controller state after final-scene completion and planet/save/load calls; same selector dispatches existing CONTROLLER_CLEANUP_LINKED_MOBY. domain_28_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: 002f6078-002f6080 checks state byte +0x20 of a linked level_mobys[index] at stride 0x100, not the scene controller lifecycle. Supplied mark_moby_for_removal C assigns 0xFE when moby >= moby_instance_end; these guards detect that same removal state before finish triggering or repeated removal. domain_29_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: 002f6084-002f6088 checks state byte +0x20 of a linked level_mobys[index] at stride 0x100, not the scene controller lifecycle. Supplied mark_moby_for_removal C assigns 0xFD when moby < moby_instance_end; these guards detect that same removal state before finish triggering or repeated removal. domain_2_value_2 -> CONTROLLER_WAIT_FOR_INITIAL_SCENE: 002f5c44-002f5c54 stores 2 to controller s3+0x20 while calling start_scene(0); the same state byte dispatches existing CONTROLLER_WAIT_FOR_INITIAL_SCENE. domain_30_value_13 -> CONTROLLER_DELETE_SELF: 002f6098-002f60a0 stores 13 to controller state after linked-moby cleanup; existing CONTROLLER_DELETE_SELF passes controller s3 to mark_moby_for_removal. domain_3_value_3 -> CONTROLLER_ADVANCE_TO_OPEN_VOLUME_WAIT: 002f5c38 branches when the initial-scene flag is already set to 002f5c74-002f5c78, storing 3 into the controller state selector; existing case 3 is CONTROLLER_ADVANCE_TO_OPEN_VOLUME_WAIT. domain_4_value_2 -> SCENE_STATE_ACTIVE: 002f5c6c compares scene_state at 0x0015f5c4 with 2 to hold this controller's scene-completion transition. Checked level-07 start_scene instructions 002bf628/002bf640 explicitly set this same word to 2 during scene setup, proving a separate active-scene domain. domain_5_value_3 -> CONTROLLER_ADVANCE_TO_OPEN_VOLUME_WAIT: 002f5c60-002f5c78 waits for scene_state to differ from 2 then stores 3 to s3+0x20, the selector for existing CONTROLLER_ADVANCE_TO_OPEN_VOLUME_WAIT. domain_6_value_4 -> CONTROLLER_WAIT_FOR_OPEN_VOLUME: 002f5c7c-002f5c84 unconditionally stores 4 to controller s3+0x20; existing case CONTROLLER_WAIT_FOR_OPEN_VOLUME tests hero against pvars+0 clip volume. domain_7_value_5 -> CONTROLLER_WAIT_FOR_FIRST_OPEN_SCENE: 002f5d00-002f5d0c stores controller state 5 after successful open-volume entry and calls start_scene(1), reaching existing CONTROLLER_WAIT_FOR_FIRST_OPEN_SCENE. domain_8_value_8 -> CONTROLLER_WAIT_FOR_FINISH_VOLUME: 002f5ca4 branches on missing open_volume to 002f5d18-002f5d1c storing controller state 8, which dispatches existing CONTROLLER_WAIT_FOR_FINISH_VOLUME. domain_9_value_7 -> CONTROLLER_CLEAR_LINKED_MOBY_FLAGS: 002f5c90-002f5c98 and 002f5d1c bypass the already-triggered open scene by storing 7 to controller state; existing CONTROLLER_CLEAR_LINKED_MOBY_FLAGS clears flags at linked moby +0x34. --- .../l07/mobys/umbris_scene_progression.c | 64 ++++++++++--------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/src/overlays/l07/mobys/umbris_scene_progression.c b/src/overlays/l07/mobys/umbris_scene_progression.c index 327988f1c5..cf716af470 100644 --- a/src/overlays/l07/mobys/umbris_scene_progression.c +++ b/src/overlays/l07/mobys/umbris_scene_progression.c @@ -56,6 +56,12 @@ void umbris_scene_progression_update(struct Moby *moby) { CONTROLLER_CLEANUP_LINKED_MOBY = 12, CONTROLLER_DELETE_SELF = 13 }; + enum { + SCENE_STATE_IDLE = 0, + SCENE_STATE_ACTIVE = 2, + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE + }; Class436Vars *scene_controller_vars = (Class436Vars *)moby->pvars; float linked_moby_to_hero_offset[4]; @@ -65,24 +71,24 @@ void umbris_scene_progression_update(struct Moby *moby) { mark_moby_for_removal( &((struct Moby *)level_mobys)[scene_controller_vars->removed_moby]); } - if (scene_state == 0) - moby->state = 1; + if (scene_state == SCENE_STATE_IDLE) + moby->state = CONTROLLER_START_INITIAL_SCENE; break; case CONTROLLER_START_INITIAL_SCENE: if (alternate_item_available[0x28] == 0) { alternate_item_available[0x28] = 1; - moby->state = 2; + moby->state = CONTROLLER_WAIT_FOR_INITIAL_SCENE; start_scene(0); } else { - moby->state = 3; + moby->state = CONTROLLER_ADVANCE_TO_OPEN_VOLUME_WAIT; } break; case CONTROLLER_WAIT_FOR_INITIAL_SCENE: - if (scene_state != 2) - moby->state = 3; + if (scene_state != SCENE_STATE_ACTIVE) + moby->state = CONTROLLER_ADVANCE_TO_OPEN_VOLUME_WAIT; break; case CONTROLLER_ADVANCE_TO_OPEN_VOLUME_WAIT: - moby->state = 4; + moby->state = CONTROLLER_WAIT_FOR_OPEN_VOLUME; break; case CONTROLLER_WAIT_FOR_OPEN_VOLUME: if (alternate_item_available[0x29] == 0) { @@ -100,32 +106,32 @@ void umbris_scene_progression_update(struct Moby *moby) { &((struct Moby *)level_mobys)[scene_controller_vars->moby_14]; e->flags |= 0x41; } - moby->state = 5; + moby->state = CONTROLLER_WAIT_FOR_FIRST_OPEN_SCENE; start_scene(1); } } else { - moby->state = 8; + moby->state = CONTROLLER_WAIT_FOR_FINISH_VOLUME; } } else { - moby->state = 7; + moby->state = CONTROLLER_CLEAR_LINKED_MOBY_FLAGS; } - if (moby->state != 4 && scene_controller_vars->removed_moby != -1) { + if (moby->state != CONTROLLER_WAIT_FOR_OPEN_VOLUME && scene_controller_vars->removed_moby != -1) { mark_moby_for_removal( &((struct Moby *)level_mobys)[scene_controller_vars->removed_moby]); } break; case CONTROLLER_WAIT_FOR_FIRST_OPEN_SCENE: - if (scene_state == 2) + if (scene_state == SCENE_STATE_ACTIVE) break; if (scene_controller_vars->moby_0c != -1) { struct Moby *e = &((struct Moby *)level_mobys)[scene_controller_vars->moby_0c]; e->flags |= 0x41; } - moby->state = 6; + moby->state = CONTROLLER_WAIT_FOR_SECOND_OPEN_SCENE; start_scene(2); break; case CONTROLLER_WAIT_FOR_SECOND_OPEN_SCENE: - if (scene_state == 2) + if (scene_state == SCENE_STATE_ACTIVE) break; if (scene_controller_vars->points_18 != -1) { set_race_camera(&l07_cuboids[scene_controller_vars->points_18].pos, @@ -133,7 +139,7 @@ void umbris_scene_progression_update(struct Moby *moby) { 0, 1); } - moby->state = 7; + moby->state = CONTROLLER_CLEAR_LINKED_MOBY_FLAGS; break; case CONTROLLER_CLEAR_LINKED_MOBY_FLAGS: if (scene_controller_vars->moby_0c != -1) { @@ -145,14 +151,14 @@ void umbris_scene_progression_update(struct Moby *moby) { e->flags &= 0xFFBE; } request_music_track(2, 4); - moby->state = 8; + moby->state = CONTROLLER_WAIT_FOR_FINISH_VOLUME; break; case CONTROLLER_WAIT_FOR_FINISH_VOLUME: if (alternate_item_available[0x2A] == 0) { struct Moby *e; if (scene_controller_vars->moby_0c == -1 || (e = &((struct Moby *)level_mobys)[scene_controller_vars->moby_0c]) == 0 || - e->state == 0xFE || e->state == 0xFD) { + e->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || e->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { if (scene_controller_vars->finish_volume != -1) { if (is_point_inside_clip_volume(&hero.motion.pos, scene_controller_vars->finish_volume) != 0) { @@ -161,34 +167,34 @@ void umbris_scene_progression_update(struct Moby *moby) { 0x72, 1); alternate_item_available[0x2A] = 1; - moby->state = 9; + moby->state = CONTROLLER_WAIT_FOR_FINISH_VOLUME_SCENE; start_scene(3); } } else { - moby->state = 13; + moby->state = CONTROLLER_DELETE_SELF; } } } else { - moby->state = 12; + moby->state = CONTROLLER_CLEANUP_LINKED_MOBY; } - if (moby->state != 8 && scene_controller_vars->moby_10 != -1) { + if (moby->state != CONTROLLER_WAIT_FOR_FINISH_VOLUME && scene_controller_vars->moby_10 != -1) { struct Moby *e = &((struct Moby *)level_mobys)[scene_controller_vars->moby_10]; e->flags |= 0x41; } break; case CONTROLLER_WAIT_FOR_FINISH_VOLUME_SCENE: - if (scene_state == 2) + if (scene_state == SCENE_STATE_ACTIVE) break; - moby->state = 10; + moby->state = CONTROLLER_WAIT_TO_START_FINAL_SCENE; queue_scene_movie_with_game_language(8); break; case CONTROLLER_WAIT_TO_START_FINAL_SCENE: - if (scene_state == 2) + if (scene_state == SCENE_STATE_ACTIVE) break; - moby->state = 11; + moby->state = CONTROLLER_WAIT_FOR_FINAL_SCENE_AND_UNLOCK_PLANET; start_scene(4); case CONTROLLER_WAIT_FOR_FINAL_SCENE_AND_UNLOCK_PLANET: - if (scene_state == 2) + if (scene_state == SCENE_STATE_ACTIVE) break; if (scene_controller_vars->points_1c != -1) { set_race_camera(&l07_cuboids[scene_controller_vars->points_1c].pos, @@ -207,16 +213,16 @@ void umbris_scene_progression_update(struct Moby *moby) { unlock_planet(8); memcard_save_data(0, 8); request_space_load(8); - moby->state = 12; + moby->state = CONTROLLER_CLEANUP_LINKED_MOBY; break; case CONTROLLER_CLEANUP_LINKED_MOBY: if (scene_controller_vars->moby_10 != -1) { struct Moby *e = &((struct Moby *)level_mobys)[scene_controller_vars->moby_10]; - if (e != 0 && e->state != 0xFE && e->state != 0xFD) { + if (e != 0 && e->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && e->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { mark_moby_for_removal(e); } } - moby->state = 13; + moby->state = CONTROLLER_DELETE_SELF; break; case CONTROLLER_DELETE_SELF: mark_moby_for_removal(moby); From 8e94d86089e2c9fd9ac9c34311053753e347339b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:08:05 +0000 Subject: [PATCH 0901/1502] decomp: clarify names in taxi_update domain_0_value_3 -> TAXI_BLEND_TO_PATH_START: Retail 0x002e452c-0x002e4534 writes 3 to this taxi's byte at +0x20, the same field loaded for switch dispatch at 0x002e4444. Its case 3 at 0x002e45a0-0x002e467c blends current-stop pose (+0xAC) toward the path sample at progress zero; reuse the existing TAXI_BLEND_TO_PATH_START member. domain_1_value_4 -> TAXI_FOLLOW_PATH: Retail 0x002e4658-0x002e467c checks blend progress >= 1, clears progress/velocity, then writes 4 to the same taxi +0x20 state field used by switch dispatch. Existing case TAXI_FOLLOW_PATH invokes advance_taxi_path at 0x002e4680; the bound helper source advances progress and samples the path. Reuse that exact local enum member. domain_2_value_5 -> TAXI_BLEND_TO_DESTINATION_POSE: Retail 0x002e4680-0x002e469c tests advance_taxi_path's completion result, clears progress/velocity and writes 5 to taxi +0x20. Case 5 loads destination pose through pvars+0xAE at 0x002e46d8-0x002e4718 and blends the path-end sample toward it at 0x002e4738-0x002e4790. Reuse existing TAXI_BLEND_TO_DESTINATION_POSE. domain_3_value_1 -> TAXI_WAIT_FOR_DEPARTURE: Retail 0x002e4790-0x002e47b8 completes the destination blend, resets progress/velocity and writes 1 to taxi +0x20 before transferring the linked placement. The same field selects existing case TAXI_WAIT_FOR_DEPARTURE, whose grounded hero and local-offset checks gate departure at 0x002e4484-0x002e4534. Reuse that member. domain_4_value_1 -> TAXI_WAIT_FOR_DEPARTURE: Retail enable branch 0x002e47c4-0x002e47f0 restores model collision and visibility, clears the disabled flag and writes 1 at 0x002e47e4 to this taxi's +0x20 dispatch field. This selects the existing TAXI_WAIT_FOR_DEPARTURE case with grounded hero/local-offset departure checks; it is not a Hero state or vehicle mode. domain_5_value_3 -> TAXI_BLEND_TO_PATH_START: The source lower bound moby->state >= 3 and upper bound <= 5 compile to the same taxi +0x20 byte load, subtract 3, unsigned <3 test at 0x002e47fc-0x002e4808. The lower endpoint is the existing TAXI_BLEND_TO_PATH_START case in this very switch, encompassing the blend/path/blend travel interval before hero locks, vector updates and sound allocation. domain_6_value_5 -> TAXI_BLEND_TO_DESTINATION_POSE: The source travel range moby->state >= 3 && moby->state <= 5 is represented by taxi +0x20 minus 3 <3 at 0x002e47fc-0x002e4808. Its inclusive upper endpoint is the existing TAXI_BLEND_TO_DESTINATION_POSE case, whose completion writes wait state 1 at 0x002e47b8. Reuse that member for this same selector's upper bound. --- src/overlays/l16/mobys/taxi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l16/mobys/taxi.c b/src/overlays/l16/mobys/taxi.c index 1df667d0b3..ae5822f65e 100644 --- a/src/overlays/l16/mobys/taxi.c +++ b/src/overlays/l16/mobys/taxi.c @@ -117,7 +117,7 @@ void taxi_update(struct Moby *moby) { FUN_L16_002e4a58_c(moby); request_taxi_destination_help_message(moby); if ((pad_pressed_words[0] & 0x10) && *(int *)&D_L16_0015F594 == 8) { - moby->state = 3; + moby->state = TAXI_BLEND_TO_PATH_START; matched_moby = find_group_moby_by_data_id(moby, *(short *)(taxi_data + 0xAE)); if (matched_moby != 0) { matched_moby[0x20] = 2; @@ -162,14 +162,14 @@ void taxi_update(struct Moby *moby) { if (1.0f <= *(float *)(taxi_data + 0xB0)) { *(float *)(taxi_data + 0xB0) = z; *(float *)(taxi_data + 0xB4) = z; - moby->state = 4; + moby->state = TAXI_FOLLOW_PATH; } break; case TAXI_FOLLOW_PATH: if (advance_taxi_path(moby)) { *(int *)(taxi_data + 0xB0) = 0; *(int *)(taxi_data + 0xB4) = 0; - moby->state = 5; + moby->state = TAXI_BLEND_TO_DESTINATION_POSE; } break; case TAXI_BLEND_TO_DESTINATION_POSE: @@ -207,7 +207,7 @@ void taxi_update(struct Moby *moby) { if (1.0f <= *(float *)(taxi_data + 0xB0)) { *(int *)(taxi_data + 0xB0) = 0; *(int *)(taxi_data + 0xB4) = 0; - moby->state = 1; + moby->state = TAXI_WAIT_FOR_DEPARTURE; transfer_moby_placement_to_linked_moby(moby); } break; @@ -219,12 +219,12 @@ void taxi_update(struct Moby *moby) { moby->visible = 1; moby->collision = taxi_model_collision; moby->flags = flags & 0xFFFE; - moby->state = 1; + moby->state = TAXI_WAIT_FOR_DEPARTURE; } break; } apply_taxi_wobble(moby); - if (moby->state >= 3 && moby->state <= 5) { + if (moby->state >= TAXI_BLEND_TO_PATH_START && moby->state <= TAXI_BLEND_TO_DESTINATION_POSE) { travel_player = &hero; travel_player->jump_lock_timer = 2; travel_player->unk1F4 = 2; From d4f0cb99564c9b0cd352dad4d9cdc27c15fa1e61 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:09:44 +0000 Subject: [PATCH 0902/1502] decomp: clarify names in falling_rock_update domain_0_value_1 -> FALLING_ROCK_STATE_WAIT_FOR_TRIGGER: Retail 0x002f90ac-0x002f90b0 reads moby+0x20 and skips ambient debris processing when it equals 1; 0x002f91f4 reads the identical byte for the state switch. Source names case 1 FALLING_ROCK_STATE_WAIT_FOR_TRIGGER, whose 0x002f92d0-0x002f9344 branch waits for hero height, proximity and control-mode conditions. This comparison therefore reuses that local state member. domain_1_value_1 -> FALLING_ROCK_STATE_WAIT_FOR_TRIGGER: Retail initialize branch copies moby position to pvars home at 0x002f9230-0x002f9240, then stores 1 to moby+0x20 at 0x002f9248-0x002f924c. That same byte selects the switch at 0x002f91f4-0x002f9214, where source case FALLING_ROCK_STATE_WAIT_FOR_TRIGGER performs the hero proximity/height trigger checks. Reuse the existing local state member. domain_2_value_4 -> FALLING_ROCK_STATE_FALLEN: Retail 0x002f9264-0x002f929c checks persistent completion flags during initialization. On completion, 0x002f92a4-0x002f92cc clears the movement vector, stores 4 to the same moby+0x20 state selector, and restores height to home.z minus 20. This directly restores the completed state already named FALLING_ROCK_STATE_FALLEN in the source switch. domain_3_value_2 -> FALLING_ROCK_STATE_WAIT_BEFORE_FALL: After the hero trigger, retail 0x002f936c-0x002f9378 scales the configured duration and stores the phase timer at pvars+0x8a; 0x002f9380-0x002f9394 writes 2 to moby+0x20. The same state selector dispatches to source FALLING_ROCK_STATE_WAIT_BEFORE_FALL, whose retail branch 0x002f93c0-0x002f93f4 updates the camera and waits for that timer before entering falling state 3. domain_4_value_3 -> FALLING_ROCK_STATE_FALLING: Retail 0x002f93c8-0x002f93d0 waits for the pre-fall timer at pvars+0x8a, then clears the movement vector and sets the hold timer at 0x002f93d8-0x002f93e8. The store of 3 to moby+0x20 at 0x002f93ec-0x002f93f4 enters the switch state already named FALLING_ROCK_STATE_FALLING; 0x002f9438-0x002f944c accelerates downward and integrates position in that branch. domain_5_value_4 -> FALLING_ROCK_STATE_FALLEN: Retail 0x002f9450-0x002f947c requires the hold timer and a fall exceeding 20 units below home. It then clears movement and writes 4 to the moby+0x20 switch selector at 0x002f94a4-0x002f94c0, clamps height to home.z minus 20 and records completion bits through 0x002f9540. This is the existing FALLING_ROCK_STATE_FALLEN member, whose branch performs eventual camera/cutscene cleanup. --- src/overlays/l01/mobys/falling_rock.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l01/mobys/falling_rock.c b/src/overlays/l01/mobys/falling_rock.c index 81d7d32af5..f09805c249 100644 --- a/src/overlays/l01/mobys/falling_rock.c +++ b/src/overlays/l01/mobys/falling_rock.c @@ -137,7 +137,7 @@ void falling_rock_update(CapMoby *falling_rock) { LevelCuboid *camera_record; falling_rock_vars = falling_rock->pvars; - if (falling_rock->state != 1 && !fast_dec_timer_s16(&falling_rock_vars->wait) && + if (falling_rock->state != FALLING_ROCK_STATE_WAIT_FOR_TRIGGER && !fast_dec_timer_s16(&falling_rock_vars->wait) && random_integer_below(100) < 5) { CapColors colors; CapVec debris_initial_velocity; @@ -173,13 +173,13 @@ void falling_rock_update(CapMoby *falling_rock) { falling_rock_vars->b28 = 4; falling_rock_vars->h3E = 5; qcopy(&falling_rock_vars->home, &falling_rock->pos); - falling_rock->state = 1; + falling_rock->state = FALLING_ROCK_STATE_WAIT_FOR_TRIGGER; if (l01_save_state.cleared[falling_rock->id] != 0 || (D_0014C190[current_level_index_macro][falling_rock->id >> 5] >> (falling_rock->id & 0x1F)) & 1) { clear_u64_value(&falling_rock_vars->rot); - falling_rock->state = 4; + falling_rock->state = FALLING_ROCK_STATE_FALLEN; falling_rock->pos.f[2] = falling_rock_vars->home.f[2] - 20.0f; falling_rock_vars->music = -1; } @@ -193,7 +193,7 @@ void falling_rock_update(CapMoby *falling_rock) { falling_rock_vars->wait = random_int_between(scale_game_frames(300), scale_game_frames(600)); falling_rock_vars->rise = scale_game_frames(falling_rock_vars->rise_len); - falling_rock->state = 2; + falling_rock->state = FALLING_ROCK_STATE_WAIT_BEFORE_FALL; l01_camera.shake_amount = 0.4f; l01_camera.shake_frames = scale_game_frames(30); allocate_voice_for_target_entry(1, 0, falling_rock); @@ -205,7 +205,7 @@ void falling_rock_update(CapMoby *falling_rock) { if (fast_dec_timer_s16(&falling_rock_vars->rise)) { clear_u64_value(&falling_rock_vars->rot); falling_rock_vars->hold = scale_game_frames(0x2D); - falling_rock->state = 3; + falling_rock->state = FALLING_ROCK_STATE_FALLING; } break; case FALLING_ROCK_STATE_FALLING: { @@ -221,7 +221,7 @@ void falling_rock_update(CapMoby *falling_rock) { l01_camera.shake_amount = 0.1f; l01_camera.shake_frames = scale_game_frames(20); clear_u64_value(&falling_rock_vars->rot); - falling_rock->state = 4; + falling_rock->state = FALLING_ROCK_STATE_FALLEN; allocate_voice_for_target_entry(0, 0, falling_rock); falling_rock->pos.f[2] = falling_rock_vars->home.f[2] - 20.0f; D_0014C190[current_level_index_macro][falling_rock->id >> 5] |= From 3e13f4584ec6b448deed60720406a0c72fcd698a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:09:45 +0000 Subject: [PATCH 0903/1502] decomp: clarify names in update_hero_timers_and_spatial_state domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x00234ccc loads the byte at hero base 0x0013F350 + 0x20A4 (0x001413F4), then 0x00234cd0-0x00234cd4 compares it with 1. The authoritative C identifies that same byte as hero.vehicle_mode, not state.current or control_mode. The branch transforms body_center with z=0.4 and sets reach_distance=2.125 and reach_height=1.25 at 0x00234cdc-0x00234d08/0x00234d60. The supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h canonically defines HERO_VEHICLE_MODE_CLANK=1, and restore_hero_from_vehicle_mode in the same authoritative source already tests this exact vehicle_mode field with that member while preserving vehicle health and removing its attachments. This proves reuse within the exact selector domain rather than numeric equivalence to a hero state or gravity mode. --- .../shared/hero/update_hero_vehicle_attachments_and_effects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c b/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c index b1696ccde2..a619a7e629 100644 --- a/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c +++ b/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c @@ -773,7 +773,7 @@ void update_hero_timers_and_spatial_state(void) { hero.still_frames = 0; skip: update_hero_planar_distance_spring_motion(); - if (hero.vehicle_mode == 1) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { transform_hero_local_offset_to_world(&hero.motion.body_center, 0.0f, 0.0f, 0.4f); hero.reach_distance = 2.125f; hero.reach_height = 1.25f; From 88e62acbb80ef8eadb06f2eda889eb040255a43c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:09:45 +0000 Subject: [PATCH 0904/1502] decomp: clarify names in update_bolt_pickup domain_0_value_0 -> MOBY_STATE_INITIALIZE: Authoritative source compares moby->state != 0 immediately before switching on that same field with case MOBY_STATE_INITIALIZE = 0. Retail 0x002b82e0-0x002b82f4 loads byte +0x20(s2), skips base-Z restoration for zero, and feeds the same state into dispatch at 0x002b8304-0x002b8314. The zero branch calls initialize_bolt_pickup at 0x002b831c. This is the existing local moby-state domain, not a hero state or control mode. domain_1_value_1 -> MOBY_STATE_PHYSICS_MOVEMENT: In the authoritative initialization case, nonzero moby_data->f2C assigns 1 to the very moby->state field selected by the existing MOBY_STATE_PHYSICS_MOVEMENT = 1 case. Retail 0x002b8324-0x002b8334 loads +0x2c(s4), selects 1 and stores byte +0x20(s2). The corresponding source case and retail 0x002b8344-0x002b85b4 apply gravity, limit velocity, query collisions and write position, proving reuse of this local state member. domain_2_value_2 -> MOBY_STATE_CHECK_COLLECTION: The initializer's zero-f2C branch assigns 2 to moby->state, the same selector with existing local case MOBY_STATE_CHECK_COLLECTION = 2. Retail 0x002b8338-0x002b8340 loads 2 and stores byte +0x20(s2). Source collection case and retail 0x002b85b8-0x002b8734 test hero proximity, credit bolt counts and remove the pickup. Thus this assignment reuses the established local collection-state member. domain_3_value_2 -> MOBY_STATE_CHECK_COLLECTION: In the source physics case, after clearing velocity and positioning at collision-point Z plus clearance, a zero collision-record flag assigns 2 to moby->state. Retail 0x002b8580-0x002b85a0 tests the record flag, clears velocity, loads 2 and stores byte +0x20(s2). This is exactly the switch selector whose existing MOBY_STATE_CHECK_COLLECTION = 2 case performs hero proximity, bolt credit and removal at 0x002b85b8-0x002b8734, so the transition reuses that member. --- src/overlays/l08/mobys/bolt_pickup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l08/mobys/bolt_pickup.c b/src/overlays/l08/mobys/bolt_pickup.c index cff558b21b..0cba1d707f 100644 --- a/src/overlays/l08/mobys/bolt_pickup.c +++ b/src/overlays/l08/mobys/bolt_pickup.c @@ -120,15 +120,15 @@ void bolt_pickup_update(Moby_2B94B0 *moby) { int hit, ok, bob_period_ticks; moby_data->ticks++; - if (moby->state != 0) + if (moby->state != MOBY_STATE_INITIALIZE) moby->pos[2] = moby_data->f8; switch (moby->state) { case MOBY_STATE_INITIALIZE: initialize_bolt_pickup(moby); if (moby_data->f2C != 0) - moby->state = 1; + moby->state = MOBY_STATE_PHYSICS_MOVEMENT; else - moby->state = 2; + moby->state = MOBY_STATE_CHECK_COLLECTION; break; case MOBY_STATE_PHYSICS_MOVEMENT: qcopy(P, moby->pos); @@ -170,7 +170,7 @@ void bolt_pickup_update(Moby_2B94B0 *moby) { P[2] = P[2] + bolt_pickup_collision_clearance_distance_gp; if (*(int *)D_L08_001746D8_2B94B0 == 0) { clear_u64_value(moby_data->vel); - moby->state = 2; + moby->state = MOBY_STATE_CHECK_COLLECTION; } } } else { From 6fa1e70baff05d12aae60420f359903423b6acea Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:09:45 +0000 Subject: [PATCH 0905/1502] decomp: clarify names in render_environment_mapped_object domain_3_value_1 -> ENVIRONMENT_MAPPING_UV_REFRESH_PENDING: The authoritative selector is environment_mapping_uv_refresh_state, the s32 read from gp-0x675c at retail 0x00232950. Its equality to 1 at 0x00232954..0x00232958 forces entry to the mapping path despite mapping_enabled being false. The same state bypasses saved-UV blending and is acknowledged as 2 after the loop; this proves a pending direct UV refresh request. domain_4_value_1 -> ENVIRONMENT_MAPPING_UV_REFRESH_PENDING: Retail 0x00232a84..0x00232a8c reads the same gp-0x675c refresh selector and branches on 1 to 0x00232aa0. That branch writes reflection-derived sphere-map U/V directly at 0x00232aa8..0x00232af8 instead of interpolating saved UVs. Source and original Ghidra agree that this is the same pending refresh tested at mapping-path entry. domain_5_value_1 -> ENVIRONMENT_MAPPING_UV_REFRESH_PENDING: Retail 0x00232b18..0x00232b20 tests the same gp-0x675c selector for 1 after the UV loop; when equal, 0x00232b28..0x00232b30 writes 2. Authoritative C and original Ghidra show the identical pending state used to force direct refresh, so this acknowledgment comparison reuses ENVIRONMENT_MAPPING_UV_REFRESH_PENDING. domain_6_value_2 -> ENVIRONMENT_MAPPING_UV_REFRESH_CONSUMED: Retail 0x00232b18..0x00232b30 tests gp-0x675c for pending value 1, loads 2 and stores it back after the refresh loop. Authoritative C and original Ghidra corroborate the 1-to-2 acknowledgment. ENVIRONMENT_MAPPING_UV_REFRESH_CONSUMED names that request consumption only; the loop may be skipped for a nonpositive vertex count, so no completed-render claim is made. --- .../mobys/render_environment_mapped_object.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/rendering/mobys/render_environment_mapped_object.c b/src/rendering/mobys/render_environment_mapped_object.c index 5c17c1f04d..2943343fca 100644 --- a/src/rendering/mobys/render_environment_mapped_object.c +++ b/src/rendering/mobys/render_environment_mapped_object.c @@ -48,6 +48,10 @@ build_moby_bone_transform(EnvironmentMappedObject *, int, void *) __asm__("func_ void render_environment_mapped_object(EnvironmentMappedObject *object) __asm__("FUN_002327a0"); void render_environment_mapped_object(EnvironmentMappedObject *mesh_object) { + enum { + ENVIRONMENT_MAPPING_UV_REFRESH_PENDING = 1, + ENVIRONMENT_MAPPING_UV_REFRESH_CONSUMED = 2 + }; Vec4 quad_positions[4]; int colors[4]; float texture_coordinates[4][2]; @@ -99,7 +103,7 @@ void render_environment_mapped_object(EnvironmentMappedObject *mesh_object) { if (game_mode == 6 && ship_substate[0] == 4) { mapping_enabled = 0; } - if (mapping_enabled != 0 || environment_mapping_uv_refresh_state == 1) { + if (mapping_enabled != 0 || environment_mapping_uv_refresh_state == ENVIRONMENT_MAPPING_UV_REFRESH_PENDING) { environment_mapping_was_active_gp = 1; fast_dec_timer(&D_001604AC); transition_fraction = convert_integer_to_float(D_001604AC) / @@ -119,7 +123,7 @@ void render_environment_mapped_object(EnvironmentMappedObject *mesh_object) { fast_vec_normalize(reflection, reflection, 1.0f); reflection[2] += 1.0f; sphere_denominator = square_root(reflection[2] * 2.0f) * 2.0f; - if (environment_mapping_uv_refresh_state == 1 || D_001604AC == 0) { + if (environment_mapping_uv_refresh_state == ENVIRONMENT_MAPPING_UV_REFRESH_PENDING || D_001604AC == 0) { environment_mapping_vertex_uvs[element_index][0] = reflection[0] / sphere_denominator + 0.5f; environment_mapping_vertex_uvs[element_index][1] = @@ -137,8 +141,8 @@ void render_environment_mapped_object(EnvironmentMappedObject *mesh_object) { transition_fraction; } } - if (environment_mapping_uv_refresh_state == 1) { - environment_mapping_uv_refresh_state = 2; + if (environment_mapping_uv_refresh_state == ENVIRONMENT_MAPPING_UV_REFRESH_PENDING) { + environment_mapping_uv_refresh_state = ENVIRONMENT_MAPPING_UV_REFRESH_CONSUMED; } } else { if (environment_mapping_was_active_gp == 1) { From 6ccf51b532c25c0bbe7c632e8c80ceccd9802d15 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:11:35 +0000 Subject: [PATCH 0906/1502] decomp: clarify names in update_gemlik_scene_controller domain_0_value_1 -> START_INITIAL_SCENE: 0030b680-0030b688 stores 1 to controller +0x20 after the scene gate becomes zero; the same byte is the switch selector at 0030b644. Existing case START_INITIAL_SCENE checks its flag and starts scene 0. domain_10_value_7 -> WAIT_LINKED_MOBY_REMOVAL_BEFORE_SCENE: 0030b854-0030b85c stores 7 to controller +0x20 from ENTER_LINKED_MOBY_REMOVAL_WAIT. Existing WAIT_LINKED_MOBY_REMOVAL_BEFORE_SCENE checks pvars[5] class/state at 0030b878-0030b8b8. domain_11_value_13 -> WAIT_TO_REMOVE_LINKED_MOBY: 0030b878-0030b880 branches on absent pvars[5] to 0030bad0-0030bad8, storing 13 to controller +0x20. Existing WAIT_TO_REMOVE_LINKED_MOBY checks the linked table byte and requests removal at 0030badc-0030bb38. domain_12_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: 0030b878-0030b88c resolves pvars[5] via moby_base and 0x100 stride; 0030b8a8-0030b8b0 loads that moby's +0x20 state unsigned and tests 0xfe. Supplied mark_moby_for_removal assigns 0xFE to this exact Moby state field for mobys at or above moby_instance_end. domain_13_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: 0030b8a8-0030b8b8 tests the unsigned +0x20 state of pvars[5]'s linked Moby against 0xfd before waiting. Supplied mark_moby_for_removal assigns 0xFD to this exact Moby state field for mobys below moby_instance_end; this is distinct from controller phase IDs. domain_14_value_8 -> WAIT_SCENE_BEFORE_FOLLOWUP: 0030b940-0030b94c writes 8 to controller +0x20 while calling start_scene(2). Existing WAIT_SCENE_BEFORE_FOLLOWUP holds this selector until the scene gate permits the movie/followup sequence at 0030b958-0030b974. domain_15_value_12 -> ENTER_LINKED_MOBY_CLEANUP_WAIT: 0030b86c-0030b874 branches on the recorded scene flag to 0030bac8-0030bacc, writing 12 to controller +0x20. Existing ENTER_LINKED_MOBY_CLEANUP_WAIT advances that same selector to removal-wait case 13. domain_16_value_9 -> START_FOLLOWUP_SCENE: 0030b958-0030b974 stores 9 into controller +0x20 when the scene gate clears and queues movie 14. Existing START_FOLLOWUP_SCENE uses that same switch byte and calls start_scene(3) at 0030b994. domain_17_value_10 -> WAIT_FOLLOWUP_SCENE: 0030b994-0030b9a4 calls start_scene(3) and writes 10 to controller +0x20. Existing WAIT_FOLLOWUP_SCENE reads the scene gate at 0030b9a8-0030b9b4 before cleanup and planet unlock. domain_18_value_11 -> WAIT_LINKED_MOBY_REMOVAL_BEFORE_SAVE: 0030ba5c-0030ba64 writes 11 into controller +0x20 after followup cleanup. Existing WAIT_LINKED_MOBY_REMOVAL_BEFORE_SAVE resolves pvars[4], waits on its removal states, and requests memcard_save_data at 0030ba68-0030bac0. domain_19_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: 0030ba68-0030ba7c resolves pvars[4] via moby_base and 0x100 stride; 0030ba94-0030ba9c loads that Moby's state at +0x20 unsigned and compares 0xfe. Supplied mark_moby_for_removal writes 0xFE to the same field for mobys at or above moby_instance_end. domain_1_value_2 -> WAIT_INITIAL_SCENE: 0030b6a4-0030b6b4 stores 2 to controller +0x20 while calling start_scene(0); existing WAIT_INITIAL_SCENE reads the scene gate at 0030b6c0-0030b6cc before progressing. domain_20_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: 0030ba94-0030baa4 compares the unsigned state at linked pvars[4] Moby +0x20 with 0xfd before allowing the save. Supplied mark_moby_for_removal writes 0xFD to that exact field for mobys below moby_instance_end, proving the removal-state domain. domain_21_value_12 -> ENTER_LINKED_MOBY_CLEANUP_WAIT: 0030bab0-0030bac0 requests memcard_save_data(0,-1) and writes 12 to controller +0x20. Existing ENTER_LINKED_MOBY_CLEANUP_WAIT dispatches from that byte and advances to linked-removal wait case 13. domain_22_value_12 -> ENTER_LINKED_MOBY_CLEANUP_WAIT: 0030ba70 branches on absent pvars[4] to 0030bac4-0030bacc, writing 12 to controller +0x20 without saving. This is the same selector used by existing ENTER_LINKED_MOBY_CLEANUP_WAIT, which advances to 13. domain_23_value_13 -> WAIT_TO_REMOVE_LINKED_MOBY: 0030bad0-0030bad8 writes 13 to controller +0x20 from ENTER_LINKED_MOBY_CLEANUP_WAIT. Existing WAIT_TO_REMOVE_LINKED_MOBY checks pvars[4]'s table entry at 0030badc-0030bb0c before removing the pvars[8] moby. domain_24_value_14 -> FINALIZE_LINKED_MOBY_CLEANUP: 0030bb14-0030bb30 conditionally marks pvars[8]'s linked moby for removal and writes 14 to controller +0x20. Existing FINALIZE_LINKED_MOBY_CLEANUP dispatches on that byte and ORs 2 into controller flags at 0030bb44-0030bb4c. domain_2_value_3 -> ENTER_CLIP_VOLUME_CHECK: 0030b698 branches to 0030b6d4-0030b6d8 to store 3 in controller +0x20 when the initial scene flag is already recorded. This is the same selector as existing ENTER_CLIP_VOLUME_CHECK, which advances to clip checking. domain_3_value_3 -> ENTER_CLIP_VOLUME_CHECK: 0030b6c0-0030b6d8 leaves WAIT_INITIAL_SCENE when the scene gate differs from 2 and stores 3 to the controller switch byte; existing ENTER_CLIP_VOLUME_CHECK then enters CHECK_CLIP_VOLUME_FOR_SCENE. domain_4_value_4 -> CHECK_CLIP_VOLUME_FOR_SCENE: 0030b6dc-0030b6e4 stores 4 in controller +0x20. Existing case CHECK_CLIP_VOLUME_FOR_SCENE uses this same selector and passes pvars[0] to the hero-position clip-volume test at 0030b6fc-0030b710. domain_5_value_5 -> WAIT_CLIP_VOLUME_SCENE: 0030b740-0030b74c stores 5 to controller +0x20 while starting scene 1 after the clip test succeeds; existing WAIT_CLIP_VOLUME_SCENE gates its linked-moby setup on scene completion at 0030b790-0030b79c. domain_6_value_6 -> ENTER_LINKED_MOBY_REMOVAL_WAIT: 0030b6f4-0030b6f8 selects 6 when the clip-scene flag is already recorded, and 0030b75c writes it to controller +0x20. Existing ENTER_LINKED_MOBY_REMOVAL_WAIT advances to removal-wait case 7. domain_7_value_7 -> WAIT_LINKED_MOBY_REMOVAL_BEFORE_SCENE: 0030b704 branches on absent pvars[0] to 0030b758-0030b75c, storing 7 into controller +0x20. Existing WAIT_LINKED_MOBY_REMOVAL_BEFORE_SCENE checks the pvars[5] moby's removal state before starting scene 2. domain_8_value_4 -> CHECK_CLIP_VOLUME_FOR_SCENE: 0030b754-0030b768 reloads controller +0x20 and compares it with 4 before removing pvars[3]'s moby. It tests whether the same controller selector still equals existing CHECK_CLIP_VOLUME_FOR_SCENE. domain_9_value_6 -> ENTER_LINKED_MOBY_REMOVAL_WAIT: 0030b848-0030b850 stores 6 to controller +0x20 after WAIT_CLIP_VOLUME_SCENE finishes or skips linked setup. The same switch byte dispatches existing ENTER_LINKED_MOBY_REMOVAL_WAIT, which advances to case 7. --- .../l13/mobys/gemlik_scene_controller.c | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/overlays/l13/mobys/gemlik_scene_controller.c b/src/overlays/l13/mobys/gemlik_scene_controller.c index 2e9f51ed05..7a97c1ace7 100644 --- a/src/overlays/l13/mobys/gemlik_scene_controller.c +++ b/src/overlays/l13/mobys/gemlik_scene_controller.c @@ -59,27 +59,31 @@ void gemlik_scene_controller_update(struct Moby *moby) { WAIT_TO_REMOVE_LINKED_MOBY = 13, FINALIZE_LINKED_MOBY_CLEANUP = 14 }; + enum { + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xfd, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xfe + }; int *scene_controller_vars = (int *)moby->pvars; switch (moby->state) { case WAIT_TO_START_INITIAL_SCENE: if (D_L13_0015F5C4 == 0) - moby->state = 1; + moby->state = START_INITIAL_SCENE; break; case START_INITIAL_SCENE: if (alternate_item_available[0x64] == 0) { alternate_item_available[0x64] = 1; - moby->state = 2; + moby->state = WAIT_INITIAL_SCENE; start_scene(0); return; } - moby->state = 3; + moby->state = ENTER_CLIP_VOLUME_CHECK; break; case WAIT_INITIAL_SCENE: if (D_L13_0015F5C4 != 2) - moby->state = 3; + moby->state = ENTER_CLIP_VOLUME_CHECK; break; case ENTER_CLIP_VOLUME_CHECK: - moby->state = 4; + moby->state = CHECK_CLIP_VOLUME_FOR_SCENE; break; case CHECK_CLIP_VOLUME_FOR_SCENE: { if (alternate_item_available[0x65] == 0) { @@ -92,16 +96,16 @@ void gemlik_scene_controller_update(struct Moby *moby) { struct Moby *other = (struct Moby *)(moby_base + scene_controller_vars[5] * 0x100); other->flags |= 0x41; } - moby->state = 5; + moby->state = WAIT_CLIP_VOLUME_SCENE; start_scene(1); } else { - moby->state = 6; + moby->state = ENTER_LINKED_MOBY_REMOVAL_WAIT; goto after_state_4; set_state_4: - moby->state = 7; + moby->state = WAIT_LINKED_MOBY_REMOVAL_BEFORE_SCENE; } after_state_4: - if (moby->state != 4 && scene_controller_vars[3] != -1) { + if (moby->state != CHECK_CLIP_VOLUME_FOR_SCENE && scene_controller_vars[3] != -1) { mark_moby_for_removal((char *)(moby_base + scene_controller_vars[3] * 0x100)); } break; @@ -128,24 +132,24 @@ void gemlik_scene_controller_update(struct Moby *moby) { D_L13_0015F3FC = 0.99f; entity[0x20] = 2; } - moby->state = 6; + moby->state = ENTER_LINKED_MOBY_REMOVAL_WAIT; } break; } case ENTER_LINKED_MOBY_REMOVAL_WAIT: - moby->state = 7; + moby->state = WAIT_LINKED_MOBY_REMOVAL_BEFORE_SCENE; break; case WAIT_LINKED_MOBY_REMOVAL_BEFORE_SCENE: { char *object; if (alternate_item_available[0x66] == 0) { struct Moby *other; if (scene_controller_vars[5] == -1) { - moby->state = 13; + moby->state = WAIT_TO_REMOVE_LINKED_MOBY; break; } other = (struct Moby *)(moby_base + scene_controller_vars[5] * 0x100); - if (other != 0 && other->oclass == 0x184 && other->state != 0xfe && - other->state != 0xfd) + if (other != 0 && other->oclass == 0x184 && other->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + other->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) return; if (scene_controller_vars[4] != -1) { struct Moby *other = (struct Moby *)(moby_base + scene_controller_vars[4] * 0x100); @@ -159,23 +163,23 @@ void gemlik_scene_controller_update(struct Moby *moby) { other->flags |= 0x41; } request_music_track(0, 5); - moby->state = 8; + moby->state = WAIT_SCENE_BEFORE_FOLLOWUP; start_scene(2); return; } - moby->state = 12; + moby->state = ENTER_LINKED_MOBY_CLEANUP_WAIT; break; } case WAIT_SCENE_BEFORE_FOLLOWUP: if (D_L13_0015F5C4 != 2) { - moby->state = 9; + moby->state = START_FOLLOWUP_SCENE; queue_scene_movie_with_game_language(14); } break; case START_FOLLOWUP_SCENE: if (D_L13_0015F5C4 != 2) { start_scene(3); - moby->state = 10; + moby->state = WAIT_FOLLOWUP_SCENE; } break; case WAIT_FOLLOWUP_SCENE: { @@ -195,24 +199,24 @@ void gemlik_scene_controller_update(struct Moby *moby) { D_0013E030.unk78 = 2.77f; } D_L13_0015F404 = 0; - moby->state = 11; + moby->state = WAIT_LINKED_MOBY_REMOVAL_BEFORE_SAVE; } break; } case WAIT_LINKED_MOBY_REMOVAL_BEFORE_SAVE: { if (scene_controller_vars[4] != -1) { struct Moby *other = (struct Moby *)(moby_base + scene_controller_vars[4] * 0x100); - if (other != 0 && other->oclass == 0x45 && other->state != 0xfe && other->state != 0xfd) + if (other != 0 && other->oclass == 0x45 && other->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && other->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) return; memcard_save_data(0, -1); - moby->state = 12; + moby->state = ENTER_LINKED_MOBY_CLEANUP_WAIT; return; } - moby->state = 12; + moby->state = ENTER_LINKED_MOBY_CLEANUP_WAIT; break; } case ENTER_LINKED_MOBY_CLEANUP_WAIT: - moby->state = 13; + moby->state = WAIT_TO_REMOVE_LINKED_MOBY; break; case WAIT_TO_REMOVE_LINKED_MOBY: if (scene_controller_vars[4] != -1) { @@ -220,7 +224,7 @@ void gemlik_scene_controller_update(struct Moby *moby) { 0xb0)] == 0xff) { if (scene_controller_vars[8] != -1) mark_moby_for_removal((char *)(moby_base + scene_controller_vars[8] * 0x100)); - moby->state = 14; + moby->state = FINALIZE_LINKED_MOBY_CLEANUP; } } else { mark_moby_for_removal(moby); From 8a12341189d98f56b00be2b34e705bfb673159bd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:13:18 +0000 Subject: [PATCH 0907/1502] decomp: clarify names in update_linked_moby_group_transform_and_fall domain_0_value_1 -> FALLING_MOBY_GROUP_AWAIT_ACTIVATION: Retail 0x002f1844-0x002f184c writes 1 to this moby's state byte at +0x20 after saving transforms and capturing linked members. The authoritative same-file activate_drek_boss_class_0565_moby tests this class-0x565 state against FALLING_MOBY_GROUP_AWAIT_ACTIVATION=1 before assigning MOBY_APPROACH_TARGET_TRANSFORM=2; reset_drek_boss_falling_moby_group also restores that named state. Thus this initialization assignment enters the same controller waiting-state domain, not a hero state. domain_1_value_4 -> MOBY_FALL_AND_REMOVE: Retail 0x002f18ec-0x002f190c compares transform progress pvars+0x330 with the fall threshold and, when pvars+8 is nonzero, writes 4 to moby+0x20. This is the exact state byte dispatched at 0x002f1754-0x002f1784 into the existing MOBY_FALL_AND_REMOVE=4 case at 0x002f19e8, which lowers vertical motion and removes the linked group and controller below z=20. domain_2_value_4 -> MOBY_FALL_AND_REMOVE: Retail 0x002f19b0-0x002f19e4 requires the recorded hero-support latch, absence of current group/class-0x764 support, zero air frames and an expired pvars+0x34c timer, then writes 4 to moby+0x20. That same byte selects the existing MOBY_FALL_AND_REMOVE=4 branch at 0x002f1780/0x002f19e8; its downward acceleration and removal calls at 0x002f1a54-0x002f1a70 prove reuse of the local member. domain_3_value_4 -> MOBY_FALL_AND_REMOVE: Retail 0x002f1b14-0x002f1b1c reloads this controller's state from moby+0x20 and skips randomized debris generation when it equals 4. It is the identical selector dispatched into the source's existing MOBY_FALL_AND_REMOVE=4 case, whose retail branch 0x002f19e8-0x002f1a70 applies falling motion and removes the linked members and controller. The source comparison moby->state != 4 therefore reuses that local state member. --- src/overlays/l18/mobys/falling_moby_group.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/overlays/l18/mobys/falling_moby_group.c b/src/overlays/l18/mobys/falling_moby_group.c index 3087292269..2f83a342e5 100644 --- a/src/overlays/l18/mobys/falling_moby_group.c +++ b/src/overlays/l18/mobys/falling_moby_group.c @@ -99,6 +99,9 @@ void falling_moby_group_update(struct Moby *moby) { MOBY_APPROACH_TARGET_TRANSFORM = 2, MOBY_FALL_AND_REMOVE = 4 }; + enum { + FALLING_MOBY_GROUP_AWAIT_ACTIVATION = 1 + }; VData *moby_vars = (VData *)moby->pvars; if (moby_vars) { float initial_acceleration_step = group_transform_initial_acceleration_gp * frame_time_sq; @@ -132,7 +135,7 @@ void falling_moby_group_update(struct Moby *moby) { moby_vars->f34C = scale_game_frames(30); moby_vars->cnt = j; capture_linked_moby_relative_transforms(moby, (char *)moby_vars + 0x30, j); - moby->state = 1; + moby->state = FALLING_MOBY_GROUP_AWAIT_ACTIVATION; break; } case MOBY_APPROACH_TARGET_TRANSFORM: { @@ -162,7 +165,7 @@ void falling_moby_group_update(struct Moby *moby) { } if (moby_vars->f330 > group_transform_fall_progress_threshold_gp && moby_vars->i8 != 0) { - moby->state = 4; + moby->state = MOBY_FALL_AND_REMOVE; } hero_on_group_or_class_764_moby = 0; for (i = 0; i < moby_vars->cnt; i++) { @@ -182,7 +185,7 @@ void falling_moby_group_update(struct Moby *moby) { if (moby_vars->f348 != 0 && hero_on_group_or_class_764_moby == 0 && hero.air_frames.s == 0) { if (fast_dec_timer(&moby_vars->f34C)) - moby->state = 4; + moby->state = MOBY_FALL_AND_REMOVE; } break; } @@ -213,7 +216,7 @@ void falling_moby_group_update(struct Moby *moby) { } apply_linked_moby_relative_transforms(moby, (char *)moby_vars + 0x30, moby_vars->cnt); if (moby_vars->f344 != 0.0f) { - if (moby->state != 4) { + if (moby->state != MOBY_FALL_AND_REMOVE) { float debris_spawn_position[4]; float s, z, debris_spawn_angle; int debris_spawn_frames; From dab0970ff8bfbd7f20d235378813be28df0f024b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:13:18 +0000 Subject: [PATCH 0908/1502] decomp: clarify names in draw_three_sky_shells_with_three_particle_types domain_0_value_0 -> THREE_SHELL_PARTICLE_PHASE_ORBIT: Authoritative C and original retail agree: initialization stores type 0 at 0x00289d70 and random phase halfwords at particle+0xC/+0xE (0x00289d74-0x00289d98). The update reads the same parts array and byte-0 type (0x00289f80-0x00289f94), increments both phases (0x00289f9c-0x00289fb4), converts them to radians and computes spherical radius-50 coordinates through 0x0028a044. Thus assignment and comparison denote the same phase-orbit particle kind. domain_1_value_2 -> THREE_SHELL_PARTICLE_COLOR_HIGH_BYTE_PULSE: Authoritative C and original retail agree: type 2 is stored at byte 0 at 0x00289df8, with a base-color table index at +0xC and staggered counters at +0xE (0x00289e20-0x00289e38). The same parts array byte-0 selector is compared with 2 at 0x0028a068. Its branch advances the counter modulo 48, folds counter*4 around 96 using 192-counter*4, shifts this triangular offset by 24, adds randomized channel offsets to the saved-index base color and writes particle+4 (0x0028a07c-0x0028a130). This proves a color high-byte pulse kind without assuming alpha semantics. domain_2_value_3 -> THREE_SHELL_PARTICLE_RANDOM_COLOR: Authoritative C and original retail agree: type 3 is stored at particle byte 0 at 0x00289e44; initialization constructs a packed baseline color and saves it at +0xC (0x00289ee8-0x00289f34). The update loads the same parts array byte-0 selector and compares it with 3 at 0x0028a134. It reads the saved packed baseline at +0xC, adds separately masked random channel offsets, and writes the current color at +4 (0x0028a13c-0x0028a17c). This proves the randomized-color kind. domain_3_value_0 -> THREE_SHELL_PARTICLE_PHASE_ORBIT: Authoritative C and original retail agree: initialization stores type 0 at 0x00289d70 and random phase halfwords at particle+0xC/+0xE (0x00289d74-0x00289d98). The update reads the same parts array and byte-0 type (0x00289f80-0x00289f94), increments both phases (0x00289f9c-0x00289fb4), converts them to radians and computes spherical radius-50 coordinates through 0x0028a044. Thus assignment and comparison denote the same phase-orbit particle kind. domain_4_value_2 -> THREE_SHELL_PARTICLE_COLOR_HIGH_BYTE_PULSE: Authoritative C and original retail agree: type 2 is stored at byte 0 at 0x00289df8, with a base-color table index at +0xC and staggered counters at +0xE (0x00289e20-0x00289e38). The same parts array byte-0 selector is compared with 2 at 0x0028a068. Its branch advances the counter modulo 48, folds counter*4 around 96 using 192-counter*4, shifts this triangular offset by 24, adds randomized channel offsets to the saved-index base color and writes particle+4 (0x0028a07c-0x0028a130). This proves a color high-byte pulse kind without assuming alpha semantics. domain_5_value_3 -> THREE_SHELL_PARTICLE_RANDOM_COLOR: Authoritative C and original retail agree: type 3 is stored at particle byte 0 at 0x00289e44; initialization constructs a packed baseline color and saves it at +0xC (0x00289ee8-0x00289f34). The update loads the same parts array byte-0 selector and compares it with 3 at 0x0028a134. It reads the saved packed baseline at +0xC, adds separately masked random channel offsets, and writes the current color at +4 (0x0028a13c-0x0028a17c). This proves the randomized-color kind. --- .../shared/rendering/sky/sky_particle_effects.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/rendering/sky/sky_particle_effects.c b/src/overlays/shared/rendering/sky/sky_particle_effects.c index 24a4ac1b15..8308aed23c 100644 --- a/src/overlays/shared/rendering/sky/sky_particle_effects.c +++ b/src/overlays/shared/rendering/sky/sky_particle_effects.c @@ -321,6 +321,11 @@ extern u8 D_L00_001BD7B0[] NOT_SDA; void draw_three_sky_shells_with_three_particle_types(void) __asm__("FUN_L00_00289cb8"); void draw_three_sky_shells_with_three_particle_types(void) { + enum { + THREE_SHELL_PARTICLE_PHASE_ORBIT = 0, + THREE_SHELL_PARTICLE_COLOR_HIGH_BYTE_PULSE = 2, + THREE_SHELL_PARTICLE_RANDOM_COLOR = 3 + }; Part *init_particle; Part *update_particle; PU *update_state; @@ -344,7 +349,7 @@ void draw_three_sky_shells_with_three_particle_types(void) { for (i = 0; i < D_L00_0016051C_c3->count; i++) { init_particle = &D_L00_0016051C_c3->parts[i]; if (i >= 0xF0) { - init_particle->type = 0; + init_particle->type = THREE_SHELL_PARTICLE_PHASE_ORBIT; init_phases = &init_particle->u; init_phases->h.h0 = rand() >> 16; init_phases->h.h2 = rand() >> 16; @@ -359,7 +364,7 @@ void draw_three_sky_shells_with_three_particle_types(void) { init_particle->b3 = 0x48; j = r & 1; init_particle->f8 = random_angle_radians(); - init_particle->type = 2; + init_particle->type = THREE_SHELL_PARTICLE_COLOR_HIGH_BYTE_PULSE; init_particle->col = sky_type2_base_colors[k]; qcopy(&init_particle->f10, D_L00_001BD7B0 + k * 16); init_particle->u.c.c0 = k; @@ -369,7 +374,7 @@ void draw_three_sky_shells_with_three_particle_types(void) { qq->c.c2 = j * 0x18; } } else { - init_particle->type = 3; + init_particle->type = THREE_SHELL_PARTICLE_RANDOM_COLOR; init_particle->u.h.h0 = random_integer_below(0x100); init_particle->b2 = (rand() >> 16) & 1; init_particle->b3 = 0x48; @@ -401,7 +406,7 @@ void draw_three_sky_shells_with_three_particle_types(void) { } for (i2 = 0; i2 < D_L00_0016051C_c3->count; i2++) { update_particle = &D_L00_0016051C_c3->parts[i2]; - if (update_particle->type == 0) { + if (update_particle->type == THREE_SHELL_PARTICLE_PHASE_ORBIT) { update_state = &update_particle->u; update_particle->u.h.h0++; update_state->h.h2++; @@ -420,7 +425,7 @@ void draw_three_sky_shells_with_three_particle_types(void) { } else { update_particle->col |= 0x24000000; } - } else if (update_particle->type == 2) { + } else if (update_particle->type == THREE_SHELL_PARTICLE_COLOR_HIGH_BYTE_PULSE) { update_state = &update_particle->u; update_state->c.c2 = (update_state->c.c2 + 1) % 0x30; if (update_state->c.c2 == 0) { @@ -441,7 +446,7 @@ void draw_three_sky_shells_with_three_particle_types(void) { x += k2 << 24; update_particle->col = x; } - } else if (update_particle->type == 3) { + } else if (update_particle->type == THREE_SHELL_PARTICLE_RANDOM_COLOR) { s32 rs = rand() >> 16; u32 x; { From e1f8adb0deb5c60f91a9bb07678fbe5a7b2d51f5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:13:18 +0000 Subject: [PATCH 0909/1502] decomp: clarify names in the_plumber_batalia_update domain_0_value_1 -> PLUMBER_UPDATE_DIALOGUE: Source assigns 1 to moby->state immediately before initialize_npc_dialogue. Retail 00306610 loads state from 0x20(s2), 00306618 dispatches 1 to dialogue update at 003066a4, and 00306698 stores a2=1 to that same byte. Original Ghidra confirms the assignment and update branch; reuse the existing local PLUMBER_UPDATE_DIALOGUE=1 member of this exact selector domain. domain_1_value_2 -> PLUMBER_SCRIPTED_HANDOFF: Source assigns 2 to moby->state after jet_reset_camera and before request_batalia_cannon_mount. Retail 003066cc-003066f8 tests dialogue data+0x36==2 and resets the indexed camera; 003066fc stores s0=2 to 0x20(s2), the state byte loaded at 00306610. 00306710 calls cannon mount; 00306638 dispatches state 2 to shared animation. Original Ghidra agrees. Reuse existing local PLUMBER_SCRIPTED_HANDOFF=2, not a hero state or dialogue-control enum. domain_2_value_5 -> PLUMBER_SAVE_AND_REMOVE: Source writes 5 to moby->state on dialogue sub==3. Retail 0030671c-00306734 tests data+4==3 then stores 5 to 0x20(s2); 00306610/00306640 read and dispatch that same state byte to 0030675c. This branch clears persistence, grants inventory, saves with (0,-1), and marks the moby for removal at 0030677c. Original Ghidra agrees. Reuse existing local PLUMBER_SAVE_AND_REMOVE=5 in this exact domain. --- src/overlays/l08/mobys/the_plumber_batalia.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l08/mobys/the_plumber_batalia.c b/src/overlays/l08/mobys/the_plumber_batalia.c index 84851e2293..ae73b83423 100644 --- a/src/overlays/l08/mobys/the_plumber_batalia.c +++ b/src/overlays/l08/mobys/the_plumber_batalia.c @@ -183,7 +183,7 @@ void the_plumber_batalia_update(L14WatchMoby *moby) { return; } watch_data->p20 = (void *)batalia_plumber_name_text; - moby->state = 1; + moby->state = PLUMBER_UPDATE_DIALOGUE; initialize_npc_dialogue(moby, watch_data); break; case PLUMBER_UPDATE_DIALOGUE: @@ -192,12 +192,12 @@ void the_plumber_batalia_update(L14WatchMoby *moby) { if (watch_data->h36 == 2) { char *camera_record = D_L08_001600EC + watch_data->i48 * 128; jet_reset_camera(camera_record + 0x30, camera_record + 0x70); - moby->state = 2; + moby->state = PLUMBER_SCRIPTED_HANDOFF; request_batalia_cannon_mount(D_L08_0015FFD8 + watch_data->i50 * 256); } if (watch_data->sub == 3) { FUN_L08_002a1880(1); - moby->state = 5; + moby->state = PLUMBER_SAVE_AND_REMOVE; } if (watch_data->sub == 4) { hero_respawn(); From 65da77f894049bd94d8a9abdcfc802658194a94c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:13:18 +0000 Subject: [PATCH 0910/1502] decomp: clarify names in update_hero_timers_and_auxiliary_state domain_1_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x002160E8-0x00216100 loads the byte at hero base 0x0013F350 + 0x20A4, compares it with 2, and decrements hero+0x1636 only on equality. The authoritative C identifies that same byte as hero.vehicle_mode and the timer as vehicle_triangle_cooldown. Supplied enter_hero_vehicle_mode context writes its mode parameter into this field and switches that parameter using HeroVehicleMode members, including HERO_VEHICLE_MODE_GIANT_CLANK. The supplied shared include/rnc/hero/hero_state.h enum HeroVehicleMode canonically defines that member as 2, proving domain membership rather than numeric equivalence to a hero state. domain_2_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x0021626C-0x002162A4 again loads hero+0x20A4, compares with 2, and selects a transformed local body-center height of 4.0 and reach distance/height 15.0/3.0. Authoritative C binds this load to hero.vehicle_mode, the exact field written from mode in supplied enter_hero_vehicle_mode context whose switch uses HeroVehicleMode members. The supplied shared header canonically assigns HERO_VEHICLE_MODE_GIANT_CLANK = 2 in HeroVehicleMode; source update_hero_smoothing_parameters also switches this same field using that member for the enlarged capsule. Reuse the shared vehicle member for this comparison, independently of state/control IDs. --- .../shared/hero/update_hero_and_vehicle_mode_effects.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/update_hero_and_vehicle_mode_effects.c b/src/overlays/shared/hero/update_hero_and_vehicle_mode_effects.c index 12d8c89185..f19a3f8e1f 100644 --- a/src/overlays/shared/hero/update_hero_and_vehicle_mode_effects.c +++ b/src/overlays/shared/hero/update_hero_and_vehicle_mode_effects.c @@ -535,7 +535,7 @@ void update_hero_timers_and_auxiliary_state(void) { } } } - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { fast_dec_timer_s16(&hero.vehicle_triangle_cooldown); } for (i = 0; i < 5; i++) { @@ -567,7 +567,7 @@ void update_hero_timers_and_auxiliary_state(void) { hero.still_frames = 0; skip: update_hero_planar_distance_spring_motion(); - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { transform_hero_local_offset_to_world(&hero.motion.body_center, 0.0f, 0.0f, 4.0f); hero.reach_distance = 15.0f; hero.reach_height = 3.0f; From e443b1c2a54d2e2653aa6179962e311d456e16cf Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:13:18 +0000 Subject: [PATCH 0911/1502] decomp: clarify names in asteroid_update domain_0_value_2 -> ASTEROID_MODE_FADING_DEBRIS: Retail 0x002eb9a8 loads asteroid pvars into s8; 0x002eb9ac reads its +0x4C mode. The comparison against 2 at 0x002eb974/0x002eb9b0 dispatches to 0x002ead30 at 0x002eb9b8 and returns. The checked source binds that callee to update_fading_asteroid_debris, whose operations decay drift velocity, decrement alpha and remove faded debris. In the authoritative source, spawn_fading_asteroid_debris writes 2 to spawned_moby_vars+0x4C. This proves a fading-debris behavior mode, separate from Moby state. domain_1_value_1 -> ASTEROID_MODE_FALLING: Retail 0x002eb9ac reads the private-data +0x4C selector; the li 1 at 0x002eb9b4 and comparison at 0x002eb9c8 dispatch to 0x002eaea8 at 0x002eb9d0 with the asteroid in a0, then return. The source binds this callee to update_falling_asteroid, which moves toward a target and handles impact. spawn_falling_asteroid writes 1 to moby_vars+0x4C in the authoritative snapshot. Thus 1 is the falling asteroid behavior mode, not boolean TRUE or the separate Moby state. --- src/overlays/l09/mobys/asteroid.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l09/mobys/asteroid.c b/src/overlays/l09/mobys/asteroid.c index 7f5607d56c..cfc9ccf4ce 100644 --- a/src/overlays/l09/mobys/asteroid.c +++ b/src/overlays/l09/mobys/asteroid.c @@ -581,6 +581,10 @@ void update_falling_asteroid(Moby *falling_rock) { /* Moby classes 263-267 */ void asteroid_update(struct Moby *asteroid_moby) { + enum { + ASTEROID_MODE_FALLING = 1, + ASTEROID_MODE_FADING_DEBRIS = 2 + }; Data_2ECC50 *moby_vars = (*(Data_2ECC50 **)&asteroid_moby->pvars); Path *path; float displacement_vector[4]; @@ -589,11 +593,11 @@ void asteroid_update(struct Moby *asteroid_moby) { float dot; int i; - if (moby_vars->mode == 2) { + if (moby_vars->mode == ASTEROID_MODE_FADING_DEBRIS) { update_fading_asteroid_debris((unsigned char *)asteroid_moby); return; } - if (moby_vars->mode == 1) { + if (moby_vars->mode == ASTEROID_MODE_FALLING) { update_falling_asteroid((void *)asteroid_moby); return; } From 833e39c0597faac9b4c620129a2df4f93053efb8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:13:18 +0000 Subject: [PATCH 0912/1502] decomp: clarify names in update_level_13_mine domain_0_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 002c209c loads moby data from +0x78; 002c22b0 loads its stored moby pointer at +0x74 into a1; 002c22bc reads that moby's state byte at +0x20. The 0xFE comparison at 002c22b8-002c22c0 branches to 002c256c, bypassing collision processing. Authoritative C identifies the selector as target->state. Supplied mark_moby_for_removal assigns MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END (0xFE) to moby->state when moby is at or above moby_instance_end, proving the same moby-state domain and this established name. domain_1_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 002c22b0 loads the stored ProjectileMoby pointer from moby data +0x74 and 002c22bc reads its state at +0x20; 002c22c4 loads 0xFD and 002c22c8 branches to 002c256c when that same state equals 0xFD, skipping collision processing. The prepared decompilation expresses the byte as -3 and authoritative C as target->state != 0xFD. Supplied mark_moby_for_removal assigns MOBY_STATE_REMOVAL_BELOW_INSTANCE_END (0xFD) to moby->state when moby < moby_instance_end, directly establishing this removal-state meaning. --- src/overlays/l13/mobys/mine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l13/mobys/mine.c b/src/overlays/l13/mobys/mine.c index 7d42f9e060..8f12fa4662 100644 --- a/src/overlays/l13/mobys/mine.c +++ b/src/overlays/l13/mobys/mine.c @@ -90,7 +90,7 @@ void level_13_mine_update(ProjectileMoby *moby) __asm__("FUN_L13_002c2048"); /* Moby class 83 */ void level_13_mine_update(ProjectileMoby *moby) { - char *moby_data = (char *)moby->data; + enum { MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD , MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE } ;char *moby_data = (char *)moby->data; ProjectileVec4 steering_and_collision_vector; float hitpos[12]; ProjectileVec4 *pos; @@ -139,7 +139,7 @@ void level_13_mine_update(ProjectileMoby *moby) { return; } target = *(ProjectileMoby **)(moby_data + 0x74); - if (target != 0 && target->state != 0xFE && target->state != 0xFD && + if (target != 0 && target->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && target->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && fast_vec_dist(pos, &target->pos) > 8.0f) { make_hit_descriptor(16.0f, &hitpos, moby, 0x30000, velocity); qcopy(&steering_and_collision_vector, pos); From d8836d7cc9e97de5ecf1598782f47f7ca7499369 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:13:18 +0000 Subject: [PATCH 0913/1502] decomp: clarify names in miner_update domain_0_value_1 -> MINER_UPDATE_DIALOGUE: Authoritative miner.c assigns moby->state = 1 in MINER_INITIALIZE before initialize_npc_dialogue and initialize_moby_grounding. Retail 002e6c54 loads s3=1; 002e6cc0 stores s3 to 0x20(s1). The same byte is loaded at 002e6c84 and compared with 1 at 002e6c88, selecting 002e6cf0-002e6d30, the update_npc_dialogue branch already labeled MINER_UPDATE_DIALOGUE in the local enum. domain_1_value_2 -> MINER_APPLY_DIALOGUE_COMPLETION: In MINER_UPDATE_DIALOGUE, a nonzero update_npc_dialogue result starts begin_dialogue_camera_transition and writes moby->state = 2. Retail 002e6d04-002e6d30 checks the updater result, calls the transition helper, loads v0=2 and stores it at 0x20(s1). Retail 002e6c84-002e6cac dispatches that exact state byte value 2 to 002e6d34, matching the existing MINER_APPLY_DIALOGUE_COMPLETION branch that applies flags, queues dialogue, clears persistence and saves. domain_2_value_1 -> MINER_UPDATE_DIALOGUE: The final moby->state = 1 in MINER_APPLY_DIALOGUE_COMPLETION follows availability updates, queue_dialogue_message, jet_clear_persistent, optional camera reset and memcard_save_data. Retail 002e6d94-002e6da0 calls the save helper then stores s3=1 to 0x20(s1). That is the same state byte read at 002e6c84 and dispatched by 002e6c88 to the dialogue updater at 002e6cf0, whose established local enum member is MINER_UPDATE_DIALOGUE. --- src/overlays/l12/mobys/miner.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l12/mobys/miner.c b/src/overlays/l12/mobys/miner.c index c41fb8a0a9..af82c7e908 100644 --- a/src/overlays/l12/mobys/miner.c +++ b/src/overlays/l12/mobys/miner.c @@ -90,7 +90,7 @@ void miner_update(L16WatchMoby *moby) { mark_moby_for_removal(moby); return; } - moby->state = 1; + moby->state = MINER_UPDATE_DIALOGUE; initialize_npc_dialogue(moby, &moby_data->activation); initialize_moby_grounding(moby); break; @@ -98,7 +98,7 @@ void miner_update(L16WatchMoby *moby) { if (alternate_item_available[1] == 0 && update_npc_dialogue(moby, &moby_data->activation)) { begin_dialogue_camera_transition(moby, 2.5f); *(int *)((char *)moby + 0x58) = 0; - moby->state = 2; + moby->state = MINER_APPLY_DIALOGUE_COMPLETION; } break; case MINER_APPLY_DIALOGUE_COMPLETION: @@ -113,7 +113,7 @@ void miner_update(L16WatchMoby *moby) { jet_reset_camera(p + 0x30, p + 0x70); } memcard_save_data(0, -1); - moby->state = 1; + moby->state = MINER_UPDATE_DIALOGUE; } } rate = 0.02f; From 95faf8ce7936de40b6a7cc2e01120e0be2395b26 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:13:18 +0000 Subject: [PATCH 0914/1502] decomp: clarify names in help_desk_lady_update domain_0_value_1 -> HELP_DESK_POLL_DIALOGUE: Retail 002e31cc loads the moby state byte at s1+20 and 002e31d0 dispatches value 1 to dialogue polling at 002e322c. Initialization at 002e3208 is followed by 002e321c storing 1 to that same byte. This is exactly the source's existing HELP_DESK_POLL_DIALOGUE selector domain. domain_3_value_2 -> HELP_DESK_REQUEST_HELP_AND_SAVE: Retail 002e326c calls update_npc_dialogue and 002e3274 tests its return; nonzero reaches 002e3280 storing 2 to s1+20. Dispatch 002e31f4 sends that same moby state value to 002e3284, which requests help and saves. Reuse the existing HELP_DESK_REQUEST_HELP_AND_SAVE member of this exact selector. domain_4_value_1 -> HELP_DESK_POLL_DIALOGUE: Within the state-2 gated branch, 002e328c stores s0=1 into the same moby state byte s1+20 loaded at 002e31cc. Value 1 is dispatched at 002e31d0 to 002e322c, the existing HELP_DESK_POLL_DIALOGUE case; this transient assignment uses that established local state domain. domain_5_value_3 -> HELP_DESK_HELP_AND_SAVE_REQUESTED: Retail state-2 branch calls help_request(0x3e82,0x84) at 002e32a8, then performs camera/widget and inventory calls, then memcard_save_data(0,-1) at 002e32d8. Instructions 002e32e0-002e32e4 store 3 into moby state s1+20 after those calls. This state records that help and save have been requested; it bypasses cases 0,1,2 on later updates. --- src/overlays/l16/mobys/help_desk_lady.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/overlays/l16/mobys/help_desk_lady.c b/src/overlays/l16/mobys/help_desk_lady.c index 10713c8d5d..92d69eddfa 100644 --- a/src/overlays/l16/mobys/help_desk_lady.c +++ b/src/overlays/l16/mobys/help_desk_lady.c @@ -115,6 +115,9 @@ void help_desk_lady_update(L16WatchMoby *moby) { HELP_DESK_POLL_DIALOGUE = 1, HELP_DESK_REQUEST_HELP_AND_SAVE = 2 }; + enum { + HELP_DESK_HELP_AND_SAVE_REQUESTED = 3 + }; L16WatchScratch gaze_vectors; L16WatchData *watch_data = moby->data; L16WatchFlags *flags; @@ -127,7 +130,7 @@ void help_desk_lady_update(L16WatchMoby *moby) { switch (moby->state) { case HELP_DESK_INITIALIZE_DIALOGUE: initialize_npc_dialogue(moby, activation); - moby->state = 1; + moby->state = HELP_DESK_POLL_DIALOGUE; watch_data->activation.radius = 20.0f; moby->opacity = 0xFF; break; @@ -136,14 +139,14 @@ void help_desk_lady_update(L16WatchMoby *moby) { if (player->disabled == 0 && player->mode != 15 && player->mode != 22) { if (is_point_inside_clip_volume((char *)player + 0x80, watch_data->activation_region) && update_npc_dialogue(moby, activation)) - moby->state = 2; + moby->state = HELP_DESK_REQUEST_HELP_AND_SAVE; } break; } case HELP_DESK_REQUEST_HELP_AND_SAVE: if (*(int *)&D_L16_0015F5C4 != 2) { char *player; - moby->state = 1; + moby->state = HELP_DESK_POLL_DIALOGUE; set_race_camera(D_L16_001D96C0, D_L16_001D96C0 + 4, 0, 1); help_request(0x3E82, 0x84); grant_inventory_item(0x21, 1); @@ -151,7 +154,7 @@ void help_desk_lady_update(L16WatchMoby *moby) { player = (char *)&D_0013E533 + 0xE9D; jet_reset_camera(player, player + 0x10); memcard_save_data(0, -1); - moby->state = 3; + moby->state = HELP_DESK_HELP_AND_SAVE_REQUESTED; } break; } From 704d5034f41e33466598201c01103a5eecaec6c0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:15:04 +0000 Subject: [PATCH 0915/1502] decomp: clarify names in elevator_update domain_0_value_2 -> ELEVATOR_WAIT_FOR_HERO: Retail 0x002e7fe8 reads moby state at +0x20; 0x002e7fec-0x002e7ff0 dispatches value 2 to 0x002e80ac, the source ELEVATOR_WAIT_FOR_HERO branch. Initialization sets reverse at 0x002e8094 and stores the same value 2 to +0x20 at 0x002e809c after selecting the starting height. This is the exact selector already named by the local enum. domain_1_value_3 -> ELEVATOR_UPDATE_HEIGHT: After hero proximity and selected-height alignment tests at 0x002e80d8-0x002e819c, retail stores the selected goal at 0x002e81c0, clears speed at 0x002e81c4 and writes 3 to moby +0x20 at 0x002e81cc. The same byte is dispatched for value 3 at 0x002e8010 to 0x002e8290, the source ELEVATOR_UPDATE_HEIGHT branch that advances Z through the scalar updater. domain_2_value_3 -> ELEVATOR_UPDATE_HEIGHT: Retail 0x002e81d8-0x002e81e8 checks that the hero is grounded on this elevator; 0x002e8238 toggles direction, 0x002e8278 clears speed and 0x002e8284 stores the selected goal. 0x002e8258 loads 3 and 0x002e828c stores it to moby +0x20, the same selector dispatched to height updating at 0x002e8010/0x002e8290 and already named ELEVATOR_UPDATE_HEIGHT in source. domain_3_value_2 -> ELEVATOR_WAIT_FOR_HERO: Retail 0x002e841c-0x002e842c compares moby Z with goal, then 0x002e8438-0x002e8448 requires no grounded hero rider before clearing basis storage at 0x002e8450. 0x002e8458 loads 2 and 0x002e8460 writes it to moby +0x20. The identical selector dispatches 2 to the proximity/rider waiting branch at 0x002e7ff0/0x002e80ac, already named ELEVATOR_WAIT_FOR_HERO. --- src/overlays/l16/mobys/elevator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l16/mobys/elevator.c b/src/overlays/l16/mobys/elevator.c index 1b441e8322..5c22aa9c7a 100644 --- a/src/overlays/l16/mobys/elevator.c +++ b/src/overlays/l16/mobys/elevator.c @@ -118,7 +118,7 @@ void elevator_update(L16PlatformMoby *moby) { elevator_data->joint * 0x80 + 0x38) + elevator_height_offset; moby->reverse = 1; - moby->state = 2; + moby->state = ELEVATOR_WAIT_FOR_HERO; break; case ELEVATOR_WAIT_FOR_HERO: if (voice_is_playing(moby, elevator_data->particle)) { @@ -143,7 +143,7 @@ void elevator_update(L16PlatformMoby *moby) { moby->reverse = (moby->reverse + 1) & 1; elevator_data->goal = motion.v[2]; elevator_data->speed = 0.0f; - moby->state = 3; + moby->state = ELEVATOR_UPDATE_HEIGHT; break; } } @@ -163,7 +163,7 @@ void elevator_update(L16PlatformMoby *moby) { elevator_data->joint * 0x80 + 0x38) + elevator_height_offset; elevator_data->speed = 0.0f; - moby->state = 3; + moby->state = ELEVATOR_UPDATE_HEIGHT; } break; case ELEVATOR_UPDATE_HEIGHT: { @@ -205,7 +205,7 @@ void elevator_update(L16PlatformMoby *moby) { if (moby->position[2] == elevator_data->goal && (hero.ground_moby != moby || hero.air_frames.s != 0)) { clear_u64_value(elevator_data->basis[1]); - moby->state = 2; + moby->state = ELEVATOR_WAIT_FOR_HERO; break; } if (elevator_data->speed != 0.0f) { From e68cb1df69f978528857e3ee361627040e326dfd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:15:04 +0000 Subject: [PATCH 0916/1502] decomp: clarify names in apply_hero_selected_flags_and_state_transitions domain_0_value_49 -> HERO_STATE_VOICE_SLOT_CLEANUP_IDLE_EXIT: Retail 0x0020bbf4-0x0020bc24 tests flag +0x12E3, contact +0x300 and exclusions on control mode +0x208C, then selects a0=0x31 for the state setter. The authoritative C passes target_state to hero_set_state(target_state, 1); original Ghidra merges these choices as FUN_002223f8(uVar5,1), and retail 0x0020be04 calls that setter with a1=1 at 0x0020be08. This establishes the HeroStateId domain, whose canonical members are supplied from include/rnc/hero/hero_state.h, rather than the separate saved_flag_selector, control mode or vehicle mode domains. domain_1_value_125 -> HERO_STATE_VEHICLE_MODE_1_DEATH_DESCENT: Retail 0x0020bc2c-0x0020bc5c tests flag +0x12E5, contact +0x300 and vehicle mode +0x20A4 equal to 1, excludes current state +0x2084 equal to 0x7D, then selects a0=0x7D. The authoritative C passes target_state to hero_set_state(target_state, 1); original Ghidra merges these choices as FUN_002223f8(uVar5,1), and retail 0x0020be04 calls that setter with a1=1 at 0x0020be08. This establishes the HeroStateId domain, whose canonical members are supplied from include/rnc/hero/hero_state.h, rather than the separate saved_flag_selector, control mode or vehicle mode domains. domain_2_value_124 -> HERO_STATE_DEATH_DESCENT: Retail 0x0020bc6c-0x0020bca8 tests contact and current state 0x3C/timer +0x41E, exits vehicle mode three, then chooses a0=0x7C when +0x22A8 is zero; the alternate destination is state 0x3C. The authoritative C passes target_state to hero_set_state(target_state, 1); original Ghidra merges these choices as FUN_002223f8(uVar5,1), and retail 0x0020be04 calls that setter with a1=1 at 0x0020be08. This establishes the HeroStateId domain, whose canonical members are supplied from include/rnc/hero/hero_state.h, rather than the separate saved_flag_selector, control mode or vehicle mode domains. domain_3_value_127 -> HERO_STATE_SINK: Retail 0x0020bcb0-0x0020bd40 tests flag +0x12EC, excludes current state 0x7F, checks +0x2F0 against position Z +0x88 with a 0.25 offset and downward velocity +0x108, exits vehicle mode three and selects a0=0x7F. The authoritative C passes target_state to hero_set_state(target_state, 1); original Ghidra merges these choices as FUN_002223f8(uVar5,1), and retail 0x0020be04 calls that setter with a1=1 at 0x0020be08. This establishes the HeroStateId domain, whose canonical members are supplied from include/rnc/hero/hero_state.h, rather than the separate saved_flag_selector, control mode or vehicle mode domains. domain_4_value_104 -> HERO_STATE_WAIT_FOR_JUMP_OR_RESPAWN: Retail 0x0020bd48-0x0020bdfc tests flag +0x12E6, current-state exclusions 0x68/0x7B, height +0x2F4 against position Z and downward velocity, then selects a0=0x68 when +0x22A8 is nonzero after exiting vehicle mode three. The authoritative C passes target_state to hero_set_state(target_state, 1); original Ghidra merges these choices as FUN_002223f8(uVar5,1), and retail 0x0020be04 calls that setter with a1=1 at 0x0020be08. This establishes the HeroStateId domain, whose canonical members are supplied from include/rnc/hero/hero_state.h, rather than the separate saved_flag_selector, control mode or vehicle mode domains. domain_5_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: Retail 0x0020bdf4-0x0020be04 selects a0=0x7B when +0x22A8 is zero after the +0x12E6 height gate; the level-13 collision-material path at 0x0020bb24/0x0020bb28 also reaches this state destination. C s7B assigns target_state=0x7B. The authoritative C passes target_state to hero_set_state(target_state, 1); original Ghidra merges these choices as FUN_002223f8(uVar5,1), and retail 0x0020be04 calls that setter with a1=1 at 0x0020be08. This establishes the HeroStateId domain, whose canonical members are supplied from include/rnc/hero/hero_state.h, rather than the separate saved_flag_selector, control mode or vehicle mode domains. domain_6_value_60 -> HERO_STATE_JUMP_WITH_HEALTH_DAMAGE: Retail 0x0020bc90-0x0020bca0 exits vehicle mode three and selects a0=0x3C when +0x22A8 is nonzero, following flag +0x12E5/contact and current-state/timer gates. C call3c assigns target_state=0x3C before the shared setter. The authoritative C passes target_state to hero_set_state(target_state, 1); original Ghidra merges these choices as FUN_002223f8(uVar5,1), and retail 0x0020be04 calls that setter with a1=1 at 0x0020be08. This establishes the HeroStateId domain, whose canonical members are supplied from include/rnc/hero/hero_state.h, rather than the separate saved_flag_selector, control mode or vehicle mode domains. --- src/overlays/shared/hero/hero_idle_sequence.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index bba99f37d7..d10a82432a 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -3476,24 +3476,24 @@ void apply_hero_selected_flags_and_state_transitions(void) { if (saved_flag_selector == 12) P.b12EA = 1; if (P.b12E3 && P.i300 && P.i208C != 0x10 && P.i208C != 0x14 && P.i208C != 7) { - target_state = 0x31; + target_state = HERO_STATE_VOICE_SLOT_CLEANUP_IDLE_EXIT; goto call; } if (P.b12E5 && P.i300 && P.b20A4 == 1 && P.i2084 != 0x7D) { - target_state = 0x7D; + target_state = HERO_STATE_VEHICLE_MODE_1_DEATH_DESCENT; goto call; } if (P.b12E5 && P.i300 && (P.i2084 != 0x3C || P.h41E != 0)) { exit_hero_vehicle_mode_if_mode_three(); if (P.i22A8) goto call3c; - target_state = 0x7C; + target_state = HERO_STATE_DEATH_DESCENT; goto call; } if (P.b12EC && P.i2084 != 0x7F && absolute_float(P.f2F0 - (P.f88 + 0.25f)) < 1.0f && 0.0f < P.f2F0 - P.f88 && P.f108 < 0.0f) { exit_hero_vehicle_mode_if_mode_three(); - target_state = 0x7F; + target_state = HERO_STATE_SINK; goto call; } if (P.b12E6 && P.i2084 != 0x68 && P.i2084 != 0x7B && @@ -3501,16 +3501,16 @@ void apply_hero_selected_flags_and_state_transitions(void) { (P.i2084 != 0x69 || P.h41E != 0) && P.f108 < 0.0f) { exit_hero_vehicle_mode_if_mode_three(); if (P.i22A8) { - target_state = 0x68; + target_state = HERO_STATE_WAIT_FOR_JUMP_OR_RESPAWN; goto call; } s7B: - target_state = 0x7B; + target_state = HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT; call: hero_set_state(target_state, 1); return; call3c: - target_state = 0x3C; + target_state = HERO_STATE_JUMP_WITH_HEALTH_DAMAGE; goto call; } if (P.b12EB && P.i2084 != 0x7B && absolute_float(P.f2F4 - (P.f88 + 0.25f)) < 1.0f && From 8eab269223ede97f4ca0c0e8692d220446c75ad8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:15:04 +0000 Subject: [PATCH 0917/1502] decomp: clarify names in gun_update domain_0_value_1 -> GUN_STATE_INACTIVE: Retail 0x002e8ad8 loads this gun's Moby.state (+0x20); 0x002e8adc immediately returns for 1. Initialization at 0x002e8b84..0x002e8b9c zeroes turn_velocity and assigns 1, establishing the inactive gun state. domain_14_value_3 -> GUN_STATE_CLEANUP: When all three target selections fail, 0x002e8cb8 branches to 0x002e8eac and 0x002e8eb0 stores 3 into this gun's Moby.state, then signals its wake moby. On the next update, 0x002e8b08 dispatches state 3 into target-removal and save-bit cleanup. domain_1_value_2 -> GUN_STATE_AIM_AND_FIRE: The state value comes directly from this gun's Moby.state at 0x002e8ad8. The <2 dispatch partitions initialization/inactive states from state 2, whose equality branch at 0x002e8b00 enters prioritized target selection, turning and shot spawning at 0x002e8ba0..0x002e8ea8. domain_2_value_0 -> GUN_STATE_INITIALIZE: Retail 0x002e8af0 dispatches gun Moby.state 0 to 0x002e8b18: it checks saved completion, removes a gun lacking its first target, otherwise resets turn_velocity at 0x002e8b84 and enters inactive state 1 at 0x002e8b9c. domain_3_value_2 -> GUN_STATE_AIM_AND_FIRE: Retail 0x002e8b00 dispatches this gun's state 2 to 0x002e8ba0. After save checks, 0x002e8c08..0x002e8cb8 selects a target, 0x002e8cc0..0x002e8d80 turns toward it and tests alignment, and 0x002e8e44 calls spawn_turret_shot. domain_4_value_3 -> GUN_STATE_CLEANUP: Retail 0x002e8b08 dispatches this gun's Moby.state 3 directly to 0x002e8efc. That path removes valid target mobys at 0x002e8f3c/0x002e8f88 and records this gun's save_id in both save bitsets at 0x002e8f94..0x002e9000. domain_5_value_3 -> GUN_STATE_CLEANUP: The initialization save checks at 0x002e8b18..0x002e8b74 send an already-cleared/saved gun to 0x002e8c00, which stores 3 to its Moby.state. Dispatch of that same value at 0x002e8b08 enters target removal and save-bit cleanup at 0x002e8efc. domain_6_value_1 -> GUN_STATE_INACTIVE: Retail 0x002e8b84 clears the gun_control turn velocity, then 0x002e8b9c stores 1 into this gun's Moby.state after confirming its first target exists. The state-1 dispatch at 0x002e8adc returns immediately without aiming or firing. domain_7_value_3 -> GUN_STATE_CLEANUP: State-2 save checks at 0x002e8ba0..0x002e8bfc converge on 0x002e8c04 storing 3 to this gun's Moby.state when already cleared/saved. The state-3 dispatch at 0x002e8b08 enters target removal and save-bit writes at 0x002e8efc..0x002e9000. --- src/overlays/l10/mobys/gun.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/overlays/l10/mobys/gun.c b/src/overlays/l10/mobys/gun.c index ff3b17b62c..fcd317a809 100644 --- a/src/overlays/l10/mobys/gun.c +++ b/src/overlays/l10/mobys/gun.c @@ -36,6 +36,12 @@ void gun_update(struct Moby *moby) __asm__("FUN_L10_002e8ab0"); /* Moby class 1346 */ void gun_update(struct Moby *moby) { + enum { + GUN_STATE_INITIALIZE = 0, + GUN_STATE_INACTIVE = 1, + GUN_STATE_AIM_AND_FIRE = 2, + GUN_STATE_CLEANUP = 3 + }; Vars *gun_control = (Vars *)moby->pvars; int *bits; float rotation[4]; @@ -45,16 +51,16 @@ void gun_update(struct Moby *moby) { int state; state = moby->state; - if (state == 1) + if (state == GUN_STATE_INACTIVE) return; - if (state < 2) { - if (state == 0) + if (state < GUN_STATE_AIM_AND_FIRE) { + if (state == GUN_STATE_INITIALIZE) goto state_zero; return; } - if (state == 2) + if (state == GUN_STATE_AIM_AND_FIRE) goto state_two; - if (state == 3) + if (state == GUN_STATE_CLEANUP) goto state_three; return; state_zero: { @@ -67,7 +73,7 @@ state_zero: { ((signed_save_id >> 5) * 4 + (current_level_index << 8))) >> (save_id & 31)) & 1) != 0) { - moby->state = 3; + moby->state = GUN_STATE_CLEANUP; return; } { @@ -76,7 +82,7 @@ state_zero: { return; } gun_control->turn_velocity = 0.0f; - moby->state = 1; + moby->state = GUN_STATE_INACTIVE; return; } } @@ -92,7 +98,7 @@ state_two: { ((signed_save_id >> 5) * 4 + (current_level_index << 8))) >> (save_id & 31)) & 1) != 0) { - moby->state = 3; + moby->state = GUN_STATE_CLEANUP; return; } { @@ -162,7 +168,7 @@ state_two: { } moby->rot.z = fast_add_rotations(moby->rot.z, 3.1415927f); } else { - moby->state = 3; + moby->state = GUN_STATE_CLEANUP; if (gun_control->wake != -1) { ((struct Moby *)((gun_control->wake << 8) + (int)D_L10_0015FFD8_8ab0))->state = 1; gun_control->wake = -1; From 83cc7d08171bf54dae92c9997bf7b209a68231a3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:15:05 +0000 Subject: [PATCH 0918/1502] decomp: clarify names in update_fighter_jet_missile domain_0_value_254 -> MOBY_STATE_PENDING_REMOVAL: Retail 0x00308ac4 loads missile_vars->target, and 0x00308ad0 loads that Moby's state byte at +0x20; 0x00308ad4-0x00308ad8 compare 0xFE and reacquire a target at 0x00308b30. Direct helper mark_moby_for_removal at 0x00274998, called with the missile Moby at 0x00308ea8/0x00308ef8, selects 0xFE at 0x002749bc and writes it to the same Moby.state offset +0x20 at 0x002749c0, then stores level_frame+2 at +0x38 (0x002749c8-0x002749e0). Thus 0xFE denotes a pending-removal Moby state; no allocation-specific distinction is claimed. --- src/overlays/shared/vehicles/fighter_jet_missile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/vehicles/fighter_jet_missile.c b/src/overlays/shared/vehicles/fighter_jet_missile.c index 3ccd0699f2..7596ab7291 100644 --- a/src/overlays/shared/vehicles/fighter_jet_missile.c +++ b/src/overlays/shared/vehicles/fighter_jet_missile.c @@ -164,7 +164,7 @@ void fighter_jet_missile_update(struct Moby *moby) __asm__("FUN_L11_003089d0"); /* Moby class 1009 */ void fighter_jet_missile_update(struct Moby *moby) { - MissileVars *missile_vars = (MissileVars *)moby->pvars; + enum { MOBY_STATE_PENDING_REMOVAL = 0xFE } ;MissileVars *missile_vars = (MissileVars *)moby->pvars; float previous_missile_position[4]; float look[4]; MissileHit hit; @@ -182,7 +182,7 @@ void fighter_jet_missile_update(struct Moby *moby) { copy_xyz_089d0(look, missile_vars->target_pos); ((int *)look)[3] = 0; target = missile_vars->target; - if (target == 0 || target->state == 0xFE || target->state == 0xFD || + if (target == 0 || target->state == MOBY_STATE_PENDING_REMOVAL || target->state == 0xFD || fast_vec_dist(&target->pos, look) > 3.0f) missile_vars->target = (struct Moby *)select_homing_missile_target( (float *)&moby->pos, (float *)&moby->rot, 0.2617994f, 0.2617994f, 60.0f); From a568202e1efe149cd8c62a7bfe2ba2dde4290328 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:17:12 +0000 Subject: [PATCH 0919/1502] decomp: clarify names in resolve_moby_hit_response domain_1_value_8 -> FALLBACK_RESPONSE_HIT_STATE: Authoritative src/mobys/resolve_moby_hit_response.c (SHA-256 1d5087edf274823115e97cba4b8a2738cc66e6f2f91092e1bfe56e43160b3b52) and original retail Ghidra agree: when hit_record+0x1C lacks the vector sentinel, both target-present and target-absent paths assign 8 to the hit-record state byte +0x28. Retail 0x00213bac/0x00213bb8 load 8 and 0x00213bbc stores it; 0x00213bc0-0x00213bc8 reads this byte and excludes 8 from the <8 dispatch, reaching 0x00213ce8-0x00213cf0, which selects DEFAULT_HIT_RESPONSE (response index 1) and output status 2. Thus 8 is a fallback-response hit-record state, not HERO_STATE_LAND. Supplied sand_shark and constructorbot callers obtain the record from find_moby_hit and consume its damage output. This entry selects the target-absent assignment. domain_3_value_8 -> FALLBACK_RESPONSE_HIT_STATE: Authoritative src/mobys/resolve_moby_hit_response.c (SHA-256 1d5087edf274823115e97cba4b8a2738cc66e6f2f91092e1bfe56e43160b3b52) and original retail Ghidra agree: when hit_record+0x1C lacks the vector sentinel, both target-present and target-absent paths assign 8 to the hit-record state byte +0x28. Retail 0x00213bac/0x00213bb8 load 8 and 0x00213bbc stores it; 0x00213bc0-0x00213bc8 reads this byte and excludes 8 from the <8 dispatch, reaching 0x00213ce8-0x00213cf0, which selects DEFAULT_HIT_RESPONSE (response index 1) and output status 2. Thus 8 is a fallback-response hit-record state, not HERO_STATE_LAND. Supplied sand_shark and constructorbot callers obtain the record from find_moby_hit and consume its damage output. This entry selects the target-present assignment. --- src/mobys/resolve_moby_hit_response.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/mobys/resolve_moby_hit_response.c b/src/mobys/resolve_moby_hit_response.c index 929a90e182..d7972759a3 100644 --- a/src/mobys/resolve_moby_hit_response.c +++ b/src/mobys/resolve_moby_hit_response.c @@ -92,6 +92,9 @@ s32 resolve_moby_hit_response(O_25a478 *hit_recipient_moby, SUBSTATE_GATED_AUXILIARY_FLAG_HIT_STATE = 5, SUBSTATE_GATED_COOLDOWN_DAMAGE_CLEARING_HIT_STATE = 7 }; + enum { + FALLBACK_RESPONSE_HIT_STATE = 8 + }; V_25a478 hit_blend_vector; V_25a478 combined_hit_vector; s32 hit_response_index; @@ -158,11 +161,11 @@ s32 resolve_moby_hit_response(O_25a478 *hit_recipient_moby, } } else { if (!hit_record->tgt) { - hit_record->state = 8; + hit_record->state = FALLBACK_RESPONSE_HIT_STATE; kind = 0x47; } else { kind = hit_record->tgt->hA6; - hit_record->state = 8; + hit_record->state = FALLBACK_RESPONSE_HIT_STATE; } } switch (hit_record->state) { From e0920a01601898e81bb3fd2b3d2917194b540e22 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:17:12 +0000 Subject: [PATCH 0920/1502] decomp: clarify names in background_ship_1_update domain_0_value_1 -> BACKGROUND_SHIP_1_FOLLOW_PATH: Retail 0x002ec4dc preserves moby in s3; 0x002ec514 reads its state byte at +0x20 and 0x002ec518 dispatches value 1 to 0x002ec620, which advances path progress and samples position/rotation (0x002ec658-0x002ec6e4). Initialization stores s2=1 into that same byte at 0x002ec5f8. The authoritative C already declares BACKGROUND_SHIP_1_FOLLOW_PATH=1 for this exact switch, so the assignment reuses its canonical local enum member. domain_1_value_2 -> BACKGROUND_SHIP_1_REMOVE: Retail 0x002ec740-0x002ec760 checks the saved hit pointer and positive float at +0x2C; 0x002ec768 loads 2 and 0x002ec770 stores it at moby+0x20. This is the same byte selected by 0x002ec514 and dispatched for value 2 at 0x002ec53c to 0x002ec774. That branch spawns three effects and calls mark_moby_for_removal at 0x002ec954. The authoritative C already names its exact switch case BACKGROUND_SHIP_1_REMOVE=2; reuse it for this transition assignment. --- src/overlays/shared/vehicles/background_ship_1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/vehicles/background_ship_1.c b/src/overlays/shared/vehicles/background_ship_1.c index 29c9ea1b41..0ae78b7a4f 100644 --- a/src/overlays/shared/vehicles/background_ship_1.c +++ b/src/overlays/shared/vehicles/background_ship_1.c @@ -227,7 +227,7 @@ void background_ship_1_update(char *moby) { qcopy(&MOBY(moby)->pos, D_L02_001B0AB0[moby_data->unk60] + 0x10); moby_data->unk68 = random_angle_radians(); moby_data->unk6C = invalid_index; - MOBY(moby)->state = 1; + MOBY(moby)->state = BACKGROUND_SHIP_1_FOLLOW_PATH; MOBY(moby)->flags |= 0x10; moby_data->unk64 = moby_data->unk74 * (float)*(int *)path; break; @@ -263,7 +263,7 @@ void background_ship_1_update(char *moby) { flag = 1; } if (flag) { - MOBY(moby)->state = 2; + MOBY(moby)->state = BACKGROUND_SHIP_1_REMOVE; } break; case BACKGROUND_SHIP_1_REMOVE: From 4143d35326de34780bbf92926485072388111a01 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:17:12 +0000 Subject: [PATCH 0921/1502] decomp: clarify names in update_menu_resource_stream domain_0_value_3 -> MEMCARD_REQUEST_FORMAT: Authoritative source SHA-256 044097aec790ac2833cd31ab7a15234a1c31d6ef0b7dcbd96f73e85443a35879 compares memory_card_state.state < 3. Retail 0x0021fe58 forms memory_card_state base 0x0013d290; 0x0021fe60 loads +0xd4 and 0x0021fe6c performs slti against 3, gating save-slot resource selection. Original Ghidra identifies this load as g_nMemoryCardOperationState. Supplied include/rnc/save/memory_card_state.h domain context explicitly assigns state/pending_state to MemoryCardOperation, whose canonical member MEMCARD_REQUEST_FORMAT equals 3; this is not an operation substep. domain_1_value_0 -> MEMCARD_QUERY_INFO: Authoritative source compares memory_card_state.pending_state < 0 in the same save-slot resource gate. Retail 0x0021fe88 loads +0xdc from memory_card_state base 0x0013d290; 0x0021fe8c bgez disables streaming for nonnegative pending operations. Original Ghidra identifies g_nPendingMemoryCardOperationState < 0. Supplied include/rnc/save/memory_card_state.h explicitly places pending_state in MemoryCardOperation, whose canonical zero member is MEMCARD_QUERY_INFO. Reusing it preserves the signed lower-bound comparison without conflating pending operations with probe or request substeps. --- src/ui/menus/system/update_menu_resource_stream.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/menus/system/update_menu_resource_stream.c b/src/ui/menus/system/update_menu_resource_stream.c index 6b9d7f2ce2..bed76f6000 100644 --- a/src/ui/menus/system/update_menu_resource_stream.c +++ b/src/ui/menus/system/update_menu_resource_stream.c @@ -90,8 +90,8 @@ s32 update_menu_resource_stream(struct MenuScreen *stream) { if (resource_index >= 5) { resource_index = 4; } - if (memory_card_state.state < 3) { - if (memory_card_state.pending_state < 0) { + if (memory_card_state.state < MEMCARD_REQUEST_FORMAT) { + if (memory_card_state.pending_state < MEMCARD_QUERY_INFO) { if (stream->data.stream.state == -1) { stream->data.stream.state = 0; } From 2cffa4588c46e6e43234130f400ebb5c583b98e5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:17:12 +0000 Subject: [PATCH 0922/1502] decomp: clarify names in update_hero_timers_and_reach_state domain_1_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x0022185c-0x00221870 loads the byte at hero+0x20A4, compares it with 2, and decrements hero+0x1636 (vehicle_triangle_cooldown). Original Ghidra uses cRam001413f4 for this comparison and again for the reach dispatch. Retail 0x002219dc-0x002219ec reads that identical +0x20A4 selector and branches on 2 to the 4.0 body-center offset and 15.0 reach-distance branch at 0x00221a30-0x00221a60. The bound C already labels that branch HERO_VEHICLE_MODE_GIANT_CLANK. Supplied enter_hero_vehicle_mode stores mode directly into hero.vehicle_mode and switches on mode using that member; HeroVehicleMode in include/rnc/hero/hero_state.h canonically defines it as 2. Thus this comparison belongs to the exact same vehicle-mode domain, independently of current-state IDs or control modes. --- src/overlays/shared/hero/hero_set_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_set_state.c b/src/overlays/shared/hero/hero_set_state.c index fffaf98c6d..e0ebcbc419 100644 --- a/src/overlays/shared/hero/hero_set_state.c +++ b/src/overlays/shared/hero/hero_set_state.c @@ -210,7 +210,7 @@ void update_hero_timers_and_reach_state(void) { } } } - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { fast_dec_timer_s16(&hero.vehicle_triangle_cooldown); } for (i = 0; i < 5; i++) { From bcfc6f5b5cb32d391b920bc37c4a3a75f0b96ea8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:17:13 +0000 Subject: [PATCH 0923/1502] decomp: clarify names in robot_qwark_update domain_0_value_3 -> ROBOT_QWARK_BROKEN_SPARKING: Retail 002dbe70-002dbe80 reads and writes Moby.state at s1+0x20 after the saved-cleared tests. This is the identical field switched at 002dc080-002dc0b0; its existing local enum member ROBOT_QWARK_BROKEN_SPARKING enters randomized particle emission at 002dc180-002dc2d8. Reuse that member for the !=3 guard. domain_1_value_3 -> ROBOT_QWARK_BROKEN_SPARKING: Retail 002dbe74 loads 3 and 002dbe80 stores it to s1+0x20, followed by broken animation selection at 002dbe88. The same Moby.state selects existing ROBOT_QWARK_BROKEN_SPARKING in the authoritative switch and the spark-emission branch at 002dc180. This is a state assignment, distinct from hit->type. domain_2_value_3 -> ROBOT_QWARK_BROKEN_SPARKING: Retail 002dc068-002dc078 tests NPC dialogue suppression but permits s1+0x20 state 3 through to the switch at 002dc080. The permitted branch is the existing ROBOT_QWARK_BROKEN_SPARKING state, whose 002dc180-002dc2d8 body emits particles rather than updating dialogue. domain_3_value_1 -> ROBOT_QWARK_UPDATE_DIALOGUE: Retail 002dc0d4 writes s2=1 to Moby.state at s1+0x20 during ROBOT_QWARK_INITIALIZE, before talker_init at 002dc0d8. The very same state byte is dispatched by 002dc088 to 002dc0fc, which calls talker_update. Reuse existing ROBOT_QWARK_UPDATE_DIALOGUE. domain_5_value_2 -> ROBOT_QWARK_RESOLVE_DIALOGUE: Retail 002dc100-002dc130 calls talker_update, checks success, runs the dialogue camera transition, then stores 2 into Moby.state at s1+0x20. Dispatch at 002dc0a8 sends that state to 002dc134-002dc174, the authoritative existing ROBOT_QWARK_RESOLVE_DIALOGUE case with gate wait and conditional warp-camera reset. domain_6_value_1 -> ROBOT_QWARK_UPDATE_DIALOGUE: Retail 002dc144 restores s2=1 into Moby.state at s1+0x20 after the resolve-dialogue global gate clears. That same byte drives 002dc088, which routes 1 to talker_update at 002dc100, matching the existing local ROBOT_QWARK_UPDATE_DIALOGUE enum member. domain_7_value_2 -> TALKER_MODE_WARP: Retail 002dbdcc loads dialogue_state from Moby.pvars into s3; 002dc148 loads its signed mode at s3+4 and 002dc14c compares it with 2. Only this mode, with warp index s3+0x4c != -1, selects l03_cuboids[index*128] and passes offsets +0x30/+0x70 to jet_reset_camera at 002dc154-002dc174. The authoritative TalkerVars.mode comment explicitly identifies 2 as talk ending in a warp. This is a separate TalkerVars mode domain, not the Moby state enum. --- src/overlays/l03/mobys/robot_qwark.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/overlays/l03/mobys/robot_qwark.c b/src/overlays/l03/mobys/robot_qwark.c index 529ef548fa..03b5cc07e7 100644 --- a/src/overlays/l03/mobys/robot_qwark.c +++ b/src/overlays/l03/mobys/robot_qwark.c @@ -77,6 +77,9 @@ void robot_qwark_update(struct Moby *robot_qwark_moby) { ROBOT_QWARK_RESOLVE_DIALOGUE = 2, ROBOT_QWARK_BROKEN_SPARKING = 3 }; + enum { + TALKER_MODE_WARP = 2 + }; struct TalkerVars *dialogue_state = (struct TalkerVars *)robot_qwark_moby->pvars; TalkerHit *hit; u8 type; @@ -94,8 +97,8 @@ void robot_qwark_update(struct Moby *robot_qwark_moby) { (D_0014C190_257218[current_level_index][(s16)robot_qwark_moby->save_id >> 5] >> (robot_qwark_moby->save_id & 0x1F)) & 1) { - if (robot_qwark_moby->state != 3) { - robot_qwark_moby->state = 3; + if (robot_qwark_moby->state != ROBOT_QWARK_BROKEN_SPARKING) { + robot_qwark_moby->state = ROBOT_QWARK_BROKEN_SPARKING; set_moby_animation(robot_qwark_moby, 1, 0); } } @@ -140,13 +143,13 @@ void robot_qwark_update(struct Moby *robot_qwark_moby) { 1 << (robot_qwark_moby->save_id & 0x1F); } robot_qwark_moby->hit_slot = 0xFF; - if (npc_dialogue_suppression_flags[0] != 0 && robot_qwark_moby->state != 3) { + if (npc_dialogue_suppression_flags[0] != 0 && robot_qwark_moby->state != ROBOT_QWARK_BROKEN_SPARKING) { return; } switch (robot_qwark_moby->state) { case ROBOT_QWARK_INITIALIZE: robot_qwark_moby->spawn_frame = *(u64 *)(D_001413D0[0] + 0x38); - robot_qwark_moby->state = 1; + robot_qwark_moby->state = ROBOT_QWARK_UPDATE_DIALOGUE; talker_init(robot_qwark_moby, dialogue_state); if (alternate_item_available[0x19] != 0) { dialogue_state->mode = 1; @@ -157,15 +160,15 @@ void robot_qwark_update(struct Moby *robot_qwark_moby) { if (talker_update(robot_qwark_moby, dialogue_state)) { alternate_item_available[0x19] = 1; begin_dialogue_camera_transition(robot_qwark_moby, 2.7f); - robot_qwark_moby->state = 2; + robot_qwark_moby->state = ROBOT_QWARK_RESOLVE_DIALOGUE; } break; case ROBOT_QWARK_RESOLVE_DIALOGUE: if (D_L03_0015F5C4 == 2) { break; } - robot_qwark_moby->state = 1; - if (dialogue_state->mode == 2 && dialogue_state->warp != -1) { + robot_qwark_moby->state = ROBOT_QWARK_UPDATE_DIALOGUE; + if (dialogue_state->mode == TALKER_MODE_WARP && dialogue_state->warp != -1) { warp_record = (char *)l03_cuboids + dialogue_state->warp * 128; jet_reset_camera(warp_record + 0x30, warp_record + 0x70); } From 9812d514b895b37e2d528a20f88695dac7baecfa Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:19:06 +0000 Subject: [PATCH 0924/1502] decomp: clarify names in taxi_update domain_0_value_3 -> TAXI_BLEND_TO_PATH_START: Retail 0x00318df4-0x00318dfc stores 3 to s3+0x20, the same taxi moby state loaded for switch dispatch at 0x00318cdc. Its existing TAXI_BLEND_TO_PATH_START case samples path progress zero and blends the current stop pose toward that sample at 0x00318e68-0x00318f44. domain_2_value_4 -> TAXI_FOLLOW_PATH: Retail 0x00318f20-0x00318f44 stores 4 to the same s3+0x20 taxi state when blend progress reaches one. The existing TAXI_FOLLOW_PATH case at 0x00318f48 calls advance_moby_path until completion; this assignment enters that exact case. domain_3_value_5 -> TAXI_BLEND_TO_DESTINATION: Retail 0x00318f48-0x00318f64 stores 5 to s3+0x20 after advance_moby_path returns nonzero and clears blend progress and velocity. The same taxi state dispatches existing TAXI_BLEND_TO_DESTINATION, whose 0x00318fa0-0x00319080 code blends the sampled path end to the destination stop pose. domain_4_value_1 -> TAXI_WAIT_FOR_PICKUP: Retail 0x00319058-0x00319080 stores 1 to s3+0x20 when destination blend reaches one, then resets the moby to its placement. This is the same state field dispatched into existing TAXI_WAIT_FOR_PICKUP, which tests grounded hero and pickup bounds at 0x00318d20-0x00318dcc. domain_5_value_1 -> TAXI_WAIT_FOR_PICKUP: Retail 0x003190d8-0x003190f4 stores 1 to s3+0x20 while restoring visibility, class collision and clearing flag bit zero after activation. That same moby state field drives existing TAXI_WAIT_FOR_PICKUP in the switch; it is not a hero state or a visibility boolean despite sharing the literal one. domain_6_value_3 -> TAXI_BLEND_TO_PATH_START: Retail 0x00319100-0x0031910c loads s3+0x20, subtracts 3 and tests unsigned less than 3, identifying inclusive taxi states 3 through 5. Bound C expresses the lower limit as moby->state >= 3. The same field's existing switch names state 3 TAXI_BLEND_TO_PATH_START; this is the travel interval's lower endpoint. domain_7_value_5 -> TAXI_BLEND_TO_DESTINATION: Retail 0x00319100-0x0031910c tests the same taxi moby state for the inclusive interval 3 through 5, enabling hero travel locks and taxi voice handling. Bound C expresses its upper endpoint as moby->state <= 5; state 5 is the existing TAXI_BLEND_TO_DESTINATION case on this exact selector. --- src/overlays/l05/mobys/taxi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l05/mobys/taxi.c b/src/overlays/l05/mobys/taxi.c index dfbe3f8cab..b51fad3a74 100644 --- a/src/overlays/l05/mobys/taxi.c +++ b/src/overlays/l05/mobys/taxi.c @@ -106,7 +106,7 @@ void taxi_update(struct Moby *moby) { select_taxi_route(moby); request_moby_variant_help_message(moby); if (pad_pressed_words[0] & 0x10) { - moby->state = 3; + moby->state = TAXI_BLEND_TO_PATH_START; destination_stop_moby = find_moby_in_owner_list_by_id(moby, taxi_data->unkB6); if (destination_stop_moby != 0) { destination_stop_moby->state = 2; @@ -151,14 +151,14 @@ void taxi_update(struct Moby *moby) { if (1.0f <= taxi_data->unkC0) { taxi_data->unkC0 = z; *(float *)&taxi_data->unkC4 = z; - moby->state = 4; + moby->state = TAXI_FOLLOW_PATH; } break; case TAXI_FOLLOW_PATH: if (advance_moby_path(moby)) { *(int *)&taxi_data->unkC0 = 0; taxi_data->unkC4 = 0; - moby->state = 5; + moby->state = TAXI_BLEND_TO_DESTINATION; } break; case TAXI_BLEND_TO_DESTINATION: @@ -196,7 +196,7 @@ void taxi_update(struct Moby *moby) { if (1.0f <= taxi_data->unkC0) { *(int *)&taxi_data->unkC0 = 0; taxi_data->unkC4 = 0; - moby->state = 1; + moby->state = TAXI_WAIT_FOR_PICKUP; reset_selected_moby_to_current_placement(moby); } break; @@ -209,12 +209,12 @@ void taxi_update(struct Moby *moby) { moby->visible = 1; moby->collision = class_collision; moby->flags = flags & 0xFFFE; - moby->state = 1; + moby->state = TAXI_WAIT_FOR_PICKUP; } break; } apply_moby_position_and_rotation_wobble(moby); - if (moby->state >= 3 && moby->state <= 5) { + if (moby->state >= TAXI_BLEND_TO_PATH_START && moby->state <= TAXI_BLEND_TO_DESTINATION) { travel_hero = &hero; travel_hero->jump_lock_timer = 2; travel_hero->unk1F4 = 2; From d187260f03c4185da6c18a1cc813df9dcc2ed314 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:19:06 +0000 Subject: [PATCH 0925/1502] decomp: clarify names in elevator_update domain_0_value_2 -> ELEVATOR_WAIT_AT_STOP: Initialization tests elevator_vars->stop (+0xA4) at 002dbe58-002dbe60 and stores 2 into moby+0x20 at 002dbe68. The same byte is loaded at 002dbd9c and value 2 dispatches to 002dbe84, the existing ELEVATOR_WAIT_AT_STOP case that releases audio and waits for rider/proximity activation. domain_1_value_1 -> ELEVATOR_WAIT_FOR_RIDER_OR_TRIGGER: When initialization finds stop (+0xA4) zero, 002dbe74 stores s2=1 into moby+0x20. Dispatch 002dbd9c-002dbda4 reads that exact byte and routes 1 to 002dbfd0, the existing ELEVATOR_WAIT_FOR_RIDER_OR_TRIGGER case checking hero ground ownership/air frames or D_0013D4DA. domain_2_value_3 -> ELEVATOR_MOVE_TO_GOAL: In ELEVATOR_WAIT_AT_STOP, the hero-height proximity branch at 002dbf6c-002dbf74 selects 3; 002dbf94-002dbfa4 toggles reverse, writes transformed endpoint to goal (+0xA8), clears speed (+0xB0) and stores 3 to moby+0x20. Dispatch 002dbdcc sends that byte value to existing ELEVATOR_MOVE_TO_GOAL at 002dc0a0. domain_3_value_3 -> ELEVATOR_MOVE_TO_GOAL: The WAIT_AT_STOP rider branch checks hero.ground_moby and zero air frames at 002dbfb0-002dbfc0, then joins endpoint setup at 002dc004. The shared retail tail clears speed at 002dc088, stores goal at 002dc094 and stores 3 to moby+0x20 at 002dc09c. That byte is the dispatch selector for existing ELEVATOR_MOVE_TO_GOAL (002dbdcc -> 002dc0a0). domain_4_value_3 -> ELEVATOR_MOVE_TO_GOAL: WAIT_FOR_RIDER_OR_TRIGGER checks ground ownership/air frames or trigger at 002dbfd0-002dbff8, then computes alternating endpoint at 002dc004-002dc084. It clears speed +0xB0, writes goal +0xA8, and stores 3 to moby+0x20 at 002dc09c. The same selector dispatches value 3 to the existing ELEVATOR_MOVE_TO_GOAL case at 002dc0a0. domain_5_value_2 -> ELEVATOR_WAIT_AT_STOP: Movement arrival compares moby position Z (+0x18) against goal (+0xA8) at 002dc204-002dc214, then verifies no grounded rider at 002dc220-002dc230. After clearing basis[1] at 002dc238 it stores 2 to moby+0x20 at 002dc248. Dispatch 002dbdc4 routes that byte value to the existing ELEVATOR_WAIT_AT_STOP branch at 002dbe84. --- src/overlays/l02/mobys/elevator.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l02/mobys/elevator.c b/src/overlays/l02/mobys/elevator.c index c5f5c4814d..dff580b4af 100644 --- a/src/overlays/l02/mobys/elevator.c +++ b/src/overlays/l02/mobys/elevator.c @@ -96,9 +96,9 @@ void elevator_update(L16PlatformMoby *moby) { level02_elevator_stop_height_offset_gp; moby->reverse = 1; if (elevator_vars->stop) { - moby->state = 2; + moby->state = ELEVATOR_WAIT_AT_STOP; } else { - moby->state = 1; + moby->state = ELEVATOR_WAIT_FOR_RIDER_OR_TRIGGER; } break; case ELEVATOR_WAIT_AT_STOP: @@ -124,7 +124,7 @@ void elevator_update(L16PlatformMoby *moby) { moby->reverse = (moby->reverse + 1) & 1; elevator_vars->goal = motion.v[2]; elevator_vars->speed = 0.0f; - moby->state = 3; + moby->state = ELEVATOR_MOVE_TO_GOAL; break; } } @@ -144,7 +144,7 @@ void elevator_update(L16PlatformMoby *moby) { elevator_vars->joint * 0x80 + 0x38) + level02_elevator_stop_height_offset_gp; elevator_vars->speed = 0.0f; - moby->state = 3; + moby->state = ELEVATOR_MOVE_TO_GOAL; } break; case ELEVATOR_WAIT_FOR_RIDER_OR_TRIGGER: @@ -164,7 +164,7 @@ void elevator_update(L16PlatformMoby *moby) { elevator_vars->joint * 0x80 + 0x38) + level02_elevator_stop_height_offset_gp; elevator_vars->speed = 0.0f; - moby->state = 3; + moby->state = ELEVATOR_MOVE_TO_GOAL; } break; case ELEVATOR_MOVE_TO_GOAL: { @@ -205,7 +205,7 @@ void elevator_update(L16PlatformMoby *moby) { if (moby->position[2] == elevator_vars->goal && (hero.ground_moby != (struct Moby *)moby || hero.air_frames.s != 0)) { clear_u64_value(elevator_vars->basis[1]); - moby->state = 2; + moby->state = ELEVATOR_WAIT_AT_STOP; break; } if (elevator_vars->speed != 0.0f) { From de286de2ec8cb1c92409eeca236737f30a9a3dea Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:19:06 +0000 Subject: [PATCH 0926/1502] decomp: clarify names in update_landmine domain_0_value_1 -> PATH_FOLLOWER_CHECK_HIT_AND_PROXIMITY: Bound source src/overlays/l08/mobys/landmine.c SHA-256 8f8dc5e8d76e3da353d0be9bf72259916965f5097211f7bbe740b0f2f22a9cf7 assigns moby->state=1 in the initialization case. Retail 0x002f44d4 keeps moby in s1, 0x002f44f0 reads its state byte at +0x20, and 0x002f4544 stores s5=1 to that exact byte. Dispatch 0x002f44f4 sends state 1 to 0x002f4548, which checks find_moby_hit, XY proximity and target equality before effects/removal. Thus this assignment enters the existing PATH_FOLLOWER_CHECK_HIT_AND_PROXIMITY case of the identical selector domain. domain_1_value_3 -> PATH_FOLLOWER_FADE_OUT: The bound source assigns moby->state=3 in PATH_FOLLOWER_FOLLOW_PATH when waypoint zero is outside the distance-24 removal branch. Original retail decompilation likewise stores 3 to param_1+0x20. Retail 0x002f4968..496c loads 3 and stores it to +0x20(s1), the state byte read at 0x002f44f0. Dispatch 0x002f4520 routes state 3 to 0x002f49bc, where alpha at +0x23 approaches zero by 128/scale_game_frames(30), is narrowed back to a byte, and zero causes removal at 0x002f4a18. This proves reuse of the existing same-selector PATH_FOLLOWER_FADE_OUT member. --- src/overlays/l08/mobys/landmine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l08/mobys/landmine.c b/src/overlays/l08/mobys/landmine.c index 0cccdd3eef..2237a391f4 100644 --- a/src/overlays/l08/mobys/landmine.c +++ b/src/overlays/l08/mobys/landmine.c @@ -62,7 +62,7 @@ void landmine_update(struct Moby *moby) { switch (moby->state) { case PATH_FOLLOWER_INITIALIZE_HEIGHT_OFFSET: { fade = moby->pos.z; - moby->state = 1; + moby->state = PATH_FOLLOWER_CHECK_HIT_AND_PROXIMITY; moby->pos.z = fade + 0.4f; return; } @@ -189,7 +189,7 @@ void landmine_update(struct Moby *moby) { mark_moby_for_removal(moby); return; } - moby->state = 3; + moby->state = PATH_FOLLOWER_FADE_OUT; } if (fast_vec_dist(&moby->pos, &point) < 0.1f) { follower->point = waypoint; From c3aa41a2e7cdb75dd089ca0f32f4be59b5b48cd6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:19:06 +0000 Subject: [PATCH 0927/1502] decomp: clarify names in update_hovering_rocket_attacker_common domain_0_value_2 -> TARGET_SELECTION_NO_TARGET: Assigned retail 0x002c3200 calls level-13 helper 0x0026bf80 with output moby_data+0x70; 0x002c3208 compares its return with 2 before position/range checks. Checked helper request 51610bbd9d454ef19a7e3af9ff3c82a4 initializes status at sp+0x10 to 0 and default target s8 at 0x0026bfe0-0x0026bfe8. Paths 0x0026bffc-0x0026c010, 0x0026c078-0x0026c084 and 0x0026c0c8-0x0026c0d0 set status 2 and clear s8. Only accepted alternate candidates replace s8 and status with 1 at 0x0026c1e4-0x0026c1e8 or 0x0026c2f4-0x0026c2f8. With no selected target, 0x0026c3a8 clears output target pointer +0x40 and position vectors; 0x0026c3d8 returns status. Thus returned 2 means no target, in a distinct domain from HIT_REACTION_REMOVE=2. --- src/overlays/l13/mobys/hovering_rocket_attacker.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l13/mobys/hovering_rocket_attacker.c b/src/overlays/l13/mobys/hovering_rocket_attacker.c index b681b01479..7a05f3a7dc 100644 --- a/src/overlays/l13/mobys/hovering_rocket_attacker.c +++ b/src/overlays/l13/mobys/hovering_rocket_attacker.c @@ -382,7 +382,7 @@ void update_hovering_rocket_attacker_common(unsigned char *moby) { HIT_REACTION_HIGH_INTERPOLATION_TARGET = 9, HIT_REACTION_HIGH_INTERPOLATION_TARGET_ALTERNATE = 10, HIT_REACTION_NO_HIT = 11 - }; + } ; enum { TARGET_SELECTION_NO_TARGET = 2}; HoveringRocketAttackerVars *moby_data; char *hit_record; int hit_reaction_code; @@ -541,7 +541,7 @@ void update_hovering_rocket_attacker_common(unsigned char *moby) { target_selection_point_table + 0x10, *(int *)target_selection_point_table); } - if (target_selection_status != 2) { + if (target_selection_status != TARGET_SELECTION_NO_TARGET) { if (moby_data->unkD8 < vector_distance_xy(moby + 0x10, moby_data->unk70) || 8.0f < absolute_float(MOBY(moby)->pos.z - moby_data->unk70[2])) { moby_data->unkB4 = 2; From c65ce6e52ef6084050e9bf22ce61fc6de3d8b1c3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:19:06 +0000 Subject: [PATCH 0928/1502] decomp: clarify names in update_two_door_gate domain_0_value_1 -> GATE_WAIT_FOR_HERO_TRIGGER: Retail 00316350 loads the switch selector from 0x20(s6); 003164f8 stores 1 to that exact byte after both doors are initialized. Original decompilation case 1 and bound C GATE_WAIT_FOR_HERO_TRIGGER then test hero distance <12 and the hero-position predicate. This is the same local gate-state domain, not a hero state. domain_1_value_2 -> GATE_RAISE_DOORS: Retail 00316538-00316544 resets private progress at +8 and stores 2 to parent state byte 0x20(s6) once both hero-trigger tests pass. The same byte selects case 2; 003165d8-00316620 raises both door Z positions from parent Z-4 toward parent Z. Bound C already names that branch GATE_RAISE_DOORS. domain_2_value_3 -> GATE_ZERO_DOOR_Y_ROTATION: Retail 00316634-00316650 checks raise progress >=1, clears progress and stores 3 to the same 0x20(s6) gate switch selector. Case 3 at 00316698-003166c4 multiplies configured Y rotation by 1-progress and stores it to both door rot.y fields. Reuse the bound C member GATE_ZERO_DOOR_Y_ROTATION. domain_3_value_4 -> GATE_TILT_DOORS_APART: Retail 003166d8-003166f4 clears completed Y-rotation progress and writes 4 to gate state byte 0x20(s6), the selector read at 00316350. Case 4 at 00316780-00316798 applies negative/positive progress*pi/2 to left/right rot.x, with a quarter-unit Z lift. Bound C names this exact branch GATE_TILT_DOORS_APART. domain_4_value_5 -> GATE_OPEN_IDLE: Retail 003167ac-003167c8 tests tilt progress >=1, clears progress and stores 5 to the gate's selector byte 0x20(s6) after opposite X rotations reach -/+pi/2. Original retail decompilation has no active case-5 work; authoritative C explicitly has case GATE_OPEN_IDLE: break. Reuse that existing local member. --- src/overlays/l11/mobys/two_door_gate.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l11/mobys/two_door_gate.c b/src/overlays/l11/mobys/two_door_gate.c index 4690efb2e8..350bdce39d 100644 --- a/src/overlays/l11/mobys/two_door_gate.c +++ b/src/overlays/l11/mobys/two_door_gate.c @@ -83,14 +83,14 @@ void two_door_gate_update(struct Moby *moby) { door_vars = gate_vars->right->pvars; *(u8 **)(door_vars + 8) = door_vars + 0x20; *(u32 *)(door_vars + 0x5C) |= 1; - moby->state = 1; + moby->state = GATE_WAIT_FOR_HERO_TRIGGER; break; } case GATE_WAIT_FOR_HERO_TRIGGER: if (vector_distance_xy(&moby->pos.x, &hero.motion.pos.f[0]) < 12.0f && is_point_inside_clip_volume(&hero.motion.pos, gate_vars->unk10) != 0) { gate_vars->t = 0.0f; - moby->state = 2; + moby->state = GATE_RAISE_DOORS; FUN_0022da68(0, 4, gate_vars->left); } break; @@ -110,7 +110,7 @@ void two_door_gate_update(struct Moby *moby) { update_entity(gate_vars->right); if (gate_vars->t >= 1.0f) { gate_vars->t = 0.0f; - moby->state = 3; + moby->state = GATE_ZERO_DOOR_Y_ROTATION; } break; case GATE_ZERO_DOOR_Y_ROTATION: { @@ -128,7 +128,7 @@ void two_door_gate_update(struct Moby *moby) { update_entity(gate_vars->right); if (gate_vars->t >= 1.0f) { gate_vars->t = 0.0f; - moby->state = 4; + moby->state = GATE_TILT_DOORS_APART; } break; } @@ -149,7 +149,7 @@ void two_door_gate_update(struct Moby *moby) { update_entity(gate_vars->right); if (gate_vars->t >= 1.0f) { gate_vars->t = 0.0f; - moby->state = 5; + moby->state = GATE_OPEN_IDLE; } break; } From 423e40f3a8af163e334a553d292146edb7906c51 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:19:06 +0000 Subject: [PATCH 0929/1502] decomp: clarify names in draw_map_screen domain_0_value_0 -> MUSIC_STREAM_READ_IDLE: Retail 0x0021c25c-0x0021c264 reads signed halfword 0x001516d8 and skips completion bookkeeping when nonzero. At zero, 0x0021c274-0x0021c29c clears pending_buffer, toggles the selected slot's 0x1000 pending bit and resets sel to -1. Original Ghidra calls this g_cdReadState.nActive; authoritative C binds it to music_stream_state.read_state. Zero thus denotes no active stream read, allowing completion retirement. domain_1_value_0 -> MUSIC_STREAM_READ_IDLE: Retail 0x0021c2a4-0x0021c2a8 reloads the same 0x001516d8 halfword and skips new map-read scheduling when nonzero. The zero path calls promote_first_available_map_entry and pick_next_map, then starts a read at 0x0021c364 and sets pending_buffer=1 at 0x0021c374. Original Ghidra identifies g_cdReadState.nActive and authoritative C identifies music_stream_state.read_state; reuse the same idle member because zero permits issuing the next read. domain_2_value_0 -> MUSIC_STREAM_READ_IDLE: Retail 0x0021c3bc-0x0021c3c4 tests the same 0x001516d8 halfword; a nonzero value returns without fallback. Only zero, combined with missing map slot and unsuccessful slot promotion, reaches pick_map_slot_to_evict at 0x0021c3e0. Original Ghidra tests g_cdReadState.nActive != 0 here, while authoritative C tests music_stream_state.read_state == 0. This is the same no-active-read gate, so it reuses MUSIC_STREAM_READ_IDLE. --- src/ui/map/draw_map_screen.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ui/map/draw_map_screen.c b/src/ui/map/draw_map_screen.c index 13aa88fa5b..3a9533f552 100644 --- a/src/ui/map/draw_map_screen.c +++ b/src/ui/map/draw_map_screen.c @@ -57,6 +57,9 @@ extern void allocate_voice_for_target_entry() __asm__("func_0022DA68"); s32 draw_map_screen(struct MenuScreen *screen) __asm__("FUN_0021be60"); s32 draw_map_screen(struct MenuScreen *screen) { + enum { + MUSIC_STREAM_READ_IDLE = 0 + }; s32 previous_selected_level_id; s32 selected_level_table_index; s32 next_level_id; @@ -196,7 +199,7 @@ s32 draw_map_screen(struct MenuScreen *screen) { update_map_icons(level_map_selection.level, 0); } - if (music_stream_state.read_state == 0) { + if (music_stream_state.read_state == MUSIC_STREAM_READ_IDLE) { if (level_map_selection.sel != -1) { menu_system.pending_buffer = 0; level_map_selection.slot_id[level_map_selection.sel] ^= 0x1000; @@ -204,7 +207,7 @@ s32 draw_map_screen(struct MenuScreen *screen) { } } pick = -1; - if (music_stream_state.read_state == 0) { + if (music_stream_state.read_state == MUSIC_STREAM_READ_IDLE) { pick = promote_first_available_map_entry(); if (pick != -1) { next = pick_next_map(); @@ -235,7 +238,7 @@ s32 draw_map_screen(struct MenuScreen *screen) { } slot = find_map_entry_slot(id); if (level_map_selection.level != level_map_selection.loaded) { - if (music_stream_state.read_state == 0 && slot == -1 && pick == slot) { + if (music_stream_state.read_state == MUSIC_STREAM_READ_IDLE && slot == -1 && pick == slot) { pick_map_slot_to_evict(level_map_selection.loaded); } } From 908a8361a4cbd1d2d62a2a87edbbf5323f3457b1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:19:06 +0000 Subject: [PATCH 0930/1502] decomp: clarify names in predict_thrown_moby_landing domain_0_value_1 -> DECOY_HELD: Retail 0x002c3b70-0x002c3b78 reads thrown_moby state at +0x20 and tests 1; that branch constructs a launch position relative to the hero. The checked decoy_update caller passes its own moby to this function and names state 1 DECOY_HELD in its same-field switch, where it verifies the holder and held item. This proves the same decoy state domain, rather than HeroStateId. domain_1_value_0 -> LANDING_REQUIRE_MOBY_PVARS_LINK: Mode is a2 retained in s7 at 0x002c3b10. At 0x002c3fa4-0x002c3fc4 mode 0 rejects null coll_hit.moby and rejects a null FUN_L00_002603d0 result. Helper retail 0x002603d0-0x002603fc checks moby flags +0x34 bit 0x20 then returns pvars(+0x78)[+8], matching supplied get_moby_pvars_link context. Caller tries mode 0 before fallback mode 2. domain_2_value_2 -> LANDING_SKIP_LINKED_MOBY_DRAW: Retail 0x002c3fcc-0x002c4000 compares s7 mode to 2. Only mode 2 with non-null collision moby and non-null FUN_L00_002603d0 result skips registration of callback 0x002c31c0; other cases register the draw callback for thrown_moby. Helper 0x002603ec-0x002603f4 returns moby pvars +8 after flag 0x20 check, proving the linked-moby condition without inferring a platform type. --- src/overlays/shared/weapons/decoy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/weapons/decoy.c b/src/overlays/shared/weapons/decoy.c index 422c1c9b13..ee2367f748 100644 --- a/src/overlays/shared/weapons/decoy.c +++ b/src/overlays/shared/weapons/decoy.c @@ -347,7 +347,7 @@ s32 predict_thrown_moby_landing(ThrowVars *throw_vars, s32 mode) __asm__("FUN_L00_002c3af8"); s32 predict_thrown_moby_landing(ThrowVars *throw_vars, struct Moby *thrown_moby, s32 mode) { - Vec4 predicted_position, predicted_velocity, position_scratch, q, ground_probe_position; + enum { LANDING_REQUIRE_MOBY_PVARS_LINK = 0 , DECOY_HELD = 1 , LANDING_SKIP_LINKED_MOBY_DRAW = 2 } ;Vec4 predicted_position, predicted_velocity, position_scratch, q, ground_probe_position; s32 prediction_countdown; s32 found = 0; s32 i; @@ -357,7 +357,7 @@ s32 predict_thrown_moby_landing(ThrowVars *throw_vars, struct Moby *thrown_moby, if (D_L00_0015F5C4 != 0) return 0; qcopy(&position_scratch, &thrown_moby->pos); - if (thrown_moby->state == 1) { + if (thrown_moby->state == DECOY_HELD) { predicted_position.f[0] = fast_cos(fast_add_rotations(-0.36196801066398620605f, fast_arc_tan(hero.facing_x, hero.facing_y))) * @@ -438,13 +438,13 @@ s32 predict_thrown_moby_landing(ThrowVars *throw_vars, struct Moby *thrown_moby, } if (prediction_countdown == 0) return 0; - if (mode == 0) { + if (mode == LANDING_REQUIRE_MOBY_PVARS_LINK) { if (coll_hit.moby == 0) return 0; if (FUN_L00_002603d0(coll_hit.moby) == 0) goto ret0; } - if (mode != 2 || coll_hit.moby == 0 || !FUN_L00_002603d0(coll_hit.moby)) + if (mode != LANDING_SKIP_LINKED_MOBY_DRAW || coll_hit.moby == 0 || !FUN_L00_002603d0(coll_hit.moby)) add_draw_callback(draw_moby_oscillating_textured_quads, thrown_moby); throw_vars->normal.q = coll_hit_normal.q; fast_vec_sub(&position_scratch, &throw_vars->landing, &D_L00_00166DC0); From 013d667c0f5daec3ad3cc535bf955755f5a1bb46 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:21:16 +0000 Subject: [PATCH 0931/1502] decomp: clarify names in shady_salesman_update domain_0_value_1 -> SHADY_SALESMAN_UPDATE_DIALOGUE: In the authoritative shady_salesman_update source (SHA-256 ae7b685ef2b9be7aa402ae44f3ad682cc53a1e50217b610e026e754f6ca692b5), the existing local enum SHADY_SALESMAN_UPDATE_DIALOGUE=1 labels the switch on moby->state. Retail 0031811c loads byte +0x20(s1), and 00318124/00318128 compare it to 1 and branch to 00318190, which calls update_npc_dialogue. Initialization loads 1 into v1 at 00318170 and stores it to the identical byte +0x20(s1) at 0031817c before initialize_npc_dialogue at 00318180. Original Ghidra likewise shows *(undefined1 *)(iVar9+0x20)=1 and cVar5=='\x01' selecting the dialogue update branch. Thus the assignment uses the exact existing moby-state enum domain, not an unrelated equal-valued control constant. --- src/overlays/l05/mobys/shady_salesman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l05/mobys/shady_salesman.c b/src/overlays/l05/mobys/shady_salesman.c index ec1e2355c5..c3f38a7e8f 100644 --- a/src/overlays/l05/mobys/shady_salesman.c +++ b/src/overlays/l05/mobys/shady_salesman.c @@ -105,7 +105,7 @@ void shady_salesman_update(WM *moby) { moby->position[2] += 0.5f; moby->position[2] = probe_ground_height(moby->position, 0, 0.5f); npc_data->ptr20 = (void *)shady_salesman_dialogue_name; - moby->state = 1; + moby->state = SHADY_SALESMAN_UPDATE_DIALOGUE; initialize_npc_dialogue(moby, npc_data); break; case SHADY_SALESMAN_UPDATE_DIALOGUE: From 020075249d2fcc68df557be9642120f2fb5a54f7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:21:17 +0000 Subject: [PATCH 0932/1502] decomp: clarify names in probe_hero_ledge_edge domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0020c770 forms hero base 0x0013f350; 0020c7c4 loads its byte +0x20a4 (0x001413f4), 0020c7c8 loads 1, and 0020c804 compares them. Original Ghidra likewise tests cRam001413f4 == 1. The bound C identifies this exact byte as hero.vehicle_mode, the same selector assigned by enter_hero_vehicle_mode and consumed by exit_hero_vehicle_mode and update_hero_collision_capsule_dimensions using HeroVehicleMode members. The shared include/rnc/hero/hero_state.h domain explicitly supplies HERO_VEHICLE_MODE_CLANK = 1. The taken branch at 0020c80c-0020c838 reduces ledge heights/reach to 0.7/0.725 and forward/drop dimensions to 0.25/-0.4, consistent with the smaller Clank capsule in the same source. Thus reuse the canonical vehicle member, rather than equal-valued HeroStateId or HeroGravityMode members. --- src/overlays/shared/hero/hero_switch_item.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 2a5aa6d945..c2855f7ba2 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -62,7 +62,7 @@ int probe_hero_ledge_edge(Vec4 *ledge_probe_origin, f32 *facing_yaw) { up = 1.5f; reach = 1.15f; min_height = 1.8f; - if (hero.vehicle_mode == 1) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { min_height = 0.7f; drop = -0.4f; fwd = 0.25f; From 58a51635e0c79932f26016b8a47c706262b124d2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:21:17 +0000 Subject: [PATCH 0933/1502] decomp: clarify names in predict_doom_bot_spawner_landing domain_0_value_1 -> THROWN_MOBY_STATE_GROW_TO_QUARTER_SCALE: Retail 002c84b8 loads the byte at thrown_moby (s5)+0x20 and 002c84bc-002c84c0 compares it to 1, selecting the hero-relative launch initialization. The same thrown_moby->state selector in update_doom_bot_spawner uses existing THROWN_MOBY_STATE_GROW_TO_QUARTER_SCALE=1 and grows scale toward pclass->scale*0.25. Both functions receive that same thrown moby, proving the domain and canonical member; this is not a hero-state or mode constant. domain_1_value_0 -> DOOM_LANDING_MODE_REQUIRE_LINKED_MOBY: Retail 002c8458 retains the third parameter in s7; 002c88ec tests it for zero. That branch rejects null coll_hit.moby at 002c88f8-002c8900 and rejects a zero FUN_002603d0 result at 002c8904-002c890c. Checked helper instructions 002603d0-002603fc return zero for null input or missing Moby flags bit 0x20, otherwise load moby->pvars at +0x78 and return its +8 link, matching supplied get_moby_pvars_link source. Thus mode zero requires a linked hit moby. Source caller tries mode 0 before mode 2 when hero.ground_moby passes this same helper. domain_2_value_2 -> DOOM_LANDING_MODE_SKIP_LINKED_MOBY_DRAW_CALLBACK: Retail 002c8914 compares the retained third parameter s7 against 2. For mode 2 only, 002c891c-002c8934 tests coll_hit.moby and its FUN_002603d0 link, branching to 002c8950 when that link is nonzero and bypassing add_draw_callback at 002c8940-002c8948. Other modes, null hit moby or missing link register that callback. Checked helper 002603d0-002603fc returns pvars+8 only with Moby flag 0x20, matching get_moby_pvars_link. This proves linked-moby draw-callback suppression without assuming the callback's rendering content. --- src/overlays/shared/weapons/glove_of_doom_bomb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/weapons/glove_of_doom_bomb.c b/src/overlays/shared/weapons/glove_of_doom_bomb.c index d02f665d06..1ceb6e170e 100644 --- a/src/overlays/shared/weapons/glove_of_doom_bomb.c +++ b/src/overlays/shared/weapons/glove_of_doom_bomb.c @@ -61,7 +61,7 @@ s32 predict_doom_bot_spawner_landing(ThrowVars *throw_vars, s32 mode) __asm__("FUN_L00_002c8440"); s32 predict_doom_bot_spawner_landing(ThrowVars *throw_vars, struct Moby *thrown_moby, s32 mode) { - Vec4 simulated_position, simulated_velocity, position_scratch, q, landing_probe_position; + enum { DOOM_LANDING_MODE_REQUIRE_LINKED_MOBY = 0 , THROWN_MOBY_STATE_GROW_TO_QUARTER_SCALE = 1 , DOOM_LANDING_MODE_SKIP_LINKED_MOBY_DRAW_CALLBACK = 2 } ;Vec4 simulated_position, simulated_velocity, position_scratch, q, landing_probe_position; s32 prediction_timer; s32 found = 0; s32 i; @@ -71,7 +71,7 @@ s32 predict_doom_bot_spawner_landing(ThrowVars *throw_vars, struct Moby *thrown_ if (D_L00_0015F5C4 != 0) return 0; qcopy(&position_scratch, &thrown_moby->pos); - if (thrown_moby->state == 1) { + if (thrown_moby->state == THROWN_MOBY_STATE_GROW_TO_QUARTER_SCALE) { simulated_position.f[0] = fast_cos(fast_add_rotations(-0.36196801066398620605f, fast_arc_tan(hero.facing_x, hero.facing_y))) * @@ -156,13 +156,13 @@ s32 predict_doom_bot_spawner_landing(ThrowVars *throw_vars, struct Moby *thrown_ } if (prediction_timer == 0) return 0; - if (mode == 0) { + if (mode == DOOM_LANDING_MODE_REQUIRE_LINKED_MOBY) { if (coll_hit.moby == 0) return 0; if (get_moby_pvars_link(coll_hit.moby) == 0) goto ret0; } - if (mode != 2 || coll_hit.moby == 0 || !get_moby_pvars_link(coll_hit.moby)) + if (mode != DOOM_LANDING_MODE_SKIP_LINKED_MOBY_DRAW_CALLBACK || coll_hit.moby == 0 || !get_moby_pvars_link(coll_hit.moby)) add_draw_callback(FUN_L00_002c7df8_2c8440, thrown_moby); throw_vars->normal.q = coll_hit_normal.q; fast_vec_sub(&position_scratch, &throw_vars->landing, &g_debug_camera_lui); From 41dc5ee1da33e647021c1520a64ad129fb9c26a3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:21:17 +0000 Subject: [PATCH 0934/1502] decomp: clarify names in update_spark_emitter domain_0_value_1 -> SPARK_EMITTER_AWAITING_ACTIVATION: Authoritative spark_emitter.c SHA-256 451311324968a4c81daa5555ed48114a87b5260ea5f9564243b536988ec1af46 assigns emitter->state=1 when emitter_data->f4 is nonzero. Retail 0x00308d24-0x00308d34 loads pvars+4, selects 1 and stores it to emitter+0x20, the same state byte read at 0x00308cdc. Dispatch 0x00308ce0-0x00308cf8 returns without action for state 1. Supplied activate_listed_spark_emitters source tests class 0x5e8 and state 1, then upon the range test sets state 2 and initializes pvars+0x28. Thus this state waits for activation by that function, rather than representing TRUE or an unrelated state domain. domain_1_value_4 -> SPARK_EMITTER_TIMED_BURSTS: Initialization loads emitter_data->f0 at retail 0x00308d38, selects 4 at 0x00308d40 and stores it to emitter+0x20 through 0x00308d88-0x00308d8c. This is the identical byte read by dispatch 0x00308cdc and compared with 4 at 0x00308d08. That branch reaches 0x00308d9c, where the pvars+0x24 timer selects five emissions and resets a random 60..120 scaled timer (0x00308da0-0x00308dd8), then calls spawn_spark at 0x00308fb0. Authoritative C already names that same-selector case SPARK_EMITTER_TIMED_BURSTS=4; reuse it for this assignment. domain_2_value_3 -> SPARK_EMITTER_RANDOMIZED_SPRAY: Initialization with emitter_data->f0 zero selects 3 at retail 0x00308d44-0x00308d48 and stores it to emitter+0x20 at 0x00308d94-0x00308d98. The same state byte is read at 0x00308cdc and compared with 3 at 0x00308d00, reaching 0x00308fc8. This timer-gated path resets pvars+0x20, selects one or 5..9 emissions and randomizes spark vectors before spawn_spark at 0x003091f4. Authoritative C already names this same-selector case SPARK_EMITTER_RANDOMIZED_SPRAY=3; reuse that established member. domain_3_value_4 -> SPARK_EMITTER_TIMED_BURSTS: After the delayed-action timer at pvars+0x28 completes and cart_burst is called at retail 0x00308d74, 0x00308d7c-0x00308d8c loads pvars+0, chooses 4 when nonzero and stores it to emitter+0x20. Dispatch reads exactly that byte at 0x00308cdc; its value-4 branch at 0x00308d08 reaches the five-spark timer path at 0x00308d9c-0x00308dd8 and emission at 0x00308fb0. This proves the assignment belongs to the existing local SPARK_EMITTER_TIMED_BURSTS=4 state, rather than a request/control mode. domain_4_value_3 -> SPARK_EMITTER_RANDOMIZED_SPRAY: After cart_burst at retail 0x00308d74, a zero pvars+0 selects 3 at 0x00308d80/0x00308d90 and writes emitter+0x20 at 0x00308d98. That exact byte supplies the state dispatch at 0x00308cdc; the value-3 branch at 0x00308d00 reaches the pvars+0x20 timer check at 0x00308fc8, randomized count/vector generation and spawn_spark at 0x003091f4. Authoritative C already declares SPARK_EMITTER_RANDOMIZED_SPRAY=3 for this selector, proving reuse for the post-action state assignment. --- src/overlays/l06/mobys/spark_emitter.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/overlays/l06/mobys/spark_emitter.c b/src/overlays/l06/mobys/spark_emitter.c index db42e6da7e..d70ae28234 100644 --- a/src/overlays/l06/mobys/spark_emitter.c +++ b/src/overlays/l06/mobys/spark_emitter.c @@ -68,6 +68,9 @@ void spark_emitter_update(struct Moby *emitter) { SPARK_EMITTER_RANDOMIZED_SPRAY = 3, SPARK_EMITTER_TIMED_BURSTS = 4 }; + enum { + SPARK_EMITTER_AWAITING_ACTIVATION = 1 + }; SparkData *emitter_data = *(void **)&emitter->pvars; SparkVector position_test_vector; SparkVector rotation_based_spark_vector; @@ -83,20 +86,20 @@ void spark_emitter_update(struct Moby *emitter) { case SPARK_EMITTER_INITIALIZE: euler_rotation_basis(&*(SparkVector *)&emitter->rot_row0, &*(SparkVector *)&emitter->rot); if (emitter_data->f4 != 0) { - emitter->state = 1; + emitter->state = SPARK_EMITTER_AWAITING_ACTIVATION; } else if (emitter_data->f0 != 0) { - emitter->state = 4; + emitter->state = SPARK_EMITTER_TIMED_BURSTS; } else { - emitter->state = 3; + emitter->state = SPARK_EMITTER_RANDOMIZED_SPRAY; } break; case SPARK_EMITTER_DELAYED_ACTION: if (fast_dec_timer(&emitter_data->f28)) { cart_burst(emitter, &*(SparkVector *)&emitter->pos, -1, 0.333f, 13.0f); if (emitter_data->f0 != 0) { - emitter->state = 4; + emitter->state = SPARK_EMITTER_TIMED_BURSTS; } else { - emitter->state = 3; + emitter->state = SPARK_EMITTER_RANDOMIZED_SPRAY; } } break; From 6194139e24f78a15bfc10898d3a0e7aaa4b33b50 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:21:17 +0000 Subject: [PATCH 0935/1502] decomp: clarify names in update_ship_rocket domain_0_value_254 -> MOBY_STATE_PENDING_REMOVAL_AT_OR_ABOVE_BOUNDARY: Retail 003097e4 loads rocket_vars->target, 003097f0 reads its Moby state byte at +0x20, and 003097f4 rejects 0xfe. Checked direct mark_moby_for_removal helper 00274998 loads the address boundary from 0015ffdc; unsigned sltu at 002749a8 and branch 002749ac select 0xfe at 002749bc when the Moby address is at or above that boundary, then sb at 002749c0 writes Moby+0x20. The assigned bounds/collision/timeout removal calls use this helper at 00309a54 and 00309a74. domain_1_value_253 -> MOBY_STATE_PENDING_REMOVAL_BELOW_BOUNDARY: Retail 003097f0 reads target Moby+0x20 and 003097f8-003097fc reject 0xfd before target steering; 0030990c clears the rejected target. Checked direct mark_moby_for_removal helper compares the Moby address unsigned against the boundary loaded from 0015ffdc at 0027499c. sltu at 002749a8 followed by 002749ac selects the below-boundary path, whose delay slot 002749b8 loads 0xfd; 002749c0 stores it into the same Moby state byte +0x20. Thus this is the below-boundary pending-removal state, without assuming the boundary's allocation meaning. --- src/overlays/shared/vehicles/ship_rocket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/vehicles/ship_rocket.c b/src/overlays/shared/vehicles/ship_rocket.c index 85dbee7f99..4e40d7c35e 100644 --- a/src/overlays/shared/vehicles/ship_rocket.c +++ b/src/overlays/shared/vehicles/ship_rocket.c @@ -55,7 +55,7 @@ void ship_rocket_update(struct Moby *moby) __asm__("FUN_L11_003094f8"); /* Moby class 1034 */ void ship_rocket_update(struct Moby *moby) { - Missile_94f8 *rocket_vars = (Missile_94f8 *)moby->pvars; + enum { MOBY_STATE_PENDING_REMOVAL_BELOW_BOUNDARY = 0xfd , MOBY_STATE_PENDING_REMOVAL_AT_OR_ABOVE_BOUNDARY = 0xfe } ;Missile_94f8 *rocket_vars = (Missile_94f8 *)moby->pvars; Vec4f *pos; Vec4 previous_pos, spray, offset, velocity, random; float fraction; @@ -118,7 +118,7 @@ void ship_rocket_update(struct Moby *moby) { } pos = &moby->pos; target = rocket_vars->target; - if (target != 0 && target->state != 0xfe && target->state != 0xfd && + if (target != 0 && target->state != MOBY_STATE_PENDING_REMOVAL_AT_OR_ABOVE_BOUNDARY && target->state != MOBY_STATE_PENDING_REMOVAL_BELOW_BOUNDARY && fast_vec_dist(&rocket_vars->target_pos, &target->pos) < 3.0f) { moby->rot.z = fast_arc_tan(rocket_vars->target->pos.x - moby->pos.x, rocket_vars->target->pos.y - moby->pos.y); From da226abf10f1b75becfa065817f9b87d9d3e6b28 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:21:17 +0000 Subject: [PATCH 0936/1502] decomp: clarify names in update_falling_debris domain_0_value_2 -> FALLING_DEBRIS_BEFORE_BURST: The source assignment debris_moby->state = 2 follows spin/life initialization and falls through to the existing FALLING_DEBRIS_BEFORE_BURST case. Retail 0x002e16cc retains the moby in s3, 0x002e16f4 reads its current state byte at +0x20, and 0x002e16d4/0x002e16f8 dispatch value 2 to 0x002e17a8. Initialization writes that same 2 from s1 to +0x20 at 0x002e17a4. This branch integrates falling motion, emits an optional trail and tests Z < 15.2 before the burst, proving reuse of the existing member for the identical selector domain. domain_1_value_3 -> FALLING_DEBRIS_AFTER_BURST: The source assignment debris_moby->state = 3 follows the complete particle burst loop and selects the existing FALLING_DEBRIS_AFTER_BURST branch on subsequent updates. Retail 0x002e1978-0x002e1980 gates the burst by position Z < 15.2, 0x002e1b68 spawns each particle, and 0x002e1b70-0x002e1b78 completes the loop. 0x002e1b80 loads 3 and 0x002e1b88 writes it to moby+0x20, the same state byte read at 0x002e16f4 and dispatched for 3 at 0x002e171c-0x002e1720. The target 0x002e1b8c continues falling/spinning without another burst until bounds removal, proving the existing member's domain and phase meaning. --- src/overlays/l08/mobys/falling_debris.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l08/mobys/falling_debris.c b/src/overlays/l08/mobys/falling_debris.c index d53259d997..7ed717a9b7 100644 --- a/src/overlays/l08/mobys/falling_debris.c +++ b/src/overlays/l08/mobys/falling_debris.c @@ -78,7 +78,7 @@ void falling_debris_update(Moby_2E2A38 *debris_moby) { random_float_between(-(D_0015ED6C_gp * 1.5707964f), D_0015ED6C_gp * 1.5707964f); debris_data->life = (int)random_float_between((float)scale_game_frames(0x5A), (float)scale_game_frames(0x96)); - debris_moby->state = 2; + debris_moby->state = FALLING_DEBRIS_BEFORE_BURST; case FALLING_DEBRIS_BEFORE_BURST: debris_data->vel[2] -= D_0015ED70 * 10.8f * 0.5f; fast_vec_add(debris_moby->pos, debris_moby->pos, debris_data); @@ -160,7 +160,7 @@ void falling_debris_update(Moby_2E2A38 *debris_moby) { burst_tertiary_frame_count, -1); } - debris_moby->state = 3; + debris_moby->state = FALLING_DEBRIS_AFTER_BURST; } break; case FALLING_DEBRIS_AFTER_BURST: From 018aa254faf0c6daaa735e73834d1e2d4542baff Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:23:20 +0000 Subject: [PATCH 0937/1502] decomp: clarify names in update_triggered_particle_spray_emitter domain_0_value_1 -> EMITTER_WAIT_FOR_TRIGGER: Retail 0x0031513c loads emitter_moby state byte +0x20; 0x00315144 dispatches value 1 to 0x003151ac, which tests pvars trigger +8 and target command +0xBC before activating group state 2. Initialization stores 1 to this exact byte at 0x003151a0. It therefore enters the existing local EMITTER_WAIT_FOR_TRIGGER domain member. domain_1_value_3 -> EMITTER_INACTIVE: Initialization's level/mission table sentinel 0xFF branch at 0x00315194 loads 3 and stores it into emitter state +0x20 at 0x003151a8. On subsequent calls the same byte loaded at 0x0031513c fails all dispatches for states 0, 1 and 2 (0x00315144-0x00315170) and returns without trigger processing or spraying. This proves inactive updater behavior. domain_2_value_3 -> EMITTER_INACTIVE: Retail 0x00315354-0x00315370 compares emitter position z (+0x18) with floor row z (row stride 0x1190, offset +8) and stores 3 into the same state byte +0x20 when below floor. The dispatch at 0x0031513c-0x00315170 performs no update for state 3 on subsequent calls, so this shares EMITTER_INACTIVE with the initialization sentinel path; current-loop completion remains unchanged. --- src/overlays/l05/mobys/triggered_spray_emitter.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/l05/mobys/triggered_spray_emitter.c b/src/overlays/l05/mobys/triggered_spray_emitter.c index 0906a953cb..fa22a1b1e1 100644 --- a/src/overlays/l05/mobys/triggered_spray_emitter.c +++ b/src/overlays/l05/mobys/triggered_spray_emitter.c @@ -57,6 +57,9 @@ void triggered_spray_emitter_update(struct Moby *emitter_moby) { EMITTER_WAIT_FOR_TRIGGER = 1, EMITTER_SPRAY_PARTICLES = 2 }; + enum { + EMITTER_INACTIVE = 3 + }; float v[4]; float particle_velocity[4]; float u[4]; @@ -76,9 +79,9 @@ void triggered_spray_emitter_update(struct Moby *emitter_moby) { switch (state = emitter_moby->state) { case EMITTER_INITIALIZE: if (D_0014C050[current_level_index][emitter_moby->mission] != 0xFF) { - emitter_moby->state = 1; + emitter_moby->state = EMITTER_WAIT_FOR_TRIGGER; } else { - emitter_moby->state = 3; + emitter_moby->state = EMITTER_INACTIVE; } break; case EMITTER_WAIT_FOR_TRIGGER: @@ -120,7 +123,7 @@ void triggered_spray_emitter_update(struct Moby *emitter_moby) { } floor = D_L05_001612D0[emitter_vars->floor].z; if (emitter_moby->pos.z < floor) { - emitter_moby->state = 3; + emitter_moby->state = EMITTER_INACTIVE; } for (i = 0; (float)i < spray_particle_count_limit_per_update_gp; i++) { big = 1; From 7652101a7fff08e2513ed11daa8af74c00cc774a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:23:21 +0000 Subject: [PATCH 0938/1502] decomp: clarify names in build_interpolated_dma_packet domain_0_value_1 -> TEXTURED_GRID_FOG_SOURCE_CAMERA: Retail 0x002a4120 loads textured_grid_fog_source_mode; s4 is set to 1 at 0x002a4100. The beq at 0x002a414c skips stores from draw_parameters +0x20/+0x24/+0x28/+0x2c to camera +0x218/+0x21c/+0x228/+0x22c when this mode equals 1. Thus value 1 retains the camera fog distances and intensities. The same selector at 0x002a4490/0x002a44c0 selects camera fog RGB, proving a shared camera fog source mode rather than generic TRUE. domain_1_value_1 -> TEXTURED_GRID_FOG_SOURCE_CAMERA: Retail 0x002a4490 reloads the same textured_grid_fog_source_mode, and bne at 0x002a44c0 skips the camera RGB override unless it equals s4=1. At 0x002a44c8..0x002a44e4 camera +0x230/+0x234/+0x238 replace draw_parameters +0x30/+0x31/+0x32. Stores 0x002a457c/0x002a4584 emit that selected RGB with fog-color register 0x3d. This is the identical camera-source mode tested at 0x002a414c, so both comparisons use the same semantic constant. --- .../shared/rendering/build_interpolated_dma_packet.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/rendering/build_interpolated_dma_packet.c b/src/overlays/shared/rendering/build_interpolated_dma_packet.c index dbeaaf55ed..ffb5adc485 100644 --- a/src/overlays/shared/rendering/build_interpolated_dma_packet.c +++ b/src/overlays/shared/rendering/build_interpolated_dma_packet.c @@ -124,6 +124,9 @@ void prepare_scaled_table_with_byte_128(char *value_target) { void build_interpolated_dma_packet(QuadDrawArgs *draw_parameters) __asm__("FUN_L02_002a40f0"); void build_interpolated_dma_packet(QuadDrawArgs *draw_parameters) { + enum { + TEXTURED_GRID_FOG_SOURCE_CAMERA = 1 + }; float view_matrix[16]; int *view_setup_dma_packet; int *cursor; @@ -136,7 +139,7 @@ void build_interpolated_dma_packet(QuadDrawArgs *draw_parameters) { textured_grid_saved_fog_far_distance = ((QuadCamera *)level02_camera_view_state)->f21C; textured_grid_saved_fog_near_intensity = ((QuadCamera *)level02_camera_view_state)->f228; textured_grid_saved_fog_far_intensity = ((QuadCamera *)level02_camera_view_state)->f22C; - if (textured_grid_fog_source_mode != 1) { + if (textured_grid_fog_source_mode != TEXTURED_GRID_FOG_SOURCE_CAMERA) { ((QuadCamera *)level02_camera_view_state)->f218 = draw_parameters->f20; ((QuadCamera *)level02_camera_view_state)->f21C = draw_parameters->f24; ((QuadCamera *)level02_camera_view_state)->f228 = draw_parameters->f28; @@ -216,7 +219,7 @@ void build_interpolated_dma_packet(QuadDrawArgs *draw_parameters) { } TEXTURE_REGISTER = (TEXTURE_CURSOR >> 8) | 0x18100000 | 0x580000000; color = draw_parameters->c30 | draw_parameters->c31 << 8 | draw_parameters->c32 << 16; - if (textured_grid_fog_source_mode == 1) { + if (textured_grid_fog_source_mode == TEXTURED_GRID_FOG_SOURCE_CAMERA) { color = ((QuadCamera *)level02_camera_view_state)->c230 | ((QuadCamera *)level02_camera_view_state)->c234 << 8 | ((QuadCamera *)level02_camera_view_state)->c238 << 16; From 0b90d7a164c2f854e37156925a87e2988d99db24 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:23:21 +0000 Subject: [PATCH 0939/1502] decomp: clarify names in batalia_deserter_update domain_0_value_1 -> DESERTER_WAIT_FOR_PLAYER: Bound source SHA-256 c0adc4b121146b339afd001d9885f5455a0f13f03a83498d64514d3044090786 declares DESERTER_WAIT_FOR_PLAYER=1 in the switch on moby->state. Retail 0x00305390 loads 1 and 0x0030539c stores it to 0x20(s1), the same state byte loaded at 0x003052ec and dispatched to 0x003053bc when equal to 1 at 0x003052f4. That branch waits for player distance below 8 before transitioning. Original Ghidra likewise writes moby+0x20=1 after initialization and tests that byte for the player-distance branch, proving canonical member reuse in the identical selector domain. domain_1_value_2 -> DESERTER_UPDATE_DIALOGUE: Bound source declares DESERTER_UPDATE_DIALOGUE=2 in the switch on moby->state. Retail 0x003053f0 loads 2 and 0x003053f8 writes it to 0x20(s1) after the player-distance threshold and persistent-clear call. The same byte loaded at 0x003052ec is compared with 2 at 0x00305300/0x00305314, selecting 0x003053fc, whose branch updates NPC dialogue at 0x00305484 and its camera at 0x00305498, then unlocks/saves/removes when dialogue completes. Original Ghidra confirms both the write and branch data flow; this reuses the existing constant for the identical moby-state selector, rather than inferring equality with another domain. --- src/overlays/l08/mobys/batalia_deserter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l08/mobys/batalia_deserter.c b/src/overlays/l08/mobys/batalia_deserter.c index 4e3bcb3f30..56ed495da7 100644 --- a/src/overlays/l08/mobys/batalia_deserter.c +++ b/src/overlays/l08/mobys/batalia_deserter.c @@ -186,14 +186,14 @@ void batalia_deserter_update(WM *moby) { } deserter_data->f2C = 4.0f; deserter_data->p40 = (void *)batalia_deserter_name_text; - moby->state = 1; + moby->state = DESERTER_WAIT_FOR_PLAYER; if (deserter_data->i64 >= 0) initialize_npc_dialogue(moby, (char *)deserter_data + 0x20); break; case DESERTER_WAIT_FOR_PLAYER: if (vector_distance(moby->position, (char *)&D_0013E633_watch + 0xE9D) < 8.0f) { jet_clear_persistent(((unsigned char *)moby)[0xB0]); - moby->state = 2; + moby->state = DESERTER_UPDATE_DIALOGUE; } break; case DESERTER_UPDATE_DIALOGUE: From 1a1a848959d88e8356c78af78db418e4c57dc0fd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:23:21 +0000 Subject: [PATCH 0940/1502] decomp: clarify names in update_puffoid_damage_and_path_goal domain_0_value_11 -> PUFFOID_STATE_DEATH_KNOCKBACK: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 003159c0-003159c8 excludes state 11 from carrier-height removal; puffoid_update's named state 11 processes death knockback then explosion/removal. domain_10_value_3 -> HIT_RESPONSE_KNOCKBACK: Retail 00315b0c returns the hit-response selector used by switch(kind); 00315b30-00315b58 overrides it to 3 for hitter class 0x47. Existing local enum HIT_RESPONSE_KNOCKBACK=3 labels the same selector's branch at 00315bd8-00315c8c, which starts knockback and assigns Puffoid states 9/17. Reuse that exact response member. domain_11_value_1 -> HIT_RESPONSE_DEATH: Retail 00315b34-00315b5c subtracts damage from private HP and overrides the returned hit-response selector to 1 when HP <= 0. Existing local HIT_RESPONSE_DEATH=1 labels this same switch(kind) domain; its branch 00315c90-00315d70 starts death knockback, assigns Puffoid death states 11/18 and calls death processing. domain_12_value_12 -> PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 00315c6c-00315c80 compares the Puffoid state against 12 to choose ordinary state 9 versus carrier state 17; 12 is the established first carrier-state boundary. domain_13_value_9 -> PUFFOID_STATE_KNOCKBACK: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 00315bd8-00315c64 prepares hit-vector knockback arc/motion; 00315c78/00315c80 writes state 9 for states below carrier boundary 12, matching puffoid_update's knockback branch. domain_14_value_17 -> PUFFOID_STATE_CARRIER_KNOCKBACK: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 00315c70-00315c80 writes state 17 for the carrier side of the state-12 boundary after knockback setup, matching puffoid_update's carrier-following knockback branch. domain_15_value_12 -> PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 00315d44-00315d58 uses state 12 as the boundary between ordinary death state 11 and carrier death state 18; puffoid_update establishes 12 as the first carrier state. domain_16_value_11 -> PUFFOID_STATE_DEATH_KNOCKBACK: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 00315c90-00315d3c prepares death knockback and clears flag 0x1000; 00315d50/00315d58 writes state 11 below carrier boundary, then calls death processing at 00315d6c. domain_17_value_18 -> PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 00315d48-00315d58 writes state 18 on the carrier side after death knockback setup, matching puffoid_update's carrier-following death branch. domain_18_value_2 -> PUFFOID_STATE_IDLE: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 00315d98-00315da8 tests state 2 with an active private timer before transitioning to state 10; puffoid_update's named state 2 is idle and chooses chase or wander. domain_19_value_3 -> PUFFOID_STATE_WANDER_NEAR_HOME: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 00315dac-00315dc0 tests state 3 and animation flag 2 before transitioning to state 10; puffoid_update's named state 3 moves toward the randomized home-relative wander goal. domain_1_value_9 -> PUFFOID_STATE_KNOCKBACK: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 003159cc-003159d0 excludes state 9 from carrier-height removal; puffoid_update's named state 9 advances knockback motion and handles landing. domain_20_value_10 -> PUFFOID_STATE_REPOSITION_AND_FACE_TARGET: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 00315dc8-00315dd4 writes state 10 when the timer interrupts idle/completed wandering; puffoid_update's named state 10 moves toward the path goal or faces the target when crossing is blocked. domain_21_value_1 -> PUFFOID_STATE_WAIT_FOR_HOME_JUMP: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 00315ea0-00315ebc tests state 1 to use secondary path+0x20 rather than current position for goal reach checks; puffoid_update's named state 1 faces that home jump endpoint and may launch toward it. domain_2_value_18 -> PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 003159d4-003159d8 excludes state 18; puffoid_update's named state 18 follows the carrier while processing death knockback and removal. domain_3_value_17 -> PUFFOID_STATE_CARRIER_KNOCKBACK: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 003159dc-003159e0 excludes state 17; puffoid_update's named state 17 follows the carrier and advances ordinary knockback. domain_4_value_0 -> PUFFOID_STATE_INITIALIZE: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 003159e8 excludes state zero from carrier-height removal; puffoid_update's named zero branch initializes private motion fields and chooses startup state. domain_5_value_12 -> PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 003159e4-003159f0 excludes state 12 from carrier-height removal and routes it to carrier visibility checks; puffoid_update names 12 as waiting for carrier jump. domain_6_value_13 -> PUFFOID_STATE_CARRIER_JUMP: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 003159f4-003159f8 excludes state 13 from carrier-height removal; puffoid_update's named state 13 integrates jump velocity plus carrier movement. domain_7_value_12 -> PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 00315a48-00315a60 selects state 12 for carrier lifecycle/visibility handling; puffoid_update's same state waits until carrier-relative jump conditions permit launch. domain_9_value_11 -> PUFFOID_STATE_DEATH_KNOCKBACK: The supplied puffoid_update passes this same Moby to update_puffoid_damage_and_path_goal before switching on moby->state; retail keeps that pointer in s2 and accesses its state byte at +0x20. Thus this is the Puffoid state domain established in puffoid_update, not the hero state domain. 00315b24-00315b2c skips additional hit processing when state is 11, the existing death-knockback state consumed by puffoid_update. --- src/overlays/l11/mobys/puffoid.c | 45 ++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/src/overlays/l11/mobys/puffoid.c b/src/overlays/l11/mobys/puffoid.c index 8a88b3ce46..e8521c6072 100644 --- a/src/overlays/l11/mobys/puffoid.c +++ b/src/overlays/l11/mobys/puffoid.c @@ -753,6 +753,19 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { HIT_RESPONSE_NON_KNOCKBACK_REACTION_ALTERNATE = 10, HIT_RESPONSE_COOLDOWN_NO_KNOCKBACK = 11 }; + enum { + PUFFOID_STATE_INITIALIZE = 0, + PUFFOID_STATE_WAIT_FOR_HOME_JUMP = 1, + PUFFOID_STATE_IDLE = 2, + PUFFOID_STATE_WANDER_NEAR_HOME = 3, + PUFFOID_STATE_KNOCKBACK = 9, + PUFFOID_STATE_REPOSITION_AND_FACE_TARGET = 0xA, + PUFFOID_STATE_DEATH_KNOCKBACK = 0xB, + PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP = 0xC, + PUFFOID_STATE_CARRIER_JUMP = 0xD, + PUFFOID_STATE_CARRIER_KNOCKBACK = 0x11, + PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK = 0x12 + }; struct L11PatrolVars *patrol_vars = (struct L11PatrolVars *)moby->pvars; Vec4 position_scratch; s32 hit_processing_status; @@ -762,15 +775,15 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { moby->scale = moby->pclass->scale * D_L11_001622CC; patrol_vars->unk1A4 = l11_puffoid_horizontal_speed_limit * frame_time; - if (patrol_vars->carrier != -1 && moby->state != 0xB && moby->state != 9 && - moby->state != 0x12 && moby->state != 0x11 && moby->state != 0 && moby->state != 0xC && - moby->state != 0xD) { + if (patrol_vars->carrier != -1 && moby->state != PUFFOID_STATE_DEATH_KNOCKBACK && moby->state != PUFFOID_STATE_KNOCKBACK && + moby->state != PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK && moby->state != PUFFOID_STATE_CARRIER_KNOCKBACK && moby->state != PUFFOID_STATE_INITIALIZE && moby->state != PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP && + moby->state != PUFFOID_STATE_CARRIER_JUMP) { if (moby->pos.z < ((struct Moby *)D_L11_0015FFD8)[patrol_vars->carrier].pos.z + 0.5f) { spawn_color_swapped_explosion_burst(moby, &moby->pos, -1, 0.5f, 10.0f); mark_moby_for_removal(moby); } } - if (moby->state == 0xC && patrol_vars->carrier != -1) { + if (moby->state == PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP && patrol_vars->carrier != -1) { if (is_moby_in_state_five(&((struct Moby *)D_L11_0015FFD8)[patrol_vars->carrier]) != 0 && moby->visible == 0) { mark_moby_for_removal(moby); @@ -787,13 +800,13 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { { s32 kind = resolve_moby_hit_response( moby, hit, &patrol_vars->hp, 0, &hit_processing_status, &dmg, 0, 4); - if (hit_processing_status != 1 && moby->state != 0xB) { + if (hit_processing_status != 1 && moby->state != PUFFOID_STATE_DEATH_KNOCKBACK) { patrol_vars->hp -= dmg; if (hit->moby->oclass == 0x47) { - kind = 3; + kind = HIT_RESPONSE_KNOCKBACK; } if (patrol_vars->hp <= 0.0f) { - kind = 1; + kind = HIT_RESPONSE_DEATH; } patrol_vars->unk140 = truncate_float_to_s32(512.0f); patrol_vars->unk148 = 0.2f; @@ -824,10 +837,10 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { trooper_knockback_arc( &position_scratch, &yaw, &patrol_vars->unk138, &patrol_vars->unk13C); trooper_start_knockback(moby, patrol_vars->unk120, 3, 1, 0, yaw); - if (moby->state < 0xC) { - moby->state = 9; + if (moby->state < PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP) { + moby->state = PUFFOID_STATE_KNOCKBACK; } else { - moby->state = 0x11; + moby->state = PUFFOID_STATE_CARRIER_KNOCKBACK; } patrol_vars->unk117 = 0x78; break; @@ -846,10 +859,10 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { trooper_knockback_arc( &position_scratch, &yaw, &patrol_vars->unk138, &patrol_vars->unk13C); trooper_start_knockback(moby, patrol_vars->unk120, 3, 1, 0, yaw); - if (moby->state < 0xC) { - moby->state = 0xB; + if (moby->state < PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP) { + moby->state = PUFFOID_STATE_DEATH_KNOCKBACK; } else { - moby->state = 0x12; + moby->state = PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK; } patrol_vars->unk117 = 0xF0; FUN_L00_00257470(moby, 0, -1); @@ -864,8 +877,8 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { moby->hit_slot = 0xFF; trooper_anim_finish(moby, patrol_vars->move); if (patrol_vars->timer != 0) { - if (moby->state == 2 || (moby->state == 3 && (moby->anim_flags & 2))) { - moby->state = 0xA; + if (moby->state == PUFFOID_STATE_IDLE || (moby->state == PUFFOID_STATE_WANDER_NEAR_HOME && (moby->anim_flags & 2))) { + moby->state = PUFFOID_STATE_REPOSITION_AND_FACE_TARGET; if (moby->prev_seq != 2) { FUN_00212f90(moby, 2, 0, scale_game_frames(10)); } @@ -886,7 +899,7 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { if (FUN_L00_0025ff38( moby, &patrol_vars->goal, 0, 0, path + 0x10, *(s32 *)path, patrol_vars->reach) != 2) { Vec4f *goal_check_position; - if (moby->state == 1) { + if (moby->state == PUFFOID_STATE_WAIT_FOR_HOME_JUMP) { goal_check_position = (Vec4f *)((char *)l11_paths[patrol_vars->path2_index] + 0x20); } else { goal_check_position = &moby->pos; From 5779f4a2b4fcfa848d164405b510e3fa570a41ab Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:23:21 +0000 Subject: [PATCH 0941/1502] decomp: clarify names in follow_camera_springs domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x002e5ae8-0x002e5af4 forms hero base 0x0013f350 and loads its +0x20a4 byte (0x001413f4), identified by the authoritative C as hero.vehicle_mode. At 0x002e5aec/0x002e5af8 this byte is compared with 2; its equal branch scales view+0x20 by 3.0f at 0x002e5b04-0x002e5b14 before adding hero_pos to form the collision origin at 0x002e5b60-0x002e5b70. This is the HeroVehicleMode selector, whose supplied canonical header include/rnc/hero/hero_state.h defines HERO_VEHICLE_MODE_GIANT_CLANK=2. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: The a0 byte loaded at retail 0x002e5af4 from hero+0x20a4 (0x001413f4), identified in the authoritative C as hero.vehicle_mode, is retained for the second comparison at 0x002e5b20 against v0=1 from 0x002e5afc. Its equal branch scales view+0x20 by 0.4f at 0x002e5b28-0x002e5b3c, then adds hero_pos for the collision origin. It is the same HeroVehicleMode selector as the preceding comparison, and the supplied canonical include/rnc/hero/hero_state.h defines HERO_VEHICLE_MODE_CLANK=1. --- src/overlays/shared/camera/follow_camera_springs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/camera/follow_camera_springs.c b/src/overlays/shared/camera/follow_camera_springs.c index 2ebf8f36a1..7bd90f3d87 100644 --- a/src/overlays/shared/camera/follow_camera_springs.c +++ b/src/overlays/shared/camera/follow_camera_springs.c @@ -1401,9 +1401,9 @@ void follow_camera_springs(void *camera_moby) { fast_vec_add(camera_state->follow.look_target, look, blended_focus_or_collision_origin); } follow_camera_transition(camera_moby, look); - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { scale_vector_xyz(look, view + 0x20, 3.0f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { scale_vector_xyz(look, view + 0x20, 0.4f); } else { scale_vector_xyz(look, view + 0x20, 0.5f); From dbd4b18785db83845112958c9e5ccb33d52015c8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:23:21 +0000 Subject: [PATCH 0942/1502] decomp: clarify names in blarg_turret_update domain_0_value_1 -> BLARG_TURRET_STATE_WAIT_FOR_TARGET: Initialization ends at 0x002b4288-0x002b428c by loading 1, then 0x002b4724 stores it at s1+0x20. This is the same turret_moby->state byte read for the switch at 0x002b4218; existing case 1 waits for target angle, distance and volume eligibility at 0x002b4290-0x002b4310. domain_1_value_3 -> BLARG_TURRET_STATE_TRACK_TARGET: After target angle < pi/2, distance < 20 and volume eligibility pass, 0x002b4360-0x002b4364 stores 3 at s1+0x20, the turret switch selector. Existing case BLARG_TURRET_STATE_TRACK_TARGET = 3 computes clamped target bearing, approaches turret yaw and calls projectile firing at 0x002b44f8-0x002b45a4. domain_2_value_5 -> BLARG_TURRET_STATE_DESTRUCTION_DELAY: The wait branch detects absent, wrong-class or unusable gun at 0x002b43a0-0x002b43d0, sets data+0x64 to 1.0 and loads state 5 at 0x002b4400-0x002b4410 for store to turret+0x20. Existing case 5 decrements that countdown before entering destruction, proving the same BLARG_TURRET_STATE_DESTRUCTION_DELAY domain. domain_3_value_1 -> BLARG_TURRET_STATE_WAIT_FOR_TARGET: Tracking fails angle, 22-unit distance or volume eligibility at 0x002b443c-0x002b44a4, resets animation and loads 1 at 0x002b44cc-0x002b44d0 for store to turret state +0x20 at 0x002b4724. That same selector dispatches existing BLARG_TURRET_STATE_WAIT_FOR_TARGET = 1, which waits for reacquisition. domain_4_value_5 -> BLARG_TURRET_STATE_DESTRUCTION_DELAY: Within tracking, gun checks at 0x002b45a8-0x002b45d8 lead to resetting animation, storing 1.0 at data+0x64 and loading state 5 at 0x002b4608-0x002b4618. The store at 0x002b4724 targets the turret switch byte; existing case 5 consumes this countdown as BLARG_TURRET_STATE_DESTRUCTION_DELAY. domain_5_value_4 -> BLARG_TURRET_STATE_DESTROY: In existing destruction-delay case, 0x002b46fc-0x002b471c decrements data+0x64 and tests <= 0; 0x002b4720-0x002b4724 stores 4 to the same turret+0x20 switch selector. Existing BLARG_TURRET_STATE_DESTROY = 4 branch at 0x002b461c-0x002b46ac creates effects, marks removal and deletes the turret. --- src/overlays/l13/mobys/blarg_turret.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l13/mobys/blarg_turret.c b/src/overlays/l13/mobys/blarg_turret.c index f1adafa321..7c46fdf515 100644 --- a/src/overlays/l13/mobys/blarg_turret.c +++ b/src/overlays/l13/mobys/blarg_turret.c @@ -133,7 +133,7 @@ void blarg_turret_update(Moby_2B5368 *turret_moby) { if (turret_moby->b53 != 0) { blend_moby_animation(turret_moby, 0, 0, 10); } - turret_moby->state = 1; + turret_moby->state = BLARG_TURRET_STATE_WAIT_FOR_TARGET; break; case BLARG_TURRET_STATE_WAIT_FOR_TARGET: target_yaw_scratch = @@ -150,7 +150,7 @@ void blarg_turret_update(Moby_2B5368 *turret_moby) { blend_moby_animation( turret_moby, 1, animation_start_frame, random_int_between(7, 13)); } - turret_moby->state = 3; + turret_moby->state = BLARG_TURRET_STATE_TRACK_TARGET; } approach_angle(&turret_moby->rot.z, data->f54, @@ -165,7 +165,7 @@ void blarg_turret_update(Moby_2B5368 *turret_moby) { blend_moby_animation(turret_moby, 0, 0, random_int_between(7, 13)); } data->f64 = 1.0f; - turret_moby->state = 5; + turret_moby->state = BLARG_TURRET_STATE_DESTRUCTION_DELAY; } break; case BLARG_TURRET_STATE_TRACK_TARGET: @@ -180,7 +180,7 @@ void blarg_turret_update(Moby_2B5368 *turret_moby) { if (turret_moby->b53 != 0) { blend_moby_animation(turret_moby, 0, 0, random_int_between(7, 13)); } - turret_moby->state = 1; + turret_moby->state = BLARG_TURRET_STATE_WAIT_FOR_TARGET; } else { float yaw_offset_limit_radians; approach_value(&data->f68, 20.0f, frame_time * 6.0f); @@ -209,7 +209,7 @@ void blarg_turret_update(Moby_2B5368 *turret_moby) { blend_moby_animation(turret_moby, 0, 0, random_int_between(7, 13)); } data->f64 = 1.0f; - turret_moby->state = 5; + turret_moby->state = BLARG_TURRET_STATE_DESTRUCTION_DELAY; } } break; @@ -247,7 +247,7 @@ void blarg_turret_update(Moby_2B5368 *turret_moby) { frame_time * 25.132742f); data->f64 -= 1.0f; if (data->f64 <= 0.0f) { - turret_moby->state = 4; + turret_moby->state = BLARG_TURRET_STATE_DESTROY; } break; } From 264cda516f2566be697061c95fa03046e2d7f1f0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:23:21 +0000 Subject: [PATCH 0943/1502] decomp: clarify names in background_ship_2_update domain_0_value_1 -> BACKGROUND_SHIP_2_FOLLOW_PATH: Authoritative source src/overlays/shared/vehicles/background_ship_2.c SHA-256 9dd595a9f61126776e9f9039ce7399454f512ae2549cd75bafd222e771d6160c defines BACKGROUND_SHIP_2_FOLLOW_PATH=1 for the switch on MOBY(moby)->state. Retail 0x002ece74 loads that same moby byte +0x20, and 0x002ece78 branches on 1 into the path-following handler at 0x002ecfa8. Initialization copies the first path position, sets progress and stores s1=1 to the identical byte at 0x002ecf80. Original Ghidra confirms this store after initialization and the state-1 branch advances/wraps progress and samples position/rotation. Therefore the assignment uses the existing FOLLOW_PATH member of this exact state domain. domain_1_value_2 -> BACKGROUND_SHIP_2_REMOVE: The authoritative function-local enum defines BACKGROUND_SHIP_2_REMOVE=2 in the switch on MOBY(moby)->state. Retail 0x002ed128-0x002ed148 tests the find_moby_hit result and its positive +0x2C float, then 0x002ed150 loads 2 and 0x002ed158 stores it to moby byte +0x20, the same selector loaded at 0x002ece74. Retail dispatch 0x002ece88/0x002ece9c sends state 2 to 0x002ed15c, whose counter/effect work ends in removal at 0x002ed33c-0x002ed340. Original Ghidra confirms the same state assignment and removal branch. Reuse BACKGROUND_SHIP_2_REMOVE for the transition into that existing case. --- src/overlays/shared/vehicles/background_ship_2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/vehicles/background_ship_2.c b/src/overlays/shared/vehicles/background_ship_2.c index e7956cdbc4..2db701114b 100644 --- a/src/overlays/shared/vehicles/background_ship_2.c +++ b/src/overlays/shared/vehicles/background_ship_2.c @@ -253,7 +253,7 @@ void background_ship_2_update(char *moby) { qcopy(&MOBY(moby)->pos, D_L02_001B0AB0[moby_data->unk60] + 0x10); moby_data->unk68 = random_angle_radians(); moby_data->unk6C = invalid_index; - MOBY(moby)->state = 1; + MOBY(moby)->state = BACKGROUND_SHIP_2_FOLLOW_PATH; MOBY(moby)->flags |= 0x10; moby_data->unk64 = moby_data->unk74 * (float)*(int *)path; break; @@ -300,7 +300,7 @@ void background_ship_2_update(char *moby) { flag = 1; } if (flag) { - MOBY(moby)->state = 2; + MOBY(moby)->state = BACKGROUND_SHIP_2_REMOVE; } break; case BACKGROUND_SHIP_2_REMOVE: From 00fc73dc8d65798bbf5a3c365bdb841671a74a8f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:25:05 +0000 Subject: [PATCH 0944/1502] decomp: clarify names in integrate_hero_motion_with_collisions domain_0_value_34 -> HERO_STATE_RISE_THEN_FALL_WITH_AIRBORNE_HIT_QUERY: Source forms player from &hero.motion.pos minus 0x80, yielding the hero base. Retail 0x002413F0 forms position 0x0013F3D0, 0x00241420 subtracts 0x80 to hero 0x0013F350, and 0x00241438 loads +0x2084 (0x001413D4), the source L16MovementPlayer.state current-state selector, separately from mode +0x208C loaded at 0x0024144C. Retail 0x0024143C-0x00241440 compares this current-state ID with 0x22 (34) and enters gravity-relative velocity limiting and the downward gravity_limit clamp at 0x00241450-0x002414E8. The supplied shared HeroStateId domain in include/rnc/hero/hero_state.h canonically names current-state 34 HERO_STATE_RISE_THEN_FALL_WITH_AIRBORNE_HIT_QUERY; this movement consumer reuses that member without claiming to implement the entire state lifecycle. domain_1_value_20 -> HERO_STATE_WRENCH_SLAM: The source player is the hero base recovered from &hero.motion.pos minus 0x80. Retail 0x00241420 and 0x00241438 load hero+0x2084 at 0x001413D4, corresponding to source player->state, while the separate player->mode field is loaded from +0x208C at 0x0024144C. After comparing state 34, retail 0x00241444 loads 0x14 (20) and 0x00241448 dispatches this same current-state value into the shared gravity-relative speed limiting arm and negative gravity_limit clamp at 0x00241450-0x002414E8. This is the current-state domain named by shared enum HeroStateId in include/rnc/hero/hero_state.h, whose canonical value-20 member is HERO_STATE_WRENCH_SLAM; reuse that existing member for this partial movement handler. --- src/overlays/l05/hero/apply_hero_ground_material_effects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l05/hero/apply_hero_ground_material_effects.c b/src/overlays/l05/hero/apply_hero_ground_material_effects.c index 26fbfd2881..6f82a6f23a 100644 --- a/src/overlays/l05/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l05/hero/apply_hero_ground_material_effects.c @@ -550,7 +550,7 @@ void integrate_hero_motion_with_collisions(void) { player = (L16MovementPlayer *)((char *)position - 0x80); update_hero_attachment(player->physics_mode, (char *)position + 0x70, (char *)position + 0x10); /* Limit the velocity by state and mode. Inside an arm `position` moves on to the velocity; it is formed again below. */ - if (player->state == 34 || player->state == 20) { + if (player->state == HERO_STATE_RISE_THEN_FALL_WITH_AIRBORNE_HIT_QUERY || player->state == HERO_STATE_WRENCH_SLAM) { float limit; float *limited_velocity; From b9bbf5a4f93495e0ea59dececcd0a11a49cf27f3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:25:05 +0000 Subject: [PATCH 0945/1502] decomp: clarify names in update_homing_projectile domain_0_value_1 -> PROJECTILE_STATE_IMPACT: In the authoritative update_homing_projectile source, impact_state is initialized to 1 and later assigned to moby[0x20] after an accepted collision. Original retail Ghidra confirms the final state-byte store of 1. Retail 0x002a4384 loads s6 with 1; 0x002a439c and 0x002a43fc copy it into query active/enabled fields, and 0x002a444c stores the same s6 into 0x20(s2) after hit-position copy at 0x002a4440-0x002a4444 and player/owner filtering at 0x002a4418-0x002a4428. Dispatch reads this same moby state at 0x002a3f78, compares 1 at 0x002a3f84-0x002a3f88, then reaches impact effect creation at 0x002a44f8 and removal at 0x002a4500. This proves reuse of the existing local PROJECTILE_STATE_IMPACT = 1 in the projectile-state domain. --- src/overlays/l16/mobys/rocket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/rocket.c b/src/overlays/l16/mobys/rocket.c index f4774fe424..0f0cfa5e6b 100644 --- a/src/overlays/l16/mobys/rocket.c +++ b/src/overlays/l16/mobys/rocket.c @@ -172,7 +172,7 @@ void homing_projectile_update(unsigned char *moby) { { int impact_state; query.flags = 0x830000; - impact_state = 1; + impact_state = PROJECTILE_STATE_IMPACT; query.owner = moby; query.scale = 1.0f; query.active = impact_state; From ef01bf3f40e9d60ce321492de66e0793c51711c5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:25:06 +0000 Subject: [PATCH 0946/1502] decomp: clarify names in update_rocket_tank_damage_and_aim domain_0_value_1 -> HIT_REACTION_NO_DAMAGE: Authoritative source binds hit_reaction_status to hit_reaction's fifth output and skips health subtraction when it equals 1. Assigned retail 0x002f80a0 passes sp+0x30 as t0; 0x002f80b4-0x002f80bc loads and compares it with 1. Checked level-18 helper 0x0025c7c8 retains t0 in s3. Its no-hit path at 0x0025c8c8-0x0025c8ec writes status 1 through s3, and 0x0025c8f0-0x0025c8f8 zeros the damage output retained from t1. The flag-rejection path at 0x0025cc84-0x0025cc98 likewise writes status 1 and zeros hit-record damage +0x2c, which 0x0025ccc0-0x0025ccc4 copies to the damage output. Thus status 1 denotes no damage; it is separate from the hero enum domains. --- src/overlays/l18/mobys/rocket_tank.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l18/mobys/rocket_tank.c b/src/overlays/l18/mobys/rocket_tank.c index 1b4c342e23..7fcb94f99c 100644 --- a/src/overlays/l18/mobys/rocket_tank.c +++ b/src/overlays/l18/mobys/rocket_tank.c @@ -264,6 +264,9 @@ extern void func_L00_0025F4A8_alt(void *, int) __asm__("FUN_L00_0025e450"); void update_rocket_tank_damage_and_aim(void *mv) { + enum { + HIT_REACTION_NO_DAMAGE = 1 + }; unsigned char *moby_bytes = mv; char *tank_data = *(char **)(moby_bytes + 0x78); int r; @@ -278,7 +281,7 @@ void update_rocket_tank_damage_and_aim(void *mv) { &damage_amount, 0, 4); - if (hit_reaction_status != 1 && moby_bytes[0x20] != 0) { + if (hit_reaction_status != HIT_REACTION_NO_DAMAGE && moby_bytes[0x20] != 0) { float remaining_health = *(float *)(tank_data + 0x20) - damage_amount; *(float *)(tank_data + 0x20) = remaining_health; if (remaining_health > 0.0f) { From 49600c2610ac6ca7c05316f986216bb944762ce1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:26:41 +0000 Subject: [PATCH 0947/1502] decomp: clarify names in update_countdown_sequence domain_0_value_3 -> DIALOGUE_PHASE_READY_TO_CONTINUE: Retail 0x301cf8-0x301d08 reads the phase halfword, compares 3 and calls 0x274080. The authoritative snapshot src/overlays/l06/mobys/countdown_sequence.c (SHA-256 ba1f67c1fd2609d17aa4a203aaf0219f98c585c779e12091844b7756def03cd4) and original retail Ghidra both compare dialogue_playback_phase at 0x0015172A with 3 before calling continue_audio_stream_if_ready. Checked level-06 helper 0x274090-0x2740c0 sets s0=0x1516d0, loads stream handle +0x50, checks the halfword +0x5a (0x15172a) equals 3, calls continuation with that handle at 0x2740ac, then stores phase 4. Supplied continue_audio_stream_if_ready source corroborates secondary stream state 3 enabling snd_continue_vag_stream. This proves a dialogue playback phase ready for continuation, separate from hero and moby state enums. domain_1_value_3 -> DIALOGUE_PHASE_READY_TO_CONTINUE: Retail 0x301fd4-0x301fe4 reads the same phase halfword at the scaled 1800-frame event, compares 3 and calls 0x274080. The authoritative snapshot src/overlays/l06/mobys/countdown_sequence.c (SHA-256 ba1f67c1fd2609d17aa4a203aaf0219f98c585c779e12091844b7756def03cd4) and original retail Ghidra both compare dialogue_playback_phase at 0x0015172A with 3 before calling continue_audio_stream_if_ready. Checked level-06 helper 0x274090-0x2740c0 sets s0=0x1516d0, loads stream handle +0x50, checks the halfword +0x5a (0x15172a) equals 3, calls continuation with that handle at 0x2740ac, then stores phase 4. Supplied continue_audio_stream_if_ready source corroborates secondary stream state 3 enabling snd_continue_vag_stream. This proves a dialogue playback phase ready for continuation, separate from hero and moby state enums. domain_2_value_3 -> DIALOGUE_PHASE_READY_TO_CONTINUE: Retail 0x302030-0x302040 reads the same phase halfword at the scaled 300-frame event, compares 3 and calls 0x274080. The authoritative snapshot src/overlays/l06/mobys/countdown_sequence.c (SHA-256 ba1f67c1fd2609d17aa4a203aaf0219f98c585c779e12091844b7756def03cd4) and original retail Ghidra both compare dialogue_playback_phase at 0x0015172A with 3 before calling continue_audio_stream_if_ready. Checked level-06 helper 0x274090-0x2740c0 sets s0=0x1516d0, loads stream handle +0x50, checks the halfword +0x5a (0x15172a) equals 3, calls continuation with that handle at 0x2740ac, then stores phase 4. Supplied continue_audio_stream_if_ready source corroborates secondary stream state 3 enabling snd_continue_vag_stream. This proves a dialogue playback phase ready for continuation, separate from hero and moby state enums. --- src/overlays/l06/mobys/countdown_sequence.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l06/mobys/countdown_sequence.c b/src/overlays/l06/mobys/countdown_sequence.c index 07ebc6d2e0..9cb60945bd 100644 --- a/src/overlays/l06/mobys/countdown_sequence.c +++ b/src/overlays/l06/mobys/countdown_sequence.c @@ -198,7 +198,7 @@ void countdown_sequence_update(unsigned char *moby) { ADVANCE_CAMERA_ALONG_PATH = 3, UPDATE_POST_PATH_TIMED_EVENTS = 4, RAMP_SHARED_VALUE_AFTER_DELAY = 5 - }; + } ; enum { DIALOGUE_PHASE_READY_TO_CONTINUE = 3}; CountdownSequenceVars *moby_vars = (CountdownSequenceVars *)MOBY(moby)->pvars; float va[4] __attribute__((aligned(16))); float vc[4] __attribute__((aligned(16))); @@ -234,7 +234,7 @@ void countdown_sequence_update(unsigned char *moby) { moby[0x20] = 3; moby_vars->unkB0 = 1; request_music_track(6, 9); - if (*(short *)dialogue_playback_phase == 3) + if (*(short *)dialogue_playback_phase == DIALOGUE_PHASE_READY_TO_CONTINUE) continue_audio_stream_if_ready(); set_moby_list_state_17(moby_vars->unk10); set_moby_list_state_15(moby_vars->unk14); @@ -305,7 +305,7 @@ void countdown_sequence_update(unsigned char *moby) { char *q; x = scale_game_frames(0x708); if (moby_vars->timer_B4 == x) { - if (*(short *)dialogue_playback_phase == 3) + if (*(short *)dialogue_playback_phase == DIALOGUE_PHASE_READY_TO_CONTINUE) continue_audio_stream_if_ready(); } else { x = scale_game_frames(900); @@ -313,7 +313,7 @@ void countdown_sequence_update(unsigned char *moby) { select_localized_moby_voice_line((struct Moby *)moby, 2); else { x = scale_game_frames(300); - if (moby_vars->timer_B4 == x && *(short *)dialogue_playback_phase == 3) + if (moby_vars->timer_B4 == x && *(short *)dialogue_playback_phase == DIALOGUE_PHASE_READY_TO_CONTINUE) continue_audio_stream_if_ready(); } } From 466f4160cf9e3481376902c29b8fa90792562299 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:26:41 +0000 Subject: [PATCH 0948/1502] decomp: clarify names in leaf_update domain_0_value_1 -> LEAF_WAIT_FOR_ACTIVATION: The authoritative leaf_update source assigns moby->state after saving position and initializing timers/base scale. Retail 0x002d7f40 loads s0=1 and 0x002d7fc0 stores it to 0x20(s3), the same byte loaded at 0x002d7f3c and dispatched at 0x002d7f44 to the distance/timer-gated waiting branch. This is the existing local LEAF_WAIT_FOR_ACTIVATION enum domain, not a control mode. domain_1_value_2 -> LEAF_UPDATE_MOTION: Retail 0x002d8114 loads v1=2 and 0x002d8124 stores it to moby state byte 0x20(s3) after randomized motion, rotation and active timer initialization. The identical byte is read at 0x002d7f3c and value 2 dispatches at 0x002d7f64 to 0x002d8128, which integrates movement, handles collisions and updates rotation/scale. The source already names this switch-domain member LEAF_UPDATE_MOTION. domain_2_value_1 -> LEAF_WAIT_FOR_ACTIVATION: After the active timer expires, retail 0x002d844c-0x002d8454 restores the saved position and 0x002d8458-0x002d846c reloads the waiting timer pair. 0x002d8468 sets v1=1 and 0x002d8470 stores it to 0x20(s3), the same moby->state byte dispatched to the distance/timer waiting branch at 0x002d7f44. Reuse existing LEAF_WAIT_FOR_ACTIVATION from this exact local switch domain. --- src/overlays/l04/mobys/leaf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l04/mobys/leaf.c b/src/overlays/l04/mobys/leaf.c index bb7fd19032..7853246f53 100644 --- a/src/overlays/l04/mobys/leaf.c +++ b/src/overlays/l04/mobys/leaf.c @@ -50,7 +50,7 @@ void leaf_update(struct Moby *moby) { qcopy(leaf_vars + 0x30, &moby->pos); *(int *)(leaf_vars + 0x40) = *(int *)(leaf_vars + 0x44) = random_int_between(120, 2400); *(float *)(leaf_vars + 0x4c) = moby->scale * random_float_between(0.8f, 1.2f); - moby->state = 1; + moby->state = LEAF_WAIT_FOR_ACTIVATION; break; case LEAF_WAIT_FOR_ACTIVATION: if (!(vector_distance_xy(&moby->pos, D_L04_00166F40) < 32.0f)) @@ -74,7 +74,7 @@ void leaf_update(struct Moby *moby) { fast_vec_normalize(motion + 8, &initialDirection, 0.098174773f); fast_vec_normalize(motion + 4, &initialDirection, leaf_motion_parameters[5] * 0.5f); *(int *)(motion + 16) = *(int *)(motion + 17) = random_int_between(720, 1200); - moby->state = 2; + moby->state = LEAF_UPDATE_MOTION; return; case LEAF_UPDATE_MOTION: fast_dec_timer((int *)(leaf_vars + 0x44)); @@ -138,7 +138,7 @@ void leaf_update(struct Moby *moby) { /* Preserve the retail ordering of the timer reload stores. */ *(volatile int *)(leaf_vars + 0x40) = timer; *(volatile int *)(leaf_vars + 0x44) = timer; - moby->state = 1; + moby->state = LEAF_WAIT_FOR_ACTIVATION; break; default: return; From 9a05b9bc0f28d81b41c906db23889af9abe01edb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:26:42 +0000 Subject: [PATCH 0949/1502] decomp: clarify names in update_mission_gated_taxi_platform domain_0_value_0 -> TAXI_PLATFORM_STATE_UNINITIALIZED: Retail 0x002cdbbc loads Moby+0x20 and 0x002cdbc0 skips the setup block when nonzero. Original Ghidra likewise tests param_1+0x20 == 0. The zero branch initializes pvars, command, path progress and initial endpoint position (0x002cdbc8-0x002cdc40), then writes 1 to that same state byte at 0x002cdc48. Thus this comparison denotes the taxi platform's uninitialized state, separate from the command selector loaded from +0xBC at 0x002cdc74. domain_1_value_1 -> TAXI_PLATFORM_STATE_INITIALIZED: Retail 0x002cdc34 loads a0=1 and 0x002cdc48 stores it to Moby+0x20 after initial path endpoint placement and clearing timer/progress fields at 0x002cdc28-0x002cdc40. Original Ghidra confirms *(param_1+0x20)=1 inside the zero-state setup block. Later updates skip that block through 0x002cdbbc-0x002cdbc0. This marks completed taxi platform initialization; boarding/traversal uses the separate +0xBC command byte, not this state. --- src/overlays/l07/mobys/mission_gated_taxi_platform.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l07/mobys/mission_gated_taxi_platform.c b/src/overlays/l07/mobys/mission_gated_taxi_platform.c index 781057409a..ffa86ee622 100644 --- a/src/overlays/l07/mobys/mission_gated_taxi_platform.c +++ b/src/overlays/l07/mobys/mission_gated_taxi_platform.c @@ -66,7 +66,7 @@ typedef struct MissionGatedTaxiPlatformVars { /* Moby class 1474 */ void mission_gated_taxi_platform_update(struct Moby *moby) { - MissionGatedTaxiPlatformVars *mission_gated_taxi_vars = + enum { TAXI_PLATFORM_STATE_UNINITIALIZED = 0 , TAXI_PLATFORM_STATE_INITIALIZED = 1 } ;MissionGatedTaxiPlatformVars *mission_gated_taxi_vars = (MissionGatedTaxiPlatformVars *)moby->pvars; char *path; float orig[4], delta[4], path_segment_offset[4]; @@ -81,7 +81,7 @@ void mission_gated_taxi_platform_update(struct Moby *moby) { path = D_L07_001B0530[mission_gated_taxi_vars->path]; qcopy(orig, &moby->pos); fast_dec_timer_s16(&mission_gated_taxi_vars->timer); - if (moby->state == 0) { + if (moby->state == TAXI_PLATFORM_STATE_UNINITIALIZED) { float f; char *pts; mission_gated_taxi_vars->unk28 = 4; @@ -98,7 +98,7 @@ void mission_gated_taxi_platform_update(struct Moby *moby) { mission_gated_taxi_vars->timer = 0; *(int *)&mission_gated_taxi_vars->unkA8 = 0; *(int *)&mission_gated_taxi_vars->unkBC = 0; - moby->state = 1; + moby->state = TAXI_PLATFORM_STATE_INITIALIZED; moby->update_dist = 0xFF; moby->draw_dist = 0xFF; mission_gated_taxi_vars->unkC4 = -1; From 4b1365897f31588dbd8c698ff54b89c9f676014b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:28:33 +0000 Subject: [PATCH 0950/1502] decomp: clarify names in shuttle_update domain_0_value_1 -> SHUTTLE_STATE_WAIT_FOR_DEPARTURE: Retail 00309d20 stores s4=1 to 0x20(s1) after attach_manipulator and path lookup during initialization. The same byte is read at 00309c80 and value 1 dispatches at 00309c88 to 00309e84, the existing SHUTTLE_STATE_WAIT_FOR_DEPARTURE branch that wobbles until clip-volume or grounded-hero departure. This is precisely the local enum's moby->state domain. domain_1_value_1 -> SHUTTLE_STATE_WAIT_FOR_DEPARTURE: Retail 00309e70-00309e78 compares hero.ground_moby with s1 (moby) in state 2 and stores s4=1 to 0x20(s1) on inequality. Retail 00309c80/00309c88 dispatches that exact state byte with value 1 to 00309e84, the existing SHUTTLE_STATE_WAIT_FOR_DEPARTURE case. Source confirms the assignment occurs when the hero has dismounted. domain_2_value_3 -> SHUTTLE_STATE_FOLLOW_PATH: Retail 00309f30-00309f98 checks the enabled flag at pvars+0xC8, direction and the appropriate clip volume, then stores 3 to 0x20(s1) at 00309f98. The same state byte read at 00309c80 dispatches value 3 through 00309cb0 to 00309fd0 and advance_shuttle_along_path at 0030a148. Thus this assignment enters the existing SHUTTLE_STATE_FOLLOW_PATH case. domain_3_value_3 -> SHUTTLE_STATE_FOLLOW_PATH: Retail 00309fa4-00309fb4 tests hero.ground_moby==moby and hero.air_frames==0; 00309fc4 enables pvars+0xC8 and 00309fcc writes v1=3 to 0x20(s1). That byte is the switch selector at 00309c80 and value 3 enters 00309fd0, whose 0030a148 call advances the shuttle path. Source's existing SHUTTLE_STATE_FOLLOW_PATH enum member names this exact domain and transition. domain_4_value_2 -> SHUTTLE_STATE_WAIT_FOR_DISMOUNT: After advance_shuttle_along_path returns nonzero at 0030a148-0030a150, retail releases the voice, resets lag/oscillation and stores v1=2 to 0x20(s1) at 0030a1a8, then reverses direction. The same selector byte at 00309c80 dispatches value 2 to 00309dc0; that branch wobbles until hero.ground_moby differs, then returns to state 1. This proves reuse of the local SHUTTLE_STATE_WAIT_FOR_DISMOUNT member. --- src/overlays/l09/mobys/shuttle.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l09/mobys/shuttle.c b/src/overlays/l09/mobys/shuttle.c index 6d9145d5ab..32a720d849 100644 --- a/src/overlays/l09/mobys/shuttle.c +++ b/src/overlays/l09/mobys/shuttle.c @@ -119,7 +119,7 @@ void shuttle_update(struct Moby *moby) { Vec4 *endpoint; attach_manipulator(moby, 0, (u8 *)shuttle_vars + 0x60); path = (PathNodes_00309c08 *)l09_paths[shuttle_vars->path]; - moby->state = 1; + moby->state = SHUTTLE_STATE_WAIT_FOR_DEPARTURE; if (D_0014C050[moby->mission + current_level_index * 16] == 0xFF) { shuttle_vars->dir = -1; shuttle_vars->node = path->count - 2; @@ -149,7 +149,7 @@ void shuttle_update(struct Moby *moby) { frame_time * 0.31415927f, frame_time * 0.4886922f); if (hero.ground_moby != moby) - moby->state = 1; + moby->state = SHUTTLE_STATE_WAIT_FOR_DEPARTURE; break; case SHUTTLE_STATE_WAIT_FOR_DEPARTURE: shuttle_vars->lag += (1.0f - shuttle_vars->lag) * 0.01f; @@ -169,12 +169,12 @@ void shuttle_update(struct Moby *moby) { is_point_inside_clip_volume(D_0013F3D0, *(s32 *)((u8 *)shuttle_vars + 0xB4))) || (shuttle_vars->dir < 0 && *(s32 *)((u8 *)shuttle_vars + 0xB0) != -1 && is_point_inside_clip_volume(D_0013F3D0, *(s32 *)((u8 *)shuttle_vars + 0xB0)))) { - moby->state = 3; + moby->state = SHUTTLE_STATE_FOLLOW_PATH; } } if (hero.ground_moby == moby && hero.air_frames.s == 0) { *(s32 *)((u8 *)shuttle_vars + 0xC8) = 1; - moby->state = 3; + moby->state = SHUTTLE_STATE_FOLLOW_PATH; } break; case SHUTTLE_STATE_FOLLOW_PATH: @@ -218,7 +218,7 @@ void shuttle_update(struct Moby *moby) { *(s32 *)((u8 *)shuttle_vars + 0xC4) = -1; shuttle_vars->lag = 0.0f; *(s32 *)((u8 *)shuttle_vars + 0xDC) = 0; - moby->state = 2; + moby->state = SHUTTLE_STATE_WAIT_FOR_DISMOUNT; shuttle_vars->yaw_offset = 3.1415927f; dir = shuttle_vars->dir; shuttle_vars->dir = -dir; From 9c303df6f4a10249a7cadb0ad3d7318c9a598be5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:28:33 +0000 Subject: [PATCH 0951/1502] decomp: clarify names in asteroid_update domain_0_value_3 -> ASTEROID_RESET_AT_HOME: Retail 0x002e16f8 loads 3 and 0x002e1700 stores it to moby byte +0x20, the same byte read for switch dispatch at 0x002e166c. This follows saving home/direction/start_scale/pieces; existing case ASTEROID_RESET_AT_HOME=3 at 0x002e19a4 restores home, initializes spin, clears velocity and restores scale. domain_1_value_2 -> ASTEROID_MOVE_AND_COLLIDE: Retail 0x002e1790 loads 2 and 0x002e1798 stores it to moby +0x20 after constructing launch velocity at 0x002e1788. This is the dispatch selector read at 0x002e166c; its existing ASTEROID_MOVE_AND_COLLIDE=2 case at 0x002e179c decrements cooldown, adds velocity to position and handles collisions. domain_2_value_4 -> ASTEROID_WAIT_TO_RESPAWN: Retail 0x002e1980 loads 4 and 0x002e1984 writes moby +0x20 after the distant timer expires for a non-child asteroid. Subsequent stores disable collision/visibility, set flags bit 1 and restore start_scale. The same selector's existing ASTEROID_WAIT_TO_RESPAWN=4 case at 0x002e1b14 waits on the home/draw-distance predicate before restoring the asteroid. domain_3_value_1 -> ASTEROID_WAIT_TO_LAUNCH: Retail 0x002e1b08 loads 1 and 0x002e1b10 stores it to moby +0x20 after the reset case restores home/scale, randomizes rotations and clears velocity. That byte is the dispatch selector; its existing ASTEROID_WAIT_TO_LAUNCH=1 case at 0x002e1704 gates launch on hero/ship and visibility/proximity, then initializes velocity. domain_4_value_3 -> ASTEROID_RESET_AT_HOME: Retail 0x002e1b50 loads a2=3 and 0x002e1b68 stores a2 to moby +0x20 after the respawn wait predicate passes, home position/class collision/visibility are restored and flags bit 1 is cleared. The identical byte is read at 0x002e166c; existing ASTEROID_RESET_AT_HOME=3 performs reset initialization at 0x002e19a4. --- src/overlays/l13/mobys/asteroid.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l13/mobys/asteroid.c b/src/overlays/l13/mobys/asteroid.c index c9e9b2590a..151fdfe45b 100644 --- a/src/overlays/l13/mobys/asteroid.c +++ b/src/overlays/l13/mobys/asteroid.c @@ -264,14 +264,14 @@ void asteroid_update(struct Moby *moby) { if (moby->scale < moby->pclass->scale) { moby->unk72 = 0; } - moby->state = 3; + moby->state = ASTEROID_RESET_AT_HOME; break; case ASTEROID_WAIT_TO_LAUNCH: if (hero.state.current == 0x32 && hero.ship_moby != 0 && hero.ship_moby->oclass == 0x45 && (moby->visible != 0 || distance < 40.0f)) { fast_vec_normalize( asteroid_vars, asteroid_vars->dir, random_float_between(1.0f, 10.0f) * frame_time); - moby->state = 2; + moby->state = ASTEROID_MOVE_AND_COLLIDE; } break; case ASTEROID_MOVE_AND_COLLIDE: @@ -314,7 +314,7 @@ void asteroid_update(struct Moby *moby) { mark_moby_for_removal(moby); return; } - moby->state = 4; + moby->state = ASTEROID_WAIT_TO_RESPAWN; moby->collision = 0; moby->flags |= 1; moby->visible = 0; @@ -356,7 +356,7 @@ void asteroid_update(struct Moby *moby) { if (moby->pclass->scale < moby->scale) { moby->unk72 = 100; } - moby->state = 1; + moby->state = ASTEROID_WAIT_TO_LAUNCH; break; case ASTEROID_WAIT_TO_RESPAWN: if (fast_bsphere_check(&asteroid_vars->home, moby->draw_dist) < 0) { @@ -364,7 +364,7 @@ void asteroid_update(struct Moby *moby) { moby->collision = moby->pclass->collision; moby->visible = 1; moby->flags &= ~1; - moby->state = 3; + moby->state = ASTEROID_RESET_AT_HOME; } break; } From bea9c707d607af7f0f16a046acd2f2bde0e329de Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:28:34 +0000 Subject: [PATCH 0952/1502] decomp: clarify names in update_flying_car domain_0_value_3 -> FLYING_CAR_WAIT_FOR_PATH_RESET: Retail 0x00306f24-0x00306f2c reads moby state at s1+0x20 and skips repeat hit handling for 3. The same field dispatches state 3 to 0x00307344, which waits on the reset timer before restoring the first path pose; reuse the bound local enum. domain_1_value_3 -> FLYING_CAR_WAIT_FOR_PATH_RESET: Retail 0x00306f48 writes 3 to s1+0x20 after the hit check, before burst, hidden flags and collision clearing. Dispatch at 0x0030700c sends this same state to the timer-gated path reset at 0x00307344; reuse the existing local member. domain_2_value_2 -> FLYING_CAR_FOLLOW_PATH: Retail 0x00307074 initializes the car path and 0x0030707c-0x00307084 stores 2 into moby+0x20. The same field dispatches 2 at 0x00307004 to 0x003071b0, calling path motion at 0x003071e8; this is the existing FLYING_CAR_FOLLOW_PATH domain. domain_3_value_1 -> FLYING_CAR_WAIT_FOR_TRIGGER: Retail 0x00307110 checks private trigger +0xC4, hides the car and clears collision, then 0x00307150 stores s5=1 into moby+0x20. State 1 dispatches to the hero clip-volume trigger test at 0x00307154-0x00307164, matching the existing local member. domain_4_value_2 -> FLYING_CAR_FOLLOW_PATH: Retail 0x00307154-0x00307164 tests the configured trigger against hero position; on success flags and collision are restored and 0x003071a4-0x003071ac stores 2 into the same moby+0x20 field whose state-2 branch calls path motion at 0x003071e8. domain_5_value_2 -> FLYING_CAR_FOLLOW_PATH: After reset timer expiry at 0x00307344-0x0030734c, retail 0x003073a8 stores s4=2 into moby+0x20 while restoring the first path point and clearing motion. Dispatch 0x00307004 selects the path-following branch for that same field and value. domain_6_value_1 -> FLYING_CAR_WAIT_FOR_TRIGGER: Retail 0x00307480 checks private trigger +0xC4 after path reset; when configured, 0x00307490 stores s5=1 to moby+0x20 and clears collision. The same state field selects the hero trigger waiting branch at 0x00307154; reuse its established enum member. domain_7_value_0 -> FLYING_CAR_INITIALIZE: Retail 0x003074a0 reloads moby state +0x20 and 0x003074a4 skips voice maintenance for zero. The same field's zero dispatch at 0x00306ff4 enters path validation and initialization at 0x0030701c-0x00307074, proving the existing FLYING_CAR_INITIALIZE member. domain_8_value_3 -> FLYING_CAR_WAIT_FOR_PATH_RESET: Retail 0x003074a8-0x003074ac compares the reloaded moby+0x20 state against 3 to skip voice maintenance. Dispatch 0x0030700c uses that identical state field and value for the timer-gated first-path-pose reset at 0x00307344. domain_9_value_1 -> FLYING_CAR_WAIT_FOR_TRIGGER: Retail 0x003074b0-0x003074b4 compares the same moby+0x20 state against 1 and returns before voice maintenance. Dispatch 0x00306fe4 routes 1 to 0x00307154, where the configured trigger is tested against hero position; reuse the local waiting-state member. --- src/overlays/l14/mobys/flying_car.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l14/mobys/flying_car.c b/src/overlays/l14/mobys/flying_car.c index d0089a3c38..793bac36f2 100644 --- a/src/overlays/l14/mobys/flying_car.c +++ b/src/overlays/l14/mobys/flying_car.c @@ -127,8 +127,8 @@ void flying_car_update(struct Moby *flying_car_moby) { hit = find_moby_hit(flying_car_moby, 0x800000, 0); flying_car_moby->hit_slot = 0xFF; - if (hit && flying_car_moby->state != 3) { - flying_car_moby->state = 3; + if (hit && flying_car_moby->state != FLYING_CAR_WAIT_FOR_PATH_RESET) { + flying_car_moby->state = FLYING_CAR_WAIT_FOR_PATH_RESET; cart_burst(flying_car_moby, &flying_car_moby->pos, 5.0f, 13.0f, -1); flying_car_moby->flags |= 0x41; flying_car_moby->collision = 0; @@ -158,7 +158,7 @@ void flying_car_update(struct Moby *flying_car_moby) { return; } FUN_L14_00307510_6ee0(flying_car_moby); - flying_car_moby->state = 2; + flying_car_moby->state = FLYING_CAR_FOLLOW_PATH; flying_car_moby->update_dist = 0xFF; flying_car_moby->draw_dist = 0xFF; flying_car_data->sound = -1; @@ -184,7 +184,7 @@ void flying_car_update(struct Moby *flying_car_moby) { (struct Moby *)(D_L14_0015FFD8_macro + (flying_car_data->part << 8)); o->flags |= 0x41; } - flying_car_moby->state = 1; + flying_car_moby->state = FLYING_CAR_WAIT_FOR_TRIGGER; } break; case FLYING_CAR_WAIT_FOR_TRIGGER: @@ -196,7 +196,7 @@ void flying_car_update(struct Moby *flying_car_moby) { (struct Moby *)(D_L14_0015FFD8_macro + (flying_car_data->part << 8)); o->flags &= 0xFFBE; } - flying_car_moby->state = 2; + flying_car_moby->state = FLYING_CAR_FOLLOW_PATH; } break; case FLYING_CAR_FOLLOW_PATH: @@ -256,7 +256,7 @@ void flying_car_update(struct Moby *flying_car_moby) { flying_car_moby->flags &= 0xFFBE; flying_car_moby->collision = flying_car_moby->pclass->collision; flying_car_data->timer = scale_game_frames(flying_car_path_reset_delay_frames_gp); - flying_car_moby->state = 2; + flying_car_moby->state = FLYING_CAR_FOLLOW_PATH; flying_car_data->f70 = 0; flying_car_data->f74 = 0; qcopy(&flying_car_moby->pos, &path->a); @@ -282,13 +282,13 @@ void flying_car_update(struct Moby *flying_car_moby) { } if (flying_car_data->trigger >= 0) { flying_car_moby->flags |= 0x41; - flying_car_moby->state = 1; + flying_car_moby->state = FLYING_CAR_WAIT_FOR_TRIGGER; flying_car_moby->collision = 0; } } break; } - if (flying_car_moby->state == 0 || flying_car_moby->state == 3 || flying_car_moby->state == 1) { + if (flying_car_moby->state == FLYING_CAR_INITIALIZE || flying_car_moby->state == FLYING_CAR_WAIT_FOR_PATH_RESET || flying_car_moby->state == FLYING_CAR_WAIT_FOR_TRIGGER) { return; } if (voice_is_playing(flying_car_moby, flying_car_data->sound) == 0) { From b0220d44959a2ff31cc770975b558baf3a9214ae Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:28:34 +0000 Subject: [PATCH 0953/1502] decomp: clarify names in the_plumber_update domain_0_value_1 -> PLUMBER_LEVEL_ONE_DIALOGUE: Retail 0x002ff1fc selects the level-one dialogue table and 0x002ff204 stores 1 into moby+0x20, the exact selector read at 0x002ff1a0. Its existing case PLUMBER_LEVEL_ONE_DIALOGUE calls update_npc_dialogue at 0x002ff248. domain_10_value_4 -> PLUMBER_LEVEL_EIGHT_DIALOGUE: Retail 0x002ff380-0x002ff388 loads 4 when pvars+6 differs from 2, then 0x002ff3cc stores it into moby+0x20. This returns to the existing PLUMBER_LEVEL_EIGHT_DIALOGUE case at 0x002ff34c, which updates the level-eight dialogue. domain_1_value_4 -> PLUMBER_LEVEL_EIGHT_DIALOGUE: Retail 0x002ff208-0x002ff22c selects dialogue table 0x161d38 for level 8 and stores 4 into moby+0x20, the switch selector. Existing PLUMBER_LEVEL_EIGHT_DIALOGUE case updates that dialogue at 0x002ff350. domain_3_value_2 -> PLUMBER_LEVEL_ONE_POST_DIALOGUE: Retail 0x002ff248-0x002ff270 tests update_npc_dialogue success, begins the camera transition, then stores 2 through 0x002ff3cc into the same moby+0x20 selector. Existing PLUMBER_LEVEL_ONE_POST_DIALOGUE case waits and performs post-dialogue cleanup. domain_5_value_1 -> PLUMBER_LEVEL_ONE_DIALOGUE: Retail 0x002ff2dc-0x002ff2e4 stores 1 into moby+0x20 after level-one post-dialogue cleanup, returning to the same selector case PLUMBER_LEVEL_ONE_DIALOGUE that calls update_npc_dialogue at 0x002ff248. domain_6_value_3 -> PLUMBER_REMOVE: Retail 0x002ff304-0x002ff318 stores 3 into moby+0x20 after planet unlock calls and before persisting the state. The same selector's existing PLUMBER_REMOVE case at 0x002ff33c calls mark_moby_for_removal and returns. domain_7_value_5 -> PLUMBER_LEVEL_EIGHT_POST_DIALOGUE: Retail 0x002ff350-0x002ff368 tests dialogue update success, stores 5 into moby+0x20 and clears pvars+8. The same selector's existing PLUMBER_LEVEL_EIGHT_POST_DIALOGUE case at 0x002ff36c waits for cutscene mode before deciding the next state. domain_9_value_6 -> PLUMBER_LEVEL_EIGHT_DIALOGUE_FINISHED: Retail 0x002ff380-0x002ff3c8 takes the pvars+6==2 branch after level-eight post-dialogue waiting, writes hero coordinates and stores 6 into moby+0x20. This is the same selector and existing PLUMBER_LEVEL_EIGHT_DIALOGUE_FINISHED case, which performs no further script action. --- src/overlays/shared/cutscenes/the_plumber.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/shared/cutscenes/the_plumber.c b/src/overlays/shared/cutscenes/the_plumber.c index 5166460347..bce8d998a5 100644 --- a/src/overlays/shared/cutscenes/the_plumber.c +++ b/src/overlays/shared/cutscenes/the_plumber.c @@ -175,10 +175,10 @@ void the_plumber_update(L01WatchMoby *plumber_moby) { return; } plumber_vars->p20 = (void *)plumber_level_one_dialogue_data; - plumber_moby->state = 1; + plumber_moby->state = PLUMBER_LEVEL_ONE_DIALOGUE; } else if (current_level_index == 8) { plumber_vars->p20 = (void *)plumber_level_eight_dialogue_data; - plumber_moby->state = 4; + plumber_moby->state = PLUMBER_LEVEL_EIGHT_DIALOGUE; } else { plumber_vars->p20 = (void *)plumber_fallback_dialogue_data; plumber_moby->state = 7; @@ -188,7 +188,7 @@ void the_plumber_update(L01WatchMoby *plumber_moby) { case PLUMBER_LEVEL_ONE_DIALOGUE: if (update_npc_dialogue(plumber_moby, plumber_vars)) { begin_dialogue_camera_transition(plumber_moby, 2.2f); - plumber_moby->state = 2; + plumber_moby->state = PLUMBER_LEVEL_ONE_POST_DIALOGUE; } break; case PLUMBER_LEVEL_ONE_POST_DIALOGUE: @@ -201,11 +201,11 @@ void the_plumber_update(L01WatchMoby *plumber_moby) { jet_reset_camera(&camera_record->pos, &camera_record->rot); } } - plumber_moby->state = 1; + plumber_moby->state = PLUMBER_LEVEL_ONE_DIALOGUE; if (plumber_vars->sub == 4) { unlock_planet(2); queue_planet_unlock_message(2); - plumber_moby->state = 3; + plumber_moby->state = PLUMBER_REMOVE; record_moby_context_bytes( (char *)plumber_moby + 0x20, 1, plumber_moby, 1, D_L01_001BAAA0); memcard_save_data(0, -1); @@ -216,7 +216,7 @@ void the_plumber_update(L01WatchMoby *plumber_moby) { return; case PLUMBER_LEVEL_EIGHT_DIALOGUE: if (update_npc_dialogue(plumber_moby, plumber_vars)) { - plumber_moby->state = 5; + plumber_moby->state = PLUMBER_LEVEL_EIGHT_POST_DIALOGUE; plumber_vars->b8 = 0; } break; @@ -227,9 +227,9 @@ void the_plumber_update(L01WatchMoby *plumber_moby) { D_0013F350_w.f80 = 130.5f; D_0013F350_w.f84 = 299.5f; D_0013F350_w.f88 = 46.0f; - plumber_moby->state = 6; + plumber_moby->state = PLUMBER_LEVEL_EIGHT_DIALOGUE_FINISHED; } else { - plumber_moby->state = 4; + plumber_moby->state = PLUMBER_LEVEL_EIGHT_DIALOGUE; } break; case PLUMBER_LEVEL_EIGHT_DIALOGUE_FINISHED: From b48b8e1fc4b2718847e6a0a636622717cf08316c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:28:34 +0000 Subject: [PATCH 0954/1502] decomp: clarify names in update_sentrybot_hit_response_and_target_visibility domain_0_value_1 -> HIT_STATUS_SKIP_REACTION: Retail 0029a5e0 passes stack+0x10 as fifth/output argument to resolve_moby_hit_response; 0029a5f4 separately saves its return as code. 0029a5f8..0029a600 compares that output with 1 and branches to 0029a880, skipping alert, damage subtraction, knockback/state setup and trooper_anim_update, while retaining common finish. Checked helper evidence 7e398fa4a07340b08ff7646672a31e9e: 00249d70 preserves t0 in s3; absent hit at 00249e70..00249e94 writes 1 through s3, and 0024a234..0024a240 also writes 1 while clearing present-hit damage. Thus 1 is a status suppressing hit reaction, not response code LETHAL_HIT_RESPONSE or a hero/moby state. --- src/overlays/shared/enemies/sentrybot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/sentrybot.c b/src/overlays/shared/enemies/sentrybot.c index 1a10833d32..30c981cc66 100644 --- a/src/overlays/shared/enemies/sentrybot.c +++ b/src/overlays/shared/enemies/sentrybot.c @@ -1554,7 +1554,7 @@ void update_sentrybot_hit_response_and_target_visibility(void *sentrybot_moby, i SENTRYBOT_FIRST_CHANNEL_BLEND_HIT_RESPONSE = 9, SENTRYBOT_FIRST_CHANNEL_BLEND_TARGET_HIT_RESPONSE = 10, SENTRYBOT_NO_KNOCKBACK_START_RESPONSE = 11 - }; + } ; enum { HIT_STATUS_SKIP_REACTION = 1}; unsigned char *moby = sentrybot_moby; SentrybotVars *sentrybot_data = (SentrybotVars *)MOBY(moby)->pvars; char *hit; @@ -1577,7 +1577,7 @@ void update_sentrybot_hit_response_and_target_visibility(void *sentrybot_moby, i impact = 0.0f; hit = FUN_L00_0025a420(moby, 0x330000, 0); code = resolve_moby_hit_response(moby, hit, &sentrybot_data->health, 0, &kind, &impact, 0, 4); - if (kind != 1 && MOBY(moby)->state != 0x17) { + if (kind != HIT_STATUS_SKIP_REACTION && MOBY(moby)->state != 0x17) { if ((unsigned char)D_001413F4[0] == 0) alert_visible_group_sentrybots(moby); sentrybot_data->health -= impact; From 49aca62f49be03f929ab90f7d88e3079e787ce48 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:30:33 +0000 Subject: [PATCH 0955/1502] decomp: clarify names in teleporter_update domain_0_value_1 -> TELEPORTER_WAIT_FOR_ACTIVATION: Retail 0x002f2578-0x002f2580 stores 1 at current moby+0x20, the same byte dispatched at 0x002f254c. Source case TELEPORTER_WAIT_FOR_ACTIVATION uses that selector and waits for a linked target, grounded hero and activation input after initialization. domain_1_value_2 -> TELEPORTER_OPEN_PARTS: Retail 0x002f2760-0x002f2774 writes 2 to current moby+0x20 after activation and clears the part velocities. That exact selector dispatches source TELEPORTER_OPEN_PARTS, whose retail 0x002f27c4-0x002f283c advances the two opening scalars toward 1.0. domain_3_value_3 -> TELEPORTER_CONTRACT_RING: Retail 0x002f2878-0x002f289c handles status 2 by seeding pvars+0x3C to 1.95 and storing state 3 into current moby+0x20. This is the dispatch selector for existing TELEPORTER_CONTRACT_RING, whose 0x002f28b0-0x002f28f8 draws and reduces that ring radius toward zero. domain_5_value_4 -> TELEPORTER_RESET: Retail 0x002f2894-0x002f289c handles status zero by storing 4 into current moby+0x20, the switch selector. Existing TELEPORTER_RESET at 0x002f2a60-0x002f2b2c restores ring radius and reverses opening scalars before returning to wait. domain_6_value_4 -> TELEPORTER_RESET: Retail 0x002f2904-0x002f2958 selects the linked destination moby and its pvars. At 0x002f29cc-0x002f29fc it writes 4 to destination+0x20, with radius zero, velocities zero and opening scalars 1.0. These are the same teleporter fields consumed by existing TELEPORTER_RESET to restore radius and close parts, proving the destination uses this teleporter state domain. domain_7_value_1 -> TELEPORTER_WAIT_FOR_ACTIVATION: After destination setup, retail 0x002f2a00-0x002f2a2c stores 1 into current moby+0x20 and clears its opening scalars and velocities. The same state byte dispatches existing TELEPORTER_WAIT_FOR_ACTIVATION, returning the source teleporter to await grounded activation. domain_8_value_1 -> TELEPORTER_WAIT_FOR_ACTIVATION: Retail 0x002f2ab8-0x002f2b2c returns the reset opening scalars to zero, then writes 1 to current moby+0x20. This exact dispatch selector already names case 1 TELEPORTER_WAIT_FOR_ACTIVATION, completing reset and returning to activation checks. --- src/overlays/l11/mobys/teleporter.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l11/mobys/teleporter.c b/src/overlays/l11/mobys/teleporter.c index 7a71543b50..e34071655e 100644 --- a/src/overlays/l11/mobys/teleporter.c +++ b/src/overlays/l11/mobys/teleporter.c @@ -79,7 +79,7 @@ void teleporter_update(struct Moby *moby) { char **slots = &teleporter_instance_vars->unk14; int i; int j; - moby->state = 1; + moby->state = TELEPORTER_WAIT_FOR_ACTIVATION; for (i = 0; i < 3; i++) { struct Hero *g = &hero; char *child_moby; @@ -126,7 +126,7 @@ void teleporter_update(struct Moby *moby) { if (D_L11_0015F594 != 0xB) break; allocate_voice_for_target_entry(0, 0, (void *)moby); - moby->state = 2; + moby->state = TELEPORTER_OPEN_PARTS; teleporter_instance_vars->unk28 = 0; teleporter_instance_vars->unk2C = 0; request_hero_target_pose(&moby->pos.x, 0, moby->rot.z); @@ -152,9 +152,9 @@ void teleporter_update(struct Moby *moby) { } else if (D_L11_0015F594 != 0xB || !(teleporter_instance_vars->unk20 > 0.25f)) { if (teleport_transition_status == 2) { teleporter_instance_vars->unk3C = 1.95f; - moby->state = 3; + moby->state = TELEPORTER_CONTRACT_RING; } else if (teleport_transition_status == 0) { - moby->state = 4; + moby->state = TELEPORTER_RESET; } } update_teleporter_child_transforms(moby); @@ -181,14 +181,14 @@ void teleporter_update(struct Moby *moby) { teleporter_instance_vars->unk34); } FUN_L11_002f3040_2518(destination_moby); - MOBY(destination_moby)->state = 4; + MOBY(destination_moby)->state = TELEPORTER_RESET; *(float *)(td + 0x3C) = 0.0f; *(float *)(td + 0x28) = 0.0f; *(float *)(td + 0x2C) = 0.0f; *(float *)(td + 0x20) = 1.0f; *(float *)(td + 0x24) = 1.0f; allocate_voice_for_target_entry(1, 0, (void *)destination_moby); - moby->state = 1; + moby->state = TELEPORTER_WAIT_FOR_ACTIVATION; teleporter_instance_vars->unk20 = 0.0f; teleporter_instance_vars->unk24 = 0.0f; *(float *)&teleporter_instance_vars->unk28 = 0.0f; @@ -218,7 +218,7 @@ void teleporter_update(struct Moby *moby) { teleporter_parts_deceleration_gp * frame_time_sq, teleporter_parts_max_speed_gp * frame_time); } else { - moby->state = 1; + moby->state = TELEPORTER_WAIT_FOR_ACTIVATION; } update_teleporter_child_transforms(moby); break; From 979784c461a178700e9009a57c76d4af4f7794e1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:30:33 +0000 Subject: [PATCH 0956/1502] decomp: clarify names in update_help_hints domain_0_value_1 -> VENDOR_EVENT_ARMED: Source switch(event_trigger_data->state) already labels 1 VENDOR_EVENT_ARMED. Retail 0x00307564 loads moby+0x78 into s3; 0x00307568 reads its state at +0x10 and dispatches 0/1 at 0x0030756c-0x00307574. Third-volume membership and hero control_mode 15 cause li v0,1 at 0x003075b0 and sw v0,0x10(s3) at 0x003075b8. Original Ghidra likewise sets puVar1[4]=1. This assignment enters the exact same state domain and existing armed branch. domain_1_value_0 -> VENDOR_EVENT_WAIT_FOR_ARMING: Source labels 0 VENDOR_EVENT_WAIT_FOR_ARMING in the switch over event_trigger_data->state. Retail dispatch reads s3+0x10 at 0x00307568, branches on zero to third-volume/control-mode arming checks at 0x00307584, and on 1 to 0x003075bc. In that armed branch hero.state.current==0x42 leads to sw zero,0x10(s3) at 0x003075d4. Original Ghidra confirms puVar1[4]=0. The reset writes the identical trigger-state field, so its value reuses the existing waiting-for-arming member. --- src/overlays/l08/mobys/help_hints.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l08/mobys/help_hints.c b/src/overlays/l08/mobys/help_hints.c index e010dcedc3..194327d991 100644 --- a/src/overlays/l08/mobys/help_hints.c +++ b/src/overlays/l08/mobys/help_hints.c @@ -42,11 +42,11 @@ void help_hints_update(struct Moby *moby) { case VENDOR_EVENT_WAIT_FOR_ARMING: if (is_point_inside_clip_volume(&hero.motion.pos, event_trigger_data->third) && hero.state.control_mode == 15) - event_trigger_data->state = 1; + event_trigger_data->state = VENDOR_EVENT_ARMED; break; case VENDOR_EVENT_ARMED: if (hero.state.current == 0x42) { - event_trigger_data->state = 0; + event_trigger_data->state = VENDOR_EVENT_WAIT_FOR_ARMING; } else if (is_point_inside_clip_volume(&hero.motion.pos, event_trigger_data->fourth) && item_unlocked[11] == 0) { item_unlocked[11] = 1; From df94cf42df2a7f7388cbc83503aacc56bf31b2c3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:30:33 +0000 Subject: [PATCH 0957/1502] decomp: clarify names in draw_fighter_jet_hud domain_0_value_8 -> FIGHTER_JET_STATE_VICTORY_EXIT: Retail 0x002eb9c0 preserves the incoming moby in s6; 0x002ebe30/0x002ebe5c loads its state byte at +0x20 and 0x002ebe60-0x002ebe70 compares 8 before displaying message 0x523E. Authoritative source SHA-256 a2ab1142cc5560d28f2ed6b48b610d6b38fc12b898da1a455dc1276db99c0d83 shows update_fighter_jet_flight queues draw_fighter_jet_hud with ship_moby. fighter_jet_update passes that same moby to the flight helper and declares FIGHTER_JET_STATE_VICTORY_EXIT=8: remaining targets iE8<=0 assigns this state, then its branch continues flight, waits timerF8, fades, dismounts and uses victory exit placements. Thus this is the fighter-jet moby state domain, not HERO_STATE_LAND or PAD_R1. --- src/overlays/l17/mobys/fighter_jet.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l17/mobys/fighter_jet.c b/src/overlays/l17/mobys/fighter_jet.c index dac12db0a5..fda368df6a 100644 --- a/src/overlays/l17/mobys/fighter_jet.c +++ b/src/overlays/l17/mobys/fighter_jet.c @@ -771,6 +771,9 @@ extern int font_print_center_small(int, int, long, void *, int) __asm__("FUN_00 void draw_fighter_jet_hud(struct Moby *moby) __asm__("FUN_L17_002eb9a8"); void draw_fighter_jet_hud(struct Moby *moby) { + enum { + FIGHTER_JET_STATE_VICTORY_EXIT = 8 + }; char *ship_vars = (char *)moby->pvars; char *screen_dimensions; int locked_target_screen_x; @@ -925,7 +928,7 @@ void draw_fighter_jet_hud(struct Moby *moby) { if (hero.ship_hp < hero.ship_hp_max / 10.0f && (D_L17_0015F5CC / 90) & 1) { font_print_center_small(0x100, 0x186, 0x80000080L, get_help_message_text(0x5269), 0x64); } - if (moby->state == 8) { + if (moby->state == FIGHTER_JET_STATE_VICTORY_EXIT) { font_print_center_small(0x100, 0xC8, 0x80005080L, get_help_message_text(0x523E), 0x64); } hp_display_step = hero.ship_hp - *(float *)(ship_vars + 0xF0); From 4acc9aa4c510d88c05bac2a0311fd16db7879ab9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:30:33 +0000 Subject: [PATCH 0958/1502] decomp: clarify names in update_lift domain_0_value_4 -> LIFT_IDLE_AT_TOP: At 0x0030a7c0-0x0030a7cc initialization stores 4 into moby state +0x20. This is the same selector loaded at 0x0030a780; existing local LIFT_IDLE_AT_TOP case handles its idle glow and bottom recall at 0x0030aba4-0x0030ac44. domain_10_value_4 -> LIFT_IDLE_AT_TOP: At 0x0030aba4-0x0030aba8 comparison against 4 reads the same moby state +0x20 switch selector. The branch tests hero ground height against bottom +0x64 and requests downward movement 3 at 0x0030ac28-0x0030ac44, proving existing LIFT_IDLE_AT_TOP. domain_11_value_3 -> LIFT_MOVE_TO_BOTTOM: At 0x0030ac28-0x0030ac44 the top-idle recall branch stores 3 into moby state +0x20 and initializes negative speed +0x68. State 3 selects bottom +0x64 for accelerated position-Z movement at 0x0030a940-0x0030a98c, matching LIFT_MOVE_TO_BOTTOM. domain_12_value_5 -> LIFT_IDLE_AT_BOTTOM: At 0x0030ac48 comparison against 5 reads the same moby state +0x20 selector. The branch checks hero ground height against top +0x60 and starts upward movement 2 at 0x0030acc8-0x0030ace0, proving existing LIFT_IDLE_AT_BOTTOM. domain_13_value_2 -> LIFT_MOVE_TO_TOP: At 0x0030acc8-0x0030ace0 bottom-idle recall stores 2 into moby state +0x20 and initializes positive speed +0x68. This same state selects top +0x60 as accelerated position-Z target at 0x0030a940-0x0030a98c, matching existing LIFT_MOVE_TO_TOP. domain_1_value_2 -> LIFT_MOVE_TO_TOP: At 0x0030a940-0x0030a950 the byte at moby +0x20 is compared with 2; equality selects pvars +0x60 (top), otherwise +0x64 (bottom), for accelerated position-Z movement. This is the existing LIFT_MOVE_TO_TOP state domain. domain_2_value_2 -> LIFT_MOVE_TO_TOP: At 0x0030a9c0-0x0030a9d4 arrival compares moby state +0x20 against 2 after position Z reaches its selected endpoint. The same state selects top +0x60 at 0x0030a940-0x0030a950, proving existing LIFT_MOVE_TO_TOP. domain_3_value_6 -> LIFT_WAIT_AT_TOP_FOR_HERO_TO_LEAVE: At 0x0030a9c0-0x0030a9d4 arrival from top movement state 2 stores 6 into moby state +0x20. The existing case for 6 waits until hero.ground_moby differs before storing idle-at-top 4 at 0x0030aa40-0x0030aa68. domain_4_value_7 -> LIFT_WAIT_AT_BOTTOM_FOR_HERO_TO_LEAVE: At 0x0030a9c8-0x0030a9d4 arrival from bottom movement state 3 stores 7 into moby state +0x20. At 0x0030aa40-0x0030aa60 this existing wait state remains until the hero leaves, then enters idle-at-bottom 5. domain_5_value_7 -> LIFT_WAIT_AT_BOTTOM_FOR_HERO_TO_LEAVE: At 0x0030aa40-0x0030aa60 the hero ground-moby check gates comparison of moby state +0x20 against 7. Equality transitions to idle-at-bottom 5; arrival from bottom movement sets 7 at 0x0030a9c8-0x0030a9d4, matching the existing local member. domain_6_value_5 -> LIFT_IDLE_AT_BOTTOM: At 0x0030aa58-0x0030aa60 the wait-at-bottom branch stores 5 into moby state +0x20 after hero.ground_moby differs. Existing LIFT_IDLE_AT_BOTTOM handles this selector; its recall branch checks hero height against top and starts upward movement at 0x0030ac48-0x0030ace0. domain_7_value_4 -> LIFT_IDLE_AT_TOP: At 0x0030aa50-0x0030aa68 the wait-at-top branch stores 4 into moby state +0x20 once the hero leaves. Existing LIFT_IDLE_AT_TOP handles this selector and checks hero height against bottom before starting downward movement at 0x0030aba4-0x0030ac44. domain_8_value_5 -> LIFT_IDLE_AT_BOTTOM: At 0x0030ab44-0x0030ab64 the mount-entry branch compares moby state +0x20 with 5 and queues upward movement 2 on equality. This is the same bottom idle state reached from wait state 7 at 0x0030aa58-0x0030aa60, named LIFT_IDLE_AT_BOTTOM locally. domain_9_value_1 -> LIFT_BLEND_TO_MOUNT_TRANSFORM: At 0x0030ab68-0x0030ab9c mount entry stores 1 into moby state +0x20, calls jet_mount and clears blend +0x70. Existing state 1 advances blend and interpolates mount position/rotation at 0x0030a7d8-0x0030a8c8 before restoring queued movement. --- src/overlays/l13/mobys/lift.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/overlays/l13/mobys/lift.c b/src/overlays/l13/mobys/lift.c index 908e6026bb..a4266f33ae 100644 --- a/src/overlays/l13/mobys/lift.c +++ b/src/overlays/l13/mobys/lift.c @@ -77,7 +77,7 @@ void lift_update(struct Moby *moby) { lift_vars->pulse = random_angle_radians(); lift_vars->voice = -1; lift_vars->timer = 0; - moby->state = 4; + moby->state = LIFT_IDLE_AT_TOP; break; case LIFT_BLEND_TO_MOUNT_TRANSFORM: { float previous_mount_blend = lift_vars->blend; @@ -124,7 +124,7 @@ void lift_update(struct Moby *moby) { set_camera_position(mount_position_work); set_camera_rotation(mount_transform_work); } - if (moby->state == 2) + if (moby->state == LIFT_MOVE_TO_TOP) target = lift_vars->top; else target = lift_vars->bottom; @@ -136,10 +136,10 @@ void lift_update(struct Moby *moby) { D_0015ED6C * 40.0f); if (absolute_float(moby->pos.z - target) == 0.0f) { lift_vars->timer = scale_game_frames(0x46); - if (moby->state == 2) - moby->state = 6; + if (moby->state == LIFT_MOVE_TO_TOP) + moby->state = LIFT_WAIT_AT_TOP_FOR_HERO_TO_LEAVE; else - moby->state = 7; + moby->state = LIFT_WAIT_AT_BOTTOM_FOR_HERO_TO_LEAVE; if (moby->command != 0) jet_end_mount(2); } @@ -154,10 +154,10 @@ void lift_update(struct Moby *moby) { lift_vars->voice = -1; } if (hero.ground_moby != moby) { - if (moby->state == 7) - moby->state = 5; + if (moby->state == LIFT_WAIT_AT_BOTTOM_FOR_HERO_TO_LEAVE) + moby->state = LIFT_IDLE_AT_BOTTOM; else - moby->state = 4; + moby->state = LIFT_IDLE_AT_TOP; } break; case LIFT_IDLE_AT_TOP: @@ -173,29 +173,29 @@ void lift_update(struct Moby *moby) { if (hero.ground_moby == moby && hero.air_frames.s == 0 && vector_distance_xy(&hero.motion.pos, &moby->pos) < 0.5f) { moby->glow_color = 0x80208020; - if (moby->state == 5) + if (moby->state == LIFT_IDLE_AT_BOTTOM) moby->command = 2; else moby->command = 3; - moby->state = 1; + moby->state = LIFT_BLEND_TO_MOUNT_TRANSFORM; hero_set_state(0x72, 1); jet_mount(D_L13_001670C0, D_L13_001670C0 + 0x10, 1, 0, 0); lift_vars->blend = 0.0f; break; } - if (moby->state == 4) { + if (moby->state == LIFT_IDLE_AT_TOP) { float d = vector_distance_xy(&moby->pos, &hero.motion.pos); if (absolute_float(hero.ground_z.f - lift_vars->bottom) < 2.0f && d < 32.0f && d > 5.0f) { moby->command = 0; - moby->state = 3; + moby->state = LIFT_MOVE_TO_BOTTOM; lift_vars->speed = -(D_0015ED6C * 5.0f); } - } else if (moby->state == 5) { + } else if (moby->state == LIFT_IDLE_AT_BOTTOM) { float d = vector_distance_xy(&moby->pos, &hero.motion.pos); if (absolute_float(hero.ground_z.f - lift_vars->top) < 2.0f && d < 32.0f && d > 5.0f) { moby->command = 0; - moby->state = 2; + moby->state = LIFT_MOVE_TO_TOP; lift_vars->speed = D_0015ED6C * 5.0f; } } From 04bd5ec38f1eec59498861013f066add3490e99f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:30:34 +0000 Subject: [PATCH 0959/1502] decomp: clarify names in bolt_thief_update domain_0_value_6 -> BOLT_THIEF_STATE_KNOCKBACK: Retail 0x002fe374-0x002fe378 compares the moby state byte at +0x20 against 6 before initializing the knockback record at data+0x70. This is the exact selector dispatched at 0x002fe428; existing case BOLT_THIEF_STATE_KNOCKBACK steps that record at 0x002fe864-0x002fe86c. domain_12_value_1 -> BOLT_THIEF_STATE_FACE_HERO: Retail 0x002fe760-0x002fe774 stores 1 to moby+0x20 after endpoint settling and clears the turn field. The same switch's existing BOLT_THIEF_STATE_FACE_HERO case at 0x002fe58c-0x002fe5d4 turns toward hero-minus-moby heading. domain_13_value_5 -> BOLT_THIEF_STATE_FOLLOW_SECONDARY_PATH: Retail 0x002fe7a0-0x002fe7c4 stores 5 to the switch selector moby+0x20 and resets path timer/counter. Existing BOLT_THIEF_STATE_FOLLOW_SECONDARY_PATH calls path movement at 0x002fe7c8; authoritative helper selects data+0xDC secondary path specifically for state 5. domain_14_value_2 -> BOLT_THIEF_STATE_WAIT_FOR_TRIGGER: Retail 0x002fe7c8-0x002fe82c writes 2 to moby+0x20 on secondary-path completion, resets progress, and copies the primary starting position. Existing BOLT_THIEF_STATE_WAIT_FOR_TRIGGER on the same selector waits for the hero clip-volume test at 0x002fe5e0-0x002fe5f0. domain_1_value_6 -> BOLT_THIEF_STATE_KNOCKBACK: Retail 0x002fe398-0x002fe424 initializes knockback at data+0x70, calls trooper_start_knockback, and stores 6 to moby+0x20. That byte is the switch selector and existing BOLT_THIEF_STATE_KNOCKBACK case advances the same record. domain_3_value_1 -> BOLT_THIEF_STATE_FACE_HERO: Retail 0x002fe468-0x002fe478 writes 1 to moby+0x20 and clears data+0xF0 turn. The switch on that same byte dispatches case 1 at 0x002fe58c-0x002fe5d4, deriving hero-minus-moby XY heading and spring turning toward it, matching existing BOLT_THIEF_STATE_FACE_HERO. domain_5_value_2 -> BOLT_THIEF_STATE_WAIT_FOR_TRIGGER: Retail 0x002fe55c-0x002fe580 initializes the path and stores 2 to moby+0x20. Case 2 on the same state byte calls the hero-position clip-volume test using data+0xE0 at 0x002fe5e0-0x002fe5f0 and waits unless true, matching existing BOLT_THIEF_STATE_WAIT_FOR_TRIGGER. domain_7_value_4 -> BOLT_THIEF_STATE_FOLLOW_PRIMARY_PATH: Retail 0x002fe5e0-0x002fe658 stores 4 to moby+0x20 after the trigger test succeeds. Existing case BOLT_THIEF_STATE_FOLLOW_PRIMARY_PATH calls update_bolt_thief_path_movement at 0x002fe678; authoritative helper source selects data+0xD8 primary path unless state is 5. domain_9_value_3 -> BOLT_THIEF_STATE_SETTLE_AT_PATH_END: Retail 0x002fe678-0x002fe68c writes 3 to the switched moby+0x20 byte when path movement completes. Existing case BOLT_THIEF_STATE_SETTLE_AT_PATH_END at 0x002fe6a8-0x002fe73c reads the primary path endpoint at path+count*16 and springs XYZ toward it. --- src/overlays/l14/mobys/bolt_thief.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/l14/mobys/bolt_thief.c b/src/overlays/l14/mobys/bolt_thief.c index 0b89fcd150..a1b312cf83 100644 --- a/src/overlays/l14/mobys/bolt_thief.c +++ b/src/overlays/l14/mobys/bolt_thief.c @@ -133,7 +133,7 @@ void bolt_thief_update(L16CrateMoby *moby) { if (hero.coll_hit_moby == moby && moby->animation != 1 && moby->frame != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(5)); hit = find_moby_hit(moby, 0x210000, 0); - if (hit && moby->state != 6) { + if (hit && moby->state != BOLT_THIEF_STATE_KNOCKBACK) { struct Hero *player = &hero; moby_data->knock_drag = 0.008f; @@ -151,13 +151,13 @@ void bolt_thief_update(L16CrateMoby *moby) { moby->position[1] - player->motion.pos.f[1])); moby_data->ticks = 0x78; FUN_L00_00257470(moby, 0, -1); - moby->state = 6; + moby->state = BOLT_THIEF_STATE_KNOCKBACK; } moby->opacity = 0xFF; switch (moby->state) { case BOLT_THIEF_STATE_INITIALIZE: if (moby_data->mode == 2) { - moby->state = 1; + moby->state = BOLT_THIEF_STATE_FACE_HERO; moby_data->turn = 0.0f; set_moby_animation(moby, 4, 0); } else { @@ -189,7 +189,7 @@ void bolt_thief_update(L16CrateMoby *moby) { return; } initialize_moby_path_state(moby); - moby->state = 2; + moby->state = BOLT_THIEF_STATE_WAIT_FOR_TRIGGER; moby->collision = 0x80; moby->flags |= 0x41; moby->bounds = 0; @@ -220,14 +220,14 @@ void bolt_thief_update(L16CrateMoby *moby) { } moby->flags &= 0xFFBE; moby->bounds = moby->model->bounds; - moby->state = 4; + moby->state = BOLT_THIEF_STATE_FOLLOW_PRIMARY_PATH; } break; case BOLT_THIEF_STATE_FOLLOW_PRIMARY_PATH: if (moby_data->mode == 0) update_linked_moby_position(moby); if (update_bolt_thief_path_movement((char *)moby)) { - moby->state = 3; + moby->state = BOLT_THIEF_STATE_SETTLE_AT_PATH_END; blend_moby_animation(moby, 3, 0, 5); } emit_moby_offset_particles(moby); @@ -262,7 +262,7 @@ void bolt_thief_update(L16CrateMoby *moby) { zero); if ((moby->status & 2) && moby->frame == moby->animation) { if (settle_data->mode == 1) { - moby->state = 1; + moby->state = BOLT_THIEF_STATE_FACE_HERO; settle_data->turn = zero; set_moby_animation(moby, 4, 0); } else { @@ -270,7 +270,7 @@ void bolt_thief_update(L16CrateMoby *moby) { moby_set_state_one(settle_data->child); settle_data->child = 0; } - moby->state = 5; + moby->state = BOLT_THIEF_STATE_FOLLOW_SECONDARY_PATH; blend_moby_animation(moby, 0, 0, 20); settle_data->timer = zero; settle_data->counter = 0; @@ -283,7 +283,7 @@ void bolt_thief_update(L16CrateMoby *moby) { if (update_bolt_thief_path_movement((char *)moby)) { char *path; - moby->state = 2; + moby->state = BOLT_THIEF_STATE_WAIT_FOR_TRIGGER; moby->bounds = 0; moby->flags |= 0x41; moby_data->timer = 0.0f; From d96473c006c054707e4159e1a9907c3154e4962d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:30:34 +0000 Subject: [PATCH 0960/1502] decomp: clarify names in sam_update domain_0_value_1 -> SAM_STATE_DIALOGUE: Retail s3 holds the Sam moby (0x002fefec); dispatch reads its state byte at +0x20 (0x002ff01c), and value 1 branches to dialogue handling at 0x002ff0f0. After initialize_npc_dialogue at 0x002ff0dc, 0x002ff0e4 stores s0=1 to that same byte. The source switch already names this exact selector value SAM_STATE_DIALOGUE. domain_1_value_2 -> SAM_STATE_POST_DIALOGUE_WAIT: After update_npc_dialogue returns nonzero at 0x002ff184-0x002ff18c, retail primes the camera target and stores v0=2 to Sam moby+0x20 at 0x002ff1d0-0x002ff1dc. Dispatch of the same byte at 0x002ff040 selects 0x002ff1e0, which waits while D_L14_0015F5C4==2. The source names that exact state SAM_STATE_POST_DIALOGUE_WAIT. domain_2_value_1 -> SAM_STATE_DIALOGUE: The state-2 branch at 0x002ff1e0-0x002ff1e8 retains Sam's state while D_L14_0015F5C4==2; otherwise 0x002ff1f0 stores s0=1 into the same moby+0x20 byte read by dispatch. Value 1 dispatches to update_npc_dialogue handling at 0x002ff0f0/0x002ff184, matching the existing SAM_STATE_DIALOGUE member; the separate global comparison is not renamed. --- src/overlays/l14/mobys/sam.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l14/mobys/sam.c b/src/overlays/l14/mobys/sam.c index 22de2b918f..7e074d050d 100644 --- a/src/overlays/l14/mobys/sam.c +++ b/src/overlays/l14/mobys/sam.c @@ -143,7 +143,7 @@ void sam_update(L14WatchMoby *moby) { } moby_data->p20 = (void *)sam_dialogue_name_text; initialize_npc_dialogue(moby, moby_data); - moby->state = 1; + moby->state = SAM_STATE_DIALOGUE; moby_data->b8 = 1; break; } @@ -165,12 +165,12 @@ void sam_update(L14WatchMoby *moby) { qcopy(D_L14_0016CF60.q10, t + 0x30); clear_u64_value((char *)&D_L14_0016CF60 + 0x20); D_L14_0016CF60.f28 = *(float *)(t + 0x78); - moby->state = 2; + moby->state = SAM_STATE_POST_DIALOGUE_WAIT; } break; case SAM_STATE_POST_DIALOGUE_WAIT: if (D_L14_0015F5C4 != 2) { - moby->state = 1; + moby->state = SAM_STATE_DIALOGUE; if ((short)moby_data->sub == 4) { unlock_planet(0xF); queue_planet_unlock_message(0xF); From 8cfffeec6026912966d51968d8b4b27a0b7bb7ff Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:30:34 +0000 Subject: [PATCH 0961/1502] decomp: clarify names in skid_mcmarx_update domain_0_value_1 -> SKID_MCMARX_IDLE_AND_TALK: Current C source SHA-256 6cf0d6233460f6fe60def8b7c8d46ca51f3a05a4e373d13a13db4b4bc1651119 already defines SKID_MCMARX_IDLE_AND_TALK=1 for switch(moby->state). Retail 0x002e1968 keeps moby in s1; 0x002e1998 reads its state byte at +0x20 and 0x002e199c dispatches 1 to 0x002e1a0c. Initialization at 0x002e19ec stores s5=1 to the exact same byte after installing dialogue data, before dialogue/grounding initialization. Original Ghidra agrees. Reuse the same selector's canonical member for this initialization-to-idle assignment. domain_1_value_2 -> SKID_MCMARX_CONVERSATION_ACTIVE: The source's existing local enum defines SKID_MCMARX_CONVERSATION_ACTIVE=2 for switch(moby->state). Retail 0x002e1a44-0x002e1a50 tests update_npc_dialogue's return; success calls the dialogue camera transition at 0x002e1a60, then 0x002e1a68 loads 2 and 0x002e1a6c stores it to moby+0x20, the same byte dispatched by 0x002e1998/0x002e19bc to the conversation-active case at 0x002e1b78. Original Ghidra confirms the success-path store. This is reuse within the proven NPC state domain. domain_3_value_1 -> SKID_MCMARX_IDLE_AND_TALK: Retail 0x002e1b78 is the moby+0x20==2 branch; 0x002e1c04 loads level_game_mode_macro, and 0x002e1c08 compares it with s4, the current NPC state 2 loaded at 0x002e1998. The taken branch's delay slot 0x002e1c0c writes s5=1 to the same moby+0x20 byte. The original Ghidra expresses this as if(iVar10!=2) state=1, and the SHA-bound source likewise returns to 1. The existing SKID_MCMARX_IDLE_AND_TALK=1 case on this exact selector updates dialogue and idle animations; reuse that canonical member without naming the separate game-mode selector. --- src/overlays/l02/mobys/skid_mcmarx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l02/mobys/skid_mcmarx.c b/src/overlays/l02/mobys/skid_mcmarx.c index 239e36c2dd..aa65a0cd8d 100644 --- a/src/overlays/l02/mobys/skid_mcmarx.c +++ b/src/overlays/l02/mobys/skid_mcmarx.c @@ -67,7 +67,7 @@ void skid_mcmarx_update(struct Moby *moby) { } watcher_vars->unk180 = 0; watcher_vars->dialog = skid_mcmarx_dialogue_data; - moby->state = 1; + moby->state = SKID_MCMARX_IDLE_AND_TALK; moby->update_dist = 0xFF; initialize_npc_dialogue(moby, watcher_vars); initialize_moby_grounding(moby); @@ -80,7 +80,7 @@ void skid_mcmarx_update(struct Moby *moby) { watcher_vars->talk_radius = 2.5f; if (update_npc_dialogue(moby, watcher_vars)) { begin_dialogue_camera_transition(moby, 2.5f); - moby->state = 2; + moby->state = SKID_MCMARX_CONVERSATION_ACTIVE; } if (watcher_vars->talk_state == 2) { help_request(2000, 10); @@ -114,7 +114,7 @@ void skid_mcmarx_update(struct Moby *moby) { D_L02_0016CE60.placed = 1; } if (level_game_mode_macro != 2) - moby->state = 1; + moby->state = SKID_MCMARX_IDLE_AND_TALK; break; } rate = 0.02f; From f41e6ffaa71babb5276eb0ddcbd81fd132266e86 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:32:24 +0000 Subject: [PATCH 0962/1502] decomp: clarify names in update_moby_glow_and_contact_explosion domain_0_value_0 -> BREAKABLE_LAMP_STATE_UNINITIALIZED: The source tests moby->state == 0 before packing configured glow RGB into moby->glow_color and spark RGB into private color. Original retail decompilation tests byte moby+0x20 for zero; lbu/bne at 0x0031c930-0x0031c934 skips exactly this initialization for nonzero state. This proves zero is the lamp's pre-initialization state. domain_1_value_1 -> BREAKABLE_LAMP_STATE_INITIALIZED: Within the zero-state initialization block, retail li v0,1 and sb v0,0x20(s2) at 0x0031c93c-0x0031c944 set the same moby state byte to one. RGB packing follows at 0x0031c948-0x0031c988. Subsequent updates with this nonzero state skip color initialization through the branch at 0x0031c934, proving the initialized state role. --- src/overlays/shared/props/breakable_lamp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/props/breakable_lamp.c b/src/overlays/shared/props/breakable_lamp.c index 0591900483..98c9d3348c 100644 --- a/src/overlays/shared/props/breakable_lamp.c +++ b/src/overlays/shared/props/breakable_lamp.c @@ -76,7 +76,7 @@ void breakable_lamp_update(struct Moby *moby) __asm__("FUN_L05_0031c8e0"); /* Moby class 1511 */ void breakable_lamp_update(struct Moby *moby) { - struct MineVars_c8e0 *glow_and_spark_state = (struct MineVars_c8e0 *)moby->pvars; + enum { BREAKABLE_LAMP_STATE_UNINITIALIZED = 0 , BREAKABLE_LAMP_STATE_INITIALIZED = 1 } ;struct MineVars_c8e0 *glow_and_spark_state = (struct MineVars_c8e0 *)moby->pvars; Vec4 tip; Vec4 debris_velocity; Vec4 effect_motion; @@ -96,8 +96,8 @@ void breakable_lamp_update(struct Moby *moby) { s32 i; s32 frames; - if (moby->state == 0) { - moby->state = 1; + if (moby->state == BREAKABLE_LAMP_STATE_UNINITIALIZED) { + moby->state = BREAKABLE_LAMP_STATE_INITIALIZED; moby->glow_color = (0x7F000000 | glow_and_spark_state->glow_b << 16 | glow_and_spark_state->glow_g << 8) | glow_and_spark_state->glow_r; From b706d772b0f5caa2b941e1e33648e31223b5d0e8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:32:24 +0000 Subject: [PATCH 0963/1502] decomp: clarify names in ammocrate_update domain_0_value_5 -> AMMOCRATE_STATE_REMOVE: Retail 0x0030f840-0x0030f844 writes 5 to pickup state at s2+0x20 after the collision explosion. The same byte selects the existing AMMOCRATE_STATE_REMOVE switch branch, which calls mark_moby_for_removal at 0x0030fcc4 and returns. domain_1_value_4 -> AMMOCRATE_STATE_COLLECTED: Retail 0x0030f848-0x0030f850 loads pickup state at s2+0x20 and compares it unsigned against 4 to gate collection. That exact field is the switch selector at 0x0030fa20; its existing AMMOCRATE_STATE_COLLECTED member is 4, following collision disabling and ship resource awards. domain_4_value_4 -> AMMOCRATE_STATE_COLLECTED: In the OCLASS_SHIP_AMMO_PICKUP branch, retail 0x0030f95c-0x0030f9b0 adds five ammunition units, clamps to maximum, and reaches the state-4 store at 0x0030fa1c. The same pickup state selector already defines 4 as AMMOCRATE_STATE_COLLECTED. domain_5_value_4 -> AMMOCRATE_STATE_COLLECTED: In the OCLASS_SHIP_HEALTH_PICKUP branch, retail 0x0030f9b4-0x0030fa14 adds one quarter maximum ship health and clamps it, then 0x0030fa18-0x0030fa1c writes 4 to pickup+0x20. This is the existing AMMOCRATE_STATE_COLLECTED selector domain. domain_6_value_4 -> AMMOCRATE_STATE_COLLECTED: Retail 0x0030f93c-0x0030f958 handles the pickup class default after collection disables collisions: when neither resource class matches, it stores 4 to s2+0x20. This exact pickup state field selects the existing AMMOCRATE_STATE_COLLECTED switch case. domain_7_value_1 -> AMMOCRATE_STATE_DAMPED_FALL: Retail initialization at 0x0030fa48-0x0030fa60 clears the child pointer and phase, refreshes the child, and supplies 1 to the pickup state store at 0x0030fca0. The same state field's existing AMMOCRATE_STATE_DAMPED_FALL branch damps velocity by 0.9 and applies gravity at 0x0030fa64-0x0030fab0. domain_8_value_2 -> AMMOCRATE_STATE_ATTRACT_TO_SHIP: Retail 0x0030fad8-0x0030fb04 tests child sequence 1, damps velocity by 0.8 and supplies 2 to the pickup state store at 0x0030fca0. This same pickup selector already names 2 AMMOCRATE_STATE_ATTRACT_TO_SHIP; its branch adds the normalized ship-minus-pickup direction to velocity at 0x0030fbe4-0x0030fc10. domain_9_value_5 -> AMMOCRATE_STATE_REMOVE: Retail case 4 at 0x0030fc9c-0x0030fca0 writes 5 to pickup+0x20 after collection. That exact byte selects the established AMMOCRATE_STATE_REMOVE case, which routes directly to removal at 0x0030fcc4 and exits. --- src/overlays/l11/mobys/ammocrate.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l11/mobys/ammocrate.c b/src/overlays/l11/mobys/ammocrate.c index f0c6ebff7c..4afb0778e9 100644 --- a/src/overlays/l11/mobys/ammocrate.c +++ b/src/overlays/l11/mobys/ammocrate.c @@ -137,10 +137,10 @@ void ammocrate_update(struct Moby *pickup) { 1, -1, 0); - pickup->state = 5; + pickup->state = AMMOCRATE_STATE_REMOVE; } } - if (pickup->state < 4) { + if (pickup->state < AMMOCRATE_STATE_COLLECTED) { if (hero.state.current == 0x32 && ship != 0 && ship->state != 0xFE && ship->state != 0xFD && (ship->oclass == 0x4DA || ship->oclass == 0x45 || ship->oclass == 0x563)) { ship_pickup_distance_metric = fast_vec_dist(&ship->pos, &pickup->pos); @@ -164,7 +164,7 @@ void ammocrate_update(struct Moby *pickup) { if (hero.ship_ammo_max < hero.ship_ammo) { hero.ship_ammo = hero.ship_ammo_max; } - pickup->state = 4; + pickup->state = AMMOCRATE_STATE_COLLECTED; break; case OCLASS_SHIP_HEALTH_PICKUP: hero.ship_hp += hero.ship_hp_max * 0.25f; @@ -175,10 +175,10 @@ void ammocrate_update(struct Moby *pickup) { if (hero.ship_hp_max < hero.ship_hp) { hero.ship_hp = hero.ship_hp_max; } - pickup->state = 4; + pickup->state = AMMOCRATE_STATE_COLLECTED; break; default: - pickup->state = 4; + pickup->state = AMMOCRATE_STATE_COLLECTED; break; } } @@ -188,7 +188,7 @@ void ammocrate_update(struct Moby *pickup) { pickup_vars->unk34 = 0; sync_ship_pickup_child_pose(pickup, pickup_vars); pickup_vars->unk30 = 0.0f; - pickup->state = 1; + pickup->state = AMMOCRATE_STATE_DAMPED_FALL; break; case AMMOCRATE_STATE_DAMPED_FALL: fast_vec_scale(&pickup_vars->unk10, &pickup_vars->unk10, 0.9f); @@ -198,7 +198,7 @@ void ammocrate_update(struct Moby *pickup) { if (sync_ship_pickup_child_pose(pickup, pickup_vars)) { if (pickup_vars->unk34->seq == 1) { fast_vec_scale(&pickup_vars->unk10, &pickup_vars->unk10, 0.8f); - pickup->state = 2; + pickup->state = AMMOCRATE_STATE_ATTRACT_TO_SHIP; } } break; @@ -229,7 +229,7 @@ void ammocrate_update(struct Moby *pickup) { fast_vec_add(&pickup->pos, &pickup->pos, &pickup_vars->unk10); break; case AMMOCRATE_STATE_COLLECTED: - pickup->state = 5; + pickup->state = AMMOCRATE_STATE_REMOVE; break; case AMMOCRATE_STATE_REMOVE: mark_moby_for_removal(pickup); From 83ce25f757e8ffc65cba4ce33b840fe29b244448 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:32:24 +0000 Subject: [PATCH 0964/1502] decomp: clarify names in update_split_door domain_0_value_1 -> SPLIT_DOOR_PHASE_TARGET_CURRENT_TRANSFORMS: Retail 0x002fc304 loads the door's own phase byte from moby+0xbc; 0x002fc308-0x002fc30c tests 1 and enters 0x002fc368. That branch loads parent/child current distances from sp+0x18 and f0 and current rotation-Y from each moby+0x44 (0x002fc37c-0x002fc388), supplying them as interpolation targets. This is a door animation phase, not hero state or the moby+0x20 state. domain_1_value_2 -> SPLIT_DOOR_PHASE_TARGET_CONFIGURED_TRANSFORMS: The signed slti at 0x002fc314 compares the zero-extended door phase byte from moby+0xbc against 2 after excluding phase 1. The same 2 is tested at 0x002fc320 to enter 0x002fc394, which loads configured distance targets and parent/child rotation-Y targets (0x002fc3a4-0x002fc3b0). Using the configured-target phase member preserves this numeric ordering test; it does not name the default branch. domain_2_value_2 -> SPLIT_DOOR_PHASE_TARGET_CONFIGURED_TRANSFORMS: Retail 0x002fc31c-0x002fc320 tests door phase byte moby+0xbc against 2 and branches to 0x002fc394. Parent distance is loaded at 0x002fc324, child distance at 0x002fc3a4, and configured parent/child rotation-Y at 0x002fc3a8/0x002fc3b0. They feed paired distance and rotation interpolation at 0x002fc3dc-0x002fc4a8. domain_3_value_1 -> SPLIT_DOOR_PHASE_TARGET_CURRENT_TRANSFORMS: The default phase path sets next_phase in s2 to 1 at 0x002fc330 and next_timer to 30 at 0x002fc338. On countdown expiry 0x002fc4fc-0x002fc50c stores s2 into the same moby+0xbc selector. Its next update therefore selects the phase-1 branch 0x002fc368, whose targets are current parent/child distances and rotation-Y values. domain_4_value_2 -> SPLIT_DOOR_PHASE_TARGET_CONFIGURED_TRANSFORMS: The phase-1 current-transform-target branch selects s2=2 at 0x002fc390 and samples the phase-two duration from gp-0x4cac/-0x4ca8 at 0x002fc36c-0x002fc378. Countdown expiry writes s2 to moby+0xbc at 0x002fc50c, selecting the configured-distance and configured-rotation branch 0x002fc394 on the next update. domain_5_value_1 -> SPLIT_DOOR_PHASE_TARGET_CURRENT_TRANSFORMS: The phase-2 configured-target branch selects s2=1 at 0x002fc3ac and samples phase-one duration from gp-0x4cb4/-0x4cb0 at 0x002fc394-0x002fc3a0. Timer expiry stores s2 to moby+0xbc at 0x002fc50c. Phase 1 then uses the measured current distances and current rotation-Y values as interpolation targets at 0x002fc37c-0x002fc388. --- src/overlays/l06/mobys/split_door.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l06/mobys/split_door.c b/src/overlays/l06/mobys/split_door.c index 20348477df..9942297cb6 100644 --- a/src/overlays/l06/mobys/split_door.c +++ b/src/overlays/l06/mobys/split_door.c @@ -88,7 +88,7 @@ void split_door_update(char *moby) { MOVE_PAIR_TO_FIXED_OFFSETS = 3, ANIMATE_PAIR_WITH_TIMED_PHASES = 4, WAIT_FOR_RESET = 5 - }; + } ; enum { SPLIT_DOOR_PHASE_TARGET_CURRENT_TRANSFORMS = 1 , SPLIT_DOOR_PHASE_TARGET_CONFIGURED_TRANSFORMS = 2}; SplitDoorVars *pair_transform_vars = (SplitDoorVars *)MOBY(moby)->pvars; char *child; float position_offset[4]; @@ -178,11 +178,11 @@ void split_door_update(char *moby) { phase_a = target_delta; phase_b = fast_vec_dist(child + 0x10, &pair_transform_vars->unk10); phase = (unsigned char)MOBY(moby)->command; - if (phase == 1) + if (phase == SPLIT_DOOR_PHASE_TARGET_CURRENT_TRANSFORMS) goto phase_one; - if (phase < 2) + if (phase < SPLIT_DOOR_PHASE_TARGET_CONFIGURED_TRANSFORMS) goto phase_default; - if (phase == 2) + if (phase == SPLIT_DOOR_PHASE_TARGET_CONFIGURED_TRANSFORMS) goto phase_two; phase_default: @@ -196,7 +196,7 @@ void split_door_update(char *moby) { rotation_acceleration = 10.0f; rotation_speed = 10.0f; rotation_damping = 5.0f; - next_phase = 1; + next_phase = SPLIT_DOOR_PHASE_TARGET_CURRENT_TRANSFORMS; next_timer = 30; goto phase_join; phase_one: @@ -210,7 +210,7 @@ void split_door_update(char *moby) { rotation_acceleration = moby_pair_phase_rotation_y_acceleration_degrees_gp; rotation_speed = moby_pair_phase_rotation_y_deceleration_degrees_gp; rotation_damping = moby_pair_phase_rotation_y_max_speed_degrees_gp; - next_phase = 2; + next_phase = SPLIT_DOOR_PHASE_TARGET_CONFIGURED_TRANSFORMS; next_timer = truncate_float_to_s32( random_float_between((float)moby_pair_phase_two_duration_min_frames_gp, (float)moby_pair_phase_two_duration_max_frames_gp)); @@ -226,7 +226,7 @@ void split_door_update(char *moby) { rotation_acceleration = moby_pair_phase_rotation_y_acceleration_degrees_gp; rotation_speed = moby_pair_phase_rotation_y_deceleration_degrees_gp; rotation_damping = moby_pair_phase_rotation_y_max_speed_degrees_gp; - next_phase = 1; + next_phase = SPLIT_DOOR_PHASE_TARGET_CURRENT_TRANSFORMS; next_timer = truncate_float_to_s32( random_float_between((float)moby_pair_phase_one_duration_min_frames_gp, (float)moby_pair_phase_one_duration_max_frames_gp)); From 0d7af757f7150bb92774dc61873a0f16b7e7b2ee Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:32:24 +0000 Subject: [PATCH 0965/1502] decomp: clarify names in elevator_update domain_0_value_3 -> ELEVATOR_STATE_MOVE_TO_BOTTOM: Initialization at 0x002b3a78-0x002b3a80 stores 3 to moby+0x20, the switch selector loaded at 0x002b3a3c. The existing state-3 branch selects LiftVars.bottom (+0x64) at 0x002b3bf4-0x002b3c04 and advances pos.z toward it. domain_10_value_3 -> ELEVATOR_STATE_MOVE_TO_BOTTOM: The automatic return path at 0x002b3eec-0x002b3f68 checks hero height near LiftVars.bottom, clears camera command, stores 3 to moby+0x20 at 0x002b3f54, and gives speed a negative sign. Existing case 3 advances pos.z to bottom. domain_11_value_5 -> ELEVATOR_STATE_WAIT_AT_BOTTOM: At 0x002b3ed0 and 0x002b3f6c the branch compares the moby+0x20 selector to 5. This path checks hero height near LiftVars.top and starts upward movement 2, reusing the existing ELEVATOR_STATE_WAIT_AT_BOTTOM member. domain_12_value_2 -> ELEVATOR_STATE_MOVE_TO_TOP: At 0x002b3f8c-0x002b4004 the automatic return path checks hero height against LiftVars.top, clears camera command, stores 2 to moby+0x20 at 0x002b3ff4 and initializes positive speed. Existing case 2 advances pos.z toward top. domain_1_value_2 -> ELEVATOR_STATE_MOVE_TO_TOP: At 0x002b3bf4-0x002b3c04 the comparison reads moby+0x20 and selects LiftVars.top (+0x60) for state 2, otherwise bottom (+0x64). It is the same selector as the existing ELEVATOR_STATE_MOVE_TO_TOP switch case. domain_2_value_2 -> ELEVATOR_STATE_MOVE_TO_TOP: After pos.z reaches its target, 0x002b3c64-0x002b3c78 compares moby+0x20 with 2 to distinguish the top movement from bottom movement. This is the same state-2 domain whose target is LiftVars.top at 0x002b3c04. domain_3_value_6 -> ELEVATOR_STATE_WAIT_FOR_HERO_EXIT_AT_TOP: When the state-2 top movement reaches its target, 0x002b3c68-0x002b3c78 stores 6 to moby+0x20. Existing case 6 releases voice and waits for the grounded centered hero to leave, then enters the top waiting state at 0x002b3ca0-0x002b3d30. domain_4_value_7 -> ELEVATOR_STATE_WAIT_FOR_HERO_EXIT_AT_BOTTOM: At target equality, bottom movement state 3 selects 7 and stores it to moby+0x20 at 0x002b3c70-0x002b3c78. Existing case 7 releases voice, waits for hero departure, and enters bottom waiting state 5 at 0x002b3d10-0x002b3d24. domain_5_value_5 -> ELEVATOR_STATE_WAIT_AT_BOTTOM: In the existing exit-wait cases, 0x002b3d10-0x002b3d24 maps state 7, reached after bottom arrival, to state 5 in moby+0x20 after hero departure. This reuses the existing ELEVATOR_STATE_WAIT_AT_BOTTOM selector member. domain_6_value_4 -> ELEVATOR_STATE_WAIT_AT_TOP: The top exit-wait path stores 4 to moby+0x20 at 0x002b3d28-0x002b3d30 after the hero-departure guard. Case 6 was reached from movement toward LiftVars.top, proving reuse of existing ELEVATOR_STATE_WAIT_AT_TOP. domain_7_value_5 -> ELEVATOR_STATE_WAIT_AT_BOTTOM: At 0x002b3e68-0x002b3e88, centered grounded reboarding compares moby+0x20 against 5; that branch requests movement 2 toward LiftVars.top. It is the existing bottom waiting case, entered from bottom exit-wait state 7. domain_8_value_1 -> ELEVATOR_STATE_BLEND_CAMERA: Reboarding stores 1 to moby+0x20 at 0x002b3e8c-0x002b3e9c, mounts the camera and clears blend at pvars+0x70. The same selector's existing case 1 advances that blend and applies camera pose at 0x002b3a84-0x002b3b98. domain_9_value_4 -> ELEVATOR_STATE_WAIT_AT_TOP: At 0x002b3ec4-0x002b3ecc the comparison reads moby+0x20 against 4. Its branch tests hero height against LiftVars.bottom and initiates downward movement 3, consistent with the existing top waiting case reached from top exit-wait. --- src/overlays/l13/mobys/elevator.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/overlays/l13/mobys/elevator.c b/src/overlays/l13/mobys/elevator.c index b7c1850c88..e0b5529fb6 100644 --- a/src/overlays/l13/mobys/elevator.c +++ b/src/overlays/l13/mobys/elevator.c @@ -79,7 +79,7 @@ void elevator_update(struct Moby *moby) { case ELEVATOR_STATE_INITIALIZE: elevator_vars->pulse = random_angle_radians(); elevator_vars->voice = -1; - moby->state = 3; + moby->state = ELEVATOR_STATE_MOVE_TO_BOTTOM; break; case ELEVATOR_STATE_BLEND_CAMERA: { float previous_camera_blend = elevator_vars->blend; @@ -127,7 +127,7 @@ void elevator_update(struct Moby *moby) { set_camera_position(camera_position_scratch); set_camera_rotation(camera_pose_scratch); } - if (moby->state == 2) { + if (moby->state == ELEVATOR_STATE_MOVE_TO_TOP) { target = elevator_vars->top; } else { target = elevator_vars->bottom; @@ -139,10 +139,10 @@ void elevator_update(struct Moby *moby) { D_0015ED70_2b39e0 * 8.0f, frame_time * 40.0f); if (absolute_float(moby->pos.z - target) == 0.0f) { - if (moby->state == 2) { - moby->state = 6; + if (moby->state == ELEVATOR_STATE_MOVE_TO_TOP) { + moby->state = ELEVATOR_STATE_WAIT_FOR_HERO_EXIT_AT_TOP; } else { - moby->state = 7; + moby->state = ELEVATOR_STATE_WAIT_FOR_HERO_EXIT_AT_BOTTOM; } if (moby->command != 0) { hero_set_state(HERO_STATE_IDLE, 0); @@ -162,9 +162,9 @@ void elevator_update(struct Moby *moby) { u8 s = moby->state; elevator_vars->armed = 0; if (s == 7) { - moby->state = 5; + moby->state = ELEVATOR_STATE_WAIT_AT_BOTTOM; } else { - moby->state = 4; + moby->state = ELEVATOR_STATE_WAIT_AT_TOP; } } break; @@ -189,31 +189,31 @@ void elevator_update(struct Moby *moby) { if (elevator_vars->armed != 0 && hero.ground_moby == moby && hero.air_frames.s == 0 && vector_distance_xy(&hero.motion.pos, &moby->pos) < 0.5f) { moby->glow_color = 0x80208020; - if (moby->state == 5) { + if (moby->state == ELEVATOR_STATE_WAIT_AT_BOTTOM) { moby->command = 2; } else { moby->command = 3; } - moby->state = 1; + moby->state = ELEVATOR_STATE_BLEND_CAMERA; hero_set_state(0x72, 1); jet_mount(D_L13_001670C0_2b39e0, D_L13_001670C0_2b39e0 + 0x10, 1, 0, 0); elevator_vars->blend = 0.0f; - } else if (moby->state == 4) { + } else if (moby->state == ELEVATOR_STATE_WAIT_AT_TOP) { char *p = (char *)&hero.motion.pos; float d = vector_distance_xy(&moby->pos, p); if (absolute_float(*(float *)(p + 0x258) - elevator_vars->bottom) < 2.0f && d < 32.0f && d > 5.0f) { moby->command = 0; - moby->state = 3; + moby->state = ELEVATOR_STATE_MOVE_TO_BOTTOM; elevator_vars->speed = -(frame_time * 5.0f); } - } else if (moby->state == 5) { + } else if (moby->state == ELEVATOR_STATE_WAIT_AT_BOTTOM) { char *p = (char *)&hero.motion.pos; float d = vector_distance_xy(&moby->pos, p); if (absolute_float(*(float *)(p + 0x258) - elevator_vars->top) < 2.0f && d < 32.0f && d > 5.0f) { moby->command = 0; - moby->state = 2; + moby->state = ELEVATOR_STATE_MOVE_TO_TOP; elevator_vars->speed = frame_time * 5.0f; } } From 1278f60d0d8d2dbedc164b2a327b3e2b678c2af0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:32:24 +0000 Subject: [PATCH 0966/1502] decomp: clarify names in ammocrate_update domain_0_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002e1da4-0x002e1db4 computes target from moby_base + pickup_private_state[0]*0x100; 0x002e1dc0 loads its Moby state byte +0x20 and 0x002e1dc4 compares 0xFE, bypassing the target-state wait when marked for removal. Supplied mark_moby_for_removal writes MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END (0xFE) to that same Moby.state field when moby >= moby_instance_end. domain_1_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002e1da4-0x002e1db4 resolves the indexed Moby target; 0x002e1dc0 loads target state at +0x20 and 0x002e1dc8-0x002e1dcc compares 0xFD, bypassing the activation gate for a removal-marked target. Supplied mark_moby_for_removal assigns MOBY_STATE_REMOVAL_BELOW_INSTANCE_END (0xFD) to Moby.state when moby < moby_instance_end, proving the selector domain and meaning. domain_2_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002e1d00 loads hero.ship_moby into s4; after its null check, 0x002e1fc0 loads unsigned Moby state byte +0x20 and 0x002e1fc4 rejects 0xFE before ship class and distance checks. This is the same Moby.state field written as MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END (0xFE) by supplied mark_moby_for_removal for moby >= moby_instance_end, rather than the separate hero.state.current selector. domain_3_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail s4 comes from hero.ship_moby at 0x002e1d00; 0x002e1fc0 reads its Moby state +0x20 and 0x002e1fc8-0x002e1fcc rejects 0xFD before distance evaluation. Supplied mark_moby_for_removal writes MOBY_STATE_REMOVAL_BELOW_INSTANCE_END (0xFD) to this Moby.state domain for moby < moby_instance_end. The rejection excludes a removal-marked ship, independently of hero.state.current checked at 0x002e1fac-0x002e1fb0. --- src/overlays/shared/pickups/fighter_jet_crate.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/pickups/fighter_jet_crate.c b/src/overlays/shared/pickups/fighter_jet_crate.c index ad2abe7cea..62e1a0a1e4 100644 --- a/src/overlays/shared/pickups/fighter_jet_crate.c +++ b/src/overlays/shared/pickups/fighter_jet_crate.c @@ -54,6 +54,10 @@ void ammocrate_update(char *moby) { SHIP_PICKUP_COLLECTED_SHRINKING = 5, SHIP_PICKUP_REMOVE_OR_RESET = 6 }; + enum { + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xfd, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xfe + }; int *pickup_private_state = ((int *)MOBY(moby)->pvars); int hero_moby = ((char *)hero.ship_moby); int hit = 0; @@ -88,7 +92,7 @@ void ammocrate_update(char *moby) { int target_index = pickup_private_state[0]; int target_base = (int)moby_base; struct Moby *target = (struct Moby *)(target_base + target_index * 0x100); - if (target != 0 && target->state != 0xfe && target->state != 0xfd && + if (target != 0 && target->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && target->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && pickup_private_state[1] != -1 && target->state != pickup_private_state[1]) { goto frame_tail; } @@ -129,8 +133,8 @@ void ammocrate_update(char *moby) { if (moby_class == 0x4da || moby_class == 0x45 || moby_class == 0x563) hit = 1; } - if (hero.state.current == 0x32 && hero_moby != 0 && MOBY(hero_moby)->state != 0xfe && - MOBY(hero_moby)->state != 0xfd) { + if (hero.state.current == 0x32 && hero_moby != 0 && MOBY(hero_moby)->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + MOBY(hero_moby)->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { short moby_class = MOBY(hero_moby)->oclass; if (moby_class == 0x4da || moby_class == 0x45 || moby_class == 0x563) distance = fast_vec_dist((void *)&MOBY(hero_moby)->pos, &MOBY(moby)->pos); From 650a8292322d65d2514807db07f2875a701d28f8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:32:24 +0000 Subject: [PATCH 0967/1502] decomp: clarify names in elevator_update domain_0_value_0 -> ELEVATOR_STATE_INITIALIZE: Retail 002ee8fc-002ee900 reads moby+0x20 and skips pre-update path reversal when zero. The same byte selects the switch at 002ee998-002ee9bc; its zero branch 002ee9c4-002eeac8 initializes path, transform and audio. This is the existing local ELEVATOR_STATE_INITIALIZE domain, not command+0xBC. domain_1_value_1 -> ELEVATOR_STATE_WAIT_FOR_RIDER: Retail 002ee9c4-002ee9cc writes 1 to moby+0x20 during initialization. That exact byte selects case 1 at 002eeacc, which waits for hero.ground_moby equality, zero frames off ground and distance below 1 at 002eebd8-002eec10 before movement. Reuse existing ELEVATOR_STATE_WAIT_FOR_RIDER. domain_2_value_2 -> ELEVATOR_STATE_FOLLOW_PATH: Retail 002eebd8-002eec10 proves the rider boarding conditions; 002eec84 stores 2 to moby+0x20 and 002eec88-002eec98 clears travelled distance and reverses direction. That byte dispatches to case 2, calling advance_elevator_along_path at 002eed0c. Reuse existing ELEVATOR_STATE_FOLLOW_PATH. domain_3_value_3 -> ELEVATOR_STATE_SETTLE_AT_ENDPOINT: Retail 002eed0c calls the established advance_elevator_along_path helper; a nonzero completion return causes 002eed18-002eed1c to store 3 to moby+0x20. Case 3 at 002eed60 tests residual velocity against 0.001 and fades motor volume while endpoint settling continues. Reuse existing ELEVATOR_STATE_SETTLE_AT_ENDPOINT. domain_4_value_4 -> ELEVATOR_STATE_WAIT_FOR_RIDER_EXIT: After residual velocity falls below the threshold, retail 002eee28-002eeeac releases owned motor audio and lowers hum, then 002eeeb0-002eeeb8 stores 4 to the switch selector moby+0x20. Case 4 at 002eeec4-002eeedc waits for hero.ground_moby to differ. Reuse existing ELEVATOR_STATE_WAIT_FOR_RIDER_EXIT. domain_5_value_1 -> ELEVATOR_STATE_WAIT_FOR_RIDER: In source SETTLE_AT_ENDPOINT, the assignment to state 1 follows state 4 and is conditional on hero.ground_moby != elevator_moby. Retail 002eeeb8-002eeedc shares this rider-absence branch with case 4, storing 1 to the same moby+0x20 switch byte. Case 1 waits for boarding; reuse ELEVATOR_STATE_WAIT_FOR_RIDER. domain_6_value_1 -> ELEVATOR_STATE_WAIT_FOR_RIDER: Source WAIT_FOR_RIDER_EXIT returns to state 1 only when hero.ground_moby differs from this elevator. Original retail case 4 calls idle glow at 002eeec4, loads ground moby at 002eeed0, compares at 002eeed4 and stores 1 at 002eeedc to moby+0x20. Reuse existing ELEVATOR_STATE_WAIT_FOR_RIDER. domain_7_value_2 -> ELEVATOR_STATE_FOLLOW_PATH: Retail 002eeee0 loads the same moby+0x20 byte used by the switch; 002eeee4-002eeee8 compares it with 2 and skips the common endpoint-settling call at 002eeef8. Case 2 already advances along the path at 002eed0c. This excludes existing ELEVATOR_STATE_FOLLOW_PATH, not command mode 2. domain_8_value_0 -> ELEVATOR_STATE_INITIALIZE: Retail 002eeee0 loads the moby+0x20 switch selector and 002eeef0 skips endpoint settling when it is zero. The zero case initializes path and transforms at 002ee9c4-002eeac8. Therefore this comparison uses existing ELEVATOR_STATE_INITIALIZE, with no relation to hero state or command modes. --- src/overlays/l14/mobys/elevator.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l14/mobys/elevator.c b/src/overlays/l14/mobys/elevator.c index b20edf52d8..e716541d23 100644 --- a/src/overlays/l14/mobys/elevator.c +++ b/src/overlays/l14/mobys/elevator.c @@ -93,7 +93,7 @@ void elevator_update(struct Moby *elevator_moby) { Vec4 delta; float level; - if (elevator_moby->state != 0 && elevator_moby->command == 2 && elevator_vars->dir < 0.0f) { + if (elevator_moby->state != ELEVATOR_STATE_INITIALIZE && elevator_moby->command == 2 && elevator_vars->dir < 0.0f) { int *path = (int *)l14_paths[elevator_vars->path2]; elevator_vars->dir = -elevator_vars->dir; elevator_vars->segment = *path - 2; @@ -106,7 +106,7 @@ void elevator_update(struct Moby *elevator_moby) { case ELEVATOR_STATE_INITIALIZE: { u16 id; elevator_moby->command = 0; - elevator_moby->state = 1; + elevator_moby->state = ELEVATOR_STATE_WAIT_FOR_RIDER; initialize_elevator_path_state(elevator_moby); qcopy(&elevator_moby->pos, ((char *)l14_paths[elevator_vars->path]) + 0x10); qcopy(&elevator_moby->rot, elevator_vars->rot); @@ -166,7 +166,7 @@ void elevator_update(struct Moby *elevator_moby) { else elevator_moby->command = 0; } - elevator_moby->state = 2; + elevator_moby->state = ELEVATOR_STATE_FOLLOW_PATH; elevator_vars->travelled = 0; elevator_vars->dir = -elevator_vars->dir; } @@ -182,7 +182,7 @@ void elevator_update(struct Moby *elevator_moby) { } elevator_moby->glow_color = fast_tween_color(elevator_moby->glow_color, 0x80808040, 0.1f); if (advance_elevator_along_path(elevator_moby) != 0) { - elevator_moby->state = 3; + elevator_moby->state = ELEVATOR_STATE_SETTLE_AT_ENDPOINT; elevator_vars->level = elevator_vars->motor_volume; } rebuild_elevator_world_path((u8 *)elevator_moby); @@ -216,18 +216,18 @@ void elevator_update(struct Moby *elevator_moby) { voice = allocate_voice_for_target_entry(1, 0, elevator_moby); if (voice >= 0) vendor_volume(voice, elevator_vars->hum_volume / 3); - elevator_moby->state = 4; + elevator_moby->state = ELEVATOR_STATE_WAIT_FOR_RIDER_EXIT; if (hero.ground_moby != elevator_moby) - elevator_moby->state = 1; + elevator_moby->state = ELEVATOR_STATE_WAIT_FOR_RIDER; } break; case ELEVATOR_STATE_WAIT_FOR_RIDER_EXIT: update_elevator_idle_glow(elevator_moby); if (hero.ground_moby != elevator_moby) - elevator_moby->state = 1; + elevator_moby->state = ELEVATOR_STATE_WAIT_FOR_RIDER; break; } - if (elevator_moby->state != 2 && elevator_moby->state != 0) { + if (elevator_moby->state != ELEVATOR_STATE_FOLLOW_PATH && elevator_moby->state != ELEVATOR_STATE_INITIALIZE) { settle_elevator_at_path_endpoint(elevator_moby); if (hero.ground_moby == elevator_moby) { fast_vec_sub(&delta, &elevator_moby->pos, &previous_elevator_position); From a116af6227ffc0de45b034663ffa229b94b0eada Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:32:25 +0000 Subject: [PATCH 0968/1502] decomp: clarify names in update_path_camera domain_0_value_4 -> PATH_CAMERA_TRANSITION_PATH_FINISHED: Authoritative source src/overlays/l14/path_camera.c SHA-256 ae53f67210e1411cf6de030a1591ba50078bb32b9ed546d29e37f54292acd788 places this assignment in if(done), after sample_path completion or descriptor/timer termination overrides. Original retail Ghidra lVar8 completion branch agrees: retail 0x0031549c branches around completion when s0 is zero; 0x003154ec loads 4 and 0x003154fc stores it into camera s6+0x7e (UpdateCam.transition_state). The same branch restores end FOV at 0x003154a4-0x003154dc, clears path_camera_active at 0x00315500-0x00315504, and samples hero.rail_spline to place and aim the returning view at 0x00315528-0x0031560c. Thus this is the camera transition value written when the path-camera run finishes; it is not a hero current-state ID. --- src/overlays/l14/path_camera.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l14/path_camera.c b/src/overlays/l14/path_camera.c index b892296770..11d049505e 100644 --- a/src/overlays/l14/path_camera.c +++ b/src/overlays/l14/path_camera.c @@ -155,6 +155,9 @@ extern float cosine_interpolate(float, float, float) __asm__("FUN_002133d0"); void update_path_camera(struct UpdateCam *path_camera) __asm__("FUN_L14_00315290"); void update_path_camera(struct UpdateCam *path_camera) { + enum { + PATH_CAMERA_TRANSITION_PATH_FINISHED = 4 + }; float initial_look_direction_or_previous_position[4]; float t[4]; float u[4]; @@ -216,7 +219,7 @@ void update_path_camera(struct UpdateCam *path_camera) { l14_camera_projection_state.fB0 = fast_sin(ang) / fast_cos(ang); update_view_context(); D_L14_001675D8 = 0.25f; - path_camera->transition_state = 4; + path_camera->transition_state = PATH_CAMERA_TRANSITION_PATH_FINISHED; path_camera_active = 0; mb = D_L14_0015FFD8_5290; reset_racer_group_to_hero_path_position((struct Moby *)(mb + *(int *)(rec + 0x50) * 256)); From bb38e5d6abd17920832d14b287adcfe18ceefe4f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:34:19 +0000 Subject: [PATCH 0969/1502] decomp: clarify names in commando_update domain_0_value_1 -> COMMANDO_DIALOGUE_BEFORE_REPOSITION: Current C assigns moby->state=1 in initialization when D_0013D3B4 is clear. Retail 0x00302e34-0x00302e3c stores 1 to s1+0x20, the exact selector byte loaded at 0x00302d6c and dispatched at 0x00302d74 into the existing COMMANDO_DIALOGUE_BEFORE_REPOSITION case. Original Ghidra agrees: this branch precedes dialogue initialization and state 1 updates dialogue before copying the indexed pose. domain_1_value_2 -> COMMANDO_DIALOGUE_AFTER_REPOSITION: Initialization's alternate branch copies indexed position and rotation into moby+0x10/+0x40 at retail 0x00302e40-0x00302e70, then stores 2 to the selector byte s1+0x20 at 0x00302e78. The same byte is loaded at 0x00302d6c and value 2 dispatches at 0x00302d94 to the existing COMMANDO_DIALOGUE_AFTER_REPOSITION case. SHA-bound C and original Ghidra agree, proving reuse of that local state member. domain_2_value_2 -> COMMANDO_DIALOGUE_AFTER_REPOSITION: In the existing COMMANDO_DIALOGUE_BEFORE_REPOSITION branch, nonzero dialogue update return at retail 0x00302e94-0x00302e9c reaches indexed pose copies 0x00302ea4-0x00302ed4 and stores 2 into s1+0x20 at 0x00302ee0. This is precisely the moby->state selector loaded at 0x00302d6c whose value 2 dispatches into COMMANDO_DIALOGUE_AFTER_REPOSITION. Original decompilation and current C show the same transition. domain_3_value_3 -> COMMANDO_POST_DIALOGUE: Retail 0x00302f40 updates dialogue in state 2; nonzero return loads 3 at 0x00302f4c, stores it into moby selector s1+0x20 at 0x00302f5c and invokes the camera transition at 0x00302f60. The selector loaded at 0x00302d6c dispatches value 3 at 0x00302d9c into the existing COMMANDO_POST_DIALOGUE case. Current SHA-bound C and original Ghidra agree, proving the existing state member applies to this assignment. domain_5_value_2 -> COMMANDO_DIALOGUE_AFTER_REPOSITION: In COMMANDO_POST_DIALOGUE, retail 0x00302f78-0x00302f80 tests dialogue storage +0x24 and branches to 0x00302fc8 when completion actions are not selected. There sb v1,0x20(s1) writes 2 retained from the selector dispatch at 0x00302d80/0x00302d94. Original Ghidra and current C explicitly assign moby->state=2 here; the same selector's existing case 2 is COMMANDO_DIALOGUE_AFTER_REPOSITION, so reuse is proven without interpreting level_game_mode. --- src/overlays/l08/mobys/commando.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l08/mobys/commando.c b/src/overlays/l08/mobys/commando.c index 7eacd67cdf..fc071a01f2 100644 --- a/src/overlays/l08/mobys/commando.c +++ b/src/overlays/l08/mobys/commando.c @@ -142,13 +142,13 @@ void commando_update(WM *moby) { commando_vars->f2C = 3.0f; commando_vars->p40 = commando_name_string; if (!D_0013D3B4) { - moby->state = 1; + moby->state = COMMANDO_DIALOGUE_BEFORE_REPOSITION; } else { char *b = D_L08_001600EC; int j = commando_vars->joint; qcopy(moby->position, b + j * 0x80 + 0x30); qcopy((char *)moby + 0x40, b + j * 0x80 + 0x70); - moby->state = 2; + moby->state = COMMANDO_DIALOGUE_AFTER_REPOSITION; } initialize_npc_dialogue(moby, (char *)commando_vars + 0x20); break; @@ -158,7 +158,7 @@ void commando_update(WM *moby) { int j = commando_vars->joint; qcopy(moby->position, b + j * 0x80 + 0x30); qcopy((char *)moby + 0x40, b + j * 0x80 + 0x70); - moby->state = 2; + moby->state = COMMANDO_DIALOGUE_AFTER_REPOSITION; D_0013D3B4 = 1; } break; @@ -168,7 +168,7 @@ void commando_update(WM *moby) { blend_moby_animation(moby, random_integer_below(2) + 1, 0, scale_game_frames(20)); } if (update_npc_dialogue(moby, (char *)commando_vars + 0x20)) { - moby->state = 3; + moby->state = COMMANDO_POST_DIALOGUE; begin_dialogue_camera_transition(moby, 2.2f); } break; @@ -185,7 +185,7 @@ void commando_update(WM *moby) { mark_moby_for_removal(moby); return; } - moby->state = 2; + moby->state = COMMANDO_DIALOGUE_AFTER_REPOSITION; } break; } From 8d4327a66307d4cd2ec2b7c3de1b6d193c6a0ab8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:34:19 +0000 Subject: [PATCH 0970/1502] decomp: clarify names in integrate_hero_motion domain_0_value_34 -> HERO_STATE_RISE_THEN_FALL_WITH_AIRBORNE_HIT_QUERY: The authoritative C derives L16MovementPlayer *player from &hero.motion.pos minus 0x80, i.e. the hero base, and declares its state selector at offset 0x2084 separately from mode at 0x208c. Retail 0x002110d8 forms that hero base; 0x002110f0 loads its state at +0x2084 and 0x002110f4-0x002110f8 compares it with 0x22. The Ghidra decompilation confirms iRam001413d4 == 0x22. This is the hero current-state selector, so reuse the supplied shared HeroStateId canonical member for 34. The branch limits horizontal velocity and clamps gravity-relative vertical velocity at 0x00211118-0x002111a0; its partial movement behavior does not rename the shared state. domain_1_value_20 -> HERO_STATE_WRENCH_SLAM: The same hero-base state load at retail 0x002110f0 (+0x2084, C player->state) is compared against 0x14 at 0x002110fc-0x00211100, sharing the velocity-limiting branch with state 34. The separate +0x208c mode load occurs at 0x00211104 and drives the later control-mode tests, so this comparison belongs to the hero current-state domain rather than that mode domain. Reuse the supplied HeroStateId canonical HERO_STATE_WRENCH_SLAM = 20; the exact C and Ghidra both show this state branch applying the gravity-relative velocity clamp. --- src/overlays/l16/hero/apply_hero_ground_material_effects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l16/hero/apply_hero_ground_material_effects.c b/src/overlays/l16/hero/apply_hero_ground_material_effects.c index de7330f1aa..2c572aff6a 100644 --- a/src/overlays/l16/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l16/hero/apply_hero_ground_material_effects.c @@ -577,7 +577,7 @@ void integrate_hero_motion(void) { player = (L16MovementPlayer *)((char *)position - 0x80); update_hero_attachment(player->physics_mode, (char *)position + 0x70, (char *)position + 0x10); /* Limit the velocity by state and mode. Inside an arm `position` moves on to the velocity; it is formed again below. */ - if (player->state == 34 || player->state == 20) { + if (player->state == HERO_STATE_RISE_THEN_FALL_WITH_AIRBORNE_HIT_QUERY || player->state == HERO_STATE_WRENCH_SLAM) { float limit; float *limited_velocity; From a971a7541e9f8b60688283f554007813d74e6737 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:34:19 +0000 Subject: [PATCH 0971/1502] decomp: clarify names in bolt_thief_update domain_0_value_6 -> BOLT_THIEF_KNOCKBACK: Retail 0x002e3890-0x002e3898 loads moby+0x20 and compares against 6 to suppress repeated knockback initialization. This is the same byte loaded at 0x002e3948 for the switch whose existing local member BOLT_THIEF_KNOCKBACK=6 updates knock physics at 0x002e3d84. domain_12_value_1 -> BOLT_THIEF_FACE_HERO: Retail 0x002e3c7c-0x002e3c9c stores the mode-tested value 1 to moby+0x20 and resets turn after settling. The destination is the switch state byte, not the mode field; its existing member BOLT_THIEF_FACE_HERO computes hero-relative heading at 0x002e3aac-0x002e3af4. domain_13_value_5 -> BOLT_THIEF_FOLLOW_OTHER_PATH: Retail 0x002e3cc0-0x002e3ce4 stores 5 to moby+0x20 and resets path progress after settling. Existing BOLT_THIEF_FOLLOW_OTHER_PATH handles this state at 0x002e3ce8, calling advance_bolt_thief_path; supplied helper source selects other_path specifically for state 5. domain_14_value_2 -> BOLT_THIEF_WAIT_FOR_HERO_TRIGGER: Retail 0x002e3ce8-0x002e3cfc stores 2 to moby+0x20 when the other path completes, then disables bounds and resets the primary-path pose. This returns to the existing BOLT_THIEF_WAIT_FOR_HERO_TRIGGER state which polls hero position and data->trigger at 0x002e3b00-0x002e3b10. domain_1_value_6 -> BOLT_THIEF_KNOCKBACK: Retail 0x002e38b8-0x002e3928 initializes the data+0x70 knockback record; 0x002e3944 stores 6 to moby+0x20. The switch consumes that exact state byte at 0x002e3948, and existing BOLT_THIEF_KNOCKBACK steps the same record at 0x002e3d84-0x002e3d90. domain_3_value_1 -> BOLT_THIEF_FACE_HERO: Retail 0x002e3988-0x002e3998 stores 1 to moby+0x20 and clears turn at data+0xF0. That exact byte selects existing BOLT_THIEF_FACE_HERO, whose 0x002e3aac-0x002e3af4 computes hero-relative XY heading and updates data+0xF0. domain_5_value_2 -> BOLT_THIEF_WAIT_FOR_HERO_TRIGGER: Retail 0x002e3a7c-0x002e3aa0 initializes path state, stores 2 to moby+0x20, disables bounds and sets collision flags. The same state byte selects existing BOLT_THIEF_WAIT_FOR_HERO_TRIGGER; 0x002e3b00-0x002e3b10 tests hero position against data+0xE0 before advancing. domain_7_value_4 -> BOLT_THIEF_FOLLOW_PRIMARY_PATH: Retail 0x002e3b00-0x002e3b78 responds to the hero-volume trigger, restores bounds, and stores 4 to moby+0x20. The same state switch's existing BOLT_THIEF_FOLLOW_PRIMARY_PATH calls advance_bolt_thief_path at 0x002e3b98; supplied helper source selects data->path unless state is FOLLOW_OTHER_PATH. domain_9_value_3 -> BOLT_THIEF_SETTLE_AT_PATH_END: Retail 0x002e3b98-0x002e3bac stores 3 to moby+0x20 when path advancement completes. Existing BOLT_THIEF_SETTLE_AT_PATH_END handles that same state byte at 0x002e3bc8-0x002e3c5c by loading the final primary-path vector and springing each position component toward it. --- src/overlays/l16/mobys/bolt_thief.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/l16/mobys/bolt_thief.c b/src/overlays/l16/mobys/bolt_thief.c index 347e1f4443..f80b84a27a 100644 --- a/src/overlays/l16/mobys/bolt_thief.c +++ b/src/overlays/l16/mobys/bolt_thief.c @@ -156,7 +156,7 @@ void bolt_thief_update(L16CrateMoby *moby) { hit = find_moby_hit(moby, 0x210000, 0); if (!hit && bolt_thief_data->child) hit = find_moby_hit(bolt_thief_data->child, 0x210000, 0); - if (hit && moby->state != 6) { + if (hit && moby->state != BOLT_THIEF_KNOCKBACK) { struct Hero *player = &hero; bolt_thief_data->knock_drag = 0.008f; @@ -174,13 +174,13 @@ void bolt_thief_update(L16CrateMoby *moby) { moby->position[1] - player->motion.pos.f[1])); bolt_thief_data->ticks = 0x78; FUN_L00_00257470(moby, 0, -1); - moby->state = 6; + moby->state = BOLT_THIEF_KNOCKBACK; } moby->opacity = 0xFF; switch (moby->state) { case BOLT_THIEF_INITIALIZE: if (bolt_thief_data->mode == 2) { - moby->state = 1; + moby->state = BOLT_THIEF_FACE_HERO; bolt_thief_data->turn = 0.0f; set_moby_animation(moby, 4, 0); } else { @@ -212,7 +212,7 @@ void bolt_thief_update(L16CrateMoby *moby) { return; } initialize_moby_path_state(moby); - moby->state = 2; + moby->state = BOLT_THIEF_WAIT_FOR_HERO_TRIGGER; moby->collision = 0x80; moby->flags |= 0x41; moby->bounds = 0; @@ -243,14 +243,14 @@ void bolt_thief_update(L16CrateMoby *moby) { } moby->flags &= 0xFFBE; moby->bounds = moby->model->bounds; - moby->state = 4; + moby->state = BOLT_THIEF_FOLLOW_PRIMARY_PATH; } break; case BOLT_THIEF_FOLLOW_PRIMARY_PATH: if (bolt_thief_data->mode == 0) update_linked_moby_position(moby); if (advance_bolt_thief_path((char *)moby)) { - moby->state = 3; + moby->state = BOLT_THIEF_SETTLE_AT_PATH_END; blend_moby_animation(moby, 3, 0, 5); } emit_moby_offset_particles(moby); @@ -285,7 +285,7 @@ void bolt_thief_update(L16CrateMoby *moby) { zero); if ((moby->status & 2) && moby->frame == moby->animation) { if (settle_data->mode == 1) { - moby->state = 1; + moby->state = BOLT_THIEF_FACE_HERO; settle_data->turn = zero; set_moby_animation(moby, 4, 0); } else { @@ -293,7 +293,7 @@ void bolt_thief_update(L16CrateMoby *moby) { set_moby_state_14(settle_data->child); settle_data->child = 0; } - moby->state = 5; + moby->state = BOLT_THIEF_FOLLOW_OTHER_PATH; blend_moby_animation(moby, 0, 0, 20); settle_data->timer = zero; settle_data->counter = 0; @@ -306,7 +306,7 @@ void bolt_thief_update(L16CrateMoby *moby) { if (advance_bolt_thief_path((char *)moby)) { char *path; - moby->state = 2; + moby->state = BOLT_THIEF_WAIT_FOR_HERO_TRIGGER; moby->bounds = 0; moby->flags |= 0x41; bolt_thief_data->timer = 0.0f; From 039560f6f8a84ba78e0d441168cc2350a9365096 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:34:20 +0000 Subject: [PATCH 0972/1502] decomp: clarify names in update_homing_mine domain_0_value_1 -> HOMING_MINE_STATE_HOMING: Retail 00304f48 loads a2=1 and 00304fa0 stores a2 to moby+0x20 during initialization after saving the start position. The same byte is loaded at 00304f44 and compared against 1 at 00304f4c to enter 00304fd0, which advances timer, motion and steering. This is the exact moby->state domain already named HOMING_MINE_STATE_HOMING=1 by the authoritative function-local enum. domain_1_value_2 -> HOMING_MINE_STATE_DETONATE: The authoritative source's coll_sphere-success assignment writes moby->state=2. Retail 003053ec calls the sphere collision helper; 003053f4 skips the store on zero, while 003053f8 loads v0=2 and 00305400 stores it to moby+0x20. Dispatch 00304f6c compares this same state byte with 2 and enters 00305404-0030546c, spawning an explosion and removing the mine. Reuse existing local HOMING_MINE_STATE_DETONATE=2. domain_2_value_2 -> HOMING_MINE_STATE_DETONATE: The source's qualifying collect_mobies_in_sphere-hit else branch writes moby->state=2. Retail 00305398-003053c0 rejects absent, same-class and parent hits; 003053c4 loads v0=2 and the qualifying branch reaches shared store 00305400 to moby+0x20. That exact byte selects the explosion/removal branch at 00304f6c and 00305404-0030546c, already named HOMING_MINE_STATE_DETONATE=2 in this function's enum. --- src/overlays/l12/mobys/homing_mine.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l12/mobys/homing_mine.c b/src/overlays/l12/mobys/homing_mine.c index 3a4185b0b2..b902c769fe 100644 --- a/src/overlays/l12/mobys/homing_mine.c +++ b/src/overlays/l12/mobys/homing_mine.c @@ -116,7 +116,7 @@ void homing_mine_update(struct Moby *moby) { case HOMING_MINE_STATE_INITIALIZE: moby->flags |= 0x1000; qcopy(&homing_mine_state->start, &moby->pos); - moby->state = 1; + moby->state = HOMING_MINE_STATE_HOMING; homing_mine_state->turn = 0.6981317f; if (moby->parent != NULL && ((struct Moby *)moby->parent)->command != 0) homing_mine_state->turn = -homing_mine_state->turn; @@ -179,9 +179,9 @@ void homing_mine_update(struct Moby *moby) { qcopy(&probe, &moby->pos); probe.f[2] += 0.35f; if (coll_sphere(&probe, 0, moby, 0.35f)) - moby->state = 2; + moby->state = HOMING_MINE_STATE_DETONATE; } else { - moby->state = 2; + moby->state = HOMING_MINE_STATE_DETONATE; } } break; From 53a063615641879170b31de5a73f63e47e791848 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:34:20 +0000 Subject: [PATCH 0973/1502] decomp: clarify names in construction_arm_update domain_0_value_6 -> CONSTRUCTION_ARM_DESTROY: At 0x002c296c-0x002c2970 the moby's +0x20 state is compared with 6, the same byte selected by the switch at 0x002c29f8. Case 6 at 0x002c2ec8-0x002c2f9c emits destruction effects and marks this moby for removal, proving reuse of the existing local DESTROY member. domain_10_value_1 -> CONSTRUCTION_ARM_WAIT_TO_TURN: At 0x002c2e40-0x002c2ec4 exit-animation completion resets the randomized wait timer, blends animation 0 and stores 1 to current moby state +0x20. This byte drives the existing WAIT_TO_TURN branch at 0x002c2a7c, which waits on that timer before choosing target yaw. domain_1_value_6 -> CONSTRUCTION_ARM_DESTROY: At 0x002c298c-0x002c29b0 a positive hit-record float at +0x2c causes 6 to be stored to this moby's +0x20 state. The same byte drives the seven-state switch; its existing DESTROY case at 0x002c2ec8-0x002c2f9c emits effects and removes the moby. domain_2_value_0 -> CONSTRUCTION_ARM_INITIALIZE: At 0x002c29b8 the current moby state byte is tested against zero before copying yaw to facing and updating joint animation. This is the same +0x20 byte switched at 0x002c29f8; its existing INITIALIZE case at 0x002c2a20-0x002c2a78 initializes timer, yaw, velocity and side. domain_3_value_1 -> CONSTRUCTION_ARM_WAIT_TO_TURN: The INITIALIZE branch stores 1 into moby state +0x20 at 0x002c2a64-0x002c2a70 after initializing the wait timer. That exact state dispatches to 0x002c2a7c-0x002c2b84, which waits for timer, proximity and group peers before selecting target yaw and entering state 2; reuse existing WAIT_TO_TURN. domain_5_value_1 -> CONSTRUCTION_ARM_WAIT_TO_TURN: At 0x002c2af0-0x002c2b28 group-list indices resolve to moby instances; only nonnegative-state peers whose +0xa6 oclass matches this construction arm reach the comparison with 1 (xori at 0x002c2b20). Peers outside state 1 delay turning. Same-class state 1 is the existing WAIT_TO_TURN branch of this class, not a generic cross-class state. domain_6_value_2 -> CONSTRUCTION_ARM_TURN_TO_TARGET_YAW: At 0x002c2b78-0x002c2b84 target yaw is stored at pvars+0x8c and 2 is stored to current moby state +0x20. The same state dispatches to the existing TURN_TO_TARGET_YAW branch 0x002c2b88-0x002c2c38, comparing yaw with target and applying spring_turn. domain_7_value_3 -> CONSTRUCTION_ARM_WAIT_FOR_ENTRY_ANIMATION: At 0x002c2bc4-0x002c2bec yaw alignment starts side*2+1 animation and stores 3 in current moby state +0x20. Existing state 3 at 0x002c2c3c-0x002c2c5c waits for that sequence and animation flag bit 2, proving WAIT_FOR_ENTRY_ANIMATION in this same switch domain. domain_8_value_4 -> CONSTRUCTION_ARM_WAIT_TO_START_EXIT_ANIMATION: At 0x002c2c64-0x002c2cb4 entry-animation completion sets the timer, starts side*2+2, sets direction and stores state 4 to +0x20. Existing state 4 decrements that timer at 0x002c2dfc and, on expiry, starts side*2+3 then enters state 5; reuse WAIT_TO_START_EXIT_ANIMATION. domain_9_value_5 -> CONSTRUCTION_ARM_WAIT_FOR_EXIT_ANIMATION: At 0x002c2dfc-0x002c2e3c timer expiry blends animation side*2+3 and stores 5 to current moby state +0x20. The existing state-5 branch at 0x002c2e40-0x002c2e60 waits for this same sequence and completion flag before resetting the wait cycle, proving WAIT_FOR_EXIT_ANIMATION. --- src/overlays/l15/mobys/construction_arm.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l15/mobys/construction_arm.c b/src/overlays/l15/mobys/construction_arm.c index ec3813a9e2..4423ef8556 100644 --- a/src/overlays/l15/mobys/construction_arm.c +++ b/src/overlays/l15/mobys/construction_arm.c @@ -85,14 +85,14 @@ void construction_arm_update(struct Moby *moby) { int animation, duration, minimum_effect_duration_frames; Vec4 origin, velocity, offset, sum; - if (moby->state != 6) { + if (moby->state != CONSTRUCTION_ARM_DESTROY) { slot = find_moby_hit(moby, 0x10000, 0); if (slot != 0 && *(float *)(slot + 0x2c) > 0.0f) hit = 1; if (hit) - moby->state = 6; + moby->state = CONSTRUCTION_ARM_DESTROY; } - if (moby->state != 0) { + if (moby->state != CONSTRUCTION_ARM_INITIALIZE) { arm_vars->facing = arm_vars->yaw; update_joint_animation(frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, moby, arm_vars, 0); } @@ -103,7 +103,7 @@ void construction_arm_update(struct Moby *moby) { FUN_L15_001f8648(construction_arm_wait_time_max_gp * 60.0f))); *(int *)&arm_vars->yaw_velocity = arm_vars->side = *(int *)&arm_vars->yaw = 0; moby->update_dist = 0xff; - moby->state = 1; + moby->state = CONSTRUCTION_ARM_WAIT_TO_TURN; break; case CONSTRUCTION_ARM_WAIT_TO_TURN: if (fast_dec_timer_s16(&arm_vars->timer) && @@ -119,7 +119,7 @@ void construction_arm_update(struct Moby *moby) { group_member_moby = (struct Moby *)((*list & 0x7fff) * 0x100 + (int)l15_moby_array); if ((signed char)group_member_moby->state >= 0 && - group_member_moby->oclass == moby->oclass && group_member_moby->state != 1) + group_member_moby->oclass == moby->oclass && group_member_moby->state != CONSTRUCTION_ARM_WAIT_TO_TURN) count++; } while ((short)*list++ >= 0); if (count != 0) { @@ -129,7 +129,7 @@ void construction_arm_update(struct Moby *moby) { } if (ready) { arm_vars->target_yaw = random_float_between(-0.20943952f, 0.20943952f); - moby->state = 2; + moby->state = CONSTRUCTION_ARM_TURN_TO_TARGET_YAW; } } break; @@ -139,7 +139,7 @@ void construction_arm_update(struct Moby *moby) { animation = arm_vars->side; animation *= 2; blend_moby_animation(moby, animation + 1, 0, scale_game_frames(6)); - moby->state = 3; + moby->state = CONSTRUCTION_ARM_WAIT_FOR_ENTRY_ANIMATION; } arm_vars->yaw = spring_turn(&arm_vars->yaw_velocity, arm_vars->yaw, @@ -155,7 +155,7 @@ void construction_arm_update(struct Moby *moby) { animation *= 2; blend_moby_animation(moby, animation + 2, 0, scale_game_frames(3)); arm_vars->direction = random_angle_radians(); - moby->state = 4; + moby->state = CONSTRUCTION_ARM_WAIT_TO_START_EXIT_ANIMATION; } break; case CONSTRUCTION_ARM_WAIT_TO_START_EXIT_ANIMATION: @@ -186,7 +186,7 @@ void construction_arm_update(struct Moby *moby) { animation = arm_vars->side; animation *= 2; blend_moby_animation(moby, animation + 3, 0, scale_game_frames(6)); - moby->state = 5; + moby->state = CONSTRUCTION_ARM_WAIT_FOR_EXIT_ANIMATION; } break; case CONSTRUCTION_ARM_WAIT_FOR_EXIT_ANIMATION: @@ -196,7 +196,7 @@ void construction_arm_update(struct Moby *moby) { arm_vars->timer = truncate_float_to_s32(random_float_between(minimum, maximum)); duration = scale_game_frames(6); blend_moby_animation(moby, 0, 0, duration); - moby->state = 1; + moby->state = CONSTRUCTION_ARM_WAIT_TO_TURN; } break; case CONSTRUCTION_ARM_DESTROY: From 2202107328c123dee146f313147878978a104b48 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:34:20 +0000 Subject: [PATCH 0974/1502] decomp: clarify names in follow_camera_apply_overrides domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x002e60b4 establishes s0 = 0x0013f350 (hero); 0x002e6108 loads unsigned byte +0x20a4 and 0x002e610c compares it with s1=1. Authoritative C identifies this exact selector as hero.vehicle_mode within control_mode==5, selecting height 1.5 versus 2.5. It therefore belongs to supplied HeroVehicleMode, whose canonical value 1 is HERO_VEHICLE_MODE_CLANK, not HeroStateId or HeroGravityMode. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x002e6164 establishes a0=hero; 0x002e6174/0x002e618c loads byte +0x20a4 and 0x002e6190-0x002e6194 compares it with 1. This is the same hero.vehicle_mode field in authoritative C, gating distance 3.0, conditional height 1.0 and camera +0x20c=0.6. The proven shared HeroVehicleMode domain supplies canonical HERO_VEHICLE_MODE_CLANK=1; this is separate from the +0x208c control-mode selector. domain_2_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x002e6200 forms hero base 0x0013f350; 0x002e6204-0x002e620c loads byte +0x20a4 and compares it with 2. Authoritative C identifies this as hero.vehicle_mode, gating vehicle offset-scale/distance/height setters and collision-probe overrides at 0x002e623c-0x002e627c. This exact field uses supplied HeroVehicleMode; canonical HERO_VEHICLE_MODE_GIANT_CLANK=2 is also already used for hero.vehicle_mode in the supplied camera collision consumers. --- src/overlays/shared/camera/follow_camera_setup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/camera/follow_camera_setup.c b/src/overlays/shared/camera/follow_camera_setup.c index 52f3d5c451..a42ddd8dbe 100644 --- a/src/overlays/shared/camera/follow_camera_setup.c +++ b/src/overlays/shared/camera/follow_camera_setup.c @@ -284,7 +284,7 @@ void follow_camera_apply_overrides(O_2e6000 *camera_moby) { flag = 1; { S40 *camera_target = (S40 *)((u8 *)camera_moby->m + 0x40); - if (hero.vehicle_mode == 1) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { camera_target->fB0 = 0.25f; follow_camera_set_height(1.5f, 0.003f); } else { @@ -295,7 +295,7 @@ void follow_camera_apply_overrides(O_2e6000 *camera_moby) { } if (hero.state.control_mode == 0x10) camera_moby->m->fF0 = 0.25f; - if (hero.vehicle_mode == 1) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { if (camera_override_state->i0 == 0) { q = (S40 *)((u8 *)camera_moby->m + 0x40); follow_camera_set_distance(1, 3.0f, 0.003f); @@ -306,7 +306,7 @@ void follow_camera_apply_overrides(O_2e6000 *camera_moby) { } *(f32 *)((u8 *)camera_moby->m + 0x20C) = 0.6f; } - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { if (camera_override_state->i10 < 2) { follow_camera_set_offset_scale(0, follow_camera_vehicle_offset_scale_gp, 0.005f); follow_camera_set_distance(1, follow_camera_vehicle_orbit_distance_gp, 0.003f); From b91312f74bbbcdf999c59a2e551f2afbf53ff778 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:34:20 +0000 Subject: [PATCH 0975/1502] decomp: clarify names in assign_gadgebot_attack_targets domain_0_value_0 -> GADGEBOT_TARGET_KIND_UNAVAILABLE: In the authoritative source kind is initialized to 0 and overwritten only when candidate+0x24 is nonnull. Retail 0x002f2374 loads that class pointer, 0x002f2378 branches on null with move v1,zero at 0x002f237c, and 0x002f2380 otherwise loads signed halfword class+0x46. Original Ghidra sVar5 follows this same zero/default flow. Thus zero is the unavailable-class-kind fallback used by this filter, not a state ID. domain_1_value_5 -> GADGEBOT_TARGET_KIND_ATTACKABLE: Retail 0x002f2374-0x002f2388 obtains kind from candidate's class pointer +0x46 and rejects every kind except 5. The accepted branch checks range, height and line of sight at 0x002f2390-0x002f243c, then calls score_gadgebot_target_candidate at 0x002f2450 and stores ranked candidate pointers at 0x002f2510. Assignment at 0x002f27d4 is committed as target at 0x002f28b0. Supplied gadgebot_update consumes this target in attack approach and record_moby_hit strike behavior. This proves kind 5 is attackable for the gadgebot target filter, independently of moby state numbers. --- src/overlays/shared/enemies/gadgebot.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/gadgebot.c b/src/overlays/shared/enemies/gadgebot.c index bc2540688f..c9c1ab10c6 100644 --- a/src/overlays/shared/enemies/gadgebot.c +++ b/src/overlays/shared/enemies/gadgebot.c @@ -1178,6 +1178,10 @@ float score_gadgebot_target_candidate(char *moby, char *candidate_moby, int targ by score, each target goes to its best-scoring mobys, and their approach angles are spread apart. */ void assign_gadgebot_attack_targets(void) { + enum { + GADGEBOT_TARGET_KIND_UNAVAILABLE = 0, + GADGEBOT_TARGET_KIND_ATTACKABLE = 5 + }; char *mobys[50]; char end[16]; char start[16]; @@ -1219,10 +1223,10 @@ void assign_gadgebot_attack_targets(void) { float range; float score; int kind; - kind = 0; + kind = GADGEBOT_TARGET_KIND_UNAVAILABLE; if (*(char **)(candidate + 0x24) != 0) kind = *(short *)(*(char **)(candidate + 0x24) + 0x46); - if (kind != 5) + if (kind != GADGEBOT_TARGET_KIND_ATTACKABLE) continue; range = 12.0f; if (S16(vars, 0x198) != 0) From 27434027dc47fd832504f20467f9dde85098535b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:36:12 +0000 Subject: [PATCH 0976/1502] decomp: clarify names in update_exploding_prop domain_0_value_1 -> EXPLODING_PROP_STATE_INITIALIZED: Retail 0x002aa2e0 loads the state byte at moby+0x20 and 0x002aa2e4-0x002aa2e8 compares it with 1. This is the same state byte written to 1 at 0x002aa8a8 after initial draw/update distance setup. The authoritative C and original Ghidra agree: this early guard tests the initialized state. domain_1_value_0 -> EXPLODING_PROP_STATE_UNINITIALIZED: On the no-hit path retail 0x002aa888 loads moby+0x20 and 0x002aa88c returns when nonzero. Only zero falls through to set draw_dist=0x80 at 0x002aa89c, update_dist=0xff at 0x002aa8a4, then state=1 at 0x002aa8a8 and check the saved removal bit. Source and Ghidra therefore establish zero as the pre-initialization state. domain_2_value_1 -> EXPLODING_PROP_STATE_INITIALIZED: Retail 0x002aa898 loads 1 into a0 and 0x002aa8a8 stores it to moby+0x20 after draw_dist/update_dist initialization at 0x002aa89c and 0x002aa8a4. On subsequent no-hit calls the nonzero check at 0x002aa88c skips this initialization. This assignment and the entry comparison use the identical moby-state domain. --- src/overlays/l15/mobys/exploding_prop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l15/mobys/exploding_prop.c b/src/overlays/l15/mobys/exploding_prop.c index 0cc5178db8..0907da5beb 100644 --- a/src/overlays/l15/mobys/exploding_prop.c +++ b/src/overlays/l15/mobys/exploding_prop.c @@ -68,7 +68,7 @@ void exploding_prop_update(struct Moby *moby) __asm__("FUN_L15_002aa280"); /* Moby class 154 */ void exploding_prop_update(struct Moby *moby) { - char *hit = 0; + enum { EXPLODING_PROP_STATE_UNINITIALIZED = 0 , EXPLODING_PROP_STATE_INITIALIZED = 1 } ;char *hit = 0; Vec4 velocity, hit_direction, push, offset, center; u32 palette[4]; u32 colors[4]; @@ -78,7 +78,7 @@ void exploding_prop_update(struct Moby *moby) { float size; void *debris; - if (D_001413F4[0] != 2 && moby->state == 1) + if (D_001413F4[0] != 2 && moby->state == EXPLODING_PROP_STATE_INITIALIZED) return; for (hit_record_index = 0; hit_record_index < 64; hit_record_index++) { @@ -186,11 +186,11 @@ void exploding_prop_update(struct Moby *moby) { mark_moby_for_removal(moby); } else { moby->hit_slot = 0xff; - if (moby->state != 0) + if (moby->state != EXPLODING_PROP_STATE_UNINITIALIZED) return; moby->draw_dist = 0x80; moby->update_dist = 0xff; - moby->state = 1; + moby->state = EXPLODING_PROP_STATE_INITIALIZED; if (D_0013DD50 != 0) { u16 save_id = moby->save_id; if ((*(s32 *)(D_0014C190 + (((s16)save_id >> 5) * 4) + current_level_index * 0x100) >> From f55d4779b450d083701f85e289879fa5af49419c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:36:13 +0000 Subject: [PATCH 0977/1502] decomp: clarify names in update_hero_airborne_planar_motion domain_0_value_10 -> HERO_STATE_PACK_JUMP: The bound source assigns state = hero.state.current; retail 0x00234b58/0x00234b6c loads hero+0x2084 (0x001413d4), the same current-state selector used in the supplied caller's HeroStateId dispatch. include/rnc/hero/hero_state.h supplies the canonical HeroStateId member. Retail 0x00234b4c/0x00234b70 compares that load with 10. Its branch builds the scaled move impulse, copies it to momentum and retains flat speed (0x00234b90-0x00234bb0); the caller also dispatches HERO_STATE_PACK_JUMP into this airborne helper. domain_1_value_16 -> HERO_STATE_PACK_LONG_JUMP: The bound source assigns state = hero.state.current; retail 0x00234b58/0x00234b6c loads hero+0x2084 (0x001413d4), the same current-state selector used in the supplied caller's HeroStateId dispatch. include/rnc/hero/hero_state.h supplies the canonical HeroStateId member. Retail 0x00234bb4-0x00234bb8 compares the current state with 0x10. The branch uses long_jump_speed, later reduces target speed and adjusts jump_gravity (0x00234bc0-0x00234c74), consistent with the caller's HERO_STATE_PACK_LONG_JUMP dispatch and canonical member 16. domain_2_value_28 -> HERO_STATE_LEDGE_JUMP: The bound source assigns state = hero.state.current; retail 0x00234b58/0x00234b6c loads hero+0x2084 (0x001413d4), the same current-state selector used in the supplied caller's HeroStateId dispatch. include/rnc/hero/hero_state.h supplies the canonical HeroStateId member. Retail 0x00234bbc/0x00234c80 tests that same current-state load against 0x1c. The branch approaches ledge_jump_speed during animation frames 13-30 and projects it along hero yaw into XY velocity (0x00234cf8-0x00234dbc). The caller's shared jump dispatch includes HERO_STATE_LEDGE_JUMP. domain_3_value_11 -> HERO_STATE_HIGH_JUMP: The bound source assigns state = hero.state.current; retail 0x00234b58/0x00234b6c loads hero+0x2084 (0x001413d4), the same current-state selector used in the supplied caller's HeroStateId dispatch. include/rnc/hero/hero_state.h supplies the canonical HeroStateId member. Retail 0x00234c84/0x00234dc0 groups current states 11 and 12 by unsigned (state-11)<2. Retail 0x00234e30-0x00234e38 then reloads hero+0x2084 and tests 11 for the high_jump_drift_speed adjustment; the corresponding bound C already names that inner comparison HERO_STATE_HIGH_JUMP. domain_4_value_12 -> HERO_STATE_STORED_HEADING_JUMP: The bound source assigns state = hero.state.current; retail 0x00234b58/0x00234b6c loads hero+0x2084 (0x001413d4), the same current-state selector used in the supplied caller's HeroStateId dispatch. include/rnc/hero/hero_state.h supplies the canonical HeroStateId member. Retail 0x00234c84/0x00234dc0 groups current states 11 and 12 by unsigned (state-11)<2. This branch copies takeoff_yaw into move_yaw and constructs XY velocity from stored drift and takeoff headings (0x00234e00-0x00234f50). Canonical HeroStateId member 12 is HERO_STATE_STORED_HEADING_JUMP, also included in the caller's jump dispatch. domain_5_value_17 -> HERO_STATE_REPEATABLE_JUMP: The bound source assigns state = hero.state.current; retail 0x00234b58/0x00234b6c loads hero+0x2084 (0x001413d4), the same current-state selector used in the supplied caller's HeroStateId dispatch. include/rnc/hero/hero_state.h supplies the canonical HeroStateId member. Retail 0x00234f6c-0x00234f70 compares the current-state load with 0x11. Its branch restores the saved move direction/yaw and after nine scaled frames builds frame_time*4.9 directional velocity (0x00234f78-0x002350a4). The same domain's canonical member 17 is HERO_STATE_REPEATABLE_JUMP, present in the caller's jump dispatch. --- .../l01/hero/update_hero_motion_for_current_state.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l01/hero/update_hero_motion_for_current_state.c b/src/overlays/l01/hero/update_hero_motion_for_current_state.c index ab149dd91a..bf7fc21e56 100644 --- a/src/overlays/l01/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l01/hero/update_hero_motion_for_current_state.c @@ -217,11 +217,11 @@ void update_hero_airborne_planar_motion(void) { s32 state; state = hero.state.current; - if (state == 10) { + if (state == HERO_STATE_PACK_JUMP) { build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); qcopy(&hero.motion.momentum, &hero.move_impulse); hero.ground_speed = hero.motion.flat_speed; - } else if (state == 16) { + } else if (state == HERO_STATE_PACK_LONG_JUMP) { if (scale_game_frames(0x36) < hero.state_timer) { approach_value(frame_time_sq * 25.0f, frame_time_sq * 7.0f, &hero.jump_gravity); } @@ -233,7 +233,7 @@ void update_hero_airborne_planar_motion(void) { speed_step(frame_time_sq * 44.0f, frame_time_sq * 45.0f); set_gravity_relative_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, 0.0f); add_hero_forward_offset(&hero.motion.velocity, &hero.motion.velocity, hero.ground_speed); - } else if (state == 0x1C) { + } else if (state == HERO_STATE_LEDGE_JUMP) { if (scale_game_frames(0x28) < hero.state_timer) { turn_to(0, frame_scale_sq * 0.04f, frame_scale_sq * 0.2f, frame_time * 15.009831f); air_accel(frame_time_sq * 20.0f); @@ -247,7 +247,7 @@ void update_hero_airborne_planar_motion(void) { } hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * hero.ledge_jump_speed; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * hero.ledge_jump_speed; - } else if (state == 11 || state == 12) { + } else if (state == HERO_STATE_HIGH_JUMP || state == HERO_STATE_STORED_HEADING_JUMP) { hero.motion.move_yaw = hero.takeoff_yaw; turn_to(0, frame_scale_sq * 0.04f, frame_scale_sq * 0.2f, frame_time * 6.981317f); if (hero.unk450 != 3) { @@ -272,7 +272,7 @@ void update_hero_airborne_planar_motion(void) { hero.motion.velocity.f[1] += fast_sin(hero.takeoff_yaw) * additional_planar_speed; build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); qcopy(&hero.motion.momentum, &hero.move_impulse); - } else if (state == 0x11) { + } else if (state == HERO_STATE_REPEATABLE_JUMP) { hero.motion.move_yaw = hero.unk470.f[3]; qcopy(&hero.motion.move_dir, &hero.unk470); if (scale_game_frames(9) < hero.state_timer) { From c1dda7c72c3be5b21888c9ca50145846539d24cb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:36:13 +0000 Subject: [PATCH 0978/1502] decomp: clarify names in gold_bolt_update domain_0_value_1 -> GOLD_BOLT_WAIT_FOR_PICKUP: Authoritative src/overlays/shared/pickups/gold_bolt.c SHA-256 0d022eec4f2e90d84a5c96d8ac4f1c90094323c31526b924787706ad14c8c7ca already declares GOLD_BOLT_WAIT_FOR_PICKUP=1 for switch(moby->state). Retail 0x00307cb4 keeps the moby in s2; 0x00307ce0 loads its byte state at +0x20 and 0x00307ce4 dispatches value 1 to 0x00307dd4, the spinning/bobbing/proximity pickup branch. Initialization writes the same byte with s6=1 at 0x00307dc8. Thus this assignment enters the existing same-selector WAIT_FOR_PICKUP case. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative C identifies this comparison as hero.vehicle_mode != 0. Retail 0x00307ec0 forms hero.motion.pos=0x0013f3d0 in s7 and 0x00307ee8 derives hero base=0x0013f350 in s4; 0x00307f24 loads the byte at hero+0x20a4, also shown as cRam001413f4 in original Ghidra. After accepting mode 3, 0x00307f30 rejects any nonzero mode, proving the listed zero comparison uses that same vehicle_mode selector. Supplied include/rnc/hero/hero_state.h HeroVehicleMode canonically declares HERO_VEHICLE_MODE_ON_FOOT=0; this is the typed vehicle-mode domain, distinct from HeroStateId and gold bolt moby state. domain_4_value_2 -> GOLD_BOLT_PICKUP_CUTSCENE: Authoritative C already declares GOLD_BOLT_PICKUP_CUTSCENE=2 on switch(moby->state). Retail 0x003081a0 loads 2 and 0x003081b4 stores it to the same moby+0x20 state byte dispatched by 0x00307ce0/0x00307d08 to 0x003081c0. This store follows camera setup, animation 0x82, and cutscene_active=1 at 0x003081a8; the destination branch updates pickup camera, follows hero transform, waits on animation/timer, saves collection and removes the bolt. The assignment therefore reuses the established same-selector PICKUP_CUTSCENE member. --- src/overlays/shared/pickups/gold_bolt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/pickups/gold_bolt.c b/src/overlays/shared/pickups/gold_bolt.c index 32372d2478..736784c4c3 100644 --- a/src/overlays/shared/pickups/gold_bolt.c +++ b/src/overlays/shared/pickups/gold_bolt.c @@ -499,7 +499,7 @@ void gold_bolt_update(struct Moby *moby) { gold_bolt_spin_y_degrees_per_second_gp * 0.017453292f * frame_time_macro; gold_bolt_instance_vars->unk60 = gold_bolt_spin_z_degrees_per_second_gp * 0.017453292f * frame_time_macro; - moby->state = 1; + moby->state = GOLD_BOLT_WAIT_FOR_PICKUP; initialize_gold_bolt_data(moby); return; case GOLD_BOLT_WAIT_FOR_PICKUP: @@ -527,7 +527,7 @@ void gold_bolt_update(struct Moby *moby) { if (hero.health.hp == 0) { return; } - if (hero.vehicle_mode != 3 && hero.vehicle_mode != 0) { + if (hero.vehicle_mode != 3 && hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { return; } if (gold_bolt_instance_vars->unkC != 0) { @@ -574,7 +574,7 @@ void gold_bolt_update(struct Moby *moby) { } hero.unk20AF = 1; cutscene_active = 1; - moby->state = 2; + moby->state = GOLD_BOLT_PICKUP_CUTSCENE; gold_bolt_instance_vars->timer = scale_game_frames(60); return; case GOLD_BOLT_PICKUP_CUTSCENE: From 98736e01cf81fca590f8885f0d8ff8904f1d6180 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:36:13 +0000 Subject: [PATCH 0979/1502] decomp: clarify names in update_alien_queen_hit_response_and_recovery domain_0_value_0 -> ALIEN_QUEEN_STATE_INITIALIZE: Retail 0x002fa9e0-0x002fa9e4 reads queen moby+0x20 and returns on zero. Prepared original Ghidra and authoritative C agree. The supplied alien_queen_update calls this helper on the same moby before switching on that same byte; its established ALIEN_QUEEN_STATE_INITIALIZE=0 branch initializes health, home, path and recovery fields, then advances to state 1. This is the queen state domain, not HeroStateId. domain_1_value_1 -> HIT_STATUS_SKIP_DAMAGE_AND_REACTION: Retail 0x002faa54 passes sp as hit evaluator argument five at 0x002faa60, separate from returned response s0 and damage at sp+4. At 0x002faa6c-0x002faa74 status 1 branches to 0x002facf0, bypassing damage scaling/subtraction and response dispatch while retaining common animation finish. Authoritative hit_status != 1 and original iStack_70 != 1 prove the gate; supplied resolver also writes status 1 for no hit. Name describes gate behavior without claiming all producer causes. domain_2_value_1 -> HIT_RESPONSE_DEATH: Retail evaluator return enters s0 at 0x002faa68 and is dispatched at 0x002fac20-0x002fac3c. Health<=0 comparison 0x002fac00 forces s0=1 at 0x002fac14. Authoritative source and original Ghidra agree that this same kind selector then enters existing HIT_RESPONSE_DEATH=1, setting queen state 14 at 0x002fac70 and selecting animation 10. Reuse the existing member of this exact response domain. domain_3_value_1 -> HIT_RESPONSE_DEATH: Retail 0x002fac18 xori tests the evaluator response s0 against 1 after positive-health branching; 0x002fac1c conditionally replaces it with 5. Source else if(kind == 1) and original lVar9 == 1 refer to the very same response value consumed by switch(kind), whose existing HIT_RESPONSE_DEATH=1 branch sets state 14. This comparison must reuse that response member rather than an equal-valued hero state or helper-internal kind. domain_4_value_5 -> HIT_RESPONSE_NONLETHAL_FALLBACK: Retail 0x002fac0c loads 5, then 0x002fac18-0x002fac1c replaces response 1 with 5 only on positive health. Authoritative source kind=5 and prepared original lVar9=5 feed the same switch as existing HIT_RESPONSE_NONLETHAL_FALLBACK=5. That branch joins 0x002fac44/0x002fac48, writing reaction value 200 to pvars+0x67 rather than entering the death handler at 0x002fac4c. Reuse the established member of the exact hit-response domain. --- src/overlays/l06/mobys/alien_queen.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l06/mobys/alien_queen.c b/src/overlays/l06/mobys/alien_queen.c index e58f8c1ffc..7791076c05 100644 --- a/src/overlays/l06/mobys/alien_queen.c +++ b/src/overlays/l06/mobys/alien_queen.c @@ -776,7 +776,7 @@ void update_alien_queen_hit_response_and_recovery(char *moby) { REDUCED_DAMAGE_SOURCE_CLASS = 0x131, DAMAGE_BOOSTING_SOURCE_CLASS = 0x33B }; - AlienQueenVars *alien_queen_hit_recovery_vars; + enum { ALIEN_QUEEN_STATE_INITIALIZE = 0 , HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1 } ;AlienQueenVars *alien_queen_hit_recovery_vars; char *hit; int hit_status; float dmg; @@ -786,7 +786,7 @@ void update_alien_queen_hit_response_and_recovery(char *moby) { float recovery_hp; int *path; alien_queen_hit_recovery_vars = ((char *)MOBY(moby)->pvars); - if (MOBY(moby)->state == 0) + if (MOBY(moby)->state == ALIEN_QUEEN_STATE_INITIALIZE) return; if ((unsigned int)(MOBY(moby)->state - 4) < 10 && alien_queen_hit_recovery_vars->unk108 != -1) D_L06_0014162A = *(short *)&alien_queen_hit_recovery_vars->unk108; @@ -796,7 +796,7 @@ void update_alien_queen_hit_response_and_recovery(char *moby) { hit = FUN_L00_0025a420(moby, 0x330000, 0); kind = resolve_moby_hit_response( moby, hit, &alien_queen_hit_recovery_vars->health, 0, &hit_status, &dmg, 0, 4); - if (hit_status != 1 && (unsigned char)moby[0x20] != 14 && (unsigned char)moby[0x20] != 3 && + if (hit_status != HIT_STATUS_SKIP_DAMAGE_AND_REACTION && (unsigned char)moby[0x20] != 14 && (unsigned char)moby[0x20] != 3 && (unsigned char)moby[0x20] != 5) { if (*(char **)(hit + 0x20) != 0) { int oclass = *(short *)(*(char **)(hit + 0x20) + 0xA6); @@ -835,9 +835,9 @@ void update_alien_queen_hit_response_and_recovery(char *moby) { alien_queen_hit_recovery_vars->health = alien_queen_hit_recovery_vars->recovery_health; } if (alien_queen_hit_recovery_vars->health <= 0.0f) - kind = 1; - else if (kind == 1) - kind = 5; + kind = HIT_RESPONSE_DEATH; + else if (kind == HIT_RESPONSE_DEATH) + kind = HIT_RESPONSE_NONLETHAL_FALLBACK; switch (kind) { case HIT_RESPONSE_SKIP_REACTION: case HIT_RESPONSE_NO_REACTION: From ec6cacc26586da22339bbd08a0c02d13e76d85a0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:36:13 +0000 Subject: [PATCH 0980/1502] decomp: clarify names in update_drone_flight_and_sparks domain_0_value_1 -> DRONE_STATE_SPARKS_UNTIL_REMOVAL: The first source assignment follows collision with a non-source moby and scale_game_frames(0x1E) stored at drone_vars+0x38. Retail Ghidra merges it into LAB_002e9274: 002e9274-002e9288 scales 30 frames, stores the countdown, and writes 1 to 0x20(s1). Dispatch 002e8e3c-002e8e4c reads that identical moby state byte and sends 1 to 002e93ec, whose 002e9444-002e949c code emits spherical spark particles then decrements the timer and removes the moby. This is exactly the existing local enum member DRONE_STATE_SPARKS_UNTIL_REMOVAL, already used for that switch branch. domain_1_value_1 -> DRONE_STATE_SPARKS_UNTIL_REMOVAL: The second source assignment follows a collision without a hit moby, distance from source greater than 10, and copying the collision position. Retail 002e9244-002e9270 performs that distance test and position copy, then falls into 002e9274-002e9288 to store a scaled 30-frame timer and 1 at moby+0x20. Original Ghidra confirms this shared LAB_002e9274 transition. That exact byte is the selector at 002e8e3c-002e8e4c, and value 1 enters the random spherical spark emission and countdown-removal branch 002e93ec-002e949c, already named DRONE_STATE_SPARKS_UNTIL_REMOVAL in this function's local enum. --- src/overlays/l17/mobys/dreks_fleet_turret_shot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l17/mobys/dreks_fleet_turret_shot.c b/src/overlays/l17/mobys/dreks_fleet_turret_shot.c index a001886dee..b91db88e7c 100644 --- a/src/overlays/l17/mobys/dreks_fleet_turret_shot.c +++ b/src/overlays/l17/mobys/dreks_fleet_turret_shot.c @@ -224,14 +224,14 @@ void fleet_turret_shot_update(struct Moby *moby) { } } drone_vars->timer_38 = scale_game_frames(0x1E); - moby->state = 1; + moby->state = DRONE_STATE_SPARKS_UNTIL_REMOVAL; return; } } else if (vector_distance_xy(&moby->pos, *(char **)&drone_vars->unk3C + 0x10) > 10.0f) { qcopy(&moby->pos, r + 0x20); drone_vars->timer_38 = scale_game_frames(0x1E); - moby->state = 1; + moby->state = DRONE_STATE_SPARKS_UNTIL_REMOVAL; return; } } From 800e3774b840a6b8228268e315a3485d4e933348 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:36:13 +0000 Subject: [PATCH 0981/1502] decomp: clarify names in update_bouncing_spark domain_0_value_3 -> SPARK_BURST_AND_REMOVE: At 00300e74-00300e80 a foreign collision owner selects 3 via sb to moby+0x20; the same state byte dispatches at 00300eb0 to the burst/removal branch 00301378-003013e4, matching the existing local enum member. domain_1_value_3 -> SPARK_BURST_AND_REMOVE: Timer helper return at 00300e84-00300e94 selects 3 by storing to moby+0x20. That identical switch selector dispatches state 3 to explosion then mark_moby_for_removal at 003013d4-003013e0, proving reuse of the existing local member. domain_2_value_1 -> SPARK_WAIT_FOR_DESCENT: At 00300edc-00300f10 gravity reduces private velocity.z; moby+0x20 is compared with 1 and cleared when z becomes negative. This is the same byte switched by the source SPARK_WAIT_FOR_DESCENT case, proving the existing member's domain. domain_3_value_0 -> SPARK_COUNT_NEXT_BOUNCE: The store of zero to moby+0x20 at 00300f10 follows the state-1 negative-vertical-velocity test. The same state byte gates bounce counting at 00301134-00301160, where zero increments bounces and selects state 1; reuse SPARK_COUNT_NEXT_BOUNCE. domain_4_value_0 -> SPARK_COUNT_NEXT_BOUNCE: The source contact condition spark_moby->state == 0 maps to lbu moby+0x20 and beq zero at 003010a4-003010a8. This identical switch selector is SPARK_COUNT_NEXT_BOUNCE; its later zero-state branch increments the bounce counter at 0030114c-00301160. domain_5_value_0 -> SPARK_COUNT_NEXT_BOUNCE: At 00301134-00301160 the moby+0x20 zero comparison gates setting state 1 and incrementing private bounces at +0x2a. This is the source switch's SPARK_COUNT_NEXT_BOUNCE selector, directly proving reuse rather than an unrelated zero-valued constant. domain_6_value_1 -> SPARK_WAIT_FOR_DESCENT: The state-byte store of 1 at 00301140-00301148 accompanies the counted-bounce increment. That same moby+0x20 byte is tested for 1 at 00300ef0-00300f10 until vertical velocity becomes negative, matching the existing SPARK_WAIT_FOR_DESCENT member. domain_7_value_2 -> SPARK_ROLL_AND_FADE: Four counted bounces trigger sb 2 to moby+0x20 at 003011e4-003011fc, zero vertical velocity and initialize rolling speed/fade rate through 00301260. The same selector dispatches to existing SPARK_ROLL_AND_FADE, which updates glow RGB and rolling motion. domain_8_value_2 -> SPARK_ROLL_AND_FADE: At 003013ec-00301400 the same moby+0x20 state byte is compared unsigned against 2: states 0/1 calculate XY vector speed, while equality to 2 reads stored rolling speed at 00301414. The boundary is the existing SPARK_ROLL_AND_FADE enum member in this exact selector domain. domain_9_value_2 -> SPARK_ROLL_AND_FADE: At 0030140c-00301414 equality of the moby+0x20 state byte with 2 selects private vel.w as speed. State 2 establishes that rolling speed at 003011f4-00301240 and uses it in the source SPARK_ROLL_AND_FADE branch, proving canonical local member reuse. --- src/overlays/l14/mobys/bouncing_spark.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l14/mobys/bouncing_spark.c b/src/overlays/l14/mobys/bouncing_spark.c index 24ea619543..d6d6858678 100644 --- a/src/overlays/l14/mobys/bouncing_spark.c +++ b/src/overlays/l14/mobys/bouncing_spark.c @@ -102,10 +102,10 @@ void bouncing_spark_update(struct Moby *spark_moby) { float hi; if (((coll_sphere(&spark_moby->pos, 0, spark_moby, 0.65f) != 0) && (D_L14_00174558 != 0)) && (D_L14_00174558 != spark_data->owner)) { - spark_moby->state = 3; + spark_moby->state = SPARK_BURST_AND_REMOVE; } if (fast_dec_timer(&spark_data->fade) != 0) { - spark_moby->state = 3; + spark_moby->state = SPARK_BURST_AND_REMOVE; } switch (spark_moby->state) { case SPARK_COUNT_NEXT_BOUNCE: @@ -113,8 +113,8 @@ void bouncing_spark_update(struct Moby *spark_moby) { case SPARK_WAIT_FOR_DESCENT: { fast_vec_add(&predicted_position_or_fade_rgb, &spark_moby->pos, &spark_data->vel); spark_data->vel.z -= spark_data->vel.w; - if ((spark_moby->state == 1) && (spark_data->vel.z < 0.0f)) { - spark_moby->state = 0; + if ((spark_moby->state == SPARK_WAIT_FOR_DESCENT) && (spark_data->vel.z < 0.0f)) { + spark_moby->state = SPARK_COUNT_NEXT_BOUNCE; } fast_dec_timer_s16(&spark_data->trail); if (spark_data->trail != 0) { @@ -160,15 +160,15 @@ void bouncing_spark_update(struct Moby *spark_moby) { qcopy(&spark_moby->pos, &predicted_position_or_fade_rgb); } if (((coll_sphere(&spark_moby->pos, 0, spark_moby, spark_contact_clearance_gp) != 0) && - ((spark_moby->state == 0) || ((spark_moby->pos.z - D_L14_00174540.hit.z) < 0.0f))) && + ((spark_moby->state == SPARK_COUNT_NEXT_BOUNCE) || ((spark_moby->pos.z - D_L14_00174540.hit.z) < 0.0f))) && ((D_L14_00174540.owner == 0) || (D_L14_00174540.owner != spark_data->owner))) { fast_vec_normalize( &position_scratch, &D_L14_00174540.normal, spark_contact_clearance_gp); fast_vec_add(&spark_moby->pos, &D_L14_00174540.hit, &position_scratch); reflect_vector(&spark_data->vel, &spark_data->vel, &D_L14_00174540.normal); allocate_voice_for_target_entry(1, 0, spark_moby); - if (spark_moby->state == 0) { - spark_moby->state = 1; + if (spark_moby->state == SPARK_COUNT_NEXT_BOUNCE) { + spark_moby->state = SPARK_WAIT_FOR_DESCENT; if ((++spark_data->bounces) == 1) { set_vector_length_xy(&spark_data->vel, &spark_data->vel, @@ -188,7 +188,7 @@ void bouncing_spark_update(struct Moby *spark_moby) { } if (spark_data->bounces >= 4) { float min; - spark_moby->state = 2; + spark_moby->state = SPARK_ROLL_AND_FADE; spark_data->vel.z = 0.0f; spark_data->vel.w = vector_length_xy(&spark_data->vel); spark_data->vel.w *= D_L14_001620A0; @@ -253,9 +253,9 @@ void bouncing_spark_update(struct Moby *spark_moby) { return; } - if (spark_moby->state < 2) { + if (spark_moby->state < SPARK_ROLL_AND_FADE) { speed = vector_length_xy(&spark_data->vel); - } else if (spark_moby->state == 2) { + } else if (spark_moby->state == SPARK_ROLL_AND_FADE) { speed = spark_data->vel.w; } else { return; From f9784014002ce9d5efdbd5c45ebe765be793c647 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:36:13 +0000 Subject: [PATCH 0982/1502] decomp: clarify names in update_moby_hit_response_burst_and_ballistic_flight domain_0_value_1 -> STATE_WAIT_FOR_HIT: Retail 0x002e981c loads 1 and 0x002e9820 stores it to moby+0x20 after initialization eligibility checks. Dispatch reads that same byte at 0x002e97ac and branches for 1 at 0x002e97b0 to 0x002e9838, which checks the hit helper with mask 0x80000, conditionally invokes the group action and sound, and clears hit_slot. Original Ghidra confirms the assignment and branch; authoritative C already names this exact selector's case STATE_WAIT_FOR_HIT=1. domain_1_value_3 -> STATE_BALLISTIC_FLIGHT: Retail 0x002e9c98 loads 3 and 0x002e9ca4 stores it to moby+0x20 in the non-0x37c launch branch, which initializes angular steps, velocity and saved height through 0x002e9d50. Dispatch reads that same byte at 0x002e97ac and selects 3 at 0x002e97dc, entering 0x002e9d54: rotate, reduce vertical velocity, integrate position, and burst/remove on height or collision condition. Original Ghidra agrees; authoritative C already names this selector's case STATE_BALLISTIC_FLIGHT=3. --- src/overlays/l18/mobys/destructible_scenery.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/destructible_scenery.c b/src/overlays/l18/mobys/destructible_scenery.c index 5ed5ac0294..2b72f2a937 100644 --- a/src/overlays/l18/mobys/destructible_scenery.c +++ b/src/overlays/l18/mobys/destructible_scenery.c @@ -70,7 +70,7 @@ void destructible_scenery_update(struct Moby *moby) { if (((unsigned char *)((int *)visited52))[mission_table_index] == 0xff) goto remove; } - moby->state = 1; + moby->state = STATE_WAIT_FOR_HIT; if (*(int *)hit_response_and_flight_private_vars != 0) *(int *)(*(int *)hit_response_and_flight_private_vars) = 3; return; @@ -176,7 +176,7 @@ void destructible_scenery_update(struct Moby *moby) { float vector[4]; float speed = random_float_between(10.0f, 15.0f) * frame_time; moby->collision = 0; - moby->state = 3; + moby->state = STATE_BALLISTIC_FLIGHT; hit_response_and_flight_private_vars[2] = randf_sym(0.0f, 90.0f) * DEG_TO_RAD * frame_time; hit_response_and_flight_private_vars[3] = From ff15bc7d61226a5ab6f2e0a1bf2e63a28d57589e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:37:56 +0000 Subject: [PATCH 0983/1502] decomp: clarify names in qwark_oltanis_update domain_0_value_1 -> QWARK_OLTANIS_STATE_UPDATE_DIALOGUE: Retail 002fbb54 initializes NPC dialogue, 002fbb5c sets the dialogue flag, and 002fbb64 stores s0=1 to moby state +0x20. The same byte is loaded at 002fba9c and value 1 dispatches at 002fbaa4 to 002fbb68, whose branch calls update_npc_dialogue at 002fbc18. The bound C already names that exact selector's case 1 QWARK_OLTANIS_STATE_UPDATE_DIALOGUE. domain_1_value_2 -> QWARK_OLTANIS_STATE_POST_DIALOGUE: Retail 002fbc18 calls update_npc_dialogue; only a nonzero return reaches begin_dialogue_camera_transition at 002fbc30 and li v0,2 / sb v0,0x20(s1) at 002fbc38-002fbc40. This is the same state byte loaded at 002fba9c and dispatched for value 2 at 002fbac4 to 002fbc44. The bound C names this exact moby-state case QWARK_OLTANIS_STATE_POST_DIALOGUE. domain_2_value_1 -> QWARK_OLTANIS_STATE_UPDATE_DIALOGUE: In the post-dialogue branch, retail 002fbc44-002fbc4c tests global 0015f5c4; on the non-2 path, 002fbc54 stores s0=1 into moby+0x20 before checking dialogue substate +4. The dispatch loads this same byte at 002fba9c and routes 1 to 002fbb68 and update_npc_dialogue at 002fbc18. This restores the existing QWARK_OLTANIS_STATE_UPDATE_DIALOGUE member, not the separate global-mode or dialogue-substate domain. --- src/overlays/l14/mobys/qwark_oltanis.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l14/mobys/qwark_oltanis.c b/src/overlays/l14/mobys/qwark_oltanis.c index 7603de3a9e..64d4e9f20f 100644 --- a/src/overlays/l14/mobys/qwark_oltanis.c +++ b/src/overlays/l14/mobys/qwark_oltanis.c @@ -181,7 +181,7 @@ void qwark_oltanis_update(L14WatchMoby *moby) { moby_vars->p20 = (void *)captain_qwark_name; initialize_npc_dialogue(moby, moby_vars); moby_vars->b8 = 1; - moby->state = 1; + moby->state = QWARK_OLTANIS_STATE_UPDATE_DIALOGUE; break; } case QWARK_OLTANIS_STATE_UPDATE_DIALOGUE: @@ -199,12 +199,12 @@ void qwark_oltanis_update(L14WatchMoby *moby) { } if (update_npc_dialogue(moby, moby_vars)) { begin_dialogue_camera_transition(moby, 3.0f); - moby->state = 2; + moby->state = QWARK_OLTANIS_STATE_POST_DIALOGUE; } break; case QWARK_OLTANIS_STATE_POST_DIALOGUE: if (D_L14_0015F5C4 != 2) { - moby->state = 1; + moby->state = QWARK_OLTANIS_STATE_UPDATE_DIALOGUE; if ((unsigned)(moby_vars->sub - 3) < 2) { if ((short)moby_vars->sub == 4) queue_dialogue_message(0x53DD, -1); From 3c133d28b5d48b6f39cff84e67a9605e277b7341 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:37:56 +0000 Subject: [PATCH 0984/1502] decomp: clarify names in fred_pokitaru_update domain_0_value_1 -> FRED_POKITARU_CHECK_DIALOGUE: Authoritative source SHA-256 07171625af1e3a51abe015b0b4b69d9db9e0e90921af28ef746eab384bb9d1be switches on moby->state and already defines FRED_POKITARU_CHECK_DIALOGUE = 1. Retail 0x002f0ebc loads that state byte at +0x20(s1), 0x002f0ec4 dispatches value 1 to the dialogue-update branch at 0x002f0f50, and 0x002f0ef8 stores 1 to precisely that byte during initialization. Original Ghidra shows *(undefined1 *)(iVar11 + 0x20) = 1 in bVar1 == 0. This assignment therefore enters the existing CHECK_DIALOGUE state. domain_1_value_2 -> FRED_POKITARU_WAIT_FOR_DIALOGUE_END: The source already defines FRED_POKITARU_WAIT_FOR_DIALOGUE_END = 2 for switch(moby->state). Retail 0x002f0f54 calls update_npc_dialogue, 0x002f0f5c tests its return, and the nonzero path calls begin_dialogue_camera_transition at 0x002f0f6c then stores 2 into +0x20(s1) at 0x002f0f78. The same byte is loaded at 0x002f0ebc and value 2 dispatches at 0x002f0ee4 to 0x002f1130, which retains the state while dialogue status equals 2. Original Ghidra confirms this state store following the dialogue-update success branch. Thus this is the existing WAIT_FOR_DIALOGUE_END member, not the separate status-global domain. domain_2_value_1 -> FRED_POKITARU_CHECK_DIALOGUE: In the authoritative source this assignment occurs in FRED_POKITARU_WAIT_FOR_DIALOGUE_END when D_L11_0015F5C4 != 2. Retail 0x002f1130 skips the transition while the separate dialogue status equals 2; otherwise 0x002f1138 stores a2 (1, established at 0x002f0ec0) into the same +0x20(s1) state byte read at 0x002f0ebc. Value 1 dispatches at 0x002f0ec4 to update_npc_dialogue at 0x002f0f54, matching the existing FRED_POKITARU_CHECK_DIALOGUE = 1 enum member. Original Ghidra shows the corresponding state = 1 before testing the pvars result and issuing save/help effects. --- src/overlays/l11/mobys/fred_pokitaru.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l11/mobys/fred_pokitaru.c b/src/overlays/l11/mobys/fred_pokitaru.c index 74be6846c2..837730e27d 100644 --- a/src/overlays/l11/mobys/fred_pokitaru.c +++ b/src/overlays/l11/mobys/fred_pokitaru.c @@ -86,7 +86,7 @@ void fred_pokitaru_update(struct Moby *moby) { } switch (moby->state) { case FRED_POKITARU_INITIALIZE: - moby->state = 1; + moby->state = FRED_POKITARU_CHECK_DIALOGUE; if (moby->prev_seq != 1) FUN_00212f90(moby, 1, 0, scale_game_frames(20)); if (D_0013D50B) { @@ -99,7 +99,7 @@ void fred_pokitaru_update(struct Moby *moby) { case FRED_POKITARU_CHECK_DIALOGUE: if (update_npc_dialogue(moby, moby_vars)) { begin_dialogue_camera_transition(moby, 3.0f); - moby->state = 2; + moby->state = FRED_POKITARU_WAIT_FOR_DIALOGUE_END; } if (alternate_item_available[1] == 0 && discount_purchase_pricing[0] == 0) { if (fast_vec_dist(&moby->pos, hero.motion.pos.f) < 4.0f) { @@ -125,7 +125,7 @@ void fred_pokitaru_update(struct Moby *moby) { break; case FRED_POKITARU_WAIT_FOR_DIALOGUE_END: if (D_L11_0015F5C4 != 2) { - moby->state = 1; + moby->state = FRED_POKITARU_CHECK_DIALOGUE; if (moby_vars->h04 == 2) { alternate_item_available[1] = 0; discount_purchase_pricing[0] = 1; From 88d2e0fd3c992a485b50b3c499c66193782061fc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:37:56 +0000 Subject: [PATCH 0985/1502] decomp: clarify names in draw_pause_menu_pages domain_0_value_20 -> PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION: Retail 00277340-0027734c loads the word at 001b9cf0, compares it with 0x14, and branches to the return path at 00277980 before any page rendering. Original retail Ghidra likewise gates the renderer on DAT_001b9cf0 != 0x14. The authoritative source (SHA-256 9544fef8197a046240836db85545ddc2c2ab715d085693f5ef7ffbc09c1b5036) identifies that exact word as D_L00_001B9CF0.state: close_pause_menu assigns its existing local enum PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION after releasing page objects and restoring gameplay resources; update_pause_menu compares the same field with the identically named enum and restores camera/render/world state before dispatching the requested action. This proves the pause-menu state domain and reuses its established semantic member, rather than the unrelated equal-valued HeroStateId member. --- src/overlays/shared/ui/menus/initialize_pause_menu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/ui/menus/initialize_pause_menu.c b/src/overlays/shared/ui/menus/initialize_pause_menu.c index fdc54b44c1..217e70aa49 100644 --- a/src/overlays/shared/ui/menus/initialize_pause_menu.c +++ b/src/overlays/shared/ui/menus/initialize_pause_menu.c @@ -724,6 +724,9 @@ extern void draw_menu_flashing_panel(int) __asm__("FUN_00223e28"); void draw_pause_menu_pages(int transfer_only) __asm__("FUN_L00_002772c0"); void draw_pause_menu_pages(int transfer_only) { + enum { + PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION = 0x14 + }; u128 corners[4]; u128 pad[5]; u128 box[2]; @@ -751,7 +754,7 @@ void draw_pause_menu_pages(int transfer_only) { } reset_gs_registers(); emit_rgba_draw_packet(0, 0, 0, 0x30); - if (D_L00_001B9CF0.state == 0x14) { + if (D_L00_001B9CF0.state == PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION) { return; } vu1_add_g_sregister(0x47, 0x5360B); From 2c3a139b4c281644f15e3569c13e05f893c562e8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:37:56 +0000 Subject: [PATCH 0986/1502] decomp: clarify names in process_pad_input domain_1_value_0 -> PAD_INPUT_FILTER_NONE: Source pad_state->mode is the s32 field at PAD+0x1CC. Retail 0x00217734-0x0021773C compares this selector to 1; 0x0021777C-0x00217780 compares it to 2. The mode-1 branch resets the same selector to zero at 0x00217774 after masking controls. Zero skips both filter branches, so this assignment restores no filtering. Original Ghidra shows the identical field, comparisons and reset. domain_2_value_2 -> PAD_INPUT_FILTER_SUPPRESS_DIRECTIONS: The selector is the same Pad input-filter field at +0x1CC, compared with 2 at retail 0x0021777C-0x00217780. This branch masks held/pressed/released/raw to 0x900 at 0x00217788-0x002177B0, forces nodir at +0x1D4 at 0x002177B8, and zeros axes[2]/axes[3] at +0x108/+0x10C at 0x002177BC-0x002177C0. Retail 0x00217574-0x002175F8 proves these exact axes synthesize direction bits 0xF000; 0x00217618-0x00217630 derives nodir from those bits. Thus directional suppression is proven by branch behavior, not by the number 2. domain_3_value_0 -> PAD_INPUT_FILTER_NONE: Retail 0x002177C4 stores zero to PAD+0x1CC after the direction-suppression filter. It is the same selector tested against 1 and 2 at 0x00217734-0x00217780, so zero restores the mode that bypasses both conditional input filters. The authoritative source and original Ghidra both reset this field after clearing axes[2]/axes[3]; reuse the identical member as the other zero reset. --- src/input/process_pad_input.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/input/process_pad_input.c b/src/input/process_pad_input.c index c6ee4c6ad8..14db100139 100644 --- a/src/input/process_pad_input.c +++ b/src/input/process_pad_input.c @@ -16,6 +16,10 @@ extern float fast_difference_between_rotations(float, float) __asm__("func void process_pad_input(struct PadState *p, u8 *buf, s32 len) __asm__("FUN_00217328"); void process_pad_input(struct PadState *pad_state, u8 *pad_read_data, s32 pad_read_byte_count) { + enum { + PAD_INPUT_FILTER_NONE = 0, + PAD_INPUT_FILTER_SUPPRESS_DIRECTIONS = 2 + }; float axis_vector[2]; s32 i, j, k; s32 held_buttons, old, ncur, nold; @@ -99,9 +103,9 @@ void process_pad_input(struct PadState *pad_state, u8 *pad_read_data, s32 pad_re pad_state->released &= ~0x5030; pad_state->analog[0] = 0.0f; pad_state->analog[1] = 0.0f; - pad_state->mode = 0; + pad_state->mode = PAD_INPUT_FILTER_NONE; } - if (pad_state->mode == 2) { + if (pad_state->mode == PAD_INPUT_FILTER_SUPPRESS_DIRECTIONS) { pad_state->held = *(volatile s32 *)&pad_state->held & 0x900; pad_state->pressed &= 0x900; pad_state->released &= 0x900; @@ -109,7 +113,7 @@ void process_pad_input(struct PadState *pad_state, u8 *pad_read_data, s32 pad_re pad_state->no_direction = 1; pad_state->analog[2] = 0.0f; pad_state->analog[3] = 0.0f; - pad_state->mode = 0; + pad_state->mode = PAD_INPUT_FILTER_NONE; } axis_vector[0] = pad_state->analog[2]; axis_vector[1] = pad_state->analog[3]; From 82c6628df08790efbd7c0a3a13865245b0d77bf5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:40:00 +0000 Subject: [PATCH 0987/1502] decomp: clarify names in draw_bot_door_lock_glow domain_0_value_1 -> GEOMETRY_QUAD_TEX1_FIXED_LOD: Retail 0x00307614 loads 1 and 0x00307620 stores it to quad+0x80. The checked level-06 draw_geometry_quad helper preserves the quad pointer in s2 at 0x00214fbc, loads its 64-bit +0x80 field at 0x002151dc, pairs that value with register address 0x14 at 0x002151e4/0x00215204, and emits the pair at 0x00215224 in the GS A+D packet. GS register 0x14 is TEX1_1; value 1 sets LCM=1 (fixed LOD), leaving the other TEX1 fields zero. This proves a TEX1 fixed-LOD register value, not a moby state or boolean. --- src/overlays/shared/props/bot_door_lock.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/props/bot_door_lock.c b/src/overlays/shared/props/bot_door_lock.c index 9473d56eb7..e4a25a5ce1 100644 --- a/src/overlays/shared/props/bot_door_lock.c +++ b/src/overlays/shared/props/bot_door_lock.c @@ -26,6 +26,9 @@ extern int D_L06_001fe9d0[][4]; void draw_bot_door_lock_glow(struct Moby *moby) __asm__("FUN_L06_00307578"); void draw_bot_door_lock_glow(struct Moby *moby) { + enum { + GEOMETRY_QUAD_TEX1_FIXED_LOD = 1 + }; struct GeometryQuad quad; OvlVec4 rotated_quad_corners[4]; float rotation[4]; @@ -45,7 +48,7 @@ void draw_bot_door_lock_glow(struct Moby *moby) { bot_door_lock_private_data[7] += 0.01f; if (1.0f < bot_door_lock_private_data[7]) bot_door_lock_private_data[7] -= 1.0f; - quad.texture_state = 1; + quad.texture_state = GEOMETRY_QUAD_TEX1_FIXED_LOD; quad.primitive = 0x4000000044ULL; quad.reserved.value = 0; quad.texture = get_effect_texture(0x18); From dee14c66490afdf602cf6265f64bbef25bb63c9e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:40:00 +0000 Subject: [PATCH 0988/1502] decomp: clarify names in update_kerwan_path_enemy_hit_reaction domain_1_value_13 -> ENEMY_DEATH_KNOCKBACK: Recipient a0 is saved in s1 at 0x002c95b4; its current-state byte is +0x20, the same Moby2C8398.state used by owner update_kerwan_path_enemy. The supplied owner calls this function through FUN_L00_001fefc8_cf bound to FUN_L03_002c95a8 and switches on this same state field. Retail 0x002c9674-0x002c9678 reads recipient+0x20 and skips hit processing when it equals 13. The lethal branch writes the same state at 0x002c9c24. Owner case ENEMY_DEATH_KNOCKBACK=13 steps the death motion and spawns debris/removes or hides the entity; this guard prevents restarting that death reaction. domain_2_value_10 -> ENEMY_KNOCKBACK_RECOVERY: Recipient a0 is saved in s1 at 0x002c95b4; its current-state byte is +0x20, the same Moby2C8398.state used by owner update_kerwan_path_enemy. The supplied owner calls this function through FUN_L00_001fefc8_cf bound to FUN_L03_002c95a8 and switches on this same state field. TURN_AWAY_KNOCKBACK_RESPONSE initializes the arc, conditionally changes facing at 0x002c9864, starts knockback at 0x002c987c and selects 10 at 0x002c98a8 for the state store at 0x002c9ae0. Owner case ENEMY_KNOCKBACK_RECOVERY=10 steps moby_data->q and resumes path movement when motion completes. domain_3_value_10 -> ENEMY_KNOCKBACK_RECOVERY: Recipient a0 is saved in s1 at 0x002c95b4; its current-state byte is +0x20, the same Moby2C8398.state used by owner update_kerwan_path_enemy. The supplied owner calls this function through FUN_L00_001fefc8_cf bound to FUN_L03_002c95a8 and switches on this same state field. Grouped responses 3/7/8 initialize the arc at 0x002c98ac, adjust its hit vector at 0x002c9980, start animation-five knockback at 0x002c999c and select 10 at 0x002c99b8 for the current-state store at 0x002c9ae0. The owner names state 10 ENEMY_KNOCKBACK_RECOVERY and handles motion completion by returning to path behavior. domain_4_value_10 -> ENEMY_KNOCKBACK_RECOVERY: Recipient a0 is saved in s1 at 0x002c95b4; its current-state byte is +0x20, the same Moby2C8398.state used by owner update_kerwan_path_enemy. The supplied owner calls this function through FUN_L00_001fefc8_cf bound to FUN_L03_002c95a8 and switches on this same state field. Grouped responses 4/5 adjust the arc at 0x002c9a90 and start animation-six knockback at 0x002c9aac, select 10 at 0x002c9abc, then store it into recipient+0x20 at 0x002c9ae0. Owner case ENEMY_KNOCKBACK_RECOVERY=10 consumes this initialized motion and restores path movement after completion. domain_5_value_13 -> ENEMY_DEATH_KNOCKBACK: Recipient a0 is saved in s1 at 0x002c95b4; its current-state byte is +0x20, the same Moby2C8398.state used by owner update_kerwan_path_enemy. The supplied owner calls this function through FUN_L00_001fefc8_cf bound to FUN_L03_002c95a8 and switches on this same state field. Nonpositive health forces DEATH_KNOCKBACK_RESPONSE at 0x002c9718. Its branch starts animation-seven knockback at 0x002c9bc8, clears flag 0x1000 at 0x002c9c14 and stores state 13 to recipient+0x20 at 0x002c9c24. Owner ENEMY_DEATH_KNOCKBACK=13 steps that motion and spawns debris/removes or hides the enemy. --- src/overlays/l03/mobys/kerwan_path_enemy.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/overlays/l03/mobys/kerwan_path_enemy.c b/src/overlays/l03/mobys/kerwan_path_enemy.c index 1170e4fe59..48e990421c 100644 --- a/src/overlays/l03/mobys/kerwan_path_enemy.c +++ b/src/overlays/l03/mobys/kerwan_path_enemy.c @@ -1491,6 +1491,10 @@ void update_kerwan_path_enemy_hit_reaction(Moby2C8398 *moby) { NO_KNOCKBACK_HIT_RESPONSE = 12, ZERO_DAMAGE_NO_KNOCKBACK_RESPONSE = 13 }; + enum { + ENEMY_KNOCKBACK_RECOVERY = 10, + ENEMY_DEATH_KNOCKBACK = 0xD + }; float hit_knockback_vector[4]; int kind; float damage; @@ -1514,7 +1518,7 @@ void update_kerwan_path_enemy_hit_reaction(Moby2C8398 *moby) { hit = find_moby_hit(moby, 0x330000, 0); hit_response_code = resolve_moby_hit_response(moby, hit, &moby_data->f20, 0, &kind, &damage, 0, 4); - if (hit != 0 && kind != 1 && moby->state != 0xD) { + if (hit != 0 && kind != 1 && moby->state != ENEMY_DEATH_KNOCKBACK) { hit_record_source_moby = *(char **)(hit + 0x20); if (hit_record_source_moby != 0) { if (hit_record_source_moby != (char *)hero.items[0].moby) { @@ -1560,7 +1564,7 @@ void update_kerwan_path_enemy_hit_reaction(Moby2C8398 *moby) { set_moby_animation(moby, 5, 5); moby_data->q.f50 = 14.0f; moby_data->q.f54 = 28.0f; - moby->state = 10; + moby->state = ENEMY_KNOCKBACK_RECOVERY; allocate_voice_for_target_entry(1, 0, (int)moby); break; case KNOCKBACK_WITHOUT_FACING_CHANGE_RESPONSE: @@ -1584,7 +1588,7 @@ void update_kerwan_path_enemy_hit_reaction(Moby2C8398 *moby) { trooper_start_knockback(angle, moby, (char *)moby_data + 0x70, 5, 5, 0); moby_data->q.f50 = 6.0f; moby_data->q.f54 = 13.0f; - moby->state = 10; + moby->state = ENEMY_KNOCKBACK_RECOVERY; allocate_voice_for_target_entry(1, 0, (int)moby); break; case ALTERNATE_ANIMATION_KNOCKBACK_RESPONSE: @@ -1607,7 +1611,7 @@ void update_kerwan_path_enemy_hit_reaction(Moby2C8398 *moby) { trooper_start_knockback(angle, moby, (char *)moby_data + 0x70, 6, 5, 2); moby_data->q.f50 = 5.0f; moby_data->q.f54 = 10.0f; - moby->state = 10; + moby->state = ENEMY_KNOCKBACK_RECOVERY; allocate_voice_for_target_entry(1, 0, (int)moby); break; case DEATH_KNOCKBACK_RESPONSE: @@ -1631,7 +1635,7 @@ void update_kerwan_path_enemy_hit_reaction(Moby2C8398 *moby) { moby_data->b255 = 0; moby->flags &= 0xEFFF; moby_data->b67 = 0xFA; - moby->state = 0xD; + moby->state = ENEMY_DEATH_KNOCKBACK; allocate_voice_for_target_entry(3, 0, (int)moby); if (moby->anim != 7) { blend_moby_animation(moby, 7, 0, scale_game_frames(6)); From 0279d3e76b385d42e35b321a41b6cce3ecf1150c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:40:00 +0000 Subject: [PATCH 0989/1502] decomp: clarify names in update_bomb domain_1_value_98 -> BOMB_STATE_EXPLODE_AND_REMOVE: Retail 0x002d2494 loads 0x62 and 0x002d2498 stores it to moby+0x20 after a sphere hit with command bit 2 clear. This is the same moby state byte reloaded at 0x002d24d8 into s6 and dispatched at 0x002d2504/0x002d250c. The authoritative local enum names 0x62 BOMB_STATE_EXPLODE_AND_REMOVE (spawn_explosion at 0x002d2a14) and 0x63 BOMB_STATE_BURST_AND_REMOVE (cart_burst at 0x002d2a8c); both remove the moby at 0x002d2a94. Original retail Ghidra confirms this data flow. domain_2_value_99 -> BOMB_STATE_BURST_AND_REMOVE: Retail 0x002d2490 loads 0x63 and 0x002d2498 stores it to moby+0x20 after a sphere hit with command bit 2 set. This is the same moby state byte reloaded at 0x002d24d8 into s6 and dispatched at 0x002d2504/0x002d250c. The authoritative local enum names 0x62 BOMB_STATE_EXPLODE_AND_REMOVE (spawn_explosion at 0x002d2a14) and 0x63 BOMB_STATE_BURST_AND_REMOVE (cart_burst at 0x002d2a8c); both remove the moby at 0x002d2a94. Original retail Ghidra confirms this data flow. domain_3_value_98 -> BOMB_STATE_EXPLODE_AND_REMOVE: Retail 0x002d2704 loads 0x62 and 0x002d2708 stores it to moby+0x20 after a segment hit with command bit 2 clear. This is the same moby state byte reloaded at 0x002d24d8 into s6 and dispatched at 0x002d2504/0x002d250c. The authoritative local enum names 0x62 BOMB_STATE_EXPLODE_AND_REMOVE (spawn_explosion at 0x002d2a14) and 0x63 BOMB_STATE_BURST_AND_REMOVE (cart_burst at 0x002d2a8c); both remove the moby at 0x002d2a94. Original retail Ghidra confirms this data flow. domain_4_value_99 -> BOMB_STATE_BURST_AND_REMOVE: Retail 0x002d2700 loads 0x63 and 0x002d2708 stores it to moby+0x20 after a segment hit with command bit 2 set. This is the same moby state byte reloaded at 0x002d24d8 into s6 and dispatched at 0x002d2504/0x002d250c. The authoritative local enum names 0x62 BOMB_STATE_EXPLODE_AND_REMOVE (spawn_explosion at 0x002d2a14) and 0x63 BOMB_STATE_BURST_AND_REMOVE (cart_burst at 0x002d2a8c); both remove the moby at 0x002d2a94. Original retail Ghidra confirms this data flow. domain_5_value_98 -> BOMB_STATE_EXPLODE_AND_REMOVE: Retail 0x002d286c loads 0x62 and 0x002d2874 stores it to moby+0x20 on the surface collision path when command bit 1 is clear. This is the same moby state byte reloaded at 0x002d24d8 into s6 and dispatched at 0x002d2504/0x002d250c. The authoritative local enum names 0x62 BOMB_STATE_EXPLODE_AND_REMOVE (spawn_explosion at 0x002d2a14) and 0x63 BOMB_STATE_BURST_AND_REMOVE (cart_burst at 0x002d2a8c); both remove the moby at 0x002d2a94. Original retail Ghidra confirms this data flow. domain_6_value_99 -> BOMB_STATE_BURST_AND_REMOVE: Retail 0x002d28cc loads 0x63 and 0x002d28d4 stores it to moby+0x20 when the moving countdown expires with command bit 2 set. This is the same moby state byte reloaded at 0x002d24d8 into s6 and dispatched at 0x002d2504/0x002d250c. The authoritative local enum names 0x62 BOMB_STATE_EXPLODE_AND_REMOVE (spawn_explosion at 0x002d2a14) and 0x63 BOMB_STATE_BURST_AND_REMOVE (cart_burst at 0x002d2a8c); both remove the moby at 0x002d2a94. Original retail Ghidra confirms this data flow. domain_7_value_98 -> BOMB_STATE_EXPLODE_AND_REMOVE: Retail 0x002d28d8 loads 0x62 and 0x002d28e0 stores it to moby+0x20 when the moving countdown expires with command bit 2 clear. This is the same moby state byte reloaded at 0x002d24d8 into s6 and dispatched at 0x002d2504/0x002d250c. The authoritative local enum names 0x62 BOMB_STATE_EXPLODE_AND_REMOVE (spawn_explosion at 0x002d2a14) and 0x63 BOMB_STATE_BURST_AND_REMOVE (cart_burst at 0x002d2a8c); both remove the moby at 0x002d2a94. Original retail Ghidra confirms this data flow. domain_8_value_99 -> BOMB_STATE_BURST_AND_REMOVE: Retail 0x002d28f0 loads 0x63 and 0x002d28f8 stores it to moby+0x20 when the stationary fuse countdown expires. This is the same moby state byte reloaded at 0x002d24d8 into s6 and dispatched at 0x002d2504/0x002d250c. The authoritative local enum names 0x62 BOMB_STATE_EXPLODE_AND_REMOVE (spawn_explosion at 0x002d2a14) and 0x63 BOMB_STATE_BURST_AND_REMOVE (cart_burst at 0x002d2a8c); both remove the moby at 0x002d2a94. Original retail Ghidra confirms this data flow. --- src/overlays/l08/mobys/bomb.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l08/mobys/bomb.c b/src/overlays/l08/mobys/bomb.c index b88934010a..311a6d4650 100644 --- a/src/overlays/l08/mobys/bomb.c +++ b/src/overlays/l08/mobys/bomb.c @@ -125,9 +125,9 @@ void moby_248_update(char *moby) { if (sphere_hit_moby != 0 && (sphere_hit_moby != bomb_vars->unk30 || bomb_vars->unk24 != 0)) { if (!(MOBY(moby)->command & 2)) - MOBY(moby)->state = 0x62; + MOBY(moby)->state = BOMB_STATE_EXPLODE_AND_REMOVE; else - MOBY(moby)->state = 0x63; + MOBY(moby)->state = BOMB_STATE_BURST_AND_REMOVE; qcopy((moby + 0x10), ((char *)D_L08_00174660)); FUN_L00_001ff660_c( &bomb_vars->unk10, &bomb_vars->unk10, ((char *)D_L08_00174660) + 0x20); @@ -182,9 +182,9 @@ void moby_248_update(char *moby) { if (v != 0) { if (v != bomb_vars->unk30 || bomb_vars->unk24 != 0) { if (!(MOBY(moby)->command & 2)) - MOBY(moby)->state = 0x62; + MOBY(moby)->state = BOMB_STATE_EXPLODE_AND_REMOVE; else - MOBY(moby)->state = 0x63; + MOBY(moby)->state = BOMB_STATE_BURST_AND_REMOVE; qcopy((moby + 0x10), ((char *)D_L08_00174660)); { char *v = &bomb_vars->unk10; @@ -220,7 +220,7 @@ void moby_248_update(char *moby) { clear_u64_value((&bomb_vars->unk10)); } } else { - MOBY(moby)->state = 0x62; + MOBY(moby)->state = BOMB_STATE_EXPLODE_AND_REMOVE; qcopy((moby + 0x10), collision_result + 0x20); FUN_L00_001ff660_c( (&bomb_vars->unk10), (&bomb_vars->unk10), collision_result + 0x40); @@ -230,16 +230,16 @@ void moby_248_update(char *moby) { } } else if (fast_dec_timer(&bomb_vars->timer_20)) { if (MOBY(moby)->command & 2) { - MOBY(moby)->state = 0x63; + MOBY(moby)->state = BOMB_STATE_BURST_AND_REMOVE; } else { - MOBY(moby)->state = 0x62; + MOBY(moby)->state = BOMB_STATE_EXPLODE_AND_REMOVE; } } break; } case BOMB_STATE_STATIONARY_FUSE: if (fast_dec_timer(&bomb_vars->timer_20)) { - MOBY(moby)->state = 0x63; + MOBY(moby)->state = BOMB_STATE_BURST_AND_REMOVE; } else if (bomb_vars->timer_20 == scale_game_frames(0x3C) || bomb_vars->timer_20 == scale_game_frames(0x28) || bomb_vars->timer_20 == scale_game_frames(0x14)) { From e8d8c310e20b7307d88239f0067172a783a96d4c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:40:00 +0000 Subject: [PATCH 0990/1502] decomp: clarify names in update_level01_cutscene_effects domain_0_value_1 -> CUTSCENE_FX_STATE_UPDATE: Authoritative source SHA-256 79cc14f4c1a08a5158e2754e8e0c77443121ac7727c63cbdfbc3018b3de83301 declares CUTSCENE_FX_STATE_UPDATE=1 and uses it in switch(moby->state). Original retail decompilation writes 1 to param_1+0x20 during initialization and dispatches that same byte's value 1 into update behavior. Retail 0030c1d0 loads +0x20; 0030c1d8/0030c1dc compare 1 and branch to 0030c200. Retail 0030c1f0/0030c1f4 stores 1 to the identical +0x20 field, while 0030c1fc sets update_dist=0xff. Thus this assignment enters the established local update state, whose 0030c200-0030c20c gate precedes scene/frame effects; it is not a boolean or cutscene-mode value. --- src/overlays/l01/mobys/cutscene_effects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/cutscene_effects.c b/src/overlays/l01/mobys/cutscene_effects.c index ced1676e64..d44103eaa3 100644 --- a/src/overlays/l01/mobys/cutscene_effects.c +++ b/src/overlays/l01/mobys/cutscene_effects.c @@ -102,7 +102,7 @@ void level01_cutscene_effects_update(struct Moby *moby) { switch (moby->state) { case CUTSCENE_FX_STATE_INITIALIZE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = CUTSCENE_FX_STATE_UPDATE; break; case CUTSCENE_FX_STATE_UPDATE: if (cutscene_mode_macro == 2) { From a26831db691912aac846a9497eef157e173d478d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:40:00 +0000 Subject: [PATCH 0991/1502] decomp: clarify names in teleporter_update domain_0_value_0 -> TELEPORTER_INITIALIZE: Source compares moby->state, the same byte used by switch(moby->state). Retail 0x00308c74-0x00308c78 tests byte +0x20 against zero; switch dispatch at 0x00308d0c-0x00308d2c reads that identical byte. Existing TELEPORTER_INITIALIZE=0 case creates the three children at 0x00308d34-0x00308de4. Reuse its canonical member. domain_11_value_4 -> TELEPORTER_RETURN_TO_IDLE: Retail 0x0030906c-0x00309070 writes 4 to current moby+0x20 if preparation poll returns zero. Existing switch case TELEPORTER_RETURN_TO_IDLE=4 uses that same selector and at 0x003091c0-0x00309294 restores radius, retracts child-motion scalars and returns to state 1. This proves the recovery state regardless of why the poll returned zero. domain_12_value_4 -> TELEPORTER_RETURN_TO_IDLE: Original Ghidra case 3 and retail 0x003090d8-0x00309120 resolve destination_moby from the current teleporter's linked moby index, read its pvars and move the hero to its position/rotation. 0x00309160 writes 4 to destination+0x20, initializing its same child/radius fields at 0x00309168-0x00309184 for the return-to-idle update. The linked destination is in the same teleporter state domain; reuse TELEPORTER_RETURN_TO_IDLE=4. domain_13_value_1 -> TELEPORTER_WAIT_FOR_USE: After transferring the hero to the linked destination and starting destination recovery, retail 0x00309188-0x003091b4 writes state 1 to the current source teleporter+0x20 and clears its child-motion scalars. This identical switch selector's existing TELEPORTER_WAIT_FOR_USE=1 waits for the next grounded-hero use input. Reuse its canonical member. domain_14_value_1 -> TELEPORTER_WAIT_FOR_USE: Retail shared recovery path 0x00309218-0x0030928c reduces both child-motion scalars to zero, then writes 1 to current moby+0x20. Original Ghidra cases 4/8 and source agree. That byte is the switch selector whose established TELEPORTER_WAIT_FOR_USE=1 branch waits for a valid grounded-hero use request. Reuse the existing state member. domain_1_value_5 -> TELEPORTER_WAIT_FOR_ACTIVATION: Retail 0x00308de8-0x00308e0c writes state 5 when both pvars+0x38 and saved active status are zero, then hides the teleporter and children. Retail 0x00308c80-0x00308ccc checks the activation volume while inactive, records activation, shows the objects, and changes state 5 to 1. This comparison identifies the inactive state waiting for activation, not the visibility byte at +0x31. domain_2_value_6 -> TELEPORTER_ENTER_WAIT_FOR_USE: Retail initialization 0x00308de8-0x00308e00 writes 6 to this moby's +0x20 state when configured or already active. The identical switch selector's existing TELEPORTER_ENTER_WAIT_FOR_USE=6 branch at 0x00308e18-0x00308e34 optionally updates the group then writes 1 and falls through to waiting checks. Reuse this member. domain_3_value_5 -> TELEPORTER_WAIT_FOR_ACTIVATION: Original Ghidra case 0 and retail 0x00308df4-0x00308e0c select state 5 and hide the teleporter when neither saved active nor pvars+0x38 is set. Activation flow 0x00308c80-0x00308ccc later shows it and replaces state 5 with wait-for-use state 1. This assignment shares the state domain and waiting-for-activation meaning of the state-5 comparison. domain_4_value_1 -> TELEPORTER_WAIT_FOR_USE: Retail 0x00308e30-0x00308e34 stores 1 to moby+0x20 after optional group entry handling, then falls through at 0x00308e38 to destination, grounded-hero and input checks. The source switch on this same moby->state already names case 1 TELEPORTER_WAIT_FOR_USE. Reuse that canonical member. domain_5_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Source g=&hero and g->vehicle_mode == 2 matches retail 0x00308e7c-0x00308e84: hero base 0x0013f350, lbu from +0x20a4 (0x001413f4), comparison to 2, and early return. This is the HeroVehicleMode field, not moby+0x20 nor hero state at 0x001413d4. Supplied include/rnc/hero/hero_state.h declares canonical HERO_VEHICLE_MODE_GIANT_CLANK=2 for exactly this selector. domain_6_value_2 -> TELEPORTER_PREPARE_TRANSFER: Retail 0x00308e68-0x00308ed0 requires a linked destination and grounded hero on this teleporter, then use input writes 2 to moby+0x20; 0x00308ed8-0x00308eec clears motion velocities and requests target pose. The same state selector already has TELEPORTER_PREPARE_TRANSFER=2, whose branch polls pose status and prepares child motion at 0x00308f90-0x00309070. domain_7_value_8 -> TELEPORTER_EFFECT_CYCLE_RETURN_TO_IDLE: Source TELEPORTER_EFFECT_CYCLE_PREPARE branch advances both child-motion scalars to 1. Retail 0x00308f70-0x00308f8c then calls voice helper, writes 8 to this moby's state +0x20 and clears radius +0x34. The identical switch state already names 8 TELEPORTER_EFFECT_CYCLE_RETURN_TO_IDLE, sharing the radius-restoration/child-reset path at 0x003091c0-0x00309294. domain_9_value_3 -> TELEPORTER_TRANSFER_TO_DESTINATION: Retail 0x00309048-0x00309068 sets radius +0x34 to 1.95 and moby+0x20 state to 3 when pose poll returns 2 after preparation gates. Existing switch member TELEPORTER_TRANSFER_TO_DESTINATION=3 handles that identical byte; 0x00309084-0x00309120 shrinks radius, resolves linked destination and transfers hero position/rotation. Reuse the established state name without naming poll status. --- src/overlays/shared/props/teleporter.c | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/overlays/shared/props/teleporter.c b/src/overlays/shared/props/teleporter.c index 76d4d8ded1..f787bb40d6 100644 --- a/src/overlays/shared/props/teleporter.c +++ b/src/overlays/shared/props/teleporter.c @@ -261,7 +261,7 @@ void teleporter_update(struct Moby *moby) { TELEPORTER_ENTER_WAIT_FOR_USE = 6, TELEPORTER_EFFECT_CYCLE_PREPARE = 7, TELEPORTER_EFFECT_CYCLE_RETURN_TO_IDLE = 8 - }; + } ; enum { TELEPORTER_WAIT_FOR_ACTIVATION = 5}; TeleporterVars *teleporter_vars = (TeleporterVars *)moby->pvars; int active = 0; @@ -272,12 +272,12 @@ void teleporter_update(struct Moby *moby) { active = 1; } active = active != 0; - if (moby->state != 0 && teleporter_vars->unk4 != -1 && !active && + if (moby->state != TELEPORTER_INITIALIZE && teleporter_vars->unk4 != -1 && !active && FUN_00214720(&hero.motion.pos, teleporter_vars->unk4) != 0) { active = 1; activate_teleporter_and_record_state(moby); show_teleporter_and_children(moby); - if (moby->state == 5) + if (moby->state == TELEPORTER_WAIT_FOR_ACTIVATION) moby->state = active; } if (teleporter_vars->unk3C != 0) { @@ -309,9 +309,9 @@ void teleporter_update(struct Moby *moby) { fast_add_rotations(MOBY(child_moby)->rot.z, (float)i * 2.0943952f); } if (teleporter_vars->unk38 != 0 || active) { - moby->state = 6; + moby->state = TELEPORTER_ENTER_WAIT_FOR_USE; } else { - moby->state = 5; + moby->state = TELEPORTER_WAIT_FOR_ACTIVATION; hide_teleporter_and_children((L01Moby *)moby); } update_teleporter_child_transforms(moby); @@ -321,7 +321,7 @@ void teleporter_update(struct Moby *moby) { if (moby->group != 0xFF) { set_moby_list_state((char *)moby->group, 1); } - moby->state = 1; + moby->state = TELEPORTER_WAIT_FOR_USE; case TELEPORTER_WAIT_FOR_USE: { struct Hero *g; if (teleporter_vars->unk8 >= 0 && @@ -330,7 +330,7 @@ void teleporter_update(struct Moby *moby) { if (*(int *)teleporter_vars == -1) break; g = &hero; - if (g->vehicle_mode == 2) + if (g->vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) break; if (((char *)g->ground_moby) != moby) break; @@ -340,7 +340,7 @@ void teleporter_update(struct Moby *moby) { if (!(pad_pressed_words[0] & 0x10)) break; allocate_voice_for_target_entry(0, 0, (void *)moby); - moby->state = 2; + moby->state = TELEPORTER_PREPARE_TRANSFER; teleporter_vars->unk30 = -1; *(int *)&teleporter_vars->unk2C = 0; *(int *)&teleporter_vars->unk28 = 0; @@ -365,7 +365,7 @@ void teleporter_update(struct Moby *moby) { teleporter_child_motion_max_speed_gp * frame_time); } else { allocate_voice_for_target_entry(1, 0, (void *)moby); - moby->state = 8; + moby->state = TELEPORTER_EFFECT_CYCLE_RETURN_TO_IDLE; teleporter_vars->unk34 = 0.0f; } update_teleporter_child_transforms(moby); @@ -389,9 +389,9 @@ void teleporter_update(struct Moby *moby) { } else if (D_L01_0015F594 != 4 || !(teleporter_vars->unk14[3] > 0.25f)) { if (transfer_preparation_status == 2) { teleporter_vars->unk34 = 1.95f; - moby->state = 3; + moby->state = TELEPORTER_TRANSFER_TO_DESTINATION; } else if (transfer_preparation_status == 0) { - moby->state = 4; + moby->state = TELEPORTER_RETURN_TO_IDLE; } } update_teleporter_child_transforms(moby); @@ -412,14 +412,14 @@ void teleporter_update(struct Moby *moby) { if (teleporter_vars->unk40 != -1 && teleporter_vars->unk44 != -1) { request_music_track(teleporter_vars->unk40, teleporter_vars->unk44); } - MOBY(destination_moby)->state = 4; + MOBY(destination_moby)->state = TELEPORTER_RETURN_TO_IDLE; td->unk34 = 0.0f; td->unk28 = 0.0f; td->unk2C = 0.0f; td->unk14[3] = 1.0f; td->unk24 = 1.0f; allocate_voice_for_target_entry(1, 0, (void *)destination_moby); - moby->state = 1; + moby->state = TELEPORTER_WAIT_FOR_USE; teleporter_vars->unk14[3] = 0.0f; teleporter_vars->unk24 = 0.0f; teleporter_vars->unk28 = 0.0f; @@ -448,7 +448,7 @@ void teleporter_update(struct Moby *moby) { teleporter_child_motion_deceleration_gp * frame_time_sq, teleporter_child_motion_max_speed_gp * frame_time); } else { - moby->state = 1; + moby->state = TELEPORTER_WAIT_FOR_USE; } update_teleporter_child_transforms(moby); break; From bc7a8ba5f0aaf2a0d903d735b3ab6bee774a4f93 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:40:00 +0000 Subject: [PATCH 0992/1502] decomp: clarify names in reveal_map_around_position domain_0_value_0 -> FALSE: Source initializes local state to 0 before the predicate. Retail 0x002485cc stores zero at sp+0x4c; 0x002485d4-0x002485fc conditionally replaces it with one for control_mode 17/18 or base_condition == 1. Loads at 0x00248708 and 0x0024871c are used exclusively in zero/nonzero branches gating filter flag bits 1 and 2. This proves Boolean false, not a hero state enum value. domain_1_value_1 -> TRUE: Source assigns state = 1 only when hero.state.control_mode == 17 or 18 or hero.base_condition == 1. Retail 0x002485c4 loads control_mode, 0x002485d4/0x002485dc test its range, and 0x002485e8-0x002485fc test base_condition and store one at sp+0x4c. Retail 0x0024870c/0x00248720 consume this as a Boolean for opposing filter gates, proving the existing TRUE constant. --- src/overlays/shared/ui/map/reveal_map_around_position.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/ui/map/reveal_map_around_position.c b/src/overlays/shared/ui/map/reveal_map_around_position.c index 687ebca56c..31dbbb785a 100644 --- a/src/overlays/shared/ui/map/reveal_map_around_position.c +++ b/src/overlays/shared/ui/map/reveal_map_around_position.c @@ -97,10 +97,10 @@ void reveal_map_around_position(f32 *position) { if (level >= 19) { level = 0; } - state = 0; + state = FALSE; if (hero.state.control_mode == 17 || hero.state.control_mode == 18 || hero.base_condition == 1) { - state = 1; + state = TRUE; } mode16 = hero.state.control_mode == 16; mode15 = hero.state.control_mode == 15; From cf370a60975aea6a4270abcb56d321c296c61dc4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:41:39 +0000 Subject: [PATCH 0993/1502] decomp: clarify names in handle_extermitank_hits_and_sync_children domain_0_value_1 -> MOBY_HIT_RESPONSE_SKIP_DAMAGE: Source SHA-256 2cc662bd124c30d0b6b850bafe103bbdd56d2dd49c0207c12b7d2adce2e96c1e and original retail 00305284..003052a0 pass sp+0x40 through t0 to resolve_moby_hit_response at level-05 00284730, then compare that output with 1 to branch past health subtraction and damage/destruction handling to 00305694. Bounded helper evidence f9e80b181e51418fb457c29f739e3ab9 proves t0 becomes s3 at 00284740. A null hit (s4) at 00284840 reaches 00284860..00284870, which stores status 1 and zeros the damage output. The response-mask rejection at 00284bfc..00284c10 also stores status 1 and clears hit+0x2c before copying that damage to the caller output at 00284c2c..00284c3c. Thus 1 denotes skipping damage processing; it is not in any supplied Hero enum domain. --- src/overlays/l05/mobys/extermitank.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l05/mobys/extermitank.c b/src/overlays/l05/mobys/extermitank.c index 6398c00886..53d8be429e 100644 --- a/src/overlays/l05/mobys/extermitank.c +++ b/src/overlays/l05/mobys/extermitank.c @@ -535,7 +535,7 @@ extern float extermitank_child_animation_speed_offset_scale_gp __asm__("D_L05_00 typedef struct Hero Hero; void handle_extermitank_hits_and_sync_children(char *moby) { - ExtermitankVars *extermitank_hit_sync_vars = (ExtermitankVars *)MOBY(moby)->pvars; + enum { MOBY_HIT_RESPONSE_SKIP_DAMAGE = 1 } ;ExtermitankVars *extermitank_hit_sync_vars = (ExtermitankVars *)MOBY(moby)->pvars; char *first; char *second; char *part0; @@ -568,7 +568,7 @@ void handle_extermitank_hits_and_sync_children(char *moby) { hit = part0; resolve_moby_hit_response( moby, hit, &extermitank_hit_sync_vars->health, 0, &hit_processing_status, &remaining, 0, 4); - if (hit_processing_status == 1 || (unsigned char)MOBY(moby)->state == 3) + if (hit_processing_status == MOBY_HIT_RESPONSE_SKIP_DAMAGE || (unsigned char)MOBY(moby)->state == 3) goto mark_children; { extermitank_hit_sync_vars->health -= remaining; From 0b4bfa39dd3e55c992ae3a287ffa15e550b844bf Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:41:39 +0000 Subject: [PATCH 0994/1502] decomp: clarify names in predict_throw_landing domain_0_value_0 -> BOMB_STATE_HELD: Retail 0x002ad48c loads thrown_moby+0x20 and 0x002ad490 selects the zero-state branch, which reconstructs the throw origin from hero facing and position at 0x002ad498..0x002ad530 and initializes a fresh 300-frame prediction at 0x002ad588. The nonzero branch instead uses the moby's actual position and remaining timer at 0x002ad598..0x002ad5c4. In the authoritative source spawn_bomb creates class 0x79 with byte +0x20 = 0; launch_bomb changes that byte to 1 and supplies launch velocity/timer. bomb_update moves the bomb only in state 1. These establish the bomb's held, pre-launch state, separately from all supplied hero enum domains. domain_1_value_2 -> THROW_LANDING_MODE_SKIP_LINKED_MOBY_MARKER: The third parameter is saved in s7 at retail 0x002ad428. At 0x002ad9f4..0x002ada18 it is compared with 2; only that mode, together with a nonnull coll_hit.moby and nonzero return from 0x002603d0, skips add_draw_callback(draw_bomb_landing_marker, thrown_moby) at 0x002ada24..0x002ada2c. Bounded helper evidence request 19afbf494d714c8db8fcad50c8dc374b shows 0x002603d0..0x002603fc returns moby->pvars+8's stored link only when moby exists and flags & 0x20, otherwise zero, matching supplied get_moby_pvars_link source. Thus this is a prediction mode suppressing the marker on linked moby hits, not a moby state or hero enum member. The bomb_update source invokes mode 2 as fallback after mode 0 fails. --- src/overlays/shared/weapons/bomb_glove_bomb.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/bomb_glove_bomb.c b/src/overlays/shared/weapons/bomb_glove_bomb.c index 112d0d20a1..b799bd2499 100644 --- a/src/overlays/shared/weapons/bomb_glove_bomb.c +++ b/src/overlays/shared/weapons/bomb_glove_bomb.c @@ -935,6 +935,10 @@ void launch_bomb(float *pos, unsigned char *moby, float *velocity) { int predict_throw_landing(LandingVars *v, M910 *thrown_moby, int mode) __asm__("FUN_L00_002ad410"); int predict_throw_landing(LandingVars *v, M910 *thrown_moby, int mode) { + enum { + BOMB_STATE_HELD = 0, + THROW_LANDING_MODE_SKIP_LINKED_MOBY_MARKER = 2 + }; U910 position, velocity, previous, hero_position, offset, start; int timer; int object_hit; @@ -946,7 +950,7 @@ int predict_throw_landing(LandingVars *v, M910 *thrown_moby, int mode) { if (D_L00_0015F5C4_002acbf0 != 0) return 0; qcopy(&previous, &thrown_moby->pos); - if (thrown_moby->state == 0) { + if (thrown_moby->state == BOMB_STATE_HELD) { position.f[0] = fast_cos(fast_add_rotations(-0.361968f, fast_arc_tan(hero.facing_x, hero.facing_y))) * 0.859039f; @@ -1065,7 +1069,7 @@ int predict_throw_landing(LandingVars *v, M910 *thrown_moby, int mode) { if (!FUN_L00_002603d0_2ad410(coll_hit.moby)) goto return_zero; } - if (mode != 2 || !coll_hit.moby || !FUN_L00_002603d0_2ad410(coll_hit.moby)) + if (mode != THROW_LANDING_MODE_SKIP_LINKED_MOBY_MARKER || !coll_hit.moby || !FUN_L00_002603d0_2ad410(coll_hit.moby)) add_draw_callback(draw_bomb_landing_marker, thrown_moby); if (!object_hit && v->last_hit) { if (v->last_hit->state == 0xfe) { From 0c2003e65f98a2a741859c5ddc89ce3734823662 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:41:39 +0000 Subject: [PATCH 0995/1502] decomp: clarify names in edwina_update domain_0_value_1 -> EDWINA_UPDATE_DIALOGUE: Retail 002eb604 loads the state byte from +0x20(s2), and 002eb60c dispatches value 1 to the dialogue update at 002eb678. In the state-zero branch, 002eb620 stores s3 (1) into that same +0x20 byte before dialogue initialization at 002eb640. This is the authoritative source switch(moby->state) domain with existing EDWINA_UPDATE_DIALOGUE = 1, proving the initialization assignment enters that member. domain_1_value_2 -> EDWINA_APPLY_DIALOGUE_COMPLETION: Retail 002eb68c calls the dialogue update and 002eb694 exits when its result is zero. On nonzero return, the camera transition at 002eb6a8 precedes li v0,2 at 002eb6b0 and sb v0,0x20(s2) at 002eb6bc. The same state byte is loaded at 002eb604 and value 2 dispatches via 002eb62c to completion handling at 002eb6c0. Reuse the existing same-selector EDWINA_APPLY_DIALOGUE_COMPLETION = 2. domain_2_value_1 -> EDWINA_UPDATE_DIALOGUE: Retail state-2 completion handling at 002eb6c0 waits for the global guard, restores the scalar at moby +0x58, clears persistence and optionally resets the camera. Instruction 002eb700 then stores s3 (loaded as 1 at 002eb608) into +0x20(s2), the same state byte dispatched at 002eb604-002eb62c. The source names this selector's value 1 EDWINA_UPDATE_DIALOGUE, so this assignment returns to that existing enum member. --- src/overlays/l12/mobys/edwina.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l12/mobys/edwina.c b/src/overlays/l12/mobys/edwina.c index 752bedeb7a..f6f51b3d8e 100644 --- a/src/overlays/l12/mobys/edwina.c +++ b/src/overlays/l12/mobys/edwina.c @@ -91,7 +91,7 @@ void edwina_update(L16WatchMoby *moby) { } switch (moby->state) { case EDWINA_INITIALIZE: - moby->state = 1; + moby->state = EDWINA_UPDATE_DIALOGUE; initialize_npc_dialogue(moby, &moby_data->activation); moby_data->activation.radius = 1.7f; initialize_moby_grounding(moby); @@ -103,7 +103,7 @@ void edwina_update(L16WatchMoby *moby) { update_npc_dialogue(moby, &moby_data->activation)) { begin_dialogue_camera_transition(moby, 2.52f); *(int *)((char *)moby + 0x58) = 0; - moby->state = 2; + moby->state = EDWINA_APPLY_DIALOGUE_COMPLETION; } break; case EDWINA_APPLY_DIALOGUE_COMPLETION: @@ -114,7 +114,7 @@ void edwina_update(L16WatchMoby *moby) { char *p = D_L12_001600EC + (moby_data->region << 7); jet_reset_camera(p + 0x30, p + 0x70); } - moby->state = 1; + moby->state = EDWINA_UPDATE_DIALOGUE; if (*(short *)((char *)moby_data + 0x24) == 2) { grant_inventory_item(4, 0); queue_dialogue_message(0x2EE6, -1); From 03e62b5e2f4a6c096ec2a9c15a1842702bab2e73 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:41:39 +0000 Subject: [PATCH 0996/1502] decomp: clarify names in process_gadgebot_interaction_candidate domain_0_value_2 -> GADGEBOT_ABSORPTION_DISABLED: Retail 0x002f2cb8 and 0x002f2cec dispatch candidate classes 0x400/0x516 to 0x002f3248. At 0x002f3250 lbu v0,0x20(s0) reads the candidate moby state, 0x002f3254 loads 2, and 0x002f3258 rejects that state before distance testing or absorption. Otherwise 0x002f3290-0x002f32a0 sets the gadgebot state 8, saves this candidate at pvars+0x304 and reports status 2. Supplied gadgebot_update state 8 moves inward toward that candidate and removes the gadgebot on arrival. The supplied select_nearest_gadgebot_interaction_target already names the same state-2 exclusion for the same candidate classes GADGEBOT_ABSORPTION_DISABLED; reuse its demonstrated domain meaning, not any equal-valued hero constant. --- src/overlays/shared/enemies/gadgebot.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/gadgebot.c b/src/overlays/shared/enemies/gadgebot.c index c9c1ab10c6..70d5879864 100644 --- a/src/overlays/shared/enemies/gadgebot.c +++ b/src/overlays/shared/enemies/gadgebot.c @@ -1428,6 +1428,9 @@ int process_gadgebot_interaction_candidate( int process_gadgebot_interaction_candidate( char *ctx, char *ow, char *moby, int flag, int *interaction_status_out) { + enum { + GADGEBOT_ABSORPTION_DISABLED = 2 + }; float candidate_position[4]; float vB[4]; float vA[4]; @@ -1564,7 +1567,7 @@ int process_gadgebot_interaction_candidate( case MOBY_CLASS_GADGEBOT_ABSORPTION_TARGET: if (flag != 0) return 0; - if (MOBY(moby)->state == 2) + if (MOBY(moby)->state == GADGEBOT_ABSORPTION_DISABLED) return 0; if (!(vector_distance_xy(ctx + 0x10, candidate_position) < 1.0f)) return 0; From c2de16c6179277ced7b8eb5ac4f7e03df12c2161 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:41:39 +0000 Subject: [PATCH 0997/1502] decomp: clarify names in agnogg_ship_front_update domain_0_value_1 -> AGNOGG_SHIP_WAIT_FOR_DESCENT_TRIGGER: Retail 002fadcc/002fadd8 writes 1 to moby+0x20 after initialization. The switch reads that same byte at 002fad94; case 1 waits on the clip-volume trigger at 002faeb8-002faec8 before entering descent. This is the existing local enum's state domain. domain_10_value_10 -> AGNOGG_SHIP_HOLD_TARGET_HEIGHT: Retail 002fb470-002fb48c performs save/show calls then writes 10 to moby+0x20. The switch reads the same state byte and case 10 at 002fb490-002fb494 copies target data+0x0C to position z, proving reuse of the existing hold-height member. domain_1_value_10 -> AGNOGG_SHIP_HOLD_TARGET_HEIGHT: Retail 002fae64-002fae68 writes 10 to moby+0x20 on the table-byte 0xFF bypass path. The same switch selector reads moby+0x20; case 10 at 002fb490-002fb494 copies data+0x0C to position z, proving reuse of the existing hold-height member. domain_2_value_2 -> AGNOGG_SHIP_DESCEND_TO_TARGET_HEIGHT: Retail 002faff0-002faff8 writes 2 to moby+0x20 after the clip-volume trigger and linked-moby preparation. The same selector's case 2 at 002faffc-002fb01c subtracts frame_time*5 from position z and later clamps to target height, matching the existing local member. domain_3_value_3 -> AGNOGG_SHIP_WAIT_FOR_ANIMATION_1_GATE: Retail 002fb104-002fb110 writes 3 to moby+0x20 after clamping z to data+0x0C. Case 3 reads that same selector and waits for moby+0x52==1 and animation flag +0x70 bit 2 at 002fb114-002fb12c, matching the existing local animation-gate member. domain_4_value_10 -> AGNOGG_SHIP_HOLD_TARGET_HEIGHT: Retail 002fb160-002fb168 branches for moby class 0x2DA to 002fb484-002fb48c, which stores 10 at moby+0x20. That is the same byte switched at 002fad94; its case 10 holds position z at data+0x0C, matching the existing local member. domain_5_value_4 -> AGNOGG_SHIP_WAIT_FOR_LINKED_MOBIES_INACTIVE: Retail 002fb168-002fb170 stores 4 at moby+0x20 on the other class branch after the animation gate. Case 4 on the same selector checks three linked indices and waits for absent/null or state 0xFD/0xFE mobies at 002fb190-002fb1d4, matching the existing local member. domain_6_value_5 -> AGNOGG_SHIP_WAIT_BEFORE_SCENE: Retail 002fb1f4-002fb208 sets data+8 timer from scale_game_frames(45), then writes 5 to moby+0x20. Case 5 reads that same state byte, waits for this timer to reach zero at 002fb20c-002fb210, then starts scene 3, matching the existing local member. domain_7_value_6 -> AGNOGG_SHIP_WAIT_FOR_SCENE_3_END: Retail 002fb21c-002fb23c calls start_scene with 3 and then writes 6 to moby+0x20. The same selector's case 6 at 002fb240-002fb250 waits while cutscene_mode is 2 before queuing the movie, matching the existing scene-3-wait member. domain_8_value_7 -> AGNOGG_SHIP_WAIT_TO_START_SCENE_4: Retail 002fb254-002fb264 queues the scene movie with argument 3 and writes 7 to moby+0x20. Case 7 on that same state byte waits on cutscene_mode at 002fb268-002fb274, then starts scene 4 at 002fb27c-002fb280, matching the existing local member. domain_9_value_8 -> AGNOGG_SHIP_WAIT_FOR_SCENE_4_END: Retail 002fb27c-002fb28c calls start_scene(4), then writes 8 to moby+0x20. Case 8 on the same selector waits while cutscene_mode is 2 at 002fb290-002fb29c before unlock/save operations, matching the existing scene-4-end member. --- src/overlays/l01/mobys/agnogg_ship_front.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l01/mobys/agnogg_ship_front.c b/src/overlays/l01/mobys/agnogg_ship_front.c index 917319b63d..2bd5ab29d2 100644 --- a/src/overlays/l01/mobys/agnogg_ship_front.c +++ b/src/overlays/l01/mobys/agnogg_ship_front.c @@ -182,7 +182,7 @@ void agnogg_ship_front_update(Moby_2FC140 *moby) { case AGNOGG_SHIP_INITIALIZE: fz = moby->pos.z - 0.75f; moby->f30 = 0xFF; - moby->state = 1; + moby->state = AGNOGG_SHIP_WAIT_FOR_DESCENT_TRIGGER; data->timer = 0; fd = data->f0; data->fC = fz; @@ -197,7 +197,7 @@ void agnogg_ship_front_update(Moby_2FC140 *moby) { if (moby->f53 != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(0x14)); } - moby->state = 10; + moby->state = AGNOGG_SHIP_HOLD_TARGET_HEIGHT; moby->flags = moby->flags & 0xFFBE; moby->f32 = level_table_byte; moby->f94 = moby->pclass->f10; @@ -227,7 +227,7 @@ void agnogg_ship_front_update(Moby_2FC140 *moby) { fast_arc_tan(moby->pos.x - l01_cuboids_macro[linked_moby_data->rec].pos.x, moby->pos.y - l01_cuboids_macro[linked_moby_data->rec].pos.y); } - moby->state = 2; + moby->state = AGNOGG_SHIP_DESCEND_TO_TARGET_HEIGHT; } } break; @@ -249,7 +249,7 @@ void agnogg_ship_front_update(Moby_2FC140 *moby) { } if (moby->pos.z <= data->fC) { moby->pos.z = data->fC; - moby->state = 3; + moby->state = AGNOGG_SHIP_WAIT_FOR_ANIMATION_1_GATE; } break; case AGNOGG_SHIP_WAIT_FOR_ANIMATION_1_GATE: @@ -263,9 +263,9 @@ void agnogg_ship_front_update(Moby_2FC140 *moby) { blend_moby_animation(moby, 2, 0, scale_game_frames(0x14)); } if (moby->oclass == 0x2DA) { - moby->state = 10; + moby->state = AGNOGG_SHIP_HOLD_TARGET_HEIGHT; } else { - moby->state = 4; + moby->state = AGNOGG_SHIP_WAIT_FOR_LINKED_MOBIES_INACTIVE; } break; case AGNOGG_SHIP_WAIT_FOR_LINKED_MOBIES_INACTIVE: @@ -293,7 +293,7 @@ void agnogg_ship_front_update(Moby_2FC140 *moby) { break; } data->timer = scale_game_frames(0x2D); - moby->state = 5; + moby->state = AGNOGG_SHIP_WAIT_BEFORE_SCENE; break; case AGNOGG_SHIP_WAIT_BEFORE_SCENE: if (data->timer != 0) { @@ -302,21 +302,21 @@ void agnogg_ship_front_update(Moby_2FC140 *moby) { data->fA = moby->f32; moby->flags = moby->flags | 0x41; start_scene(3); - moby->state = 6; + moby->state = AGNOGG_SHIP_WAIT_FOR_SCENE_3_END; break; case AGNOGG_SHIP_WAIT_FOR_SCENE_3_END: if (cutscene_mode_macro == 2) { break; } queue_scene_movie_with_game_language(3); - moby->state = 7; + moby->state = AGNOGG_SHIP_WAIT_TO_START_SCENE_4; break; case AGNOGG_SHIP_WAIT_TO_START_SCENE_4: if (cutscene_mode_macro == 2) { break; } start_scene(4); - moby->state = 8; + moby->state = AGNOGG_SHIP_WAIT_FOR_SCENE_4_END; break; case AGNOGG_SHIP_WAIT_FOR_SCENE_4_END: if (cutscene_mode_macro == 2) { @@ -354,7 +354,7 @@ void agnogg_ship_front_update(Moby_2FC140 *moby) { } memcard_save_data(0, -1); show_tracked_moby(); - moby->state = 10; + moby->state = AGNOGG_SHIP_HOLD_TARGET_HEIGHT; break; case AGNOGG_SHIP_HOLD_TARGET_HEIGHT: moby->pos.z = data->fC; From d932a327811a6d77a94a25bddf1d04d704a1cf9e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:41:40 +0000 Subject: [PATCH 0998/1502] decomp: clarify names in scenery_ship_update domain_0_value_1 -> SCENERY_SHIP_FOLLOW_PATH: Authoritative source SHA-256 49e5c548d4175a3d6376e4e016739ed4d0ac22e449fc71a426ecc02f5d4f8d42 assigns MOBY(moby)->state = 1 after path initialization. Retail 0x002d7430 loads 1 and 0x002d7434 stores it to 0x20(s4), the identical byte loaded at 0x002d71a4 and compared with 1 at 0x002d71a8-0x002d71ac to enter 0x002d7450. That branch invokes advance_scenery_ship_along_path at 0x002d74bc and maintains trails. Original Ghidra confirms both the byte assignment and dispatch. Thus reuse the existing local enum SCENERY_SHIP_FOLLOW_PATH = 1 from this same selector domain. domain_1_value_2 -> SCENERY_SHIP_SPAWN_EFFECTS_AND_REMOVE: Source assigns MOBY(moby)->state = 2 when damaged during FOLLOW_PATH. Retail 0x002d76f0-0x002d7710 checks a non-null hit with positive float at hit+0x2C; 0x002d7718 loads 2 and 0x002d7720 stores it to 0x20(s4). The same state byte loaded at 0x002d71a4 is compared with 2 at 0x002d71b8/0x002d71cc, selecting 0x002d7724. This branch spawns class 0x72E at 0x002d77b8, 0x002d77f4 and 0x002d7830, then marks the moby for removal at 0x002d7838. Original Ghidra agrees. Reuse existing local enum SCENERY_SHIP_SPAWN_EFFECTS_AND_REMOVE = 2 in this exact state domain. --- src/overlays/l05/mobys/scenery_ship.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l05/mobys/scenery_ship.c b/src/overlays/l05/mobys/scenery_ship.c index e3405c14a5..864c1cf075 100644 --- a/src/overlays/l05/mobys/scenery_ship.c +++ b/src/overlays/l05/mobys/scenery_ship.c @@ -242,7 +242,7 @@ void scenery_ship_update(char *moby) { } scenery_ship_instance_vars->fC = fast_vec_dist((float *)(path + 0x10), (float *)(path + 0x20)); - MOBY(moby)->state = 1; + MOBY(moby)->state = SCENERY_SHIP_FOLLOW_PATH; scenery_ship_instance_vars->f8 = (float)*(int *)path * scenery_ship_instance_vars->f4; break; } @@ -307,7 +307,7 @@ void scenery_ship_update(char *moby) { if (hit != 0 && 0.0f < *(float *)(hit + 0x2C)) damaged = 1; if (damaged) - MOBY(moby)->state = 2; + MOBY(moby)->state = SCENERY_SHIP_SPAWN_EFFECTS_AND_REMOVE; break; } case SCENERY_SHIP_SPAWN_EFFECTS_AND_REMOVE: { From 0aeaad1f8cefd1d2c6f212b4b687555de5609c25 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:41:40 +0000 Subject: [PATCH 0999/1502] decomp: clarify names in _getAllRefs domain_0_value_2 -> MPEG_PICTURE_CODING_PREDICTIVE: At 0x001257ac-0x001257b4 decoder+0x150 (picture_coding_type) equals 2 to require forward prediction even without mb_type bit 3. At 0x001259f0-0x00125a1c the same coding type permits second-field forward reference selection. This identifies the predictive (P) picture coding domain, separately from motion_type. domain_1_value_2 -> MPEG_MOTION_FRAME: Incoming motion_type is preserved in s4 at 0x00125768. Under picture_structure==3 at 0x001257bc-0x001257c4, the comparison at 0x001257cc-0x001257d0 selects a single 16-row _getRef0 prediction with fieldpred=0 and unhalved pmv dy (0x001257e4-0x00125814): frame motion compensation. domain_2_value_3 -> MPEG_MOTION_DUAL_PRIME: In the frame-picture forward path, 0x001258a4 compares s4 against the retained picture_structure value 3. Its branch calls _dualPrimeVector at 0x001258c0, then uses original and derived vectors for both destination fields, averaging the cross-field predictions at 0x00125938 and 0x001259ac. This proves dual-prime motion rather than a generic mode number. domain_3_value_1 -> MPEG_MOTION_FIELD: In the non-frame picture path 0x00125a20-0x00125a24 compares motion_type to 1. The selected reference comes from refs[same][mvfs[0][0]] at 0x00125a38-0x00125a5c, and one 16-row prediction covers the current field with its supplied field motion vector. This is field prediction, distinct from the two-part mode 2 branch. domain_4_value_2 -> MPEG_MOTION_16X8: For a field picture, comparison 0x00125a74 selects two _getRef0 calls: first height 8 at yofs 0 (0x00125ab8-0x00125ac8), then height 8 at yofs 8 (0x00125b20-0x00125b3c), with independent pmv[0][0] and pmv[1][0] and mvfs selectors. Thus motion_type 2 here means two 16-by-8 partitions, not frame prediction. domain_5_value_3 -> MPEG_MOTION_DUAL_PRIME: Field-picture comparison 0x00125b44 uses motion_type 3 to call _dualPrimeVector at 0x00125b68. The original vector predicts from refs[0][currentfield]; the derived stack vector at sp+0x20/+0x24 predicts from the opposite field and is averaged via stack argument 1 at 0x00125be4. This is the same dual-prime motion mode as in frame pictures. domain_6_value_2 -> MPEG_MOTION_FRAME: Backward prediction is gated by mb_type bit 2 at 0x00125c28. Within picture_structure==3, comparison 0x00125c40-0x00125c44 selects ref_images[1] and one 16-row prediction with fieldpred=0, unhalved pmv[0][1] (0x00125c4c-0x00125c80). This repeats the forward frame-motion meaning of motion_type 2. domain_7_value_1 -> MPEG_MOTION_FIELD: For backward prediction in a field picture, 0x00125d0c compares motion_type to 1. mvfs[0][1] chooses decoder+0x1cc or +0x1dc at 0x00125d14-0x00125d20, then a single 16-row _getRef0 call at 0x00125d54 uses pmv[0][1]. This repeats the forward single-field prediction mode. domain_8_value_2 -> MPEG_MOTION_16X8: Backward field-picture comparison 0x00125d64 selects two predictions using pmv[0][1] and pmv[1][1], with independently selected source fields. The calls at 0x00125dac and 0x00125df4 each have height 8; the second has yofs=8 at 0x00125df0. This proves the same two 16-by-8 partitions as forward field motion_type 2. --- src/sdk/mpeg/ref_images/_getAllRefs.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/sdk/mpeg/ref_images/_getAllRefs.c b/src/sdk/mpeg/ref_images/_getAllRefs.c index 1e4044d5db..9d15affb6d 100644 --- a/src/sdk/mpeg/ref_images/_getAllRefs.c +++ b/src/sdk/mpeg/ref_images/_getAllRefs.c @@ -23,6 +23,13 @@ void _getAllRefs(struct MpegDecoder *decoder, int mvfs[2][2], int *dmvector) { + enum { + MPEG_MOTION_FIELD = 1, + MPEG_PICTURE_CODING_PREDICTIVE = 2, + MPEG_MOTION_FRAME = 2, + MPEG_MOTION_16X8 = 2, + MPEG_MOTION_DUAL_PRIME = 3 + }; int dmv[2][2]; struct MpegRefImage *refs[2][2]; int one = 1; @@ -34,9 +41,9 @@ void _getAllRefs(struct MpegDecoder *decoder, decoder->mb_buf[decoder->mb_buf_index].fetch_count = 0; - if ((mb_type & 8) || decoder->picture_coding_type == 2) { + if ((mb_type & 8) || decoder->picture_coding_type == MPEG_PICTURE_CODING_PREDICTIVE) { if (decoder->picture_structure == 3) { - if (motion_type == 2 || !(mb_type & 8)) { + if (motion_type == MPEG_MOTION_FRAME || !(mb_type & 8)) { _getRef0(decoder, decoder->ref_images[0], 0, @@ -74,7 +81,7 @@ void _getAllRefs(struct MpegDecoder *decoder, pmv[1][0][1] >> 1, same, 0); - } else if (motion_type == 3) { + } else if (motion_type == MPEG_MOTION_DUAL_PRIME) { _dualPrimeVector(decoder, dmv, dmvector, pmv[0][0][0], pmv[0][0][1] >> 1); _getRef0(decoder, decoder->ref_images[0], @@ -139,7 +146,7 @@ void _getAllRefs(struct MpegDecoder *decoder, if (decoder->picture_coding_type == one && decoder->second_field) { same = currentfield != mvfs[0][0]; } - if (motion_type == 1 || !(mb_type & 8)) { + if (motion_type == MPEG_MOTION_FIELD || !(mb_type & 8)) { _getRef0(decoder, refs[same][mvfs[0][0]], 0, @@ -152,7 +159,7 @@ void _getAllRefs(struct MpegDecoder *decoder, pmv[0][0][1], 0, 0); - } else if (motion_type == 2) { + } else if (motion_type == MPEG_MOTION_16X8) { _getRef0(decoder, refs[same][mvfs[0][0]], 0, @@ -179,7 +186,7 @@ void _getAllRefs(struct MpegDecoder *decoder, pmv[1][0][1], 0, 0); - } else if (motion_type == 3) { + } else if (motion_type == MPEG_MOTION_DUAL_PRIME) { same = decoder->second_field ? motion_type - 2 : 0; _dualPrimeVector(decoder, dmv, dmvector, pmv[0][0][0], pmv[0][0][1]); _getRef0(decoder, @@ -216,7 +223,7 @@ void _getAllRefs(struct MpegDecoder *decoder, if (mb_type & 4) { if (decoder->picture_structure == 3) { same = 1; - if (motion_type == 2) { + if (motion_type == MPEG_MOTION_FRAME) { _getRef0(decoder, decoder->ref_images[1], 0, @@ -255,7 +262,7 @@ void _getAllRefs(struct MpegDecoder *decoder, same, avg); } - } else if (motion_type == 1) { + } else if (motion_type == MPEG_MOTION_FIELD) { _getRef0(decoder, mvfs[0][1] ? decoder->ref_images[9] : decoder->ref_images[5], 0, @@ -268,7 +275,7 @@ void _getAllRefs(struct MpegDecoder *decoder, pmv[0][1][1], 0, avg); - } else if (motion_type == 2) { + } else if (motion_type == MPEG_MOTION_16X8) { _getRef0(decoder, mvfs[0][1] ? decoder->ref_images[9] : decoder->ref_images[5], 0, From 4f4971ab6d195acc037b8bddd28239f6d90546dd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:43:40 +0000 Subject: [PATCH 1000/1502] decomp: clarify names in rocket_strike_fighter_update domain_0_value_0 -> ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE: Retail 0x002fcbe0-0x002fcbe8 loads the updated moby's state byte at s1+0x20 and gates save-bit checks on zero. The same byte is dispatched at 0x002fcd80-0x002fcd98 into the source's existing INITIALIZE case, which validates the flight path and initializes motion. domain_10_value_1 -> ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS: Retail 0x002fd2ac-0x002fd2b0 compares the same s1+0x20 fighter state byte with 1 before voice maintenance. Value 1 dispatches at 0x002fcd88 to the three-mission and visibility gate at 0x002fcecc, already named WAIT_FOR_MISSIONS in this function's local enum. domain_1_value_3 -> ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN: Retail 0x002fcc94-0x002fcc9c compares s1+0x20 with 3 to prevent a qualifying hit from reentering the state. That exact state byte dispatches value 3 at 0x002fcdb0 to the timer-expiry/reset handler 0x002fd1f4, already named WAIT_FOR_RESPAWN in the source. domain_2_value_3 -> ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN: Retail 0x002fcd00-0x002fcd38 stores 3 to the fighter's state at s1+0x20 after a hit, produces the burst, and disables collision. Dispatch of this same byte at 0x002fcdb0 selects the existing WAIT_FOR_RESPAWN case, which waits on pvars+0x7c before restoring motion. domain_3_value_1 -> ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS: Retail 0x002fce50-0x002fce70 stores s6=1 into s1+0x20 when the fighter has a linked rocket, hiding collision during initialization. The same state byte dispatches 1 at 0x002fcd88 to 0x002fcecc, the source's WAIT_FOR_MISSIONS case checking three mission bytes and target visibility. domain_4_value_2 -> ROCKET_STRIKE_FIGHTER_STATE_FOLLOW_PATH: Retail 0x002fce9c-0x002fcea8 stores 2 to s1+0x20 in the initialization branch without a linked rocket. Dispatch of the same byte at 0x002fcda8 reaches 0x002fd108, which calls advance_rocket_strike_fighter_along_flight_path, matching the existing FOLLOW_PATH enum member. domain_6_value_2 -> ROCKET_STRIKE_FIGHTER_STATE_FOLLOW_PATH: Retail 0x002fd094-0x002fd0f4 loads 2 and stores it at s1+0x20 after mission/visibility checks, save-bit writes and collision restoration, then activates the flythrough. The same byte's value 2 selects the existing FOLLOW_PATH case and flight-path helper at 0x002fd108. domain_7_value_2 -> ROCKET_STRIKE_FIGHTER_STATE_FOLLOW_PATH: Retail 0x002fd1f4-0x002fd254 waits for the respawn timer, restores collision, reloads the timer, stores s3=2 at s1+0x20, zeros path progress and restores the first path position. This is the same fighter state byte whose value 2 dispatches to the existing FOLLOW_PATH case. domain_8_value_0 -> ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE: Retail 0x002fd29c-0x002fd2a0 reloads s1+0x20 and skips voice maintenance when it is zero. This is the same fighter state byte dispatched at 0x002fcd98 into path validation/initialization, already represented by ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE in the authoritative source. domain_9_value_3 -> ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN: Retail 0x002fd2a4-0x002fd2a8 compares the reloaded fighter state byte with 3 and skips voice maintenance. The same byte's value 3 dispatches at 0x002fcdb0 to timer expiry and motion reset, the authoritative source's existing WAIT_FOR_RESPAWN case. --- src/overlays/l14/mobys/rocket_strike_fighter.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l14/mobys/rocket_strike_fighter.c b/src/overlays/l14/mobys/rocket_strike_fighter.c index 2f6bb81603..ceca3bca61 100644 --- a/src/overlays/l14/mobys/rocket_strike_fighter.c +++ b/src/overlays/l14/mobys/rocket_strike_fighter.c @@ -94,7 +94,7 @@ void rocket_strike_fighter_update(struct Moby *moby) { Vec4 target_view_point_or_rocket_offset; Vec4 rocket_position; - if (moby->state == 0) { + if (moby->state == ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE) { u16 id = moby->save_id; if (D_L14_001BB930.cleared[(short)id] != 0 || (D_0014C190_257218[current_level_index][(short)id >> 5] >> (id & 0x1F)) & 1) { @@ -106,7 +106,7 @@ void rocket_strike_fighter_update(struct Moby *moby) { { void *hit = find_moby_hit(moby, 0x800000, 0); moby->hit_slot = 0xFF; - if (hit != 0 && moby_vars->rocket == -1 && moby->state != 3) { + if (hit != 0 && moby_vars->rocket == -1 && moby->state != ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN) { if (current_level_index == 14) { enemy_fighter_destruction_count = enemy_fighter_destruction_count + 1; if (enemy_fighter_destruction_count >= 3 && item_unlocked[0x18] == 0) { @@ -115,7 +115,7 @@ void rocket_strike_fighter_update(struct Moby *moby) { queue_dialogue_message(0x53D6, -1); } } - moby->state = 3; + moby->state = ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN; FUN_L00_0025f090(moby, &moby->pos, -1, 5.0f, 13.0f); moby->collision = 0; moby->flags |= 0x41; @@ -146,7 +146,7 @@ void rocket_strike_fighter_update(struct Moby *moby) { initialize_flight_path_state(moby); if (moby_vars->rocket != 0) { struct Moby *c; - moby->state = 1; + moby->state = ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS; moby->update_dist = 0xFF; moby->flags |= 0x41; moby->collision = 0; @@ -154,7 +154,7 @@ void rocket_strike_fighter_update(struct Moby *moby) { c->flags |= 0x41; moby_vars->stage = 0; } else { - moby->state = 2; + moby->state = ROCKET_STRIKE_FIGHTER_STATE_FOLLOW_PATH; moby->update_dist = 0x80; } moby->draw_dist = 0x80; @@ -198,7 +198,7 @@ void rocket_strike_fighter_update(struct Moby *moby) { moby->flags &= 0xFFBE; moby->collision = moby->pclass->collision; rocket->flags &= 0xFFBE; - moby->state = 2; + moby->state = ROCKET_STRIKE_FIGHTER_STATE_FOLLOW_PATH; activate_descriptor(moby_vars->flythrough); target->draw_dist = 0xFF; target->update_dist = 0xFF; @@ -234,7 +234,7 @@ void rocket_strike_fighter_update(struct Moby *moby) { moby->flags &= 0xFFBE; moby->collision = moby->pclass->collision; moby_vars->timer = scale_game_frames(rocket_strike_fighter_respawn_delay_frames_gp); - moby->state = 2; + moby->state = ROCKET_STRIKE_FIGHTER_STATE_FOLLOW_PATH; moby_vars->segment = 0; moby_vars->along = 0; qcopy(&moby->pos, path + 0x10); @@ -246,7 +246,7 @@ void rocket_strike_fighter_update(struct Moby *moby) { break; } spawn_rocket_strike_fighter_exhaust(moby); - if (moby->state != 0 && moby->state != 3 && moby->state != 1 && + if (moby->state != ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE && moby->state != ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN && moby->state != ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS && voice_is_playing(moby, moby_vars->sound) == 0) moby_vars->sound = allocate_voice_for_target_entry(0, 4, moby); } From e3852dc007641f00a90fc21ee7bb61baff1b284d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:43:41 +0000 Subject: [PATCH 1001/1502] decomp: clarify names in machinegun_turret_update domain_0_value_3 -> TURRET_STATE_WAIT_FOR_TARGET: Retail 0x002b3cbc-0x002b3ccc writes 3 to moby+0x20 when activation short private+0x88 is nonzero. This is the exact byte switched at 0x002b3c1c; its existing TURRET_STATE_WAIT_FOR_TARGET case queries a target and waking cuboid at 0x002b3e68-0x002b3eac. Reuse this function's established state member. domain_1_value_1 -> TURRET_STATE_WAIT_FOR_ACTIVATION: Retail 0x002b3cd0-0x002b3cf8 writes 1 to moby+0x20, lowers Z and disables collision/flag after initialization without activation. The same state byte selects existing TURRET_STATE_WAIT_FOR_ACTIVATION, whose private+0x88 activation and +0x98 timer gate deployment at 0x002b3d0c-0x002b3d30. domain_2_value_2 -> TURRET_STATE_DEPLOY: Retail 0x002b3d0c-0x002b3d30 checks activation and timer, then writes 2 into moby+0x20, the outer switch selector. Existing TURRET_STATE_DEPLOY handles that value: saved-height interpolation at 0x002b3d80-0x002b3dc0 restores elevated position and collision before waiting for a target. domain_3_value_3 -> TURRET_STATE_WAIT_FOR_TARGET: After deployment countdown completes, retail 0x002b3e28-0x002b3e64 resets target-wait timeout, writes 3 to the switched moby+0x20 byte, restores saved Z and clears aiming phase. The existing TURRET_STATE_WAIT_FOR_TARGET case for this exact selector performs target selection at 0x002b3e74. domain_4_value_2 -> MOBY_SELECTION_NO_TARGET: Retail 0x002b3e74-0x002b3e80 compares the direct return of select_moby_by_xy_distance (0x00268038) with 2 before using its output position. Checked helper request 35ff17dd38ad4bc388c1fd0b2b3c3448 shows 0x002680a0-0x002680a4 clearing selected s1 and setting status s5=2; candidate selection replaces status with 1, and absent-target branch 0x00268264-0x00268280 clears pointer/vectors and returns s5. Supplied helper source names this exact domain MOBY_SELECTION_NO_TARGET. domain_5_value_4 -> TURRET_STATE_AIM_AND_FIRE: Retail 0x002b3e88-0x002b3eac accepts a selected point inside private+0x90 waking cuboid and writes 4 to moby+0x20. This is the exact outer switch state byte, whose existing TURRET_STATE_AIM_AND_FIRE case computes heading at 0x002b3ef0-0x002b3fa8 and periodically spawns flying bolts at 0x002b3fac-0x002b410c. domain_6_value_2 -> MOBY_SELECTION_NO_TARGET: Retail 0x002b4120-0x002b4148 compares the direct return from target selector 0x00268038 to 2, setting the target-missing predicate without reading its point when equal. Checked helper request 35ff17dd38ad4bc388c1fd0b2b3c3448 proves status s5=2 accompanies null selected pointer (0x002680a0-0x002680a4), survives only without successful candidate replacement, clears outputs at 0x00268264-0x0026827c and returns at 0x00268280. Reuse supplied helper's MOBY_SELECTION_NO_TARGET domain member, separate from turret state 2. domain_7_value_1 -> TURRET_STATE_WAIT_FOR_ACTIVATION: Retail retraction completion 0x002b4258-0x002b42ac writes 1 to switched moby+0x20 at 0x002b4270, restores heading, clears activation private+0x88, resets delay and lowers Z. This returns to the existing TURRET_STATE_WAIT_FOR_ACTIVATION case, which waits on that activation and delay at 0x002b3d0c-0x002b3d20. --- src/overlays/l14/mobys/machinegun_turret.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/l14/mobys/machinegun_turret.c b/src/overlays/l14/mobys/machinegun_turret.c index 0ce4da0f11..fef577a920 100644 --- a/src/overlays/l14/mobys/machinegun_turret.c +++ b/src/overlays/l14/mobys/machinegun_turret.c @@ -231,7 +231,7 @@ void machinegun_turret_update(char *moby) { enum { TURRET_SPAWN_CENTER = 0, TURRET_SPAWN_UNNEGATED_OFFSET = 1 - }; + } ; enum { MOBY_SELECTION_NO_TARGET = 2}; MachinegunTurretVars *machinegun_turret_private_vars; float target_point_scratch[4]; float spawn_position[4]; @@ -270,10 +270,10 @@ void machinegun_turret_update(char *moby) { machinegun_turret_private_vars->unk76 = scaled_wait_frames_or_target_query_status; machinegun_turret_private_vars->unk8B = 0; if (machinegun_turret_private_vars->unk88 != 0) { - MOBY(moby)->state = 3; + MOBY(moby)->state = TURRET_STATE_WAIT_FOR_TARGET; machinegun_turret_private_vars->unk8A = 1; } else { - MOBY(moby)->state = 1; + MOBY(moby)->state = TURRET_STATE_WAIT_FOR_ACTIVATION; MOBY(moby)->pos.z = MOBY(moby)->pos.z - machinegun_turret_retraction_depth_gp; MOBY(moby)->collision = 0; machinegun_turret_private_vars->unk8A = 0; @@ -289,7 +289,7 @@ void machinegun_turret_update(char *moby) { if (fast_dec_timer(&machinegun_turret_private_vars->timer) == 0) { return; } - MOBY(moby)->state = 2; + MOBY(moby)->state = TURRET_STATE_DEPLOY; machinegun_turret_private_vars->unk74 = func_001F9850_2B4E40(D_L14_0016150C); machinegun_turret_private_vars->unk78 = 1.0f / func_001FA888_2B4E40(machinegun_turret_private_vars->unk74); @@ -318,7 +318,7 @@ void machinegun_turret_update(char *moby) { } machinegun_turret_private_vars->unk76 = func_001F9850_2B4E40(machinegun_turret_target_wait_timeout_frames_gp); - MOBY(moby)->state = 3; + MOBY(moby)->state = TURRET_STATE_WAIT_FOR_TARGET; machinegun_turret_private_vars->unk74 = func_001F9850_2B4E40(60); MOBY(moby)->pos.z = machinegun_turret_private_vars->base_z; *(int *)&machinegun_turret_private_vars->unk8C = 0; @@ -326,10 +326,10 @@ void machinegun_turret_update(char *moby) { case TURRET_STATE_WAIT_FOR_TARGET: scaled_wait_frames_or_target_query_status = select_moby_by_xy_distance(moby, (char *)target_point_scratch, 34.0f); - if (scaled_wait_frames_or_target_query_status != 2) { + if (scaled_wait_frames_or_target_query_status != MOBY_SELECTION_NO_TARGET) { if (is_point_inside_clip_volume(target_point_scratch, machinegun_turret_private_vars->unk90) != 0) { - MOBY(moby)->state = 4; + MOBY(moby)->state = TURRET_STATE_AIM_AND_FIRE; set_moby_animation(moby, 3, 0); machinegun_turret_private_vars->unk74 = func_001F9850_2B4E40(120); machinegun_turret_private_vars->timer_9C = func_001F9850_2B4E40(20); @@ -419,7 +419,7 @@ void machinegun_turret_update(char *moby) { scaled_wait_frames_or_target_query_status = select_moby_by_xy_distance(moby, (char *)target_query_result, 34.0f); target_missing_or_outside_waking_cuboid = - (scaled_wait_frames_or_target_query_status == 2 || + (scaled_wait_frames_or_target_query_status == MOBY_SELECTION_NO_TARGET || is_point_inside_clip_volume(target_query_result, machinegun_turret_private_vars->unk90) == 0); if (target_missing_or_outside_waking_cuboid == 0) { @@ -464,7 +464,7 @@ void machinegun_turret_update(char *moby) { return; } MOBY(moby)->rot.z = machinegun_turret_private_vars->unk84; - MOBY(moby)->state = 1; + MOBY(moby)->state = TURRET_STATE_WAIT_FOR_ACTIVATION; machinegun_turret_private_vars->unk74 = func_001F9850_2B4E40(60); machinegun_turret_private_vars->unk88 = 0; machinegun_turret_private_vars->timer = From f7bc55d247aa90ce7aff1d7093d7ffc1bd7a444c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:43:41 +0000 Subject: [PATCH 1002/1502] decomp: clarify names in update_preview_animation_and_attachments domain_0_value_0 -> CD_READ_STATE_IDLE: Retail 0x00225f1c-0x00225f24 loads the halfword at 0x001516d0+8 and skips pending-buffer decompression when nonzero; zero reaches decompress_wad at 0x00225f4c and publication of the loaded animation. The bound current source identifies this exact field as music_stream_state.read_state. Supplied start_audio_stream_read source tests the same field against CD_READ_STATE_IDLE=0 before starting a read and sets CD_READ_STATE_ACTIVE=1 after success, proving the CD-read idle domain. domain_1_value_0 -> CD_READ_STATE_IDLE: Retail 0x00225fb4-0x00225fbc loads the same halfword at 0x001516d0+8 and branches away from starting an animation stream when nonzero. With zero and an uncached request, 0x00226078 calls start_audio_stream_read. The bound current source identifies this selector as music_stream_state.read_state; supplied start_audio_stream_read uses CD_READ_STATE_IDLE=0 on that same field and sets ACTIVE=1 after read acceptance, proving this is the same idle CD-read state. --- .../update_preview_animation_and_attachments.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ui/menus/item_preview/update_preview_animation_and_attachments.c b/src/ui/menus/item_preview/update_preview_animation_and_attachments.c index 211bd619be..78738298d5 100644 --- a/src/ui/menus/item_preview/update_preview_animation_and_attachments.c +++ b/src/ui/menus/item_preview/update_preview_animation_and_attachments.c @@ -79,6 +79,9 @@ s32 update_preview_animation_and_attachments(Moby *source_moby, Moby **attachment1, Moby **attachment2) { + enum { + CD_READ_STATE_IDLE = 0 + }; s32 animation_complete; s32 delay_expired; s32 activate_request; @@ -96,7 +99,7 @@ s32 update_preview_animation_and_attachments(Moby *source_moby, delay_expired = 1; } } - if (menu_system.pending_buffer != 0 && music_stream_state.read_state == 0) { + if (menu_system.pending_buffer != 0 && music_stream_state.read_state == CD_READ_STATE_IDLE) { s32 buffer_index = menu_system.pending_buffer - 1; s32 *buffer_slot = &menu_system.stream_buffer[buffer_index]; s32 buffer_address = *buffer_slot; @@ -112,7 +115,7 @@ s32 update_preview_animation_and_attachments(Moby *source_moby, preview_animation_requests[0].animation_id); menu_system.pending_buffer = 0; } - if (menu_system.pending_buffer == 0 && music_stream_state.read_state == 0 && + if (menu_system.pending_buffer == 0 && music_stream_state.read_state == CD_READ_STATE_IDLE && preview_request_count > 0) { if (preview_animation_requests[0].status == 0) { u32 animation_id = preview_animation_requests[0].animation_id; From 295db2d92f82b20a1aea3c3b49c549844782850d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:43:41 +0000 Subject: [PATCH 1003/1502] decomp: clarify names in update_rail_taxi domain_0_value_1 -> TAXI_WAIT_FOR_ROUTE_TRIGGER: Initialization stores 1 to Moby+0x20 at 0x002d3450-0x002d3458, the exact byte read by the switch at 0x002d33b4. Its existing case TAXI_WAIT_FOR_ROUTE_TRIGGER scans five route volumes at 0x002d34c4-0x002d35bc; reuse this local taxi enum member. domain_1_value_2 -> TAXI_FOLLOW_OUTBOUND_PATH: After a route trigger selects command and positions the taxi, 0x002d357c-0x002d3584 stores 2 to the switched Moby+0x20. The existing TAXI_FOLLOW_OUTBOUND_PATH case loads the selected outbound array at pvars+0x94 and calls rail advancement at 0x002d35c8-0x002d35e8. domain_2_value_3 -> TAXI_WAIT_FOR_RETURN_REQUEST: Outbound path absence or completion at 0x002d35dc-0x002d35ec reaches the store of 3 to Moby+0x20 at 0x002d35f4-0x002d35f8. Existing case TAXI_WAIT_FOR_RETURN_REQUEST levels the taxi and tests the grounded rider, route help and request conditions at 0x002d3690-0x002d36d4. domain_3_value_4 -> TAXI_WAIT_FOR_RETURN_DEPARTURE: Return-request branch calls target-pose setup at 0x002d36e0, loads 4 at 0x002d36ec and stores it to switched Moby+0x20 at 0x002d3824. Existing TAXI_WAIT_FOR_RETURN_DEPARTURE case polls pose status at 0x002d36f0 and enters return travel only when zero. domain_4_value_5 -> TAXI_FOLLOW_RETURN_PATH: The departure wait polls 0x00223708 at 0x002d36f0 and stores 5 to switched Moby+0x20 at 0x002d3704 when zero. Existing TAXI_FOLLOW_RETURN_PATH case advances the selected return array pvars+0xA8 at 0x002d3728-0x002d3740, proving the same taxi state domain. domain_5_value_6 -> TAXI_WAIT_FOR_HERO_TO_MOVE_AWAY: Return-rail completion at 0x002d3744-0x002d3750 stores 6 to switched Moby+0x20. Existing TAXI_WAIT_FOR_HERO_TO_MOVE_AWAY case levels pitch/roll then tests taxi-to-hero distance before choosing onward travel or trigger waiting at 0x002d37e4-0x002d3874. domain_6_value_7 -> TAXI_FOLLOW_ONWARD_PATH: With selected onward path present and hero distance greater than 15, 0x002d381c-0x002d382c stores 7 to switched Moby+0x20 and resets path index. Existing TAXI_FOLLOW_ONWARD_PATH case advances pvars+0xBC selected onward path at 0x002d3878-0x002d3890. domain_7_value_1 -> TAXI_WAIT_FOR_ROUTE_TRIGGER: When no onward path exists and horizontal hero distance exceeds 5, 0x002d386c-0x002d3874 stores 1 to Moby+0x20. This is the byte switched at 0x002d33b4; existing TAXI_WAIT_FOR_ROUTE_TRIGGER case resumes the active five-route trigger scan at 0x002d34c4. domain_8_value_1 -> TAXI_WAIT_FOR_ROUTE_TRIGGER: On onward-path completion, 0x002d3894-0x002d38a4 stores 1 to switched Moby+0x20 while clearing draw distance and collision. Existing local TAXI_WAIT_FOR_ROUTE_TRIGGER case handles the next route trigger scan at 0x002d34c4-0x002d35bc; reuse its canonical member. --- src/overlays/l03/mobys/taxi.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/l03/mobys/taxi.c b/src/overlays/l03/mobys/taxi.c index 1ba6184e1e..352d021c02 100644 --- a/src/overlays/l03/mobys/taxi.c +++ b/src/overlays/l03/mobys/taxi.c @@ -155,7 +155,7 @@ void rail_taxi_update(struct Moby *taxi_moby) { taxi_moby->draw_dist = 0; taxi_moby->update_dist = 0xFF; taxi_vars->route = -1; - taxi_moby->state = 1; + taxi_moby->state = TAXI_WAIT_FOR_ROUTE_TRIGGER; taxi_moby->collision = 0; if (l03_save_state.cleared[(s16)taxi_moby->save_id] != 0 || (D_0014C190_257218[current_level_index][(s16)taxi_moby->save_id >> 5] >> @@ -186,7 +186,7 @@ void rail_taxi_update(struct Moby *taxi_moby) { route_path->points[1].f[1] - taxi_moby->pos.y); } taxi_moby->command = route_index; - taxi_moby->state = 2; + taxi_moby->state = TAXI_FOLLOW_OUTBOUND_PATH; taxi_moby->draw_dist = 0x80; taxi_vars->idx = 1; taxi_vars->speed = rail_flyer_max_speed_gp * frame_time; @@ -199,7 +199,7 @@ void rail_taxi_update(struct Moby *taxi_moby) { if (taxi_vars->out[taxi_moby->command] == -1 || advance_moby_along_rail_path( taxi_moby, taxi_vars->out[taxi_moby->command], &taxi_vars->snd)) { - taxi_moby->state = 3; + taxi_moby->state = TAXI_WAIT_FOR_RETURN_REQUEST; taxi_vars->unkE4 = -1; } break; @@ -220,14 +220,14 @@ void rail_taxi_update(struct Moby *taxi_moby) { request_taxi_return_help_message(taxi_moby, taxi_vars->help[taxi_moby->command]); if ((((u32)pad_pressed_lui) & 0x10) && D_L03_0015F594 == 8) { request_hero_target_pose(&taxi_moby->pos, taxi_moby->rot.z, 0); - taxi_moby->state = 4; + taxi_moby->state = TAXI_WAIT_FOR_RETURN_DEPARTURE; taxi_vars->idx = 1; } } break; case TAXI_WAIT_FOR_RETURN_DEPARTURE: if (!get_hero_target_pose_status()) { - taxi_moby->state = 5; + taxi_moby->state = TAXI_FOLLOW_RETURN_PATH; } break; case TAXI_FOLLOW_RETURN_PATH: @@ -237,7 +237,7 @@ void rail_taxi_update(struct Moby *taxi_moby) { } if (advance_moby_along_rail_path( taxi_moby, taxi_vars->back[taxi_moby->command], &taxi_vars->snd)) { - taxi_moby->state = 6; + taxi_moby->state = TAXI_WAIT_FOR_HERO_TO_MOVE_AWAY; } break; case TAXI_WAIT_FOR_HERO_TO_MOVE_AWAY: @@ -255,18 +255,18 @@ void rail_taxi_update(struct Moby *taxi_moby) { frame_time * 12.566371f); if (taxi_vars->onward[taxi_moby->command] != -1 && fast_vec_dist(&taxi_moby->pos, &hero.motion.pos) > 15.0f) { - taxi_moby->state = 7; + taxi_moby->state = TAXI_FOLLOW_ONWARD_PATH; taxi_vars->idx = 1; } else if (taxi_vars->onward[taxi_moby->command] == -1 && vector_distance_xy(&taxi_moby->pos, &hero.motion.pos) > 5.0f) { - taxi_moby->state = 1; + taxi_moby->state = TAXI_WAIT_FOR_ROUTE_TRIGGER; } break; case TAXI_FOLLOW_ONWARD_PATH: if (advance_moby_along_rail_path( taxi_moby, taxi_vars->onward[taxi_moby->command], &taxi_vars->snd)) { taxi_moby->draw_dist = 0; - taxi_moby->state = 1; + taxi_moby->state = TAXI_WAIT_FOR_ROUTE_TRIGGER; taxi_moby->collision = 0; } break; From abad91526e243b5c11326c5c6065da5fd2b4f5e2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:43:41 +0000 Subject: [PATCH 1004/1502] decomp: clarify names in handle_extermibot_hits_and_update_targeting domain_0_value_1 -> EXTERMIBOT_HIT_STATUS_SKIP_RESPONSE: Retail 0x003034dc passes sp+0x20 as fifth output to 0x00284730; 0x003034f4-0x003034fc tests that status against 1 and skips damage subtraction and response dispatch. Checked helper retains that pointer in s3 at 0x00284740, writes 1 and zero output damage on absent-hit path 0x00284840-0x00284878, and also writes 1 while clearing hit damage at 0x00284c04-0x00284c10 when damage-enable flags are absent. This is the skip-response status, distinct from returned EXTERMIBOT_HIT_LETHAL=1. domain_1_value_14 -> EXTERMIBOT_DEATH_KNOCKBACK: Retail 0x00303504-0x0030350c reads the recipient moby's state byte at s3+0x20 and skips further hit processing when it equals 14. The same state byte is assigned 14 after death knockback at 0x00303714-0x0030371c. Authoritative source extermibot_update calls this handler before switching on moby[0x20], whose established EXTERMIBOT_DEATH_KNOCKBACK=14 branch steps motion, emits death debris and removes the moby. This proves the same current-state domain. domain_2_value_11 -> EXTERMIBOT_NONLETHAL_KNOCKBACK: Retail 0x00303514-0x00303530 forces lethal response when HP is exhausted; remaining response cases 3-8 enter the branch 0x003035b8, adjust attacker-relative knockback, start animation 5 at 0x00303644 and store 11 to recipient state s3+0x20 at 0x00303654. Authoritative caller extermibot_update dispatches that same byte as EXTERMIBOT_NONLETHAL_KNOCKBACK=11, steps motion and can resume following its target. Reuse its established state name, distinct from response code 11. domain_3_value_14 -> EXTERMIBOT_DEATH_KNOCKBACK: Retail lethal response cases 1/2 branch at 0x00303660 clears flag 0x1000, configures death knockback, adjusts attacker-relative heading and starts animation 6 at 0x0030370c, then stores 14 to recipient state s3+0x20 at 0x0030371c. Authoritative caller extermibot_update invokes this handler then switches on that same byte; its established EXTERMIBOT_DEATH_KNOCKBACK=14 branch steps motion, spawns death debris and removes the moby. Same state domain as the entry guard. --- src/overlays/l05/mobys/extermibot.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/overlays/l05/mobys/extermibot.c b/src/overlays/l05/mobys/extermibot.c index ccbedbf070..d6a4ac11cc 100644 --- a/src/overlays/l05/mobys/extermibot.c +++ b/src/overlays/l05/mobys/extermibot.c @@ -753,6 +753,11 @@ void handle_extermibot_hits_and_update_targeting(Moby *moby) { EXTERMIBOT_HIT_FLASH_ONLY = 10, EXTERMIBOT_HIT_NO_REACTION = 11 }; + enum { + EXTERMIBOT_HIT_STATUS_SKIP_RESPONSE = 1, + EXTERMIBOT_NONLETHAL_KNOCKBACK = 11, + EXTERMIBOT_DEATH_KNOCKBACK = 14 + }; Vec_3047E8 working_vector; Vec_3047E8 hit_test_endpoint; int collision_hit_status; @@ -791,7 +796,7 @@ void handle_extermibot_hits_and_update_targeting(Moby *moby) { } hit_response = resolve_moby_hit_response( moby, hit_record, &moby_data->hp, 0, &collision_hit_status, &dmg, 0, 4); - if (collision_hit_status != 1 && moby->state != 14) { + if (collision_hit_status != EXTERMIBOT_HIT_STATUS_SKIP_RESPONSE && moby->state != EXTERMIBOT_DEATH_KNOCKBACK) { moby_data->hp = moby_data->hp - dmg; if (moby_data->hp <= 0.0f) { hit_response = 1; @@ -826,7 +831,7 @@ void handle_extermibot_hits_and_update_targeting(Moby *moby) { trooper_knockback_arc( working_vector, &nonlethal_knockback_heading, &moby_data->f88, &moby_data->f8C); trooper_start_knockback(moby, moby_data->f70, nonlethal_knockback_heading, 5, 1, 0); - moby->state = 11; + moby->state = EXTERMIBOT_NONLETHAL_KNOCKBACK; moby_data->b67 = 0x78; break; case EXTERMIBOT_HIT_LETHAL: @@ -843,7 +848,7 @@ void handle_extermibot_hits_and_update_targeting(Moby *moby) { trooper_knockback_arc( working_vector, &death_knockback_heading, &moby_data->f88, &moby_data->f8C); trooper_start_knockback(moby, moby_data->f70, death_knockback_heading, 6, 1, 0); - moby->state = 14; + moby->state = EXTERMIBOT_DEATH_KNOCKBACK; moby_data->b67 = 0xF0; if (hit_record->who != 0 && *(struct Moby **)&hit_record->who->pclass != 0 && *(short *)((u8 *)((struct Moby *)hit_record->who->pclass) + 0x46) == 5) { From 927b21764cccdc84ab416e128d8f8e47828dd48f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:45:33 +0000 Subject: [PATCH 1005/1502] decomp: clarify names in update_hero_ledge_probe domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0022d094/0022d09c establishes hero base 0x0013f350; 0022d100 lbu v0,0x20a4(v1) and 0022d104 bne v0,zero,0022d1b0 gate probe eligibility on the byte identified as hero.vehicle_mode in the authoritative source (SHA-256 017a9b28528c3d438cd3c2044842cced615409b871d687b233165dc20a3dd09b). Original Ghidra tests the same cRam001413f4 against zero. The supplied enter_hero_vehicle_mode_and_set_moby stores its vehicle_mode argument to this exact +0x20A4 field; exit_hero_vehicle_mode_and_restore_moby clears it and restores the original hero moby. Existing consumers hero_frame_update, update_hero_collision_dimensions and request_hero_idle_state_for_vehicle_mode already use HERO_VEHICLE_MODE_ON_FOOT for the same field/domain. Thus this is HeroVehicleMode's canonical zero member from include/rnc/hero/hero_state.h, independently of numeric equality with state/control/gravity constants. --- src/overlays/shared/hero/hero_frame_update.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index 541f5cc32e..39c26fa9b4 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -458,7 +458,7 @@ void update_hero_ledge_probe(void) { if (hero.ledge_probe_cooldown != 0) return; allowed = 0; - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if ((hero.state.control_mode == 4 && (hero.past_jump_apex != 0 || hero.motion.velocity.f[2] < frame_time * 3.5f)) || hero.state.control_mode == 2 || hero.state.current == 8 || hero.state.current == 0x1A || From 9ade3a76d8b30cdd26262b971222ce20143812db Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:45:34 +0000 Subject: [PATCH 1006/1502] decomp: clarify names in gadgebot_telepot_pad_update domain_0_value_0 -> TELEPOT_PAD_STATE_UNINITIALIZED: In bound gadgebot_telepot_pad_update, retail 0x002be864 preserves the incoming pad moby in s5; 0x002be8a0 loads its state byte at +0x20 and 0x002be8a4 skips setup when nonzero. The zero branch clears the camera-effect countdown at 0x002be8b4, scales both configured frame intervals at 0x002be8ac..0x002be8c4, then stores state 1 at 0x002be8cc. Original Ghidra agrees: state zero denotes this pad's pending initialization. domain_1_value_1 -> TELEPOT_PAD_STATE_INITIALIZED: Retail 0x002be8c8 loads 1 and 0x002be8cc stores it to incoming pad moby s5+0x20 immediately after clearing the countdown and scaling the two camera-effect intervals. On subsequent updates the byte load/branch at 0x002be8a0..0x002be8a4 bypasses that initialization for this nonzero state. Bound C and original Ghidra both show the assignment completing initialization; it belongs to the pad state domain, separate from hero modes. --- src/overlays/l10/mobys/gadgebot_telepot_pad.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/gadgebot_telepot_pad.c b/src/overlays/l10/mobys/gadgebot_telepot_pad.c index 15a6a1ed2e..14c10c5e77 100644 --- a/src/overlays/l10/mobys/gadgebot_telepot_pad.c +++ b/src/overlays/l10/mobys/gadgebot_telepot_pad.c @@ -67,6 +67,10 @@ void gadgebot_telepot_pad_update(char *moby) __asm__("FUN_L10_002be858"); /* Moby classes 351, 1301 */ void gadgebot_telepot_pad_update(char *moby) { + enum { + TELEPOT_PAD_STATE_UNINITIALIZED = 0, + TELEPOT_PAD_STATE_INITIALIZED = 1 + }; int *telepot_pad_vars = ((int *)MOBY(moby)->pvars); float position[4]; float velocity[4]; @@ -76,13 +80,13 @@ void gadgebot_telepot_pad_update(char *moby) { int i; char *hero_bytes; int life; - if (MOBY(moby)->state == 0) { + if (MOBY(moby)->state == TELEPOT_PAD_STATE_UNINITIALIZED) { gadgebot_telepot_camera_effect_remaining_frames = 0; gadgebot_telepot_camera_spring_decay_frames_gp = func_001F9850_2BFBB8(gadgebot_telepot_camera_spring_decay_frames_gp); gadgebot_telepot_camera_effect_duration_frames_gp = func_001F9850_2BFBB8(gadgebot_telepot_camera_effect_duration_frames_gp); - MOBY(moby)->state = 1; + MOBY(moby)->state = TELEPOT_PAD_STATE_INITIALIZED; } hero_bytes = D_0013F350; if ((unsigned char)hero_bytes[0x20A4] == 1 && *telepot_pad_vars != -1 && From e970ff0d0a831b589653fe23c1d400ad6fef3880 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:45:34 +0000 Subject: [PATCH 1007/1502] decomp: clarify names in shuttle_update domain_0_value_1 -> SHUTTLE_STATE_WAIT_FOR_ACTIVATION: Initialization stores 1 to moby state byte +0x20 at 0x002f1a80 (sb a1,0x20(s3)); the same byte is dispatched at 0x002f19a8/0x002f19b0 to the grounded-player and activation-input checks at 0x002f1b34-0x002f1bcc. This is the existing local SHUTTLE_STATE_WAIT_FOR_ACTIVATION=1 domain. domain_1_value_2 -> SHUTTLE_STATE_TRAVEL: After consuming shuttle_vars->go and removing help, 0x002f1be0 loads 2 and 0x002f1be8 stores it to moby +0x20. Dispatch 0x002f19d4 sends that same state byte to 0x002f1ec0, calling update_shuttle_travel_and_camera at 0x002f1ecc. Reuse existing local SHUTTLE_STATE_TRAVEL=2. domain_2_value_3 -> SHUTTLE_STATE_RESET_AFTER_TRAVEL: The nonzero return from update_shuttle_travel_and_camera at 0x002f1ecc passes the completion test 0x002f1ed4; 0x002f1ed8 loads 3 and 0x002f1edc stores it to moby +0x20 before arrival placement. Dispatch 0x002f19dc selects the reset branch at 0x002f2034, matching existing SHUTTLE_STATE_RESET_AFTER_TRAVEL=3. domain_3_value_1 -> SHUTTLE_STATE_WAIT_FOR_ACTIVATION: In the state-3 reset branch, 0x002f203c stores s7=1 (defined at 0x002f19a0) to moby +0x20 while restoring animation sequence 2 and sound bookkeeping at 0x002f2040-0x002f2074. The same byte dispatches state 1 to activation waiting at 0x002f19b0; reuse SHUTTLE_STATE_WAIT_FOR_ACTIVATION. --- src/overlays/l17/mobys/shuttle.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l17/mobys/shuttle.c b/src/overlays/l17/mobys/shuttle.c index 728fc93cd7..3726490b18 100644 --- a/src/overlays/l17/mobys/shuttle.c +++ b/src/overlays/l17/mobys/shuttle.c @@ -142,7 +142,7 @@ void shuttle_update(struct Moby *shuttle_moby) { shuttle_moby->update_dist = 0xFF; shuttle_moby->draw_dist = 0x80; shuttle_moby->spawn_frame = *(long *)(((char *)hero.moby) + 0x38); - shuttle_moby->state = 1; + shuttle_moby->state = SHUTTLE_STATE_WAIT_FOR_ACTIVATION; if (shuttle_moby->prev_seq != 2) { blend_moby_animation(shuttle_moby, 2, 0, 0); } @@ -196,7 +196,7 @@ void shuttle_update(struct Moby *shuttle_moby) { if (shuttle_vars->go != 0) { shuttle_vars->go = 0; remove_help_message_for_selector(10); - shuttle_moby->state = 2; + shuttle_moby->state = SHUTTLE_STATE_TRAVEL; allocate_voice_for_target_entry(2, 0, (int)shuttle_moby); if (shuttle_moby->prev_seq != 0) { blend_moby_animation(shuttle_moby, 0, 0, 0); @@ -247,7 +247,7 @@ void shuttle_update(struct Moby *shuttle_moby) { if (update_shuttle_travel_and_camera(shuttle_moby, shuttle_vars->side)) { int ofs; int base; - shuttle_moby->state = 3; + shuttle_moby->state = SHUTTLE_STATE_RESET_AFTER_TRAVEL; shuttle_vars->wA4 = 0; ofs = shuttle_vars->cam[shuttle_vars->sel] << 7; base = (int)D_L17_001600EC; @@ -271,7 +271,7 @@ void shuttle_update(struct Moby *shuttle_moby) { } break; case SHUTTLE_STATE_RESET_AFTER_TRAVEL: - shuttle_moby->state = 1; + shuttle_moby->state = SHUTTLE_STATE_WAIT_FOR_ACTIVATION; if (shuttle_moby->prev_seq != 2) { blend_moby_animation(shuttle_moby, 2, 0, scale_game_frames(30)); } From 8fb07bedc7b38519abb3ba14477283b75f3bc13a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:45:34 +0000 Subject: [PATCH 1008/1502] decomp: clarify names in update_help_hints domain_0_value_1 -> HINT_DIALOGUE_CHECK_TRIGGERS: Source copies moby->state into hint_dialogue_state and switches on local HINT_DIALOGUE_CHECK_TRIGGERS=1. Retail 0x002ed3c8 loads that same incoming moby byte +0x20; 0x002ed3d4-0x002ed3d8 dispatch value 1 to 0x002ed408, the NPC/volume/hint checks. Initialization at 0x002ed3fc-0x002ed404 writes 1 to the same +0x20 field after setting wait. Thus this assignment enters the already named local trigger-check state. domain_8_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Authoritative source tests hero.moby->seq == 0xC together with hero.vehicle_mode == 2 before setting alternate_item_available byte +0x6F. Retail 0x002ed8c4 establishes hero base 0x0013F350; 0x002ed8cc-0x002ed8d4 follows its moby pointer +0x2080 and checks sequence byte +0x52, then 0x002ed8dc-0x002ed8e4 loads hero vehicle-mode byte +0x20A4 (0x001413F4) and compares 2. This is the distinct vehicle_mode selector, not current-state or control_mode. Supplied include/rnc/hero/hero_state.h HeroVehicleMode canonically names 2 HERO_VEHICLE_MODE_GIANT_CLANK. domain_9_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Source requires hero.vehicle_mode == 2 for the vol1C hint when alternate_item_available byte +0x6F is zero. Retail 0x002ed900 sets s0 to hero.motion.pos at 0x0013F3D0; 0x002ed910 loads comparison constant 2 and 0x002ed914-0x002ed918 compares the byte at s0+0x2024 = 0x001413F4, the same hero.vehicle_mode byte tested at 0x002ed8dc. The checked field therefore belongs to supplied HeroVehicleMode, whose canonical member for 2 is HERO_VEHICLE_MODE_GIANT_CLANK; no HeroStateId equivalence is inferred. --- src/overlays/l15/mobys/help_hints.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l15/mobys/help_hints.c b/src/overlays/l15/mobys/help_hints.c index e1b2bbaffa..86fce62465 100644 --- a/src/overlays/l15/mobys/help_hints.c +++ b/src/overlays/l15/mobys/help_hints.c @@ -81,7 +81,7 @@ void help_hints_update(struct Moby *moby) { case HINT_DIALOGUE_INITIALIZE: moby->update_dist = 0xFF; hint_dialogue_data->wait = scale_game_frames(0x4B0); - moby->state = 1; + moby->state = HINT_DIALOGUE_CHECK_TRIGGERS; break; case HINT_DIALOGUE_CHECK_TRIGGERS: if (hint_dialogue_data->npc[0] != -1) { @@ -180,11 +180,11 @@ void help_hints_update(struct Moby *moby) { hint_dialogue_data->hold3C = 0; } } - if (hero.moby->seq == 0xC && hero.vehicle_mode == 2) { + if (hero.moby->seq == 0xC && hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { ((Items *)alternate_item_available)->f6F = 1; } if (is_point_inside_clip_volume(&hero.motion.pos, hint_dialogue_data->vol1C) != 0 && - hero.vehicle_mode == 2 && ((Items *)alternate_item_available)->f6F == 0 && + hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && ((Items *)alternate_item_available)->f6F == 0 && ((Help *)quartu_help_message_state)->busy == 0 && ((Help *)quartu_help_message_state)->cur == -1 && *(int *)(item_usage + 0x6EC) >= 0) { help_request(0x3A9C, 0x80); From 8f4cc4012e1500741ebfe8194ef162a1d2ce685d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:45:34 +0000 Subject: [PATCH 1009/1502] decomp: clarify names in do_space_transition domain_1_value_3 -> MEMCARD_REQUEST_FORMAT: Retail 0x002321ac-b8 and 0x002321e0-ec load memory_card_state at 0x0013d290+0xd4 and test state < 3, looping through memcard_update_state at 0x002321d0 otherwise. Original Ghidra identifies this as g_nMemoryCardOperationState. The authoritative C names the same field memory_card_state.state; the supplied header explicitly assigns state/pending_state to MemoryCardOperation, whose canonical value 3 is MEMCARD_REQUEST_FORMAT, not any per-operation substep. domain_2_value_0 -> MEMCARD_QUERY_INFO: Retail 0x002321c0-c4 and 0x002321f4-f8 load 0x0013d290+0xdc and continue servicing memory-card work while it is nonnegative. Original Ghidra calls this g_nPendingMemoryCardOperationState; authoritative C names memory_card_state.pending_state. The supplied memory_card_state.h domain context explicitly makes this a MemoryCardOperation field; its canonical zero member is MEMCARD_QUERY_INFO. This is an operation threshold, not a probe/create/read substep. domain_3_value_2 -> MEMCARD_DISPATCH_PENDING_OPERATION: Retail 0x00232754-5c loads constant 2 and compares memory_card_state at 0x0013d290+0xd4 against it, continuing the memcard_update_state loop until equality and no pending operation. Original Ghidra identifies the loaded field as g_nMemoryCardOperationState, matching authoritative C memory_card_state.state. Header domain context assigns this field to MemoryCardOperation, whose existing value 2 is MEMCARD_DISPATCH_PENDING_OPERATION; no per-operation step is involved. domain_4_value_0 -> MEMCARD_QUERY_INFO: Retail 0x00232764-68 loads the pending operation field at 0x0013d290+0xdc and branches back to the servicing loop when nonnegative. The original Ghidra g_nPendingMemoryCardOperationState and authoritative C memory_card_state.pending_state identify the same selector as the earlier drain loop. Supplied header context assigns pending_state to MemoryCardOperation, so reuse canonical MEMCARD_QUERY_INFO=0 as its nonnegative-operation threshold, independently of substep enums. --- src/game/transitions/do_space_transition.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/transitions/do_space_transition.c b/src/game/transitions/do_space_transition.c index 84168626fe..f0b3cba663 100644 --- a/src/game/transitions/do_space_transition.c +++ b/src/game/transitions/do_space_transition.c @@ -117,7 +117,7 @@ void do_space_transition(void) { view_context.fog_far_int = 128.0f; set_background_color(0, 0, 0); if (space_load_macro < 0) { - while (memory_card_state.state >= 3 || memory_card_state.pending_state >= 0) { + while (memory_card_state.state >= MEMCARD_REQUEST_FORMAT || memory_card_state.pending_state >= MEMCARD_QUERY_INFO) { memcard_update_state(); run_state_handler(); } @@ -223,7 +223,7 @@ void do_space_transition(void) { tick_space_transition(); } while (service_level_archive_load() == 0); } - while (memory_card_state.state != 2 || memory_card_state.pending_state >= 0) { + while (memory_card_state.state != MEMCARD_DISPATCH_PENDING_OPERATION || memory_card_state.pending_state >= MEMCARD_QUERY_INFO) { FlushCache(0); sceGsSyncV(0); memcard_update_state(); From 33101d3406735ca613cf77f224727ab39ed5cc81 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:45:34 +0000 Subject: [PATCH 1010/1502] decomp: clarify names in update_fleet_camera_box_watcher domain_0_value_118 -> HERO_STATE_HURT_WITH_DISPLACEMENT_VELOCITY: Source hero_current_state is loaded directly from h->state.current with h=&hero. Retail 0x002f2760-0x002f2768 loads hero+0x2084 and compares 0x76, resetting pvars+0x6C at 0x002f2778. This proves the HeroStateId domain, whose supplied canonical member for 118 is HERO_STATE_HURT_WITH_DISPLACEMENT_VELOCITY; it is not the separate control-mode load at 0x002f2740. domain_1_value_50 -> HERO_STATE_OPTIONAL_IDLE_ANIMATION: Source h=&hero and hero_current_state=h->state.current bind this comparison to HeroStateId. Retail 0x002f2764 loads hero+0x2084; 0x002f276c-0x002f2778 compares 0x32 and resets the clip-volume sequence. Reuse the supplied HeroStateId canonical member HERO_STATE_OPTIONAL_IDLE_ANIMATION=50 rather than a control or vehicle mode. domain_2_value_1 -> CAMERA_BOX_WATCHER_MONITOR: Retail 0x002f297c-0x002f2984 stores 1 to the input watcher's byte at moby+0x20 after initialization. The same byte is dispatched at 0x002f28d0-0x002f28d8 to monitoring code 0x002f2988. Source already names that exact selector's case 1 CAMERA_BOX_WATCHER_MONITOR. domain_6_value_2 -> CAMERA_BOX_WATCHER_ALIGN_FIRST_TARGET: Retail 0x002f2cc4-0x002f2cd0 stores 2 to the input watcher's moby+0x20 after the help gate opens. Dispatch 0x002f28f8 selects 0x002f2cec, which turns toward pvars+0x44 and checks angular alignment. The existing case on this same moby->state is CAMERA_BOX_WATCHER_ALIGN_FIRST_TARGET. domain_7_value_3 -> CAMERA_BOX_WATCHER_WAIT_AND_ALIGN_SECOND_TARGET: Retail 0x002f2d70-0x002f2d90 stores 3 to watcher moby+0x20 when the first target angular error is small and loads the scaled 60-frame timer. Dispatch 0x002f2900 selects 0x002f2d94, which waits on that timer then aligns toward pvars+0x40. Reuse this selector's existing CAMERA_BOX_WATCHER_WAIT_AND_ALIGN_SECOND_TARGET case member. domain_8_value_1 -> CAMERA_BOX_WATCHER_MONITOR: Retail 0x002f28d4 establishes s1=1; after second-target alignment and the idle-state helper, 0x002f2e3c-0x002f2e40 marks completion and stores s1 into the input watcher's moby+0x20. That exact byte dispatches value 1 to monitoring at 0x002f28d8; reuse the existing CAMERA_BOX_WATCHER_MONITOR member. --- src/overlays/l17/mobys/camera_box_watcher.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l17/mobys/camera_box_watcher.c b/src/overlays/l17/mobys/camera_box_watcher.c index 08faabbe8c..ea76e301e7 100644 --- a/src/overlays/l17/mobys/camera_box_watcher.c +++ b/src/overlays/l17/mobys/camera_box_watcher.c @@ -115,7 +115,7 @@ void fleet_camera_box_watcher_update(struct Moby *moby) { case CLIP_VOLUME_SEQUENCE_MONITOR_FOLLOWUP: { struct Hero *h = &hero; int hero_current_state = h->state.current; - if (hero_current_state == 0x76 || hero_current_state == 0x32) { + if (hero_current_state == HERO_STATE_HURT_WITH_DISPLACEMENT_VELOCITY || hero_current_state == HERO_STATE_OPTIONAL_IDLE_ANIMATION) { pvars->unk6C = 0; } else if (is_point_inside_clip_volume(&h->motion.pos, pvars->unk64) || is_point_inside_clip_volume(&h->motion.pos, pvars->unk68)) { @@ -167,7 +167,7 @@ void fleet_camera_box_watcher_update(struct Moby *moby) { pvars->unk44); pvars->unk4C = 1; } - moby->state = 1; + moby->state = CAMERA_BOX_WATCHER_MONITOR; break; case CAMERA_BOX_WATCHER_MONITOR: pending_help_clip_volume_index = -1; @@ -261,7 +261,7 @@ void fleet_camera_box_watcher_update(struct Moby *moby) { } if (fleet_help_request_gate_state[0] != 0 || fleet_help_request_gate_state[9] != -1) { pvars->unk50 = 0; - moby->state = 2; + moby->state = CAMERA_BOX_WATCHER_ALIGN_FIRST_TARGET; pvars->unk5C = scale_game_frames(0xB4); hero_set_state(0x72, 0); } @@ -278,7 +278,7 @@ void fleet_camera_box_watcher_update(struct Moby *moby) { *(float *)(D_L17_001600EC + ((pvars->unk44 << 7) + 0x34)) - *(float *)(cam + 0x144)); if (fast_difference_between_rotations(*(float *)(cam + 0x158), target_heading) < 0.034906585f) { - moby->state = 3; + moby->state = CAMERA_BOX_WATCHER_WAIT_AND_ALIGN_SECOND_TARGET; pvars->unk5C = scale_game_frames(0x3C); } break; @@ -298,7 +298,7 @@ void fleet_camera_box_watcher_update(struct Moby *moby) { 0.034906585f) { enter_hero_idle_state_for_current_vehicle_mode(); pvars->unk4C = 1; - moby->state = 1; + moby->state = CAMERA_BOX_WATCHER_MONITOR; } } break; From a20356b560bfc0f503205fb4828007fc9f2a1666 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:45:34 +0000 Subject: [PATCH 1011/1502] decomp: clarify names in sharkigator_update domain_0_value_2 -> SHARKIGATOR_WAIT_TO_LEAP: Retail 002d169c retains the moby in s2 and 002d16b4 reads its state byte at +0x20; 002d16dc dispatches value 2 to 002d19c4. Initialization materializes 2 at 002d16fc and stores it to that identical byte at 002d1710, saves initial height at 002d1724 and sets the leap delay via 002d1b58..002d1b64. The destination handler decrements +0x7c and waits for water-height, control-mode and timer conditions (002d19c4..002d1a18). This is the exact selector already named SHARKIGATOR_WAIT_TO_LEAP=2 in the function-local enum, not a Hero domain. domain_1_value_3 -> SHARKIGATOR_UPDATE_LEAP: Retail 002d16b4 reads moby(s2)+0x20 and 002d16e0..002d16e4 dispatch value 3 to 002d1b68. The waiting handler positions and rotates the moby, initializes vertical velocity at 002d1ab4, then materializes 3 at 002d1ae8 and writes the same state byte at 002d1af0. Its destination integrates height and gravity at 002d1c10..002d1c54 and performs leap splash/camera handling. This matches the existing function-local SHARKIGATOR_UPDATE_LEAP=3 member used by the switch over MOBY(moby)->state. --- src/overlays/l05/mobys/sharkigator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l05/mobys/sharkigator.c b/src/overlays/l05/mobys/sharkigator.c index 6e42a25600..91195cf707 100644 --- a/src/overlays/l05/mobys/sharkigator.c +++ b/src/overlays/l05/mobys/sharkigator.c @@ -87,7 +87,7 @@ void sharkigator_update(char *moby) { state_zero: { float height; if (sharkigator_instance_vars->unk64 != 0) { - MOBY(moby)->state = 2; + MOBY(moby)->state = SHARKIGATOR_WAIT_TO_LEAP; MOBY(moby)->flags |= 1; MOBY(moby)->update_dist = 0xff; sharkigator_instance_vars->unk74 = MOBY(moby)->pos.z; @@ -180,7 +180,7 @@ state_two: { if (MOBY(moby)->prev_seq != state) set_action_2d1688(moby, 2, 0, scale_game_frames(5)); MOBY(moby)->command = 0; - MOBY(moby)->state = 3; + MOBY(moby)->state = SHARKIGATOR_UPDATE_LEAP; jet_mount(point + 0x140, point + 0x150, 0, 0, 0); return; } From 53e9802ecd7d4402463852764f62ae33d1613651 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:45:34 +0000 Subject: [PATCH 1012/1502] decomp: clarify names in helga_update domain_0_value_1 -> HELGA_UPDATE_DIALOGUE: Authoritative helga.c SHA-256 08583a0251f07a93b7f75d7ffc60bf0743a55c08e5b7f1f2e542cc26d5997b89 assigns helga_moby->state=1 during HELGA_INITIALIZE. Retail 0x002da9bc loads a2=1 and 0x002da9d8 stores it to +0x20(s2), the same byte read at 0x002da8ac and dispatched by 0x002da8b0 to 0x002daa00. That branch calls update_npc_dialogue with this moby and pvars+0x80. Original Ghidra agrees. Therefore reuse existing HELGA_UPDATE_DIALOGUE=1 from this exact local state domain. domain_1_value_2 -> HELGA_RESOLVE_DIALOGUE: In authoritative helga_update, successful update_npc_dialogue starts begin_dialogue_camera_transition and assigns helga_moby->state=2. Retail 0x002daa04-0x002daa30 checks the update return, calls the transition, loads v0=2 and stores to +0x20(s2). The dispatcher reads the same byte at 0x002da8ac and branches for 2 at 0x002da8d4 to 0x002daa84, the existing HELGA_RESOLVE_DIALOGUE case, which handles persistence/camera outcomes and reward acceptance. Original Ghidra confirms this same field and transition; reuse the existing local member. domain_2_value_1 -> HELGA_UPDATE_DIALOGUE: Within HELGA_RESOLVE_DIALOGUE in the authoritative snapshot, the nonactive global-mode branch assigns helga_moby->state=1 after persistence/camera handling and before checking acceptance. Original Ghidra shows *(undefined1 *)(iVar6+0x20)=1 there. Retail 0x002dab10 loads v0=1 (also set on the alternate path at 0x002daa94), and 0x002dab18 stores v0 to +0x20(s2). Dispatch 0x002da8ac-0x002da8b0 reads this same owner state byte and sends 1 to the update_npc_dialogue branch at 0x002daa00. Reuse existing HELGA_UPDATE_DIALOGUE=1. --- src/overlays/l03/mobys/helga.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l03/mobys/helga.c b/src/overlays/l03/mobys/helga.c index a203715488..81588f181c 100644 --- a/src/overlays/l03/mobys/helga.c +++ b/src/overlays/l03/mobys/helga.c @@ -166,7 +166,7 @@ void helga_update(struct Moby *helga_moby) { } } helga_moby->spawn_frame = *(u64 *)(D_001413D0[0] + 0x38); - helga_moby->state = 1; + helga_moby->state = HELGA_UPDATE_DIALOGUE; talk->script = helga_dialogue_script; helga_vars->talk.unk48 = 5; initialize_npc_dialogue(helga_moby, talk); @@ -175,7 +175,7 @@ void helga_update(struct Moby *helga_moby) { case HELGA_UPDATE_DIALOGUE: if (update_npc_dialogue(helga_moby, talk)) { begin_dialogue_camera_transition(helga_moby, 2.3f); - helga_moby->state = 2; + helga_moby->state = HELGA_RESOLVE_DIALOGUE; if (helga_vars->link != -1) { helper_moby = (struct Moby *)((helga_vars->link << 8) + (s32)D_L03_0015FFD8); if (helper_moby->oclass == 0x3F4) { @@ -205,7 +205,7 @@ void helga_update(struct Moby *helga_moby) { &l03_cuboids[helga_vars->talk.warp].rot); } } - helga_moby->state = 1; + helga_moby->state = HELGA_UPDATE_DIALOGUE; if (helga_vars->talk.mode == 2) { grant_inventory_item(0xC, 1); queue_dialogue_message(0xBC8, -1); From eab3acfedc33f25dfdf5fcc90f9ff6ce61d9959c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:47:33 +0000 Subject: [PATCH 1013/1502] decomp: clarify names in update_hero_airborne_planar_velocity domain_0_value_10 -> HERO_STATE_PACK_JUMP: Source state = hero.state.current corresponds to retail lw a0,0x2084(s0) at 0x0022b460, with s0 = hero (0x0013f350). This is the shared HeroStateId selector from include/rnc/hero/hero_state.h, also dispatched by the supplied update_hero_motion_for_current_state caller; it is separate from control_mode at +0x208c. At 0x0022b444/0x0022b464 this loaded state is compared with 10; the branch builds move impulse, copies +0x920 to momentum +0x150 and copies flat_speed +0x164 to ground_speed +0x194 (0x0022b484-0x0022b4a4). The shared domain canonically names 10 HERO_STATE_PACK_JUMP, and the supplied caller handles that same member in its jump family. domain_1_value_16 -> HERO_STATE_PACK_LONG_JUMP: Source state = hero.state.current corresponds to retail lw a0,0x2084(s0) at 0x0022b460, with s0 = hero (0x0013f350). This is the shared HeroStateId selector from include/rnc/hero/hero_state.h, also dispatched by the supplied update_hero_motion_for_current_state caller; it is separate from control_mode at +0x208c. At 0x0022b4a8-0x0022b4ac the current state is compared with 16. The branch selects long_jump_speed (+0x3f4), approaches jump_gravity (+0x4a0), and rebuilds forward planar velocity (0x0022b4cc-0x0022b568). The shared HeroStateId member for this selector/value is HERO_STATE_PACK_LONG_JUMP, also used by the caller's jump and trail logic. domain_2_value_28 -> HERO_STATE_LEDGE_JUMP: Source state = hero.state.current corresponds to retail lw a0,0x2084(s0) at 0x0022b460, with s0 = hero (0x0013f350). This is the shared HeroStateId selector from include/rnc/hero/hero_state.h, also dispatched by the supplied update_hero_motion_for_current_state caller; it is separate from control_mode at +0x208c. At 0x0022b4b0/0x0022b574 the current state is compared with 0x1c. This path gates steering and air acceleration on the state timer and approaches ledge_jump_speed (+0x45c) over animation frames 13-30, then constructs XY velocity from yaw (0x0022b57c-0x0022b734). The shared domain canonically names this state HERO_STATE_LEDGE_JUMP; the caller dispatches that member in its jump family. domain_3_value_76 -> HERO_STATE_ALT_LEDGE_JUMP: Source state = hero.state.current corresponds to retail lw a0,0x2084(s0) at 0x0022b460, with s0 = hero (0x0013f350). This is the shared HeroStateId selector from include/rnc/hero/hero_state.h, also dispatched by the supplied update_hero_motion_for_current_state caller; it is separate from control_mode at +0x208c. At 0x0022b578/0x0022b660 the same current-state register is compared with 0x4c. The branch approaches ledge_jump_speed (+0x45c) during animation frames 5-18 with a 1.25 scaled target, then uses the shared yaw-based XY velocity path (0x0022b668-0x0022b734). The established HeroStateId member for this selector is HERO_STATE_ALT_LEDGE_JUMP, present in the caller jump dispatch. domain_4_value_11 -> HERO_STATE_HIGH_JUMP: Source state = hero.state.current corresponds to retail lw a0,0x2084(s0) at 0x0022b460, with s0 = hero (0x0013f350). This is the shared HeroStateId selector from include/rnc/hero/hero_state.h, also dispatched by the supplied update_hero_motion_for_current_state caller; it is separate from control_mode at +0x208c. Retail 0x0022b664/0x0022b738 tests unsigned current_state-11 < 2, implementing the source's state == 11 || state == 12. A reload of exactly hero+0x2084 at 0x0022b7ac then compares 11 at 0x0022b7b0 to gate drift-speed decay near landing. The source already names that inner test HERO_STATE_HIGH_JUMP, independently confirming the shared canonical member for the outer 11 comparison. domain_5_value_12 -> HERO_STATE_STORED_HEADING_JUMP: Source state = hero.state.current corresponds to retail lw a0,0x2084(s0) at 0x0022b460, with s0 = hero (0x0013f350). This is the shared HeroStateId selector from include/rnc/hero/hero_state.h, also dispatched by the supplied update_hero_motion_for_current_state caller; it is separate from control_mode at +0x208c. Retail 0x0022b664/0x0022b738 admits current-state IDs 11 and 12 via unsigned state-11 < 2. The common path copies takeoff_yaw +0x43c to move_yaw +0x180, steers, and combines stored heading/drift velocity (0x0022b778-0x0022b8c8). The shared HeroStateId domain canonically names 12 HERO_STATE_STORED_HEADING_JUMP; the supplied caller includes that member in the same jump dispatch. domain_6_value_17 -> HERO_STATE_REPEATABLE_JUMP: Source state = hero.state.current corresponds to retail lw a0,0x2084(s0) at 0x0022b460, with s0 = hero (0x0013f350). This is the shared HeroStateId selector from include/rnc/hero/hero_state.h, also dispatched by the supplied update_hero_motion_for_current_state caller; it is separate from control_mode at +0x208c. At 0x0022b8e4-0x0022b8e8 the loaded current state is compared with 0x11. This branch restores move_dir from hero+0x470 and move_yaw from +0x47c, gates turning and planar velocity on scaled frame 9, and copies flat_speed to ground_speed (0x0022b8f0-0x0022ba1c). The shared canonical HeroStateId member for this selector/value is HERO_STATE_REPEATABLE_JUMP, used by the caller jump dispatch. domain_7_value_45 -> HERO_STATE_ITEM_RELEASE_FALL: Source state = hero.state.current corresponds to retail lw a0,0x2084(s0) at 0x0022b460, with s0 = hero (0x0013f350). This is the shared HeroStateId selector from include/rnc/hero/hero_state.h, also dispatched by the supplied update_hero_motion_for_current_state caller; it is separate from control_mode at +0x208c. Retail 0x0022b8ec/0x0022ba20 compares the same current state with 0x2d. The branch springs a temporary yaw, computes its difference from hero yaw and rotates about the fixed local pivot (0x0022ba28-0x0022baa0). The supplied caller dispatches HERO_STATE_ITEM_RELEASE_FALL with HERO_STATE_FALL and performs the corresponding 0x2d pivot path before calling this helper, confirming the shared canonical state member. --- .../hero/update_hero_motion_for_current_state.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l06/hero/update_hero_motion_for_current_state.c b/src/overlays/l06/hero/update_hero_motion_for_current_state.c index f662e0c44d..045549d100 100644 --- a/src/overlays/l06/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l06/hero/update_hero_motion_for_current_state.c @@ -642,11 +642,11 @@ void update_hero_airborne_planar_velocity(void) { s32 state; state = hero.state.current; - if (state == 10) { + if (state == HERO_STATE_PACK_JUMP) { build_scaled_hero_move_impulse(0.7f, ED6C * 0.0f); qcopy(&hero.motion.momentum, &hero.move_impulse); hero.ground_speed = hero.motion.flat_speed; - } else if (state == 16) { + } else if (state == HERO_STATE_PACK_LONG_JUMP) { if (FUN_001f96f8_2b438(0x36) < hero.state_timer) { approach_value_2b438(ED70 * 25.0f, ED70 * 7.0f, &hero.jump_gravity); } @@ -658,7 +658,7 @@ void update_hero_airborne_planar_velocity(void) { speed_step(ED70 * 44.0f, ED70 * 45.0f); set_gravity_relative_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, 0.0f); add_hero_forward_offset(&hero.motion.velocity, &hero.motion.velocity, hero.ground_speed); - } else if (state == 0x1C) { + } else if (state == HERO_STATE_LEDGE_JUMP) { if (FUN_001f96f8_2b438(0x28) < hero.state_timer) { turn_to(0, ED64 * 0.04f, ED64 * 0.2f, ED6C * 15.009831f); air_accel(ED70 * 20.0f); @@ -674,7 +674,7 @@ void update_hero_airborne_planar_velocity(void) { FUN_001f9dc8_2b438(hero.motion.rot.f[2]) * hero.ledge_jump_speed; hero.motion.velocity.f[1] = FUN_001f9de0_2b438(hero.motion.rot.f[2]) * hero.ledge_jump_speed; - } else if (state == 0x4C) { + } else if (state == HERO_STATE_ALT_LEDGE_JUMP) { if (5.0f <= hero.anim_frame && hero.anim_frame <= 18.0f) { if (15.0f < hero.anim_frame) { approach_value_2b438(0.0f, ED70 * 8.0f, &hero.ledge_jump_speed); @@ -686,7 +686,7 @@ void update_hero_airborne_planar_velocity(void) { FUN_001f9dc8_2b438(hero.motion.rot.f[2]) * hero.ledge_jump_speed; hero.motion.velocity.f[1] = FUN_001f9de0_2b438(hero.motion.rot.f[2]) * hero.ledge_jump_speed; - } else if (state == 11 || state == 12) { + } else if (state == HERO_STATE_HIGH_JUMP || state == HERO_STATE_STORED_HEADING_JUMP) { hero.motion.move_yaw = hero.takeoff_yaw; turn_to(0, ED64 * 0.04f, ED64 * 0.2f, ED6C * 6.981317f); if (hero.unk450 != 3) { @@ -714,7 +714,7 @@ void update_hero_airborne_planar_velocity(void) { FUN_001f9de0_2b438(hero.takeoff_yaw) * speed_component_or_yaw_delta; build_scaled_hero_move_impulse(0.7f, ED6C * 0.0f); qcopy(&hero.motion.momentum, &hero.move_impulse); - } else if (state == 0x11) { + } else if (state == HERO_STATE_REPEATABLE_JUMP) { hero.motion.move_yaw = hero.unk470.f[3]; qcopy(&hero.motion.move_dir, &hero.unk470); if (FUN_001f96f8_2b438(9) < hero.state_timer) { @@ -736,7 +736,7 @@ void update_hero_airborne_planar_velocity(void) { } hero.ground_speed = hero.motion.flat_speed; } else { - if (state == 0x2D) { + if (state == HERO_STATE_ITEM_RELEASE_FALL) { x = hero.motion.rot.f[2]; hero.motion.yaw_error = FUN_L00_0025bc98_2b438(&x, &hero.motion.yaw_rate, From be32faa58331fbd43859a304f818e9e91218b88f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:47:33 +0000 Subject: [PATCH 1014/1502] decomp: clarify names in update_level_gameplay_frame domain_0_value_0 -> LEVEL_RENDER_PHASE_SELECT_RANDOM_MODE: Authoritative source src/game/update_level_gameplay_frame.c (SHA-256 b6d292240737665df8f70dacca2ffe3ef62372b1fd6c7d42730b263793c2af36) and prepared original Ghidra agree: retail 0x0022ec54 writes zero to render-state +0x5C; 0x0022ec5c..0x0022ec70 tests this same phase, and its zero branch at 0x0022ec74..0x0022eca4 chooses a different mode in 0..3 by adding (rand >> 16) % 3 + 1 and masking with 3. This names the phase's random-mode selection role, not a moby state. domain_1_value_2 -> LEVEL_RENDER_PHASE_REQUEST_LOAD: Retail 0x0022ec5c..0x0022ec64 loads phase from render-state +0x5C and tests signed phase < 2. Values below this threshold prepare a scene and increment phase at 0x0022ecb0..0x0022ecc4. The >=2 path at 0x0022ed9c..0x0022edb8 clears the archive-load gate when set, stores 1 to space_load_in_progress, and returns. Source and original Ghidra agree: 2 is the phase threshold for requesting the load, separate from render mode. domain_2_value_0 -> LEVEL_RENDER_PHASE_SELECT_RANDOM_MODE: Authoritative source src/game/update_level_gameplay_frame.c (SHA-256 b6d292240737665df8f70dacca2ffe3ef62372b1fd6c7d42730b263793c2af36) and prepared original Ghidra agree: retail 0x0022ec54 writes zero to render-state +0x5C; 0x0022ec5c..0x0022ec70 tests this same phase, and its zero branch at 0x0022ec74..0x0022eca4 chooses a different mode in 0..3 by adding (rand >> 16) % 3 + 1 and masking with 3. This names the phase's random-mode selection role, not a moby state. domain_3_value_4 -> LEVEL_RENDER_MODE_FADE_OUT: The selector is render-state mode +0x58, distinct from phase +0x5C. Retail 0x0022ec70/0x0022eca4 assigns mode 4 for the nonzero preparation phase. Equality at 0x0022ee28..0x0022ee30 gates remaining-duration scaling at 0x0022ee40..0x0022ee80. Equality at 0x0022f100..0x0022f108 gates the last-56-frame fade: 0x0022f150..0x0022f1b4 reduces object scale toward zero, and 0x0022f1b8..0x0022f1e0 reduces warp-trail alpha with remaining time. Source and original Ghidra agree on this fade-out render mode. domain_4_value_4 -> LEVEL_RENDER_MODE_FADE_OUT: The selector is render-state mode +0x58, distinct from phase +0x5C. Retail 0x0022ec70/0x0022eca4 assigns mode 4 for the nonzero preparation phase. Equality at 0x0022ee28..0x0022ee30 gates remaining-duration scaling at 0x0022ee40..0x0022ee80. Equality at 0x0022f100..0x0022f108 gates the last-56-frame fade: 0x0022f150..0x0022f1b4 reduces object scale toward zero, and 0x0022f1b8..0x0022f1e0 reduces warp-trail alpha with remaining time. Source and original Ghidra agree on this fade-out render mode. domain_5_value_4 -> LEVEL_RENDER_MODE_FADE_OUT: The selector is render-state mode +0x58, distinct from phase +0x5C. Retail 0x0022ec70/0x0022eca4 assigns mode 4 for the nonzero preparation phase. Equality at 0x0022ee28..0x0022ee30 gates remaining-duration scaling at 0x0022ee40..0x0022ee80. Equality at 0x0022f100..0x0022f108 gates the last-56-frame fade: 0x0022f150..0x0022f1b4 reduces object scale toward zero, and 0x0022f1b8..0x0022f1e0 reduces warp-trail alpha with remaining time. Source and original Ghidra agree on this fade-out render mode. --- src/game/update_level_gameplay_frame.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/game/update_level_gameplay_frame.c b/src/game/update_level_gameplay_frame.c index 50af0b1364..464fff9da9 100644 --- a/src/game/update_level_gameplay_frame.c +++ b/src/game/update_level_gameplay_frame.c @@ -156,7 +156,7 @@ extern void build_object_rotation_matrix(void) __asm__("func_0022DE10"); void update_level_gameplay_frame(void) __asm__("FUN_0022eaa8"); void update_level_gameplay_frame(void) { - Vector4 first_position; + enum { LEVEL_RENDER_PHASE_SELECT_RANDOM_MODE = 0 , LEVEL_RENDER_PHASE_REQUEST_LOAD = 2 , LEVEL_RENDER_MODE_FADE_OUT = 4 } ;Vector4 first_position; Vector4 second_position; Matrix4x4 first_transform; Matrix4x4 second_transform; @@ -221,14 +221,14 @@ void update_level_gameplay_frame(void) { } if (current_level_index != 0 && (current_level_index != 1 || level_available[3] != 0) && D_0015EE48 < 3) { - level_render_state.state = 0; + level_render_state.state = LEVEL_RENDER_PHASE_SELECT_RANDOM_MODE; } - if (level_render_state.state < 2) { - if (level_render_state.state == 0) { + if (level_render_state.state < LEVEL_RENDER_PHASE_REQUEST_LOAD) { + if (level_render_state.state == LEVEL_RENDER_PHASE_SELECT_RANDOM_MODE) { mode_advance = (RandomNext() >> 16) % 3 + 1; level_render_state.mode = (level_render_state.mode + mode_advance) & 3; } else { - level_render_state.mode = 4; + level_render_state.mode = LEVEL_RENDER_MODE_FADE_OUT; } level_render_state.history_index = 0; level_render_state.history_count = 0; @@ -267,7 +267,7 @@ void update_level_gameplay_frame(void) { } update_view_context(); scale = 1.0f; - if (level_render_state.mode == 4) { + if (level_render_state.mode == LEVEL_RENDER_MODE_FADE_OUT) { scale = (f32)(render_sequence.end - render_sequence.time) / (f32)render_sequence.end; scale_vector(&first_position, &mode4_render_vector_delta_gp, scale); fast_vec_add(&D_001604F0, &D_001604F0, &first_position); @@ -324,7 +324,7 @@ void update_level_gameplay_frame(void) { &first_transform.rows[3]); qcopy(&level_render_state.secondary_history_positions[history_slot], &second_transform.rows[3]); - if (level_render_state.mode == 4) { + if (level_render_state.mode == LEVEL_RENDER_MODE_FADE_OUT) { if (current_level_index == 0 || (current_level_index == 1 && level_available[3] == 0)) { interpolated_object->flags |= 1; From 7b1847b87ae558dcf716e029ee14f96fc975cbfc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:49:21 +0000 Subject: [PATCH 1015/1502] decomp: clarify names in scatter_ground_particles domain_0_value_2 -> GROUND_PARTICLES_STATE_SCATTER: In authoritative ground_particle_scatter.c (SHA-256 7aeb93752b9841387058488132c77c359472192d327afbdadf71700115f7d84f), the existing local enum GROUND_PARTICLES_STATE_SCATTER=2 labels switch(moby->state). Retail 0x00307de4 loads the byte at input+0x20; 0x00307df0-0x00307df4 compares that same byte with 2 and branches to the recurring scatter/countdown path at 0x00307e28. Initialization loads 2 at 0x00307e04 and stores it to the identical input+0x20 state byte at 0x00307e14. Original Ghidra likewise writes state 2 in state 0 and executes scatter passes for state 2. Thus this assignment enters the exact same already-named state domain; reuse its canonical local member. --- src/overlays/shared/rendering/effects/ground_particle_scatter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/rendering/effects/ground_particle_scatter.c b/src/overlays/shared/rendering/effects/ground_particle_scatter.c index 7bacc1f1db..44b8bf6447 100644 --- a/src/overlays/shared/rendering/effects/ground_particle_scatter.c +++ b/src/overlays/shared/rendering/effects/ground_particle_scatter.c @@ -167,7 +167,7 @@ void ground_particle_scatter_update(Moby *moby) { switch (moby->state) { case GROUND_PARTICLES_STATE_INITIALIZE: - moby->state = 2; + moby->state = GROUND_PARTICLES_STATE_SCATTER; moby->update_dist = 0xFF; randomize_ground_particle_scatter_parameters(flag); break; From 3de252525d80c4ad0898763bdea929787408bddd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:49:21 +0000 Subject: [PATCH 1016/1502] decomp: clarify names in morphoray_update domain_0_value_0 -> MORPHORAY_STATE_UNINITIALIZED: The selector is this morphoray Moby's state byte, not hero state: retail 002bc808 copies argument a0 to s3, 002bc824 loads byte +0x20(s3), and 002bc830 skips the initialization block when nonzero. On zero, 002bc838 stores 1 to the same byte and 002bc83c-002bc854 initialize voice/light indices to -1 and the light fade countdown to zero. The authoritative C and retail decompilation show the same guard and resets, proving zero denotes the uninitialized morphoray state. domain_1_value_1 -> MORPHORAY_STATE_INITIALIZED: Retail 002bc810 loads 1 into a0; after the zero test of this function's morphoray Moby state at 002bc824-002bc830, 002bc838 stores that 1 at +0x20(s3). The accompanying 002bc844/002bc84c/002bc854 stores reset voice/light indices and fade countdown. Later calls with this nonzero state skip those resets. The C assigns moby->state = 1 only inside moby->state == 0, proving this is the initialized marker, while independent button/mode gates at 002bc894-002bc8e4 still control firing. --- src/overlays/shared/weapons/morphoray.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/morphoray.c b/src/overlays/shared/weapons/morphoray.c index 4351191651..eae0406dc9 100644 --- a/src/overlays/shared/weapons/morphoray.c +++ b/src/overlays/shared/weapons/morphoray.c @@ -1503,6 +1503,10 @@ void morphoray_update(Moby *moby) __asm__("FUN_L00_002bc7e8"); /* Moby class 185 */ void morphoray_update(Moby *moby) { + enum { + MORPHORAY_STATE_UNINITIALIZED = 0, + MORPHORAY_STATE_INITIALIZED = 1 + }; Vq direction; Vq points[3]; Vq matrix[4]; @@ -1517,8 +1521,8 @@ void morphoray_update(Moby *moby) { busy = 1; } morphoray_state = (struct Ray *)moby->pvars; - if (moby->state == 0) { - moby->state = 1; + if (moby->state == MORPHORAY_STATE_UNINITIALIZED) { + moby->state = MORPHORAY_STATE_INITIALIZED; morphoray_point_light_slot = -1; D_L00_001617C8 = -1; morphoray_light_fade_countdown = 0; From 1a4ab7ee147d5fd5345ee78b096c0c0251356f3f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:49:22 +0000 Subject: [PATCH 1017/1502] decomp: clarify names in update_hero_ground_contact_and_gravity domain_0_value_0 -> GROUND_MATERIAL_WATER: Retail 0x00233fb8-0x00233fc8 stores collision_hit_material() into hero+0x12E0 and tests it against zero. Its zero branch at 0x00233fcc-0x00234018 resolves water_surface_z, checks hero position against that height, starts in_water_frames and repeats the ray with mask 0x24. The SHA-bound source's update_hero_ground_material_flags consumes the same hero.ground_type using established GROUND_MATERIAL_WATER=0 to calculate water_depth and wading. This proves material-domain identity, independently of state ID zero. domain_1_value_13 -> GROUND_MATERIAL_SINK_TRIGGER: Retail 0x00234060-0x0023406c compares hero+0x12E0, the collision material stored at 0x00233fc8, with 13. The branch 0x00234074-0x002340a8 records the hit point z as water_surface_z and probes again starting 0.01 below it. In the supplied source update_hero_ground_material_flags reads this same hero.ground_type and uses established GROUND_MATERIAL_SINK_TRIGGER=0xD to set selector_13; its ensuing height/descent check calls hero_set_state(HERO_STATE_SINK,1). Thus this is the sink-trigger material domain, not HERO_STATE_JUMP_WITH_TRANSFORM_TRAIL. domain_2_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: Retail 0x00234200-0x00234208 loads hero+0x20B3 and compares it to 1 to allow clearing air_frames regardless of ground slope. The exact same byte is loaded at 0x002342a0 for the later gravity switch; value 1 branches to 0x002342e4-0x00234300, copies normalized ground_normal into gravity_dir and scales it by -1.0. The current source already labels that switch branch HERO_GRAVITY_OPPOSITE_GROUND_NORMAL, matching the supplied shared HeroGravityMode member. Reuse that canonical member for this comparison. --- .../l12/hero/update_hero_motion_for_current_state.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l12/hero/update_hero_motion_for_current_state.c b/src/overlays/l12/hero/update_hero_motion_for_current_state.c index 1db26d33e2..3cfcb53b19 100644 --- a/src/overlays/l12/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l12/hero/update_hero_motion_for_current_state.c @@ -213,6 +213,10 @@ extern CollisionHit D_L12_001742C0_lui __asm__("D_L12_001742C0") NOT_SDA; void update_hero_ground_contact_and_gravity(void) __asm__("FUN_L12_00233e80"); void update_hero_ground_contact_and_gravity(void) { + enum { + GROUND_MATERIAL_WATER = 0, + GROUND_MATERIAL_SINK_TRIGGER = 0xD + }; V collision_ray_second_endpoint, ground_ray_first_endpoint, ground_geometry_scratch, ground_probe_first_endpoint, unused_ground_probe_output, hit_surface_angles, normalized_hit_normal; @@ -262,7 +266,7 @@ void update_hero_ground_contact_and_gravity(void) { } hero.ground_sound_class = collision_sound_class; hero.ground_type = collision_hit_material(); - if (hero.ground_type == 0) { + if (hero.ground_type == GROUND_MATERIAL_WATER) { hero.water_surface_z = resolve_camera_surface_height(D_L12_001742E0, (u8 *)&hero.water_surface_normal); if (hero.motion.pos.f[2] < hero.water_surface_z && hero.in_water_frames <= 0) { @@ -281,7 +285,7 @@ void update_hero_ground_contact_and_gravity(void) { } hero.ground_sound_class = collision_sound_class; } - if (hero.ground_type == 0xD) { + if (hero.ground_type == GROUND_MATERIAL_SINK_TRIGGER) { hero.water_surface_z = D_L12_001742C0_lui.point.f[2]; ground_ray_first_endpoint.f[2] = D_L12_001742C0_lui.point.f[2] - 0.01f; if (FUN_001efa68_u( @@ -314,7 +318,7 @@ void update_hero_ground_contact_and_gravity(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == 1 || + if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = D_L12_001742C0_lui.moby; From 4f22e8127bc3726e1b4a5ea233dc90ef6df02f7b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:49:22 +0000 Subject: [PATCH 1018/1502] decomp: clarify names in update_radial_exploding_prop domain_0_value_1 -> RADIAL_EXPLODING_PROP_STATE_INITIALIZED: Retail 002a78d8..002a78e0 reads the state byte at moby+0x20 and returns on 1 outside global mode 2. This is the same byte written to 1 at 002a7f84 during the no-hit initialization sequence, which sets distances and doubles scale. Thus 1 denotes the prop's initialized state, not a control mode. domain_1_value_0 -> RADIAL_EXPLODING_PROP_STATE_UNINITIALIZED: Retail 002a7f70..002a7f84 reads moby+0x20, skips the no-hit initialization when nonzero, and changes zero to 1. The following 002a7f80..002a7fbc sets update/draw distances and doubles scale, proving zero is this prop's pre-initialization state. domain_2_value_1 -> RADIAL_EXPLODING_PROP_STATE_INITIALIZED: Retail 002a7f7c loads 1 and 002a7f84 stores it to moby+0x20 after the zero-state test at 002a7f74. This transition accompanies distance setup, scale doubling and saved-removal checking. It is the identical state field compared with 1 at 002a78d8..002a78e0, so both uses share the initialized-state member. --- src/overlays/l15/mobys/radial_exploding_prop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l15/mobys/radial_exploding_prop.c b/src/overlays/l15/mobys/radial_exploding_prop.c index ed28bae3f1..98beef1b67 100644 --- a/src/overlays/l15/mobys/radial_exploding_prop.c +++ b/src/overlays/l15/mobys/radial_exploding_prop.c @@ -71,7 +71,7 @@ void radial_exploding_prop_update(struct Moby *moby) __asm__("FUN_L15_002a7880") /* Moby classes 148, 255 */ void radial_exploding_prop_update(struct Moby *moby) { - char *slot = 0; + enum { RADIAL_EXPLODING_PROP_STATE_UNINITIALIZED = 0 , RADIAL_EXPLODING_PROP_STATE_INITIALIZED = 1 } ;char *slot = 0; Vec velocity, hit_direction_step, doubled_hit_direction_step, offset, debris_origin; u32 palette[4]; u32 colors[4]; @@ -83,7 +83,7 @@ void radial_exploding_prop_update(struct Moby *moby) { void *effect; Vec *base_position; - if (D_001413F4[0] != 2 && moby->state == 1) + if (D_001413F4[0] != 2 && moby->state == RADIAL_EXPLODING_PROP_STATE_INITIALIZED) return; for (slot_index = 0; slot_index < 64; slot_index++) { @@ -216,10 +216,10 @@ void radial_exploding_prop_update(struct Moby *moby) { no_hit: moby->hit_slot = 0xff; - if (moby->state != 0) + if (moby->state != RADIAL_EXPLODING_PROP_STATE_UNINITIALIZED) return; moby->update_dist = 0xff; - moby->state = 1; + moby->state = RADIAL_EXPLODING_PROP_STATE_INITIALIZED; moby->draw_dist = 0x80; moby->scale = moby->scale + moby->scale; { From 480f3b1af9265f1a04f2b303d2d864446efd3999 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:49:22 +0000 Subject: [PATCH 1019/1502] decomp: clarify names in update_hero_ground_contact domain_0_value_0 -> GROUND_MATERIAL_WATER: Retail 0x0020a8d8 calls collision_hit_material and 0x0020a8e8 stores its result at hero+0x12e0 (hero.ground_type). The zero comparison at 0x0020a8e0-0x0020a8e4 enters 0x0020a8ec-0x0020a918: resolve_camera_surface_height consumes the hit position, writes water_surface_z, and hero.in_water_frames becomes 1 when hero.motion.pos.z is below it. Original Ghidra confirms sRam00140630 == 0 gates that water-height and immersion-counter flow. This is collision material, not a hero state domain. domain_3_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: Retail 0x0020ab3c loads hero+0x20b3 (hero.gravity_mode), and 0x0020ab40-0x0020ab44 compares it with 1 to accept ground contact despite the slope limit. The same byte is loaded at 0x0020abdc and compared with 1 at 0x0020abe0; its branch at 0x0020ac20-0x0020ac3c copies ground_normal to gravity_dir and scales by -1. Original Ghidra uses bRam00141403 in both comparisons. The authoritative C already names that switch branch HERO_GRAVITY_OPPOSITE_GROUND_NORMAL, proving this comparison belongs to the shared HeroGravityMode domain and must reuse its canonical member. --- src/overlays/shared/hero/update_hero_ground_contact.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/update_hero_ground_contact.c b/src/overlays/shared/hero/update_hero_ground_contact.c index 5e49217a53..5f05c2dae0 100644 --- a/src/overlays/shared/hero/update_hero_ground_contact.c +++ b/src/overlays/shared/hero/update_hero_ground_contact.c @@ -93,6 +93,9 @@ extern struct Hero hero_lui __asm__("D_0013F350") NOT_SDA; void update_hero_ground_contact(void) __asm__("FUN_L15_0020a7a0"); void update_hero_ground_contact(void) { + enum { + GROUND_MATERIAL_WATER = 0 + }; V shared_ray_endpoint, ground_ray_endpoint, ground_displacement_or_angles, surface_probe_endpoint, unused_probe_vector, probe_surface_angles, probe_surface_normal; f32 f; @@ -136,7 +139,7 @@ void update_hero_ground_contact(void) { } hero.ground_sound_class = collision_sound_class; hero.ground_type = collision_hit_material(); - if (hero.ground_type == 0) { + if (hero.ground_type == GROUND_MATERIAL_WATER) { hero.water_surface_z = resolve_camera_surface_height(D_L15_00174460, &hero.water_surface_normal); if (hero.motion.pos.f[2] < hero.water_surface_z && hero.in_water_frames <= 0) { @@ -185,7 +188,7 @@ void update_hero_ground_contact(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == 1 || + if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = HH.moby; From 225a840197d6b8f410279ea8006825f541b1dc4e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:51:06 +0000 Subject: [PATCH 1020/1502] decomp: clarify names in hero_update_hop_movement domain_0_value_10 -> HERO_STATE_PACK_JUMP: Source snapshot d8ab05c8bdef330a6ba6409e8125f5625c9eb8c013a891f69ddfe6bf34bc4da5 assigns state = hero.state.current. Retail 0x00235c20 establishes hero base 0x0013f350 and 0x00235c30 loads a0 from hero+0x2084 (0x001413d4 in original Ghidra), proving this selector is the current-state ID domain HeroStateId in include/rnc/hero/hero_state.h, not hero.state.control_mode at +0x208c. 0x00235c14/0x00235c34 compare that loaded current state with 10; 0x00235c54-0x00235c74 builds/copies movement impulse into momentum and copies flat speed to ground speed. Reuse canonical HeroStateId member HERO_STATE_PACK_JUMP=10. domain_1_value_16 -> HERO_STATE_PACK_LONG_JUMP: Source snapshot d8ab05c8bdef330a6ba6409e8125f5625c9eb8c013a891f69ddfe6bf34bc4da5 assigns state = hero.state.current. Retail 0x00235c20 establishes hero base 0x0013f350 and 0x00235c30 loads a0 from hero+0x2084 (0x001413d4 in original Ghidra), proving this selector is the current-state ID domain HeroStateId in include/rnc/hero/hero_state.h, not hero.state.control_mode at +0x208c. 0x00235c78-0x00235c7c compares the same current-state load with 16. The selected branch reads long_jump_speed at hero+0x3f4, adjusts jump gravity after a timer threshold, and rebuilds forward velocity at 0x00235d24-0x00235d38. Reuse canonical HERO_STATE_PACK_LONG_JUMP=16. domain_2_value_28 -> HERO_STATE_LEDGE_JUMP: Source snapshot d8ab05c8bdef330a6ba6409e8125f5625c9eb8c013a891f69ddfe6bf34bc4da5 assigns state = hero.state.current. Retail 0x00235c20 establishes hero base 0x0013f350 and 0x00235c30 loads a0 from hero+0x2084 (0x001413d4 in original Ghidra), proving this selector is the current-state ID domain HeroStateId in include/rnc/hero/hero_state.h, not hero.state.control_mode at +0x208c. 0x00235c80 supplies 28 and 0x00235d44 compares it to the loaded current state. 0x00235dbc-0x00235e80 gates ledge_jump_speed updates by animation frames 13..30 and constructs velocity XY from it and hero yaw. Reuse canonical HERO_STATE_LEDGE_JUMP=28. domain_3_value_11 -> HERO_STATE_HIGH_JUMP: Source snapshot d8ab05c8bdef330a6ba6409e8125f5625c9eb8c013a891f69ddfe6bf34bc4da5 assigns state = hero.state.current. Retail 0x00235c20 establishes hero base 0x0013f350 and 0x00235c30 loads a0 from hero+0x2084 (0x001413d4 in original Ghidra), proving this selector is the current-state ID domain HeroStateId in include/rnc/hero/hero_state.h, not hero.state.control_mode at +0x208c. 0x00235d48 subtracts 11 from the current-state load and 0x00235e84 tests the unsigned result below 2, implementing the source state==11 || state==12. The same field is reloaded at 0x00235ef8 and compared with 11 at 0x00235ef4-0x00235efc, corresponding to the existing HERO_STATE_HIGH_JUMP check and high-jump drift adjustment. Reuse canonical HERO_STATE_HIGH_JUMP=11. domain_4_value_12 -> HERO_STATE_STORED_HEADING_JUMP: Source snapshot d8ab05c8bdef330a6ba6409e8125f5625c9eb8c013a891f69ddfe6bf34bc4da5 assigns state = hero.state.current. Retail 0x00235c20 establishes hero base 0x0013f350 and 0x00235c30 loads a0 from hero+0x2084 (0x001413d4 in original Ghidra), proving this selector is the current-state ID domain HeroStateId in include/rnc/hero/hero_state.h, not hero.state.control_mode at +0x208c. 0x00235d48 subtracts 11 from the current-state load and 0x00235e84 tests the unsigned result below 2, selecting exactly states 11 and 12. This branch copies takeoff_yaw at +0x43c into move_yaw at +0x180 and builds drift/takeoff-heading velocity; only state 11 gets the extra apex-dependent adjustment. The proven current-state domain supplies canonical HERO_STATE_STORED_HEADING_JUMP=12. domain_5_value_17 -> HERO_STATE_REPEATABLE_JUMP: Source snapshot d8ab05c8bdef330a6ba6409e8125f5625c9eb8c013a891f69ddfe6bf34bc4da5 assigns state = hero.state.current. Retail 0x00235c20 establishes hero base 0x0013f350 and 0x00235c30 loads a0 from hero+0x2084 (0x001413d4 in original Ghidra), proving this selector is the current-state ID domain HeroStateId in include/rnc/hero/hero_state.h, not hero.state.control_mode at +0x208c. 0x00236030-0x00236034 compares the current-state load with 17. 0x0023603c-0x00236050 restores saved move heading/direction from hero+0x470; after nine scaled frames, 0x002360c4-0x00236158 sets or adds frame_time*4.9 movement along that direction. Reuse canonical current-state member HERO_STATE_REPEATABLE_JUMP=17. domain_6_value_45 -> HERO_STATE_ITEM_RELEASE_FALL: Source snapshot d8ab05c8bdef330a6ba6409e8125f5625c9eb8c013a891f69ddfe6bf34bc4da5 assigns state = hero.state.current. Retail 0x00235c20 establishes hero base 0x0013f350 and 0x00235c30 loads a0 from hero+0x2084 (0x001413d4 in original Ghidra), proving this selector is the current-state ID domain HeroStateId in include/rnc/hero/hero_state.h, not hero.state.control_mode at +0x208c. 0x00236038 supplies 45 and 0x0023616c compares it with the same current-state load. 0x002361bc-0x002361ec springs a temporary hero yaw toward move_yaw and applies its yaw delta through rotate_hero_about_fixed_local_pivot before common airborne steering. Reuse canonical current-state member HERO_STATE_ITEM_RELEASE_FALL=45; this movement handler need not implement the item-release lifecycle. --- src/overlays/shared/hero/hero_update_hop_movement.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/hero/hero_update_hop_movement.c b/src/overlays/shared/hero/hero_update_hop_movement.c index f1b48b4f2d..70e8d08012 100644 --- a/src/overlays/shared/hero/hero_update_hop_movement.c +++ b/src/overlays/shared/hero/hero_update_hop_movement.c @@ -81,11 +81,11 @@ void hero_update_hop_movement(void) { s32 state; state = hero.state.current; - if (state == 10) { + if (state == HERO_STATE_PACK_JUMP) { build_scaled_hero_move_impulse(0.7f, ED6C * 0.0f); qcopy(&hero.motion.momentum, &hero.move_impulse); hero.ground_speed = hero.motion.flat_speed; - } else if (state == 16) { + } else if (state == HERO_STATE_PACK_LONG_JUMP) { if (scale_game_frames(0x36) < hero.state_timer) { approach_value(ED70 * 25.0f, ED70 * 7.0f, &hero.jump_gravity); } @@ -97,7 +97,7 @@ void hero_update_hop_movement(void) { speed_step(ED70 * 44.0f, ED70 * 45.0f); set_gravity_relative_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, 0.0f); add_hero_forward_offset(&hero.motion.velocity, &hero.motion.velocity, hero.ground_speed); - } else if (state == 0x1C) { + } else if (state == HERO_STATE_LEDGE_JUMP) { if (scale_game_frames(0x28) < hero.state_timer) { turn_to(0, ED64 * 0.04f, ED64 * 0.2f, ED6C * 15.009831f); steer_hero_planar_velocity(ED70 * 20.0f); @@ -111,7 +111,7 @@ void hero_update_hop_movement(void) { } hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * hero.ledge_jump_speed; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * hero.ledge_jump_speed; - } else if (state == 11 || state == 12) { + } else if (state == HERO_STATE_HIGH_JUMP || state == HERO_STATE_STORED_HEADING_JUMP) { hero.motion.move_yaw = hero.takeoff_yaw; turn_to(0, ED64 * 0.04f, ED64 * 0.2f, ED6C * 6.981317f); if (hero.unk450 != 3) { @@ -135,7 +135,7 @@ void hero_update_hop_movement(void) { hero.motion.velocity.f[1] += fast_sin(hero.takeoff_yaw) * velocity_scale_or_yaw_delta; build_scaled_hero_move_impulse(0.7f, ED6C * 0.0f); qcopy(&hero.motion.momentum, &hero.move_impulse); - } else if (state == 0x11) { + } else if (state == HERO_STATE_REPEATABLE_JUMP) { hero.motion.move_yaw = hero.unk470.f[3]; qcopy(&hero.motion.move_dir, &hero.unk470); if (scale_game_frames(9) < hero.state_timer) { @@ -154,7 +154,7 @@ void hero_update_hop_movement(void) { } hero.ground_speed = hero.motion.flat_speed; } else { - if (state == 0x2D) { + if (state == HERO_STATE_ITEM_RELEASE_FALL) { x = hero.motion.rot.f[2]; hero.motion.yaw_error = spring_angle(&x, &hero.motion.yaw_rate, From ff1c2727cbecaa69c235f9ac8a8094ef2e31feef Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:51:06 +0000 Subject: [PATCH 1021/1502] decomp: clarify names in update_hero_ground_contact domain_0_value_0 -> GROUND_MATERIAL_WATER: Retail 0x002100e8-0x002100f8 stores collision_hit_material into hero+0x12e0 (hero.ground_type) and tests zero. The zero branch at 0x002100fc-0x00210128 resolves water_surface_z and starts in_water_frames when the hero position is below it, then probes underlying ground. The authoritative same-file apply_hero_ground_material_effects explicitly defines GROUND_MATERIAL_WATER=0 for saved hero.ground_type and computes water depth/wading. This proves the material domain and established name, independently of equal-valued state enums. domain_3_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: Retail 0x0021037c-0x00210384 reads hero+0x20b3 (hero.gravity_mode) and compares with 1 to accept near-ground contact. The same field is selected at 0x0021041c-0x00210420; its mode-1 branch at 0x00210460-0x0021047c copies hero.ground_normal into gravity_dir and scales it by -1. Retail 0x002102cc-0x002102d0 establishes ground_normal from the normalized collision normal. The existing same-function switch and supplied HeroGravityMode domain identify this exact selector/member as HERO_GRAVITY_OPPOSITE_GROUND_NORMAL=1. --- src/overlays/l16/hero/apply_hero_ground_material_effects.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l16/hero/apply_hero_ground_material_effects.c b/src/overlays/l16/hero/apply_hero_ground_material_effects.c index 2c572aff6a..4f7032ded2 100644 --- a/src/overlays/l16/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l16/hero/apply_hero_ground_material_effects.c @@ -192,6 +192,9 @@ extern CollisionHit HH __asm__("D_L16_00174240") NOT_SDA; void update_hero_ground_contact(void) __asm__("FUN_L16_0020ffb0"); void update_hero_ground_contact(void) { + enum { + GROUND_MATERIAL_WATER = 0 + }; V_u collision_ray_endpoint, ground_probe_endpoint, ground_offset_or_angles, side_probe_endpoint, unused_side_probe_endpoint, probe_surface_angles, normalized_hit_normal; f32 f; @@ -236,7 +239,7 @@ void update_hero_ground_contact(void) { } hero.ground_sound_class = collision_sound_class; hero.ground_type = collision_hit_material(); - if (hero.ground_type == 0) { + if (hero.ground_type == GROUND_MATERIAL_WATER) { hero.water_surface_z = resolve_camera_surface_height(D_L16_00174260, (u8 *)&hero.water_surface_normal); if (hero.motion.pos.f[2] < hero.water_surface_z && hero.in_water_frames <= 0) { @@ -290,7 +293,7 @@ void update_hero_ground_contact(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == 1 || + if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = HH.moby; From fdaa9d7cda68b10c0f95054fa91783c68ccfa405 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:51:06 +0000 Subject: [PATCH 1022/1502] decomp: clarify names in EnableInterrupts domain_0_value_0 -> INTERRUPT_ENABLE_BIT_CLEAR: At 0x0011d6a8 mfc0 saves COP0 Status; 0x0011d6ac loads 0x10000 and 0x0011d6b0 masks the saved value to bit 16. EI at 0x0011d6b4 enables interrupts after that snapshot; sltu v0,zero,v0 at 0x0011d6bc returns whether the saved bit was nonzero. Thus zero in source status != 0 means INTERRUPT_ENABLE_BIT_CLEAR. Prepared SyncDCache context uses this exact name for the identical CpuReadStatus() & 0x10000 comparison before restoring with EnableInterrupts. --- src/sdk/interrupts/enable_interrupts.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/interrupts/enable_interrupts.c b/src/sdk/interrupts/enable_interrupts.c index 80fc36cab2..cdac4d7bce 100644 --- a/src/sdk/interrupts/enable_interrupts.c +++ b/src/sdk/interrupts/enable_interrupts.c @@ -2,10 +2,13 @@ #include "rnc/sdk/kernel.h" s32 EnableInterrupts(void) { + enum { + INTERRUPT_ENABLE_BIT_CLEAR = 0 + }; u32 status; status = CpuReadStatus(); status &= 0x10000; CpuEnableInt(); - return status != 0; + return status != INTERRUPT_ENABLE_BIT_CLEAR; } From bcbd300a5d8a503fdc06ad1f444813c12627eca7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:52:58 +0000 Subject: [PATCH 1023/1502] decomp: clarify names in update_hero_ground_contact_and_gravity domain_0_value_0 -> GROUND_MATERIAL_WATER: The selector is hero.ground_type, assigned collision_hit_material() at retail 0x00232ef8-0x00232f08 (hero+0x12E0). Its zero branch at 0x00232f04-0x00232f58 resolves water_surface_z, checks hero Z against it and sets in_water_frames before re-querying with mask 0x24. Original Ghidra sRam00140630 follows the same flow. The authoritative source update_hero_ground_material_effects saves this exact field and already names value 0 GROUND_MATERIAL_WATER, computing water_depth and wading; reuse that proven material-domain spelling. domain_3_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: Retail 0x0023315c-0x00233164 compares byte hero+0x20B3 with 1 while deciding air_frames reset. The identical byte is loaded at 0x002331fc and tested at 0x00233200; its value-1 branch 0x00233240-0x0023325c copies normalized ground_normal (hero+0x270) into gravity_dir (hero+0x290) and scales by -1. Original Ghidra bRam00141403 agrees. Authoritative source identifies both selectors as hero.gravity_mode and already uses HERO_GRAVITY_OPPOSITE_GROUND_NORMAL in the latter switch, proving this comparison belongs to the shared HeroGravityMode enum rather than HeroStateId or vehicle mode. --- src/overlays/shared/hero/hero_frame_update.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index 39c26fa9b4..7badf30e5a 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -1142,6 +1142,9 @@ extern CollisionHit HH __asm__("D_L01_001742C0") NOT_SDA; void update_hero_ground_contact_and_gravity(void) __asm__("FUN_L01_00232dc0"); void update_hero_ground_contact_and_gravity(void) { + enum { + GROUND_MATERIAL_WATER = 0 + }; V collision_ray_end, ground_ray_start, ground_delta_or_angles, side_ray_start, unused_side_probe_point, side_hit_angles, normalized_side_hit_normal; f32 f; @@ -1185,7 +1188,7 @@ void update_hero_ground_contact_and_gravity(void) { } hero.ground_sound_class = collision_sound_class; hero.ground_type = collision_hit_material(); - if (hero.ground_type == 0) { + if (hero.ground_type == GROUND_MATERIAL_WATER) { hero.water_surface_z = resolve_camera_surface_height(D_L01_001742E0, (u8 *)&hero.water_surface_normal); if (hero.motion.pos.f[2] < hero.water_surface_z && hero.in_water_frames <= 0) { @@ -1234,7 +1237,7 @@ void update_hero_ground_contact_and_gravity(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == 1 || + if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = HH.moby; From b7f7668879810e6aa5b50623129ebc3b4475366e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:54:38 +0000 Subject: [PATCH 1024/1502] decomp: clarify names in hydrodisplacer_update domain_0_value_1 -> HYDRODISPLACER_WAIT_FOR_ANIMATION_FLAG: Retail 002dfaf4-002dfafc stores 1 to entity+0x20 after initialization. The same byte is the outer switch selector at 002dfabc; its case 1 at 002dfb00-002dfb14 waits for anim_flags bit 2. Reuse the existing local moby->state enum member. domain_1_value_2 -> HYDRODISPLACER_WAIT_FOR_ACTIVATION: Retail 002dfb00-002dfb14 tests entity+0x70 bit 2 and stores 2 to entity+0x20. That byte selects the outer switch; case 2 at 002dfb18-002dfb9c checks input, ground class and activation gates. This is the existing local WAIT_FOR_ACTIVATION state. domain_2_value_3 -> HYDRODISPLACER_WAIT_FOR_HERO_FLAG: Retail 002dfb88-002dfb9c passes activation/control-mode gates and stores 3 to entity+0x20 before hero_set_state(0x38,0). The same outer switch byte dispatches case 3, whose 002dfc08-002dfc10 waits for hero animation flag bit 2. Reuse existing WAIT_FOR_HERO_FLAG. domain_3_value_4 -> HYDRODISPLACER_CAMERA_TRANSITION: Retail 002dfcc0-002dfcdc validates both platform camera indices, clears command at entity+0xBC and stores 4 to entity+0x20, then mounts the camera and stores node indices. Outer state case 4 dispatches camera command substates at 002dfdac onward. Reuse existing CAMERA_TRANSITION. domain_4_value_5 -> HYDRODISPLACER_WAIT_FOR_TIMER: Retail 002dfd30-002dfd48 stores 5 to entity+0x20 and initializes the pvars countdown from scaled tank fill time when camera indices are unavailable. Outer switch case 5 at 002e0148-002e0184 tests that countdown and cleans up on completion. Reuse existing WAIT_FOR_TIMER. domain_5_value_2 -> HYDRODISPLACER_WAIT_FOR_ACTIVATION: Retail 002e0094-002e00b0 waits for fade scalar zero in camera command substate 2, then stores 2 to entity+0x20 and calls hero_set_state(0x3A,0). The destination is the outer moby state byte, not command+0xBC; its case 2 runs activation gates at 002dfb18 onward. Reuse WAIT_FOR_ACTIVATION. domain_6_value_2 -> HYDRODISPLACER_WAIT_FOR_ACTIVATION: Retail 002e0168-002e0184 calls the countdown helper or handles ground loss, performs end_hydrodisplacer_interaction and stores 2 to entity+0x20. This is the outer switch selector read at 002dfabc, whose case 2 tests activation input and platform gates. Reuse existing WAIT_FOR_ACTIVATION. --- src/overlays/shared/props/hydrodisplacer.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/props/hydrodisplacer.c b/src/overlays/shared/props/hydrodisplacer.c index f948809d50..bfd0f7a2c8 100644 --- a/src/overlays/shared/props/hydrodisplacer.c +++ b/src/overlays/shared/props/hydrodisplacer.c @@ -151,11 +151,11 @@ void hydrodisplacer_update(Moby *moby) { switch (moby->state) { case HYDRODISPLACER_INITIALIZE: allocate_voice_for_target_entry(0, 0, moby); - moby->state = 1; + moby->state = HYDRODISPLACER_WAIT_FOR_ANIMATION_FLAG; break; case HYDRODISPLACER_WAIT_FOR_ANIMATION_FLAG: if (moby->anim_flags & 2) { - moby->state = 2; + moby->state = HYDRODISPLACER_WAIT_FOR_ACTIVATION; } break; case HYDRODISPLACER_WAIT_FOR_ACTIVATION: @@ -171,7 +171,7 @@ void hydrodisplacer_update(Moby *moby) { if (func_L00_002E1790_2E0E50(moby) == 0 || (unsigned int)hero.state.control_mode >= 2) { break; } - moby->state = 3; + moby->state = HYDRODISPLACER_WAIT_FOR_HERO_FLAG; hero_set_state(0x38, 0); if (hero.hydro_tank_full != 0) { set_hero_animation(0x83, 0, func_001F9850_2E0E50(6)); @@ -205,7 +205,7 @@ void hydrodisplacer_update(Moby *moby) { } if (platform[1] != -1 && platform[2] != -1) { moby->command = 0; - moby->state = 4; + moby->state = HYDRODISPLACER_CAMERA_TRANSITION; hydrodisplacer_interaction_state->f10 = 0.0f; jet_mount(g_debug_camera.position, g_debug_camera.angles, 1, 0, 0); if (hero.hydro_tank_full != 0) { @@ -217,7 +217,7 @@ void hydrodisplacer_update(Moby *moby) { } break; } - moby->state = 5; + moby->state = HYDRODISPLACER_WAIT_FOR_TIMER; hydrodisplacer_interaction_state->i0 = func_001FA898_2E0E50(scale_time(hydrodisplacer_tank_fill_time_macro)); if (hero.hydro_tank_full == 0) { @@ -311,7 +311,7 @@ void hydrodisplacer_update(Moby *moby) { approach_value(&fade_level_macro, 0.0f, 1.0f / func_001F9850_2E0E50(15)); return; } - moby->state = 2; + moby->state = HYDRODISPLACER_WAIT_FOR_ACTIVATION; hero_set_state(0x3A, 0); if (hero.hydro_tank_full != 0) { set_hero_animation(0x48, 0, func_001F9850_2E0E50(6)); @@ -327,7 +327,7 @@ void hydrodisplacer_update(Moby *moby) { break; } end_hydrodisplacer_interaction(moby); - moby->state = 2; + moby->state = HYDRODISPLACER_WAIT_FOR_ACTIVATION; break; } } From 2c7da258add871a31721e06fb9f6c61c1163ce7f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:54:38 +0000 Subject: [PATCH 1025/1502] decomp: clarify names in update_hero_ground_contact domain_1_value_13 -> GROUND_MATERIAL_SINK_TRIGGER: Source SHA-256 6e87e2c0a17e80ef7eebd3d78c88fb023d831199bf8b6a6cdb5f250e05ba71f4 already defines GROUND_MATERIAL_SINK_TRIGGER=0xD in process_hero_ground_material_effects for saved hero.ground_type; that branch sets selector_13, whose descending surface-entry path calls hero_set_state(HERO_STATE_SINK,1). Assigned retail 0x002217d8-0x002217e8 stores collision_hit_material() into hero+0x12e0; 0x00221880-0x002218c8 compares the same field with 13, records HH.point.z as water_surface_z and probes below the surface. This is the same ground-material domain, not HeroStateId. domain_4_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: Retail 0x00221a88-0x00221a90 loads hero+0x20b3 and compares it with 1 to permit grounding on steep surfaces. The identical byte selector at 0x00221b28-0x00221b2c dispatches value 1 to 0x00221b6c-0x00221b88, copying the normalized ground normal and scaling it by -1 into gravity_dir. Authoritative C identifies both reads as hero.gravity_mode and already labels that switch case HERO_GRAVITY_OPPOSITE_GROUND_NORMAL, the canonical value 1 member of HeroGravityMode in include/rnc/hero/hero_state.h. --- src/overlays/l02/hero/update_hero_state_motion.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l02/hero/update_hero_state_motion.c b/src/overlays/l02/hero/update_hero_state_motion.c index fcc916581b..d9ab8ad13a 100644 --- a/src/overlays/l02/hero/update_hero_state_motion.c +++ b/src/overlays/l02/hero/update_hero_state_motion.c @@ -336,6 +336,9 @@ extern CollisionHit HH __asm__("D_L02_00174440") NOT_SDA; void update_hero_ground_contact(void) __asm__("FUN_L02_002216a0"); void update_hero_ground_contact(void) { + enum { + GROUND_MATERIAL_SINK_TRIGGER = 0xD + }; V collision_ray_end, collision_ray_start, ground_geometry_scratch, probe_ray_start, unused_probe_point, probe_surface_angles, normalized_probe_hit_normal; f32 f; @@ -395,7 +398,7 @@ void update_hero_ground_contact(void) { } hero.ground_sound_class = collision_sound_class; } - if (hero.ground_type == 0xD) { + if (hero.ground_type == GROUND_MATERIAL_SINK_TRIGGER) { hero.water_surface_z = HH.point.f[2]; collision_ray_start.f[2] = HH.point.f[2] - 0.01f; if (collision_line(&collision_ray_start, &collision_ray_end, 4, (s32)hero.moby, 0) == 0) { @@ -436,7 +439,7 @@ void update_hero_ground_contact(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == 1 || + if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = HH.moby; From b650b8f9ef70b81519741891183cdf52aae98fd8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:54:38 +0000 Subject: [PATCH 1026/1502] decomp: clarify names in update_fleet_beam domain_1_value_2 -> BEAM_UPDATE_OSCILLATING: This assignment targets beam_moby->state, the same byte at s4+0x20 read at 0x002a8de0 and dispatched at 0x002a8e18. The +0x44 endpoint branch computes the distance-scaled interpolation step at 0x002a8ec8-0x002a8ee8 and stores state 2 at 0x002a8ef0. Its existing BEAM_UPDATE_OSCILLATING case advances/reverses the fraction at 0x002a8fe4-0x002a9028 and interpolates beam position at 0x002a908c. Reuse the existing function-local member of this exact selector domain. domain_2_value_2 -> BEAM_UPDATE_OSCILLATING: The alternate +0x68 endpoint branch at retail 0x002a8e98-0x002a8ec4 joins the same interpolation-step computation and sb state=2 at 0x002a8ef0; original Ghidra joins at LAB_002a8ec8. This writes the same Moby state byte dispatched into existing BEAM_UPDATE_OSCILLATING, which bounds and reverses the interpolation fraction and uses the alternate endpoint at 0x002a9058. Reuse the existing local enum member, not a numerically equal hero-domain constant. domain_3_value_1 -> BEAM_UPDATE_STATIONARY: When both endpoint indices at pvars+0x44 and +0x68 equal -1, retail 0x002a8e9c branches to 0x002a8ef4, storing s0=1 into the same beam state byte s4+0x20. Dispatch at 0x002a8df4 sends state 1 to 0x002a8fa0, the existing BEAM_UPDATE_STATIONARY case. That branch checks hero clip-volume membership and gates shared effects without interpolating the Moby position. This proves reuse of the existing beam selector member. --- src/overlays/l17/mobys/fleet_beam.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l17/mobys/fleet_beam.c b/src/overlays/l17/mobys/fleet_beam.c index 9997480e9c..f34bce0c39 100644 --- a/src/overlays/l17/mobys/fleet_beam.c +++ b/src/overlays/l17/mobys/fleet_beam.c @@ -127,14 +127,14 @@ void fleet_beam_update(struct Moby *beam_moby) { qcopy(beam_vars, &beam_moby->pos); beam_vars->unk54 = beam_vars->unk48 * frame_time / fast_vec_dist(beam_vars, D_L17_001600EC + (k << 7) + 0x30); - beam_moby->state = 2; + beam_moby->state = BEAM_UPDATE_OSCILLATING; } else if ((j = beam_vars->unk68) != -1) { qcopy(beam_vars, &beam_moby->pos); beam_vars->unk54 = beam_vars->unk48 * frame_time / fast_vec_dist(beam_vars, D_L17_0015FFD0[2] + (j << 8) + 0x10); - beam_moby->state = 2; + beam_moby->state = BEAM_UPDATE_OSCILLATING; } else { - beam_moby->state = 1; + beam_moby->state = BEAM_UPDATE_STATIONARY; } beam_vars->unk60 = 0; beam_vars->unk4C = 0.1f; From 508a71a4029b9848b57911f984f0ea98cc6ba912 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:54:38 +0000 Subject: [PATCH 1027/1502] decomp: clarify names in elevator_with_button_update domain_0_value_3 -> ELEVATOR_MOVE_TO_BOTTOM: 0031575c-0031576c initializes this elevator's state byte at s2+0x20 to 3; the same byte selects the local elevator switch, whose state 3 drives progress to zero/bottom at 00315910-0031595c. domain_10_value_4 -> ELEVATOR_WAIT_AT_TOP: 00315b14-00315b20 selects 4 when the rider leaves return-wait state 6/top. State 6 was selected on top arrival at 00315a60-00315a70; the same elevator state field drives the local enum switch. domain_11_value_7 -> ELEVATOR_WAIT_TO_RETURN_FROM_BOTTOM: 00315c1c-00315c34 compares the elevator state byte with 7 after timer completion and grounded centered-rider checks, then selects move-to-top 2, consistent with returning from bottom. domain_12_value_2 -> ELEVATOR_MOVE_TO_TOP: 00315c24-00315c34 selects elevator state 2 from return-wait-at-bottom 7 after rider gates. 00315910-0031595c proves state 2 targets progress 1 and therefore top height. domain_13_value_3 -> ELEVATOR_MOVE_TO_BOTTOM: 00315c24-00315c3c selects elevator state 3 from return-wait-at-top 6 after rider gates. The state-2 test at 00315910-00315928 leaves target zero for state 3, giving bottom height. domain_14_value_5 -> ELEVATOR_WAIT_AT_BOTTOM: 00315d44-00315d5c compares this elevator's state byte with 5 and saves upward movement 2 in command before fade entry. 00315e08-00315e90 also recalls state 5 toward top, agreeing with local wait-at-bottom. domain_15_value_1 -> ELEVATOR_FADE_BEFORE_CAMERA_MOUNT: 00315d64-00315d70 assigns elevator state 1 and clears fade. State 1 at 00315770-003157f0 raises fade to 1, builds the lift camera view, mounts the camera, and restores the saved movement state. domain_16_value_4 -> ELEVATOR_WAIT_AT_TOP: 00315d74-00315d7c compares elevator state with 4; 00315d9c-00315e04 then checks hero height against bottom and selects downward movement 3. This is the same local enum state used after top arrival. domain_17_value_3 -> ELEVATOR_MOVE_TO_BOTTOM: 00315d9c-00315e04 checks hero ground height near bottom and horizontal recall distance, clears command and selects state 3 from wait-at-top 4. State 3 moves progress to zero/bottom at 00315910-0031595c. domain_18_value_5 -> ELEVATOR_WAIT_AT_BOTTOM: 00315e08 compares elevator state with 5 before testing hero height near top at 00315e28-00315e44 and recalling upward. This matches existing local state 5 selected on bottom arrival at 00315a7c. domain_19_value_2 -> ELEVATOR_MOVE_TO_TOP: 00315e28-00315e90 checks hero height near top and horizontal recall distance, clears command and writes state 2 from wait-at-bottom 5. 00315910-0031595c proves state 2 moves progress toward top. domain_1_value_2 -> ELEVATOR_MOVE_TO_TOP: 00315910-00315928 compares the elevator state byte s2+0x20 with 2 and selects target progress 1; 0031593c-0031595c maps that progress to top height, matching the existing local enum. domain_2_value_2 -> ELEVATOR_MOVE_TO_TOP: 00315a60-00315a70 tests the same elevator state byte against 2 after endpoint completion, distinguishing top arrival and selecting return-wait state 6; progress 1 means top at 0031593c-0031595c. domain_3_value_6 -> ELEVATOR_WAIT_TO_RETURN_FROM_TOP: 00315a54-00315a70 assigns 6 on commanded completion of state 2/top. The existing elevator switch handles 6 with timer and rider gates at 00315aac-00315b30 before return movement. domain_4_value_7 -> ELEVATOR_WAIT_TO_RETURN_FROM_BOTTOM: 00315a54-00315a68 assigns 7 on commanded completion of state 3, whose target is bottom/zero at 00315910-0031595c. The local enum names this timer/rider-gated return wait. domain_5_value_2 -> ELEVATOR_MOVE_TO_TOP: 00315a74-00315a84 tests elevator state at s2+0x20 against 2 on uncommanded endpoint completion and selects wait-at-top 4; state 2 targets progress 1/top at 00315910-0031595c. domain_6_value_4 -> ELEVATOR_WAIT_AT_TOP: 00315a74-00315a84 selects state 4 after uncommanded state-2/top completion. 00315d74-00315e04 recalls this state toward bottom when hero ground height is near bottom, matching the existing elevator enum. domain_7_value_5 -> ELEVATOR_WAIT_AT_BOTTOM: 00315a74-00315a7c selects state 5 after uncommanded bottom arrival. 00315e08-00315e90 recalls this state toward top when hero ground height is near top, matching the local elevator enum. domain_8_value_7 -> ELEVATOR_WAIT_TO_RETURN_FROM_BOTTOM: 00315b14-00315b28 compares elevator state s2+0x20 with 7 on rider departure and changes it to wait-at-bottom 5; commanded bottom arrival selected 7 at 00315a54-00315a68. domain_9_value_5 -> ELEVATOR_WAIT_AT_BOTTOM: 00315b14-00315b28 selects 5 when the rider leaves state 7, which is entered after commanded bottom arrival at 00315a54-00315a68. This reuses the existing local wait-at-bottom member. --- src/overlays/l05/mobys/elevator_with_button.c | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/overlays/l05/mobys/elevator_with_button.c b/src/overlays/l05/mobys/elevator_with_button.c index ddde666feb..143e365aae 100644 --- a/src/overlays/l05/mobys/elevator_with_button.c +++ b/src/overlays/l05/mobys/elevator_with_button.c @@ -95,7 +95,7 @@ void elevator_with_button_update(struct Moby *moby) { elevator_vars->phase = random_angle_radians(); elevator_vars->sound = -1; elevator_vars->base_yaw = moby->rot.z; - moby->state = 3; + moby->state = ELEVATOR_MOVE_TO_BOTTOM; break; case ELEVATOR_FADE_BEFORE_CAMERA_MOUNT: D_0014162A = elevator_vars->marker; @@ -127,7 +127,7 @@ void elevator_with_button_update(struct Moby *moby) { progress_speed_limit = frame_time; max_speed = frame_time_sq; } - target = moby->state == 2 ? 1.0f : 0.0f; + target = moby->state == ELEVATOR_MOVE_TO_TOP ? 1.0f : 0.0f; advance_accelerated_scalar(&elevator_vars->progress, &elevator_vars->speed, target, @@ -157,16 +157,16 @@ void elevator_with_button_update(struct Moby *moby) { elevator_vars->speed = -0.00125f; } if (moby->command) { - if (moby->state == 2) { - moby->state = 6; + if (moby->state == ELEVATOR_MOVE_TO_TOP) { + moby->state = ELEVATOR_WAIT_TO_RETURN_FROM_TOP; } else { - moby->state = 7; + moby->state = ELEVATOR_WAIT_TO_RETURN_FROM_BOTTOM; } } else { - if (moby->state == 2) { - moby->state = 4; + if (moby->state == ELEVATOR_MOVE_TO_TOP) { + moby->state = ELEVATOR_WAIT_AT_TOP; } else { - moby->state = 5; + moby->state = ELEVATOR_WAIT_AT_BOTTOM; } } } @@ -183,10 +183,10 @@ void elevator_with_button_update(struct Moby *moby) { } if (hero.ground_moby != moby) { jet_end_mount(1); - if (moby->state == 7) { - moby->state = 5; + if (moby->state == ELEVATOR_WAIT_TO_RETURN_FROM_BOTTOM) { + moby->state = ELEVATOR_WAIT_AT_BOTTOM; } else { - moby->state = 4; + moby->state = ELEVATOR_WAIT_AT_TOP; } break; } @@ -205,10 +205,10 @@ void elevator_with_button_update(struct Moby *moby) { vector_distance_xy(&hero.motion.pos, &moby->pos) < 0.5f) { allocate_voice_for_target_entry(1, 0, moby); moby->glow_color = 0x80208020; - if (moby->state == 7) { - moby->state = 2; + if (moby->state == ELEVATOR_WAIT_TO_RETURN_FROM_BOTTOM) { + moby->state = ELEVATOR_MOVE_TO_TOP; } else { - moby->state = 3; + moby->state = ELEVATOR_MOVE_TO_BOTTOM; } } break; @@ -229,26 +229,26 @@ void elevator_with_button_update(struct Moby *moby) { place_marker_ring(moby); } moby->glow_color = 0x80208020; - if (moby->state == 5) { + if (moby->state == ELEVATOR_WAIT_AT_BOTTOM) { moby->command = 2; } else { moby->command = 3; } - moby->state = 1; + moby->state = ELEVATOR_FADE_BEFORE_CAMERA_MOUNT; elevator_vars->fade = 0.0f; - } else if (moby->state == 4) { + } else if (moby->state == ELEVATOR_WAIT_AT_TOP) { f32 dist = vector_distance_xy(&moby->pos, &hero.motion.pos); if (absolute_float(hero.ground_z.f - elevator_vars->bottom) < 2.0f && dist < 32.0f && dist > 5.0f) { moby->command = 0; - moby->state = 3; + moby->state = ELEVATOR_MOVE_TO_BOTTOM; } - } else if (moby->state == 5) { + } else if (moby->state == ELEVATOR_WAIT_AT_BOTTOM) { f32 dist = vector_distance_xy(&moby->pos, &hero.motion.pos); if (absolute_float(hero.ground_z.f - elevator_vars->top) < 2.0f && dist < 32.0f && dist > 5.0f) { moby->command = 0; - moby->state = 2; + moby->state = ELEVATOR_MOVE_TO_TOP; } } break; From 55bd6cd70fd9b154d071303497959dc62ee04d6b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:54:38 +0000 Subject: [PATCH 1028/1502] decomp: clarify names in devestator_ammo_update domain_0_value_1 -> AMMO_PICKUP_WAIT_FOR_COLLECTION: Retail 002c5400 loads pickup state byte +0x20 into v1; 002c5404-002c5408 compares it with 1 before shared physics. The same state byte indexes the switch at 002c556c-002c557c. SHA-bound C names that switch member AMMO_PICKUP_WAIT_FOR_COLLECTION=1, whose branch gates timer, velocity, hero reach and ammo capacity. domain_1_value_4 -> AMMO_PICKUP_RESTORE_SCALE: Retail 002c5400 loads the pickup state byte +0x20; 002c540c-002c5410 compares it with 4 before shared physics. This is the same selector as switch(pickup_moby->state), whose existing AMMO_PICKUP_RESTORE_SCALE=4 branch at 002c5b3c-002c5ba4 restores class scale and collision. domain_2_value_3 -> AMMO_PICKUP_PULSE_ALPHA: Retail 002c5414-002c5418 compares the pickup state byte loaded at 002c5400 with 3. The same byte selects the existing AMMO_PICKUP_PULSE_ALPHA=3 switch branch, where 002c59f4-002c5ac8 computes a periodic alpha target and stores the updated alpha byte +0x23. domain_3_value_1 -> AMMO_PICKUP_WAIT_FOR_COLLECTION: SHA-bound C case AMMO_PICKUP_INITIALIZE assigns pickup_moby->state=1. Retail 002c5b30 loads 1 and 002c5b38 stores it into the same +0x20 state byte used by the switch; its existing member AMMO_PICKUP_WAIT_FOR_COLLECTION=1 handles collection eligibility and ammo grant. domain_4_value_2 -> AMMO_PICKUP_COLLECTED: After add_ammo at 002c56dc and pickup-total accounting at 002c5788, retail 002c574c loads a2=2 and 002c578c stores it into pickup state +0x20. The exact C assignment therefore reuses existing AMMO_PICKUP_COLLECTED=2, whose branch moves the collected pickup toward hero body center and removes it on arrival. domain_5_value_3 -> AMMO_PICKUP_PULSE_ALPHA: On failed collection, retail 002c582c calls the pickup/hero helper and compares its result with -0.2; 002c5850 loads 3 and 002c585c stores it into pickup state +0x20. The same selector has existing AMMO_PICKUP_PULSE_ALPHA=3, whose branch at 002c59f4-002c5ac8 animates alpha periodically. domain_6_value_1 -> AMMO_PICKUP_WAIT_FOR_COLLECTION: In existing AMMO_PICKUP_PULSE_ALPHA, retail 002c5ad4 calls the pickup/hero helper, 002c5ae4 tests its result against zero, and 002c5af0 supplies 1 for the state store at 002c5b38. Exact C returns to state 1, the existing AMMO_PICKUP_WAIT_FOR_COLLECTION member of this same pickup state switch. domain_7_value_1 -> AMMO_PICKUP_WAIT_FOR_COLLECTION: In the pulse-alpha branch, retail 002c5af4-002c5b24 loads the pickup weapon index, compares weapon ammo count against capacity at vendor entry +0x0e, then 002c5b30-002c5b38 writes 1 into pickup state +0x20 when capacity remains. Exact C reuses existing AMMO_PICKUP_WAIT_FOR_COLLECTION=1. domain_8_value_1 -> AMMO_PICKUP_WAIT_FOR_COLLECTION: In existing AMMO_PICKUP_RESTORE_SCALE, retail 002c5b80-002c5b90 compares relative remaining scale with 0.01; 002c5b94 loads 1, 002c5b98 snaps scale to class scale, and 002c5b9c stores 1 into pickup state +0x20 before restoring collision. This returns to existing AMMO_PICKUP_WAIT_FOR_COLLECTION=1. --- src/overlays/shared/pickups/weapon_ammo.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/pickups/weapon_ammo.c b/src/overlays/shared/pickups/weapon_ammo.c index 2c89125abb..da72ed83ee 100644 --- a/src/overlays/shared/pickups/weapon_ammo.c +++ b/src/overlays/shared/pickups/weapon_ammo.c @@ -146,7 +146,7 @@ void devestator_ammo_update(struct Moby *pickup_moby) { pickup_vars = (AmmoPickup *)pickup_moby->pvars; FUN_001f9740_2c53c0(&pickup_vars->timer); state = pickup_moby->state; - if (state == 1 || state == 4 || state == 3) { + if (state == AMMO_PICKUP_WAIT_FOR_COLLECTION || state == AMMO_PICKUP_RESTORE_SCALE || state == AMMO_PICKUP_PULSE_ALPHA) { magnitude = FUN_001f9af0_2c53c0(&pickup_vars->velocity); if (magnitude != 0.0f) { qcopy(&position, &pickup_moby->pos); @@ -170,7 +170,7 @@ void devestator_ammo_update(struct Moby *pickup_moby) { } switch (pickup_moby->state) { case AMMO_PICKUP_INITIALIZE: - pickup_moby->state = 1; + pickup_moby->state = AMMO_PICKUP_WAIT_FOR_COLLECTION; break; case AMMO_PICKUP_WAIT_FOR_COLLECTION: { struct Hero *player; @@ -237,7 +237,7 @@ void devestator_ammo_update(struct Moby *pickup_moby) { } account_idx = pickup_vars->weapon; weapon_ammo_pickup_totals[account_idx] += weapon_ammo_counts[account_idx] - before; - pickup_moby->state = 2; + pickup_moby->state = AMMO_PICKUP_COLLECTED; pickup_moby->scale *= frame_scale_macro * 0.20000005f + 1.0f; clear_u64_value(&pickup_vars->velocity); elapsed = D_L00_0015F5CC_macro - D_L00_00161838_macro; @@ -253,7 +253,7 @@ void devestator_ammo_update(struct Moby *pickup_moby) { if (pickup_moby->alpha < 0xFF) ++pickup_moby->alpha; if (jet_distance(pickup_moby, hero.moby) <= -0.2f) { - pickup_moby->state = 3; + pickup_moby->state = AMMO_PICKUP_PULSE_ALPHA; pickup_vars->recovery_timer = FUN_001f96f8_2c53c0(60); } return; @@ -310,12 +310,12 @@ void devestator_ammo_update(struct Moby *pickup_moby) { approach_value(value_ptr, target, (float)(128 / random)); pickup_moby->alpha = FUN_001fa6d0_2c53c0(*value_ptr); if (jet_distance(pickup_moby, hero.moby) >= 0.0f) { - pickup_moby->state = 1; + pickup_moby->state = AMMO_PICKUP_WAIT_FOR_COLLECTION; return; } idx = pickup_vars->weapon; if (weapon_ammo_counts[idx] < D_L00_001C40B0[idx].hE) { - pickup_moby->state = 1; + pickup_moby->state = AMMO_PICKUP_WAIT_FOR_COLLECTION; } return; } @@ -329,7 +329,7 @@ void devestator_ammo_update(struct Moby *pickup_moby) { remaining = (target - current) / target; if (remaining < 0.01f) { pickup_moby->scale = target; - pickup_moby->state = 1; + pickup_moby->state = AMMO_PICKUP_WAIT_FOR_COLLECTION; pickup_moby->collision = pickup_moby->pclass->collision; } break; From 0a8ca949d410a22d503a81b218bff54a587829ed Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:54:38 +0000 Subject: [PATCH 1029/1502] decomp: clarify names in update_hero_ground_contact domain_0_value_0 -> HERO_GROUND_MATERIAL_WATER: Retail 0x00229788-0x00229798 stores collision_hit_material into hero+0x12E0 and tests zero; 0x0022979c-0x002297c8 resolves the surface height into hero.water_surface_z and starts in_water_frames when hero position is below it. At 0x002297cc-0x002297e8 it recasts through this surface with mask 0x24. Original Ghidra sRam00140630==0 and authoritative C agree; this selector is collision material, not HeroStateId. domain_1_value_13 -> HERO_GROUND_MATERIAL_SINK_SURFACE: Retail 0x00229830-0x00229878 compares hero+0x12E0, populated by collision_hit_material at 0x00229788-0x00229798, with 13, saves hit Z as water_surface_z, and recasts from hit Z minus 0.01. Authoritative same-file apply_hero_ground_material_response already names previous_ground_type 13 HERO_GROUND_MATERIAL_SINK_SURFACE: it copies hero.ground_type before clearing it, sets selector_13, and enters HERO_STATE_SINK when below that surface and descending. This proves the same ground-material domain and existing semantic constant. domain_3_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: Retail 0x002299ec-0x002299f4 loads hero+0x20B3 and compares 1 to permit grounding on steep surfaces. The identical byte selector is read at 0x00229a8c-0x00229a90; its value-1 branch at 0x00229ad0-0x00229aec copies normalized ground normal hero+0x270 to gravity_dir hero+0x290 and scales by -1. Authoritative source uses hero_lui.gravity_mode for both and already uses HERO_GRAVITY_OPPOSITE_GROUND_NORMAL in its switch, proving the supplied HeroGravityMode domain rather than state or vehicle mode. --- .../l06/hero/update_hero_motion_for_current_state.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l06/hero/update_hero_motion_for_current_state.c b/src/overlays/l06/hero/update_hero_motion_for_current_state.c index 045549d100..1cb0ce82d9 100644 --- a/src/overlays/l06/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l06/hero/update_hero_motion_for_current_state.c @@ -421,6 +421,10 @@ extern struct Hero hero_lui __asm__("D_0013F350") NOT_SDA; void update_hero_ground_contact(void) __asm__("FUN_L06_00229650"); void update_hero_ground_contact(void) { + enum { + HERO_GROUND_MATERIAL_WATER = 0, + HERO_GROUND_MATERIAL_SINK_SURFACE = 0xD + }; V collision_ray_end, ground_ray_start, ground_offset_or_angles, surface_probe_start, unused_surface_probe_point, hit_surface_angles, normalized_hit_normal; f32 f; @@ -464,7 +468,7 @@ void update_hero_ground_contact(void) { } hero_lui.ground_sound_class = ground_sound_class; hero_lui.ground_type = collision_hit_material(); - if (hero_lui.ground_type == 0) { + if (hero_lui.ground_type == HERO_GROUND_MATERIAL_WATER) { hero_lui.water_surface_z = resolve_camera_surface_height(D_L06_001745E0, (u8 *)&hero_lui + 0x280); if (hero_lui.motion.pos.f[2] < hero_lui.water_surface_z && hero_lui.in_water_frames <= 0) { @@ -479,7 +483,7 @@ void update_hero_ground_contact(void) { } hero_lui.ground_sound_class = ground_sound_class; } - if (hero_lui.ground_type == 0xD) { + if (hero_lui.ground_type == HERO_GROUND_MATERIAL_SINK_SURFACE) { hero_lui.water_surface_z = D_L06_001745E8; ground_ray_start.f[2] = D_L06_001745E8 - 0.01f; if (collision_line(&ground_ray_start, &collision_ray_end, 4, hero_lui.moby, 0) == 0) { @@ -512,7 +516,7 @@ void update_hero_ground_contact(void) { } if (hero_lui.ground_distance < 0.02f) { hero_lui.frames_off_ground.s = 0; - if (hero_lui.ground_slope.f <= 0.87266463f || hero_lui.gravity_mode == 1 || + if (hero_lui.ground_slope.f <= 0.87266463f || hero_lui.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero_lui.state.control_mode == 0x16) { hero_lui.air_frames.s = 0; hero_lui.last_landed_moby = HH.moby; From 50affa623c8abccfd38d77a75dfef107dac05224 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:56:25 +0000 Subject: [PATCH 1030/1502] decomp: clarify names in update_path_mover domain_0_value_0 -> PATH_MOVER_STATE_UNINITIALIZED: Retail 0x002abc6c loads the moby's byte at +0x20, identified by the authoritative C as moby->state; 0x002abc70 skips setup when nonzero. The zero branch 0x002abc78-0x002abd08 selects start_end, initializes normalized progress, copies the selected endpoint to moby->pos, clears wait/speed/rise, initializes voice to -1, and writes state 1. Thus zero denotes this path mover's uninitialized state, independently of command at moby+0xBC. domain_1_value_1 -> PATH_MOVER_STATE_INITIALIZED: Retail 0x002abce4 loads a0=1 and 0x002abcf8 stores that byte to moby+0x20 after endpoint placement and wait/speed/rise initialization (0x002abcd8-0x002abcf0). The next update's 0x002abc6c-0x002abc70 nonzero test bypasses this setup. This is the initialized state of update_path_mover, not the distinct command byte at +0xBC or a hero-state domain. --- src/overlays/l14/mobys/path_mover.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/path_mover.c b/src/overlays/l14/mobys/path_mover.c index 16818a0848..5ac5ea2cfd 100644 --- a/src/overlays/l14/mobys/path_mover.c +++ b/src/overlays/l14/mobys/path_mover.c @@ -68,6 +68,10 @@ void path_mover_update(struct Moby *moby) { PATH_MOVER_COMMAND_WAIT_AT_FIRST_POINT = 1, PATH_MOVER_COMMAND_TRAVERSE_PATH = 2 }; + enum { + PATH_MOVER_STATE_UNINITIALIZED = 0, + PATH_MOVER_STATE_INITIALIZED = 1 + }; PathMoverVars *path_mover_vars = (PathMoverVars *)moby->pvars; LevelPath *path; Vec4 orig; @@ -112,7 +116,7 @@ void path_mover_update(struct Moby *moby) { } qcopy(&orig, &moby->pos); fast_dec_timer_s16(&path_mover_vars->wait); - if (moby->state == 0) { + if (moby->state == PATH_MOVER_STATE_UNINITIALIZED) { f32 t; Vec4 *points; @@ -131,7 +135,7 @@ void path_mover_update(struct Moby *moby) { path_mover_vars->wait = 0; path_mover_vars->speed = 0.0f; path_mover_vars->rise = 0.0f; - moby->state = 1; + moby->state = PATH_MOVER_STATE_INITIALIZED; moby->update_dist = 0xFF; moby->draw_dist = 0xFF; path_mover_vars->voice = -1; From e9e33fc24c84fe66bf1987169a7b626b92b5b76f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:56:26 +0000 Subject: [PATCH 1031/1502] decomp: clarify names in update_heavy_gunship domain_0_value_2 -> HEAVY_GUNSHIP_FOLLOW_SECONDARY_PATH: The parent argument is preserved in s4 at 0x002e9b80; its state byte at +0x20 is read at 0x002e9bd8 and dispatches value 2 to 0x002e9ffc. Initialization copies follow[1].path point zero via pvars+0x40 at 0x002e9cc4-0x002e9cd0, then sb s0,0x20(s4) at 0x002e9cdc writes 2 (s0 loaded at 0x002e9bdc). The receiving branch uses pvars+0x30/+0x40 for secondary-path waypoints and movement. This is precisely the same moby->state domain already named HEAVY_GUNSHIP_FOLLOW_SECONDARY_PATH=2 in the authoritative function enum. domain_2_value_1 -> HEAVY_GUNSHIP_FOLLOW_PRIMARY_PATH: The state-3 branch at 0x002ea260 loads 1 and stores it to the parent s4+0x20 at 0x002ea268, then loads follow[0].path from pvars+0x10, copies its first point to the parent position, and faces its second point at 0x002ea26c-0x002ea298. The same state byte is dispatched for value 1 at 0x002e9bf8 to 0x002e9d08, which advances follow[0] waypoints and moves the parent. Thus this assignment enters the exact parent-state domain already named HEAVY_GUNSHIP_FOLLOW_PRIMARY_PATH=1, rather than a projectile or part state. --- src/overlays/l08/mobys/heavy_gunship.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l08/mobys/heavy_gunship.c b/src/overlays/l08/mobys/heavy_gunship.c index aa2ed89cc3..09ce48aadd 100644 --- a/src/overlays/l08/mobys/heavy_gunship.c +++ b/src/overlays/l08/mobys/heavy_gunship.c @@ -303,7 +303,7 @@ void heavy_gunship_update(struct Moby *moby) { moby->flags |= 0x4000; qcopy(&moby->pos, &swarm_vars->follow[1].path->points[0]); spawn_heavy_gunship_parts(moby); - moby->state = 2; + moby->state = HEAVY_GUNSHIP_FOLLOW_SECONDARY_PATH; moby->rot.z = fast_arc_tan(swarm_vars->follow[1].path->points[1].f[0] - moby->pos.x, swarm_vars->follow[1].path->points[1].f[1] - moby->pos.y); break; @@ -407,7 +407,7 @@ void heavy_gunship_update(struct Moby *moby) { case HEAVY_GUNSHIP_START_PRIMARY_PATH: { LevelPath *path; - moby->state = 1; + moby->state = HEAVY_GUNSHIP_FOLLOW_PRIMARY_PATH; path = swarm_vars->follow[0].path; qcopy(&moby->pos, &path->points[0]); moby->rot.z = From 15c381ff2fddf4070e66f3a046167f0d53e3c735 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:56:26 +0000 Subject: [PATCH 1032/1502] decomp: clarify names in update_hero_ground_contact_and_surface_slopes domain_5_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: Retail 0x00212bc0 loads byte hero+0x20B3 and 0x00212bc4-0x00212bc8 compares it with 1 to permit ground contact despite the slope limit. This is the same gravity selector loaded at 0x00212c60 and tested against 1 at 0x00212c64; its selected branch copies hero.ground_normal from hero+0x270 to gravity_dir at hero+0x290 (0x00212ca8-0x00212cac), then scales by -1 at 0x00212cbc. Original Ghidra bRam00141403 and the SHA-bound current C agree. Thus this comparison belongs to the existing HeroGravityMode domain and reuses its canonical HERO_GRAVITY_OPPOSITE_GROUND_NORMAL member, already used in this function's gravity switch. --- src/overlays/shared/hero/hero_switch_item.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index c2855f7ba2..d26817384b 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -3430,7 +3430,7 @@ void update_hero_ground_contact_and_surface_slopes(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == 1 || + if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = HH.moby; From cd588c595f6b2d4e359a3a5f8e972d63833ca072 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:56:26 +0000 Subject: [PATCH 1033/1502] decomp: clarify names in big_al_update domain_0_value_1 -> BIG_AL_UPDATE_DIALOGUE: Retail 0x002db564 retains guide_moby in s2; 0x002db594 loads its state byte at +0x20 and 0x002db598 dispatches value 1 to 0x002db69c, the source BIG_AL_UPDATE_DIALOGUE case. The initialization path writes 1 to this same +0x20 at 0x002db670 before initialize_npc_dialogue and initialize_moby_grounding. Thus the assignment uses the existing BIG_AL_UPDATE_DIALOGUE member of the exact same selector domain. domain_3_value_2 -> BIG_AL_RESOLVE_DIALOGUE: Retail 0x002db7bc-0x002db7c8 calls update_npc_dialogue on s2 and its pvars and tests success; 0x002db7fc-0x002db81c starts the dialogue camera transition, clears animation speed and writes 2 to guide_moby state +0x20. The same state load at 0x002db594 dispatches value 2 through 0x002db5b8 to 0x002db820, the source BIG_AL_RESOLVE_DIALOGUE case handling dialogue outcome. Reuse the existing member for this same guide state field. domain_4_value_1 -> BIG_AL_UPDATE_DIALOGUE: Inside the source BIG_AL_RESOLVE_DIALOGUE case, retail 0x002db828-0x002db834 restores animation speed, then 0x002db8a4-0x002db8ac writes 1 to the original guide_moby in s2 at state offset +0x20. The same owner's state value 1 dispatches at 0x002db594-0x002db598 to the update_npc_dialogue path at 0x002db69c/0x002db7bc. Therefore this return transition reuses BIG_AL_UPDATE_DIALOGUE, not a reward-moby or hero state constant. --- src/overlays/l03/mobys/big_al.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l03/mobys/big_al.c b/src/overlays/l03/mobys/big_al.c index 90c6e448bd..1ab225a5a2 100644 --- a/src/overlays/l03/mobys/big_al.c +++ b/src/overlays/l03/mobys/big_al.c @@ -117,7 +117,7 @@ void big_al_update(struct Moby *guide_moby) { } } guide_moby->spawn_frame = *(u64 *)(D_001413D0_db558[0] + 0x38); - guide_moby->state = 1; + guide_moby->state = BIG_AL_UPDATE_DIALOGUE; initialize_npc_dialogue(guide_moby, (struct TalkState *)&v->talk); initialize_moby_grounding(guide_moby); if (D_0013D4C2[0] != 0) { @@ -154,7 +154,7 @@ void big_al_update(struct Moby *guide_moby) { } begin_dialogue_camera_transition(guide_moby, 2.7f); guide_moby->anim_speed = 0.0f; - guide_moby->state = 2; + guide_moby->state = BIG_AL_RESOLVE_DIALOGUE; } break; case BIG_AL_RESOLVE_DIALOGUE: @@ -174,7 +174,7 @@ void big_al_update(struct Moby *guide_moby) { jet_reset_camera(&l03_cuboids[v->warp].pos, &l03_cuboids[v->warp].rot); } } - guide_moby->state = 1; + guide_moby->state = BIG_AL_UPDATE_DIALOGUE; if (v->talk.mode != 2) { break; } From bb44e96e4de4f4c44bd0a9bc9c082c0e7ec85a57 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:56:26 +0000 Subject: [PATCH 1034/1502] decomp: clarify names in update_hero_attachment domain_0_value_0 -> HERO_ATTACHMENT_MODE_INACTIVE: Retail 0x00233f9c clears s6 (source mode = 0); 0x002340d8 tests that same register and returns before resolving hero+0x360 when it remains zero. This is the local inactive attachment mode, not a hero state ID. domain_1_value_1 -> HERO_ATTACHMENT_MODE_PROBE: Retail 0x00233fdc..0x0023400c selects hero+0x2FC as attached object +0x360 and sets s6 to 1 at 0x00233ff0. Unless anchor flags promote it to 2, comparison 0x00234478 selects probe output minus hero position at 0x00234494..0x002344ac. domain_2_value_1 -> HERO_ATTACHMENT_MODE_PROBE: Retail 0x0023402c..0x00234050 selects hero+0x4F8 into attachment +0x360 and sets local s6 to 1. This is the same probe strategy tested at 0x00234478, before possible promotion from saved anchor flags at 0x002343bc..0x002343c4. domain_3_value_1 -> HERO_ATTACHMENT_MODE_PROBE: Retail 0x00234058..0x00234078 selects hero+0x4F8 into attachment +0x360 and assigns local s6 = 1. With no saved anchor flags and zero residual amount, 0x00234478..0x002344b0 derives displacement and yaw from probe outputs. domain_4_value_1 -> HERO_ATTACHMENT_MODE_PROBE: Retail 0x0023407c..0x002340b0 retains a nonnull hero+0x360, assigns s6 = 1 at 0x0023408c and loads residual amount into f22. Mode 1 is the default probe strategy compared at 0x00234478; nonzero f22 overrides strategy with residual motion at 0x002343d0..0x00234474. domain_5_value_2 -> HERO_ATTACHMENT_MODE_ANCHORED: Retail 0x002343ac loads 2, 0x002343bc masks hero+0x364 with 3, and 0x002343c4 conditionally assigns 2 to s6 when either saved position/rotation anchor flag is present. Its branch at 0x002344bc reconstructs +0x310/+0x320/+0x330 via transform_attachment_pose at 0x00234500/0x00234520. domain_6_value_1 -> HERO_ATTACHMENT_MODE_PROBE: Retail 0x002343dc prepares 1 and 0x00234478 compares it with s6. This branch calls probe_ground_height_cf at 0x00234494, copies output yaw at 0x002344b0, and subtracts hero position from probed position at 0x002344ac rather than reconstructing saved anchors. domain_7_value_2 -> HERO_ATTACHMENT_MODE_ANCHORED: Retail 0x002344bc compares s6 against 2 from 0x002343ac. The selected branch calls transform_attachment_pose at 0x00234500 and 0x00234520 with saved local position anchors hero+0x310/+0x330 and rotation anchor +0x320, then applies attachment-derived movement/facing. --- src/overlays/shared/hero/set_hero_animation.c | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/overlays/shared/hero/set_hero_animation.c b/src/overlays/shared/hero/set_hero_animation.c index 5466f64c6d..988fc1c0aa 100644 --- a/src/overlays/shared/hero/set_hero_animation.c +++ b/src/overlays/shared/hero/set_hero_animation.c @@ -1447,6 +1447,11 @@ extern f32 frame_time_sq_macro __asm__("D_0015ED70") MACRO_ADDR; void update_hero_attachment(void) __asm__("FUN_L00_00233f80"); void update_hero_attachment(void) { + enum { + HERO_ATTACHMENT_MODE_INACTIVE = 0, + HERO_ATTACHMENT_MODE_PROBE = 1, + HERO_ATTACHMENT_MODE_ANCHORED = 2 + }; Vec_234800 probed_position, unanchored_probe_rotation, attachment_motion_scratch, attachment_position_motion_scratch, probe_transform_scratch, anchored_probe_rotation, primary_attachment_position, primary_attachment_rotation, secondary_attachment_position, @@ -1456,12 +1461,12 @@ void update_hero_attachment(void) { int mode; Plat *plat; - mode = 0; + mode = HERO_ATTACHMENT_MODE_INACTIVE; amt = 0.0f; saved_hero_yaw = ((Hero_234800 *)hero_233f80)->v90.z; if (((Hero_234800 *)hero_233f80)->h30E == 0) { if (((Hero_234800 *)hero_233f80)->p2FC != 0) { - mode = 1; + mode = HERO_ATTACHMENT_MODE_PROBE; if (((Hero_234800 *)hero_233f80)->p360 != ((Hero_234800 *)hero_233f80)->p2FC) { ((Hero_234800 *)hero_233f80)->i364 &= ~1; } @@ -1474,13 +1479,13 @@ void update_hero_attachment(void) { } else if (((Hero_234800 *)hero_233f80)->i2084 == 0x1C && ((Hero_234800 *)hero_233f80)->p4F8 != 0) { ((Hero_234800 *)hero_233f80)->p360 = ((Hero_234800 *)hero_233f80)->p4F8; - mode = 1; + mode = HERO_ATTACHMENT_MODE_PROBE; } else if (((Hero_234800 *)hero_233f80)->i208C == 3 && ((Hero_234800 *)hero_233f80)->p4F8 != 0) { ((Hero_234800 *)hero_233f80)->p360 = ((Hero_234800 *)hero_233f80)->p4F8; - mode = 1; + mode = HERO_ATTACHMENT_MODE_PROBE; } else if (((Hero_234800 *)hero_233f80)->p360 != 0) { - mode = 1; + mode = HERO_ATTACHMENT_MODE_PROBE; convert_integer_to_float(scale_game_frames(120) - ((Hero_234800 *)hero_233f80)->h30E); scale_game_frames_v_233f80(120); amt = ((Hero_234800 *)hero_233f80)->h30E; @@ -1575,7 +1580,7 @@ void update_hero_attachment(void) { ((Hero_234800 *)hero_233f80)->i364 &= ~2; } if (((Hero_234800 *)hero_233f80)->i364 & 3) { - mode = 2; + mode = HERO_ATTACHMENT_MODE_ANCHORED; } clear_u64_value(&attachment_motion_scratch); clear_u64_value(&attachment_position_motion_scratch); @@ -1592,7 +1597,7 @@ void update_hero_attachment(void) { qcopy(&attachment_motion_scratch, &((Hero_234800 *)hero_233f80)->v350); } qcopy(&attachment_position_motion_scratch, &attachment_motion_scratch); - } else if (mode == 1) { + } else if (mode == HERO_ATTACHMENT_MODE_PROBE) { probe_ground_height_cf(((Hero_234800 *)hero_233f80)->i2080, ((Hero_234800 *)hero_233f80)->p360, &((Hero_234800 *)hero_233f80)->pos, @@ -1603,7 +1608,7 @@ void update_hero_attachment(void) { fast_vec_sub( &attachment_motion_scratch, &probed_position, &((Hero_234800 *)hero_233f80)->pos); qcopy((Vec_234800 *)(hero_233f80 + 0x350), &attachment_motion_scratch); - } else if (mode == 2) { + } else if (mode == HERO_ATTACHMENT_MODE_ANCHORED) { probe_ground_height_cf(((Hero_234800 *)hero_233f80)->i2080, ((Hero_234800 *)hero_233f80)->p360, &((Hero_234800 *)hero_233f80)->pos, From a9074321a868706785a38dc8c1de98c53b976ca1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:58:21 +0000 Subject: [PATCH 1035/1502] decomp: clarify names in draw_ship_hud domain_1_value_8 -> JET_FIGHTER_STATE_DELAYED_EXIT: Retail 0x00311d70 preserves the callback moby in s7; 0x003123fc loads its state from +0x20, and 0x00312400-0x00312404 compares that byte with 8 before drawing message 0x523E. The bound source update_player_ship_flight registers draw_ship_hud with ship_moby; jet_fighter_update passes its same moby to that flight function. Its existing enum names 8 JET_FIGHTER_STATE_DELAYED_EXIT, entered when ship_vars->sE8 <= 0 with iF8 set to D_L11_00162168. That state continues flight, waits for iF8, fades, dismounts and moves the ship/hero to victory destinations before entering INACTIVE. Thus this HUD test uses the established jet-fighter delayed-exit domain, not the equal-valued HERO_STATE_LAND or PAD_R1. --- src/overlays/l11/mobys/jet_fighter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/jet_fighter.c b/src/overlays/l11/mobys/jet_fighter.c index 35c30f1ebf..cd3998472d 100644 --- a/src/overlays/l11/mobys/jet_fighter.c +++ b/src/overlays/l11/mobys/jet_fighter.c @@ -355,6 +355,9 @@ void draw_ship_hud(struct Moby *moby) __asm__("FUN_L11_00311d50"); extern void draw_ship_hud(); void draw_ship_hud(struct Moby *moby) { + enum { + JET_FIGHTER_STATE_DELAYED_EXIT = 8 + }; ShipVars *ship_hud_vars = (ShipVars *)moby->pvars; short *list; void *found[12]; @@ -564,7 +567,7 @@ void draw_ship_hud(struct Moby *moby) { help_request(0x2AFD, 0x56); } - if (moby->state == 8) { + if (moby->state == JET_FIGHTER_STATE_DELAYED_EXIT) { font_print_center_large(0x100, 0xC8, 0x80005080, get_help_message_text(0x523E), 0x11); } From e998fab097097614872e01bca8810a96a5be891d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:58:21 +0000 Subject: [PATCH 1036/1502] decomp: clarify names in hero_move_state_velocity domain_0_value_10 -> HERO_STATE_PACK_JUMP: Authoritative C assigns state = hero.state.current; retail 0x00214670 forms hero base 0x0013f350 and 0x00214680 loads current-state offset 0x2084 into a0. This proves the HeroStateId domain supplied by include/rnc/hero/hero_state.h, rather than control_mode at offset 0x208c. 0x00214664/0x00214684 compare that current state with 10; 0x002146a4 builds the move impulse, 0x002146ac-0x002146b8 copy it to momentum, and 0x002146bc-0x002146c4 copy flat_speed to ground_speed. Reuse the canonical HeroStateId member PACK_JUMP = 10. domain_1_value_16 -> HERO_STATE_PACK_LONG_JUMP: Authoritative C assigns state = hero.state.current; retail 0x00214670 forms hero base 0x0013f350 and 0x00214680 loads current-state offset 0x2084 into a0. This proves the HeroStateId domain supplied by include/rnc/hero/hero_state.h, rather than control_mode at offset 0x208c. 0x002146c8-0x002146cc compare the same a0 current state with 16. The branch updates jump_gravity after timer threshold 0x36, uses long_jump_speed at hero+0x3f4 before threshold 0x37, steps ground speed, and rebuilds forward planar velocity at 0x00214774-0x00214788. Reuse canonical PACK_LONG_JUMP = 16. domain_2_value_28 -> HERO_STATE_LEDGE_JUMP: Authoritative C assigns state = hero.state.current; retail 0x00214670 forms hero base 0x0013f350 and 0x00214680 loads current-state offset 0x2084 into a0. This proves the HeroStateId domain supplied by include/rnc/hero/hero_state.h, rather than control_mode at offset 0x208c. 0x002146d0 loads 0x1c and 0x00214794 compares it with the same a0 current state. 0x0021480c-0x0021487c gate ledge_jump_speed by animation frames 13 through 30 and ramp it toward frame_time*2 before frame 27; 0x0021492c-0x00214954 generate yaw-aligned XY velocity. Reuse canonical LEDGE_JUMP = 28. domain_3_value_76 -> HERO_STATE_ALT_LEDGE_JUMP: Authoritative C assigns state = hero.state.current; retail 0x00214670 forms hero base 0x0013f350 and 0x00214680 loads current-state offset 0x2084 into a0. This proves the HeroStateId domain supplied by include/rnc/hero/hero_state.h, rather than control_mode at offset 0x208c. 0x00214798 loads 0x4c and 0x00214880 compares it with the same current-state a0. 0x00214888-0x00214924 use animation frames 5 through 18 and frame_time*1.25 before frame 15 to update the same ledge_jump_speed consumed by yaw-aligned velocity at 0x0021492c-0x00214954. Reuse canonical ALT_LEDGE_JUMP = 76. domain_4_value_11 -> HERO_STATE_HIGH_JUMP: Authoritative C assigns state = hero.state.current; retail 0x00214670 forms hero base 0x0013f350 and 0x00214680 loads current-state offset 0x2084 into a0. This proves the HeroStateId domain supplied by include/rnc/hero/hero_state.h, rather than control_mode at offset 0x208c. 0x00214884 subtracts 11 from current-state a0 and 0x00214958-0x0021495c accept the unsigned range of two states. This listed state == 11 comparison is the first member of that range. 0x002149c8-0x002149d0 separately compare hero+0x2084 with 11 for high_jump_drift_speed processing, already written as HERO_STATE_HIGH_JUMP in C. Reuse that canonical member. domain_5_value_12 -> HERO_STATE_STORED_HEADING_JUMP: Authoritative C assigns state = hero.state.current; retail 0x00214670 forms hero base 0x0013f350 and 0x00214680 loads current-state offset 0x2084 into a0. This proves the HeroStateId domain supplied by include/rnc/hero/hero_state.h, rather than control_mode at offset 0x208c. 0x00214884 subtracts 11 from current-state a0 and 0x00214958-0x0021495c accept values 11 and 12. Thus the listed state == 12 comparison tests HeroStateId, whose canonical member is STORED_HEADING_JUMP = 12. The shared branch copies takeoff_yaw at hero+0x43c to move_yaw at 0x00214998-0x002149a8 and constructs velocity from stored headings; 0x002149d0 skips the high-jump-only adjustment for 12. domain_6_value_17 -> HERO_STATE_REPEATABLE_JUMP: Authoritative C assigns state = hero.state.current; retail 0x00214670 forms hero base 0x0013f350 and 0x00214680 loads current-state offset 0x2084 into a0. This proves the HeroStateId domain supplied by include/rnc/hero/hero_state.h, rather than control_mode at offset 0x208c. 0x00214b04-0x00214b08 compare current-state a0 with 0x11. 0x00214b10-0x00214b24 restore move_yaw and move_dir from hero+0x470; after the nine-frame threshold, 0x00214bb0-0x00214c2c construct frame_time*4.9 planar motion from that heading or direction. Reuse canonical HeroStateId REPEATABLE_JUMP = 17. domain_7_value_45 -> HERO_STATE_ITEM_RELEASE_FALL: Authoritative C assigns state = hero.state.current; retail 0x00214670 forms hero base 0x0013f350 and 0x00214680 loads current-state offset 0x2084 into a0. This proves the HeroStateId domain supplied by include/rnc/hero/hero_state.h, rather than control_mode at offset 0x208c. 0x00214b0c loads 0x2d and 0x00214c40 compares the same current-state a0 with it. 0x00214c90-0x00214ca0 spring a temporary copy of hero yaw toward move_yaw, then 0x00214ca4-0x00214cc0 apply its wrapped yaw delta through rotate_hero_about_fixed_local_pivot. Reuse canonical HeroStateId ITEM_RELEASE_FALL = 45. --- .../shared/hero/hero_move_state_velocity.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/hero/hero_move_state_velocity.c b/src/overlays/shared/hero/hero_move_state_velocity.c index 6e8bd20644..2cec2a8da3 100644 --- a/src/overlays/shared/hero/hero_move_state_velocity.c +++ b/src/overlays/shared/hero/hero_move_state_velocity.c @@ -59,11 +59,11 @@ void hero_move_state_velocity(void) { s32 state; state = hero.state.current; - if (state == 10) { + if (state == HERO_STATE_PACK_JUMP) { build_scaled_hero_move_impulse(0.7f, ED6C * 0.0f); qcopy(&hero.motion.momentum, &hero.move_impulse); hero.ground_speed = hero.motion.flat_speed; - } else if (state == 16) { + } else if (state == HERO_STATE_PACK_LONG_JUMP) { if (FUN_001f96f8_214658(0x36) < hero.state_timer) { approach_value(ED70 * 25.0f, ED70 * 7.0f, &hero.jump_gravity); } @@ -75,7 +75,7 @@ void hero_move_state_velocity(void) { speed_step(ED70 * 44.0f, ED70 * 45.0f); set_gravity_relative_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, 0.0f); add_hero_forward_offset(&hero.motion.velocity, &hero.motion.velocity, hero.ground_speed); - } else if (state == 0x1C) { + } else if (state == HERO_STATE_LEDGE_JUMP) { if (FUN_001f96f8_214658(0x28) < hero.state_timer) { turn_to(0, ED64 * 0.04f, ED64 * 0.2f, ED6C * 15.009831f); steer_hero_planar_velocity(ED70 * 20.0f); @@ -91,7 +91,7 @@ void hero_move_state_velocity(void) { FUN_001f9dc8_214658(hero.motion.rot.f[2]) * hero.ledge_jump_speed; hero.motion.velocity.f[1] = FUN_001f9de0_214658(hero.motion.rot.f[2]) * hero.ledge_jump_speed; - } else if (state == 0x4C) { + } else if (state == HERO_STATE_ALT_LEDGE_JUMP) { if (5.0f <= hero.anim_frame && hero.anim_frame <= 18.0f) { if (15.0f < hero.anim_frame) { approach_value(0.0f, ED70 * 8.0f, &hero.ledge_jump_speed); @@ -103,7 +103,7 @@ void hero_move_state_velocity(void) { FUN_001f9dc8_214658(hero.motion.rot.f[2]) * hero.ledge_jump_speed; hero.motion.velocity.f[1] = FUN_001f9de0_214658(hero.motion.rot.f[2]) * hero.ledge_jump_speed; - } else if (state == 11 || state == 12) { + } else if (state == HERO_STATE_HIGH_JUMP || state == HERO_STATE_STORED_HEADING_JUMP) { hero.motion.move_yaw = hero.takeoff_yaw; turn_to(0, ED64 * 0.04f, ED64 * 0.2f, ED6C * 6.981317f); if (hero.unk450 != 3) { @@ -131,7 +131,7 @@ void hero_move_state_velocity(void) { FUN_001f9de0_214658(hero.takeoff_yaw) * heading_velocity_scale_or_pivot_yaw_delta; build_scaled_hero_move_impulse(0.7f, ED6C * 0.0f); qcopy(&hero.motion.momentum, &hero.move_impulse); - } else if (state == 0x11) { + } else if (state == HERO_STATE_REPEATABLE_JUMP) { hero.motion.move_yaw = hero.unk470.f[3]; qcopy(&hero.motion.move_dir, &hero.unk470); if (FUN_001f96f8_214658(9) < hero.state_timer) { @@ -152,7 +152,7 @@ void hero_move_state_velocity(void) { } hero.ground_speed = hero.motion.flat_speed; } else { - if (state == 0x2D) { + if (state == HERO_STATE_ITEM_RELEASE_FALL) { x = hero.motion.rot.f[2]; hero.motion.yaw_error = FUN_L00_0025bc98_214658(&x, &hero.motion.yaw_rate, From 5e573c70fa307960dc2fb98b14d1bffa6d317c8c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:58:21 +0000 Subject: [PATCH 1037/1502] decomp: clarify names in run_level_main_loop domain_0_value_3 -> MEMCARD_REQUEST_FORMAT: Source reads memory_card_state.state after memcard_update_state. Retail 0x002460e4..0x002460f4 loads 0x0013d290+0xd4 (0x0013d364) and tests signed state >=3, matching original Ghidra 2 < iRam0013d364. Supplied memory_card_state.h domain explicitly assigns state/pending_state to MemoryCardOperation, whose canonical value 3 is MEMCARD_REQUEST_FORMAT. Reuse as the inclusive operation-range boundary, without claiming every >=3 operation is format. domain_1_value_0 -> MEMCARD_QUERY_INFO: Retail 0x002460fc..0x00246100 loads pending operation at 0x0013d290+0xdc (0x0013d36c) and branches away when negative; original Ghidra tests -1 < iRam0013d36c. Authoritative C identifies memory_card_state.pending_state. Supplied shared header assigns pending_state to MemoryCardOperation, with MEMCARD_QUERY_INFO=0. This names the lower boundary of nonnegative pending operations, preserving >=. domain_4_value_0 -> LEVEL_MODE_DEBUG_FLAG_GATED_UPDATE: Authoritative local int mode is loaded directly from D_L00_0015F5C4. Retail 0x002462a4 loads its gp alias into a3 and 0x002462a8 branches on zero. The same mode global drives the earlier switch at 0x00245f54, whose established value 0 is LEVEL_MODE_DEBUG_FLAG_GATED_UPDATE; branch invokes the same 0x00297f78 update at 0x002462f4 as switch mode 0 at 0x00245fa8. domain_5_value_2 -> LEVEL_MODE_DEBUG_PROFILER_RENDER: Source mode snapshots D_L00_0015F5C4, the same selector as saved_level_mode. Retail 0x002462a4..0x002462b0 compares its gp-loaded value against 2. Earlier switch value 2 is established LEVEL_MODE_DEBUG_PROFILER_RENDER (0x00245fd0..0x00245fe4); timed path repeats that branch's update_cutscene_playback at 0x00246320, proving shared selector domain rather than numeric coincidence. domain_7_value_0 -> LEVEL_MODE_DEBUG_FLAG_GATED_UPDATE: Retail 0x002462e4 checks a3, still the D_L00_0015F5C4 mode loaded at 0x002462a4, for zero before callback registration and 0x00297f78 at 0x002462f4. Authoritative mode ==0 repeats the established switch LEVEL_MODE_DEBUG_FLAG_GATED_UPDATE branch (same helper at 0x00245fa8), proving reuse of its canonical local constant. domain_8_value_2 -> LEVEL_MODE_DEBUG_PROFILER_RENDER: Retail 0x00246304 compares a3 (level mode from 0x002462a4) to 2, then tests D_L00_0016C8B0 and invokes 0x00298f90 at 0x00246320. Source identifies that helper as update_cutscene_playback, also called by established switch LEVEL_MODE_DEBUG_PROFILER_RENDER at 0x00245fd8. Reuse value 2 in the identical level-mode domain. --- src/overlays/shared/game/run_level_main_loop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/game/run_level_main_loop.c b/src/overlays/shared/game/run_level_main_loop.c index c8dd3b2e2e..88d781d3cb 100644 --- a/src/overlays/shared/game/run_level_main_loop.c +++ b/src/overlays/shared/game/run_level_main_loop.c @@ -227,7 +227,7 @@ void run_level_main_loop(void) { } memcard_update_state(); run_state_handler(); - if (memory_card_state.state >= 3 || memory_card_state.pending_state >= 0) { + if (memory_card_state.state >= MEMCARD_REQUEST_FORMAT || memory_card_state.pending_state >= MEMCARD_QUERY_INFO) { if (D_L00_001B9CF0.unk13C == 0) { int rotation_period_frames = 55; float size; @@ -265,17 +265,17 @@ void run_level_main_loop(void) { if (hero.fall_fade_pending == 0) { int mode = D_L00_0015F5C4; - if (mode == 0 || mode == 2) { + if (mode == LEVEL_MODE_DEBUG_FLAG_GATED_UPDATE || mode == LEVEL_MODE_DEBUG_PROFILER_RENDER) { int frame_timer_threshold = 9600; if (pal_mode != 0) { frame_timer_threshold = 11520; } if (frame_timer_threshold < *(volatile int *)0x10000800) { - if (mode == 0) { + if (mode == LEVEL_MODE_DEBUG_FLAG_GATED_UPDATE) { register_audio_stream_callback(); handle_pause_input(); - } else if (mode == 2 && D_L00_0016C8B0 == 0) { + } else if (mode == LEVEL_MODE_DEBUG_PROFILER_RENDER && D_L00_0016C8B0 == 0) { register_audio_stream_callback(); update_cutscene_playback(); } From 72c33974882c1043d9c5674d902f756080db3e61 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:58:21 +0000 Subject: [PATCH 1038/1502] decomp: clarify names in draw_debug_profiler domain_0_value_0 -> FALSE: pal_mode is the existing PAL-video flag at D_0015ED80. Retail 0x001f3af4 loads it and 0x001f3af8 branches on zero to draw_ties_1 at 0x001f3b10, whereas nonzero calls draw_ties_2. The same flag selects the PAL timing divisor at 0x001f407c-0x001f40a0. Zero is therefore the false PAL flag; reuse supplied FALSE=0, not NULL or a new mode enum. domain_1_value_6 -> FONT_STATE_EFFECTS_DATA: Retail 0x001f3c7c reads D_0015F620 (source font_state), 0x001f3c80 loads 6 and 0x001f3c84 skips the effects-data reference when equal. Otherwise 0x001f3c90-0x001f3c98 passes D_0010FAA0 and the halfword at D_0010FA90 to vu1_add_data_ref, then 0x001f3ca0 stores the same 6. Source gates this on effects enable 0x20 and draw_config.unk30. This is the cached state identifying that effects-data reference, not a game or moby state. domain_2_value_6 -> FONT_STATE_EFFECTS_DATA: The assignment font_state=6 maps to retail 0x001f3ca0 storing s0=6 into D_0015F620 immediately after vu1_add_data_ref(D_0010FAA0,D_0010FA90[0]) at 0x001f3c94. The comparison at 0x001f3c84 uses this same global and value to suppress that reference. Reuse FONT_STATE_EFFECTS_DATA for both tokens in this proven upload-state domain. domain_3_value_8 -> FONT_STATE_PART_DRAW: Retail 0x001f3d50-0x001f3d88 gates on draw_config.unk38, sets GS register 8 to 5, selects alternate GS registers, flushes cache and calls part_proc at 0x001f3d78, then stores 8 into the same D_0015F620 font_state global. The immediately following paired callbacks at 0x001f3d94 and 0x001f3da0 use the established part_draw_label and category 8. Thus FONT_STATE_PART_DRAW names the state recorded for the part-draw phase; it does not assert an unproved particle subtype or resource layout. domain_4_value_0 -> FALSE: Retail 0x001f407c loads D_0015ED80, the source pal_mode flag, and 0x001f408c branches when it is zero to retain the 9600 divisor; nonzero selects 11520 at 0x001f4094-0x001f40a0. The original Ghidra identifies NTSC versus PAL divisors. This comparison checks whether the PAL flag is false; reuse supplied boolean FALSE=0. domain_5_value_0 -> FALSE: Retail 0x001f4138 loads D_0015ED80 (source pal_mode) and 0x001f413c branches on zero to light_ties and patch_tie_texture_fields at 0x001f415c/0x001f4164. Nonzero calls register_entity_render_resources and copy_render_buffer_pair at 0x001f4144/0x001f414c. Together with the same flag's PAL timing selection, zero is the false PAL flag. Reuse supplied FALSE=0. --- src/rendering/debug/draw_debug_profiler.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/rendering/debug/draw_debug_profiler.c b/src/rendering/debug/draw_debug_profiler.c index c41b964f40..7e25cba35b 100644 --- a/src/rendering/debug/draw_debug_profiler.c +++ b/src/rendering/debug/draw_debug_profiler.c @@ -111,6 +111,10 @@ extern float sequence_macro __asm__("D_0015F43C") MACRO_ADDR; extern s32 game_mode_macro __asm__("D_0015F604") MACRO_ADDR; void draw_debug_profiler(void) { + enum { + FONT_STATE_EFFECTS_DATA = 6, + FONT_STATE_PART_DRAW = 8 + }; f32 rcnt1_count_float; f32 div; @@ -137,7 +141,7 @@ void draw_debug_profiler(void) { } append_dma_tag(0x02010000); if (draw_enable_mask & 4) { - if (pal_mode != 0) { + if (pal_mode != FALSE) { draw_ties_2(); } else { draw_ties_1(); @@ -177,9 +181,9 @@ void draw_debug_profiler(void) { } append_dma_tag(0x02080000); setup_gif_paging(0); - if ((draw_enable_mask & 0x20) && draw_config.unk30 != 0 && font_state != 6) { + if ((draw_enable_mask & 0x20) && draw_config.unk30 != 0 && font_state != FONT_STATE_EFFECTS_DATA) { vu1_add_data_ref(D_0010FAA0, D_0010FA90[0]); - font_state = 6; + font_state = FONT_STATE_EFFECTS_DATA; } noop_core_callback_secondary(vu_effects_label, 4); noop_core_callback(vu_effects_label, 4); @@ -201,7 +205,7 @@ void draw_debug_profiler(void) { vu1_gs_regs_alt(); FlushCache(0); part_proc(); - font_state = 8; + font_state = FONT_STATE_PART_DRAW; } noop_core_callback(part_draw_label, 8); noop_core_callback_secondary(part_draw_label, 8); @@ -265,7 +269,7 @@ void draw_debug_profiler(void) { vu0_load_micro_program(D_00100AE0); FlushCache(0); rcnt1_count_float = convert_integer_to_float(*(volatile s32 *)0x10000800); - D_0015F614 = rcnt1_count_float / (pal_mode != 0 ? 11520.0f : 9600.0f); + D_0015F614 = rcnt1_count_float / (pal_mode != FALSE ? 11520.0f : 9600.0f); vu1_sync_chain(2); noop_core_callback(dma_sync_empty_label, 0x11); if (draw_enable_mask & 2) { @@ -279,7 +283,7 @@ void draw_debug_profiler(void) { noop_core_callback(dma_sync_empty_label, 0x11); if (draw_enable_mask & 4) { if (draw_config.tie.enabled != 0) { - if (pal_mode != 0) { + if (pal_mode != FALSE) { register_entity_render_resources(); copy_render_buffer_pair(); } else { From 28e43f04d3725cba843e6f154ee76ceb75a5c17b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 19:58:21 +0000 Subject: [PATCH 1039/1502] decomp: clarify names in update_hero_ground_contact domain_0_value_0 -> GROUND_MATERIAL_WATER: Retail 0x002403e0-0x002403f0 obtains collision_hit_material and stores the s16 at hero+0x12e0; zero selects 0x002403f4-0x00240440, resolving water_surface_z, starting in_water_frames when position Z is below that surface, then retrying mask 0x24. Authoritative source apply_hero_ground_material_effects preserves this same hero.ground_type in saved_ground_type and already names value 0 GROUND_MATERIAL_WATER, calculating water_depth and wading. This proves the collision-material domain, independently of state IDs. domain_5_value_1 -> HERO_GRAVITY_OPPOSITE_GROUND_NORMAL: Retail 0x002406e8-0x002406f0 loads hero+0x20b3 as u8 and compares it to 1 to permit landing despite slope. The same byte selects the gravity-direction dispatch at 0x00240788-0x002407cc; its value-1 arm 0x002407cc-0x002407e8 copies ground_normal from hero+0x270 into gravity_dir and scales by -1. Source switch(hero.gravity_mode) already uses HERO_GRAVITY_OPPOSITE_GROUND_NORMAL for this arm, proving membership in shared HeroGravityMode rather than HeroStateId or vehicle/control modes. --- src/overlays/l05/hero/apply_hero_ground_material_effects.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l05/hero/apply_hero_ground_material_effects.c b/src/overlays/l05/hero/apply_hero_ground_material_effects.c index 6f82a6f23a..f945af9637 100644 --- a/src/overlays/l05/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l05/hero/apply_hero_ground_material_effects.c @@ -163,6 +163,9 @@ extern CollisionHit HH __asm__("D_L05_00174240") NOT_SDA; void update_hero_ground_contact(void) __asm__("FUN_L05_002402a8"); void update_hero_ground_contact(void) { + enum { + GROUND_MATERIAL_WATER = 0 + }; V shared_probe_endpoint, ground_probe_endpoint, ground_vector_scratch, side_probe_endpoint, unused_probe_vector, hit_normal_angles, normalized_hit_normal; f32 f; @@ -206,7 +209,7 @@ void update_hero_ground_contact(void) { } hero.ground_sound_class = ground_sound_class; hero.ground_type = collision_hit_material(); - if (hero.ground_type == 0) { + if (hero.ground_type == GROUND_MATERIAL_WATER) { hero.water_surface_z = resolve_camera_surface_height(D_L05_00174260, (u8 *)&hero.water_surface_normal); if (hero.motion.pos.f[2] < hero.water_surface_z && hero.in_water_frames <= 0) { @@ -271,7 +274,7 @@ void update_hero_ground_contact(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == 1 || + if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = HH.moby; From fb98552bb9cb298ae1aafe41091802300a39d45f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:00:24 +0000 Subject: [PATCH 1040/1502] decomp: clarify names in update_pool_tiles_and_effects domain_0_value_1 -> POOL_UPDATE_TILES_AND_EFFECTS: SHA-bound source src/overlays/l01/mobys/pool_tiles_and_effects.c (6cbe3eb48e32fe36b32e8727980a4b025ab7fcdda867bbe5c74079c57b5209a7) defines POOL_UPDATE_TILES_AND_EFFECTS=1 and dispatches switch(moby->state) to that case. Original retail decompilation writes 1 to param_1+0x20 in initialization and tests the same byte for 1. Instructions 0x002fd14c-0x002fd158 load byte +0x20 and branch on 1 to 0x002fd3e4; 0x002fd17c loads 1 and 0x002fd190 stores it to +0x20(s8). That branch scans seven clip volumes, updates colors/splashes, flushes/queues water drawing (0x002fd670-0x002fd68c), and emits drips/bubbles through 0x002fd940, proving reuse of the existing local pool state member. --- src/overlays/l01/mobys/pool_tiles_and_effects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/pool_tiles_and_effects.c b/src/overlays/l01/mobys/pool_tiles_and_effects.c index e3744359b9..83c73a0ff5 100644 --- a/src/overlays/l01/mobys/pool_tiles_and_effects.c +++ b/src/overlays/l01/mobys/pool_tiles_and_effects.c @@ -281,7 +281,7 @@ void pool_tiles_and_effects_update(struct Moby *moby) { volumes = (s32 *)moby->pvars; switch (moby->state) { case POOL_INITIALIZE: - moby->state = 1; + moby->state = POOL_UPDATE_TILES_AND_EFFECTS; moby->update_dist = 0xFF; moby->pos.z = moby->pos.z + 0.5f; pool_init_tiles(pool_tiles, 21); From 20f35192a400e2a381afa751845899b38627b5b8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:00:24 +0000 Subject: [PATCH 1041/1502] decomp: clarify names in shrub_update domain_0_value_2 -> SHRUB_FOLLOW_SECONDARY_PATH_AND_FIRE_RANDOMLY: Retail 002e8ce0 retains input moby in s4; 002e8d38 reads its state byte at +0x20 and 002e8d3c-002e8d40 dispatch value 2 to 002e9154. Initialization copies follow[1].path point zero at 002e8e24-002e8e30, spawns parts, then 002e8e3c stores that same value 2 to +0x20(s4). The destination branch selects follow[1] at 002e915c, moves along its points, and timer-fires a null-target rocket at 002e9344-002e93f8. This is the same parent state selector already named SHRUB_FOLLOW_SECONDARY_PATH_AND_FIRE_RANDOMLY in the bound C local enum. domain_3_value_1 -> SHRUB_FOLLOW_PRIMARY_PATH_AND_FIRE_AT_TARGET: Retail 002e9420 loads 1 and 002e9428 writes it to +0x20(s4), the same input moby state read at 002e8d38 and dispatched at 002e8d58 to 002e8e68. The entry branch uses follow[0].path at 002e942c to place the moby at point zero and aim at point one. The destination state follows that primary path at 002e8e68 onward and command-fires a rocket using target_index at 002e8e94-002e8ea4 and target s3 at 002e90dc-002e90f0. Reuse existing local enum member SHRUB_FOLLOW_PRIMARY_PATH_AND_FIRE_AT_TARGET for this exact parent state domain. --- src/overlays/l08/mobys/shrub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l08/mobys/shrub.c b/src/overlays/l08/mobys/shrub.c index 343ae943b6..2580003690 100644 --- a/src/overlays/l08/mobys/shrub.c +++ b/src/overlays/l08/mobys/shrub.c @@ -265,7 +265,7 @@ void shrub_update(struct Moby *moby) { moby->flags |= 0x4000; qcopy(&moby->pos, &shrub_control_vars->follow[1].path->points[0]); spawn_shrub_parts((char *)moby); - moby->state = 2; + moby->state = SHRUB_FOLLOW_SECONDARY_PATH_AND_FIRE_RANDOMLY; moby->rot.z = fast_arc_tan(shrub_control_vars->follow[1].path->points[1].f[0] - moby->pos.x, shrub_control_vars->follow[1].path->points[1].f[1] - moby->pos.y); @@ -375,7 +375,7 @@ void shrub_update(struct Moby *moby) { case SHRUB_BEGIN_PRIMARY_PATH: { LevelPath *path; - moby->state = 1; + moby->state = SHRUB_FOLLOW_PRIMARY_PATH_AND_FIRE_AT_TARGET; path = shrub_control_vars->follow[0].path; qcopy(&moby->pos, &path->points[0]); moby->rot.z = From 2f00cdb17c076384eb7abbcf6470e5334004789e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:00:24 +0000 Subject: [PATCH 1042/1502] decomp: clarify names in armed_transport_update domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Authoritative src/overlays/shared/enemies/armed_transport.c SHA-256 99ba0fc61638fb545ee595bbf07caba0e8761ced0f82adf52fa9a58f9c866751 identifies this selector as hero.vehicle_mode. Retail 0x002e2948 loads 0x00140000, 0x002e2950 reads the byte at 0x001413f4, and 0x002e294c/0x002e2954 compare it with 2 after the death timer test; equality enters explosion/removal. Original Ghidra likewise shows cRam001413f4 == '\x02'. Supplied HeroVehicleMode in include/rnc/hero/hero_state.h declares HERO_VEHICLE_MODE_GIANT_CLANK=2, and the same source's update_armed_transport_damage_and_targeting already compares hero.vehicle_mode with that member for lethal damage and sound handling. Thus this is the exact vehicle-mode domain, independent of transport state, HeroStateId or HeroGravityMode. --- src/overlays/shared/enemies/armed_transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/armed_transport.c b/src/overlays/shared/enemies/armed_transport.c index 1597917758..ce91603240 100644 --- a/src/overlays/shared/enemies/armed_transport.c +++ b/src/overlays/shared/enemies/armed_transport.c @@ -375,7 +375,7 @@ void armed_transport_update(char *transport_moby) { transport_data->unk194 -= dt + dt; MOBY(transport_moby)->rot.x += dt * 0.2617994f; - if (fast_dec_timer((int *)(&transport_data->unk160)) || hero.vehicle_mode == 2) { + if (fast_dec_timer((int *)(&transport_data->unk160)) || hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { spawn_explosion(transport_moby, D_L16_0015F580, &MOBY(transport_moby)->pos, From 18977954d8912347c2d47734c09bf50124a0d165 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:00:24 +0000 Subject: [PATCH 1043/1502] decomp: clarify names in seeker_update domain_1_value_1 -> SEEKER_STATE_IDLE_HOVER: Retail 0x002c5af4 stores 1 to moby+0x20, the same byte loaded for switch dispatch at 0x002c5a34. Existing local enum names this selector value SEEKER_STATE_IDLE_HOVER; case 1 at 0x002c5b28-0x002c5b6c eases height toward probed ground+0.5 before facing target. domain_2_value_2 -> SEEKER_STATE_CHASE: Retail 0x002c5cb0 enables pvars+0x198 movement and 0x002c5cb8 stores 2 to moby+0x20, the switch selector at 0x002c5a34. Existing SEEKER_STATE_CHASE=2 handles target-facing movement and distance hysteresis at 0x002c5d48-0x002c5fc8. domain_3_value_4 -> SEEKER_STATE_TIMED_CHASE: After animation-completion test at 0x002c5cbc-0x002c5cc4, retail 0x002c5cf0 stores 4 to moby+0x20, the same moby state switch selector. Existing SEEKER_STATE_TIMED_CHASE=4 shares chase movement; this entry reaches 0x002c60a0-0x002c60b4 to initialize the scaled 180-frame timer if zero. domain_4_value_2 -> SEEKER_STATE_CHASE: Retail 0x002c5fe4-0x002c5fec compares 2 against byte moby+0x20, the exact switch selector loaded at 0x002c5a34. Within shared CHASE/TIMED_CHASE movement, this guard selects established SEEKER_STATE_CHASE=2 before the distance<6 transition to animation wait. domain_5_value_3 -> SEEKER_STATE_CHASE_ANIMATION_WAIT: Retail 0x002c5ff4-0x002c6004 writes 3 to moby+0x20 after distance<6 and state==2, then requests animation 3 at 0x002c6018-0x002c6020. Existing SEEKER_STATE_CHASE_ANIMATION_WAIT=3 names this same selector case, whose 0x002c5cbc-0x002c5cc4 branch waits for anim_flags & 2. domain_6_value_4 -> SEEKER_STATE_TIMED_CHASE: Hurt recovery tests decayed velocity at 0x002c6050-0x002c6064, enables movement at 0x002c6094 and stores 4 to moby+0x20 at 0x002c6098. This is the switch state byte, with established SEEKER_STATE_TIMED_CHASE=4; 0x002c60a0-0x002c60b4 initializes its timer if zero. --- src/overlays/shared/enemies/seeker.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/enemies/seeker.c b/src/overlays/shared/enemies/seeker.c index 2045197cf0..4054edc43d 100644 --- a/src/overlays/shared/enemies/seeker.c +++ b/src/overlays/shared/enemies/seeker.c @@ -142,7 +142,7 @@ void seeker_update(struct Moby *moby) { seeker_instance_vars->unkD8 = 0.5f; seeker_instance_vars->unkD0 = truncate_float_to_s32(512.0f); seeker_instance_vars->speed = frame_time * 7.75f; - moby->state = 1; + moby->state = SEEKER_STATE_IDLE_HOVER; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -174,7 +174,7 @@ void seeker_update(struct Moby *moby) { seeker_instance_vars->voice = allocate_voice_for_target_entry(1, 4, moby); } seeker_instance_vars->moving = 1; - moby->state = 2; + moby->state = SEEKER_STATE_CHASE; } break; case SEEKER_STATE_CHASE_ANIMATION_WAIT: @@ -183,7 +183,7 @@ void seeker_update(struct Moby *moby) { FUN_L01_0026e090(moby->group, 1); } seeker_instance_vars->moving = 1; - moby->state = 4; + moby->state = SEEKER_STATE_TIMED_CHASE; if (seeker_instance_vars->voice == -1) { seeker_instance_vars->voice = allocate_voice_for_target_entry(1, 4, moby); } @@ -252,8 +252,8 @@ void seeker_update(struct Moby *moby) { } FUN_L00_00258830(moby, &vel, 0, 0.0f, 0.5f, 0.0f); } - if (target_distance_xy < 6.0f && moby->state == 2) { - moby->state = 3; + if (target_distance_xy < 6.0f && moby->state == SEEKER_STATE_CHASE) { + moby->state = SEEKER_STATE_CHASE_ANIMATION_WAIT; if (moby->prev_seq != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } @@ -269,7 +269,7 @@ void seeker_update(struct Moby *moby) { seeker_instance_vars->voice = allocate_voice_for_target_entry(1, 4, moby); } seeker_instance_vars->moving = 1; - moby->state = 4; + moby->state = SEEKER_STATE_TIMED_CHASE; if (seeker_instance_vars->timer == 0) { seeker_instance_vars->timer = scale_game_frames(180); } From 947b3e45763f803bc880987813a4085d06619a1f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:00:24 +0000 Subject: [PATCH 1044/1502] decomp: clarify names in volume_camera_swing domain_10_value_10 -> SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END: The selector is SwingCameraParams.type: retail 0x002ec9c4-0x002ec9d8 follows the UpdateCam descriptor_index through camera_descriptors+0x1c and reads params+0x2c; it is not a HeroStateId. Retail 0x002ecd54-0x002ece14 gives type 10 stick-skippable timing; the type 10 path still outputs angle at 0x002ecf18-0x002ecf2c after at_end, and 0x002ed1b0-0x002ed1f8 starts its slide. This agrees with the same selector's existing member in volume_camera_swing_check. domain_12_value_3 -> SWING_CAMERA_TYPE_ONE_FRAME_SWING: The selector is SwingCameraParams.type: retail 0x002ec9c4-0x002ec9d8 follows the UpdateCam descriptor_index through camera_descriptors+0x1c and reads params+0x2c; it is not a HeroStateId. Retail 0x002ece18-0x002ece50 selects type 3, sets the swing duration to convert_integer_to_float(scale_game_frames(1)), and clamps params+0x2e to that duration; 0x002eced0-0x002ecef4 divides that timer by the duration to compute the swing angle. This names the scaled one-frame swing behavior, not an inferred gameplay state. domain_13_value_1 -> SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END: The selector is SwingCameraParams.type: retail 0x002ec9c4-0x002ec9d8 follows the UpdateCam descriptor_index through camera_descriptors+0x1c and reads params+0x2c; it is not a HeroStateId. Retail 0x002ecee4-0x002ecf2c omits set_follow_camera_angle_blend_from_direction for type 1 when at_end is set; 0x002ed1b0-0x002ed1f8 starts the slide. Reuse the same selector's established member from volume_camera_swing_check. domain_22_value_1 -> SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END: The selector is SwingCameraParams.type: retail 0x002ec9c4-0x002ec9d8 follows the UpdateCam descriptor_index through camera_descriptors+0x1c and reads params+0x2c; it is not a HeroStateId. Retail 0x002ed1b0-0x002ed1f8 calls follow_camera_start_slide for type 1, while 0x002ecef0-0x002ecf10 releases angle output at the swing end. This is the same type already named by volume_camera_swing_check. domain_24_value_10 -> SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END: The selector is SwingCameraParams.type: retail 0x002ec9c4-0x002ec9d8 follows the UpdateCam descriptor_index through camera_descriptors+0x1c and reads params+0x2c; it is not a HeroStateId. Retail 0x002ed1c0-0x002ed1f8 includes type 10 in follow_camera_start_slide; angle output at 0x002ecef0-0x002ecf2c remains enabled at its end. Reuse the existing same-domain member in volume_camera_swing_check. domain_2_value_5 -> SWING_CAMERA_TYPE_SNAP_ON_ENTRY: The selector is SwingCameraParams.type: retail 0x002ec9c4-0x002ec9d8 follows the UpdateCam descriptor_index through camera_descriptors+0x1c and reads params+0x2c; it is not a HeroStateId. Retail 0x002ecaa8-0x002ecac0 applies the L-button exit test to type 5. The same selector's word comparison at 0x002ecb1c-0x002ecb24 requires type 5 with timer zero, then 0x002ecb2c-0x002ecc70 directly rebuilds camera eye, look target, position, and reset state. Thus this type snaps on entry. domain_3_value_5 -> SWING_CAMERA_TYPE_SNAP_ON_ENTRY: The selector is SwingCameraParams.type: retail 0x002ec9c4-0x002ec9d8 follows the UpdateCam descriptor_index through camera_descriptors+0x1c and reads params+0x2c; it is not a HeroStateId. Retail 0x002ecb1c-0x002ecb24 compares the combined type/timer word to 5, proving type 5 and timer zero. The branch 0x002ecb2c-0x002ecc70 clears swing and directly sets camera position, look target, distance, height, and reset slots. Original Ghidra's float-word test 7.00649e-45 represents the same bits; this is the entry snap. domain_4_value_10 -> SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END: The selector is SwingCameraParams.type: retail 0x002ec9c4-0x002ec9d8 follows the UpdateCam descriptor_index through camera_descriptors+0x1c and reads params+0x2c; it is not a HeroStateId. Retail 0x002ecc94-0x002eccbc recognizes type 10 and sets blend output flags and tail.mode; 0x002ed1b0-0x002ed1f8 starts its slide, and the angle suppression at 0x002ecef0-0x002ecf10 excludes type 10. Reuse the member established in volume_camera_swing_check for this same params->type. domain_7_value_4 -> SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST: The selector is SwingCameraParams.type: retail 0x002ec9c4-0x002ec9d8 follows the UpdateCam descriptor_index through camera_descriptors+0x1c and reads params+0x2c; it is not a HeroStateId. The bound volume_camera_swing_active obtains the same descriptor params and names type 4 SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST: while hero_requested_camera_mode[0]==3 and timer>0 it bypasses volume tests. volume_camera_swing calls that activation helper at 0x002eca18; its type-4 timing branch at 0x002eccf4-0x002ecd44 therefore consumes this exact same camera-type domain. domain_8_value_1 -> SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END: The selector is SwingCameraParams.type: retail 0x002ec9c4-0x002ec9d8 follows the UpdateCam descriptor_index through camera_descriptors+0x1c and reads params+0x2c; it is not a HeroStateId. Retail 0x002ecd54-0x002ece14 gives type 1 the stick-skippable swing; 0x002ecef0-0x002ecf10 suppresses angle output at its end, and 0x002ed1b0-0x002ed1f8 starts the slide. The same params->type member is already named in volume_camera_swing_check. --- .../shared/camera/swing_volume_camera.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/shared/camera/swing_volume_camera.c b/src/overlays/shared/camera/swing_volume_camera.c index f8f29a4c34..a871100080 100644 --- a/src/overlays/shared/camera/swing_volume_camera.c +++ b/src/overlays/shared/camera/swing_volume_camera.c @@ -132,7 +132,7 @@ s32 volume_camera_swing_active(struct UpdateCam *swing_camera_record) { void volume_camera_swing(struct UpdateCam *cam) __asm__("FUN_L00_002ec988"); void volume_camera_swing(struct UpdateCam *swing_camera_record) { - CameraVec gravity_offset_or_yaw_direction; + enum { SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END = 1 , SWING_CAMERA_TYPE_ONE_FRAME_SWING = 3 , SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST = 4 , SWING_CAMERA_TYPE_SNAP_ON_ENTRY = 5 , SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END = 10 } ;CameraVec gravity_offset_or_yaw_direction; SwingCameraParams *params; struct UpdateCam *rec; Vec4f *pos; @@ -169,7 +169,7 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { D_L00_00166DD8) >= 1.3962634f) { goto stop; } - if (params->l_buttons_end != 0 && params->type == 5 && + if (params->l_buttons_end != 0 && params->type == SWING_CAMERA_TYPE_SNAP_ON_ENTRY && (pad_held_words[0] & (PAD_L2 | PAD_L1))) { stop: if (params->timer != 0) { @@ -188,7 +188,7 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { FOLLOW_CAM_STATE(((struct UpdateCam *)camera_globals->unk180))->follow.lateral_damping; } /* One word over type and timer: type 5 on its first frame snaps the camera. */ - if (*(s32 *)¶ms->type == 5) { + if (*(s32 *)¶ms->type == SWING_CAMERA_TYPE_SNAP_ON_ENTRY) { *(s32 *)¶ms->swing = 0; rec = current_follow_cam; rig = FOLLOW_CAM_STATE(rec); @@ -229,7 +229,7 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { at_end = 0; total = convert_integer_to_float(scale_game_frames(200)); params->timer++; - if (params->type == 10) { + if (params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END) { set_follow_camera_blend_output_flags(); FOLLOW_CAM_STATE(current_follow_cam)->tail.mode = 0x14D; } @@ -237,7 +237,7 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { set_follow_camera_blend_output_flags(); FOLLOW_CAM_STATE(current_follow_cam)->tail.mode = 2; } - if (params->type == 2 || params->type == 4) { + if (params->type == 2 || params->type == SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST) { { FollowCamFlags *ctl = &FOLLOW_CAM_STATE(current_follow_cam)->tail.ctl; ctl->flags |= 3; @@ -247,7 +247,7 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { params->timer = scale_game_frames(200); } FUN_L00_002e8620(); - } else if (params->type == 1 || params->type == 7 || params->type == 10 || params->type == 9) { + } else if (params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || params->type == 7 || params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END || params->type == 9) { /* Moving the left stick skips to the end of the swing. */ struct PadState *pad = &controller_state; if (pad->analog[0] != 0.0f || pad->analog[1] != 0.0f) { @@ -263,7 +263,7 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { at_end = 0; params->timer = 1; } - } else if (params->type == 3) { + } else if (params->type == SWING_CAMERA_TYPE_ONE_FRAME_SWING) { total = convert_integer_to_float(scale_game_frames(1)); if (params->timer > scale_game_frames(1)) { at_end = 1; @@ -281,7 +281,7 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { fast_sin(camera_descriptors[swing_camera_record->descriptor_index].yaw); *(s32 *)&gravity_offset_or_yaw_direction[2] = 0; swing = params->swing * 0.017453292f * (params->timer / total); - if ((params->type != 1 && params->type != 7 && params->type != 9) || at_end == 0) { + if ((params->type != SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END && params->type != 7 && params->type != 9) || at_end == 0) { set_follow_camera_angle_blend_from_direction( gravity_offset_or_yaw_direction, swing, params->pitch * 0.017453292f); } @@ -341,7 +341,7 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { lateral_spring_blend_fraction); } } - if (params->type == 1 || params->type == 7 || params->type == 10) { + if (params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || params->type == 7 || params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END) { FUN_L00_002e8620(); follow_camera_start_slide(); follow_camera_set_up_spring(0.01f, 0.2f); From e196df6d199359cebbffa1605c97b20dce305ee6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:00:25 +0000 Subject: [PATCH 1045/1502] decomp: clarify names in update_gunship domain_0_value_2 -> GUNSHIP_FOLLOW_SECONDARY_PATH_AND_FIRE_RANDOMLY: Same-selector proof: retail loads the parent state from 0x20(s4) at 0x002e2550 and branches on value 2 to 0x002e299c. Initialization retains s4 as the parent, sets s0=2 at 0x002e2554, and stores s0 to 0x20(s4) at 0x002e2648 after secondary-path placement and part spawning. That branch follows follow[1] at s5+0x30 and fires a NULL-target rocket on timer expiry at 0x002e2b8c-0x002e2c40. This is exactly the existing local GUNSHIP_FOLLOW_SECONDARY_PATH_AND_FIRE_RANDOMLY=2 member of the parent moby->state switch. domain_2_value_1 -> GUNSHIP_FOLLOW_PRIMARY_PATH_AND_FIRE_AT_TARGET: Same-selector proof: at 0x002e2c68-0x002e2c70 the state-3 branch stores 1 to the parent state at 0x20(s4), copies follow[0].path point 0 into that parent's position, and points it toward point 1. The parent state load/dispatch at 0x002e2550-0x002e2570 routes value 1 to 0x002e2680, which follows the primary path and fires at the indexed target on command through 0x002e2998. Thus the assignment reuses the existing local GUNSHIP_FOLLOW_PRIMARY_PATH_AND_FIRE_AT_TARGET=1 member, without importing another object's state domain. --- src/overlays/l08/mobys/gunship.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l08/mobys/gunship.c b/src/overlays/l08/mobys/gunship.c index 17fd7a8b58..5cff847e45 100644 --- a/src/overlays/l08/mobys/gunship.c +++ b/src/overlays/l08/mobys/gunship.c @@ -372,7 +372,7 @@ void gunship_update(struct Moby *moby) { truncate_float_to_s32(scale_time(random_float_between(300.0f, 600.0f))); qcopy(&moby->pos, &gunship_control_vars->follow[1].path->points[0]); spawn_gunship_parts(moby); - moby->state = 2; + moby->state = GUNSHIP_FOLLOW_SECONDARY_PATH_AND_FIRE_RANDOMLY; moby->rot.z = fast_arc_tan(gunship_control_vars->follow[1].path->points[1].f[0] - moby->pos.x, gunship_control_vars->follow[1].path->points[1].f[1] - moby->pos.y); @@ -491,7 +491,7 @@ void gunship_update(struct Moby *moby) { case GUNSHIP_BEGIN_PRIMARY_PATH: { LevelPath *path; - moby->state = 1; + moby->state = GUNSHIP_FOLLOW_PRIMARY_PATH_AND_FIRE_AT_TARGET; path = gunship_control_vars->follow[0].path; qcopy(&moby->pos, &path->points[0]); moby->rot.z = From ee5b3779746c0f703e0131b06d460ac9871a8023 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:02:21 +0000 Subject: [PATCH 1046/1502] decomp: clarify names in gadgetron_ceo_update domain_0_value_1 -> GADGETRON_CEO_POLL_DIALOGUE: Retail 0x002e6818 binds s1 to the CEO moby; 0x002e6894 loads its +0x20 state byte for the switch. At 0x002e68bc-0x002e68d4 initialization stores 1 to that same byte and initializes NPC dialogue. The same source selector already names case 1 GADGETRON_CEO_POLL_DIALOGUE. domain_10_value_1 -> GADGETRON_CEO_POLL_DIALOGUE: Retail 0x002e6c8c-0x002e6cc0 handles moby event 2, stores literal 1 into s1+0x20 at 0x002e6ca4, installs the return camera, clears the event, and restores the environment. The written destination is the CEO state selector with existing case 1 GADGETRON_CEO_POLL_DIALOGUE. domain_1_value_2 -> GADGETRON_CEO_WAIT_AFTER_DIALOGUE: Retail 0x002e6958-0x002e6984 polls NPC dialogue, restores initial yaw and starts the dialogue camera transition, then stores 2 to s1+0x20. This is the exact CEO state byte loaded by the switch at 0x002e6894; its source case 2 is already GADGETRON_CEO_WAIT_AFTER_DIALOGUE. domain_4_value_3 -> GADGETRON_CEO_MONITOR_CHALLENGE_EVENTS: Retail 0x002e6a90 loads s2=3 for the activation check; after installing the challenge start camera and saved pose, 0x002e6af8 stores s2 to the CEO state byte s1+0x20 and 0x002e6afc activates the challenge environment. That destination is the switch selector, whose existing case 3 is GADGETRON_CEO_MONITOR_CHALLENGE_EVENTS; this does not rename activation->mode. domain_5_value_3 -> GADGETRON_CEO_MONITOR_CHALLENGE_EVENTS: Retail 0x002e6b04-0x002e6b20 checks player mode 22, then stores s2=3 into s1+0x20 and calls the challenge environment activation helper. The written byte is the CEO state switch selector at 0x002e6894, so the existing GADGETRON_CEO_MONITOR_CHALLENGE_EVENTS member applies to this assignment. domain_6_value_1 -> GADGETRON_CEO_POLL_DIALOGUE: Retail 0x002e6b2c-0x002e6b44 waits until the dialogue gate is not 2, then stores 1 into s1+0x20 before checking the activation previous value. This destination is the same NPC state byte used by the switch at 0x002e6894 and its already named GADGETRON_CEO_POLL_DIALOGUE case. domain_7_value_1 -> GADGETRON_CEO_POLL_DIALOGUE: Retail 0x002e6b64-0x002e6b90 waits for the save gate to become zero, stores 1 at s1+0x20 in the item-grant call delay slot, and requests memcard saving. The assignment targets the exact CEO state selector, whose existing case 1 is GADGETRON_CEO_POLL_DIALOGUE. domain_8_value_1 -> GADGETRON_CEO_POLL_DIALOGUE: Retail 0x002e6c08-0x002e6c24 tests player mode zero, stores 1 to the CEO state byte s1+0x20, and restores the non-challenge environment. The byte is the switch selector loaded at 0x002e6894; reuse its existing GADGETRON_CEO_POLL_DIALOGUE constant rather than a hero or control-mode enum. --- src/overlays/l16/mobys/gadgetron_ceo.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l16/mobys/gadgetron_ceo.c b/src/overlays/l16/mobys/gadgetron_ceo.c index 2bec43d18f..b3138540ab 100644 --- a/src/overlays/l16/mobys/gadgetron_ceo.c +++ b/src/overlays/l16/mobys/gadgetron_ceo.c @@ -186,7 +186,7 @@ void gadgetron_ceo_update(L16ChallengeMoby *ceo_moby) { switch (ceo_moby->state) { case GADGETRON_CEO_INITIALIZE_DIALOGUE: ceo_moby->opacity = 255; - ceo_moby->state = 1; + ceo_moby->state = GADGETRON_CEO_POLL_DIALOGUE; initialize_npc_dialogue(ceo_moby, activation); *(float *)((char *)ceo_data + 0x2C) = 3.7f; ceo_data->initial_yaw = ceo_moby->yaw; @@ -202,7 +202,7 @@ void gadgetron_ceo_update(L16ChallengeMoby *ceo_moby) { if (update_npc_dialogue(ceo_moby, (char *)ceo_data + 0x20)) { ceo_moby->yaw = ceo_data->initial_yaw; begin_dialogue_camera_transition(3.5f, ceo_moby); - ceo_moby->state = 2; + ceo_moby->state = GADGETRON_CEO_WAIT_AFTER_DIALOGUE; } if (!D_0013D4DE && vector_distance_xy(&hero.motion.pos, ceo_moby->position) < 3.5f) { int elapsed, period; @@ -233,11 +233,11 @@ void gadgetron_ceo_update(L16ChallengeMoby *ceo_moby) { camera = (char *)hero.saved_pos_rot; qcopy(camera, pose + 0x20); qcopy(camera + 0x10, pose + 0x30); - ceo_moby->state = 3; + ceo_moby->state = GADGETRON_CEO_MONITOR_CHALLENGE_EVENTS; activate_gadgetron_ceo_challenge_environment((char *)ceo_moby); } if (((L16ChallengePlayer *)((char *)&D_0013E633_challenge + 0xE1D))->mode == 22) { - ceo_moby->state = 3; + ceo_moby->state = GADGETRON_CEO_MONITOR_CHALLENGE_EVENTS; activate_gadgetron_ceo_challenge_environment((char *)ceo_moby); } break; @@ -245,7 +245,7 @@ void gadgetron_ceo_update(L16ChallengeMoby *ceo_moby) { case GADGETRON_CEO_WAIT_AFTER_DIALOGUE: if (*(int *)&D_L16_0015F5C4 != 2) { int previous; - ceo_moby->state = 1; + ceo_moby->state = GADGETRON_CEO_POLL_DIALOGUE; previous = activation->previous; if (previous == 4) { FUN_L16_002923d0(0); @@ -255,7 +255,7 @@ void gadgetron_ceo_update(L16ChallengeMoby *ceo_moby) { break; case GADGETRON_CEO_WAIT_TO_SAVE: if (*(int *)&D_L16_0015F5C4 == 0) { - ceo_moby->state = 1; + ceo_moby->state = GADGETRON_CEO_POLL_DIALOGUE; grant_inventory_item(31, 1); memcard_save_data(0, -1); } @@ -275,7 +275,7 @@ void gadgetron_ceo_update(L16ChallengeMoby *ceo_moby) { D_0015EE6C_p = player->points; } if (((L16ChallengePlayer *)((char *)&D_0013E633_challenge + 0xE1D))->mode == 0) { - ceo_moby->state = 1; + ceo_moby->state = GADGETRON_CEO_POLL_DIALOGUE; restore_gadgetron_ceo_non_challenge_environment((char *)ceo_moby); } event = ceo_moby->event; @@ -299,7 +299,7 @@ void gadgetron_ceo_update(L16ChallengeMoby *ceo_moby) { restore_gadgetron_ceo_non_challenge_environment((char *)ceo_moby); } if (ceo_moby->event == 2) { - ceo_moby->state = 1; + ceo_moby->state = GADGETRON_CEO_POLL_DIALOGUE; set_race_camera(gadgetron_ceo_challenge_return_pose, gadgetron_ceo_challenge_return_pose + 0x10, 0, From 7e42a93dfcc8e60300d7718b6ff3f3e10e0f9b2f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:02:21 +0000 Subject: [PATCH 1047/1502] decomp: clarify names in render_configured_text_label domain_0_value_0 -> FALSE: Source snapshot src/ui/menus/widgets/render_configured_text_label.c SHA-256 5e10fee19cbb6218e0cc55e28fe8a173d8d8d7099c8c8e71ce055d220507a73d assigns value_variant = pal_mode != 0 in the list-selection arm gated by flag 0x8000. Retail 0x0021a454 loads pal_mode from gp-0x7e80 and 0x0021a534 executes sltu s0,zero,v0, explicitly normalizing false/nonzero into a Boolean 0/1 variant. Original Ghidra decompilation corroborates uVar8 = (uint)(uVar2 != 0). Retail 0x0021a658 shifts that variant by two for the text table offset. Existing FALSE=0 therefore fits this Boolean comparison without inferring a video-mode enum or borrowing MENU_ACTION_DISABLED. --- src/ui/menus/widgets/render_configured_text_label.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/menus/widgets/render_configured_text_label.c b/src/ui/menus/widgets/render_configured_text_label.c index 26898f893e..0cacf6c19b 100644 --- a/src/ui/menus/widgets/render_configured_text_label.c +++ b/src/ui/menus/widgets/render_configured_text_label.c @@ -98,7 +98,7 @@ int render_configured_text_label(struct MenuScreen *label) { struct MenuScreen *page = menu_system.current->focus; value_index = page->data.list.selected; if (selector_flags & 0x8000) { - value_variant = pal_mode != 0; + value_variant = pal_mode != FALSE; } } else if (selector_flags & 0x100) { struct MenuScreen *page = menu_system.current->focus; From fd2c27e5e37051fcf2d115ee7312136de8cafbcd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:02:21 +0000 Subject: [PATCH 1048/1502] decomp: clarify names in handle_pause_input domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Authoritative source d8843ebb7e145ce53aead14bdf7a40a0474157546291fa1f2242e57838297fe6 compares hero.vehicle_mode == 2. Retail 0x00298090 forms hero base 0x0013f350; 0x00298094 loads comparison value 2, 0x00298098 lbu reads hero+0x20a4 (0x001413f4), and 0x0029809c branches on inequality. Original Ghidra confirms cRam001413f4 == '\x02'. This is distinct from current state at +0x2084 and control_mode at +0x208c used immediately afterward. The successful gate leads via 0x002980e0/0x00298228 to mode_freeze_init(4,0), consistent with supplied FREEZE_VEHICLE_PAUSE. Thus the selector belongs to supplied HeroVehicleMode in include/rnc/hero/hero_state.h, whose canonical value-2 member is HERO_VEHICLE_MODE_GIANT_CLANK; equal-valued HeroStateId, HeroGravityMode and PAD_R2 do not belong to this selector. --- src/overlays/shared/cutscenes/update_cutscene_playback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/cutscenes/update_cutscene_playback.c b/src/overlays/shared/cutscenes/update_cutscene_playback.c index fa6cadab70..4d60e0f338 100644 --- a/src/overlays/shared/cutscenes/update_cutscene_playback.c +++ b/src/overlays/shared/cutscenes/update_cutscene_playback.c @@ -214,7 +214,7 @@ void handle_pause_input(void) { return; } area = current_level_index; - if (area == 15 && level_timer >= 8 && hero.vehicle_mode == 2 && HELD && + if (area == 15 && level_timer >= 8 && hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && HELD && hero.state.current != 0x72) { if (D_L00_00166E00->h86 == 0x13) return; From f42cc8720ae12b4dc8028c47c56e0d2020498eb9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:02:22 +0000 Subject: [PATCH 1049/1502] decomp: clarify names in hero_switch_item domain_0_value_2 -> HERO_ITEM_SWITCH_MODE_BLOCKED: Authoritative source src/overlays/shared/hero/hero_switch_item.c SHA-256 444e3f82e688928211ab69524bb176bc64cb2318e37469c4b5ab80a25ea53240 loads item_switch_mode from items[i].switch_lock. Retail 0x00210584-0x00210598 computes hero+i*0x50 and loads its byte at +0x10AC; 0x0021059C xori with 2 and 0x002105A4 movz clear changed (s6) exactly for mode 2. The zero changed branch at 0x002105D8 skips the item removal/refresh block. Original Ghidra likewise clears bVar3 when this byte is 2. Thus this is the item-switch blocking mode, independent of hero or moby state IDs. domain_1_value_1 -> HERO_ITEM_SWITCH_MODE_RELOAD_TIMER_WHEN_ZERO: The same source snapshot loads unsigned char item_switch_mode from items[i].switch_lock, a separate slot switch domain. Retail 0x00210590 loads 1 and 0x002105A0 compares that with the +0x10AC byte loaded at 0x00210598. Only equality reaches 0x002105A8-0x002105B8: load signed timer at +0x10A8, skip if nonzero, otherwise load timer_reload byte at +0x10AD and store it to the timer. Original Ghidra shows the identical mode-1 and zero-timer condition. This proves timer reloading when zero, without assigning any hero-state or vehicle-mode semantics. --- src/overlays/shared/hero/hero_switch_item.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index d26817384b..12cb1955d9 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -1928,6 +1928,10 @@ extern void replenish_hero_drones(void) __asm__("FUN_L00_002cdcc0"); void hero_switch_item(int i) __asm__("FUN_L00_0020fea0"); void hero_switch_item(int i) { + enum { + HERO_ITEM_SWITCH_MODE_RELOAD_TIMER_WHEN_ZERO = 1, + HERO_ITEM_SWITCH_MODE_BLOCKED = 2 + }; int changed; int flag6; int flag4; @@ -2176,10 +2180,10 @@ void hero_switch_item(int i) { { struct Hero *s = (struct Hero *)(((char *)&hero) + i * sizeof(struct HeroItemSlot)); item_switch_mode = s->items[0].switch_lock; - if (item_switch_mode == 2) { + if (item_switch_mode == HERO_ITEM_SWITCH_MODE_BLOCKED) { changed = 0; } - if (item_switch_mode == 1 && s->items[0].timer == 0) { + if (item_switch_mode == HERO_ITEM_SWITCH_MODE_RELOAD_TIMER_WHEN_ZERO && s->items[0].timer == 0) { s->items[0].timer = s->items[0].timer_reload; } } From 5e880c97303562e1b81e48e6d9662dbc8b68ed20 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:02:22 +0000 Subject: [PATCH 1050/1502] decomp: clarify names in apply_hero_item_slot_selection domain_0_value_2 -> ITEM_SWITCH_GATE_BLOCK_SWITCH: Current C loads unsigned char item_switch_gate_state from hero.items[i].switch_lock. Retail 0x0023e3ac-0x0023e3c0 computes hero+i*0x50 and loads byte +0x10ac; xori with 2 at 0x0023e3c4 and movz s6,zero,v0 at 0x0023e3cc clear changed when this byte equals 2, preventing the refresh branch at 0x0023e400. Original Ghidra likewise clears bVar3 for this byte value. domain_1_value_1 -> ITEM_SWITCH_GATE_RELOAD_ZERO_TIMER: The same unsigned switch_lock byte loaded at retail 0x0023e3c0 is compared with a1=1 by bne at 0x0023e3c8. On equality, lh +0x10a8 at 0x0023e3d0 checks the slot timer; if zero, lbu +0x10ad and sh +0x10a8 at 0x0023e3dc-0x0023e3e0 reload it from timer_reload. Current C and original Ghidra show precisely this zero-timer reload behavior, proving a switch-gate domain independent of hero state IDs. --- .../shared/hero/process_hero_primary_item_input.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/process_hero_primary_item_input.c b/src/overlays/shared/hero/process_hero_primary_item_input.c index 33eb457a75..40a8c7b51a 100644 --- a/src/overlays/shared/hero/process_hero_primary_item_input.c +++ b/src/overlays/shared/hero/process_hero_primary_item_input.c @@ -131,6 +131,10 @@ void set_hero_item_switch_timer_for_item(int id) __asm__("FUN_L00_0020 void apply_hero_item_slot_selection(int i) __asm__("FUN_L05_0023dc88"); void apply_hero_item_slot_selection(int i) { + enum { + ITEM_SWITCH_GATE_RELOAD_ZERO_TIMER = 1, + ITEM_SWITCH_GATE_BLOCK_SWITCH = 2 + }; int changed; int flag6; int flag4; @@ -388,10 +392,10 @@ void apply_hero_item_slot_selection(int i) { { struct Hero *s = (struct Hero *)(((char *)&hero) + i * sizeof(struct HeroItemSlot)); item_switch_gate_state = s->items[0].switch_lock; - if (item_switch_gate_state == 2) { + if (item_switch_gate_state == ITEM_SWITCH_GATE_BLOCK_SWITCH) { changed = 0; } - if (item_switch_gate_state == 1 && s->items[0].timer == 0) { + if (item_switch_gate_state == ITEM_SWITCH_GATE_RELOAD_ZERO_TIMER && s->items[0].timer == 0) { s->items[0].timer = s->items[0].timer_reload; } } From da35ac8881796b335182e978cc31cbeaf8d28b08 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:02:22 +0000 Subject: [PATCH 1051/1502] decomp: clarify names in spawner_egg_update domain_2_value_2 -> SPAWNER_EGG_STATE_SHRINKING: Retail 0030b958 calls the life timer helper using s2+0x18, then 0030b964-0030b968 stores 2 at s1+0x20 on expiry. s1 is the original moby (0030b3c0), whose same state byte is read at 0030b400 and dispatched as 2 to 0030ba58 (0030b428). That branch decays this egg's scale at 0030ba64-0030ba74 and conditionally removes it. The authoritative function already names this exact state SPAWNER_EGG_STATE_SHRINKING=2. domain_3_value_2 -> SPAWNER_EGG_STATE_SHRINKING: Retail 0030ba40 calls respawn_spawner_child, stores its returned child at s2+0x14 (0030ba48), then loads 2 and stores it to the original egg's s1+0x20 state byte at 0030ba4c-0030ba54. This is the same field read at 0030b400 and dispatched to the scale-decay branch 0030ba58 for value 2. The authoritative switch already uses SPAWNER_EGG_STATE_SHRINKING=2 for that branch, proving canonical reuse regardless of respawn success. --- src/overlays/shared/enemies/spawner_egg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/spawner_egg.c b/src/overlays/shared/enemies/spawner_egg.c index 6ae19dbffd..2e878685e6 100644 --- a/src/overlays/shared/enemies/spawner_egg.c +++ b/src/overlays/shared/enemies/spawner_egg.c @@ -261,7 +261,7 @@ void spawner_egg_update(struct Moby *moby) { } } if (fast_dec_timer_s16(&bubble_vars->life) != 0) { - moby->state = 2; + moby->state = SPAWNER_EGG_STATE_SHRINKING; } moby->rot.x = normalize_angle(bubble_vars->vel.f[0]); moby->rot.y = normalize_angle(bubble_vars->vel.f[1]); @@ -276,7 +276,7 @@ void spawner_egg_update(struct Moby *moby) { moby->pos.w = 0.0f; step.q = ((Vec4 *)&moby->pos)->q; bubble_vars->held = respawn_spawner_child(bubble_vars->owner, &step); - moby->state = 2; + moby->state = SPAWNER_EGG_STATE_SHRINKING; break; case SPAWNER_EGG_STATE_SHRINKING: rate = frame_scale * 0.05f; From 1b24d5ec99d15d92bbcb3ca4f7644e0125ed805f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:02:22 +0000 Subject: [PATCH 1052/1502] decomp: clarify names in update_hoverboard_girl domain_0_value_1 -> HOVERBOARD_GIRL_STATE_UPDATE_DIALOGUE: Retail 0x00316bb4 loads 1 and 0x00316bcc stores it to the moby state byte +0x20 while initializing NPC dialogue at 0x00316bc8. The same byte is loaded at 0x00316af8 and value 1 dispatches to the existing HOVERBOARD_GIRL_STATE_UPDATE_DIALOGUE case at 0x00316be0, which calls update_npc_dialogue. domain_1_value_3 -> HOVERBOARD_GIRL_STATE_WAIT_TO_RESUME_DIALOGUE: Retail 0x00316be4 calls update_npc_dialogue; a nonzero result invokes the camera transition at 0x00316bfc, then 0x00316c04-0x00316c08 writes 3 to the same moby state byte +0x20. Dispatch at 0x00316b1c reaches the existing WAIT_TO_RESUME_DIALOGUE case at 0x00316e3c; this retains state while game_mode is 2 and resumes UPDATE_DIALOGUE otherwise. domain_5_value_2 -> GAME_MODE_CUTSCENE: Retail 0x00316b20 loads game_mode through gp-0x763c, identified as D_L05_0015F5C4 in the source and original decompilation; 0x00316e3c-0x00316e40 compares it to 2. The direct helper update_hoverboard_girl_cutscene_instances loads the same absolute 0x0015f5c4 at 0x00316994-0x00316998 and tests 2 at 0x003169a0/0x003169c4. Its authoritative supplied source already names that same selector/value GAME_MODE_CUTSCENE and applies manipulators to class-matched cutscene instances. This proves domain identity independently of numeric agreement. domain_6_value_1 -> HOVERBOARD_GIRL_STATE_UPDATE_DIALOGUE: Retail 0x00316e40 bypasses resumption while game_mode is 2; otherwise 0x00316e48 stores s4 (loaded with 1 at 0x00316ac4) to moby +0x20. This is the exact selector dispatched at 0x00316af8-0x00316afc to the already named UPDATE_DIALOGUE case, so the existing canonical local member applies. domain_8_value_2 -> GAME_MODE_CUTSCENE: Retail 0x003172e4-0x003172e8 loads the absolute game_mode at 0x0015f5c4, then 0x003172ec-0x003172f0 skips ordinary instance joint updates when it is 2. The direct cutscene-instance helper instead handles class-matched instances only for the same global value at 0x00316998-0x003169c4; its supplied source establishes GAME_MODE_CUTSCENE = 2. Both loads address the exact same mode selector, distinct from moby, dialogue and hero state domains. --- src/overlays/l05/mobys/hoverboard_girl.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/overlays/l05/mobys/hoverboard_girl.c b/src/overlays/l05/mobys/hoverboard_girl.c index 6ef08b95ff..5a8eea6436 100644 --- a/src/overlays/l05/mobys/hoverboard_girl.c +++ b/src/overlays/l05/mobys/hoverboard_girl.c @@ -202,6 +202,9 @@ void hoverboard_girl_update(HoverboardGirlMoby *moby) { HOVERBOARD_GIRL_STATE_UPDATE_DIALOGUE = 1, HOVERBOARD_GIRL_STATE_WAIT_TO_RESUME_DIALOGUE = 3 }; + enum { + GAME_MODE_CUTSCENE = 2 + }; HoverboardGirlState *state = moby->data; HoverboardGirlVector target_position; HoverboardGirlVector head_position; @@ -228,14 +231,14 @@ void hoverboard_girl_update(HoverboardGirlMoby *moby) { entries[dialogue_entry_index]->state = 13; } state->dialogue_name = race_girl_name; - moby->state = 1; + moby->state = HOVERBOARD_GIRL_STATE_UPDATE_DIALOGUE; initialize_npc_dialogue(moby, state); initialize_moby_grounding(moby); break; case HOVERBOARD_GIRL_STATE_UPDATE_DIALOGUE: if (update_npc_dialogue(moby, state) != 0) { begin_dialogue_camera_transition(2.0f, moby); - moby->state = 3; + moby->state = HOVERBOARD_GIRL_STATE_WAIT_TO_RESUME_DIALOGUE; } if (state->dialogue_state == 3) { state->previous_dialogue_state = state->dialogue_state; @@ -284,8 +287,8 @@ void hoverboard_girl_update(HoverboardGirlMoby *moby) { } break; case HOVERBOARD_GIRL_STATE_WAIT_TO_RESUME_DIALOGUE: - if (game_mode != 2) { - moby->state = 1; + if (game_mode != GAME_MODE_CUTSCENE) { + moby->state = HOVERBOARD_GIRL_STATE_UPDATE_DIALOGUE; if (state->previous_dialogue_state == 4) { alternate_item_available = 1; queue_dialogue_message(0x1395, scale_game_frames(300)); @@ -381,7 +384,7 @@ void hoverboard_girl_update(HoverboardGirlMoby *moby) { breast_growth_count_gp = state->breast_growth_count_gp; } } - if (game_mode != 2) { + if (game_mode != GAME_MODE_CUTSCENE) { update_hoverboard_girl_boobs_animation(moby, state); if (big_head_cheat_enabled != 0) state->joints[0].target_scale = 2.75f; From 622f3d3a44b8aef045b2553bc931490388ec9ec8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:04:10 +0000 Subject: [PATCH 1053/1502] decomp: clarify names in update_toxic_crab_hit_reactions_and_targeting domain_0_value_1 -> TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION: Source snapshot src/overlays/l10/mobys/toxic_crab.c SHA-256 6414abd79c9897e18726e9b924be96e0a493c2ef803fb1d8b80a351bd6e1aba6 shows toxic_crab_update passing its own m directly to this function before switching on m->state. Retail retains that argument in s3 at 0x002e3f04 and accesses the same state byte at +0x20; original Ghidra uses param_1+0x20. Thus this selector is the toxic crab state domain already named by the caller's local enum, not HeroStateId, HeroVehicleMode or hit_response_code. At 0x002e3f54-0x002e3f5c retail compares this byte with 1 before activation. Caller case WAIT_FOR_ACTIVATION handles this same value by waiting for activation conditions. domain_10_value_1 -> TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION: Source snapshot src/overlays/l10/mobys/toxic_crab.c SHA-256 6414abd79c9897e18726e9b924be96e0a493c2ef803fb1d8b80a351bd6e1aba6 shows toxic_crab_update passing its own m directly to this function before switching on m->state. Retail retains that argument in s3 at 0x002e3f04 and accesses the same state byte at +0x20; original Ghidra uses param_1+0x20. Thus this selector is the toxic crab state domain already named by the caller's local enum, not HeroStateId, HeroVehicleMode or hit_response_code. Retail 0x002e4750-0x002e4784 writes state 1 when within 1 of the stored home position after prolonged target loss, subject to the separate vehicle-mode check, and selects idle animation 0. Caller case WAIT_FOR_ACTIVATION consumes this same value 1. domain_1_value_2 -> TOXIC_CRAB_STATE_ACTIVATE: Source snapshot src/overlays/l10/mobys/toxic_crab.c SHA-256 6414abd79c9897e18726e9b924be96e0a493c2ef803fb1d8b80a351bd6e1aba6 shows toxic_crab_update passing its own m directly to this function before switching on m->state. Retail retains that argument in s3 at 0x002e3f04 and accesses the same state byte at +0x20; original Ghidra uses param_1+0x20. Thus this selector is the toxic crab state domain already named by the caller's local enum, not HeroStateId, HeroVehicleMode or hit_response_code. At 0x002e3f64-0x002e3f68 retail writes 2 to the same byte after the item-linked activation path. Caller case ACTIVATE handles value 2 with activation timing/animation before pursuit or facing. domain_2_value_11 -> TOXIC_CRAB_STATE_DEATH_EFFECTS: Source snapshot src/overlays/l10/mobys/toxic_crab.c SHA-256 6414abd79c9897e18726e9b924be96e0a493c2ef803fb1d8b80a351bd6e1aba6 shows toxic_crab_update passing its own m directly to this function before switching on m->state. Retail retains that argument in s3 at 0x002e3f04 and accesses the same state byte at +0x20; original Ghidra uses param_1+0x20. Thus this selector is the toxic crab state domain already named by the caller's local enum, not HeroStateId, HeroVehicleMode or hit_response_code. At 0x002e4018-0x002e4020 retail excludes state 11 from hit processing. Caller case DEATH_EFFECTS for 11 spawns death particles/explosions and removes the moby; the death response writes 11 at 0x002e44f8. domain_3_value_12 -> TOXIC_CRAB_STATE_FALL_TO_DEATH: Source snapshot src/overlays/l10/mobys/toxic_crab.c SHA-256 6414abd79c9897e18726e9b924be96e0a493c2ef803fb1d8b80a351bd6e1aba6 shows toxic_crab_update passing its own m directly to this function before switching on m->state. Retail retains that argument in s3 at 0x002e3f04 and accesses the same state byte at +0x20; original Ghidra uses param_1+0x20. Thus this selector is the toxic crab state domain already named by the caller's local enum, not HeroStateId, HeroVehicleMode or hit_response_code. At 0x002e4024-0x002e4028 retail excludes state 12 from hit processing. Caller case FALL_TO_DEATH handles 12 by integrating downward motion and probing ground before death effects/removal; its knockback branch assigns 12 when below home height. domain_4_value_10 -> TOXIC_CRAB_STATE_HIT_KNOCKBACK: Source snapshot src/overlays/l10/mobys/toxic_crab.c SHA-256 6414abd79c9897e18726e9b924be96e0a493c2ef803fb1d8b80a351bd6e1aba6 shows toxic_crab_update passing its own m directly to this function before switching on m->state. Retail retains that argument in s3 at 0x002e3f04 and accesses the same state byte at +0x20; original Ghidra uses param_1+0x20. Thus this selector is the toxic crab state domain already named by the caller's local enum, not HeroStateId, HeroVehicleMode or hit_response_code. Retail 0x002e4390-0x002e4398 writes state 10 in the shared knockback-response branch, followed by a 60-frame timer and knockback vector setup. Caller case HIT_KNOCKBACK consumes value 10 with step_moby_motion(m, crab_data->v70). domain_5_value_10 -> TOXIC_CRAB_STATE_HIT_KNOCKBACK: Source snapshot src/overlays/l10/mobys/toxic_crab.c SHA-256 6414abd79c9897e18726e9b924be96e0a493c2ef803fb1d8b80a351bd6e1aba6 shows toxic_crab_update passing its own m directly to this function before switching on m->state. Retail retains that argument in s3 at 0x002e3f04 and accesses the same state byte at +0x20; original Ghidra uses param_1+0x20. Thus this selector is the toxic crab state domain already named by the caller's local enum, not HeroStateId, HeroVehicleMode or hit_response_code. Retail 0x002e4414-0x002e4420 writes state 10 in the vehicle-dependent knockback branch, then initializes knockback strength at 0x002e4440-0x002e4474. Caller case HIT_KNOCKBACK consumes the same value 10 with step_moby_motion. domain_6_value_11 -> TOXIC_CRAB_STATE_DEATH_EFFECTS: Source snapshot src/overlays/l10/mobys/toxic_crab.c SHA-256 6414abd79c9897e18726e9b924be96e0a493c2ef803fb1d8b80a351bd6e1aba6 shows toxic_crab_update passing its own m directly to this function before switching on m->state. Retail retains that argument in s3 at 0x002e3f04 and accesses the same state byte at +0x20; original Ghidra uses param_1+0x20. Thus this selector is the toxic crab state domain already named by the caller's local enum, not HeroStateId, HeroVehicleMode or hit_response_code. Retail 0x002e44f0-0x002e4504 writes state 11 and clears flag 0x1000 for lethal/death hit responses. Caller case DEATH_EFFECTS for 11 emits particles/explosions and removes the crab. domain_7_value_1 -> TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION: Source snapshot src/overlays/l10/mobys/toxic_crab.c SHA-256 6414abd79c9897e18726e9b924be96e0a493c2ef803fb1d8b80a351bd6e1aba6 shows toxic_crab_update passing its own m directly to this function before switching on m->state. Retail retains that argument in s3 at 0x002e3f04 and accesses the same state byte at +0x20; original Ghidra uses param_1+0x20. Thus this selector is the toxic crab state domain already named by the caller's local enum, not HeroStateId, HeroVehicleMode or hit_response_code. Retail 0x002e454c-0x002e4554 tests state 1 to select special targeting range logic, including zero range unless hero contact is present. Caller case WAIT_FOR_ACTIVATION consumes the same state value and waits for activation conditions. domain_8_value_1 -> TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION: Source snapshot src/overlays/l10/mobys/toxic_crab.c SHA-256 6414abd79c9897e18726e9b924be96e0a493c2ef803fb1d8b80a351bd6e1aba6 shows toxic_crab_update passing its own m directly to this function before switching on m->state. Retail retains that argument in s3 at 0x002e3f04 and accesses the same state byte at +0x20; original Ghidra uses param_1+0x20. Thus this selector is the toxic crab state domain already named by the caller's local enum, not HeroStateId, HeroVehicleMode or hit_response_code. Retail 0x002e46c4-0x002e46cc compares state with 1 and bypasses target-loss counting for that state. Caller case WAIT_FOR_ACTIVATION identifies value 1 as the waiting state; this function resets the target-loss counter for it. domain_9_value_8 -> TOXIC_CRAB_STATE_RETURN_HOME: Source snapshot src/overlays/l10/mobys/toxic_crab.c SHA-256 6414abd79c9897e18726e9b924be96e0a493c2ef803fb1d8b80a351bd6e1aba6 shows toxic_crab_update passing its own m directly to this function before switching on m->state. Retail retains that argument in s3 at 0x002e3f04 and accesses the same state byte at +0x20; original Ghidra uses param_1+0x20. Thus this selector is the toxic crab state domain already named by the caller's local enum, not HeroStateId, HeroVehicleMode or hit_response_code. Retail 0x002e4704-0x002e4734 measures distance to pvars+0x170, then writes state 8 when distance exceeds 1 after prolonged target loss, choosing animation 4. Caller initializes v170 from the starting position and case RETURN_HOME (8) steers toward v170. --- src/overlays/l10/mobys/toxic_crab.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/overlays/l10/mobys/toxic_crab.c b/src/overlays/l10/mobys/toxic_crab.c index 67d252a471..2257488f1f 100644 --- a/src/overlays/l10/mobys/toxic_crab.c +++ b/src/overlays/l10/mobys/toxic_crab.c @@ -1012,6 +1012,14 @@ void update_toxic_crab_hit_reactions_and_targeting(void *mv) { ARC_ADJUSTED_KNOCKBACK_HIT_RESPONSE = 10, SUPPRESSED_HIT_RESPONSE = 11 }; + enum { + TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION = 1, + TOXIC_CRAB_STATE_ACTIVATE = 2, + TOXIC_CRAB_STATE_RETURN_HOME = 8, + TOXIC_CRAB_STATE_HIT_KNOCKBACK = 10, + TOXIC_CRAB_STATE_DEATH_EFFECTS = 0xB, + TOXIC_CRAB_STATE_FALL_TO_DEATH = 0xC + }; Moby *moby = mv; AlignedVec4f vA; AlignedVec4f vB; @@ -1029,8 +1037,8 @@ void update_toxic_crab_hit_reactions_and_targeting(void *mv) { if (((Hero *)(((char *)&hero)))->items[0].item_id == 0x15) { if (((D_2E52B0 *)((Hero *)(((char *)&hero)))->items[0].moby->pvars)->f10 == moby) { func_L10_002E14F8_2E52B0(moby); - if (moby->state == 1) - moby->state = 2; + if (moby->state == TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION) + moby->state = TOXIC_CRAB_STATE_ACTIVATE; } } if (moby_data->f38 != 0) { @@ -1046,7 +1054,7 @@ void update_toxic_crab_hit_reactions_and_targeting(void *mv) { hit_response_code = resolve_moby_hit_response(moby, hit_record, &moby_data->f20, 0, &A, &B, 0, 4); fast_dec_timer_s16(&moby_data->h26); - if ((unsigned int)A >= 2 && moby->state != 0xB && moby->state != 0xC) { + if ((unsigned int)A >= 2 && moby->state != TOXIC_CRAB_STATE_DEATH_EFFECTS && moby->state != TOXIC_CRAB_STATE_FALL_TO_DEATH) { if (current_level_index == 10 && hit_record != 0 && hit_record->f20 != 0 && hit_record->f20->oclass == 0x31A) { if (moby_data->f1AC != 0 && item_unlocked[0x11] == 0) { @@ -1119,7 +1127,7 @@ void update_toxic_crab_hit_reactions_and_targeting(void *mv) { case ANIMATED_KNOCKBACK_HIT_RESPONSE: case HIT_DIRECTED_KNOCKBACK_HIT_RESPONSE: case ARC_ADJUSTED_KNOCKBACK_HIT_RESPONSE: - moby->state = 10; + moby->state = TOXIC_CRAB_STATE_HIT_KNOCKBACK; moby_data->h26 = scale_game_frames(60); moby_data->f80 = toxic_crab_hit_knockback_gravity_gp * D_0015ED70; trooper_set_knockback(moby_data->a70, 0.5f, 0.5f); @@ -1134,7 +1142,7 @@ void update_toxic_crab_hit_reactions_and_targeting(void *mv) { case VEHICLE_SCALED_KNOCKBACK_HIT_RESPONSE: case VEHICLE_DEPENDENT_KNOCKBACK_HIT_RESPONSE: { float knockback_strength; - moby->state = 10; + moby->state = TOXIC_CRAB_STATE_HIT_KNOCKBACK; moby_data->h26 = scale_game_frames(60); moby_data->f80 = toxic_crab_hit_knockback_gravity_gp * D_0015ED70; knockback_strength = ((Hero *)(((char *)&hero)))->vehicle_mode == 1 ? 1.0f : 3.0f; @@ -1151,7 +1159,7 @@ void update_toxic_crab_hit_reactions_and_targeting(void *mv) { } case LETHAL_HIT_RESPONSE: case DEATH_HIT_RESPONSE: - moby->state = 11; + moby->state = TOXIC_CRAB_STATE_DEATH_EFFECTS; moby->flags &= 0xEFFF; break; case NO_STATE_TRANSITION_HIT_RESPONSE: @@ -1167,7 +1175,7 @@ void update_toxic_crab_hit_reactions_and_targeting(void *mv) { } if (moby_data->f1AC != 0) { moby_data->f1A0 = D_L10_00161E40_gp + 6.0f; - } else if (moby->state == 1) { + } else if (moby->state == TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION) { if (moby == ((Moby *)((Hero *)(((char *)&hero)))->unk240) || moby == ((Moby *)((Hero *)(((char *)&hero)))->coll_hit_moby)) { moby_data->f1A0 = 6.0f; @@ -1198,15 +1206,15 @@ void update_toxic_crab_hit_reactions_and_targeting(void *mv) { l10_paths[moby_data->f1B0]->points, l10_paths[moby_data->f1B0]->count); } - if (moby->state != 1 && moby_data->f164 == 2) { + if (moby->state != TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION && moby_data->f164 == 2) { moby_data->f1D4++; if (scale_game_frames(300) < moby_data->f1D4) { if (1.0f < fast_vec_dist(&moby->pos, &moby_data->a170)) { - moby->state = 8; + moby->state = TOXIC_CRAB_STATE_RETURN_HOME; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(12)); } else if (((Hero *)(((char *)&hero)))->vehicle_mode != 1) { - moby->state = 1; + moby->state = TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(20)); } From 727630ea635776d83f1734434cc8c9b037499075 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:04:10 +0000 Subject: [PATCH 1054/1502] decomp: clarify names in update_doom_bot_spawner domain_0_value_2 -> THROWN_MOBY_STATE_MOVE_WITH_COLLISION: Retail 002c8ad4 loads the thrown Moby state byte at +0x20(s3), and 002c8ad8 compares it unsigned against 2 before updating flags. The identical +0x20 byte selects the six-entry state switch at 002c8b88..002c8ba8. Its established local enum names 2 THROWN_MOBY_STATE_MOVE_WITH_COLLISION; that branch integrates velocity and resolves collision at 002c8d34..002c9008. Reuse this member as the ordering boundary without changing the less-than comparison. domain_1_value_1 -> THROWN_MOBY_STATE_GROW_TO_QUARTER_SCALE: In initialization, retail 002c8bb0 loads 1 and 002c8bbc stores it to the same Moby state byte +0x20(s3) used by the switch. Its next dispatch selects case 1 at 002c8bd0, where 002c8bdc..002c8c18 compares scale against pclass scale times 0.25 and grows below that threshold. The source already names that exact selector member THROWN_MOBY_STATE_GROW_TO_QUARTER_SCALE. domain_2_value_3 -> THROWN_MOBY_STATE_SPAWN_SEQUENCE: The collision settling path increments and stores the halfword timer at 002c8f6c..002c8f70, tests collision ownership and signed timer duration, then stores 3 into +0x20(s3) at 002c8fa8 and clears the timer. This is the same Moby state selector loaded at 002c8b88. Its existing case 3 THROWN_MOBY_STATE_SPAWN_SEQUENCE at 002c900c counts active class-00ba objects and calls established spawn_doom_bot at 002c9194. domain_3_value_4 -> THROWN_MOBY_STATE_FADE_OUT: After spawn_doom_bot at 002c9194, retail 002c91a4..002c91b8 increments spawn_count and tests it against four. 002c91bc..002c91c0 stores 4 to the Moby state byte +0x20(s3), the switch selector. The source's existing case 4 THROWN_MOBY_STATE_FADE_OUT reaches 002c9200, reducing scale and alpha at 002c9220..002c9238 and eventually removing the Moby at 002c9284. domain_4_value_0 -> THROWN_MOBY_STATE_INITIALIZE: Retail 002c9294 stores zero directly to the switch's Moby state byte +0x20(s3), reached by case 5 and default. Zero dispatches to the existing THROWN_MOBY_STATE_INITIALIZE case at 002c8bb0, which enters growth state 1 and initializes effect_timer, spawn_count and timer at 002c8bbc..002c8bcc. Thus the assignment reuses INITIALIZE, rather than naming its destination after the reset branch. --- src/overlays/shared/weapons/glove_of_doom_bomb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/weapons/glove_of_doom_bomb.c b/src/overlays/shared/weapons/glove_of_doom_bomb.c index 1ceb6e170e..588be21529 100644 --- a/src/overlays/shared/weapons/glove_of_doom_bomb.c +++ b/src/overlays/shared/weapons/glove_of_doom_bomb.c @@ -209,7 +209,7 @@ void doom_bot_spawner_update(struct Moby *thrown_moby) { if (thrown_moby->pos.x < 2.0f || 1021.0f < thrown_moby->pos.x || thrown_moby->pos.y < 2.0f || 1021.0f < thrown_moby->pos.y || thrown_moby->pos.z < 2.0f || 1021.0f < thrown_moby->pos.z) goto remove; - if (hero.unk20A5 && thrown_moby->state < 2) + if (hero.unk20A5 && thrown_moby->state < THROWN_MOBY_STATE_MOVE_WITH_COLLISION) thrown_moby->flags |= 0x41; else thrown_moby->flags &= 0xffbe; @@ -222,7 +222,7 @@ void doom_bot_spawner_update(struct Moby *thrown_moby) { } switch (thrown_moby->state) { case THROWN_MOBY_STATE_INITIALIZE: - thrown_moby->state = 1; + thrown_moby->state = THROWN_MOBY_STATE_GROW_TO_QUARTER_SCALE; spawner_throw_vars->effect_timer = scale_game_frames(4); spawner_throw_vars->timer = 0; spawner_throw_vars->spawn_count = 0; @@ -310,7 +310,7 @@ void doom_bot_spawner_update(struct Moby *thrown_moby) { spawner_throw_vars->timer = settled; if (!coll_hit.moby || coll_hit.unk1C > 0 || (settled_frames = (s16)settled, scale_game_frames(240) < settled_frames)) { - thrown_moby->state = 3; + thrown_moby->state = THROWN_MOBY_STATE_SPAWN_SEQUENCE; spawner_throw_vars->timer = 0; } } @@ -368,7 +368,7 @@ void doom_bot_spawner_update(struct Moby *thrown_moby) { s32 spawned = spawner_throw_vars->spawn_count + 1; spawner_throw_vars->spawn_count = spawned; if (spawned > 3) - thrown_moby->state = 4; + thrown_moby->state = THROWN_MOBY_STATE_FADE_OUT; } } } @@ -399,6 +399,6 @@ void doom_bot_spawner_update(struct Moby *thrown_moby) { } case THROWN_MOBY_STATE_RESET_TO_INITIALIZE: default: - thrown_moby->state = 0; + thrown_moby->state = THROWN_MOBY_STATE_INITIALIZE; } } From c31621df7cbee1c62a7f72dad4eb026b8c5beec2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:04:11 +0000 Subject: [PATCH 1055/1502] decomp: clarify names in process_moby_attachment_damage domain_0_value_6 -> STARFIGHTER_STATE_OWNER_UNAVAILABLE: Retail 002e9a84-002e9a8c reads moby+0x20 and excludes states >=6. The supplied update_qwarks_starfighter passes this same moby to this function and names its +0x20 selector state 6 STARFIGHTER_STATE_OWNER_UNAVAILABLE; its owner validity checks assign 6. This is the starfighter state domain, not HeroStateId. domain_10_value_1 -> ATTACHMENT_DAMAGE_APPLIED: Retail 002e9fac-002e9fd4 subtracts child hit damage from shared health, sets s8/source mode to 1 and starts reaction animation. Later stage crossing can overwrite it with 2. This is the same applied-damage outcome as the first attachment branch. domain_11_value_7 -> STARFIGHTER_STATE_DEATH_FLIGHT: The child path calls death helper 002e97e0 at 002e9f88 after health <= damage, then 002e9fec-002e9ff4 compares moby+0x20 with 7. Supplied death helper assigns STARFIGHTER_STATE_DEATH_FLIGHT=7; the caller dispatches the same moby's starfighter state. domain_12_value_5 -> STARFIGHTER_STATE_TRACTOR_BEAM: Retail child-path 002ea084-002ea098 compares moby+0x20 with 5 and stores 4 during a health-stage transition. Supplied caller passes this same moby from STARFIGHTER_STATE_TRACTOR_BEAM=5, proving the starfighter state domain rather than equal-valued unrelated enums. domain_13_value_4 -> STARFIGHTER_STATE_FOLLOW_COMMAND_PATH_WITH_TIMED_VOLLEY: Retail 002ea094-002ea098 stores 4 to the same moby+0x20 selector after detecting tractor state 5 in the child damage path. Supplied update_qwarks_starfighter dispatches this exact domain with state 4 named STARFIGHTER_STATE_FOLLOW_COMMAND_PATH_WITH_TIMED_VOLLEY and passes that moby to this function. domain_14_value_2 -> ATTACHMENT_DAMAGE_STAGE_ADVANCED: Retail 002ea038 tests health below the stage threshold, detaches the indexed attachment, increments moby+0xBC at 002ea09c-002ea0a4, resets voice/flags and sets s8/source mode to 2 at 002ea12c. This is the child-path stage-advance damage outcome. domain_15_value_0 -> ATTACHMENT_DAMAGE_NONE: Source mode>0 guards post-damage voice processing. Retail 002ea1b8 uses blez s8 to bypass it; s8 is initialized zero and receives only damage outcomes 1, 2 and 3. The zero boundary therefore means no attachment damage processed. domain_1_value_0 -> ATTACHMENT_DAMAGE_NONE: Retail 002e9aa4 initializes s8 (source mode) to zero before either attachment hit path. 002e9e30 and 002ea1b0 continue child scanning only while it remains zero; 002ea1b8 bypasses damage voice processing for zero. It records that no damage outcome has yet been applied. domain_2_value_3 -> ATTACHMENT_DAMAGE_LETHAL: Retail 002e9c08-002e9c30 compares health at data+0x20 against hit+0x2C, calls begin_starfighter_death_sequence at 002e97e0 when damage exhausts health, and sets s8/source mode to 3. Thus 3 identifies the lethal damage outcome. domain_3_value_1 -> ATTACHMENT_DAMAGE_APPLIED: Retail 002e9c48-002e9c78 subtracts hit damage from shared health, sets s8/source mode to 1, resets reaction timer and starts the hit animation. A later threshold crossing overwrites it with 2. Value 1 records ordinary applied damage before any stage advance. domain_4_value_7 -> STARFIGHTER_STATE_DEATH_FLIGHT: Retail 002e9c28 calls 002e97e0 for lethal health depletion, then 002e9c88-002e9c90 compares that same moby+0x20 with 7. Supplied begin_starfighter_death_sequence assigns STARFIGHTER_STATE_DEATH_FLIGHT=7 to that moby, and update_qwarks_starfighter dispatches the same state domain. domain_5_value_5 -> STARFIGHTER_STATE_TRACTOR_BEAM: Retail 002e9d1c-002e9d30 compares moby+0x20 with 5 and replaces it with 4 on damage-stage crossing. Supplied update_qwarks_starfighter names this same selector STARFIGHTER_STATE_TRACTOR_BEAM=5 and calls this function with its own moby from that case; attachment and steering helpers corroborate state 5. domain_6_value_4 -> STARFIGHTER_STATE_FOLLOW_COMMAND_PATH_WITH_TIMED_VOLLEY: Retail 002e9d2c-002e9d30 stores 4 into moby+0x20 when leaving tractor state 5 on a damage-stage crossing. Supplied caller passes this same moby and names state 4 STARFIGHTER_STATE_FOLLOW_COMMAND_PATH_WITH_TIMED_VOLLEY; attack-command code uses state 4 for timed rocket volleys. domain_7_value_2 -> ATTACHMENT_DAMAGE_STAGE_ADVANCED: Retail 002e9ccc tests health below stage threshold; 002e9d34-002e9d3c increments moby+0xBC, with attachment detachment, voice release and flags reset, then 002e9dbc sets s8/source mode to 2. It marks damage that advanced the command/damage stage. domain_8_value_0 -> ATTACHMENT_DAMAGE_NONE: Source for-loop continues only while mode==0; retail 002e9e30 and 002ea1b0 test s8 against zero. Damage branches set s8 to 1, 2 or 3, so this comparison specifically selects the no-damage-outcome state, separate from moby state and damage-stage selectors. domain_9_value_3 -> ATTACHMENT_DAMAGE_LETHAL: In the child attachment path, 002e9f68-002e9f90 compares shared health to hit damage, calls death helper 002e97e0 on depletion and sets s8/source mode to 3. This is the same lethal damage outcome as the first-attachment path. --- src/overlays/l13/mobys/qwarks_starfighter.c | 42 +++++++++++++-------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/overlays/l13/mobys/qwarks_starfighter.c b/src/overlays/l13/mobys/qwarks_starfighter.c index bd7d8af7d8..2c3f3484c4 100644 --- a/src/overlays/l13/mobys/qwarks_starfighter.c +++ b/src/overlays/l13/mobys/qwarks_starfighter.c @@ -723,6 +723,16 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { CHILD_HIT_HALF_DAMAGE = 0x127, CHILD_HIT_FIXED_DAMAGE = 0x3F1 }; + enum { + ATTACHMENT_DAMAGE_NONE = 0, + ATTACHMENT_DAMAGE_APPLIED = 1, + ATTACHMENT_DAMAGE_STAGE_ADVANCED = 2, + ATTACHMENT_DAMAGE_LETHAL = 3, + STARFIGHTER_STATE_FOLLOW_COMMAND_PATH_WITH_TIMED_VOLLEY = 4, + STARFIGHTER_STATE_TRACTOR_BEAM = 5, + STARFIGHTER_STATE_OWNER_UNAVAILABLE = 6, + STARFIGHTER_STATE_DEATH_FLIGHT = 7 + }; int hit; int rf; int mode; @@ -736,9 +746,9 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { Hit_2EAE80 *r; Sub *dd; - if (moby->state < 6) { + if (moby->state < STARFIGHTER_STATE_OWNER_UNAVAILABLE) { dd = &moby_data->sub; - mode = 0; + mode = ATTACHMENT_DAMAGE_NONE; rf = 0; k6 = 6.0f; step = (float)dd->max_health / k6; @@ -763,17 +773,17 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { } if (dd->health <= r->f2C) { func_L13_002EAC18_2EAE80(moby, moby_data, dd, r); - mode = 3; + mode = ATTACHMENT_DAMAGE_LETHAL; moby_data->first->bA4 = 0xFF; } else { dd->health = dd->health - r->f2C; moby_data->b67 = 0xFA; - mode = 1; + mode = ATTACHMENT_DAMAGE_APPLIED; moby_data->sub.h6 = scale_game_frames(0); func_L00_0025E4B0_2EAE80(moby, moby_data->q60); moby_data->first->bA4 = 0xFF; } - if (moby->state == 7) { + if (moby->state == STARFIGHTER_STATE_DEATH_FLIGHT) { moby->bBC++; rf = 1; { @@ -791,8 +801,8 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { allocate_voice_for_target_entry(7, 0, moby); func_L13_002EAAB8_2EAE80(moby, moby_data, tv); } - if (moby->state == 5) { - moby->state = 4; + if (moby->state == STARFIGHTER_STATE_TRACTOR_BEAM) { + moby->state = STARFIGHTER_STATE_FOLLOW_COMMAND_PATH_WITH_TIMED_VOLLEY; } moby->bBC++; if (moby_data->i11C != -1) { @@ -813,7 +823,7 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { } moby_data->h138 = 0; moby_data->b148 = 0; - mode = 2; + mode = ATTACHMENT_DAMAGE_STAGE_ADVANCED; if (moby->bBC == 7) { for (j = moby->bBC - 1; j < 10; j++) { func_L13_002EAAB8_2EAE80(moby, moby_data, l13_starfighter_attachment_slot_indices_by_command[j]); @@ -825,7 +835,7 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { } } } - for (i = 0; i < 11 && mode == 0; i++) { + for (i = 0; i < 11 && mode == ATTACHMENT_DAMAGE_NONE; i++) { if (moby_data->list[i] == 0) { continue; } @@ -855,17 +865,17 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { } if (dd->health <= r->f2C) { func_L13_002EAC18_2EAE80(moby, moby_data, dd, r); - mode = 3; + mode = ATTACHMENT_DAMAGE_LETHAL; moby_data->list[i]->bA4 = 0xFF; } else { dd->health = dd->health - r->f2C; moby_data->b67 = 0xFA; - mode = 1; + mode = ATTACHMENT_DAMAGE_APPLIED; moby_data->sub.h6 = scale_game_frames(0); func_L00_0025E4B0_2EAE80(moby, moby_data->q60); moby_data->list[i]->bA4 = 0xFF; } - if (moby->state == 7) { + if (moby->state == STARFIGHTER_STATE_DEATH_FLIGHT) { moby->bBC++; rf = 1; { @@ -883,8 +893,8 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { func_L13_002EAAB8_2EAE80(moby, moby_data, tv); } allocate_voice_for_target_entry(7, 0, moby); - if (moby->state == 5) { - moby->state = 4; + if (moby->state == STARFIGHTER_STATE_TRACTOR_BEAM) { + moby->state = STARFIGHTER_STATE_FOLLOW_COMMAND_PATH_WITH_TIMED_VOLLEY; } moby->bBC++; if (moby_data->i11C != -1) { @@ -905,7 +915,7 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { } moby_data->h138 = 0; moby_data->b148 = 0; - mode = 2; + mode = ATTACHMENT_DAMAGE_STAGE_ADVANCED; if (moby->bBC == 7) { for (k = moby->bBC - 1; k < 10; k++) { func_L13_002EAAB8_2EAE80(moby, moby_data, l13_starfighter_attachment_slot_indices_by_command[k]); @@ -916,7 +926,7 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { moby_data->b148 = 1; } } - if (mode > 0) { + if (mode > ATTACHMENT_DAMAGE_NONE) { if (rf != 0) { switch (moby->bBC - 1) { case DAMAGE_STAGE_SKIP_LINE_QUEUE: From f27c92d5b09cfa7c596b4f4a1903bb8075fe056e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:04:11 +0000 Subject: [PATCH 1056/1502] decomp: clarify names in dreks_fleet_turret_update domain_0_value_1 -> FLEET_TURRET_WAIT_FOR_TARGET: Retail 0x002cb374 loads 1 and 0x002cb380 stores it to s3+0x20 during initialization; 0x002cb34c reads that identical moby state byte for dispatch. Source already names its case 1 FLEET_TURRET_WAIT_FOR_TARGET, whose branch tests zone visibility or hero-ship proximity before acquisition. domain_1_value_2 -> FLEET_TURRET_AIM_AND_FIRE_AT_ZONE: Retail 0x002cb480 calls the zone collision ray, 0x002cb488 skips on obstruction, and 0x002cb490/0x002cb498 store 2 to s3+0x20 when clear. This is the same byte dispatched at 0x002cb34c; source case 2 is already FLEET_TURRET_AIM_AND_FIRE_AT_ZONE and computes zone-based aiming and projectile spawning. domain_2_value_3 -> FLEET_TURRET_AIM_AND_FIRE_AT_HERO_SHIP: Retail 0x002cb49c-0x002cb4c0 checks hero state, ship pointer and ship class 0x563; 0x002cb4cc-0x002cb4e8 checks distance below 254 before 0x002cb4ec/0x002cb4f4 store 3 to s3+0x20. The existing case 3 on this same state byte is FLEET_TURRET_AIM_AND_FIRE_AT_HERO_SHIP and validates the ship then aims and fires. domain_3_value_1 -> FLEET_TURRET_WAIT_FOR_TARGET: In retail zone-firing case 2, 0x002cb4fc reads the hero flag and 0x002cb500 bypasses the reset while nonzero; otherwise 0x002cb508/0x002cb50c store 1 to s3+0x20. This restores the identical dispatch byte to the existing FLEET_TURRET_WAIT_FOR_TARGET case, which performs acquisition tests. domain_4_value_1 -> FLEET_TURRET_WAIT_FOR_TARGET: Retail 0x002cb86c-0x002cb890 tests the hero state, ship pointer and class in ship-firing case 3. Failed tests reach 0x002cb894/0x002cb898 and store 1 to s3+0x20 before returning. That same state byte dispatches to existing FLEET_TURRET_WAIT_FOR_TARGET; this is a return to acquisition when the required ship is absent. --- src/overlays/l17/mobys/dreks_fleet_turret.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l17/mobys/dreks_fleet_turret.c b/src/overlays/l17/mobys/dreks_fleet_turret.c index 173ca094b0..fbd036f7b3 100644 --- a/src/overlays/l17/mobys/dreks_fleet_turret.c +++ b/src/overlays/l17/mobys/dreks_fleet_turret.c @@ -102,7 +102,7 @@ void dreks_fleet_turret_update(struct Moby *turret_moby) { process_dreks_fleet_turret_hits(turret_moby); switch (turret_moby->state) { case FLEET_TURRET_INITIALIZE: - turret_moby->state = 1; + turret_moby->state = FLEET_TURRET_WAIT_FOR_TARGET; turret_vars->f20 = 15.0f; turret_vars->s24 = 0xF; distribute_group_blarg_ships_along_path(turret_moby); @@ -121,13 +121,13 @@ void dreks_fleet_turret_update(struct Moby *turret_moby) { fast_vec_add(from, from, targeting_vector_scratch); from[2] += 0.5f; if (collision_line(targeting_vector_scratch, from, 2, turret_moby, 0) == 0) { - turret_moby->state = 2; + turret_moby->state = FLEET_TURRET_AIM_AND_FIRE_AT_ZONE; } } else if (g->state.current == 0x32) { char *hero_ship_moby = ((char *)g->ship_moby); if (hero_ship_moby != 0 && MOBY(hero_ship_moby)->oclass == 0x563) { if (vector_distance_xy(&turret_moby->pos, &g->motion.pos) < 254.0f) { - turret_moby->state = 3; + turret_moby->state = FLEET_TURRET_AIM_AND_FIRE_AT_HERO_SHIP; } } } @@ -135,7 +135,7 @@ void dreks_fleet_turret_update(struct Moby *turret_moby) { } case FLEET_TURRET_AIM_AND_FIRE_AT_ZONE: { if (hero.unk308 == 0) { - turret_moby->state = 1; + turret_moby->state = FLEET_TURRET_WAIT_FOR_TARGET; } { float j[8]; @@ -205,7 +205,7 @@ void dreks_fleet_turret_update(struct Moby *turret_moby) { struct Hero *g = &hero; if (g->state.current != 0x32 || ((char *)g->ship_moby) == 0 || g->ship_moby->oclass != 0x563) { - turret_moby->state = 1; + turret_moby->state = FLEET_TURRET_WAIT_FOR_TARGET; } else { Aim347 aim; float j[8]; From cbaf489170c14399d2999ea906c34812536ae0dc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:06:02 +0000 Subject: [PATCH 1057/1502] decomp: clarify names in update_hero_in_vehicle_mode domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: The SHA-256-bound source src/overlays/shared/hero/hero_idle_sequence.c (ce278edbb2b51d4dc66e73dc1a63c0317d621ac142401b36ae7bb841233a5e97) explicitly compares hero.vehicle_mode == 2. Retail 0x00206860 establishes s0=&hero.motion.pos (hero+0x80), 0x0020686c establishes s1=hero, and 0x00206870 lbu v1,0x20a4(s1) is compared with li v0,2 at 0x00206874/0x00206878. The prepared decompilation independently tests cRam001413f4 == 2 (0x0013f350+0x20a4). This is the same vehicle_mode field used by coordinate_hero_frame_update to dispatch this pipeline, not state.current at +0x2084, control mode, or glow palette at +0x22fe. The provided HeroVehicleMode enum in include/rnc/hero/hero_state.h canonically defines HERO_VEHICLE_MODE_GIANT_CLANK=2. The selected branch calls update_hero_bone_attachment at 0x002068b4 and samples bone point 6 into hero+0x1d80 at 0x002068d4..0x002068e4; the supplied draw_hero_glow_quads source consumes that same position under HERO_VEHICLE_MODE_GIANT_CLANK. Domain and member reuse are therefore established by selector identity and matching data flow, not numeric coincidence. --- src/overlays/shared/hero/hero_idle_sequence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index d10a82432a..d0859d1b59 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -920,7 +920,7 @@ void update_hero_in_vehicle_mode(void) { } } reveal_map_around_position(&hero.motion.pos); - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { struct Hero *g = &hero; if (D_0015EDB3_macro) *(f32 *)((char *)&D_L00_0017B85C_lui + 0x210) = 1.4f * D_0015EE18_gp; From 0038258fc2fd031a8515f48846c1e4bac0256f82 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:06:02 +0000 Subject: [PATCH 1058/1502] decomp: clarify names in update_help_hints domain_0_value_1 -> TUTORIAL_HINT_STATE_UPDATE: Retail 0x0030acf8-0x0030ad04 loads moby+0x20 and dispatches value 1 to the update branch at 0x0030ad30. Initialization at 0x0030ad1c/0x0030ad24 stores 1 to that identical state byte. Authoritative C already names this selector's case 1 TUTORIAL_HINT_STATE_UPDATE; reuse that existing member for the transition assignment. domain_1_value_0 -> HELP_STATE_INACTIVE: Retail 0x0030ae50-0x0030ae84 reads the playback state at 0x00179890, requires zero, and also requires cur at +0x24 to be -1 before level-availability hint 0x3E8/4. Authoritative C binds those reads to help_state.state and help_state.cur, distinct from moby->state and hero control modes. Prepared help_request C names the identical state==0 and cur==-1 admission condition HELP_STATE_INACTIVE before setting the pending message; this proves the help-playback domain and inactive meaning. domain_2_value_0 -> HELP_STATE_INACTIVE: Retail 0x0030aeac-0x0030aee0 reads the playback state at 0x00179890, requires zero, and also requires cur at +0x24 to be -1 before level-availability hint 0x3E9/5. Authoritative C binds those reads to help_state.state and help_state.cur, distinct from moby->state and hero control modes. Prepared help_request C names the identical state==0 and cur==-1 admission condition HELP_STATE_INACTIVE before setting the pending message; this proves the help-playback domain and inactive meaning. domain_3_value_0 -> HELP_STATE_INACTIVE: Retail 0x0030af08-0x0030af48 reads the playback state at 0x00179890, requires zero, and also requires cur at +0x24 to be -1 before combined level-availability hint 0x3EA/6. Authoritative C binds those reads to help_state.state and help_state.cur, distinct from moby->state and hero control modes. Prepared help_request C names the identical state==0 and cur==-1 admission condition HELP_STATE_INACTIVE before setting the pending message; this proves the help-playback domain and inactive meaning. domain_4_value_0 -> HELP_STATE_INACTIVE: Retail 0x0030af8c-0x0030b004 reads the playback state at 0x00179890, requires zero, and also requires cur at +0x24 to be -1 before elapsed-usage hint 0x3EF/0x43. Authoritative C binds those reads to help_state.state and help_state.cur, distinct from moby->state and hero control modes. Prepared help_request C names the identical state==0 and cur==-1 admission condition HELP_STATE_INACTIVE before setting the pending message; this proves the help-playback domain and inactive meaning. domain_5_value_0 -> HELP_STATE_INACTIVE: Retail 0x0030b050-0x0030b084 reads the playback state at 0x00179890, requires zero, and also requires cur at +0x24 to be -1 before clip-volume hint 0x3EC/0x40. Authoritative C binds those reads to help_state.state and help_state.cur, distinct from moby->state and hero control modes. Prepared help_request C names the identical state==0 and cur==-1 admission condition HELP_STATE_INACTIVE before setting the pending message; this proves the help-playback domain and inactive meaning. domain_6_value_0 -> HELP_STATE_INACTIVE: Retail 0x0030b0e4-0x0030b11c reads the playback state at 0x00179890, requires zero, and also requires cur at +0x24 to be -1 before follow-up hint 0x3ED/0x41. Authoritative C binds those reads to help_state.state and help_state.cur, distinct from moby->state and hero control modes. Prepared help_request C names the identical state==0 and cur==-1 admission condition HELP_STATE_INACTIVE before setting the pending message; this proves the help-playback domain and inactive meaning. domain_7_value_0 -> HELP_STATE_INACTIVE: Retail 0x0030b224-0x0030b284 reads the playback state at 0x00179890, requires zero, and also requires cur at +0x24 to be -1 before clip-volume usage-counter and hint processing. Authoritative C binds those reads to help_state.state and help_state.cur, distinct from moby->state and hero control modes. Prepared help_request C names the identical state==0 and cur==-1 admission condition HELP_STATE_INACTIVE before setting the pending message; this proves the help-playback domain and inactive meaning. domain_8_value_0 -> HELP_STATE_INACTIVE: Retail 0x0030b4a4-0x0030b4b8 reads the playback state at 0x00179890, requires zero, and also requires cur at +0x24 to be -1 before nearby health-hint candidate processing. Authoritative C binds those reads to help_state.state and help_state.cur, distinct from moby->state and hero control modes. Prepared help_request C names the identical state==0 and cur==-1 admission condition HELP_STATE_INACTIVE before setting the pending message; this proves the help-playback domain and inactive meaning. --- src/overlays/l01/mobys/help_hints.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l01/mobys/help_hints.c b/src/overlays/l01/mobys/help_hints.c index 73938cda6b..6127bf06a1 100644 --- a/src/overlays/l01/mobys/help_hints.c +++ b/src/overlays/l01/mobys/help_hints.c @@ -38,7 +38,7 @@ void help_hints_update(struct Moby *moby) { enum { TUTORIAL_HINT_STATE_INITIALIZE = 0, TUTORIAL_HINT_STATE_UPDATE = 1 - }; + } ; enum { HELP_STATE_INACTIVE = 0}; s32 *tutorial_hint_vars; struct Moby *hint_candidate_moby; struct Moby *health_hint_candidate_moby; @@ -50,7 +50,7 @@ void help_hints_update(struct Moby *moby) { case TUTORIAL_HINT_STATE_INITIALIZE: tutorial_hint_vars[5] = 0; moby->update_dist = 0xFF; - moby->state = 1; + moby->state = TUTORIAL_HINT_STATE_UPDATE; tutorial_hint_vars[10] = 0; break; case TUTORIAL_HINT_STATE_UPDATE: @@ -72,22 +72,22 @@ void help_hints_update(struct Moby *moby) { } } if (cutscene_mode_macro == 0) { - if (level_available[3] != 0 && level_available[2] == 0 && help_state.state == 0 && + if (level_available[3] != 0 && level_available[2] == 0 && help_state.state == HELP_STATE_INACTIVE && help_state.cur == -1 && help_records[4].count == 0) { help_request(0x3E8, 4); } else if (level_available[3] == 0 && level_available[2] != 0 && - help_state.state == 0 && help_state.cur == -1 && + help_state.state == HELP_STATE_INACTIVE && help_state.cur == -1 && help_records[5].count == 0) { help_request(0x3E9, 5); } else if (level_available[3] != 0 && level_available[2] != 0 && - help_state.state == 0 && help_state.cur == -1 && + help_state.state == HELP_STATE_INACTIVE && help_state.cur == -1 && help_records[6].count == 0 && help_records[4].count == 0) { help_request(0x3EA, 6); } } if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_vars[15]) && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && - help_state.state == 0 && help_state.cur == -1) { + help_state.state == HELP_STATE_INACTIVE && help_state.cur == -1) { usage_time_value = scale_game_frames(D_0015EEA4_macro) - usage_stats.stat[9].latest_time_bucket * 600; /* "< 1" rather than "!": cc1 would otherwise test the bit as (v >> level) & 1 */ @@ -98,13 +98,13 @@ void help_hints_update(struct Moby *moby) { } if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_vars[14]) && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && - D_L01_0015F68C < 3 && help_state.state == 0 && help_state.cur == -1 && + D_L01_0015F68C < 3 && help_state.state == HELP_STATE_INACTIVE && help_state.cur == -1 && help_records[0x40].count == 0) { help_request(0x3EC, 0x40); } if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_vars[14]) && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && - hero.state.current == 1 && D_L01_0015F688 == -1 && help_state.state == 0 && + hero.state.current == 1 && D_L01_0015F688 == -1 && help_state.state == HELP_STATE_INACTIVE && help_state.cur == -1 && help_records[0x40].count != 0 && help_records[0x41].count == 0) { help_request(0x3ED, 0x41); @@ -125,7 +125,7 @@ void help_hints_update(struct Moby *moby) { } } if (hero.state.control_mode == 0x12 && tutorial_hint_vars[10] == 0 && - help_state.state == 0 && help_state.cur == -1 && + help_state.state == HELP_STATE_INACTIVE && help_state.cur == -1 && (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_vars[8]) || is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_vars[9]))) { tutorial_hint_vars[11]++; @@ -167,7 +167,7 @@ void help_hints_update(struct Moby *moby) { health_hint_candidate_moby = health_hint_candidate_moby->next) { if (health_hint_candidate_moby->oclass == 0x326 && fast_vec_dist(&health_hint_candidate_moby->pos, &hero.motion.pos) < 10.0f && - help_state.state == 0 && help_state.cur == -1 && help_records[1].count == 0 && + help_state.state == HELP_STATE_INACTIVE && help_state.cur == -1 && help_records[1].count == 0 && help_records[2].count == 0 && usage_stats.stat[13].count == 0 && is_moby_in_state_one(health_hint_candidate_moby) == 0) { if (hero.health.hp < hero_max_health) { From f628a2391de5265d69a326a39533347c7112460a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:06:03 +0000 Subject: [PATCH 1059/1502] decomp: clarify names in mine_layer_update domain_0_value_1 -> MINE_LAYER_FACE_TARGET_AND_WAIT_FOR_RANGE: Initialization stores 1 to the same moby state byte at s2+0x20 (0x002ca048-0x002ca050) loaded for switch dispatch at 0x002c9f5c-0x002c9f84. Existing local enum member MINE_LAYER_FACE_TARGET_AND_WAIT_FOR_RANGE names case 1, whose 0x002ca084-0x002ca124 branch turns toward target aim and tests XY range and height before advancing. domain_1_value_2 -> MINE_LAYER_WAIT_FOR_ANIMATION_BEFORE_PATROL: After target XY and height gates at 0x002ca0d4-0x002ca110, li v0,2 and sb v0,0x20(s2) at 0x002ca114/0x002ca124 assign the exact state byte used by the switch. This reuses its existing MINE_LAYER_WAIT_FOR_ANIMATION_BEFORE_PATROL member; case 2 at 0x002ca14c waits for anim_flags & 2 before entering patrol state 3. domain_2_value_3 -> MINE_LAYER_PATROL_AND_FIRE: The animation flag test at 0x002ca14c-0x002ca154 gates li v0,3 and sb v0,0x20(s2) at 0x002ca158/0x002ca164, followed by patrol and firing timer setup. This is the switch's same state field and existing MINE_LAYER_PATROL_AND_FIRE member: case 3 moves along path points at 0x002ca1b0-0x002ca32c and fires timer-driven projectiles at 0x002ca330-0x002ca4b8. domain_3_value_1 -> MINE_LAYER_FACE_TARGET_AND_WAIT_FOR_RANGE: In the patrol branch, arrival within 1 unit, an expired patrol timer and target XY distance greater than 25 lead to li v0,1 at 0x002ca24c and sb v0,0x20(s2) at 0x002ca258, then animation sequence 0. The destination is the same dispatch byte whose existing case 1, MINE_LAYER_FACE_TARGET_AND_WAIT_FOR_RANGE, turns toward target aim and waits for range. domain_4_value_1 -> MINE_LAYER_FACE_TARGET_AND_WAIT_FOR_RANGE: In existing MINE_LAYER_KNOCKBACK_AND_RECOVER, step_moby_motion result mask 0x60 at 0x002ca4c8-0x002ca4d8 gates restoration of animation sequence 0 and li v0,1 / sb v0,0x20(s2) at 0x002ca508-0x002ca510. This writes the same switch state byte and returns to existing case 1 MINE_LAYER_FACE_TARGET_AND_WAIT_FOR_RANGE, rather than a hero state or control mode. domain_5_value_4 -> MINE_LAYER_KNOCKBACK_AND_RECOVER: The post-switch lbu v0,0x20(s2) and sltiu v0,v0,4 at 0x002ca658-0x002ca65c compare the very same moby state byte used for dispatch. Existing local enum MINE_LAYER_KNOCKBACK_AND_RECOVER equals 4 and names the first knockback case at 0x002ca4c8; the comparison restricts ordinary gravity/ground probing to preceding states 0-3 while cases 4 and 5 use step_moby_motion. Reusing this member preserves the exact numeric boundary. --- src/overlays/l03/mobys/mine_layer.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l03/mobys/mine_layer.c b/src/overlays/l03/mobys/mine_layer.c index 67f2aca9ae..f08635f1f4 100644 --- a/src/overlays/l03/mobys/mine_layer.c +++ b/src/overlays/l03/mobys/mine_layer.c @@ -176,7 +176,7 @@ void mine_layer_update(struct Moby *mine_layer_moby) { qcopy(&mine_layer_moby->pos, &path->points[0]); mine_layer_vars->patrol.idx = 1; mine_layer_moby->scale *= mine_layer_initial_scale_multiplier_gp; - mine_layer_moby->state = 1; + mine_layer_moby->state = MINE_LAYER_FACE_TARGET_AND_WAIT_FOR_RANGE; if (mine_layer_moby->prev_seq != 0) { blend_moby_animation(mine_layer_moby, 0, 0, 0); } @@ -191,7 +191,7 @@ void mine_layer_update(struct Moby *mine_layer_moby) { mine_layer_vars->turn); if (vector_distance_xy(&mine_layer_moby->pos, &target.aim) < sight && absolute_float(target.aim.f[2] - mine_layer_moby->pos.z) < 4.0f) { - mine_layer_moby->state = 2; + mine_layer_moby->state = MINE_LAYER_WAIT_FOR_ANIMATION_BEFORE_PATROL; if (mine_layer_moby->prev_seq != 1) { blend_moby_animation(mine_layer_moby, 1, 0, scale_game_frames(10)); } @@ -199,7 +199,7 @@ void mine_layer_update(struct Moby *mine_layer_moby) { break; case MINE_LAYER_WAIT_FOR_ANIMATION_BEFORE_PATROL: if (mine_layer_moby->anim_flags & 2) { - mine_layer_moby->state = 3; + mine_layer_moby->state = MINE_LAYER_PATROL_AND_FIRE; mine_layer_vars->patrol_timer = scale_game_frames(120); if (mine_layer_moby->prev_seq != 2) { blend_moby_animation(mine_layer_moby, 2, 0, scale_game_frames(10)); @@ -220,7 +220,7 @@ void mine_layer_update(struct Moby *mine_layer_moby) { if (fast_vec_dist(&mine_layer_moby->pos, &pt->path->points[patrol_point_index]) < 1.0f) { if (mine_layer_vars->patrol_timer == 0 && vector_distance_xy(&mine_layer_moby->pos, &target.aim) > 25.0f) { - mine_layer_moby->state = 1; + mine_layer_moby->state = MINE_LAYER_FACE_TARGET_AND_WAIT_FOR_RANGE; if (mine_layer_moby->prev_seq != 0) { blend_moby_animation(mine_layer_moby, 0, 0, scale_game_frames(10)); } @@ -267,7 +267,7 @@ void mine_layer_update(struct Moby *mine_layer_moby) { if (mine_layer_moby->prev_seq != 0) { blend_moby_animation(mine_layer_moby, 0, 0, scale_game_frames(10)); } - mine_layer_moby->state = 1; + mine_layer_moby->state = MINE_LAYER_FACE_TARGET_AND_WAIT_FOR_RANGE; } else if (mine_layer_moby->pos.z < 5.0f) { qcopy(muzzle, &mine_layer_moby->pos); muzzle[2] += 0.5f; @@ -323,7 +323,7 @@ void mine_layer_update(struct Moby *mine_layer_moby) { } break; } - if (mine_layer_moby->state < 4) { + if (mine_layer_moby->state < MINE_LAYER_KNOCKBACK_AND_RECOVER) { mine_layer_vars->fall_speed += frame_time_sq * 9.8f; mine_layer_moby->pos.z -= mine_layer_vars->fall_speed - 2.0f; ground = probe_ground_height(&mine_layer_moby->pos, 0, 0.5f); From 1c11894e93e3b41f3ed5265a5776ad37ad19dc6e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:06:03 +0000 Subject: [PATCH 1060/1502] decomp: clarify names in update_mine domain_0_value_3 -> MINE_ARM_AND_MONITOR_PROXIMITY: Retail 0x002cbf7c loads 3 and 0x002cbf8c stores it to mine s3+0x20 after the motion helper reports landing; 0x002cbfb8 initializes the arming timer. The same mine+0x20 selects the source switch whose existing MINE_ARM_AND_MONITOR_PROXIMITY branch decrements that timer at 0x002cc074-0x002cc078 and monitors proximity. domain_3_value_2 -> MINE_HOME_ON_TARGET: Retail 0x002cc0c4-0x002cc0d4 stores 2 into mine s3+0x20 when target distance is below 3 and the arming timer is zero. This is the exact field dispatched at 0x002cbf40; its existing MINE_HOME_ON_TARGET branch at 0x002cbfe4-0x002cc068 subtracts mine position from target position and adds a scaled displacement to the mine. domain_4_value_5 -> MINE_SHRINK_AND_REMOVE: Retail age/target checks at 0x002cc0e4-0x002cc13c select 5 and store it into mine s3+0x20, the same state selector loaded at 0x002cbf40. Existing MINE_SHRINK_AND_REMOVE branch 0x002cc774-0x002cc7dc decays the mine scale and removes it below the class-scale threshold, proving reuse of that local state member. domain_5_value_4 -> MINE_EXPLODE_AND_REMOVE: Retail hero XY and vertical proximity checks at 0x002cc144-0x002cc198 select 4 and 0x002cc1a4 stores it to mine s3+0x20. This exact field drives the existing MINE_EXPLODE_AND_REMOVE case, whose 0x002cc224-0x002cc768 branch sends blast hits, creates debris, shakes the camera and removes the mine. domain_6_value_4 -> MINE_EXPLODE_AND_REMOVE: Retail 0x002cc1c8 loads 4 into a3; flagged nearby-moby and target/timer tests at 0x002cc1f0-0x002cc220 store a3 to mine s3+0x20. This is the exact dispatched state field, and the source's existing MINE_EXPLODE_AND_REMOVE branch 0x002cc224-0x002cc768 performs blast/debris effects followed by removal. domain_7_value_1 -> MINE_DEBRIS_WIDE_SPAWN_RADIUS: Retail random-below-four result is retained as kind in s0 at 0x002cc2e0-0x002cc2f0. Comparison with s8=1 at 0x002cc3b0 uniquely raises the radius upper bound from 0.25 to 0.5 at 0x002cc3b8-0x002cc3bc. The same s0 comparison at 0x002cc454 dispatches the existing MINE_DEBRIS_WIDE_SPAWN_RADIUS case; cos/sin and mine-position addition at 0x002cc3d8-0x002cc40c prove the radial spawn role. --- src/overlays/l03/mobys/mine.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l03/mobys/mine.c b/src/overlays/l03/mobys/mine.c index 06a9564cf9..8585221da4 100644 --- a/src/overlays/l03/mobys/mine.c +++ b/src/overlays/l03/mobys/mine.c @@ -83,7 +83,7 @@ void mine_layer_mine_update(struct Moby *mine_moby) { break; case MINE_FALL_UNTIL_LANDING: if (step_moby_motion(mine_moby, mine_vars) & 1) { - mine_moby->state = 3; + mine_moby->state = MINE_ARM_AND_MONITOR_PROXIMITY; if (mine_moby->prev_seq != 1) { blend_moby_animation(mine_moby, 1, 0, scale_game_frames(10)); } @@ -109,17 +109,17 @@ void mine_layer_mine_update(struct Moby *mine_moby) { if (target_moby != 0 && target_moby->state != 0xFE && target_moby->state != 0xFD && vector_distance_xy(&mine_moby->pos, &target_moby->pos) < 3.0f && mine_vars->timer == 0) { - mine_moby->state = 2; + mine_moby->state = MINE_HOME_ON_TARGET; allocate_voice_for_target_entry(2, 0, mine_moby); } if (scale_game_frames(3600) < mine_vars->age && (mine_vars->target == 0 || mine_vars->target->state == 0xFE || mine_vars->target->state == 0xFD || scale_game_frames(5400) < mine_vars->age)) { - mine_moby->state = 5; + mine_moby->state = MINE_SHRINK_AND_REMOVE; } if (vector_distance_xy(&hero.moby->pos, &mine_moby->pos) < 0.5f && absolute_float(mine_moby->pos.z - hero.motion.pos.f[2]) < 0.25f) { - mine_moby->state = 4; + mine_moby->state = MINE_EXPLODE_AND_REMOVE; break; } nearby_moby_count = collect_mobies_in_sphere(&mine_moby->pos, 0x10, mine_moby, 0, 1.0f); @@ -128,7 +128,7 @@ void mine_layer_mine_update(struct Moby *mine_moby) { if ((nearby_moby->flags & 0x1000) && (nearby_moby != mine_vars->target || mine_vars->timer == 0)) { - mine_moby->state = 4; + mine_moby->state = MINE_EXPLODE_AND_REMOVE; break; } } @@ -170,7 +170,7 @@ void mine_layer_mine_update(struct Moby *mine_moby) { debris_vector_scratch[2] = random_float_between(frame_time * 4.0f, vector_scratch[kind]); *(OvlQuad *)debris_velocity = *(OvlQuad *)debris_vector_scratch; - rr = random_float_between(0.0f, kind == 1 ? 0.5f : 0.25f); + rr = random_float_between(0.0f, kind == MINE_DEBRIS_WIDE_SPAWN_RADIUS ? 0.5f : 0.25f); debris_azimuth = random_angle_radians(); debris_vector_scratch[0] = fast_cos(debris_azimuth) * rr; debris_vector_scratch[1] = fast_sin(debris_azimuth) * rr; From 256efeb1703c50fb9bccdf9ff5f52eac474ba120 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:06:03 +0000 Subject: [PATCH 1061/1502] decomp: clarify names in update_bomber_tank_damage_and_aim domain_0_value_0 -> BOMBER_TANK_STATE_INITIALIZE: Retail 0x002d4cb4 preserves the moby argument in s5; 0x002d4dac-0x002d4db0 loads its state byte at +0x20 and skips damage for zero. Checked caller 0x002d42e4 preserves the same argument in s2 and passes it directly at 0x002d4374-0x002d4378; 0x002d4380/0x002d43a8 dispatches that same +0x20 state byte, with zero entering part allocation at 0x002d43f0-0x002d450c and health/aim initialization through 0x002d4744. This proves the same state domain as the existing caller-local BOMBER_TANK_STATE_INITIALIZE = 0 in the authoritative source. domain_2_value_2 -> BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM: Retail 0x002d4ce8 loads moby pvars into s4; 0x002d5378-0x002d5380 compares pvars+0xF4 with 2. That branch centers yaw/pitch at +0x170/+0x178 through 0x002d549c-0x002d550c instead of calculating target-relative aim at 0x002d5388-0x002d548c. The checked caller passes the identical moby at 0x002d4378 and loads its same pvars at 0x002d4310; mode +0xF4 == 2 suppresses activation/firing transitions at 0x002d4754-0x002d4758, 0x002d47f0-0x002d4820 and 0x002d4a24-0x002d4a28. This is the exact mode domain already named BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM = 2 in update_bomber_tank, separate from moby states. --- src/overlays/l08/mobys/bomber_tank.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l08/mobys/bomber_tank.c b/src/overlays/l08/mobys/bomber_tank.c index b885eba221..bb08244b8e 100644 --- a/src/overlays/l08/mobys/bomber_tank.c +++ b/src/overlays/l08/mobys/bomber_tank.c @@ -419,6 +419,10 @@ extern int bomber_tank_part_3_destroyed_by_class_661_gp __asm__("D_L08_0015F5B8" __attribute__((sda)); void update_bomber_tank_damage_and_aim(Moby *moby) { + enum { + BOMBER_TANK_STATE_INITIALIZE = 0, + BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM = 2 + }; Data *bomber_tank_damage_and_aim_vars = (Data *)moby->pvars; Hit_2D5FA8 *source; Hit_2D5FA8 *part_a_source; @@ -448,7 +452,7 @@ void update_bomber_tank_damage_and_aim(Moby *moby) { resolve_moby_hit_response( moby, source, &bomber_tank_damage_and_aim_vars->health, 0, &hit, &damage, 0, 4); one = 1; - if (hit != one && moby->state != 0) { + if (hit != one && moby->state != BOMBER_TANK_STATE_INITIALIZE) { bomber_tank_damage_and_aim_vars->health -= damage; if (damage != 0.0f) allocate_voice_for_target_entry(4, 0, moby); @@ -671,7 +675,7 @@ void update_bomber_tank_damage_and_aim(Moby *moby) { ((Path *)l08_paths[bomber_tank_damage_and_aim_vars->path])->count); if (bomber_tank_damage_and_aim_vars->fF0 == 0) bomber_tank_damage_and_aim_vars->fF0 = *(int *)D_001413D0; - if (bomber_tank_damage_and_aim_vars->mode != 2) { + if (bomber_tank_damage_and_aim_vars->mode != BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM) { float yaw, distance, pitch; fast_vec_sub(burst_position_or_aim_scratch, bomber_tank_damage_and_aim_vars->target, From c511d417babf2ef8c0e84d1d3185ac043ce6dbae Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:06:03 +0000 Subject: [PATCH 1062/1502] decomp: clarify names in mine_glove_update domain_0_value_3 -> MINE_GLOVE_RELEASE_HELD_MOBY: Retail 002c1cd4..002c1cd8 stores 3 into 0x20(s5), the same glove moby state loaded at 002c2258 for dispatch. Its existing case MINE_GLOVE_RELEASE_HELD_MOBY at 002c22b4 calls initialize_moby_motion_at_position at 002c22c4 with held moby and pvars, then clears held at 002c2378. Reuse the source's exact domain member. domain_1_value_1 -> MINE_GLOVE_WAIT_FOR_ANIMATION: In initialization, retail 002c2284..002c2298 tests anim_flags at 0x70(s5), selects 1 when bit 2 is clear, and stores to glove state 0x20(s5). This is the same selector dispatched at 002c2258; existing case MINE_GLOVE_WAIT_FOR_ANIMATION at 002c229c..002c22b0 waits for that bit before advancing. domain_4_value_4 -> MINE_GLOVE_POST_RELEASE_WAIT: Retail 002c2388..002c2394 stores 4 to the same glove state 0x20(s5) after the held-moby release path and sets countdown +0x58 at 002c239c. Existing MINE_GLOVE_POST_RELEASE_WAIT case 002c23a0..002c23c4 waits for hero state !=0x23 and item animation inactive before leaving 4. This assignment and named case share the exact selector. domain_6_value_6 -> MINE_GLOVE_REMOVE_HELD_MOBY: Existing MINE_GLOVE_BEGIN_HELD_MOBY_REMOVAL case at retail 002c23c8..002c23d0 stores 6 into glove moby state 0x20(s5), the dispatch selector at 002c2258. Existing MINE_GLOVE_REMOVE_HELD_MOBY case 002c23d4..002c23e8 calls mark_moby_for_removal on non-null held and clears it; reuse that exact domain constant. --- src/overlays/shared/weapons/mine_glove.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/weapons/mine_glove.c b/src/overlays/shared/weapons/mine_glove.c index 5584bd02ca..81c9d0fd6b 100644 --- a/src/overlays/shared/weapons/mine_glove.c +++ b/src/overlays/shared/weapons/mine_glove.c @@ -185,7 +185,7 @@ void mine_glove_update(struct Moby *moby) { (hero.state.current == 0x23 && hero.state_timer == scale_game_frames(0x10))) { allocate_hero_voice_for_entry(0x1A, 0); use_ammo(-1, 1); - moby->state = 3; + moby->state = MINE_GLOVE_RELEASE_HELD_MOBY; } } if (mine_glove_vars->held != 0 && !hero.item_use_locked) { @@ -274,7 +274,7 @@ void mine_glove_update(struct Moby *moby) { case MINE_GLOVE_INITIALIZE: mine_glove_vars->held = 0; if (!(moby->anim_flags & 2)) - moby->state = 1; + moby->state = MINE_GLOVE_WAIT_FOR_ANIMATION; else moby->state = 2; case MINE_GLOVE_WAIT_FOR_ANIMATION: @@ -301,7 +301,7 @@ void mine_glove_update(struct Moby *moby) { mine_glove_vars->held = 0; mine_glove_vars->timer54 = scale_game_frames(10); } - moby->state = 4; + moby->state = MINE_GLOVE_POST_RELEASE_WAIT; mine_glove_vars->timer58 = scale_game_frames(0x14); break; case MINE_GLOVE_POST_RELEASE_WAIT: @@ -309,7 +309,7 @@ void mine_glove_update(struct Moby *moby) { moby->state = 2; break; case MINE_GLOVE_BEGIN_HELD_MOBY_REMOVAL: - moby->state = 6; + moby->state = MINE_GLOVE_REMOVE_HELD_MOBY; break; case MINE_GLOVE_REMOVE_HELD_MOBY: if (mine_glove_vars->held != 0) { From b78ab62c74b8b0f8c3950e6fed7d83aeb9e50fe6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:06:03 +0000 Subject: [PATCH 1063/1502] decomp: clarify names in blarg_ship_update domain_0_value_1 -> BLARG_SHIP_FOLLOW_PATH: Retail 0x002f415c loads 1 and 0x002f4178 stores it to moby+0x20, the exact field dispatched at 0x002f411c-0x002f413c. The source names that switch member BLARG_SHIP_FOLLOW_PATH; its branch advances and wraps path progress/index at 0x002f41e0-0x002f429c and calls the path-transform helper at 0x002f42ac. domain_1_value_4 -> BLARG_SHIP_INACTIVE: Initialization tests pvars+0x88 at retail 0x002f4150-0x002f4158 and branches to 0x002f49c8, loading 4 and storing it into moby+0x20 at 0x002f49cc, clearing collision and setting flag bit 1. This is the same switch selector as existing BLARG_SHIP_INACTIVE=4, whose source branch does no work; supplied activation source selects this state before restoring collision and entering state 5. domain_2_value_2 -> BLARG_SHIP_BURST_AND_HIDE: Retail 0x002f42b4 loads moby+0x20, the switch selector, and 0x002f42b8-0x002f42bc compares it with 2. The matching branch bursts, drops a pickup and emits an effect at 0x002f42c4-0x002f431c, then enters state 3 with collision cleared. The authoritative local enum already names selector value 2 BLARG_SHIP_BURST_AND_HIDE. domain_3_value_3 -> BLARG_SHIP_WAIT_TO_REACTIVATE: After the state-2 burst/drop/effect branch, retail 0x002f4324-0x002f4328 selects 3 and jumps to the moby+0x20 store at 0x002f49cc, also hiding and clearing collision. The same selector's existing BLARG_SHIP_WAIT_TO_REACTIVATE=3 branch at 0x002f4368-0x002f4428 waits for sphere/distance/timer tests before restoring state 1 and class collision. domain_4_value_3 -> BLARG_SHIP_WAIT_TO_REACTIVATE: For an invisible path-following craft, retail 0x002f432c-0x002f4358 checks distance to hero against 32; 0x002f435c loads 3 and 0x002f4360 branches to the moby+0x20 state store at 0x002f49cc. The authoritative switch on that exact field already names 3 BLARG_SHIP_WAIT_TO_REACTIVATE, whose branch waits then restores state 1, flags and collision. domain_5_value_1 -> BLARG_SHIP_FOLLOW_PATH: Retail 0x002f43d8-0x002f43e4 passes the reactivation timer test and loads 1; 0x002f43f0 stores it to moby+0x20, followed by animation/flag/class-collision restoration at 0x002f43f4-0x002f4428. This exact switch selector already has BLARG_SHIP_FOLLOW_PATH=1, whose branch advances the path progress/index and updates the path transform. domain_6_value_4 -> BLARG_SHIP_INACTIVE: After tracking/firing, retail 0x002f4920-0x002f4930 tests visibility and branches to 0x002f49c8 when invisible. That block stores 4 to moby+0x20, clears collision and sets flag bit 1 at 0x002f49cc-0x002f49d8. The identical selector is named BLARG_SHIP_INACTIVE=4 in the authoritative local enum, with an empty update branch and later activation supported by the supplied list function. domain_7_value_4 -> BLARG_SHIP_INACTIVE: The existing BLARG_SHIP_BURST_AND_DEACTIVATE branch follows hero displacement then bursts/drops/emits an effect at retail 0x002f4934-0x002f49c0. It falls through 0x002f49c8-0x002f49d8 to store 4 into the switch's moby+0x20 field, clear collision and set flag bit 1. Reuse that exact selector's existing BLARG_SHIP_INACTIVE=4 member. --- src/overlays/l17/mobys/blarg_ship.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l17/mobys/blarg_ship.c b/src/overlays/l17/mobys/blarg_ship.c index d793956977..15089f938a 100644 --- a/src/overlays/l17/mobys/blarg_ship.c +++ b/src/overlays/l17/mobys/blarg_ship.c @@ -92,13 +92,13 @@ void blarg_ship_update(struct Moby *moby) { moby->draw_dist = 0xFF; moby->update_dist = 0xFF; if (moby_pvars->unk88 == 0) { - moby->state = 1; + moby->state = BLARG_SHIP_FOLLOW_PATH; moby_pvars->unk6C = randf_sym(0.3f, 0.5f); moby_pvars->unk70 = random_angle_radians(); moby_pvars->unk74 = randf_sym(60.0f, 120.0f) * DEG_TO_RAD * frame_time; moby_pvars->unk78 = random_float_between(8.0f, 12.0f); } else { - moby->state = 4; + moby->state = BLARG_SHIP_INACTIVE; moby->collision = 0; moby->flags |= 1; } @@ -119,7 +119,7 @@ void blarg_ship_update(struct Moby *moby) { } fast_add_rotations(moby_pvars->unk70, moby_pvars->unk74); update_moby_path_transform(moby); - if (moby->state == 2) { + if (moby->state == BLARG_SHIP_BURST_AND_HIDE) { cart_burst(moby, &moby->pos, -1, 2.0f, 13.0f); if (random_integer_below(2)) { spawn_ship_pickup((char *)&moby->pos, 0xE0); @@ -127,12 +127,12 @@ void blarg_ship_update(struct Moby *moby) { spawn_ship_pickup((char *)&moby->pos, 0xE4); } FUN_0022da68(1, 0, (int)moby); - moby->state = 3; + moby->state = BLARG_SHIP_WAIT_TO_REACTIVATE; moby->collision = 0; moby->flags |= 1; } else if (moby->visible == 0) { if (fast_vec_dist(&moby->pos, &hero.motion.pos) < 32.0f) { - moby->state = 3; + moby->state = BLARG_SHIP_WAIT_TO_REACTIVATE; moby->collision = 0; moby->flags |= 1; } @@ -145,7 +145,7 @@ void blarg_ship_update(struct Moby *moby) { if (fast_vec_dist(&moby->pos, &hero.motion.pos) > 32.0f) { moby_pvars->unk84 += 1; if (scale_game_frames(60) < moby_pvars->unk84) { - moby->state = 1; + moby->state = BLARG_SHIP_FOLLOW_PATH; if (moby->prev_seq) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } @@ -266,7 +266,7 @@ void blarg_ship_update(struct Moby *moby) { } } if (moby->visible == 0) { - moby->state = 4; + moby->state = BLARG_SHIP_INACTIVE; moby->collision = 0; moby->flags |= 1; } @@ -283,7 +283,7 @@ void blarg_ship_update(struct Moby *moby) { spawn_ship_pickup((char *)&moby->pos, 0xE4); } FUN_0022da68(1, 0, (int)moby); - moby->state = 4; + moby->state = BLARG_SHIP_INACTIVE; moby->collision = 0; moby->flags |= 1; break; From c64f73a3ebc3bfb458418807fcbca6ea38d09b16 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:06:04 +0000 Subject: [PATCH 1064/1502] decomp: clarify names in update_orbit_camera_position domain_0_value_0 -> CAMERA_ORBIT_MODE_FOLLOW: Retail 00329d3c loads the camera orbit pointer from camera+0x70; 00329d8c loads its signed mode at +0x1C and 00329d90 branches away on nonzero. The zero fallthrough constructs a focus-relative radial/height goal at 00329d98-00329e48, springs camera position at 00329e4c-00329ea8 and samples collision points. The authoritative source binds this same +0x1C field to CameraOrbit.mode and Orbit_32B1F8.mode. reset_hero_follow_camera_from_preset assigns CAMERA_ORBIT_MODE_FOLLOW=0 to it; update_hero_follow_camera_orbit switches that same field from FOLLOW=0 to ORBITING=1 on vert_ramp_launch and back to FOLLOW when launch ends. The assigned function calls that helper at 0032a474 with the same camera pointer, proving the shared camera orbit mode domain and canonical FOLLOW name. --- src/overlays/shared/camera/hoverboard_camera.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/camera/hoverboard_camera.c b/src/overlays/shared/camera/hoverboard_camera.c index 75a5501949..e30796dfc9 100644 --- a/src/overlays/shared/camera/hoverboard_camera.c +++ b/src/overlays/shared/camera/hoverboard_camera.c @@ -482,6 +482,9 @@ extern float D_L05_00174278 NOT_SDA; void update_orbit_camera_position(Camera_32B1F8 *camera) __asm__("FUN_L05_00329ce8"); void update_orbit_camera_position(Camera_32B1F8 *camera) { + enum { + CAMERA_ORBIT_MODE_FOLLOW = 0 + }; V_32B1F8 down; V_32B1F8 focus; V_32B1F8 rel; @@ -512,7 +515,7 @@ void update_orbit_camera_position(Camera_32B1F8 *camera) { spring = &orbit->spring; fast_vec_normalize(&down, up_axis, -1.0f); qcopy(&focus, &focus_state->pos); - if (orbit->mode == 0) { + if (orbit->mode == CAMERA_ORBIT_MODE_FOLLOW) { fast_vec_sub(&rel, pos = &camera->pos, &focus); probe_step = 0; along = fast_vec_dot(&rel, &focus_state->axis); From ff10c06142850b669a08ab3fd509c76419de0f75 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:07:57 +0000 Subject: [PATCH 1065/1502] decomp: clarify names in blarg_ship_update domain_0_value_1 -> BLARG_SHIP_FOLLOW_PATH: Initialization writes 1 to moby state byte +0x20 at 003198bc/003198d8. The switch reads that same byte at 0031987c; its existing BLARG_SHIP_FOLLOW_PATH case advances wrapped path progress at 00319940-003199fc and calls update_moby_path_transform at 00319a0c. domain_1_value_4 -> BLARG_SHIP_INACTIVE: The initialization branch with nonzero private +0x88 jumps at 003198b4 to 0031a170, loading 4 and storing it into the switch's moby state byte +0x20 at 0031a174, then clearing collision and setting flags bit 1. The same selector already has the empty BLARG_SHIP_INACTIVE=4 case. domain_2_value_2 -> BLARG_SHIP_BURST_AND_WAIT_TO_REACTIVATE: 00319a14 reloads moby state byte +0x20, and 00319a18-00319a1c compare it with 2. The matched branch bursts, spawns effects and writes state 3 at 00319aa0. This is exactly the existing BLARG_SHIP_BURST_AND_WAIT_TO_REACTIVATE=2 member of the same moby-state switch. domain_3_value_3 -> BLARG_SHIP_WAIT_TO_REACTIVATE: After the state-2 burst and voice call, 00319a9c loads 3 and 00319aa0 stores it into moby state +0x20, disabling collision and setting flag 1. The same selector's existing BLARG_SHIP_WAIT_TO_REACTIVATE=3 branch gates on spatial checks and a timer before restoring state 1 and class collision at 00319b7c-00319bb4. domain_4_value_3 -> BLARG_SHIP_WAIT_TO_REACTIVATE: The invisible path-following branch checks hero distance against 32 at 00319ac8-00319ae4, loads 3 at 00319ae8 and jumps to the state-byte store 0031a174. This selects the existing BLARG_SHIP_WAIT_TO_REACTIVATE=3 case, whose timed and spatial gates restore path following and collision. domain_5_value_1 -> BLARG_SHIP_FOLLOW_PATH: In existing BLARG_SHIP_WAIT_TO_REACTIVATE, the counter is compared with scale_game_frames(60) at 00319b54-00319b6c; 00319b70 loads 1 and 00319b7c stores it at moby+0x20, followed by restored collision at 00319bb4. The same byte is the switch selector, with BLARG_SHIP_FOLLOW_PATH=1 advancing path progress. domain_6_value_4 -> BLARG_SHIP_INACTIVE: At the end of the maneuver-and-fire branch, 0031a0ac-0031a0b8 test visibility and jump to 0031a170 when zero. That common tail stores 4 into moby state +0x20 and disables collision. The selector already names its empty case 4 BLARG_SHIP_INACTIVE; supplied activate_listed_blarg_ship selects state 4 before activating state 5. domain_7_value_4 -> BLARG_SHIP_INACTIVE: Existing BLARG_SHIP_BURST_AND_DEACTIVATE performs cart_burst, effect spawns and voice at 0031a104-0031a168, then 0031a170-0031a180 stores 4 into moby state +0x20, clears collision and sets flag 1. This is the same selector's existing BLARG_SHIP_INACTIVE=4 case, also selected for reactivation by activate_listed_blarg_ship. --- src/overlays/l11/mobys/blarg_ship.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l11/mobys/blarg_ship.c b/src/overlays/l11/mobys/blarg_ship.c index fcda90841e..106f72591f 100644 --- a/src/overlays/l11/mobys/blarg_ship.c +++ b/src/overlays/l11/mobys/blarg_ship.c @@ -141,13 +141,13 @@ void blarg_ship_update(struct Moby *moby) { moby->draw_dist = 0xFF; moby->update_dist = 0xFF; if (moby_vars->unk88 == 0) { - moby->state = 1; + moby->state = BLARG_SHIP_FOLLOW_PATH; moby_vars->unk6C = randf_sym(0.3f, 0.5f); moby_vars->unk70 = random_angle_radians(); moby_vars->unk74 = randf_sym(60.0f, 120.0f) * DEG_TO_RAD * frame_scale_inv_macro[1]; moby_vars->unk78 = random_float_between(8.0f, 12.0f); } else { - moby->state = 4; + moby->state = BLARG_SHIP_INACTIVE; moby->collision = 0; moby->flags |= 1; } @@ -166,7 +166,7 @@ void blarg_ship_update(struct Moby *moby) { } fast_add_rotations(moby_vars->unk70, moby_vars->unk74); update_moby_path_transform(moby); - if (moby->state == 2) { + if (moby->state == BLARG_SHIP_BURST_AND_WAIT_TO_REACTIVATE) { cart_burst(moby, &moby->pos, -1, 2.0f, 13.0f); if (random_integer_below(2)) { spawn_moby_with_random_yaw(&moby->pos, D_L11_0015F580, 0x4C4); @@ -175,12 +175,12 @@ void blarg_ship_update(struct Moby *moby) { } allocate_voice_for_target_entry(1, 0, (int)moby); *(unsigned short *)(D_00141C18) = 0xFFFF; - moby->state = 3; + moby->state = BLARG_SHIP_WAIT_TO_REACTIVATE; moby->collision = 0; moby->flags |= 1; } else if (moby->visible == 0) { if (fast_vec_dist(&moby->pos, &hero.motion.pos) < 32.0f) { - moby->state = 3; + moby->state = BLARG_SHIP_WAIT_TO_REACTIVATE; moby->collision = 0; moby->flags |= 1; } @@ -193,7 +193,7 @@ void blarg_ship_update(struct Moby *moby) { if (fast_vec_dist(&moby->pos, &hero.motion.pos) > 32.0f) { moby_vars->unk84 += 1; if (scale_game_frames(60) < moby_vars->unk84) { - moby->state = 1; + moby->state = BLARG_SHIP_FOLLOW_PATH; if (moby->prev_seq) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } @@ -314,7 +314,7 @@ void blarg_ship_update(struct Moby *moby) { } } if (moby->visible == 0) { - moby->state = 4; + moby->state = BLARG_SHIP_INACTIVE; moby->collision = 0; moby->flags |= 1; } @@ -332,7 +332,7 @@ void blarg_ship_update(struct Moby *moby) { spawn_moby_with_random_yaw(&moby->pos, D_L11_0015F580, 0x4C2); } allocate_voice_for_target_entry(1, 0, (int)moby); - moby->state = 4; + moby->state = BLARG_SHIP_INACTIVE; moby->collision = 0; moby->flags |= 1; break; From 953fdfa03db15d038d50f5a6c37c150d619b1b85 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:07:57 +0000 Subject: [PATCH 1066/1502] decomp: clarify names in pokitaru_boat_update domain_0_value_0 -> POKITARU_BOAT_INITIALIZE: Retail 00309b1c-00309b2c reads moby byte +0x20 and skips saved-height restoration only for zero; 00309b4c-00309b74 switches on that same byte. Source names its case zero POKITARU_BOAT_INITIALIZE; reuse that member for the pre-switch comparison. domain_1_value_1 -> POKITARU_BOAT_WAIT_FOR_ACTIVATION: Retail 00309c8c-00309c9c writes one to moby+0x20 after initializing path position and segment. The same byte selects case one at 00309cd8-00309d00, which waits on pvars+0xB8. Source already names this selector's case POKITARU_BOAT_WAIT_FOR_ACTIVATION. domain_2_value_5 -> POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO: Retail 00309d68-00309d74 writes five to moby+0x20 after activated path placement and yaw setup. That same switch byte selects case five at 0030a2bc-0030a384, loading the path target and adjusting boat z relative to hero z; source's existing member is POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO. domain_3_value_3 -> POKITARU_BOAT_WAIT_FOR_GROUP_CLEAR: Retail 00309fb0-00309fd0 tests final movement length; after voice cleanup 0030a088-0030a08c stores three to moby+0x20. The same selector's case three at 0030a1c8-0030a1f4 waits for is_pokitaru_boat_target_group_clear, matching existing POKITARU_BOAT_WAIT_FOR_GROUP_CLEAR. domain_4_value_4 -> POKITARU_BOAT_RISE_ABOVE_PATH: Retail 0030a1fc-0030a210 clears pvars+0xD0 and stores four to moby+0x20 when the group-clear predicate and pvars+0xB0 permit. Case four of that same byte at 0030a214-0030a2a8 advances boat z toward path target z+6, matching existing POKITARU_BOAT_RISE_ABOVE_PATH. domain_5_value_5 -> POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO: Retail 0030a200 branches to 0030a2b0 when pvars+0xB0 is zero after group clearance; 0030a2b0-0030a2b8 stores five to moby+0x20. This is the exact switch selector whose case five is already POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO, implemented at 0030a2bc-0030a384. domain_6_value_5 -> POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO: Retail 0030a288-0030a2a8 compares boat z against path target z+5.9; on reaching it 0030a2b0-0030a2b8 stores five to moby+0x20. That field directly selects the existing POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO case at 0030a2bc-0030a384, so the transition reuses its member. --- src/overlays/l11/mobys/pokitaru_boat.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l11/mobys/pokitaru_boat.c b/src/overlays/l11/mobys/pokitaru_boat.c index a41db7bcfc..004b6b4532 100644 --- a/src/overlays/l11/mobys/pokitaru_boat.c +++ b/src/overlays/l11/mobys/pokitaru_boat.c @@ -110,7 +110,7 @@ void pokitaru_boat_update(struct Moby *moby) { qcopy(start_pos, &moby->pos); qcopy(start_rot, &moby->rot); - if (moby->state != 0) { + if (moby->state != POKITARU_BOAT_INITIALIZE) { moby->pos.z = boat_vars->height_e4; } update_pokitaru_boat_joint_effects(moby); @@ -138,7 +138,7 @@ void pokitaru_boat_update(struct Moby *moby) { boat_vars->path_c4 = path; qcopy(&moby->pos, (char *)path + 0x10); boat_vars->seg_d4 = 1; - moby->state = 1; + moby->state = POKITARU_BOAT_WAIT_FOR_ACTIVATION; for (part_angle_index = 0; part_angle_index < 4; part_angle_index++) { boat_vars->wobble_f0[part_angle_index] = random_angle_radians(); } @@ -158,7 +158,7 @@ void pokitaru_boat_update(struct Moby *moby) { qcopy(&moby->pos, (char *)path + n * 16 - 16); last = (float *)((char *)path + (n - 1) * 16); moby->rot.z = fast_arc_tan(last[4] - moby->pos.x, last[5] - moby->pos.y); - moby->state = 5; + moby->state = POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO; } break; case POKITARU_BOAT_FOLLOW_PATH: { @@ -229,7 +229,7 @@ void pokitaru_boat_update(struct Moby *moby) { } boat_vars->slot_c8 = -1; } - moby->state = 3; + moby->state = POKITARU_BOAT_WAIT_FOR_GROUP_CLEAR; } approach_angle(&moby->rot.z, fast_arc_tan(target[0] - moby->pos.x, target[1] - moby->pos.y), @@ -255,9 +255,9 @@ void pokitaru_boat_update(struct Moby *moby) { if (is_pokitaru_boat_target_group_clear(moby) != 0) { if (boat_vars->flag_b0 != 0) { boat_vars->approach_d0 = 0.0f; - moby->state = 4; + moby->state = POKITARU_BOAT_RISE_ABOVE_PATH; } else { - moby->state = 5; + moby->state = POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO; } } break; @@ -270,7 +270,7 @@ void pokitaru_boat_update(struct Moby *moby) { frame_time_sq, frame_time); if (target[2] + 5.9f <= moby->pos.z) { - moby->state = 5; + moby->state = POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO; } break; case POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO: From f3e663561d7b22d7a634d2cc0b169ca0cdc8553a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:07:57 +0000 Subject: [PATCH 1067/1502] decomp: clarify names in update_drek_boss_damage_and_phase_transitions domain_0_value_1 -> HIT_PROCESSING_NO_DAMAGE: Retail 0x002f5f68-0x002f5f84 passes sp+0xB0 as resolve_moby_hit_response's status output and skips damage when it equals 1. Checked level-18 helper 0x0025c7c8 saves that output in s3; 0x0025c8c8-0x0025c900 writes 1 and zero damage when the hit record is absent. Its other write of 1 at 0x0025cc8c-0x0025cc98 clears hit damage +0x2C, subsequently copied to the damage output at 0x0025ccc0-0x0025ccc4. Thus 1 denotes no damage, not a moby or hero state. domain_1_value_12 -> DREK_BOSS_SELECT_NEXT_ACTION: Source type is assigned MOBY(moby)->state, proven by retail lbu v1,0x20(s2) at 0x002f5f8c, with s2 the boss argument. 0x002f5f90-0x002f5f98 tests states 12 through 19. Supplied boss dispatcher uses this same boss +0x20 selector and DREK_BOSS_SELECT_NEXT_ACTION for the action selection branch; it assigns 0xC to return to that branch. Reuse established Drek member value 12, not equal-valued HeroStateId. domain_2_value_19 -> DREK_BOSS_FOLLOW_HERO: Retail 0x002f5f8c-0x002f5f98 loads the boss state byte at argument +0x20 and tests the inclusive 12..19 range. Source type is directly MOBY(moby)->state. Supplied drek_final_boss_robot_update dispatches this same field under DREK_BOSS_FOLLOW_HERO, performs hero-follow movement and ring refresh, and its action-selection branch assigns 0x13 for follow-hero. This proves established Drek member 19 as the upper bound. domain_3_value_2 -> DREK_BOSS_CIRCLE_AND_FIRE_AT_HERO: Retail 0x002f5fa0-0x002f5fa4 compares the same boss state byte loaded at 0x002f5f8c to 2 after the 12..19 range fails. The authoritative C directly repeats MOBY(moby)->state == DREK_BOSS_CIRCLE_AND_FIRE_AT_HERO inside this damage path; retail 0x002f604c-0x002f6054 repeats that comparison before hit animation. Supplied dispatcher implements circling movement and hero-directed rockets under that canonical Drek state member. domain_4_value_12 -> DREK_BOSS_SELECT_NEXT_ACTION: The second source type binding also reads MOBY(moby)->state. Retail 0x002f6350-0x002f635c loads boss +0x20 and tests unsigned (state-12)<8 before polling the linked moby. Supplied dispatcher uses the same boss state selector with DREK_BOSS_SELECT_NEXT_ACTION and assigns 0xC when attacks end. The lower bound therefore reuses canonical Drek state 12; it is unrelated to hero state or linked-moby status codes. domain_5_value_19 -> DREK_BOSS_FOLLOW_HERO: Retail 0x002f6350-0x002f635c tests the boss +0x20 byte in range 12..19, corresponding to source type <= 0x13. This branch itself writes 0x13 back to the same boss state field at 0x002f6384-0x002f6390, starts animation 1 and creates a ring effect. Supplied dispatcher names that same state DREK_BOSS_FOLLOW_HERO and refreshes the ring during hero-follow movement, proving canonical member 19. domain_6_value_1 -> LINKED_MOBY_REARMED: Retail 0x002f6364-0x002f637c calls poll_moby_state_and_rearm on the linked moby indexed by boss pvars +0x21C and compares its return to 1. Checked level-18 helper 0x002d8050-0x002d806c reads linked moby state +0x20, accepts state 3, returns 1 and stores state 1 in the return delay slot. Other branches return 0 or -1. This is a rearmed transition status, not Drek state 1 or a hero domain. --- src/overlays/l18/mobys/drek_final_boss_robot.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/overlays/l18/mobys/drek_final_boss_robot.c b/src/overlays/l18/mobys/drek_final_boss_robot.c index 273e7fadbd..b28c58b1a3 100644 --- a/src/overlays/l18/mobys/drek_final_boss_robot.c +++ b/src/overlays/l18/mobys/drek_final_boss_robot.c @@ -1813,6 +1813,10 @@ extern short l18_drek_boss_class_scale_multiplier_gp __asm__("D_L18_00162330") _ /* Ported from rac1-decomp src/overlays/l18_veldin2/vendor_002F2AE0.c (func_L18_002F72E0) */ void update_drek_boss_damage_and_phase_transitions(char *moby) { + enum { + HIT_PROCESSING_NO_DAMAGE = 1, + LINKED_MOBY_REARMED = 1 + }; char *boss_data = ((char *)MOBY(moby)->pvars); int hit_processing_status; float step; @@ -1846,9 +1850,9 @@ void update_drek_boss_damage_and_phase_transitions(char *moby) { } resolve_moby_hit_response( moby, hit_record, boss_data + 0x20, 0, &hit_processing_status, &step, 0, 4); - if (hit_processing_status != 1) { + if (hit_processing_status != HIT_PROCESSING_NO_DAMAGE) { int type = MOBY(moby)->state; - if ((type >= 0xC && type <= 0x13) || type == 2) { + if ((type >= DREK_BOSS_SELECT_NEXT_ACTION && type <= DREK_BOSS_FOLLOW_HERO) || type == DREK_BOSS_CIRCLE_AND_FIRE_AT_HERO) { char *o = *(char **)(hit_record + 0x20); if (o != 0) { short h = *(short *)(o + 0xA6); @@ -1947,10 +1951,10 @@ void update_drek_boss_damage_and_phase_transitions(char *moby) { } { int type = MOBY(moby)->state; - if (type >= 0xC && type <= 0x13) { + if (type >= DREK_BOSS_SELECT_NEXT_ACTION && type <= DREK_BOSS_FOLLOW_HERO) { int linked_moby_state_transition_status = poll_moby_state_and_rearm( (char *)*(int *)&D_L18_0015FFD8_5e80 + (*(int *)(boss_data + 0x21C) << 8)); - if (linked_moby_state_transition_status == 1) { + if (linked_moby_state_transition_status == LINKED_MOBY_REARMED) { moby[0x20] = 0x13; if (MOBY(moby)->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(0x14)); From caa47df60e486b18a3358ff9697f8bf18f0d9b52 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:09:48 +0000 Subject: [PATCH 1068/1502] decomp: clarify names in update_debug_camera domain_0_value_2 -> DEBUG_CONTROL_MODE_CAPTURE_HERO_CAMERA_OFFSET: Retail 0x001f43d4-0x001f43dc compares 2 against the word at debug menu base 0x0016c058 + 0x14 (DAT_0016c06c in original Ghidra), matching g_debug_menu.control_mode in the bound source. On equality, 0x001f43ec-0x001f445c copies debug camera position and basis to its target and resets follow-camera state. The supplied update_debug_menu switches on that exact same field and already names value 2 DEBUG_CONTROL_MODE_CAPTURE_HERO_CAMERA_OFFSET, capturing hero-to-camera distance, angle, height and yaw; handle_pause_input also gates update_hero_from_debug_camera on this same field equaling 2. Thus reuse is supported by selector identity and data flow, not numeric coincidence. --- src/overlays/shared/rendering/debug/update_debug_menu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/rendering/debug/update_debug_menu.c b/src/overlays/shared/rendering/debug/update_debug_menu.c index c2f32fe0fc..7ab450ce45 100644 --- a/src/overlays/shared/rendering/debug/update_debug_menu.c +++ b/src/overlays/shared/rendering/debug/update_debug_menu.c @@ -187,6 +187,9 @@ static inline void copy_vector3(f32 *dst, f32 *src) { void update_debug_camera(void) __asm__("FUN_L00_001f3aa0"); void update_debug_camera(void) { + enum { + DEBUG_CONTROL_MODE_CAPTURE_HERO_CAMERA_OFFSET = 2 + }; struct PadStateWords *pad; DebugMenuState *menu; int moved; @@ -382,7 +385,7 @@ void update_debug_camera(void) { copy_matrix3x4(l00_camera.unk350, r); } } - if (g_debug_menu.control_mode == 2 && l00_camera.unk180 != 0) { + if (g_debug_menu.control_mode == DEBUG_CONTROL_MODE_CAPTURE_HERO_CAMERA_OFFSET && l00_camera.unk180 != 0) { target = (DebugCameraTarget *)l00_camera.unk180; qcopy(target->position, l00_camera.pos.f); qcopy(target->basis, l00_camera.unk350); From 9857ee82a5901df898433d42838c84397547e82f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:09:49 +0000 Subject: [PATCH 1069/1502] decomp: clarify names in update_help_state domain_10_value_5 -> HELP_STATE_WAIT_FOR_DISMISSAL: At 0x001fe5d4-0x001fe628 the elapsed start-delay checks matching message audio and optionally calls 0x00215b10, then loads 5. Shared 0x001fe7c8-0x001fe7d4 stores the same state selector and resets timer; its existing case 5 is HELP_STATE_WAIT_FOR_DISMISSAL. domain_11_value_6 -> HELP_STATE_DISMISS_DELAY: The dismissal-wait completion records help statistics then loads 6 at 0x001fe778 and writes D_001996D0.state at 0x001fe77c, clearing timer at 0x001fe784. Existing case 6 on that selector is HELP_STATE_DISMISS_DELAY. domain_12_value_7 -> HELP_STATE_DISMISSING: At 0x001fe794-0x001fe7c0 case 6 waits for its bounded delay or Triangle; 0x001fe7c4-0x001fe7d4 loads 7, stores D_001996D0.state and clears timer. Existing case 7 of the identical selector is HELP_STATE_DISMISSING. domain_13_value_8 -> HELP_STATE_QUEUED_MESSAGE_WAIT: At 0x001fe840-0x001fe860 dismissal waits until timer>=8, tests queued at +0x38, and writes 8 to D_001996D0.state when queued is nonzero. Existing case 8 for this field is HELP_STATE_QUEUED_MESSAGE_WAIT, waiting for queued to clear. domain_14_value_0 -> HELP_STATE_IDLE: At 0x001fe850-0x001fe86c dismissal with no queued message stores zero to D_001996D0.state and clears msg to -1. This same switch selector's established case 0 is HELP_STATE_IDLE, which waits for pending messages. domain_1_value_0 -> HELP_STATE_IDLE: At 0x001fdf34-0x001fdf44 the disabled/startup reset clears pending and timer and stores zero at D_001996D0+0. The same address is loaded as the switch selector at 0x001fdf48; its established case 0 waits for pending messages. domain_2_value_0 -> HELP_STATE_IDLE: At 0x001fe090-0x001fe0a4 the queued-message completion clears msg and shown and stores zero to D_001996D0.state. This is the identical field selected at 0x001fdf48, whose existing HELP_STATE_IDLE case resolves pending messages. domain_3_value_7 -> HELP_STATE_DISMISSING: The display-start Triangle path computes timer=8-timer at 0x001fe214-0x001fe224, then writes 7 to the switch selector D_001996D0.state at 0x001fe22c-0x001fe238. Existing case HELP_STATE_DISMISSING handles that field's value 7. domain_4_value_2 -> HELP_STATE_DISMISSAL_WAIT_AUDIO_GATE: At 0x001fe23c-0x001fe254 display-start waits for timer>=6 and loads 2; shared 0x001fe4ac-0x001fe4b4 resets timer and stores it to D_001996D0.state. Its existing case 2 is HELP_STATE_DISMISSAL_WAIT_AUDIO_GATE, testing message audio and the scaled delay. domain_5_value_7 -> HELP_STATE_DISMISSING: The audio-gate Triangle path loads 7 at 0x001fe33c and branches to 0x001fe77c, storing it to the same D_001996D0.state selector and resetting timer at 0x001fe784. Existing case 7 is HELP_STATE_DISMISSING. domain_6_value_3 -> HELP_STATE_DISMISSAL_WAIT_TRANSITION_DELAY: The audio-gate completion loads 3 at 0x001fe390 or 0x001fe3a8 and reaches 0x001fe7c8-0x001fe7d4 to store D_001996D0.state and clear timer. Existing case 3 for this same selector is HELP_STATE_DISMISSAL_WAIT_TRANSITION_DELAY. domain_7_value_7 -> HELP_STATE_DISMISSING: At 0x001fe48c-0x001fe490 the transition-delay Triangle path loads 7 and jumps to 0x001fe77c, writing D_001996D0.state and resetting timer. The same field's established case 7 is HELP_STATE_DISMISSING. domain_8_value_4 -> HELP_STATE_DISMISSAL_WAIT_START_DELAY: At 0x001fe494-0x001fe4a8 transition-delay waits until timer>=8 and loads 4. Shared 0x001fe4ac-0x001fe4b4 clears timer and writes the switch selector. Existing case 4 is HELP_STATE_DISMISSAL_WAIT_START_DELAY. domain_9_value_6 -> HELP_STATE_DISMISS_DELAY: At 0x001fe59c-0x001fe5bc the start-delay Triangle path writes 6 to D_001996D0.state and sets timer=4-timer. That identical switch selector's existing case 6 is HELP_STATE_DISMISS_DELAY, preceding dismissal. --- src/ui/help/update_help_state.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/ui/help/update_help_state.c b/src/ui/help/update_help_state.c index 306395bb7c..efc8e7f2dc 100644 --- a/src/ui/help/update_help_state.c +++ b/src/ui/help/update_help_state.c @@ -65,7 +65,7 @@ void update_help_state(void) { if (game_mode != 0 || help_state.started == 0) { help_state.pending = -1; - help_state.state = 0; + help_state.state = HELP_STATE_IDLE; help_state.timer = 0; return; } @@ -89,7 +89,7 @@ void update_help_state(void) { RECORD_LATEST_TIME(); RECORD_FLAGS(); help_state.msg = -1; - help_state.state = 0; + help_state.state = HELP_STATE_IDLE; help_state.shown = 0; break; @@ -117,10 +117,10 @@ void update_help_state(void) { RECORD_LATEST_TIME(); RECORD_FLAGS(); help_state.timer = 8 - help_state.timer; - help_state.state = 7; + help_state.state = HELP_STATE_DISMISSING; } else if (help_state.timer >= 6) { help_state.timer = 0; - help_state.state = 2; + help_state.state = HELP_STATE_DISMISSAL_WAIT_AUDIO_GATE; } break; } @@ -132,14 +132,14 @@ void update_help_state(void) { if (controller_state.pressed & PAD_TRIANGLE) { RECORD_COUNT(); RECORD_LATEST_TIME(); - help_state.state = 7; + help_state.state = HELP_STATE_DISMISSING; help_state.timer = 0; RECORD_FLAGS(); } else if (help_state.timer >= scale_game_frames(0x18)) { if (music_stream_state.secondary.state == 3 || (id = help_msgs[help_state.msg].audio_track_offset) == -1 || id != music_stream_state.secondary.track - 0x7530) { - help_state.state = 3; + help_state.state = HELP_STATE_DISMISSAL_WAIT_TRANSITION_DELAY; help_state.timer = 0; } } @@ -151,12 +151,12 @@ void update_help_state(void) { if (controller_state.pressed & PAD_TRIANGLE) { RECORD_COUNT(); RECORD_LATEST_TIME(); - help_state.state = 7; + help_state.state = HELP_STATE_DISMISSING; help_state.timer = 0; RECORD_FLAGS(); } else if (help_state.timer >= 8) { help_state.timer = 0; - help_state.state = 4; + help_state.state = HELP_STATE_DISMISSAL_WAIT_START_DELAY; } break; @@ -167,7 +167,7 @@ void update_help_state(void) { if (controller_state.pressed & PAD_TRIANGLE) { RECORD_COUNT(); RECORD_LATEST_TIME(); - help_state.state = 6; + help_state.state = HELP_STATE_DISMISS_DELAY; RECORD_FLAGS(); help_state.timer = 4 - help_state.timer; } else if (help_state.timer >= 4) { @@ -176,7 +176,7 @@ void update_help_state(void) { music_stream_state.secondary.state == 3) { continue_audio_stream_if_ready(); } - help_state.state = 5; + help_state.state = HELP_STATE_WAIT_FOR_DISMISSAL; help_state.timer = 0; } break; @@ -194,7 +194,7 @@ void update_help_state(void) { (controller_state.pressed & PAD_TRIANGLE)) { RECORD_COUNT(); RECORD_LATEST_TIME(); - help_state.state = 6; + help_state.state = HELP_STATE_DISMISS_DELAY; help_state.timer = 0; RECORD_FLAGS(); } @@ -203,7 +203,7 @@ void update_help_state(void) { case HELP_STATE_DISMISS_DELAY: if (D_0015EE1D == 0 || help_state.timer >= 4 || (controller_state.pressed & PAD_TRIANGLE)) { - help_state.state = 7; + help_state.state = HELP_STATE_DISMISSING; help_state.timer = 0; } break; @@ -219,9 +219,9 @@ void update_help_state(void) { } if (help_state.timer >= 8) { if (help_state.queued != 0) { - help_state.state = 8; + help_state.state = HELP_STATE_QUEUED_MESSAGE_WAIT; } else { - help_state.state = 0; + help_state.state = HELP_STATE_IDLE; help_state.msg = -1; } help_state.timer = 0; From 9c6773923a143aefafebab5d4503a52b1841b5ae Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:09:49 +0000 Subject: [PATCH 1070/1502] decomp: clarify names in update_camera_position_and_orientation_from_paths domain_0_value_0 -> CAMERA_PRESET_KIND_RAIL_SEGMENT_SYNC: Retail 003153dc-003153e8 loads the selected CameraPreset +0x30 kind and tests zero. Its branch copies hero rail_segment and rail_seg_frac into camera progress at 00315400-00315430, then uses that same segment and the ratio of hero offset to hero segment length to locate the camera on the corresponding preset track segment at 00315450-00315504. This proves rail-segment synchronization rather than any hero enum domain. domain_1_value_2 -> CAMERA_PRESET_KIND_MAPPED_PATHS: Retail 00315580-003155e4 compares the same CameraPreset +0x30 selector with 2 and loads track_path, target spline, path and look_path. 00315690-003157ec finds the hero segment in stored mapped ranges, sums target-path lengths and proportionally samples the camera track. The supplied source's reset_camera_state_and_prepare_preset_paths already names this exact CameraPreset.kind value CAMERA_PRESET_KIND_MAPPED_PATHS = 2 and prepares those same path mappings. domain_2_value_0 -> CAMERA_PRESET_KIND_RAIL_SEGMENT_SYNC: Retail 00315b58-00315b70 reloads the identical selected CameraPreset +0x30 kind and tests zero, after the level-14 check; this chooses nonlooping look-ahead sampling. Its selector is the same preset field tested at 003153e0-003153e8, whose zero branch synchronizes camera track position to hero rail_segment and rail_seg_frac at 00315400-00315504. Reuse the same rail-segment-sync kind member for this second comparison. --- src/overlays/shared/camera/grindrail_camera.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/camera/grindrail_camera.c b/src/overlays/shared/camera/grindrail_camera.c index ec082b8122..f670014968 100644 --- a/src/overlays/shared/camera/grindrail_camera.c +++ b/src/overlays/shared/camera/grindrail_camera.c @@ -311,6 +311,10 @@ extern int current_level_index_macro __asm__("D_0015ED84") MACRO_ADDR; void update_camera_position_and_orientation_from_paths(Cam *cam) __asm__("FUN_L01_00315358"); void update_camera_position_and_orientation_from_paths(Cam *camera_to_update) { + enum { + CAMERA_PRESET_KIND_RAIL_SEGMENT_SYNC = 0, + CAMERA_PRESET_KIND_MAPPED_PATHS = 2 + }; float camera_goal[4]; float look_offset[4]; float look_dir[4]; @@ -333,7 +337,7 @@ void update_camera_position_and_orientation_from_paths(Cam *camera_to_update) { float look_length; float pitch_step; - if (mode == 0) { + if (mode == CAMERA_PRESET_KIND_RAIL_SEGMENT_SYNC) { Path *path; float dist; @@ -357,7 +361,7 @@ void update_camera_position_and_orientation_from_paths(Cam *camera_to_update) { camera_to_update->pos[1], rail_point[1], &data->vel[1], rate, 0.175f, 0.0f); camera_to_update->pos[2] = cam_interp_values( camera_to_update->pos[2], rail_point[2], &data->vel[2], rate, 0.175f, 0.0f); - } else if (mode == 2) { + } else if (mode == CAMERA_PRESET_KIND_MAPPED_PATHS) { Path *pathA = ((Path *)l01_paths[path_index]); Path *pathD = (Path *)l01_splines_macro[camera_path_preset->target].path; Path *pathC = ((Path *)l01_paths[camera_path_preset->path]); @@ -491,7 +495,7 @@ void update_camera_position_and_orientation_from_paths(Cam *camera_to_update) { 20.0f, 1.0f, 0.0f); - if (current_level_index_macro == 0xE && camera_path_preset->kind == 0) { + if (current_level_index_macro == 0xE && camera_path_preset->kind == CAMERA_PRESET_KIND_RAIL_SEGMENT_SYNC) { sample_path(path, delta, &segment, &fraction, lead, 0); } else { sample_path(path, delta, &segment, &fraction, lead, 1); From 2366c1357b1c1fa12746f08eaa706079540f0a65 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:09:49 +0000 Subject: [PATCH 1071/1502] decomp: clarify names in update_homing_spark_projectile domain_0_value_2 -> SPARK_CLEANUP_AND_REMOVE: Retail 0x002d47e0 preserves the projectile argument in s4. After checking the distinct target at pvars+0x10 for class 0xE9 and target states 0x40/1, 0x002d4860-0x002d4864 stores 2 to projectile s4+0x20. 0x002d4868-0x002d4878 reads that same field into s2 and dispatches 2 to 0x002d516c, which releases the verified voice, clears its slot and removes the projectile. This is the existing local SPARK_CLEANUP_AND_REMOVE domain, not a target or Hero state. domain_1_value_2 -> SPARK_CLEANUP_AND_REMOVE: The first collision_line with mask 0x10 at 0x002d5038 is followed by nonnull collision-moby and hero-moby/class-0x1DF checks. 0x002d506c-0x002d5070 writes 2 to s4+0x20, the same projectile field read at 0x002d4868 and dispatched to the existing SPARK_CLEANUP_AND_REMOVE branch at 0x002d516c. That branch releases the voice and removes this projectile. domain_2_value_2 -> SPARK_CLEANUP_AND_REMOVE: After copying the collision position and adding 2.0 to the ray endpoint Z, retail 0x002d50a4 repeats collision_line with mask 0x10 and checks the returned moby against hero/class 0x1DF. 0x002d50d8-0x002d50dc assigns 2 to projectile s4+0x20. The same field selects the existing local SPARK_CLEANUP_AND_REMOVE case via 0x002d4868-0x002d4878, whose body releases audio and removes the projectile. domain_3_value_2 -> SPARK_CLEANUP_AND_REMOVE: Retail 0x002d50e0-0x002d50f8 performs the 0.5-radius collection at the projectile position, passing s4 as the projectile. The nonzero result and hero-moby/class-0x1DF checks lead to 0x002d5128-0x002d512c storing 2 to s4+0x20. This is the exact field dispatched at 0x002d4868-0x002d4878 to SPARK_CLEANUP_AND_REMOVE, which clears the verified voice slot and removes the projectile. domain_4_value_2 -> SPARK_CLEANUP_AND_REMOVE: Retail 0x002d5130 decrements the projectile pvars timer at +0x14. Timer completion, a null target at pvars+0x10, or target removal states 0xFE/0xFD lead through 0x002d5138-0x002d5168 to a store of 2 at projectile s4+0x20. Reading the same field at 0x002d4868 dispatches 2 to 0x002d516c, the existing SPARK_CLEANUP_AND_REMOVE branch that releases the verified voice and removes this moby. --- src/overlays/shared/enemies/blarg_helicopter_spark.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/enemies/blarg_helicopter_spark.c b/src/overlays/shared/enemies/blarg_helicopter_spark.c index 98e5b1c748..16995b994d 100644 --- a/src/overlays/shared/enemies/blarg_helicopter_spark.c +++ b/src/overlays/shared/enemies/blarg_helicopter_spark.c @@ -125,7 +125,7 @@ void helicopter_spark_update(Moby *moby) { } else if (homing_spark_pvars->target->oclass == 0xE9) { voice_slot = (int *)(((char *)homing_spark_pvars->target->pvars) + 0x1B8); if (homing_spark_pvars->target->state == 0x40 || homing_spark_pvars->target->state == 1) { - moby->state = 2; + moby->state = SPARK_CLEANUP_AND_REMOVE; } } state = moby->state; @@ -266,7 +266,7 @@ void helicopter_spark_update(Moby *moby) { D_L03_00173F58 != 0 && (D_L03_00173F58 == ((Hero *)(D_0013E533 + 0xE1D))->moby || D_L03_00173F58->oclass == 0x1DF)) { - moby->state = 2; + moby->state = SPARK_CLEANUP_AND_REMOVE; } qcopy(&ray_end, &muzzle); ray_end.z += 2.0f; @@ -275,13 +275,13 @@ void helicopter_spark_update(Moby *moby) { D_L03_00173F58 != 0 && (D_L03_00173F58 == ((Hero *)(D_0013E533 + 0xE1D))->moby || D_L03_00173F58->oclass == 0x1DF)) { - moby->state = 2; + moby->state = SPARK_CLEANUP_AND_REMOVE; } if (collect_mobies_in_sphere(0.5f, &moby->pos, 0x10, moby, &hit) != 0 && D_L03_00173F58 != 0 && (D_L03_00173F58 == ((Hero *)(D_0013E533 + 0xE1D))->moby || D_L03_00173F58->oclass == 0x1DF)) { - moby->state = 2; + moby->state = SPARK_CLEANUP_AND_REMOVE; } } } @@ -289,7 +289,7 @@ void helicopter_spark_update(Moby *moby) { if (fast_dec_timer(&homing_spark_pvars->timer) != 0 || homing_spark_pvars->target == 0 || homing_spark_pvars->target->state == 0xFE || homing_spark_pvars->target->state == 0xFD) { - moby->state = 2; + moby->state = SPARK_CLEANUP_AND_REMOVE; } break; case SPARK_CLEANUP_AND_REMOVE: From da91a703dcfb5881213130bf28b9f0e4c83c6aa5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:09:49 +0000 Subject: [PATCH 1072/1502] decomp: clarify names in skid_mcmarx_update domain_0_value_1 -> SKID_MCMARX_WAIT_FOR_RACE_MODE: Retail 00307998 loads the selector from moby+0x20; 0030799c-003079a0 dispatch value 1 to 00307b30, which waits for control mode 0x16. After initializing path, position, yaw, speed settings and bob phase, 00307b24-00307b2c stores 1 to that identical moby+0x20 byte. Source switch(moby->state) already names this destination SKID_MCMARX_WAIT_FOR_RACE_MODE, proving canonical local-domain reuse. domain_1_value_2 -> SKID_MCMARX_FOLLOW_PATH: Retail 00307998 loads moby+0x20 and 003079c0 dispatches value 2 to 00307bec. After control-mode gating, motion reset, launch-timer setup and child creation, 00307be0-00307be8 stores 2 to the same moby+0x20 state byte. Its destination runs advance_racer_path_node at 00307c14, steering, jumping and movement updates. The source already names that exact switch domain member SKID_MCMARX_FOLLOW_PATH. domain_2_value_0 -> SKID_MCMARX_INITIALIZE: Retail 00307bf8-00307c08 checks control mode against 0x16 and stores zero to moby+0x20 when it differs. This is the same state byte loaded at 00307998; 003079b0 dispatches zero to 003079d0, initializing flags, path, position, yaw, speeds and bob phase through 00307b20. Source switch(moby->state) already calls this exact destination SKID_MCMARX_INITIALIZE, establishing local-domain reuse rather than equal-valued hero constants. --- src/overlays/l05/mobys/skid_mcmarx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l05/mobys/skid_mcmarx.c b/src/overlays/l05/mobys/skid_mcmarx.c index 7db8a93e2c..61287c3b4d 100644 --- a/src/overlays/l05/mobys/skid_mcmarx.c +++ b/src/overlays/l05/mobys/skid_mcmarx.c @@ -464,7 +464,7 @@ void skid_mcmarx_update(Moby *moby) { racer_instance_vars->launch_speed *= handicap; } racer_instance_vars->bob_phase = random_angle_radians(); - moby->state = 1; + moby->state = SKID_MCMARX_WAIT_FOR_RACE_MODE; break; } case SKID_MCMARX_WAIT_FOR_RACE_MODE: @@ -492,14 +492,14 @@ void skid_mcmarx_update(Moby *moby) { racer_instance_vars->child->flags |= 0x8000; } } - moby->state = 2; + moby->state = SKID_MCMARX_FOLLOW_PATH; } break; case SKID_MCMARX_FOLLOW_PATH: { Hero *hero = (Hero *)(((char *)&D_0013F350)); if (hero->state.control_mode != 0x16) { - moby->state = 0; + moby->state = SKID_MCMARX_INITIALIZE; } else { float ground; float height_above_ground; From 63fbfbbbcaf143334e11319d97f4e76ba8a427c1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:09:50 +0000 Subject: [PATCH 1073/1502] decomp: clarify names in update_elevator domain_0_value_1 -> WAIT_FOR_INITIAL_HERO_ACTIVATION: Initialization selects state 1 at 0x002fc710-0x002fc724; its case at 0x002fc808-0x002fc874 waits for hero clip-volume inclusion or hero moby class 0x57 before advancing. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_10_value_5 -> MOVE_TO_NODE_BASE_HEIGHT: The hero-below proximity branch writes 5 at 0x002fcd94-0x002fcda0; the existing movement case uses node base z as target for state 5. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_11_value_4 -> WAIT_FOR_HERO_TRIGGER_AT_NODE_BASE_HEIGHT: The proximity branch compares moby+0x20 with 4 at 0x002fcdec-0x002fcdf4 and tests hero z above elevator z, matching the existing base-height trigger case. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_12_value_6 -> MOVE_TO_NODE_OFFSET_HEIGHT: The hero-above branch loads 6 at 0x002fce1c and stores it at 0x002fce20, selecting movement whose target is node base plus offset. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_13_value_6 -> MOVE_TO_NODE_OFFSET_HEIGHT: Within movement cases, moby+0x20 is compared with 6 at 0x002fce50-0x002fce68; only that state adds node+0x28 to the node+0x38 height target. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_14_value_6 -> MOVE_TO_NODE_OFFSET_HEIGHT: At target-error completion, 0x002fcedc-0x002fcee0 compares the same moby+0x20 with movement state 6, whose target included the node offset. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_15_value_7 -> WAIT_FOR_HERO_CLEARANCE_AT_NODE_OFFSET_HEIGHT: Completion of movement state 6 stores 7 at 0x002fcee8-0x002fceec. Cases 7/8 wait for hero XY distance >=1, establishing offset-height clearance state 7. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_16_value_8 -> WAIT_FOR_HERO_CLEARANCE_AT_NODE_BASE_HEIGHT: Completion of base-height movement state 5 selects 8 at 0x002fcf24-0x002fcf28 and stores via 0x002fcf6c; cases 7/8 wait for hero clearance. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_17_value_7 -> WAIT_FOR_HERO_CLEARANCE_AT_NODE_OFFSET_HEIGHT: Clearance cases compare moby+0x20 with 7 at 0x002fcf58-0x002fcf60 after hero XY distance >=1, distinguishing the offset-height clearance branch. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_18_value_3 -> WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT: Offset-height clearance state 7 selects 3 at 0x002fcf68 and stores at 0x002fcf6c, rearming the existing offset-height trigger case without moving z. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_19_value_4 -> WAIT_FOR_HERO_TRIGGER_AT_NODE_BASE_HEIGHT: Base-height clearance state 8 selects 4 at 0x002fcf64 and stores at 0x002fcf6c, rearming the existing base-height trigger case without moving z. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_1_value_3 -> WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT: Initialization stores state 3 at moby+0x20 (0x002fc71c-0x002fc724) and initializes z to node base plus offset at 0x002fc728-0x002fc754, matching the existing offset-height trigger case. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_20_value_5 -> MOVE_TO_NODE_BASE_HEIGHT: The source lower bound moby->state >=5 corresponds to retail 0x002fcf90-0x002fcf98 subtracting 5 and testing unsigned range <4, covering movement and clearance states 5 through 8. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_21_value_8 -> WAIT_FOR_HERO_CLEARANCE_AT_NODE_BASE_HEIGHT: The source upper bound moby->state <=8 corresponds to retail 0x002fcf90-0x002fcf98 testing unsigned state-minus-5 <4; 8 is the existing base-height clearance endpoint. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_2_value_3 -> WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT: Hero-volume activation sets state 3 via 0x002fc83c-0x002fc844 and clears the timer; this is the same moby+0x20 selector dispatched to the existing offset-height trigger case. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_3_value_3 -> WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT: Hero class 0x57 activation writes 3 to moby+0x20 at 0x002fc864-0x002fc86c, entering the existing offset-height trigger case after initial positioning. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_4_value_3 -> WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT: The scene wait branch tests D_L06_0015F5C4 at 0x002fc878-0x002fc88c and stores state 3 via 0x002fcf6c when clear, resuming the existing offset-height trigger case. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_5_value_2 -> WAIT_FOR_SCENE_GAME_MODE_CLEAR: start_scene(3) at 0x002fca64-0x002fca68 is followed by state 2 via 0x002fca70 and 0x002fcf6c; case 2 waits for the scene game-mode global to clear. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_6_value_3 -> WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT: The contact-trigger path reads moby+0x20 and compares with 3 at 0x002fcd14-0x002fcd1c before selecting movement to base height, matching the existing offset-height trigger case. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_7_value_5 -> MOVE_TO_NODE_BASE_HEIGHT: After the state-3 contact comparison, 0x002fcd24-0x002fcd28 stores state 5. Its movement case targets node+0x38 without the state-6-only offset addition. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_8_value_6 -> MOVE_TO_NODE_OFFSET_HEIGHT: The alternate contact path stores state 6 at 0x002fce20; the movement case at 0x002fce60-0x002fce74 adds node+0x28 to base z only for this state. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. domain_9_value_3 -> WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT: The proximity branch compares moby+0x20 with 3 at 0x002fcd60-0x002fcd68 and requires the hero below the elevator before selecting base-height movement. All accesses use this elevator's moby+0x20 state selector, the exact domain of the existing function-local enum. --- src/overlays/l06/mobys/elevator.c | 42 +++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/overlays/l06/mobys/elevator.c b/src/overlays/l06/mobys/elevator.c index 013326ff29..e3ef1cfd97 100644 --- a/src/overlays/l06/mobys/elevator.c +++ b/src/overlays/l06/mobys/elevator.c @@ -206,9 +206,9 @@ void elevator_update(Moby_2FDA70 *moby) { moby_data->f94 = 0; moby_data->f88 = -1; if (D_0013D4AF_2FDA70[0] == 0) { - moby->state = 1; + moby->state = WAIT_FOR_INITIAL_HERO_ACTIVATION; } else { - moby->state = 3; + moby->state = WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT; } moby->pos.z = l06_cuboids_macro[moby_data->f78].pos.z + l06_cuboids_macro[moby_data->f78].axes[2].z; @@ -227,16 +227,16 @@ void elevator_update(Moby_2FDA70 *moby) { if (((Flags *)(alternate_item_available))->f20 == 0) { ((Flags *)(alternate_item_available))->f20 = 1; } - moby->state = 3; + moby->state = WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT; moby_data->f90 = 0; } else if (((Hero_2FDA70 *)(D_0013F350))->moby->fA6 == 0x57) { - moby->state = 3; + moby->state = WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT; moby_data->f84 = 1; } break; case WAIT_FOR_SCENE_GAME_MODE_CLEAR: if (D_L06_0015F5C4_macro == 0) { - moby->state = 3; + moby->state = WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT; } break; case WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT: @@ -278,7 +278,7 @@ void elevator_update(Moby_2FDA70 *moby) { if (D_0013D5DD_2FDA70[0x10] != 0 && D_L06_00161F78 == 0) { D_L06_00161F78 = 1; start_scene(3); - moby->state = 2; + moby->state = WAIT_FOR_SCENE_GAME_MODE_CLEAR; break; } } else if (D_0013D5CA_2FDA70[0] == 0) { @@ -336,26 +336,26 @@ void elevator_update(Moby_2FDA70 *moby) { moby->pos.z + 0.29f < ((Hero_2FDA70 *)(D_0013F350))->pos.z && vector_distance_xy(&((Hero_2FDA70 *)(D_0013F350))->pos, &moby->pos) < 1.0f) { allocate_voice_for_target_entry(0, 0, (int)moby); - if (moby->state == 3) { - moby->state = 5; + if (moby->state == WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT) { + moby->state = MOVE_TO_NODE_BASE_HEIGHT; set_moby_and_links_to_states_8_and_9(D_L06_0015FFD8_macro + (moby_data->f64 << 8)); moby_data->f90 = scale_game_frames(0x78); } else { - moby->state = 6; + moby->state = MOVE_TO_NODE_OFFSET_HEIGHT; set_moby_and_links_to_states_8_and_9(D_L06_0015FFD8_macro + (moby_data->f68 << 8)); moby_data->f90 = scale_game_frames(0x78); } } else if (vector_distance_xy(&moby->pos, &((Hero_2FDA70 *)(D_0013F350))->pos) < 24.0f && - moby->state == 3 && ((Hero_2FDA70 *)(D_0013F350))->pos.z + 5.0f < moby->pos.z) { + moby->state == WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT && ((Hero_2FDA70 *)(D_0013F350))->pos.z + 5.0f < moby->pos.z) { moby_data->f84 = 1; moby_data->f94 = 1; - moby->state = 5; + moby->state = MOVE_TO_NODE_BASE_HEIGHT; set_moby_and_links_to_states_8_and_9(D_L06_0015FFD8_macro + (moby_data->f64 << 8)); set_moby_and_links_to_states_8_and_9(D_L06_0015FFD8_macro + (moby_data->f60 << 8)); moby_data->f90 = scale_game_frames(0x78); } else if (vector_distance_xy(&moby->pos, &((Hero_2FDA70 *)(D_0013F350))->pos) < 24.0f && - moby->state == 4 && moby->pos.z < ((Hero_2FDA70 *)(D_0013F350))->pos.z - 5.0f) { - moby->state = 6; + moby->state == WAIT_FOR_HERO_TRIGGER_AT_NODE_BASE_HEIGHT && moby->pos.z < ((Hero_2FDA70 *)(D_0013F350))->pos.z - 5.0f) { + moby->state = MOVE_TO_NODE_OFFSET_HEIGHT; set_moby_and_links_to_states_8_and_9(D_L06_0015FFD8_macro + (moby_data->f68 << 8)); moby_data->f90 = scale_game_frames(0x78); } @@ -365,7 +365,7 @@ void elevator_update(Moby_2FDA70 *moby) { float target; float height_acceleration_step; target = l06_cuboids_macro[moby_data->f78].pos.z; - if (moby->state == 6) { + if (moby->state == MOVE_TO_NODE_OFFSET_HEIGHT) { target += l06_cuboids_macro[moby_data->f78].axes[2].z; } height_acceleration_step = height_cycle_acceleration_gp * frame_time_sq_macro; @@ -376,12 +376,12 @@ void elevator_update(Moby_2FDA70 *moby) { height_acceleration_step, height_cycle_max_speed_gp * D_0015ED6C); if (absolute_float(moby->pos.z - target) < 0.01f) { - if (moby->state == 6) { - moby->state = 7; + if (moby->state == MOVE_TO_NODE_OFFSET_HEIGHT) { + moby->state = WAIT_FOR_HERO_CLEARANCE_AT_NODE_OFFSET_HEIGHT; set_moby_and_links_to_states_4_and_5(D_L06_0015FFD8_macro + (moby_data->f64 << 8)); } else { set_moby_and_links_to_states_4_and_5(D_L06_0015FFD8_macro + (moby_data->f68 << 8)); - moby->state = 8; + moby->state = WAIT_FOR_HERO_CLEARANCE_AT_NODE_BASE_HEIGHT; } } break; @@ -389,10 +389,10 @@ void elevator_update(Moby_2FDA70 *moby) { case WAIT_FOR_HERO_CLEARANCE_AT_NODE_OFFSET_HEIGHT: case WAIT_FOR_HERO_CLEARANCE_AT_NODE_BASE_HEIGHT: if (vector_distance_xy(&((Hero_2FDA70 *)(D_0013F350))->pos, &moby->pos) >= 1.0f) { - if (moby->state == 7) { - moby->state = 3; + if (moby->state == WAIT_FOR_HERO_CLEARANCE_AT_NODE_OFFSET_HEIGHT) { + moby->state = WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT; } else { - moby->state = 4; + moby->state = WAIT_FOR_HERO_TRIGGER_AT_NODE_BASE_HEIGHT; } } break; @@ -402,7 +402,7 @@ void elevator_update(Moby_2FDA70 *moby) { } else { ((Hero_2FDA70 *)(D_0013F350))->f22CB = 0; } - if (moby->state >= 5 && moby->state <= 8) { + if (moby->state >= MOVE_TO_NODE_BASE_HEIGHT && moby->state <= WAIT_FOR_HERO_CLEARANCE_AT_NODE_BASE_HEIGHT) { moby_data->f9C = 0.0f; moby->f90 = D_L06_00161F74; } else { From 4fd6f1bc9599eb2f1e4d426b3a4bf53ce588ae29 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:09:50 +0000 Subject: [PATCH 1074/1502] decomp: clarify names in bolt_thief_update domain_0_value_8 -> BOLT_THIEF_KNOCKBACK: Retail 0x002e2e98-0x002e2ea0 compares 8 with byte +0x20 of s2, the moby argument also used by switch dispatch at 0x002e2f90. This is the existing bolt-thief state domain; case 8 at 0x002e37bc runs knockback motion and collision/fall removal. domain_12_value_5 -> BOLT_THIEF_FOLLOW_PRIMARY_PATH_TO_EXIT: Retail 0x002e334c tests the active pickup count and, when zero, loads 5 at 0x002e3354 and stores it to s2+0x20 at 0x002e3364. The same selector dispatches existing case 5, which follows primary waypoints to exit or secondary path. domain_14_value_6 -> BOLT_THIEF_FOLLOW_SECONDARY_PATH: Retail 0x002e34f0-0x002e3510 detects selection of primary path count-1, checks configured secondary path ID at pvars+0x114 and stores 6 to s2+0x20. Existing case 6 at 0x002e3584 uses the secondary follower at pvars+0x100/+0x110. domain_15_value_7 -> BOLT_THIEF_FACE_HERO: Retail 0x002e3688-0x002e36b8 compares hero distance with 19 and stores 7 to s2+0x20 when farther away. Existing case 7 at 0x002e36bc computes hero-facing heading and spring-turns the same moby without a position step. domain_16_value_6 -> BOLT_THIEF_FOLLOW_SECONDARY_PATH: Retail existing case 7 tests hero distance below 17 or helper success, calculates the next secondary waypoint, and stores 6 to s2+0x20 at 0x002e377c. This resumes existing case 6's secondary follower movement; direction can reverse at 0x002e37ac-0x002e37b8. domain_3_value_8 -> BOLT_THIEF_KNOCKBACK: Retail 0x002e2f68 calls trooper_start_knockback on s2, then 0x002e2f88-0x002e2f8c stores 8 to that moby's +0x20 switch selector. The existing BOLT_THIEF_KNOCKBACK case consumes this same field at 0x002e37bc. domain_4_value_1 -> BOLT_THIEF_WAIT_FOR_HERO_NEAR_TRIGGER: Retail initialization stores 1 to s2+0x20 at 0x002e3040. Dispatch reads the same byte at 0x002e2f90; existing case 1 at 0x002e3060-0x002e30b8 waits for hero distance below 24 from the configured trigger-path first point. domain_5_value_5 -> BOLT_THIEF_FOLLOW_PRIMARY_PATH_TO_EXIT: Retail case 1's successful hero-distance test calls the target-list builder at 0x002e30b0, loads 5 at 0x002e30bc and branches to the s2+0x20 store at 0x002e3364. Same selector's existing case 5 follows primary waypoints and exits at count-1. domain_6_value_3 -> BOLT_THIEF_WAIT_FOR_ANIMATION_BEFORE_PULLING_PICKUPS: Retail 0x002e3160-0x002e3180 detects a zero fourth component in the next primary waypoint and stores 3 to s2+0x20. Same moby selector's existing case 3 at 0x002e3204 waits for animation flag bit 2 before entering pickup pulling. domain_9_value_4 -> BOLT_THIEF_PULL_PICKUPS_TO_JOINT: Retail 0x002e3254-0x002e3264 stores 4 to s2+0x20 after the case-3 animation completion branch. This is the thief's switch selector, not the list entry selector. Existing case 4 at 0x002e328c-0x002e3348 moves pickups toward joint 0. --- src/overlays/l08/mobys/bolt_thief.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l08/mobys/bolt_thief.c b/src/overlays/l08/mobys/bolt_thief.c index e13ec4a7c8..14f66aafba 100644 --- a/src/overlays/l08/mobys/bolt_thief.c +++ b/src/overlays/l08/mobys/bolt_thief.c @@ -121,7 +121,7 @@ void bolt_thief_update(struct Moby *moby) { moby->shadow_range = 0x17; } } - if (FUN_L00_0025a420(moby, 0x210000, 0) != 0 && moby->state != 8) { + if (FUN_L00_0025a420(moby, 0x210000, 0) != 0 && moby->state != BOLT_THIEF_KNOCKBACK) { int i; for (i = 0; i < 0x32; i++) { @@ -150,7 +150,7 @@ void bolt_thief_update(struct Moby *moby) { 0); bolt_thief_instance_vars->b67 = 0x78; FUN_L00_00257470(moby, 0, -1); - moby->state = 8; + moby->state = BOLT_THIEF_KNOCKBACK; } moby->hit_slot = 0xFF; switch (moby->state) { @@ -168,7 +168,7 @@ void bolt_thief_update(struct Moby *moby) { bolt_thief_instance_vars->b29 = 0; moby->spawn_frame = *(u64 *)(*(char **)D_001413D0 + 0x38); clear_u64_value(&bolt_thief_instance_vars->v40); - moby->state = 1; + moby->state = BOLT_THIEF_WAIT_FOR_HERO_NEAR_TRIGGER; if (moby->prev_seq != 1) { FUN_00212f90(moby, 1, 0, 0); } @@ -177,7 +177,7 @@ void bolt_thief_update(struct Moby *moby) { qcopy(&point, &l08_paths[bolt_thief_instance_vars->w220]->points[0]); if (fast_vec_dist(hero.motion.pos.f, &point) < 24.0f) { build_bolt_thief_target_list((char *)moby); - moby->state = 5; + moby->state = BOLT_THIEF_FOLLOW_PRIMARY_PATH_TO_EXIT; if (moby->prev_seq != 3) { FUN_00212f90(moby, 3, 0, 6); } @@ -198,7 +198,7 @@ void bolt_thief_update(struct Moby *moby) { path = follower->path; qcopy(&point, &path->points[next]); if (path->points[next].f[3] == 0.0f) { - moby->state = 3; + moby->state = BOLT_THIEF_WAIT_FOR_ANIMATION_BEFORE_PULLING_PICKUPS; if (moby->prev_seq != 2) { FUN_00212f90(moby, 2, 0, 6); } @@ -225,7 +225,7 @@ void bolt_thief_update(struct Moby *moby) { other->state = 3; } } - moby->state = 4; + moby->state = BOLT_THIEF_PULL_PICKUPS_TO_JOINT; if (moby->prev_seq != 6) { FUN_00212f90(moby, 6, 0, 6); } @@ -254,7 +254,7 @@ void bolt_thief_update(struct Moby *moby) { } } if (active_count == 0) { - moby->state = 5; + moby->state = BOLT_THIEF_FOLLOW_PRIMARY_PATH_TO_EXIT; if (moby->prev_seq != 3) { FUN_00212f90(moby, 3, 0, 6); } @@ -295,7 +295,7 @@ void bolt_thief_update(struct Moby *moby) { } if (follower->path->count - 1 == next) { if (bolt_thief_instance_vars->follow[1].path_id >= 0) { - moby->state = 6; + moby->state = BOLT_THIEF_FOLLOW_SECONDARY_PATH; break; } mark_moby_for_removal(moby); @@ -328,7 +328,7 @@ void bolt_thief_update(struct Moby *moby) { follower->point = next; } if (fast_vec_dist(hero.motion.pos.f, &moby->pos) > 19.0f) { - moby->state = 7; + moby->state = BOLT_THIEF_FACE_HERO; } break; } @@ -349,7 +349,7 @@ void bolt_thief_update(struct Moby *moby) { follower = &bolt_thief_instance_vars->follow[1]; next = (follower->point + follower->path->count + follower->direction) % follower->path->count; - moby->state = 6; + moby->state = BOLT_THIEF_FOLLOW_SECONDARY_PATH; if (fast_vec_dist(hero_position, &follower->path->points[next]) < distance) { follower->direction *= -1; } From 8c6e4534f722deefc8b20eebb1f1dddfd358ec2e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:09:50 +0000 Subject: [PATCH 1075/1502] decomp: clarify names in shuttle_update domain_0_value_1 -> WAIT_FOR_SHUTTLE_ROUTE_REQUEST: Retail 0x003026a8-0x003026bc stores 1 to s3+0x20 after initialization; 0x00302618 loads that same byte for the outer switch. The authoritative source names its case 1 WAIT_FOR_SHUTTLE_ROUTE_REQUEST, whose branch handles route prompts and go requests. domain_10_value_7 -> WAIT_TO_SELECT_SHUTTLE_SAVE_FLOW: Retail 0x00302f58-0x00302f7c waits for the shared gate, queues movie 5, then stores 7 to moby+0x20. Existing outer case 7 WAIT_TO_SELECT_SHUTTLE_SAVE_FLOW selects immediate save and request resumption or scene 5 followed by deferred-save state 9. domain_1_value_3 -> UPDATE_SHUTTLE_PATH_RIDE: Retail 0x00302a1c-0x00302a24 consumes pvars+0x110 and stores 3 to moby+0x20 before ride setup. The same state byte selects existing case UPDATE_SHUTTLE_PATH_RIDE, which calls 0x00303160 at 0x00302bb0 until ride completion. domain_2_value_4 -> RESTORE_SHUTTLE_IDLE_ANIMATION: Retail 0x00302bb0-0x00302bc0 stores 4 to moby+0x20 only after the path-ride helper reports completion. Existing case 4 RESTORE_SHUTTLE_IDLE_ANIMATION at 0x00302e80-0x00302eb4 returns to request state and blends animation sequence 2. domain_3_value_6 -> WAIT_FOR_HERO_NEAR_LINKED_MOBY: Retail 0x00302cd4-0x00302d08 consumes the follow-up flag, initializes the indexed linked moby and stores 6 to moby+0x20. Existing case 6 at 0x00302d48-0x00302d88 waits for hero distance from that linked moby to be less than 3.5, proving the existing lifecycle member. domain_4_value_8 -> WAIT_TO_ENTER_SHUTTLE_SAVE_FLOW: Retail 0x00302d90-0x00302e14 handles hero proximity, removes the linked moby, unlocks planet 5 and stores 8 to moby+0x20. Existing case 8 WAIT_TO_ENTER_SHUTTLE_SAVE_FLOW at 0x00302f58-0x00302f7c waits for the shared gate and transitions to save-flow selection state 7. domain_5_value_1 -> WAIT_FOR_SHUTTLE_ROUTE_REQUEST: Retail 0x00302e50-0x00302e7c prepares forced-return route selector 2, destination 0 and go/follow-up flags, then stores 1 to moby+0x20. The outer switch reads this same byte; existing request-state case 1 consumes go and enters ride state 3, independently of the separate route selector. domain_6_value_1 -> WAIT_FOR_SHUTTLE_ROUTE_REQUEST: Retail 0x00302e80-0x00302e88 stores 1 to moby+0x20 from existing RESTORE_SHUTTLE_IDLE_ANIMATION and blends sequence 2 if needed. The outer switch loads moby+0x20 at 0x00302618 and existing case 1 resumes route-request processing. domain_7_value_9 -> WAIT_TO_SAVE_AND_RESUME_SHUTTLE_REQUESTS: Retail 0x00302ee8-0x00302ef4 calls start_scene(5) and loads 9, with 0x00302f7c storing it to moby+0x20. Existing case 9 at 0x00302f20-0x00302f54 waits for the shared gate, saves through memcard_save_data(0,-1), and returns to request state 1. domain_8_value_1 -> WAIT_FOR_SHUTTLE_ROUTE_REQUEST: Retail 0x00302ef8-0x00302f14 follows the immediate-save branch, calls the planet unlock message helper, stores 1 to moby+0x20 and saves. This is the exact byte used by the outer switch and its existing WAIT_FOR_SHUTTLE_ROUTE_REQUEST member, not a hero-state selector. domain_9_value_1 -> WAIT_FOR_SHUTTLE_ROUTE_REQUEST: Retail 0x00302f38-0x00302f54 calls the planet unlock message helper and memcard_save_data(0,-1), then stores 1 to moby+0x20. Existing deferred-save case 9 therefore resumes the outer switch's WAIT_FOR_SHUTTLE_ROUTE_REQUEST state. --- src/overlays/l06/mobys/shuttle.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l06/mobys/shuttle.c b/src/overlays/l06/mobys/shuttle.c index 978ea35012..bd1bc4d665 100644 --- a/src/overlays/l06/mobys/shuttle.c +++ b/src/overlays/l06/mobys/shuttle.c @@ -288,7 +288,7 @@ void shuttle_update(struct Moby *moby) { moby->update_dist = 0xFF; moby->draw_dist = 0x80; moby->spawn_frame = hero.moby->spawn_frame; - moby->state = 1; + moby->state = WAIT_FOR_SHUTTLE_ROUTE_REQUEST; if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, 0); } @@ -385,7 +385,7 @@ void shuttle_update(struct Moby *moby) { } if (shuttle_vars->go != 0) { shuttle_vars->go = 0; - moby->state = 3; + moby->state = UPDATE_SHUTTLE_PATH_RIDE; remove_help_message_for_selector(10); if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 0); @@ -411,7 +411,7 @@ void shuttle_update(struct Moby *moby) { if (update_shuttle_path_ride((char *)moby, shuttle_vars->side) != 0) { int ofs; int base; - moby->state = 4; + moby->state = RESTORE_SHUTTLE_IDLE_ANIMATION; shuttle_vars->fF4 = 0; ofs = shuttle_vars->cam[shuttle_vars->sel] << 7; base = (int)l06_cuboids; @@ -439,7 +439,7 @@ void shuttle_update(struct Moby *moby) { initialize_moby_particle_effect_state(D_L06_0015FFD8_302578 + (shuttle_vars->f10C << 8)); shuttle_vars->f114 = 0; - moby->state = 6; + moby->state = WAIT_FOR_HERO_NEAR_LINKED_MOBY; if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(30)); } @@ -459,7 +459,7 @@ void shuttle_update(struct Moby *moby) { start_scene(12); mark_moby_for_removal(linked_moby); unlock_planet(5); - moby->state = 8; + moby->state = WAIT_TO_ENTER_SHUTTLE_SAVE_FLOW; jet_clear_persistent(shuttle_vars->fF8); jet_reset_camera(b, rot); } @@ -472,11 +472,11 @@ void shuttle_update(struct Moby *moby) { shuttle_vars->sel = 0; shuttle_vars->go = 1; shuttle_vars->f114 = 1; - moby->state = 1; + moby->state = WAIT_FOR_SHUTTLE_ROUTE_REQUEST; } break; case RESTORE_SHUTTLE_IDLE_ANIMATION: - moby->state = 1; + moby->state = WAIT_FOR_SHUTTLE_ROUTE_REQUEST; if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(30)); } @@ -485,10 +485,10 @@ void shuttle_update(struct Moby *moby) { if (D_L06_0015F5C4 != 2) { if (D_0013D4D5[9] != 0) { start_scene(5); - moby->state = 9; + moby->state = WAIT_TO_SAVE_AND_RESUME_SHUTTLE_REQUESTS; } else { queue_planet_unlock_message(5); - moby->state = 1; + moby->state = WAIT_FOR_SHUTTLE_ROUTE_REQUEST; enter_hero_idle_state_for_current_vehicle_mode(); memcard_save_data(0, -1); } @@ -498,13 +498,13 @@ void shuttle_update(struct Moby *moby) { if (D_L06_0015F5C4 != 2) { queue_planet_unlock_message(5); memcard_save_data(0, -1); - moby->state = 1; + moby->state = WAIT_FOR_SHUTTLE_ROUTE_REQUEST; } break; case WAIT_TO_ENTER_SHUTTLE_SAVE_FLOW: if (D_L06_0015F5C4 != 2) { queue_scene_movie_with_game_language(5); - moby->state = 7; + moby->state = WAIT_TO_SELECT_SHUTTLE_SAVE_FLOW; } break; } From f8d8b039da0b3022f78c00055c6dcf50d81ca297 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:11:40 +0000 Subject: [PATCH 1076/1502] decomp: clarify names in update_child_sets_controller domain_0_value_1 -> CHILD_SETS_STATE_WAIT_FOR_LINK_TRIGGER: Source SHA-256 4e316b17e7b11c294235896728843f54818e70642edc4c0e4aa9315a216dcb13 assigns 1 to child_sets_controller->state after creating and posing the children. Retail 0030ca70..0030ca7c supplies 1 to the byte store at 0030d17c, at controller +0x20. This is the exact field read for dispatch at 0030c7b8. Its existing case 1, 0030ca80..0030caa8, waits for the linked-moby predicate; reuse the same local enum member. domain_1_value_2 -> CHILD_SETS_STATE_FADE_BEFORE_ACTIVATION: Retail 0030ca80..0030caa8 tests the linked-moby index and predicate, then stores 2 at s3+0x20, the same controller-state byte used by dispatch at 0030c7b8. Existing source case CHILD_SETS_STATE_FADE_BEFORE_ACTIVATION owns that value and retail 0030caac..0030cae4 approaches pvars+0xC to 1 before the child activation loops at 0030cbc8..0030ccd0. Reuse this canonical local state constant. domain_2_value_3 -> CHILD_SETS_STATE_UNFOLD_AND_BLEND_POSES: Retail 0030cad4..0030caec checks that controller pvars fade at +0xC reached 1, then stores 3 to s3+0x20, the same state byte read at 0030c7b8. The existing source case CHILD_SETS_STATE_UNFOLD_AND_BLEND_POSES corresponds to retail 0030ccec onward: staggered child progress, update_child_set_poses at 0030cf74, and pose interpolation at 0030d05c..0030d0d4. Reuse the existing member for this transition. domain_3_value_4 -> CHILD_SETS_STATE_FADE_AFTER_HERO_HANDOFF: Retail 0030d0d8..0030d114 tests fade reaching 1, finishes child poses and stores 4 to s3+0x20. It ends the mount and hands back the hero pose through set_race_camera at 0030d110..0030d12c. This is the same controller-state dispatch field at 0030c7b8, whose existing source case CHILD_SETS_STATE_FADE_AFTER_HERO_HANDOFF approaches fade to zero at 0030d140..0030d174. Reuse that member. domain_4_value_5 -> CHILD_SETS_STATE_COMPLETE: Existing case CHILD_SETS_STATE_FADE_AFTER_HERO_HANDOFF approaches controller pvars+0xC to zero. Retail 0030d164..0030d178 compares that fade exactly with zero and only then supplies 5 to the state-byte store at 0030d17c (s3+0x20). On subsequent updates 0030c7b8..0030c7c0 dispatches only state values below 5 and returns for 5, proving completion of this controller sequence, without claiming that external code cannot reactivate it. --- src/overlays/l11/mobys/child_sets_controller.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/overlays/l11/mobys/child_sets_controller.c b/src/overlays/l11/mobys/child_sets_controller.c index d47330641f..5fd7163bdf 100644 --- a/src/overlays/l11/mobys/child_sets_controller.c +++ b/src/overlays/l11/mobys/child_sets_controller.c @@ -72,6 +72,9 @@ void child_sets_controller_update(struct Moby *child_sets_controller) { CHILD_SETS_STATE_UNFOLD_AND_BLEND_POSES = 3, CHILD_SETS_STATE_FADE_AFTER_HERO_HANDOFF = 4 }; + enum { + CHILD_SETS_STATE_COMPLETE = 5 + }; CamVars_c788 *child_sets_controller_vars = (CamVars_c788 *)child_sets_controller->pvars; Vec4f pos; Vec4f rot; @@ -140,13 +143,13 @@ void child_sets_controller_update(struct Moby *child_sets_controller) { D_L11_00161F10[i]->collision = 0; } update_child_set_poses(child_sets_controller); - child_sets_controller->state = 1; + child_sets_controller->state = CHILD_SETS_STATE_WAIT_FOR_LINK_TRIGGER; break; case CHILD_SETS_STATE_WAIT_FOR_LINK_TRIGGER: if (child_sets_controller_vars->link != -1 && test_linked_moby_turn_trigger( (void *)(D_L11_0015FFD8_c788 + (child_sets_controller_vars->link << 8)))) { - child_sets_controller->state = 2; + child_sets_controller->state = CHILD_SETS_STATE_FADE_BEFORE_ACTIVATION; } break; case CHILD_SETS_STATE_FADE_BEFORE_ACTIVATION: @@ -154,7 +157,7 @@ void child_sets_controller_update(struct Moby *child_sets_controller) { D_L11_0015F3FC = child_sets_controller_vars->fade; if (1.0f <= child_sets_controller_vars->fade) { int j; - child_sets_controller->state = 3; + child_sets_controller->state = CHILD_SETS_STATE_UNFOLD_AND_BLEND_POSES; qcopy(&pos, &((struct Moby *)(D_L11_0015FFD8_c788 + (child_sets_controller_vars->link << 8))) ->pos); @@ -278,7 +281,7 @@ void child_sets_controller_update(struct Moby *child_sets_controller) { D_L11_00161ED4 = 1.0f; D_L11_00161ED8 = 1.0f; update_child_set_poses(child_sets_controller); - child_sets_controller->state = 4; + child_sets_controller->state = CHILD_SETS_STATE_FADE_AFTER_HERO_HANDOFF; jet_end_mount(3); set_race_camera(&hero.motion.pos, &hero.motion.rot, 0, 1); alternate_item_available[0x56] = 1; @@ -288,7 +291,7 @@ void child_sets_controller_update(struct Moby *child_sets_controller) { approach_value(&child_sets_controller_vars->fade, 0.0f, frame_time * 4.0f); D_L11_0015F3FC = child_sets_controller_vars->fade; if (child_sets_controller_vars->fade == 0.0f) { - child_sets_controller->state = 5; + child_sets_controller->state = CHILD_SETS_STATE_COMPLETE; } break; } From 5ccac7d3508ecdf7b53a5dc4aac6d5a6ca91ab9c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:11:40 +0000 Subject: [PATCH 1077/1502] decomp: clarify names in crate_update domain_0_value_0 -> CRATE_STATE_INITIALIZE: Retail 0x002cf2bc..0x002cf2d8 reads the updated crate's state byte at s1+0x20 and skips stack motion for zero; 0x002cf348 dispatches that same byte to the source's existing CRATE_STATE_INITIALIZE case. domain_10_value_1 -> CRATE_STATE_PROCESS_HITS: Retail 0x002cf8d0..0x002cf934 attaches the respawning crate atop the eligible group crate, links rider/below and writes 1 to the updated crate state at 0x002cf908 while restoring visibility/collision; reuse existing CRATE_STATE_PROCESS_HITS. domain_11_value_1 -> CRATE_STATE_PROCESS_HITS: Retail 0x002cfa90..0x002cfa98 reads the updated crate's state +0x20 and compares it to 1 to detect successful group-stack respawn. This is the same state byte dispatched to existing CRATE_STATE_PROCESS_HITS, not a control selector. domain_12_value_1 -> CRATE_STATE_PROCESS_HITS: Retail 0x002cfaa0..0x002cfae8 probes ground when stack respawn did not restore state 1, then writes 1 at 0x002cfab8, clears rider/below and restores visibility/collision. It resumes the existing CRATE_STATE_PROCESS_HITS branch. domain_13_value_1 -> CRATE_STATE_PROCESS_HITS: Retail 0x002cfc6c..0x002cfc88 ticks the reactivation command byte and, when complete, writes 1 to the updated crate state +0x20 and clears flags bit 0. The same selector dispatches to existing CRATE_STATE_PROCESS_HITS. domain_1_value_6 -> CRATE_STATE_WAIT_RESPAWN: Retail 0x002cf39c..0x002cf3c0 writes 6 to this crate's state at +0x20 while disabling collision during initialization; the same selector's existing CRATE_STATE_WAIT_RESPAWN case at 0x002cf830 waits for the respawn checks. domain_2_value_1 -> CRATE_STATE_PROCESS_HITS: Retail 0x002cf3c4..0x002cf3c8 writes 1 to the updated crate state after ordinary initialization; the dispatch at 0x002cf348 and hit-handling branch at 0x002cf428 establish the existing CRATE_STATE_PROCESS_HITS member. domain_3_value_5 -> CRATE_STATE_DETONATION_COUNTDOWN: Retail 0x002cf428..0x002cf488 tests class 0x1F9 and hero contact, clears command +0xBC, and writes 5 to crate state +0x20. Its existing state-5 case at 0x002cfaec initializes and runs the detonation countdown. domain_4_value_5 -> CRATE_STATE_DETONATION_COUNTDOWN: Retail 0x002cf4d8..0x002cf528 writes 5 to the same crate state byte after a damaging contact, sets its command timer and saves spawn_frame. The existing state-5 handler flashes, sounds and calls break_crate when the countdown ends. domain_5_value_2 -> CRATE_STATE_CLASS_CHANGE_COOLDOWN: Retail 0x002cf5bc..0x002cf620 changes the crate class and class pointers, updates animation, writes 2 to state +0x20 and starts a 15-frame command timer. Existing CRATE_STATE_CLASS_CHANGE_COOLDOWN decrements that timer at 0x002cf6a4. domain_6_value_1 -> CRATE_STATE_PROCESS_HITS: Retail 0x002cf6a4..0x002cf6c8 decrements the class-change command byte, resets hit_slot on expiration and writes 1 to the same crate state selector. This returns to the existing CRATE_STATE_PROCESS_HITS dispatch branch. domain_7_value_6 -> CRATE_STATE_WAIT_RESPAWN: Retail 0x002cf7b8..0x002cf81c hides the broken respawnable crate, disables collision, writes 6 to its state byte and initializes pvars+0xC9 with a delay. Existing CRATE_STATE_WAIT_RESPAWN consumes that delay at 0x002cf884. domain_8_value_1 -> CRATE_STATE_PROCESS_HITS: Retail 0x002cf894..0x002cf8cc restores an ungrouped crate after the respawn checks, writes state 1 at +0x20, restores visibility and collision. The same selector dispatches 1 to existing CRATE_STATE_PROCESS_HITS. domain_9_value_1 -> CRATE_STATE_PROCESS_HITS: Retail 0x002cfa08..0x002cfa68 iterates this crate's group, compares the member state byte +0x20 to 1, then reads its pvars+0xA0 rider. At 0x002cf8d0..0x002cf8fc it places the respawning crate atop that member and links CrateVars rider/below, proving this is the crate state domain and existing PROCESS_HITS state. --- src/overlays/shared/pickups/crate.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/overlays/shared/pickups/crate.c b/src/overlays/shared/pickups/crate.c index 86b5dc03d6..dfa249de19 100644 --- a/src/overlays/shared/pickups/crate.c +++ b/src/overlays/shared/pickups/crate.c @@ -287,7 +287,7 @@ void crate_update(struct Moby *moby) { } else { coll->flags &= ~1; } - if (crate_vars->frameB4 != D_L00_0015F5CC_macro && moby->state != 0 && + if (crate_vars->frameB4 != D_L00_0015F5CC_macro && moby->state != CRATE_STATE_INITIALIZE && (crate_vars->flags & 0xC)) { update_crate_stack_motion(moby); } @@ -305,12 +305,12 @@ void crate_update(struct Moby *moby) { case CRATE_STATE_INITIALIZE: clear_u64_value(&crate_vars->unk40); if (D_0015ED84 == 0x12 && moby->oclass == 0x1FF && crate_vars->unkC8 != 0) { - moby->state = 6; + moby->state = CRATE_STATE_WAIT_RESPAWN; moby->flags |= 0x41; moby->collision = 0; moby->flags &= ~0x1000; } else { - moby->state = 1; + moby->state = CRATE_STATE_PROCESS_HITS; } crate_vars->unkA8 = 0; if ((crate_vars->flags ^ 1) & 1) { @@ -330,7 +330,7 @@ void crate_update(struct Moby *moby) { (hero.ground_moby == moby && hero.air_frames.s == 0) || hero.ledge_moby == (s32)moby || touched)) { moby->command = 0; - moby->state = 5; + moby->state = CRATE_STATE_DETONATION_COUNTDOWN; break; } if (hit_contact == NULL || !(hit_contact->damage > 0.0f)) { @@ -341,7 +341,7 @@ void crate_update(struct Moby *moby) { doHit = 0; } if (moby->oclass == 0x1F9) { - moby->state = 5; + moby->state = CRATE_STATE_DETONATION_COUNTDOWN; if (hit_contact->hit.s.flags & 0x20000) { moby->command = 1; } else { @@ -372,7 +372,7 @@ void crate_update(struct Moby *moby) { moby->pclass = D_L00_00197300[moby->class_slot]; update_moby_animation_state(moby); moby->unk72 = ((Part *)moby->pclass)->unkE; - moby->state = 2; + moby->state = CRATE_STATE_CLASS_CHANGE_COOLDOWN; moby->command = scale_game_frames(15); doHit = 0; } @@ -399,7 +399,7 @@ void crate_update(struct Moby *moby) { case CRATE_STATE_CLASS_CHANGE_COOLDOWN: if (--moby->command == 0xFF) { moby->hit_slot = 0xFF; - moby->state = 1; + moby->state = CRATE_STATE_PROCESS_HITS; } break; @@ -430,7 +430,7 @@ void crate_update(struct Moby *moby) { if (moby->unkB4 >= 2) { moby->unkB4 = 1; } - moby->state = 6; + moby->state = CRATE_STATE_WAIT_RESPAWN; if (D_0015ED84 == 0x12) { crate_vars->unkC9 = FUN_L00_00257b90(300, 720); } else { @@ -452,7 +452,7 @@ void crate_update(struct Moby *moby) { break; } if (moby->group == 0xFF) { - moby->state = 1; + moby->state = CRATE_STATE_PROCESS_HITS; moby->visible = 1; moby->flags &= ~1; moby->collision = ((Part *)moby->pclass)->unk10; @@ -489,7 +489,7 @@ void crate_update(struct Moby *moby) { get_first_moby_in_group(&it, moby->group, 0, 0); while (it != NULL) { if (moby != it && !(vector_distance_xy(&moby->pos, &it->pos) > 0.1f) && - it->state == 1) { + it->state == CRATE_STATE_PROCESS_HITS) { CrateVars *ipv = (CrateVars *)it->pvars; if (ipv->rider == NULL) { @@ -498,7 +498,7 @@ void crate_update(struct Moby *moby) { ipv->rider = moby; crate_vars->below = it; crate_vars->rider = NULL; - moby->state = 1; + moby->state = CRATE_STATE_PROCESS_HITS; moby->visible = 1; moby->flags &= ~1; moby->collision = ((Part *)moby->pclass)->unk10; @@ -509,9 +509,9 @@ void crate_update(struct Moby *moby) { } get_next_moby_in_group(&it, it, 0, 0); } - if (moby->state != 1) { + if (moby->state != CRATE_STATE_PROCESS_HITS) { moby->pos.z = probe_ground_height(&moby->pos, 0, 0.5f); - moby->state = 1; + moby->state = CRATE_STATE_PROCESS_HITS; crate_vars->rider = NULL; crate_vars->below = NULL; moby->visible = 1; @@ -549,7 +549,7 @@ void crate_update(struct Moby *moby) { case CRATE_STATE_REACTIVATION_DELAY: if (FUN_L00_001fefc8(&moby->command)) { - moby->state = 1; + moby->state = CRATE_STATE_PROCESS_HITS; moby->flags &= ~1; } break; From 2b65db2ea6091ac30a5018fdb7b0343f33cc1878 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:11:40 +0000 Subject: [PATCH 1078/1502] decomp: clarify names in bomber_jet_update domain_0_value_0 -> BOMBER_JET_STATE_INITIALIZE: Retail 0x002f798c loads the bomber jet state byte from s5+0x20 and 0x002f7990 skips initialization when nonzero. The zero branch builds stop_nodes from path point w==1 (0x002f7a0c-0x002f7a64), clears gun_side, initializes last_fire_node and cutscene_timer to -1, and saves base_speed/base_scale at 0x002f7a68-0x002f7a88. This proves initialization of this bomber jet moby, not a hero enum. domain_1_value_0 -> BOMBER_JET_STATE_INITIALIZE: Retail 0x002f7bb4 loads the same bomber jet state byte s5+0x20 and 0x002f7bb8 bypasses the call when nonzero; zero invokes gunship_follow_path at 0x002f7bc0 with this moby in a0. This is the same selector and initialization value as 0x002f798c. Checked helper 0x002f5464-0x002f54a4 dispatches that moby state zero to path initialization, including path endpoint preparation at 0x002f54a4-0x002f5540. Both comparisons therefore reuse BOMBER_JET_STATE_INITIALIZE. --- src/overlays/l01/mobys/bomber_jet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l01/mobys/bomber_jet.c b/src/overlays/l01/mobys/bomber_jet.c index 405aefec11..1eea37f495 100644 --- a/src/overlays/l01/mobys/bomber_jet.c +++ b/src/overlays/l01/mobys/bomber_jet.c @@ -261,7 +261,7 @@ void bomber_jet_update(GunshipMoby *m) __asm__("FUN_L01_002f7728"); /* Moby class 688 */ void bomber_jet_update(GunshipMoby *bomber_jet_moby) { - GunshipVars *gunship_vars = bomber_jet_moby->vars; + enum { BOMBER_JET_STATE_INITIALIZE = 0 } ;GunshipVars *gunship_vars = bomber_jet_moby->vars; GunshipFollow *sub = &gunship_vars->sub; float distance_scale; void *hit; @@ -320,7 +320,7 @@ void bomber_jet_update(GunshipMoby *bomber_jet_moby) { return; } do { - if (bomber_jet_moby->state == 0) { + if (bomber_jet_moby->state == BOMBER_JET_STATE_INITIALIZE) { if (sub->path != -1) { GunshipPath *path = (GunshipPath *)l01_paths[sub->path]; j = 0; @@ -365,7 +365,7 @@ void bomber_jet_update(GunshipMoby *bomber_jet_moby) { bomber_jet_moby->alpha = 0x80; } if (gunship_vars->trigger_volume != -1) { - if (bomber_jet_moby->state == 0) { + if (bomber_jet_moby->state == BOMBER_JET_STATE_INITIALIZE) { gunship_update((char *)bomber_jet_moby); } if (gunship_vars->cutscene_timer == -1 && From 5d505ace06936d3b4c3b1331a6a0a8c62a17d495 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:13:18 +0000 Subject: [PATCH 1079/1502] decomp: clarify names in bomb_glove_update domain_0_value_3 -> BOMB_GLOVE_RELEASE_HELD_MOBY: Retail 0x002c28cc-0x002c28dc consumes one ammo and stores 3 at moby +0x20 (s3, original a0). The same byte is the switch selector at 0x002c2fa8; existing source case BOMB_GLOVE_RELEASE_HELD_MOBY=3 calls launch_bomb on held moby at 0x002c3024, then clears held. This reuses the exact same local enum domain. domain_2_value_1 -> BOMB_GLOVE_WAIT_FOR_ANIMATION: Retail initialization at 0x002c2fd0 clears held and tests moby animation flag bit 2 at +0x70. When absent, 0x002c2fe4 loads 1 and 0x002c2fe8 stores it to the same +0x20 byte selected by the switch at 0x002c2fa8. Existing BOMB_GLOVE_WAIT_FOR_ANIMATION=1 branch at 0x002c2fec-0x002c3000 waits for that animation bit. domain_5_value_4 -> BOMB_GLOVE_POST_RELEASE_WAIT: After launch_bomb at 0x002c3024 and delivery bookkeeping, 0x002c30cc clears held, 0x002c30b8 loads 4 into a2, and 0x002c30d4 stores a2 to original moby +0x20. The existing same-domain case BOMB_GLOVE_POST_RELEASE_WAIT=4 at 0x002c30e0-0x002c3108 waits for hero state/animation completion before transitioning. domain_7_value_6 -> BOMB_GLOVE_REMOVE_HELD_MOBY: Existing BOMB_GLOVE_BEGIN_HELD_MOBY_REMOVAL branch at 0x002c310c loads 6 and 0x002c3114 stores it to original moby +0x20, the switch selector at 0x002c2fa8. Existing same-domain case BOMB_GLOVE_REMOVE_HELD_MOBY=6 at 0x002c3118-0x002c3124 passes nonnull held moby to mark_moby_for_removal. --- src/overlays/shared/weapons/bomb_glove.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/weapons/bomb_glove.c b/src/overlays/shared/weapons/bomb_glove.c index 39f6131686..fb8958e850 100644 --- a/src/overlays/shared/weapons/bomb_glove.c +++ b/src/overlays/shared/weapons/bomb_glove.c @@ -212,7 +212,7 @@ void bomb_glove_update(struct Moby *moby) { (hero.state.current == 0x23 && hero.state_timer == scale_game_frames(0x10))) { allocate_hero_voice_for_entry(0x1A, 0); use_ammo(-1, 1); - moby->state = 3; + moby->state = BOMB_GLOVE_RELEASE_HELD_MOBY; } } if (bomb_glove_vars->held != 0) { @@ -339,7 +339,7 @@ void bomb_glove_update(struct Moby *moby) { case BOMB_GLOVE_INITIALIZE: bomb_glove_vars->held = 0; if (!(moby->anim_flags & 2)) - moby->state = 1; + moby->state = BOMB_GLOVE_WAIT_FOR_ANIMATION; else moby->state = 2; case BOMB_GLOVE_WAIT_FOR_ANIMATION: @@ -364,7 +364,7 @@ void bomb_glove_update(struct Moby *moby) { (((DeliveryStats_2c26c8 *)item_usage)->levels | (1u << current_level_index)) | 0x80000000; bomb_glove_vars->held = 0; - moby->state = 4; + moby->state = BOMB_GLOVE_POST_RELEASE_WAIT; bomb_glove_vars->timer = scale_game_frames(0x14); } break; @@ -373,7 +373,7 @@ void bomb_glove_update(struct Moby *moby) { moby->state = 2; break; case BOMB_GLOVE_BEGIN_HELD_MOBY_REMOVAL: - moby->state = 6; + moby->state = BOMB_GLOVE_REMOVE_HELD_MOBY; break; case BOMB_GLOVE_REMOVE_HELD_MOBY: /* Retail reloads held after destruction before the common tail. */ From 89c07052e5d3d014a1dd44477cdf780e68962cad Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:13:18 +0000 Subject: [PATCH 1080/1502] decomp: clarify names in veldin_robot_enemy_update domain_0_value_1 -> VELDIN_ROBOT_STATE_WAIT_TO_FOLLOW_PATH: At 0x002e0d10-0x002e0d34 initialization copies path point zero into moby position then stores 1. Existing WAIT_TO_FOLLOW_PATH case cycles animations and waits for vars+0x114 != 2 before entering path motion. The retail selector loads moby+0x20 at 0x002e0c5c and dispatches it at 0x002e0c60-0x002e0c7c; this assignment writes that same byte, matching the existing function-local VELDIN_ROBOT_STATE enum, not a Hero or control-mode domain. domain_10_value_3 -> VELDIN_ROBOT_STATE_FACE_TARGET: In DAMAGE_KNOCKBACK, 0x002e14f8-0x002e1504 calls step_moby_motion and masks its result by 0x140; a nonzero result reaches store 3 at 0x002e151c. This returns to the existing FACE_TARGET case, matching recovery behavior. The retail selector loads moby+0x20 at 0x002e0c5c and dispatches it at 0x002e0c60-0x002e0c7c; this assignment writes that same byte, matching the existing function-local VELDIN_ROBOT_STATE enum, not a Hero or control-mode domain. domain_1_value_3 -> VELDIN_ROBOT_STATE_FACE_TARGET: At 0x002e0cfc the negative path index selects 0x002e0d40-0x002e0d4c, which stores 3 when initialization has no path. Existing FACE_TARGET case at 0x002e0fbc-0x002e1010 turns toward target-relative XY heading. The retail selector loads moby+0x20 at 0x002e0c5c and dispatches it at 0x002e0c60-0x002e0c7c; this assignment writes that same byte, matching the existing function-local VELDIN_ROBOT_STATE enum, not a Hero or control-mode domain. domain_2_value_2 -> VELDIN_ROBOT_STATE_FOLLOW_PATH: At 0x002e0df0-0x002e0e08 the wait handler stores 2 when vars+0x114 differs from 2. Existing FOLLOW_PATH handler at 0x002e0e24-0x002e0fb0 fetches indexed waypoints, updates speed, advances pathPt and moves position. The retail selector loads moby+0x20 at 0x002e0c5c and dispatches it at 0x002e0c60-0x002e0c7c; this assignment writes that same byte, matching the existing function-local VELDIN_ROBOT_STATE enum, not a Hero or control-mode domain. domain_3_value_3 -> VELDIN_ROBOT_STATE_FACE_TARGET: At 0x002e0f4c-0x002e0f74 pathPt increments and is compared with path count; completion stores 3. That is the existing FACE_TARGET selector case, whose target-relative XY angle drives heading at 0x002e0fbc-0x002e1010. The retail selector loads moby+0x20 at 0x002e0c5c and dispatches it at 0x002e0c60-0x002e0c7c; this assignment writes that same byte, matching the existing function-local VELDIN_ROBOT_STATE enum, not a Hero or control-mode domain. domain_4_value_4 -> VELDIN_ROBOT_STATE_WAIT_TO_START_COLLISION_PROBES: At 0x002e10c0-0x002e10f0 FACE_TARGET checks vars+0x114 and successful register_beam_slot then stores 4. Existing WAIT_TO_START_COLLISION_PROBES case continues facing and waits on moby+0x70 bit 2 before clearing timer and entering probe state 5. The retail selector loads moby+0x20 at 0x002e0c5c and dispatches it at 0x002e0c60-0x002e0c7c; this assignment writes that same byte, matching the existing function-local VELDIN_ROBOT_STATE enum, not a Hero or control-mode domain. domain_5_value_5 -> VELDIN_ROBOT_STATE_PROCESS_COLLISION_PROBES: At 0x002e1164-0x002e1178 the wait handler tests moby+0x70 bit 2, clears vars+0x1d8 and stores 5. Existing PROCESS_COLLISION_PROBES case builds a bone transform and issues collision_line calls at 0x002e1348 and 0x002e13bc. The retail selector loads moby+0x20 at 0x002e0c5c and dispatches it at 0x002e0c60-0x002e0c7c; this assignment writes that same byte, matching the existing function-local VELDIN_ROBOT_STATE enum, not a Hero or control-mode domain. domain_6_value_6 -> VELDIN_ROBOT_STATE_WAIT_TO_RETURN_TO_FACE_TARGET: At 0x002e1348-0x002e138c the first collision probe, animation-derived qualification and hit-moby comparison lead to beam-slot release and store 6. Existing WAIT_TO_RETURN_TO_FACE_TARGET case faces target and waits on bit 2 before returning to state 3. The retail selector loads moby+0x20 at 0x002e0c5c and dispatches it at 0x002e0c60-0x002e0c7c; this assignment writes that same byte, matching the existing function-local VELDIN_ROBOT_STATE enum, not a Hero or control-mode domain. domain_7_value_6 -> VELDIN_ROBOT_STATE_WAIT_TO_RETURN_TO_FACE_TARGET: At 0x002e13bc-0x002e1408 the second collision probe clips endpoint; qualified hit-moby comparison releases the beam slot and stores 6. Existing WAIT_TO_RETURN_TO_FACE_TARGET handler at 0x002e1494-0x002e151c waits before returning to FACE_TARGET. The retail selector loads moby+0x20 at 0x002e0c5c and dispatches it at 0x002e0c60-0x002e0c7c; this assignment writes that same byte, matching the existing function-local VELDIN_ROBOT_STATE enum, not a Hero or control-mode domain. domain_8_value_6 -> VELDIN_ROBOT_STATE_WAIT_TO_RETURN_TO_FACE_TARGET: At 0x002e1438-0x002e1478 the bit-2-gated timer increments and its previous value is compared with beam_hit_frames; equality releases beam slot and stores 6. Existing WAIT_TO_RETURN_TO_FACE_TARGET case waits before returning to state 3. The retail selector loads moby+0x20 at 0x002e0c5c and dispatches it at 0x002e0c60-0x002e0c7c; this assignment writes that same byte, matching the existing function-local VELDIN_ROBOT_STATE enum, not a Hero or control-mode domain. domain_9_value_3 -> VELDIN_ROBOT_STATE_FACE_TARGET: In WAIT_TO_RETURN_TO_FACE_TARGET, 0x002e1494-0x002e14e8 approaches target-relative heading and 0x002e14ec-0x002e151c tests bit 2 then stores 3. This reenters the existing FACE_TARGET handler at 0x002e0fbc. The retail selector loads moby+0x20 at 0x002e0c5c and dispatches it at 0x002e0c60-0x002e0c7c; this assignment writes that same byte, matching the existing function-local VELDIN_ROBOT_STATE enum, not a Hero or control-mode domain. --- src/overlays/l00/mobys/veldin_robot_enemy.c | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l00/mobys/veldin_robot_enemy.c b/src/overlays/l00/mobys/veldin_robot_enemy.c index 5e4391bc4f..3f17e53224 100644 --- a/src/overlays/l00/mobys/veldin_robot_enemy.c +++ b/src/overlays/l00/mobys/veldin_robot_enemy.c @@ -223,10 +223,10 @@ void veldin_robot_enemy_update(ElectroidMoby *moby) { return; } qcopy(&moby->pos, &toad_paths[vars->pathIdx]->pts[0]); - moby->state = 1; + moby->state = VELDIN_ROBOT_STATE_WAIT_TO_FOLLOW_PATH; ELECTROID_ANIM(moby, 1, 5); } else { - moby->state = 3; + moby->state = VELDIN_ROBOT_STATE_FACE_TARGET; ELECTROID_ANIM(moby, 1, 5); } break; @@ -239,7 +239,7 @@ void veldin_robot_enemy_update(ElectroidMoby *moby) { } } if (vars->unk114 != 2) { - moby->state = 2; + moby->state = VELDIN_ROBOT_STATE_FOLLOW_PATH; ELECTROID_ANIM(moby, 9, scale_game_frames_s32(10)); } break; @@ -261,7 +261,7 @@ void veldin_robot_enemy_update(ElectroidMoby *moby) { if (fast_vec_length(&dir) < vars->speed + vars->speed) { vars->pathPt++; if (vars->pathPt == path->count) { - moby->state = 3; + moby->state = VELDIN_ROBOT_STATE_FACE_TARGET; ELECTROID_ANIM(moby, 1, scale_game_frames_s32(10)); } } @@ -280,7 +280,7 @@ void veldin_robot_enemy_update(ElectroidMoby *moby) { ELECTROID_ANIM(moby, random_integer_below(2) + 1, scale_game_frames_s32(20)); } if (vars->unk114 != 2 && register_beam_slot(moby, 0, 0) != 0) { - moby->state = 4; + moby->state = VELDIN_ROBOT_STATE_WAIT_TO_START_COLLISION_PROBES; ELECTROID_ANIM(moby, 5, scale_game_frames_s32(10)); } break; @@ -292,7 +292,7 @@ void veldin_robot_enemy_update(ElectroidMoby *moby) { 12.566371f); if (moby->unk70 & 2) { vars->timer = 0; - moby->state = 5; + moby->state = VELDIN_ROBOT_STATE_PROCESS_COLLISION_PROBES; ELECTROID_ANIM(moby, 6, scale_game_frames_s32(10)); } break; @@ -335,14 +335,14 @@ void veldin_robot_enemy_update(ElectroidMoby *moby) { if (collision_line(&mtx[3], &probe, 0, moby, &query) != 0 && hit != 0 && coll_hit.moby == (*(s32 *)&D_001413D0_lui)) { release_beam_slot_by_id(moby); - moby->state = 6; + moby->state = VELDIN_ROBOT_STATE_WAIT_TO_RETURN_TO_FACE_TARGET; ELECTROID_ANIM(moby, 7, scale_game_frames_s32(10)); } if (collision_line(&mtx[3], &dir, 0, moby, &query) != 0) { qcopy(&dir, &coll_hit.point); if (hit != 0 && coll_hit.moby == (*(s32 *)&D_001413D0_lui)) { release_beam_slot_by_id(moby); - moby->state = 6; + moby->state = VELDIN_ROBOT_STATE_WAIT_TO_RETURN_TO_FACE_TARGET; ELECTROID_ANIM(moby, 7, scale_game_frames_s32(10)); } } @@ -350,7 +350,7 @@ void veldin_robot_enemy_update(ElectroidMoby *moby) { if (moby->unk70 & 2) { if (vars->timer++ == veldin_robot_beam_hit_frames) { release_beam_slot_by_id(moby); - moby->state = 6; + moby->state = VELDIN_ROBOT_STATE_WAIT_TO_RETURN_TO_FACE_TARGET; ELECTROID_ANIM(moby, 12, scale_game_frames_s32(10)); } } @@ -363,13 +363,13 @@ void veldin_robot_enemy_update(ElectroidMoby *moby) { fast_arc_tan(target->pos.f[0] - moby->pos.f[0], target->pos.f[1] - moby->pos.f[1]), 12.566371f); if (moby->unk70 & 2) { - moby->state = 3; + moby->state = VELDIN_ROBOT_STATE_FACE_TARGET; ELECTROID_ANIM(moby, 1, scale_game_frames_s32(10)); } break; case VELDIN_ROBOT_STATE_DAMAGE_KNOCKBACK: if (step_moby_motion(moby, vars->unk70) & 0x140) { - moby->state = 3; + moby->state = VELDIN_ROBOT_STATE_FACE_TARGET; ELECTROID_ANIM(moby, 1, scale_game_frames_s32(10)); } break; From 90793ba3e6fccf65b507c88242ce090c1a7f39eb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:13:18 +0000 Subject: [PATCH 1081/1502] decomp: clarify names in skids_agent_update domain_0_value_1 -> SKIDS_AGENT_IDLE_AND_TALK: Retail 0x002e0df8 reads owner s2+0x20 as the switch selector. Initialization loads 1 at 0x002e0e30 and stores it to that same byte at 0x002e0e48, entering the existing SKIDS_AGENT_IDLE_AND_TALK case that updates dialogue and idle animation. domain_1_value_2 -> SKIDS_AGENT_CONVERSATION_ACTIVE: After update_npc_dialogue succeeds and begin_dialogue_camera_transition runs, retail 0x002e0ef8 loads 2 and 0x002e0f00 stores it to s2+0x20, the moby state switch selector. This enters the existing SKIDS_AGENT_CONVERSATION_ACTIVE case at 0x002e112c. domain_3_value_1 -> SKIDS_AGENT_IDLE_AND_TALK: Retail 0x002e1130-0x002e1140 tests the separate level mode, then loads 1 and writes s2+0x20 when conversation mode ends. That byte is the same moby->state selector loaded at 0x002e0df8, returning to the existing SKIDS_AGENT_IDLE_AND_TALK case. domain_4_value_5 -> SKIDS_AGENT_END_CONVERSATION: Retail 0x002e1184-0x002e11d0 handles dialogue outcome pvars+4 == 2, hides owner and prop, starts the disc stream, then stores 5 to s2+0x20. The same state selector dispatches to existing SKIDS_AGENT_END_CONVERSATION, whose 0x002e1254-0x002e126c grants the item, saves and deletes the owner. domain_5_value_4 -> SKIDS_AGENT_FADE_TO_ZERO_AND_DELETE: Retail 0x002e13dc-0x002e13f8 tests fade pvars+0x17c == 1 after interpolation completion and stores 4 into s2+0x20. This is the same state selector as 0x002e0df8; existing SKIDS_AGENT_FADE_TO_ZERO_AND_DELETE at 0x002e1408 approaches fade to zero and removes prop and owner. --- src/overlays/l02/mobys/skids_agent.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l02/mobys/skids_agent.c b/src/overlays/l02/mobys/skids_agent.c index b5fe3e7d9a..3676db3c50 100644 --- a/src/overlays/l02/mobys/skids_agent.c +++ b/src/overlays/l02/mobys/skids_agent.c @@ -121,7 +121,7 @@ void skids_agent_update(struct Moby *moby) { goto kill; } skids_agent_vars->unk20 = skids_agent_dialogue_data; - moby->state = 1; + moby->state = SKIDS_AGENT_IDLE_AND_TALK; initialize_npc_dialogue(moby, skids_agent_vars); initialize_moby_grounding(moby); prop = create_moby(0x38); @@ -140,7 +140,7 @@ void skids_agent_update(struct Moby *moby) { } if (update_npc_dialogue(moby, skids_agent_vars) != 0) { begin_dialogue_camera_transition(moby, 2.2f); - moby->state = 2; + moby->state = SKIDS_AGENT_CONVERSATION_ACTIVE; } else if (item_available[0x5] == 0 && vector_distance_xy(&moby->pos, &hero.motion.pos) < 3.0f) { if (D_00141968[14].count != 0) { @@ -177,7 +177,7 @@ void skids_agent_update(struct Moby *moby) { break; case SKIDS_AGENT_CONVERSATION_ACTIVE: if (level_game_mode != 2) { - moby->state = 1; + moby->state = SKIDS_AGENT_IDLE_AND_TALK; if (skids_agent_vars->unk4 == 0) { jet_clear_persistent(moby->mission); if (skids_agent_vars->unk150 != -1) { @@ -194,7 +194,7 @@ void skids_agent_update(struct Moby *moby) { skids_agent_vars->unk178->visible = 0; } start_indexed_disc_stream(2); - moby->state = 5; + moby->state = SKIDS_AGENT_END_CONVERSATION; } } else if (talk_camera.placed == 0) { fast_vec_normalize(&talk_camera.pos, &moby->rot_row0, 2.5f); @@ -239,7 +239,7 @@ void skids_agent_update(struct Moby *moby) { } else { approach_value(&skids_agent_vars->unk17C, 1.0f, 0.1f); if (skids_agent_vars->unk17C == 1.0f) { - moby->state = 4; + moby->state = SKIDS_AGENT_FADE_TO_ZERO_AND_DELETE; jet_end_mount(0); } } From ac82e78a8af6e0cb70016996ef754d593282a8fb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:15:06 +0000 Subject: [PATCH 1082/1502] decomp: clarify names in water_update domain_0_value_7 -> WATER_RISE_COMPLETE: Retail 0030cde0-0030cdfc tests the mission completion byte and stores 7 to moby+0x20 while selecting z=44. The same moby+0x20 is loaded for dispatch at 0030cab8, whose existing source case is WATER_RISE_COMPLETE; timed rise also broadcasts 7 at z>=44. domain_1_value_3 -> WATER_WAIT_FOR_RISE_TRIGGER: Retail 0030cde8 supplies 3 to the store at 0030ce08 into moby+0x20 and initializes the timer at 0030ce0c. Dispatch reads that exact field at 0030cab8; its existing case WATER_WAIT_FOR_RISE_TRIGGER checks proximity and supporting moby before entering timed rise at 0030d198. domain_2_value_1 -> WATER_MOVE_TO_RAISED_HEIGHT: Retail 0030ce58-0030ce78 tests starts_raised at pvars+8, stores 1 to moby+0x20 at 0030ce70, and loads raised_z from pvars+0. The same dispatch field's existing WATER_MOVE_TO_RAISED_HEIGHT case passes pvars+0 to the movement helper at 0030d038-0030d040. domain_3_value_2 -> WATER_MOVE_TO_LOWERED_HEIGHT: The starts_raised false initialization path selects 2 at 0030ce7c and stores it to moby+0x20 at 0030ce80, then loads lowered_z from pvars+4 at 0030ce84. This is the same selector as existing WATER_MOVE_TO_LOWERED_HEIGHT, which targets pvars+4 at 0030cf3c-0030cf44. domain_4_value_2 -> WATER_MOVE_TO_LOWERED_HEIGHT: The nonnegative pvars+0x10 initialization path branches from 0030ce44 with 2 supplied at 0030ce48 to the moby+0x20 store at 0030ce80 and sets z from pvars+4. That dispatch selector already names state 2 WATER_MOVE_TO_LOWERED_HEIGHT, targeting this lowered_z field in its movement branch. domain_5_value_1 -> WATER_MOVE_TO_RAISED_HEIGHT: Retail 0030cef4-0030cf0c recognizes completed mission byte 0xff, stores 1 to moby+0x20 at 0030cf04, and copies pvars+0 raised_z to moby z. The dispatch field at 0030cab8 uses existing WATER_MOVE_TO_RAISED_HEIGHT for 1, whose movement target is also pvars+0. domain_6_value_8 -> WATER_TIMED_RISE: Retail 0030d170-0030d198 checks a grounded hero supported by class 0x33e and writes 8 to moby+0x20; 0030d1a0-0030d1ac resets rise_step and initializes its timer. This exact dispatch field's existing WATER_TIMED_RISE case at 0030d2c8-0030d338 advances staged timers and raises surface z. domain_7_value_3 -> WATER_WAIT_FOR_RISE_TRIGGER: Retail 0030d478 loads moby+0x20, the same state field dispatched at 0030cab8; subtracting 3 at 0030d47c and testing unsigned <5 at 0030d480 implements the source range 3..7. Its lower endpoint is therefore the existing same-selector member WATER_WAIT_FOR_RISE_TRIGGER, without assigning meanings to intermediate states. domain_8_value_7 -> WATER_RISE_COMPLETE: Retail 0030d478-0030d484 bounds the dispatch field moby+0x20 to the inclusive range 3..7 before height visibility checks. Existing case WATER_RISE_COMPLETE names that exact selector's upper endpoint 7; completion stores at 0030cdfc and broadcast at 0030d42c confirm the domain, without naming states 4..6. --- src/overlays/l05/mobys/water.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l05/mobys/water.c b/src/overlays/l05/mobys/water.c index d035c458b4..9bedef440e 100644 --- a/src/overlays/l05/mobys/water.c +++ b/src/overlays/l05/mobys/water.c @@ -192,10 +192,10 @@ void water_update(struct Moby *moby) { } } if (visited52[moby->mission + (current_level_index << 4)] == 0xFF) { - moby->state = 7; + moby->state = WATER_RISE_COMPLETE; moby->pos.z = 44.0f; } else { - moby->state = 3; + moby->state = WATER_WAIT_FOR_RISE_TRIGGER; water_vars->timer = scale_game_frames(0x3C); if (moby->pos.z < water_vars->lowered_z) { l05_water_grids[water_vars->record_index].visible_subtiles = 0; @@ -207,14 +207,14 @@ void water_update(struct Moby *moby) { water_vars->lowered_z = z; water_vars->raised_z = z + 4.5f; if (water_vars->starts_raised != 0) { - moby->state = 1; + moby->state = WATER_MOVE_TO_RAISED_HEIGHT; moby->pos.z = water_vars->raised_z; } else { - moby->state = 2; + moby->state = WATER_MOVE_TO_LOWERED_HEIGHT; moby->pos.z = water_vars->lowered_z; } } else { - moby->state = 2; + moby->state = WATER_MOVE_TO_LOWERED_HEIGHT; moby->pos.z = water_vars->lowered_z; } } @@ -228,7 +228,7 @@ void water_update(struct Moby *moby) { set_moby_list_state(moby->group, 1); } else if (water_vars->f10 >= 0) { if (visited52[moby->mission + (current_level_index << 4)] == 0xFF) { - moby->state = 1; + moby->state = WATER_MOVE_TO_RAISED_HEIGHT; moby->pos.z = water_vars->raised_z; } } @@ -291,7 +291,7 @@ void water_update(struct Moby *moby) { if (h->ground_moby != 0 && h->air_frames.s == 0 && h->ground_moby->oclass == 0x33E) { water_vars->f1C = 0; - moby->state = 8; + moby->state = WATER_TIMED_RISE; rise_step = 0; water_vars->timer = scale_game_frames(rise_frames[0]); } @@ -361,7 +361,7 @@ void water_update(struct Moby *moby) { e->z = moby->pos.z; grid_in_view = 0.0f; if (check_scaled_vector_bsphere((char *)moby, 48.0f) != -1 && - (!(moby->state >= 3 && moby->state <= 7) || + (!(moby->state >= WATER_WAIT_FOR_RISE_TRIGGER && moby->state <= WATER_RISE_COMPLETE) || (moby->pos.z > water_vars->lowered_z && moby->pos.z < water_vars->raised_z))) { grid_in_view = 1.0f; } From 97acfb6712b3474bd1f2dd08ec1dce335400effe Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:15:06 +0000 Subject: [PATCH 1083/1502] decomp: clarify names in platform_update domain_0_value_0 -> PLATFORM_INITIALIZE: Retail 0x002e3f24-0x002e3f28 reads moby state at s1+0x20 and skips the dependency gate when zero; the same byte selects the outer switch at 0x002e3f8c-0x002e3fb0. Source case PLATFORM_INITIALIZE configures kind-dependent movement, proving this comparison uses that existing platform state member. domain_1_value_0 -> PLATFORM_INITIALIZE: Retail 0x002e3f54-0x002e3f58 rereads the same moby state byte at s1+0x20 and bypasses the group dependency gate when zero. That byte is the outer platform state selector, whose existing zero member PLATFORM_INITIALIZE initializes paths and collision at 0x002e3fb8-0x002e4218. domain_2_value_7 -> PLATFORM_FOLLOW_WAYPOINTS: Retail 0x002e4074-0x002e407c writes 7 to moby+0x20 after initializing path, index and direction. The same state's handler at 0x002e4228-0x002e4340 selects a modulo-indexed waypoint and steers toward it, matching existing PLATFORM_FOLLOW_WAYPOINTS in this exact selector domain. domain_3_value_2 -> PLATFORM_OSCILLATE_BETWEEN_PATH_ENDPOINTS: Retail 0x002e4118-0x002e4120 writes 2 to moby+0x20 after path and random phase initialization. State 2 at 0x002e434c-0x002e44e4 computes a folded sine factor and interpolates path nodes 0 and 1, proving reuse of existing PLATFORM_OSCILLATE_BETWEEN_PATH_ENDPOINTS. domain_4_value_4 -> PLATFORM_OSCILLATE_BETWEEN_PATH_ENDPOINTS_FIXED_PITCH: Retail 0x002e4158 sets pitch to -pi/2 and 0x002e41cc-0x002e41d4 writes 4 to the same moby state selector. State 4 interpolates path endpoints at 0x002e44e8-0x002e4624 and fixes pitch again at 0x002e4638, matching the existing platform fixed-pitch oscillation member. domain_5_value_1 -> PLATFORM_DRAWING_AND_COLLISION_DISABLED: Retail kind-3 initialization at 0x002e41d8-0x002e41ec clears moby draw_dist at +0x32 and collision at +0x94 while writing 1 to moby state +0x20. The original decompilation and source corroborate these stores; the outer switch has no case-1 movement handler. This names the established drawing/collision-disabled platform condition without claiming external activation semantics. domain_6_value_9 -> PLATFORM_TRACK_REFERENCED_MOBY_HEIGHT: Retail 0x002e41f0-0x002e41fc writes 9 to moby state +0x20. Its handler at 0x002e4914-0x002e494c uses vars+0xF0 to index another moby and copy its position Z into a target retaining current X/Y, then steers with a height offset. This is existing PLATFORM_TRACK_REFERENCED_MOBY_HEIGHT. domain_7_value_2 -> PLATFORM_OSCILLATE_BETWEEN_PATH_ENDPOINTS: Retail 0x002e4640-0x002e4670 decrements the wait timer, toggles direction, and writes 2 to moby state +0x20 on expiry. This is the same selector as the established state-2 folded-sine endpoint interpolation at 0x002e434c-0x002e44e4, so the transition reuses PLATFORM_OSCILLATE_BETWEEN_PATH_ENDPOINTS. domain_8_value_4 -> PLATFORM_OSCILLATE_BETWEEN_PATH_ENDPOINTS_FIXED_PITCH: Retail 0x002e46e4-0x002e470c decrements the fixed-pitch wait timer, toggles direction and writes 4 to moby state +0x20. Its destination is the established state-4 endpoint interpolation with pitch fixed to -pi/2 at 0x002e44e8-0x002e4638, proving reuse of the existing fixed-pitch oscillation member. domain_9_value_0 -> PLATFORM_INITIALIZE: Retail 0x002e48b8-0x002e48e4 checks the falling platform's non-null path and XY distance to its first node, then writes zero to moby state +0x20 on arrival. The same state byte dispatches to PLATFORM_INITIALIZE, which rebuilds kind-dependent path, collision and movement configuration at 0x002e3fb8-0x002e4218. --- src/overlays/l12/mobys/platform.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/overlays/l12/mobys/platform.c b/src/overlays/l12/mobys/platform.c index 60e3b06794..436bb60782 100644 --- a/src/overlays/l12/mobys/platform.c +++ b/src/overlays/l12/mobys/platform.c @@ -284,6 +284,9 @@ void platform_update(Moby *moby) { PLATFORM_KIND_DISABLE_DRAWING_AND_COLLISION = 3, PLATFORM_KIND_TRACK_REFERENCED_MOBY_HEIGHT = 4 }; + enum { + PLATFORM_DRAWING_AND_COLLISION_DISABLED = 1 + }; float oldPos[4]; float oldRot[4]; float delta[4]; @@ -295,12 +298,12 @@ void platform_update(Moby *moby) { platform_vars = (*(Data_2E51E8 **)&moby->pvars); qcopy(oldPos, (*(float(*)[4]) & moby->pos)); qcopy(oldRot, (*(float(*)[4]) & moby->rot)); - if (moby->state != 0 && platform_vars->fFC != -1 && + if (moby->state != PLATFORM_INITIALIZE && platform_vars->fFC != -1 && (signed char)(*(Moby **)&D_L12_0015FFD8_p)[platform_vars->fFC].state >= 0) { emit_platform_exhaust_effects((char *)moby); return; } - if (moby->state != 0 && platform_vars->fDC != -1 && + if (moby->state != PLATFORM_INITIALIZE && platform_vars->fDC != -1 && count_active_moby_group_members(platform_vars->fDC, -1) != 0) { emit_platform_exhaust_effects((char *)moby); return; @@ -319,7 +322,7 @@ void platform_update(Moby *moby) { platform_vars->fD4 = 6.0f; platform_vars->f3E |= 9; clear_u64_value(platform_vars->vel); - moby->state = 7; + moby->state = PLATFORM_FOLLOW_WAYPOINTS; break; case PLATFORM_KIND_OSCILLATE_BETWEEN_PATH_ENDPOINTS: (*(int *)&moby->collision) = (*(Class_2E51E8 **)&moby->pclass)->f10; @@ -333,7 +336,7 @@ void platform_update(Moby *moby) { platform_vars->fD8 = random_angle_radians(); platform_vars->f3E |= 9; clear_u64_value(platform_vars->vel); - moby->state = 2; + moby->state = PLATFORM_OSCILLATE_BETWEEN_PATH_ENDPOINTS; break; case PLATFORM_KIND_OSCILLATE_BETWEEN_PATH_ENDPOINTS_FIXED_PITCH: (*(int *)&moby->collision) = (*(Class_2E51E8 **)&moby->pclass)->f10; @@ -347,15 +350,15 @@ void platform_update(Moby *moby) { if (platform_vars->fD0 == 0.0f) platform_vars->fD0 = 8.0f; clear_u64_value(platform_vars->vel); - moby->state = 4; + moby->state = PLATFORM_OSCILLATE_BETWEEN_PATH_ENDPOINTS_FIXED_PITCH; break; case PLATFORM_KIND_DISABLE_DRAWING_AND_COLLISION: moby->draw_dist = 0; - moby->state = 1; + moby->state = PLATFORM_DRAWING_AND_COLLISION_DISABLED; (*(int *)&moby->collision) = 0; break; case PLATFORM_KIND_TRACK_REFERENCED_MOBY_HEIGHT: - moby->state = 9; + moby->state = PLATFORM_TRACK_REFERENCED_MOBY_HEIGHT; platform_vars->fD4 = 4.0f; platform_vars->fD0 = 4.0f; platform_vars->f3E &= 0xFFFE; @@ -443,7 +446,7 @@ void platform_update(Moby *moby) { } else { platform_vars->walk.dir = 1; } - moby->state = 2; + moby->state = PLATFORM_OSCILLATE_BETWEEN_PATH_ENDPOINTS; } if (is_hero_on_moby(moby)) { compute_platform_target_tilt((char *)moby, angles, 1); @@ -460,7 +463,7 @@ void platform_update(Moby *moby) { } else { platform_vars->walk.dir = 1; } - moby->state = 4; + moby->state = PLATFORM_OSCILLATE_BETWEEN_PATH_ENDPOINTS_FIXED_PITCH; } if (platform_vars->walk.dir == 2) { emit_platform_exhaust_effects((char *)moby); @@ -512,7 +515,7 @@ void platform_update(Moby *moby) { if (platform_vars->walk.path != 0 && vector_distance_xy((*(float(*)[4]) & moby->pos), &platform_vars->walk.path->nodes[0]) < 0.5f) { - moby->state = 0; + moby->state = PLATFORM_INITIALIZE; } if ((*(float(*)[4]) & moby->pos)[2] < 0.0f) { mark_moby_for_removal(moby); From 90d5d8c8a1fd723872976988bba82dd173a1b908 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:15:06 +0000 Subject: [PATCH 1084/1502] decomp: clarify names in update_blarg_space_fighter domain_0_value_1 -> FIGHTER_WAIT_TO_JOIN_PATH: Retail 0x002c452c loads 1 into s0 and 0x002c4584 stores it to input moby+0x20, the same selector dispatched at 0x002c449c-0x002c44bc. Initialization then enters the existing FIGHTER_WAIT_TO_JOIN_PATH case, whose linked-object gate and path join execute at 0x002c45a4-0x002c4680. domain_11_value_4 -> FIGHTER_WAIT_TO_REINITIALIZE: Retail 0x002c47c8-0x002c47cc stores 4 to input moby+0x20 when the linked boss is absent, removed or in state 1. The same moby->state switch already names 4 FIGHTER_WAIT_TO_REINITIALIZE; its 0x002c4e78-0x002c4ecc branch waits for the linked gate, restores health and returns to initialization. domain_13_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002c4df8-0x002c4e3c reads p->state at moby+0x20 on the linked moby resolved from fighter_data->fBC through the 0x100-byte table before accessing data+0x10E. This is the common Moby lifecycle field, not a vehicle/control substate: supplied mark_moby_for_removal writes 0xFE for moby >= moby_instance_end to that same state field. The check excludes or detects this removal sentinel before using the object. domain_14_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002c4df8-0x002c4e3c reads p->state at moby+0x20 on the linked moby resolved from fighter_data->fBC through the 0x100-byte table before accessing data+0x10E. This is the common Moby lifecycle field, not a vehicle/control substate: supplied mark_moby_for_removal writes 0xFD for moby < moby_instance_end to that same state field. The check excludes or detects this removal sentinel before using the object. domain_15_value_4 -> FIGHTER_WAIT_TO_REINITIALIZE: Retail 0x002c4e5c-0x002c4e60 stores 4 to input moby+0x20 after destruction effects, optional pickup and linked counter handling. The source's same moby->state selector names case 4 FIGHTER_WAIT_TO_REINITIALIZE, which waits for a live eligible link before health restoration and state reset. domain_16_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002c4e78-0x002c4ea4 reads p->state at moby+0x20 on the linked moby resolved from fighter_data->fBC through the 0x100-byte table before reinitialization. This is the common Moby lifecycle field, not a vehicle/control substate: supplied mark_moby_for_removal writes 0xFE for moby >= moby_instance_end to that same state field. The check excludes or detects this removal sentinel before using the object. domain_17_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002c4e78-0x002c4ea4 reads p->state at moby+0x20 on the linked moby resolved from fighter_data->fBC through the 0x100-byte table before reinitialization. This is the common Moby lifecycle field, not a vehicle/control substate: supplied mark_moby_for_removal writes 0xFD for moby < moby_instance_end to that same state field. The check excludes or detects this removal sentinel before using the object. domain_18_value_0 -> FIGHTER_INITIALIZE: Retail 0x002c4eb8-0x002c4ec8 restores fighter health from data+0x24, then 0x002c4ecc stores zero to input moby+0x20. This exact field is the switch selector at 0x002c449c, whose existing FIGHTER_INITIALIZE member 0 performs path, node-index, position and flag initialization. domain_1_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002c45b4-0x002c45d0 reads p->state at moby+0x20 on the linked moby resolved from fighter_data->fBC and the 0x100-byte moby table. This is the common Moby lifecycle field, not a vehicle/control substate: supplied mark_moby_for_removal writes 0xFE for moby >= moby_instance_end to that same state field. The check excludes or detects this removal sentinel before using the object. domain_2_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002c45b4-0x002c45d0 reads p->state at moby+0x20 on the linked moby resolved from fighter_data->fBC and the 0x100-byte moby table. This is the common Moby lifecycle field, not a vehicle/control substate: supplied mark_moby_for_removal writes 0xFD for moby < moby_instance_end to that same state field. The check excludes or detects this removal sentinel before using the object. domain_3_value_2 -> FIGHTER_FOLLOW_PATH_AND_ATTACK: Retail 0x002c4660 loads 2 and 0x002c4680 stores it to input moby+0x20 after path-point selection, position copying and activation flags. This is the same selector as the existing FIGHTER_FOLLOW_PATH_AND_ATTACK case, which calls damage processing at 0x002c468c and path following at 0x002c4840. domain_4_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002c4474 and 0x002c4694-0x002c46b0 reads veh->state at moby+0x20 on the hero vehicle moby loaded from hero+0x15F0, with instance data loaded at moby+0x78. This is the common Moby lifecycle field, not a vehicle/control substate: supplied mark_moby_for_removal writes 0xFE for moby >= moby_instance_end to that same state field. The check excludes or detects this removal sentinel before using the object. domain_5_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002c4474 and 0x002c4694-0x002c46b0 reads veh->state at moby+0x20 on the hero vehicle moby loaded from hero+0x15F0, with instance data loaded at moby+0x78. This is the common Moby lifecycle field, not a vehicle/control substate: supplied mark_moby_for_removal writes 0xFD for moby < moby_instance_end to that same state field. The check excludes or detects this removal sentinel before using the object. domain_6_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002c4758-0x002c479c reads p->state at moby+0x20 on the linked moby resolved through index times 0x100, then promoted to boss with data at +0x78. This is the common Moby lifecycle field, not a vehicle/control substate: supplied mark_moby_for_removal writes 0xFE for moby >= moby_instance_end to that same state field. The check excludes or detects this removal sentinel before using the object. domain_7_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002c4758-0x002c479c reads p->state at moby+0x20 on the linked moby resolved through index times 0x100, then promoted to boss with data at +0x78. This is the common Moby lifecycle field, not a vehicle/control substate: supplied mark_moby_for_removal writes 0xFD for moby < moby_instance_end to that same state field. The check excludes or detects this removal sentinel before using the object. domain_8_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002c4798-0x002c47bc reads boss->state at moby+0x20 on the same checked linked moby retained in s0 after loading its instance data. This is the common Moby lifecycle field, not a vehicle/control substate: supplied mark_moby_for_removal writes 0xFE for moby >= moby_instance_end to that same state field. The check excludes or detects this removal sentinel before using the object. domain_9_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002c4798-0x002c47bc reads boss->state at moby+0x20 on the same checked linked moby retained in s0 after loading its instance data. This is the common Moby lifecycle field, not a vehicle/control substate: supplied mark_moby_for_removal writes 0xFD for moby < moby_instance_end to that same state field. The check excludes or detects this removal sentinel before using the object. --- src/overlays/l13/mobys/blarg_space_fighter.c | 26 +++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/overlays/l13/mobys/blarg_space_fighter.c b/src/overlays/l13/mobys/blarg_space_fighter.c index 3b8214f1c4..ee35afd835 100644 --- a/src/overlays/l13/mobys/blarg_space_fighter.c +++ b/src/overlays/l13/mobys/blarg_space_fighter.c @@ -551,6 +551,10 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { FIGHTER_DESTRUCTION_SKIP_SPAWN_ALTERNATE = 8, FIGHTER_DESTRUCTION_SKIP_SPAWN_SECOND_ALTERNATE = 9 }; + enum { + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE + }; Data_2C56B0 *fighter_data; Moby_2C56B0 *veh; Veh *vehd = 0; @@ -589,7 +593,7 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { fighter_data->fA8 = scale_game_frames(0x14) + 5; moby->b30 = 0xFF; moby->h32 = 0xFF; - moby->state = 1; + moby->state = FIGHTER_WAIT_TO_JOIN_PATH; moby->bBC = 0; moby->flags = (moby->flags | 1) & 0xEFFF; moby->f94 = 0; @@ -600,7 +604,7 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { Moby_2C56B0 *p; if (fighter_data->fBC == -1 || (p = (Moby_2C56B0 *)(D_L13_0015FFD8 + (fighter_data->fBC << 8))) == 0 || - p->state == 0xFE || p->state == 0xFD || p->bBC == 4) { + p->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || p->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END || p->bBC == 4) { fast_vec_normalize(scratch_vector, D_L13_001670C0 + 0x84, 40.0f); fast_vec_sub(scratch_vector, D_L13_001670C0, scratch_vector); fighter_data->hB6 = fighter_data->hB4 = @@ -610,7 +614,7 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { moby->f94 = moby->cls->f10; moby->b31 = 1; moby->flags = (moby->flags & 0xFFFE) | 0x1000; - moby->state = 2; + moby->state = FIGHTER_FOLLOW_PATH_AND_ATTACK; } break; } @@ -621,7 +625,7 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { FUN_L13_002c37e0_c( (unsigned char *)moby, (unsigned char *)fighter_data, &fighter_data->f20); - if (veh != 0 && veh->state != 0xFE && veh->state != 0xFD) { + if (veh != 0 && veh->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && veh->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { vehd = veh->data; qcopy(hpos, &((Hero_2C56B0 *)(((char *)&D_0013F350)))->veh->pos); close = 0; @@ -644,13 +648,13 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { bossd = 0; if (fighter_data->fBC != -1) { Moby_2C56B0 *p = (Moby_2C56B0 *)(D_L13_0015FFD8 + (fighter_data->fBC << 8)); - if (p != 0 && p->state != 0xFE && p->state != 0xFD) { + if (p != 0 && p->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && p->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { boss = p; bossd = p->data; } } - if (boss == 0 || boss->state == 0xFE || boss->state == 0xFD || boss->state == 1) { - moby->state = 4; + if (boss == 0 || boss->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || boss->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END || boss->state == 1) { + moby->state = FIGHTER_WAIT_TO_REINITIALIZE; moby->f94 = 0; moby->flags = (moby->flags | 0x41) & 0xEFFF; return; @@ -808,7 +812,7 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { bossd = 0; if (fighter_data->fBC != -1) { Moby_2C56B0 *p = (Moby_2C56B0 *)(D_L13_0015FFD8 + (fighter_data->fBC << 8)); - if (p != 0 && p->state != 0xFE && p->state != 0xFD) { + if (p != 0 && p->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && p->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { boss = p; bossd = p->data; } @@ -818,7 +822,7 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { bossd->b10E--; } } - moby->state = 4; + moby->state = FIGHTER_WAIT_TO_REINITIALIZE; moby->f94 = 0; moby->flags = (moby->flags | 0x41) & 0xEFFF; break; @@ -827,9 +831,9 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { Moby_2C56B0 *p; if (fighter_data->fBC != -1 && (p = (Moby_2C56B0 *)(D_L13_0015FFD8 + (fighter_data->fBC << 8))) != 0 && - p->state != 0xFE && p->state != 0xFD && p->bBC != 4) { + p->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && p->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && p->bBC != 4) { fighter_data->f20 = fighter_data->h24; - moby->state = 0; + moby->state = FIGHTER_INITIALIZE; } break; } From f90ccf9fbd5d5e7ddcca7e3eae5f05add3050866 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:15:07 +0000 Subject: [PATCH 1085/1502] decomp: clarify names in taxi_update domain_0_value_3 -> TAXI_STATE_BLEND_STOP_TO_PATH_START: Retail 0x002f0694-0x002f069c stores 3 to s4+0x20, the same taxi state byte selected at 0x002f05a4. After prepare_taxi_route, this enters the existing case that blends picked-stop pose to the path sample at zero (0x002f0a2c-0x002f0b08). domain_10_value_5 -> TAXI_STATE_BLEND_PATH_END_TO_STOP: Retail 0x002f0c50-0x002f0c6c calls advance_moby_path, and on completion clears progress/velocity and stores 5 to s4+0x20. The same taxi switch selects existing TAXI_STATE_BLEND_PATH_END_TO_STOP, blending sampled path end toward target stop. domain_11_value_1 -> TAXI_STATE_WAIT_AT_STOP: Retail 0x002f0d64-0x002f0d8c detects completed path-end-to-stop blend, clears progress/velocity, writes 1 to s4+0x20 and calls reset_selected_moby_to_current_placement. It returns to existing TAXI_STATE_WAIT_AT_STOP on that exact selector. domain_12_value_7 -> TAXI_STATE_BLEND_SAVED_POSE_TO_PATH_START: Retail 0x002f0e28-0x002f0e6c saves pose, initializes/selects the route, stores 7 to s4+0x20 and restores saved pose. Same taxi state selector; existing case TAXI_STATE_BLEND_SAVED_POSE_TO_PATH_START blends saved pose to the zero path sample. domain_14_value_1 -> TAXI_STATE_WAIT_AT_STOP: Retail 0x002f0ea4-0x002f0f0c exits the item-sentinel gate, restores class collision/visibility, clears flags bit 0 and writes 1 to s4+0x20. This is the taxi switch byte, so reuse existing TAXI_STATE_WAIT_AT_STOP rather than any Hero state member. domain_15_value_3 -> TAXI_STATE_BLEND_STOP_TO_PATH_START: Source compares moby->state >= 3; retail 0x002f0f18-0x002f0f24 loads s4+0x20 and performs unsigned (state-3)<2. The lower endpoint is the same taxi selector's existing TAXI_STATE_BLEND_STOP_TO_PATH_START, bounding the rider-lock/audio branch. domain_16_value_4 -> TAXI_STATE_FOLLOW_PATH: Source compares moby->state <= 4; retail 0x002f0f18-0x002f0f24 implements the inclusive taxi-state range 3..4 as unsigned (state-3)<2. The upper endpoint is the same selector's existing TAXI_STATE_FOLLOW_PATH, not Hero state 4 or an audio control value. domain_2_value_1 -> TAXI_STATE_WAIT_AT_STOP: Retail 0x002f071c-0x002f075c copies stop 0 cuboid position/rotation to the taxi and stores 1 to s4+0x20. This is the same selector as the existing TAXI_STATE_WAIT_AT_STOP case, not the picked/target stop-index domain. domain_3_value_3 -> TAXI_STATE_BLEND_STOP_TO_PATH_START: Retail 0x002f07bc-0x002f07d4 updates the picked stop, calls prepare_taxi_route, and stores 3 to s4+0x20. The same taxi state selector dispatches case TAXI_STATE_BLEND_STOP_TO_PATH_START, which blends picked-stop pose to path progress zero. domain_4_value_1 -> TAXI_STATE_WAIT_AT_STOP: Retail 0x002f0820-0x002f085c copies stop 1 cuboid position/rotation to the taxi and writes 1 to s4+0x20. This exact field drives the existing TAXI_STATE_WAIT_AT_STOP case; the stop-index stores at pvars+0xB4/+0xB6 are separate. domain_5_value_3 -> TAXI_STATE_BLEND_STOP_TO_PATH_START: Retail 0x002f08ac-0x002f08bc selects picked stop 0, calls prepare_taxi_route, and stores 3 to s4+0x20. Same taxi state byte as switch load 0x002f05a4; existing case 3 blends picked-stop pose to path start at 0x002f0a2c-0x002f0b08. domain_6_value_1 -> TAXI_STATE_WAIT_AT_STOP: Retail 0x002f0908-0x002f0954 copies stop 2 cuboid pose to moby position/rotation and stores 1 to s4+0x20. This exact taxi state field is selected by the switch, where canonical member TAXI_STATE_WAIT_AT_STOP is already defined as 1. domain_7_value_3 -> TAXI_STATE_BLEND_STOP_TO_PATH_START: Retail 0x002f09a0-0x002f09b4 selects picked stop 2, prepares the route, then stores 3 to s4+0x20. The same taxi-state selector dispatches the existing picked-stop-to-path-start positional/angular blend in case 3. domain_8_value_4 -> TAXI_STATE_FOLLOW_PATH: Retail 0x002f0ae4-0x002f0b08 tests completed stop-to-path-start blend, clears progress/velocity and stores 4 to s4+0x20. Same byte as the taxi switch; existing TAXI_STATE_FOLLOW_PATH case calls advance_moby_path at 0x002f0c50. domain_9_value_4 -> TAXI_STATE_FOLLOW_PATH: Retail 0x002f0bec-0x002f0c10 completes the saved-pose-to-path-start blend, clears progress/velocity, and stores 4 to the taxi state byte s4+0x20. This dispatches existing TAXI_STATE_FOLLOW_PATH, whose handler advances the selected path. --- src/overlays/l14/mobys/taxi.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/overlays/l14/mobys/taxi.c b/src/overlays/l14/mobys/taxi.c index 9e972316f5..41d89ae43d 100644 --- a/src/overlays/l14/mobys/taxi.c +++ b/src/overlays/l14/mobys/taxi.c @@ -125,7 +125,7 @@ void taxi_update(struct Moby *moby) { request_taxi_stop_prompt(moby); if ((pad_pressed_words[0] & button) && D_L14_0015F594 == 4) { struct Moby *m; - moby->state = 3; + moby->state = TAXI_STATE_BLEND_STOP_TO_PATH_START; m = find_group_moby_by_tag(moby, taxi_vars->target); if (m != 0) { m->state = 2; @@ -144,7 +144,7 @@ void taxi_update(struct Moby *moby) { taxi_vars->picked = 0; qcopy_nc(&moby->pos, &l14_cuboids[taxi_vars->points[taxi_vars->picked]].pos); qcopy_nc(&moby->rot, &l14_cuboids[taxi_vars->points[taxi_vars->picked]].rot); - moby->state = 1; + moby->state = TAXI_STATE_WAIT_AT_STOP; qcopy_nc(taxi_vars->pos, &l14_cuboids[taxi_vars->points[taxi_vars->picked]].pos); qcopy_nc(taxi_vars->rot, @@ -156,7 +156,7 @@ void taxi_update(struct Moby *moby) { taxi_vars->picked = 1; } prepare_taxi_route(moby); - moby->state = 3; + moby->state = TAXI_STATE_BLEND_STOP_TO_PATH_START; } } if (taxi_vars->clip[1] >= 0 && taxi_vars->picked != 1 && @@ -166,7 +166,7 @@ void taxi_update(struct Moby *moby) { taxi_vars->picked = 1; qcopy_nc(&moby->pos, &l14_cuboids[taxi_vars->points[taxi_vars->picked]].pos); qcopy_nc(&moby->rot, &l14_cuboids[taxi_vars->points[taxi_vars->picked]].rot); - moby->state = 1; + moby->state = TAXI_STATE_WAIT_AT_STOP; qcopy_nc(taxi_vars->pos, &l14_cuboids[taxi_vars->points[taxi_vars->picked]].pos); qcopy_nc(taxi_vars->rot, @@ -174,7 +174,7 @@ void taxi_update(struct Moby *moby) { } else { taxi_vars->picked = 0; prepare_taxi_route(moby); - moby->state = 3; + moby->state = TAXI_STATE_BLEND_STOP_TO_PATH_START; } } if (taxi_vars->clip[2] >= 0 && taxi_vars->picked < 2 && @@ -184,7 +184,7 @@ void taxi_update(struct Moby *moby) { taxi_vars->picked = 2; qcopy_nc(&moby->pos, &l14_cuboids[taxi_vars->points[taxi_vars->picked]].pos); qcopy_nc(&moby->rot, &l14_cuboids[taxi_vars->points[taxi_vars->picked]].rot); - moby->state = 1; + moby->state = TAXI_STATE_WAIT_AT_STOP; qcopy_nc(taxi_vars->pos, &l14_cuboids[taxi_vars->points[taxi_vars->picked]].pos); qcopy_nc(taxi_vars->rot, @@ -192,7 +192,7 @@ void taxi_update(struct Moby *moby) { } else { taxi_vars->picked = 2; prepare_taxi_route(moby); - moby->state = 3; + moby->state = TAXI_STATE_BLEND_STOP_TO_PATH_START; } } } @@ -225,7 +225,7 @@ void taxi_update(struct Moby *moby) { if (1.0f <= taxi_vars->t) { taxi_vars->t = 0.0f; taxi_vars->tv = 0.0f; - moby->state = 4; + moby->state = TAXI_STATE_FOLLOW_PATH; } break; } @@ -254,7 +254,7 @@ void taxi_update(struct Moby *moby) { if (1.0f <= taxi_vars->t) { taxi_vars->t = 0.0f; taxi_vars->tv = 0.0f; - moby->state = 4; + moby->state = TAXI_STATE_FOLLOW_PATH; } break; } @@ -266,7 +266,7 @@ void taxi_update(struct Moby *moby) { if (advance_moby_path((char *)moby)) { taxi_vars->t = 0.0f; taxi_vars->tv = 0.0f; - moby->state = 5; + moby->state = TAXI_STATE_BLEND_PATH_END_TO_STOP; } break; } @@ -296,7 +296,7 @@ void taxi_update(struct Moby *moby) { if (1.0f <= taxi_vars->t) { taxi_vars->t = 0.0f; taxi_vars->tv = 0.0f; - moby->state = 1; + moby->state = TAXI_STATE_WAIT_AT_STOP; reset_selected_moby_to_current_placement(moby); } g = &hero; @@ -314,7 +314,7 @@ void taxi_update(struct Moby *moby) { initialize_taxi_stop_from_position(moby); taxi_vars->picked = taxi_vars->target; prepare_taxi_route(moby); - moby->state = 7; + moby->state = TAXI_STATE_BLEND_SAVED_POSE_TO_PATH_START; qcopy(taxi_vars->pos, taxi_vars->save_pos); qcopy(taxi_vars->rot, taxi_vars->save_rot); { @@ -340,13 +340,13 @@ void taxi_update(struct Moby *moby) { moby->visible = 1; moby->collision = class_collision; moby->flags = bits & 0xFFFE; - moby->state = 1; + moby->state = TAXI_STATE_WAIT_AT_STOP; } break; } } apply_moby_position_and_rotation_wobble((char *)moby); - if (moby->state >= 3 && moby->state <= 4) { + if (moby->state >= TAXI_STATE_BLEND_STOP_TO_PATH_START && moby->state <= TAXI_STATE_FOLLOW_PATH) { struct Hero *g = &hero; if (g->ground_moby == moby && g->air_frames.s == 0) { g->jump_lock_timer = 2; From 50aa304e66950d8397455cdd607bcd5bcca96b69 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:15:07 +0000 Subject: [PATCH 1086/1502] decomp: clarify names in update_help_hints domain_0_value_1 -> TUTORIAL_TRIGGER_STATE_UPDATE_HINTS_AND_STATS: Authoritative help_hints.c snapshot SHA-256 01c66c3da666b4349204d5f6e2d9f5ffff6d254f5fafb96e60bb7684fc48ae9a defines this local enum member as 1 and uses it for switch(moby->state). Retail 0x002e444c loads state from +0x20(s0); 0x002e4458-0x002e445c compares that byte with 1 and enters 0x002e4488. Initialization 0x002e4470-0x002e4474 stores 1 into the identical +0x20(s0) byte, alongside update_dist=0xFF and pvars+0x14=-1 at 0x002e447c/0x002e4484. Original Ghidra confirms that state 1 proceeds through volume checks, help requests and usage updates; retail 0x002e4518-0x002e45a0 updates usage count/time/mask and 0x002e45d4 requests help. Thus the assignment enters the already named local tutorial-trigger update state, independent of equal-valued hero enums. --- src/overlays/l04/mobys/help_hints.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l04/mobys/help_hints.c b/src/overlays/l04/mobys/help_hints.c index a34d313ad0..32a6e8b1bd 100644 --- a/src/overlays/l04/mobys/help_hints.c +++ b/src/overlays/l04/mobys/help_hints.c @@ -78,7 +78,7 @@ void help_hints_update(Moby *moby) { switch (moby->state) { case TUTORIAL_TRIGGER_STATE_INITIALIZE: moby->update_dist = 0xFF; - moby->state = 1; + moby->state = TUTORIAL_TRIGGER_STATE_UPDATE_HINTS_AND_STATS; tutorial_trigger_vars->f14 = -1; break; case TUTORIAL_TRIGGER_STATE_UPDATE_HINTS_AND_STATS: From c67f4219ae1c7ae77ffe66f9c264330369d5ba58 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:15:07 +0000 Subject: [PATCH 1087/1502] decomp: clarify names in update_vendor_purchase domain_0_value_0 -> VENDOR_PURCHASE_INACTIVE: The source snapshots vendor_menu.purchase_state from offset +0x5C; retail 0x0029baa8..0x0029baac returns immediately for zero. open_vendor_menu already names this same field/value VENDOR_PURCHASE_INACTIVE, and 0x0029c608 clears it after either outcome. domain_10_value_0 -> VENDOR_MENU_MODE_EXISTING_VENDOR: This is the same vendor_menu.mode +0x40 selector: open_vendor_menu establishes zero as VENDOR_MENU_MODE_EXISTING_VENDOR and one on spawning a missing vendor. Retail 0x0029c4f8..0x0029c504 passes its nonzero comparison to build_vendor_menu_rows after the item grant, preserving that exact mode domain. domain_11_value_0 -> VENDOR_PURCHASE_INACTIVE: Retail 0x0029c608 writes zero to vendor_menu+0x5C after finalized purchase/cancellation. The load at 0x0029baa8 and zero branch at 0x0029baac make subsequent calls return immediately; open_vendor_menu already names zero for this exact field VENDOR_PURCHASE_INACTIVE. domain_1_value_1 -> VENDOR_PURCHASE_INITIALIZE: The caller update_vendor_menu assigns purchase_state=1 on purchase input. Retail dispatch 0x0029bab8 enters initialization: quantity=1, confirmation=0, creates class 0x471 moby and tests affordability/capacity, then stores state 2 at 0x0029bcfc..0x0029bd04. domain_2_value_2 -> VENDOR_PURCHASE_AWAIT_INPUT: Retail 0x0029bcfc..0x0029bd04 assigns 2 after display initialization and affordability checks. The matching state dispatch at 0x0029bd08 handles quantity buttons and waits for fresh cancel/confirm input before leaving this stage. domain_3_value_2 -> VENDOR_PURCHASE_AWAIT_INPUT: purchase_state is the +0x5C snapshot, not a moby state. Retail 0x0029bd08 dispatches value 2 into quantity adjustment 0x0029bd10..0x0029bfb4 and fresh cancel/confirm checks 0x0029bfb8..0x0029c060; absent a decision it advances the display animation and returns. domain_4_value_3 -> VENDOR_PURCHASE_WAIT_DECISION_ANIMATION: Cancel input at retail 0x0029bfb8..0x0029bfcc stores 3 to vendor_menu+0x5C at 0x0029bfd8..0x0029bfdc, clears confirmation and blends the display animation. State 3 then waits on animation flags before advancing to 4. domain_5_value_3 -> VENDOR_PURCHASE_WAIT_DECISION_ANIMATION: Confirm input at retail 0x0029c014..0x0029c028 stores 3 to the same purchase field at 0x0029c030..0x0029c034, sets confirmation and blends the display animation. Both decision paths converge on the state-3 animation wait. domain_6_value_3 -> VENDOR_PURCHASE_WAIT_DECISION_ANIMATION: Retail 0x0029c0b4 dispatches purchase state 3, advances menu_mobys[4] animation at 0x0029c0c0, tests +0x53 and +0x70 flags, then writes -1.0 to +0x58 and purchase state 4 at 0x0029c0f4..0x0029c0f8. No payment or input handling occurs in this stage. domain_7_value_4 -> VENDOR_PURCHASE_FINALIZE: Retail 0x0029c0e4..0x0029c0f8 stores 4 after the decision animation condition. Its consumer 0x0029c114..0x0029c608 waits on the display animation flag, gates purchases on confirmation, grants ammo/items and deducts payment or handles cancellation, then clears purchase_state. domain_8_value_4 -> VENDOR_PURCHASE_FINALIZE: Retail 0x0029c114 rejects purchase states other than 4. The state-4 branch advances animation, then performs confirmed ammo/item grant, payment, row/text refresh or cancellation and clears +0x5C at 0x0029c608, proving this is the purchase finalization stage. domain_9_value_0 -> VENDOR_MENU_MODE_EXISTING_VENDOR: The selector is vendor_menu.mode at +0x40, not purchase_state or hero mode. open_vendor_menu starts from cleared storage and sets this field to VENDOR_MENU_MODE_SPAWNED_VENDOR only when creating a missing vendor moby, and names zero VENDOR_MENU_MODE_EXISTING_VENDOR. Retail 0x0029c40c..0x0029c418 passes mode!=0 to build_vendor_menu_rows after ammo purchase. --- src/overlays/shared/vendor/vendor_menu.c | 32 +++++++++++++++--------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/overlays/shared/vendor/vendor_menu.c b/src/overlays/shared/vendor/vendor_menu.c index 597d6846d5..05af3aaf8d 100644 --- a/src/overlays/shared/vendor/vendor_menu.c +++ b/src/overlays/shared/vendor/vendor_menu.c @@ -902,15 +902,23 @@ extern void set_scrolling_status_message(int) __asm__("FUN_00237e90"); #define CUR_TB (D_L00_001C40B0[CUR_ITEM.item]) void update_vendor_purchase(void) { + enum { + VENDOR_PURCHASE_INACTIVE = 0, + VENDOR_MENU_MODE_EXISTING_VENDOR = 0, + VENDOR_PURCHASE_INITIALIZE = 1, + VENDOR_PURCHASE_AWAIT_INPUT = 2, + VENDOR_PURCHASE_WAIT_DECISION_ANIMATION = 3, + VENDOR_PURCHASE_FINALIZE = 4 + }; u128 lv; s32 purchase_state; s32 purchase_cost, k, last_row_index; purchase_state = vendor_menu.purchase_state; - if (purchase_state == 0) { + if (purchase_state == VENDOR_PURCHASE_INACTIVE) { return; } - if (purchase_state == 1) { + if (purchase_state == VENDOR_PURCHASE_INITIALIZE) { D_L00_00161E34 = 1; vendor_purchase_confirmed_gp = 0; init_moby_instance(&vendor_menu.menu_mobys[4], 0x471); @@ -945,10 +953,10 @@ void update_vendor_purchase(void) { allocate_voice_for_target_entry(2, 0, vendor_menu.vendor_moby); } } - vendor_menu.purchase_state = 2; + vendor_menu.purchase_state = VENDOR_PURCHASE_AWAIT_INPUT; return; } - if (purchase_state == 2) { + if (purchase_state == VENDOR_PURCHASE_AWAIT_INPUT) { if (vendor_ammo_quantity_adjustment_enabled_gp == 1) { if (controller_state.held_unmasked & 0x8000) { vendor_ammo_decrease_held_frames++; @@ -995,7 +1003,7 @@ void update_vendor_purchase(void) { } if (controller_state.pressed_unmasked & 0x10) { if (!(l00_vendor_previous_pressed_buttons & 0x10)) { - vendor_menu.purchase_state = 3; + vendor_menu.purchase_state = VENDOR_PURCHASE_WAIT_DECISION_ANIMATION; vendor_purchase_confirmed_gp = 0; blend_moby_animation(&vendor_menu.menu_mobys[4], 0, @@ -1007,7 +1015,7 @@ void update_vendor_purchase(void) { } if (controller_state.pressed_unmasked & 0x40) { if (!(l00_vendor_previous_pressed_buttons & 0x40)) { - vendor_menu.purchase_state = 3; + vendor_menu.purchase_state = VENDOR_PURCHASE_WAIT_DECISION_ANIMATION; vendor_purchase_confirmed_gp = 1; blend_moby_animation(&vendor_menu.menu_mobys[4], 0, @@ -1024,16 +1032,16 @@ void update_vendor_purchase(void) { update_entity(&vendor_menu.menu_mobys[4]); return; } - if (purchase_state == 3) { + if (purchase_state == VENDOR_PURCHASE_WAIT_DECISION_ANIMATION) { advance_moby_animation(&vendor_menu.menu_mobys[4]); if (!vendor_menu.menu_mobys[4].b53 && (vendor_menu.menu_mobys[4].b70 & 2)) { vendor_menu.menu_mobys[4].f58 = -1.0f; - vendor_menu.purchase_state = 4; + vendor_menu.purchase_state = VENDOR_PURCHASE_FINALIZE; } update_entity(&vendor_menu.menu_mobys[4]); return; } - if (purchase_state != 4) { + if (purchase_state != VENDOR_PURCHASE_FINALIZE) { return; } advance_moby_animation(&vendor_menu.menu_mobys[4]); @@ -1069,7 +1077,7 @@ void update_vendor_purchase(void) { ammo_bought_stats[CUR_ITEM.item] += k; handle_vendor_auxiliary_moby_event(3); D_0015ED98 = D_0015ED98 - purchase_cost; - build_vendor_menu_rows(vendor_menu.mode != 0); + build_vendor_menu_rows(vendor_menu.mode != VENDOR_MENU_MODE_EXISTING_VENDOR); set_scrolling_status_message(get_help_message_text(0x4F5F)); allocate_voice_for_target_entry(7, 0, vendor_menu.vendor_moby); } else { @@ -1089,7 +1097,7 @@ void update_vendor_purchase(void) { vendor_item_0x18_purchased[0] = 1; } D_0015ED98 = D_0015ED98 - purchase_cost; - build_vendor_menu_rows(vendor_menu.mode != 0); + build_vendor_menu_rows(vendor_menu.mode != VENDOR_MENU_MODE_EXISTING_VENDOR); if (vendor_menu.item_text != -1) { set_animation_parameter(vendor_menu.item_text, 0); } @@ -1122,7 +1130,7 @@ void update_vendor_purchase(void) { } else { allocate_voice_for_target_entry(0, 0, vendor_menu.vendor_moby); } - vendor_menu.purchase_state = 0; + vendor_menu.purchase_state = VENDOR_PURCHASE_INACTIVE; } update_entity(&vendor_menu.menu_mobys[4]); } From bd6d2d200b131b828a848e1bb4bd4afc0799c6c1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:15:07 +0000 Subject: [PATCH 1088/1502] decomp: clarify names in process_hero_item_action_input domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: SHA-bound src/overlays/shared/hero/process_hero_item_action_input.c (2bedf389512a0e676fde8d891d2a84df56cc9a14c1862b59238acc4d9d3d41c0) identifies the selector as hero.vehicle_mode. Retail 0x0022ee5c establishes hero base 0x0013f350; 0x0022ee60 loads its vehicle_mode byte at +0x20a4 and 0x0022ee64-0x0022ee70 permits zero and returns false for nonzero. Original Ghidra cRam001413f4 agrees. This is the vehicle-mode selector, distinct from current state at +0x2084 and control mode at +0x208c. Reuse HeroVehicleMode.HERO_VEHICLE_MODE_ON_FOOT=0 from supplied include/rnc/hero/hero_state.h domain. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: In the same SHA-bound source, the item-31 branch compares hero.vehicle_mode == 0 before can_select_hero_item_31. Retail 0x0022f428 forms the same hero base, 0x0022f42c loads byte +0x20a4 and 0x0022f430 branches away for nonzero; zero continues to the eligibility helper at 0x0022f438. Supplied helper source independently rejects hero_state->vehicle_mode before checking control_mode, confirming the same vehicle-mode field/domain. Original Ghidra explicitly warns that this repeated gate is unreachable after the initial gate. Reuse canonical HeroVehicleMode.HERO_VEHICLE_MODE_ON_FOOT=0; do not substitute equal-valued hero state or gravity constants. --- src/overlays/shared/hero/process_hero_item_action_input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/process_hero_item_action_input.c b/src/overlays/shared/hero/process_hero_item_action_input.c index 61fb2cb68f..657b26bb8a 100644 --- a/src/overlays/shared/hero/process_hero_item_action_input.c +++ b/src/overlays/shared/hero/process_hero_item_action_input.c @@ -415,7 +415,7 @@ s32 process_hero_item_action_input(void) { if (hero.item_use_locked != 0 && (hero.items[0].item_id != 8 || hero.unk308 != 1)) { return 0; } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { return 0; } if (hero.items[0].moby == NULL) { @@ -537,7 +537,7 @@ s32 process_hero_item_action_input(void) { break; case HERO_ITEM_CLASS_GATED_BUFFERED_ACTIVATE: - if (hero.vehicle_mode == 0 && can_select_hero_item_31() != 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT && can_select_hero_item_31() != 0) { if (pad_pressed_within(buttons, scale_game_frames(7), NULL) != 0 && D_00141660 == 0x1F && hero.items[0].moby->oclass == 0x1E3 && hero.vehicle_toggle_timer == 0) { From 0e999b8ede8575ab49d6babee4ab72293f7d14d5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:17:06 +0000 Subject: [PATCH 1089/1502] decomp: clarify names in update_resort_owner_state_transitions domain_0_value_3 -> RESORT_OWNER_WAIT_TO_FOLLOW_HERO: Retail 002d14d8-002d14e0 loads this NPC's state from s3+0x20 and tests the inclusive 3..5 range. The same field dispatches at 002d1574-002d1594; case 3 at 002d194c-002d1998 waits for hero distance >6 and a valid hero-directed path. Source ResortOwnerState canonically names 3 RESORT_OWNER_WAIT_TO_FOLLOW_HERO; this is not the separate path-leg or HeroStateId domain. domain_1_value_5 -> RESORT_OWNER_FOLLOW_DISTANT_HERO: Retail 002d14d8-002d14e0 implements state >=3 && state <=5 by subtracting 3 and testing <3 on NPC state +0x20. Its upper endpoint is the same state 5 dispatched to 002d1a20-002d1aac, which updates a hero-directed target and returns to follow state 4 below distance 4. Source ResortOwnerState names this exact selector member RESORT_OWNER_FOLLOW_DISTANT_HERO. domain_2_value_4 -> RESORT_OWNER_FOLLOW_HERO: Retail 002d1508-002d1510 subtracts 4 from the NPC state loaded at +0x20 and tests <3, proving the lower bound of the 4..6 range. The same selector's case 4 at 002d199c-002d1a14 follows a hero-directed path and changes to distant following above distance 8. Reuse source ResortOwnerState member RESORT_OWNER_FOLLOW_HERO. domain_3_value_6 -> RESORT_OWNER_MOVE_TO_PATH_POINT: Retail 002d1508-002d1510 tests NPC state minus 4 <3, giving inclusive upper endpoint 6. Same-selector case 6 at 002d1ab8-002d1ae4 indexes points[leg] from pvars+0xE0 and updates the path target; arrival is tested at 002d1ae8-002d1b08. This is the source ResortOwnerState member RESORT_OWNER_MOVE_TO_PATH_POINT. domain_4_value_3 -> RESORT_OWNER_WAIT_TO_FOLLOW_HERO: Retail 002d155c-002d1564 stores 3 at pvars+0x15C after accepting a jump landing target, then enters state 7 at 002d1568-002d1570. Jump completion loads that exact +0x15C into state-setter a1 at 002d1e50-002d1e68. Thus next_state shares the NPC state domain, whose case 3 at 002d194c-002d1998 and source enum name RESORT_OWNER_WAIT_TO_FOLLOW_HERO establish the deferred state. domain_5_value_8 -> RESORT_OWNER_MOVE_TO_GATE_TARGET: First-path-leg retail 002d1b4c-002d1bc8 builds target from gates[0] position and scaled gate basis rows; 002d1bcc-002d1bd8 stores 8 at pvars+0x15C before entering jump state 7. At 002d1e60-002d1e68 that field feeds the NPC state setter. Same-selector state 8 tests arrival at gate target at 002d1e74-002d1ea4; source ResortOwnerState names it RESORT_OWNER_MOVE_TO_GATE_TARGET. domain_6_value_8 -> RESORT_OWNER_MOVE_TO_GATE_TARGET: Second-path-leg retail 002d1bdc-002d1c5c builds the gate-relative target using gates[1], then 002d1c64-002d1c98 stores 8 to pvars+0x15C and enters jump state 7. Animation completion at 002d1e50-002d1e68 passes +0x15C to the same NPC state setter, proving the deferred-state domain. Source enum and state-8 target arrival branch 002d1e74-002d1ea4 establish RESORT_OWNER_MOVE_TO_GATE_TARGET. domain_7_value_4 -> RESORT_OWNER_FOLLOW_HERO: Gate-departure arrival retail 002d1f24-002d1f54 increments leg and selects the next cuboid target; 002d1f58-002d1f68 stores 4 to pvars+0x15C before entering jump state 7. The completion branch 002d1e60-002d1e68 loads that field as the NPC state setter argument. It therefore reuses ResortOwnerState 4, RESORT_OWNER_FOLLOW_HERO, corroborated by hero-directed case 4 at 002d199c-002d1a14. --- src/overlays/l11/mobys/resort_owner.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l11/mobys/resort_owner.c b/src/overlays/l11/mobys/resort_owner.c index 30e2371a9d..78b54f27bd 100644 --- a/src/overlays/l11/mobys/resort_owner.c +++ b/src/overlays/l11/mobys/resort_owner.c @@ -365,17 +365,17 @@ void update_resort_owner_state_transitions(void *resort_owner_moby) { float position_scratch[4]; float dialogue_rotation[4]; - if (moby->state >= 3 && moby->state <= 5 && proximity == 0) { + if (moby->state >= RESORT_OWNER_WAIT_TO_FOLLOW_HERO && moby->state <= RESORT_OWNER_FOLLOW_DISTANT_HERO && proximity == 0) { FUN_L11_002d2088_c(moby, 6); return; } - if (moby->state >= 4 && moby->state <= 6) { + if (moby->state >= RESORT_OWNER_FOLLOW_HERO && moby->state <= RESORT_OWNER_MOVE_TO_PATH_POINT) { fast_vec_normalize(position_scratch, &moby->rot_row0, 3.0f); fast_vec_add(position_scratch, position_scratch, &moby->pos); if (try_find_resort_owner_jump_target(moby, position_scratch)) { qcopy(&moby_vars->target, position_scratch); moby_vars->target.z = ground_height_14b0(&moby_vars->target); - moby_vars->next_state = 3; + moby_vars->next_state = RESORT_OWNER_WAIT_TO_FOLLOW_HERO; FUN_L11_002d2088_c(moby, 7); } } @@ -480,7 +480,7 @@ void update_resort_owner_state_transitions(void *resort_owner_moby) { &o->rot_row2, resort_owner_gate_jump_target_local_z_offset_gp); fast_vec_add(&moby_vars->target, &moby_vars->target, position_scratch); - moby_vars->next_state = 8; + moby_vars->next_state = RESORT_OWNER_MOVE_TO_GATE_TARGET; FUN_L11_002d2088_c(moby, 7); break; } @@ -500,7 +500,7 @@ void update_resort_owner_state_transitions(void *resort_owner_moby) { resort_owner_gate_jump_target_local_z_offset_gp); fast_vec_add(&moby_vars->target, &moby_vars->target, position_scratch); l11_cuboids[moby_vars->unk110].pos.z += 500.0f; - moby_vars->next_state = 8; + moby_vars->next_state = RESORT_OWNER_MOVE_TO_GATE_TARGET; FUN_L11_002d2088_c(moby, 7); break; } @@ -558,7 +558,7 @@ void update_resort_owner_state_transitions(void *resort_owner_moby) { if (vector_distance_xy(&moby->pos, &moby_vars->target) < 0.5f) { int next_leg_index = ++moby_vars->leg; qcopy(&moby_vars->target, &l11_cuboids[moby_vars->unkD0[next_leg_index]].pos); - moby_vars->next_state = 4; + moby_vars->next_state = RESORT_OWNER_FOLLOW_HERO; FUN_L11_002d2088_c(moby, 7); } break; From 18854ffe83d5cd4723b9c463a04dccaac27d8b4f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:17:06 +0000 Subject: [PATCH 1090/1502] decomp: clarify names in minibomber_update domain_0_value_0 -> MINIBOMBER_STATE_INITIALIZE: 0x002b47e8-0x002b47ec loads and compares the moby +0x20 byte against zero before the probe; the same byte drives switch(moby->state), whose existing local enum names zero INITIALIZE. domain_10_value_3 -> MINIBOMBER_STATE_RETRACE_INTRO_OR_EXIT_PATH: 0x002b4cf8 loads 3 and 0x002b4d04 stores it to moby +0x20 beside retrace initialization 0x002b5c30. This is the switch selector with existing RETRACE_INTRO_OR_EXIT_PATH member, not control field +0xB4. domain_11_value_5 -> MINIBOMBER_STATE_AIM_AT_BOMB_POINT: 0x002b4d28-0x002b4d2c stores 5 to moby +0x20 and initializes aim countdown and bomb-point index. The same byte selects existing AIM_AT_BOMB_POINT, whose body computes bombPath XY heading at 0x002b4eac-0x002b4ef4. domain_12_value_4 -> MINIBOMBER_STATE_HOLD_AT_PATH_END: 0x002b4db8-0x002b4dbc writes 4 to moby +0x20 on traversal completion, then toggles direction and copies endpoint target at 0x002b4ea0. This enters existing HOLD_AT_PATH_END case for the same state byte. domain_13_value_4 -> MINIBOMBER_STATE_HOLD_AT_PATH_END: 0x002b4f48 branches to 0x002b50e4 with 4 from 0x002b4f4c when animation 2 interrupts aim; 0x002b50e4 stores moby +0x20 and sets aim-return timer. Same selector's existing 4 member is HOLD_AT_PATH_END. domain_14_value_6 -> MINIBOMBER_STATE_RELEASE_BOMB: 0x002b4f5c loads 6 and 0x002b4f64 stores moby +0x20 after aim countdown completion, saving angle and starting animation 1. Same state selector's existing RELEASE_BOMB case creates the projectile at 0x002b5098. domain_15_value_4 -> MINIBOMBER_STATE_HOLD_AT_PATH_END: 0x002b50dc-0x002b50e4 writes 4 to moby +0x20 when the incremented bomb-point index reaches path count, followed by aim-return countdown. This is the existing HOLD_AT_PATH_END switch member for the identical state byte. domain_16_value_5 -> MINIBOMBER_STATE_AIM_AT_BOMB_POINT: 0x002b50f8-0x002b510c resets aim countdown and writes 5 to moby +0x20 when more bomb points remain after release. That same byte selects existing AIM_AT_BOMB_POINT, computing the indexed target's relative heading. domain_17_value_1 -> MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH: 0x002b521c loads moby +0x20 and 0x002b5220-0x002b5224 skips audio for values below 2, implementing source state > 1. The comparison bound is the same selector's existing WAIT_TO_FOLLOW_PATH=1 member. domain_18_value_9 -> MINIBOMBER_STATE_DESTROY: 0x002b522c-0x002b5230 compares the loaded moby +0x20 state byte to 9 to skip voice playback/allocation. Same byte drives existing DESTROY switch case, which releases its owned voice and removes the moby. domain_1_value_1 -> MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH: 0x002b47f0-0x002b47f4 compares the loaded moby +0x20 state byte with 1 before the probe. The same selector has existing case MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH, waiting at 0x002b49d8. domain_2_value_9 -> MINIBOMBER_STATE_DESTROY: 0x002b47f8-0x002b47fc compares the moby +0x20 state byte with 9 before the probe. This is the same selector as existing MINIBOMBER_STATE_DESTROY, whose body removes the moby at 0x002b520c. domain_3_value_1 -> MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH: 0x002b4994 loads 1 and 0x002b49a8 stores it to moby +0x20 after path initialization and before hiding via 0x002b5c98. This enters the existing WAIT_TO_FOLLOW_PATH switch member for that exact byte. domain_4_value_2 -> MINIBOMBER_STATE_FOLLOW_INTRO_OR_EXIT_PATH: 0x002b49dc loads 2 and 0x002b49ec stores it to moby +0x20 when pvars+0xB4 permits departure; 0x002b4a00 initializes following. The same byte selects existing FOLLOW_INTRO_OR_EXIT_PATH case. domain_5_value_3 -> MINIBOMBER_STATE_RETRACE_INTRO_OR_EXIT_PATH: 0x002b4a48-0x002b4a50 writes 3 to moby +0x20 when control +0xB4 equals 2 while following. The same state selector's existing RETRACE_INTRO_OR_EXIT_PATH case negates its path step at 0x002b4bf4. domain_6_value_4 -> MINIBOMBER_STATE_HOLD_AT_PATH_END: 0x002b4b44 loads 4 and 0x002b4b78 writes moby +0x20 after copying the completed path endpoint to +0x180 and preparing heading/easing. This enters existing HOLD_AT_PATH_END case of the same state selector. domain_7_value_2 -> MINIBOMBER_STATE_FOLLOW_INTRO_OR_EXIT_PATH: 0x002b4bac loads 2 and 0x002b4bbc writes it to moby +0x20 when retrace control clears. The target byte is the switch selector already naming 2 FOLLOW_INTRO_OR_EXIT_PATH, which selects intro/exit paths. domain_8_value_1 -> MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH: 0x002b4c08 loads 1 and 0x002b4c14 writes it to moby +0x20 on completed negative path traversal, alongside hide/release helper 0x002b5c98. This enters existing WAIT_TO_FOLLOW_PATH for the same selector. domain_9_value_7 -> MINIBOMBER_STATE_TRAVERSE_PATH: 0x002b4cd4-0x002b4cdc writes 7 to moby +0x20 after selecting starting progress on path +0xDC. Same byte selects existing TRAVERSE_PATH, whose body advances that path at 0x002b4dac. --- src/overlays/l14/mobys/minibomber.c | 34 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/overlays/l14/mobys/minibomber.c b/src/overlays/l14/mobys/minibomber.c index 36bdc9382b..7cfd15abc2 100644 --- a/src/overlays/l14/mobys/minibomber.c +++ b/src/overlays/l14/mobys/minibomber.c @@ -309,8 +309,8 @@ void minibomber_update(Moby_2B5938 *moby) { FUN_L14_002b5428_c((char *)moby); FUN_L14_002b5dd8_c((char *)moby); if (moby->f31 != 0) { - if (fast_vec_dist(moby->pos, D_L14_001674C0) < 40.0f && moby->state != 0 && - moby->state != 1 && moby->state != 9) { + if (fast_vec_dist(moby->pos, D_L14_001674C0) < 40.0f && moby->state != MINIBOMBER_STATE_INITIALIZE && + moby->state != MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH && moby->state != MINIBOMBER_STATE_DESTROY) { FUN_L00_0025a120(moby); } } @@ -369,7 +369,7 @@ void minibomber_update(Moby_2B5938 *moby) { FUN_L14_002b55b0_c((char *)moby); d->f108 = -1; moby->f30 = 0x80; - moby->state = 1; + moby->state = MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH; FUN_L14_002b5c98_c((char *)moby); fill_transfer_words(manipulator_state, 0, 0x40); attach_manipulator(moby, 0, manipulator_state); @@ -378,7 +378,7 @@ void minibomber_update(Moby_2B5938 *moby) { } case MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH: if (d->fB4 != 2) { - moby->state = 2; + moby->state = MINIBOMBER_STATE_FOLLOW_INTRO_OR_EXIT_PATH; moby->f34 &= 0xFFBE; moby->f94 = moby->cls->f10; FUN_L14_002b5d18_c((char *)moby); @@ -392,7 +392,7 @@ void minibomber_update(Moby_2B5938 *moby) { path = ((PathNode *)l14_paths[d->f150]); } if (d->fB4 == 2) { - moby->state = 3; + moby->state = MINIBOMBER_STATE_RETRACE_INTRO_OR_EXIT_PATH; } else if (advance_minibomber_along_path((char *)moby, (char *)path, (int)&d->fE8, @@ -424,7 +424,7 @@ void minibomber_update(Moby_2B5938 *moby) { d->f154 = minibomber_intro_exit_heading_error_gain_gp; d->f158 = minibomber_heading_velocity_damping_gp; d->f15C = minibomber_heading_velocity_limit_gp; - moby->state = 4; + moby->state = MINIBOMBER_STATE_HOLD_AT_PATH_END; d->f104 = 0.0f; d->f102 = 0; } @@ -438,7 +438,7 @@ void minibomber_update(Moby_2B5938 *moby) { path = ((PathNode *)l14_paths[d->f150]); } if (d->fB4 != 2) { - moby->state = 2; + moby->state = MINIBOMBER_STATE_FOLLOW_INTRO_OR_EXIT_PATH; } else if (advance_minibomber_along_path( (char *)moby, (char *)path, @@ -453,7 +453,7 @@ void minibomber_update(Moby_2B5938 *moby) { minibomber_retrace_and_traversal_heading_error_gain_gp, minibomber_heading_velocity_damping_gp, minibomber_heading_velocity_limit_gp) != 0) { - moby->state = 1; + moby->state = MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH; FUN_L14_002b5c98_c((char *)moby); } break; @@ -477,15 +477,15 @@ void minibomber_update(Moby_2B5938 *moby) { q = ((PathNode *)l14_paths[d->fDC]) + d->fE8; d->fEC = q[1].v[3]; } - moby->state = 7; + moby->state = MINIBOMBER_STATE_TRAVERSE_PATH; d->fE4 = 0.0f; clear_u64_value(d->fF0); } else if (d->fB4 == 2) { - moby->state = 3; + moby->state = MINIBOMBER_STATE_RETRACE_INTRO_OR_EXIT_PATH; FUN_L14_002b5c30_c((char *)moby); } else if (fast_dec_timer_s16(&d->f102) != 0) { if (moby->f53 != 2) { - moby->state = 5; + moby->state = MINIBOMBER_STATE_AIM_AT_BOMB_POINT; d->f102 = scale_game_frames(minibomber_bomb_aim_duration_frames); d->f104 = 0.0f; d->f100 = 0; @@ -511,7 +511,7 @@ void minibomber_update(Moby_2B5938 *moby) { minibomber_heading_velocity_damping_gp, minibomber_heading_velocity_limit_gp) != 0) { PathNode *path; - moby->state = 4; + moby->state = MINIBOMBER_STATE_HOLD_AT_PATH_END; if (d->f10C == 0) { d->f10C = 1; } else { @@ -547,11 +547,11 @@ void minibomber_update(Moby_2B5938 *moby) { convert_integer_to_float(scale_game_frames(minibomber_bomb_aim_duration_frames))); build_axis_rotation_quaternion(d->f120, 2, blended_aim_angle); if (moby->f53 == 2) { - moby->state = 4; + moby->state = MINIBOMBER_STATE_HOLD_AT_PATH_END; d->f102 = scale_game_frames(minibomber_aim_return_duration_frames); } else if (fast_dec_timer_s16(&d->f102) != 0) { d->f104 = blended_aim_angle; - moby->state = 6; + moby->state = MINIBOMBER_STATE_RELEASE_BOMB; set_moby_animation_c(moby, 1, 0); } break; @@ -576,11 +576,11 @@ void minibomber_update(Moby_2B5938 *moby) { FUN_L14_002b5968_u((char *)moby, v, d->f104); d->f100++; if (d->f100 >= ((PathNode *)l14_paths[d->fD8])->n) { - moby->state = 4; + moby->state = MINIBOMBER_STATE_HOLD_AT_PATH_END; d->f102 = scale_game_frames(minibomber_aim_return_duration_frames); } else { d->f102 = scale_game_frames(minibomber_bomb_aim_duration_frames); - moby->state = 5; + moby->state = MINIBOMBER_STATE_AIM_AT_BOMB_POINT; } } break; @@ -621,7 +621,7 @@ void minibomber_update(Moby_2B5938 *moby) { return; } } - if (moby->state > 1 && moby->state != 9) { + if (moby->state > MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH && moby->state != MINIBOMBER_STATE_DESTROY) { if (voice_is_playing(moby, d->f108) == 0) { d->f108 = allocate_voice_for_target_entry(0, 4, (int)moby); } From af905238d74e93f695fbadd9c85099870a8f6eff Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:17:07 +0000 Subject: [PATCH 1091/1502] decomp: clarify names in bomb_spawner_update domain_0_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002bf054-0x002bf064 reads pooled Moby+0x20 and excludes 0xFE/0xFD before incrementing live count. Supplied mark_moby_for_removal assigns 0xFE to this same Moby state field for objects at or above moby_instance_end, establishing the removal-state domain. domain_10_value_3 -> SPAWNER_SPAWN_ENABLED_SHARED: Activation case SPAWNER_ACTIVATION_ENTER_SHARED_SPAWN_ENABLED loads 3 at retail 0x002bf360 and writes owner Moby+0x20 at 0x002bf398. The outer switch uses precisely this field and already names state 3 SPAWNER_SPAWN_ENABLED_SHARED; reuse that state member rather than activation-domain value 3. domain_11_value_7 -> SPAWNER_SPAWN_ENABLED_SHARED_ALIAS: Activation case SPAWNER_ACTIVATION_ENTER_SHARED_SPAWN_ENABLED_ALIAS loads 7 at 0x002bf370 and stores it to owner Moby+0x20 at 0x002bf524. The same field is the outer state selector with established member SPAWNER_SPAWN_ENABLED_SHARED_ALIAS=7, proving the destination state domain. domain_12_value_2 -> SPAWNER_SPAWN_ENABLED: Activation case SPAWNER_ACTIVATION_SET_SPAWN_ENABLED loads 2 at retail 0x002bf380 and stores it to owner Moby+0x20 at 0x002bf3c0. The outer switch selects that same Moby field and names state 2 SPAWNER_SPAWN_ENABLED; the activation selector b84 remains a separate domain. domain_13_value_5 -> SPAWNER_SPAWN_ENABLED_AFTER_PROXIMITY: After proximity gate 0x002bf314, activation case SPAWNER_ACTIVATION_ENTER_SPAWN_ENABLED_AFTER_PROXIMITY loads 5 at 0x002bf38c and stores it into owner Moby+0x20 at 0x002bf398. This exact field selects established outer case SPAWNER_SPAWN_ENABLED_AFTER_PROXIMITY=5. domain_14_value_5 -> SPAWNER_SPAWN_ENABLED_AFTER_PROXIMITY: Activation case SPAWNER_ACTIVATION_ENTER_SPAWN_ENABLED_AFTER_PROXIMITY_ALIAS loads 5 at 0x002bf3a8 and stores it to owner Moby+0x20 at 0x002bf524. The outer switch on the same field already establishes state 5 as SPAWNER_SPAWN_ENABLED_AFTER_PROXIMITY; alias describes activation, not a distinct destination state. domain_15_value_1 -> SPAWNER_WAIT_FOR_PROXIMITY: The activation STAY_IN_PROXIMITY_WAIT/default branch loads 1 at retail 0x002bf3b4 and stores it to owner Moby+0x20 at 0x002bf3c0. That same field is the outer state selector, whose established state 1 waits at proximity gate 0x002bf314. Reuse the state member, not activation value 1. domain_16_value_1 -> SPAWNER_WAIT_FOR_PROXIMITY: Outer SPAWNER_RESET_TO_PROXIMITY_WAIT/default path loads 1 at retail 0x002bf51c and writes owner Moby+0x20 at 0x002bf524. The same field dispatches established SPAWNER_WAIT_FOR_PROXIMITY=1, with its distance gate at 0x002bf310-0x002bf314, proving the reset destination. domain_1_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002bf054-0x002bf070 excludes 0xFD from the pooled Moby state before counting it live. Supplied mark_moby_for_removal writes 0xFD to Moby->state when the pointer is below moby_instance_end; the field and live-child filtering establish the same removal-state domain. domain_2_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002bf098-0x002bf0c4 traverses next at Moby+0x28, filters class 0x221 at +0xA6 and excludes state +0x20 value 0xFE from live count. Supplied mark_moby_for_removal names this same Moby-state value for removal at or above moby_instance_end. domain_3_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002bf0a8-0x002bf0c4 excludes class-0x221 Moby state +0x20 value 0xFD before incrementing live count. Supplied mark_moby_for_removal assigns this same field/value for pointers below moby_instance_end, proving the generic removal-state domain. domain_5_value_8 -> SPAWNER_DESTROY: Retail 0x002bf1d8-0x002bf234 subtracts hit damage from hp and stores 8 to the owner Moby+0x20 on nonpositive health. The same owner state is dispatched at 0x002bf24c-0x002bf270; established C case SPAWNER_DESTROY emits explosion/effects at 0x002bf404-0x002bf500 and removes the owner at 0x002bf504. domain_6_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002bf2b4-0x002bf2c8 checks pooled child Moby+0x20 against 0xFE/0xFD before calling mark_moby_for_removal on it. Supplied removal helper writes 0xFE to this field for pointers at or above moby_instance_end; this check avoids marking an already removed child. domain_7_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002bf2b4-0x002bf2c8 excludes pooled child state 0xFD before calling mark_moby_for_removal. Supplied helper assigns 0xFD to the same Moby state field below moby_instance_end, directly establishing the removal-domain meaning. domain_8_value_1 -> SPAWNER_WAIT_FOR_PROXIMITY: Retail initialization 0x002bf298-0x002bf30c removes live pooled children and sets initial fields, then stores 1 to owner Moby+0x20. This exact field selects the established SPAWNER_WAIT_FOR_PROXIMITY case, which waits on the proximity predicate at 0x002bf310-0x002bf314. domain_9_value_2 -> SPAWNER_SPAWN_ENABLED: Under established SPAWNER_WAIT_FOR_PROXIMITY, activation case SPAWNER_ACTIVATION_ENTER_SPAWN_ENABLED loads 2 at 0x002bf350 and stores it to owner Moby+0x20 at 0x002bf3c0. This is the same field dispatched by the outer switch, whose established SPAWNER_SPAWN_ENABLED case enables the common spawn gate. --- src/overlays/shared/enemies/bomb_spawner.c | 30 ++++++++++++---------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/overlays/shared/enemies/bomb_spawner.c b/src/overlays/shared/enemies/bomb_spawner.c index 385e0c2fd7..ecf42905d7 100644 --- a/src/overlays/shared/enemies/bomb_spawner.c +++ b/src/overlays/shared/enemies/bomb_spawner.c @@ -178,6 +178,10 @@ void bomb_spawner_update(struct Moby *moby) { SPAWNER_ACTIVATION_ENTER_SPAWN_ENABLED_AFTER_PROXIMITY_ALIAS = 5, SPAWNER_ACTIVATION_STAY_IN_PROXIMITY_WAIT = 6 }; + enum { + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE + }; int used[4]; Vec4A_2bef68 launch_origin; Vec4A_2bef68 launch_velocity; @@ -217,14 +221,14 @@ void bomb_spawner_update(struct Moby *moby) { if (id == -1) continue; o = (struct Moby *)(D_L03_0015FFD8_macro + (id << 8)); - if (o != 0 && o->state != 0xFE && o->state != 0xFD) { + if (o != 0 && o->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && o->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { spawner_data->count++; } } { struct Moby *o; for (o = (struct Moby *)D_L03_0015FFE4_macro; o != 0; o = o->next) { - if (o->oclass == 0x221 && o->state != 0xFE && o->state != 0xFD) { + if (o->oclass == 0x221 && o->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && o->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { spawner_data->count++; } } @@ -263,7 +267,7 @@ void bomb_spawner_update(struct Moby *moby) { trooper_anim_update(moby, spawner_data->f60); } else { mark_moby_for_removal_cf(moby, 0, -1); - moby->state = 8; + moby->state = SPAWNER_DESTROY; spawner_data->b67 = 0x78; trooper_anim_update(moby, spawner_data->f60); } @@ -278,7 +282,7 @@ void bomb_spawner_update(struct Moby *moby) { if (id == -1) continue; o = (struct Moby *)(D_L03_0015FFD8_macro + (id << 8)); - if (o != 0 && o->state != 0xFE && o->state != 0xFD) { + if (o != 0 && o->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && o->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { mark_moby_for_removal(o); } } @@ -286,33 +290,33 @@ void bomb_spawner_update(struct Moby *moby) { spawner_data->b5A = 3; spawner_data->b58 = 8; spawner_data->b29 = 0; - moby->state = 1; + moby->state = SPAWNER_WAIT_FOR_PROXIMITY; break; } case SPAWNER_WAIT_FOR_PROXIMITY: if (near1) { switch (spawner_data->b84) { case SPAWNER_ACTIVATION_ENTER_SPAWN_ENABLED: - moby->state = 2; + moby->state = SPAWNER_SPAWN_ENABLED; break; case SPAWNER_ACTIVATION_ENTER_SHARED_SPAWN_ENABLED: - moby->state = 3; + moby->state = SPAWNER_SPAWN_ENABLED_SHARED; break; case SPAWNER_ACTIVATION_ENTER_SHARED_SPAWN_ENABLED_ALIAS: - moby->state = 7; + moby->state = SPAWNER_SPAWN_ENABLED_SHARED_ALIAS; break; case SPAWNER_ACTIVATION_SET_SPAWN_ENABLED: - moby->state = 2; + moby->state = SPAWNER_SPAWN_ENABLED; break; case SPAWNER_ACTIVATION_ENTER_SPAWN_ENABLED_AFTER_PROXIMITY: - moby->state = 5; + moby->state = SPAWNER_SPAWN_ENABLED_AFTER_PROXIMITY; break; case SPAWNER_ACTIVATION_ENTER_SPAWN_ENABLED_AFTER_PROXIMITY_ALIAS: - moby->state = 5; + moby->state = SPAWNER_SPAWN_ENABLED_AFTER_PROXIMITY; break; case SPAWNER_ACTIVATION_STAY_IN_PROXIMITY_WAIT: default: - moby->state = 1; + moby->state = SPAWNER_WAIT_FOR_PROXIMITY; break; } } @@ -368,7 +372,7 @@ void bomb_spawner_update(struct Moby *moby) { } case SPAWNER_RESET_TO_PROXIMITY_WAIT: default: - moby->state = 1; + moby->state = SPAWNER_WAIT_FOR_PROXIMITY; break; } if (spawn && cond && timerDone && room) { From 6fbf6ca1af0f12f634d93a5ab9e83082867b5f54 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:17:07 +0000 Subject: [PATCH 1092/1502] decomp: clarify names in test_dummy_update domain_0_value_0 -> TEST_DUMMY_KIND_THROWER: The comparison loads dummy_data->kind at data+0xC0 (002cdfac) and branches on zero at 002cdfb8, selecting state 3 at 002cdfc0-002cdfc8. This is the identical field read at 002cdee0 by initialization's existing TEST_DUMMY_KIND_THROWER case, which creates child 0x35F at 002cdef8-002cdf28. State 3 proceeds to throwing state 4, whose 002ce144-002ce1bc computes and launches the child's ballistic projectile. Original Ghidra case 2 and authoritative C agree; reuse the existing kind constant, not a state or hero constant. domain_1_value_1 -> TEST_DUMMY_KIND_PATH_MOVER: Retail 002cdfac loads dummy_data->kind at data+0xC0; 002cdfa8 sets v1=1 and 002cdfcc compares that field to v1, dispatching to movement state 5 at 002ce4f4-002ce4fc. Initialization reads the same field at 002cdee0 and compares against 1 at 002cdee4-002cdee8, the authoritative C's existing TEST_DUMMY_KIND_PATH_MOVER case creating child 0x374. State 5 limits indexed path-node minus moby position and adds it back at 002ce2ec-002ce32c. Original Ghidra confirms this selector and dispatch, proving canonical same-domain reuse. --- src/overlays/l16/mobys/test_dummy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l16/mobys/test_dummy.c b/src/overlays/l16/mobys/test_dummy.c index c804ef33aa..0a14499206 100644 --- a/src/overlays/l16/mobys/test_dummy.c +++ b/src/overlays/l16/mobys/test_dummy.c @@ -204,9 +204,9 @@ void test_dummy_update(unsigned char *moby) { dummy_data->timer = scale_game_frames(30); dummy_data->node = 1; dummy_data->step = 1; - if (dummy_data->kind == 0) { + if (dummy_data->kind == TEST_DUMMY_KIND_THROWER) { moby[0x20] = 3; - } else if (dummy_data->kind == 1) { + } else if (dummy_data->kind == TEST_DUMMY_KIND_PATH_MOVER) { moby[0x20] = 5; } else { moby[0x20] = 7; From c0368706a46499fe5832b41551d75c61be1eaae3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:17:07 +0000 Subject: [PATCH 1093/1502] decomp: clarify names in update_help_hints domain_0_value_1 -> TUTORIAL_HINTS_UPDATE: The exact source switches on moby->state with TUTORIAL_HINTS_UPDATE = 1. Retail 0x002df55c-0x002df568 reads moby+0x20 and dispatches 1 to the update body at 0x002df594; initialization writes that same byte to 1 at 0x002df584-0x002df588. Reuse the existing member of this exact moby-state domain. domain_10_value_0 -> HELP_PLAYBACK_IDLE: Retail 0x002dfd50-002dfd80 tests the word at 0x00179510 for zero and current message at +0x24 for -1 before help_request(0xBBD,0x19); original Ghidra uses iRam00179510 and iRam00179534 for these same gates. Checked level-03 helper 0x001fd2a8-0x001fd2c8 rejects nonzero state or an occupied current message, then 0x001fd310-0x001fd318 records the accepted message. This proves an idle playback gate in l03_help_message_playback_state.state, separate from moby and hero domains. domain_11_value_0 -> HELP_PLAYBACK_IDLE: Retail 0x002dfeb0-002dfee0 tests the word at 0x00179510 for zero and current message at +0x24 for -1 before help_request(0xBBE,0x1A); original Ghidra uses iRam00179510 and iRam00179534 for these same gates. Checked level-03 helper 0x001fd2a8-0x001fd2c8 rejects nonzero state or an occupied current message, then 0x001fd310-0x001fd318 records the accepted message. This proves an idle playback gate in l03_help_message_playback_state.state, separate from moby and hero domains. domain_12_value_0 -> HELP_PLAYBACK_IDLE: Retail 0x002dffd4-002e0004 tests the word at 0x00179510 for zero and current message at +0x24 for -1 before help_request(0xBBF,0x1B); original Ghidra uses iRam00179510 and iRam00179534 for these same gates. Checked level-03 helper 0x001fd2a8-0x001fd2c8 rejects nonzero state or an occupied current message, then 0x001fd310-0x001fd318 records the accepted message. This proves an idle playback gate in l03_help_message_playback_state.state, separate from moby and hero domains. domain_13_value_0 -> HELP_PLAYBACK_IDLE: Retail 0x002e0044-002e0074 tests the word at 0x00179510 for zero and current message at +0x24 for -1 before help_request(0x4E2F,0x79); original Ghidra uses iRam00179510 and iRam00179534 for these same gates. Checked level-03 helper 0x001fd2a8-0x001fd2c8 rejects nonzero state or an occupied current message, then 0x001fd310-0x001fd318 records the accepted message. This proves an idle playback gate in l03_help_message_playback_state.state, separate from moby and hero domains. domain_1_value_0 -> HELP_PLAYBACK_IDLE: Retail 0x002df628-002df654 tests the word at 0x00179510 for zero and current message at +0x24 for -1 before help_request(0xBB8,0x14); original Ghidra uses iRam00179510 and iRam00179534 for these same gates. Checked level-03 helper 0x001fd2a8-0x001fd2c8 rejects nonzero state or an occupied current message, then 0x001fd310-0x001fd318 records the accepted message. This proves an idle playback gate in l03_help_message_playback_state.state, separate from moby and hero domains. domain_2_value_0 -> HELP_PLAYBACK_IDLE: Retail 0x002df694-002df6c0 tests the word at 0x00179510 for zero and current message at +0x24 for -1 before help_request(0xBB9,0x15); original Ghidra uses iRam00179510 and iRam00179534 for these same gates. Checked level-03 helper 0x001fd2a8-0x001fd2c8 rejects nonzero state or an occupied current message, then 0x001fd310-0x001fd318 records the accepted message. This proves an idle playback gate in l03_help_message_playback_state.state, separate from moby and hero domains. domain_3_value_0 -> HELP_PLAYBACK_IDLE: Retail 0x002df700-002df72c tests the word at 0x00179510 for zero and current message at +0x24 for -1 before help_request(0xBBB,0x17); original Ghidra uses iRam00179510 and iRam00179534 for these same gates. Checked level-03 helper 0x001fd2a8-0x001fd2c8 rejects nonzero state or an occupied current message, then 0x001fd310-0x001fd318 records the accepted message. This proves an idle playback gate in l03_help_message_playback_state.state, separate from moby and hero domains. domain_4_value_0 -> HELP_PLAYBACK_IDLE: Retail 0x002df8fc-002df92c tests the word at 0x00179510 for zero and current message at +0x24 for -1 before help_request(0xBBA,0x16); original Ghidra uses iRam00179510 and iRam00179534 for these same gates. Checked level-03 helper 0x001fd2a8-0x001fd2c8 rejects nonzero state or an occupied current message, then 0x001fd310-0x001fd318 records the accepted message. This proves an idle playback gate in l03_help_message_playback_state.state, separate from moby and hero domains. domain_5_value_0 -> HELP_PLAYBACK_IDLE: Retail 0x002df96c-002df9cc tests the word at 0x00179510 for zero and current message at +0x24 for -1 before help_request(0xBBC,0x18); original Ghidra uses iRam00179510 and iRam00179534 for these same gates. Checked level-03 helper 0x001fd2a8-0x001fd2c8 rejects nonzero state or an occupied current message, then 0x001fd310-0x001fd318 records the accepted message. This proves an idle playback gate in l03_help_message_playback_state.state, separate from moby and hero domains. domain_6_value_0 -> HELP_PLAYBACK_IDLE: Retail 0x002dfaa8-002dfae8 tests the word at 0x00179510 for zero and current message at +0x24 for -1 before help_request(0x4E20,0x4A); original Ghidra uses iRam00179510 and iRam00179534 for these same gates. Checked level-03 helper 0x001fd2a8-0x001fd2c8 rejects nonzero state or an occupied current message, then 0x001fd310-0x001fd318 records the accepted message. This proves an idle playback gate in l03_help_message_playback_state.state, separate from moby and hero domains. domain_7_value_0 -> HELP_PLAYBACK_IDLE: Retail 0x002dfbe8-002dfc18 tests the word at 0x00179510 for zero and current message at +0x24 for -1 before help_request(0x3EC,0x40); original Ghidra uses iRam00179510 and iRam00179534 for these same gates. Checked level-03 helper 0x001fd2a8-0x001fd2c8 rejects nonzero state or an occupied current message, then 0x001fd310-0x001fd318 records the accepted message. This proves an idle playback gate in l03_help_message_playback_state.state, separate from moby and hero domains. domain_8_value_0 -> HELP_PLAYBACK_IDLE: Retail 0x002dfc7c-002dfcb8 tests the word at 0x00179510 for zero and current message at +0x24 for -1 before help_request(0x3ED,0x41); original Ghidra uses iRam00179510 and iRam00179534 for these same gates. Checked level-03 helper 0x001fd2a8-0x001fd2c8 rejects nonzero state or an occupied current message, then 0x001fd310-0x001fd318 records the accepted message. This proves an idle playback gate in l03_help_message_playback_state.state, separate from moby and hero domains. domain_9_value_0 -> HELP_PLAYBACK_IDLE: Retail 0x002dfcf8-002dfd28 tests the word at 0x00179510 for zero and current message at +0x24 for -1 before help_request(0xBC0,0x54); original Ghidra uses iRam00179510 and iRam00179534 for these same gates. Checked level-03 helper 0x001fd2a8-0x001fd2c8 rejects nonzero state or an occupied current message, then 0x001fd310-0x001fd318 records the accepted message. This proves an idle playback gate in l03_help_message_playback_state.state, separate from moby and hero domains. --- src/overlays/l03/mobys/help_hints.c | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/overlays/l03/mobys/help_hints.c b/src/overlays/l03/mobys/help_hints.c index 8b5ea34ca4..474a326e76 100644 --- a/src/overlays/l03/mobys/help_hints.c +++ b/src/overlays/l03/mobys/help_hints.c @@ -44,7 +44,7 @@ void help_hints_update(struct Moby *moby) { enum { TUTORIAL_HINTS_INITIALIZE = 0, TUTORIAL_HINTS_UPDATE = 1 - }; + } ; enum { HELP_PLAYBACK_IDLE = 0}; s32 *tutorial_hint_state = ((s32 *)moby->pvars); struct Moby *candidate_moby; s32 count; @@ -57,7 +57,7 @@ void help_hints_update(struct Moby *moby) { tutorial_hint_state[20] = 0; tutorial_hint_state[21] = 0; moby->update_dist = 0xFF; - moby->state = 1; + moby->state = TUTORIAL_HINTS_UPDATE; break; case TUTORIAL_HINTS_UPDATE: if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_state[30]) && @@ -67,19 +67,19 @@ void help_hints_update(struct Moby *moby) { if (alternate_item_available[0x1A] == 0) { if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_state[0]) && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && - l03_help_message_playback_state.state == 0 && + l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x14].level_mask >= 0) { help_request(0xBB8, 0x14); } if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_state[3]) && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && - l03_help_message_playback_state.state == 0 && + l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x15].level_mask >= 0) { help_request(0xBB9, 0x15); } if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_state[6]) && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && - l03_help_message_playback_state.state == 0 && + l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x17].level_mask >= 0) { help_request(0xBBB, 0x17); } @@ -109,13 +109,13 @@ void help_hints_update(struct Moby *moby) { usage_stats.stat[3].count == 0 && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && tutorial_hint_state[20] % 6 == 0 && tutorial_hint_state[20] != 0 && - l03_help_message_playback_state.state == 0 && + l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x16].count == 0) { help_request(0xBBA, 0x16); } if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_state[10]) && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && - l03_help_message_playback_state.state == 0 && + l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x18].count == 0) { scaled_time_value = scale_game_frames(D_0015EEA4) - usage_stats.stat[9].latest_time_bucket * 600; @@ -134,7 +134,7 @@ void help_hints_update(struct Moby *moby) { if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_state[15]) && count == 0 && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && hero.state.current != 0x1E && item_available[0xF] != 0 && get_ammo(0xF) >= 0x15 && - l03_help_message_playback_state.state == 0 && + l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x4A].count == 0 && usage_stats.stat[19].count == 0) { help_request(0x4E20, 0x4A); @@ -151,26 +151,26 @@ void help_hints_update(struct Moby *moby) { } if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_state[14]) && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && - D_L03_0015F68C < 3 && l03_help_message_playback_state.state == 0 && + D_L03_0015F68C < 3 && l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x40].count == 0) { help_request(0x3EC, 0x40); } if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_state[14]) && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && hero.state.current == HERO_STATE_LOOK && D_L03_0015F688 == -1 && - l03_help_message_playback_state.state == 0 && + l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x40].count != 0 && help_records[0x41].count == 0) { help_request(0x3ED, 0x41); } if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_state[16]) && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && - l03_help_message_playback_state.state == 0 && + l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x54].count == 0) { help_request(0xBC0, 0x54); } if (D_L03_0015F5C4 == 0 && item_available[0x34] != 0 && - l03_help_message_playback_state.state == 0 && + l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x19].count == 0) { help_request(0xBBD, 0x19); } @@ -191,7 +191,7 @@ void help_hints_update(struct Moby *moby) { } if (usage_stats.stat[15].count == 0 && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && - tutorial_hint_state[21] >= 3 && l03_help_message_playback_state.state == 0 && + tutorial_hint_state[21] >= 3 && l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x1A].count == 0) { help_request(0xBBE, 0x1A); } @@ -206,13 +206,13 @@ void help_hints_update(struct Moby *moby) { } if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_state[11]) && usage_stats.stat[16].count == 0 && hero.state.control_mode == 6 && - hero.items[0].item_id == 8 && l03_help_message_playback_state.state == 0 && + hero.items[0].item_id == 8 && l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x1B].count == 0) { help_request(0xBBF, 0x1B); } if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_state[17]) && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && - l03_help_message_playback_state.state == 0 && + l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x79].count == 0) { help_request(0x4E2F, 0x79); } From af4bc3f4a51536f65ca78c36c707e95ac1df716e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:18:47 +0000 Subject: [PATCH 1094/1502] decomp: clarify names in blaster_update domain_0_value_0 -> BLASTER_STATE_UNINITIALIZED: In authoritative blaster.c SHA-256 56e96366deed85f31eef1133ebf6f4bb2493238ccf077562745414e3674a45e9, blaster_update tests moby->state == 0 solely to perform initialization. Retail 002b49c0 preserves the moby argument in s4, 002b49fc loads its byte at +0x20, and 002b4a04 skips setup when nonzero. The zero path stores state 1 at 002b4a14, initializes the pvars light handle (+0x10) to -1 at 002b4a18 and glow (+0x14) to zero at 002b4a1c. The supplied original decompilation confirms the same guard and setup. This is the blaster instance's uninitialized state, not hero.state.current at hero+0x2084. domain_1_value_1 -> BLASTER_STATE_INITIALIZED: Retail 002b4a0c loads 1 and 002b4a14 stores that byte into +0x20 of the original moby argument held in s4, inside the zero-state guard at 002b49fc..002b4a04. The same block initializes BlasterVars.light to -1 and glow to zero (002b4a18..002b4a1c), then joins regular timer, aiming, firing and light maintenance at 002b4a20. Authoritative blaster_update and the original retail decompilation show no other writes to this moby state in the assigned function; storing 1 prevents reinitializing those persistent effect fields on subsequent updates. Thus INITIALIZED names the proven initialization transition without attributing hero or animation semantics. --- src/overlays/shared/weapons/blaster.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/blaster.c b/src/overlays/shared/weapons/blaster.c index c271e19fc1..a81fe1584b 100644 --- a/src/overlays/shared/weapons/blaster.c +++ b/src/overlays/shared/weapons/blaster.c @@ -210,6 +210,10 @@ void blaster_update(struct Moby *moby) __asm__("FUN_L00_002b49a8"); /* Moby class 168 */ void blaster_update(struct Moby *moby) { + enum { + BLASTER_STATE_UNINITIALIZED = 0, + BLASTER_STATE_INITIALIZED = 1 + }; BlasterVec velocity; BlasterVec aim_point; BlasterVec launch; @@ -232,8 +236,8 @@ void blaster_update(struct Moby *moby) { never = 0; pitch = 0.0f; blaster_vars = (BlasterVars *)moby->pvars; - if (moby->state == 0) { - moby->state = 1; + if (moby->state == BLASTER_STATE_UNINITIALIZED) { + moby->state = BLASTER_STATE_INITIALIZED; blaster_vars->light = -1; blaster_vars->glow = 0; } From f19484d4d801b3f52f9c3bed95ccdb55972937e2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:18:48 +0000 Subject: [PATCH 1095/1502] decomp: clarify names in blarg_space_commando_update domain_0_value_1 -> BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION: Retail 00308034 stores 1 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION=1 in this function's switch domain. Initialization saves home and initializes the point, then enters target-facing action selection at 00308038..003081b8. domain_10_value_11 -> BLARG_SPACE_COMMANDO_APPROACH_TARGET_UNTIL_BLOCKED_OR_NEAR: Retail 003083b0 stores 11 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_APPROACH_TARGET_UNTIL_BLOCKED_OR_NEAR=11 in this function's switch domain. Nonzero pvars+184 exits timer wait to case11 with animation1; case11 steers and moves toward target and checks blocked-path/near-target exits. domain_11_value_6 -> BLARG_SPACE_COMMANDO_RESUME_SAVED_STATE_AFTER_ANIMATION: Retail 0030855c stores 6 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_RESUME_SAVED_STATE_AFTER_ANIMATION=6 in this function's switch domain. After the case5 animation completes, state6 is stored and command1 saved at 00308564; case6 copies command+bc back to state+20 on completion at 00308580..0030859c. domain_12_value_2 -> BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION: Retail 00308734 stores 2 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION=2 in this function's switch domain. Case7 XY distance<15 enters case2 with animation3; case2 waits for animation completion before entering established action-selection case3. domain_13_value_2 -> BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION: Retail 00308760 stores 2 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION=2 in this function's switch domain. Case7 blocked-path branch also enters case2 with animation3; the same case2 completion handler at 003081bc..003081d4 enters action selection. domain_14_value_5 -> BLARG_SPACE_COMMANDO_FACE_TARGET_AND_PROBE_DURING_ANIMATION: Retail 0030879c stores 5 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_FACE_TARGET_AND_PROBE_DURING_ANIMATION=5 in this function's switch domain. Case7 near-target threshold branch enters case5 with animation6; case5 faces target and sweeps its frame9..15 probe at 003083cc..0030853c. domain_15_value_13 -> BLARG_SPACE_COMMANDO_RETURN_HOME: Retail 003088d8 stores 13 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_RETURN_HOME=13 in this function's switch domain. Case11 with zero pvars+184 enters case13, which computes bearing to saved home+170, moves toward it and exits when within1 at 00308aa8..00308bd4. domain_16_value_12 -> BLARG_SPACE_COMMANDO_PROBE_DURING_ANIMATION_THEN_RESUME_APPROACH: Retail 003088f0 stores 12 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_PROBE_DURING_ANIMATION_THEN_RESUME_APPROACH=12 in this function's switch domain. Case11 nearby path obstruction enters case12 with animation6; case12 probes during inclusive frames9..15 and resumes approach11 at 00308a70..00308a8c. domain_17_value_12 -> BLARG_SPACE_COMMANDO_PROBE_DURING_ANIMATION_THEN_RESUME_APPROACH: Retail 00308948 stores 12 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_PROBE_DURING_ANIMATION_THEN_RESUME_APPROACH=12 in this function's switch domain. Case11 near-target branch saves point+1e0 and enters case12 with animation6; its frame-gated probe resumes established approach11 after completion. domain_18_value_11 -> BLARG_SPACE_COMMANDO_APPROACH_TARGET_UNTIL_BLOCKED_OR_NEAR: Retail 00308a8c stores 11 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_APPROACH_TARGET_UNTIL_BLOCKED_OR_NEAR=11 in this function's switch domain. Case12 anim_flags bit2 completion resumes case11 with animation1; 003087b8..00308960 implements target approach until blocked or near. domain_19_value_1 -> BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION: Retail 00308bd4 stores 1 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION=1 in this function's switch domain. Case13 reaches distance<1 from home+170 and returns to case1 with animation0; case1 faces target and selects actions. domain_1_value_2 -> BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION: Retail 00308118 stores 2 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION=2 in this function's switch domain. Target bearing difference below 0.2617994 selects animation3 and enters case2, whose 003081bc..003081d4 completion gate enters action-selection state3. domain_20_value_1 -> BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION: Retail 00308c10 stores 1 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION=1 in this function's switch domain. Case15 motion result bit0x40 clears the full velocity quadword at 00308c00 and returns to case1 with animation0, whose handler faces target and selects actions. domain_2_value_7 -> BLARG_SPACE_COMMANDO_APPROACH_TARGET_WITH_TURN_OFFSET: Retail 00308144 stores 7 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_APPROACH_TARGET_WITH_TURN_OFFSET=7 in this function's switch domain. The other bearing branch selects animation1 and enters case7, which steers toward target bearing plus pvars+1a8 at 003085a8..0030860c. domain_3_value_5 -> BLARG_SPACE_COMMANDO_FACE_TARGET_AND_PROBE_DURING_ANIMATION: Retail 0030816c stores 5 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_FACE_TARGET_AND_PROBE_DURING_ANIMATION=5 in this function's switch domain. The near-target branch selects animation6 and enters case5, which faces target and performs the frame9..15 swept probe at 003083cc..0030853c. domain_4_value_11 -> BLARG_SPACE_COMMANDO_APPROACH_TARGET_UNTIL_BLOCKED_OR_NEAR: Retail 003081a0 stores 11 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_APPROACH_TARGET_UNTIL_BLOCKED_OR_NEAR=11 in this function's switch domain. Mode2 with nonzero pvars+184 enters case11, whose 003087b8..00308960 movement and path checks approach the target until blocked or near. domain_5_value_3 -> BLARG_SPACE_COMMANDO_SELECT_ACTION_AFTER_ANIMATION: Retail 003081d4 stores 3 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_SELECT_ACTION_AFTER_ANIMATION=3 in this function's switch domain. Case2 tests anim_flags bit2 then calls 00309370 and enters case3, which selects timer-wait state4 or target-facing state1 at 00308200..00308294. domain_6_value_4 -> BLARG_SPACE_COMMANDO_FACE_TARGET_AND_WAIT_FOR_TIMER: Retail 00308250 stores 4 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_FACE_TARGET_AND_WAIT_FOR_TIMER=4 in this function's switch domain. Case3 completion with mode!=2 and XY distance<15 selects animation4 and initializes pvars+194 countdown at 00308270..0030827c; case4 faces target and ticks it. domain_7_value_1 -> BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION: Retail 0030828c stores 1 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION=1 in this function's switch domain. Case3 alternative returns to case1 and animation0; 00308038..003081b8 faces target and chooses the subsequent action. domain_8_value_3 -> BLARG_SPACE_COMMANDO_SELECT_ACTION_AFTER_ANIMATION: Retail 00308314 stores 3 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_SELECT_ACTION_AFTER_ANIMATION=3 in this function's switch domain. Expiration of pvars+194 at 003082fc..00308304 enters case3 and invokes 00309370, matching the established animation-gated action selector. domain_9_value_5 -> BLARG_SPACE_COMMANDO_FACE_TARGET_AND_PROBE_DURING_ANIMATION: Retail 0030837c stores 5 to 0x20(s2), the identical moby state byte loaded for dispatch at 00307f30..00307f50. Current C assigns moby->state and already declares BLARG_SPACE_COMMANDO_FACE_TARGET_AND_PROBE_DURING_ANIMATION=5 in this function's switch domain. Near-target exit from timer wait initializes pvars+1e0 and animation6, then case5 faces target and performs the animation-frame-gated swept probe. --- src/overlays/l13/mobys/blarg_space_commando.c | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/overlays/l13/mobys/blarg_space_commando.c b/src/overlays/l13/mobys/blarg_space_commando.c index f7a065a698..a95d642bd7 100644 --- a/src/overlays/l13/mobys/blarg_space_commando.c +++ b/src/overlays/l13/mobys/blarg_space_commando.c @@ -221,7 +221,7 @@ void blarg_space_commando_update(struct Moby *moby) { random_float_between(0.95f, 1.05f); qcopy(&blarg_space_commando_vars->home, &moby->pos); moby_point_position(moby, 0, &blarg_space_commando_vars->unk1E0); - moby->state = 1; + moby->state = BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION; break; case BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION: approach_angle(&moby->rot.z, @@ -237,24 +237,24 @@ void blarg_space_commando_update(struct Moby *moby) { moby->rot.z, fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y)) < 0.2617994f) { - moby->state = 2; + moby->state = BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION; if (moby->prev_seq != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } } else { - moby->state = 7; + moby->state = BLARG_SPACE_COMMANDO_APPROACH_TARGET_WITH_TURN_OFFSET; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(20)); } } } else { - moby->state = 5; + moby->state = BLARG_SPACE_COMMANDO_FACE_TARGET_AND_PROBE_DURING_ANIMATION; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(10)); } } } else if (blarg_space_commando_vars->unk184 != 0) { - moby->state = 11; + moby->state = BLARG_SPACE_COMMANDO_APPROACH_TARGET_UNTIL_BLOCKED_OR_NEAR; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(20)); } @@ -262,7 +262,7 @@ void blarg_space_commando_update(struct Moby *moby) { break; case BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION: if (moby->anim_flags & 2) { - moby->state = 3; + moby->state = BLARG_SPACE_COMMANDO_SELECT_ACTION_AFTER_ANIMATION; FUN_L13_00309370_c((char *)moby); if (moby->prev_seq != 5) { blend_moby_animation(moby, 5, 0, scale_game_frames(10)); @@ -273,14 +273,14 @@ void blarg_space_commando_update(struct Moby *moby) { if (moby->anim_flags & 2) { f32 dist = vector_distance_xy(&moby->pos, &target->pos); if (blarg_space_commando_vars->unk164 != 2 && dist < 15.0f) { - moby->state = 4; + moby->state = BLARG_SPACE_COMMANDO_FACE_TARGET_AND_WAIT_FOR_TIMER; if (moby->prev_seq != 4) { blend_moby_animation(moby, 4, 0, scale_game_frames(20)); } blarg_space_commando_vars->timer = scale_game_frames(blarg_space_commando_face_target_wait_frames); } else { - moby->state = 1; + moby->state = BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(20)); } @@ -295,7 +295,7 @@ void blarg_space_commando_update(struct Moby *moby) { frame_time_sq * 6.2831855f, frame_time * 3.1415927f); if (fast_dec_timer(&blarg_space_commando_vars->timer) != 0) { - moby->state = 3; + moby->state = BLARG_SPACE_COMMANDO_SELECT_ACTION_AFTER_ANIMATION; FUN_L13_00309370_c((char *)moby); if (moby->prev_seq != 5) { blend_moby_animation(moby, 5, 0, scale_game_frames(5)); @@ -303,12 +303,12 @@ void blarg_space_commando_update(struct Moby *moby) { } else if (vector_distance_xy(&moby->pos, &target->pos) < l13_blarg_space_commando_probe_trigger_distance_xy) { moby_point_position(moby, 0, &blarg_space_commando_vars->unk1E0); - moby->state = 5; + moby->state = BLARG_SPACE_COMMANDO_FACE_TARGET_AND_PROBE_DURING_ANIMATION; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(10)); } } else if (blarg_space_commando_vars->unk184 != 0) { - moby->state = 11; + moby->state = BLARG_SPACE_COMMANDO_APPROACH_TARGET_UNTIL_BLOCKED_OR_NEAR; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(20)); } @@ -341,7 +341,7 @@ void blarg_space_commando_update(struct Moby *moby) { } qcopy(&blarg_space_commando_vars->unk1E0, &point); if (moby->anim_flags & 2) { - moby->state = 6; + moby->state = BLARG_SPACE_COMMANDO_RESUME_SAVED_STATE_AFTER_ANIMATION; moby->command = 1; if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(10)); @@ -385,17 +385,17 @@ void blarg_space_commando_update(struct Moby *moby) { { f32 dist = vector_distance_xy(&moby->pos, &target->pos); if (dist < 15.0f) { - moby->state = 2; + moby->state = BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION; if (moby->prev_seq != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } } else if (path_blocked != 0) { - moby->state = 2; + moby->state = BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION; if (moby->prev_seq != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } } else if (dist < l13_blarg_space_commando_probe_trigger_distance_xy) { - moby->state = 5; + moby->state = BLARG_SPACE_COMMANDO_FACE_TARGET_AND_PROBE_DURING_ANIMATION; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(10)); } @@ -423,16 +423,16 @@ void blarg_space_commando_update(struct Moby *moby) { blocked = 1; } if (blarg_space_commando_vars->unk184 == 0) { - moby->state = 13; + moby->state = BLARG_SPACE_COMMANDO_RETURN_HOME; } else if (blocked != 0) { - moby->state = 12; + moby->state = BLARG_SPACE_COMMANDO_PROBE_DURING_ANIMATION_THEN_RESUME_APPROACH; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(10)); } } else if (vector_distance_xy(&moby->pos, &target->pos) < l13_blarg_space_commando_probe_trigger_distance_xy) { moby_point_position(moby, 0, &blarg_space_commando_vars->unk1E0); - moby->state = 12; + moby->state = BLARG_SPACE_COMMANDO_PROBE_DURING_ANIMATION_THEN_RESUME_APPROACH; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(10)); } @@ -459,7 +459,7 @@ void blarg_space_commando_update(struct Moby *moby) { } qcopy(&blarg_space_commando_vars->unk1E0, &point); if (moby->anim_flags & 2) { - moby->state = 11; + moby->state = BLARG_SPACE_COMMANDO_APPROACH_TARGET_UNTIL_BLOCKED_OR_NEAR; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(20)); } @@ -485,7 +485,7 @@ void blarg_space_commando_update(struct Moby *moby) { blarg_space_commando_vars->path, &moby->pos, &moby->pos, 0.75f); } if (fast_vec_dist(&blarg_space_commando_vars->home, &moby->pos) < 1.0f) { - moby->state = 1; + moby->state = BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(20)); } @@ -495,7 +495,7 @@ void blarg_space_commando_update(struct Moby *moby) { hit = step_moby_motion(moby, &blarg_space_commando_vars->vel); if (hit & 0x40) { qzero(&blarg_space_commando_vars->vel); - moby->state = 1; + moby->state = BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } From ad81c14a19d836bd04ae3eca04b095c3ac439796 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:18:48 +0000 Subject: [PATCH 1096/1502] decomp: clarify names in update_plasmabot domain_2_value_4 -> PLASMABOT_AIM_AT_TARGET: The authoritative C assigns state from ((unsigned char *)moby)[0x20], the exact byte used by the switch with existing PLASMABOT_AIM_AT_TARGET=4. Retail 0x002b2590 loads v1 from 0x20(s2), then 0x002b2594 subtracts 4 and 0x002b2598 tests the four-state range. Original Ghidra uVar11 follows the same byte load. Thus the lower bound is the existing plasmabot aiming-state member, not HERO_STATE_CROUCH. domain_3_value_7 -> PLASMABOT_WAIT_ANIMATION_BEFORE_AIM: The final C state<=7 tests the same moby+0x20 state byte as the named switch. Existing PLASMABOT_WAIT_ANIMATION_BEFORE_AIM=7 is the inclusive upper bound. Retail 0x002b2590..0x002b259c implements the inclusive states 4 through 7 as unsigned (state-4)<4; case 7 at 0x002b23c0..0x002b23f8 waits for animation completion before returning to aiming state 4. This is the plasmabot state domain, not the hero jump domain. domain_4_value_1 -> PLASMABOT_WAIT_TO_START_PATH_TRAVERSAL: C state is loaded directly from moby+0x20, matching the switch selector whose existing member PLASMABOT_WAIT_TO_START_PATH_TRAVERSAL=1 names this exact domain. Retail 0x002b25a0 loads 1 and 0x002b25a4 excludes that state from the common aim reset. The corresponding case 0x002b1b90..0x002b1bc8 waits on gates before entering path-start state 2 at 0x002b1be4. Original Ghidra uVar11!=1 agrees; hero look and control-mode constants do not apply. --- src/overlays/shared/enemies/plasmabot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/plasmabot.c b/src/overlays/shared/enemies/plasmabot.c index a0b7a9d3ee..f8871b5c70 100644 --- a/src/overlays/shared/enemies/plasmabot.c +++ b/src/overlays/shared/enemies/plasmabot.c @@ -794,7 +794,7 @@ void plasmabot_update(char *moby) { } } state = ((unsigned char *)moby)[0x20]; - if (!(state >= 4 && state <= 7) && state != 1) { + if (!(state >= PLASMABOT_AIM_AT_TARGET && state <= PLASMABOT_WAIT_ANIMATION_BEFORE_AIM) && state != PLASMABOT_WAIT_TO_START_PATH_TRAVERSAL) { update_plasmabot_aim_quaternion(moby, 0, MOBY(moby)->rot.z); update_plasmabot_aim_joint_rotation(moby, MOBY(moby)->rot.z); } From 952035804d3367aa84d3f82565acbe831540ad62 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:18:48 +0000 Subject: [PATCH 1097/1502] decomp: clarify names in update_fighter_jet_flight domain_0_value_7 -> FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY: Retail 0x002ec388 preserves the first ship-moby argument in s3; 0x002ecdd8-0x002ecdec subtracts collision damage from hero ship HP and tests for HP below zero. After explosion call 0x002eceb8, 0x002ecec0-0x002ecec4 stores 7 to s3+0x20, the same moby state consumed by fighter_jet_update, which passes this moby to update_fighter_jet_flight. The supplied caller source explicitly defines FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY=7; its case ticks ship_vars->hit_timer, invokes hero_respawn and resets the moby. This establishes the fighter-jet state domain and canonical existing name. domain_1_value_7 -> FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY: Retail 0x002ecda0-0x002ecdb4 routes no-moby/class-0x15B collisions to 0x002eced4; 0x002ecf24 zeros hero ship HP and 0x002ecf3c invokes the explosion helper. At 0x002ecf44-0x002ecf50 the respawn delay is stored at vars+0x62 and 7 is stored at s3+0x20. s3 is the incoming fighter-jet moby (0x002ec388), passed by fighter_jet_update; supplied caller source maps vars+0x62 to hit_timer and names its state-7 handler FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY, which waits on that timer then calls hero_respawn. Reuse that existing same-domain state name. --- src/overlays/l17/mobys/fighter_jet.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l17/mobys/fighter_jet.c b/src/overlays/l17/mobys/fighter_jet.c index fda368df6a..4074fdf563 100644 --- a/src/overlays/l17/mobys/fighter_jet.c +++ b/src/overlays/l17/mobys/fighter_jet.c @@ -1197,6 +1197,9 @@ void update_fighter_jet_flight(FighterJetMoby *ship_moby, FighterJetVars *ship_vars) __asm__("FUN_L17_002ec360"); void update_fighter_jet_flight(FighterJetMoby *ship_moby, FighterJetVars *ship_vars) { + enum { + FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY = 7 + }; sceVu0FVECTOR pre_movement_ship_position; sceVu0FVECTOR death_explosion_velocity; UQ_c4 movement_delta; @@ -1544,7 +1547,7 @@ void update_fighter_jet_flight(FighterJetMoby *ship_moby, FighterJetVars *ship_v 1, -1, 0); - ship_moby->state = 7; + ship_moby->state = FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY; } ship_vars->iDC = D_L17_0016215C; } @@ -1569,7 +1572,7 @@ void update_fighter_jet_flight(FighterJetMoby *ship_moby, FighterJetVars *ship_v -1, 0); ship_vars->s62 = l17_fighter_jet_collision_death_respawn_delay; - ship_moby->state = 7; + ship_moby->state = FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY; ship_moby->flags |= 0x41; } } From 81f47c7fdd0bd89f9aa90ffbd56654053e72a245 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:18:48 +0000 Subject: [PATCH 1098/1502] decomp: clarify names in sound_update domain_11_value_7 -> VOICE_SLOT_START_QUEUED: Retail 0x0022ce88-0x0022cea8 checks game mode separately, then loads voice-slot state at pool+0x74 and exempts state 7 from status-only flag 0x10. That same slot state selects the new-play request at 0x0022d5f4-0x0022d664, proving VOICE_SLOT_START_QUEUED rather than a game-mode value. domain_12_value_7 -> VOICE_SLOT_START_QUEUED: Retail 0x0022d194-0x0022d1a0 reads the voice-slot state at pool+0x74, using the 0x70-byte slot offset, and selects initial six-sample occlusion history for state 7. The same state byte selects the new sound submission at 0x0022d5f4-0x0022d664, proving the canonical queued-start state. domain_17_value_7 -> VOICE_SLOT_START_QUEUED: Retail 0x0022d4c4-0x0022d4e0 tests voice-slot state 7 on the stop-command path and clears state, owner and owner context without sending a stop request. Other states call snd_stop_sound. Together with the state-7 new-play path at 0x0022d62c-0x0022d664, this proves a queued, unstarted voice. domain_18_value_7 -> VOICE_SLOT_START_QUEUED: Retail 0x0022d5ec-0x0022d5f8 loads the same voice-slot state byte and branches on 7. Non-7 calls snd_set_sound_params_cb at 0x0022d61c; state 7 becomes 1 and calls snd_play_sound_vol_pan_pmpb at 0x0022d660. This directly proves the existing VOICE_SLOT_START_QUEUED constant. domain_3_value_7 -> VOICE_SLOT_START_QUEUED: Retail 0x0022cdf0-0x0022ce18 reads the voice-slot state byte at pool+0x74 with a 0x70-byte stride. State 7 bypasses the valid-handle requirement; 0x0022d5f4-0x0022d664 later submits snd_play_sound_vol_pan_pmpb for that same slot state, proving the established queued-start domain. domain_6_value_4 -> VOICE_SLOT_STOP_REQUESTED: Retail 0x0022ce4c-0x0022ce84 loads the same voice-slot state at pool+0x74 and sets command flag 0x20 for state 4. At 0x0022d4b4-0x0022d50c that flag stops the sound and sets slot state 6 pending the playing-status callback, proving VOICE_SLOT_STOP_REQUESTED. domain_7_value_6 -> VOICE_SLOT_STOP_PENDING: Retail 0x0022ce58-0x0022ce78 exempts voice-slot state 6 from another owner-removal stop request. The same slot state byte is written with 6 at 0x0022d4ec-0x0022d508 after snd_stop_sound and before snd_sound_is_still_playing_cb, proving the established VOICE_SLOT_STOP_PENDING member. --- src/audio/voices/sound_update.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/audio/voices/sound_update.c b/src/audio/voices/sound_update.c index f82d5fa629..a416cf438e 100644 --- a/src/audio/voices/sound_update.c +++ b/src/audio/voices/sound_update.c @@ -145,7 +145,7 @@ s32 sound_update(void) { for (slot_index = 0; slot_index < 30; slot_index++) { { s32 state = voice_pool.voices[slot_index].state; - if (state != 7) { + if (state != VOICE_SLOT_START_QUEUED) { if (voice_pool.voices[slot_index].handle == 0) { continue; } @@ -172,7 +172,7 @@ s32 sound_update(void) { } { s32 state = voice_pool.voices[slot_index].state; - if (state == 4 || (state != 6 && owner_removed && + if (state == VOICE_SLOT_STOP_REQUESTED || (state != VOICE_SLOT_STOP_PENDING && owner_removed && voice_pool.voices[slot_index].definition->source_state != 0)) { voice_flags[slot_index] = 0x20; continue; @@ -180,7 +180,7 @@ s32 sound_update(void) { } if (game_mode != 0 && game_mode != 2 && game_mode != 6) { s32 state = voice_pool.voices[slot_index].state; - if (state != 7) { + if (state != VOICE_SLOT_START_QUEUED) { voice_flags[slot_index] = 0x10; continue; } @@ -252,7 +252,7 @@ s32 sound_update(void) { } { s32 state = voice_pool.voices[slot_index].state; - if (state == 7) { + if (state == VOICE_SLOT_START_QUEUED) { if ((game_mode != 0 && game_mode != 2) || boot_level_active != 0) { continue; } @@ -342,7 +342,7 @@ s32 sound_update(void) { if (command_flags & 0x20) { { s32 state = voice_pool.voices[slot_index].state; - if (state == 7) { + if (state == VOICE_SLOT_START_QUEUED) { voice_pool.voices[slot_index].owner = NULL; voice_pool.voices[slot_index].owner_context = 0; voice_pool.voices[slot_index].state = 0; @@ -378,7 +378,7 @@ s32 sound_update(void) { } { s32 state = voice_pool.voices[slot_index].state; - if (state != 7) { + if (state != VOICE_SLOT_START_QUEUED) { snd_set_sound_params_cb(handle, parameter_mask, voice_volumes[slot_index], From 6961a226e0cb5d81f23176c3306d7c755d1de5f0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:18:49 +0000 Subject: [PATCH 1099/1502] decomp: clarify names in update_drone domain_0_value_5 -> DRONE_STATE_REMOVE: The selector is the drone Moby state byte at +0x20 (entry moby retained in s5), not hero.state.current. Retail 002cf174-002cf190 subtracts four from alpha and assigns 5 below six; dispatch 002ce7f4 reaches 002cf194-002cf1b8, which decrements the hero drone count, clears slots[drone_vars->slot], and calls mark_moby_for_removal. Thus 5 is removal; the <5 gate excludes this cleanup state. domain_10_value_2 -> DRONE_STATE_ORBIT: The local state is loaded from updated_moby->state, retail lbu at 002ce7c0. Comparison 2 at 002ce7d4-002ce7dc dispatches to 002ce804, where 002ce868-002ce940 combines desired yaw with hero drone phase and rotates an offset; 002ce948-002ce9bc adds it to hero position and computes movement. Source state2 confirms orbit around the hero. Invalid pursuit targets reset the same state byte to 2 at 002cf028-002cf038 while clearing target and target_oclass, returning the drone to orbit. domain_11_value_4 -> DRONE_STATE_FADE: Retail 002ce3a8 loads drone pvars from entry moby+0x78; 002ce7bc, 002cec38 and 002cf024 assign 4 to its +0x20 state following hit handling. Dispatch 002ce7ec sends that state to 002cf088, where valid targets may still be tracked but 002cf174-002cf190 always decrements alpha and transitions to removal below six. The slot loop proves oclass 0x1DF at 002ce484-002ce488 before its state<4 test at 002ce4b4-002ce4cc. Both <4 comparisons therefore use the fade boundary in the drone state domain. domain_12_value_5 -> DRONE_STATE_REMOVE: The selector is the drone Moby state byte at +0x20 (entry moby retained in s5), not hero.state.current. Retail 002cf174-002cf190 subtracts four from alpha and assigns 5 below six; dispatch 002ce7f4 reaches 002cf194-002cf1b8, which decrements the hero drone count, clears slots[drone_vars->slot], and calls mark_moby_for_removal. Thus 5 is removal; the <5 gate excludes this cleanup state. domain_13_value_4 -> DRONE_STATE_FADE: Retail 002ce3a8 loads drone pvars from entry moby+0x78; 002ce7bc, 002cec38 and 002cf024 assign 4 to its +0x20 state following hit handling. Dispatch 002ce7ec sends that state to 002cf088, where valid targets may still be tracked but 002cf174-002cf190 always decrements alpha and transitions to removal below six. The slot loop proves oclass 0x1DF at 002ce484-002ce488 before its state<4 test at 002ce4b4-002ce4cc. Both <4 comparisons therefore use the fade boundary in the drone state domain. domain_18_value_4 -> DRONE_STATE_FADE: Retail 002ce3a8 loads drone pvars from entry moby+0x78; 002ce7bc, 002cec38 and 002cf024 assign 4 to its +0x20 state following hit handling. Dispatch 002ce7ec sends that state to 002cf088, where valid targets may still be tracked but 002cf174-002cf190 always decrements alpha and transitions to removal below six. The slot loop proves oclass 0x1DF at 002ce484-002ce488 before its state<4 test at 002ce4b4-002ce4cc. Both <4 comparisons therefore use the fade boundary in the drone state domain. domain_19_value_2 -> DRONE_STATE_ORBIT: The local state is loaded from updated_moby->state, retail lbu at 002ce7c0. Comparison 2 at 002ce7d4-002ce7dc dispatches to 002ce804, where 002ce868-002ce940 combines desired yaw with hero drone phase and rotates an offset; 002ce948-002ce9bc adds it to hero position and computes movement. Source state2 confirms orbit around the hero. Invalid pursuit targets reset the same state byte to 2 at 002cf028-002cf038 while clearing target and target_oclass, returning the drone to orbit. domain_22_value_5 -> DRONE_STATE_REMOVE: The selector is the drone Moby state byte at +0x20 (entry moby retained in s5), not hero.state.current. Retail 002cf174-002cf190 subtracts four from alpha and assigns 5 below six; dispatch 002ce7f4 reaches 002cf194-002cf1b8, which decrements the hero drone count, clears slots[drone_vars->slot], and calls mark_moby_for_removal. Thus 5 is removal; the <5 gate excludes this cleanup state. domain_3_value_4 -> DRONE_STATE_FADE: Retail 002ce3a8 loads drone pvars from entry moby+0x78; 002ce7bc, 002cec38 and 002cf024 assign 4 to its +0x20 state following hit handling. Dispatch 002ce7ec sends that state to 002cf088, where valid targets may still be tracked but 002cf174-002cf190 always decrements alpha and transitions to removal below six. The slot loop proves oclass 0x1DF at 002ce484-002ce488 before its state<4 test at 002ce4b4-002ce4cc. Both <4 comparisons therefore use the fade boundary in the drone state domain. domain_6_value_3 -> DRONE_STATE_PURSUE_TARGET: Retail 002ce600-002ce65c takes the nearest available slot drone, stores selected_target_moby in pvars+0x30, its oclass in +0x48 and adjusted position in +0x10, then assigns state 3 to that drone's +0x20. The dispatch at 002ce7c4-002ce7c8 reaches 002ced0c: 002ced6c-002cedd0 validates this same target, 002cedec-002cee64 predicts its position from the prior offset and moves the drone toward it. Source state3 and original retail decompilation confirm target pursuit and collision handling. domain_7_value_4 -> DRONE_STATE_FADE: Retail 002ce3a8 loads drone pvars from entry moby+0x78; 002ce7bc, 002cec38 and 002cf024 assign 4 to its +0x20 state following hit handling. Dispatch 002ce7ec sends that state to 002cf088, where valid targets may still be tracked but 002cf174-002cf190 always decrements alpha and transitions to removal below six. The slot loop proves oclass 0x1DF at 002ce484-002ce488 before its state<4 test at 002ce4b4-002ce4cc. Both <4 comparisons therefore use the fade boundary in the drone state domain. domain_8_value_3 -> DRONE_STATE_PURSUE_TARGET: Retail 002ce600-002ce65c takes the nearest available slot drone, stores selected_target_moby in pvars+0x30, its oclass in +0x48 and adjusted position in +0x10, then assigns state 3 to that drone's +0x20. The dispatch at 002ce7c4-002ce7c8 reaches 002ced0c: 002ced6c-002cedd0 validates this same target, 002cedec-002cee64 predicts its position from the prior offset and moves the drone toward it. Source state3 and original retail decompilation confirm target pursuit and collision handling. domain_9_value_4 -> DRONE_STATE_FADE: Retail 002ce3a8 loads drone pvars from entry moby+0x78; 002ce7bc, 002cec38 and 002cf024 assign 4 to its +0x20 state following hit handling. Dispatch 002ce7ec sends that state to 002cf088, where valid targets may still be tracked but 002cf174-002cf190 always decrements alpha and transitions to removal below six. The slot loop proves oclass 0x1DF at 002ce484-002ce488 before its state<4 test at 002ce4b4-002ce4cc. Both <4 comparisons therefore use the fade boundary in the drone state domain. --- src/overlays/shared/weapons/drone.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/overlays/shared/weapons/drone.c b/src/overlays/shared/weapons/drone.c index 892b72e1b8..2c98cf3399 100644 --- a/src/overlays/shared/weapons/drone.c +++ b/src/overlays/shared/weapons/drone.c @@ -351,7 +351,7 @@ void drone_update(struct Moby *updated_moby) __asm__("FUN_L00_002ce358"); /* Moby class 479 */ void drone_update(struct Moby *updated_moby) { - DroneVars *drone_vars = (DroneVars *)updated_moby->pvars; + enum { DRONE_STATE_ORBIT = 2 , DRONE_STATE_PURSUE_TARGET = 3 , DRONE_STATE_FADE = 4 , DRONE_STATE_REMOVE = 5 } ;DroneVars *drone_vars = (DroneVars *)updated_moby->pvars; Vec4 collision_data[1], old_pos; Vec4 direction, rotated; Vec4 target_pos, matrix[4]; @@ -370,7 +370,7 @@ void drone_update(struct Moby *updated_moby) { return; } updated_moby->flags &= 0xFFBE; - if (updated_moby->state < 5) { + if (updated_moby->state < DRONE_STATE_REMOVE) { ((DroneSlots *)&hero)->counter++; if (((DroneSlots *)&hero)->ammo_used < ((DroneSlots *)&hero)->counter) { closest = 0; @@ -392,7 +392,7 @@ void drone_update(struct Moby *updated_moby) { ((DroneSlots *)&hero)->exclusions[count] = *(struct Moby **)(drone->pvars + 0x30); count++; - if (drone->state < 4) + if (drone->state < DRONE_STATE_FADE) ((DroneSlots *)&hero)->ammo_capacity++; if (count > 8) break; @@ -436,7 +436,7 @@ void drone_update(struct Moby *updated_moby) { if (target_height_data != 0) old_pos.f[2] += *(f32 *)(target_height_data + 0x10); qcopy(&assigned->offset, &old_pos); - closest->state = 3; + closest->state = DRONE_STATE_PURSUE_TARGET; random = rand_2cc608() % 3; allocate_voice_for_target_entry(random + (random > 0), 0, updated_moby); ((DroneSlots *)&hero)->exclusions[count] = assigned->target; @@ -468,22 +468,22 @@ void drone_update(struct Moby *updated_moby) { if (cat >= 5) { if (hit == 0 || h == 0 || *(s16 *)(h + 0xA6) != 0x4D6 || fast_dec_timer_s16(&drone_vars->health)) - updated_moby->state = 4; + updated_moby->state = DRONE_STATE_FADE; } } } } dispatch_state: state = updated_moby->state; - if (state == 3) + if (state == DRONE_STATE_PURSUE_TARGET) goto state3; - if (state < 4) { - if (state == 2) + if (state < DRONE_STATE_FADE) { + if (state == DRONE_STATE_ORBIT) goto state2; } else { - if (state == 4) + if (state == DRONE_STATE_FADE) goto state4; - if (state == 5) + if (state == DRONE_STATE_REMOVE) goto state5; } goto update_effects; @@ -574,7 +574,7 @@ state2: { 1, -1, 0); - updated_moby->state = 4; + updated_moby->state = DRONE_STATE_FADE; } } } @@ -667,13 +667,13 @@ state3: { 1, -1, 0); - updated_moby->state = 4; + updated_moby->state = DRONE_STATE_FADE; } } } } } else { - updated_moby->state = 2; + updated_moby->state = DRONE_STATE_ORBIT; drone_vars->target_oclass = -1; drone_vars->target = 0; } @@ -709,7 +709,7 @@ state4: { fade_alpha: updated_moby->alpha -= 4; if (updated_moby->alpha < 6) - updated_moby->state = 5; + updated_moby->state = DRONE_STATE_REMOVE; goto update_effects; } state5: { From ea51738211736e83261c7d35f05b8732280c0324 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:18:49 +0000 Subject: [PATCH 1100/1502] decomp: clarify names in turret_update domain_0_value_4 -> TURRET_STATE_IDLE: Retail 00304c94 binds the argument Moby to s2; 00304cec loads its state byte +0x20 and 00304cf4 tests the 4 lower bound. This is the identical selector loaded at 00304f58 and dispatched by 00304f5c-00304f60 to 00304fec, the source's existing TURRET_STATE_IDLE branch managing proximity tracking and beam lighting. Reuse the existing enum member as the >= bound without altering the comparison. domain_1_value_4 -> TURRET_STATE_IDLE: Retail 00304dd8 calls jet_end_mount and 00304de4 resets hero state; 00304df0 loads 4 and 00304dfc stores it to the same turret Moby +0x20 used by the switch at 00304f58-00304f60. That dispatch selects the established TURRET_STATE_IDLE branch at 00304fec; source likewise returns to idle after mount-exit input, separately setting command +0xbc to 2. domain_2_value_5 -> TURRET_STATE_MOUNTED: Retail 00304dd4 reads turret Moby state +0x20; 00304e18 loads 5 and 00304e1c skips mount setup when already equal. Otherwise 00304e28 sets dismount delay and 00304e38 calls jet_mount. This state byte is later dispatched at 00304f80 to 00305218, the source's existing TURRET_STATE_MOUNTED branch consuming hero stick input, firing barrels and updating the camera. domain_3_value_5 -> TURRET_STATE_MOUNTED: After jet_mount at retail 00304e38 and mount animation setup, 00304e68 loads 5 and 00304e70 stores it to turret Moby state +0x20. The same byte is read at 00304f58 and value 5 dispatches at 00304f80 to 00305218, matching the existing TURRET_STATE_MOUNTED enum branch for aiming, firing and mounted camera handling. domain_4_value_4 -> TURRET_STATE_IDLE: Retail initialization dispatch 00304f90 attaches the manipulator and 00304fac spawns the turret base. Register s0 contains 4 from 00304f5c; 00304fbc stores s0 to turret Moby state +0x20 while initialization records rest height and clears beam/setup fields. Subsequent value-4 dispatch at 00304f60 enters 00304fec, already named TURRET_STATE_IDLE in the authoritative source enum and switch. --- src/overlays/l09/mobys/turret.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l09/mobys/turret.c b/src/overlays/l09/mobys/turret.c index d4c2eb13fc..78f6ea2e53 100644 --- a/src/overlays/l09/mobys/turret.c +++ b/src/overlays/l09/mobys/turret.c @@ -113,7 +113,7 @@ void turret_update(struct Moby *moby) { moby->flags &= ~4; moby_point_position(moby, 3, &seat); seat.f[2] += 0.4f; - if (moby->state >= 4) { + if (moby->state >= TURRET_STATE_IDLE) { if (fast_dec_timer_s16(&turret_vars->mount_delay) != 0 && moby->command == 1 && hero.state.control_mode != 0x14 && hero.state.control_mode != 7 && hero.state.current != 0x3D) { @@ -129,17 +129,17 @@ void turret_update(struct Moby *moby) { jet_end_mount(0); hero_set_state(0, 1); moby->command = 2; - moby->state = 4; + moby->state = TURRET_STATE_IDLE; blend_moby_animation(moby, 0, 0, 1); } else { - if (moby->state != 5) { + if (moby->state != TURRET_STATE_MOUNTED) { turret_vars->dismount_delay = 2; jet_mount(&moby->pos, &moby->rot, 0, 0, 0); if (moby->prev_seq != 5) { blend_moby_animation(moby, 5, 0, scale_game_frames(5)); } } - moby->state = 5; + moby->state = TURRET_STATE_MOUNTED; } } else if (moby->command == 2) { if (fast_vec_dist(&seat, &hero.moby->pos) > 1.2f || hero.ground_moby != moby) { @@ -158,7 +158,7 @@ void turret_update(struct Moby *moby) { attach_manipulator(moby, 0, turret_vars); work_vector.q = *(u128 *)&moby->pos; spawn_turret_base(moby, &work_vector); - moby->state = 4; + moby->state = TURRET_STATE_IDLE; turret_vars->rest_z = moby->pos.z; turret_vars->pitch = 0.0f; moby->rot.z = 0.0f; From 65cb47e8c6f4b231406ee4ae711e4aa176933f81 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:20:53 +0000 Subject: [PATCH 1101/1502] decomp: clarify names in constructorbot_update domain_0_value_7 -> L02_BOT_SELECT_ATTACK_OR_WANDER: Initialization default enters state 7 through retail 0x002d7918-0x002d792c and shared store 0x002d7c00-0x002d7c08; its handler at 0x002d7c98-0x002d7eb0 chooses attack preparation, post movement or random wandering. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_10_value_11 -> L02_BOT_WAIT_FOR_ANIMATION_BEFORE_ATTACK: Retail 0x002d7d90-0x002d7dc8 checks target-facing angle and stores 11 to owner+0x20; state 11 at 0x002d8088-0x002d8110 faces target and waits for animation completion before shot state 12. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_11_value_5 -> L02_BOT_MOVE_TO_POST: Failed distance-to-post test branches to 0x002d7de4-0x002d7df0 and stores 5 to owner+0x20; state 5 walks to the post cuboid at 0x002d7b6c-0x002d7b90. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_12_value_6 -> L02_BOT_WANDER: Retail 0x002d7e1c-0x002d7e9c constructs a random planar destination at pvars+0x1e0 around the post, then stores state 6 at 0x002d7eb0; handler 0x002d7bb4 walks to that destination. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_13_value_8 -> L02_BOT_WAIT_FOR_WAKE_TRIGGER_BEFORE_GROUND_ALIGNMENT: Retail 0x002d7fe8-0x002d7ff0 compares owner+0x20 with 8 after the wake gate; this branch selects animation 4 and state 2 before the ground-alignment state 3. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_14_value_2 -> L02_BOT_WAIT_FOR_WAKE_ANIMATION: State-8 wake branch selects animation 4 at 0x002d8008-0x002d801c and joins state-2 store at 0x002d8054-0x002d805c; state 2 waits on animation completion at 0x002d79a4. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_15_value_9 -> L02_BOT_WAIT_FOR_WAKE_TRIGGER_WITH_ALTERNATE_WAKE_ANIMATION: Retail 0x002d8020 compares the same owner+0x20 state byte with 9 after wake gating; its branch selects animation 16 instead of state 8's animation 4, then enters state 2. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_16_value_2 -> L02_BOT_WAIT_FOR_WAKE_ANIMATION: State-9 wake branch selects animation 16 at 0x002d8038-0x002d8050 and stores 2 at 0x002d805c; state 2 waits for anim_flags bit 2 before advancing to ground alignment. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_17_value_5 -> L02_BOT_MOVE_TO_POST: The remaining wake-trigger branch loads 5 at 0x002d8024 and stores it to owner+0x20 at 0x002d806c; state 5 walks toward the post cuboid position at 0x002d7b6c-0x002d7b90. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_18_value_12 -> L02_BOT_UPDATE_ATTACK_SHOTS: Retail 0x002d80e8-0x002d8110 checks animation completion and stores 12 to owner+0x20; state 12 updates shot slots and constructs a hit descriptor at 0x002d8144-0x002d8224. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_19_value_13 -> L02_BOT_WAIT_FOR_ANIMATION_BEFORE_ATTACK_RECHECK: Retail 0x002d8228-0x002d823c stores 13 on attack animation completion; state 13 at 0x002d82a0-0x002d83b0 faces target and waits for completion before range/height recheck. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_1_value_10 -> L02_BOT_WAIT_FOR_WAKE_TRIGGER: Retail 0x002d794c-0x002d7954 stores 10 to owner+0x20 for start mode 1; state 10 executes the volume/distance wake gate at 0x002d7f8c-0x002d7fe4. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_20_value_12 -> L02_BOT_UPDATE_ATTACK_SHOTS: Attack recheck range and height tests at 0x002d8304-0x002d835c load 12, stored at 0x002d8370; established state 12 updates tracked attack shots and their hit descriptor. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_21_value_7 -> L02_BOT_SELECT_ATTACK_OR_WANDER: Failed attack recheck gates at 0x002d832c/0x002d835c reach shared store of state 7 at 0x002d83a4-0x002d83b0, returning to the established attack/wander selection handler. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_22_value_7 -> L02_BOT_SELECT_ATTACK_OR_WANDER: Hit knockback motion completion mask 0x40 at 0x002d838c-0x002d839c reaches state-7 store at 0x002d83a4-0x002d83b0, restoring attack/wander selection. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_2_value_8 -> L02_BOT_WAIT_FOR_WAKE_TRIGGER_BEFORE_GROUND_ALIGNMENT: Retail 0x002d7958-0x002d7978 selects animation 2 then stores 8 to owner+0x20; the wake gate recognizes state 8 at 0x002d7fec and enters animation 4/state 2 before ground alignment. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_3_value_9 -> L02_BOT_WAIT_FOR_WAKE_TRIGGER_WITH_ALTERNATE_WAKE_ANIMATION: Retail 0x002d797c-0x002d79a0 selects animation 15 and stores 9 to owner+0x20; the shared wake gate recognizes 9 at 0x002d8020, selects animation 16 and enters state 2. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_4_value_3 -> L02_BOT_ALIGN_TO_GROUND_AT_POST: Retail 0x002d79a4-0x002d79c0 tests animation completion and stores 3 to owner+0x20; handler 0x002d79e0-0x002d7af0 moves toward the post and approaches probed ground height. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_5_value_4 -> L02_BOT_WAIT_FOR_ANIMATION_BEFORE_MOVE_TO_POST: Ground height equality at 0x002d7aec-0x002d7b0c stores state 4 and starts animation 5; state 4 at 0x002d7b34-0x002d7b50 waits for anim_flags bit 2 then enters MOVE_TO_POST. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_6_value_5 -> L02_BOT_MOVE_TO_POST: Retail 0x002d7b34-0x002d7b50 stores 5 after animation completion; state 5 at 0x002d7b6c-0x002d7b90 calls the walker with the post cuboid position as destination. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_7_value_7 -> L02_BOT_SELECT_ATTACK_OR_WANDER: Post walker return 4 at 0x002d7b94-0x002d7ba4 reaches shared state-7 store 0x002d7c00-0x002d7c08; state 7 chooses attack or a random wander destination at 0x002d7c98-0x002d7eb0. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_8_value_7 -> L02_BOT_SELECT_ATTACK_OR_WANDER: Wander walker completion mask 6 at 0x002d7bc8-0x002d7bd8 reaches shared state-7 store 0x002d7c00-0x002d7c08, returning to the attack/wander choice handler. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. domain_9_value_5 -> L02_BOT_MOVE_TO_POST: Wandering target-range and height gates at 0x002d7c24-0x002d7c7c store 5 to owner+0x20; established state 5 passes the post cuboid destination to the walker at 0x002d7b6c-0x002d7b90. Source selector is moby->state; retail dispatch reads 0x20(s4) at 0x002d77e0, and these accesses use that same byte, proving the existing local bot-state enum domain rather than start modes or HERO_STATE. --- src/overlays/l02/mobys/constructorbot.c | 46 ++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/overlays/l02/mobys/constructorbot.c b/src/overlays/l02/mobys/constructorbot.c index f2031187fe..c44aa2bc53 100644 --- a/src/overlays/l02/mobys/constructorbot.c +++ b/src/overlays/l02/mobys/constructorbot.c @@ -209,31 +209,31 @@ void constructorbot_update(struct Moby *moby) { if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 0); } - moby->state = 7; + moby->state = L02_BOT_SELECT_ATTACK_OR_WANDER; break; case L02_BOT_START_WAIT_FOR_WAKE_TRIGGER: if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 0); } - moby->state = 10; + moby->state = L02_BOT_WAIT_FOR_WAKE_TRIGGER; break; case L02_BOT_START_WAIT_FOR_WAKE_TRIGGER_BEFORE_GROUND_ALIGNMENT: if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, 0); } - moby->state = 8; + moby->state = L02_BOT_WAIT_FOR_WAKE_TRIGGER_BEFORE_GROUND_ALIGNMENT; break; case L02_BOT_START_WAIT_FOR_WAKE_TRIGGER_WITH_ALTERNATE_WAKE_ANIMATION: if (moby->prev_seq != 15) { blend_moby_animation(moby, 15, 0, 0); } - moby->state = 9; + moby->state = L02_BOT_WAIT_FOR_WAKE_TRIGGER_WITH_ALTERNATE_WAKE_ANIMATION; break; } break; case L02_BOT_WAIT_FOR_WAKE_ANIMATION: if (moby->anim_flags & 2) { - moby->state = 3; + moby->state = L02_BOT_ALIGN_TO_GROUND_AT_POST; if (moby->prev_seq != 4) { blend_moby_animation(moby, 4, 0, 0); } @@ -259,7 +259,7 @@ void constructorbot_update(struct Moby *moby) { constructorbot_gravity_gp * frame_time_sq); approach_value(&moby->pos.z, ground, bot_private_vars->velocity[2]); if (moby->pos.z == ground) { - moby->state = 4; + moby->state = L02_BOT_WAIT_FOR_ANIMATION_BEFORE_MOVE_TO_POST; if (moby->prev_seq != 5) { blend_moby_animation(moby, 5, 4, scale_game_frames(10)); } @@ -267,7 +267,7 @@ void constructorbot_update(struct Moby *moby) { break; case L02_BOT_WAIT_FOR_ANIMATION_BEFORE_MOVE_TO_POST: if (moby->anim_flags & 2) { - moby->state = 5; + moby->state = L02_BOT_MOVE_TO_POST; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(6)); } @@ -281,7 +281,7 @@ void constructorbot_update(struct Moby *moby) { if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(30)); } - moby->state = 7; + moby->state = L02_BOT_SELECT_ATTACK_OR_WANDER; } break; case L02_BOT_WANDER: @@ -293,13 +293,13 @@ void constructorbot_update(struct Moby *moby) { if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } - moby->state = 7; + moby->state = L02_BOT_SELECT_ATTACK_OR_WANDER; } else if (fast_vec_dist(bot_private_vars->target + 0x10, &l02_cuboids[bot_private_vars->post].pos) < bot_private_vars->attack_range && absolute_float(*(float *)(bot_private_vars->target + 0x18) - moby->pos.z) < 4.0f) { - moby->state = 5; + moby->state = L02_BOT_MOVE_TO_POST; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(10)); } @@ -317,13 +317,13 @@ void constructorbot_update(struct Moby *moby) { FUN_L00_00258278( (char *)moby, angle, &bot_private_vars->turn_speed, 0.02f, 0.3f, 0.1f); if (fast_difference_between_rotations(moby->rot.z, angle) < 0.08726646f) { - moby->state = 0xB; + moby->state = L02_BOT_WAIT_FOR_ANIMATION_BEFORE_ATTACK; if (moby->prev_seq != 8) { blend_moby_animation(moby, 8, 0, scale_game_frames(6)); } } } else { - moby->state = 5; + moby->state = L02_BOT_MOVE_TO_POST; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(10)); } @@ -338,7 +338,7 @@ void constructorbot_update(struct Moby *moby) { fast_vec_add(bot_private_vars->wander, bot_private_vars->wander, &l02_cuboids[bot_private_vars->post].pos); - moby->state = 6; + moby->state = L02_BOT_WANDER; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(10)); } @@ -374,18 +374,18 @@ void constructorbot_update(struct Moby *moby) { triggered = 1; } if (triggered) { - if (moby->state == 8) { + if (moby->state == L02_BOT_WAIT_FOR_WAKE_TRIGGER_BEFORE_GROUND_ALIGNMENT) { if (moby->prev_seq != 4) { blend_moby_animation(moby, 4, 0, scale_game_frames(10)); } - moby->state = 2; - } else if (moby->state == 9) { + moby->state = L02_BOT_WAIT_FOR_WAKE_ANIMATION; + } else if (moby->state == L02_BOT_WAIT_FOR_WAKE_TRIGGER_WITH_ALTERNATE_WAKE_ANIMATION) { if (moby->prev_seq != 0x10) { blend_moby_animation(moby, 0x10, 0, scale_game_frames(10)); } - moby->state = 2; + moby->state = L02_BOT_WAIT_FOR_WAKE_ANIMATION; } else { - moby->state = 5; + moby->state = L02_BOT_MOVE_TO_POST; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(6)); } @@ -400,7 +400,7 @@ void constructorbot_update(struct Moby *moby) { FUN_L00_00258278((char *)moby, angle, &bot_private_vars->turn_speed, 0.02f, 0.3f, 0.1f); if (moby->anim_flags & 2) { moby->anim_speed = 1.0f; - moby->state = 0xC; + moby->state = L02_BOT_UPDATE_ATTACK_SHOTS; if (moby->prev_seq != 9) { blend_moby_animation(moby, 9, 0, scale_game_frames(6)); } @@ -425,7 +425,7 @@ void constructorbot_update(struct Moby *moby) { collect_mobies_around_tracked_objects(bot_private_vars->shots, (int)moby, (int)shot); if (moby->anim_flags & 2) { moby->anim_speed = 1.0f; - moby->state = 0xD; + moby->state = L02_BOT_WAIT_FOR_ANIMATION_BEFORE_ATTACK_RECHECK; if (random_integer_below(0xFF) & 1) { if (moby->prev_seq != 10) { blend_moby_animation(moby, 10, 0, scale_game_frames(6)); @@ -444,12 +444,12 @@ void constructorbot_update(struct Moby *moby) { if (vector_distance_xy(&moby->pos, bot_private_vars->target + 0x10) < bot_private_vars->attack_range + 1.0f && absolute_float(*(float *)(bot_private_vars->target + 0x18) - moby->pos.z) < 3.0f) { - moby->state = 0xC; + moby->state = L02_BOT_UPDATE_ATTACK_SHOTS; if (moby->prev_seq != 9) { blend_moby_animation(moby, 9, 0, scale_game_frames(6)); } } else { - moby->state = 7; + moby->state = L02_BOT_SELECT_ATTACK_OR_WANDER; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(6)); } @@ -458,7 +458,7 @@ void constructorbot_update(struct Moby *moby) { break; case L02_BOT_HIT_KNOCKBACK_RECOVERY: if (step_moby_motion(moby, bot_private_vars->knockback) & 0x40) { - moby->state = 7; + moby->state = L02_BOT_SELECT_ATTACK_OR_WANDER; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(6)); } From f158a5a992513fab874ca8b5b60430ce8e850b10 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:20:53 +0000 Subject: [PATCH 1102/1502] decomp: clarify names in blarg_ship_update domain_0_value_1 -> BLARG_SHIP_STATE_WAIT_FOR_TARGET_IN_VOLUME: Retail 002e4bd0/002e4bd8 stores 1 to ship+0x20, the selector loaded at 002e4b08. The existing enum names this same selector's case 1 WAIT_FOR_TARGET_IN_VOLUME; its branch at 002e4c10-002e4c30 waits for target clip-volume inclusion before advancing. domain_10_value_5 -> BLARG_SHIP_STATE_FIRE_COOLDOWN: Retail 002e57ac-002e57f4 handles other saved states after hit-animation completion, writes 5 at ship+0x20 and initializes timer +0x168 from cooldown duration +0x164. Existing enum case 5 for that same switch byte is FIRE_COOLDOWN, matching the firing-to-cooldown transition. domain_1_value_2 -> BLARG_SHIP_STATE_RISE_TO_ENTRY_PATH: Retail 002e4c20/002e4c30 writes 2 to ship+0x20 after target-volume inclusion. This is the same byte switched at 002e4b08 and named RISE_TO_ENTRY_PATH by the existing local enum; 002e4dd8-002e4de0 raises Z before entry-node proximity advances state. domain_2_value_3 -> BLARG_SHIP_STATE_FOLLOW_ENTRY_PATH: Retail 002e4e14/002e4e24 writes 3 to ship+0x20 after distance to the entry path first point falls below 0.5. The existing enum for that selector names case 3 FOLLOW_ENTRY_PATH, whose 002e4e4c-002e4fcc branch moves toward and advances indexed nodes. domain_3_value_4 -> BLARG_SHIP_STATE_FIRE_AT_TARGET: Retail 002e4fd0-002e4fd8 writes 4 to ship+0x20 when the entry path node count is exhausted and resets the path index. The existing switch on this byte names case 4 FIRE_AT_TARGET; 002e5244-002e5334 emits rockets in animation windows. domain_4_value_6 -> BLARG_SHIP_STATE_FLY_AWAY: Retail 002e4ff8-002e5004 branches on hero inclusion in the departure clip volume to 002e53e4/002e53e8, storing 6 at ship+0x20. This same switch byte has existing enum member FLY_AWAY=6; 002e5690-002e5714 ascends, shrinks and removes the ship. domain_5_value_5 -> BLARG_SHIP_STATE_FIRE_COOLDOWN: Retail 002e5378-002e53c4 detects firing timer expiry, writes 5 at ship+0x20 and loads cooldown duration from private +0x164. Existing enum case 5 on this byte is FIRE_COOLDOWN; its branch continues aiming and returns to firing after timer expiry. domain_6_value_6 -> BLARG_SHIP_STATE_FLY_AWAY: Retail 002e53d4-002e53e8 tests the departure clip volume while in cooldown and stores 6 to ship+0x20 when inside. This is the update switch selector at 002e4b08, whose existing FLY_AWAY=6 branch ascends and shrinks until removal at 002e5690-002e5714. domain_7_value_4 -> BLARG_SHIP_STATE_FIRE_AT_TARGET: Retail 002e5578-002e55bc detects cooldown timer expiry, selects firing animation 3, writes 4 to ship+0x20, restores firing animation speed and loads private +0x160 firing duration. Existing enum case 4 for this selector is FIRE_AT_TARGET and emits rockets. domain_8_value_4 -> BLARG_SHIP_STATE_FIRE_AT_TARGET: Source assigns pre_hit_state from ship->bBC; supplied helper source saves moby->state into moby->command before entering hit reaction. Retail 002e5738 loads +0xBC, 002e573c compares it with 4, and 002e5764 restores it to selector +0x20 with firing animation and duration. Thus it uses the existing FIRE_AT_TARGET=4 ship-state member. domain_9_value_6 -> BLARG_SHIP_STATE_FLY_AWAY: Source pre_hit_state is the saved ship state at +0xBC, captured by the supplied hit helper before entering state 7. Retail 002e5780 compares this saved byte with 6 and 002e57a8 restores it to ship+0x20. It therefore shares the existing switch domain and canonical FLY_AWAY=6 member. --- src/overlays/l10/mobys/blarg_ship.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l10/mobys/blarg_ship.c b/src/overlays/l10/mobys/blarg_ship.c index 611032e8f4..cb839df0c1 100644 --- a/src/overlays/l10/mobys/blarg_ship.c +++ b/src/overlays/l10/mobys/blarg_ship.c @@ -221,14 +221,14 @@ void blarg_ship_update(Ship_5E48 *ship) { ship->s34 |= 0x41; if (ship->b53 != 0) blend_moby_animation(ship, 0, 0, 0); - ship->state = 1; + ship->state = BLARG_SHIP_STATE_WAIT_FOR_TARGET_IN_VOLUME; if (visited52[ship->bB0 + (D_0015ED84 << 4)] != 0xFF) break; goto del; case BLARG_SHIP_STATE_WAIT_FOR_TARGET_IN_VOLUME: if (!is_point_inside_clip_volume(&tgt->pos, d->i148)) break; - ship->state = 2; + ship->state = BLARG_SHIP_STATE_RISE_TO_ENTRY_PATH; if (ship->b53 != 1) blend_moby_animation(ship, 1, 0, scale_game_frames(20)); ship->s34 &= 0xFFBE; @@ -250,7 +250,7 @@ void blarg_ship_update(Ship_5E48 *ship) { blend_moby_animation(ship, 2, 0, scale_game_frames(20)); ship->pos.z += D_0015ED6C * 4.0f; if (fast_vec_dist(&ship->pos, &l10_paths[d->i140]->points[0]) < 0.5f) { - ship->state = 3; + ship->state = BLARG_SHIP_STATE_FOLLOW_ENTRY_PATH; if (ship->b53 != 2) blend_moby_animation(ship, 2, 0, scale_game_frames(10)); } @@ -273,14 +273,14 @@ void blarg_ship_update(Ship_5E48 *ship) { d->i158 = n; } else { d->i158 = 0; - ship->state = 4; + ship->state = BLARG_SHIP_STATE_FIRE_AT_TARGET; d->i168 = truncate_float_to_s32(FUN_L04_001f1978(d->f160 * 60.0f)); } } break; case BLARG_SHIP_STATE_FIRE_AT_TARGET: if (is_point_inside_clip_volume(&(&hero)->motion.pos, d->i1B0)) { - ship->state = 6; + ship->state = BLARG_SHIP_STATE_FLY_AWAY; break; } *(u128_2E52B0 *)&A = *(u128_2E52B0 *)&tgt->pos; @@ -330,7 +330,7 @@ void blarg_ship_update(Ship_5E48 *ship) { if (fast_dec_timer(&d->i168)) { if (ship->b53 != 2) blend_moby_animation(ship, 2, 0, scale_game_frames(10)); - ship->state = 5; + ship->state = BLARG_SHIP_STATE_FIRE_COOLDOWN; d->i168 = truncate_float_to_s32(FUN_L04_001f1978(d->f164 * 60.0f)); } qcopy(&B, &l10_paths[d->i144]->points[d->i158]); @@ -345,7 +345,7 @@ void blarg_ship_update(Ship_5E48 *ship) { break; case BLARG_SHIP_STATE_FIRE_COOLDOWN: if (is_point_inside_clip_volume(&(&hero)->motion.pos, d->i1B0)) { - ship->state = 6; + ship->state = BLARG_SHIP_STATE_FLY_AWAY; break; } *(u128_2E52B0 *)&A = *(u128_2E52B0 *)&tgt->pos; @@ -371,7 +371,7 @@ void blarg_ship_update(Ship_5E48 *ship) { if (fast_dec_timer(&d->i168)) { blend_moby_animation(ship, 3, 0, scale_game_frames(10)); ship->f58 = blarg_ship_firing_animation_speed_gp; - ship->state = 4; + ship->state = BLARG_SHIP_STATE_FIRE_AT_TARGET; d->i168 = truncate_float_to_s32(FUN_L04_001f1978(d->f160 * 60.0f)); } qcopy(&B, &l10_paths[d->i144]->points[d->i158]); @@ -399,17 +399,17 @@ void blarg_ship_update(Ship_5E48 *ship) { if (!(ship->b70 & 2)) break; pre_hit_state = ship->bBC; - if (pre_hit_state == 4) { + if (pre_hit_state == BLARG_SHIP_STATE_FIRE_AT_TARGET) { blend_moby_animation(ship, 3, 0, scale_game_frames(10)); ship->f58 = blarg_ship_firing_animation_speed_gp; ship->state = pre_hit_state; d->i168 = truncate_float_to_s32(FUN_L04_001f1978(d->f160 * 60.0f)); - } else if (pre_hit_state == 6) { + } else if (pre_hit_state == BLARG_SHIP_STATE_FLY_AWAY) { blend_moby_animation(ship, 2, 0, scale_game_frames(10)); ship->state = pre_hit_state; } else { blend_moby_animation(ship, 2, 0, scale_game_frames(10)); - ship->state = 5; + ship->state = BLARG_SHIP_STATE_FIRE_COOLDOWN; d->i168 = truncate_float_to_s32(FUN_L04_001f1978(d->f164 * 60.0f)); } break; From d76536f748674b4b7444fe413725a860992b1431 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:20:53 +0000 Subject: [PATCH 1103/1502] decomp: clarify names in update_deplanetizer_gun_sequence_effects domain_0_value_1 -> UPDATE_SEQUENCE_EFFECTS: Source switch(moby->state) already defines UPDATE_SEQUENCE_EFFECTS=1 and uses it to enter sequence effect processing. Retail 002f8924 loads moby+0x20, 002f892c/002f8930 compares that same byte with 1 and branches to 002f8980. Initialization loads v0=1 at 002f8964 and stores it to the identical moby+0x20 byte at 002f8974 after initializing timing thresholds. Original Ghidra likewise sets *(undefined1 *)(iVar8+0x20)=1 and gates the update body on that byte equaling 1. This proves reuse of the existing member for this assignment, independently of the separate global sequence-state domain. --- src/overlays/l18/mobys/cutscene_effects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l18/mobys/cutscene_effects.c b/src/overlays/l18/mobys/cutscene_effects.c index 4badd62a5f..e2113b95a5 100644 --- a/src/overlays/l18/mobys/cutscene_effects.c +++ b/src/overlays/l18/mobys/cutscene_effects.c @@ -137,7 +137,7 @@ void deplanetizer_effects_update(struct Moby *moby) { deplanetizer_three_quad_scale_ramp_start_frame_gp = 190; deplanetizer_three_quad_scale_ramp_end_frame_gp = 365; moby->update_dist = 255; - moby->state = 1; + moby->state = UPDATE_SEQUENCE_EFFECTS; return; case UPDATE_SEQUENCE_EFFECTS: break; From dbb77f8bbba08a48682f5e7e57e94cd791f16b82 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:20:54 +0000 Subject: [PATCH 1104/1502] decomp: clarify names in robot_dog_update domain_0_value_0 -> ROBOT_DOG_DETECTION_LINE_BLOCKED: The source mode field is pvars+0x1e4, read at retail 002eedd0-002eedd4 for the nonzero detection trigger. Checked direct helper 002efa48 loads the same pvars via moby+0x78. At 002efcf4 it performs the source collision_line query; 002efd08 converts its result to result==0, then 002efd18 stores that boolean at +0x1e4. The facing-cone path shifts it left at 002efd1c-002efd20, so a blocked line produces zero in either path. This is a detection classification, separate from moby+0x20 state. domain_1_value_2 -> ROBOT_DOG_DETECTION_CLEAR_LINE_IN_FACING_CONE: In TRACK_TARGET_FACING, local mode is loaded from robot_dog_vars->mode at retail 002ef060 and compared to 2 at 002ef064. Direct helper 002efa48 computes heading from pvars+0x180 minus moby XY (002efc98-002efcb0), compares it with moby yaw +0x48 (002efcb4-002efcc0), and queries collision_line (002efcf4). At 002efd08 the clear-line result becomes 1; when heading difference is below 1.0471976 radians (002efd0c-002efd14), 002efd1c shifts that 1 into 2 and 002efd20 stores it at pvars+0x1e4. Thus value 2 proves clear line within the facing cone, not a moby state ID. domain_2_value_0 -> ROBOT_DOG_DETECTION_LINE_BLOCKED: The source TRACK_TARGET_FACING exit requires t1E0==0 and robot_dog_vars->mode==0. Retail 002ef124-002ef134 masks the packed load at pvars+0x1e0 to test the timer and byte +0x1e4 before entering state 3. That same byte is written by direct helper 002efa48: collision_line at 002efcf4 is normalized by sltiu at 002efd08 and stored at 002efd18; the within-cone shift at 002efd1c-002efd20 preserves zero for a blocked query. Reuse the same detection-domain zero member as domain_0; neither zero comparison belongs to the moby-state or hero domains. --- src/overlays/l17/mobys/robot_dog.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l17/mobys/robot_dog.c b/src/overlays/l17/mobys/robot_dog.c index 7a83a43907..fdb0f6be28 100644 --- a/src/overlays/l17/mobys/robot_dog.c +++ b/src/overlays/l17/mobys/robot_dog.c @@ -147,6 +147,10 @@ void robot_dog_update(unsigned char *m) __asm__("FUN_L17_002eeb68"); /* Moby classes 573, 1382 */ void robot_dog_update(unsigned char *robot_dog_moby) { + enum { + ROBOT_DOG_DETECTION_LINE_BLOCKED = 0, + ROBOT_DOG_DETECTION_CLEAR_LINE_IN_FACING_CONE = 2 + }; Vars1382 *robot_dog_vars; struct Moby *facing_target_moby; int clip_volume_suppressed; @@ -222,7 +226,7 @@ void robot_dog_update(unsigned char *robot_dog_moby) { } break; case ROBOT_DOG_STATE_WAIT_FOR_DETECTION_TRIGGER: - if (robot_dog_vars->mode != 0 && random_integer_below(0x1F) == 0) { + if (robot_dog_vars->mode != ROBOT_DOG_DETECTION_LINE_BLOCKED && random_integer_below(0x1F) == 0) { robot_dog_moby[0x20] = 2; if (robot_dog_moby[0x53] != 1) { blend_moby_animation(robot_dog_moby, 1, 0, scale_game_frames(10)); @@ -285,7 +289,7 @@ void robot_dog_update(unsigned char *robot_dog_moby) { } MOBY(robot_dog_moby)->anim_speed = 1.7f; mode = robot_dog_vars->mode; - if (mode == 2 && + if (mode == ROBOT_DOG_DETECTION_CLEAR_LINE_IN_FACING_CONE && (fast_dec_timer_s16(&robot_dog_vars->t1E2) || D_0013E533[0x2EC1] != 3)) { if (random_integer_below(3) == 0) { if (robot_dog_moby[0x53] != mode) { @@ -302,7 +306,7 @@ void robot_dog_update(unsigned char *robot_dog_moby) { blend_moby_animation(robot_dog_moby, 7, 0, scale_game_frames(10)); } } - } else if (robot_dog_vars->t1E0 == 0 && robot_dog_vars->mode == 0) { + } else if (robot_dog_vars->t1E0 == 0 && robot_dog_vars->mode == ROBOT_DOG_DETECTION_LINE_BLOCKED) { robot_dog_moby[0x20] = 3; if (robot_dog_moby[0x53] != 0) { clip_volume_id_or_animation_value = random_integer_below( From e49d18302395b0eb3fa94279aacc3d21384994a9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:20:54 +0000 Subject: [PATCH 1105/1502] decomp: clarify names in blarg_helicopter_update domain_1_value_1 -> BLARG_HELICOPTER_WAIT_FOR_ACTIVATION: Retail 002ea320 loads 1 and 002ea328 stores it to s3+0x20, the same moby->state byte read for the switch at 002ea1bc. This finishes initialization and enters existing WAIT_FOR_ACTIVATION, whose branch 002ea32c-002ea374 waits for activation timer or hero clip-volume entry. domain_2_value_2 -> BLARG_HELICOPTER_FOLLOW_INITIAL_PATH: Retail 002ea3c0 loads 2 and 002ea3d4 stores it to moby state s3+0x20 after the activation condition. The same switch's case 2 at 002ea3e0-002ea474 calls follow_blarg_helicopter_path with pvars+0xa0, proving reuse of existing FOLLOW_INITIAL_PATH. domain_3_value_3 -> BLARG_HELICOPTER_AIM_AND_FIRE: Retail 002ea460 calls follow_blarg_helicopter_path; on nonzero return 002ea46c loads 3 and 002ea474 stores it to s3+0x20. That same state selector dispatches to case 3 at 002ea478, which turns toward target and calls spawn_rocket at 002ea7bc, matching existing AIM_AND_FIRE. domain_4_value_4 -> BLARG_HELICOPTER_MOVE_BETWEEN_PATH_ENDPOINTS: Retail 002ea8f0-002ea90c tests accumulated shots against the threshold, requires the pvars+0xa4 path, and clears the shot count; 002ea914 stores 4 to moby state. Case 4 uses that path and pvars+0xbe to choose its first or last point at 002ea990-002ea9e8, matching existing MOVE_BETWEEN_PATH_ENDPOINTS. domain_5_value_3 -> BLARG_HELICOPTER_AIM_AND_FIRE: Retail endpoint movement case tests speed pvars+0x94 for zero at 002eaa3c-002eaa48, resets firing timer and toggles endpoint selector at 002eaa50-002eaa68, then stores 3 to s3+0x20 at 002eaa70. This returns to the same switch's existing AIM_AND_FIRE branch and rocket firing behavior. domain_6_value_0 -> BLARG_HELICOPTER_INITIALIZE: Retail explosion/reset branch retains the moby when pvars+0xc0 is nonzero, resets activation timer at 002eac98 and collision at 002eac9c, then stores zero to s3+0x20 at 002eaca4. This reenters the same state switch's existing INITIALIZE case, which restores health, paths and child setup at 002ea1e4-002ea328. domain_7_value_1 -> BLARG_HELICOPTER_WAIT_FOR_ACTIVATION: Source compares moby->state > 1 after child synchronization; retail 002ead6c loads the same s3+0x20 switch selector and 002ead70-002ead74 skips this behavior for states below 2. Existing WAIT_FOR_ACTIVATION is the state 1 boundary: initialization and activation waiting are excluded before visible nearby helicopter processing. --- src/overlays/l12/mobys/blarg_helicopter.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l12/mobys/blarg_helicopter.c b/src/overlays/l12/mobys/blarg_helicopter.c index 604a4802d7..b21c445314 100644 --- a/src/overlays/l12/mobys/blarg_helicopter.c +++ b/src/overlays/l12/mobys/blarg_helicopter.c @@ -288,7 +288,7 @@ void blarg_helicopter_update(struct Moby *moby) { } } blarg_helicopter_vars->unkB4 = 0; - moby->state = 1; + moby->state = BLARG_HELICOPTER_WAIT_FOR_ACTIVATION; break; } case BLARG_HELICOPTER_WAIT_FOR_ACTIVATION: { @@ -310,7 +310,7 @@ void blarg_helicopter_update(struct Moby *moby) { child->flags &= 0xffbe; moby->flags |= 0x1000; a = moby->pclass->collision; - moby->state = 2; + moby->state = BLARG_HELICOPTER_FOLLOW_INITIAL_PATH; moby->collision = a; } break; @@ -331,7 +331,7 @@ void blarg_helicopter_update(struct Moby *moby) { blarg_helicopter_vars->unk8C = limit * scale_game_frames(15); } if (follow_blarg_helicopter_path(moby, blarg_helicopter_vars->unkA0)) - moby->state = 3; + moby->state = BLARG_HELICOPTER_AIM_AND_FIRE; break; case BLARG_HELICOPTER_AIM_AND_FIRE: { int count, limit, a, b, color, life, size; @@ -410,7 +410,7 @@ void blarg_helicopter_update(struct Moby *moby) { } if (blarg_helicopter_vars->unkBC >= limit && blarg_helicopter_vars->unkA4 != -1) { blarg_helicopter_vars->unkBC = 0; - moby->state = 4; + moby->state = BLARG_HELICOPTER_MOVE_BETWEEN_PATH_ENDPOINTS; } else blarg_helicopter_vars->unk8C = scale_game_frames(40); } @@ -438,7 +438,7 @@ void blarg_helicopter_update(struct Moby *moby) { if (blarg_helicopter_vars->unk94 == 0.0f) { blarg_helicopter_vars->unk8C = scale_game_frames(50); blarg_helicopter_vars->unkBE = blarg_helicopter_vars->unkBE == 0; - moby->state = 3; + moby->state = BLARG_HELICOPTER_AIM_AND_FIRE; break; } } else @@ -506,7 +506,7 @@ void blarg_helicopter_update(struct Moby *moby) { b = scale_game_frames(400); blarg_helicopter_vars->unkC4 = FUN_L00_00257b90(a, b); moby->collision = 0; - moby->state = 0; + moby->state = BLARG_HELICOPTER_INITIALIZE; moby->flags = (moby->flags | 0x41) & 0xefff; break; } @@ -527,7 +527,7 @@ void blarg_helicopter_update(struct Moby *moby) { (*(struct Moby **)(&blarg_helicopter_vars->unkAC))->flags |= 6; } } - if (blarg_helicopter_vars->unkC0 == 0 && moby->state > 1 && moby->visible && + if (blarg_helicopter_vars->unkC0 == 0 && moby->state > BLARG_HELICOPTER_WAIT_FOR_ACTIVATION && moby->visible && fast_vec_dist(&moby->pos, D_L12_00167240) < 30.0f) { FUN_L00_0025a120((char *)moby); moby->shadow_range = 24; From 099c9d6239bf096329d0e27431323c3b0c6fc881 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:23:10 +0000 Subject: [PATCH 1106/1502] decomp: clarify names in devastator_update domain_0_value_0 -> DEVASTATOR_STATE_UNINITIALIZED: Bound source src/overlays/shared/weapons/devastator.c SHA-256 219ec018ab402a188dad934abb4cc3246a053720c267d40b26cb4c4a443ac45f compares the input devastator_moby->state to 0. Retail 002b210c keeps a0 in s6; 002b2164 loads its pvars into s3. At 002b2170/2180, lbu from s6+0x20 and bne skip initialization for nonzero state. Only zero executes 002b2190-2198, setting state to 1, pvars light +0x1c to -1 and glow +0x1e to 0. Original Ghidra shows the same zero-only initialization block. Thus this value identifies the Devastator state requiring initialization. domain_1_value_1 -> DEVASTATOR_STATE_INITIALIZED: Retail 002b2188 loads 1 and 002b2190 stores that byte to s6+0x20, the input Devastator Moby state established at 002b210c. The adjacent stores 002b2194/2198 initialize its pvars light handle to -1 and glow countdown to zero. On subsequent calls 002b2170/2180 bypass this block for the stored nonzero state. The original Ghidra and bound C agree: devastator_moby->state = 1 is confined to the state-zero initialization block. This value marks initialization completed for this Devastator update, with no claim about hero state IDs. --- src/overlays/shared/weapons/devastator.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/devastator.c b/src/overlays/shared/weapons/devastator.c index fcf90795f8..d037627b21 100644 --- a/src/overlays/shared/weapons/devastator.c +++ b/src/overlays/shared/weapons/devastator.c @@ -298,6 +298,10 @@ void devastator_update(struct Moby *m) __asm__("FUN_L00_002b2100"); /* Moby class 157 */ void devastator_update(struct Moby *devastator_moby) { + enum { + DEVASTATOR_STATE_UNINITIALIZED = 0, + DEVASTATOR_STATE_INITIALIZED = 1 + }; Matrix3 rotation; Matrix4 inverse; Vec_2b2100 velocity; @@ -318,8 +322,8 @@ void devastator_update(struct Moby *devastator_moby) { emit_object_offset_particles(devastator_moby); height = 0.75f; limit = 10000.0f; - if ((unsigned char)devastator_moby->state == 0) { - devastator_moby->state = 1; + if ((unsigned char)devastator_moby->state == DEVASTATOR_STATE_UNINITIALIZED) { + devastator_moby->state = DEVASTATOR_STATE_INITIALIZED; devastator_vars->light = -1; devastator_vars->glow = 0; } From 03698d34c621b81f50ac15f54f41b162898cce2f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:23:10 +0000 Subject: [PATCH 1107/1502] decomp: clarify names in decoy_update domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Authoritative decoy.c SHA-256 b53f1c3ced104758d5efc13caf438ff8d2875332944c5044f5d23b8a239a856d compares hero.vehicle_mode != 0. Retail 0x002c44c0 forms hero base 0x0013f350; 0x002c44c4 loads byte +0x20a4 (0x001413f4), and 0x002c44c8 branches on zero to bypass held-decoy removal. Original Ghidra tests cRam001413f4 against zero at the same branch. This explicitly maps the selector to hero.vehicle_mode, the HeroVehicleMode domain supplied from include/rnc/hero/hero_state.h, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT. The held-state removal on nonzero mode supports the domain usage; equal-valued HeroStateId, gravity, and decoy constants do not apply. --- src/overlays/shared/weapons/decoy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/decoy.c b/src/overlays/shared/weapons/decoy.c index ee2367f748..358faf19e0 100644 --- a/src/overlays/shared/weapons/decoy.c +++ b/src/overlays/shared/weapons/decoy.c @@ -571,7 +571,7 @@ void decoy_update(char *moby) { mark_moby_for_removal(moby); return; } - if (hero.vehicle_mode != 0 && (u8)MOBY(moby)->state == 1) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && (u8)MOBY(moby)->state == 1) { mine_spawn_drops(moby, D_L00_001B0830_lui); mark_moby_for_removal(moby); return; From bf6b869de0a8206df47119744acddf7eb125c55d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:23:10 +0000 Subject: [PATCH 1108/1502] decomp: clarify names in blarg_space_commando_update domain_0_value_1 -> BLARG_COMMANDO_STATE_SELECT_ACTION: 002fdd64 stores 1 to moby+0x20 after initialization and saving home. The switch reads this identical byte at 002fdc70; existing case SELECT_ACTION=1 faces the target and selects route/ranged/melee/chase behavior. domain_10_value_5 -> BLARG_COMMANDO_STATE_MELEE_ATTACK: 002fe2dc-002fe304 compares target distance with the melee threshold and stores 5 to moby+0x20 when close. Existing MELEE_ATTACK=5 handles this exact selector byte with the frame 9-15 hit-segment sweep. domain_11_value_11 -> BLARG_COMMANDO_STATE_CHASE_TARGET: 002fe320-002fe338 stores 11 to moby+0x20 when the chase countdown is nonzero, with animation 1. Existing CHASE_TARGET=11 consumes the identical state byte and performs target-facing movement and path clearance. domain_12_value_1 -> HERO_VEHICLE_MODE_CLANK: Source explicitly compares hero.vehicle_mode; retail 002fe3fc-002fe408 loads its byte at 0x001413f4 and compares with 1 before slowing melee windup. This is the HeroVehicleMode selector, whose supplied header declares HERO_VEHICLE_MODE_CLANK=1; the same source beam consumer already uses that member with hero.vehicle_mode. domain_13_value_6 -> BLARG_COMMANDO_STATE_MELEE_RECOVERY: 002fe4f8-002fe51c detects melee animation completion, stores 6 to moby+0x20 and saves return state 1 in moby+0xbc. Existing MELEE_RECOVERY=6 handles this exact switch byte and later copies the saved command back to state. domain_14_value_13 -> BLARG_COMMANDO_STATE_RETURN_HOME: 002fe670-002fe680 stores 13 to moby+0x20 when vars+0x188 expires during chase. Existing RETURN_HOME=13 consumes this exact switch byte and steers toward the saved vars+0x170 home vector at 002fe840 onward. domain_15_value_12 -> BLARG_COMMANDO_STATE_CHASE_MELEE_ATTACK: 002fe684-002fe698 stores 12 to moby+0x20 when the path-query point is near the moby and starts animation 6. Existing CHASE_MELEE_ATTACK=12 consumes the same switch selector and performs a hit sweep before returning to chase. domain_16_value_12 -> BLARG_COMMANDO_STATE_CHASE_MELEE_ATTACK: 002fe6b4-002fe6e0 stores 12 to moby+0x20 when target XY distance is below the melee threshold during chase. Existing CHASE_MELEE_ATTACK=12 is this same selector domain and runs the frame 9-15 sweep at 002fe6fc-002fe804. domain_17_value_11 -> BLARG_COMMANDO_STATE_CHASE_TARGET: 002fe808-002fe824 stores 11 to moby+0x20 after chase-melee animation completion, restoring movement animation 1. Existing CHASE_TARGET=11 consumes this exact state selector and resumes target-facing forward movement. domain_18_value_1 -> BLARG_COMMANDO_STATE_SELECT_ACTION: 002fe93c-002fe96c measures distance from saved home and stores 1 to moby+0x20 when within 1.0, restoring animation 0. Existing SELECT_ACTION=1 is the same switch byte and chooses the next action. domain_19_value_1 -> BLARG_COMMANDO_STATE_SELECT_ACTION: 002fe978-002fe99c steps knockback motion, tests returned mask 0x40 and stores 1 to moby+0x20 on recovery. Existing SELECT_ACTION=1 consumes this exact switch byte; the branch restores animation 0 before action selection resumes. domain_1_value_14 -> BLARG_COMMANDO_STATE_APPROACH_ROUTE_DESTINATION: 002fdd90-002fdd98 stores 14 to moby+0x20 when the route and volume gate activates. This is the same selector byte read at 002fdc70; existing case APPROACH_ROUTE_DESTINATION=14 loads the route destination at 002fdf48-002fdf78. domain_2_value_2 -> BLARG_COMMANDO_STATE_RANGED_ATTACK_WINDUP: 002fde30-002fdea4 selects 2 and stores it to moby+0x20 after distance and facing checks, starting animation 3. Existing switch case RANGED_ATTACK_WINDUP=2 reads this same selector and waits before beam initialization at 002fe190. domain_3_value_5 -> BLARG_COMMANDO_STATE_MELEE_ATTACK: 002fde4c/002fde50 and 002fdec0-002fdecc select 5 at close target distance and store it to moby+0x20, starting animation 6. Existing MELEE_ATTACK=5 is the same switch domain and performs the frame 9-15 hit sweep. domain_4_value_11 -> BLARG_COMMANDO_STATE_CHASE_TARGET: 002fdee8-002fdf00 selects 11 when vars+0x188 is nonzero and stores it to moby+0x20, starting movement animation 1. Existing CHASE_TARGET=11 handles this exact switch selector with target-facing forward movement and path checks. domain_5_value_1 -> BLARG_COMMANDO_STATE_SELECT_ACTION: 002fe028-002fe05c clears turn speed and the route volume gate, then stores 1 to moby+0x20 after arrival and facing the target. Existing SELECT_ACTION=1 consumes this exact state byte in the switch at 002fdc70. domain_6_value_3 -> BLARG_COMMANDO_STATE_RANGED_ATTACK_RECOVERY: 002fe190-002fe1a8 calls beam initialization after windup animation completion and stores 3 to moby+0x20. Existing RANGED_ATTACK_RECOVERY=3 consumes this exact switch selector and waits before cooldown or action selection. domain_7_value_4 -> BLARG_COMMANDO_STATE_RANGED_ATTACK_COOLDOWN: 002fe1d4-002fe218 stores 4 to moby+0x20 and initializes vars+0x19c with scaled cooldown frames. Existing RANGED_ATTACK_COOLDOWN=4 handles this exact state selector and decrements that timer at 002fe298. domain_8_value_1 -> BLARG_COMMANDO_STATE_SELECT_ACTION: 002fe21c-002fe228 stores 1 to moby+0x20 in the alternate ranged recovery branch and restores animation 0. Existing SELECT_ACTION=1 consumes this same switch selector, choosing the next action. domain_9_value_3 -> BLARG_COMMANDO_STATE_RANGED_ATTACK_RECOVERY: 002fe298-002fe2c0 detects cooldown completion, calls beam initialization, and stores 3 to moby+0x20. Existing RANGED_ATTACK_RECOVERY=3 is the destination in this same state domain, also entered after initial beam emission. --- .../shared/enemies/blarg_space_commando.c | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/overlays/shared/enemies/blarg_space_commando.c b/src/overlays/shared/enemies/blarg_space_commando.c index df7ae181e1..0134edba01 100644 --- a/src/overlays/shared/enemies/blarg_space_commando.c +++ b/src/overlays/shared/enemies/blarg_space_commando.c @@ -183,12 +183,12 @@ void blarg_space_commando_update(struct Moby *moby) { blarg_commando_state->ctl.unk24 = movement_max_horizontal_speed_gp * frame_time; blarg_commando_state->ctl.flags |= 8; qcopy(&blarg_commando_state->home, &moby->pos); - moby->state = 1; + moby->state = BLARG_COMMANDO_STATE_SELECT_ACTION; break; case BLARG_COMMANDO_STATE_SELECT_ACTION: if (blarg_commando_state->volume != -1 && blarg_commando_state->route != -1) { if (is_point_inside_clip_volume(&hero.motion.pos, blarg_commando_state->volume) != 0) { - moby->state = 14; + moby->state = BLARG_COMMANDO_STATE_APPROACH_ROUTE_DESTINATION; break; } if (vector_distance_xy(&moby->pos, &target->pos) > 7.0f) { @@ -207,19 +207,19 @@ void blarg_space_commando_update(struct Moby *moby) { moby->rot.z, fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y)) < 0.17453292f) { - moby->state = 2; + moby->state = BLARG_COMMANDO_STATE_RANGED_ATTACK_WINDUP; if (moby->prev_seq != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } } } else { - moby->state = 5; + moby->state = BLARG_COMMANDO_STATE_MELEE_ATTACK; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(10)); } } } else if (blarg_commando_state->unk188 != 0) { - moby->state = 11; + moby->state = BLARG_COMMANDO_STATE_CHASE_TARGET; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(20)); } @@ -246,7 +246,7 @@ void blarg_space_commando_update(struct Moby *moby) { if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(18)); } - moby->state = 1; + moby->state = BLARG_COMMANDO_STATE_SELECT_ACTION; } } else { FUN_L00_00258278(moby, @@ -280,7 +280,7 @@ void blarg_space_commando_update(struct Moby *moby) { frame_time * 3.1415927f); if (moby->anim_flags & 2) { FUN_L06_002ff100_u(moby); - moby->state = 3; + moby->state = BLARG_COMMANDO_STATE_RANGED_ATTACK_RECOVERY; if (moby->prev_seq != 5) { blend_moby_animation(moby, 5, 0, scale_game_frames(10)); } @@ -289,13 +289,13 @@ void blarg_space_commando_update(struct Moby *moby) { case BLARG_COMMANDO_STATE_RANGED_ATTACK_RECOVERY: if (moby->anim_flags & 2) { if (blarg_commando_state->unk164 != 2) { - moby->state = 4; + moby->state = BLARG_COMMANDO_STATE_RANGED_ATTACK_COOLDOWN; if (moby->prev_seq != 4) { blend_moby_animation(moby, 4, 0, scale_game_frames(20)); } blarg_commando_state->timer = scale_game_frames(ranged_attack_cooldown_frames_gp); } else { - moby->state = 1; + moby->state = BLARG_COMMANDO_STATE_SELECT_ACTION; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(20)); } @@ -311,18 +311,18 @@ void blarg_space_commando_update(struct Moby *moby) { frame_time * 3.1415927f); if (fast_dec_timer(&blarg_commando_state->timer) != 0) { FUN_L06_002ff100_u(moby); - moby->state = 3; + moby->state = BLARG_COMMANDO_STATE_RANGED_ATTACK_RECOVERY; if (moby->prev_seq != 5) { blend_moby_animation(moby, 5, 0, scale_game_frames(5)); } } else if (vector_distance_xy(&moby->pos, &target->pos) < melee_attack_distance_threshold_gp) { - moby->state = 5; + moby->state = BLARG_COMMANDO_STATE_MELEE_ATTACK; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(10)); } } else if (blarg_commando_state->unk188 != 0) { - moby->state = 11; + moby->state = BLARG_COMMANDO_STATE_CHASE_TARGET; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(20)); } @@ -339,7 +339,7 @@ void blarg_space_commando_update(struct Moby *moby) { qcopy(&movement_input_or_output_or_melee_origin, &moby->pos); movement_input_or_output_or_melee_origin.f[2] += 0.3f; cur_frame = compute_interpolated_record_value(moby); - if (hero.vehicle_mode == 1 && cur_frame < 9.0f) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK && cur_frame < 9.0f) { moby->anim_speed = vehicle_melee_windup_animation_speed_gp; } if (cur_frame >= 9.0f && cur_frame <= 15.0f) { @@ -361,7 +361,7 @@ void blarg_space_commando_update(struct Moby *moby) { } qcopy(&blarg_commando_state->unk200, &position_or_movement_vector); if (moby->anim_flags & 2) { - moby->state = 6; + moby->state = BLARG_COMMANDO_STATE_MELEE_RECOVERY; moby->command = 1; if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(10)); @@ -402,15 +402,15 @@ void blarg_space_commando_update(struct Moby *moby) { near = 1; } if (blarg_commando_state->unk188 == 0) { - moby->state = 13; + moby->state = BLARG_COMMANDO_STATE_RETURN_HOME; } else if (near != 0) { - moby->state = 12; + moby->state = BLARG_COMMANDO_STATE_CHASE_MELEE_ATTACK; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(10)); } } else if (vector_distance_xy(&moby->pos, &target->pos) < melee_attack_distance_threshold_gp) { - moby->state = 12; + moby->state = BLARG_COMMANDO_STATE_CHASE_MELEE_ATTACK; if (moby->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(10)); } @@ -440,7 +440,7 @@ void blarg_space_commando_update(struct Moby *moby) { } qcopy(&blarg_commando_state->unk200, &position_or_movement_vector); if (moby->anim_flags & 2) { - moby->state = 11; + moby->state = BLARG_COMMANDO_STATE_CHASE_TARGET; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(20)); } @@ -470,7 +470,7 @@ void blarg_space_commando_update(struct Moby *moby) { blarg_commando_state->path, &moby->pos, &moby->pos, 0.75f); } if (fast_vec_dist(&blarg_commando_state->home, &moby->pos) < 1.0f) { - moby->state = 1; + moby->state = BLARG_COMMANDO_STATE_SELECT_ACTION; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(20)); } @@ -479,7 +479,7 @@ void blarg_space_commando_update(struct Moby *moby) { case BLARG_COMMANDO_STATE_KNOCKBACK: hit = step_moby_motion(moby, &blarg_commando_state->vel); if (hit & 0x40) { - moby->state = 1; + moby->state = BLARG_COMMANDO_STATE_SELECT_ACTION; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } From 56c07a2112a3aeb1e1ca308aae7f74792c49d324 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:23:10 +0000 Subject: [PATCH 1109/1502] decomp: clarify names in draw_tresspasser_puzzle domain_0_value_1 -> TRESSPASSER_SELECTED_RING_FIRST: Source state is loaded from puzzle_state+0xe0, not moby state. Retail 0x002d949c..0x002d94b0 compares that field to 1 and writes +1 to first_step at sp+0x90. First-ring base is pvars+0x20 (0x002d9514); the same selector 1 applies rotation and selected-ring color to that ring at 0x002d9538..0x002d9544 and 0x002d9c28..0x002d9cc4. Original Ghidra confirms this data flow, proving selected first ring. domain_1_value_2 -> TRESSPASSER_SELECTED_RING_SECOND: Source state is pvars+0xe0. Retail 0x002d94a8..0x002d94c4 compares it to 2 and writes +1 to second_step at sp+0x94. Base pvars+0x50 is the second ring at 0x002d9518; selector 2 applies its rotation at 0x002d97b8..0x002d97c8 and selected color at 0x002d9e74..0x002d9f08. Original Ghidra agrees; this is ring selection, not a hero or moby state. domain_2_value_1 -> TRESSPASSER_SELECTED_RING_FIRST: This negative-rotation branch loads the same pvars+0xe0 selector at retail 0x002d94e8 and compares to 1 at 0x002d94ec, then writes -1 to first_step at sp+0x90 (0x002d94f4..0x002d94fc). Original Ghidra and source show the first ring at +0x20 with offset +0x14; selector 1 also rotates/highlights that ring. It must reuse the positive branch's selected-first-ring member. domain_3_value_2 -> TRESSPASSER_SELECTED_RING_SECOND: In the negative-rotation branch, retail 0x002d94f0 loads 2 and 0x002d9500 compares the pvars+0xe0 selector against it; 0x002d9508..0x002d950c stores -1 to second_step at sp+0x94. Source and original Ghidra connect this step to the second ring at +0x50 and offset +0x18, with selector 2 rotating/highlighting that ring. Reuse the same selected-second-ring member as the positive branch. domain_4_value_0 -> TRESSPASSER_MARKER_ABSENT: marker_state is loaded from markers->slot[i], the separate pvars+0xb0 array established at retail 0x002d9430. Retail 0x002da328..0x002da330 skips drawing the marker arc when the loaded word is zero; nonzero words draw using marker radii at 0x002da354..0x002da370. Original Ghidra *piVar2 and source confirm that zero denotes an absent marker, not a ring-selection state. domain_5_value_2 -> TRESSPASSER_MARKER_REACHED: Source marker_state comes from the pvars+0xb0 marker array. Retail 0x002d9704..0x002d9724 tests a nonzero opposite marker and stores 2 to it when an unobstructed strip reaches it; equivalent stores occur at 0x002d9970 and 0x002d9b88. Retail 0x002da334..0x002da340 compares the final marker word to 2 and selects the established reached-marker arc color. Original Ghidra and source prove reached marker in a separate domain from ring selection. --- src/overlays/shared/props/trespasser_pad.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/props/trespasser_pad.c b/src/overlays/shared/props/trespasser_pad.c index 9604e8dd50..d88c9c3a88 100644 --- a/src/overlays/shared/props/trespasser_pad.c +++ b/src/overlays/shared/props/trespasser_pad.c @@ -487,7 +487,7 @@ void align_hero_to_tresspasser_pad(struct Moby *moby) { void draw_tresspasser_puzzle(char *moby) { /* Fakematch: the texture sits at retail's stack offset inside this frame. */ - struct { + enum { TRESSPASSER_MARKER_ABSENT = 0 , TRESSPASSER_SELECTED_RING_FIRST = 1 , TRESSPASSER_SELECTED_RING_SECOND = 2 , TRESSPASSER_MARKER_REACHED = 2 } ;struct { char pad0[0x78]; u64 texture; char pad80[0x10]; @@ -517,17 +517,17 @@ void draw_tresspasser_puzzle(char *moby) { third_step = 0; if (puzzle_state->unkE4 > 0.31415927f) { state = puzzle_state->unkE0; - if (state == 1) + if (state == TRESSPASSER_SELECTED_RING_FIRST) first_step = 1; - else if (state == 2) + else if (state == TRESSPASSER_SELECTED_RING_SECOND) second_step = 1; else third_step = 1; } else if (puzzle_state->unkE4 < -0.31415927f) { state = puzzle_state->unkE0; - if (state == 1) + if (state == TRESSPASSER_SELECTED_RING_FIRST) first_step = -1; - else if (state == 2) + else if (state == TRESSPASSER_SELECTED_RING_SECOND) second_step = -1; else third_step = -1; @@ -845,8 +845,8 @@ void draw_tresspasser_puzzle(char *moby) { angle = fast_add_rotations(-0.08726646f, (float)(i * 30) * 0.017453292f); phase = fast_add_rotations(angle, 0.17453292f); marker_state = markers->slot[i]; - if (marker_state != 0) { - if (marker_state == 2) + if (marker_state != TRESSPASSER_MARKER_ABSENT) { + if (marker_state == TRESSPASSER_MARKER_REACHED) color = tresspasser_reached_marker_arc_color_gp; else if (D_L02_0015F5CC & 0x20) color = tresspasser_unreached_marker_arc_flag_set_color_gp; From 8d54f760f8d0acf53a71c6015fee5b40fae28533 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:23:11 +0000 Subject: [PATCH 1110/1502] decomp: clarify names in update_rocket domain_0_value_4 -> ROCKET_STATE_FOLLOW_ROUTE: Retail 0x002dd410 loads the current rocket byte at s5+0x20 and 0x002dd414 compares it with 4 before hit-triggered removal. The same byte is loaded at 0x002dd458 for state dispatch; authoritative source names its case 4 ROCKET_STATE_FOLLOW_ROUTE, whose 0x002ddaac-0x002ddc08 branch advances route waypoints. domain_1_value_3 -> ROCKET_STATE_WAIT_FOR_ACTIVATION: Retail initialization 0x002dd518-0x002dd530 stores the route, copies its first position, sets waypoint 1 and writes 3 to s5+0x20. This is the exact byte dispatched at 0x002dd458; existing case 3 ROCKET_STATE_WAIT_FOR_ACTIVATION tests activation range and timer at 0x002dda18-0x002dda50. domain_2_value_2 -> ROCKET_STATE_HOME_TOWARD_TARGET: Retail 0x002dd6ac-0x002dd6dc checks yaw and pitch alignment, then 0x002dd6e0-0x002dd6e4 writes 2 to rocket s5+0x20, the dispatch byte. Existing case 2 ROCKET_STATE_HOME_TOWARD_TARGET guides toward target position and subtracts 60 target health at 0x002dd8e8-0x002dd918. domain_3_value_6 -> ROCKET_STATE_EXPLODE_AND_REMOVE: On target proximity, retail 0x002dd90c-0x002dd930 subtracts 60 health, clears velocity, requests voice and writes 6 to s5+0x20. This is the same rocket state selector as the existing case 6 ROCKET_STATE_EXPLODE_AND_REMOVE; 0x002de320-0x002de39c conditionally spawns an explosion then removes this moby. domain_4_value_4 -> ROCKET_STATE_FOLLOW_ROUTE: After activation-distance and timer tests at 0x002dda18-0x002dda50, retail 0x002dda58-0x002dda60 writes 4 to rocket s5+0x20. This exact byte feeds the state switch at 0x002dd458. Existing case 4 ROCKET_STATE_FOLLOW_ROUTE computes the next route waypoint and advances position at 0x002ddabc-0x002ddc08. domain_6_value_6 -> ROCKET_STATE_EXPLODE_AND_REMOVE: At the route terminus, retail 0x002de150-0x002de18c finishes linked-group debris effects and requests voice, then 0x002de190-0x002de198 writes 6 to rocket s5+0x20. The same dispatch byte selects existing ROCKET_STATE_EXPLODE_AND_REMOVE at case 6, implemented by explosion/removal at 0x002de320-0x002de39c. domain_7_value_6 -> ROCKET_STATE_EXPLODE_AND_REMOVE: Configured-heading flight tests collision, position bounds and proximity at retail 0x002de248-0x002de318; failure paths write 6 to s5+0x20 at 0x002de2d8, 0x002de2e8 or 0x002de31c. This is the rocket dispatch byte and existing case 6 ROCKET_STATE_EXPLODE_AND_REMOVE conditionally explodes and removes the moby at 0x002de320-0x002de39c. --- src/overlays/l08/mobys/rocket.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l08/mobys/rocket.c b/src/overlays/l08/mobys/rocket.c index 00d76215cc..f80eced611 100644 --- a/src/overlays/l08/mobys/rocket.c +++ b/src/overlays/l08/mobys/rocket.c @@ -186,7 +186,7 @@ void rocket_update(M46 *moby) { }; V46 target, delta, velocity_correction_or_effect_velocity, effect, aux; D46 *data = moby->data; - if (FUN_L00_0025a420(moby, 0x210000, 0) && moby->state != 4) { + if (FUN_L00_0025a420(moby, 0x210000, 0) && moby->state != ROCKET_STATE_FOLLOW_ROUTE) { allocate_voice_for_target_entry(0, 0, moby); cart_burst(moby, moby->position, -1, 0.5f, 13.0f); mark_moby_for_removal(moby); @@ -209,7 +209,7 @@ void rocket_update(M46 *moby) { data->path = ((Route_2dd4f8_2dd3c0 *)l08_paths[data->path_index]); qcopy(moby->position, data->path->e[0]); data->waypoint = 1; - moby->state = 3; + moby->state = ROCKET_STATE_WAIT_FOR_ACTIVATION; moby->animation = 0; moby->flags = 0; return; @@ -236,7 +236,7 @@ void rocket_update(M46 *moby) { moby->rotation[2] = fast_arc_tan(data->velocity[0], data->velocity[1]); if (fast_difference_between_rotations(yaw, data->yaw) < 0.08726646f && fast_difference_between_rotations(pitch, data->pitch) < 0.08726646f) - moby->state = 2; + moby->state = ROCKET_STATE_HOME_TOWARD_TARGET; radius = random_float_between(0.0f, rocket_effect_radial_speed_range_end_gp) * D_0015ED6C; angle = random_angle_radians(); fast_vec_normalize(effect, moby->matrix[2], radius * fast_cos(angle)); @@ -280,7 +280,7 @@ void rocket_update(M46 *moby) { target_data->health -= 60; clear_u64_value(data->velocity); allocate_voice_for_target_entry(0, 0, moby); - moby->state = 6; + moby->state = ROCKET_STATE_EXPLODE_AND_REMOVE; } radius = random_float_between(0.0f, rocket_effect_radial_speed_range_end_gp) * D_0015ED6C; angle = random_angle_radians(); @@ -310,7 +310,7 @@ void rocket_update(M46 *moby) { data->activation_range && fast_dec_timer(&data->timer)) { moby->flags = 0x40; - moby->state = 4; + moby->state = ROCKET_STATE_FOLLOW_ROUTE; moby->animation = moby->model->animation; moby->rotation[2] = fast_arc_tan(data->path->e[1][0] - moby->position[0], data->path->e[1][1] - moby->position[1]); @@ -491,7 +491,7 @@ void rocket_update(M46 *moby) { else FUN_L08_002de528_u(moby, data->effect_path, 30, 0); allocate_voice_for_target_entry(2, 0, moby); - moby->state = 6; + moby->state = ROCKET_STATE_EXPLODE_AND_REMOVE; } return; } @@ -510,7 +510,7 @@ void rocket_update(M46 *moby) { moby->position[0] > 500.0f || moby->position[1] < 5.0f || moby->position[1] > 500.0f || moby->position[2] < 5.0f || moby->position[2] > 500.0f || fast_vec_dist(D_0013F3D0, moby->position) < 16.0f) - moby->state = 6; + moby->state = ROCKET_STATE_EXPLODE_AND_REMOVE; return; case ROCKET_STATE_EXPLODE_AND_REMOVE: if (D_L08_0015FFDC < (unsigned int)moby) From 8ef40bb8adccd8b63d98a154ded25eb9da5958dd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:23:11 +0000 Subject: [PATCH 1111/1502] decomp: clarify names in blarg_trooper_update domain_0_value_3 -> BLARG_TROOPER_APPROACH_TARGET: At 002e7320..002e7328 retail loads the unsigned state byte at s1+0x20 and tests it against 3 before clearing visibility flags. The same byte selects the switch at 002e745c..002e747c; its established local enum names 3 BLARG_TROOPER_APPROACH_TARGET. Reuse that member as the ordered-state threshold. domain_1_value_2 -> BLARG_TROOPER_WAIT_FOR_ACTIVATION: Initialization saves the home position at 002e7514..002e7518 and ultimately stores 2 to s1+0x20 at 002e7f9c..002e7fa0. This is the same state byte dispatched at 002e745c; existing case BLARG_TROOPER_WAIT_FOR_ACTIVATION implements idle target/volume/command activation gates at 002e7680..002e7820. domain_2_value_1 -> BLARG_TROOPER_FOLLOW_WAYPOINTS: Activation chooses a path point index at 002e780c..002e7814, then stores 1 to the dispatched state byte s1+0x20 at 002e7818..002e7820. Existing BLARG_TROOPER_FOLLOW_WAYPOINTS case consumes that index, advances/clamps indexed path points and steers toward them at 002e7878..002e791c. domain_3_value_3 -> BLARG_TROOPER_APPROACH_TARGET: The waypoint case tests XY distance to the selected target against pvars+0x264 at 002e7924..002e7938 and stores 3 to s1+0x20 at 002e7944. This is the switch selector byte, whose existing BLARG_TROOPER_APPROACH_TARGET case computes target heading and steers toward its position at 002e7a4c..002e7ae0. domain_4_value_6 -> BLARG_TROOPER_FIRE_PROJECTILE: Preparation tests animation completion at 002e7c14..002e7c1c, selects animation 10 and stores 6 to s1+0x20 at 002e7c5c..002e7c64. This dispatched state already has case BLARG_TROOPER_FIRE_PROJECTILE, which obtains the child origin, builds trajectory and spawns the projectile at 002e7c9c..002e7d88. domain_5_value_7 -> BLARG_TROOPER_WAIT_BETWEEN_SHOTS: Firing completion tests animation flags at 002e7d8c..002e7d94, blends animation 5 and stores 7 to s1+0x20 at 002e7dd4..002e7ddc. The same byte dispatches existing BLARG_TROOPER_WAIT_BETWEEN_SHOTS, which continues aiming, waits toward idle and randomly retries preparation at 002e7de0..002e7e58. domain_6_value_3 -> BLARG_TROOPER_APPROACH_TARGET: Between shots, target direction is compared with moby heading at 002e7e94..002e7ecc; excess heading difference stores 3 to s1+0x20 at 002e7ed4..002e7edc. This is the established switch selector and resumes BLARG_TROOPER_APPROACH_TARGET, whose branch steers toward the target and checks readiness to shoot. domain_7_value_2 -> BLARG_TROOPER_WAIT_FOR_ACTIVATION: Return-home steering targets saved pvars+0x220 at 002e7ee0..002e7ef4. After XY distance falls below 1.0 at 002e7f74..002e7f90, retail stores 2 to s1+0x20 at 002e7f98..002e7fa0. The identical switch selector has existing member BLARG_TROOPER_WAIT_FOR_ACTIVATION for case 2. domain_8_value_5 -> BLARG_TROOPER_PREPARE_SHOT: Shared state5 entry stores 5 to s1+0x20 at 002e8040..002e8048, reached by approach/recovery heading readiness and random between-shot retry. This is the same dispatched state byte; existing BLARG_TROOPER_PREPARE_SHOT aims, grounds the moby, starts animation 2 and transitions to firing at 002e7ba4..002e7c64. domain_9_value_3 -> BLARG_TROOPER_APPROACH_TARGET: Shared state3 entry stores 3 to s1+0x20 at 002e804c..002e8054, reached when activation has no path, waypoints end, target is too distant between shots, or recovery must resume pursuit. The same state byte dispatches existing BLARG_TROOPER_APPROACH_TARGET and its target-heading/movement branch at 002e7948..002e7ba0. --- src/overlays/l12/mobys/blarg_trooper.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l12/mobys/blarg_trooper.c b/src/overlays/l12/mobys/blarg_trooper.c index d6a7ad47a2..1746f2153b 100644 --- a/src/overlays/l12/mobys/blarg_trooper.c +++ b/src/overlays/l12/mobys/blarg_trooper.c @@ -183,7 +183,7 @@ void blarg_trooper_update(struct Moby *moby) { manipulator_set_scale(trooper_update_vars + 0x120, 3.0f); if (D_L12_0015F5C4 == 2) goto hide; - if (moby->state >= 3) { + if (moby->state >= BLARG_TROOPER_APPROACH_TARGET) { moby->flags &= 0xffbe; if (TROOPER_CHILD__blarg_trooper_update) TROOPER_CHILD__blarg_trooper_update->flags &= 0xffbe; @@ -268,7 +268,7 @@ void blarg_trooper_update(struct Moby *moby) { if (TROOPER_CHILD__blarg_trooper_update) TROOPER_CHILD__blarg_trooper_update->flags |= 0x41; } - moby->state = 2; + moby->state = BLARG_TROOPER_WAIT_FOR_ACTIVATION; break; } case BLARG_TROOPER_WAIT_FOR_ACTIVATION: { @@ -305,7 +305,7 @@ void blarg_trooper_update(struct Moby *moby) { else { TROOPER_I__blarg_trooper_update(0x260) = select_point_index_by_distance( &moby->pos, ((char *)l12_paths[TROOPER_I__blarg_trooper_update(0x254)]), 0.0f); - moby->state = 1; + moby->state = BLARG_TROOPER_FOLLOW_WAYPOINTS; } break; } @@ -330,7 +330,7 @@ void blarg_trooper_update(struct Moby *moby) { goto state3; else if (vector_distance_xy(&moby->pos, &target->pos) < TROOPER_F__blarg_trooper_update(0x264)) - moby->state = 3; + moby->state = BLARG_TROOPER_APPROACH_TARGET; break; } case BLARG_TROOPER_APPROACH_TARGET: { @@ -387,7 +387,7 @@ void blarg_trooper_update(struct Moby *moby) { if (moby->anim_flags & 2) { if (moby->prev_seq != 10 && moby->seq == moby->prev_seq) blend_moby_animation_ex(moby, 10, 0, scale_game_frames(5), 5); - moby->state = 6; + moby->state = BLARG_TROOPER_FIRE_PROJECTILE; } break; } @@ -417,7 +417,7 @@ void blarg_trooper_update(struct Moby *moby) { if (moby->anim_flags & 2) { if (moby->prev_seq != 5 && moby->seq == moby->prev_seq) blend_moby_animation_ex(moby, 5, 0, scale_game_frames(8), 5); - moby->state = 7; + moby->state = BLARG_TROOPER_WAIT_BETWEEN_SHOTS; } break; } @@ -435,7 +435,7 @@ void blarg_trooper_update(struct Moby *moby) { goto state3; angle = fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y); if (fast_difference_between_rotations(moby->rot.z, angle) > 0.4886922f) - moby->state = 3; + moby->state = BLARG_TROOPER_APPROACH_TARGET; break; } case BLARG_TROOPER_RETURN_HOME: { @@ -449,7 +449,7 @@ void blarg_trooper_update(struct Moby *moby) { TROOPER_F__blarg_trooper_update(0x188) = angle * 0.7f; TROOPER_F__blarg_trooper_update(0x208) = angle * 0.4f; if (vector_distance_xy(&moby->pos, trooper_update_vars + 0x220) < 1.0f) - moby->state = 2; + moby->state = BLARG_TROOPER_WAIT_FOR_ACTIVATION; break; } case BLARG_TROOPER_KNOCKBACK_RECOVERY: { @@ -461,12 +461,12 @@ void blarg_trooper_update(struct Moby *moby) { angle = fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y); if (fast_difference_between_rotations(moby->rot.z, angle) < 0.12217305f) { state5: - moby->state = 5; + moby->state = BLARG_TROOPER_PREPARE_SHOT; break; } } state3: - moby->state = 3; + moby->state = BLARG_TROOPER_APPROACH_TARGET; break; } if (!(moby->pos.z < 2.0f)) From 010e418e4f44894954a834da1d6bd611f17075a5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:23:11 +0000 Subject: [PATCH 1112/1502] decomp: clarify names in update_fighter_jet_flight domain_0_value_2 -> FIGHTER_JET_STATE_MOUNT_PLAYER: Retail 002ba18c preserves the caller's jet_moby in s3; 002ba928 loads its +0x20 state byte and 002ba930 compares against 2, selecting direct camera offset initialization rather than springs (002ba96c..002ba978). The supplied fighter_jet_update passes this same jet_moby while handling its established FIGHTER_JET_STATE_MOUNT_PLAYER=2, immediately before changing it to FLIGHT. Thus this is the jet mount state, not a hero or camera mode. domain_1_value_2 -> FIGHTER_JET_STATE_MOUNT_PLAYER: Retail 002baaf8..002bab04 compares 2 against the same s3+0x20 jet state byte retained from a0 at 002ba18c; 002bab0c..002bab18 directly copies camera rotation into flight data instead of springing it. fighter_jet_update calls this function with jet_moby during established FIGHTER_JET_STATE_MOUNT_PLAYER=2 before assigning FLIGHT, proving the same mount-state domain as the first camera comparison. domain_2_value_6 -> FIGHTER_JET_STATE_STOP_DEATH_SOUNDS: After collision damage makes player health negative at 002bae1c..002bae30, retail spawns the explosion at 002baef4, sets flight-data +0x62 death_timer from scale_game_frames(240) at 002baefc..002baf04, then stores 6 into the caller's jet_moby state byte s3+0x20 at 002baf08..002baf0c. The supplied fighter_jet_update names this same jet state FIGHTER_JET_STATE_STOP_DEATH_SOUNDS=6; its case releases engine/weapon voices and transitions to WAIT_FOR_DEATH_RESET. domain_3_value_6 -> FIGHTER_JET_STATE_STOP_DEATH_SOUNDS: The no-hit-moby collision branch zeros health at 002baf70, spawns an explosion at 002baf84, sets jet flags and a 240-frame death timer at 002baf8c..002bafa0, then stores 6 into the same jet_moby+0x20 state byte at 002bafa4..002bafa8. fighter_jet_update receives that same object and its established FIGHTER_JET_STATE_STOP_DEATH_SOUNDS=6 case stops the engine/weapon voices before WAIT_FOR_DEATH_RESET. This is the jet death transition, not HERO_STATE_FALL or VOICE_SLOT_STOP_PENDING. --- src/overlays/l13/mobys/fighter_jet.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/overlays/l13/mobys/fighter_jet.c b/src/overlays/l13/mobys/fighter_jet.c index 3defad8c37..52625e478e 100644 --- a/src/overlays/l13/mobys/fighter_jet.c +++ b/src/overlays/l13/mobys/fighter_jet.c @@ -1216,6 +1216,10 @@ extern void update_view_context(void) __asm__("FUN_001f2d98"); void update_fighter_jet_flight(void *moby_arg, void *data_arg) __asm__("FUN_L13_002ba178"); void update_fighter_jet_flight(void *moby_arg, void *data_arg) { + enum { + FIGHTER_JET_STATE_MOUNT_PLAYER = 2, + FIGHTER_JET_STATE_STOP_DEATH_SOUNDS = 6 + }; FlightMoby *moby = moby_arg; FlightData *jet_flight_state = data_arg; FlightVec old_pos; @@ -1441,7 +1445,7 @@ void update_fighter_jet_flight(void *moby_arg, void *data_arg) { camera.v.rot[2] = 0.65f; *(u128 *)camera_offsets[0] = *(u128 *)camera.v.pos; *(u128 *)camera_offsets[1] = *(u128 *)camera.v.rot; - if (moby->state == 2) { + if (moby->state == FIGHTER_JET_STATE_MOUNT_PLAYER) { jet_flight_state->camera_offset_x = camera_offsets[jet_flight_state->camera_mode][0]; jet_flight_state->camera_offset_y = camera_offsets[jet_flight_state->camera_mode][1]; jet_flight_state->camera_offset_z = camera_offsets[jet_flight_state->camera_mode][2]; @@ -1479,7 +1483,7 @@ void update_fighter_jet_flight(void *moby_arg, void *data_arg) { fast_subtract_rotations(fast_add_rotations(jet_flight_state->pitch, 0.09817477f), jet_flight_state->steer_y * (frame_scale_gp * 0.012271847f)); camera.v.rot[2] = jet_flight_state->yaw; - if (moby->state == 2) { + if (moby->state == FIGHTER_JET_STATE_MOUNT_PLAYER) { qcopy(&jet_flight_state->camera_roll, camera.v.rot); } else { spring_angle((char *)&jet_flight_state->camera_roll, @@ -1574,7 +1578,7 @@ void update_fighter_jet_flight(void *moby_arg, void *data_arg) { -1, 0); jet_flight_state->death_timer = scale_game_frames(240); - moby->state = 6; + moby->state = FIGHTER_JET_STATE_STOP_DEATH_SOUNDS; } jet_flight_state->hit_cooldown = scale_game_frames(10); } @@ -1600,7 +1604,7 @@ void update_fighter_jet_flight(void *moby_arg, void *data_arg) { 0); moby->flags |= 0x41; jet_flight_state->death_timer = scale_game_frames(240); - moby->state = 6; + moby->state = FIGHTER_JET_STATE_STOP_DEATH_SOUNDS; } } } From c1507e47c28b676c19d7edca13c965f358d2cb80 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:25:18 +0000 Subject: [PATCH 1113/1502] decomp: clarify names in update_blarg_heavy_interceptor domain_0_value_8 -> INTERCEPTOR_STATE_GROUP_EFFECTS_CONTROLLER: Retail 0x002ac668 loads object state at s4+0x20; 0x002ac674..0x002ac694 compares 8 and exclusively updates light-ring alpha (0x002aed50) and registers draw_blarg_heavy_interceptor_group_effects. Source callback draws selected group members' beams/rings, proving group-effects controller state. domain_10_value_5 -> INTERCEPTOR_STATE_FOLLOW_RETURN_PATH: Retail 0x002aceb8..0x002acf24 waits for try_retract_turret_group, stores 5 at object+0x20, initializes path pvars+0x204 at count-2, and advances with negative direction. The same selector's existing FOLLOW_RETURN_PATH=5 case continues that helper until completion. domain_11_value_6 -> INTERCEPTOR_STATE_REJOIN_PATROL: Retail 0x002acf7c..0x002acfec detects return-path completion, queries a nearby segment on pvars+0x78, saves segment/distance and writes state 6 at object+0x20. The established REJOIN_PATROL=6 branch maps that progress to the patrol path and eases the moby back. domain_12_value_1 -> INTERCEPTOR_STATE_PATROL_AND_SCAN: Retail 0x002ad150..0x002ad178 measures distance to the sampled patrol position and stores 1 at object+0x20 when below 0.5. This returns the same state selector from REJOIN_PATROL to the existing PATROL_AND_SCAN=1 case, which resumes patrol sampling and target scans. domain_13_value_9 -> INTERCEPTOR_STATE_DEATH_FALL: Retail 0x002ad208..0x002ad434 initializes death timer, launch velocity and spin, then stores 9 into object+0x20. The same selector's established DEATH_FALL=9 case at 0x002ad438 integrates velocity, applies drag/gravity and removes on bounds, timer or collision. domain_14_value_0 -> INTERCEPTOR_STATE_INITIALIZE: Retail 0x002ad7c0..0x002ad7c4 loads signed object+0x20 and checks negativity before animation particle upkeep. Source spells this (s8)moby->state >= 0; the zero boundary is the existing INITIALIZE=0 member of this exact selector, not a boolean or hero state. domain_15_value_1 -> INTERCEPTOR_STATE_PATROL_AND_SCAN: Retail 0x002ad804..0x002ad838 reloads object+0x20, compares 1 and allocates voice type 0 if needed. This is the same moby->state byte dispatched into existing PATROL_AND_SCAN=1, so the audio guard should reuse that canonical local member. domain_16_value_3 -> INTERCEPTOR_STATE_TRACK_TARGET: Retail 0x002ad83c..0x002ad848 tests object+0x20 in the range 3..4 before voice type 2 upkeep. Source splits this into equality with 3 or 4; the existing local state switch identifies 3 as TRACK_TARGET, with target-position easing and timer behavior. domain_17_value_4 -> INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY: Retail 0x002ad83c..0x002ad874 tests object+0x20 in 3..4 for shared voice type 2 upkeep. Source's equality with 4 uses the exact field dispatched by existing WAIT_FOR_GROUP_READY=4, whose branch gates return travel on turret group readiness. domain_1_value_0 -> INTERCEPTOR_STATE_INITIALIZE: Retail 0x002ac704..0x002ac70c tests object+0x20 states 1 through 6; source expresses the lower bound as moby->state > 0. The same field dispatches the established INTERCEPTOR_STATE_INITIALIZE=0 at 0x002ac74c..0x002ac774, so reuse its canonical boundary member. domain_2_value_7 -> INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL: Retail 0x002ac704..0x002ac70c restricts object+0x20 to states 1 through 6, matching source moby->state < 7. This is the same selector as the local INITIALIZE_DEATH_FALL=7 case, whose 0x002ad208 onward initializes death timer and launch velocity; reuse that upper boundary. domain_3_value_8 -> INTERCEPTOR_STATE_GROUP_EFFECTS_CONTROLLER: Retail 0x002ac788..0x002ac7e4 tests pvars+0x1B6==1, disables collision, sets state byte object+0x20 to 8, and counts group members. On subsequent updates 0x002ac674..0x002ac694 updates ring alpha and registers the callback that draws group-member effects, proving the controller role. domain_4_value_1 -> INTERCEPTOR_STATE_PATROL_AND_SCAN: Retail 0x002ac974 stores 1 into the same object+0x20 field dispatched at 0x002ac74c after path/manipulator initialization. The local enum already names case 1 PATROL_AND_SCAN, whose branch advances paired patrol paths and scans spatial queries for targets. domain_5_value_3 -> INTERCEPTOR_STATE_TRACK_TARGET: Retail 0x002ac9a8..0x002ac9c4 tests turret group activation, writes 3 to object+0x20 and initializes the tracking timer. The same state selector's established case 3 TRACK_TARGET at 0x002acb74 follows stored target pvars+0x18C until loss or expiry. domain_6_value_3 -> INTERCEPTOR_STATE_TRACK_TARGET: Retail 0x002acb50..0x002acb70 activates waiting turrets, writes 3 to object+0x20, then sets tracking duration at pvars+0x1F2. This enters the existing TRACK_TARGET=3 case on the same moby->state selector, which eases the aim point toward the stored target. domain_7_value_4 -> INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY: Retail 0x002accc0..0x002accfc handles negative target state or tracking timer expiry, resets return progress and stores 4 into object+0x20. The same selector's existing WAIT_FOR_GROUP_READY=4 case waits for try_retract_turret_group before entering return-path movement. domain_8_value_4 -> INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY: Retail 0x002acba0 branches on missing target to 0x002accec..0x002accfc, clearing return progress and storing state 4 at object+0x20. This is the same moby->state domain as established WAIT_FOR_GROUP_READY=4, whose branch gates the return transition on turret-group readiness. domain_9_value_4 -> INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY: Retail 0x002acd98..0x002acda0 reloads object+0x20 and compares 4 before return-position easing and group-retraction checks. Source shares this block after TRACK_TARGET fallthrough, so the guard selects the existing WAIT_FOR_GROUP_READY=4 member of that exact state domain. --- .../l14/mobys/blarg_heavy_interceptor.c | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/overlays/l14/mobys/blarg_heavy_interceptor.c b/src/overlays/l14/mobys/blarg_heavy_interceptor.c index ed89730b6b..e4da24d936 100644 --- a/src/overlays/l14/mobys/blarg_heavy_interceptor.c +++ b/src/overlays/l14/mobys/blarg_heavy_interceptor.c @@ -258,7 +258,7 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { INTERCEPTOR_STATE_REJOIN_PATROL = 6, INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL = 7, INTERCEPTOR_STATE_DEATH_FALL = 9 - }; + } ; enum { INTERCEPTOR_STATE_GROUP_EFFECTS_CONTROLLER = 8}; BlargHeavyInterceptorVars *moby_vars = (BlargHeavyInterceptorVars *)moby->pvars; float vector_scratch[4]; float secondary_vector_scratch[4]; @@ -272,7 +272,7 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { FUN_0020c828(moby); return; } - if (moby->state == 8) { + if (moby->state == INTERCEPTOR_STATE_GROUP_EFFECTS_CONTROLLER) { FUN_L14_002aed50_c618(moby); add_draw_callback(draw_blarg_heavy_interceptor_group_effects, moby); return; @@ -289,7 +289,7 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { } } process_blarg_heavy_interceptor_hit_reactions(moby); - if (moby->state > 0 && moby->state < 7) { + if (moby->state > INTERCEPTOR_STATE_INITIALIZE && moby->state < INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL) { if (fast_vec_dist(&moby->pos, D_L14_001674C0) < 40.0f) { FUN_L00_0025a120(moby); } @@ -302,7 +302,7 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { moby->flags = (moby->flags | 0x41) & 0xEFFF; moby->collision = 0; moby->update_dist = 0xFF; - moby->state = 8; + moby->state = INTERCEPTOR_STATE_GROUP_EFFECTS_CONTROLLER; moby_vars->unk58 = truncate_float_to_s32(17.0f); moby_vars->unk5A = truncate_float_to_s32(6.0f); moby_vars->group_member_count = count_moby_group_members(moby); @@ -342,7 +342,7 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { attach_manipulator_c618(moby, 1, moby_vars->unk120); moby_vars->unk1C0[2] = moby_vars->unk1C0[1] = 0.0f; *(int *)&moby_vars->unk180[3] = 0; - moby->state = 1; + moby->state = INTERCEPTOR_STATE_PATROL_AND_SCAN; moby->command = 0; break; case INTERCEPTOR_STATE_PATROL_AND_SCAN: { @@ -353,7 +353,7 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { (blarg_heavy_interceptor_patrol_glow_green_gp << 8) | blarg_heavy_interceptor_patrol_glow_red_gp; if (is_turret_group_activated_or_empty(moby_vars->turret_group)) { - moby->state = 3; + moby->state = INTERCEPTOR_STATE_TRACK_TARGET; moby_vars->timer_1F2 = scale_game_frames(blarg_heavy_interceptor_target_tracking_duration_frames_gp); } @@ -397,7 +397,7 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { } *(s32 *)&moby_vars->unk1D0[0] = -1; activate_waiting_turrets_in_group(moby_vars->turret_group); - moby->state = 3; + moby->state = INTERCEPTOR_STATE_TRACK_TARGET; moby_vars->timer_1F2 = scale_game_frames(blarg_heavy_interceptor_target_tracking_duration_frames_gp); break; @@ -439,13 +439,13 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { moby_vars->unk8C = 0.0f; moby_vars->path_point = 0; moby_vars->unk208 = 0; - moby->state = 4; + moby->state = INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY; } } else { moby_vars->path_point = 0; moby_vars->unk8C = 0.0f; moby_vars->unk208 = 0; - moby->state = 4; + moby->state = INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY; } case INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY: moby->glow_color = 0xFF000000 | @@ -466,7 +466,7 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { moby_vars->flags |= 8; FUN_L14_002aea08_c618(moby); } - if (moby->state == 4) { + if (moby->state == INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY) { if (moby->prev_seq == 0) { blend_moby_animation_c618(moby, 2, 0, 5); } @@ -490,7 +490,7 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { if (try_retract_turret_group(moby_vars->turret_group)) { LevelPath *p = l14_paths[moby_vars->patrol_path]; - moby->state = 5; + moby->state = INTERCEPTOR_STATE_FOLLOW_RETURN_PATH; moby_vars->path_point = p->count - 2; moby_vars->unk8C = p->points[moby_vars->path_point].f[3]; moby_vars->unk208 = 0; @@ -512,7 +512,7 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { moby_vars->path_segment = near_seg; moby_vars->unk1C0[3] = near_t; moby_vars->unk200 = 0; - moby->state = 6; + moby->state = INTERCEPTOR_STATE_REJOIN_PATROL; } break; case INTERCEPTOR_STATE_REJOIN_PATROL: { @@ -558,7 +558,7 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { 0.0f); update_blarg_heavy_interceptor_aim_transforms(moby, 0); if (fast_vec_dist(&moby->pos, vector_scratch) < 0.5f) { - moby->state = 1; + moby->state = INTERCEPTOR_STATE_PATROL_AND_SCAN; } FUN_L00_0025d808_c618(((int *)l14_paths[moby_vars->unk78]), vector_scratch, @@ -644,7 +644,7 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { moby_vars->yaw_drift = randf_sym(0.0f, 0.08726646f); moby->rot.x = fast_add_rotations(moby->rot.x, randf_sym(0.0f, 0.7853982f)); moby->rot.y = fast_add_rotations(moby->rot.y, randf_sym(0.0f, 0.7853982f)); - moby->state = 9; + moby->state = INTERCEPTOR_STATE_DEATH_FALL; FUN_L14_002aead8_c618(moby); return; } @@ -747,17 +747,17 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { return; } } - if ((s8)moby->state >= 0 && moby->prev_seq == 1) { + if ((s8)moby->state >= INTERCEPTOR_STATE_INITIALIZE && moby->prev_seq == 1) { if (moby->command == 1) { spawn_particles_at_shape_points(moby, D_L14_0015F580, 0xFFFF); } } else { moby->command = 0; } - if (moby->state == 1 && !voice_is_playing(moby, *(s32 *)&moby_vars->unk1D0[0])) { + if (moby->state == INTERCEPTOR_STATE_PATROL_AND_SCAN && !voice_is_playing(moby, *(s32 *)&moby_vars->unk1D0[0])) { *(s32 *)&moby_vars->unk1D0[0] = allocate_voice_c618(0, 4, moby); } - if ((moby->state == 3 || moby->state == 4) && + if ((moby->state == INTERCEPTOR_STATE_TRACK_TARGET || moby->state == INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY) && !voice_is_playing(moby, *(s32 *)&moby_vars->unk1D0[0])) { *(s32 *)&moby_vars->unk1D0[0] = allocate_voice_c618(2, 4, moby); } From a958c46f181819e55100d0fb874673e354819a71 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:25:18 +0000 Subject: [PATCH 1114/1502] decomp: clarify names in update_hoven_anklebiter domain_0_value_9 -> ANKLEBITER_DORMANT: 002e1c94-002e1cec: initialization tests sleep at data+0x2bc, saves home, stores 9 to moby+0x20 and disables collision. This is the same byte dispatched by the existing ANKLEBITER_DORMANT case. domain_11_value_12 -> ANKLEBITER_LEAP_TO_HOME: 002e24e0-002e2590: trajectory helper receives current position and home, launch speed and gravity; fall setup follows and 12 is stored at moby+0x20. Existing case 12 steps that home-leap motion. domain_12_value_14 -> ANKLEBITER_LAND_AFTER_LEAP: 002e2594-002e25d0: home leap motion result bit 1 selects state 14 at moby+0x20 and landing animation 9. Existing case 14 waits for animation flag 2 before pursuit. domain_13_value_4 -> ANKLEBITER_PURSUE_TARGET: 002e25f8-002e2674: landing animation flag 2 selects 4 at moby+0x20, clears blocked, initializes circle heading/timer and selects pursuit animation. Reuses the same state domain's pursuit case. domain_14_value_4 -> ANKLEBITER_PURSUE_TARGET: 002e26dc-002e26f0 branches to 002e2ab0: facing animation completion selects 4 at moby+0x20, clears blocked and selects pursuit animation. Existing case 4 performs target-heading movement. domain_15_value_6 -> ANKLEBITER_RETURN_HOME: 002e2778-002e2788 branches to 002e28dc-002e28e4 when movement returns 2: state 6 is stored at moby+0x20 and return_timer cleared. Existing case 6 computes home heading and moves home. domain_16_value_5 -> ANKLEBITER_MELEE_ATTACK: 002e27e4-002e2834: target XY distance below 1.5 selects 5 at moby+0x20 and animation 4. Existing case 5 gates its target interaction by animation window, reach and facing. domain_17_value_6 -> ANKLEBITER_RETURN_HOME: 002e28b8-002e28e4: loss-of-range pursuit path with proximity/random gate writes 6 at moby+0x20 and clears return_timer. Existing case 6 moves toward home and returns to idle near home. domain_18_value_4 -> ANKLEBITER_PURSUE_TARGET: 002e2a78-002e2ab8: completed melee animation and target XY distance at least 2 lead to state 4 at moby+0x20, blocked reset and pursuit animation. Same selector's case 4 pursues target. domain_19_value_1 -> ANKLEBITER_IDLE: 002e2af4-002e2b40: return-home XY distance below 2 selects state 1 at moby+0x20 and animation 0. Existing case 1 performs idle movement and target detection. domain_1_value_11 -> ANKLEBITER_WAIT_FOR_LEAP_TRIGGER: 002e1cf0-002e1d2c: nonzero home[3] selects 11 at moby+0x20 with collision disabled. The same selector's case 11 at 002e2408 waits for target range/height or proximity before preparing the home leap. domain_20_value_4 -> ANKLEBITER_PURSUE_TARGET: 002e2ba4-002e2bec: target within home range and elapsed return_timer over scaled 70 lead to group alert then state 4 via 002e23f4. The state write resets blocked and selects pursuit animation. domain_21_value_4 -> ANKLEBITER_PURSUE_TARGET: 002e2bf0-002e2c14: return-home proximity 1 branch stores 4 at moby+0x20, clears blocked and selects pursuit animation. This is the same selector as existing ANKLEBITER_PURSUE_TARGET. domain_22_value_10 -> ANKLEBITER_RECOVER_AFTER_KNOCKBACK: 002e2c30-002e2c70: knockback fall motion result bit 1 selects 10 at moby+0x20 and animation 13. Existing case 10 resumes pursuit after interpolated animation value exceeds 29. domain_23_value_6 -> ANKLEBITER_RETURN_HOME: 002e2ca4-002e2cc4: controlled-motion helper completion selects 6 at moby+0x20 and clears return_timer/stuck. Existing case 6 performs home-heading movement and idle transition. domain_24_value_4 -> ANKLEBITER_PURSUE_TARGET: 002e2cc8-002e2cf8: recovery animation value above 29 selects 4 at moby+0x20, clears blocked and selects pursuit animation. Reuse the existing pursuit state for this same selector. domain_25_value_15 -> ANKLEBITER_DEATH_EFFECTS_AND_REMOVE: 002e2d04-002e2d7c: death motion/animation completion stops animation, records removal and stores 15 at moby+0x20. Existing case 15 emits particles and death sparks then removes the moby. domain_26_value_9 -> ANKLEBITER_DORMANT: 002e2df8-002e2e04: enabled-moby postprocessing reads the same moby+0x20 state byte used for dispatch and skips state 9. Existing ANKLEBITER_DORMANT case and sleep initialization establish this domain member. domain_27_value_8 -> ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME: 002e2e00-002e2e0c: normal collision postprocessing skips state 8 from the same moby+0x20 dispatch byte. Existing case 8 at 002e2ca4-002e2cc4 runs controlled motion then selects RETURN_HOME on completion. domain_2_value_1 -> ANKLEBITER_IDLE: 002e1d30-002e1d58: initialization saves home, stores 1 at moby+0x20 and selects animation 0. The existing case ANKLEBITER_IDLE uses this selector for home-relative target checks and idle wandering. domain_4_value_3 -> ANKLEBITER_FACE_TARGET_BEFORE_PURSUIT: 002e1ed0-002e1f2c: target range and height tests lead to storing 3 at moby+0x20. Existing case 3 at 002e2680-002e26f0 turns toward the target and resumes pursuit when animation flag 2 is set. domain_5_value_3 -> ANKLEBITER_FACE_TARGET_BEFORE_PURSUIT: 002e1fd4-002e203c: idle proximity branch sets circle heading/timer then writes 3 to the same moby+0x20 state selector. Existing case 3 turns toward target before selecting pursuit, so reuse its established member. domain_7_value_9 -> ANKLEBITER_DORMANT: 002e2194-002e21f0: group enumeration returns moby pointers at sp+0x50; lb/lbu read each member's state at +0x20, and xori 9 excludes dormant members from group_count. Source types iterator as AnklebiterMoby and uses its state in the same anklebiter group activation gate. domain_8_value_13 -> ANKLEBITER_ACTIVATE_FROM_DORMANCY: 002e22bc-002e22fc: dormant activation gates store 13 at moby+0x20, select animation 7 and scatter sparks. Existing case 13 restores collision and turns toward the target before pursuit. domain_9_value_4 -> ANKLEBITER_PURSUE_TARGET: 002e237c-002e2404: activation animation flag 2 gates state 4 at moby+0x20, clears blocked and calls pursuit-animation selection. The same selector dispatches existing ANKLEBITER_PURSUE_TARGET. --- src/overlays/l12/mobys/hoven_anklebiter.c | 48 +++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/overlays/l12/mobys/hoven_anklebiter.c b/src/overlays/l12/mobys/hoven_anklebiter.c index 03335900ad..1b42aaee5a 100644 --- a/src/overlays/l12/mobys/hoven_anklebiter.c +++ b/src/overlays/l12/mobys/hoven_anklebiter.c @@ -327,19 +327,19 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { case ANKLEBITER_INITIALIZE: if (data->sleep) { qcopy(data->home, moby->pos); - moby->state = 9; + moby->state = ANKLEBITER_DORMANT; if (moby->anim != 12) blend_moby_animation(moby, 12, 0, 3); moby->collision = 0; moby->flags = (moby->flags | 0x41) & 0xEFFF; } else if (data->home[3] != 0.0f) { - moby->state = 11; + moby->state = ANKLEBITER_WAIT_FOR_LEAP_TRIGGER; moby->joints = 0; moby->flags &= 0xEFFF; moby->collision = 0; } else { qcopy(data->home, moby->pos); - moby->state = 1; + moby->state = ANKLEBITER_IDLE; if (moby->anim != 0) blend_moby_animation(moby, 0, 0, 3); } @@ -382,7 +382,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { idle_angle = fast_arc_tan(target->pos[0] - moby->pos[0], target->pos[1] - moby->pos[1]); idle_difference = fast_difference_between_rotations(moby->rot[2], idle_angle); if (idle_distance < data->range && absolute_float(moby->pos[2] - target->pos[2]) < 4.0f) { - moby->state = 3; + moby->state = ANKLEBITER_FACE_TARGET_BEFORE_PURSUIT; if (idle_difference < 0.9599311f) { if (moby->anim != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(5)); @@ -395,7 +395,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { data->circle_rate = -data->circle_rate; data->circle_angle = data->circle_rate * 0.017453292f; data->circle_timer = scale_game_frames((int)random_float_between(30.0f, 90.0f)); - moby->state = 3; + moby->state = ANKLEBITER_FACE_TARGET_BEFORE_PURSUIT; if (moby->anim != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(7)); moby->proximity = 0; @@ -421,7 +421,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { count = 0; func_L00_0025A208_2E2EF0((int *)&iterator, moby->group, 0, 0); while (iterator) { - if ((signed char)iterator->state >= 0 && iterator->state != 9) + if ((signed char)iterator->state >= 0 && iterator->state != ANKLEBITER_DORMANT) count++; func_L00_0025A2F0_2E2EF0((int *)&iterator, (int)iterator, 0, 0); } @@ -438,7 +438,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { } else if (!((moby->proximity & 1) && fast_dec_timer_s16(&data->group_timer)) && moby->proximity != 7) break; - moby->state = 13; + moby->state = ANKLEBITER_ACTIVATE_FROM_DORMANCY; if (moby->anim != 7) blend_moby_animation(moby, 7, 0, 1); moby->flags |= 0x1000; @@ -456,7 +456,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { data->circle_rate = -data->circle_rate; data->circle_angle = data->circle_rate * 0.017453292f; data->circle_timer = scale_game_frames((int)random_float_between(30.0f, 90.0f)); - moby->state = 4; + moby->state = ANKLEBITER_PURSUE_TARGET; data->blocked = 0; select_hoven_anklebiter_pursuit_animation((struct Moby *)moby); moby->proximity = 0; @@ -486,14 +486,14 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { setup_fall54(moby->rot[2], (char *)moby, data->fall, 8, 1, 0); data->fall_a = 5.0f; data->fall_b = 10.0f; - moby->state = 12; + moby->state = ANKLEBITER_LEAP_TO_HOME; moby->flags |= 0x1000; moby->collision = *(int *)(moby->model + 0x10); } break; case ANKLEBITER_LEAP_TO_HOME: if (step_moby_motion(moby, data->fall) & 1) { - moby->state = 14; + moby->state = ANKLEBITER_LAND_AFTER_LEAP; if (moby->anim != 9) blend_moby_animation(moby, 9, 8, scale_game_frames(7)); return; @@ -505,7 +505,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { break; case ANKLEBITER_LAND_AFTER_LEAP: if (moby->anim_flags & 2) { - moby->state = 4; + moby->state = ANKLEBITER_PURSUE_TARGET; data->blocked = 0; if (random_integer_below(256) & 1) data->circle_rate = -data->circle_rate; @@ -518,7 +518,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { angle = fast_arc_tan(target->pos[0] - moby->pos[0], target->pos[1] - moby->pos[1]); approach_w((char *)moby, &data->turn_velocity, angle, 0.03f, 0.3f, D_0015ED6C * 6.2831855f); if (moby->anim_flags & 2) { - moby->state = 4; + moby->state = ANKLEBITER_PURSUE_TARGET; data->blocked = 0; select_hoven_anklebiter_pursuit_animation((struct Moby *)moby); } @@ -533,7 +533,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { data->look_angle = look_difference; if (move_hoven_anklebiter_toward_heading( (struct Moby *)moby, fast_add_rotations(chase_angle, data->circle_angle)) == 2) { - moby->state = 6; + moby->state = ANKLEBITER_RETURN_HOME; data->return_timer = 0; } else { if (fast_dec_timer(&data->circle_timer)) { @@ -542,7 +542,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { } fast_vec_sub(target_report_or_vector_scratch.v0, target->pos, data->home); if (vector_distance_xy(moby->pos, target->pos) < 1.5f) { - moby->state = 5; + moby->state = ANKLEBITER_MELEE_ATTACK; if (moby->anim != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(5)); } else if (fast_vec_length(target_report_or_vector_scratch.v0) < data->range + 5.5f && @@ -550,7 +550,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { if (moby->group != 255) FUN_L01_0026e090(moby->group, 1); } else if (moby->proximity != 1 && random_integer_below(9) == 0) { - moby->state = 6; + moby->state = ANKLEBITER_RETURN_HOME; data->return_timer = 0; } } @@ -581,7 +581,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { 1.0f); } if ((moby->anim_flags & 2) && vector_distance_xy(moby->pos, target->pos) >= 2.0f) { - moby->state = 4; + moby->state = ANKLEBITER_PURSUE_TARGET; data->blocked = 0; select_hoven_anklebiter_pursuit_animation((struct Moby *)moby); } @@ -592,7 +592,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { (struct Moby *)moby, fast_arc_tan(data->home[0] - moby->pos[0], data->home[1] - moby->pos[1])); if (vector_distance_xy(moby->pos, data->home) < 2.0f) { - moby->state = 1; + moby->state = ANKLEBITER_IDLE; if (moby->anim != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(7)); } @@ -608,12 +608,12 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { if (data->return_timer > scale_game_frames(70)) { if (moby->group != 255) FUN_L01_0026e090(moby->group, 1); - moby->state = 4; + moby->state = ANKLEBITER_PURSUE_TARGET; data->blocked = 0; select_hoven_anklebiter_pursuit_animation((struct Moby *)moby); } } else if (moby->proximity == 1) { - moby->state = 4; + moby->state = ANKLEBITER_PURSUE_TARGET; data->blocked = 0; select_hoven_anklebiter_pursuit_animation((struct Moby *)moby); } @@ -625,7 +625,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { if (moby->group != 255) FUN_L01_0026e090(moby->group, 1); if (step_moby_motion(moby, data->fall) & 1) { - moby->state = 10; + moby->state = ANKLEBITER_RECOVER_AFTER_KNOCKBACK; if (moby->anim != 13) blend_moby_animation(moby, 13, 8, scale_game_frames(8)); return; @@ -637,14 +637,14 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { break; case ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME: if (func_L00_002DDEA0_2E2EF0(moby, data->fall)) { - moby->state = 6; + moby->state = ANKLEBITER_RETURN_HOME; data->return_timer = 0; data->stuck = 0; } break; case ANKLEBITER_RECOVER_AFTER_KNOCKBACK: if (compute_interpolated_record_value(moby) > 29.0f) { - moby->state = 4; + moby->state = ANKLEBITER_PURSUE_TARGET; data->blocked = 0; select_hoven_anklebiter_pursuit_animation((struct Moby *)moby); return; @@ -656,7 +656,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { (compute_interpolated_record_value(moby) > 37.0f && moby->anim_end == moby->anim)) { moby->anim_rate = 0.0f; mark_moby_for_removal_cf(moby, 0, -1); - moby->state = 15; + moby->state = ANKLEBITER_DEATH_EFFECTS_AND_REMOVE; moby->flags |= 8; } else if (moby->pos[2] < 10.0f) { mark_moby_for_removal_cf(moby, 0, -1); @@ -676,7 +676,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { return; } } - if (moby->enabled && moby->state != 9 && moby->state != 8) { + if (moby->enabled && moby->state != ANKLEBITER_DORMANT && moby->state != ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME) { func_L00_00263950_2E2EF0( (char *)moby, data->collision_data, 0, D_0015ED64 * 0.018f, D_0015ED64 * 0.3f); if (moby->enabled && fast_vec_dist(moby->pos, D_L12_00167240) < 28.0f) { From 782dc05a0e4dd39efe1d5e09929141d3a9a55972 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:25:19 +0000 Subject: [PATCH 1115/1502] decomp: clarify names in helicopter_update domain_0_value_0 -> HELICOPTER_INITIALIZE: 002c5694..002c56a0 loads moby+0x20 and excludes zero from the reset-to-wait guard. This is the same byte selected by the state switch at 002c580c..002c582c and the existing HELICOPTER_INITIALIZE case. domain_11_value_2 -> HELICOPTER_FOLLOW_ENTRY_PATH: 002c5abc..002c5acc writes 2 to moby+0x20 when pvars+0x1ac entry_path is present. Existing HELICOPTER_FOLLOW_ENTRY_PATH case reads that entry_path and interpolates its points starting at 002c5b48. domain_12_value_3 -> HELICOPTER_APPROACH_AREA_PATH: 002c5abc..002c5b28 routes absent entry_path to state 3 at moby+0x20. Same selector's existing HELICOPTER_APPROACH_AREA_PATH case scans area_path and steers toward a qualifying point at 002c5e60..002c5f10. domain_14_value_2 -> HELICOPTER_FOLLOW_ENTRY_PATH: 002c5b10..002c5b20 writes 2 into moby+0x20 when entry_path is present on the alternative activation route. This enters existing HELICOPTER_FOLLOW_ENTRY_PATH, which reads pvars+0x1ac at 002c5b48. domain_15_value_3 -> HELICOPTER_APPROACH_AREA_PATH: 002c5b10..002c5b28 writes 3 to moby+0x20 when entry_path is absent on the alternative activation route. Existing HELICOPTER_APPROACH_AREA_PATH uses pvars+0x194 area_path at 002c5e60. domain_17_value_5 -> HELICOPTER_ENGAGE_AND_FIRE: 002c5d48..002c5d5c writes 5 to moby+0x20 and clears fire_timer at pvars+0x168 after entry-path arrival with goal status other than 2. Existing HELICOPTER_ENGAGE_AND_FIRE case steers and spawns shots at 002c5fdc..002c60b8. domain_18_value_4 -> HELICOPTER_HOLD_POSITION_WAIT_FOR_TARGET: 002c5d48..002c5d64 writes 4 to moby+0x20 after entry-path arrival with goal status 2. Existing HELICOPTER_HOLD_POSITION_WAIT_FOR_TARGET case uses current position as destination and waits on the same status at 002c5f68..002c5fa8. domain_1_value_64 -> HELICOPTER_DEAD_WAIT_FOR_RESET: 002c569c..002c56a0 excludes 0x40 from the guard on moby+0x20, the switch selector. Existing case HELICOPTER_DEAD_WAIT_FOR_RESET handles that same state at 002c6404..002c650c. domain_20_value_5 -> HELICOPTER_ENGAGE_AND_FIRE: 002c5f54..002c5fc8 chooses moby+0x20 state 5 and clears fire_timer after area approach with goal status other than 2. This is the same selector and member as existing HELICOPTER_ENGAGE_AND_FIRE. domain_21_value_4 -> HELICOPTER_HOLD_POSITION_WAIT_FOR_TARGET: 002c5f54..002c5f64 routes area approach arrival with goal status 2 to the state-4 store at 002c60e4. Existing HELICOPTER_HOLD_POSITION_WAIT_FOR_TARGET handles the same moby+0x20 selector. domain_23_value_5 -> HELICOPTER_ENGAGE_AND_FIRE: 002c5fb0..002c5fcc writes 5 to moby+0x20 and clears fire_timer when the holding moby is inside area_path and status permits engagement. Existing HELICOPTER_ENGAGE_AND_FIRE then runs the shot logic. domain_24_value_3 -> HELICOPTER_APPROACH_AREA_PATH: 002c5fb0..002c5fd8 writes 3 into moby+0x20 when the holding moby is outside area_path. Same state selector's existing HELICOPTER_APPROACH_AREA_PATH scans and approaches those path points. domain_26_value_4 -> HELICOPTER_HOLD_POSITION_WAIT_FOR_TARGET: 002c60bc..002c60e4 steers toward current position and stores 4 at moby+0x20 when engagement receives goal status 2. Existing HELICOPTER_HOLD_POSITION_WAIT_FOR_TARGET performs that holding behavior on the next update. domain_27_value_64 -> HELICOPTER_DEAD_WAIT_FOR_RESET: 002c63e0..002c6400 detaches both turret manipulators then stores 0x40 at moby+0x20. Existing HELICOPTER_DEAD_WAIT_FOR_RESET case begins at 002c6404 and restores initial height and scale when vehicle mode changes. domain_28_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: 002c6480..002c6488 loads byte 0x001413f4 and 002c64e0 compares it to 2 before reset. Authoritative C binds it to hero.vehicle_mode, whose supplied HeroVehicleMode canonical member is HERO_VEHICLE_MODE_GIANT_CLANK=2. domain_29_value_0 -> HELICOPTER_INITIALIZE: 002c64e8..002c650c restores saved height minus 7.5 and doubles scale, storing zero at moby+0x20 at 002c64fc. Same byte drives existing HELICOPTER_INITIALIZE, which applies the matching initialization height/scale changes. domain_2_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: 002c56b4..002c56bc compares byte 0x001413f4 to 2; authoritative C binds this load to hero.vehicle_mode. Supplied HeroVehicleMode domain defines its canonical member HERO_VEHICLE_MODE_GIANT_CLANK=2; this is separate from moby state. domain_30_value_1 -> HELICOPTER_WAIT_FOR_ACTIVATION: 002c654c..002c6554 compares the moby+0x20 switch selector with 1 to skip the common height clamp while waiting. It reuses existing HELICOPTER_WAIT_FOR_ACTIVATION=1 from this exact function's state enum. domain_3_value_1 -> HELICOPTER_WAIT_FOR_ACTIVATION: 002c56f4..002c56fc writes 1 to moby+0x20 after hiding collision and pilot. The same byte drives the switch whose existing HELICOPTER_WAIT_FOR_ACTIVATION case gates activation at 002c59f0. domain_5_value_1 -> HELICOPTER_WAIT_FOR_ACTIVATION: 002c5708..002c571c compares moby+0x20 to 1 and selects wake_range at pvars+0x198. This is the state selector with existing HELICOPTER_WAIT_FOR_ACTIVATION=1, rather than a goal-status selector. domain_7_value_0 -> HELICOPTER_INITIALIZE: 002c57cc..002c57e0 tests moby+0x20 for zero before checking pvars+0x2e and removing mobys. Same selector drives existing HELICOPTER_INITIALIZE case, which sets pvars+0x2e to 1 at 002c58b4. domain_8_value_1 -> HELICOPTER_WAIT_FOR_ACTIVATION: 002c5930..002c593c stores 1 into the moby+0x20 switch selector after entry-path initialization. Existing HELICOPTER_WAIT_FOR_ACTIVATION case then handles the collision-hidden activation wait. domain_9_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: 002c59fc..002c5a04 loads byte 0x001413f4 and compares it with 2 in the activation case. Authoritative C identifies hero.vehicle_mode; supplied HeroVehicleMode names 2 HERO_VEHICLE_MODE_GIANT_CLANK. --- src/overlays/l15/mobys/helicopter.c | 44 ++++++++++++++--------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/overlays/l15/mobys/helicopter.c b/src/overlays/l15/mobys/helicopter.c index 890c8f9ad3..bf9a8c26a2 100644 --- a/src/overlays/l15/mobys/helicopter.c +++ b/src/overlays/l15/mobys/helicopter.c @@ -422,19 +422,19 @@ void helicopter_update(struct Moby *moby) { if (helicopter_instance_vars->pilot == 0) { helicopter_instance_vars->pilot = create_class_55b_moby_from_source(moby); } - if (moby->state != 0 && moby->state != 0x40 && helicopter_instance_vars->unk1A4 != 0 && - hero.vehicle_mode != 2) { + if (moby->state != HELICOPTER_INITIALIZE && moby->state != HELICOPTER_DEAD_WAIT_FOR_RESET && helicopter_instance_vars->unk1A4 != 0 && + hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK) { moby->collision = 0; moby->flags = (moby->flags | 0x41) & 0xEFFF; helicopter_instance_vars->unk58 = 0; if (helicopter_instance_vars->pilot != 0) helicopter_instance_vars->pilot->flags |= 0x41; - moby->state = 1; + moby->state = HELICOPTER_WAIT_FOR_ACTIVATION; return; } process_helicopter_hits(moby); goal.status = 0; - if (moby->state == 1) { + if (moby->state == HELICOPTER_WAIT_FOR_ACTIVATION) { helicopter_instance_vars->range = helicopter_instance_vars->wake_range; goto near; } @@ -454,7 +454,7 @@ void helicopter_update(struct Moby *moby) { if (goal.target == 0) goal.target = hero.moby; target = goal.target; - if (moby->state != 0 && helicopter_instance_vars->unk2E != 1) { + if (moby->state != HELICOPTER_INITIALIZE && helicopter_instance_vars->unk2E != 1) { if (helicopter_instance_vars->pilot != 0) mark_moby_for_removal(helicopter_instance_vars->pilot); mark_moby_for_removal(moby); @@ -484,7 +484,7 @@ void helicopter_update(struct Moby *moby) { } *(u128 *)&moby->pos = path->points[0].q; } - moby->state = 1; + moby->state = HELICOPTER_WAIT_FOR_ACTIVATION; helicopter_instance_vars->speed = 0.0f; helicopter_instance_vars->pitch_velocity = 0.0f; helicopter_instance_vars->yaw_velocity = 0.0f; @@ -505,7 +505,7 @@ void helicopter_update(struct Moby *moby) { helicopter_instance_vars->pilot->flags |= 0x41; break; case HELICOPTER_WAIT_FOR_ACTIVATION: - if (helicopter_instance_vars->unk1A4 != 0 && hero.vehicle_mode != 2) { + if (helicopter_instance_vars->unk1A4 != 0 && hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK) { moby->collision = 0; moby->flags = (moby->flags | 0x41) & 0xEFFF; helicopter_instance_vars->unk58 = 0; @@ -524,9 +524,9 @@ void helicopter_update(struct Moby *moby) { moby->flags = (moby->flags & 0xFFBE) | 0x1000; helicopter_instance_vars->unk58 = 0x19; if (helicopter_instance_vars->entry_path != -1) - moby->state = 2; + moby->state = HELICOPTER_FOLLOW_ENTRY_PATH; else - moby->state = 3; + moby->state = HELICOPTER_APPROACH_AREA_PATH; } else { if (helicopter_instance_vars->trigger_volume != -1) break; @@ -536,9 +536,9 @@ void helicopter_update(struct Moby *moby) { moby->flags = (moby->flags & 0xFFBE) | 0x1000; helicopter_instance_vars->unk58 = 0x19; if (helicopter_instance_vars->entry_path != -1) - moby->state = 2; + moby->state = HELICOPTER_FOLLOW_ENTRY_PATH; else - moby->state = 3; + moby->state = HELICOPTER_APPROACH_AREA_PATH; } if (helicopter_instance_vars->pilot != 0) helicopter_instance_vars->pilot->flags &= 0xFFBE; @@ -574,10 +574,10 @@ void helicopter_update(struct Moby *moby) { D_L15_001B0AB0[helicopter_instance_vars->area_path]->points, D_L15_001B0AB0[helicopter_instance_vars->area_path]->count)) { if (goal.status != 2) { - moby->state = 5; + moby->state = HELICOPTER_ENGAGE_AND_FIRE; helicopter_instance_vars->fire_timer = 0; } else { - moby->state = 4; + moby->state = HELICOPTER_HOLD_POSITION_WAIT_FOR_TARGET; } } if (segment + 1 < path->count - 8) { @@ -644,10 +644,10 @@ void helicopter_update(struct Moby *moby) { if (vector_distance_xy(&move, &moby->pos) < 1.0f || point_in_path_xy(&moby->pos, path->points, path->count)) { if (goal.status != 2) { - moby->state = 5; + moby->state = HELICOPTER_ENGAGE_AND_FIRE; helicopter_instance_vars->fire_timer = 0; } else { - moby->state = 4; + moby->state = HELICOPTER_HOLD_POSITION_WAIT_FOR_TARGET; } } break; @@ -661,10 +661,10 @@ void helicopter_update(struct Moby *moby) { if (goal.status == 2) break; if (point_in_path_xy(&moby->pos, path->points, path->count)) { - moby->state = 5; + moby->state = HELICOPTER_ENGAGE_AND_FIRE; helicopter_instance_vars->fire_timer = 0; } else { - moby->state = 3; + moby->state = HELICOPTER_APPROACH_AREA_PATH; } break; } @@ -688,7 +688,7 @@ void helicopter_update(struct Moby *moby) { aim.q = *(u128 *)&moby->pos; target_pos.q = *(u128 *)&target->pos; steer_helicopter(moby, (SteeringVec_4f88 *)&aim, (SteeringVec_4f88 *)&target_pos); - moby->state = 4; + moby->state = HELICOPTER_HOLD_POSITION_WAIT_FOR_TARGET; } break; case HELICOPTER_RECOIL: @@ -764,7 +764,7 @@ void helicopter_update(struct Moby *moby) { FUN_L00_00257470(moby, 0x200, -1); detach_manipulator(moby, helicopter_instance_vars->turret_yaw_joint); detach_manipulator(moby, helicopter_instance_vars->turret_pitch_joint); - moby->state = 0x40; + moby->state = HELICOPTER_DEAD_WAIT_FOR_RESET; return; } case HELICOPTER_DEAD_WAIT_FOR_RESET: @@ -778,17 +778,17 @@ void helicopter_update(struct Moby *moby) { *(int *)(D_0014C190 + (((short)moby->save_id >> 5) * 4 + (current_level_index << 8))) &= ~(1 << (moby->save_id & 0x1F)); D_L15_001BAAD0[(short)moby->save_id >> 5] &= ~(1 << (moby->save_id & 0x1F)); - if (hero.vehicle_mode != 2) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK) { moby->pos.z = helicopter_instance_vars->height - 7.5f; moby->scale *= 2.0f; - moby->state = 0; + moby->state = HELICOPTER_INITIALIZE; } return; } if (moby->visible != 0 && fast_vec_dist(&moby->pos, D_L15_001673C0) < 40.0f) { FUN_L00_0025a120(moby); } - if (moby->state != 1) { + if (moby->state != HELICOPTER_WAIT_FOR_ACTIVATION) { float climb = absolute_float(moby->pos.z - previous_pos.f[2]); float limit = frame_time * 10.0f; if (limit < climb) { From a478feaa4d820cc9a92f030b0f004a45296c580f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:27:18 +0000 Subject: [PATCH 1116/1502] decomp: clarify names in update_debug_menu domain_0_value_110 -> DEBUG_CAPTURE_STATUS_NO: Retail 001f460c loads 0x6e and 001f4630 stores it to menu+0xf8 (start_capture_status) when leaving the menu. Exact draw_debug_menu copies this byte into a NUL-terminated one-character string: ASCII 'n', the reset capture indicator. domain_11_value_3 -> DEBUG_OCCLUSION_MODE_COUNT: Retail 001f4a7c..001f4a90 increments menu+0x1c, tests against 3 and wraps to zero; 001f4aa8..001f4ac0 wraps negative values to 2. Exact C identifies occlusion_mode, proving a three-value selector and its exclusive count. domain_15_value_3 -> DEBUG_COLLISION_MODE_COUNT: Retail 001f4bb4..001f4bc8 increments menu+0x2c, tests against 3 and wraps to zero; 001f4be0..001f4bf8 wraps negative values to 2. Exact C identifies collision_mode, proving its three-value selector count independently of occlusion modes. domain_19_value_121 -> DEBUG_CAPTURE_STATUS_YES: Retail 001f5670..001f56ac opens the sample text file, seeks, writes the formatted sample line and closes it; 001f56b4..001f56b8 then stores 0x79 to sample_capture_status. Exact draw_debug_menu renders that byte as ASCII 'y'. domain_1_value_110 -> DEBUG_CAPTURE_STATUS_NO: Retail 001f460c loads 0x6e and 001f4614 stores it to menu+0xf9 (sample_capture_status) on menu exit. Exact draw_debug_menu renders this byte as a one-character NUL-terminated string; ASCII 'n' is the reset capture indicator. domain_20_value_121 -> DEBUG_CAPTURE_STATUS_YES: Retail 001f5860..001f589c opens the start-point text file, seeks, writes its formatted line and closes it; 001f58a0..001f58a4 stores 0x79 to start_capture_status. Exact draw_debug_menu renders that byte as ASCII 'y'. domain_2_value_4 -> DEBUG_CONTROL_MODE_COUNT: Retail 001f48d0..001f48e4 increments menu+0x14, tests slti against 4, and wraps to zero. The exact C identifies control_mode and enumerates its four cases 0..3, proving 4 is the exclusive mode count. domain_3_value_0 -> DEBUG_CONTROL_MODE_ENABLE_LOW_FOUR_UPDATE_FLAGS: Retail 001f48e4 wraps menu+0x14 control_mode to zero; the same selector at 001f491c/001f4930 dispatches zero to 001f4958..001f4960, storing 15 in update_flags. Reuse the exact C's existing member for that same selector. domain_4_value_0 -> DEBUG_CONTROL_MODE_ENABLE_LOW_FOUR_UPDATE_FLAGS: Retail 001f4900..001f4910 tests decremented control_mode against zero and wraps negative values to 3. Zero is the existing control_mode member whose dispatch at 001f4930 reaches the update_flags=15 store at 001f4960. domain_5_value_3 -> DEBUG_CONTROL_MODE_ENABLE_SECOND_AND_THIRD_UPDATE_FLAGS: Retail 001f490c..001f4910 wraps control_mode to 3; 001f4944/001f4948 dispatches this same value to 001f49e8..001f49f0, storing mask 6 to update_flags. Reuse the established exact-C member for this selector. domain_6_value_8 -> DEBUG_PROFILER_MODE_COUNT: Retail 001f4a08..001f4a1c increments menu+0x18, tests against 8 and wraps to zero; 001f4a34..001f4a4c wraps negative values to 7. Exact C identifies profiler_mode, proving eight selectable values and the exclusive count. --- .../rendering/debug/update_debug_menu.c | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/overlays/shared/rendering/debug/update_debug_menu.c b/src/overlays/shared/rendering/debug/update_debug_menu.c index 7ab450ce45..139a5b385e 100644 --- a/src/overlays/shared/rendering/debug/update_debug_menu.c +++ b/src/overlays/shared/rendering/debug/update_debug_menu.c @@ -510,6 +510,14 @@ void update_debug_menu(void) { DEBUG_CONTROL_MODE_CAPTURE_HERO_CAMERA_OFFSET = 2, DEBUG_CONTROL_MODE_ENABLE_SECOND_AND_THIRD_UPDATE_FLAGS = 3 }; + enum { + DEBUG_OCCLUSION_MODE_COUNT = 3, + DEBUG_COLLISION_MODE_COUNT = 3, + DEBUG_CONTROL_MODE_COUNT = 4, + DEBUG_PROFILER_MODE_COUNT = 8, + DEBUG_CAPTURE_STATUS_NO = 110, + DEBUG_CAPTURE_STATUS_YES = 121 + }; DebugRowCounts row_counts; union { struct { @@ -528,8 +536,8 @@ void update_debug_menu(void) { set_background_color(level_view_context.background_color[0], level_view_context.background_color[1], level_view_context.background_color[2]); - g_debug_menu.start_capture_status = 110; - g_debug_menu.sample_capture_status = 110; + g_debug_menu.start_capture_status = DEBUG_CAPTURE_STATUS_NO; + g_debug_menu.sample_capture_status = DEBUG_CAPTURE_STATUS_NO; g_debug_menu.unknown_94 = (s32)l00_camera.pos.f[0] >> 2; g_debug_menu.unknown_98 = (s32)l00_camera.pos.f[1] >> 2; g_debug_menu.unknown_9c = (s32)l00_camera.pos.f[2] >> 2; @@ -578,12 +586,12 @@ void update_debug_menu(void) { case DEBUG_OPTION_ROW_CONTROL_MODE: if (controller_words.buttons.w.pressed & 0x50) { if (controller_words.buttons.w.pressed & 0x40) { - if (++g_debug_menu.control_mode >= 4) - g_debug_menu.control_mode = 0; + if (++g_debug_menu.control_mode >= DEBUG_CONTROL_MODE_COUNT) + g_debug_menu.control_mode = DEBUG_CONTROL_MODE_ENABLE_LOW_FOUR_UPDATE_FLAGS; } if (controller_words.buttons.w.pressed & 0x10) { - if (--g_debug_menu.control_mode < 0) - g_debug_menu.control_mode = 3; + if (--g_debug_menu.control_mode < DEBUG_CONTROL_MODE_ENABLE_LOW_FOUR_UPDATE_FLAGS) + g_debug_menu.control_mode = DEBUG_CONTROL_MODE_ENABLE_SECOND_AND_THIRD_UPDATE_FLAGS; } switch (g_debug_menu.control_mode) { case DEBUG_CONTROL_MODE_ENABLE_LOW_FOUR_UPDATE_FLAGS: @@ -611,7 +619,7 @@ void update_debug_menu(void) { break; case DEBUG_OPTION_ROW_PROFILER_MODE: if (controller_words.buttons.w.pressed & 0x40) { - if (++g_debug_menu.profiler_mode >= 8) + if (++g_debug_menu.profiler_mode >= DEBUG_PROFILER_MODE_COUNT) g_debug_menu.profiler_mode = 0; } if (controller_words.buttons.w.pressed & 0x10) { @@ -625,7 +633,7 @@ void update_debug_menu(void) { break; } if (controller_words.buttons.w.pressed & 0x40) { - if (++g_debug_menu.occlusion_mode >= 3) + if (++g_debug_menu.occlusion_mode >= DEBUG_OCCLUSION_MODE_COUNT) g_debug_menu.occlusion_mode = 0; } if (controller_words.buttons.w.pressed & 0x10) { @@ -661,7 +669,7 @@ void update_debug_menu(void) { break; case DEBUG_OPTION_ROW_COLLISION_MODE: if (controller_words.buttons.w.pressed & 0x40) { - if (++g_debug_menu.collision_mode >= 3) + if (++g_debug_menu.collision_mode >= DEBUG_COLLISION_MODE_COUNT) g_debug_menu.collision_mode = 0; } if (controller_words.buttons.w.pressed & 0x10) { @@ -901,7 +909,7 @@ void update_debug_menu(void) { sceLseek(fd, 0, 2); sceWrite(fd, scratch.sample.line, strlen(scratch.sample.line)); sceClose(fd); - g_debug_menu.sample_capture_status = 121; + g_debug_menu.sample_capture_status = DEBUG_CAPTURE_STATUS_YES; } { f32 *samples = occlusion_samples; @@ -948,7 +956,7 @@ void update_debug_menu(void) { sceLseek(fd, 0, 2); sceWrite(fd, scratch.start_point.line, strlen(scratch.start_point.line)); sceClose(fd); - g_debug_menu.start_capture_status = 121; + g_debug_menu.start_capture_status = DEBUG_CAPTURE_STATUS_YES; } } break; From c91738421ec747e720d9479c235688ad1e997ccc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:27:18 +0000 Subject: [PATCH 1117/1502] decomp: clarify names in update_vendor_menu domain_0_value_0 -> VENDOR_MENU_MODE_EXISTING_VENDOR: Authoritative C open_vendor_menu clears vendor_menu, sets mode to VENDOR_MENU_MODE_SPAWNED_VENDOR only when its vendor argument is null and create_moby runs, and otherwise uses VENDOR_MENU_MODE_EXISTING_VENDOR (0). Original retail Ghidra DAT_001ca500 is vendor_menu+0x40, the same selector in this update; no hero state equivalence is claimed. Retail 0029c6d0-0029c6e0 tests +0x40 for zero to enable world updates during opening, also enabled when menu state is closing. domain_11_value_1 -> VENDOR_PURCHASE_INITIALIZE: Retail 0029d4a8-0029d4b0 stores 1 to vendor_menu+0x5c upon fresh confirm input, then 0029d504 calls update_vendor_purchase. Authoritative update_vendor_purchase tests the same field against VENDOR_PURCHASE_INITIALIZE (1) and initializes the purchase dialog moby before entering AWAIT_INPUT. domain_12_value_0 -> VENDOR_MENU_MODE_EXISTING_VENDOR: Authoritative C open_vendor_menu clears vendor_menu, sets mode to VENDOR_MENU_MODE_SPAWNED_VENDOR only when its vendor argument is null and create_moby runs, and otherwise uses VENDOR_MENU_MODE_EXISTING_VENDOR (0). Original retail Ghidra DAT_001ca500 is vendor_menu+0x40, the same selector in this update; no hero state equivalence is claimed. Retail 0029d5b0-0029d5c8 tests +0x40 for nonzero before copying stored look angles back to the camera during closing. domain_13_value_2 -> VENDOR_MENU_CLOSING: Retail 0029d5f0 loads 2 and 0029d5fc stores it to D_001CA4C0 after the close countdown, reverse animation and camera restoration. The same field dispatches to existing VENDOR_MENU_CLOSING; subsequent closing cleanup occurs at 0029c908-0029c9bc. domain_1_value_2 -> VENDOR_MENU_CLOSING: Retail 0029c6d8-0029c6e0 compares the state at D_001CA4C0 to 2, the same field dispatched by the existing local VENDOR_MENU_CLOSING label. Closing runs detach cleanup at 0029c968-0029c9bc. domain_2_value_0 -> VENDOR_MENU_OPENING: vendor_menu_state is copied directly from vendor_menu.state in authoritative C. Retail 0029c7f8-0029c7fc tests this field for zero before fading and waiting for the opening transition at 0029c838-0029c890; reuse the local VENDOR_MENU_OPENING member. domain_3_value_0 -> VENDOR_MENU_MODE_EXISTING_VENDOR: Authoritative C open_vendor_menu clears vendor_menu, sets mode to VENDOR_MENU_MODE_SPAWNED_VENDOR only when its vendor argument is null and create_moby runs, and otherwise uses VENDOR_MENU_MODE_EXISTING_VENDOR (0). Original retail Ghidra DAT_001ca500 is vendor_menu+0x40, the same selector in this update; no hero state equivalence is claimed. Retail 0029c85c-0029c860 tests +0x40 for nonzero to bypass the existing-vendor opening wait. domain_4_value_1 -> VENDOR_MENU_OPEN: Retail 0029c86c loads 1 and 0029c884 stores it to D_001CA4C0 after the opening wait, resetting frames and starting vendor animation. That same field dispatches to the existing VENDOR_MENU_OPEN label and interactive selection handling. domain_5_value_2 -> VENDOR_MENU_CLOSING: Authoritative vendor_menu_state is a direct copy of vendor_menu.state; retail 0029c8cc-0029c8d0 compares it to 2 before the closing wait and manipulator cleanup. This is the exact domain already named VENDOR_MENU_CLOSING in the local dispatch enum. domain_6_value_0 -> VENDOR_MENU_MODE_EXISTING_VENDOR: Authoritative C open_vendor_menu clears vendor_menu, sets mode to VENDOR_MENU_MODE_SPAWNED_VENDOR only when its vendor argument is null and create_moby runs, and otherwise uses VENDOR_MENU_MODE_EXISTING_VENDOR (0). Original retail Ghidra DAT_001ca500 is vendor_menu+0x40, the same selector in this update; no hero state equivalence is claimed. Retail 0029c8d8-0029c8fc permits a purchased-item exit cutscene only when +0x40 is zero and the selected cutscene id is nonnegative. domain_7_value_0 -> VENDOR_MENU_MODE_EXISTING_VENDOR: Authoritative C open_vendor_menu clears vendor_menu, sets mode to VENDOR_MENU_MODE_SPAWNED_VENDOR only when its vendor argument is null and create_moby runs, and otherwise uses VENDOR_MENU_MODE_EXISTING_VENDOR (0). Original retail Ghidra DAT_001ca500 is vendor_menu+0x40, the same selector in this update; no hero state equivalence is claimed. Retail 0029c930-0029c934 tests +0x40 for nonzero to bypass the existing-vendor closing wait. domain_8_value_0 -> VENDOR_MENU_MODE_EXISTING_VENDOR: Authoritative C open_vendor_menu clears vendor_menu, sets mode to VENDOR_MENU_MODE_SPAWNED_VENDOR only when its vendor argument is null and create_moby runs, and otherwise uses VENDOR_MENU_MODE_EXISTING_VENDOR (0). Original retail Ghidra DAT_001ca500 is vendor_menu+0x40, the same selector in this update; no hero state equivalence is claimed. Retail 0029c9f4-0029ca0c tests +0x40 for zero before applying the stored vendor-menu eye and look camera vectors. domain_9_value_0 -> VENDOR_PURCHASE_INACTIVE: Retail 0029cfc8-0029cfd0 loads vendor_menu+0x5c (Ghidra DAT_001ca51c) and skips selection/input if nonzero. The authoritative update_vendor_purchase reads this exact purchase_state field and returns for its VENDOR_PURCHASE_INACTIVE member (0), also restoring it after finalization. --- src/overlays/shared/vendor/vendor_menu.c | 29 ++++++++++++++---------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/overlays/shared/vendor/vendor_menu.c b/src/overlays/shared/vendor/vendor_menu.c index 05af3aaf8d..3bbb0e4aa3 100644 --- a/src/overlays/shared/vendor/vendor_menu.c +++ b/src/overlays/shared/vendor/vendor_menu.c @@ -1144,6 +1144,11 @@ void update_vendor_menu(void) { VENDOR_MENU_CLOSING = 2, VENDOR_MENU_EXIT_CUTSCENE = 3 }; + enum { + VENDOR_MENU_MODE_EXISTING_VENDOR = 0, + VENDOR_PURCHASE_INACTIVE = 0, + VENDOR_PURCHASE_INITIALIZE = 1 + }; Vec4 position_scratch; Vec4 position_contribution_scratch; f32 camera_rotation_matrix[4][4]; @@ -1171,7 +1176,7 @@ void update_vendor_menu(void) { switch (vendor_menu.state) { case VENDOR_MENU_OPENING: case VENDOR_MENU_CLOSING: - if (vendor_menu.mode == 0 || vendor_menu.state == 2) { + if (vendor_menu.mode == VENDOR_MENU_MODE_EXISTING_VENDOR || vendor_menu.state == VENDOR_MENU_CLOSING) { if ((g_debug_menu.update_flags & 2) || ((g_debug_menu.update_flags & 0x10) && (((u32)pad_pressed_lui) & 0x200))) { reset_frame_counters(); @@ -1194,16 +1199,16 @@ void update_vendor_menu(void) { noop_main_callback(vendor_part_update_label, 5); } vendor_menu_state = vendor_menu.state; - if (vendor_menu_state == 0) { + if (vendor_menu_state == VENDOR_MENU_OPENING) { fade_level -= 0.34f; if (fade_level < 0.0f) { fade_level = 0.0f; } vendor_menu.frames++; - if (vendor_menu.frames >= scale_game_frames(40) || vendor_menu.mode != 0) { + if (vendor_menu.frames >= scale_game_frames(40) || vendor_menu.mode != VENDOR_MENU_MODE_EXISTING_VENDOR) { fade_level = 0.0f; vendor_menu.unk0C = 1; - vendor_menu.state = 1; + vendor_menu.state = VENDOR_MENU_OPEN; vendor_menu.frames = 0; FUN_00212f90(vendor_menu.vendor_moby, 3, 0, 8); vendor_menu.vendor_moby->f58 = 1.0f; @@ -1211,15 +1216,15 @@ void update_vendor_menu(void) { vendor_opening_countdown_frames = 8; allocate_voice_for_target_entry(4, 0, vendor_menu.vendor_moby); } - } else if (vendor_menu_state == 2) { + } else if (vendor_menu_state == VENDOR_MENU_CLOSING) { ok = 0; - if (vendor_menu.mode == 0 && vendor_menu.purchased_item >= 0) { + if (vendor_menu.mode == VENDOR_MENU_MODE_EXISTING_VENDOR && vendor_menu.purchased_item >= 0) { if (vendor_exit_cutscene_ids_by_item[vendor_menu.purchased_item] >= 0) { ok = 1; } } vendor_menu.frames++; - if (vendor_menu.frames >= scale_game_frames(40) || vendor_menu.mode != 0) { + if (vendor_menu.frames >= scale_game_frames(40) || vendor_menu.mode != VENDOR_MENU_MODE_EXISTING_VENDOR) { FUN_00212f90(vendor_menu.vendor_moby, 1, 0, 8); row = vendor_slots; for (k = 0; k < 4; k++) { @@ -1240,7 +1245,7 @@ void update_vendor_menu(void) { if (vendor_menu.frames <= scale_game_frames(36)) { add_draw_callback(draw_vendor_inset_quads, vendor_menu.vendor_moby); } - if (vendor_menu.mode == 0) { + if (vendor_menu.mode == VENDOR_MENU_MODE_EXISTING_VENDOR) { set_camera_position(&vendor_menu.eye); set_camera_rotation(&vendor_menu.look); } @@ -1360,7 +1365,7 @@ void update_vendor_menu(void) { &vendor_menu.menu_mobys[3].pos, &position_contribution_scratch); vendor_menu.frames++; - if (vendor_menu.purchase_state == 0 && l00_vendor_close_pending == 0) { + if (vendor_menu.purchase_state == VENDOR_PURCHASE_INACTIVE && l00_vendor_close_pending == 0) { if (vendor_menu.row_count < 8) { if ((controller_state.pressed_unmasked & 0x2000) && !(l00_vendor_previous_pressed_buttons & 0x2000)) { if (vendor_menu.cursor < vendor_menu.row_count - 1) { @@ -1468,7 +1473,7 @@ void update_vendor_menu(void) { } if ((controller_state.pressed_unmasked & 0x40) && !(l00_vendor_previous_pressed_buttons & 0x40) && CUR_ITEM.state == 0) { - vendor_menu.purchase_state = 1; + vendor_menu.purchase_state = VENDOR_PURCHASE_INITIALIZE; allocate_voice_for_target_entry(0, 0, vendor_menu.vendor_moby); } if ((controller_state.pressed_unmasked & 0x10) && D_L00_0016118C == 0) { @@ -1492,13 +1497,13 @@ void update_vendor_menu(void) { select_level_vu_chain(); FUN_00212f90(vendor_menu.vendor_moby, 4, 9, 8); vendor_menu.vendor_moby->f58 = frame_scale * -0.5f; - if (vendor_menu.mode != 0) { + if (vendor_menu.mode != VENDOR_MENU_MODE_EXISTING_VENDOR) { qcopy(g_debug_camera.angles, &vendor_menu.look); } ((Vec4 *)g_debug_camera.basis)[0].q = D_L00_00165F80[0].q; ((Vec4 *)g_debug_camera.basis)[1].q = D_L00_00165F80[1].q; ((Vec4 *)g_debug_camera.basis)[2].q = D_L00_00165F80[2].q; - vendor_menu.state = 2; + vendor_menu.state = VENDOR_MENU_CLOSING; vendor_menu.unk08 = 0; vendor_menu.frames = 0; if (hero.items[0].moby != 0) { From 1a99d901b95a589bb232c0ecc317b8d330b2b005 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:27:19 +0000 Subject: [PATCH 1118/1502] decomp: clarify names in update_morphoray_chicken domain_0_value_0 -> CHICKEN_STATE_INITIALIZE: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. 002c9848..002c9894 tests state zero, advances to idle, clears flee_timer, initializes expiry/sound timers and health; this is the existing INITIALIZE arm's pre-dispatch setup. domain_10_value_4 -> CHICKEN_STATE_CLOSE_RANGE_FLEE_FROM_HERO: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. 002ca4a8..002ca4cc selects hero distance below size*3; successful forward movement stores 4 at 002ca624. Existing arm 4 at 002ca6c0 uses doubled forward steps and returns to ordinary flee beyond size*4, proving CLOSE_RANGE_FLEE_FROM_HERO. domain_11_value_1 -> CHICKEN_STATE_IDLE: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. The ordinary-distance FLEE_FROM_HERO forward probe at 002ca638..002ca9a8 resets failed/backward movement via 002ca9b4 to state 1 with randomized flee_timer and animation 0/1, matching existing IDLE. domain_12_value_1 -> CHICKEN_STATE_IDLE: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. CLOSE_RANGE_FLEE_FROM_HERO timer/distance branch 002ca6c0..002ca83c reaches 002ca9b4 when the forward probe fails/backtracks, restoring state 1 and idle timer/animation, the existing IDLE arm. domain_13_value_3 -> CHICKEN_STATE_FLEE_FROM_HERO: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. 002ca6c0..002ca6f4 requires expired flee_timer and hero distance beyond size*4; valid ordinary forward movement then stores 3 at 002ca84c and blends animation 3, returning from close-range fleeing to existing FLEE_FROM_HERO. domain_14_value_1 -> CHICKEN_STATE_IDLE: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. The doubled-step close-range flee path 002ca860..002ca9a8 reaches store 1 at 002ca9b4 on failed/backward movement, restoring flee_timer and animation 0/1 for the existing IDLE arm. domain_15_value_0 -> CHICKEN_STATE_INITIALIZE: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. Within existing EMIT_FEATHERS arm, helper success at 002caa04..002caa20 stores zero to the same state byte and clears callback record+0x68. Next update's 002c9848..002c9894 performs the existing INITIALIZE setup. domain_16_value_5 -> CHICKEN_STATE_EMIT_FEATHERS: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. 002cac40..002cac48 compares the same state byte to 5 to skip ground-normal alignment. Existing arm 5 at 002caa04..002cab14 emits feathers through 002cbf68 and returns before normal movement; reuse EMIT_FEATHERS. domain_1_value_1 -> CHICKEN_STATE_IDLE: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. 002c9854..002c985c stores 1 during initialization; dispatch arm 1 at 002c9fa4 blends animations 0/1 and waits for nearby-hero flee triggers, matching existing IDLE. domain_2_value_6 -> CHICKEN_STATE_DEAD: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. 002c9898..002c98a0 returns immediately for state 6. Its writer at 002c9ed8..002c9f04 follows health below 1 and death particle/feather emission, clears collision and command and disables normal updates; this is the retained dead chicken state. domain_3_value_6 -> CHICKEN_STATE_DEAD: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. After health below 1 at 002c9ae4..002c9af0 and death feather emission, 002c9ed8..002c9f04 retains non-expiring chickens with collision zero, flags changed, gold zero and command zero, storing 6 at 002c9efc. The entry guard then skips every update in this dead state. domain_4_value_3 -> CHICKEN_STATE_FLEE_FROM_HERO: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. 002ca0ac..002ca130 enters 3 from IDLE after a valid forward movement probe. Existing state-3 arm 002ca3dc..002ca6bc turns toward the hero-to-chicken angle and moves forward, proving FLEE_FROM_HERO. domain_5_value_2 -> CHICKEN_STATE_TURN_AWAY_FROM_HERO: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. 002ca194..002ca208 stores 2 when a nearby hero and heading mismatch require turning. Existing arm 2 at 002ca21c turns toward flee_angle with equal movement endpoints, proving TURN_AWAY_FROM_HERO. domain_6_value_3 -> CHICKEN_STATE_FLEE_FROM_HERO: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. 002ca2a0..002ca370 stores 3 from TURN_AWAY_FROM_HERO after timer, nearby-hero and forward ground-height checks. It enters the existing FLEE_FROM_HERO arm, using animation 3. domain_7_value_1 -> CHICKEN_STATE_IDLE: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. 002ca384..002ca3d4 reaches idle reset 002ca9ac..002ca9f8 when turning is aligned or hero distance exceeds size*6; state 1 restores the existing IDLE behavior and randomized flee timer. domain_8_value_1 -> CHICKEN_STATE_IDLE: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. 002ca3dc..002ca45c stores 1 at 002ca418 when fleeing exceeds size*6, randomizes flee_timer and resumes animation 0/1. The destination is the same byte's existing IDLE switch arm. domain_9_value_1 -> CHICKEN_STATE_IDLE: The SHA-bound morphoray_chicken.c and original retail decompilation agree that this token reads/writes chicken_moby->state, the same byte at s2+0x20 selected by the dispatch at 002c9f7c..002c9fa0; it therefore belongs to the existing local CHICKEN_STATE domain, not HeroStateId. In the close-distance branch of FLEE_FROM_HERO, failed/backward movement tests 002ca5a8..002ca614 reach 002ca9ac, whose 002ca9b4 store resets state 1, timer and animation to existing IDLE. --- .../shared/weapons/morphoray_chicken.c | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/overlays/shared/weapons/morphoray_chicken.c b/src/overlays/shared/weapons/morphoray_chicken.c index 11184db405..d20fd35e66 100644 --- a/src/overlays/shared/weapons/morphoray_chicken.c +++ b/src/overlays/shared/weapons/morphoray_chicken.c @@ -365,6 +365,9 @@ void morphoray_chicken_update(Moby *chicken_moby) { CHICKEN_STATE_CLOSE_RANGE_FLEE_FROM_HERO = 4, CHICKEN_STATE_EMIT_FEATHERS = 5 }; + enum { + CHICKEN_STATE_DEAD = 6 + }; Vec4A next_pos; Vec4A ahead; Vec4A motion_and_normal_scratch; @@ -389,15 +392,15 @@ void morphoray_chicken_update(Moby *chicken_moby) { anim_speed = chicken_moby->anim_speed; flee_angle = fast_arc_tan(chicken_moby->pos.x - player->motion.pos.f[0], chicken_moby->pos.y - player->motion.pos.f[1]); - if (chicken_moby->state == 0) { - chicken_moby->state = 1; + if (chicken_moby->state == CHICKEN_STATE_INITIALIZE) { + chicken_moby->state = CHICKEN_STATE_IDLE; chicken_vars->flee_timer = 0; chicken_vars->expire_timer = -1; chicken_vars->sound_timer = random_int_between(scale_game_frames(0x78), scale_game_frames(0x12C)); chicken_vars->health = 1.0f; } - if (chicken_moby->state == 6) { + if (chicken_moby->state == CHICKEN_STATE_DEAD) { return; } if (D_0013E520[0x15] != 0) { @@ -529,7 +532,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { chicken_moby->collision = 0; chicken_moby->flags = (chicken_moby->flags & 0xEFFF) | 0x41; chicken_vars->gold = 0; - chicken_moby->state = 6; + chicken_moby->state = CHICKEN_STATE_DEAD; chicken_moby->command = 0; return; } @@ -565,7 +568,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { next_pos.y - chicken_moby->pos.y)) < 1.5707964f && fast_vec_dist(&chicken_moby->pos, &next_pos) > size * 0.01f)) { - chicken_moby->state = 3; + chicken_moby->state = CHICKEN_STATE_FLEE_FROM_HERO; blend_moby_animation(chicken_moby, 3, 0, scale_game_frames(10)); } else { chicken_vars->flee_timer = @@ -576,7 +579,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { fast_difference_between_rotations(flee_angle, chicken_moby->rot.z)) { move_moby_xy_with_collision_constraints( chicken_moby, &next_pos, &next_pos, 0, size * 0.2f, size * 0.5f, speed, 0.2617994f); - chicken_moby->state = 2; + chicken_moby->state = CHICKEN_STATE_TURN_AWAY_FROM_HERO; blend_moby_animation(chicken_moby, 3, 0, scale_game_frames(10)); } else { move_moby_xy_with_collision_constraints( @@ -600,13 +603,13 @@ void morphoray_chicken_update(Moby *chicken_moby) { fast_vec_add(&ahead, &ahead, &next_pos); if (absolute_float(probe_ground_height(&ahead, 0, 0.5f) - ahead.z) <= (frame_time + frame_time) * size) { - chicken_moby->state = 3; + chicken_moby->state = CHICKEN_STATE_FLEE_FROM_HERO; blend_moby_animation(chicken_moby, 3, 0, scale_game_frames(10)); } } else if (fast_difference_between_rotations(flee_angle, chicken_moby->rot.z) < 0.08726646f || vector_distance_xy(&chicken_moby->pos, &hero.motion.pos) > size * 6.0f) { - chicken_moby->state = 1; + chicken_moby->state = CHICKEN_STATE_IDLE; chicken_vars->flee_timer = random_int_between(scale_game_frames(0x3C), scale_game_frames(0xB4)); blend_moby_animation( @@ -615,7 +618,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { break; case CHICKEN_STATE_FLEE_FROM_HERO: if (vector_distance_xy(&chicken_moby->pos, &hero.motion.pos) > size * 6.0f) { - chicken_moby->state = 1; + chicken_moby->state = CHICKEN_STATE_IDLE; chicken_vars->flee_timer = random_int_between(scale_game_frames(0x3C), scale_game_frames(0xB4)); blend_moby_animation( @@ -641,13 +644,13 @@ void morphoray_chicken_update(Moby *chicken_moby) { fast_arc_tan(next_pos.x - chicken_moby->pos.x, next_pos.y - chicken_moby->pos.y)) || fast_vec_dist(&chicken_moby->pos, &next_pos) < size * 0.01f)) { - chicken_moby->state = 1; + chicken_moby->state = CHICKEN_STATE_IDLE; chicken_vars->flee_timer = random_int_between(scale_game_frames(0x3C), scale_game_frames(0xB4)); blend_moby_animation( chicken_moby, random_integer_below(2) == 0, 0, scale_game_frames(5)); } else { - chicken_moby->state = 4; + chicken_moby->state = CHICKEN_STATE_CLOSE_RANGE_FLEE_FROM_HERO; blend_moby_animation(chicken_moby, 2, 0, scale_game_frames(10)); } } else { @@ -669,7 +672,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { fast_arc_tan(next_pos.x - chicken_moby->pos.x, next_pos.y - chicken_moby->pos.y)) || fast_vec_dist(&chicken_moby->pos, &next_pos) < size * 0.01f)) { - chicken_moby->state = 1; + chicken_moby->state = CHICKEN_STATE_IDLE; chicken_vars->flee_timer = random_int_between(scale_game_frames(0x3C), scale_game_frames(0xB4)); blend_moby_animation( @@ -698,13 +701,13 @@ void morphoray_chicken_update(Moby *chicken_moby) { fast_arc_tan(next_pos.x - chicken_moby->pos.x, next_pos.y - chicken_moby->pos.y)) || fast_vec_dist(&chicken_moby->pos, &next_pos) < size * 0.01f)) { - chicken_moby->state = 1; + chicken_moby->state = CHICKEN_STATE_IDLE; chicken_vars->flee_timer = random_int_between(scale_game_frames(0x3C), scale_game_frames(0xB4)); blend_moby_animation( chicken_moby, random_integer_below(2) == 0, 0, scale_game_frames(5)); } else { - chicken_moby->state = 3; + chicken_moby->state = CHICKEN_STATE_FLEE_FROM_HERO; blend_moby_animation(chicken_moby, 3, 0, scale_game_frames(10)); } } else { @@ -726,7 +729,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { fast_arc_tan(next_pos.x - chicken_moby->pos.x, next_pos.y - chicken_moby->pos.y)) || fast_vec_dist(&chicken_moby->pos, &next_pos) < size * 0.01f)) { - chicken_moby->state = 1; + chicken_moby->state = CHICKEN_STATE_IDLE; chicken_vars->flee_timer = random_int_between(scale_game_frames(0x3C), scale_game_frames(0xB4)); blend_moby_animation( @@ -736,7 +739,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { break; case CHICKEN_STATE_EMIT_FEATHERS: if (FUN_L00_002dc9f0(chicken_moby, chicken_vars->unk10) != 0) { - chicken_moby->state = 0; + chicken_moby->state = CHICKEN_STATE_INITIALIZE; *(short *)(chicken_vars->unk14 + 0x68) = 0; } if (random_integer_below(4) != 0) { @@ -790,7 +793,7 @@ void morphoray_chicken_update(Moby *chicken_moby) { if (collision_hit_material() == 0) { chicken_vars->health = 0.0f; } - if (chicken_moby->state != 5) { + if (chicken_moby->state != CHICKEN_STATE_EMIT_FEATHERS) { float pitch; float roll; chicken_moby->pos.z = coll_hit.point.f[2]; From e1e3fcbe129cab8b6bdf5dd7952f61ebf199c6c5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:27:19 +0000 Subject: [PATCH 1119/1502] decomp: clarify names in update_batalia_bolt_pickup domain_0_value_1 -> BOLT_PICKUP_WAIT_FOR_HERO: Retail 0x002e3aa8 loads 1 and 0x002e3ab0 stores it to moby+0x20 after surface pose initialization and attachment conversion. The dispatch at 0x002e38ac reads this exact field; source case BOLT_PICKUP_WAIT_FOR_HERO handles its surface idle and hero-proximity checks. domain_1_value_4 -> BOLT_PICKUP_FALL_AND_BOUNCE: Retail 0x002e3b10..0x002e3b60 detects negative attached-support state, clears pickup velocity, builds its fall spin matrix, and writes 4 to moby+0x20. That exact dispatch field selects existing BOLT_PICKUP_FALL_AND_BOUNCE, whose branch applies gravity, reflection and collision handling. domain_2_value_2 -> BOLT_PICKUP_TURN_TOWARD_HERO: Retail 0x002e3b68..0x002e3bc0 tests hero vertical and planar reach, initializes pvars+0x68 timer and stores 2 to moby+0x20. The existing switch on that field names state 2 BOLT_PICKUP_TURN_TOWARD_HERO and computes hero-facing yaw before collection launch. domain_3_value_3 -> BOLT_PICKUP_FLY_TO_HERO_AND_CREDIT_BOLTS: Retail 0x002e3e70..0x002e3f20 initializes launch velocity, target pointer and homing magnitudes, then stores 3 to moby+0x20. The existing case for this same state selector is BOLT_PICKUP_FLY_TO_HERO_AND_CREDIT_BOLTS, implementing target flight and source/total/level bolt credit. domain_4_value_2 -> BOLT_PICKUP_TURN_TOWARD_HERO: Retail 0x002e47f4..0x002e4844 detects the fallen pickup below both saved height and hero, copies the hero basis into pvars+0x10, sets its timer and branches to 0x002e4bd0..0x002e4bd8, storing 2 into moby+0x20. This is the exact selector of existing BOLT_PICKUP_TURN_TOWARD_HERO. domain_5_value_5 -> BOLT_PICKUP_RETURN_TO_SURFACE: Retail 0x002e4934..0x002e4aa8 saves collision anchor, computes surface target pose, velocity and angular increments over the return duration, then stores 5 to moby+0x20 and the duration to pvars+0x68. The same selector's existing BOLT_PICKUP_RETURN_TO_SURFACE case consumes those increments and timer. domain_6_value_2 -> BOLT_PICKUP_TURN_TOWARD_HERO: Retail 0x002e4aac..0x002e4afc checks hero reach immediately after preparing surface return, initializes pvars+0x68 and branches to 0x002e4bd0..0x002e4bd8 to store 2 into moby+0x20. This redirects the pickup into the existing BOLT_PICKUP_TURN_TOWARD_HERO case of the same switch. domain_7_value_2 -> BOLT_PICKUP_TURN_TOWARD_HERO: Retail 0x002e4b78..0x002e4bd8 checks hero reach on return-timer expiration, sets the short launch timer at pvars+0x68, and writes 2 to moby+0x20. That is the exact field dispatched at 0x002e38ac and named BOLT_PICKUP_TURN_TOWARD_HERO in the existing local enum and case. domain_8_value_1 -> BOLT_PICKUP_WAIT_FOR_HERO: Retail 0x002e4bdc..0x002e4c34 checks nonzero moby+0xbc after the return timer, writes 1 to moby+0x20, and restores the saved surface pose or converts it to attachment-local form. This resumes existing BOLT_PICKUP_WAIT_FOR_HERO on the same moby-state dispatch, preserving attachment following and proximity detection. --- src/overlays/l08/mobys/batalia_bolt_pickup.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/l08/mobys/batalia_bolt_pickup.c b/src/overlays/l08/mobys/batalia_bolt_pickup.c index 3c5e4fa650..9ad9dbfc44 100644 --- a/src/overlays/l08/mobys/batalia_bolt_pickup.c +++ b/src/overlays/l08/mobys/batalia_bolt_pickup.c @@ -248,7 +248,7 @@ void update_batalia_bolt_pickup(struct Moby *moby) { convert_pose_to_reference_local( moby, linked, vars->anchor, vars->v10, vars->v20, vars->v30); } - moby->state = 1; + moby->state = BOLT_PICKUP_WAIT_FOR_HERO; vars->s6C = 0; vars->u70.i = truncate_float_to_s32(random_float_between(0.0f, (float)scale_game_frames(600))); @@ -268,14 +268,14 @@ void update_batalia_bolt_pickup(struct Moby *moby) { &moby->rot_row1, l08_bolt_pickup_detached_fall_spin_speed_degrees * 0.017453292f * frame_time); - moby->state = 4; + moby->state = BOLT_PICKUP_FALL_AND_BOUNCE; break; } } if (absolute_float(moby->pos.z - hero.motion.pos.f[2]) < hero.reach_distance && vector_distance_xy(&moby->pos, hero.motion.pos.f) < hero.reach_height) { vars->timer = scale_game_frames(1); - moby->state = 2; + moby->state = BOLT_PICKUP_TURN_TOWARD_HERO; } if (moby->visible == 0) { if (moby > D_L08_0015FFDC && @@ -363,7 +363,7 @@ void update_batalia_bolt_pickup(struct Moby *moby) { } else { vars->f64 = random_float_between(-30.0f, 30.0f) * deg_to_rad; } - moby->state = 3; + moby->state = BOLT_PICKUP_FLY_TO_HERO_AND_CREDIT_BOLTS; } else { if (scale_game_frames(10) < vars->timer) { float goal_yaw = fast_add_rotations( @@ -578,7 +578,7 @@ void update_batalia_bolt_pickup(struct Moby *moby) { *(u128_4BE8_p *)vars->v10 = *(u128_4BE8_p *)((char *)&hero + 0x90); vars->timer = scale_game_frames(1); - moby->state = 2; + moby->state = BOLT_PICKUP_TURN_TOWARD_HERO; break; } if (coll_sphere(0.25f, &moby->pos, 0x22, moby) != 0) { @@ -620,7 +620,7 @@ void update_batalia_bolt_pickup(struct Moby *moby) { vars->spin_x = fast_subtract_rotations(vars->v30[0], moby->rot.x) * per_frame; vars->spin_y = fast_subtract_rotations(vars->v30[1], moby->rot.y) * per_frame; vars->spin_z = fast_subtract_rotations(vars->v30[2], moby->rot.z) * per_frame; - moby->state = 5; + moby->state = BOLT_PICKUP_RETURN_TO_SURFACE; vars->timer = frames; vars->u7C.i = D_L08_00174658_lui; if (absolute_float(moby->pos.z - hero.motion.pos.f[2]) < hero.reach_distance && @@ -628,7 +628,7 @@ void update_batalia_bolt_pickup(struct Moby *moby) { Vars_4BE8 *vars = (Vars_4BE8 *)moby->pvars; vars->timer = scale_game_frames(1); - moby->state = 2; + moby->state = BOLT_PICKUP_TURN_TOWARD_HERO; } } } @@ -649,11 +649,11 @@ void update_batalia_bolt_pickup(struct Moby *moby) { if (absolute_float(moby->pos.z - hero.motion.pos.f[2]) < hero.reach_distance && vector_distance_xy(&moby->pos, hero.motion.pos.f) < hero.reach_height) { vars->timer = scale_game_frames(1); - moby->state = 2; + moby->state = BOLT_PICKUP_TURN_TOWARD_HERO; break; } if (moby->command != 0) { - moby->state = 1; + moby->state = BOLT_PICKUP_WAIT_FOR_HERO; if (vars->u7C.i != 0) { Vars_4BE8 *vars = (Vars_4BE8 *)moby->pvars; From 3b79466153e460f822c12898dbdb745a68ff3b74 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:27:19 +0000 Subject: [PATCH 1120/1502] decomp: clarify names in snow_plow_update domain_0_value_3 -> SNOW_PLOW_WAIT_TO_RESUME_PATH: Owner Moby is s5 at 0x002ca42c; 0x002ca8c0 loads 3 and 0x002ca8dc stores it to owner+0x20 (moby->state), while 0x002ca8bc separately sets pvars+0x149 to 1. The same acquisition saves position/heading and stores scale_game_frames(36000) at pvars+0x11c (0x002ca8c8-0x002ca8e4). Checked direct helper gunship_follow_path at level-04 0x002cb8b8 preserves that Moby as s4 and pvars as s3; 0x002cbbb4-0x002cbbe4 dispatches owner+0x20 value 3 to 0x002cc104. That branch decrements the timer at pvars+0x11c, returns while unexpired, and on expiry clears the timer and writes s0=1 to owner+0x20 at 0x002cc114-0x002cc11c. State 1 instead enters path interpolation at 0x002cc120 and writes path position to owner+0x10 at 0x002cc450. This proves a wait before resuming path following, distinct from the movement return substate. --- src/overlays/l04/mobys/snow_plow.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l04/mobys/snow_plow.c b/src/overlays/l04/mobys/snow_plow.c index a296e3e0c2..26100d0f63 100644 --- a/src/overlays/l04/mobys/snow_plow.c +++ b/src/overlays/l04/mobys/snow_plow.c @@ -117,7 +117,7 @@ void snow_plow_update(struct Moby *moby) { SNOW_PLOW_CLASS_OFFSET_WITH_FOUR_HIT_SPAWNS_AND_TARGET_VOICE_SELECTOR_ONE = 0x1d, SNOW_PLOW_CLASS_OFFSET_WITH_THREE_HIT_SPAWNS_AND_TARGET_VOICE_SELECTOR_ZERO = 0x20, SNOW_PLOW_CLASS_OFFSET_WITH_TARGET_VOICE_SELECTOR_ZERO = 0x59 - }; + } ; enum { SNOW_PLOW_WAIT_TO_RESUME_PATH = 3}; Vec4 update_start_position; Vec4 delta, *return_delta_ptr; /* The sphere query is its position followed by the record; the hit cases pass one or the other. */ @@ -186,7 +186,7 @@ void snow_plow_update(struct Moby *moby) { snow_plow_vars->unk149 = 1; snow_plow_vars->unk14C = moby->rot.z; *(int *)&snow_plow_vars->unk7C = 0; - moby->state = 3; + moby->state = SNOW_PLOW_WAIT_TO_RESUME_PATH; snow_plow_vars->unk11C = scale_game_frames(36000); break; } From f909f3058f218e89f1cb0912a70c54ecfe947caa Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:29:02 +0000 Subject: [PATCH 1121/1502] decomp: clarify names in memcard_update_state domain_0_value_1 -> MEMCARD_PROCESS_INFO_RESULT: Retail 00209490 requests sceMcGetInfo; accepted dispatch stores 1 at base+0xd4 at 002094a0-002094a8. The same selector's branch 1 processes the synchronized result at 002094ac-00209518, proving canonical MemoryCardOperation MEMCARD_PROCESS_INFO_RESULT. domain_10_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_11_value_8 -> MEMCARD_PROBE_SAVE_HEADER: Retail sceMcChdir at 0020967c is followed on accepted dispatch by sub=0 and major selector base+0xd4=8 at 0020968c-00209698. Branch 8 opens the save, reads its eight-byte size header, validates both words and closes (002096c8-0020999c), proving MEMCARD_PROBE_SAVE_HEADER. domain_12_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_13_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_14_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_15_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_16_value_21 -> MEMCARD_BEGIN_SCAN_SAVE_INFO: Retail probe-close branch 00209984-0020999c passes 21 through 0020a550-0020a558 into major selector base+0xd4. Branch 21 at 0020a064-0020a08c initializes scan_save_index=-1 and record_index=0 then state=22, proving MEMCARD_BEGIN_SCAN_SAVE_INFO. domain_17_value_10 -> MEMCARD_CREATE_SAVE_DIRECTORY: Retail 002099a0-002099c0 stores 10 to major selector base+0xd4, clears sub and save_index, then enters the creation switch. Its space check, mkdir and file open/write/close phases at 002099c4-00209e24 prove canonical MemoryCardOperation MEMCARD_CREATE_SAVE_DIRECTORY. domain_18_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_19_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_1_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_21_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_22_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_23_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_24_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_25_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_26_value_12 -> MEMCARD_DELETE_SAVE_DIRECTORY: Retail 00209e28-00209e4c stores 12 to major selector base+0xd4 and initializes deletion. Branch 12 enumerates entries with sceMcGetDir and deletes entries/directory at 00209e50-0020a060, proving canonical MemoryCardOperation MEMCARD_DELETE_SAVE_DIRECTORY. domain_27_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_28_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_29_value_22 -> MEMCARD_ADVANCE_SAVE_INFO_SCAN: Retail 0020a064-0020a08c initializes scan index and stores 22 to major selector base+0xd4; 0020a090-0020a0d8 increments through five scan indices. Scanned-read close returns to 22 via 0020a54c-0020a558. This is canonical MemoryCardOperation MEMCARD_ADVANCE_SAVE_INFO_SCAN. domain_2_value_2 -> MEMCARD_DISPATCH_PENDING_OPERATION: Retail 00209510-00209518 stores 2 in major selector base+0xd4 after info processing. Branch 2 at 0020951c-00209584 dispatches pending_state into that selector; format/unformat bypass paths also set 2 via 0020a550-0020a558. Thus MC.state uses MEMCARD_DISPATCH_PENDING_OPERATION. domain_30_value_23 -> MEMCARD_READ_SCANNED_SAVE_INFO: Retail major selector base+0xd4 is assigned 23 at 0020a0cc-0020a0d8. Its comparisons at 0020a148-0020a178, 0020a36c-0020a39c and 0020a53c-0020a558 select scan_save_index, memcard_restore_info, and return to scanning. Thus this MC.state token reuses MEMCARD_READ_SCANNED_SAVE_INFO, not a read substep. domain_31_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_32_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_33_value_14 -> MEMCARD_READ_SAVE: Retail 0020a10c-0020a118 stores 14 to major selector base+0xd4 after validating selected save and initializing record/sub indices. Branch 14 opens, reads main data, restores twenty level records and closes (0020a11c-0020a558), proving canonical MemoryCardOperation MEMCARD_READ_SAVE. domain_34_value_23 -> MEMCARD_READ_SCANNED_SAVE_INFO: Retail major selector base+0xd4 is assigned 23 at 0020a0cc-0020a0d8. Its comparisons at 0020a148-0020a178, 0020a36c-0020a39c and 0020a53c-0020a558 select scan_save_index, memcard_restore_info, and return to scanning. Thus this MC.state token reuses MEMCARD_READ_SCANNED_SAVE_INFO, not a read substep. domain_35_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_36_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_37_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_38_value_23 -> MEMCARD_READ_SCANNED_SAVE_INFO: Retail major selector base+0xd4 is assigned 23 at 0020a0cc-0020a0d8. Its comparisons at 0020a148-0020a178, 0020a36c-0020a39c and 0020a53c-0020a558 select scan_save_index, memcard_restore_info, and return to scanning. Thus this MC.state token reuses MEMCARD_READ_SCANNED_SAVE_INFO, not a read substep. domain_39_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_40_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_41_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_42_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_43_value_23 -> MEMCARD_READ_SCANNED_SAVE_INFO: Retail major selector base+0xd4 is assigned 23 at 0020a0cc-0020a0d8. Its comparisons at 0020a148-0020a178, 0020a36c-0020a39c and 0020a53c-0020a558 select scan_save_index, memcard_restore_info, and return to scanning. Thus this MC.state token reuses MEMCARD_READ_SCANNED_SAVE_INFO, not a read substep. domain_44_value_22 -> MEMCARD_ADVANCE_SAVE_INFO_SCAN: Retail 0020a064-0020a08c initializes scan index and stores 22 to major selector base+0xd4; 0020a090-0020a0d8 increments through five scan indices. Scanned-read close returns to 22 via 0020a54c-0020a558. This is canonical MemoryCardOperation MEMCARD_ADVANCE_SAVE_INFO_SCAN. domain_45_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_46_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_47_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_48_value_16 -> MEMCARD_UPDATE_SAVE: Retail 0020a55c-0020a598 checks errors and selected save then clears sub and stores 16 to major selector base+0xd4. Branch 16 opens for write, skips header, overwrites main data and indexed record, then closes (0020a59c-0020a8fc), proving MEMCARD_UPDATE_SAVE. domain_49_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_4_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_50_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_51_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_52_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_53_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_54_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_55_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_56_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_57_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_58_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_59_value_20 -> MEMCARD_WRITE_FULL_SAVE: Retail 0020a990-0020a9e0 validates card and save, clears record/sub indices and stores 20 to major selector base+0xd4. Branch 20 opens and writes main span plus twenty record spans plus eight bytes then closes (0020a9e4-0020ab8c), proving MEMCARD_WRITE_FULL_SAVE. domain_5_value_4 -> MEMCARD_PROCESS_FORMAT_RESULT: After accepted SceMcFormat at 002095b0, retail 002095c0-002095c8 stores 4 in major selector base+0xd4. Branch 4 processes MC.result at 002095cc-002095e0 and 0020963c-00209650, proving MEMCARD_PROCESS_FORMAT_RESULT in MemoryCardOperation. domain_60_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_61_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_62_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_63_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_6_value_2 -> MEMCARD_DISPATCH_PENDING_OPERATION: Retail 00209510-00209518 stores 2 in major selector base+0xd4 after info processing. Branch 2 at 0020951c-00209584 dispatches pending_state into that selector; format/unformat bypass paths also set 2 via 0020a550-0020a558. Thus MC.state uses MEMCARD_DISPATCH_PENDING_OPERATION. domain_7_value_0 -> MEMCARD_QUERY_INFO: Retail 00209420 loads state from memory-card base+0xd4 for the major switch; zero selects sceMcGetInfo at 00209450-002094a8. This MC.state assignment resets that same selector to its canonical MemoryCardOperation member MEMCARD_QUERY_INFO, including shared reset stores at 0020a690-0020a69c and 0020ab58-0020ab88. domain_8_value_6 -> MEMCARD_PROCESS_UNFORMAT_RESULT: After accepted SceMcUnformat at 0020960c, retail 0020961c-00209624 stores 6 in major selector base+0xd4. Branch 6 processes its synchronized result at 00209628-00209650, proving MEMCARD_PROCESS_UNFORMAT_RESULT in MemoryCardOperation. domain_9_value_2 -> MEMCARD_DISPATCH_PENDING_OPERATION: Retail 00209510-00209518 stores 2 in major selector base+0xd4 after info processing. Branch 2 at 0020951c-00209584 dispatches pending_state into that selector; format/unformat bypass paths also set 2 via 0020a550-0020a558. Thus MC.state uses MEMCARD_DISPATCH_PENDING_OPERATION. --- src/save/memcard_update_state.c | 124 ++++++++++++++++---------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/src/save/memcard_update_state.c b/src/save/memcard_update_state.c index f87f452ce3..e1ca141ff6 100644 --- a/src/save/memcard_update_state.c +++ b/src/save/memcard_update_state.c @@ -58,7 +58,7 @@ void memcard_update_state(void) { MC.cur = 0; } if (sceMcGetInfo(CARD.port, CARD.slot, &CARD.type, &CARD.free, &CARD.format) == 0) { - MC.state = 1; + MC.state = MEMCARD_PROCESS_INFO_RESULT; } break; @@ -69,9 +69,9 @@ void memcard_update_state(void) { CARD.errors = -1; } if (++MC.cur < 1) { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; } else { - MC.state = 2; + MC.state = MEMCARD_DISPATCH_PENDING_OPERATION; } MC.busy = 0; break; @@ -92,7 +92,7 @@ void memcard_update_state(void) { } else { if (++MC.cur >= 31) { MC.cur = 0; - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; } } MC.busy = 0; @@ -101,12 +101,12 @@ void memcard_update_state(void) { case MEMCARD_REQUEST_FORMAT: if (CARD.format == 0) { if (SceMcFormat(CARD.port, CARD.slot) == 0) { - MC.state = 4; + MC.state = MEMCARD_PROCESS_FORMAT_RESULT; } break; } MC.busy = 0; - MC.state = 2; + MC.state = MEMCARD_DISPATCH_PENDING_OPERATION; break; case MEMCARD_PROCESS_FORMAT_RESULT: @@ -114,7 +114,7 @@ void memcard_update_state(void) { MC.err = 1; MC.err_card = MC.cur; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; break; @@ -122,12 +122,12 @@ void memcard_update_state(void) { case MEMCARD_REQUEST_UNFORMAT: if (CARD.format == 0) { if (SceMcUnformat(CARD.port, CARD.slot) == 0) { - MC.state = 6; + MC.state = MEMCARD_PROCESS_UNFORMAT_RESULT; } break; } MC.busy = 0; - MC.state = 2; + MC.state = MEMCARD_DISPATCH_PENDING_OPERATION; break; case MEMCARD_PROCESS_UNFORMAT_RESULT: @@ -135,7 +135,7 @@ void memcard_update_state(void) { MC.err = 2; MC.err_card = MC.cur; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; break; @@ -143,7 +143,7 @@ void memcard_update_state(void) { case MEMCARD_REQUEST_CHDIR: if (sceMcChdir(CARD.port, CARD.slot, D_0013D1D0, 0) == 0) { MC.sub = 0; - MC.state = 8; + MC.state = MEMCARD_PROBE_SAVE_HEADER; } break; @@ -166,7 +166,7 @@ void memcard_update_state(void) { MC.err = 4; MC.err_card = MC.cur; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -197,7 +197,7 @@ void memcard_update_state(void) { } else { MC.err = 4; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; } MC.busy = 0; @@ -225,7 +225,7 @@ void memcard_update_state(void) { if (MC.result >= 0) { MC.err = 0x2716; if (sceMcClose(MC.fd) == 0) { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -242,7 +242,7 @@ void memcard_update_state(void) { } else { MC.err = 4; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -250,14 +250,14 @@ void memcard_update_state(void) { case MEMCARD_PROBE_REQUEST_CLOSE: if (sceMcClose(MC.fd) == 0) { MC.busy = 0; - MC.state = 21; + MC.state = MEMCARD_BEGIN_SCAN_SAVE_INFO; } break; } break; case MEMCARD_BEGIN_CREATE_SAVE_DIRECTORY: - MC.state = 10; + MC.state = MEMCARD_CREATE_SAVE_DIRECTORY; MC.sub = 0; CARD.save_index = 0; case MEMCARD_CREATE_SAVE_DIRECTORY: @@ -268,7 +268,7 @@ void memcard_update_state(void) { } else { MC.err = 7; MC.err_card = MC.cur; - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; } MC.busy = 0; @@ -291,7 +291,7 @@ void memcard_update_state(void) { } else { MC.err = 0xD; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; break; @@ -377,7 +377,7 @@ void memcard_update_state(void) { } else { MC.err = 0xA; MC.err_card = MC.cur; - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -397,7 +397,7 @@ void memcard_update_state(void) { if (MC.result >= 0) { MC.err = 0xB; if (sceMcClose(MC.fd) == 0) { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -412,7 +412,7 @@ void memcard_update_state(void) { } else { MC.err = 0xD; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; break; @@ -424,7 +424,7 @@ void memcard_update_state(void) { } else { MC.err = 0xC; MC.err_card = MC.cur; - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; } MC.busy = 0; @@ -439,7 +439,7 @@ void memcard_update_state(void) { break; case MEMCARD_CREATE_RESET_CARD_STATUS: MC.card[0].save_index = -1; - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.card[0].errors = 0; break; @@ -447,7 +447,7 @@ void memcard_update_state(void) { break; case MEMCARD_BEGIN_DELETE_SAVE_DIRECTORY: - MC.state = 12; + MC.state = MEMCARD_DELETE_SAVE_DIRECTORY; MC.sub = 0; CARD.save_index = -2; case MEMCARD_DELETE_SAVE_DIRECTORY: @@ -478,7 +478,7 @@ void memcard_update_state(void) { } else { MC.err = 0x12; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; } MC.busy = 0; @@ -510,7 +510,7 @@ void memcard_update_state(void) { MC.err = 0x12; } } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; break; @@ -518,7 +518,7 @@ void memcard_update_state(void) { break; case MEMCARD_BEGIN_SCAN_SAVE_INFO: - MC.state = 22; + MC.state = MEMCARD_ADVANCE_SAVE_INFO_SCAN; CARD.scan_save_index = -1; MC.record_index = 0; break; @@ -527,9 +527,9 @@ void memcard_update_state(void) { CARD.scan_save_index++; if (CARD.scan_save_index < 5) { MC.sub = 0; - MC.state = 23; + MC.state = MEMCARD_READ_SCANNED_SAVE_INFO; } else { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -537,19 +537,19 @@ void memcard_update_state(void) { case MEMCARD_BEGIN_READ_SAVE: if (CARD.save_index < 0) { MC.busy = 0; - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.err = 0x13; break; } MC.record_index = 0; MC.sub = 0; - MC.state = 14; + MC.state = MEMCARD_READ_SAVE; case MEMCARD_READ_SAVE: case MEMCARD_READ_SCANNED_SAVE_INFO: switch (MC.sub) { case MEMCARD_READ_SAVE_REQUEST_OPEN: - if (MC.state == 23) { + if (MC.state == MEMCARD_READ_SCANNED_SAVE_INFO) { sprintf(name, D_0013D270, CARD.scan_save_index); } else { sprintf(name, D_0013D270, CARD.save_index); @@ -577,7 +577,7 @@ void memcard_update_state(void) { } else { MC.err = 0x1C; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; } MC.busy = 0; @@ -598,7 +598,7 @@ void memcard_update_state(void) { if (MC.result >= 0) { MC.err = 0x1B; if (sceMcClose(MC.fd) == 0) { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -615,7 +615,7 @@ void memcard_update_state(void) { } else { MC.err = 0x1C; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; break; @@ -630,7 +630,7 @@ void memcard_update_state(void) { break; case MEMCARD_READ_SAVE_PROCESS_MAIN_DATA_READ_RESULT: if (MC.result == MC.size) { - if (MC.state == 23) { + if (MC.state == MEMCARD_READ_SCANNED_SAVE_INFO) { memcard_restore_info(memcard_game_data_buffer, MC.cur, CARD.scan_save_index); MC.sub = 8; } else { @@ -644,7 +644,7 @@ void memcard_update_state(void) { if (MC.result >= 0) { MC.err = 0x1B; if (sceMcClose(MC.fd) == 0) { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -661,7 +661,7 @@ void memcard_update_state(void) { } else { MC.err = 0x1C; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; break; @@ -690,7 +690,7 @@ void memcard_update_state(void) { if (MC.result >= 0) { MC.err = 0x1B; if (sceMcClose(MC.fd) == 0) { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -707,17 +707,17 @@ void memcard_update_state(void) { } else { MC.err = 0x1C; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; break; case MEMCARD_READ_SAVE_REQUEST_CLOSE: if (sceMcClose(MC.fd) == 0) { - if (MC.state == 23) { + if (MC.state == MEMCARD_READ_SCANNED_SAVE_INFO) { MC.busy = 0; - MC.state = 22; + MC.state = MEMCARD_ADVANCE_SAVE_INFO_SCAN; } else { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; } } @@ -728,20 +728,20 @@ void memcard_update_state(void) { case MEMCARD_BEGIN_UPDATE_SAVE: if (CARD.errors != 0) { MC.busy = 0; - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.err = 0x2717; break; } if (CARD.save_index < 0) { MC.busy = 0; - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.err = 0x1D; break; } MC.sub = 0; - MC.state = 16; + MC.state = MEMCARD_UPDATE_SAVE; case MEMCARD_UPDATE_SAVE: switch (MC.sub) { case MEMCARD_UPDATE_SAVE_REQUEST_OPEN: @@ -769,7 +769,7 @@ void memcard_update_state(void) { } else { MC.err = 0x26; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; } MC.busy = 0; @@ -783,7 +783,7 @@ void memcard_update_state(void) { if (MC.result >= 0) { MC.sub = 4; } else { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -803,7 +803,7 @@ void memcard_update_state(void) { if (MC.result >= 0) { MC.err = 0x25; if (sceMcClose(MC.fd) == 0) { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -820,7 +820,7 @@ void memcard_update_state(void) { } else { MC.err = 0x26; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; break; @@ -837,7 +837,7 @@ void memcard_update_state(void) { if (MC.result >= 0) { MC.sub = 8; } else { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -857,7 +857,7 @@ void memcard_update_state(void) { if (MC.result >= 0) { MC.err = 0x25; if (sceMcClose(MC.fd) == 0) { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -874,13 +874,13 @@ void memcard_update_state(void) { } else { MC.err = 0x1C; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; break; case MEMCARD_UPDATE_SAVE_REQUEST_CLOSE: if (sceMcClose(MC.fd) == 0) { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; } break; @@ -914,21 +914,21 @@ void memcard_update_state(void) { case MEMCARD_BEGIN_WRITE_FULL_SAVE: if (CARD.errors != 0) { MC.busy = 0; - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.err = 0x2718; break; } if (CARD.save_index < 0) { MC.busy = 0; - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.err = 0x27; break; } MC.record_index = 0; MC.sub = 0; - MC.state = 20; + MC.state = MEMCARD_WRITE_FULL_SAVE; case MEMCARD_WRITE_FULL_SAVE: switch (MC.sub) { case MEMCARD_WRITE_FULL_SAVE_REQUEST_OPEN: @@ -951,7 +951,7 @@ void memcard_update_state(void) { } MC.err = 0x2B; MC.err_card = MC.cur; - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; break; @@ -966,7 +966,7 @@ void memcard_update_state(void) { if (MC.result >= 0) { MC.err = 0xB; if (sceMcClose(MC.fd) == 0) { - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; } @@ -981,7 +981,7 @@ void memcard_update_state(void) { } else { MC.err = 0x2D; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; break; @@ -990,7 +990,7 @@ void memcard_update_state(void) { MC.err = 0x2C; MC.err_card = MC.cur; } - MC.state = 0; + MC.state = MEMCARD_QUERY_INFO; MC.cur = 0; MC.busy = 0; break; From 5c49a1a74a95029afef47366e0d44da6e63e47f8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:29:03 +0000 Subject: [PATCH 1122/1502] decomp: clarify names in doom_bot_update domain_0_value_11 -> DOOM_BOT_DETONATE: Retail 002c009c-002c00ac: A successful find_moby_hit call writes 11 to moby+20; the same byte selects the explosion/blast/removal arm at 002c1248-002c13f4. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_10_value_2 -> DOOM_BOT_SELECT_MOVEMENT_MODE: Retail 002c0730-002c074c: Recovery fall requires animation completion and collision contact before writing 2 to moby+20; case 2 enters shared target and movement-mode selection. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_11_value_2 -> DOOM_BOT_SELECT_MOVEMENT_MODE: Retail 002c0750-002c0764: Animation flag bit 2 gates a store of 2 to moby+20, whose shared switch arm checks targets and chooses movement modes 4 or 5. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_14_value_11 -> DOOM_BOT_DETONATE: Retail 002c07bc-002c07f8: Target proximity plus a successful sphere collision writes 11 to moby+20, entering the existing explosion/blast/removal arm. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_15_value_6 -> DOOM_BOT_ALIGN_TO_TARGET: Retail 002c085c-002c08e4: After hop trajectory initialization and target-position copy, 6 is stored to moby+20; case 6 turns toward stored target heading before jump. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_16_value_4 -> DOOM_BOT_MOVE_HIGH_TURN_RATE: Retail 002c0944-002c0964: This writes 4 to moby+20 alongside turn_rate=frame_scale*0.1*speed, matching the named high-turn-rate member of the same switch. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_17_value_2 -> DOOM_BOT_SELECT_MOVEMENT_MODE: Retail 002c0a38-002c0a88: Rejected target is cleared and 2 is stored to moby+20; the case-2 shared handler reacquires targets and chooses movement mode. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_18_value_5 -> DOOM_BOT_MOVE_LOW_TURN_RATE: Retail 002c0aa0-002c0afc: No target causes a store of 5 to moby+20 and turn_rate=frame_scale*0.0273*speed, matching the named low-turn-rate switch member. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_19_value_6 -> DOOM_BOT_ALIGN_TO_TARGET: Retail 002c0b10-002c0b94: Successful try_start_moby_hop copies target position, configures turn rate and writes 6 to moby+20, entering target-heading alignment. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_1_value_11 -> DOOM_BOT_DETONATE: Retail 002c0138-002c0140: The moby+20 comparison skips ordinary setup for 11, the same selector member whose switch arm spawns the explosion and removes the bot. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_20_value_5 -> DOOM_BOT_MOVE_LOW_TURN_RATE: Retail 002c0bb4-002c0c20: The hero-target branch stores 5 to moby+20 and applies turn_rate factor 0.0273, matching the same switch's low-turn-rate mode. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_21_value_5 -> DOOM_BOT_MOVE_LOW_TURN_RATE: Retail 002c0c24-002c0c94: The greater-than-20 distance branch writes 5 to moby+20 and selects the 0.0273 turn-rate factor, the established low-turn-rate mode. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_22_value_4 -> DOOM_BOT_MOVE_HIGH_TURN_RATE: Retail 002c0c98-002c0ce8: The nearer-target branch writes 4 to moby+20 and selects turn-rate factor 0.1, the established high-turn-rate switch member. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_23_value_4 -> DOOM_BOT_MOVE_HIGH_TURN_RATE: Retail 002c0d70-002c0d78: This comparison reloads moby+20 and tests high-turn-rate state 4 before checking the saved preceding movement mode. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_24_value_5 -> DOOM_BOT_MOVE_LOW_TURN_RATE: Retail 002c0aa4,002c0d80-002c0d84: old_state is loaded directly from moby+20 into s1 at 002c0aa4; its comparison with 5 detects entry from the established low-turn-rate mode. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_25_value_12 -> DOOM_BOT_WAIT_FOR_TRANSITION_ANIMATION: Retail 002c0d8c-002c0db8: The low-to-high movement-mode transition stores 12 to moby+20 and starts animation 1; case 12 waits for completion before restoring state 4. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_26_value_6 -> DOOM_BOT_ALIGN_TO_TARGET: Retail 002c0ff0-002c1054: A successful obstacle-hop attempt configures the target turn rate and stores 6 to moby+20, whose switch arm aligns heading before jumping. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_27_value_8 -> DOOM_BOT_COLLISION_RECOVERY_FALL: Retail 002c1058-002c10cc: Failed obstacle-hop recovery builds a retreat velocity and stores 8 to moby+20; case 8 applies gravity and collision damping. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_28_value_7 -> DOOM_BOT_EXECUTE_JUMP: Retail 002c1188-002c11b0: Once heading error is below threshold, config.anim2C is started and 7 is stored to moby+20; case 7 calls update_arc_motion. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_29_value_4 -> DOOM_BOT_MOVE_HIGH_TURN_RATE: Retail 002c1400-002c1460: Transition animation completion writes 4 to moby+20, starts animation 7 and restores turn_rate factor 0.1, matching the high-turn-rate mode. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_2_value_0 -> DOOM_BOT_INITIALIZE: Retail 002c0194-002c0308: The moby+20 zero comparison gates config clearing, movement/gravity initialization and target/timer clearing before initial fall. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_30_value_2 -> DOOM_BOT_SELECT_MOVEMENT_MODE: Retail 002c15c0-002c15fc: Initial-fall contact writes 2 to moby+20, entering the shared handler that selects target and movement modes. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_31_value_0 -> DOOM_BOT_INITIALIZE: Retail 002c1644: The reset-to-initialize arm clears moby+20; the next update's zero-state gate initializes config, movement parameters, target and timer. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_32_value_0 -> DOOM_BOT_INITIALIZE: Retail 002c0640-002c0644,002c1644: Out-of-range switch selectors reach a zero store to moby+20; zero is the same state used by the pre-switch initialization gate at 002c0194. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_3_value_14 -> DOOM_BOT_INITIAL_FALL: Retail 002c02e0-002c02e8: Initialization clears target and timer and stores 14 to moby+20; its switch arm at 002c1478 applies gravity and collision landing. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_4_value_13 -> DOOM_BOT_SQUIRM: Retail 002c033c-002c03f8: The comparison reads moby+20, the same switch selector whose case 13 prints the established squirm diagnostic at 002c1464-002c146c. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_5_value_11 -> DOOM_BOT_DETONATE: Retail 002c040c-002c041c: Age exceeding scale_game_frames(3600) stores 11 to moby+20, selecting the existing detonation arm with explosion and removal. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_6_value_11 -> DOOM_BOT_DETONATE: Retail 002c0454-002c04a8: A flagged class-5 collision stores 11 to moby+20, selecting the same detonation switch arm at 002c1248-002c13f4. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_7_value_8 -> DOOM_BOT_COLLISION_RECOVERY_FALL: Retail 002c0518-002c0564: Collision normal is copied into velocity and limited before 8 is stored to moby+20; case 8 integrates gravity and damps velocity on contact. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_8_value_11 -> DOOM_BOT_DETONATE: Retail 002c05d4-002c05e8: The timer threshold stores 11 into moby+20, the exact switch selector whose case 11 generates blast effects and removes the bot. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. domain_9_value_1 -> DOOM_BOT_WAIT_FOR_ANIMATION_BEFORE_MOVEMENT: Retail 002c0664-002c0678: The initialization diagnostic arm writes 1 to moby+20; case 1 at 002c0750 waits for animation flag bit 2 before selecting movement state 2. Authoritative source uses this same moby->state domain in doom_bot_update's named local enum. --- src/overlays/shared/weapons/doom_bot.c | 60 +++++++++++++------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/overlays/shared/weapons/doom_bot.c b/src/overlays/shared/weapons/doom_bot.c index b712f13c3c..93fb081c5e 100644 --- a/src/overlays/shared/weapons/doom_bot.c +++ b/src/overlays/shared/weapons/doom_bot.c @@ -196,7 +196,7 @@ void doom_bot_update(struct Moby *moby) { return; } if (find_moby_hit(moby, 0x800001, 0)) - moby->state = 11; + moby->state = DOOM_BOT_DETONATE; scale = convert_integer_to_float(item_text_variant[0x14]) + 1.0f; moby->scale += (moby->pclass->scale * scale - moby->scale) * 0.05f; speed = convert_integer_to_float(item_text_variant[0x14]) * 0.5f + 1.0f; @@ -204,13 +204,13 @@ void doom_bot_update(struct Moby *moby) { moby->anim_speed = speed / scale; else moby->anim_speed = 1.0f; - if (moby->state != 11) { + if (moby->state != DOOM_BOT_DETONATE) { int damage = truncate_float_to_s32(scale * 183.296f) + 1; DoomBotParams *hp = (DoomBotParams *)&hero; hp->damage = damage; hp->f1EF0 = 0; hp->f1EC4 = scale * 0.198f + 0.02f; - if (moby->state == 0) { + if (moby->state == DOOM_BOT_INITIALIZE) { float frame, turn; memset(&hp->config, 0, 64); frame = frame_scale; @@ -238,7 +238,7 @@ void doom_bot_update(struct Moby *moby) { hp->config.rate = frame * 0.01f; hp->config.max = frame * 0.045f; doom_bot_vars->target_moby = 0; - moby->state = 14; + moby->state = DOOM_BOT_INITIAL_FALL; doom_bot_vars->timer = 0; doom_bot_vars->turn_rate = frame_scale * 0.1f * speed; save_state_fields_to_hero((char *)doom_bot_vars); @@ -246,7 +246,7 @@ void doom_bot_update(struct Moby *moby) { if (moby->prev_seq != 5) blend_moby_animation(moby, 5, 0, scale_game_frames(5)); } - if (moby->state == 13) { + if (moby->state == DOOM_BOT_SQUIRM) { if (!doom_bot_vars->owner || doom_bot_vars->owner->state == 0xFE || doom_bot_vars->owner->state == 0xFD || moby->pos.x < 2.0f || moby->pos.x > 1021.0f || moby->pos.y < 2.0f || moby->pos.y > 1021.0f || @@ -258,7 +258,7 @@ void doom_bot_update(struct Moby *moby) { } doom_bot_vars->age++; if (scale_game_frames(3600) < doom_bot_vars->age) - moby->state = 11; + moby->state = DOOM_BOT_DETONATE; fast_dec_timer(&doom_bot_vars->timer); qcopy(&doom_bot_vars->previous_position, &moby->pos); if (probe_moby_raised_sphere_collision((char *)moby, 5, 0)) { @@ -266,7 +266,7 @@ void doom_bot_update(struct Moby *moby) { (((struct Moby *)coll_hit.moby)->flags & 0x1000) && ((struct Moby *)coll_hit.moby)->pclass && ((struct Moby *)coll_hit.moby)->pclass->type == 5) { - moby->state = 11; + moby->state = DOOM_BOT_DETONATE; } else if (!coll_hit.moby || coll_hit.unk1C < 0) { z = moby->pos.z; qcopy_nc(&moby->pos, coll_hit.pad30); @@ -277,7 +277,7 @@ void doom_bot_update(struct Moby *moby) { &doom_bot_vars->velocity, &doom_bot_vars->velocity, frame_scale * 0.05f); FUN_L00_001ff600( frame_scale * 0.05f, &doom_bot_vars->velocity, &doom_bot_vars->velocity); - moby->state = 8; + moby->state = DOOM_BOT_COLLISION_RECOVERY_FALL; if (doom_bot_vars->target_moby) { doom_bot_vars->last = doom_bot_vars->target_moby; doom_bot_vars->timer += 500; @@ -291,14 +291,14 @@ void doom_bot_update(struct Moby *moby) { return; } if (doom_bot_vars->timer >= 4001) - moby->state = 11; + moby->state = DOOM_BOT_DETONATE; } if (probe_ground_height(&moby->pos, 0, 0.5f) != 0 && coll_hit.moby) FUN_L00_00260400(moby, coll_hit.moby, &moby->pos, &moby->rot, &moby->pos, &moby->rot); switch (moby->state) { case DOOM_BOT_INITIALIZE: debug_print(D_L00_001E9B48); - moby->state = 1; + moby->state = DOOM_BOT_WAIT_FOR_ANIMATION_BEFORE_MOVEMENT; break; case DOOM_BOT_COLLISION_RECOVERY_FALL: { DoomBotParams *hp; @@ -319,7 +319,7 @@ void doom_bot_update(struct Moby *moby) { if (moby->prev_seq != 5) blend_moby_animation(moby, 5, 0, scale_game_frames(5)); } else - moby->state = 2; + moby->state = DOOM_BOT_SELECT_MOVEMENT_MODE; } goto Falling; } @@ -327,7 +327,7 @@ void doom_bot_update(struct Moby *moby) { case DOOM_BOT_WAIT_FOR_ANIMATION_TO_SELECT_MOVEMENT: case DOOM_BOT_WAIT_FOR_ANIMATION_COMPLETION: if (moby->anim_flags & 2) - moby->state = 2; + moby->state = DOOM_BOT_SELECT_MOVEMENT_MODE; goto Contact; case DOOM_BOT_SELECT_MOVEMENT_MODE: case DOOM_BOT_UPDATE_TARGET_AND_MOVEMENT: @@ -344,7 +344,7 @@ void doom_bot_update(struct Moby *moby) { } if (fast_vec_dist(&moby->pos, &doom_bot_vars->target_moby->pos) < reach && coll_sphere(&moby->pos, speed, 1, moby)) { - moby->state = 11; + moby->state = DOOM_BOT_DETONATE; break; } if (vector_distance(&moby->pos, &doom_bot_vars->target_moby->pos) < reach * 0.5f && @@ -357,7 +357,7 @@ void doom_bot_update(struct Moby *moby) { doom_bot_vars->turn_rate = frame_scale * 0.066f * speed; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(2)); - moby->state = 6; + moby->state = DOOM_BOT_ALIGN_TO_TARGET; } } qcopy(&movement_and_detonation_vectors[0], &moby->pos); @@ -366,7 +366,7 @@ void doom_bot_update(struct Moby *moby) { doom_bot_vars->target_moby = select_class5_target_or_hero( moby, &movement_and_detonation_vectors[0], &moby->rot, doom_bot_vars->last, 1); doom_bot_vars->turn_rate = frame_scale * 0.1f * speed; - moby->state = 4; + moby->state = DOOM_BOT_MOVE_HIGH_TURN_RATE; if (!doom_bot_vars->target_moby) { angle = random_float_between(-3.1415927f, 3.1415927f); if (random_integer_below(4) == 0) { @@ -394,13 +394,13 @@ void doom_bot_update(struct Moby *moby) { doom_bot_vars->target_moby->pclass->type != 5 || !(doom_bot_vars->target_moby->flags & 0x1000))) { doom_bot_vars->target_moby = 0; - moby->state = 2; + moby->state = DOOM_BOT_SELECT_MOVEMENT_MODE; doom_bot_vars->turn_rate = frame_scale * 0.0273f * speed; break; } old_state = moby->state; if (!doom_bot_vars->target_moby) { - moby->state = 5; + moby->state = DOOM_BOT_MOVE_LOW_TURN_RATE; if (moby->prev_seq != 6) blend_moby_animation(moby, 6, 0, scale_game_frames(10)); doom_bot_vars->turn_rate = frame_scale * 0.0273f * speed; @@ -411,26 +411,26 @@ void doom_bot_update(struct Moby *moby) { doom_bot_vars->turn_rate = frame_scale * 0.066f * speed; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(2)); - moby->state = 6; + moby->state = DOOM_BOT_ALIGN_TO_TARGET; break; } distance = vector_distance(&moby->pos, &doom_bot_vars->target_moby->pos); { DoomBotParams *hp = (DoomBotParams *)&hero; if (doom_bot_vars->target_moby == hp->moby) { - moby->state = 5; + moby->state = DOOM_BOT_MOVE_LOW_TURN_RATE; if ((moby->anim_flags & 2) && moby->prev_seq != 6) blend_moby_animation(moby, 6, 0, scale_game_frames(0)); doom_bot_vars->turn_rate = frame_scale * 0.0273f * speed; } } if (!(distance < 8.0f) && distance > 20.0f) { - moby->state = 5; + moby->state = DOOM_BOT_MOVE_LOW_TURN_RATE; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); doom_bot_vars->turn_rate = frame_scale * 0.0273f * speed; } else { - moby->state = 4; + moby->state = DOOM_BOT_MOVE_HIGH_TURN_RATE; if (moby->prev_seq != 7) blend_moby_animation(moby, 7, 0, scale_game_frames(10)); doom_bot_vars->turn_rate = frame_scale * 0.1f * speed; @@ -453,8 +453,8 @@ void doom_bot_update(struct Moby *moby) { } else clearance = 5.0f; } - if (moby->state == 4 && old_state == 5) { - moby->state = 12; + if (moby->state == DOOM_BOT_MOVE_HIGH_TURN_RATE && old_state == DOOM_BOT_MOVE_LOW_TURN_RATE) { + moby->state = DOOM_BOT_WAIT_FOR_TRANSITION_ANIMATION; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); goto Contact; @@ -512,7 +512,7 @@ void doom_bot_update(struct Moby *moby) { doom_bot_vars->turn_rate = frame_scale * 0.066f * speed; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(2)); - moby->state = 6; + moby->state = DOOM_BOT_ALIGN_TO_TARGET; goto Contact; } if (doom_bot_vars->target_moby) { @@ -523,7 +523,7 @@ void doom_bot_update(struct Moby *moby) { doom_bot_vars->velocity.f[1] = moby->pos.y - doom_bot_vars->target.f[1]; doom_bot_vars->velocity.f[2] = 0.01f; fast_vec_normalize(&doom_bot_vars->velocity, &doom_bot_vars->velocity, 0.1f); - moby->state = 8; + moby->state = DOOM_BOT_COLLISION_RECOVERY_FALL; if (moby->prev_seq != 5) blend_moby_animation(moby, 5, 0, scale_game_frames(5)); break; @@ -543,7 +543,7 @@ void doom_bot_update(struct Moby *moby) { restore_state_fields_from_hero((char *)doom_bot_vars); if (fast_difference_between_rotations(moby->rot.z, heading) < 0.08726646f) { blend_moby_animation(moby, hp->config.anim2C, 0, scale_game_frames(3)); - moby->state = 7; + moby->state = DOOM_BOT_EXECUTE_JUMP; } goto Contact; } @@ -609,7 +609,7 @@ void doom_bot_update(struct Moby *moby) { return; case DOOM_BOT_WAIT_FOR_TRANSITION_ANIMATION: if (moby->anim_flags & 2) { - moby->state = 4; + moby->state = DOOM_BOT_MOVE_HIGH_TURN_RATE; if (moby->prev_seq != 7) blend_moby_animation(moby, 7, 0, scale_game_frames(10)); doom_bot_vars->turn_rate = frame_scale * 0.1f * speed; @@ -647,7 +647,7 @@ void doom_bot_update(struct Moby *moby) { if (moby->prev_seq != 5) blend_moby_animation(moby, 5, 0, scale_game_frames(5)); } else - moby->state = 2; + moby->state = DOOM_BOT_SELECT_MOVEMENT_MODE; } /* Fakematch: the do-while(0) splits the scheduling region. */ Falling: @@ -672,10 +672,10 @@ void doom_bot_update(struct Moby *moby) { compute_moby_state_from_vertical_probe(moby) | ((unsigned char)(int)doom_bot_vars >> 8); break; case DOOM_BOT_RESET_TO_INITIALIZE: - moby->state = 0; + moby->state = DOOM_BOT_INITIALIZE; break; default: - moby->state = 0; + moby->state = DOOM_BOT_INITIALIZE; break; } if (moby->pos.x < 2.0f || moby->pos.x > 1021.0f || moby->pos.y < 2.0f || From e20defa887cbc9d651283966cb937e89e197b042 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:29:03 +0000 Subject: [PATCH 1123/1502] decomp: clarify names in blarg_helicopter_update domain_0_value_0 -> BLARG_HELICOPTER_INITIALIZE: Retail 002ccac0-002ccad0 reads moby+0x20 and bypasses the enabled check when zero; 002ccbb0-002ccbd0 dispatches that same byte, whose zero branch initializes health, paths and manipulators at 002ccbd8-002ccdcc. This is the existing helicopter INITIALIZE domain. domain_10_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 002cd18c-002cd1a8 compares the tracked class-0x350 projectile state byte +0x20 with 0xfd and enters the branch that clears data->projectile at 002cd2d4. Supplied mark_moby_for_removal source assigns 0xfd to the same Moby state field when moby < moby_instance_end, proving the removal-state meaning. domain_11_value_3 -> BLARG_HELICOPTER_EXIT: Retail 002cd728-002cd7e4 tests the target switch region and prepares the selected exit path's segment lengths, then passes 3 to 002cdb18, saving it in moby+0xbc. Retail 002cdc80-002cdc88 restores that byte to moby+0x20; existing EXIT branch 002cd898 handles exit-path travel or climb, proving the saved-state domain. domain_12_value_4 -> BLARG_HELICOPTER_TIMED_REACTION: The patrol switch-region branch at 002cd740-002cd7e4 reaches shared 002cdb18-002cdb30: saved EXIT state goes to moby+0xbc, 4 goes to the moby+0x20 selector, and a 15-frame timer is stored at data+0x206. Existing TIMED_REACTION at 002cdc70 restores the saved selector after that timer. domain_13_value_2 -> BLARG_HELICOPTER_PATROL_AND_ATTACK: Retail 002cdae8-002cdb14 toggles alternate, selects route_a or route_b, copies its first point, resets route index to 1 and loads 2; 002cdb1c saves it at moby+0xbc. Retail 002cdc80-002cdc88 restores this byte into the same +0x20 selector whose existing case 2 is PATROL_AND_ATTACK. domain_14_value_4 -> BLARG_HELICOPTER_TIMED_REACTION: Exit completion at 002cdae8-002cdb14 resets the alternate patrol route and reaches 002cdb18-002cdb30, writing 4 to moby+0x20 with a 15-frame timer while saving PATROL_AND_ATTACK at +0xbc. Existing TIMED_REACTION branch 002cdc70-002cdc88 consumes that timer and restores the saved state. domain_5_value_1 -> BLARG_HELICOPTER_ACTIVATION_PATH: Retail 002ccd44-002ccdc0 checks activation path/region, computes segment lengths, copies its first point to moby+0x10 and writes 1 to moby+0x20. The same byte dispatches the existing ACTIVATION_PATH branch at 002ccdd0, which waits for the region and travels that path. domain_6_value_2 -> BLARG_HELICOPTER_PATROL_AND_ATTACK: Retail 002ccdc4-002ccdcc writes 2 to moby+0x20 when initialization does not enter activation travel. That exact selector dispatches existing PATROL_AND_ATTACK at 002cd10c, selecting route_a/route_b, aiming the gun and spawning homing sparks. domain_7_value_2 -> BLARG_HELICOPTER_PATROL_AND_ATTACK: Retail 002ccf78-002ccf98 restores route_a start position/index and loads 2, then 002cdb18-002cdb30 saves it at moby+0xbc while entering timed reaction. Retail 002cdc80-002cdc88 copies this saved byte back to the moby+0x20 switch selector, proving previous_state shares the PATROL_AND_ATTACK domain. domain_8_value_4 -> BLARG_HELICOPTER_TIMED_REACTION: Activation completion at 002ccf78-002ccf98 reaches 002cdb18-002cdb30, which writes 4 to moby+0x20 and starts the 15-frame reaction timer. The same selector's existing TIMED_REACTION branch at 002cdc70-002cdc88 decrements that timer and restores moby+0xbc. domain_9_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 002cd174-002cd19c loads the tracked projectile, verifies class 0x350 and compares its moby state byte +0x20 against 0xfe before abandoning projectile tracking. Supplied mark_moby_for_removal source assigns this same Moby state value when moby >= moby_instance_end; this is the removal domain, not a helicopter lifecycle state. --- .../shared/enemies/blarg_helicopter.c | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/overlays/shared/enemies/blarg_helicopter.c b/src/overlays/shared/enemies/blarg_helicopter.c index 0042422f9d..8429ef1430 100644 --- a/src/overlays/shared/enemies/blarg_helicopter.c +++ b/src/overlays/shared/enemies/blarg_helicopter.c @@ -208,6 +208,10 @@ void blarg_helicopter_update(HMob49 *moby) { BLARG_HELICOPTER_TIMED_REACTION = 4, BLARG_HELICOPTER_DESTROY = 5 }; + enum { + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 253, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 254 + }; HData49 *data = moby->data; HWork49 helicopter_update_scratch; float target_range = 40.0f; @@ -223,7 +227,7 @@ void blarg_helicopter_update(HMob49 *moby) { mark_moby_for_removal(moby); return; } - if (data->route_a.path_id == -1 || (moby->state != 0 && data->enabled != 1)) { + if (data->route_a.path_id == -1 || (moby->state != BLARG_HELICOPTER_INITIALIZE && data->enabled != 1)) { if (data->child_index != -1) mark_moby_for_removal((HMob49 *)(D_L03_0015FFD8_c + (data->child_index << 8))); mark_moby_for_removal(moby); @@ -290,10 +294,10 @@ void blarg_helicopter_update(HMob49 *moby) { for (i = 0; i < path->count - 2; i++) path->points[i].length = fast_vec_dist(&path->points[i], &path->points[i + 1]); *(HQuad49_2CDDC8 *)moby->position = *(HQuad49_2CDDC8 *)path->points; - moby->state = 1; + moby->state = BLARG_HELICOPTER_ACTIVATION_PATH; break; } - moby->state = 2; + moby->state = BLARG_HELICOPTER_PATROL_AND_ATTACK; break; } case BLARG_HELICOPTER_ACTIVATION_PATH: { @@ -342,8 +346,8 @@ void blarg_helicopter_update(HMob49 *moby) { data->alternate = 0; qcopy(moby->position, data->route_a.path->points); data->route_a.index = 1; - moby->previous_state = 2; - moby->state = 4; + moby->previous_state = BLARG_HELICOPTER_PATROL_AND_ATTACK; + moby->state = BLARG_HELICOPTER_TIMED_REACTION; data->reaction_timer = scale_game_frames(15); break; } @@ -422,8 +426,8 @@ void blarg_helicopter_update(HMob49 *moby) { moby->rotation[2] = spring_turn(&data->yaw_velocity, moby->rotation[2], angle, 0.01f, 0.3f, 0.1f); projectile = data->projectile; - if (!projectile || projectile->class_id != 0x350 || projectile->state == 254 || - projectile->state == 253) { + if (!projectile || projectile->class_id != 0x350 || projectile->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || + projectile->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { moby_point_position(moby, 0, helicopter_update_scratch.movement); fast_vec_sub(helicopter_update_scratch.direction, helicopter_update_scratch.target.position, @@ -554,8 +558,8 @@ void blarg_helicopter_update(HMob49 *moby) { for (i = 0; i < path->count - 2; i++) path->points[i].length = fast_vec_dist(&path->points[i], &path->points[i + 1]); } - moby->previous_state = 3; - moby->state = 4; + moby->previous_state = BLARG_HELICOPTER_EXIT; + moby->state = BLARG_HELICOPTER_TIMED_REACTION; data->reaction_timer = scale_game_frames(15); break; } else if (is_point_inside_clip_volume(helicopter_update_scratch.target.position, @@ -640,8 +644,8 @@ void blarg_helicopter_update(HMob49 *moby) { route = data->alternate ? &data->route_b : &data->route_a; qcopy(moby->position, route->path->points); route->index = 1; - moby->previous_state = 2; - moby->state = 4; + moby->previous_state = BLARG_HELICOPTER_PATROL_AND_ATTACK; + moby->state = BLARG_HELICOPTER_TIMED_REACTION; data->reaction_timer = scale_game_frames(15); break; } From 879d11eeb4af339cbc7a7fcbe6b532a81c47f6bb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:31:14 +0000 Subject: [PATCH 1124/1502] decomp: clarify names in sand_shark_update domain_10_value_5 -> SAND_SHARK_APPROACH_TARGET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4484). Reuse the existing local enum member: case 5 steers and walks toward target +0x1d0 at 0x002d49cc-0x002d4a88. This is not the hero state or camera/walk mode domain. domain_11_value_15 -> SAND_SHARK_FACE_TARGET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d45c8). Reuse the existing local enum member: case 15 rotates toward target without the walking update at 0x002d4668-0x002d46bc. This is not the hero state or camera/walk mode domain. domain_12_value_6 -> SAND_SHARK_CLOSE_RANGE_ATTACK: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4618). Reuse the existing local enum member: case 6 faces the close target and performs the animation-window attack at 0x002d4bec-0x002d4cc0. This is not the hero state or camera/walk mode domain. domain_13_value_5 -> SAND_SHARK_APPROACH_TARGET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d464c). Reuse the existing local enum member: case 5 steers and walks toward target +0x1d0 at 0x002d49cc-0x002d4a88. This is not the hero state or camera/walk mode domain. domain_14_value_18 -> SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4be8). Reuse the existing local enum member: cases 17/18 approach ground clamped to home.z and dispatch 18 to offset return state 23 at 0x002d474c-0x002d4808. This is not the hero state or camera/walk mode domain. domain_15_value_6 -> SAND_SHARK_CLOSE_RANGE_ATTACK: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d46fc). Reuse the existing local enum member: case 6 faces the close target and performs the animation-window attack at 0x002d4bec-0x002d4cc0. This is not the hero state or camera/walk mode domain. domain_16_value_5 -> SAND_SHARK_APPROACH_TARGET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4730). Reuse the existing local enum member: case 5 steers and walks toward target +0x1d0 at 0x002d49cc-0x002d4a88. This is not the hero state or camera/walk mode domain. domain_17_value_18 -> SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4be8). Reuse the existing local enum member: cases 17/18 approach ground clamped to home.z and dispatch 18 to offset return state 23 at 0x002d474c-0x002d4808. This is not the hero state or camera/walk mode domain. domain_18_value_17 -> SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this comparison uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d47f8). Reuse the existing local enum member: cases 17/18 approach ground clamped to home.z and dispatch 17 to offset approach state 22 at 0x002d474c-0x002d4808. This is not the hero state or camera/walk mode domain. domain_19_value_22 -> SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4804). Reuse the existing local enum member: state 22 shares target walking with 5 while temporarily adding/restoring height at 0x002d4994-0x002d4ab0. This is not the hero state or camera/walk mode domain. domain_1_value_12 -> SAND_SHARK_WAIT_FOR_HERO_LAUNCH_TRIGGER: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4098). Reuse the existing local enum member: case 12 tests hero position in launch volumes and initializes velocity at 0x002d5194-0x002d52d4. This is not the hero state or camera/walk mode domain. domain_20_value_23 -> SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4808). Reuse the existing local enum member: state 23 shares home walking with 7 while temporarily adding/restoring height at 0x002d4d90-0x002d4e98. This is not the hero state or camera/walk mode domain. domain_21_value_19 -> SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET: Bound C and original retail Ghidra agree this comparison uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d48b8). Reuse the existing local enum member: ground convergence dispatch selects approach state 5 for state 19 at 0x002d4848-0x002d48dc. This is not the hero state or camera/walk mode domain. domain_22_value_5 -> SAND_SHARK_APPROACH_TARGET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d48c8). Reuse the existing local enum member: case 5 steers and walks toward target +0x1d0 at 0x002d49cc-0x002d4a88. This is not the hero state or camera/walk mode domain. domain_23_value_20 -> SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME: Bound C and original retail Ghidra agree this comparison uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d48cc). Reuse the existing local enum member: ground convergence dispatch selects return state 7 for state 20 at 0x002d4848-0x002d48dc. This is not the hero state or camera/walk mode domain. domain_24_value_7 -> SAND_SHARK_RETURN_HOME: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d48d0). Reuse the existing local enum member: case 7 walks toward home +0x220 and tests arrival at 0x002d4dc4-0x002d4ec8. This is not the hero state or camera/walk mode domain. domain_25_value_14 -> SAND_SHARK_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4934). Reuse the existing local enum member: case 14 walks toward target and checks path output proximity at 0x002d44a0-0x002d45a4. This is not the hero state or camera/walk mode domain. domain_26_value_22 -> SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this comparison uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4984). Reuse the existing local enum member: state 22 shares target walking with 5 while temporarily adding/restoring height at 0x002d4994-0x002d4ab0. This is not the hero state or camera/walk mode domain. domain_27_value_22 -> SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this comparison uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4a94). Reuse the existing local enum member: state 22 shares target walking with 5 while temporarily adding/restoring height at 0x002d4994-0x002d4ab0. This is not the hero state or camera/walk mode domain. domain_28_value_7 -> SAND_SHARK_RETURN_HOME: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4bcc). Reuse the existing local enum member: case 7 walks toward home +0x220 and tests arrival at 0x002d4dc4-0x002d4ec8. This is not the hero state or camera/walk mode domain. domain_29_value_22 -> SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this comparison uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4b14). Reuse the existing local enum member: state 22 shares target walking with 5 while temporarily adding/restoring height at 0x002d4994-0x002d4ab0. This is not the hero state or camera/walk mode domain. domain_2_value_3 -> SAND_SHARK_WAIT_FOR_TARGET_IN_VOLUME: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d40e8). Reuse the existing local enum member: case 3 waits on target membership in volume +0x278 at 0x002d4458-0x002d4484. This is not the hero state or camera/walk mode domain. domain_30_value_19 -> SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4b28). Reuse the existing local enum member: ground convergence dispatch selects approach state 5 for state 19 at 0x002d4848-0x002d48dc. This is not the hero state or camera/walk mode domain. domain_31_value_5 -> SAND_SHARK_APPROACH_TARGET: Bound C and original retail Ghidra agree this comparison uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4b84). Reuse the existing local enum member: case 5 steers and walks toward target +0x1d0 at 0x002d49cc-0x002d4a88. This is not the hero state or camera/walk mode domain. domain_32_value_6 -> SAND_SHARK_CLOSE_RANGE_ATTACK: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4ba0). Reuse the existing local enum member: case 6 faces the close target and performs the animation-window attack at 0x002d4bec-0x002d4cc0. This is not the hero state or camera/walk mode domain. domain_33_value_7 -> SAND_SHARK_RETURN_HOME: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4bcc). Reuse the existing local enum member: case 7 walks toward home +0x220 and tests arrival at 0x002d4dc4-0x002d4ec8. This is not the hero state or camera/walk mode domain. domain_34_value_14 -> SAND_SHARK_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4bdc). Reuse the existing local enum member: case 14 walks toward target and checks path output proximity at 0x002d44a0-0x002d45a4. This is not the hero state or camera/walk mode domain. domain_35_value_18 -> SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4be8). Reuse the existing local enum member: cases 17/18 approach ground clamped to home.z and dispatch 18 to offset return state 23 at 0x002d474c-0x002d4808. This is not the hero state or camera/walk mode domain. domain_36_value_5 -> SAND_SHARK_APPROACH_TARGET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4d00). Reuse the existing local enum member: case 5 steers and walks toward target +0x1d0 at 0x002d49cc-0x002d4a88. This is not the hero state or camera/walk mode domain. domain_37_value_23 -> SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this comparison uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4d80). Reuse the existing local enum member: state 23 shares home walking with 7 while temporarily adding/restoring height at 0x002d4d90-0x002d4e98. This is not the hero state or camera/walk mode domain. domain_38_value_23 -> SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this comparison uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4e7c). Reuse the existing local enum member: state 23 shares home walking with 7 while temporarily adding/restoring height at 0x002d4d90-0x002d4e98. This is not the hero state or camera/walk mode domain. domain_39_value_7 -> SAND_SHARK_RETURN_HOME: Bound C and original retail Ghidra agree this comparison uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4ec4). Reuse the existing local enum member: case 7 walks toward home +0x220 and tests arrival at 0x002d4dc4-0x002d4ec8. This is not the hero state or camera/walk mode domain. domain_3_value_29 -> SAND_SHARK_WAIT_FOR_LINKED_MOBY_BEFORE_INITIALIZE: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4120). Reuse the existing local enum member: state 29 waits on linked moby state and then initializes at 0x002d4160-0x002d41c4. This is not the hero state or camera/walk mode domain. domain_40_value_3 -> SAND_SHARK_WAIT_FOR_TARGET_IN_VOLUME: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4ee8). Reuse the existing local enum member: case 3 waits on target membership in volume +0x278 at 0x002d4458-0x002d4484. This is not the hero state or camera/walk mode domain. domain_41_value_18 -> SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4f10). Reuse the existing local enum member: cases 17/18 approach ground clamped to home.z and dispatch 18 to offset return state 23 at 0x002d474c-0x002d4808. This is not the hero state or camera/walk mode domain. domain_42_value_2 -> SAND_SHARK_WANDER_AROUND_HOME: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4f5c). Reuse the existing local enum member: case 2 steers around home and randomizes turn offset at 0x002d4214-0x002d4300. This is not the hero state or camera/walk mode domain. domain_43_value_5 -> SAND_SHARK_APPROACH_TARGET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4fe8). Reuse the existing local enum member: case 5 steers and walks toward target +0x1d0 at 0x002d49cc-0x002d4a88. This is not the hero state or camera/walk mode domain. domain_44_value_7 -> SAND_SHARK_RETURN_HOME: Bound C and original retail Ghidra agree this comparison uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d5020). Reuse the existing local enum member: case 7 walks toward home +0x220 and tests arrival at 0x002d4dc4-0x002d4ec8. This is not the hero state or camera/walk mode domain. domain_45_value_5 -> SAND_SHARK_APPROACH_TARGET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d502c). Reuse the existing local enum member: case 5 steers and walks toward target +0x1d0 at 0x002d49cc-0x002d4a88. This is not the hero state or camera/walk mode domain. domain_46_value_22 -> SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d5030). Reuse the existing local enum member: state 22 shares target walking with 5 while temporarily adding/restoring height at 0x002d4994-0x002d4ab0. This is not the hero state or camera/walk mode domain. domain_47_value_21 -> SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d5090). Reuse the existing local enum member: ground convergence for state 21 sets path threshold and enters state 14 at 0x002d4904-0x002d4934. This is not the hero state or camera/walk mode domain. domain_49_value_1 -> SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d5188). Reuse the existing local enum member: case 1 enters ground alignment state 18 at 0x002d41e8-0x002d41f4, leading to offset return home. This is not the hero state or camera/walk mode domain. domain_4_value_1 -> SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4144). Reuse the existing local enum member: case 1 enters ground alignment state 18 at 0x002d41e8-0x002d41f4, leading to offset return home. This is not the hero state or camera/walk mode domain. domain_50_value_13 -> SAND_SHARK_BALLISTIC_FLIGHT: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d52d4). Reuse the existing local enum member: case 13 adds velocity to position and applies gravity at 0x002d5390-0x002d53d0. This is not the hero state or camera/walk mode domain. domain_51_value_23 -> SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d540c). Reuse the existing local enum member: state 23 shares home walking with 7 while temporarily adding/restoring height at 0x002d4d90-0x002d4e98. This is not the hero state or camera/walk mode domain. domain_52_value_26 -> SAND_SHARK_INACTIVE_WAIT_FOR_RELAUNCH: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d5500). Reuse the existing local enum member: state 26 refreshes group relaunch reference or removes moby at 0x002d55f4-0x002d5608. This is not the hero state or camera/walk mode domain. domain_53_value_26 -> SAND_SHARK_INACTIVE_WAIT_FOR_RELAUNCH: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d55b8). Reuse the existing local enum member: state 26 refreshes group relaunch reference or removes moby at 0x002d55f4-0x002d5608. This is not the hero state or camera/walk mode domain. domain_6_value_0 -> SAND_SHARK_INITIALIZE: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d41c4). Reuse the existing local enum member: case 0 captures home and initializes walking at 0x002d3fbc-0x002d4044. This is not the hero state or camera/walk mode domain. domain_7_value_18 -> SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d41f4). Reuse the existing local enum member: cases 17/18 approach ground clamped to home.z and dispatch 18 to offset return state 23 at 0x002d474c-0x002d4808. This is not the hero state or camera/walk mode domain. domain_8_value_17 -> SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_HEIGHT_OFFSET: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d4440). Reuse the existing local enum member: cases 17/18 approach ground clamped to home.z and dispatch 17 to offset approach state 22 at 0x002d474c-0x002d4808. This is not the hero state or camera/walk mode domain. domain_9_value_21 -> SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK: Bound C and original retail Ghidra agree this assignment uses the same sand-shark moby state byte +0x20 as the dispatch at 0x002d3f10-0x002d3f38 (occurrence near 0x002d5090). Reuse the existing local enum member: ground convergence for state 21 sets path threshold and enters state 14 at 0x002d4904-0x002d4934. This is not the hero state or camera/walk mode domain. --- src/overlays/l02/mobys/sand_shark.c | 102 ++++++++++++++-------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/src/overlays/l02/mobys/sand_shark.c b/src/overlays/l02/mobys/sand_shark.c index 960d04d35b..b331ccb7c1 100644 --- a/src/overlays/l02/mobys/sand_shark.c +++ b/src/overlays/l02/mobys/sand_shark.c @@ -350,7 +350,7 @@ void sand_shark_update(struct Moby *moby) { mark_moby_for_removal(moby); return; } - moby->state = 0xC; + moby->state = SAND_SHARK_WAIT_FOR_HERO_LAUNCH_TRIGGER; moby->collision = 0; moby->pos.z += 10.0f; moby->flags = (moby->flags | 1) & ~0x1000; @@ -359,16 +359,16 @@ void sand_shark_update(struct Moby *moby) { } } else if (sand_shark_behavior_vars->unk278 >= 0) { sand_shark_behavior_vars->walk_18C = 0.2f; - moby->state = 3; + moby->state = SAND_SHARK_WAIT_FOR_TARGET_IN_VOLUME; if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(3)); } } else if (sand_shark_behavior_vars->unk258 >= 0) { - moby->state = 0x1D; + moby->state = SAND_SHARK_WAIT_FOR_LINKED_MOBY_BEFORE_INITIALIZE; moby->collision = 0; moby->flags = (moby->flags | 0x41) & ~0x1000; } else { - moby->state = 1; + moby->state = SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET; if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(3)); } @@ -383,13 +383,13 @@ void sand_shark_update(struct Moby *moby) { moby->collision = moby->pclass->collision; sand_shark_behavior_vars->unk258 = -1; sand_shark_behavior_vars->unk25C = scale_game_frames(0x1518); - moby->state = 0; + moby->state = SAND_SHARK_INITIALIZE; moby->pos.z -= sand_shark_height_offset_gp; } break; case SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET: fast_vec_sub(&position_or_offset_scratch, &hero.motion.pos, &moby->pos); - moby->state = 0x12; + moby->state = SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(3)); } @@ -438,13 +438,13 @@ void sand_shark_update(struct Moby *moby) { sand_shark_behavior_vars->turn_timer = scale_game_frames((int)random_float_between(30.0f, 90.0f)); sand_shark_behavior_vars->walk_step = D_0015ED6C * 4.0f; - moby->state = 0x11; + moby->state = SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_HEIGHT_OFFSET; if (moby->prev_seq != 0xC) { blend_moby_animation(moby, 0xC, 0, scale_game_frames(3)); } } } else if (sand_shark_behavior_vars->unk25E != 0 && random_integer_below(0x13) == 0) { - moby->state = 0x15; + moby->state = SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK; allocate_voice_for_target_entry(4, 0, moby); if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 0); @@ -456,7 +456,7 @@ void sand_shark_update(struct Moby *moby) { if (sand_shark_behavior_vars->unk214 != 2 && is_point_inside_clip_volume(&sand_shark_behavior_vars->target, sand_shark_behavior_vars->unk278)) { - moby->state = 5; + moby->state = SAND_SHARK_APPROACH_TARGET; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(3)); } @@ -493,23 +493,23 @@ void sand_shark_update(struct Moby *moby) { } if (sand_shark_behavior_vars->unk25E != 0) { if (hit14) { - moby->state = 0xF; + moby->state = SAND_SHARK_FACE_TARGET; if (moby->prev_seq != 5) { blend_moby_animation(moby, 5, 0, scale_game_frames(0xA)); } } else if (vector_distance_xy(&moby->pos, &target_or_particle_vector) < 1.5f) { - moby->state = 6; + moby->state = SAND_SHARK_CLOSE_RANGE_ATTACK; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(0xA)); } } else if (sand_shark_behavior_vars->unk214 != 2) { - moby->state = 5; + moby->state = SAND_SHARK_APPROACH_TARGET; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(0xF)); } } } else { - moby->state = 0x12; + moby->state = SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET; } break; } @@ -523,18 +523,18 @@ void sand_shark_update(struct Moby *moby) { D_0015ED6C * 6.2831855f); if (sand_shark_behavior_vars->unk25E != 0) { if (vector_distance_xy(&moby->pos, &sand_shark_behavior_vars->target) < 1.5f) { - moby->state = 6; + moby->state = SAND_SHARK_CLOSE_RANGE_ATTACK; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(0xA)); } } else if (sand_shark_behavior_vars->unk214 != 2) { - moby->state = 5; + moby->state = SAND_SHARK_APPROACH_TARGET; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(0xF)); } } } else { - moby->state = 0x12; + moby->state = SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET; } break; case SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_HEIGHT_OFFSET: @@ -552,10 +552,10 @@ void sand_shark_update(struct Moby *moby) { if (moby->prev_seq != 0xC) { blend_moby_animation(moby, 0xC, 0, scale_game_frames(5)); } - if (moby->state == 0x11) { - moby->state = 0x16; + if (moby->state == SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_HEIGHT_OFFSET) { + moby->state = SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET; } else { - moby->state = 0x17; + moby->state = SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET; } } moby->pos.z -= sand_shark_height_offset_gp; @@ -574,20 +574,20 @@ void sand_shark_update(struct Moby *moby) { position_or_offset_scratch.f[2] = g; if (approach_value(&moby->pos.z, g + sand_shark_height_offset_gp, D_0015ED6C * 4.0f) == 0.0f) { - if (moby->state == 0x13) { - moby->state = 5; + if (moby->state == SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET) { + moby->state = SAND_SHARK_APPROACH_TARGET; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(3)); } - } else if (moby->state == 0x14) { - moby->state = 7; + } else if (moby->state == SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME) { + moby->state = SAND_SHARK_RETURN_HOME; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(3)); } } else { sand_shark_behavior_vars->unk294 = random_float_between(2.0f, 3.5f); sand_shark_behavior_vars->walk_step = D_0015ED6C * 4.0f; - moby->state = 0xE; + moby->state = SAND_SHARK_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(3)); } @@ -599,7 +599,7 @@ void sand_shark_update(struct Moby *moby) { } case SAND_SHARK_APPROACH_TARGET: case SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET: - if (moby->state == 0x16) { + if (moby->state == SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET) { moby->pos.z += sand_shark_height_offset_gp; if (random_integer_below(0xFF) & 1) { particle_position_or_forward_step.q = *(OvlQuad *)&moby->pos; @@ -625,39 +625,39 @@ void sand_shark_update(struct Moby *moby) { &target_or_particle_vector, 1.0f); FUN_L02_002d63c0_e50(moby); - if (moby->state == 0x16) { + if (moby->state == SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET) { moby->pos.z -= sand_shark_height_offset_gp; } if (sand_shark_behavior_vars->unk214 != 2) { if (sand_shark_behavior_vars->unk278 >= 0 && !is_point_inside_clip_volume(&sand_shark_behavior_vars->target, sand_shark_behavior_vars->unk278)) { - moby->state = 7; + moby->state = SAND_SHARK_RETURN_HOME; } else { fast_vec_sub(&target_home_delta, &sand_shark_behavior_vars->target, &sand_shark_behavior_vars->home); if (vector_distance_xy(&moby->pos, &navigation_point) < 12.0f && - moby->state == 0x16) { - moby->state = 0x13; + moby->state == SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET) { + moby->state = SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET; allocate_voice_for_target_entry(4, 0, moby); if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(3)); } } else if (vector_distance_xy(&moby->pos, &navigation_point) < 1.5f && - moby->state == 5) { - moby->state = 6; + moby->state == SAND_SHARK_APPROACH_TARGET) { + moby->state = SAND_SHARK_CLOSE_RANGE_ATTACK; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(3)); } } } } else if (sand_shark_behavior_vars->unk278 >= 0) { - moby->state = 7; + moby->state = SAND_SHARK_RETURN_HOME; } else if (sand_shark_behavior_vars->unk25E != 0) { - moby->state = 0xE; + moby->state = SAND_SHARK_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK; } else { - moby->state = 0x12; + moby->state = SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET; } break; case SAND_SHARK_CLOSE_RANGE_ATTACK: @@ -676,7 +676,7 @@ void sand_shark_update(struct Moby *moby) { } if ((moby->anim_flags & 2) && vector_distance_xy(&moby->pos, &sand_shark_behavior_vars->target) > 1.5f) { - moby->state = 5; + moby->state = SAND_SHARK_APPROACH_TARGET; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(3)); } @@ -693,7 +693,7 @@ void sand_shark_update(struct Moby *moby) { break; case SAND_SHARK_RETURN_HOME: case SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET: - if (moby->state == 0x17) { + if (moby->state == SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET) { moby->pos.z += sand_shark_height_offset_gp; if (random_integer_below(0xFF) & 1) { particle_position_or_forward_step.q = *(OvlQuad *)&moby->pos; @@ -717,26 +717,26 @@ void sand_shark_update(struct Moby *moby) { &position_or_offset_scratch, &target_or_particle_vector, 1.0f); - if (moby->state == 0x17) { + if (moby->state == SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET) { moby->pos.z -= sand_shark_height_offset_gp; } if (vector_distance_xy(&moby->pos, &sand_shark_behavior_vars->home) < 0.5f) { sand_shark_behavior_vars->unk298 = 0; - if (moby->state == 7) { + if (moby->state == SAND_SHARK_RETURN_HOME) { if (sand_shark_behavior_vars->unk278 >= 0) { - moby->state = 3; + moby->state = SAND_SHARK_WAIT_FOR_TARGET_IN_VOLUME; if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(3)); } } else { - moby->state = 0x12; + moby->state = SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET; sand_shark_behavior_vars->walk_step = D_0015ED6C * 1.5f; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(3)); } } } else { - moby->state = 2; + moby->state = SAND_SHARK_WANDER_AROUND_HOME; sand_shark_behavior_vars->walk_step = D_0015ED6C * 1.5f; if (moby->prev_seq != 0xC) { blend_moby_animation(moby, 0xC, 0, scale_game_frames(5)); @@ -751,15 +751,15 @@ void sand_shark_update(struct Moby *moby) { if (sand_shark_behavior_vars->unk278 >= 0) { if (is_point_inside_clip_volume(&sand_shark_behavior_vars->target, sand_shark_behavior_vars->unk278)) { - moby->state = 5; + moby->state = SAND_SHARK_APPROACH_TARGET; sand_shark_behavior_vars->walk_step = sand_shark_behavior_vars->unk254 * D_0015ED6C; } } else if (fast_vec_length(&target_home_delta) < sand_shark_behavior_vars->unk24C) { - if (moby->state == 7) { - moby->state = 5; + if (moby->state == SAND_SHARK_RETURN_HOME) { + moby->state = SAND_SHARK_APPROACH_TARGET; } else { - moby->state = 0x16; + moby->state = SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET; } sand_shark_behavior_vars->walk_step = sand_shark_behavior_vars->unk254 * D_0015ED6C; @@ -768,7 +768,7 @@ void sand_shark_update(struct Moby *moby) { } } } else if (sand_shark_behavior_vars->unk25E != 0 && random_integer_below(0x13) == 0) { - moby->state = 0x15; + moby->state = SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK; allocate_voice_for_target_entry(4, 0, moby); if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 0); @@ -798,7 +798,7 @@ void sand_shark_update(struct Moby *moby) { break; case SAND_SHARK_SUCK_CANNON_INTERACTION: if (FUN_L00_002dc9f0_e50(moby, sand_shark_behavior_vars->unk120)) { - moby->state = 1; + moby->state = SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET; sand_shark_behavior_vars->unkC8 = 0; } break; @@ -831,7 +831,7 @@ void sand_shark_update(struct Moby *moby) { if (moby->prev_seq != 0xB) { blend_moby_animation(moby, 0xB, 0, 0); } - moby->state = 0xD; + moby->state = SAND_SHARK_BALLISTIC_FLIGHT; } break; } @@ -862,7 +862,7 @@ void sand_shark_update(struct Moby *moby) { moby->collision = moby->pclass->collision; moby->flags |= 0x1000; moby->pos.z = sand_shark_behavior_vars->home.f[2] - sink; - moby->state = 0x17; + moby->state = SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET; moby->rot.y = 0.0f; if (moby->prev_seq != 0xC) { blend_moby_animation(moby, 0xC, 0, scale_game_frames(1)); @@ -885,7 +885,7 @@ void sand_shark_update(struct Moby *moby) { sand_shark_behavior_vars->unk27C = select_group_class_29c_moby(moby); if (sand_shark_behavior_vars->unk27C != 0) { emit_sand_shark_dust_burst(moby); - moby->state = 0x1A; + moby->state = SAND_SHARK_INACTIVE_WAIT_FOR_RELAUNCH; moby->anim_speed = 0.0f; qcopy(&moby->pos, &sand_shark_behavior_vars->home); moby->collision = 0; @@ -911,7 +911,7 @@ void sand_shark_update(struct Moby *moby) { if (sand_shark_behavior_vars->unk27C != 0) { emit_sand_shark_dust_burst(moby); moby->alpha = 0x80; - moby->state = 0x1A; + moby->state = SAND_SHARK_INACTIVE_WAIT_FOR_RELAUNCH; qcopy(&moby->pos, &sand_shark_behavior_vars->home); moby->collision = 0; moby->pos.z -= 10.0f; From adceece3c2f34d1837b44b29519d38d76d3e75bb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:31:15 +0000 Subject: [PATCH 1125/1502] decomp: clarify names in birdbot_update domain_0_value_0 -> BIRDBOT_STATE_INITIALIZE: Retail 0x002e6ca0-0x002e6cb0 reads moby+0x20 and skips path selection when zero; the same byte selects the initialization branch at 0x002e70ec-0x002e7114, named BIRDBOT_STATE_INITIALIZE in the bound C. domain_10_value_1 -> BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION: Cuboid deployment arrival test at 0x002e7a1c-0x002e7ad8 joins the state-1 write at 0x002e85e8-0x002e85ec. This writes the same moby+0x20 byte used by the existing BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION dispatch. domain_11_value_1 -> BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION: Ground-descent deployment tests the remaining step at 0x002e7ab8-0x002e7ad8 then joins the state-1 write at 0x002e85e8-0x002e85ec. The same moby state byte selects the existing tracking and action-selection case. domain_12_value_1 -> BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION: Blocked muzzle collision at 0x002e7c38-0x002e7c44 branches to 0x002e8074; idle blending precedes writing 1 to moby+0x20 at 0x002e809c-0x002e80a0. That byte selects existing BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION. domain_13_value_7 -> BIRDBOT_STATE_RECOVER_FROM_BURST: Burst termination after shot count/range checks blends recovery animation at 0x002e7cc8-0x002e7d5c; 0x002e7d6c loads 7, stored to moby+0x20 at 0x002e7eec. Same state byte selects existing BIRDBOT_STATE_RECOVER_FROM_BURST at 0x002e7d70. domain_14_value_9 -> BIRDBOT_STATE_BEGIN_PATH_MOVEMENT: Recovery commits selected node at 0x002e7eb8 and path-entry animation rate at 0x002e7ee4-0x002e7ef4 while writing 9 to moby+0x20. The same byte selects existing BIRDBOT_STATE_BEGIN_PATH_MOVEMENT and its speed reset. domain_15_value_6 -> BIRDBOT_STATE_FIRE_BURST: Recovery's clear muzzle test resets shot count at 0x002e8014-0x002e802c and writes 6 to moby+0x20 at 0x002e8030. This is the same state byte selecting existing BIRDBOT_STATE_FIRE_BURST and projectile emission. domain_16_value_1 -> BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION: Recovery fallback blends idle then stores 1 to moby+0x20 at 0x002e8074-0x002e80a0. State dispatch reads this same byte, whose existing case 1 tracks selected target heading and chooses firing or path movement. domain_17_value_10 -> BIRDBOT_STATE_MOVE_TO_PATH_NODE: Existing BEGIN_PATH_MOVEMENT clears speed and turn spring at 0x002e80bc-0x002e80c0 and stores 10 to moby+0x20 at 0x002e80c8. The same state selector enters existing BIRDBOT_STATE_MOVE_TO_PATH_NODE at 0x002e80d4. domain_18_value_11 -> BIRDBOT_STATE_BRAKE_AND_FACE_TARGET: Arrival within 0.25 of main path node is checked at 0x002e8324-0x002e836c, then 11 is stored to moby+0x20 at 0x002e8378. The same state byte selects existing BIRDBOT_STATE_BRAKE_AND_FACE_TARGET at 0x002e837c. domain_19_value_1 -> BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION: Brake/facing animation completion is checked at 0x002e85a0-0x002e85b8, then idle blend and state-1 write follow at 0x002e85c0-0x002e85ec. This same moby state byte selects existing target tracking/action selection. domain_1_value_1 -> BIRDBOT_HIT_REACTION_FATAL_KNOCKBACK: At 0x002e6d08-0x002e6d10 the helper return is saved in s0, the switch(kind) selector. Health minus damage <=0 forces s0=1 at 0x002e6db4-0x002e6dd4, selecting the existing fatal-hit-reaction branch rather than the separate moby state domain. domain_20_value_9 -> BIRDBOT_STATE_BEGIN_PATH_MOVEMENT: Nonfatal knockback recovery commits selected node at 0x002e8684 and stores 9 to moby+0x20 at 0x002e8688. Existing state dispatch for that byte enters BIRDBOT_STATE_BEGIN_PATH_MOVEMENT to reset speed and turn spring. domain_21_value_1 -> BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION: Nonfatal recovery with no path travel needed blends idle and writes 1 to moby+0x20 at 0x002e8694-0x002e86c0. The same state byte dispatches existing BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION. domain_22_value_1 -> BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION: Common ground handling reads moby+0x20 at 0x002e89bc and compares it with 1 at 0x002e89b8-0x002e89c0. That exact byte is the earlier state switch selector; existing case 1 is BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION. domain_24_value_6 -> BIRDBOT_STATE_FIRE_BURST: Common ground handling compares the moby+0x20 state byte with 6 at 0x002e89cc-0x002e89d0. This is the same selector as the existing BIRDBOT_STATE_FIRE_BURST case, which spawns projectiles at 0x002e7c98. domain_25_value_7 -> BIRDBOT_STATE_RECOVER_FROM_BURST: Common ground handling compares the moby+0x20 state byte with 7 at 0x002e89d4-0x002e89d8. This is the same selector as existing BIRDBOT_STATE_RECOVER_FROM_BURST, entered on burst termination at 0x002e7d6c/0x002e7eec. domain_26_value_11 -> BIRDBOT_STATE_BRAKE_AND_FACE_TARGET: Common ground handling compares moby+0x20 with 11 at 0x002e89dc-0x002e89e0. The same state byte is assigned on node arrival at 0x002e8378 and selects existing BIRDBOT_STATE_BRAKE_AND_FACE_TARGET. domain_2_value_14 -> BIRDBOT_STATE_FATAL_KNOCKBACK: Retail 0x002e6ec4-0x002e6ed0 writes 14 to moby+0x20 after lethal knockback setup. This same byte is the state switch selector; its existing BIRDBOT_STATE_FATAL_KNOCKBACK branch steps motion then explodes and removes the moby at 0x002e87b8-0x002e899c. domain_3_value_12 -> BIRDBOT_STATE_NONFATAL_KNOCKBACK: Retail 0x002e6fe0-0x002e6fe8 writes 12 to moby+0x20 after nonfatal knockback setup and animation blend. The same byte dispatches the existing BIRDBOT_STATE_NONFATAL_KNOCKBACK branch, which recovers on motion bit 0x40 at 0x002e8604-0x002e86c0. domain_4_value_12 -> BIRDBOT_STATE_NONFATAL_KNOCKBACK: Retail 0x002e70ac-0x002e70b4 writes 12 to moby+0x20 after the low-speed nonfatal reaction. The state dispatch reads that byte at 0x002e70ec; existing state 12 updates motion and permits recovery at 0x002e8604-0x002e86c0. domain_5_value_2 -> BIRDBOT_STATE_WAIT_FOR_TRIGGER: Initialization writes 2 to moby+0x20 at 0x002e7350-0x002e7358. The same byte dispatches existing BIRDBOT_STATE_WAIT_FOR_TRIGGER: distance, clip volume or external activation gates deployment at 0x002e766c-0x002e7750. domain_6_value_6 -> BIRDBOT_STATE_FIRE_BURST: Retail 0x002e74d4-0x002e74ec writes 6 to moby+0x20 after clear muzzle collision and shot-counter reset. The same state selector enters existing BIRDBOT_STATE_FIRE_BURST, which emits projectiles on animation-frame crossing at 0x002e7aec-0x002e7ca8. domain_7_value_9 -> BIRDBOT_STATE_BEGIN_PATH_MOVEMENT: Retail 0x002e7618-0x002e7628 commits the selected main path index and writes 9 to moby+0x20. The same byte selects existing BIRDBOT_STATE_BEGIN_PATH_MOVEMENT at 0x002e80a4-0x002e80c8, resetting movement speed and turn spring before state 10. domain_8_value_3 -> BIRDBOT_STATE_DEPLOY: Trigger handling restores motion flags and writes 3 to moby+0x20 at 0x002e7708-0x002e7750. The same byte dispatches existing BIRDBOT_STATE_DEPLOY, following the side path, approaching a cuboid or descending to ground at 0x002e7754-0x002e7ae8. domain_9_value_1 -> BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION: Side-path deployment completes when its cursor is the final node at 0x002e77f8-0x002e7804 and joins the state-1 write at 0x002e85e8-0x002e85ec. The same moby+0x20 byte selects existing target tracking/action selection at 0x002e735c-0x002e7628. --- src/overlays/l01/mobys/birdbot.c | 48 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/overlays/l01/mobys/birdbot.c b/src/overlays/l01/mobys/birdbot.c index 407f839820..c09b38bde5 100644 --- a/src/overlays/l01/mobys/birdbot.c +++ b/src/overlays/l01/mobys/birdbot.c @@ -546,7 +546,7 @@ void birdbot_update(PeMoby *birdbot_moby) { if (birdbot_vars->w1C8 > 0) { birdbot_vars->w1C8--; } - if (birdbot_moby->state != 0) { + if (birdbot_moby->state != BIRDBOT_STATE_INITIALIZE) { path_reposition_requested = select_birdbot_path_node(birdbot_moby, &idx); } target_search_radius = flag ? birdbot_vars->f1A0 * 2.0f : birdbot_vars->f1A0; @@ -574,7 +574,7 @@ void birdbot_update(PeMoby *birdbot_moby) { birdbot_vars->h1E2 = scale_game_frames(0x258); birdbot_vars->f20 -= dmg; if (birdbot_vars->f20 <= 0.0f) { - kind = 1; + kind = BIRDBOT_HIT_REACTION_FATAL_KNOCKBACK; } switch (kind) { case BIRDBOT_HIT_REACTION_KEEP_CURRENT_STATE: @@ -600,7 +600,7 @@ void birdbot_update(PeMoby *birdbot_moby) { FUN_L00_0025c558_u( knockback_heading, birdbot_moby, birdbot_vars->x70, 9, scale_game_frames(2), 0); birdbot_vars->b67 = 0xB4; - birdbot_moby->state = 0xE; + birdbot_moby->state = BIRDBOT_STATE_FATAL_KNOCKBACK; birdbot_moby->h34 &= 0xEFFF; trooper_anim_update(birdbot_moby, (short *)birdbot_vars->x60); birdbot_vars->h26 = scale_game_frames(0x3C); @@ -623,7 +623,7 @@ void birdbot_update(PeMoby *birdbot_moby) { if (birdbot_moby->b53 != 0xB) { blend_moby_animation(birdbot_moby, 0xB, 0, scale_game_frames(6)); } - birdbot_moby->state = 0xC; + birdbot_moby->state = BIRDBOT_STATE_NONFATAL_KNOCKBACK; trooper_anim_update(birdbot_moby, (short *)birdbot_vars->x60); break; case BIRDBOT_HIT_REACTION_LOW_SPEED_NONFATAL_KNOCKBACK: @@ -640,7 +640,7 @@ void birdbot_update(PeMoby *birdbot_moby) { *(u128 *)&va = *(u128 *)&hit->pos; trooper_knockback_arc(&va, &knockback_heading, &birdbot_vars->f88, &birdbot_vars->f8C); FUN_L00_0025c558_u(knockback_heading, birdbot_moby, birdbot_vars->x70, 0xE, 6, 0); - birdbot_moby->state = 0xC; + birdbot_moby->state = BIRDBOT_STATE_NONFATAL_KNOCKBACK; trooper_anim_update(birdbot_moby, (short *)birdbot_vars->x60); break; } @@ -712,7 +712,7 @@ void birdbot_update(PeMoby *birdbot_moby) { birdbot_moby->w94 = 0; birdbot_moby->h34 |= 0x41; } - birdbot_moby->state = 2; + birdbot_moby->state = BIRDBOT_STATE_WAIT_FOR_TRIGGER; break; } case BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION: { @@ -741,7 +741,7 @@ void birdbot_update(PeMoby *birdbot_moby) { if (collision_line(&vb, &va, 0, birdbot_moby, 0) == 0) { birdbot_vars->h1A4 = 0; birdbot_vars->f198 = 4.0f; - birdbot_moby->state = 6; + birdbot_moby->state = BIRDBOT_STATE_FIRE_BURST; if (birdbot_moby->b53 != 4) { blend_moby_animation(birdbot_moby, 4, 0, scale_game_frames(6)); } @@ -766,7 +766,7 @@ void birdbot_update(PeMoby *birdbot_moby) { f = *(float *)&birdbot_path_entry_animation_speed_gp; c->idx = i; birdbot_moby->f58 = f; - birdbot_moby->state = 9; + birdbot_moby->state = BIRDBOT_STATE_BEGIN_PATH_MOVEMENT; } } } @@ -796,7 +796,7 @@ void birdbot_update(PeMoby *birdbot_moby) { if (birdbot_moby->b53 != 8) { blend_moby_animation(birdbot_moby, 8, 0, scale_game_frames(10)); } - birdbot_moby->state = 3; + birdbot_moby->state = BIRDBOT_STATE_DEPLOY; } break; case BIRDBOT_STATE_DEPLOY: @@ -821,7 +821,7 @@ void birdbot_update(PeMoby *birdbot_moby) { if (birdbot_moby->b53 != 0) { blend_moby_animation(birdbot_moby, 0, 0, scale_game_frames(5)); } - birdbot_moby->state = 1; + birdbot_moby->state = BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION; } else { fast_vec_sub(&va, &vb, &birdbot_moby->pos); fast_vec_normalize(&va, &va, frame_time * 5.0f); @@ -862,7 +862,7 @@ void birdbot_update(PeMoby *birdbot_moby) { if (birdbot_moby->b53 != 0) { blend_moby_animation(birdbot_moby, 0, 0, scale_game_frames(5)); } - birdbot_moby->state = 1; + birdbot_moby->state = BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION; } } else { clear_u64_value(&va); @@ -875,7 +875,7 @@ void birdbot_update(PeMoby *birdbot_moby) { if (birdbot_moby->b53 != 0) { blend_moby_animation(birdbot_moby, 0, 0, scale_game_frames(5)); } - birdbot_moby->state = 1; + birdbot_moby->state = BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION; } } spawn_birdbot_movement_particles((SplashMoby *)birdbot_moby, @@ -918,7 +918,7 @@ void birdbot_update(PeMoby *birdbot_moby) { if (birdbot_moby->b53 != 0) { blend_moby_animation(birdbot_moby, 0, 0, scale_game_frames(5)); } - birdbot_moby->state = 1; + birdbot_moby->state = BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION; break; } } @@ -931,7 +931,7 @@ void birdbot_update(PeMoby *birdbot_moby) { blend_moby_animation(birdbot_moby, 5, 5, scale_game_frames(10)); } birdbot_moby->f58 = 0.5f; - birdbot_moby->state = 7; + birdbot_moby->state = BIRDBOT_STATE_RECOVER_FROM_BURST; } } break; @@ -960,7 +960,7 @@ void birdbot_update(PeMoby *birdbot_moby) { blend_moby_animation(birdbot_moby, 8, 0, scale_game_frames(10)); } birdbot_moby->f58 = *(float *)&birdbot_path_entry_animation_speed_gp; - birdbot_moby->state = 9; + birdbot_moby->state = BIRDBOT_STATE_BEGIN_PATH_MOVEMENT; } else { float d; @@ -981,7 +981,7 @@ void birdbot_update(PeMoby *birdbot_moby) { if (collision_line(&vb, &va, 0, birdbot_moby, 0) == 0) { birdbot_vars->h1A4 = 0; birdbot_vars->f198 = 4.0f; - birdbot_moby->state = 6; + birdbot_moby->state = BIRDBOT_STATE_FIRE_BURST; if (birdbot_moby->b53 != 4) { blend_moby_animation(birdbot_moby, 4, 0, scale_game_frames(6)); } @@ -993,7 +993,7 @@ void birdbot_update(PeMoby *birdbot_moby) { if (birdbot_moby->b53 != 0) { blend_moby_animation(birdbot_moby, 0, 0, scale_game_frames(5)); } - birdbot_moby->state = 1; + birdbot_moby->state = BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION; } } break; @@ -1002,7 +1002,7 @@ void birdbot_update(PeMoby *birdbot_moby) { birdbot_moby->f58 = 1.0f; birdbot_vars->f1B8 = 0.0f; birdbot_vars->f1BC = 0.0f; - birdbot_moby->state = 0xA; + birdbot_moby->state = BIRDBOT_STATE_MOVE_TO_PATH_NODE; spawn_birdbot_movement_particles((SplashMoby *)birdbot_moby, (u128 *)&birdbot_position_before_update); break; @@ -1067,7 +1067,7 @@ void birdbot_update(PeMoby *birdbot_moby) { qcopy(&va, &c->path->points[c->idx]); va.f[2] += path_node_height_offset; if (fast_vec_dist(&birdbot_moby->pos, &va) < 0.25f) { - birdbot_moby->state = 0xB; + birdbot_moby->state = BIRDBOT_STATE_BRAKE_AND_FACE_TARGET; } spawn_birdbot_movement_particles((SplashMoby *)birdbot_moby, (u128 *)&birdbot_position_before_update); @@ -1118,7 +1118,7 @@ void birdbot_update(PeMoby *birdbot_moby) { if (birdbot_moby->b53 != 0) { blend_moby_animation(birdbot_moby, 0, 0, scale_game_frames(6)); } - birdbot_moby->state = 1; + birdbot_moby->state = BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION; } spawn_birdbot_movement_particles((SplashMoby *)birdbot_moby, (u128 *)&birdbot_position_before_update); @@ -1137,13 +1137,13 @@ void birdbot_update(PeMoby *birdbot_moby) { f = *(float *)&birdbot_path_entry_animation_speed_gp; birdbot_vars->main.idx = i; birdbot_moby->f58 = f; - birdbot_moby->state = 9; + birdbot_moby->state = BIRDBOT_STATE_BEGIN_PATH_MOVEMENT; return; } if (birdbot_moby->b53 != 0) { blend_moby_animation(birdbot_moby, 0, 0, scale_game_frames(6)); } - birdbot_moby->state = 1; + birdbot_moby->state = BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION; } if (birdbot_moby->pos.f[0] < 2.0f || birdbot_moby->pos.f[0] > 1021.0f || birdbot_moby->pos.f[1] < 2.0f || birdbot_moby->pos.f[1] > 1021.0f || @@ -1243,8 +1243,8 @@ void birdbot_update(PeMoby *birdbot_moby) { } trooper_anim_finish(birdbot_moby, birdbot_vars->x60); birdbot_vars->f1CC = frame; - if (birdbot_moby->state == 1 || birdbot_moby->state == 5 || birdbot_moby->state == 6 || - birdbot_moby->state == 7 || birdbot_moby->state == 0xB) { + if (birdbot_moby->state == BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION || birdbot_moby->state == 5 || birdbot_moby->state == BIRDBOT_STATE_FIRE_BURST || + birdbot_moby->state == BIRDBOT_STATE_RECOVER_FROM_BURST || birdbot_moby->state == BIRDBOT_STATE_BRAKE_AND_FACE_TARGET) { birdbot_vars->fE8 += frame_time_sq * 9.8f; birdbot_moby->pos.f[2] -= birdbot_vars->fE8 - 2.0f; ground = probe_ground_height(&birdbot_moby->pos, 0, 0.5f); From 9071110020536fe95b6d271db589b91e86e5970f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:31:16 +0000 Subject: [PATCH 1126/1502] decomp: clarify names in update_kerwan_path_enemy domain_0_value_14 -> ENEMY_HIDDEN_AT_PATH_START: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail 0x002c8f74-0x002c8fc0 places the enemy at primary path node zero, sets flags 0x41 and clears model pointer +0x94; death/failure branches converge on state-14 store 0x002c9550-0x002c9564. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_HIDDEN_AT_PATH_START for this listed occurrence. domain_10_value_4 -> ENEMY_PROJECTILE_ATTACK_WINDUP: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail 0x002c7838-0x002c7864 stores enemy state 4 and starts animation 3 after target gates. Its case 0x002c7950-0x002c7984 waits for completion, then enters state 5 and animation 4. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_PROJECTILE_ATTACK_WINDUP for this listed occurrence. domain_13_value_1 -> ENEMY_WAIT_FOR_ACTIVATION: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 1 at 0x002c752c-0x002c7864 waits at the path start or checks target/trigger gates before movement or attack. Initialization 0x002c748c, completed paths 0x002c8438/0x002c8518, heading completion 0x002c8d18 and respawn 0x002c9034 store this same wait state. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_ACTIVATION for this listed occurrence. domain_14_value_5 -> ENEMY_PROJECTILE_ATTACK: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail 0x002c7958-0x002c7968 stores state 5 and clears shot counter +0x254. Case 5 at 0x002c7aac-0x002c7c4c constructs target-directed launch vectors from joint zero and calls spawn_homing_rocket at 0x002d4288. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_PROJECTILE_ATTACK for this listed occurrence. domain_15_value_6 -> ENEMY_MELEE_ATTACK: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail target proximity/height gates store 6 at 0x002c777c-0x002c778c, 0x002c79d0-0x002c79e0, 0x002c7dec-0x002c7dfc and 0x002c7e8c-0x002c7e9c. Case 6 at 0x002c7f68-0x002c8124 applies an animation-window, range and facing gated hit to selected_target.obj. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MELEE_ATTACK for this listed occurrence. domain_16_value_7 -> ENEMY_MOVE_TO_PATH_NODE: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 7 at 0x002c8200-0x002c8268 computes heading to primary path[index] and steps the mover to that node. Stores of 7 after incrementing/selecting pf.idx enter this exact dispatch; the pre-dispatch comparison at 0x002c7194 bounds states below that same member. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MOVE_TO_PATH_NODE for this listed occurrence. domain_17_value_7 -> ENEMY_MOVE_TO_PATH_NODE: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 7 at 0x002c8200-0x002c8268 computes heading to primary path[index] and steps the mover to that node. Stores of 7 after incrementing/selecting pf.idx enter this exact dispatch; the pre-dispatch comparison at 0x002c7194 bounds states below that same member. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MOVE_TO_PATH_NODE for this listed occurrence. domain_18_value_8 -> ENEMY_FOLLOW_PATH_TO_END: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail stores at 0x002c7708-0x002c770c, 0x002c7ca4-0x002c7cac and 0x002c81f4-0x002c81fc enter state 8. Case 8 at 0x002c838c-0x002c8438 projects the primary cursor, moves to indexed nodes and advances until the final node. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_FOLLOW_PATH_TO_END for this listed occurrence. domain_19_value_6 -> ENEMY_MELEE_ATTACK: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail target proximity/height gates store 6 at 0x002c777c-0x002c778c, 0x002c79d0-0x002c79e0, 0x002c7dec-0x002c7dfc and 0x002c7e8c-0x002c7e9c. Case 6 at 0x002c7f68-0x002c8124 applies an animation-window, range and facing gated hit to selected_target.obj. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MELEE_ATTACK for this listed occurrence. domain_1_value_13 -> ENEMY_DEATH_KNOCKBACK: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail dispatch case 13 at 0x002c8d48-0x002c8f70 steps knockback then emits debris and removes or hides the enemy. The path-id removal guard at 0x002c7144-0x002c714c explicitly exempts this same state. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_DEATH_KNOCKBACK for this listed occurrence. domain_20_value_6 -> ENEMY_MELEE_ATTACK: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail target proximity/height gates store 6 at 0x002c777c-0x002c778c, 0x002c79d0-0x002c79e0, 0x002c7dec-0x002c7dfc and 0x002c7e8c-0x002c7e9c. Case 6 at 0x002c7f68-0x002c8124 applies an animation-window, range and facing gated hit to selected_target.obj. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MELEE_ATTACK for this listed occurrence. domain_21_value_7 -> ENEMY_MOVE_TO_PATH_NODE: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 7 at 0x002c8200-0x002c8268 computes heading to primary path[index] and steps the mover to that node. Stores of 7 after incrementing/selecting pf.idx enter this exact dispatch; the pre-dispatch comparison at 0x002c7194 bounds states below that same member. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MOVE_TO_PATH_NODE for this listed occurrence. domain_22_value_7 -> ENEMY_MOVE_TO_PATH_NODE: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 7 at 0x002c8200-0x002c8268 computes heading to primary path[index] and steps the mover to that node. Stores of 7 after incrementing/selecting pf.idx enter this exact dispatch; the pre-dispatch comparison at 0x002c7194 bounds states below that same member. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MOVE_TO_PATH_NODE for this listed occurrence. domain_23_value_7 -> ENEMY_MOVE_TO_PATH_NODE: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 7 at 0x002c8200-0x002c8268 computes heading to primary path[index] and steps the mover to that node. Stores of 7 after incrementing/selecting pf.idx enter this exact dispatch; the pre-dispatch comparison at 0x002c7194 bounds states below that same member. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MOVE_TO_PATH_NODE for this listed occurrence. domain_24_value_1 -> ENEMY_WAIT_FOR_ACTIVATION: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 1 at 0x002c752c-0x002c7864 waits at the path start or checks target/trigger gates before movement or attack. Initialization 0x002c748c, completed paths 0x002c8438/0x002c8518, heading completion 0x002c8d18 and respawn 0x002c9034 store this same wait state. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_ACTIVATION for this listed occurrence. domain_25_value_7 -> ENEMY_MOVE_TO_PATH_NODE: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 7 at 0x002c8200-0x002c8268 computes heading to primary path[index] and steps the mover to that node. Stores of 7 after incrementing/selecting pf.idx enter this exact dispatch; the pre-dispatch comparison at 0x002c7194 bounds states below that same member. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MOVE_TO_PATH_NODE for this listed occurrence. domain_26_value_8 -> ENEMY_FOLLOW_PATH_TO_END: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail stores at 0x002c7708-0x002c770c, 0x002c7ca4-0x002c7cac and 0x002c81f4-0x002c81fc enter state 8. Case 8 at 0x002c838c-0x002c8438 projects the primary cursor, moves to indexed nodes and advances until the final node. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_FOLLOW_PATH_TO_END for this listed occurrence. domain_27_value_7 -> ENEMY_MOVE_TO_PATH_NODE: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 7 at 0x002c8200-0x002c8268 computes heading to primary path[index] and steps the mover to that node. Stores of 7 after incrementing/selecting pf.idx enter this exact dispatch; the pre-dispatch comparison at 0x002c7194 bounds states below that same member. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MOVE_TO_PATH_NODE for this listed occurrence. domain_28_value_1 -> ENEMY_WAIT_FOR_ACTIVATION: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 1 at 0x002c752c-0x002c7864 waits at the path start or checks target/trigger gates before movement or attack. Initialization 0x002c748c, completed paths 0x002c8438/0x002c8518, heading completion 0x002c8d18 and respawn 0x002c9034 store this same wait state. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_ACTIVATION for this listed occurrence. domain_29_value_7 -> ENEMY_MOVE_TO_PATH_NODE: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 7 at 0x002c8200-0x002c8268 computes heading to primary path[index] and steps the mover to that node. Stores of 7 after incrementing/selecting pf.idx enter this exact dispatch; the pre-dispatch comparison at 0x002c7194 bounds states below that same member. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MOVE_TO_PATH_NODE for this listed occurrence. domain_2_value_12 -> ENEMY_TURN_TO_HEADING: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail 0x002c718c-0x002c71cc compares enemy state 12 and distributes saved heading +0x28c relative to yaw into look joints. Case 12 at 0x002c8b64-0x002c8d44 turns toward that heading then resumes saved path/wait state. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_TURN_TO_HEADING for this listed occurrence. domain_30_value_1 -> ENEMY_WAIT_FOR_ACTIVATION: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 1 at 0x002c752c-0x002c7864 waits at the path start or checks target/trigger gates before movement or attack. Initialization 0x002c748c, completed paths 0x002c8438/0x002c8518, heading completion 0x002c8d18 and respawn 0x002c9034 store this same wait state. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_ACTIVATION for this listed occurrence. domain_31_value_1 -> ENEMY_WAIT_FOR_ACTIVATION: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 1 at 0x002c752c-0x002c7864 waits at the path start or checks target/trigger gates before movement or attack. Initialization 0x002c748c, completed paths 0x002c8438/0x002c8518, heading completion 0x002c8d18 and respawn 0x002c9034 store this same wait state. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_ACTIVATION for this listed occurrence. domain_32_value_1 -> ENEMY_WAIT_FOR_ACTIVATION: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 1 at 0x002c752c-0x002c7864 waits at the path start or checks target/trigger gates before movement or attack. Initialization 0x002c748c, completed paths 0x002c8438/0x002c8518, heading completion 0x002c8d18 and respawn 0x002c9034 store this same wait state. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_ACTIVATION for this listed occurrence. domain_33_value_2 -> ENEMY_WAIT_FOR_LINKED_MOBY: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail linked-index checks at 0x002c7508-0x002c7524 and shared entry 0x002c8550-0x002c8574 store state 2. Its case at 0x002c7868-0x002c794c waits on instance indexed by data+0x284, clearing the link and returning to wait when absent/inactive. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_LINKED_MOBY for this listed occurrence. domain_34_value_7 -> ENEMY_MOVE_TO_PATH_NODE: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 7 at 0x002c8200-0x002c8268 computes heading to primary path[index] and steps the mover to that node. Stores of 7 after incrementing/selecting pf.idx enter this exact dispatch; the pre-dispatch comparison at 0x002c7194 bounds states below that same member. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MOVE_TO_PATH_NODE for this listed occurrence. domain_35_value_1 -> ENEMY_WAIT_FOR_ACTIVATION: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 1 at 0x002c752c-0x002c7864 waits at the path start or checks target/trigger gates before movement or attack. Initialization 0x002c748c, completed paths 0x002c8438/0x002c8518, heading completion 0x002c8d18 and respawn 0x002c9034 store this same wait state. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_ACTIVATION for this listed occurrence. domain_36_value_7 -> ENEMY_MOVE_TO_PATH_NODE: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 7 at 0x002c8200-0x002c8268 computes heading to primary path[index] and steps the mover to that node. Stores of 7 after incrementing/selecting pf.idx enter this exact dispatch; the pre-dispatch comparison at 0x002c7194 bounds states below that same member. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MOVE_TO_PATH_NODE for this listed occurrence. domain_37_value_14 -> ENEMY_HIDDEN_AT_PATH_START: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail 0x002c8f74-0x002c8fc0 places the enemy at primary path node zero, sets flags 0x41 and clears model pointer +0x94; death/failure branches converge on state-14 store 0x002c9550-0x002c9564. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_HIDDEN_AT_PATH_START for this listed occurrence. domain_38_value_11 -> ENEMY_FALL_UNDER_GRAVITY: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail state 11 entry at 0x002c88c0-0x002c88c8 and 0x002c930c-0x002c9340 initializes/enters falling; case 11 at 0x002c88cc-0x002c8a00 integrates vertical acceleration and collision. Range check at 0x002c9194-0x002c91a4 excludes states 11 through 14 from ordinary gravity. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_FALL_UNDER_GRAVITY for this listed occurrence. domain_39_value_14 -> ENEMY_HIDDEN_AT_PATH_START: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail 0x002c8f74-0x002c8fc0 places the enemy at primary path node zero, sets flags 0x41 and clears model pointer +0x94; death/failure branches converge on state-14 store 0x002c9550-0x002c9564. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_HIDDEN_AT_PATH_START for this listed occurrence. domain_3_value_7 -> ENEMY_MOVE_TO_PATH_NODE: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 7 at 0x002c8200-0x002c8268 computes heading to primary path[index] and steps the mover to that node. Stores of 7 after incrementing/selecting pf.idx enter this exact dispatch; the pre-dispatch comparison at 0x002c7194 bounds states below that same member. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MOVE_TO_PATH_NODE for this listed occurrence. domain_40_value_1 -> ENEMY_WAIT_FOR_ACTIVATION: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 1 at 0x002c752c-0x002c7864 waits at the path start or checks target/trigger gates before movement or attack. Initialization 0x002c748c, completed paths 0x002c8438/0x002c8518, heading completion 0x002c8d18 and respawn 0x002c9034 store this same wait state. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_ACTIVATION for this listed occurrence. domain_41_value_1 -> ENEMY_WAIT_FOR_ACTIVATION: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 1 at 0x002c752c-0x002c7864 waits at the path start or checks target/trigger gates before movement or attack. Initialization 0x002c748c, completed paths 0x002c8438/0x002c8518, heading completion 0x002c8d18 and respawn 0x002c9034 store this same wait state. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_ACTIVATION for this listed occurrence. domain_42_value_14 -> ENEMY_HIDDEN_AT_PATH_START: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail 0x002c8f74-0x002c8fc0 places the enemy at primary path node zero, sets flags 0x41 and clears model pointer +0x94; death/failure branches converge on state-14 store 0x002c9550-0x002c9564. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_HIDDEN_AT_PATH_START for this listed occurrence. domain_43_value_14 -> ENEMY_HIDDEN_AT_PATH_START: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail 0x002c8f74-0x002c8fc0 places the enemy at primary path node zero, sets flags 0x41 and clears model pointer +0x94; death/failure branches converge on state-14 store 0x002c9550-0x002c9564. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_HIDDEN_AT_PATH_START for this listed occurrence. domain_44_value_1 -> ENEMY_WAIT_FOR_ACTIVATION: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 1 at 0x002c752c-0x002c7864 waits at the path start or checks target/trigger gates before movement or attack. Initialization 0x002c748c, completed paths 0x002c8438/0x002c8518, heading completion 0x002c8d18 and respawn 0x002c9034 store this same wait state. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_ACTIVATION for this listed occurrence. domain_47_value_11 -> ENEMY_FALL_UNDER_GRAVITY: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail state 11 entry at 0x002c88c0-0x002c88c8 and 0x002c930c-0x002c9340 initializes/enters falling; case 11 at 0x002c88cc-0x002c8a00 integrates vertical acceleration and collision. Range check at 0x002c9194-0x002c91a4 excludes states 11 through 14 from ordinary gravity. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_FALL_UNDER_GRAVITY for this listed occurrence. domain_48_value_14 -> ENEMY_HIDDEN_AT_PATH_START: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail 0x002c8f74-0x002c8fc0 places the enemy at primary path node zero, sets flags 0x41 and clears model pointer +0x94; death/failure branches converge on state-14 store 0x002c9550-0x002c9564. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_HIDDEN_AT_PATH_START for this listed occurrence. domain_49_value_10 -> ENEMY_KNOCKBACK_RECOVERY: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail 0x002c91a8-0x002c91b8 tests state 10 to suppress ordinary vertical acceleration. Case 10 at 0x002c85ac-0x002c86e0 steps nonlethal knockback and resumes primary path/wait on completion bit 0x40; supplied hit reaction enters the existing ENEMY_KNOCKBACK_RECOVERY member. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_KNOCKBACK_RECOVERY for this listed occurrence. domain_4_value_1 -> ENEMY_WAIT_FOR_ACTIVATION: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail case 1 at 0x002c752c-0x002c7864 waits at the path start or checks target/trigger gates before movement or attack. Initialization 0x002c748c, completed paths 0x002c8438/0x002c8518, heading completion 0x002c8d18 and respawn 0x002c9034 store this same wait state. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_ACTIVATION for this listed occurrence. domain_50_value_11 -> ENEMY_FALL_UNDER_GRAVITY: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail state 11 entry at 0x002c88c0-0x002c88c8 and 0x002c930c-0x002c9340 initializes/enters falling; case 11 at 0x002c88cc-0x002c8a00 integrates vertical acceleration and collision. Range check at 0x002c9194-0x002c91a4 excludes states 11 through 14 from ordinary gravity. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_FALL_UNDER_GRAVITY for this listed occurrence. domain_51_value_14 -> ENEMY_HIDDEN_AT_PATH_START: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail 0x002c8f74-0x002c8fc0 places the enemy at primary path node zero, sets flags 0x41 and clears model pointer +0x94; death/failure branches converge on state-14 store 0x002c9550-0x002c9564. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_HIDDEN_AT_PATH_START for this listed occurrence. domain_5_value_2 -> ENEMY_WAIT_FOR_LINKED_MOBY: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail linked-index checks at 0x002c7508-0x002c7524 and shared entry 0x002c8550-0x002c8574 store state 2. Its case at 0x002c7868-0x002c794c waits on instance indexed by data+0x284, clearing the link and returning to wait when absent/inactive. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_LINKED_MOBY for this listed occurrence. domain_6_value_9 -> ENEMY_FOLLOW_ALTERNATE_PATH: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail 0x002c763c-0x002c7644 clears alternate cursor +0x298 then stores state 9. Case 9 at 0x002c8460-0x002c8518 follows path ID +0x290 using that cursor, clears the ID at completion and returns to wait. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_FOLLOW_ALTERNATE_PATH for this listed occurrence. domain_7_value_2 -> ENEMY_WAIT_FOR_LINKED_MOBY: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail linked-index checks at 0x002c7508-0x002c7524 and shared entry 0x002c8550-0x002c8574 store state 2. Its case at 0x002c7868-0x002c794c waits on instance indexed by data+0x284, clearing the link and returning to wait when absent/inactive. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_WAIT_FOR_LINKED_MOBY for this listed occurrence. domain_8_value_8 -> ENEMY_FOLLOW_PATH_TO_END: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail stores at 0x002c7708-0x002c770c, 0x002c7ca4-0x002c7cac and 0x002c81f4-0x002c81fc enter state 8. Case 8 at 0x002c838c-0x002c8438 projects the primary cursor, moves to indexed nodes and advances until the final node. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_FOLLOW_PATH_TO_END for this listed occurrence. domain_9_value_6 -> ENEMY_MELEE_ATTACK: The supplied C token selects m->state, the unsigned byte at input moby+0x20, loaded from s3+0x20 for the dispatch at 0x002c72fc-0x002c731c. It therefore belongs to the existing function-local enemy-state enum, not HeroStateId or animation IDs. Retail target proximity/height gates store 6 at 0x002c777c-0x002c778c, 0x002c79d0-0x002c79e0, 0x002c7dec-0x002c7dfc and 0x002c7e8c-0x002c7e9c. Case 6 at 0x002c7f68-0x002c8124 applies an animation-window, range and facing gated hit to selected_target.obj. Original retail Ghidra and current source agree; reuse the existing canonical member ENEMY_MELEE_ATTACK for this listed occurrence. --- src/overlays/l03/mobys/kerwan_path_enemy.c | 94 +++++++++++----------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/src/overlays/l03/mobys/kerwan_path_enemy.c b/src/overlays/l03/mobys/kerwan_path_enemy.c index 48e990421c..b30db718ad 100644 --- a/src/overlays/l03/mobys/kerwan_path_enemy.c +++ b/src/overlays/l03/mobys/kerwan_path_enemy.c @@ -413,21 +413,21 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { } if (D_L03_0015F5C4 == 2) { m->flags |= 0x41; - } else if (m->state != 0xE) { + } else if (m->state != ENEMY_HIDDEN_AT_PATH_START) { m->flags &= 0xFFBE; } if (m->pos[0] < 2.0f || 1021.0f < m->pos[0] || m->pos[1] < 2.0f || 1021.0f < m->pos[1] || - m->pos[2] < 2.0f || 1021.0f < m->pos[2] || (moby_data->pf.id == -1 && m->state != 0xD)) { + m->pos[2] < 2.0f || 1021.0f < m->pos[2] || (moby_data->pf.id == -1 && m->state != ENEMY_DEATH_KNOCKBACK)) { mark_moby_for_removal(m); return; } FUN_L00_001fefc8_cf(m); fast_subtract_rotations_cf(&moby_data->b263); if (m->b31 != 0 || target_distance < 24.0f) { - if (m->state == 0xC) { + if (m->state == ENEMY_TURN_TO_HEADING) { moby_data->look0.f68 = fast_subtract_rotations(moby_data->f28C, m->rot[2]) * 0.25f; moby_data->look1.f68 = fast_subtract_rotations(moby_data->f28C, m->rot[2]) * 0.75f; - } else if (m->state < 7 && target_distance < moby_data->f270) { + } else if (m->state < ENEMY_MOVE_TO_PATH_NODE && target_distance < moby_data->f270) { moby_data->look1.f68 = fast_subtract_rotations(fast_arc_tan(selected_target.pos[0] - m->pos[0], selected_target.pos[1] - m->pos[1]), @@ -482,7 +482,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { moby_data->pf.path = np; qcopy(m->pos, np + 0x10); } - m->state = 1; + m->state = ENEMY_WAIT_FOR_ACTIVATION; moby_data->s288 = m->s32; moby_data->s28A = D_L03_001618F4 & 7; D_L03_001618F4_i++; @@ -499,7 +499,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { } if (moby_data->i284 != -1 && moby_data->i290 == -1) { blend_moby_animation(m, 0, 0, scale_game_frames(10)); - m->state = 2; + m->state = ENEMY_WAIT_FOR_LINKED_MOBY; } break; case ENEMY_WAIT_FOR_ACTIVATION: @@ -517,14 +517,14 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { (target_distance < moby_data->f294 && absolute_float(selected_target.pos[2] - m->pos[2]) < 4.0f)) { moby_data->i298 = 0; - m->state = 9; + m->state = ENEMY_FOLLOW_ALTERNATE_PATH; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } } } else if (moby_data->i284 != -1) { blend_moby_animation(m, 0, 0, scale_game_frames(10)); - m->state = 2; + m->state = ENEMY_WAIT_FOR_LINKED_MOBY; } else { if (target_distance < moby_data->f270 || target_distance < moby_data->f27C) { if (try_start_kerwan_path_enemy_heading_turn( @@ -539,14 +539,14 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { absolute_float(selected_target.pos[2] - m->pos[2]) < 4.0f) { moby_data->f27C = 0.0f; moby_data->s256 = 1; - m->state = 8; + m->state = ENEMY_FOLLOW_PATH_TO_END; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } } if (target_distance < 3.5f && absolute_float(selected_target.pos[2] - m->pos[2]) < 3.0f) { - m->state = 6; + m->state = ENEMY_MELEE_ATTACK; if (m->anim != 2) { blend_moby_animation(m, 2, 0, scale_game_frames(10)); } @@ -558,7 +558,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { fast_arc_tan(selected_target.pos[0] - m->pos[0], selected_target.pos[1] - m->pos[1])) < 0.7853982f) { if (m->b31 != 0) { - m->state = 4; + m->state = ENEMY_PROJECTILE_ATTACK_WINDUP; if (m->anim != 3) { blend_moby_animation(m, 3, 0, scale_game_frames(10)); } @@ -576,7 +576,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { { Moby2C8398 *o = &D_L03_0015FFD8_m[moby_data->i284]; if (o == 0 || o->state == 0xFE || o->state == 0xFD || (m->b52 == 0xA && (m->b70 & 2))) { - m->state = 1; + m->state = ENEMY_WAIT_FOR_ACTIVATION; blend_moby_animation(m, 0, 0, scale_game_frames(10)); moby_data->s250 = scale_game_frames(0x3C); moby_data->i284 = -1; @@ -591,14 +591,14 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { break; case ENEMY_PROJECTILE_ATTACK_WINDUP: if (m->b70 & 2) { - m->state = 5; + m->state = ENEMY_PROJECTILE_ATTACK; moby_data->b254 = 0; if (m->anim != 4) { blend_moby_animation(m, 4, 0, 0); } } else if (target_distance < 3.5f && absolute_float(selected_target.pos[2] - m->pos[2]) < 3.0f) { - m->state = 6; + m->state = ENEMY_MELEE_ATTACK; if (m->anim != 2) { blend_moby_animation(m, 2, 0, scale_game_frames(10)); } @@ -608,14 +608,14 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { Data2C8398 *d2 = m->data; if (d2->pf.idx < *(int *)d2->pf.path - 1) { d2->pf.idx++; - m->state = 7; + m->state = ENEMY_MOVE_TO_PATH_NODE; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } } } else { is_value_within_interpolated_window_cf(m); - m->state = 7; + m->state = ENEMY_MOVE_TO_PATH_NODE; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } @@ -661,7 +661,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { if (target_distance < moby_data->f27C && absolute_float(selected_target.pos[2] - m->pos[2]) < 4.0f) { moby_data->f27C = 0.0f; - m->state = 8; + m->state = ENEMY_FOLLOW_PATH_TO_END; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } @@ -685,7 +685,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { } if (target_distance < 3.5f && absolute_float(selected_target.pos[2] - m->pos[2]) < 3.0f) { - m->state = 6; + m->state = ENEMY_MELEE_ATTACK; if (m->anim != 2) { blend_moby_animation(m, 2, 0, scale_game_frames(10)); } @@ -699,7 +699,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { (char *)&selected_target)) { break; } - m->state = 6; + m->state = ENEMY_MELEE_ATTACK; if (m->anim != 2) { blend_moby_animation(m, 2, 0, scale_game_frames(10)); } @@ -709,14 +709,14 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { Data2C8398 *d2 = m->data; if (d2->pf.idx < *(int *)d2->pf.path - 1) { d2->pf.idx++; - m->state = 7; + m->state = ENEMY_MOVE_TO_PATH_NODE; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } } } else { is_value_within_interpolated_window_cf(m); - m->state = 7; + m->state = ENEMY_MOVE_TO_PATH_NODE; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } @@ -761,12 +761,12 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { Data2C8398 *d2 = m->data; if (d2->pf.idx < *(int *)d2->pf.path - 1) { d2->pf.idx++; - m->state = 7; + m->state = ENEMY_MOVE_TO_PATH_NODE; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } } else { - m->state = 1; + m->state = ENEMY_WAIT_FOR_ACTIVATION; if (m->anim != 0) { blend_moby_animation(m, 0, 0, scale_game_frames(10)); } @@ -778,7 +778,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { } } else { is_value_within_interpolated_window_cf(m); - m->state = 7; + m->state = ENEMY_MOVE_TO_PATH_NODE; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } @@ -790,7 +790,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { case ENEMY_MOVE_TO_PATH_NODE: { PathF2C8398 *pf = &moby_data->pf; if (moby_data->s256 != 0) { - m->state = 8; + m->state = ENEMY_FOLLOW_PATH_TO_END; break; } { @@ -816,12 +816,12 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { Data2C8398 *d2 = m->data; if (d2->pf.idx < *(int *)d2->pf.path - 1) { d2->pf.idx++; - m->state = 7; + m->state = ENEMY_MOVE_TO_PATH_NODE; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } } else { - m->state = 1; + m->state = ENEMY_WAIT_FOR_ACTIVATION; if (m->anim != 0) { blend_moby_animation(m, 0, 0, scale_game_frames(10)); } @@ -833,13 +833,13 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { } } else { is_value_within_interpolated_window_cf(m); - m->state = 7; + m->state = ENEMY_MOVE_TO_PATH_NODE; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } } } else { - m->state = 1; + m->state = ENEMY_WAIT_FOR_ACTIVATION; if (m->anim != 0) { blend_moby_animation(m, 0, 0, scale_game_frames(10)); } @@ -871,7 +871,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { if (pf->idx < *(int *)pf->path - 1) { pf->idx++; } else { - m->state = 1; + m->state = ENEMY_WAIT_FOR_ACTIVATION; if (m->anim != 0) { blend_moby_animation(m, 0, 0, scale_game_frames(10)); } @@ -905,13 +905,13 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { moby_data->i298++; } else { moby_data->i290 = -1; - m->state = 1; + m->state = ENEMY_WAIT_FOR_ACTIVATION; if (m->anim != 0) { blend_moby_animation(m, 0, 0, scale_game_frames(10)); } if (moby_data->i284 != -1) { blend_moby_animation(m, 0, 0, scale_game_frames(10)); - m->state = 2; + m->state = ENEMY_WAIT_FOR_LINKED_MOBY; } else { try_start_kerwan_path_enemy_heading_turn( fast_arc_tan(selected_target.pos[0] - m->pos[0], @@ -938,12 +938,12 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { Data2C8398 *d2 = m->data; if (d2->pf.idx < *(int *)d2->pf.path - 1) { d2->pf.idx++; - m->state = 7; + m->state = ENEMY_MOVE_TO_PATH_NODE; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } } else { - m->state = 1; + m->state = ENEMY_WAIT_FOR_ACTIVATION; if (m->anim != 0) { blend_moby_animation(m, 0, 0, scale_game_frames(10)); } @@ -955,7 +955,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { } } else { is_value_within_interpolated_window_cf(m); - m->state = 7; + m->state = ENEMY_MOVE_TO_PATH_NODE; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } @@ -1021,7 +1021,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { *(OvlQuad *)m->pos = *(OvlQuad *)(moby_data->pf.path + 0x10); clear_u64_value(moby_data->v40); moby_data->mv.f18 = 0.0f; - m->state = 0xE; + m->state = ENEMY_HIDDEN_AT_PATH_START; m->flags |= 0x41; m->i94 = 0; return; @@ -1033,7 +1033,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { if (g + 5.0f < m->pos[2]) { allocate_voice_for_target_entry(0xA, 0x21, (int)m); blend_moby_animation(m, 0xB, 0, scale_game_frames(10)); - m->state = 0xB; + m->state = ENEMY_FALL_UNDER_GRAVITY; } break; } @@ -1126,7 +1126,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { *(OvlQuad *)m->pos = *(OvlQuad *)(moby_data->pf.path + 0x10); clear_u64_value(moby_data->v40); moby_data->mv.f18 = 0.0f; - m->state = 0xE; + m->state = ENEMY_HIDDEN_AT_PATH_START; m->flags |= 0x41; m->i94 = 0; return; @@ -1150,7 +1150,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { } m->f58 = 1.0f; } else { - m->state = 1; + m->state = ENEMY_WAIT_FOR_ACTIVATION; if (m->anim != 0) { blend_moby_animation(m, 0, 0, scale_game_frames(10)); } @@ -1171,7 +1171,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } } else { - m->state = 1; + m->state = ENEMY_WAIT_FOR_ACTIVATION; if (m->anim != 0) { blend_moby_animation(m, 0, 0, scale_game_frames(10)); } @@ -1255,7 +1255,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { *(OvlQuad *)m->pos = *(OvlQuad *)(moby_data->pf.path + 0x10); clear_u64_value(moby_data->v40); moby_data->mv.f18 = 0.0f; - m->state = 0xE; + m->state = ENEMY_HIDDEN_AT_PATH_START; m->flags |= 0x41; m->i94 = 0; return; @@ -1270,7 +1270,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { *(OvlQuad *)m->pos = *(OvlQuad *)(moby_data->pf.path + 0x10); clear_u64_value(moby_data->v40); moby_data->mv.f18 = 0.0f; - m->state = 0xE; + m->state = ENEMY_HIDDEN_AT_PATH_START; m->flags |= 0x41; m->i94 = 0; return; @@ -1297,7 +1297,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { m->flags = (m->flags & 0xFFBE) | 0x1000; moby_data->f20 = convert_integer_to_float(moby_data->s24); qcopy(m->pos, moby_data->pf.path + 0x10); - m->state = 1; + m->state = ENEMY_WAIT_FOR_ACTIVATION; break; } if (m->b31 != 0) { @@ -1345,9 +1345,9 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { m->rot[2] = transformed_rotation[2]; } } - if (!(m->state >= 0xB && m->state <= 0xE)) { + if (!(m->state >= ENEMY_FALL_UNDER_GRAVITY && m->state <= ENEMY_HIDDEN_AT_PATH_START)) { float g; - if (m->state == 0xA) { + if (m->state == ENEMY_KNOCKBACK_RECOVERY) { moby_data->mv.f18 = 0.0f; } else { moby_data->mv.f18 = moby_data->mv.f18 + frame_time_sq * 9.8f; @@ -1376,7 +1376,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { } } else if (g + 5.0f < m->pos[2]) { blend_moby_animation(m, 0xB, 0, scale_game_frames(10)); - m->state = 0xB; + m->state = ENEMY_FALL_UNDER_GRAVITY; clear_u64_value(&moby_data->q); moby_data->q.f8 = -moby_data->mv.f18; moby_data->q.f10 = frame_time_sq * 19.6f; @@ -1450,7 +1450,7 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { *(OvlQuad *)m->pos = *(OvlQuad *)(pf->path + 0x10); clear_u64_value(moby_data->v40); moby_data->mv.f18 = 0.0f; - m->state = 0xE; + m->state = ENEMY_HIDDEN_AT_PATH_START; m->flags |= 0x41; m->i94 = 0; } From fe4af7dd6e3b02c6f6bcd95d5071a1ac9657340e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:31:16 +0000 Subject: [PATCH 1127/1502] decomp: clarify names in big_axebot_update domain_0_value_10 -> BIG_AXEBOT_STATE_DYING: 002ba720..002ba730 excludes state 10 from hit processing; the same byte dispatches at 002bac84, whose case 10 performs death motion, effects and removal at 002bbbb0..002bbca8. domain_10_value_4 -> BIG_AXEBOT_STATE_FOLLOW_PATH: 002baea4..002baf00 validates path and clip-volume conditions then stores 4 at moby+0x20; case 4 at 002bb0c4 reads indexed path and advances waypoints, existing FOLLOW_PATH. domain_11_value_7 -> BIG_AXEBOT_STATE_MELEE_ATTACK: IDLE proximity branch at 002baf44..002baf80 tests target distance below 4.5 and blends animation 4/frame 4 before shared store 7 at 002bb984; existing MELEE_ATTACK case at 002bb6e8. domain_12_value_2 -> BIG_AXEBOT_STATE_ALERT: 002bb07c..002bb0c0 gates on alert flag, blends animation 2 then writes 2 to moby+0x20; case 2 at 002baf94 waits for that animation and returns idle, existing ALERT. domain_13_value_1 -> BIG_AXEBOT_STATE_IDLE: ALERT animation completion at 002baf94..002bafc0 chooses idle animation through 002bb8dc..002bb900, storing 1 at moby+0x20; same byte selects established IDLE case. domain_14_value_7 -> BIG_AXEBOT_STATE_MELEE_ATTACK: WAIT_FOR_TARGET at 002bb008..002bb044 tests distance below 4.5 and blends attack animation 4/frame 4, then shared store 7 at 002bb984; existing MELEE_ATTACK case consumes this state. domain_15_value_2 -> BIG_AXEBOT_STATE_ALERT: WAIT_FOR_TARGET proximity branch 002bb048..002bb0c0 reaches alert flag check and animation 2 then stores 2 to moby+0x20; existing ALERT handler uses this same byte at 002baf94. domain_16_value_7 -> BIG_AXEBOT_STATE_MELEE_ATTACK: FOLLOW_PATH tests target distance below 4.5 at 002bb104..002bb140, blends animation 4/frame 4 and stores 7 to moby+0x20; case 7 implements melee contact at 002bb6e8..002bb808. domain_17_value_1 -> BIG_AXEBOT_STATE_IDLE: Path waypoint completion at 002bb178..002bb204 chooses an idle animation and writes state 1 via 002bb8fc..002bb900; moby+0x20 dispatches to existing IDLE case at 002bad68. domain_18_value_7 -> BIG_AXEBOT_STATE_MELEE_ATTACK: CHASE_TARGET proximity branch at 002bb3c8..002bb404 blends attack animation 4/frame 4 below 4.5 distance then shared store 7 at 002bb984; existing MELEE_ATTACK handler owns state 7. domain_19_value_9 -> BIG_AXEBOT_STATE_TURN: 002bb46c..002bb4a0 finds forward point outside path, clears turning velocity, blends animation 8 and stores 9 at moby+0x20; case 9 at 002bba88 turns toward home or target. domain_1_value_0 -> BIG_AXEBOT_STATE_INITIALIZE: 002ba720..002ba730 excludes zero state from hit processing; the same moby+0x20 byte dispatches at 002bac84 to case 0 initialization of HP, home and manipulators at 002bacac..002bad64. domain_20_value_6 -> BIG_AXEBOT_STATE_RETURN_HOME: 002bb4a8..002bb4d4 tests copied target position against allowed path and stores 6 at moby+0x20 if outside; existing RETURN_HOME case 002bb4d8..002bb6e4 steers toward saved home. domain_21_value_7 -> BIG_AXEBOT_STATE_MELEE_ATTACK: RETURN_HOME branch at 002bb4d8..002bb514 tests target distance below 4.5 and blends animation 4/frame 4 before shared store 7 at 002bb984; existing MELEE_ATTACK case uses that state. domain_22_value_1 -> BIG_AXEBOT_STATE_IDLE: 002bb5e0..002bb608 measures distance to saved home and stores 1 to moby+0x20 below 2.0; state switch dispatches that byte to existing IDLE case at 002bad68. domain_23_value_9 -> BIG_AXEBOT_STATE_TURN: 002bb674..002bb6b4 detects forward path boundary, clears turn velocity, selects animation 8 and stores 9 at moby+0x20 with home-turn flag; existing TURN case at 002bba88. domain_24_value_1 -> BIG_AXEBOT_STATE_IDLE: 002bb6bc..002bb6e4 finds copied target back inside permitted path and writes 1 to moby+0x20; the same selector dispatches to established IDLE case 002bad68. domain_25_value_1 -> BIG_AXEBOT_STATE_IDLE: MELEE_ATTACK completion at 002bb878..002bb900 sets cooldown, selects idle animation and stores 1 at moby+0x20; that byte selects existing IDLE handler 002bad68. domain_26_value_7 -> BIG_AXEBOT_STATE_MELEE_ATTACK: HIT_RECOVERY flag branch 002bb940..002bb984 clears recovery flag, blends animation 4/frame 4, sets speed 1.5 and stores 7 at moby+0x20; existing MELEE_ATTACK case handles contact. domain_27_value_1 -> BIG_AXEBOT_STATE_IDLE: 002bba34..002bba84 sees recovery displacement exhausted, writes 1 to moby+0x20 and clears cooldown; same state byte selects existing IDLE handler at 002bad68. domain_28_value_5 -> BIG_AXEBOT_STATE_CHASE_TARGET: TURN animation completion at 002bba88..002bbad4 stores 5 at moby+0x20 and blends locomotion animation 9; existing CHASE_TARGET case 002bb318 steers and walks toward target. domain_29_value_8 -> BIG_AXEBOT_STATE_HIT_RECOVERY: 002bbe34..002bbe40 copies moby+0x20 to saved data+0x401 except when equal to 8; the same selector's case 8 at 002bb904 handles hit recovery, matching existing HIT_RECOVERY. domain_2_value_0 -> BIG_AXEBOT_STATE_INITIALIZE: 002ba790..002ba794 checks the same moby+0x20 byte before applying damage; zero is the existing INITIALIZE case that sets HP/home/manipulators at 002bacac..002bad64. domain_30_value_0 -> BIG_AXEBOT_STATE_INITIALIZE: 002bbf08 tests moby+0x20 against zero before bone aiming; this is the same byte switched at 002bac84 whose zero case initializes HP, home and manipulators, existing INITIALIZE. domain_3_value_8 -> BIG_AXEBOT_STATE_HIT_RECOVERY: 002ba9d8..002ba9f4 blends hit animation 5, sets animation speed 2 and writes 8 to moby+0x20; that byte selects the existing HIT_RECOVERY case at 002bb904. domain_4_value_8 -> BIG_AXEBOT_STATE_HIT_RECOVERY: 002baa94..002baac8 blends hit animation 5 and starts knockback, writing 8 to moby+0x20 at 002baac0; its switch case is the existing HIT_RECOVERY handler at 002bb904. domain_5_value_1 -> BIG_AXEBOT_STATE_IDLE: 002bab20..002bab38 sets recovery timer and writes 1 to moby+0x20 after animation 6/frame 2; this same byte dispatches to established IDLE case at 002bad68. domain_6_value_10 -> BIG_AXEBOT_STATE_DYING: Fatal reaction branch sets knockback and writes 10 to moby+0x20 at 002bac1c; case 10 at 002bbbb0 performs death motion and effects/removal, matching existing DYING. domain_7_value_0 -> BIG_AXEBOT_STATE_INITIALIZE: 002bac64..002bac74 tests moby+0x20 against zero before the active/removal guard; the same byte dispatches to existing INITIALIZE case at 002bac84..002bacac. domain_8_value_3 -> BIG_AXEBOT_STATE_WAIT_FOR_TARGET: 002bad30..002bad44 tests data+0x400 and writes 3 to moby+0x20; existing WAIT_FOR_TARGET case at 002bafc4 waits for timer/proximity then enters attack or alert. domain_9_value_1 -> BIG_AXEBOT_STATE_IDLE: 002bad60..002bad64 writes 1 to moby+0x20 on ordinary initialization; state switch at 002bac84 sends this byte to existing IDLE handler at 002bad68. --- src/overlays/l04/mobys/big_axebot.c | 60 ++++++++++++++--------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/overlays/l04/mobys/big_axebot.c b/src/overlays/l04/mobys/big_axebot.c index 80644a0f21..9d502fac08 100644 --- a/src/overlays/l04/mobys/big_axebot.c +++ b/src/overlays/l04/mobys/big_axebot.c @@ -361,7 +361,7 @@ void big_axebot_update(M_B7B0 *moby) { } } fast_dec_timer_s16(&data->f404); - if (moby->state != 10 && moby->state != 0) { + if (moby->state != BIG_AXEBOT_STATE_DYING && moby->state != BIG_AXEBOT_STATE_INITIALIZE) { int unused_hit_reaction_output; float dmg; Hit_B7B0 *hit; @@ -372,7 +372,7 @@ void big_axebot_update(M_B7B0 *moby) { hit = (Hit_B7B0 *)find_moby_hit(moby, 0x210000, 0); hit_reaction_result = hit_reaction(moby, hit, &data->hp, 0, &unused_hit_reaction_output, &dmg, 0, 4); - if (hit != 0 && dmg != 0.0f && moby->state != 0) { + if (hit != 0 && dmg != 0.0f && moby->state != BIG_AXEBOT_STATE_INITIALIZE) { if (hit->att != 0) { struct Hero *h = &hero; if (hit->att != h->items[0].moby) { @@ -421,7 +421,7 @@ void big_axebot_update(M_B7B0 *moby) { blend_big_axebot_and_axe_animation( (char *)moby, (void *)5, 0, (void *)scale_game_frames(6)); set_big_axebot_and_axe_animation_speed(moby, 2.0f); - moby->state = 8; + moby->state = BIG_AXEBOT_STATE_HIT_RECOVERY; } data->f42C = 3.4f / scale_time(7.0f) * 0.5f; data->fB7 = 0x78; @@ -439,7 +439,7 @@ void big_axebot_update(M_B7B0 *moby) { blend_big_axebot_and_axe_animation( (char *)moby, (void *)5, 0, (void *)scale_game_frames(6)); set_big_axebot_and_axe_animation_speed(moby, 2.0f); - moby->state = 8; + moby->state = BIG_AXEBOT_STATE_HIT_RECOVERY; trooper_start_knockback(knockback_yaw, moby, data->fC0, 5, 1, 0); data->f110 = 5.0f; data->f114 = 10.0f; @@ -455,7 +455,7 @@ void big_axebot_update(M_B7B0 *moby) { blend_big_axebot_and_axe_animation( (char *)moby, (void *)6, (void *)2, (void *)scale_game_frames(4)); data->f402 = scale_game_frames(0x28); - moby->state = 1; + moby->state = BIG_AXEBOT_STATE_IDLE; data->f42C = 3.4f / scale_time(7.0f); data->fB7 = 0x78; trooper_anim_update(moby, (short *)data->fB0); @@ -472,7 +472,7 @@ void big_axebot_update(M_B7B0 *moby) { trooper_start_knockback(knockback_yaw, moby, data->fC0, 7, 1, 0); data->f110 = 12.0f; data->f114 = 25.0f; - moby->state = 10; + moby->state = BIG_AXEBOT_STATE_DYING; data->fB7 = 0x78; trooper_anim_update(moby, (short *)data->fB0); FUN_L00_00257470(moby, 0, -1); @@ -492,7 +492,7 @@ void big_axebot_update(M_B7B0 *moby) { } data->f38 = 0; FUN_L00_001fefc8(&data->f406); - if (moby->state != 0 && data->f2E != 1) { + if (moby->state != BIG_AXEBOT_STATE_INITIALIZE && data->f2E != 1) { if (data->f424 != 0) { mark_moby_for_removal(data->f424); } @@ -521,11 +521,11 @@ void big_axebot_update(M_B7B0 *moby) { data->f58 = 0xA; data->f5A = 0xC; if (data->f400 != 0) { - moby->state = 3; + moby->state = BIG_AXEBOT_STATE_WAIT_FOR_TARGET; blend_big_axebot_and_axe_animation( (char *)moby, (void *)0xA, 0, (void *)scale_game_frames(0xC)); } else { - moby->state = 1; + moby->state = BIG_AXEBOT_STATE_IDLE; } break; case BIG_AXEBOT_STATE_IDLE: { @@ -550,7 +550,7 @@ void big_axebot_update(M_B7B0 *moby) { } if (data->f430 != -1 && data->f434 != -1 && data->f43A == 0 && (flag || is_point_inside_clip_volume(&hero.motion.pos, data->f430) != 0)) { - moby->state = 4; + moby->state = BIG_AXEBOT_STATE_FOLLOW_PATH; moby->fBC |= 1; data->f43A = 1; } else { @@ -562,14 +562,14 @@ void big_axebot_update(M_B7B0 *moby) { if (target_distance < 4.5f) { blend_big_axebot_and_axe_animation( (char *)moby, (void *)4, (void *)4, (void *)scale_game_frames(0xC)); - moby->state = 7; + moby->state = BIG_AXEBOT_STATE_MELEE_ATTACK; } else if (flag ? target_distance < data->f43C * 2.0f : target_distance < data->f43C) { int nf = (moby->fBC & 1) == 0; if (nf) { blend_big_axebot_and_axe_animation( (char *)moby, (void *)2, 0, (void *)scale_game_frames(0xC)); - moby->state = 2; + moby->state = BIG_AXEBOT_STATE_ALERT; moby->fBC |= 1; } } @@ -586,7 +586,7 @@ void big_axebot_update(M_B7B0 *moby) { : 0), 0, (void *)scale_game_frames(0xC)); - moby->state = 1; + moby->state = BIG_AXEBOT_STATE_IDLE; } break; case BIG_AXEBOT_STATE_WAIT_FOR_TARGET: @@ -598,13 +598,13 @@ void big_axebot_update(M_B7B0 *moby) { if (target_distance < 4.5f) { blend_big_axebot_and_axe_animation( (char *)moby, (void *)4, (void *)4, (void *)scale_game_frames(0xC)); - moby->state = 7; + moby->state = BIG_AXEBOT_STATE_MELEE_ATTACK; } else if (flag ? target_distance < data->f43C * 2.0f : target_distance < data->f43C) { int nf = (moby->fBC & 1) == 0; if (nf) { blend_big_axebot_and_axe_animation( (char *)moby, (void *)2, 0, (void *)scale_game_frames(0xC)); - moby->state = 2; + moby->state = BIG_AXEBOT_STATE_ALERT; moby->fBC |= 1; } } @@ -621,7 +621,7 @@ void big_axebot_update(M_B7B0 *moby) { if (target_distance < 4.5f) { blend_big_axebot_and_axe_animation( (char *)moby, (void *)4, (void *)4, (void *)scale_game_frames(0xC)); - moby->state = 7; + moby->state = BIG_AXEBOT_STATE_MELEE_ATTACK; } if (vector_distance_xy(path->pts[data->f438], moby->pos) < 1.0f) { data->f438++; @@ -633,7 +633,7 @@ void big_axebot_update(M_B7B0 *moby) { blend_big_axebot_and_axe_animation( (char *)moby, (void *)0xD, 0, (void *)scale_game_frames(0x18)); } - moby->state = 1; + moby->state = BIG_AXEBOT_STATE_IDLE; break; } } @@ -668,7 +668,7 @@ void big_axebot_update(M_B7B0 *moby) { if (target_distance < 4.5f) { blend_big_axebot_and_axe_animation( (char *)moby, (void *)4, (void *)4, (void *)scale_game_frames(0xC)); - moby->state = 7; + moby->state = BIG_AXEBOT_STATE_MELEE_ATTACK; } else if (data->f41C != -1) { vector_quaternion_scratch[0] = fast_cos(moby->rot[2]) * 2.0f; vector_quaternion_scratch[1] = fast_sin(moby->rot[2]) * 2.0f; @@ -680,12 +680,12 @@ void big_axebot_update(M_B7B0 *moby) { data->f410 = 0.0f; blend_big_axebot_and_axe_animation( (char *)moby, (void *)8, 0, (void *)scale_game_frames(0xC)); - moby->state = 9; + moby->state = BIG_AXEBOT_STATE_TURN; } if (point_in_path_xy(tpos, ((P_B7B0 *)l04_paths[data->f41C])->pts, ((P_B7B0 *)l04_paths[data->f41C])->count) == 0) { - moby->state = 6; + moby->state = BIG_AXEBOT_STATE_RETURN_HOME; } } break; @@ -693,7 +693,7 @@ void big_axebot_update(M_B7B0 *moby) { if (target_distance < 4.5f) { blend_big_axebot_and_axe_animation( (char *)moby, (void *)4, (void *)4, (void *)scale_game_frames(0xC)); - moby->state = 7; + moby->state = BIG_AXEBOT_STATE_MELEE_ATTACK; } else { float a; @@ -711,7 +711,7 @@ void big_axebot_update(M_B7B0 *moby) { leg_walker_update( moby, data->f1A0, frame_time * 4.0f, data->f414, frame_time_sq * 20.0f); if (vector_distance_xy(moby->pos, data->home) < 2.0f) { - moby->state = 1; + moby->state = BIG_AXEBOT_STATE_IDLE; } if (data->f41C != -1) { vector_quaternion_scratch[0] = fast_cos(moby->rot[2]) * 2.0f; @@ -724,13 +724,13 @@ void big_axebot_update(M_B7B0 *moby) { data->f410 = 0.0f; blend_big_axebot_and_axe_animation( (char *)moby, (void *)8, 0, (void *)scale_game_frames(0xC)); - moby->state = 9; + moby->state = BIG_AXEBOT_STATE_TURN; moby->fBC |= 0x10; } if (point_in_path_xy(tpos, ((P_B7B0 *)l04_paths[data->f41C])->pts, ((P_B7B0 *)l04_paths[data->f41C])->count) != 0) { - moby->state = 1; + moby->state = BIG_AXEBOT_STATE_IDLE; } } } @@ -770,7 +770,7 @@ void big_axebot_update(M_B7B0 *moby) { : 0), 0, (void *)scale_game_frames(0xC)); - moby->state = 1; + moby->state = BIG_AXEBOT_STATE_IDLE; } break; case BIG_AXEBOT_STATE_HIT_RECOVERY: @@ -780,7 +780,7 @@ void big_axebot_update(M_B7B0 *moby) { blend_big_axebot_and_axe_animation( (char *)moby, (void *)4, (void *)4, (void *)scale_game_frames(6)); set_big_axebot_and_axe_animation_speed(moby, 1.5f); - moby->state = 7; + moby->state = BIG_AXEBOT_STATE_MELEE_ATTACK; } else if (moby->f53 == 8 && (hd < 28.0f || moby->f52 != moby->f53)) { float hit_recovery_displacement_limit = frame_scale * 0.11111111f; @@ -810,14 +810,14 @@ void big_axebot_update(M_B7B0 *moby) { frame_time_sq * 6.2831855f, frame_time * 4.1887903f); } else { - moby->state = 1; + moby->state = BIG_AXEBOT_STATE_IDLE; data->f402 = 0; } } break; case BIG_AXEBOT_STATE_TURN: if (moby->f52 == 8 && (moby->f70 & 2)) { - moby->state = 5; + moby->state = BIG_AXEBOT_STATE_CHASE_TARGET; moby->fBC = (moby->fBC | 8) & ~0x10; blend_big_axebot_and_axe_animation( (char *)moby, (void *)9, 0, (void *)scale_game_frames(0xC)); @@ -904,7 +904,7 @@ void big_axebot_update(M_B7B0 *moby) { build_axis_rotation_quaternion(vector_quaternion_scratch, 1, data->f408); build_axis_rotation_quaternion(data->m120.q, 2, 0.0f); multiply_quaternions(data->m120.q, data->m120.q, vector_quaternion_scratch); - if (moby->state != 8) { + if (moby->state != BIG_AXEBOT_STATE_HIT_RECOVERY) { data->f401 = moby->state; } data->f420 += frame_time_sq * 29.8f; @@ -926,7 +926,7 @@ void big_axebot_update(M_B7B0 *moby) { mark_moby_for_removal(moby); return; } - if (moby->state != 0) { + if (moby->state != BIG_AXEBOT_STATE_INITIALIZE) { float q[4]; float bone_transform[4][4]; float bone_euler_angles[4]; From ea2bed89e642a8f11829c22d9f701e529bda3064 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:31:17 +0000 Subject: [PATCH 1128/1502] decomp: clarify names in blarg_trooper_update domain_0_value_0 -> BLARG_TROOPER_STATE_INITIALIZE: 002c4954-002c4968 loads moby+0x20 and skips the initialized-pvars removal guard when zero; the same field dispatches to the initialization case at 002c4e74-002c4e9c. domain_10_value_5 -> BLARG_TROOPER_STATE_AIM: 002c5164-002c5190 checks the raised sight line and selected target identity, then writes 5 to moby+0x20 and blends animation 3, selecting established AIM. domain_11_value_7 -> BLARG_TROOPER_STATE_MELEE_ATTACK: 002c51c0-002c51e4 tests the close-range cooldown, stores 7 to moby+0x20 and chooses animation 7; state 7 is the established timed MELEE_ATTACK handler. domain_12_value_1 -> BLARG_TROOPER_STATE_IDLE: 002c5204-002c5234 exits path movement when target distance is below 13 or path-point distance below 1; 002c581c-002c5840 blends animation 0 and writes state 1, established IDLE. domain_13_value_7 -> BLARG_TROOPER_STATE_MELEE_ATTACK: 002c5538-002c55b0 checks close target range and yaw alignment in flagged running, then stores 7 to moby+0x20 and blends animation 7, selecting established MELEE_ATTACK. domain_14_value_5 -> BLARG_TROOPER_STATE_AIM: 002c55b4-002c55ec checks target distance below 14 in flagged running, stores 5 to moby+0x20 and blends animation 3, selecting established AIM. domain_15_value_7 -> BLARG_TROOPER_STATE_MELEE_ATTACK: 002c55f8-002c566c checks range below 1 and yaw difference below 0.2617994, writes 7 to moby+0x20 and blends animation 7, selecting established MELEE_ATTACK. domain_16_value_5 -> BLARG_TROOPER_STATE_AIM: 002c5670-002c56a4 checks target distance above 9, writes 5 to moby+0x20 and blends ready animation 3, selecting established AIM. domain_17_value_1 -> BLARG_TROOPER_STATE_IDLE: 002c56b4-002c56bc branches when selected-point distance is below 1 to 002c581c-002c5840, which selects animation 0 and writes 1 to moby+0x20, established IDLE. domain_18_value_1 -> BLARG_TROOPER_STATE_IDLE: 002c57bc-002c5814 checks jump animation 2 completion and branches to 002c581c-002c5840, blending animation 0 and storing state 1, the established IDLE case. domain_19_value_2 -> BLARG_TROOPER_STATE_MOVE_TO_PATH_POINT: 002c592c-002c596c checks target distance above 14 while aiming, blends animation 10 and stores 2 to moby+0x20, selecting established MOVE_TO_PATH_POINT. domain_1_value_11 -> BLARG_TROOPER_STATE_DYING: 002c4b34-002c4b3c loads moby+0x20 and compares it unsigned against 11 to exclude dying troopers from hit reactions; the same state field dispatches the established DYING case. domain_20_value_3 -> BLARG_TROOPER_STATE_RUN_TO_TARGET_OR_PATH_POINT: 002c5970-002c59bc checks target distance below 8 and expired movement cooldown while aiming, blends animation 11 and stores state 3, selecting the established running handler. domain_21_value_7 -> BLARG_TROOPER_STATE_MELEE_ATTACK: 002c59c0-002c59f4 checks target distance below 2.5 while aiming, stores 7 to moby+0x20 and selects animation 7, the established MELEE_ATTACK state. domain_22_value_6 -> BLARG_TROOPER_STATE_FIRE: 002c5a94-002c5b0c checks target-facing alignment, writes 6 at moby+0x20, blends animation 5 and initializes shot count 3; established FIRE consumes that shot count and spawns projectiles. domain_23_value_7 -> BLARG_TROOPER_STATE_MELEE_ATTACK: 002c5bd8-002c5c10 checks target distance below 2.5 during firing, stores 7 to moby+0x20 and blends animation 7, selecting established MELEE_ATTACK. domain_24_value_5 -> BLARG_TROOPER_STATE_AIM: 002c5d50-002c5d8c checks animation completion and expired firing cooldown/count, sets a new cooldown and writes state 5 with animation 4, returning to established AIM. domain_25_value_5 -> BLARG_TROOPER_STATE_AIM: 002c5f80-002c5fbc checks melee animation completion, writes 5 to moby+0x20, sets cooldown and blends animation 4, returning to established AIM. domain_26_value_9 -> BLARG_TROOPER_STATE_BACKWARD_RECOVERY: 002c60d4-002c60e0 loads moby+0x20 and tests equality with 9 to select recovery-exit animation 9 rather than 0; this is the same selector as established BACKWARD_RECOVERY. domain_27_value_1 -> BLARG_TROOPER_STATE_IDLE: 002c60e4-002c610c blends the recovery-exit animation, stores 1 to moby+0x20 and sets the movement cooldown, returning to the established IDLE case. domain_28_value_1 -> BLARG_TROOPER_STATE_IDLE: Source current_state is assigned directly from moby->state; retail 002c6134-002c613c loads moby+0x20 and tests 1 to enable target-facing joints, reusing established IDLE. domain_29_value_3 -> BLARG_TROOPER_STATE_RUN_TO_TARGET_OR_PATH_POINT: Source current_state snapshots moby->state; retail 002c6134-002c6144 tests that same byte against 3 to enable target-facing joints, reusing the established running state. domain_2_value_11 -> BLARG_TROOPER_STATE_DYING: 002c4cac-002c4cf4 starts fatal knockback with animation 13 and stores 11 to moby+0x20; the established DYING switch case steps that motion toward removal. domain_30_value_4 -> BLARG_TROOPER_STATE_JUMP: Source current_state snapshots moby->state; retail 002c6134-002c614c tests that byte against 4 for target-facing joints, reusing the established JUMP case. domain_31_value_5 -> BLARG_TROOPER_STATE_AIM: Source current_state snapshots moby->state; retail 002c6134-002c6154 tests that byte against 5 for target-facing joints, reusing the established AIM case. domain_32_value_6 -> BLARG_TROOPER_STATE_FIRE: Source current_state snapshots moby->state; retail 002c6134-002c615c tests that byte against 6 for target-facing joints, reusing the established FIRE case. domain_3_value_8 -> BLARG_TROOPER_STATE_HIT_RECOVERY: 002c4d18-002c4d2c selects animation 8 after hit reaction 3/6 and stores 8 at moby+0x20, the exact field switched by the established HIT_RECOVERY case. domain_4_value_10 -> BLARG_TROOPER_STATE_KNOCKBACK_RECOVERY: 002c4dcc-002c4de8 selects animation 12 after hit reaction 4/5 and stores 10 at moby+0x20, selecting the established KNOCKBACK_RECOVERY case. domain_5_value_5 -> BLARG_TROOPER_STATE_AIM: 002c4f1c-002c4f40 initializes the ready animation 3 and writes 5 to moby+0x20 when pvars+0xFC is set; this field selects the established AIM case. domain_6_value_1 -> BLARG_TROOPER_STATE_IDLE: 002c4f44-002c4f74 chooses an initial idle animation 0/1 and stores 1 to moby+0x20; the same field selects established IDLE. domain_7_value_3 -> BLARG_TROOPER_STATE_RUN_TO_TARGET_OR_PATH_POINT: 002c5020-002c5028 branches on the flag to 002c5998; 002c59a8-002c59bc selects run animation 11 and stores 3 to moby+0x20, selecting the established running case. domain_8_value_2 -> BLARG_TROOPER_STATE_MOVE_TO_PATH_POINT: 002c5064-002c5078 branches on target distance greater than 14 to 002c5948; 002c5958-002c596c selects animation 10 and writes state 2, selecting established MOVE_TO_PATH_POINT. domain_9_value_3 -> BLARG_TROOPER_STATE_RUN_TO_TARGET_OR_PATH_POINT: 002c5080-002c50a0 checks distance below 8 and expired pvars+0x108, then 002c5998-002c59bc selects animation 11 and stores state 3 for the established running handler. --- src/overlays/l04/mobys/blarg_trooper.c | 60 +++++++++++++------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/overlays/l04/mobys/blarg_trooper.c b/src/overlays/l04/mobys/blarg_trooper.c index 63aad39590..f17d9cca5d 100644 --- a/src/overlays/l04/mobys/blarg_trooper.c +++ b/src/overlays/l04/mobys/blarg_trooper.c @@ -242,7 +242,7 @@ void blarg_trooper_update(struct Moby *moby) { target_distance = vector_distance_xy(pos, update_scratch.tgt); dmg = 0.0f; alive = compute_interpolated_record_value(moby); - if (moby->state != 0 && blarg_trooper_pvars->unk2E != 1) { + if (moby->state != BLARG_TROOPER_STATE_INITIALIZE && blarg_trooper_pvars->unk2E != 1) { char *o = blarg_trooper_pvars->gun_moby; if (o != 0) { mark_moby_for_removal(o); @@ -283,7 +283,7 @@ void blarg_trooper_update(struct Moby *moby) { r = hit_reaction(moby, hit, &blarg_trooper_pvars->health, 0, &hit_reaction_status, &dmg, 0, 4); fast_dec_timer_s16(&blarg_trooper_pvars->timer_F0); fast_dec_timer_s16(&blarg_trooper_pvars->timer_F2); - if (hit != 0 && moby->state < 0xB && blarg_trooper_pvars->timer_F0 == 0) { + if (hit != 0 && moby->state < BLARG_TROOPER_STATE_DYING && blarg_trooper_pvars->timer_F0 == 0) { char *o; float t; o = *(char **)(hit + 0x20); @@ -334,7 +334,7 @@ void blarg_trooper_update(struct Moby *moby) { fatal_knockback_yaw, moby, blarg_trooper_pvars->motion, 0xD, 1, 0); blarg_trooper_pvars->unkC0[0] = 12.0f; blarg_trooper_pvars->unkC0[1] = 25.0f; - moby->state = 0xB; + moby->state = BLARG_TROOPER_STATE_DYING; FUN_L00_00257470(moby, 0, -1); break; case BLARG_TROOPER_HIT_REACTION_START_HIT_RECOVERY: @@ -342,7 +342,7 @@ void blarg_trooper_update(struct Moby *moby) { int attacker_class; blarg_trooper_pvars->unk67 = 0x96; blend_moby_animation(moby, (void *)8, 0, (void *)scale_game_frames(5)); - moby->state = 8; + moby->state = BLARG_TROOPER_STATE_HIT_RECOVERY; attacker_class = *(short *)(*(char **)(hit + 0x20) + 0xA6); if (attacker_class == 0x131 || attacker_class == 0xB0) { blarg_trooper_pvars->unkF4 = 2.0f / scale_time(15.0f) * 0.5f; @@ -359,7 +359,7 @@ void blarg_trooper_update(struct Moby *moby) { case BLARG_TROOPER_HIT_REACTION_KNOCKBACK_RECOVERY: blarg_trooper_pvars->unk67 = 0xFA; blend_moby_animation(moby, (void *)0xC, 0, (void *)scale_game_frames(5)); - moby->state = 0xA; + moby->state = BLARG_TROOPER_STATE_KNOCKBACK_RECOVERY; blarg_trooper_pvars->unkF4 = 2.0f / scale_time(15.0f); *(OvlQuad *)update_scratch.w.p.v70 = *(OvlQuad *)(hit + 0x10); trooper_knockback_arc( @@ -405,11 +405,11 @@ void blarg_trooper_update(struct Moby *moby) { } if (blarg_trooper_pvars->unkFC != 0) { blend_moby_animation(moby, (void *)3, 0, (void *)scale_game_frames(0xA)); - moby->state = 5; + moby->state = BLARG_TROOPER_STATE_AIM; } else { blend_moby_animation( moby, (void *)((rand() ^ 1) & 1), 0, (void *)scale_game_frames(0xA)); - moby->state = 1; + moby->state = BLARG_TROOPER_STATE_IDLE; } break; case BLARG_TROOPER_STATE_IDLE: @@ -429,18 +429,18 @@ void blarg_trooper_update(struct Moby *moby) { } if (flag) { blend_moby_animation(moby, (void *)0xB, 0, (void *)scale_game_frames(8)); - moby->state = 3; + moby->state = BLARG_TROOPER_STATE_RUN_TO_TARGET_OR_PATH_POINT; break; } if (target_distance > 2.5f && best > 1.0f) { if (target_distance > 14.0f) { blend_moby_animation(moby, (void *)0xA, 0, (void *)scale_game_frames(8)); - moby->state = 2; + moby->state = BLARG_TROOPER_STATE_MOVE_TO_PATH_POINT; break; } if (target_distance < 8.0f && blarg_trooper_pvars->timer_108 == 0) { blend_moby_animation(moby, (void *)0xB, 0, (void *)scale_game_frames(8)); - moby->state = 3; + moby->state = BLARG_TROOPER_STATE_RUN_TO_TARGET_OR_PATH_POINT; break; } } @@ -454,14 +454,14 @@ void blarg_trooper_update(struct Moby *moby) { if (collision_line(update_scratch.w.p.v70, update_scratch.w.p.v80, 0, moby, 0) != 0 && D_L04_00173FD8 == target) { - moby->state = 5; + moby->state = BLARG_TROOPER_STATE_AIM; blend_moby_animation(moby, (void *)3, 0, (void *)scale_game_frames(7)); } } } else if (target_distance <= 2.5f) { int t = blarg_trooper_pvars->timer_F2; if (t <= 0) { - moby->state = 7; + moby->state = BLARG_TROOPER_STATE_MELEE_ATTACK; blend_moby_animation(moby, (void *)7, 0, (void *)scale_game_frames(7)); } else if (scale_game_frames(0x14) < t) { blarg_trooper_pvars->timer_F2 = scale_game_frames(0x14); @@ -471,7 +471,7 @@ void blarg_trooper_update(struct Moby *moby) { case BLARG_TROOPER_STATE_MOVE_TO_PATH_POINT: if (target_distance < 13.0f || best < 1.0f) { blend_moby_animation(moby, 0, 0, (void *)scale_game_frames(0xA)); - moby->state = 1; + moby->state = BLARG_TROOPER_STATE_IDLE; } else { float f; { @@ -544,11 +544,11 @@ void blarg_trooper_update(struct Moby *moby) { fast_arc_tan(update_scratch.v50[0] - moby->pos.x, update_scratch.v50[1] - moby->pos.y), moby->rot.z) < 0.2617994f) { - moby->state = 7; + moby->state = BLARG_TROOPER_STATE_MELEE_ATTACK; blend_moby_animation(moby, (void *)7, 0, (void *)scale_game_frames(7)); blarg_trooper_pvars->unkFF = 0; } else if (target_distance < 14.0f) { - moby->state = 5; + moby->state = BLARG_TROOPER_STATE_AIM; blend_moby_animation(moby, (void *)3, 0, (void *)scale_game_frames(7)); blarg_trooper_pvars->unkFF = 0; } @@ -558,14 +558,14 @@ void blarg_trooper_update(struct Moby *moby) { fast_difference_between_rotations(fast_arc_tan(update_scratch.v50[0] - moby->pos.x, update_scratch.v50[1] - moby->pos.y), moby->rot.z) < 0.2617994f) { - moby->state = 7; + moby->state = BLARG_TROOPER_STATE_MELEE_ATTACK; blend_moby_animation(moby, (void *)7, 0, (void *)scale_game_frames(7)); } else if (target_distance > 9.0f) { - moby->state = 5; + moby->state = BLARG_TROOPER_STATE_AIM; blend_moby_animation(moby, (void *)3, 0, (void *)scale_game_frames(7)); } else if (best < 1.0f) { blend_moby_animation(moby, 0, 0, (void *)scale_game_frames(0xA)); - moby->state = 1; + moby->state = BLARG_TROOPER_STATE_IDLE; } else { { float a = fast_arc_tan(update_scratch.v60[0] - moby->pos.x, @@ -592,7 +592,7 @@ void blarg_trooper_update(struct Moby *moby) { blarg_trooper_pvars->unkD0[0] = -(frame_time * 7.668f); } else if (moby->anim_flags & 2) { blend_moby_animation(moby, 0, 0, (void *)scale_game_frames(0xA)); - moby->state = 1; + moby->state = BLARG_TROOPER_STATE_IDLE; } break; case BLARG_TROOPER_STATE_AIM: { @@ -611,17 +611,17 @@ void blarg_trooper_update(struct Moby *moby) { if (!flag && target_distance > 2.5f && best > 1.0f) { if (target_distance > 14.0f) { blend_moby_animation(moby, (void *)0xA, 0, (void *)scale_game_frames(9)); - moby->state = 2; + moby->state = BLARG_TROOPER_STATE_MOVE_TO_PATH_POINT; break; } if (target_distance < 8.0f && blarg_trooper_pvars->timer_108 == 0) { blend_moby_animation(moby, (void *)0xB, 0, (void *)scale_game_frames(5)); - moby->state = 3; + moby->state = BLARG_TROOPER_STATE_RUN_TO_TARGET_OR_PATH_POINT; break; } } if (target_distance < 2.5f) { - moby->state = 7; + moby->state = BLARG_TROOPER_STATE_MELEE_ATTACK; blend_moby_animation(moby, (void *)7, 0, (void *)scale_game_frames(7)); break; } @@ -636,7 +636,7 @@ void blarg_trooper_update(struct Moby *moby) { moby->rot.z, fast_arc_tan(update_scratch.v50[0] - moby->pos.x, update_scratch.v50[1] - moby->pos.y)) < 0.7853982f) { - moby->state = 6; + moby->state = BLARG_TROOPER_STATE_FIRE; blend_moby_animation(moby, (void *)5, 0, (void *)scale_game_frames(7)); blarg_trooper_pvars->timer_F2 = scale_game_frames(0x1E); blarg_trooper_pvars->unkFD = 3; @@ -662,7 +662,7 @@ void blarg_trooper_update(struct Moby *moby) { frame_time * 4.712389f); } if (target_distance < 2.5f) { - moby->state = 7; + moby->state = BLARG_TROOPER_STATE_MELEE_ATTACK; blend_moby_animation(moby, (void *)7, 0, (void *)scale_game_frames(7)); } if (moby->prev_seq == 5 && blarg_trooper_pvars->unkD0[2] < 2.0f && alive >= 2.0f && @@ -686,7 +686,7 @@ void blarg_trooper_update(struct Moby *moby) { } else if ((moby->anim_flags & 2) && blarg_trooper_pvars->timer_F2 == 0 && blarg_trooper_pvars->unkFD == 0) { blarg_trooper_pvars->timer_F2 = scale_game_frames(0xB4); - moby->state = 5; + moby->state = BLARG_TROOPER_STATE_AIM; blend_moby_animation(moby, (void *)4, 0, (void *)scale_game_frames(0xA)); } break; @@ -726,7 +726,7 @@ void blarg_trooper_update(struct Moby *moby) { } } if (moby->anim_flags & 2) { - moby->state = 5; + moby->state = BLARG_TROOPER_STATE_AIM; blarg_trooper_pvars->timer_F2 = scale_game_frames(0x14); blend_moby_animation(moby, (void *)4, 0, (void *)scale_game_frames(7)); } @@ -748,8 +748,8 @@ void blarg_trooper_update(struct Moby *moby) { if (moby->anim_flags & 2) { *(unsigned short *)&blarg_trooper_pvars->path_selector ^= 1; blend_moby_animation( - moby, (void *)(moby->state == 9 ? 9 : 0), 0, (void *)scale_game_frames(9)); - moby->state = 1; + moby, (void *)(moby->state == BLARG_TROOPER_STATE_BACKWARD_RECOVERY ? 9 : 0), 0, (void *)scale_game_frames(9)); + moby->state = BLARG_TROOPER_STATE_IDLE; blarg_trooper_pvars->timer_108 = scale_game_frames(0x78); } break; @@ -763,8 +763,8 @@ void blarg_trooper_update(struct Moby *moby) { trooper_anim_finish(moby, &blarg_trooper_pvars->anim_state); { int current_state = moby->state; - if (current_state == 1 || current_state == 3 || current_state == 4 || current_state == 5 || - current_state == 6) { + if (current_state == BLARG_TROOPER_STATE_IDLE || current_state == BLARG_TROOPER_STATE_RUN_TO_TARGET_OR_PATH_POINT || current_state == BLARG_TROOPER_STATE_JUMP || current_state == BLARG_TROOPER_STATE_AIM || + current_state == BLARG_TROOPER_STATE_FIRE) { char *t = target; if (t == 0) { t = *(char **)((char *)(&hero.moby)); From 0ff7427006a6ee048684d6bd9762f76e7e972df5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:31:17 +0000 Subject: [PATCH 1129/1502] decomp: clarify names in toxic_crab_update domain_10_value_5 -> TOXIC_CRAB_STATE_PURSUE_TARGET: 0x002e2440-0x002e2488: Countdown expiry enters 5 and resets pursuit motion. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_11_value_1 -> HERO_VEHICLE_MODE_CLANK: 0x002e27b0-0x002e27bc: retail loads the byte at 0x001413f4 (hero base 0x0013f350 plus 0x20a4), identified by authoritative typed C as hero.vehicle_mode, and suppresses translational pursuit movement in mode 1. This is the HeroVehicleMode selector, so reuse its supplied canonical member HERO_VEHICLE_MODE_CLANK=1, independently of the crab state enum. domain_12_value_6 -> TOXIC_CRAB_STATE_PAUSE_PURSUIT: 0x002e2894-0x002e28b4: A nearby sight-line obstruction enters 6 with a 60-frame timer. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_13_value_6 -> TOXIC_CRAB_STATE_PAUSE_PURSUIT: 0x002e2984-0x002e29c8: Insufficient pursuit travel while aligned enters 6 with a 60-frame timer. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_14_value_5 -> TOXIC_CRAB_STATE_PURSUE_TARGET: 0x002e2a40-0x002e2a58: The animation-resumption guard compares current moby state against 5. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_15_value_1 -> HERO_VEHICLE_MODE_CLANK: 0x002e2b44-0x002e2b68: retail loads the byte at 0x001413f4 (hero base 0x0013f350 plus 0x20a4), identified by authoritative typed C as hero.vehicle_mode, and selects the one-unit home leash in mode 1. This is the HeroVehicleMode selector, so reuse its supplied canonical member HERO_VEHICLE_MODE_CLANK=1, independently of the crab state enum. domain_16_value_8 -> TOXIC_CRAB_STATE_RETURN_HOME: 0x002e2b34-0x002e2b9c: Excess distance from saved home data+0x170 or target-control 2 enters 8. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_17_value_7 -> TOXIC_CRAB_STATE_MELEE_ATTACK: 0x002e2c10-0x002e2c70: Proximity, heading, sight and vulnerability checks enter 7 with attack animation 6/7. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_18_value_5 -> TOXIC_CRAB_STATE_PURSUE_TARGET: 0x002e2db4-0x002e2de0: Clear obstruction recheck resumes 5 and resets pursuit motion. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_19_value_1 -> HERO_VEHICLE_MODE_CLANK: 0x002e2df0-0x002e2e1c: retail loads the byte at 0x001413f4 (hero base 0x0013f350 plus 0x20a4), identified by authoritative typed C as hero.vehicle_mode, and selects the one-unit home leash in mode 1 during pursuit pause. This is the HeroVehicleMode selector, so reuse its supplied canonical member HERO_VEHICLE_MODE_CLANK=1, independently of the crab state enum. domain_20_value_8 -> TOXIC_CRAB_STATE_RETURN_HOME: 0x002e2de4-0x002e2e50: Pause handling enters 8 when beyond saved-home distance or target-control 2. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_21_value_7 -> TOXIC_CRAB_STATE_MELEE_ATTACK: 0x002e2ed0-0x002e2f48: Pause handling enters 7 after proximity, sight and heading gates. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_22_value_8 -> TOXIC_CRAB_STATE_RETURN_HOME: 0x002e3148-0x002e31b0: Completed melee enters 8 when beyond home distance or target-control 2. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_23_value_5 -> TOXIC_CRAB_STATE_PURSUE_TARGET: 0x002e31c4-0x002e31d8: Completed melee otherwise enters 5 and resets pursuit motion. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_24_value_7 -> TOXIC_CRAB_STATE_MELEE_ATTACK: 0x002e3318-0x002e3348 and 0x002e3524-0x002e3574: Back-away timer/distance completion enters 7 and chooses attack animation 6/7. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_25_value_3 -> TOXIC_CRAB_STATE_FACE_TRACKED_POSITION: 0x002e3478-0x002e34a0: Return-home distance below one enters 3, whose handler turns to data+0x120/+0x124. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_26_value_5 -> TOXIC_CRAB_STATE_PURSUE_TARGET: 0x002e34bc-0x002e34e0: Return-home handler enters 5 when target-control is no longer 2 and resets pursuit motion. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_27_value_7 -> TOXIC_CRAB_STATE_MELEE_ATTACK: 0x002e350c-0x002e352c: Knockback motion collision flags 0x41 lead to 7 and attack animation selection. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_28_value_12 -> TOXIC_CRAB_STATE_FALL_TO_DEATH: 0x002e3580-0x002e35ec: Knockback dropping below saved home height enters 12 and reduces vertical motion. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_29_value_11 -> TOXIC_CRAB_STATE_DEATH_EFFECTS: 0x002e3640-0x002e3680: Fall ground/material handling stores 11 before initializing death knockback; case 11 emits effects and removes. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_2_value_1 -> TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION: 0x002e20f0-0x002e20fc: Initialization stores 1 to moby+0x20 before selecting idle animation 0. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_30_value_3 -> TOXIC_CRAB_STATE_FACE_TRACKED_POSITION: 0x002e391c-0x002e3924: Post-dispatch gravity guard compares the same current state against 3. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_31_value_5 -> TOXIC_CRAB_STATE_PURSUE_TARGET: 0x002e3928-0x002e392c: Post-dispatch gravity guard compares the same current state against 5. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_32_value_7 -> TOXIC_CRAB_STATE_MELEE_ATTACK: 0x002e3930-0x002e3934: Post-dispatch gravity guard compares the same current state against 7. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_33_value_8 -> TOXIC_CRAB_STATE_RETURN_HOME: 0x002e3938-0x002e393c: Post-dispatch gravity guard compares the same current state against 8. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_34_value_12 -> TOXIC_CRAB_STATE_FALL_TO_DEATH: 0x002e39bc-0x002e3a0c: Ground height below saved home height minus two enters 12 with falling animation. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_5_value_2 -> TOXIC_CRAB_STATE_ACTIVATE: 0x002e21d4-0x002e21e4: Linked moby validity/save checks store 2 and seed the activation timer. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_6_value_2 -> TOXIC_CRAB_STATE_ACTIVATE: 0x002e2204-0x002e2228: Target-control checks store 2 and seed the activation timer. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_7_value_5 -> TOXIC_CRAB_STATE_PURSUE_TARGET: 0x002e2318-0x002e2354: Activation completion enters 5, clears blocked motion and saves pursuit position. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_8_value_3 -> TOXIC_CRAB_STATE_FACE_TRACKED_POSITION: 0x002e2380-0x002e2390: Activation completion outside the proximity threshold enters 3. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. domain_9_value_4 -> TOXIC_CRAB_STATE_WAIT_TO_PURSUE: 0x002e2408-0x002e243c: Tracked-position facing enters 4 and seeds a random countdown. The store/comparison uses m->state at moby+0x20, the identical selector dispatched at 0x002e1f48-0x002e1f68 and already named by the function-local TOXIC_CRAB_STATE enum; reuse that existing member. --- src/overlays/l10/mobys/toxic_crab.c | 56 ++++++++++++++--------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/overlays/l10/mobys/toxic_crab.c b/src/overlays/l10/mobys/toxic_crab.c index 2257488f1f..8c378bdf74 100644 --- a/src/overlays/l10/mobys/toxic_crab.c +++ b/src/overlays/l10/mobys/toxic_crab.c @@ -303,7 +303,7 @@ void toxic_crab_update(Moby2E30F8 *m) { } } } - m->state = 1; + m->state = TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION; if (m->anim != 0) { blend_moby_animation(m, 0, 0, 0); } @@ -320,7 +320,7 @@ void toxic_crab_update(Moby2E30F8 *m) { (((short)p->id >> 5) * 4 + (current_level_index << 8))) >> (p->id & 0x1F)) & 1)) { - m->state = 2; + m->state = TOXIC_CRAB_STATE_ACTIVATE; crab_data->i1A8 = scale_game_frames(1); if (m->b21 != 0xFF) { activate_waiting_moby_group_members((struct Moby *)m); @@ -328,7 +328,7 @@ void toxic_crab_update(Moby2E30F8 *m) { } } if (crab_data->i164 != 2 || crab_data->i1B4 != 0) { - m->state = 2; + m->state = TOXIC_CRAB_STATE_ACTIVATE; crab_data->i1A8 = scale_game_frames(1); if (m->b21 != 0xFF) { activate_waiting_moby_group_members((struct Moby *)m); @@ -354,7 +354,7 @@ void toxic_crab_update(Moby2E30F8 *m) { } else if (m->b70 & 2) { if (vector_distance_xy(m->pos, &hero.motion.pos) < *(float *)&D_L10_00161E40_gp) { float x; - m->state = 5; + m->state = TOXIC_CRAB_STATE_PURSUE_TARGET; crab_data->i1D8 = 0; qcopy(crab_data->v1C0, m->pos); crab_data->fF4 = 0.0f; @@ -364,7 +364,7 @@ void toxic_crab_update(Moby2E30F8 *m) { blend_moby_animation(m, 3, 0, scale_game_frames(5)); } } else { - m->state = 3; + m->state = TOXIC_CRAB_STATE_FACE_TRACKED_POSITION; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(10)); } @@ -375,7 +375,7 @@ void toxic_crab_update(Moby2E30F8 *m) { float ang = fast_arc_tan(crab_data->f120 - m->pos[0], crab_data->f124 - m->pos[1]); FUN_L00_00258278((char *)m, &crab_data->f190, ang, 0.02f, 0.3f, frame_time * 6.2831855f); if (crab_data->i164 != 2) { - m->state = 4; + m->state = TOXIC_CRAB_STATE_WAIT_TO_PURSUE; crab_data->i1A8 = truncate_float_to_s32(random_float_between(0.0f, (float)crab_data->i1B8)); } @@ -384,7 +384,7 @@ void toxic_crab_update(Moby2E30F8 *m) { case TOXIC_CRAB_STATE_WAIT_TO_PURSUE: if (fast_dec_timer(&crab_data->i1A8)) { float x; - m->state = 5; + m->state = TOXIC_CRAB_STATE_PURSUE_TARGET; crab_data->i1D8 = 0; qcopy(crab_data->v1C0, m->pos); crab_data->fF4 = 0.0f; @@ -440,7 +440,7 @@ void toxic_crab_update(Moby2E30F8 *m) { v[1] = fast_sin(aim) * (MOBY(target_moby)->oclass == 0x359 ? 2.0f : 3.57f); v[2] = 0.0f; fast_vec_add(v, v, target_moby + 0x10); - if (hero.vehicle_mode != 1) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_CLANK) { float rot = m->f48; int r; m->f48 = fast_arc_tan(v[0] - m->pos[0], v[1] - m->pos[1]); @@ -461,7 +461,7 @@ void toxic_crab_update(Moby2E30F8 *m) { *(short *)(*(char **)(h + 0x18) + 0xA6) != 0x31A) && fast_vec_dist(from2, h + 0x20) < toxic_crab_obstacle_pause_distance_gp) { - m->state = 6; + m->state = TOXIC_CRAB_STATE_PAUSE_PURSUIT; crab_data->i1A8 = scale_game_frames(0x3C); if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(7)); @@ -481,7 +481,7 @@ void toxic_crab_update(Moby2E30F8 *m) { if (D_L10_0015F5CC % 7 == 0 && crab_data->i1A8 == 0) { if (vector_distance_xy(crab_data->v1C0, m->pos) < crab_data->fF4 && diff <= toxic_crab_pursuit_heading_threshold_degrees_gp * DEG_TO_RAD) { - m->state = 6; + m->state = TOXIC_CRAB_STATE_PAUSE_PURSUIT; crab_data->i1A8 = scale_game_frames(0x3C); if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(7)); @@ -494,7 +494,7 @@ void toxic_crab_update(Moby2E30F8 *m) { } else { crab_data->i1D8 = 0; } - if (m->state == 5 && fast_dec_timer(&crab_data->i1A8) && 0.0f < crab_data->fF4 && + if (m->state == TOXIC_CRAB_STATE_PURSUE_TARGET && fast_dec_timer(&crab_data->i1A8) && 0.0f < crab_data->fF4 && crab_data->i1D8 == 0 && m->anim == 1) { blend_moby_animation(m, 3, 0, scale_game_frames(7)); } @@ -512,8 +512,8 @@ void toxic_crab_update(Moby2E30F8 *m) { m->f58 = 1.2f; { float home = fast_vec_dist(m->pos, crab_data->v170); - if ((hero.vehicle_mode == 1 ? 1.0f : 30.0f) < home || crab_data->i164 == 2) { - m->state = 8; + if ((hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK ? 1.0f : 30.0f) < home || crab_data->i164 == 2) { + m->state = TOXIC_CRAB_STATE_RETURN_HOME; blend_moby_animation(m, 4, 0, scale_game_frames(0xC)); } else if (vector_distance_xy(m->pos, target_moby + 0x10) < (MOBY(target_moby)->oclass == 0x359 ? 2.45f : 4.02f)) { @@ -523,7 +523,7 @@ void toxic_crab_update(Moby2E30F8 *m) { if (random_integer_below(100) & 1) { anim = 6; } - m->state = 7; + m->state = TOXIC_CRAB_STATE_MELEE_ATTACK; blend_moby_animation(m, anim, 0, scale_game_frames(7)); } } @@ -561,7 +561,7 @@ void toxic_crab_update(Moby2E30F8 *m) { } } if (ok) { - m->state = 5; + m->state = TOXIC_CRAB_STATE_PURSUE_TARGET; crab_data->i1D8 = 0; qcopy(crab_data->v1C0, m->pos); crab_data->fF4 = 0.0f; @@ -570,8 +570,8 @@ void toxic_crab_update(Moby2E30F8 *m) { } { float home = fast_vec_dist(m->pos, crab_data->v170); - if ((hero.vehicle_mode == 1 ? 1.0f : 30.0f) < home || crab_data->i164 == 2) { - m->state = 8; + if ((hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK ? 1.0f : 30.0f) < home || crab_data->i164 == 2) { + m->state = TOXIC_CRAB_STATE_RETURN_HOME; blend_moby_animation(m, 4, 0, scale_game_frames(0xC)); } else if (vector_distance_xy(m->pos, target_moby + 0x10) < (MOBY(target_moby)->oclass == 0x359 ? 2.45f : 4.02f)) { @@ -581,7 +581,7 @@ void toxic_crab_update(Moby2E30F8 *m) { if (random_integer_below(100) & 1) { anim = 6; } - m->state = 7; + m->state = TOXIC_CRAB_STATE_MELEE_ATTACK; blend_moby_animation(m, anim, 0, scale_game_frames(7)); } } @@ -629,10 +629,10 @@ void toxic_crab_update(Moby2E30F8 *m) { float home = fast_vec_dist(m->pos, crab_data->v170); if ((((unsigned char *)&D_0013E533)[0x2EC1] == 1 ? 1.0f : 30.0f) < home || crab_data->i164 == 2) { - m->state = 8; + m->state = TOXIC_CRAB_STATE_RETURN_HOME; blend_moby_animation(m, 4, 0, scale_game_frames(0xC)); } else { - m->state = 5; + m->state = TOXIC_CRAB_STATE_PURSUE_TARGET; crab_data->i1D8 = 0; qcopy(crab_data->v1C0, m->pos); crab_data->fF4 = 0.0f; @@ -670,7 +670,7 @@ void toxic_crab_update(Moby2E30F8 *m) { toxic_crab_back_away_distance_limit_gp < fast_vec_dist(m->pos, target_moby + 0x10)) { int anim; - m->state = 7; + m->state = TOXIC_CRAB_STATE_MELEE_ATTACK; crab_data->fF4 = frame_time * 5.0f; anim = 7; if (random_integer_below(100) & 1) { @@ -703,12 +703,12 @@ void toxic_crab_update(Moby2E30F8 *m) { dir[2] = 0.0f; FUN_L00_00258b50(m, &crab_data->iD0, dir, out, 1.0f); if (fast_vec_dist(m->pos, crab_data->v170) < 1.0f) { - m->state = 3; + m->state = TOXIC_CRAB_STATE_FACE_TRACKED_POSITION; if (m->anim != 1) { blend_moby_animation(m, 1, 0, scale_game_frames(0x14)); } } else if (crab_data->i164 != 2) { - m->state = 5; + m->state = TOXIC_CRAB_STATE_PURSUE_TARGET; crab_data->i1D8 = 0; qcopy(crab_data->v1C0, m->pos); crab_data->fF4 = 0.0f; @@ -722,7 +722,7 @@ void toxic_crab_update(Moby2E30F8 *m) { case TOXIC_CRAB_STATE_HIT_KNOCKBACK: if (step_moby_motion(m, crab_data->v70) & 0x41) { int anim; - m->state = 7; + m->state = TOXIC_CRAB_STATE_MELEE_ATTACK; crab_data->fF4 = frame_time * 5.0f; anim = 7; if (random_integer_below(100) & 1) { @@ -733,7 +733,7 @@ void toxic_crab_update(Moby2E30F8 *m) { if (m->anim != 0xE) { blend_moby_animation(m, 0xE, 0, scale_game_frames(6)); } - m->state = 0xC; + m->state = TOXIC_CRAB_STATE_FALL_TO_DEATH; crab_data->f78 = crab_data->f78 / 3.0f; } break; @@ -754,7 +754,7 @@ void toxic_crab_update(Moby2E30F8 *m) { return; } m->s34 &= 0xEFFF; - m->state = 0xB; + m->state = TOXIC_CRAB_STATE_DEATH_EFFECTS; knockback_collision_radius_fixed = truncate_float_to_s32(768.0f); x = toxic_crab_death_knockback_gravity_gp * frame_time_sq; crab_data->bAD = 0; @@ -806,7 +806,7 @@ void toxic_crab_update(Moby2E30F8 *m) { } } } - if (m->state == 3 || m->state == 5 || m->state == 7 || m->state == 8) { + if (m->state == TOXIC_CRAB_STATE_FACE_TRACKED_POSITION || m->state == TOXIC_CRAB_STATE_PURSUE_TARGET || m->state == TOXIC_CRAB_STATE_MELEE_ATTACK || m->state == TOXIC_CRAB_STATE_RETURN_HOME) { float ground_height = probe_ground_height(m->pos, 0, 0.5f); if (ground_height < m->pos[2]) { crab_data->f78 = crab_data->f78 - crab_data->f80; @@ -821,7 +821,7 @@ void toxic_crab_update(Moby2E30F8 *m) { if (m->anim != 0xE) { blend_moby_animation(m, 0xE, 0, scale_game_frames(6)); } - m->state = 0xC; + m->state = TOXIC_CRAB_STATE_FALL_TO_DEATH; } } } From bf6371eea0b85ce42f3f6285e754af1156953f18 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:33:08 +0000 Subject: [PATCH 1130/1502] decomp: clarify names in robosquawker_update domain_0_value_0 -> ROBOSQUAWKER_STATE_INITIALIZE: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b5248-002b5258: The nonzero state check skips timer-based range restoration during initialization. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_10_value_14 -> ROBOSQUAWKER_STATE_FLIGHT_IDLE: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b5b68-002b5bb0: Random-point flight collision clears movement and returns to flight idle. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_11_value_14 -> ROBOSQUAWKER_STATE_FLIGHT_IDLE: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b5bbc-002b5c24: Random-point flight finishes when remaining distance is below step length or the step is zero. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_12_value_15 -> ROBOSQUAWKER_STATE_FLY_TO_RANDOM_POINT: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b5d24-002b5e1c: Path-flight collision samples a new home-relative destination and enters random-point flight. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_13_value_17 -> ROBOSQUAWKER_STATE_LAND: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b5eec-002b5f88: At a flight waypoint, target proximity and height gates clear velocity and enter landing. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_14_value_17 -> ROBOSQUAWKER_STATE_LAND: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b5f94-002b6074: The path-flight command/random branch clears velocity, releases the particle and enters landing. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_15_value_3 -> ROBOSQUAWKER_STATE_CHASE_TARGET: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b6168-002b61e8: Landing clamps Z to ground, resets steering and selects chase with animation 5. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_16_value_14 -> ROBOSQUAWKER_STATE_FLIGHT_IDLE: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b62ec-002b633c: Takeoff reaches ground plus six, clamps altitude and enters flight idle. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_17_value_2 -> ROBOSQUAWKER_STATE_FACE_AWAY_WAIT_FOR_CHASE: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b6354-002b63e0: Ground idle passes proximity, height and random gates to enter the existing face-away waiting case. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_18_value_3 -> ROBOSQUAWKER_STATE_CHASE_TARGET: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b6428-002b6490: Ground idle command branch initializes steering and chase timer before selecting chase. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_19_value_16 -> ROBOSQUAWKER_STATE_TAKEOFF: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b64c4-002b650c: Ground idle detects a distant target with flight enabled, zeros velocity and enters takeoff. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_1_value_99 -> ROBOSQUAWKER_STATE_DEATH_KNOCKBACK: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b52cc-002b52dc: The hit-processing gate excludes the lethal knockback state. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_20_value_2 -> ROBOSQUAWKER_STATE_FACE_AWAY_WAIT_FOR_CHASE: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b6528-002b65c4: Close-target waiting passes tighter range and height gates, raises Z by one and enters face-away waiting. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_21_value_11 -> ROBOSQUAWKER_STATE_HOME_HOP: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b6714-002b67a8: Home-directed ballistic setup and motion startup precede the home-hop state store. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_22_value_3 -> ROBOSQUAWKER_STATE_CHASE_TARGET: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b67ac-002b67e0: Home-hop motion completion clears the motion record and resumes chase. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_23_value_3 -> ROBOSQUAWKER_STATE_CHASE_TARGET: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b68f0-002b6a00: Face-away waiting target gates reset steering and timer before entering chase. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_24_value_3 -> ROBOSQUAWKER_STATE_CHASE_TARGET: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b6978-002b6a00: Face-away waiting command/random gate shares steering reset and the chase state store. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_25_value_4 -> ROBOSQUAWKER_STATE_PECK_ATTACK: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b6be0-002b6c6c: Chase reaches attack range without movement-block bit 2 and selects peck attack with animation 6. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_26_value_5 -> ROBOSQUAWKER_STATE_RETURN_HOME: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b6cc8-002b6d48: Chase loses the home-relative target range/height gate and selects return home. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_27_value_3 -> ROBOSQUAWKER_STATE_CHASE_TARGET: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b6f44-002b6f84: Peck attack animation completion with target beyond 1.5 resumes chase. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_28_value_1 -> ROBOSQUAWKER_STATE_GROUND_IDLE: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b7104-002b7138: Return-home movement reaches within two XY units of saved home and selects ground idle. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_29_value_3 -> ROBOSQUAWKER_STATE_CHASE_TARGET: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b7158-002b71c4: Return-home detects target inside the saved-home radius and resumes chase. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_2_value_99 -> ROBOSQUAWKER_STATE_DEATH_KNOCKBACK: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b53ac-002b5470: Health at vars+0x20 falls to zero or below; lethal arc startup precedes this state store. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_30_value_3 -> ROBOSQUAWKER_STATE_CHASE_TARGET: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b71a4-002b71c4: Return-home command byte 1 also takes the shared chase state store. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_31_value_12 -> ROBOSQUAWKER_STATE_BLOCKED_RETURN_HOME: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b71ec-002b7210: Return-home movement bit 2 restores previous XY and enters the blocked-return case. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_32_value_3 -> ROBOSQUAWKER_STATE_CHASE_TARGET: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b7244-002b7274: Surviving damage motion completes, clears the motion vector and resumes chase. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_33_value_14 -> ROBOSQUAWKER_STATE_FLIGHT_IDLE: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b72cc-002b730c: Recovery motion helper completes, restoring animation 0 and selecting flight idle. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_34_value_4 -> ROBOSQUAWKER_STATE_PECK_ATTACK: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b74f0-002b7534: Blocked return finds target within 1.5 XY units with acceptable vertical ratio and selects peck attack. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_35_value_5 -> ROBOSQUAWKER_STATE_RETURN_HOME: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b7550-002b7584: Blocked return sees acceptable vertical ratio and no movement-block bit 2 and retries return home. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_36_value_16 -> ROBOSQUAWKER_STATE_TAKEOFF: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b75f0-002b7614: Blocked return passes a random gate, clears velocity and selects takeoff. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_38_value_5 -> ROBOSQUAWKER_STATE_RETURN_HOME: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b7838-002b7878: Forward avoidance leaves its anchor-distance bound or lacks an anchor and selects return home. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_3_value_6 -> ROBOSQUAWKER_STATE_DAMAGE_KNOCKBACK: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b54a0-002b550c: The surviving-health branch starts damage motion and stores this state. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_4_value_1 -> ROBOSQUAWKER_STATE_GROUND_IDLE: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b5570-002b558c: Initialization with nonzero vars+0x20A selects ground idle and animation 3. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_5_value_14 -> ROBOSQUAWKER_STATE_FLIGHT_IDLE: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b55ac-002b55cc: Initialization raises Z by six and selects the established flight idle case. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_6_value_17 -> ROBOSQUAWKER_STATE_LAND: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b5700-002b5798: Flight idle gates on target distance and height, releases its particle and selects descending landing. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_7_value_17 -> ROBOSQUAWKER_STATE_LAND: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b57a4-002b5880: Flight idle command/random gate resets steering, clears movement and enters landing. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_8_value_18 -> ROBOSQUAWKER_STATE_FOLLOW_FLIGHT_PATH: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b5884-002b5918: Flight idle copies the indexed walker path waypoint into vars+0x1E0 and enters path following. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. domain_9_value_15 -> ROBOSQUAWKER_STATE_FLY_TO_RANDOM_POINT: Authoritative robosquawker.c SHA-256 6a81299453846cf015ea9583d245d2e4966374c0a7f5b7bc4cbf29608dc41406 and original retail Ghidra agree at 002b591c-002b5a2c: Flight idle samples offsets around saved home into vars+0x1E0 and selects random-point flight. The token reads/writes robosquawker_moby->state, retail s2+0x20, whose load at 002b5530 selects the same function's existing ROBOSQUAWKER_STATE enum switch; reuse its canonical equal-valued member. --- src/overlays/l13/mobys/robosquawker.c | 76 +++++++++++++-------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/overlays/l13/mobys/robosquawker.c b/src/overlays/l13/mobys/robosquawker.c index f6b5af95ee..fbb2b3a157 100644 --- a/src/overlays/l13/mobys/robosquawker.c +++ b/src/overlays/l13/mobys/robosquawker.c @@ -513,7 +513,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { } robosquawker_vars->w38 = 0; fast_dec_timer_s16(&robosquawker_vars->h208); - if (robosquawker_moby->state != 0) { + if (robosquawker_moby->state != ROBOSQUAWKER_STATE_INITIALIZE) { if (fast_dec_timer_s16(&robosquawker_vars->h214) != 0) { robosquawker_vars->f1FC = robosquawker_vars->v1D0.f[3]; } else { @@ -526,7 +526,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { robosquawker_moby, hit, &robosquawker_vars->f20, 0, &hits, &dmg, 0, 4); fast_dec_timer_s16(&robosquawker_vars->h26); if (robosquawker_vars->h26 < scale_game_frames(0x2D) && hit != 0 && - robosquawker_moby->state != 0x63) { + robosquawker_moby->state != ROBOSQUAWKER_STATE_DEATH_KNOCKBACK) { if (hit->src->hA6 >= 0xB0 && hit->src->hA6 <= 0xB1 && robosquawker_vars->h26 != 0) { hit->f2C = 0.0f; } @@ -562,7 +562,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { 0); robosquawker_vars->f170 = 11.0f; robosquawker_vars->f174 = 18.0f; - robosquawker_moby->state = 0x63; + robosquawker_moby->state = ROBOSQUAWKER_STATE_DEATH_KNOCKBACK; release_robosquawker_particle((Level13VendorMoby *)robosquawker_vars); robosquawker_vars->x110[7] = 0x78; trooper_anim_update(robosquawker_moby, (short *)robosquawker_vars->x110); @@ -579,7 +579,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { 0); robosquawker_vars->f170 = 5.0f; robosquawker_vars->f174 = 10.0f; - robosquawker_moby->state = 6; + robosquawker_moby->state = ROBOSQUAWKER_STATE_DAMAGE_KNOCKBACK; release_robosquawker_particle((Level13VendorMoby *)robosquawker_vars); *(unsigned char *)&robosquawker_vars->x110[7] = 0xFA; robosquawker_vars->h26 = scale_game_frames(0x3C); @@ -593,12 +593,12 @@ void robosquawker_update(RsMoby *robosquawker_moby) { qcopy(&robosquawker_vars->v1D0, &robosquawker_moby->pos); robosquawker_vars->v1D0.f[3] = robosquawker_vars->f1FC; if (robosquawker_vars->h20A != 0) { - robosquawker_moby->state = 1; + robosquawker_moby->state = ROBOSQUAWKER_STATE_GROUND_IDLE; if (robosquawker_moby->b53 != 3) { blend_moby_animation(robosquawker_moby, 3, 0, 0); } } else { - robosquawker_moby->state = 0xE; + robosquawker_moby->state = ROBOSQUAWKER_STATE_FLIGHT_IDLE; robosquawker_moby->pos.f[2] += 6.0f; if (robosquawker_moby->b53 != 0) { blend_moby_animation(robosquawker_moby, 0, 0, 0); @@ -638,7 +638,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { if (robosquawker_moby->b53 != 0) { blend_moby_animation(robosquawker_moby, 0, 0, scale_game_frames(3)); } - robosquawker_moby->state = 0x11; + robosquawker_moby->state = ROBOSQUAWKER_STATE_LAND; release_robosquawker_particle((Level13VendorMoby *)robosquawker_vars); } else if (d > 1.0f && robosquawker_moby->bBC == 1 && random_integer_below(4) == 0) { if (random_integer_below(0x100) & 1) { @@ -650,7 +650,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { blend_moby_animation(robosquawker_moby, 0, 0, scale_game_frames(3)); } release_robosquawker_particle((Level13VendorMoby *)robosquawker_vars); - robosquawker_moby->state = 0x11; + robosquawker_moby->state = ROBOSQUAWKER_STATE_LAND; clear_u64_value(&robosquawker_vars->v40); robosquawker_moby->bBC = 0; } else if (robosquawker_vars->w220 != -1) { @@ -665,7 +665,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { } } qcopy(&robosquawker_vars->v1E0, path + robosquawker_vars->w224 * 16 + 16); - robosquawker_moby->state = 0x12; + robosquawker_moby->state = ROBOSQUAWKER_STATE_FOLLOW_FLIGHT_PATH; } else if (fast_dec_timer(&robosquawker_vars->w20C) != 0) { int i; @@ -688,7 +688,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { if (robosquawker_moby->b53 != 0) { blend_moby_animation(robosquawker_moby, 0, 0, scale_game_frames(3)); } - robosquawker_moby->state = 0xF; + robosquawker_moby->state = ROBOSQUAWKER_STATE_FLY_TO_RANDOM_POINT; } break; } @@ -714,7 +714,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { if (robosquawker_moby->b53 != 0) { blend_moby_animation(robosquawker_moby, 0, 0, scale_game_frames(3)); } - robosquawker_moby->state = 0xE; + robosquawker_moby->state = ROBOSQUAWKER_STATE_FLIGHT_IDLE; } else { qcopy(&robosquawker_moby->pos, &va); } @@ -723,7 +723,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { if (robosquawker_moby->b53 != 0) { blend_moby_animation(robosquawker_moby, 0, 0, scale_game_frames(3)); } - robosquawker_moby->state = 0xE; + robosquawker_moby->state = ROBOSQUAWKER_STATE_FLIGHT_IDLE; } update_robosquawker_particle((unsigned char *)robosquawker_moby, (char *)robosquawker_vars); break; @@ -764,7 +764,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { if (robosquawker_moby->b53 != 0) { blend_moby_animation(robosquawker_moby, 0, 0, scale_game_frames(3)); } - robosquawker_moby->state = 0xF; + robosquawker_moby->state = ROBOSQUAWKER_STATE_FLY_TO_RANDOM_POINT; } else { qcopy(&robosquawker_moby->pos, &va); } @@ -788,7 +788,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { blend_moby_animation(robosquawker_moby, 0, 0, scale_game_frames(3)); } qzero(&robosquawker_vars->v40); - robosquawker_moby->state = 0x11; + robosquawker_moby->state = ROBOSQUAWKER_STATE_LAND; release_robosquawker_particle((Level13VendorMoby *)robosquawker_vars); } else if (g > 1.0f && robosquawker_moby->bBC == 1 && random_integer_below(4) == 0) { if (random_integer_below(0x100) & 1) { @@ -802,7 +802,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { } release_robosquawker_particle((Level13VendorMoby *)robosquawker_vars); qzero(&robosquawker_vars->v40); - robosquawker_moby->state = 0x11; + robosquawker_moby->state = ROBOSQUAWKER_STATE_LAND; clear_u64_value(&robosquawker_vars->v40); robosquawker_moby->bBC = 0; } @@ -828,7 +828,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { } robosquawker_vars->f1F4 = robosquawker_vars->f1F8 * 0.017453292f; robosquawker_vars->w210 = scale_game_frames((int)random_float_between(30.0f, 90.0f)); - robosquawker_moby->state = 3; + robosquawker_moby->state = ROBOSQUAWKER_STATE_CHASE_TARGET; clear_u64_value(&robosquawker_vars->v40); if (robosquawker_moby->b53 != 5) { blend_moby_animation(robosquawker_moby, 5, 0, scale_game_frames(3)); @@ -852,7 +852,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { if (robosquawker_moby->b53 != 0) { blend_moby_animation(robosquawker_moby, 0, 0, scale_game_frames(3)); } - robosquawker_moby->state = 0xE; + robosquawker_moby->state = ROBOSQUAWKER_STATE_FLIGHT_IDLE; clear_u64_value(&robosquawker_vars->v40); } update_robosquawker_particle((unsigned char *)robosquawker_moby, (char *)robosquawker_vars); @@ -863,7 +863,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { if (fast_vec_length(&va) < robosquawker_vars->f1FC + 4.0f && absolute_float(robosquawker_moby->pos.f[2] - selected_target_record.pos.f[2]) < 8.0f && random_integer_below(0x13) == 0) { - robosquawker_moby->state = 2; + robosquawker_moby->state = ROBOSQUAWKER_STATE_FACE_AWAY_WAIT_FOR_CHASE; if (robosquawker_moby->b53 != 4) { blend_moby_animation(robosquawker_moby, 4, 0, scale_game_frames(3)); } @@ -873,7 +873,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { } robosquawker_vars->f1F4 = robosquawker_vars->f1F8 * 0.017453292f; robosquawker_vars->w210 = scale_game_frames((int)random_float_between(30.0f, 90.0f)); - robosquawker_moby->state = 3; + robosquawker_moby->state = ROBOSQUAWKER_STATE_CHASE_TARGET; if (robosquawker_moby->b53 != 5) { blend_moby_animation(robosquawker_moby, 5, 0, scale_game_frames(3)); } @@ -881,7 +881,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { } else if (fast_vec_length(&va) > robosquawker_vars->f1FC + 6.0f && robosquawker_vars->h20A == 0) { qzero(&robosquawker_vars->v40); - robosquawker_moby->state = 0x10; + robosquawker_moby->state = ROBOSQUAWKER_STATE_TAKEOFF; if (robosquawker_moby->b53 != 0) { blend_moby_animation(robosquawker_moby, 0, 0, scale_game_frames(3)); } @@ -893,7 +893,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { if (fast_vec_length(&va) < robosquawker_vars->f1FC - 4.0f && absolute_float(robosquawker_moby->pos.f[2] - selected_target_record.pos.f[2]) < 8.0f && random_integer_below(0x13) == 0) { - robosquawker_moby->state = 2; + robosquawker_moby->state = ROBOSQUAWKER_STATE_FACE_AWAY_WAIT_FOR_CHASE; robosquawker_moby->pos.f[2] += 1.0f; if (robosquawker_moby->b53 != 4) { blend_moby_animation(robosquawker_moby, 4, 0, scale_game_frames(3)); @@ -938,7 +938,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { robosquawker_vars->f174 = 10.0f; update_robosquawker_particle((unsigned char *)robosquawker_moby, (char *)robosquawker_vars); - robosquawker_moby->state = 0xB; + robosquawker_moby->state = ROBOSQUAWKER_STATE_HOME_HOP; } break; } @@ -946,7 +946,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { if (step_moby_motion(robosquawker_moby, robosquawker_vars->x120) & 1) { release_robosquawker_particle((Level13VendorMoby *)robosquawker_vars); qzero(robosquawker_vars->x120); - robosquawker_moby->state = 3; + robosquawker_moby->state = ROBOSQUAWKER_STATE_CHASE_TARGET; if (random_integer_below(0x100) & 1) { robosquawker_vars->f1F8 = -robosquawker_vars->f1F8; } @@ -980,7 +980,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { } robosquawker_vars->f1F4 = robosquawker_vars->f1F8 * 0.017453292f; robosquawker_vars->w210 = scale_game_frames((int)random_float_between(30.0f, 90.0f)); - robosquawker_moby->state = 3; + robosquawker_moby->state = ROBOSQUAWKER_STATE_CHASE_TARGET; if (robosquawker_moby->b53 != 5) { blend_moby_animation(robosquawker_moby, 5, 0, scale_game_frames(3)); } @@ -991,7 +991,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { } robosquawker_vars->f1F4 = robosquawker_vars->f1F8 * 0.017453292f; robosquawker_vars->w210 = scale_game_frames((int)random_float_between(30.0f, 90.0f)); - robosquawker_moby->state = 3; + robosquawker_moby->state = ROBOSQUAWKER_STATE_CHASE_TARGET; if (robosquawker_moby->b53 != 5) { blend_moby_animation(robosquawker_moby, 5, 0, scale_game_frames(3)); } @@ -1038,7 +1038,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { selected_target_record.moby->state != 0xFE && selected_target_record.moby->state != 0xFD && d < 2.3f)) && !(res & 2)) { - robosquawker_moby->state = 4; + robosquawker_moby->state = ROBOSQUAWKER_STATE_PECK_ATTACK; if (robosquawker_moby->b53 != 6) { blend_moby_animation(robosquawker_moby, 6, 0, scale_game_frames(3)); } @@ -1054,7 +1054,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { FUN_L01_0026e090(robosquawker_moby->b21, 1); } } else if (robosquawker_moby->bBC != 1) { - robosquawker_moby->state = 5; + robosquawker_moby->state = ROBOSQUAWKER_STATE_RETURN_HOME; } } robosquawker_moby->bBC = 0; @@ -1098,7 +1098,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { } if ((robosquawker_moby->b70 & 2) && vector_distance_xy(&robosquawker_moby->pos, &selected_target_record) > 1.5f) { - robosquawker_moby->state = 3; + robosquawker_moby->state = ROBOSQUAWKER_STATE_CHASE_TARGET; if (robosquawker_moby->b53 != 5) { blend_moby_animation(robosquawker_moby, 5, 0, scale_game_frames(3)); } @@ -1133,7 +1133,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { va.f[2] = 0.0f; res = FUN_L00_00258b50(robosquawker_moby, &robosquawker_vars->w180, &va, &vb, 1.0f); if (vector_distance_xy(&robosquawker_moby->pos, &robosquawker_vars->v1D0) < 2.0f) { - robosquawker_moby->state = 1; + robosquawker_moby->state = ROBOSQUAWKER_STATE_GROUND_IDLE; if (robosquawker_moby->b53 != 3) { blend_moby_animation(robosquawker_moby, 3, 0, scale_game_frames(3)); } @@ -1143,19 +1143,19 @@ void robosquawker_update(RsMoby *robosquawker_moby) { if (robosquawker_moby->b21 != 0xFF) { FUN_L01_0026e090(robosquawker_moby->b21, 1); } - robosquawker_moby->state = 3; + robosquawker_moby->state = ROBOSQUAWKER_STATE_CHASE_TARGET; if (robosquawker_moby->b53 != 5) { blend_moby_animation(robosquawker_moby, 5, 0, scale_game_frames(3)); } } else if (robosquawker_moby->bBC == 1) { - robosquawker_moby->state = 3; + robosquawker_moby->state = ROBOSQUAWKER_STATE_CHASE_TARGET; if (robosquawker_moby->b53 != 5) { blend_moby_animation(robosquawker_moby, 5, 0, scale_game_frames(3)); } } else if (res & 2) { robosquawker_moby->pos.f[0] = previous_position.f[0]; robosquawker_moby->pos.f[1] = previous_position.f[1]; - robosquawker_moby->state = 0xC; + robosquawker_moby->state = ROBOSQUAWKER_STATE_BLOCKED_RETURN_HOME; if (robosquawker_moby->b53 != 4) { blend_moby_animation(robosquawker_moby, 4, 0, scale_game_frames(3)); } @@ -1167,7 +1167,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { case ROBOSQUAWKER_STATE_DAMAGE_KNOCKBACK: if (step_moby_motion(robosquawker_moby, robosquawker_vars->x120) & 1) { qzero(robosquawker_vars->x120); - robosquawker_moby->state = 3; + robosquawker_moby->state = ROBOSQUAWKER_STATE_CHASE_TARGET; if (robosquawker_moby->b53 != 5) { blend_moby_animation(robosquawker_moby, 5, 0, scale_game_frames(3)); } @@ -1181,7 +1181,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { case ROBOSQUAWKER_STATE_RECOVER_TO_FLIGHT_IDLE: release_robosquawker_particle((Level13VendorMoby *)robosquawker_vars); if (FUN_L00_002dc9f0(robosquawker_moby, robosquawker_vars->x120) != 0) { - robosquawker_moby->state = 0xE; + robosquawker_moby->state = ROBOSQUAWKER_STATE_FLIGHT_IDLE; if (robosquawker_moby->b53 != 0) { blend_moby_animation(robosquawker_moby, 0, 0, 0); } @@ -1231,12 +1231,12 @@ void robosquawker_update(RsMoby *robosquawker_moby) { fast_vec_sub(&vc, &selected_target_record, &robosquawker_vars->v1D0); if (vector_distance_xy(&robosquawker_moby->pos, &selected_target_record) < 1.5f && r <= 1.0f) { - robosquawker_moby->state = 4; + robosquawker_moby->state = ROBOSQUAWKER_STATE_PECK_ATTACK; if (robosquawker_moby->b53 != 6) { blend_moby_animation(robosquawker_moby, 6, 0, scale_game_frames(3)); } } else if (r <= 1.0f && !(res & 2)) { - robosquawker_moby->state = 5; + robosquawker_moby->state = ROBOSQUAWKER_STATE_RETURN_HOME; if (robosquawker_moby->b53 != 5) { blend_moby_animation(robosquawker_moby, 5, 0, scale_game_frames(3)); } @@ -1253,7 +1253,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { } if (random_integer_below(0x63) == 0) { qzero(&robosquawker_vars->v40); - robosquawker_moby->state = 0x10; + robosquawker_moby->state = ROBOSQUAWKER_STATE_TAKEOFF; if (robosquawker_moby->b53 != 0) { blend_moby_animation(robosquawker_moby, 0, 0, scale_game_frames(3)); } @@ -1315,7 +1315,7 @@ void robosquawker_update(RsMoby *robosquawker_moby) { if (robosquawker_vars->p218 == 0 || vector_distance_xy(&robosquawker_moby->pos, robosquawker_vars->p218 + 0x10) > convert_integer_to_float(robosquawker_vars->h216)) { - robosquawker_moby->state = 5; + robosquawker_moby->state = ROBOSQUAWKER_STATE_RETURN_HOME; if (robosquawker_moby->b53 != 5) { blend_moby_animation(robosquawker_moby, 5, 0, scale_game_frames(3)); } From b0758e04754fedc6b09ac9dcfef23e4cb141c417 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:33:09 +0000 Subject: [PATCH 1131/1502] decomp: clarify names in drek_final_boss_robot_update domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Bound C tests hero.vehicle_mode == 2 in DREK_BOSS_WAIT_FOR_ENCOUNTER_TRIGGER. Retail 0x002f2efc sets s1 to hero position 0x0013F3D0; 0x002f2f10 loads byte s1+0x2024 = 0x001413F4, and 0x002f2f14-0x002f2f18 compares it with 2. Original Ghidra calls that byte cRam001413f4. The successful branch starts scene 0 and resumes boss circle/fire state. This proves the exact vehicle_mode selector, whose supplied shared HeroVehicleMode enum canonically names 2 HERO_VEHICLE_MODE_GIANT_CLANK; it is not hero.state.current or control_mode. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Bound C tests hero.vehicle_mode != 0 before disabling hero.moby collision and restoring the saved hero moby/clearing vehicle mode. Retail 0x002f32c4 sets s1=0x0013F350; 0x002f3348 loads byte s1+0x20A4 = 0x001413F4 and 0x002f334c skips the vehicle-moby changes when zero, followed by restore helper call 0x002f336c. Original Ghidra tests the same cRam001413f4 != zero. This is the identical vehicle_mode byte used by the encounter comparison, proving the shared HeroVehicleMode domain, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT. --- src/overlays/l18/mobys/drek_final_boss_robot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/mobys/drek_final_boss_robot.c b/src/overlays/l18/mobys/drek_final_boss_robot.c index b28c58b1a3..305db3ef1a 100644 --- a/src/overlays/l18/mobys/drek_final_boss_robot.c +++ b/src/overlays/l18/mobys/drek_final_boss_robot.c @@ -525,7 +525,7 @@ void drek_final_boss_robot_update(BossMoby *moby) { break; case DREK_BOSS_WAIT_FOR_ENCOUNTER_TRIGGER: if (is_point_inside_clip_volume(hero.motion.pos.f, boss_data->f274) != 0 && - hero.vehicle_mode == 2) { + hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { moby->f20 = 7; moby->f34 |= 0x41; start_scene(0); @@ -624,7 +624,7 @@ void drek_final_boss_robot_update(BossMoby *moby) { frame_time * 6.2831855f); update_drek_boss_arena_circling_movement((struct Moby *)moby); if (boss_data->f38C <= 301.0f) { - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { ((BossMoby *)hero.moby)->f94 = 0; ((BossMoby *)hero.moby)->f34 |= 0x41; } From 47140dbc2eeef191968ed9556116ef06377c2bce Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:33:09 +0000 Subject: [PATCH 1132/1502] decomp: clarify names in update_qwarks_starfighter domain_0_value_1 -> STARFIGHTER_STATE_WAIT_FOR_HERO_SHIP: Retail 0x002eb364 writes 1 to s5+0x20 after attachment/path initialization; s5 is the original moby argument (0x002eb0a4) and this exact byte selects the named starfighter switch at 0x002eb1a0. Case 1 waits for hero mode 0x32 and a ship. domain_10_value_2 -> STARFIGHTER_STATE_FOLLOW_INITIAL_PATH: Retail 0x002ec9e8-0x002ec9fc reads s5+0x20 and uses unsigned threshold 2 before attachment updates. This is exactly the original starfighter moby selector at 0x002eb1a0, so reuse its established FOLLOW_INITIAL_PATH lower-bound member. domain_11_value_8 -> STARFIGHTER_STATE_EXPLODE_AND_REMOVE: Retail 0x002eca04-0x002eca30 compares s5+0x20 against 8 and gates joint effects on the remaining timer only for that state. The selector is the same original starfighter moby byte, whose established case 8 performs explosion/removal. domain_12_value_6 -> STARFIGHTER_STATE_OWNER_UNAVAILABLE: Retail 0x002ecb2c-0x002ecb48 compares original moby byte s5+0x20 with 6 before checking linked ship validity. The failed checks write 6 back at 0x002ecb88; this is the exact selector of established OWNER_UNAVAILABLE case. domain_13_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002ecb30-0x002ecb68 obtains the indexed linked Moby, validates class 0x45 and reads +0x20 for comparison with 0xFE. Checked generic removal helper 0x0025a800-0x0025a818 writes this state when the Moby pointer is at or above 0x0015ffdc. This is a generic removal sentinel, not a starfighter or HeroStateId state. domain_14_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002ecb60-0x002ecb70 compares the linked class-0x45 Moby's +0x20 state against 0xFD. Checked generic removal helper 0x0025a800-0x0025a818 writes 0xFD for Moby pointers below 0x0015ffdc. The supplied source already uses this exact removal-sentinel spelling in update_moby_joint_attachments. domain_16_value_6 -> STARFIGHTER_STATE_OWNER_UNAVAILABLE: Retail 0x002ecb4c-0x002ecb88 enters 6 when the linked class-0x45 ship is absent, wrong-class, removed or state 7. The store is to original moby s5+0x20, proving reuse of its established OWNER_UNAVAILABLE case rather than a ship-state constant. domain_17_value_6 -> STARFIGHTER_STATE_OWNER_UNAVAILABLE: Retail 0x002ecc20-0x002ecc28 tests original moby s5+0x20 against 6 before conditional hero-ship voice-line processing. This is the same selector dispatched at 0x002eb1a0 and assigned 6 by the linked-owner failure branch, hence OWNER_UNAVAILABLE. domain_18_value_2 -> STARFIGHTER_STATE_FOLLOW_INITIAL_PATH: Source final range tests moby->state >= 2 && <= 5; retail 0x002ecca4-0x002eccb0 reads s5+0x20, subtracts 2 and tests unsigned <4. This is the named starfighter switch selector, so its lower endpoint is established FOLLOW_INITIAL_PATH. domain_19_value_5 -> STARFIGHTER_STATE_TRACTOR_BEAM: Source final range tests moby->state >= 2 && <= 5; retail 0x002ecca4-0x002eccb0 implements states 2 through 5 using subtract-2 and unsigned <4 on s5+0x20. This exact starfighter selector has established TRACTOR_BEAM=5, corroborated by beam drawing and capture case behavior. domain_1_value_2 -> STARFIGHTER_STATE_FOLLOW_INITIAL_PATH: Retail 0x002eb4e0-0x002eb4e8 stores 2 to the original moby state byte after the hero-ship wait. The same byte selects established case FOLLOW_INITIAL_PATH, which calls 0x002e9160 with path slot zero at 0x002eb560-0x002eb588. domain_20_value_9 -> STARFIGHTER_STATE_RESET: Retail 0x002eccb8-0x002eccc8 tests the external flag and writes 9 to original moby state s5+0x20. The same byte dispatches established RESET, which releases children/handles, restores path pose, clears fields and returns to INITIALIZE. domain_2_value_3 -> STARFIGHTER_STATE_FOLLOW_COMMAND_PATH: Retail 0x002eb590 tests initial-path completion, selects the command path via 0x001d3448, then 0x002eb5e8-0x002eb5f0 writes 3 to the same moby+0x20 dispatched by the named FOLLOW_COMMAND_PATH case. domain_3_value_8 -> STARFIGHTER_STATE_EXPLODE_AND_REMOVE: Retail death-flight branch 0x002ec0a4-0x002ec0f0 checks path completion/end, reloads the timer and writes 8 to s5+0x20. This is the same selector as established EXPLODE_AND_REMOVE, whose case emits an explosion and removes this moby. domain_5_value_0 -> STARFIGHTER_STATE_INITIALIZE: Retail reset tail 0x002ec7b0-0x002ec828 clears runtime fields and writes zero to s5+0x20. That is the same moby state selector read at 0x002eb1a0, where established INITIALIZE creates parts and initializes paths and handles. domain_6_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Source child is starfighter_vars->child110, validated class 0x160; retail 0x002ec9bc-0x002ec9d8 compares its Moby state at +0x20 with 0xFE before clearing the reference. Checked removal helper 0x0025a7f0-0x0025a818 compares the Moby pointer to 0x0015ffdc and writes 0xFE at +0x20 for at/above-boundary instances. Reuse the spelling established in update_moby_joint_attachments in the supplied source. domain_7_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002ec9bc-0x002ec9d8 compares the class-0x160 child Moby state at +0x20 with 0xFD and clears its reference. Checked removal helper 0x0025a800-0x0025a818 writes 0xFD to this generic Moby field when its pointer is below 0x0015ffdc. Reuse the supplied source's update_moby_joint_attachments removal-sentinel spelling. --- src/overlays/l13/mobys/qwarks_starfighter.c | 36 ++++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/overlays/l13/mobys/qwarks_starfighter.c b/src/overlays/l13/mobys/qwarks_starfighter.c index 2c3f3484c4..04de35b18f 100644 --- a/src/overlays/l13/mobys/qwarks_starfighter.c +++ b/src/overlays/l13/mobys/qwarks_starfighter.c @@ -1626,6 +1626,10 @@ void qwarks_starfighter_update(Moby388 *moby) { STARFIGHTER_STATE_EXPLODE_AND_REMOVE = 8, STARFIGHTER_STATE_RESET = 9 }; + enum { + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE + }; Ship388 *starfighter_vars = moby->d; float offset[4]; float joint[4]; @@ -1680,7 +1684,7 @@ void qwarks_starfighter_update(Moby388 *moby) { starfighter_vars->b10C = 1; starfighter_vars->bFE = 0; starfighter_vars->bFC = 0; - moby->state = 1; + moby->state = STARFIGHTER_STATE_WAIT_FOR_HERO_SHIP; starfighter_vars->b10E = 8; starfighter_vars->child110 = 0; starfighter_vars->snd114 = -1; @@ -1728,7 +1732,7 @@ void qwarks_starfighter_update(Moby388 *moby) { *(int *)(ship + 0x138) = 0x234; } } - moby->state = 2; + moby->state = STARFIGHTER_STATE_FOLLOW_INITIAL_PATH; } break; } @@ -1759,7 +1763,7 @@ void qwarks_starfighter_update(Moby388 *moby) { *(int *)(ship + 0x118) = 0; starfighter_vars->b13B = qwarks_starfighter_command_path_slots[moby->bBC]; starfighter_vars->iF8 = scale_game_frames(0x14); - moby->state = 3; + moby->state = STARFIGHTER_STATE_FOLLOW_COMMAND_PATH; starfighter_vars->s9C = select_point_index_by_distance( moby->pos, walker_paths[starfighter_vars->paths[starfighter_vars->b13B]], 0.0f); starfighter_vars->s9C = @@ -2024,7 +2028,7 @@ void qwarks_starfighter_update(Moby388 *moby) { starfighter_vars->s9C >= *(int *)walker_paths[starfighter_vars->paths[starfighter_vars->b13B]] - 1) { starfighter_vars->iF8 = scale_game_frames(0xB4); - moby->state = 8; + moby->state = STARFIGHTER_STATE_EXPLODE_AND_REMOVE; } moby->rot[0] = fast_add_rotations(moby->rot[0], frame_time * 4.1887903f); { @@ -2216,7 +2220,7 @@ void qwarks_starfighter_update(Moby388 *moby) { moby->bBC = 0; qzero(&starfighter_vars->f70); qzero(starfighter_vars->v80); - moby->state = 0; + moby->state = STARFIGHTER_STATE_INITIALIZE; return; } } @@ -2263,9 +2267,9 @@ void qwarks_starfighter_update(Moby388 *moby) { starfighter_vars->child110 = 0; } else if (child->cls_id != 0x160) { starfighter_vars->child110 = 0; - } else if (child->state == 0xFE) { + } else if (child->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END) { starfighter_vars->child110 = 0; - } else if (child->state == 0xFD) { + } else if (child->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { starfighter_vars->child110 = 0; } else if (child->state < 3) { child->state = 3; @@ -2273,9 +2277,9 @@ void qwarks_starfighter_update(Moby388 *moby) { } } - if (moby->state >= 2) { + if (moby->state >= STARFIGHTER_STATE_FOLLOW_INITIAL_PATH) { update_moby_joint_attachments(moby, starfighter_vars); - if (moby->state != 8 || scale_game_frames(0x78) < starfighter_vars->iF8) { + if (moby->state != STARFIGHTER_STATE_EXPLODE_AND_REMOVE || scale_game_frames(0x78) < starfighter_vars->iF8) { emit_gated_moby_joint_effects(moby, starfighter_vars); } if (starfighter_vars->snd114 != -1) { @@ -2302,10 +2306,10 @@ void qwarks_starfighter_update(Moby388 *moby) { { Moby388 *owner = (Moby388 *)((char *)moby_base + (starfighter_vars->i134 << 8)); - if (moby->state != 6) { - if (owner == 0 || owner->cls_id != 0x45 || owner->state == 0xFE || - owner->state == 0xFD || owner->state == 7) { - moby->state = 6; + if (moby->state != STARFIGHTER_STATE_OWNER_UNAVAILABLE) { + if (owner == 0 || owner->cls_id != 0x45 || owner->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || + owner->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END || owner->state == 7) { + moby->state = STARFIGHTER_STATE_OWNER_UNAVAILABLE; if (queue_starfighter_voice_line( moby, starfighter_vars, D_L13_00161950 + 0x1D, 1) != 0) { D_L13_00161950 = (D_L13_00161950 + 1) % 4; @@ -2325,7 +2329,7 @@ void qwarks_starfighter_update(Moby388 *moby) { starfighter_vars->b13A = 0; } } else { - if (moby->state != 6) { + if (moby->state != STARFIGHTER_STATE_OWNER_UNAVAILABLE) { char *hero = ((char *)&D_0013F350); if (*(int *)(hero + 0x2084) == 0x32) { if (*(Moby388 **)(hero + 0x15F0) != 0 && @@ -2340,8 +2344,8 @@ void qwarks_starfighter_update(Moby388 *moby) { } fast_dec_timer_s16(&starfighter_vars->h144); fast_dec_timer_s16(&starfighter_vars->h146); - if (moby->state >= 2 && moby->state <= 5 && (((unsigned char *)D_0013E533)[0x242C] & 1)) { - moby->state = 9; + if (moby->state >= STARFIGHTER_STATE_FOLLOW_INITIAL_PATH && moby->state <= STARFIGHTER_STATE_TRACTOR_BEAM && (((unsigned char *)D_0013E533)[0x242C] & 1)) { + moby->state = STARFIGHTER_STATE_RESET; } } From eac0ebbf71ed60d06a6a3006afd3bffae387b927 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:33:10 +0000 Subject: [PATCH 1133/1502] decomp: clarify names in update_hero_motion_for_current_state domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Authoritative C tests hero.gravity_mode in CROUCH_SWING before update_hero_target_heading. Retail 0x002396a4 loads byte hero+0x20B3 and 0x002396a8 skips heading update when nonzero; original Ghidra tests cRam00141403 == zero. The snapshot gravity-frame comment identifies this exact byte as zero for world Z up, hence world-down gravity. Reuse HeroGravityMode.HERO_GRAVITY_WORLD_DOWN from include/rnc/hero/hero_state.h. domain_10_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source APPROACH_TARGET_POSE selects on-foot turning when hero.vehicle_mode == 0. Retail 0x0023bd94 loads hero+0x20A4; after modes three and one, 0x0023be20 branches away if the same selector is nonzero. Zero reaches step-dependent turn_to or turn_hero_toward_move_direction_with_stick_scale at 0x0023be28-0x0023be80. Original Ghidra agrees. Reuse canonical HeroVehicleMode.HERO_VEHICLE_MODE_ON_FOOT for this exact source/retail selector. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source APPROACH_TARGET_POSE invokes adjust_hero_pose_targets_from_motion only when hero.vehicle_mode == 0. Retail 0x0023be88 reloads byte hero+0x20A4 and 0x0023be8c bypasses the call for nonzero; zero calls 0x00235638 at 0x0023be94. Original Ghidra uses cRam001413f4 == zero. This is shared HeroVehicleMode, not the current-state or request domain. Reuse canonical HERO_VEHICLE_MODE_ON_FOOT. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source APPROACH_TARGET_POSE calls clip_hero_horizontal_velocity(1) when hero.vehicle_mode == 0. Retail 0x0023bee4 loads hero byte +0x20A4 and 0x0023bee8 skips clipping if nonzero; zero reaches 0x0023bef0-0x0023bef4. Original Ghidra tests the same cRam001413f4 byte. The source vehicle_mode field and byte identity establish shared HeroVehicleMode; reuse canonical HERO_VEHICLE_MODE_ON_FOOT, independently of current-state values. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: Source r is &D_L01_0017C0A8[hero.attack_record], a HeroTableRow2C attack record, not hero.state.current. Retail 0x002397cc-0x002397e8 computes table base 0x0017C0A8 plus index*0x2C; 0x00239830-0x0023985c reads kind at row+4, tests zero and selects 0.75 distance offset. The same row+4 feeds the existing named profile switch at 0x00239924-0x00239998, which advances before frame 18. Reuse canonical HeroComboKind member for this same selector. domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source compares r->kind on the HeroTableRow2C selected by hero.attack_record. Retail 0x002397cc-0x002397e8 forms 0x0017C0A8+index*0x2C; 0x00239830 reads row+4 and 0x00239860 compares it to one, selecting the 0.6 distance offset. This identical row+4 drives the existing named switch at 0x00239924-0x00239a30 with staged forward speeds 5.7,4.5,3.0. Reuse HeroComboKind.HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: In source WRENCH_COMBO, r remains the selected HeroTableRow2C attack record. Retail 0x00239ac0 reloads kind from 4(s1), and 0x00239ac4-0x00239ac8 compares against one before target-yaw-dependent animation speed adjustment at 0x00239ad0-0x00239b08. The same s1 row+4 already selects the canonical staged-forward-deceleration profile at 0x00239924-0x00239a30. Reuse that exact HeroComboKind member, independently of hero current-state IDs. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source WRENCH_COMBO gates free heading updates on r->kind == 1 and animation frame >7. Retail 0x00239ab8-0x00239abc reaches 0x00239b68 with kind loaded from 4(s1); 0x00239b68-0x00239b9c compares one, animation-changing and frame 7 before suppressing heading update. s1 is the attack record formed at 0x002397cc-0x002397e8, whose identical kind selects the existing staged-deceleration switch branch. Reuse canonical HeroComboKind member. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source common jump path compares hero.vehicle_mode before adjust_hero_pose_targets_from_motion. Retail 0x0023ba78 loads byte hero+0x20A4, 0x0023ba7c bypasses pose adjustment when nonzero, and 0x0023ba84 invokes it for zero; original Ghidra uses cRam001413f4. This is the source vehicle_mode selector in shared HeroVehicleMode, distinct from hero current state +0x2084 and control mode +0x208C. Reuse canonical HERO_VEHICLE_MODE_ON_FOOT. domain_7_value_1 -> HERO_VEHICLE_MODE_CLANK: Source APPROACH_TARGET_POSE compares hero.vehicle_mode to one for target speed frame_time*0.9. Retail 0x0023bd2c loads hero byte +0x20A4, then 0x0023bd48 compares the same loaded selector against one and 0x0023bd50-0x0023bd70 selects the 0.9 speed. Original Ghidra tests cRam001413f4 == 1. This proves the shared HeroVehicleMode selector, not a HeroStateId. Reuse canonical HERO_VEHICLE_MODE_CLANK supplied for that exact domain. domain_9_value_1 -> HERO_VEHICLE_MODE_CLANK: Source APPROACH_TARGET_POSE uses hero.vehicle_mode == 1 for its 7.8539815 turn-rate branch. Retail 0x0023bd94 loads hero+0x20A4; 0x0023bde0 compares that same byte to one, selecting turn parameters at 0x0023bde8-0x0023be1c. Original Ghidra tests cRam001413f4 == 1. The source field and retail byte establish shared HeroVehicleMode, separate from current-state IDs. Reuse its canonical HERO_VEHICLE_MODE_CLANK member. --- .../update_hero_motion_for_current_state.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l01/hero/update_hero_motion_for_current_state.c b/src/overlays/l01/hero/update_hero_motion_for_current_state.c index bf7fc21e56..4f385d5c0d 100644 --- a/src/overlays/l01/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l01/hero/update_hero_motion_for_current_state.c @@ -1323,7 +1323,7 @@ void update_hero_motion_for_current_state(void) { ok = 0; } if (ok) { - if (hero.gravity_mode == 0) { + if (hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1360,11 +1360,11 @@ void update_hero_motion_for_current_state(void) { if (d < 0.0f) { d = 0.0f; } - if (r->kind == 0) { + if (r->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { attack_kind_distance_offset = 0.75f; range = 0.8f; cap = 4.0f; - } else if (r->kind == 1) { + } else if (r->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { attack_kind_distance_offset = 0.6f; range = 1.7f; cap = 4.0f; @@ -1411,7 +1411,7 @@ void update_hero_motion_for_current_state(void) { } fast_cos_cf(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || ((Moby *)hero.melee_target) != 0) { - if (r->kind == 1 && + if (r->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1423,7 +1423,7 @@ void update_hero_motion_for_current_state(void) { int ok; ok = 1; - if (r->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (r->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2111,7 +2111,7 @@ void update_hero_motion_for_current_state(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -2187,7 +2187,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = frame_time * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = frame_time * 0.9f; } } else { @@ -2198,21 +2198,21 @@ void update_hero_motion_for_current_state(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to(0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, frame_time * 9.948377f); } else { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } speed_step(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { From fcc8d3f7f7ad8f0af516ab7a09617a3f26c215dc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:33:10 +0000 Subject: [PATCH 1134/1502] decomp: clarify names in update_hero_state_motion domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Bound C tests hero.gravity_mode in CROUCH_SWING. Retail 0x00227ba8 reads byte hero+0x20B3 and 0x00227bac skips target-heading adjustment when nonzero; original Ghidra uses cRam00141403. The supplied ground-contact source switches this exact gravity_mode field: WORLD_DOWN sets gravity_dir Z=-1, while OPPOSITE_GROUND_NORMAL negates the ground normal. This proves HeroGravityMode, distinct from current-state and vehicle selectors. domain_10_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Bound APPROACH_TARGET_POSE code tests hero.vehicle_mode==0 before selecting on-foot steering based on hero.state.step. Retail 0x0022a008 compares the byte previously loaded from hero+0x20A4 at 0x00229f7c with zero; 0x0022a010-0x0022a068 selects step-dependent turning. This exact vehicle_mode field is switched using ON_FOOT in supplied hurt-response/collision source, proving HeroVehicleMode rather than HeroStateId. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Bound target-pose code tests hero.vehicle_mode==0 before pose adjustment. Retail 0x0022a070 loads hero+0x20A4 and 0x0022a074 branches over adjust_hero_pose_targets_from_motion at 0x0022a07c when nonzero. Original Ghidra tests cRam001413f4. Supplied hurt-response/collision source uses the exact hero.vehicle_mode selector with canonical ON_FOOT, establishing the shared HeroVehicleMode domain. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Bound target-pose code tests hero.vehicle_mode==0 before horizontal clipping. Retail 0x0022a0cc loads byte hero+0x20A4 and 0x0022a0d0 skips clip_hero_horizontal_velocity(1) at 0x0022a0d8 when nonzero. Original Ghidra tests cRam001413f4. The same field is the HeroVehicleMode selector in supplied hurt-response/collision source, proving reuse of canonical HERO_VEHICLE_MODE_ON_FOOT. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: In WRENCH_COMBO, r=&D_L02_0017C228[hero.attack_record]. Retail 0x00227cd0-0x00227cec uses stride 0x2C and 0x00227d34 loads r+4, testing zero at 0x00227d38 to choose the 0.75 distance offset. The same r->kind selects the already named FRAME_GATED_FORWARD_ADVANCE switch arm at 0x00227e28-0x00227e9c (4.4 forward speed until frame 18). This proves the exact HeroComboKind domain. domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: The attack-record pointer is formed with stride 0x2C at 0x00227cd0-0x00227cec. Retail 0x00227d34 loads row+4 and 0x00227d64 compares it with one to select the 0.6 distance offset. The identical row+4 selector drives the already named STAGED_FORWARD_DECELERATION arm at 0x00227ea0-0x00227f34 with 5.7/4.5/3.0 speeds around frames 7/8/9. Thus this comparison belongs to HeroComboKind. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Bound C compares r->kind before slowing animation for positive attack-target yaw difference. Retail 0x00227fc4 loads the same attack-record row+4; 0x00227fc8-0x00227fcc compares it with one before yaw and animation-speed operations at 0x00227fd4-0x0022800c. That row+4 is also the named staged-deceleration switch selector at 0x00227e28-0x00227f34, proving HeroComboKind membership. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Bound C gates target-heading adjustment on r->kind==1 and animation frame>7. Retail 0x00227fc0 loads the attack-record row+4, 0x0022806c-0x00228070 compares it with one, and 0x00228078-0x002280a0 checks animation transition/frame seven. This is the same row+4 selector used by the named STAGED_FORWARD_DECELERATION arm at 0x00227ea0-0x00227f34, establishing the exact HeroComboKind domain. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Bound jump code tests hero.vehicle_mode before adjust_hero_pose_targets_from_motion. Retail 0x00229c60 reads byte hero+0x20A4; 0x00229c64 skips the pose call at 0x00229c6c when nonzero. Original Ghidra tests cRam001413f4. The supplied hurt-response and collision-dimension functions switch this same hero.vehicle_mode field using canonical HERO_VEHICLE_MODE_ON_FOOT, proving the HeroVehicleMode domain. domain_7_value_1 -> HERO_VEHICLE_MODE_CLANK: In APPROACH_TARGET_POSE, bound C compares hero.vehicle_mode==1 to select frame_time*0.9 target speed. Retail 0x00229f14 loads hero+0x20A4, 0x00229f30 compares the same byte against one, and 0x00229f38-0x00229f58 sets that speed. Original Ghidra uses cRam001413f4. This exact field is the HeroVehicleMode selector in the supplied source, whose canonical member for one is HERO_VEHICLE_MODE_CLANK. domain_9_value_1 -> HERO_VEHICLE_MODE_CLANK: Bound target-pose motion tests hero.vehicle_mode==1 for its turning profile. Retail 0x00229f7c reads hero+0x20A4 and 0x00229fc8 compares it against one, selecting turn rate frame_time*7.8539815 at 0x00229fd0-0x0022a004. Original Ghidra uses cRam001413f4, the same vehicle_mode selector established by supplied hurt-response/collision source and HeroVehicleMode; reuse its canonical CLANK member. --- .../l02/hero/update_hero_state_motion.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l02/hero/update_hero_state_motion.c b/src/overlays/l02/hero/update_hero_state_motion.c index d9ab8ad13a..d6b1aee549 100644 --- a/src/overlays/l02/hero/update_hero_state_motion.c +++ b/src/overlays/l02/hero/update_hero_state_motion.c @@ -1484,7 +1484,7 @@ void update_hero_state_motion(void) { ok = 0; } if (ok) { - if (hero.gravity_mode == 0) { + if (hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1521,11 +1521,11 @@ void update_hero_state_motion(void) { if (d < 0.0f) { d = 0.0f; } - if (r->kind == 0) { + if (r->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { attack_distance_offset = 0.75f; range = 0.8f; cap = 4.0f; - } else if (r->kind == 1) { + } else if (r->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { attack_distance_offset = 0.6f; range = 1.7f; cap = 4.0f; @@ -1572,7 +1572,7 @@ void update_hero_state_motion(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || ((Moby *)hero.melee_target) != 0) { - if (r->kind == 1 && + if (r->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1584,7 +1584,7 @@ void update_hero_state_motion(void) { int ok; ok = 1; - if (r->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (r->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2231,7 +2231,7 @@ void update_hero_state_motion(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -2307,7 +2307,7 @@ void update_hero_state_motion(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = frame_time * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = frame_time * 0.9f; } } else { @@ -2318,21 +2318,21 @@ void update_hero_state_motion(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to(0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, frame_time * 9.948377f); } else { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } speed_step(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { From acdb17412dcb6a6cae95de9c9b1661147d0166e7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:35:01 +0000 Subject: [PATCH 1135/1502] decomp: clarify names in update_hero_motion_for_current_state domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Retail 0x0021907c loads the byte at hero+0x20b3 and 0x00219080 skips heading adjustment when nonzero; original Ghidra tests cRam00141403. Authoritative C identifies this exact byte as hero.gravity_mode, the selector of shared HeroGravityMode, whose canonical zero member is HERO_GRAVITY_WORLD_DOWN. This is separate from current state at +0x2084. domain_10_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021cc30 tests the hero+0x20a4 selector for zero before the step-one turn or stick-scaled turning path. Source names that byte hero.vehicle_mode, matching original Ghidra cRam001413f4 and shared HeroVehicleMode. Therefore this zero comparison reuses canonical HERO_VEHICLE_MODE_ON_FOOT, independently of the current-state switch. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021cc98 loads hero+0x20a4 and 0x0021cc9c branches over adjust_hero_pose_targets_from_motion for nonzero. Source identifies the byte as hero.vehicle_mode, corroborated by original Ghidra cRam001413f4. Its shared HeroVehicleMode zero member is HERO_VEHICLE_MODE_ON_FOOT, fitting this on-foot pose gate. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021ccf4 loads hero+0x20a4 and 0x0021ccf8 skips the horizontal-velocity clip for nonzero; zero calls the helper with argument one at 0x0021cd00-0x0021cd04. Source and original Ghidra identify the same vehicle-mode byte, proving shared HeroVehicleMode and reuse of canonical HERO_VEHICLE_MODE_ON_FOOT. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: Retail 0x002191a4-0x002191c0 computes table 0x0017c088 plus hero.attack_record times 0x2c; 0x00219208 loads row+4 and 0x0021920c tests zero to select spacing 0.75. Source tb points to this attack row and the same tb->kind switch already names zero HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE, proving shared HeroComboKind rather than a state ID. domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: The attack row pointer computed at retail 0x002191a4-0x002191c0 indexes 0x0017c088 with stride 0x2c. Row+4 is loaded at 0x00219208 and tested against one at 0x00219238, selecting spacing 0.6. Source uses the identical tb->kind selector in its already named HeroComboKind switch; one is canonically HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x00219498 loads +4 from the same attack-record row retained in s1 and 0x002194a0 compares it with one before positive heading-error animation slowing. Original Ghidra retains the table-derived selector. Authoritative C uses tb->kind here and in the named HeroComboKind switch, establishing the canonical member HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x00219540-0x00219574 tests attack row+4 against one, animation-changing status, and frame greater than seven to disable heading updates. This is the same tb->kind loaded from attack_records stride 0x2c, already switched with named HeroComboKind members in the source; reuse HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021c87c reads hero+0x20a4 and 0x0021c880 skips pose adjustment for nonzero, calling adjust_hero_pose_targets_from_motion only for zero at 0x0021c888. Original Ghidra tests cRam001413f4; authoritative C identifies this byte as hero.vehicle_mode, the shared HeroVehicleMode selector, whose zero member is HERO_VEHICLE_MODE_ON_FOOT. domain_7_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0021cb3c loads hero+0x20a4 and 0x0021cb58 compares it with one, selecting the 0.9 frame-time speed at 0x0021cb60-0x0021cb80. Source identifies that exact byte as hero.vehicle_mode, belonging to shared HeroVehicleMode with canonical one HERO_VEHICLE_MODE_CLANK; original Ghidra confirms cRam001413f4, distinct from hero current state. domain_9_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0021cba4 reloads hero+0x20a4; after the distinct mode-three branch, 0x0021cbf0 compares the retained selector with one and chooses the 7.8539815 turning limit. Authoritative C maps this byte to hero.vehicle_mode in shared HeroVehicleMode, whose canonical one is HERO_VEHICLE_MODE_CLANK. Original Ghidra shows the same byte comparison. --- .../update_hero_motion_for_current_state.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l16/hero/update_hero_motion_for_current_state.c b/src/overlays/l16/hero/update_hero_motion_for_current_state.c index e63053e0ea..e3d6553f9f 100644 --- a/src/overlays/l16/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l16/hero/update_hero_motion_for_current_state.c @@ -1782,7 +1782,7 @@ void update_hero_motion_for_current_state(void) { if (hero.anim_changing == 0 && hero.anim_frame > 6.0f) { ok = 0; } - if (ok && hero.gravity_mode == 0) { + if (ok && hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1824,11 +1824,11 @@ void update_hero_motion_for_current_state(void) { if (d < 0.0f) { d = 0.0f; } - if (tb->kind == 0) { + if (tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { off = 0.75f; tol = 0.8f; mx = 4.0f; - } else if (tb->kind == 1) { + } else if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { off = 0.6f; tol = 1.7f; mx = 4.0f; @@ -1873,7 +1873,7 @@ void update_hero_motion_for_current_state(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || (struct MobyView *)hero.melee_target != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1883,7 +1883,7 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2982,7 +2982,7 @@ void update_hero_motion_for_current_state(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -3050,7 +3050,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = D_0015ED6C_a * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = D_0015ED6C_a * 0.9f; } } else { @@ -3061,21 +3061,21 @@ void update_hero_motion_for_current_state(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to(0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, frame_time * 9.948377f); } else { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } speed_step(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { From 1db236e618cbaef80d8471218ebc0320d0620cdd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:35:01 +0000 Subject: [PATCH 1136/1502] decomp: clarify names in is_robot_dog_in_state_5 domain_0_value_254 -> MOBY_STATE_PENDING_REMOVAL: Retail 0x002c5b80 loads the unsigned Moby.state byte at a0+0x20; 0x002c5b7c sets 0xFE and 0x002c5b84 rejects that byte value. The authoritative source types this exact selector as moby->state. In the same source, can_release_linked_robot_dog declares MOBY_STATE_PENDING_REMOVAL = 0xFE and compares state copied from moby->state against it before its class check. Thus both predicates use the same Moby state sentinel domain, rather than an unrelated equal-valued control mode. --- src/overlays/l03/mobys/robot_dog.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l03/mobys/robot_dog.c b/src/overlays/l03/mobys/robot_dog.c index 4d5b4f21ce..cd23b36851 100644 --- a/src/overlays/l03/mobys/robot_dog.c +++ b/src/overlays/l03/mobys/robot_dog.c @@ -25,7 +25,10 @@ int is_robot_dog_in_state_5(struct Moby *moby) { enum { ROBOT_DOG_FOLLOW_PATH = 5 }; - if (moby && moby->state != 0xFE && moby->state != 0xFD && moby->oclass == 0x23D && + enum { + MOBY_STATE_PENDING_REMOVAL = 0xFE + }; + if (moby && moby->state != MOBY_STATE_PENDING_REMOVAL && moby->state != 0xFD && moby->oclass == 0x23D && moby->state == ROBOT_DOG_FOLLOW_PATH) { return 1; } From ec5cbb04c666f7a48678da046ad2014c0db61e7d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:36:41 +0000 Subject: [PATCH 1137/1502] decomp: clarify names in save_card_state_create_save_pending domain_0_value_0 -> MEMCARD_QUERY_INFO: Retail 0x00208d28 establishes a1=0x0013d290; 0x00208d38 loads pending_state at +0xdc and 0x00208d3c branches on signed >=0. The same field receives operation 9 at 0x00208d48. Original Ghidra identifies it as g_nPendingMemoryCardOperationState, and the supplied include/rnc/save/memory_card_state.h declaration context explicitly assigns state/pending_state to MemoryCardOperation, whose canonical zero member is MEMCARD_QUERY_INFO. Reuse that domain member as the signed comparison boundary without changing the threshold. --- src/ui/menus/save_data/save_card_state_create_save_pending.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/menus/save_data/save_card_state_create_save_pending.c b/src/ui/menus/save_data/save_card_state_create_save_pending.c index 25e5f6cecd..16e9907eac 100644 --- a/src/ui/menus/save_data/save_card_state_create_save_pending.c +++ b/src/ui/menus/save_data/save_card_state_create_save_pending.c @@ -6,7 +6,7 @@ void save_card_state_create_save_pending(void) __asm__("FUN_00208d20"); void save_card_state_create_save_pending(void) { struct MemoryCardState *card_state = &memory_card_state; - if (card_state->state == MEMCARD_DISPATCH_PENDING_OPERATION && card_state->pending_state < 0) { + if (card_state->state == MEMCARD_DISPATCH_PENDING_OPERATION && card_state->pending_state < MEMCARD_QUERY_INFO) { card_state->pending_state = MEMCARD_BEGIN_CREATE_SAVE_DIRECTORY; card_state->pending_card = 0; mode_freeze_state = 0xF; From e8697f3ad63eee1a46a843b7762c2fffff67c0c7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:38:35 +0000 Subject: [PATCH 1138/1502] decomp: clarify names in enable_dmac domain_0_value_0 -> INTERRUPT_ENABLE_BIT_CLEAR: Retail 0x00119174 reads COP0 Status into s0; 0x00119178-0x0011917c mask it with 0x10000. At 0x00119180, zero skips DIntr at 0x00119188, so the source status != 0 tests whether the saved interrupt-enable bit is not clear. Supplied EnableInterrupts context uses INTERRUPT_ENABLE_BIT_CLEAR for the identical CpuReadStatus() & 0x10000 domain. domain_1_value_0 -> INTERRUPT_ENABLE_BIT_CLEAR: Retail 0x001191a0 tests the same saved s0 originally read and masked at 0x00119174-0x0011917c; zero skips EnableInterrupts at 0x001191a8. Thus the second source status != 0 restores interrupts only when the saved enable bit was set. It shares the exact masked COP0 Status domain and INTERRUPT_ENABLE_BIT_CLEAR meaning of the first comparison and supplied EnableInterrupts context. --- src/sdk/kernel/enable_dmac.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sdk/kernel/enable_dmac.c b/src/sdk/kernel/enable_dmac.c index 1b8543ef4d..e77405bda9 100644 --- a/src/sdk/kernel/enable_dmac.c +++ b/src/sdk/kernel/enable_dmac.c @@ -8,17 +8,20 @@ extern s32 DIntr(); s32 enable_dmac(s32 channel_index) __asm__("FUN_00119160"); s32 enable_dmac(s32 channel_index) { + enum { + INTERRUPT_ENABLE_BIT_CLEAR = 0 + }; u32 status; s32 dmac_enable_result; status = CpuReadStatus(); status &= 0x10000; - if (status != 0) { + if (status != INTERRUPT_ENABLE_BIT_CLEAR) { DIntr(); } dmac_enable_result = _EnableDmac(channel_index); CpuSync(); - if (status != 0) { + if (status != INTERRUPT_ENABLE_BIT_CLEAR) { EnableInterrupts(); } return dmac_enable_result; From 5a4673d191cafdb4efe829d99a4e1ad26eb6179c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:40:25 +0000 Subject: [PATCH 1139/1502] decomp: clarify names in activate_waiting_moby_group_members domain_0_value_2 -> MOBY_GROUP_MEMBER_ACTIVATE: Retail 0x002e0138-0x002e0158 selects moby_group_member_lists using the input moby's group byte +0x21. At 0x002e0168-0x002e017c each masked 15-bit index resolves a Moby with 0x100 stride; 0x002e0180-0x002e0188 tests its state byte +0x20 for waiting state 1 and stores 2 only on that branch. This is the activation destination in the established activate_waiting_moby_group_members function. The supplied toxic-crab context likewise changes WAIT_FOR_ACTIVATION to ACTIVATE (2), and screamer's waiting state transitions to state 2 before rising. MOBY_GROUP_MEMBER_ACTIVATE describes the common activation role; the unrelated Hero constants do not belong to this Moby group-member state domain. --- src/overlays/l10/mobys/screamer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l10/mobys/screamer.c b/src/overlays/l10/mobys/screamer.c index 9cb13b4ec7..012d81d1f8 100644 --- a/src/overlays/l10/mobys/screamer.c +++ b/src/overlays/l10/mobys/screamer.c @@ -495,6 +495,9 @@ void activate_waiting_moby_group_members(struct Moby *moby) { enum { MOBY_GROUP_MEMBER_WAITING_FOR_ACTIVATION = 1 }; + enum { + MOBY_GROUP_MEMBER_ACTIVATE = 2 + }; short *group_entry; if (moby->group != 0xFF) { group_entry = moby_group_member_lists[moby->group]; @@ -505,7 +508,7 @@ void activate_waiting_moby_group_members(struct Moby *moby) { (struct Moby *)((*(unsigned short *)group_entry & 0x7FFF) * 256 + (int)moby_array_base); if (listed_entity->state == MOBY_GROUP_MEMBER_WAITING_FOR_ACTIVATION) - listed_entity->state = 2; + listed_entity->state = MOBY_GROUP_MEMBER_ACTIVATE; } while (*group_entry++ >= 0); } } From 0fd8f49e2f3ed5ddcb7ae817dd9abedbe8ff308d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:40:25 +0000 Subject: [PATCH 1140/1502] decomp: clarify names in update_unfolding_column_piece domain_0_value_1 -> UNFOLDING_COLUMN_PIECE_INITIALIZED: This assignment targets the same moby state byte +0x20 read at retail 003061dc. In the established MOBY_PVARS_INITIALIZE branch, 003061f8 loads pvars +0x78; 00306204 sets byte +0x28 to 4, and 00306208/0c/10 clear short +0x3E, int +0x20 and short +0x24. Then 00306200 loads 1 and 00306218 stores it to moby state, exactly as the original decompilation and authoritative C show. Thus 1 identifies the piece after its pvars initialization completes, supporting INITIALIZED without inferring later behavior. domain_1_value_3 -> UNFOLDING_COLUMN_PIECE_RELEASED: The authoritative source header documents the column releasing this piece through state 2, already named UNFOLDING_COLUMN_PIECE_RELEASE in this exact selector domain. Retail 003061dc reads moby state +0x20, 003061e4/e8 selects 2, 003061ec loads pvars +0x78, and 0030621c/24 marks short +0x3E with 5. Retail 00306220 loads 3 and 0030622c writes it back to the same moby state byte. Original Ghidra and current C agree: 3 is the state after the documented release action has been applied, supporting RELEASED without naming the unknown pvars field. --- src/overlays/l14/mobys/unfolding_column_piece.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/unfolding_column_piece.c b/src/overlays/l14/mobys/unfolding_column_piece.c index cf4949db3e..5e4a119087 100644 --- a/src/overlays/l14/mobys/unfolding_column_piece.c +++ b/src/overlays/l14/mobys/unfolding_column_piece.c @@ -10,6 +10,10 @@ void unfolding_column_piece_update(void *updated_moby) { MOBY_PVARS_INITIALIZE = 0, UNFOLDING_COLUMN_PIECE_RELEASE = 2 }; + enum { + UNFOLDING_COLUMN_PIECE_INITIALIZED = 1, + UNFOLDING_COLUMN_PIECE_RELEASED = 3 + }; struct Moby *moby = updated_moby; char *moby_pvars; switch ((unsigned char)((char)moby->state)) { @@ -19,11 +23,11 @@ void unfolding_column_piece_update(void *updated_moby) { *(int *)(moby_pvars + 0x20) = 0; *(short *)(moby_pvars + 0x24) = 0; *(short *)(moby_pvars + 0x3E) = 0; - moby->state = 1; + moby->state = UNFOLDING_COLUMN_PIECE_INITIALIZED; break; case UNFOLDING_COLUMN_PIECE_RELEASE: *(short *)(((char *)moby->pvars) + 0x3E) = 5; - moby->state = 3; + moby->state = UNFOLDING_COLUMN_PIECE_RELEASED; break; } } From 18153a51393b847893d45a98baecaed362a37f7a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:44:16 +0000 Subject: [PATCH 1141/1502] decomp: clarify names in request_taxi_stop_prompt domain_0_value_5 -> TAXI_STATE_BLEND_PATH_END_TO_STOP: Retail 002f1408 loads state from the supplied taxi Moby+0x20; 002f13fc/002f140c compare it with 5, selecting target stop pvars+0xB6 at 002f1414 instead of picked +0xB4. Same-object caller flow is checked at 002f0544 (s4=a0), 002f05a4 (state switch), and 002f0e0c/002f0e10 (passes s4 to this prompt). Caller 002f0c50-002f0c6c enters state 5 when advance_moby_path completes, clearing t/tv; 002f0ca8-002f0ce8 loads points[target] stop position/rotation, 002f0cec-002f0d24 samples path end and interpolates toward the stop, and 002f0d64-002f0d8c returns to wait state 1 at blend completion. This is the exact taxi Moby state domain whose source enum already names 5 TAXI_STATE_BLEND_PATH_END_TO_STOP, not a control/request or hero state. --- src/overlays/l14/mobys/taxi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/taxi.c b/src/overlays/l14/mobys/taxi.c index 41d89ae43d..b2e1fdba8a 100644 --- a/src/overlays/l14/mobys/taxi.c +++ b/src/overlays/l14/mobys/taxi.c @@ -469,9 +469,12 @@ struct Moby *find_group_moby_by_tag(struct Moby *moby, int tag) { extern void try_set_help_message(int, int) __asm__("FUN_00215130"); void request_taxi_stop_prompt(struct Moby *moby) { + enum { + TAXI_STATE_BLEND_PATH_END_TO_STOP = 5 + }; char *taxi_prompt_vars = (char *)moby->pvars; int taxi_stop_index = *(short *)(taxi_prompt_vars + 0xB4); - if (moby->state == 5) { + if (moby->state == TAXI_STATE_BLEND_PATH_END_TO_STOP) { taxi_stop_index = *(short *)(taxi_prompt_vars + 0xB6); } switch (taxi_stop_index) { From ee2b25f8118e902b8656b92584a8e6a0e826057d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:47:19 +0000 Subject: [PATCH 1142/1502] decomp: clarify names in _decPicture domain_0_value_3 -> FRAME_PICTURE: Retail 0x00129408 loads decoder+0x174, identified as dwPictureStructure in the prepared original Ghidra decompilation. The comparison at 0x0012940c tests 3; with second_field at +0x120 nonzero it reports 'odd number of field pictures' at 0x00129424 and clears that flag at 0x0012942c, distinguishing a frame picture from paired field pictures. The same +0x174 selector is reloaded at 0x00129430 and dispatched at 0x00129438..0x00129478; its value 3 already uses local FRAME_PICTURE in authoritative C. Thus the comparison belongs to the exact same picture-structure domain and should reuse FRAME_PICTURE, rather than infer a coding-type enum from the existing field spelling. --- src/sdk/mpeg/picture/decpicture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdk/mpeg/picture/decpicture.c b/src/sdk/mpeg/picture/decpicture.c index 884ef0035d..c85c6f264a 100644 --- a/src/sdk/mpeg/picture/decpicture.c +++ b/src/sdk/mpeg/picture/decpicture.c @@ -32,7 +32,7 @@ s32 _decPicture(struct MpegDecoderState *decoder) { s32 decode_succeeded; struct MpegReferenceImage *reference; - if (decoder->picture_coding_type == 3 && decoder->second_field != 0) { + if (decoder->picture_coding_type == FRAME_PICTURE && decoder->second_field != 0) { _Error(decoder, odd_field_picture_count_error_message); decoder->second_field = 0; } From fff6761c4a2619d5085960a1fc3c628b9a4468e3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:48:58 +0000 Subject: [PATCH 1143/1502] decomp: clarify names in _skipMB0 domain_0_value_2 -> MPEG_PICTURE_CODING_TYPE_P: The authoritative selector is decoder->picture_coding_type at offset 0x150, already containing canonical MPEG_PICTURE_CODING_TYPE_I=1. Assigned retail 0x00127b70-0x00127b88 tests 2 and clears forward motion predictors for skipped macroblocks. Checked _decMB0 retail 0x00127c54-0x00127c68 copies this exact field into IPU_CTRL picture-coding-type bits 24..26; 0x00128018-0x00128070 supplies zero forward prediction when type 2 lacks intra/forward flags. Checked motion consumer 0x0012579c-0x001257bc enters forward-reference prediction for type 2 even without explicit forward flag, whereas backward prediction at 0x00125c28 requires flag 4. This establishes the MPEG predictive P-picture domain, rather than an unrelated mode sharing number 2. domain_1_value_2 -> MPEG_MOTION_TYPE_FRAME: Assigned retail 0x00127b8c-0x00127ba0 stores 2 through a2 when decoder picture_structure at 0x174 equals frame structure 3. Checked _slice0 0x00127a94 and 0x00127ac4 carries this exact output via sp+0x4c to motion-compensation t0; 0x001255d4 forwards it to 0x00125740, where 0x00125768 saves it as s4. Frame-structure dispatch at 0x001257bc-0x00125814 selects mode 2 for a single 16-line prediction from the frame reference at decoder+0x1b8 with no field selection. Sibling decode 0x00127cb4-0x00127ce0 supplies 2 for frame_pred_frame_dct, otherwise reading the two-bit MPEG motion type. Thus this assignment is frame motion type, not picture_structure value 2. domain_2_value_1 -> MPEG_MOTION_TYPE_FIELD: Assigned retail 0x00127b94-0x00127bb4 stores mode 1 for non-frame pictures and initializes both motion-reference selectors from picture_structure==2. Checked _slice0 0x00127a94/0x00127ac4 forwards that output unchanged through sp+0x4c to _motionComp0 and its child 0x00125740 (saved s4 at 0x00125768). Non-frame mode-1 dispatch at 0x00125a24-0x00125a70 selects a single field reference using the supplied selector and predicts 16 lines; mode 2 instead makes two 8-line predictions at 0x00125a74-0x00125b40. Frame-picture mode 1 also selects fields and makes two field predictions at 0x00125818-0x00125898 with vertical motion divided by two. These behaviors prove field motion type 1 in this output domain. --- src/sdk/mpeg/macroblock/skip_mb0.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/sdk/mpeg/macroblock/skip_mb0.c b/src/sdk/mpeg/macroblock/skip_mb0.c index fd5e8a3d84..fb0ba37a7d 100644 --- a/src/sdk/mpeg/macroblock/skip_mb0.c +++ b/src/sdk/mpeg/macroblock/skip_mb0.c @@ -25,6 +25,11 @@ s32 _skipMB0(struct MpegDecoder *decoder, enum { MPEG_PICTURE_CODING_TYPE_I = 1 }; + enum { + MPEG_MOTION_TYPE_FIELD = 1, + MPEG_PICTURE_CODING_TYPE_P = 2, + MPEG_MOTION_TYPE_FRAME = 2 + }; s32 buf_offset; s32 bottom_field; s32 ok; @@ -33,16 +38,16 @@ s32 _skipMB0(struct MpegDecoder *decoder, buf_offset = decoder->mb_buf_index * 0x140; *(s32 *)((u8 *)(((u8 *)decoder + (buf_offset))) + 0x6CC) = 1; decoder->dc_reset = 1; - if (decoder->picture_coding_type == 2) { + if (decoder->picture_coding_type == MPEG_PICTURE_CODING_TYPE_P) { skip_state->unk14 = 0; skip_state->unk10 = 0; skip_state->unk4 = 0; skip_state->unk0 = 0; } if (decoder->picture_structure == 3) { - *picture_structure_mode = 2; + *picture_structure_mode = MPEG_MOTION_TYPE_FRAME; } else { - *picture_structure_mode = 1; + *picture_structure_mode = MPEG_MOTION_TYPE_FIELD; bottom_field = decoder->picture_structure == 2; motion_reference->unk4 = bottom_field; motion_reference->unk0 = bottom_field; From 73ed3bbb0e7a49e475e2e6888cb8ed9bb86214ce Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:52:04 +0000 Subject: [PATCH 1144/1502] decomp: clarify names in update_gold_bolt_visuals domain_0_value_1 -> GOLD_BOLT_WAIT_FOR_PICKUP: Retail 0x00308390 preserves the incoming gold bolt Moby in s0; 0x003083a4 loads its state byte at +0x20, and 0x00308398/0x003083b0 compare it with 1, skipping bobbing/spin unless equal. Original Ghidra confirms *(char *)(iVar3 + 0x20) == 1. The authoritative source gold_bolt_update switches on this same Moby state field, assigns GOLD_BOLT_WAIT_FOR_PICKUP = 1 after initializing saved home position and spin increments, and its waiting case performs the same home-Z sine bobbing and rotations before checking hero proximity and entering GOLD_BOLT_PICKUP_CUTSCENE. spawn_gold_bolt_particles also names the same gold bolt Moby state comparison GOLD_BOLT_WAIT_FOR_PICKUP. Thus the selector belongs to the established gold bolt state domain, rather than any equal-valued hero enum. --- src/overlays/shared/pickups/gold_bolt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/pickups/gold_bolt.c b/src/overlays/shared/pickups/gold_bolt.c index 736784c4c3..fe3c478e1d 100644 --- a/src/overlays/shared/pickups/gold_bolt.c +++ b/src/overlays/shared/pickups/gold_bolt.c @@ -620,12 +620,15 @@ void gold_bolt_update(struct Moby *moby) { void update_gold_bolt_visuals(struct Moby *moby) __asm__("FUN_L01_00308380"); void update_gold_bolt_visuals(struct Moby *moby) { + enum { + GOLD_BOLT_WAIT_FOR_PICKUP = 1 + }; char *gold_bolt_visual_vars = (char *)moby->pvars; float updated_rotation_z; float bobbing_sine; float k; moby->scale = moby->pclass->scale * *(float *)&D_L01_00161F10_gp; - if (moby->state == 1) { + if (moby->state == GOLD_BOLT_WAIT_FOR_PICKUP) { bobbing_sine = fast_sin(moby->rot.w); moby->pos.z = *(float *)(gold_bolt_visual_vars + 0x18) + *(float *)&l01_gold_bolt_bobbing_height_offset_gp + *(float *)&l01_gold_bolt_bobbing_amplitude_gp * bobbing_sine; From 6075276540f1bb854d5099713822558208ace1a8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:55:50 +0000 Subject: [PATCH 1145/1502] decomp: clarify names in _pictureData0 domain_0_value_1 -> DECODE_STATUS_SLICE_DECODE_ERROR: The authoritative source assigns _slice0's return to decode_status; retail 0x0012776c-0x00127778 saves that return in s0 and retries when it equals 1. Checked retail _slice0 branches at 0x00127a18 to 0x00127a80 after _mbAddressIncrement leaves slice_error (+0x11c) nonzero, and at 0x00127a78 falls into the same path after _decMB0 fails. That path clears slice_error and returns 1 at 0x00127a88. These are slice decoding errors, distinct from status 2 aborts and status 3 lookahead termination. domain_2_value_1 -> DECODE_STATUS_SLICE_DECODE_ERROR: This comparison reads the same decode_status assigned from _slice0 at retail 0x00127774. _slice0 returns 1 at 0x00127a88 for macroblock-address decode errors or _decMB0 failure, as proven by branches 0x00127a18 and 0x00127a78. In _pictureData0, 0x001277a8 computes status-1 and 0x001277e4-0x001277f8 reports '= Skip to the next picture =' for statuses 1/2. It is the identical slice-decode status domain as the retry comparison, so both eligible value-1 occurrences reuse DECODE_STATUS_SLICE_DECODE_ERROR. --- src/sdk/mpeg/picture/_pictureData0.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sdk/mpeg/picture/_pictureData0.c b/src/sdk/mpeg/picture/_pictureData0.c index 1108e43099..e7e348edce 100644 --- a/src/sdk/mpeg/picture/_pictureData0.c +++ b/src/sdk/mpeg/picture/_pictureData0.c @@ -21,6 +21,9 @@ s32 _pictureData0(MpegDec *decoder) { DECODE_STATUS_SUCCESS = 0, DECODE_STATUS_ABORT_PICTURE = 2 }; + enum { + DECODE_STATUS_SLICE_DECODE_ERROR = 1 + }; s32 decode_status; s32 mbs; @@ -32,7 +35,7 @@ s32 _pictureData0(MpegDec *decoder) { } do { decode_status = _slice0(decoder, mbs); - } while (decode_status == 1 || decode_status == 3); + } while (decode_status == DECODE_STATUS_SLICE_DECODE_ERROR || decode_status == 3); _waitIpuIdle(decoder); if (_waitBdecOut(decoder) == 0) { decode_status = DECODE_STATUS_ABORT_PICTURE; @@ -42,7 +45,7 @@ s32 _pictureData0(MpegDec *decoder) { if (decode_status == DECODE_STATUS_SUCCESS) { _doMC(decoder, decoder->unk810 == 0); } - if (decode_status == 1 || decode_status == DECODE_STATUS_ABORT_PICTURE) { + if (decode_status == DECODE_STATUS_SLICE_DECODE_ERROR || decode_status == DECODE_STATUS_ABORT_PICTURE) { _Error(decoder, skip_to_next_picture_error_message); } return decode_status == DECODE_STATUS_SUCCESS; From 6ca0dfa117bf1171e3b5edce5655321a2f79ac9a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:57:39 +0000 Subject: [PATCH 1146/1502] decomp: clarify names in spawn_timed_hero_relative_particle domain_0_value_1 -> PARTICLE_MODE_HERO_RELATIVE: Retail 00272fa4 retains mode from t2 in s1; 00272fc8-00272fd0 compares it with 1 and stores it at particle+0x30. Only that branch calls fast_vec_sub at 00272fdc with destination particle+0x20, input position in s2/a1, and D_0013F3D0 in a2, initializing position minus the hero reference. Original Ghidra param_8 == 1 agrees. The authoritative source's update_timed_hero_relative_particle tests the same +0x30 mode against 1 and adds hero.motion.pos to this payload offset to reconstruct particle+0x10. Nanotech collection callers pass mode 1 and infobot passes 0. This proves a hero-relative particle position mode, independently of unrelated hero state/gravity/vehicle constants. --- src/overlays/shared/rendering/effects/particles.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/rendering/effects/particles.c b/src/overlays/shared/rendering/effects/particles.c index b39145d8ee..3ab0ee177e 100644 --- a/src/overlays/shared/rendering/effects/particles.c +++ b/src/overlays/shared/rendering/effects/particles.c @@ -936,11 +936,14 @@ unsigned char *spawn_timed_hero_relative_particle(u128 *position, int mode, float size_scale) { + enum { + PARTICLE_MODE_HERO_RELATIVE = 1 + }; unsigned char *particle = create_part(0x3B); if (particle) { int *particle_data = (int *)(particle + 0x20); particle_data[4] = mode; - if (mode == 1) + if (mode == PARTICLE_MODE_HERO_RELATIVE) fast_vec_sub(particle_data, position, D_0013F3D0); qcopy(particle + 0x10, position); *(int *)(particle + 4) = packed_color; From c74b6c35155642923a1eb103cc8f6edba3bae143 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:59:17 +0000 Subject: [PATCH 1147/1502] decomp: clarify names in process_dreks_fleet_turret_hits domain_0_value_1 -> HIT_REACTION_NO_DAMAGE: Retail caller 0x002cbc84 passes sp as fifth argument to hit_reaction at 0x002cbc94; 0x002cbc9c-0x002cbca4 tests this output against 1 to skip subtraction and hit-animation restart. Checked level-17 helper 0x00254d78 preserves this output pointer in s3. With no hit record (s4==0), 0x00254e78-0x00254e9c writes status 1 and 0x00254ea0-0x00254ea8 writes zero to the sixth-argument float output. The suppression path 0x00255234-0x00255248 likewise writes status 1 and clears hit_record+0x2c, which 0x00255264-0x00255274 copies to the float output. Thus 1 denotes the no-damage outcome, not turret depletion or a Moby/Hero state. --- src/overlays/l17/mobys/dreks_fleet_turret.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l17/mobys/dreks_fleet_turret.c b/src/overlays/l17/mobys/dreks_fleet_turret.c index fbd036f7b3..175db88d97 100644 --- a/src/overlays/l17/mobys/dreks_fleet_turret.c +++ b/src/overlays/l17/mobys/dreks_fleet_turret.c @@ -301,6 +301,9 @@ void process_dreks_fleet_turret_hits(struct Moby *turret_moby) { FLEET_TURRET_DESTROY = 4, FLEET_TURRET_NOT_DEPLETED = 0xB }; + enum { + HIT_REACTION_NO_DAMAGE = 1 + }; char *turret_vars; char *hit_animation_state; char *hit_record; @@ -323,7 +326,7 @@ void process_dreks_fleet_turret_hits(struct Moby *turret_moby) { hit_animation_state = turret_vars + 0x60; hit_reaction( turret_moby, hit_record, turret_vars + 0x20, 0, &hit_reaction_status, &fv, 0, 4); - if (hit_reaction_status != 1 && turret_moby->state != FLEET_TURRET_DESTROY) { + if (hit_reaction_status != HIT_REACTION_NO_DAMAGE && turret_moby->state != FLEET_TURRET_DESTROY) { float remaining_value = *(float *)(turret_vars + 0x20) - fv; *(float *)(turret_vars + 0x20) = remaining_value; depletion_status = FLEET_TURRET_NOT_DEPLETED; From 6beff9f16ae7602f0251b2dbe614edfe2e9003fa Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 20:59:17 +0000 Subject: [PATCH 1148/1502] decomp: clarify names in sceMcGetDir domain_0_value_0 -> RPC_SUBMISSION_SUCCESS: Retail sceMcGetDir calls sceSifCallRpc for command 0xD with mode 1 at 0x00123fe0, saves its return in s0 at 0x00123fe8, and compares it with zero at 0x00123fec. The zero branch stores pending command 0xD at 0x00123ffc; the nonzero branch releases mc_sema at 0x00124000. Original Ghidra and the SHA-bound C agree. Supplied sceSifCallRpc mode-1 flow returns zero when sceSifSendCmd succeeds and negative values on failures. Supplied callers subsequently use sceMcSync for completion, proving this zero denotes RPC submission success rather than directory-query completion. --- src/sdk/storage/memory_card/sce_mc_get_dir.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/storage/memory_card/sce_mc_get_dir.c b/src/sdk/storage/memory_card/sce_mc_get_dir.c index a741b16f90..57eaf4a164 100644 --- a/src/sdk/storage/memory_card/sce_mc_get_dir.c +++ b/src/sdk/storage/memory_card/sce_mc_get_dir.c @@ -21,6 +21,9 @@ extern s32 sceSifWriteBackDCache(); extern s32 strncpy(s8 *, s8 *, s32); s32 sceMcGetDir(s32 port, s32 slot, s8 *name, s32 mode, s32 maxent, s32 table) { + enum { + RPC_SUBMISSION_SUCCESS = 0 + }; s32 rpc_submission_status; s32 request_status; register s32 path_arg = slot; @@ -46,7 +49,7 @@ s32 sceMcGetDir(s32 port, s32 slot, s8 *name, s32 mode, s32 maxent, s32 table) { } rpc_submission_status = sceSifCallRpc( &mc_rpc_client, MC_FUNC_GET_DIR, 1, &D_00159AB0, 0x414, mc_rpc_result, 4, 0, 0); - if (rpc_submission_status == 0) { + if (rpc_submission_status == RPC_SUBMISSION_SUCCESS) { mc_current_func = MC_FUNC_GET_DIR; } else { SignalSema(mc_sema); From c8da29fda2891e484012fb6dea63fefe6bc89d53 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:00:59 +0000 Subject: [PATCH 1149/1502] decomp: clarify names in sceMcChdir domain_0_value_0 -> RPC_DISPATCH_SUCCESS: In source sceMcChdir, rpc_dispatch_status receives sceSifCallRpc with mode 1. Retail 0x001241a8 calls RPC, 0x001241b0 saves v0 in s0, and 0x001241b4 branches on nonzero to SignalSema at 0x001241c8. The zero path records MC_FUNC_CHDIR (0xC) at 0x001241bc-0x001241c4. Original Ghidra likewise tests iVar1 == 0 before recording the pending request. Supplied sceSifCallRpc mode-1 source returns 0 when sceSifSendCmd succeeds, and -2 when it fails. The caller proceeds from MEMCARD_REQUEST_CHDIR to a separate completion-processing state when sceMcChdir returns zero. Thus this zero names successful immediate RPC dispatch, not completed chdir. --- src/sdk/storage/memory_card/sce_mc_chdir.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/storage/memory_card/sce_mc_chdir.c b/src/sdk/storage/memory_card/sce_mc_chdir.c index f8c08d421e..179654adfc 100644 --- a/src/sdk/storage/memory_card/sce_mc_chdir.c +++ b/src/sdk/storage/memory_card/sce_mc_chdir.c @@ -21,6 +21,9 @@ extern s32 sceSifWriteBackDCache(); extern s32 strncpy(s8 *, s8 *, s32); s32 sceMcChdir(s32 port, s32 slot, s8 *path, s32 pwd) { + enum { + RPC_DISPATCH_SUCCESS = 0 + }; s32 rpc_dispatch_status; s32 chdir_request_status; @@ -48,7 +51,7 @@ s32 sceMcChdir(s32 port, s32 slot, s8 *path, s32 pwd) { 4, &mceStorePwd, pwd); - if (rpc_dispatch_status == 0) { + if (rpc_dispatch_status == RPC_DISPATCH_SUCCESS) { mc_current_func = MC_FUNC_CHDIR; } else { SignalSema(mc_sema); From af5235e91f4152bddaab2e9ad0ab6ddebd46e082 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:00:59 +0000 Subject: [PATCH 1150/1502] decomp: clarify names in _pictureData0 domain_0_value_3 -> DECODE_STATUS_SLICE_LOOKAHEAD_STOP: Authoritative source src/sdk/video/mpeg/picture/_pictureData0.c SHA-256 5c34786c5cb58c6d4d56f0d672a868654472f9a3a999701257622994ea096b1c assigns decode_status directly from _slice0. Retail 0x00127774 saves that return in s0 and 0x00127780 compares it against 3 to repeat _slice0. Checked helper _slice0 at 0x001279e4 peeks 23 bits before decoding the next macroblock address; zero lookahead at 0x001279ec or nonzero decoder slice_error at 0x001279f4-0x001279f8 clears that error and reaches 0x00127a04-0x00127a08, returning 3 instead of proceeding to address decoding at 0x00127a0c. Thus this status stops slice processing at the lookahead check and the caller retries. It is the same decode-status domain as existing local DECODE_STATUS constants, not picture-structure value 3. --- src/sdk/mpeg/picture/_pictureData0.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdk/mpeg/picture/_pictureData0.c b/src/sdk/mpeg/picture/_pictureData0.c index e7e348edce..3dbfe80d47 100644 --- a/src/sdk/mpeg/picture/_pictureData0.c +++ b/src/sdk/mpeg/picture/_pictureData0.c @@ -24,6 +24,9 @@ s32 _pictureData0(MpegDec *decoder) { enum { DECODE_STATUS_SLICE_DECODE_ERROR = 1 }; + enum { + DECODE_STATUS_SLICE_LOOKAHEAD_STOP = 3 + }; s32 decode_status; s32 mbs; @@ -35,7 +38,7 @@ s32 _pictureData0(MpegDec *decoder) { } do { decode_status = _slice0(decoder, mbs); - } while (decode_status == DECODE_STATUS_SLICE_DECODE_ERROR || decode_status == 3); + } while (decode_status == DECODE_STATUS_SLICE_DECODE_ERROR || decode_status == DECODE_STATUS_SLICE_LOOKAHEAD_STOP); _waitIpuIdle(decoder); if (_waitBdecOut(decoder) == 0) { decode_status = DECODE_STATUS_ABORT_PICTURE; From b2da40eeccd3d102599b58bc12d32bb9604abb6d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:03:13 +0000 Subject: [PATCH 1151/1502] decomp: clarify names in mode_freeze_init domain_1_value_4 -> GAME_MODE_FREEZE: The established mode_freeze_init saves game_mode into freeze.return_game_mode, sets game_mode=4, retains incoming mode separately in freeze.state and initializes freeze messages/timers. Original Ghidra likewise saves g_nGameStage to DAT_00193314 then assigns stage 4. Retail 0x001fbaf4-0x001fbb08 loads the prior mode at 0x0015F604 and saves it to freeze +0x14; 0x001fbb04 loads a0=4 and 0x001fbb1c stores it to that same game-mode global. Incoming a0 was separately preserved in s0 at 0x001fbad8 and is stored to freeze +0 at 0x001fbb24 before dispatch. Thus 4 identifies the global freeze game mode, independently of freeze selector 4 (vehicle pause). --- src/game/mode_freeze_init.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/game/mode_freeze_init.c b/src/game/mode_freeze_init.c index 678ba08ce1..9466bb2533 100644 --- a/src/game/mode_freeze_init.c +++ b/src/game/mode_freeze_init.c @@ -19,6 +19,9 @@ void mode_freeze_init(u32 mode, s32 freeze_context) { FREEZE_PUSH_HELP_HISTORY = 5, FREEZE_VIDEO_MODE_CHANGE = 6 }; + enum { + GAME_MODE_FREEZE = 4 + }; FreezeModeState *freeze_state; if (game_mode != 3) { @@ -27,7 +30,7 @@ void mode_freeze_init(u32 mode, s32 freeze_context) { } freeze.return_game_mode = game_mode; freeze.context = freeze_context; - game_mode = 4; + game_mode = GAME_MODE_FREEZE; freeze.state = mode; switch (mode) { case FREEZE_CONTROL_MODE_16_PAUSE: From 1725134d9bf5dc14116f28a78302457f639a24f7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:03:13 +0000 Subject: [PATCH 1152/1502] decomp: clarify names in process_blarg_heavy_interceptor_hit_reactions domain_0_value_1 -> HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE: Retail 0x002ad8f8 passes sp as hit_reaction's fifth-argument output; 0x002ad90c-0x002ad914 loads it and branches on status 1 to 0x002ad9ec, bypassing health subtraction, reaction dispatch and trooper_anim_update. Checked level-14 helper 0x002628b0 saves this pointer in s3; absent-hit path 0x002629b0-0x002629e8 writes 1 and zero damage, and suppression path 0x00262d74-0x00262d80 also writes 1 and clears damage. The helper separately returns reaction s1 at 0x00262de8. Thus this is a damage-response bypass status, not HIT_REACTION_LETHAL=1 or a moby/hero state. --- src/overlays/l14/mobys/blarg_heavy_interceptor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/blarg_heavy_interceptor.c b/src/overlays/l14/mobys/blarg_heavy_interceptor.c index e4da24d936..b97a2f4efe 100644 --- a/src/overlays/l14/mobys/blarg_heavy_interceptor.c +++ b/src/overlays/l14/mobys/blarg_heavy_interceptor.c @@ -789,7 +789,7 @@ void process_blarg_heavy_interceptor_hit_reactions(struct Moby *moby) { HIT_REACTION_LOW_RED_FLASH_AND_HIT_ANIMATION = 10, HIT_REACTION_NONE = 11 } ; enum { INTERCEPTOR_STATE_PATROL_AND_SCAN = 1 , INTERCEPTOR_STATE_ALERT_GROUP = 2 , INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL = 7}; - BlargHeavyInterceptorVars *blarg_heavy_interceptor_vars = + enum { HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE = 1 } ;BlargHeavyInterceptorVars *blarg_heavy_interceptor_vars = (BlargHeavyInterceptorVars *)moby->pvars; int hit_reaction_status; float damage_amount; @@ -803,7 +803,7 @@ void process_blarg_heavy_interceptor_hit_reactions(struct Moby *moby) { &damage_amount, 0, 4); - if (hit_reaction_status != 1 && moby->state < INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL) { + if (hit_reaction_status != HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE && moby->state < INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL) { float remaining_health = blarg_heavy_interceptor_vars->health - damage_amount; blarg_heavy_interceptor_vars->health = remaining_health; if (remaining_health <= 0.0f) From 18e2bf8ed4fa3527824cae4d12571548f1d6bd67 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:03:13 +0000 Subject: [PATCH 1153/1502] decomp: clarify names in update_owner_linked_moby_state domain_0_value_254 -> MOBY_STATE_MARKED_FOR_REMOVAL: Assigned retail 0031003c-00310054 loads owner_moby from this moby's pvars+0x70 and compares its state byte at +0x20 with FE. Checked mark_moby_for_removal helper at level-11 00274998, called by assigned 00310160, selects FE at 002749bc and writes it to the same Moby state offset +0x20 at 002749c0. This proves FE marks a Moby for removal rather than being one of this class's local states 0..4. The helper's alternate FD marker remains unnamed because the address-boundary meaning is unresolved. --- src/overlays/l11/mobys/owner_linked_moby.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l11/mobys/owner_linked_moby.c b/src/overlays/l11/mobys/owner_linked_moby.c index d5148bee06..b6f108c34f 100644 --- a/src/overlays/l11/mobys/owner_linked_moby.c +++ b/src/overlays/l11/mobys/owner_linked_moby.c @@ -105,11 +105,11 @@ void owner_linked_moby_update(struct Moby *moby) { LINKED_MOBY_STATE_HANDLE_HITS = 2, LINKED_MOBY_STATE_FADE_OUT = 3, LINKED_MOBY_STATE_REMOVE = 4 - }; + } ; enum { MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE}; OwnerLinkedMobyVars *owner_linked_moby_vars = (OwnerLinkedMobyVars *)moby->pvars; char *health_ptr = &owner_linked_moby_vars->unk20; struct Moby *owner_moby = owner_linked_moby_vars->unk70; - if (owner_moby == 0 || owner_moby->state == 0xFE || owner_moby->state == 0xFD) { + if (owner_moby == 0 || owner_moby->state == MOBY_STATE_MARKED_FOR_REMOVAL || owner_moby->state == 0xFD) { if (moby->state < LINKED_MOBY_STATE_FADE_OUT) { moby->state = LINKED_MOBY_STATE_REMOVE; } From 4a84ea973fb05e103bf1ef18bfad588c0bf980a9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:05:15 +0000 Subject: [PATCH 1154/1502] decomp: clarify names in cvt domain_0_value_3 -> DTOA_MODE_FRACTIONAL_DIGITS: Retail 0x00118384-0x00118390 selects s3=3 only for ch=='f'; 0x001183d8 passes s3 as _dtoa_r's mode at 0x001183f0. In the same 'f' branch, 0x00118420 and 0x00118450-0x00118454 form the output boundary as digits+ndigits+*decpt, then 0x00118480-0x00118498 pad with zeros. Thus ndigits counts digits after the decimal point for this mode, rather than total significant digits. Authoritative C and original Ghidra show identical flow. domain_1_value_2 -> DTOA_MODE_SIGNIFICANT_DIGITS: Retail 0x00118394-0x001183ac selects mode 2 for non-'f' conversions and increments ndigits for 'e'/'E' to include the leading significant digit. 0x001183d8 and 0x001183e4 forward mode and adjusted ndigits to _dtoa_r at 0x001183f0. Unlike 'f', the non-'f' padding boundary at 0x00118420 is digits+ndigits without adding *decpt; the 'g'/'G' checks at 0x001183fc-0x00118414 suppress padding unless ALT. This proves the total significant-digit precision role in the source and original Ghidra. --- src/sdk/libc/stdio/cvt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/sdk/libc/stdio/cvt.c b/src/sdk/libc/stdio/cvt.c index 811fdf497d..caf67a6a53 100644 --- a/src/sdk/libc/stdio/cvt.c +++ b/src/sdk/libc/stdio/cvt.c @@ -42,17 +42,21 @@ static s8 *cvt(struct _reent *reentrancy_state, s32 ch, s32 *length) { + enum { + DTOA_MODE_SIGNIFICANT_DIGITS = 2, + DTOA_MODE_FRACTIONAL_DIGITS = 3 + }; s32 mode, dsgn; s8 *digits, *bp, *rve; double_union value_bits; if (ch == 'f') { - mode = 3; + mode = DTOA_MODE_FRACTIONAL_DIGITS; } else { if (ch == 'e' || ch == 'E') { ndigits++; } - mode = 2; + mode = DTOA_MODE_SIGNIFICANT_DIGITS; } value_bits.d = number_to_format; if (word0(value_bits) & Sign_bit) { From 97b361dadab33910666e47a1e5b7d74c24c97aba Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:07:18 +0000 Subject: [PATCH 1155/1502] decomp: clarify names in update_swing_gate domain_0_value_1 -> SWING_GATE_WAIT_FOR_OPEN_CONDITION: Retail 0031b438 loads 1 and 0031b440 stores it to +0x20(s1), the identical moby->state byte dispatched at 0031b410. Original Ghidra case 0 resets Y rotation and velocity before this assignment. The authoritative local enum already names this selector's case 1 SWING_GATE_WAIT_FOR_OPEN_CONDITION, whose branch waits on configured target openState at 0031b44c-0031b484. domain_10_value_1 -> SWING_GATE_WAIT_FOR_OPEN_CONDITION: Retail 0031b5b8 tests the updated return rotation against zero; 0031b5c8 and 0031b5d0 clear Y rotation and velocity, then 0031b5cc loads 1 for the +0x20(s1) store at 0031b5d4. This is the same moby->state byte dispatched at 0031b410 and named case 1 SWING_GATE_WAIT_FOR_OPEN_CONDITION in the authoritative local enum. domain_3_value_3 -> SWING_GATE_SWINGING: Retail 0031b498-0031b4b0 seeds angular velocity and Y rotation from speed times frame_time, then 0031b4b4 loads 3 and 0031b4bc stores it to +0x20(s1). That byte is this gate's switch selector at 0031b410; its existing case 3 SWING_GATE_SWINGING performs cosine-driven rotation integration and damping at 0031b4c0-0031b51c. domain_6_value_4 -> SWING_GATE_RETURN_TO_ZERO: Retail 0031b538 loads gate_motion->shutState and 0031b53c compares it to the indexed target's state. On equality 0031b548 loads 4, stored at 0031b5d4 into +0x20(s1), the gate's own switch selector. Its existing case 4 SWING_GATE_RETURN_TO_ZERO subtracts rate from Y rotation at 0031b5a8-0031b5ac and clamps rotation and velocity to zero. domain_9_value_2 -> SWING_GATE_HOLD_ROTATION: In original Ghidra case 4, absent/invalid target or configured openState takes the bypass at 0031b54c-0031b584. After the existing helper call, 0031b59c loads 2 and 0031b5a4 stores it to +0x20(s1), the same gate state dispatched at 0031b410. The authoritative local enum already names case 2 SWING_GATE_HOLD_ROTATION; its no-op preserves rotation on subsequent updates. --- src/overlays/l07/mobys/swing_gate.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l07/mobys/swing_gate.c b/src/overlays/l07/mobys/swing_gate.c index 4c21de3ed5..fffe588966 100644 --- a/src/overlays/l07/mobys/swing_gate.c +++ b/src/overlays/l07/mobys/swing_gate.c @@ -42,7 +42,7 @@ void swing_gate_update(struct Moby *moby) { switch (moby->state) { case SWING_GATE_INITIALIZE: moby->rot.y = 0; - moby->state = 1; + moby->state = SWING_GATE_WAIT_FOR_OPEN_CONDITION; gate_motion->vel = 0; break; case SWING_GATE_WAIT_FOR_OPEN_CONDITION: @@ -53,7 +53,7 @@ void swing_gate_update(struct Moby *moby) { gate_motion->vel = gate_motion->speed * frame_time; moby->rot.y = gate_motion->vel; allocate_voice_for_target_entry(0, 0, moby); - moby->state = 3; + moby->state = SWING_GATE_SWINGING; break; case SWING_GATE_HOLD_ROTATION: break; @@ -67,14 +67,14 @@ void swing_gate_update(struct Moby *moby) { break; if (target->state != gate_motion->shutState) return; - moby->state = 4; + moby->state = SWING_GATE_RETURN_TO_ZERO; break; case SWING_GATE_RETURN_TO_ZERO: if (gate_motion->target == -1 || (target = &D_L07_0015FFD8[gate_motion->target]) == 0 || target->state == 0xFE || target->state == 0xFD || target->state == gate_motion->openState) { allocate_voice_for_target_entry(0, 0, moby); - moby->state = 2; + moby->state = SWING_GATE_HOLD_ROTATION; break; } updated_y_rotation = fast_subtract_rotations(moby->rot.y, gate_motion->rate); @@ -82,7 +82,7 @@ void swing_gate_update(struct Moby *moby) { if (0.0f < updated_y_rotation) { moby->rot.y = 0; gate_motion->vel = 0; - moby->state = 1; + moby->state = SWING_GATE_WAIT_FOR_OPEN_CONDITION; } break; case 5: From ea8c8cbb7e3cf47a6a830ce316fe6fe3674c3dfe Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:07:18 +0000 Subject: [PATCH 1156/1502] decomp: clarify names in handle_refueling_station_damage domain_0_value_3 -> REFUELING_STATION_STATE_EXPLODE: Assigned retail 0x00303b4c retains a0 moby in s2; 0x00303b5c loads its state byte +0x20 and 0x00303b34/60 compare against 3 to skip damage. Checked caller 0x00303d24..38 passes that same moby, then loads +0x20 at 0x00303d3c and branches on 3 at 0x00303d64..68 to 0x00303f30. That branch calls spawn_explosion at 0x00303fa0 and mark_moby_for_removal at 0x00303fa8. Authoritative caller source names this exact state REFUELING_STATION_STATE_EXPLODE=3; the selector is this same station state domain. domain_3_value_3 -> REFUELING_STATION_STATE_EXPLODE: Lethal damage path zeros health at 0x00303c18, updates feedback, then loads 3 at 0x00303ca0 and stores it to original moby state +0x20 at 0x00303ca8. Checked caller passes original moby at 0x00303d24..38 and immediately dispatches its +0x20 state at 0x00303d3c..68: value 3 enters 0x00303f30, calls spawn_explosion at 0x00303fa0 and mark_moby_for_removal at 0x00303fa8. Its established source enum calls that state REFUELING_STATION_STATE_EXPLODE=3; assignment and comparison must share that same state member. --- src/overlays/l09/mobys/refueling_station.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l09/mobys/refueling_station.c b/src/overlays/l09/mobys/refueling_station.c index 09ec6348fd..2fe961c172 100644 --- a/src/overlays/l09/mobys/refueling_station.c +++ b/src/overlays/l09/mobys/refueling_station.c @@ -96,11 +96,14 @@ void handle_refueling_station_damage(struct Moby *moby, DAMAGE_RESULT_UNAVAILABLE = 0, DAMAGE_RESULT_NO_HIT_OR_SUPPRESSED_RESPONSE = 11 }; + enum { + REFUELING_STATION_STATE_EXPLODE = 3 + }; VendorHitSource *damage_hit_record; struct Moby *link; s32 hit; - if (moby->state != 3) { + if (moby->state != REFUELING_STATION_STATE_EXPLODE) { damage_hit_record = find_moby_hit(moby, 0x330000, 0); if (damage_hit_record != 0) { debug_print(D_L09_00208F90, moby->oclass, fptodp(damage_hit_record->damage)); @@ -136,7 +139,7 @@ void handle_refueling_station_damage(struct Moby *moby, FUN_L00_00257470(moby, 0, -1); refueling_station_vars->anim[7] = 0x78; trooper_anim_update(moby, refueling_station_vars->anim); - moby->state = 3; + moby->state = REFUELING_STATION_STATE_EXPLODE; } else { *health -= damage_hit_record->damage; refueling_station_vars->anim[7] = 0xFA; From 31dc656d951bf9a23355af9cb1802080f7d10095 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:09:24 +0000 Subject: [PATCH 1157/1502] decomp: clarify names in handle_linked_moby_damage domain_0_value_3 -> LINKED_MOBY_STATE_DESTROYED: Selector is this moby's state byte +0x20: retail 0x00303fe4 saves a0 in s3, 0x00303ff4 loads +0x20 and 0x00303ff8 skips processing for 3. The same s3 state is written 3 at 0x00304180..0x00304188 only after accepted lethal damage, health zeroing (0x00304098..0x003040b0), flag clearing and linked command delivery. Checked level-09 helper 0x00276df8 called at 0x00304178 sets killed/save bits at 0x00276e5c..0x00276ed8, consistent with supplied FUN_L00_00257470 source level_moby_killed updates. Thus this is the destroyed state in this handler, not a response code or command. domain_5_value_3 -> LINKED_MOBY_STATE_DESTROYED: Retail 0x00304180 loads 3 and 0x00304188 stores it to +0x20(s3), the same moby->state tested by 0x00303ff4..0x00303ff8. This follows health<=hit damage at 0x00304098..0x003040a8, zero health at 0x003040b0, clearing flag 0x1000, notifying linked mobys and calling 0x00276df8 at 0x00304178. Checked helper 0x00276e5c..0x00276ed8 records killed/save bits, matching supplied level_moby_killed source context. Nonlethal flow instead subtracts damage and starts hurt_timer at 0x0030418c..0x0030419c. Reuse the destroyed-state member for both comparison and assignment. --- src/overlays/l09/mobys/handle_linked_moby_damage.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l09/mobys/handle_linked_moby_damage.c b/src/overlays/l09/mobys/handle_linked_moby_damage.c index 5f6f516215..22e29f3978 100644 --- a/src/overlays/l09/mobys/handle_linked_moby_damage.c +++ b/src/overlays/l09/mobys/handle_linked_moby_damage.c @@ -44,11 +44,14 @@ void handle_linked_moby_damage(struct Moby *moby, DAMAGE_RESULT_UNAVAILABLE = 0, DAMAGE_RESULT_NO_HIT_OR_SUPPRESSED_RESPONSE = 11 }; + enum { + LINKED_MOBY_STATE_DESTROYED = 3 + }; VendorHitSource *damage_hit_record; struct Moby *link; s32 hit; - if (moby->state != 3) { + if (moby->state != LINKED_MOBY_STATE_DESTROYED) { damage_hit_record = find_moby_hit(moby, 0x330000, 0); if (damage_hit_record != 0) { debug_print(D_L09_00208FF0, moby->oclass, fptodp(damage_hit_record->damage)); @@ -90,7 +93,7 @@ void handle_linked_moby_damage(struct Moby *moby, } } FUN_L00_00257470(moby, 0, -1); - moby->state = 3; + moby->state = LINKED_MOBY_STATE_DESTROYED; } else { *health -= damage_hit_record->damage; linked_moby_damage_vars->hurt_timer = scale_game_frames(60); From a938b9f22c4267e9cf2c454db3b266580d4f0d46 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:11:04 +0000 Subject: [PATCH 1158/1502] decomp: clarify names in process_blarg_gunner_hits domain_0_value_2 -> BLARG_GUNNER_STATE_DESTROY: Retail 0x002b4a74 preserves the receiving gunner moby in s0; 0x002b4a80 loads its state byte at +0x20 and 0x002b4a84 skips hit processing when it equals 2. The supplied authoritative blarg_gunner_update switches on the same moby->state and explicitly names 2 BLARG_GUNNER_STATE_DESTROY, whose branch waits for animation completion then spawns an explosion and marks that gunner for removal. Its ACTIVE branch passes that same moby and pvars to this function, proving the exact gunner-state domain. domain_3_value_2 -> BLARG_GUNNER_STATE_DESTROY: Retail 0x002b4b7c..0x002b4b94 compares effective hit damage against gunner health and takes the lethal path, clears health, updates feedback, selects animation 3 at 0x002b4bfc..0x002b4c18, then writes 2 to the receiving gunner's +0x20 state at 0x002b4c1c..0x002b4c24. Authoritative blarg_gunner_update names this same moby->state value BLARG_GUNNER_STATE_DESTROY and handles it by explosion and mark_moby_for_removal after animation completion. Reuse that established semantic member for both entry and guard. --- src/overlays/l13/mobys/blarg_gunner.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l13/mobys/blarg_gunner.c b/src/overlays/l13/mobys/blarg_gunner.c index 347212d814..f7b54ef764 100644 --- a/src/overlays/l13/mobys/blarg_gunner.c +++ b/src/overlays/l13/mobys/blarg_gunner.c @@ -111,11 +111,14 @@ void process_blarg_gunner_hits(struct Moby *moby, char *moby_vars) { enum { HIT_REACTION_NONE = 11 }; + enum { + BLARG_GUNNER_STATE_DESTROY = 2 + }; float *tm = (float *)(moby_vars + 0x20); char *hit_record; int k; int hit_reaction_result; - if (moby->state != 2) { + if (moby->state != BLARG_GUNNER_STATE_DESTROY) { hit_record = find_moby_hit(moby, 0x330000, 0); hit_reaction_result = hit_reaction(moby, hit_record, tm, 0, &k, 0, 0, 4); if (hit_record != 0) { @@ -175,7 +178,7 @@ void process_blarg_gunner_hits(struct Moby *moby, char *moby_vars) { trooper_anim_update(moby, (short *)(moby_vars + 0x60)); if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 1, 0); - moby->state = 2; + moby->state = BLARG_GUNNER_STATE_DESTROY; } else { *tm = current_health - hit_damage; *(unsigned char *)(moby_vars + 0x67) = 0xFA; From 694543d776b7dcf269a340f4421e1850bcda502a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:12:47 +0000 Subject: [PATCH 1159/1502] decomp: clarify names in process_blarg_heavy_interceptor_hit_reactions domain_0_value_3 -> HIT_REACTION_STATUS_ENABLE_HIT_PARTICLES: Retail 0x002ad8f8 passes sp as hit_reaction's fifth argument; 0x002ad960-0x002ad968 compares its status output to 3 and writes 1 to moby+0xbc (command). The authoritative source's update_blarg_heavy_interceptor calls this handler before its state machine, then invokes spawn_particles_at_shape_points only when command==1, prev_seq==1 and signed state>=0, otherwise clearing command. Thus status 3 enables hit-sequence particles, conditional on the caller's animation/state checks. Checked helper 0x002628b0 saves this output pointer in s3; 0x00262c1c-0x00262c30 selects status 3 and 0x00262c68 writes it through s3. Reaction return is independently table-loaded into s1 at 0x00262c98 and returned at 0x00262de8; equal-valued HIT_REACTION_PLAY_HIT_ANIMATION and HERO_STATE_STOP therefore do not fit this status domain. --- src/overlays/l14/mobys/blarg_heavy_interceptor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/blarg_heavy_interceptor.c b/src/overlays/l14/mobys/blarg_heavy_interceptor.c index b97a2f4efe..acbb7ecc85 100644 --- a/src/overlays/l14/mobys/blarg_heavy_interceptor.c +++ b/src/overlays/l14/mobys/blarg_heavy_interceptor.c @@ -789,7 +789,7 @@ void process_blarg_heavy_interceptor_hit_reactions(struct Moby *moby) { HIT_REACTION_LOW_RED_FLASH_AND_HIT_ANIMATION = 10, HIT_REACTION_NONE = 11 } ; enum { INTERCEPTOR_STATE_PATROL_AND_SCAN = 1 , INTERCEPTOR_STATE_ALERT_GROUP = 2 , INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL = 7}; - enum { HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE = 1 } ;BlargHeavyInterceptorVars *blarg_heavy_interceptor_vars = + enum { HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE = 1 } ; enum { HIT_REACTION_STATUS_ENABLE_HIT_PARTICLES = 3} ;BlargHeavyInterceptorVars *blarg_heavy_interceptor_vars = (BlargHeavyInterceptorVars *)moby->pvars; int hit_reaction_status; float damage_amount; @@ -810,7 +810,7 @@ void process_blarg_heavy_interceptor_hit_reactions(struct Moby *moby) { hit_reaction_result = 1; if (moby->state == INTERCEPTOR_STATE_PATROL_AND_SCAN) moby->state = INTERCEPTOR_STATE_ALERT_GROUP; - if (hit_reaction_status == 3) + if (hit_reaction_status == HIT_REACTION_STATUS_ENABLE_HIT_PARTICLES) moby->command = 1; switch (hit_reaction_result) { case HIT_REACTION_ANIMATE_WITH_LOW_RED_FLASH: From 0d668925f69781f9b7082a38410150f7b7190747 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:12:47 +0000 Subject: [PATCH 1160/1502] decomp: clarify names in update_robot_dog_glow_effects domain_1_value_0 -> ROBOT_DOG_GLOW_MODE_SLOW_PULSE: Retail 0x002f0264 initializes s2 (C mode, Ghidra iVar8) to zero. When neither 1 nor 2, 0x002f02a0-0x002f02c4 retains the scaled 0xAA-frame pulse period from 0x002f0244-0x002f0254, the slowest of the three sine periods. domain_2_value_1 -> ROBOT_DOG_GLOW_MODE_MEDIUM_PULSE: Retail 0x002f0284-0x002f0288 assigns s2=1 for states 4/5/6 in the original switch. The comparison at 0x002f02b0 selects scale_game_frames(0x5A), intermediate between default 0xAA and fast 0x32; this is a glow mode, not a Moby state. domain_3_value_2 -> ROBOT_DOG_GLOW_MODE_FAST_PULSE: Retail 0x002f028c-0x002f0290 assigns s2=2 to the listed robot-dog state group. 0x002f02a0-0x002f02c0 selects scaled 0x32 frames, the shortest sine pulse period; s2 also selects alternate color packing at 0x002f0378. domain_4_value_0 -> ROBOT_DOG_GLOW_MODE_SLOW_PULSE: C mode>=0 corresponds to retail bltz s2 at 0x002f0298 skipping all glow work for -1. Zero is the slow-pulse mode initialized at 0x002f0264, retaining scaled 0xAA frames; this comparison uses that minimum active glow-mode member. domain_5_value_2 -> ROBOT_DOG_GLOW_MODE_FAST_PULSE: Retail 0x002f029c-0x002f02ac compares s2 against 2 and loads 0x32 into a0 for frame scaling. The resulting period is the modulo divisor and phase denominator at 0x002f02e8-0x002f0308, proving the fast-pulse glow-mode comparison. domain_6_value_1 -> ROBOT_DOG_GLOW_MODE_MEDIUM_PULSE: Retail 0x002f02a4 loads comparison value 1 and 0x002f02b0-0x002f02b8 tests s2 against it to select scaled 0x5A frames. This is the same medium-pulse mode assigned at 0x002f0288, between periods 0xAA and 0x32. domain_7_value_2 -> ROBOT_DOG_GLOW_MODE_FAST_PULSE: Retail 0x002f0374-0x002f0378 compares s2 against 2 to select the alternate packed color at 0x002f0388-0x002f03ac. The same live s2 binding selects scaled 0x32 frames at 0x002f02a0-0x002f02c0, so reuse the fast-pulse glow member. domain_8_value_0 -> ROBOT_DOG_GLOW_MODE_SLOW_PULSE: Retail 0x002f0380 tests the same s2 glow mode against zero: zero reaches normal RGB packing at 0x002f03b0-0x002f03c0, nonzero uses alternate packing. Its zero binding retains scaled 0xAA frames at 0x002f02b0-0x002f02c4, proving reuse of slow-pulse mode. --- src/overlays/l17/mobys/robot_dog.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/overlays/l17/mobys/robot_dog.c b/src/overlays/l17/mobys/robot_dog.c index fdb0f6be28..6b7332f2b0 100644 --- a/src/overlays/l17/mobys/robot_dog.c +++ b/src/overlays/l17/mobys/robot_dog.c @@ -787,6 +787,11 @@ extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); void draw_three_moby_effect_quads(struct Moby *effect_owner) __asm__("FUN_L17_002f0448"); void update_robot_dog_glow_effects(struct Moby *moby) { + enum { + ROBOT_DOG_GLOW_MODE_SLOW_PULSE = 0, + ROBOT_DOG_GLOW_MODE_MEDIUM_PULSE = 1, + ROBOT_DOG_GLOW_MODE_FAST_PULSE = 2 + }; char *robot_dog_glow_vars; int glow_pulse_period_frames; int alpha; @@ -812,12 +817,12 @@ void update_robot_dog_glow_effects(struct Moby *moby) { robot_dog_glow_vars = (char *)moby->pvars; glow_pulse_period_frames = scale_game_frames(glow_pulse_period_frames); alpha = 0x80; - mode = 0; + mode = ROBOT_DOG_GLOW_MODE_SLOW_PULSE; switch (moby->state) { case ROBOT_DOG_STATE_FALL_UNTIL_LANDING: case ROBOT_DOG_STATE_TRACK_TARGET_FACING: case ROBOT_DOG_STATE_WAIT_FOR_CHASE_TRIGGER: - mode = 1; + mode = ROBOT_DOG_GLOW_MODE_MEDIUM_PULSE; break; case ROBOT_DOG_STATE_WAIT_FOR_CHASE_TRIGGER_FAST_PULSE: case ROBOT_DOG_STATE_TURN_TOWARD_TARGET: @@ -827,16 +832,16 @@ void update_robot_dog_glow_effects(struct Moby *moby) { case 13: case 14: case ROBOT_DOG_STATE_FALL_THEN_REMOVE: - mode = 2; + mode = ROBOT_DOG_GLOW_MODE_FAST_PULSE; break; case ROBOT_DOG_STATE_RECOVER_THEN_REINITIALIZE: mode = -1; break; } - if (mode >= 0) { - if (mode == 2) { + if (mode >= ROBOT_DOG_GLOW_MODE_SLOW_PULSE) { + if (mode == ROBOT_DOG_GLOW_MODE_FAST_PULSE) { glow_pulse_period_frames = scale_game_frames(0x32); - } else if (mode == 1) { + } else if (mode == ROBOT_DOG_GLOW_MODE_MEDIUM_PULSE) { glow_pulse_period_frames = scale_game_frames(0x5A); } glow_pulse_sine = fast_sin(((float)(D_L17_0015F5CC % glow_pulse_period_frames) / @@ -855,9 +860,9 @@ void update_robot_dog_glow_effects(struct Moby *moby) { if (g > 255) { g = 255; } - if (mode == 2) { + if (mode == ROBOT_DOG_GLOW_MODE_FAST_PULSE) { color = (alpha << 24) | (b << 16) | ((r / 2) << 8) | g; - } else if (mode != 0) { + } else if (mode != ROBOT_DOG_GLOW_MODE_SLOW_PULSE) { color = (alpha << 24) | (b << 16) | ((r / 2) << 8) | g; } else { color = (alpha << 24) | (b << 16) | (g << 8) | r; From 8c040e96337c75786160c513e02760e3b76e7289 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:12:47 +0000 Subject: [PATCH 1161/1502] decomp: clarify names in handle_blarg_helicopter_hits domain_0_value_1 -> HIT_REACTION_SKIP_DAMAGE: Retail 0x002ce290 passes sp as hit_reaction's fifth output argument; 0x002ce2ac-0x002ce2b0 loads that status and branches over health subtraction and reaction handling when it equals 1. Bounded level-03 helper 0x00248f00 preserves that pointer in s3 at 0x00248f10. With no hit record, 0x00249018-0x00249048 stores status 1 through s3, zeros the float damage output through the saved sixth argument, and returns 0xB. The flag-controlled path at 0x00249394-0x002493e0 also stores status 1 and zeros hit damage at hit_record+0x2C; 0x00249408-0x0024940c copies that zero to the float output. Thus 1 suppresses damage application; it is distinct from the helper return and from helicopter current-state IDs. --- src/overlays/shared/enemies/blarg_helicopter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/blarg_helicopter.c b/src/overlays/shared/enemies/blarg_helicopter.c index 8429ef1430..e137044404 100644 --- a/src/overlays/shared/enemies/blarg_helicopter.c +++ b/src/overlays/shared/enemies/blarg_helicopter.c @@ -864,6 +864,9 @@ void handle_blarg_helicopter_hits(char *helicopter_moby) { BLARG_HELICOPTER_TIMED_REACTION = 4, BLARG_HELICOPTER_DESTROY = 5 }; + enum { + HIT_REACTION_SKIP_DAMAGE = 1 + }; int hit_reaction_status; float fv; int hit_reaction_result; @@ -876,7 +879,7 @@ void handle_blarg_helicopter_hits(char *helicopter_moby) { hit_record = find_moby_hit(helicopter_moby, 0x330000, 0); hit_reaction_result = hit_reaction( helicopter_moby, hit_record, helicopter_data + 0x20, 0, &hit_reaction_status, &fv, 0, 4); - if (hit_reaction_status != 1 && MOBY(helicopter_moby)->state != BLARG_HELICOPTER_DESTROY) { + if (hit_reaction_status != HIT_REACTION_SKIP_DAMAGE && MOBY(helicopter_moby)->state != BLARG_HELICOPTER_DESTROY) { float remaining_health = *(float *)(helicopter_data + 0x20) - fv; *(float *)(helicopter_data + 0x20) = remaining_health; if (hit_reaction_result == 1 || remaining_health <= 0.0f) { From 6abc51d250c7f67aba19a8965d2346b149d80f33 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:12:47 +0000 Subject: [PATCH 1162/1502] decomp: clarify names in process_helicopter_hits domain_0_value_1 -> HIT_REACTION_SKIP_DAMAGE: Caller 0x002c6958 passes sp as hit_reaction fifth output; 0x002c6974-0x002c6978 loads it and branches on 1 past health subtraction and reactions to 0x002c6aec. Checked level-15 helper 0x00249d70 retains this output pointer in s3. Its no-hit-record path 0x00249e70-0x00249ea8 writes 1 at 0x00249e94 and clears the damage output at 0x00249ea0. Its control-mask rejection path 0x0024a22c-0x0024a240 likewise writes 1 at 0x0024a238 and zeros hit damage +0x2c at 0x0024a240, which is copied to the caller damage output at 0x0024a268-0x0024a26c. These paths establish status 1 as skip damage, independently of moby state or return-code values. --- src/overlays/l15/mobys/helicopter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l15/mobys/helicopter.c b/src/overlays/l15/mobys/helicopter.c index bf9a8c26a2..bfe7be678d 100644 --- a/src/overlays/l15/mobys/helicopter.c +++ b/src/overlays/l15/mobys/helicopter.c @@ -889,6 +889,9 @@ void process_helicopter_hits(struct Moby *moby) { HELICOPTER_DEATH_EFFECTS = 7, HELICOPTER_DEAD_WAIT_FOR_RESET = 0x40 }; + enum { + HIT_REACTION_SKIP_DAMAGE = 1 + }; int hit_reaction_status; float fv; int hit_reaction_code; @@ -900,7 +903,7 @@ void process_helicopter_hits(struct Moby *moby) { hit_record = find_moby_hit(moby, 0x330000, 0); hit_reaction_code = hit_reaction(moby, hit_record, helicopter_vars + 0x20, 0, &hit_reaction_status, &fv, 0, 4); - if (hit_reaction_status != 1 && moby->state != HELICOPTER_DEATH_EFFECTS && moby->state != HELICOPTER_DEAD_WAIT_FOR_RESET) { + if (hit_reaction_status != HIT_REACTION_SKIP_DAMAGE && moby->state != HELICOPTER_DEATH_EFFECTS && moby->state != HELICOPTER_DEAD_WAIT_FOR_RESET) { float remaining_health = *(float *)(helicopter_vars + 0x20) - fv; *(float *)(helicopter_vars + 0x20) = remaining_health; if (hit_reaction_code == 1 || remaining_health <= 0.0f) { From 89ff6b00343eb2a1b1b253ac1980e3e6b7e72492 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:14:34 +0000 Subject: [PATCH 1163/1502] decomp: clarify names in handle_owner_linked_moby_hits domain_0_value_2 -> HIT_STATUS_DAMAGE_PROCESSING_THRESHOLD: Authoritative source SHA-256 afff1129e7cc1227aa2aa370b41c65b214f886870e06d08b86475049fe950786 tests hit_status >=2 before comparing health with hit_record+0x2c and subtracting damage or entering the lethal branch. Original Ghidra shows 1 < aiStack_80[0]; retail 0030fed0 passes sp as fifth helper argument, and 0030ff10-0030ff18 loads that output and performs slti against 2 to skip damage handling. Checked helper 00280358 saves fifth argument t0 in s3 at 00280368, initializes *s3=0 at 002803b0, writes 1 without a hit record at 00280488-0028048c, writes default hit status 2 at 00280718-00280720, and writes statuses 3/4 through 002806e0-002806f0/00280720. Suppressed-damage path 0028082c-00280838 writes status 1 and clears damage. Thus 2 is the lower bound for the caller's damage processing, in the status-output domain distinct from the reaction returned via s1 at 002808a0. No existing equal-valued reaction or Hero constant belongs to this selector. --- src/overlays/l11/mobys/owner_linked_moby.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/owner_linked_moby.c b/src/overlays/l11/mobys/owner_linked_moby.c index b6f108c34f..ce6910261e 100644 --- a/src/overlays/l11/mobys/owner_linked_moby.c +++ b/src/overlays/l11/mobys/owner_linked_moby.c @@ -40,6 +40,9 @@ void handle_owner_linked_moby_hits(struct Moby *moby, unsigned char *private_dat LINKED_MOBY_STATE_FADE_OUT = 3, LINKED_MOBY_STATE_REMOVE = 4 }; + enum { + HIT_STATUS_DAMAGE_PROCESSING_THRESHOLD = 2 + }; int hit_status; char *hit_record; if (moby->state != LINKED_MOBY_STATE_REMOVE) { @@ -58,7 +61,7 @@ void handle_owner_linked_moby_hits(struct Moby *moby, unsigned char *private_dat case HIT_REACTION_NO_RESPONSE: break; } - if (hit_status >= 2) { + if (hit_status >= HIT_STATUS_DAMAGE_PROCESSING_THRESHOLD) { if (*health <= *(float *)(hit_record + 0x2C)) { unsigned char *owner_moby; *health = 0.0f; From 8d66fb3f65db8b755d20e54b53bc169f664c0082 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:14:34 +0000 Subject: [PATCH 1164/1502] decomp: clarify names in apply_hero_ground_material_response domain_1_value_8 -> HERO_GROUND_MATERIAL_SLIP_SURFACE: The source snapshot b50006f31a54d4e7f6c3f944768e426c9c6ecf102d96b062afa9cabc6007c20c saves hero.ground_type as previous_ground_type; supplied update_hero_ground_contact assigns that field from collision_hit_material(), proving the material domain rather than HeroStateId. Retail 0x00222FE8 loads the signed material from hero+0x12E0 into s3. At 0x0022309C-0x002230A0 s3 is compared with 8; its matching branch stores 1 at hero+0x12EA at 0x002230AC, the established on_slip_ground field. Original Ghidra likewise has sVar1 == 8 setting uRam0014063a = 1. Thus SLIP_SURFACE names the directly proven response without claiming a physical substance. --- src/overlays/l06/hero/update_hero_motion_for_current_state.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l06/hero/update_hero_motion_for_current_state.c b/src/overlays/l06/hero/update_hero_motion_for_current_state.c index 1cb0ce82d9..17ba6d7b1b 100644 --- a/src/overlays/l06/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l06/hero/update_hero_motion_for_current_state.c @@ -38,6 +38,9 @@ void apply_hero_ground_material_response(void) { HERO_GROUND_MATERIAL_MAGNETIC = 2, HERO_GROUND_MATERIAL_SINK_SURFACE = 0xD }; + enum { + HERO_GROUND_MATERIAL_SLIP_SURFACE = 8 + }; struct Hero *hero_state = &hero; struct Hero *vehicle_response_check_hero; struct Hero *grounded_response_check_hero; @@ -69,7 +72,7 @@ void apply_hero_ground_material_response(void) { struct Hero *gx = &hero; gx->selector_1 = 1; } - if (previous_ground_type == 8) { + if (previous_ground_type == HERO_GROUND_MATERIAL_SLIP_SURFACE) { struct Hero *gx = &hero; gx->on_slip_ground = 1; } From 72f205b2f3518aed006745721da3e52e762cc2dd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:14:34 +0000 Subject: [PATCH 1165/1502] decomp: clarify names in handle_refueling_station_damage domain_0_value_254 -> MOBY_STATE_REMOVAL_PENDING_AT_OR_ABOVE_ADDRESS_BOUNDARY: Root 0x00303c44 reads linked Moby state +0x20 and 0x00303c40/48 excludes 0xFE before command=1. Checked caller 0x00303d10 calls both assigned root (0x00303d34) and source-named mark_moby_for_removal (0x00303d9c, 0x00303fa8 after explosion). That sibling 0x0026e4f0 compares its moby address against pointer [0x0015ffdc] using sltu at 0x0026e500; the at-or-above branch selects 0xFE at 0x0026e514 and writes it to the identical state field +0x20 at 0x0026e518, then schedules current frame+2 at +0x38. This proves pending removal with the at-or-above address-boundary distinction, without claiming the boundary's pool meaning. domain_1_value_253 -> MOBY_STATE_REMOVAL_PENDING_BELOW_ADDRESS_BOUNDARY: Root 0x00303c44 loads linked Moby state +0x20; 0x00303c4c/50 excludes 0xFD before linked command=1. Checked common caller 0x00303d10 invokes root at 0x00303d34 and source-named mark_moby_for_removal 0x0026e4f0 at 0x00303d9c/0x00303fa8. Removal sibling compares moby address with pointer [0x0015ffdc] via sltu at 0x0026e500, selects 0xFD on the below-boundary branch at 0x0026e50c/510, and stores it to Moby state +0x20 at 0x0026e518. It also writes current frame+2 to +0x38 at 0x0026e520/530/538. Thus 0xFD is the below-address-boundary pending-removal state; no static/dynamic pool classification is inferred. --- src/overlays/l09/mobys/refueling_station.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/overlays/l09/mobys/refueling_station.c b/src/overlays/l09/mobys/refueling_station.c index 2fe961c172..ddb4623676 100644 --- a/src/overlays/l09/mobys/refueling_station.c +++ b/src/overlays/l09/mobys/refueling_station.c @@ -99,6 +99,10 @@ void handle_refueling_station_damage(struct Moby *moby, enum { REFUELING_STATION_STATE_EXPLODE = 3 }; + enum { + MOBY_STATE_REMOVAL_PENDING_BELOW_ADDRESS_BOUNDARY = 0xFD, + MOBY_STATE_REMOVAL_PENDING_AT_OR_ABOVE_ADDRESS_BOUNDARY = 0xFE + }; VendorHitSource *damage_hit_record; struct Moby *link; s32 hit; @@ -131,7 +135,7 @@ void handle_refueling_station_damage(struct Moby *moby, moby->flags &= ~0x1000; if (refueling_station_vars->link != -1) { link = &moby_list[refueling_station_vars->link]; - if (link != 0 && link->state != 0xFE && link->state != 0xFD && + if (link != 0 && link->state != MOBY_STATE_REMOVAL_PENDING_AT_OR_ABOVE_ADDRESS_BOUNDARY && link->state != MOBY_STATE_REMOVAL_PENDING_BELOW_ADDRESS_BOUNDARY && (link->oclass == 0x494 || link->oclass == 0x49D || link->oclass == 0x4A0)) { link->command = 1; } From 7e0b2566136059bb4d053cb3c978f36b6b7884cd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:16:50 +0000 Subject: [PATCH 1166/1502] decomp: clarify names in start_vendor_exit_cutscene domain_0_value_3 -> SECONDARY_MUSIC_STREAM_READY_TO_CONTINUE: Authoritative source binds mode to music_stream_state.secondary.state. Retail 0x0029af24/0x0029af48 loads signed halfword at 0x001516d0+0x5a (0x0015172a), comparing it with 3 at 0x0029af28-0x0029af4c, then calls continue_audio_stream_if_ready at 0x0029af54. Checked level-00 helper 0x002652e8 (evidence request f5536406fca84d56bdcf5b4910564d8c) loads the secondary stream handle at +0x50, rejects zero, compares the identical +0x5a field with 3 at 0x00265308-0x0026530c, calls the audio continuation routine at 0x00265314, and stores state 4 at 0x00265328. Thus 3 is the secondary music-stream state ready to continue, a separate domain from HERO_STATE_STOP and VENDOR_MENU_EXIT_CUTSCENE. --- src/overlays/shared/vendor/vendor_menu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/vendor/vendor_menu.c b/src/overlays/shared/vendor/vendor_menu.c index 3bbb0e4aa3..a193c81a46 100644 --- a/src/overlays/shared/vendor/vendor_menu.c +++ b/src/overlays/shared/vendor/vendor_menu.c @@ -573,6 +573,9 @@ void start_vendor_exit_cutscene(void) { enum { VENDOR_MENU_EXIT_CUTSCENE = 3 }; + enum { + SECONDARY_MUSIC_STREAM_READY_TO_CONTINUE = 3 + }; VendorMenu *vendor_state; VendorMoby_29a6b0 *moby; s32 index, exit_cutscene_id, offset; @@ -625,7 +628,7 @@ void start_vendor_exit_cutscene(void) { state->queued_secondary_track = 0x2734; FUN_L00_002455c0(0); mode = music_stream_state.secondary.state; - while (mode != 3) { + while (mode != SECONDARY_MUSIC_STREAM_READY_TO_CONTINUE) { sound_update(); sce_gs_sync_v(0); mode = music_stream_state.secondary.state; From 7897de8cf7d3afa278cd0e73d1135d60b66c9675 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:16:51 +0000 Subject: [PATCH 1167/1502] decomp: clarify names in process_blarg_helicopter_hits domain_0_value_1 -> HIT_PROCESSING_SKIP_HIT: Authoritative C passes &hit_processing_status as hit_reaction argument 5. Retail 0x002eb278 passes sp in t0; 0x002eb294-0x002eb298 loads that output and branches on 1 to 0x002eb458, bypassing damage subtraction, death selection and surviving-hit reactions. Checked level-12 helper 0x00273378 retains t0 in s3. Its null-hit-record path at 0x00273478-0x002734b0 writes 1 through s3 at 0x0027349c, zeros the damage output and returns 0xB. The suppression path 0x00273834-0x00273848 also writes status 1 and clears hit damage at +0x2c. Thus 1 denotes the skip-hit processing disposition, independently of the return reaction code and moby state. Existing Hero/TRUE constants have no proven domain equivalence. --- src/overlays/l12/mobys/blarg_helicopter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l12/mobys/blarg_helicopter.c b/src/overlays/l12/mobys/blarg_helicopter.c index b21c445314..5332670ec4 100644 --- a/src/overlays/l12/mobys/blarg_helicopter.c +++ b/src/overlays/l12/mobys/blarg_helicopter.c @@ -634,7 +634,7 @@ extern void trooper_anim_update(void *m, short *p) __asm__("FUN_L00_0025d458"); extern void trooper_anim_finish(void *, void *) __asm__("FUN_L00_0025d538"); void process_blarg_helicopter_hits(struct Moby *moby) { - enum { BLARG_HELICOPTER_KNOCKBACK = 5 , BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET = 6 } ;int hit_processing_status; + enum { BLARG_HELICOPTER_KNOCKBACK = 5 , BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET = 6 } ; enum { HIT_PROCESSING_SKIP_HIT = 1} ;int hit_processing_status; float fv; int hit_reaction_code; BlargHelicopterVars *blarg_helicopter_hit_vars; @@ -645,7 +645,7 @@ void process_blarg_helicopter_hits(struct Moby *moby) { hit_record = find_moby_hit(moby, 0x330000, 0); hit_reaction_code = hit_reaction( moby, hit_record, &blarg_helicopter_hit_vars->health, 0, &hit_processing_status, &fv, 0, 4); - if (hit_processing_status != 1 && moby->state != BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET && + if (hit_processing_status != HIT_PROCESSING_SKIP_HIT && moby->state != BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET && *(short *)(*(char **)(hit_record + 0x20) + 0xA6) != 0xB8 && *(short *)(*(char **)(hit_record + 0x20) + 0xA6) != 0x199) { float remaining_health; From 35d6dcf1777605058b804981d176cc21621e54d9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:19:46 +0000 Subject: [PATCH 1168/1502] decomp: clarify names in update_bubble_motion_and_scale domain_0_value_2 -> BUBBLE_SHRINK_TO_REMOVAL: Authoritative bubble.c SHA-256 a4ac242eed37fc52f95b8bb1d98e510d847a787a085a6413e3bec92d2dcece9f declares BUBBLE_SHRINK_TO_REMOVAL = 2 and uses it in switch (bubble_moby->state). Retail 0031ab68 loads state from 0x20(s1); 0031ab74-0031ab78 dispatches value 2 to 0031ac30. The surface crossing comparison at 0031abe8-0031abf8 leads to velocity scaling and li v0,2 / sb v0,0x20(s1) at 0031ac0c-0031ac14, so the assignment targets that identical state domain. Its branch approaches moby scale toward zero at 0031acfc-0031ad14 and removes the moby at 0031ad24-0031ad28. Original retail Ghidra confirms the same byte assignment and state-2 shrink branch; reuse the established local enum, with no hero-domain equivalence inferred. --- src/overlays/l11/mobys/bubble.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/bubble.c b/src/overlays/l11/mobys/bubble.c index 0edbafb6cb..cae1174420 100644 --- a/src/overlays/l11/mobys/bubble.c +++ b/src/overlays/l11/mobys/bubble.c @@ -90,7 +90,7 @@ void bubble_update(struct Moby *bubble_moby) { if (bubble_moby->pos.z < *bubble_vars->unk24) { fast_vec_scale( bubble_vars, bubble_vars, *(float *)&bubble_surface_crossing_velocity_scale_gp); - bubble_moby->state = 2; + bubble_moby->state = BUBBLE_SHRINK_TO_REMOVAL; spawn_bubble_surface_effects((struct Moby *)bubble_moby, bubble_vars->unk24, 8, 4); } break; From 0acef735449ac26f1efb8a1131dda4aa16a5b0be Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:21:27 +0000 Subject: [PATCH 1169/1502] decomp: clarify names in resolve_hero_surface_reactions domain_1_value_8 -> HERO_GROUND_TYPE_SLIP: Retail 0x0021dd64 loads hero+0x12E0 (source hero.ground_type) into s2 before the surface block is cleared. At 0x0021dec8-0x0021dedc, comparison of s2 against 8 conditionally stores 1 to hero+0x12EA, the established source field on_slip_ground. Original Ghidra confirms sVar1 == 8 sets uRam0014063a = 1. This proves a ground-type slip reaction, not HeroStateId LAND despite its equal numeric value. The name describes this demonstrated reaction without claiming a material identity or exclusivity; type 12 also sets this flag. --- src/overlays/l14/hero/update_hero_motion_by_state.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l14/hero/update_hero_motion_by_state.c b/src/overlays/l14/hero/update_hero_motion_by_state.c index cf7eb71ee4..bde38024f2 100644 --- a/src/overlays/l14/hero/update_hero_motion_by_state.c +++ b/src/overlays/l14/hero/update_hero_motion_by_state.c @@ -40,6 +40,9 @@ void resolve_hero_surface_reactions(void) { HERO_GROUND_TYPE_ICE = 7, HERO_GROUND_TYPE_SINKING_SURFACE = 0xD }; + enum { + HERO_GROUND_TYPE_SLIP = 8 + }; struct Hero *hero_ptr; struct Hero *hero_data = &hero; int keep = hero_data->ground_sound_class; @@ -89,7 +92,7 @@ void resolve_hero_surface_reactions(void) { struct Hero *q = &hero; q->selector_13 = 1; } - if (saved_ground_type == 8) { + if (saved_ground_type == HERO_GROUND_TYPE_SLIP) { struct Hero *q = &hero; q->on_slip_ground = 1; } From 63888bdf9d84c873bc7370d2f9e19d8a56fdc461 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:21:28 +0000 Subject: [PATCH 1170/1502] decomp: clarify names in suck_beam_build domain_0_value_30 -> HERO_STATE_LOOK_RELEASE_WAIT: Retail 002ddd00 forms the hero base 0013f350; 002ddd08 loads v1 from hero+0x2084, then 002ddd0c/002ddd18 compares that same word with 0x1e. SHA-bound suck_beam_build assigns hero.state.current to hero_state before this comparison, proving the HeroStateId selector rather than control_mode or vehicle mode. The supplied shared HeroStateId declaration canonically names value 30 HERO_STATE_LOOK_RELEASE_WAIT. On this branch, hero.moby flags bit 0 permits copying the fixed orientation rows at 00166fd0, consistent with the source's look-state aiming path. domain_1_value_1 -> HERO_STATE_LOOK: Retail 002ddd08 loads hero+0x2084 into v1; when it differs from 30, 002ddd20 loads 1 and 002ddd24 compares the unchanged v1 with that value. Authoritative source binds this word to hero.state.current through hero_state, establishing the exact shared HeroStateId domain. Its canonical member for 1 is HERO_STATE_LOOK. Both accepted states pass through 002ddd2c-002ddd68 to test hero.moby flags and copy the same aiming orientation; the separate hero+0x22c8 comparison at 002ddd7c is not being renamed. --- src/overlays/shared/weapons/suckcannon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/suckcannon.c b/src/overlays/shared/weapons/suckcannon.c index 81992131c2..08af2f1e40 100644 --- a/src/overlays/shared/weapons/suckcannon.c +++ b/src/overlays/shared/weapons/suckcannon.c @@ -2842,7 +2842,7 @@ void suck_beam_build(char *cannon_moby, char *suction_origin) { D_L00_00161B84 = 1.7f; suck_beam_reset_pending = 0; hero_state = hero.state.current; - if ((hero_state == 0x1E || hero_state == 1) && (hero.moby->flags & 1)) { + if ((hero_state == HERO_STATE_LOOK_RELEASE_WAIT || hero_state == HERO_STATE_LOOK) && (hero.moby->flags & 1)) { qcopy((char *)beam_initialization_vectors, D_L00_00166FD0); qcopy((char *)beam_initialization_vectors + 0x10, D_L00_00166FD0 + 0x10); qcopy((char *)beam_initialization_vectors + 0x20, D_L00_00166FD0 + 0x20); From b1f38895ce899986d995dbcc8ffd9cd8a17db7a6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:21:28 +0000 Subject: [PATCH 1171/1502] decomp: clarify names in process_gunship_part_hits domain_0_value_0 -> GUNSHIP_TARGETS_EXHAUSTED_VOICE_ENTRY: Source assigns state only -1 or existing local voice-entry members 0/1/2 and passes it to allocate_voice_for_target_entry. Retail s3 starts at -1 (0x002e2278), receives 1 at 0x002e22d4/0x002e22f0, 2 at 0x002e2308 and 0 at 0x002e234c. At 0x002e24a4 bltz s3 skips the call; 0x002e24a8 moves this same selector to a0 for jal 0x00295ee0 at 0x002e24b0. Thus the >=0 token is the inclusive lower bound of this proven local voice-entry domain; reuse its canonical zero member GUNSHIP_TARGETS_EXHAUSTED_VOICE_ENTRY rather than an unrelated equal-valued enum. --- src/overlays/l08/mobys/gunship.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/gunship.c b/src/overlays/l08/mobys/gunship.c index 5cff847e45..1caec3f3d5 100644 --- a/src/overlays/l08/mobys/gunship.c +++ b/src/overlays/l08/mobys/gunship.c @@ -319,7 +319,7 @@ void process_gunship_part_hits(struct Moby *moby) { ((char *)moby)[0x20] = 99; } } - if (state >= 0) + if (state >= GUNSHIP_TARGETS_EXHAUSTED_VOICE_ENTRY) allocate_voice_for_target_entry(state, 0, moby); } From c6d40e6646b1aaabf1cc8f5606eb42e500bc9d2c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:23:51 +0000 Subject: [PATCH 1172/1502] decomp: clarify names in swingshot_hook_update domain_0_value_253 -> MOBY_STATE_REMOVAL_PENDING: The SHA-bound source uses owner_moby->state; retail 002c7094 loads that Moby from hook vars word zero, 002c70a0 validates class D0, and 002c70ac-002c70b8 compares its +0x20 state with FE and FD before hook removal at 002c71ec. Checked direct helper mark_moby_for_removal (0024eb68) compares its Moby pointer with the boundary loaded at 0024eb6c; 0024eb88 selects FD, and 0024eb90 stores it into the same Moby +0x20 state field. It also stores the global counter plus two at Moby +0x38 (0024eba8-0024ebb0). Original decompilation and R5900 instructions agree that FD is a pending removal marker. The name does not assert its unknown distinction from FE. --- src/overlays/shared/weapons/swingshot_hook.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/swingshot_hook.c b/src/overlays/shared/weapons/swingshot_hook.c index 1870ffb68f..ce04afa262 100644 --- a/src/overlays/shared/weapons/swingshot_hook.c +++ b/src/overlays/shared/weapons/swingshot_hook.c @@ -58,6 +58,9 @@ void swingshot_hook_update(unsigned char *hook_moby) { enum { MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE }; + enum { + MOBY_STATE_REMOVAL_PENDING = 0xFD + }; unsigned char **hook_vars; struct Moby *owner_moby; if (hook_moby == 0) @@ -67,7 +70,7 @@ void swingshot_hook_update(unsigned char *hook_moby) { return; owner_moby = hook_vars[0]; if (owner_moby == 0 || owner_moby->oclass != 0xD0 || owner_moby->state == MOBY_STATE_MARKED_FOR_REMOVAL || - owner_moby->state == 0xFD || + owner_moby->state == MOBY_STATE_REMOVAL_PENDING || *(unsigned char **)(((unsigned char *)owner_moby->pvars) + 0x14) != hook_moby) { goto kill; } From 1971f8568cf2fa3c5d1e4f0b66a8a960f5baa743 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:26:02 +0000 Subject: [PATCH 1173/1502] decomp: clarify names in door_left_update domain_0_value_1 -> DOOR_CLOSED: Initialization copies position to home at 0x002fedb0-0x002fedb8 and clears the translation fraction at 0x002fedc0, then branches to 0x002fef70/0x002fef74 to store 1 into s0+0x20. That exact byte is the selector loaded at 0x002fed84 and source case DOOR_CLOSED=1; reuse this existing door-domain member. domain_1_value_2 -> DOOR_OPENING: The DOOR_CLOSED proximity and height checks at 0x002fedd0-0x002fee10 select 2 at 0x002fee14, stored to the switch selector byte s0+0x20 at 0x002feec4. Source DOOR_OPENING=2 increments the translation fraction at 0x002fee38-0x002fee50, proving opening rather than an unrelated numeric domain. domain_2_value_3 -> DOOR_OPEN: Opening increments vars+0x10 and clamps it to 1 at 0x002fee38-0x002fee54; 0x002fee5c loads 3 for the state-byte store at 0x002fef74. The shared tail translates home by the full signed two-unit offset at fraction 1. This is the existing selector member DOOR_OPEN=3. domain_3_value_4 -> DOOR_CLOSING: In source DOOR_OPEN, both hero and camera distances must exceed radius*1.1; retail checks at 0x002fee74-0x002feeb0 then load 4 at 0x002feeb4 and store it into selector s0+0x20 at 0x002feec4. Existing DOOR_CLOSING=4 decrements the translation fraction at 0x002fef4c-0x002fef68. domain_4_value_2 -> DOOR_OPENING: During DOOR_CLOSING, renewed hero proximity and height checks at 0x002feeec-0x002fef28 branch at 0x002fef2c with 2 loaded at 0x002fef30 to the state-byte store 0x002fef74. The same selector's existing DOOR_OPENING=2 increases translation fraction, proving the reversal to opening. domain_5_value_1 -> DOOR_CLOSED: Closing subtracts the movement increment at 0x002fef58 and tests the fraction against zero. At the endpoint 0x002fef6c clamps fraction to zero and 0x002fef70-0x002fef74 stores 1 into selector s0+0x20. The common tail then places the door at saved home, matching existing DOOR_CLOSED=1. --- src/overlays/l01/mobys/door_left.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l01/mobys/door_left.c b/src/overlays/l01/mobys/door_left.c index 2df788eed7..22e9c2b919 100644 --- a/src/overlays/l01/mobys/door_left.c +++ b/src/overlays/l01/mobys/door_left.c @@ -51,13 +51,13 @@ void door_left_update(HoverMoby *door_moby) { case DOOR_INITIALIZE: qcopy(&door_vars->home, &door_moby->pos); door_vars->t = 0.0f; - door_moby->state = 1; + door_moby->state = DOOR_CLOSED; break; case DOOR_CLOSED: player = &hero.motion.pos; if (vector_distance_xy(door_vars, player) < door_vars->radius && absolute_float(door_moby->pos.f[2] - player->f[2]) < 2.0f) { - door_moby->state = 2; + door_moby->state = DOOR_OPENING; if (door_moby->oclass == 0x300) { FUN_0022da68(0, 0, door_moby); } @@ -67,14 +67,14 @@ void door_left_update(HoverMoby *door_moby) { door_vars->t += 1.0f / scale_time(20.0f); if (door_vars->t >= 1.0f) { door_vars->t = 1.0f; - door_moby->state = 3; + door_moby->state = DOOR_OPEN; } break; case DOOR_OPEN: k = 1.1f; if (vector_distance_xy(door_vars, &hero.motion.pos) > door_vars->radius * k && vector_distance_xy(door_vars, camera_pos) > door_vars->radius * k) { - door_moby->state = 4; + door_moby->state = DOOR_CLOSING; if (door_moby->oclass == 0x300) { FUN_0022da68(0, 0, door_moby); } @@ -84,12 +84,12 @@ void door_left_update(HoverMoby *door_moby) { player = &hero.motion.pos; if (vector_distance_xy(door_vars, player) < door_vars->radius && absolute_float(door_moby->pos.f[2] - player->f[2]) < 2.0f) { - door_moby->state = 2; + door_moby->state = DOOR_OPENING; } else { door_vars->t -= 1.0f / scale_time(20.0f); if (door_vars->t <= 0.0f) { door_vars->t = 0.0f; - door_moby->state = 1; + door_moby->state = DOOR_CLOSED; } } break; From 3e0c703d48a705e77c3c22c40034ce403ebb0216 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:27:45 +0000 Subject: [PATCH 1174/1502] decomp: clarify names in cull_and_submit_water_grid_tile domain_0_value_14 -> WATER_TILE_VU_ENTRY_FAR_CLIP_PENDING: Retail 002b8e80 selects mode 1's far-mask path; 002b8ed4 clears s4 exactly when packed far clip bits s7 are zero, while 002b8f2c clears other surviving tested modes. Thus at 002b8f44..50 nonzero s4 selects 0xe only with far-clip work still pending. At 002b8f58..5c it is passed as a0 to 00262388. Bounded helper 00262388 saves a0 in t4; 002624f0..f8 ORs it into 0x14000000 and writes the VIF MSCAL command. This proves a water-tile VU entry address selected for the pending far-clip condition, without claiming the internal VU algorithm. domain_1_value_12 -> WATER_TILE_VU_ENTRY_NO_FAR_CLIP: Retail 002b8ce8 bypasses CPU clip tests for zero mode; otherwise 002b8ed4 clears mode when far clip bits s7 are zero, and 002b8f2c clears the non-far-test branch after common-plane rejection. Retail 002b8f44..54 maps this zero state to 0xc, then 002b8f58..5c passes it in a0 to 00262388. Helper 00262388 preserves it in t4 and 002624f0..f8 writes 0x14000000 OR t4, a VIF MSCAL entry command. The name describes the no-pending-far-clip dispatch condition; it does not assert that every internal VU clip operation is absent. --- src/overlays/shared/rendering/render_water_grids.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/rendering/render_water_grids.c b/src/overlays/shared/rendering/render_water_grids.c index 3dbbe458c8..87917381c2 100644 --- a/src/overlays/shared/rendering/render_water_grids.c +++ b/src/overlays/shared/rendering/render_water_grids.c @@ -70,6 +70,10 @@ void cull_and_submit_water_grid_tile(f32 *grid_center_position, s32 index, s32 m WATER_TILE_MODE_SKIP_CLIP_TESTS = 0, WATER_TILE_MODE_TEST_FAR_CLIP = 1 }; + enum { + WATER_TILE_VU_ENTRY_NO_FAR_CLIP = 0xc, + WATER_TILE_VU_ENTRY_FAR_CLIP_PENDING = 0xe + }; f32 corners[4][4]; f32 near_clip[4]; f32 far_clip[4]; @@ -155,9 +159,9 @@ void cull_and_submit_water_grid_tile(f32 *grid_center_position, s32 index, s32 m } tile_vertex_offset = (index & 3) * 4 + (index >> 2) * 0x44; if (mode != WATER_TILE_MODE_SKIP_CLIP_TESTS) { - mode = 0xe; + mode = WATER_TILE_VU_ENTRY_FAR_CLIP_PENDING; } else { - mode = 0xc; + mode = WATER_TILE_VU_ENTRY_NO_FAR_CLIP; } FUN_L01_00262388(mode, tile_vertex_offset); } From 17c2a655d87627512905ab8d2a6b302b26b435aa Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:27:45 +0000 Subject: [PATCH 1175/1502] decomp: clarify names in set_resort_owner_state domain_0_value_14 -> RESORT_OWNER_CHECK_POST_PATH_DIALOGUE: Retail 0x002d20a0 writes a1 to this resort-owner Moby.state at +0x20; 0x002d20fc..0x002d2118 reloads that same field, compares it to 14 and sets pvars+0x2C to 10.0. Authoritative ResortOwnerState defines RESORT_OWNER_CHECK_POST_PATH_DIALOGUE=0xE and the same selector already uses that member as a case. Checked caller evidence 0x002d1e18..0x002d1e44 enters 14 after path-completion dialogue, and 0x002d1fb0..0x002d201c polls post-path dialogue before entering 15. This comparison belongs to the established NPC state domain, so reuse its canonical member. domain_1_value_14 -> RESORT_OWNER_CHECK_POST_PATH_DIALOGUE: Retail 0x002d2124 reloads resort-owner Moby.state from +0x20 and 0x002d2128 compares it to s2=14, initialized at 0x002d2100; only this state writes 2 to pvars+0x56 at 0x002d2130..0x002d2138. The identical Moby.state selector is named by authoritative ResortOwnerState, whose RESORT_OWNER_CHECK_POST_PATH_DIALOGUE=0xE already labels the enclosing state-entry group. Source caller polls update_npc_dialogue in that state and then enters 15, matching checked caller evidence 0x002d1fb0..0x002d201c. Reuse the canonical resort-owner member rather than unrelated HeroStateId. --- src/overlays/l11/mobys/resort_owner.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l11/mobys/resort_owner.c b/src/overlays/l11/mobys/resort_owner.c index 78b54f27bd..a2be0ce275 100644 --- a/src/overlays/l11/mobys/resort_owner.c +++ b/src/overlays/l11/mobys/resort_owner.c @@ -606,10 +606,10 @@ void set_resort_owner_state(struct Moby *moby, unsigned char state) { case RESORT_OWNER_CHECK_POST_PATH_DIALOGUE: if (moby->prev_seq != 0) FUN_00212f90(moby, 0, 0, scale_game_frames(0x14)); - if (moby->state == 14) + if (moby->state == RESORT_OWNER_CHECK_POST_PATH_DIALOGUE) moby_vars->unk2C = 10.0f; clear_u64_value(moby_vars->unk130); - if (moby->state == 14) + if (moby->state == RESORT_OWNER_CHECK_POST_PATH_DIALOGUE) moby_vars->unk56 = 2; break; case RESORT_OWNER_FOLLOW_HERO: From 7da4496d06323b6d7780241645c0ffc53e2cce9d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:27:46 +0000 Subject: [PATCH 1176/1502] decomp: clarify names in update_test_dummy_damage_and_respawn domain_0_value_1 -> HIT_REACTION_STATUS_NO_DAMAGE: Assigned retail 0x002ceb0c passes stack+0x40 as hit_reaction's fifth argument; 0x002ceb20..0x002ceb24 loads that status and bypasses health subtraction and reaction when it equals 1. Checked level-16 helper 0x00255db0 moves fifth argument t0 to s3 at 0x00255dc0. Its null-hit-record branch 0x00255ec0..0x00255ef8 stores 1 through s3 at 0x00255ee4 and clears the sixth-argument damage output at 0x00255ef0. Its flag-suppression branch 0x0025627c..0x00256290 likewise stores 1 at 0x00256288 and zeros hit damage +0x2c at 0x00256290, copied to the damage output at 0x002562b8..0x002562bc. Thus 1 denotes a no-damage outcome, without asserting a specific missing-hit or suppression cause; unrelated equal-valued dummy/Hero constants do not apply. --- src/overlays/l16/mobys/test_dummy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l16/mobys/test_dummy.c b/src/overlays/l16/mobys/test_dummy.c index 0a14499206..3d02918ac2 100644 --- a/src/overlays/l16/mobys/test_dummy.c +++ b/src/overlays/l16/mobys/test_dummy.c @@ -535,6 +535,9 @@ void update_test_dummy_damage_and_respawn(void *moby) { TEST_DUMMY_STATE_BURST = 10, TEST_DUMMY_STATE_RESPAWN = 11 }; + enum { + HIT_REACTION_STATUS_NO_DAMAGE = 1 + }; L16HitMoby *hit_moby = moby; float matrix[16]; int status; @@ -571,7 +574,7 @@ void update_test_dummy_damage_and_respawn(void *moby) { amount = 0.0f; dummy_hit_record = find_moby_hit(hit_moby, 0x330000, 0); hit_reaction(hit_moby, dummy_hit_record, &hit_data->health, 0, &status, &amount, 0, 4); - if (status != 1 && hit_moby->state != TEST_DUMMY_STATE_BURST && hit_moby->state != TEST_DUMMY_STATE_RESPAWN) { + if (status != HIT_REACTION_STATUS_NO_DAMAGE && hit_moby->state != TEST_DUMMY_STATE_BURST && hit_moby->state != TEST_DUMMY_STATE_RESPAWN) { hit_data->health -= amount; if (hit_data->health <= 0.0f) { hit_moby->state = TEST_DUMMY_STATE_BURST; From 32325a57141867f2e3c3e7b053a2fb717734e97a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:29:34 +0000 Subject: [PATCH 1177/1502] decomp: clarify names in switch_active_camera_record domain_12_value_0 -> CAMERA_TRANSITION_STATE_CLEARED: Retail 0x001ec16c stores zero into outgoing camera +0x7e, the exact transition-state field loaded at 0x001ebf64 and 0x001ec0b8. This unconditional cleanup precedes retaining that camera as previous and installing the incoming current pointer at 0x001ec19c, proving the cleared outgoing transition-state value. domain_1_value_4 -> CAMERA_TRANSITION_STATE_BLOCK_ACTIVATION: Retail 0x001ebf64 loads the outgoing camera's signed state at +0x7e; 0x001ebf6c..0x001ebf84 compare it to 4 and set incoming activation_blocked at +0x8e to 1, bypassing transition and transform-inheritance setup. domain_2_value_2 -> CAMERA_TRANSITION_STATE_REQUEST_TRANSITION: Retail 0x001ebf64 loads outgoing camera +0x7e, and 0x001ebf88 compares that state to 2. Equality enters 0x001ebfa8 regardless of descriptor kind and reaches 0x001ec038..0x001ec050 to advance preview_camera.transition_phase; descriptor 1/5 optionally configure rate/frame-count transitions. domain_6_value_3 -> CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM: The outgoing +0x7e state loaded at 0x001ebf64 remains in a0. Retail 0x001ec054 compares it to 3 and branches to 0x001ec078, whose four lq/sq pairs copy outgoing transform offsets +0x30,+0,+0x10,+0x20 to the incoming camera and set handoff_state to inherited-transform value 2. domain_7_value_5 -> CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM_WITH_RATE_TRANSITION: Retail 0x001ec05c compares outgoing camera +0x7e state to 5 and selects the 64-byte transform inheritance at 0x001ec078..0x001ec0b0. The same state is reloaded at 0x001ec0b8 and tested at 0x001ec0bc to initialize rate configuration and advance transition_phase. domain_8_value_5 -> CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM_WITH_RATE_TRANSITION: Retail 0x001ec0b8 reloads the outgoing camera +0x7e state after copying its transform; 0x001ec0bc compares it to 5 and enters 0x001ec0d0, selecting rate mode 0, setting both configured rates from incoming +0x78 or defaults, then advancing transition_phase at 0x001ec13c..0x001ec158. This is the same state domain and value tested at 0x001ec05c. --- src/camera/switch_active_camera_record.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/camera/switch_active_camera_record.c b/src/camera/switch_active_camera_record.c index e8d8058a56..c97495b03a 100644 --- a/src/camera/switch_active_camera_record.c +++ b/src/camera/switch_active_camera_record.c @@ -60,6 +60,13 @@ void switch_active_camera_record(struct UpdateCam *next_camera) { CAMERA_DESCRIPTOR_FRAME_COUNT_TRANSITION = 5, CAMERA_DESCRIPTOR_INHERIT_TRANSFORM_WITH_RATE_TRANSITION = 6 }; + enum { + CAMERA_TRANSITION_STATE_CLEARED = 0, + CAMERA_TRANSITION_STATE_REQUEST_TRANSITION = 2, + CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM = 3, + CAMERA_TRANSITION_STATE_BLOCK_ACTIVATION = 4, + CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM_WITH_RATE_TRANSITION = 5 + }; struct UpdateCam *previous_camera; CameraDescriptorInfo *descriptor; f32 transition_duration; @@ -76,9 +83,9 @@ void switch_active_camera_record(struct UpdateCam *next_camera) { if (descriptor != 0) { descriptor_kind = descriptor->descriptor_kind; } - if (previous_transition_state == 4) { + if (previous_transition_state == CAMERA_TRANSITION_STATE_BLOCK_ACTIVATION) { next_camera->activation_blocked = 1; - } else if (previous_transition_state == 2 || descriptor_kind == CAMERA_DESCRIPTOR_RATE_TRANSITION || descriptor_kind == CAMERA_DESCRIPTOR_FRAME_COUNT_TRANSITION) { + } else if (previous_transition_state == CAMERA_TRANSITION_STATE_REQUEST_TRANSITION || descriptor_kind == CAMERA_DESCRIPTOR_RATE_TRANSITION || descriptor_kind == CAMERA_DESCRIPTOR_FRAME_COUNT_TRANSITION) { if (descriptor_kind == CAMERA_DESCRIPTOR_RATE_TRANSITION) { mode_one_duration = next_camera->transition_duration; preview_camera.transition_mode = CAMERA_TRANSITION_RATE_BASED; @@ -103,14 +110,14 @@ void switch_active_camera_record(struct UpdateCam *next_camera) { } else { preview_camera.transition_phase = 2; } - } else if (previous_transition_state == 3 || previous_transition_state == 5 || + } else if (previous_transition_state == CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM || previous_transition_state == CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM_WITH_RATE_TRANSITION || descriptor_kind == CAMERA_DESCRIPTOR_INHERIT_TRANSFORM || descriptor_kind == CAMERA_DESCRIPTOR_INHERIT_TRANSFORM_WITH_RATE_TRANSITION) { qcopy(&next_camera->pos, &previous_camera->pos); qcopy(&next_camera->m0, &previous_camera->m0); qcopy(&next_camera->m1, &previous_camera->m1); qcopy(&next_camera->m2, &previous_camera->m2); next_camera->handoff_state = CAMERA_HANDOFF_INHERITED_TRANSFORM; - if (previous_camera->transition_state == 5 || descriptor_kind == CAMERA_DESCRIPTOR_INHERIT_TRANSFORM_WITH_RATE_TRANSITION) { + if (previous_camera->transition_state == CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM_WITH_RATE_TRANSITION || descriptor_kind == CAMERA_DESCRIPTOR_INHERIT_TRANSFORM_WITH_RATE_TRANSITION) { handoff_duration = next_camera->transition_duration; preview_camera.transition_mode = CAMERA_TRANSITION_RATE_BASED; if (handoff_duration > 0.0f) { @@ -135,7 +142,7 @@ void switch_active_camera_record(struct UpdateCam *next_camera) { } position = &next_camera->pos; - previous_camera->transition_state = 0; + previous_camera->transition_state = CAMERA_TRANSITION_STATE_CLEARED; previous_camera->handoff_state = CAMERA_HANDOFF_NONE; previous_camera->activation_blocked = 0; preview_camera.previous = previous_camera; From 5869a9eb341852e55f85853bd8e6c6430f51feb7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:29:34 +0000 Subject: [PATCH 1178/1502] decomp: clarify names in underwater_door_update domain_0_value_3 -> DOOR_HOLD_AWAY_FROM_ORIGIN: Authoritative underwater_door.c SHA-256 935fe729f314513eb4d36d4b9dc2f47d75c4d487ef0270e79c0ccf7dacb3f957 and original retail decompilation show state 2 increasing signed travel away from saved origin and updating position. At 0x002bdf48-0x002bdf60, strict scale*3/class-scale < absolute(travel) gates completion; trigger at pvars+0x10 != -1 selects 3, stored to the same door Moby's state byte at 0x002be094. Triggerless completion selects 5 instead. Original Ghidra switch has no active case 3: its default returns via 0x002be098 without changing position or travel, so state 3 holds the attained position away from origin. This is the existing local DOOR_* state domain loaded at moby+0x20 (0x002bddf8/0x002bde10), not the unrelated HeroStateId domain. --- src/overlays/shared/props/underwater_door.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/props/underwater_door.c b/src/overlays/shared/props/underwater_door.c index c81a45a588..75735d1a40 100644 --- a/src/overlays/shared/props/underwater_door.c +++ b/src/overlays/shared/props/underwater_door.c @@ -32,6 +32,9 @@ void underwater_door_update(struct Moby *moby) { DOOR_WAIT_FOR_STOP_VOLUME_EXIT = 5, DOOR_RETURN_TO_ORIGIN = 6 }; + enum { + DOOR_HOLD_AWAY_FROM_ORIGIN = 3 + }; MovingMobyVars *door_motion_data = (MovingMobyVars *)moby->pvars; Vec4 offset; Vec4 updated_door_position; @@ -88,7 +91,7 @@ void underwater_door_update(struct Moby *moby) { if (!(scale * step / moby->pclass->scale < magnitude)) return; if (door_motion_data->trigger != -1) { - moby->state = 3; + moby->state = DOOR_HOLD_AWAY_FROM_ORIGIN; return; } moby->state = DOOR_WAIT_FOR_STOP_VOLUME_EXIT; From eaeed4cdb1ee8b7090e63bebff00cbdcf4fca093 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:31:18 +0000 Subject: [PATCH 1179/1502] decomp: clarify names in process_plasmabot_hit_reaction domain_0_value_1 -> HIT_KIND_SKIP_DAMAGE_AND_REACTION: Retail 0x002b3018 passes &hit_kind in t0 to hit_reaction; 0x002b3030-0x002b3038 branches directly to final color-animation finish when that output equals 1, skipping damage deduction, reaction dispatch and animation update. Checked helper 0x002628b0 saves t0 in s3; 0x002629b0-0x002629e8 writes 1 for absent hit_info and zero damage, while 0x00262d6c-0x00262d80 writes 1 and clears damage when damage-enable flags are absent. This is a separate hit-kind control domain, not reaction_outcome or moby state. domain_1_value_10 -> PLASMABOT_WAIT_ANIMATION_BEFORE_RESUMING_AIM: Original Ghidra and retail 0x002b30a0/0x002b30ac store 10 at moby+0x20; 0x002b3108-0x002b3110 starts animation 7. Supplied authoritative update_plasmabot calls this function on the same moby, then switches on that exact byte using established local PLASMABOT_WAIT_ANIMATION_BEFORE_RESUMING_AIM=10; its branch waits for animation 7 completion then blends idle animation 0 and sets aim state 4. Thus assignment belongs to the plasmabot state domain. domain_2_value_12 -> PLASMABOT_SPAWN_DEBRIS_AND_REMOVE: Retail 0x002b3124-0x002b313c tests hit_info+0x24 bit 0x800000 and writes 12 at moby+0x20 when set, confirmed by original Ghidra. Authoritative update_plasmabot calls this routine on the same moby and dispatches that byte with established PLASMABOT_SPAWN_DEBRIS_AND_REMOVE=12; its branch spawns plasmabot death debris and path/ballistic debris, releases beam slot and marks moby for removal. This proves the exact plasmabot state domain rather than HeroStateId. domain_3_value_11 -> PLASMABOT_FALL_THEN_EXPLODE: Retail 0x002b3124-0x002b313c writes 11 at moby+0x20 when hit_info+0x24 bit 0x800000 is clear; original Ghidra confirms this choice. Authoritative update_plasmabot calls this function before dispatching the same byte; its established PLASMABOT_FALL_THEN_EXPLODE=11 branch steps pvars+0x60 motion until contact mask 0x160, then releases beam, spawns death debris/effects, records death and removes the moby. Therefore this assignment uses that existing plasmabot state meaning. --- src/overlays/shared/enemies/plasmabot.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/enemies/plasmabot.c b/src/overlays/shared/enemies/plasmabot.c index f8871b5c70..74d1f8639c 100644 --- a/src/overlays/shared/enemies/plasmabot.c +++ b/src/overlays/shared/enemies/plasmabot.c @@ -1087,7 +1087,7 @@ void process_plasmabot_hit_reaction(struct Moby *moby) { HIT_REACTION_DEATH = 2, HIT_REACTION_STAGGER = 3, HIT_REACTION_NONE = 11 - }; + } ; enum { HIT_KIND_SKIP_DAMAGE_AND_REACTION = 1 , PLASMABOT_WAIT_ANIMATION_BEFORE_RESUMING_AIM = 0xA , PLASMABOT_FALL_THEN_EXPLODE = 0xB , PLASMABOT_SPAWN_DEBRIS_AND_REMOVE = 0xC}; PlasmabotVars *state = (PlasmabotVars *)moby->pvars; int hit_kind; float damage; @@ -1108,7 +1108,7 @@ void process_plasmabot_hit_reaction(struct Moby *moby) { hit_info = 0; } reaction_outcome = hit_reaction(moby, hit_info, &state->health, 0, &hit_kind, &damage, 0, 4); - if (hit_kind != 1 && ((unsigned char *)moby)[0x20] != 0xB) { + if (hit_kind != HIT_KIND_SKIP_DAMAGE_AND_REACTION && ((unsigned char *)moby)[0x20] != 0xB) { state->health -= damage; if (state->health <= 0.0f) reaction_outcome = 1; @@ -1125,7 +1125,7 @@ void process_plasmabot_hit_reaction(struct Moby *moby) { int stagger_duration_frames; float frame_duration, stagger_motion_z, k; release_beam_slot_by_id(moby); - moby->state = 0xA; + moby->state = PLASMABOT_WAIT_ANIMATION_BEFORE_RESUMING_AIM; stagger_duration_frames = scale_game_frames(0x3C); frame_duration = frame_time; stagger_motion_z = plasmabot_stagger_motion_z_scale_gp * frame_duration; @@ -1149,9 +1149,9 @@ void process_plasmabot_hit_reaction(struct Moby *moby) { case HIT_REACTION_DEATH: { float y; if (*(int *)(hit_info + 0x24) & 0x800000) { - moby->state = 0xC; + moby->state = PLASMABOT_SPAWN_DEBRIS_AND_REMOVE; } else { - moby->state = 0xB; + moby->state = PLASMABOT_FALL_THEN_EXPLODE; } moby->flags &= 0xEFFF; { From 910e4889b9c80f98848743773467297f7c742d28 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:31:18 +0000 Subject: [PATCH 1180/1502] decomp: clarify names in shuttle_update domain_1_value_4 -> SHUTTLE_STATE_NO_PATH: Retail 0x002dbecc loads shuttle pvars+0x80 (LiftVars.path), and 0x002dbed0..0x002dbed4 compares it with -1. Only the no-path branch copies moby position/rotation into pvars+0x60/+0x70 at 0x002dbedc..0x002dbef8, loads 4 at 0x002dbefc and stores it to moby+0x20 at 0x002dbf04, then sets ridable=1. That same moby state byte is dispatched at 0x002dbe90..0x002dbebc: state 4 bypasses route selection/departure/travel and reaches the common wobble call at 0x002dc050. Checked helper instructions 0x002dc4bc..0x002dc4d8 restore the saved home transform; 0x002dc500..0x002dc59c apply periodic position/rotation offsets. Authoritative C and original Ghidra agree. This proves the no-path shuttle state in the existing function-local SHUTTLE_STATE domain, unrelated to HERO_STATE_CROUCH=4. --- src/overlays/l08/mobys/shuttle.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/shuttle.c b/src/overlays/l08/mobys/shuttle.c index 5aed3380dc..5004e8a382 100644 --- a/src/overlays/l08/mobys/shuttle.c +++ b/src/overlays/l08/mobys/shuttle.c @@ -97,6 +97,9 @@ void shuttle_update(struct Moby *moby) { SHUTTLE_STATE_WAIT_FOR_DEPARTURE = 2, SHUTTLE_STATE_TRAVEL = 3 }; + enum { + SHUTTLE_STATE_NO_PATH = 4 + }; LiftVars *shuttle_vars = (LiftVars *)moby->pvars; Vec4 old_pos; Vec4 old_rot; @@ -122,7 +125,7 @@ void shuttle_update(struct Moby *moby) { if (shuttle_vars->path == -1) { qcopy(&shuttle_vars->home_pos, &moby->pos); qcopy(&shuttle_vars->home_rot, &moby->rot); - moby->state = 4; + moby->state = SHUTTLE_STATE_NO_PATH; shuttle_vars->ridable = 1; } else { shuttle_vars->unk100 = -1; From e2b85240fa9a6bcbd3d1109295a945791418a1d1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:31:19 +0000 Subject: [PATCH 1181/1502] decomp: clarify names in update_armed_transport_damage_and_targeting domain_0_value_1 -> HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE: Retail caller 0x002e2c54 passes sp as t0 to hit_reaction at 0x002e2c60; 0x002e2c6c loads this hit.status output and 0x002e2c70-0x002e2c74 compares it with 1, branching to 0x002e2dbc past damage subtraction, death/hit responses and trooper_anim_update. Checked level-16 helper 0x00255db0 saves t0 in s3 at 0x00255dc0; when the hit-record argument s4 is null, 0x00255ec0-0x00255ee4 stores 1 through s3 and zeroes the damage output at 0x00255ee8-0x00255ef0. For a present record, control-bit tests at 0x00256244-0x0025627c can likewise reach 0x00256284-0x00256290, storing status 1 and clearing record damage. This proves a hit-reaction status that skips the caller's damage-response processing, independent of moby/hero states. --- src/overlays/shared/enemies/armed_transport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/armed_transport.c b/src/overlays/shared/enemies/armed_transport.c index ce91603240..e440fc56da 100644 --- a/src/overlays/shared/enemies/armed_transport.c +++ b/src/overlays/shared/enemies/armed_transport.c @@ -443,7 +443,7 @@ void armed_transport_update(char *transport_moby) { /* Update interaction ownership, damage responses and pursuit tracking. */ void update_armed_transport_damage_and_targeting(struct Moby *transport_moby) { - enum { ARMED_TRANSPORT_STATE_DYING = 8 } ;L16Hit_e hit; + enum { ARMED_TRANSPORT_STATE_DYING = 8 } ; enum { HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE = 1} ;L16Hit_e hit; ArmedTransportVars *transport_data = (ArmedTransportVars *)transport_moby->pvars; float zero; char *hit_record; @@ -466,7 +466,7 @@ void update_armed_transport_damage_and_targeting(struct Moby *transport_moby) { hit_record = find_moby_hit(transport_moby, 0x330000, 0); response = hit_reaction( transport_moby, hit_record, &transport_data->health, 0, &hit.status, &hit.amount, 0, 4); - if (hit.status != 1 && transport_moby->state != ARMED_TRANSPORT_STATE_DYING) { + if (hit.status != HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE && transport_moby->state != ARMED_TRANSPORT_STATE_DYING) { transport_data->health -= hit.amount; if (transport_data->health <= zero || (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && hit.amount >= 2.0f)) response = 1; From ac16020c5045632db7c97d39a35ba7d68f3f5136 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:34:19 +0000 Subject: [PATCH 1182/1502] decomp: clarify names in update_hero_ground_material_effects domain_3_value_13 -> GROUND_MATERIAL_SINK_TRIGGER: The bound source saves hero.ground_type (assigned collision_hit_material() by supplied ground-contact code). Retail 0x0022cd7c loads that material into s2, distinct from state.current at hero+0x2084. At 0x0022cf38 the s2==13 branch writes 1 to hero+0x12ec at 0x0022cf48 (selector_13). Retail 0x0022cfd8-0x0022cfdc tests this same flag and exits when zero; when set, the following surface-height and downward-displacement checks at 0x0022cff0-0x0022d054 lead to l01_hero_set_state(0x7f,1) at 0x0022d064-0x0022d06c, named HERO_STATE_SINK in the authoritative C. Thus this material enables the sink transition; the name makes no claim about its physical substance. --- src/overlays/shared/hero/hero_frame_update.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index 7badf30e5a..ba238f520f 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -334,6 +334,9 @@ void update_hero_ground_material_effects(void) { GROUND_MATERIAL_WATER = 0, GROUND_MATERIAL_MAGNETIC = 2 }; + enum { + GROUND_MATERIAL_SINK_TRIGGER = 0xD + }; struct Hero *hero_ptr = &hero; int saved_ground_type; int x; @@ -391,7 +394,7 @@ void update_hero_ground_material_effects(void) { struct Hero *q = &hero; q->selector_4 = 1; } - if (saved_ground_type == 0xD) { + if (saved_ground_type == GROUND_MATERIAL_SINK_TRIGGER) { struct Hero *q = &hero; q->selector_13 = 1; } From 538a1bf64672868a3e9394de22305164c8f2e3d4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:36:10 +0000 Subject: [PATCH 1183/1502] decomp: clarify names in effect_slots_fire domain_0_value_0 -> EFFECT_SHOT_TRACKING_PHASE: Source computes phase = D_L02_0015F5CC & 3 and save_shot = phase == 0. Retail 0x00264e78..0x00264e8c loads the counter, masks with 3, and tests the masked value below 1; 0x00264ed4 saves that boolean. At 0x00265080..0x00265090 the third-particle index test and saved boolean gate 0x00265098..0x002650d0, which stores the spawned effect pointer into the first empty of seven slots. Thus zero denotes the effect shot-tracking phase, rather than a boolean FALSE or NULL pointer domain. --- src/overlays/shared/weapons/effect_slots_fire.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/effect_slots_fire.c b/src/overlays/shared/weapons/effect_slots_fire.c index b552eeb157..2a41c7e534 100644 --- a/src/overlays/shared/weapons/effect_slots_fire.c +++ b/src/overlays/shared/weapons/effect_slots_fire.c @@ -55,6 +55,9 @@ void effect_slots_fire(char *slots, float distance) __asm__("FUN_L02_00264e70"); void effect_slots_fire(char *slots, float *position, float *direction, float distance) { + enum { + EFFECT_SHOT_TRACKING_PHASE = 0 + }; float origin[4] __attribute__((aligned(16))); float end[4] __attribute__((aligned(16))); float adjusted[4] __attribute__((aligned(16))); @@ -73,7 +76,7 @@ void effect_slots_fire(char *slots, float *position, float *direction, float dis { int phase = D_L02_0015F5CC & 3; - save_shot = phase == 0; + save_shot = phase == EFFECT_SHOT_TRACKING_PHASE; } qcopy(origin, position); fast_vec_normalize(adjusted, direction, distance + 0.75f); From 6b804d893f6dfaf040a3f833c2fbb770076521c7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:36:10 +0000 Subject: [PATCH 1184/1502] decomp: clarify names in giant_clank_pad_update domain_0_value_3 -> GIANT_CLANK_PAD_ACTIVATION_DISABLED: Retail 0x002ed078 preserves the pad argument in s1; 0x002ed088 loads its state at +0x20. Dispatch 0x002ed08c..0x002ed0b8 handles only states 0, 1 and 2; state 3 returns without reaching the activation checks at 0x002ed144. After the on-foot path enables the linked vehicle and calls enter_hero_vehicle_mode (0x002ed2d8..0x002ed304), the level-18 branch starts scene 6 and writes 3 to this same pad state at 0x002ed35c..0x002ed370. Initialization also selects 3 for level 18 with mission-table byte 0xff (0x002ed104..0x002ed134). Thus 3 disables this pad's subsequent activation checking. The current C switch/default and original retail Ghidra decompilation agree; this is the local GIANT_CLANK_PAD state domain, not equal-valued HeroStateId.HERO_STATE_STOP. --- src/overlays/shared/vehicles/giant_clank_pad.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/vehicles/giant_clank_pad.c b/src/overlays/shared/vehicles/giant_clank_pad.c index 92a8d56d31..ed15e3c4e9 100644 --- a/src/overlays/shared/vehicles/giant_clank_pad.c +++ b/src/overlays/shared/vehicles/giant_clank_pad.c @@ -31,6 +31,9 @@ void giant_clank_pad_update(struct Moby *moby) { GIANT_CLANK_PAD_ARM_ACTIVATION = 1, GIANT_CLANK_PAD_CHECK_ACTIVATION = 2 }; + enum { + GIANT_CLANK_PAD_ACTIVATION_DISABLED = 3 + }; struct Moby *linked = moby->pvars; struct Moby *linked_vehicle_moby; struct Moby *pad; @@ -109,7 +112,7 @@ void giant_clank_pad_update(struct Moby *moby) { start_scene(6); *(u128 *)hero.saved_pos_rot = *(u128 *)&hero.motion.pos; *(u128 *)(hero.saved_pos_rot + 16) = *(u128 *)&hero.motion.rot; - moby->state = 3; + moby->state = GIANT_CLANK_PAD_ACTIVATION_DISABLED; return; } break; From c7029d198e91f8d1c93ade4f633ac81f4892f240 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:36:11 +0000 Subject: [PATCH 1185/1502] decomp: clarify names in escalator_update domain_0_value_0 -> NULL: Authoritative source declares escalator_motion_state as char * loaded from MOBY(moby)->pvars. Retail 0x002dc6d8 loads s0 from moby+0x78; 0x002dc6dc branches to the return epilogue when s0 equals zero. Ghidra likewise returns for iVar2 == 0, before reading the distinct state byte at 0x002dc6e4. Subsequent s0+0x40/+0xa0 accesses prove a storage pointer, so existing NULL denotes pointer absence rather than ESCALATOR_STATE_INITIALIZE or FALSE. --- src/overlays/shared/props/escalator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/props/escalator.c b/src/overlays/shared/props/escalator.c index 378aed762f..199214ac30 100644 --- a/src/overlays/shared/props/escalator.c +++ b/src/overlays/shared/props/escalator.c @@ -32,7 +32,7 @@ void escalator_update(char *moby) { float y; int state; - if (escalator_motion_state == 0) + if (escalator_motion_state == NULL) return; state = MOBY(moby)->state; if (state == ESCALATOR_STATE_TIMED_NEGATIVE_YAW_MOTION) From 71dec92120f5764c66ea2828d3bede441460206d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:38:01 +0000 Subject: [PATCH 1186/1502] decomp: clarify names in update_gameplay_frame domain_1_value_4 -> GAME_MODE_FREEZE: The bound source src/game/update_gameplay_frame.c (SHA-256 4f492c2486de54000f4ae342d740d65485ecb0f8b49d6f4203291980cd5872d4) declares update_mode_freeze at func_001FCE28 and invokes it only for game_mode == 4. Retail 0x001eb254 loads game_mode from 0x0015f604; 0x001eb368 loads 4, 0x001eb3cc compares that same selector, and 0x001eb3d4 calls 0x001fce28 before sound_update. This is the same game-mode selector whose value 3 is established GAME_MODE_MAIN_MENU, not a nested handler substate. Prepared helper evidence cd0248743b23467494bbee41d644d136 confirms the exact helper boundary and caller at 0x001eb3d4; its 0x001fd620 and 0x001fd65c restore game_mode from saved state, consistent with the established freeze-mode handler. No existing supplied constant belongs to this mode/value: PAD_L1=4 is an input mask, not game_mode. --- src/game/update_gameplay_frame.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/game/update_gameplay_frame.c b/src/game/update_gameplay_frame.c index 8e7a8e0209..7ff3aae725 100644 --- a/src/game/update_gameplay_frame.c +++ b/src/game/update_gameplay_frame.c @@ -67,6 +67,9 @@ void update_gameplay_frame(void) { enum { GAME_MODE_MAIN_MENU = 3 }; + enum { + GAME_MODE_FREEZE = 4 + }; Vec4 first_position; Vec4 next_position; RenderSequenceActor *actor; @@ -146,7 +149,7 @@ void update_gameplay_frame(void) { } update_menu_system(); sound_update(); - } else if (game_mode == 4) { + } else if (game_mode == GAME_MODE_FREEZE) { update_mode_freeze(); sound_update(); } From 7776d5d402a902a4c4d28420511fe6567b50ce1d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:38:02 +0000 Subject: [PATCH 1187/1502] decomp: clarify names in update_pyrocitor_flame_effect_slots domain_0_value_2 -> PYROCITOR_FLAME_MIN_TRACKED_FRAME_COUNT: Authoritative pyrocitor.c SHA-256 16e1aaa48b35f6b5077b0b11591b4cc7f65a60b8d075bf08e3341523e88356a5 loads sub_type from flame_effect+0xA. Original retail Ghidra confirms the signed-halfword comparison and slot clearing; retail 0x002b8580 lh s0,0xa(s1), 0x002b858c slti v0,s0,2 and 0x002b8728-0x002b872c clear the tracked pointer when below 2. Checked sibling producer 0x0026b230, returned to the common caller pyrocitor_update and registered in this table, generates a random range at 0x0026b2d8/0x0026b38c, calls the established scale_time 0x001fef10 at 0x0026b2e0/0x0026b394 and truncate_float_to_s32 0x00200250 at 0x0026b2e8/0x0026b39c, then stores the frame count to +0xA at 0x0026b2f4/0x0026b3a8. Optional item-variant scaling writes the same halfword at 0x0026b4a4. Thus 2 is the minimum retained frame count, not an equal-valued hero/pad enum member. --- src/overlays/shared/weapons/pyrocitor.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/pyrocitor.c b/src/overlays/shared/weapons/pyrocitor.c index f2946de49c..f10dd83db1 100644 --- a/src/overlays/shared/weapons/pyrocitor.c +++ b/src/overlays/shared/weapons/pyrocitor.c @@ -803,6 +803,9 @@ void update_pyrocitor_flame_effect_slots(char *moby) { enum { PYROCITOR_FLAME_SUBTYPE_SPARK_BURST = 10 }; + enum { + PYROCITOR_FLAME_MIN_TRACKED_FRAME_COUNT = 2 + }; float hit_direction_vector[4]; char hit_descriptor[0x30]; char qv[16]; @@ -879,7 +882,7 @@ void update_pyrocitor_flame_effect_slots(char *moby) { spark_third_frame_count, *(int *)&pyrocitor_spark_lookup_index_and_flags_gp); } - } else if (sub_type < 2) { + } else if (sub_type < PYROCITOR_FLAME_MIN_TRACKED_FRAME_COUNT) { *(int *)(slots_base - (-(i * 4))) = 0; } } else { From bd5808b52849b01c8dda0a2fb6cb6fd06c6dfb54 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:38:02 +0000 Subject: [PATCH 1188/1502] decomp: clarify names in switch_active_camera_record domain_0_value_0 -> CAMERA_DESCRIPTOR_NULL_FALLBACK: Retail 0x001ebf1c initializes a3 (descriptor_kind) to zero. 0x001ebf4c..0x001ebf5c resolves next_camera->descriptor_index * 0x20 and loads the descriptor pointer at +0x1c. The branch at 0x001ebf60 skips the +0x1d kind-byte load at 0x001ebf68 when that pointer is null, preserving the initializer. Thus this exact source initializer supplies the null-descriptor fallback selector; it is a descriptor-kind constant, distinct from camera transition state, mode and phase domains. --- src/camera/switch_active_camera_record.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/camera/switch_active_camera_record.c b/src/camera/switch_active_camera_record.c index c97495b03a..fd196817dc 100644 --- a/src/camera/switch_active_camera_record.c +++ b/src/camera/switch_active_camera_record.c @@ -67,6 +67,9 @@ void switch_active_camera_record(struct UpdateCam *next_camera) { CAMERA_TRANSITION_STATE_BLOCK_ACTIVATION = 4, CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM_WITH_RATE_TRANSITION = 5 }; + enum { + CAMERA_DESCRIPTOR_NULL_FALLBACK = 0 + }; struct UpdateCam *previous_camera; CameraDescriptorInfo *descriptor; f32 transition_duration; @@ -74,7 +77,7 @@ void switch_active_camera_record(struct UpdateCam *next_camera) { f32 handoff_duration; f32 *previous_position; Vec4f *position; - s32 descriptor_kind = 0; + s32 descriptor_kind = CAMERA_DESCRIPTOR_NULL_FALLBACK; s32 previous_transition_state; descriptor = D_0015EF90[next_camera->descriptor_index].descriptor; From 0114a3e5121d70d3741ed1020b950465aa5a9814 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:38:02 +0000 Subject: [PATCH 1189/1502] decomp: clarify names in process_horny_toad_hit_reaction domain_0_value_1 -> HIT_RESPONSE_NO_HIT: Retail 0x002d51e8 passes the find_moby_hit record as a1 to helper 0x0025a478; 0x002d51f4 passes &hit_response_status (sp+0x10) as t0. The helper saves a1 in s4 at 0x0025a4a0 and t0 in s3 at 0x0025a488. Its null-hit branch writes 1 to *s3 at 0x0025a5ac, clears the separate damage output and returns; its supplied decompilation likewise shows param_2 == 0 producing *param_5 = 1. The caller loads that status at 0x002d5208 and compares it to 1 at 0x002d520c-0x002d5210 to bypass damage reaction. Thus 1 denotes no hit record in the hit-response domain, independent of all moby and hero state enums. --- src/overlays/shared/enemies/horny_toad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/horny_toad.c b/src/overlays/shared/enemies/horny_toad.c index d791ca5faa..544f3530bd 100644 --- a/src/overlays/shared/enemies/horny_toad.c +++ b/src/overlays/shared/enemies/horny_toad.c @@ -463,7 +463,7 @@ void horny_toad_update(Moby *moby) { void process_horny_toad_hit_reaction(unsigned char *m) __asm__("FUN_L00_002d5160"); void process_horny_toad_hit_reaction(unsigned char *toad_moby) { - unsigned char *toad_vars = *(unsigned char **)(toad_moby + 0x78); + enum { HIT_RESPONSE_NO_HIT = 1 } ;unsigned char *toad_vars = *(unsigned char **)(toad_moby + 0x78); unsigned char *hit; s32 hit_response_status; f32 damage; @@ -487,7 +487,7 @@ void process_horny_toad_hit_reaction(unsigned char *toad_moby) { damage = 0.0f; hit = find_moby_hit(toad_moby, 0x330000, 0); hit_reaction(toad_moby, hit, toad_vars + 0x20, 0, &hit_response_status, &damage, 0, 4); - if (hit_response_status != 1 && MOBY(toad_moby)->state != 12 && damage != 0.0f) { + if (hit_response_status != HIT_RESPONSE_NO_HIT && MOBY(toad_moby)->state != 12 && damage != 0.0f) { /* Fakematch: register pins give retail's choices: 41 in $t0, the frame time and later 0.75 in $f4, the squared frame time first in $f0. */ register s32 hit_state __asm__("$8") = 0x29; From c87b82993e4e4f3da2b8bff212203f4e39101bba Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:40:04 +0000 Subject: [PATCH 1190/1502] decomp: clarify names in floor_button_update domain_0_value_2 -> FLOOR_BUTTON_STATE_DISABLED: Retail 0030c620-0030c688 tests recorded save flags, save bits and mission eligibility; the disabling branch loads 2 at 0030c694 and stores it to moby->state (+0x20) at 0030c69c, sets fixed green glow and clears matching path keys. Dispatch at 0030c5c4-0030c5dc handles only states 0 and 1; state 2 returns without pulse or press processing. Thus this is the floor-button disabled state, distinct from command +0xBC and unrelated Hero enums. domain_1_value_1 -> FLOOR_BUTTON_STATE_WAIT_FOR_PRESS: Retail 0030c72c-0030c734 stores 1 to the same moby state byte +0x20 read by dispatch at 0030c5c4-0030c5d4. The state-1 branch at 0030c738 pulses glow and waits for hero.ground_moby == moby with zero air frames at 0030c7d4-0030c7e4. This is exactly the selector domain and branch already named FLOOR_BUTTON_STATE_WAIT_FOR_PRESS = 1 in the authoritative function-local enum. domain_2_value_2 -> FLOOR_BUTTON_STATE_DISABLED: After grounded hero contact at 0030c7d4-0030c7e4 and save-flag writes at 0030c808/0030c864, retail loads 2 at 0030c870 and stores it to moby->state (+0x20) at 0030c880, sets fixed green glow, plays voice and clears matching path keys. Dispatch 0030c5c4-0030c5dc returns for state 2, ending pulse and further press handling. This is the same floor-button disabled state assigned by initialization at 0030c69c; command +0xBC remains separately valued. --- src/overlays/shared/props/floor_button.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/props/floor_button.c b/src/overlays/shared/props/floor_button.c index 9b2c1ef5a2..589885caea 100644 --- a/src/overlays/shared/props/floor_button.c +++ b/src/overlays/shared/props/floor_button.c @@ -30,6 +30,9 @@ void floor_button_update(struct Moby *moby) { FLOOR_BUTTON_STATE_INITIALIZE = 0, FLOOR_BUTTON_STATE_WAIT_FOR_PRESS = 1 }; + enum { + FLOOR_BUTTON_STATE_DISABLED = 2 + }; s32 *floor_button_private_state = (s32 *)moby->pvars; s16 id; s32 i; @@ -50,7 +53,7 @@ void floor_button_update(struct Moby *moby) { (floor_button_private_state[2] != 0 && D_0014C050[moby->mission + current_level_index * 16] == 0xFF)) { moby->command = 2; moby->glow_color = 0x80208020; - moby->state = 2; + moby->state = FLOOR_BUTTON_STATE_DISABLED; list = floor_button_private_state[0]; if (list != -1) { i = 0; @@ -65,7 +68,7 @@ void floor_button_update(struct Moby *moby) { } } } else { - moby->state = 1; + moby->state = FLOOR_BUTTON_STATE_WAIT_FOR_PRESS; } break; case FLOOR_BUTTON_STATE_WAIT_FOR_PRESS: @@ -86,7 +89,7 @@ void floor_button_update(struct Moby *moby) { D_0014C050[moby->mission + current_level_index * 16] == 0xFF)) { l05_mission_gated_moby_save_flags.collected[(s16)moby->save_id] = moby->mission + 2; } - moby->state = 2; + moby->state = FLOOR_BUTTON_STATE_DISABLED; moby->command = 1; moby->glow_color = 0x80208020; allocate_voice_for_target_entry(0, 0, moby); From 84bd8b19e3a19c26b74dc5e6974c48f0e657822b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:40:04 +0000 Subject: [PATCH 1191/1502] decomp: clarify names in draw_hud_segment_meter domain_0_value_0 -> FALSE: The authoritative source binds this comparison to pal_mode != 0. Retail 0x0024974c loads the flag at 0x0015ed80 into a1, 0x00249760 uses movz to select frame_size-50 when false, and 0x00249774 copies it to a3. In the level-13 branch, 0x002497d4 sets y=18 and 0x002497d8 movn selects y=10 when that same flag is nonzero. Thus zero is the boolean false value of pal_mode; reuse the supplied existing FALSE=0 rather than infer a state or video-standard enum. --- src/overlays/shared/ui/hud/draw_hud_segment_meter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/ui/hud/draw_hud_segment_meter.c b/src/overlays/shared/ui/hud/draw_hud_segment_meter.c index 32bf30fc1a..99437edfc5 100644 --- a/src/overlays/shared/ui/hud/draw_hud_segment_meter.c +++ b/src/overlays/shared/ui/hud/draw_hud_segment_meter.c @@ -42,7 +42,7 @@ s32 draw_hud_segment_meter(u8 *meter_state) { { if (level == 13) { y = 18; - if (pal_mode != 0) + if (pal_mode != FALSE) y = 10; } alpha = convert_integer_to_float(meter_state[0x70]) * 0.125f; From e581276c93281ce7313b14f0481fedb9e751b0da Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:40:05 +0000 Subject: [PATCH 1192/1502] decomp: clarify names in spawn_hoven_anklebiter_death_sparks domain_0_value_15 -> ANKLEBITER_DEATH_EFFECTS_AND_REMOVE: Retail 0x002e30ec loads the byte at moby+0x20 and 0x002e30f0 compares it with 15; 0x002e30f8-0x002e3114 multiplies the outer burst count by 1.5 before truncation. Bound source identifies this byte as moby->state. In update_hoven_anklebiter the same moby's state 15 is named ANKLEBITER_DEATH_EFFECTS_AND_REMOVE, entered after death-fall completion; its branch calls this exact function twice and removes that moby. This proves the anklebiter state domain rather than the unrelated HeroStateId domain. domain_1_value_15 -> ANKLEBITER_DEATH_EFFECTS_AND_REMOVE: Retail 0x002e31a4 reloads the original moby argument, 0x002e31ac loads its state byte at +0x20, and 0x002e31b0 compares with 15. The taken state-specific body 0x002e31b8-0x002e31d4 scales horizontal and vertical spark speeds by 0.55 and lowers emission Z by 0.2. It tests exactly the same anklebiter state byte as the entry comparison. The authoritative update_hoven_anklebiter caller names state 15 ANKLEBITER_DEATH_EFFECTS_AND_REMOVE, calls this function twice with that moby in the named branch, then removes it; reuse that established domain member. --- src/overlays/l12/mobys/hoven_anklebiter.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l12/mobys/hoven_anklebiter.c b/src/overlays/l12/mobys/hoven_anklebiter.c index 1b42aaee5a..380d635976 100644 --- a/src/overlays/l12/mobys/hoven_anklebiter.c +++ b/src/overlays/l12/mobys/hoven_anklebiter.c @@ -758,6 +758,9 @@ extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); void spawn_hoven_anklebiter_death_sparks(struct Moby *moby) __asm__("FUN_L12_002e3098"); void spawn_hoven_anklebiter_death_sparks(struct Moby *moby) { + enum { + ANKLEBITER_DEATH_EFFECTS_AND_REMOVE = 15 + }; float pos[4]; float spark_launch_velocity[4]; float gravity_adjusted_spark_velocity[4]; @@ -780,7 +783,7 @@ void spawn_hoven_anklebiter_death_sparks(struct Moby *moby) { count = D_L12_0016183C; spark_moby_vars = (char *)moby->pvars; - if (moby->state == 15) + if (moby->state == ANKLEBITER_DEATH_EFFECTS_AND_REMOVE) count = truncate_float_to_s32((float)count * 1.5f); for (i = 0; i < count; i++) { pos_ptr = pos; @@ -791,7 +794,7 @@ void spawn_hoven_anklebiter_death_sparks(struct Moby *moby) { angle = random_angle_radians(); speed = random_float_between(l12_anklebiter_spark_horizontal_speed_range_start, l12_anklebiter_spark_horizontal_speed_range_end); rise = random_float_between(l12_anklebiter_spark_vertical_speed_range_start, l12_anklebiter_spark_vertical_speed_range_end); - if (moby->state == 15) { + if (moby->state == ANKLEBITER_DEATH_EFFECTS_AND_REMOVE) { speed *= 0.55f; rise *= 0.55f; pos[2] -= 0.2f; From e1aa59818150ec0703fd439711dceb5d66d7d9c2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:40:05 +0000 Subject: [PATCH 1193/1502] decomp: clarify names in poison_vessel_update domain_0_value_2 -> HIT_STATUS_DAMAGE_PROCESSING_MINIMUM: Retail 00307be4 passes sp+0x10 as the fifth argument to checked level-13 helper 00266500; 00307c24-00307c2c loads that output and skips damage processing when it is less than 2. Otherwise 00307c34-00307cd4 compares health with hit->damage, enters destruction or subtracts damage. Checked helper request e27a7790d6144bd28cf3557c6b5d94db: 00266510 retains this output pointer in s3; 00266558 initializes status 0, 00266630-00266634 sets status 1 for no hit, 002668c0-002668c8 writes ordinary status 2, 00266888-002668c8 writes statuses 3/4 on alternate branches, and 002669d4-002669e0 resets status to 1 while clearing damage. The return reaction code is independently held in s1 and returned at 00266a48. Thus 2 is the minimum hit-status value admitting the vessel's damage-processing branch, not the equal-valued hit-result enum member. --- src/overlays/l13/mobys/poison_vessel.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/poison_vessel.c b/src/overlays/l13/mobys/poison_vessel.c index c31b43098b..5323ab3690 100644 --- a/src/overlays/l13/mobys/poison_vessel.c +++ b/src/overlays/l13/mobys/poison_vessel.c @@ -287,6 +287,9 @@ void poison_vessel_update(struct Moby *moby) { HIT_RESULT_STUN_KNOCKBACK = 3, HIT_RESULT_NO_REACTION = 11 }; + enum { + HIT_STATUS_DAMAGE_PROCESSING_MINIMUM = 2 + }; struct BlastVars *poison_vessel_vars = (struct BlastVars *)moby->pvars; struct BlastHit *hit; float *health; @@ -317,7 +320,7 @@ void poison_vessel_update(struct Moby *moby) { break; } effects = poison_vessel_vars->effects; - if (kind >= 2) { + if (kind >= HIT_STATUS_DAMAGE_PROCESSING_MINIMUM) { if (*health <= hit->damage) { *health = 0; moby->flags &= 0xEFFF; From bb55c55fbdf5ded87db38af0c3c14cef4d853cf8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:40:05 +0000 Subject: [PATCH 1194/1502] decomp: clarify names in apply_hero_ground_material_effects domain_0_value_14 -> GROUND_MATERIAL_FIXED_WATER_DEPTH: The selector is saved_ground_type, loaded as a signed short from hero+0x12e0 into s2 at retail 0x002097d4, before that field is reset. At 0x00209864 material 14 selects 0x0020986c-0x0020988c, which stores 0.2f to hero.water_depth (+0x22a4), stores hero.ground_z (+0x2d8) plus 0.2f to water_surface_z (+0x2f0), and sets base_condition. Original Ghidra sVar1==0xe and the authoritative C agree. This proves the fixed-water-depth effect without claiming a physical substance or borrowing a HeroStateId. domain_5_value_13 -> GROUND_MATERIAL_SINK_TRIGGER: Retail 0x002099d8 compares saved material s2 with 13 and 0x002099e8 sets hero+0x12ec (selector_13). At 0x00209a78 that same byte gates the final branch, which tests current state, proximity below water_surface_z and negative displacement Z at 0x00209a84-0x00209af4, then calls hero_set_state(0x7f,1) at 0x00209b04-0x00209b0c. The bound C names this request HERO_STATE_SINK. Embedded update_hero_ground_contact also obtains ground_type from collision_hit_material and records a surface height for material 13. Thus 13 is a material sink trigger, not the equal-numbered hero jump state. --- .../l16/hero/apply_hero_ground_material_effects.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l16/hero/apply_hero_ground_material_effects.c b/src/overlays/l16/hero/apply_hero_ground_material_effects.c index 4f7032ded2..25fa630f41 100644 --- a/src/overlays/l16/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l16/hero/apply_hero_ground_material_effects.c @@ -30,6 +30,10 @@ void apply_hero_ground_material_effects(void) { GROUND_MATERIAL_WATER = 0, GROUND_MATERIAL_MAGNET = 2 }; + enum { + GROUND_MATERIAL_SINK_TRIGGER = 0xD, + GROUND_MATERIAL_FIXED_WATER_DEPTH = 0xE + }; struct Hero *hero_data = &hero; int keep = hero_data->ground_sound_class; int saved_ground_type = hero_data->ground_type; @@ -51,7 +55,7 @@ void apply_hero_ground_material_effects(void) { } } } - if (saved_ground_type == 0xE) { + if (saved_ground_type == GROUND_MATERIAL_FIXED_WATER_DEPTH) { struct Hero *q = &hero; q->base_condition = 1; q->water_depth = 0.2f; @@ -102,7 +106,7 @@ void apply_hero_ground_material_effects(void) { struct Hero *q = &hero; q->selector_4 = 1; } - if (saved_ground_type == 0xD) { + if (saved_ground_type == GROUND_MATERIAL_SINK_TRIGGER) { struct Hero *q = &hero; q->selector_13 = 1; } From a05888e86f62ff71939a614ad22803a4754c5d43 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:43:06 +0000 Subject: [PATCH 1195/1502] decomp: clarify names in process_hero_ground_material_effects domain_0_value_3 -> GROUND_MATERIAL_SINK_SURFACE_TRIGGER: Retail 0x0021b6cc loads saved collision ground_type from Hero+0x12E0 into s2, not state.current at +0x2084. At 0x0021b75c material 3 selects the store of 1 to Hero+0x12E6 at 0x0021b76c. The flag is read at 0x0021b8fc and gates the sink_surface_z (+0x2F4) versus position.z (+0x88) tests at 0x0021b91c-0x0021b96c and downward displacement (+0x108) test at 0x0021b98c-0x0021b998, followed by vehicle-mode exit and state transition. Supplied update_hero_ground_contact C records collision-hit height into sink_surface_z specifically for ground_type 3. This proves a sink-surface trigger material, without inferring a physical substance or equating its numeric ID to HeroStateId. --- src/overlays/l02/hero/update_hero_state_motion.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l02/hero/update_hero_state_motion.c b/src/overlays/l02/hero/update_hero_state_motion.c index d6b1aee549..19110ff83c 100644 --- a/src/overlays/l02/hero/update_hero_state_motion.c +++ b/src/overlays/l02/hero/update_hero_state_motion.c @@ -39,6 +39,9 @@ void process_hero_ground_material_effects(void) { GROUND_MATERIAL_MAGNETIC = 2, GROUND_MATERIAL_SINK_TRIGGER = 0xD }; + enum { + GROUND_MATERIAL_SINK_SURFACE_TRIGGER = 3 + }; struct Hero *hero_state = &hero; int keep = hero_state->ground_sound_class; int saved_ground_type = hero_state->ground_type; @@ -61,7 +64,7 @@ void process_hero_ground_material_effects(void) { } } sphere_probe_selector = D_0015ED84_c; - if (saved_ground_type == 3) { + if (saved_ground_type == GROUND_MATERIAL_SINK_SURFACE_TRIGGER) { struct Hero *q = &hero; q->selector_3 = 1; sphere_probe_selector = D_0015ED84_d; From 84723f53161d8e1e7e1f03b648830b87ee991dc5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:44:45 +0000 Subject: [PATCH 1196/1502] decomp: clarify names in poison_vessel_update domain_0_value_254 -> MOBY_STATE_MARKED_FOR_REMOVAL: Authoritative C SHA-256 249a061ffd4b7604933d763ef306255fd28d8f1af09e95f77e5b775b5033ea9f aliases data->target as target_moby. Retail 002e8174 loads that moby pointer, 002e8180 reads its state byte at +0x20, and 002e8184-002e8188 compare 0xFE; the match marks the vessel for termination and clears its target at 002e8198-002e81a0. The established mark_moby_for_removal call at 002e82e8 targets checked level-15 helper 0023e168. Bounded evidence request b6c027a05e164e16ab5306121d045dbd shows 0023e18c loads 0xFE and 0023e190 stores it to the passed moby's +0x20 state byte. The alternative pointer-threshold path loads 0xFD at 0023e188. Thus 0xFE is a moby state removal marker, independently proven from the removal writer, not inferred from numeric equality or the vessel's 0/1 movement states. --- src/overlays/l15/mobys/poison_vessel.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l15/mobys/poison_vessel.c b/src/overlays/l15/mobys/poison_vessel.c index 78c3bc4587..6db88bbf0c 100644 --- a/src/overlays/l15/mobys/poison_vessel.c +++ b/src/overlays/l15/mobys/poison_vessel.c @@ -139,6 +139,9 @@ void poison_vessel_update(Moby_2E9358 *moby) { POISON_VESSEL_FREE_FLIGHT = 0, POISON_VESSEL_FOLLOW_TARGET = 1 }; + enum { + MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE + }; Vec previous_position; Vec collision_scratch_vector; Vec temporary_vector; @@ -189,7 +192,7 @@ void poison_vessel_update(Moby_2E9358 *moby) { if (data->target != 0) { Moby_2E9358 *target_moby = data->target; - if (target_moby->state == 0xFE || data->target->state == 0xFD) { + if (target_moby->state == MOBY_STATE_MARKED_FOR_REMOVAL || data->target->state == 0xFD) { moby->bBC = state; data->target = 0; } else if (D_L15_00174458_lui[0] != 0) { From da6b2936106e0db410f47cd757f8c8702c1816d7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:46:25 +0000 Subject: [PATCH 1197/1502] decomp: clarify names in chomper_update domain_0_value_1 -> CHOMPER_WAIT_TO_APPROACH_TARGET: Initialization copies moby position to home pvars+0x1D0 at 002e5f08-002e5f10, then 002e5f20 stores 1 to moby+0x20. The switch loads that exact byte at 002e5e88; its existing local member CHOMPER_WAIT_TO_APPROACH_TARGET=1 names the destination, which waits on pvars+0x1C4 before entering approach. domain_1_value_4 -> CHOMPER_APPROACH_TARGET: The wait branch at 002e5f6c-002e5f84 tests pvars+0x1C4 and stores 4 to moby+0x20. This is the exact byte dispatched at 002e5e88, whose existing CHOMPER_APPROACH_TARGET=4 branch calls move_chomper_toward_position with target pvars+0x180 at 002e5fa0-002e5fa8. domain_2_value_5 -> CHOMPER_FACE_TARGET: After moving toward target pvars+0x180, retail 002e5fb8-002e5fd4 stores 5 to moby+0x20 when distance is below 1.25. That same switch selector has existing CHOMPER_FACE_TARGET=5; its body 002e600c-002e6060 computes target-minus-position heading and approaches moby yaw. domain_3_value_6 -> CHOMPER_RETURN_HOME: Retail 002e5ff0-002e6008 stores 6 to moby+0x20 when pvars+0x1C4 equals 2 during approach. This is the switch selector at 002e5e88. Existing CHOMPER_RETURN_HOME=6 calls movement toward pvars+0x1D0 at 002e610c-002e6114, the home vector saved during initialization. domain_4_value_4 -> CHOMPER_APPROACH_TARGET: In CHOMPER_FACE_TARGET, retail 002e60b4-002e60f0 tests animation flag bit 2 and target distance above 1.5, then stores 4 to moby+0x20. The same byte is the switch selector; existing CHOMPER_APPROACH_TARGET=4 moves toward that same target pvars+0x180 at 002e5fa0-002e5fa8. domain_5_value_1 -> CHOMPER_WAIT_TO_APPROACH_TARGET: The return-home branch moves toward saved home pvars+0x1D0 at 002e610c-002e6114 and stores 1 to moby+0x20 at 002e6140 after distance falls below 1.0. This selector's existing CHOMPER_WAIT_TO_APPROACH_TARGET=1 waits on pvars+0x1C4; arrival also selects animation 2, as initialization does. domain_6_value_4 -> CHOMPER_APPROACH_TARGET: While returning home, retail 002e6168-002e617c tests pvars+0x1C4 != 2 and stores 4 to moby+0x20. That exact byte controls the switch at 002e5e88. Existing CHOMPER_APPROACH_TARGET=4 names its branch, which moves toward target pvars+0x180 at 002e5fa0-002e5fa8. domain_7_value_1 -> CHOMPER_WAIT_TO_APPROACH_TARGET: In numeric case 7, retail 002e6180-002e619c calls 002db3f0 with moby and pvars+0x120, then on nonzero return stores 1 to moby+0x20 and clears pvars+0xC8. The destination is the same switch selector's existing CHOMPER_WAIT_TO_APPROACH_TARGET=1, independently of unresolved semantics of case 7. --- src/overlays/l16/mobys/chomper.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l16/mobys/chomper.c b/src/overlays/l16/mobys/chomper.c index 7d061ea327..dcac5ba835 100644 --- a/src/overlays/l16/mobys/chomper.c +++ b/src/overlays/l16/mobys/chomper.c @@ -119,7 +119,7 @@ void chomper_update(struct Moby *chomper_moby) { if (rand() & 1) chomper_moby->flags |= 0x8000; qcopy(chomper_data->unk1D0, &chomper_moby->pos); - chomper_moby->state = 1; + chomper_moby->state = CHOMPER_WAIT_TO_APPROACH_TARGET; if (chomper_moby->prev_seq != 2) blend_moby_animation(chomper_moby, 2, 0, scale_game_frames(20)); chomper_data->unk58 = truncate_float_to_s32(8.0f); @@ -127,7 +127,7 @@ void chomper_update(struct Moby *chomper_moby) { break; case CHOMPER_WAIT_TO_APPROACH_TARGET: if (chomper_data->unk1C4 != 2) { - chomper_moby->state = 4; + chomper_moby->state = CHOMPER_APPROACH_TARGET; if (chomper_moby->prev_seq != 0) blend_moby_animation(chomper_moby, 0, 0, scale_game_frames(20)); } @@ -137,11 +137,11 @@ void chomper_update(struct Moby *chomper_moby) { break; case CHOMPER_APPROACH_TARGET: if (move_chomper_toward_position(chomper_moby, chomper_data->unk180) < 1.25f) { - chomper_moby->state = 5; + chomper_moby->state = CHOMPER_FACE_TARGET; if (chomper_moby->prev_seq != 1) blend_moby_animation(chomper_moby, 1, 0, scale_game_frames(20)); } else if (chomper_data->unk1C4 == 2) - chomper_moby->state = 6; + chomper_moby->state = CHOMPER_RETURN_HOME; break; case CHOMPER_FACE_TARGET: { float *yaw = &chomper_moby->rot.z; @@ -157,7 +157,7 @@ void chomper_update(struct Moby *chomper_moby) { collect_mobies_in_sphere_at_moby_point(chomper_moby, 0, 1, 0.333f, 1.0f, 1.0f, 0, 1, 0); } else if ((chomper_moby->anim_flags & 2) && fast_vec_dist(&chomper_moby->pos, chomper_data->unk180) > 1.5f) { - chomper_moby->state = 4; + chomper_moby->state = CHOMPER_APPROACH_TARGET; if (chomper_moby->prev_seq != 0) blend_moby_animation(chomper_moby, 0, 0, scale_game_frames(20)); } @@ -165,15 +165,15 @@ void chomper_update(struct Moby *chomper_moby) { } case CHOMPER_RETURN_HOME: if (move_chomper_toward_position(chomper_moby, chomper_data->unk1D0) < 1.0f) { - chomper_moby->state = 1; + chomper_moby->state = CHOMPER_WAIT_TO_APPROACH_TARGET; if (chomper_moby->prev_seq != 2) blend_moby_animation(chomper_moby, 2, 0, scale_game_frames(20)); } else if (chomper_data->unk1C4 != 2) - chomper_moby->state = 4; + chomper_moby->state = CHOMPER_APPROACH_TARGET; break; case 7: if (FUN_L00_002dc9f0(chomper_moby, &chomper_data->unk120)) { - chomper_moby->state = 1; + chomper_moby->state = CHOMPER_WAIT_TO_APPROACH_TARGET; chomper_data->unkC8 = 0; } break; From 9fc96c063caec2563a042e6b33a403d4fd972884 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:46:26 +0000 Subject: [PATCH 1198/1502] decomp: clarify names in update_linked_moby_hitbox domain_0_value_0 -> LINKED_HITBOX_STATE_INITIALIZE: Retail 0x002c9cf8 loads the owner's state byte at s3+0x20; 0x002c9cfc skips the linked-moby scan when it is zero. The same byte is moved to t0 at 0x002c9d00 and dispatches the switch at 0x002c9dd0-0x002c9dec. Thus this comparison uses the same domain as existing LINKED_HITBOX_STATE_INITIALIZE=0, whose branch caches classes/alpha/transforms before advancing to state 1. domain_3_value_1 -> LINKED_HITBOX_STATE_WAIT_FOR_LINKED_MOBIES: Retail 0x002c9f38 loads 1 and 0x002c9f44 stores it to the same owner state byte s3+0x20 that dispatches the switch. It follows initialization of linked classes, alpha, transforms and scale. The existing state-1 branch at 0x002c9f48 waits until the linked-moby difference count t3 is zero; reuse the existing LINKED_HITBOX_STATE_WAIT_FOR_LINKED_MOBIES member. domain_4_value_2 -> LINKED_HITBOX_STATE_WAIT_FOR_TARGET_STATE_OR_TIMER: Retail state-1 branch 0x002c9f48 checks the linked-moby difference count, optionally assigns the target's requested state, copies pvars+0x0c into timer +0x40 at 0x002c9f68-0x002c9f70, and writes 2 to owner state s3+0x20 at 0x002c9f78. The same selector's existing state-2 branch waits on target-state or timer completion; reuse LINKED_HITBOX_STATE_WAIT_FOR_TARGET_STATE_OR_TIMER. domain_5_value_3 -> LINKED_HITBOX_STATE_REMOVE: Retail 0x002c9fd0-0x002c9fe0 compares the configured target state at pvars+0x17 with the target's state byte. On equality, 0x002c9fe8-0x002c9fec writes 3 to owner s3+0x20, the switch selector. Existing LINKED_HITBOX_STATE_REMOVE=3 dispatches to 0x002ca028-0x002ca04c, optionally removing the target and always removing the owner. domain_6_value_3 -> LINKED_HITBOX_STATE_REMOVE: Retail 0x002c9ff4-0x002ca010 checks timer-enable flag 8, passes pvars+0x40 to the timer helper, and writes 3 to owner state s3+0x20 when the helper reports completion. This is the same switch domain as existing LINKED_HITBOX_STATE_REMOVE=3, whose branch 0x002ca028-0x002ca04c removes the owner and optionally its target. --- src/overlays/l10/mobys/linked_moby_hitbox.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l10/mobys/linked_moby_hitbox.c b/src/overlays/l10/mobys/linked_moby_hitbox.c index 2f083b66ae..1d51ba1a6f 100644 --- a/src/overlays/l10/mobys/linked_moby_hitbox.c +++ b/src/overlays/l10/mobys/linked_moby_hitbox.c @@ -156,7 +156,7 @@ void linked_moby_hitbox_update(struct Moby *moby) { target = &D_L10_0015FFD8[linked_hitbox_vars->unk10]; } if ((moby->mission == 0xff || visited52[moby->mission + (D_0015ED84 << 4)] != 0xff) && - moby->state != 0) { + moby->state != LINKED_HITBOX_STATE_INITIALIZE) { int i; for (i = 0; i < 5; i++) { int *entry = slot + i * 2; @@ -225,7 +225,7 @@ void linked_moby_hitbox_update(struct Moby *moby) { float now = *(float *)linked_hitbox_vars; float scale = moby->pclass->scale; float size = (now < initial ? initial * scale : now * scale); - moby->state = 1; + moby->state = LINKED_HITBOX_STATE_WAIT_FOR_LINKED_MOBIES; moby->scale = size; } break; @@ -234,7 +234,7 @@ void linked_moby_hitbox_update(struct Moby *moby) { if (target != 0 && linked_hitbox_vars->unk16 != -1) target->state = *(unsigned char *)&linked_hitbox_vars->unk16; linked_hitbox_vars->unk40 = linked_hitbox_vars->unkC; - moby->state = 2; + moby->state = LINKED_HITBOX_STATE_WAIT_FOR_TARGET_STATE_OR_TIMER; } spawn_linked_hitbox_contact_effects(moby, (HitBox *)linked_hitbox_vars); return; @@ -248,10 +248,10 @@ void linked_moby_hitbox_update(struct Moby *moby) { } if ((linked_hitbox_vars->unk8 & 4) == 0 && target != 0 && linked_hitbox_vars->unk17 != -1 && target->state == linked_hitbox_vars->unk17) - moby->state = 3; + moby->state = LINKED_HITBOX_STATE_REMOVE; if ((linked_hitbox_vars->unk8 & 8) == 0 && FUN_001f9740_2c9c70(&linked_hitbox_vars->unk40) != 0) - moby->state = 3; + moby->state = LINKED_HITBOX_STATE_REMOVE; spawn_linked_hitbox_contact_effects(moby, (HitBox *)linked_hitbox_vars); return; case LINKED_HITBOX_STATE_REMOVE: From 41a050d24afd6e7c5e7274bd8b3e1ba99bf7cef1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:46:26 +0000 Subject: [PATCH 1199/1502] decomp: clarify names in update_level14_racer domain_0_value_20 -> RACE_PHASE_START_RACER_DELAYS: Authoritative src/overlays/l14/mobys/racer.c SHA-256 79f07bd99b6ba6b2b5318b1f0a42071f3cca99c76964fd259ac3f7d2960d15bf compares race_state->phase against 0x14 only in RACER_STATE_WAIT_FOR_RACE_START. Original retail Ghidra case 1 and instructions 0x002d6094-0x002d60a0 load 20, read the controller pointer D_L14_00167500 and signed halfword +0x86, and return on inequality. Equality reaches 0x002d60a8-0x002d60b0: scale_game_frames(racer_vars->delay at +0x80) is stored to the racer countdown +0x6c. The store at 0x002d60bc then enters RACER_STATE_WAIT_FOR_START_DELAY; 0x002d60c0-0x002d60c8 waits for that countdown before activation. Thus this controller phase starts racer delay countdowns; it is distinct from Moby +0x20 state. --- src/overlays/l14/mobys/racer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/racer.c b/src/overlays/l14/mobys/racer.c index ef1630b5af..0d87ab481e 100644 --- a/src/overlays/l14/mobys/racer.c +++ b/src/overlays/l14/mobys/racer.c @@ -116,6 +116,9 @@ void level14_racer_update(struct Moby *racer_moby) { RACER_STATE_FOLLOW_PATH = 5, RACER_STATE_WAIT_FOR_EXIT_VOLUME = 6 }; + enum { + RACE_PHASE_START_RACER_DELAYS = 0x14 + }; struct L14RacerVars *racer_vars = (struct L14RacerVars *)racer_moby->pvars; u8 pos[16]; f32 spawned_object_planar_velocity[3]; @@ -144,7 +147,7 @@ void level14_racer_update(struct Moby *racer_moby) { attach_manipulator(racer_moby, 4, racer_vars->manips[2]); return; case RACER_STATE_WAIT_FOR_RACE_START: - if (race_state->phase == 0x14) { + if (race_state->phase == RACE_PHASE_START_RACER_DELAYS) { racer_vars->timer = scale_game_frames(racer_vars->delay); racer_moby->state = RACER_STATE_WAIT_FOR_START_DELAY; } From f27304a478cda5cc31b8588cc95b28899e9d93e3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:46:26 +0000 Subject: [PATCH 1200/1502] decomp: clarify names in update_menu_system domain_1_value_0 -> MENU_SYSTEM_STATE_INITIALIZE_PREVIEW: Authoritative src/ui/menus/system/update_menu_system.c SHA-256 e89076db0190d75aed8323da29aed86d45bee24e7d49506dffca4656e20e49e0 declares menu_system={0}, with the comment that initialize_menu_preview_scene fills it when the menu opens. Retail 0x002192ec loads menu_system.state from 0x001d5bf0; 0x0021935c branches on zero directly to 0x0021936c calling initialize_menu_preview_scene (0x00218f98). Checked helper instructions 0x00218fa4-0x00218fb0 replace this state with 2, and 0x00218fe4/0x00218ff0 install the initial page into next/current, followed by workspace and preview-moby initialization. Thus zero selects preview initialization within the menu-system-state domain; no equivalence to MenuTextAction or game_mode is inferred. --- src/ui/menus/system/update_menu_system.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/menus/system/update_menu_system.c b/src/ui/menus/system/update_menu_system.c index 0a291ee425..5632457da6 100644 --- a/src/ui/menus/system/update_menu_system.c +++ b/src/ui/menus/system/update_menu_system.c @@ -41,6 +41,9 @@ void update_menu_system(void) { MENU_SYSTEM_STATE_PAGE_TRANSITION_PENDING = 1, MENU_SYSTEM_STATE_FINALIZE_CLOSE = 0x14 }; + enum { + MENU_SYSTEM_STATE_INITIALIZE_PREVIEW = 0 + }; s32 i; s32 j; s32 k; @@ -72,7 +75,7 @@ void update_menu_system(void) { game_mode = 0; return; } - if (menu_system.state == 0 || menu_system.state == 0x2D) { + if (menu_system.state == MENU_SYSTEM_STATE_INITIALIZE_PREVIEW || menu_system.state == 0x2D) { initialize_menu_preview_scene(); } if (mode_freeze_flags & 1) { From 3d79c0bbfc8da7ecc988019238cb445c70755523 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:48:12 +0000 Subject: [PATCH 1201/1502] decomp: clarify names in update_drek_boss_state_dependent_scalars domain_0_value_19 -> DREK_BOSS_FOLLOW_HERO: Authoritative source src/overlays/l18/mobys/drek_final_boss_robot.c SHA-256 e694995cbf5c28af5d9669bf41173aed0273caf5c3b906f9711e36a308777b1e loads boss_state = MOBY(moby)->state. Retail 0x002f729c retains the boss argument in s6 and 0x002f7348 loads v1 from 0x20(s6); original Ghidra cVar1 = *(char *)(param_1 + 0x20) corroborates the Drek boss state domain. Retail 0x002f7330/0x002f7360 compares this byte with 0x13 and selects gated follow and hero-to-arena-node distance scalar overrides. The same source caller's DREK_BOSS_FOLLOW_HERO case calls update_drek_boss_hero_follow_movement, refreshes the ring effect, and records 0x13 in f350 on exit; action selection assigns moby->f20 = 0x13 for DREK_BOSS_FOLLOW_HERO. domain_1_value_9 -> DREK_BOSS_APPROACH_PATH_START: Authoritative source src/overlays/l18/mobys/drek_final_boss_robot.c SHA-256 e694995cbf5c28af5d9669bf41173aed0273caf5c3b906f9711e36a308777b1e loads boss_state = MOBY(moby)->state. Retail 0x002f729c retains the boss argument in s6 and 0x002f7348 loads v1 from 0x20(s6); original Ghidra cVar1 = *(char *)(param_1 + 0x20) corroborates the Drek boss state domain. Retail 0x002f7438-0x002f7440 compares the boss state with 9 to select the fixed scalar targets. In the caller, DREK_BOSS_WAIT_TO_RESTORE_SAVED_TRANSFORM assigns moby->f20 = 9; DREK_BOSS_APPROACH_PATH_START advances toward boss_data->f340 + 4, the path's first point, and then assigns 10 on arrival. domain_3_value_0 -> DREK_BOSS_INITIALIZE: Authoritative source src/overlays/l18/mobys/drek_final_boss_robot.c SHA-256 e694995cbf5c28af5d9669bf41173aed0273caf5c3b906f9711e36a308777b1e loads boss_state = MOBY(moby)->state. Retail 0x002f729c retains the boss argument in s6 and 0x002f7348 loads v1 from 0x20(s6); original Ghidra cVar1 = *(char *)(param_1 + 0x20) corroborates the Drek boss state domain. Retail 0x002f7468 tests the loaded boss state against zero before the scan path. The same boss caller dispatches DREK_BOSS_INITIALIZE to initialize position, flags, health and group fields, and changes moby->f20 to 1. The supplied existing constant explicitly binds DREK_BOSS_INITIALIZE to 0. domain_4_value_10 -> DREK_BOSS_FOLLOW_PATH_AND_FIRE_AT_MOBYS: Authoritative source src/overlays/l18/mobys/drek_final_boss_robot.c SHA-256 e694995cbf5c28af5d9669bf41173aed0273caf5c3b906f9711e36a308777b1e loads boss_state = MOBY(moby)->state. Retail 0x002f729c retains the boss argument in s6 and 0x002f7348 loads v1 from 0x20(s6); original Ghidra cVar1 = *(char *)(param_1 + 0x20) corroborates the Drek boss state domain. Retail 0x002f746c-0x002f7470 compares the loaded boss state with 10. The caller assigns moby->f20 = 10 after approaching the first path point; its DREK_BOSS_FOLLOW_PATH_AND_FIRE_AT_MOBYS case advances path nodes, selects a platform firing target, launches rockets, and assigns 0xB near the path end. domain_5_value_11 -> DREK_BOSS_FINISH_PATH_AND_WAIT_FOR_HERO: Authoritative source src/overlays/l18/mobys/drek_final_boss_robot.c SHA-256 e694995cbf5c28af5d9669bf41173aed0273caf5c3b906f9711e36a308777b1e loads boss_state = MOBY(moby)->state. Retail 0x002f729c retains the boss argument in s6 and 0x002f7348 loads v1 from 0x20(s6); original Ghidra cVar1 = *(char *)(param_1 + 0x20) corroborates the Drek boss state domain. Retail 0x002f7474-0x002f7478 compares the boss state with 0xB. The caller's preceding DREK_BOSS_FOLLOW_PATH_AND_FIRE_AT_MOBYS case assigns moby->f20 = 0xB. DREK_BOSS_FINISH_PATH_AND_WAIT_FOR_HERO finishes remaining path nodes and waits for the nearby grounded hero before selecting the next state. domain_6_value_1 -> DREK_BOSS_WAIT_FOR_ENCOUNTER_TRIGGER: Authoritative source src/overlays/l18/mobys/drek_final_boss_robot.c SHA-256 e694995cbf5c28af5d9669bf41173aed0273caf5c3b906f9711e36a308777b1e loads boss_state = MOBY(moby)->state. Retail 0x002f729c retains the boss argument in s6 and 0x002f7348 loads v1 from 0x20(s6); original Ghidra cVar1 = *(char *)(param_1 + 0x20) corroborates the Drek boss state domain. Retail 0x002f747c-0x002f7480 compares the boss state with 1. The caller's initialize case assigns moby->f20 = 1, and DREK_BOSS_WAIT_FOR_ENCOUNTER_TRIGGER checks the hero against a clip volume and encounter path, starting the scene or path movement only after the appropriate trigger. domain_7_value_27 -> DREK_BOSS_RUN_ENDING_SEQUENCE: Authoritative source src/overlays/l18/mobys/drek_final_boss_robot.c SHA-256 e694995cbf5c28af5d9669bf41173aed0273caf5c3b906f9711e36a308777b1e loads boss_state = MOBY(moby)->state. Retail 0x002f729c retains the boss argument in s6 and 0x002f7348 loads v1 from 0x20(s6); original Ghidra cVar1 = *(char *)(param_1 + 0x20) corroborates the Drek boss state domain. Retail 0x002f7484-0x002f7488 compares the boss state with 0x1B. The caller enters moby->f20 = 0x1B after death animation and in the ending trigger branch; DREK_BOSS_RUN_ENDING_SEQUENCE runs scenes 3-5, mounts the jet, starts the slideshow, queues the movie and removes the boss. --- src/overlays/l18/mobys/drek_final_boss_robot.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l18/mobys/drek_final_boss_robot.c b/src/overlays/l18/mobys/drek_final_boss_robot.c index 305db3ef1a..75baddb9ef 100644 --- a/src/overlays/l18/mobys/drek_final_boss_robot.c +++ b/src/overlays/l18/mobys/drek_final_boss_robot.c @@ -2519,7 +2519,7 @@ void update_drek_boss_state_dependent_scalars(char *moby) { f + drek_boss_second_scalar_near_hero_target_gp; boss_state = MOBY(moby)->state; - if (boss_state == 0x13) { + if (boss_state == DREK_BOSS_FOLLOW_HERO) { char *g = D_0013E533 + 0xe1d; if ((*(int *)(g + 0x208c) == 0xf || *(int *)(g + 0x2084) == 0x42) && *(int *)(boss_data + 0x364) == 0 && *(float *)(boss_data + 0x390) <= 25.0f && @@ -2542,15 +2542,15 @@ void update_drek_boss_state_dependent_scalars(char *moby) { y = l18_drek_boss_second_scalar_near_node_follow_target_gp; } } - } else if (boss_state == 9 || boss_state == 6) { + } else if (boss_state == DREK_BOSS_APPROACH_PATH_START || boss_state == 6) { x = drek_boss_follow_camera_distance_target_gp; y = drek_boss_follow_camera_height_target_gp; first_scalar_value = (float *)(selected_scalar_record + 0x34); second_scalar_value = (float *)(selected_scalar_record + 0x38); first_scalar_update_state = (float *)(boss_data + 0x378); second_scalar_update_state = (float *)(boss_data + 0x37c); - } else if (boss_state == 0 || boss_state == 10 || boss_state == 11 || boss_state == 1 || - boss_state == 0x1b) { + } else if (boss_state == DREK_BOSS_INITIALIZE || boss_state == DREK_BOSS_FOLLOW_PATH_AND_FIRE_AT_MOBYS || boss_state == DREK_BOSS_FINISH_PATH_AND_WAIT_FOR_HERO || boss_state == DREK_BOSS_WAIT_FOR_ENCOUNTER_TRIGGER || + boss_state == DREK_BOSS_RUN_ENDING_SEQUENCE) { int i; char *g; char *follow_camera_gate_source; From b45b6dc5243a0f4b9ef0c1d1db01f2b5ba64df42 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:49:46 +0000 Subject: [PATCH 1202/1502] decomp: clarify names in process_hero_hit_response domain_0_value_0 -> CUTSCENE_MODE_INACTIVE: Retail 0x002315e0-0x002315ec loads D_L01_0015F5C4 (cutscene_mode) and returns zero when nonzero, before hit-record processing. Original Ghidra checks iRam0015f5c4 != 0. The authoritative source declares the same global and already names zero CUTSCENE_MODE_INACTIVE in update_hero_timers_and_vehicle_transitions, where cutscene_mode == CUTSCENE_MODE_INACTIVE permits a vehicle transition. This is the same selector and inactive meaning, not an equal-valued hero state. --- src/overlays/shared/hero/hero_frame_update.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index ba238f520f..6e2177be41 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -824,6 +824,9 @@ extern OvlMobyEntry40 l01_moby_hit_response_entries[] __asm__("D_L01_00178580"); s32 process_hero_hit_response(s32 apply_state_and_motion_response) __asm__("FUN_L01_00231580"); s32 process_hero_hit_response(s32 apply_state_and_motion_response) { + enum { + CUTSCENE_MODE_INACTIVE = 0 + }; u8 *hero_moby; OvlMobyEntry40 *hero_moby_entry; u8 *mob; @@ -844,7 +847,7 @@ s32 process_hero_hit_response(s32 apply_state_and_motion_response) { if (G.invulnerable_frames != 0) { return 0; } - if (cutscene_mode != 0) { + if (cutscene_mode != CUTSCENE_MODE_INACTIVE) { return 0; } G.damage_source_moby = 0; From 69fe20d1ce1958c0a113f3f2ed8a75acd56f1746 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:51:49 +0000 Subject: [PATCH 1203/1502] decomp: clarify names in update_linked_moby_rotation domain_12_value_2 -> ADVANCE_ROTATION: Within REVERSE_ROTATION, missing/invalid linked moby or active_state match branches through 0x002c827c to 0x002c8298 loading 2; 0x002c8364 stores it to this moby's +0x20 state. Dispatch reads precisely that byte at 0x002c7f9c; existing ADVANCE_ROTATION case 2 resumes adding rotation steps, proving reuse. domain_13_value_1 -> WAIT_TO_ADVANCE_ROTATION: Retail reversal completion at 0x002c832c-0x002c8344 restores initial rotation and zero progress, then 0x002c8360 loads 1 and 0x002c8364 stores it to this moby's +0x20 state. Existing WAIT_TO_ADVANCE_ROTATION case 1 at 0x002c8014 gates the next advance on linked active_state, proving the local member applies. domain_2_value_2 -> ADVANCE_ROTATION: Retail 0x002c806c clears progress, then 0x002c8074 loads 2 and 0x002c8364 stores it to the same moby's state byte at +0x20 used by dispatch at 0x002c7f9c. This enters existing ADVANCE_ROTATION case 2, which adds angle steps at 0x002c80d4-0x002c814c; reuse the local member. domain_5_value_4 -> REVERSE_ROTATION: In ADVANCE_ROTATION, the linked inactive_state match at 0x002c80ac-0x002c80b0 selects 4 at 0x002c80d0, stored to this moby's +0x20 at 0x002c8364. The same state selector's existing REVERSE_ROTATION case 4 subtracts progress and angles at 0x002c829c-0x002c8310; reuse that member. domain_6_value_3 -> HOLD_ROTATION_OFFSET: After advancement reaches progress >= 1, retail 0x002c8164-0x002c819c sets saved initial rotation plus full offsets, 0x002c81a4 clamps progress to 1, and 0x002c81a0/0x002c81ac writes 3 to this moby's +0x20. Existing HOLD_ROTATION_OFFSET case 3 then waits for linked inactive_state at 0x002c81d4-0x002c820c. domain_9_value_4 -> REVERSE_ROTATION: Existing HOLD_ROTATION_OFFSET case tests linked inactive_state at 0x002c8208-0x002c820c, sets progress to 1 at 0x002c8224 and selects 4 at 0x002c8238 for the +0x20 store at 0x002c8364. This is the same moby state dispatched into existing REVERSE_ROTATION, whose branch subtracts all three angle steps. --- src/overlays/l13/mobys/linked_moby_rotation.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l13/mobys/linked_moby_rotation.c b/src/overlays/l13/mobys/linked_moby_rotation.c index b653fdfb34..e8ed3ebcc4 100644 --- a/src/overlays/l13/mobys/linked_moby_rotation.c +++ b/src/overlays/l13/mobys/linked_moby_rotation.c @@ -64,7 +64,7 @@ void linked_moby_rotation_update(struct Moby *moby) { allocate_voice_for_target_entry(rotation_vars->start_sound, 0, moby); } rotation_vars->progress = 0.0f; - moby->state = 2; + moby->state = ADVANCE_ROTATION; break; case ADVANCE_ROTATION: if (rotation_vars->linked_index != -1 && @@ -74,7 +74,7 @@ void linked_moby_rotation_update(struct Moby *moby) { if (rotation_vars->start_sound != -1) { allocate_voice_for_target_entry(rotation_vars->start_sound, 0, moby); } - moby->state = 4; + moby->state = REVERSE_ROTATION; break; } { @@ -95,7 +95,7 @@ void linked_moby_rotation_update(struct Moby *moby) { moby->rot.z = fast_add_rotations(rotation_vars->initial_rot[2], rotation_vars->angle[2] * radians); rotation_vars->progress = 1.0f; - moby->state = 3; + moby->state = HOLD_ROTATION_OFFSET; if (rotation_vars->end_sound != -1) { allocate_voice_for_target_entry(rotation_vars->start_sound, 0, moby); } @@ -113,7 +113,7 @@ void linked_moby_rotation_update(struct Moby *moby) { if (rotation_vars->start_sound != -1) { allocate_voice_for_target_entry(rotation_vars->start_sound, 0, moby); } - moby->state = 4; + moby->state = REVERSE_ROTATION; break; case REVERSE_ROTATION: if (rotation_vars->linked_index == -1 || @@ -123,7 +123,7 @@ void linked_moby_rotation_update(struct Moby *moby) { if (rotation_vars->start_sound != -1) { allocate_voice_for_target_entry(rotation_vars->start_sound, 0, moby); } - moby->state = 2; + moby->state = ADVANCE_ROTATION; } else { int invalid_index = -1; radians = 0.017453292f; @@ -145,7 +145,7 @@ void linked_moby_rotation_update(struct Moby *moby) { if (rotation_vars->start_sound != invalid_index) { allocate_voice_for_target_entry(rotation_vars->end_sound, 0, moby); } - moby->state = 1; + moby->state = WAIT_TO_ADVANCE_ROTATION; } break; case 5: From d92a370712079a5c71032cdd4b4b39de7d5e6189 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:53:42 +0000 Subject: [PATCH 1204/1502] decomp: clarify names in thruster_pack_lock_update domain_0_value_2 -> THRUSTER_PACK_LOCK_STATE_LOWERED: Retail 0030ee18 reads the lock's state byte at moby+0x20. After saved UID byte/bit checks at 0030ee74-0030eeb8, 0030eec4 loads 2 and 0030eed4 stores it to that same state byte; 0030eedc/0030eee8 subtract and store 1.5 from moby+0x18 (z). The original decompilation confirms this restoration path. State 2 bypasses both init and active dispatch, proving the lowered lock state rather than a hero-state domain. domain_1_value_1 -> THRUSTER_PACK_LOCK_STATE_ACTIVE: Retail 0030eef4-0030eefc stores 1 to moby+0x20 after initialization when no saved lowered state is restored. The same byte is loaded at 0030ee18 and compared to 1 at 0030ee24-0030ee28 to enter 0030ef00, the source's existing THRUSTER_PACK_LOCK_STATE_ACTIVE case. This reuses the exact established lock-state member, unrelated to equal-valued hero constants. domain_2_value_2 -> THRUSTER_PACK_LOCK_STATE_LOWERED: In the ACTIVE lock branch, retail 0030ef08-0030ef38 checks hero ground contact, item availability, air frames and hero state before 0030efcc loads 2 and 0030efdc stores it into the lock state byte at moby+0x20. Instructions 0030efe4 and 0030eff0 subtract 1.5 from lock z and store it, matching the original decompilation and the initialization restore path's state 2. Both assignments therefore share the same lowered lock-state member. --- src/overlays/shared/props/thruster_pack_lock.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/props/thruster_pack_lock.c b/src/overlays/shared/props/thruster_pack_lock.c index bc3fe64119..a3153e1ccf 100644 --- a/src/overlays/shared/props/thruster_pack_lock.c +++ b/src/overlays/shared/props/thruster_pack_lock.c @@ -100,6 +100,9 @@ void thruster_pack_lock_update(Lock *moby) { THRUSTER_PACK_LOCK_STATE_INIT = 0, THRUSTER_PACK_LOCK_STATE_ACTIVE = 1 }; + enum { + THRUSTER_PACK_LOCK_STATE_LOWERED = 2 + }; char *vars = moby->vars; switch (moby->state) { @@ -113,13 +116,13 @@ void thruster_pack_lock_update(Lock *moby) { ((*(int *)(D_0014C190_r + (((short)moby->uid >> 5) * 4 + (level << 8))) >> (moby->uid & 0x1F)) & 1)) { - moby->state = 2; + moby->state = THRUSTER_PACK_LOCK_STATE_LOWERED; moby->z = moby->z - 1.5f; allocate_voice_for_target_entry(0, 0, moby); return; } } - moby->state = 1; + moby->state = THRUSTER_PACK_LOCK_STATE_ACTIVE; break; } case THRUSTER_PACK_LOCK_STATE_ACTIVE: @@ -138,7 +141,7 @@ void thruster_pack_lock_update(Lock *moby) { l11_thruster_pack_lock_restore_state.collected[(short)moby->uid] = group + 2; } } - moby->state = 2; + moby->state = THRUSTER_PACK_LOCK_STATE_LOWERED; moby->z = moby->z - 1.5f; allocate_voice_for_target_entry(0, 0, moby); } From 988b93dbba434b80c6435789c03204042ab36691 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:55:23 +0000 Subject: [PATCH 1205/1502] decomp: clarify names in update_linked_state_sliding_platform domain_0_value_1 -> PLATFORM_WAIT_TO_MOVE_OUTWARD: Retail 0030d034..0030d060 saves moby +0x10 position to pvars origin and resets the sound slot; 0030d3a0..0030d3a8 stores 1 to moby +0x20. This is the same state byte dispatched at 0030d00c..0030d02c, whose existing case PLATFORM_WAIT_TO_MOVE_OUTWARD=1 waits for the linked target halfword state at 0030d070..0030d0a8. domain_10_value_4 -> PLATFORM_RETURN_TO_ORIGIN: Retail 0030d234..0030d270 compares linked target +0x20 against pvars +0x18, plays trigger sound and stores 4 to the platform state byte +0x20. This selector already has PLATFORM_RETURN_TO_ORIGIN=4, whose branch moves toward and restores the saved origin at 0030d2d0..0030d400. domain_13_value_2 -> PLATFORM_MOVE_OUTWARD: Retail 0030d274..0030d2cc reverses the return path when the target is absent, excluded or equals pvars +0x16: trigger sound then store 2 to moby +0x20. This is the switch selector for existing PLATFORM_MOVE_OUTWARD=2; its branch uses the outward negative transformed Y step at 0030d19c..0030d208. domain_14_value_1 -> PLATFORM_WAIT_TO_MOVE_OUTWARD: Retail 0030d30c..0030d3a8 restores saved origin, releases the owned voice, clears sound slot and level flag, then stores 1 to moby +0x20. Existing PLATFORM_WAIT_TO_MOVE_OUTWARD=1 selects that same state byte and waits for linked target pvars +0x16 before starting another outward move. domain_3_value_2 -> PLATFORM_MOVE_OUTWARD: Retail 0030d070..0030d0a8 gates on linked target state; after trigger sound, 0030d0c8..0030d0d0 stores 2 to the dispatched moby +0x20 state byte. Existing PLATFORM_MOVE_OUTWARD=2 handles this exact selector and moves by negative transformed local Y at 0030d19c..0030d208 until origin distance exceeds radius. domain_6_value_4 -> PLATFORM_RETURN_TO_ORIGIN: Retail 0030d108..0030d12c compares linked target state to pvars +0x18, plays trigger sound and stores 4 to moby +0x20. The existing case PLATFORM_RETURN_TO_ORIGIN=4 dispatches that same byte and applies the opposite movement step, snapping to saved origin at 0030d30c..0030d324. domain_7_value_3 -> PLATFORM_WAIT_TO_RETURN: Retail 0030d144..0030d198 tests radius < distance, plays arrival sound, sets the level flag and stores 3 to moby +0x20. The same byte selects existing PLATFORM_WAIT_TO_RETURN=3, which waits for linked target state pvars +0x18 at 0030d214..0030d270 before entering return state 4. --- src/overlays/l07/mobys/linked_sliding_platform.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l07/mobys/linked_sliding_platform.c b/src/overlays/l07/mobys/linked_sliding_platform.c index f613a23f3e..0c58f15db4 100644 --- a/src/overlays/l07/mobys/linked_sliding_platform.c +++ b/src/overlays/l07/mobys/linked_sliding_platform.c @@ -73,7 +73,7 @@ void linked_sliding_platform_update(struct Moby *moby) { sliding_platform_vars->sound_slot = -1; if (sliding_platform_vars->flag_index != -1) D_L07_00184528[sliding_platform_vars->flag_index] = 0; - moby->state = 1; + moby->state = PLATFORM_WAIT_TO_MOVE_OUTWARD; break; } case PLATFORM_WAIT_TO_MOVE_OUTWARD: @@ -85,7 +85,7 @@ void linked_sliding_platform_update(struct Moby *moby) { } if (sliding_platform_vars->trigger_sound != -1) allocate_voice_for_target_entry(sliding_platform_vars->trigger_sound, 0, moby); - moby->state = 2; + moby->state = PLATFORM_MOVE_OUTWARD; break; case PLATFORM_MOVE_OUTWARD: if (sliding_platform_vars->target_index != -1 && @@ -94,7 +94,7 @@ void linked_sliding_platform_update(struct Moby *moby) { target->state != 0xfe && target->state != 0xfd && target->state == sliding_platform_vars->target_state_word) { allocate_voice_for_target_entry(sliding_platform_vars->trigger_sound, 0, moby); - moby->state = 4; + moby->state = PLATFORM_RETURN_TO_ORIGIN; break; } distance = vector_distance_xy(&moby->pos, origin); @@ -103,7 +103,7 @@ void linked_sliding_platform_update(struct Moby *moby) { allocate_voice_for_target_entry(sliding_platform_vars->arrival_sound, 0, moby); if (sliding_platform_vars->flag_index != -1) D_L07_00184528[sliding_platform_vars->flag_index] = 1; - moby->state = 3; + moby->state = PLATFORM_WAIT_TO_RETURN; } else { step.q = 0; step.f[1] = -(frame_scale * 0.01f); @@ -123,7 +123,7 @@ void linked_sliding_platform_update(struct Moby *moby) { return; if (sliding_platform_vars->trigger_sound != -1) allocate_voice_for_target_entry(sliding_platform_vars->trigger_sound, 0, moby); - moby->state = 4; + moby->state = PLATFORM_RETURN_TO_ORIGIN; } } break; @@ -134,7 +134,7 @@ void linked_sliding_platform_update(struct Moby *moby) { target->state == 0xfe || target->state == 0xfd || target->state == sliding_platform_vars->target_state) { allocate_voice_for_target_entry(sliding_platform_vars->trigger_sound, 0, moby); - moby->state = 2; + moby->state = PLATFORM_MOVE_OUTWARD; return; } distance = vector_distance_xy(&moby->pos, origin); @@ -156,7 +156,7 @@ void linked_sliding_platform_update(struct Moby *moby) { allocate_voice_for_target_entry(sliding_platform_vars->arrival_sound, 0, moby); if (sliding_platform_vars->flag_index != -1) D_L07_00184528[sliding_platform_vars->flag_index] = 0; - moby->state = 1; + moby->state = PLATFORM_WAIT_TO_MOVE_OUTWARD; break; } step.q = 0; From 9c6642b4405e3c7ab9ed9a1c57197841afd2eb40 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:55:23 +0000 Subject: [PATCH 1206/1502] decomp: clarify names in taunter_update domain_2_value_1 -> TAUNTER_STATE_WAIT_FOR_ENABLE_FLAG: Retail 0x002b6fb8 loads taunter object state byte +0x20 into v1; 0x002b6fbc-0x002b6fc0 tests that snapshot against 1. At 0x002b6fc8-0x002b6fd0, this branch waits while object flags byte +0x70 lacks bit 0x02. When set, 0x002b6fd8-0x002b6fe4 increments the state from 1 to 2 (the existing same-domain TAUNTER_STATE_ACTIVE) and clears private retry +0x0c. Both paths exit active handling for this frame. The original Ghidra and authoritative C confirm the flag-gated waiting state. The name claims only the flag's local enabling role, not its external producer or event identity. --- src/overlays/shared/weapons/taunter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/taunter.c b/src/overlays/shared/weapons/taunter.c index c710087ec2..eac592ba45 100644 --- a/src/overlays/shared/weapons/taunter.c +++ b/src/overlays/shared/weapons/taunter.c @@ -459,6 +459,9 @@ void taunter_update(Moby *taunter_moby) { TAUNTER_STATE_INITIALIZE = 0, TAUNTER_STATE_ACTIVE = 2 }; + enum { + TAUNTER_STATE_WAIT_FOR_ENABLE_FLAG = 1 + }; Vars *taunter_vars; s32 taunter_state; s32 voice_slot_index; @@ -485,7 +488,7 @@ void taunter_update(Moby *taunter_moby) { taunter_effect_reset_pending = 1; } taunter_state = taunter_moby->state; - if ((u8)taunter_state == 1) { + if ((u8)taunter_state == TAUNTER_STATE_WAIT_FOR_ENABLE_FLAG) { if (taunter_moby->flags & 2) { taunter_moby->state = taunter_state + 1; taunter_vars->retry = 0; From 1c89aeb4e93145ffdb9c077ae509118bffb21101 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:55:24 +0000 Subject: [PATCH 1207/1502] decomp: clarify names in follow_5968 domain_0_value_0 -> FOLLOW_TARGET_STATUS_DEFAULT_HERO: Retail 0x0025ff98 loads the hero moby into s8 and 0x0025ffa0 initializes stack status to zero. Original Ghidra iVar13=iRam001413d0 and uStack_c0=0 agree with the SHA-bound source. Without rejection or replacement this status is stored at output+0x44 and returned at 0x00260388-0x00260390, proving default hero selection. domain_1_value_2 -> FOLLOW_TARGET_STATUS_HERO_EXCLUDED: Retail 0x0025ff9c-0x0025ffc8 branches on hero control/current restrictions, clears selected s8 and stores status 2. Original Ghidra sets iVar13=0 and uStack_c0=2 in this branch. This is the same selection-status role as the sibling's local COMBAT_TARGET_STATUS_HERO_EXCLUDED, not a HeroStateId. domain_2_value_2 -> FOLLOW_TARGET_STATUS_HERO_EXCLUDED: Retail 0x00260028-0x0026003c calls the hero-position exclusion-volume helper; a nonzero result loads 2 and clears selected s8 before storing status at 0x00260088. Original Ghidra jumps to LAB_00260088 and sets uStack_c0=2. The source list rejection therefore excludes the default hero, while later candidates may replace this status. domain_3_value_2 -> FOLLOW_TARGET_STATUS_HERO_EXCLUDED: Retail 0x00260070-0x00260088 calls the XY region helper on hero position and, for a zero result, clears selected s8 and stores status 2. Original Ghidra LAB_00260088 and current target_region_vertices branch agree. It denotes hero exclusion, not necessarily final absence of a target because candidate loops can overwrite it. domain_4_value_1 -> FOLLOW_TARGET_STATUS_ALTERNATE_MOBY: Retail 0x00260194-0x002601a4 accepts an indexed candidate after distance and spatial gates: moves candidate s2 into selected s8, stores status 1 and updates best from f20. Original Ghidra sets uStack_c0=1 and iVar13=iVar11. Source selected_moby=indexed_candidate proves alternate moby selection. domain_5_value_1 -> FOLLOW_TARGET_STATUS_ALTERNATE_MOBY: Retail 0x002602a4-0x002602b4 accepts a candidate from the 20-entry list after eligibility, distance and spatial gates: moves s2 into s8, stores status 1 and updates best. Original Ghidra sets uStack_c0=1 with iVar13=iVar11. The output pointer/status flow at 0x002602d0 and 0x00260388 proves the same alternate-moby status domain. --- src/overlays/shared/game/unlock_planet.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/game/unlock_planet.c b/src/overlays/shared/game/unlock_planet.c index 37a7b6d410..79e5961a97 100644 --- a/src/overlays/shared/game/unlock_planet.c +++ b/src/overlays/shared/game/unlock_planet.c @@ -123,6 +123,11 @@ int FUN_L00_0025ff38(char *query_moby, float *target_region_vertices, int nv) { + enum { + FOLLOW_TARGET_STATUS_DEFAULT_HERO = 0, + FOLLOW_TARGET_STATUS_ALTERNATE_MOBY = 1, + FOLLOW_TARGET_STATUS_HERO_EXCLUDED = 2 + }; struct Hero *hero_data = &hero_lui; char *selected_moby; char *indexed_candidate; @@ -135,22 +140,22 @@ int FUN_L00_0025ff38(char *query_moby, float candidate_distance_score; selected_moby = (char *)hero_data->moby; - target_selection_status = 0; + target_selection_status = FOLLOW_TARGET_STATUS_DEFAULT_HERO; if (hero_data->state.control_mode == 0x18 || hero_data->state.current == 0x72) { selected_moby = 0; - target_selection_status = 2; + target_selection_status = FOLLOW_TARGET_STATUS_HERO_EXCLUDED; } else if (exclusion_list_bound > 0) { for (k = 0; k < exclusion_list_bound - 1; k++) { if (is_point_inside_clip_volume(&hero_lui.motion.pos, list[k]) != 0) { selected_moby = 0; - target_selection_status = 2; + target_selection_status = FOLLOW_TARGET_STATUS_HERO_EXCLUDED; break; } } } else if (target_region_vertices != 0 && nv > 0) { if (point_in_path_xy(&hero_lui.motion.pos, target_region_vertices, nv) == 0) { selected_moby = 0; - target_selection_status = 2; + target_selection_status = FOLLOW_TARGET_STATUS_HERO_EXCLUDED; } } for (i = 1; i <= D_L00_001B0830_lui[0]; i++) { @@ -184,7 +189,7 @@ int FUN_L00_0025ff38(char *query_moby, } if (ok) { selected_moby = indexed_candidate; - target_selection_status = 1; + target_selection_status = FOLLOW_TARGET_STATUS_ALTERNATE_MOBY; best = candidate_distance_score; } } @@ -218,7 +223,7 @@ int FUN_L00_0025ff38(char *query_moby, } if (ok) { selected_moby = listed_candidate; - target_selection_status = 1; + target_selection_status = FOLLOW_TARGET_STATUS_ALTERNATE_MOBY; best = candidate_distance_score; } } From 7417e5cdb4f352f5239dfec006ee23dadb2a1f28 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:55:24 +0000 Subject: [PATCH 1208/1502] decomp: clarify names in process_ultramech_hits_and_update_target domain_0_value_1 -> HIT_CLASSIFICATION_NO_DAMAGE: Retail caller 0x002d0ff0 passes sp+0x40 as fifth output parameter to 0x00249d60; 0x002d1088-0x002d1090 reads it and skips health subtraction and local reaction processing when it equals 1. Checked level-15 classifier evidence request 29c879d0d43d4cdf8cb2acd834794347 retains that output pointer in s3 at 0x00249d70. No-hit path 0x00249e70-0x00249ea8 writes 1 through s3, clears damage output, and returns 11. Suppression path 0x0024a22c-0x0024a240 writes 1 through s3 and zeros hit-record damage at +0x2c, copied to caller damage output at 0x0024a268-0x0024a26c. Thus 1 denotes no damage in this classifier output, independently of the reaction-code return and moby-state byte. Existing equal-valued hero, reaction and Ultramech state members belong to different domains. --- src/overlays/l15/mobys/ultramech_unlimited.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l15/mobys/ultramech_unlimited.c b/src/overlays/l15/mobys/ultramech_unlimited.c index 22d94b1c08..42ba395e94 100644 --- a/src/overlays/l15/mobys/ultramech_unlimited.c +++ b/src/overlays/l15/mobys/ultramech_unlimited.c @@ -989,6 +989,9 @@ void process_ultramech_hits_and_update_target(void *ultramech_instance) { ULTRAMECH_DEATH_EFFECTS = 10, ULTRAMECH_DEAD_WAIT_FOR_RESET = 0x40 }; + enum { + HIT_CLASSIFICATION_NO_DAMAGE = 1 + }; UMoby *ultramech_moby = ultramech_instance; UData *ultramech_vars = ultramech_moby->data; char *slot = 0; @@ -1026,7 +1029,7 @@ void process_ultramech_hits_and_update_target(void *ultramech_instance) { } code = FUN_00249d60(ultramech_moby, slot, &ultramech_vars->f20, 0, &kind, &impact, 0, 4); if (slot != 0) { - if (kind != 1 && (state = ultramech_moby->state) != 10 && state != ULTRAMECH_DEAD_WAIT_FOR_RESET && + if (kind != HIT_CLASSIFICATION_NO_DAMAGE && (state = ultramech_moby->state) != 10 && state != ULTRAMECH_DEAD_WAIT_FOR_RESET && *(short *)(*(char **)(slot + 0x20) + 0xA6) != 0x350) { ultramech_vars->f20 -= impact; if (*(unsigned short *)(slot + 0x2A) == 0x100) From ca59dfbd0f97a731a56c1fea904e5ecb573fba64 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:57:09 +0000 Subject: [PATCH 1209/1502] decomp: clarify names in update_frog_health_respawn_and_target domain_0_value_1 -> HIT_STATUS_DAMAGE_SUPPRESSED: Retail 0x002e95c0 passes the stack kind output to resolve_moby_hit_response; 0x002e95d8-0x002e95e0 skips subtraction when it is 1. Checked level-06 helper 0x00269288 retains this pointer in s3. Its null-hit path 0x00269398-0x002693d0 sets status 1 and zero damage; its response-flag suppression path 0x0026975c-0x00269768 likewise sets status 1 and clears hit damage before output at 0x00269790-0x00269794. This is the hit-status domain, separate from the returned hit-result code. domain_3_value_1 -> FROG_TARGET_MODE_EXPLICIT_TARGET: Retail 0x002e97bc-0x002e97ec checks target_id at vars+0x204 against -1, indexes the moby array with target_id*0x100, stores that moby at vars+0x1c0, copies its position to vars+0x180, and stores 1 at vars+0x1c4. Original Ghidra and authoritative frog_state->target_mode assignment identify this as explicitly indexed target mode, not a moby state or Hero mode. domain_4_value_2 -> FROG_TARGET_MODE_NO_PURSUIT_TARGET: Retail 0x002e9838-0x002e985c calls select_hero_or_gadgebot_target with vars+0x1c0 as output, then stores 2 at vars+0x1c4 when that output is null. The frog_update consumer in the supplied C avoids starting ordinary pursuit when +0x1c4 is 2 and switches APPROACH_TARGET to RETURN_HOME. The later fallback pointer assignment does not change this mode, so the name describes pursuit eligibility rather than pointer nullness. domain_5_value_2 -> FROG_TARGET_MODE_NO_PURSUIT_TARGET: Retail 0x002e987c-0x002e98d0 rejects an automatically selected target if point_in_path_xy returns zero, or if a class-0x359 target is farther than 2.0 in XY. Both rejection paths clear vars+0x1c0 and store 2 to vars+0x1c4. This is the same frog target-mode field whose value 2 prevents pursuit and sends APPROACH_TARGET to RETURN_HOME in the supplied frog_update source. domain_6_value_0 -> FROG_TARGET_MODE_AUTOMATIC_TARGET: Retail 0x002e9840 automatically selects hero/gadgebot into vars+0x1c0; 0x002e987c checks path inclusion and 0x002e988c-0x002e98c0 checks class-0x359 distance. Accepted targets store zero at vars+0x1c4 at 0x002e9898 or 0x002e98c0. Original Ghidra and C show this mode only after accepting that automatic target, distinct from target_id-selected mode 1 and rejected pursuit mode 2. domain_7_value_2 -> FROG_TARGET_MODE_NO_PURSUIT_TARGET: Retail 0x002e9908 obtains a path-constrained target position at vars+0x180. Unless the helper returns 2, 0x002e9918-0x002e9960 stores 2 at vars+0x1c4 if spawn-to-goal XY distance exceeds range or absolute vertical separation exceeds 3.0. The same field value prevents pursuit and triggers return home in supplied frog_update. The helper return value 2 is a separate domain and is not renamed. --- src/overlays/shared/enemies/frog.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/enemies/frog.c b/src/overlays/shared/enemies/frog.c index 8ce22a03a5..9d395830d6 100644 --- a/src/overlays/shared/enemies/frog.c +++ b/src/overlays/shared/enemies/frog.c @@ -590,6 +590,12 @@ void update_frog_health_respawn_and_target(struct Moby *moby) { HIT_RESULT_REMOVE_OR_RESPAWN = 2, HIT_RESULT_NO_RESPONSE = 11 }; + enum { + FROG_TARGET_MODE_AUTOMATIC_TARGET = 0, + HIT_STATUS_DAMAGE_SUPPRESSED = 1, + FROG_TARGET_MODE_EXPLICIT_TARGET = 1, + FROG_TARGET_MODE_NO_PURSUIT_TARGET = 2 + }; struct RespawnVars *frog_state; struct MobyHit *hit; int kind; @@ -610,7 +616,7 @@ void update_frog_health_respawn_and_target(struct Moby *moby) { damage = 0.0f; hit = find_moby_hit(moby, 0x330000, 0); code = resolve_moby_hit_response(moby, hit, &frog_state->health, 0, &kind, &damage, 0, 4); - if (kind != 1 && moby->state != 0xE) { + if (kind != HIT_STATUS_DAMAGE_SUPPRESSED && moby->state != 0xE) { frog_state->health = frog_state->health - damage; if (frog_state->health <= 0.0f) { code = 1; @@ -665,7 +671,7 @@ void update_frog_health_respawn_and_target(struct Moby *moby) { } if (frog_state->target_id != -1) { struct Moby *target = &D_L06_0015FFD8_e94f0[frog_state->target_id]; - frog_state->target_mode = 1; + frog_state->target_mode = FROG_TARGET_MODE_EXPLICIT_TARGET; frog_state->target = target; qcopy(&frog_state->target_pos, &target->pos); } else if (D_001413F4_e94f0[0] == 1) { @@ -673,16 +679,16 @@ void update_frog_health_respawn_and_target(struct Moby *moby) { select_hero_or_gadgebot_target( (char *)moby, (char **)&frog_state->target, frog_state->range); if (frog_state->target == 0) { - frog_state->target_mode = 2; + frog_state->target_mode = FROG_TARGET_MODE_NO_PURSUIT_TARGET; } else { int *path = D_L06_001B0C30[frog_state->path]; if (point_in_path_xy(&frog_state->target->pos, path + 4, *path) == 0 || (frog_state->target->oclass == 0x359 && 2.0f < vector_distance_xy(&moby->pos, &frog_state->target->pos))) { frog_state->target = 0; - frog_state->target_mode = 2; + frog_state->target_mode = FROG_TARGET_MODE_NO_PURSUIT_TARGET; } else { - frog_state->target_mode = 0; + frog_state->target_mode = FROG_TARGET_MODE_AUTOMATIC_TARGET; } } } @@ -692,7 +698,7 @@ void update_frog_health_respawn_and_target(struct Moby *moby) { if (activate_effect_l08(moby, goal, frog_state->range, 0, 0, path + 4, *path) != 2) { if (frog_state->range < vector_distance_xy(&frog_state->spawn_pos, goal) || 3.0f < absolute_float(moby->pos.z - frog_state->target_pos.z)) { - frog_state->target_mode = 2; + frog_state->target_mode = FROG_TARGET_MODE_NO_PURSUIT_TARGET; } } } From f96ca6d927b30776ffa307991fc1f500ddef47f7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:59:05 +0000 Subject: [PATCH 1210/1502] decomp: clarify names in update_linked_moby_hitbox domain_0_value_254 -> MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF: Assigned retail 0x002c9d60-0x002c9d70 excludes 0xfe/0xfd from linked_moby->state (+0x20). The same update calls established mark_moby_for_removal at 0x002ca040/0x002ca048. Checked level-10 helper 0x002415e0 compares its moby pointer unsigned against *(0x0015ffdc) at 0x002415f0; the at-or-above branch loads 0xfe at 0x00241604 and stores it into that same Moby state byte at 0x00241608. Thus this is the removal marker selected at or above the cutoff; allocation-class meaning is not claimed. domain_1_value_253 -> MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF: Assigned retail 0x002c9d60-0x002c9d70 excludes 0xfd from linked_moby->state (+0x20), alongside 0xfe. Checked direct mark_moby_for_removal helper (level-10 0x002415e0, request 1c6da87dc465453c95240786fb853c86) uses sltu at 0x002415f0 to compare the moby pointer with *(0x0015ffdc). Its below-cutoff path loads 0xfd at 0x00241600, joins the state-byte store at 0x00241608, and records a counter plus two at +0x38. This proves a removal marker selected below the cutoff without inventing its allocation-class meaning. --- src/overlays/l10/mobys/linked_moby_hitbox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/linked_moby_hitbox.c b/src/overlays/l10/mobys/linked_moby_hitbox.c index 1d51ba1a6f..0d7464eb8e 100644 --- a/src/overlays/l10/mobys/linked_moby_hitbox.c +++ b/src/overlays/l10/mobys/linked_moby_hitbox.c @@ -145,7 +145,7 @@ void linked_moby_hitbox_update(struct Moby *moby) { LINKED_HITBOX_STATE_WAIT_FOR_LINKED_MOBIES = 1, LINKED_HITBOX_STATE_WAIT_FOR_TARGET_STATE_OR_TIMER = 2, LINKED_HITBOX_STATE_REMOVE = 3 - }; + } ; enum { MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF = 0xfd , MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF = 0xfe}; LinkedMobyHitboxVars *linked_hitbox_vars = (LinkedMobyHitboxVars *)moby->pvars; int differences = 0; struct Moby *target = 0; @@ -164,7 +164,7 @@ void linked_moby_hitbox_update(struct Moby *moby) { if (index != -1) { struct Moby *linked_moby = &D_L10_0015FFD8[index]; if (linked_moby != 0 && linked_moby->oclass == *(short *)(entry + 1) && - linked_moby->state != 0xfe && linked_moby->state != 0xfd) { + linked_moby->state != MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF && linked_moby->state != MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF) { unsigned short id = linked_moby->save_id; if ((((*(int *)((unsigned char *)D_0014C190_257218 + (((short)id >> 5) * 4) + (D_0015ED84 << 8)) >> From 2e8ec6983ff264d89ea5eb11d6d4ab5380072b36 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 21:59:05 +0000 Subject: [PATCH 1211/1502] decomp: clarify names in _decMB0 domain_0_value_2 -> MOTION_TYPE_FRAME: In the authoritative C, this assignment is guarded by picture_structure == 3 and frame_pred_frame_dct != 0. Retail 0x00127cb4-0x00127cd0 stores 2 through s5 (motion_type); 0x00127d2c-0x00127d38 recognizes that same value as frame_motion for frame pictures, yielding one vector and suppressing field-in-frame vertical handling. Original Ghidra independently shows the same guarded assignment and frame-format boolean. This names the frame-picture motion syntax, not value 2 in the distinct field-picture interpretation. domain_1_value_0 -> DCT_TYPE_FRAME: The authoritative C initializes dct_type to 0 before conditionally reading one DCT-selection bit only for frame pictures with frame_pred_frame_dct == 0 and macroblock flags & 3. Retail 0x00127d68-0x00127da8 defaults to zero and stores this output; 0x00127f74-0x00127f8c shifts it into IPU block-decode command bit 25. In particular frame_pred_frame_dct enabled forces this zero selection, proving frame DCT rather than field DCT. Original Ghidra matches this default/read/output flow. domain_2_value_0 -> DCT_TYPE_FRAME: This is the else assignment of the same dct_type selection: authoritative C leaves it zero when frame_pred_frame_dct is enabled, when picture structure is not a frame, or when no block decoding is needed. Retail 0x00127d70/0x00127d7c/0x00127da0 supplies zero to the store at 0x00127da8, and the output becomes IPU block-decode bit 25 at 0x00127f84. The enabled frame_pred_frame_dct path proves zero selects frame DCT; use the same constant as the initialization, not a generic FALSE. domain_3_value_2 -> PICTURE_CODING_TYPE_PREDICTIVE: Authoritative C obtains coding_type from decoder->picture_coding_type (offset 0x150); retail 0x00128014-0x0012802c compares it to 2 and tests mb_type & 9. Only this picture type defaults non-intra blocks lacking forward vectors to zero forward motion predictors at 0x00128034-0x00128044 and frame/field forward motion at 0x00128048-0x00128070. This is the predictive P-picture fallback, also identified as P-picture in the supplied prior retail findings. It is a picture-coding selector, separate from motion_type despite sharing numeric 2. domain_4_value_1 -> MOTION_TYPE_FIELD: This assignment occurs in the predictive-picture zero-forward-motion fallback when picture_structure != 3. Retail 0x00128048-0x0012805c stores 1 through s5 (motion_type), then 0x00128060-0x00128070 selects the current field via picture_structure == 2. Earlier 0x00127d3c-0x00127d4c makes field-picture motion_type 1 use one vector, with frame_motion clear; the adjacent field selection proves single-field motion, distinct from frame motion value 2. Original Ghidra shows both the store and field-selector update. --- src/sdk/mpeg/macroblock/_decMB0.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/sdk/mpeg/macroblock/_decMB0.c b/src/sdk/mpeg/macroblock/_decMB0.c index fcea4a6867..359283ba9a 100644 --- a/src/sdk/mpeg/macroblock/_decMB0.c +++ b/src/sdk/mpeg/macroblock/_decMB0.c @@ -25,6 +25,12 @@ int _decMB0(struct MpegDecoder *decoder, int *motion_field_select, int differential_motion_vector) { + enum { + DCT_TYPE_FRAME = 0, + MOTION_TYPE_FIELD = 1, + MOTION_TYPE_FRAME = 2, + PICTURE_CODING_TYPE_PREDICTIVE = 2 + }; int *dct_type_output; int *motion_field_select_output; u32 intra_quantiser_command_bits; @@ -57,7 +63,7 @@ int _decMB0(struct MpegDecoder *decoder, } if (type_code & 0xC) { if ((decoder->picture_structure == 3) && (decoder->frame_pred_frame_dct != 0)) { - *motion_type = 2; + *motion_type = MOTION_TYPE_FRAME; } else { *motion_type = _nextBit(decoder, 2); } @@ -78,12 +84,12 @@ int _decMB0(struct MpegDecoder *decoder, if (frame_motion == 0) { field_in_frame = structure == 3; } - dct_type = 0; + dct_type = DCT_TYPE_FRAME; if (((decoder->picture_structure == 3) && (decoder->frame_pred_frame_dct == 0)) && (((*mb_type) & 3) != 0)) { dct_type = _nextBit(decoder, 1); } else { - dct_type = 0; + dct_type = DCT_TYPE_FRAME; } *dct_type_output = dct_type; if ((*mb_type) & 0x10) { @@ -182,7 +188,7 @@ int _decMB0(struct MpegDecoder *decoder, } coding_type = decoder->picture_coding_type; decode_success = 1; - if (coding_type == 2) { + if (coding_type == PICTURE_CODING_TYPE_PREDICTIVE) { decode_success = 1; if (!((*mb_type) & 9)) { motion_vector_state->unk0 = @@ -191,7 +197,7 @@ int _decMB0(struct MpegDecoder *decoder, if (decoder->picture_structure == 3) { *motion_type = coding_type; } else { - *motion_type = 1; + *motion_type = MOTION_TYPE_FIELD; *motion_field_select_output = decoder->picture_structure == 2; } decode_success = 1; From c49787f999c28c4c46ff89665054c1d924929613 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:01:00 +0000 Subject: [PATCH 1212/1502] decomp: clarify names in update_alien_snapper_hit_response_and_targeting domain_0_value_17 -> ALIEN_SNAPPER_STATE_DEATH_MOTION: Retail 0x002f92c4-0x002f92cc reads moby+0x20 and excludes 17 before damage processing; original Ghidra agrees. The authoritative alien_snapper_update calls this helper on the same moby before dispatching that field, and its named state 17 advances death motion, emits break fragments and removes the moby. The same field is set to 17 by the death response at 0x002f93d0. domain_1_value_3 -> ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER: Retail 0x002f92c4-0x002f92d4 tests the current moby+0x20 against 3 to bypass hit processing, matching original Ghidra. Supplied alien_snapper_update passes this same moby to the helper before its state switch; its named state 3 checks clip_volume with is_point_inside_clip_volume and only then enters state 4 and the jump preparation sequence. This is the snapper current-state domain, not a hero state or reaction selector. domain_2_value_14 -> ALIEN_SNAPPER_STATE_HIT_KNOCKBACK: Retail 0x002f9358-0x002f9364 stores 14 at moby+0x20 in the nonlethal response arm; 0x002f9368-0x002f93b0 initializes pvars+0x70 motion and response animation 9. Original Ghidra agrees. Supplied alien_snapper_update calls this helper before switching on the same moby->state, and its named state 14 advances that motion, checks the route and transitions to retreat state 13. domain_3_value_17 -> ALIEN_SNAPPER_STATE_DEATH_MOTION: Retail 0x002f93c4-0x002f93d0 stores 17 at moby+0x20 for death response cases 1/2; 0x002f9430-0x002f9458 starts response animation 10 and death bookkeeping, as original Ghidra shows. The authoritative alien_snapper_update calls this helper before dispatching the same moby state; its named state 17 advances death motion, emits fragments and removes the moby. Reuse the same member as the state-17 comparison. domain_4_value_1 -> ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION: Retail 0x002f9590-0x002f9598 compares moby+0x20 with 1, then 0x002f95a8-0x002f95cc selects a six-unit or zero targeting radius based on hero contact; original Ghidra agrees. Supplied alien_snapper_update calls this helper on the same moby before state dispatch. Its named state 1 waits while target status f164 is 2 and otherwise enters activation state 2 and starts its timer. Thus this is the snapper activation-wait state. --- src/overlays/l06/mobys/alien_snapper.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/overlays/l06/mobys/alien_snapper.c b/src/overlays/l06/mobys/alien_snapper.c index dbcc5f20ff..2bb8d22e74 100644 --- a/src/overlays/l06/mobys/alien_snapper.c +++ b/src/overlays/l06/mobys/alien_snapper.c @@ -725,6 +725,12 @@ void update_alien_snapper_hit_response_and_targeting(Moby *moby) { SNAPPER_RETURN_HOME = 12, SNAPPER_RETREAT_FROM_TARGET = 13 }; + enum { + ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION = 1, + ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER = 3, + ALIEN_SNAPPER_STATE_HIT_KNOCKBACK = 14, + ALIEN_SNAPPER_STATE_DEATH_MOTION = 0x11 + }; BlargVars *snapper_vars = (struct BlargVars *)moby->pvars; int hit; float damage; @@ -745,7 +751,7 @@ void update_alien_snapper_hit_response_and_targeting(Moby *moby) { reaction = resolve_moby_hit_response(moby, target, &snapper_vars->health, 0, &hit, &damage, 0, 4); - if (hit != 1 && moby->state != 0x11 && moby->state != 3) { + if (hit != 1 && moby->state != ALIEN_SNAPPER_STATE_DEATH_MOTION && moby->state != ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER) { snapper_vars->health = snapper_vars->health - damage; if (moby->group != 0xFF) { func_L06_002FAAC8_2FA618(moby); @@ -768,7 +774,7 @@ void update_alien_snapper_hit_response_and_targeting(Moby *moby) { case HIT_RESPONSE_NONLETHAL_ANIMATION_MAINTENANCE: case HIT_RESPONSE_NONLETHAL_ANIMATION_FEEDBACK: case HIT_RESPONSE_NONLETHAL_KNOCKBACK: - moby->state = 14; + moby->state = ALIEN_SNAPPER_STATE_HIT_KNOCKBACK; snapper_vars->f88 = frame_time + frame_time; snapper_vars->f8C = frame_time; snapper_vars->fC0 = 5.0f; @@ -779,7 +785,7 @@ void update_alien_snapper_hit_response_and_targeting(Moby *moby) { break; case REACTION_DEATH: case HIT_RESPONSE_DEATH_SEQUENCE: - moby->state = 0x11; + moby->state = ALIEN_SNAPPER_STATE_DEATH_MOTION; moby->flags &= 0xEFFF; snapper_vars->f88 = frame_time * 8.0f; snapper_vars->f8C = frame_time * 5.0f; @@ -815,7 +821,7 @@ void update_alien_snapper_hit_response_and_targeting(Moby *moby) { if (snapper_vars->f1AC != 0) { snapper_vars->f1A0 = l06_alien_snapper_base_targeting_radius + 6.0f; - } else if (moby->state == 1) { + } else if (moby->state == ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION) { if (moby == ((Moby *)hero.unk240) || moby == ((Moby *)hero.coll_hit_moby)) { snapper_vars->f1A0 = 6.0f; } else { From 5252e8bb49c4a03e5befc88aba5f26297257e3a4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:01:00 +0000 Subject: [PATCH 1213/1502] decomp: clarify names in update_sliding_gate domain_0_value_1 -> MOVING_MOBY_WAIT_AT_HOME: Retail 0x0031aaa4-0x0031aadc saves moby+0x10 position into private home, clears the indicator and home.w, then stores 1 to moby+0x20 at 0x0031aad4. This is the exact byte selected at 0x0031aa7c by the existing MOVING_MOBY_WAIT_AT_HOME case. domain_10_value_4 -> MOVING_MOBY_RETURN_HOME: Retail 0x0031acf0-0x0031ad60 waits at the offset until override/target shut-state conditions permit return, clears home.w and loads 4 for the common moby+0x20 store. Existing MOVING_MOBY_RETURN_HOME is the case for that exact selector and value. domain_13_value_2 -> MOVING_MOBY_MOVE_TO_OFFSET: Retail return-path reversal at 0x0031adb4-0x0031add0 optionally starts sound and loads 2 for the shared store at 0x0031aeb8 to moby+0x20. The exact same byte selects existing MOVING_MOBY_MOVE_TO_OFFSET, whose branch advances toward home plus transformed destination offset. domain_14_value_1 -> MOVING_MOBY_WAIT_AT_HOME: Retail 0x0031ae74-0x0031aeb8 restores saved home to moby position, clears the indexed indicator and writes 1 to moby+0x20. This returns to the existing MOVING_MOBY_WAIT_AT_HOME case of the switch on that exact byte. domain_3_value_2 -> MOVING_MOBY_MOVE_TO_OFFSET: Retail 0x0031ab34-0x0031ab80 measures the configured destination offset and initializes home.w, then loads 2 for the common store to moby+0x20 at 0x0031aeb8. The same selector's existing MOVING_MOBY_MOVE_TO_OFFSET case transforms and adds positive offset steps. domain_6_value_4 -> MOVING_MOBY_RETURN_HOME: Retail state-2 reversal path 0x0031abd4-0x0031abf0 optionally starts sound and loads 4 for the common moby+0x20 store. This is the same state byte dispatched at 0x0031aa7c; existing MOVING_MOBY_RETURN_HOME case applies negative offset steps and restores saved home. domain_7_value_3 -> MOVING_MOBY_WAIT_AT_OFFSET: Retail 0x0031ac8c-0x0031acc8 clamps position to saved home plus transformed offset, clears remaining progress, sets indicator to 1 and stores 3 at moby+0x20. The existing MOVING_MOBY_WAIT_AT_OFFSET case uses this same selector and waits for the return condition. --- src/overlays/l07/mobys/sliding_gate.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l07/mobys/sliding_gate.c b/src/overlays/l07/mobys/sliding_gate.c index 3e27b825b4..732185b523 100644 --- a/src/overlays/l07/mobys/sliding_gate.c +++ b/src/overlays/l07/mobys/sliding_gate.c @@ -68,7 +68,7 @@ void sliding_gate_update(struct Moby *moby) { qcopy(&offset_motion->home, &moby->pos); if (offset_motion->indicator != -1) D_L07_00184528[offset_motion->indicator] = 0; - moby->state = 1; + moby->state = MOVING_MOBY_WAIT_AT_HOME; offset_motion->home.w = 0; return; case MOVING_MOBY_WAIT_AT_HOME: @@ -86,7 +86,7 @@ void sliding_gate_update(struct Moby *moby) { offset_motion->home.w = fast_vec_length(&offset_vector); if (offset_motion->startSound != -1) allocate_voice_for_target_entry(offset_motion->startSound, 0, moby); - moby->state = 2; + moby->state = MOVING_MOBY_MOVE_TO_OFFSET; break; case MOVING_MOBY_MOVE_TO_OFFSET: if (force_start || @@ -95,7 +95,7 @@ void sliding_gate_update(struct Moby *moby) { target->state != 0xfd && target->state == offset_motion->shutState)) { if (offset_motion->startSound != -1) allocate_voice_for_target_entry(offset_motion->startSound, 0, moby); - moby->state = 4; + moby->state = MOVING_MOBY_RETURN_HOME; break; } start.q = 0; @@ -114,7 +114,7 @@ void sliding_gate_update(struct Moby *moby) { offset_motion->home.w = 0; if (offset_motion->indicator != -1) D_L07_00184528[offset_motion->indicator] = 1; - moby->state = 3; + moby->state = MOVING_MOBY_WAIT_AT_OFFSET; if (offset_motion->endSound != -1) allocate_voice_for_target_entry(offset_motion->startSound, 0, moby); return; @@ -127,7 +127,7 @@ void sliding_gate_update(struct Moby *moby) { offset_motion->home.w = 0; if (offset_motion->startSound != -1) allocate_voice_for_target_entry(offset_motion->startSound, 0, moby); - moby->state = 4; + moby->state = MOVING_MOBY_RETURN_HOME; break; case MOVING_MOBY_RETURN_HOME: if (!force_start && @@ -136,7 +136,7 @@ void sliding_gate_update(struct Moby *moby) { target->state == 0xfd || target->state == offset_motion->openState)) { if (offset_motion->startSound != -1) allocate_voice_for_target_entry(offset_motion->startSound, 0, moby); - moby->state = 2; + moby->state = MOVING_MOBY_MOVE_TO_OFFSET; break; } start.q = 0; @@ -157,7 +157,7 @@ void sliding_gate_update(struct Moby *moby) { allocate_voice_for_target_entry(offset_motion->endSound, 0, moby); if (offset_motion->indicator != -1) D_L07_00184528[offset_motion->indicator] = 0; - moby->state = 1; + moby->state = MOVING_MOBY_WAIT_AT_HOME; break; case 5: break; From 5199e138b833430bc178eede030f4d4e167c77d0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:01:00 +0000 Subject: [PATCH 1214/1502] decomp: clarify names in update_darter_hit_reactions_and_targeting domain_1_value_2 -> TARGET_SELECTION_DEFAULT_REJECTED_NO_REPLACEMENT: Retail caller 0x002e1aa8/0x002e1ab0 feeds ahead_f return into s3; 0x002e1ab4 compares it with 2. Checked helper 0x002527c8 loads the default candidate from 0x0013f350+0x2080 (=D_001413D0, the caller's fallback target). At 0x00252830..34 it clears that candidate and sets status s5=2 on rejection. Selecting any replacement at 0x002528d0..d8 or 0x00252954..5c overwrites status with 1. With no replacement, 0x002529f4 clears output target and 0x00252a10 returns unchanged status 2. Thus 2 specifically records default rejection without replacement; it is a selection status, not a moby state. domain_4_value_2 -> TARGET_SELECTION_DEFAULT_REJECTED_NO_REPLACEMENT: Retail 0x002e1bd8/0x002e1c20/0x002e1c3c merge path-constrained and ordinary selection returns in s3 for the comparison with 2 at 0x002e1c44. Ordinary helper 0x002527c8 clears its default candidate and sets status 2 at 0x00252830..34; replacements overwrite it with 1. Path helper 0x00252a48 likewise loads default candidate from D_001413D0 at 0x00252aa8, clears it and sets status 2 at 0x00252ac4..d8 or 0x00252b44..98 when default eligibility fails. Replacement selections at 0x00252cac..b0 and 0x00252dbc..c0 overwrite status with 1. Otherwise null output is written at 0x00252e70 and status 2 returned at 0x00252ea0. Both helpers therefore share default-rejected-without-replacement status 2. --- src/overlays/l10/mobys/darter.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/darter.c b/src/overlays/l10/mobys/darter.c index 1f0a61db8c..f4946ecdf9 100644 --- a/src/overlays/l10/mobys/darter.c +++ b/src/overlays/l10/mobys/darter.c @@ -649,6 +649,9 @@ void update_darter_hit_reactions_and_targeting(struct Moby *moby) { enum { DARTER_STATE_DYING = 13 }; + enum { + TARGET_SELECTION_DEFAULT_REJECTED_NO_REPLACEMENT = 2 + }; MobyData *class_1199_vars = ((struct MobyData *)moby->pvars); float vector_scratch[4]; float transformed_offset[4]; @@ -715,7 +718,7 @@ void update_darter_hit_reactions_and_targeting(struct Moby *moby) { } if (class_1199_vars->f174 == 2) { target_selection_status = ahead_f(class_1199_vars->f180, moby, class_1199_vars->fC0); - if (target_selection_status != 2) { + if (target_selection_status != TARGET_SELECTION_DEFAULT_REJECTED_NO_REPLACEMENT) { LevelCuboid *bp = &l10_cuboids[class_1199_vars->f194]; fast_vec_sub(vector_scratch, D_0013F3D0, &bp->pos); vector_scratch[3] = 0.0f; @@ -745,7 +748,7 @@ void update_darter_hit_reactions_and_targeting(struct Moby *moby) { } else { target_selection_status = ahead_f(class_1199_vars->f180, moby, class_1199_vars->fC0); } - if (target_selection_status != 2) { + if (target_selection_status != TARGET_SELECTION_DEFAULT_REJECTED_NO_REPLACEMENT) { if (class_1199_vars->f180 < vector_distance_xy(class_1199_vars->f130, class_1199_vars->fC0)) { class_1199_vars->f104 = 2; From 4c368739912f762e6f9349ee9590a206cbdfa657 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:03:06 +0000 Subject: [PATCH 1215/1502] decomp: clarify names in taunter_update domain_1_value_3 -> TAUNTER_STATE_ACTIVATION_DISABLED: Retail 0x002b6f70-0x002b6f84 reads this taunter object's type byte +0x53 and, when it equals 2, stores 3 into its distinct state byte +0x20. At 0x002b6f8c emission is disabled; the state dispatch at 0x002b6f90-0x002b6fe8 excludes state 3 from initialize (0), wait-for-enable (1), and ACTIVE (2), branching directly to 0x002b7358. It therefore bypasses button activation, voice allocation/release and apply_taunter_to_nearby_mobies, while the common effect-slot tail may still execute. Original Ghidra and authoritative taunter_update C agree. ACTIVATION_DISABLED names this bounded state role without asserting object destruction or any hero enum equivalence. --- src/overlays/shared/weapons/taunter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/taunter.c b/src/overlays/shared/weapons/taunter.c index eac592ba45..3c0f101543 100644 --- a/src/overlays/shared/weapons/taunter.c +++ b/src/overlays/shared/weapons/taunter.c @@ -462,6 +462,9 @@ void taunter_update(Moby *taunter_moby) { enum { TAUNTER_STATE_WAIT_FOR_ENABLE_FLAG = 1 }; + enum { + TAUNTER_STATE_ACTIVATION_DISABLED = 3 + }; Vars *taunter_vars; s32 taunter_state; s32 voice_slot_index; @@ -480,7 +483,7 @@ void taunter_update(Moby *taunter_moby) { if (taunter_vars->radius == 0.0f) taunter_vars->radius = 30.0f; if (taunter_moby->type == 2) - taunter_moby->state = 3; + taunter_moby->state = TAUNTER_STATE_ACTIVATION_DISABLED; taunter_effect_emission_disabled = 1; if (taunter_moby->state == TAUNTER_STATE_INITIALIZE) { taunter_vars->anim = -1; From e78ca0c286842fbb85fc974a4dd25afe975e4910 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:03:06 +0000 Subject: [PATCH 1216/1502] decomp: clarify names in update_frog_health_respawn_and_target domain_1_value_15 -> FROG_STATE_RESPAWN: Retail s1 is the frog moby (0x002e9504), and 0x002e96dc-0x002e96e0 stores 15 into its state byte at +0x20. This follows the nonzero-lives branch: 0x002e96ac-0x002e96cc decrements lives at pvars+0x240 and restores health from max_health, while 0x002e96c8-0x002e96d4 copies spawn_pos at pvars+0x210 to moby->pos. It then clears collision and changes flags at 0x002e96e4-0x002e96f0. Original Ghidra and authoritative C agree this is the frog respawn entry, not a Hero state or hit-result ID. The frog_update initialization path also assigns 0xF with the same collision/flag setup. --- src/overlays/shared/enemies/frog.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/frog.c b/src/overlays/shared/enemies/frog.c index 9d395830d6..b5adc22c80 100644 --- a/src/overlays/shared/enemies/frog.c +++ b/src/overlays/shared/enemies/frog.c @@ -596,6 +596,9 @@ void update_frog_health_respawn_and_target(struct Moby *moby) { FROG_TARGET_MODE_EXPLICIT_TARGET = 1, FROG_TARGET_MODE_NO_PURSUIT_TARGET = 2 }; + enum { + FROG_STATE_RESPAWN = 0xF + }; struct RespawnVars *frog_state; struct MobyHit *hit; int kind; @@ -642,7 +645,7 @@ void update_frog_health_respawn_and_target(struct Moby *moby) { frog_state->lives = frog_state->lives - 1; frog_state->health = frog_state->max_health; qcopy(&moby->pos, &frog_state->spawn_pos); - moby->state = 0xF; + moby->state = FROG_STATE_RESPAWN; moby->collision = 0; moby->flags = (moby->flags & 0xEFFF) | 0x41; break; From 32beaefa2e2067866dcf3a61ed65522c25449c16 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:03:06 +0000 Subject: [PATCH 1217/1502] decomp: clarify names in process_hero_incoming_hit domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 00208eb0 loads the byte at hero+0x20A4, the source hero.vehicle_mode selector, and 00208eb4-00208ec4 compares it with 2 before requiring incoming_hit_record->i24 bit 2. The same field is loaded at 00209010 and compared with 2 at 00209014 to enter the source case HERO_VEHICLE_MODE_GIANT_CLANK at 00209220. Thus this comparison belongs to the supplied HeroVehicleMode domain and reuses its canonical member, not an equal-valued state or gravity constant. domain_1_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 00208f14 loads hero+0x20A4 into a3, 00208f18 sets a1 to 2, and 00208f28 gates conversion of hit record+0x2C followed by subtraction/clamping of hero+0x1630 (source hero.vehicle_hp) at 00208f30-00208f48. This is the same hero.vehicle_mode byte dispatched at 00209010-00209014 into the existing HERO_VEHICLE_MODE_GIANT_CLANK case, whose 00209230 resource check and 00209244 charged-blast removal agree. Reuse the supplied canonical HeroVehicleMode member. --- src/overlays/l15/hero/update_hero_motion_for_current_state.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l15/hero/update_hero_motion_for_current_state.c b/src/overlays/l15/hero/update_hero_motion_for_current_state.c index bfc60a00d1..a9dac0b9e6 100644 --- a/src/overlays/l15/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l15/hero/update_hero_motion_for_current_state.c @@ -228,7 +228,7 @@ s32 process_hero_incoming_hit(s32 apply_hit_reaction) { if (incoming_hit_record->p34 != hero_moby) { return 0; } - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { if (!(incoming_hit_record->i24 & 2)) { return 0; } @@ -238,7 +238,7 @@ s32 process_hero_incoming_hit(s32 apply_hit_reaction) { D_0013DF88[current_level_index]++; hero.damage_source_moby = (struct Moby *)incoming_hit_record->p20; D_0015EEA8++; - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { hero.vehicle_hp -= truncate_float_to_s32(incoming_hit_record->f2C); if (hero.vehicle_hp < 0) { hero.vehicle_hp = 0; From 43e1bd041fe83dd435e754b86ee77cdcb5f6dacd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:03:06 +0000 Subject: [PATCH 1218/1502] decomp: clarify names in underwater_ring_update domain_0_value_1 -> UNDERWATER_RING_STATE_READY: Retail 0x002e5ae8..0x002e5b10 clears ring timers/progress, sets black color and stores 1 to this moby's +0x20 state, the same byte selected by the switch at 0x002e5a00. This exits INITIALIZE into the existing READY=1 case. domain_1_value_4 -> UNDERWATER_RING_STATE_COMPLETED: Retail 0x002e5b14..0x002e5b9c tests saved completion and enabled, copies restart_timer to timer, then stores 4 to moby+0x20. That exact switch selector dispatches case 4, which flashes color and writes persistent save bits; reuse existing COMPLETED=4. domain_2_value_1 -> UNDERWATER_RING_STATE_READY: Retail 0x002e5a60 stores this ring as parent at pvars+0x10 and 0x002e5a94..0x002e5ab0 installs it into class-0x4b9 child ring pvars. At 0x002e5bb0..0x002e5bb8 the pointer is loaded and its +0x20 state compared with 1 before starting its timer. This is the same underwater-ring state domain and existing READY=1 member. domain_3_value_2 -> UNDERWATER_RING_STATE_TIMED_CHALLENGE: The parent loaded from ring pvars+0x10 at retail 0x002e5bb0 was established as the initializing ring at 0x002e5a60/0x002e5aa4. Retail 0x002e5bc4..0x002e5be8 stores 2 to that parent's +0x20 state and initializes its timer to 900 or scaled frame_count, entering the existing TIMED_CHALLENGE=2 case. domain_4_value_2 -> UNDERWATER_RING_STATE_TIMED_CHALLENGE: Retail 0x002e5c24..0x002e5c2c compares this moby's +0x20 switch-state byte with 2. The guarded block checks completed-ring counts and decrements the challenge timer, resetting on timeout or entering completion on success. Reuse existing TIMED_CHALLENGE=2 for this same selector. domain_5_value_4 -> UNDERWATER_RING_STATE_COMPLETED: Retail 0x002e5c34..0x002e5c74 accepts child_count >= notified_count, sets group state 4, emits the success cue, copies restart_timer into timer and stores 4 to this moby's +0x20 switch selector. It enters the existing COMPLETED=4 case that flashes and persists save bits. domain_6_value_1 -> UNDERWATER_RING_STATE_READY: Retail RESET case 0x002e5d54..0x002e5d78 sets black color, clears triggered and child_count, and stores 1 to this moby's +0x20 switch-state byte. This restores the existing READY=1 state that accepts the first crossing and starts the parent challenge. --- src/overlays/shared/props/underwater_ring.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/props/underwater_ring.c b/src/overlays/shared/props/underwater_ring.c index 5a7c280f6f..fc1cdbb8ef 100644 --- a/src/overlays/shared/props/underwater_ring.c +++ b/src/overlays/shared/props/underwater_ring.c @@ -90,7 +90,7 @@ void underwater_ring_update(struct Moby *moby) { ring_vars->triggered = 0; ring_vars->flash_timer = 0; set_moby_color(moby, 0, 0, 0); - moby->state = 1; + moby->state = UNDERWATER_RING_STATE_READY; break; case UNDERWATER_RING_STATE_READY: case UNDERWATER_RING_STATE_TIMED_CHALLENGE: @@ -105,16 +105,16 @@ void underwater_ring_update(struct Moby *moby) { if (ring_vars->enabled != 0) { set_moby_list_state(moby->group, 4); ring_vars->timer = ring_vars->restart_timer; - moby->state = 4; + moby->state = UNDERWATER_RING_STATE_COMPLETED; break; } } if (ring_vars->triggered == 0 && near_parent) { struct Moby *parent = ring_vars->parent; VendorVars *parent_vars = (VendorVars *)parent->pvars; - if (parent->state == 1) { + if (parent->state == UNDERWATER_RING_STATE_READY) { ring_vars->child_count = 0; - parent->state = 2; + parent->state = UNDERWATER_RING_STATE_TIMED_CHALLENGE; parent_vars->timer = parent_vars->frame_count < 1 ? 900 : scale_game_frames(ring_vars->frame_count); } @@ -123,12 +123,12 @@ void underwater_ring_update(struct Moby *moby) { set_moby_color(moby, 0, 0xff, 0); ring_vars->triggered = 1; } - if (moby->state == 2) { + if (moby->state == UNDERWATER_RING_STATE_TIMED_CHALLENGE) { if (ring_vars->child_count >= ring_vars->notified_count) { set_moby_list_state(moby->group, 4); allocate_voice_for_target_entry(1, 0x31, moby); ring_vars->timer = ring_vars->restart_timer; - moby->state = 4; + moby->state = UNDERWATER_RING_STATE_COMPLETED; break; } else { if (fast_dec_timer_s16(&ring_vars->timer) != 0) { @@ -157,7 +157,7 @@ void underwater_ring_update(struct Moby *moby) { set_moby_color(moby, 0, 0, 0); ring_vars->child_count = 0; ring_vars->triggered = 0; - moby->state = 1; + moby->state = UNDERWATER_RING_STATE_READY; break; case UNDERWATER_RING_STATE_COMPLETED: { u16 save_id; From 3d8d0995f984b11ee365ed8e04998c173d3be8fa Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:04:47 +0000 Subject: [PATCH 1219/1502] decomp: clarify names in update_screamer_hit_reactions_and_targeting domain_0_value_2 -> TARGET_SELECTION_DEFAULT_TARGET_EXCLUDED: Authoritative C compares ahead_f's return in target_selection_status. Retail 0x002dff24 calls checked helper 0x002527c8, saves v0 in s3 at 0x002dff2c and compares to 2 at 0x002dff30. Helper loads the initial/default target from 0x001413D0 at 0x0025281c; exclusion branches clear s1 at 0x00252830 and set status s5=2 at 0x00252834. Alternative candidate selection sets s1 and s5=1 at 0x002528d0-0x002528d8 or 0x00252954-0x0025295c. If status remains 2, the default is excluded with no replacement: output target is cleared at 0x002529f4, status is stored at output+0x44 and returned at 0x00252a0c-0x00252a10. domain_1_value_2 -> TARGET_SELECTION_DEFAULT_TARGET_EXCLUDED: Retail 0x002e00c8 compares s3 against 2 after returns from unconstrained helper 0x002527c8 or path-constrained helper 0x00252a48 (calls 0x002e0050/0x002e0098). In 0x002527c8 default exclusion clears the initial target and sets 2 at 0x00252830-0x00252834; selecting an alternative changes status to 1. Path helper loads the same initial/default target at 0x00252aa8 and excludes it with status 2 at 0x00252ac4-0x00252ad8, or after constraint rejection at 0x00252b40-0x00252b4c and 0x00252b90-0x00252b98. Alternative selection sets target s8 and status 1 at 0x00252cac-0x00252cb0 or 0x00252dbc-0x00252dc0. Unreplaced excluded default leaves null output at 0x00252e70 and returns 2 via sp+0x10 at 0x00252ea0. Thus both merged helpers share this exclusion status, separate from unrelated hero enums. --- src/overlays/l10/mobys/screamer.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/screamer.c b/src/overlays/l10/mobys/screamer.c index 012d81d1f8..d2a5dbab34 100644 --- a/src/overlays/l10/mobys/screamer.c +++ b/src/overlays/l10/mobys/screamer.c @@ -389,6 +389,9 @@ void update_screamer_hit_reactions_and_targeting(struct Moby *moby) { SCREAMER_STATE_WAIT_FOR_ACTIVATION = 1, SCREAMER_STATE_DEATH_KNOCKBACK = 11 }; + enum { + TARGET_SELECTION_DEFAULT_TARGET_EXCLUDED = 2 + }; MobyData_2DFC38 *screamer_vars = (MobyData_2DFC38 *)moby->pvars; Hit_2DFC38 *hit_record; float relative_offset[4]; @@ -455,7 +458,7 @@ void update_screamer_hit_reactions_and_targeting(struct Moby *moby) { if (screamer_vars->f174 == 2) { target_selection_status = ahead_f(screamer_vars->f180, moby, screamer_vars->fC0); - if (target_selection_status != 2) { + if (target_selection_status != TARGET_SELECTION_DEFAULT_TARGET_EXCLUDED) { LevelCuboid *bp = &l10_cuboids[screamer_vars->f194]; fast_vec_sub(relative_offset, D_0013F3D0, &bp->pos); relative_offset[3] = 0.0f; @@ -476,7 +479,7 @@ void update_screamer_hit_reactions_and_targeting(struct Moby *moby) { } else { target_selection_status = ahead_f(screamer_vars->f180, moby, screamer_vars->fC0); } - if (target_selection_status != 2) { + if (target_selection_status != TARGET_SELECTION_DEFAULT_TARGET_EXCLUDED) { if (screamer_vars->f180 < vector_distance_xy(screamer_vars->f130, screamer_vars->fC0)) screamer_vars->f104 = 2; else if (moby->visible == 0) From 295a48b723e66537ee31c35fc849286e0a9ec928 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:04:47 +0000 Subject: [PATCH 1220/1502] decomp: clarify names in apply_hero_ground_material_effects domain_5_value_13 -> GROUND_MATERIAL_SINK_TRIGGER: The authoritative source snapshots hero.ground_type into saved_ground_type, corroborated by retail lh s2,0x12e0(s1) at 0x00239ff4 before reset. Retail 0x0023a1f0-0x0023a200 compares that material snapshot with 13 and sets hero.selector_13 at offset 0x12ec. Retail 0x0023a2dc-0x0023a36c reads that flag, excludes current state 0x7f (named HERO_STATE_SINK in the supplied source), checks proximity below water_surface_z and negative vertical displacement, then requests 0x7f through hero_set_state at 0x0023a430. Supplied update_hero_ground_contact also obtains ground_type from collision_hit_material and records water_surface_z for material 13. Thus this is a ground-material sink trigger, independently of the equal-valued hero state enum member 13. --- src/overlays/l05/hero/apply_hero_ground_material_effects.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l05/hero/apply_hero_ground_material_effects.c b/src/overlays/l05/hero/apply_hero_ground_material_effects.c index f945af9637..8c103fca1d 100644 --- a/src/overlays/l05/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l05/hero/apply_hero_ground_material_effects.c @@ -25,6 +25,9 @@ void apply_hero_ground_material_effects(void) { GROUND_MATERIAL_MAGNET = 2, GROUND_MATERIAL_FIXED_SHALLOW_WATER = 14 }; + enum { + GROUND_MATERIAL_SINK_TRIGGER = 13 + }; u8 save = hero.ground_sound_class; s16 saved_ground_type = hero.ground_type; f32 water_depth; @@ -72,7 +75,7 @@ void apply_hero_ground_material_effects(void) { hero.unk12E9 = 1; if (saved_ground_type == 4) hero.selector_4 = 1; - if (saved_ground_type == 13) + if (saved_ground_type == GROUND_MATERIAL_SINK_TRIGGER) hero.selector_13 = 1; if (saved_ground_type == 1) hero.selector_1 = 1; From 34b05a7bf38188e51173378102a50c5d0c545f8a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:04:48 +0000 Subject: [PATCH 1221/1502] decomp: clarify names in process_hero_hurt_response domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x00218b30 loads hero+0x20A4 (source hero.vehicle_mode); 0x00218b34-0x00218b44 compares 2 and selects response-record eligibility bit 2. The same hero+0x20A4 selector is loaded at 0x00218cb0 and value 2 dispatches at 0x00218cb4 to the existing HERO_VEHICLE_MODE_GIANT_CLANK branch. That branch tests vehicle_hp and calls remove_giant_clank_charged_blast at 0x00218ee4. This proves the HeroVehicleMode domain and canonical value-2 member, rather than numeric equivalence to HeroStateId or HeroGravityMode. domain_1_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x00218bc0 loads hero+0x20A4 (source hero.vehicle_mode), compares 2 at 0x00218bc4-0x00218bc8, then converts record+0x2C damage and subtracts it from hero+0x1630 (vehicle_hp), clamping at zero at 0x00218bd0-0x00218be8. The same selector/value dispatches at 0x00218cb0-0x00218cb4 into the existing HERO_VEHICLE_MODE_GIANT_CLANK branch, whose HP test and remove_giant_clank_charged_blast call confirm the canonical HeroVehicleMode member applies to this comparison. --- src/overlays/l18/hero/apply_hero_ground_type_effects.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l18/hero/apply_hero_ground_type_effects.c b/src/overlays/l18/hero/apply_hero_ground_type_effects.c index b68f2eb069..0d6dc5733e 100644 --- a/src/overlays/l18/hero/apply_hero_ground_type_effects.c +++ b/src/overlays/l18/hero/apply_hero_ground_type_effects.c @@ -214,7 +214,7 @@ s32 process_hero_hurt_response(s32 apply_hurt_response) { if (response_record->p34 != hero_moby_bytes) { return 0; } - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { if (!(response_record->i24 & 2)) { return 0; } @@ -228,7 +228,7 @@ s32 process_hero_hurt_response(s32 apply_hurt_response) { hero.unk5BE = 1; return 0; } - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { hero.vehicle_hp -= truncate_float_to_s32(response_record->f2C); if (hero.vehicle_hp < 0) { hero.vehicle_hp = 0; From fae249b900c7ff70033c3f187344e1ca0d443f0a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:07:15 +0000 Subject: [PATCH 1222/1502] decomp: clarify names in hero_check_damage domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x00210d88 loads hero+0x20a4 (hero.vehicle_mode), and 0x00210d8c..0x00210d98 compares it to 2 before requiring hit flags bit 2. The identical selector is loaded at 0x00210f08 and dispatched for 2 at 0x00210f2c to the already named HERO_VEHICLE_MODE_GIANT_CLANK branch. Bound enter_hero_vehicle_mode stores mode into hero.vehicle_mode and its canonical Giant Clank case initializes hero.vehicle_hp to 200; this proves the HeroVehicleMode domain, rather than an equal-valued state or gravity constant. domain_1_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x00210e18 loads hero+0x20a4, compares against 2 at 0x00210e1c..0x00210e20, then converts hit damage from hit entry+0x2c and subtracts it from hero+0x1630 at 0x00210e28..0x00210e40 with a zero floor. Authoritative C identifies these fields as hero.vehicle_mode and hero.vehicle_hp. Bound enter_hero_vehicle_mode initializes this HP field to 200 in HERO_VEHICLE_MODE_GIANT_CLANK, and the same selector's named Giant Clank switch branch tests this HP at 0x00211160. Reuse the canonical HeroVehicleMode member from include/rnc/hero/hero_state.h. --- src/overlays/shared/hero/hero_switch_item.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 12cb1955d9..18068ac1e3 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -2493,7 +2493,7 @@ s32 hero_check_damage(s32 apply_damage_response) { if (hero_hit_entry->owner != hero_moby) { return 0; } - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { if (!(hero_hit_entry->flags & 2)) { return 0; } @@ -2507,7 +2507,7 @@ s32 hero_check_damage(s32 apply_damage_response) { hero.unk5BE = 1; return 0; } - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { hero.vehicle_hp -= truncate_float_to_s32(hero_hit_entry->damage); if (hero.vehicle_hp < 0) { hero.vehicle_hp = 0; From 6ee75a748e3f69d5b00e0d9582d8dbba49e34411 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:09:03 +0000 Subject: [PATCH 1223/1502] decomp: clarify names in resolve_moby_hit_response domain_0_value_71 -> FALLBACK_HIT_KIND: Retail 0x00213ac0 loads hit_record+0x2A into s6 (source kind), and 0x00213ac4-0x00213ac8 compares it with 0x47 for vector blending. The same s6 receives 0x47 on the no-target fallback at 0x00213ba0-0x00213bb4; target-present flow instead loads target+0xA6. Thus both occurrences share the hit-kind domain and the name denotes the proven fallback role, not a hero state or attack identity. Original Ghidra uVar11 and authoritative C kind show identical flow. domain_1_value_71 -> FALLBACK_HIT_KIND: Retail 0x00213ba0 reads hit_record+0x20; if null, 0x00213bac-0x00213bb4 sets hit-record state 8 and s6=0x47. If present, 0x00213ba8 loads target+0xA6 into that same s6. The common tail exports s6 at 0x00213cf4-0x00213cfc and records it at 0x00213e1c-0x00213e20. Authoritative C and original Ghidra agree: 0x47 is the fallback hit kind when no target supplies a kind, sharing the domain of the earlier kind comparison. --- src/mobys/resolve_moby_hit_response.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/mobys/resolve_moby_hit_response.c b/src/mobys/resolve_moby_hit_response.c index d7972759a3..05d2f4da10 100644 --- a/src/mobys/resolve_moby_hit_response.c +++ b/src/mobys/resolve_moby_hit_response.c @@ -95,6 +95,9 @@ s32 resolve_moby_hit_response(O_25a478 *hit_recipient_moby, enum { FALLBACK_RESPONSE_HIT_STATE = 8 }; + enum { + FALLBACK_HIT_KIND = 0x47 + }; V_25a478 hit_blend_vector; V_25a478 combined_hit_vector; s32 hit_response_index; @@ -144,7 +147,7 @@ s32 resolve_moby_hit_response(O_25a478 *hit_recipient_moby, hit_vector_scale_table[hit_vector_scale_row][hit_record->state]); kind = hit_record->kind; hit_record->u.s.f1C = 5627.9248f; - if (kind == 0x47) { + if (kind == FALLBACK_HIT_KIND) { hit_blend_vector.f[0] = fast_cos(fast_arc_tan(hit_recipient_moby->x - hero.motion.pos.f[0], hit_recipient_moby->y - hero.motion.pos.f[1])); @@ -162,7 +165,7 @@ s32 resolve_moby_hit_response(O_25a478 *hit_recipient_moby, } else { if (!hit_record->tgt) { hit_record->state = FALLBACK_RESPONSE_HIT_STATE; - kind = 0x47; + kind = FALLBACK_HIT_KIND; } else { kind = hit_record->tgt->hA6; hit_record->state = FALLBACK_RESPONSE_HIT_STATE; From fb035d6db6d3675cb36bb21b2091548b9345cfab Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:09:03 +0000 Subject: [PATCH 1224/1502] decomp: clarify names in update_seeker_damage_and_target domain_0_value_0 -> SEEKER_STATE_INITIALIZE: Retail 0x002c623c preserves the Moby argument in s2; 0x002c6258-0x002c625c tests its state byte at +0x20 for zero and returns. The authoritative source shows seeker_update calling this function on that same moby before switching on moby->state; its existing SEEKER_STATE_INITIALIZE=0 branch initializes pvars and transitions to idle hover. Thus this is the seeker initialization state, not a Hero or response selector. domain_1_value_7 -> SEEKER_STATE_EXPLODE: Retail 0x002c6294-0x002c62ac decrements pvars+0x184 and writes 7 to the same Moby state byte +0x20 when the countdown completes. In the authoritative source, seeker_update calls this routine before its switch(moby->state), whose existing SEEKER_STATE_EXPLODE=7 branch spawns an explosion and removes that Moby. This assignment selects that established seeker state. domain_2_value_6 -> SEEKER_STATE_FATAL_KNOCKBACK: Retail 0x002c6394-0x002c639c compares the recipient Moby state byte +0x20 with 6 to skip further hit processing. The fatal response branch writes that identical field/value at 0x002c65bc-0x002c65c4 after starting knockback and marking the Moby for removal accounting. The same-moby caller seeker_update dispatches existing SEEKER_STATE_FATAL_KNOCKBACK=6, steps motion, then bursts and removes it on collision. domain_3_value_5 -> SEEKER_STATE_HURT_KNOCKBACK: Retail hurt branch 0x002c6444-0x002c64c8 computes attacker-relative impulse and starts knockback on the recipient; 0x002c64d0-0x002c64e0 writes 5 to its state byte +0x20. Authoritative seeker_update calls this routine on the same Moby and dispatches existing SEEKER_STATE_HURT_KNOCKBACK=5, steps motion, preserves height and recovers to timed chase when velocity slows. This is the established seeker state domain. domain_4_value_6 -> SEEKER_STATE_FATAL_KNOCKBACK: Retail 0x002c64f8-0x002c65c8 handles fatal hit response: clears flag 0x1000, sets XY/Z impulse, starts knockback at 0x002c65a4, calls removal accounting at 0x002c65b4, then writes 6 to recipient Moby+0x20 at 0x002c65c4. The authoritative same-moby caller seeker_update names that dispatched state SEEKER_STATE_FATAL_KNOCKBACK=6 and steps motion until burst/removal. Reuse the canonical seeker member for both comparison and assignment. --- src/overlays/shared/enemies/seeker.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/enemies/seeker.c b/src/overlays/shared/enemies/seeker.c index 4054edc43d..d95bced001 100644 --- a/src/overlays/shared/enemies/seeker.c +++ b/src/overlays/shared/enemies/seeker.c @@ -433,6 +433,12 @@ void update_seeker_damage_and_target(Moby *moby) { RESPONSE_REACTION_ONLY = 9, RESPONSE_NO_REACTION = 11 }; + enum { + SEEKER_STATE_INITIALIZE = 0, + SEEKER_STATE_HURT_KNOCKBACK = 5, + SEEKER_STATE_FATAL_KNOCKBACK = 6, + SEEKER_STATE_EXPLODE = 7 + }; char hit_pos[16]; int hit; float damage; @@ -445,13 +451,13 @@ void update_seeker_damage_and_target(Moby *moby) { int lost_state; seeker_vars = (struct Data *)moby->pvars; - if (moby->state == 0) { + if (moby->state == SEEKER_STATE_INITIALIZE) { return; } moby->scale = moby->scale + ((((Cls *)moby->pclass)->scale * D_L09_0016140C) - moby->scale) * 0.1f; if (fast_dec_timer(&seeker_vars->timer) == 2) { - moby->state = 7; + moby->state = SEEKER_STATE_EXPLODE; return; } if (seeker_vars->timer == scale_game_frames(0xA) || @@ -467,7 +473,7 @@ void update_seeker_damage_and_target(Moby *moby) { source = find_moby_hit(moby, 0x330000, 0); response = resolve_moby_hit_response(moby, source, &seeker_vars->health, 0, &hit, &damage, 0, 4); - if (hit != 1 && moby->state != 6) { + if (hit != 1 && moby->state != SEEKER_STATE_FATAL_KNOCKBACK) { seeker_vars->health = seeker_vars->health - damage; if (seeker_vars->health <= 0.0f) { response = 1; @@ -500,7 +506,7 @@ void update_seeker_damage_and_target(Moby *moby) { *(Q_2C73D0 *)hit_pos = source->pos; func_L00_0025BBA0_2C73D0(hit_pos, &knock_angle, &seeker_vars->f88, &seeker_vars->f8C); func_L00_0025D5B0_2C73D0(moby, seeker_vars->f70, knock_angle, 4, 1, 0); - moby->state = 5; + moby->state = SEEKER_STATE_HURT_KNOCKBACK; if (moby->group != 0xFF) { func_L01_0026F040_2C73D0(moby->group, 1); } @@ -521,7 +527,7 @@ void update_seeker_damage_and_target(Moby *moby) { hit_pos, &knock_angle_fatal, &seeker_vars->f88, &seeker_vars->f8C); func_L00_0025D5B0_2C73D0(moby, seeker_vars->f70, knock_angle_fatal, 4, 1, 0); mark_moby_for_removal_cf(moby, 0, -1); - moby->state = 6; + moby->state = SEEKER_STATE_FATAL_KNOCKBACK; seeker_vars->reactTime = 0xF0; break; case RESPONSE_NONE: From 5b1de25de57e8307e96ccb3ae3c4717365f7b12e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:12:06 +0000 Subject: [PATCH 1225/1502] decomp: clarify names in build_interpolated_dma_packet domain_0_value_341514 -> TEXTURED_GRID_BLEND_MODE_ABOVE_ALPHA_LIMIT: Authoritative build_interpolated_dma_packet C initializes blend_mode=0x5360A and replaces it only when !(alpha_limit < draw_parameters->alpha), with alpha_limit=0x60. Retail 0x002a44fc loads caller alpha +0x3f; 0x002a4528/0x002a4530 compare 0x60 against it; 0x002a4544/0x002a4548 construct 0x5360A, and movz at 0x002a4550 retains that value exactly when caller alpha exceeds the limit. Store 0x002a45d0 emits the selected packed state beside register selector 0x47 at 0x002a45d8. Thus this is the existing blend_mode domain's above-alpha-limit packet value, without assuming its full bit-field meaning. domain_1_value_341771 -> TEXTURED_GRID_BLEND_MODE_AT_OR_BELOW_ALPHA_LIMIT: Authoritative C assigns blend_mode=0x5370B inside !(alpha_limit < draw_parameters->alpha), where alpha_limit=0x60. Retail 0x002a4538/0x002a453c constructs 0x5370B in a1; sltu at 0x002a4530 is zero for caller alpha +0x3f <=0x60, and movz a2,a1,a0 at 0x002a4550 then selects this packed value. Retail Ghidra independently expresses bVar3 < 0x61. The selected value reaches packet +0x80 at 0x002a45d0, paired with register selector 0x47. This proves the at-or-below-alpha-limit role in the existing blend_mode domain. --- .../shared/rendering/build_interpolated_dma_packet.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/rendering/build_interpolated_dma_packet.c b/src/overlays/shared/rendering/build_interpolated_dma_packet.c index ffb5adc485..abdacb02d2 100644 --- a/src/overlays/shared/rendering/build_interpolated_dma_packet.c +++ b/src/overlays/shared/rendering/build_interpolated_dma_packet.c @@ -127,6 +127,10 @@ void build_interpolated_dma_packet(QuadDrawArgs *draw_parameters) { enum { TEXTURED_GRID_FOG_SOURCE_CAMERA = 1 }; + enum { + TEXTURED_GRID_BLEND_MODE_ABOVE_ALPHA_LIMIT = 0x5360A, + TEXTURED_GRID_BLEND_MODE_AT_OR_BELOW_ALPHA_LIMIT = 0x5370B + }; float view_matrix[16]; int *view_setup_dma_packet; int *cursor; @@ -226,9 +230,9 @@ void build_interpolated_dma_packet(QuadDrawArgs *draw_parameters) { } words = (long *)PACKET_CURSOR; alpha_limit = 0x60; - blend_mode = 0x5360A; + blend_mode = TEXTURED_GRID_BLEND_MODE_ABOVE_ALPHA_LIMIT; if (!(alpha_limit < draw_parameters->alpha)) { - blend_mode = 0x5370B; + blend_mode = TEXTURED_GRID_BLEND_MODE_AT_OR_BELOW_ALPHA_LIMIT; } words[0] = 0x8000000000008001; words[1] = 0xEEEEEEEE; From 9e413f91dd4d1d08b4b094bfe46a49ae1e6e3c9e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:14:30 +0000 Subject: [PATCH 1226/1502] decomp: clarify names in sentrybot_alarm_update domain_0_value_2 -> SENTRYBOT_ALARM_MODE_GROUP_RELEASE_ONLY: Retail 002cb4f0 loads the alarm moby's pvars from moby+0x78; 002cb510 loads word 0 and 002cb514-002cb538 compares it with 2 and selects state 6 (WAIT_FOR_GROUP_RELEASE_TRIGGER), bypassing state 3's alarm-start route. States 6/7 advance to release state 8 at 002cb838-002cb888; state 8 calls activate_first_inactive_group_moby at 002cb930-002cb938 and expires into state 9 at 002cb974-002cb984. In state 9, 002cb9bc-002cb9dc compares that same pvars word with 2 and returns to state 6, whereas other modes proceed to alarm-stop state 10. This proves a group-release-only control mode, distinct from moby+0x20 state IDs and Hero enums. --- src/overlays/shared/enemies/sentrybot_alarm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/sentrybot_alarm.c b/src/overlays/shared/enemies/sentrybot_alarm.c index cbc4bcb1d5..79ca5d3d0d 100644 --- a/src/overlays/shared/enemies/sentrybot_alarm.c +++ b/src/overlays/shared/enemies/sentrybot_alarm.c @@ -90,7 +90,7 @@ void sentrybot_alarm_update(unsigned char *moby) __asm__("FUN_L15_002cb4c8"); /* Moby class 408 */ void sentrybot_alarm_update(unsigned char *moby) { - enum { SENTRYBOT_ALARM_STATE_INITIALIZE = 0 , SENTRYBOT_ALARM_STATE_STANDBY_PULSE = 1 , SENTRYBOT_ALARM_STATE_STANDBY_RETURN_TRANSITION = 2 , SENTRYBOT_ALARM_STATE_WAIT_FOR_ALARM_TRIGGER = 3 , SENTRYBOT_ALARM_STATE_ALARM_START_TRANSITION = 4 ,SENTRYBOT_ALARM_STATE_ACTIVE_PULSE = 5 , SENTRYBOT_ALARM_STATE_WAIT_FOR_GROUP_RELEASE_TRIGGER = 6 , SENTRYBOT_ALARM_STATE_GROUP_RELEASE_START_TRANSITION = 7 ,SENTRYBOT_ALARM_STATE_RELEASE_GROUP_MOBYS = 8 , SENTRYBOT_ALARM_STATE_GROUP_RELEASE_STOP_TRANSITION = 9 , SENTRYBOT_ALARM_STATE_ALARM_STOP_TRANSITION = 10} ;float position[4]; + enum { SENTRYBOT_ALARM_STATE_INITIALIZE = 0 , SENTRYBOT_ALARM_STATE_STANDBY_PULSE = 1 , SENTRYBOT_ALARM_STATE_STANDBY_RETURN_TRANSITION = 2 , SENTRYBOT_ALARM_STATE_WAIT_FOR_ALARM_TRIGGER = 3 , SENTRYBOT_ALARM_STATE_ALARM_START_TRANSITION = 4 ,SENTRYBOT_ALARM_STATE_ACTIVE_PULSE = 5 , SENTRYBOT_ALARM_STATE_WAIT_FOR_GROUP_RELEASE_TRIGGER = 6 , SENTRYBOT_ALARM_STATE_GROUP_RELEASE_START_TRANSITION = 7 ,SENTRYBOT_ALARM_STATE_RELEASE_GROUP_MOBYS = 8 , SENTRYBOT_ALARM_STATE_GROUP_RELEASE_STOP_TRANSITION = 9 , SENTRYBOT_ALARM_STATE_ALARM_STOP_TRANSITION = 10} ; enum { SENTRYBOT_ALARM_MODE_GROUP_RELEASE_ONLY = 2} ;float position[4]; float step; int color; int mode; @@ -101,7 +101,7 @@ void sentrybot_alarm_update(unsigned char *moby) { l15_sentrybot_alarm_effect_update_stamp = 0; D_L15_00161AB8 = 0; *(int *)&D_L15_00161ABC_gp = 0; - if (mode == 2) { + if (mode == SENTRYBOT_ALARM_MODE_GROUP_RELEASE_ONLY) { MOBY(moby)->state = 6; if (MOBY(moby)->prev_seq != 4) blend_moby_animation(moby, 4, 0, 0); From 90907b2dba48374390de96b31f511d0a3566a414 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:14:30 +0000 Subject: [PATCH 1227/1502] decomp: clarify names in taxi_update domain_0_value_2 -> TAXI_HIDDEN_STOP: Bound source src/overlays/l05/mobys/taxi.c SHA-256 829b66bcd794411320c4d28a2a7114c6077322d89992cc74feb893d3ae852390 and original retail Ghidra agree: 0x00318e00-0x00318e04 looks up the moby at taxi_data+0xB6 destination stop. Retail 0x00318e10-0x00318e2c stores state 2 at returned moby+0x20, sets flags bit 0, clears collision at +0x94 and visibility at +0x31. Lookup retail 0x00319598-0x003195f4 matches returned moby pvars+0xB4 to the requested stop (request 0fcb222ed2934e899e757c5dd8f81f5f). Arrival helper 0x00319520-0x00319578 repeats that destination lookup, copies the departure stop pose into the returned moby and invokes the same taxi initialization helper used by root state 0 (request dc155a2ead914b4f9b11f09027a4cad1). Initialization retail 0x00319320-0x0031933c restores state 1, visibility and collision, or 0x00319300-0x00319318 selects activation-wait state 6 (request 17aab3527ae146eca063f964b9986a36). This shared stop layout and initialization prove the taxi state domain; 2 denotes the hidden stop counterpart during travel, distinct from activation-wait 6 and unrelated hero enum values. --- src/overlays/l05/mobys/taxi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l05/mobys/taxi.c b/src/overlays/l05/mobys/taxi.c index b51fad3a74..4f565e746c 100644 --- a/src/overlays/l05/mobys/taxi.c +++ b/src/overlays/l05/mobys/taxi.c @@ -72,7 +72,7 @@ void taxi_update(struct Moby *moby) { TAXI_FOLLOW_PATH = 4, TAXI_BLEND_TO_DESTINATION = 5, TAXI_WAIT_FOR_ACTIVATION = 6 - }; + } ; enum { TAXI_HIDDEN_STOP = 2}; TaxiVars *taxi_data = (TaxiVars *)moby->pvars; float old_position[4], old_rotation[4], position_delta[4], rotation_or_start_position_scratch[4], interpolation_end_position[4], @@ -109,7 +109,7 @@ void taxi_update(struct Moby *moby) { moby->state = TAXI_BLEND_TO_PATH_START; destination_stop_moby = find_moby_in_owner_list_by_id(moby, taxi_data->unkB6); if (destination_stop_moby != 0) { - destination_stop_moby->state = 2; + destination_stop_moby->state = TAXI_HIDDEN_STOP; destination_stop_moby->flags |= 1; destination_stop_moby->visible = 0; destination_stop_moby->collision = 0; From f10020e95a53221146261eb999e025302ad744b7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:14:30 +0000 Subject: [PATCH 1228/1502] decomp: clarify names in update_puffoid_damage_and_path_goal domain_0_value_1 -> HIT_PROCESSING_SKIP_DAMAGE_AND_REACTION: Retail 00315b00 passes sp+10 as the fifth output of resolve_moby_hit_response at 00315b0c; 00315b14-00315b1c loads it and branches on status 1 to 00315d88, bypassing HP subtraction 00315b34-00315b40 and reaction dispatch/animation update through 00315d80. Checked level-11 helper evidence 613f33146b2f4e86a7380b86d922f52e saves that output pointer in s3 at 00280368. Absent-hit path 00280468-002804a0 writes status 1 at 0028048c and zero damage output, while suppression path 0028082c-00280838 writes status 1 and zeroes hit damage. Returned response is separately held in s1 and returned at 002808a0. Thus the constant names the status that skips this caller's damage/reaction handling, not HIT_RESPONSE_DEATH or a state ID. --- src/overlays/l11/mobys/puffoid.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l11/mobys/puffoid.c b/src/overlays/l11/mobys/puffoid.c index e8521c6072..a778840a14 100644 --- a/src/overlays/l11/mobys/puffoid.c +++ b/src/overlays/l11/mobys/puffoid.c @@ -766,6 +766,9 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { PUFFOID_STATE_CARRIER_KNOCKBACK = 0x11, PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK = 0x12 }; + enum { + HIT_PROCESSING_SKIP_DAMAGE_AND_REACTION = 1 + }; struct L11PatrolVars *patrol_vars = (struct L11PatrolVars *)moby->pvars; Vec4 position_scratch; s32 hit_processing_status; @@ -800,7 +803,7 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { { s32 kind = resolve_moby_hit_response( moby, hit, &patrol_vars->hp, 0, &hit_processing_status, &dmg, 0, 4); - if (hit_processing_status != 1 && moby->state != PUFFOID_STATE_DEATH_KNOCKBACK) { + if (hit_processing_status != HIT_PROCESSING_SKIP_DAMAGE_AND_REACTION && moby->state != PUFFOID_STATE_DEATH_KNOCKBACK) { patrol_vars->hp -= dmg; if (hit->moby->oclass == 0x47) { kind = HIT_RESPONSE_KNOCKBACK; From 2f937d93b2f71ebae88ceb9af17bb1c33032cbb7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:16:59 +0000 Subject: [PATCH 1229/1502] decomp: clarify names in the_plumber_update domain_0_value_7 -> PLUMBER_FALLBACK_DIALOGUE_INITIALIZED: The selector is the plumber moby's state byte at +0x20, loaded at retail 0x002ff1a0. Initialization compares current_level_index with 1 and 8 (0x002ff1dc-0x002ff220); the remaining branch loads state 7 and fallback dialogue table 0x00161d48 (0x002ff220-0x002ff224), stores the table at pvars+0x20 and state at moby+0x20 (0x002ff228-0x002ff22c), then calls initialize_npc_dialogue with that moby/pvars (0x002ff230-0x002ff238). On later updates the unsigned state<7 dispatch guard at 0x002ff1a4-0x002ff1a8 sends 7 directly to common tracking at 0x002ff3d0, with no scripted dialogue handler. The bound source's plumber_fallback_dialogue_data selection and initialize_npc_dialogue call agree with the original retail decompilation and instructions. This is the same local plumber-state domain as PLUMBER_INITIALIZE, not any HERO_STATE or cutscene-mode domain. --- src/overlays/shared/cutscenes/the_plumber.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/cutscenes/the_plumber.c b/src/overlays/shared/cutscenes/the_plumber.c index bce8d998a5..36476aa44f 100644 --- a/src/overlays/shared/cutscenes/the_plumber.c +++ b/src/overlays/shared/cutscenes/the_plumber.c @@ -151,6 +151,9 @@ void the_plumber_update(L01WatchMoby *plumber_moby) { PLUMBER_LEVEL_EIGHT_POST_DIALOGUE = 5, PLUMBER_LEVEL_EIGHT_DIALOGUE_FINISHED = 6 }; + enum { + PLUMBER_FALLBACK_DIALOGUE_INITIALIZED = 7 + }; L01WatchScratch look_tracking_vectors; L01WatchData *plumber_vars = (L01WatchData *)plumber_moby->data; float rate; @@ -181,7 +184,7 @@ void the_plumber_update(L01WatchMoby *plumber_moby) { plumber_moby->state = PLUMBER_LEVEL_EIGHT_DIALOGUE; } else { plumber_vars->p20 = (void *)plumber_fallback_dialogue_data; - plumber_moby->state = 7; + plumber_moby->state = PLUMBER_FALLBACK_DIALOGUE_INITIALIZED; } initialize_npc_dialogue(plumber_moby, plumber_vars); break; From dbd4aeddf3e4dba3f757d4a1eb6a5d7991260a8f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:18:55 +0000 Subject: [PATCH 1230/1502] decomp: clarify names in homing_mine_update domain_0_value_1 -> HOMING_MINE_WAIT_FOR_PROXIMITY: Retail 0x0031920c-0x00319214 writes 1 to 0x20(s2), the same moby state byte dispatched at 0x003191c4-0x003191e4. After home/collision initialization this enters case 1 at 0x00319220, which tests target XY/Z or sight proximity at 0x00319250-0x003192d8. This proves reuse of local HOMING_MINE_WAIT_FOR_PROXIMITY = 1. domain_1_value_3 -> HOMING_MINE_CHASE: Retail 0x00319308-0x0031930c writes 3 to 0x20(s2) after proximity activation resets speed, timeout and bob timer. The identical byte is the switch selector at 0x003191c4; its case 3 at 0x00319358 accelerates and moves toward sight at 0x003193a4-0x003194ac. Reuse existing HOMING_MINE_CHASE = 3 even though this intermediate assignment is followed by state 2. domain_2_value_2 -> HOMING_MINE_START_CHASE: Retail 0x00319318 and 0x00319324 load 2, stored at 0x0031932c to 0x20(s2), exactly the mine state selector read at 0x003191c4. Its case 2 at 0x00319330-0x00319354 selects animation sequence 1 then enters state 3 and falls into chase movement. This proves the existing local HOMING_MINE_START_CHASE = 2 applies. domain_3_value_3 -> HOMING_MINE_CHASE: Retail case 2 selects sequence 1 at 0x00319330-0x0031934c, then 0x00319350-0x00319354 writes 3 to 0x20(s2), the same byte dispatched by this function's switch. Execution falls directly into case 3 acceleration, bobbing and sight-directed displacement at 0x00319358-0x003194ac. Reuse existing HOMING_MINE_CHASE = 3. --- src/overlays/l07/mobys/homing_mine.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l07/mobys/homing_mine.c b/src/overlays/l07/mobys/homing_mine.c index 6b4898c9e2..0390f9b5c8 100644 --- a/src/overlays/l07/mobys/homing_mine.c +++ b/src/overlays/l07/mobys/homing_mine.c @@ -174,7 +174,7 @@ void homing_mine_update(struct Moby *moby) { moby->flags |= 0x1000; qcopy(&homing_mine_vars->home, &moby->pos); moby->collision = moby->pclass->collision; - moby->state = 1; + moby->state = HOMING_MINE_WAIT_FOR_PROXIMITY; break; case HOMING_MINE_WAIT_FOR_PROXIMITY: timer = scale_game_frames(600); @@ -189,16 +189,16 @@ void homing_mine_update(struct Moby *moby) { homing_mine_vars->timeout = scale_game_frames(600); moby->command = 1; homing_mine_vars->bob_timer = scale_game_frames(7); - moby->state = 3; + moby->state = HOMING_MINE_CHASE; if (homing_mine_vars->sound != -1) set_moby_list_state(homing_mine_vars->sound, 2); - moby->state = 2; + moby->state = HOMING_MINE_START_CHASE; } break; case HOMING_MINE_START_CHASE: if (moby->prev_seq != 1) FUN_00212f90(moby, 1, 0, 10); - moby->state = 3; + moby->state = HOMING_MINE_CHASE; case HOMING_MINE_CHASE: if ((moby->anim_flags & 2) && moby->seq == 1 && moby->prev_seq != 2) { FUN_00212f90(moby, 2, 0, 10); From 016daa4da6199167b0131db056c68388ee372f7d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:18:55 +0000 Subject: [PATCH 1231/1502] decomp: clarify names in door_update domain_0_value_1 -> DOOR_STATE_WAIT_AT_ORIGIN: Retail 002e8898-002e88a4 saves moby position into pvars origin and loads v1=1; 002e8de4 stores it to s1+0x20, the switch selector read at 002e8830. This is the existing local DOOR_STATE_WAIT_AT_ORIGIN case, whose 002e8a1c clears displacement to zero. domain_1_value_4 -> DOOR_STATE_WAIT_DISPLACED: Retail 002e89a4-002e89c0 tests absolute pvars+0x14 displacement against 2.0; after voice cleanup, 002e8a0c loads v1=4 and 002e8de4 stores the door state byte. Existing DOOR_STATE_WAIT_DISPLACED handles that same selector and holds position while clip-volume conditions remain. domain_2_value_2 -> DOOR_STATE_MOVE_AWAY_FROM_ORIGIN: The WAIT_AT_ORIGIN branch tests clip volumes at 002e8a94-002e8acc and reaches 002e8c90-002e8c94 to store 2 into s1+0x20. This directly selects existing DOOR_STATE_MOVE_AWAY_FROM_ORIGIN, whose 002e88dc-002e8904 adds the signed frame-time step to displacement. domain_3_value_5 -> DOOR_STATE_RETURN_TO_ORIGIN: Retail WAIT_DISPLACED branch 002e8b60-002e8bac waits for clip-volume tests to clear, then 002e8bec-002e8bf4 stores 5 at s1+0x20. Existing DOOR_STATE_RETURN_TO_ORIGIN uses this same selector and reduces displacement toward zero at 002e8c98-002e8ce4. domain_4_value_2 -> DOOR_STATE_MOVE_AWAY_FROM_ORIGIN: During RETURN_TO_ORIGIN, retail clip-volume hits at 002e8c34-002e8c84 branch to 002e8c90-002e8c94, storing 2 into the same s1+0x20 state selector. This resumes existing DOOR_STATE_MOVE_AWAY_FROM_ORIGIN and its signed outward displacement addition at 002e8900-002e8904. domain_5_value_1 -> DOOR_STATE_WAIT_AT_ORIGIN: Retail 002e8d88-002e8d94 checks pvars+0x14 displacement equals zero after reconstructing origin-plus-offset position. Following voice cleanup, 002e8ddc loads v1=1 and 002e8de4 stores the door state byte, selecting existing DOOR_STATE_WAIT_AT_ORIGIN. --- src/overlays/l17/mobys/door.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l17/mobys/door.c b/src/overlays/l17/mobys/door.c index 1f38b466ba..f8c1617e8e 100644 --- a/src/overlays/l17/mobys/door.c +++ b/src/overlays/l17/mobys/door.c @@ -78,7 +78,7 @@ void door_update(struct Moby *door_moby) { door_moby->command = 1; } *(OvlQuad *)door_vars = *(OvlQuad *)&door_moby->pos; - door_moby->state = 1; + door_moby->state = DOOR_STATE_WAIT_AT_ORIGIN; break; case DOOR_STATE_MOVE_AWAY_FROM_ORIGIN: if (door_moby->pclass->sound_defs != 0 && @@ -114,7 +114,7 @@ void door_update(struct Moby *door_moby) { } } (*(int *)(door_vars + ((0x20)))) = -1; - door_moby->state = 4; + door_moby->state = DOOR_STATE_WAIT_DISPLACED; } break; case DOOR_STATE_WAIT_AT_ORIGIN: @@ -143,7 +143,7 @@ void door_update(struct Moby *door_moby) { (*(int *)(door_vars + ((0x20)))) = allocate_voice_for_target_entry(0, 4, (int)door_moby); } - door_moby->state = 2; + door_moby->state = DOOR_STATE_MOVE_AWAY_FROM_ORIGIN; } break; case 3: @@ -172,7 +172,7 @@ void door_update(struct Moby *door_moby) { (*(int *)(door_vars + ((0x20)))) = allocate_voice_for_target_entry(0, 4, (int)door_moby); } - door_moby->state = 5; + door_moby->state = DOOR_STATE_RETURN_TO_ORIGIN; break; case DOOR_STATE_RETURN_TO_ORIGIN: if (door_moby->pclass->sound_defs != 0 && @@ -186,7 +186,7 @@ void door_update(struct Moby *door_moby) { is_point_inside_clip_volume(D_L17_0015FFD8 + (*(int *)(door_vars + ((0x10)))) * 0x100 + 0x10, (*(int *)(door_vars + ((0x18))))))) { - door_moby->state = 2; + door_moby->state = DOOR_STATE_MOVE_AWAY_FROM_ORIGIN; break; } displacement_sample = absolute_float((*(float *)(door_vars + ((0x14))))); @@ -227,7 +227,7 @@ void door_update(struct Moby *door_moby) { } } (*(int *)(door_vars + ((0x20)))) = -1; - door_moby->state = 1; + door_moby->state = DOOR_STATE_WAIT_AT_ORIGIN; } break; } From 5450fb60f35b3572c57b4cb23deace7354d5abe8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:18:56 +0000 Subject: [PATCH 1232/1502] decomp: clarify names in pool_splash domain_0_value_0 -> POOL_SPLASH_KEEP_GREATER_MAGNITUDE: In the SHA-256-bound source src/overlays/shared/vendor/draw_vendor_purchase_text.c (d4fd8e734492edd975739bd0b0c7fe5ffa5fd1bf8e1bb4c73c4465e253f6677b), mode == 0 compares absolute_float(height) against the write-bank cell and retains the existing signed height only when its magnitude is greater. Retail saves a2 at 0x002a3f3c, reloads it at 0x002a40ec, and branches on nonzero at 0x002a40f0 to the alternate-bank addition at 0x002a41a4-0x002a41cc. The zero path calls the absolute-value helper at 0x002a412c and 0x002a4150, compares at 0x002a4158, and selects the existing signed cell at 0x002a41a0 before the common store at 0x002a41ec. Original Ghidra param_7 == 0 shows the same operation. Supplied hero_set_state water-surface-entry and hero_update_movement splash callers pass 0 as this third argument, tying the selector to pool splash combination behavior rather than hero state. Thus the constant names the proven greater-magnitude selection operation. --- src/overlays/shared/vendor/draw_vendor_purchase_text.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/vendor/draw_vendor_purchase_text.c b/src/overlays/shared/vendor/draw_vendor_purchase_text.c index 15e348258a..82872c2a3b 100644 --- a/src/overlays/shared/vendor/draw_vendor_purchase_text.c +++ b/src/overlays/shared/vendor/draw_vendor_purchase_text.c @@ -147,6 +147,9 @@ void pool_splash(HeightTile *tile, void pool_splash( HeightTile *tile, int count, int mode, float x, float z, float radius, float amount) { + enum { + POOL_SPLASH_KEEP_GREATER_MAGNITUDE = 0 + }; HeightTile *tiles = tile; int row; int i; @@ -186,7 +189,7 @@ void pool_splash( } else { height = amount / square_root(dist_sq); } - if (mode == 0) { + if (mode == POOL_SPLASH_KEEP_GREATER_MAGNITUDE) { float magnitude = absolute_float(height); if (magnitude < absolute_float(tile->heights[l00_pool_height_write_bank_index][row][col])) { height = tile->heights[l00_pool_height_write_bank_index][row][col]; From 1b3a9753c2f7862aa53381f97e9d77c0b014861a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:18:56 +0000 Subject: [PATCH 1233/1502] decomp: clarify names in update_seeker_damage_and_target domain_0_value_2 -> SEEKER_TARGET_STATUS_LOST: Retail 0x002c6670/0x002c667c calls target selection and loads status 2; 0x002c66c4 compares the return with it. Checked helper 0x0027f7d8-0x0027f7dc clears the default target and sets 2; accepted candidates set 1 at 0x0027f878-0x0027f880, and 0x0027f9b4-0x0027f9b8 stores/returns status. Assigned 0x002c675c-0x002c6764 clears an invalid target and sets the same pvars+0x164 status; seeker_update does not begin chase while status is 2. domain_1_value_2 -> SEEKER_TARGET_STATUS_LOST: Retail 0x002c66b4 loads 2 for the path-constrained target query at 0x002c66bc, compared at 0x002c66c4. Checked helper 0x0027fa6c-0x0027fa80 clears the target and sets status 2, as do failed constraints at 0x0027faf0-0x0027fb40; accepted targets replace status with 1 at 0x0027fc54-0x0027fc5c. 0x0027fe40-0x0027fe48 stores/returns status at goal+0x44, corresponding to pvars+0x164. Assigned range/height failures store that same lost status at 0x002c66f4/0x002c6728. --- src/overlays/shared/enemies/seeker.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/seeker.c b/src/overlays/shared/enemies/seeker.c index d95bced001..7d5e59a7bc 100644 --- a/src/overlays/shared/enemies/seeker.c +++ b/src/overlays/shared/enemies/seeker.c @@ -439,6 +439,9 @@ void update_seeker_damage_and_target(Moby *moby) { SEEKER_STATE_FATAL_KNOCKBACK = 6, SEEKER_STATE_EXPLODE = 7 }; + enum { + SEEKER_TARGET_STATUS_LOST = 2 + }; char hit_pos[16]; int hit; float damage; @@ -552,7 +555,7 @@ void update_seeker_damage_and_target(Moby *moby) { seeker_vars->reach = 24.0f; goal = seeker_vars->target; target_selection_status = func_L00_00260D30_2C73D0(moby, goal, 24.0f); - lost_state = 2; + lost_state = SEEKER_TARGET_STATUS_LOST; } else { Path *path; seeker_vars->reach = 12.0f; @@ -560,7 +563,7 @@ void update_seeker_damage_and_target(Moby *moby) { goal = seeker_vars->target; target_selection_status = activate_effect_l08(moby, goal, 12.0f, 0, 0, path->pts, path->count); - lost_state = 2; + lost_state = SEEKER_TARGET_STATUS_LOST; } if (target_selection_status != lost_state && seeker_vars->retreat == 0) { if (seeker_vars->reach < vector_distance_xy(&moby->pos, goal)) { From b611aed4bc906eb08c7db34b76bccc19052695bf Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:18:56 +0000 Subject: [PATCH 1234/1502] decomp: clarify names in teleporter_update domain_1_value_0 -> HERO_TARGET_POSE_INACTIVE: Source binds teleport_transition_status to get_hero_target_pose_status; retail 0x002f27bc calls level-11 0x0025a968 and 0x002f27e0 preserves its return for comparison at 0x002f2894. Bounded helper instructions 0x0025a96c-0x0025a9ac return 1 for hero states 0x65/0x66, 2 for 0x67, and 0 outside that range. Supplied request_hero_target_pose source checks exactly the 0x65..0x67 group and enters 0x65 when outside it, establishing the target-pose activity group. Thus zero means target pose inactive, and the consumer enters TELEPORTER_RESET. This is a helper return status, not any shared state/mode enum. --- src/overlays/l11/mobys/teleporter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l11/mobys/teleporter.c b/src/overlays/l11/mobys/teleporter.c index e34071655e..a644ea099d 100644 --- a/src/overlays/l11/mobys/teleporter.c +++ b/src/overlays/l11/mobys/teleporter.c @@ -71,7 +71,7 @@ void teleporter_update(struct Moby *moby) { TELEPORTER_OPEN_PARTS = 2, TELEPORTER_CONTRACT_RING = 3, TELEPORTER_RESET = 4 - }; + } ; enum { HERO_TARGET_POSE_INACTIVE = 0}; TeleporterVars *teleporter_instance_vars = (TeleporterVars *)moby->pvars; switch (moby->state) { @@ -153,7 +153,7 @@ void teleporter_update(struct Moby *moby) { if (teleport_transition_status == 2) { teleporter_instance_vars->unk3C = 1.95f; moby->state = TELEPORTER_CONTRACT_RING; - } else if (teleport_transition_status == 0) { + } else if (teleport_transition_status == HERO_TARGET_POSE_INACTIVE) { moby->state = TELEPORTER_RESET; } } From 5f226cb4d46d6d9a60709eb4b387625a54c2523d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:20:37 +0000 Subject: [PATCH 1235/1502] decomp: clarify names in bolt_thief_update domain_0_value_2 -> BOLT_THIEF_MODE_FACE_HERO_FROM_START: Retail 0x002fe458 loads mode from moby-owned data+0xFC; equality to 2 at 0x002fe460 enters FACE_HERO directly (state byte+0x20 set to 1 at 0x002fe470), resets turn and selects animation 4, bypassing path/trigger initialization. FACE_HERO at 0x002fe58c-0x002fe5d4 turns toward hero XY. This is a mode selector, not the state enum. domain_1_value_1 -> BOLT_THIEF_MODE_PRIMARY_PATH_THEN_FACE_HERO: Retail 0x002fe4e4 tests the same data+0xFC mode loaded at 0x002fe458: value 1 skips secondary-path (+0xDC) validation, while still validating primary path and trigger. At 0x002fe760-0x002fe780 the same mode 1 ends primary endpoint settling by entering FACE_HERO instead of secondary-path traversal. Authoritative initialize_moby_path_state likewise skips secondary path setup for mode 1. domain_2_value_1 -> BOLT_THIEF_MODE_PRIMARY_PATH_THEN_FACE_HERO: Retail 0x002fe5f8-0x002fe63c compares data+0xFC with 1 after the hero enters the trigger: mode 1 starts animation 0 and skips child spawning, then joins state FOLLOW_PRIMARY_PATH at 0x002fe658. At primary endpoint completion 0x002fe760-0x002fe780 mode 1 switches to FACE_HERO; it is the same mode as the secondary-path-validation exemption. domain_3_value_0 -> BOLT_THIEF_MODE_PATH_LOOP_WITH_LINKED_CHILD: Retail 0x002fe664-0x002fe674 tests data+0xFC == 0 and invokes update_linked_moby_position during FOLLOW_PRIMARY_PATH. The trigger branch spawns a child into data+0xF4 at 0x002fe61c-0x002fe62c for non-1 modes. Checked helper 0x002fec38-0x002fec88 reads that same child and supplies child+0x10 as the position destination. Mode 0 then takes the non-1 endpoint branch into FOLLOW_SECONDARY_PATH and resets to trigger waiting after that path. domain_4_value_0 -> BOLT_THIEF_MODE_PATH_LOOP_WITH_LINKED_CHILD: Retail 0x002fe6a8 reloads the same moby+0x78 data pointer into s0; 0x002fe6b8-0x002fe6d0 tests its +0xFC mode == 0 and updates the linked child while settling at the primary path endpoint. This matches mode 0 in FOLLOW_PRIMARY_PATH. Checked helper 0x002fec38-0x002fec88 reads data+0xF4 and updates child+0x10; the non-1 endpoint branch releases the child and enters secondary-path traversal, which resets the loop. domain_5_value_1 -> BOLT_THIEF_MODE_PRIMARY_PATH_THEN_FACE_HERO: Retail 0x002fe760-0x002fe780 reads settle_data+0xFC from the moby-owned data pointer reloaded at 0x002fe6a8. Value 1 enters FACE_HERO and resets turn after primary endpoint settling; other values enter FOLLOW_SECONDARY_PATH. This is the same mode 1 that skips secondary-path validation at 0x002fe4e4 and child spawning at 0x002fe5fc, proving primary-path-then-facing behavior. --- src/overlays/l14/mobys/bolt_thief.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/overlays/l14/mobys/bolt_thief.c b/src/overlays/l14/mobys/bolt_thief.c index a1b312cf83..590c8a95cf 100644 --- a/src/overlays/l14/mobys/bolt_thief.c +++ b/src/overlays/l14/mobys/bolt_thief.c @@ -125,6 +125,11 @@ void bolt_thief_update(L16CrateMoby *moby) { BOLT_THIEF_STATE_FOLLOW_SECONDARY_PATH = 5, BOLT_THIEF_STATE_KNOCKBACK = 6 }; + enum { + BOLT_THIEF_MODE_PATH_LOOP_WITH_LINKED_CHILD = 0, + BOLT_THIEF_MODE_PRIMARY_PATH_THEN_FACE_HERO = 1, + BOLT_THIEF_MODE_FACE_HERO_FROM_START = 2 + }; L16CrateData *moby_data = moby->data; char *hit; @@ -156,7 +161,7 @@ void bolt_thief_update(L16CrateMoby *moby) { moby->opacity = 0xFF; switch (moby->state) { case BOLT_THIEF_STATE_INITIALIZE: - if (moby_data->mode == 2) { + if (moby_data->mode == BOLT_THIEF_MODE_FACE_HERO_FROM_START) { moby->state = BOLT_THIEF_STATE_FACE_HERO; moby_data->turn = 0.0f; set_moby_animation(moby, 4, 0); @@ -171,7 +176,7 @@ void bolt_thief_update(L16CrateMoby *moby) { mark_moby_for_removal(moby); return; } - if (moby_data->mode != 1) { + if (moby_data->mode != BOLT_THIEF_MODE_PRIMARY_PATH_THEN_FACE_HERO) { if (moby_data->other_path == -1) { debug_print(D_L14_001FCFA0, moby->id); mark_moby_for_removal(moby); @@ -211,7 +216,7 @@ void bolt_thief_update(L16CrateMoby *moby) { } case BOLT_THIEF_STATE_WAIT_FOR_TRIGGER: if (is_point_inside_clip_volume(&hero.motion.pos, moby_data->trigger)) { - if (moby_data->mode == 1) { + if (moby_data->mode == BOLT_THIEF_MODE_PRIMARY_PATH_THEN_FACE_HERO) { set_moby_animation(moby, 0, 0); } else { moby_data->child = spawn_bolt_thief_mine(moby, moby->position); @@ -224,7 +229,7 @@ void bolt_thief_update(L16CrateMoby *moby) { } break; case BOLT_THIEF_STATE_FOLLOW_PRIMARY_PATH: - if (moby_data->mode == 0) + if (moby_data->mode == BOLT_THIEF_MODE_PATH_LOOP_WITH_LINKED_CHILD) update_linked_moby_position(moby); if (update_bolt_thief_path_movement((char *)moby)) { moby->state = BOLT_THIEF_STATE_SETTLE_AT_PATH_END; @@ -238,7 +243,7 @@ void bolt_thief_update(L16CrateMoby *moby) { float target[4]; float zero; - if (settle_data->mode == 0) + if (settle_data->mode == BOLT_THIEF_MODE_PATH_LOOP_WITH_LINKED_CHILD) update_linked_moby_position(moby); qcopy(target, path + *(int *)path * 16); zero = 0.0f; @@ -261,7 +266,7 @@ void bolt_thief_update(L16CrateMoby *moby) { bolt_thief_path_spring_damping_gp, zero); if ((moby->status & 2) && moby->frame == moby->animation) { - if (settle_data->mode == 1) { + if (settle_data->mode == BOLT_THIEF_MODE_PRIMARY_PATH_THEN_FACE_HERO) { moby->state = BOLT_THIEF_STATE_FACE_HERO; settle_data->turn = zero; set_moby_animation(moby, 4, 0); From f24dc56fe715d72c418aa4ae1ea2d40e15e12b0f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:20:37 +0000 Subject: [PATCH 1236/1502] decomp: clarify names in update_blarg_space_commando_damage_targeting_and_ground_motion domain_0_value_1 -> HIT_STATUS_SKIP_DAMAGE_PROCESSING: Retail 0x00308dc0 passes sp+0x30 as hit-status output; 0x00308dd8..0x00308de0 skips health/reaction processing when it equals 1. Checked helper request 13264e6d0bca45bfad34ba0d34d42f8a maps t0 to s3 at 0x00266510; 0x00266630..0x00266640 sets output 1 and zero damage for no hit, and 0x002669d4..0x002669e0 sets output 1 while clearing disallowed damage. This is hit status, not the equal-valued death result. domain_1_value_16 -> BLARG_SPACE_COMMANDO_DYING: Retail 0x00308de8..0x00308df0 loads moby+0x20 and suppresses damage processing for state 16. Checked caller c91bfc7ff5b94003b7eeefd610bdd9f5 calls this function on the same a0 moby at 0x00307ec8 then dispatches that same byte at 0x00307f30..0x00307f50. Authoritative source names this selector's state 16 BLARG_SPACE_COMMANDO_DYING, whose motion branch explodes and removes the moby. domain_2_value_15 -> BLARG_SPACE_COMMANDO_KNOCKBACK: Retail 0x00308e7c..0x00308e84 stores 15 into the same moby+0x20 state byte consumed by checked caller 0x00307ec8 and 0x00307f30..0x00307f50. The branch sets a scaled 60-frame stun timer and animation-7 knockback at 0x00308e88..0x00308efc. Authoritative caller source names state 15 BLARG_SPACE_COMMANDO_KNOCKBACK and steps velocity until recovery or removal. domain_3_value_16 -> BLARG_SPACE_COMMANDO_DYING: Retail 0x00308f00..0x00308f08 stores 16 to moby+0x20 following hit results 1/2, clears flag 0x1000 and starts animation-8 knockback. Checked caller c91bfc7ff5b94003b7eeefd610bdd9f5 invokes this routine at 0x00307ec8 before dispatching the same moby state. Authoritative source names state 16 BLARG_SPACE_COMMANDO_DYING, with subsequent motion, explosion and removal. domain_6_value_15 -> BLARG_SPACE_COMMANDO_KNOCKBACK: Retail 0x0030919c..0x003091a4 compares the same moby+0x20 state byte unsigned against 15 before slope push and ordinary gravity/height correction. Checked caller at 0x00307ec8 passes this same moby and dispatches its state at 0x00307f30. Source's canonical BLARG_SPACE_COMMANDO_KNOCKBACK=15 begins dedicated step_moby_motion handling; the comparison excludes that and later states from ordinary ground motion. domain_7_value_15 -> BLARG_SPACE_COMMANDO_KNOCKBACK: Retail 0x003090d0 loads moby+0x20 on the no-ground path and 0x00309288..0x0030928c compares it unsigned against 15 before applying gravity. This is the same state consumed by checked caller 0x00307f30 after its call at 0x00307ec8. Authoritative source calls state 15 BLARG_SPACE_COMMANDO_KNOCKBACK and gives that state dedicated motion processing, proving the threshold domain. --- src/overlays/l13/mobys/blarg_space_commando.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/overlays/l13/mobys/blarg_space_commando.c b/src/overlays/l13/mobys/blarg_space_commando.c index a95d642bd7..37b04358b8 100644 --- a/src/overlays/l13/mobys/blarg_space_commando.c +++ b/src/overlays/l13/mobys/blarg_space_commando.c @@ -609,6 +609,11 @@ void update_blarg_space_commando_damage_targeting_and_ground_motion(struct Moby GROUND_MATERIAL_KILLS_WALKER_WITH_EXPLOSION = 11, GROUND_MATERIAL_EXPLODES_WALKER = 13 }; + enum { + HIT_STATUS_SKIP_DAMAGE_PROCESSING = 1, + BLARG_SPACE_COMMANDO_KNOCKBACK = 0xF, + BLARG_SPACE_COMMANDO_DYING = 0x10 + }; struct WalkerVars_8d10 *blarg_space_commando_private_data = (struct WalkerVars_8d10 *)moby->pvars; char *hit; @@ -631,7 +636,7 @@ void update_blarg_space_commando_damage_targeting_and_ground_motion(struct Moby hit = find_moby_hit(moby, 0x330000, 0); code = resolve_moby_hit_response( moby, hit, &blarg_space_commando_private_data->health, 0, &kind, &damage, 0, 4); - if (kind != 1 && moby->state != 0x10) { + if (kind != HIT_STATUS_SKIP_DAMAGE_PROCESSING && moby->state != BLARG_SPACE_COMMANDO_DYING) { if (hit != 0 && *(struct Moby **)(hit + 0x20) != 0 && (*(struct Moby **)(hit + 0x20))->oclass == 0x4EE) { damage = 0.0f; @@ -654,7 +659,7 @@ void update_blarg_space_commando_damage_targeting_and_ground_motion(struct Moby case 8: case 9: case 10: - moby->state = 0xF; + moby->state = BLARG_SPACE_COMMANDO_KNOCKBACK; blarg_space_commando_private_data->stun_timer = scale_game_frames(0x3C); blarg_space_commando_private_data->knock_up = blarg_space_commando_stun_horizontal_knockback_speed * frame_time; @@ -672,7 +677,7 @@ void update_blarg_space_commando_damage_targeting_and_ground_motion(struct Moby break; case HIT_RESULT_DEATH: case HIT_RESULT_DYING_KNOCKBACK: - moby->state = 0x10; + moby->state = BLARG_SPACE_COMMANDO_DYING; moby->flags &= ~0x1000; blarg_space_commando_private_data->knock_up = blarg_space_commando_dying_horizontal_knockback_speed * frame_time; @@ -756,7 +761,7 @@ void update_blarg_space_commando_damage_targeting_and_ground_motion(struct Moby mark_moby_for_removal(moby); return; default: - if (moby->state < 0xF) { + if (moby->state < BLARG_SPACE_COMMANDO_KNOCKBACK) { if (fast_arc_tan(coll_hit_1638.normal_z, vector_length_xy(&coll_hit_1638.normal_x)) > 0.6981317f) { fast_vec_normalize(&push, &coll_hit_1638.normal_x, 0.05f); @@ -776,7 +781,7 @@ void update_blarg_space_commando_damage_targeting_and_ground_motion(struct Moby break; } } else { - if (moby->state < 0xF) { + if (moby->state < BLARG_SPACE_COMMANDO_KNOCKBACK) { blarg_space_commando_private_data->fall_speed -= frame_time_sq * 9.8f; moby->pos.z += blarg_space_commando_private_data->fall_speed; } From 1d9c07159833420a8c733fe3db6a5eb15621f14a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:20:37 +0000 Subject: [PATCH 1237/1502] decomp: clarify names in stationary_ship_update domain_0_value_1 -> CARRIER_STATE_WAIT_FOR_TRIGGER: Source assigns v->state = 1 in CARRIER_STATE_INITIALIZE and switches on that same CarrierVars.state field. Retail 0x002f4998 loads carrier pvars into s2, 0x002f49a4 reads state +0x174, and 0x002f49cc-0x002f49d0 dispatch value 1 to the hero clip-volume test at 0x002f4a24-0x002f4a30. Initialization stores that same value to +0x174 at 0x002f4a04. Thus reuse the existing CARRIER_STATE_WAIT_FOR_TRIGGER member of this exact local state domain. domain_1_value_2 -> CARRIER_STATE_FOLLOW_PATH: Within CARRIER_STATE_WAIT_FOR_TRIGGER the source writes v->state = 2 only after the hero clip-volume test succeeds. Retail 0x002f4a28-0x002f4a38 tests the call result and stores 2 to carrier pvars +0x174. The same +0x174 field is loaded at 0x002f49a4 and value 2 dispatches through 0x002f49f0 to 0x002f4b28, which calls gunship_follow_path. This proves reuse of existing CARRIER_STATE_FOLLOW_PATH in the same carrier-state domain. domain_2_value_1 -> CARRIER_STATE_WAIT_FOR_TRIGGER: The source comparison v->state != 1 in the attached-rider loop reads the identical CarrierVars.state selector used by the named switch. Retail 0x002f4da8 sets comparison value 1, 0x002f4dac reads halfword +0x174 from the carrier pvars s2, and 0x002f4db0 skips clearing rider flags 0x41 while that state holds. Retail 0x002f49cc-0x002f4a30 dispatches this same state value to the hero clip-volume wait. Reuse the established local CARRIER_STATE_WAIT_FOR_TRIGGER member. --- src/overlays/l01/mobys/stationary_ship.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l01/mobys/stationary_ship.c b/src/overlays/l01/mobys/stationary_ship.c index 08ff34ba06..c2cae86a34 100644 --- a/src/overlays/l01/mobys/stationary_ship.c +++ b/src/overlays/l01/mobys/stationary_ship.c @@ -134,7 +134,7 @@ void stationary_ship_update(CarrierMoby *carrier_moby) { switch (v->state) { case CARRIER_STATE_INITIALIZE: v->unk194 = -1; - v->state = 1; + v->state = CARRIER_STATE_WAIT_FOR_TRIGGER; v->arrived = 0; v->keep = 0; carrier_moby->unk30 = 0xFF; @@ -142,7 +142,7 @@ void stationary_ship_update(CarrierMoby *carrier_moby) { return; case CARRIER_STATE_WAIT_FOR_TRIGGER: if (is_point_inside_clip_volume(&hero.motion.pos, volume_or_path_node_index) != 0) { - v->state = 2; + v->state = CARRIER_STATE_FOLLOW_PATH; carrier_moby->flags &= ~0x41; if (v->camera != -1) { cv = (CarrierCamVars *)((CarrierMoby *)ents)[v->camera].pvars; @@ -205,7 +205,7 @@ void stationary_ship_update(CarrierMoby *carrier_moby) { for (i = 0; i < 8; i++) { offs = l01_carrier_rider_local_offsets; if (v->riders[i] != -1) { - if (v->state != 1) { + if (v->state != CARRIER_STATE_WAIT_FOR_TRIGGER) { ((CarrierMoby *)ents)[v->riders[i]].flags &= ~0x41; } transform_vector_by_basis(&offs.v[i], &offs.v[i], &carrier_moby->unkC0); From dc459f3bd4c083c8a0a51b63335760311ce7c170 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:22:23 +0000 Subject: [PATCH 1238/1502] decomp: clarify names in hero_pick_help_mode domain_0_value_111 -> HERO_STATE_HOVERBOARD_RESPAWN_ANIMATION_WAIT: Retail 0x00255398-0x002553b4 chooses a0=0x6f after the steep wall-normal and velocity-heading tests when ground_distance is below 1.0. In the authoritative source, state flows unchanged through change_state to hero_set_state(state, 1); retail 0x00255720 calls 0x0024cee8 with the selected ID in a0 and a1=1. This proves the HeroStateId domain, whose supplied shared header defines this canonical member. domain_10_value_109 -> HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT: Retail 0x002556dc-0x00255724 recognizes trick animations 0x69..0x6c, indexes landing thresholds by air_pose_index, and reaches hero_set_state with retained a0=0x6d when anim_frame is below its threshold. In the authoritative source, state flows unchanged through change_state to hero_set_state(state, 1); retail 0x00255720 calls 0x0024cee8 with the selected ID in a0 and a1=1. This proves the HeroStateId domain, whose supplied shared header defines this canonical member. domain_1_value_109 -> HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT: Retail 0x002553a8-0x002553bc chooses a0=0x6d on the alternate ground-distance branch of the same wall collision test. In the authoritative source, state flows unchanged through change_state to hero_set_state(state, 1); retail 0x00255720 calls 0x0024cee8 with the selected ID in a0 and a1=1. This proves the HeroStateId domain, whose supplied shared header defines this canonical member. domain_2_value_109 -> HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT: Retail 0x002553d0-0x00255400 compares XY displacement with one quarter of XY velocity after wall_hit and selects a0=0x6d when displacement is smaller. In the authoritative source, state flows unchanged through change_state to hero_set_state(state, 1); retail 0x00255720 calls 0x0024cee8 with the selected ID in a0 and a1=1. This proves the HeroStateId domain, whose supplied shared header defines this canonical member. domain_3_value_110 -> HERO_STATE_HOVERBOARD_RESPAWN_POSITION_OR_TIMEOUT_WAIT: Retail 0x0025540c-0x00255440 tests level 5 and position Z below 61.4, stores 61.4 at hero+0x8a0 (board_floor_z), and selects a0=0x6e. In the authoritative source, state flows unchanged through change_state to hero_set_state(state, 1); retail 0x00255720 calls 0x0024cee8 with the selected ID in a0 and a1=1. This proves the HeroStateId domain, whose supplied shared header defines this canonical member. domain_4_value_110 -> HERO_STATE_HOVERBOARD_RESPAWN_POSITION_OR_TIMEOUT_WAIT: Retail 0x00255448-0x00255474 tests level 16 and position Z below 76.0, stores 76.0 at hero+0x8a0 (board_floor_z), and selects a0=0x6e. In the authoritative source, state flows unchanged through change_state to hero_set_state(state, 1); retail 0x00255720 calls 0x0024cee8 with the selected ID in a0 and a1=1. This proves the HeroStateId domain, whose supplied shared header defines this canonical member. domain_5_value_109 -> HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT: Retail 0x00255478-0x002554a4 tests on_slip_ground and ground_distance below 0.1 in level 16 and selects a0=0x6d. In the authoritative source, state flows unchanged through change_state to hero_set_state(state, 1); retail 0x00255720 calls 0x0024cee8 with the selected ID in a0 and a1=1. This proves the HeroStateId domain, whose supplied shared header defines this canonical member. domain_6_value_109 -> HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT: Retail 0x00255514-0x0025557c takes the lesser of current and predecessor path-point Z, tests hero is over 0.5 below it and over 4.0 away in XY, and selects a0=0x6d. In the authoritative source, state flows unchanged through change_state to hero_set_state(state, 1); retail 0x00255720 calls 0x0024cee8 with the selected ID in a0 and a1=1. This proves the HeroStateId domain, whose supplied shared header defines this canonical member. domain_7_value_109 -> HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT: Retail 0x00255674-0x00255694 compares absolute hero rotation at +0x94 against 1.0471976 after the grounded/contact, jump and downward-velocity gates and selects a0=0x6d. In the authoritative source, state flows unchanged through change_state to hero_set_state(state, 1); retail 0x00255720 calls 0x0024cee8 with the selected ID in a0 and a1=1. This proves the HeroStateId domain, whose supplied shared header defines this canonical member. domain_8_value_109 -> HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT: Retail 0x00255698-0x002556ac compares absolute hero rotation at +0x90 against 1.0471976 during the landing checks and selects a0=0x6d. In the authoritative source, state flows unchanged through change_state to hero_set_state(state, 1); retail 0x00255720 calls 0x0024cee8 with the selected ID in a0 and a1=1. This proves the HeroStateId domain, whose supplied shared header defines this canonical member. domain_9_value_109 -> HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT: Retail 0x002556b0-0x002556d8 compares yaw against board_air_yaw via fast_difference_between_rotations, selecting a0=0x6d when the difference exceeds 1.3962634. In the authoritative source, state flows unchanged through change_state to hero_set_state(state, 1); retail 0x00255720 calls 0x0024cee8 with the selected ID in a0 and a1=1. This proves the HeroStateId domain, whose supplied shared header defines this canonical member. --- .../hero/process_hero_primary_item_input.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/shared/hero/process_hero_primary_item_input.c b/src/overlays/shared/hero/process_hero_primary_item_input.c index 40a8c7b51a..ab495a767f 100644 --- a/src/overlays/shared/hero/process_hero_primary_item_input.c +++ b/src/overlays/shared/hero/process_hero_primary_item_input.c @@ -1850,9 +1850,9 @@ int hero_pick_help_mode(void) { if (fast_difference_between_rotations( fast_arc_tan(player->motion.velocity.f[0], player->motion.velocity.f[1]), player->unk8A4) < 0.7853982f) { - state = 0x6F; + state = HERO_STATE_HOVERBOARD_RESPAWN_ANIMATION_WAIT; if (!(player->ground_distance < 1.0f)) - state = 0x6D; + state = HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT; goto change_state; } } @@ -1862,7 +1862,7 @@ int hero_pick_help_mode(void) { if ((&hero)->wall_hit) { float distance = vector_length_xy(&(&hero)->motion.displacement); if (distance < vector_length_xy(&(&hero)->motion.velocity) * 0.25f) { - state = 0x6D; + state = HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT; goto change_state; } level = *(int *)0x0015ED84; @@ -1870,18 +1870,18 @@ int hero_pick_help_mode(void) { if (level == 5) { if ((&hero)->motion.pos.f[2] < 61.4f) { (&hero)->board_floor_z = 61.4f; - state = 0x6E; + state = HERO_STATE_HOVERBOARD_RESPAWN_POSITION_OR_TIMEOUT_WAIT; goto change_state; } } if (level == 0x10) { if ((&hero)->motion.pos.f[2] < 76.0f) { (&hero)->board_floor_z = 76.0f; - state = 0x6E; + state = HERO_STATE_HOVERBOARD_RESPAWN_POSITION_OR_TIMEOUT_WAIT; goto change_state; } if ((&hero)->on_slip_ground && (&hero)->ground_distance < 0.1f) { - state = 0x6D; + state = HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT; goto change_state; } } @@ -1903,7 +1903,7 @@ int hero_pick_help_mode(void) { minimum = previous_path_point_height; distance = vector_distance_xy(&(&hero)->motion.pos, &path->p[index]); if (0.5f < minimum - (&hero)->motion.pos.f[2] && 4.0f < distance) { - state = 0x6D; + state = HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT; goto change_state; } } @@ -1929,21 +1929,21 @@ int hero_pick_help_mode(void) { if (!((&hero)->motion.velocity.f[2] < 0.0f)) return 0; if (1.0471976f < absolute_float((&hero)->motion.rot.f[1])) { - state = 0x6D; + state = HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT; goto change_state; } if (1.0471976f < absolute_float((&hero)->motion.rot.f[0])) { - state = 0x6D; + state = HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT; goto change_state; } if (1.3962634f < fast_difference_between_rotations((&hero)->motion.rot.f[2], (&hero)->board_air_yaw)) { - state = 0x6D; + state = HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT; goto change_state; } if ((unsigned)(*((unsigned char *)(&hero)->moby + 0x53) - 0x69) < 4 && (&hero)->anim_frame < (float)(&l05_hoverboard_trick_landing_frame_thresholds)[(&hero)->air_pose_index]) { - state = 0x6D; + state = HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT; goto change_state; } goto continue_fall; From e18bd42891e4e0e6c08f71c92e4736f1f6d8a5f6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:24:28 +0000 Subject: [PATCH 1239/1502] decomp: clarify names in process_amoeboid_hits_and_update_targeting domain_2_value_8 -> LARGE_AMOEBOID_PROCESS_KNOCKBACK: Retail 0x002eedf8 loads the incoming amoeboid's byte state at +0x20; 0x002eee0c-0x002eee10 compares it against 8 to suppress repeat hit processing. This is the same Moby.state domain used by supplied large_amoeboid_update, which calls this helper on its moby before switching on moby[0x20]. Its established LARGE_AMOEBOID_PROCESS_KNOCKBACK=8 case calls step_moby_motion on pvars+0x60. Assigned retail independently initializes smaller amoeboid knockback via 0x002eef74/0x002ef054 and stores 8 to their +0x20 states at 0x002eef80/0x002ef060. Thus reuse the existing canonical state member, not the unrelated pvars+0x84 motion flag 8. domain_3_value_0 -> LARGE_AMOEBOID_INITIALIZE: Retail 0x002ef0e0-0x002ef0e4 reads incoming moby state byte +0x20 and bypasses height-based removal when zero; original Ghidra shows the same zero-state guard. Supplied large_amoeboid_update calls this assigned helper with its own moby before switching on that exact moby[0x20] field. Its established LARGE_AMOEBOID_INITIALIZE=0 case initializes variant size, stored position, movement parameters and activation state before assigning subsequent states. These are the same amoeboid current-state selector and object, so reuse LARGE_AMOEBOID_INITIALIZE for this comparison. --- src/overlays/shared/enemies/large_amoeboid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/large_amoeboid.c b/src/overlays/shared/enemies/large_amoeboid.c index bad97a9a80..c015d734bd 100644 --- a/src/overlays/shared/enemies/large_amoeboid.c +++ b/src/overlays/shared/enemies/large_amoeboid.c @@ -655,7 +655,7 @@ void large_amoeboid_update(unsigned char *moby) { /* Ported from rac1-decomp (src/overlays/shared/vendor_002B90A8.c: func_L01_002F0040), where it is exact; names translated to the US level program. */ void process_amoeboid_hits_and_update_targeting(char *moby) { - V_2F0040 scratch_vector; + enum { LARGE_AMOEBOID_INITIALIZE = 0 , LARGE_AMOEBOID_PROCESS_KNOCKBACK = 8 } ;V_2F0040 scratch_vector; V_2F0040 line_test_endpoint; int flag; float amount; @@ -719,7 +719,7 @@ void process_amoeboid_hits_and_update_targeting(char *moby) { } resolve_moby_hit_response(moby, hit_record, &moby_vars->health, 0, &flag, &amount, 0, 4); if (flag != 1 && amount != 0.0f && MOBY(moby)->state != 0xB && MOBY(moby)->state != 0xA && - MOBY(moby)->state != 8) { + MOBY(moby)->state != LARGE_AMOEBOID_PROCESS_KNOCKBACK) { size_multiplier = 0.8f; allocate_voice_for_target_entry(0, 0, moby); hit_decrement = 1.0f; @@ -797,7 +797,7 @@ void process_amoeboid_hits_and_update_targeting(char *moby) { } MOBY(moby)->hit_slot = 0xFF; removal_height_entry_index = moby_vars->unk258; - if (removal_height_entry_index != 0 && MOBY(moby)->state != 0 && + if (removal_height_entry_index != 0 && MOBY(moby)->state != LARGE_AMOEBOID_INITIALIZE && MOBY(moby)->pos.z < *(float *)(removal_height_entry_index * 0x1190 + pool_draw_tiles + 8)) { clear_u64_value(&scratch_vector); spawn_amoeboid_burst_sparks((unsigned char *)moby, (float *)&scratch_vector); From 297e75eee3dc2bfc85e8ea53d1aa60c2293b1134 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:26:22 +0000 Subject: [PATCH 1240/1502] decomp: clarify names in bolt_thief_update domain_0_value_2 -> BOLT_THIEF_MODE_FACE_HERO_IN_PLACE: At 0x002e3978-0x002e39a8 the +0xFC configuration equals 2 and directly enters state 1, clears turn and child, and sets animation 4, bypassing path and trigger initialization. State 1 at 0x002e3aac-0x002e3af4 computes hero-relative XY heading and updates rotation without advancing position: face hero in place. domain_1_value_1 -> BOLT_THIEF_MODE_SINGLE_PATH_THEN_FACE_HERO: At 0x002e3a04 mode +0xFC equal to 1 skips validation of other_path +0xDC while still requiring primary path +0xD8 and trigger +0xE0. Together with 0x002e3b18-0x002e3b38 (no child spawn) and 0x002e3c80-0x002e3ca8 (settle then face hero), this identifies the single-path-then-face-hero configuration. domain_2_value_1 -> BOLT_THIEF_MODE_SINGLE_PATH_THEN_FACE_HERO: At 0x002e3b18-0x002e3b38, mode +0xFC equal to 1 selects animation 0 and bypasses child spawning before state 4 follows the primary path. This same field equals 1 at 0x002e3c80-0x002e3ca8 to enter face-hero state 1 after settling, and skips other-path validation at 0x002e3a04: single path then face hero. domain_3_value_0 -> BOLT_THIEF_MODE_LINKED_MOBY_PATH_CYCLE: At 0x002e3b84-0x002e3b94 mode +0xFC equal to zero updates the linked moby while following the primary path. The non-1 trigger branch spawns child +0xF4, and the non-1 settle branch clears that child and enters other-path state 5, which returns to trigger state 2. Checked helper 0x002e4124-0x002e4174 uses child +0xF4 and child position +0x10 for these updates: linked-moby path cycle. domain_4_value_0 -> BOLT_THIEF_MODE_LINKED_MOBY_PATH_CYCLE: At 0x002e3bc8 moby+0x78 is reloaded as settle_data, so its +0xFC is the identical configuration domain. The zero comparison 0x002e3bd8-0x002e3bf0 updates the linked moby while springing toward the primary path endpoint. Mode zero then takes the non-1 branch 0x002e3cac-0x002e3ce4 into the other-path cycle; helper 0x002e4128-0x002e4174 updates child +0xF4 position. domain_5_value_1 -> BOLT_THIEF_MODE_SINGLE_PATH_THEN_FACE_HERO: At 0x002e3c80-0x002e3ca8 settle_data->mode (+0xFC of the same moby data reloaded at 0x002e3bc8) equal to 1 enters face-hero state 1, resets turn and selects animation 4 instead of following the other path. Together with 0x002e3a04 skipping other-path validation and 0x002e3b18 skipping child spawn, this is single path then face hero. --- src/overlays/l16/mobys/bolt_thief.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/overlays/l16/mobys/bolt_thief.c b/src/overlays/l16/mobys/bolt_thief.c index f80b84a27a..c21df9f50e 100644 --- a/src/overlays/l16/mobys/bolt_thief.c +++ b/src/overlays/l16/mobys/bolt_thief.c @@ -146,6 +146,11 @@ void bolt_thief_update(L16CrateMoby *moby) { BOLT_THIEF_FOLLOW_OTHER_PATH = 5, BOLT_THIEF_KNOCKBACK = 6 }; + enum { + BOLT_THIEF_MODE_LINKED_MOBY_PATH_CYCLE = 0, + BOLT_THIEF_MODE_SINGLE_PATH_THEN_FACE_HERO = 1, + BOLT_THIEF_MODE_FACE_HERO_IN_PLACE = 2 + }; L16CrateData *bolt_thief_data = moby->data; char *hit; @@ -179,7 +184,7 @@ void bolt_thief_update(L16CrateMoby *moby) { moby->opacity = 0xFF; switch (moby->state) { case BOLT_THIEF_INITIALIZE: - if (bolt_thief_data->mode == 2) { + if (bolt_thief_data->mode == BOLT_THIEF_MODE_FACE_HERO_IN_PLACE) { moby->state = BOLT_THIEF_FACE_HERO; bolt_thief_data->turn = 0.0f; set_moby_animation(moby, 4, 0); @@ -194,7 +199,7 @@ void bolt_thief_update(L16CrateMoby *moby) { mark_moby_for_removal(moby); return; } - if (bolt_thief_data->mode != 1) { + if (bolt_thief_data->mode != BOLT_THIEF_MODE_SINGLE_PATH_THEN_FACE_HERO) { if (bolt_thief_data->other_path == -1) { debug_print(D_L16_001E8720, moby->id); mark_moby_for_removal(moby); @@ -234,7 +239,7 @@ void bolt_thief_update(L16CrateMoby *moby) { } case BOLT_THIEF_WAIT_FOR_HERO_TRIGGER: if (is_point_inside_clip_volume(&hero.motion.pos, bolt_thief_data->trigger)) { - if (bolt_thief_data->mode == 1) { + if (bolt_thief_data->mode == BOLT_THIEF_MODE_SINGLE_PATH_THEN_FACE_HERO) { set_moby_animation(moby, 0, 0); } else { bolt_thief_data->child = spawn_bolt_thief_mine(moby, moby->position); @@ -247,7 +252,7 @@ void bolt_thief_update(L16CrateMoby *moby) { } break; case BOLT_THIEF_FOLLOW_PRIMARY_PATH: - if (bolt_thief_data->mode == 0) + if (bolt_thief_data->mode == BOLT_THIEF_MODE_LINKED_MOBY_PATH_CYCLE) update_linked_moby_position(moby); if (advance_bolt_thief_path((char *)moby)) { moby->state = BOLT_THIEF_SETTLE_AT_PATH_END; @@ -261,7 +266,7 @@ void bolt_thief_update(L16CrateMoby *moby) { float target[4]; float zero; - if (settle_data->mode == 0) + if (settle_data->mode == BOLT_THIEF_MODE_LINKED_MOBY_PATH_CYCLE) update_linked_moby_position(moby); qcopy(target, path + *(int *)path * 16); zero = 0.0f; @@ -284,7 +289,7 @@ void bolt_thief_update(L16CrateMoby *moby) { *(float *)&D_L16_00161D98_gp, zero); if ((moby->status & 2) && moby->frame == moby->animation) { - if (settle_data->mode == 1) { + if (settle_data->mode == BOLT_THIEF_MODE_SINGLE_PATH_THEN_FACE_HERO) { moby->state = BOLT_THIEF_FACE_HERO; settle_data->turn = zero; set_moby_animation(moby, 4, 0); From d2ee4d6ed8c863c10012b71354cc6fe92d4b1ff4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:26:22 +0000 Subject: [PATCH 1241/1502] decomp: clarify names in update_hover_moby_steering domain_0_value_6 -> SAND_MOUSE_FADE_OUT_AND_RESET_HOME: Retail 0x002e3838 retains the moby argument in s2, and 0x002e3874-0x002e388c compares its state byte +0x20 with 6 to select movement_state+0x30 (home) as reference. Checked caller 0x002e47ec-0x002e47f4 passes the same sand-mouse moby s3 and pvars s4. Caller 0x002e4838-0x002e4844 stores 6 in that moby's +0x20; 0x002e4878-0x002e49f8 fades alpha, then restores home and changes state to 19. The authoritative caller C already names this exact state SAND_MOUSE_FADE_OUT_AND_RESET_HOME; it is unrelated to HeroStateId. domain_1_value_6 -> SAND_MOUSE_FADE_OUT_AND_RESET_HOME: Retail 0x002e3bc0-0x002e3bf0 compares the same s2 moby state byte +0x20 with 6 and clamps stored movement at movement_state+0x10 to frame_time*2.7. Checked caller 0x002e47ec-0x002e47f4 passes its sand-mouse moby s3 unchanged; 0x002e4838-0x002e4844 assigns this same state byte 6. Caller fade alpha and home reset at 0x002e4878-0x002e49f8, together with authoritative sand_mouse_update enum SAND_MOUSE_FADE_OUT_AND_RESET_HOME=6, prove the domain and canonical state name. domain_2_value_6 -> SAND_MOUSE_FADE_OUT_AND_RESET_HOME: Retail 0x002e3e0c-0x002e3e14 tests moby state byte +0x20 against 6 and returns before hero proximity avoidance. This is the same moby passed by sand_mouse_update at 0x002e47ec-0x002e47f4. Caller 0x002e4838-0x002e4844 stores 6 into its +0x20 before the fade-alpha and reset-home handler at 0x002e4878-0x002e49f8. Authoritative caller C names that state SAND_MOUSE_FADE_OUT_AND_RESET_HOME=6, proving this comparison's meaning independently of equal-valued hero state IDs. --- src/overlays/shared/enemies/sand_mouse.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/sand_mouse.c b/src/overlays/shared/enemies/sand_mouse.c index 6c8168f4cb..04f7ca041f 100644 --- a/src/overlays/shared/enemies/sand_mouse.c +++ b/src/overlays/shared/enemies/sand_mouse.c @@ -349,6 +349,9 @@ void update_hover_moby_steering(struct Moby *moby, char *movement_state) { HOVER_FACE_GOAL_AND_WAIT = 0, HOVER_MOVE_TOWARD_GOAL = 2 }; + enum { + SAND_MOUSE_FADE_OUT_AND_RESET_HOME = 6 + }; Vec4 velocity_adjustment; f32 reference_distance, direction_yaw, movement_magnitude, ground, near; s32 hit; @@ -356,7 +359,7 @@ void update_hover_moby_steering(struct Moby *moby, char *movement_state) { struct Moby *target; fast_vec_sub(&velocity_adjustment, movement_state, &moby->pos); - if (moby->state == 6) + if (moby->state == SAND_MOUSE_FADE_OUT_AND_RESET_HOME) reference_distance = vector_distance_xy(&moby->pos, movement_state + 0x30); else reference_distance = vector_distance_xy(&moby->pos, &hero.motion.pos); @@ -421,7 +424,7 @@ void update_hover_moby_steering(struct Moby *moby, char *movement_state) { velocity_adjustment.f[2] *= frame_scale * -0.100000024f + 1.0f; fast_vec_add( ((f32 *)(movement_state + 0x10)), ((f32 *)(movement_state + 0x10)), &velocity_adjustment); - if (moby->state == 6) + if (moby->state == SAND_MOUSE_FADE_OUT_AND_RESET_HOME) clamp_vector_length( ((f32 *)(movement_state + 0x10)), ((f32 *)(movement_state + 0x10)), frame_time * 2.7f); hit = move_moby_with_collision_integer_radius(moby, @@ -466,7 +469,7 @@ void update_hover_moby_steering(struct Moby *moby, char *movement_state) { } } collision_done: - if (moby->state == 6 || !(reference_distance < 1.1f)) + if (moby->state == SAND_MOUSE_FADE_OUT_AND_RESET_HOME || !(reference_distance < 1.1f)) return; near = 1.1f - reference_distance; direction_yaw = From a9bdd9d6fe546a1abcf3d4a790c066dd195dbd79 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:29:10 +0000 Subject: [PATCH 1242/1502] decomp: clarify names in teleporter_update domain_0_value_2 -> HERO_TARGET_POSE_STATUS_TRANSFER_READY: Source transfer_preparation_status receives get_hero_target_pose_status(), matching original Ghidra case 2 and retail jal 0x002495d0 at 0x00308f90 with return saved at 0x00308fb4. Checked helper 0x002495d0-0x00249614 returns 2 only for global 0x001413d4 == 0x67. Supplied request_hero_target_pose source establishes hero.state.current 0x65..0x67 as the target-pose range. Retail 0x00309048-0x00309068 tests this return against 2 and, after preparation gates, sets radius 1.95 and TELEPORTER_TRANSFER_TO_DESTINATION. Thus the helper status permits transfer here; it is not HERO_STATE_RUN, vehicle mode 2, gravity mode 2 or teleporter state 2. domain_1_value_0 -> HERO_TARGET_POSE_STATUS_INACTIVE: The same int transfer_preparation_status is the return of get_hero_target_pose_status at retail 0x00308f90, preserved at 0x00308fb4. Checked helper 0x002495d0-0x00249614 returns 1 for global 0x001413d4 values 0x65/0x66, 2 for 0x67, and 0 for every value outside that range. Supplied request_hero_target_pose source identifies 0x65..0x67 as its hero.state.current range and enters 0x65 when outside it. Zero therefore denotes an inactive target-pose state range, corroborated by original Ghidra case 2 and retail 0x0030906c-0x00309070 selecting TELEPORTER_RETURN_TO_IDLE instead of transfer. No cancellation or failure reason is implied. --- src/overlays/shared/props/teleporter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/props/teleporter.c b/src/overlays/shared/props/teleporter.c index f787bb40d6..2e9d807069 100644 --- a/src/overlays/shared/props/teleporter.c +++ b/src/overlays/shared/props/teleporter.c @@ -261,7 +261,7 @@ void teleporter_update(struct Moby *moby) { TELEPORTER_ENTER_WAIT_FOR_USE = 6, TELEPORTER_EFFECT_CYCLE_PREPARE = 7, TELEPORTER_EFFECT_CYCLE_RETURN_TO_IDLE = 8 - } ; enum { TELEPORTER_WAIT_FOR_ACTIVATION = 5}; + } ; enum { TELEPORTER_WAIT_FOR_ACTIVATION = 5} ; enum { HERO_TARGET_POSE_STATUS_INACTIVE = 0 , HERO_TARGET_POSE_STATUS_TRANSFER_READY = 2}; TeleporterVars *teleporter_vars = (TeleporterVars *)moby->pvars; int active = 0; @@ -387,10 +387,10 @@ void teleporter_update(struct Moby *moby) { teleporter_child_motion_deceleration_gp * frame_time_sq, teleporter_child_motion_max_speed_gp * frame_time); } else if (D_L01_0015F594 != 4 || !(teleporter_vars->unk14[3] > 0.25f)) { - if (transfer_preparation_status == 2) { + if (transfer_preparation_status == HERO_TARGET_POSE_STATUS_TRANSFER_READY) { teleporter_vars->unk34 = 1.95f; moby->state = TELEPORTER_TRANSFER_TO_DESTINATION; - } else if (transfer_preparation_status == 0) { + } else if (transfer_preparation_status == HERO_TARGET_POSE_STATUS_INACTIVE) { moby->state = TELEPORTER_RETURN_TO_IDLE; } } From e9cea154bdc9193e49408a5dfce497be4fdcfac3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:30:53 +0000 Subject: [PATCH 1243/1502] decomp: clarify names in update_kerwan_path_enemy_hit_reaction domain_0_value_1 -> HIT_REACTION_SUPPRESSED: Retail 002c9644 passes sp+0x10 as the fifth helper argument; 002c9664-002c966c reads that output and skips damage/knockback when it equals 1. Checked level-03 helper 00248f00 saves this output pointer in s3 at 00248f10. Its no-hit-record path writes 1 at 00249030-00249034 and zero damage at 00249040. Its cooldown/flag-gated path at 00249394-002493dc writes 1 at 002493d4-002493d8 and clears hit+0x2c at 002493e0, copied to damage output at 00249408-0024940c. Thus 1 is a reaction-suppression status, distinct from the table-loaded response returned in v0 at 00249448 and saved in caller s3 at 002c9658. --- src/overlays/l03/mobys/kerwan_path_enemy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l03/mobys/kerwan_path_enemy.c b/src/overlays/l03/mobys/kerwan_path_enemy.c index b30db718ad..32cb16fd86 100644 --- a/src/overlays/l03/mobys/kerwan_path_enemy.c +++ b/src/overlays/l03/mobys/kerwan_path_enemy.c @@ -1495,6 +1495,9 @@ void update_kerwan_path_enemy_hit_reaction(Moby2C8398 *moby) { ENEMY_KNOCKBACK_RECOVERY = 10, ENEMY_DEATH_KNOCKBACK = 0xD }; + enum { + HIT_REACTION_SUPPRESSED = 1 + }; float hit_knockback_vector[4]; int kind; float damage; @@ -1518,7 +1521,7 @@ void update_kerwan_path_enemy_hit_reaction(Moby2C8398 *moby) { hit = find_moby_hit(moby, 0x330000, 0); hit_response_code = resolve_moby_hit_response(moby, hit, &moby_data->f20, 0, &kind, &damage, 0, 4); - if (hit != 0 && kind != 1 && moby->state != ENEMY_DEATH_KNOCKBACK) { + if (hit != 0 && kind != HIT_REACTION_SUPPRESSED && moby->state != ENEMY_DEATH_KNOCKBACK) { hit_record_source_moby = *(char **)(hit + 0x20); if (hit_record_source_moby != 0) { if (hit_record_source_moby != (char *)hero.items[0].moby) { From eb5a4f65b26d77e2e0cfe75bcb50271a6e120fe5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:32:39 +0000 Subject: [PATCH 1244/1502] decomp: clarify names in update_blarg_space_commando_damage_targeting_and_ground_motion domain_0_value_2 -> TARGET_MODE_NO_ELIGIBLE_TARGET: Authoritative src/overlays/l13/mobys/blarg_space_commando.c SHA-256 a84474dcdef9f1c6ac593d5bd6fc4210631a8261f02996a48ff5ab4ff7b3bc40 and original assigned Ghidra/instructions reviewed. Assigned 0x00308fd4 passes pvars+0x120 to target helper 0x0026bf80. Checked helper request 07d4d7bfece44b2292d86aed06167a85 retains that output in s5 and at 0x0026c3d0 writes its selection status to 0x44(s5), proving pvars+0x164 is the targeting-status domain, separate from moby state and hit results. Helper 0x0026c0c8..0x0026c0d0 sets status 2 when the primary target fails path eligibility, while successful alternative candidates set status 1 at 0x0026c1dc..0x0026c1ec and 0x0026c2ec..0x0026c2fc. Assigned 0x00309010..0x00309058 stores 2 at +0x164 when target distance from home exceeds the selected range or absolute target height difference exceeds 3.0, invalidating target eligibility. domain_1_value_2 -> TARGET_MODE_NO_ELIGIBLE_TARGET: Authoritative src/overlays/l13/mobys/blarg_space_commando.c SHA-256 a84474dcdef9f1c6ac593d5bd6fc4210631a8261f02996a48ff5ab4ff7b3bc40 and original assigned Ghidra/instructions reviewed. Assigned 0x00308fd4 passes pvars+0x120 to target helper 0x0026bf80. Checked helper request 07d4d7bfece44b2292d86aed06167a85 retains that output in s5 and at 0x0026c3d0 writes its selection status to 0x44(s5), proving pvars+0x164 is the targeting-status domain, separate from moby state and hit results. Helper 0x0026c0c8..0x0026c0d0 sets status 2 when the primary target fails path eligibility, while successful alternative candidates set status 1 at 0x0026c1dc..0x0026c1ec and 0x0026c2ec..0x0026c2fc. Assigned 0x0030905c..0x00309084 checks target_moby != -1 and calls clip-volume eligibility helper 0x0026b9a8 on pvars+0x120. A zero return stores 2 at +0x164, the same ineligible-target status as the range/height rejection. --- src/overlays/l13/mobys/blarg_space_commando.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l13/mobys/blarg_space_commando.c b/src/overlays/l13/mobys/blarg_space_commando.c index 37b04358b8..eca7f2186e 100644 --- a/src/overlays/l13/mobys/blarg_space_commando.c +++ b/src/overlays/l13/mobys/blarg_space_commando.c @@ -614,6 +614,9 @@ void update_blarg_space_commando_damage_targeting_and_ground_motion(struct Moby BLARG_SPACE_COMMANDO_KNOCKBACK = 0xF, BLARG_SPACE_COMMANDO_DYING = 0x10 }; + enum { + TARGET_MODE_NO_ELIGIBLE_TARGET = 2 + }; struct WalkerVars_8d10 *blarg_space_commando_private_data = (struct WalkerVars_8d10 *)moby->pvars; char *hit; @@ -716,12 +719,12 @@ void update_blarg_space_commando_damage_targeting_and_ground_motion(struct Moby vector_distance_xy(&blarg_space_commando_private_data->home, &blarg_space_commando_private_data->target) || absolute_float(moby->pos.z - blarg_space_commando_private_data->target.z) > 3.0f) { - blarg_space_commando_private_data->mode = 2; + blarg_space_commando_private_data->mode = TARGET_MODE_NO_ELIGIBLE_TARGET; } if (blarg_space_commando_private_data->target_moby != -1 && is_point_inside_clip_volume(&blarg_space_commando_private_data->target, blarg_space_commando_private_data->target_moby) == 0) { - blarg_space_commando_private_data->mode = 2; + blarg_space_commando_private_data->mode = TARGET_MODE_NO_ELIGIBLE_TARGET; } else { blarg_space_commando_private_data->target_moby = -1; } From e9f4aaa00ca717863b9e23e448f4458a9d26a882 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:32:39 +0000 Subject: [PATCH 1245/1502] decomp: clarify names in update_hero_ground_contact_and_gravity domain_0_value_13 -> GROUND_MATERIAL_SINK_TRIGGER: Retail 0x00232ef8-0x00232f08 stores collision_hit_material() into hero+0x12E0 (hero.ground_type); 0x00232fa0-0x00232fe8 compares that stored material with 13, captures HH.point.z as water_surface_z and re-probes below it. The authoritative same-file update_hero_ground_material_effects saves this exact hero.ground_type domain, already defines GROUND_MATERIAL_SINK_TRIGGER=0xD, sets selector_13 on that material, then requests HERO_STATE_SINK when descending below the saved surface. This proves reuse of the established material name rather than HeroStateId member 13. --- src/overlays/shared/hero/hero_frame_update.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index 6e2177be41..7caedb0d3c 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -1151,6 +1151,9 @@ void update_hero_ground_contact_and_gravity(void) { enum { GROUND_MATERIAL_WATER = 0 }; + enum { + GROUND_MATERIAL_SINK_TRIGGER = 0xD + }; V collision_ray_end, ground_ray_start, ground_delta_or_angles, side_ray_start, unused_side_probe_point, side_hit_angles, normalized_side_hit_normal; f32 f; @@ -1209,7 +1212,7 @@ void update_hero_ground_contact_and_gravity(void) { } hero.ground_sound_class = collision_sound_class; } - if (hero.ground_type == 0xD) { + if (hero.ground_type == GROUND_MATERIAL_SINK_TRIGGER) { hero.water_surface_z = HH.point.f[2]; ground_ray_start.f[2] = HH.point.f[2] - 0.01f; if (FUN_001efa68_c(&ground_ray_start, &collision_ray_end, 4, (s32)hero.moby, 0) == 0) { From 895530c81ec34181515a0b5eb48714de9da9a527 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:34:43 +0000 Subject: [PATCH 1246/1502] decomp: clarify names in update_hero_ground_contact domain_0_value_0 -> GROUND_MATERIAL_WATER_SURFACE_TRIGGER: Authoritative source a70f95bd3860e23998eef44d3d66b833a3e855573550f1f4fdcd2672242212c0 assigns collision_hit_material() to hero.ground_type. Retail 0x002217d8-0x002217e8 calls the material helper, stores its return at hero+0x12E0 and selects the zero branch. At 0x002217ec-0x00221818 that branch resolves water_surface_z and sets in_water_frames when hero.pos.z is below it; 0x0022181c-0x00221838 repeats the ray with mask 0x24. Original retail Ghidra confirms the same material-zero water tracking path, proving a water-surface trigger rather than a hero state. domain_1_value_3 -> GROUND_MATERIAL_SINK_SURFACE_TRIGGER: Retail 0x002217d8-0x002217e8 stores the collision material into hero+0x12E0; 0x002218d4-0x00221918 compares that same field with 3, copies HH.point.z into hero+0x2F4 (sink_surface_z), lowers the ray start to hit.z-0.01 and probes with mask 4. Original retail Ghidra agrees. In the authoritative C snapshot, process_hero_ground_material_effects already names saved_ground_type==3 GROUND_MATERIAL_SINK_SURFACE_TRIGGER; saved_ground_type is copied directly from this same hero.ground_type field. Its selector_3 consumer tests sink_surface_z during downward surface crossing. Reuse that exact material-domain name, not HERO_STATE_STOP. --- src/overlays/l02/hero/update_hero_state_motion.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l02/hero/update_hero_state_motion.c b/src/overlays/l02/hero/update_hero_state_motion.c index 19110ff83c..cd1ed007ce 100644 --- a/src/overlays/l02/hero/update_hero_state_motion.c +++ b/src/overlays/l02/hero/update_hero_state_motion.c @@ -342,6 +342,10 @@ void update_hero_ground_contact(void) { enum { GROUND_MATERIAL_SINK_TRIGGER = 0xD }; + enum { + GROUND_MATERIAL_WATER_SURFACE_TRIGGER = 0, + GROUND_MATERIAL_SINK_SURFACE_TRIGGER = 3 + }; V collision_ray_end, collision_ray_start, ground_geometry_scratch, probe_ray_start, unused_probe_point, probe_surface_angles, normalized_probe_hit_normal; f32 f; @@ -385,7 +389,7 @@ void update_hero_ground_contact(void) { } hero.ground_sound_class = collision_sound_class; hero.ground_type = collision_hit_material(); - if (hero.ground_type == 0) { + if (hero.ground_type == GROUND_MATERIAL_WATER_SURFACE_TRIGGER) { hero.water_surface_z = resolve_camera_surface_height(D_L02_00174460, (u8 *)&hero.water_surface_normal); if (hero.motion.pos.f[2] < hero.water_surface_z && hero.in_water_frames <= 0) { @@ -408,7 +412,7 @@ void update_hero_ground_contact(void) { goto d1; } } - if (hero.ground_type == 3) { + if (hero.ground_type == GROUND_MATERIAL_SINK_SURFACE_TRIGGER) { hero.sink_surface_z = HH.point.f[2]; collision_ray_start.f[2] = HH.point.f[2] - 0.01f; if (collision_line(&collision_ray_start, &collision_ray_end, 4, (s32)hero.moby, 0) == 0) { From c17c3525e99f3cc682ceac8bc876b18268f21567 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:36:23 +0000 Subject: [PATCH 1247/1502] decomp: clarify names in tresspasser_pad_update domain_0_value_0 -> NULL: The source declares Data *pad_puzzle_state from moby->pvars. Retail lw s2,0x78(s3) at 0x002d8af4 followed by beq s2,zero at 0x002d8af8 returns before dereference, proving this zero is the null pointer sentinel rather than a state ID. domain_1_value_1 -> TRESSPASSER_PAD_STATE_WAIT_FOR_TOOL_ACTIVATION: Retail 0x002d8b50 stores s1=1 to moby state byte +0x20, the same byte loaded at 0x002d8b00 and dispatched to 0x002d8bf8 for value 1. That branch checks ground contact, held item 0x1A and its command before activation, matching the existing local enum member. domain_2_value_4 -> TRESSPASSER_PAD_STATE_COMPLETED: Retail 0x002d8ba8..0x002d8bf4 tests the save-id collected byte or level save bit and stores 4 to the same moby state byte +0x20 used by the dispatcher. This bypasses interaction for saved completion; the completion commit also stores 4 at 0x002d92bc after setting both save bits and command, proving the completed pad state. domain_3_value_2 -> TRESSPASSER_PAD_STATE_ACTIVE_PUZZLE: After held tool command activation, retail 0x002d8ce4..0x002d8cf0 stores 2 to moby state +0x20 and initializes camera transition storage. The dispatcher at 0x002d8b24 routes that same state byte value 2 to camera interpolation, puzzle drawing and ring input at 0x002d8d2c onward, matching the existing local enum. domain_4_value_3 -> TRESSPASSER_PAD_STATE_COMMIT_COMPLETION: Retail 0x002d9038..0x002d9058 checks that the 12-marker scan found no remaining marker value 1, decrements the timer and stores 3 to moby state +0x20. Dispatch of that byte value 3 reaches 0x002d9214, which commits save bits and command, matching the existing COMMIT_COMPLETION enum member. domain_5_value_1 -> TRESSPASSER_PAD_STATE_WAIT_FOR_TOOL_ACTIVATION: Retail 0x002d9194..0x002d91f8 tests the exit gate, hero state and held item then stores 1 to moby state +0x20 before ending the camera mount and requesting idle. The same byte value dispatches at 0x002d8b04 to the ground-contact/tool-command waiting branch, proving reuse of the existing WAIT_FOR_TOOL_ACTIVATION member. domain_6_value_4 -> TRESSPASSER_PAD_STATE_COMPLETED: Retail 0x002d9274 and 0x002d929c commit both save-id bit arrays; 0x002d92a0..0x002d92b0 ends the camera mount and requests hero state, then 0x002d92b8 sets moby command and 0x002d92bc stores 4 to moby state +0x20. Initialization assigns the same state for an already-saved pad, proving the shared completed state. --- src/overlays/shared/props/trespasser_pad.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/props/trespasser_pad.c b/src/overlays/shared/props/trespasser_pad.c index d88c9c3a88..0d5bb79bf3 100644 --- a/src/overlays/shared/props/trespasser_pad.c +++ b/src/overlays/shared/props/trespasser_pad.c @@ -244,17 +244,20 @@ void tresspasser_pad_update(Moby *moby) { TRESSPASSER_PAD_STATE_ACTIVE_PUZZLE = 2, TRESSPASSER_PAD_STATE_COMMIT_COMPLETION = 3 }; + enum { + TRESSPASSER_PAD_STATE_COMPLETED = 4 + }; Vec_2D9F08 camera_pos, camera_rot; Data *pad_puzzle_state = (struct Data *)moby->pvars; int i; - if (pad_puzzle_state == 0) { + if (pad_puzzle_state == NULL) { return; } switch (moby->state) { case TRESSPASSER_PAD_STATE_INITIALIZE: pad_puzzle_state->h12 = 0; - moby->state = 1; + moby->state = TRESSPASSER_PAD_STATE_WAIT_FOR_TOOL_ACTIVATION; D_L02_001D33B0[2][1] = 17.0f; D_L02_001D33B0[0][1] = 17.0f; D_L02_001D33B0[1][0] = 17.0f; @@ -270,7 +273,7 @@ void tresspasser_pad_update(Moby *moby) { (current_level_index_macro << 8)))[(short)moby->save_id >> 5] >> (moby->save_id & 0x1F)) & 1) { - moby->state = 4; + moby->state = TRESSPASSER_PAD_STATE_COMPLETED; } } break; @@ -299,7 +302,7 @@ void tresspasser_pad_update(Moby *moby) { hero_set_state(0x72, 0); set_hero_animation(0x57, 0, scale_game_frames(6)); jet_mount(&D_L02_00167440_2D9F08[0], &D_L02_00167440_2D9F08[1], 1, 0, 0); - moby->state = 2; + moby->state = TRESSPASSER_PAD_STATE_ACTIVE_PUZZLE; pad_puzzle_state->h10 = scale_game_frames(0x3C); pad_puzzle_state->f110 = 0.0f; qcopy(&pad_puzzle_state->vF0, &D_L02_00167440_2D9F08[0]); @@ -378,7 +381,7 @@ void tresspasser_pad_update(Moby *moby) { } } else if (i == 12) { if (fast_dec_timer_s16(&pad_puzzle_state->h10)) { - moby->state = 3; + moby->state = TRESSPASSER_PAD_STATE_COMMIT_COMPLETION; } } else if (((struct PadStateWords *)&controller_state)->unmasked.held_pressed & 0xA00000000000) { @@ -413,7 +416,7 @@ void tresspasser_pad_update(Moby *moby) { if (((pad_pressed_lui & 0x10) && D_L02_00179A10.i0 == 0 && D_L02_00179A10.i24 == -1) || ((Hero *)(D_0013E633_2D9F08 + 0xE1D))->state.current != 0x72 || ((Hero *)(D_0013E633_2D9F08 + 0xE1D))->items[0].item_id != 0x1A) { - moby->state = 1; + moby->state = TRESSPASSER_PAD_STATE_WAIT_FOR_TOOL_ACTIVATION; jet_end_mount(1); request_hero_idle_state_for_vehicle_mode(); pad_puzzle_state->h10 = scale_game_frames(0x3C); @@ -431,7 +434,7 @@ void tresspasser_pad_update(Moby *moby) { jet_end_mount(1); hero_set_state(0, 1); moby->command = 1; - moby->state = 4; + moby->state = TRESSPASSER_PAD_STATE_COMPLETED; } break; } From 5eb132bc8645134ade452d0266105dea58bdd4ed Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:36:23 +0000 Subject: [PATCH 1248/1502] decomp: clarify names in update_drawbridge domain_1_value_6 -> DRAWBRIDGE_COMPLETE: Retail 0x002f563c-0x002f5658 stores 6 to the same moby+0x20 byte dispatched at 0x002f55d8, and sets bridge scalars to final 20/1000/1000. The authoritative C already names this selector's case 6 DRAWBRIDGE_COMPLETE; reuse that local member. domain_2_value_1 -> WAIT_FOR_DRAWBRIDGE_ACTIVATION: Retail 0x002f5630 and 0x002f565c store 1 to moby+0x20 when the mission-table byte is not 0xFF. That exact byte selects the switch; its established case WAIT_FOR_DRAWBRIDGE_ACTIVATION at 0x002f582c-0x002f5880 waits on activation gates before entering state 3. domain_3_value_3 -> FADE_BEFORE_DRAWBRIDGE_ANIMATION: Retail 0x002f5860-0x002f5880 stores 3 to moby+0x20 and initializes private fade+0x6C to -0.01 after activation gates pass. This is the same selector as the existing local case FADE_BEFORE_DRAWBRIDGE_ANIMATION, which advances fade and enters animation state 4 at fade>=1. domain_4_value_4 -> ANIMATE_DRAWBRIDGE_AND_CAMERA: Retail 0x002f5930-0x002f5954 tests private fade>=1 and stores 4 to moby+0x20. The same state byte dispatches the established ANIMATE_DRAWBRIDGE_AND_CAMERA case: 0x002f5974-0x002f5a78 advances bridge scalars and 0x002f5b2c-0x002f5c70 interpolates and applies camera transforms. domain_5_value_5 -> FADE_AFTER_DRAWBRIDGE_ANIMATION: Retail 0x002f5a7c-0x002f5aa8 tests final yaw scalar>=1000, stores 5 to moby+0x20 and sets private fade to -1. This exact selector has existing member FADE_AFTER_DRAWBRIDGE_ANIMATION; its case at 0x002f5c7c advances fade and performs camera cleanup before completion. domain_6_value_6 -> DRAWBRIDGE_COMPLETE: Retail 0x002f5cf8-0x002f5d24 tests final fade>=1 and stores 6 to moby+0x20 before help/dialogue/save calls. This is the same switch byte loaded at 0x002f55d8 and already named DRAWBRIDGE_COMPLETE in the authoritative local enum, also selected on initialization with final bridge transforms. --- src/overlays/l06/mobys/drawbridge.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l06/mobys/drawbridge.c b/src/overlays/l06/mobys/drawbridge.c index a3fdec6add..01fce05f2a 100644 --- a/src/overlays/l06/mobys/drawbridge.c +++ b/src/overlays/l06/mobys/drawbridge.c @@ -136,12 +136,12 @@ void drawbridge_update(Moby *moby) { case INITIALIZE_DRAWBRIDGE_SEGMENTS: { int status = visited52[moby->mission + (current_level_index << 4)]; if (status == 0xFF) { - moby->state = 6; + moby->state = DRAWBRIDGE_COMPLETE; drawbridge_extension_gp = 20.0f; drawbridge_pitch_degrees_gp = 1000.0f; drawbridge_yaw_degrees_gp = 1000.0f; } else { - moby->state = 1; + moby->state = WAIT_FOR_DRAWBRIDGE_ACTIVATION; } for (i = 0; i < 20; i++) { drawbridge_control_vars->a[i] = create_moby(0x405); @@ -181,7 +181,7 @@ void drawbridge_update(Moby *moby) { case WAIT_FOR_DRAWBRIDGE_ACTIVATION: if (D_001413F4_r[0] == 1 && D_0013D4D6[0] != 0 && D_L06_0015F5C4 == 0) { D_L06_0015F3FC = 1.0f; - moby->state = 3; + moby->state = FADE_BEFORE_DRAWBRIDGE_ANIMATION; drawbridge_control_vars->fade = -0.01f; } break; @@ -199,7 +199,7 @@ void drawbridge_update(Moby *moby) { 0, 0); } else if (1.0f <= drawbridge_control_vars->fade) { - moby->state = 4; + moby->state = ANIMATE_DRAWBRIDGE_AND_CAMERA; moby->command = allocate_voice_for_target_entry(0, 4, drawbridge_control_vars->c[9]); } break; @@ -232,7 +232,7 @@ void drawbridge_update(Moby *moby) { drawbridge_yaw_max_speed_gp * frame_time); } if (1000.0f <= drawbridge_yaw_degrees_gp) { - moby->state = 5; + moby->state = FADE_AFTER_DRAWBRIDGE_ANIMATION; drawbridge_control_vars->fade = -1.0f; } slot = moby->command; @@ -280,7 +280,7 @@ void drawbridge_update(Moby *moby) { enter_hero_idle_state_for_current_vehicle_mode(); jet_end_mount(3); } else if (1.0f <= drawbridge_control_vars->fade) { - moby->state = 6; + moby->state = DRAWBRIDGE_COMPLETE; help_request(0x1776, 0x2D); queue_dialogue_message(0x177C, -1); memcard_save_data(0, -1); From 0475fefdd86af925d17ee0e2324b704e618f9094 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:38:12 +0000 Subject: [PATCH 1249/1502] decomp: clarify names in update_hero_ground_contact domain_0_value_13 -> GROUND_MATERIAL_SINK_TRIGGER: Retail 0x002100e8-0x002100f8 stores collision_hit_material() in hero+0x12e0; 0x00210190-0x002101d8 compares that same material field with 13, records HH.point.z as water_surface_z and probes beneath it. Authoritative source SHA-256 2dc776afedfbc4f69737d32c62dc09888f2412d96da7944073108a2f4912109f already names 0xD GROUND_MATERIAL_SINK_TRIGGER in apply_hero_ground_material_effects: saved_ground_type is copied from the same hero.ground_type, material 13 sets selector_13, and that selector gates the submerged/downward-motion transition to HERO_STATE_SINK. This establishes the same material domain and sink-trigger meaning, independently of the unrelated state ID 13. --- src/overlays/l16/hero/apply_hero_ground_material_effects.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l16/hero/apply_hero_ground_material_effects.c b/src/overlays/l16/hero/apply_hero_ground_material_effects.c index 25fa630f41..4bb5844669 100644 --- a/src/overlays/l16/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l16/hero/apply_hero_ground_material_effects.c @@ -199,6 +199,9 @@ void update_hero_ground_contact(void) { enum { GROUND_MATERIAL_WATER = 0 }; + enum { + GROUND_MATERIAL_SINK_TRIGGER = 0xD + }; V_u collision_ray_endpoint, ground_probe_endpoint, ground_offset_or_angles, side_probe_endpoint, unused_side_probe_endpoint, probe_surface_angles, normalized_hit_normal; f32 f; @@ -259,7 +262,7 @@ void update_hero_ground_contact(void) { } hero.ground_sound_class = collision_sound_class; } - if (hero.ground_type == 0xD) { + if (hero.ground_type == GROUND_MATERIAL_SINK_TRIGGER) { hero.water_surface_z = HH.point.f[2]; ground_probe_endpoint.f[2] = HH.point.f[2] - 0.01f; if (collision_line(&ground_probe_endpoint, &collision_ray_endpoint, 4, (s32)hero.moby, 0) == From d686193d45c7b696cbe04983616b552a11d04cd6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:38:12 +0000 Subject: [PATCH 1250/1502] decomp: clarify names in update_mine domain_0_value_1 -> MINE_WAIT_AT_GOAL: Retail 003198e0 loads 1 and 003198e8 stores it to moby+0x20 after velocity/home/orientation initialization. The same byte is loaded at 0031986c and dispatched at 00319870-00319890. Its case-1 branch (003198f4-00319acc) holds moby position at pvars+0x80 goal and waits for perch proximity or sight triggers. Authoritative C already names that exact selector's case 1 MINE_WAIT_AT_GOAL=1, proving reuse for this assignment, separately from command at moby+0xbc. domain_1_value_2 -> MINE_CHASE_TARGET: Retail 00319ac4 loads 2 and 00319acc stores it to moby+0x20 after the case-1 perch/sight trigger initializes dive_speed, life_timer and bob_timer. This is the same state byte dispatched at 0031986c-00319890. Its case-2 branch at 00319ad0-00319e88 steers toward sight position, adds chase acceleration to velocity and integrates position. Authoritative C already names this selector's case 2 MINE_CHASE_TARGET=2, proving reuse for the transition assignment rather than command/animation values. --- src/overlays/l07/mobys/mine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l07/mobys/mine.c b/src/overlays/l07/mobys/mine.c index f96e81f4cd..6f88b8588e 100644 --- a/src/overlays/l07/mobys/mine.c +++ b/src/overlays/l07/mobys/mine.c @@ -221,7 +221,7 @@ void diving_mine_update(struct Moby *moby) { moby->rot.z = fast_arc_tan(swooper_instance_vars->goal.f[0] - moby->pos.x, swooper_instance_vars->goal.f[1] - moby->pos.y); swooper_instance_vars->unk29 = 0; - moby->state = 1; + moby->state = MINE_WAIT_AT_GOAL; moby->command = 0; break; case MINE_WAIT_AT_GOAL: @@ -250,7 +250,7 @@ void diving_mine_update(struct Moby *moby) { swooper_instance_vars->life_timer = scale_game_frames(600); moby->command = 1; swooper_instance_vars->bob_timer = scale_game_frames(7); - moby->state = 2; + moby->state = MINE_CHASE_TARGET; } break; case MINE_CHASE_TARGET: From 5035ca7104676b824529c87e4c01d5ebdcfb4ca0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:38:13 +0000 Subject: [PATCH 1251/1502] decomp: clarify names in update_heavy_gunship domain_1_value_1 -> HEAVY_GUNSHIP_PART_DETACHED: In authoritative update_heavy_gunship source (SHA-256 999fd855deb4ed0e0f066ccffa21c6ae23df6a1e9cf37ee4d85784563ab0ee7a), part is loaded from swarm_vars->parts[i].moby. Retail 0x002ea2c8 loads that hierarchy slot; 0x002ea2e8 loads the part's pvars; 0x002ea300 computes part position minus parent position into those pvars, and 0x002ea318 normalizes it to frame_time*5.0. At 0x002ea320 the same part's state byte +0x20 receives 1, then 0x002ea324 clears its hierarchy slot. This proves detached-part entry rather than parent primary-path state. Bounded retail process_heavy_gunship_part_hits evidence 3fafa65c61cb41fb816b3862074cae6f corroborates the same domain: after accumulated hits reach twelve, 0x002e98a8/0x002e98c8 prepare outward drift from the anchor, 0x002e98d8 sets the selected part state to 1 and 0x002e98e0 clears the slot; the random trailing-part path repeats this at 0x002e991c-0x002e9954. --- src/overlays/l08/mobys/heavy_gunship.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/heavy_gunship.c b/src/overlays/l08/mobys/heavy_gunship.c index 09ce48aadd..82d4dbdd32 100644 --- a/src/overlays/l08/mobys/heavy_gunship.c +++ b/src/overlays/l08/mobys/heavy_gunship.c @@ -262,6 +262,9 @@ void heavy_gunship_update(struct Moby *moby) { HEAVY_GUNSHIP_START_PRIMARY_PATH = 3, HEAVY_GUNSHIP_DISPERSE_AND_REMOVE = 0x63 }; + enum { + HEAVY_GUNSHIP_PART_DETACHED = 1 + }; HeavyGunshipVars *swarm_vars = (HeavyGunshipVars *)moby->pvars; SwarmPathFollower *follower; struct Moby *target; @@ -423,7 +426,7 @@ void heavy_gunship_update(struct Moby *moby) { cart_burst(moby, &part->pos, -1, 3.0f, 13.0f); fast_vec_sub(drift, &part->pos, &moby->pos); fast_vec_normalize(drift, drift, frame_time * 5.0f); - part->state = 1; + part->state = HEAVY_GUNSHIP_PART_DETACHED; swarm_vars->parts[i].moby = NULL; } } From dc769922717ce1ede461f718bc001d4887a9a8eb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:39:59 +0000 Subject: [PATCH 1252/1502] decomp: clarify names in update_hero_ground_contact domain_0_value_13 -> GROUND_MATERIAL_SINK_TRIGGER: Authoritative src/overlays/l05/hero/apply_hero_ground_material_effects.c SHA-256 b0e631378eea28f0bc3028c062c013a1b6c7eb8964cf86f7f327411ae7a52cb3 already declares GROUND_MATERIAL_SINK_TRIGGER=13 in apply_hero_ground_material_effects. That consumer saves hero.ground_type, tests saved_ground_type against this material, sets hero.selector_13, and triggers the sink transition when water_surface_z is above the descending hero. Assigned retail 0x002403e0-0x002403f0 obtains collision_hit_material and stores it at hero+0x12E0. 0x00240488-0x00240494 compares that same material field with 13; 0x002404ac-0x002404d0 records the collision-point Z into water_surface_z at hero+0x2F0 and retries below it with mask 4. Original Ghidra confirms sRam00140630==0xD and this surface/retry flow. Thus the existing sink-trigger material constant fits this exact selector, independently of equal-valued state IDs. --- src/overlays/l05/hero/apply_hero_ground_material_effects.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l05/hero/apply_hero_ground_material_effects.c b/src/overlays/l05/hero/apply_hero_ground_material_effects.c index 8c103fca1d..7a94088a54 100644 --- a/src/overlays/l05/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l05/hero/apply_hero_ground_material_effects.c @@ -169,6 +169,9 @@ void update_hero_ground_contact(void) { enum { GROUND_MATERIAL_WATER = 0 }; + enum { + GROUND_MATERIAL_SINK_TRIGGER = 0xD + }; V shared_probe_endpoint, ground_probe_endpoint, ground_vector_scratch, side_probe_endpoint, unused_probe_vector, hit_normal_angles, normalized_hit_normal; f32 f; @@ -228,7 +231,7 @@ void update_hero_ground_contact(void) { } hero.ground_sound_class = ground_sound_class; } - if (hero.ground_type == 0xD) { + if (hero.ground_type == GROUND_MATERIAL_SINK_TRIGGER) { hero.water_surface_z = D_L05_00174268; ground_probe_endpoint.f[2] = D_L05_00174268 - 0.01f; if (collision_line(&ground_probe_endpoint, &shared_probe_endpoint, 4, (s32)hero.moby, 0) == From 186273af7e8d2dc22e7a0fb22752703532c2b6d7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:42:07 +0000 Subject: [PATCH 1253/1502] decomp: clarify names in run_level_main_loop domain_0_value_0 -> PAL_MODE_DISABLED: Authoritative source src/overlays/shared/game/run_level_main_loop.c SHA-256 04addf2fa2a4192904a17251dac3245e2658768348ef76f846ecbdd4f10efcad uses pal_mode != 0 to select the frame timer divisor. Original retail Ghidra tests iRam0015ed80 != 0; instructions 0x0024623c..0x00246264 load that selector and take the zero branch with divisor 9600.0, while nonzero selects 11520.0. Thus zero is the disabled PAL flag, without identifying the alternative television standard. domain_1_value_0 -> PROFILER_MODE_DISABLED: The authoritative source binds g_debug_menu.profiler_mode to the selector tested after the mode-zero gate. Original retail Ghidra tests DAT_0016c070 != 0; instructions 0x00246278..0x00246288 load debug-menu offset 0x18 and branch over the callback at 0x00246288 when it is zero. Zero therefore disables the profiler-mode callback in this path. It is a debug profiler selector, not the separately loaded level frame mode or any hero-state ID. domain_2_value_0 -> PAL_MODE_DISABLED: This second authoritative pal_mode != 0 comparison loads the same retail 0x0015ed80 selector as the earlier divisor test. Original retail Ghidra initializes the threshold to 0x2580 and changes it to 0x2d00 only for nonzero iRam0015ed80. Instructions 0x002462bc..0x002462d8 load that flag, initialize 9600, and movn selects 11520 only when the flag is nonzero. Zero is the same disabled PAL flag and must reuse PAL_MODE_DISABLED. --- src/overlays/shared/game/run_level_main_loop.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/game/run_level_main_loop.c b/src/overlays/shared/game/run_level_main_loop.c index 88d781d3cb..7b9fa21b16 100644 --- a/src/overlays/shared/game/run_level_main_loop.c +++ b/src/overlays/shared/game/run_level_main_loop.c @@ -98,6 +98,10 @@ void run_level_main_loop(void) { LEVEL_MODE_GAME_STATE_UPDATE = 6, LEVEL_MODE_TIMED_BUFFER_SEQUENCE = 7 }; + enum { + PAL_MODE_DISABLED = 0, + PROFILER_MODE_DISABLED = 0 + }; int i; int saved_level_mode; int quit; @@ -258,8 +262,8 @@ void run_level_main_loop(void) { noop_main_callback(level_frame_callback_args, 0x10); vu1_sync_chain(1); D_L00_0015F5D0 = convert_integer_to_float(*(volatile int *)0x10000800) / - (pal_mode != 0 ? 11520.0f : 9600.0f); - if (D_L00_0015F5C4 == 0 && g_debug_menu.profiler_mode != 0) { + (pal_mode != PAL_MODE_DISABLED ? 11520.0f : 9600.0f); + if (D_L00_0015F5C4 == 0 && g_debug_menu.profiler_mode != PROFILER_MODE_DISABLED) { noop_main_callback(); } if (hero.fall_fade_pending == 0) { @@ -268,7 +272,7 @@ void run_level_main_loop(void) { if (mode == LEVEL_MODE_DEBUG_FLAG_GATED_UPDATE || mode == LEVEL_MODE_DEBUG_PROFILER_RENDER) { int frame_timer_threshold = 9600; - if (pal_mode != 0) { + if (pal_mode != PAL_MODE_DISABLED) { frame_timer_threshold = 11520; } if (frame_timer_threshold < *(volatile int *)0x10000800) { From 39d8ff659c619fc1ad5b9720ccbfdda2cada2bbb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:43:51 +0000 Subject: [PATCH 1254/1502] decomp: clarify names in update_drawbridge domain_0_value_255 -> DRAWBRIDGE_MISSION_ALREADY_COMPLETE: Authoritative drawbridge.c SHA-256 77fd89fd548fb57bd92e951d3879f35ed1ded089c6f234352270654fd27d03d4 loads status from visited52[moby->mission + (current_level_index << 4)]. Retail 0x002f5604-0x002f562c computes that mission/level entry, loads its byte and compares against 0xFF. Equality at 0x002f5634-0x002f5658 sets moby+0x20 to established DRAWBRIDGE_COMPLETE (6) and restores extension=20, pitch=1000, yaw=1000 before child placement. Those are the final targets of normal animation at 0x002f5974-0x002f5aa8; normal completion also enters 6 at 0x002f5cf8-0x002f5d24. Original Ghidra agrees. Thus this mission-table sentinel means this drawbridge is already complete, independently of the separate moby state enum. --- src/overlays/l06/mobys/drawbridge.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l06/mobys/drawbridge.c b/src/overlays/l06/mobys/drawbridge.c index 01fce05f2a..423daa0021 100644 --- a/src/overlays/l06/mobys/drawbridge.c +++ b/src/overlays/l06/mobys/drawbridge.c @@ -127,6 +127,9 @@ void drawbridge_update(Moby *moby) { FADE_AFTER_DRAWBRIDGE_ANIMATION = 5, DRAWBRIDGE_COMPLETE = 6 }; + enum { + DRAWBRIDGE_MISSION_ALREADY_COMPLETE = 0xFF + }; Vec_2F69D0 position, rotation, from_pos, from_rot, to_pos, to_rot; Data *drawbridge_control_vars = (struct Data *)moby->pvars; float previous_fade, blend; @@ -135,7 +138,7 @@ void drawbridge_update(Moby *moby) { switch (moby->state) { case INITIALIZE_DRAWBRIDGE_SEGMENTS: { int status = visited52[moby->mission + (current_level_index << 4)]; - if (status == 0xFF) { + if (status == DRAWBRIDGE_MISSION_ALREADY_COMPLETE) { moby->state = DRAWBRIDGE_COMPLETE; drawbridge_extension_gp = 20.0f; drawbridge_pitch_degrees_gp = 1000.0f; From 99ccdb76e338e1122c27e2169bc8fa05b253b511 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:43:51 +0000 Subject: [PATCH 1255/1502] decomp: clarify names in seeker_update domain_0_value_2 -> SEEKER_DISPATCH_MODE_SKIP_STATE_UPDATE: Retail 0x002c5a20-0x002c5a24 loads the separate global at 0x0015f5c4 (alternate gp load at 0x002c5a0c); 0x002c5a28 loads 2 and 0x002c5a2c branches directly to the epilogue at 0x002c6210 on equality. The moby state byte is first read at 0x002c5a34 and dispatched at 0x002c5a54, so this value skips the state update switch. Original Ghidra iVar7==2 return and authoritative mode=seeker_state_dispatch_mode; if(mode==2)return agree. This selector is separate from moby->state and all supplied hero enum domains. --- src/overlays/shared/enemies/seeker.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/seeker.c b/src/overlays/shared/enemies/seeker.c index 7d5e59a7bc..21e45adb02 100644 --- a/src/overlays/shared/enemies/seeker.c +++ b/src/overlays/shared/enemies/seeker.c @@ -102,6 +102,9 @@ void seeker_update(struct Moby *moby) { SEEKER_STATE_FATAL_KNOCKBACK = 6, SEEKER_STATE_EXPLODE = 7 }; + enum { + SEEKER_DISPATCH_MODE_SKIP_STATE_UPDATE = 2 + }; Moby52Vars *seeker_instance_vars = (Moby52Vars *)moby->pvars; struct Moby *target; Vec4 vel; @@ -122,7 +125,7 @@ void seeker_update(struct Moby *moby) { moby->shadow_range = 0x17; } mode = seeker_state_dispatch_mode; - if (mode == 2) { + if (mode == SEEKER_DISPATCH_MODE_SKIP_STATE_UPDATE) { return; } switch (moby->state) { From e0825ec8b31850dd5a0c89ad8ace8dff6f2783cb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:43:51 +0000 Subject: [PATCH 1256/1502] decomp: clarify names in ground_attached_update domain_2_value_273 -> ROUTE_ENTRY_ADVANCE_LIMIT: Retail 0x002d035c..0x002d0384 indexes D_L00_001B04B0 by vars+0xc0, checks row count, then loads first entry state at row+0x1c. At 0x002d0398 state 0x111 branches to 0x002d03b8/0x002d03bc to invalidate route_index. The following unsigned (state-0x11)<0x100 test at 0x002d039c..0x002d03a4 bounds the advance sequence to 0x11..0x110; 0x002d03ac..0x002d03c4 checks count and increments that sequence by one. Thus 0x111 is its explicit excluded advance limit, which invalidates instead of taking the out-of-range reset-and-clear path at 0x002d03c8..0x002d0404. This names a route-entry boundary, not a hero state. --- src/overlays/shared/pickups/crate.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/pickups/crate.c b/src/overlays/shared/pickups/crate.c index dfa249de19..099c27ea71 100644 --- a/src/overlays/shared/pickups/crate.c +++ b/src/overlays/shared/pickups/crate.c @@ -653,6 +653,9 @@ struct Vars; void ground_attached_update(M_2cfcb8 *moby) __asm__("FUN_L00_002cfcb8"); void ground_attached_update(M_2cfcb8 *moby) { + enum { + ROUTE_ENTRY_ADVANCE_LIMIT = 0x111 + }; V_2cfcb8 probe_top; V_2cfcb8 probe_bottom; V_2cfcb8 probe_up; @@ -828,7 +831,7 @@ void ground_attached_update(M_2cfcb8 *moby) { s32 entry_state = route->entries[0].state; if (entry_state == 1 || entry_state == 3) { vars->route_index = -1; - } else if (entry_state == 0x111) { + } else if (entry_state == ROUTE_ENTRY_ADVANCE_LIMIT) { vars->route_index = -1; } else if ((u32)(entry_state - 0x11) < 0x100) { if (entry_state - 0x10 >= route->count) { From cf5637be5fedec6b22bf49da9e2cf68f7ac6e0ec Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:43:51 +0000 Subject: [PATCH 1257/1502] decomp: clarify names in shrub_update domain_2_value_1 -> SHRUB_PART_RELEASED: In SHRUB_BREAK_APART_AND_REMOVE, retail 002e946c selects the parent's child-part table at pvars+0x70. 002e9488 loads each child Moby into s2; 002e94a8 loads that child's pvars into s1. 002e94b8-002e94dc stores child-position minus parent-position into child pvars and normalizes it to frame_time*5.0. 002e947c provides 1, 002e94e0 writes it to the CHILD state byte at s2+0x20, and 002e94e4 immediately clears the parent's table slot. Current C expresses exactly this as part->state=1 followed by shrub_control_vars->parts[i].moby=NULL. Thus this is the released child-part state, a separate domain from the parent's state 1; SHRUB_PART_RELEASED describes the proven transition without claiming the unobserved child update lifecycle. --- src/overlays/l08/mobys/shrub.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/shrub.c b/src/overlays/l08/mobys/shrub.c index 2580003690..9dd9017df7 100644 --- a/src/overlays/l08/mobys/shrub.c +++ b/src/overlays/l08/mobys/shrub.c @@ -224,6 +224,9 @@ void shrub_update(struct Moby *moby) { SHRUB_BEGIN_PRIMARY_PATH = 3, SHRUB_BREAK_APART_AND_REMOVE = 0x63 }; + enum { + SHRUB_PART_RELEASED = 1 + }; SwarmVars *shrub_control_vars = (SwarmVars *)moby->pvars; SwarmPathFollower *follower; struct Moby *target; @@ -391,7 +394,7 @@ void shrub_update(struct Moby *moby) { cart_burst(moby, &part->pos, -1, 3.0f, 13.0f); fast_vec_sub(drift, &part->pos, &moby->pos); fast_vec_normalize(drift, drift, frame_time * 5.0f); - part->state = 1; + part->state = SHRUB_PART_RELEASED; shrub_control_vars->parts[i].moby = NULL; } } From 4e7e253a26e78bbba0e3ba51463945437d46cbc9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:43:51 +0000 Subject: [PATCH 1258/1502] decomp: clarify names in update_mode_freeze domain_0_value_0 -> GAME_MODE_CONTINUE: 0x001fced8-0x001fcef0 accepts Cross after the delay and stores zero to game_mode; the established FREEZE_MODE_DELAYED_CONTINUE branch then exits. 0x001fd698-0x001fd6c4 resumes sounds/music for that continuation mode. domain_12_value_0 -> GAME_MODE_CONTINUE: 0x001fd1d0-0x001fd278 selects the confirmed choice, performs resource cleanup and stores zero to game_mode at 0x001fd264 before the callback; this leaves the frozen choice and continues with audio resumption. domain_13_value_0 -> GAME_MODE_CONTINUE: 0x001fd284-0x001fd2b4 handles the alternate cancelled choice and stores zero to game_mode at 0x001fd288 before optional lap correction; final 0x001fd698-0x001fd6c4 resumes audio in this continuation mode. domain_1_value_0 -> GAME_MODE_CONTINUE: 0x001fcf20-0x001fcf54 hides hero.moby and disables collision on Triangle, then stores zero to game_mode to continue; the established outer case is FREEZE_MODE_TRIANGLE_HIDE_HERO_CONTINUE. domain_2_value_0 -> GAME_MODE_CONTINUE: 0x001fcf58-0x001fcf5c branches to 0x001fd0d8-0x001fd0dc on the alternate Cross path, storing zero to game_mode to continue out of FREEZE_MODE_TRIANGLE_HIDE_HERO_CONTINUE. domain_3_value_0 -> VIDEO_MODE_REQUEST_PAL_DISABLED: Retail 0x001fcfe0-0x001fd004 starts timed preview after fade: sb zero to 0x0016034c. Original retail Ghidra names that exact byte g_bRequestedPalVideoMode and authoritative C names it requested_video_mode. This proves PAL request enabled/disabled, without assuming a particular alternative standard. domain_4_value_1 -> VIDEO_MODE_REQUEST_PAL_ENABLED: Retail 0x001fd01c-0x001fd02c restores the flag on timeout: sb s2 (known 1) to 0x0016034c. Original retail Ghidra names that exact byte g_bRequestedPalVideoMode and authoritative C names it requested_video_mode. This proves PAL request enabled/disabled, without assuming a particular alternative standard. domain_5_value_1 -> VIDEO_MODE_REQUEST_PAL_ENABLED: Retail 0x001fd044-0x001fd05c restores the flag on Triangle: sb s2 (known 1) to 0x0016034c. Original retail Ghidra names that exact byte g_bRequestedPalVideoMode and authoritative C names it requested_video_mode. This proves PAL request enabled/disabled, without assuming a particular alternative standard. domain_6_value_0 -> VIDEO_MODE_REQUEST_PAL_DISABLED: Retail 0x001fd060-0x001fd078 retains the preview choice on Cross: sb zero to 0x0016034c. Original retail Ghidra names that exact byte g_bRequestedPalVideoMode and authoritative C names it requested_video_mode. This proves PAL request enabled/disabled, without assuming a particular alternative standard. domain_7_value_0 -> GAME_MODE_CONTINUE: 0x001fd0a4-0x001fd0d0 tests Triangle, stores zero to game_mode and sets hero.ship_flags bit 0. This is the established FREEZE_MODE_TRIANGLE_SET_SHIP_FLAG_CONTINUE continuation branch. domain_8_value_0 -> GAME_MODE_CONTINUE: 0x001fd0d4-0x001fd0dc tests Cross and stores zero to game_mode for the alternate continuation path of FREEZE_MODE_TRIANGLE_SET_SHIP_FLAG_CONTINUE. domain_9_value_0 -> GAME_MODE_CONTINUE: 0x001fd0e8-0x001fd104 tests pressed Cross and stores zero to game_mode in the established FREEZE_MODE_AWAIT_CROSS_CONTINUE case; final audio resumption follows outside frozen modes. --- src/game/update_mode_freeze.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/game/update_mode_freeze.c b/src/game/update_mode_freeze.c index 11039f62e7..2d22fcec8d 100644 --- a/src/game/update_mode_freeze.c +++ b/src/game/update_mode_freeze.c @@ -60,6 +60,11 @@ void update_mode_freeze(void) { MODE_FREEZE_RESUME_WITH_ACTION_LIST = 16, MODE_FREEZE_BOOT_GATED_CROSS_RELOAD = 19 }; + enum { + GAME_MODE_CONTINUE = 0, + VIDEO_MODE_REQUEST_PAL_DISABLED = 0, + VIDEO_MODE_REQUEST_PAL_ENABLED = 1 + }; s32 video_mode; s32 step; sound_update(); @@ -78,7 +83,7 @@ void update_mode_freeze(void) { state = &freeze; if (scale_game_frames(0x78) < state->unk20) { if (controller_state.pressed & PAD_CROSS) { - game_mode = 0; + game_mode = GAME_MODE_CONTINUE; if (current_level_index == 1) { memcard_save_data(0, -1); } @@ -95,9 +100,9 @@ void update_mode_freeze(void) { moby->flags = (u16)(moby->flags | 1); noop_main_callback(); noop_callback_k(hero.saved_pos_rot, hero.saved_pos_rot + 0x10, 0, 1); - game_mode = 0; + game_mode = GAME_MODE_CONTINUE; } else if (controller_state.pressed & PAD_CROSS) { - game_mode = 0; + game_mode = GAME_MODE_CONTINUE; } break; @@ -118,7 +123,7 @@ void update_mode_freeze(void) { game_mode = freeze.return_game_mode; } else if (controller_state.pressed & PAD_CROSS) { fade_to_black(4); - requested_video_mode = 0; + requested_video_mode = VIDEO_MODE_REQUEST_PAL_DISABLED; freeze.choice = 2; freeze.unk20 = scale_game_frames(0x258); } @@ -126,14 +131,14 @@ void update_mode_freeze(void) { case VIDEO_MODE_TEST_PREVIEW_ACTIVE: if ((freeze.unk20 == 0) || ((--freeze.unk20) == 0)) { - requested_video_mode = 1; + requested_video_mode = VIDEO_MODE_REQUEST_PAL_ENABLED; freeze.choice = 3; } else if (controller_state.pressed & PAD_TRIANGLE) { fade_to_black(4); - requested_video_mode = 1; + requested_video_mode = VIDEO_MODE_REQUEST_PAL_ENABLED; game_mode = freeze.return_game_mode; } else if (controller_state.pressed & PAD_CROSS) { - requested_video_mode = 0; + requested_video_mode = VIDEO_MODE_REQUEST_PAL_DISABLED; game_mode = freeze.return_game_mode; } break; @@ -154,17 +159,17 @@ void update_mode_freeze(void) { case FREEZE_MODE_TRIANGLE_SET_SHIP_FLAG_CONTINUE: D_0015F648 = 2; if (controller_state.pressed & PAD_TRIANGLE) { - game_mode = 0; + game_mode = GAME_MODE_CONTINUE; hero.ship_flags = (u8)(hero.ship_flags | 1); } else if (controller_state.pressed & PAD_CROSS) { - game_mode = 0; + game_mode = GAME_MODE_CONTINUE; } break; case FREEZE_MODE_AWAIT_CROSS_CONTINUE: D_0015F648 = 2; if (controller_state.pressed & PAD_CROSS) { - game_mode = 0; + game_mode = GAME_MODE_CONTINUE; } break; @@ -217,10 +222,10 @@ void update_mode_freeze(void) { D_0015EE3C++; } } - game_mode = 0; + game_mode = GAME_MODE_CONTINUE; noop_callback_k(saved_camera_vectors, saved_camera_vectors + 0x10, 0, 1); } else { - game_mode = 0; + game_mode = GAME_MODE_CONTINUE; if (hero.race_lap >= 3) { hero.race_lap = (s16)(((u16)hero.race_lap) - 1); hero.unk890[0xBC] = 3; From a90b4cc316ccf258f05945190875651d5242deb3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:45:42 +0000 Subject: [PATCH 1259/1502] decomp: clarify names in volume_camera_swing domain_0_value_8 -> SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE: Retail 0x002ec9c4-0x002ec9d8 indexes the camera descriptor table through record+0x84, loads params from descriptor+0x1c, then reads the signed type at params+0x2c. Original Ghidra pfVar1+0xb and the bound SwingCameraParams.type agree; this is not HeroStateId. At 0x002ec9d8-0x002ec9f4 type 8 returns when current_follow_cam->state (+0x70)->tail.mode (+0x230) is zero, so entry requires nonzero follow mode. The same type comparison is reused in the distance, height and offset branches at 0x002ecf58-0x002ecf70, 0x002ecfdc-0x002ecff4 and 0x002ed040-0x002ed058. domain_10_value_6 -> SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE: Retail 0x002ec9c4-0x002ec9d8 indexes the camera descriptor table through record+0x84, loads params from descriptor+0x1c, then reads the signed type at params+0x2c. Original Ghidra pfVar1+0xb and the bound SwingCameraParams.type agree; this is not HeroStateId. At 0x002ec9fc-0x002eca10 type 6 returns when current_follow_cam->state (+0x70)->tail.mode (+0x230) is nonzero, so entry requires zero follow mode. The same type comparison is reused in the distance, height and offset branches at 0x002ecf4c-0x002ecf70, 0x002ecfd0-0x002ecff4 and 0x002ed034-0x002ed058. domain_11_value_8 -> SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE: Retail 0x002ec9c4-0x002ec9d8 indexes the camera descriptor table through record+0x84, loads params from descriptor+0x1c, then reads the signed type at params+0x2c. Original Ghidra pfVar1+0xb and the bound SwingCameraParams.type agree; this is not HeroStateId. At 0x002ec9d8-0x002ec9f4 type 8 returns when current_follow_cam->state (+0x70)->tail.mode (+0x230) is zero, so entry requires nonzero follow mode. The same type comparison is reused in the distance, height and offset branches at 0x002ecf58-0x002ecf70, 0x002ecfdc-0x002ecff4 and 0x002ed040-0x002ed058. domain_12_value_6 -> SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE: Retail 0x002ec9c4-0x002ec9d8 indexes the camera descriptor table through record+0x84, loads params from descriptor+0x1c, then reads the signed type at params+0x2c. Original Ghidra pfVar1+0xb and the bound SwingCameraParams.type agree; this is not HeroStateId. At 0x002ec9fc-0x002eca10 type 6 returns when current_follow_cam->state (+0x70)->tail.mode (+0x230) is nonzero, so entry requires zero follow mode. The same type comparison is reused in the distance, height and offset branches at 0x002ecf4c-0x002ecf70, 0x002ecfd0-0x002ecff4 and 0x002ed034-0x002ed058. domain_13_value_8 -> SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE: Retail 0x002ec9c4-0x002ec9d8 indexes the camera descriptor table through record+0x84, loads params from descriptor+0x1c, then reads the signed type at params+0x2c. Original Ghidra pfVar1+0xb and the bound SwingCameraParams.type agree; this is not HeroStateId. At 0x002ec9d8-0x002ec9f4 type 8 returns when current_follow_cam->state (+0x70)->tail.mode (+0x230) is zero, so entry requires nonzero follow mode. The same type comparison is reused in the distance, height and offset branches at 0x002ecf58-0x002ecf70, 0x002ecfdc-0x002ecff4 and 0x002ed040-0x002ed058. domain_1_value_6 -> SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE: Retail 0x002ec9c4-0x002ec9d8 indexes the camera descriptor table through record+0x84, loads params from descriptor+0x1c, then reads the signed type at params+0x2c. Original Ghidra pfVar1+0xb and the bound SwingCameraParams.type agree; this is not HeroStateId. At 0x002ec9fc-0x002eca10 type 6 returns when current_follow_cam->state (+0x70)->tail.mode (+0x230) is nonzero, so entry requires zero follow mode. The same type comparison is reused in the distance, height and offset branches at 0x002ecf4c-0x002ecf70, 0x002ecfd0-0x002ecff4 and 0x002ed034-0x002ed058. domain_5_value_9 -> SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END: Retail 0x002ec9c4-0x002ec9d8 indexes the camera descriptor table through record+0x84, loads params from descriptor+0x1c, then reads the signed type at params+0x2c. Original Ghidra pfVar1+0xb and the bound SwingCameraParams.type agree; this is not HeroStateId. At 0x002ecd68-0x002ece14 type 9 shares the 200-frame end/400-frame restart timing. At 0x002ecef8-0x002ecf2c it joins types 1 and 7 in suppressing set_follow_camera_angle_blend_from_direction when at_end is set, releasing angle control at the end. The slide calls at 0x002ed1b0-0x002ed1f8 select only 1,7,10, so type 9 has no slide qualifier. domain_7_value_9 -> SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END: Retail 0x002ec9c4-0x002ec9d8 indexes the camera descriptor table through record+0x84, loads params from descriptor+0x1c, then reads the signed type at params+0x2c. Original Ghidra pfVar1+0xb and the bound SwingCameraParams.type agree; this is not HeroStateId. At 0x002ecd68-0x002ece14 type 9 shares the 200-frame end/400-frame restart timing. At 0x002ecef8-0x002ecf2c it joins types 1 and 7 in suppressing set_follow_camera_angle_blend_from_direction when at_end is set, releasing angle control at the end. The slide calls at 0x002ed1b0-0x002ed1f8 select only 1,7,10, so type 9 has no slide qualifier. domain_8_value_6 -> SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE: Retail 0x002ec9c4-0x002ec9d8 indexes the camera descriptor table through record+0x84, loads params from descriptor+0x1c, then reads the signed type at params+0x2c. Original Ghidra pfVar1+0xb and the bound SwingCameraParams.type agree; this is not HeroStateId. At 0x002ec9fc-0x002eca10 type 6 returns when current_follow_cam->state (+0x70)->tail.mode (+0x230) is nonzero, so entry requires zero follow mode. The same type comparison is reused in the distance, height and offset branches at 0x002ecf4c-0x002ecf70, 0x002ecfd0-0x002ecff4 and 0x002ed034-0x002ed058. domain_9_value_8 -> SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE: Retail 0x002ec9c4-0x002ec9d8 indexes the camera descriptor table through record+0x84, loads params from descriptor+0x1c, then reads the signed type at params+0x2c. Original Ghidra pfVar1+0xb and the bound SwingCameraParams.type agree; this is not HeroStateId. At 0x002ec9d8-0x002ec9f4 type 8 returns when current_follow_cam->state (+0x70)->tail.mode (+0x230) is zero, so entry requires nonzero follow mode. The same type comparison is reused in the distance, height and offset branches at 0x002ecf58-0x002ecf70, 0x002ecfdc-0x002ecff4 and 0x002ed040-0x002ed058. --- src/overlays/shared/camera/swing_volume_camera.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/shared/camera/swing_volume_camera.c b/src/overlays/shared/camera/swing_volume_camera.c index a871100080..56fac7dfd6 100644 --- a/src/overlays/shared/camera/swing_volume_camera.c +++ b/src/overlays/shared/camera/swing_volume_camera.c @@ -132,7 +132,7 @@ s32 volume_camera_swing_active(struct UpdateCam *swing_camera_record) { void volume_camera_swing(struct UpdateCam *cam) __asm__("FUN_L00_002ec988"); void volume_camera_swing(struct UpdateCam *swing_camera_record) { - enum { SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END = 1 , SWING_CAMERA_TYPE_ONE_FRAME_SWING = 3 , SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST = 4 , SWING_CAMERA_TYPE_SNAP_ON_ENTRY = 5 , SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END = 10 } ;CameraVec gravity_offset_or_yaw_direction; + enum { SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END = 1 , SWING_CAMERA_TYPE_ONE_FRAME_SWING = 3 , SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST = 4 , SWING_CAMERA_TYPE_SNAP_ON_ENTRY = 5 , SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END = 10 } ; enum { SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE = 6 , SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE = 8 , SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END = 9} ;CameraVec gravity_offset_or_yaw_direction; SwingCameraParams *params; struct UpdateCam *rec; Vec4f *pos; @@ -148,10 +148,10 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { f32 lateral_spring_blend_fraction; params = camera_descriptors[swing_camera_record->descriptor_index].params; - if (params->type == 8 && FOLLOW_CAM_STATE(current_follow_cam)->tail.mode == 0) { + if (params->type == SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE && FOLLOW_CAM_STATE(current_follow_cam)->tail.mode == 0) { return; } - if (params->type == 6 && FOLLOW_CAM_STATE(current_follow_cam)->tail.mode != 0) { + if (params->type == SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE && FOLLOW_CAM_STATE(current_follow_cam)->tail.mode != 0) { return; } if (volume_camera_swing_active(swing_camera_record) == 0) { @@ -247,7 +247,7 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { params->timer = scale_game_frames(200); } FUN_L00_002e8620(); - } else if (params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || params->type == 7 || params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END || params->type == 9) { + } else if (params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || params->type == 7 || params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END || params->type == SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END) { /* Moving the left stick skips to the end of the swing. */ struct PadState *pad = &controller_state; if (pad->analog[0] != 0.0f || pad->analog[1] != 0.0f) { @@ -281,12 +281,12 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { fast_sin(camera_descriptors[swing_camera_record->descriptor_index].yaw); *(s32 *)&gravity_offset_or_yaw_direction[2] = 0; swing = params->swing * 0.017453292f * (params->timer / total); - if ((params->type != SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END && params->type != 7 && params->type != 9) || at_end == 0) { + if ((params->type != SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END && params->type != 7 && params->type != SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END) || at_end == 0) { set_follow_camera_angle_blend_from_direction( gravity_offset_or_yaw_direction, swing, params->pitch * 0.017453292f); } if (params->distance != 0.0f) { - if (params->type == 6 || params->type == 8) { + if (params->type == SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE || params->type == SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE) { follow_camera_set_distance(0, params->distance, 0.002f); FUN_L00_002e8490(params->distance + 1.36f); } else { @@ -295,14 +295,14 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { } } if (params->height != 0.0f) { - if (params->type == 6 || params->type == 8) { + if (params->type == SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE || params->type == SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE) { follow_camera_set_height(params->height, 0.002f); } else { follow_camera_set_height(params->height, 0.003f); } } if (params->offset_scale != 0.0f) { - if (params->type == 6 || params->type == 8) { + if (params->type == SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE || params->type == SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE) { follow_camera_set_offset_scale(0, params->offset_scale, 0.002f); } else { follow_camera_set_offset_scale(0, params->offset_scale, 0.005f); From ff2eebbb9040515c0191b56e30ea946fbe459d8e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:45:42 +0000 Subject: [PATCH 1260/1502] decomp: clarify names in update_gunship domain_1_value_1 -> GUNSHIP_PART_RELEASED: In the authoritative update_gunship snapshot, part comes from gunship_control_vars->links[i].part in GUNSHIP_BREAK_APART_AND_REMOVE. Retail 0x002e2cb8-0x002e2cd0 loads each linked child from the 16-byte link table. At 0x002e2cf0 its pvars is loaded; 0x002e2d00-0x002e2d24 writes part position minus parent position there and normalizes this outward drift to frame_time*5. At 0x002e2d28 sb s7,0x20(s3) assigns state 1 to that child, immediately followed at 0x002e2d2c by clearing its parent link. Thus this is the linked-part released state, distinct from the parent's primary-path state 1 and all Hero modes. --- src/overlays/l08/mobys/gunship.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/gunship.c b/src/overlays/l08/mobys/gunship.c index 1caec3f3d5..eb696a98a6 100644 --- a/src/overlays/l08/mobys/gunship.c +++ b/src/overlays/l08/mobys/gunship.c @@ -332,6 +332,9 @@ void gunship_update(struct Moby *moby) { GUNSHIP_BEGIN_PRIMARY_PATH = 3, GUNSHIP_BREAK_APART_AND_REMOVE = 0x63 }; + enum { + GUNSHIP_PART_RELEASED = 1 + }; GunshipVars *gunship_control_vars = (GunshipVars *)moby->pvars; SwarmPathFollower *follower; struct Moby *target; @@ -508,7 +511,7 @@ void gunship_update(struct Moby *moby) { cart_burst(moby, &part->pos, -1, 3.0f, 13.0f); fast_vec_sub(drift, &part->pos, &moby->pos); fast_vec_normalize(drift, drift, frame_time * 5.0f); - part->state = 1; + part->state = GUNSHIP_PART_RELEASED; gunship_control_vars->links[i].part = NULL; } } From 0702c9c397c257c3f4e3817bee0bfc9be315c54e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:45:42 +0000 Subject: [PATCH 1261/1502] decomp: clarify names in gadgetron_ceo_update domain_0_value_3 -> GADGETRON_CEO_DIALOGUE_START_CHALLENGE: Retail 0x002e6840/0x002e684c establishes s3=data+0x20; 0x002e6a8c-0x002e6a98 compares signed short s3+0x36 with 3. Its taken branch saves the dialogue entry, selects entry 2, calls set_race_camera with gadgetron_ceo_challenge_start_pose at 0x002e6acc, then enters CEO challenge monitoring and activates the challenge environment at 0x002e6af8-0x002e6b00. Bounded helper 0x00261888 confirms this same activation short indexes 0x1c-byte dialogue records at 0x00261a50-0x00261a5c. Thus entry 3 triggers starting the challenge, not HERO_STATE_STOP or CEO state 3. domain_1_value_2 -> GADGETRON_CEO_DIALOGUE_AFTER_CHALLENGE_START: In the authoritative source, activation->mode=2 is executed only in the mode==3 challenge-start branch. Retail 0x002e6aa4-0x002e6ab8 saves the prior entry at s3+4, writes short 2 at s3+0x36 and records the pending time; 0x002e6acc-0x002e6b00 then installs the challenge-start pose and activates challenge monitoring/environment. Helper evidence request 39d7322e0a364d7bacfcce2c376e33be at 0x00261a50-0x00261a5c proves +0x36 is a dialogue-table index. The name describes the entry selected after starting, without borrowing HERO_STATE_RUN, gravity or vehicle constants. domain_2_value_4 -> GADGETRON_CEO_DIALOGUE_AFTER_CHALLENGE_RETURN: Retail 0x002e6c28-0x002e6c54 handles moby event 1 by returning CEO state to dialogue polling, calling set_race_camera with gadgetron_ceo_challenge_return_pose and clearing the event. If the flag at 0x0013d507 is clear, 0x002e6c68-0x002e6c7c saves the current activation dialogue entry, writes entry 4 to s3+0x36 and sets its activation flag/time before restoring the non-challenge environment. The checked dialogue helper indexes records with that exact +0x36 short at 0x00261a50-0x00261a5c. This proves the event-1 return follow-up dialogue entry, not HERO_STATE_CROUCH, VOICE_SLOT_STOP_REQUESTED or CEO state 4. --- src/overlays/l16/mobys/gadgetron_ceo.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/overlays/l16/mobys/gadgetron_ceo.c b/src/overlays/l16/mobys/gadgetron_ceo.c index b3138540ab..7e65642a5c 100644 --- a/src/overlays/l16/mobys/gadgetron_ceo.c +++ b/src/overlays/l16/mobys/gadgetron_ceo.c @@ -173,6 +173,11 @@ void gadgetron_ceo_update(L16ChallengeMoby *ceo_moby) { GADGETRON_CEO_MONITOR_CHALLENGE_EVENTS = 3, GADGETRON_CEO_WAIT_TO_SAVE = 4 }; + enum { + GADGETRON_CEO_DIALOGUE_AFTER_CHALLENGE_START = 2, + GADGETRON_CEO_DIALOGUE_START_CHALLENGE = 3, + GADGETRON_CEO_DIALOGUE_AFTER_CHALLENGE_RETURN = 4 + }; L16ChallengeScratch ceo_gaze_vectors; L16ChallengeData *ceo_data = ceo_moby->data; L16ChallengeActivation *activation = (L16ChallengeActivation *)ceo_data->activation; @@ -219,13 +224,13 @@ void gadgetron_ceo_update(L16ChallengeMoby *ceo_moby) { *(unsigned short *)(statistics + 0x43A) = scale_game_frames(D_0015EEA4) / 600; } } - if (activation->mode == 3) { + if (activation->mode == GADGETRON_CEO_DIALOGUE_START_CHALLENGE) { char *camera; char *pose; int pending; pending = D_L16_0015F5CC; activation->previous = (unsigned short)activation->mode; - activation->mode = 2; + activation->mode = GADGETRON_CEO_DIALOGUE_AFTER_CHALLENGE_START; activation->pending = pending; ceo_moby->event = 0; pose = gadgetron_ceo_challenge_start_pose; @@ -292,7 +297,7 @@ void gadgetron_ceo_update(L16ChallengeMoby *ceo_moby) { previous = activation->mode; pending = D_L16_0015F5CC; activation->previous = previous; - activation->mode = 4; + activation->mode = GADGETRON_CEO_DIALOGUE_AFTER_CHALLENGE_RETURN; activation->pending = pending; activation->flag = event; } From f05f7904188a139bf51fa1fa29f47b1ff55f8740 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:47:45 +0000 Subject: [PATCH 1262/1502] decomp: clarify names in ryno_update domain_0_value_1 -> RYNO_STATE_WAIT_ANIMATION: At 0x002cc620 the weapon Moby is retained in s3; 0x002cc8a8-0x002cc8ac stores 1 at its state byte +0x20 after initialization. The same byte selects the switch at 0x002cc874, whose existing RYNO_STATE_WAIT_ANIMATION case waits for anim_flags bit 2 at 0x002cc8b8-0x002cc8cc. domain_1_value_2 -> RYNO_STATE_READY_TO_FIRE: Retail 0x002cc8b8-0x002cc8cc tests this weapon's animation flags and stores 2 to s3+0x20 when bit 2 is set. That identical state byte selects the existing RYNO_STATE_READY_TO_FIRE case, which gates firing on pressed input, item availability and ammo at 0x002cc8f8-0x002cc924. domain_2_value_4 -> RYNO_STATE_FIRE_SALVO: After pressed-fire, item-lock and use_ammo gates at 0x002cc8f8-0x002cc924, retail 0x002cc9bc-0x002cc9c8 writes 4 into weapon Moby s3+0x20 and clears shot timer, slot and shot count. This is the same selector as existing RYNO_STATE_FIRE_SALVO, which emits timer-spaced rockets at 0x002ccb7c-0x002ccce8. domain_3_value_2 -> RYNO_STATE_READY_TO_FIRE: In the existing RYNO_STATE_READY_TO_FIRE_WITH_RETICLE case, 0x002cca48-0x002cca5c tests held input mask 5 and loads 2 on release, branching to the store at 0x002cceac into weapon Moby s3+0x20. The same state byte dispatches to existing RYNO_STATE_READY_TO_FIRE and its pressed-fire/ammo gates. domain_4_value_4 -> RYNO_STATE_FIRE_SALVO: The reticle-ready branch passes pressed-input, item-lock and ammo gates at 0x002cca60-0x002cca90; 0x002ccb30-0x002ccb48 stores 4 into weapon Moby s3+0x20 and resets shot timer, slot and shots before starting animation. This selector dispatches to existing RYNO_STATE_FIRE_SALVO at 0x002ccb7c, which repeatedly creates rockets. domain_5_value_5 -> RYNO_STATE_COOLDOWN: Retail 0x002cccec-0x002ccd24 compares incremented shots against 7, releases the item switch lock, cancels its animation, and stores 5 into weapon Moby s3+0x20 at 0x002ccd14 while initializing the 60-frame timers. The same state selector's existing RYNO_STATE_COOLDOWN case waits for the shot timer at 0x002cce94-0x002cceac. domain_6_value_2 -> RYNO_STATE_READY_TO_FIRE: The existing RYNO_STATE_COOLDOWN case decrements the shot timer at 0x002cce94-0x002cce9c, then clears target and shots and writes 2 into weapon Moby s3+0x20 at 0x002cceac. This is the same selector dispatched at 0x002cc874, with 2 already canonically named RYNO_STATE_READY_TO_FIRE in the bound C. --- src/overlays/shared/weapons/ryno.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/weapons/ryno.c b/src/overlays/shared/weapons/ryno.c index b7e5f9790a..ed9f13de08 100644 --- a/src/overlays/shared/weapons/ryno.c +++ b/src/overlays/shared/weapons/ryno.c @@ -285,12 +285,12 @@ void ryno_update(struct Moby *ryno_moby) { case RYNO_STATE_INITIALIZE: ryno_vars->target = 0; hero.items[0].switch_lock = 0; - ryno_moby->state = 1; + ryno_moby->state = RYNO_STATE_WAIT_ANIMATION; ryno_vars->track_timer = 0; break; case RYNO_STATE_WAIT_ANIMATION: if (ryno_moby->anim_flags & 2) - ryno_moby->state = 2; + ryno_moby->state = RYNO_STATE_READY_TO_FIRE; break; case RYNO_STATE_READY_TO_FIRE: if (hero.state.current == 1) @@ -312,7 +312,7 @@ void ryno_update(struct Moby *ryno_moby) { s->stat[23].level_mask = s->stat[23].level_mask | (1 << D_0015ED84) | 0x80000000; } hero.items[0].switch_lock = 2; - ryno_moby->state = 4; + ryno_moby->state = RYNO_STATE_FIRE_SALVO; ryno_vars->shot_timer = 0; ryno_vars->slot = 0; ryno_vars->shots = 0; @@ -327,7 +327,7 @@ void ryno_update(struct Moby *ryno_moby) { case RYNO_STATE_READY_TO_FIRE_WITH_RETICLE: suck_draw_reticle(ryno_moby, 0xFF0F0FFF, 1.0f, 0.0f, 0, 0x23, -1, 90.0f, 4); if ((controller_state.held & 5) == 0) { - ryno_moby->state = 2; + ryno_moby->state = RYNO_STATE_READY_TO_FIRE; return; } if ((controller_state.pressed & hero.items[0].button_mask) == 0) @@ -347,7 +347,7 @@ void ryno_update(struct Moby *ryno_moby) { s->stat[23].level_mask = s->stat[23].level_mask | (1 << D_0015ED84) | 0x80000000; } hero.items[0].switch_lock = 2; - ryno_moby->state = 4; + ryno_moby->state = RYNO_STATE_FIRE_SALVO; ryno_vars->shot_timer = 0; ryno_vars->slot = 0; ryno_vars->shots = 0; @@ -396,7 +396,7 @@ void ryno_update(struct Moby *ryno_moby) { if (ryno_vars->shots >= 7) { hero.items[0].switch_lock = 0; cancel_hero_item_animation(); - ryno_moby->state = 5; + ryno_moby->state = RYNO_STATE_COOLDOWN; ryno_vars->shot_timer = scale_game_frames(60); ryno_vars->track_timer = scale_game_frames(60); } @@ -433,7 +433,7 @@ void ryno_update(struct Moby *ryno_moby) { return; ryno_vars->shots = 0; ryno_vars->target = 0; - ryno_moby->state = 2; + ryno_moby->state = RYNO_STATE_READY_TO_FIRE; break; case 6: case 7: From 27c113641151a35606770e9302c0e58e39a3c18d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:49:38 +0000 Subject: [PATCH 1263/1502] decomp: clarify names in update_hero_ground_contact domain_0_value_3 -> GROUND_MATERIAL_SINK_SURFACE_PROBE_THROUGH: Retail 0x002403e0-0x002403f0 stores collision_hit_material into hero+0x12E0, proving the material selector. At 0x002404dc-0x00240520, material 3 stores collision hit Z into hero+0x2F4 (source hero.sink_surface_z), lowers ground_probe_endpoint.z by 0.01, and retries collision_line with mask 4. The supplied same-source material-effects consumer tests selector_3 against sink_surface_z while descending and requests state 0x68 or 0x7B. This proves a sink-surface material probed through for underlying ground, without identifying a particular substance. domain_1_value_11 -> GROUND_MATERIAL_SINK_SURFACE_CONTACT_BYPASS: The collision_hit_material return/store at retail 0x002403e0-0x002403f0 proves hero.ground_type is the collision material domain. At 0x0024052c-0x00240548 material 11 copies collision hit Z into hero+0x2F4 (source hero.sink_surface_z) and branches through 0x00240770 to 0x00240774, bypassing moby/contact point, distance, normal and grounded-counter updates. The supplied same-source material-effects consumer uses selector_11 and sink_surface_z to request state 0x7B for descent below this surface. The name states the proven sink-surface/contact-bypass behavior only. --- .../l05/hero/apply_hero_ground_material_effects.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l05/hero/apply_hero_ground_material_effects.c b/src/overlays/l05/hero/apply_hero_ground_material_effects.c index 7a94088a54..db54499930 100644 --- a/src/overlays/l05/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l05/hero/apply_hero_ground_material_effects.c @@ -172,6 +172,10 @@ void update_hero_ground_contact(void) { enum { GROUND_MATERIAL_SINK_TRIGGER = 0xD }; + enum { + GROUND_MATERIAL_SINK_SURFACE_PROBE_THROUGH = 3, + GROUND_MATERIAL_SINK_SURFACE_CONTACT_BYPASS = 0xB + }; V shared_probe_endpoint, ground_probe_endpoint, ground_vector_scratch, side_probe_endpoint, unused_probe_vector, hit_normal_angles, normalized_hit_normal; f32 f; @@ -239,7 +243,7 @@ void update_hero_ground_contact(void) { goto d1; } } - if (hero.ground_type == 3) { + if (hero.ground_type == GROUND_MATERIAL_SINK_SURFACE_PROBE_THROUGH) { hero.sink_surface_z = D_L05_00174268; ground_probe_endpoint.f[2] = D_L05_00174268 - 0.01f; if (collision_line(&ground_probe_endpoint, &shared_probe_endpoint, 4, (s32)hero.moby, 0) == @@ -247,7 +251,7 @@ void update_hero_ground_contact(void) { goto d1; } } - if (hero.ground_type == 0xB) { + if (hero.ground_type == GROUND_MATERIAL_SINK_SURFACE_CONTACT_BYPASS) { hero.sink_surface_z = D_L05_00174268; goto d1; } From 7c5130323a67bf5453a0000b2e2abc1c00610417 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:51:15 +0000 Subject: [PATCH 1264/1502] decomp: clarify names in metal_detector_update domain_0_value_1 -> METAL_DETECTOR_ACTIVE: The assigned source already declares METAL_DETECTOR_ACTIVE = 1 for this exact moby->state switch. Retail 0x002d2fd8 loads 1 and 0x002d2fe0 stores it to byte +0x20 of s5, the same detector moby whose selector is loaded at 0x002d2f48. Original Ghidra case 0 performs this assignment after initialization; cases 1/2 enter tracking at 0x002d2fe4. Reuse the existing canonical local member for the assignment. domain_1_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 0x002d3414 loads hero.metal_detector_target into a0, checks class at +0xa6, then 0x002d342c loads that Moby's state byte at +0x20; 0x002d3430-0x002d3434 rejects 0xFE before collection. Original Ghidra expresses this as target +0x20 == -2. Supplied mark_moby_for_removal source assigns MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE to this same struct Moby state field when moby >= moby_instance_end. The assigned function calls that removal operation on hero.metal_detector_target at 0x002d357c-0x002d3580 after draining its count, proving the generic Moby removal-state domain rather than a hero/control domain. domain_2_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 0x002d3414 loads hero.metal_detector_target into a0 and 0x002d342c reads its +0x20 Moby state byte; 0x002d3438-0x002d343c rejects 0xFD before collection. Original Ghidra expresses this same target-state test as == -3. Supplied mark_moby_for_removal source assigns MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD to struct Moby.state for moby < moby_instance_end. The target is passed to mark_moby_for_removal at 0x002d357c-0x002d3580 after count drainage. These are the same generic Moby removal sentinels, with the allocation-side distinction proved by the supplied writer source. --- src/overlays/shared/weapons/metal_detector.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/metal_detector.c b/src/overlays/shared/weapons/metal_detector.c index bb21070aff..5e4ad28986 100644 --- a/src/overlays/shared/weapons/metal_detector.c +++ b/src/overlays/shared/weapons/metal_detector.c @@ -229,6 +229,10 @@ void metal_detector_update(struct Moby *moby) { METAL_DETECTOR_ACTIVE = 1, METAL_DETECTOR_TRACK_AND_COLLECT = 2 }; + enum { + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE + }; Vars2d2ee8 *metal_detector_vars; struct Moby *target_moby; TargetVars2d2ee8 *tv; @@ -268,7 +272,7 @@ void metal_detector_update(struct Moby *moby) { metal_detector_vars->unk28 = 0; qzero(&D_L00_001E1160); attach_manipulator(moby, 3, &D_L00_001E1160); - moby->state = 1; + moby->state = METAL_DETECTOR_ACTIVE; break; case 3: case 4: @@ -369,7 +373,7 @@ void metal_detector_update(struct Moby *moby) { } target_moby = hero.metal_detector_target; if (target_moby != 0 && target_moby->oclass == 0x25D && - target_moby->state != 0xFE && target_moby->state != 0xFD && + target_moby->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && target_moby->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && hero.detector_target_dist < 1.0f) { tv = (TargetVars2d2ee8 *)target_moby->pvars; while (tv->count > 0) { From d8476a662aeec7fa5dea1bd0353240b5fcc1322c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:52:56 +0000 Subject: [PATCH 1265/1502] decomp: clarify names in update_spawner_bomb domain_0_value_1 -> SPAWNER_BOMB_STATE_SPAWN_CHILD: Retail 002c4934..002c4958 tests the damped motion vector length against 0.025 and stores 1 to the same moby state byte +0x20 dispatched at 002c4770..002c4778. That dispatch reaches ground placement and revive_spawner_pooled_child at 002c4d94..002c4dd8, proving reuse of the existing local SPAWNER_BOMB_STATE_SPAWN_CHILD. domain_1_value_1 -> SPAWNER_BOMB_STATE_SPAWN_CHILD: Retail sphere-collision path 002c4b14..002c4b40 tests damped velocity length below 0.025 and stores 1 to moby+0x20. The identical state selector at 002c4770..002c4778 enters ground placement and pooled-child revival at 002c4d94..002c4dd8, the existing SPAWNER_BOMB_STATE_SPAWN_CHILD branch. domain_2_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 002c4c18..002c4c58 traverses the Moby list through +0x28 and reads each neighbor's actual state byte at +0x20, skipping 0xfe before position repulsion. Supplied mark_moby_for_removal assigns MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END=0xFE to this same struct Moby state field for mobys at or above moby_instance_end; this is the removal sentinel domain. domain_3_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 002c4c50..002c4c5c reads the linked neighbor Moby's state byte +0x20 and skips 0xfd before applying position repulsion. Supplied mark_moby_for_removal writes MOBY_STATE_REMOVAL_BELOW_INSTANCE_END=0xFD to struct Moby.state for mobys below moby_instance_end, proving the removal-state meaning of this comparison. domain_4_value_2 -> SPAWNER_BOMB_STATE_SHRINKING: Retail 002c4cd8..002c4ce8 decrements the timer at pvars+0x14 and on expiry writes 2 to moby+0x20. State dispatch 002c479c sends that same byte value to 002c4de8, which reduces bomb scale and optionally grows the held child, exactly the existing local SPAWNER_BOMB_STATE_SHRINKING branch; expiry need not create a child. domain_5_value_2 -> SPAWNER_BOMB_STATE_SHRINKING: Retail 002c4dd0..002c4de4 calls revive_spawner_pooled_child, saves its returned child at pvars+0x18, and writes 2 to the bomb's state byte +0x20. The same byte is dispatched at 002c479c to bomb shrinkage and optional held-child growth at 002c4de8..002c4e3c, proving reuse of SPAWNER_BOMB_STATE_SHRINKING. domain_6_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Retail 002c4dd8 stores the revived struct Moby child at pvars+0x18; 002c4e8c..002c4e9c reloads that child, reads its state byte +0x20 and removes the shrinking bomb when it is 0xfe. Supplied mark_moby_for_removal writes MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END=0xFE to that same Moby state field, proving the removal sentinel rather than a bomb-local state. domain_7_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Retail 002c4e8c..002c4ea4 reloads the child stored from revive_spawner_pooled_child at pvars+0x18, reads its actual Moby state byte +0x20, and branches to bomb removal when it equals 0xfd. Supplied mark_moby_for_removal assigns MOBY_STATE_REMOVAL_BELOW_INSTANCE_END=0xFD to that same field for below-instance-end mobys, establishing the removal-state domain. --- src/overlays/shared/enemies/bomb_spawner_bomb.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/enemies/bomb_spawner_bomb.c b/src/overlays/shared/enemies/bomb_spawner_bomb.c index bbe425eb94..a4b47f2ce2 100644 --- a/src/overlays/shared/enemies/bomb_spawner_bomb.c +++ b/src/overlays/shared/enemies/bomb_spawner_bomb.c @@ -191,7 +191,7 @@ void bomb_spawner_bomb_update(struct Moby *moby) __asm__("FUN_L03_002c4718"); /* Drifts and bounces off walls (state 0), lands and spawns its child moby (1), then shrinks while the child grows (2). */ /* Moby class 545 */ void bomb_spawner_bomb_update(struct Moby *moby) { - enum { SPAWNER_BOMB_STATE_MOVING = 0 , SPAWNER_BOMB_STATE_SPAWN_CHILD = 1 , SPAWNER_BOMB_STATE_SHRINKING = 2 } ;float *bomb_runtime; + enum { SPAWNER_BOMB_STATE_MOVING = 0 , SPAWNER_BOMB_STATE_SPAWN_CHILD = 1 , SPAWNER_BOMB_STATE_SHRINKING = 2 } ; enum { MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xfd , MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xfe} ;float *bomb_runtime; Vec4 *pos; struct Moby *other; Vec4 old_pos; @@ -234,7 +234,7 @@ void bomb_spawner_bomb_update(struct Moby *moby) { collision_hit_material() == -1) { fast_vec_scale(bomb_runtime, bomb_runtime, 0.5f); if (fast_vec_length(bomb_runtime) < 0.025f) { - moby->state = 1; + moby->state = SPAWNER_BOMB_STATE_SPAWN_CHILD; goto first_collision_timer; } } @@ -264,7 +264,7 @@ void bomb_spawner_bomb_update(struct Moby *moby) { collision_hit_material() == -1) { fast_vec_scale(bomb_runtime, bomb_runtime, 0.5f); if (fast_vec_length(bomb_runtime) < 0.025f) - moby->state = 1; + moby->state = SPAWNER_BOMB_STATE_SPAWN_CHILD; } } else if (((struct Moby *)D_L03_00173F40.moby)->oclass != 0x221) { reflect_vector(bomb_runtime, bomb_runtime, &D_L03_00173F40.normal_x); @@ -281,7 +281,7 @@ void bomb_spawner_bomb_update(struct Moby *moby) { } } for (other = D_L03_0015FFE4; other != NULL; other = other->next) { - if (other == moby || (int)other == 0 || other->state == 0xfe || other->state == 0xfd) + if (other == moby || (int)other == 0 || other->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || other->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) continue; fast_vec_sub(&delta, (Vec4 *)&moby->pos, &other->pos); delta.f[2] = 0.0f; @@ -292,7 +292,7 @@ void bomb_spawner_bomb_update(struct Moby *moby) { } } if (fast_dec_timer_s16(bomb_runtime + 5)) - moby->state = 2; + moby->state = SPAWNER_BOMB_STATE_SHRINKING; moby->rot.x = normalize_angle(bomb_runtime[0]); moby->rot.y = normalize_angle(bomb_runtime[1]); moby->collision_disable = old_disable; @@ -311,7 +311,7 @@ void bomb_spawner_bomb_update(struct Moby *moby) { next_pos.q = *(u128 *)pos; *(struct Moby **)(bomb_runtime + 6) = revive_spawner_pooled_child(*(struct Moby **)(bomb_runtime + 4), &next_pos, -1); - moby->state = 2; + moby->state = SPAWNER_BOMB_STATE_SHRINKING; break; } case SPAWNER_BOMB_STATE_SHRINKING: { @@ -324,7 +324,7 @@ void bomb_spawner_bomb_update(struct Moby *moby) { if (moby->scale < moby->pclass->scale * (frame_scale * 0.05f)) { moby->scale = 0.0001f; other = *(struct Moby **)(bomb_runtime + 6); - if (other == NULL || other->state == 0xfe || other->state == 0xfd || + if (other == NULL || other->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || other->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END || !(*(int *)(bomb_runtime + 7) & 4) || other->pclass->scale - 0.01f <= other->scale) goto remove_moby; } From d3af9def14da01fbbe08aa605b06c82e35053596 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:54:41 +0000 Subject: [PATCH 1266/1502] decomp: clarify names in mine_glove_update domain_0_value_2 -> MINE_GLOVE_IDLE: At 002c2280 initialization clears held; 002c2284..002c2298 tests glove anim_flags bit 2 and stores 2 into 0x20(s5) when animation waiting is unnecessary. s5 is the assigned moby (002c1adc), and 002c2258 loads that same byte as the local glove switch selector. Source state 2 has no specialized switch action, the passive idle successor also reached after post-release waiting. domain_1_value_2 -> MINE_GLOVE_IDLE: The MINE_GLOVE_WAIT_FOR_ANIMATION branch at 002c229c..002c22b0 tests 0x70(s5) bit 2 and stores 2 to the exact glove switch selector 0x20(s5) on completion of the wait. In the authoritative switch, 2 has no specialized action; it is the same passive idle phase selected by initialization and by completion of post-release waiting, rather than a hero state or controller domain. domain_2_value_2 -> MINE_GLOVE_IDLE: At 002c23a0..002c23c4 the MINE_GLOVE_POST_RELEASE_WAIT branch retains state 4 while hero current state is 0x23 or item animation is active, then stores 2 to 0x20(s5), the glove's own selector loaded at 002c2258. This returns to the same passive idle phase reached after initial animation waiting; source switch state 2 has no specialized action, while common aiming and reacquisition continue. --- src/overlays/shared/weapons/mine_glove.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/weapons/mine_glove.c b/src/overlays/shared/weapons/mine_glove.c index 81c9d0fd6b..673046b156 100644 --- a/src/overlays/shared/weapons/mine_glove.c +++ b/src/overlays/shared/weapons/mine_glove.c @@ -142,6 +142,9 @@ void mine_glove_update(struct Moby *moby) { MINE_GLOVE_BEGIN_HELD_MOBY_REMOVAL = 5, MINE_GLOVE_REMOVE_HELD_MOBY = 6 }; + enum { + MINE_GLOVE_IDLE = 2 + }; GloveVars *mine_glove_vars; Vec4 saved, offset, rotatedOffset; Vec4 local[4]; @@ -276,10 +279,10 @@ void mine_glove_update(struct Moby *moby) { if (!(moby->anim_flags & 2)) moby->state = MINE_GLOVE_WAIT_FOR_ANIMATION; else - moby->state = 2; + moby->state = MINE_GLOVE_IDLE; case MINE_GLOVE_WAIT_FOR_ANIMATION: if (moby->anim_flags & 2) - moby->state = 2; + moby->state = MINE_GLOVE_IDLE; break; case MINE_GLOVE_RELEASE_HELD_MOBY: if (mine_glove_vars->held != 0) { @@ -306,7 +309,7 @@ void mine_glove_update(struct Moby *moby) { break; case MINE_GLOVE_POST_RELEASE_WAIT: if (hero.state.current != 0x23 && !hero.item_anim_active) - moby->state = 2; + moby->state = MINE_GLOVE_IDLE; break; case MINE_GLOVE_BEGIN_HELD_MOBY_REMOVAL: moby->state = MINE_GLOVE_REMOVE_HELD_MOBY; From 7a9e5e077b0080749f32cf09dc3e8d3578466fad Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:56:53 +0000 Subject: [PATCH 1267/1502] decomp: clarify names in update_beam_barrier domain_0_value_1 -> BEAM_BARRIER_ACTIVE: Retail 002f6480 retains the input moby in s3; 002f64b4 reads its state byte at +0x20 and 002f64b8 dispatches value 1 to 002f6554 (voice, strand, collision and linked-completion updates). Initialization stores 1 to that identical +0x20 field at 002f6540. The bound C already names this selector's value 1 BEAM_BARRIER_ACTIVE, proving canonical reuse for the assignment. domain_2_value_2 -> BEAM_BARRIER_EMIT_SPARK_BURST: After the four linked-moby checks, retail 002f6aac loads 2, 002f6ab0 disables this moby's collision and 002f6ab4 stores 2 at +0x20(s3), the same field dispatched at 002f64b4/002f64dc. That branch starts at 002f6bb0 and emits nine groups of twenty particles through 002f6d74. Bound C already names this exact switch domain's value 2 BEAM_BARRIER_EMIT_SPARK_BURST. domain_3_value_3 -> BEAM_BARRIER_REMOVE: After the nine-by-twenty particle loop, retail 002f6d78 loads 3 and 002f6d80 stores it to +0x20(s3). This is the original moby's state read at 002f64b4; its value 3 dispatches at 002f64e4 to 002f6d84, which calls mark_moby_for_removal with that same moby. Bound C already names this switch value BEAM_BARRIER_REMOVE, proving reuse for the transition assignment. --- src/overlays/l06/mobys/beam_barrier.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l06/mobys/beam_barrier.c b/src/overlays/l06/mobys/beam_barrier.c index 571bcce97d..1e0b52930b 100644 --- a/src/overlays/l06/mobys/beam_barrier.c +++ b/src/overlays/l06/mobys/beam_barrier.c @@ -135,7 +135,7 @@ void beam_barrier_update(struct Moby *moby) { D_L06_00161E40[3] = 0x22; D_L06_00161E40[0] = 0; beam_barrier_control_vars->voice = -1; - moby->state = 1; + moby->state = BEAM_BARRIER_ACTIVE; moby->flags = moby->flags | 0x4000; return; } @@ -257,7 +257,7 @@ void beam_barrier_update(struct Moby *moby) { if (!all_done) return; moby->collision = 0; - moby->state = 2; + moby->state = BEAM_BARRIER_EMIT_SPARK_BURST; { int voice = beam_barrier_control_vars->voice; if (voice != -1) { @@ -329,7 +329,7 @@ void beam_barrier_update(struct Moby *moby) { } while (spark >= 0); segment = next_segment; } while (segment < 9); - moby->state = 3; + moby->state = BEAM_BARRIER_REMOVE; return; } case BEAM_BARRIER_REMOVE: From d1828916366c065169f1719d8464e3e654e282d3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:56:53 +0000 Subject: [PATCH 1268/1502] decomp: clarify names in handle_hero_gadget_button domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00240f34 establishes a0=&hero; 0x00240f38 loads the byte at hero+0x20a4, mapped by the authoritative source to hero.vehicle_mode. 0x00240f3c branches on zero to continue equipped-item processing, while nonzero returns 0 at 0x00240f44-0x00240f48. This is the HeroVehicleMode selector, not state.current or control_mode. The supplied shared include/rnc/hero/hero_state.h HeroVehicleMode member HERO_VEHICLE_MODE_ON_FOOT=0 canonically names this no-vehicle mode. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: In ITEM_VEHICLE_MODE_TOGGLE, retail 0x002413cc establishes s0=&hero and 0x002413d0 loads hero+0x20a4, the same hero.vehicle_mode byte used by the entry guard at 0x00240f38. 0x002413d4 rejects nonzero mode before can_select_hero_item_31 at 0x002413dc; the successful path requests the vehicle toggle via +0x22dc/+0x22de at 0x00241450-0x00241458. The supplied canonical HeroVehicleMode enum names zero HERO_VEHICLE_MODE_ON_FOOT, matching this on-foot prerequisite. --- src/overlays/l01/hero/hero_set_state.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l01/hero/hero_set_state.c b/src/overlays/l01/hero/hero_set_state.c index 761dffdf6e..36e83d8889 100644 --- a/src/overlays/l01/hero/hero_set_state.c +++ b/src/overlays/l01/hero/hero_set_state.c @@ -1624,7 +1624,7 @@ int handle_hero_gadget_button(void) { if (hero.item_use_locked != 0 && (hero.items[0].item_id != 8 || hero.unk308 != 1)) return 0; - if (hero.vehicle_mode != 0) + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) return 0; if (hero.items[0].moby == 0) return 0; @@ -1702,7 +1702,7 @@ int handle_hero_gadget_button(void) { } break; case ITEM_VEHICLE_MODE_TOGGLE: - if (hero.vehicle_mode == 0 && can_select_hero_item_31() != 0 && + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT && can_select_hero_item_31() != 0 && pad_pressed_within(buttons, scale_game_frames(7), 0) != 0 && D_00141660 == 0x1f && hero.items[0].moby->oclass == 0x1e3 && hero.vehicle_toggle_timer == 0) { allocate_hero_voice_for_entry(0x18, 0); From 6c242b14a8028be75b9024600c0f7b668537678d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:58:39 +0000 Subject: [PATCH 1269/1502] decomp: clarify names in update_mine domain_0_value_254 -> MOBY_STATE_MARKED_FOR_REMOVAL: Target is loaded from MineVars+0x68 at 0x002cc080; lbu 0x20(a1) at 0x002cc08c supplies target_moby->state and comparison against 0xFE at 0x002cc090 excludes homing. Checked level-03 direct helper mark_moby_for_removal (0x0023d6d8, evidence request 824a581d92d64eb48b76cce460ea3c49) sets v0=0xFE at 0x0023d6fc and stores it into the same moby state offset +0x20 at 0x0023d700. The helper is called on this mine after explosion at 0x002cc764 and after shrink at 0x002cc7d8. Thus 0xFE denotes a moby marked for removal; this does not claim it is the only removal state or establish its allocation category. --- src/overlays/l03/mobys/mine.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l03/mobys/mine.c b/src/overlays/l03/mobys/mine.c index 8585221da4..96659b9fb4 100644 --- a/src/overlays/l03/mobys/mine.c +++ b/src/overlays/l03/mobys/mine.c @@ -66,6 +66,9 @@ void mine_layer_mine_update(struct Moby *mine_moby) { MINE_DEBRIS_RANDOM_PALETTE_COLOR = 2, MINE_DEBRIS_SPHERICAL_VELOCITY = 3 }; + enum { + MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE + }; MineBlast blast = l03_mine_camera_blast_template; MineVec vector_scratch; MineVars *mine_vars = (MineVars *)mine_moby->pvars; @@ -106,7 +109,7 @@ void mine_layer_mine_update(struct Moby *mine_moby) { case MINE_ARM_AND_MONITOR_PROXIMITY: fast_dec_timer(&mine_vars->timer); target_moby = mine_vars->target; - if (target_moby != 0 && target_moby->state != 0xFE && target_moby->state != 0xFD && + if (target_moby != 0 && target_moby->state != MOBY_STATE_MARKED_FOR_REMOVAL && target_moby->state != 0xFD && vector_distance_xy(&mine_moby->pos, &target_moby->pos) < 3.0f && mine_vars->timer == 0) { mine_moby->state = MINE_HOME_ON_TARGET; From 5b87c315235915af11dce82333b80df528dc9763 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:58:39 +0000 Subject: [PATCH 1270/1502] decomp: clarify names in screamer_update domain_0_value_1 -> SCREAMER_STATE_WAIT_FOR_ACTIVATION: Original retail 002df280 retains the moby in s1; 002df310 reads its state byte at +0x20 for this function's switch. The authoritative C declares the destination member in this same screamer-state enum. 002df38c..002df398 writes 1 to +0x20 after home/goal initialization when pvars+0x174 equals 1; case 1 waits on the activation gate before entering state 2. domain_10_value_9 -> SCREAMER_STATE_WAIT_TO_WANDER: Original retail 002df280 retains the moby in s1; 002df310 reads its state byte at +0x20 for this function's switch. The authoritative C declares the destination member in this same screamer-state enum. 002dfb68..002dfb88 detects a blocked candidate wander step, clears step and writes 9 to +0x20. Destination 002dfa28 waits on wander_timer before choosing the next random wander goal. domain_11_value_9 -> SCREAMER_STATE_WAIT_TO_WANDER: Original retail 002df280 retains the moby in s1; 002df310 reads its state byte at +0x20 for this function's switch. The authoritative C declares the destination member in this same screamer-state enum. 002dfb94..002dfbb8 tests step vector length against zero and writes 9 to +0x20 on zero length. Destination case 9 waits on wander_timer before generating the next home-relative goal. domain_1_value_2 -> SCREAMER_STATE_WAIT_TO_RISE: Original retail 002df280 retains the moby in s1; 002df310 reads its state byte at +0x20 for this function's switch. The authoritative C declares the destination member in this same screamer-state enum. 002df3ac..002df3d4 releases the activation gate and stores 2 to +0x20; destination case 2 at 002df3f0 waits for animation flag bit 2 before rising. domain_2_value_4 -> SCREAMER_STATE_RISE_FROM_HOME: Original retail 002df280 retains the moby in s1; 002df310 reads its state byte at +0x20 for this function's switch. The authoritative C declares the destination member in this same screamer-state enum. 002df3f0..002df408 gates on animation bit 2 and stores 4 to +0x20 while clearing velocity. Destination 002df424..002df494 advances pos.z toward home.z+2. domain_3_value_5 -> SCREAMER_STATE_FOLLOW_PATH: Original retail 002df280 retains the moby in s1; 002df310 reads its state byte at +0x20 for this function's switch. The authoritative C declares the destination member in this same screamer-state enum. 002df470..002df494 stores 5 to +0x20 when the rise scalar completes. Destination 002df498 onward indexes path/node fields +0x150/+0x158 and moves toward that waypoint. domain_4_value_6 -> SCREAMER_STATE_FACE_LEADER_AT_WAYPOINT: Original retail 002df280 retains the moby in s1; 002df310 reads its state byte at +0x20 for this function's switch. The authoritative C declares the destination member in this same screamer-state enum. 002df64c..002df694 advances the arrived node index and writes 6 to +0x20 when its marker is positive. Destination 002df724..002df784 turns toward leader loaded from pvars+0x100. domain_5_value_10 -> SCREAMER_STATE_WANDER: Original retail 002df280 retains the moby in s1; 002df310 reads its state byte at +0x20 for this function's switch. The authoritative C declares the destination member in this same screamer-state enum. 002df6b0..002df6cc compares the advanced node index with path count and writes 10 to +0x20 at path completion, then initializes home and wander_goal. Destination 002dfabc onward steps toward wander_goal. domain_6_value_10 -> SCREAMER_STATE_WANDER: Original retail 002df280 retains the moby in s1; 002df310 reads its state byte at +0x20 for this function's switch. The authoritative C declares the destination member in this same screamer-state enum. 002df7f8..002df824 writes 10 to +0x20 after the leader-facing waypoint action when node_index equals path count; 002df844..002df878 initializes home/wander_goal for destination wander movement. domain_7_value_5 -> SCREAMER_STATE_FOLLOW_PATH: Original retail 002df280 retains the moby in s1; 002df310 reads its state byte at +0x20 for this function's switch. The authoritative C declares the destination member in this same screamer-state enum. 002df80c branches to 002df884 when more path nodes remain; v0=5 from 002df810 is stored to +0x20 at 002df890, resuming the existing path-following switch branch. domain_8_value_7 -> SCREAMER_STATE_IDLE_AT_HOME: Original retail 002df280 retains the moby in s1; 002df310 reads its state byte at +0x20 for this function's switch. The authoritative C declares the destination member in this same screamer-state enum. 002df9f8..002dfa24 measures XY distance to home and writes 7 to +0x20 when below 2.0. The same selector's existing IDLE_AT_HOME case performs no state-specific work. domain_9_value_10 -> SCREAMER_STATE_WANDER: Original retail 002df280 retains the moby in s1; 002df310 reads its state byte at +0x20 for this function's switch. The authoritative C declares the destination member in this same screamer-state enum. 002dfa28..002dfab8 waits for wander_timer, creates a random offset added to home into wander_goal (+0x140), then stores 10 to +0x20 to enter the existing goal-stepping wander branch. --- src/overlays/l10/mobys/screamer.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/overlays/l10/mobys/screamer.c b/src/overlays/l10/mobys/screamer.c index d2a5dbab34..68f7aa1e37 100644 --- a/src/overlays/l10/mobys/screamer.c +++ b/src/overlays/l10/mobys/screamer.c @@ -127,20 +127,20 @@ void screamer_update(Moby *moby) { if (screamer_data->f174 != 1) { mark_moby_for_removal(moby); } else { - moby->state = 1; + moby->state = SCREAMER_STATE_WAIT_FOR_ACTIVATION; } break; case SCREAMER_STATE_WAIT_FOR_ACTIVATION: if (screamer_data->f104 == 2 && screamer_data->f174 != 0) break; - moby->state = 2; + moby->state = SCREAMER_STATE_WAIT_TO_RISE; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); break; case SCREAMER_STATE_WAIT_TO_RISE: if ((moby->anim_flags & 2) == 0) break; - moby->state = 4; + moby->state = SCREAMER_STATE_RISE_FROM_HOME; clear_u64_value(&screamer_data->vel); if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); @@ -155,7 +155,7 @@ void screamer_update(Moby *moby) { D_0015ED70 * 18.0f, D_0015ED70 * 18.0f, D_0015ED6C * 6.0f) == 0.0f) { - moby->state = 5; + moby->state = SCREAMER_STATE_FOLLOW_PATH; } break; case SCREAMER_STATE_FOLLOW_PATH: { @@ -191,13 +191,13 @@ void screamer_update(Moby *moby) { { int node_index = screamer_data->node_index++; if (0.0f < l10_paths[screamer_data->path]->points[node_index].f[3]) { - moby->state = 6; + moby->state = SCREAMER_STATE_FACE_LEADER_AT_WAYPOINT; if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } else { if (node_index + 1 != l10_paths[screamer_data->path]->count) break; - moby->state = 10; + moby->state = SCREAMER_STATE_WANDER; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); probe_ground_height(&moby->pos, 0, 0.5f); @@ -230,14 +230,14 @@ void screamer_update(Moby *moby) { activate_waiting_moby_group_members(linked); } if (screamer_data->node_index == l10_paths[screamer_data->path]->count) { - moby->state = 10; + moby->state = SCREAMER_STATE_WANDER; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); probe_ground_height(&moby->pos, 0, 0.5f); qcopy(&screamer_data->home, &D_L10_00174360_2E0630); qcopy(&screamer_data->wander_goal, &moby->pos); } else { - moby->state = 5; + moby->state = SCREAMER_STATE_FOLLOW_PATH; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); } @@ -267,7 +267,7 @@ void screamer_update(Moby *moby) { screamer_data->vel.z = climb; func_L00_00259B08_2E0630(moby, &screamer_data->vel, 0.5f, 0x200, 0.0f, 0); if (vector_distance_xy(&moby->pos, &screamer_data->home) < 2.0f) - moby->state = 7; + moby->state = SCREAMER_STATE_IDLE_AT_HOME; break; } case SCREAMER_STATE_WAIT_TO_WANDER: { @@ -285,7 +285,7 @@ void screamer_update(Moby *moby) { waypoint[2] = zero; waypoint[2] = random_float_between(5.0f, 7.0f); fast_vec_add(&screamer_data->wander_goal, waypoint, &screamer_data->home); - moby->state = 10; + moby->state = SCREAMER_STATE_WANDER; break; } case SCREAMER_STATE_WANDER: @@ -301,12 +301,12 @@ void screamer_update(Moby *moby) { fast_vec_add(waypoint, &screamer_data->step, &moby->pos); if (func_L00_001F10E0_2E0630(0.4f, waypoint, 0, moby)) { clear_u64_value(&screamer_data->step); - moby->state = 9; + moby->state = SCREAMER_STATE_WAIT_TO_WANDER; } else { qcopy(&moby->pos, waypoint); } if (fast_vec_length(&screamer_data->step) == 0.0f) - moby->state = 9; + moby->state = SCREAMER_STATE_WAIT_TO_WANDER; break; case SCREAMER_STATE_DEATH_KNOCKBACK: if ((step_moby_motion(moby, screamer_data->react) & 1) == 0) From 5501e9a8d3d8c6a58f09b790fbe12ccc319a5818 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:58:39 +0000 Subject: [PATCH 1271/1502] decomp: clarify names in bomb_glove_update domain_1_value_2 -> BOMB_GLOVE_READY: The original a0 moby is retained in s3 at 0x002c26d4; its +0x20 byte is the switch selector at 0x002c2fa8. Initialization clears held at 0x002c2fd0, then stores 2 at 0x002c2fe8 when anim_flags bit 2 is set, otherwise entering BOMB_GLOVE_WAIT_FOR_ANIMATION=1. State 2 has no switch action and is the stable ready state before input/timing consumes ammo and enters RELEASE_HELD_MOBY at 0x002c28cc-0x002c28dc. This is the glove state domain, not a hero or control enum. domain_2_value_2 -> BOMB_GLOVE_READY: In BOMB_GLOVE_WAIT_FOR_ANIMATION=1, retail 0x002c2fec-0x002c3000 reads original moby s3+0x70, tests animation flag bit 2 and stores 2 into s3+0x20 when it becomes set. This is exactly the switch selector loaded at 0x002c2fa8 and the same stable destination selected by initialization. Therefore reuse BOMB_GLOVE_READY=2 in the function-local glove state domain. domain_3_value_2 -> BOMB_GLOVE_READY: After release clears held and enters BOMB_GLOVE_POST_RELEASE_WAIT=4 at 0x002c30cc-0x002c30dc, retail 0x002c30e0-0x002c3108 waits until hero.state.current differs from 0x23 and hero.item_anim_active is zero, then stores 2 into original glove s3+0x20. This returns to the same stable ready destination reached after initialization/animation wait, with no state-2 switch action. Reuse BOMB_GLOVE_READY=2; the hero fields are conditions, not the assigned selector. --- src/overlays/shared/weapons/bomb_glove.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/weapons/bomb_glove.c b/src/overlays/shared/weapons/bomb_glove.c index fb8958e850..30045edcfd 100644 --- a/src/overlays/shared/weapons/bomb_glove.c +++ b/src/overlays/shared/weapons/bomb_glove.c @@ -168,6 +168,9 @@ void bomb_glove_update(struct Moby *moby) { BOMB_GLOVE_BEGIN_HELD_MOBY_REMOVAL = 5, BOMB_GLOVE_REMOVE_HELD_MOBY = 6 }; + enum { + BOMB_GLOVE_READY = 2 + }; CarrierVars_2c26c8 *bomb_glove_vars; OvlVec4 local[4], saved, offset, rotatedOffset, pos, target, basis[3], matrix[4]; OvlVec4 launch; @@ -341,10 +344,10 @@ void bomb_glove_update(struct Moby *moby) { if (!(moby->anim_flags & 2)) moby->state = BOMB_GLOVE_WAIT_FOR_ANIMATION; else - moby->state = 2; + moby->state = BOMB_GLOVE_READY; case BOMB_GLOVE_WAIT_FOR_ANIMATION: if (moby->anim_flags & 2) - moby->state = 2; + moby->state = BOMB_GLOVE_READY; break; case BOMB_GLOVE_RELEASE_HELD_MOBY: if (bomb_glove_vars->held == 0) { @@ -370,7 +373,7 @@ void bomb_glove_update(struct Moby *moby) { break; case BOMB_GLOVE_POST_RELEASE_WAIT: if (hero.state.current != 0x23 && !hero.item_anim_active) - moby->state = 2; + moby->state = BOMB_GLOVE_READY; break; case BOMB_GLOVE_BEGIN_HELD_MOBY_REMOVAL: moby->state = BOMB_GLOVE_REMOVE_HELD_MOBY; From f3c3c2028cf65c4162edc0342fe2430a19047243 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 22:58:40 +0000 Subject: [PATCH 1272/1502] decomp: clarify names in bolt_thief_update domain_0_value_3 -> BOLT_PICKUP_CONTROLLED_BY_THIEF: The source list builder selects class 0x279 pickups, not hero or thief objects. Retail 0x002e2eb0-0x002e2ed8 traverses pvars+0x158 and compares each pickup byte +0x20 with 3 before resetting it to 1 on thief knockback. The same pickup byte is set to 3 at 0x002e3244 immediately before the thief's joint-pulling phase, which directly updates pickup positions at 0x002e32c8-0x002e3304. Thus 3 denotes pickups under thief control; its comparison and assignment share this pickup domain. domain_3_value_3 -> BOLT_PICKUP_CONTROLLED_BY_THIEF: Retail 0x002e321c refreshes the class-0x279 target list; 0x002e3230-0x002e3244 loads each listed pickup and writes 3 to its +0x20 state after the signed-state eligibility test. The thief then enters its own separate state 4 at 0x002e3264. In that phase 0x002e32c8 obtains thief joint 0, 0x002e32dc subtracts pickup position and 0x002e3300 adds the pull displacement directly to pickup position. This proves pickup state 3 is controlled by the thief, distinct from thief state 3. domain_5_value_4 -> BOLT_PICKUP_COLLECTION_TRIGGERED: Retail 0x002e331c compares the joint-pull displacement length against twice the frame scalar; on reaching the threshold 0x002e332c writes 4 to the listed class-0x279 pickup state, 0x002e3330 clears its target-list slot, and 0x002e3334-0x002e333c increments the thief collection count. Bounded checked direct helper 0x002afcf0, called with the same pickup objects at 0x002e349c, rejects already-state-4 pickups at 0x002afd2c-0x002afd3c, stores the attraction target at pvars+0x60 (0x002afe68), initializes motion and sets pickup state 4 at 0x002afee8. Together these prove collection is triggered, without claiming immediate removal or completed award. --- src/overlays/l08/mobys/bolt_thief.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/l08/mobys/bolt_thief.c b/src/overlays/l08/mobys/bolt_thief.c index 14f66aafba..0509637b22 100644 --- a/src/overlays/l08/mobys/bolt_thief.c +++ b/src/overlays/l08/mobys/bolt_thief.c @@ -109,6 +109,10 @@ void bolt_thief_update(struct Moby *moby) { BOLT_THIEF_FACE_HERO = 7, BOLT_THIEF_KNOCKBACK = 8 }; + enum { + BOLT_PICKUP_CONTROLLED_BY_THIEF = 3, + BOLT_PICKUP_COLLECTION_TRIGGERED = 4 + }; Vec4 point; Vec4 step; BoltThiefVars *bolt_thief_instance_vars; @@ -127,7 +131,7 @@ void bolt_thief_update(struct Moby *moby) { for (i = 0; i < 0x32; i++) { struct Moby *other = bolt_thief_instance_vars->list[i]; - if (other != 0 && other->state == 3) { + if (other != 0 && other->state == BOLT_PICKUP_CONTROLLED_BY_THIEF) { other->state = 1; } } @@ -222,7 +226,7 @@ void bolt_thief_update(struct Moby *moby) { struct Moby *other = bolt_thief_instance_vars->list[i]; if (other != 0 && (signed char)other->state >= 0) { - other->state = 3; + other->state = BOLT_PICKUP_CONTROLLED_BY_THIEF; } } moby->state = BOLT_THIEF_PULL_PICKUPS_TO_JOINT; @@ -247,7 +251,7 @@ void bolt_thief_update(struct Moby *moby) { FUN_L00_0025f730(&point, D_0015ED6C * 4.0f); fast_vec_add(&other->pos, &other->pos, &point); if (fast_vec_length(&point) < 2.0f * D_0015ED6C) { - other->state = 4; + other->state = BOLT_PICKUP_COLLECTION_TRIGGERED; bolt_thief_instance_vars->list[i] = 0; bolt_thief_instance_vars->w22C++; } From be0294688d2df31c455153d80b60e4bbb29071ad Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:00:21 +0000 Subject: [PATCH 1273/1502] decomp: clarify names in taxi_update domain_0_value_2 -> TAXI_STATE_HIDDEN: Retail 0x002f06a0-0x002f06c8 finds the group moby by target tag at taxi pvars+0xB6, stores 2 to returned moby+0x20, sets flags bit 0, clears collision at +0x94 and visibility at +0x31. This is a hidden taxi-state assignment, not stop index 2: bounded helper 0x002f1278-0x002f12d0 finds a moby through the same helper/tag, restores its stop pose and calls taxi-stop initializer 0x002f1040 on that returned pointer. Supplied source for that initializer enters TAXI_STATE_WAIT_AT_STOP. Evidence request a87e51b84f594ba39314bcc5961bd24f, report SHA-256 0cc6e3719e9f59ce3c1e7f53375da31a41af2b8c09c1951f77423dfc3b1591ea establishes the selected moby's taxi-state domain. domain_1_value_2 -> TAXI_STATE_HIDDEN: Retail 0x002f0e70-0x002f0ea0 finds the group moby by taxi target at pvars+0xB6 after the saved-pose route transition, writes 2 to returned moby+0x20, sets flags bit 0 and clears collision +0x94 and visibility +0x31. It performs the same hidden-taxi transition as 0x002f06b8. Bounded helper 0x002f1278-0x002f12d0 uses the identical lookup and target field, restores the returned moby's stop pose and passes that pointer to taxi initializer 0x002f1040, proving this state selector belongs to the taxi domain. Thus both listed stores reuse TAXI_STATE_HIDDEN; none of the supplied Hero constants or TAXI_STOP_RETURN_FEEDER_ORIGIN names this state. --- src/overlays/l14/mobys/taxi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/taxi.c b/src/overlays/l14/mobys/taxi.c index b2e1fdba8a..6749a4940b 100644 --- a/src/overlays/l14/mobys/taxi.c +++ b/src/overlays/l14/mobys/taxi.c @@ -93,6 +93,9 @@ void taxi_update(struct Moby *moby) { TAXI_STATE_WAIT_FOR_ITEM_GATE = 6, TAXI_STATE_BLEND_SAVED_POSE_TO_PATH_START = 7 }; + enum { + TAXI_STATE_HIDDEN = 2 + }; L14TaxiVars *taxi_vars = (L14TaxiVars *)moby->pvars; float previous_position[4], previous_rotation[4], position_delta[4], blend_from_position_or_rotation_matrix[4], blend_to_position[4], blend_from_rotation[4], @@ -128,7 +131,7 @@ void taxi_update(struct Moby *moby) { moby->state = TAXI_STATE_BLEND_STOP_TO_PATH_START; m = find_group_moby_by_tag(moby, taxi_vars->target); if (m != 0) { - m->state = 2; + m->state = TAXI_STATE_HIDDEN; m->flags |= 1; m->visible = 0; m->collision = 0; @@ -320,7 +323,7 @@ void taxi_update(struct Moby *moby) { { struct Moby *m = find_group_moby_by_tag(moby, taxi_vars->target); if (m != 0) { - m->state = 2; + m->state = TAXI_STATE_HIDDEN; m->flags |= 1; m->visible = 0; m->collision = 0; From 1f447838f51e562547e2e68db76d5b18eb1609d7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:00:21 +0000 Subject: [PATCH 1274/1502] decomp: clarify names in revive_spawner_pooled_child domain_0_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Authoritative source src/overlays/shared/enemies/bomb_spawner_bomb.c SHA-256 687e5798723fc1009b13bc950bd092e9cd7a6b3f2aae46458d5035c80a87631d already declares this canonical name in update_spawner_bomb for the same Moby->state domain. Checked caller 0x002c4dd0 revives the child and stores it at pvars+0x18; 0x002c4e98-0x002c4ea4 reads that child's +0x20 state. Removal sibling 0x0023d6dc loads boundary 0x0015ffdc, 0x0023d6e8 compares the Moby pointer unsigned, and 0x0023d700 writes the selected value to the same +0x20 byte. 0x0023d6ec/0x0023d6fc selects 0xFE when the Moby pointer is at or above the boundary. Assigned retail 0x002becf0-0x002bed10 tests this state on the indexed pooled Moby and permits revival rather than counting it live; original Ghidra reads +0x20 as -2. domain_1_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Authoritative source src/overlays/shared/enemies/bomb_spawner_bomb.c SHA-256 687e5798723fc1009b13bc950bd092e9cd7a6b3f2aae46458d5035c80a87631d already declares this canonical name in update_spawner_bomb for the same Moby->state domain. Checked caller 0x002c4dd0 revives the child and stores it at pvars+0x18; 0x002c4e98-0x002c4ea4 reads that child's +0x20 state. Removal sibling 0x0023d6dc loads boundary 0x0015ffdc, 0x0023d6e8 compares the Moby pointer unsigned, and 0x0023d700 writes the selected value to the same +0x20 byte. 0x0023d6e8-0x0023d6f8 selects 0xFD when the Moby pointer is below the boundary. Assigned retail 0x002becfc branches on this value at the pooled Moby's +0x20 state, permitting revival rather than counting it live; original Ghidra reads it as -3. domain_2_value_254 -> MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END: Authoritative source src/overlays/shared/enemies/bomb_spawner_bomb.c SHA-256 687e5798723fc1009b13bc950bd092e9cd7a6b3f2aae46458d5035c80a87631d already declares this canonical name in update_spawner_bomb for the same Moby->state domain. Checked caller 0x002c4dd0 revives the child and stores it at pvars+0x18; 0x002c4e98-0x002c4ea4 reads that child's +0x20 state. Removal sibling 0x0023d6dc loads boundary 0x0015ffdc, 0x0023d6e8 compares the Moby pointer unsigned, and 0x0023d700 writes the selected value to the same +0x20 byte. 0x0023d6ec/0x0023d6fc selects 0xFE at or above the boundary. Assigned retail 0x002beecc loads 0xFE and 0x002beee0-0x002beee8 compares linked-list Moby +0x20, skipping this removed class-0x221 Moby in the live count. The linked-list cursor advances via +0x28, not another state domain. domain_3_value_253 -> MOBY_STATE_REMOVAL_BELOW_INSTANCE_END: Authoritative source src/overlays/shared/enemies/bomb_spawner_bomb.c SHA-256 687e5798723fc1009b13bc950bd092e9cd7a6b3f2aae46458d5035c80a87631d already declares this canonical name in update_spawner_bomb for the same Moby->state domain. Checked caller 0x002c4dd0 revives the child and stores it at pvars+0x18; 0x002c4e98-0x002c4ea4 reads that child's +0x20 state. Removal sibling 0x0023d6dc loads boundary 0x0015ffdc, 0x0023d6e8 compares the Moby pointer unsigned, and 0x0023d700 writes the selected value to the same +0x20 byte. 0x0023d6e8-0x0023d6f8 selects 0xFD below the boundary. Assigned retail 0x002beed0 loads 0xFD and 0x002beeec-0x002beef0 compares linked-list Moby +0x20, skipping this removed class-0x221 Moby in the live count. Original Ghidra confirms the same state byte as -3. --- src/overlays/shared/enemies/bomb_spawner_bomb.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/bomb_spawner_bomb.c b/src/overlays/shared/enemies/bomb_spawner_bomb.c index a4b47f2ce2..6bfdc45e64 100644 --- a/src/overlays/shared/enemies/bomb_spawner_bomb.c +++ b/src/overlays/shared/enemies/bomb_spawner_bomb.c @@ -80,6 +80,10 @@ struct Moby *revive_spawner_pooled_child(struct Moby *spawner_moby, Vec4 *at, s3 enum { SPAWNER_CHILD_STATE_INITIAL = 0 }; + enum { + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE + }; Vec4 pos; Vec4 *spawn_position_source; Spawner *spawner_data; @@ -107,7 +111,7 @@ struct Moby *revive_spawner_pooled_child(struct Moby *spawner_moby, Vec4 *at, s3 continue; } current_moby = &D_L03_0015FFD8_gp[pooled_child_moby_index]; - if (current_moby != NULL && current_moby->state != 0xFE && current_moby->state != 0xFD) { + if (current_moby != NULL && current_moby->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && current_moby->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { spawner_data->live++; continue; } @@ -172,8 +176,8 @@ struct Moby *revive_spawner_pooled_child(struct Moby *spawner_moby, Vec4 *at, s3 } } for (current_moby = D_L03_0015FFE4; current_moby != NULL; current_moby = current_moby->next) { - if (current_moby->oclass == 0x221 && current_moby->state != 0xFE && - current_moby->state != 0xFD) { + if (current_moby->oclass == 0x221 && current_moby->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + current_moby->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { spawner_data->live++; } } From 2e90d75dc8a97afa53d58f0678a03b1776e63477 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:02:10 +0000 Subject: [PATCH 1275/1502] decomp: clarify names in process_hero_equipped_item_input domain_0_value_0 -> WRENCH_MOBY_STATE_READY: Retail 0x002280C0 loads equipped moby from hero+0x1090; 0x002280CC-D4 validates it with is_wrench_moby (class 0x47 in supplied context), then 0x002280DC-E0 loads its state byte +0x20 and rejects nonzero before melee requests or launch_hero_wrench at 0x0022815C. Original Ghidra tests *(char *)(iVar3+0x20) != 0 with the same flow. Checked launch helper 0x00217658 loads that same hero+0x1090 at 0x00217778, validates it at 0x0021777C, and writes 10 to moby+0x20 at 0x002177A0-B0 before initializing throw direction, speed and trail. Thus zero is the wrench moby state ready to accept this attack/throw input, in a distinct object-state domain. --- src/overlays/shared/hero/hero_set_state.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/hero_set_state.c b/src/overlays/shared/hero/hero_set_state.c index e0ebcbc419..b6f27ad2d3 100644 --- a/src/overlays/shared/hero/hero_set_state.c +++ b/src/overlays/shared/hero/hero_set_state.c @@ -3318,6 +3318,9 @@ extern s32 D_00141660 NOT_SDA; int process_hero_equipped_item_input(void) __asm__("FUN_L00_00227fa0"); int process_hero_equipped_item_input(void) { + enum { + WRENCH_MOBY_STATE_READY = 0 + }; int item_press_age_frames[3]; int start; int mask; @@ -3356,7 +3359,7 @@ int process_hero_equipped_item_input(void) { if (!is_wrench_moby((char *)equipped_item_moby)) { break; } - if (equipped_item_moby->state != 0) { + if (equipped_item_moby->state != WRENCH_MOBY_STATE_READY) { break; } if ((controller_state.held & 0xA) || From 455fcb4a42acc1dc8339626596759b3e26efcdc6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:02:10 +0000 Subject: [PATCH 1276/1502] decomp: clarify names in tesla_claw_update domain_0_value_4 -> TESLA_CLAW_STATE_FINISHED: Retail 002b8814 retains the Tesla Claw Moby in s3; 002b8908 loads its +0x20 state and 002b8904-002b8910 excludes value 4 from firing. The same field is the switch selector at 002b8eac and already has canonical TESLA_CLAW_STATE_FINISHED = 4; completion writes it at 002b92d4. domain_1_value_0 -> TESLA_CLAW_STATE_INITIALIZE: Retail 002b8914 tests the same s3+0x20 Moby state loaded at 002b8908 against zero to prevent firing during initialization. That exact field selects the switch at 002b8eac; its existing TESLA_CLAW_STATE_INITIALIZE = 0 branch initializes timer, light, targets and locks at 002b8ed4-002b8f2c. domain_4_value_1 -> TESLA_CLAW_STATE_WAIT_FOR_FIRE: In the existing TESLA_CLAW_STATE_INITIALIZE branch, retail 002b8efc loads 1 and 002b8f08 stores it to s3+0x20, the same Moby state dispatched at 002b8eac. It enters canonical TESLA_CLAW_STATE_WAIT_FOR_FIRE = 1 after timer/light setup and before waiting for active fire. domain_5_value_3 -> TESLA_CLAW_STATE_FIRING: Within TESLA_CLAW_STATE_WAIT_FOR_FIRE, active firing in s6 passes 002b8f38, starts equipped-item animation at 002b8f40, and writes 3 to s3+0x20 at 002b8f48-002b8f4c. This is the same switch field whose canonical TESLA_CLAW_STATE_FIRING member is 3. domain_6_value_3 -> TESLA_CLAW_STATE_FIRING: The pressed-fire, unlocked and active path updates firing-start statistics and calls start_equipped_item_animation at 002b9010; 002b901c sets v0 to 3 and 002b917c stores it to the Tesla Claw Moby state at s3+0x20. This enters existing TESLA_CLAW_STATE_FIRING = 3 on the same switch domain. domain_7_value_1 -> TESLA_CLAW_STATE_WAIT_FOR_FIRE: In the wait-for-fire branch's pressed-button but inactive path, 002b9020-002b9038 clears targets and locks; 002b9024 sets 1 and 002b9044 writes s3+0x20 before canceling item animation at 002b9048. The same Moby state selector already names 1 TESLA_CLAW_STATE_WAIT_FOR_FIRE. domain_8_value_1 -> TESLA_CLAW_STATE_WAIT_FOR_FIRE: The TESLA_CLAW_STATE_FIRING release/inactive/locked path clears targets, locks and reach at 002b9160-002b9174 and cancels item animation at 002b9170. Retail 002b9178-002b917c writes 1 to s3+0x20, returning the same switch selector to canonical TESLA_CLAW_STATE_WAIT_FOR_FIRE = 1. domain_9_value_4 -> TESLA_CLAW_STATE_FINISHED: Retail s8 captures hero.items[0].state == 3 at 002b882c-002b8848. After completion releases the point light and resets its handle at 002b92a0-002b92b8, 002b92bc-002b92d4 writes 4 to the same s3+0x20 Moby state dispatched by the switch. Reuse its canonical TESLA_CLAW_STATE_FINISHED = 4. --- src/overlays/shared/weapons/tesla_claw.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/shared/weapons/tesla_claw.c b/src/overlays/shared/weapons/tesla_claw.c index 78ac51dcdf..f4d322ee9f 100644 --- a/src/overlays/shared/weapons/tesla_claw.c +++ b/src/overlays/shared/weapons/tesla_claw.c @@ -515,8 +515,8 @@ void tesla_claw_update(struct Moby *tesla_claw_moby) { if ((unsigned int)hero.state.control_mode < 2 || hero.state.control_mode == 9) help_request(0x4E30, 0x81); } - if ((controller_state.held & hero.items[0].button_mask) && tesla_claw_moby->state != 4 && - tesla_claw_moby->state != 0 && !hero.item_use_locked && hero.state.current != 0x72) { + if ((controller_state.held & hero.items[0].button_mask) && tesla_claw_moby->state != TESLA_CLAW_STATE_FINISHED && + tesla_claw_moby->state != TESLA_CLAW_STATE_INITIALIZE && !hero.item_use_locked && hero.state.current != 0x72) { if (tesla_claw_vars->timer == 0) { if (ready > 0) { if (fast_dec_timer_s16(&tesla_claw_vars->tick)) { @@ -668,7 +668,7 @@ void tesla_claw_update(struct Moby *tesla_claw_moby) { tesla_claw_vars->timer = scale_game_frames(16); tesla_claw_vars->light = FUN_L00_0023e5e0_2b2100(&tesla_claw_vars->pos, 0.0f, 0.0f, 0); tesla_beam_restart_pending = 1; - tesla_claw_moby->state = 1; + tesla_claw_moby->state = TESLA_CLAW_STATE_WAIT_FOR_FIRE; tesla_claw_vars->f3E = 20; tesla_claw_vars->sound = -1; tesla_claw_vars->target2 = 0; @@ -682,7 +682,7 @@ void tesla_claw_update(struct Moby *tesla_claw_moby) { fast_dec_timer(&tesla_claw_vars->timer); if (active) { start_equipped_item_animation(); - tesla_claw_moby->state = 3; + tesla_claw_moby->state = TESLA_CLAW_STATE_FIRING; } if ((controller_state.pressed & (player_hero = &hero)->items[0].button_mask) && !player_hero->item_use_locked) { @@ -694,13 +694,13 @@ void tesla_claw_update(struct Moby *tesla_claw_moby) { firing_start_stats->longest = scale_game_frames(D_0015EEA4) / 600; firing_start_stats->levels = (firing_start_stats->levels | (1 << current_level_index)) | 0x80000000; start_equipped_item_animation(); - tesla_claw_moby->state = 3; + tesla_claw_moby->state = TESLA_CLAW_STATE_FIRING; } else { tesla_claw_vars->target = 0; tesla_claw_vars->target2 = 0; tesla_claw_vars->lock = 0; tesla_claw_vars->lock2 = 0; - tesla_claw_moby->state = 1; + tesla_claw_moby->state = TESLA_CLAW_STATE_WAIT_FOR_FIRE; allocate_voice_for_target_entry(0, 0, tesla_claw_moby); cancel_hero_item_animation(); } @@ -731,7 +731,7 @@ void tesla_claw_update(struct Moby *tesla_claw_moby) { tesla_claw_vars->lock2 = 0; tesla_claw_vars->reach = 0.0f; cancel_hero_item_animation(); - tesla_claw_moby->state = 1; + tesla_claw_moby->state = TESLA_CLAW_STATE_WAIT_FOR_FIRE; } break; case TESLA_CLAW_STATE_FINISHED: @@ -764,7 +764,7 @@ void tesla_claw_update(struct Moby *tesla_claw_moby) { } } if (done && tesla_claw_vars->light == -1) - tesla_claw_moby->state = 4; + tesla_claw_moby->state = TESLA_CLAW_STATE_FINISHED; } /* Starts the beam when one is pending: lays 19 points from the moby toward its target and resets the segment state. */ From afd470b2ec65d24abd9dde7565849f45d1e4f61f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:02:10 +0000 Subject: [PATCH 1277/1502] decomp: clarify names in volume_camera_swing domain_2_value_7 -> SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY: Retail 0x002ec9c4-0x002ec9d8 indexes camera_descriptors by record+0x84, loads descriptor+0x1c into s8 and reads params+0x2c. This proves SwingCameraParams.type, a camera behavior selector separate from HeroStateId, HeroGravityMode, HeroVehicleMode and FollowCamTail.mode. Retail 0x002ecd58-0x002ece14 routes type 7 through the stick-skippable 200-frame swing-end/400-frame restart timing. At 0x002ecef8-0x002ecf2c type 7 suppresses set_follow_camera_angle_blend_from_direction when at_end is set. At 0x002ed1b8-0x002ed1f8 it calls follow_camera_start_slide and the up-spring setter. Checked caller 0x002ed294-0x002ed2ec limits the timer-zero frames_off_ground check to types 1 and 10; type 7 bypasses it and reaches the call at 0x002ed318, permitting airborne entry subject to the ordinary volume eligibility checks. Original retail Ghidra decompilation and bound C agree. This occurrence selects the timing branch. domain_3_value_7 -> SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY: Retail 0x002ec9c4-0x002ec9d8 indexes camera_descriptors by record+0x84, loads descriptor+0x1c into s8 and reads params+0x2c. This proves SwingCameraParams.type, a camera behavior selector separate from HeroStateId, HeroGravityMode, HeroVehicleMode and FollowCamTail.mode. Retail 0x002ecd58-0x002ece14 routes type 7 through the stick-skippable 200-frame swing-end/400-frame restart timing. At 0x002ecef8-0x002ecf2c type 7 suppresses set_follow_camera_angle_blend_from_direction when at_end is set. At 0x002ed1b8-0x002ed1f8 it calls follow_camera_start_slide and the up-spring setter. Checked caller 0x002ed294-0x002ed2ec limits the timer-zero frames_off_ground check to types 1 and 10; type 7 bypasses it and reaches the call at 0x002ed318, permitting airborne entry subject to the ordinary volume eligibility checks. Original retail Ghidra decompilation and bound C agree. This != occurrence controls angle-output suppression at the swing end. domain_4_value_7 -> SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY: Retail 0x002ec9c4-0x002ec9d8 indexes camera_descriptors by record+0x84, loads descriptor+0x1c into s8 and reads params+0x2c. This proves SwingCameraParams.type, a camera behavior selector separate from HeroStateId, HeroGravityMode, HeroVehicleMode and FollowCamTail.mode. Retail 0x002ecd58-0x002ece14 routes type 7 through the stick-skippable 200-frame swing-end/400-frame restart timing. At 0x002ecef8-0x002ecf2c type 7 suppresses set_follow_camera_angle_blend_from_direction when at_end is set. At 0x002ed1b8-0x002ed1f8 it calls follow_camera_start_slide and the up-spring setter. Checked caller 0x002ed294-0x002ed2ec limits the timer-zero frames_off_ground check to types 1 and 10; type 7 bypasses it and reaches the call at 0x002ed318, permitting airborne entry subject to the ordinary volume eligibility checks. Original retail Ghidra decompilation and bound C agree. This occurrence selects slide initialization and up-spring output. --- src/overlays/shared/camera/swing_volume_camera.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/camera/swing_volume_camera.c b/src/overlays/shared/camera/swing_volume_camera.c index 56fac7dfd6..d146814ac8 100644 --- a/src/overlays/shared/camera/swing_volume_camera.c +++ b/src/overlays/shared/camera/swing_volume_camera.c @@ -132,7 +132,7 @@ s32 volume_camera_swing_active(struct UpdateCam *swing_camera_record) { void volume_camera_swing(struct UpdateCam *cam) __asm__("FUN_L00_002ec988"); void volume_camera_swing(struct UpdateCam *swing_camera_record) { - enum { SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END = 1 , SWING_CAMERA_TYPE_ONE_FRAME_SWING = 3 , SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST = 4 , SWING_CAMERA_TYPE_SNAP_ON_ENTRY = 5 , SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END = 10 } ; enum { SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE = 6 , SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE = 8 , SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END = 9} ;CameraVec gravity_offset_or_yaw_direction; + enum { SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END = 1 , SWING_CAMERA_TYPE_ONE_FRAME_SWING = 3 , SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST = 4 , SWING_CAMERA_TYPE_SNAP_ON_ENTRY = 5 , SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END = 10 } ; enum { SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE = 6 , SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE = 8 , SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END = 9} ; enum { SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY = 7} ;CameraVec gravity_offset_or_yaw_direction; SwingCameraParams *params; struct UpdateCam *rec; Vec4f *pos; @@ -247,7 +247,7 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { params->timer = scale_game_frames(200); } FUN_L00_002e8620(); - } else if (params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || params->type == 7 || params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END || params->type == SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END) { + } else if (params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY || params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END || params->type == SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END) { /* Moving the left stick skips to the end of the swing. */ struct PadState *pad = &controller_state; if (pad->analog[0] != 0.0f || pad->analog[1] != 0.0f) { @@ -281,7 +281,7 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { fast_sin(camera_descriptors[swing_camera_record->descriptor_index].yaw); *(s32 *)&gravity_offset_or_yaw_direction[2] = 0; swing = params->swing * 0.017453292f * (params->timer / total); - if ((params->type != SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END && params->type != 7 && params->type != SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END) || at_end == 0) { + if ((params->type != SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END && params->type != SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY && params->type != SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END) || at_end == 0) { set_follow_camera_angle_blend_from_direction( gravity_offset_or_yaw_direction, swing, params->pitch * 0.017453292f); } @@ -341,7 +341,7 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { lateral_spring_blend_fraction); } } - if (params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || params->type == 7 || params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END) { + if (params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY || params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END) { FUN_L00_002e8620(); follow_camera_start_slide(); follow_camera_set_up_spring(0.01f, 0.2f); From e42183eb9b1d2383afb53b8914749b77f6e80454 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:04:15 +0000 Subject: [PATCH 1278/1502] decomp: clarify names in bomb_spawner_update domain_0_value_2 -> HIT_STATUS_DAMAGE_PROCESSING_THRESHOLD: Retail 0x002bf1a4-0x002bf1c4 passes sp+0x80 as fifth-argument status output to resolve_moby_hit_response; 0x002bf1c8-0x002bf1d0 tests that output against 2, and 0x002bf1d8-0x002bf1f4 subtracts hit+0x2C from spawner hp only on status >=2. Checked helper request 12ae18c00fe448ddaa21784772560d5f (level-03 0x00248f00) saves t0 in s3 at 0x00248f10, writes status 0 at 0x00248f58/0x00248fdc, writes status 1 on the no-hit path at 0x00249030-0x00249034, and writes hit-response statuses 2/3/4 through 0x002492c8. The helper can downgrade status to 1 and zero damage at 0x002493d4-0x002493e0. Thus 2 is the lower threshold for entering this caller's damage processing, in the helper output domain, separate from all equal-valued spawner enums. --- src/overlays/shared/enemies/bomb_spawner.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/bomb_spawner.c b/src/overlays/shared/enemies/bomb_spawner.c index ecf42905d7..405696a604 100644 --- a/src/overlays/shared/enemies/bomb_spawner.c +++ b/src/overlays/shared/enemies/bomb_spawner.c @@ -182,6 +182,9 @@ void bomb_spawner_update(struct Moby *moby) { MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE }; + enum { + HIT_STATUS_DAMAGE_PROCESSING_THRESHOLD = 2 + }; int used[4]; Vec4A_2bef68 launch_origin; Vec4A_2bef68 launch_velocity; @@ -259,7 +262,7 @@ void bomb_spawner_update(struct Moby *moby) { } r = (Hit_2C0330 *)find_moby_hit(moby, 0xC30000, 0); resolve_moby_hit_response(moby, r, &spawner_data->hp, 0, &damage_query_status, 0, 0, 4); - if (damage_query_status >= 2) { + if (damage_query_status >= HIT_STATUS_DAMAGE_PROCESSING_THRESHOLD) { float remaining_health = spawner_data->hp - r->f2C; spawner_data->hp = remaining_health; if (remaining_health > 0.0f) { From ff3b557edac9ec0b5e91f701dc33ffc9036d1f6d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:04:15 +0000 Subject: [PATCH 1279/1502] decomp: clarify names in handle_hero_gadget_button domain_0_value_0 -> WRENCH_MOBY_STATE_READY_FOR_ATTACK: Retail 0x00240ff8 loads equipped slot-0 moby; 0x00241004-0x00241010 verifies is_wrench_moby. 0x00241014-0x00241018 reads its byte state at +0x20 and rejects nonzero before selecting wrench melee (0x13/0x70), crouch swing (0x15), or launch_hero_wrench at 0x00241094. Checked launch helper 0x00236ec0-0x00236ecc reloads and verifies that same slot moby; 0x00236ee8 loads 10 and 0x00236ef8 writes it to +0x20 before throw transform/velocity setup. Thus zero is the wrench moby's attack-ready state, in a distinct domain from hero state IDs. --- src/overlays/l01/hero/hero_set_state.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l01/hero/hero_set_state.c b/src/overlays/l01/hero/hero_set_state.c index 36e83d8889..3fcd508b63 100644 --- a/src/overlays/l01/hero/hero_set_state.c +++ b/src/overlays/l01/hero/hero_set_state.c @@ -1611,6 +1611,9 @@ extern int get_ammo(int) __asm__("FUN_L00_00233e98"); int handle_hero_gadget_button(void) __asm__("FUN_L01_00240ed8"); int handle_hero_gadget_button(void) { + enum { + WRENCH_MOBY_STATE_READY_FOR_ATTACK = 0 + }; int wrench_button_history_age; int item_animation_button_history_age; int item_state_button_history_age; @@ -1641,7 +1644,7 @@ int handle_hero_gadget_button(void) { pad_pressed_within(buttons, scale_game_frames(7), &wrench_button_history_age) != 0) { moby = hero.items[0].moby; - if (moby != 0 && is_wrench_moby((char *)moby) != 0 && moby->state == 0) { + if (moby != 0 && is_wrench_moby((char *)moby) != 0 && moby->state == WRENCH_MOBY_STATE_READY_FOR_ATTACK) { if ((controller_state.held & 0xa) != 0 || ((hero.state.current == 1 || hero.state.current == 0x1e) && scale_game_frames(0x14) < hero.state_timer)) { From e5f5ecb2defd535550297c2b9c85efa77a359634 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:04:15 +0000 Subject: [PATCH 1280/1502] decomp: clarify names in sand_mouse_update domain_0_value_5 -> SAND_MOUSE_FOLLOW_HERO: Retail 0x002e3f60-0x002e3f68 loads this moby's state byte from s3+0x20 and compares it against 5 to select parent-facing input. The same byte is dispatched at 0x002e4004-0x002e4024; authoritative C names its case 5 SAND_MOUSE_FOLLOW_HERO, whose 0x002e47e4-0x002e47f4 calls compute a hero-relative goal and steer toward it. Reuse that established same-domain member as the >= boundary; this does not assert all later states follow the hero. domain_10_value_20 -> SAND_MOUSE_RETURN_TO_PARENT: Retail 0x002e4a44-0x002e4a70 gates on fall-helper bit 2, zeros velocity and copies indexed parent's position to private target; 0x002e4a74-0x002e4a7c stores 0x14 into self state +0x20. The same self-state switch already names case 20 SAND_MOUSE_RETURN_TO_PARENT; 0x002e4a80-0x002e4b54 faces and moves toward that captured target, then restores waiting state. domain_11_value_1 -> SAND_MOUSE_WAIT_FOR_HERO_IN_VOLUME: Retail return handler checks mover bit 4 at 0x002e4b04, restores idle animation, then 0x002e4b3c-0x002e4b58 commands parent 1, writes 1 to self state +0x20 and hides self. The self byte is the switch selector, whose authoritative case 1 is SAND_MOUSE_WAIT_FOR_HERO_IN_VOLUME and waits on hero-volume/line acceptance. Only the self-state assignment is proposed; parent command 1 is a separate domain. domain_1_value_1 -> SAND_MOUSE_WAIT_FOR_HERO_IN_VOLUME: Retail initialization loads 1 at 0x002e427c and stores it to this moby's state byte s3+0x20 at 0x002e4288. The same field selects authoritative C case SAND_MOUSE_WAIT_FOR_HERO_IN_VOLUME; retail 0x002e4350-0x002e4384 and 0x002e4468-0x002e449c gate activation on hero position in the configured volume. This assignment enters that established local-enum state. domain_2_value_2 -> SAND_MOUSE_WAIT_FOR_PARENT_READY: Retail 0x002e4528-0x002e4540 commands indexed parent +0xbc to 5 and writes 2 to self s3+0x20. Dispatch reads self +0x20; case 2 at 0x002e4544-0x002e457c waits for indexed parent's state +0x20 to equal 5 before proceeding. Authoritative C already names this self-state SAND_MOUSE_WAIT_FOR_PARENT_READY, distinct from the parent's command domain. domain_3_value_3 -> SAND_MOUSE_MOVE_TOWARD_HERO: In the activation path without a parent, retail 0x002e4520 branches to 0x002e4584; 0x002e4588-0x002e4594 writes 3 into self state +0x20 and restores draw distance. This is the same self-state dispatched into authoritative case SAND_MOUSE_MOVE_TOWARD_HERO at 0x002e4598, which computes the hero-relative approach target and steps movement at 0x002e4614-0x002e4624. domain_4_value_3 -> SAND_MOUSE_MOVE_TOWARD_HERO: Retail 0x002e4554-0x002e4564 checks the indexed parent's state for readiness; 0x002e4568-0x002e4570 writes 3 to self state +0x20 on success. This self-state is the existing local-enum SAND_MOUSE_MOVE_TOWARD_HERO case, retail 0x002e4598-0x002e4624, which refreshes the hero-relative target, faces it and calls the movement step. domain_5_value_3 -> SAND_MOUSE_MOVE_TOWARD_HERO: Retail parent-ready case branches on absent parent at 0x002e454c to 0x002e4580, clears timer and stores 3 to self state +0x20 at 0x002e4594. This is the same field loaded for switch dispatch at 0x002e4004. Existing SAND_MOUSE_MOVE_TOWARD_HERO case 3 computes a hero-relative target and moves toward it at 0x002e4598-0x002e4624; reuse that local member. domain_6_value_4 -> SAND_MOUSE_BEGIN_FOLLOW_HERO: Retail 0x002e4628-0x002e4654 tests mover result bits or distance to hero below 1.0, then 0x002e465c-0x002e4670 zeros velocity and stores 4 at self +0x20. Existing authoritative case SAND_MOUSE_BEGIN_FOLLOW_HERO handles that same switch field and transitions to follow state 5 at 0x002e46f0-0x002e4734. Reuse its established member for the state assignment. domain_7_value_5 -> SAND_MOUSE_FOLLOW_HERO: Retail begin-follow handler 0x002e46f0-0x002e4728 releases hero control and clears self/parent flag bits, then 0x002e472c-0x002e4734 stores 5 to self state +0x20. Same-byte switch case 5 is already SAND_MOUSE_FOLLOW_HERO in authoritative C; 0x002e47e4-0x002e47f4 computes a hero-relative goal and steers toward it. This is a self-state assignment, not the helper's subsequent state-2 write. domain_8_value_6 -> SAND_MOUSE_FADE_OUT_AND_RESET_HOME: Retail failed-follow path 0x002e4830-0x002e4844 zeros velocity, initializes fade timer +0x4c and stores 6 to self +0x20. The same dispatch domain's established SAND_MOUSE_FADE_OUT_AND_RESET_HOME case at 0x002e4878-0x002e49f8 emits particles/reduces alpha until resetting position and target to home. Reuse the existing local-enum member. domain_9_value_19 -> SAND_MOUSE_DAMP_VELOCITY_BEFORE_RETURN: Retail fade completion 0x002e4888-0x002e48b4 copies home into self position and private target, zeros velocity and writes 0x13 to self state +0x20. That exact switch field selects established SAND_MOUSE_DAMP_VELOCITY_BEFORE_RETURN case 19 at 0x002e49fc-0x002e4a40, damping XY velocity before the return transition. Reuse that existing local member. --- src/overlays/shared/enemies/sand_mouse.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/overlays/shared/enemies/sand_mouse.c b/src/overlays/shared/enemies/sand_mouse.c index 04f7ca041f..a01ae5f508 100644 --- a/src/overlays/shared/enemies/sand_mouse.c +++ b/src/overlays/shared/enemies/sand_mouse.c @@ -513,7 +513,7 @@ void sand_mouse_update(struct Moby *moby) { return; } if (sand_mouse_vars->parent != -1) { - if (moby->state >= 5) { + if (moby->state >= SAND_MOUSE_FOLLOW_HERO) { ((Data *)((struct Moby *)ents)[sand_mouse_vars->parent].pvars)->target[0] = fast_arc_tan(moby->pos.x - ((struct Moby *)ents)[sand_mouse_vars->parent].pos.x, moby->pos.y - ((struct Moby *)ents)[sand_mouse_vars->parent].pos.y); @@ -580,7 +580,7 @@ void sand_mouse_update(struct Moby *moby) { mover_2e3f20.unk48 = scale_game_frames(4); mover_2e3f20.unk28 = 3.1415927f; } - moby->state = 1; + moby->state = SAND_MOUSE_WAIT_FOR_HERO_IN_VOLUME; moby->draw_dist = 0; break; case SAND_MOUSE_WAIT_FOR_HERO_IN_VOLUME: @@ -626,10 +626,10 @@ void sand_mouse_update(struct Moby *moby) { set_hero_animation(0, 0, (float)scale_game_frames(6)); if (sand_mouse_vars->parent != -1) { ((struct Moby *)ents)[sand_mouse_vars->parent].command = 5; - moby->state = 2; + moby->state = SAND_MOUSE_WAIT_FOR_PARENT_READY; } else { moby->draw_dist = 0xFF; - moby->state = 3; + moby->state = SAND_MOUSE_MOVE_TOWARD_HERO; } } } @@ -639,14 +639,14 @@ void sand_mouse_update(struct Moby *moby) { case SAND_MOUSE_WAIT_FOR_PARENT_READY: if (sand_mouse_vars->parent != -1) { if (((struct Moby *)ents)[sand_mouse_vars->parent].state == 5) { - moby->state = 3; + moby->state = SAND_MOUSE_MOVE_TOWARD_HERO; sand_mouse_vars->timer = 0; moby->draw_dist = 0xFF; } } else { sand_mouse_vars->timer = 0; moby->draw_dist = 0xFF; - moby->state = 3; + moby->state = SAND_MOUSE_MOVE_TOWARD_HERO; } break; case SAND_MOUSE_MOVE_TOWARD_HERO: @@ -663,7 +663,7 @@ void sand_mouse_update(struct Moby *moby) { 6) || vector_distance_xy(((float *)&moby->pos), hero_2e3f20->pos) < 1.0f) { qzero(sand_mouse_vars->vel); - moby->state = 4; + moby->state = SAND_MOUSE_BEGIN_FOLLOW_HERO; sand_mouse_vars->timer = scale_game_frames(0x78); } if (vector_distance_xy(((float *)&moby->pos), sand_mouse_vars->home) > 0.4f && @@ -680,7 +680,7 @@ void sand_mouse_update(struct Moby *moby) { if (sand_mouse_vars->parent != -1) { ((struct Moby *)ents)[sand_mouse_vars->parent].flags &= 0xFFBE; } - moby->state = 5; + moby->state = SAND_MOUSE_FOLLOW_HERO; if (hero_2e3f20->helper != 0 && hero_2e3f20->helper->oclass == 0x1B1 && hero_2e3f20->helper->state != 0xFE && hero_2e3f20->helper->state != 0xFD) { sand_mouse_vars->b48 = 0xFF; @@ -700,7 +700,7 @@ void sand_mouse_update(struct Moby *moby) { } qzero(sand_mouse_vars->vel); sand_mouse_vars->timer = sand_mouse_fade_duration_frames_gp; - moby->state = 6; + moby->state = SAND_MOUSE_FADE_OUT_AND_RESET_HOME; if (sand_mouse_vars->parent != -1) { ((struct Moby *)ents)[sand_mouse_vars->parent].command = 5; } @@ -713,7 +713,7 @@ void sand_mouse_update(struct Moby *moby) { qcopy(((float *)&moby->pos), sand_mouse_vars->home); qcopy(sand_mouse_vars->target, sand_mouse_vars->home); qzero(sand_mouse_vars->vel); - moby->state = 0x13; + moby->state = SAND_MOUSE_DAMP_VELOCITY_BEFORE_RETURN; moby->flags &= 0xFDFF; } else { int cr; @@ -764,7 +764,7 @@ void sand_mouse_update(struct Moby *moby) { qzero(sand_mouse_vars->vel); qcopy(sand_mouse_vars->target, ((float *)&((struct Moby *)ents)[sand_mouse_vars->parent].pos)); - moby->state = 0x14; + moby->state = SAND_MOUSE_RETURN_TO_PARENT; } break; case SAND_MOUSE_RETURN_TO_PARENT: { @@ -788,7 +788,7 @@ void sand_mouse_update(struct Moby *moby) { blend_moby_animation(moby, 0, 0, scale_game_frames(6)); } ((struct Moby *)ents)[sand_mouse_vars->parent].command = 1; - moby->state = 1; + moby->state = SAND_MOUSE_WAIT_FOR_HERO_IN_VOLUME; moby->draw_dist = 0; } } break; From 900b16e0ce53a7e9232628d8b264bcb7c443110e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:06:10 +0000 Subject: [PATCH 1281/1502] decomp: clarify names in bolt_thief_update domain_0_value_1 -> BOLT_PICKUP_RELEASED_FROM_THIEF: The authoritative bolt_thief.c snapshot SHA-256 85fa79e7a1a170617e1a8e094029228d170c35811340ffcf8d393957c822efcb assigns 1 only to list[i] pickups currently in BOLT_PICKUP_CONTROLLED_BY_THIEF (3) when a hit starts thief knockback. Retail 0x002e2eb0-0x002e2ed8 traverses pvars+0x158; 0x002e2ec4 loads each pickup's +0x20 state, 0x002e2ec8 tests against 3, and its taken delay-slot store at 0x002e2ecc writes a2=1 (loaded at 0x002e2eac). The thief then receives knockback setup and state 8 at 0x002e2f68-0x002e2f8c. The list builder selects class 0x279; this is the pickup state domain, not the thief or hero domain. The transition relinquishes thief control and supports the bounded behavioral name RELEASED_FROM_THIEF without asserting the complete state-1 lifecycle. --- src/overlays/l08/mobys/bolt_thief.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l08/mobys/bolt_thief.c b/src/overlays/l08/mobys/bolt_thief.c index 0509637b22..ee0181c90f 100644 --- a/src/overlays/l08/mobys/bolt_thief.c +++ b/src/overlays/l08/mobys/bolt_thief.c @@ -113,6 +113,9 @@ void bolt_thief_update(struct Moby *moby) { BOLT_PICKUP_CONTROLLED_BY_THIEF = 3, BOLT_PICKUP_COLLECTION_TRIGGERED = 4 }; + enum { + BOLT_PICKUP_RELEASED_FROM_THIEF = 1 + }; Vec4 point; Vec4 step; BoltThiefVars *bolt_thief_instance_vars; @@ -132,7 +135,7 @@ void bolt_thief_update(struct Moby *moby) { struct Moby *other = bolt_thief_instance_vars->list[i]; if (other != 0 && other->state == BOLT_PICKUP_CONTROLLED_BY_THIEF) { - other->state = 1; + other->state = BOLT_PICKUP_RELEASED_FROM_THIEF; } } { From 801a60b39ace7ebfed6bd512a3023d52ade7393b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:06:10 +0000 Subject: [PATCH 1282/1502] decomp: clarify names in test_dummy_update domain_0_value_2 -> TEST_DUMMY_TARGET_MODE_NO_MOBY_TARGET: At 002ce080-002ce094 the random alternative bypasses target acquisition and writes 2 at 002ce5cc. The selector is dummy_data->mode at pvars+0xB4, not moby state/kind or a Hero mode. Checked helper 0025b830 (evidence request 348397ca406c4674ba271b3472a5b5e3) receives target=pvars+0x70 at 002ce5a0. It stores selected moby at target+0x40 (0025bbc8/0025bc58) and targeting status at target+0x44 (0025bc80), exactly pvars+0xB4. Status 2 is paired with clearing selected moby s8 at 0025b8ac-0025b8c0, 0025b928-0025b934 and 0025b978-0025b980; choosing another moby changes status to 1 at 0025ba8c-0025ba98 or 0025bb9c-0025bba8. Thus 2 denotes no selected moby target. domain_1_value_2 -> TEST_DUMMY_TARGET_MODE_NO_MOBY_TARGET: At 002ce098-002ce0e8 comparison with 2 chooses the per-node indexed aim position instead of the acquired target vector. The selector is dummy_data->mode at pvars+0xB4, not moby state/kind or a Hero mode. Checked helper 0025b830 (evidence request 348397ca406c4674ba271b3472a5b5e3) receives target=pvars+0x70 at 002ce5a0. It stores selected moby at target+0x40 (0025bbc8/0025bc58) and targeting status at target+0x44 (0025bc80), exactly pvars+0xB4. Status 2 is paired with clearing selected moby s8 at 0025b8ac-0025b8c0, 0025b928-0025b934 and 0025b978-0025b980; choosing another moby changes status to 1 at 0025ba8c-0025ba98 or 0025bb9c-0025bba8. Thus 2 denotes no selected moby target. domain_2_value_2 -> TEST_DUMMY_TARGET_MODE_NO_MOBY_TARGET: At 002ce578-002ce584 the spray approach random alternative bypasses target acquisition and writes 2 at 002ce5cc. The selector is dummy_data->mode at pvars+0xB4, not moby state/kind or a Hero mode. Checked helper 0025b830 (evidence request 348397ca406c4674ba271b3472a5b5e3) receives target=pvars+0x70 at 002ce5a0. It stores selected moby at target+0x40 (0025bbc8/0025bc58) and targeting status at target+0x44 (0025bc80), exactly pvars+0xB4. Status 2 is paired with clearing selected moby s8 at 0025b8ac-0025b8c0, 0025b928-0025b934 and 0025b978-0025b980; choosing another moby changes status to 1 at 0025ba8c-0025ba98 or 0025bb9c-0025bba8. Thus 2 denotes no selected moby target. domain_3_value_2 -> TEST_DUMMY_TARGET_MODE_NO_MOBY_TARGET: At 002ce5d0-002ce610 comparison with 2 skips turning toward the acquired target; other modes use pvars+0x70/+0x74. The selector is dummy_data->mode at pvars+0xB4, not moby state/kind or a Hero mode. Checked helper 0025b830 (evidence request 348397ca406c4674ba271b3472a5b5e3) receives target=pvars+0x70 at 002ce5a0. It stores selected moby at target+0x40 (0025bbc8/0025bc58) and targeting status at target+0x44 (0025bc80), exactly pvars+0xB4. Status 2 is paired with clearing selected moby s8 at 0025b8ac-0025b8c0, 0025b928-0025b934 and 0025b978-0025b980; choosing another moby changes status to 1 at 0025ba8c-0025ba98 or 0025bb9c-0025bba8. Thus 2 denotes no selected moby target. --- src/overlays/l16/mobys/test_dummy.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/overlays/l16/mobys/test_dummy.c b/src/overlays/l16/mobys/test_dummy.c index 3d02918ac2..e05a6d3ee8 100644 --- a/src/overlays/l16/mobys/test_dummy.c +++ b/src/overlays/l16/mobys/test_dummy.c @@ -146,6 +146,9 @@ void test_dummy_update(unsigned char *moby) { TEST_DUMMY_KIND_PATH_MOVER = 1, TEST_DUMMY_KIND_SPRAYER = 2 }; + enum { + TEST_DUMMY_TARGET_MODE_NO_MOBY_TARGET = 2 + }; L16QuadVector position_or_delta, position_or_direction, launch_velocity; L16HitDescriptor fx; L16DummyData *dummy_data = ((L16DummyData *)MOBY(moby)->pvars); @@ -232,13 +235,13 @@ void test_dummy_update(unsigned char *moby) { FUN_L00_0025ff38( 12.0f, (char *)moby, dummy_data->target, 0, 0, p + 16, *(int *)p); } else { - dummy_data->mode = 2; + dummy_data->mode = TEST_DUMMY_TARGET_MODE_NO_MOBY_TARGET; } } } break; case TEST_DUMMY_STATE_THROW_AT_TARGET: /* thrower: launch the held object at the target, then face it or the next node */ - if (dummy_data->mode == 2) { + if (dummy_data->mode == TEST_DUMMY_TARGET_MODE_NO_MOBY_TARGET) { qcopy(position_or_delta.f, D_L16_001600EC_c + dummy_data->aim[dummy_data->node] * 0x80 + 0x30); } else { @@ -351,13 +354,13 @@ void test_dummy_update(unsigned char *moby) { FUN_L00_0025ff38( 12.0f, (char *)moby, dummy_data->target, 0, 0, p + 16, *(int *)p); } else { - dummy_data->mode = 2; + dummy_data->mode = TEST_DUMMY_TARGET_MODE_NO_MOBY_TARGET; } } } break; case TEST_DUMMY_STATE_SPRAY_FROM_CHILD: /* sprayer: face the target and emit from the child toward it */ - if (dummy_data->mode != 2) { + if (dummy_data->mode != TEST_DUMMY_TARGET_MODE_NO_MOBY_TARGET) { position_or_delta.quad = *(u128 *)(moby + 16); move_test_dummy_toward_position_and_heading( moby, From 8f2c0e8a3b3f4a049d08c82baf085ce7cc6a9361 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:07:54 +0000 Subject: [PATCH 1283/1502] decomp: clarify names in infobot_update domain_0_value_2 -> INFOBOT_WAIT_FOR_PLAYER: At 002d5e7c..002d5e88 initialization with arrived!=0 stores 2 to 0x20(s5), the same byte loaded for dispatch at 002d5e30. Existing case INFOBOT_WAIT_FOR_PLAYER=2 handles rotation settling and active-player proximity at 002d5fa8..002d6114. domain_10_value_7 -> INFOBOT_ORBIT_PATH_ENDPOINT: At 002d65a0..002d65f0 the final segment and low speed cause endpoint position copy and state 7 store to moby+0x20. Existing INFOBOT_ORBIT_PATH_ENDPOINT=7 computes a cosine/sine orbit about the final path point at 002d6814..002d693c. domain_11_value_8 -> INFOBOT_START_SCENE_SEQUENCE: At 002d6930..002d6968 proximity to the orbit path endpoint plus active player stores 8 to moby+0x20. This is the same Infobot selector whose existing INFOBOT_START_SCENE_SEQUENCE=8 performs setup and optional msg0 dispatch at 002d6a10..002d6a70. domain_12_value_9 -> INFOBOT_WAIT_TO_DISPATCH_MSG1: At 002d6a50..002d6a68 scene setup stores 9 to the moby+0x20 dispatch byte before optional signed msg0 dispatch. Existing INFOBOT_WAIT_TO_DISPATCH_MSG1=9 waits on the global gate and optionally dispatches pvars+0x0D at 002d6a74..002d6aa8. domain_13_value_10 -> INFOBOT_WAIT_TO_START_FINAL_SCENE: At 002d6a74..002d6a9c the msg1 stage clears its gate, stores 10 to moby+0x20 and optionally dispatches msg1. Existing INFOBOT_WAIT_TO_START_FINAL_SCENE=10 waits again and optionally starts signed msg2 at 002d6aac..002d6adc. domain_14_value_11 -> INFOBOT_SAVE_AND_REMOVE: At 002d6ac0..002d6adc optional signed msg2 start is followed by store of 11 to moby+0x20. Existing INFOBOT_SAVE_AND_REMOVE=11 gates the save, planet message and removal calls at 002d6ae0..002d6b08. domain_1_value_2 -> INFOBOT_WAIT_FOR_PLAYER: At 002d5e94..002d5ea4 waiting!=0 selects 2 and stores it to moby state 0x20(s5). The identical field selects the existing INFOBOT_WAIT_FOR_PLAYER=2 branch with active-player proximity gating; this is the Infobot state domain. domain_2_value_1 -> INFOBOT_IDLE: At 002d5e98..002d5ea4 waiting==0 selects 1 for the byte at moby+0x20, the switch selector. Authoritative C already declares INFOBOT_IDLE=1 and its empty state-specific branch reaches common attachment processing. domain_3_value_5 -> INFOBOT_ORBIT_CARRIER: At 002d5eb8..002d5ecc attach!=-1 causes a store of 5 to the dispatch byte moby+0x20. Existing INFOBOT_ORBIT_CARRIER=5 computes cosine/sine offset and height 3 at 002d6320..002d6368, then uses common carrier attachment processing. domain_4_value_3 -> INFOBOT_WAIT_TO_FOLLOW_SLOT_PATH: At 002d5f78..002d5fa4 initialization copies slots[0] path start, clears seg and stores 3 to moby+0x20. Existing INFOBOT_WAIT_TO_FOLLOW_SLOT_PATH=3 validates slots[seg] and waits for camera-target proximity before entering slot path movement. domain_5_value_8 -> INFOBOT_START_SCENE_SEQUENCE: At 002d6104..002d6114 active-player proximity stores 8 to the same moby+0x20 switch selector. Existing INFOBOT_START_SCENE_SEQUENCE=8 at 002d6a10..002d6a70 performs unlock/setup, enters 9 and optionally dispatches signed msg0. domain_6_value_2 -> INFOBOT_WAIT_FOR_PLAYER: At 002d613c..002d615c an absent slots[seg] (-1) causes 2 to be stored at moby+0x20. This returns to the same selector's existing INFOBOT_WAIT_FOR_PLAYER=2 branch, whose rotation settling and player proximity gate appear at 002d5fa8..002d6114. domain_7_value_4 -> INFOBOT_FOLLOW_SLOT_PATH: At 002d6258..002d628c camera-target distance below 8 causes state 4 to be stored at moby+0x20 and dialogue record value 1 to be set. Existing INFOBOT_FOLLOW_SLOT_PATH=4 invokes movement on slots[seg] at 002d6298..002d62c4. domain_8_value_4 -> INFOBOT_FOLLOW_SLOT_PATH: At 002d62d0..002d62ec the byte read from moby+0x20 is compared with 4 after the slot-path helper; seg increments only after leaving that state. The same switch selector already names case 4 INFOBOT_FOLLOW_SLOT_PATH. domain_9_value_6 -> INFOBOT_FOLLOW_PATH: At 002d6394..002d63b4 carrier command 6 gates detachment, then 6 is stored to moby+0x20. The store destination is the Infobot dispatch byte, distinct from carrier command at +0xBC. Existing INFOBOT_FOLLOW_PATH=6 interpolates infobot->path at 002d6468 onward. --- src/overlays/shared/pickups/infobot.c | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/overlays/shared/pickups/infobot.c b/src/overlays/shared/pickups/infobot.c index fcf4b2b4fc..d6c90ee8f0 100644 --- a/src/overlays/shared/pickups/infobot.c +++ b/src/overlays/shared/pickups/infobot.c @@ -351,18 +351,18 @@ void infobot_update(struct Moby *moby) { infobot->yaw = moby->rot.z; infobot->home = MPOS(moby)->q; if (infobot->arrived != 0) { - moby->state = 2; + moby->state = INFOBOT_WAIT_FOR_PLAYER; FUN_L00_002d6bf0_2d5de8(moby); } else { if (infobot->waiting != 0) { - moby->state = 2; + moby->state = INFOBOT_WAIT_FOR_PLAYER; } else { - moby->state = 1; + moby->state = INFOBOT_IDLE; } moby->flags |= 0x41; } if (infobot->attach != -1) { - moby->state = 5; + moby->state = INFOBOT_ORBIT_CARRIER; FUN_L00_002d6bf0_2d5de8(moby); break; } @@ -377,7 +377,7 @@ void infobot_update(struct Moby *moby) { } MPOS(moby)->q = toad_paths[infobot->slots[0]]->pts[0].q; infobot->seg = 0; - moby->state = 3; + moby->state = INFOBOT_WAIT_TO_FOLLOW_SLOT_PATH; break; case INFOBOT_IDLE: break; @@ -408,7 +408,7 @@ void infobot_update(struct Moby *moby) { return; } if (fast_vec_dist(&D_0013F3D0, &moby->pos) < range && D_0013F3D0.active != 0) { - moby->state = 8; + moby->state = INFOBOT_START_SCENE_SEQUENCE; } break; case INFOBOT_WAIT_TO_FOLLOW_SLOT_PATH: @@ -418,7 +418,7 @@ void infobot_update(struct Moby *moby) { return; } if (infobot->slots[infobot->seg] == -1) { - moby->state = 2; + moby->state = INFOBOT_WAIT_FOR_PLAYER; break; } heading = @@ -437,14 +437,14 @@ void infobot_update(struct Moby *moby) { D_0015ED6C * 1.5707964f, &infobot->spin[0]); if (fast_vec_dist(&D_0013F350.target, &moby->pos) < 8.0f) { - moby->state = 4; + moby->state = INFOBOT_FOLLOW_SLOT_PATH; set_moby_dialogue_record_value(moby, 1); } break; case INFOBOT_FOLLOW_SLOT_PATH: FUN_L00_002d5988_2d5de8(moby, toad_paths[infobot->slots[infobot->seg]], 3); FUN_L00_002d6cd0_2d5de8(moby); - if (moby->state != 4) { + if (moby->state != INFOBOT_FOLLOW_SLOT_PATH) { infobot->seg++; } break; @@ -471,7 +471,7 @@ void infobot_update(struct Moby *moby) { if (infobot->path == -1) { break; } - moby->state = 6; + moby->state = INFOBOT_FOLLOW_PATH; infobot->attach = -1; MPOS(moby)->q = toad_paths[infobot->path]->pts[0].q; moby->rot.z = fast_arc_tan( @@ -505,7 +505,7 @@ void infobot_update(struct Moby *moby) { if (segment >= path->count - 1) { if (infobot->speed <= D_0015ED70 * 16.0f) { MPOS(moby)->q = ((Vec *)path)[path->count].q; - moby->state = 7; + moby->state = INFOBOT_ORBIT_PATH_ENDPOINT; break; } segment = path->count - 2; @@ -563,7 +563,7 @@ void infobot_update(struct Moby *moby) { MPOS(moby)->q = step.q; if (fast_vec_dist(&D_0013F3D0, &orbit_path->pts[orbit_path->count - 1]) < 2.0f && D_0013F3D0.active != 0) { - moby->state = 8; + moby->state = INFOBOT_START_SCENE_SEQUENCE; } moby->rot.y = spring_turn(moby->rot.y, 0.0f, @@ -587,7 +587,7 @@ void infobot_update(struct Moby *moby) { jet_reset_camera(&D_L00_001600EC_2d5de8[infobot->cutscene].pos, &D_L00_001600EC_2d5de8[infobot->cutscene].dir); } - moby->state = 9; + moby->state = INFOBOT_WAIT_TO_DISPATCH_MSG1; if (infobot->msg0 != -1) { start_scene(infobot->msg0); } @@ -596,7 +596,7 @@ void infobot_update(struct Moby *moby) { if (D_L00_0015F5C4 == 2) { break; } - moby->state = 10; + moby->state = INFOBOT_WAIT_TO_START_FINAL_SCENE; if (infobot->msg1 != -1) { queue_scene_movie_with_game_language(infobot->msg1); } @@ -608,7 +608,7 @@ void infobot_update(struct Moby *moby) { if (infobot->msg2 != -1) { start_scene(infobot->msg2); } - moby->state = 11; + moby->state = INFOBOT_SAVE_AND_REMOVE; break; case INFOBOT_SAVE_AND_REMOVE: if (D_L00_0015F5C4 == 2) { From dd4a05be9e539df302c833cb1ee818d53d1b07fd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:07:54 +0000 Subject: [PATCH 1284/1502] decomp: clarify names in bolt_crank_update domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 002e0de0 constructs hero.motion.pos at 0x0013f3d0; 002e0e08 subtracts 0x80 to obtain hero base 0x0013f350. The lbu v0,0x20a4(s0) at 002e0e0c therefore reads hero.vehicle_mode, and bnel v0,zero at 002e0e10 skips crank activation for nonzero modes. The zero path checks hero facing, height, equipped item and input before entering HERO_STATE_CRANK at 002e0f88. This is the exact hero.vehicle_mode selector in the bound source, belonging to the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT. The distinct hero.state.current load at 002e0cdc uses hero+0x2084, so neither HERO_STATE_IDLE nor any Moby.state constant applies. --- src/overlays/shared/props/bolt_crank.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/props/bolt_crank.c b/src/overlays/shared/props/bolt_crank.c index 8cb5c32de7..e77a91001b 100644 --- a/src/overlays/shared/props/bolt_crank.c +++ b/src/overlays/shared/props/bolt_crank.c @@ -133,7 +133,7 @@ void bolt_crank_update(struct Moby *moby) { } distance = vector_distance_xy(&moby->pos, &hero.motion.pos); if (distance < 1.75f) { - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { angle = fast_arc_tan(moby->pos.x - hero.motion.pos.f[0], moby->pos.y - hero.motion.pos.f[1]); yaw_diff = fast_difference_between_rotations(hero.motion.rot.f[2], angle); From 8f84ddb820f040931abac20730a81dfa9230652d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:07:54 +0000 Subject: [PATCH 1285/1502] decomp: clarify names in update_explosive_projectile domain_0_value_1 -> EXPLOSIVE_PROJECTILE_STATE_BURST: Retail 0x002f6d28-0x002f6d44 compares distance from pvars+0x10 target to moby position against pvars+0x38. On arrival 0x002f6d4c-0x002f6d58 copies target to position and stores 1 to moby+0x20 (moby->state). The subsequent load and zero test at 0x002f6d5c-0x002f6d60 enter the layered burst effects, optional radial collection at 0x002f6df8, and final removal at 0x002f76d0. Thus value 1 requests this projectile's burst state, independent of all supplied hero enum domains. domain_1_value_0 -> EXPLOSIVE_PROJECTILE_STATE_FLYING: Retail 0x002f6a94-0x002f6ab4 loads projectile pvars velocity and adds it to moby position; 0x002f6c18 and 0x002f6cb0 emit trail effects. Target arrival sets moby+0x20 to 1 at 0x002f6d58. At 0x002f6d60 a zero state branches directly to the return epilogue 0x002f76d8, preserving the moving projectile and bypassing every burst effect and final removal. This proves zero is the continuing flight state of this projectile, not an equal-valued hero state or control mode. --- src/overlays/shared/enemies/bomber_jet_projectile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/bomber_jet_projectile.c b/src/overlays/shared/enemies/bomber_jet_projectile.c index 40193cdbea..4ff63332f2 100644 --- a/src/overlays/shared/enemies/bomber_jet_projectile.c +++ b/src/overlays/shared/enemies/bomber_jet_projectile.c @@ -96,7 +96,7 @@ void explosive_projectile_update(struct Moby *moby) __asm__("FUN_L01_002f6a30"); /* Moby class 686 */ void explosive_projectile_update(struct Moby *moby) { - Vec_2F7E08 old_pos; + enum { EXPLOSIVE_PROJECTILE_STATE_FLYING = 0 , EXPLOSIVE_PROJECTILE_STATE_BURST = 1 } ;Vec_2F7E08 old_pos; Vec_2F7E08 smoke_pos; Data *projectile_vars; int rate_divisor; @@ -169,9 +169,9 @@ void explosive_projectile_update(struct Moby *moby) { if (fast_vec_dist(&projectile_vars->target, &(*(Vec_2F7E08 *)&moby->pos)) < projectile_vars->f38) { qcopy(&(*(Vec_2F7E08 *)&moby->pos), &projectile_vars->target); - moby->state = 1; + moby->state = EXPLOSIVE_PROJECTILE_STATE_BURST; } - if (moby->state != 0) { + if (moby->state != EXPLOSIVE_PROJECTILE_STATE_FLYING) { size_scale = 8.0f; camera_distance = fast_vec_dist(camera_pos, &(*(Vec_2F7E08 *)&moby->pos)); if (cutscene_active_macro != 0) { From 8a19f076385673495b3e77fbfba084446292aa7e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:11:41 +0000 Subject: [PATCH 1286/1502] decomp: clarify names in update_drone domain_0_value_254 -> MOBY_STATE_MARKED_FOR_REMOVAL: Retail 002ce490-002ce498 loads slot drone Moby+0x20 and clears its slot on FE. update_drone calls mark_moby_for_removal at 002cf1b4; checked helper 0024eb78-0024eb90 selects FE on its >=0015ffdc branch and stores it to the same Moby state byte. This proves a marked-for-removal Moby state, independent of drone states 2-5. domain_2_value_254 -> MOBY_STATE_MARKED_FOR_REMOVAL: Retail 002ce5a4-002ce5b8 reaches a drone's target through pvars+0x30, loads target Moby+0x20 and treats FE like no usable target for reassignment. Checked directly called removal helper 0024eb8c-0024eb90 writes FE to Moby+0x20 when marking removal. Both selectors are the same generic Moby state domain. domain_4_value_254 -> MOBY_STATE_MARKED_FOR_REMOVAL: Retail 002ced6c-002ced90 loads drone_vars target, checks its oclass, then tests target Moby+0x20 against FE before pursuit. Checked mark_moby_for_removal 0024eb8c-0024eb90 stores FE into that Moby state byte; FE therefore denotes a moby marked for removal and invalid for pursuit. domain_6_value_254 -> MOBY_STATE_MARKED_FOR_REMOVAL: Retail 002cee9c-002ceeac loads the collision-hit Moby from coll_hit+0x18 and rejects state FE from its +0x20 byte before target-hit processing. The assigned function's directly called mark_moby_for_removal helper writes FE to Moby+0x20 at 0024eb8c-0024eb90, proving the generic Moby removal-state domain. domain_8_value_254 -> MOBY_STATE_MARKED_FOR_REMOVAL: Retail 002cf088-002cf0ac loads the fading drone's target, validates class, and compares target Moby+0x20 with FE, branching to target clear at 002cf16c. Checked directly called removal helper 0024eb8c-0024eb90 writes FE to precisely Moby+0x20, proving a marked-for-removal target state. --- src/overlays/shared/weapons/drone.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/shared/weapons/drone.c b/src/overlays/shared/weapons/drone.c index 2c98cf3399..42f8108a5e 100644 --- a/src/overlays/shared/weapons/drone.c +++ b/src/overlays/shared/weapons/drone.c @@ -351,7 +351,7 @@ void drone_update(struct Moby *updated_moby) __asm__("FUN_L00_002ce358"); /* Moby class 479 */ void drone_update(struct Moby *updated_moby) { - enum { DRONE_STATE_ORBIT = 2 , DRONE_STATE_PURSUE_TARGET = 3 , DRONE_STATE_FADE = 4 , DRONE_STATE_REMOVE = 5 } ;DroneVars *drone_vars = (DroneVars *)updated_moby->pvars; + enum { DRONE_STATE_ORBIT = 2 , DRONE_STATE_PURSUE_TARGET = 3 , DRONE_STATE_FADE = 4 , DRONE_STATE_REMOVE = 5 } ; enum { MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE} ;DroneVars *drone_vars = (DroneVars *)updated_moby->pvars; Vec4 collision_data[1], old_pos; Vec4 direction, rotated; Vec4 target_pos, matrix[4]; @@ -384,7 +384,7 @@ void drone_update(struct Moby *updated_moby) { drone = ((DroneSlots *)&hero)->slots[k]; if (drone != 0) { if (drone->oclass == 0x1DF) { - if (drone->state == 0xFE) { + if (drone->state == MOBY_STATE_MARKED_FOR_REMOVAL) { ((DroneSlots *)&hero)->slots[k] = 0; } else if (drone->state == 0xFD) { ((DroneSlots *)&hero)->slots[k] = 0; @@ -416,7 +416,7 @@ void drone_update(struct Moby *updated_moby) { drone = ((DroneSlots *)&hero)->slots[i]; if (drone != 0) { struct Moby *drone_target = *(struct Moby **)(drone->pvars + 0x30); - if (drone_target == 0 || drone_target->state == 0xFE || + if (drone_target == 0 || drone_target->state == MOBY_STATE_MARKED_FOR_REMOVAL || drone_target->state == 0xFD) { f32 candidate_distance = vector_distance_xy(&drone->pos, &old_pos); if (candidate_distance < distance) { @@ -609,7 +609,7 @@ state3: { updated_moby->collision = pclass->collision; func_L00_002CF328_2CF808(updated_moby); target = drone_vars->target; - if (target != 0 && target->oclass == drone_vars->target_oclass && target->state != 0xFE && + if (target != 0 && target->oclass == drone_vars->target_oclass && target->state != MOBY_STATE_MARKED_FOR_REMOVAL && target->state != 0xFD) { char *h = get_moby_target_info(target); qcopy(&target_pos, &drone_vars->target->pos); @@ -625,7 +625,7 @@ state3: { qcopy(&collision_data[0], &updated_moby->pos); if (coll_sphere(0.25f, &collision_data[0], 0, updated_moby)) { struct Moby *hm = (struct Moby *)coll_hit.moby; - if (!hm || hm->state == 0xFE || hm->state == 0xFD || hm != drone_vars->target || + if (!hm || hm->state == MOBY_STATE_MARKED_FOR_REMOVAL || hm->state == 0xFD || hm != drone_vars->target || hm->oclass == 0) { qcopy(&updated_moby->pos, &coll_hit_position); } else { @@ -689,7 +689,7 @@ state4: { goto fade_clear; if (target->oclass != drone_vars->target_oclass) goto fade_clear; - if (target->state == 0xFE) + if (target->state == MOBY_STATE_MARKED_FOR_REMOVAL) goto fade_clear; if (target->state == 0xFD) goto fade_clear; From 38e8495907df8d1c7659bb4c510f80392535bcba Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:13:28 +0000 Subject: [PATCH 1287/1502] decomp: clarify names in gunship_follow_path domain_0_value_0 -> GUNSHIP_PATH_STATE_INITIALIZE: Retail 002f5204..002f5210 reads moby byte +0x20 and excludes zero and three from group checks. This is the identical byte dispatched at 002f5464..002f54a4; zero enters path initialization, already named GUNSHIP_PATH_STATE_INITIALIZE in the SHA-bound source. domain_1_value_3 -> GUNSHIP_PATH_STATE_WAIT_FOR_RESUME_TIMER: Retail 002f5204..002f5210 compares moby byte +0x20 to three. The same state byte dispatches to 002f59b4..002f59cc, decrementing pvars+0x11c and resuming state one on expiry; the source already calls this GUNSHIP_PATH_STATE_WAIT_FOR_RESUME_TIMER. domain_2_value_0 -> GUNSHIP_PATH_STATE_INITIALIZE: Retail 002f533c..002f5340 suppresses voice allocation while moby byte +0x20 is zero. The same byte is the state selector at 002f5464, with zero reaching initialization at 002f54a4; reuse the existing GUNSHIP_PATH_STATE_INITIALIZE member. domain_3_value_2 -> GUNSHIP_PATH_STATE_WAIT_FOR_PATH: Retail 002f55e0..002f55f8 detects path_id at cursor+0x14 equal to -1 and stores two into moby+0x20. State two dispatches to 002f5958, waits until path_id exists, and resets to initialization. This matches the existing GUNSHIP_PATH_STATE_WAIT_FOR_PATH. domain_6_value_3 -> GUNSHIP_PATH_STATE_WAIT_FOR_RESUME_TIMER: Retail 002f5918..002f5928 tests signed pvars+0x11c positive and stores three to moby+0x20. State three at 002f59b4 decrements that exact timer before returning to follow state, proving the existing GUNSHIP_PATH_STATE_WAIT_FOR_RESUME_TIMER. domain_7_value_1 -> GUNSHIP_PATH_STATE_FOLLOW_PATH: Retail 002f591c..002f5954 completes initialization without a positive resume timer by writing one to moby+0x20. Dispatch 002f546c sends this state to spline advancement and interpolated movement at 002f59d0 onward, matching existing GUNSHIP_PATH_STATE_FOLLOW_PATH. domain_8_value_0 -> GUNSHIP_PATH_STATE_INITIALIZE: Retail 002f5958..002f5968 returns while cursor path_id is -1, otherwise stores zero to moby+0x20. The identical selector sends zero to path setup at 002f54a4, so this reset reuses existing GUNSHIP_PATH_STATE_INITIALIZE. domain_9_value_1 -> GUNSHIP_PATH_STATE_FOLLOW_PATH: Retail 002f59b4..002f59cc decrements pvars+0x11c, clears it on expiry and stores s0=one to moby+0x20. That state dispatches at 002f546c to interpolated movement 002f59d0; reuse the existing GUNSHIP_PATH_STATE_FOLLOW_PATH. --- src/overlays/shared/vehicles/gunship.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/vehicles/gunship.c b/src/overlays/shared/vehicles/gunship.c index 71b7463ff8..90f6cbc245 100644 --- a/src/overlays/shared/vehicles/gunship.c +++ b/src/overlays/shared/vehicles/gunship.c @@ -225,7 +225,7 @@ void gunship_update(struct Moby *moby) { return; } path_cursor = &v->path; - if (moby->group != 0xFF && moby->state != 0 && moby->state != 3) { + if (moby->group != 0xFF && moby->state != GUNSHIP_PATH_STATE_INITIALIZE && moby->state != GUNSHIP_PATH_STATE_WAIT_FOR_RESUME_TIMER) { s32 bad = 0; get_first_moby_in_group(&it, moby->group, 0, 0); if (it == moby) { @@ -253,7 +253,7 @@ void gunship_update(struct Moby *moby) { } if ((moby->oclass == 0x33 || moby->oclass == 0x46A || moby->oclass == 0x473 || moby->oclass == 0x474) && - (level_frame_count & 7) == (((s32)moby >> 8) & 7) && v->unk13A <= 0 && moby->state != 0 && + (level_frame_count & 7) == (((s32)moby >> 8) & 7) && v->unk13A <= 0 && moby->state != GUNSHIP_PATH_STATE_INITIALIZE && FUN_L00_0028d8c0(moby, v->unk11E) == 0) { v->unk11E = allocate_voice_for_target_entry(0, 4, moby); } @@ -301,7 +301,7 @@ void gunship_update(struct Moby *moby) { if (500.0f < v->unk134) v->unk134 = FUN_002132a8(-1.0f, 1.0f) * v->unk134 / 1000.0f; if (path_cursor->path_id == -1) { - moby->state = 2; + moby->state = GUNSHIP_PATH_STATE_WAIT_FOR_PATH; return; } v->unk121 = (moby - (struct Moby *)D_L01_0015FFD8) / 2 % 7; @@ -364,18 +364,18 @@ void gunship_update(struct Moby *moby) { } } if (v->unk11C > 0) { - moby->state = 3; + moby->state = GUNSHIP_PATH_STATE_WAIT_FOR_RESUME_TIMER; return; } if (D_0015ED84 == 3 || D_0015ED84 == 9) v->unk13A = 0; - moby->state = 1; + moby->state = GUNSHIP_PATH_STATE_FOLLOW_PATH; return; case GUNSHIP_PATH_STATE_WAIT_FOR_PATH: if (path_cursor->path_id == -1) return; - moby->state = 0; + moby->state = GUNSHIP_PATH_STATE_INITIALIZE; if (v->unk11E != -1) { u8 *e = (u8 *)((char *)&voice_pool) + v->unk11E * 0x70; if (*(struct Moby **)(e + 0x88) == moby && e[0x74] != 0) @@ -387,7 +387,7 @@ void gunship_update(struct Moby *moby) { case GUNSHIP_PATH_STATE_WAIT_FOR_RESUME_TIMER: if (fast_dec_timer_s16(&v->unk11C)) { v->unk11C = 0; - moby->state = 1; + moby->state = GUNSHIP_PATH_STATE_FOLLOW_PATH; } return; From a6aee8048a25c0e0c3b8c18184447361d242ba3f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:15:11 +0000 Subject: [PATCH 1288/1502] decomp: clarify names in process_hero_primary_item_input domain_0_value_0 -> WRENCH_MOBY_STATE_READY: Retail 0x251d28 loads hero.items[0].moby (+0x1090); 0x251d34 verifies it with source-established is_wrench_moby, whose supplied definition tests oclass 0x47. Instructions 0x251d44-0x251d48 read that moby's state byte +0x20 and reject every nonzero state before wrench swing/throw dispatch. Zero therefore denotes the wrench moby's attack-ready state. Checked helper launch_hero_wrench at 0x244758, called at 0x251dc4, reloads this equipped moby at 0x244878, verifies it at 0x24487c, sets the slot thrown flag at 0x244890, then writes 10 to the same moby state byte at 0x2448a0-0x2448b0 while initializing throw motion. This proves a wrench-moby state domain separate from hero.state.current; READY describes the proven input gate without asserting a full lifecycle. --- src/overlays/shared/hero/process_hero_primary_item_input.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/process_hero_primary_item_input.c b/src/overlays/shared/hero/process_hero_primary_item_input.c index ab495a767f..2487a091e2 100644 --- a/src/overlays/shared/hero/process_hero_primary_item_input.c +++ b/src/overlays/shared/hero/process_hero_primary_item_input.c @@ -683,6 +683,9 @@ int process_hero_primary_item_input(void) { ITEM_AMMO_MENU_DEVICE = 32, ITEM_RACE_PROJECTILE = 36 }; + enum { + WRENCH_MOBY_STATE_READY = 0 + }; float joint_pos[4]; int press_time0, press_time1, press_time2; int start_timer; @@ -725,7 +728,7 @@ int process_hero_primary_item_input(void) { if (!is_wrench_moby(item)) { break; } - if (item->state != 0) { + if (item->state != WRENCH_MOBY_STATE_READY) { break; } if ((controller_state.held & 0xA) || From ac9048059fd2434787b89f2ce6215acd60f583e3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:15:11 +0000 Subject: [PATCH 1289/1502] decomp: clarify names in helicopter_update domain_1_value_2 -> HELICOPTER_GOAL_UNAVAILABLE: 0x002c57ac..0x002c57b0 range override: Goal status is the word at sp+0x74, output+0x44 of checked level-15 helpers 0x0024f560/0x0024f7e0, separate from moby+0x20 state and hero.vehicle_mode. Helper 0x0024f5c8..0x0024f5cc clears the default target and sets status 2; 0x0024f85c..0x0024f870 and 0x0024f918..0x0024f930 also set 2 on excluded/restricted default goals. Alternate selection sets 1 (0x0024fa44..0x0024fa48), and final status writes occur at 0x0024f7a4 / 0x0024fc30. Caller 0x002c579c..0x002c57b0 overrides status to 2 when goal distance exceeds range. Thus 2 denotes an unavailable goal, not only out of range. domain_2_value_2 -> HELICOPTER_GOAL_UNAVAILABLE: 0x002c5a64..0x002c5a6c activation guard: Goal status is the word at sp+0x74, output+0x44 of checked level-15 helpers 0x0024f560/0x0024f7e0, separate from moby+0x20 state and hero.vehicle_mode. Helper 0x0024f5c8..0x0024f5cc clears the default target and sets status 2; 0x0024f85c..0x0024f870 and 0x0024f918..0x0024f930 also set 2 on excluded/restricted default goals. Alternate selection sets 1 (0x0024fa44..0x0024fa48), and final status writes occur at 0x0024f7a4 / 0x0024fc30. Caller 0x002c579c..0x002c57b0 overrides status to 2 when goal distance exceeds range. Thus 2 denotes an unavailable goal, not only out of range. domain_3_value_2 -> HELICOPTER_GOAL_UNAVAILABLE: 0x002c5ae0..0x002c5ae8 activation guard: Goal status is the word at sp+0x74, output+0x44 of checked level-15 helpers 0x0024f560/0x0024f7e0, separate from moby+0x20 state and hero.vehicle_mode. Helper 0x0024f5c8..0x0024f5cc clears the default target and sets status 2; 0x0024f85c..0x0024f870 and 0x0024f918..0x0024f930 also set 2 on excluded/restricted default goals. Alternate selection sets 1 (0x0024fa44..0x0024fa48), and final status writes occur at 0x0024f7a4 / 0x0024fc30. Caller 0x002c579c..0x002c57b0 overrides status to 2 when goal distance exceeds range. Thus 2 denotes an unavailable goal, not only out of range. domain_4_value_2 -> HELICOPTER_GOAL_UNAVAILABLE: 0x002c5d48..0x002c5d64 engagement/holding transition: Goal status is the word at sp+0x74, output+0x44 of checked level-15 helpers 0x0024f560/0x0024f7e0, separate from moby+0x20 state and hero.vehicle_mode. Helper 0x0024f5c8..0x0024f5cc clears the default target and sets status 2; 0x0024f85c..0x0024f870 and 0x0024f918..0x0024f930 also set 2 on excluded/restricted default goals. Alternate selection sets 1 (0x0024fa44..0x0024fa48), and final status writes occur at 0x0024f7a4 / 0x0024fc30. Caller 0x002c579c..0x002c57b0 overrides status to 2 when goal distance exceeds range. Thus 2 denotes an unavailable goal, not only out of range. domain_5_value_2 -> HELICOPTER_GOAL_UNAVAILABLE: 0x002c5f50..0x002c5f64 engagement/holding transition: Goal status is the word at sp+0x74, output+0x44 of checked level-15 helpers 0x0024f560/0x0024f7e0, separate from moby+0x20 state and hero.vehicle_mode. Helper 0x0024f5c8..0x0024f5cc clears the default target and sets status 2; 0x0024f85c..0x0024f870 and 0x0024f918..0x0024f930 also set 2 on excluded/restricted default goals. Alternate selection sets 1 (0x0024fa44..0x0024fa48), and final status writes occur at 0x0024f7a4 / 0x0024fc30. Caller 0x002c579c..0x002c57b0 overrides status to 2 when goal distance exceeds range. Thus 2 denotes an unavailable goal, not only out of range. domain_6_value_2 -> HELICOPTER_GOAL_UNAVAILABLE: 0x002c5fa0..0x002c5fa8 holding guard: Goal status is the word at sp+0x74, output+0x44 of checked level-15 helpers 0x0024f560/0x0024f7e0, separate from moby+0x20 state and hero.vehicle_mode. Helper 0x0024f5c8..0x0024f5cc clears the default target and sets status 2; 0x0024f85c..0x0024f870 and 0x0024f918..0x0024f930 also set 2 on excluded/restricted default goals. Alternate selection sets 1 (0x0024fa44..0x0024fa48), and final status writes occur at 0x0024f7a4 / 0x0024fc30. Caller 0x002c579c..0x002c57b0 overrides status to 2 when goal distance exceeds range. Thus 2 denotes an unavailable goal, not only out of range. domain_7_value_2 -> HELICOPTER_GOAL_UNAVAILABLE: 0x002c5ff0..0x002c60e4 firing/holding branch: Goal status is the word at sp+0x74, output+0x44 of checked level-15 helpers 0x0024f560/0x0024f7e0, separate from moby+0x20 state and hero.vehicle_mode. Helper 0x0024f5c8..0x0024f5cc clears the default target and sets status 2; 0x0024f85c..0x0024f870 and 0x0024f918..0x0024f930 also set 2 on excluded/restricted default goals. Alternate selection sets 1 (0x0024fa44..0x0024fa48), and final status writes occur at 0x0024f7a4 / 0x0024fc30. Caller 0x002c579c..0x002c57b0 overrides status to 2 when goal distance exceeds range. Thus 2 denotes an unavailable goal, not only out of range. --- src/overlays/l15/mobys/helicopter.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/overlays/l15/mobys/helicopter.c b/src/overlays/l15/mobys/helicopter.c index bfe7be678d..2546b9100c 100644 --- a/src/overlays/l15/mobys/helicopter.c +++ b/src/overlays/l15/mobys/helicopter.c @@ -399,6 +399,9 @@ void helicopter_update(struct Moby *moby) { HELICOPTER_DEATH_EFFECTS = 7, HELICOPTER_DEAD_WAIT_FOR_RESET = 0x40 }; + enum { + HELICOPTER_GOAL_UNAVAILABLE = 2 + }; Vec4 previous_pos; HelicopterGoal goal; Vec4 move; @@ -450,7 +453,7 @@ void helicopter_update(struct Moby *moby) { helicopter_instance_vars->chase_range, moby, &goal, 0, 0, path->points, path->count); } if (helicopter_instance_vars->range < fast_vec_dist(&moby->pos, &goal)) - goal.status = 2; + goal.status = HELICOPTER_GOAL_UNAVAILABLE; if (goal.target == 0) goal.target = hero.moby; target = goal.target; @@ -516,7 +519,7 @@ void helicopter_update(struct Moby *moby) { if (helicopter_instance_vars->wait_group != -1 || (is_point_inside_clip_volume(&hero.motion.pos, helicopter_instance_vars->trigger_volume) && - goal.status != 2)) { + goal.status != HELICOPTER_GOAL_UNAVAILABLE)) { if (helicopter_instance_vars->wait_group != -1 && count_active_moby_group_members(helicopter_instance_vars->wait_group, 0x40)) break; @@ -530,7 +533,7 @@ void helicopter_update(struct Moby *moby) { } else { if (helicopter_instance_vars->trigger_volume != -1) break; - if (goal.status == 2) + if (goal.status == HELICOPTER_GOAL_UNAVAILABLE) break; moby->collision = moby->pclass->collision; moby->flags = (moby->flags & 0xFFBE) | 0x1000; @@ -573,7 +576,7 @@ void helicopter_update(struct Moby *moby) { point_in_path_xy(&moby->pos, D_L15_001B0AB0[helicopter_instance_vars->area_path]->points, D_L15_001B0AB0[helicopter_instance_vars->area_path]->count)) { - if (goal.status != 2) { + if (goal.status != HELICOPTER_GOAL_UNAVAILABLE) { moby->state = HELICOPTER_ENGAGE_AND_FIRE; helicopter_instance_vars->fire_timer = 0; } else { @@ -643,7 +646,7 @@ void helicopter_update(struct Moby *moby) { steer_helicopter(moby, (SteeringVec_4f88 *)&move, (SteeringVec_4f88 *)&point); if (vector_distance_xy(&move, &moby->pos) < 1.0f || point_in_path_xy(&moby->pos, path->points, path->count)) { - if (goal.status != 2) { + if (goal.status != HELICOPTER_GOAL_UNAVAILABLE) { moby->state = HELICOPTER_ENGAGE_AND_FIRE; helicopter_instance_vars->fire_timer = 0; } else { @@ -658,7 +661,7 @@ void helicopter_update(struct Moby *moby) { move.q = *(u128 *)&moby->pos; point.q = *(u128 *)&target->pos; steer_helicopter(moby, (SteeringVec_4f88 *)&move, (SteeringVec_4f88 *)&point); - if (goal.status == 2) + if (goal.status == HELICOPTER_GOAL_UNAVAILABLE) break; if (point_in_path_xy(&moby->pos, path->points, path->count)) { moby->state = HELICOPTER_ENGAGE_AND_FIRE; @@ -670,7 +673,7 @@ void helicopter_update(struct Moby *moby) { } case HELICOPTER_ENGAGE_AND_FIRE: moby_point_position(moby, 0, &point); - if (goal.status != 2) { + if (goal.status != HELICOPTER_GOAL_UNAVAILABLE) { compute_helicopter_flocking_steering_point(moby, move.f, *(Goal_52b8 *)&goal); aim.q = *(u128 *)&target->pos; steer_helicopter(moby, (SteeringVec_4f88 *)&move, (SteeringVec_4f88 *)&aim); From 46b04247355a4022001695d686e76d2852a54201 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:15:11 +0000 Subject: [PATCH 1290/1502] decomp: clarify names in update_hoven_anklebiter domain_2_value_5 -> ANKLEBITER_LEAP_TO_HOME_MOTION_FLAGS: Bound source src/overlays/l12/mobys/hoven_anklebiter.c SHA-256 43cccd070c334568882152a6fb7ac6bc7d36385252c55871529fc142c64b6ecf sets data->fall_mode=5 only during WAIT_FOR_LEAP_TRIGGER trajectory setup. Retail 002e24e0-002e2534 scales launch/gravity, computes the trajectory from moby position to home and stores 5 at data+0x144. 002e2540 passes data+0x120 as the motion record; 002e2574 selects LEAP_TO_HOME, whose 002e2598 call advances that same record. Bounded level-12 helper 00275588 reads record+0x24 as flags: 00275a78-00275ab8 masks 4 and bypasses heading interpolation when set; other masks 0x10 and 0x20 occur at 00275700 and 00275b6c. Setup helper 00275448 likewise masks/ORs flags at record+0x24 (00275518-00275528). Therefore 5 is the contextual leap-to-home motion flag preset, separate from moby->state MELEE_ATTACK=5; no individual bit-1 meaning claimed. --- src/overlays/l12/mobys/hoven_anklebiter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l12/mobys/hoven_anklebiter.c b/src/overlays/l12/mobys/hoven_anklebiter.c index 380d635976..83cd837e99 100644 --- a/src/overlays/l12/mobys/hoven_anklebiter.c +++ b/src/overlays/l12/mobys/hoven_anklebiter.c @@ -306,6 +306,9 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { ANKLEBITER_DEATH_EFFECTS_AND_REMOVE = 15, ANKLEBITER_DEATH_FALL = 99 }; + enum { + ANKLEBITER_LEAP_TO_HOME_MOTION_FLAGS = 5 + }; TargetReport target_report_or_vector_scratch; AnklebiterMoby *iterator; float trajectory; @@ -481,7 +484,7 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { &trajectory, data->launch_speed, -hoven_anklebiter_leap_gravity_gp); - data->fall_mode = 5; + data->fall_mode = ANKLEBITER_LEAP_TO_HOME_MOTION_FLAGS; data->falling = 0; setup_fall54(moby->rot[2], (char *)moby, data->fall, 8, 1, 0); data->fall_a = 5.0f; From d5de43c2b960205cc0f0f491492495d0ded656bd Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:17:19 +0000 Subject: [PATCH 1291/1502] decomp: clarify names in update_debug_menu domain_3_value_0 -> DEBUG_OCCLUSION_MODE_NO_DATA_FALLBACK: Retail 001f4a50..001f4a68 loads D_L00_0015F600, tests against zero, and on null stores zero to menu+0x1c. The authoritative C and original Ghidra identify this field as g_debug_menu.occlusion_mode. Thus zero is the mode forced when occlusion data is absent; this name makes no unsupported OFF claim. domain_4_value_0 -> DEBUG_OCCLUSION_MODE_NO_DATA_FALLBACK: Retail 001f4a7c..001f4a90 increments the same menu+0x1c occlusion selector and wraps it to zero at count three. This is the identical field and value forced by the absent-data branch at 001f4a50..001f4a68, proving reuse of DEBUG_OCCLUSION_MODE_NO_DATA_FALLBACK rather than any equal-valued hero constant. domain_5_value_0 -> DEBUG_OCCLUSION_MODE_NO_DATA_FALLBACK: Retail 001f4aa8..001f4ac0 decrements menu+0x1c and uses bgez to detect crossing below zero before wrapping to two. The lower comparison is against the same zero occlusion mode forced when D_L00_0015F600 is null at 001f4a50..001f4a68; authoritative C confirms this selector is g_debug_menu.occlusion_mode. --- src/overlays/shared/rendering/debug/update_debug_menu.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/rendering/debug/update_debug_menu.c b/src/overlays/shared/rendering/debug/update_debug_menu.c index 139a5b385e..e524b77bf7 100644 --- a/src/overlays/shared/rendering/debug/update_debug_menu.c +++ b/src/overlays/shared/rendering/debug/update_debug_menu.c @@ -518,6 +518,9 @@ void update_debug_menu(void) { DEBUG_CAPTURE_STATUS_NO = 110, DEBUG_CAPTURE_STATUS_YES = 121 }; + enum { + DEBUG_OCCLUSION_MODE_NO_DATA_FALLBACK = 0 + }; DebugRowCounts row_counts; union { struct { @@ -629,15 +632,15 @@ void update_debug_menu(void) { break; case DEBUG_OPTION_ROW_OCCLUSION_MODE: if (!D_L00_0015F600) { - g_debug_menu.occlusion_mode = 0; + g_debug_menu.occlusion_mode = DEBUG_OCCLUSION_MODE_NO_DATA_FALLBACK; break; } if (controller_words.buttons.w.pressed & 0x40) { if (++g_debug_menu.occlusion_mode >= DEBUG_OCCLUSION_MODE_COUNT) - g_debug_menu.occlusion_mode = 0; + g_debug_menu.occlusion_mode = DEBUG_OCCLUSION_MODE_NO_DATA_FALLBACK; } if (controller_words.buttons.w.pressed & 0x10) { - if (--g_debug_menu.occlusion_mode < 0) + if (--g_debug_menu.occlusion_mode < DEBUG_OCCLUSION_MODE_NO_DATA_FALLBACK) g_debug_menu.occlusion_mode = 2; } break; From ea687a2ac65a4e5bfe2286b306f496c76feee913 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:17:19 +0000 Subject: [PATCH 1292/1502] decomp: clarify names in memcard_update_state domain_0_value_0 -> MEMCARD_QUERY_INFO: Retail 00209520 loads pending operation from memory-card base+0xdc and 00209524 branches on negativity; 00209548 stores that same v1 directly to base+0xd4, the major operation selector loaded at 00209420. Thus pending_state uses exactly the MemoryCardOperation domain, as also documented in include/rnc/save/memory_card_state.h. Its nonnegative lower bound is the canonical zero member MEMCARD_QUERY_INFO, whose branch 00209450-002094a8 requests sceMcGetInfo. The -1 clearing store at 0020955c-00209568 is outside that operation range; this reuse names the lower bound without treating the comparison as equality. --- src/save/memcard_update_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/save/memcard_update_state.c b/src/save/memcard_update_state.c index e1ca141ff6..5820f219a0 100644 --- a/src/save/memcard_update_state.c +++ b/src/save/memcard_update_state.c @@ -77,7 +77,7 @@ void memcard_update_state(void) { break; case MEMCARD_DISPATCH_PENDING_OPERATION: - if (MC.pending_state >= 0) { + if (MC.pending_state >= MEMCARD_QUERY_INFO) { if (MC.card[0].sync_result == 0) { if (MC.pending_card >= 0) { MC.cur = MC.pending_card; From 06eed9ff01603e0c3586e11476fbaade984e63a0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:17:20 +0000 Subject: [PATCH 1293/1502] decomp: clarify names in update_resident_gameplay_state domain_0_value_0 -> LEVEL_RENDER_STATE_PLAYBACK_TO_MENU: Bound source uses level_render_state.state for this comparison and for the existing LEVEL_RENDER_STATE_PLAYBACK_TO_MENU=0 switch label. Retail 0x0022f8b4-0x0022f8e8 loads the same resident selector at 0x0013e050 and gates the variant-indexed early skip target comparison. Original retail decompilation agrees on g_nResidentTextureDisplayMode; this is exact selector identity, not numeric equivalence to a hero state. domain_1_value_8 -> LEVEL_RENDER_STATE_PLAYBACK_WITH_MUSIC_RESUME: Source compares level_render_state.state, the identical selector of existing LEVEL_RENDER_STATE_PLAYBACK_WITH_MUSIC_RESUME=8. Retail 0x0022f8ec-0x0022f918 reloads resident selector 0x0013e050, compares it with 8 and tests time against end minus scaled 30 frames. The original decompilation confirms this shared playback branch; nonzero completion at 0x0022fb48 resumes music. domain_2_value_0 -> LEVEL_RENDER_STATE_PLAYBACK_TO_MENU: Bound source uses level_render_state.state for this comparison and for the existing LEVEL_RENDER_STATE_PLAYBACK_TO_MENU=0 switch label. Retail 0x0022f944-0x0022f9ac loads the same resident selector at 0x0013e050 and selects the variant-indexed skip seek, bank quotient and frame remainder. Original retail decompilation agrees on g_nResidentTextureDisplayMode; this is exact selector identity, not numeric equivalence to a hero state. domain_3_value_255 -> RESIDENT_OBJECT_STATE_LIST_END: Retail 0x0022fab4-0x0022facc loads object_cursor from 0x0015ff1c and its byte at offset 0x20, exiting the scan on 0xff. At 0x0022fb08-0x0022fb14 it advances by the 0x100-byte object stride and repeats until that same sentinel. Original Ghidra while(bVar1 != 0xff) and source object_cursor->state != 0xFF prove the list-termination role without asserting a hero lifecycle state. domain_4_value_0 -> LEVEL_RENDER_STATE_PLAYBACK_TO_MENU: Bound source uses level_render_state.state for this comparison and for the existing LEVEL_RENDER_STATE_PLAYBACK_TO_MENU=0 switch label. Retail 0x0022fb1c-0x0022fb44 loads the same resident selector at 0x0013e050 and selects completion through pause_all_sounds(0), menu_system.state=14 and exit request. Original retail decompilation agrees on g_nResidentTextureDisplayMode; this is exact selector identity, not numeric equivalence to a hero state. domain_7_value_0 -> LEVEL_RENDER_STATE_PLAYBACK_TO_MENU: Bound source uses level_render_state.state for this comparison and for the existing LEVEL_RENDER_STATE_PLAYBACK_TO_MENU=0 switch label. Retail 0x0022fe50-0x0022fe94 loads the same resident selector at 0x0013e050 and selects the state-zero timing branch for playback class 0 shadow control. Original retail decompilation agrees on g_nResidentTextureDisplayMode; this is exact selector identity, not numeric equivalence to a hero state. domain_8_value_0 -> LEVEL_RENDER_STATE_PLAYBACK_TO_MENU: Bound source uses level_render_state.state for this comparison and for the existing LEVEL_RENDER_STATE_PLAYBACK_TO_MENU=0 switch label. Retail 0x0022fee0-0x0022ff0c loads the same resident selector at 0x0013e050 and selects the state-zero 350-frame timing branch for playback class 10. Original retail decompilation agrees on g_nResidentTextureDisplayMode; this is exact selector identity, not numeric equivalence to a hero state. domain_9_value_0 -> LEVEL_RENDER_STATE_PLAYBACK_TO_MENU: Bound source uses level_render_state.state for this comparison and for the existing LEVEL_RENDER_STATE_PLAYBACK_TO_MENU=0 switch label. Retail 0x0023003c-0x00230054 loads the same resident selector at 0x0013e050 and selects the state-zero class-specific playback color/effect timeline. Original retail decompilation agrees on g_nResidentTextureDisplayMode; this is exact selector identity, not numeric equivalence to a hero state. --- src/game/update_resident_gameplay_state.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/game/update_resident_gameplay_state.c b/src/game/update_resident_gameplay_state.c index aeb04cf11e..8c95a05622 100644 --- a/src/game/update_resident_gameplay_state.c +++ b/src/game/update_resident_gameplay_state.c @@ -145,6 +145,9 @@ void update_resident_gameplay_state(void) { LEVEL_RENDER_STATE_GAMEPLAY = 4, LEVEL_RENDER_STATE_PLAYBACK_WITH_MUSIC_RESUME = 8 }; + enum { + RESIDENT_OBJECT_STATE_LIST_END = 0xFF + }; Vector4 scratch_vectors[4]; s32 keyframe_flags; s32 ticks_per_bank; @@ -188,13 +191,13 @@ void update_resident_gameplay_state(void) { skip = level_render_state.skip; if ((controller_state.pressed & (PAD_TRIANGLE | PAD_CROSS)) && scale_game_frames(30) < render_sequence.time && sequence == 0.0f) { - if (level_render_state.state == 0 && + if (level_render_state.state == LEVEL_RENDER_STATE_PLAYBACK_TO_MENU && render_sequence.time < scale_game_frames( playback_skip_target_frames[level_render_state.content_variant] - 30)) { skip = 1; } - if (level_render_state.state == 8 && + if (level_render_state.state == LEVEL_RENDER_STATE_PLAYBACK_WITH_MUSIC_RESUME && render_sequence.time < render_sequence.end - scale_game_frames(30)) { skip = 1; } @@ -204,7 +207,7 @@ void update_resident_gameplay_state(void) { music_stream_state.secondary.state != 7) { music_stream_state.secondary.state = 5; } - if (level_render_state.state == 0) { + if (level_render_state.state == LEVEL_RENDER_STATE_PLAYBACK_TO_MENU) { render_sequence.time = scale_game_frames( playback_skip_target_frames[level_render_state.content_variant]); render_sequence.sequence_frame = render_sequence.time / ticks_per_bank; @@ -241,13 +244,13 @@ void update_resident_gameplay_state(void) { } } level_render_state.player->flags &= ~1; - for (object_cursor = moby_instance_end; object_cursor->state != 0xFF; object_cursor++) { + for (object_cursor = moby_instance_end; object_cursor->state != RESIDENT_OBJECT_STATE_LIST_END; object_cursor++) { if (!(object_cursor->state & 0x80) && (object_cursor->class_id == 0x4A || object_cursor->class_id == 0xCB)) { object_cursor->flags &= ~0x80; } } - if (level_render_state.state == 0) { + if (level_render_state.state == LEVEL_RENDER_STATE_PLAYBACK_TO_MENU) { pause_all_sounds(0); menu_system.state = 0xE; space_load_in_progress[0] = 1; @@ -328,7 +331,7 @@ void update_resident_gameplay_state(void) { playback_object->cached_selector = 0xFF; refresh_moby_spatial_bounds(playback_object); if (playback_object->class_id == 0) { - if (level_render_state.state == 0) { + if (level_render_state.state == LEVEL_RENDER_STATE_PLAYBACK_TO_MENU) { if (current_level_index == 10 && item_available[6] == 0) { playback_object->unk7F = 0; } else if (render_sequence.time <= scale_game_frames(0x3E)) { @@ -346,7 +349,7 @@ void update_resident_gameplay_state(void) { playback_object->unk7F = 0; } } else if (playback_object->class_id == 10) { - if (level_render_state.state == 0) { + if (level_render_state.state == LEVEL_RENDER_STATE_PLAYBACK_TO_MENU) { if (render_sequence.time <= scale_game_frames(350)) { playback_object->unk7F = 0x18; } else { @@ -384,7 +387,7 @@ void update_resident_gameplay_state(void) { if ((u16)playback_object->class_id - 0x213U < 3) { enqueue_callback_list_4(render_environment_mapped_object, playback_object); add_draw_callback(draw_light_flare, playback_object); - if (level_render_state.state == 0) { + if (level_render_state.state == LEVEL_RENDER_STATE_PLAYBACK_TO_MENU) { if (render_sequence.time < scale_game_frames(360)) { s32 color_intensity = (s32)(fast_cos( From 0df5ff97e2762158dd55beebc2ff0d600d9c909c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:19:14 +0000 Subject: [PATCH 1294/1502] decomp: clarify names in update_vendor_menu domain_0_value_0 -> VENDOR_ROW_PURCHASE_REQUEST_ENABLED: Authoritative vendor_menu.c SHA-256 a8d34ee47667db091f2adb234ef33571585a8dc168cd979557cb680ee7c8fe10 defines CUR_ITEM as vendor_menu.rows[vendor_menu.cursor]. Retail 0029d488-0029d49c multiplies cursor at menu+0x58 by the 0x14 row stride and loads row.state at menu+0xD8+cursor*0x14. At 0029d4a0 a nonzero row state skips purchase initialization; zero, after a fresh confirm button test at 0029d46c-0029d480, reaches 0029d4a8-0029d4b0 storing VENDOR_PURCHASE_INITIALIZE into the separate purchase_state field at menu+0x5C. The handler is called at 0029d504. Supplied original Ghidra shows the same selected-row zero comparison and DAT_001ca51c=1. Checked helper 0029ba78 confirms initialization opens the decision UI and checks funds/ammo separately before accepting and finalizing purchases; zero therefore enables requesting the purchase prompt, not guaranteed purchase success. Existing zero-valued constants belong to distinct proven selectors and cannot be reused for this row-state domain. --- src/overlays/shared/vendor/vendor_menu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/vendor/vendor_menu.c b/src/overlays/shared/vendor/vendor_menu.c index a193c81a46..d051f84f45 100644 --- a/src/overlays/shared/vendor/vendor_menu.c +++ b/src/overlays/shared/vendor/vendor_menu.c @@ -1152,6 +1152,9 @@ void update_vendor_menu(void) { VENDOR_PURCHASE_INACTIVE = 0, VENDOR_PURCHASE_INITIALIZE = 1 }; + enum { + VENDOR_ROW_PURCHASE_REQUEST_ENABLED = 0 + }; Vec4 position_scratch; Vec4 position_contribution_scratch; f32 camera_rotation_matrix[4][4]; @@ -1475,7 +1478,7 @@ void update_vendor_menu(void) { } } if ((controller_state.pressed_unmasked & 0x40) && !(l00_vendor_previous_pressed_buttons & 0x40) && - CUR_ITEM.state == 0) { + CUR_ITEM.state == VENDOR_ROW_PURCHASE_REQUEST_ENABLED) { vendor_menu.purchase_state = VENDOR_PURCHASE_INITIALIZE; allocate_voice_for_target_entry(0, 0, vendor_menu.vendor_moby); } From 20d724295e34e2c1853c0938a98bf1ad52826dcc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:19:14 +0000 Subject: [PATCH 1295/1502] decomp: clarify names in doom_bot_update domain_0_value_254 -> MOBY_STATE_PENDING_REMOVAL: Retail 002c0768 loads target_moby from bot pvars+38; 002c0774 loads that Moby's unsigned state byte at +20, and 002c0778 rejects FE. This is the general target Moby lifecycle field, not the bot's 0..15 movement selector. Checked direct helper mark_moby_for_removal at 0024eb68 selects FE at 0024eb8c and stores it to input Moby+20 at 0024eb90, then records global 0015f5cc+2 at Moby+38 (0024eba8-0024ebb0). Assigned detonation calls this helper at 002c13f0. Thus FE is a pending-removal lifecycle marker. Helper evidence request 9ece92f0c1ba422bae66c1ef5bb989d3, report SHA-256 a09daae3bc66f620ad7eeb187bc27bc7236858d02a0a4043b795c91c75caa591. --- src/overlays/shared/weapons/doom_bot.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/doom_bot.c b/src/overlays/shared/weapons/doom_bot.c index 93fb081c5e..1606b38bce 100644 --- a/src/overlays/shared/weapons/doom_bot.c +++ b/src/overlays/shared/weapons/doom_bot.c @@ -175,6 +175,9 @@ void doom_bot_update(struct Moby *moby) { DOOM_BOT_INITIAL_FALL = 14, DOOM_BOT_RESET_TO_INITIALIZE = 15 }; + enum { + MOBY_STATE_PENDING_REMOVAL = 0xFE + }; OvlVec4 movement_and_detonation_vectors[4]; float clearance; DoomBotVars *doom_bot_vars; @@ -334,7 +337,7 @@ void doom_bot_update(struct Moby *moby) { case DOOM_BOT_MOVE_HIGH_TURN_RATE: case DOOM_BOT_MOVE_LOW_TURN_RATE: { target = doom_bot_vars->target_moby; - if (target && target->state != 0xFE && target->state != 0xFD) { + if (target && target->state != MOBY_STATE_PENDING_REMOVAL && target->state != 0xFD) { height = target->pos.z; aim = (AimInfo *)get_moby_target_info((char *)doom_bot_vars->target_moby); reach = speed; From 48a6bb6daa74acc9cf862512e6a3785997683ff5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:19:14 +0000 Subject: [PATCH 1296/1502] decomp: clarify names in update_ground_melee_enemy domain_10_value_3 -> GROUND_ENEMY_STATE_CHASE: Idle command-byte wake check 002e2e78-002e2e8c initializes side angle/timer; 002e2ef8 loads state 3 for the common moby+0x20 store at 002e3e5c, selecting established CHASE. domain_12_value_3 -> GROUND_ENEMY_STATE_CHASE: Accepted target in shared alert arm reaches 002e3000-002e305c side/timer initialization, then 002e3060-002e306c writes 3 to moby+0x20 and starts animation 0: established CHASE. domain_13_value_3 -> GROUND_ENEMY_STATE_CHASE: Command 1 check at 002e2fe4-002e2ff8 reaches the same 002e3000 side/timer setup and state-byte write of 3 at 002e306c; this is established CHASE, as in the source's second shared-arm branch. domain_14_value_4 -> GROUND_ENEMY_STATE_MELEE_ATTACK: Chase movement flags bit 4 or close target without bit 2 at 002e326c-002e32a8 reach 002e32b8 writing 4 to moby+0x20 and animation 1, selecting established MELEE_ATTACK. domain_15_value_5 -> GROUND_ENEMY_STATE_RETURN_HOME: Chase low movement speed, excessive target slope or movement bit 2 at 002e32ec-002e3328 sets the home timer, then writes 5 to moby+0x20 at 002e33c4, selecting established RETURN_HOME. domain_16_value_5 -> GROUND_ENEMY_STATE_RETURN_HOME: Chase target beyond home range/height and absent command 1 at 002e333c-002e33b4 reaches 002e33bc-002e33c4 writing 5 to moby+0x20; same established RETURN_HOME arm navigates to captured home. domain_17_value_3 -> GROUND_ENEMY_STATE_CHASE: Melee animation completion and distance >1.5 at 002e3544-002e3570 lead to 002e3580 writing 3 to moby+0x20 and animation 0; the switch's established CHASE state uses this byte. domain_18_value_1 -> GROUND_ENEMY_STATE_IDLE: Return-home movement compares distance to pvars+0x1d0 with 2 at 002e3710-002e3730, then writes 1 to moby+0x20 at 002e3744 and selects idle animation 2. domain_19_value_3 -> GROUND_ENEMY_STATE_CHASE: Return-home timer and target-within-range checks 002e3784-002e37bc lead to 002e37e0 writing 3 to moby+0x20, resuming established CHASE with animation 0. domain_1_value_99 -> GROUND_ENEMY_STATE_FATAL_KNOCKBACK: 002e281c-002e2820 reads moby state +0x20 and skips damage handling for fatal state 99; the same byte dispatches case 99 at 002e2c9c-002e2cc0. domain_20_value_3 -> GROUND_ENEMY_STATE_CHASE: Return-home command-byte comparison to 1 at 002e37c4-002e37cc reaches the same write of 3 to moby+0x20 at 002e37e0; source confirms this second branch resumes established CHASE. domain_21_value_12 -> GROUND_ENEMY_STATE_BLOCKED_RETURN_HOME: Return-home movement bit 2 at 002e3808 causes previous xy restoration at 002e3820-002e3824 and writes 12 to moby+0x20 at 002e382c, selecting established BLOCKED_RETURN_HOME. domain_22_value_9 -> GROUND_ENEMY_STATE_HURT_RECOVERY: Hurt knockback step completion bit 1 at 002e3854-002e3864 loads 9 and writes it to moby+0x20 at 002e3878, selects animation 3, and enters established HURT_RECOVERY. domain_23_value_1 -> GROUND_ENEMY_STATE_IDLE: Recovery helper 002fdea0 returns nonzero at 002e38c4-002e38d0 before 002e38e4 writes 1 to moby+0x20 and selects animation 2; this selects established IDLE. domain_24_value_3 -> GROUND_ENEMY_STATE_CHASE: Hurt-recovery animation value >29 at 002e3904-002e3920 leads to 002e3930 writing 3 to moby+0x20 and selecting animation 0; this is the established CHASE selector value. domain_25_value_4 -> GROUND_ENEMY_STATE_MELEE_ATTACK: Blocked return tests movement bit 4 at 002e3af0-002e3af8 or close target with slope <=1 at 002e3afc-002e3b30 and branches to the write of 4 at 002e32b8: established MELEE_ATTACK. domain_26_value_5 -> GROUND_ENEMY_STATE_RETURN_HOME: Blocked-return slope <=1 and clear movement bit 2 at 002e3b34-002e3b50 write 5 to moby+0x20 at 002e3b60 and select animation 0, resuming established RETURN_HOME. domain_27_value_1 -> GROUND_ENEMY_STATE_IDLE: Blocked-return handling tests home timer result s7 at 002e3b90, then writes 1 to moby+0x20 at 002e3ba4 and selects idle animation 2; same selector as established IDLE. domain_29_value_5 -> GROUND_ENEMY_STATE_RETURN_HOME: Leashed walk checks anchor and converted leash distance at 002e3e20-002e3e48; missing or exceeded anchor loads 5 at 002e3e50 and writes moby+0x20 at 002e3e5c, selecting established RETURN_HOME. domain_2_value_7 -> GROUND_ENEMY_STATE_RECOVER_TO_IDLE: 002e2828-002e282c excludes state 7 on moby+0x20 from damage handling; the same byte dispatches established RECOVER_TO_IDLE, whose helper completion writes idle at 002e38c4-002e3900. domain_4_value_99 -> GROUND_ENEMY_STATE_FATAL_KNOCKBACK: 002e2944-002e295c tests nonpositive remaining health; 002e2a54 disables collision and 002e2a58 writes 99 to moby+0x20, selecting the established fatal knockback arm. domain_6_value_6 -> GROUND_ENEMY_STATE_HURT_KNOCKBACK: Positive remaining health branches to 002e2a78; knockback setup at 002e2aac-002e2ae0 precedes the write of 6 to moby+0x20 at 002e2b08, selecting established HURT_KNOCKBACK. domain_7_value_1 -> GROUND_ENEMY_STATE_IDLE: Initialization captures home at 002e2cc8-002e2cd0 and writes 1 to moby+0x20 at 002e2ce0; this byte is the switch selector for established IDLE. domain_9_value_2 -> GROUND_ENEMY_STATE_ALERT_TURN: Idle target range/height checks 002e2db8-002e2e38 lead to 002e2e50 writing 2 to moby+0x20 and animation 4; the established case 2 turns toward the query at 002e2efc-002e2f48. --- .../shared/enemies/ground_melee_enemy.c | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/overlays/shared/enemies/ground_melee_enemy.c b/src/overlays/shared/enemies/ground_melee_enemy.c index ae02a73274..63cfced485 100644 --- a/src/overlays/shared/enemies/ground_melee_enemy.c +++ b/src/overlays/shared/enemies/ground_melee_enemy.c @@ -228,7 +228,7 @@ void ground_melee_enemy_update(Moby *moby) { int expired; float ground; - if (moby->state != 99 && moby->state != 7) { + if (moby->state != GROUND_ENEMY_STATE_FATAL_KNOCKBACK && moby->state != GROUND_ENEMY_STATE_RECOVER_TO_IDLE) { Hit_2E39E0 *hit; damage = 0.0f; hit = find_moby_hit(moby, 0x330000, 0); @@ -278,7 +278,7 @@ void ground_melee_enemy_update(Moby *moby) { else explode_2E39E0(moby, 0, -1); moby->collision = 0; - moby->state = 99; + moby->state = GROUND_ENEMY_STATE_FATAL_KNOCKBACK; ground_enemy_vars->f117 = 120; effects_start_2E39E0(moby, ground_enemy_vars->effects); } else { @@ -294,7 +294,7 @@ void ground_melee_enemy_update(Moby *moby) { 0); ground_enemy_vars->f170 = 5.0f; ground_enemy_vars->f174 = 10.0f; - moby->state = 6; + moby->state = GROUND_ENEMY_STATE_HURT_KNOCKBACK; ground_enemy_vars->f117 = 250; ground_enemy_vars->cooldown = scale_game_frames(60); effects_start_2E39E0(moby, ground_enemy_vars->effects); @@ -337,7 +337,7 @@ void ground_melee_enemy_update(Moby *moby) { switch (moby->state) { case GROUND_ENEMY_STATE_INITIALIZE: qcopy(&ground_enemy_vars->home, &moby->pos); - moby->state = 1; + moby->state = GROUND_ENEMY_STATE_IDLE; ground_enemy_vars->f29 = 0; ground_enemy_vars->health = 1.0f; ground_enemy_vars->f24 = 1; @@ -360,7 +360,7 @@ void ground_melee_enemy_update(Moby *moby) { fast_vec_sub(&step, &query, &moby->pos); if ((kind < 2 || fast_vec_length(&step) < ground_enemy_vars->range + 4.0f) && absolute_float(moby->pos.z - query.z) < 8.0f && !random_integer_below(19)) { - moby->state = 2; + moby->state = GROUND_ENEMY_STATE_ALERT_TURN; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(random_int_between(10, 13))); } else if (moby->command == 1 && !random_integer_below(19)) { @@ -369,7 +369,7 @@ void ground_melee_enemy_update(Moby *moby) { ground_enemy_vars->side = ground_enemy_vars->side_deg * 0.017453292f; ground_enemy_vars->side_timer = scale_game_frames((int)random_float_between(30.0f, 90.0f)); - moby->state = 3; + moby->state = GROUND_ENEMY_STATE_CHASE; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(random_int_between(10, 13))); moby->command = 0; @@ -395,7 +395,7 @@ void ground_melee_enemy_update(Moby *moby) { ground_enemy_vars->side = ground_enemy_vars->side_deg * 0.017453292f; ground_enemy_vars->side_timer = scale_game_frames((int)random_float_between(30.0f, 90.0f)); - moby->state = 3; + moby->state = GROUND_ENEMY_STATE_CHASE; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(random_int_between(10, 13))); moby->command = 0; @@ -405,7 +405,7 @@ void ground_melee_enemy_update(Moby *moby) { ground_enemy_vars->side = ground_enemy_vars->side_deg * 0.017453292f; ground_enemy_vars->side_timer = scale_game_frames((int)random_float_between(30.0f, 90.0f)); - moby->state = 3; + moby->state = GROUND_ENEMY_STATE_CHASE; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(random_int_between(10, 13))); moby->command = 0; @@ -441,18 +441,18 @@ void ground_melee_enemy_update(Moby *moby) { } fast_vec_sub(&away, &query, &ground_enemy_vars->home); if ((flags & 4) || (vector_distance_xy(&moby->pos, &query) < 1.5f && !(flags & 2))) { - moby->state = 4; + moby->state = GROUND_ENEMY_STATE_MELEE_ATTACK; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(random_int_between(10, 13))); } else if (ground_enemy_vars->f190 < frame_time || 1.0f < steep || (flags & 2)) { ground_enemy_vars->home_timer = scale_game_frames(50); - moby->state = 5; + moby->state = GROUND_ENEMY_STATE_RETURN_HOME; } else if (fast_vec_length(&away) < ground_enemy_vars->range + 4.0f && absolute_float(moby->pos.z - query.z) < 8.0f) { if (moby->group != 0xFF) FUN_L01_0026e090(moby->group, 1); } else if (moby->command != 1) { - moby->state = 5; + moby->state = GROUND_ENEMY_STATE_RETURN_HOME; } moby->command = 0; break; @@ -478,7 +478,7 @@ void ground_melee_enemy_update(Moby *moby) { spawn_nearby_effect(query.who, moby, 1, &goal, &step, 1.0f); } if ((moby->anim_flags & 2) && vector_distance_xy(&moby->pos, &query) > 1.5f) { - moby->state = 3; + moby->state = GROUND_ENEMY_STATE_CHASE; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(random_int_between(10, 13))); } @@ -511,7 +511,7 @@ void ground_melee_enemy_update(Moby *moby) { fast_vec_add(&goal, &moby->pos, &step); flags = move_w(moby, &ground_enemy_vars->steer, &goal, &step, 1.0f); if (vector_distance_xy(&moby->pos, &ground_enemy_vars->home) < 2.0f) { - moby->state = 1; + moby->state = GROUND_ENEMY_STATE_IDLE; if (moby->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(random_int_between(10, 13))); } @@ -519,17 +519,17 @@ void ground_melee_enemy_update(Moby *moby) { if (expired && fast_vec_length(&away) < ground_enemy_vars->range) { if (moby->group != 0xFF) FUN_L01_0026e090(moby->group, 1); - moby->state = 3; + moby->state = GROUND_ENEMY_STATE_CHASE; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(random_int_between(10, 13))); } else if (expired && moby->command == 1) { - moby->state = 3; + moby->state = GROUND_ENEMY_STATE_CHASE; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(random_int_between(10, 13))); } else if (flags & 2) { moby->pos.x = previous.x; moby->pos.y = previous.y; - moby->state = 12; + moby->state = GROUND_ENEMY_STATE_BLOCKED_RETURN_HOME; if (moby->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(random_int_between(10, 13))); } @@ -538,7 +538,7 @@ void ground_melee_enemy_update(Moby *moby) { } case GROUND_ENEMY_STATE_HURT_KNOCKBACK: if (step_moby_motion(moby, ground_enemy_vars->motion) & 1) { - moby->state = 9; + moby->state = GROUND_ENEMY_STATE_HURT_RECOVERY; if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(random_int_between(10, 13))); return; @@ -550,7 +550,7 @@ void ground_melee_enemy_update(Moby *moby) { break; case GROUND_ENEMY_STATE_RECOVER_TO_IDLE: if (recover_2E39E0(moby, ground_enemy_vars->motion)) { - moby->state = 1; + moby->state = GROUND_ENEMY_STATE_IDLE; if (moby->prev_seq != 2) blend_moby_animation(moby, 2, 0, 0); ground_enemy_vars->fC8 = 0; @@ -558,7 +558,7 @@ void ground_melee_enemy_update(Moby *moby) { break; case GROUND_ENEMY_STATE_HURT_RECOVERY: if (compute_interpolated_record_value(moby) > 29.0f) { - moby->state = 3; + moby->state = GROUND_ENEMY_STATE_CHASE; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(random_int_between(10, 13))); return; @@ -601,15 +601,15 @@ void ground_melee_enemy_update(Moby *moby) { flags = move_w(moby, &ground_enemy_vars->steer, &goal, &step, 1.0f); fast_vec_sub(&away, &query, &ground_enemy_vars->home); if ((flags & 4) || (vector_distance_xy(&moby->pos, &query) < 1.5f && steep <= 1.0f)) { - moby->state = 4; + moby->state = GROUND_ENEMY_STATE_MELEE_ATTACK; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(random_int_between(10, 13))); } else if (steep <= 1.0f && !(flags & 2)) { - moby->state = 5; + moby->state = GROUND_ENEMY_STATE_RETURN_HOME; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(random_int_between(10, 13))); } else if ((flags & 2) && expired) { - moby->state = 1; + moby->state = GROUND_ENEMY_STATE_IDLE; if (moby->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(random_int_between(10, 13))); } else if (moby->anim_flags & 2) { @@ -660,7 +660,7 @@ void ground_melee_enemy_update(Moby *moby) { if (ground_enemy_vars->anchor == 0 || vector_distance_xy(&moby->pos, &ground_enemy_vars->anchor->pos) > convert_integer_to_float(ground_enemy_vars->leash)) { - moby->state = 5; + moby->state = GROUND_ENEMY_STATE_RETURN_HOME; if (moby->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(random_int_between(10, 13))); } From 336e63e5212bc6df19e060b316337bb4446294f6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:19:15 +0000 Subject: [PATCH 1297/1502] decomp: clarify names in suckcannon_update domain_0_value_3 -> SUCKCANNON_STATE_SUCTION_ACTIVE: Retail 0x002da830-0x002da840 compares the cannon argument s3 byte +0x20 with 3 before beam draw; 0x002da858 dispatches that same byte. Source case SUCKCANNON_STATE_SUCTION_ACTIVE runs update_suck_cannon_suction, so this comparison uses the existing cannon state domain. domain_11_value_4 -> SUCKCANNON_STATE_LOADED_AIM: On active suction termination retail 0x002dad24 stops the effect; positive stored count at 0x002dad34 leads to sequence 6, cleared cooldown, blocked=1 and state 4 at 0x002dad6c, stored to cannon +0x20. This is the same selector as existing SUCKCANNON_STATE_LOADED_AIM. domain_12_value_1 -> SUCKCANNON_STATE_EMPTY_IDLE: Active suction termination with empty stored count clears cooldown at retail 0x002dad70, blends sequence 1, and loads 1 at 0x002dad94 for the shared cannon +0x20 state store. This returns to the existing empty-idle case, rather than any hero or animation domain. domain_13_value_5 -> SUCKCANNON_STATE_FIRE_STORED_MOBY: Loaded aiming fire checks precede retail 0x002db104-0x002db138 starting item animation, blending sequence 5, setting firing=2 and a 25-frame cooldown. 0x002db1c8 loads 5 for the +0x20 cannon state store at 0x002db1dc. Existing case 5 removes a stored slot and dispatches its fire handler. domain_15_value_4 -> SUCKCANNON_STATE_LOADED_AIM: After stored projectile handler dispatch at retail 0x002db734, stored count is decremented at 0x002db744-0x002db750. Positive remaining count loads 4 at 0x002db75c and stores it to cannon +0x20 at 0x002db774, returning to the existing loaded-aim case. domain_16_value_1 -> SUCKCANNON_STATE_EMPTY_IDLE: After the final stored shot, retail 0x002db760-0x002db770 sets a twenty-frame cooldown, loads 1 and clears firing before the cannon +0x20 store at 0x002db774. Source next_state=1 is immediately assigned to suck_cannon_moby->state, proving the existing EMPTY_IDLE state domain. domain_1_value_0 -> SUCKCANNON_STATE_INITIALIZE: Retail 0x002da830-0x002da840 compares the same cannon moby +0x20 byte with zero before beam draw; 0x002da858 dispatches it. Source SUCKCANNON_STATE_INITIALIZE resets stored collision flags and the beam, proving reuse of the existing local state member. domain_2_value_4 -> SUCKCANNON_STATE_LOADED_AIM: Initialization reads stored count at retail 0x002da8e4 and, when positive, blends sequence 6 then loads 4 at 0x002da918 and stores it to cannon moby +0x20 at 0x002da924. That is the switch selector whose existing member 4 maintains loaded aiming and targets. domain_3_value_1 -> SUCKCANNON_STATE_EMPTY_IDLE: The initialization empty-count branch clears cooldown at retail 0x002da91c, loads 1 at 0x002da920, and stores it to the cannon switch selector +0x20 at 0x002da924. Existing member SUCKCANNON_STATE_EMPTY_IDLE handles empty input waiting in this same domain. domain_4_value_4 -> SUCKCANNON_STATE_LOADED_AIM: Retail 0x002da988 tests stored count in empty idle; a positive count blends sequence 6 and loads 4 at 0x002da9b4 before the shared +0x20 state store at 0x002db774. This enters the existing loaded aiming case of the cannon state switch. domain_5_value_2 -> SUCKCANNON_STATE_SUCTION_STARTUP: Held fire, cooldown and hero eligibility checks precede voice allocation and ten-frame cooldown at retail 0x002daa18-0x002daa3c. 0x002daad0 loads state 2, ultimately stored to s3+0x20 at 0x002db1dc. Existing case 2 is the timed SUCKCANNON_STATE_SUCTION_STARTUP. domain_6_value_4 -> SUCKCANNON_STATE_LOADED_AIM: Source startup cancellation sets next_state=4 then goto changed, which assigns next_state to suck_cannon_moby->state. Retail 0x002dab84 tests stored count; positive count blends sequence 6 and loads 4 at 0x002dabb0 before +0x20 store 0x002db774. Thus next_state carries the existing loaded-aim state domain. domain_7_value_1 -> SUCKCANNON_STATE_EMPTY_IDLE: Startup cancellation with no stored mobys clears cooldown and blends sequence 1; retail 0x002dabb4-0x002dabd8 loads 1 before the shared cannon +0x20 store at 0x002db774. Source next_state goes through changed into that selector, proving the existing EMPTY_IDLE member applies. domain_8_value_3 -> SUCKCANNON_STATE_SUCTION_ACTIVE: Retail 0x002dabdc-0x002dabfc tests startup timer expiration, resets cooldown to twenty frames, and loads 3 for the cannon +0x20 store at 0x002db774. Source next_state is assigned through changed to that selector; existing case 3 invokes update_suck_cannon_suction. --- src/overlays/shared/weapons/suckcannon.c | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/overlays/shared/weapons/suckcannon.c b/src/overlays/shared/weapons/suckcannon.c index 08af2f1e40..47e851fc82 100644 --- a/src/overlays/shared/weapons/suckcannon.c +++ b/src/overlays/shared/weapons/suckcannon.c @@ -1433,7 +1433,7 @@ void suckcannon_update(SuckMoby *suck_cannon_moby) { 5); cannon = suck_cannon_moby->data; slot_released = ((SuckHero *)&hero)->slot_state == 3; - if ((u8)suck_cannon_moby->state != 3 && (u8)suck_cannon_moby->state != 0) + if ((u8)suck_cannon_moby->state != SUCKCANNON_STATE_SUCTION_ACTIVE && (u8)suck_cannon_moby->state != SUCKCANNON_STATE_INITIALIZE) suck_beam_queue_draw((int)suck_cannon_moby); refresh_suck_cannon_slots(); switch ((u8)suck_cannon_moby->state) { @@ -1448,10 +1448,10 @@ void suckcannon_update(SuckMoby *suck_cannon_moby) { if (((SuckHero *)&hero)->count > 0) { cannon->blocked = 1; blend_moby_animation(suck_cannon_moby, 6, 0, scale_game_frames(4)); - suck_cannon_moby->state = 4; + suck_cannon_moby->state = SUCKCANNON_STATE_LOADED_AIM; } else { cannon->cooldown = 0; - suck_cannon_moby->state = 1; + suck_cannon_moby->state = SUCKCANNON_STATE_EMPTY_IDLE; } suck_reset(suck_cannon_moby); break; @@ -1463,7 +1463,7 @@ void suckcannon_update(SuckMoby *suck_cannon_moby) { cancel_hero_item_animation(); if (((SuckHero *)&hero)->count > 0) { blend_moby_animation(suck_cannon_moby, 6, 0, scale_game_frames(4)); - suck_cannon_moby->state = 4; + suck_cannon_moby->state = SUCKCANNON_STATE_LOADED_AIM; break; } if ((controller_state.held & ((SuckHero *)&hero)->fire_buttons) && cannon->cooldown == 0 && @@ -1479,7 +1479,7 @@ void suckcannon_update(SuckMoby *suck_cannon_moby) { if (scale_game_frames(D_0015EEA4) / 600 > stats->longest) stats->longest = scale_game_frames(D_0015EEA4) / 600; stats->level_mask = (stats->level_mask | (1 << current_level_index)) | 0x80000000; - suck_cannon_moby->state = 2; + suck_cannon_moby->state = SUCKCANNON_STATE_SUCTION_STARTUP; } break; case SUCKCANNON_STATE_SUCTION_STARTUP: @@ -1498,17 +1498,17 @@ void suckcannon_update(SuckMoby *suck_cannon_moby) { ((SuckHero *)&hero)->firing = 0; if (((SuckHero *)&hero)->count > 0) { blend_moby_animation(suck_cannon_moby, 6, 0, scale_game_frames(4)); - next_state = 4; + next_state = SUCKCANNON_STATE_LOADED_AIM; goto changed; } else { cannon->cooldown = 0; blend_moby_animation(suck_cannon_moby, 1, 0, scale_game_frames(4)); - next_state = 1; + next_state = SUCKCANNON_STATE_EMPTY_IDLE; goto changed; } } else if (fast_dec_timer(&cannon->cooldown)) { cannon->cooldown = scale_game_frames(20); - next_state = 3; + next_state = SUCKCANNON_STATE_SUCTION_ACTIVE; goto changed; } break; @@ -1536,12 +1536,12 @@ void suckcannon_update(SuckMoby *suck_cannon_moby) { blend_moby_animation(suck_cannon_moby, 6, 0, scale_game_frames(4)); cannon->cooldown = 0; cannon->blocked = 1; - suck_cannon_moby->state = 4; + suck_cannon_moby->state = SUCKCANNON_STATE_LOADED_AIM; goto done; } else { cannon->cooldown = 0; blend_moby_animation(suck_cannon_moby, 1, 0, scale_game_frames(4)); - suck_cannon_moby->state = 1; + suck_cannon_moby->state = SUCKCANNON_STATE_EMPTY_IDLE; goto done; } } else { @@ -1620,7 +1620,7 @@ void suckcannon_update(SuckMoby *suck_cannon_moby) { if (scale_game_frames(D_0015EEA4) / 600 > stats->longest) stats->longest = scale_game_frames(D_0015EEA4) / 600; stats->level_mask = (stats->level_mask | (1 << current_level_index)) | 0x80000000; - suck_cannon_moby->state = 5; + suck_cannon_moby->state = SUCKCANNON_STATE_FIRE_STORED_MOBY; } break; case 6: @@ -1774,11 +1774,11 @@ void suckcannon_update(SuckMoby *suck_cannon_moby) { ((SuckHero *)&hero)->count--; if (((SuckHero *)&hero)->count > 0) { ((SuckHero *)&hero)->firing = 0; - suck_cannon_moby->state = 4; + suck_cannon_moby->state = SUCKCANNON_STATE_LOADED_AIM; goto done; } else { cannon->cooldown = scale_game_frames(20); - next_state = 1; + next_state = SUCKCANNON_STATE_EMPTY_IDLE; ((SuckHero *)&hero)->firing = 0; suck_cannon_moby->state = next_state; goto done; From 717328b421fe0a4aac3092b6998515a0e023a6c3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:21:22 +0000 Subject: [PATCH 1298/1502] decomp: clarify names in puffoid_update domain_0_value_20 -> PUFFOID_STATE_WAIT_TO_RESUME_COMMAND: 0031431c-00314368 compares moby+0x20 to 20 to skip damage/C8 reset; the same selector dispatches state 20, whose 00315790-003157b4 completion restores command. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_10_value_1 -> PUFFOID_STATE_WAIT_FOR_HOME_JUMP: 003147f0-003147fc stores 1 into moby+0x20 on case 8 landing and places z at ground minus one; successor case 1 waits and constructs the home jump. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_11_value_4 -> PUFFOID_STATE_CHASE_TARGET: 00314810-00314834 randomizes heading offset and stores 4 into moby+0x20 from idle; matching case 4 moves toward target+0x10 and enters spray below its distance threshold. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_12_value_3 -> PUFFOID_STATE_WANDER_NEAR_HOME: 003148b0-00314918 builds a random horizontal destination relative to pvars+0x220 home and stores 3 into moby+0x20; matching case 3 moves toward that destination. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_13_value_4 -> PUFFOID_STATE_CHASE_TARGET: 00314940-00314974 stores 4 into moby+0x20 after randomizing the chase heading offset while wandering; established case 4 moves toward the target and tests spray range. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_14_value_2 -> PUFFOID_STATE_IDLE: 0031499c-003149c4 stores saved value 2 into moby+0x20 when wander animation completes and the random gate permits; established case 2 is the idle dispatch branch. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_15_value_5 -> PUFFOID_STATE_SPRAY_ATTACK: 003149e0-00314a38 tests target XY distance and animation completion, then stores 5 into moby+0x20; matching case 5 faces the target and emits the spray helper. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_16_value_6 -> PUFFOID_STATE_RETURN_HOME: 00314a50-00314a64 branches to the store at 00314b64 with value 6 when pvars+0x214 equals 2; matching case 6 moves toward home at pvars+0x220. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_17_value_4 -> PUFFOID_STATE_CHASE_TARGET: 00314b2c-00314b4c stores 4 into moby+0x20 after reposition animation completes with pvars+0x214 unequal to 2; established case 4 follows target position. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_18_value_6 -> PUFFOID_STATE_RETURN_HOME: 00314b50-00314b64 stores 6 into moby+0x20 when reposition completes and pvars+0x244 is zero; established case 6 moves toward home at pvars+0x220. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_19_value_4 -> PUFFOID_STATE_CHASE_TARGET: 00314b8c-00314bb4 stores 4 into moby+0x20 when target distance exceeds the spray threshold at animation completion; established case 4 chases the target. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_1_value_2 -> PUFFOID_START_MODE_FOLLOW_PATH: Retail 00314498-003144b8 loads pvars+0x238 and compares to 2, then writes established follow-path state 19 to moby+0x20; 003144cc-00314508 selects travel animation, copies path point zero and sets point to one. Original Ghidra case 0 and authoritative C agree. This is the separate initialization mode selector, not a current-state ID. domain_20_value_6 -> PUFFOID_STATE_RETURN_HOME: 00314bdc-00314bec stores 6 into moby+0x20 when pvars+0x214 equals 2 during spray; established case 6 moves toward pvars+0x220 home. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_21_value_2 -> PUFFOID_STATE_IDLE: 00314c48-00314c7c tests distance to home below one and stores 2 into moby+0x20; this directly resumes the established idle case 2. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_22_value_4 -> PUFFOID_STATE_CHASE_TARGET: 00314c98-00314ccc randomizes heading offset and stores 4 into moby+0x20 on return-home interruption; established case 4 moves toward the target. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_23_value_2 -> PUFFOID_STATE_IDLE: 00314d7c-00314da8 checks landing inside the path and supplies 2 to the shared moby+0x20 store at 0031539c; established idle case 2 resumes after valid knockback landing. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_24_value_13 -> PUFFOID_STATE_CARRIER_JUMP: 00314f04-00314f2c transforms the carrier-relative destination to world space then stores 13 into moby+0x20; following setup initializes jump velocity and case 13 integrates it. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_25_value_14 -> PUFFOID_STATE_CARRIER_IDLE: 00315054-003150a0 probes landing during carrier jump, restores animation speed and stores 14 into moby+0x20; established case 14 follows carrier position/rotation while idle. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_26_value_15 -> PUFFOID_STATE_CARRIER_CHASE_TARGET: 003150a4-00315104 follows the carrier, randomizes chase heading offset and stores 15 into moby+0x20; matching case 15 follows carrier and moves toward target. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_27_value_16 -> PUFFOID_STATE_CARRIER_SPRAY_ATTACK: 0031517c-003151a4 tests target distance below spray threshold and stores 16 into moby+0x20; matching case 16 follows carrier, faces target and emits spray. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_28_value_14 -> PUFFOID_STATE_CARRIER_IDLE: 003151c4-003151dc stores 14 into moby+0x20 when pvars+0x214 equals 2 during carrier chase; established case 14 follows carrier without target chase movement. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_29_value_15 -> PUFFOID_STATE_CARRIER_CHASE_TARGET: 00315234-0031525c stores 15 into moby+0x20 when target distance exceeds spray threshold; established case 15 follows carrier and chases the target. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_2_value_19 -> PUFFOID_STATE_FOLLOW_PATH: 003144a8-003144b8 stores 19 into moby+0x20 when mode 2 initializes indexed path travel; matching case 19 follows points and advances their index at 00315454-00315610. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_30_value_14 -> PUFFOID_STATE_CARRIER_IDLE: 00315284-00315294 stores 14 into moby+0x20 when pvars+0x214 equals 2 during carrier spray; established case 14 implements carrier idle. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_31_value_14 -> PUFFOID_STATE_CARRIER_IDLE: 00315368-0031539c checks a valid path landing after carrier knockback and stores 14 into moby+0x20; established case 14 resumes carrier idle. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_32_value_9 -> PUFFOID_STATE_KNOCKBACK: 003157d4-003157dc reads moby+0x20 and compares 9 to gate smoke; the same selector's case 9 updates knockback motion and returns to idle after valid landing. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_33_value_11 -> PUFFOID_STATE_DEATH_KNOCKBACK: 003157e0-003157e4 compares moby+0x20 to 11 to gate smoke; established case 11 updates fatal knockback then spawns explosion and removes the moby. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_34_value_17 -> PUFFOID_STATE_CARRIER_KNOCKBACK: 003157e8-003157ec compares moby+0x20 to 17 to gate smoke; established case 17 follows carrier, updates knockback and resumes carrier idle on valid landing. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_35_value_18 -> PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK: 003157f0-003157f4 compares moby+0x20 to 18 to gate smoke; established case 18 follows carrier, updates fatal knockback and explodes/removes the moby. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_3_value_1 -> PUFFOID_START_MODE_WAIT_FOR_HOME_JUMP: Retail 0031450c-00314574 compares the pvars+0x238 initialization mode to 1, writes established home-jump-wait state 1 to moby+0x20, places the moby at path point zero minus one Z and copies path point one into home. Original Ghidra case 0 and authoritative C agree; a separate start-mode enum is required. domain_4_value_1 -> PUFFOID_STATE_WAIT_FOR_HOME_JUMP: 0031450c-00314574 stores mode value 1 into moby+0x20 and copies path+0x20 into home; matching state 1 waits and prepares the home jump at 00314600-00314748. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_5_value_12 -> PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP: 00314580-003145b8 selects 12 in moby+0x20 for a nonnegative carrier index and hides the creature; matching case 12 gates and prepares a carrier jump at 00314dfc-00314fe8. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_6_value_2 -> PUFFOID_STATE_IDLE: 003145bc-003145f4 grounds the creature, stores 2 into moby+0x20 and copies its position to home; the same selector's established case 2 waits before chase or wander. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_7_value_7 -> PUFFOID_STATE_JUMP_HOME: 00314698-003146e0 stores 7 into moby+0x20 and forms jump velocity toward path+0x20, the stored home; matching case 7 integrates gravity and lands into idle. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_8_value_7 -> PUFFOID_STATE_JUMP_HOME: 003147d0-003147ec reads moby+0x20 and compares 7 to distinguish the home-jump landing into idle from case 8's transition to home-jump wait. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. domain_9_value_2 -> PUFFOID_STATE_IDLE: 003147e0-003147ec stores 2 into moby+0x20 after home-jump landing and sets the ground height; this is the same selector as established idle case 2. Authoritative C and prepared original retail Ghidra agree; reuse the existing function-local enum for this exact state selector. --- src/overlays/l11/mobys/puffoid.c | 70 +++++++++++++++++--------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/src/overlays/l11/mobys/puffoid.c b/src/overlays/l11/mobys/puffoid.c index a778840a14..337bf7af41 100644 --- a/src/overlays/l11/mobys/puffoid.c +++ b/src/overlays/l11/mobys/puffoid.c @@ -137,12 +137,16 @@ void puffoid_update(struct Moby *moby) { PUFFOID_PATH_ANIM_SPRAY_ATTACK = 6, PUFFOID_PATH_ANIM_EXIT_SPRAY_ATTACK = 7 }; + enum { + PUFFOID_START_MODE_WAIT_FOR_HOME_JUMP = 1, + PUFFOID_START_MODE_FOLLOW_PATH = 2 + }; CreatureVars_4318 *puffoid_vars = (CreatureVars_4318 *)moby->pvars; struct Moby *target; float pos[4]; int i; - if (moby->state != 0x14) { + if (moby->state != PUFFOID_STATE_WAIT_TO_RESUME_COMMAND) { puffoid_vars->unkC8 = 0; update_puffoid_damage_and_path_goal(moby); } @@ -171,27 +175,27 @@ void puffoid_update(struct Moby *moby) { if (rand() & 1) { moby->flags |= 0x8000; } - if (puffoid_vars->mode == 2) { - moby->state = 0x13; + if (puffoid_vars->mode == PUFFOID_START_MODE_FOLLOW_PATH) { + moby->state = PUFFOID_STATE_FOLLOW_PATH; if (moby->prev_seq != 4) { blend_moby_animation(moby, 4, 0, scale_game_frames(10)); } qcopy(&moby->pos, (char *)l11_paths[puffoid_vars->path] + 0x10); puffoid_vars->point = 1; - } else if (puffoid_vars->mode == 1) { - moby->state = 1; + } else if (puffoid_vars->mode == PUFFOID_START_MODE_WAIT_FOR_HOME_JUMP) { + moby->state = PUFFOID_STATE_WAIT_FOR_HOME_JUMP; qcopy(&moby->pos, (char *)l11_paths[puffoid_vars->path] + 0x10); moby->pos.z -= 1.0f; qcopy(puffoid_vars->home, (char *)l11_paths[puffoid_vars->path] + 0x20); } else if (puffoid_vars->carrier >= 0) { - moby->state = 0xC; + moby->state = PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP; puffoid_vars->unk258 = random_float_between(-3.0f, 3.0f); moby->visible = 0; moby->collision = 0; moby->flags |= 1; } else { moby->pos.z = FUN_L00_00259710(&moby->pos); - moby->state = 2; + moby->state = PUFFOID_STATE_IDLE; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 5); } @@ -209,7 +213,7 @@ void puffoid_update(struct Moby *moby) { frame_time_sq * 8.726646f, frame_time * 12.566371f); if (puffoid_vars->unk214 != 2 && random_integer_below(9) == 0) { - moby->state = 7; + moby->state = PUFFOID_STATE_JUMP_HOME; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 5); } @@ -236,11 +240,11 @@ void puffoid_update(struct Moby *moby) { pos[2] += 1.0f; h = probe_ground_height(pos, 0, 0.5f); if (moby->pos.z < h) { - if (moby->state == 7) { + if (moby->state == PUFFOID_STATE_JUMP_HOME) { moby->pos.z = h; - moby->state = 2; + moby->state = PUFFOID_STATE_IDLE; } else { - moby->state = 1; + moby->state = PUFFOID_STATE_WAIT_FOR_HOME_JUMP; moby->pos.z = h - 1.0f; } } @@ -252,7 +256,7 @@ void puffoid_update(struct Moby *moby) { random_float_between(-puffoid_chase_heading_offset_limit_degrees_gp, puffoid_chase_heading_offset_limit_degrees_gp) * 0.017453292f; - moby->state = 4; + moby->state = PUFFOID_STATE_CHASE_TARGET; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -264,7 +268,7 @@ void puffoid_update(struct Moby *moby) { puffoid_vars->unk260[1] = fast_sin(a) * wander_radius; puffoid_vars->unk260[2] = 0.0f; fast_vec_add(puffoid_vars->unk260, puffoid_vars->unk260, puffoid_vars->home); - moby->state = 3; + moby->state = PUFFOID_STATE_WANDER_NEAR_HOME; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -277,12 +281,12 @@ void puffoid_update(struct Moby *moby) { random_float_between(-puffoid_chase_heading_offset_limit_degrees_gp, puffoid_chase_heading_offset_limit_degrees_gp) * 0.017453292f; - moby->state = 4; + moby->state = PUFFOID_STATE_CHASE_TARGET; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } } else if ((moby->anim_flags & 2) && random_integer_below(3) == 0) { - moby->state = 2; + moby->state = PUFFOID_STATE_IDLE; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } @@ -291,7 +295,7 @@ void puffoid_update(struct Moby *moby) { case PUFFOID_STATE_CHASE_TARGET: if ((moby->anim_flags & 2) && vector_distance_xy(&moby->pos, &target->pos) < puffoid_spray_target_distance_metric_threshold_gp) { - moby->state = 5; + moby->state = PUFFOID_STATE_SPRAY_ATTACK; if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(10)); } @@ -300,7 +304,7 @@ void puffoid_update(struct Moby *moby) { (float *)&target->pos); } if (puffoid_vars->unk214 == 2) { - moby->state = 6; + moby->state = PUFFOID_STATE_RETURN_HOME; } break; case PUFFOID_STATE_REPOSITION_AND_FACE_TARGET: @@ -323,9 +327,9 @@ void puffoid_update(struct Moby *moby) { } if (moby->anim_flags & 2) { if (puffoid_vars->unk214 != 2) { - moby->state = 4; + moby->state = PUFFOID_STATE_CHASE_TARGET; } else if (puffoid_vars->unk244 == 0) { - moby->state = 6; + moby->state = PUFFOID_STATE_RETURN_HOME; } } break; @@ -333,12 +337,12 @@ void puffoid_update(struct Moby *moby) { update_moby_target_heading_and_conditional_movement((char *)moby, (float *)&target->pos); if ((moby->anim_flags & 2) && puffoid_spray_target_distance_metric_threshold_gp < vector_distance_xy(&moby->pos, &target->pos)) { - moby->state = 4; + moby->state = PUFFOID_STATE_CHASE_TARGET; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } } else if (puffoid_vars->unk214 == 2) { - moby->state = 6; + moby->state = PUFFOID_STATE_RETURN_HOME; } qcopy(pos, &moby->pos); pos[2] += 0.333f; @@ -346,7 +350,7 @@ void puffoid_update(struct Moby *moby) { break; case PUFFOID_STATE_RETURN_HOME: if (vector_distance_xy(&moby->pos, puffoid_vars->home) < 1.0f) { - moby->state = 2; + moby->state = PUFFOID_STATE_IDLE; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } @@ -355,7 +359,7 @@ void puffoid_update(struct Moby *moby) { random_float_between(-puffoid_chase_heading_offset_limit_degrees_gp, puffoid_chase_heading_offset_limit_degrees_gp) * 0.017453292f; - moby->state = 4; + moby->state = PUFFOID_STATE_CHASE_TARGET; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -379,7 +383,7 @@ void puffoid_update(struct Moby *moby) { mark_moby_for_removal(moby); return; } - moby->state = 2; + moby->state = PUFFOID_STATE_IDLE; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } @@ -421,7 +425,7 @@ void puffoid_update(struct Moby *moby) { dest[2] = 1.0f; transform_vector_by_basis(dest, dest, &carrier_moby->rot_row0); fast_vec_add(dest, dest, &carrier_moby->pos); - moby->state = 0xD; + moby->state = PUFFOID_STATE_CARRIER_JUMP; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, 5); } @@ -455,7 +459,7 @@ void puffoid_update(struct Moby *moby) { pos[2] += 1.0f; if (moby->pos.z < probe_ground_height(pos, 0, 0.5f)) { moby->anim_speed = 1.0f; - moby->state = 0xE; + moby->state = PUFFOID_STATE_CARRIER_IDLE; } } break; @@ -472,7 +476,7 @@ void puffoid_update(struct Moby *moby) { random_float_between(-puffoid_chase_heading_offset_limit_degrees_gp, puffoid_chase_heading_offset_limit_degrees_gp) * 0.017453292f; - moby->state = 0xF; + moby->state = PUFFOID_STATE_CARRIER_CHASE_TARGET; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -488,13 +492,13 @@ void puffoid_update(struct Moby *moby) { update_moby_target_heading_and_conditional_movement((char *)moby, (float *)&target->pos); if ((moby->anim_flags & 2) && vector_distance_xy(&moby->pos, &target->pos) < puffoid_spray_target_distance_metric_threshold_gp) { - moby->state = 0x10; + moby->state = PUFFOID_STATE_CARRIER_SPRAY_ATTACK; if (moby->prev_seq != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(10)); } } if (puffoid_vars->unk214 == 2) { - moby->state = 0xE; + moby->state = PUFFOID_STATE_CARRIER_IDLE; } break; case PUFFOID_STATE_CARRIER_SPRAY_ATTACK: @@ -507,12 +511,12 @@ void puffoid_update(struct Moby *moby) { update_moby_target_heading_and_conditional_movement((char *)moby, (float *)&target->pos); if ((moby->anim_flags & 2) && puffoid_spray_target_distance_metric_threshold_gp < vector_distance_xy(&moby->pos, &target->pos)) { - moby->state = 0xF; + moby->state = PUFFOID_STATE_CARRIER_CHASE_TARGET; if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } } else if (puffoid_vars->unk214 == 2) { - moby->state = 0xE; + moby->state = PUFFOID_STATE_CARRIER_IDLE; } qcopy(pos, &moby->pos); pos[2] += 0.333f; @@ -538,7 +542,7 @@ void puffoid_update(struct Moby *moby) { mark_moby_for_removal(moby); return; } - moby->state = 0xE; + moby->state = PUFFOID_STATE_CARRIER_IDLE; if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } @@ -636,7 +640,7 @@ void puffoid_update(struct Moby *moby) { break; } if (puffoid_vars->smoke != 0.0f) { - if (moby->state == 9 || moby->state == 0xB || moby->state == 0x11 || moby->state == 0x12) { + if (moby->state == PUFFOID_STATE_KNOCKBACK || moby->state == PUFFOID_STATE_DEATH_KNOCKBACK || moby->state == PUFFOID_STATE_CARRIER_KNOCKBACK || moby->state == PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK) { for (i = 0; i < 3; i++) { float vel[4]; float a; From ac4e8dc2cf9b1d6dd1f35438aa5fd8beb41fad46 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:21:22 +0000 Subject: [PATCH 1299/1502] decomp: clarify names in sand_shark_update domain_2_value_11 -> SAND_SHARK_LANDED_AFTER_KNOCKBACK: Retail 0x002d3e60 preserves the assigned moby in s3; state dispatch loads its +0x20 byte at 0x002d3f10. In established SAND_SHARK_KNOCKBACK_UNTIL_LANDING, 0x002d50fc-0x002d5108 calls step_moby_motion(moby,pvars+0x120) and masks return bit 1; success writes 11 to that same moby state byte at 0x002d5120 and selects sequence 4 with flag 8 at 0x002d5124-0x002d513c. Original retail Ghidra case 8 and authoritative C agree. Checked level-02 helper 0x0025ecc0 evidence request fcf0e91189224ad8a8fc2ac573ce8523 shows position integration at 0x0025f1f4-0x0025f218, contact at 0x0025f34c-0x0025f398, normal.z threshold and inward velocity dot-product tests at 0x0025f39c-0x0025f3dc, then ORs return bit 1 at 0x0025f3fc and sets knockback substate 2 at 0x0025f400. Thus 11 is the sand-shark state entered after knockback landing, not HERO_STATE_HIGH_JUMP. --- src/overlays/l02/mobys/sand_shark.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l02/mobys/sand_shark.c b/src/overlays/l02/mobys/sand_shark.c index b331ccb7c1..442a628d5f 100644 --- a/src/overlays/l02/mobys/sand_shark.c +++ b/src/overlays/l02/mobys/sand_shark.c @@ -290,6 +290,9 @@ void sand_shark_update(struct Moby *moby) { SAND_SHARK_BALLISTIC_FLIGHT_WITH_PARTICLES = 27, SAND_SHARK_WAIT_FOR_LINKED_MOBY_BEFORE_INITIALIZE = 29 }; + enum { + SAND_SHARK_LANDED_AFTER_KNOCKBACK = 0xB + }; Varsd3e50 *sand_shark_behavior_vars; OvlVec4 position_or_offset_scratch; OvlVec4 target_or_particle_vector; @@ -784,7 +787,7 @@ void sand_shark_update(struct Moby *moby) { break; case SAND_SHARK_KNOCKBACK_UNTIL_LANDING: if (step_moby_motion(moby, sand_shark_behavior_vars->unk120) & 1) { - moby->state = 0xB; + moby->state = SAND_SHARK_LANDED_AFTER_KNOCKBACK; if (moby->prev_seq != 4) { blend_moby_animation(moby, 4, 8, scale_game_frames(3)); } From d5afaa4506fc6d2d4b2da2039c1a9ea2a94ac7ae Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:21:23 +0000 Subject: [PATCH 1300/1502] decomp: clarify names in update_qwarks_starfighter domain_1_value_3 -> STARFIGHTER_SHIELD_STATE_DEACTIVATE_REQUESTED: Authoritative C shows child = starfighter_vars->child110 in the branch where moby->bBC != 4. Retail 0x002ec8dc-0x002ec8e8 creates this child through 0x002e8438 only for command 4; checked helper 0x002e844c-0x002e8450 creates class 0x160. When command 4 ends, 0x002ec9a4-0x002ec9d0 validates this same child, excludes FD/FE removal states, and tests state < 3 before requesting state 3 at 0x002ec9e4. Thus 3 is the shield deactivation request threshold, in its own class-specific state domain. domain_2_value_3 -> STARFIGHTER_SHIELD_STATE_DEACTIVATE_REQUESTED: Retail 0x002ec8c0-0x002ec8e8 maintains or creates the class-0x160 shield while command byte +0xBC equals 4. Its opposite branch releases the shield sound and validates child110 as class 0x160 at 0x002ec9a4-0x002ec9b4. After excluding removal states, 0x002ec9d0-0x002ec9e4 writes 3 to the shield's state only if below 3. The command-4 branch reverses states >=3 to 1 at 0x002ec8ec-0x002ec8fc. These paired control writes prove a shield deactivation request, without inferring the shield update's completion behavior. --- src/overlays/l13/mobys/qwarks_starfighter.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l13/mobys/qwarks_starfighter.c b/src/overlays/l13/mobys/qwarks_starfighter.c index 04de35b18f..3b7ddf8c59 100644 --- a/src/overlays/l13/mobys/qwarks_starfighter.c +++ b/src/overlays/l13/mobys/qwarks_starfighter.c @@ -1630,6 +1630,9 @@ void qwarks_starfighter_update(Moby388 *moby) { MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE }; + enum { + STARFIGHTER_SHIELD_STATE_DEACTIVATE_REQUESTED = 3 + }; Ship388 *starfighter_vars = moby->d; float offset[4]; float joint[4]; @@ -2271,8 +2274,8 @@ void qwarks_starfighter_update(Moby388 *moby) { starfighter_vars->child110 = 0; } else if (child->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { starfighter_vars->child110 = 0; - } else if (child->state < 3) { - child->state = 3; + } else if (child->state < STARFIGHTER_SHIELD_STATE_DEACTIVATE_REQUESTED) { + child->state = STARFIGHTER_SHIELD_STATE_DEACTIVATE_REQUESTED; } } } From 71cd23c85964948858957803d751ffd5219ef221 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:21:23 +0000 Subject: [PATCH 1301/1502] decomp: clarify names in ultramech_unlimited_update domain_0_value_0 -> ULTRAMECH_INITIALIZE: Retail 0x002cf3fc-0x002cf400 loads owner state byte +0x20 and skips the mode reset when zero. This is the identical byte switched at 0x002cf4ac-0x002cf4cc; authoritative local enum names its initialization case ULTRAMECH_INITIALIZE. domain_10_value_7 -> ULTRAMECH_APPROACH_TARGET: Retail 0x002cfcac-0x002cfcd8 tests target XY distance against the approach range and stores 7 at owner state+0x20. Existing case ULTRAMECH_APPROACH_TARGET for this selector computes flocking steering and constrained movement at 0x002d03c0-0x002d05c0. domain_11_value_8 -> ULTRAMECH_MELEE_ATTACK: Retail 0x002cfd00-0x002cfd28 tests combat-target distance against melee range and stores 8 to owner+0x20. This exact selector's existing case ULTRAMECH_MELEE_ATTACK performs windowed hit sphere/segment processing at 0x002d07c4-0x002d08e8. domain_12_value_5 -> ULTRAMECH_FIRE_BURST: Source attack-selection fallback assigns 5 to ultramech_moby->state and resets shots; retail shared branch 0x002d0388-0x002d03bc stores 5 at owner+0x20 and clears data+0x1c4. Existing case ULTRAMECH_FIRE_BURST emits projectiles and counts shots. domain_13_value_6 -> ULTRAMECH_WAIT_BETWEEN_BURSTS: Retail 0x002cff14-0x002cff90 checks at least six shots and animation completion, stores 6 at owner+0x20 and initializes a countdown. Same selector's existing ULTRAMECH_WAIT_BETWEEN_BURSTS case waits for timer expiry before returning to firing. domain_14_value_7 -> ULTRAMECH_APPROACH_TARGET: Retail 0x002cffa0-0x002cffd4 tests combat-target distance against the approach threshold while firing and stores 7 at owner+0x20. This is the same switch state byte whose existing canonical local member is ULTRAMECH_APPROACH_TARGET. domain_15_value_8 -> ULTRAMECH_MELEE_ATTACK: Retail 0x002cfffc-0x002d0028 compares target distance with the melee threshold and stores 8 to owner state+0x20 during firing. Same selector's existing local enum names 8 ULTRAMECH_MELEE_ATTACK, with windowed hit processing in that case. domain_16_value_3 -> ULTRAMECH_BALLISTIC_PATH_MOVE: Retail 0x002d0090-0x002d0194 stores 3 to owner+0x20, toggles path side and computes launch velocity to a path point. Existing ULTRAMECH_BALLISTIC_PATH_MOVE case integrates this velocity, subtracts gravity and handles landing at 0x002cfaa4-0x002cfbdc. domain_17_value_4 -> ULTRAMECH_AIM_AND_SELECT_ATTACK: Source firing-state target-unavailable branch assigns 4 to ultramech_moby->state. Retail 0x002cfd8c-0x002cfd90 branches to 0x002d0a68-0x002d0a74, storing 4 to the same owner+0x20 switch selector, existing ULTRAMECH_AIM_AND_SELECT_ATTACK. domain_18_value_3 -> ULTRAMECH_BALLISTIC_PATH_MOVE: Retail 0x002d0280-0x002d0374 stores 3 at owner state+0x20, increments path point and solves path launch velocity from the between-bursts handler. Same selector's existing ULTRAMECH_BALLISTIC_PATH_MOVE case consumes that velocity with gravity. domain_19_value_5 -> ULTRAMECH_FIRE_BURST: Retail 0x002d0378-0x002d03bc decrements the burst-wait timer, then stores 5 at owner+0x20, selects firing animation and clears shots. The same state selector already has local enum member ULTRAMECH_FIRE_BURST for its projectile-emitting case. domain_1_value_64 -> ULTRAMECH_DEAD_WAIT_FOR_RESET: Retail 0x002cf408-0x002cf40c compares the owner state byte +0x20 with 0x40. The same selector's existing ULTRAMECH_DEAD_WAIT_FOR_RESET case disables the moby and clears save bits at 0x002d0bc0-0x002d0c8c. domain_20_value_4 -> ULTRAMECH_AIM_AND_SELECT_ATTACK: Source between-bursts unavailable-target branch assigns 4 to ultramech_moby->state. Retail 0x002d0198-0x002d01a0 branches to the shared 0x002d0a68-0x002d0a74 store of 4 at owner+0x20, the existing ULTRAMECH_AIM_AND_SELECT_ATTACK selector member. domain_21_value_8 -> ULTRAMECH_MELEE_ATTACK: Retail 0x002d0414-0x002d0438 compares target distance against melee range during approach and stores 8 to owner state+0x20. This is the existing switch domain containing canonical local member ULTRAMECH_MELEE_ATTACK, not a hero state or animation ID. domain_22_value_4 -> ULTRAMECH_AIM_AND_SELECT_ATTACK: Retail 0x002d03e0-0x002d03e4 branches on unavailable target to 0x002d0460-0x002d0468, storing 4 at owner+0x20. Same selector is switched at 0x002cf4ac and already names case 4 ULTRAMECH_AIM_AND_SELECT_ATTACK. domain_23_value_4 -> ULTRAMECH_AIM_AND_SELECT_ATTACK: Retail 0x002d0560-0x002d05b0 checks constrained approach movement/path containment, copies the resulting position and stores 4 at owner+0x20 on stopping. Existing same-selector local member ULTRAMECH_AIM_AND_SELECT_ATTACK names its subsequent aiming handler. domain_24_value_3 -> ULTRAMECH_BALLISTIC_PATH_MOVE: Retail 0x002d0640-0x002d0798 checks melee distance/path availability, stores 3 at owner+0x20, increments path point and calculates launch velocity. This exact state selector already names the velocity/gravity consumer ULTRAMECH_BALLISTIC_PATH_MOVE. domain_25_value_4 -> ULTRAMECH_AIM_AND_SELECT_ATTACK: Retail 0x002d079c-0x002d07c0 compares target distance above melee range, then branches to shared 0x002d0a70-0x002d0a74 store of 4 at owner+0x20. Existing local enum for this switch selector names 4 ULTRAMECH_AIM_AND_SELECT_ATTACK. domain_26_value_3 -> ULTRAMECH_BALLISTIC_PATH_MOVE: Retail 0x002d0958-0x002d0a64 stores 3 at owner+0x20 after knockback completion, toggles path side, probes destination ground and solves launch velocity. Same state byte's existing ULTRAMECH_BALLISTIC_PATH_MOVE case integrates velocity and gravity. domain_27_value_4 -> ULTRAMECH_AIM_AND_SELECT_ATTACK: Source knockback-recovery path-disabled branch assigns 4 to owner state. Retail 0x002d094c-0x002d0954 branches to shared 0x002d0a6c-0x002d0a74 store of 4 at owner+0x20. Existing enum for this exact selector names 4 ULTRAMECH_AIM_AND_SELECT_ATTACK. domain_28_value_64 -> ULTRAMECH_DEAD_WAIT_FOR_RESET: Retail 0x002d0b94-0x002d0bbc spawns break fragments then stores 0x40 to owner+0x20 and returns. The same switch selector's existing ULTRAMECH_DEAD_WAIT_FOR_RESET case at 0x002d0bc0 disables collision, clears save flags and waits for reset. domain_29_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Source dead/reset case tests hero.vehicle_mode != 2. Retail 0x002d0c0c reads byte 0x001413f4; 0x002d0c1c and 0x002d0c84 compare it with 2 before reset. This exact hero field belongs to supplied HeroVehicleMode with canonical member HERO_VEHICLE_MODE_GIANT_CLANK. domain_2_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Source compares hero.vehicle_mode, not moby state. Retail 0x002cf410-0x002cf41c loads byte 0x001413f4 and compares with 2; supplied HeroVehicleMode domain canonically names that selector value HERO_VEHICLE_MODE_GIANT_CLANK. domain_30_value_0 -> ULTRAMECH_INITIALIZE: Retail 0x002d0c84-0x002d0c8c stores zero at owner+0x20 after leaving the required hero mode in the dead/reset handler. That byte is the switch selector, whose existing local zero member ULTRAMECH_INITIALIZE resets data and entry-path position. domain_31_value_1 -> ULTRAMECH_WAIT_FOR_ACTIVATION: Source nonmoving ground correction requires ultramech_moby->state > 1. Retail 0x002d0ea4-0x002d0eac loads the same owner+0x20 switch byte and exits when below 2, equivalent to the source bound. Existing enum names the upper excluded state 1 ULTRAMECH_WAIT_FOR_ACTIVATION. domain_32_value_64 -> ULTRAMECH_DEAD_WAIT_FOR_RESET: Retail 0x002d0eb4-0x002d0eb8 compares the owner state+0x20 with 0x40 and skips ground correction for that state. It is the same switch selector whose existing canonical local member ULTRAMECH_DEAD_WAIT_FOR_RESET disables the dead moby. domain_3_value_1 -> ULTRAMECH_WAIT_FOR_ACTIVATION: Retail 0x002cf474-0x002cf490 stores 1 to owner+0x20 after mode exit, voice release and collision disable. This is the switch selector, whose existing enum case 1 ULTRAMECH_WAIT_FOR_ACTIVATION performs activation gating at 0x002cf5d0 onward. domain_4_value_1 -> ULTRAMECH_WAIT_FOR_ACTIVATION: Retail 0x002cf5a4-0x002cf5b0 stores 1 to owner state +0x20 after initialization and entry-position setup. The same state byte dispatches the existing ULTRAMECH_WAIT_FOR_ACTIVATION case at 0x002cf5d0. domain_5_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Source hero.vehicle_mode == 2 gates enabling the ultramech collision pointer. Retail 0x002cf618-0x002cf644 reads 0x001413f4, compares 2 and updates owner flags/pointer. This exact hero field belongs to supplied HeroVehicleMode, canonical member HERO_VEHICLE_MODE_GIANT_CLANK. domain_6_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Source pl is assigned &hero immediately before pl->vehicle_mode == 2. Retail 0x002cf664-0x002cf66c reads byte at hero base 0x0013f350 +0x20a4 = 0x001413f4, the same hero.vehicle_mode byte, proving supplied HeroVehicleMode member HERO_VEHICLE_MODE_GIANT_CLANK. domain_7_value_2 -> ULTRAMECH_FOLLOW_ENTRY_PATH: Retail 0x002cf6d0-0x002cf6e0 stores 2 to owner+0x20 after activation gates; 0x002cf700-0x002cf784 initializes the entry path. Same selector's existing case ULTRAMECH_FOLLOW_ENTRY_PATH projects and interpolates that path at 0x002cf7e0 onward. domain_8_value_4 -> ULTRAMECH_AIM_AND_SELECT_ATTACK: Retail 0x002cf8a0-0x002cf8f4 detects the end of entry-path segments, ground-clamps and stores 4 to owner state+0x20 with a timer. Existing local enum maps that same switch byte's case 4 to ULTRAMECH_AIM_AND_SELECT_ATTACK. domain_9_value_4 -> ULTRAMECH_AIM_AND_SELECT_ATTACK: Retail 0x002cfbb0-0x002cfbd0 ground-clamps a ballistic landing and stores 4 at owner+0x20 with a timer. The identical byte selects existing ULTRAMECH_AIM_AND_SELECT_ATTACK, whose body turns toward the combat target and selects attacks. --- src/overlays/l15/mobys/ultramech_unlimited.c | 60 ++++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/overlays/l15/mobys/ultramech_unlimited.c b/src/overlays/l15/mobys/ultramech_unlimited.c index 42ba395e94..8ff8a5000f 100644 --- a/src/overlays/l15/mobys/ultramech_unlimited.c +++ b/src/overlays/l15/mobys/ultramech_unlimited.c @@ -299,7 +299,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { ultramech_vars = ultramech_moby->data; process_ultramech_hits_and_update_target(ultramech_moby); combat_target = ultramech_vars->target; - if (ultramech_moby->state != 0 && ultramech_moby->state != 0x40 && hero.vehicle_mode != 2) { + if (ultramech_moby->state != ULTRAMECH_INITIALIZE && ultramech_moby->state != ULTRAMECH_DEAD_WAIT_FOR_RESET && hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK) { ultramech_moby->w94 = 0; ultramech_moby->flags |= 0x41; idx = ultramech_vars->snd; @@ -313,7 +313,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { ultramech_vars->snd = -1; ultramech_moby->flags &= 0xEFFF; ultramech_vars->b58 = 0; - ultramech_moby->state = 1; + ultramech_moby->state = ULTRAMECH_WAIT_FOR_ACTIVATION; return; } FUN_L00_00263ac8(2.5f, (int)ultramech_moby, 6, ultramech_vars->v200); @@ -341,7 +341,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { ultramech_vars->w1D4 = 1; if (ultramech_vars->path != -1) ultramech_moby->pos.q = D_L15_001B0AB0[ultramech_vars->path]->points[0].q; - ultramech_moby->state = 1; + ultramech_moby->state = ULTRAMECH_WAIT_FOR_ACTIVATION; if (ultramech_moby->anim != 0) blend_moby_animation(ultramech_moby, 0, 0, 5); break; @@ -351,14 +351,14 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { if (ultramech_vars->w1CC != -1 && count_active_moby_group_members(ultramech_vars->w1CC, 0x40)) break; - if (hero.vehicle_mode == 2) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { ultramech_moby->w94 = *(int *)(ultramech_moby->cls + 0x10); ultramech_moby->flags = (ultramech_moby->flags & 0xFFBE) | 0x1000; } } if (ultramech_vars->w164 != 2 && ultramech_vars->path != -1) { struct Hero *pl = &hero; - if (pl->vehicle_mode == 2 && (ultramech_moby->flags & 0x1000)) { + if (pl->vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && (ultramech_moby->flags & 0x1000)) { if (ultramech_vars->w1D0 != -1 && !point_in_path_xy(&pl->motion.pos, D_L15_001B0AB0[ultramech_vars->w1D0]->points, @@ -368,7 +368,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { } else { LevelPath *path; int i; - ultramech_moby->state = 2; + ultramech_moby->state = ULTRAMECH_FOLLOW_ENTRY_PATH; if (ultramech_moby->anim != 4) blend_moby_animation(ultramech_moby, 4, 0, scale_game_frames(0x14)); path = D_L15_001B0AB0[ultramech_vars->path]; @@ -418,7 +418,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { float z = probe_ground_height(&ultramech_moby->pos, 0, 0.5f); if (ultramech_moby->pos.f[2] < z) ultramech_moby->pos.f[2] = z; - ultramech_moby->state = 4; + ultramech_moby->state = ULTRAMECH_AIM_AND_SELECT_ATTACK; ultramech_vars->timer = scale_game_frames(0xF); break; } @@ -473,7 +473,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { } if (ultramech_moby->pos.f[2] < z) { ultramech_moby->pos.f[2] = z; - ultramech_moby->state = 4; + ultramech_moby->state = ULTRAMECH_AIM_AND_SELECT_ATTACK; ultramech_vars->timer = scale_game_frames(0xF); } } @@ -494,17 +494,17 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { if (ultramech_vars->w1D8 == 0 && vector_distance_xy(&ultramech_moby->pos, &combat_target->pos) < *(float *)&ultramech_approach_target_range_gp) { - ultramech_moby->state = 7; + ultramech_moby->state = ULTRAMECH_APPROACH_TARGET; if (ultramech_moby->anim != 1) blend_moby_animation(ultramech_moby, 1, 0, scale_game_frames(0xA)); } else if (ultramech_vars->w1D8 == 0 && vector_distance_xy(&ultramech_moby->pos, &combat_target->pos) < *(float *)&ultramech_melee_range_gp) { - ultramech_moby->state = 8; + ultramech_moby->state = ULTRAMECH_MELEE_ATTACK; if (ultramech_moby->anim != 2) blend_moby_animation(ultramech_moby, 2, 0, scale_game_frames(0xA)); } else { - ultramech_moby->state = 5; + ultramech_moby->state = ULTRAMECH_FIRE_BURST; if (ultramech_moby->anim != 6) blend_moby_animation(ultramech_moby, 6, 0, scale_game_frames(0x14)); ultramech_vars->shots = 0; @@ -555,7 +555,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { emit_radial_particle_burst(ultramech_moby, &vector_or_hit_descriptor, 0); ultramech_vars->shots++; } else if ((float)ultramech_vars->shots >= 6.0f && (ultramech_moby->animFlags & 2)) { - ultramech_moby->state = 6; + ultramech_moby->state = ULTRAMECH_WAIT_BETWEEN_BURSTS; if (ultramech_moby->anim != 0) blend_moby_animation(ultramech_moby, 0, 0, scale_game_frames(0xA)); ultramech_vars->timer = @@ -563,19 +563,19 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { } else if (ultramech_vars->w1D8 == 0 && vector_distance_xy(&ultramech_moby->pos, &combat_target->pos) < *(float *)&ultramech_approach_target_range_gp) { - ultramech_moby->state = 7; + ultramech_moby->state = ULTRAMECH_APPROACH_TARGET; if (ultramech_moby->anim != 1) blend_moby_animation(ultramech_moby, 1, 0, scale_game_frames(0xA)); } else if (ultramech_vars->w1D8 == 0 && vector_distance_xy(&ultramech_moby->pos, &combat_target->pos) < *(float *)&ultramech_melee_range_gp) { - ultramech_moby->state = 8; + ultramech_moby->state = ULTRAMECH_MELEE_ATTACK; if (ultramech_moby->anim != 2) blend_moby_animation(ultramech_moby, 2, 0, scale_game_frames(0xA)); } else if (ultramech_vars->w1D8 == 0 && vector_distance_xy(&ultramech_moby->pos, &combat_target->pos) > 10.0f && ultramech_vars->w1C8 != 0 && ultramech_vars->w1D4 == 0) { - ultramech_moby->state = 3; + ultramech_moby->state = ULTRAMECH_BALLISTIC_PATH_MOVE; ultramech_vars->timer = 0; ultramech_vars->side = (ultramech_vars->side + 1) & 1; if (ultramech_moby->anim != 3) @@ -598,7 +598,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { -(*(float *)&ultramech_path_gravity_gp * frame_time_sq)); } } else { - ultramech_moby->state = 4; + ultramech_moby->state = ULTRAMECH_AIM_AND_SELECT_ATTACK; if (ultramech_moby->anim != 0) blend_moby_animation(ultramech_moby, 0, 0, scale_game_frames(0x14)); } @@ -619,7 +619,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { ->idx[ultramech_vars->side]] ->count - 1) { - ultramech_moby->state = 3; + ultramech_moby->state = ULTRAMECH_BALLISTIC_PATH_MOVE; ultramech_vars->timer = 0; ultramech_vars->point++; if (ultramech_moby->anim != 3) @@ -641,13 +641,13 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { *(float *)&ultramech_path_horizontal_speed_gp * frame_time, -(*(float *)&ultramech_path_gravity_gp * frame_time_sq)); } else if (fast_dec_timer(&ultramech_vars->timer)) { - ultramech_moby->state = 5; + ultramech_moby->state = ULTRAMECH_FIRE_BURST; if (ultramech_moby->anim != 6) blend_moby_animation(ultramech_moby, 6, 0, scale_game_frames(0x14)); ultramech_vars->shots = 0; } } else { - ultramech_moby->state = 4; + ultramech_moby->state = ULTRAMECH_AIM_AND_SELECT_ATTACK; if (ultramech_moby->anim != 0) blend_moby_animation(ultramech_moby, 0, 0, scale_game_frames(0x14)); } @@ -660,12 +660,12 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { ultramech_moby, &position_or_motion_vector, ultramech_vars->f1B8); if (vector_distance_xy(&ultramech_moby->pos, &combat_target->pos) < *(float *)&ultramech_melee_range_gp) { - ultramech_moby->state = 8; + ultramech_moby->state = ULTRAMECH_MELEE_ATTACK; if (ultramech_moby->anim != 2) blend_moby_animation(ultramech_moby, 2, 0, scale_game_frames(0xA)); } } else { - ultramech_moby->state = 4; + ultramech_moby->state = ULTRAMECH_AIM_AND_SELECT_ATTACK; if (ultramech_moby->anim != 0) blend_moby_animation(ultramech_moby, 0, 0, scale_game_frames(0x14)); } @@ -693,7 +693,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { D_L15_001B0AB0[ultramech_vars->side]->points, D_L15_001B0AB0[ultramech_vars->side]->count)) { qcopy(&ultramech_moby->pos, &vector_or_hit_descriptor); - ultramech_moby->state = 4; + ultramech_moby->state = ULTRAMECH_AIM_AND_SELECT_ATTACK; if (ultramech_moby->anim != 0) blend_moby_animation(ultramech_moby, 0, 0, scale_game_frames(0xC)); } else { @@ -717,7 +717,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { ->idx[ultramech_vars->side]] ->count - 1) { - ultramech_moby->state = 3; + ultramech_moby->state = ULTRAMECH_BALLISTIC_PATH_MOVE; ultramech_vars->timer = 0; ultramech_vars->point++; if (ultramech_moby->anim != 3) @@ -740,7 +740,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { -(*(float *)&ultramech_path_gravity_gp * frame_time_sq)); } else if (*(float *)&ultramech_melee_range_gp < vector_distance_xy(&ultramech_moby->pos, &combat_target->pos)) { - ultramech_moby->state = 4; + ultramech_moby->state = ULTRAMECH_AIM_AND_SELECT_ATTACK; if (ultramech_moby->anim != 0) blend_moby_animation(ultramech_moby, 0, 0, scale_game_frames(0x14)); } @@ -780,7 +780,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { } if ((r & 0x40) || (ultramech_vars->w1D8 != 0 && (ultramech_moby->animFlags & 2))) { if (ultramech_vars->w1D4 == 0) { - ultramech_moby->state = 3; + ultramech_moby->state = ULTRAMECH_BALLISTIC_PATH_MOVE; ultramech_vars->timer = 0; ultramech_vars->side = (ultramech_vars->side + 1) & 1; qcopy(&vector_or_hit_descriptor, @@ -802,7 +802,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { *(float *)&ultramech_path_horizontal_speed_gp * frame_time, -(*(float *)&ultramech_path_gravity_gp * frame_time_sq)); } else { - ultramech_moby->state = 4; + ultramech_moby->state = ULTRAMECH_AIM_AND_SELECT_ATTACK; if (ultramech_moby->anim != 0) blend_moby_animation(ultramech_moby, 0, 0, scale_game_frames(0x14)); } @@ -842,7 +842,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { FUN_L00_00263fd8(ultramech_moby, 0x64C, pp, rr, 0, 0, 0.0f, dd, dd, D_L15_0015F580); } spawn_moby_break_fragments(ultramech_moby, 0x7A9, 1, 0x7A9, 2, 4, 2); - ultramech_moby->state = 0x40; + ultramech_moby->state = ULTRAMECH_DEAD_WAIT_FOR_RESET; return; case ULTRAMECH_DEAD_WAIT_FOR_RESET: ultramech_moby->w94 = 0; @@ -854,8 +854,8 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { (((short)ultramech_moby->id >> 5) * 4 + (current_level_index << 8))) &= ~(1 << (ultramech_moby->id & 0x1F)); D_L15_001BAAD0[(short)ultramech_moby->id >> 5] &= ~(1 << (ultramech_moby->id & 0x1F)); - if (hero.vehicle_mode != 2) - ultramech_moby->state = 0; + if (hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK) + ultramech_moby->state = ULTRAMECH_INITIALIZE; break; } if (moving) { @@ -904,7 +904,7 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { : FUN_L00_00257b90(0x14, 0x1E))); } } - } else if (ultramech_moby->state > 1 && ultramech_moby->state != 0x40) { + } else if (ultramech_moby->state > ULTRAMECH_WAIT_FOR_ACTIVATION && ultramech_moby->state != ULTRAMECH_DEAD_WAIT_FOR_RESET) { float z; ultramech_vars->fE8 += frame_time_sq * 30.0f; ultramech_moby->pos.f[2] -= ultramech_vars->fE8 - 2.0f; From 3251b3fb3f01d9703af015c69047d83e036bfb0f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:23:16 +0000 Subject: [PATCH 1302/1502] decomp: clarify names in toxic_crab_update domain_0_value_254 -> MOBY_STATE_MARKED_FOR_REMOVAL: Authoritative C resolves p from the moby instance array and tests p->state. Retail 0x002e2070-0x002e2074 reads p+0x20 and compares 0xFE before invalidating the linked index at 0x002e20e8-0x002e20ec. Checked direct helper mark_moby_for_removal at 0x002415e0 compares the moby address to [0x0015FFDC], selects 0xFE at 0x00241604, and writes moby+0x20 at 0x00241608; it schedules frame counter+2 at +0x38. This proves a removal marker, not a toxic-crab behavior state. domain_2_value_254 -> MOBY_STATE_MARKED_FOR_REMOVAL: Retail 0x002e2170-0x002e2184 forms the linked moby pointer from its instance index shifted by 8, reads state at +0x20 and compares 0xFE. That condition activates the waiting crab at 0x002e21d4-0x002e21e4. Checked mark_moby_for_removal writes 0xFE to the same moby state byte at 0x00241604-0x00241608 for addresses at or above [0x0015FFDC], then stores frame counter+2 at +0x38. Reuse the same removal-marker name for this identical domain and value. --- src/overlays/l10/mobys/toxic_crab.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/toxic_crab.c b/src/overlays/l10/mobys/toxic_crab.c index 8c378bdf74..2f3f34d1a9 100644 --- a/src/overlays/l10/mobys/toxic_crab.c +++ b/src/overlays/l10/mobys/toxic_crab.c @@ -233,6 +233,9 @@ void toxic_crab_update(Moby2E30F8 *m) { TOXIC_CRAB_STATE_DEATH_EFFECTS = 11, TOXIC_CRAB_STATE_FALL_TO_DEATH = 12 }; + enum { + MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE + }; int see = 0; Crab2E30F8 *crab_data = m->data; char *target_moby; @@ -293,7 +296,7 @@ void toxic_crab_update(Moby2E30F8 *m) { int k = crab_data->i1BC; if (k != -1) { Moby2E30F8 *p = (Moby2E30F8 *)((char *)D_L10_0015FFD0_macro[2] + (k << 8)); - if (p == 0 || p->state == 0xFE || p->state == 0xFD || + if (p == 0 || p->state == MOBY_STATE_MARKED_FOR_REMOVAL || p->state == 0xFD || (((*(int *)(((char *)&D_0014C190) + (((short)p->id >> 5) * 4 + (current_level_index << 8))) >> (p->id & 0x1F)) & @@ -315,7 +318,7 @@ void toxic_crab_update(Moby2E30F8 *m) { if (crab_data->i1BC != -1) { char *moby_instance_array_base = D_L10_0015FFD8; Moby2E30F8 *p = (Moby2E30F8 *)(moby_instance_array_base + (crab_data->i1BC << 8)); - if (p == 0 || p->state == 0xFE || p->state == 0xFD || + if (p == 0 || p->state == MOBY_STATE_MARKED_FOR_REMOVAL || p->state == 0xFD || ((*(int *)(((char *)&D_0014C190) + (((short)p->id >> 5) * 4 + (current_level_index << 8))) >> (p->id & 0x1F)) & From 05cba9d268afcc5e29734925790bd517aa98c7cb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:23:16 +0000 Subject: [PATCH 1303/1502] decomp: clarify names in helicopter_update domain_0_value_0 -> HELICOPTER_GOAL_DEFAULT_TARGET: Authoritative helicopter.c SHA-256 0f51ad06b873d80895f659b9223be4000b49f0142ac52640e8e2e5264a5a25ce initializes goal.status at retail 0x002c5714 (sp+0x74), output+0x44 of both direct goal helpers. Checked level-15 helper 0x0024f560 initializes classification s5=0 at 0x0024f590 and loads the default target from 0x00141350+0x2080 at 0x0024f5b4. Rejection clears that target and sets classification 2 at 0x0024f5c8..0x0024f5cc; alternate selection changes target and classification to 1 at 0x0024f668..0x0024f670 and 0x0024f6ec..0x0024f6f4. Final stores at 0x0024f754/0x0024f788/0x0024f7a4 publish classification at output+0x44. Second helper independently loads the same default target at 0x0024f840 and initializes classification zero at 0x0024f848, changes to 2 on exclusions (0x0024f85c..0x0024f870, 0x0024f928..0x0024f930), changes to 1 with alternate selection (0x0024fa44..0x0024fa48, 0x0024fb54..0x0024fb58), and publishes it at 0x0024fc30. Thus zero classifies the default target rather than helicopter state, hero mode, or general availability. --- src/overlays/l15/mobys/helicopter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l15/mobys/helicopter.c b/src/overlays/l15/mobys/helicopter.c index 2546b9100c..763bd326cd 100644 --- a/src/overlays/l15/mobys/helicopter.c +++ b/src/overlays/l15/mobys/helicopter.c @@ -402,6 +402,9 @@ void helicopter_update(struct Moby *moby) { enum { HELICOPTER_GOAL_UNAVAILABLE = 2 }; + enum { + HELICOPTER_GOAL_DEFAULT_TARGET = 0 + }; Vec4 previous_pos; HelicopterGoal goal; Vec4 move; @@ -436,7 +439,7 @@ void helicopter_update(struct Moby *moby) { return; } process_helicopter_hits(moby); - goal.status = 0; + goal.status = HELICOPTER_GOAL_DEFAULT_TARGET; if (moby->state == HELICOPTER_WAIT_FOR_ACTIVATION) { helicopter_instance_vars->range = helicopter_instance_vars->wake_range; goto near; From 2050f0a99c070dd3027486e265db39dd492a35a3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:26:26 +0000 Subject: [PATCH 1304/1502] decomp: clarify names in circular_saw_enemy_update domain_0_value_1 -> CIRCULAR_SAW_STATE_IDLE: 002c23b0-002c23c0 loads moby+0x20 and compares 1/3 before the proximity melee transition; this is the same byte dispatched by the named moby->state switch at 002c28d0-002c28f0. domain_10_value_4 -> CIRCULAR_SAW_STATE_FOLLOW_PATH: 002c29d4-002c29f8 stores 4 into moby+0x20 when an authored path exists; the same field dispatches FOLLOW_PATH with indexed path traversal at 002c2e3c-002c3168. domain_11_value_7 -> CIRCULAR_SAW_STATE_MELEE_ATTACK: 002c2bac-002c2bdc selects attack animation 7 and stores state 7 after target distance <2, expired timer and melee spacing succeed; the named state is MELEE_ATTACK. domain_12_value_3 -> CIRCULAR_SAW_STATE_CHASE_TARGET: 002c2c20-002c2c48 selects forward animation 1, clears the movement-direction selector and stores 3 to moby+0x20 after target acquisition; this enters existing CHASE_TARGET. domain_13_value_1 -> CIRCULAR_SAW_STATE_IDLE: 002c2cac-002c2cd0 returns from completed jump animation to animation 0 and stores 1 in moby+0x20; the same selector's existing IDLE branch handles wandering and waiting. domain_14_value_7 -> CIRCULAR_SAW_STATE_MELEE_ATTACK: 002c2da4-002c2dd0 selects attack animation and writes state 7 through 002c2e38 when chase range, cooldown and melee-spacing gates pass; reuse MELEE_ATTACK. domain_15_value_1 -> CIRCULAR_SAW_STATE_IDLE: 002c2de0-002c2e38 copies the home position to destination, tests distance <1, selects animation 0 and writes 1 to moby+0x20; this returns CHASE_TARGET to named IDLE. domain_16_value_7 -> CIRCULAR_SAW_STATE_MELEE_ATTACK: 002c2f64-002c2f90 selects attack animation 7 and writes 7 through 002c3010 after path-follow target distance/cooldown/melee-spacing gates; same state byte enters MELEE_ATTACK. domain_17_value_3 -> CIRCULAR_SAW_STATE_CHASE_TARGET: 002c2fec-002c3010 selects forward animation 1, clears pvars+0x14c and writes 3 to moby+0x20 after path-follow target acquisition; reuse established CHASE_TARGET. domain_18_value_5 -> CIRCULAR_SAW_STATE_POINT_ATTACK: 002c30c8-002c30e8 tests configured clip volumes; 002c2fb8-002c2fcc saves the selected point index, writes 5 to moby+0x20 and clears the separate point-attack phase. This enters POINT_ATTACK. domain_19_value_7 -> CIRCULAR_SAW_STATE_MELEE_ATTACK: 002c3294-002c32c8 selects attack animation 7, initializes cooldown, writes 7 into moby+0x20 and clears yaw velocity after melee gates in POINT_ATTACK; reuse MELEE_ATTACK. domain_1_value_3 -> CIRCULAR_SAW_STATE_CHASE_TARGET: 002c23b0-002c23c0 compares the current moby+0x20 byte with 3, the same selector dispatched to the established CHASE_TARGET branch with flock steering at 002c2d60-002c2d68. domain_20_value_3 -> CIRCULAR_SAW_STATE_CHASE_TARGET: 002c330c-002c3330 selects forward animation 1, clears direction selector and stores 3 into moby+0x20 after target acquisition in POINT_ATTACK; same byte enters named CHASE_TARGET. domain_21_value_4 -> CIRCULAR_SAW_STATE_FOLLOW_PATH: 002c34f4-002c35e4 turns from the authored attack point toward the current path point; once yaw error is below 0.17453292 it writes 4 to moby+0x20 and resets cooldown, returning to FOLLOW_PATH. domain_22_value_1 -> CIRCULAR_SAW_STATE_IDLE: 002c3608-002c3678 exits the melee state after cooldown and attack completion/value gate, selects animation 0 and writes 1 into moby+0x20; this is the established IDLE state. domain_23_value_1 -> CIRCULAR_SAW_STATE_IDLE: 002c36c8-002c3734 completes recovery when animation 8 passes 30 or completion is flagged, selects animation 0 and writes 1 to moby+0x20; reuse existing IDLE. domain_24_value_0 -> CIRCULAR_SAW_STATE_INITIALIZE: 002c3750-002c3768 calls the suck-cannon helper with moby and pvars+0xc0; on completion it clears moby+0x20 to zero and pvars+0x1e8, causing the same selector to enter INITIALIZE. domain_25_value_9 -> CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED: 002c3860-002c386c compares the moby+0x20 state with 9 and bypasses normal movement/gravity. The same selector's named SUCK_CANNON_CONTROLLED case calls the helper at 002c3750-002c3768; supplied launch method sets this state. domain_26_value_4 -> CIRCULAR_SAW_STATE_FOLLOW_PATH: 002c3874-002c3920 compares moby+0x20 to 4 before forward-facing movement at frame_time*2; the same byte's established FOLLOW_PATH switch case computes indexed path steering. domain_27_value_3 -> CIRCULAR_SAW_STATE_CHASE_TARGET: 002c3924-002c3be8 selects the movement branch for moby+0x20 value 3, using flock destination, relative yaw and directional animation; this is the same named CHASE_TARGET selector. domain_28_value_5 -> CIRCULAR_SAW_STATE_POINT_ATTACK: 002c3bec-002c3c24 compares moby+0x20 with 5 before moving toward the authored attack destination. The same field dispatches POINT_ATTACK and its separate approach/attack/turn phases. domain_29_value_7 -> CIRCULAR_SAW_STATE_MELEE_ATTACK: 002c3bf0-002c3c24 compares moby+0x20 with 7 and checks attack animation and value >15 before destination movement; this is the existing MELEE_ATTACK state also used for joint hit collection. domain_2_value_7 -> CIRCULAR_SAW_STATE_MELEE_ATTACK: 002c240c-002c242c selects attack animation 7, initializes the attack timer and stores 7 into moby+0x20; the named MELEE_ATTACK branch uses this same state byte and joint hit collection. domain_30_value_6 -> CIRCULAR_SAW_STATE_HIT_RECOVERY: 002c3d5c-002c3d68 excludes moby+0x20 value 6 from the ordinary stationary collision pass; the same selector's HIT_RECOVERY branch and recoil movement at 002c3794-002c385c establish its domain. domain_31_value_8 -> CIRCULAR_SAW_STATE_DYING: 002c3d60-002c3d68 excludes moby+0x20 value 8 from the ordinary collision pass; the same selector's existing DYING case destroys on animation completion at 002c3738-002c3748. domain_3_value_8 -> CIRCULAR_SAW_STATE_DYING: 002c2438-002c2448 excludes moby+0x20 value 8 from hit processing; the same state selector dispatches DYING, whose animation-completion branch destroys the moby at 002c3738-002c3748. domain_4_value_0 -> CIRCULAR_SAW_STATE_INITIALIZE: 002c2438-002c2448 excludes zero in moby+0x20 from hit processing; the same selector dispatches INITIALIZE, which writes hp and initial movement configuration at 002c28f8-002c29f8. domain_5_value_0 -> CIRCULAR_SAW_STATE_INITIALIZE: 002c2490-002c2494 rechecks moby+0x20 against zero after hit_reaction; this is the same state byte as the named INITIALIZE switch case, not a hit-reaction result. domain_6_value_6 -> CIRCULAR_SAW_STATE_HIT_RECOVERY: 002c25f0-002c2684 selects recovery animation 8, stores recoil magnitude at pvars+0x13c and writes 6 to moby+0x20, entering the existing HIT_RECOVERY state. domain_7_value_7 -> CIRCULAR_SAW_STATE_MELEE_ATTACK: 002c26f8-002c2744 compares moby+0x20 with 7 and animation+0x52 with 7, gating joint-centered melee hit collection by interpolated animation values 15..44; reuse MELEE_ATTACK. domain_8_value_0 -> CIRCULAR_SAW_STATE_INITIALIZE: 002c2860 tests the current moby+0x20 byte against zero before removal/voice cleanup; it is the same state field used by the existing INITIALIZE case at 002c28f8. domain_9_value_1 -> CIRCULAR_SAW_STATE_IDLE: 002c29d4-002c29f0 stores 1 into moby+0x20 after initialization when path index pvars+0x150 is -1; the established IDLE case performs wander and target-range waiting. --- src/overlays/l04/mobys/circular_saw_enemy.c | 56 ++++++++++----------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/overlays/l04/mobys/circular_saw_enemy.c b/src/overlays/l04/mobys/circular_saw_enemy.c index e82b1fb0aa..f5b03fb16f 100644 --- a/src/overlays/l04/mobys/circular_saw_enemy.c +++ b/src/overlays/l04/mobys/circular_saw_enemy.c @@ -543,16 +543,16 @@ void circular_saw_enemy_update(M_35F0 *moby) { qcopy(dest, moby->pos); moby->f30 = 0x20; update_circular_saw_engine_sound((struct Moby *)moby); - if (moby->state == 1 || moby->state == 3) { + if (moby->state == CIRCULAR_SAW_STATE_IDLE || moby->state == CIRCULAR_SAW_STATE_CHASE_TARGET) { H_35F0 *h = (H_35F0 *)(((char *)((char *)&hero))); if (h->f240 == moby || fast_vec_dist(moby->pos, h->pos) < 1.5f) { blend_moby_animation(moby, (void *)7, 0, (void *)scale_game_frames(10)); data->f146 = scale_game_frames(0x3C); - moby->state = 7; + moby->state = CIRCULAR_SAW_STATE_MELEE_ATTACK; } } FUN_L00_001fefc8(&data->f14D); - if (moby->state != 8 && moby->state != 0) { + if (moby->state != CIRCULAR_SAW_STATE_DYING && moby->state != CIRCULAR_SAW_STATE_INITIALIZE) { int unused_hit_reaction_output; float dmg; Hit_35F0 *hit; @@ -562,7 +562,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { dmg = 0.0f; hit = find_moby_hit(moby, 0x210000, 0); r = hit_reaction(moby, hit, &data->hp, 0, &unused_hit_reaction_output, &dmg, 0, 4); - if (hit != 0 && moby->state != 0 && data->f14D == 0) { + if (hit != 0 && moby->state != CIRCULAR_SAW_STATE_INITIALIZE && data->f14D == 0) { if (hit->att != 0) { struct Hero *h = &hero; if (hit->att != h->items[0].moby) { @@ -609,7 +609,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { } else { data->f13C = 10.0f / scale_time(15.0f); } - moby->state = 6; + moby->state = CIRCULAR_SAW_STATE_HIT_RECOVERY; moby->rot = fast_add_rotations(3.1415927f, ang); data->fB7 = 0x78; trooper_anim_update(moby, (short *)data->fB0); @@ -633,7 +633,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { } data->f38 = 0; fast_dec_timer_s16(&data->f136); - if (moby->state == 7 && moby->f52 == 7 && hd > 15.0f && hd < 44.0f) { + if (moby->state == CIRCULAR_SAW_STATE_MELEE_ATTACK && moby->f52 == 7 && hd > 15.0f && hd < 44.0f) { int i; for (i = 0; i < 4; i++) { S_35F0 melee_hit_parameters; @@ -656,7 +656,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { } } } - if (moby->state != 0 && data->f2E != 1) { + if (moby->state != CIRCULAR_SAW_STATE_INITIALIZE && data->f2E != 1) { int engine_voice_index = data->f238; if (engine_voice_index != -1) { char *e = (char *)((char *)&D_0013E550) + engine_voice_index * 0x70; @@ -700,9 +700,9 @@ void circular_saw_enemy_update(M_35F0 *moby) { data->f136 = 0; data->f144 = 0; if (data->f150 == -1) { - moby->state = 1; + moby->state = CIRCULAR_SAW_STATE_IDLE; } else { - moby->state = 4; + moby->state = CIRCULAR_SAW_STATE_FOLLOW_PATH; } break; } @@ -737,13 +737,13 @@ void circular_saw_enemy_update(M_35F0 *moby) { check_circular_saw_melee_attack_spacing((char *)moby) != 0) { blend_moby_animation(moby, (void *)7, 0, (void *)scale_game_frames(10)); data->f146 = scale_game_frames(0x3C); - moby->state = 7; + moby->state = CIRCULAR_SAW_STATE_MELEE_ATTACK; } else if (flag ? target_distance < data->f140 * 2.0f : target_distance < data->f140) { if (data->f146 == 0) { blend_moby_animation(moby, (void *)1, 0, (void *)scale_game_frames(10)); data->f14C = 0; - moby->state = 3; + moby->state = CIRCULAR_SAW_STATE_CHASE_TARGET; } } } @@ -757,7 +757,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { data->f78 = -(frame_time * 7.668f); } else if (moby->f70 & 2) { blend_moby_animation(moby, 0, 0, (void *)scale_game_frames(10)); - moby->state = 1; + moby->state = CIRCULAR_SAW_STATE_IDLE; } break; case CIRCULAR_SAW_STATE_CHASE_TARGET: @@ -772,13 +772,13 @@ void circular_saw_enemy_update(M_35F0 *moby) { check_circular_saw_melee_attack_spacing((char *)moby) != 0) { blend_moby_animation(moby, (void *)7, 0, (void *)scale_game_frames(10)); data->f146 = scale_game_frames(0x3C); - moby->state = 7; + moby->state = CIRCULAR_SAW_STATE_MELEE_ATTACK; } } else if (flag == 0) { qcopy(dest, data->f120); if (vector_distance_xy(moby->pos, data->f120) < 1.0f) { blend_moby_animation(moby, 0, 0, (void *)scale_game_frames(10)); - moby->state = 1; + moby->state = CIRCULAR_SAW_STATE_IDLE; } } func_L00_002592B0_b((char *)moby, @@ -809,13 +809,13 @@ void circular_saw_enemy_update(M_35F0 *moby) { check_circular_saw_melee_attack_spacing((char *)moby) != 0) { blend_moby_animation(moby, (void *)7, 0, (void *)scale_game_frames(10)); data->f146 = scale_game_frames(0x3C); - moby->state = 7; + moby->state = CIRCULAR_SAW_STATE_MELEE_ATTACK; } else if (flag ? target_distance < data->f140 * 2.0f : target_distance < data->f140) { if (data->f146 == 0) { blend_moby_animation(moby, (void *)1, 0, (void *)scale_game_frames(10)); data->f14C = 0; - moby->state = 3; + moby->state = CIRCULAR_SAW_STATE_CHASE_TARGET; } } } @@ -836,7 +836,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { if (data->f146 == 0 && data->f160[i] != -1 && is_point_inside_clip_volume(moby->pos, data->f160[i]) != 0) { data->f158 = data->f160[i]; - moby->state = 5; + moby->state = CIRCULAR_SAW_STATE_POINT_ATTACK; data->f15A = 0; break; } @@ -873,14 +873,14 @@ void circular_saw_enemy_update(M_35F0 *moby) { check_circular_saw_melee_attack_spacing((char *)moby) != 0) { blend_moby_animation(moby, (void *)7, 0, (void *)scale_game_frames(10)); data->f146 = scale_game_frames(0x3C); - moby->state = 7; + moby->state = CIRCULAR_SAW_STATE_MELEE_ATTACK; data->f130 = 0.0f; } else if (flag ? target_distance < data->f140 * 2.0f : target_distance < data->f140) { if (data->f146 == 0) { blend_moby_animation(moby, (void *)1, 0, (void *)scale_game_frames(10)); data->f14C = 0; - moby->state = 3; + moby->state = CIRCULAR_SAW_STATE_CHASE_TARGET; } } } @@ -931,7 +931,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { moby->rot, fast_arc_tan(path->pts[data->f154][0] - moby->pos[0], path->pts[data->f154][1] - moby->pos[1])) < 0.17453292f) { - moby->state = 4; + moby->state = CIRCULAR_SAW_STATE_FOLLOW_PATH; data->f146 = scale_game_frames(0xF0); } break; @@ -945,7 +945,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { if (data->f146 == 0 && (hd > 44.0f || (moby->f70 & 2))) { blend_moby_animation(moby, 0, 0, (void *)scale_game_frames(5)); data->f146 = scale_game_frames(0x78); - moby->state = 1; + moby->state = CIRCULAR_SAW_STATE_IDLE; data->f14E |= 2; } func_L00_002592B0_b((char *)moby, @@ -959,7 +959,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { if ((moby->f52 == 8 && compute_interpolated_record_value(moby) > 30.0f) || (moby->f70 & 2)) { blend_moby_animation(moby, 0, 0, (void *)scale_game_frames(10)); - moby->state = 1; + moby->state = CIRCULAR_SAW_STATE_IDLE; data->f146 = 0; } break; @@ -972,7 +972,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { break; case CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED: if (FUN_L00_002dc9f0(moby, data->fC0) != 0) { - moby->state = 0; + moby->state = CIRCULAR_SAW_STATE_INITIALIZE; data->f1E8 = 0; } break; @@ -988,10 +988,10 @@ void circular_saw_enemy_update(M_35F0 *moby) { move_moby_xy_with_collision_constraints(moby, moby->pos, v, 1, 0.25f, 0.57f, 0.5f, 0.5235988f); } } - if (moby->state == 9) { + if (moby->state == CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED) { return; } - if (moby->state == 4) { + if (moby->state == CIRCULAR_SAW_STATE_FOLLOW_PATH) { V4_35F0 v; V4_35F0 np; { @@ -1011,7 +1011,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { qcopy(moby->pos, np); } } - } else if (moby->state == 3) { + } else if (moby->state == CIRCULAR_SAW_STATE_CHASE_TARGET) { V4_35F0 v; V4_35F0 np; float ang = fast_arc_tan(dest[0] - moby->pos[0], dest[1] - moby->pos[1]); @@ -1063,7 +1063,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { data->f144 = scale_game_frames(0xF); } } - } else if (moby->state == 5 || (moby->state == 7 && moby->f52 == 7 && hd > 15.0f)) { + } else if (moby->state == CIRCULAR_SAW_STATE_POINT_ATTACK || (moby->state == CIRCULAR_SAW_STATE_MELEE_ATTACK && moby->f52 == 7 && hd > 15.0f)) { if (vector_distance_xy(moby->pos, dest) > frame_time * 2.0f) { V4_35F0 v; V4_35F0 np; @@ -1084,7 +1084,7 @@ void circular_saw_enemy_update(M_35F0 *moby) { } } } - } else if (moby->state != 6 && moby->state != 8) { + } else if (moby->state != CIRCULAR_SAW_STATE_HIT_RECOVERY && moby->state != CIRCULAR_SAW_STATE_DYING) { V4_35F0 v; { qcopy(v, moby->pos); From 53fa75111697bc88caac1a62603df45cf33b969d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:26:27 +0000 Subject: [PATCH 1305/1502] decomp: clarify names in woodcut_bot_update domain_0_value_11 -> WOODCUT_BOT_DEATH_KNOCKBACK: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d1820-0x002d1828 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1a38-0x002d1a80 starts death knockback and writes state 11; 0x002d3188-0x002d3260 updates falling, emits effects and removes the moby. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_10_value_5 -> WOODCUT_BOT_MOVE_TOWARD_TARGET: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2128-0x002d212c compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d26b0-0x002d2704 derives selected-target bearing and calls the walker with frame_time*4. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_11_value_10 -> WOODCUT_BOT_TURN_BEFORE_MOVEMENT: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2164-0x002d2168 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d2ff0-0x002d3184 spring-turns toward target or saved position and chooses movement state 5 or return state 6. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_12_value_6 -> WOODCUT_BOT_RETURN_TO_SAVED_POSITION: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d21f8-0x002d2628 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d2960-0x002d29e0 tests distance to saved d+0x3B0 and walks toward that position. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_13_value_5 -> WOODCUT_BOT_MOVE_TOWARD_TARGET: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2220-0x002d2628 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d26b0-0x002d2704 derives selected-target bearing and calls the walker with frame_time*4. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_14_value_1 -> WOODCUT_BOT_IDLE: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2260-0x002d2e10 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1f84-0x002d21fc chooses idle animations and waits for the action timer before selecting movement or melee. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_15_value_8 -> WOODCUT_BOT_MELEE_ATTACK: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d24a4-0x002d2de8 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1ce8-0x002d1ea0 gates melee collision queries on state 8 and animation 4 frames 16..27; 0x002d2b7c-0x002d2ba0 returns idle on completion. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_16_value_5 -> WOODCUT_BOT_MOVE_TOWARD_TARGET: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d24f0-0x002d2628 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d26b0-0x002d2704 derives selected-target bearing and calls the walker with frame_time*4. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_17_value_10 -> WOODCUT_BOT_TURN_BEFORE_MOVEMENT: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2564-0x002d2568 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d2ff0-0x002d3184 spring-turns toward target or saved position and chooses movement state 5 or return state 6. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_18_value_8 -> WOODCUT_BOT_MELEE_ATTACK: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d25e4-0x002d2de8 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1ce8-0x002d1ea0 gates melee collision queries on state 8 and animation 4 frames 16..27; 0x002d2b7c-0x002d2ba0 returns idle on completion. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_19_value_5 -> WOODCUT_BOT_MOVE_TOWARD_TARGET: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2624-0x002d2628 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d26b0-0x002d2704 derives selected-target bearing and calls the walker with frame_time*4. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_1_value_0 -> WOODCUT_BOT_INITIALIZE: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d1830 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1ed4-0x002d1f80 initializes HP, flags and timers, saves position and attaches the manipulator. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_20_value_10 -> WOODCUT_BOT_TURN_BEFORE_MOVEMENT: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2680-0x002d2688 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d2ff0-0x002d3184 spring-turns toward target or saved position and chooses movement state 5 or return state 6. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_21_value_1 -> WOODCUT_BOT_IDLE: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d257c-0x002d2e10 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1f84-0x002d21fc chooses idle animations and waits for the action timer before selecting movement or melee. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_22_value_8 -> WOODCUT_BOT_MELEE_ATTACK: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2768-0x002d2de8 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1ce8-0x002d1ea0 gates melee collision queries on state 8 and animation 4 frames 16..27; 0x002d2b7c-0x002d2ba0 returns idle on completion. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_23_value_7 -> WOODCUT_BOT_STOP_MOVEMENT: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2814-0x002d2874 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d2b30-0x002d2b78 calls the walker with zero speed and waits for d+0x217 before selecting idle or action. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_24_value_10 -> WOODCUT_BOT_TURN_BEFORE_MOVEMENT: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2870-0x002d2874 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d2ff0-0x002d3184 spring-turns toward target or saved position and chooses movement state 5 or return state 6. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_25_value_6 -> WOODCUT_BOT_RETURN_TO_SAVED_POSITION: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d28b0-0x002d28b8 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d2960-0x002d29e0 tests distance to saved d+0x3B0 and walks toward that position. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_26_value_8 -> WOODCUT_BOT_MELEE_ATTACK: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d293c-0x002d2de8 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1ce8-0x002d1ea0 gates melee collision queries on state 8 and animation 4 frames 16..27; 0x002d2b7c-0x002d2ba0 returns idle on completion. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_27_value_7 -> WOODCUT_BOT_STOP_MOVEMENT: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2980-0x002d2ac4 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d2b30-0x002d2b78 calls the walker with zero speed and waits for d+0x217 before selecting idle or action. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_28_value_10 -> WOODCUT_BOT_TURN_BEFORE_MOVEMENT: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2a88-0x002d2a8c compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d2ff0-0x002d3184 spring-turns toward target or saved position and chooses movement state 5 or return state 6. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_29_value_7 -> WOODCUT_BOT_STOP_MOVEMENT: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2abc-0x002d2ac4 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d2b30-0x002d2b78 calls the walker with zero speed and waits for d+0x217 before selecting idle or action. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_2_value_0 -> WOODCUT_BOT_INITIALIZE: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d18a8-0x002d18ac compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1ed4-0x002d1f80 initializes HP, flags and timers, saves position and attaches the manipulator. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_30_value_8 -> WOODCUT_BOT_MELEE_ATTACK: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2b28-0x002d2de8 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1ce8-0x002d1ea0 gates melee collision queries on state 8 and animation 4 frames 16..27; 0x002d2b7c-0x002d2ba0 returns idle on completion. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_31_value_4 -> WOODCUT_BOT_SELECT_ACTION_WHILE_EXCITED: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2b70-0x002d2b78 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d2578-0x002d2688 tests excitement and target geometry to select idle, melee, movement or turning. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_32_value_1 -> WOODCUT_BOT_IDLE: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2b6c-0x002d2e10 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1f84-0x002d21fc chooses idle animations and waits for the action timer before selecting movement or melee. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_33_value_1 -> WOODCUT_BOT_IDLE: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2b9c-0x002d2e10 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1f84-0x002d21fc chooses idle animations and waits for the action timer before selecting movement or melee. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_34_value_1 -> WOODCUT_BOT_IDLE: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2c10-0x002d2fe4 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1f84-0x002d21fc chooses idle animations and waits for the action timer before selecting movement or melee. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_35_value_8 -> WOODCUT_BOT_MELEE_ATTACK: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2de0-0x002d2de8 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1ce8-0x002d1ea0 gates melee collision queries on state 8 and animation 4 frames 16..27; 0x002d2b7c-0x002d2ba0 returns idle on completion. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_36_value_1 -> WOODCUT_BOT_IDLE: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2dec-0x002d2e10 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1f84-0x002d21fc chooses idle animations and waits for the action timer before selecting movement or melee. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_37_value_1 -> WOODCUT_BOT_IDLE: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2bf4-0x002d2fe4 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1f84-0x002d21fc chooses idle animations and waits for the action timer before selecting movement or melee. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_38_value_1 -> WOODCUT_BOT_IDLE: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2fe0-0x002d2fe4 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1f84-0x002d21fc chooses idle animations and waits for the action timer before selecting movement or melee. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_39_value_6 -> WOODCUT_BOT_RETURN_TO_SAVED_POSITION: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d304c-0x002d3058 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d2960-0x002d29e0 tests distance to saved d+0x3B0 and walks toward that position. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_3_value_11 -> WOODCUT_BOT_DEATH_KNOCKBACK: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d1a5c-0x002d1a80 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1a38-0x002d1a80 starts death knockback and writes state 11; 0x002d3188-0x002d3260 updates falling, emits effects and removes the moby. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_40_value_5 -> WOODCUT_BOT_MOVE_TOWARD_TARGET: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d3048-0x002d3080 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d26b0-0x002d2704 derives selected-target bearing and calls the walker with frame_time*4. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_41_value_9 -> WOODCUT_BOT_HIT_RECOVERY_AND_REPOSITION: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d33c8-0x002d33d4 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1b4c-0x002d1b54 enters state 9 after a hit; 0x002d2ba4-0x002d2fec searches path-bounded reposition candidates and applies reposition motion. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_42_value_5 -> WOODCUT_BOT_MOVE_TOWARD_TARGET: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d33d8-0x002d33e0 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d26b0-0x002d2704 derives selected-target bearing and calls the walker with frame_time*4. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_4_value_9 -> WOODCUT_BOT_HIT_RECOVERY_AND_REPOSITION: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d1b4c-0x002d1b54 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1b4c-0x002d1b54 enters state 9 after a hit; 0x002d2ba4-0x002d2fec searches path-bounded reposition candidates and applies reposition motion. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_5_value_1 -> WOODCUT_BOT_IDLE: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d1c2c-0x002d1c34 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1f84-0x002d21fc chooses idle animations and waits for the action timer before selecting movement or melee. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_6_value_8 -> WOODCUT_BOT_MELEE_ATTACK: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d1ce8-0x002d1cf0 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1ce8-0x002d1ea0 gates melee collision queries on state 8 and animation 4 frames 16..27; 0x002d2b7c-0x002d2ba0 returns idle on completion. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_7_value_3 -> WOODCUT_BOT_PLAY_ANIMATION_AND_EMIT_DEBRIS: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d1f50-0x002d1f5c compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d2268-0x002d2460 plays animations and emits twenty debris pieces at animation window 36. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_8_value_1 -> WOODCUT_BOT_IDLE: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d1f7c-0x002d1f80 compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1f84-0x002d21fc chooses idle animations and waits for the action timer before selecting movement or melee. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. domain_9_value_8 -> WOODCUT_BOT_MELEE_ATTACK: Authoritative C src/overlays/l04/mobys/woodcut_bot.c SHA-256 7ccd497147fc23a4b802773c55e8dac789cac6419b38acabaa6e8e6cc9de595e identifies this token as m->state. Retail 0x002d2094-0x002d209c compares or assigns the moby state byte at s2+0x20, the same selector dispatched at 0x002d1eac-0x002d1ecc. Reuse the existing local state enum member: 0x002d1ce8-0x002d1ea0 gates melee collision queries on state 8 and animation 4 frames 16..27; 0x002d2b7c-0x002d2ba0 returns idle on completion. Original retail Ghidra confirms this field and flow; it is separate from reaction r and HeroStateId. --- src/overlays/l04/mobys/woodcut_bot.c | 84 ++++++++++++++-------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/src/overlays/l04/mobys/woodcut_bot.c b/src/overlays/l04/mobys/woodcut_bot.c index c76cf898a4..73cb2e95a7 100644 --- a/src/overlays/l04/mobys/woodcut_bot.c +++ b/src/overlays/l04/mobys/woodcut_bot.c @@ -381,7 +381,7 @@ void woodcut_bot_update(WBMoby *m) { qcopy(duplicate_position_snapshot, pos); fast_dec_timer_s16(&d->t3C4); - if (m->state != 0xB && m->state != 0) { + if (m->state != WOODCUT_BOT_DEATH_KNOCKBACK && m->state != WOODCUT_BOT_INITIALIZE) { int r; int htype; float damage; @@ -394,7 +394,7 @@ void woodcut_bot_update(WBMoby *m) { r = hit_reaction(m, p, &d->hp, 0, &htype, &damage, 0, 4); d->fE0 = 0x15E; d->fE8 = 0.35f; - if (p != 0 && damage != 0.0f && m->state != 0 && d->t3C4 == 0) { + if (p != 0 && damage != 0.0f && m->state != WOODCUT_BOT_INITIALIZE && d->t3C4 == 0) { unsigned char *hit_source_moby; float knockback_gravity_step; float b; @@ -440,7 +440,7 @@ void woodcut_bot_update(WBMoby *m) { trooper_start_knockback(angle, m, d->fC0, 8, 1, 0); d->f110 = 14.0f; d->f114 = 24.0f; - m->state = 0xB; + m->state = WOODCUT_BOT_DEATH_KNOCKBACK; FUN_L00_00257470(m, 0, -1); d->fB7 = 0x78; trooper_anim_update(m, d->fB0); @@ -455,7 +455,7 @@ void woodcut_bot_update(WBMoby *m) { m->fBC |= 5; blend_moby_animation(m, 5, 0, scale_game_frames(3)); reset_walker_gait_helpers(d->f160); - m->state = 9; + m->state = WOODCUT_BOT_HIT_RECOVERY_AND_REPOSITION; hit_source_moby_class = *(short *)(*(char **)(p + 0x20) + 0xA6); if (hit_source_moby_class == 0x131 || hit_source_moby_class == 0xB0) { d->f3E4 = (2.0f / scale_time(15.0f)) * 0.5f; @@ -474,7 +474,7 @@ void woodcut_bot_update(WBMoby *m) { case WOODCUT_BOT_REACTION_RECOIL_TO_IDLE_WITH_COOLDOWNS: blend_moby_animation(m, 6, 0, scale_game_frames(10)); reset_walker_gait_helpers(d->f160); - m->state = 1; + m->state = WOODCUT_BOT_IDLE; d->f3E4 = 2.0f / scale_time(15.0f); *(OvlQuad *)v = *(OvlQuad *)(p + 0x10); trooper_knockback_arc(v, &angle, &d->f3E4, &one); @@ -501,7 +501,7 @@ void woodcut_bot_update(WBMoby *m) { d->f38 = 0; fast_dec_timer_s16(&d->t3C6); - if (m->state == 8) { + if (m->state == WOODCUT_BOT_MELEE_ATTACK) { if (m->anim == 4 && hd > 16.0f && hd < 27.0f) { WBJoints joints = D_L04_001DC450; float pts[6][4]; @@ -545,10 +545,10 @@ void woodcut_bot_update(WBMoby *m) { attach_manipulator(m, 6, manipulator); initialize_woodcut_bot_movement_data(m); if (d->f3C0 != 0) { - m->state = 3; + m->state = WOODCUT_BOT_PLAY_ANIMATION_AND_EMIT_DEBRIS; blend_moby_animation(m, 0xB, 0, scale_game_frames(10)); } else { - m->state = 1; + m->state = WOODCUT_BOT_IDLE; } break; case WOODCUT_BOT_IDLE: @@ -566,21 +566,21 @@ void woodcut_bot_update(WBMoby *m) { if (d->t3C2 == 0) { if (target_distance < 3.0f && adiff < 1.5707964f) { blend_moby_animation(m, 4, 0, scale_game_frames(10)); - m->state = 8; + m->state = WOODCUT_BOT_MELEE_ATTACK; } else if (excited ? (target_distance < d->f3E8 * 2.0f) : (target_distance < d->f3E8)) { if (m->fBC & 1) { if (excited || d->f3DC == -1 || point_in_path_xy(selected_target_position, ((int *)l04_paths[d->f3DC]) + 4, *((int *)l04_paths[d->f3DC])) != 0) { - m->state = 5; + m->state = WOODCUT_BOT_MOVE_TOWARD_TARGET; m->fBC |= 8; } } else { d->f3D0 = 0.0f; blend_moby_animation(m, 0x10, 0, scale_game_frames(10)); reset_walker_gait_helpers(d->f160); - m->state = 0xA; + m->state = WOODCUT_BOT_TURN_BEFORE_MOVEMENT; m->fBC |= 1; } } @@ -590,7 +590,7 @@ void woodcut_bot_update(WBMoby *m) { (d->f3DC != -1 && point_in_path_xy(selected_target_position, ((int *)l04_paths[d->f3DC]) + 4, *((int *)l04_paths[d->f3DC])) == 0)) { - m->state = 6; + m->state = WOODCUT_BOT_RETURN_TO_SAVED_POSITION; m->fBC |= 8; } } @@ -603,11 +603,11 @@ void woodcut_bot_update(WBMoby *m) { point_in_path_xy(selected_target_position, ((int *)l04_paths[d->f3DC]) + 4, *((int *)l04_paths[d->f3DC])) != 0) { - m->state = 5; + m->state = WOODCUT_BOT_MOVE_TOWARD_TARGET; m->fBC |= 8; } else { blend_moby_animation(m, 0, 0, scale_game_frames(10)); - m->state = 1; + m->state = WOODCUT_BOT_IDLE; } } break; @@ -651,21 +651,21 @@ void woodcut_bot_update(WBMoby *m) { if (d->t3C2 == 0) { if (target_distance < 3.0f && adiff < 1.5707964f) { blend_moby_animation(m, 4, 0, scale_game_frames(10)); - m->state = 8; + m->state = WOODCUT_BOT_MELEE_ATTACK; } else if (excited ? (target_distance < d->f3E8 * 2.0f) : (target_distance < d->f3E8)) { if (m->fBC & 1) { if (excited || d->f3DC == -1 || point_in_path_xy(selected_target_position, ((int *)l04_paths[d->f3DC]) + 4, *((int *)l04_paths[d->f3DC])) != 0) { - m->state = 5; + m->state = WOODCUT_BOT_MOVE_TOWARD_TARGET; m->fBC |= 8; } } else { d->f3D0 = 0.0f; blend_moby_animation(m, 0x10, 0, scale_game_frames(10)); reset_walker_gait_helpers(d->f160); - m->state = 0xA; + m->state = WOODCUT_BOT_TURN_BEFORE_MOVEMENT; m->fBC |= 1; } } @@ -677,20 +677,20 @@ void woodcut_bot_update(WBMoby *m) { if (target_distance < 3.0f && adiff < 1.5707964f) { blend_moby_animation(m, 4, 0, scale_game_frames(10)); reset_walker_gait_helpers(d->f160); - m->state = 8; + m->state = WOODCUT_BOT_MELEE_ATTACK; } else if (d->f3DC == -1 || point_in_path_xy(selected_target_position, ((int *)l04_paths[d->f3DC]) + 4, *((int *)l04_paths[d->f3DC])) != 0) { - m->state = 5; + m->state = WOODCUT_BOT_MOVE_TOWARD_TARGET; m->fBC |= 8; } else if (adiff > 1.5707964f) { d->f3D0 = 0.0f; blend_moby_animation(m, 0x10, 0, scale_game_frames(10)); reset_walker_gait_helpers(d->f160); - m->state = 0xA; + m->state = WOODCUT_BOT_TURN_BEFORE_MOVEMENT; } } else { - m->state = 1; + m->state = WOODCUT_BOT_IDLE; } break; case WOODCUT_BOT_MOVE_TOWARD_TARGET: { @@ -707,7 +707,7 @@ void woodcut_bot_update(WBMoby *m) { if (target_distance < 3.0f && adiff < 1.5707964f) { blend_moby_animation(m, 4, 0, scale_game_frames(10)); reset_walker_gait_helpers(d->f160); - m->state = 8; + m->state = WOODCUT_BOT_MELEE_ATTACK; } else if (d->f3DC != -1) { float v[4]; @@ -721,21 +721,21 @@ void woodcut_bot_update(WBMoby *m) { if (excited && point_in_path_xy(selected_target_position, ((int *)l04_paths[d->f3DC]) + 4, *((int *)l04_paths[d->f3DC])) == 0) { - m->state = 7; + m->state = WOODCUT_BOT_STOP_MOVEMENT; } else if (point_in_path_xy(selected_target_position, ((int *)l04_paths[d->f3DC]) + 4, *((int *)l04_paths[d->f3DC])) != 0) { d->f3D0 = 0.0f; blend_moby_animation(m, 0x10, 0, scale_game_frames(10)); reset_walker_gait_helpers(d->f160); - m->state = 0xA; + m->state = WOODCUT_BOT_TURN_BEFORE_MOVEMENT; } } if (!excited) { if (point_in_path_xy(selected_target_position, ((int *)l04_paths[d->f3DC]) + 4, *((int *)l04_paths[d->f3DC])) == 0) { - m->state = 6; + m->state = WOODCUT_BOT_RETURN_TO_SAVED_POSITION; } } } @@ -749,14 +749,14 @@ void woodcut_bot_update(WBMoby *m) { if (target_distance < 3.0f && adiff < 1.5707964f) { blend_moby_animation(m, 4, 0, scale_game_frames(10)); reset_walker_gait_helpers(d->f160); - m->state = 8; + m->state = WOODCUT_BOT_MELEE_ATTACK; } else { if (m->fBC & 8) { m->fBC &= ~8; reset_leg_rig_from_animation(m, d->f160); } if (vector_distance_xy(pos, d->f3B0) < 2.0f) { - m->state = 7; + m->state = WOODCUT_BOT_STOP_MOVEMENT; } else { leg_walker_update(m, d->f160, @@ -776,12 +776,12 @@ void woodcut_bot_update(WBMoby *m) { d->f3D0 = 0.0f; blend_moby_animation(m, 0x10, 0, scale_game_frames(10)); reset_walker_gait_helpers(d->f160); - m->state = 0xA; + m->state = WOODCUT_BOT_TURN_BEFORE_MOVEMENT; m->fBC |= 0x10; } else if (point_in_path_xy(selected_target_position, ((int *)l04_paths[d->f3DC]) + 4, *((int *)l04_paths[d->f3DC])) != 0) { - m->state = 7; + m->state = WOODCUT_BOT_STOP_MOVEMENT; } } } @@ -791,14 +791,14 @@ void woodcut_bot_update(WBMoby *m) { if (target_distance < 3.0f && adiff < 1.5707964f) { blend_moby_animation(m, 4, 0, scale_game_frames(10)); reset_walker_gait_helpers(d->f160); - m->state = 8; + m->state = WOODCUT_BOT_MELEE_ATTACK; } else { leg_walker_update(m, d->f160, frame_time * 0.0f, m->rot[2], frame_time_sq * 20.0f); if (d->f217 == 0) { if (excited) { - m->state = 4; + m->state = WOODCUT_BOT_SELECT_ACTION_WHILE_EXCITED; } else { - m->state = 1; + m->state = WOODCUT_BOT_IDLE; } } } @@ -807,7 +807,7 @@ void woodcut_bot_update(WBMoby *m) { if (m->anim == 4 && (m->f70 & 2)) { d->t3C2 = 0; blend_moby_animation(m, 0, 0, scale_game_frames(10)); - m->state = 1; + m->state = WOODCUT_BOT_IDLE; } break; case WOODCUT_BOT_HIT_RECOVERY_AND_REPOSITION: @@ -816,7 +816,7 @@ void woodcut_bot_update(WBMoby *m) { m->fBC &= ~4; if (d->f3DC == -1) { blend_moby_animation(m, 0, 0, scale_game_frames(10)); - m->state = 1; + m->state = WOODCUT_BOT_IDLE; d->t3C2 = 0; } else { WBAngles tab = D_L04_001DC468; @@ -856,14 +856,14 @@ void woodcut_bot_update(WBMoby *m) { if (m->anim == 5) { if (target_distance < 3.0f && adiff < 1.5707964f) { blend_moby_animation(m, 4, 0, scale_game_frames(10)); - m->state = 8; + m->state = WOODCUT_BOT_MELEE_ATTACK; } else { blend_moby_animation(m, 0, 0, scale_game_frames(10)); - m->state = 1; + m->state = WOODCUT_BOT_IDLE; } } else { blend_moby_animation(m, 0, 0, scale_game_frames(10)); - m->state = 1; + m->state = WOODCUT_BOT_IDLE; d->t3C2 = 0; } } @@ -900,7 +900,7 @@ void woodcut_bot_update(WBMoby *m) { frame_time_sq * 6.2831855f, frame_time * 4.1887903f); } else { - m->state = 1; + m->state = WOODCUT_BOT_IDLE; d->t3C2 = 0; } } @@ -911,10 +911,10 @@ void woodcut_bot_update(WBMoby *m) { if ((m->fBC & 0x10) || point_in_path_xy(selected_target_position, ((int *)l04_paths[d->f3DC]) + 4, *((int *)l04_paths[d->f3DC])) == 0) { - m->state = 6; + m->state = WOODCUT_BOT_RETURN_TO_SAVED_POSITION; blend_moby_animation(m, 0, 0, scale_game_frames(10)); } else { - m->state = 5; + m->state = WOODCUT_BOT_MOVE_TOWARD_TARGET; blend_moby_animation(m, 0, 0, scale_game_frames(10)); } m->fBC = (m->fBC | 8) & ~0x10; @@ -972,9 +972,9 @@ void woodcut_bot_update(WBMoby *m) { build_axis_rotation_quaternion(recoil_scratch, 1, d->f3C8); build_axis_rotation_quaternion(d->f130, 2, 0.0f); multiply_quaternions(d->f130, d->f130, recoil_scratch); - if (m->state != 9) + if (m->state != WOODCUT_BOT_HIT_RECOVERY_AND_REPOSITION) d->f3C1 = m->state; - if (m->state != 5 && m->fBC != 6) { + if (m->state != WOODCUT_BOT_MOVE_TOWARD_TARGET && m->fBC != 6) { float g; d->f3E0 += frame_time_sq * 9.8f; From 83051c2de03624a265442d7c83f5052b3fefec87 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:28:20 +0000 Subject: [PATCH 1306/1502] decomp: clarify names in sentrybot_update domain_0_value_2 -> SENTRYBOT_TARGET_MODE_SUPPRESS_DIRECT_EMISSION: Authoritative sentrybot.c SHA-256 61855d0244cebc6621c4a9872d10d71a9919f1929cbf319bdfd6672336c3407e loads mode from instance_data+0x114 in SENTRYBOT_ALERT_IDLE. Retail 0x002991d8 and 0x00299244-0x00299268 compare this field with 2; unequal with data+0x15b clear routes to heading helper continuation 16/animation 3 at 0x00299310-0x00299318, the established emission-wait state. Equal instead reaches timer/visibility/patrol handling. Checked producer 0x0029a570 loads the same moby pvars at 0x0029a5a0; 0x0029aaa4-0x0029aac8 writes 2 when the visibility gate is false, 0x0029aacc-0x0029ab18 writes 2 on visible-but-response-gated paths, and 0x0029ab3c-0x0029ab4c forces 2 during the global gate. This proves suppression of the direct emission response, not a hero or moby state ID. domain_1_value_2 -> SENTRYBOT_TARGET_MODE_SUPPRESS_DIRECT_EMISSION: This second mode != 2 uses the same local loaded from sentrybot_instance_data+0x114, not moby+0x20. Original retail Ghidra case 0xc and instructions 0x002992e8-0x00299334 show visibility byte +0x15a selecting this branch: mode unequal 2 and +0x15b clear routes to continuation 16/animation 3 (0x00299304-0x00299318); equal 2 instead requests continuation 12/animation 0 (0x00299324-0x00299334), established ALERT_IDLE. Checked producer 0x0029aab8-0x0029aac8 and 0x0029ab0c-0x0029ab18 writes 2 on unseen or gated target-response paths. Thus this occurrence shares SENTRYBOT_TARGET_MODE_SUPPRESS_DIRECT_EMISSION with the first comparison; timer-driven responses remain possible. --- src/overlays/shared/enemies/sentrybot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/sentrybot.c b/src/overlays/shared/enemies/sentrybot.c index 30c981cc66..52bbe9d500 100644 --- a/src/overlays/shared/enemies/sentrybot.c +++ b/src/overlays/shared/enemies/sentrybot.c @@ -276,7 +276,7 @@ void sentrybot_update(unsigned char *moby) { SENTRYBOT_ANIM_TURN_NEGATIVE_HEADING_DELTA = 10, SENTRYBOT_ANIM_TURN_POSITIVE_HEADING_DELTA = 11, SENTRYBOT_ANIM_TURN_AROUND = 12 - }; + } ; enum { SENTRYBOT_TARGET_MODE_SUPPRESS_DIRECT_EMISSION = 2}; float va[4]; float vb[4]; float emission_origin[4]; @@ -1031,7 +1031,7 @@ void sentrybot_update(unsigned char *moby) { } } else { int mode = sentrybot_instance_data->unk114; - if (mode != 2 && sentrybot_instance_data->unk15B == 0) { + if (mode != SENTRYBOT_TARGET_MODE_SUPPRESS_DIRECT_EMISSION && sentrybot_instance_data->unk15B == 0) { begin_sentrybot_turn_toward_point((char *)moby, sentrybot_instance_data, (float *)(&sentrybot_instance_data->unkD0), @@ -1048,7 +1048,7 @@ void sentrybot_update(unsigned char *moby) { set_sentrybot_alarm_duration(linked_alarm_moby, scale_game_frames(0x1E)); } } else if (sentrybot_instance_data->has_line_of_sight != 0) { - if (mode != 2 && sentrybot_instance_data->unk15B == 0) { + if (mode != SENTRYBOT_TARGET_MODE_SUPPRESS_DIRECT_EMISSION && sentrybot_instance_data->unk15B == 0) { begin_sentrybot_turn_toward_point((char *)moby, sentrybot_instance_data, (float *)(target + 0x10), From 91d3b76b3bfff1a7690c4890e668cde30b30564a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:30:15 +0000 Subject: [PATCH 1307/1502] decomp: clarify names in suckcannon_update domain_0_value_3 -> SUCKCANNON_ANIMATION_SUCTION_LOOP: The selector is the cannon animation sequence byte +0x53, not its state byte +0x20: retail helper 0x00257880 moves new_seq a1 into s3 at 0x002578a0, indexes the class sequence table with it at 0x002578a8-0x002578c8, and stores it at +0x53 at 0x00257964. Assigned retail 0x002dac00-0x002dac40 compares this byte with 3 and blends sequence 3 when needed within SUCKCANNON_STATE_SUCTION_ACTIVE. At 0x002dad98-0x002dadbc animation flag 2 causes sequence 3 to restart with a two-frame blend, immediately followed by suction update at 0x002dadc4. Startup also selects 3 at 0x002daae4-0x002daafc. Original Ghidra case 3 and supplied blend_moby_animation C corroborate a repeating suction animation, a domain distinct from SUCKCANNON_STATE_SUCTION_ACTIVE and HERO_STATE_STOP. --- src/overlays/shared/weapons/suckcannon.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/suckcannon.c b/src/overlays/shared/weapons/suckcannon.c index 47e851fc82..992d742971 100644 --- a/src/overlays/shared/weapons/suckcannon.c +++ b/src/overlays/shared/weapons/suckcannon.c @@ -1418,6 +1418,9 @@ void suckcannon_update(SuckMoby *suck_cannon_moby) { SUCKCANNON_STATE_LOADED_AIM = 4, SUCKCANNON_STATE_FIRE_STORED_MOBY = 5 }; + enum { + SUCKCANNON_ANIMATION_SUCTION_LOOP = 3 + }; SuckWork aim_and_fire_scratch; SuckCannon *cannon; SuckStats *stats; @@ -1513,7 +1516,7 @@ void suckcannon_update(SuckMoby *suck_cannon_moby) { } break; case SUCKCANNON_STATE_SUCTION_ACTIVE: - if (suck_cannon_moby->anim_state != 3 && + if (suck_cannon_moby->anim_state != SUCKCANNON_ANIMATION_SUCTION_LOOP && (suck_cannon_moby->anim_state != 0 || (suck_cannon_moby->anim_flags & 2))) blend_moby_animation(suck_cannon_moby, 3, 0, scale_game_frames(5)); fast_dec_timer(&cannon->cooldown); From ee95965a2ba97e1e2f4fa07fba65ea483d42f863 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:30:15 +0000 Subject: [PATCH 1308/1502] decomp: clarify names in peckbot_update domain_10_value_14 -> PECKBOT_STATE_AIRBORNE_IDLE: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f03b4-002f03d8 zero destination-movement velocity returns to airborne idle. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_AIRBORNE_IDLE member. Reuse that same selector-domain constant. domain_11_value_3 -> PECKBOT_STATE_CHASE_TARGET: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f051c-002f0528 landing clamps Z to ground and selects chase with animation 2. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_CHASE_TARGET member. Reuse that same selector-domain constant. domain_12_value_14 -> PECKBOT_STATE_AIRBORNE_IDLE: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f05b4-002f05dc ascent clamps Z to ground plus six and selects airborne idle. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_AIRBORNE_IDLE member. Reuse that same selector-domain constant. domain_13_value_2 -> PECKBOT_STATE_FACE_AWAY_FROM_TARGET: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f066c-002f067c ground idle close-target gates select the branch that faces away from target. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_FACE_AWAY_FROM_TARGET member. Reuse that same selector-domain constant. domain_14_value_3 -> PECKBOT_STATE_CHASE_TARGET: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0718-002f072c ground idle hit response initializes turning and selects chase. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_CHASE_TARGET member. Reuse that same selector-domain constant. domain_15_value_16 -> PECKBOT_STATE_ASCEND: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0770-002f077c ground idle far-target condition selects ascent. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_ASCEND member. Reuse that same selector-domain constant. domain_16_value_2 -> PECKBOT_STATE_FACE_AWAY_FROM_TARGET: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0814-002f0834 close-target waiting selects face-away behavior and raises Z by one. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_FACE_AWAY_FROM_TARGET member. Reuse that same selector-domain constant. domain_17_value_11 -> PECKBOT_STATE_HOME_TRIGGERED_KNOCKBACK: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0990-002f09dc home-facing trigger initializes the home knockback arc and selects its update state. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_HOME_TRIGGERED_KNOCKBACK member. Reuse that same selector-domain constant. domain_18_value_3 -> PECKBOT_STATE_CHASE_TARGET: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f09ec-002f0a00 completed home-triggered knockback returns to chase. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_CHASE_TARGET member. Reuse that same selector-domain constant. domain_19_value_3 -> PECKBOT_STATE_CHASE_TARGET: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0bc0-002f0c28 face-away close-target response initializes turning and selects chase. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_CHASE_TARGET member. Reuse that same selector-domain constant. domain_1_value_99 -> PECKBOT_STATE_FATAL_KNOCKBACK: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002efdd4-002efddc comparison excludes the fatal knockback state before processing another hit. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_FATAL_KNOCKBACK member. Reuse that same selector-domain constant. domain_20_value_3 -> PECKBOT_STATE_CHASE_TARGET: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0ba4-002f0c28 face-away hit response shares the turning setup and chase assignment. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_CHASE_TARGET member. Reuse that same selector-domain constant. domain_21_value_16 -> PECKBOT_STATE_ASCEND: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0c88-002f0c9c face-away far-target response selects ascent. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_ASCEND member. Reuse that same selector-domain constant. domain_22_value_4 -> PECKBOT_STATE_ATTACK_TARGET: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0e80-002f0ea8 chase reaches target within 1.5 with movement bit 2 clear and selects attack. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_ATTACK_TARGET member. Reuse that same selector-domain constant. domain_23_value_12 -> PECKBOT_STATE_RECOVER_FROM_BLOCKED_MOVEMENT: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0eec-002f0f08 chase movement or height-ratio failure restores old XY and selects blocked-movement recovery. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_RECOVER_FROM_BLOCKED_MOVEMENT member. Reuse that same selector-domain constant. domain_24_value_5 -> PECKBOT_STATE_RETURN_HOME: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0fa0-002f0fb0 chase loses the home-relative target range gate and selects return home. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_RETURN_HOME member. Reuse that same selector-domain constant. domain_25_value_16 -> PECKBOT_STATE_ASCEND: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0fc8-002f0ff8 chase ground-probe outcome selects ascent. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_ASCEND member. Reuse that same selector-domain constant. domain_26_value_3 -> PECKBOT_STATE_CHASE_TARGET: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f11b8-002f11d4 attack animation completion with target beyond 1.5 selects chase. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_CHASE_TARGET member. Reuse that same selector-domain constant. domain_27_value_1 -> PECKBOT_STATE_GROUNDED_IDLE: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f135c-002f1378 return-home distance below two selects grounded idle. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_GROUNDED_IDLE member. Reuse that same selector-domain constant. domain_28_value_3 -> PECKBOT_STATE_CHASE_TARGET: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f13c8-002f1404 return-home close-target branch selects chase. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_CHASE_TARGET member. Reuse that same selector-domain constant. domain_29_value_3 -> PECKBOT_STATE_CHASE_TARGET: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f13e4-002f1404 return-home hit response shares the chase assignment. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_CHASE_TARGET member. Reuse that same selector-domain constant. domain_2_value_99 -> PECKBOT_STATE_FATAL_KNOCKBACK: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002eff28-002eff3c nonpositive remaining health starts fatal knockback and selects this state. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_FATAL_KNOCKBACK member. Reuse that same selector-domain constant. domain_30_value_12 -> PECKBOT_STATE_RECOVER_FROM_BLOCKED_MOVEMENT: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f1434-002f1450 return-home blocked movement restores old XY and selects recovery. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_RECOVER_FROM_BLOCKED_MOVEMENT member. Reuse that same selector-domain constant. domain_31_value_16 -> PECKBOT_STATE_ASCEND: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f1484-002f14b4 return-home ground-probe outcome selects ascent. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_ASCEND member. Reuse that same selector-domain constant. domain_32_value_3 -> PECKBOT_STATE_CHASE_TARGET: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f14dc-002f14f4 completed nonfatal knockback selects chase. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_CHASE_TARGET member. Reuse that same selector-domain constant. domain_33_value_14 -> PECKBOT_STATE_AIRBORNE_IDLE: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f155c-002f1570 delegated case-7 completion selects the already established airborne-idle branch. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_AIRBORNE_IDLE member. Reuse that same selector-domain constant. domain_34_value_4 -> PECKBOT_STATE_ATTACK_TARGET: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f1824-002f1850 recovery reaches close target with acceptable height ratio and selects attack. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_ATTACK_TARGET member. Reuse that same selector-domain constant. domain_35_value_5 -> PECKBOT_STATE_RETURN_HOME: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f1878-002f18a0 recovery height ratio at most one and movement bit 2 clear selects return home. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_RETURN_HOME member. Reuse that same selector-domain constant. domain_36_value_16 -> PECKBOT_STATE_ASCEND: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f18d8-002f18f4 recovery far-target branch selects ascent. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_ASCEND member. Reuse that same selector-domain constant. domain_37_value_16 -> PECKBOT_STATE_ASCEND: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f1974-002f19a4 recovery ground-probe outcome selects ascent. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_ASCEND member. Reuse that same selector-domain constant. domain_39_value_5 -> PECKBOT_STATE_RETURN_HOME: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f1bc8-002f1c08 forward movement with absent or distant leader selects return home. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_RETURN_HOME member. Reuse that same selector-domain constant. domain_3_value_6 -> PECKBOT_STATE_NONFATAL_KNOCKBACK: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002effa4-002effc0 positive remaining health starts nonfatal knockback and selects this state. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_NONFATAL_KNOCKBACK member. Reuse that same selector-domain constant. domain_4_value_1 -> PECKBOT_STATE_GROUNDED_IDLE: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0024-002f0034 ground-mode initialization selects the idle branch with animation 4. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_GROUNDED_IDLE member. Reuse that same selector-domain constant. domain_5_value_14 -> PECKBOT_STATE_AIRBORNE_IDLE: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0054-002f0074 air-mode initialization raises position Z by six and selects airborne idle. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_AIRBORNE_IDLE member. Reuse that same selector-domain constant. domain_6_value_17 -> PECKBOT_STATE_DESCEND: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f019c-002f01a4 airborne idle selects descent after close-target gates. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_DESCEND member. Reuse that same selector-domain constant. domain_7_value_17 -> PECKBOT_STATE_DESCEND: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0234-002f023c airborne idle selects descent after hit and timer gates and clears velocity. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_DESCEND member. Reuse that same selector-domain constant. domain_8_value_15 -> PECKBOT_STATE_MOVE_TO_DESTINATION: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f02c0-002f02d8 a random elevated home-relative destination is constructed before selecting destination movement. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_MOVE_TO_DESTINATION member. Reuse that same selector-domain constant. domain_9_value_14 -> PECKBOT_STATE_AIRBORNE_IDLE: Authoritative peckbot.c and original retail Ghidra agree: retail 0x002f0398-002f03a8 destination movement collision clears velocity and returns to airborne idle. This token reads or writes peckbot_moby->state at s2+0x20, the exact byte loaded by 0x002effdc for the switch already using the function-local PECKBOT_STATE_AIRBORNE_IDLE member. Reuse that same selector-domain constant. --- src/overlays/l01/mobys/peckbot.c | 76 ++++++++++++++++---------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/overlays/l01/mobys/peckbot.c b/src/overlays/l01/mobys/peckbot.c index 5098a92c08..7aac95d861 100644 --- a/src/overlays/l01/mobys/peckbot.c +++ b/src/overlays/l01/mobys/peckbot.c @@ -282,7 +282,7 @@ void peckbot_update(Mob577 *peckbot_moby) { hit_reaction(peckbot_moby, hit, &peckbot_vars->health, 0, &hitA0, &hitA4, 0, 4); fast_dec_timer_s16(&peckbot_vars->flee_timer); if (peckbot_vars->flee_timer < scale_game_frames(0x2D) && hit != NULL && - peckbot_moby->state != 0x63) { + peckbot_moby->state != PECKBOT_STATE_FATAL_KNOCKBACK) { if ((hit->cls->oclass == 0xB0 || hit->cls->oclass == 0xB1) && peckbot_vars->flee_timer != 0) { hit->dmg = 0.0f; @@ -310,7 +310,7 @@ void peckbot_update(Mob577 *peckbot_moby) { trooper_start_knockback(peckbot_moby, peckbot_vars->knock, 7, 1, 0, angle); peckbot_vars->x170 = 11.0f; peckbot_vars->x174 = 18.0f; - peckbot_moby->state = 0x63; + peckbot_moby->state = PECKBOT_STATE_FATAL_KNOCKBACK; peckbot_vars->x117 = 0x78; trooper_anim_update(peckbot_moby, peckbot_vars->fx110); FUN_L00_00257470(peckbot_moby, 0, -1); @@ -321,7 +321,7 @@ void peckbot_update(Mob577 *peckbot_moby) { trooper_start_knockback(peckbot_moby, peckbot_vars->knock, 6, 1, 0, angle); peckbot_vars->x170 = 5.0f; peckbot_vars->x174 = 10.0f; - peckbot_moby->state = 6; + peckbot_moby->state = PECKBOT_STATE_NONFATAL_KNOCKBACK; peckbot_vars->x117 = 0xFA; peckbot_vars->flee_timer = scale_game_frames(0x3C); trooper_anim_update(peckbot_moby, peckbot_vars->fx110); @@ -334,10 +334,10 @@ void peckbot_update(Mob577 *peckbot_moby) { qcopy(&peckbot_vars->home, &peckbot_moby->pos); peckbot_vars->x29 = 0; if (peckbot_vars->x20A != 0) { - peckbot_moby->state = 1; + peckbot_moby->state = PECKBOT_STATE_GROUNDED_IDLE; SET_ANIM(peckbot_moby, 4, 0, 0); } else { - peckbot_moby->state = 14; + peckbot_moby->state = PECKBOT_STATE_AIRBORNE_IDLE; peckbot_moby->pos.f[2] = peckbot_moby->pos.f[2] + 6.0f; SET_ANIM(peckbot_moby, 0, 0, 0); } @@ -363,7 +363,7 @@ void peckbot_update(Mob577 *peckbot_moby) { fast_vec_length(&vector_scratch) < peckbot_vars->range + 4.0f && absolute_float(peckbot_moby->pos.f[2] - target.pos.f[2]) < 8.0f && random_integer_below(0x13) == 0) { - peckbot_moby->state = 17; + peckbot_moby->state = PECKBOT_STATE_DESCEND; } else if (peckbot_vars->x228 == 0 && peckbot_moby->hit == 1 && random_integer_below(0x13) == 0) { if (random_integer_below(0x100) & 1) { @@ -371,7 +371,7 @@ void peckbot_update(Mob577 *peckbot_moby) { } peckbot_vars->turn_off = peckbot_vars->turn_deg * DEG_TO_RAD; peckbot_vars->turn_timer = scale_game_frames(random_float_between(30.0f, 90.0f)); - peckbot_moby->state = 17; + peckbot_moby->state = PECKBOT_STATE_DESCEND; clear_u64_value(&peckbot_vars->vel); peckbot_moby->hit = 0; } else if (fast_dec_timer(&peckbot_vars->idle_timer) != 0) { @@ -383,7 +383,7 @@ void peckbot_update(Mob577 *peckbot_moby) { position_scratch.f[2] = 0.0f; position_scratch.f[2] = random_float_between(5.0f, 7.0f); fast_vec_add(&peckbot_vars->dest, &position_scratch, &peckbot_vars->home); - peckbot_moby->state = 15; + peckbot_moby->state = PECKBOT_STATE_MOVE_TO_DESTINATION; } break; case PECKBOT_STATE_MOVE_TO_DESTINATION: @@ -395,12 +395,12 @@ void peckbot_update(Mob577 *peckbot_moby) { fast_vec_add(&vector_scratch, &peckbot_vars->vel, &peckbot_moby->pos); if (coll_sphere(&vector_scratch, 0, peckbot_moby, 0.4f) != 0) { clear_u64_value(&peckbot_vars->vel); - peckbot_moby->state = 14; + peckbot_moby->state = PECKBOT_STATE_AIRBORNE_IDLE; } else { qcopy(&peckbot_moby->pos, &vector_scratch); } if (fast_vec_length(&peckbot_vars->vel) == 0.0f) { - peckbot_moby->state = 14; + peckbot_moby->state = PECKBOT_STATE_AIRBORNE_IDLE; } break; case PECKBOT_STATE_DESCEND: @@ -418,7 +418,7 @@ void peckbot_update(Mob577 *peckbot_moby) { } peckbot_vars->turn_off = peckbot_vars->turn_deg * DEG_TO_RAD; peckbot_vars->turn_timer = scale_game_frames(random_float_between(30.0f, 90.0f)); - peckbot_moby->state = 3; + peckbot_moby->state = PECKBOT_STATE_CHASE_TARGET; clear_u64_value(&peckbot_vars->vel); SET_ANIM(peckbot_moby, 2, 0, scale_game_frames(3)); } @@ -429,7 +429,7 @@ void peckbot_update(Mob577 *peckbot_moby) { peckbot_moby->pos.f[2] += peckbot_vars->vel.f[2]; if (ascent_ground_height + 6.0f <= peckbot_moby->pos.f[2]) { peckbot_moby->pos.f[2] = ascent_ground_height + 6.0f; - peckbot_moby->state = 14; + peckbot_moby->state = PECKBOT_STATE_AIRBORNE_IDLE; peckbot_vars->x228 = scale_game_frames(0xB4); clear_u64_value(&peckbot_vars->vel); } @@ -439,7 +439,7 @@ void peckbot_update(Mob577 *peckbot_moby) { if (fast_vec_length(&vector_scratch) < peckbot_vars->range + 4.0f && absolute_float(peckbot_moby->pos.f[2] - target.pos.f[2]) < 8.0f && random_integer_below(0x13) == 0) { - peckbot_moby->state = 2; + peckbot_moby->state = PECKBOT_STATE_FACE_AWAY_FROM_TARGET; SET_ANIM(peckbot_moby, 5, 0, scale_game_frames(3)); } else if (peckbot_moby->hit == 1 && random_integer_below(0x13) == 0) { if (random_integer_below(0x100) & 1) { @@ -447,12 +447,12 @@ void peckbot_update(Mob577 *peckbot_moby) { } peckbot_vars->turn_off = peckbot_vars->turn_deg * DEG_TO_RAD; peckbot_vars->turn_timer = scale_game_frames(random_float_between(30.0f, 90.0f)); - peckbot_moby->state = 3; + peckbot_moby->state = PECKBOT_STATE_CHASE_TARGET; SET_ANIM(peckbot_moby, 2, 0, scale_game_frames(3)); peckbot_moby->hit = 0; } else if (fast_vec_length(&vector_scratch) > peckbot_vars->range + 6.0f && peckbot_vars->x20A == 0) { - peckbot_moby->state = 16; + peckbot_moby->state = PECKBOT_STATE_ASCEND; SET_ANIM(peckbot_moby, 0, 0, scale_game_frames(3)); } break; @@ -461,7 +461,7 @@ void peckbot_update(Mob577 *peckbot_moby) { if (fast_vec_length(&vector_scratch) < peckbot_vars->range - 4.0f && absolute_float(peckbot_moby->pos.f[2] - target.pos.f[2]) < 8.0f && random_integer_below(0x13) == 0) { - peckbot_moby->state = 2; + peckbot_moby->state = PECKBOT_STATE_FACE_AWAY_FROM_TARGET; peckbot_moby->pos.f[2] = peckbot_moby->pos.f[2] + 1.0f; SET_ANIM(peckbot_moby, 5, 0, scale_game_frames(3)); } @@ -492,12 +492,12 @@ void peckbot_update(Mob577 *peckbot_moby) { peckbot_moby, peckbot_vars->knock, 6, 1, 0, peckbot_moby->rot.f[2]); peckbot_vars->x170 = 5.0f; peckbot_vars->x174 = 10.0f; - peckbot_moby->state = 11; + peckbot_moby->state = PECKBOT_STATE_HOME_TRIGGERED_KNOCKBACK; } break; case PECKBOT_STATE_HOME_TRIGGERED_KNOCKBACK: if (step_moby_motion(peckbot_moby, peckbot_vars->knock) & 1) { - peckbot_moby->state = 3; + peckbot_moby->state = PECKBOT_STATE_CHASE_TARGET; if (random_integer_below(0x100) & 1) { peckbot_vars->turn_deg = -peckbot_vars->turn_deg; } @@ -527,7 +527,7 @@ void peckbot_update(Mob577 *peckbot_moby) { } peckbot_vars->turn_off = peckbot_vars->turn_deg * DEG_TO_RAD; peckbot_vars->turn_timer = scale_game_frames(random_float_between(30.0f, 90.0f)); - peckbot_moby->state = 3; + peckbot_moby->state = PECKBOT_STATE_CHASE_TARGET; SET_ANIM(peckbot_moby, 2, 0, scale_game_frames(3)); peckbot_moby->hit = 0; } else if (peckbot_moby->hit == 1 && random_integer_below(0x13) == 0) { @@ -536,12 +536,12 @@ void peckbot_update(Mob577 *peckbot_moby) { } peckbot_vars->turn_off = peckbot_vars->turn_deg * DEG_TO_RAD; peckbot_vars->turn_timer = scale_game_frames(random_float_between(30.0f, 90.0f)); - peckbot_moby->state = 3; + peckbot_moby->state = PECKBOT_STATE_CHASE_TARGET; SET_ANIM(peckbot_moby, 2, 0, scale_game_frames(3)); peckbot_moby->hit = 0; } else if (fast_vec_length(&vector_scratch) > peckbot_vars->range + 6.0f && peckbot_vars->x20A == 0) { - peckbot_moby->state = 16; + peckbot_moby->state = PECKBOT_STATE_ASCEND; SET_ANIM(peckbot_moby, 0, 0, scale_game_frames(3)); } if (peckbot_moby->anim == 5 && (peckbot_moby->anim_flags & 2)) { @@ -575,12 +575,12 @@ void peckbot_update(Mob577 *peckbot_moby) { fast_vec_sub(&home_to_target, &target.pos, &peckbot_vars->home); if (vector_distance_xy(&peckbot_moby->pos, &target.pos) < 1.5f && !(movement_result_flags & 2)) { - peckbot_moby->state = 4; + peckbot_moby->state = PECKBOT_STATE_ATTACK_TARGET; SET_ANIM(peckbot_moby, 3, 0, scale_game_frames(3)); } else if (chase_target_height_distance_ratio > 1.0f || (movement_result_flags & 2)) { peckbot_moby->pos.f[0] = oldpos.f[0]; peckbot_moby->pos.f[1] = oldpos.f[1]; - peckbot_moby->state = 12; + peckbot_moby->state = PECKBOT_STATE_RECOVER_FROM_BLOCKED_MOVEMENT; SET_ANIM(peckbot_moby, 5, 0, scale_game_frames(3)); } else if (fast_vec_length(&home_to_target) < peckbot_vars->range + 4.0f && absolute_float(peckbot_moby->pos.f[2] - target.pos.f[2]) < 8.0f) { @@ -588,11 +588,11 @@ void peckbot_update(Mob577 *peckbot_moby) { FUN_L01_0026e090(peckbot_moby->group, 1); } } else if (peckbot_moby->hit != 1) { - peckbot_moby->state = 5; + peckbot_moby->state = PECKBOT_STATE_RETURN_HOME; } FUN_00213508(&peckbot_moby->pos, 0, 0.5f); if (FUN_L00_001f35d8_cf() == 0 || FUN_L00_001f35d8_cf() == 8) { - peckbot_moby->state = 16; + peckbot_moby->state = PECKBOT_STATE_ASCEND; SET_ANIM(peckbot_moby, 0, 0, scale_game_frames(3)); } peckbot_moby->hit = 0; @@ -620,7 +620,7 @@ void peckbot_update(Mob577 *peckbot_moby) { } if ((peckbot_moby->anim_flags & 2) && vector_distance_xy(&peckbot_moby->pos, &target.pos) > 1.5f) { - peckbot_moby->state = 3; + peckbot_moby->state = PECKBOT_STATE_CHASE_TARGET; SET_ANIM(peckbot_moby, 2, 0, scale_game_frames(3)); } attack_ground_height = FUN_00213508(&peckbot_moby->pos, 0, 0.5f); @@ -649,7 +649,7 @@ void peckbot_update(Mob577 *peckbot_moby) { movement_result_flags = FUN_L00_00258b50( peckbot_moby, &peckbot_vars->x180, &vector_scratch, &position_scratch, 1.0f); if (vector_distance_xy(&peckbot_moby->pos, &peckbot_vars->home) < 2.0f) { - peckbot_moby->state = 1; + peckbot_moby->state = PECKBOT_STATE_GROUNDED_IDLE; SET_ANIM(peckbot_moby, 4, 0, scale_game_frames(3)); } fast_vec_sub(&home_to_target, &target.pos, &peckbot_vars->home); @@ -657,27 +657,27 @@ void peckbot_update(Mob577 *peckbot_moby) { if (peckbot_moby->group != 0xFF) { FUN_L01_0026e090(peckbot_moby->group, 1); } - peckbot_moby->state = 3; + peckbot_moby->state = PECKBOT_STATE_CHASE_TARGET; SET_ANIM(peckbot_moby, 2, 0, scale_game_frames(3)); } else if (peckbot_moby->hit == 1) { - peckbot_moby->state = 3; + peckbot_moby->state = PECKBOT_STATE_CHASE_TARGET; SET_ANIM(peckbot_moby, 2, 0, scale_game_frames(3)); } else if (movement_result_flags & 2) { peckbot_moby->pos.f[0] = oldpos.f[0]; peckbot_moby->pos.f[1] = oldpos.f[1]; - peckbot_moby->state = 12; + peckbot_moby->state = PECKBOT_STATE_RECOVER_FROM_BLOCKED_MOVEMENT; SET_ANIM(peckbot_moby, 5, 0, scale_game_frames(3)); } FUN_00213508(&peckbot_moby->pos, 0, 0.5f); if (FUN_L00_001f35d8_cf() == 0 || FUN_L00_001f35d8_cf() == 8) { - peckbot_moby->state = 16; + peckbot_moby->state = PECKBOT_STATE_ASCEND; SET_ANIM(peckbot_moby, 0, 0, scale_game_frames(3)); } peckbot_moby->hit = 0; break; case PECKBOT_STATE_NONFATAL_KNOCKBACK: if (step_moby_motion(peckbot_moby, peckbot_vars->knock) & 1) { - peckbot_moby->state = 3; + peckbot_moby->state = PECKBOT_STATE_CHASE_TARGET; SET_ANIM(peckbot_moby, 2, 0, scale_game_frames(3)); return; } else if (peckbot_moby->pos.f[2] < 5.0f) { @@ -688,7 +688,7 @@ void peckbot_update(Mob577 *peckbot_moby) { break; case 7: if (FUN_L00_002dc9f0(peckbot_moby, peckbot_vars->knock) != 0) { - peckbot_moby->state = 14; + peckbot_moby->state = PECKBOT_STATE_AIRBORNE_IDLE; peckbot_vars->x228 = scale_game_frames(0xB4); SET_ANIM(peckbot_moby, 0, 0, 0); peckbot_vars->xC8 = 0; @@ -793,15 +793,15 @@ void peckbot_update(Mob577 *peckbot_moby) { fast_vec_sub(&home_to_target, &target.pos, &peckbot_vars->home); if (vector_distance_xy(&peckbot_moby->pos, &target.pos) < 1.5f && recovery_target_height_distance_ratio <= 1.0f) { - peckbot_moby->state = 4; + peckbot_moby->state = PECKBOT_STATE_ATTACK_TARGET; SET_ANIM(peckbot_moby, 3, 0, scale_game_frames(3)); } else if (recovery_target_height_distance_ratio <= 1.0f && !(recovery_movement_result_flags & 2)) { - peckbot_moby->state = 5; + peckbot_moby->state = PECKBOT_STATE_RETURN_HOME; SET_ANIM(peckbot_moby, 2, 0, scale_game_frames(3)); } else if (vector_distance_xy(&peckbot_moby->pos, &target.pos) > peckbot_vars->range + 6.0f) { - peckbot_moby->state = 16; + peckbot_moby->state = PECKBOT_STATE_ASCEND; SET_ANIM(peckbot_moby, 0, 0, scale_game_frames(3)); } else if (peckbot_moby->anim_flags & 2) { random_integer_below(4); @@ -811,7 +811,7 @@ void peckbot_update(Mob577 *peckbot_moby) { } FUN_00213508(&peckbot_moby->pos, 0, 0.5f); if (FUN_L00_001f35d8_cf() == 0 || FUN_L00_001f35d8_cf() == 8) { - peckbot_moby->state = 16; + peckbot_moby->state = PECKBOT_STATE_ASCEND; SET_ANIM(peckbot_moby, 0, 0, scale_game_frames(3)); } peckbot_moby->hit = 0; @@ -859,7 +859,7 @@ void peckbot_update(Mob577 *peckbot_moby) { if (peckbot_vars->leader == NULL || vector_distance_xy(&peckbot_moby->pos, &peckbot_vars->leader->pos) > convert_integer_to_float(peckbot_vars->x216)) { - peckbot_moby->state = 5; + peckbot_moby->state = PECKBOT_STATE_RETURN_HOME; SET_ANIM(peckbot_moby, 2, 0, scale_game_frames(3)); } peckbot_moby->hit = 0; From a9a255eac7a4649f1fd9c0715706f3cd3ab6667c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:30:16 +0000 Subject: [PATCH 1309/1502] decomp: clarify names in gadgebot_update domain_0_value_1 -> GADGEBOT_WAIT_FOR_SPAWN_PAD: 0x002f00c4-0x002f00d0 excludes byte moby+0x20 value 1 before hit handling; the same byte selects the established spawn-wait case at 0x002f04bc-0x002f0660. domain_10_value_5 -> GADGEBOT_SEEK_AND_ATTACK_TARGET: 0x002f01cc-0x002f01e4 supplies 5 to the store at moby+0x20 and clears substate for attack command. The established state-5 branch seeks targets and applies strike hits. domain_11_value_4 -> GADGEBOT_STAND_AND_FACE_HERO: 0x002f0184 branches command 2 to 0x002f01e8-0x002f01f4, storing 4 in moby+0x20. The same selector's established state-4 handler idles and faces hero. domain_12_value_7 -> GADGEBOT_SEEK_INTERACTION_TARGET: 0x002f01b0-0x002f01f4 maps interaction command 4 to main-state 7 and clears substate. Same moby+0x20 selector as established interaction search/approach case. domain_13_value_1 -> GADGEBOT_WAIT_FOR_SPAWN_PAD: 0x002f0220-0x002f0228 reads moby+0x20 and compares 1 to choose manipulator scale target. It is exactly the byte used by main-state dispatch and the existing spawn-wait case. domain_14_value_1 -> GADGEBOT_WAIT_FOR_SPAWN_PAD: 0x002f04ac-0x002f04b0 stores 1 at moby+0x20 after initialization spawns the pad/container and initializes paths. The next update enters established spawn-wait case at 0x002f04bc. domain_15_value_3 -> GADGEBOT_FOLLOW_HERO: 0x002f0594-0x002f05ac stores 3 at moby+0x20 after the spawn container is absent/released; that same byte dispatches established follow-hero movement at 0x002f06c8. domain_16_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source selector is hero.vehicle_mode, distinct from hero state and gadgebot state. Retail 0x002f05b8-0x002f05c0 reads byte 0x001413f4 and branches on zero to the on-foot visibility handling. Supplied include/rnc/hero/hero_state.h HeroVehicleMode declares canonical HERO_VEHICLE_MODE_ON_FOOT=0 for precisely this vehicle-mode selector. domain_18_value_4 -> GADGEBOT_STAND_AND_FACE_HERO: 0x002f07c0 defines s1=4; 0x002f07f0 branches to 0x002f06b8-0x002f06c4 which stores s1 at this gadgebot's moby+0x20 and restores position. This destination selector has the established stand/face-hero case. domain_19_value_4 -> GADGEBOT_STAND_AND_FACE_HERO: 0x002f0820-0x002f0828 compares this gadgebot's moby+0x20 against 4 to skip follow movement after the clip-volume check. It is the same main-state selector as existing stand/face-hero case. domain_1_value_2 -> GADGEBOT_WANDER_NEAR_HOME: 0x002f0128-0x002f012c compares moby+0x20 with 2 for command eligibility. This is the same selector as the established wander case, which calls wander movement at 0x002f0664-0x002f06ac. domain_20_value_4 -> GADGEBOT_STAND_AND_FACE_HERO: 0x002f0cbc-0x002f0cd0 tests movement flag 0x20, writes 4 to moby+0x20 and restores saved position. Same main-state byte as established idle-and-face-hero state. domain_21_value_4 -> GADGEBOT_STAND_AND_FACE_HERO: 0x002f12a0-0x002f12b4 tests attack-approach movement flag 0x20, writes 4 to moby+0x20 and restores entry position. Existing state-4 case on this exact selector stands and faces hero. domain_22_value_3 -> GADGEBOT_FOLLOW_HERO: 0x002f0ff8 sets s0=3; 0x002f1574-0x002f159c reaches empty-target timeout and stores s0 at moby+0x20 while clearing substate. This returns to the established follow-hero main-state handler. domain_23_value_4 -> GADGEBOT_STAND_AND_FACE_HERO: 0x002f16fc-0x002f1714 tests interaction-approach movement flag 0x20, stores 4 to moby+0x20 and restores position. The same byte selects established stand-and-face-hero behavior. domain_24_value_3 -> GADGEBOT_FOLLOW_HERO: 0x002f1718-0x002f1728 handles completed interaction search without target, clears moby+0xBC and writes 3 to moby+0x20. That selector's existing state-3 case follows hero. domain_25_value_4 -> GADGEBOT_STAND_AND_FACE_HERO: 0x002f18f0-0x002f193c finishes knockback on motion collision, restores home position and writes 4 to moby+0x20. Existing main-state 4 stands and faces hero. domain_26_value_7 -> GADGEBOT_SEEK_INTERACTION_TARGET: 0x002f1b18-0x002f1b28 loads main-state byte moby+0x20 and computes state!=7 as interaction-helper argument. State 7 is the same established interaction-target search/approach branch. domain_27_value_1 -> GADGEBOT_WAIT_FOR_SPAWN_PAD: 0x002f1b38-0x002f1b40 compares moby+0x20 against 1 to skip common movement/gravity processing. This exact selector's existing state-1 branch waits for spawn container release. domain_28_value_9 -> GADGEBOT_UPDATE_KNOCKBACK: 0x002f1cf8-0x002f1d04 compares main-state byte moby+0x20 with 9 to bypass ordinary ground integration. Existing state-9 handler at 0x002f18f0 uses step_moby_motion with knockback storage. domain_29_value_4 -> GADGEBOT_STAND_AND_FACE_HERO: 0x002f1fbc-0x002f1fcc restores home position and writes 4 to moby+0x20 after out-of-bounds/fall checks. Same selector as established idle animation and face-hero main-state case. domain_2_value_5 -> GADGEBOT_SEEK_AND_ATTACK_TARGET: 0x002f0134-0x002f0138 compares moby+0x20 with 5 for command eligibility; the same main-state byte dispatches the established target seek/attack handler at 0x002f0ef8-0x002f15c4. domain_3_value_3 -> GADGEBOT_FOLLOW_HERO: 0x002f013c-0x002f0140 compares moby+0x20 with 3. This same main-state selector dispatches the established follow handler at 0x002f06c8, which routes movement toward hero position. domain_5_value_7 -> GADGEBOT_SEEK_INTERACTION_TARGET: 0x002f014c-0x002f0150 compares moby+0x20 with 7 for command eligibility; the established state-7 handler at 0x002f15c8 searches for and approaches an interaction target. domain_6_value_4 -> GADGEBOT_STAND_AND_FACE_HERO: 0x002f0154-0x002f0158 compares moby+0x20 with 4; the established state-4 branch at 0x002f0e54-0x002f0eec selects idle animation and turns toward hero. domain_7_value_3 -> GADGEBOT_FOLLOW_HERO: 0x002f0198-0x002f01e4 handles the follow command: reads moby+0x20, compares with 3 and writes 3 while clearing substate only when different. Same selector as existing follow case. domain_8_value_3 -> GADGEBOT_FOLLOW_HERO: 0x002f01c4-0x002f01e4 loads 3 for follow command and stores it to moby+0x20, clearing moby+0xBC. Source main-state case GADGEBOT_FOLLOW_HERO uses that same byte. domain_9_value_5 -> GADGEBOT_SEEK_AND_ATTACK_TARGET: 0x002f01cc-0x002f01d4 reads moby+0x20 and compares against 5 for the attack command, before shared store/reset. Same selector as established seek/attack main state. --- src/overlays/shared/enemies/gadgebot.c | 50 +++++++++++++------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/overlays/shared/enemies/gadgebot.c b/src/overlays/shared/enemies/gadgebot.c index 70d5879864..5d8fc43843 100644 --- a/src/overlays/shared/enemies/gadgebot.c +++ b/src/overlays/shared/enemies/gadgebot.c @@ -352,35 +352,35 @@ void gadgebot_update(GbMoby *moby) { hero_distance = vector_distance_xy(moby->pos, hero.motion.pos.f); dz = absolute_float(moby->pos[2] - hero.ground_point.f[2]); *(OvlQuad *)save1 = *(OvlQuad *)save0 = *(OvlQuad *)moby->pos; - if (moby->state != 1) { + if (moby->state != GADGEBOT_WAIT_FOR_SPAWN_PAD) { FUN_L06_002f3640_u(moby); if (hero_distance < 16.0f && absolute_float(moby->pos[2] - hero.motion.pos.f[2]) < 1.5f) { int ok = 0; - if (moby->state == 2 || moby->state == 5 || moby->state == 3 || moby->state == 6 || - moby->state == 7 || moby->state == 4) { + if (moby->state == GADGEBOT_WANDER_NEAR_HOME || moby->state == GADGEBOT_SEEK_AND_ATTACK_TARGET || moby->state == GADGEBOT_FOLLOW_HERO || moby->state == 6 || + moby->state == GADGEBOT_SEEK_INTERACTION_TARGET || moby->state == GADGEBOT_STAND_AND_FACE_HERO) { ok = 1; } if (ok) { l06_gadgebot_command_range_stats.unk2C++; switch (D_00141610[0]) { case GADGEBOT_COMMAND_FOLLOW_HERO: - if (moby->state != 3) { - moby->state = 3; + if (moby->state != GADGEBOT_FOLLOW_HERO) { + moby->state = GADGEBOT_FOLLOW_HERO; moby->sub = 0; } break; case GADGEBOT_COMMAND_SEEK_AND_ATTACK_TARGET: - if (moby->state != 5) { - moby->state = 5; + if (moby->state != GADGEBOT_SEEK_AND_ATTACK_TARGET) { + moby->state = GADGEBOT_SEEK_AND_ATTACK_TARGET; moby->sub = 0; } break; case GADGEBOT_COMMAND_STAND_AND_FACE_HERO: - moby->state = 4; + moby->state = GADGEBOT_STAND_AND_FACE_HERO; break; case GADGEBOT_COMMAND_SEEK_INTERACTION_TARGET: moby->sub = 0; - moby->state = 7; + moby->state = GADGEBOT_SEEK_INTERACTION_TARGET; break; } } @@ -390,7 +390,7 @@ void gadgebot_update(GbMoby *moby) { if (gadgebot_vars->unk101 == 0) { attach_manipulator((char *)moby, 0, &gadgebot_vars->unk100); } - if (moby->state != 1) { + if (moby->state != GADGEBOT_WAIT_FOR_SPAWN_PAD) { approach_value(&gadgebot_vars->unk308, 2.3f, frame_scale * 0.1f); } else { approach_value(&gadgebot_vars->unk308, 1.0f, frame_scale * 0.1f); @@ -440,7 +440,7 @@ void gadgebot_update(GbMoby *moby) { } gadgebot_vars->unk28C = random_angle_radians(); gadgebot_vars->unk27C = -1; - moby->state = 1; + moby->state = GADGEBOT_WAIT_FOR_SPAWN_PAD; moby->unk94 = 0; break; } @@ -473,9 +473,9 @@ void gadgebot_update(GbMoby *moby) { } moby->flags = (moby->flags & 0xFFBE) | 0x1000; moby->unk94 = moby->cls->unk10; - moby->state = 3; + moby->state = GADGEBOT_FOLLOW_HERO; } else { - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { moby->flags |= 0x41; gadgebot_vars->unk170->flags |= 0x41; moby->flags &= 0xEFFF; @@ -543,12 +543,12 @@ void gadgebot_update(GbMoby *moby) { if (referenced_moby->cls_id == 0x3F7 && referenced_moby->state != 4 && is_point_inside_clip_volume(((GbMoby *)hero.moby)->pos, *tb) != 0 && is_point_inside_clip_volume(moby->pos, *tb) == 0) { - moby->state = 4; + moby->state = GADGEBOT_STAND_AND_FACE_HERO; *(OvlQuad *)moby->pos = *(OvlQuad *)vector_and_hit_scratch; break; } } - if (moby->state != 4) { + if (moby->state != GADGEBOT_STAND_AND_FACE_HERO) { switch (moby->sub) { case GADGEBOT_FOLLOW_INITIALIZE: moby->sub = 1; @@ -645,7 +645,7 @@ void gadgebot_update(GbMoby *moby) { } } if (flags & 0x20) { - moby->state = 4; + moby->state = GADGEBOT_STAND_AND_FACE_HERO; *(OvlQuad *)moby->pos = *(OvlQuad *)temporary_position; } if (hero_distance < 0.8f || hit != 0 || dz > 1.75f) { @@ -786,7 +786,7 @@ void gadgebot_update(GbMoby *moby) { movement_displacement_output, 1.0f) & 0x20) { - moby->state = 4; + moby->state = GADGEBOT_STAND_AND_FACE_HERO; *(OvlQuad *)moby->pos = *(OvlQuad *)save0; } if (vector_distance_xy(moby->pos, gadgebot_vars->target->pos) < 1.5f) { @@ -856,7 +856,7 @@ void gadgebot_update(GbMoby *moby) { } if (fast_dec_timer(&gadgebot_vars->unk194) != 0 && gadgebot_vars->target_searched != 0 && gadgebot_vars->target == 0) { - moby->state = 3; + moby->state = GADGEBOT_FOLLOW_HERO; moby->sub = 0; } else if (gadgebot_vars->target_searched != 0 && gadgebot_vars->target == 0) { gadgebot_vars->target_searched = 0; @@ -899,12 +899,12 @@ void gadgebot_update(GbMoby *moby) { movement_displacement_output, 1.0f) & 0x20) { - moby->state = 4; + moby->state = GADGEBOT_STAND_AND_FACE_HERO; *(OvlQuad *)moby->pos = *(OvlQuad *)save0; } } else if (gadgebot_vars->target_searched != 0) { moby->sub = 0; - moby->state = 3; + moby->state = GADGEBOT_FOLLOW_HERO; } break; case 2: @@ -957,7 +957,7 @@ void gadgebot_update(GbMoby *moby) { cart_burst(moby, moby->pos, -1, 0.5f, 13.0f); qcopy(moby->pos, gadgebot_vars->unkE0); - moby->state = 4; + moby->state = GADGEBOT_STAND_AND_FACE_HERO; for (i = 0; i < 10; i++) { float effect_scale_factor = random_float_between(0.1f, 1.0f); int cr = random_int_between(0x40, 0xFF); @@ -998,11 +998,11 @@ void gadgebot_update(GbMoby *moby) { } break; } - interaction_result = FUN_L06_002f32f0_u(moby, moby->state != 7); + interaction_result = FUN_L06_002f32f0_u(moby, moby->state != GADGEBOT_SEEK_INTERACTION_TARGET); if (interaction_result == 2) { return; } - if (moby->state != 1) { + if (moby->state != GADGEBOT_WAIT_FOR_SPAWN_PAD) { float saved_control_f10; float saved_control_f24; @@ -1049,7 +1049,7 @@ void gadgebot_update(GbMoby *moby) { gadgebot_vars->unk284 = 0.0f; qcopy(moby->pos, vector_and_hit_scratch); } - if (moby->state != 9) { + if (moby->state != GADGEBOT_UPDATE_KNOCKBACK) { float ground_height; if (interaction_result == 0) { @@ -1108,7 +1108,7 @@ void gadgebot_update(GbMoby *moby) { moby->pos[0] > 1021.0f || moby->pos[1] < 2.0f || moby->pos[1] > 1021.0f || moby->pos[2] < 2.0f || moby->pos[2] > 1021.0f) { qcopy(moby->pos, gadgebot_vars->unkE0); - moby->state = 4; + moby->state = GADGEBOT_STAND_AND_FACE_HERO; return; } } From 8185d68368d43a6d431fcc412bdd28e630620491 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:32:31 +0000 Subject: [PATCH 1310/1502] decomp: clarify names in toxic_crab_update domain_0_value_253 -> MOBY_STATE_ALTERNATE_REMOVAL_MARKER: Initialization resolves linked moby p from the instance array plus index<<8 (0x002e2058-0x002e2064), reads p+0x20 and compares 0xFD at 0x002e2078-0x002e207c, invalidating the link. Checked established mark_moby_for_removal helper 0x002415e0 compares its moby address against [0x0015FFDC] at 0x002415e4-0x002415f4, selects 0xFD at 0x00241600 or 0xFE at 0x00241604, then stores either at moby+0x20 (0x00241608) and schedules frame counter+2 at +0x38. Thus 0xFD is the alternate removal marker in this same moby-state field, not a crab behavior state. domain_1_value_253 -> MOBY_STATE_ALTERNATE_REMOVAL_MARKER: WAIT_FOR_ACTIVATION resolves linked moby p from array base plus data+0x1BC shifted by 8 at 0x002e2160-0x002e2174, reads p+0x20 at 0x002e2180, and compares 0xFD at 0x002e2188-0x002e218c to enter activation. Checked mark_moby_for_removal 0x002415e0 selects 0xFD for moby addresses below [0x0015FFDC] (0x002415e4-0x00241600), otherwise 0xFE, storing the selected removal marker at moby+0x20 at 0x00241608 with frame counter+2 at +0x38. This proves the same alternate removal-marker role as the initialization comparison. --- src/overlays/l10/mobys/toxic_crab.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/toxic_crab.c b/src/overlays/l10/mobys/toxic_crab.c index 2f3f34d1a9..11f42adcd6 100644 --- a/src/overlays/l10/mobys/toxic_crab.c +++ b/src/overlays/l10/mobys/toxic_crab.c @@ -236,6 +236,9 @@ void toxic_crab_update(Moby2E30F8 *m) { enum { MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE }; + enum { + MOBY_STATE_ALTERNATE_REMOVAL_MARKER = 0xFD + }; int see = 0; Crab2E30F8 *crab_data = m->data; char *target_moby; @@ -296,7 +299,7 @@ void toxic_crab_update(Moby2E30F8 *m) { int k = crab_data->i1BC; if (k != -1) { Moby2E30F8 *p = (Moby2E30F8 *)((char *)D_L10_0015FFD0_macro[2] + (k << 8)); - if (p == 0 || p->state == MOBY_STATE_MARKED_FOR_REMOVAL || p->state == 0xFD || + if (p == 0 || p->state == MOBY_STATE_MARKED_FOR_REMOVAL || p->state == MOBY_STATE_ALTERNATE_REMOVAL_MARKER || (((*(int *)(((char *)&D_0014C190) + (((short)p->id >> 5) * 4 + (current_level_index << 8))) >> (p->id & 0x1F)) & @@ -318,7 +321,7 @@ void toxic_crab_update(Moby2E30F8 *m) { if (crab_data->i1BC != -1) { char *moby_instance_array_base = D_L10_0015FFD8; Moby2E30F8 *p = (Moby2E30F8 *)(moby_instance_array_base + (crab_data->i1BC << 8)); - if (p == 0 || p->state == MOBY_STATE_MARKED_FOR_REMOVAL || p->state == 0xFD || + if (p == 0 || p->state == MOBY_STATE_MARKED_FOR_REMOVAL || p->state == MOBY_STATE_ALTERNATE_REMOVAL_MARKER || ((*(int *)(((char *)&D_0014C190) + (((short)p->id >> 5) * 4 + (current_level_index << 8))) >> (p->id & 0x1F)) & From 116fc751fdf206a4d9499e6b7053a8c5e7af876d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:32:31 +0000 Subject: [PATCH 1311/1502] decomp: clarify names in hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022b784..0x0022b798 permits requested state 100 during dying control mode only with b=2; reuse the canonical member for that requested-state domain. domain_10_value_124 -> HERO_STATE_DEATH_DESCENT: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022b820..0x0022b824 compares requested state 124 in the zero-health exception list; reuse canonical HeroStateId death-descent member without asserting an independent lifecycle. domain_11_value_127 -> HERO_STATE_SINK: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022b828..0x0022b82c permits state 127; source named sink/Ghidra case 0x7f initialize water-relative descent and zero health at 0x0022bb7c..0x0022bc18. domain_12_value_106 -> HERO_STATE_DROWN: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022b830..0x0022b834 compares requested state 106 in the zero-health exception list; canonical HeroStateId names it DROWN, and supplied per-frame source groups it with animation-completion respawn states. domain_13_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022b838..0x0022b83c permits state 128; source named state/Ghidra case 0x80 zero health and limit momentum to frame_time*3.5 at 0x0022bb1c..0x0022bb78. domain_14_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022b840..0x0022b844 compares requested state 130 in the zero-health exception list; reuse canonical HeroStateId member; supplied per-frame source groups it with dying states that respawn on animation completion. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source selector is hero.vehicle_mode, distinct from hero.state.current. Retail lbu at hero+0x20A4 matches original Ghidra cRam001413f4, proving the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. 0x0022b868..0x0022b8b8 tests zero before clearing moby collision-disable, item locks and transform history. domain_17_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source selector is hero.vehicle_mode, distinct from hero.state.current. Retail lbu at hero+0x20A4 matches original Ghidra cRam001413f4, proving the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. 0x0022b974..0x0022b988 tests nonzero and calls request_hero_idle_state_for_vehicle_mode; zero takes the on-foot idle setup. domain_18_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source selector is hero.vehicle_mode, distinct from hero.state.current. Retail lbu at hero+0x20A4 matches original Ghidra cRam001413f4, proving the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. 0x0022bfd4..0x0022bfe8 tests zero before cancel_hero_item_animation in APPROACH_TARGET_POSE. domain_20_value_1 -> HERO_VEHICLE_MODE_CLANK: Source selector is hero.vehicle_mode, distinct from hero.state.current. Retail lbu at hero+0x20A4 matches original Ghidra cRam001413f4, proving the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. 0x0022bff4 loads vehicle_mode and 0x0022c01c compares it with s1=1, choosing animation 2 at 0x0022c024..0x0022c03c. Reuse canonical CLANK member for this exact field. domain_21_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source selector is hero.vehicle_mode, distinct from hero.state.current. Retail lbu at hero+0x20A4 matches original Ghidra cRam001413f4, proving the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. 0x0022bff4..0x0022c074 selects separate animations for vehicle modes 3 and 1; zero uses state.step+3 and the normal locomotion frame table. domain_22_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source selector is hero.vehicle_mode, distinct from hero.state.current. Retail lbu at hero+0x20A4 matches original Ghidra cRam001413f4, proving the shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. 0x0022c9e0..0x0022c9f8 tests zero before allocating fatal-fall voice; source p->vehicle_mode and Ghidra cRam001413f4 identify the exact selector. domain_24_value_41 -> HERO_STATE_GRIND_JUMP: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022cc10..0x0022cc30 tests requested_state-41 unsigned <2 and assigns jump flags 3, otherwise 0x50. Source groups canonical GRIND_JUMP and GRIND_RAIL_TRANSFER in this shared jump entry; this is the lower endpoint. domain_25_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022cc10..0x0022cc30 tests requested_state-41 unsigned <2 and assigns jump flags 3, otherwise 0x50. Source groups canonical GRIND_JUMP and GRIND_RAIL_TRANSFER in this shared jump entry; this is the upper endpoint. domain_3_value_6 -> HERO_STATE_FALL: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022b7e8..0x0022b7ec permits state 6 through the zero-health guard; source case HERO_STATE_FALL and Ghidra case 6 share falling setup at 0x0022c99c. domain_4_value_61 -> HERO_STATE_DYING: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022b7f0..0x0022b7f4 permits state 61 through the zero-health guard; source dying case and retail 0x0022bad8..0x0022bb18 initialize dying control mode and animation. domain_5_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022b7f8..0x0022b7fc compares requested state 71 in the zero-health exception list; reuse canonical HeroStateId member, distinct from the separate vehicle-mode field. domain_6_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022b800..0x0022b804 permits state 87; source and Ghidra case 0x57 set dying control mode and animation 3 at 0x0022e5a4..0x0022e5e4. domain_7_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022b808..0x0022b80c compares requested state 98 in the zero-health exception list; canonical shared HeroStateId supplies the vehicle-mode-2 dying name. domain_8_value_119 -> HERO_STATE_FATAL_FALL: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022b810..0x0022b814 permits state 119; source fatal-fall case and Ghidra case 0x77 share falling setup and add tumble targets at 0x0022c99c..0x0022ca60. domain_9_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: Retail 0x0022b748 saves requested_state in s1 and 0x0022b888 stores it to hero.state.current (+0x2084), proving the shared HeroStateId domain in include/rnc/hero/hero_state.h; original Ghidra stores param_1 to iRam001413d4 and dispatches it. 0x0022b818..0x0022b81c permits state 123; source named state/Ghidra case 0x7b initialize respawn wait at 0x0022e3b8..0x0022e418; supplied per-frame branch respawns on height or timeout. --- src/overlays/l02/hero/hero_set_state.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l02/hero/hero_set_state.c b/src/overlays/l02/hero/hero_set_state.c index 6617006d06..f3187f7955 100644 --- a/src/overlays/l02/hero/hero_set_state.c +++ b/src/overlays/l02/hero/hero_set_state.c @@ -75,7 +75,7 @@ int hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((level_game_mode == 2 || level_game_mode == 6) && b != 2) @@ -83,8 +83,8 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -101,7 +101,7 @@ int hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -129,7 +129,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); return 1; } @@ -339,14 +339,14 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation( p->state.step + 3, D_L02_0015F6D8[p->state.step], (float)scale_game_frames(8)); } @@ -620,7 +620,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -705,7 +705,7 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 252452481105af4ce2e62ba6840f072310597a2d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:32:32 +0000 Subject: [PATCH 1312/1502] decomp: clarify names in l01_hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023cff4-0x0023d008 compares requested state 100 and second argument 2 in death control mode; shared cases 99/100 at 0x0024041c-0x00240454 cancel item animation and optionally play idle. domain_10_value_124 -> HERO_STATE_DEATH_DESCENT: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023d090-0x0023d094 compares requested s1 with 0x7C in the health-zero whitelist. This operand flows directly into hero.state.current; reuse canonical shared HeroStateId member 124 without asserting a lifecycle beyond the supplied canonical identity. domain_11_value_127 -> HERO_STATE_SINK: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023d098-0x0023d09c admits 127; entry 0x0023d3ec-0x0023d488 clears health and initializes descent relative to water_surface_z-0.37. domain_12_value_106 -> HERO_STATE_DROWN: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023d0a0-0x0023d0a4 admits 106; entry 0x0023da68-0x0023dc0c sets death mode, zero health, water-related usage statistics and animation 0x5F. domain_13_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023d0a8-0x0023d0ac admits 128; entry 0x0023d38c-0x0023d3e8 sets death mode, clears health and limits copied momentum using frame_time*3.5. domain_14_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023d0b0-0x0023d0b4 admits 130; entry 0x0023dc10-0x0023dc5c sets death mode, explicitly zeroes health and selects animation 0x80. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Shared HeroVehicleMode is proven by the byte hero+0x20A4: assigned retail reads it as vehicle_mode, independently of current state at +0x2084 and control mode at +0x208C. Supplied enter_hero_vehicle_mode_and_set_moby stores its vehicle_mode argument to +0x20A4 and tests that same byte against HERO_VEHICLE_MODE_CLANK; authoritative source includes include/rnc/hero/hero_state.h. Original Ghidra uses cRam001413f4 for these same comparisons. 0x0023d0d8 loads the mode and 0x0023d104 branches on nonzero, leaving the zero-mode path to clear collision-disable, item flags and trail history at 0x0023d10c-0x0023d128. domain_17_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Shared HeroVehicleMode is proven by the byte hero+0x20A4: assigned retail reads it as vehicle_mode, independently of current state at +0x2084 and control mode at +0x208C. Supplied enter_hero_vehicle_mode_and_set_moby stores its vehicle_mode argument to +0x20A4 and tests that same byte against HERO_VEHICLE_MODE_CLANK; authoritative source includes include/rnc/hero/hero_state.h. Original Ghidra uses cRam001413f4 for these same comparisons. Idle entry 0x0023d1e4-0x0023d1f4 reads +0x20A4 and delegates nonzero modes to request_hero_idle_state_for_vehicle_mode; zero continues ordinary idle motion setup. domain_18_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Shared HeroVehicleMode is proven by the byte hero+0x20A4: assigned retail reads it as vehicle_mode, independently of current state at +0x2084 and control mode at +0x208C. Supplied enter_hero_vehicle_mode_and_set_moby stores its vehicle_mode argument to +0x20A4 and tests that same byte against HERO_VEHICLE_MODE_CLANK; authoritative source includes include/rnc/hero/hero_state.h. Original Ghidra uses cRam001413f4 for these same comparisons. 0x0023dfc0-0x0023dfd4 reads +0x20A4 and calls cancel_hero_item_animation only for zero mode in APPROACH_TARGET_POSE. domain_20_value_1 -> HERO_VEHICLE_MODE_CLANK: Shared HeroVehicleMode is proven by the byte hero+0x20A4: assigned retail reads it as vehicle_mode, independently of current state at +0x2084 and control mode at +0x208C. Supplied enter_hero_vehicle_mode_and_set_moby stores its vehicle_mode argument to +0x20A4 and tests that same byte against HERO_VEHICLE_MODE_CLANK; authoritative source includes include/rnc/hero/hero_state.h. Original Ghidra uses cRam001413f4 for these same comparisons. 0x0023dfe0 loads +0x20A4; after excluding mode 3, 0x0023e008 compares against s1=1 and 0x0023e010-0x0023e028 selects animation 2. The supplied vehicle-entry caller explicitly compares this identical stored vehicle_mode with canonical CLANK=1. domain_21_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Shared HeroVehicleMode is proven by the byte hero+0x20A4: assigned retail reads it as vehicle_mode, independently of current state at +0x2084 and control mode at +0x208C. Supplied enter_hero_vehicle_mode_and_set_moby stores its vehicle_mode argument to +0x20A4 and tests that same byte against HERO_VEHICLE_MODE_CLANK; authoritative source includes include/rnc/hero/hero_state.h. Original Ghidra uses cRam001413f4 for these same comparisons. 0x0023e02c tests the +0x20A4 mode against zero after excluding 3 and 1; zero selects the ordinary step-indexed ground animation at 0x0023e034-0x0023e060. domain_22_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Shared HeroVehicleMode is proven by the byte hero+0x20A4: assigned retail reads it as vehicle_mode, independently of current state at +0x2084 and control mode at +0x208C. Supplied enter_hero_vehicle_mode_and_set_moby stores its vehicle_mode argument to +0x20A4 and tests that same byte against HERO_VEHICLE_MODE_CLANK; authoritative source includes include/rnc/hero/hero_state.h. Original Ghidra uses cRam001413f4 for these same comparisons. Fatal-fall entry 0x0023e5e0-0x0023e5f8 reads +0x20A4 and allocates the fatal-fall voice only for zero mode. Reuse canonical ON_FOOT=0 for the proven vehicle selector. domain_24_value_41 -> HERO_STATE_GRIND_JUMP: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023e810 subtracts 0x29 from requested s1 and 0x0023e818 bounds the result below 2; 0x0023e824-0x0023e830 assigns mask 3 for the two canonical grind jump/transfer states in common jump entry. Authoritative >=0x29 lower bound is canonical GRIND_JUMP. domain_25_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023e810-0x0023e830 range-tests requested s1 as 0x29..0x2A and assigns mask 3 in airborne mode 4. Authoritative <=0x2A upper bound is canonical GRIND_RAIL_TRANSFER in the same shared state domain. domain_3_value_6 -> HERO_STATE_FALL: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023d058-0x0023d05c admits requested 6 in the health-zero guard; case 6 shares fall entry with 119 at 0x0023e59c-0x0023e700, initializing airborne coefficients and velocity. domain_4_value_61 -> HERO_STATE_DYING: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023d060-0x0023d064 admits 61 in the health-zero guard; its entry at 0x0023d348-0x0023d388 sets death control mode 0x14 and animation 0x45. domain_5_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023d068-0x0023d06c compares requested s1 with 0x47 in the health-zero whitelist. This is the same requested-state selector as the shared HeroStateId member, rather than vehicle_mode itself; reuse canonical member 71. domain_6_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023d070-0x0023d074 admits 87 in the health-zero whitelist; its entry 0x00240044-0x00240084 sets death mode 0x14, copies resolved motion and selects animation 3. domain_7_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023d078-0x0023d07c compares requested s1 with 0x62 in the health-zero whitelist. The compared operand is requested_state, not vehicle_mode; canonical shared state member 98 therefore applies. domain_8_value_119 -> HERO_STATE_FATAL_FALL: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023d080-0x0023d084 admits 119 in the health-zero whitelist; fall entry 0x0023e59c-0x0023e640 initializes dedicated randomized tumble rotations when current==119. domain_9_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: The selector is shared HeroStateId from include/rnc/hero/hero_state.h: retail 0x0023cfb8 saves requested a0 in s1, 0x0023d0f8 stores s1 to hero.state.current (+0x2084), and 0x0023d188-0x0023d1a8 dispatches it. Supplied enter_hero_vehicle_mode_and_set_moby passes initial_state. Authoritative C and original retail Ghidra agree; reuse the canonical shared state member, not an equal-valued control, vehicle or item constant. 0x0023d088-0x0023d08c compares requested s1 with 0x7B in the health-zero whitelist. Supplied ground-material caller compares hero.state.current with 0x7B and requests l01_hero_set_state(0x7B,1), corroborating the same shared state domain; reuse canonical member 123. --- src/overlays/l01/hero/hero_set_state.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l01/hero/hero_set_state.c b/src/overlays/l01/hero/hero_set_state.c index 3fcd508b63..0732e4be72 100644 --- a/src/overlays/l01/hero/hero_set_state.c +++ b/src/overlays/l01/hero/hero_set_state.c @@ -74,7 +74,7 @@ int l01_hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((cutscene_mode == 2 || cutscene_mode == 6) && b != 2) @@ -82,8 +82,8 @@ int l01_hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -100,7 +100,7 @@ int l01_hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -128,7 +128,7 @@ int l01_hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); return 1; } @@ -552,14 +552,14 @@ int l01_hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation( p->state.step + 3, D_L01_0015F6D8[p->state.step], (float)scale_game_frames(8)); } @@ -727,7 +727,7 @@ int l01_hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -812,7 +812,7 @@ int l01_hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 26e408415d6b8d2308dcdbc37751e7ff6f32fab8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:34:47 +0000 Subject: [PATCH 1313/1502] decomp: clarify names in hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00230b94..0x00230ba4 compares requested s1 with 0x64 for the dying-mode override; original Ghidra compares param_1 with 100. Existing case HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE shares 0x00234a90..0x00234ac8 idle animation/item cancellation. domain_10_value_124 -> HERO_STATE_DEATH_DESCENT: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00230c30..0x00230c34 compares requested s1 with 0x7C in the zero-health exception list. The proven requested/current-state domain permits canonical HeroStateId reuse even though this entry handler provides no distinct setup. domain_11_value_127 -> HERO_STATE_SINK: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00230c38..0x00230c3c admits 0x7F; 0x00230f8c..0x00231028 clears health and sets descent toward water_surface_z minus 0.37, agreeing with the existing SINK case. domain_12_value_106 -> HERO_STATE_DROWN: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00230c40..0x00230c44 admits 0x6A; 0x00231608..0x002317ac clears health, selects dying mode and animation 0x5F in the existing DROWN case. domain_13_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00230c48..0x00230c4c admits 0x80; 0x00230f2c..0x00230f88 clears health and limits copied momentum with frame_time*3.5 in the named dying case. domain_14_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00230c50..0x00230c54 admits 0x82; 0x002317b0..0x002317fc clears health, sets dying mode and animation 0x80 in the named case. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Original Ghidra cRam001413f4 and authoritative C p->vehicle_mode identify the byte at hero+0x20A4 as the exact HeroVehicleMode selector, separate from state.current at +0x2084 and control_mode at +0x208C. Reuse include/rnc/hero/hero_state.h canonical HeroVehicleMode member. 0x00230c78 loads hero+0x20A4 and 0x00230ca4 gates normal collision, item and trail reset on zero. domain_17_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Original Ghidra cRam001413f4 and authoritative C p->vehicle_mode identify the byte at hero+0x20A4 as the exact HeroVehicleMode selector, separate from state.current at +0x2084 and control_mode at +0x208C. Reuse include/rnc/hero/hero_state.h canonical HeroVehicleMode member. 0x00230d84..0x00230d94 loads hero+0x20A4 and routes nonzero modes to request_hero_idle_state_for_vehicle_mode; zero continues normal idle. domain_18_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Original Ghidra cRam001413f4 and authoritative C p->vehicle_mode identify the byte at hero+0x20A4 as the exact HeroVehicleMode selector, separate from state.current at +0x2084 and control_mode at +0x208C. Reuse include/rnc/hero/hero_state.h canonical HeroVehicleMode member. 0x00231bec..0x00231c00 loads hero+0x20A4 and cancels item animation only when zero in APPROACH_TARGET_POSE. domain_20_value_1 -> HERO_VEHICLE_MODE_CLANK: Original Ghidra cRam001413f4 and authoritative C p->vehicle_mode identify the byte at hero+0x20A4 as the exact HeroVehicleMode selector, separate from state.current at +0x2084 and control_mode at +0x208C. Reuse include/rnc/hero/hero_state.h canonical HeroVehicleMode member. 0x00231c0c loads hero+0x20A4; 0x00231c34 compares it with saved s1=1 and 0x00231c3c..0x00231c54 selects animation 2 for this mode. domain_21_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Original Ghidra cRam001413f4 and authoritative C p->vehicle_mode identify the byte at hero+0x20A4 as the exact HeroVehicleMode selector, separate from state.current at +0x2084 and control_mode at +0x208C. Reuse include/rnc/hero/hero_state.h canonical HeroVehicleMode member. 0x00231c58 tests the hero+0x20A4 vehicle selector against zero before 0x00231c60..0x00231c8c chooses normal step-indexed locomotion animation. domain_22_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Original Ghidra cRam001413f4 and authoritative C p->vehicle_mode identify the byte at hero+0x20A4 as the exact HeroVehicleMode selector, separate from state.current at +0x2084 and control_mode at +0x208C. Reuse include/rnc/hero/hero_state.h canonical HeroVehicleMode member. 0x0023283c..0x00232854 loads hero+0x20A4 and allocates fatal-fall entry voice only for zero. domain_24_value_41 -> HERO_STATE_GRIND_JUMP: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00232a6c..0x00232a84 tests unsigned requested_state-0x29 < 2, corresponding to source lower bound 0x29; named GRIND_JUMP setup 0x00232dbc..0x00232e5c retains grind mode 0xF. domain_25_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00232a6c..0x00232a84 tests unsigned requested_state-0x29 < 2, corresponding to source upper bound 0x2A; named rail-transfer setup 0x00232f24..0x00232fb4 and facing selection 0x002338b0..0x0023391c agree. domain_3_value_6 -> HERO_STATE_FALL: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00230bf8..0x00230bfc admits requested 6 despite zero health; entry 0x002327f8..0x0023295c initializes fall gravity and velocity. domain_4_value_61 -> HERO_STATE_DYING: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00230c00..0x00230c04 admits requested 0x3D; 0x00230ee8..0x00230f28 enters dying control mode 0x14 and animation 0x45. domain_5_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00230c08..0x00230c0c compares s1 to 0x47 in the zero-health exception list. Reuse canonical HeroStateId member; this level's entry need not implement its complete lifecycle. domain_6_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00230c10..0x00230c14 admits 0x57; 0x002346b8..0x002346f8 sets dying control mode and animation 3, matching the named vehicle-mode-3 dying case. domain_7_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00230c18..0x00230c1c compares requested s1 to 0x62 in the zero-health exception list. Reuse the exact canonical HeroStateId member without inferring vehicle identity. domain_8_value_119 -> HERO_STATE_FATAL_FALL: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00230c20..0x00230c24 admits 0x77; 0x00232818..0x0023289c tests that current state and initializes randomized fatal-fall tumble targets. domain_9_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: The authoritative hero_set_state snapshot (src/overlays/l08/hero/hero_set_state.c, SHA-256 c532b5f34de13af24eb827478ab4544005dac650343cb12decb88a2ae3e3263c) and original Ghidra agree: retail 0x00230b58 saves a0 as s1, 0x00230c98 writes s1 to hero+0x2084 (state.current), and 0x00230d38 dispatches it. Thus requested_state is the exact HeroStateId domain declared in include/rnc/hero/hero_state.h, distinct from control_mode and vehicle_mode. 0x00230c28..0x00230c2c compares requested s1 with 0x7B. Supplied apply_hero_ground_type_effects also compares state.current with 0x7B and requests it on material 0xB; canonical HeroStateId establishes the shared member. --- src/overlays/l08/hero/hero_set_state.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l08/hero/hero_set_state.c b/src/overlays/l08/hero/hero_set_state.c index 4815d6e32d..81ada3ac69 100644 --- a/src/overlays/l08/hero/hero_set_state.c +++ b/src/overlays/l08/hero/hero_set_state.c @@ -75,7 +75,7 @@ int hero_set_state(int requested_state, int b) { float grind_vector_scratch[4]; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((level_game_mode == 2 || level_game_mode == 6) && b != 2) @@ -83,8 +83,8 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -101,7 +101,7 @@ int hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -129,7 +129,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); return 1; } @@ -573,14 +573,14 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation( p->state.step + 3, D_L08_0015F6D8[p->state.step], (float)scale_game_frames(8)); } @@ -917,7 +917,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -1002,7 +1002,7 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 542c5c24433cfa8a2d2496fcd70ade80ef472fda Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:36:44 +0000 Subject: [PATCH 1314/1502] decomp: clarify names in hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: 0x002166a4-0x002166b8 compares s1 with 100 in the death lock; shared entry 0x0021a008-0x0021a040 cancels item animation and optionally plays idle. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_10_value_106 -> HERO_STATE_DROWN: 0x00216750-0x00216754 accepts request 0x6A; 0x00217118-0x002172bc enters death mode, zeroes health and selects drowning animation 0x5F. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_11_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: 0x00216758-0x0021675c accepts request 0x80; 0x00216a3c-0x00216a98 zeroes health, enters death mode and caps copied momentum to frame_time*3.5. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_12_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: 0x00216760-0x00216764 accepts request 0x82; 0x002172c0-0x0021730c enters death mode, zeroes health, copies momentum and selects animation 0x80. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x00216788 loads vehicle_mode at Hero+0x20A4 and 0x002167b4 branches on zero before on-foot collision/lock/trail resets. Authoritative source identifies this byte as p->vehicle_mode; original Ghidra cRam001413f4 comparisons corroborate it. This proves the separate HeroVehicleMode selector in supplied include/rnc/hero/hero_state.h; reuse its canonical member, not a same-number HeroStateId. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x00216894-0x002168a4 reads Hero+0x20A4 and calls request_hero_idle_state_for_vehicle_mode when nonzero; zero continues ordinary hero idle motion. Authoritative source identifies this byte as p->vehicle_mode; original Ghidra cRam001413f4 comparisons corroborate it. This proves the separate HeroVehicleMode selector in supplied include/rnc/hero/hero_state.h; reuse its canonical member, not a same-number HeroStateId. domain_16_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x00217670-0x00217684 reads Hero+0x20A4 and cancels hero item animation for zero during APPROACH_TARGET_POSE entry. Authoritative source identifies this byte as p->vehicle_mode; original Ghidra cRam001413f4 comparisons corroborate it. This proves the separate HeroVehicleMode selector in supplied include/rnc/hero/hero_state.h; reuse its canonical member, not a same-number HeroStateId. domain_18_value_1 -> HERO_VEHICLE_MODE_CLANK: 0x00217690 reads Hero+0x20A4; 0x002176b8-0x002176d8 compares with s1=1 and selects animation 2 for canonical CLANK vehicle mode. Authoritative source identifies this byte as p->vehicle_mode; original Ghidra cRam001413f4 comparisons corroborate it. This proves the separate HeroVehicleMode selector in supplied include/rnc/hero/hero_state.h; reuse its canonical member, not a same-number HeroStateId. domain_19_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x002176dc-0x00217710 tests the same Hero+0x20A4 vehicle-mode load for zero and selects ordinary step+3 locomotion animation. Authoritative source identifies this byte as p->vehicle_mode; original Ghidra cRam001413f4 comparisons corroborate it. This proves the separate HeroVehicleMode selector in supplied include/rnc/hero/hero_state.h; reuse its canonical member, not a same-number HeroStateId. domain_1_value_6 -> HERO_STATE_FALL: 0x00216708-0x0021670c accepts request 6 in the zero-health whitelist; FALL entry 0x00218188-0x002182ec establishes falling mode and motion. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_20_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x002181cc-0x002181e4 tests Hero+0x20A4 for zero before allocating the on-foot fatal-fall entry voice. Authoritative source identifies this byte as p->vehicle_mode; original Ghidra cRam001413f4 comparisons corroborate it. This proves the separate HeroVehicleMode selector in supplied include/rnc/hero/hero_state.h; reuse its canonical member, not a same-number HeroStateId. domain_22_value_41 -> HERO_STATE_GRIND_JUMP: 0x002183fc-0x0021841c tests s1-0x29 unsigned below 2 and sets unk2284=3 for the canonical GRIND_JUMP/GRIND_RAIL_TRANSFER interval, matching source requested_state>=0x29. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_23_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: 0x002183fc-0x0021841c tests s1-0x29 unsigned below 2 and sets unk2284=3 for the canonical GRIND_JUMP/GRIND_RAIL_TRANSFER interval, matching source requested_state<=0x2A. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_2_value_61 -> HERO_STATE_DYING: 0x00216710-0x00216714 accepts request 0x3D; 0x002169f8-0x00216a38 enters death mode 0x14 and selects dying animation 0x45. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_3_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: 0x00216718-0x0021671c accepts request 0x47 in the zero-health whitelist; reuse canonical HeroStateId member for that request, independently of control_mode. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_4_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: 0x00216720-0x00216724 accepts request 0x57; 0x00219c30-0x00219c70 enters death mode, copies momentum and selects animation 3. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_5_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: 0x00216728-0x0021672c accepts request 0x62 in the zero-health whitelist; reuse canonical HeroStateId member for that same requested-state domain. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_6_value_119 -> HERO_STATE_FATAL_FALL: 0x00216730-0x00216734 accepts request 0x77; 0x002181b0-0x0021822c recognizes current state 0x77 and adds fatal-fall voice and tumble setup. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_7_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: 0x00216738-0x0021673c accepts request 0x7B in the zero-health whitelist; canonical HeroStateId supplies its lifecycle meaning within the proven request-state domain. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_8_value_124 -> HERO_STATE_DEATH_DESCENT: 0x00216740-0x00216744 accepts request 0x7C in the zero-health whitelist; canonical HeroStateId identifies this requested state as DEATH_DESCENT. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. domain_9_value_127 -> HERO_STATE_SINK: 0x00216748-0x0021674c accepts request 0x7F; 0x00216a9c-0x00216b38 zeroes health and initializes downward water-surface-relative motion. Retail 0x00216668 retains requested_state/a0 in s1; 0x002167a8 stores s1 at Hero+0x2084 (state.current), and 0x00216838-0x00216858 dispatches it. Source named switch cases and original Ghidra switch(param_1) prove HeroStateId domain from include/rnc/hero/hero_state.h, distinct from control_mode +0x208C. --- src/overlays/l03/hero/hero_set_state.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l03/hero/hero_set_state.c b/src/overlays/l03/hero/hero_set_state.c index 616b8c6e00..9f10ea8829 100644 --- a/src/overlays/l03/hero/hero_set_state.c +++ b/src/overlays/l03/hero/hero_set_state.c @@ -74,7 +74,7 @@ int hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L03_0015F5C4 == 2 || D_L03_0015F5C4 == 6) && b != 2) @@ -82,8 +82,8 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -100,7 +100,7 @@ int hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -128,7 +128,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); return 1; } @@ -557,14 +557,14 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation( p->state.step + 3, D_L03_0015F6D8[p->state.step], (float)scale_game_frames(8)); } @@ -875,7 +875,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -960,7 +960,7 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From dce6424fe82f26f637f729058450de8be3d97322 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:36:44 +0000 Subject: [PATCH 1315/1502] decomp: clarify names in hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x0024012c..0x00240140 permits request 100 with b=2 in dying control mode; its named source case cancels item animation and optionally selects idle animation at 0x00243b7c..0x00243bb4. domain_10_value_106 -> HERO_STATE_DROWN: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x002401d8..0x002401dc permits 0x6A at zero health. Named DROWN entry at 0x00240be0..0x00240d84 clears health, enters dying control mode, updates drowning usage statistics and selects animation 0x5F. domain_11_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x002401e0..0x002401e4 permits 0x80 at zero health. Named DYING_SPEED_LIMITED entry at 0x00240504..0x00240560 clears health and applies frame_time*3.5 to copied momentum. domain_12_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x002401e8..0x002401ec permits 0x82 at zero health. Named DYING_ZERO_HEALTH entry at 0x00240d88..0x00240dd4 clears health, enters control mode 0x14 and selects animation 0x80. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The source selector is explicitly Hero.vehicle_mode, a separate byte field. Retail 0x00240210 loads Hero+0x20A4, distinct from current-state +0x2084 and control-mode +0x208C. Original Ghidra identifies the same byte as cRam001413f4. This proves the supplied shared HeroVehicleMode domain rather than HeroStateId. 0x0024023c branches on the zero vehicle byte before clearing collision/item locks and transform history. HeroVehicleMode canonically declares HERO_VEHICLE_MODE_ON_FOOT=0. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The source selector is explicitly Hero.vehicle_mode, a separate byte field. Retail 0x00240210 loads Hero+0x20A4, distinct from current-state +0x2084 and control-mode +0x208C. Original Ghidra identifies the same byte as cRam001413f4. This proves the supplied shared HeroVehicleMode domain rather than HeroStateId. 0x0024031c..0x00240328 tests nonzero vehicle_mode before request_hero_idle_state_for_vehicle_mode; zero takes the on-foot idle path. HeroVehicleMode canonically declares HERO_VEHICLE_MODE_ON_FOOT=0. domain_16_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The source selector is explicitly Hero.vehicle_mode, a separate byte field. Retail 0x00240210 loads Hero+0x20A4, distinct from current-state +0x2084 and control-mode +0x208C. Original Ghidra identifies the same byte as cRam001413f4. This proves the supplied shared HeroVehicleMode domain rather than HeroStateId. 0x002412d4..0x002412e8 tests zero vehicle_mode before cancel_hero_item_animation in APPROACH_TARGET_POSE. HeroVehicleMode canonically declares HERO_VEHICLE_MODE_ON_FOOT=0. domain_18_value_1 -> HERO_VEHICLE_MODE_CLANK: The source selector is explicitly Hero.vehicle_mode, a separate byte field. Retail 0x00240210 loads Hero+0x20A4, distinct from current-state +0x2084 and control-mode +0x208C. Original Ghidra identifies the same byte as cRam001413f4. This proves the supplied shared HeroVehicleMode domain rather than HeroStateId. 0x002412f4 loads vehicle_mode; after rejecting mode 3, 0x0024131c compares that byte with s1=1, choosing animation 2 at 0x00241324..0x0024133c. Source has p->vehicle_mode==1 here. Shared HeroVehicleMode declares canonical HERO_VEHICLE_MODE_CLANK=1. domain_19_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The source selector is explicitly Hero.vehicle_mode, a separate byte field. Retail 0x00240210 loads Hero+0x20A4, distinct from current-state +0x2084 and control-mode +0x208C. Original Ghidra identifies the same byte as cRam001413f4. This proves the supplied shared HeroVehicleMode domain rather than HeroStateId. 0x00241340 tests zero vehicle_mode before choosing the indexed on-foot run animation in APPROACH_TARGET_POSE. HeroVehicleMode canonically declares HERO_VEHICLE_MODE_ON_FOOT=0. domain_1_value_6 -> HERO_STATE_FALL: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x00240190..0x00240194 exempts FALL from zero-health rejection. The existing named FALL branch initializes falling control mode 2 and gravity/velocity at 0x00241c9c..0x00241e00. domain_20_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The source selector is explicitly Hero.vehicle_mode, a separate byte field. Retail 0x00240210 loads Hero+0x20A4, distinct from current-state +0x2084 and control-mode +0x208C. Original Ghidra identifies the same byte as cRam001413f4. This proves the supplied shared HeroVehicleMode domain rather than HeroStateId. 0x00241ce0..0x00241cf8 tests zero vehicle_mode before allocating the fatal-fall voice. HeroVehicleMode canonically declares HERO_VEHICLE_MODE_ON_FOOT=0. domain_22_value_41 -> HERO_STATE_GRIND_JUMP: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x00241f10..0x00241f30 tests the two-state requested range starting at 0x29 and chooses unk2284=3 within shared jump entry. Source expresses requested_state>=0x29 && requested_state<=0x2A and already lists HERO_STATE_GRIND_JUMP/HERO_STATE_GRIND_RAIL_TRANSFER in that entry. Shared HeroStateId canonically names lower bound 41 as GRIND_JUMP. domain_23_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x00241f10..0x00241f30 tests requested_state-0x29<2 in shared jump entry. Source expresses the upper bound requested_state<=0x2A and already lists HERO_STATE_GRIND_RAIL_TRANSFER in that entry. Shared HeroStateId canonically names upper bound 42 as GRIND_RAIL_TRANSFER. domain_2_value_61 -> HERO_STATE_DYING: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x00240198..0x0024019c exempts DYING from zero-health rejection. Existing named DYING entry at 0x002404c0..0x00240500 sets control_mode=0x14 and animation 0x45. domain_3_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x002401a0..0x002401a4 compares requested_state with 0x47 in the zero-health exception list. The shared HeroStateId declares canonical HERO_STATE_VEHICLE_MODE_1_DYING=71 for this exact current-state domain; reuse that member. domain_4_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x002401a8..0x002401ac exempts state 0x57 from zero-health rejection. Existing named vehicle-mode-3 dying branch at 0x00243818..0x00243858 sets dying control mode 0x14 and copies momentum. domain_5_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x002401b0..0x002401b4 compares requested_state with 0x62 in the zero-health exception list. Shared HeroStateId declares canonical HERO_STATE_VEHICLE_MODE_2_DYING=98 in this exact state.current domain; reuse that member. domain_6_value_119 -> HERO_STATE_FATAL_FALL: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x002401b8..0x002401bc permits 0x77 at zero health. Existing named FATAL_FALL shares FALL entry; 0x00241cc4..0x00241d40 tests current==0x77 and initializes its tumble targets. domain_7_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x002401c0..0x002401c4 compares requested_state with 0x7B in the zero-health exception list. Shared HeroStateId names this exact current-state ID HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT=123; reuse the established domain member without claiming new lifecycle evidence. domain_8_value_124 -> HERO_STATE_DEATH_DESCENT: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x002401c8..0x002401cc compares requested_state with 0x7C in the zero-health exception list. Shared HeroStateId declares HERO_STATE_DEATH_DESCENT=124 for this exact selector domain; reuse the canonical member. domain_9_value_127 -> HERO_STATE_SINK: Retail 0x002400f0 saves a0 in s1, 0x00240230 stores s1 to Hero+0x2084 (state.current), and 0x002402c0..0x002402e0 dispatches the same selector. Original Ghidra has iRam001413d4=param_1 and switch(param_1). Thus requested_state belongs to shared HeroStateId in include/rnc/hero/hero_state.h, not control_mode or vehicle_mode. 0x002401d0..0x002401d4 permits 0x7F at zero health. Named SINK entry 0x00240564..0x00240600 clears health, targets water_surface_z-0.37 and initializes bounded downward motion. Supplied ground-material caller requests HERO_STATE_SINK during downward surface crossing. --- src/overlays/l12/hero/hero_set_state.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l12/hero/hero_set_state.c b/src/overlays/l12/hero/hero_set_state.c index 934ce3475c..a617285de8 100644 --- a/src/overlays/l12/hero/hero_set_state.c +++ b/src/overlays/l12/hero/hero_set_state.c @@ -72,7 +72,7 @@ int hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L12_0015F5C4 == 2 || D_L12_0015F5C4 == 6) && b != 2) @@ -80,8 +80,8 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -98,7 +98,7 @@ int hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -126,7 +126,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); return 1; } @@ -604,14 +604,14 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation( p->state.step + 3, D_L12_0015F6D8[p->state.step], (float)scale_game_frames(8)); } @@ -888,7 +888,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -973,7 +973,7 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 670cbd86d649b52ff0146c710a6405db75dec37d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:36:45 +0000 Subject: [PATCH 1316/1502] decomp: clarify names in hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: 0x0022ffb4-0x0022ffb8 admits request 0x64 from dying control; source dispatch already uses this canonical member. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_10_value_106 -> HERO_STATE_DROWN: 0x00230060-0x00230064 admits request 0x6A in the health-zero guard; reuse supplied canonical HeroStateId member. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_11_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: 0x00230068-0x0023006c admits request 0x80; source matching branch zeros health and limits momentum at 0x0023038c-0x002303c4. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_12_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: 0x00230070-0x00230074 compares request 0x82 as the last health-zero exception; reuse supplied canonical HeroStateId member. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00230098-0x002300e8: zero mode clears collision suppression, item blocking and trail history. The byte loaded at hero+0x20A4 is explicitly p->vehicle_mode in authoritative C and cRam001413f4 in original Ghidra. Supplied resolve_hero_surface_reactions and process_hero_hit_reaction use HERO_VEHICLE_MODE_ON_FOOT for this same Hero.vehicle_mode selector; reuse canonical HeroVehicleMode from include/rnc/hero/hero_state.h, independently of state.current. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002301a4-0x002301b4: nonzero mode delegates idle setup to the vehicle helper. The byte loaded at hero+0x20A4 is explicitly p->vehicle_mode in authoritative C and cRam001413f4 in original Ghidra. Supplied resolve_hero_surface_reactions and process_hero_hit_reaction use HERO_VEHICLE_MODE_ON_FOOT for this same Hero.vehicle_mode selector; reuse canonical HeroVehicleMode from include/rnc/hero/hero_state.h, independently of state.current. domain_16_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002308c4-0x002308d8: zero mode cancels the hero item animation. The byte loaded at hero+0x20A4 is explicitly p->vehicle_mode in authoritative C and cRam001413f4 in original Ghidra. Supplied resolve_hero_surface_reactions and process_hero_hit_reaction use HERO_VEHICLE_MODE_ON_FOOT for this same Hero.vehicle_mode selector; reuse canonical HeroVehicleMode from include/rnc/hero/hero_state.h, independently of state.current. domain_18_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x002308e4 loads hero+0x20A4 (vehicle_mode), 0x0023090c compares that same byte with s1=1, and 0x00230914-0x0023092c chooses animation 2. Authoritative source explicitly compares p->vehicle_mode == 1; original Ghidra agrees via cRam001413f4. This is the exact HeroVehicleMode field domain in include/rnc/hero/hero_state.h, whose canonical value 1 member is HERO_VEHICLE_MODE_CLANK; it is separate from the request-state and control-mode domains. domain_19_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00230930-0x00230964: zero mode selects step-indexed on-foot locomotion animation. The byte loaded at hero+0x20A4 is explicitly p->vehicle_mode in authoritative C and cRam001413f4 in original Ghidra. Supplied resolve_hero_surface_reactions and process_hero_hit_reaction use HERO_VEHICLE_MODE_ON_FOOT for this same Hero.vehicle_mode selector; reuse canonical HeroVehicleMode from include/rnc/hero/hero_state.h, independently of state.current. domain_1_value_6 -> HERO_STATE_FALL: 0x00230018-0x0023001c admits request 6 in the health-zero guard; source FALL entry initializes falling motion at 0x00231488. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_20_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002314cc-0x002314e4: zero mode allocates the fatal-fall hero voice. The byte loaded at hero+0x20A4 is explicitly p->vehicle_mode in authoritative C and cRam001413f4 in original Ghidra. Supplied resolve_hero_surface_reactions and process_hero_hit_reaction use HERO_VEHICLE_MODE_ON_FOOT for this same Hero.vehicle_mode selector; reuse canonical HeroVehicleMode from include/rnc/hero/hero_state.h, independently of state.current. domain_22_value_41 -> HERO_STATE_GRIND_JUMP: 0x002316fc-0x00231704 subtracts 0x29 from the saved request and tests a two-state interval; source >=0x29 lower endpoint selects grind jump/transfer setup. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_23_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: 0x002316fc-0x00231714 tests request-minus-0x29 below 2; source <=0x2A upper endpoint selects grind jump/transfer setup. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_2_value_61 -> HERO_STATE_DYING: 0x00230020-0x00230024 admits request 0x3D; its source DYING branch sets control_mode 0x14 at 0x00230348-0x00230350. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_3_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: 0x00230028-0x0023002c compares request 0x47 in the health-zero admission guard; reuse the supplied canonical state member. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_4_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: 0x00230030-0x00230034 admits request 0x57; source matching state entry sets dying control at 0x002331f0-0x002331f8. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_5_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: 0x00230038-0x0023003c admits request 0x62 in the health-zero guard; reuse canonical HeroStateId membership. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_6_value_119 -> HERO_STATE_FATAL_FALL: 0x00230040-0x00230044 admits request 0x77; source FALL/FATAL_FALL shared entry specializes fatal tumble at 0x002314c4-0x0023152c. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_7_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: 0x00230048-0x0023004c admits request 0x7B in the health-zero guard. Supplied surface-reaction caller passes 0x7B directly to hero_set_state. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_8_value_124 -> HERO_STATE_DEATH_DESCENT: 0x00230050-0x00230054 admits request 0x7C in the health-zero guard; reuse supplied canonical HeroStateId member. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. domain_9_value_127 -> HERO_STATE_SINK: 0x00230058-0x0023005c admits request 0x7F; source SINK branch zeros health and targets water-surface Z at 0x002303ec-0x0023046c. Selector requested_state is original param_1/a0, preserved in s1 at 0x0022ff78 and stored into hero+0x2084 (state.current) at 0x002300b8 before dispatch 0x00230148-0x00230168. This proves the exact HeroStateId domain in include/rnc/hero/hero_state.h, rather than control_mode or vehicle_mode; authoritative C and original retail Ghidra agree. --- src/overlays/l14/hero/hero_set_state.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l14/hero/hero_set_state.c b/src/overlays/l14/hero/hero_set_state.c index 3156780a77..06f5136f68 100644 --- a/src/overlays/l14/hero/hero_set_state.c +++ b/src/overlays/l14/hero/hero_set_state.c @@ -71,7 +71,7 @@ int hero_set_state(int requested_state, int b) { float grind_direction_or_jump_reference_position[4]; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L14_0015F5C4 == 2 || D_L14_0015F5C4 == 6) && b != 2) @@ -79,8 +79,8 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -97,7 +97,7 @@ int hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -125,7 +125,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); return 1; } @@ -349,14 +349,14 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation( p->state.step + 3, D_L14_0015F6D8[p->state.step], (float)scale_game_frames(8)); } @@ -690,7 +690,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -775,7 +775,7 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From afdd4d9cb1f183ed9fe267b4d6727f5a0fdb029a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:36:46 +0000 Subject: [PATCH 1317/1502] decomp: clarify names in hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: 0x0024dbac-0x0024dbbc permits request 100 while death control mode is active; original Ghidra cases 99/100 and retail 0x002513d0-0x00251408 cancel item animation and optionally select idle animation. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_10_value_106 -> HERO_STATE_DROWN: 0x0024dc58-0x0024dc5c admits request 0x6A; original Ghidra case 0x6A and retail 0x0024e620-0x0024e648 initialize death mode and clear health, then 0x0024e7ac-0x0024e7c4 selects animation 0x5F. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_11_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: 0x0024dc60-0x0024dc64 admits request 0x80; original Ghidra case 0x80 and retail 0x0024df44-0x0024dfa0 clear health, enter death mode and limit copied momentum using frame_time*3.5. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_12_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: 0x0024dc68-0x0024dc6c admits request 0x82; original Ghidra case 0x82 and retail 0x0024e7c8-0x0024e814 clear health, enter death mode, copy momentum and select animation 0x80. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x0024dc90/0x0024dcbc tests vehicle_mode zero before resetting collision and item flags. Original Ghidra reads cRam001413f4, the Hero+0x20A4 byte identified by authoritative C as vehicle_mode. This is the separate HeroVehicleMode domain in include/rnc/hero/hero_state.h, with canonical HERO_VEHICLE_MODE_ON_FOOT=0; it is not state.current or control_mode. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x0024dd9c-0x0024dda8 tests nonzero vehicle_mode and delegates idle entry to the vehicle helper. Original Ghidra reads cRam001413f4, the Hero+0x20A4 byte identified by authoritative C as vehicle_mode. This is the separate HeroVehicleMode domain in include/rnc/hero/hero_state.h, with canonical HERO_VEHICLE_MODE_ON_FOOT=0; it is not state.current or control_mode. domain_16_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x0024ec08-0x0024ec18 tests zero vehicle_mode before canceling item animation. Original Ghidra reads cRam001413f4, the Hero+0x20A4 byte identified by authoritative C as vehicle_mode. This is the separate HeroVehicleMode domain in include/rnc/hero/hero_state.h, with canonical HERO_VEHICLE_MODE_ON_FOOT=0; it is not state.current or control_mode. domain_18_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0024ec28 loads Hero+0x20A4, then 0x0024ec50 compares that byte with s1=1 and 0x0024ec58-0x0024ec70 selects animation 2. Original Ghidra case 0x65 compares cRam001413f4 with 1; authoritative C identifies this exact byte as vehicle_mode. Thus reuse canonical HeroVehicleMode member HERO_VEHICLE_MODE_CLANK=1, independently of current-state IDs. domain_19_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x0024ec74-0x0024eca8 tests zero vehicle_mode before selecting the on-foot step-indexed animation. Original Ghidra reads cRam001413f4, the Hero+0x20A4 byte identified by authoritative C as vehicle_mode. This is the separate HeroVehicleMode domain in include/rnc/hero/hero_state.h, with canonical HERO_VEHICLE_MODE_ON_FOOT=0; it is not state.current or control_mode. domain_1_value_6 -> HERO_STATE_FALL: 0x0024dc10-0x0024dc14 admits request 6 through the zero-health guard; original Ghidra case 6 and retail 0x0024f5c4-0x0024f728 initialize airborne gravity, velocity and fall animation. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_20_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x0024f608-0x0024f620 tests zero vehicle_mode before allocating the fatal-fall voice. Original Ghidra reads cRam001413f4, the Hero+0x20A4 byte identified by authoritative C as vehicle_mode. This is the separate HeroVehicleMode domain in include/rnc/hero/hero_state.h, with canonical HERO_VEHICLE_MODE_ON_FOOT=0; it is not state.current or control_mode. domain_22_value_41 -> HERO_STATE_GRIND_JUMP: Original Ghidra tests param_1-0x29U<2; retail 0x0024f838-0x0024f858 selects unk2284=3 for the pair of request states. Source groups this branch with HERO_STATE_GRIND_JUMP and HERO_STATE_GRIND_RAIL_TRANSFER; reuse canonical lower bound HERO_STATE_GRIND_JUMP=41. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_23_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: Original Ghidra tests param_1-0x29U<2; retail 0x0024f838-0x0024f858 selects unk2284=3 for the two grind jump requests. Source's upper bound requested_state<=0x2A is in the shared HeroStateId domain and reuses HERO_STATE_GRIND_RAIL_TRANSFER=42. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_2_value_61 -> HERO_STATE_DYING: 0x0024dc18-0x0024dc1c admits request 0x3D; original Ghidra case 0x3D and retail 0x0024df00-0x0024df40 initialize death control mode 0x14 and animation 0x45. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_3_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: 0x0024dc20-0x0024dc24 compares the saved requested state with 0x47 in the zero-health admission guard. This request is in the exact HeroStateId domain, whose canonical member is HERO_STATE_VEHICLE_MODE_1_DYING=71. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_4_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: 0x0024dc28-0x0024dc2c admits request 0x57; original Ghidra case 0x57 and retail 0x0025106c-0x002510ac enter death control mode 0x14, copy momentum and select vehicle animation 3. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_5_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: 0x0024dc30-0x0024dc34 compares saved requested state with 0x62 in the zero-health admission guard. The exact HeroStateId domain supplies canonical HERO_STATE_VEHICLE_MODE_2_DYING=98; no vehicle-mode selector is being renamed here. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_6_value_119 -> HERO_STATE_FATAL_FALL: 0x0024dc38-0x0024dc3c admits request 0x77; original Ghidra cases 6/0x77 and retail 0x0024f608-0x0024f668 give the fatal-fall variant voice and randomized tumble targets within fall initialization. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_7_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: 0x0024dc40-0x0024dc44 compares saved requested state with 0x7B in the zero-health guard. Supplied update_hero_surface_condition_flags requests this same state after collision material 0xB; canonical shared HeroStateId member is HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT=123. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_8_value_124 -> HERO_STATE_DEATH_DESCENT: 0x0024dc48-0x0024dc4c compares saved requested state with 0x7C in the zero-health admission guard. The stored/dispatched request belongs to exact shared HeroStateId, whose canonical member is HERO_STATE_DEATH_DESCENT=124. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. domain_9_value_127 -> HERO_STATE_SINK: 0x0024dc50-0x0024dc54 admits request 0x7F; original Ghidra case 0x7F and retail 0x0024dfa4-0x0024e040 clear health and initialize downward motion targeting water_surface_z minus 0.37. Supplied water transition caller requests HERO_STATE_SINK. Domain proof: incoming a0 is saved in s1 at 0x0024db70, stored to Hero+0x2084 (state.current) at 0x0024dcb0 and dispatched at 0x0024dd50-0x0024dd60; original Ghidra assigns param_1 to iRam001413d4 and switches on it. Supplied include/rnc/hero/hero_state.h declares canonical HeroStateId members for this exact selector. --- src/overlays/l11/hero/hero_set_state.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l11/hero/hero_set_state.c b/src/overlays/l11/hero/hero_set_state.c index cb0cfb3cbc..89f50d8892 100644 --- a/src/overlays/l11/hero/hero_set_state.c +++ b/src/overlays/l11/hero/hero_set_state.c @@ -71,7 +71,7 @@ int hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L11_0015F5C4 == 2 || D_L11_0015F5C4 == 6) && b != 2) @@ -79,8 +79,8 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -97,7 +97,7 @@ int hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -125,7 +125,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); return 1; } @@ -573,14 +573,14 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation( p->state.step + 3, D_L11_0015F6D8[p->state.step], (float)scale_game_frames(8)); } @@ -854,7 +854,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -939,7 +939,7 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 003971ddc1b329946057199a4b9f265e75704a47 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:36:46 +0000 Subject: [PATCH 1318/1502] decomp: clarify names in update_hero_state_machine domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: The embedded authoritative C binds this selector to hero.vehicle_mode; retail loads the byte at hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control mode +0x208c. The supplied include/rnc/hero/hero_state.h HeroVehicleMode domain canonically names this field's values. Retail 0x00242a58-0x00242a60 compares that byte with 1 to bypass item-use locking for the HUD selector. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: The embedded authoritative C binds this selector to hero.vehicle_mode; retail loads the byte at hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control mode +0x208c. The supplied include/rnc/hero/hero_state.h HeroVehicleMode domain canonically names this field's values. Retail 0x00242a80-0x00242a88 compares the same byte with 1 to bypass item-selection blocking. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The embedded authoritative C binds this selector to hero.vehicle_mode; retail loads the byte at hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control mode +0x208c. The supplied include/rnc/hero/hero_state.h HeroVehicleMode domain canonically names this field's values. Retail 0x00242a9c-0x00242aa0 tests that byte for zero before permitting the item-selector HUD path; supplied hero_frame_update also uses ON_FOOT on this same field. domain_4_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: The embedded authoritative C binds this selector to hero.vehicle_mode; retail loads the byte at hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control mode +0x208c. The supplied include/rnc/hero/hero_state.h HeroVehicleMode domain canonically names this field's values. Retail 0x00242ce8-0x00242cf0 compares the same vehicle byte with 2 to exempt this mode from fatal-fall entry, matching the supplied canonical HeroVehicleMode member. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The embedded authoritative C binds this selector to hero.vehicle_mode; retail loads the byte at hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control mode +0x208c. The supplied include/rnc/hero/hero_state.h HeroVehicleMode domain canonically names this field's values. Retail 0x00243c28-0x00243c2c tests the byte for zero to enable on-foot LOOK animation selection. domain_6_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The embedded authoritative C binds this selector to hero.vehicle_mode; retail loads the byte at hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control mode +0x208c. The supplied include/rnc/hero/hero_state.h HeroVehicleMode domain canonically names this field's values. Retail 0x00243d14-0x00243d24 tests the byte for nonzero and calls request_hero_idle_state_for_vehicle_mode; zero continues the on-foot crouch/idle exits. domain_7_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The embedded authoritative C binds this selector to hero.vehicle_mode; retail loads the byte at hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control mode +0x208c. The supplied include/rnc/hero/hero_state.h HeroVehicleMode domain canonically names this field's values. Retail 0x002446b4-0x002446b8 tests the same vehicle byte for nonzero before the target-pose braking transition, independently of the current-state selector. domain_8_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The embedded authoritative C binds this selector to hero.vehicle_mode; retail loads the byte at hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control mode +0x208c. The supplied include/rnc/hero/hero_state.h HeroVehicleMode domain canonically names this field's values. Retail 0x0024712c-0x00247130 tests the byte for zero to select on-foot look-release animations, mirroring LOOK at 0x00243c28. --- .../l01/hero/update_hero_state_machine.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l01/hero/update_hero_state_machine.c b/src/overlays/l01/hero/update_hero_state_machine.c index 482d602fc2..b416e4c2d3 100644 --- a/src/overlays/l01/hero/update_hero_state_machine.c +++ b/src/overlays/l01/hero/update_hero_state_machine.c @@ -165,9 +165,9 @@ void update_hero_state_machine(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L01_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.vehicle_mode == 0 || hero.vehicle_mode == 3)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; if (hero.quick_swap_tap_window != 0) { @@ -230,7 +230,7 @@ void update_hero_state_machine(void) { } } if (fatal_fall_trigger_z > hero.motion.pos.f[2] && hero.ground_distance > 2.0f && - hero.vehicle_mode != 2 && hero.state.current != 0x77) { + hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { l01_hero_set_state(0x77, 1); } else { switch (hero.state.current) { @@ -628,7 +628,7 @@ void update_hero_state_machine(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { @@ -655,7 +655,7 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); break; } @@ -911,7 +911,7 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { l01_hero_set_state(0x66, 1); } break; @@ -1934,7 +1934,7 @@ void update_hero_state_machine(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { From feca635c7fde90636f9779e6b3b2d34562a31510 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:38:52 +0000 Subject: [PATCH 1319/1502] decomp: clarify names in hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. 0x00216c94..0x00216ca8 admits requested state 100 with b=2 from terminal control; original cases 99/100 and 0x0021a9dc..0x0021aa14 cancel item animation and enter mode 0x18. domain_10_value_106 -> HERO_STATE_DROWN: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. 0x00216d40..0x00216d44 admits state 0x6A; original case 0x6A and 0x00217608..0x00217630 enter terminal mode 0x14, block item selection and clear health. domain_11_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. 0x00216d48..0x00216d4c admits requested state 0x80 through the zero-health allowlist. The supplied shared HeroStateId canonically identifies DYING_SPEED_LIMITED; the entry gate need not implement its movement consumer. domain_12_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. 0x00216d50..0x00216d54 admits state 0x82; original case 0x82 and 0x002177b0..0x002177fc enter terminal mode 0x14, explicitly clear health and select animation 0x80. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative C reads hero.vehicle_mode, a separate field from state.current and control_mode. Original Ghidra uses cRam001413f4; retail reads the byte at hero+0x20A4. This proves the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h, whose canonical zero is HERO_VEHICLE_MODE_ON_FOOT and one is HERO_VEHICLE_MODE_CLANK. 0x00216d78 and 0x00216da4 test the vehicle byte against zero before clearing collision_disable, item-selection flags and transform history. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative C reads hero.vehicle_mode, a separate field from state.current and control_mode. Original Ghidra uses cRam001413f4; retail reads the byte at hero+0x20A4. This proves the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h, whose canonical zero is HERO_VEHICLE_MODE_ON_FOOT and one is HERO_VEHICLE_MODE_CLANK. Original case 0 idle tests the vehicle byte nonzero; 0x00216e84..0x00216e94 dispatches vehicle-state setup for that nonzero branch. domain_16_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative C reads hero.vehicle_mode, a separate field from state.current and control_mode. Original Ghidra uses cRam001413f4; retail reads the byte at hero+0x20A4. This proves the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h, whose canonical zero is HERO_VEHICLE_MODE_ON_FOOT and one is HERO_VEHICLE_MODE_CLANK. Original case 0x65 and 0x00217b60..0x00217b74 test vehicle_mode zero to call cancel_hero_item_animation. domain_18_value_1 -> HERO_VEHICLE_MODE_CLANK: The authoritative C reads hero.vehicle_mode, a separate field from state.current and control_mode. Original Ghidra uses cRam001413f4; retail reads the byte at hero+0x20A4. This proves the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h, whose canonical zero is HERO_VEHICLE_MODE_ON_FOOT and one is HERO_VEHICLE_MODE_CLANK. Original case 0x65 tests cRam001413f4 == 1; 0x00217b80..0x00217bc8 loads the vehicle byte and compares it to s1=1, selecting animation 2. The canonical CLANK identity comes from the proven shared vehicle domain. domain_19_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative C reads hero.vehicle_mode, a separate field from state.current and control_mode. Original Ghidra uses cRam001413f4; retail reads the byte at hero+0x20A4. This proves the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h, whose canonical zero is HERO_VEHICLE_MODE_ON_FOOT and one is HERO_VEHICLE_MODE_CLANK. Original case 0x65 and 0x00217bcc..0x00217c00 test that same vehicle byte against zero before selecting step-indexed ground-running animations. domain_1_value_6 -> HERO_STATE_FALL: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. The zero-health allowlist at 0x00216cf8..0x00216cfc admits state 6; original cases 6/0x77 and 0x0021857c..0x00218640 initialize fall acceleration, control_mode 2 and velocity. domain_20_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative C reads hero.vehicle_mode, a separate field from state.current and control_mode. Original Ghidra uses cRam001413f4; retail reads the byte at hero+0x20A4. This proves the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h, whose canonical zero is HERO_VEHICLE_MODE_ON_FOOT and one is HERO_VEHICLE_MODE_CLANK. Original cases 6/0x77 and 0x002185c0..0x002185d8 test the vehicle byte zero before allocating the fatal-fall voice. domain_22_value_41 -> HERO_STATE_GRIND_JUMP: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. Original Ghidra tests param_1-0x29U<2. Retail 0x002187f0..0x00218810 tests the two-state range starting at 41 and assigns category 3 under airborne control_mode 4. Canonical lower member is GRIND_JUMP. domain_23_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. Original Ghidra tests param_1-0x29U<2. Retail 0x002187f0..0x00218810 recognizes exactly states 41 and 42 and assigns category 3 under airborne control_mode 4. Canonical upper member is GRIND_RAIL_TRANSFER. domain_2_value_61 -> HERO_STATE_DYING: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. 0x00216d00..0x00216d04 admits state 0x3D through the zero-health gate; original case 0x3D and 0x00216fe8..0x00217028 set terminal mode 0x14 and animation 0x45. domain_3_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. 0x00216d08..0x00216d0c compares requested state 0x47 in the zero-health allowlist. Canonical HeroStateId identifies that state as vehicle-mode-1 dying; this is a state ID, not vehicle_mode 71. domain_4_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. 0x00216d10..0x00216d14 admits state 0x57; original case 0x57 and 0x0021a604..0x0021a644 set terminal mode 0x14, copy resolved velocity to momentum and select animation 3. domain_5_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. 0x00216d18..0x00216d1c admits state 0x62; original case 0x62 and 0x0021a3d4..0x0021a414 set terminal control_mode 0x14 and copy resolved velocity to momentum. domain_6_value_119 -> HERO_STATE_FATAL_FALL: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. 0x00216d20..0x00216d24 admits state 0x77; original cases 6/0x77 share falling setup, while 0x002185b8..0x00218620 adds state-0x77 voice and randomized tumble targets. domain_7_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. 0x00216d28..0x00216d2c admits state 0x7B; original case 0x7B and 0x0021a130..0x0021a190 initialize mode 0x19, collision_off_frames=10000, voice and animation 0x71. Reuse canonical state lifecycle naming. domain_8_value_124 -> HERO_STATE_DEATH_DESCENT: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. 0x00216d30..0x00216d34 admits requested state 0x7C through the zero-health allowlist. The supplied shared HeroStateId canonically identifies this member as DEATH_DESCENT within the proven current-state domain. domain_9_value_127 -> HERO_STATE_SINK: Retail 0x00216c58 saves requested_state in s1, 0x00216d98 stores it to hero+0x2084 (state.current), and 0x00216e28..0x00216e48 dispatches s1. Original Ghidra uses param_1 for these comparisons and the same current-state store. This proves the HeroStateId domain in supplied include/rnc/hero/hero_state.h (SHA-256 365a17ce757a987ddb6dfce0502b41c3f41b429a2079129789a10a4695bddb2d), separate from control_mode +0x208C and vehicle_mode +0x20A4; reuse its canonical member. 0x00216d38..0x00216d3c admits requested state 0x7F through the zero-health allowlist. The supplied shared HeroStateId canonically identifies this member as SINK within the proven current-state domain. --- src/overlays/l15/hero/hero_set_state.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l15/hero/hero_set_state.c b/src/overlays/l15/hero/hero_set_state.c index 136ccb21fb..cc8a199540 100644 --- a/src/overlays/l15/hero/hero_set_state.c +++ b/src/overlays/l15/hero/hero_set_state.c @@ -74,7 +74,7 @@ int hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L15_0015F5C4 == 2 || D_L15_0015F5C4 == 6) && b != 2) @@ -82,8 +82,8 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -100,7 +100,7 @@ int hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -128,7 +128,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { set_hero_state_for_vehicle_mode(); return 1; } @@ -527,14 +527,14 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation( p->state.step + 3, D_L15_0015F6D8[p->state.step], (float)scale_game_frames(8)); } @@ -818,7 +818,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -903,7 +903,7 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From d3d7e3b96e830d323c0bbf52b6c44c2dba7ff891 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:38:53 +0000 Subject: [PATCH 1320/1502] decomp: clarify names in update_hero_state_transitions domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x00253b3c-0x00253b44 compares that byte with 1 to bypass the item-use lock. Authoritative C maps hero.vehicle_mode to hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084, step +0x2088 and control mode +0x208c. Checked idle-mode helper 0x00251560 reads the same absolute byte, selects IDLE for zero at 0x00251580-0x00251588 and mode-3 idle for three at 0x00251594-0x0025159c. This establishes the separate HeroVehicleMode selector domain in include/rnc/hero/hero_state.h; reuse its canonical member. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x00253b64-0x00253b6c compares that byte with 1 to bypass the item-selection blocker. Authoritative C maps hero.vehicle_mode to hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084, step +0x2088 and control mode +0x208c. Checked idle-mode helper 0x00251560 reads the same absolute byte, selects IDLE for zero at 0x00251580-0x00251588 and mode-3 idle for three at 0x00251594-0x0025159c. This establishes the separate HeroVehicleMode selector domain in include/rnc/hero/hero_state.h; reuse its canonical member. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00253b84-0x00253b90 permits zero or three in the HUD item-selector gate; this token is its zero comparison. Authoritative C maps hero.vehicle_mode to hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084, step +0x2088 and control mode +0x208c. Checked idle-mode helper 0x00251560 reads the same absolute byte, selects IDLE for zero at 0x00251580-0x00251588 and mode-3 idle for three at 0x00251594-0x0025159c. This establishes the separate HeroVehicleMode selector domain in include/rnc/hero/hero_state.h; reuse its canonical member. domain_4_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x00253dd0-0x00253dd8 compares that byte with 2 and excludes it from the fatal-fall entry gate. Authoritative C maps hero.vehicle_mode to hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084, step +0x2088 and control mode +0x208c. Checked idle-mode helper 0x00251560 reads the same absolute byte, selects IDLE for zero at 0x00251580-0x00251588 and mode-3 idle for three at 0x00251594-0x0025159c. This establishes the separate HeroVehicleMode selector domain in include/rnc/hero/hero_state.h; reuse its canonical member. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00254d48-0x00254d50 allows LOOK item-dependent animation selection only when this byte is zero. Authoritative C maps hero.vehicle_mode to hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084, step +0x2088 and control mode +0x208c. Checked idle-mode helper 0x00251560 reads the same absolute byte, selects IDLE for zero at 0x00251580-0x00251588 and mode-3 idle for three at 0x00251594-0x0025159c. This establishes the separate HeroVehicleMode selector domain in include/rnc/hero/hero_state.h; reuse its canonical member. domain_7_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00254e34-0x00254e44 tests the same byte for nonzero and dispatches request_hero_idle_state_for_vehicle_mode on LOOK exit. Authoritative C maps hero.vehicle_mode to hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084, step +0x2088 and control mode +0x208c. Checked idle-mode helper 0x00251560 reads the same absolute byte, selects IDLE for zero at 0x00251580-0x00251588 and mode-3 idle for three at 0x00251594-0x0025159c. This establishes the separate HeroVehicleMode selector domain in include/rnc/hero/hero_state.h; reuse its canonical member. domain_8_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002557d4-0x002557d8 tests the same byte for nonzero before target-pose braking at sufficient speed. Authoritative C maps hero.vehicle_mode to hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084, step +0x2088 and control mode +0x208c. Checked idle-mode helper 0x00251560 reads the same absolute byte, selects IDLE for zero at 0x00251580-0x00251588 and mode-3 idle for three at 0x00251594-0x0025159c. This establishes the separate HeroVehicleMode selector domain in include/rnc/hero/hero_state.h; reuse its canonical member. domain_9_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002584c4-0x002584c8 tests the same byte for zero before LOOK_RELEASE_WAIT item-dependent animation selection. Authoritative C maps hero.vehicle_mode to hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084, step +0x2088 and control mode +0x208c. Checked idle-mode helper 0x00251560 reads the same absolute byte, selects IDLE for zero at 0x00251580-0x00251588 and mode-3 idle for three at 0x00251594-0x0025159c. This establishes the separate HeroVehicleMode selector domain in include/rnc/hero/hero_state.h; reuse its canonical member. --- .../l11/hero/update_hero_state_transitions.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l11/hero/update_hero_state_transitions.c b/src/overlays/l11/hero/update_hero_state_transitions.c index 58d546c099..a25b47c4f8 100644 --- a/src/overlays/l11/hero/update_hero_state_transitions.c +++ b/src/overlays/l11/hero/update_hero_state_transitions.c @@ -156,9 +156,9 @@ void update_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L11_0015F594_gp == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.vehicle_mode == 0 || hero.vehicle_mode == 3)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; if (hero.quick_swap_tap_window != 0) { @@ -221,7 +221,7 @@ void update_hero_state_transitions(void) { } } if (hero_fatal_fall_entry_z_threshold > hero.motion.pos.f[2] && - hero.ground_distance > 2.0f && hero.vehicle_mode != 2 && + hero.ground_distance > 2.0f && hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { hero_set_state(0x77, 1); } else { @@ -629,7 +629,7 @@ void update_hero_state_transitions(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (hero.moby->prev_seq != 0xD) { @@ -656,7 +656,7 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); break; } @@ -912,7 +912,7 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; @@ -1984,7 +1984,7 @@ void update_hero_state_transitions(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (hero.moby->prev_seq != 0xD) { From ac11c09d529fd02b71b1a80f1d897712720f3345 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:38:54 +0000 Subject: [PATCH 1321/1502] decomp: clarify names in hero_set_state domain_0_value_100 -> HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE: 0x00227e2c-0x00227e40 permits this state with argument 2 through the dying guard; its named source case cancels item animation. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_10_value_106 -> HERO_STATE_DROWN: 0x00227ed8-0x00227edc exempts 0x6A; source named DROWN entry at 0x002287a0-0x002287c8 sets terminal mode and zero health. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_11_value_128 -> HERO_STATE_DYING_SPEED_LIMITED: 0x00227ee0-0x00227ee4 compares requested state 0x80; supplied hurt-response caller requests it for specific damage-source mobys, matching canonical HeroStateId member. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_12_value_130 -> HERO_STATE_DYING_ZERO_HEALTH: 0x00227ee8-0x00227eec compares requested state 0x82; named source entry at 0x00228948-0x00228970 explicitly clears health and enters terminal mode. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x00227f10 loads hero+0x20A4 and 0x00227f3c gates on zero before clearing collision/action flags and trail history. Authoritative source identifies this byte as Hero.vehicle_mode; original Ghidra uses cRam001413f4. Supplied process_hero_hurt_response switches on the identical hero.vehicle_mode field with HERO_VEHICLE_MODE_ON_FOOT. This binds the comparisons to shared HeroVehicleMode in include/rnc/hero/hero_state.h, whose canonical members are ON_FOOT=0 and CLANK=1, independently of state/control-mode IDs. domain_15_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Idle entry 0x0022801c-0x0022802c loads hero+0x20A4 and calls set_hero_state_for_vehicle_mode only when nonzero. Authoritative source identifies this byte as Hero.vehicle_mode; original Ghidra uses cRam001413f4. Supplied process_hero_hurt_response switches on the identical hero.vehicle_mode field with HERO_VEHICLE_MODE_ON_FOOT. This binds the comparisons to shared HeroVehicleMode in include/rnc/hero/hero_state.h, whose canonical members are ON_FOOT=0 and CLANK=1, independently of state/control-mode IDs. domain_16_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Approach-target entry 0x00228e14-0x00228e28 tests hero+0x20A4 against zero before canceling the hero item animation. Authoritative source identifies this byte as Hero.vehicle_mode; original Ghidra uses cRam001413f4. Supplied process_hero_hurt_response switches on the identical hero.vehicle_mode field with HERO_VEHICLE_MODE_ON_FOOT. This binds the comparisons to shared HeroVehicleMode in include/rnc/hero/hero_state.h, whose canonical members are ON_FOOT=0 and CLANK=1, independently of state/control-mode IDs. domain_18_value_1 -> HERO_VEHICLE_MODE_CLANK: 0x00228e34-0x00228e7c compares hero+0x20A4 with 3, then 1; the mode-1 branch selects animation 2. Authoritative source identifies this byte as Hero.vehicle_mode; original Ghidra uses cRam001413f4. Supplied process_hero_hurt_response switches on the identical hero.vehicle_mode field with HERO_VEHICLE_MODE_ON_FOOT. This binds the comparisons to shared HeroVehicleMode in include/rnc/hero/hero_state.h, whose canonical members are ON_FOOT=0 and CLANK=1, independently of state/control-mode IDs. domain_19_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: 0x00228e80-0x00228eb4 tests the same vehicle byte against zero, then selects on-foot locomotion animations from state.step. Authoritative source identifies this byte as Hero.vehicle_mode; original Ghidra uses cRam001413f4. Supplied process_hero_hurt_response switches on the identical hero.vehicle_mode field with HERO_VEHICLE_MODE_ON_FOOT. This binds the comparisons to shared HeroVehicleMode in include/rnc/hero/hero_state.h, whose canonical members are ON_FOOT=0 and CLANK=1, independently of state/control-mode IDs. domain_1_value_6 -> HERO_STATE_FALL: 0x00227e90-0x00227e94 exempts this requested state from the zero-health guard; source named FALL entry initializes falling mode and velocity at 0x00229a20. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_20_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Fatal-fall entry 0x00229a64-0x00229a7c tests hero+0x20A4 against zero before allocating the hero fatal-fall voice. Authoritative source identifies this byte as Hero.vehicle_mode; original Ghidra uses cRam001413f4. Supplied process_hero_hurt_response switches on the identical hero.vehicle_mode field with HERO_VEHICLE_MODE_ON_FOOT. This binds the comparisons to shared HeroVehicleMode in include/rnc/hero/hero_state.h, whose canonical members are ON_FOOT=0 and CLANK=1, independently of state/control-mode IDs. domain_22_value_41 -> HERO_STATE_GRIND_JUMP: 0x00229c94-0x00229cb4 tests the requested-state interval 0x29..0x2A to select grind jump flags; named source GRIND_JUMP tuning restores grind mode at 0x0022a140. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_23_value_42 -> HERO_STATE_GRIND_RAIL_TRANSFER: 0x00229c94-0x00229cb4 tests interval 0x29..0x2A; named GRIND_RAIL_TRANSFER tuning restores grind mode at 0x0022a298 and selects facing-relative animation at 0x0022acb0. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_2_value_61 -> HERO_STATE_DYING: 0x00227e98-0x00227e9c exempts this requested state; named DYING branch at 0x00228180 enters control_mode 0x14. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_3_value_71 -> HERO_STATE_VEHICLE_MODE_1_DYING: 0x00227ea0-0x00227ea4 compares the requested state against 0x47; supplied HeroStateId canonically names this state VEHICLE_MODE_1_DYING. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_4_value_87 -> HERO_STATE_VEHICLE_MODE_3_DYING: 0x00227ea8-0x00227eac exempts 0x57; source named vehicle-mode-3 dying entry at 0x0022beb8 enters terminal mode 0x14. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_5_value_98 -> HERO_STATE_VEHICLE_MODE_2_DYING: 0x00227eb0-0x00227eb4 exempts 0x62; named source entry at 0x0022bc88 enters terminal control_mode 0x14 and selects animation 7. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_6_value_119 -> HERO_STATE_FATAL_FALL: 0x00227eb8-0x00227ebc exempts 0x77; source named FATAL_FALL entry shares falling setup and adds tumble targets at 0x00229a64-0x00229ac4. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_7_value_123 -> HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT: 0x00227ec0-0x00227ec4 exempts 0x7B; source named entry at 0x0022b9e4 uses mode 0x19 and collision-off timer, also requested by supplied ground-effect caller. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_8_value_124 -> HERO_STATE_DEATH_DESCENT: 0x00227ec8-0x00227ecc compares requested state 0x7C; supplied HeroStateId canonical DEATH_DESCENT is reused in this exact state domain without inferring a control-mode meaning. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. domain_9_value_127 -> HERO_STATE_SINK: 0x00227ed0-0x00227ed4 compares requested state 0x7F; supplied HeroStateId canonical SINK is reused in this exact state domain; branch lifecycle need not be recovered again. Source assigns requested_state to hero.state.current; original retail Ghidra stores param_1 into iRam001413d4. Retail 0x00227df0 preserves a0 in s1, 0x00227f30 stores it to hero+0x2084, and 0x00227fc0-0x00227fe0 dispatches that state. This proves the supplied shared HeroStateId domain in include/rnc/hero/hero_state.h. --- src/overlays/l18/hero/hero_set_state.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/l18/hero/hero_set_state.c b/src/overlays/l18/hero/hero_set_state.c index 5276b2b7c3..6ced479a64 100644 --- a/src/overlays/l18/hero/hero_set_state.c +++ b/src/overlays/l18/hero/hero_set_state.c @@ -76,7 +76,7 @@ int hero_set_state(int requested_state, int b) { float grind_direction_or_jump_probe_position[4]; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != 0x64 || b != 2)) + if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L18_0015F5C4 == 2 || D_L18_0015F5C4 == 6) && b != 2) @@ -84,8 +84,8 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != 6 && requested_state != 0x3D && requested_state != 0x47 && requested_state != 0x57 && requested_state != 0x62 && requested_state != 0x77 && requested_state != 0x7B && - requested_state != 0x7C && requested_state != 0x7F && requested_state != 0x6A && requested_state != 0x80 && requested_state != 0x82) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -102,7 +102,7 @@ int hero_set_state(int requested_state, int b) { p->state.step = 0; p->unk20A5 = 0; p->item_use_locked = 0; - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { MOBY(moby)->collision_disable = 0; p->tilt_disabled = 0; p->item_select_blocked = 0; @@ -130,7 +130,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->unk1010 = random_int_between(scale_game_frames(0x32), scale_game_frames(0x64)); clear_hero_idle_rotation_targets(); - if (p->vehicle_mode != 0) { + if (p->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { set_hero_state_for_vehicle_mode(); return 1; } @@ -569,14 +569,14 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->item_use_locked = 1; - if (p->vehicle_mode == 0) + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); if (b) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 1) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { set_hero_animation(2, 0, (float)scale_game_frames(8)); - } else if (p->vehicle_mode == 0) { + } else if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { set_hero_animation( p->state.step + 3, D_L18_0015F6D8[p->state.step], (float)scale_game_frames(8)); } @@ -917,7 +917,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; if (p->state.current == 0x77) { - if (p->vehicle_mode == 0) { + if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { p->health.unk22B2 = allocate_hero_voice_for_entry(0x17, 0x20); } p->pivot_rot_x_target = randf_sym(frame_time * 3.1415927f, frame_time * 4.3633232f); @@ -1002,7 +1002,7 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= 0x29 && requested_state <= 0x2A) { + if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; From 2e2c393890ee8a778c94460bc93652cbad38c1a6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:38:55 +0000 Subject: [PATCH 1322/1502] decomp: clarify names in l01_hero_set_state domain_5_value_0 -> FALSE: domain_5_value_0 -> FALSE. The authoritative source tests pal_mode != 0 while initializing HERO_STATE_JUMP_WITH_VELOCITY_KEY_PROFILE: true selects scale_game_frames(0x22), false selects scale_game_frames(0x23). Retail 0x0023f138-0x0023f148 loads the pal_mode global at 0x0015ED80 and branches on zero; 0x0023f150-0x0023f15c selects nominal timing 34 versus 35 before scaling. Original retail Ghidra agrees via if (iRam0015ed80 == 0). This is the disabled/false side of the existing PAL-mode predicate, so supplied established FALSE=0 fits the boolean use, independently of HeroStateId and HeroVehicleMode. --- src/overlays/l01/hero/hero_set_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l01/hero/hero_set_state.c b/src/overlays/l01/hero/hero_set_state.c index 0732e4be72..5faf741056 100644 --- a/src/overlays/l01/hero/hero_set_state.c +++ b/src/overlays/l01/hero/hero_set_state.c @@ -1025,7 +1025,7 @@ int l01_hero_set_state(int requested_state, int b) { u->unk4A6 = scale_game_frames(0x55); u->ledge_probe_cooldown = scale_game_frames(0x46); u->velocity_keys_active = 1; - if (pal_mode != 0) { + if (pal_mode != FALSE) { u->unk3D0 = scale_game_frames(0x22); } else { u->unk3D0 = scale_game_frames(0x23); From 94429afb33435e9fd3a8a3966e41d82ba63375b7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:41:11 +0000 Subject: [PATCH 1323/1502] decomp: clarify names in update_hero_state_machine domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0021c784-0x0021c7a0 compares the +0x20A4 byte with 1 to bypass item-use locking before the HUD selector request. The authoritative C maps this selector to hero.vehicle_mode; original Ghidra cRam001413f4 and retail byte loads at hero+0x20A4 identify the same separate HeroVehicleMode selector, distinct from current state +0x2084 and control mode +0x208C. Reuse the canonical member supplied in include/rnc/hero/hero_state.h. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0021c7ac-0x0021c7c8 compares that same +0x20A4 byte with 1 to bypass the item-selection block before requesting the HUD selector. The authoritative C maps this selector to hero.vehicle_mode; original Ghidra cRam001413f4 and retail byte loads at hero+0x20A4 identify the same separate HeroVehicleMode selector, distinct from current state +0x2084 and control mode +0x208C. Reuse the canonical member supplied in include/rnc/hero/hero_state.h. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021c7d4-0x0021c7e0 tests the +0x20A4 byte for zero as an allowed HUD item-selector mode. Checked helper 0x0021a198-0x0021a1c0 reads absolute 0x001413F4 (hero+0x20A4) and requests canonical IDLE=0 for zero. The authoritative C maps this selector to hero.vehicle_mode; original Ghidra cRam001413f4 and retail byte loads at hero+0x20A4 identify the same separate HeroVehicleMode selector, distinct from current state +0x2084 and control mode +0x208C. Reuse the canonical member supplied in include/rnc/hero/hero_state.h. domain_4_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x0021ca20-0x0021ca38 compares the +0x20A4 byte with 2 to exempt this vehicle mode from low-altitude respawn-state entry. The authoritative C maps this selector to hero.vehicle_mode; original Ghidra cRam001413f4 and retail byte loads at hero+0x20A4 identify the same separate HeroVehicleMode selector, distinct from current state +0x2084 and control mode +0x208C. Reuse the canonical member supplied in include/rnc/hero/hero_state.h. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail LOOK handler 0x0021d960-0x0021d984 tests +0x20A4 for zero before on-foot crouch/idle animation selection. Checked mode-idle helper 0x0021a198-0x0021a1c0 maps this same zero-valued byte to canonical IDLE. The authoritative C maps this selector to hero.vehicle_mode; original Ghidra cRam001413f4 and retail byte loads at hero+0x20A4 identify the same separate HeroVehicleMode selector, distinct from current state +0x2084 and control mode +0x208C. Reuse the canonical member supplied in include/rnc/hero/hero_state.h. domain_6_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0021da4c-0x0021da58 tests +0x20A4 nonzero and invokes request_hero_idle_state_for_vehicle_mode; zero continues to CROUCH/IDLE. Checked helper 0x0021a198-0x0021a1c0 maps the identical byte's zero value to IDLE. The authoritative C maps this selector to hero.vehicle_mode; original Ghidra cRam001413f4 and retail byte loads at hero+0x20A4 identify the same separate HeroVehicleMode selector, distinct from current state +0x2084 and control mode +0x208C. Reuse the canonical member supplied in include/rnc/hero/hero_state.h. domain_7_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail target-pose handler 0x0021e3ec-0x0021e418 tests +0x20A4 nonzero before speed-dependent braking state 0x66. Checked helper 0x0021a198-0x0021a1c0 confirms this separate byte's zero value selects normal IDLE. The authoritative C maps this selector to hero.vehicle_mode; original Ghidra cRam001413f4 and retail byte loads at hero+0x20A4 identify the same separate HeroVehicleMode selector, distinct from current state +0x2084 and control mode +0x208C. Reuse the canonical member supplied in include/rnc/hero/hero_state.h. domain_8_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail LOOK_RELEASE_WAIT 0x00221260-0x00221284 tests +0x20A4 zero before crouch/idle animation handling, mirroring LOOK. Checked helper 0x0021a198-0x0021a1c0 maps this same selector's zero value to normal IDLE. The authoritative C maps this selector to hero.vehicle_mode; original Ghidra cRam001413f4 and retail byte loads at hero+0x20A4 identify the same separate HeroVehicleMode selector, distinct from current state +0x2084 and control mode +0x208C. Reuse the canonical member supplied in include/rnc/hero/hero_state.h. --- .../l03/hero/update_hero_state_machine.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l03/hero/update_hero_state_machine.c b/src/overlays/l03/hero/update_hero_state_machine.c index 7367316230..f2207aa6c1 100644 --- a/src/overlays/l03/hero/update_hero_state_machine.c +++ b/src/overlays/l03/hero/update_hero_state_machine.c @@ -168,9 +168,9 @@ void update_hero_state_machine(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L03_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.vehicle_mode == 0 || hero.vehicle_mode == 3)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; if (hero.quick_swap_tap_window != 0) { @@ -232,7 +232,7 @@ void update_hero_state_machine(void) { } } if (hero_low_altitude_respawn_z_threshold > hero.motion.pos.f[2] && - hero.ground_distance > 2.0f && hero.vehicle_mode != 2 && + hero.ground_distance > 2.0f && hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { hero_set_state(0x77, 1); } else { @@ -631,7 +631,7 @@ void update_hero_state_machine(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { @@ -658,7 +658,7 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); break; } @@ -914,7 +914,7 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; @@ -2034,7 +2034,7 @@ void update_hero_state_machine(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { From 41365c692f4b870896dce0164e2e4e2c2f013597 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:43:02 +0000 Subject: [PATCH 1324/1502] decomp: clarify names in hero_set_state domain_5_value_0 -> FALSE: Authoritative C tests pal_mode != 0 to choose scale_game_frames(0x22), otherwise scale_game_frames(0x23), in HERO_STATE_JUMP_WITH_VELOCITY_KEY_PROFILE. Original Ghidra tests iRam0015ed80 == 0 with the same branches. Retail 0x00233594..0x002335b4 loads pal_mode at 0x0015ED80, branches on zero, and selects 0x22 for enabled/nonzero versus 0x23 for disabled/zero. Thus zero is the false/disabled PAL flag condition, supporting supplied existing FALSE=0 rather than a HeroStateId or HeroVehicleMode member. --- src/overlays/l08/hero/hero_set_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l08/hero/hero_set_state.c b/src/overlays/l08/hero/hero_set_state.c index 81ada3ac69..897079f781 100644 --- a/src/overlays/l08/hero/hero_set_state.c +++ b/src/overlays/l08/hero/hero_set_state.c @@ -1258,7 +1258,7 @@ int hero_set_state(int requested_state, int b) { u->unk4A6 = scale_game_frames(0x55); u->ledge_probe_cooldown = scale_game_frames(0x46); u->velocity_keys_active = 1; - if (pal_mode != 0) { + if (pal_mode != FALSE) { u->unk3D0 = scale_game_frames(0x22); } else { u->unk3D0 = scale_game_frames(0x23); From 51aed1dee3e6538f63481d4fdfef3cbccf56ebfe Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:43:03 +0000 Subject: [PATCH 1325/1502] decomp: clarify names in update_hero_state_machine domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Authoritative C binds hero.vehicle_mode to the byte at hero+0x20a4 (absolute 0x1413f4), also cRam001413f4 in original Ghidra; this is the separate HeroVehicleMode selector supplied by include/rnc/hero/hero_state.h, not current state (+0x2084), step (+0x2088), or control mode (+0x208c). Retail 0x255a88-0x255a8c loads that byte and compares it with 1 to bypass item_use_locked in selector-HUD eligibility; reuse canonical HeroVehicleMode CLANK=1. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Authoritative C binds hero.vehicle_mode to the byte at hero+0x20a4 (absolute 0x1413f4), also cRam001413f4 in original Ghidra; this is the separate HeroVehicleMode selector supplied by include/rnc/hero/hero_state.h, not current state (+0x2084), step (+0x2088), or control mode (+0x208c). Retail 0x255ab0-0x255ab4 loads that same byte and compares with 1 to bypass item_select_blocked in the same HUD eligibility gate; reuse canonical CLANK=1. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Authoritative C binds hero.vehicle_mode to the byte at hero+0x20a4 (absolute 0x1413f4), also cRam001413f4 in original Ghidra; this is the separate HeroVehicleMode selector supplied by include/rnc/hero/hero_state.h, not current state (+0x2084), step (+0x2088), or control mode (+0x208c). Retail 0x255acc-0x255ad8 tests that byte for zero before the distinct mode-3 alternative in selector-HUD eligibility; reuse canonical HeroVehicleMode ON_FOOT=0. domain_4_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Authoritative C binds hero.vehicle_mode to the byte at hero+0x20a4 (absolute 0x1413f4), also cRam001413f4 in original Ghidra; this is the separate HeroVehicleMode selector supplied by include/rnc/hero/hero_state.h, not current state (+0x2084), step (+0x2088), or control mode (+0x208c). Retail 0x255d18-0x255d20 compares that byte against 2 and bypasses the fatal-fall transition when equal; authoritative C uses hero.vehicle_mode != 2. Reuse canonical GIANT_CLANK=2 in this exact mode domain. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Authoritative C binds hero.vehicle_mode to the byte at hero+0x20a4 (absolute 0x1413f4), also cRam001413f4 in original Ghidra; this is the separate HeroVehicleMode selector supplied by include/rnc/hero/hero_state.h, not current state (+0x2084), step (+0x2088), or control mode (+0x208c). Retail LOOK handling 0x256c8c-0x256c94 tests that byte for zero before ordinary idle/crouch animation selection; original Ghidra case 1 tests cRam001413f4 == 0. Reuse canonical ON_FOOT=0. domain_6_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Authoritative C binds hero.vehicle_mode to the byte at hero+0x20a4 (absolute 0x1413f4), also cRam001413f4 in original Ghidra; this is the separate HeroVehicleMode selector supplied by include/rnc/hero/hero_state.h, not current state (+0x2084), step (+0x2088), or control mode (+0x208c). Retail 0x256d7c-0x256d88 reads that same byte and calls request_hero_idle_state_for_vehicle_mode (0x251288) when nonzero; source LOOK exit tests hero.vehicle_mode != 0. Reuse canonical ON_FOOT=0. domain_7_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Authoritative C binds hero.vehicle_mode to the byte at hero+0x20a4 (absolute 0x1413f4), also cRam001413f4 in original Ghidra; this is the separate HeroVehicleMode selector supplied by include/rnc/hero/hero_state.h, not current state (+0x2084), step (+0x2088), or control mode (+0x208c). Retail target-pose branch 0x25771c-0x257748 reads that byte, skips vehicle braking when zero and otherwise tests speed before state 0x66; source tests hero.vehicle_mode != 0. Reuse canonical ON_FOOT=0. domain_8_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Authoritative C binds hero.vehicle_mode to the byte at hero+0x20a4 (absolute 0x1413f4), also cRam001413f4 in original Ghidra; this is the separate HeroVehicleMode selector supplied by include/rnc/hero/hero_state.h, not current state (+0x2084), step (+0x2088), or control mode (+0x208c). Retail LOOK_RELEASE_WAIT 0x25addc-0x25ade4 tests that byte for zero before ordinary idle/crouch animation selection, corroborated by original Ghidra case 0x1e. Reuse canonical ON_FOOT=0. --- .../l05/hero/update_hero_state_machine.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l05/hero/update_hero_state_machine.c b/src/overlays/l05/hero/update_hero_state_machine.c index 01b880b4a4..de8ba30ccf 100644 --- a/src/overlays/l05/hero/update_hero_state_machine.c +++ b/src/overlays/l05/hero/update_hero_state_machine.c @@ -173,9 +173,9 @@ void update_hero_state_machine(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && item_selector_hud_open_blocker == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.vehicle_mode == 0 || hero.vehicle_mode == 3)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; if (hero.quick_swap_tap_window != 0) { @@ -237,7 +237,7 @@ void update_hero_state_machine(void) { } } if (fatal_fall_entry_z_threshold > hero.motion.pos.f[2] && - hero.ground_distance > 2.0f && hero.vehicle_mode != 2 && + hero.ground_distance > 2.0f && hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { hero_set_state(0x77, 1); } else { @@ -649,7 +649,7 @@ void update_hero_state_machine(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { @@ -676,7 +676,7 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); break; } @@ -932,7 +932,7 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; @@ -2294,7 +2294,7 @@ void update_hero_state_machine(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { From e5df9775e41fb0782000af95403e54440ad13833 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:44:46 +0000 Subject: [PATCH 1326/1502] decomp: clarify names in update_hero_state_transitions domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Authoritative C binds this selector to hero.vehicle_mode; original Ghidra cRam001413f4 corresponds to the byte loaded at hero+0x20A4, separate from current-state hero+0x2084 and control-mode hero+0x208C. Supplied include/rnc/hero/hero_state.h HeroVehicleMode is the matching selector domain. Retail 0x00246318-0x00246328 compares this byte with 1 to bypass item_use_locked when permitting the selector HUD. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Authoritative C binds this selector to hero.vehicle_mode; original Ghidra cRam001413f4 corresponds to the byte loaded at hero+0x20A4, separate from current-state hero+0x2084 and control-mode hero+0x208C. Supplied include/rnc/hero/hero_state.h HeroVehicleMode is the matching selector domain. Retail 0x00246340-0x00246350 compares the same byte with 1 to bypass item_select_blocked in the second HUD activation gate. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Authoritative C binds this selector to hero.vehicle_mode; original Ghidra cRam001413f4 corresponds to the byte loaded at hero+0x20A4, separate from current-state hero+0x2084 and control-mode hero+0x208C. Supplied include/rnc/hero/hero_state.h HeroVehicleMode is the matching selector domain. Retail 0x0024635c-0x00246368 accepts zero or 3 from this same byte before queuing the selector HUD; zero reuses the canonical ON_FOOT member. domain_4_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Authoritative C binds this selector to hero.vehicle_mode; original Ghidra cRam001413f4 corresponds to the byte loaded at hero+0x20A4, separate from current-state hero+0x2084 and control-mode hero+0x208C. Supplied include/rnc/hero/hero_state.h HeroVehicleMode is the matching selector domain. Retail 0x002465ac-0x002465b0 compares the same hero+0x20A4 byte against 2, suppressing fatal-fall entry for that mode; reuse canonical GIANT_CLANK. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Authoritative C binds this selector to hero.vehicle_mode; original Ghidra cRam001413f4 corresponds to the byte loaded at hero+0x20A4, separate from current-state hero+0x2084 and control-mode hero+0x208C. Supplied include/rnc/hero/hero_state.h HeroVehicleMode is the matching selector domain. Retail 0x00247554-0x00247558 tests the same byte for zero in LOOK before selecting the on-foot gadget/crouch animation. domain_7_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Authoritative C binds this selector to hero.vehicle_mode; original Ghidra cRam001413f4 corresponds to the byte loaded at hero+0x20A4, separate from current-state hero+0x2084 and control-mode hero+0x208C. Supplied include/rnc/hero/hero_state.h HeroVehicleMode is the matching selector domain. Retail 0x00247640-0x00247650 tests the same byte for nonzero after LOOK input release, calling request_hero_idle_state_for_vehicle_mode for modes other than ON_FOOT. domain_8_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Authoritative C binds this selector to hero.vehicle_mode; original Ghidra cRam001413f4 corresponds to the byte loaded at hero+0x20A4, separate from current-state hero+0x2084 and control-mode hero+0x208C. Supplied include/rnc/hero/hero_state.h HeroVehicleMode is the matching selector domain. Retail 0x002483c0-0x002483ec tests the same byte for nonzero during APPROACH_TARGET_POSE before requesting the braking state at sufficient XY speed. domain_9_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Authoritative C binds this selector to hero.vehicle_mode; original Ghidra cRam001413f4 corresponds to the byte loaded at hero+0x20A4, separate from current-state hero+0x2084 and control-mode hero+0x208C. Supplied include/rnc/hero/hero_state.h HeroVehicleMode is the matching selector domain. Retail 0x0024b304-0x0024b308 tests the same byte for zero in LOOK_RELEASE_WAIT before the same gadget/crouch animation selection as LOOK. --- .../l12/hero/update_hero_state_transitions.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l12/hero/update_hero_state_transitions.c b/src/overlays/l12/hero/update_hero_state_transitions.c index d6281997c6..de2fa75773 100644 --- a/src/overlays/l12/hero/update_hero_state_transitions.c +++ b/src/overlays/l12/hero/update_hero_state_transitions.c @@ -157,9 +157,9 @@ void update_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && item_selector_hud_activation_blocked == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.vehicle_mode == 0 || hero.vehicle_mode == 3)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; if (hero.quick_swap_tap_window != 0) { @@ -222,7 +222,7 @@ void update_hero_state_transitions(void) { } } if (fatal_fall_entry_z > hero.motion.pos.f[2] && hero.ground_distance > 2.0f && - hero.vehicle_mode != 2 && hero.state.current != 0x77) { + hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { hero_set_state(0x77, 1); } else { switch (hero.state.current) { @@ -633,7 +633,7 @@ void update_hero_state_transitions(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (hero.moby->prev_seq != 0xD) { @@ -660,7 +660,7 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); break; } @@ -972,7 +972,7 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; @@ -2096,7 +2096,7 @@ void update_hero_state_transitions(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (hero.moby->prev_seq != 0xD) { From 9921bb53d8fd366d85cbf7354ef4bbffede0fac5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:46:37 +0000 Subject: [PATCH 1327/1502] decomp: clarify names in hero_set_state domain_3_value_0 -> FALSE: The authoritative source tests the established pal_mode flag with != 0 in HERO_STATE_JUMP_WITH_VELOCITY_KEY_PROFILE. Retail 0x00218d24-0x00218d48 loads global 0x0015ED80 and branches on zero: zero selects scale_game_frames(0x23), nonzero selects scale_game_frames(0x22). Original Ghidra case 0xF shows the same iRam0015ed80 == 0 selection. This is a Boolean enabled/disabled test of PAL mode, so reuse the supplied FALSE=0 constant, independently of HeroStateId and HeroVehicleMode. --- src/overlays/l03/hero/hero_set_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l03/hero/hero_set_state.c b/src/overlays/l03/hero/hero_set_state.c index 9f10ea8829..d5b5ebc7ac 100644 --- a/src/overlays/l03/hero/hero_set_state.c +++ b/src/overlays/l03/hero/hero_set_state.c @@ -1173,7 +1173,7 @@ int hero_set_state(int requested_state, int b) { u->unk4A6 = scale_game_frames(0x55); u->ledge_probe_cooldown = scale_game_frames(0x46); u->velocity_keys_active = 1; - if (pal_mode != 0) { + if (pal_mode != FALSE) { u->unk3D0 = scale_game_frames(0x22); } else { u->unk3D0 = scale_game_frames(0x23); From d6551d7a9e9daaa81f7065e93f0a9106398a29c2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:52:45 +0000 Subject: [PATCH 1328/1502] decomp: clarify names in process_hero_state_transitions domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x00235720..0x00235724 loads +0x20a4 and compares against 1 to bypass item-use locking in the HUD selector gate. The bound source identifies hero.vehicle_mode; original retail Ghidra uses cRam001413f4, corresponding to byte hero+0x20a4, distinct from current state +0x2084 and control mode +0x208c. Reuse the canonical HeroVehicleMode member from include/rnc/hero/hero_state.h. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x00235748..0x0023574c loads +0x20a4 and compares against 1 to bypass item-selection blocking in the same HUD gate. The bound source identifies hero.vehicle_mode; original retail Ghidra uses cRam001413f4, corresponding to byte hero+0x20a4, distinct from current state +0x2084 and control mode +0x208c. Reuse the canonical HeroVehicleMode member from include/rnc/hero/hero_state.h. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00235764..0x00235768 loads +0x20a4 and accepts zero before the separate comparison against mode 3. The bound source identifies hero.vehicle_mode; original retail Ghidra uses cRam001413f4, corresponding to byte hero+0x20a4, distinct from current state +0x2084 and control mode +0x208c. Reuse the canonical HeroVehicleMode member from include/rnc/hero/hero_state.h. domain_4_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x002359b4..0x002359b8 loads +0x20a4 and skips fatal-fall entry when it equals 2; bound C expresses vehicle_mode != 2. The bound source identifies hero.vehicle_mode; original retail Ghidra uses cRam001413f4, corresponding to byte hero+0x20a4, distinct from current state +0x2084 and control mode +0x208c. Reuse the canonical HeroVehicleMode member from include/rnc/hero/hero_state.h. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail LOOK handler 0x002362c8..0x002362cc tests +0x20a4 against zero before selecting normal gadget/crouch animations. The bound source identifies hero.vehicle_mode; original retail Ghidra uses cRam001413f4, corresponding to byte hero+0x20a4, distinct from current state +0x2084 and control mode +0x208c. Reuse the canonical HeroVehicleMode member from include/rnc/hero/hero_state.h. domain_6_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002363b4..0x002363c0 tests +0x20a4 against zero and calls request_hero_idle_state_for_vehicle_mode for nonzero modes after LOOK release. The bound source identifies hero.vehicle_mode; original retail Ghidra uses cRam001413f4, corresponding to byte hero+0x20a4, distinct from current state +0x2084 and control mode +0x208c. Reuse the canonical HeroVehicleMode member from include/rnc/hero/hero_state.h. domain_7_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0023700c..0x00237010 tests +0x20a4 against zero; nonzero modes can enter target-position braking when speed reaches frame_time*2.7. The bound source identifies hero.vehicle_mode; original retail Ghidra uses cRam001413f4, corresponding to byte hero+0x20a4, distinct from current state +0x2084 and control mode +0x208c. Reuse the canonical HeroVehicleMode member from include/rnc/hero/hero_state.h. domain_8_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail LOOK_RELEASE_WAIT handler 0x0023ad80..0x0023ad84 tests +0x20a4 against zero before normal gadget/crouch animation selection. The bound source identifies hero.vehicle_mode; original retail Ghidra uses cRam001413f4, corresponding to byte hero+0x20a4, distinct from current state +0x2084 and control mode +0x208c. Reuse the canonical HeroVehicleMode member from include/rnc/hero/hero_state.h. --- .../l14/hero/process_hero_state_transitions.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l14/hero/process_hero_state_transitions.c b/src/overlays/l14/hero/process_hero_state_transitions.c index af0fe8fa2e..c7c1b432fd 100644 --- a/src/overlays/l14/hero/process_hero_state_transitions.c +++ b/src/overlays/l14/hero/process_hero_state_transitions.c @@ -174,9 +174,9 @@ void process_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L14_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.vehicle_mode == 0 || hero.vehicle_mode == 3)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; if (hero.quick_swap_tap_window != 0) { @@ -239,7 +239,7 @@ void process_hero_state_transitions(void) { } } if (hero_fatal_fall_height_threshold > hero.motion.pos.f[2] && - hero.ground_distance > 2.0f && hero.vehicle_mode != 2 && + hero.ground_distance > 2.0f && hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { hero_set_state(0x77, 1); } else { @@ -506,7 +506,7 @@ void process_hero_state_transitions(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { @@ -533,7 +533,7 @@ void process_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); break; } @@ -825,7 +825,7 @@ void process_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; @@ -2311,7 +2311,7 @@ void process_hero_state_transitions(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { From 8969ff3f4fc95303666096a75f2b188e54a75ed7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:54:37 +0000 Subject: [PATCH 1329/1502] decomp: clarify names in update_hero_state_machine domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: The SHA-bound source maps hero.vehicle_mode to the byte at hero+0x20A4 (absolute 0x001413F4), independently of state.current +0x2084, step +0x2088 and control_mode +0x208C. Checked directly called helper 0x0021AB68 reads that same byte: mode 0 selects IDLE=0 at 0x0021ABA4-0x0021ABB4, mode 2 selects mode-2 idle 90, and mode 3 selects idle 83. This establishes the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical member rather than an equal-valued state ID. Retail 0x0021D168-0x0021D16C loads +0x20A4 and compares it with 1 to bypass the item-use lock in the HUD selector input gate; original Ghidra cRam001413f4 == 1 corroborates this comparison. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: The SHA-bound source maps hero.vehicle_mode to the byte at hero+0x20A4 (absolute 0x001413F4), independently of state.current +0x2084, step +0x2088 and control_mode +0x208C. Checked directly called helper 0x0021AB68 reads that same byte: mode 0 selects IDLE=0 at 0x0021ABA4-0x0021ABB4, mode 2 selects mode-2 idle 90, and mode 3 selects idle 83. This establishes the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical member rather than an equal-valued state ID. Retail 0x0021D190-0x0021D194 loads +0x20A4 and compares with 1 to bypass item-select blocking; source and original Ghidra both use the same vehicle selector as the preceding item-use gate. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The SHA-bound source maps hero.vehicle_mode to the byte at hero+0x20A4 (absolute 0x001413F4), independently of state.current +0x2084, step +0x2088 and control_mode +0x208C. Checked directly called helper 0x0021AB68 reads that same byte: mode 0 selects IDLE=0 at 0x0021ABA4-0x0021ABB4, mode 2 selects mode-2 idle 90, and mode 3 selects idle 83. This establishes the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical member rather than an equal-valued state ID. Retail 0x0021D1AC-0x0021D1B8 reads +0x20A4, accepts zero or 3 before creating the HUD item selector; original Ghidra checks cRam001413f4 == 0 or == 3. domain_4_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: The SHA-bound source maps hero.vehicle_mode to the byte at hero+0x20A4 (absolute 0x001413F4), independently of state.current +0x2084, step +0x2088 and control_mode +0x208C. Checked directly called helper 0x0021AB68 reads that same byte: mode 0 selects IDLE=0 at 0x0021ABA4-0x0021ABB4, mode 2 selects mode-2 idle 90, and mode 3 selects idle 83. This establishes the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical member rather than an equal-valued state ID. Retail 0x0021D3F8-0x0021D400 reads +0x20A4 and compares with 2 to exempt this vehicle mode from the fatal-fall threshold transition. Original Ghidra cRam001413f4 != 2 and current C hero.vehicle_mode != 2 agree. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The SHA-bound source maps hero.vehicle_mode to the byte at hero+0x20A4 (absolute 0x001413F4), independently of state.current +0x2084, step +0x2088 and control_mode +0x208C. Checked directly called helper 0x0021AB68 reads that same byte: mode 0 selects IDLE=0 at 0x0021ABA4-0x0021ABB4, mode 2 selects mode-2 idle 90, and mode 3 selects idle 83. This establishes the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical member rather than an equal-valued state ID. In LOOK, retail 0x0021E330-0x0021E334 reads +0x20A4 and gates ordinary hero look animation selection on zero; original Ghidra case 1 checks cRam001413f4 == 0 before selecting animation 13 or get_hero_help_value(1). domain_6_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The SHA-bound source maps hero.vehicle_mode to the byte at hero+0x20A4 (absolute 0x001413F4), independently of state.current +0x2084, step +0x2088 and control_mode +0x208C. Checked directly called helper 0x0021AB68 reads that same byte: mode 0 selects IDLE=0 at 0x0021ABA4-0x0021ABB4, mode 2 selects mode-2 idle 90, and mode 3 selects idle 83. This establishes the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical member rather than an equal-valued state ID. In LOOK exit, retail 0x0021E41C-0x0021E428 reads +0x20A4: nonzero calls the checked set_hero_state_for_vehicle_mode helper, while zero continues to CROUCH/IDLE. Original Ghidra case 1 corroborates cRam001413f4 != 0. domain_7_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The SHA-bound source maps hero.vehicle_mode to the byte at hero+0x20A4 (absolute 0x001413F4), independently of state.current +0x2084, step +0x2088 and control_mode +0x208C. Checked directly called helper 0x0021AB68 reads that same byte: mode 0 selects IDLE=0 at 0x0021ABA4-0x0021ABB4, mode 2 selects mode-2 idle 90, and mode 3 selects idle 83. This establishes the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical member rather than an equal-valued state ID. In APPROACH_TARGET_POSE, retail 0x0021EDBC-0x0021EDC0 reads +0x20A4 and skips vehicle braking when zero; nonzero with sufficient speed enters state 102. Original Ghidra case 0x65 and current C use this same vehicle-mode comparison. domain_8_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The SHA-bound source maps hero.vehicle_mode to the byte at hero+0x20A4 (absolute 0x001413F4), independently of state.current +0x2084, step +0x2088 and control_mode +0x208C. Checked directly called helper 0x0021AB68 reads that same byte: mode 0 selects IDLE=0 at 0x0021ABA4-0x0021ABB4, mode 2 selects mode-2 idle 90, and mode 3 selects idle 83. This establishes the supplied HeroVehicleMode domain in include/rnc/hero/hero_state.h; reuse its canonical member rather than an equal-valued state ID. In LOOK_RELEASE_WAIT, retail 0x00222688-0x0022268C reads +0x20A4 and gates ordinary hero look animations on zero; original Ghidra case 0x1E corroborates cRam001413f4 == 0 before held crouch/look animation handling. --- .../l15/hero/update_hero_state_machine.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l15/hero/update_hero_state_machine.c b/src/overlays/l15/hero/update_hero_state_machine.c index b627e5f1a4..881127b141 100644 --- a/src/overlays/l15/hero/update_hero_state_machine.c +++ b/src/overlays/l15/hero/update_hero_state_machine.c @@ -173,9 +173,9 @@ void update_hero_state_machine(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L15_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.vehicle_mode == 0 || hero.vehicle_mode == 3)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; if (hero.quick_swap_tap_window != 0) { @@ -238,7 +238,7 @@ void update_hero_state_machine(void) { } } if (hero_fatal_fall_trigger_z > hero.motion.pos.f[2] && hero.ground_distance > 2.0f && - hero.vehicle_mode != 2 && hero.state.current != 0x77) { + hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { hero_set_state(0x77, 1); } else { switch (hero.state.current) { @@ -626,7 +626,7 @@ void update_hero_state_machine(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { @@ -653,7 +653,7 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { set_hero_state_for_vehicle_mode(); break; } @@ -904,7 +904,7 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; @@ -2280,7 +2280,7 @@ void update_hero_state_machine(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { From 0d294e27715090977ad47dff670f2eaf842b30c7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:54:37 +0000 Subject: [PATCH 1330/1502] decomp: clarify names in update_hero_state_transitions domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: The authoritative snapshot maps hero.vehicle_mode to the byte at hero+0x20a4 (0x001413f4), distinct from current state +0x2084 and control mode +0x208c. Original retail Ghidra cRam001413f4 agrees. Checked request_hero_idle_state_for_vehicle_mode at 0x00234c20 reads that same byte and mode 0 selects IDLE at 0x00234c40-0x00234c48, establishing the supplied shared HeroVehicleMode domain; reuse its canonical member. At 0x00237218-0x0023721c this byte equals 1 to bypass the item-use lock for opening the selector. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: The authoritative snapshot maps hero.vehicle_mode to the byte at hero+0x20a4 (0x001413f4), distinct from current state +0x2084 and control mode +0x208c. Original retail Ghidra cRam001413f4 agrees. Checked request_hero_idle_state_for_vehicle_mode at 0x00234c20 reads that same byte and mode 0 selects IDLE at 0x00234c40-0x00234c48, establishing the supplied shared HeroVehicleMode domain; reuse its canonical member. At 0x00237240-0x00237244 this same byte equals 1 to bypass the item-selection block. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative snapshot maps hero.vehicle_mode to the byte at hero+0x20a4 (0x001413f4), distinct from current state +0x2084 and control mode +0x208c. Original retail Ghidra cRam001413f4 agrees. Checked request_hero_idle_state_for_vehicle_mode at 0x00234c20 reads that same byte and mode 0 selects IDLE at 0x00234c40-0x00234c48, establishing the supplied shared HeroVehicleMode domain; reuse its canonical member. At 0x0023725c-0x00237260 mode zero admits the item-selector path; the helper independently maps zero to IDLE. domain_4_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: The authoritative snapshot maps hero.vehicle_mode to the byte at hero+0x20a4 (0x001413f4), distinct from current state +0x2084 and control mode +0x208c. Original retail Ghidra cRam001413f4 agrees. Checked request_hero_idle_state_for_vehicle_mode at 0x00234c20 reads that same byte and mode 0 selects IDLE at 0x00234c40-0x00234c48, establishing the supplied shared HeroVehicleMode domain; reuse its canonical member. At 0x002374ac-0x002374b0 the same byte is compared with 2 to exclude that vehicle mode from the below-height fatal-fall transition. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative snapshot maps hero.vehicle_mode to the byte at hero+0x20a4 (0x001413f4), distinct from current state +0x2084 and control mode +0x208c. Original retail Ghidra cRam001413f4 agrees. Checked request_hero_idle_state_for_vehicle_mode at 0x00234c20 reads that same byte and mode 0 selects IDLE at 0x00234c40-0x00234c48, establishing the supplied shared HeroVehicleMode domain; reuse its canonical member. At 0x002383f8-0x002383fc mode zero gates normal hero animation selection in LOOK. domain_6_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative snapshot maps hero.vehicle_mode to the byte at hero+0x20a4 (0x001413f4), distinct from current state +0x2084 and control mode +0x208c. Original retail Ghidra cRam001413f4 agrees. Checked request_hero_idle_state_for_vehicle_mode at 0x00234c20 reads that same byte and mode 0 selects IDLE at 0x00234c40-0x00234c48, establishing the supplied shared HeroVehicleMode domain; reuse its canonical member. At 0x002384e4-0x002384f0 nonzero mode calls request_hero_idle_state_for_vehicle_mode; zero continues to normal CROUCH/IDLE selection. domain_7_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative snapshot maps hero.vehicle_mode to the byte at hero+0x20a4 (0x001413f4), distinct from current state +0x2084 and control mode +0x208c. Original retail Ghidra cRam001413f4 agrees. Checked request_hero_idle_state_for_vehicle_mode at 0x00234c20 reads that same byte and mode 0 selects IDLE at 0x00234c40-0x00234c48, establishing the supplied shared HeroVehicleMode domain; reuse its canonical member. At 0x00238eb8-0x00238ebc nonzero mode enables the moving target-arrival braking state, while zero leaves that branch. domain_8_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The authoritative snapshot maps hero.vehicle_mode to the byte at hero+0x20a4 (0x001413f4), distinct from current state +0x2084 and control mode +0x208c. Original retail Ghidra cRam001413f4 agrees. Checked request_hero_idle_state_for_vehicle_mode at 0x00234c20 reads that same byte and mode 0 selects IDLE at 0x00234c40-0x00234c48, establishing the supplied shared HeroVehicleMode domain; reuse its canonical member. At 0x0023ccf0-0x0023ccf4 mode zero gates ordinary look-release animation handling, matching LOOK's same byte test. --- .../l08/hero/update_hero_state_transitions.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l08/hero/update_hero_state_transitions.c b/src/overlays/l08/hero/update_hero_state_transitions.c index 90a492ecf5..01f637a4ea 100644 --- a/src/overlays/l08/hero/update_hero_state_transitions.c +++ b/src/overlays/l08/hero/update_hero_state_transitions.c @@ -189,9 +189,9 @@ void update_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L08_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.vehicle_mode == 0 || hero.vehicle_mode == 3)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; if (hero.quick_swap_tap_window != 0) { @@ -254,7 +254,7 @@ void update_hero_state_transitions(void) { } } if (hero_fatal_fall_z_threshold > hero.motion.pos.f[2] && hero.ground_distance > 2.0f && - hero.vehicle_mode != 2 && hero.state.current != 0x77) { + hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { hero_set_state(0x77, 1); } else { switch (hero.state.current) { @@ -657,7 +657,7 @@ void update_hero_state_transitions(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { @@ -684,7 +684,7 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { request_hero_idle_state_for_vehicle_mode(); break; } @@ -947,7 +947,7 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; @@ -2462,7 +2462,7 @@ void update_hero_state_transitions(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { From 20cfa220dc2028efebf21c87377a3bdf3e0785d4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:54:38 +0000 Subject: [PATCH 1331/1502] decomp: clarify names in update_hero_state_machine domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0023b560 loads +0x20A4 and 0x0023b564 compares it with 1 to bypass the item-use lock. The same mode 1 selects the existing CLANK four-slot HUD case at 0x0023b5ac/0x0023b694. These comparisons read the same hero.vehicle_mode byte at hero+0x20A4 as the switch at 0x0023b5a8, whose existing cases use HeroVehicleMode members from include/rnc/hero/hero_state.h; this is separate from hero.state.current at +0x2084. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0023b588 loads +0x20A4 and 0x0023b58c compares it with 1 to bypass the item-selection block. The existing same-selector CLANK case reaches the four-slot HUD setup at 0x0023b694. These comparisons read the same hero.vehicle_mode byte at hero+0x20A4 as the switch at 0x0023b5a8, whose existing cases use HeroVehicleMode members from include/rnc/hero/hero_state.h; this is separate from hero.state.current at +0x2084. domain_2_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x0023b848 loads vehicle_mode +0x20A4 and 0x0023b84c compares with 2, excluding that mode from the death-fall transition. HeroVehicleMode supplies canonical GIANT_CLANK=2 for this exact selector. These comparisons read the same hero.vehicle_mode byte at hero+0x20A4 as the switch at 0x0023b5a8, whose existing cases use HeroVehicleMode members from include/rnc/hero/hero_state.h; this is separate from hero.state.current at +0x2084. domain_3_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: LOOK processing at 0x0023c128 loads vehicle_mode +0x20A4 and branches on nonzero at 0x0023c12c, leaving zero to perform ordinary hero look animation selection. The same byte's existing switch names zero ON_FOOT. These comparisons read the same hero.vehicle_mode byte at hero+0x20A4 as the switch at 0x0023b5a8, whose existing cases use HeroVehicleMode members from include/rnc/hero/hero_state.h; this is separate from hero.state.current at +0x2084. domain_4_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0023c214 loads vehicle_mode +0x20A4; nonzero at 0x0023c218 calls enter_hero_idle_state_for_current_vehicle_mode, while zero continues normal CROUCH/IDLE logic. Existing same-selector switch establishes ON_FOOT=0. These comparisons read the same hero.vehicle_mode byte at hero+0x20A4 as the switch at 0x0023b5a8, whose existing cases use HeroVehicleMode members from include/rnc/hero/hero_state.h; this is separate from hero.state.current at +0x2084. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: APPROACH_TARGET_POSE at 0x0023ca88 loads vehicle_mode +0x20A4; zero branches away at 0x0023ca8c, while nonzero can enter braking state 0x66 based on speed. Existing same-byte switch uses canonical ON_FOOT for zero. These comparisons read the same hero.vehicle_mode byte at hero+0x20A4 as the switch at 0x0023b5a8, whose existing cases use HeroVehicleMode members from include/rnc/hero/hero_state.h; this is separate from hero.state.current at +0x2084. domain_6_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: LOOK_RELEASE_WAIT at 0x002417fc loads vehicle_mode +0x20A4; 0x00241800 skips ordinary look-animation selection when nonzero. Zero is the same ON_FOOT member already used by the vehicle_mode switch. These comparisons read the same hero.vehicle_mode byte at hero+0x20A4 as the switch at 0x0023b5a8, whose existing cases use HeroVehicleMode members from include/rnc/hero/hero_state.h; this is separate from hero.state.current at +0x2084. --- src/overlays/l06/hero/update_hero_state_machine.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l06/hero/update_hero_state_machine.c b/src/overlays/l06/hero/update_hero_state_machine.c index 473d924a98..7fbb6a887b 100644 --- a/src/overlays/l06/hero/update_hero_state_machine.c +++ b/src/overlays/l06/hero/update_hero_state_machine.c @@ -179,8 +179,8 @@ void update_hero_state_machine(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L06_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0)) { switch (hero.vehicle_mode) { case HERO_VEHICLE_MODE_ON_FOOT: case 3: { @@ -259,7 +259,7 @@ void update_hero_state_machine(void) { } } if (death_fall_trigger_z > hero.motion.pos.f[2] && hero.ground_distance > 2.0f && - hero.vehicle_mode != 2 && hero.state.current != 0x77) { + hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { hero_set_state(0x77, 1); } else { switch (hero.state.current) { @@ -518,7 +518,7 @@ void update_hero_state_machine(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { @@ -545,7 +545,7 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { enter_hero_idle_state_for_current_vehicle_mode(); break; } @@ -778,7 +778,7 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; @@ -2657,7 +2657,7 @@ void update_hero_state_machine(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { From 3800e93de4512eeb452482e6e79b355c17bc2b82 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:56:37 +0000 Subject: [PATCH 1332/1502] decomp: clarify names in update_hero_motion_by_state domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Source HERO_STATE_CROUCH_SWING tests hero.gravity_mode == 0 before updating target heading. Original retail case 0x15 tests cRam00141403 == 0; instructions 0x00248e24-0x00248e54 load hero+0x20B3 and gate the heading helper. This identifies the gravity selector, separate from hero+0x2084 state and +0x20A4 vehicle mode, so reuse canonical HeroGravityMode member HERO_GRAVITY_WORLD_DOWN. domain_10_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source approach-target-pose turning uses hero.vehicle_mode == 0 before choosing step-specific turning or stick-scaled turning. Retail 0x0024b6e8-0x0024b748 tests the +0x20A4 byte from 0x0024b65c against zero and checks separate step +0x2088. Original Ghidra agrees; selector provenance proves HeroVehicleMode, so reuse canonical ON_FOOT. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source approach-target-pose calls adjust_hero_pose_targets_from_motion when hero.vehicle_mode == 0. Retail 0x0024b74c-0x0024b760 loads hero byte +0x20A4, branches on nonzero and calls the pose helper only for zero. Original Ghidra case 0x65 agrees. This is the same proven HeroVehicleMode domain, so reuse canonical ON_FOOT. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source approach-target-pose clips horizontal velocity only when hero.vehicle_mode == 0. Original Ghidra tests cRam001413f4; retail 0x0024b7ac-0x0024b7bc loads hero+0x20A4, skips on nonzero and calls clip helper with one for zero. This proves the same HeroVehicleMode selector and supports canonical HERO_VEHICLE_MODE_ON_FOOT. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: Source tb is &D_L05_0017C088[hero.attack_record], and this comparison selects spacing 0.75 before the same tb->kind switch's named forward-advance case. Retail 0x00248f4c-0x00248f68 forms the row with stride 0x2C; 0x00248fb0-0x00248fdc loads row+4 and tests zero. Original Ghidra agrees. This is the supplied HeroComboKind domain, so reuse its canonical zero member. domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source compares tb->kind after tb=&D_L05_0017C088[hero.attack_record] and selects spacing 0.6. Retail 0x00248fb0 loads row+4; 0x00248fe0-0x0024900c tests one and subtracts 0.6. The same row+4 dispatch at 0x002490a4-0x002491fc supplies staged forward deceleration, matching the existing named source case and supplied HeroComboKind member. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source uses tb->kind == 1 to modify animation speed during attack-target turning, with tb bound to the indexed attack record. Retail 0x00249240-0x00249288 reads the same row+4 and tests one before angular-difference and reciprocal animation-speed calculations. Original Ghidra case 0x13 agrees; reuse the canonical HeroComboKind member already used by this row's switch. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source tb->kind == 1 disables target heading after animation frame 7 when animation is stable. Original Ghidra case 0x13 and retail 0x002492e8-0x00249340 test the same attack row+4 against one and gate heading on animation state/frame. Row provenance at 0x00248f4c-0x00248f68 proves HeroComboKind, whose canonical one member is STAGED_FORWARD_DECELERATION. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source jump handling calls adjust_hero_pose_targets_from_motion only when hero.vehicle_mode == 0. Original Ghidra tests cRam001413f4 == 0; retail 0x0024b2f4-0x0024b304 loads byte hero+0x20A4 and gates that pose helper. This is the supplied HeroVehicleMode selector, distinct from the current-state word at +0x2084; reuse canonical ON_FOOT. domain_7_value_1 -> HERO_VEHICLE_MODE_CLANK: Source approach-target-pose handling compares hero.vehicle_mode == 1 and selects frame_time*0.9 target speed. Original Ghidra case 0x65 tests cRam001413f4 against one. Retail 0x0024b5f4-0x0024b638 loads hero+0x20A4 and selects the 0.9 multiplier, proving the HeroVehicleMode selector and permitting canonical HERO_VEHICLE_MODE_CLANK. domain_9_value_1 -> HERO_VEHICLE_MODE_CLANK: Source approach-target-pose handling compares hero.vehicle_mode == 1 to select turning coefficients and frame_time*7.8539815 bound. Retail 0x0024b65c loads byte hero+0x20A4; 0x0024b6a8-0x0024b6e4 tests one and constructs those turn inputs. Original Ghidra cRam001413f4 branch agrees; reuse the supplied HeroVehicleMode CLANK member. --- .../l05/hero/update_hero_motion_by_state.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l05/hero/update_hero_motion_by_state.c b/src/overlays/l05/hero/update_hero_motion_by_state.c index 5e869b9a9f..ae3965fc3f 100644 --- a/src/overlays/l05/hero/update_hero_motion_by_state.c +++ b/src/overlays/l05/hero/update_hero_motion_by_state.c @@ -1667,7 +1667,7 @@ void update_hero_motion_by_state(void) { if (hero.anim_changing == 0 && hero.anim_frame > 6.0f) { ok = 0; } - if (ok && hero.gravity_mode == 0) { + if (ok && hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1709,11 +1709,11 @@ void update_hero_motion_by_state(void) { if (d < 0.0f) { d = 0.0f; } - if (tb->kind == 0) { + if (tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { off = 0.75f; tol = 0.8f; mx = 4.0f; - } else if (tb->kind == 1) { + } else if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { off = 0.6f; tol = 1.7f; mx = 4.0f; @@ -1758,7 +1758,7 @@ void update_hero_motion_by_state(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || (struct MobyView *)hero.melee_target != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1768,7 +1768,7 @@ void update_hero_motion_by_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2846,7 +2846,7 @@ void update_hero_motion_by_state(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -2918,7 +2918,7 @@ void update_hero_motion_by_state(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = frame_time * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = frame_time * 0.9f; } } else { @@ -2929,21 +2929,21 @@ void update_hero_motion_by_state(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to(0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, frame_time * 9.948377f); } else { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } speed_step(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { From d642d33d730615adc7792d87c9c5d1a2dc85b635 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:56:38 +0000 Subject: [PATCH 1333/1502] decomp: clarify names in update_hero_motion_for_current_state domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Source CROUCH_SWING compares hero.gravity_mode, not the state selector. Retail 00230034 loads hero+0x20B3 and 00230038 gates heading adjustment on zero; supplied ground-contact source dispatches this same gravity_mode as HeroGravityMode and sets gravity_dir.z=-1 for HERO_GRAVITY_WORLD_DOWN. domain_10_value_1 -> HERO_VEHICLE_MODE_CLANK: Source APPROACH_TARGET_POSE selects turning parameters using hero.vehicle_mode. Retail 002334d4 loads hero+0x20A4 and 00233520-0023355c tests one before the 7.8539815-rate turn. Supplied hit-response and capsule-target switches establish this exact field as HeroVehicleMode with canonical CLANK one. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source APPROACH_TARGET_POSE tests hero.vehicle_mode==0 before its step-dependent on-foot turning. Retail 00233560 tests the hero+0x20A4 byte against zero, then 00233568-002335c0 chooses the turn helper from step. Supplied same-field HeroVehicleMode switches establish canonical ON_FOOT zero. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source APPROACH_TARGET_POSE calls adjust_hero_pose_targets_from_motion for hero.vehicle_mode==0. Retail 002335c8-002335d8 reads byte hero+0x20A4, branches on nonzero, and calls the pose helper for zero. This exact field belongs to the supplied HeroVehicleMode switches naming zero ON_FOOT. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source APPROACH_TARGET_POSE calls adjust_hero_velocity_from_collision_probes only when hero.vehicle_mode==0. Retail 00233624-00233634 loads hero+0x20A4 and gates that call on zero. Supplied hit-response and smoothed-parameters switches use the identical vehicle_mode field with canonical HeroVehicleMode ON_FOOT zero. domain_14_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: Source VEHICLE_MODE_1_ATTACK sets tb=&D_L06_0017C3A8[hero.attack_record], the same shared attack-record kind domain as WRENCH_COMBO. Retail 00233820-0023383c forms the indexed row and loads row+4; 00233840 tests zero for early advance. Canonical HeroComboKind zero is corroborated by same-table dispatch 002302ec-00230328. domain_15_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source VEHICLE_MODE_1_ATTACK compares tb->kind==1 in the early advance condition on the same attack-record array. Retail 0023383c-00233848 loads row+4 and compares one; 00233850-00233880 gates speed on frame<5.5. Same-table kind-one dispatch 0023032c-002303c0 establishes the canonical shared HeroComboKind. domain_16_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source VEHICLE_MODE_1_ATTACK selects joint index zero versus two from tb->kind==1. Retail 002338c8 loads row+4 and 002338d4-002338dc tests one to select the joint pair used for midpoint sound. The row is D_L06_0017C3A8[hero.attack_record], identical to the proven HeroComboKind staged-deceleration selector at 0023032c-002303c0. domain_17_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source VEHICLE_MODE_1_ATTACK uses the same attack-record tb->kind for yaw-dependent animation-speed scaling. Retail 00233990-002339d8 loads row+4, compares one and applies reciprocal yaw-difference scaling. Same indexed row kind dispatch at 0023032c-002303c0 proves canonical HeroComboKind STAGED_FORWARD_DECELERATION membership. domain_18_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source VEHICLE_MODE_1_ATTACK tests the same attack-record tb->kind before disabling heading updates after frame seven. Retail 00233a38-00233a70 compares row+4 to one and gates on animation-change/frame values. This is the identical shared HeroComboKind selector whose one branch stages forward deceleration at 0023032c-002303c0. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: Source tb=&D_L06_0017C3A8[hero.attack_record] identifies the shared HeroComboKind domain. Retail 0023015c-00230178 forms the 0x2C-byte indexed row; 002301c0-002301ec reads kind at row+4 and tests zero for target-spacing tuning. Same row selector dispatch 002302ec-00230328 implements the canonical frame-gated forward advance. domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source WRENCH_COMBO uses tb from the attack_record-indexed HeroTableRow2C array. Retail 002301f0 tests row+4 against one for spacing parameters; same selector at 002302b4-002303c0 selects 5.7/4.5/3.0 frame-staged forward speed, proving canonical HeroComboKind membership. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source tb remains the attack_record-indexed HeroTableRow2C pointer in WRENCH_COMBO. Retail 00230450-00230498 reloads row+4, compares to one, and scales animation speed from attack-target yaw difference. It is the same kind field whose staged forward deceleration dispatch is 0023032c-002303c0, matching shared HeroComboKind. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source WRENCH_COMBO compares the same indexed attack-record tb->kind before disabling target-heading adjustment after frame seven. Retail 002304f8-00230530 tests row+4==1, animation-change flag and frame>7. The identical selector's 0023032c-002303c0 staged speed branch proves reuse of canonical HeroComboKind. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source jump branch compares hero.vehicle_mode before adjust_hero_pose_targets_from_motion. Retail 00233158-00233168 loads byte hero+0x20A4 and calls the pose helper only for zero. Supplied process_hero_hit_response and update_hero_smoothed_parameters use this same vehicle_mode field in HeroVehicleMode switches with canonical ON_FOOT zero. domain_6_value_1 -> HERO_VEHICLE_MODE_CLANK: Source jump branch compares hero.vehicle_mode before update_hero_motion_response_parameters. Retail 0023316c-00233180 reloads hero+0x20A4 and tests one for that call. Supplied hit-response and capsule-smoothing switches identify the same vehicle_mode field as HeroVehicleMode, including canonical CLANK one. domain_8_value_1 -> HERO_VEHICLE_MODE_CLANK: Source APPROACH_TARGET_POSE selects 0.9-scaled target speed for hero.vehicle_mode==1. Retail 0023346c loads hero+0x20A4; 00233488-002334b0 tests one and stores the 0.9-scaled speed. Same field is explicitly switched using HeroVehicleMode CLANK in the supplied hit-response and smoothed-parameters source. --- .../update_hero_motion_for_current_state.c | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/overlays/l06/hero/update_hero_motion_for_current_state.c b/src/overlays/l06/hero/update_hero_motion_for_current_state.c index 17ba6d7b1b..f1cffee743 100644 --- a/src/overlays/l06/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l06/hero/update_hero_motion_for_current_state.c @@ -1687,7 +1687,7 @@ void update_hero_motion_for_current_state(void) { if (hero.anim_changing == 0 && hero.anim_frame > 6.0f) { ok = 0; } - if (ok && hero.gravity_mode == 0) { + if (ok && hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1729,11 +1729,11 @@ void update_hero_motion_for_current_state(void) { if (d < 0.0f) { d = 0.0f; } - if (tb->kind == 0) { + if (tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { off = 0.75f; tol = 0.8f; mx = 4.0f; - } else if (tb->kind == 1) { + } else if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { off = 0.6f; tol = 1.7f; mx = 4.0f; @@ -1778,7 +1778,7 @@ void update_hero_motion_for_current_state(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || (struct MobyView *)hero.melee_target != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1788,7 +1788,7 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, D_0015ED6C_c * 15.009831f); } else { s32 ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2777,10 +2777,10 @@ void update_hero_motion_for_current_state(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } - if (hero.vehicle_mode == 1) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { update_hero_motion_response_parameters(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -2853,7 +2853,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = D_0015ED6C_a * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = D_0015ED6C_a * 0.9f; } } else { @@ -2864,9 +2864,9 @@ void update_hero_motion_for_current_state(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, D_0015ED6C_c * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, D_0015ED6C_c * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to( 0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, D_0015ED6C_c * 9.948377f); @@ -2874,12 +2874,12 @@ void update_hero_motion_for_current_state(void) { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } FUN_L00_00212088(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_velocity_from_collision_probes(1); } if (hero.air_frames.s != 0) { @@ -2941,12 +2941,12 @@ void update_hero_motion_for_current_state(void) { s32 ok; tb = &D_L06_0017C3A8[hero.attack_record]; hero.target_speed = 0.0f; - if ((tb->kind == 0 ? 1 : tb->kind == 1) && hero.anim_frame < 5.5f) { + if ((tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE ? 1 : tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) && hero.anim_frame < 5.5f) { hero.target_speed = D_0015ED6C_c * 3.5f; } if (hero.anim_changing == 0 && (f32)tb->f1C <= hero.anim_frame && hero.anim_frame <= (f32)tb->f20) { - s32 k = tb->kind == 1 ? 0 : 2; + s32 k = tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION ? 0 : 2; moby_point_position((struct MobyView *)hero.moby, k, &v10); moby_point_position((struct MobyView *)hero.moby, k | 1, &vector_or_descriptor_scratch); fast_vec_add(&vector_or_hit_descriptor_scratch, &v10, &vector_or_descriptor_scratch); @@ -2964,7 +2964,7 @@ void update_hero_motion_for_current_state(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || (struct MobyView *)hero.melee_target != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -2974,7 +2974,7 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, D_0015ED6C_c * 15.009831f); } else { ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { From 5863eb10d45bdf29d0cbcd966e9340269ec04c0e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:56:39 +0000 Subject: [PATCH 1334/1502] decomp: clarify names in process_hero_state_transitions domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Bound C hero.vehicle_mode maps to retail byte hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control_mode +0x208c. Checked helper 0x0022c420 loads the same byte; 0x0022c428-0x0022c46c maps mode 2 to state 0x5a and mode 0 to IDLE, corroborating the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. Retail 0x0022ea38-0x0022ea3c compares this byte with 1 to bypass the item-use lock for Triangle HUD activation. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Bound C hero.vehicle_mode maps to retail byte hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control_mode +0x208c. Checked helper 0x0022c420 loads the same byte; 0x0022c428-0x0022c46c maps mode 2 to state 0x5a and mode 0 to IDLE, corroborating the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. Retail 0x0022ea60-0x0022ea64 compares this byte with 1 to bypass the item-selection lock in the same activation gate. domain_2_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Bound C hero.vehicle_mode maps to retail byte hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control_mode +0x208c. Checked helper 0x0022c420 loads the same byte; 0x0022c428-0x0022c46c maps mode 2 to state 0x5a and mode 0 to IDLE, corroborating the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. Retail 0x0022ea7c-0x0022ea80 tests the byte for zero before allowing the HUD activation block, with a separate mode-3 alternative. domain_4_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Bound C hero.vehicle_mode maps to retail byte hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control_mode +0x208c. Checked helper 0x0022c420 loads the same byte; 0x0022c428-0x0022c46c maps mode 2 to state 0x5a and mode 0 to IDLE, corroborating the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. Retail 0x0022eccc-0x0022ecd0 excludes byte value 2 from low-height fatal-fall entry. Checked mode dispatch selects state 0x5a for 2; its jump branch invokes spawn_giant_clank_hit_sphere at 0x0023469c. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Bound C hero.vehicle_mode maps to retail byte hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control_mode +0x208c. Checked helper 0x0022c420 loads the same byte; 0x0022c428-0x0022c46c maps mode 2 to state 0x5a and mode 0 to IDLE, corroborating the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. LOOK retail 0x0022fc48-0x0022fc4c tests this byte for zero to enter ordinary hero item/crouch look-animation selection. domain_6_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Bound C hero.vehicle_mode maps to retail byte hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control_mode +0x208c. Checked helper 0x0022c420 loads the same byte; 0x0022c428-0x0022c46c maps mode 2 to state 0x5a and mode 0 to IDLE, corroborating the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. LOOK exit retail 0x0022fd34-0x0022fd40 tests the same byte for nonzero then calls mode-state dispatch; its checked zero arm selects IDLE at 0x0022c43c-0x0022c46c. domain_7_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Bound C hero.vehicle_mode maps to retail byte hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control_mode +0x208c. Checked helper 0x0022c420 loads the same byte; 0x0022c428-0x0022c46c maps mode 2 to state 0x5a and mode 0 to IDLE, corroborating the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. Target-pose approach retail 0x00230708-0x0023070c tests the byte for zero, skipping vehicle braking-state selection in the on-foot mode. domain_8_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Bound C hero.vehicle_mode maps to retail byte hero+0x20a4 (absolute 0x001413f4), distinct from current state +0x2084 and control_mode +0x208c. Checked helper 0x0022c420 loads the same byte; 0x0022c428-0x0022c46c maps mode 2 to state 0x5a and mode 0 to IDLE, corroborating the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. LOOK_RELEASE_WAIT retail 0x0023505c-0x00235060 tests the byte for zero before the same ordinary hero item/crouch look-animation selection. --- .../l18/hero/process_hero_state_transitions.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/overlays/l18/hero/process_hero_state_transitions.c b/src/overlays/l18/hero/process_hero_state_transitions.c index 241f03906e..5f43f0afdc 100644 --- a/src/overlays/l18/hero/process_hero_state_transitions.c +++ b/src/overlays/l18/hero/process_hero_state_transitions.c @@ -196,9 +196,9 @@ void process_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && hero_triangle_hud_activation_inhibit == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.vehicle_mode == 0 || hero.vehicle_mode == 3)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; if (hero.quick_swap_tap_window != 0) { @@ -261,7 +261,7 @@ void process_hero_state_transitions(void) { } } if (D_L18_0015F638 > hero.motion.pos.f[2] && hero.ground_distance > 2.0f && - hero.vehicle_mode != 2 && hero.state.current != 0x77) { + hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { hero_set_state(0x77, 1); } else { switch (hero.state.current) { @@ -664,7 +664,7 @@ void process_hero_state_transitions(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { @@ -691,7 +691,7 @@ void process_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { set_hero_state_for_vehicle_mode(); break; } @@ -949,7 +949,7 @@ void process_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; @@ -2749,7 +2749,7 @@ void process_hero_state_transitions(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { From 9117be038635bf0a9956fe226e2a93b495431a46 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:59:03 +0000 Subject: [PATCH 1335/1502] decomp: clarify names in update_hero_motion_for_current_state domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: Exact C compares hero.gravity_mode, not hero.state.current. Retail 0x00217db0 loads byte hero+0x20b3 and 0x00217db4 branches on nonzero before update_hero_target_heading at 0x00217ddc. Original Ghidra cRam00141403 == 0 agrees (0x13f350+0x20b3). This binds the gravity-mode selector to supplied HeroGravityMode in include/rnc/hero/hero_state.h; reuse canonical WORLD_DOWN=0. domain_10_value_1 -> HERO_VEHICLE_MODE_CLANK: C hero.vehicle_mode==1 chooses target-pose turning parameters. Retail 0x0021c2e4 loads byte hero+0x20a4 and 0x0021c330 branches unless it equals one; 0x0021c338-0x0021c36c prepares the 7.8539815*frame_time turn limit. Original Ghidra cRam001413f4 == 1 agrees. Same field as the jump vehicle-mode consumer establishes HeroVehicleMode; reuse CLANK=1. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: C zero vehicle_mode selects on-foot target-pose turning. Retail 0x0021c370 tests the byte +0x20a4 retained in v1 for zero, then checks step at +0x2088 separately and chooses turn_to or stick-scale turning through 0x0021c3d0. Ghidra distinguishes cRam001413f4 from iRam001413d8. Thus selector belongs to HeroVehicleMode; reuse ON_FOOT=0. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: C zero hero.vehicle_mode gates pose adjustment in target-pose approach. Retail 0x0021c3d8 loads byte hero+0x20a4 and 0x0021c3dc skips 0x00212130 unless zero. Ghidra LAB_0021c3d8 tests cRam001413f4==0. Same byte as jump mode selection at 0x0021bf5c, distinct from state and step words, proves HeroVehicleMode and canonical ON_FOOT=0. domain_13_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: C zero hero.vehicle_mode gates collision-probe velocity adjustment. Retail 0x0021c434-0x0021c444 loads hero+0x20a4, skips the call when nonzero, and calls 0x0020f128 with one for zero. Ghidra cRam001413f4==0 agrees. This is the same proven HeroVehicleMode selector as the neighboring pose and turn choices; reuse canonical ON_FOOT=0. domain_14_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: C tb=&D_L17_0017C528[hero.attack_record] in VEHICLE_MODE_1_ATTACK. Retail 0x0021c6b8-0x0021c6cc forms the row with stride 0x2c; 0x0021c6d0-0x0021c6d4 tests row+4 for zero before the early forward-speed frame gate. Ghidra reads record*0x2c+0x17c52c, identical to the combo switch's kind domain at 0x0021817c. Reuse canonical HeroComboKind FRAME_GATED_FORWARD_ADVANCE=0. domain_15_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: C early vehicle attack speed accepts tb->kind zero or one. Retail 0x0021c6d0-0x0021c6dc loads attack row+4 and compares one after zero; row address is attack_record*0x2c+0x17c528 at 0x0021c6b8-0x0021c6cc. Ghidra confirms this same field. It is HeroComboKind, the selector of staged forward deceleration in the wrench-combo consumer; reuse its canonical one member. domain_16_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: C tb->kind==1 selects joint pair 0/1 rather than 2/3 for attack sound positioning. Retail 0x0021c75c-0x0021c778 loads attack row+4, xors with one and conditionally zeroes the joint index. Ghidra uses the same record*0x2c+0x17c52c field. Proven attack-record kind domain matches HeroComboKind; reuse STAGED_FORWARD_DECELERATION=1 although this consumer uses it for joint selection. domain_17_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: C target-aimed vehicle attack tests tb->kind before yaw-dependent animation slowing. Retail 0x0021c824-0x0021c830 loads attack row+4 and compares one, then 0x0021c834-0x0021c86c computes yaw delta and animation speed. Ghidra LAB_0021c828 confirms the row-kind test; row formed at 0x0021c6b8-0x0021c6cc is the same attack-record domain as the combo switch. Reuse canonical HeroComboKind one. domain_18_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: C tb->kind==1 disables free heading updates after frame seven during vehicle attack. Retail 0x0021c8cc-0x0021c904 compares attack row+4 to one, checks animation-changing and frame, and clears the heading gate. Ghidra confirms record*0x2c+0x17c52c kind. Its shared HeroComboKind domain is proven by identical row indexing/offset in the wrench-combo switch; reuse STAGED_FORWARD_DECELERATION=1. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: C tb=&D_L17_0017C528[hero.attack_record]; retail 0x00218024-0x00218040 forms row address using attack_record at hero+0xa60 and stride 0x2c. 0x00218088-0x002180b4 loads row+4 and tests zero for spacing 0.75. Ghidra reads index*0x2c+0x17c52c. This is the same kind field switched at 0x0021817c-0x002181f0 for frame-gated forward advance, proving supplied HeroComboKind domain and canonical zero member. domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: C tb is the attack_record-indexed HeroTableRow2C; retail 0x00218088-0x002180e4 tests row+4 against one and selects spacing 0.6. Original Ghidra reads the same 0x17c52c+record*0x2c field. Its switch at 0x0021817c-0x00218288 selects staged 5.7/4.5/3.0 forward speeds. Thus reuse canonical HeroComboKind STAGED_FORWARD_DECELERATION=1 from include/rnc/overlay/hero_tables.h. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: C tests tb->kind in the target-aimed combo branch. Retail 0x00218318-0x00218324 loads attack row+4 and compares one; 0x00218328-0x00218360 uses positive target-yaw delta to reduce animation speed. Ghidra LAB_0021831c confirms the same row-kind load. Row comes from attack_record*0x2c at 0x00218024-0x00218040, the same HeroComboKind selector whose one arm has staged forward deceleration. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: C tests tb->kind before disabling free heading updates after animation frame seven. Retail 0x002183c0-0x002183f8 compares the attack row+4 kind to one, checks hero+0xa9c and frame at +0xaa8, then clears the heading gate. Ghidra agrees. The row is D_L17_0017C528[hero.attack_record], also switched at 0x0021817c into staged forward deceleration for one; reuse canonical HeroComboKind member. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: C hero.vehicle_mode controls jump pose adjustment. Retail 0x0021bf5c loads hero+0x20a4 as a byte, 0x0021bf60 skips adjust_hero_pose_targets_from_motion when nonzero, and 0x0021bf68 calls it for zero. Ghidra cRam001413f4 == 0 agrees. This is the supplied HeroVehicleMode field, distinct from current-state word +0x2084 and step +0x2088; reuse canonical ON_FOOT=0. domain_6_value_1 -> HERO_VEHICLE_MODE_CLANK: C hero.vehicle_mode==1 selects update_hero_motion_response_parameters in jump handling. Retail 0x0021bf70-0x0021bf84 loads byte +0x20a4, compares one and calls 0x00212958. Original Ghidra cRam001413f4 == 1 agrees. This proves the supplied HeroVehicleMode selector rather than a current-state ID; reuse its canonical CLANK=1 member. domain_8_value_1 -> HERO_VEHICLE_MODE_CLANK: C tests hero.vehicle_mode in approach-target-pose movement. Retail 0x0021c27c loads byte hero+0x20a4; after the separate three test, 0x0021c298-0x0021c2c0 tests one and selects target speed 0.9*frame_time. Ghidra cRam001413f4 == 1 agrees. The same +0x20a4 selector used in jump handling is HeroVehicleMode; reuse canonical CLANK=1 without naming mode three. --- .../update_hero_motion_for_current_state.c | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/overlays/l17/hero/update_hero_motion_for_current_state.c b/src/overlays/l17/hero/update_hero_motion_for_current_state.c index ade1987b9c..709c26a999 100644 --- a/src/overlays/l17/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l17/hero/update_hero_motion_for_current_state.c @@ -1354,7 +1354,7 @@ void update_hero_motion_for_current_state(void) { if (hero.anim_changing == 0 && hero.anim_frame > 6.0f) { ok = 0; } - if (ok && hero.gravity_mode == 0) { + if (ok && hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1415,11 +1415,11 @@ void update_hero_motion_for_current_state(void) { if (d < 0.0f) { d = 0.0f; } - if (tb->kind == 0) { + if (tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { off = 0.75f; tol = 0.8f; mx = 4.0f; - } else if (tb->kind == 1) { + } else if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { off = 0.6f; tol = 1.7f; mx = 4.0f; @@ -1464,7 +1464,7 @@ void update_hero_motion_for_current_state(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || (struct MobyView *)hero.melee_target != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1474,7 +1474,7 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2726,10 +2726,10 @@ void update_hero_motion_for_current_state(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } - if (hero.vehicle_mode == 1) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { update_hero_motion_response_parameters(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -2799,7 +2799,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = D_0015ED6C_a * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = D_0015ED6C_a * 0.9f; } } else { @@ -2810,21 +2810,21 @@ void update_hero_motion_for_current_state(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to(0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, frame_time * 9.948377f); } else { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } speed_step(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_velocity_from_collision_probes(1); } if (hero.air_frames.s != 0) { @@ -2899,12 +2899,12 @@ void update_hero_motion_for_current_state(void) { s32 ok; tb = &D_L17_0017C528[hero.attack_record]; hero.target_speed = 0.0f; - if ((tb->kind == 0 ? 1 : tb->kind == 1) && hero.anim_frame < 5.5f) { + if ((tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE ? 1 : tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) && hero.anim_frame < 5.5f) { hero.target_speed = frame_time * 3.5f; } if (hero.anim_changing == 0 && (f32)tb->f1C <= hero.anim_frame && hero.anim_frame <= (f32)tb->f20) { - s32 k = tb->kind == 1 ? 0 : 2; + s32 k = tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION ? 0 : 2; moby_point_position((struct MobyView *)hero.moby, k, &v10); moby_point_position((struct MobyView *)hero.moby, k | 1, &vector_workspace); fast_vec_add(&scratch_vector, &v10, &vector_workspace); @@ -2914,7 +2914,7 @@ void update_hero_motion_for_current_state(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || (struct MobyView *)hero.melee_target != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -2924,7 +2924,7 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { From dbdc9932655033409beef3508818c4f658001ce1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:59:04 +0000 Subject: [PATCH 1336/1502] decomp: clarify names in update_hero_motion_for_current_state domain_0_value_0 -> HERO_GRAVITY_WORLD_DOWN: The CROUCH_SWING source tests hero.gravity_mode. Retail 0x00221e58 loads byte hero+0x20b3 (0x00141403), then 0x00221e5c skips heading update when nonzero; original Ghidra tests cRam00141403 == 0. This is the separate HeroGravityMode selector identified in the supplied shared hero_state.h domain, whose canonical zero member is HERO_GRAVITY_WORLD_DOWN. domain_10_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source APPROACH_TARGET_POSE uses hero.vehicle_mode == 0 to select on-foot turning, including state.step-dependent turn_to or turn_hero_toward_move_direction_with_stick_scale. Retail 0x002259a8 tests the same byte loaded at 0x0022591c from hero+0x20a4 for zero; original Ghidra confirms cRam001413f4 == 0. Reuse the canonical zero member of the supplied HeroVehicleMode domain. domain_11_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00225a10 loads byte hero+0x20a4, and 0x00225a14 branches over the pose helper at 0x00225a1c when nonzero. Source identifies the comparison as hero.vehicle_mode == 0 and original Ghidra tests cRam001413f4 == 0. This is the same separate HeroVehicleMode selector used for target speed and turning, so reuse supplied HERO_VEHICLE_MODE_ON_FOOT. domain_12_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00225a6c loads byte hero+0x20a4 and 0x00225a70 skips the planar-probe helper at 0x00225a78 when nonzero. Authoritative source calls adjust_hero_planar_velocity_from_probes(1) under hero.vehicle_mode == 0; original Ghidra tests cRam001413f4 == 0. This proves the same supplied HeroVehicleMode domain and its canonical HERO_VEHICLE_MODE_ON_FOOT member. domain_1_value_0 -> HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE: Source tb is &D_L18_0017C628[hero.attack_record], a HeroTableRow2C pointer. Retail 0x00221f80-0x00221f9c computes the 0x2c-byte row and 0x00221fe4 loads row+4 for the zero comparison, choosing spacing 0.75. The unchanged row+4 dispatch at 0x002220d8-0x0022214c selects frame<18 forward speed 4.4. This proves the same HeroComboKind domain already named in the source switch and supplied hero_tables.h. domain_2_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Retail 0x00221fe4 loads kind from attack row+4 and 0x00222014 compares it with 1, choosing spacing 0.6. Source tb remains the indexed HeroTableRow2C attack row; the same tb->kind switch uses HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION. Original Ghidra and 0x00222150-0x002221e4 confirm staged forward speeds 5.7, 4.5 and 3.0 for this row kind, proving reuse of the supplied HeroComboKind member. domain_3_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source tests the same tb->kind used by its named HeroComboKind switch. Retail 0x00222274 loads attack row+4 and 0x0022227c compares against 1 before the positive attack-yaw-delta animation-speed adjustment. Original Ghidra iVar8 comes from iVar8+0x17c62c, the identical kind field. Reuse the canonical HeroComboKind value-1 member, independently of hero state and attack_record index. domain_4_value_1 -> HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION: Source tests tb->kind alongside animation-change and frame>7 to gate heading updates. Retail 0x0022231c-0x00222350 compares the row+4 kind with 1 and then hero+0xa9c and hero+0xaa8; original Ghidra confirms the same indexed attack-row field. That unchanged selector is already dispatched with named HeroComboKind members in C; reuse its canonical staged-forward-deceleration member. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Source jump-family comparison reads hero.vehicle_mode. Retail 0x00225600 loads byte hero+0x20a4 and 0x00225604 skips adjust_hero_pose_targets_from_motion when nonzero; original Ghidra tests cRam001413f4 == 0. This is the separate HeroVehicleMode field identified by the supplied shared header, whose canonical zero member is HERO_VEHICLE_MODE_ON_FOOT, not hero.state.current at +0x2084. domain_7_value_1 -> HERO_VEHICLE_MODE_CLANK: Source APPROACH_TARGET_POSE compares hero.vehicle_mode with 1 to choose target speed frame_time*0.9. Retail 0x002258b4 loads byte hero+0x20a4 and 0x002258d0 compares it with 1 before 0x002258d8-0x002258f8 computes that speed; original Ghidra tests cRam001413f4 == 1. This proves the supplied HeroVehicleMode selector, allowing canonical HERO_VEHICLE_MODE_CLANK reuse. domain_9_value_1 -> HERO_VEHICLE_MODE_CLANK: Source APPROACH_TARGET_POSE tests hero.vehicle_mode for its turn coefficients. Retail 0x0022591c loads byte hero+0x20a4 and 0x00225968 compares it with 1, selecting gain 0.03 and maximum rate frame_time*7.8539815. Original Ghidra uses cRam001413f4 == 1. The byte is the same separate HeroVehicleMode selector as the preceding speed selection, with canonical member HERO_VEHICLE_MODE_CLANK supplied in hero_state.h. --- .../update_hero_motion_for_current_state.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/l18/hero/update_hero_motion_for_current_state.c b/src/overlays/l18/hero/update_hero_motion_for_current_state.c index f0ad661977..84f377e3ca 100644 --- a/src/overlays/l18/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l18/hero/update_hero_motion_for_current_state.c @@ -1352,7 +1352,7 @@ void update_hero_motion_for_current_state(void) { if (hero.anim_changing == 0 && hero.anim_frame > 6.0f) { ok = 0; } - if (ok && hero.gravity_mode == 0) { + if (ok && hero.gravity_mode == HERO_GRAVITY_WORLD_DOWN) { update_hero_target_heading(14.0f, 0.5235988f, 0.7853982f); } } @@ -1394,11 +1394,11 @@ void update_hero_motion_for_current_state(void) { if (d < 0.0f) { d = 0.0f; } - if (tb->kind == 0) { + if (tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE) { off = 0.75f; tol = 0.8f; mx = 4.0f; - } else if (tb->kind == 1) { + } else if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) { off = 0.6f; tol = 1.7f; mx = 4.0f; @@ -1443,7 +1443,7 @@ void update_hero_motion_for_current_state(void) { } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || (struct MobyView *)hero.melee_target != NULL) { - if (tb->kind == 1 && + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && fast_subtract_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) > 0.0f) { hero.anim_speed = 1.0f / (fast_difference_between_rotations(hero.attack_target_yaw, hero.motion.rot.f[2]) + @@ -1453,7 +1453,7 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == 1 && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2599,7 +2599,7 @@ void update_hero_motion_for_current_state(void) { hero.jump_gravity = hero.fall_gravity; } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } if (hero.state.current == HERO_STATE_PACK_LONG_JUMP || hero.state.current == 0xD) { @@ -2672,7 +2672,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.vehicle_mode == 3) { hero.target_speed = D_0015ED6C_a * 1.5f; - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero.target_speed = D_0015ED6C_a * 0.9f; } } else { @@ -2683,21 +2683,21 @@ void update_hero_motion_for_current_state(void) { k = 1.0f; if (hero.vehicle_mode == 3) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 5.5850534f); - } else if (hero.vehicle_mode == 1) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { turn_to(0, frame_scale_sq * 0.03f, frame_scale_sq * 0.3f, frame_time * 7.8539815f); - } else if (hero.vehicle_mode == 0) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.state.step == 1) { turn_to(0, frame_scale_sq * 0.016f, frame_scale_sq * 0.15f, frame_time * 9.948377f); } else { turn_hero_toward_move_direction_with_stick_scale(); } } - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_pose_targets_from_motion(); } speed_step(frame_time_sq * 7.5f * k, frame_time_sq * 8.5f); set_planar_vel(99999.0f); - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { adjust_hero_planar_velocity_from_probes(1); } if (hero.air_frames.s != 0) { From 6ee50fc6cdae47bbf2ef5bfb3e871c041561edbc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 00:01:00 +0000 Subject: [PATCH 1337/1502] decomp: clarify names in hero_update_transitions domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 00229cb0-00229cb4 loads +0x20A4 and compares with 1 to bypass item-use locking, matching the switch's named CLANK branch at 00229cfc -> 00229de4. The source selector hero.vehicle_mode is the same byte hero+0x20A4 used by the existing HeroVehicleMode switch at 00229cf8; canonical members are supplied by include/rnc/hero/hero_state.h. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 00229cd8-00229cdc loads +0x20A4 and compares with 1 to bypass item-selector blocking, matching the same named CLANK switch branch at 00229cfc -> 00229de4. The source selector hero.vehicle_mode is the same byte hero+0x20A4 used by the existing HeroVehicleMode switch at 00229cf8; canonical members are supplied by include/rnc/hero/hero_state.h. domain_2_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 00229f94-00229f9c compares byte +0x20A4 with 2, exempting this vehicle mode from low-height fatal-fall entry. This is the supplied canonical GIANT_CLANK member of HeroVehicleMode. The source selector hero.vehicle_mode is the same byte hero+0x20A4 used by the existing HeroVehicleMode switch at 00229cf8; canonical members are supplied by include/rnc/hero/hero_state.h. domain_3_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0022af50-0022af54 loads +0x20A4 and skips ordinary look-state animation selection when nonzero. Original Ghidra bRam001413f4==0 agrees with the existing ON_FOOT switch case. The source selector hero.vehicle_mode is the same byte hero+0x20A4 used by the existing HeroVehicleMode switch at 00229cf8; canonical members are supplied by include/rnc/hero/hero_state.h. domain_4_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0022b03c-0022b048 loads +0x20A4 and calls set_hero_idle_state_for_vehicle_mode when nonzero; zero continues through ordinary crouch/IDLE exits. Original Ghidra and bound C agree. The source selector hero.vehicle_mode is the same byte hero+0x20A4 used by the existing HeroVehicleMode switch at 00229cf8; canonical members are supplied by include/rnc/hero/hero_state.h. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0022bdcc-0022bdd0 loads +0x20A4 and excludes zero from target-pose braking transition 0x66. Original Ghidra case 0x65 tests bRam001413f4==0 on the same vehicle selector. The source selector hero.vehicle_mode is the same byte hero+0x20A4 used by the existing HeroVehicleMode switch at 00229cf8; canonical members are supplied by include/rnc/hero/hero_state.h. domain_6_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 00231a3c-00231a40 loads +0x20A4 and allows ordinary look-release animation selection only for zero. Original Ghidra case 0x1e and the bound C identify this same ON_FOOT domain. The source selector hero.vehicle_mode is the same byte hero+0x20A4 used by the existing HeroVehicleMode switch at 00229cf8; canonical members are supplied by include/rnc/hero/hero_state.h. --- src/overlays/shared/hero/hero_update_transitions.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/hero/hero_update_transitions.c b/src/overlays/shared/hero/hero_update_transitions.c index 84e1b8daad..80ffa368f3 100644 --- a/src/overlays/shared/hero/hero_update_transitions.c +++ b/src/overlays/shared/hero/hero_update_transitions.c @@ -200,8 +200,8 @@ void hero_update_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L00_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0)) { switch (hero.vehicle_mode) { case HERO_VEHICLE_MODE_ON_FOOT: case 3: { @@ -280,7 +280,7 @@ void hero_update_transitions(void) { } } if (D_L00_0015F638 > hero.motion.pos.f[2] && hero.ground_distance > 2.0f && - hero.vehicle_mode != 2 && hero.state.current != 0x77) { + hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { hero_set_state(0x77, 1); } else { switch (hero.state.current) { @@ -696,7 +696,7 @@ void hero_update_transitions(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (hero.moby->prev_seq != 0xD) { @@ -723,7 +723,7 @@ void hero_update_transitions(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { set_hero_idle_state_for_vehicle_mode(); break; } @@ -1035,7 +1035,7 @@ void hero_update_transitions(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; @@ -3292,7 +3292,7 @@ void hero_update_transitions(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (hero.moby->prev_seq != 0xD) { From fadee477eefd08c4db37b80dd40d2e3f37db6087 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 00:08:43 +0000 Subject: [PATCH 1338/1502] decomp: clarify names in update_hero_state_transitions domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: The source selector hero.vehicle_mode is the retail unsigned byte hero+0x20A4 (absolute 0x001413F4), loaded for vehicle dispatch at 0x00225a30; this switch already uses HERO_VEHICLE_MODE_ON_FOOT=0 and HERO_VEHICLE_MODE_CLANK=1. It is distinct from current-state +0x2084 and control-mode +0x208C, proving the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. Retail 0x002259e4-0x002259ec compares that byte with 1 to bypass item-use lock before HUD selection; original Ghidra bRam001413f4 == 1 and source agree. domain_1_value_1 -> HERO_VEHICLE_MODE_CLANK: The source selector hero.vehicle_mode is the retail unsigned byte hero+0x20A4 (absolute 0x001413F4), loaded for vehicle dispatch at 0x00225a30; this switch already uses HERO_VEHICLE_MODE_ON_FOOT=0 and HERO_VEHICLE_MODE_CLANK=1. It is distinct from current-state +0x2084 and control-mode +0x208C, proving the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. Retail 0x00225a0c-0x00225a14 again compares that byte with 1 to bypass item-select blocking; the identical byte's dispatch selects the established Clank four-slot HUD at 0x00225a34 and 0x00225b1c. domain_2_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: The source selector hero.vehicle_mode is the retail unsigned byte hero+0x20A4 (absolute 0x001413F4), loaded for vehicle dispatch at 0x00225a30; this switch already uses HERO_VEHICLE_MODE_ON_FOOT=0 and HERO_VEHICLE_MODE_CLANK=1. It is distinct from current-state +0x2084 and control-mode +0x208C, proving the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. Retail 0x00225ccc-0x00225cd4 compares the same vehicle byte with 2, exempting this mode from the low-position, ground-distance fatal-fall transition. Original Ghidra bRam001413f4 != 2 agrees; shared HeroVehicleMode canonically names 2 GIANT_CLANK. domain_3_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The source selector hero.vehicle_mode is the retail unsigned byte hero+0x20A4 (absolute 0x001413F4), loaded for vehicle dispatch at 0x00225a30; this switch already uses HERO_VEHICLE_MODE_ON_FOOT=0 and HERO_VEHICLE_MODE_CLANK=1. It is distinct from current-state +0x2084 and control-mode +0x208C, proving the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. Retail 0x00226c88-0x00226c8c tests vehicle byte +0x20A4 against zero before LOOK animation selection. Ghidra case 1 bRam001413f4 == 0 matches source and the existing on-foot switch member. domain_4_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The source selector hero.vehicle_mode is the retail unsigned byte hero+0x20A4 (absolute 0x001413F4), loaded for vehicle dispatch at 0x00225a30; this switch already uses HERO_VEHICLE_MODE_ON_FOOT=0 and HERO_VEHICLE_MODE_CLANK=1. It is distinct from current-state +0x2084 and control-mode +0x208C, proving the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. Retail 0x00226d74-0x00226d80 tests vehicle byte +0x20A4 against zero and calls enter_hero_idle_state_for_current_vehicle_mode for nonzero modes; zero continues to on-foot crouch/idle handling. domain_5_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The source selector hero.vehicle_mode is the retail unsigned byte hero+0x20A4 (absolute 0x001413F4), loaded for vehicle dispatch at 0x00225a30; this switch already uses HERO_VEHICLE_MODE_ON_FOOT=0 and HERO_VEHICLE_MODE_CLANK=1. It is distinct from current-state +0x2084 and control-mode +0x208C, proving the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. Retail 0x00227b04-0x00227b08 tests the identical vehicle byte for nonzero before allowing the target-pose braking state at sufficient speed. Original Ghidra case 0x65 bRam001413f4 == 0 exit agrees with the source != 0 guard. domain_6_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: The source selector hero.vehicle_mode is the retail unsigned byte hero+0x20A4 (absolute 0x001413F4), loaded for vehicle dispatch at 0x00225a30; this switch already uses HERO_VEHICLE_MODE_ON_FOOT=0 and HERO_VEHICLE_MODE_CLANK=1. It is distinct from current-state +0x2084 and control-mode +0x208C, proving the supplied shared HeroVehicleMode domain in include/rnc/hero/hero_state.h. Retail 0x0022cd24-0x0022cd28 tests the same +0x20A4 byte against zero in LOOK_RELEASE_WAIT, enabling the on-foot animation selection before held-mask-5 release processing. Original Ghidra case 0x1e and source agree. --- .../l17/hero/update_hero_state_transitions.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l17/hero/update_hero_state_transitions.c b/src/overlays/l17/hero/update_hero_state_transitions.c index a048a27c1b..69623167dc 100644 --- a/src/overlays/l17/hero/update_hero_state_transitions.c +++ b/src/overlays/l17/hero/update_hero_state_transitions.c @@ -199,8 +199,8 @@ void update_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L17_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == 1 || hero.unk1B2 != 0)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0)) { switch (hero.vehicle_mode) { case HERO_VEHICLE_MODE_ON_FOOT: case 3: { @@ -279,7 +279,7 @@ void update_hero_state_transitions(void) { } } if (D_L17_0015F638 > hero.motion.pos.f[2] && hero.ground_distance > 2.0f && - hero.vehicle_mode != 2 && hero.state.current != 0x77) { + hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && hero.state.current != 0x77) { hero_set_state(0x77, 1); } else { switch (hero.state.current) { @@ -697,7 +697,7 @@ void update_hero_state_transitions(void) { } break; case HERO_STATE_LOOK: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { @@ -724,7 +724,7 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { enter_hero_idle_state_for_current_vehicle_mode(); break; } @@ -1041,7 +1041,7 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != 0 && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; @@ -3038,7 +3038,7 @@ void update_hero_state_transitions(void) { } break; case HERO_STATE_LOOK_RELEASE_WAIT: - if (hero.vehicle_mode == 0) { + if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { if (hero.unk20AA == 0 || hero.unk20A5 != 0) { if (controller_state.held & 0xA) { if (((unsigned char *)hero.moby)[0x53] != 0xD) { From 0ff3e1abc0a34e7b8aba39921494f5b6212154ce Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 11:57:23 +0000 Subject: [PATCH 1339/1502] decomp: format naming changes after upstream rebase --- .../shared/math/interpolation/spring_turn.h | 3 +- .../shared/rendering/effects/particles.h | 3 +- src/audio/music/music_update_stream.c | 6 +- src/audio/voices/pause_all_sounds.c | 3 +- src/audio/voices/sound_update.c | 5 +- src/camera/switch_active_camera_record.c | 15 +- src/camera/update_camera.c | 5 +- src/camera/update_camera_blend.c | 5 +- src/game/transitions/do_space_transition.c | 6 +- src/game/update_level_gameplay_frame.c | 7 +- src/game/update_resident_gameplay_state.c | 4 +- src/mobys/create_moby.c | 3 +- .../decoder/buffers/read_buf_begin_get.c | 4 +- .../decoder/video_output/vo_buf_create.c | 6 +- .../decoder/video_output/vo_buf_get_tag.c | 4 +- src/overlays/l00/level_class_tables.c | 4 +- src/overlays/l00/mobys/help_hints.c | 6 +- src/overlays/l00/mobys/veldin_robot_enemy.c | 9 +- src/overlays/l01/hero/hero_set_state.c | 21 +- .../update_hero_motion_for_current_state.c | 3 +- .../l01/hero/update_hero_state_machine.c | 9 +- src/overlays/l01/mobys/birdbot.c | 6 +- src/overlays/l01/mobys/bomber_jet.c | 5 +- src/overlays/l01/mobys/falling_rock.c | 4 +- src/overlays/l01/mobys/help_hints.c | 21 +- src/overlays/l01/mobys/water_lily.c | 18 +- src/overlays/l02/hero/hero_set_state.c | 27 +- .../l02/hero/update_hero_state_motion.c | 6 +- src/overlays/l02/mobys/constructorbot.c | 12 +- src/overlays/l02/mobys/liftcar_platform.c | 9 +- src/overlays/l02/mobys/sand_shark.c | 26 +- src/overlays/l02/mobys/transport_pod.c | 6 +- src/overlays/l03/hero/hero_set_state.c | 18 +- .../update_hero_motion_for_current_state.c | 9 +- .../l03/hero/update_hero_state_machine.c | 9 +- src/overlays/l03/level_class_tables.c | 4 +- src/overlays/l03/mobys/help_hints.c | 11 +- src/overlays/l03/mobys/kerwan_path_enemy.c | 26 +- .../l03/mobys/metropolis_train_carriage.c | 5 +- src/overlays/l03/mobys/mine.c | 6 +- src/overlays/l03/mobys/mine_layer.c | 6 +- src/overlays/l03/mobys/path_mover_spawner.c | 6 +- src/overlays/l03/mobys/robot_dog.c | 10 +- src/overlays/l03/mobys/robot_qwark.c | 3 +- src/overlays/l04/level_class_tables.c | 4 +- src/overlays/l04/mobys/big_axebot.c | 3 +- src/overlays/l04/mobys/blarg_trooper.c | 32 +- src/overlays/l04/mobys/circular_saw_enemy.c | 28 +- src/overlays/l04/mobys/snow_plow.c | 5 +- src/overlays/l04/mobys/suck_cannon.c | 19 +- .../l04/mobys/translation_delta_matrix.c | 5 +- src/overlays/l04/mobys/woodcut_bot.c | 10 +- .../hero/apply_hero_ground_material_effects.c | 6 +- src/overlays/l05/hero/hero_set_state.c | 18 +- .../l05/hero/update_hero_motion_by_state.c | 11 +- .../l05/hero/update_hero_state_machine.c | 9 +- src/overlays/l05/level_class_tables.c | 4 +- src/overlays/l05/mobys/amoeboid.c | 23 +- src/overlays/l05/mobys/extermibot.c | 69 +-- src/overlays/l05/mobys/extermitank.c | 34 +- src/overlays/l05/mobys/fog_zone.c | 6 +- src/overlays/l05/mobys/rising_gate.c | 13 +- src/overlays/l05/mobys/taxi.c | 5 +- src/overlays/l05/mobys/triggered_motion.c | 18 +- src/overlays/l05/mobys/triggered_slide.c | 5 +- src/overlays/l06/hero/hero_set_state.c | 18 +- .../update_hero_motion_for_current_state.c | 29 +- .../l06/hero/update_hero_state_machine.c | 9 +- src/overlays/l06/level_class_tables.c | 4 +- src/overlays/l06/mobys/alien_queen.c | 50 +- src/overlays/l06/mobys/alien_snapper.c | 132 ++++-- src/overlays/l06/mobys/beam_barrier.c | 16 +- src/overlays/l06/mobys/countdown_sequence.c | 8 +- src/overlays/l06/mobys/elevator.c | 9 +- src/overlays/l06/mobys/hangar_door.c | 17 +- src/overlays/l06/mobys/shuttle.c | 117 +++-- src/overlays/l06/mobys/split_door.c | 6 +- .../l07/mobys/equalizer_ammo_spawner.c | 7 +- .../l07/mobys/mission_gated_taxi_platform.c | 6 +- src/overlays/l07/mobys/snagglebeast.c | 8 +- .../l07/mobys/umbris_scene_progression.c | 12 +- src/overlays/l07/mobys/water.c | 3 +- src/overlays/l08/hero/hero_set_state.c | 18 +- .../update_hero_motion_for_current_state.c | 3 +- .../l08/hero/update_hero_state_transitions.c | 9 +- src/overlays/l08/level_class_tables.c | 4 +- src/overlays/l08/mobys/blarg_bombthrower.c | 12 +- src/overlays/l08/mobys/bomb.c | 61 ++- src/overlays/l08/mobys/bomber_tank.c | 18 +- .../l08/mobys/flickering_mesh_effect.c | 6 +- src/overlays/l08/mobys/swing_gate.c | 7 +- .../l09/draw_level09_textured_surfaces.c | 3 +- src/overlays/l09/level_class_tables.c | 4 +- src/overlays/l09/mobys/damage_causer.c | 6 +- src/overlays/l09/mobys/refueling_station.c | 4 +- src/overlays/l10/level_class_tables.c | 2 +- src/overlays/l10/mobys/blarg_ship.c | 10 +- src/overlays/l10/mobys/darter.c | 115 +++-- src/overlays/l10/mobys/jitter_strand_grid.c | 12 +- src/overlays/l10/mobys/linked_moby_hitbox.c | 9 +- src/overlays/l10/mobys/toxic_crab.c | 74 ++- src/overlays/l11/hero/hero_set_state.c | 18 +- .../l11/hero/update_hero_motion_by_state.c | 11 +- .../l11/hero/update_hero_state_transitions.c | 9 +- src/overlays/l11/mobys/bubble.c | 12 +- src/overlays/l11/mobys/energy_sphere.c | 31 +- src/overlays/l11/mobys/jet_fighter.c | 35 +- src/overlays/l11/mobys/owner_linked_moby.c | 8 +- src/overlays/l11/mobys/puffoid.c | 34 +- src/overlays/l11/mobys/resort_owner.c | 9 +- src/overlays/l11/mobys/teleporter.c | 5 +- src/overlays/l12/hero/hero_set_state.c | 18 +- .../update_hero_motion_for_current_state.c | 6 +- .../l12/hero/update_hero_state_transitions.c | 9 +- src/overlays/l12/level_class_tables.c | 4 +- src/overlays/l12/mobys/blarg_helicopter.c | 19 +- src/overlays/l12/mobys/blarg_trooper.c | 3 +- src/overlays/l12/mobys/homing_mine_spawner.c | 5 +- src/overlays/l12/mobys/hoven_anklebiter.c | 46 +- src/overlays/l12/mobys/hoven_turret.c | 52 +-- .../l12/mobys/planetbuster_maximus_part.c | 9 +- src/overlays/l13/level_class_tables.c | 2 +- src/overlays/l13/mobys/attached_rocket.c | 22 +- src/overlays/l13/mobys/blarg_space_fighter.c | 18 +- src/overlays/l13/mobys/elevator.c | 3 +- src/overlays/l13/mobys/fighter_jet.c | 3 +- .../l13/mobys/gemlik_scene_controller.c | 7 +- .../l13/mobys/hovering_rocket_attacker.c | 5 +- src/overlays/l13/mobys/lift.c | 3 +- src/overlays/l13/mobys/mine.c | 9 +- src/overlays/l13/mobys/moby_path_follower.c | 8 +- src/overlays/l13/mobys/qwarks_starfighter.c | 24 +- .../l13/mobys/tracked_group_watcher.c | 7 +- src/overlays/l14/hero/hero_set_state.c | 18 +- .../l14/hero/process_hero_state_transitions.c | 9 +- .../l14/hero/update_hero_motion_by_state.c | 12 +- src/overlays/l14/level_class_tables.c | 2 +- .../l14/mobys/blarg_heavy_interceptor.c | 46 +- src/overlays/l14/mobys/bolt_thief.c | 5 +- src/overlays/l14/mobys/bouncing_spark.c | 3 +- src/overlays/l14/mobys/elevator.c | 6 +- src/overlays/l14/mobys/enemy_fighter.c | 6 +- src/overlays/l14/mobys/flying_car.c | 4 +- src/overlays/l14/mobys/machinegun_turret.c | 10 +- src/overlays/l14/mobys/minibomber.c | 28 +- src/overlays/l14/mobys/morphoray_pickup.c | 13 +- .../l14/mobys/path_lightning_controller.c | 8 +- src/overlays/l14/mobys/platform.c | 6 +- .../l14/mobys/rocket_strike_fighter.c | 11 +- src/overlays/l14/mobys/taxi.c | 3 +- src/overlays/l14/mobys/wind_control.c | 6 +- src/overlays/l14/path_key_camera.c | 17 +- src/overlays/l15/hero/hero_set_state.c | 18 +- .../update_hero_motion_for_current_state.c | 3 +- .../l15/hero/update_hero_state_machine.c | 9 +- src/overlays/l15/level_class_tables.c | 2 +- src/overlays/l15/mobys/construction_arm.c | 3 +- src/overlays/l15/mobys/exploding_prop.c | 6 +- src/overlays/l15/mobys/helicopter.c | 25 +- src/overlays/l15/mobys/help_hints.c | 3 +- src/overlays/l15/mobys/poison_vessel.c | 3 +- .../l15/mobys/radial_exploding_prop.c | 6 +- src/overlays/l15/mobys/ultramech_scientist.c | 5 +- src/overlays/l15/mobys/ultramech_unlimited.c | 30 +- .../hero/apply_hero_ground_material_effects.c | 6 +- src/overlays/l16/hero/hero_set_state.c | 18 +- .../update_hero_motion_for_current_state.c | 11 +- .../l16/hero/update_hero_state_transitions.c | 9 +- src/overlays/l16/level_class_tables.c | 4 +- src/overlays/l16/mobys/path_walker.c | 7 +- .../l16/mobys/spinning_sprite_effect.c | 19 +- src/overlays/l16/mobys/test_dummy.c | 3 +- src/overlays/l16/mobys/wall_button_blocker.c | 6 +- src/overlays/l17/hero/hero_set_state.c | 18 +- .../update_hero_motion_for_current_state.c | 11 +- .../l17/hero/update_hero_state_transitions.c | 9 +- src/overlays/l17/level_class_tables.c | 4 +- src/overlays/l17/mobys/camera_box_watcher.c | 3 +- src/overlays/l17/mobys/dreks_fleet_turret.c | 3 +- src/overlays/l17/mobys/fighter_jet.c | 4 +- src/overlays/l17/mobys/fleet_backdrop.c | 6 +- src/overlays/l17/mobys/magnet_elevator.c | 5 +- src/overlays/l17/mobys/robot_dog.c | 6 +- src/overlays/l18/hero/hero_set_state.c | 18 +- .../l18/hero/process_hero_state_transitions.c | 9 +- .../update_hero_motion_for_current_state.c | 11 +- src/overlays/l18/level_class_tables.c | 4 +- src/overlays/l18/mobys/camera_transition.c | 16 +- .../l18/mobys/drek_boss_electric_ball.c | 56 ++- src/overlays/l18/mobys/drek_fight_missile.c | 17 +- .../l18/mobys/drek_final_boss_robot.c | 35 +- src/overlays/l18/mobys/floating_platform.c | 3 +- src/overlays/l18/mobys/gadgebot.c | 3 +- src/overlays/l18/mobys/inert_moby.c | 6 +- src/overlays/l18/mobys/rocket.c | 5 +- .../l18/mobys/thruster_pack_lock_red.c | 8 +- .../shared/camera/follow_camera_setup.c | 13 +- .../shared/camera/follow_camera_springs.c | 32 +- src/overlays/shared/camera/grindrail_camera.c | 3 +- .../shared/camera/moby_controlled_camera.c | 44 +- .../shared/camera/path_flythrough_camera.c | 16 +- src/overlays/shared/camera/scripted_camera.c | 5 +- .../shared/camera/swing_volume_camera.c | 53 ++- .../cutscenes/update_cutscene_playback.c | 4 +- .../shared/cutscenes/update_npc_dialogue.c | 3 +- src/overlays/shared/enemies/armed_transport.c | 17 +- .../shared/enemies/armed_transport_rocket.c | 5 +- .../shared/enemies/blarg_elite_commando.c | 9 +- .../shared/enemies/blarg_helicopter.c | 12 +- .../shared/enemies/blarg_paratrooper.c | 31 +- .../shared/enemies/blarg_ship_rocket.c | 14 +- src/overlays/shared/enemies/bomb_spawner.c | 9 +- .../shared/enemies/bomb_spawner_bomb.c | 25 +- .../shared/enemies/bomber_jet_projectile.c | 9 +- src/overlays/shared/enemies/frog.c | 40 +- src/overlays/shared/enemies/gadgebot.c | 26 +- .../shared/enemies/ground_melee_enemy.c | 3 +- .../shared/enemies/hero_seeking_mine.c | 8 +- src/overlays/shared/enemies/horny_toad.c | 36 +- src/overlays/shared/enemies/large_amoeboid.c | 9 +- .../shared/enemies/path_or_ballistic_debris.c | 5 +- src/overlays/shared/enemies/plasmabot.c | 11 +- src/overlays/shared/enemies/sandmouse.c | 6 +- src/overlays/shared/enemies/scoutbot.c | 10 +- src/overlays/shared/enemies/sentrybot.c | 34 +- src/overlays/shared/enemies/sentrybot_alarm.c | 29 +- .../shared/game/run_level_main_loop.c | 6 +- src/overlays/shared/hero/hero_frame_update.c | 3 +- src/overlays/shared/hero/hero_idle_sequence.c | 11 +- .../shared/hero/hero_move_state_velocity.c | 9 +- src/overlays/shared/hero/hero_set_state.c | 18 +- src/overlays/shared/hero/hero_switch_item.c | 24 +- .../shared/hero/hero_update_movement.c | 434 +++++++++++++----- .../shared/hero/hero_update_transitions.c | 9 +- .../hero/process_hero_primary_item_input.c | 9 +- src/overlays/shared/hero/set_hero_animation.c | 7 +- .../shared/hero/update_hero_ground_contact.c | 3 +- .../shared/math/interpolation/spring_turn.c | 40 +- .../mobys/allocate_moby_animation_slot.c | 29 +- .../mobys/evaluate_moby_animation_pose.c | 4 +- .../mobys/select_auto_aim_target_moby.c | 4 +- .../mobys/test_path_segment_strict_crossing.c | 27 +- .../mobys/update_object_wander_movement.c | 20 +- src/overlays/shared/pickups/buried_bolts.c | 6 +- src/overlays/shared/pickups/crate.c | 6 +- .../shared/pickups/fighter_jet_crate.c | 6 +- src/overlays/shared/pickups/gadget_pickup.c | 29 +- src/overlays/shared/pickups/gold_bolt.c | 32 +- src/overlays/shared/pickups/infobot.c | 20 +- src/overlays/shared/pickups/nanotech_ball.c | 48 +- src/overlays/shared/pickups/pilots_helmet.c | 19 +- src/overlays/shared/pickups/weapon_ammo.c | 3 +- src/overlays/shared/props/bolt_crank.c | 7 +- src/overlays/shared/props/breakable_lamp.c | 6 +- src/overlays/shared/props/electric_water.c | 27 +- .../shared/props/energy_sphere_holder.c | 18 +- src/overlays/shared/props/escalator.c | 8 +- src/overlays/shared/props/floor_button.c | 12 +- .../shared/props/linked_spark_emitter.c | 7 +- .../shared/props/moby_state_trigger.c | 5 +- src/overlays/shared/props/teleporter.c | 9 +- src/overlays/shared/props/trespasser_pad.c | 42 +- .../rendering/debug/update_debug_menu.c | 3 +- .../shared/rendering/effects/particles.c | 40 +- .../update_three_phase_effect_particle.c | 35 +- .../ui/hud/draw_hud_item_selector_panel.c | 19 +- .../shared/ui/hud/draw_hud_segment_meter.c | 11 +- .../shared/ui/menus/initialize_pause_menu.c | 16 +- .../shared/vehicles/fighter_jet_missile.c | 5 +- .../shared/vehicles/fighter_jet_rocket.c | 6 +- .../vehicles/giant_clank_charged_blast.c | 8 +- .../shared/vehicles/giant_clank_missile.c | 53 ++- .../shared/vehicles/giant_clank_pad.c | 3 +- src/overlays/shared/vehicles/gunship.c | 7 +- src/overlays/shared/vehicles/hoverboard.c | 28 +- src/overlays/shared/vehicles/ship_rocket.c | 9 +- src/overlays/shared/vehicles/veldin_ship.c | 3 +- .../shared/vendor/draw_vendor_purchase_text.c | 20 +- src/overlays/shared/vendor/vendor.c | 6 +- src/overlays/shared/vendor/vendor_menu.c | 33 +- src/overlays/shared/weapons/bomb_glove_bomb.c | 15 +- src/overlays/shared/weapons/decoy.c | 10 +- src/overlays/shared/weapons/decoy_glove.c | 17 +- src/overlays/shared/weapons/doom_bot.c | 3 +- src/overlays/shared/weapons/drone.c | 22 +- .../shared/weapons/effect_slots_fire.c | 14 +- .../shared/weapons/glove_of_doom_bomb.c | 10 +- .../shared/weapons/gold_devastator_missile.c | 3 +- src/overlays/shared/weapons/metal_detector.c | 3 +- src/overlays/shared/weapons/mine.c | 35 +- src/overlays/shared/weapons/morphoray.c | 113 +++-- .../shared/weapons/morphoray_chicken.c | 32 +- src/overlays/shared/weapons/suckcannon.c | 22 +- src/overlays/shared/weapons/swingshot_hook.c | 3 +- src/overlays/shared/weapons/tesla_claw.c | 9 +- src/overlays/shared/weapons/turret_rocket.c | 18 +- .../shared/weapons/visibomb_missile.c | 18 +- src/overlays/shared/weapons/wrench.c | 7 +- .../shared/world/load_level_gameplay.c | 9 +- src/rendering/debug/draw_debug_profiler.c | 3 +- src/rendering/frame/render_level_frame.c | 3 +- .../mobys/render_environment_mapped_object.c | 6 +- src/sdk/mpeg/picture/_pictureData0.c | 6 +- src/sdk/mpeg/ref_images/_updateRefImage.c | 6 +- src/sdk/mpeg/ref_images/disprefimagefield.c | 3 +- .../update_menu_preview_class_pose.c | 5 +- .../draw_checking_memory_card_data_menu.c | 3 +- src/ui/menus/save_data/draw_save_slot_list.c | 7 +- src/ui/menus/save_data/loading_data_menu.c | 6 +- .../save_card_state_create_save_pending.c | 3 +- .../menus/save_data/save_card_state_saving.c | 3 +- .../stream_image/update_menu_stream_image.c | 3 +- src/ui/menus/widgets/draw_menu_item_grid.c | 3 +- .../menus/widgets/draw_menu_selection_text.c | 3 +- src/ui/menus/widgets/enter_menu_help_text.c | 5 +- src/ui/text/link_localized_display_text.c | 5 +- 316 files changed, 3284 insertions(+), 1607 deletions(-) diff --git a/include/rnc/overlay/shared/math/interpolation/spring_turn.h b/include/rnc/overlay/shared/math/interpolation/spring_turn.h index dfdec7efe4..980cff2ac2 100644 --- a/include/rnc/overlay/shared/math/interpolation/spring_turn.h +++ b/include/rnc/overlay/shared/math/interpolation/spring_turn.h @@ -8,7 +8,8 @@ s32 get_first_moby_in_group(void *, s32, s32, s32) __asm__("FUN_L00_002591d0"); s32 solve_quadratic_equation(f32 *, f32 *, f32, f32, f32) __asm__("FUN_L00_002595a0"); s32 get_next_moby_in_group(void *, void *, s32, s32) __asm__("FUN_L00_002592b8"); -void move_moby_xy_with_collision_constraints(void *, void *, void *, s32, f32, f32, f32, f32) __asm__("FUN_L00_00258490"); +void move_moby_xy_with_collision_constraints( + void *, void *, void *, s32, f32, f32, f32, f32) __asm__("FUN_L00_00258490"); float calculate_triangular_corrected_scalar(float *, float *, int *, diff --git a/include/rnc/overlay/shared/rendering/effects/particles.h b/include/rnc/overlay/shared/rendering/effects/particles.h index c256e2d9d5..b815c507d8 100644 --- a/include/rnc/overlay/shared/rendering/effects/particles.h +++ b/include/rnc/overlay/shared/rendering/effects/particles.h @@ -14,7 +14,8 @@ void *spawn_mode_controlled_rotating_alpha_fade_particle(void *, struct EmberParticle; struct EffectParticle; -unsigned char *spawn_timed_hero_relative_particle(u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); +unsigned char *spawn_timed_hero_relative_particle( + u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); unsigned char *spawn_color_tween_emitter_particle(void *, unsigned char, unsigned char, diff --git a/src/audio/music/music_update_stream.c b/src/audio/music/music_update_stream.c index 3a416b86ca..36794746b4 100644 --- a/src/audio/music/music_update_stream.c +++ b/src/audio/music/music_update_stream.c @@ -79,7 +79,8 @@ void music_update_stream(MusicPlaying *music_stream) { if (music_stream->state == 1 || music_stream->state == 8 || music_stream->state == 9) { return; } - if (music_stream->state != MUSIC_STREAM_STATE_WAITING_FOR_BUFFER && music_stream->state != 3) { + if (music_stream->state != MUSIC_STREAM_STATE_WAITING_FOR_BUFFER && + music_stream->state != 3) { sound_handle = music_stream->handle; music_stream->handle = 0xFFFFFFFF; snd_get_vag_stream_time_remaining_cb( @@ -88,7 +89,8 @@ void music_update_stream(MusicPlaying *music_stream) { sound_handle, set_sound_handle_id, (long)(unsigned int)music_stream); return; } - if (music_stream->handle != 0xFFFFFFFF && music_stream->state == MUSIC_STREAM_STATE_WAITING_FOR_BUFFER) { + if (music_stream->handle != 0xFFFFFFFF && + music_stream->state == MUSIC_STREAM_STATE_WAITING_FOR_BUFFER) { snd_is_vag_stream_buffered_cb(music_stream->handle, music_channel_ready_callback, (long)(unsigned int)music_stream); diff --git a/src/audio/voices/pause_all_sounds.c b/src/audio/voices/pause_all_sounds.c index 4e53d957b6..a8fbf4c650 100644 --- a/src/audio/voices/pause_all_sounds.c +++ b/src/audio/voices/pause_all_sounds.c @@ -30,7 +30,8 @@ extern s32 D_00141660[]; extern u8 D_0014161B NOT_SDA; extern s32 D_0015EEA0_macro __asm__("D_0015EEA0") MACRO_ADDR; extern s32 alternate_animation_sequence_macro __asm__("D_0015EE20") MACRO_ADDR; -extern s32 help_history_selected_index[] __asm__("D_001D0398"); /* help_history_list list.selected */ +extern s32 + help_history_selected_index[] __asm__("D_001D0398"); /* help_history_list list.selected */ extern void update_skill_point_and_gold_weapon_menu_entries() __asm__("func_00226E58"); diff --git a/src/audio/voices/sound_update.c b/src/audio/voices/sound_update.c index a416cf438e..c72f174ecc 100644 --- a/src/audio/voices/sound_update.c +++ b/src/audio/voices/sound_update.c @@ -172,8 +172,9 @@ s32 sound_update(void) { } { s32 state = voice_pool.voices[slot_index].state; - if (state == VOICE_SLOT_STOP_REQUESTED || (state != VOICE_SLOT_STOP_PENDING && owner_removed && - voice_pool.voices[slot_index].definition->source_state != 0)) { + if (state == VOICE_SLOT_STOP_REQUESTED || + (state != VOICE_SLOT_STOP_PENDING && owner_removed && + voice_pool.voices[slot_index].definition->source_state != 0)) { voice_flags[slot_index] = 0x20; continue; } diff --git a/src/camera/switch_active_camera_record.c b/src/camera/switch_active_camera_record.c index fd196817dc..c2a944f5bc 100644 --- a/src/camera/switch_active_camera_record.c +++ b/src/camera/switch_active_camera_record.c @@ -88,7 +88,9 @@ void switch_active_camera_record(struct UpdateCam *next_camera) { } if (previous_transition_state == CAMERA_TRANSITION_STATE_BLOCK_ACTIVATION) { next_camera->activation_blocked = 1; - } else if (previous_transition_state == CAMERA_TRANSITION_STATE_REQUEST_TRANSITION || descriptor_kind == CAMERA_DESCRIPTOR_RATE_TRANSITION || descriptor_kind == CAMERA_DESCRIPTOR_FRAME_COUNT_TRANSITION) { + } else if (previous_transition_state == CAMERA_TRANSITION_STATE_REQUEST_TRANSITION || + descriptor_kind == CAMERA_DESCRIPTOR_RATE_TRANSITION || + descriptor_kind == CAMERA_DESCRIPTOR_FRAME_COUNT_TRANSITION) { if (descriptor_kind == CAMERA_DESCRIPTOR_RATE_TRANSITION) { mode_one_duration = next_camera->transition_duration; preview_camera.transition_mode = CAMERA_TRANSITION_RATE_BASED; @@ -113,14 +115,19 @@ void switch_active_camera_record(struct UpdateCam *next_camera) { } else { preview_camera.transition_phase = 2; } - } else if (previous_transition_state == CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM || previous_transition_state == CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM_WITH_RATE_TRANSITION || - descriptor_kind == CAMERA_DESCRIPTOR_INHERIT_TRANSFORM || descriptor_kind == CAMERA_DESCRIPTOR_INHERIT_TRANSFORM_WITH_RATE_TRANSITION) { + } else if (previous_transition_state == CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM || + previous_transition_state == + CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM_WITH_RATE_TRANSITION || + descriptor_kind == CAMERA_DESCRIPTOR_INHERIT_TRANSFORM || + descriptor_kind == CAMERA_DESCRIPTOR_INHERIT_TRANSFORM_WITH_RATE_TRANSITION) { qcopy(&next_camera->pos, &previous_camera->pos); qcopy(&next_camera->m0, &previous_camera->m0); qcopy(&next_camera->m1, &previous_camera->m1); qcopy(&next_camera->m2, &previous_camera->m2); next_camera->handoff_state = CAMERA_HANDOFF_INHERITED_TRANSFORM; - if (previous_camera->transition_state == CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM_WITH_RATE_TRANSITION || descriptor_kind == CAMERA_DESCRIPTOR_INHERIT_TRANSFORM_WITH_RATE_TRANSITION) { + if (previous_camera->transition_state == + CAMERA_TRANSITION_STATE_INHERIT_TRANSFORM_WITH_RATE_TRANSITION || + descriptor_kind == CAMERA_DESCRIPTOR_INHERIT_TRANSFORM_WITH_RATE_TRANSITION) { handoff_duration = next_camera->transition_duration; preview_camera.transition_mode = CAMERA_TRANSITION_RATE_BASED; if (handoff_duration > 0.0f) { diff --git a/src/camera/update_camera.c b/src/camera/update_camera.c index e2714f90d6..2cc13d45c8 100644 --- a/src/camera/update_camera.c +++ b/src/camera/update_camera.c @@ -30,7 +30,10 @@ void update_camera(void) __asm__("FUN_001edaa8"); extern s32 game_mode_macro __asm__("D_0015F604") MACRO_ADDR; void update_camera(void) { - enum { CAMERA_TRANSITION_PHASE_IDLE = 0 } ;struct PreviewCamera *camera; + enum { + CAMERA_TRANSITION_PHASE_IDLE = 0 + }; + struct PreviewCamera *camera; struct UpdateCam *target; char *camera_shake_base; float rotation_matrix[16]; diff --git a/src/camera/update_camera_blend.c b/src/camera/update_camera_blend.c index 82e5588e7b..5c69876c6b 100644 --- a/src/camera/update_camera_blend.c +++ b/src/camera/update_camera_blend.c @@ -15,7 +15,10 @@ extern int step_camera_blend(void *, struct CameraBlend *) __asm__("func_001ECAF void update_camera_blend(char *to_cam) __asm__("FUN_001ed2b0"); void update_camera_blend(char *to_cam) { - enum { CAMERA_TRANSITION_PHASE_IDLE = 0 } ;struct CameraTransition *transition = &cam_trans_state; + enum { + CAMERA_TRANSITION_PHASE_IDLE = 0 + }; + struct CameraTransition *transition = &cam_trans_state; int transition_complete; if (transition->kind == 0) { diff --git a/src/game/transitions/do_space_transition.c b/src/game/transitions/do_space_transition.c index f0b3cba663..3030829a40 100644 --- a/src/game/transitions/do_space_transition.c +++ b/src/game/transitions/do_space_transition.c @@ -117,7 +117,8 @@ void do_space_transition(void) { view_context.fog_far_int = 128.0f; set_background_color(0, 0, 0); if (space_load_macro < 0) { - while (memory_card_state.state >= MEMCARD_REQUEST_FORMAT || memory_card_state.pending_state >= MEMCARD_QUERY_INFO) { + while (memory_card_state.state >= MEMCARD_REQUEST_FORMAT || + memory_card_state.pending_state >= MEMCARD_QUERY_INFO) { memcard_update_state(); run_state_handler(); } @@ -223,7 +224,8 @@ void do_space_transition(void) { tick_space_transition(); } while (service_level_archive_load() == 0); } - while (memory_card_state.state != MEMCARD_DISPATCH_PENDING_OPERATION || memory_card_state.pending_state >= MEMCARD_QUERY_INFO) { + while (memory_card_state.state != MEMCARD_DISPATCH_PENDING_OPERATION || + memory_card_state.pending_state >= MEMCARD_QUERY_INFO) { FlushCache(0); sceGsSyncV(0); memcard_update_state(); diff --git a/src/game/update_level_gameplay_frame.c b/src/game/update_level_gameplay_frame.c index 464fff9da9..3136f23694 100644 --- a/src/game/update_level_gameplay_frame.c +++ b/src/game/update_level_gameplay_frame.c @@ -156,7 +156,12 @@ extern void build_object_rotation_matrix(void) __asm__("func_0022DE10"); void update_level_gameplay_frame(void) __asm__("FUN_0022eaa8"); void update_level_gameplay_frame(void) { - enum { LEVEL_RENDER_PHASE_SELECT_RANDOM_MODE = 0 , LEVEL_RENDER_PHASE_REQUEST_LOAD = 2 , LEVEL_RENDER_MODE_FADE_OUT = 4 } ;Vector4 first_position; + enum { + LEVEL_RENDER_PHASE_SELECT_RANDOM_MODE = 0, + LEVEL_RENDER_PHASE_REQUEST_LOAD = 2, + LEVEL_RENDER_MODE_FADE_OUT = 4 + }; + Vector4 first_position; Vector4 second_position; Matrix4x4 first_transform; Matrix4x4 second_transform; diff --git a/src/game/update_resident_gameplay_state.c b/src/game/update_resident_gameplay_state.c index 8c95a05622..9edefe59b1 100644 --- a/src/game/update_resident_gameplay_state.c +++ b/src/game/update_resident_gameplay_state.c @@ -244,7 +244,9 @@ void update_resident_gameplay_state(void) { } } level_render_state.player->flags &= ~1; - for (object_cursor = moby_instance_end; object_cursor->state != RESIDENT_OBJECT_STATE_LIST_END; object_cursor++) { + for (object_cursor = moby_instance_end; + object_cursor->state != RESIDENT_OBJECT_STATE_LIST_END; + object_cursor++) { if (!(object_cursor->state & 0x80) && (object_cursor->class_id == 0x4A || object_cursor->class_id == 0xCB)) { object_cursor->flags &= ~0x80; diff --git a/src/mobys/create_moby.c b/src/mobys/create_moby.c index 371aadadc5..5424052b36 100644 --- a/src/mobys/create_moby.c +++ b/src/mobys/create_moby.c @@ -22,7 +22,8 @@ struct Moby *create_moby(s32 oclass) { struct Moby *moby_slot; for (moby_slot = moby_instance_end; moby_slot < moby_instance_perm_end; moby_slot++) { - if (moby_slot->state >= MOBY_STATE_REUSE_THRESHOLD && moby_slot->spawn_frame <= (u32)world_update_time) { + if (moby_slot->state >= MOBY_STATE_REUSE_THRESHOLD && + moby_slot->spawn_frame <= (u32)world_update_time) { if (moby_slot->state == 0xFF) { moby_slot[1].state = 0xFF; } diff --git a/src/movies/decoder/buffers/read_buf_begin_get.c b/src/movies/decoder/buffers/read_buf_begin_get.c index a65551894d..956ade4155 100644 --- a/src/movies/decoder/buffers/read_buf_begin_get.c +++ b/src/movies/decoder/buffers/read_buf_begin_get.c @@ -4,7 +4,9 @@ s32 read_buf_begin_get(struct ReadBuf *buf, u8 **ptr) __asm__("FUN_0023b9d8"); s32 read_buf_begin_get(struct ReadBuf *ring_buffer, u8 **read_start_out) { if (ring_buffer->count != 0) { - *read_start_out = ring_buffer->data + (ring_buffer->put - ring_buffer->count + ring_buffer->size) % ring_buffer->size; + *read_start_out = + ring_buffer->data + + (ring_buffer->put - ring_buffer->count + ring_buffer->size) % ring_buffer->size; } return ring_buffer->count; } diff --git a/src/movies/decoder/video_output/vo_buf_create.c b/src/movies/decoder/video_output/vo_buf_create.c index eaaf2fb606..c0db1aecd0 100644 --- a/src/movies/decoder/video_output/vo_buf_create.c +++ b/src/movies/decoder/video_output/vo_buf_create.c @@ -6,7 +6,11 @@ void vo_buf_create(struct VoBuf *buf, struct VoTag *tag, s32 size) __asm__("FUN_0023d190"); -void vo_buf_create(struct VoBuf *buffer_descriptor, struct VoData *data, struct VoTag *tag, s32 size) { +void vo_buf_create(struct VoBuf *buffer_descriptor, + struct VoData *data, + struct VoTag *tag, + + s32 size) { s32 i; buffer_descriptor->count = 0; diff --git a/src/movies/decoder/video_output/vo_buf_get_tag.c b/src/movies/decoder/video_output/vo_buf_get_tag.c index 79b32ce320..851b821a5f 100644 --- a/src/movies/decoder/video_output/vo_buf_get_tag.c +++ b/src/movies/decoder/video_output/vo_buf_get_tag.c @@ -8,5 +8,7 @@ struct VoTag *vo_buf_get_tag(struct VoBuf *picture_queue) { if (vo_buf_is_empty(picture_queue) != 0) { return 0; } - return picture_queue->tag + (picture_queue->write - picture_queue->count + picture_queue->size) % picture_queue->size; + return picture_queue->tag + + (picture_queue->write - picture_queue->count + picture_queue->size) % + picture_queue->size; } diff --git a/src/overlays/l00/level_class_tables.c b/src/overlays/l00/level_class_tables.c index a8b81d9db1..128edd5695 100644 --- a/src/overlays/l00/level_class_tables.c +++ b/src/overlays/l00/level_class_tables.c @@ -17,7 +17,9 @@ #include "rnc/overlay/shared/vehicles.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" -s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" diff --git a/src/overlays/l00/mobys/help_hints.c b/src/overlays/l00/mobys/help_hints.c index f70a674841..68d0984c4e 100644 --- a/src/overlays/l00/mobys/help_hints.c +++ b/src/overlays/l00/mobys/help_hints.c @@ -27,7 +27,11 @@ void help_hints_update(HelpMoby *moby) __asm__("FUN_L00_002e0988"); /* Moby class 1413 */ void help_hints_update(HelpMoby *moby) { - enum { HELP_HINTS_STATE_UNINITIALIZED = 0 , HELP_HINTS_STATE_INITIALIZED = 1 } ;s32 *vars; + enum { + HELP_HINTS_STATE_UNINITIALIZED = 0, + HELP_HINTS_STATE_INITIALIZED = 1 + }; + s32 *vars; s32 *target_index_ptr; s32 i; HelpTarget *target_moby; diff --git a/src/overlays/l00/mobys/veldin_robot_enemy.c b/src/overlays/l00/mobys/veldin_robot_enemy.c index 3f17e53224..c400c345ff 100644 --- a/src/overlays/l00/mobys/veldin_robot_enemy.c +++ b/src/overlays/l00/mobys/veldin_robot_enemy.c @@ -436,7 +436,14 @@ f32 veldin_robot_knockback_xy_scale_gp __asm__("D_L00_00161BDC") = 1e+01 f32 veldin_robot_knockback_z_scale_gp __asm__("D_L00_00161BE0") = 9.5f; void update_veldin_robot_damage_and_targeting(ElectroidMoby *moby) { - enum { VELDIN_ROBOT_STATE_INITIALIZE = 0 , VELDIN_ROBOT_STATE_WAIT_TO_FOLLOW_PATH = 1 , VELDIN_ROBOT_STATE_PROCESS_COLLISION_PROBES = 5 , VELDIN_ROBOT_STATE_DAMAGE_KNOCKBACK = 7 , VELDIN_ROBOT_STATE_DEATH_KNOCKBACK = 8 } ;ElectroidVars *vars; + enum { + VELDIN_ROBOT_STATE_INITIALIZE = 0, + VELDIN_ROBOT_STATE_WAIT_TO_FOLLOW_PATH = 1, + VELDIN_ROBOT_STATE_PROCESS_COLLISION_PROBES = 5, + VELDIN_ROBOT_STATE_DAMAGE_KNOCKBACK = 7, + VELDIN_ROBOT_STATE_DEATH_KNOCKBACK = 8 + }; + ElectroidVars *vars; void *anim; ElectroidHit *coll; Path *path; diff --git a/src/overlays/l01/hero/hero_set_state.c b/src/overlays/l01/hero/hero_set_state.c index 5faf741056..cc8a7ed6a5 100644 --- a/src/overlays/l01/hero/hero_set_state.c +++ b/src/overlays/l01/hero/hero_set_state.c @@ -74,7 +74,8 @@ int l01_hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((cutscene_mode == 2 || cutscene_mode == 6) && b != 2) @@ -82,8 +83,16 @@ int l01_hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -812,7 +821,8 @@ int l01_hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; @@ -1644,7 +1654,8 @@ int handle_hero_gadget_button(void) { pad_pressed_within(buttons, scale_game_frames(7), &wrench_button_history_age) != 0) { moby = hero.items[0].moby; - if (moby != 0 && is_wrench_moby((char *)moby) != 0 && moby->state == WRENCH_MOBY_STATE_READY_FOR_ATTACK) { + if (moby != 0 && is_wrench_moby((char *)moby) != 0 && + moby->state == WRENCH_MOBY_STATE_READY_FOR_ATTACK) { if ((controller_state.held & 0xa) != 0 || ((hero.state.current == 1 || hero.state.current == 0x1e) && scale_game_frames(0x14) < hero.state_timer)) { diff --git a/src/overlays/l01/hero/update_hero_motion_for_current_state.c b/src/overlays/l01/hero/update_hero_motion_for_current_state.c index 4f385d5c0d..4e2cda5cbf 100644 --- a/src/overlays/l01/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l01/hero/update_hero_motion_for_current_state.c @@ -1423,7 +1423,8 @@ void update_hero_motion_for_current_state(void) { int ok; ok = 1; - if (r->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (r->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && + hero.anim_frame > 7.0f) { ok = 0; } if (ok) { diff --git a/src/overlays/l01/hero/update_hero_state_machine.c b/src/overlays/l01/hero/update_hero_state_machine.c index b416e4c2d3..badbb2d55b 100644 --- a/src/overlays/l01/hero/update_hero_state_machine.c +++ b/src/overlays/l01/hero/update_hero_state_machine.c @@ -165,8 +165,10 @@ void update_hero_state_machine(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L01_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; @@ -911,7 +913,8 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { l01_hero_set_state(0x66, 1); } break; diff --git a/src/overlays/l01/mobys/birdbot.c b/src/overlays/l01/mobys/birdbot.c index c09b38bde5..d1ba587343 100644 --- a/src/overlays/l01/mobys/birdbot.c +++ b/src/overlays/l01/mobys/birdbot.c @@ -1243,8 +1243,10 @@ void birdbot_update(PeMoby *birdbot_moby) { } trooper_anim_finish(birdbot_moby, birdbot_vars->x60); birdbot_vars->f1CC = frame; - if (birdbot_moby->state == BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION || birdbot_moby->state == 5 || birdbot_moby->state == BIRDBOT_STATE_FIRE_BURST || - birdbot_moby->state == BIRDBOT_STATE_RECOVER_FROM_BURST || birdbot_moby->state == BIRDBOT_STATE_BRAKE_AND_FACE_TARGET) { + if (birdbot_moby->state == BIRDBOT_STATE_TRACK_TARGET_AND_SELECT_ACTION || + birdbot_moby->state == 5 || birdbot_moby->state == BIRDBOT_STATE_FIRE_BURST || + birdbot_moby->state == BIRDBOT_STATE_RECOVER_FROM_BURST || + birdbot_moby->state == BIRDBOT_STATE_BRAKE_AND_FACE_TARGET) { birdbot_vars->fE8 += frame_time_sq * 9.8f; birdbot_moby->pos.f[2] -= birdbot_vars->fE8 - 2.0f; ground = probe_ground_height(&birdbot_moby->pos, 0, 0.5f); diff --git a/src/overlays/l01/mobys/bomber_jet.c b/src/overlays/l01/mobys/bomber_jet.c index 1eea37f495..bbde8b4c74 100644 --- a/src/overlays/l01/mobys/bomber_jet.c +++ b/src/overlays/l01/mobys/bomber_jet.c @@ -261,7 +261,10 @@ void bomber_jet_update(GunshipMoby *m) __asm__("FUN_L01_002f7728"); /* Moby class 688 */ void bomber_jet_update(GunshipMoby *bomber_jet_moby) { - enum { BOMBER_JET_STATE_INITIALIZE = 0 } ;GunshipVars *gunship_vars = bomber_jet_moby->vars; + enum { + BOMBER_JET_STATE_INITIALIZE = 0 + }; + GunshipVars *gunship_vars = bomber_jet_moby->vars; GunshipFollow *sub = &gunship_vars->sub; float distance_scale; void *hit; diff --git a/src/overlays/l01/mobys/falling_rock.c b/src/overlays/l01/mobys/falling_rock.c index f09805c249..c696ef8308 100644 --- a/src/overlays/l01/mobys/falling_rock.c +++ b/src/overlays/l01/mobys/falling_rock.c @@ -137,8 +137,8 @@ void falling_rock_update(CapMoby *falling_rock) { LevelCuboid *camera_record; falling_rock_vars = falling_rock->pvars; - if (falling_rock->state != FALLING_ROCK_STATE_WAIT_FOR_TRIGGER && !fast_dec_timer_s16(&falling_rock_vars->wait) && - random_integer_below(100) < 5) { + if (falling_rock->state != FALLING_ROCK_STATE_WAIT_FOR_TRIGGER && + !fast_dec_timer_s16(&falling_rock_vars->wait) && random_integer_below(100) < 5) { CapColors colors; CapVec debris_initial_velocity; CapVec pos; diff --git a/src/overlays/l01/mobys/help_hints.c b/src/overlays/l01/mobys/help_hints.c index 6127bf06a1..cb20b872ef 100644 --- a/src/overlays/l01/mobys/help_hints.c +++ b/src/overlays/l01/mobys/help_hints.c @@ -38,7 +38,10 @@ void help_hints_update(struct Moby *moby) { enum { TUTORIAL_HINT_STATE_INITIALIZE = 0, TUTORIAL_HINT_STATE_UPDATE = 1 - } ; enum { HELP_STATE_INACTIVE = 0}; + }; + enum { + HELP_STATE_INACTIVE = 0 + }; s32 *tutorial_hint_vars; struct Moby *hint_candidate_moby; struct Moby *health_hint_candidate_moby; @@ -72,8 +75,9 @@ void help_hints_update(struct Moby *moby) { } } if (cutscene_mode_macro == 0) { - if (level_available[3] != 0 && level_available[2] == 0 && help_state.state == HELP_STATE_INACTIVE && - help_state.cur == -1 && help_records[4].count == 0) { + if (level_available[3] != 0 && level_available[2] == 0 && + help_state.state == HELP_STATE_INACTIVE && help_state.cur == -1 && + help_records[4].count == 0) { help_request(0x3E8, 4); } else if (level_available[3] == 0 && level_available[2] != 0 && help_state.state == HELP_STATE_INACTIVE && help_state.cur == -1 && @@ -104,9 +108,9 @@ void help_hints_update(struct Moby *moby) { } if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_vars[14]) && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && - hero.state.current == 1 && D_L01_0015F688 == -1 && help_state.state == HELP_STATE_INACTIVE && - help_state.cur == -1 && help_records[0x40].count != 0 && - help_records[0x41].count == 0) { + hero.state.current == 1 && D_L01_0015F688 == -1 && + help_state.state == HELP_STATE_INACTIVE && help_state.cur == -1 && + help_records[0x40].count != 0 && help_records[0x41].count == 0) { help_request(0x3ED, 0x41); } if (help_records[0x42].count < 2 && @@ -167,8 +171,9 @@ void help_hints_update(struct Moby *moby) { health_hint_candidate_moby = health_hint_candidate_moby->next) { if (health_hint_candidate_moby->oclass == 0x326 && fast_vec_dist(&health_hint_candidate_moby->pos, &hero.motion.pos) < 10.0f && - help_state.state == HELP_STATE_INACTIVE && help_state.cur == -1 && help_records[1].count == 0 && - help_records[2].count == 0 && usage_stats.stat[13].count == 0 && + help_state.state == HELP_STATE_INACTIVE && help_state.cur == -1 && + help_records[1].count == 0 && help_records[2].count == 0 && + usage_stats.stat[13].count == 0 && is_moby_in_state_one(health_hint_candidate_moby) == 0) { if (hero.health.hp < hero_max_health) { if (usage_stats.stat[13].count < 0xFFFF) { diff --git a/src/overlays/l01/mobys/water_lily.c b/src/overlays/l01/mobys/water_lily.c index e9459c6858..faaaccd92d 100644 --- a/src/overlays/l01/mobys/water_lily.c +++ b/src/overlays/l01/mobys/water_lily.c @@ -12,7 +12,9 @@ #include "qcopy.h" #include "rnc/camera.h" #include "rnc/overlay/shared/math/interpolation/spring_turn.h" -void move_moby_xy_with_collision_constraints(void *, void *, void *, s32, f32, f32, f32, f32) __asm__("FUN_L00_00258490"); + +void move_moby_xy_with_collision_constraints( + void *, void *, void *, s32, f32, f32, f32, f32) __asm__("FUN_L00_00258490"); extern f32 frame_time_macro __asm__("D_0015ED6C") MACRO_ADDR; @@ -131,13 +133,13 @@ void water_lily_update(HoverMoby *water_lily) { } } move_moby_xy_with_collision_constraints(water_lily, - &collision_adjusted_position, - &water_lily->pos, - 3, - 0.1f, - water_lily_collision_radius_gp, - 600.0f, - 1.5707964f); + &collision_adjusted_position, + &water_lily->pos, + 3, + 0.1f, + water_lily_collision_radius_gp, + 600.0f, + 1.5707964f); water_lily->pos.v.x = collision_adjusted_position.v.x; water_lily->pos.v.y = collision_adjusted_position.v.y; water_lily->pos.v.z = previous_water_lily_position.v.z; diff --git a/src/overlays/l02/hero/hero_set_state.c b/src/overlays/l02/hero/hero_set_state.c index f3187f7955..05305e4593 100644 --- a/src/overlays/l02/hero/hero_set_state.c +++ b/src/overlays/l02/hero/hero_set_state.c @@ -75,7 +75,8 @@ int hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((level_game_mode == 2 || level_game_mode == 6) && b != 2) @@ -83,8 +84,16 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -705,7 +714,8 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; @@ -1861,8 +1871,10 @@ void update_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && item_selector_hud_inhibit == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; @@ -2442,7 +2454,8 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; diff --git a/src/overlays/l02/hero/update_hero_state_motion.c b/src/overlays/l02/hero/update_hero_state_motion.c index cd1ed007ce..e59ecab0a4 100644 --- a/src/overlays/l02/hero/update_hero_state_motion.c +++ b/src/overlays/l02/hero/update_hero_state_motion.c @@ -446,7 +446,8 @@ void update_hero_ground_contact(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || + if (hero.ground_slope.f <= 0.87266463f || + hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = HH.moby; @@ -1591,7 +1592,8 @@ void update_hero_state_motion(void) { int ok; ok = 1; - if (r->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (r->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && + hero.anim_frame > 7.0f) { ok = 0; } if (ok) { diff --git a/src/overlays/l02/mobys/constructorbot.c b/src/overlays/l02/mobys/constructorbot.c index c44aa2bc53..d9daf6fffb 100644 --- a/src/overlays/l02/mobys/constructorbot.c +++ b/src/overlays/l02/mobys/constructorbot.c @@ -275,9 +275,9 @@ void constructorbot_update(struct Moby *moby) { break; case L02_BOT_MOVE_TO_POST: if (step_mover_2e3f20((char *)moby, - bot_private_vars->walk, - (float *)&l02_cuboids[bot_private_vars->post].pos, - (char *)bot_private_vars->velocity) == 4) { + bot_private_vars->walk, + (float *)&l02_cuboids[bot_private_vars->post].pos, + (char *)bot_private_vars->velocity) == 4) { if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(30)); } @@ -286,9 +286,9 @@ void constructorbot_update(struct Moby *moby) { break; case L02_BOT_WANDER: if (step_mover_2e3f20((char *)moby, - bot_private_vars->walk, - bot_private_vars->wander, - (char *)bot_private_vars->velocity) & + bot_private_vars->walk, + bot_private_vars->wander, + (char *)bot_private_vars->velocity) & 6) { if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); diff --git a/src/overlays/l02/mobys/liftcar_platform.c b/src/overlays/l02/mobys/liftcar_platform.c index c58bb18247..39b4a03a44 100644 --- a/src/overlays/l02/mobys/liftcar_platform.c +++ b/src/overlays/l02/mobys/liftcar_platform.c @@ -73,14 +73,17 @@ void liftcar_platform_update(struct Moby *moby) { if (hero.ground_moby == moby && hero.air_frames.s == 0 && moby->command == 0) { ride = 1; } else if (vector_distance_xy(&moby->pos, &hero.motion.pos) < 16.0f) { - if (moby->state == LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_BELOW && hero.motion.pos.f[2] < moby->pos.z - 5.0f) { + if (moby->state == LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_BELOW && + hero.motion.pos.f[2] < moby->pos.z - 5.0f) { ride = 1; - } else if (moby->state == LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_ABOVE && moby->pos.z + 5.0f < hero.motion.pos.f[2]) { + } else if (moby->state == LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_ABOVE && + moby->pos.z + 5.0f < hero.motion.pos.f[2]) { ride = 1; } } if (ride) { - if (moby->state == LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_BELOW || moby->state == LIFTCAR_PLATFORM_WAIT_FOR_MISSION_GATE) { + if (moby->state == LIFTCAR_PLATFORM_WAIT_FOR_RIDER_OR_HERO_BELOW || + moby->state == LIFTCAR_PLATFORM_WAIT_FOR_MISSION_GATE) { moby->state = LIFTCAR_PLATFORM_ANIMATE_THEN_WAIT_FOR_RIDER_OR_HERO_ABOVE; set_moby_animation(driver, 0, 0); platform_vars->unkA4 = allocate_voice_for_target_entry(2, 4, driver); diff --git a/src/overlays/l02/mobys/sand_shark.c b/src/overlays/l02/mobys/sand_shark.c index 442a628d5f..bc4b8be230 100644 --- a/src/overlays/l02/mobys/sand_shark.c +++ b/src/overlays/l02/mobys/sand_shark.c @@ -239,8 +239,7 @@ extern void turn_angle_e50(float *, float, float *, float, float, float) __asm__("FUN_L00_0025be00"); extern int step_moby_motion(void *, void *) __asm__("FUN_L00_0025c698"); extern void FUN_L00_00263ac8_e50(void *, int, void *, float) __asm__("FUN_L00_00263ac8"); -extern void -spawn_effect(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); +extern void spawn_effect(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); extern int FUN_L00_002dc9f0_e50(void *, void *) __asm__("FUN_L00_002dc9f0"); extern void FUN_L01_0026d930_e50(void *) __asm__("FUN_L01_0026d930"); extern void emit_sand_shark_dust_burst(void *) __asm__("FUN_L02_002d3dd0"); @@ -447,7 +446,8 @@ void sand_shark_update(struct Moby *moby) { } } } else if (sand_shark_behavior_vars->unk25E != 0 && random_integer_below(0x13) == 0) { - moby->state = SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK; + moby->state = + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK; allocate_voice_for_target_entry(4, 0, moby); if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 0); @@ -555,7 +555,8 @@ void sand_shark_update(struct Moby *moby) { if (moby->prev_seq != 0xC) { blend_moby_animation(moby, 0xC, 0, scale_game_frames(5)); } - if (moby->state == SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_HEIGHT_OFFSET) { + if (moby->state == + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_HEIGHT_OFFSET) { moby->state = SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET; } else { moby->state = SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET; @@ -771,7 +772,8 @@ void sand_shark_update(struct Moby *moby) { } } } else if (sand_shark_behavior_vars->unk25E != 0 && random_integer_below(0x13) == 0) { - moby->state = SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK; + moby->state = + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK; allocate_voice_for_target_entry(4, 0, moby); if (moby->prev_seq != 0) { blend_moby_animation(moby, 0, 0, 0); @@ -846,13 +848,13 @@ void sand_shark_update(struct Moby *moby) { fast_vec_scale(&target_or_particle_vector, &target_or_particle_vector, D_0015ED6C * 5.0f); life = scale_game_frames(random_int_between(0x14, 0x28)); spawn_effect(&moby->pos, - &target_or_particle_vector, - D_L02_001619E4, - D_L02_001619E8, - life, - 0x64, - random_int_between(0x78, 0x96), - 0); + &target_or_particle_vector, + D_L02_001619E4, + D_L02_001619E8, + life, + 0x64, + random_int_between(0x78, 0x96), + 0); } /* fallthrough */ case SAND_SHARK_BALLISTIC_FLIGHT: { diff --git a/src/overlays/l02/mobys/transport_pod.c b/src/overlays/l02/mobys/transport_pod.c index 24a07c7dbe..10b2edb08c 100644 --- a/src/overlays/l02/mobys/transport_pod.c +++ b/src/overlays/l02/mobys/transport_pod.c @@ -110,7 +110,11 @@ void transport_pod_update(unsigned char *moby) { TRANSPORT_POD_POSITION_RAILS_FROM_CONFIGURED_OFFSETS = 15, TRANSPORT_POD_CYCLE_RAILS_TO_SPLIT_HEIGHTS = 16, TRANSPORT_POD_CYCLE_RAILS_TO_SHARED_LOWER_HEIGHT = 17 - } ; enum { HERO_TARGET_POSE_STATUS_INACTIVE = 0 , HERO_TARGET_POSE_STATUS_READY = 2}; + }; + enum { + HERO_TARGET_POSE_STATUS_INACTIVE = 0, + HERO_TARGET_POSE_STATUS_READY = 2 + }; Varsdc88 *transport_pod_vars = ((Varsdc88 *)MOBY(moby)->pvars); int i; int *path; diff --git a/src/overlays/l03/hero/hero_set_state.c b/src/overlays/l03/hero/hero_set_state.c index d5b5ebc7ac..83ef216f81 100644 --- a/src/overlays/l03/hero/hero_set_state.c +++ b/src/overlays/l03/hero/hero_set_state.c @@ -74,7 +74,8 @@ int hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L03_0015F5C4 == 2 || D_L03_0015F5C4 == 6) && b != 2) @@ -82,8 +83,16 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -960,7 +969,8 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; diff --git a/src/overlays/l03/hero/update_hero_motion_for_current_state.c b/src/overlays/l03/hero/update_hero_motion_for_current_state.c index ad964ea7c4..f4e177c594 100644 --- a/src/overlays/l03/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l03/hero/update_hero_motion_for_current_state.c @@ -514,7 +514,8 @@ void update_hero_motion_for_current_state(void) { } else { s32 idx = hero.pack_swim_voice; if (idx != -1) { - struct VoiceSlot *swim_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + idx * 0x70); + struct VoiceSlot *swim_voice_slot = + (struct VoiceSlot *)(((u8 *)&voice_pool) + idx * 0x70); if (swim_voice_slot->pm88 == MV(hero.moby) && swim_voice_slot->b74 != 0) { release_voice_slot(idx); } @@ -1478,7 +1479,8 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2090,7 +2092,8 @@ void update_hero_motion_for_current_state(void) { if (hero.unk2224 != -1) { struct VoiceSlot *alternate_landing_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + hero.unk2224 * 0x70); - if (alternate_landing_voice_slot->pm88 == MV(hero.moby) && alternate_landing_voice_slot->b74 != 0) { + if (alternate_landing_voice_slot->pm88 == MV(hero.moby) && + alternate_landing_voice_slot->b74 != 0) { release_voice_slot(hero.unk2224); } } diff --git a/src/overlays/l03/hero/update_hero_state_machine.c b/src/overlays/l03/hero/update_hero_state_machine.c index f2207aa6c1..d1620fa07d 100644 --- a/src/overlays/l03/hero/update_hero_state_machine.c +++ b/src/overlays/l03/hero/update_hero_state_machine.c @@ -168,8 +168,10 @@ void update_hero_state_machine(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L03_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; @@ -914,7 +916,8 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; diff --git a/src/overlays/l03/level_class_tables.c b/src/overlays/l03/level_class_tables.c index e684c12245..5d21e4baa7 100644 --- a/src/overlays/l03/level_class_tables.c +++ b/src/overlays/l03/level_class_tables.c @@ -22,7 +22,9 @@ #include "rnc/overlay/shared/ui/hud/hud_keep_visible.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" -s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" diff --git a/src/overlays/l03/mobys/help_hints.c b/src/overlays/l03/mobys/help_hints.c index 474a326e76..717ba051f0 100644 --- a/src/overlays/l03/mobys/help_hints.c +++ b/src/overlays/l03/mobys/help_hints.c @@ -44,7 +44,10 @@ void help_hints_update(struct Moby *moby) { enum { TUTORIAL_HINTS_INITIALIZE = 0, TUTORIAL_HINTS_UPDATE = 1 - } ; enum { HELP_PLAYBACK_IDLE = 0}; + }; + enum { + HELP_PLAYBACK_IDLE = 0 + }; s32 *tutorial_hint_state = ((s32 *)moby->pvars); struct Moby *candidate_moby; s32 count; @@ -191,7 +194,8 @@ void help_hints_update(struct Moby *moby) { } if (usage_stats.stat[15].count == 0 && ((u32)hero.state.control_mode < 2 || hero.state.control_mode == 9) && - tutorial_hint_state[21] >= 3 && l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && + tutorial_hint_state[21] >= 3 && + l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x1A].count == 0) { help_request(0xBBE, 0x1A); } @@ -206,7 +210,8 @@ void help_hints_update(struct Moby *moby) { } if (is_point_inside_clip_volume(&hero.motion.pos, tutorial_hint_state[11]) && usage_stats.stat[16].count == 0 && hero.state.control_mode == 6 && - hero.items[0].item_id == 8 && l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && + hero.items[0].item_id == 8 && + l03_help_message_playback_state.state == HELP_PLAYBACK_IDLE && l03_help_message_playback_state.cur == -1 && help_records[0x1B].count == 0) { help_request(0xBBF, 0x1B); } diff --git a/src/overlays/l03/mobys/kerwan_path_enemy.c b/src/overlays/l03/mobys/kerwan_path_enemy.c index 32cb16fd86..37d5e0d737 100644 --- a/src/overlays/l03/mobys/kerwan_path_enemy.c +++ b/src/overlays/l03/mobys/kerwan_path_enemy.c @@ -43,7 +43,10 @@ int try_start_kerwan_path_enemy_heading_turn(float desired_heading, struct Moby *moby, struct Moby *target) { - enum { ENEMY_TURN_TO_HEADING = 0xC } ;KerwanPathEnemyVars *enemy_pvars = (KerwanPathEnemyVars *)moby->pvars; + enum { + ENEMY_TURN_TO_HEADING = 0xC + }; + KerwanPathEnemyVars *enemy_pvars = (KerwanPathEnemyVars *)moby->pvars; int linked_moby_index; float heading_delta; unsigned char previous_state; @@ -417,7 +420,8 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { m->flags &= 0xFFBE; } if (m->pos[0] < 2.0f || 1021.0f < m->pos[0] || m->pos[1] < 2.0f || 1021.0f < m->pos[1] || - m->pos[2] < 2.0f || 1021.0f < m->pos[2] || (moby_data->pf.id == -1 && m->state != ENEMY_DEATH_KNOCKBACK)) { + m->pos[2] < 2.0f || 1021.0f < m->pos[2] || + (moby_data->pf.id == -1 && m->state != ENEMY_DEATH_KNOCKBACK)) { mark_moby_for_removal(m); return; } @@ -804,9 +808,9 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { } } if (!(step_mover_2e3f20((char *)m, - (char *)&moby_data->mv, - (float *)(pf->path + 0x10 + pf->idx * 0x10), - (char *)moby_data->v40) & + (char *)&moby_data->mv, + (float *)(pf->path + 0x10 + pf->idx * 0x10), + (char *)moby_data->v40) & 0x14)) { break; } @@ -862,9 +866,9 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { pf->idx = seg; } if (!(step_mover_2e3f20((char *)m, - (char *)&moby_data->mv, - (float *)(pf->path + 0x10 + pf->idx * 0x10), - (char *)moby_data->v40) & + (char *)&moby_data->mv, + (float *)(pf->path + 0x10 + pf->idx * 0x10), + (char *)moby_data->v40) & 0x14)) { break; } @@ -895,9 +899,9 @@ void kerwan_path_enemy_update(Moby2C8398 *m) { moby_data->i298 = seg; } if (!(step_mover_2e3f20((char *)m, - (char *)&moby_data->mv, - (float *)(path + 0x10 + moby_data->i298 * 0x10), - (char *)moby_data->v40) & + (char *)&moby_data->mv, + (float *)(path + 0x10 + moby_data->i298 * 0x10), + (char *)moby_data->v40) & 0x14)) { break; } diff --git a/src/overlays/l03/mobys/metropolis_train_carriage.c b/src/overlays/l03/mobys/metropolis_train_carriage.c index 7d8b532611..4d6827e96e 100644 --- a/src/overlays/l03/mobys/metropolis_train_carriage.c +++ b/src/overlays/l03/mobys/metropolis_train_carriage.c @@ -33,7 +33,10 @@ typedef struct MetropolisTrainCarriageVars { /* Moby class 1210 */ void metropolis_train_carriage_update(struct Moby *moby) { - enum { METROPOLIS_TRAIN_CARRIAGE_STATE_INITIALIZE = 0 } ;float position_delta[4]; + enum { + METROPOLIS_TRAIN_CARRIAGE_STATE_INITIALIZE = 0 + }; + float position_delta[4]; float joint_zero_world_position[4]; MetropolisTrainCarriageVars *carriage_pvars; char *current_position; diff --git a/src/overlays/l03/mobys/mine.c b/src/overlays/l03/mobys/mine.c index 96659b9fb4..8eceefff5b 100644 --- a/src/overlays/l03/mobys/mine.c +++ b/src/overlays/l03/mobys/mine.c @@ -109,7 +109,8 @@ void mine_layer_mine_update(struct Moby *mine_moby) { case MINE_ARM_AND_MONITOR_PROXIMITY: fast_dec_timer(&mine_vars->timer); target_moby = mine_vars->target; - if (target_moby != 0 && target_moby->state != MOBY_STATE_MARKED_FOR_REMOVAL && target_moby->state != 0xFD && + if (target_moby != 0 && target_moby->state != MOBY_STATE_MARKED_FOR_REMOVAL && + target_moby->state != 0xFD && vector_distance_xy(&mine_moby->pos, &target_moby->pos) < 3.0f && mine_vars->timer == 0) { mine_moby->state = MINE_HOME_ON_TARGET; @@ -173,7 +174,8 @@ void mine_layer_mine_update(struct Moby *mine_moby) { debris_vector_scratch[2] = random_float_between(frame_time * 4.0f, vector_scratch[kind]); *(OvlQuad *)debris_velocity = *(OvlQuad *)debris_vector_scratch; - rr = random_float_between(0.0f, kind == MINE_DEBRIS_WIDE_SPAWN_RADIUS ? 0.5f : 0.25f); + rr = random_float_between(0.0f, + kind == MINE_DEBRIS_WIDE_SPAWN_RADIUS ? 0.5f : 0.25f); debris_azimuth = random_angle_radians(); debris_vector_scratch[0] = fast_cos(debris_azimuth) * rr; debris_vector_scratch[1] = fast_sin(debris_azimuth) * rr; diff --git a/src/overlays/l03/mobys/mine_layer.c b/src/overlays/l03/mobys/mine_layer.c index f08635f1f4..78fbf567ca 100644 --- a/src/overlays/l03/mobys/mine_layer.c +++ b/src/overlays/l03/mobys/mine_layer.c @@ -212,9 +212,9 @@ void mine_layer_update(struct Moby *mine_layer_moby) { pt = &mine_layer_vars->patrol; patrol_point_index = pt->idx; step_mover_2e3f20(mine_layer_moby, - mine_layer_vars->walk, - &pt->path->points[patrol_point_index], - mine_layer_vars->effect); + mine_layer_vars->walk, + &pt->path->points[patrol_point_index], + mine_layer_vars->effect); mine_layer_moby->anim_speed = mine_layer_patrol_animation_speed_gp; fast_dec_timer_s16(&mine_layer_vars->patrol_timer); if (fast_vec_dist(&mine_layer_moby->pos, &pt->path->points[patrol_point_index]) < 1.0f) { diff --git a/src/overlays/l03/mobys/path_mover_spawner.c b/src/overlays/l03/mobys/path_mover_spawner.c index 05ebe36245..f40569291a 100644 --- a/src/overlays/l03/mobys/path_mover_spawner.c +++ b/src/overlays/l03/mobys/path_mover_spawner.c @@ -75,7 +75,11 @@ void path_mover_spawner_update(struct RailSpawnerMoby *moby) __asm__("FUN_L03_00 /* Moby class 899 */ void path_mover_spawner_update(struct RailSpawnerMoby *moby) { - enum { PATH_MOVER_SPAWNER_STATE_UNINITIALIZED = 0 , PATH_MOVER_SPAWNER_STATE_INITIALIZED = 1 } ;struct RailSpawnerVars *vars = moby->vars; + enum { + PATH_MOVER_SPAWNER_STATE_UNINITIALIZED = 0, + PATH_MOVER_SPAWNER_STATE_INITIALIZED = 1 + }; + struct RailSpawnerVars *vars = moby->vars; LevelPath *path; float spawn_distance; int i; diff --git a/src/overlays/l03/mobys/robot_dog.c b/src/overlays/l03/mobys/robot_dog.c index cd23b36851..20356a1061 100644 --- a/src/overlays/l03/mobys/robot_dog.c +++ b/src/overlays/l03/mobys/robot_dog.c @@ -28,8 +28,8 @@ int is_robot_dog_in_state_5(struct Moby *moby) { enum { MOBY_STATE_PENDING_REMOVAL = 0xFE }; - if (moby && moby->state != MOBY_STATE_PENDING_REMOVAL && moby->state != 0xFD && moby->oclass == 0x23D && - moby->state == ROBOT_DOG_FOLLOW_PATH) { + if (moby && moby->state != MOBY_STATE_PENDING_REMOVAL && moby->state != 0xFD && + moby->oclass == 0x23D && moby->state == ROBOT_DOG_FOLLOW_PATH) { return 1; } return 0; @@ -312,9 +312,9 @@ void robot_dog_update(char *moby) { robot_dog_state->i278 = seg; } if (step_mover_2e3f20(moby, - (char *)&robot_dog_state->i180, - (char *)path + (robot_dog_state->i278 * 0x10 + 0x10), - (char *)robot_dog_state->v40) & + (char *)&robot_dog_state->i180, + (char *)path + (robot_dog_state->i278 * 0x10 + 0x10), + (char *)robot_dog_state->v40) & 0x14) { if (robot_dog_state->i278 < *path - 1) { robot_dog_state->i278++; diff --git a/src/overlays/l03/mobys/robot_qwark.c b/src/overlays/l03/mobys/robot_qwark.c index 03b5cc07e7..95a571d6f6 100644 --- a/src/overlays/l03/mobys/robot_qwark.c +++ b/src/overlays/l03/mobys/robot_qwark.c @@ -143,7 +143,8 @@ void robot_qwark_update(struct Moby *robot_qwark_moby) { 1 << (robot_qwark_moby->save_id & 0x1F); } robot_qwark_moby->hit_slot = 0xFF; - if (npc_dialogue_suppression_flags[0] != 0 && robot_qwark_moby->state != ROBOT_QWARK_BROKEN_SPARKING) { + if (npc_dialogue_suppression_flags[0] != 0 && + robot_qwark_moby->state != ROBOT_QWARK_BROKEN_SPARKING) { return; } switch (robot_qwark_moby->state) { diff --git a/src/overlays/l04/level_class_tables.c b/src/overlays/l04/level_class_tables.c index 62bc1a17de..bd7fddeda0 100644 --- a/src/overlays/l04/level_class_tables.c +++ b/src/overlays/l04/level_class_tables.c @@ -17,7 +17,9 @@ #include "rnc/overlay/shared/ui/hud/hud_keep_visible.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" -s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" diff --git a/src/overlays/l04/mobys/big_axebot.c b/src/overlays/l04/mobys/big_axebot.c index 9d502fac08..70d201589b 100644 --- a/src/overlays/l04/mobys/big_axebot.c +++ b/src/overlays/l04/mobys/big_axebot.c @@ -248,7 +248,8 @@ extern int FUN_L00_001fefc8(void *); extern int is_point_inside_clip_volume(void *point, int volume_index) __asm__("FUN_00214720"); extern int hit_reaction(void *, void *, void *, int, int *, float *, int, int) __asm__("FUN_L00_0025a478"); -extern int move_moby_xy_with_collision_constraints(void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); +extern int move_moby_xy_with_collision_constraints( + void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); extern int step_moby_motion(void *, void *) __asm__("FUN_L00_0025c698"); extern int allocate_voice_for_target_entry(int, int, char *); extern int mark_moby_for_removal_cf() __asm__("FUN_L04_002ba470"); diff --git a/src/overlays/l04/mobys/blarg_trooper.c b/src/overlays/l04/mobys/blarg_trooper.c index f17d9cca5d..6dd97726d7 100644 --- a/src/overlays/l04/mobys/blarg_trooper.c +++ b/src/overlays/l04/mobys/blarg_trooper.c @@ -149,7 +149,8 @@ extern void record_moby_hit(void *, void *) __asm__("FUN_L00_00259a88"); extern void update_joint_animation(char *, char *, int, float, float) __asm__("FUN_L00_002628d8"); extern void spawn_blarg_trooper_projectile(void *, void *, void *, int) __asm__("FUN_L04_002aee30"); void destroy_blarg_trooper(struct Moby *arg) __asm__("FUN_L04_002c4808"); -extern int move_moby_xy_with_collision_constraints(void *, void *, void *, float, float, float, float, int) __asm__("FUN_L00_00258490"); +extern int move_moby_xy_with_collision_constraints( + void *, void *, void *, float, float, float, float, int) __asm__("FUN_L00_00258490"); void blarg_trooper_update(struct Moby *moby) __asm__("FUN_L04_002c4850"); @@ -496,7 +497,8 @@ void blarg_trooper_update(struct Moby *moby) { update_scratch.w.p.v70[1] = fast_sin(moby->rot.z) * (frame_time * 2.5f); update_scratch.w.p.v70[2] = 0.0f; fast_vec_add(update_scratch.w.p.v70, update_scratch.w.p.v70, pos); - move_moby_xy_with_collision_constraints(moby, pos, update_scratch.w.p.v70, 0.5f, 1.0f, 0.5f, 0.5235988f, 0); + move_moby_xy_with_collision_constraints( + moby, pos, update_scratch.w.p.v70, 0.5f, 1.0f, 0.5f, 0.5235988f, 0); } break; case BLARG_TROOPER_STATE_RUN_TO_TARGET_OR_PATH_POINT: @@ -519,13 +521,13 @@ void blarg_trooper_update(struct Moby *moby) { fast_vec_add(update_scratch.w.p.v70, update_scratch.w.p.v70, pos); qcopy(update_scratch.w.p.v80, pos); if (move_moby_xy_with_collision_constraints(moby, - update_scratch.w.p.v80, - update_scratch.w.p.v70, - 0.5f, - 1.0f, - 0.5f, - 0.5235988f, - 0) != 0) { + update_scratch.w.p.v80, + update_scratch.w.p.v70, + 0.5f, + 1.0f, + 0.5f, + 0.5235988f, + 0) != 0) { if (point_in_path_xy(update_scratch.w.p.v80, path->pts, path->count) != 0) { qcopy(pos, update_scratch.w.p.v80); k = 0xB; @@ -743,12 +745,16 @@ void blarg_trooper_update(struct Moby *moby) { fast_vec_add(update_scratch.w.p.v70, update_scratch.w.p.v70, pos); blarg_trooper_pvars->unkF4 = blarg_trooper_pvars->unkF4 + -2.0f / (scale_time(15.0f) * scale_time(15.0f)); - move_moby_xy_with_collision_constraints(moby, pos, update_scratch.w.p.v70, 0.5f, 1.0f, 0.5f, 0.5235988f, 1); + move_moby_xy_with_collision_constraints( + moby, pos, update_scratch.w.p.v70, 0.5f, 1.0f, 0.5f, 0.5235988f, 1); } if (moby->anim_flags & 2) { *(unsigned short *)&blarg_trooper_pvars->path_selector ^= 1; blend_moby_animation( - moby, (void *)(moby->state == BLARG_TROOPER_STATE_BACKWARD_RECOVERY ? 9 : 0), 0, (void *)scale_game_frames(9)); + moby, + (void *)(moby->state == BLARG_TROOPER_STATE_BACKWARD_RECOVERY ? 9 : 0), + 0, + (void *)scale_game_frames(9)); moby->state = BLARG_TROOPER_STATE_IDLE; blarg_trooper_pvars->timer_108 = scale_game_frames(0x78); } @@ -763,7 +769,9 @@ void blarg_trooper_update(struct Moby *moby) { trooper_anim_finish(moby, &blarg_trooper_pvars->anim_state); { int current_state = moby->state; - if (current_state == BLARG_TROOPER_STATE_IDLE || current_state == BLARG_TROOPER_STATE_RUN_TO_TARGET_OR_PATH_POINT || current_state == BLARG_TROOPER_STATE_JUMP || current_state == BLARG_TROOPER_STATE_AIM || + if (current_state == BLARG_TROOPER_STATE_IDLE || + current_state == BLARG_TROOPER_STATE_RUN_TO_TARGET_OR_PATH_POINT || + current_state == BLARG_TROOPER_STATE_JUMP || current_state == BLARG_TROOPER_STATE_AIM || current_state == BLARG_TROOPER_STATE_FIRE) { char *t = target; if (t == 0) { diff --git a/src/overlays/l04/mobys/circular_saw_enemy.c b/src/overlays/l04/mobys/circular_saw_enemy.c index f5b03fb16f..e81e41b742 100644 --- a/src/overlays/l04/mobys/circular_saw_enemy.c +++ b/src/overlays/l04/mobys/circular_saw_enemy.c @@ -469,9 +469,10 @@ I4_35F0 D_L04_00161890 = { extern float fast_cos(float); extern float fast_sin(float); extern int collect_mobies_in_sphere(void *, int, void *, void *, float) __asm__("FUN_L00_001f2868"); -extern int move_moby_xy_with_collision_constraints(void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); -extern int FUN_L00_002dc9f0(void *, void *); -short D_L04_00161878 = 0x101; +extern int move_moby_xy_with_collision_constraints( + void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); +extern int FUN_L00_002dc9f0(void *, void *); +short D_L04_00161878 = 0x101; extern void FUN_L01_0026d930(char *p); extern void update_circular_saw_engine_sound(struct Moby *) __asm__("FUN_L04_002c1b80"); extern void transform_vector_by_basis(void *, void *, void *); @@ -633,7 +634,8 @@ void circular_saw_enemy_update(M_35F0 *moby) { } data->f38 = 0; fast_dec_timer_s16(&data->f136); - if (moby->state == CIRCULAR_SAW_STATE_MELEE_ATTACK && moby->f52 == 7 && hd > 15.0f && hd < 44.0f) { + if (moby->state == CIRCULAR_SAW_STATE_MELEE_ATTACK && moby->f52 == 7 && hd > 15.0f && + hd < 44.0f) { int i; for (i = 0; i < 4; i++) { S_35F0 melee_hit_parameters; @@ -985,7 +987,8 @@ void circular_saw_enemy_update(M_35F0 *moby) { v[2] = 0.0f; fast_vec_add(v, v, moby->pos); data->f13C += -10.0f / (scale_time(15.0f) * scale_time(15.0f)); - move_moby_xy_with_collision_constraints(moby, moby->pos, v, 1, 0.25f, 0.57f, 0.5f, 0.5235988f); + move_moby_xy_with_collision_constraints( + moby, moby->pos, v, 1, 0.25f, 0.57f, 0.5f, 0.5235988f); } } if (moby->state == CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED) { @@ -1046,7 +1049,8 @@ void circular_saw_enemy_update(M_35F0 *moby) { anim = 0; } qcopy(np, moby->pos); - moved = move_moby_xy_with_collision_constraints(moby, np, v, 0, 0.25f, 0.57f, 0.5f, 0.5235988f); + moved = move_moby_xy_with_collision_constraints( + moby, np, v, 0, 0.25f, 0.57f, 0.5f, 0.5235988f); if (data->f138 == -1 || point_in_path_xy(np, ((P_35F0 *)l04_paths[data->f138])->pts, @@ -1063,7 +1067,8 @@ void circular_saw_enemy_update(M_35F0 *moby) { data->f144 = scale_game_frames(0xF); } } - } else if (moby->state == CIRCULAR_SAW_STATE_POINT_ATTACK || (moby->state == CIRCULAR_SAW_STATE_MELEE_ATTACK && moby->f52 == 7 && hd > 15.0f)) { + } else if (moby->state == CIRCULAR_SAW_STATE_POINT_ATTACK || + (moby->state == CIRCULAR_SAW_STATE_MELEE_ATTACK && moby->f52 == 7 && hd > 15.0f)) { if (vector_distance_xy(moby->pos, dest) > frame_time * 2.0f) { V4_35F0 v; V4_35F0 np; @@ -1075,7 +1080,8 @@ void circular_saw_enemy_update(M_35F0 *moby) { v[2] = 0.0f; fast_vec_add(v, v, moby->pos); qcopy(np, moby->pos); - move_moby_xy_with_collision_constraints(moby, np, v, 0, 0.25f, 1.25f, 0.5f, 0.5235988f); + move_moby_xy_with_collision_constraints( + moby, np, v, 0, 0.25f, 1.25f, 0.5f, 0.5235988f); if (data->f138 == -1 || point_in_path_xy(np, ((P_35F0 *)l04_paths[data->f138])->pts, @@ -1084,11 +1090,13 @@ void circular_saw_enemy_update(M_35F0 *moby) { } } } - } else if (moby->state != CIRCULAR_SAW_STATE_HIT_RECOVERY && moby->state != CIRCULAR_SAW_STATE_DYING) { + } else if (moby->state != CIRCULAR_SAW_STATE_HIT_RECOVERY && + moby->state != CIRCULAR_SAW_STATE_DYING) { V4_35F0 v; { qcopy(v, moby->pos); - move_moby_xy_with_collision_constraints(moby, moby->pos, v, 0, 0.25f, 0.57f, 0.5f, 0.5235988f); + move_moby_xy_with_collision_constraints( + moby, moby->pos, v, 0, 0.25f, 0.57f, 0.5f, 0.5235988f); } } data->f78 += frame_time_sq * 9.8f; diff --git a/src/overlays/l04/mobys/snow_plow.c b/src/overlays/l04/mobys/snow_plow.c index 26100d0f63..44acbebc33 100644 --- a/src/overlays/l04/mobys/snow_plow.c +++ b/src/overlays/l04/mobys/snow_plow.c @@ -117,7 +117,10 @@ void snow_plow_update(struct Moby *moby) { SNOW_PLOW_CLASS_OFFSET_WITH_FOUR_HIT_SPAWNS_AND_TARGET_VOICE_SELECTOR_ONE = 0x1d, SNOW_PLOW_CLASS_OFFSET_WITH_THREE_HIT_SPAWNS_AND_TARGET_VOICE_SELECTOR_ZERO = 0x20, SNOW_PLOW_CLASS_OFFSET_WITH_TARGET_VOICE_SELECTOR_ZERO = 0x59 - } ; enum { SNOW_PLOW_WAIT_TO_RESUME_PATH = 3}; + }; + enum { + SNOW_PLOW_WAIT_TO_RESUME_PATH = 3 + }; Vec4 update_start_position; Vec4 delta, *return_delta_ptr; /* The sphere query is its position followed by the record; the hit cases pass one or the other. */ diff --git a/src/overlays/l04/mobys/suck_cannon.c b/src/overlays/l04/mobys/suck_cannon.c index aced727ad0..86bd129ab9 100644 --- a/src/overlays/l04/mobys/suck_cannon.c +++ b/src/overlays/l04/mobys/suck_cannon.c @@ -13,7 +13,10 @@ #include "rnc/overlay/shared/world/level_labels.h" #include "rnc/overlay/shared/game/unlock_planet.h" #include "rnc/overlay/shared/rendering/effects/particles.h" -unsigned char *spawn_timed_hero_relative_particle(u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); + +unsigned char *spawn_timed_hero_relative_particle( + u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); + #include "rnc/save/memcard_save_data.h" /* Warp portal: spins, opens once the hero is near, then warps to the exit moby. */ @@ -143,13 +146,13 @@ void update_suck_cannon_particles(char *moby) { col = fast_tween_color(0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - timer_progress)); if (D_L04_0015F5C4 != 2) spawn_timed_hero_relative_particle(d, - col, - truncate_float_to_s32(sprite_data->a[i]) & 0xFF, - 0x35, - 1, - 2, - 0, - sprite_data->d[i]); + col, + truncate_float_to_s32(sprite_data->a[i]) & 0xFF, + 0x35, + 1, + 2, + 0, + sprite_data->d[i]); fast_vec_add(d, d, particle_position_step); } } diff --git a/src/overlays/l04/mobys/translation_delta_matrix.c b/src/overlays/l04/mobys/translation_delta_matrix.c index 0eb221df20..e60d8ea43a 100644 --- a/src/overlays/l04/mobys/translation_delta_matrix.c +++ b/src/overlays/l04/mobys/translation_delta_matrix.c @@ -14,7 +14,10 @@ void translation_delta_matrix_update(char *moby) __asm__("FUN_L04_002d3580"); /* Moby class 584 */ void translation_delta_matrix_update(char *moby) { - enum { MOBY_TRANSLATION_DELTA_STATE_INITIALIZE = 0 } ;char *moby_vars = ((char *)MOBY(moby)->pvars); + enum { + MOBY_TRANSLATION_DELTA_STATE_INITIALIZE = 0 + }; + char *moby_vars = ((char *)MOBY(moby)->pvars); float position_delta[4]; fast_vec_sub(position_delta, moby + 0x10, moby_vars + 0xA0); update_entity_matrix(moby_vars + 0x60, position_delta, moby + 0x40, moby + 0x40); diff --git a/src/overlays/l04/mobys/woodcut_bot.c b/src/overlays/l04/mobys/woodcut_bot.c index 73cb2e95a7..61aa14586b 100644 --- a/src/overlays/l04/mobys/woodcut_bot.c +++ b/src/overlays/l04/mobys/woodcut_bot.c @@ -299,9 +299,10 @@ extern void *memset(void *, int, unsigned int); extern void coll_line_fix(void *, void *, int, void *, void *) __asm__("FUN_001efa68"); extern void add_vectors(void *, void *, void *) __asm__("FUN_L00_001ff290"); extern void FUN_L00_00257470(void *, int, int); -extern void move_moby_xy_with_collision_constraints(void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); -extern void FUN_L00_0025a120(void *); -extern void trooper_knockback_arc(void *, float *, void *, void *) __asm__("FUN_L00_0025ab48"); +extern void move_moby_xy_with_collision_constraints( + void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); +extern void FUN_L00_0025a120(void *); +extern void trooper_knockback_arc(void *, float *, void *, void *) __asm__("FUN_L00_0025ab48"); extern void trooper_start_knockback(float, void *, void *, int, int, int) __asm__("FUN_L00_0025c558"); extern void trooper_anim_update(void *, void *) __asm__("FUN_L00_0025d458"); @@ -966,7 +967,8 @@ void woodcut_bot_update(WBMoby *m) { recoil_scratch[2] = 0.0f; fast_vec_add(recoil_scratch, recoil_scratch, pos); d->f3E4 += -2.0f / (scale_time(15.0f) * scale_time(15.0f)); - move_moby_xy_with_collision_constraints(m, pos, recoil_scratch, 1, 0.25f, 1.0f, 0.75f, 0.87266463f); + move_moby_xy_with_collision_constraints( + m, pos, recoil_scratch, 1, 0.25f, 1.0f, 0.75f, 0.87266463f); } d->f3C8 *= 0.96f; build_axis_rotation_quaternion(recoil_scratch, 1, d->f3C8); diff --git a/src/overlays/l05/hero/apply_hero_ground_material_effects.c b/src/overlays/l05/hero/apply_hero_ground_material_effects.c index db54499930..3407b9679d 100644 --- a/src/overlays/l05/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l05/hero/apply_hero_ground_material_effects.c @@ -284,7 +284,8 @@ void update_hero_ground_contact(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || + if (hero.ground_slope.f <= 0.87266463f || + hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = HH.moby; @@ -563,7 +564,8 @@ void integrate_hero_motion_with_collisions(void) { player = (L16MovementPlayer *)((char *)position - 0x80); update_hero_attachment(player->physics_mode, (char *)position + 0x70, (char *)position + 0x10); /* Limit the velocity by state and mode. Inside an arm `position` moves on to the velocity; it is formed again below. */ - if (player->state == HERO_STATE_RISE_THEN_FALL_WITH_AIRBORNE_HIT_QUERY || player->state == HERO_STATE_WRENCH_SLAM) { + if (player->state == HERO_STATE_RISE_THEN_FALL_WITH_AIRBORNE_HIT_QUERY || + player->state == HERO_STATE_WRENCH_SLAM) { float limit; float *limited_velocity; diff --git a/src/overlays/l05/hero/hero_set_state.c b/src/overlays/l05/hero/hero_set_state.c index eb488ba203..73fd29270e 100644 --- a/src/overlays/l05/hero/hero_set_state.c +++ b/src/overlays/l05/hero/hero_set_state.c @@ -87,7 +87,8 @@ int hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L05_0015F5C4 == 2 || D_L05_0015F5C4 == 6) && b != 2) @@ -95,8 +96,16 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -1129,7 +1138,8 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; diff --git a/src/overlays/l05/hero/update_hero_motion_by_state.c b/src/overlays/l05/hero/update_hero_motion_by_state.c index ae3965fc3f..340f6f9f7b 100644 --- a/src/overlays/l05/hero/update_hero_motion_by_state.c +++ b/src/overlays/l05/hero/update_hero_motion_by_state.c @@ -728,8 +728,8 @@ void update_hero_motion_by_state(void) { build_spherical_offset( &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { - f32 sp = - hero.ground_speed * vector_length_xyz_cf(swim_motion_scale_samples, 0x1E) * 5.0f; + f32 sp = hero.ground_speed * vector_length_xyz_cf(swim_motion_scale_samples, 0x1E) * + 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -857,8 +857,8 @@ void update_hero_motion_by_state(void) { } speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { - f32 sp = - hero.ground_speed * vector_length_xyz_cf(swim_motion_scale_samples, 0x1E) * 5.5f; + f32 sp = hero.ground_speed * vector_length_xyz_cf(swim_motion_scale_samples, 0x1E) * + 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; @@ -1768,7 +1768,8 @@ void update_hero_motion_by_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { diff --git a/src/overlays/l05/hero/update_hero_state_machine.c b/src/overlays/l05/hero/update_hero_state_machine.c index de8ba30ccf..bdfefb1bd9 100644 --- a/src/overlays/l05/hero/update_hero_state_machine.c +++ b/src/overlays/l05/hero/update_hero_state_machine.c @@ -173,8 +173,10 @@ void update_hero_state_machine(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && item_selector_hud_open_blocker == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; @@ -932,7 +934,8 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; diff --git a/src/overlays/l05/level_class_tables.c b/src/overlays/l05/level_class_tables.c index 577385bda1..931a58f8b4 100644 --- a/src/overlays/l05/level_class_tables.c +++ b/src/overlays/l05/level_class_tables.c @@ -18,7 +18,9 @@ #include "rnc/overlay/shared/vehicles.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" -s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" diff --git a/src/overlays/l05/mobys/amoeboid.c b/src/overlays/l05/mobys/amoeboid.c index ad8747961c..161decf5b6 100644 --- a/src/overlays/l05/mobys/amoeboid.c +++ b/src/overlays/l05/mobys/amoeboid.c @@ -14,12 +14,13 @@ extern float fast_cos(float); extern float fast_sin(float); /* Ported from rac1-decomp (src/overlays/l05_rilgar/vendor_002D28D0.c: func_L05_002DBF10), where it is exact; names translated to the US level program. */ -extern float approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); -extern int FUN_L00_00258b50(void *, void *, void *, void *, float); -extern void FUN_L01_0026d930(char *p); -extern void handle_amoeboid_hits(unsigned char *m) __asm__("FUN_L05_002daf58"); -extern void spawn_amoeboid_particles(unsigned char *moby) __asm__("FUN_L05_002db018"); -void mark_moby_for_removal(void *obj) __asm__("FUN_0020c828"); +extern float + approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); +extern int FUN_L00_00258b50(void *, void *, void *, void *, float); +extern void FUN_L01_0026d930(char *p); +extern void handle_amoeboid_hits(unsigned char *m) __asm__("FUN_L05_002daf58"); +extern void spawn_amoeboid_particles(unsigned char *moby) __asm__("FUN_L05_002db018"); +void mark_moby_for_removal(void *obj) __asm__("FUN_0020c828"); void amoeboid_update(struct Moby *m) __asm__("FUN_L05_002dac80"); typedef struct Moby Moby; @@ -76,11 +77,11 @@ void amoeboid_update(struct Moby *moby) { float yaw = fast_arc_tan(*(float *)(path_node_base + 0x10) - moby->pos.x, *(float *)(path_node_base + 0x14) - moby->pos.y); approach_angle(&moby->rot.z, - &moby_data->unkBC, - yaw, - frame_time_sq * 1.0471976f, - frame_time_sq * 1.0471976f, - frame_time * 3.1415927f); + &moby_data->unkBC, + yaw, + frame_time_sq * 1.0471976f, + frame_time_sq * 1.0471976f, + frame_time * 3.1415927f); facing_direction[0] = fast_cos(moby->rot.z); facing_direction[1] = fast_sin(moby->rot.z); facing_direction[2] = 0.0f; diff --git a/src/overlays/l05/mobys/extermibot.c b/src/overlays/l05/mobys/extermibot.c index d6a4ac11cc..881af0dda4 100644 --- a/src/overlays/l05/mobys/extermibot.c +++ b/src/overlays/l05/mobys/extermibot.c @@ -20,9 +20,10 @@ extern float random_angle_radians(void) __asm__("FUN_00213308"); extern float D_0015ED6C; extern float D_0015ED70; float absolute_float(float input) __asm__("func_001F99C0"); -extern float approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); -extern int FUN_L00_00258b50(void *, void *, void *, void *, float); -extern void FUN_L01_0026d930(char *p); +extern float + approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); +extern int FUN_L00_00258b50(void *, void *, void *, void *, float); +extern void FUN_L01_0026d930(char *p); /* Extermibot update: wakes from its dormant pose, walks its path, closes in on the target and strikes it, bursts into sparks between strikes, and dies on a hit. */ /* Ported from rac1-decomp (src/overlays/l05_rilgar/vendor_002D28D0.c: func_L05_003033A0), where it is exact; names translated to the US level program. */ @@ -264,11 +265,11 @@ void extermibot_update(unsigned char *moby) { yaw = fast_arc_tan(moby_data->goal[0] - MOBY(moby)->pos.x, moby_data->goal[1] - MOBY(moby)->pos.y); approach_angle(moby_yaw_ptr, - &moby_data->yaw_vel, - yaw, - D_0015ED70 * 6.2831855f, - D_0015ED70 * 6.2831855f, - D_0015ED6C * 6.2831855f); + &moby_data->yaw_vel, + yaw, + D_0015ED70 * 6.2831855f, + D_0015ED70 * 6.2831855f, + D_0015ED6C * 6.2831855f); if (fast_difference_between_rotations( MOBY(moby)->rot.z, fast_arc_tan(moby_data->goal[0] - MOBY(moby)->pos.x, @@ -301,11 +302,11 @@ void extermibot_update(unsigned char *moby) { yaw = fast_arc_tan(MOBY(target_moby)->pos.x - MOBY(moby)->pos.x, MOBY(target_moby)->pos.y - MOBY(moby)->pos.y); approach_angle(moby_yaw_ptr, - &moby_data->yaw_vel, - yaw, - D_0015ED70 * 6.2831855f, - D_0015ED70 * 6.2831855f, - D_0015ED6C * 6.2831855f); + &moby_data->yaw_vel, + yaw, + D_0015ED70 * 6.2831855f, + D_0015ED70 * 6.2831855f, + D_0015ED6C * 6.2831855f); if (fast_difference_between_rotations( MOBY(moby)->rot.z, fast_arc_tan(MOBY(target_moby)->pos.x - MOBY(moby)->pos.x, @@ -401,11 +402,11 @@ void extermibot_update(unsigned char *moby) { yaw = fast_arc_tan(MOBY(target_moby)->pos.x - MOBY(moby)->pos.x, MOBY(target_moby)->pos.y - MOBY(moby)->pos.y); approach_angle(moby_yaw_ptr, - &moby_data->yaw_vel, - yaw, - D_0015ED70 * 12.566371f, - D_0015ED70 * 12.566371f, - D_0015ED6C * 25.132742f); + &moby_data->yaw_vel, + yaw, + D_0015ED70 * 12.566371f, + D_0015ED70 * 12.566371f, + D_0015ED6C * 25.132742f); if ((MOBY(moby)->anim_flags & 2) && MOBY(moby)->prev_seq == 2) { blend_moby_animation(moby, 7, 0, scale_game_frames(5)); } @@ -796,7 +797,8 @@ void handle_extermibot_hits_and_update_targeting(Moby *moby) { } hit_response = resolve_moby_hit_response( moby, hit_record, &moby_data->hp, 0, &collision_hit_status, &dmg, 0, 4); - if (collision_hit_status != EXTERMIBOT_HIT_STATUS_SKIP_RESPONSE && moby->state != EXTERMIBOT_DEATH_KNOCKBACK) { + if (collision_hit_status != EXTERMIBOT_HIT_STATUS_SKIP_RESPONSE && + moby->state != EXTERMIBOT_DEATH_KNOCKBACK) { moby_data->hp = moby_data->hp - dmg; if (moby_data->hp <= 0.0f) { hit_response = 1; @@ -996,18 +998,19 @@ void move_extermibot_along_path(struct Moby *moby, s32 destination_position, f32 offset_heading = fast_add_rotations(fast_arc_tan(goal.x - moby->pos.x, goal.y - moby->pos.y), side); ((ApproachAngleTargetFirst)approach_angle)(&moby->rot.z, - offset_heading, - &walker_vars->yaw_vel, - frame_time_sq * 12.566371f, - frame_time_sq * 12.566371f, - frame_time * 25.132742f); + offset_heading, + &walker_vars->yaw_vel, + frame_time_sq * 12.566371f, + frame_time_sq * 12.566371f, + frame_time * 25.132742f); } else { - ((ApproachAngleTargetFirst)approach_angle)(&moby->rot.z, - fast_arc_tan(goal.x - moby->pos.x, goal.y - moby->pos.y), - &walker_vars->yaw_vel, - frame_time_sq * 12.566371f, - frame_time_sq * 12.566371f, - frame_time * 25.132742f); + ((ApproachAngleTargetFirst)approach_angle)( + &moby->rot.z, + fast_arc_tan(goal.x - moby->pos.x, goal.y - moby->pos.y), + &walker_vars->yaw_vel, + frame_time_sq * 12.566371f, + frame_time_sq * 12.566371f, + frame_time * 25.132742f); } if (fast_difference_between_rotations( moby->rot.z, fast_arc_tan(goal.x - moby->pos.x, goal.y - moby->pos.y)) < 1.5707964f && @@ -1132,11 +1135,13 @@ f32 push_point_from_path(s32 path_index, void *input, void *output, f32 distance qcopy_nc(&working, point); for (i = 0; i < ((SegmentPath *)l05_paths[path_index])->count - 1; i++) { path_table_slot = ((SegmentPath **)&l05_paths[path_index]); - if ((*path_table_slot)->points[i].f[3] == 0.0f && (*path_table_slot)->points[i + 1].f[3] == 0.0f) + if ((*path_table_slot)->points[i].f[3] == 0.0f && + (*path_table_slot)->points[i + 1].f[3] == 0.0f) continue; func_001F9BF0_3054B0(&difference, &working, &(*path_table_slot)->points[i]); difference.i[2] = 0; - func_001F9BF0_3054B0(&segment, &(*path_table_slot)->points[i + 1], &(*path_table_slot)->points[i]); + func_001F9BF0_3054B0( + &segment, &(*path_table_slot)->points[i + 1], &(*path_table_slot)->points[i]); segment.i[2] = 0; func_L00_001FF4B0_3054B0(&scaled_segment, &segment, 1.0f); func_001F9CA0_3054B0(&cross, &difference, &scaled_segment); diff --git a/src/overlays/l05/mobys/extermitank.c b/src/overlays/l05/mobys/extermitank.c index 53d8be429e..b8a4e8cf95 100644 --- a/src/overlays/l05/mobys/extermitank.c +++ b/src/overlays/l05/mobys/extermitank.c @@ -264,9 +264,9 @@ void extermitank_update(unsigned char *moby) { last = n - 1; idx = (extermitank_vars->unkC0 + n + dir) % n; step_mover_2e3f20((char *)moby, - &extermitank_vars->unk70, - (float *)(path + (idx * 16 + 0x10)), - extermitank_vars->unk40); + &extermitank_vars->unk70, + (float *)(path + (idx * 16 + 0x10)), + extermitank_vars->unk40); if (vector_distance_xy(moby + 0x10, *(char **)(pp + 0x10) + (idx * 16 + 0x10)) < 1.0f) { if (idx == last) { char *q = *(char **)(pp + 0x10); @@ -308,9 +308,10 @@ void extermitank_update(unsigned char *moby) { &extermitank_vars->unk198, 0, 0.0f, D_0015ED6C_gp * 1.5707964f); } build_axis_rotation_quaternion(extermitank_vars->unk140, 1, extermitank_vars->unk198); - build_axis_rotation_quaternion(extermitank_vars->unk100, - 2, - fast_subtract_rotations(extermitank_vars->unk194, MOBY(moby)->rot.z)); + build_axis_rotation_quaternion( + extermitank_vars->unk100, + 2, + fast_subtract_rotations(extermitank_vars->unk194, MOBY(moby)->rot.z)); break; } case EXTERMITANK_FIRE_PARTICLES: { @@ -327,9 +328,9 @@ void extermitank_update(unsigned char *moby) { last = n - 1; idx = (extermitank_vars->unkC0 + n + dir) % n; step_mover_2e3f20((char *)moby, - &extermitank_vars->unk70, - (float *)(path + (idx * 16 + 0x10)), - extermitank_vars->unk40); + &extermitank_vars->unk70, + (float *)(path + (idx * 16 + 0x10)), + extermitank_vars->unk40); if (vector_distance_xy(moby + 0x10, *(char **)(pp + 0x10) + (idx * 16 + 0x10)) < 1.0f) { if (idx == last) { char *q = *(char **)(pp + 0x10); @@ -481,9 +482,10 @@ void extermitank_update(unsigned char *moby) { &extermitank_vars->unk198, 0, 0.08726646f, D_0015ED6C_gp * 1.5707964f); } build_axis_rotation_quaternion(extermitank_vars->unk140, 1, extermitank_vars->unk198); - build_axis_rotation_quaternion(extermitank_vars->unk100, - 2, - fast_subtract_rotations(extermitank_vars->unk194, MOBY(moby)->rot.z)); + build_axis_rotation_quaternion( + extermitank_vars->unk100, + 2, + fast_subtract_rotations(extermitank_vars->unk194, MOBY(moby)->rot.z)); break; } case EXTERMITANK_REMOVE: @@ -535,7 +537,10 @@ extern float extermitank_child_animation_speed_offset_scale_gp __asm__("D_L05_00 typedef struct Hero Hero; void handle_extermitank_hits_and_sync_children(char *moby) { - enum { MOBY_HIT_RESPONSE_SKIP_DAMAGE = 1 } ;ExtermitankVars *extermitank_hit_sync_vars = (ExtermitankVars *)MOBY(moby)->pvars; + enum { + MOBY_HIT_RESPONSE_SKIP_DAMAGE = 1 + }; + ExtermitankVars *extermitank_hit_sync_vars = (ExtermitankVars *)MOBY(moby)->pvars; char *first; char *second; char *part0; @@ -568,7 +573,8 @@ void handle_extermitank_hits_and_sync_children(char *moby) { hit = part0; resolve_moby_hit_response( moby, hit, &extermitank_hit_sync_vars->health, 0, &hit_processing_status, &remaining, 0, 4); - if (hit_processing_status == MOBY_HIT_RESPONSE_SKIP_DAMAGE || (unsigned char)MOBY(moby)->state == 3) + if (hit_processing_status == MOBY_HIT_RESPONSE_SKIP_DAMAGE || + (unsigned char)MOBY(moby)->state == 3) goto mark_children; { extermitank_hit_sync_vars->health -= remaining; diff --git a/src/overlays/l05/mobys/fog_zone.c b/src/overlays/l05/mobys/fog_zone.c index 395d5a38a2..9e9050ca8e 100644 --- a/src/overlays/l05/mobys/fog_zone.c +++ b/src/overlays/l05/mobys/fog_zone.c @@ -89,9 +89,9 @@ void fog_zone_update(struct Moby *moby) { fog_zone_vars->preset_fog_454 = 0; { int saved_volume_blend_color = l05_volume_blended_color_low_byte + - (l05_volume_blended_color_lower_middle_byte << 8) + - (l05_volume_blended_color_upper_middle_byte << 16) + - (l05_volume_blended_color_high_byte << 24); + (l05_volume_blended_color_lower_middle_byte << 8) + + (l05_volume_blended_color_upper_middle_byte << 16) + + (l05_volume_blended_color_high_byte << 24); fog_zone_vars->unk34 = 0x40408070; fog_zone_vars->unk30 = saved_volume_blend_color; } diff --git a/src/overlays/l05/mobys/rising_gate.c b/src/overlays/l05/mobys/rising_gate.c index d81d289419..70b914c2da 100644 --- a/src/overlays/l05/mobys/rising_gate.c +++ b/src/overlays/l05/mobys/rising_gate.c @@ -26,7 +26,8 @@ float gate_swing_max_speed_gp __asm__("D_L05_00161E94") = 1.44e+03f; extern int gate_mobys_314eb0 __asm__("D_L05_0015FFD8"); extern float advance_accelerated_scalar(float, float, float, float, float *, float *) __asm__("FUN_00213f38"); -extern float approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); +extern float +approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); /* Gate: waits for its trigger moby, then rises to topZ and swings its yaw back to 0, with sounds per class. */ void rising_gate_update(struct Moby *gate_moby) __asm__("FUN_L05_00314eb0"); @@ -77,11 +78,11 @@ void rising_gate_update(struct Moby *gate_moby) { } if (fast_dec_timer(&gate_vars->swingTimer)) { approach_angle(&gate_moby->rot.y, - &gate_vars->swingSpeed, - 0.0f, - gate_swing_acceleration_gp * 0.017453292f * frame_time_sq, - gate_swing_deceleration_gp * 0.017453292f * frame_time_sq, - gate_swing_max_speed_gp * 0.017453292f * frame_time); + &gate_vars->swingSpeed, + 0.0f, + gate_swing_acceleration_gp * 0.017453292f * frame_time_sq, + gate_swing_deceleration_gp * 0.017453292f * frame_time_sq, + gate_swing_max_speed_gp * 0.017453292f * frame_time); if (gate_moby->rot.y == 0.0f) gate_moby->state = GATE_YAW_ALIGNED; } else if (gate_vars->swingTimer == 1 && gate_moby->oclass == 0x354) { diff --git a/src/overlays/l05/mobys/taxi.c b/src/overlays/l05/mobys/taxi.c index 4f565e746c..1f673e23da 100644 --- a/src/overlays/l05/mobys/taxi.c +++ b/src/overlays/l05/mobys/taxi.c @@ -72,7 +72,10 @@ void taxi_update(struct Moby *moby) { TAXI_FOLLOW_PATH = 4, TAXI_BLEND_TO_DESTINATION = 5, TAXI_WAIT_FOR_ACTIVATION = 6 - } ; enum { TAXI_HIDDEN_STOP = 2}; + }; + enum { + TAXI_HIDDEN_STOP = 2 + }; TaxiVars *taxi_data = (TaxiVars *)moby->pvars; float old_position[4], old_rotation[4], position_delta[4], rotation_or_start_position_scratch[4], interpolation_end_position[4], diff --git a/src/overlays/l05/mobys/triggered_motion.c b/src/overlays/l05/mobys/triggered_motion.c index efaa27e20b..26fe86299b 100644 --- a/src/overlays/l05/mobys/triggered_motion.c +++ b/src/overlays/l05/mobys/triggered_motion.c @@ -12,7 +12,8 @@ extern int allocate_voice_for_target_entry() __asm__("FUN_0022da68"); extern short D_L05_0015FFD8 __asm__("D_L05_0015FFD8"); extern float advance_accelerated_scalar(float, float, float, float, float *, float *) __asm__("FUN_00213f38"); -extern float approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); +extern float +approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); extern char *D_001413D0_lui __asm__("D_001413D0") NOT_SDA; @@ -43,7 +44,10 @@ void triggered_motion_update(char *moby) { MOBY_RETURN_TO_SAVED_POSITION = 4, MOBY_SETTLE_AT_UPPER_MANIPULATOR_ANGLE = 5, MOBY_SETTLE_AT_ZERO_MANIPULATOR_ANGLE = 6 - } ; enum { MOBY_MOTION_SEQUENCE_COMPLETE = 7}; + }; + enum { + MOBY_MOTION_SEQUENCE_COMPLETE = 7 + }; TriggeredMotionVars *motion_and_manipulator_vars = (TriggeredMotionVars *)MOBY(moby)->pvars; float target[4]; float delta[4]; @@ -100,11 +104,11 @@ void triggered_motion_update(char *moby) { approach = -0.5934119f; } approach_angle(&motion_and_manipulator_vars->unk60, - &motion_and_manipulator_vars->unk64, - approach, - frame_time_sq * 4.1887903f, - frame_time_sq * 4.1887903f, - frame_time * 12.566371f); + &motion_and_manipulator_vars->unk64, + approach, + frame_time_sq * 4.1887903f, + frame_time_sq * 4.1887903f, + frame_time * 12.566371f); if (motion_and_manipulator_vars->unk60 > 0.5934119f || motion_and_manipulator_vars->unk60 < 0.0f) { if (motion_and_manipulator_vars->unk60 > 0.5934119f) diff --git a/src/overlays/l05/mobys/triggered_slide.c b/src/overlays/l05/mobys/triggered_slide.c index a3dcff3d3f..d1f088da2a 100644 --- a/src/overlays/l05/mobys/triggered_slide.c +++ b/src/overlays/l05/mobys/triggered_slide.c @@ -35,7 +35,10 @@ void triggered_slide_update(char *moby) { MOBY_WAIT_FOR_TRIGGER = 1, MOBY_SLIDE_TO_END_POINT = 2, MOBY_LOWER_BELOW_POSE_HEIGHT = 3 - } ; enum { MOBY_LOWERING_COMPLETE = 4}; + }; + enum { + MOBY_LOWERING_COMPLETE = 4 + }; TriggeredSlideVars *slide_and_lowering_vars = (TriggeredSlideVars *)MOBY(moby)->pvars; float slide_motion_scratch[4]; float slide_step_distance; diff --git a/src/overlays/l06/hero/hero_set_state.c b/src/overlays/l06/hero/hero_set_state.c index 1072633f56..b3c51a8d1e 100644 --- a/src/overlays/l06/hero/hero_set_state.c +++ b/src/overlays/l06/hero/hero_set_state.c @@ -79,7 +79,8 @@ int hero_set_state(int requested_state, int b) { } d; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L06_0015F5C4 == 2 || D_L06_0015F5C4 == 6) && b != 2) @@ -87,8 +88,16 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -748,7 +757,8 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; diff --git a/src/overlays/l06/hero/update_hero_motion_for_current_state.c b/src/overlays/l06/hero/update_hero_motion_for_current_state.c index f1cffee743..c118de126d 100644 --- a/src/overlays/l06/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l06/hero/update_hero_motion_for_current_state.c @@ -519,7 +519,8 @@ void update_hero_ground_contact(void) { } if (hero_lui.ground_distance < 0.02f) { hero_lui.frames_off_ground.s = 0; - if (hero_lui.ground_slope.f <= 0.87266463f || hero_lui.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || + if (hero_lui.ground_slope.f <= 0.87266463f || + hero_lui.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero_lui.state.control_mode == 0x16) { hero_lui.air_frames.s = 0; hero_lui.last_landed_moby = HH.moby; @@ -1788,7 +1789,8 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, D_0015ED6C_c * 15.009831f); } else { s32 ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2044,7 +2046,8 @@ void update_hero_motion_for_current_state(void) { if (hero.grind_voice != -1) { struct VoiceSlot *grind_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + hero.grind_voice * 0x70); - if (grind_voice_slot->pm88 == (struct MobyView *)hero.moby && grind_voice_slot->b74 != 0) { + if (grind_voice_slot->pm88 == (struct MobyView *)hero.moby && + grind_voice_slot->b74 != 0) { release_voice_slot(hero.grind_voice); } } @@ -2354,7 +2357,8 @@ void update_hero_motion_for_current_state(void) { &sf, 0.3f, hero.rail_spline_loops); - rail_ahead_pitch = fast_arc_tan(vector_distance_xy(&hero.rail_point, &vector_or_descriptor_scratch), + rail_ahead_pitch = + fast_arc_tan(vector_distance_xy(&hero.rail_point, &vector_or_descriptor_scratch), vector_or_descriptor_scratch.f[2] - hero.rail_point.f[2]); if (rail_ahead_pitch > 0.0f) { sp = rail_ahead_pitch * 1.9098593f * (D_0015ED6C_c * -2.5f); @@ -2365,7 +2369,8 @@ void update_hero_motion_for_current_state(void) { } } else { sp = -rail_ahead_pitch * 2.864789f * (D_0015ED6C_c * 8.0f); - if (rail_ahead_pitch < -0.19198622f && hero.grind_pose != 2 && hero.grind_pose != 3) { + if (rail_ahead_pitch < -0.19198622f && hero.grind_pose != 2 && + hero.grind_pose != 3) { hero.grind_pose = 1; } else if (rail_ahead_pitch > -0.12217305f && hero.grind_pose == 1) { hero.grind_pose = -1; @@ -2631,7 +2636,8 @@ void update_hero_motion_for_current_state(void) { if (hero.voice_slot4 != -1) { struct VoiceSlot *landing_item_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + hero.voice_slot4 * 0x70); - if (landing_item_voice_slot->pm88 == (struct MobyView *)hero.moby && landing_item_voice_slot->b74 != 0) { + if (landing_item_voice_slot->pm88 == (struct MobyView *)hero.moby && + landing_item_voice_slot->b74 != 0) { release_voice_slot(hero.voice_slot4); } } @@ -2641,7 +2647,8 @@ void update_hero_motion_for_current_state(void) { if (hero.unk2224 != -1) { struct VoiceSlot *landing_entry4_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + hero.unk2224 * 0x70); - if (landing_entry4_voice_slot->pm88 == (struct MobyView *)hero.moby && landing_entry4_voice_slot->b74 != 0) { + if (landing_entry4_voice_slot->pm88 == (struct MobyView *)hero.moby && + landing_entry4_voice_slot->b74 != 0) { release_voice_slot(hero.unk2224); } } @@ -2941,7 +2948,10 @@ void update_hero_motion_for_current_state(void) { s32 ok; tb = &D_L06_0017C3A8[hero.attack_record]; hero.target_speed = 0.0f; - if ((tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE ? 1 : tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) && hero.anim_frame < 5.5f) { + if ((tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE + ? 1 + : tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) && + hero.anim_frame < 5.5f) { hero.target_speed = D_0015ED6C_c * 3.5f; } if (hero.anim_changing == 0 && (f32)tb->f1C <= hero.anim_frame && @@ -2974,7 +2984,8 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, D_0015ED6C_c * 15.009831f); } else { ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { diff --git a/src/overlays/l06/hero/update_hero_state_machine.c b/src/overlays/l06/hero/update_hero_state_machine.c index 7fbb6a887b..0bc9c76598 100644 --- a/src/overlays/l06/hero/update_hero_state_machine.c +++ b/src/overlays/l06/hero/update_hero_state_machine.c @@ -179,8 +179,10 @@ void update_hero_state_machine(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L06_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0)) { switch (hero.vehicle_mode) { case HERO_VEHICLE_MODE_ON_FOOT: case 3: { @@ -778,7 +780,8 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; diff --git a/src/overlays/l06/level_class_tables.c b/src/overlays/l06/level_class_tables.c index 4c8caa4da0..49bd1a65ea 100644 --- a/src/overlays/l06/level_class_tables.c +++ b/src/overlays/l06/level_class_tables.c @@ -20,7 +20,9 @@ #include "rnc/overlay/shared/ui/hud/hud_keep_visible.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" -s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" diff --git a/src/overlays/l06/mobys/alien_queen.c b/src/overlays/l06/mobys/alien_queen.c index 7791076c05..091c270f30 100644 --- a/src/overlays/l06/mobys/alien_queen.c +++ b/src/overlays/l06/mobys/alien_queen.c @@ -121,14 +121,15 @@ extern short l06_alien_queen_movement_speed __asm__("D_L06_00161EF4") __attribut f32 alien_queen_movement_acceleration_gp __asm__("D_L06_00161EFC") = 8.0f; extern short l06_alien_queen_attack_distance __asm__("D_L06_00161F00") __attribute__((sda)); extern short l06_alien_queen_retreat_distance __asm__("D_L06_00161F04") __attribute__((sda)); -extern short l06_alien_queen_attack_heading_tolerance_degrees __asm__("D_L06_00161F08") __attribute__((sda)); -extern void FUN_L06_002fa9c0_c(void *) __asm__("FUN_L06_002fa9c0"); -void set_moby_list_state_18(int idx) __asm__("FUN_L06_002f9948"); -void FUN_L06_002fb870(char *arg); -void FUN_L06_002fbc30(char *arg); -int FUN_L06_002fba28(char *moby); -extern void func_L00_00264B40_q(void *, int, float, void *) __asm__("FUN_L00_00263ac8"); -extern void func_L00_0025B178_q(void *) __asm__("FUN_L00_0025a120"); +extern short l06_alien_queen_attack_heading_tolerance_degrees __asm__("D_L06_00161F08") + __attribute__((sda)); +extern void FUN_L06_002fa9c0_c(void *) __asm__("FUN_L06_002fa9c0"); +void set_moby_list_state_18(int idx) __asm__("FUN_L06_002f9948"); +void FUN_L06_002fb870(char *arg); +void FUN_L06_002fbc30(char *arg); +int FUN_L06_002fba28(char *moby); +extern void func_L00_00264B40_q(void *, int, float, void *) __asm__("FUN_L00_00263ac8"); +extern void func_L00_0025B178_q(void *) __asm__("FUN_L00_0025a120"); extern int queue_animation_update(int, int, void *, void *, void *, void *, int) __asm__("FUN_001ff308"); extern void func_L00_00236710_q(void) __asm__("FUN_L00_00235d80"); @@ -388,7 +389,25 @@ typedef struct AlienQueenVars { /* Moby class 1051 */ void alien_queen_update(unsigned char *moby) { - enum { ALIEN_QUEEN_STATE_INITIALIZE = 0 , ALIEN_QUEEN_STATE_WAIT_TO_START_INTRO = 1 , ALIEN_QUEEN_STATE_INTRO = 2 , ALIEN_QUEEN_STATE_FIRST_RECOVERY_CAMERA = 3 , ALIEN_QUEEN_STATE_FROG_RECOVERY_ORBIT = 4 , ALIEN_QUEEN_STATE_SECOND_RECOVERY_CAMERA = 5 , ALIEN_QUEEN_STATE_GROUP_RECOVERY_ORBIT = 6 , ALIEN_QUEEN_STATE_WAIT_TO_APPROACH_TARGET = 7 , ALIEN_QUEEN_STATE_APPROACH_TARGET = 8 , ALIEN_QUEEN_STATE_ATTACK_WINDUP = 9 , ALIEN_QUEEN_STATE_ATTACK_HIT_QUERIES = 10 , ALIEN_QUEEN_STATE_WAIT_FOR_ORBIT_ANIMATION_END = 11, ALIEN_QUEEN_STATE_TIMED_ORBIT = 12 , ALIEN_QUEEN_STATE_RETURN_HOME = 13 , ALIEN_QUEEN_STATE_DEATH = 14 , ALIEN_QUEEN_STATE_POST_DEATH = 15 } ;AlienQueenVars *alien_queen_update_vars = (AlienQueenVars *)MOBY(moby)->pvars; + enum { + ALIEN_QUEEN_STATE_INITIALIZE = 0, + ALIEN_QUEEN_STATE_WAIT_TO_START_INTRO = 1, + ALIEN_QUEEN_STATE_INTRO = 2, + ALIEN_QUEEN_STATE_FIRST_RECOVERY_CAMERA = 3, + ALIEN_QUEEN_STATE_FROG_RECOVERY_ORBIT = 4, + ALIEN_QUEEN_STATE_SECOND_RECOVERY_CAMERA = 5, + ALIEN_QUEEN_STATE_GROUP_RECOVERY_ORBIT = 6, + ALIEN_QUEEN_STATE_WAIT_TO_APPROACH_TARGET = 7, + ALIEN_QUEEN_STATE_APPROACH_TARGET = 8, + ALIEN_QUEEN_STATE_ATTACK_WINDUP = 9, + ALIEN_QUEEN_STATE_ATTACK_HIT_QUERIES = 10, + ALIEN_QUEEN_STATE_WAIT_FOR_ORBIT_ANIMATION_END = 11, + ALIEN_QUEEN_STATE_TIMED_ORBIT = 12, + ALIEN_QUEEN_STATE_RETURN_HOME = 13, + ALIEN_QUEEN_STATE_DEATH = 14, + ALIEN_QUEEN_STATE_POST_DEATH = 15 + }; + AlienQueenVars *alien_queen_update_vars = (AlienQueenVars *)MOBY(moby)->pvars; char *target; float step[4]; @@ -572,7 +591,8 @@ void alien_queen_update(unsigned char *moby) { moby[0x20] = 0xC; break; } - if (dist < *(float *)&l06_alien_queen_attack_distance && turn < *(float *)&l06_alien_queen_attack_heading_tolerance_degrees * 0.017453292f) { + if (dist < *(float *)&l06_alien_queen_attack_distance && + turn < *(float *)&l06_alien_queen_attack_heading_tolerance_degrees * 0.017453292f) { moby[0x20] = 9; moby[0xBC] = 7; if ((unsigned char)moby[0x53] != 4) { @@ -776,7 +796,11 @@ void update_alien_queen_hit_response_and_recovery(char *moby) { REDUCED_DAMAGE_SOURCE_CLASS = 0x131, DAMAGE_BOOSTING_SOURCE_CLASS = 0x33B }; - enum { ALIEN_QUEEN_STATE_INITIALIZE = 0 , HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1 } ;AlienQueenVars *alien_queen_hit_recovery_vars; + enum { + ALIEN_QUEEN_STATE_INITIALIZE = 0, + HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1 + }; + AlienQueenVars *alien_queen_hit_recovery_vars; char *hit; int hit_status; float dmg; @@ -796,8 +820,8 @@ void update_alien_queen_hit_response_and_recovery(char *moby) { hit = FUN_L00_0025a420(moby, 0x330000, 0); kind = resolve_moby_hit_response( moby, hit, &alien_queen_hit_recovery_vars->health, 0, &hit_status, &dmg, 0, 4); - if (hit_status != HIT_STATUS_SKIP_DAMAGE_AND_REACTION && (unsigned char)moby[0x20] != 14 && (unsigned char)moby[0x20] != 3 && - (unsigned char)moby[0x20] != 5) { + if (hit_status != HIT_STATUS_SKIP_DAMAGE_AND_REACTION && (unsigned char)moby[0x20] != 14 && + (unsigned char)moby[0x20] != 3 && (unsigned char)moby[0x20] != 5) { if (*(char **)(hit + 0x20) != 0) { int oclass = *(short *)(*(char **)(hit + 0x20) + 0xA6); switch (oclass) { diff --git a/src/overlays/l06/mobys/alien_snapper.c b/src/overlays/l06/mobys/alien_snapper.c index 2bb8d22e74..a70f8e7133 100644 --- a/src/overlays/l06/mobys/alien_snapper.c +++ b/src/overlays/l06/mobys/alien_snapper.c @@ -134,9 +134,12 @@ extern float l06_alien_snapper_gravity __asm__("D_L06_00161EB4") __attribute__(( extern float l06_alien_snapper_bite_approach_radius __asm__("D_L06_00161EC4") __attribute__((sda)); extern float l06_alien_snapper_max_home_distance __asm__("D_L06_00161EC8") __attribute__((sda)); extern float l06_alien_snapper_base_targeting_radius __asm__("D_L06_00161ED0") __attribute__((sda)); -extern float l06_alien_snapper_retreat_distance_limit __asm__("D_L06_00161ED4") __attribute__((sda)); -extern int l06_alien_snapper_retreat_bite_override_enabled __asm__("D_L06_00161EDC") __attribute__((sda)); -extern int l06_alien_snapper_retreat_bite_start_frame __asm__("D_L06_00161EE0") __attribute__((sda)); +extern float l06_alien_snapper_retreat_distance_limit __asm__("D_L06_00161ED4") + __attribute__((sda)); +extern int l06_alien_snapper_retreat_bite_override_enabled __asm__("D_L06_00161EDC") + __attribute__((sda)); +extern int l06_alien_snapper_retreat_bite_start_frame __asm__("D_L06_00161EE0") + __attribute__((sda)); void update_alien_snapper_hit_response_and_targeting(Moby *moby) __asm__("FUN_L06_002f91e8"); extern char D_0013F3D0[]; extern void update_alien_snapper_hit_response_and_targeting(Moby *) __asm__("FUN_L06_002f91e8"); @@ -246,7 +249,31 @@ approach_angle(f32 *angle, f32 target, f32 *vel, f32, f32, f32) __asm__("FUN_L00 /* Moby class 1048 */ void alien_snapper_update(Moby *moby) { - enum { ALIEN_SNAPPER_STATE_INITIALIZE = 0 , ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION = 1 , ALIEN_SNAPPER_STATE_ACTIVATION_SEQUENCE = 2 ,ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER = 3 , ALIEN_SNAPPER_STATE_PREPARE_HOME_NODE_JUMP = 4 , ALIEN_SNAPPER_STATE_JUMP_TO_HOME_NODE = 5 , ALIEN_SNAPPER_STATE_FACE_GOAL_AND_WAIT = 6, ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH = 7 , ALIEN_SNAPPER_STATE_APPROACH_TARGET = 8 , ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET = 9 , ALIEN_SNAPPER_STATE_WAIT_FOR_REPOSITION_ANIMATION = 10, ALIEN_SNAPPER_STATE_BITE_TARGET = 11 , ALIEN_SNAPPER_STATE_RETURN_HOME = 12 , ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET = 13 , ALIEN_SNAPPER_STATE_HIT_KNOCKBACK = 14 , ALIEN_SNAPPER_STATE_FACE_HERO = 15 , ALIEN_SNAPPER_STATE_BITE_HERO = 16 , ALIEN_SNAPPER_STATE_DEATH_MOTION = 17 } ; enum { ALIEN_SNAPPER_ANIM_ACTIVATION = 3 ,ALIEN_SNAPPER_ANIM_HOME_NODE_JUMP_WINDUP = 6} ;SnapperVars_91A8 *snapper_behavior = (SnapperVars_91A8 *)moby->pvars; + enum { + ALIEN_SNAPPER_STATE_INITIALIZE = 0, + ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION = 1, + ALIEN_SNAPPER_STATE_ACTIVATION_SEQUENCE = 2, + ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER = 3, + ALIEN_SNAPPER_STATE_PREPARE_HOME_NODE_JUMP = 4, + ALIEN_SNAPPER_STATE_JUMP_TO_HOME_NODE = 5, + ALIEN_SNAPPER_STATE_FACE_GOAL_AND_WAIT = 6, + ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH = 7, + ALIEN_SNAPPER_STATE_APPROACH_TARGET = 8, + ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET = 9, + ALIEN_SNAPPER_STATE_WAIT_FOR_REPOSITION_ANIMATION = 10, + ALIEN_SNAPPER_STATE_BITE_TARGET = 11, + ALIEN_SNAPPER_STATE_RETURN_HOME = 12, + ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET = 13, + ALIEN_SNAPPER_STATE_HIT_KNOCKBACK = 14, + ALIEN_SNAPPER_STATE_FACE_HERO = 15, + ALIEN_SNAPPER_STATE_BITE_HERO = 16, + ALIEN_SNAPPER_STATE_DEATH_MOTION = 17 + }; + enum { + ALIEN_SNAPPER_ANIM_ACTIVATION = 3, + ALIEN_SNAPPER_ANIM_HOME_NODE_JUMP_WINDUP = 6 + }; + SnapperVars_91A8 *snapper_behavior = (SnapperVars_91A8 *)moby->pvars; Moby *target; float target_goal_radius; float target_gap_angle_radians; @@ -331,17 +358,20 @@ void alien_snapper_update(Moby *moby) { case ALIEN_SNAPPER_STATE_ACTIVATION_SEQUENCE: if (moby->prev_seq == 0) { if (snapper_behavior->timer == 0) { - snapper_behavior->timer = truncate_float_to_s32(scale_time(random_float_between(0.0f, 20.0f))); + snapper_behavior->timer = + truncate_float_to_s32(scale_time(random_float_between(0.0f, 20.0f))); } else if (fast_dec_timer(&snapper_behavior->timer) != 0) { if (moby->prev_seq != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } } } else if (moby->anim_flags & 2) { - if (vector_distance_xy(&moby->pos, ((char *)&D_0013F3D0)) < l06_alien_snapper_base_targeting_radius) { + if (vector_distance_xy(&moby->pos, ((char *)&D_0013F3D0)) < + l06_alien_snapper_base_targeting_radius) { moby->state = 8; - snapper_behavior->angle_jitter = random_float_between(snapper_behavior->jitter_degrees * 0.017453292f, - -(snapper_behavior->jitter_degrees * 0.017453292f)); + snapper_behavior->angle_jitter = + random_float_between(snapper_behavior->jitter_degrees * 0.017453292f, + -(snapper_behavior->jitter_degrees * 0.017453292f)); if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -358,7 +388,8 @@ void alien_snapper_update(Moby *moby) { break; case ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER: if (snapper_behavior->clip_volume >= 0) { - if (is_point_inside_clip_volume(((char *)&D_0013F3D0), snapper_behavior->clip_volume) != 0) { + if (is_point_inside_clip_volume(((char *)&D_0013F3D0), snapper_behavior->clip_volume) != + 0) { moby->state = 4; if (moby->prev_seq != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(5)); @@ -376,18 +407,22 @@ void alien_snapper_update(Moby *moby) { moby->state = 5; qcopy(&snapper_behavior->home, &l06_cuboids[snapper_behavior->node].pos); snapper_behavior->return_speed = - vector_distance_xy(&moby->pos, &snapper_behavior->home) / (float)scale_game_frames(60); - snapper_behavior->f8C = func_L00_0025BC48_91A8( - &moby->pos, &snapper_behavior->home, 0, snapper_behavior->return_speed, -snapper_behavior->f80); + vector_distance_xy(&moby->pos, &snapper_behavior->home) / + (float)scale_game_frames(60); + snapper_behavior->f8C = func_L00_0025BC48_91A8(&moby->pos, + &snapper_behavior->home, + 0, + snapper_behavior->return_speed, + -snapper_behavior->f80); snapper_behavior->f94 = 5; snapper_behavior->fAD = 3; - func_L00_0025D5B0_91A8( - moby, - snapper_behavior->f70, - 7, - 1, - 0, - fast_arc_tan(snapper_behavior->home.x - moby->pos.x, snapper_behavior->home.y - moby->pos.y)); + func_L00_0025D5B0_91A8(moby, + snapper_behavior->f70, + 7, + 1, + 0, + fast_arc_tan(snapper_behavior->home.x - moby->pos.x, + snapper_behavior->home.y - moby->pos.y)); if (moby->prev_seq != 7) { blend_moby_animation(moby, 7, 0, 5); } @@ -405,14 +440,16 @@ void alien_snapper_update(Moby *moby) { break; case ALIEN_SNAPPER_STATE_FACE_GOAL_AND_WAIT: func_L00_002592B0_91A8(moby, - fast_arc_tan(snapper_behavior->goal_x - moby->pos.x, snapper_behavior->goal_y - moby->pos.y), + fast_arc_tan(snapper_behavior->goal_x - moby->pos.x, + snapper_behavior->goal_y - moby->pos.y), &snapper_behavior->turn_speed, 0.05f, 0.3f, frame_time * 6.2831855f); if (snapper_behavior->f164 != 2) { moby->state = 7; - snapper_behavior->timer = truncate_float_to_s32(random_float_between(0.0f, (float)snapper_behavior->timer_max)); + snapper_behavior->timer = truncate_float_to_s32( + random_float_between(0.0f, (float)snapper_behavior->timer_max)); } else if (snapper_behavior->f1AC != 0) { moby->state = 9; if (moby->prev_seq != 1) { @@ -423,7 +460,8 @@ void alien_snapper_update(Moby *moby) { case ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET: { int near; - approach_value(&snapper_behavior->speed, snapper_behavior->base_speed * frame_time, D_0015ED70 * 6.0f); + approach_value( + &snapper_behavior->speed, snapper_behavior->base_speed * frame_time, D_0015ED70 * 6.0f); func_L00_002592B0_91A8( moby, fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y), @@ -447,10 +485,12 @@ void alien_snapper_update(Moby *moby) { scratch.m.dir[0] = fast_cos(moby->rot.z) * 2.0f; scratch.m.dir[1] = fast_sin(moby->rot.z) * 2.0f; scratch.m.dir[2] = 0.0f; - func_L00_00259B88_91A8(moby, &snapper_behavior->movement, scratch.m.dir, scratch.m.out, 1.0f); + func_L00_00259B88_91A8( + moby, &snapper_behavior->movement, scratch.m.dir, scratch.m.out, 1.0f); moby->rot.z = saved_rot; func_L00_00262DF0_91A8(0.5f, snapper_behavior->path, &moby->pos, &moby->pos); - if (FUN_L00_00261b48(snapper_behavior->path, &moby->pos, &target->pos, scratch.m.path_point) != 0 && + if (FUN_L00_00261b48( + snapper_behavior->path, &moby->pos, &target->pos, scratch.m.path_point) != 0 && fast_vec_dist(&moby->pos, scratch.m.path_point) < snapper_behavior->reach_distance) { near = 1; } @@ -461,7 +501,8 @@ void alien_snapper_update(Moby *moby) { if (moby->prev_seq != 5) { blend_moby_animation(moby, 5, 0, scale_game_frames(10)); } - } else if (vector_distance_xy(&moby->pos, &target->pos) < l06_alien_snapper_bite_approach_radius) { + } else if (vector_distance_xy(&moby->pos, &target->pos) < + l06_alien_snapper_bite_approach_radius) { moby->state = 0xB; if (moby->prev_seq != 4) { blend_moby_animation(moby, 4, 0, scale_game_frames(10)); @@ -480,8 +521,9 @@ void alien_snapper_update(Moby *moby) { case ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH: if (fast_dec_timer(&snapper_behavior->timer) != 0) { moby->state = 8; - snapper_behavior->angle_jitter = random_float_between(snapper_behavior->jitter_degrees * 0.017453292f, - -(snapper_behavior->jitter_degrees * 0.017453292f)); + snapper_behavior->angle_jitter = + random_float_between(snapper_behavior->jitter_degrees * 0.017453292f, + -(snapper_behavior->jitter_degrees * 0.017453292f)); if (moby->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -489,7 +531,9 @@ void alien_snapper_update(Moby *moby) { break; case ALIEN_SNAPPER_STATE_APPROACH_TARGET: { if (l06_alien_snapper_bite_approach_radius < vector_distance_xy(&moby->pos, &target->pos)) { - approach_value(&snapper_behavior->speed, snapper_behavior->base_speed * frame_time, D_0015ED70 * 6.0f); + approach_value(&snapper_behavior->speed, + snapper_behavior->base_speed * frame_time, + D_0015ED70 * 6.0f); } else { approach_value(&snapper_behavior->speed, 0.0f, D_0015ED70 * 20.0f); } @@ -515,12 +559,16 @@ void alien_snapper_update(Moby *moby) { scratch.m.dir[0] = fast_cos(moby->rot.z) * 2.0f; scratch.m.dir[1] = fast_sin(moby->rot.z) * 2.0f; scratch.m.dir[2] = 0.0f; - func_L00_00259B88_91A8(moby, &snapper_behavior->movement, scratch.m.dir, scratch.m.out, 1.0f); + func_L00_00259B88_91A8( + moby, &snapper_behavior->movement, scratch.m.dir, scratch.m.out, 1.0f); moby->rot.z = saved_rot; func_L00_00262DF0_91A8(0.5f, snapper_behavior->path, &moby->pos, &moby->pos); - if (l06_alien_snapper_max_home_distance < fast_vec_dist(&moby->pos, &snapper_behavior->home) || snapper_behavior->f164 == 2) { + if (l06_alien_snapper_max_home_distance < + fast_vec_dist(&moby->pos, &snapper_behavior->home) || + snapper_behavior->f164 == 2) { moby->state = 0xC; - } else if (vector_distance_xy(&moby->pos, &target->pos) < l06_alien_snapper_bite_approach_radius) { + } else if (vector_distance_xy(&moby->pos, &target->pos) < + l06_alien_snapper_bite_approach_radius) { if (absolute_float(target->pos.z - moby->pos.z) < 1.0f) { char *hero = ((char *)&D_0013F350); @@ -564,7 +612,9 @@ void alien_snapper_update(Moby *moby) { } break; case ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET: { - approach_value(&snapper_behavior->speed, snapper_behavior->base_speed * 3.0f * frame_time, D_0015ED70 * 20.0f); + approach_value(&snapper_behavior->speed, + snapper_behavior->base_speed * 3.0f * frame_time, + D_0015ED70 * 20.0f); func_L00_002592B0_91A8( moby, fast_arc_tan(target->pos.x - moby->pos.x, target->pos.y - moby->pos.y), @@ -578,7 +628,8 @@ void alien_snapper_update(Moby *moby) { scratch.m.dir[0] = fast_cos(moby->rot.z) * 2.0f; scratch.m.dir[1] = fast_sin(moby->rot.z) * 2.0f; scratch.m.dir[2] = 0.0f; - func_L00_00259B88_91A8(moby, &snapper_behavior->movement, scratch.m.dir, scratch.m.out, 1.0f); + func_L00_00259B88_91A8( + moby, &snapper_behavior->movement, scratch.m.dir, scratch.m.out, 1.0f); moby->rot.z = saved_rot; func_L00_00262DF0_91A8(0.5f, snapper_behavior->path, &moby->pos, &moby->pos); if (fast_dec_timer(&snapper_behavior->timer) != 0 || @@ -587,7 +638,8 @@ void alien_snapper_update(Moby *moby) { snapper_behavior->speed = frame_time * 5.0f; if (l06_alien_snapper_retreat_bite_override_enabled != 0) { if (moby->prev_seq != 4) { - blend_moby_animation(moby, 4, l06_alien_snapper_retreat_bite_start_frame, scale_game_frames(5)); + blend_moby_animation( + moby, 4, l06_alien_snapper_retreat_bite_start_frame, scale_game_frames(5)); } } else { if (moby->prev_seq != 4) { @@ -598,9 +650,11 @@ void alien_snapper_update(Moby *moby) { break; } case ALIEN_SNAPPER_STATE_RETURN_HOME: { - approach_value(&snapper_behavior->speed, snapper_behavior->base_speed * frame_time, D_0015ED70 * 6.0f); + approach_value( + &snapper_behavior->speed, snapper_behavior->base_speed * frame_time, D_0015ED70 * 6.0f); func_L00_002592B0_91A8(moby, - fast_arc_tan(snapper_behavior->home.x - moby->pos.x, snapper_behavior->home.y - moby->pos.y), + fast_arc_tan(snapper_behavior->home.x - moby->pos.x, + snapper_behavior->home.y - moby->pos.y), &snapper_behavior->turn_speed, 0.05f, 0.3f, @@ -608,7 +662,8 @@ void alien_snapper_update(Moby *moby) { scratch.m.dir[0] = fast_cos(moby->rot.z) * 2.0f; scratch.m.dir[1] = fast_sin(moby->rot.z) * 2.0f; scratch.m.dir[2] = 0.0f; - func_L00_00259B88_91A8(moby, &snapper_behavior->movement, scratch.m.dir, scratch.m.out, 1.0f); + func_L00_00259B88_91A8( + moby, &snapper_behavior->movement, scratch.m.dir, scratch.m.out, 1.0f); func_L00_00262DF0_b91A8(snapper_behavior->path, &moby->pos, &moby->pos, 0.5f); if (fast_vec_dist(&moby->pos, &snapper_behavior->home) < 1.0f) { moby->state = 6; @@ -751,7 +806,8 @@ void update_alien_snapper_hit_response_and_targeting(Moby *moby) { reaction = resolve_moby_hit_response(moby, target, &snapper_vars->health, 0, &hit, &damage, 0, 4); - if (hit != 1 && moby->state != ALIEN_SNAPPER_STATE_DEATH_MOTION && moby->state != ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER) { + if (hit != 1 && moby->state != ALIEN_SNAPPER_STATE_DEATH_MOTION && + moby->state != ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER) { snapper_vars->health = snapper_vars->health - damage; if (moby->group != 0xFF) { func_L06_002FAAC8_2FA618(moby); diff --git a/src/overlays/l06/mobys/beam_barrier.c b/src/overlays/l06/mobys/beam_barrier.c index 1e0b52930b..00ae458dbe 100644 --- a/src/overlays/l06/mobys/beam_barrier.c +++ b/src/overlays/l06/mobys/beam_barrier.c @@ -51,10 +51,10 @@ extern float l06_beam_barrier_segment_euler_rotations[] __asm__ extern int D_L06_00161E40[] MACRO_ADDR; extern int D_L06_00161E50; extern int D_L06_00161E54; -extern f32 l06_beam_barrier_strand_length __asm__("D_L06_00161E08") __attribute__((sda)); -extern float l06_beam_barrier_transform_scale __asm__("D_L06_00161E0C") __attribute__((sda)); -float beam_barrier_collision_z_offset_gp __asm__("D_L06_00161E18") = 2.25f; -extern int beam_barrier_burst_color_from_gp __asm__("D_L06_00161E1C") __attribute__((sda)); +extern f32 l06_beam_barrier_strand_length __asm__("D_L06_00161E08") __attribute__((sda)); +extern float l06_beam_barrier_transform_scale __asm__("D_L06_00161E0C") __attribute__((sda)); +float beam_barrier_collision_z_offset_gp __asm__("D_L06_00161E18") = 2.25f; +extern int beam_barrier_burst_color_from_gp __asm__("D_L06_00161E1C") __attribute__((sda)); int beam_barrier_burst_color_to_gp __asm__("D_L06_00161E20") = 0x80802080; /* RGBA, 0xAABBGGRR */ float beam_barrier_burst_scale_min_gp __asm__("D_L06_00161E24") = 0.125f; float beam_barrier_burst_scale_max_gp __asm__("D_L06_00161E28") = 0.333f; @@ -297,10 +297,14 @@ void beam_barrier_update(struct Moby *moby) { do { segment_offset = segment * 16; spark = 19; - euler_rotation_matrix(work.shared.local, (char *)l06_beam_barrier_segment_euler_rotations + segment_offset); + euler_rotation_matrix(work.shared.local, + (char *)l06_beam_barrier_segment_euler_rotations + + segment_offset); next_segment = segment + 1; multiply_matrix(work.shared.local, work.matrix, work.shared.local); - transform_vector(work.point, (char *)l06_beam_barrier_segment_local_offsets + segment_offset, work.matrix); + transform_vector(work.point, + (char *)l06_beam_barrier_segment_local_offsets + segment_offset, + work.matrix); fast_vec_add(work.shared.collision.delta, work.point, pos); work.shared.collision.delta[3] = 1.0f; do { diff --git a/src/overlays/l06/mobys/countdown_sequence.c b/src/overlays/l06/mobys/countdown_sequence.c index 9cb60945bd..6478db2d42 100644 --- a/src/overlays/l06/mobys/countdown_sequence.c +++ b/src/overlays/l06/mobys/countdown_sequence.c @@ -198,7 +198,10 @@ void countdown_sequence_update(unsigned char *moby) { ADVANCE_CAMERA_ALONG_PATH = 3, UPDATE_POST_PATH_TIMED_EVENTS = 4, RAMP_SHARED_VALUE_AFTER_DELAY = 5 - } ; enum { DIALOGUE_PHASE_READY_TO_CONTINUE = 3}; + }; + enum { + DIALOGUE_PHASE_READY_TO_CONTINUE = 3 + }; CountdownSequenceVars *moby_vars = (CountdownSequenceVars *)MOBY(moby)->pvars; float va[4] __attribute__((aligned(16))); float vc[4] __attribute__((aligned(16))); @@ -313,7 +316,8 @@ void countdown_sequence_update(unsigned char *moby) { select_localized_moby_voice_line((struct Moby *)moby, 2); else { x = scale_game_frames(300); - if (moby_vars->timer_B4 == x && *(short *)dialogue_playback_phase == DIALOGUE_PHASE_READY_TO_CONTINUE) + if (moby_vars->timer_B4 == x && + *(short *)dialogue_playback_phase == DIALOGUE_PHASE_READY_TO_CONTINUE) continue_audio_stream_if_ready(); } } diff --git a/src/overlays/l06/mobys/elevator.c b/src/overlays/l06/mobys/elevator.c index e3ef1cfd97..573a218b9c 100644 --- a/src/overlays/l06/mobys/elevator.c +++ b/src/overlays/l06/mobys/elevator.c @@ -346,7 +346,8 @@ void elevator_update(Moby_2FDA70 *moby) { moby_data->f90 = scale_game_frames(0x78); } } else if (vector_distance_xy(&moby->pos, &((Hero_2FDA70 *)(D_0013F350))->pos) < 24.0f && - moby->state == WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT && ((Hero_2FDA70 *)(D_0013F350))->pos.z + 5.0f < moby->pos.z) { + moby->state == WAIT_FOR_HERO_TRIGGER_AT_NODE_OFFSET_HEIGHT && + ((Hero_2FDA70 *)(D_0013F350))->pos.z + 5.0f < moby->pos.z) { moby_data->f84 = 1; moby_data->f94 = 1; moby->state = MOVE_TO_NODE_BASE_HEIGHT; @@ -354,7 +355,8 @@ void elevator_update(Moby_2FDA70 *moby) { set_moby_and_links_to_states_8_and_9(D_L06_0015FFD8_macro + (moby_data->f60 << 8)); moby_data->f90 = scale_game_frames(0x78); } else if (vector_distance_xy(&moby->pos, &((Hero_2FDA70 *)(D_0013F350))->pos) < 24.0f && - moby->state == WAIT_FOR_HERO_TRIGGER_AT_NODE_BASE_HEIGHT && moby->pos.z < ((Hero_2FDA70 *)(D_0013F350))->pos.z - 5.0f) { + moby->state == WAIT_FOR_HERO_TRIGGER_AT_NODE_BASE_HEIGHT && + moby->pos.z < ((Hero_2FDA70 *)(D_0013F350))->pos.z - 5.0f) { moby->state = MOVE_TO_NODE_OFFSET_HEIGHT; set_moby_and_links_to_states_8_and_9(D_L06_0015FFD8_macro + (moby_data->f68 << 8)); moby_data->f90 = scale_game_frames(0x78); @@ -402,7 +404,8 @@ void elevator_update(Moby_2FDA70 *moby) { } else { ((Hero_2FDA70 *)(D_0013F350))->f22CB = 0; } - if (moby->state >= MOVE_TO_NODE_BASE_HEIGHT && moby->state <= WAIT_FOR_HERO_CLEARANCE_AT_NODE_BASE_HEIGHT) { + if (moby->state >= MOVE_TO_NODE_BASE_HEIGHT && + moby->state <= WAIT_FOR_HERO_CLEARANCE_AT_NODE_BASE_HEIGHT) { moby_data->f9C = 0.0f; moby->f90 = D_L06_00161F74; } else { diff --git a/src/overlays/l06/mobys/hangar_door.c b/src/overlays/l06/mobys/hangar_door.c index 34f2683022..a305be13d5 100644 --- a/src/overlays/l06/mobys/hangar_door.c +++ b/src/overlays/l06/mobys/hangar_door.c @@ -11,9 +11,10 @@ /* Ported from rac1-decomp (src/overlays/l06_blarg/vendor_002B5990.c: func_L06_002B5990), where it is exact; names translated to the US level program. */ #include "rnc/overlay/shared/world/cuboid.h" -extern float approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); -extern int D_L06_0015F5C4; -void hangar_door_update(char *m) __asm__("FUN_L06_002b4770"); +extern float + approach_angle(float *, float *, float, float, float, float) __asm__("FUN_L00_0025be00"); +extern int D_L06_0015F5C4; +void hangar_door_update(char *m) __asm__("FUN_L06_002b4770"); #include "sda.h" @@ -59,11 +60,11 @@ void hangar_door_update(char *door_moby) { } if (door_data->unk18 != door_data->unk14) { approach_angle(&door_data->unk18, - &door_data->unk8, - door_data->unk14, - frame_time_sq * 1.5707964f, - frame_time_sq * 1.5707964f, - frame_time * 1.5707964f); + &door_data->unk8, + door_data->unk14, + frame_time_sq * 1.5707964f, + frame_time_sq * 1.5707964f, + frame_time * 1.5707964f); } switch (((unsigned char *)door_moby)[0x20]) { case HANGAR_DOOR_INITIALIZE: diff --git a/src/overlays/l06/mobys/shuttle.c b/src/overlays/l06/mobys/shuttle.c index bd1bc4d665..e52a68745f 100644 --- a/src/overlays/l06/mobys/shuttle.c +++ b/src/overlays/l06/mobys/shuttle.c @@ -136,8 +136,8 @@ int shuttle_forced_return_requested_gp __asm__("D_L06_00162100") = 0; #include "rnc/overlay/l06/mobys/shuttle_data/shuttle_update.h" -extern int l06_shuttle_projected_sprite_start_color __asm__("D_L06_0016210C") __attribute__((sda)); -extern int l06_shuttle_projected_sprite_end_color __asm__("D_L06_00162110") __attribute__((sda)); +extern int l06_shuttle_projected_sprite_start_color __asm__("D_L06_0016210C") __attribute__((sda)); +extern int l06_shuttle_projected_sprite_end_color __asm__("D_L06_00162110") __attribute__((sda)); extern unsigned char D_0013D4D5[] NOT_SDA; /* Update of moby class 1109 (shuttle): waits at one of three camera points, takes the hero's choice of destination, flies there through a cutscene and hands over to the level's travel sequence. */ @@ -192,26 +192,42 @@ Colors D_L06_00201948 = { {0x4f008fff, 0x4f008fff, 0x4f007fff, 0x4f006fff, 0x2fffffff, 0x2fffffff} }; -extern float l06_shuttle_explosion_spark_velocity_scale_random_bound_a __asm__("D_L06_00162114") __attribute__((sda)); -extern float l06_shuttle_explosion_spark_velocity_scale_random_bound_b __asm__("D_L06_00162118") __attribute__((sda)); -extern float l06_shuttle_explosion_spark_velocity_w_random_bound_a __asm__("D_L06_0016211C") __attribute__((sda)); -extern float l06_shuttle_explosion_spark_velocity_w_random_bound_b __asm__("D_L06_00162120") __attribute__((sda)); -extern float l06_shuttle_explosion_spark_acceleration_scale_random_bound_a __asm__("D_L06_00162124") __attribute__((sda)); -extern float l06_shuttle_explosion_spark_acceleration_scale_random_bound_b __asm__("D_L06_00162128") __attribute__((sda)); -extern float l06_shuttle_explosion_spark_acceleration_w_random_bound_a __asm__("D_L06_0016212C") __attribute__((sda)); -extern float l06_shuttle_explosion_spark_acceleration_w_random_bound_b __asm__("D_L06_00162130") __attribute__((sda)); -extern int l06_shuttle_explosion_spark_first_color_blend_a __asm__("D_L06_00162134") __attribute__((sda)); -extern int l06_shuttle_explosion_spark_first_color_blend_b __asm__("D_L06_00162138") __attribute__((sda)); -extern int l06_shuttle_explosion_spark_second_color_blend_a __asm__("D_L06_0016213C") __attribute__((sda)); -extern int l06_shuttle_explosion_spark_second_color_blend_b __asm__("D_L06_00162140") __attribute__((sda)); -extern int l06_shuttle_explosion_spark_timing_random_min_frames __asm__("D_L06_00162144") __attribute__((sda)); -extern int l06_shuttle_explosion_spark_timing_base_a_frames __asm__("D_L06_00162148") __attribute__((sda)); -extern int l06_shuttle_explosion_spark_timing_base_b_frames __asm__("D_L06_0016214C") __attribute__((sda)); -extern int D_L06_00162150 __attribute__((sda)); -extern int l06_shuttle_explosion_spark_table_index __asm__("D_L06_00162154") __attribute__((sda)); -extern int l06_shuttle_explosion_spark_alternate_mode_flag __asm__("D_L06_00162158") __attribute__((sda)); -extern void random_vector(void *, float, float) __asm__("FUN_L00_00257d78"); -extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); +extern float l06_shuttle_explosion_spark_velocity_scale_random_bound_a __asm__("D_L06_00162114") + __attribute__((sda)); +extern float l06_shuttle_explosion_spark_velocity_scale_random_bound_b __asm__("D_L06_00162118") + __attribute__((sda)); +extern float l06_shuttle_explosion_spark_velocity_w_random_bound_a __asm__("D_L06_0016211C") + __attribute__((sda)); +extern float l06_shuttle_explosion_spark_velocity_w_random_bound_b __asm__("D_L06_00162120") + __attribute__((sda)); +extern float l06_shuttle_explosion_spark_acceleration_scale_random_bound_a __asm__("D_L06_00162124") + __attribute__((sda)); +extern float l06_shuttle_explosion_spark_acceleration_scale_random_bound_b __asm__("D_L06_00162128") + __attribute__((sda)); +extern float l06_shuttle_explosion_spark_acceleration_w_random_bound_a __asm__("D_L06_0016212C") + __attribute__((sda)); +extern float l06_shuttle_explosion_spark_acceleration_w_random_bound_b __asm__("D_L06_00162130") + __attribute__((sda)); +extern int l06_shuttle_explosion_spark_first_color_blend_a __asm__("D_L06_00162134") + __attribute__((sda)); +extern int l06_shuttle_explosion_spark_first_color_blend_b __asm__("D_L06_00162138") + __attribute__((sda)); +extern int l06_shuttle_explosion_spark_second_color_blend_a __asm__("D_L06_0016213C") + __attribute__((sda)); +extern int l06_shuttle_explosion_spark_second_color_blend_b __asm__("D_L06_00162140") + __attribute__((sda)); +extern int l06_shuttle_explosion_spark_timing_random_min_frames __asm__("D_L06_00162144") + __attribute__((sda)); +extern int l06_shuttle_explosion_spark_timing_base_a_frames __asm__("D_L06_00162148") + __attribute__((sda)); +extern int l06_shuttle_explosion_spark_timing_base_b_frames __asm__("D_L06_0016214C") + __attribute__((sda)); +extern int D_L06_00162150 __attribute__((sda)); +extern int l06_shuttle_explosion_spark_table_index __asm__("D_L06_00162154") __attribute__((sda)); +extern int l06_shuttle_explosion_spark_alternate_mode_flag __asm__("D_L06_00162158") + __attribute__((sda)); +extern void random_vector(void *, float, float) __asm__("FUN_L00_00257d78"); +extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); extern u8 * spawn_spark(void *, void *, void *, int, int, int, int, int, int) __asm__("FUN_00218888"); extern void cart_burst(void *, void *, int, float, float) __asm__("FUN_L00_0025f090"); @@ -671,9 +687,12 @@ int update_shuttle_path_ride(char *moby, int path) { return ride->progress == 1.0f; } -void spawn_shuttle_explosion_effect(float scale, char *moby, char *pos, char *push, int count) __asm__("FUN_L06_00303748"); +void spawn_shuttle_explosion_effect( + float scale, char *moby, char *pos, char *push, int count) __asm__("FUN_L06_00303748"); -void spawn_shuttle_explosion_effect(float scale, char *moby, char *explosion_origin, char *push, int count) { +void spawn_shuttle_explosion_effect( + + float scale, char *moby, char *explosion_origin, char *push, int count) { float position[4], direction[4], velocity[4], acceleration[4]; Colors first_colors, second_colors; int i; @@ -721,22 +740,41 @@ void spawn_shuttle_explosion_effect(float scale, char *moby, char *explosion_ori random_vector(direction, 0.0f, 0.9f); fast_vec_add(direction, direction, push); fast_vec_scale( - velocity, direction, random_float_between(l06_shuttle_explosion_spark_velocity_scale_random_bound_a, l06_shuttle_explosion_spark_velocity_scale_random_bound_b) * frame_time); + velocity, + direction, + random_float_between(l06_shuttle_explosion_spark_velocity_scale_random_bound_a, + l06_shuttle_explosion_spark_velocity_scale_random_bound_b) * + frame_time); random_vector(direction, 0.0f, 0.9f); fast_vec_add(direction, direction, push); - fast_vec_scale(acceleration, - direction, - random_float_between(l06_shuttle_explosion_spark_acceleration_scale_random_bound_a, l06_shuttle_explosion_spark_acceleration_scale_random_bound_b) * frame_time); - velocity[3] = random_float_between(l06_shuttle_explosion_spark_velocity_w_random_bound_a, l06_shuttle_explosion_spark_velocity_w_random_bound_b) * scale; - acceleration[3] = random_float_between(l06_shuttle_explosion_spark_acceleration_w_random_bound_a, l06_shuttle_explosion_spark_acceleration_w_random_bound_b) * scale; - color1 = fast_tween_color(l06_shuttle_explosion_spark_first_color_blend_a, l06_shuttle_explosion_spark_first_color_blend_b, random_float_between(0.0f, 1.0f)); - color2 = fast_tween_color(l06_shuttle_explosion_spark_second_color_blend_a, l06_shuttle_explosion_spark_second_color_blend_b, random_float_between(0.0f, 1.0f)); - life = truncate_float_to_s32( - scale_time(random_float_between((float)l06_shuttle_explosion_spark_timing_random_min_frames, (float)(l06_shuttle_explosion_spark_timing_random_min_frames << 1)))); - size = truncate_float_to_s32( - scale_time(random_float_between((float)l06_shuttle_explosion_spark_timing_base_a_frames, (float)l06_shuttle_explosion_spark_timing_base_a_frames * 1.2f))); - fade = truncate_float_to_s32( - scale_time(random_float_between((float)l06_shuttle_explosion_spark_timing_base_b_frames * 0.8f, (float)l06_shuttle_explosion_spark_timing_base_b_frames))); + fast_vec_scale( + acceleration, + direction, + random_float_between(l06_shuttle_explosion_spark_acceleration_scale_random_bound_a, + l06_shuttle_explosion_spark_acceleration_scale_random_bound_b) * + frame_time); + velocity[3] = random_float_between(l06_shuttle_explosion_spark_velocity_w_random_bound_a, + l06_shuttle_explosion_spark_velocity_w_random_bound_b) * + scale; + acceleration[3] = + random_float_between(l06_shuttle_explosion_spark_acceleration_w_random_bound_a, + l06_shuttle_explosion_spark_acceleration_w_random_bound_b) * + scale; + color1 = fast_tween_color(l06_shuttle_explosion_spark_first_color_blend_a, + l06_shuttle_explosion_spark_first_color_blend_b, + random_float_between(0.0f, 1.0f)); + color2 = fast_tween_color(l06_shuttle_explosion_spark_second_color_blend_a, + l06_shuttle_explosion_spark_second_color_blend_b, + random_float_between(0.0f, 1.0f)); + life = truncate_float_to_s32(scale_time(random_float_between( + (float)l06_shuttle_explosion_spark_timing_random_min_frames, + (float)(l06_shuttle_explosion_spark_timing_random_min_frames << 1)))); + size = truncate_float_to_s32(scale_time( + random_float_between((float)l06_shuttle_explosion_spark_timing_base_a_frames, + (float)l06_shuttle_explosion_spark_timing_base_a_frames * 1.2f))); + fade = truncate_float_to_s32(scale_time( + random_float_between((float)l06_shuttle_explosion_spark_timing_base_b_frames * 0.8f, + (float)l06_shuttle_explosion_spark_timing_base_b_frames))); spawn_spark(position, velocity, acceleration, @@ -745,7 +783,8 @@ void spawn_shuttle_explosion_effect(float scale, char *moby, char *explosion_ori life, size, fade, - l06_shuttle_explosion_spark_table_index + (l06_shuttle_explosion_spark_alternate_mode_flag << 16)); + l06_shuttle_explosion_spark_table_index + + (l06_shuttle_explosion_spark_alternate_mode_flag << 16)); } } diff --git a/src/overlays/l06/mobys/split_door.c b/src/overlays/l06/mobys/split_door.c index 9942297cb6..234b8dfad9 100644 --- a/src/overlays/l06/mobys/split_door.c +++ b/src/overlays/l06/mobys/split_door.c @@ -88,7 +88,11 @@ void split_door_update(char *moby) { MOVE_PAIR_TO_FIXED_OFFSETS = 3, ANIMATE_PAIR_WITH_TIMED_PHASES = 4, WAIT_FOR_RESET = 5 - } ; enum { SPLIT_DOOR_PHASE_TARGET_CURRENT_TRANSFORMS = 1 , SPLIT_DOOR_PHASE_TARGET_CONFIGURED_TRANSFORMS = 2}; + }; + enum { + SPLIT_DOOR_PHASE_TARGET_CURRENT_TRANSFORMS = 1, + SPLIT_DOOR_PHASE_TARGET_CONFIGURED_TRANSFORMS = 2 + }; SplitDoorVars *pair_transform_vars = (SplitDoorVars *)MOBY(moby)->pvars; char *child; float position_offset[4]; diff --git a/src/overlays/l07/mobys/equalizer_ammo_spawner.c b/src/overlays/l07/mobys/equalizer_ammo_spawner.c index f3c6cb82d0..83dd07a9a0 100644 --- a/src/overlays/l07/mobys/equalizer_ammo_spawner.c +++ b/src/overlays/l07/mobys/equalizer_ammo_spawner.c @@ -44,7 +44,12 @@ void equalizer_ammo_spawner_update(struct Moby *moby) __asm__("FUN_L07_0031d2e0" /* Moby class 1142 */ void equalizer_ammo_spawner_update(struct Moby *moby) { - enum { EQUALIZER_AMMO_SPAWNER_INITIALIZE_PATH = 0 , EQUALIZER_AMMO_SPAWNER_WAIT_FOR_TRIGGER = 1 , EQUALIZER_AMMO_SPAWNER_COMPLETE = 2 } ;int *ammo_spawner_state = ((int *)moby->pvars); + enum { + EQUALIZER_AMMO_SPAWNER_INITIALIZE_PATH = 0, + EQUALIZER_AMMO_SPAWNER_WAIT_FOR_TRIGGER = 1, + EQUALIZER_AMMO_SPAWNER_COMPLETE = 2 + }; + int *ammo_spawner_state = ((int *)moby->pvars); int state = moby->state; if (state == EQUALIZER_AMMO_SPAWNER_WAIT_FOR_TRIGGER) goto state_one; diff --git a/src/overlays/l07/mobys/mission_gated_taxi_platform.c b/src/overlays/l07/mobys/mission_gated_taxi_platform.c index ffa86ee622..3975c17b14 100644 --- a/src/overlays/l07/mobys/mission_gated_taxi_platform.c +++ b/src/overlays/l07/mobys/mission_gated_taxi_platform.c @@ -66,7 +66,11 @@ typedef struct MissionGatedTaxiPlatformVars { /* Moby class 1474 */ void mission_gated_taxi_platform_update(struct Moby *moby) { - enum { TAXI_PLATFORM_STATE_UNINITIALIZED = 0 , TAXI_PLATFORM_STATE_INITIALIZED = 1 } ;MissionGatedTaxiPlatformVars *mission_gated_taxi_vars = + enum { + TAXI_PLATFORM_STATE_UNINITIALIZED = 0, + TAXI_PLATFORM_STATE_INITIALIZED = 1 + }; + MissionGatedTaxiPlatformVars *mission_gated_taxi_vars = (MissionGatedTaxiPlatformVars *)moby->pvars; char *path; float orig[4], delta[4], path_segment_offset[4]; diff --git a/src/overlays/l07/mobys/snagglebeast.c b/src/overlays/l07/mobys/snagglebeast.c index 83d1ff18bf..0e3c3f55cb 100644 --- a/src/overlays/l07/mobys/snagglebeast.c +++ b/src/overlays/l07/mobys/snagglebeast.c @@ -652,7 +652,7 @@ struct ChaserTarget { extern s32 level_frame_count_lui __asm__("D_L07_0015F5CC"); extern float D_0015ED6C; extern struct ChaserTarget D_L07_00173EC0; -extern int step_mover_2e3f20(struct Moby *, void *, int, void *) __asm__("FUN_L00_00259028"); +extern int step_mover_2e3f20(struct Moby *, void *, int, void *) __asm__("FUN_L00_00259028"); extern int probe_vertical_ground_collision(void *, struct Moby *, int, float, float) __asm__("FUN_L00_002583f0"); int update_snagglebeast_chase_movement(struct Moby *chaser_moby, struct ChaserVars *chaser_vars, @@ -2069,9 +2069,11 @@ void snagglebeast_update(unsigned char *moby) { &pfrac, snagglebeast_instance_state->unk1AC, 1); - hero_to_sample_distance = vector_distance_xy(((char *)&hero) + 0x80, &start); + hero_to_sample_distance = + vector_distance_xy(((char *)&hero) + 0x80, &start); moby_to_sample_distance = vector_distance_xy(moby + 0x10, &start); - } while (hero_to_sample_distance < 8.0f || moby_to_sample_distance < 12.0f); + } while (hero_to_sample_distance < 8.0f || + moby_to_sample_distance < 12.0f); add_random_xy_offset((float *)&start, 0.5f); fast_vec_sub(&direction, &start, ((char *)&hero) + 0x80); zv = start.f[2]; diff --git a/src/overlays/l07/mobys/umbris_scene_progression.c b/src/overlays/l07/mobys/umbris_scene_progression.c index cf716af470..b86659c940 100644 --- a/src/overlays/l07/mobys/umbris_scene_progression.c +++ b/src/overlays/l07/mobys/umbris_scene_progression.c @@ -115,7 +115,8 @@ void umbris_scene_progression_update(struct Moby *moby) { } else { moby->state = CONTROLLER_CLEAR_LINKED_MOBY_FLAGS; } - if (moby->state != CONTROLLER_WAIT_FOR_OPEN_VOLUME && scene_controller_vars->removed_moby != -1) { + if (moby->state != CONTROLLER_WAIT_FOR_OPEN_VOLUME && + scene_controller_vars->removed_moby != -1) { mark_moby_for_removal( &((struct Moby *)level_mobys)[scene_controller_vars->removed_moby]); } @@ -158,7 +159,8 @@ void umbris_scene_progression_update(struct Moby *moby) { struct Moby *e; if (scene_controller_vars->moby_0c == -1 || (e = &((struct Moby *)level_mobys)[scene_controller_vars->moby_0c]) == 0 || - e->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || e->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { + e->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || + e->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { if (scene_controller_vars->finish_volume != -1) { if (is_point_inside_clip_volume(&hero.motion.pos, scene_controller_vars->finish_volume) != 0) { @@ -177,7 +179,8 @@ void umbris_scene_progression_update(struct Moby *moby) { } else { moby->state = CONTROLLER_CLEANUP_LINKED_MOBY; } - if (moby->state != CONTROLLER_WAIT_FOR_FINISH_VOLUME && scene_controller_vars->moby_10 != -1) { + if (moby->state != CONTROLLER_WAIT_FOR_FINISH_VOLUME && + scene_controller_vars->moby_10 != -1) { struct Moby *e = &((struct Moby *)level_mobys)[scene_controller_vars->moby_10]; e->flags |= 0x41; } @@ -218,7 +221,8 @@ void umbris_scene_progression_update(struct Moby *moby) { case CONTROLLER_CLEANUP_LINKED_MOBY: if (scene_controller_vars->moby_10 != -1) { struct Moby *e = &((struct Moby *)level_mobys)[scene_controller_vars->moby_10]; - if (e != 0 && e->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && e->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { + if (e != 0 && e->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + e->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { mark_moby_for_removal(e); } } diff --git a/src/overlays/l07/mobys/water.c b/src/overlays/l07/mobys/water.c index 32da774253..b8ce1e9bd3 100644 --- a/src/overlays/l07/mobys/water.c +++ b/src/overlays/l07/mobys/water.c @@ -311,7 +311,8 @@ void water_update(Moby_30D8E8 *water_moby) { l07_water_grids[water_data->idx].z = water_moby->pos[2]; on = 0.0f; if (water_moby->f94 != 0 && FUN_L01_00275690_2cd2b0(water_moby, 48.0f) != -1) { - if (!(water_moby->state >= WATER_WAIT_FOR_HERO_IN_VOLUME && water_moby->state <= WATER_REMOVE_ABOVE_HIGH_HEIGHT) || + if (!(water_moby->state >= WATER_WAIT_FOR_HERO_IN_VOLUME && + water_moby->state <= WATER_REMOVE_ABOVE_HIGH_HEIGHT) || (water_moby->pos[2] > water_data->lo && water_moby->pos[2] < water_data->hi)) { on = 1.0f; } diff --git a/src/overlays/l08/hero/hero_set_state.c b/src/overlays/l08/hero/hero_set_state.c index 897079f781..b5954e7a12 100644 --- a/src/overlays/l08/hero/hero_set_state.c +++ b/src/overlays/l08/hero/hero_set_state.c @@ -75,7 +75,8 @@ int hero_set_state(int requested_state, int b) { float grind_vector_scratch[4]; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((level_game_mode == 2 || level_game_mode == 6) && b != 2) @@ -83,8 +84,16 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -1002,7 +1011,8 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; diff --git a/src/overlays/l08/hero/update_hero_motion_for_current_state.c b/src/overlays/l08/hero/update_hero_motion_for_current_state.c index 619fc29626..ee43223601 100644 --- a/src/overlays/l08/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l08/hero/update_hero_motion_for_current_state.c @@ -1548,7 +1548,8 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { diff --git a/src/overlays/l08/hero/update_hero_state_transitions.c b/src/overlays/l08/hero/update_hero_state_transitions.c index 01f637a4ea..e9e754ba1a 100644 --- a/src/overlays/l08/hero/update_hero_state_transitions.c +++ b/src/overlays/l08/hero/update_hero_state_transitions.c @@ -189,8 +189,10 @@ void update_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L08_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; @@ -947,7 +949,8 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; diff --git a/src/overlays/l08/level_class_tables.c b/src/overlays/l08/level_class_tables.c index 58d24a7228..6a10a90291 100644 --- a/src/overlays/l08/level_class_tables.c +++ b/src/overlays/l08/level_class_tables.c @@ -19,7 +19,9 @@ #include "rnc/overlay/shared/ui/hud/hud_keep_visible.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" -s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" diff --git a/src/overlays/l08/mobys/blarg_bombthrower.c b/src/overlays/l08/mobys/blarg_bombthrower.c index 928020efe6..f3d4fd4395 100644 --- a/src/overlays/l08/mobys/blarg_bombthrower.c +++ b/src/overlays/l08/mobys/blarg_bombthrower.c @@ -332,9 +332,9 @@ void blarg_bombthrower_update(struct Moby *moby) { break; case BOMBTHROWER_STATE_APPROACH_WAYPOINT: step_mover_2e3f20((char *)moby, - bombthrower_vars->blkD0, - (float *)&bombthrower_vars->waypoint->pos, - (char *)bombthrower_vars->v40); + bombthrower_vars->blkD0, + (float *)&bombthrower_vars->waypoint->pos, + (char *)bombthrower_vars->v40); if (fast_vec_dist(&moby->pos, &bombthrower_vars->waypoint->pos) < 3.0f) { if (fast_difference_between_rotations( moby->rot.z, @@ -374,9 +374,9 @@ void blarg_bombthrower_update(struct Moby *moby) { break; case BOMBTHROWER_STATE_MOVE_ONTO_WAYPOINT: step_mover_2e3f20((char *)moby, - bombthrower_vars->blkD0, - (float *)&bombthrower_vars->waypoint->pos, - (char *)bombthrower_vars->v40); + bombthrower_vars->blkD0, + (float *)&bombthrower_vars->waypoint->pos, + (char *)bombthrower_vars->v40); if (moby->anim_flags & 2) { FUN_00212f90(bombthrower_vars->waypoint, 1, 0, scale_game_frames(6)); qcopy(&moby->pos, &bombthrower_vars->waypoint->pos); diff --git a/src/overlays/l08/mobys/bomb.c b/src/overlays/l08/mobys/bomb.c index 311a6d4650..7259628a57 100644 --- a/src/overlays/l08/mobys/bomb.c +++ b/src/overlays/l08/mobys/bomb.c @@ -54,30 +54,29 @@ extern int collision_line(void *, void *, int, void *, int) __asm__ extern int coll_sphere(float, void *, int, void *) __asm__("FUN_L00_001f0d60"); extern int collect_mobies_in_sphere(void *, float, int, void *, void *) __asm__("FUN_L00_001f2868"); float bomb_downward_acceleration_gp __asm__("D_L08_00161860") = 15.0f; -extern void FUN_L00_001ff660_c(void *, void *, void *) __asm__("FUN_L00_001ff660"); -extern void jet_animate(void *, float) __asm__("FUN_L00_00259fe8"); -extern void trooper_anim_update(void *, short *) __asm__("FUN_L00_0025d458"); -extern void trooper_anim_finish(void *, void *) __asm__("FUN_L00_0025d538"); -extern void spawn_explosion(void *, - void *, - void *, - float, - float, - int, - int, - int, - float, - float, - float, - float, - int, - float, - int, - int, - int, - int) __asm__("FUN_L00_0025e450"); -extern void -spawn_effect(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); +extern void FUN_L00_001ff660_c(void *, void *, void *) __asm__("FUN_L00_001ff660"); +extern void jet_animate(void *, float) __asm__("FUN_L00_00259fe8"); +extern void trooper_anim_update(void *, short *) __asm__("FUN_L00_0025d458"); +extern void trooper_anim_finish(void *, void *) __asm__("FUN_L00_0025d538"); +extern void spawn_explosion(void *, + void *, + void *, + float, + float, + int, + int, + int, + float, + float, + float, + float, + int, + float, + int, + int, + int, + int) __asm__("FUN_L00_0025e450"); +extern void spawn_effect(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); extern float D_L08_0015F580_macro[] __asm__("D_L08_0015F580") MACRO_ADDR; void moby_248_update(char *moby) __asm__("FUN_L08_002d23f0"); extern float D_0015ED6C; @@ -156,13 +155,13 @@ void moby_248_update(char *moby) { fast_vec_normalize(normalized_direction, normalized_direction, D_0015ED6C); selected_table_entry = (int *)table_or_bounce_scratch.b + random_integer_below(4); spawn_effect((moby + 0x10), - normalized_direction, - *selected_table_entry, - 0x4FFF, - scale_game_frames(0x2D), - 0x32, - 0x78, - 1); + normalized_direction, + *selected_table_entry, + 0x4FFF, + scale_game_frames(0x2D), + 0x32, + 0x78, + 1); } qcopy(c.r.start, moby + 0x10); collision_z_offset = 0.16f; diff --git a/src/overlays/l08/mobys/bomber_tank.c b/src/overlays/l08/mobys/bomber_tank.c index bb08244b8e..47346809d1 100644 --- a/src/overlays/l08/mobys/bomber_tank.c +++ b/src/overlays/l08/mobys/bomber_tank.c @@ -299,7 +299,8 @@ void bomber_tank_update(Moby *moby) { bomber_tank_update_vars->part_b->collision = bomber_tank_update_vars->part_b->pclass->collision; moby->flags |= 0x1000; - if (bomber_tank_update_vars->mode != BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM) { + if (bomber_tank_update_vars->mode != + BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM) { moby->state = BOMBER_TANK_STATE_FOLLOW_PATH; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); @@ -325,7 +326,8 @@ void bomber_tank_update(Moby *moby) { bomber_tank_update_vars->part_b->collision = bomber_tank_update_vars->part_b->pclass->collision; moby->flags |= 0x1000; - if (bomber_tank_update_vars->mode != BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM) { + if (bomber_tank_update_vars->mode != + BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM) { moby->state = BOMBER_TANK_STATE_FOLLOW_PATH; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); @@ -675,7 +677,8 @@ void update_bomber_tank_damage_and_aim(Moby *moby) { ((Path *)l08_paths[bomber_tank_damage_and_aim_vars->path])->count); if (bomber_tank_damage_and_aim_vars->fF0 == 0) bomber_tank_damage_and_aim_vars->fF0 = *(int *)D_001413D0; - if (bomber_tank_damage_and_aim_vars->mode != BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM) { + if (bomber_tank_damage_and_aim_vars->mode != + BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM) { float yaw, distance, pitch; fast_vec_sub(burst_position_or_aim_scratch, bomber_tank_damage_and_aim_vars->target, @@ -716,8 +719,10 @@ void update_bomber_tank_damage_and_aim(Moby *moby) { D_0015ED70 * 12.566371f, D_0015ED6C_lui * 9.424778f); } - build_axis_rotation_quaternion(burst_position_or_aim_scratch, 1, bomber_tank_damage_and_aim_vars->pitch); - build_axis_rotation_quaternion(bomber_tank_damage_and_aim_vars->f110, 2, bomber_tank_damage_and_aim_vars->yaw); + build_axis_rotation_quaternion( + burst_position_or_aim_scratch, 1, bomber_tank_damage_and_aim_vars->pitch); + build_axis_rotation_quaternion( + bomber_tank_damage_and_aim_vars->f110, 2, bomber_tank_damage_and_aim_vars->yaw); multiply_quaternions(bomber_tank_damage_and_aim_vars->f110, burst_position_or_aim_scratch, bomber_tank_damage_and_aim_vars->f110); @@ -1183,7 +1188,8 @@ void remove_bomber_tank_linked_debris(struct Moby *moby) { index = *list & 0x7fff; linked_group_moby = (struct Moby *)D_L08_0015FFD8 + index; while (1) { - if (linked_group_moby->state < LINKED_MOBY_ACTIVE_STATE_LIMIT && linked_group_moby != moby) { + if (linked_group_moby->state < LINKED_MOBY_ACTIVE_STATE_LIMIT && + linked_group_moby != moby) { u16 class_id = linked_group_moby->oclass; if ((u32)(class_id - 0x24c) < 0xb) { mark_moby_for_removal(linked_group_moby); diff --git a/src/overlays/l08/mobys/flickering_mesh_effect.c b/src/overlays/l08/mobys/flickering_mesh_effect.c index 9de65333f1..ec87a2daa9 100644 --- a/src/overlays/l08/mobys/flickering_mesh_effect.c +++ b/src/overlays/l08/mobys/flickering_mesh_effect.c @@ -626,7 +626,11 @@ void flickering_mesh_effect_update(struct Moby *moby) __asm__("FUN_L08_002f70a0" /* Moby class 671 */ void flickering_mesh_effect_update(struct Moby *moby) { - enum { FLICKERING_MESH_STATE_UNINITIALIZED = 0 , FLICKERING_MESH_STATE_INITIALIZED = 1 } ;FlickerLightVars *light_vars; + enum { + FLICKERING_MESH_STATE_UNINITIALIZED = 0, + FLICKERING_MESH_STATE_INITIALIZED = 1 + }; + FlickerLightVars *light_vars; Vec4 pos; f32 view, draw_fade_distance, fade; s32 hidden; diff --git a/src/overlays/l08/mobys/swing_gate.c b/src/overlays/l08/mobys/swing_gate.c index 7844e11c3a..ef516cc24e 100644 --- a/src/overlays/l08/mobys/swing_gate.c +++ b/src/overlays/l08/mobys/swing_gate.c @@ -40,7 +40,12 @@ void swing_gate_update(struct Moby *moby) __asm__("FUN_L08_002ea4c0"); /* Moby classes 468, 469 */ void swing_gate_update(struct Moby *moby) { - enum { SWING_GATE_STATE_INITIALIZE = 0 , SWING_GATE_STATE_FOLLOW_DRIVER = 1 , SWING_GATE_STATE_OPEN_LATCHED = 2 } ;SwingGateVars *swing_gate_vars = (SwingGateVars *)moby->pvars; + enum { + SWING_GATE_STATE_INITIALIZE = 0, + SWING_GATE_STATE_FOLLOW_DRIVER = 1, + SWING_GATE_STATE_OPEN_LATCHED = 2 + }; + SwingGateVars *swing_gate_vars = (SwingGateVars *)moby->pvars; f32 progress = *(f32 *)D_L08_0015FFD8[swing_gate_vars->driver].pvars; Vec4 gate_rotation_matrix[4]; Vec4 gate_position_offset; diff --git a/src/overlays/l09/draw_level09_textured_surfaces.c b/src/overlays/l09/draw_level09_textured_surfaces.c index aa2d5d8406..9d5d3ccea1 100644 --- a/src/overlays/l09/draw_level09_textured_surfaces.c +++ b/src/overlays/l09/draw_level09_textured_surfaces.c @@ -314,7 +314,8 @@ void build_packet_and_draw_scaled_entries(void *data_ptr, void *list_ptr, int co (unsigned char)surface_draw_settings[0x31] << 8 | (unsigned char)surface_draw_settings[0x32] << 16; /* Retail reads the mode after the packet cursor stores. */ - if (*(volatile int *)&textured_grid_view_settings_mode == TEXTURED_GRID_USE_CURRENT_VIEW_SETTINGS) + if (*(volatile int *)&textured_grid_view_settings_mode == + TEXTURED_GRID_USE_CURRENT_VIEW_SETTINGS) color = (long)(*(int *)(current + 0x230 / 4) | (*(int *)(current + 0x234 / 4) << 8) | (*(int *)(current + 0x238 / 4) << 16)); { diff --git a/src/overlays/l09/level_class_tables.c b/src/overlays/l09/level_class_tables.c index dba32b9024..73ecadc6ed 100644 --- a/src/overlays/l09/level_class_tables.c +++ b/src/overlays/l09/level_class_tables.c @@ -17,7 +17,9 @@ #include "rnc/overlay/shared/vehicles.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" -s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" diff --git a/src/overlays/l09/mobys/damage_causer.c b/src/overlays/l09/mobys/damage_causer.c index 54c7dcd239..01adbb6702 100644 --- a/src/overlays/l09/mobys/damage_causer.c +++ b/src/overlays/l09/mobys/damage_causer.c @@ -32,7 +32,11 @@ extern s32 D_L09_0015F5CC NOT_SDA; /* Moby class 1206 */ void damage_causer_update(struct Moby *moby) { - enum { DAMAGE_CAUSER_STATE_UNINITIALIZED = 0 , DAMAGE_CAUSER_STATE_INITIALIZED = 1 } ;char *damage_causer_vars = (char *)moby->pvars; + enum { + DAMAGE_CAUSER_STATE_UNINITIALIZED = 0, + DAMAGE_CAUSER_STATE_INITIALIZED = 1 + }; + char *damage_causer_vars = (char *)moby->pvars; float sphere_query_workspace[24]; int i; float count_as_float; diff --git a/src/overlays/l09/mobys/refueling_station.c b/src/overlays/l09/mobys/refueling_station.c index ddb4623676..9b0b9cffa7 100644 --- a/src/overlays/l09/mobys/refueling_station.c +++ b/src/overlays/l09/mobys/refueling_station.c @@ -135,7 +135,9 @@ void handle_refueling_station_damage(struct Moby *moby, moby->flags &= ~0x1000; if (refueling_station_vars->link != -1) { link = &moby_list[refueling_station_vars->link]; - if (link != 0 && link->state != MOBY_STATE_REMOVAL_PENDING_AT_OR_ABOVE_ADDRESS_BOUNDARY && link->state != MOBY_STATE_REMOVAL_PENDING_BELOW_ADDRESS_BOUNDARY && + if (link != 0 && + link->state != MOBY_STATE_REMOVAL_PENDING_AT_OR_ABOVE_ADDRESS_BOUNDARY && + link->state != MOBY_STATE_REMOVAL_PENDING_BELOW_ADDRESS_BOUNDARY && (link->oclass == 0x494 || link->oclass == 0x49D || link->oclass == 0x4A0)) { link->command = 1; } diff --git a/src/overlays/l10/level_class_tables.c b/src/overlays/l10/level_class_tables.c index 7f53cf4bb5..ca0d350a42 100644 --- a/src/overlays/l10/level_class_tables.c +++ b/src/overlays/l10/level_class_tables.c @@ -369,7 +369,7 @@ struct CameraType level_camera_types[9] __asm__("D_L10_001DDE80") __attribute__( {17, FUN_L00_002ed230, noop_main_callback, noop_main_callback, noop_main_callback}, {19, evaluate_descriptor_eligibility, initialize_path_camera, - update_path_flythrough_camera, noop_main_callback }, + update_path_flythrough_camera, noop_main_callback }, {23, volume_camera_check, noop_main_callback, noop_main_callback, noop_main_callback}, {-1, 0, 0, 0, 0}, }; diff --git a/src/overlays/l10/mobys/blarg_ship.c b/src/overlays/l10/mobys/blarg_ship.c index cb839df0c1..0bbdc8aee5 100644 --- a/src/overlays/l10/mobys/blarg_ship.c +++ b/src/overlays/l10/mobys/blarg_ship.c @@ -486,7 +486,12 @@ void update_blarg_ship_hit_reactions_and_targeting(struct Moby *moby) { COLOR_UPDATE_WITHOUT_STATE_CHANGE_HIT_RESPONSE = 10, COLOR_EFFECT_ONLY_HIT_RESPONSE = 12, NO_REACTION_HIT_RESPONSE = 13 - } ; enum { HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1 , BLARG_SHIP_STATE_HIT_REACTION = 7 , BLARG_SHIP_STATE_EXPLODE = 8}; + }; + enum { + HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1, + BLARG_SHIP_STATE_HIT_REACTION = 7, + BLARG_SHIP_STATE_EXPLODE = 8 + }; BlargShipVars *pvars = (BlargShipVars *)moby->pvars; char *ship_hit_record = find_moby_hit(moby, 0x370000, 0); int ship_hit_processing_status; @@ -495,7 +500,8 @@ void update_blarg_ship_hit_reactions_and_targeting(struct Moby *moby) { dmg = 0.0f; hit_response_code = resolve_moby_hit_response( moby, ship_hit_record, &pvars->unk20, 5, &ship_hit_processing_status, &dmg, 0, 4); - if (ship_hit_record != 0 && ship_hit_processing_status != HIT_STATUS_SKIP_DAMAGE_AND_REACTION && moby->state != BLARG_SHIP_STATE_EXPLODE) { + if (ship_hit_record != 0 && ship_hit_processing_status != HIT_STATUS_SKIP_DAMAGE_AND_REACTION && + moby->state != BLARG_SHIP_STATE_EXPLODE) { if ((pvars->unk20 -= dmg) <= 0.0f) { hit_response_code = 1; } diff --git a/src/overlays/l10/mobys/darter.c b/src/overlays/l10/mobys/darter.c index f4946ecdf9..29755e89ef 100644 --- a/src/overlays/l10/mobys/darter.c +++ b/src/overlays/l10/mobys/darter.c @@ -104,7 +104,8 @@ extern float l10_darter_max_wander_height_offset __asm__("D_L10_00161E08") __att extern float l10_darter_bob_amplitude __asm__("D_L10_00161E0C") __attribute__((sda)); extern float l10_darter_bob_period_seconds __asm__("D_L10_00161E10") __attribute__((sda)); extern float l10_darter_max_height_offset __asm__("D_L10_00161E14") __attribute__((sda)); -extern float l10_darter_height_change_interval_seconds __asm__("D_L10_00161E18") __attribute__((sda)); +extern float l10_darter_height_change_interval_seconds __asm__("D_L10_00161E18") + __attribute__((sda)); extern float D_L10_00161E1C __attribute__((sda)); extern float D_L10_00161E20 __attribute__((sda)); extern int coll_sphere_mobys(float, void *, int, void *, void *) __asm__("FUN_L00_001f2868"); @@ -191,8 +192,9 @@ void darter_update(Moby *moby) { moby->pos.z = l10_cuboids[darter_vars->f194].pos.z; add_vectors(&vector_and_collision_scratch[4], &moby->pos, vector_and_collision_scratch); darter_vars->height_offset = random_float_between(0.0f, l10_darter_max_height_offset); - darter_vars->height_timer = truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * - random_float_between(0.75f, 1.25f)); + darter_vars->height_timer = truncate_float_to_s32( + scale_time(l10_darter_height_change_interval_seconds * 60.0f) * + random_float_between(0.75f, 1.25f)); if (moby->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); break; @@ -228,8 +230,8 @@ void darter_update(Moby *moby) { D_0015ED70 * 25.132742f, frame_time * 50.265484f); if (fast_difference_between_rotations( - fast_arc_tan(darter_vars->goal.x - moby->pos.x, darter_vars->goal.y - moby->pos.y), moby->rot.z) < - 0.78539819f) { + fast_arc_tan(darter_vars->goal.x - moby->pos.x, darter_vars->goal.y - moby->pos.y), + moby->rot.z) < 0.78539819f) { advance_accelerated_scalar(&travelled, dist, &speed, @@ -248,7 +250,8 @@ void darter_update(Moby *moby) { vector_and_collision_scratch[0] = fast_cos(angle) * radius; vector_and_collision_scratch[1] = fast_sin(angle) * radius; vector_and_collision_scratch[2] = zero; - vector_and_collision_scratch[2] = random_float_between(l10_darter_min_wander_height_offset, l10_darter_max_wander_height_offset); + vector_and_collision_scratch[2] = random_float_between( + l10_darter_min_wander_height_offset, l10_darter_max_wander_height_offset); fast_vec_add(&darter_vars->goal, vector_and_collision_scratch, &darter_vars->home); } else if (dist < 0.1f) { moby->state = DARTER_STATE_WAIT_BETWEEN_WANDER_GOALS; @@ -287,7 +290,8 @@ void darter_update(Moby *moby) { vector_and_collision_scratch[0] = fast_cos(angle) * radius; vector_and_collision_scratch[1] = fast_sin(angle) * radius; vector_and_collision_scratch[2] = 0.0f; - vector_and_collision_scratch[2] = random_float_between(l10_darter_min_wander_height_offset, l10_darter_max_wander_height_offset); + vector_and_collision_scratch[2] = random_float_between( + l10_darter_min_wander_height_offset, l10_darter_max_wander_height_offset); fast_vec_add(&darter_vars->goal, vector_and_collision_scratch, &darter_vars->home); moby->state = DARTER_STATE_WANDER; } @@ -323,7 +327,9 @@ void darter_update(Moby *moby) { ground_height = probe_ground_height(&moby->pos, 0, 0.5f); qcopy(vector_and_collision_scratch, &target->pos); if (vector_and_collision_scratch[2] < moby->pos.z) { - vector_and_collision_scratch[2] = vector_and_collision_scratch[2] - (moby->pos.z - vector_and_collision_scratch[2]) * 4.0f; + vector_and_collision_scratch[2] = + vector_and_collision_scratch[2] - + (moby->pos.z - vector_and_collision_scratch[2]) * 4.0f; } else { vector_and_collision_scratch[2] = moby->pos.z; } @@ -335,10 +341,11 @@ void darter_update(Moby *moby) { darter_vars->velocity.x = fast_cos(moby->rot.z) * vector_length_xy(&darter_vars->velocity); darter_vars->velocity.y = fast_sin(moby->rot.z) * vector_length_xy(&darter_vars->velocity); func_L00_00259B08_2E0630(moby, &darter_vars->velocity, 0.5f, 0x200, 0.0f, 0); - func_L00_0025CC58_2E0630(&moby->rot.y, - 0, - -fast_arc_tan(vector_length_xy(&darter_vars->velocity), darter_vars->velocity.z), - frame_time * 6.2831855f); + func_L00_0025CC58_2E0630( + &moby->rot.y, + 0, + -fast_arc_tan(vector_length_xy(&darter_vars->velocity), darter_vars->velocity.z), + frame_time * 6.2831855f); if (vector_distance_xy(&moby->pos, &target->pos) < l10_darter_attack_distance) { if (absolute_float(moby->pos.z - ((Hero_2e01a8 *)((char *)&hero))->motion.pos.f[2]) < 2.0f) { @@ -364,11 +371,11 @@ void darter_update(Moby *moby) { 0.02f, 0.3f, frame_time * 6.2831855f); - func_L00_0025CC58_2E0630( - &moby->rot.y, - 0, - -fast_arc_tan(vector_distance_xy(&moby->pos, &darter_vars->vE0), darter_vars->vE0.z - moby->pos.z), - frame_time * 12.566371f); + func_L00_0025CC58_2E0630(&moby->rot.y, + 0, + -fast_arc_tan(vector_distance_xy(&moby->pos, &darter_vars->vE0), + darter_vars->vE0.z - moby->pos.z), + frame_time * 12.566371f); if (is_value_within_interpolated_window((char *)moby, 20.0f)) { float one = 1.0f; *(int *)&vector_and_collision_scratch[13] = 1; @@ -383,8 +390,13 @@ void darter_update(Moby *moby) { *(short *)((char *)vector_and_collision_scratch + 0x3A) = moby->oclass; ((unsigned char *)vector_and_collision_scratch)[0x38] = 0; FUN_L00_0024f7c8(moby, 0, vector_and_collision_scratch); - coll_sphere_mobys(0.4f, vector_and_collision_scratch, 0, moby, &vector_and_collision_scratch[8]); - collision_line(&moby->pos, vector_and_collision_scratch, 9, moby, &vector_and_collision_scratch[8]); + coll_sphere_mobys( + 0.4f, vector_and_collision_scratch, 0, moby, &vector_and_collision_scratch[8]); + collision_line(&moby->pos, + vector_and_collision_scratch, + 9, + moby, + &vector_and_collision_scratch[8]); } if (darter_vars->f104 != 2 && (moby->anim_flags & 2) == 0) break; @@ -396,12 +408,13 @@ void darter_update(Moby *moby) { float zero = 0.0f; float climb; func_L00_0025CC58_2E0630(&moby->rot.y, 0, zero, frame_time * 12.566371f); - approach_w(moby, - fast_arc_tan(darter_vars->home.x - moby->pos.x, darter_vars->home.y - moby->pos.y), - &darter_vars->turn_speed, - 0.02f, - 0.3f, - frame_time * 6.2831855f); + approach_w( + moby, + fast_arc_tan(darter_vars->home.x - moby->pos.x, darter_vars->home.y - moby->pos.y), + &darter_vars->turn_speed, + 0.02f, + 0.3f, + frame_time * 6.2831855f); darter_vars->velocity.x = fast_cos(moby->rot.z) * (frame_time * 6.0f); darter_vars->velocity.y = fast_sin(moby->rot.z) * (frame_time * 6.0f); darter_vars->velocity.z = zero; @@ -420,19 +433,21 @@ void darter_update(Moby *moby) { case DARTER_STATE_CUBOID_PATROL: { float dist = fast_vec_dist(&moby->pos, &target->pos); float climb; - approach_w(moby, - fast_arc_tan(darter_vars->home.x - moby->pos.x, darter_vars->home.y - moby->pos.y), - &darter_vars->turn_speed, - 0.02f, - 0.3f, - frame_time * 0.78539819f); + approach_w( + moby, + fast_arc_tan(darter_vars->home.x - moby->pos.x, darter_vars->home.y - moby->pos.y), + &darter_vars->turn_speed, + 0.02f, + 0.3f, + frame_time * 0.78539819f); darter_vars->velocity.x = fast_cos(moby->rot.z) * (frame_time * 4.0f); darter_vars->velocity.y = fast_sin(moby->rot.z) * (frame_time * 4.0f); darter_vars->velocity.z = 0.0f; if (fast_dec_timer(&darter_vars->height_timer)) { darter_vars->height_offset = random_float_between(0.0f, l10_darter_max_height_offset); - darter_vars->height_timer = truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * - random_float_between(0.75f, 1.25f)); + darter_vars->height_timer = truncate_float_to_s32( + scale_time(l10_darter_height_change_interval_seconds * 60.0f) * + random_float_between(0.75f, 1.25f)); } climb = l10_cuboids[darter_vars->f194].pos.z - moby->pos.z - darter_vars->height_offset; if (frame_time + frame_time < climb) { @@ -489,8 +504,9 @@ void darter_update(Moby *moby) { break; moby->state = DARTER_STATE_CUBOID_PATROL; darter_vars->height_offset = random_float_between(0.0f, l10_darter_max_height_offset); - darter_vars->height_timer = truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * - random_float_between(0.75f, 1.25f)); + darter_vars->height_timer = + truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * + random_float_between(0.75f, 1.25f)); break; } case DARTER_STATE_CUBOID_CHARGE_ATTACK: { @@ -524,7 +540,8 @@ void darter_update(Moby *moby) { vector_and_collision_scratch[11] = one; clear_u64_value(&vector_and_collision_scratch[4]); FUN_L00_0024f7c8(moby, 0, vector_and_collision_scratch); - coll_sphere_mobys(0.2f, vector_and_collision_scratch, 0, moby, &vector_and_collision_scratch[4]); + coll_sphere_mobys( + 0.2f, vector_and_collision_scratch, 0, moby, &vector_and_collision_scratch[4]); if (fast_vec_dist(&moby->pos, &target->pos) < one || *(int *)(((char *)&hero) + 0x208C) == 7 || (moby->anim_flags & 2)) { moby->state = DARTER_STATE_CUBOID_RETURN_HOME; @@ -536,18 +553,20 @@ void darter_update(Moby *moby) { break; moby->state = DARTER_STATE_CUBOID_PATROL; darter_vars->height_offset = random_float_between(zero, l10_darter_max_height_offset); - darter_vars->height_timer = truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * - random_float_between(0.75f, 1.25f)); + darter_vars->height_timer = + truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * + random_float_between(0.75f, 1.25f)); break; } case DARTER_STATE_CUBOID_RETURN_HOME: { float climb; - approach_w(moby, - fast_arc_tan(darter_vars->home.x - moby->pos.x, darter_vars->home.y - moby->pos.y), - &darter_vars->turn_speed, - 0.02f, - 0.3f, - frame_time * 1.0471976f); + approach_w( + moby, + fast_arc_tan(darter_vars->home.x - moby->pos.x, darter_vars->home.y - moby->pos.y), + &darter_vars->turn_speed, + 0.02f, + 0.3f, + frame_time * 1.0471976f); darter_vars->velocity.x = fast_cos(moby->rot.z) * (frame_time * 4.0f); darter_vars->velocity.y = fast_sin(moby->rot.z) * (frame_time * 4.0f); darter_vars->velocity.z = 0.0f; @@ -563,8 +582,9 @@ void darter_update(Moby *moby) { moby->state = DARTER_STATE_CUBOID_PATROL; moby->command = scale_game_frames(0x78); darter_vars->height_offset = random_float_between(0.0f, l10_darter_max_height_offset); - darter_vars->height_timer = truncate_float_to_s32(scale_time(l10_darter_height_change_interval_seconds * 60.0f) * - random_float_between(0.75f, 1.25f)); + darter_vars->height_timer = truncate_float_to_s32( + scale_time(l10_darter_height_change_interval_seconds * 60.0f) * + random_float_between(0.75f, 1.25f)); } break; } @@ -579,7 +599,8 @@ void darter_update(Moby *moby) { if (moby->state != DARTER_STATE_INITIALIZE && moby->state != DARTER_STATE_DYING) { darter_vars->bob_angle = fast_add_rotations( darter_vars->bob_angle, - 360.0f / (float)truncate_float_to_s32(scale_time(l10_darter_bob_period_seconds * 60.0f)) * + 360.0f / + (float)truncate_float_to_s32(scale_time(l10_darter_bob_period_seconds * 60.0f)) * 0.017453292f); moby->pos.z = moby->pos.z + l10_darter_bob_amplitude * fast_cos(darter_vars->bob_angle); } diff --git a/src/overlays/l10/mobys/jitter_strand_grid.c b/src/overlays/l10/mobys/jitter_strand_grid.c index fc5a1724ca..2b3979e08d 100644 --- a/src/overlays/l10/mobys/jitter_strand_grid.c +++ b/src/overlays/l10/mobys/jitter_strand_grid.c @@ -18,9 +18,10 @@ extern s32 D_L10_00161D68; extern int D_L10_00161D64; extern int D_L10_00161D68; -extern float l10_jitter_strand_random_vector_time_scale __asm__("D_L10_00161D54") __attribute__((sda)); -float jitter_strand_row_y_span_gp __asm__("D_L10_00161D58") = 2.5f; -float jitter_strand_phase_advance_rate_gp __asm__("D_L10_00161D5C") = 2.0f; +extern float l10_jitter_strand_random_vector_time_scale __asm__("D_L10_00161D54") + __attribute__((sda)); +float jitter_strand_row_y_span_gp __asm__("D_L10_00161D58") = 2.5f; +float jitter_strand_phase_advance_rate_gp __asm__("D_L10_00161D5C") = 2.0f; typedef struct { Vec4 pos[4][30][20]; @@ -75,8 +76,9 @@ void jitter_strand_grid_update(struct Moby *moby) { row * (jitter_strand_row_y_span_gp / 20.0f) - jitter_strand_row_y_span_gp * 0.5f; jitter_strand_grid_vars->pos[group][row][strand_column].f[3] = 1.0f; - random_vector( - &jitter[row][strand_column], 0.0f, l10_jitter_strand_random_vector_time_scale * frame_time); + random_vector(&jitter[row][strand_column], + 0.0f, + l10_jitter_strand_random_vector_time_scale * frame_time); } for (row = 1; row < 19; row++) { fast_vec_add(&jitter_strand_grid_vars->vel[group][row][strand_column], diff --git a/src/overlays/l10/mobys/linked_moby_hitbox.c b/src/overlays/l10/mobys/linked_moby_hitbox.c index 0d7464eb8e..0494ee8883 100644 --- a/src/overlays/l10/mobys/linked_moby_hitbox.c +++ b/src/overlays/l10/mobys/linked_moby_hitbox.c @@ -145,7 +145,11 @@ void linked_moby_hitbox_update(struct Moby *moby) { LINKED_HITBOX_STATE_WAIT_FOR_LINKED_MOBIES = 1, LINKED_HITBOX_STATE_WAIT_FOR_TARGET_STATE_OR_TIMER = 2, LINKED_HITBOX_STATE_REMOVE = 3 - } ; enum { MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF = 0xfd , MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF = 0xfe}; + }; + enum { + MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF = 0xfd, + MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF = 0xfe + }; LinkedMobyHitboxVars *linked_hitbox_vars = (LinkedMobyHitboxVars *)moby->pvars; int differences = 0; struct Moby *target = 0; @@ -164,7 +168,8 @@ void linked_moby_hitbox_update(struct Moby *moby) { if (index != -1) { struct Moby *linked_moby = &D_L10_0015FFD8[index]; if (linked_moby != 0 && linked_moby->oclass == *(short *)(entry + 1) && - linked_moby->state != MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF && linked_moby->state != MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF) { + linked_moby->state != MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF && + linked_moby->state != MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF) { unsigned short id = linked_moby->save_id; if ((((*(int *)((unsigned char *)D_0014C190_257218 + (((short)id >> 5) * 4) + (D_0015ED84 << 8)) >> diff --git a/src/overlays/l10/mobys/toxic_crab.c b/src/overlays/l10/mobys/toxic_crab.c index 11f42adcd6..9c8baca487 100644 --- a/src/overlays/l10/mobys/toxic_crab.c +++ b/src/overlays/l10/mobys/toxic_crab.c @@ -299,7 +299,8 @@ void toxic_crab_update(Moby2E30F8 *m) { int k = crab_data->i1BC; if (k != -1) { Moby2E30F8 *p = (Moby2E30F8 *)((char *)D_L10_0015FFD0_macro[2] + (k << 8)); - if (p == 0 || p->state == MOBY_STATE_MARKED_FOR_REMOVAL || p->state == MOBY_STATE_ALTERNATE_REMOVAL_MARKER || + if (p == 0 || p->state == MOBY_STATE_MARKED_FOR_REMOVAL || + p->state == MOBY_STATE_ALTERNATE_REMOVAL_MARKER || (((*(int *)(((char *)&D_0014C190) + (((short)p->id >> 5) * 4 + (current_level_index << 8))) >> (p->id & 0x1F)) & @@ -321,7 +322,8 @@ void toxic_crab_update(Moby2E30F8 *m) { if (crab_data->i1BC != -1) { char *moby_instance_array_base = D_L10_0015FFD8; Moby2E30F8 *p = (Moby2E30F8 *)(moby_instance_array_base + (crab_data->i1BC << 8)); - if (p == 0 || p->state == MOBY_STATE_MARKED_FOR_REMOVAL || p->state == MOBY_STATE_ALTERNATE_REMOVAL_MARKER || + if (p == 0 || p->state == MOBY_STATE_MARKED_FOR_REMOVAL || + p->state == MOBY_STATE_ALTERNATE_REMOVAL_MARKER || ((*(int *)(((char *)&D_0014C190) + (((short)p->id >> 5) * 4 + (current_level_index << 8))) >> (p->id & 0x1F)) & @@ -500,7 +502,8 @@ void toxic_crab_update(Moby2E30F8 *m) { } else { crab_data->i1D8 = 0; } - if (m->state == TOXIC_CRAB_STATE_PURSUE_TARGET && fast_dec_timer(&crab_data->i1A8) && 0.0f < crab_data->fF4 && + if (m->state == TOXIC_CRAB_STATE_PURSUE_TARGET && + fast_dec_timer(&crab_data->i1A8) && 0.0f < crab_data->fF4 && crab_data->i1D8 == 0 && m->anim == 1) { blend_moby_animation(m, 3, 0, scale_game_frames(7)); } @@ -518,7 +521,8 @@ void toxic_crab_update(Moby2E30F8 *m) { m->f58 = 1.2f; { float home = fast_vec_dist(m->pos, crab_data->v170); - if ((hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK ? 1.0f : 30.0f) < home || crab_data->i164 == 2) { + if ((hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK ? 1.0f : 30.0f) < home || + crab_data->i164 == 2) { m->state = TOXIC_CRAB_STATE_RETURN_HOME; blend_moby_animation(m, 4, 0, scale_game_frames(0xC)); } else if (vector_distance_xy(m->pos, target_moby + 0x10) < @@ -576,7 +580,8 @@ void toxic_crab_update(Moby2E30F8 *m) { } { float home = fast_vec_dist(m->pos, crab_data->v170); - if ((hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK ? 1.0f : 30.0f) < home || crab_data->i164 == 2) { + if ((hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK ? 1.0f : 30.0f) < home || + crab_data->i164 == 2) { m->state = TOXIC_CRAB_STATE_RETURN_HOME; blend_moby_animation(m, 4, 0, scale_game_frames(0xC)); } else if (vector_distance_xy(m->pos, target_moby + 0x10) < @@ -812,7 +817,9 @@ void toxic_crab_update(Moby2E30F8 *m) { } } } - if (m->state == TOXIC_CRAB_STATE_FACE_TRACKED_POSITION || m->state == TOXIC_CRAB_STATE_PURSUE_TARGET || m->state == TOXIC_CRAB_STATE_MELEE_ATTACK || m->state == TOXIC_CRAB_STATE_RETURN_HOME) { + if (m->state == TOXIC_CRAB_STATE_FACE_TRACKED_POSITION || + m->state == TOXIC_CRAB_STATE_PURSUE_TARGET || m->state == TOXIC_CRAB_STATE_MELEE_ATTACK || + m->state == TOXIC_CRAB_STATE_RETURN_HOME) { float ground_height = probe_ground_height(m->pos, 0, 0.5f); if (ground_height < m->pos[2]) { crab_data->f78 = crab_data->f78 - crab_data->f80; @@ -841,14 +848,21 @@ void toxic_crab_update(Moby2E30F8 *m) { extern int l10_toxic_crab_particle_group_count __asm__("D_L10_00161E74") __attribute__((sda)); extern int l10_toxic_crab_particles_per_group __asm__("D_L10_00161E78") __attribute__((sda)); -extern float l10_toxic_crab_particle_group_position_jitter __asm__("D_L10_00161E7C") __attribute__((sda)); +extern float l10_toxic_crab_particle_group_position_jitter __asm__("D_L10_00161E7C") + __attribute__((sda)); extern float l10_toxic_crab_particle_position_jitter __asm__("D_L10_00161E80") __attribute__((sda)); -extern float l10_toxic_crab_particle_adjusted_velocity_jitter __asm__("D_L10_00161E84") __attribute__((sda)); -extern float l10_toxic_crab_particle_speed_lower_bound __asm__("D_L10_00161E88") __attribute__((sda)); -extern float l10_toxic_crab_particle_speed_upper_bound __asm__("D_L10_00161E8C") __attribute__((sda)); -extern float l10_toxic_crab_particle_rise_lower_bound __asm__("D_L10_00161E90") __attribute__((sda)); -extern float l10_toxic_crab_particle_rise_upper_bound __asm__("D_L10_00161E94") __attribute__((sda)); -extern float l10_toxic_crab_particle_vertical_velocity_drop_scale __asm__("D_L10_00161E98") __attribute__((sda)); +extern float l10_toxic_crab_particle_adjusted_velocity_jitter __asm__("D_L10_00161E84") + __attribute__((sda)); +extern float l10_toxic_crab_particle_speed_lower_bound __asm__("D_L10_00161E88") + __attribute__((sda)); +extern float l10_toxic_crab_particle_speed_upper_bound __asm__("D_L10_00161E8C") + __attribute__((sda)); +extern float l10_toxic_crab_particle_rise_lower_bound __asm__("D_L10_00161E90") + __attribute__((sda)); +extern float l10_toxic_crab_particle_rise_upper_bound __asm__("D_L10_00161E94") + __attribute__((sda)); +extern float l10_toxic_crab_particle_vertical_velocity_drop_scale __asm__("D_L10_00161E98") + __attribute__((sda)); extern float D_L10_00161E9C __attribute__((sda)); extern float D_L10_00161EA0 __attribute__((sda)); extern int l10_toxic_crab_particle_start_color_a __asm__("D_L10_00161EA4") __attribute__((sda)); @@ -857,9 +871,10 @@ extern int l10_toxic_crab_particle_start_color_b __asm__("D_L10_00161EAC") __a extern int l10_toxic_crab_particle_end_color_b __asm__("D_L10_00161EB0") __attribute__((sda)); extern int l10_toxic_crab_particle_life_frames __asm__("D_L10_00161EB4") __attribute__((sda)); extern int l10_toxic_crab_particle_fade_frames __asm__("D_L10_00161EB8") __attribute__((sda)); -extern int l10_toxic_crab_particle_random_duration_base __asm__("D_L10_00161EBC") __attribute__((sda)); -extern void add_random_offset_to_vector_xyz(void *, float) __asm__("FUN_L00_0025f8e0"); -extern int fast_tween_color_3a90(int, int, float) __asm__("FUN_001fa6e0"); +extern int l10_toxic_crab_particle_random_duration_base __asm__("D_L10_00161EBC") + __attribute__((sda)); +extern void add_random_offset_to_vector_xyz(void *, float) __asm__("FUN_L00_0025f8e0"); +extern int fast_tween_color_3a90(int, int, float) __asm__("FUN_001fa6e0"); void emit_moby_particles(struct Moby *moby) __asm__("FUN_L10_002e3a90"); @@ -893,8 +908,10 @@ void emit_moby_particles(struct Moby *moby) { add_random_offset_to_vector_xyz(pos_ptr, l10_toxic_crab_particle_group_position_jitter); pos[2] += 0.55f; angle = random_angle_radians(); - speed = random_float_between(l10_toxic_crab_particle_speed_lower_bound, l10_toxic_crab_particle_speed_upper_bound); - rise = random_float_between(l10_toxic_crab_particle_rise_lower_bound, l10_toxic_crab_particle_rise_upper_bound); + speed = random_float_between(l10_toxic_crab_particle_speed_lower_bound, + l10_toxic_crab_particle_speed_upper_bound); + rise = random_float_between(l10_toxic_crab_particle_rise_lower_bound, + l10_toxic_crab_particle_rise_upper_bound); if (*((u8 *)moby + 0x20) == 11) { speed *= 0.55f; rise *= 0.55f; @@ -907,17 +924,23 @@ void emit_moby_particles(struct Moby *moby) { push[2] = 0.0f; fast_vec_add(particle_velocity, particle_velocity, push); qcopy(adjusted_particle_velocity, particle_velocity); - adjusted_particle_velocity[2] -= l10_toxic_crab_particle_vertical_velocity_drop_scale * D_0015ED70 * (float)scale_game_frames(l10_toxic_crab_particle_fade_frames); + adjusted_particle_velocity[2] -= + l10_toxic_crab_particle_vertical_velocity_drop_scale * D_0015ED70 * + (float)scale_game_frames(l10_toxic_crab_particle_fade_frames); for (j = 0; j < l10_toxic_crab_particles_per_group; j++) { size = random_float_between(0.5f, 1.5f); particle_velocity[3] = size * D_L10_00161E9C; adjusted_particle_velocity[3] = size * D_L10_00161EA0; add_random_offset_to_vector_xyz(pos, l10_toxic_crab_particle_position_jitter); - add_random_offset_to_vector_xyz(adjusted_particle_velocity, l10_toxic_crab_particle_adjusted_velocity_jitter * D_0015ED6C); - start_color = fast_tween_color_3a90( - l10_toxic_crab_particle_start_color_a, l10_toxic_crab_particle_start_color_b, random_float_between(0.0f, 1.0f)); - end_color = fast_tween_color_3a90( - l10_toxic_crab_particle_end_color_a, l10_toxic_crab_particle_end_color_b, random_float_between(0.0f, 1.0f)); + add_random_offset_to_vector_xyz(adjusted_particle_velocity, + l10_toxic_crab_particle_adjusted_velocity_jitter * + D_0015ED6C); + start_color = fast_tween_color_3a90(l10_toxic_crab_particle_start_color_a, + l10_toxic_crab_particle_start_color_b, + random_float_between(0.0f, 1.0f)); + end_color = fast_tween_color_3a90(l10_toxic_crab_particle_end_color_a, + l10_toxic_crab_particle_end_color_b, + random_float_between(0.0f, 1.0f)); life = scale_game_frames(l10_toxic_crab_particle_life_frames); fade = scale_game_frames(l10_toxic_crab_particle_fade_frames); time_base = (float)l10_toxic_crab_particle_random_duration_base; @@ -1060,7 +1083,8 @@ void update_toxic_crab_hit_reactions_and_targeting(void *mv) { hit_response_code = resolve_moby_hit_response(moby, hit_record, &moby_data->f20, 0, &A, &B, 0, 4); fast_dec_timer_s16(&moby_data->h26); - if ((unsigned int)A >= 2 && moby->state != TOXIC_CRAB_STATE_DEATH_EFFECTS && moby->state != TOXIC_CRAB_STATE_FALL_TO_DEATH) { + if ((unsigned int)A >= 2 && moby->state != TOXIC_CRAB_STATE_DEATH_EFFECTS && + moby->state != TOXIC_CRAB_STATE_FALL_TO_DEATH) { if (current_level_index == 10 && hit_record != 0 && hit_record->f20 != 0 && hit_record->f20->oclass == 0x31A) { if (moby_data->f1AC != 0 && item_unlocked[0x11] == 0) { diff --git a/src/overlays/l11/hero/hero_set_state.c b/src/overlays/l11/hero/hero_set_state.c index 89f50d8892..81dc5552f8 100644 --- a/src/overlays/l11/hero/hero_set_state.c +++ b/src/overlays/l11/hero/hero_set_state.c @@ -71,7 +71,8 @@ int hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L11_0015F5C4 == 2 || D_L11_0015F5C4 == 6) && b != 2) @@ -79,8 +80,16 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -939,7 +948,8 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; diff --git a/src/overlays/l11/hero/update_hero_motion_by_state.c b/src/overlays/l11/hero/update_hero_motion_by_state.c index 5c7e8e70cb..49d015c6c8 100644 --- a/src/overlays/l11/hero/update_hero_motion_by_state.c +++ b/src/overlays/l11/hero/update_hero_motion_by_state.c @@ -824,8 +824,8 @@ void update_hero_motion_by_state(void) { build_spherical_offset( &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { - f32 sp = - hero.ground_speed * vector_length_xyz_cf(swim_animation_speed_factors, 0x1E) * 5.0f; + f32 sp = hero.ground_speed * + vector_length_xyz_cf(swim_animation_speed_factors, 0x1E) * 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -955,8 +955,8 @@ void update_hero_motion_by_state(void) { } speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { - f32 sp = - hero.ground_speed * vector_length_xyz_cf(swim_animation_speed_factors, 0x1E) * 5.5f; + f32 sp = hero.ground_speed * + vector_length_xyz_cf(swim_animation_speed_factors, 0x1E) * 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; @@ -1551,7 +1551,8 @@ void update_hero_motion_by_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { diff --git a/src/overlays/l11/hero/update_hero_state_transitions.c b/src/overlays/l11/hero/update_hero_state_transitions.c index a25b47c4f8..2bf942585d 100644 --- a/src/overlays/l11/hero/update_hero_state_transitions.c +++ b/src/overlays/l11/hero/update_hero_state_transitions.c @@ -156,8 +156,10 @@ void update_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L11_0015F594_gp == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; @@ -912,7 +914,8 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; diff --git a/src/overlays/l11/mobys/bubble.c b/src/overlays/l11/mobys/bubble.c index cae1174420..1d19daa810 100644 --- a/src/overlays/l11/mobys/bubble.c +++ b/src/overlays/l11/mobys/bubble.c @@ -46,7 +46,8 @@ extern short bubble_horizontal_deceleration_gp __asm__("D_L11_00162408") __attri extern short bubble_surface_crossing_velocity_scale_gp __asm__("D_L11_0016240C") __attribute__((sda)); extern short bubble_spark_spawn_random_limit_gp __asm__("D_L11_00162410") __attribute__((sda)); -extern short l11_bubble_shrink_effect_randomization_scale __asm__("D_L11_00162414") __attribute__((sda)); +extern short l11_bubble_shrink_effect_randomization_scale __asm__("D_L11_00162414") + __attribute__((sda)); extern short bubble_shrink_effect_color_range_start_gp __asm__("D_L11_00162418") __attribute__((sda)); extern short bubble_shrink_effect_color_range_end_gp __asm__("D_L11_0016241C") __attribute__((sda)); @@ -101,10 +102,11 @@ void bubble_update(struct Moby *bubble_moby) { spawn_bubble_surface_effects((struct Moby *)bubble_moby, bubble_vars->unk24, 0, 1); random_vector(randomized_effect_vector, 0.0f, frame_scale_inv_macro[1]); randomized_effect_vector[2] = absolute_float(randomized_effect_vector[2]); - spawned_effect = func_L00_0026FF20_p(&bubble_moby->pos, - randomized_effect_vector, - *(float *)&l11_bubble_shrink_effect_randomization_scale, - *bubble_vars->unk24); + spawned_effect = + func_L00_0026FF20_p(&bubble_moby->pos, + randomized_effect_vector, + *(float *)&l11_bubble_shrink_effect_randomization_scale, + *bubble_vars->unk24); if (spawned_effect != 0) { *(int *)(spawned_effect + 4) = fast_tween_color(*(int *)&bubble_shrink_effect_color_range_start_gp, diff --git a/src/overlays/l11/mobys/energy_sphere.c b/src/overlays/l11/mobys/energy_sphere.c index b72d92fc57..77ba0fe935 100644 --- a/src/overlays/l11/mobys/energy_sphere.c +++ b/src/overlays/l11/mobys/energy_sphere.c @@ -229,13 +229,13 @@ void spawn_moby_radial_spark(struct Moby *source_moby) { extern float D_L11_001677C0_lui[] __asm__("D_L11_001677C0") NOT_SDA; extern int FUN_001fa6e0_q(int, int, float) __asm__("FUN_001fa6e0"); extern unsigned char *spawn_timed_hero_relative_particle(float f, - void *pos, - int a1, - unsigned char a2, - int idx, - int flag, - int s, - int mode) __asm__("FUN_L00_00272f68"); + void *pos, + int a1, + unsigned char a2, + int idx, + int flag, + int s, + int mode) __asm__("FUN_L00_00272f68"); extern short energy_sphere_particle_color_end_gp __asm__("D_L11_00162384") __attribute__((sda)); extern short energy_sphere_particle_color_start_gp __asm__("D_L11_00162380") __attribute__((sda)); @@ -261,14 +261,15 @@ void spawn_energy_sphere_particles(struct Moby *moby) { effect_byte_cursor[0] += effect_byte_cursor[4]; updated_effect_byte = truncate_float_to_s32((float)effect_byte_cursor[0]); spawn_timed_hero_relative_particle(*(float *)(energy_sphere_vars + 0x1C) * - convert_integer_to_float(effect_byte_cursor[8]) * 0.025f, - effect_position, - a, - updated_effect_byte, - 0x35, - 1, - 2, - 0); + convert_integer_to_float(effect_byte_cursor[8]) * + 0.025f, + effect_position, + a, + updated_effect_byte, + 0x35, + 1, + 2, + 0); effect_byte_cursor++; fast_vec_add(effect_position, effect_position, position_step); } diff --git a/src/overlays/l11/mobys/jet_fighter.c b/src/overlays/l11/mobys/jet_fighter.c index cd3998472d..052e0bfe63 100644 --- a/src/overlays/l11/mobys/jet_fighter.c +++ b/src/overlays/l11/mobys/jet_fighter.c @@ -774,13 +774,18 @@ extern float D_L11_0016204C __attribute__((sda)); extern float D_L11_0016207C __attribute__((sda)); extern float D_L11_00162080 __attribute__((sda)); extern float D_L11_0016208C __attribute__((sda)); -extern float l11_jet_fighter_horizontal_steering_spring_error_gain __asm__("D_L11_0016209C") __attribute__((sda)); -extern float l11_jet_fighter_horizontal_steering_spring_damping_coefficient __asm__("D_L11_001620A0") __attribute__((sda)); +extern float l11_jet_fighter_horizontal_steering_spring_error_gain __asm__("D_L11_0016209C") + __attribute__((sda)); +extern float + l11_jet_fighter_horizontal_steering_spring_damping_coefficient __asm__("D_L11_001620A0") + __attribute__((sda)); #include "rnc/overlay/l11/mobys/jet_fighter_data/update_player_ship_flight_10.h" -extern float l11_jet_fighter_vertical_steering_spring_error_gain __asm__("D_L11_001620AC") __attribute__((sda)); -extern float l11_jet_fighter_vertical_steering_spring_damping_coefficient __asm__("D_L11_001620B0") __attribute__((sda)); +extern float l11_jet_fighter_vertical_steering_spring_error_gain __asm__("D_L11_001620AC") + __attribute__((sda)); +extern float l11_jet_fighter_vertical_steering_spring_damping_coefficient __asm__("D_L11_001620B0") + __attribute__((sda)); #include "rnc/overlay/l11/mobys/jet_fighter_data/update_player_ship_flight_9.h" @@ -804,18 +809,24 @@ extern float D_L11_001620FC __attribute__((sda)); #include "rnc/overlay/l11/mobys/jet_fighter_data/update_player_ship_flight_5.h" -extern float l11_jet_fighter_camera_local_x_spring_error_gain __asm__("D_L11_00162104") __attribute__((sda)); -extern float l11_jet_fighter_camera_local_x_spring_damping_coefficient __asm__("D_L11_00162108") __attribute__((sda)); +extern float l11_jet_fighter_camera_local_x_spring_error_gain __asm__("D_L11_00162104") + __attribute__((sda)); +extern float l11_jet_fighter_camera_local_x_spring_damping_coefficient __asm__("D_L11_00162108") + __attribute__((sda)); #include "rnc/overlay/l11/mobys/jet_fighter_data/update_player_ship_flight_4.h" -extern float l11_jet_fighter_camera_local_y_spring_error_gain __asm__("D_L11_00162110") __attribute__((sda)); -extern float l11_jet_fighter_camera_local_y_spring_damping_coefficient __asm__("D_L11_00162114") __attribute__((sda)); +extern float l11_jet_fighter_camera_local_y_spring_error_gain __asm__("D_L11_00162110") + __attribute__((sda)); +extern float l11_jet_fighter_camera_local_y_spring_damping_coefficient __asm__("D_L11_00162114") + __attribute__((sda)); #include "rnc/overlay/l11/mobys/jet_fighter_data/update_player_ship_flight_3.h" -extern float l11_jet_fighter_camera_local_z_spring_error_gain __asm__("D_L11_0016211C") __attribute__((sda)); -extern float l11_jet_fighter_camera_local_z_spring_damping_coefficient __asm__("D_L11_00162120") __attribute__((sda)); +extern float l11_jet_fighter_camera_local_z_spring_error_gain __asm__("D_L11_0016211C") + __attribute__((sda)); +extern float l11_jet_fighter_camera_local_z_spring_damping_coefficient __asm__("D_L11_00162120") + __attribute__((sda)); #include "rnc/overlay/l11/mobys/jet_fighter_data/update_player_ship_flight_2.h" @@ -1259,7 +1270,9 @@ void jet_fighter_update(struct Moby *moby) { if (moby != 0) { ship_vars = (ShipVars_2838 *)moby->pvars; fast_dec_timer(&ship_vars->iDC); - if (moby->state != JET_FIGHTER_STATE_WAIT_FOR_RESPAWN && moby->state != JET_FIGHTER_STATE_WAIT_FOR_BOARDING && moby->state != JET_FIGHTER_STATE_BOARD) { + if (moby->state != JET_FIGHTER_STATE_WAIT_FOR_RESPAWN && + moby->state != JET_FIGHTER_STATE_WAIT_FOR_BOARDING && + moby->state != JET_FIGHTER_STATE_BOARD) { hit = find_moby_hit(moby, 0x30001, 0); if (hit != 0 && moby->state == JET_FIGHTER_STATE_FLIGHT) { struct Hero *g = &hero; diff --git a/src/overlays/l11/mobys/owner_linked_moby.c b/src/overlays/l11/mobys/owner_linked_moby.c index ce6910261e..e4a2a76166 100644 --- a/src/overlays/l11/mobys/owner_linked_moby.c +++ b/src/overlays/l11/mobys/owner_linked_moby.c @@ -108,11 +108,15 @@ void owner_linked_moby_update(struct Moby *moby) { LINKED_MOBY_STATE_HANDLE_HITS = 2, LINKED_MOBY_STATE_FADE_OUT = 3, LINKED_MOBY_STATE_REMOVE = 4 - } ; enum { MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE}; + }; + enum { + MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE + }; OwnerLinkedMobyVars *owner_linked_moby_vars = (OwnerLinkedMobyVars *)moby->pvars; char *health_ptr = &owner_linked_moby_vars->unk20; struct Moby *owner_moby = owner_linked_moby_vars->unk70; - if (owner_moby == 0 || owner_moby->state == MOBY_STATE_MARKED_FOR_REMOVAL || owner_moby->state == 0xFD) { + if (owner_moby == 0 || owner_moby->state == MOBY_STATE_MARKED_FOR_REMOVAL || + owner_moby->state == 0xFD) { if (moby->state < LINKED_MOBY_STATE_FADE_OUT) { moby->state = LINKED_MOBY_STATE_REMOVE; } diff --git a/src/overlays/l11/mobys/puffoid.c b/src/overlays/l11/mobys/puffoid.c index 337bf7af41..c50933d32d 100644 --- a/src/overlays/l11/mobys/puffoid.c +++ b/src/overlays/l11/mobys/puffoid.c @@ -205,7 +205,7 @@ void puffoid_update(struct Moby *moby) { case PUFFOID_STATE_WAIT_FOR_HOME_JUMP: { char *path = (char *)l11_paths[puffoid_vars->path]; float home_jump_heading = fast_arc_tan(*(float *)(path + 0x20) - moby->pos.x, - *(float *)(path + 0x24) - moby->pos.y); + *(float *)(path + 0x24) - moby->pos.y); approach_angle(&moby->rot.z, &puffoid_vars->unk250, home_jump_heading, @@ -315,7 +315,7 @@ void puffoid_update(struct Moby *moby) { if (test_path_segment_strict_crossing(puffoid_vars->unk230, &moby->pos, pos)) { float *rz = &moby->rot.z; float target_facing_heading = fast_arc_tan(puffoid_vars->target->pos.x - moby->pos.x, - puffoid_vars->target->pos.y - moby->pos.y); + puffoid_vars->target->pos.y - moby->pos.y); approach_angle(rz, &puffoid_vars->unk250, target_facing_heading, @@ -640,7 +640,10 @@ void puffoid_update(struct Moby *moby) { break; } if (puffoid_vars->smoke != 0.0f) { - if (moby->state == PUFFOID_STATE_KNOCKBACK || moby->state == PUFFOID_STATE_DEATH_KNOCKBACK || moby->state == PUFFOID_STATE_CARRIER_KNOCKBACK || moby->state == PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK) { + if (moby->state == PUFFOID_STATE_KNOCKBACK || + moby->state == PUFFOID_STATE_DEATH_KNOCKBACK || + moby->state == PUFFOID_STATE_CARRIER_KNOCKBACK || + moby->state == PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK) { for (i = 0; i < 3; i++) { float vel[4]; float a; @@ -782,8 +785,11 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { moby->scale = moby->pclass->scale * D_L11_001622CC; patrol_vars->unk1A4 = l11_puffoid_horizontal_speed_limit * frame_time; - if (patrol_vars->carrier != -1 && moby->state != PUFFOID_STATE_DEATH_KNOCKBACK && moby->state != PUFFOID_STATE_KNOCKBACK && - moby->state != PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK && moby->state != PUFFOID_STATE_CARRIER_KNOCKBACK && moby->state != PUFFOID_STATE_INITIALIZE && moby->state != PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP && + if (patrol_vars->carrier != -1 && moby->state != PUFFOID_STATE_DEATH_KNOCKBACK && + moby->state != PUFFOID_STATE_KNOCKBACK && + moby->state != PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK && + moby->state != PUFFOID_STATE_CARRIER_KNOCKBACK && moby->state != PUFFOID_STATE_INITIALIZE && + moby->state != PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP && moby->state != PUFFOID_STATE_CARRIER_JUMP) { if (moby->pos.z < ((struct Moby *)D_L11_0015FFD8)[patrol_vars->carrier].pos.z + 0.5f) { spawn_color_swapped_explosion_burst(moby, &moby->pos, -1, 0.5f, 10.0f); @@ -807,7 +813,8 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { { s32 kind = resolve_moby_hit_response( moby, hit, &patrol_vars->hp, 0, &hit_processing_status, &dmg, 0, 4); - if (hit_processing_status != HIT_PROCESSING_SKIP_DAMAGE_AND_REACTION && moby->state != PUFFOID_STATE_DEATH_KNOCKBACK) { + if (hit_processing_status != HIT_PROCESSING_SKIP_DAMAGE_AND_REACTION && + moby->state != PUFFOID_STATE_DEATH_KNOCKBACK) { patrol_vars->hp -= dmg; if (hit->moby->oclass == 0x47) { kind = HIT_RESPONSE_KNOCKBACK; @@ -884,7 +891,8 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { moby->hit_slot = 0xFF; trooper_anim_finish(moby, patrol_vars->move); if (patrol_vars->timer != 0) { - if (moby->state == PUFFOID_STATE_IDLE || (moby->state == PUFFOID_STATE_WANDER_NEAR_HOME && (moby->anim_flags & 2))) { + if (moby->state == PUFFOID_STATE_IDLE || + (moby->state == PUFFOID_STATE_WANDER_NEAR_HOME && (moby->anim_flags & 2))) { moby->state = PUFFOID_STATE_REPOSITION_AND_FACE_TARGET; if (moby->prev_seq != 2) { FUN_00212f90(moby, 2, 0, scale_game_frames(10)); @@ -1002,7 +1010,10 @@ s32 is_moby_in_bob_target_exclusion_state(const u8 *moby) { PUFFOID_STATE_WAIT_TO_RESUME_COMMAND = 0x14 }; u32 moby_state = moby[0x20]; - if (moby_state == PUFFOID_STATE_WAIT_TO_RESUME_COMMAND || moby_state == PUFFOID_STATE_DEATH_KNOCKBACK || moby_state == PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK || moby_state == PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP) { + if (moby_state == PUFFOID_STATE_WAIT_TO_RESUME_COMMAND || + moby_state == PUFFOID_STATE_DEATH_KNOCKBACK || + moby_state == PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK || + moby_state == PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP) { return 1; } return 0; @@ -1026,8 +1037,11 @@ int process_puffoid_suck_cannon_suction(struct Moby *moby) { }; int grab_check_result = process_moby_suck_cannon_suction(moby); if (grab_check_result != 0) { - if (moby->state == PUFFOID_STATE_IDLE || moby->state == PUFFOID_STATE_CHASE_TARGET || moby->state == PUFFOID_STATE_SPRAY_ATTACK || moby->state == PUFFOID_STATE_RETURN_HOME || - moby->state == PUFFOID_STATE_CARRIER_IDLE || moby->state == PUFFOID_STATE_CARRIER_CHASE_TARGET || moby->state == PUFFOID_STATE_CARRIER_SPRAY_ATTACK || + if (moby->state == PUFFOID_STATE_IDLE || moby->state == PUFFOID_STATE_CHASE_TARGET || + moby->state == PUFFOID_STATE_SPRAY_ATTACK || moby->state == PUFFOID_STATE_RETURN_HOME || + moby->state == PUFFOID_STATE_CARRIER_IDLE || + moby->state == PUFFOID_STATE_CARRIER_CHASE_TARGET || + moby->state == PUFFOID_STATE_CARRIER_SPRAY_ATTACK || moby->state == PUFFOID_STATE_WAIT_TO_RESUME_COMMAND) { if (moby->state != PUFFOID_STATE_WAIT_TO_RESUME_COMMAND) { moby->command = moby->state; diff --git a/src/overlays/l11/mobys/resort_owner.c b/src/overlays/l11/mobys/resort_owner.c index a2be0ce275..7a1693084a 100644 --- a/src/overlays/l11/mobys/resort_owner.c +++ b/src/overlays/l11/mobys/resort_owner.c @@ -92,7 +92,11 @@ typedef struct ResortOwnerVars { } ResortOwnerVars; void trigger_pokitaru_paired_rotation(struct Moby *moby) { - enum { POKITARU_PAIRED_ROTATION_WAITING = 1 , POKITARU_PAIRED_ROTATION_ROTATING = 2 } ;ResortOwnerVars *state = (ResortOwnerVars *)moby->pvars; + enum { + POKITARU_PAIRED_ROTATION_WAITING = 1, + POKITARU_PAIRED_ROTATION_ROTATING = 2 + }; + ResortOwnerVars *state = (ResortOwnerVars *)moby->pvars; if (moby->oclass == 0x41 && moby->state == POKITARU_PAIRED_ROTATION_WAITING) { char *child; D_0013D3E2[0] = moby->state; @@ -365,7 +369,8 @@ void update_resort_owner_state_transitions(void *resort_owner_moby) { float position_scratch[4]; float dialogue_rotation[4]; - if (moby->state >= RESORT_OWNER_WAIT_TO_FOLLOW_HERO && moby->state <= RESORT_OWNER_FOLLOW_DISTANT_HERO && proximity == 0) { + if (moby->state >= RESORT_OWNER_WAIT_TO_FOLLOW_HERO && + moby->state <= RESORT_OWNER_FOLLOW_DISTANT_HERO && proximity == 0) { FUN_L11_002d2088_c(moby, 6); return; } diff --git a/src/overlays/l11/mobys/teleporter.c b/src/overlays/l11/mobys/teleporter.c index a644ea099d..f64717a4e6 100644 --- a/src/overlays/l11/mobys/teleporter.c +++ b/src/overlays/l11/mobys/teleporter.c @@ -71,7 +71,10 @@ void teleporter_update(struct Moby *moby) { TELEPORTER_OPEN_PARTS = 2, TELEPORTER_CONTRACT_RING = 3, TELEPORTER_RESET = 4 - } ; enum { HERO_TARGET_POSE_INACTIVE = 0}; + }; + enum { + HERO_TARGET_POSE_INACTIVE = 0 + }; TeleporterVars *teleporter_instance_vars = (TeleporterVars *)moby->pvars; switch (moby->state) { diff --git a/src/overlays/l12/hero/hero_set_state.c b/src/overlays/l12/hero/hero_set_state.c index a617285de8..154ecb7be9 100644 --- a/src/overlays/l12/hero/hero_set_state.c +++ b/src/overlays/l12/hero/hero_set_state.c @@ -72,7 +72,8 @@ int hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L12_0015F5C4 == 2 || D_L12_0015F5C4 == 6) && b != 2) @@ -80,8 +81,16 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -973,7 +982,8 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; diff --git a/src/overlays/l12/hero/update_hero_motion_for_current_state.c b/src/overlays/l12/hero/update_hero_motion_for_current_state.c index 3cfcb53b19..600d2a7a26 100644 --- a/src/overlays/l12/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l12/hero/update_hero_motion_for_current_state.c @@ -318,7 +318,8 @@ void update_hero_ground_contact_and_gravity(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || + if (hero.ground_slope.f <= 0.87266463f || + hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = D_L12_001742C0_lui.moby; @@ -1886,7 +1887,8 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { diff --git a/src/overlays/l12/hero/update_hero_state_transitions.c b/src/overlays/l12/hero/update_hero_state_transitions.c index de2fa75773..384550da16 100644 --- a/src/overlays/l12/hero/update_hero_state_transitions.c +++ b/src/overlays/l12/hero/update_hero_state_transitions.c @@ -157,8 +157,10 @@ void update_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && item_selector_hud_activation_blocked == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; @@ -972,7 +974,8 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; diff --git a/src/overlays/l12/level_class_tables.c b/src/overlays/l12/level_class_tables.c index dd9a8d1999..78e256f817 100644 --- a/src/overlays/l12/level_class_tables.c +++ b/src/overlays/l12/level_class_tables.c @@ -19,7 +19,9 @@ #include "rnc/overlay/shared/ui/hud/hud_keep_visible.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" -s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" diff --git a/src/overlays/l12/mobys/blarg_helicopter.c b/src/overlays/l12/mobys/blarg_helicopter.c index 5332670ec4..c6e2a996b8 100644 --- a/src/overlays/l12/mobys/blarg_helicopter.c +++ b/src/overlays/l12/mobys/blarg_helicopter.c @@ -527,8 +527,8 @@ void blarg_helicopter_update(struct Moby *moby) { (*(struct Moby **)(&blarg_helicopter_vars->unkAC))->flags |= 6; } } - if (blarg_helicopter_vars->unkC0 == 0 && moby->state > BLARG_HELICOPTER_WAIT_FOR_ACTIVATION && moby->visible && - fast_vec_dist(&moby->pos, D_L12_00167240) < 30.0f) { + if (blarg_helicopter_vars->unkC0 == 0 && moby->state > BLARG_HELICOPTER_WAIT_FOR_ACTIVATION && + moby->visible && fast_vec_dist(&moby->pos, D_L12_00167240) < 30.0f) { FUN_L00_0025a120((char *)moby); moby->shadow_range = 24; } @@ -634,7 +634,14 @@ extern void trooper_anim_update(void *m, short *p) __asm__("FUN_L00_0025d458"); extern void trooper_anim_finish(void *, void *) __asm__("FUN_L00_0025d538"); void process_blarg_helicopter_hits(struct Moby *moby) { - enum { BLARG_HELICOPTER_KNOCKBACK = 5 , BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET = 6 } ; enum { HIT_PROCESSING_SKIP_HIT = 1} ;int hit_processing_status; + enum { + BLARG_HELICOPTER_KNOCKBACK = 5, + BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET = 6 + }; + enum { + HIT_PROCESSING_SKIP_HIT = 1 + }; + int hit_processing_status; float fv; int hit_reaction_code; BlargHelicopterVars *blarg_helicopter_hit_vars; @@ -645,7 +652,8 @@ void process_blarg_helicopter_hits(struct Moby *moby) { hit_record = find_moby_hit(moby, 0x330000, 0); hit_reaction_code = hit_reaction( moby, hit_record, &blarg_helicopter_hit_vars->health, 0, &hit_processing_status, &fv, 0, 4); - if (hit_processing_status != HIT_PROCESSING_SKIP_HIT && moby->state != BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET && + if (hit_processing_status != HIT_PROCESSING_SKIP_HIT && + moby->state != BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET && *(short *)(*(char **)(hit_record + 0x20) + 0xA6) != 0xB8 && *(short *)(*(char **)(hit_record + 0x20) + 0xA6) != 0x199) { float remaining_health; @@ -659,7 +667,8 @@ void process_blarg_helicopter_hits(struct Moby *moby) { } else if (hit_reaction_code != 0xB) { blarg_helicopter_hit_vars->unk67 = 0xB4; trooper_anim_update(moby, (short *)&blarg_helicopter_hit_vars->anim_state); - if (*(float *)(hit_record + 0x1C) == 5627.925f && moby->state != BLARG_HELICOPTER_KNOCKBACK) { + if (*(float *)(hit_record + 0x1C) == 5627.925f && + moby->state != BLARG_HELICOPTER_KNOCKBACK) { hit_to_moby_angle = fast_arc_tan(moby->pos.x - *(float *)(hit_record + 0), moby->pos.y - *(float *)(hit_record + 4)); hit_yaw_offset = fast_subtract_rotations(hit_to_moby_angle, moby->rot.z); diff --git a/src/overlays/l12/mobys/blarg_trooper.c b/src/overlays/l12/mobys/blarg_trooper.c index 1746f2153b..99f359d4f7 100644 --- a/src/overlays/l12/mobys/blarg_trooper.c +++ b/src/overlays/l12/mobys/blarg_trooper.c @@ -592,7 +592,8 @@ void process_blarg_trooper_damage_and_alerts(struct Moby *moby) { ? trooper_damage_alert_vars->alert_speed : 20.0f; } - if (trooper_damage_alert_vars->call_enabled != 0 && moby->state != BLARG_TROOPER_WAIT_FOR_ACTIVATION) { + if (trooper_damage_alert_vars->call_enabled != 0 && + moby->state != BLARG_TROOPER_WAIT_FOR_ACTIVATION) { trooper_damage_alert_vars->call_timer++; if (scale_game_frames(0x3C) * 17 < trooper_damage_alert_vars->call_timer) { s32 count = 0; diff --git a/src/overlays/l12/mobys/homing_mine_spawner.c b/src/overlays/l12/mobys/homing_mine_spawner.c index d6d2e9b56a..b0a46b4e08 100644 --- a/src/overlays/l12/mobys/homing_mine_spawner.c +++ b/src/overlays/l12/mobys/homing_mine_spawner.c @@ -173,7 +173,10 @@ extern char D_0013E533[]; extern int select_moby_combat_target(char *, char *, float) __asm__("FUN_L00_0025fcb8"); void update_homing_mine_spawner_target(struct Moby *spawner) { - enum { HOMING_MINE_SPAWNER_CLEAR_LINKED_MOBYS = 0 } ;HomingMineSpawnerVars *spawner_data = (HomingMineSpawnerVars *)spawner->pvars; + enum { + HOMING_MINE_SPAWNER_CLEAR_LINKED_MOBYS = 0 + }; + HomingMineSpawnerVars *spawner_data = (HomingMineSpawnerVars *)spawner->pvars; char *pad; if (spawner->state != HOMING_MINE_SPAWNER_CLEAR_LINKED_MOBYS) { if (spawner_data->unk38 != 0) { diff --git a/src/overlays/l12/mobys/hoven_anklebiter.c b/src/overlays/l12/mobys/hoven_anklebiter.c index 83cd837e99..f8a1bf4595 100644 --- a/src/overlays/l12/mobys/hoven_anklebiter.c +++ b/src/overlays/l12/mobys/hoven_anklebiter.c @@ -39,7 +39,8 @@ int process_hoven_anklebiter_suck_cannon_suction(struct Moby *moby) { ANKLEBITER_ACTIVATE_FROM_DORMANCY = 13 }; int active; - if (moby->state == ANKLEBITER_DORMANT || moby->state == ANKLEBITER_WAIT_FOR_LEAP_TRIGGER || moby->state == ANKLEBITER_ACTIVATE_FROM_DORMANCY) + if (moby->state == ANKLEBITER_DORMANT || moby->state == ANKLEBITER_WAIT_FOR_LEAP_TRIGGER || + moby->state == ANKLEBITER_ACTIVATE_FROM_DORMANCY) return 0; active = process_moby_suck_cannon_suction(moby); if (active) { @@ -679,7 +680,8 @@ void hoven_anklebiter_update(AnklebiterMoby *moby) { return; } } - if (moby->enabled && moby->state != ANKLEBITER_DORMANT && moby->state != ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME) { + if (moby->enabled && moby->state != ANKLEBITER_DORMANT && + moby->state != ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME) { func_L00_00263950_2E2EF0( (char *)moby, data->collision_data, 0, D_0015ED64 * 0.018f, D_0015ED64 * 0.3f); if (moby->enabled && fast_vec_dist(moby->pos, D_L12_00167240) < 28.0f) { @@ -736,14 +738,21 @@ int move_hoven_anklebiter_toward_heading(struct Moby *moby, float speed) { int D_L12_0016183C = 0xa; int D_L12_00161840 = 8; -extern float l12_anklebiter_spark_burst_origin_jitter __asm__("D_L12_00161844") __attribute__((sda)); +extern float l12_anklebiter_spark_burst_origin_jitter __asm__("D_L12_00161844") + __attribute__((sda)); extern float l12_anklebiter_spark_position_jitter __asm__("D_L12_00161848") __attribute__((sda)); -extern float l12_anklebiter_spark_velocity_jitter_scale __asm__("D_L12_0016184C") __attribute__((sda)); -extern float l12_anklebiter_spark_horizontal_speed_range_start __asm__("D_L12_00161850") __attribute__((sda)); -extern float l12_anklebiter_spark_horizontal_speed_range_end __asm__("D_L12_00161854") __attribute__((sda)); -extern float l12_anklebiter_spark_vertical_speed_range_start __asm__("D_L12_00161858") __attribute__((sda)); -extern float l12_anklebiter_spark_vertical_speed_range_end __asm__("D_L12_0016185C") __attribute__((sda)); -extern float l12_anklebiter_spark_downward_velocity_scale __asm__("D_L12_00161860") __attribute__((sda)); +extern float l12_anklebiter_spark_velocity_jitter_scale __asm__("D_L12_0016184C") + __attribute__((sda)); +extern float l12_anklebiter_spark_horizontal_speed_range_start __asm__("D_L12_00161850") + __attribute__((sda)); +extern float l12_anklebiter_spark_horizontal_speed_range_end __asm__("D_L12_00161854") + __attribute__((sda)); +extern float l12_anklebiter_spark_vertical_speed_range_start __asm__("D_L12_00161858") + __attribute__((sda)); +extern float l12_anklebiter_spark_vertical_speed_range_end __asm__("D_L12_0016185C") + __attribute__((sda)); +extern float l12_anklebiter_spark_downward_velocity_scale __asm__("D_L12_00161860") + __attribute__((sda)); extern float D_L12_00161864 __attribute__((sda)); extern float D_L12_00161868 __attribute__((sda)); int D_L12_0016186C = 0x8000eeee; @@ -795,8 +804,10 @@ void spawn_hoven_anklebiter_death_sparks(struct Moby *moby) { add_random_offset_to_vector_xyz(pos_ptr, l12_anklebiter_spark_burst_origin_jitter); pos[2] += 0.55f; angle = random_angle_radians(); - speed = random_float_between(l12_anklebiter_spark_horizontal_speed_range_start, l12_anklebiter_spark_horizontal_speed_range_end); - rise = random_float_between(l12_anklebiter_spark_vertical_speed_range_start, l12_anklebiter_spark_vertical_speed_range_end); + speed = random_float_between(l12_anklebiter_spark_horizontal_speed_range_start, + l12_anklebiter_spark_horizontal_speed_range_end); + rise = random_float_between(l12_anklebiter_spark_vertical_speed_range_start, + l12_anklebiter_spark_vertical_speed_range_end); if (moby->state == ANKLEBITER_DEATH_EFFECTS_AND_REMOVE) { speed *= 0.55f; rise *= 0.55f; @@ -809,13 +820,16 @@ void spawn_hoven_anklebiter_death_sparks(struct Moby *moby) { push[2] = 0.0f; fast_vec_add(spark_launch_velocity, spark_launch_velocity, push); qcopy(gravity_adjusted_spark_velocity, spark_launch_velocity); - gravity_adjusted_spark_velocity[2] -= l12_anklebiter_spark_downward_velocity_scale * D_0015ED70 * (float)scale_game_frames(D_L12_00161880); + gravity_adjusted_spark_velocity[2] -= l12_anklebiter_spark_downward_velocity_scale * + D_0015ED70 * (float)scale_game_frames(D_L12_00161880); for (j = 0; j < D_L12_00161840; j++) { size = random_float_between(0.5f, 1.5f); spark_launch_velocity[3] = size * D_L12_00161864; gravity_adjusted_spark_velocity[3] = size * D_L12_00161868; add_random_offset_to_vector_xyz(pos, l12_anklebiter_spark_position_jitter); - add_random_offset_to_vector_xyz(gravity_adjusted_spark_velocity, l12_anklebiter_spark_velocity_jitter_scale * D_0015ED6C); + add_random_offset_to_vector_xyz(gravity_adjusted_spark_velocity, + l12_anklebiter_spark_velocity_jitter_scale * + D_0015ED6C); start_color = fast_tween_color(D_L12_0016186C, D_L12_00161874, random_float_between(0.0f, 1.0f)); end_color = @@ -919,7 +933,8 @@ void process_hoven_anklebiter_damage_and_alerts(struct Moby *moby) { anklebiter_vars->reset_alert = 0; anklebiter_vars->alert_timer = scale_game_frames(0xF0); } - if (moby->state != ANKLEBITER_DORMANT && moby->state != ANKLEBITER_WAIT_FOR_LEAP_TRIGGER && moby->state != ANKLEBITER_INITIALIZE) { + if (moby->state != ANKLEBITER_DORMANT && moby->state != ANKLEBITER_WAIT_FOR_LEAP_TRIGGER && + moby->state != ANKLEBITER_INITIALIZE) { if (fast_dec_timer(&anklebiter_vars->alert_timer)) { anklebiter_vars->speed = 12.0f; } else { @@ -943,7 +958,8 @@ void process_hoven_anklebiter_damage_and_alerts(struct Moby *moby) { coll = find_hit_e3528(moby, 0x330000, 0); dmg = 0.0f; resolve_moby_hit_response(moby, coll, &anklebiter_vars->health, 0, &hit, &dmg, 0, 4); - if (coll != 0 && moby->state != ANKLEBITER_DEATH_FALL && moby->state != ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME) { + if (coll != 0 && moby->state != ANKLEBITER_DEATH_FALL && + moby->state != ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME) { if (moby->group != 0xFF) { FUN_L01_0026e090(moby->group, 7); } diff --git a/src/overlays/l12/mobys/hoven_turret.c b/src/overlays/l12/mobys/hoven_turret.c index 55f3ffae8a..9e6ed614c5 100644 --- a/src/overlays/l12/mobys/hoven_turret.c +++ b/src/overlays/l12/mobys/hoven_turret.c @@ -159,32 +159,32 @@ extern int D_L12_00161F20 MACRO_ADDR; extern int D_L12_00161F24 MACRO_ADDR; extern int random_int_between(int, int) __asm__("FUN_L00_00257b90"); extern int hero_set_state(int, int) __asm__("FUN_L12_002400d0"); -extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); -extern void hero_respawn(void) __asm__("FUN_L00_00211250"); -extern void set_race_camera(void *, void *, int, int) __asm__("FUN_L00_00216f90"); -extern void moby_point_position(void *, int, void *) __asm__("FUN_L00_0024f7c8"); -extern void jet_clear_persistent(int) __asm__("FUN_L00_002502a0"); -extern void spawn_explosion(void *, - void *, - void *, - float, - float, - int, - int, - int, - float, - float, - float, - int, - float, - float, - int, - int, - int, - int) __asm__("FUN_L00_0025e450"); -extern void FUN_L00_00262cf0(void *, void *, float, float, float); -extern void start_scene(int) __asm__("FUN_L00_00298840"); -extern void queue_scene_movie_with_game_language(int) __asm__("FUN_L00_00299460"); +extern void build_axis_rotation_quaternion(void *, int, float) __asm__("FUN_L00_001fff28"); +extern void hero_respawn(void) __asm__("FUN_L00_00211250"); +extern void set_race_camera(void *, void *, int, int) __asm__("FUN_L00_00216f90"); +extern void moby_point_position(void *, int, void *) __asm__("FUN_L00_0024f7c8"); +extern void jet_clear_persistent(int) __asm__("FUN_L00_002502a0"); +extern void spawn_explosion(void *, + void *, + void *, + float, + float, + int, + int, + int, + float, + float, + float, + int, + float, + float, + int, + int, + int, + int) __asm__("FUN_L00_0025e450"); +extern void FUN_L00_00262cf0(void *, void *, float, float, float); +extern void start_scene(int) __asm__("FUN_L00_00298840"); +extern void queue_scene_movie_with_game_language(int) __asm__("FUN_L00_00299460"); extern void spawn_turret_rocket(void *, void *, void *, int) __asm__("FUN_L08_002e7eb0"); extern void update_hoven_turret_target_alignment_timer(void *) __asm__("FUN_L12_00303370"); extern void draw_hoven_turret_hud() __asm__("FUN_L12_00304218"); diff --git a/src/overlays/l12/mobys/planetbuster_maximus_part.c b/src/overlays/l12/mobys/planetbuster_maximus_part.c index 74379cc46f..28f8ba4d16 100644 --- a/src/overlays/l12/mobys/planetbuster_maximus_part.c +++ b/src/overlays/l12/mobys/planetbuster_maximus_part.c @@ -63,10 +63,11 @@ extern float spring_angle(void *, float, void *, int, float, float, float) __asm__("FUN_L00_0025bc98"); extern int D_L12_00161F20 MACRO_ADDR; extern int D_L12_00161F24 MACRO_ADDR; -extern int l12_planetbuster_maximus_proximity_fire_counter __asm__("D_L12_00161F34") __attribute__((sda)); -extern int planetbuster_maximus_gun_part_slots[] __asm__("D_L12_001FB670"); -extern int D_L12_001FB688[]; -extern int FUN_L00_001fefc8(void *); +extern int l12_planetbuster_maximus_proximity_fire_counter __asm__("D_L12_00161F34") + __attribute__((sda)); +extern int planetbuster_maximus_gun_part_slots[] __asm__("D_L12_001FB670"); +extern int D_L12_001FB688[]; +extern int FUN_L00_001fefc8(void *); extern void * spawn_blarg_trooper_projectile(void *, void *, void *, int) __asm__("FUN_L04_002aee30"); extern void spawn_effect(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); diff --git a/src/overlays/l13/level_class_tables.c b/src/overlays/l13/level_class_tables.c index 9cc3df6b4a..e7c1c63663 100644 --- a/src/overlays/l13/level_class_tables.c +++ b/src/overlays/l13/level_class_tables.c @@ -383,7 +383,7 @@ struct CameraType level_camera_types[8] __asm__("D_L13_001F6200") __attribute__( update_target_tracking_camera, conditionally_set_camera_state_three }, {19, evaluate_descriptor_eligibility, initialize_path_camera, - update_path_flythrough_camera, noop_main_callback }, + update_path_flythrough_camera, noop_main_callback }, {23, volume_camera_check, noop_main_callback, noop_main_callback, noop_main_callback}, {-1, 0, 0, 0, 0}, }; diff --git a/src/overlays/l13/mobys/attached_rocket.c b/src/overlays/l13/mobys/attached_rocket.c index 89922a3513..85a31c5df0 100644 --- a/src/overlays/l13/mobys/attached_rocket.c +++ b/src/overlays/l13/mobys/attached_rocket.c @@ -64,7 +64,10 @@ void launch_attached_rocket(struct Moby *moby, int distance_reference_moby, float max_travel_distance) { - enum { ATTACHED_ROCKET_STATE_FLIGHT = 0 } ;AttachedRocketVars *moby_vars = (AttachedRocketVars *)moby->pvars; + enum { + ATTACHED_ROCKET_STATE_FLIGHT = 0 + }; + AttachedRocketVars *moby_vars = (AttachedRocketVars *)moby->pvars; char *source_moby = (char *)moby_vars->unk20; char *mp; moby_vars->unk28 = max_travel_distance; @@ -113,7 +116,14 @@ void spawn_attached_rocket_explosion(struct Moby *moby) __asm__("FUN_L13_003060b /* Moby class 1233 */ void attached_rocket_update(struct Moby *moby) { - enum { ATTACHED_ROCKET_STATE_ATTACHED = 1 } ; enum { MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xfd , MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xfe} ;AttachedRocketVars *attached_rocket_vars = (AttachedRocketVars *)moby->pvars; + enum { + ATTACHED_ROCKET_STATE_ATTACHED = 1 + }; + enum { + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xfd, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xfe + }; + AttachedRocketVars *attached_rocket_vars = (AttachedRocketVars *)moby->pvars; struct Moby *source; struct Moby *target; struct { @@ -132,7 +142,9 @@ void attached_rocket_update(struct Moby *moby) { qcopy(&work.old_pos, &moby->pos); if (moby->state == ATTACHED_ROCKET_STATE_ATTACHED) { source = attached_rocket_vars->unk20; - if (source == 0 || source->oclass != 0x65 || source->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || source->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) + if (source == 0 || source->oclass != 0x65 || + source->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || + source->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) goto remove; qcopy(&moby->rot, &source->rot); *(OvlQuad *)&moby->rot_row0 = *(OvlQuad *)&source->rot_row0; @@ -142,8 +154,8 @@ void attached_rocket_update(struct Moby *moby) { qcopy(&attached_rocket_vars->unk10, &moby->pos); { struct Moby *source = attached_rocket_vars->unk20; - if (source != 0 && source->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && source->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && - (source->flags & 1)) + if (source != 0 && source->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + source->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && (source->flags & 1)) moby->flags |= 1; else moby->flags &= 0xfffe; diff --git a/src/overlays/l13/mobys/blarg_space_fighter.c b/src/overlays/l13/mobys/blarg_space_fighter.c index ee35afd835..93b00aa68e 100644 --- a/src/overlays/l13/mobys/blarg_space_fighter.c +++ b/src/overlays/l13/mobys/blarg_space_fighter.c @@ -604,7 +604,8 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { Moby_2C56B0 *p; if (fighter_data->fBC == -1 || (p = (Moby_2C56B0 *)(D_L13_0015FFD8 + (fighter_data->fBC << 8))) == 0 || - p->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || p->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END || p->bBC == 4) { + p->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || + p->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END || p->bBC == 4) { fast_vec_normalize(scratch_vector, D_L13_001670C0 + 0x84, 40.0f); fast_vec_sub(scratch_vector, D_L13_001670C0, scratch_vector); fighter_data->hB6 = fighter_data->hB4 = @@ -625,7 +626,8 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { FUN_L13_002c37e0_c( (unsigned char *)moby, (unsigned char *)fighter_data, &fighter_data->f20); - if (veh != 0 && veh->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && veh->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { + if (veh != 0 && veh->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + veh->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { vehd = veh->data; qcopy(hpos, &((Hero_2C56B0 *)(((char *)&D_0013F350)))->veh->pos); close = 0; @@ -648,12 +650,14 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { bossd = 0; if (fighter_data->fBC != -1) { Moby_2C56B0 *p = (Moby_2C56B0 *)(D_L13_0015FFD8 + (fighter_data->fBC << 8)); - if (p != 0 && p->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && p->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { + if (p != 0 && p->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + p->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { boss = p; bossd = p->data; } } - if (boss == 0 || boss->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || boss->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END || boss->state == 1) { + if (boss == 0 || boss->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || + boss->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END || boss->state == 1) { moby->state = FIGHTER_WAIT_TO_REINITIALIZE; moby->f94 = 0; moby->flags = (moby->flags | 0x41) & 0xEFFF; @@ -812,7 +816,8 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { bossd = 0; if (fighter_data->fBC != -1) { Moby_2C56B0 *p = (Moby_2C56B0 *)(D_L13_0015FFD8 + (fighter_data->fBC << 8)); - if (p != 0 && p->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && p->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { + if (p != 0 && p->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + p->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { boss = p; bossd = p->data; } @@ -831,7 +836,8 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) { Moby_2C56B0 *p; if (fighter_data->fBC != -1 && (p = (Moby_2C56B0 *)(D_L13_0015FFD8 + (fighter_data->fBC << 8))) != 0 && - p->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && p->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && p->bBC != 4) { + p->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + p->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && p->bBC != 4) { fighter_data->f20 = fighter_data->h24; moby->state = FIGHTER_INITIALIZE; } diff --git a/src/overlays/l13/mobys/elevator.c b/src/overlays/l13/mobys/elevator.c index e0b5529fb6..f826049821 100644 --- a/src/overlays/l13/mobys/elevator.c +++ b/src/overlays/l13/mobys/elevator.c @@ -241,7 +241,8 @@ void compute_elevator_camera_pose(struct Moby *moby, float horizontal_offset_radius = 2.5f; float z = 1.5f; unsigned char *x; - if ((moby->command >= 2 && (moby->command & 1)) || (moby->state >= ELEVATOR_STATE_MOVE_TO_TOP && (moby->state & 1))) { + if ((moby->command >= 2 && (moby->command & 1)) || + (moby->state >= ELEVATOR_STATE_MOVE_TO_TOP && (moby->state & 1))) { camera_offset_azimuth = fast_subtract_rotations(camera_offset_azimuth, 1.5707964f); } else { camera_offset_azimuth = fast_add_rotations(camera_offset_azimuth, 1.5707964f); diff --git a/src/overlays/l13/mobys/fighter_jet.c b/src/overlays/l13/mobys/fighter_jet.c index 52625e478e..9efd2a9ee9 100644 --- a/src/overlays/l13/mobys/fighter_jet.c +++ b/src/overlays/l13/mobys/fighter_jet.c @@ -1786,7 +1786,8 @@ void fighter_jet_update(Jet *jet_moby) { jet_data->hit_class = 0; fast_dec_timer((int *)&jet_data->timer); initial_state = jet_moby->state; - if ((unsigned int)(initial_state - 6) >= 2 && (unsigned char)initial_state != FIGHTER_JET_STATE_WAIT_FOR_ENTRY && + if ((unsigned int)(initial_state - 6) >= 2 && + (unsigned char)initial_state != FIGHTER_JET_STATE_WAIT_FOR_ENTRY && (unsigned char)initial_state != FIGHTER_JET_STATE_MOUNT_PLAYER) { JetHit *hit = (JetHit *)find_moby_hit(jet_moby, 0x30001, 0); if (hit && jet_moby->state == FIGHTER_JET_STATE_FLIGHT) { diff --git a/src/overlays/l13/mobys/gemlik_scene_controller.c b/src/overlays/l13/mobys/gemlik_scene_controller.c index 7a97c1ace7..f3e7bf47c6 100644 --- a/src/overlays/l13/mobys/gemlik_scene_controller.c +++ b/src/overlays/l13/mobys/gemlik_scene_controller.c @@ -148,7 +148,8 @@ void gemlik_scene_controller_update(struct Moby *moby) { break; } other = (struct Moby *)(moby_base + scene_controller_vars[5] * 0x100); - if (other != 0 && other->oclass == 0x184 && other->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + if (other != 0 && other->oclass == 0x184 && + other->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && other->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) return; if (scene_controller_vars[4] != -1) { @@ -206,7 +207,9 @@ void gemlik_scene_controller_update(struct Moby *moby) { case WAIT_LINKED_MOBY_REMOVAL_BEFORE_SAVE: { if (scene_controller_vars[4] != -1) { struct Moby *other = (struct Moby *)(moby_base + scene_controller_vars[4] * 0x100); - if (other != 0 && other->oclass == 0x45 && other->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && other->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) + if (other != 0 && other->oclass == 0x45 && + other->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + other->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) return; memcard_save_data(0, -1); moby->state = ENTER_LINKED_MOBY_CLEANUP_WAIT; diff --git a/src/overlays/l13/mobys/hovering_rocket_attacker.c b/src/overlays/l13/mobys/hovering_rocket_attacker.c index 7a05f3a7dc..91d72c746e 100644 --- a/src/overlays/l13/mobys/hovering_rocket_attacker.c +++ b/src/overlays/l13/mobys/hovering_rocket_attacker.c @@ -382,7 +382,10 @@ void update_hovering_rocket_attacker_common(unsigned char *moby) { HIT_REACTION_HIGH_INTERPOLATION_TARGET = 9, HIT_REACTION_HIGH_INTERPOLATION_TARGET_ALTERNATE = 10, HIT_REACTION_NO_HIT = 11 - } ; enum { TARGET_SELECTION_NO_TARGET = 2}; + }; + enum { + TARGET_SELECTION_NO_TARGET = 2 + }; HoveringRocketAttackerVars *moby_data; char *hit_record; int hit_reaction_code; diff --git a/src/overlays/l13/mobys/lift.c b/src/overlays/l13/mobys/lift.c index a4266f33ae..f3f9148234 100644 --- a/src/overlays/l13/mobys/lift.c +++ b/src/overlays/l13/mobys/lift.c @@ -214,7 +214,8 @@ void compute_lift_mount_transform(struct Moby *moby, float *mount_position, floa char *mount_facing_target_base; clear_u64_value(mount_rotation); k = 2.25f; - if ((moby->command >= 2 && (moby->command & 1)) || (moby->state >= LIFT_MOVE_TO_TOP && (moby->state & 1))) { + if ((moby->command >= 2 && (moby->command & 1)) || + (moby->state >= LIFT_MOVE_TO_TOP && (moby->state & 1))) { mount_offset_angle = -1.5707964f; mount_rotation[0] = moby->rot.y; } else { diff --git a/src/overlays/l13/mobys/mine.c b/src/overlays/l13/mobys/mine.c index 8f12fa4662..de8a86b5c3 100644 --- a/src/overlays/l13/mobys/mine.c +++ b/src/overlays/l13/mobys/mine.c @@ -90,7 +90,11 @@ void level_13_mine_update(ProjectileMoby *moby) __asm__("FUN_L13_002c2048"); /* Moby class 83 */ void level_13_mine_update(ProjectileMoby *moby) { - enum { MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD , MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE } ;char *moby_data = (char *)moby->data; + enum { + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE + }; + char *moby_data = (char *)moby->data; ProjectileVec4 steering_and_collision_vector; float hitpos[12]; ProjectileVec4 *pos; @@ -139,7 +143,8 @@ void level_13_mine_update(ProjectileMoby *moby) { return; } target = *(ProjectileMoby **)(moby_data + 0x74); - if (target != 0 && target->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && target->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && + if (target != 0 && target->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + target->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && fast_vec_dist(pos, &target->pos) > 8.0f) { make_hit_descriptor(16.0f, &hitpos, moby, 0x30000, velocity); qcopy(&steering_and_collision_vector, pos); diff --git a/src/overlays/l13/mobys/moby_path_follower.c b/src/overlays/l13/mobys/moby_path_follower.c index f45591cb3c..68fa204847 100644 --- a/src/overlays/l13/mobys/moby_path_follower.c +++ b/src/overlays/l13/mobys/moby_path_follower.c @@ -17,7 +17,13 @@ void moby_path_follower_update(struct Moby *moby) __asm__("FUN_L13_0030bb70"); /* Moby class 1403 */ void moby_path_follower_update(struct Moby *moby) { - enum { PATH_FOLLOWER_STATE_INITIALIZE = 0 , PATH_FOLLOWER_STATE_PROJECT_TARGET_ONTO_PATH = 1 , PATH_FOLLOWER_STATE_ADVANCE_ALONG_PATH = 2 , PATH_FOLLOWER_STATE_PATH_END_REACHED = 3 } ;int *moby_vars = (int *)moby->pvars; + enum { + PATH_FOLLOWER_STATE_INITIALIZE = 0, + PATH_FOLLOWER_STATE_PROJECT_TARGET_ONTO_PATH = 1, + PATH_FOLLOWER_STATE_ADVANCE_ALONG_PATH = 2, + PATH_FOLLOWER_STATE_PATH_END_REACHED = 3 + }; + int *moby_vars = (int *)moby->pvars; char *path; char *pth; char *target_moby; diff --git a/src/overlays/l13/mobys/qwarks_starfighter.c b/src/overlays/l13/mobys/qwarks_starfighter.c index 3b7ddf8c59..101071f529 100644 --- a/src/overlays/l13/mobys/qwarks_starfighter.c +++ b/src/overlays/l13/mobys/qwarks_starfighter.c @@ -179,7 +179,8 @@ void emit_gated_moby_joint_effects(struct Moby *source_moby, char *emission_gate -100, 1); } else if (source_moby->command == 0 || - l13_starfighter_attachment_slot_indices_by_command[source_moby->command - 1] != + l13_starfighter_attachment_slot_indices_by_command[source_moby->command - + 1] != joint_effect_gate_slot_indices[i] || random_integer_below(9) == 0) { effect_frame_count = scale_game_frames(random_int_between(0xF, 0x16)); @@ -285,7 +286,8 @@ void update_moby_joint_attachments(struct Moby *parent_moby, char *attachment_da *(char **)(attachment_data + 0xF0) = spawn_moby_joint_attachment(parent_moby, attachment_joint_index, 0x191); attached_moby = *(char **)(attachment_data + 0xF0); - if (attached_moby != 0 && MOBY(attached_moby)->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + if (attached_moby != 0 && + MOBY(attached_moby)->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && MOBY(attached_moby)->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { moby_point_position(parent_moby, attachment_joint_index, attached_moby + 0x10); if (MOBY(attached_moby)->pos.x < 22.0f) @@ -826,7 +828,10 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { mode = ATTACHMENT_DAMAGE_STAGE_ADVANCED; if (moby->bBC == 7) { for (j = moby->bBC - 1; j < 10; j++) { - func_L13_002EAAB8_2EAE80(moby, moby_data, l13_starfighter_attachment_slot_indices_by_command[j]); + func_L13_002EAAB8_2EAE80( + moby, + moby_data, + l13_starfighter_attachment_slot_indices_by_command[j]); } allocate_voice_for_target_entry(7, 0, moby); } @@ -918,7 +923,8 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { mode = ATTACHMENT_DAMAGE_STAGE_ADVANCED; if (moby->bBC == 7) { for (k = moby->bBC - 1; k < 10; k++) { - func_L13_002EAAB8_2EAE80(moby, moby_data, l13_starfighter_attachment_slot_indices_by_command[k]); + func_L13_002EAAB8_2EAE80( + moby, moby_data, l13_starfighter_attachment_slot_indices_by_command[k]); } allocate_voice_for_target_entry(7, 0, moby); } @@ -2282,7 +2288,8 @@ void qwarks_starfighter_update(Moby388 *moby) { if (moby->state >= STARFIGHTER_STATE_FOLLOW_INITIAL_PATH) { update_moby_joint_attachments(moby, starfighter_vars); - if (moby->state != STARFIGHTER_STATE_EXPLODE_AND_REMOVE || scale_game_frames(0x78) < starfighter_vars->iF8) { + if (moby->state != STARFIGHTER_STATE_EXPLODE_AND_REMOVE || + scale_game_frames(0x78) < starfighter_vars->iF8) { emit_gated_moby_joint_effects(moby, starfighter_vars); } if (starfighter_vars->snd114 != -1) { @@ -2310,7 +2317,8 @@ void qwarks_starfighter_update(Moby388 *moby) { { Moby388 *owner = (Moby388 *)((char *)moby_base + (starfighter_vars->i134 << 8)); if (moby->state != STARFIGHTER_STATE_OWNER_UNAVAILABLE) { - if (owner == 0 || owner->cls_id != 0x45 || owner->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || + if (owner == 0 || owner->cls_id != 0x45 || + owner->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || owner->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END || owner->state == 7) { moby->state = STARFIGHTER_STATE_OWNER_UNAVAILABLE; if (queue_starfighter_voice_line( @@ -2347,7 +2355,9 @@ void qwarks_starfighter_update(Moby388 *moby) { } fast_dec_timer_s16(&starfighter_vars->h144); fast_dec_timer_s16(&starfighter_vars->h146); - if (moby->state >= STARFIGHTER_STATE_FOLLOW_INITIAL_PATH && moby->state <= STARFIGHTER_STATE_TRACTOR_BEAM && (((unsigned char *)D_0013E533)[0x242C] & 1)) { + if (moby->state >= STARFIGHTER_STATE_FOLLOW_INITIAL_PATH && + moby->state <= STARFIGHTER_STATE_TRACTOR_BEAM && + (((unsigned char *)D_0013E533)[0x242C] & 1)) { moby->state = STARFIGHTER_STATE_RESET; } } diff --git a/src/overlays/l13/mobys/tracked_group_watcher.c b/src/overlays/l13/mobys/tracked_group_watcher.c index 0d647cdb4d..e21f513321 100644 --- a/src/overlays/l13/mobys/tracked_group_watcher.c +++ b/src/overlays/l13/mobys/tracked_group_watcher.c @@ -8,7 +8,12 @@ void tracked_group_watcher_update(struct Moby *moby) __asm__("FUN_L13_0030be60") /* Moby class 1577 */ void tracked_group_watcher_update(struct Moby *moby) { - enum { TRACKED_GROUP_WATCHER_STATE_INITIALIZE_TRACKING = 0 , TRACKED_GROUP_WATCHER_STATE_MONITOR_TRACKED_MOBYS = 1 , TRACKED_GROUP_WATCHER_STATE_ZERO_THRESHOLD_IDLE = 2 } ;int *moby_vars = (int *)moby->pvars; + enum { + TRACKED_GROUP_WATCHER_STATE_INITIALIZE_TRACKING = 0, + TRACKED_GROUP_WATCHER_STATE_MONITOR_TRACKED_MOBYS = 1, + TRACKED_GROUP_WATCHER_STATE_ZERO_THRESHOLD_IDLE = 2 + }; + int *moby_vars = (int *)moby->pvars; if (moby->state == TRACKED_GROUP_WATCHER_STATE_INITIALIZE_TRACKING) { int *ids = moby_vars + 4; int *cls = moby_vars + 12; diff --git a/src/overlays/l14/hero/hero_set_state.c b/src/overlays/l14/hero/hero_set_state.c index 06f5136f68..c42130564d 100644 --- a/src/overlays/l14/hero/hero_set_state.c +++ b/src/overlays/l14/hero/hero_set_state.c @@ -71,7 +71,8 @@ int hero_set_state(int requested_state, int b) { float grind_direction_or_jump_reference_position[4]; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L14_0015F5C4 == 2 || D_L14_0015F5C4 == 6) && b != 2) @@ -79,8 +80,16 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -775,7 +784,8 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; diff --git a/src/overlays/l14/hero/process_hero_state_transitions.c b/src/overlays/l14/hero/process_hero_state_transitions.c index c7c1b432fd..986b3efc40 100644 --- a/src/overlays/l14/hero/process_hero_state_transitions.c +++ b/src/overlays/l14/hero/process_hero_state_transitions.c @@ -174,8 +174,10 @@ void process_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L14_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; @@ -825,7 +827,8 @@ void process_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; diff --git a/src/overlays/l14/hero/update_hero_motion_by_state.c b/src/overlays/l14/hero/update_hero_motion_by_state.c index bde38024f2..9becdf6e03 100644 --- a/src/overlays/l14/hero/update_hero_motion_by_state.c +++ b/src/overlays/l14/hero/update_hero_motion_by_state.c @@ -1303,7 +1303,8 @@ void update_hero_motion_by_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -1965,14 +1966,16 @@ void update_hero_motion_by_state(void) { vector_and_hit_descriptor_scratch.f[2] - hero.rail_point.f[2]); if (rail_lookahead_slope_angle > 0.0f) { sp = rail_lookahead_slope_angle * 1.9098593f * (frame_time * -2.5f); - if (rail_lookahead_slope_angle > 0.2617994f && hero.grind_pose != 2 && hero.grind_pose != 3) { + if (rail_lookahead_slope_angle > 0.2617994f && hero.grind_pose != 2 && + hero.grind_pose != 3) { hero.grind_pose = 0; } else if (rail_lookahead_slope_angle < 0.13962634f && hero.grind_pose == 0) { hero.grind_pose = -1; } } else { sp = -rail_lookahead_slope_angle * 2.864789f * (frame_time * 8.0f); - if (rail_lookahead_slope_angle < -0.19198622f && hero.grind_pose != 2 && hero.grind_pose != 3) { + if (rail_lookahead_slope_angle < -0.19198622f && hero.grind_pose != 2 && + hero.grind_pose != 3) { hero.grind_pose = 1; } else if (rail_lookahead_slope_angle > -0.12217305f && hero.grind_pose == 1) { hero.grind_pose = -1; @@ -2246,7 +2249,8 @@ void update_hero_motion_by_state(void) { if (hero.unk2224 != -1) { struct VoiceSlot *alternate_landing_voice_slot = (struct VoiceSlot *)(((u8 *)&voice_pool) + hero.unk2224 * 0x70); - if (alternate_landing_voice_slot->pm88 == MV(hero.moby) && alternate_landing_voice_slot->b74 != 0) { + if (alternate_landing_voice_slot->pm88 == MV(hero.moby) && + alternate_landing_voice_slot->b74 != 0) { release_voice_slot(hero.unk2224); } } diff --git a/src/overlays/l14/level_class_tables.c b/src/overlays/l14/level_class_tables.c index bd8ee7c3a4..26e53deca0 100644 --- a/src/overlays/l14/level_class_tables.c +++ b/src/overlays/l14/level_class_tables.c @@ -352,7 +352,7 @@ struct CameraType level_camera_types[10] __asm__("D_L14_001FDA00") __attribute__ {17, FUN_L00_002ed230, noop_main_callback, noop_main_callback, noop_main_callback}, {19, evaluate_descriptor_eligibility, initialize_path_camera, - update_path_flythrough_camera, noop_main_callback }, + update_path_flythrough_camera, noop_main_callback }, {20, check_path_camera_priority, setup_path_camera, update_path_camera, noop_main_callback}, {21, check_path_key_camera_priority, initialize_path_key_camera, diff --git a/src/overlays/l14/mobys/blarg_heavy_interceptor.c b/src/overlays/l14/mobys/blarg_heavy_interceptor.c index acbb7ecc85..a6f5e9b54e 100644 --- a/src/overlays/l14/mobys/blarg_heavy_interceptor.c +++ b/src/overlays/l14/mobys/blarg_heavy_interceptor.c @@ -258,7 +258,10 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { INTERCEPTOR_STATE_REJOIN_PATROL = 6, INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL = 7, INTERCEPTOR_STATE_DEATH_FALL = 9 - } ; enum { INTERCEPTOR_STATE_GROUP_EFFECTS_CONTROLLER = 8}; + }; + enum { + INTERCEPTOR_STATE_GROUP_EFFECTS_CONTROLLER = 8 + }; BlargHeavyInterceptorVars *moby_vars = (BlargHeavyInterceptorVars *)moby->pvars; float vector_scratch[4]; float secondary_vector_scratch[4]; @@ -289,7 +292,8 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { } } process_blarg_heavy_interceptor_hit_reactions(moby); - if (moby->state > INTERCEPTOR_STATE_INITIALIZE && moby->state < INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL) { + if (moby->state > INTERCEPTOR_STATE_INITIALIZE && + moby->state < INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL) { if (fast_vec_dist(&moby->pos, D_L14_001674C0) < 40.0f) { FUN_L00_0025a120(moby); } @@ -754,10 +758,12 @@ void blarg_heavy_interceptor_update(struct Moby *moby) { } else { moby->command = 0; } - if (moby->state == INTERCEPTOR_STATE_PATROL_AND_SCAN && !voice_is_playing(moby, *(s32 *)&moby_vars->unk1D0[0])) { + if (moby->state == INTERCEPTOR_STATE_PATROL_AND_SCAN && + !voice_is_playing(moby, *(s32 *)&moby_vars->unk1D0[0])) { *(s32 *)&moby_vars->unk1D0[0] = allocate_voice_c618(0, 4, moby); } - if ((moby->state == INTERCEPTOR_STATE_TRACK_TARGET || moby->state == INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY) && + if ((moby->state == INTERCEPTOR_STATE_TRACK_TARGET || + moby->state == INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY) && !voice_is_playing(moby, *(s32 *)&moby_vars->unk1D0[0])) { *(s32 *)&moby_vars->unk1D0[0] = allocate_voice_c618(2, 4, moby); } @@ -788,8 +794,19 @@ void process_blarg_heavy_interceptor_hit_reactions(struct Moby *moby) { HIT_REACTION_ANIMATE_WITH_LOW_RED_FLASH = 9, HIT_REACTION_LOW_RED_FLASH_AND_HIT_ANIMATION = 10, HIT_REACTION_NONE = 11 - } ; enum { INTERCEPTOR_STATE_PATROL_AND_SCAN = 1 , INTERCEPTOR_STATE_ALERT_GROUP = 2 , INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL = 7}; - enum { HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE = 1 } ; enum { HIT_REACTION_STATUS_ENABLE_HIT_PARTICLES = 3} ;BlargHeavyInterceptorVars *blarg_heavy_interceptor_vars = + }; + enum { + INTERCEPTOR_STATE_PATROL_AND_SCAN = 1, + INTERCEPTOR_STATE_ALERT_GROUP = 2, + INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL = 7 + }; + enum { + HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE = 1 + }; + enum { + HIT_REACTION_STATUS_ENABLE_HIT_PARTICLES = 3 + }; + BlargHeavyInterceptorVars *blarg_heavy_interceptor_vars = (BlargHeavyInterceptorVars *)moby->pvars; int hit_reaction_status; float damage_amount; @@ -803,7 +820,8 @@ void process_blarg_heavy_interceptor_hit_reactions(struct Moby *moby) { &damage_amount, 0, 4); - if (hit_reaction_status != HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE && moby->state < INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL) { + if (hit_reaction_status != HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE && + moby->state < INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL) { float remaining_health = blarg_heavy_interceptor_vars->health - damage_amount; blarg_heavy_interceptor_vars->health = remaining_health; if (remaining_health <= 0.0f) @@ -1698,7 +1716,10 @@ update_moby_rotation_oscillation(u8 *, u8 *, u8 *, f32, f32, f32) __asm__("FUN_L void update_blarg_heavy_interceptor_oscillation_and_patrol_heading(struct Moby *moby) __asm__("FUN_L14_002aea08"); void update_blarg_heavy_interceptor_oscillation_and_patrol_heading(struct Moby *moby) { - enum { INTERCEPTOR_STATE_PATROL_AND_SCAN = 1 } ;BlargHeavyInterceptorVars *interceptor_private_vars = (BlargHeavyInterceptorVars *)moby->pvars; + enum { + INTERCEPTOR_STATE_PATROL_AND_SCAN = 1 + }; + BlargHeavyInterceptorVars *interceptor_private_vars = (BlargHeavyInterceptorVars *)moby->pvars; f32 heading_offset; update_moby_vertical_oscillation( blarg_heavy_interceptor_vertical_oscillation_amplitude_gp, @@ -1782,10 +1803,12 @@ int update_blarg_heavy_interceptor_aim_transforms(struct Moby *moby, int flag) { 1.0f); rotation_angle = fast_subtract_rotations( fast_arc_tan(half_span_vector[0], half_span_vector[1]), moby->rot.z); - build_axis_rotation_quaternion(blarg_heavy_interceptor_private_vars->unkF0, 2, rotation_angle); + build_axis_rotation_quaternion( + blarg_heavy_interceptor_private_vars->unkF0, 2, rotation_angle); blarg_heavy_interceptor_private_vars->unk1B0[3] = rotation_angle; rotation_angle = -fast_arc_tan(vector_length_xy(half_span_vector), half_span_vector[2]); - build_axis_rotation_quaternion(blarg_heavy_interceptor_private_vars->unk130, 1, rotation_angle); + build_axis_rotation_quaternion( + blarg_heavy_interceptor_private_vars->unk130, 1, rotation_angle); blarg_heavy_interceptor_private_vars->unk1C0[0] = rotation_angle; qcopy(blarg_heavy_interceptor_private_vars->unk90, blarg_heavy_interceptor_private_vars->unk170); @@ -1970,7 +1993,8 @@ int try_retract_turret_group(int index) { checked_moby = moby_array_start + (moby_index_or_state << 8); if ((((unsigned char *)MOBY(checked_moby)->pvars))[0x8B] == 0) { moby_index_or_state = checked_moby[0x20]; - if (moby_index_or_state != TURRET_STATE_RETRACTING && moby_index_or_state != TURRET_STATE_WAITING) { + if (moby_index_or_state != TURRET_STATE_RETRACTING && + moby_index_or_state != TURRET_STATE_WAITING) { return 0; } } diff --git a/src/overlays/l14/mobys/bolt_thief.c b/src/overlays/l14/mobys/bolt_thief.c index 590c8a95cf..2b41bc9729 100644 --- a/src/overlays/l14/mobys/bolt_thief.c +++ b/src/overlays/l14/mobys/bolt_thief.c @@ -339,7 +339,10 @@ typedef struct BoltThiefVars { } BoltThiefVars; int update_bolt_thief_path_movement(struct Moby *moby) { - enum { BOLT_THIEF_STATE_FOLLOW_SECONDARY_PATH = 5 } ;float pos[4]; + enum { + BOLT_THIEF_STATE_FOLLOW_SECONDARY_PATH = 5 + }; + float pos[4]; float delta[4]; BoltThiefVars *bolt_thief_state = (BoltThiefVars *)moby->pvars; float path_sample_step = bolt_thief_default_path_sample_rate_gp * frame_time; diff --git a/src/overlays/l14/mobys/bouncing_spark.c b/src/overlays/l14/mobys/bouncing_spark.c index d6d6858678..d5d32b4548 100644 --- a/src/overlays/l14/mobys/bouncing_spark.c +++ b/src/overlays/l14/mobys/bouncing_spark.c @@ -160,7 +160,8 @@ void bouncing_spark_update(struct Moby *spark_moby) { qcopy(&spark_moby->pos, &predicted_position_or_fade_rgb); } if (((coll_sphere(&spark_moby->pos, 0, spark_moby, spark_contact_clearance_gp) != 0) && - ((spark_moby->state == SPARK_COUNT_NEXT_BOUNCE) || ((spark_moby->pos.z - D_L14_00174540.hit.z) < 0.0f))) && + ((spark_moby->state == SPARK_COUNT_NEXT_BOUNCE) || + ((spark_moby->pos.z - D_L14_00174540.hit.z) < 0.0f))) && ((D_L14_00174540.owner == 0) || (D_L14_00174540.owner != spark_data->owner))) { fast_vec_normalize( &position_scratch, &D_L14_00174540.normal, spark_contact_clearance_gp); diff --git a/src/overlays/l14/mobys/elevator.c b/src/overlays/l14/mobys/elevator.c index e716541d23..8173775862 100644 --- a/src/overlays/l14/mobys/elevator.c +++ b/src/overlays/l14/mobys/elevator.c @@ -93,7 +93,8 @@ void elevator_update(struct Moby *elevator_moby) { Vec4 delta; float level; - if (elevator_moby->state != ELEVATOR_STATE_INITIALIZE && elevator_moby->command == 2 && elevator_vars->dir < 0.0f) { + if (elevator_moby->state != ELEVATOR_STATE_INITIALIZE && elevator_moby->command == 2 && + elevator_vars->dir < 0.0f) { int *path = (int *)l14_paths[elevator_vars->path2]; elevator_vars->dir = -elevator_vars->dir; elevator_vars->segment = *path - 2; @@ -227,7 +228,8 @@ void elevator_update(struct Moby *elevator_moby) { elevator_moby->state = ELEVATOR_STATE_WAIT_FOR_RIDER; break; } - if (elevator_moby->state != ELEVATOR_STATE_FOLLOW_PATH && elevator_moby->state != ELEVATOR_STATE_INITIALIZE) { + if (elevator_moby->state != ELEVATOR_STATE_FOLLOW_PATH && + elevator_moby->state != ELEVATOR_STATE_INITIALIZE) { settle_elevator_at_path_endpoint(elevator_moby); if (hero.ground_moby == elevator_moby) { fast_vec_sub(&delta, &elevator_moby->pos, &previous_elevator_position); diff --git a/src/overlays/l14/mobys/enemy_fighter.c b/src/overlays/l14/mobys/enemy_fighter.c index 3bbbb0cdb0..79a60851ad 100644 --- a/src/overlays/l14/mobys/enemy_fighter.c +++ b/src/overlays/l14/mobys/enemy_fighter.c @@ -136,7 +136,8 @@ void enemy_fighter_update(struct Moby *moby) { break; } spawn_enemy_fighter_exhaust(moby); - if (moby->state != ENEMY_FIGHTER_STATE_INITIALIZE && moby->state != ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN && + if (moby->state != ENEMY_FIGHTER_STATE_INITIALIZE && + moby->state != ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN && voice_is_playing(moby, enemy_fighter_vars->sound) == 0) enemy_fighter_vars->sound = allocate_voice_for_target_entry(0, 4, moby); } @@ -163,7 +164,8 @@ void spawn_enemy_fighter_exhaust(struct Moby *emitter_moby) { int life; float size; - if (emitter_moby->state == ENEMY_FIGHTER_STATE_INITIALIZE || emitter_moby->state == ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN || emitter_moby->visible == 0) + if (emitter_moby->state == ENEMY_FIGHTER_STATE_INITIALIZE || + emitter_moby->state == ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN || emitter_moby->visible == 0) return; fast_vec_scale(&step, &emitter_moby->rot_row0, enemy_fighter_exhaust_base_row0_offset_gp); fast_vec_add(&pos, &emitter_moby->pos, &step); diff --git a/src/overlays/l14/mobys/flying_car.c b/src/overlays/l14/mobys/flying_car.c index 793bac36f2..a9443b489f 100644 --- a/src/overlays/l14/mobys/flying_car.c +++ b/src/overlays/l14/mobys/flying_car.c @@ -288,7 +288,9 @@ void flying_car_update(struct Moby *flying_car_moby) { } break; } - if (flying_car_moby->state == FLYING_CAR_INITIALIZE || flying_car_moby->state == FLYING_CAR_WAIT_FOR_PATH_RESET || flying_car_moby->state == FLYING_CAR_WAIT_FOR_TRIGGER) { + if (flying_car_moby->state == FLYING_CAR_INITIALIZE || + flying_car_moby->state == FLYING_CAR_WAIT_FOR_PATH_RESET || + flying_car_moby->state == FLYING_CAR_WAIT_FOR_TRIGGER) { return; } if (voice_is_playing(flying_car_moby, flying_car_data->sound) == 0) { diff --git a/src/overlays/l14/mobys/machinegun_turret.c b/src/overlays/l14/mobys/machinegun_turret.c index fef577a920..f2dbc62bc6 100644 --- a/src/overlays/l14/mobys/machinegun_turret.c +++ b/src/overlays/l14/mobys/machinegun_turret.c @@ -231,7 +231,10 @@ void machinegun_turret_update(char *moby) { enum { TURRET_SPAWN_CENTER = 0, TURRET_SPAWN_UNNEGATED_OFFSET = 1 - } ; enum { MOBY_SELECTION_NO_TARGET = 2}; + }; + enum { + MOBY_SELECTION_NO_TARGET = 2 + }; MachinegunTurretVars *machinegun_turret_private_vars; float target_point_scratch[4]; float spawn_position[4]; @@ -515,7 +518,10 @@ void process_machinegun_turret_hit_reactions(struct Moby *moby) { HIT_REACTION_ANIMATE_WITH_LOW_RED_FLASH = 9, HIT_REACTION_LOW_RED_FLASH_AND_HIT_ANIMATION = 10, HIT_REACTION_NONE = 11 - } ; enum { TURRET_STATE_DESTROY = 6}; + }; + enum { + TURRET_STATE_DESTROY = 6 + }; MachinegunTurretVars *moby_vars = (MachinegunTurretVars *)moby->pvars; int loc0; float damage_amount = 0.0f; diff --git a/src/overlays/l14/mobys/minibomber.c b/src/overlays/l14/mobys/minibomber.c index 7cfd15abc2..df0c568821 100644 --- a/src/overlays/l14/mobys/minibomber.c +++ b/src/overlays/l14/mobys/minibomber.c @@ -309,8 +309,10 @@ void minibomber_update(Moby_2B5938 *moby) { FUN_L14_002b5428_c((char *)moby); FUN_L14_002b5dd8_c((char *)moby); if (moby->f31 != 0) { - if (fast_vec_dist(moby->pos, D_L14_001674C0) < 40.0f && moby->state != MINIBOMBER_STATE_INITIALIZE && - moby->state != MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH && moby->state != MINIBOMBER_STATE_DESTROY) { + if (fast_vec_dist(moby->pos, D_L14_001674C0) < 40.0f && + moby->state != MINIBOMBER_STATE_INITIALIZE && + moby->state != MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH && + moby->state != MINIBOMBER_STATE_DESTROY) { FUN_L00_0025a120(moby); } } @@ -621,7 +623,8 @@ void minibomber_update(Moby_2B5938 *moby) { return; } } - if (moby->state > MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH && moby->state != MINIBOMBER_STATE_DESTROY) { + if (moby->state > MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH && + moby->state != MINIBOMBER_STATE_DESTROY) { if (voice_is_playing(moby, d->f108) == 0) { d->f108 = allocate_voice_for_target_entry(0, 4, (int)moby); } @@ -661,7 +664,8 @@ void process_minibomber_hit_reactions(struct Moby *hit_owner_moby) { char *hit_record; int k; float remaining_health; - if (hit_owner_moby->state == MINIBOMBER_STATE_INITIALIZE || hit_owner_moby->state == MINIBOMBER_STATE_DESTROY) + if (hit_owner_moby->state == MINIBOMBER_STATE_INITIALIZE || + hit_owner_moby->state == MINIBOMBER_STATE_DESTROY) return; hit_owner_moby->scale = hit_owner_moby->pclass->scale; damage_amount = 0.0f; @@ -742,7 +746,8 @@ void update_minibomber_oscillation(struct Moby *moby) { unsigned char state = raw; char *minibomber_instance_vars = (char *)moby->pvars; float spring_target; - if (state == MINIBOMBER_STATE_INITIALIZE || state == MINIBOMBER_STATE_DESTROY || state == MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH) + if (state == MINIBOMBER_STATE_INITIALIZE || state == MINIBOMBER_STATE_DESTROY || + state == MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH) return; spring_target = *(float *)&D_L14_00161540_gp; if ((raw >= 2 && raw <= 3) || state == MINIBOMBER_STATE_TRAVERSE_PATH) { @@ -895,9 +900,15 @@ void ease_minibomber_position_and_heading(char *moby, float heading_velocity_damping, float heading_velocity_limit) { - enum { MINIBOMBER_STATE_HOLD_AT_PATH_END = 4 , MINIBOMBER_STATE_RELEASE_BOMB = 6 } ;int minibomber_private_vars_base; + enum { + MINIBOMBER_STATE_HOLD_AT_PATH_END = 4, + MINIBOMBER_STATE_RELEASE_BOMB = 6 + }; + int minibomber_private_vars_base; int moby_state = MOBY(moby)->state & 0xFF; - if ((moby_state >= MINIBOMBER_STATE_HOLD_AT_PATH_END && moby_state <= MINIBOMBER_STATE_RELEASE_BOMB) || moby_state == 8) { + if ((moby_state >= MINIBOMBER_STATE_HOLD_AT_PATH_END && + moby_state <= MINIBOMBER_STATE_RELEASE_BOMB) || + moby_state == 8) { minibomber_private_vars_base = *(int *)(moby + 0x78); vendor_spring((float *)&MOBY(moby)->pos, (float *)(minibomber_private_vars_base + 0xF0), @@ -1138,7 +1149,8 @@ void emit_minibomber_exhaust_puffs(struct Moby *moby) { int signed_puff_value; int life; float size; - if (moby->state < MINIBOMBER_STATE_FOLLOW_INTRO_OR_EXIT_PATH || moby->state == MINIBOMBER_STATE_DESTROY) + if (moby->state < MINIBOMBER_STATE_FOLLOW_INTRO_OR_EXIT_PATH || + moby->state == MINIBOMBER_STATE_DESTROY) return; fast_vec_scale(exhaust_position_offset, &moby->rot_row0, -1.25f); fast_vec_add(pos, &moby->pos, exhaust_position_offset); diff --git a/src/overlays/l14/mobys/morphoray_pickup.c b/src/overlays/l14/mobys/morphoray_pickup.c index b8616767b9..9c0434fec3 100644 --- a/src/overlays/l14/mobys/morphoray_pickup.c +++ b/src/overlays/l14/mobys/morphoray_pickup.c @@ -155,8 +155,14 @@ typedef struct { extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); -extern unsigned char * -spawn_timed_hero_relative_particle(float f, void *pos, int b, unsigned char a2, int idx, int flag, int s, int mode) __asm__("FUN_L00_00272f68"); +extern unsigned char *spawn_timed_hero_relative_particle(float f, + void *pos, + int b, + unsigned char a2, + int idx, + int flag, + int s, + int mode) __asm__("FUN_L00_00272f68"); void update_morphoray_particles(struct Moby *morphoray_moby) { float particle_position_and_step[8]; @@ -191,7 +197,8 @@ void update_morphoray_particles(struct Moby *morphoray_moby) { elapsed_timer_fraction = elapsed_timer_fraction / (float)scale_game_frames(255); c = fast_tween_color(0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - elapsed_timer_fraction)); k = truncate_float_to_s32(*a++); - spawn_timed_hero_relative_particle(effect_data->c[j], particle_position_and_step, c, k, 0x35, 1, 2, 0); + spawn_timed_hero_relative_particle( + effect_data->c[j], particle_position_and_step, c, k, 0x35, 1, 2, 0); j++; fast_vec_add( particle_position_and_step, particle_position_and_step, &particle_position_and_step[4]); diff --git a/src/overlays/l14/mobys/path_lightning_controller.c b/src/overlays/l14/mobys/path_lightning_controller.c index b12dde9ba2..db67a3f552 100644 --- a/src/overlays/l14/mobys/path_lightning_controller.c +++ b/src/overlays/l14/mobys/path_lightning_controller.c @@ -56,7 +56,13 @@ void path_lightning_controller_update(struct Moby *moby) __asm__("FUN_L14_002ed2 /* Moby class 684 */ void path_lightning_controller_update(struct Moby *moby) { - enum { PATH_LIGHTNING_STATE_INITIALIZE = 0 , PATH_LIGHTNING_STATE_WAIT_SCENE_START = 1 , PATH_LIGHTNING_STATE_WAIT_TRACKED_MOBY_RESTORE = 2 , PATH_LIGHTNING_STATE_ACTIVE = 3 } ;char *moby_vars = (char *)moby->pvars; + enum { + PATH_LIGHTNING_STATE_INITIALIZE = 0, + PATH_LIGHTNING_STATE_WAIT_SCENE_START = 1, + PATH_LIGHTNING_STATE_WAIT_TRACKED_MOBY_RESTORE = 2, + PATH_LIGHTNING_STATE_ACTIVE = 3 + }; + char *moby_vars = (char *)moby->pvars; int visible_path_point_indices[5]; float visibility_test_point[4]; int moby_state; diff --git a/src/overlays/l14/mobys/platform.c b/src/overlays/l14/mobys/platform.c index 1dc2fe0d35..e7276e73d4 100644 --- a/src/overlays/l14/mobys/platform.c +++ b/src/overlays/l14/mobys/platform.c @@ -54,7 +54,11 @@ typedef struct TiltingPlatformVars { /* Moby class 309 */ void tilting_platform_update(struct Moby *moby) { - enum { TILTING_PLATFORM_STATE_UNINITIALIZED = 0 , TILTING_PLATFORM_STATE_INITIALIZED = 1 } ;TiltingPlatformVars *tilting_platform_state = (TiltingPlatformVars *)moby->pvars; + enum { + TILTING_PLATFORM_STATE_UNINITIALIZED = 0, + TILTING_PLATFORM_STATE_INITIALIZED = 1 + }; + TiltingPlatformVars *tilting_platform_state = (TiltingPlatformVars *)moby->pvars; void *rotation; u128 old_rotation; qcopy(&old_rotation, &moby->rot); diff --git a/src/overlays/l14/mobys/rocket_strike_fighter.c b/src/overlays/l14/mobys/rocket_strike_fighter.c index ceca3bca61..1c1f42aba9 100644 --- a/src/overlays/l14/mobys/rocket_strike_fighter.c +++ b/src/overlays/l14/mobys/rocket_strike_fighter.c @@ -106,7 +106,8 @@ void rocket_strike_fighter_update(struct Moby *moby) { { void *hit = find_moby_hit(moby, 0x800000, 0); moby->hit_slot = 0xFF; - if (hit != 0 && moby_vars->rocket == -1 && moby->state != ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN) { + if (hit != 0 && moby_vars->rocket == -1 && + moby->state != ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN) { if (current_level_index == 14) { enemy_fighter_destruction_count = enemy_fighter_destruction_count + 1; if (enemy_fighter_destruction_count >= 3 && item_unlocked[0x18] == 0) { @@ -246,7 +247,9 @@ void rocket_strike_fighter_update(struct Moby *moby) { break; } spawn_rocket_strike_fighter_exhaust(moby); - if (moby->state != ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE && moby->state != ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN && moby->state != ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS && + if (moby->state != ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE && + moby->state != ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN && + moby->state != ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS && voice_is_playing(moby, moby_vars->sound) == 0) moby_vars->sound = allocate_voice_for_target_entry(0, 4, moby); } @@ -285,7 +288,9 @@ void spawn_rocket_strike_fighter_exhaust(struct Moby *moby) { int grey; float size; - if (moby->state == ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE || moby->state == ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN || moby->state == ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS) + if (moby->state == ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE || + moby->state == ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN || + moby->state == ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS) return; fast_vec_scale(&step, &moby->rot_row0, rocket_strike_fighter_exhaust_base_row0_offset_gp); fast_vec_add(&pos, &moby->pos, &step); diff --git a/src/overlays/l14/mobys/taxi.c b/src/overlays/l14/mobys/taxi.c index 6749a4940b..ea15abfd63 100644 --- a/src/overlays/l14/mobys/taxi.c +++ b/src/overlays/l14/mobys/taxi.c @@ -349,7 +349,8 @@ void taxi_update(struct Moby *moby) { } } apply_moby_position_and_rotation_wobble((char *)moby); - if (moby->state >= TAXI_STATE_BLEND_STOP_TO_PATH_START && moby->state <= TAXI_STATE_FOLLOW_PATH) { + if (moby->state >= TAXI_STATE_BLEND_STOP_TO_PATH_START && + moby->state <= TAXI_STATE_FOLLOW_PATH) { struct Hero *g = &hero; if (g->ground_moby == moby && g->air_frames.s == 0) { g->jump_lock_timer = 2; diff --git a/src/overlays/l14/mobys/wind_control.c b/src/overlays/l14/mobys/wind_control.c index d8ee062c3b..714e76faf6 100644 --- a/src/overlays/l14/mobys/wind_control.c +++ b/src/overlays/l14/mobys/wind_control.c @@ -73,7 +73,11 @@ void wind_control_update(struct Moby *wind_control_moby) __asm__("FUN_L14_002eaf /* Moby class 610 */ void wind_control_update(struct Moby *wind_control_moby) { - enum { WIND_CONTROL_STATE_UNINITIALIZED = 0 , WIND_CONTROL_STATE_INITIALIZED = 1 } ;L14WindVars *wind_vars = (L14WindVars *)wind_control_moby->pvars; + enum { + WIND_CONTROL_STATE_UNINITIALIZED = 0, + WIND_CONTROL_STATE_INITIALIZED = 1 + }; + L14WindVars *wind_vars = (L14WindVars *)wind_control_moby->pvars; float wind_direction_or_push_delta[4]; char *pos; struct Hero *hero_base; diff --git a/src/overlays/l14/path_key_camera.c b/src/overlays/l14/path_key_camera.c index 15ea516e6d..824aac53b4 100644 --- a/src/overlays/l14/path_key_camera.c +++ b/src/overlays/l14/path_key_camera.c @@ -36,11 +36,12 @@ compute_position_from_spherical_offset(void *, void *, void *) __asm__("FUN_L00_ void initialize_path_key_camera(struct UpdateCam *cam) __asm__("FUN_L14_003159d8"); void initialize_path_key_camera(struct UpdateCam *path_key_camera_object) { - float camera_placement_parameters[4]; - float pad[4]; /* unused; keeps the frame layout */ - float hero_look_direction[4]; - float up[4]; - char *rec = *(char **)(l14_camera_preset_rows + path_key_camera_object->descriptor_index * 32 + 0x1C); + float camera_placement_parameters[4]; + float pad[4]; /* unused; keeps the frame layout */ + float hero_look_direction[4]; + float up[4]; + char *rec = + *(char **)(l14_camera_preset_rows + path_key_camera_object->descriptor_index * 32 + 0x1C); char *path; LevelSpline *path_record_table; char *camera_saved_state; @@ -103,14 +104,16 @@ void initialize_path_key_camera(struct UpdateCam *path_key_camera_object) { camera_placement_parameters[1] = camera_parameters[1]; camera_placement_parameters[0] = hero_heading_radians; camera_placement_parameters[2] = camera_parameters[2]; - compute_position_from_spherical_offset(&path_key_camera_object->pos, camera_placement_parameters, &hero.motion); + compute_position_from_spherical_offset( + &path_key_camera_object->pos, camera_placement_parameters, &hero.motion); fast_vec_sub(hero_look_direction, &hero.motion, &path_key_camera_object->pos); fast_vec_scale(up, &hero.gravity_dir, -1.5f); fast_vec_add(hero_look_direction, hero_look_direction, up); fast_vec_normalize(&path_key_camera_object->m0, hero_look_direction, 1.0f); fast_vec_cross(&path_key_camera_object->m1, &path_key_camera_object->m0, up); fast_vec_normalize(&path_key_camera_object->m1, &path_key_camera_object->m1, 1.0f); - fast_vec_cross(&path_key_camera_object->m2, &path_key_camera_object->m1, &path_key_camera_object->m0); + fast_vec_cross( + &path_key_camera_object->m2, &path_key_camera_object->m1, &path_key_camera_object->m0); /* give every key without a duration (+0x44) the default 10000 */ camera_key_default_cursor = (int *)&D_L14_001F6488_59d8[0x11]; for (j = 38; j >= 0; j--) { diff --git a/src/overlays/l15/hero/hero_set_state.c b/src/overlays/l15/hero/hero_set_state.c index cc8a199540..18e9f8abc8 100644 --- a/src/overlays/l15/hero/hero_set_state.c +++ b/src/overlays/l15/hero/hero_set_state.c @@ -74,7 +74,8 @@ int hero_set_state(int requested_state, int b) { int old20A7; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L15_0015F5C4 == 2 || D_L15_0015F5C4 == 6) && b != 2) @@ -82,8 +83,16 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -903,7 +912,8 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; diff --git a/src/overlays/l15/hero/update_hero_motion_for_current_state.c b/src/overlays/l15/hero/update_hero_motion_for_current_state.c index a9dac0b9e6..7a73639d1b 100644 --- a/src/overlays/l15/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l15/hero/update_hero_motion_for_current_state.c @@ -1726,7 +1726,8 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { diff --git a/src/overlays/l15/hero/update_hero_state_machine.c b/src/overlays/l15/hero/update_hero_state_machine.c index 881127b141..5d06e1d0b9 100644 --- a/src/overlays/l15/hero/update_hero_state_machine.c +++ b/src/overlays/l15/hero/update_hero_state_machine.c @@ -173,8 +173,10 @@ void update_hero_state_machine(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L15_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; @@ -904,7 +906,8 @@ void update_hero_state_machine(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; diff --git a/src/overlays/l15/level_class_tables.c b/src/overlays/l15/level_class_tables.c index 0a521b1880..a248a0de06 100644 --- a/src/overlays/l15/level_class_tables.c +++ b/src/overlays/l15/level_class_tables.c @@ -364,7 +364,7 @@ struct CameraType level_camera_types[10] __asm__("D_L15_001E3F00") __attribute__ {17, FUN_L00_002ed230, noop_main_callback, noop_main_callback, noop_main_callback}, {19, evaluate_descriptor_eligibility, initialize_path_camera, - update_path_flythrough_camera, noop_main_callback }, + update_path_flythrough_camera, noop_main_callback }, {22, dispatch_moby_follow_camera_update, noop_main_callback, noop_main_callback, noop_main_callback }, diff --git a/src/overlays/l15/mobys/construction_arm.c b/src/overlays/l15/mobys/construction_arm.c index 4423ef8556..61760d6fa2 100644 --- a/src/overlays/l15/mobys/construction_arm.c +++ b/src/overlays/l15/mobys/construction_arm.c @@ -119,7 +119,8 @@ void construction_arm_update(struct Moby *moby) { group_member_moby = (struct Moby *)((*list & 0x7fff) * 0x100 + (int)l15_moby_array); if ((signed char)group_member_moby->state >= 0 && - group_member_moby->oclass == moby->oclass && group_member_moby->state != CONSTRUCTION_ARM_WAIT_TO_TURN) + group_member_moby->oclass == moby->oclass && + group_member_moby->state != CONSTRUCTION_ARM_WAIT_TO_TURN) count++; } while ((short)*list++ >= 0); if (count != 0) { diff --git a/src/overlays/l15/mobys/exploding_prop.c b/src/overlays/l15/mobys/exploding_prop.c index 0907da5beb..ea545603bd 100644 --- a/src/overlays/l15/mobys/exploding_prop.c +++ b/src/overlays/l15/mobys/exploding_prop.c @@ -68,7 +68,11 @@ void exploding_prop_update(struct Moby *moby) __asm__("FUN_L15_002aa280"); /* Moby class 154 */ void exploding_prop_update(struct Moby *moby) { - enum { EXPLODING_PROP_STATE_UNINITIALIZED = 0 , EXPLODING_PROP_STATE_INITIALIZED = 1 } ;char *hit = 0; + enum { + EXPLODING_PROP_STATE_UNINITIALIZED = 0, + EXPLODING_PROP_STATE_INITIALIZED = 1 + }; + char *hit = 0; Vec4 velocity, hit_direction, push, offset, center; u32 palette[4]; u32 colors[4]; diff --git a/src/overlays/l15/mobys/helicopter.c b/src/overlays/l15/mobys/helicopter.c index 763bd326cd..ea705c285e 100644 --- a/src/overlays/l15/mobys/helicopter.c +++ b/src/overlays/l15/mobys/helicopter.c @@ -428,7 +428,8 @@ void helicopter_update(struct Moby *moby) { if (helicopter_instance_vars->pilot == 0) { helicopter_instance_vars->pilot = create_class_55b_moby_from_source(moby); } - if (moby->state != HELICOPTER_INITIALIZE && moby->state != HELICOPTER_DEAD_WAIT_FOR_RESET && helicopter_instance_vars->unk1A4 != 0 && + if (moby->state != HELICOPTER_INITIALIZE && moby->state != HELICOPTER_DEAD_WAIT_FOR_RESET && + helicopter_instance_vars->unk1A4 != 0 && hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK) { moby->collision = 0; moby->flags = (moby->flags | 0x41) & 0xEFFF; @@ -511,7 +512,8 @@ void helicopter_update(struct Moby *moby) { helicopter_instance_vars->pilot->flags |= 0x41; break; case HELICOPTER_WAIT_FOR_ACTIVATION: - if (helicopter_instance_vars->unk1A4 != 0 && hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK) { + if (helicopter_instance_vars->unk1A4 != 0 && + hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK) { moby->collision = 0; moby->flags = (moby->flags | 0x41) & 0xEFFF; helicopter_instance_vars->unk58 = 0; @@ -845,11 +847,11 @@ void helicopter_update(struct Moby *moby) { frame_time_sq * 6.2831855f, frame_time * 1.5707964f); build_axis_rotation_quaternion(helicopter_instance_vars->turret_yaw_joint + 0x10, - 2, - helicopter_instance_vars->turret_yaw); + 2, + helicopter_instance_vars->turret_yaw); build_axis_rotation_quaternion(helicopter_instance_vars->turret_pitch_joint + 0x10, - 2, - helicopter_instance_vars->turret_pitch); + 2, + helicopter_instance_vars->turret_pitch); helicopter_instance_vars->shot = 0; } else { moby_point_position(moby, 0, &turret_pos); @@ -874,11 +876,11 @@ void helicopter_update(struct Moby *moby) { frame_time_sq * 6.2831855f, frame_time * 1.5707964f); build_axis_rotation_quaternion(helicopter_instance_vars->turret_yaw_joint + 0x10, - 2, - helicopter_instance_vars->turret_yaw); + 2, + helicopter_instance_vars->turret_yaw); build_axis_rotation_quaternion(helicopter_instance_vars->turret_pitch_joint + 0x10, - 2, - helicopter_instance_vars->turret_pitch); + 2, + helicopter_instance_vars->turret_pitch); } } @@ -909,7 +911,8 @@ void process_helicopter_hits(struct Moby *moby) { hit_record = find_moby_hit(moby, 0x330000, 0); hit_reaction_code = hit_reaction(moby, hit_record, helicopter_vars + 0x20, 0, &hit_reaction_status, &fv, 0, 4); - if (hit_reaction_status != HIT_REACTION_SKIP_DAMAGE && moby->state != HELICOPTER_DEATH_EFFECTS && moby->state != HELICOPTER_DEAD_WAIT_FOR_RESET) { + if (hit_reaction_status != HIT_REACTION_SKIP_DAMAGE && + moby->state != HELICOPTER_DEATH_EFFECTS && moby->state != HELICOPTER_DEAD_WAIT_FOR_RESET) { float remaining_health = *(float *)(helicopter_vars + 0x20) - fv; *(float *)(helicopter_vars + 0x20) = remaining_health; if (hit_reaction_code == 1 || remaining_health <= 0.0f) { diff --git a/src/overlays/l15/mobys/help_hints.c b/src/overlays/l15/mobys/help_hints.c index 86fce62465..e870de59cc 100644 --- a/src/overlays/l15/mobys/help_hints.c +++ b/src/overlays/l15/mobys/help_hints.c @@ -184,7 +184,8 @@ void help_hints_update(struct Moby *moby) { ((Items *)alternate_item_available)->f6F = 1; } if (is_point_inside_clip_volume(&hero.motion.pos, hint_dialogue_data->vol1C) != 0 && - hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && ((Items *)alternate_item_available)->f6F == 0 && + hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && + ((Items *)alternate_item_available)->f6F == 0 && ((Help *)quartu_help_message_state)->busy == 0 && ((Help *)quartu_help_message_state)->cur == -1 && *(int *)(item_usage + 0x6EC) >= 0) { help_request(0x3A9C, 0x80); diff --git a/src/overlays/l15/mobys/poison_vessel.c b/src/overlays/l15/mobys/poison_vessel.c index 6db88bbf0c..8326f68a13 100644 --- a/src/overlays/l15/mobys/poison_vessel.c +++ b/src/overlays/l15/mobys/poison_vessel.c @@ -192,7 +192,8 @@ void poison_vessel_update(Moby_2E9358 *moby) { if (data->target != 0) { Moby_2E9358 *target_moby = data->target; - if (target_moby->state == MOBY_STATE_MARKED_FOR_REMOVAL || data->target->state == 0xFD) { + if (target_moby->state == MOBY_STATE_MARKED_FOR_REMOVAL || + data->target->state == 0xFD) { moby->bBC = state; data->target = 0; } else if (D_L15_00174458_lui[0] != 0) { diff --git a/src/overlays/l15/mobys/radial_exploding_prop.c b/src/overlays/l15/mobys/radial_exploding_prop.c index 98beef1b67..a1c0c28a49 100644 --- a/src/overlays/l15/mobys/radial_exploding_prop.c +++ b/src/overlays/l15/mobys/radial_exploding_prop.c @@ -71,7 +71,11 @@ void radial_exploding_prop_update(struct Moby *moby) __asm__("FUN_L15_002a7880") /* Moby classes 148, 255 */ void radial_exploding_prop_update(struct Moby *moby) { - enum { RADIAL_EXPLODING_PROP_STATE_UNINITIALIZED = 0 , RADIAL_EXPLODING_PROP_STATE_INITIALIZED = 1 } ;char *slot = 0; + enum { + RADIAL_EXPLODING_PROP_STATE_UNINITIALIZED = 0, + RADIAL_EXPLODING_PROP_STATE_INITIALIZED = 1 + }; + char *slot = 0; Vec velocity, hit_direction_step, doubled_hit_direction_step, offset, debris_origin; u32 palette[4]; u32 colors[4]; diff --git a/src/overlays/l15/mobys/ultramech_scientist.c b/src/overlays/l15/mobys/ultramech_scientist.c index 5cf8dc59ce..544620bf7d 100644 --- a/src/overlays/l15/mobys/ultramech_scientist.c +++ b/src/overlays/l15/mobys/ultramech_scientist.c @@ -114,7 +114,10 @@ void ultramech_scientist_update(struct Moby *moby) { ULTRAMECH_SCIENTIST_WAIT_FOR_FIRST_SCENE = 6, ULTRAMECH_SCIENTIST_START_SECOND_SCENE_AND_SAVE = 7, ULTRAMECH_SCIENTIST_SAVE_AND_DISABLE = 8 - } ; enum { ULTRAMECH_SCIENTIST_DISABLED = 9}; + }; + enum { + ULTRAMECH_SCIENTIST_DISABLED = 9 + }; UltramechScientistVars *ultramech_scientist_private_data; char *hero_pos; struct Moby *moby_list_cursor; diff --git a/src/overlays/l15/mobys/ultramech_unlimited.c b/src/overlays/l15/mobys/ultramech_unlimited.c index 8ff8a5000f..c0913bd415 100644 --- a/src/overlays/l15/mobys/ultramech_unlimited.c +++ b/src/overlays/l15/mobys/ultramech_unlimited.c @@ -213,7 +213,8 @@ extern float approach_angle(void *, float, void *, float, float, float) __asm__( extern float compute_ultramech_flocking_steering_point(void *, void *, float) __asm__("FUN_L15_002cf110"); -extern int move_moby_xy_with_collision_constraints(void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); +extern int move_moby_xy_with_collision_constraints( + void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); extern int sweep_hit_segment(void *a, void *b, void *c, void *d, void *e, void *f, int n) __asm__("FUN_L00_00259d08"); @@ -299,7 +300,9 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { ultramech_vars = ultramech_moby->data; process_ultramech_hits_and_update_target(ultramech_moby); combat_target = ultramech_vars->target; - if (ultramech_moby->state != ULTRAMECH_INITIALIZE && ultramech_moby->state != ULTRAMECH_DEAD_WAIT_FOR_RESET && hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK) { + if (ultramech_moby->state != ULTRAMECH_INITIALIZE && + ultramech_moby->state != ULTRAMECH_DEAD_WAIT_FOR_RESET && + hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK) { ultramech_moby->w94 = 0; ultramech_moby->flags |= 0x41; idx = ultramech_vars->snd; @@ -358,7 +361,8 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { } if (ultramech_vars->w164 != 2 && ultramech_vars->path != -1) { struct Hero *pl = &hero; - if (pl->vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && (ultramech_moby->flags & 0x1000)) { + if (pl->vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && + (ultramech_moby->flags & 0x1000)) { if (ultramech_vars->w1D0 != -1 && !point_in_path_xy(&pl->motion.pos, D_L15_001B0AB0[ultramech_vars->w1D0]->points, @@ -682,13 +686,13 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { &position_or_motion_vector, &position_or_motion_vector, frame_time * 6.5f); add_vectors(&vector_arithmetic_result, &position_or_motion_vector, &ultramech_moby->pos); if (!move_moby_xy_with_collision_constraints(ultramech_moby, - &vector_or_hit_descriptor, - &position_or_motion_vector, - 1, - 2.25f, - 1.75f, - 0.5f, - 0.5235988f) || + &vector_or_hit_descriptor, + &position_or_motion_vector, + 1, + 2.25f, + 1.75f, + 0.5f, + 0.5235988f) || point_in_path_xy(&vector_or_hit_descriptor, D_L15_001B0AB0[ultramech_vars->side]->points, D_L15_001B0AB0[ultramech_vars->side]->count)) { @@ -904,7 +908,8 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { : FUN_L00_00257b90(0x14, 0x1E))); } } - } else if (ultramech_moby->state > ULTRAMECH_WAIT_FOR_ACTIVATION && ultramech_moby->state != ULTRAMECH_DEAD_WAIT_FOR_RESET) { + } else if (ultramech_moby->state > ULTRAMECH_WAIT_FOR_ACTIVATION && + ultramech_moby->state != ULTRAMECH_DEAD_WAIT_FOR_RESET) { float z; ultramech_vars->fE8 += frame_time_sq * 30.0f; ultramech_moby->pos.f[2] -= ultramech_vars->fE8 - 2.0f; @@ -1029,7 +1034,8 @@ void process_ultramech_hits_and_update_target(void *ultramech_instance) { } code = FUN_00249d60(ultramech_moby, slot, &ultramech_vars->f20, 0, &kind, &impact, 0, 4); if (slot != 0) { - if (kind != HIT_CLASSIFICATION_NO_DAMAGE && (state = ultramech_moby->state) != 10 && state != ULTRAMECH_DEAD_WAIT_FOR_RESET && + if (kind != HIT_CLASSIFICATION_NO_DAMAGE && (state = ultramech_moby->state) != 10 && + state != ULTRAMECH_DEAD_WAIT_FOR_RESET && *(short *)(*(char **)(slot + 0x20) + 0xA6) != 0x350) { ultramech_vars->f20 -= impact; if (*(unsigned short *)(slot + 0x2A) == 0x100) diff --git a/src/overlays/l16/hero/apply_hero_ground_material_effects.c b/src/overlays/l16/hero/apply_hero_ground_material_effects.c index 4bb5844669..3af666de02 100644 --- a/src/overlays/l16/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l16/hero/apply_hero_ground_material_effects.c @@ -300,7 +300,8 @@ void update_hero_ground_contact(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || + if (hero.ground_slope.f <= 0.87266463f || + hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = HH.moby; @@ -587,7 +588,8 @@ void integrate_hero_motion(void) { player = (L16MovementPlayer *)((char *)position - 0x80); update_hero_attachment(player->physics_mode, (char *)position + 0x70, (char *)position + 0x10); /* Limit the velocity by state and mode. Inside an arm `position` moves on to the velocity; it is formed again below. */ - if (player->state == HERO_STATE_RISE_THEN_FALL_WITH_AIRBORNE_HIT_QUERY || player->state == HERO_STATE_WRENCH_SLAM) { + if (player->state == HERO_STATE_RISE_THEN_FALL_WITH_AIRBORNE_HIT_QUERY || + player->state == HERO_STATE_WRENCH_SLAM) { float limit; float *limited_velocity; diff --git a/src/overlays/l16/hero/hero_set_state.c b/src/overlays/l16/hero/hero_set_state.c index e256051af0..e0852737de 100644 --- a/src/overlays/l16/hero/hero_set_state.c +++ b/src/overlays/l16/hero/hero_set_state.c @@ -89,7 +89,8 @@ int hero_set_state(int requested_state, int b) { float vec[4]; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L16_0015F5C4 == 2 || D_L16_0015F5C4 == 6) && b != 2) @@ -97,8 +98,16 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -1185,7 +1194,8 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; diff --git a/src/overlays/l16/hero/update_hero_motion_for_current_state.c b/src/overlays/l16/hero/update_hero_motion_for_current_state.c index e3d6553f9f..0b768f8d5b 100644 --- a/src/overlays/l16/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l16/hero/update_hero_motion_for_current_state.c @@ -726,8 +726,8 @@ void update_hero_motion_for_current_state(void) { build_spherical_offset( &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { - f32 sp = - hero.ground_speed * vector_length_xyz_cf(swim_animation_speed_profile, 0x1E) * 5.0f; + f32 sp = hero.ground_speed * + vector_length_xyz_cf(swim_animation_speed_profile, 0x1E) * 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -855,8 +855,8 @@ void update_hero_motion_for_current_state(void) { } speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { - f32 sp = - hero.ground_speed * vector_length_xyz_cf(swim_animation_speed_profile, 0x1E) * 5.5f; + f32 sp = hero.ground_speed * + vector_length_xyz_cf(swim_animation_speed_profile, 0x1E) * 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; @@ -1883,7 +1883,8 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { diff --git a/src/overlays/l16/hero/update_hero_state_transitions.c b/src/overlays/l16/hero/update_hero_state_transitions.c index d79d64867c..79b1a80b33 100644 --- a/src/overlays/l16/hero/update_hero_state_transitions.c +++ b/src/overlays/l16/hero/update_hero_state_transitions.c @@ -196,8 +196,10 @@ void update_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L16_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; @@ -952,7 +954,8 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; diff --git a/src/overlays/l16/level_class_tables.c b/src/overlays/l16/level_class_tables.c index e9060aa13b..805ba38a82 100644 --- a/src/overlays/l16/level_class_tables.c +++ b/src/overlays/l16/level_class_tables.c @@ -20,7 +20,9 @@ #include "rnc/overlay/shared/vehicles.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" -s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" diff --git a/src/overlays/l16/mobys/path_walker.c b/src/overlays/l16/mobys/path_walker.c index 2a4129b1e7..cf0064da82 100644 --- a/src/overlays/l16/mobys/path_walker.c +++ b/src/overlays/l16/mobys/path_walker.c @@ -152,12 +152,13 @@ void path_walker_update(unsigned char *walker_moby) { height = random_float_between(path_walker_height_range_start_gp, path_walker_height_range_end_gp); if (walker_data->owner[0x31] != 0 && walker_data->countdown != 0) { - candidate_path_parameter = linked_walker_data->parameter - random_float_between(path_walker_gap_range_start_gp, - path_walker_gap_range_end_gp); + candidate_path_parameter = linked_walker_data->parameter - + random_float_between(path_walker_gap_range_start_gp, + path_walker_gap_range_end_gp); walker_data->countdown--; } else { candidate_path_parameter = walker_data->parameter + - path_walker_reposition_advance_rate_gp * frame_time; + path_walker_reposition_advance_rate_gp * frame_time; } if (candidate_path_parameter < 0.0f) { candidate_path_parameter += walker_data->period; diff --git a/src/overlays/l16/mobys/spinning_sprite_effect.c b/src/overlays/l16/mobys/spinning_sprite_effect.c index e71f09b683..1cda722c29 100644 --- a/src/overlays/l16/mobys/spinning_sprite_effect.c +++ b/src/overlays/l16/mobys/spinning_sprite_effect.c @@ -16,7 +16,10 @@ #include "rnc/world/collision/collision_line.h" #include "rnc/math/random.h" #include "rnc/overlay/shared/rendering/effects/particles.h" -unsigned char *spawn_timed_hero_relative_particle(u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); + +unsigned char *spawn_timed_hero_relative_particle( + u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); + #include "rnc/world/collision/ground_probe.h" /* updates the moby: initialises in state 0, then runs its motion in state 1 */ /* Ported from rac1-decomp (src/overlays/l16_kalebo3/vendor_002A50F0.c: func_L16_002CA848), where it is exact; names translated to the US level program. */ @@ -125,13 +128,13 @@ void draw_spinning_sprite_effect_sprites(struct Moby *moby) { col = fast_tween_color(0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - elapsed_cycle_fraction)); spawn_timed_hero_relative_particle(d, - col, - truncate_float_to_s32(sprite_data->a[i]) & 0xFF, - 0x35, - 1, - 2, - 0, - sprite_data->d[i]); + col, + truncate_float_to_s32(sprite_data->a[i]) & 0xFF, + 0x35, + 1, + 2, + 0, + sprite_data->d[i]); fast_vec_add(d, d, particle_position_step); } } diff --git a/src/overlays/l16/mobys/test_dummy.c b/src/overlays/l16/mobys/test_dummy.c index e05a6d3ee8..e6ff7d0b86 100644 --- a/src/overlays/l16/mobys/test_dummy.c +++ b/src/overlays/l16/mobys/test_dummy.c @@ -577,7 +577,8 @@ void update_test_dummy_damage_and_respawn(void *moby) { amount = 0.0f; dummy_hit_record = find_moby_hit(hit_moby, 0x330000, 0); hit_reaction(hit_moby, dummy_hit_record, &hit_data->health, 0, &status, &amount, 0, 4); - if (status != HIT_REACTION_STATUS_NO_DAMAGE && hit_moby->state != TEST_DUMMY_STATE_BURST && hit_moby->state != TEST_DUMMY_STATE_RESPAWN) { + if (status != HIT_REACTION_STATUS_NO_DAMAGE && hit_moby->state != TEST_DUMMY_STATE_BURST && + hit_moby->state != TEST_DUMMY_STATE_RESPAWN) { hit_data->health -= amount; if (hit_data->health <= 0.0f) { hit_moby->state = TEST_DUMMY_STATE_BURST; diff --git a/src/overlays/l16/mobys/wall_button_blocker.c b/src/overlays/l16/mobys/wall_button_blocker.c index ac926529ab..d58406dde8 100644 --- a/src/overlays/l16/mobys/wall_button_blocker.c +++ b/src/overlays/l16/mobys/wall_button_blocker.c @@ -44,7 +44,11 @@ void wall_button_blocker_update(struct Moby *moby) __asm__("FUN_L16_002e36e8"); /* Moby class 1387 */ void wall_button_blocker_update(struct Moby *moby) { - enum { WALL_BUTTON_BLOCKER_STATE_UNINITIALIZED = 0 , WALL_BUTTON_BLOCKER_STATE_INITIALIZED = 1 } ;float *rotation_scale_data = (float *)moby->pvars; + enum { + WALL_BUTTON_BLOCKER_STATE_UNINITIALIZED = 0, + WALL_BUTTON_BLOCKER_STATE_INITIALIZED = 1 + }; + float *rotation_scale_data = (float *)moby->pvars; if (moby->state == WALL_BUTTON_BLOCKER_STATE_UNINITIALIZED) { fast_vec_normalize(&moby->rot_row1, &moby->rot_row1, rotation_scale_data[0] * 0.25f); fast_vec_normalize(&moby->rot_row2, &moby->rot_row2, rotation_scale_data[1] * 0.25f); diff --git a/src/overlays/l17/hero/hero_set_state.c b/src/overlays/l17/hero/hero_set_state.c index 1d4cb339d5..6a454bc6c0 100644 --- a/src/overlays/l17/hero/hero_set_state.c +++ b/src/overlays/l17/hero/hero_set_state.c @@ -103,7 +103,8 @@ int hero_set_state(int requested_state, int b) { V4_21ED38 sampled_path_position; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L17_0015F5C4 == 2 || D_L17_0015F5C4 == 6) && b != 2) @@ -111,8 +112,16 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -1106,7 +1115,8 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; diff --git a/src/overlays/l17/hero/update_hero_motion_for_current_state.c b/src/overlays/l17/hero/update_hero_motion_for_current_state.c index 709c26a999..33812a25b0 100644 --- a/src/overlays/l17/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l17/hero/update_hero_motion_for_current_state.c @@ -1474,7 +1474,8 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2899,7 +2900,10 @@ void update_hero_motion_for_current_state(void) { s32 ok; tb = &D_L17_0017C528[hero.attack_record]; hero.target_speed = 0.0f; - if ((tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE ? 1 : tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) && hero.anim_frame < 5.5f) { + if ((tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE + ? 1 + : tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) && + hero.anim_frame < 5.5f) { hero.target_speed = frame_time * 3.5f; } if (hero.anim_changing == 0 && (f32)tb->f1C <= hero.anim_frame && @@ -2924,7 +2928,8 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { diff --git a/src/overlays/l17/hero/update_hero_state_transitions.c b/src/overlays/l17/hero/update_hero_state_transitions.c index 69623167dc..b438a4f6a3 100644 --- a/src/overlays/l17/hero/update_hero_state_transitions.c +++ b/src/overlays/l17/hero/update_hero_state_transitions.c @@ -199,8 +199,10 @@ void update_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L17_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0)) { switch (hero.vehicle_mode) { case HERO_VEHICLE_MODE_ON_FOOT: case 3: { @@ -1041,7 +1043,8 @@ void update_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; diff --git a/src/overlays/l17/level_class_tables.c b/src/overlays/l17/level_class_tables.c index 0d5abc6cee..d4e1e3c8c2 100644 --- a/src/overlays/l17/level_class_tables.c +++ b/src/overlays/l17/level_class_tables.c @@ -18,7 +18,9 @@ #include "rnc/overlay/shared/vehicles.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" -s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" diff --git a/src/overlays/l17/mobys/camera_box_watcher.c b/src/overlays/l17/mobys/camera_box_watcher.c index ea76e301e7..39a313fe9a 100644 --- a/src/overlays/l17/mobys/camera_box_watcher.c +++ b/src/overlays/l17/mobys/camera_box_watcher.c @@ -115,7 +115,8 @@ void fleet_camera_box_watcher_update(struct Moby *moby) { case CLIP_VOLUME_SEQUENCE_MONITOR_FOLLOWUP: { struct Hero *h = &hero; int hero_current_state = h->state.current; - if (hero_current_state == HERO_STATE_HURT_WITH_DISPLACEMENT_VELOCITY || hero_current_state == HERO_STATE_OPTIONAL_IDLE_ANIMATION) { + if (hero_current_state == HERO_STATE_HURT_WITH_DISPLACEMENT_VELOCITY || + hero_current_state == HERO_STATE_OPTIONAL_IDLE_ANIMATION) { pvars->unk6C = 0; } else if (is_point_inside_clip_volume(&h->motion.pos, pvars->unk64) || is_point_inside_clip_volume(&h->motion.pos, pvars->unk68)) { diff --git a/src/overlays/l17/mobys/dreks_fleet_turret.c b/src/overlays/l17/mobys/dreks_fleet_turret.c index 175db88d97..d529de15d6 100644 --- a/src/overlays/l17/mobys/dreks_fleet_turret.c +++ b/src/overlays/l17/mobys/dreks_fleet_turret.c @@ -326,7 +326,8 @@ void process_dreks_fleet_turret_hits(struct Moby *turret_moby) { hit_animation_state = turret_vars + 0x60; hit_reaction( turret_moby, hit_record, turret_vars + 0x20, 0, &hit_reaction_status, &fv, 0, 4); - if (hit_reaction_status != HIT_REACTION_NO_DAMAGE && turret_moby->state != FLEET_TURRET_DESTROY) { + if (hit_reaction_status != HIT_REACTION_NO_DAMAGE && + turret_moby->state != FLEET_TURRET_DESTROY) { float remaining_value = *(float *)(turret_vars + 0x20) - fv; *(float *)(turret_vars + 0x20) = remaining_value; depletion_status = FLEET_TURRET_NOT_DEPLETED; diff --git a/src/overlays/l17/mobys/fighter_jet.c b/src/overlays/l17/mobys/fighter_jet.c index 4074fdf563..5f8266079a 100644 --- a/src/overlays/l17/mobys/fighter_jet.c +++ b/src/overlays/l17/mobys/fighter_jet.c @@ -1771,7 +1771,9 @@ void fighter_jet_update(ShipMoby *moby) { if (moby != 0) { ship_vars = (ShipVars *)moby->vars; fast_dec_timer(&ship_vars->timerDC); - if (moby->state != FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY && moby->state != FIGHTER_JET_STATE_WAIT_FOR_BOARDING && moby->state != FIGHTER_JET_STATE_BOARDING_FADE) { + if (moby->state != FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY && + moby->state != FIGHTER_JET_STATE_WAIT_FOR_BOARDING && + moby->state != FIGHTER_JET_STATE_BOARDING_FADE) { hit = (ShipHit *)find_moby_hit(moby, 0x30001, 0); if (hit != 0 && moby->state == FIGHTER_JET_STATE_PILOTED_FLIGHT) { struct Hero *g = &hero; diff --git a/src/overlays/l17/mobys/fleet_backdrop.c b/src/overlays/l17/mobys/fleet_backdrop.c index 8e8c54398f..645dc7b6a2 100644 --- a/src/overlays/l17/mobys/fleet_backdrop.c +++ b/src/overlays/l17/mobys/fleet_backdrop.c @@ -198,7 +198,11 @@ void fleet_backdrop_animation_update(struct Moby *moby) __asm__("FUN_L17_002f384 /* Moby class 1772 */ void fleet_backdrop_animation_update(struct Moby *moby) { - enum { FLEET_BACKDROP_STATE_UNINITIALIZED = 0 , FLEET_BACKDROP_STATE_INITIALIZED = 1 } ;FleetBackdropAnimationVars *moby_pvars = (FleetBackdropAnimationVars *)moby->pvars; + enum { + FLEET_BACKDROP_STATE_UNINITIALIZED = 0, + FLEET_BACKDROP_STATE_INITIALIZED = 1 + }; + FleetBackdropAnimationVars *moby_pvars = (FleetBackdropAnimationVars *)moby->pvars; float offset_accumulator[4]; float pvar_angle_offset[4]; float vector_sum[4]; diff --git a/src/overlays/l17/mobys/magnet_elevator.c b/src/overlays/l17/mobys/magnet_elevator.c index 85e4a1c130..2dd13bf6ec 100644 --- a/src/overlays/l17/mobys/magnet_elevator.c +++ b/src/overlays/l17/mobys/magnet_elevator.c @@ -122,12 +122,13 @@ void magnet_elevator_update(struct Moby *moby) { frame_time * 4.0f); if ((*(float *)((char *)(state) + (0x70))) < 1.0f) { float remaining_camera_blend_ratio = (1.0f - (*(float *)((char *)(state) + (0x70)))) / - (1.0f - previous_camera_blend_progress); + (1.0f - previous_camera_blend_progress); char *camera_pose_base; FUN_L17_002ee9c0_c(moby, (char *)camera_position, (char *)camera_rotation); fast_vec_sub(camera_position_offset, D_L17_001676C0, camera_position); camera_pose_base = D_L17_001676C0 - 0x140; - fast_vec_scale(camera_position_offset, camera_position_offset, remaining_camera_blend_ratio); + fast_vec_scale( + camera_position_offset, camera_position_offset, remaining_camera_blend_ratio); fast_vec_add(camera_position, camera_position, camera_position_offset); camera_rotation[1] = fast_add_rotations( fast_subtract_rotations((*(float *)((char *)(camera_pose_base) + (0x154))), diff --git a/src/overlays/l17/mobys/robot_dog.c b/src/overlays/l17/mobys/robot_dog.c index 6b7332f2b0..0da5e116c7 100644 --- a/src/overlays/l17/mobys/robot_dog.c +++ b/src/overlays/l17/mobys/robot_dog.c @@ -226,7 +226,8 @@ void robot_dog_update(unsigned char *robot_dog_moby) { } break; case ROBOT_DOG_STATE_WAIT_FOR_DETECTION_TRIGGER: - if (robot_dog_vars->mode != ROBOT_DOG_DETECTION_LINE_BLOCKED && random_integer_below(0x1F) == 0) { + if (robot_dog_vars->mode != ROBOT_DOG_DETECTION_LINE_BLOCKED && + random_integer_below(0x1F) == 0) { robot_dog_moby[0x20] = 2; if (robot_dog_moby[0x53] != 1) { blend_moby_animation(robot_dog_moby, 1, 0, scale_game_frames(10)); @@ -306,7 +307,8 @@ void robot_dog_update(unsigned char *robot_dog_moby) { blend_moby_animation(robot_dog_moby, 7, 0, scale_game_frames(10)); } } - } else if (robot_dog_vars->t1E0 == 0 && robot_dog_vars->mode == ROBOT_DOG_DETECTION_LINE_BLOCKED) { + } else if (robot_dog_vars->t1E0 == 0 && + robot_dog_vars->mode == ROBOT_DOG_DETECTION_LINE_BLOCKED) { robot_dog_moby[0x20] = 3; if (robot_dog_moby[0x53] != 0) { clip_volume_id_or_animation_value = random_integer_below( diff --git a/src/overlays/l18/hero/hero_set_state.c b/src/overlays/l18/hero/hero_set_state.c index 6ced479a64..27c60c892c 100644 --- a/src/overlays/l18/hero/hero_set_state.c +++ b/src/overlays/l18/hero/hero_set_state.c @@ -76,7 +76,8 @@ int hero_set_state(int requested_state, int b) { float grind_direction_or_jump_probe_position[4]; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L18_0015F5C4 == 2 || D_L18_0015F5C4 == 6) && b != 2) @@ -84,8 +85,16 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -1002,7 +1011,8 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; diff --git a/src/overlays/l18/hero/process_hero_state_transitions.c b/src/overlays/l18/hero/process_hero_state_transitions.c index 5f43f0afdc..5166d486a4 100644 --- a/src/overlays/l18/hero/process_hero_state_transitions.c +++ b/src/overlays/l18/hero/process_hero_state_transitions.c @@ -196,8 +196,10 @@ void process_hero_state_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && hero_triangle_hud_activation_inhibit == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT || hero.vehicle_mode == 3)) { int id; @@ -949,7 +951,8 @@ void process_hero_state_transitions(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; diff --git a/src/overlays/l18/hero/update_hero_motion_for_current_state.c b/src/overlays/l18/hero/update_hero_motion_for_current_state.c index 84f377e3ca..cbb82489c9 100644 --- a/src/overlays/l18/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l18/hero/update_hero_motion_for_current_state.c @@ -682,8 +682,8 @@ void update_hero_motion_for_current_state(void) { build_spherical_offset( &hero.motion.velocity, hero.ground_speed, hero.motion.rot.f[2], yaw); } else if (hero.state.current == 0x33) { - f32 sp = - hero.ground_speed * vector_length_xyz_cf(hero_swim_speed_scale_data, 0x1E) * 5.0f; + f32 sp = hero.ground_speed * + vector_length_xyz_cf(hero_swim_speed_scale_data, 0x1E) * 5.0f; if (hero.state.prev == 0x35 && scale_game_frames(15) > hero.state_timer) { if (sp < frame_time * 4.5f) { sp = frame_time * 4.5f; @@ -814,8 +814,8 @@ void update_hero_motion_for_current_state(void) { } speed_step(frame_time_sq * 4.0f, frame_time_sq * 5.0f); { - f32 sp = - hero.ground_speed * vector_length_xyz_cf(hero_swim_speed_scale_data, 0x1E) * 5.5f; + f32 sp = hero.ground_speed * + vector_length_xyz_cf(hero_swim_speed_scale_data, 0x1E) * 5.5f; hero.motion.velocity.f[0] = fast_cos(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[1] = fast_sin(hero.motion.rot.f[2]) * sp; hero.motion.velocity.f[2] = 0.0f; @@ -1453,7 +1453,8 @@ void update_hero_motion_for_current_state(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { diff --git a/src/overlays/l18/level_class_tables.c b/src/overlays/l18/level_class_tables.c index fd33650535..f1ba4a4162 100644 --- a/src/overlays/l18/level_class_tables.c +++ b/src/overlays/l18/level_class_tables.c @@ -19,7 +19,9 @@ #include "rnc/overlay/shared/vehicles.h" #include "rnc/overlay/shared/vendor.h" #include "rnc/overlay/shared/weapons.h" -s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + +s32 get_morphoray_chicken_slot_record(s32) __asm__("FUN_L00_002caf40"); + #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" #include "rnc/overlay/shared/weapons/devastator.h" #include "rnc/overlay/shared/weapons/mine.h" diff --git a/src/overlays/l18/mobys/camera_transition.c b/src/overlays/l18/mobys/camera_transition.c index a9d9f6383f..621ad5f09c 100644 --- a/src/overlays/l18/mobys/camera_transition.c +++ b/src/overlays/l18/mobys/camera_transition.c @@ -71,7 +71,10 @@ void boss_camera_transition_update(struct Moby *moby) { STATE_INTERPOLATE_TRANSITION = 3, STATE_INTERPOLATE_TRANSITION_WITH_RAMP_UP = 4, STATE_POST_TRANSITION_RAMP_DOWN = 5 - } ; enum { STATE_IDLE = 1}; + }; + enum { + STATE_IDLE = 1 + }; BossCameraTransitionVars *transition_private_vars = (BossCameraTransitionVars *)moby->pvars; float transition_scratch_vectors[12]; switch (moby->state) { @@ -243,7 +246,10 @@ void start_camera_transition(struct Moby *moby, int transition_delay_frames, int transition_mode) { - enum { CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP = 2 } ;BossCameraTransitionVars *position_rotation_transition_vars = + enum { + CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP = 2 + }; + BossCameraTransitionVars *position_rotation_transition_vars = (BossCameraTransitionVars *)moby->pvars; *(int *)&position_rotation_transition_vars->unk60 = 0; position_rotation_transition_vars->unk64 = 0; @@ -284,7 +290,11 @@ float get_camera_transition_progress(Level18VendorFloatMoby *moby) { s32 classify_moby_state_two_or_three(const u8 *moby) __asm__("FUN_L18_002dfba0"); s32 classify_moby_state_two_or_three(const u8 *moby) { - enum { CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP = 2 , CAMERA_TRANSITION_STATE_INTERPOLATE_TRANSITION = 3 } ;u32 state = MOBY(moby)->state; + enum { + CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP = 2, + CAMERA_TRANSITION_STATE_INTERPOLATE_TRANSITION = 3 + }; + u32 state = MOBY(moby)->state; s32 state_classification = 2; if (state == CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP) { diff --git a/src/overlays/l18/mobys/drek_boss_electric_ball.c b/src/overlays/l18/mobys/drek_boss_electric_ball.c index faab9603ae..ed555e11c0 100644 --- a/src/overlays/l18/mobys/drek_boss_electric_ball.c +++ b/src/overlays/l18/mobys/drek_boss_electric_ball.c @@ -203,11 +203,13 @@ float homing_spark_quad_vertices[4][4][4] __asm__("D_L18_001D9B70") = { {0.0f, -3.0f, 3.0f, 1.0f}}, }; -extern s32 fast_tween_color_c(s32, s32, f32) __asm__("func_001FA6E0"); -extern s64 get_effect_texture_c(s32) __asm__("func_001F44B8"); -extern int l18_homing_spark_blend_minuend_selector __asm__("D_L18_00161EE4") __attribute__((sda)); -extern int l18_homing_spark_blend_subtrahend_selector __asm__("D_L18_00161EE8") __attribute__((sda)); -extern int l18_homing_spark_blend_alpha_factor_selector __asm__("D_L18_00161EEC") __attribute__((sda)); +extern s32 fast_tween_color_c(s32, s32, f32) __asm__("func_001FA6E0"); +extern s64 get_effect_texture_c(s32) __asm__("func_001F44B8"); +extern int l18_homing_spark_blend_minuend_selector __asm__("D_L18_00161EE4") __attribute__((sda)); +extern int l18_homing_spark_blend_subtrahend_selector __asm__("D_L18_00161EE8") + __attribute__((sda)); +extern int l18_homing_spark_blend_alpha_factor_selector __asm__("D_L18_00161EEC") + __attribute__((sda)); extern int l18_homing_spark_blend_addend_selector __asm__("D_L18_00161EF0") __attribute__((sda)); extern int D_L18_00161EF8 __attribute__((sda)); extern int l18_homing_spark_quad_texture_ids __asm__("D_L18_00161F08") __attribute__((sda)); @@ -223,24 +225,36 @@ void homing_spark_draw(char *moby) { clear_u64_value(quad_euler_angles); quad_euler_angles[2] = fast_arc_tan(l18_camera_lui.pos.f[0] - MOBY(moby)->pos.x, - l18_camera_lui.pos.f[1] - MOBY(moby)->pos.y); + l18_camera_lui.pos.f[1] - MOBY(moby)->pos.y); quad_euler_angles[1] = -fast_arc_tan(vector_distance_xy(moby + 0x10, &l18_camera_lui.pos.f[0]), - l18_camera_lui.pos.f[2] - MOBY(moby)->pos.z); + l18_camera_lui.pos.f[2] - MOBY(moby)->pos.z); euler_rotation_matrix(quad_transform_matrices[0][0], quad_euler_angles); euler_rotation_matrix(quad_transform_matrices[1][0], quad_euler_angles); - fast_vec_scale(quad_transform_matrices[1][1], quad_transform_matrices[1][1], *(float *)(homing_spark_private_vars + 0x24)); - fast_vec_scale(quad_transform_matrices[1][2], quad_transform_matrices[1][2], *(float *)(homing_spark_private_vars + 0x24)); + fast_vec_scale(quad_transform_matrices[1][1], + quad_transform_matrices[1][1], + *(float *)(homing_spark_private_vars + 0x24)); + fast_vec_scale(quad_transform_matrices[1][2], + quad_transform_matrices[1][2], + *(float *)(homing_spark_private_vars + 0x24)); qcopy(quad_transform_matrices[0][3], moby + 0x10); qcopy(quad_transform_matrices[1][3], moby + 0x10); quad_euler_angles[0] = *(float *)(homing_spark_private_vars + 0x2C); euler_rotation_matrix(quad_transform_matrices[2][0], quad_euler_angles); - fast_vec_scale(quad_transform_matrices[2][1], quad_transform_matrices[2][1], *(float *)(homing_spark_private_vars + 0x24)); - fast_vec_scale(quad_transform_matrices[2][2], quad_transform_matrices[2][2], *(float *)(homing_spark_private_vars + 0x24)); + fast_vec_scale(quad_transform_matrices[2][1], + quad_transform_matrices[2][1], + *(float *)(homing_spark_private_vars + 0x24)); + fast_vec_scale(quad_transform_matrices[2][2], + quad_transform_matrices[2][2], + *(float *)(homing_spark_private_vars + 0x24)); qcopy(quad_transform_matrices[2][3], moby + 0x10); quad_euler_angles[0] = *(float *)(homing_spark_private_vars + 0x30); euler_rotation_matrix(quad_transform_matrices[3][0], quad_euler_angles); - fast_vec_scale(quad_transform_matrices[3][1], quad_transform_matrices[3][1], *(float *)(homing_spark_private_vars + 0x24)); - fast_vec_scale(quad_transform_matrices[3][2], quad_transform_matrices[3][2], *(float *)(homing_spark_private_vars + 0x24)); + fast_vec_scale(quad_transform_matrices[3][1], + quad_transform_matrices[3][1], + *(float *)(homing_spark_private_vars + 0x24)); + fast_vec_scale(quad_transform_matrices[3][2], + quad_transform_matrices[3][2], + *(float *)(homing_spark_private_vars + 0x24)); qcopy(quad_transform_matrices[3][3], moby + 0x10); { int i; @@ -248,21 +262,25 @@ void homing_spark_draw(char *moby) { Pkt *quad_packet; for (i = 0; i < 4; i++) { { - long r = - ((long (*)(int))get_effect_texture_c)(((int *)&(*(short *)&l18_homing_spark_quad_texture_ids))[i]); + long r = ((long (*)(int))get_effect_texture_c)( + ((int *)&(*(short *)&l18_homing_spark_quad_texture_ids))[i]); quad_packet = &pkt[i]; quad_packet->b = r; } quad_packet->c = 0xFF9000000260; - quad_packet->d = (l18_homing_spark_blend_minuend_selector) | (long)(l18_homing_spark_blend_subtrahend_selector) << 2 | (long)(l18_homing_spark_blend_alpha_factor_selector) << 4 | - (long)(l18_homing_spark_blend_addend_selector) << 6 | 0x8000L << 24; + quad_packet->d = (l18_homing_spark_blend_minuend_selector) | + (long)(l18_homing_spark_blend_subtrahend_selector) << 2 | + (long)(l18_homing_spark_blend_alpha_factor_selector) << 4 | + (long)(l18_homing_spark_blend_addend_selector) << 6 | 0x8000L << 24; quad_packet->a = 0; for (j = 0; j < 4; j++) { pkt[i].uv[j][0] = homing_spark_quad_uvs[j][0]; pkt[i].uv[j][1] = homing_spark_quad_uvs[j][1]; if (i == 0) { - pkt[0].color[j] = fast_tween_color_c( - D_L18_00161EF8 & 0xFFFFFF, D_L18_00161EF8, *(float *)(homing_spark_private_vars + 0x24)); + pkt[0].color[j] = + fast_tween_color_c(D_L18_00161EF8 & 0xFFFFFF, + D_L18_00161EF8, + *(float *)(homing_spark_private_vars + 0x24)); } else { pkt[i].color[j] = ((int *)&(*(short *)&D_L18_00161EF8))[i]; } diff --git a/src/overlays/l18/mobys/drek_fight_missile.c b/src/overlays/l18/mobys/drek_fight_missile.c index 0a48e9deff..0a067a3099 100644 --- a/src/overlays/l18/mobys/drek_fight_missile.c +++ b/src/overlays/l18/mobys/drek_fight_missile.c @@ -122,7 +122,10 @@ typedef struct DrekFightMissileVars { /* Moby class 1355 */ void drek_fight_missile_update(struct Moby *moby) { - enum { DREK_MISSILE_WAIT_FOR_ACTIVATION = 1 } ;DrekFightMissileVars *missile_vars = (DrekFightMissileVars *)moby->pvars; + enum { + DREK_MISSILE_WAIT_FOR_ACTIVATION = 1 + }; + DrekFightMissileVars *missile_vars = (DrekFightMissileVars *)moby->pvars; if (moby->state != DREK_MISSILE_WAIT_TO_EXPLODE) { moby->rot.x = fast_add_rotations(moby->rot.x, *(float *)&l18_drek_missile_roll_rate_degrees_gp * @@ -163,9 +166,11 @@ void drek_fight_missile_update(struct Moby *moby) { } moby->state = DREK_MISSILE_DIVE; missile_vars->unk130[0] = - fast_cos(moby->rot.z) * (*(float *)&l18_drek_missile_wander_horizontal_speed_gp * frame_time); + fast_cos(moby->rot.z) * + (*(float *)&l18_drek_missile_wander_horizontal_speed_gp * frame_time); missile_vars->unk130[1] = - fast_sin(moby->rot.z) * (*(float *)&l18_drek_missile_wander_horizontal_speed_gp * frame_time); + fast_sin(moby->rot.z) * + (*(float *)&l18_drek_missile_wander_horizontal_speed_gp * frame_time); missile_vars->unk130[2] = missile_vars->unk144; missile_vars->unk14C = 0; break; @@ -310,8 +315,10 @@ int update_drek_fight_missile_wander_movement(char *moby, float *wander_target_p *(float *)(missile_vars + 0x150), *(float *)(missile_vars + 0x150), *(float *)(missile_vars + 0x154)); - MOBY(moby)->pos.x += fast_cos(MOBY(moby)->rot.z) * (*(float *)&l18_drek_missile_wander_horizontal_speed_gp * frame_time); - MOBY(moby)->pos.y += fast_sin(MOBY(moby)->rot.z) * (*(float *)&l18_drek_missile_wander_horizontal_speed_gp * frame_time); + MOBY(moby)->pos.x += fast_cos(MOBY(moby)->rot.z) * + (*(float *)&l18_drek_missile_wander_horizontal_speed_gp * frame_time); + MOBY(moby)->pos.y += fast_sin(MOBY(moby)->rot.z) * + (*(float *)&l18_drek_missile_wander_horizontal_speed_gp * frame_time); FUN_00213f38_c((float *)&MOBY(moby)->pos.z, (float *)(missile_vars + 0x144), wander_target_position[2], diff --git a/src/overlays/l18/mobys/drek_final_boss_robot.c b/src/overlays/l18/mobys/drek_final_boss_robot.c index 75baddb9ef..8ff5e7b2ac 100644 --- a/src/overlays/l18/mobys/drek_final_boss_robot.c +++ b/src/overlays/l18/mobys/drek_final_boss_robot.c @@ -330,7 +330,8 @@ extern int launch_first_idle_group_class_0772_moby(int idx, extern int count_group_gadgebots_not_in_state_8(int idx) __asm__("FUN_L18_002fc7e0"); extern int random_integer_below(int) __asm__("FUN_00213260"); extern s32 allocate_voice_for_target_entry(s32, s32, void *) __asm__("func_0022DA68"); -extern short l18_drek_boss_hero_follow_default_radius __asm__("D_L18_00162378") __attribute__((sda)); +extern short l18_drek_boss_hero_follow_default_radius __asm__("D_L18_00162378") + __attribute__((sda)); extern short l18_drek_boss_scene_2_started_gp __asm__("D_L18_00162360") __attribute__((sda)); extern short D_L18_00162390 __attribute__((sda)); extern short l18_drek_boss_paired_transition_duration_frames_gp __asm__("D_L18_00162394") @@ -1852,7 +1853,8 @@ void update_drek_boss_damage_and_phase_transitions(char *moby) { moby, hit_record, boss_data + 0x20, 0, &hit_processing_status, &step, 0, 4); if (hit_processing_status != HIT_PROCESSING_NO_DAMAGE) { int type = MOBY(moby)->state; - if ((type >= DREK_BOSS_SELECT_NEXT_ACTION && type <= DREK_BOSS_FOLLOW_HERO) || type == DREK_BOSS_CIRCLE_AND_FIRE_AT_HERO) { + if ((type >= DREK_BOSS_SELECT_NEXT_ACTION && type <= DREK_BOSS_FOLLOW_HERO) || + type == DREK_BOSS_CIRCLE_AND_FIRE_AT_HERO) { char *o = *(char **)(hit_record + 0x20); if (o != 0) { short h = *(short *)(o + 0xA6); @@ -2138,11 +2140,12 @@ int advance_drek_boss_planar_position_toward_target(char *moby, /* Moves a moby's follow distance toward a target, clamped to a range, then applies it. */ /* Ported from rac1-decomp (src/overlays/l18_veldin2/vendor_002F2AE0.c: func_L18_002F7DC0), where it is exact; names translated to the US level program. */ -extern short l18_drek_boss_hero_follow_target_distance __asm__("D_L18_0016234C") __attribute__((sda)); -extern void FUN_L00_0025f730(void *a, float x); -int advance_drek_boss_planar_position_toward_target(char *moby, - float arg, - void *x) __asm__("FUN_L18_002f6878"); +extern short l18_drek_boss_hero_follow_target_distance __asm__("D_L18_0016234C") + __attribute__((sda)); +extern void FUN_L00_0025f730(void *a, float x); +int advance_drek_boss_planar_position_toward_target(char *moby, + float arg, + void *x) __asm__("FUN_L18_002f6878"); extern short drek_boss_hero_follow_mode_0f_radius_gp __asm__("D_L18_0016237C") __attribute__((sda)); @@ -2160,15 +2163,17 @@ void update_drek_boss_hero_follow_movement(struct Moby *moby) { FUN_L00_0025f730(follow_target_position, *(float *)&drek_boss_hero_follow_mode_0f_radius_gp); } else { - FUN_L00_0025f730(follow_target_position, *(float *)&l18_drek_boss_hero_follow_default_radius); + FUN_L00_0025f730(follow_target_position, + *(float *)&l18_drek_boss_hero_follow_default_radius); } fast_vec_add(follow_target_position, follow_target_position, D_L18_001600EC + (*(int *)(moby_vars + 0x344) << 7) + 0x30); follow_speed_limit = hero.motion.speed_xy; - follow_speed_limit += - (vector_distance_xy(&moby->pos, follow_target_position) - *(float *)&l18_drek_boss_hero_follow_target_distance) / - *(float *)&l18_drek_boss_hero_follow_target_distance * (frame_time * 4.75f); + follow_speed_limit += (vector_distance_xy(&moby->pos, follow_target_position) - + *(float *)&l18_drek_boss_hero_follow_target_distance) / + *(float *)&l18_drek_boss_hero_follow_target_distance * + (frame_time * 4.75f); hi = frame_time * 20.0f; lo = frame_time * 4.75f; if (follow_speed_limit > hi) { @@ -2472,7 +2477,8 @@ extern short l18_drek_boss_scalar_acceleration_and_braking_gp __asm__("D_L18_001 #include "rnc/overlay/l18/mobys/drek_final_boss_robot_data/update_drek_boss_state_dependent_scalars_3.h" -extern float l18_drek_boss_second_scalar_near_node_follow_target_gp __asm__("D_L18_001623DC") __attribute__((sda)); +extern float l18_drek_boss_second_scalar_near_node_follow_target_gp __asm__("D_L18_001623DC") + __attribute__((sda)); #include "rnc/overlay/l18/mobys/drek_final_boss_robot_data/update_drek_boss_state_dependent_scalars_2.h" @@ -2549,7 +2555,10 @@ void update_drek_boss_state_dependent_scalars(char *moby) { second_scalar_value = (float *)(selected_scalar_record + 0x38); first_scalar_update_state = (float *)(boss_data + 0x378); second_scalar_update_state = (float *)(boss_data + 0x37c); - } else if (boss_state == DREK_BOSS_INITIALIZE || boss_state == DREK_BOSS_FOLLOW_PATH_AND_FIRE_AT_MOBYS || boss_state == DREK_BOSS_FINISH_PATH_AND_WAIT_FOR_HERO || boss_state == DREK_BOSS_WAIT_FOR_ENCOUNTER_TRIGGER || + } else if (boss_state == DREK_BOSS_INITIALIZE || + boss_state == DREK_BOSS_FOLLOW_PATH_AND_FIRE_AT_MOBYS || + boss_state == DREK_BOSS_FINISH_PATH_AND_WAIT_FOR_HERO || + boss_state == DREK_BOSS_WAIT_FOR_ENCOUNTER_TRIGGER || boss_state == DREK_BOSS_RUN_ENDING_SEQUENCE) { int i; char *g; diff --git a/src/overlays/l18/mobys/floating_platform.c b/src/overlays/l18/mobys/floating_platform.c index 7143450a6a..5ae0ec6eb6 100644 --- a/src/overlays/l18/mobys/floating_platform.c +++ b/src/overlays/l18/mobys/floating_platform.c @@ -281,7 +281,8 @@ spawn_spark(void *, void *, void *, int, int, int, int, int, int) __asm__("FUN_0 extern int FUN_001fa6e0(int, int, float); extern short floating_platform_spark_first_vector_length_base_rate_gp __asm__("D_L18_00161A68") __attribute__((sda)); -extern short l18_floating_platform_spark_second_vector_length_base_rate_gp __asm__("D_L18_00161A6C") __attribute__((sda)); +extern short l18_floating_platform_spark_second_vector_length_base_rate_gp __asm__("D_L18_00161A6C") + __attribute__((sda)); extern short floating_platform_spark_second_vector_downward_z_rate_gp __asm__("D_L18_00161A70") __attribute__((sda)); extern short diff --git a/src/overlays/l18/mobys/gadgebot.c b/src/overlays/l18/mobys/gadgebot.c index a1e952837e..9a2e7b67b0 100644 --- a/src/overlays/l18/mobys/gadgebot.c +++ b/src/overlays/l18/mobys/gadgebot.c @@ -324,7 +324,8 @@ void update_gadgebot_damage_target_and_glow(struct Moby *moby) { if (moby->state == GADGEBOT_INITIALIZE || moby->state == GADGEBOT_IDLE) { return; } - if (moby->state != GADGEBOT_SUCK_CANNON_SUCTION && game_frame != gadgebot_joint_glows_last_queued_frame_gp) { + if (moby->state != GADGEBOT_SUCK_CANNON_SUCTION && + game_frame != gadgebot_joint_glows_last_queued_frame_gp) { gadgebot_joint_glows_last_queued_frame_gp = game_frame; add_draw_callback(draw_group_gadgebot_joint_glows, moby); } diff --git a/src/overlays/l18/mobys/inert_moby.c b/src/overlays/l18/mobys/inert_moby.c index 70b69303cf..3997bc5322 100644 --- a/src/overlays/l18/mobys/inert_moby.c +++ b/src/overlays/l18/mobys/inert_moby.c @@ -49,7 +49,11 @@ void inert_moby_update(Level18VendorMobyShort *moby) __asm__("FUN_L18_002f7ab0") /* Moby class 1432 */ void inert_moby_update(Level18VendorMobyShort *moby) { - enum { INERT_MOBY_STATE_UNINITIALIZED = 0 , INERT_MOBY_STATE_INITIALIZED = 1 } ;if (moby->state == INERT_MOBY_STATE_UNINITIALIZED) { + enum { + INERT_MOBY_STATE_UNINITIALIZED = 0, + INERT_MOBY_STATE_INITIALIZED = 1 + }; + if (moby->state == INERT_MOBY_STATE_UNINITIALIZED) { moby->state = INERT_MOBY_STATE_INITIALIZED; moby->flags |= 3; moby->substate = 0; diff --git a/src/overlays/l18/mobys/rocket.c b/src/overlays/l18/mobys/rocket.c index a598b10447..ed68e25168 100644 --- a/src/overlays/l18/mobys/rocket.c +++ b/src/overlays/l18/mobys/rocket.c @@ -48,7 +48,10 @@ void rocket_moby_update(struct Moby *moby) __asm__("FUN_L18_002d5050"); /* Moby class 564 */ void rocket_moby_update(struct Moby *moby) { - enum { ROCKET_STATE_FLYING = 0 } ;L18D *moby_vars = (L18D *)moby->pvars; + enum { + ROCKET_STATE_FLYING = 0 + }; + L18D *moby_vars = (L18D *)moby->pvars; float target_movement_step[4]; float movement_step[4]; float rotation_angles[4]; diff --git a/src/overlays/l18/mobys/thruster_pack_lock_red.c b/src/overlays/l18/mobys/thruster_pack_lock_red.c index cfa429f6b5..1950a93151 100644 --- a/src/overlays/l18/mobys/thruster_pack_lock_red.c +++ b/src/overlays/l18/mobys/thruster_pack_lock_red.c @@ -56,7 +56,10 @@ void thruster_pack_lock_red_update(struct Moby *moby) { STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT = 3, STATE_WAIT_FOR_DEPRESSION_TRIGGER = 4, STATE_SETTLE_DEPRESSED_HEIGHT = 5 - } ; enum { STATE_DEPRESSED_HEIGHT_SETTLED = 6}; + }; + enum { + STATE_DEPRESSED_HEIGHT_SETTLED = 6 + }; char *thruster_pack_lock_red_private_vars = (char *)moby->pvars; int index; @@ -210,7 +213,8 @@ int poll_moby_state_and_rearm(struct Moby *moby) { moby->state = THRUSTER_PACK_LOCK_RED_STATE_APPROACH_CONFIGURED_HEIGHT; return 1; } - if (moby->state == THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER && moby_private_vars[0x6C / 4] == 0) { + if (moby->state == THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER && + moby_private_vars[0x6C / 4] == 0) { return -1; } return 0; diff --git a/src/overlays/shared/camera/follow_camera_setup.c b/src/overlays/shared/camera/follow_camera_setup.c index a42ddd8dbe..1d78481a9c 100644 --- a/src/overlays/shared/camera/follow_camera_setup.c +++ b/src/overlays/shared/camera/follow_camera_setup.c @@ -24,10 +24,11 @@ extern float D_L00_0015EF44_macro __asm__("D_L00_0015EF44") MACRO_ADDR; extern unsigned char *D_L00_00168FC0_lui __asm__("D_L00_00168FC0") NOT_SDA; extern int D_L00_0015EF60_macro __asm__("D_L00_0015EF60") MACRO_ADDR; extern float D_L00_00161CA0_gp __asm__("D_L00_00161CA0") __attribute__((sda)); -extern float l00_follow_camera_collision_probe_step_growth_factor __asm__("D_L00_00161CDC") __attribute__((sda)); -extern float l00_follow_camera_collision_probe_count __asm__("D_L00_00161CE0") __attribute__((sda)); -extern float l00_follow_camera_collision_probe_scale __asm__("D_L00_00161CE4") __attribute__((sda)); -extern float D_L00_00161D1C_gp __asm__("D_L00_00161D1C") __attribute__((sda)); +extern float l00_follow_camera_collision_probe_step_growth_factor __asm__("D_L00_00161CDC") + __attribute__((sda)); +extern float l00_follow_camera_collision_probe_count __asm__("D_L00_00161CE0") __attribute__((sda)); +extern float l00_follow_camera_collision_probe_scale __asm__("D_L00_00161CE4") __attribute__((sda)); +extern float D_L00_00161D1C_gp __asm__("D_L00_00161D1C") __attribute__((sda)); typedef struct { char pad0[0x2C]; @@ -943,8 +944,8 @@ int update_follow_camera_orbit_after_collision(unsigned char *camera_moby, return sphere_collision_found; } adjusted_orbit_length = fast_vec_length(A); - if (hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && absolute_float(D_0013CA40_lui[0]) > 0.05f && - sphere_collision_found) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_GIANT_CLANK && + absolute_float(D_0013CA40_lui[0]) > 0.05f && sphere_collision_found) { adjusted_orbit_length -= follow_camera_collision_retraction_rate_gp * frame_scale; *(short *)(B + 0x34) = scale_game_frames(0x884); } diff --git a/src/overlays/shared/camera/follow_camera_springs.c b/src/overlays/shared/camera/follow_camera_springs.c index 7bd90f3d87..70daee4200 100644 --- a/src/overlays/shared/camera/follow_camera_springs.c +++ b/src/overlays/shared/camera/follow_camera_springs.c @@ -111,14 +111,16 @@ extern float D_L00_00166EEC NOT_SDA; extern s32 D_L00_00161D24_gp __asm__("D_L00_00161D24") __attribute__((sda)); extern short follow_camera_ground_aware_focus_transition_frames_gp __asm__("D_L00_00161D38") __attribute__((sda)); -extern short l00_follow_camera_ground_focus_exit_transition_frames_gp __asm__("D_L00_00161D3C") __attribute__((sda)); +extern short l00_follow_camera_ground_focus_exit_transition_frames_gp __asm__("D_L00_00161D3C") + __attribute__((sda)); extern short D_L00_00161D40_gp __asm__("D_L00_00161D40") __attribute__((sda)); extern short follow_camera_blend_out_focus_offset_gp __asm__("D_L00_00161D48") __attribute__((sda)); extern short follow_camera_project_hero_focus_blend_base_frames_gp __asm__("D_L00_00161D4C") __attribute__((sda)); extern short follow_camera_focus_blend_transition_frames_gp __asm__("D_L00_00161D50") __attribute__((sda)); -extern short l00_follow_camera_post_blend_focus_transition_frames_gp __asm__("D_L00_00161D54") __attribute__((sda)); +extern short l00_follow_camera_post_blend_focus_transition_frames_gp __asm__("D_L00_00161D54") + __attribute__((sda)); extern short follow_camera_project_hero_focus_offset_gp __asm__("D_L00_00161D58") __attribute__((sda)); extern short follow_camera_hold_focus_blend_base_frames_gp __asm__("D_L00_00161D5C") @@ -963,7 +965,8 @@ void FUN_L00_002e4930(char *camera) { if (p->state.control_mode == 2) { attach_state->prev = attach_state->state; attach_state->state = 1; - attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); + attach_state->timer = + scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); attach_state->invTimer = 1.0f / convert_integer_to_float(attach_state->timer); return; } @@ -972,12 +975,14 @@ void FUN_L00_002e4930(char *camera) { if (D_001413DC == 2) { attach_state->prev = 4; attach_state->state = 1; - attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); + attach_state->timer = + scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); attach_state->invTimer = 1.0f / convert_integer_to_float(attach_state->timer); } else { attach_state->prev = 4; attach_state->state = 0; - attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); + attach_state->timer = + scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); attach_state->invTimer = 1.0f / convert_integer_to_float(attach_state->timer); } return; @@ -1015,14 +1020,16 @@ void FUN_L00_002e4930(char *camera) { if (attach_state->state == 6 && camera_secondary_mode_lui != 0xB) { attach_state->prev = attach_state->state; attach_state->state = 0; - attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); + attach_state->timer = + scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); attach_state->invTimer = 1.0f / convert_integer_to_float(attach_state->timer); return; } if ((attach_state->state == 3 || attach_state->state == 5) && D_001413DC != 4) { attach_state->prev = attach_state->state; attach_state->state = 0; - attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); + attach_state->timer = + scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); attach_state->invTimer = 1.0f / convert_integer_to_float(attach_state->timer); return; } @@ -1039,7 +1046,8 @@ void FUN_L00_002e4930(char *camera) { to_one: attach_state->prev = attach_state->state; attach_state->state = 1; - attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); + attach_state->timer = + scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); r = 1.0f / convert_integer_to_float(attach_state->timer); camera_timer_base_frames = *(int *)&D_L00_00161D24_gp; attach_state->invTimer = r; @@ -1059,7 +1067,8 @@ void FUN_L00_002e4930(char *camera) { if (attach_state->state == 0xA && FUN_001f9770_c2(&attach_state->moveTimer)) { attach_state->prev = attach_state->state; attach_state->state = 0; - attach_state->timer = scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); + attach_state->timer = + scale_game_frames(*(int *)&l00_follow_camera_post_blend_focus_transition_frames_gp); attach_state->invTimer = 1.0f / convert_integer_to_float(attach_state->timer); return; } @@ -1299,7 +1308,10 @@ void follow_camera_transition(O002e5730 *camera, void *input_offset) { compute_follow_camera_target_position( camera, input_offset, &target_position, attach_state->xc4); attach_mode = attach_state->xc4; - if (attach_mode == CAM_ATTACH_BLEND_TO_PROJECT_HERO_FOCUS_VELOCITY || attach_mode == CAM_ATTACH_BLEND_FOCUS_VELOCITY_WITH_HOLD_TRANSITION || attach_mode == CAM_ATTACH_BLEND_OUT_FOCUS_VELOCITY || attach_mode == CAM_ATTACH_BLEND_BACK_FOCUS_VELOCITY || + if (attach_mode == CAM_ATTACH_BLEND_TO_PROJECT_HERO_FOCUS_VELOCITY || + attach_mode == CAM_ATTACH_BLEND_FOCUS_VELOCITY_WITH_HOLD_TRANSITION || + attach_mode == CAM_ATTACH_BLEND_OUT_FOCUS_VELOCITY || + attach_mode == CAM_ATTACH_BLEND_BACK_FOCUS_VELOCITY || attach_mode == CAM_ATTACH_HERO_POSITION_BASE) { x = follow_camera_position_transition_end_stiffness_gp + (follow_camera_position_default_stiffness_gp - diff --git a/src/overlays/shared/camera/grindrail_camera.c b/src/overlays/shared/camera/grindrail_camera.c index f670014968..da0e347c3f 100644 --- a/src/overlays/shared/camera/grindrail_camera.c +++ b/src/overlays/shared/camera/grindrail_camera.c @@ -495,7 +495,8 @@ void update_camera_position_and_orientation_from_paths(Cam *camera_to_update) { 20.0f, 1.0f, 0.0f); - if (current_level_index_macro == 0xE && camera_path_preset->kind == CAMERA_PRESET_KIND_RAIL_SEGMENT_SYNC) { + if (current_level_index_macro == 0xE && + camera_path_preset->kind == CAMERA_PRESET_KIND_RAIL_SEGMENT_SYNC) { sample_path(path, delta, &segment, &fraction, lead, 0); } else { sample_path(path, delta, &segment, &fraction, lead, 1); diff --git a/src/overlays/shared/camera/moby_controlled_camera.c b/src/overlays/shared/camera/moby_controlled_camera.c index 8c01d8f173..5498f35ca3 100644 --- a/src/overlays/shared/camera/moby_controlled_camera.c +++ b/src/overlays/shared/camera/moby_controlled_camera.c @@ -72,11 +72,11 @@ int test_moby_camera_control_activation(char *moby) __asm__("FUN_L02_002fb648"); int test_moby_camera_control_activation(char *moby) { char *special = D_L02_001674DC; - MobyCameraControl *camera_control_entry = - (MobyCameraControl *)(*(char **)(l02_moby_record_table + *(short *)(moby + 0x84) * 32 + 0x1c)); - char *target = camera_control_entry->target; - int *activation_path_record; - int hero_containment_result; + MobyCameraControl *camera_control_entry = (MobyCameraControl *)(*( + char **)(l02_moby_record_table + *(short *)(moby + 0x84) * 32 + 0x1c)); + char *target = camera_control_entry->target; + int *activation_path_record; + int hero_containment_result; if (special != 0 && special == target) { return 1; @@ -191,23 +191,23 @@ int test_moby_camera_target_angle_limits(char *moby, float residual_angle_limit_ void apply_moby_camera_control(char *moby) __asm__("FUN_L02_002fb9c8"); void apply_moby_camera_control(char *moby) { - MobyCameraControl *moby_camera_control_record = - (MobyCameraControl *)(*(char **)(l02_moby_record_table + *(short *)(moby + 0x84) * 32 + 0x1c)); - char *target; - unsigned short *group; - int id; - int index; - int duration; - int count; - int end; - int frames; - int active; - int hit; - float scale; - float angle; - float heading; - float amount; - float heading_vector[3]; + MobyCameraControl *moby_camera_control_record = (MobyCameraControl *)(*( + char **)(l02_moby_record_table + *(short *)(moby + 0x84) * 32 + 0x1c)); + char *target; + unsigned short *group; + int id; + int index; + int duration; + int count; + int end; + int frames; + int active; + int hit; + float scale; + float angle; + float heading; + float amount; + float heading_vector[3]; if (moby_camera_control_record->unk50 != 0) { moby_camera_control_record->unk20 = 0; diff --git a/src/overlays/shared/camera/path_flythrough_camera.c b/src/overlays/shared/camera/path_flythrough_camera.c index 1d09458eba..863466ac94 100644 --- a/src/overlays/shared/camera/path_flythrough_camera.c +++ b/src/overlays/shared/camera/path_flythrough_camera.c @@ -34,16 +34,20 @@ extern int point_in_path_xy(float *, float *, int) __asm__("FUN_L00_00259740"); int check_descriptor_hero_trigger(char *moby) __asm__("FUN_L10_002f5a78"); int check_descriptor_hero_trigger(char *moby) { - unsigned char *trigger_descriptor_record = *(unsigned char **)(l10_descriptor_table + *(short *)(moby + 0x84) * 32 + 0x1C); + unsigned char *trigger_descriptor_record = + *(unsigned char **)(l10_descriptor_table + *(short *)(moby + 0x84) * 32 + 0x1C); if (*(int *)(trigger_descriptor_record + 0x0C) >= 0) { - if (is_point_inside_clip_volume(&hero.motion.pos, *(int *)(trigger_descriptor_record + 0x0C))) + if (is_point_inside_clip_volume(&hero.motion.pos, + *(int *)(trigger_descriptor_record + 0x0C))) return 1; } else if (*(int *)(trigger_descriptor_record + 0x10) >= 0) { - if (test_point_in_transformed_unit_cylinder(&hero.motion.pos, *(int *)(trigger_descriptor_record + 0x10))) + if (test_point_in_transformed_unit_cylinder(&hero.motion.pos, + *(int *)(trigger_descriptor_record + 0x10))) return 1; } else if (*(int *)(trigger_descriptor_record + 0x08) >= 0) { - if (test_point_in_transformed_unit_sphere((float *)(&hero.motion.pos), *(int *)(trigger_descriptor_record + 0x08))) + if (test_point_in_transformed_unit_sphere((float *)(&hero.motion.pos), + *(int *)(trigger_descriptor_record + 0x08))) return 1; } else if (*(int *)(trigger_descriptor_record + 0x14) >= 0) { int i = *(int *)(trigger_descriptor_record + 0x14); @@ -89,8 +93,8 @@ extern VendorView_5f18 l10_camera_view __asm__("D_L10_0016CEC0"); void initialize_path_camera(struct UpdateCam *path_camera) __asm__("FUN_L10_002f5b58"); void initialize_path_camera(struct UpdateCam *path_camera) { - char *rec = *(char **)(l10_descriptor_table + path_camera->descriptor_index * 32 + 0x1C); - VendorCamRun_5f18 *run; + char *rec = *(char **)(l10_descriptor_table + path_camera->descriptor_index * 32 + 0x1C); + VendorCamRun_5f18 *run; VendorCamStops_5f18 *stops; f32 *fov; Vec4f *m1, *m2, *pos; diff --git a/src/overlays/shared/camera/scripted_camera.c b/src/overlays/shared/camera/scripted_camera.c index 0275d475f7..80af3f9737 100644 --- a/src/overlays/shared/camera/scripted_camera.c +++ b/src/overlays/shared/camera/scripted_camera.c @@ -130,7 +130,10 @@ void jet_mount(V_2eaaa0 *pa, V_2eaaa0 *pb, s32 mode, s32 transition_duration_fra void jet_end_mount(int mode) __asm__("FUN_L00_002eac18"); void jet_end_mount(int mode) { - enum { JET_END_MOUNT_REPOSITION_BEHIND_HERO = 0 } ;LevelCamera *camera_globals = &l00_camera_lui; + enum { + JET_END_MOUNT_REPOSITION_BEHIND_HERO = 0 + }; + LevelCamera *camera_globals = &l00_camera_lui; char *current_follow_camera = ((char *)camera_globals->unk180); initialize_camera_record_handoff_defaults(); if (mode == JET_END_MOUNT_REPOSITION_BEHIND_HERO) { diff --git a/src/overlays/shared/camera/swing_volume_camera.c b/src/overlays/shared/camera/swing_volume_camera.c index d146814ac8..c4b0bf0ae4 100644 --- a/src/overlays/shared/camera/swing_volume_camera.c +++ b/src/overlays/shared/camera/swing_volume_camera.c @@ -104,7 +104,8 @@ s32 volume_camera_swing_active(struct UpdateCam *swing_camera_record) { type = *(u16 *)¶ms->type; if (params->type == 2 && D_001413DC == 0x1A && params->timer > 0) { forced = 1; - } else if ((s16)type == SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST && hero_requested_camera_mode[0] == 3) { + } else if ((s16)type == SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST && + hero_requested_camera_mode[0] == 3) { forced = 0 < params->timer; } if (params->clip_volume >= 0 && @@ -132,7 +133,22 @@ s32 volume_camera_swing_active(struct UpdateCam *swing_camera_record) { void volume_camera_swing(struct UpdateCam *cam) __asm__("FUN_L00_002ec988"); void volume_camera_swing(struct UpdateCam *swing_camera_record) { - enum { SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END = 1 , SWING_CAMERA_TYPE_ONE_FRAME_SWING = 3 , SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST = 4 , SWING_CAMERA_TYPE_SNAP_ON_ENTRY = 5 , SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END = 10 } ; enum { SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE = 6 , SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE = 8 , SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END = 9} ; enum { SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY = 7} ;CameraVec gravity_offset_or_yaw_direction; + enum { + SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END = 1, + SWING_CAMERA_TYPE_ONE_FRAME_SWING = 3, + SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST = 4, + SWING_CAMERA_TYPE_SNAP_ON_ENTRY = 5, + SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END = 10 + }; + enum { + SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE = 6, + SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE = 8, + SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END = 9 + }; + enum { + SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY = 7 + }; + CameraVec gravity_offset_or_yaw_direction; SwingCameraParams *params; struct UpdateCam *rec; Vec4f *pos; @@ -148,10 +164,12 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { f32 lateral_spring_blend_fraction; params = camera_descriptors[swing_camera_record->descriptor_index].params; - if (params->type == SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE && FOLLOW_CAM_STATE(current_follow_cam)->tail.mode == 0) { + if (params->type == SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE && + FOLLOW_CAM_STATE(current_follow_cam)->tail.mode == 0) { return; } - if (params->type == SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE && FOLLOW_CAM_STATE(current_follow_cam)->tail.mode != 0) { + if (params->type == SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE && + FOLLOW_CAM_STATE(current_follow_cam)->tail.mode != 0) { return; } if (volume_camera_swing_active(swing_camera_record) == 0) { @@ -247,7 +265,10 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { params->timer = scale_game_frames(200); } FUN_L00_002e8620(); - } else if (params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY || params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END || params->type == SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END) { + } else if (params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || + params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY || + params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END || + params->type == SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END) { /* Moving the left stick skips to the end of the swing. */ struct PadState *pad = &controller_state; if (pad->analog[0] != 0.0f || pad->analog[1] != 0.0f) { @@ -281,12 +302,16 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { fast_sin(camera_descriptors[swing_camera_record->descriptor_index].yaw); *(s32 *)&gravity_offset_or_yaw_direction[2] = 0; swing = params->swing * 0.017453292f * (params->timer / total); - if ((params->type != SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END && params->type != SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY && params->type != SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END) || at_end == 0) { + if ((params->type != SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END && + params->type != SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY && + params->type != SWING_CAMERA_TYPE_RELEASE_ANGLE_AT_END) || + at_end == 0) { set_follow_camera_angle_blend_from_direction( gravity_offset_or_yaw_direction, swing, params->pitch * 0.017453292f); } if (params->distance != 0.0f) { - if (params->type == SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE || params->type == SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE) { + if (params->type == SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE || + params->type == SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE) { follow_camera_set_distance(0, params->distance, 0.002f); FUN_L00_002e8490(params->distance + 1.36f); } else { @@ -295,14 +320,16 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { } } if (params->height != 0.0f) { - if (params->type == SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE || params->type == SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE) { + if (params->type == SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE || + params->type == SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE) { follow_camera_set_height(params->height, 0.002f); } else { follow_camera_set_height(params->height, 0.003f); } } if (params->offset_scale != 0.0f) { - if (params->type == SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE || params->type == SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE) { + if (params->type == SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE || + params->type == SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE) { follow_camera_set_offset_scale(0, params->offset_scale, 0.002f); } else { follow_camera_set_offset_scale(0, params->offset_scale, 0.005f); @@ -341,7 +368,9 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { lateral_spring_blend_fraction); } } - if (params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY || params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END) { + if (params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || + params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_ALLOW_AIRBORNE_ENTRY || + params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END) { FUN_L00_002e8620(); follow_camera_start_slide(); follow_camera_set_up_spring(0.01f, 0.2f); @@ -362,7 +391,9 @@ s32 volume_camera_swing_check(struct UpdateCam *swing_camera_record) { return 0; if (params->type == 11 && D_001413F4 != 2) return 0; - if ((params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END) && params->timer == 0) { + if ((params->type == SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END || + params->type == SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END) && + params->timer == 0) { struct Hero *hero_data = &hero; if (hero_data->frames_off_ground.s != 0) { if (current_level_index != 14) diff --git a/src/overlays/shared/cutscenes/update_cutscene_playback.c b/src/overlays/shared/cutscenes/update_cutscene_playback.c index 4d60e0f338..ba7a8b65a7 100644 --- a/src/overlays/shared/cutscenes/update_cutscene_playback.c +++ b/src/overlays/shared/cutscenes/update_cutscene_playback.c @@ -214,8 +214,8 @@ void handle_pause_input(void) { return; } area = current_level_index; - if (area == 15 && level_timer >= 8 && hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && HELD && - hero.state.current != 0x72) { + if (area == 15 && level_timer >= 8 && hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && + HELD && hero.state.current != 0x72) { if (D_L00_00166E00->h86 == 0x13) return; mode_freeze_init(4, 0); diff --git a/src/overlays/shared/cutscenes/update_npc_dialogue.c b/src/overlays/shared/cutscenes/update_npc_dialogue.c index bf57f248cb..e5ef1b549a 100644 --- a/src/overlays/shared/cutscenes/update_npc_dialogue.c +++ b/src/overlays/shared/cutscenes/update_npc_dialogue.c @@ -157,7 +157,8 @@ s32 update_npc_dialogue(struct Moby *moby, struct SceneTrigger *trigger) { /* a fresh block-local pointer (not `entry`) keeps retail's registers */ struct SceneEntry *unpaid = &trigger->entries[trigger->entry]; - if (unpaid->cost_kind == MENU_CONDITION_PURCHASE_PRICE_MET || unpaid->cost_kind == MENU_CONDITION_BOLT_THRESHOLD_AND_COUNT_DIFFERENCE_MET) { + if (unpaid->cost_kind == MENU_CONDITION_PURCHASE_PRICE_MET || + unpaid->cost_kind == MENU_CONDITION_BOLT_THRESHOLD_AND_COUNT_DIFFERENCE_MET) { handle = queue_animation_update(2, 0x754E, initialize_bolt_counter_hud, diff --git a/src/overlays/shared/enemies/armed_transport.c b/src/overlays/shared/enemies/armed_transport.c index e440fc56da..7eb2c4881b 100644 --- a/src/overlays/shared/enemies/armed_transport.c +++ b/src/overlays/shared/enemies/armed_transport.c @@ -375,7 +375,8 @@ void armed_transport_update(char *transport_moby) { transport_data->unk194 -= dt + dt; MOBY(transport_moby)->rot.x += dt * 0.2617994f; - if (fast_dec_timer((int *)(&transport_data->unk160)) || hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { + if (fast_dec_timer((int *)(&transport_data->unk160)) || + hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { spawn_explosion(transport_moby, D_L16_0015F580, &MOBY(transport_moby)->pos, @@ -443,7 +444,13 @@ void armed_transport_update(char *transport_moby) { /* Update interaction ownership, damage responses and pursuit tracking. */ void update_armed_transport_damage_and_targeting(struct Moby *transport_moby) { - enum { ARMED_TRANSPORT_STATE_DYING = 8 } ; enum { HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE = 1} ;L16Hit_e hit; + enum { + ARMED_TRANSPORT_STATE_DYING = 8 + }; + enum { + HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE = 1 + }; + L16Hit_e hit; ArmedTransportVars *transport_data = (ArmedTransportVars *)transport_moby->pvars; float zero; char *hit_record; @@ -466,9 +473,11 @@ void update_armed_transport_damage_and_targeting(struct Moby *transport_moby) { hit_record = find_moby_hit(transport_moby, 0x330000, 0); response = hit_reaction( transport_moby, hit_record, &transport_data->health, 0, &hit.status, &hit.amount, 0, 4); - if (hit.status != HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE && transport_moby->state != ARMED_TRANSPORT_STATE_DYING) { + if (hit.status != HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE && + transport_moby->state != ARMED_TRANSPORT_STATE_DYING) { transport_data->health -= hit.amount; - if (transport_data->health <= zero || (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && hit.amount >= 2.0f)) + if (transport_data->health <= zero || + (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && hit.amount >= 2.0f)) response = 1; if (response > 0) { if (response >= 3) { diff --git a/src/overlays/shared/enemies/armed_transport_rocket.c b/src/overlays/shared/enemies/armed_transport_rocket.c index d38dafaf09..82c84cbec0 100644 --- a/src/overlays/shared/enemies/armed_transport_rocket.c +++ b/src/overlays/shared/enemies/armed_transport_rocket.c @@ -55,7 +55,10 @@ void armed_transport_rocket_update(char *m) __asm__("FUN_L16_002a0a98"); /* Moby class 50 */ void armed_transport_rocket_update(char *rocket_moby) { - enum { ARMED_TRANSPORT_ROCKET_STATE_FLYING = 0 } ;float desired[4], next_position[4], delta[4], blend[4]; + enum { + ARMED_TRANSPORT_ROCKET_STATE_FLYING = 0 + }; + float desired[4], next_position[4], delta[4], blend[4]; char *rocket_data = ((char *)MOBY(rocket_moby)->pvars); void *remaining; float yaw, pitch; diff --git a/src/overlays/shared/enemies/blarg_elite_commando.c b/src/overlays/shared/enemies/blarg_elite_commando.c index 4d9b41af0c..237fecbb6f 100644 --- a/src/overlays/shared/enemies/blarg_elite_commando.c +++ b/src/overlays/shared/enemies/blarg_elite_commando.c @@ -681,7 +681,11 @@ void start_blarg_elite_commando_return_to_initial_position( void start_blarg_elite_commando_return_to_initial_position(struct Moby *moby, int return_countdown_ticks) { - enum { COMMANDO_STATE_RETURN_TO_INITIAL_POSITION = 1 , COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM = 10 } ;L16DamageData *commando_data = (L16DamageData *)moby->pvars; + enum { + COMMANDO_STATE_RETURN_TO_INITIAL_POSITION = 1, + COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM = 10 + }; + L16DamageData *commando_data = (L16DamageData *)moby->pvars; if (moby->state == COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM) { moby->state = COMMANDO_STATE_RETURN_TO_INITIAL_POSITION; if (moby->prev_seq != 1) { @@ -919,7 +923,8 @@ void emit_blarg_elite_commando_joint_sparks(char *commando_moby) { }; float matrix[16], velocity[4], acceleration[4], scatter[4]; int i; - if (MOBY(commando_moby)->visible == 0 || MOBY(commando_moby)->state == COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM) + if (MOBY(commando_moby)->visible == 0 || + MOBY(commando_moby)->state == COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM) return; for (i = 0; i < 2; i++) { float speed, z; diff --git a/src/overlays/shared/enemies/blarg_helicopter.c b/src/overlays/shared/enemies/blarg_helicopter.c index e137044404..c0d67448c2 100644 --- a/src/overlays/shared/enemies/blarg_helicopter.c +++ b/src/overlays/shared/enemies/blarg_helicopter.c @@ -227,7 +227,8 @@ void blarg_helicopter_update(HMob49 *moby) { mark_moby_for_removal(moby); return; } - if (data->route_a.path_id == -1 || (moby->state != BLARG_HELICOPTER_INITIALIZE && data->enabled != 1)) { + if (data->route_a.path_id == -1 || + (moby->state != BLARG_HELICOPTER_INITIALIZE && data->enabled != 1)) { if (data->child_index != -1) mark_moby_for_removal((HMob49 *)(D_L03_0015FFD8_c + (data->child_index << 8))); mark_moby_for_removal(moby); @@ -426,7 +427,8 @@ void blarg_helicopter_update(HMob49 *moby) { moby->rotation[2] = spring_turn(&data->yaw_velocity, moby->rotation[2], angle, 0.01f, 0.3f, 0.1f); projectile = data->projectile; - if (!projectile || projectile->class_id != 0x350 || projectile->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || + if (!projectile || projectile->class_id != 0x350 || + projectile->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || projectile->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { moby_point_position(moby, 0, helicopter_update_scratch.movement); fast_vec_sub(helicopter_update_scratch.direction, @@ -879,7 +881,8 @@ void handle_blarg_helicopter_hits(char *helicopter_moby) { hit_record = find_moby_hit(helicopter_moby, 0x330000, 0); hit_reaction_result = hit_reaction( helicopter_moby, hit_record, helicopter_data + 0x20, 0, &hit_reaction_status, &fv, 0, 4); - if (hit_reaction_status != HIT_REACTION_SKIP_DAMAGE && MOBY(helicopter_moby)->state != BLARG_HELICOPTER_DESTROY) { + if (hit_reaction_status != HIT_REACTION_SKIP_DAMAGE && + MOBY(helicopter_moby)->state != BLARG_HELICOPTER_DESTROY) { float remaining_health = *(float *)(helicopter_data + 0x20) - fv; *(float *)(helicopter_data + 0x20) = remaining_health; if (hit_reaction_result == 1 || remaining_health <= 0.0f) { @@ -887,7 +890,8 @@ void handle_blarg_helicopter_hits(char *helicopter_moby) { } else if (hit_reaction_result != 0xB) { *(unsigned char *)(helicopter_data + 0x67) = 0xB4; trooper_anim_update(helicopter_moby, (short *)(helicopter_data + 0x60)); - if (*(float *)(hit_record + 0x1C) == 5627.925f && MOBY(helicopter_moby)->state != BLARG_HELICOPTER_TIMED_REACTION) { + if (*(float *)(hit_record + 0x1C) == 5627.925f && + MOBY(helicopter_moby)->state != BLARG_HELICOPTER_TIMED_REACTION) { reaction_heading_angle = fast_arc_tan(MOBY(helicopter_moby)->pos.x - *(float *)(hit_record + 0), MOBY(helicopter_moby)->pos.y - *(float *)(hit_record + 4)); diff --git a/src/overlays/shared/enemies/blarg_paratrooper.c b/src/overlays/shared/enemies/blarg_paratrooper.c index 8793e9a920..726580e624 100644 --- a/src/overlays/shared/enemies/blarg_paratrooper.c +++ b/src/overlays/shared/enemies/blarg_paratrooper.c @@ -157,9 +157,11 @@ extern int activate_effect_l08(void *, void *, float, int, int, void *, int) __asm__("FUN_L00_0025ff38"); extern float l08_paratrooper_model_scale_multiplier __asm__("D_L08_00162180") __attribute__((sda)); extern float D_L08_00162184 __attribute__((sda)); -extern float l08_paratrooper_recovery_knockback_xy_speed __asm__("D_L08_0016218C") __attribute__((sda)); +extern float l08_paratrooper_recovery_knockback_xy_speed __asm__("D_L08_0016218C") + __attribute__((sda)); extern float l08_paratrooper_death_knockback_z_speed __asm__("D_L08_00162190") __attribute__((sda)); -extern float l08_paratrooper_death_knockback_xy_speed __asm__("D_L08_00162194") __attribute__((sda)); +extern float l08_paratrooper_death_knockback_xy_speed __asm__("D_L08_00162194") + __attribute__((sda)); extern float D_L08_001621B0 __attribute__((sda)); /* Paratrooper: initializes its path and steering, patrols, attacks its target, @@ -289,9 +291,9 @@ void blarg_paratrooper_update(char *moby) { } } step_mover_2e3f20(moby, - (char *)paratrooper_private_state + 0xD0, - path + 0x10 + paratrooper_private_state->f1F4 * 16, - pos); + (char *)paratrooper_private_state + 0xD0, + path + 0x10 + paratrooper_private_state->f1F4 * 16, + pos); if (target && paratrooper_private_state->f164 != 2 && fast_dec_timer((char *)paratrooper_private_state + 0x1F0)) { paratrooper_private_state->f1F4 = select_point_index_by_distance( @@ -311,10 +313,10 @@ void blarg_paratrooper_update(char *moby) { (*(unsigned char *)((char *)(moby) + 0x20)) = 3; } else { step_mover_2e3f20(moby, - (char *)paratrooper_private_state + 0xD0, - ((char *)l08_paths[paratrooper_private_state->f1D4]) + 0x10 + - paratrooper_private_state->f1F4 * 16, - pos); + (char *)paratrooper_private_state + 0xD0, + ((char *)l08_paths[paratrooper_private_state->f1D4]) + 0x10 + + paratrooper_private_state->f1F4 * 16, + pos); if ((*(unsigned char *)((char *)(moby) + 0x53)) != 2) blend_moby_animation(moby, 2, 0, random302618() % 4 + 7); } @@ -601,7 +603,13 @@ void blarg_paratrooper_update(char *moby) { /* Ported from rac1-decomp (src/overlays/shared/vendor_002D3DF8.c: func_L08_00303998), where it is exact; names translated to the US level program. */ void update_blarg_paratrooper_damage_and_state(char *moby) { - enum { PARATROOPER_HIT_REACTION_LETHAL = 1 , PARATROOPER_HIT_REACTION_DEATH_KNOCKBACK = 2, PARATROOPER_HIT_REACTION_RECOVERY_KNOCKBACK = 3, PARATROOPER_HIT_REACTION_NONE = 11} ;Paratrooper302618 *data; + enum { + PARATROOPER_HIT_REACTION_LETHAL = 1, + PARATROOPER_HIT_REACTION_DEATH_KNOCKBACK = 2, + PARATROOPER_HIT_REACTION_RECOVERY_KNOCKBACK = 3, + PARATROOPER_HIT_REACTION_NONE = 11 + }; + Paratrooper302618 *data; char *target, *child, *attached, *chased; float pos[4] __attribute__((aligned(16))); float matrix[16] __attribute__((aligned(16))); @@ -614,7 +622,8 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { return; { float timer_scale = D_L08_001621B0 * frame_time; - ((Moby *)moby)->scale = *(float *)(((char *)MOBY(moby)->pclass) + 0x24) * l08_paratrooper_model_scale_multiplier; + ((Moby *)moby)->scale = *(float *)(((char *)MOBY(moby)->pclass) + 0x24) * + l08_paratrooper_model_scale_multiplier; data->unkF4 = timer_scale; } diff --git a/src/overlays/shared/enemies/blarg_ship_rocket.c b/src/overlays/shared/enemies/blarg_ship_rocket.c index 9d5ad5c831..2b3572841c 100644 --- a/src/overlays/shared/enemies/blarg_ship_rocket.c +++ b/src/overlays/shared/enemies/blarg_ship_rocket.c @@ -55,13 +55,13 @@ void emit_moby_sprite_particles(char *moby) { color_blend_offset = color_blend_offset / (float)scale_game_frames(0xFF); col = fast_tween_color(0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - color_blend_offset)); spawn_timed_hero_relative_particle(d, - col, - truncate_float_to_s32(sprite_data->a[i]) & 0xFF, - 0x35, - 1, - 2, - 0, - sprite_data->d[i]); + col, + truncate_float_to_s32(sprite_data->a[i]) & 0xFF, + 0x35, + 1, + 2, + 0, + sprite_data->d[i]); fast_vec_add(d, d, particle_position_step); } } diff --git a/src/overlays/shared/enemies/bomb_spawner.c b/src/overlays/shared/enemies/bomb_spawner.c index 405696a604..1a136654df 100644 --- a/src/overlays/shared/enemies/bomb_spawner.c +++ b/src/overlays/shared/enemies/bomb_spawner.c @@ -224,14 +224,16 @@ void bomb_spawner_update(struct Moby *moby) { if (id == -1) continue; o = (struct Moby *)(D_L03_0015FFD8_macro + (id << 8)); - if (o != 0 && o->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && o->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { + if (o != 0 && o->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + o->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { spawner_data->count++; } } { struct Moby *o; for (o = (struct Moby *)D_L03_0015FFE4_macro; o != 0; o = o->next) { - if (o->oclass == 0x221 && o->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && o->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { + if (o->oclass == 0x221 && o->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + o->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { spawner_data->count++; } } @@ -285,7 +287,8 @@ void bomb_spawner_update(struct Moby *moby) { if (id == -1) continue; o = (struct Moby *)(D_L03_0015FFD8_macro + (id << 8)); - if (o != 0 && o->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && o->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { + if (o != 0 && o->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + o->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { mark_moby_for_removal(o); } } diff --git a/src/overlays/shared/enemies/bomb_spawner_bomb.c b/src/overlays/shared/enemies/bomb_spawner_bomb.c index 6bfdc45e64..df5928ad3a 100644 --- a/src/overlays/shared/enemies/bomb_spawner_bomb.c +++ b/src/overlays/shared/enemies/bomb_spawner_bomb.c @@ -111,7 +111,9 @@ struct Moby *revive_spawner_pooled_child(struct Moby *spawner_moby, Vec4 *at, s3 continue; } current_moby = &D_L03_0015FFD8_gp[pooled_child_moby_index]; - if (current_moby != NULL && current_moby->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && current_moby->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { + if (current_moby != NULL && + current_moby->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + current_moby->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { spawner_data->live++; continue; } @@ -176,7 +178,8 @@ struct Moby *revive_spawner_pooled_child(struct Moby *spawner_moby, Vec4 *at, s3 } } for (current_moby = D_L03_0015FFE4; current_moby != NULL; current_moby = current_moby->next) { - if (current_moby->oclass == 0x221 && current_moby->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + if (current_moby->oclass == 0x221 && + current_moby->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && current_moby->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { spawner_data->live++; } @@ -195,7 +198,16 @@ void bomb_spawner_bomb_update(struct Moby *moby) __asm__("FUN_L03_002c4718"); /* Drifts and bounces off walls (state 0), lands and spawns its child moby (1), then shrinks while the child grows (2). */ /* Moby class 545 */ void bomb_spawner_bomb_update(struct Moby *moby) { - enum { SPAWNER_BOMB_STATE_MOVING = 0 , SPAWNER_BOMB_STATE_SPAWN_CHILD = 1 , SPAWNER_BOMB_STATE_SHRINKING = 2 } ; enum { MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xfd , MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xfe} ;float *bomb_runtime; + enum { + SPAWNER_BOMB_STATE_MOVING = 0, + SPAWNER_BOMB_STATE_SPAWN_CHILD = 1, + SPAWNER_BOMB_STATE_SHRINKING = 2 + }; + enum { + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xfd, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xfe + }; + float *bomb_runtime; Vec4 *pos; struct Moby *other; Vec4 old_pos; @@ -285,7 +297,9 @@ void bomb_spawner_bomb_update(struct Moby *moby) { } } for (other = D_L03_0015FFE4; other != NULL; other = other->next) { - if (other == moby || (int)other == 0 || other->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || other->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) + if (other == moby || (int)other == 0 || + other->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || + other->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) continue; fast_vec_sub(&delta, (Vec4 *)&moby->pos, &other->pos); delta.f[2] = 0.0f; @@ -328,7 +342,8 @@ void bomb_spawner_bomb_update(struct Moby *moby) { if (moby->scale < moby->pclass->scale * (frame_scale * 0.05f)) { moby->scale = 0.0001f; other = *(struct Moby **)(bomb_runtime + 6); - if (other == NULL || other->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || other->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END || + if (other == NULL || other->state == MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END || + other->state == MOBY_STATE_REMOVAL_BELOW_INSTANCE_END || !(*(int *)(bomb_runtime + 7) & 4) || other->pclass->scale - 0.01f <= other->scale) goto remove_moby; } diff --git a/src/overlays/shared/enemies/bomber_jet_projectile.c b/src/overlays/shared/enemies/bomber_jet_projectile.c index 4ff63332f2..3586a5e1ba 100644 --- a/src/overlays/shared/enemies/bomber_jet_projectile.c +++ b/src/overlays/shared/enemies/bomber_jet_projectile.c @@ -54,7 +54,8 @@ typedef struct { extern int collect_mobies_in_sphere(float, void *, int, void *, void *) __asm__("FUN_L00_001f2868"); extern int spawn_glow_particle(void *, void *, void *, float, int, int, int, int, int) __asm__("FUN_L00_002ac910"); extern void spawn_effect(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); -extern void spawn_particle_alt_9768(void *, void *, int, int, int, float) __asm__("FUN_L00_0026a4c8"); +extern void +spawn_particle_alt_9768(void *, void *, int, int, int, float) __asm__("FUN_L00_0026a4c8"); extern void spawn_particle(void *, void *, int, int, float, int, int, int, int, float) __asm__("FUN_L00_0026a9f0"); extern void spawn_shrinking_effect_particle_with_gravity_and_secondary_spawns( void *, void *, int, int, float, int, int, int, int) __asm__("FUN_L00_0026bb70"); @@ -96,7 +97,11 @@ void explosive_projectile_update(struct Moby *moby) __asm__("FUN_L01_002f6a30"); /* Moby class 686 */ void explosive_projectile_update(struct Moby *moby) { - enum { EXPLOSIVE_PROJECTILE_STATE_FLYING = 0 , EXPLOSIVE_PROJECTILE_STATE_BURST = 1 } ;Vec_2F7E08 old_pos; + enum { + EXPLOSIVE_PROJECTILE_STATE_FLYING = 0, + EXPLOSIVE_PROJECTILE_STATE_BURST = 1 + }; + Vec_2F7E08 old_pos; Vec_2F7E08 smoke_pos; Data *projectile_vars; int rate_divisor; diff --git a/src/overlays/shared/enemies/frog.c b/src/overlays/shared/enemies/frog.c index b5adc22c80..ba3707bf5a 100644 --- a/src/overlays/shared/enemies/frog.c +++ b/src/overlays/shared/enemies/frog.c @@ -185,13 +185,13 @@ extern int *D_L06_001B0C30[]; extern int D_L06_0015F5C4 MACRO_ADDR; extern int D_L06_0015FDF8 MACRO_ADDR; extern int l06_frog_updates_disabled __asm__("D_L06_00161C10") __attribute__((sda)); -extern int l06_frog_frame_slot_assignment_count __asm__("D_L06_00161C14") __attribute__((sda)); -extern short D_L06_00161BF0[1] __attribute__((sda)); -extern char D_0013F3D0[]; -extern f32 D_L06_0015F580[] MACRO_ADDR; -extern struct Moby *D_L06_0015FFD8_e94f0 __asm__("D_L06_0015FFD8"); -extern u8 D_001413F4_e94f0[] __asm__("D_001413F4"); -extern struct Moby *D_001413D0_lui __asm__("D_001413D0") NOT_SDA; +extern int l06_frog_frame_slot_assignment_count __asm__("D_L06_00161C14") __attribute__((sda)); +extern short D_L06_00161BF0[1] __attribute__((sda)); +extern char D_0013F3D0[]; +extern f32 D_L06_0015F580[] MACRO_ADDR; +extern struct Moby *D_L06_0015FFD8_e94f0 __asm__("D_L06_0015FFD8"); +extern u8 D_001413F4_e94f0[] __asm__("D_001413F4"); +extern struct Moby *D_001413D0_lui __asm__("D_001413D0") NOT_SDA; extern float frog_facing_rotation_blend_factor_gp __asm__("D_L06_00161C00") __attribute__((sda)); extern f32 D_0015ED6C; extern u128 D_L06_001745E0 NOT_SDA; @@ -245,7 +245,23 @@ void frog_update(unsigned char *moby) __asm__("FUN_L06_002e8678"); /* Moby class 827 */ void frog_update(unsigned char *moby) { - enum { FROG_STATE_INITIALIZE = 0 , FROG_STATE_WAIT_WITH_CHILD = 1 , FROG_STATE_WAIT_TO_FOLLOW_PATH = 3 , FROG_STATE_FOLLOW_PATH = 4 , FROG_STATE_JUMP_TO_HOME = 5 , FROG_STATE_AIRBORNE_MOTION = 6, FROG_STATE_LANDING_ANIMATION = 7 , FROG_STATE_WANDER = 8 , FROG_STATE_APPROACH_TARGET = 9 , FROG_STATE_BLINKING_APPROACH_TARGET = 10 , FROG_STATE_APPROACH_PAUSE = 11 , FROG_STATE_ATTACK = 12 , FROG_STATE_RETURN_HOME = 13 , FROG_STATE_SUCK_CANNON_HELD = 16 } ;float A[4] __attribute__((aligned(16))); + enum { + FROG_STATE_INITIALIZE = 0, + FROG_STATE_WAIT_WITH_CHILD = 1, + FROG_STATE_WAIT_TO_FOLLOW_PATH = 3, + FROG_STATE_FOLLOW_PATH = 4, + FROG_STATE_JUMP_TO_HOME = 5, + FROG_STATE_AIRBORNE_MOTION = 6, + FROG_STATE_LANDING_ANIMATION = 7, + FROG_STATE_WANDER = 8, + FROG_STATE_APPROACH_TARGET = 9, + FROG_STATE_BLINKING_APPROACH_TARGET = 10, + FROG_STATE_APPROACH_PAUSE = 11, + FROG_STATE_ATTACK = 12, + FROG_STATE_RETURN_HOME = 13, + FROG_STATE_SUCK_CANNON_HELD = 16 + }; + float A[4] __attribute__((aligned(16))); float B[4] __attribute__((aligned(16))); float C[4] __attribute__((aligned(16))); float D[4] __attribute__((aligned(16))); @@ -954,7 +970,8 @@ int update_moby_grab_state(struct Moby *moby) { }; int grab_check_result = process_moby_suck_cannon_suction(moby); if (grab_check_result != 0) { - if (moby->state == FROG_STATE_WANDER || moby->state == FROG_STATE_APPROACH_TARGET || moby->state == FROG_STATE_ATTACK || moby->state == FROG_STATE_RETURN_HOME || + if (moby->state == FROG_STATE_WANDER || moby->state == FROG_STATE_APPROACH_TARGET || + moby->state == FROG_STATE_ATTACK || moby->state == FROG_STATE_RETURN_HOME || moby->state == FROG_STATE_SUCK_CANNON_HELD) { if (moby->state != FROG_STATE_SUCK_CANNON_HELD) { moby->command = moby->state; @@ -994,7 +1011,10 @@ int update_moby_suck_cannon_storage_state(unsigned char *moby) { s32 cancel_moby_suction_and_save_state(unsigned char *moby) __asm__("FUN_L06_002ea7c8"); s32 cancel_moby_suction_and_save_state(unsigned char *moby) { - enum { FROG_STATE_SUCK_CANNON_HELD = 0x10 } ;u8 previous_state; + enum { + FROG_STATE_SUCK_CANNON_HELD = 0x10 + }; + u8 previous_state; s32 helper_result; helper_result = cancel_suck_cannon_suction(moby); previous_state = MOBY(moby)->state; diff --git a/src/overlays/shared/enemies/gadgebot.c b/src/overlays/shared/enemies/gadgebot.c index 5d8fc43843..80a0c38c59 100644 --- a/src/overlays/shared/enemies/gadgebot.c +++ b/src/overlays/shared/enemies/gadgebot.c @@ -356,8 +356,11 @@ void gadgebot_update(GbMoby *moby) { FUN_L06_002f3640_u(moby); if (hero_distance < 16.0f && absolute_float(moby->pos[2] - hero.motion.pos.f[2]) < 1.5f) { int ok = 0; - if (moby->state == GADGEBOT_WANDER_NEAR_HOME || moby->state == GADGEBOT_SEEK_AND_ATTACK_TARGET || moby->state == GADGEBOT_FOLLOW_HERO || moby->state == 6 || - moby->state == GADGEBOT_SEEK_INTERACTION_TARGET || moby->state == GADGEBOT_STAND_AND_FACE_HERO) { + if (moby->state == GADGEBOT_WANDER_NEAR_HOME || + moby->state == GADGEBOT_SEEK_AND_ATTACK_TARGET || + moby->state == GADGEBOT_FOLLOW_HERO || moby->state == 6 || + moby->state == GADGEBOT_SEEK_INTERACTION_TARGET || + moby->state == GADGEBOT_STAND_AND_FACE_HERO) { ok = 1; } if (ok) { @@ -1152,14 +1155,14 @@ float score_gadgebot_target_candidate(char *moby, float score_gadgebot_target_candidate(char *moby, char *candidate_moby, int target_kind) { float candidate_score = vector_distance_xy(&MOBY(moby)->pos, candidate_moby + 0x10); - float t = - fast_difference_between_rotations(l06_camera.yaw, - fast_arc_tan(*(float *)(candidate_moby + 0x10) - MOBY(moby)->pos.x, - *(float *)(candidate_moby + 0x14) - MOBY(moby)->pos.y)); - float u = - fast_difference_between_rotations(MOBY(moby)->rot.z, - fast_arc_tan(*(float *)(candidate_moby + 0x10) - MOBY(moby)->pos.x, - *(float *)(candidate_moby + 0x14) - MOBY(moby)->pos.y)); + float t = fast_difference_between_rotations( + l06_camera.yaw, + fast_arc_tan(*(float *)(candidate_moby + 0x10) - MOBY(moby)->pos.x, + *(float *)(candidate_moby + 0x14) - MOBY(moby)->pos.y)); + float u = fast_difference_between_rotations( + MOBY(moby)->rot.z, + fast_arc_tan(*(float *)(candidate_moby + 0x10) - MOBY(moby)->pos.x, + *(float *)(candidate_moby + 0x14) - MOBY(moby)->pos.y)); candidate_score = candidate_score + u * 10.0f; candidate_score = candidate_score + t * 3.0f; if (((unsigned char *)candidate_moby)[0x31] == 0) { @@ -1704,7 +1707,8 @@ void update_gadgebot_glow_effects(char *moby) { tint = 0x3228AAAA; if (MOBY(moby)->state == GADGEBOT_FOLLOW_HERO || MOBY(moby)->state == 6) { tint = 0x3228AA28; - } else if (MOBY(moby)->state == GADGEBOT_SEEK_AND_ATTACK_TARGET || MOBY(moby)->state == GADGEBOT_UPDATE_KNOCKBACK) { + } else if (MOBY(moby)->state == GADGEBOT_SEEK_AND_ATTACK_TARGET || + MOBY(moby)->state == GADGEBOT_UPDATE_KNOCKBACK) { tint = 0x322828AA; } else if (MOBY(moby)->state == GADGEBOT_SEEK_INTERACTION_TARGET) { tint = 0x32AA2828; diff --git a/src/overlays/shared/enemies/ground_melee_enemy.c b/src/overlays/shared/enemies/ground_melee_enemy.c index 63cfced485..7885368c84 100644 --- a/src/overlays/shared/enemies/ground_melee_enemy.c +++ b/src/overlays/shared/enemies/ground_melee_enemy.c @@ -228,7 +228,8 @@ void ground_melee_enemy_update(Moby *moby) { int expired; float ground; - if (moby->state != GROUND_ENEMY_STATE_FATAL_KNOCKBACK && moby->state != GROUND_ENEMY_STATE_RECOVER_TO_IDLE) { + if (moby->state != GROUND_ENEMY_STATE_FATAL_KNOCKBACK && + moby->state != GROUND_ENEMY_STATE_RECOVER_TO_IDLE) { Hit_2E39E0 *hit; damage = 0.0f; hit = find_moby_hit(moby, 0x330000, 0); diff --git a/src/overlays/shared/enemies/hero_seeking_mine.c b/src/overlays/shared/enemies/hero_seeking_mine.c index a04e0fea18..b9036a48ba 100644 --- a/src/overlays/shared/enemies/hero_seeking_mine.c +++ b/src/overlays/shared/enemies/hero_seeking_mine.c @@ -67,7 +67,13 @@ void hero_seeking_mine_update(char *moby) __asm__("FUN_L15_002a2488"); /* Moby class 77 */ void hero_seeking_mine_update(char *moby) { - enum { GROUP_MOBY_STATE_RESET = 0 , GROUP_MOBY_STATE_RISING = 2 , GROUP_MOBY_STATE_HERO_SEEKING = 3 , GROUP_MOBY_STATE_BURST = 4 } ;float va[4]; + enum { + GROUP_MOBY_STATE_RESET = 0, + GROUP_MOBY_STATE_RISING = 2, + GROUP_MOBY_STATE_HERO_SEEKING = 3, + GROUP_MOBY_STATE_BURST = 4 + }; + float va[4]; float pb[4]; char *group_moby_data; char *callback_frame_stamp; diff --git a/src/overlays/shared/enemies/horny_toad.c b/src/overlays/shared/enemies/horny_toad.c index 544f3530bd..203bb47ee5 100644 --- a/src/overlays/shared/enemies/horny_toad.c +++ b/src/overlays/shared/enemies/horny_toad.c @@ -136,13 +136,16 @@ extern float horny_toad_target_animation_start_index_gp __asm__("D_L00_00161984" __attribute__((sda)); extern short D_L00_00161960 __attribute__((sda)); -extern s32 D_L00_0015F5C4_2d5160 __asm__("D_L00_0015F5C4"); -extern f32 l00_horny_toad_knockback_gravity __asm__("D_L00_00161970") __attribute__((sda)); -extern f32 l00_horny_toad_knockback_horizontal_deceleration __asm__("D_L00_00161974") __attribute__((sda)); -extern f32 l00_horny_toad_knockback_horizontal_speed __asm__("D_L00_00161978") __attribute__((sda)); -extern f32 l00_horny_toad_knockback_vertical_speed __asm__("D_L00_0016197C") __attribute__((sda)); -extern f32 l00_horny_toad_knockback_landing_animation_frame __asm__("D_L00_00161988") __attribute__((sda)); -extern f32 l00_horny_toad_knockback_apex_animation_frame __asm__("D_L00_0016198C") __attribute__((sda)); +extern s32 D_L00_0015F5C4_2d5160 __asm__("D_L00_0015F5C4"); +extern f32 l00_horny_toad_knockback_gravity __asm__("D_L00_00161970") __attribute__((sda)); +extern f32 l00_horny_toad_knockback_horizontal_deceleration __asm__("D_L00_00161974") + __attribute__((sda)); +extern f32 l00_horny_toad_knockback_horizontal_speed __asm__("D_L00_00161978") __attribute__((sda)); +extern f32 l00_horny_toad_knockback_vertical_speed __asm__("D_L00_0016197C") __attribute__((sda)); +extern f32 l00_horny_toad_knockback_landing_animation_frame __asm__("D_L00_00161988") + __attribute__((sda)); +extern f32 l00_horny_toad_knockback_apex_animation_frame __asm__("D_L00_0016198C") + __attribute__((sda)); extern unsigned char *D_L00_001B04B0_2d5160[] __asm__("D_L00_001B04B0"); extern void hit_reaction(void *, void *, void *, s32, s32 *, f32 *, s32, s32) __asm__("FUN_L00_0025a478"); @@ -259,7 +262,8 @@ void horny_toad_update(Moby *moby) { break; case HORNY_TOAD_FACE_FOLLOW_MOBY: { Moby *followed_moby = (Moby *)(moby_table + (horny_toad_vars->follow_moby << 8)); - if (followed_moby != 0 && followed_moby->state != MOBY_STATE_MARKED_FOR_REMOVAL && followed_moby->state != 0xFD) { + if (followed_moby != 0 && followed_moby->state != MOBY_STATE_MARKED_FOR_REMOVAL && + followed_moby->state != 0xFD) { approach_angle( &moby->rot.z, fast_arc_tan((*(ToadVec *)&followed_moby->pos)[0] - (*(ToadVec *)&moby->pos)[0], @@ -439,7 +443,8 @@ void horny_toad_update(Moby *moby) { } break; } - if (moby->state != HORNY_TOAD_RECOVER_FROM_REACTION && moby->state != HORNY_TOAD_DYING && moby->state != HORNY_TOAD_RUN_MOVEMENT_SEQUENCE) { + if (moby->state != HORNY_TOAD_RECOVER_FROM_REACTION && moby->state != HORNY_TOAD_DYING && + moby->state != HORNY_TOAD_RUN_MOVEMENT_SEQUENCE) { approach_value(probe_ground_height((*(ToadVec *)&moby->pos), 0, 0.5f), frame_time * 7.0f, &(*(ToadVec *)&moby->pos)[2]); @@ -463,7 +468,10 @@ void horny_toad_update(Moby *moby) { void process_horny_toad_hit_reaction(unsigned char *m) __asm__("FUN_L00_002d5160"); void process_horny_toad_hit_reaction(unsigned char *toad_moby) { - enum { HIT_RESPONSE_NO_HIT = 1 } ;unsigned char *toad_vars = *(unsigned char **)(toad_moby + 0x78); + enum { + HIT_RESPONSE_NO_HIT = 1 + }; + unsigned char *toad_vars = *(unsigned char **)(toad_moby + 0x78); unsigned char *hit; s32 hit_response_status; f32 damage; @@ -487,7 +495,8 @@ void process_horny_toad_hit_reaction(unsigned char *toad_moby) { damage = 0.0f; hit = find_moby_hit(toad_moby, 0x330000, 0); hit_reaction(toad_moby, hit, toad_vars + 0x20, 0, &hit_response_status, &damage, 0, 4); - if (hit_response_status != HIT_RESPONSE_NO_HIT && MOBY(toad_moby)->state != 12 && damage != 0.0f) { + if (hit_response_status != HIT_RESPONSE_NO_HIT && MOBY(toad_moby)->state != 12 && + damage != 0.0f) { /* Fakematch: register pins give retail's choices: 41 in $t0, the frame time and later 0.75 in $f4, the squared frame time first in $f0. */ register s32 hit_state __asm__("$8") = 0x29; @@ -626,7 +635,10 @@ extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); int process_suck_cannon_suction_and_update_moby_state(char *a) __asm__("FUN_L00_002d56e0"); int process_suck_cannon_suction_and_update_moby_state(char *moby) { - enum { MOBY_STATE_SUCK_CANNON_ACTIVE = 0x9 } ;int suction_result = process_moby_suck_cannon_suction(moby); + enum { + MOBY_STATE_SUCK_CANNON_ACTIVE = 0x9 + }; + int suction_result = process_moby_suck_cannon_suction(moby); if (suction_result == 0) { if (MOBY(moby)->state == MOBY_STATE_SUCK_CANNON_ACTIVE) MOBY(moby)->state = 0x5; diff --git a/src/overlays/shared/enemies/large_amoeboid.c b/src/overlays/shared/enemies/large_amoeboid.c index c015d734bd..b876c5b47c 100644 --- a/src/overlays/shared/enemies/large_amoeboid.c +++ b/src/overlays/shared/enemies/large_amoeboid.c @@ -655,7 +655,11 @@ void large_amoeboid_update(unsigned char *moby) { /* Ported from rac1-decomp (src/overlays/shared/vendor_002B90A8.c: func_L01_002F0040), where it is exact; names translated to the US level program. */ void process_amoeboid_hits_and_update_targeting(char *moby) { - enum { LARGE_AMOEBOID_INITIALIZE = 0 , LARGE_AMOEBOID_PROCESS_KNOCKBACK = 8 } ;V_2F0040 scratch_vector; + enum { + LARGE_AMOEBOID_INITIALIZE = 0, + LARGE_AMOEBOID_PROCESS_KNOCKBACK = 8 + }; + V_2F0040 scratch_vector; V_2F0040 line_test_endpoint; int flag; float amount; @@ -894,7 +898,8 @@ char *activate_smaller_amoeboid(void *source_moby) { group_index_or_list_entry = index; index &= 0x7FFF; smaller_amoeboid = (struct Moby *)(entities + (index << 8)); - if (smaller_amoeboid->state != LARGE_AMOEBOID_DORMANT || smaller_amoeboid->oclass != next_class) + if (smaller_amoeboid->state != LARGE_AMOEBOID_DORMANT || + smaller_amoeboid->oclass != next_class) goto advance; { /* Retail reads both pvars pointers and update_dist before writing the entity. */ diff --git a/src/overlays/shared/enemies/path_or_ballistic_debris.c b/src/overlays/shared/enemies/path_or_ballistic_debris.c index 3d685f5b67..16e880f8e5 100644 --- a/src/overlays/shared/enemies/path_or_ballistic_debris.c +++ b/src/overlays/shared/enemies/path_or_ballistic_debris.c @@ -69,7 +69,10 @@ void path_or_ballistic_debris_update(struct Moby *moby) __asm__("FUN_L14_002dfd1 /* Moby class 403 */ void path_or_ballistic_debris_update(struct Moby *moby) { - enum { DEBRIS_STATE_FOLLOW_PATH = 0 } ;Data *debris_private_vars = (Data *)moby->pvars; + enum { + DEBRIS_STATE_FOLLOW_PATH = 0 + }; + Data *debris_private_vars = (Data *)moby->pvars; Vec4 probe; f32 position_offset[4]; f32 *velocity; diff --git a/src/overlays/shared/enemies/plasmabot.c b/src/overlays/shared/enemies/plasmabot.c index 74d1f8639c..e8ccacf837 100644 --- a/src/overlays/shared/enemies/plasmabot.c +++ b/src/overlays/shared/enemies/plasmabot.c @@ -794,7 +794,8 @@ void plasmabot_update(char *moby) { } } state = ((unsigned char *)moby)[0x20]; - if (!(state >= PLASMABOT_AIM_AT_TARGET && state <= PLASMABOT_WAIT_ANIMATION_BEFORE_AIM) && state != PLASMABOT_WAIT_TO_START_PATH_TRAVERSAL) { + if (!(state >= PLASMABOT_AIM_AT_TARGET && state <= PLASMABOT_WAIT_ANIMATION_BEFORE_AIM) && + state != PLASMABOT_WAIT_TO_START_PATH_TRAVERSAL) { update_plasmabot_aim_quaternion(moby, 0, MOBY(moby)->rot.z); update_plasmabot_aim_joint_rotation(moby, MOBY(moby)->rot.z); } @@ -1087,7 +1088,13 @@ void process_plasmabot_hit_reaction(struct Moby *moby) { HIT_REACTION_DEATH = 2, HIT_REACTION_STAGGER = 3, HIT_REACTION_NONE = 11 - } ; enum { HIT_KIND_SKIP_DAMAGE_AND_REACTION = 1 , PLASMABOT_WAIT_ANIMATION_BEFORE_RESUMING_AIM = 0xA , PLASMABOT_FALL_THEN_EXPLODE = 0xB , PLASMABOT_SPAWN_DEBRIS_AND_REMOVE = 0xC}; + }; + enum { + HIT_KIND_SKIP_DAMAGE_AND_REACTION = 1, + PLASMABOT_WAIT_ANIMATION_BEFORE_RESUMING_AIM = 0xA, + PLASMABOT_FALL_THEN_EXPLODE = 0xB, + PLASMABOT_SPAWN_DEBRIS_AND_REMOVE = 0xC + }; PlasmabotVars *state = (PlasmabotVars *)moby->pvars; int hit_kind; float damage; diff --git a/src/overlays/shared/enemies/sandmouse.c b/src/overlays/shared/enemies/sandmouse.c index e0510e8667..9405574b2d 100644 --- a/src/overlays/shared/enemies/sandmouse.c +++ b/src/overlays/shared/enemies/sandmouse.c @@ -497,9 +497,9 @@ extern char D_L01_0020BA30[] NOT_SDA; extern float fast_vec_dist(void *, void *); extern int debug_print() __asm__("FUN_001e93b0"); extern int FUN_L00_00257b90(int, int); -extern int step_mover_2e3f20(void *, void *, void *, void *) __asm__("FUN_L00_00259028"); -extern s32 collision_line(void *, void *, s32, void *, s32); -extern s32 rand(void); +extern int step_mover_2e3f20(void *, void *, void *, void *) __asm__("FUN_L00_00259028"); +extern s32 collision_line(void *, void *, s32, void *, s32); +extern s32 rand(void); extern short sandmouse_follow_duration_frames_gp __asm__("D_L01_00162098") __attribute__((sda)); extern short sandmouse_projectile_count_limit_gp __asm__("D_L01_0016209C") __attribute__((sda)); extern short sandmouse_fade_duration_frames_gp __asm__("D_L01_001620A4") __attribute__((sda)); diff --git a/src/overlays/shared/enemies/scoutbot.c b/src/overlays/shared/enemies/scoutbot.c index 6f4e342501..7548398620 100644 --- a/src/overlays/shared/enemies/scoutbot.c +++ b/src/overlays/shared/enemies/scoutbot.c @@ -416,7 +416,10 @@ void scoutbot_update(Moby *moby) { /* Ported from rac1-decomp (src/overlays/shared/vendor_002D3DF8.c: func_L08_002D49E8), where it is exact; names translated to the US level program. */ void update_scoutbot_health_and_target(struct Moby *moby) { - enum { SCOUTBOT_STATE_EXPLODE_AND_REMOVE = 0x63 } ;ScoutbotVars *scoutbot_pvars = (ScoutbotVars *)moby->pvars; + enum { + SCOUTBOT_STATE_EXPLODE_AND_REMOVE = 0x63 + }; + ScoutbotVars *scoutbot_pvars = (ScoutbotVars *)moby->pvars; int hit; float dmg; int hit_reaction_code; @@ -644,7 +647,10 @@ void update_scoutbot_movement(struct Moby *moby) { void *enter_scoutbot_return_home_state(struct Moby *moby) __asm__("FUN_L08_002d4050"); void *enter_scoutbot_return_home_state(struct Moby *moby) { - enum { SCOUTBOT_STATE_RETURN_HOME = 3 } ;void *suction_cancel_status = cancel_suck_cannon_suction(moby); + enum { + SCOUTBOT_STATE_RETURN_HOME = 3 + }; + void *suction_cancel_status = cancel_suck_cannon_suction(moby); ScoutbotVars *scoutbot_data = (ScoutbotVars *)moby->pvars; moby->state = SCOUTBOT_STATE_RETURN_HOME; scoutbot_data->unk200 = 4.0f; diff --git a/src/overlays/shared/enemies/sentrybot.c b/src/overlays/shared/enemies/sentrybot.c index 52bbe9d500..d33ba0584a 100644 --- a/src/overlays/shared/enemies/sentrybot.c +++ b/src/overlays/shared/enemies/sentrybot.c @@ -276,7 +276,10 @@ void sentrybot_update(unsigned char *moby) { SENTRYBOT_ANIM_TURN_NEGATIVE_HEADING_DELTA = 10, SENTRYBOT_ANIM_TURN_POSITIVE_HEADING_DELTA = 11, SENTRYBOT_ANIM_TURN_AROUND = 12 - } ; enum { SENTRYBOT_TARGET_MODE_SUPPRESS_DIRECT_EMISSION = 2}; + }; + enum { + SENTRYBOT_TARGET_MODE_SUPPRESS_DIRECT_EMISSION = 2 + }; float va[4]; float vb[4]; float emission_origin[4]; @@ -337,7 +340,8 @@ void sentrybot_update(unsigned char *moby) { fast_dec_timer_s16(&sentrybot_instance_data->attention_timer); if (sentrybot_instance_data->alert_timer != 0 && sentrybot_instance_data->alarm_moby_index != -1) { - char *linked_alarm_moby = (char *)((sentrybot_instance_data->alarm_moby_index << 8) + (int)l15_moby_array); + char *linked_alarm_moby = + (char *)((sentrybot_instance_data->alarm_moby_index << 8) + (int)l15_moby_array); if (*(int *)(*(char **)(linked_alarm_moby + 0x78) + 8) != 0) set_sentrybot_alarm_duration(linked_alarm_moby, 0xB4); } @@ -706,8 +710,9 @@ void sentrybot_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 0xD) blend_moby_animation(moby, 0xD, 0, scale_game_frames(10)); if (sentrybot_instance_data->alarm_moby_index != -1) { - char *linked_alarm_moby = (char *)((sentrybot_instance_data->alarm_moby_index << 8) + - (int)l15_moby_array); + char *linked_alarm_moby = + (char *)((sentrybot_instance_data->alarm_moby_index << 8) + + (int)l15_moby_array); if (*(int *)(*(char **)(linked_alarm_moby + 0x78) + 8) != 0) set_sentrybot_alarm_duration(linked_alarm_moby, scale_game_frames(0x1E)); } @@ -1024,14 +1029,16 @@ void sentrybot_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 0xD) blend_moby_animation(moby, 0xD, 0, scale_game_frames(10)); if (sentrybot_instance_data->alarm_moby_index != -1) { - char *linked_alarm_moby = (char *)((sentrybot_instance_data->alarm_moby_index << 8) + - (int)l15_moby_array); + char *linked_alarm_moby = + (char *)((sentrybot_instance_data->alarm_moby_index << 8) + + (int)l15_moby_array); if (*(int *)(*(char **)(linked_alarm_moby + 0x78) + 8) != 0) set_sentrybot_alarm_duration(linked_alarm_moby, -1); } } else { int mode = sentrybot_instance_data->unk114; - if (mode != SENTRYBOT_TARGET_MODE_SUPPRESS_DIRECT_EMISSION && sentrybot_instance_data->unk15B == 0) { + if (mode != SENTRYBOT_TARGET_MODE_SUPPRESS_DIRECT_EMISSION && + sentrybot_instance_data->unk15B == 0) { begin_sentrybot_turn_toward_point((char *)moby, sentrybot_instance_data, (float *)(&sentrybot_instance_data->unkD0), @@ -1042,13 +1049,15 @@ void sentrybot_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 0xD) blend_moby_animation(moby, 0xD, 0, scale_game_frames(10)); if (sentrybot_instance_data->alarm_moby_index != -1) { - char *linked_alarm_moby = (char *)((sentrybot_instance_data->alarm_moby_index << 8) + - (int)l15_moby_array); + char *linked_alarm_moby = + (char *)((sentrybot_instance_data->alarm_moby_index << 8) + + (int)l15_moby_array); if (*(int *)(*(char **)(linked_alarm_moby + 0x78) + 8) != 0) set_sentrybot_alarm_duration(linked_alarm_moby, scale_game_frames(0x1E)); } } else if (sentrybot_instance_data->has_line_of_sight != 0) { - if (mode != SENTRYBOT_TARGET_MODE_SUPPRESS_DIRECT_EMISSION && sentrybot_instance_data->unk15B == 0) { + if (mode != SENTRYBOT_TARGET_MODE_SUPPRESS_DIRECT_EMISSION && + sentrybot_instance_data->unk15B == 0) { begin_sentrybot_turn_toward_point((char *)moby, sentrybot_instance_data, (float *)(target + 0x10), @@ -1554,7 +1563,10 @@ void update_sentrybot_hit_response_and_target_visibility(void *sentrybot_moby, i SENTRYBOT_FIRST_CHANNEL_BLEND_HIT_RESPONSE = 9, SENTRYBOT_FIRST_CHANNEL_BLEND_TARGET_HIT_RESPONSE = 10, SENTRYBOT_NO_KNOCKBACK_START_RESPONSE = 11 - } ; enum { HIT_STATUS_SKIP_REACTION = 1}; + }; + enum { + HIT_STATUS_SKIP_REACTION = 1 + }; unsigned char *moby = sentrybot_moby; SentrybotVars *sentrybot_data = (SentrybotVars *)MOBY(moby)->pvars; char *hit; diff --git a/src/overlays/shared/enemies/sentrybot_alarm.c b/src/overlays/shared/enemies/sentrybot_alarm.c index 79ca5d3d0d..24dadc6f3a 100644 --- a/src/overlays/shared/enemies/sentrybot_alarm.c +++ b/src/overlays/shared/enemies/sentrybot_alarm.c @@ -55,7 +55,10 @@ extern short sentrybot_alarm_voice_owner_gp __asm__("D_L15_00161AC8") __attribut int activate_first_inactive_group_moby(int moby_group_index, void *pos) __asm__("FUN_L15_002a2868"); int activate_first_inactive_group_moby(int moby_group_index, void *pos) { - enum { GROUP_MOBY_STATE_INACTIVE = 1 } ;short *group_moby_entry = (short *)D_L15_001ABE40[moby_group_index]; + enum { + GROUP_MOBY_STATE_INACTIVE = 1 + }; + short *group_moby_entry = (short *)D_L15_001ABE40[moby_group_index]; struct Hero *hero_data = &hero; do { unsigned char *listed_moby = @@ -90,7 +93,23 @@ void sentrybot_alarm_update(unsigned char *moby) __asm__("FUN_L15_002cb4c8"); /* Moby class 408 */ void sentrybot_alarm_update(unsigned char *moby) { - enum { SENTRYBOT_ALARM_STATE_INITIALIZE = 0 , SENTRYBOT_ALARM_STATE_STANDBY_PULSE = 1 , SENTRYBOT_ALARM_STATE_STANDBY_RETURN_TRANSITION = 2 , SENTRYBOT_ALARM_STATE_WAIT_FOR_ALARM_TRIGGER = 3 , SENTRYBOT_ALARM_STATE_ALARM_START_TRANSITION = 4 ,SENTRYBOT_ALARM_STATE_ACTIVE_PULSE = 5 , SENTRYBOT_ALARM_STATE_WAIT_FOR_GROUP_RELEASE_TRIGGER = 6 , SENTRYBOT_ALARM_STATE_GROUP_RELEASE_START_TRANSITION = 7 ,SENTRYBOT_ALARM_STATE_RELEASE_GROUP_MOBYS = 8 , SENTRYBOT_ALARM_STATE_GROUP_RELEASE_STOP_TRANSITION = 9 , SENTRYBOT_ALARM_STATE_ALARM_STOP_TRANSITION = 10} ; enum { SENTRYBOT_ALARM_MODE_GROUP_RELEASE_ONLY = 2} ;float position[4]; + enum { + SENTRYBOT_ALARM_STATE_INITIALIZE = 0, + SENTRYBOT_ALARM_STATE_STANDBY_PULSE = 1, + SENTRYBOT_ALARM_STATE_STANDBY_RETURN_TRANSITION = 2, + SENTRYBOT_ALARM_STATE_WAIT_FOR_ALARM_TRIGGER = 3, + SENTRYBOT_ALARM_STATE_ALARM_START_TRANSITION = 4, + SENTRYBOT_ALARM_STATE_ACTIVE_PULSE = 5, + SENTRYBOT_ALARM_STATE_WAIT_FOR_GROUP_RELEASE_TRIGGER = 6, + SENTRYBOT_ALARM_STATE_GROUP_RELEASE_START_TRANSITION = 7, + SENTRYBOT_ALARM_STATE_RELEASE_GROUP_MOBYS = 8, + SENTRYBOT_ALARM_STATE_GROUP_RELEASE_STOP_TRANSITION = 9, + SENTRYBOT_ALARM_STATE_ALARM_STOP_TRANSITION = 10 + }; + enum { + SENTRYBOT_ALARM_MODE_GROUP_RELEASE_ONLY = 2 + }; + float position[4]; float step; int color; int mode; @@ -116,7 +135,8 @@ void sentrybot_alarm_update(unsigned char *moby) { (fast_sin(*(float *)(alarm_state + 5)) + 1.0f) * 0.5f, 0x801414bc, 0x801414dc); step = frame_time; MOBY(moby)->glow_color = color; - *(float *)(alarm_state + 5) = fast_add_rotations(*(float *)(alarm_state + 5), step * 6.2831855f); + *(float *)(alarm_state + 5) = + fast_add_rotations(*(float *)(alarm_state + 5), step * 6.2831855f); if (alarm_state[2] == 0) goto update; if (D_L15_0015F5C4 != 2) { @@ -172,7 +192,8 @@ void sentrybot_alarm_update(unsigned char *moby) { (fast_sin(*(float *)(alarm_state + 5)) + 1.0f) * 0.5f, 0x801414dc, 0x8004048c); step = frame_time; MOBY(moby)->glow_color = color; - *(float *)(alarm_state + 5) = fast_add_rotations(*(float *)(alarm_state + 5), step * 12.566371f); + *(float *)(alarm_state + 5) = + fast_add_rotations(*(float *)(alarm_state + 5), step * 12.566371f); if (fast_dec_timer(alarm_state + 6) || D_L15_0015F5C4 == 2) { set_sentrybot_alarm_duration((char *)moby, 0); alarm_state[2] = 0; diff --git a/src/overlays/shared/game/run_level_main_loop.c b/src/overlays/shared/game/run_level_main_loop.c index 7b9fa21b16..d3413c8032 100644 --- a/src/overlays/shared/game/run_level_main_loop.c +++ b/src/overlays/shared/game/run_level_main_loop.c @@ -231,7 +231,8 @@ void run_level_main_loop(void) { } memcard_update_state(); run_state_handler(); - if (memory_card_state.state >= MEMCARD_REQUEST_FORMAT || memory_card_state.pending_state >= MEMCARD_QUERY_INFO) { + if (memory_card_state.state >= MEMCARD_REQUEST_FORMAT || + memory_card_state.pending_state >= MEMCARD_QUERY_INFO) { if (D_L00_001B9CF0.unk13C == 0) { int rotation_period_frames = 55; float size; @@ -269,7 +270,8 @@ void run_level_main_loop(void) { if (hero.fall_fade_pending == 0) { int mode = D_L00_0015F5C4; - if (mode == LEVEL_MODE_DEBUG_FLAG_GATED_UPDATE || mode == LEVEL_MODE_DEBUG_PROFILER_RENDER) { + if (mode == LEVEL_MODE_DEBUG_FLAG_GATED_UPDATE || + mode == LEVEL_MODE_DEBUG_PROFILER_RENDER) { int frame_timer_threshold = 9600; if (pal_mode != PAL_MODE_DISABLED) { diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index 7caedb0d3c..fc1345dfe4 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -1246,7 +1246,8 @@ void update_hero_ground_contact_and_gravity(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || + if (hero.ground_slope.f <= 0.87266463f || + hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = HH.moby; diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index d0859d1b59..0e20d2e7a3 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -93,7 +93,8 @@ int hero_idle_sequence(int a) __asm__("FUN_L00_00205000"); int hero_idle_sequence(int allow_item_idle_sequence) { struct Hero *vehicle_mode_owner = &hero; int vehicle_mode = vehicle_mode_owner->vehicle_mode; - if (vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK || (vehicle_mode < 3 ? vehicle_mode == HERO_VEHICLE_MODE_CLANK : vehicle_mode == 3)) { + if (vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK || + (vehicle_mode < 3 ? vehicle_mode == HERO_VEHICLE_MODE_CLANK : vehicle_mode == 3)) { return 0; } { @@ -1556,7 +1557,8 @@ void apply_hero_and_item_scale_sequence(void) { if (j == 1) item_moby = *(unsigned char **)&hero_state->items[i].moby2; item_scale = sequence_scale; - if (i == 0 && hero_state->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT && 1.0f < sequence_scale) + if (i == 0 && hero_state->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT && + 1.0f < sequence_scale) item_scale = 1.0f; if (item_moby) { fast_vec_scale(item_moby + 0xC0, item_moby + 0xC0, item_scale); @@ -1711,7 +1713,10 @@ extern G_00208038 D_0013F350_00208038 __asm__("D_0013F350"); void enqueue_hero_glow_draw_callback_once(void) __asm__("FUN_L00_00207d00"); /* Appends v, b, x and y to the list in ((char *)&hero) and calls FUN_L00_00207d00. */ -void enqueue_hero_glow_quad(u128 *glow_position, int b, float x, float y) __asm__("FUN_L00_00208038"); +void enqueue_hero_glow_quad(u128 *glow_position, + int b, + float x, + float y) __asm__("FUN_L00_00208038"); void enqueue_hero_glow_quad(u128 *glow_position, int b, float x, float y) { G_00208038 *hero_glow_queue_owner = &D_0013F350_00208038; diff --git a/src/overlays/shared/hero/hero_move_state_velocity.c b/src/overlays/shared/hero/hero_move_state_velocity.c index 2cec2a8da3..abd7659f79 100644 --- a/src/overlays/shared/hero/hero_move_state_velocity.c +++ b/src/overlays/shared/hero/hero_move_state_velocity.c @@ -665,8 +665,10 @@ void update_hero_tilt(void) { if (k == 0x11 || k == 0x15 || k == 0x16) { return; } - if (current_hero_state == HERO_STATE_FATAL_FALL || current_hero_state == HERO_STATE_VOICE_SLOT_CLEANUP_IDLE_EXIT || - current_hero_state == HERO_STATE_ITEM_RELEASE_FALL || current_hero_state == HERO_STATE_GRAPPLE_SWING_ENTRY) { + if (current_hero_state == HERO_STATE_FATAL_FALL || + current_hero_state == HERO_STATE_VOICE_SLOT_CLEANUP_IDLE_EXIT || + current_hero_state == HERO_STATE_ITEM_RELEASE_FALL || + current_hero_state == HERO_STATE_GRAPPLE_SWING_ENTRY) { return; } tilt_targets[0] = 0.0f; @@ -1263,7 +1265,8 @@ void launch_hero_wrench(void) { s32 state; state = hero.state.current; - aimed = (state == HERO_STATE_LOOK || state == HERO_STATE_LOOK_RELEASE_WAIT) && scale_game_frames(0x14) < hero.state_timer; + aimed = (state == HERO_STATE_LOOK || state == HERO_STATE_LOOK_RELEASE_WAIT) && + scale_game_frames(0x14) < hero.state_timer; if (aimed) { target = hero.items[0].moby; has_target = 0; diff --git a/src/overlays/shared/hero/hero_set_state.c b/src/overlays/shared/hero/hero_set_state.c index b6f27ad2d3..d0175c98bb 100644 --- a/src/overlays/shared/hero/hero_set_state.c +++ b/src/overlays/shared/hero/hero_set_state.c @@ -686,7 +686,8 @@ int hero_set_state(int requested_state, int b) { V4_222B80 sampled_path_position; { struct Hero *p = &hero; - if (p->state.control_mode == 0x14 && (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + if (p->state.control_mode == 0x14 && + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) return 0; } if ((D_L00_0015F5C4 == 2 || D_L00_0015F5C4 == 6) && b != 2) @@ -694,8 +695,16 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->health.hp == 0 && (p->state.control_mode == 2 || p->state.control_mode == 7) && - requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && requested_state != HERO_STATE_FATAL_FALL && requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && - requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && requested_state != HERO_STATE_DROWN && requested_state != HERO_STATE_DYING_SPEED_LIMITED && requested_state != HERO_STATE_DYING_ZERO_HEALTH) + requested_state != HERO_STATE_FALL && requested_state != HERO_STATE_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_1_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_3_DYING && + requested_state != HERO_STATE_VEHICLE_MODE_2_DYING && + requested_state != HERO_STATE_FATAL_FALL && + requested_state != HERO_STATE_HEIGHT_OR_TIMEOUT_RESPAWN_WAIT && + requested_state != HERO_STATE_DEATH_DESCENT && requested_state != HERO_STATE_SINK && + requested_state != HERO_STATE_DROWN && + requested_state != HERO_STATE_DYING_SPEED_LIMITED && + requested_state != HERO_STATE_DYING_ZERO_HEALTH) return 0; } { @@ -1696,7 +1705,8 @@ int hero_set_state(int requested_state, int b) { return 0; } p->state.control_mode = 4; - if (requested_state >= HERO_STATE_GRIND_JUMP && requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { + if (requested_state >= HERO_STATE_GRIND_JUMP && + requested_state <= HERO_STATE_GRIND_RAIL_TRANSFER) { p->unk2284 = 3; } else { p->unk2284 = 0x50; diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 18068ac1e3..8bf51dbbf5 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -772,10 +772,10 @@ void update_hero_condition_animation(void) { } } -extern s32 l00_hero_item_animation_slot_ids[2] __asm__("D_L00_0015F6A0") __attribute__((sda)); -extern u8 D_L00_00197BC0_lui[] __asm__("D_L00_00197BC0") NOT_SDA; -extern char *D_L00_00197300[]; -extern u8 D_L00_0017CA80[] NOT_SDA; +extern s32 l00_hero_item_animation_slot_ids[2] __asm__("D_L00_0015F6A0") __attribute__((sda)); +extern u8 D_L00_00197BC0_lui[] __asm__("D_L00_00197BC0") NOT_SDA; +extern char *D_L00_00197300[]; +extern u8 D_L00_0017CA80[] NOT_SDA; extern struct HeroEase hero_eases[] __asm__("D_L00_0017A680"); extern void advance_moby_animation_blend(void *, unsigned char *) __asm__("FUN_L00_0024f190"); extern float approach_value(float *, float, float) __asm__("FUN_00213ed8"); @@ -825,8 +825,8 @@ void update_hero_item_slot_blends(void) { if (want) { struct Hero *h = &hero; if (hero.item_slot_blends[i] == 0) { - u8 *allocated_item_slot_blend = - allocate_moby_animation_slot((u8 *)h->moby, l00_hero_item_animation_slot_ids[i]); + u8 *allocated_item_slot_blend = allocate_moby_animation_slot( + (u8 *)h->moby, l00_hero_item_animation_slot_ids[i]); hero.item_slot_blends[i] = allocated_item_slot_blend; *(f32 *)(allocated_item_slot_blend + 8) = 0.0f; *(u8 **)(hero.item_slot_blends[i] + 0x18) = @@ -1068,7 +1068,8 @@ void start_equipped_item_animation(void) { if (hero.held_item_anim_blend[i] != 0) { release_moby_animation_slot((u8 *)hero.moby, &hero.held_item_anim_blend[i]); } - slot_animation_object = allocate_moby_animation_slot((u8 *)hero.moby, l00_hero_item_animation_slot_ids[i]); + slot_animation_object = + allocate_moby_animation_slot((u8 *)hero.moby, l00_hero_item_animation_slot_ids[i]); hero.held_item_anim_blend[i] = slot_animation_object; if (slot_animation_object != 0) { hero.item_hold_anim = slot_animation_id; @@ -2183,7 +2184,8 @@ void hero_switch_item(int i) { if (item_switch_mode == HERO_ITEM_SWITCH_MODE_BLOCKED) { changed = 0; } - if (item_switch_mode == HERO_ITEM_SWITCH_MODE_RELOAD_TIMER_WHEN_ZERO && s->items[0].timer == 0) { + if (item_switch_mode == HERO_ITEM_SWITCH_MODE_RELOAD_TIMER_WHEN_ZERO && + s->items[0].timer == 0) { s->items[0].timer = s->items[0].timer_reload; } } @@ -2393,7 +2395,8 @@ void exit_hero_vehicle_mode(void) { } { struct Hero *vehicle_animation_owner = &hero; - if (vehicle_animation_owner->vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && vehicle_animation_owner->unk1634 != -1) { + if (vehicle_animation_owner->vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && + vehicle_animation_owner->unk1634 != -1) { set_animation_parameter(vehicle_animation_owner->unk1634, 0); vehicle_animation_owner->unk1634 = -1; } @@ -3434,7 +3437,8 @@ void update_hero_ground_contact_and_surface_slopes(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || + if (hero.ground_slope.f <= 0.87266463f || + hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = HH.moby; diff --git a/src/overlays/shared/hero/hero_update_movement.c b/src/overlays/shared/hero/hero_update_movement.c index b12f117122..9311fc312f 100644 --- a/src/overlays/shared/hero/hero_update_movement.c +++ b/src/overlays/shared/hero/hero_update_movement.c @@ -272,7 +272,9 @@ void hero_update_movement(void) { if (hero.unk20A5 != 0) { movement_and_hit_descriptor_scratch.q = 0; movement_and_hit_descriptor_scratch.f[0] = 1.0f; - transform_vector_by_basis(&hero.motion.move_dir, &movement_and_hit_descriptor_scratch, &D_L00_00166DD8[0x1F8]); + transform_vector_by_basis(&hero.motion.move_dir, + &movement_and_hit_descriptor_scratch, + &D_L00_00166DD8[0x1F8]); hero.motion.move_yaw = *(f32 *)D_L00_00166DD8; turn_to(0, frame_scale_sq, frame_scale_sq * 0.0f, frame_time * 174.53293f); if (D_L00_0015F688 > 0 && fast_dec_timer(&D_L00_0015F688) != 0) { @@ -627,13 +629,20 @@ void hero_update_movement(void) { s32 lo2; s32 hi2; pl = &hero_b; - moby_point_position((struct MobyView *)pl->moby, 4, &movement_and_hit_descriptor_scratch); + moby_point_position( + (struct MobyView *)pl->moby, 4, &movement_and_hit_descriptor_scratch); spatial_and_hit_descriptor_scratch.q = 0; spatial_and_hit_descriptor_scratch.f[0] = 0.4f; - transform_vector_by_basis(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, &((struct MobyView *)pl->moby)->vC0); - fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch); + transform_vector_by_basis(&spatial_and_hit_descriptor_scratch, + &spatial_and_hit_descriptor_scratch, + &((struct MobyView *)pl->moby)->vC0); + fast_vec_add(&movement_and_hit_descriptor_scratch, + &movement_and_hit_descriptor_scratch, + &spatial_and_hit_descriptor_scratch); qcopy(&v10, &hero_b.motion.displacement); - fast_vec_normalize(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, frame_time * 1.5f); + fast_vec_normalize(&spatial_and_hit_descriptor_scratch, + &spatial_and_hit_descriptor_scratch, + frame_time * 1.5f); fast_vec_add(&v10, &v10, &spatial_and_hit_descriptor_scratch); v10.f[2] += frame_time * 2.0f; FUN_L00_0026f080(&movement_and_hit_descriptor_scratch, &v10, 25200.0f, -1.0f); @@ -654,11 +663,18 @@ void hero_update_movement(void) { moby_point_position(gm, i % 2, &movement_and_hit_descriptor_scratch); spatial_and_hit_descriptor_scratch.q = 0; spatial_and_hit_descriptor_scratch.f[0] = -0.15f; - transform_vector_by_basis(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, &((struct MobyView *)hero.moby)->vC0); - fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch); - movement_and_hit_descriptor_scratch.f[0] += random_float_between(0.0f, 0.03f); - movement_and_hit_descriptor_scratch.f[1] += random_float_between(0.0f, 0.03f); - movement_and_hit_descriptor_scratch.f[2] += random_float_between(0.0f, 0.03f); + transform_vector_by_basis(&spatial_and_hit_descriptor_scratch, + &spatial_and_hit_descriptor_scratch, + &((struct MobyView *)hero.moby)->vC0); + fast_vec_add(&movement_and_hit_descriptor_scratch, + &movement_and_hit_descriptor_scratch, + &spatial_and_hit_descriptor_scratch); + movement_and_hit_descriptor_scratch.f[0] += + random_float_between(0.0f, 0.03f); + movement_and_hit_descriptor_scratch.f[1] += + random_float_between(0.0f, 0.03f); + movement_and_hit_descriptor_scratch.f[2] += + random_float_between(0.0f, 0.03f); qcopy(&v10, &hero.motion.displacement); FUN_L00_00262cf0(&v10, &v10, @@ -668,7 +684,10 @@ void hero_update_movement(void) { hero.pack_particle_timer = truncate_float_to_s32((frame_time * 7.0f - hero.ground_speed) / (frame_time * 7.0f) * scale_game_frames(5)); - FUN_L00_0026f080(&movement_and_hit_descriptor_scratch, &v10, random_float_between(6300.0f, 9450.0f), -1.0f); + FUN_L00_0026f080(&movement_and_hit_descriptor_scratch, + &v10, + random_float_between(6300.0f, 9450.0f), + -1.0f); } } } @@ -750,13 +769,20 @@ void hero_update_movement(void) { fast_vec_normalize(&hero.motion.momentum, &hero.motion.momentum, len); qcopy(&hero.motion.velocity, &hero.motion.momentum); if (fast_dec_timer(&hero.puff_timer) == 2) { - moby_point_position((struct MobyView *)hero.moby, 4, &movement_and_hit_descriptor_scratch); + moby_point_position( + (struct MobyView *)hero.moby, 4, &movement_and_hit_descriptor_scratch); spatial_and_hit_descriptor_scratch.q = 0; spatial_and_hit_descriptor_scratch.f[0] = 0.4f; - transform_vector_by_basis(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, &((struct MobyView *)hero.moby)->vC0); - fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch); + transform_vector_by_basis(&spatial_and_hit_descriptor_scratch, + &spatial_and_hit_descriptor_scratch, + &((struct MobyView *)hero.moby)->vC0); + fast_vec_add(&movement_and_hit_descriptor_scratch, + &movement_and_hit_descriptor_scratch, + &spatial_and_hit_descriptor_scratch); qcopy(&v10, &hero.motion.displacement); - fast_vec_normalize(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, frame_time * 1.5f); + fast_vec_normalize(&spatial_and_hit_descriptor_scratch, + &spatial_and_hit_descriptor_scratch, + frame_time * 1.5f); fast_vec_add(&v10, &v10, &spatial_and_hit_descriptor_scratch); v10.f[2] += frame_time * 2.0f; FUN_L00_0026f080(&movement_and_hit_descriptor_scratch, &v10, 25200.0f, -1.0f); @@ -834,8 +860,11 @@ void hero_update_movement(void) { f32 d; f32 ground_moby_yaw_step_limit; clear_u64_value(&movement_and_hit_descriptor_scratch); - fast_vec_add(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &((struct MobyView *)hero.ground_moby)->u10.v10); - fast_vec_sub(&hero.motion.velocity, &movement_and_hit_descriptor_scratch, &hero.motion.pos); + fast_vec_add(&movement_and_hit_descriptor_scratch, + &movement_and_hit_descriptor_scratch, + &((struct MobyView *)hero.ground_moby)->u10.v10); + fast_vec_sub( + &hero.motion.velocity, &movement_and_hit_descriptor_scratch, &hero.motion.pos); FUN_L00_0025f730(&hero.motion.velocity, frame_time * 2.0f); d = fast_subtract_rotations(((struct MobyView *)hero.ground_moby)->u40.f48.v, hero.motion.rot.f[2]); @@ -901,7 +930,8 @@ void hero_update_movement(void) { case HERO_STATE_APPROACH_TARGET_MOBY: { f32 hit; f32 hit2; - qcopy(&movement_and_hit_descriptor_scratch, &((struct MobyView *)hero.grapple_target)->u10.v10); + qcopy(&movement_and_hit_descriptor_scratch, + &((struct MobyView *)hero.grapple_target)->u10.v10); hero.unk970 = fast_vec_dist(&hero.motion.pos, &movement_and_hit_descriptor_scratch); hero.target_arrival_frames = scale_game_frames(60); if (hero.grapple_pull_speed > 0.0f) { @@ -931,16 +961,24 @@ void hero_update_movement(void) { if (hero.grapple_pull_ending != 0) { step_angle_toward_target(&hero.motion.rot.f[1], 0, 0.0f, frame_time * 3.8397243f); } else { - f32 an = fast_add_rotations(-fast_arc_tan(vector_distance_xy(&hero.motion.pos, &movement_and_hit_descriptor_scratch), - movement_and_hit_descriptor_scratch.f[2] - hero.motion.pos.f[2]), - 1.5707964f); + f32 an = fast_add_rotations( + -fast_arc_tan( + vector_distance_xy(&hero.motion.pos, &movement_and_hit_descriptor_scratch), + movement_and_hit_descriptor_scratch.f[2] - hero.motion.pos.f[2]), + 1.5707964f); step_angle_toward_target(&hero.motion.rot.f[1], 0, an, frame_time * 6.4577184f); } - spatial_and_hit_descriptor_scratch.f[0] = fast_cos(fast_add_rotations(hero.motion.rot.f[2], -1.5707964f)) * -0.57f; - spatial_and_hit_descriptor_scratch.f[1] = fast_sin(fast_add_rotations(hero.motion.rot.f[2], -1.5707964f)) * -0.57f; + spatial_and_hit_descriptor_scratch.f[0] = + fast_cos(fast_add_rotations(hero.motion.rot.f[2], -1.5707964f)) * -0.57f; + spatial_and_hit_descriptor_scratch.f[1] = + fast_sin(fast_add_rotations(hero.motion.rot.f[2], -1.5707964f)) * -0.57f; spatial_and_hit_descriptor_scratch.f[2] = 0.0f; - fast_vec_add(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, &hero.motion.pos); - fast_vec_sub(&v10, &((struct MobyView *)hero.grapple_target)->u10.v10, &spatial_and_hit_descriptor_scratch); + fast_vec_add(&spatial_and_hit_descriptor_scratch, + &spatial_and_hit_descriptor_scratch, + &hero.motion.pos); + fast_vec_sub(&v10, + &((struct MobyView *)hero.grapple_target)->u10.v10, + &spatial_and_hit_descriptor_scratch); fast_vec_normalize(&hero.motion.velocity, &v10, hero.grapple_pull_speed); if (scale_game_frames(30) > hero.target_arrival_frames) { f32 t = scale_game_frames(30) - hero.target_arrival_frames; @@ -953,12 +991,15 @@ void hero_update_movement(void) { qcopy(&hero.motion.velocity, &hero.motion.displacement); fast_vec_scale(&hero.motion.velocity, &hero.motion.velocity, 0.9f); hero.motion.velocity.f[2] -= frame_time_sq * 15.0f; - qcopy(&movement_and_hit_descriptor_scratch, &((struct MobyView *)hero.grapple_target)->u10.v10); + qcopy(&movement_and_hit_descriptor_scratch, + &((struct MobyView *)hero.grapple_target)->u10.v10); hero.unk970 = fast_vec_dist(&hero.motion.pos, &movement_and_hit_descriptor_scratch); fast_vec_add(&v10, &hero.motion.pos, &hero.motion.velocity); fast_vec_sub(&movement_vector_scratch, &v10, &movement_and_hit_descriptor_scratch); fast_vec_normalize(&movement_vector_scratch, &movement_vector_scratch, hero.tether_radius); - fast_vec_add(&spatial_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &movement_vector_scratch); + fast_vec_add(&spatial_and_hit_descriptor_scratch, + &movement_and_hit_descriptor_scratch, + &movement_vector_scratch); fast_vec_sub(&hero.motion.velocity, &spatial_and_hit_descriptor_scratch, &hero.motion.pos); break; } @@ -987,8 +1028,11 @@ void hero_update_movement(void) { } hero.motion.move_yaw = hero.swing_yaw; turn_to(0, frame_scale_sq * 0.02f, frame_scale_sq * 0.3f, frame_time * 4.712389f); - fast_vec_sub(&movement_and_hit_descriptor_scratch, &((struct MobyView *)hero.swing_target_moby)->u10.v10, &hero.motion.pos); - fast_vec_normalize(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, 1.0f); + fast_vec_sub(&movement_and_hit_descriptor_scratch, + &((struct MobyView *)hero.swing_target_moby)->u10.v10, + &hero.motion.pos); + fast_vec_normalize( + &movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, 1.0f); if (movement_and_hit_descriptor_scratch.f[2] < 0.23f) { movement_and_hit_descriptor_scratch.f[2] = 0.23f; } @@ -996,9 +1040,16 @@ void hero_update_movement(void) { spatial_and_hit_descriptor_scratch.f[2] = hero.motion.rot.f[2]; euler_rotation_matrix(matrix_vector_scratch, &spatial_and_hit_descriptor_scratch); transpose_rotation_matrix(transposed_yaw_matrix, matrix_vector_scratch); - transform_vector(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, transposed_yaw_matrix); - v10.f[0] = -fast_arc_tan(square_root(movement_and_hit_descriptor_scratch.f[0] * movement_and_hit_descriptor_scratch.f[0] + movement_and_hit_descriptor_scratch.f[2] * movement_and_hit_descriptor_scratch.f[2]), movement_and_hit_descriptor_scratch.f[1]); - v10.f[1] = fast_arc_tan(movement_and_hit_descriptor_scratch.f[2], movement_and_hit_descriptor_scratch.f[0]); + transform_vector(&movement_and_hit_descriptor_scratch, + &movement_and_hit_descriptor_scratch, + transposed_yaw_matrix); + v10.f[0] = -fast_arc_tan(square_root(movement_and_hit_descriptor_scratch.f[0] * + movement_and_hit_descriptor_scratch.f[0] + + movement_and_hit_descriptor_scratch.f[2] * + movement_and_hit_descriptor_scratch.f[2]), + movement_and_hit_descriptor_scratch.f[1]); + v10.f[1] = fast_arc_tan(movement_and_hit_descriptor_scratch.f[2], + movement_and_hit_descriptor_scratch.f[0]); spring_angle(&hero.motion.rot.f[1], v10.f[1], &hero.motion.rot_spring_vel.f[1], @@ -1179,7 +1230,11 @@ void hero_update_movement(void) { matrix_vector_scratch[0].f[2] = 0.0f; make_hit_descriptor( &v10, (struct MobyView *)hero.moby, 0x30000, 1.0f, &matrix_vector_scratch[0]); - collect_mobies_in_sphere(0.8f, &movement_and_hit_descriptor_scratch, 0x10, (struct MobyView *)hero.moby, &v10); + collect_mobies_in_sphere(0.8f, + &movement_and_hit_descriptor_scratch, + 0x10, + (struct MobyView *)hero.moby, + &v10); } if (hero.past_apex != 0.0f && hero.air_frames.s == 0) { if (hero.rise_fall_land_frames == 0) { @@ -1248,7 +1303,8 @@ void hero_update_movement(void) { if (hero.anim_changing == 0 && hero.anim_frame > 23.5f && hero.motion.displacement.f[2] < 0.0f && hero.air_frames.s != 0) { qcopy(&movement_and_hit_descriptor_scratch, &hero.motion.pos); - offset_hero_position_against_gravity(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, -0.5f); + offset_hero_position_against_gravity( + &movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, -0.5f); matrix_vector_scratch[0].f[0] = fast_cos(hero.motion.rot.f[2]) * 2.0f; matrix_vector_scratch[0].f[1] = fast_sin(hero.motion.rot.f[2]) * 2.0f; matrix_vector_scratch[0].f[2] = 0.0f; @@ -1258,7 +1314,11 @@ void hero_update_movement(void) { ((u8 *)&spatial_and_hit_descriptor_scratch)[9] = 1; ((s16 *)&spatial_and_hit_descriptor_scratch)[5] = 0x47; ((u8 *)&spatial_and_hit_descriptor_scratch)[8] = 0; - collect_mobies_in_sphere(0.4f, &movement_and_hit_descriptor_scratch, 0x10, (struct MobyView *)hero.moby, &v10); + collect_mobies_in_sphere(0.4f, + &movement_and_hit_descriptor_scratch, + 0x10, + (struct MobyView *)hero.moby, + &v10); } test_hero_animation_frame_window(27.0f); if (hero.state_timer < rise_end_frame) { @@ -1432,7 +1492,8 @@ void hero_update_movement(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { s32 ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -1517,8 +1578,11 @@ void hero_update_movement(void) { movement_vector_scratch.f[0] = fast_cos(hero.motion.rot.f[2]) * 2.0f; movement_vector_scratch.f[1] = fast_sin(hero.motion.rot.f[2]) * 2.0f; movement_vector_scratch.f[2] = 1.3f; - make_hit_descriptor( - &movement_and_hit_descriptor_scratch, (struct MobyView *)hero.moby, 0x30000, 3.0f, &movement_vector_scratch); + make_hit_descriptor(&movement_and_hit_descriptor_scratch, + (struct MobyView *)hero.moby, + 0x30000, + 3.0f, + &movement_vector_scratch); ((u8 *)&v10)[9] = 3; movement_and_hit_descriptor_scratch.f[3] = 5627.925f; ((u8 *)&v10)[8] = 0; @@ -1530,7 +1594,12 @@ void hero_update_movement(void) { fast_vec_add( &matrix_vector_scratch[0], &matrix_vector_scratch[0], &hero.motion.pos); emit_filtered_entry_sparkles( - o, collect_mobies_in_sphere(0.8f, &matrix_vector_scratch[0], 0, o, &movement_and_hit_descriptor_scratch)); + o, + collect_mobies_in_sphere(0.8f, + &matrix_vector_scratch[0], + 0, + o, + &movement_and_hit_descriptor_scratch)); a = fast_add_rotations(hero.motion.rot.f[2], -0.87266463f); matrix_vector_scratch[0].f[0] = fast_cos(a) * 0.8f; matrix_vector_scratch[0].f[1] = fast_sin(a) * 0.8f; @@ -1539,8 +1608,11 @@ void hero_update_movement(void) { &matrix_vector_scratch[0], &matrix_vector_scratch[0], &hero.motion.pos); emit_filtered_entry_sparkles( o, - collect_mobies_in_sphere( - 0.8f, &matrix_vector_scratch[0], 0, (struct MobyView *)hero.moby, &movement_and_hit_descriptor_scratch)); + collect_mobies_in_sphere(0.8f, + &matrix_vector_scratch[0], + 0, + (struct MobyView *)hero.moby, + &movement_and_hit_descriptor_scratch)); a = fast_add_rotations(hero.motion.rot.f[2], 0.87266463f); matrix_vector_scratch[0].f[0] = fast_cos(a) * 0.8f; matrix_vector_scratch[0].f[1] = fast_sin(a) * 0.8f; @@ -1548,7 +1620,12 @@ void hero_update_movement(void) { fast_vec_add( &matrix_vector_scratch[0], &matrix_vector_scratch[0], &hero.motion.pos); emit_filtered_entry_sparkles( - o, collect_mobies_in_sphere(0.8f, &matrix_vector_scratch[0], 0, o, &movement_and_hit_descriptor_scratch)); + o, + collect_mobies_in_sphere(0.8f, + &matrix_vector_scratch[0], + 0, + o, + &movement_and_hit_descriptor_scratch)); } } if (scale_game_frames(10) < hero.state_timer) { @@ -1585,8 +1662,11 @@ void hero_update_movement(void) { f32 a; f32 f; update_hero_target_speed_from_stick(); - transform_vector(&movement_and_hit_descriptor_scratch, &hero_b.motion.move_dir, (Vec4 *)hero_b.inv_rot_matrix); - a = absolute_float(fast_arc_tan(movement_and_hit_descriptor_scratch.f[0], movement_and_hit_descriptor_scratch.f[1])); + transform_vector(&movement_and_hit_descriptor_scratch, + &hero_b.motion.move_dir, + (Vec4 *)hero_b.inv_rot_matrix); + a = absolute_float(fast_arc_tan(movement_and_hit_descriptor_scratch.f[0], + movement_and_hit_descriptor_scratch.f[1])); if (a > 0.69813168f) { f32 x0 = hero.target_speed; f32 x1 = hero.ground_speed; @@ -1777,15 +1857,19 @@ void hero_update_movement(void) { } if (current_level_index != 0xF) { emit_hero_randomized_motion_effects(4, 2); - movement_and_hit_descriptor_scratch.f[0] = hero.motion.pos.f[0] + random_float_between(-0.25f, 0.25f); - movement_and_hit_descriptor_scratch.f[1] = hero.motion.pos.f[1] + random_float_between(-0.25f, 0.25f); - movement_and_hit_descriptor_scratch.f[2] = hero.motion.pos.f[2] + random_float_between(-0.1f, 0.4f); + movement_and_hit_descriptor_scratch.f[0] = + hero.motion.pos.f[0] + random_float_between(-0.25f, 0.25f); + movement_and_hit_descriptor_scratch.f[1] = + hero.motion.pos.f[1] + random_float_between(-0.25f, 0.25f); + movement_and_hit_descriptor_scratch.f[2] = + hero.motion.pos.f[2] + random_float_between(-0.1f, 0.4f); fast_vec_scale(&v10, &hero.motion.displacement, 0.9f); v10.f[0] += random_float_between(frame_time * -0.7f, frame_time * 0.7f); v10.f[1] += random_float_between(frame_time * -0.7f, frame_time * 0.7f); v10.f[2] += random_float_between(frame_time, frame_time * 2.0f); - spawn_random_alpha_rotated_particle( - &movement_and_hit_descriptor_scratch, &v10, random_float_between(37800.0f, 75600.0f)); + spawn_random_alpha_rotated_particle(&movement_and_hit_descriptor_scratch, + &v10, + random_float_between(37800.0f, 75600.0f)); } f = fast_vec_length(&hero.motion.platform_delta); if (f > frame_time * 0.5f) { @@ -1945,7 +2029,12 @@ void hero_update_movement(void) { qcopy(&spatial_and_hit_descriptor_scratch, &hero.motion.pos); si = hero.rail_segment; sf = hero.rail_seg_frac; - h = sample_path((void *)hero.rail_spline, &spatial_and_hit_descriptor_scratch, &si, &sf, q, hero.rail_spline_loops); + h = sample_path((void *)hero.rail_spline, + &spatial_and_hit_descriptor_scratch, + &si, + &sf, + q, + hero.rail_spline_loops); qcopy(&movement_vector_scratch, &hero.motion.pos); si = hero.rail_segment; sf = hero.rail_seg_frac; @@ -1956,11 +2045,13 @@ void hero_update_movement(void) { q + 0.1f, hero.rail_spline_loops)) == 0 || hero.rail_spline_loops != 0) { - f32 a = - fast_subtract_rotations(hero.rail_dir_yaw, - fast_arc_tan(movement_vector_scratch.f[0] - spatial_and_hit_descriptor_scratch.f[0], - movement_vector_scratch.f[1] - spatial_and_hit_descriptor_scratch.f[1])) * - 0.37f; + f32 a = fast_subtract_rotations( + hero.rail_dir_yaw, + fast_arc_tan(movement_vector_scratch.f[0] - + spatial_and_hit_descriptor_scratch.f[0], + movement_vector_scratch.f[1] - + spatial_and_hit_descriptor_scratch.f[1])) * + 0.37f; if (a > 0.7853982f) { a = 0.7853982f; } @@ -1987,10 +2078,14 @@ void hero_update_movement(void) { if ((struct MobyView *)hero.grind_look_moby != NULL) { f32 a; f32 k; - fast_vec_sub( - &spatial_and_hit_descriptor_scratch, &((struct MobyView *)hero.grind_look_moby)->u10.v10, &hero.motion.pos); - transform_vector_by_basis(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, (Vec4 *)hero.inv_rot_matrix); - a = fast_arc_tan(spatial_and_hit_descriptor_scratch.f[0], spatial_and_hit_descriptor_scratch.f[1]); + fast_vec_sub(&spatial_and_hit_descriptor_scratch, + &((struct MobyView *)hero.grind_look_moby)->u10.v10, + &hero.motion.pos); + transform_vector_by_basis(&spatial_and_hit_descriptor_scratch, + &spatial_and_hit_descriptor_scratch, + (Vec4 *)hero.inv_rot_matrix); + a = fast_arc_tan(spatial_and_hit_descriptor_scratch.f[0], + spatial_and_hit_descriptor_scratch.f[1]); if (((struct MobyView *)hero.moby)->b52 == 0x31) { a = fast_subtract_rotations(a, 1.5707964f); hero_eases[3].rot_target.f[2] = a * 0.3f; @@ -2024,15 +2119,19 @@ void hero_update_movement(void) { hero.rail_segment, hero.grind_direction, hero.rail_spline_loops); - fast_vec_sub(&spatial_and_hit_descriptor_scratch, (Vec4 *)hero.rail_spline + (idx + 1), &movement_and_hit_descriptor_scratch); + fast_vec_sub(&spatial_and_hit_descriptor_scratch, + (Vec4 *)hero.rail_spline + (idx + 1), + &movement_and_hit_descriptor_scratch); if (fast_vec_length(&spatial_and_hit_descriptor_scratch) < 0.001f) { if (hero.rail_segment == idx) { hero.rail_off_frames = scale_game_frames(1); break; } } else { - hero.rail_dir_yaw = fast_arc_tan(spatial_and_hit_descriptor_scratch.f[0], spatial_and_hit_descriptor_scratch.f[1]); - hero.rail_pitch = fast_arc_tan(vector_length_xy(&spatial_and_hit_descriptor_scratch), spatial_and_hit_descriptor_scratch.f[2]); + hero.rail_dir_yaw = fast_arc_tan(spatial_and_hit_descriptor_scratch.f[0], + spatial_and_hit_descriptor_scratch.f[1]); + hero.rail_pitch = fast_arc_tan(vector_length_xy(&spatial_and_hit_descriptor_scratch), + spatial_and_hit_descriptor_scratch.f[2]); } hero.motion.move_yaw = fast_add_rotations(hero.rail_dir_yaw, hero.grind_yaw_offset); turn_to(0, frame_scale_sq * 0.015f, frame_scale_sq * 0.15f, frame_time * 6.2831855f); @@ -2050,22 +2149,30 @@ void hero_update_movement(void) { } if (hero.rail_switching != 0 && hero.rail_transfer_frames <= scale_game_frames(48)) { f32 previous_path_blend_fraction; - fast_vec_sub(&spatial_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &v10); + fast_vec_sub(&spatial_and_hit_descriptor_scratch, + &movement_and_hit_descriptor_scratch, + &v10); hero.rail_transfer_frames++; - fast_vec_scale( - &spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, (f32)hero.rail_transfer_frames / (f32)scale_game_frames(48)); + fast_vec_scale(&spatial_and_hit_descriptor_scratch, + &spatial_and_hit_descriptor_scratch, + (f32)hero.rail_transfer_frames / (f32)scale_game_frames(48)); previous_path_blend_fraction = (f32)(hero.rail_transfer_frames - 1) / (f32)scale_game_frames(48); fast_vec_sub(&movement_vector_scratch, &movement_and_hit_descriptor_scratch, &v10); fast_vec_scale(&movement_vector_scratch, &movement_vector_scratch, previous_path_blend_fraction); - hero.motion.pos.f[2] += spatial_and_hit_descriptor_scratch.f[2] - movement_vector_scratch.f[2]; + hero.motion.pos.f[2] += + spatial_and_hit_descriptor_scratch.f[2] - movement_vector_scratch.f[2]; fast_vec_add(&movement_vector_scratch, &v10, &spatial_and_hit_descriptor_scratch); - fast_vec_sub(&spatial_and_hit_descriptor_scratch, &movement_vector_scratch, &hero.motion.pos); + fast_vec_sub(&spatial_and_hit_descriptor_scratch, + &movement_vector_scratch, + &hero.motion.pos); hero.motion.velocity.f[0] = spatial_and_hit_descriptor_scratch.f[0]; hero.motion.velocity.f[1] = spatial_and_hit_descriptor_scratch.f[1]; - fast_vec_sub(&spatial_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &hero.rail_point); + fast_vec_sub(&spatial_and_hit_descriptor_scratch, + &movement_and_hit_descriptor_scratch, + &hero.rail_point); hero.motion.pos.f[2] += spatial_and_hit_descriptor_scratch.f[2]; if (hero.motion.pos.f[2] < hero.rail_point.f[2]) { if (hero.rail_transfer_frames <= scale_game_frames(48) && @@ -2074,7 +2181,9 @@ void hero_update_movement(void) { } } } else { - fast_vec_sub(&spatial_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, &hero.rail_point); + fast_vec_sub(&spatial_and_hit_descriptor_scratch, + &movement_and_hit_descriptor_scratch, + &hero.rail_point); hero.motion.velocity.f[0] = spatial_and_hit_descriptor_scratch.f[0]; hero.motion.velocity.f[1] = spatial_and_hit_descriptor_scratch.f[1]; hero.motion.pos.f[2] += spatial_and_hit_descriptor_scratch.f[2]; @@ -2134,9 +2243,15 @@ void hero_update_movement(void) { si = hero.rail_segment; sf = hero.rail_seg_frac; qcopy(&spatial_and_hit_descriptor_scratch, &hero.motion.pos); - sample_path((void *)hero.rail_spline, &spatial_and_hit_descriptor_scratch, &si, &sf, 0.3f, hero.rail_spline_loops); - e = fast_arc_tan(vector_distance_xy(&hero.rail_point, &spatial_and_hit_descriptor_scratch), - spatial_and_hit_descriptor_scratch.f[2] - hero.rail_point.f[2]); + sample_path((void *)hero.rail_spline, + &spatial_and_hit_descriptor_scratch, + &si, + &sf, + 0.3f, + hero.rail_spline_loops); + e = fast_arc_tan( + vector_distance_xy(&hero.rail_point, &spatial_and_hit_descriptor_scratch), + spatial_and_hit_descriptor_scratch.f[2] - hero.rail_point.f[2]); if (e > 0.0f) { sp = e * 1.9098593f * (frame_time * -2.5f); if (e > 0.2617994f && hero.grind_pose != 2 && hero.grind_pose != 3) { @@ -2167,7 +2282,8 @@ void hero_update_movement(void) { if (hero.unk574 < 0.0f) { hero.unk574 = 0.0f; } - fast_vec_sub(&hero.motion.velocity, &movement_and_hit_descriptor_scratch, &hero.rail_point); + fast_vec_sub( + &hero.motion.velocity, &movement_and_hit_descriptor_scratch, &hero.rail_point); fast_vec_sub(&spatial_and_hit_descriptor_scratch, &hero.rail_point, &hero.motion.pos); { f32 mx = frame_time * 7.0f; @@ -2185,9 +2301,12 @@ void hero_update_movement(void) { hero.rail_snap_dist = len; } if (hero.rail_snap_dist < len) { - fast_vec_normalize(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, hero.rail_snap_dist); + fast_vec_normalize(&spatial_and_hit_descriptor_scratch, + &spatial_and_hit_descriptor_scratch, + hero.rail_snap_dist); } - fast_vec_add(&hero.motion.pos, &hero.motion.pos, &spatial_and_hit_descriptor_scratch); + fast_vec_add( + &hero.motion.pos, &hero.motion.pos, &spatial_and_hit_descriptor_scratch); } if (hero.motion.pos.f[2] < hero.rail_point.f[2] && hero.ground_distance < 1.0f && hero.motion.pos.f[2] < hero.rail_point.f[2]) { @@ -2199,12 +2318,18 @@ void hero_update_movement(void) { matrix_vector_scratch[1].f[0] = fast_cos(a); matrix_vector_scratch[1].f[1] = fast_sin(a); matrix_vector_scratch[1].f[2] = 0.0f; - make_hit_descriptor( - &spatial_and_hit_descriptor_scratch, (struct MobyView *)hero.moby, 0x10000, 1.0f, &matrix_vector_scratch[1]); + make_hit_descriptor(&spatial_and_hit_descriptor_scratch, + (struct MobyView *)hero.moby, + 0x10000, + 1.0f, + &matrix_vector_scratch[1]); qcopy(&matrix_vector_scratch[2], &hero.motion.pos); matrix_vector_scratch[2].f[2] += 0.6f; - collect_mobies_in_sphere( - 1.0f, &matrix_vector_scratch[2], 0x10, (struct MobyView *)hero.moby, &spatial_and_hit_descriptor_scratch); + collect_mobies_in_sphere(1.0f, + &matrix_vector_scratch[2], + 0x10, + (struct MobyView *)hero.moby, + &spatial_and_hit_descriptor_scratch); } break; } @@ -2218,12 +2343,14 @@ void hero_update_movement(void) { f32 a; f32 r; qcopy(&v10, &movement_and_hit_descriptor_scratch); - fast_vec_scale(&spatial_and_hit_descriptor_scratch, &hero.motion.displacement, 0.4f); + fast_vec_scale( + &spatial_and_hit_descriptor_scratch, &hero.motion.displacement, 0.4f); a = fast_add_rotations(hero.grab_rail_yaw, randf_sym(0.0f, 0.5235988f)); r = random_float_between(frame_time * 0.0f, frame_time * 4.0f); spatial_and_hit_descriptor_scratch.f[0] += fast_cos(a) * r; spatial_and_hit_descriptor_scratch.f[1] += fast_sin(a) * r; - spatial_and_hit_descriptor_scratch.f[2] = random_float_between(frame_time * 3.0f, frame_time * 5.0f); + spatial_and_hit_descriptor_scratch.f[2] = + random_float_between(frame_time * 3.0f, frame_time * 5.0f); spatial_and_hit_descriptor_scratch.f[3] = -(frame_time_sq * 35.0f); spawn_color_decaying_effect_particle(&v10, &spatial_and_hit_descriptor_scratch, 0); } @@ -2252,21 +2379,27 @@ void hero_update_movement(void) { hero.rail_candidate_kind); idx = offset_path_index( hero.follow_path_spline, hero.follow_path_segment, 1, hero.rail_candidate_kind); - fast_vec_sub(&spatial_and_hit_descriptor_scratch, (Vec4 *)hero.follow_path_spline + (idx + 1), &v10); + fast_vec_sub( + &spatial_and_hit_descriptor_scratch, (Vec4 *)hero.follow_path_spline + (idx + 1), &v10); if (fast_vec_length(&spatial_and_hit_descriptor_scratch) < 0.001f) { if (hero.follow_path_segment == idx) { hero.follow_path_end_frames = scale_game_frames(1); break; } } else { - hero.grab_rail_yaw = fast_arc_tan(spatial_and_hit_descriptor_scratch.f[0], spatial_and_hit_descriptor_scratch.f[1]); - hero.follow_path_pitch = fast_arc_tan(vector_length_xy(&spatial_and_hit_descriptor_scratch), spatial_and_hit_descriptor_scratch.f[2]); + hero.grab_rail_yaw = fast_arc_tan(spatial_and_hit_descriptor_scratch.f[0], + spatial_and_hit_descriptor_scratch.f[1]); + hero.follow_path_pitch = + fast_arc_tan(vector_length_xy(&spatial_and_hit_descriptor_scratch), + spatial_and_hit_descriptor_scratch.f[2]); } hero.motion.move_yaw = hero.grab_rail_yaw; turn_to(0, frame_scale_sq * 0.018f, frame_scale_sq * 0.2f, frame_time * 6.4577184f); approach_value(&hero.follow_path_speed, frame_time * 14.0f, frame_time_sq * 9.0f); fast_vec_sub(&hero.motion.velocity, &v10, &hero.grab_rail_point); - fast_vec_sub(&spatial_and_hit_descriptor_scratch, &hero.grab_rail_point, &movement_and_hit_descriptor_scratch); + fast_vec_sub(&spatial_and_hit_descriptor_scratch, + &hero.grab_rail_point, + &movement_and_hit_descriptor_scratch); { f32 fl; f32 len; @@ -2282,7 +2415,9 @@ void hero_update_movement(void) { hero.unk618.f = len; } if (hero.unk618.f < len) { - fast_vec_normalize(&spatial_and_hit_descriptor_scratch, &spatial_and_hit_descriptor_scratch, hero.unk618.f); + fast_vec_normalize(&spatial_and_hit_descriptor_scratch, + &spatial_and_hit_descriptor_scratch, + hero.unk618.f); } fast_vec_add(&hero.motion.pos, &hero.motion.pos, &spatial_and_hit_descriptor_scratch); } @@ -2328,7 +2463,9 @@ void hero_update_movement(void) { fast_sin(fast_add_rotations(hero.motion.rot.f[2], -1.5707964f)) * 0.3f; matrix_vector_scratch[0].f[2] = 0.0f; } - fast_vec_add(&movement_vector_scratch, &spatial_and_hit_descriptor_scratch, &matrix_vector_scratch[0]); + fast_vec_add(&movement_vector_scratch, + &spatial_and_hit_descriptor_scratch, + &matrix_vector_scratch[0]); check_ledge_grab(); if (hero.ledge_found == 0) { break; @@ -2575,7 +2712,8 @@ void hero_update_movement(void) { qcopy(&hero.takeoff_pos, &hero.motion.pos); } if (hero.rail_land_frames != 0 || - (jump_timer_or_trail_mode < jump_timer_threshold && hero.state.current != HERO_STATE_HIGH_JUMP && + (jump_timer_or_trail_mode < jump_timer_threshold && + hero.state.current != HERO_STATE_HIGH_JUMP && hero.state.current != HERO_STATE_PACK_LONG_JUMP && hero.state.current != 0xC && hero.state.current != 0x11 && hero.state.current != 0x1C && hero.state.current != 0x4C)) { @@ -2628,11 +2766,17 @@ void hero_update_movement(void) { } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&movement_and_hit_descriptor_scratch, &hero.motion.pos); - FUN_L00_00233810(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, 0.5f); + FUN_L00_00233810(&movement_and_hit_descriptor_scratch, + &movement_and_hit_descriptor_scratch, + 0.5f); qcopy(&v10, &movement_and_hit_descriptor_scratch); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; v10.f[1] += fast_sin(hero.motion.rot.f[2]) * 0.85f; - if (collision_line(&movement_and_hit_descriptor_scratch, &v10, 4, (struct MobyView *)hero.moby, 0) != 0) { + if (collision_line(&movement_and_hit_descriptor_scratch, + &v10, + 4, + (struct MobyView *)hero.moby, + 0) != 0) { hero.jump_blocked_ahead = 1; } } @@ -2676,8 +2820,10 @@ void hero_update_movement(void) { if (hero.state.current == HERO_STATE_PACK_LONG_JUMP && scale_game_frames(8) < hero.state_timer && hero.anim_frame < 28.0f) { s32 n; - transform_hero_local_offset_to_world(&movement_and_hit_descriptor_scratch, 0.8f, 0.0f, 0.3f); - n = collect_mobies_in_sphere(0.9f, &movement_and_hit_descriptor_scratch, 0, (struct MobyView *)hero.moby, NULL); + transform_hero_local_offset_to_world( + &movement_and_hit_descriptor_scratch, 0.8f, 0.0f, 0.3f); + n = collect_mobies_in_sphere( + 0.9f, &movement_and_hit_descriptor_scratch, 0, (struct MobyView *)hero.moby, NULL); if (n != 0) { s32 i; fast_vec_scale(&v10, &hero.motion.displacement, 7.0f); @@ -2722,11 +2868,13 @@ void hero_update_movement(void) { f32 l; f32 k; fast_vec_sub(&movement_and_hit_descriptor_scratch, &hero.target_pose, &hero.motion.pos); - hero.motion.move_yaw = fast_arc_tan(movement_and_hit_descriptor_scratch.f[0], movement_and_hit_descriptor_scratch.f[1]); + hero.motion.move_yaw = fast_arc_tan(movement_and_hit_descriptor_scratch.f[0], + movement_and_hit_descriptor_scratch.f[1]); l = vector_length_xy(&movement_and_hit_descriptor_scratch); if (l > 0.2f) { hero.stick_magnitude = 1.0f; - hero.motion.move_yaw = fast_arc_tan(movement_and_hit_descriptor_scratch.f[0], movement_and_hit_descriptor_scratch.f[1]); + hero.motion.move_yaw = fast_arc_tan(movement_and_hit_descriptor_scratch.f[0], + movement_and_hit_descriptor_scratch.f[1]); hero.target_speed = l; if (l < D_L00_0017BDB8.x0C) { hero.target_speed = D_L00_0017BDB8.x08 * frame_time; @@ -2835,18 +2983,31 @@ void hero_update_movement(void) { s32 ok; tb = &attack_records[hero.attack_record]; hero.target_speed = 0.0f; - if ((tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE ? 1 : tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) && hero.anim_frame < 5.5f) { + if ((tb->kind == HERO_COMBO_KIND_FRAME_GATED_FORWARD_ADVANCE + ? 1 + : tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION) && + hero.anim_frame < 5.5f) { hero.target_speed = frame_time * 3.5f; } if (hero.anim_changing == 0 && (f32)tb->f1C <= hero.anim_frame && hero.anim_frame <= (f32)tb->f20) { s32 k = tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION ? 0 : 2; moby_point_position((struct MobyView *)hero.moby, k, &v10); - moby_point_position((struct MobyView *)hero.moby, k | 1, &spatial_and_hit_descriptor_scratch); - fast_vec_add(&movement_and_hit_descriptor_scratch, &v10, &spatial_and_hit_descriptor_scratch); - fast_vec_scale(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, 0.5f); - play_entity_sound( - (struct MobyView *)hero.moby, 0.25f, &movement_and_hit_descriptor_scratch, 0x10000, 1.0f, 1.0f, 0, 1, 0); + moby_point_position( + (struct MobyView *)hero.moby, k | 1, &spatial_and_hit_descriptor_scratch); + fast_vec_add( + &movement_and_hit_descriptor_scratch, &v10, &spatial_and_hit_descriptor_scratch); + fast_vec_scale( + &movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, 0.5f); + play_entity_sound((struct MobyView *)hero.moby, + 0.25f, + &movement_and_hit_descriptor_scratch, + 0x10000, + 1.0f, + 1.0f, + 0, + 1, + 0); } approach_value(&hero.anim_speed, 1.0f, 0.2f); if (hero.heading_locked != 0 || (struct MobyView *)hero.melee_target != NULL) { @@ -2860,7 +3021,8 @@ void hero_update_movement(void) { turn_to(0, frame_scale_sq * 0.05f, frame_scale_sq * 0.2f, frame_time * 15.009831f); } else { ok = 1; - if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && hero.anim_changing == 0 && hero.anim_frame > 7.0f) { + if (tb->kind == HERO_COMBO_KIND_STAGED_FORWARD_DECELERATION && + hero.anim_changing == 0 && hero.anim_frame > 7.0f) { ok = 0; } if (ok) { @@ -2986,7 +3148,9 @@ void hero_update_movement(void) { fast_sin(fast_add_rotations(hero.motion.rot.f[2], -1.5707964f)) * 0.3f; matrix_vector_scratch[0].f[2] = 0.0f; } - fast_vec_add(&movement_vector_scratch, &spatial_and_hit_descriptor_scratch, &matrix_vector_scratch[0]); + fast_vec_add(&movement_vector_scratch, + &spatial_and_hit_descriptor_scratch, + &matrix_vector_scratch[0]); check_ledge_grab(); if (hero.ledge_found == 0) { break; @@ -3056,25 +3220,44 @@ void hero_update_movement(void) { switch (hero.attack_record) { case HERO_ATTACK_RECORD_POINT_3_STRIKE: if (hero.anim_frame > 7.0f && hero.anim_frame < 14.0f) { - moby_point_position((struct MobyView *)hero.moby, 3, &movement_and_hit_descriptor_scratch); - collect_mobies_in_sphere(2.0f, &movement_and_hit_descriptor_scratch, 0x10, (struct MobyView *)hero.moby, &v10); + moby_point_position( + (struct MobyView *)hero.moby, 3, &movement_and_hit_descriptor_scratch); + collect_mobies_in_sphere(2.0f, + &movement_and_hit_descriptor_scratch, + 0x10, + (struct MobyView *)hero.moby, + &v10); } break; case HERO_ATTACK_RECORD_POINT_4_STRIKE: if (hero.anim_frame > 7.0f && hero.anim_frame < 14.0f) { - moby_point_position((struct MobyView *)hero.moby, 4, &movement_and_hit_descriptor_scratch); - collect_mobies_in_sphere(2.0f, &movement_and_hit_descriptor_scratch, 0x10, (struct MobyView *)hero.moby, &v10); + moby_point_position( + (struct MobyView *)hero.moby, 4, &movement_and_hit_descriptor_scratch); + collect_mobies_in_sphere(2.0f, + &movement_and_hit_descriptor_scratch, + 0x10, + (struct MobyView *)hero.moby, + &v10); } break; case HERO_ATTACK_RECORD_PAIRED_POINT_STRIKE: if (hero.anim_frame > 14.0f && hero.anim_frame < 21.0f) { f32 sphere_radius = 2.0f; - moby_point_position((struct MobyView *)hero.moby, 3, &movement_and_hit_descriptor_scratch); - collect_mobies_in_sphere( - sphere_radius, &movement_and_hit_descriptor_scratch, 0x10, (struct MobyView *)hero.moby, &v10); + moby_point_position( + (struct MobyView *)hero.moby, 3, &movement_and_hit_descriptor_scratch); + collect_mobies_in_sphere(sphere_radius, + &movement_and_hit_descriptor_scratch, + 0x10, + (struct MobyView *)hero.moby, + &v10); sphere_radius = 0.0f; - moby_point_position((struct MobyView *)hero.moby, 4, &movement_and_hit_descriptor_scratch); - collect_mobies_in_sphere(2.0f, &movement_and_hit_descriptor_scratch, 0x10, (struct MobyView *)hero.moby, &v10); + moby_point_position( + (struct MobyView *)hero.moby, 4, &movement_and_hit_descriptor_scratch); + collect_mobies_in_sphere(2.0f, + &movement_and_hit_descriptor_scratch, + 0x10, + (struct MobyView *)hero.moby, + &v10); } break; } @@ -3159,7 +3342,8 @@ void hero_update_movement(void) { f32 effect_pitch = z; z = 1.0f; for (i = 0; i < 2; i++) { - moby_point_position((struct MobyView *)hero.moby, i + 3, &movement_and_hit_descriptor_scratch); + moby_point_position( + (struct MobyView *)hero.moby, i + 3, &movement_and_hit_descriptor_scratch); movement_and_hit_descriptor_scratch.f[0] += fast_cos(hero.motion.rot.f[2]) * 1.4f; movement_and_hit_descriptor_scratch.f[1] += fast_sin(hero.motion.rot.f[2]) * 1.4f; spawn_giant_clank_missile((struct MobyView *)hero.moby, @@ -3185,7 +3369,15 @@ void hero_update_movement(void) { stick_target(frame_time * 6.0f, 0); qcopy(&movement_and_hit_descriptor_scratch, &hero.motion.pos); movement_and_hit_descriptor_scratch.f[2] -= 1.0f; - play_entity_sound((struct MobyView *)hero.moby, 3.5f, &movement_and_hit_descriptor_scratch, 0x30000, 40.0f, 1.0f, 0, 1, 0); + play_entity_sound((struct MobyView *)hero.moby, + 3.5f, + &movement_and_hit_descriptor_scratch, + 0x30000, + 40.0f, + 1.0f, + 0, + 1, + 0); if (hero.move_lock_timer == 0) { hero_move_state_velocity(); } @@ -3203,9 +3395,19 @@ void hero_update_movement(void) { d = fast_difference_between_rotations(hero.motion.rot.f[2], hero.motion.move_yaw); for (i = 0; i < 3; i++) { transform_hero_polar_offset_to_world( - &movement_and_hit_descriptor_scratch, 1.8f, fast_add_rotations(-0.7853982f, (f32)i * 0.7853982f), 1.4f); - play_entity_sound( - (struct MobyView *)hero.moby, 2.7f, &movement_and_hit_descriptor_scratch, 0x30000, 40.0f, 1.0f, 0, 1, 0); + &movement_and_hit_descriptor_scratch, + 1.8f, + fast_add_rotations(-0.7853982f, (f32)i * 0.7853982f), + 1.4f); + play_entity_sound((struct MobyView *)hero.moby, + 2.7f, + &movement_and_hit_descriptor_scratch, + 0x30000, + 40.0f, + 1.0f, + 0, + 1, + 0); } if (test_hero_animation_frame_window(30.0f) != 0 || test_hero_animation_frame_window(0.0f) != 0) { diff --git a/src/overlays/shared/hero/hero_update_transitions.c b/src/overlays/shared/hero/hero_update_transitions.c index 80ffa368f3..099bccd156 100644 --- a/src/overlays/shared/hero/hero_update_transitions.c +++ b/src/overlays/shared/hero/hero_update_transitions.c @@ -200,8 +200,10 @@ void hero_update_transitions(void) { try_start_hero_weapon_fire_state() == 0) { if ((controller_state.pressed & 0x10) || (controller_state.pressed_unmasked & 0x10)) { if (hero.items[0].switch_lock != 2 && D_L00_0015F594 == 0 && - (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0) && - (hero.item_select_blocked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0)) { + (hero.item_use_locked == 0 || hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || + hero.unk1B2 != 0) && + (hero.item_select_blocked == 0 || + hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK || hero.unk1B2 != 0)) { switch (hero.vehicle_mode) { case HERO_VEHICLE_MODE_ON_FOOT: case 3: { @@ -1035,7 +1037,8 @@ void hero_update_transitions(void) { break; } } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && frame_time * 2.7f <= hero.motion.speed_xy) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + frame_time * 2.7f <= hero.motion.speed_xy) { hero_set_state(0x66, 1); } break; diff --git a/src/overlays/shared/hero/process_hero_primary_item_input.c b/src/overlays/shared/hero/process_hero_primary_item_input.c index 2487a091e2..415e865cad 100644 --- a/src/overlays/shared/hero/process_hero_primary_item_input.c +++ b/src/overlays/shared/hero/process_hero_primary_item_input.c @@ -395,7 +395,8 @@ void apply_hero_item_slot_selection(int i) { if (item_switch_gate_state == ITEM_SWITCH_GATE_BLOCK_SWITCH) { changed = 0; } - if (item_switch_gate_state == ITEM_SWITCH_GATE_RELOAD_ZERO_TIMER && s->items[0].timer == 0) { + if (item_switch_gate_state == ITEM_SWITCH_GATE_RELOAD_ZERO_TIMER && + s->items[0].timer == 0) { s->items[0].timer = s->items[0].timer_reload; } } @@ -1824,7 +1825,8 @@ extern s32 current_level_index __asm__("D_0015ED84") __attribute__((sda)); extern float frame_time __asm__("D_0015ED6C") MACRO_ADDR; extern void fast_vec_normalize(void *, void *, float) __asm__("FUN_001f9bf8"); extern int offset_path_index(void *, int, int, int) __asm__("FUN_L00_0025d7a0"); -extern int l05_hoverboard_trick_landing_frame_thresholds __asm__("D_L05_0015F698") __attribute__((sda)); +extern int l05_hoverboard_trick_landing_frame_thresholds __asm__("D_L05_0015F698") + __attribute__((sda)); int hero_pick_help_mode(void) __asm__("FUN_L05_00255208"); @@ -1945,7 +1947,8 @@ int hero_pick_help_mode(void) { goto change_state; } if ((unsigned)(*((unsigned char *)(&hero)->moby + 0x53) - 0x69) < 4 && - (&hero)->anim_frame < (float)(&l05_hoverboard_trick_landing_frame_thresholds)[(&hero)->air_pose_index]) { + (&hero)->anim_frame < + (float)(&l05_hoverboard_trick_landing_frame_thresholds)[(&hero)->air_pose_index]) { state = HERO_STATE_HOVERBOARD_RESPAWN_HEIGHT_OR_ANIMATION_WAIT; goto change_state; } diff --git a/src/overlays/shared/hero/set_hero_animation.c b/src/overlays/shared/hero/set_hero_animation.c index 988fc1c0aa..3207f80cb7 100644 --- a/src/overlays/shared/hero/set_hero_animation.c +++ b/src/overlays/shared/hero/set_hero_animation.c @@ -920,8 +920,11 @@ int resolve_hero_gravity_mode(void) { int state = hero_gravity_mode_state->state.current; int return_value = hero_gravity_mode_state->unk308; - if (state == HERO_STATE_DIRECTION_LIMITED_GROUND_MOVE || state == HERO_STATE_ANIMATION_FRAME_EXIT_WAIT || state == HERO_STATE_ATTACK_RECORD_FRAME_EXIT_WAIT || - (hero_gravity_mode_state->on_magnet_ground != 0 && D_0013D4DC[0] != 0 && state == HERO_STATE_IDLE && + if (state == HERO_STATE_DIRECTION_LIMITED_GROUND_MOVE || + state == HERO_STATE_ANIMATION_FRAME_EXIT_WAIT || + state == HERO_STATE_ATTACK_RECORD_FRAME_EXIT_WAIT || + (hero_gravity_mode_state->on_magnet_ground != 0 && D_0013D4DC[0] != 0 && + state == HERO_STATE_IDLE && hero_gravity_mode_state->air_frames.s < scale_game_frames(4))) { return_value = 1; } diff --git a/src/overlays/shared/hero/update_hero_ground_contact.c b/src/overlays/shared/hero/update_hero_ground_contact.c index 5f05c2dae0..24953985e3 100644 --- a/src/overlays/shared/hero/update_hero_ground_contact.c +++ b/src/overlays/shared/hero/update_hero_ground_contact.c @@ -188,7 +188,8 @@ void update_hero_ground_contact(void) { } if (hero.ground_distance < 0.02f) { hero.frames_off_ground.s = 0; - if (hero.ground_slope.f <= 0.87266463f || hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || + if (hero.ground_slope.f <= 0.87266463f || + hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.state.control_mode == 0x16) { hero.air_frames.s = 0; hero.last_landed_moby = HH.moby; diff --git a/src/overlays/shared/math/interpolation/spring_turn.c b/src/overlays/shared/math/interpolation/spring_turn.c index f2847b12f2..69ee2c836d 100644 --- a/src/overlays/shared/math/interpolation/spring_turn.c +++ b/src/overlays/shared/math/interpolation/spring_turn.c @@ -194,11 +194,26 @@ extern int FUN_L00_001f0d60_258490(void *, float, int, void *) __asm__("FUN_L0 int move_moby_xy_with_collision_constraints( - void *ign, V_258490 *to, V_258490 *pos, int flags, float h, float r, float lim, float slope) __asm__("FUN_L00_00258490"); + void *ign, + V_258490 *to, + V_258490 *pos, + int flags, + float h, + float r, + float lim, + float slope) __asm__("FUN_L00_00258490"); int move_moby_xy_with_collision_constraints( - void *ign, V_258490 *to, V_258490 *proposed_position, int flags, float collision_height_offset, float collision_radius, float ground_height_difference_limit, float slope) { + void *ign, + V_258490 *to, + V_258490 *proposed_position, + int flags, + float collision_height_offset, + float collision_radius, + float ground_height_difference_limit, + + float slope) { V_258490 movement_displacement; V_258490 line_probe_displacement; V_258490 line_probe_start; @@ -233,15 +248,19 @@ int move_moby_xy_with_collision_constraints( up.f[2] = collision_height_offset; fast_vec_add(&line_probe_start, to, &up); fast_vec_add(&line_probe_end, &line_probe_start, &line_probe_displacement); - if (ok && FUN_001efa68_258490(&line_probe_start, &line_probe_end, line_collision_flag_bit_2 | 0x24, ign, 0)) { + if (ok && FUN_001efa68_258490( + &line_probe_start, &line_probe_end, line_collision_flag_bit_2 | 0x24, ign, 0)) { line_collision_result = D_L00_00173E40_258490; if (*(int *)(line_collision_result + 0x1C) > 0) { nrm = (float *)(line_collision_result + 0x40); - if (slope <= fast_arc_tan(*(float *)(line_collision_result + 0x48), vector_length_xy(nrm))) { + if (slope <= + fast_arc_tan(*(float *)(line_collision_result + 0x48), vector_length_xy(nrm))) { *(int *)(line_collision_result + 0x48) = 0; sceVu0Normalize(nrm, nrm); { - float k = -movement_displacement.f[0] * *(float *)(line_collision_result + 0x40) - movement_displacement.f[1] * *(float *)(line_collision_result + 0x44); + float k = + -movement_displacement.f[0] * *(float *)(line_collision_result + 0x40) - + movement_displacement.f[1] * *(float *)(line_collision_result + 0x44); if (0.0f < k) { fast_vec_scale(nrm, nrm, k); ok = 0; @@ -263,7 +282,9 @@ int move_moby_xy_with_collision_constraints( if (!FUN_L00_001f0d60_258490(&sphere_probe_center, collision_radius, 0x24, ign)) { break; } - sphere_contact_angle = fast_arc_tan(vector_distance_xy(proposed_position, sphere_contact_position), *(float *)(sphere_collision_result + 0x28) - proposed_position->f[2]); + sphere_contact_angle = + fast_arc_tan(vector_distance_xy(proposed_position, sphere_contact_position), + *(float *)(sphere_collision_result + 0x28) - proposed_position->f[2]); if (*(int *)(sphere_collision_result + 0x18) != 0 || slope < sphere_contact_angle) { qcopy(proposed_position, &coll_hit_position); ok = 0; @@ -361,7 +382,8 @@ int move_moby_with_step_collision(char *moby, if (D_L00_00173E40[7] > 0) { float ground_normal_angle_or_hit_height; movement_collision_result_flags |= 2; - ground_normal_angle_or_hit_height = fast_arc_tan(*(float *)((char *)D_L00_00173E40 + 0x48), + ground_normal_angle_or_hit_height = + fast_arc_tan(*(float *)((char *)D_L00_00173E40 + 0x48), vector_length_xy((char *)D_L00_00173E40 + 0x40)); if (ground_normal_angle_or_hit_height > 0.5f) { movement_collision_result_flags |= 4; @@ -581,8 +603,8 @@ s32 FUN_L00_00258b50(Obj *moby, void approach_w(unsigned char *, float *, float, float, float, float) __asm__("FUN_L00_00258278"); int move_w(unsigned char *, char *, float *, void *, float) __asm__("FUN_L00_00258b50"); -int step_mover_2e3f20(unsigned char *m, char *c, float *tgt, void *out) __asm__("FUN_L00_00259028"); -int step_mover_2e3f20(unsigned char *moby, +int step_mover_2e3f20(unsigned char *m, char *c, float *tgt, void *out) __asm__("FUN_L00_00259028"); +int step_mover_2e3f20(unsigned char *moby, char *movement_control, float *target_position, diff --git a/src/overlays/shared/mobys/allocate_moby_animation_slot.c b/src/overlays/shared/mobys/allocate_moby_animation_slot.c index 41f769f995..dc2abad18d 100644 --- a/src/overlays/shared/mobys/allocate_moby_animation_slot.c +++ b/src/overlays/shared/mobys/allocate_moby_animation_slot.c @@ -197,7 +197,8 @@ void advance_moby_animation_blend(void *unused, unsigned char *animation_state) float unscaled_frame_step = *(float *)(animation_state + 0x28); animation_state[5] = 0; if (unscaled_frame_step != 0.0f && *(float *)(animation_state + 0x2C) != 0.0f) { - float advanced_frame_progress = *(float *)(animation_state + 0x24) + unscaled_frame_step * *(float *)(animation_state + 0x2C); + float advanced_frame_progress = *(float *)(animation_state + 0x24) + + unscaled_frame_step * *(float *)(animation_state + 0x2C); *(float *)(animation_state + 0x24) = advanced_frame_progress; if (unscaled_frame_step > 0.0f) { if (advanced_frame_progress > 0.99f && advanced_frame_progress < 1.01f) { @@ -217,28 +218,37 @@ void advance_moby_animation_blend(void *unused, unsigned char *animation_state) animation_state[0x21]++; o = animation_state[0x23] * 4; if (animation_state[0x21] >= - *(unsigned char *)(*(int *)(*(unsigned char **)(animation_state + 0x14) + o + 0x48) + + *(unsigned char *)(*(int *)(*(unsigned char **)(animation_state + 0x14) + + o + 0x48) + 0x10)) { animation_state[0x21] = 0; animation_state[5] |= 2; } { - float unscaled_frame_remainder = (*(float *)(animation_state + 0x24) - 1.0f) / *(float *)(animation_state + 0x2C); + float unscaled_frame_remainder = + (*(float *)(animation_state + 0x24) - 1.0f) / + *(float *)(animation_state + 0x2C); float frame_progress_scale; animation_table_byte_offset = animation_state[0x22] * 4; p = animation_state[0x20] * 4; *(float *)(animation_state + 0x24) = unscaled_frame_remainder; - frame_progress_scale = **(float **)(*(int *)(*(unsigned char **)(animation_state + 0x14) + animation_table_byte_offset + 0x48) + p + - 0x1C); + frame_progress_scale = + **(float **)(*(int *)(*(unsigned char **)(animation_state + 0x14) + + animation_table_byte_offset + 0x48) + + p + 0x1C); *(float *)(animation_state + 0x2C) = frame_progress_scale; - *(float *)(animation_state + 0x24) = unscaled_frame_remainder * frame_progress_scale; + *(float *)(animation_state + 0x24) = + unscaled_frame_remainder * frame_progress_scale; } } while (*(float *)(animation_state + 0x24) >= 1.0f); } } } if (animation_state[6]) { - FUN_L00_0024f440(animation_state, animation_state[0x22], animation_state[0x20], *(int *)(animation_state + 0x38)); + FUN_L00_0024f440(animation_state, + animation_state[0x22], + animation_state[0x20], + *(int *)(animation_state + 0x38)); } else { int o = animation_state[0x22] * 4; int p = animation_state[0x20] * 4; @@ -246,7 +256,10 @@ void advance_moby_animation_blend(void *unused, unsigned char *animation_state) *(int *)(*(int *)(*(unsigned char **)(animation_state + 0x14) + o + 0x48) + p + 0x1C); } if (animation_state[7]) { - FUN_L00_0024f440(animation_state, animation_state[0x23], animation_state[0x21], *(int *)(animation_state + 0x3C)); + FUN_L00_0024f440(animation_state, + animation_state[0x23], + animation_state[0x21], + *(int *)(animation_state + 0x3C)); } else { int o = animation_state[0x23] * 4; int p = animation_state[0x21] * 4; diff --git a/src/overlays/shared/mobys/evaluate_moby_animation_pose.c b/src/overlays/shared/mobys/evaluate_moby_animation_pose.c index 240a217455..87b4e56af2 100644 --- a/src/overlays/shared/mobys/evaluate_moby_animation_pose.c +++ b/src/overlays/shared/mobys/evaluate_moby_animation_pose.c @@ -44,7 +44,9 @@ int FUN_L00_00257218_u3(Moby257218 *drop_source_moby, int *pickup_item_type) { int drops = 1; if (*pickup_item_type <= 0 || - (drop_source_moby != 0 && (D_0014C190[D_0015ED84][(s16)drop_source_moby->uid >> 5] >> (drop_source_moby->uid & 0x1F)) & 1)) { + (drop_source_moby != 0 && (D_0014C190[D_0015ED84][(s16)drop_source_moby->uid >> 5] >> + (drop_source_moby->uid & 0x1F)) & + 1)) { for (i = 0; i < 12 && D_0015EDD0_macro[i] != 0xFF; i++) { x = D_0015EDD0_macro[i] & 0x3F; if (item_available[x]) { diff --git a/src/overlays/shared/mobys/select_auto_aim_target_moby.c b/src/overlays/shared/mobys/select_auto_aim_target_moby.c index 60a4ae2b00..1bb79b2e6f 100644 --- a/src/overlays/shared/mobys/select_auto_aim_target_moby.c +++ b/src/overlays/shared/mobys/select_auto_aim_target_moby.c @@ -463,7 +463,9 @@ void queue_formatted_dialogue_message(s32 help_message_selector, s32 message_duration_frames) { if (message_duration_frames == -1) message_duration_frames = scale_game_frames(0xB4); - sprintf(l00_dialogue_message_text_buffer, get_help_message_text(help_message_selector), format_argument); + sprintf(l00_dialogue_message_text_buffer, + get_help_message_text(help_message_selector), + format_argument); D_L00_0015F640 = message_duration_frames; } diff --git a/src/overlays/shared/mobys/test_path_segment_strict_crossing.c b/src/overlays/shared/mobys/test_path_segment_strict_crossing.c index dd9cceda73..8c183fd2a2 100644 --- a/src/overlays/shared/mobys/test_path_segment_strict_crossing.c +++ b/src/overlays/shared/mobys/test_path_segment_strict_crossing.c @@ -110,7 +110,11 @@ typedef struct { int FUN_L00_00261b48(int idx, void *a, void *b, void *c); -int FUN_L00_00261b48(int segment_path_index, void *segment_start, void *segment_end, void *adjusted_endpoint) { +int FUN_L00_00261b48(int segment_path_index, + void *segment_start, + void *segment_end, + + void *adjusted_endpoint) { float v[4], perpendicular_xy_axis[4], z[4], previous_path_point_in_basis[4], u[4]; float best; float zero; @@ -128,7 +132,9 @@ int FUN_L00_00261b48(int segment_path_index, void *segment_start, void *segment_ clear_u64_value(z); z[2] = 1.0f; best = 1.0f; - fast_vec_sub(previous_path_point_in_basis, (char *)((SegmentPath **)D_L00_001B04B0_261968)[segment_path_index] + 0x10, segment_start); + fast_vec_sub(previous_path_point_in_basis, + (char *)((SegmentPath **)D_L00_001B04B0_261968)[segment_path_index] + 0x10, + segment_start); transform_vector_by_basis(previous_path_point_in_basis, previous_path_point_in_basis, v); previous_path_point_slot = previous_path_point_in_basis; current_path_point_slot = u; @@ -136,11 +142,16 @@ int FUN_L00_00261b48(int segment_path_index, void *segment_start, void *segment_ offset = 0x20; zero = 0.0f; do { - fast_vec_sub(current_path_point_slot, (char *)((SegmentPath **)D_L00_001B04B0_261968)[segment_path_index] + offset, segment_start); + fast_vec_sub(current_path_point_slot, + (char *)((SegmentPath **)D_L00_001B04B0_261968)[segment_path_index] + + offset, + segment_start); transform_vector_by_basis(current_path_point_slot, current_path_point_slot, v); if (previous_path_point_in_basis[3] != zero || u[3] != zero) { if (u[1] * previous_path_point_in_basis[1] < 0.0f) { - float x = (previous_path_point_in_basis[0] - u[0]) / (previous_path_point_in_basis[1] - u[1]) * -u[1] + u[0]; + float x = (previous_path_point_in_basis[0] - u[0]) / + (previous_path_point_in_basis[1] - u[1]) * -u[1] + + u[0]; if (x > 0.0f && x < best) { best = x; found = 1; @@ -345,7 +356,13 @@ void path_sample_at_distance(PointPath *path, f32 spacing) __asm__("FUN_L00_00262360"); void path_sample_at_distance( - PointPath *path, s32 *seg_out, f32 *along, Vec4 *sampled_position, f32 path_distance, f32 spacing) { + PointPath *path, + s32 *seg_out, + f32 *along, + Vec4 *sampled_position, + f32 path_distance, + + f32 spacing) { Vec4 sampling_intermediate; s32 seg; diff --git a/src/overlays/shared/mobys/update_object_wander_movement.c b/src/overlays/shared/mobys/update_object_wander_movement.c index f5c892759d..5298532046 100644 --- a/src/overlays/shared/mobys/update_object_wander_movement.c +++ b/src/overlays/shared/mobys/update_object_wander_movement.c @@ -12,7 +12,8 @@ #include "rnc/overlay/shared/mobys/find_moby_hit.h" void step_angle_toward_target(void *, s32, f32, f32) __asm__("FUN_L00_0025bc00"); -s32 move_moby_xy_with_collision_constraints(void *, void *, void *, s32, f32, f32, f32, f32) __asm__("FUN_L00_00258490"); +s32 move_moby_xy_with_collision_constraints( + void *, void *, void *, s32, f32, f32, f32, f32) __asm__("FUN_L00_00258490"); void update_object_wander_movement(u8 *moving_object, u8 *movement_state, f32 a, @@ -47,14 +48,15 @@ void update_object_wander_movement(u8 *moving_object, fast_cos(*(f32 *)(moving_object + 0x48)) * *(f32 *)(movement_state + 0x14); ((f32 *)proposed_position)[1] += fast_sin(*(f32 *)(moving_object + 0x48)) * *(f32 *)(movement_state + 0x14); - movement_unconstrained = move_moby_xy_with_collision_constraints(moving_object, - pos, - proposed_position, - 0, - collision_height_offset, - *(f32 *)(movement_state + 0x10), - ground_height_difference_limit, - 0.52359879f); + movement_unconstrained = + move_moby_xy_with_collision_constraints(moving_object, + pos, + proposed_position, + 0, + collision_height_offset, + *(f32 *)(movement_state + 0x10), + ground_height_difference_limit, + 0.52359879f); *(f32 *)(moving_object + 0x18) = probe_ground_height(pos, 0, 0.5f); planar_distance = vector_distance_xy(pos, movement_state); if (movement_unconstrained == 0 || *(f32 *)(movement_state + 0x1C) < planar_distance) { diff --git a/src/overlays/shared/pickups/buried_bolts.c b/src/overlays/shared/pickups/buried_bolts.c index da2b44b719..3cb4b89406 100644 --- a/src/overlays/shared/pickups/buried_bolts.c +++ b/src/overlays/shared/pickups/buried_bolts.c @@ -32,7 +32,11 @@ void buried_bolts_update(struct Moby *moby) __asm__("FUN_L01_002f2eb8"); /* Moby class 605 */ void buried_bolts_update(struct Moby *moby) { - enum { AREA_MOBY_STATE_UNINITIALIZED = 0 , AREA_MOBY_STATE_INITIALIZED = 1 } ;AreaVars *area_vars = (AreaVars *)moby->pvars; + enum { + AREA_MOBY_STATE_UNINITIALIZED = 0, + AREA_MOBY_STATE_INITIALIZED = 1 + }; + AreaVars *area_vars = (AreaVars *)moby->pvars; Vec4 target; s32 k; s32 *path; diff --git a/src/overlays/shared/pickups/crate.c b/src/overlays/shared/pickups/crate.c index 099c27ea71..5368aebfce 100644 --- a/src/overlays/shared/pickups/crate.c +++ b/src/overlays/shared/pickups/crate.c @@ -664,7 +664,8 @@ void ground_attached_update(M_2cfcb8 *moby) { M_2cfcb8 *later_group_member; Vars *vars; Vars *below_vars; - V_2cfcb8 *ungrouped_crate_position, *group_crate_probe_position, *stacked_crate_position, *stack_base_probe_position; + V_2cfcb8 *ungrouped_crate_position, *group_crate_probe_position, *stacked_crate_position, + *stack_base_probe_position; R_2cfcb8 *route; s32 group, flags_before, i, member_flags; M_2cfcb8 *below; @@ -762,7 +763,8 @@ void ground_attached_update(M_2cfcb8 *moby) { stacked_crate_position = &moby->pos; below = (*(H_2cfcb8 *)&D_L00_00173E40).moby; qcopy(stacked_crate_position, &below->pos); - FUN_001f9a10_2cfcb8(stacked_crate_position, stacked_crate_position, (u8 *)below + 0xE0); + FUN_001f9a10_2cfcb8( + stacked_crate_position, stacked_crate_position, (u8 *)below + 0xE0); vars = (*(H_2cfcb8 *)&D_L00_00173E40).moby->vars; if (is_moby_in_class_range_500_to_540(moby) != 0) { vars->next_member = moby; diff --git a/src/overlays/shared/pickups/fighter_jet_crate.c b/src/overlays/shared/pickups/fighter_jet_crate.c index 62e1a0a1e4..62e497a931 100644 --- a/src/overlays/shared/pickups/fighter_jet_crate.c +++ b/src/overlays/shared/pickups/fighter_jet_crate.c @@ -92,7 +92,8 @@ void ammocrate_update(char *moby) { int target_index = pickup_private_state[0]; int target_base = (int)moby_base; struct Moby *target = (struct Moby *)(target_base + target_index * 0x100); - if (target != 0 && target->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && target->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && + if (target != 0 && target->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + target->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && pickup_private_state[1] != -1 && target->state != pickup_private_state[1]) { goto frame_tail; } @@ -133,7 +134,8 @@ void ammocrate_update(char *moby) { if (moby_class == 0x4da || moby_class == 0x45 || moby_class == 0x563) hit = 1; } - if (hero.state.current == 0x32 && hero_moby != 0 && MOBY(hero_moby)->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + if (hero.state.current == 0x32 && hero_moby != 0 && + MOBY(hero_moby)->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && MOBY(hero_moby)->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END) { short moby_class = MOBY(hero_moby)->oclass; if (moby_class == 0x4da || moby_class == 0x45 || moby_class == 0x563) diff --git a/src/overlays/shared/pickups/gadget_pickup.c b/src/overlays/shared/pickups/gadget_pickup.c index cd83610a4b..22c2d49e36 100644 --- a/src/overlays/shared/pickups/gadget_pickup.c +++ b/src/overlays/shared/pickups/gadget_pickup.c @@ -168,17 +168,18 @@ void tresspasser_update(struct Moby *moby) { gadget_pickup_state + 0x40, gadget_pickup_state + 0x44); lerp_vector(position, (void *)a, (void *)b, *(float *)(gadget_pickup_state + 0x40)); - output[2] = - fast_add_rotations(fast_subtract_rotations(d[2], c[2]) * *(float *)(gadget_pickup_state + 0x40), c[2]); - output[1] = - fast_add_rotations(fast_subtract_rotations(d[1], c[1]) * *(float *)(gadget_pickup_state + 0x40), c[1]); - output[0] = - fast_add_rotations(fast_subtract_rotations(d[0], c[0]) * *(float *)(gadget_pickup_state + 0x40), c[0]); + output[2] = fast_add_rotations( + fast_subtract_rotations(d[2], c[2]) * *(float *)(gadget_pickup_state + 0x40), c[2]); + output[1] = fast_add_rotations( + fast_subtract_rotations(d[1], c[1]) * *(float *)(gadget_pickup_state + 0x40), c[1]); + output[0] = fast_add_rotations( + fast_subtract_rotations(d[0], c[0]) * *(float *)(gadget_pickup_state + 0x40), c[0]); if (D_L02_00167400 && *(short *)(D_L02_00167400 + 0x86) != 5) jet_mount(position, output, 1, 0, 0); set_camera_position(position); set_camera_rotation(output); - if (D_L02_00179A10.i0 == 0 && D_L02_00179A10.i24 == -1 && 0.2f < *(float *)(gadget_pickup_state + 0x40)) { + if (D_L02_00179A10.i0 == 0 && D_L02_00179A10.i24 == -1 && + 0.2f < *(float *)(gadget_pickup_state + 0x40)) { approach_value(1.0f, frame_time * 4.0f, &D_L02_0015F3FC); } else { approach_value(0.0f, D_0015ED6C * 4.0f, &D_L02_0015F3FC); @@ -259,13 +260,13 @@ void update_collectible_sprite_effect(char *moby) { col = func_001FA8A8_2ebce8_ea8b0( 0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - timer_elapsed_fraction)); spawn_timed_hero_relative_particle(d, - col, - truncate_float_to_s32(sprite_data->a[i]) & 0xFF, - 0x35, - 1, - 2, - 0, - sprite_data->d[i]); + col, + truncate_float_to_s32(sprite_data->a[i]) & 0xFF, + 0x35, + 1, + 2, + 0, + sprite_data->d[i]); fast_vec_add(d, d, sprite_position_step); } } diff --git a/src/overlays/shared/pickups/gold_bolt.c b/src/overlays/shared/pickups/gold_bolt.c index fe3c478e1d..6d196deecc 100644 --- a/src/overlays/shared/pickups/gold_bolt.c +++ b/src/overlays/shared/pickups/gold_bolt.c @@ -66,9 +66,10 @@ extern void FUN_L01_003089f0_f(struct Moby *) __asm__("FUN_L01_003089f void update_gold_bolt_glow_rings(struct Moby *m) __asm__("FUN_L01_00308550"); extern void FUN_L01_003089f0_u(char *) __asm__("FUN_L01_003089f0"); extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); -extern unsigned char *spawn_timed_hero_relative_particle(void *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); -extern void spawn_moving_hero_relative_alpha_fade_particle( - void *, void *, int, int, int, int, float) __asm__("FUN_L00_002730e0"); +extern unsigned char *spawn_timed_hero_relative_particle( + void *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); +extern void spawn_moving_hero_relative_alpha_fade_particle( + void *, void *, int, int, int, int, float) __asm__("FUN_L00_002730e0"); extern s32 D_0015ED84; extern char camera_pos[] __asm__("D_L01_00167240"); @@ -83,7 +84,8 @@ extern s32 cutscene_active __asm__("D_L01_0015F404"); extern f32 D_L01_00161F10_gp __asm__("D_L01_00161F10") __attribute__((sda)); extern f32 l01_gold_bolt_bobbing_height_offset_gp __asm__("D_L01_00161F14") __attribute__((sda)); extern f32 l01_gold_bolt_bobbing_amplitude_gp __asm__("D_L01_00161F18") __attribute__((sda)); -extern f32 l01_gold_bolt_bobbing_phase_degrees_per_second_gp __asm__("D_L01_00161F2C") __attribute__((sda)); +extern f32 l01_gold_bolt_bobbing_phase_degrees_per_second_gp __asm__("D_L01_00161F2C") + __attribute__((sda)); extern s32 D_L01_00161F50_gp __asm__("D_L01_00161F50") __attribute__((sda)); extern f32 gold_bolt_spin_x_degrees_per_second_gp __asm__("D_L01_00161F20") __attribute__((sda)); extern f32 gold_bolt_spin_y_degrees_per_second_gp __asm__("D_L01_00161F24") __attribute__((sda)); @@ -512,8 +514,9 @@ void gold_bolt_update(struct Moby *moby) { moby->rot.y, gold_bolt_spin_y_degrees_per_second_gp * 0.017453292f * frame_time_macro); moby->rot.z = fast_add_rotations( moby->rot.z, gold_bolt_spin_z_degrees_per_second_gp * 0.017453292f * frame_time_macro); - moby->rot.w = - fast_add_rotations(moby->rot.w, l01_gold_bolt_bobbing_phase_degrees_per_second_gp * 0.017453292f * frame_time_macro); + moby->rot.w = fast_add_rotations(moby->rot.w, + l01_gold_bolt_bobbing_phase_degrees_per_second_gp * + 0.017453292f * frame_time_macro); FUN_L01_00308550_f(moby); if (!random_integer_below(D_L01_00161F50_gp)) { FUN_L01_003089f0_f(moby); @@ -630,7 +633,8 @@ void update_gold_bolt_visuals(struct Moby *moby) { moby->scale = moby->pclass->scale * *(float *)&D_L01_00161F10_gp; if (moby->state == GOLD_BOLT_WAIT_FOR_PICKUP) { bobbing_sine = fast_sin(moby->rot.w); - moby->pos.z = *(float *)(gold_bolt_visual_vars + 0x18) + *(float *)&l01_gold_bolt_bobbing_height_offset_gp + + moby->pos.z = *(float *)(gold_bolt_visual_vars + 0x18) + + *(float *)&l01_gold_bolt_bobbing_height_offset_gp + *(float *)&l01_gold_bolt_bobbing_amplitude_gp * bobbing_sine; moby->rot.x = fast_add_rotations(moby->rot.x, *(float *)(gold_bolt_visual_vars + 0x68)); moby->rot.y = fast_add_rotations(moby->rot.y, *(float *)(gold_bolt_visual_vars + 0x64)); @@ -713,13 +717,13 @@ void update_gold_bolt_glow_rings(struct Moby *moby) { gold_bolt_glow_ring_tween_end_color_gp, absolute_float(0.5f - pulse_progress)); spawn_timed_hero_relative_particle(glow_particle_position, - packed_color, - truncate_float_to_s32(ring_rotations[i]), - gold_bolt_glow_ring_particle_texture_index_gp, - gold_bolt_glow_ring_particle_use_flags_44_gp, - 2, - 0, - sz[i] * scale); + packed_color, + truncate_float_to_s32(ring_rotations[i]), + gold_bolt_glow_ring_particle_texture_index_gp, + gold_bolt_glow_ring_particle_use_flags_44_gp, + 2, + 0, + sz[i] * scale); fast_vec_add(glow_particle_position, glow_particle_position, step); } } diff --git a/src/overlays/shared/pickups/infobot.c b/src/overlays/shared/pickups/infobot.c index d6c90ee8f0..6d6d6816fd 100644 --- a/src/overlays/shared/pickups/infobot.c +++ b/src/overlays/shared/pickups/infobot.c @@ -18,7 +18,10 @@ #include "rnc/mobys/moby_spawn.h" #include "rnc/overlay/shared/game/unlock_planet.h" #include "rnc/overlay/shared/rendering/effects/particles.h" -unsigned char *spawn_timed_hero_relative_particle(u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); + +unsigned char *spawn_timed_hero_relative_particle( + u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); + #include "rnc/save/memcard_save_data.h" typedef struct Moby Moby; @@ -696,13 +699,14 @@ void update_infobot_particle_effect(char *moby) { col = fast_tween_color(0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - f)); if (D_15F5C4_2d6cd0 != 2) { spawn_timed_hero_relative_particle(d, - col, - truncate_float_to_s32(infobot_particle_state->a[i]) & 0xFF, - 0x35, - 1, - 2, - 0, - infobot_particle_state->d[i]); + col, + truncate_float_to_s32(infobot_particle_state->a[i]) & + 0xFF, + 0x35, + 1, + 2, + 0, + infobot_particle_state->d[i]); } fast_vec_add(d, d, particle_position_step); } diff --git a/src/overlays/shared/pickups/nanotech_ball.c b/src/overlays/shared/pickups/nanotech_ball.c index 193ff994c0..279bafff79 100644 --- a/src/overlays/shared/pickups/nanotech_ball.c +++ b/src/overlays/shared/pickups/nanotech_ball.c @@ -188,11 +188,11 @@ void FUN_00214890_002d8418(Vec4_002d8418 *, float) __asm__("FUN_00214890"); void spawn_moving_hero_relative_alpha_fade_particle( void *, Vec4_002d8418 *, int, int, int, int, float) __asm__("FUN_L00_002730e0"); -s32 FUN_001f96f8_2d8510(s32) __asm__("FUN_001f96f8"); -s32 FUN_001fa6e0_2d8510(s32, s32, f32) __asm__("FUN_001fa6e0"); -u8 *spawn_timed_hero_relative_particle(void *, s32, u8, s32, s32, s32, s32, f32) __asm__("FUN_L00_00272f68"); -void FUN_001f9bf8_002d8850(void *, void *, float) __asm__("FUN_001f9bf8"); -void draw_nanotech_ball(Moby *moby) __asm__("FUN_L00_002d9810"); +s32 FUN_001f96f8_2d8510(s32) __asm__("FUN_001f96f8"); +s32 FUN_001fa6e0_2d8510(s32, s32, f32) __asm__("FUN_001fa6e0"); +u8 *spawn_timed_hero_relative_particle(void *, s32, u8, s32, s32, s32, s32, f32) __asm__("FUN_L00_00272f68"); +void FUN_001f9bf8_002d8850(void *, void *, float) __asm__("FUN_001f9bf8"); +void draw_nanotech_ball(Moby *moby) __asm__("FUN_L00_002d9810"); extern int func_001F9850_2D9EA0(int) __asm__("FUN_001f96f8"); extern void func_L00_001FF4B0_2D9EA0(void *, void *, float) __asm__("FUN_001f9bf8"); extern void func_001F9BD8_2D9EA0(void *, void *, void *) __asm__("FUN_001f9a10"); @@ -1170,27 +1170,27 @@ s32 update_nanotech_ball_collection_effects(M_2d8510 *moby) { << 24; c = al | (c & 0xFFFFFF); effect_position.z = z + nanotech_ball_collection_particle_z_offsets[i]; - effect_record = spawn_timed_hero_relative_particle(&effect_position, - c, - truncate_float_to_s32(effect_data->f60[i]), - nanotech_ball_collection_particle_byte_source_index, - 0, - 2, - 1, - nanotech_ball_collection_particle_scale_factors[i] * - color_progress_or_size_factor); + effect_record = spawn_timed_hero_relative_particle( + &effect_position, + c, + truncate_float_to_s32(effect_data->f60[i]), + nanotech_ball_collection_particle_byte_source_index, + 0, + 2, + 1, + nanotech_ball_collection_particle_scale_factors[i] * color_progress_or_size_factor); if (effect_record) effect_record[2] = *D_L00_001B2080_lui.pF8; - effect_record = - spawn_timed_hero_relative_particle(&effect_position, - al | 0xFFFFFF, - truncate_float_to_s32(effect_data->f60[i]), - nanotech_ball_collection_particle_byte_source_index, - nanotech_ball_collection_second_particle_mode_selector, - 2, - 1, - nanotech_ball_collection_particle_scale_factors[i] * - (color_progress_or_size_factor * 0.7f)); + effect_record = spawn_timed_hero_relative_particle( + &effect_position, + al | 0xFFFFFF, + truncate_float_to_s32(effect_data->f60[i]), + nanotech_ball_collection_particle_byte_source_index, + nanotech_ball_collection_second_particle_mode_selector, + 2, + 1, + nanotech_ball_collection_particle_scale_factors[i] * + (color_progress_or_size_factor * 0.7f)); if (effect_record) effect_record[2] = *D_L00_001B2080_lui.pF8; fast_vec_add(&effect_position, &effect_position, &effect_position_step); diff --git a/src/overlays/shared/pickups/pilots_helmet.c b/src/overlays/shared/pickups/pilots_helmet.c index 090e8ae21c..55e788b1a2 100644 --- a/src/overlays/shared/pickups/pilots_helmet.c +++ b/src/overlays/shared/pickups/pilots_helmet.c @@ -17,7 +17,10 @@ #include "rnc/overlay/shared/game/unlock_planet.h" #include "rnc/overlay/shared/pickups/infobot.h" #include "rnc/overlay/shared/rendering/effects/particles.h" -unsigned char *spawn_timed_hero_relative_particle(u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); + +unsigned char *spawn_timed_hero_relative_particle( + u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); + #include "rnc/save/memcard_save_data.h" typedef struct { @@ -200,13 +203,13 @@ void emit_moby_color_cycling_particles(unsigned char *moby) { color_cycle_progress = color_cycle_progress / (float)scale_game_frames(0xff); c = fast_tween_color(0x4040FFFF, 0x1040FFFF, absolute_float(0.5f - color_cycle_progress)); spawn_timed_hero_relative_particle(sprite_position_and_step, - c, - truncate_float_to_s32(*a++), - 0x35, - 1, - 2, - 0, - moby_data->c[j]); + c, + truncate_float_to_s32(*a++), + 0x35, + 1, + 2, + 0, + moby_data->c[j]); j++; fast_vec_add( sprite_position_and_step, sprite_position_and_step, &sprite_position_and_step[1]); diff --git a/src/overlays/shared/pickups/weapon_ammo.c b/src/overlays/shared/pickups/weapon_ammo.c index da72ed83ee..3449e50849 100644 --- a/src/overlays/shared/pickups/weapon_ammo.c +++ b/src/overlays/shared/pickups/weapon_ammo.c @@ -146,7 +146,8 @@ void devestator_ammo_update(struct Moby *pickup_moby) { pickup_vars = (AmmoPickup *)pickup_moby->pvars; FUN_001f9740_2c53c0(&pickup_vars->timer); state = pickup_moby->state; - if (state == AMMO_PICKUP_WAIT_FOR_COLLECTION || state == AMMO_PICKUP_RESTORE_SCALE || state == AMMO_PICKUP_PULSE_ALPHA) { + if (state == AMMO_PICKUP_WAIT_FOR_COLLECTION || state == AMMO_PICKUP_RESTORE_SCALE || + state == AMMO_PICKUP_PULSE_ALPHA) { magnitude = FUN_001f9af0_2c53c0(&pickup_vars->velocity); if (magnitude != 0.0f) { qcopy(&position, &pickup_moby->pos); diff --git a/src/overlays/shared/props/bolt_crank.c b/src/overlays/shared/props/bolt_crank.c index e77a91001b..f3aeea2ff5 100644 --- a/src/overlays/shared/props/bolt_crank.c +++ b/src/overlays/shared/props/bolt_crank.c @@ -166,11 +166,8 @@ void bolt_crank_update(struct Moby *moby) { goto done; } l01_hero_set_state(HERO_STATE_CRANK, 1); - jet_mount(camera_pos, - camera_pos + 0x10, - 3, - scale_game_frames(0xB4), - 0); + jet_mount( + camera_pos, camera_pos + 0x10, 3, scale_game_frames(0xB4), 0); set_camera_rotation(&l01_cuboids[crank->camera_point].rot); set_camera_position(&l01_cuboids[crank->camera_point].pos); set_camera_5_track_acceleration_yz(crank->camera_params[0], diff --git a/src/overlays/shared/props/breakable_lamp.c b/src/overlays/shared/props/breakable_lamp.c index 98c9d3348c..c05d4d1aa6 100644 --- a/src/overlays/shared/props/breakable_lamp.c +++ b/src/overlays/shared/props/breakable_lamp.c @@ -76,7 +76,11 @@ void breakable_lamp_update(struct Moby *moby) __asm__("FUN_L05_0031c8e0"); /* Moby class 1511 */ void breakable_lamp_update(struct Moby *moby) { - enum { BREAKABLE_LAMP_STATE_UNINITIALIZED = 0 , BREAKABLE_LAMP_STATE_INITIALIZED = 1 } ;struct MineVars_c8e0 *glow_and_spark_state = (struct MineVars_c8e0 *)moby->pvars; + enum { + BREAKABLE_LAMP_STATE_UNINITIALIZED = 0, + BREAKABLE_LAMP_STATE_INITIALIZED = 1 + }; + struct MineVars_c8e0 *glow_and_spark_state = (struct MineVars_c8e0 *)moby->pvars; Vec4 tip; Vec4 debris_velocity; Vec4 effect_motion; diff --git a/src/overlays/shared/props/electric_water.c b/src/overlays/shared/props/electric_water.c index 0612397593..ef4eceb4cf 100644 --- a/src/overlays/shared/props/electric_water.c +++ b/src/overlays/shared/props/electric_water.c @@ -440,8 +440,9 @@ void electric_water_update(struct Moby *moby) { electric_water_controller_vars->voice0 = trooper_play_sound(0, 5, electric_water_controller_vars->owner, 0x28F); } - if (moby->state == ELECTRIC_WATER_ON && voice_is_playing(electric_water_controller_vars->owner, - electric_water_controller_vars->voice1) == 0) { + if (moby->state == ELECTRIC_WATER_ON && + voice_is_playing(electric_water_controller_vars->owner, + electric_water_controller_vars->voice1) == 0) { electric_water_controller_vars->voice1 = trooper_play_sound(1, 5, electric_water_controller_vars->owner, 0x28F); } @@ -1031,15 +1032,21 @@ extern float frame_scale __asm__("D_0015ED60"); extern char D_L15_001D3750_8710[] __asm__("D_L15_001D3750"); extern char D_L15_001D3BB0_8710[] __asm__("D_L15_001D3BB0"); extern int D_L15_00161CC8_8710 __asm__("D_L15_00161CC8"); -extern short l15_electric_water_bolt_draw_accumulator_decrement_rate __asm__("D_L15_00161C58") __attribute__((sda)); -extern short l15_electric_water_bolt_draw_wrapped_accumulator __asm__("D_L15_00161C54") __attribute__((sda)); -extern short l15_electric_water_first_bolt_path_first_pass_alpha __asm__("D_L15_00161C3C") __attribute__((sda)); -extern short l15_electric_water_first_bolt_path_second_pass_alpha __asm__("D_L15_00161C44") __attribute__((sda)); +extern short l15_electric_water_bolt_draw_accumulator_decrement_rate __asm__("D_L15_00161C58") + __attribute__((sda)); +extern short l15_electric_water_bolt_draw_wrapped_accumulator __asm__("D_L15_00161C54") + __attribute__((sda)); +extern short l15_electric_water_first_bolt_path_first_pass_alpha __asm__("D_L15_00161C3C") + __attribute__((sda)); +extern short l15_electric_water_first_bolt_path_second_pass_alpha __asm__("D_L15_00161C44") + __attribute__((sda)); extern short D_L15_00161C64_gp __asm__("D_L15_00161C64") __attribute__((sda)); extern short D_L15_00161C68_gp __asm__("D_L15_00161C68") __attribute__((sda)); extern short D_L15_00161C9C_gp __asm__("D_L15_00161C9C") __attribute__((sda)); -extern short l15_electric_water_second_bolt_path_first_pass_alpha __asm__("D_L15_00161C6C") __attribute__((sda)); -extern short l15_electric_water_second_bolt_path_second_pass_alpha __asm__("D_L15_00161C70") __attribute__((sda)); +extern short l15_electric_water_second_bolt_path_first_pass_alpha __asm__("D_L15_00161C6C") + __attribute__((sda)); +extern short l15_electric_water_second_bolt_path_second_pass_alpha __asm__("D_L15_00161C70") + __attribute__((sda)); extern short D_L15_00161C74_gp __asm__("D_L15_00161C74") __attribute__((sda)); extern short D_L15_00161C78_gp __asm__("D_L15_00161C78") __attribute__((sda)); extern short D_L15_00161CA0_gp __asm__("D_L15_00161CA0") __attribute__((sda)); @@ -1047,7 +1054,9 @@ extern void draw_beam_and_arc_two_pass_quads(char *, int, int, int, float, floa extern void FUN_L15_002d8e48_8710(char *) __asm__("FUN_L15_002d8e48"); #define F(x) (*(float *)&(x)) void draw_electric_water_bolt_effect(char *moby) { - float decremented_accumulator = F(l15_electric_water_bolt_draw_wrapped_accumulator) - F(l15_electric_water_bolt_draw_accumulator_decrement_rate) * frame_scale; + float decremented_accumulator = + F(l15_electric_water_bolt_draw_wrapped_accumulator) - + F(l15_electric_water_bolt_draw_accumulator_decrement_rate) * frame_scale; F(l15_electric_water_bolt_draw_wrapped_accumulator) = decremented_accumulator; if (decremented_accumulator <= -8.0f) { F(l15_electric_water_bolt_draw_wrapped_accumulator) = decremented_accumulator + 8.0f; diff --git a/src/overlays/shared/props/energy_sphere_holder.c b/src/overlays/shared/props/energy_sphere_holder.c index a59ea1ed6c..0c74600154 100644 --- a/src/overlays/shared/props/energy_sphere_holder.c +++ b/src/overlays/shared/props/energy_sphere_holder.c @@ -12,7 +12,9 @@ #include "rnc/overlay/shared/props/energy_sphere_holder_data/update_energy_sphere_holder_beam_effects.h" #include "rnc/overlay/shared/props.h" #include "rnc/overlay/shared/rendering/effects/particles.h" -unsigned char *spawn_timed_hero_relative_particle(u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); + +unsigned char *spawn_timed_hero_relative_particle( + u128 *, int, unsigned char, int, int, int, int, float) __asm__("FUN_L00_00272f68"); typedef struct { float ph[4]; @@ -159,13 +161,13 @@ void update_energy_sphere_holder_beam_effects(char *moby) { energy_sphere_holder_beam_color_end_gp, absolute_float(0.5f - timer_progress)); spawn_timed_hero_relative_particle(beam_sprite_position, - beam_sprite_color, - truncate_float_to_s32(beam->ph[i]), - energy_sphere_holder_beam_texture_index_gp, - energy_sphere_holder_beam_particle_variant_flag_gp, - 2, - 0, - beam->sz[i]); + beam_sprite_color, + truncate_float_to_s32(beam->ph[i]), + energy_sphere_holder_beam_texture_index_gp, + energy_sphere_holder_beam_particle_variant_flag_gp, + 2, + 0, + beam->sz[i]); fast_vec_add(beam_sprite_position, beam_sprite_position, step); } if ((level_frame_count & 3) == 3 && ((unsigned char *)moby)[0x31] != 0) { diff --git a/src/overlays/shared/props/escalator.c b/src/overlays/shared/props/escalator.c index 199214ac30..a708367d4c 100644 --- a/src/overlays/shared/props/escalator.c +++ b/src/overlays/shared/props/escalator.c @@ -27,7 +27,13 @@ void escalator_update(char *moby) __asm__("FUN_L02_002dc6b0"); /* Moby classes 296, 652, 653 */ void escalator_update(char *moby) { - enum { ESCALATOR_STATE_INITIALIZE = 0 , ESCALATOR_STATE_TIMED_NEGATIVE_YAW_MOTION = 1 , ESCALATOR_STATE_TIMED_POSITIVE_YAW_MOTION = 2 , ESCALATOR_STATE_CONSTANT_SPEED_MOTION = 3 } ;EscalatorVars *escalator_motion_state = (EscalatorVars *)MOBY(moby)->pvars; + enum { + ESCALATOR_STATE_INITIALIZE = 0, + ESCALATOR_STATE_TIMED_NEGATIVE_YAW_MOTION = 1, + ESCALATOR_STATE_TIMED_POSITIVE_YAW_MOTION = 2, + ESCALATOR_STATE_CONSTANT_SPEED_MOTION = 3 + }; + EscalatorVars *escalator_motion_state = (EscalatorVars *)MOBY(moby)->pvars; float limit; float y; int state; diff --git a/src/overlays/shared/props/floor_button.c b/src/overlays/shared/props/floor_button.c index 589885caea..9dc333f2dd 100644 --- a/src/overlays/shared/props/floor_button.c +++ b/src/overlays/shared/props/floor_button.c @@ -50,7 +50,8 @@ void floor_button_update(struct Moby *moby) { id = (s16)moby->save_id; if (l05_mission_gated_moby_save_flags.collected[id] != 0 || (D_0014C190_257218[current_level_index][id >> 5] >> (moby->save_id & 31) & 1) != 0 || - (floor_button_private_state[2] != 0 && D_0014C050[moby->mission + current_level_index * 16] == 0xFF)) { + (floor_button_private_state[2] != 0 && + D_0014C050[moby->mission + current_level_index * 16] == 0xFF)) { moby->command = 2; moby->glow_color = 0x80208020; moby->state = FLOOR_BUTTON_STATE_DISABLED; @@ -60,7 +61,8 @@ void floor_button_update(struct Moby *moby) { if (*(s32 *)l05_paths[list] > 0) { do { path_key_cursor = ((char *)l05_paths[list]) + i * 16; - if (*(f32 *)(path_key_cursor + 0x1C) == ((f32 *)floor_button_private_state)[1]) + if (*(f32 *)(path_key_cursor + 0x1C) == + ((f32 *)floor_button_private_state)[1]) *(s32 *)(path_key_cursor + 0x1C) = 0; list = floor_button_private_state[0]; i++; @@ -72,7 +74,8 @@ void floor_button_update(struct Moby *moby) { } break; case FLOOR_BUTTON_STATE_WAIT_FOR_PRESS: - angle = fast_add_rotations(*(f32 *)(floor_button_private_state + 3), frame_time * 6.2831855f); + angle = + fast_add_rotations(*(f32 *)(floor_button_private_state + 3), frame_time * 6.2831855f); *(f32 *)(floor_button_private_state + 3) = angle; color = truncate_float_to_s32((fast_sin(angle) * 4.0f - 3.0f) * 128.0f); if (color > 0x80) @@ -99,7 +102,8 @@ void floor_button_update(struct Moby *moby) { if (*(s32 *)l05_paths[list] > 0) { do { path_key_cursor = ((char *)l05_paths[list]) + i * 16; - if (*(f32 *)(path_key_cursor + 0x1C) == ((f32 *)floor_button_private_state)[1]) + if (*(f32 *)(path_key_cursor + 0x1C) == + ((f32 *)floor_button_private_state)[1]) *(s32 *)(path_key_cursor + 0x1C) = 0; list = floor_button_private_state[0]; i++; diff --git a/src/overlays/shared/props/linked_spark_emitter.c b/src/overlays/shared/props/linked_spark_emitter.c index f102faf406..35ddcf6526 100644 --- a/src/overlays/shared/props/linked_spark_emitter.c +++ b/src/overlays/shared/props/linked_spark_emitter.c @@ -105,9 +105,10 @@ void linked_spark_emitter_update(unsigned char *moby) { visited52[(unsigned char)MOBY(moby)->mission + (D_0015ED84 << 4)] == 0xFF) { mark_moby_killed_and_release_owned_voice(moby); } else { - Voice *emitter_voice_slot = (Voice *)((unsigned char *)&voice_pool + MOBY(moby)->command * 0x70); - float lo, hi, z, one; - int i; + Voice *emitter_voice_slot = + (Voice *)((unsigned char *)&voice_pool + MOBY(moby)->command * 0x70); + float lo, hi, z, one; + int i; if (emitter_voice_slot->owner != (char *)moby || emitter_voice_slot->active == 0) { MOBY(moby)->command = allocate_voice_for_target_entry(0, 4, moby); } diff --git a/src/overlays/shared/props/moby_state_trigger.c b/src/overlays/shared/props/moby_state_trigger.c index afbe0fc224..3ff933c9a3 100644 --- a/src/overlays/shared/props/moby_state_trigger.c +++ b/src/overlays/shared/props/moby_state_trigger.c @@ -111,7 +111,10 @@ void moby_spatial_trigger_update(struct Moby *trigger_moby) __asm__("FUN_L05_002 /* Moby class 258 */ void moby_spatial_trigger_update(struct Moby *trigger_moby) { - enum { SPATIAL_TRIGGER_STATE_UNINITIALIZED = 0 } ;TriggerVars *trigger_vars = (TriggerVars *)trigger_moby->pvars; + enum { + SPATIAL_TRIGGER_STATE_UNINITIALIZED = 0 + }; + TriggerVars *trigger_vars = (TriggerVars *)trigger_moby->pvars; Vec4 target; s32 inside; s32 i; diff --git a/src/overlays/shared/props/teleporter.c b/src/overlays/shared/props/teleporter.c index 2e9d807069..750f58e710 100644 --- a/src/overlays/shared/props/teleporter.c +++ b/src/overlays/shared/props/teleporter.c @@ -261,7 +261,14 @@ void teleporter_update(struct Moby *moby) { TELEPORTER_ENTER_WAIT_FOR_USE = 6, TELEPORTER_EFFECT_CYCLE_PREPARE = 7, TELEPORTER_EFFECT_CYCLE_RETURN_TO_IDLE = 8 - } ; enum { TELEPORTER_WAIT_FOR_ACTIVATION = 5} ; enum { HERO_TARGET_POSE_STATUS_INACTIVE = 0 , HERO_TARGET_POSE_STATUS_TRANSFER_READY = 2}; + }; + enum { + TELEPORTER_WAIT_FOR_ACTIVATION = 5 + }; + enum { + HERO_TARGET_POSE_STATUS_INACTIVE = 0, + HERO_TARGET_POSE_STATUS_TRANSFER_READY = 2 + }; TeleporterVars *teleporter_vars = (TeleporterVars *)moby->pvars; int active = 0; diff --git a/src/overlays/shared/props/trespasser_pad.c b/src/overlays/shared/props/trespasser_pad.c index 0d5bb79bf3..8511fbb02d 100644 --- a/src/overlays/shared/props/trespasser_pad.c +++ b/src/overlays/shared/props/trespasser_pad.c @@ -100,21 +100,25 @@ extern void func_L02_002DA728_2D9F08(Moby *) __asm__("FUN_L02_002d92f0"); extern void func_L02_002D9D48_2D9F08(void *, void *, Moby *) __asm__("FUN_L02_002d8910"); extern float advance_accelerated_scalar(float *, float *, float, float, float, float) __asm__("FUN_00213f38"); -extern void func_L02_002DA820_2D9F08(void) __asm__("FUN_L02_002d93e8"); -extern void func_L00_0025E590_2D9F08(Moby *, Data *) __asm__("FUN_L00_0025d538"); -extern float D_L02_001D33B0[4][4]; -extern Lvl D_L02_001BBB40_2D9F08 __asm__("D_L02_001BB830"); -extern int current_level_index_macro __asm__("D_0015ED84") MACRO_ADDR; -extern Vec_2D9F08 D_L02_00167440_2D9F08[] __asm__("D_L02_001673C0"); -extern float frame_time_sq_macro __asm__("D_0015ED70") MACRO_ADDR; -extern float frame_time_macro __asm__("D_0015ED6C") MACRO_ADDR; -extern int D_L02_0017EB08_lui __asm__("D_L02_0017EB08") NOT_SDA; -extern Idle D_L02_00179A10; -extern int D_L02_001BADE0_2D9F08[] __asm__("D_L02_001BAAD0"); -extern int l02_tresspasser_puzzle_texture_index_offset __asm__("D_L02_00161B1C") __attribute__((sda)); -extern int l02_tresspasser_pad_no_ground_contact_glow_color __asm__("D_L02_00161AA8") __attribute__((sda)); -extern int l02_tresspasser_pad_without_tool_glow_color __asm__("D_L02_00161AA4") __attribute__((sda)); -extern int l02_tresspasser_pad_tool_equipped_glow_color __asm__("D_L02_00161AA0") __attribute__((sda)); +extern void func_L02_002DA820_2D9F08(void) __asm__("FUN_L02_002d93e8"); +extern void func_L00_0025E590_2D9F08(Moby *, Data *) __asm__("FUN_L00_0025d538"); +extern float D_L02_001D33B0[4][4]; +extern Lvl D_L02_001BBB40_2D9F08 __asm__("D_L02_001BB830"); +extern int current_level_index_macro __asm__("D_0015ED84") MACRO_ADDR; +extern Vec_2D9F08 D_L02_00167440_2D9F08[] __asm__("D_L02_001673C0"); +extern float frame_time_sq_macro __asm__("D_0015ED70") MACRO_ADDR; +extern float frame_time_macro __asm__("D_0015ED6C") MACRO_ADDR; +extern int D_L02_0017EB08_lui __asm__("D_L02_0017EB08") NOT_SDA; +extern Idle D_L02_00179A10; +extern int D_L02_001BADE0_2D9F08[] __asm__("D_L02_001BAAD0"); +extern int l02_tresspasser_puzzle_texture_index_offset __asm__("D_L02_00161B1C") + __attribute__((sda)); +extern int l02_tresspasser_pad_no_ground_contact_glow_color __asm__("D_L02_00161AA8") + __attribute__((sda)); +extern int l02_tresspasser_pad_without_tool_glow_color __asm__("D_L02_00161AA4") + __attribute__((sda)); +extern int l02_tresspasser_pad_tool_equipped_glow_color __asm__("D_L02_00161AA0") + __attribute__((sda)); extern char D_0013E633_2D9F08[] __asm__("D_0013E533"); extern void func_L00_002607A8_d92f0(void *a, float x) __asm__("FUN_L00_0025f730"); @@ -490,7 +494,13 @@ void align_hero_to_tresspasser_pad(struct Moby *moby) { void draw_tresspasser_puzzle(char *moby) { /* Fakematch: the texture sits at retail's stack offset inside this frame. */ - enum { TRESSPASSER_MARKER_ABSENT = 0 , TRESSPASSER_SELECTED_RING_FIRST = 1 , TRESSPASSER_SELECTED_RING_SECOND = 2 , TRESSPASSER_MARKER_REACHED = 2 } ;struct { + enum { + TRESSPASSER_MARKER_ABSENT = 0, + TRESSPASSER_SELECTED_RING_FIRST = 1, + TRESSPASSER_SELECTED_RING_SECOND = 2, + TRESSPASSER_MARKER_REACHED = 2 + }; + struct { char pad0[0x78]; u64 texture; char pad80[0x10]; diff --git a/src/overlays/shared/rendering/debug/update_debug_menu.c b/src/overlays/shared/rendering/debug/update_debug_menu.c index e524b77bf7..77eb72ac3c 100644 --- a/src/overlays/shared/rendering/debug/update_debug_menu.c +++ b/src/overlays/shared/rendering/debug/update_debug_menu.c @@ -385,7 +385,8 @@ void update_debug_camera(void) { copy_matrix3x4(l00_camera.unk350, r); } } - if (g_debug_menu.control_mode == DEBUG_CONTROL_MODE_CAPTURE_HERO_CAMERA_OFFSET && l00_camera.unk180 != 0) { + if (g_debug_menu.control_mode == DEBUG_CONTROL_MODE_CAPTURE_HERO_CAMERA_OFFSET && + l00_camera.unk180 != 0) { target = (DebugCameraTarget *)l00_camera.unk180; qcopy(target->position, l00_camera.pos.f); qcopy(target->basis, l00_camera.unk350); diff --git a/src/overlays/shared/rendering/effects/particles.c b/src/overlays/shared/rendering/effects/particles.c index 3ab0ee177e..11a2ea06b6 100644 --- a/src/overlays/shared/rendering/effects/particles.c +++ b/src/overlays/shared/rendering/effects/particles.c @@ -915,27 +915,27 @@ void update_color_tween_emitter_particle(struct EffectParticle *particle) { } extern unsigned char *D_L00_001B2080_lui[] __asm__("D_L00_001B2080") NOT_SDA; +unsigned char *spawn_timed_hero_relative_particle(u128 *position, + int packed_color, + unsigned char initial_rotation, + int particle_texture_index, + int flag, + int lifetime_frames, + int mode, + + float size_scale) __asm__("FUN_L00_00272f68"); + +unsigned char *spawn_timed_hero_relative_particle( + u128 *a, int c, unsigned char b, int idx, int flag, int n, int mode, float f); unsigned char *spawn_timed_hero_relative_particle(u128 *position, - int packed_color, - unsigned char initial_rotation, - int particle_texture_index, - int flag, - int lifetime_frames, - int mode, - - float size_scale) __asm__("FUN_L00_00272f68"); - -unsigned char * -spawn_timed_hero_relative_particle(u128 *a, int c, unsigned char b, int idx, int flag, int n, int mode, float f); -unsigned char *spawn_timed_hero_relative_particle(u128 *position, - int packed_color, - unsigned char initial_rotation, - int particle_texture_index, - int flag, - int lifetime_frames, - int mode, - - float size_scale) { + int packed_color, + unsigned char initial_rotation, + int particle_texture_index, + int flag, + int lifetime_frames, + int mode, + + float size_scale) { enum { PARTICLE_MODE_HERO_RELATIVE = 1 }; diff --git a/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c b/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c index fc458fe953..37e7edea3c 100644 --- a/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c +++ b/src/overlays/shared/rendering/effects/update_three_phase_effect_particle.c @@ -201,14 +201,14 @@ int FUN_001160d8_00269958(void) __asm__("FUN_00 extern unsigned char *D_L00_001B2090 NOT_SDA; void spawn_effect(u128 *a, u128 *b, int c, int d, int n, int s1, int s2, int flag) __asm__("FUN_L00_00269958"); void spawn_effect(u128 *spawn_position, - u128 *initial_velocity, - int initial_color, - int color_endpoint, - int lifetime, - int scalar_base, - int scalar_delta, - - int flag) { + u128 *initial_velocity, + int initial_color, + int color_endpoint, + int lifetime, + int scalar_base, + int scalar_delta, + + int flag) { unsigned char *particle = FUN_L00_002678b8_00269958(4); if (particle) { int *particle_data; @@ -502,13 +502,13 @@ extern unsigned char *D_L00_001B20A0_0026a4c8 __asm__("D_L00_001B20A0") __attribute__((section(".data"))); unsigned char *FUN_L00_002678b8_0026a4c8(int) __asm__("FUN_L00_002678b8"); void spawn_particle_alt_9768(u128 *a, u128 *b, int c, int d, int n, float f) __asm__("FUN_L00_0026a4c8"); -void spawn_particle_alt_9768(u128 *spawn_position, - u128 *initial_velocity, - int initial_color, - int final_color, - int lifetime, +void spawn_particle_alt_9768(u128 *spawn_position, + u128 *initial_velocity, + int initial_color, + int final_color, + int lifetime, - float particle_scalar_change) { + float particle_scalar_change) { if (lifetime) { unsigned char *particle = FUN_L00_002678b8_0026a4c8(8); if (particle) { @@ -2965,7 +2965,12 @@ spawn_random_planar_drift_particle(void *, int, float, float) __asm__("FUN_L00_0 void update_ballistic_effect_particle_with_contact_spawns(struct EffectParticle *) __asm__("FUN_L00_0026f660"); void update_ballistic_effect_particle_with_contact_spawns(struct EffectParticle *particle) { - enum { BALLISTIC_PARTICLE_MODE_NO_CONTACT_TEST = 0 , BALLISTIC_PARTICLE_MODE_LINE_CONTACT_HEIGHT_SNAPPED_SPAWN = 1 , BALLISTIC_PARTICLE_MODE_WATER_SURFACE_CONTACT_SPAWN = 3 } ;char *particle_data = particle->data; + enum { + BALLISTIC_PARTICLE_MODE_NO_CONTACT_TEST = 0, + BALLISTIC_PARTICLE_MODE_LINE_CONTACT_HEIGHT_SNAPPED_SPAWN = 1, + BALLISTIC_PARTICLE_MODE_WATER_SURFACE_CONTACT_SPAWN = 3 + }; + char *particle_data = particle->data; int mode = *(int *)(particle_data + 0x10); V next_position; char *particle_position; diff --git a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c index c37658a0b4..ce43922d31 100644 --- a/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c +++ b/src/overlays/shared/ui/hud/draw_hud_item_selector_panel.c @@ -86,7 +86,8 @@ int hud_draw_gauge_frame(HudElem_237840 *gauge_element) { } } hud_screen_position(gauge_element, &screen_position[0], &screen_position[1]); - apply_hud_slide_offset(gauge_element, &screen_position[0], &screen_position[1], gauge_element->unk6C, 0); + apply_hud_slide_offset( + gauge_element, &screen_position[0], &screen_position[1], gauge_element->unk6C, 0); w = D_L00_0015F760 * 0xD0; h = D_L00_0015F764 * 0xA0; bh = D_L00_0015F760 * 0x260; @@ -120,8 +121,12 @@ int hud_draw_gauge_frame(HudElem_237840 *gauge_element) { append_screen_rect_packet(left, top, right, top + 32, 0x80000000, 1); } while (i < gauge_element->unk74); w = get_icon_frame(*(int *)gauge_element, 0); - draw_rotated_hud_sprite( - w, screen_position[0] + gauge_element->unk48, screen_position[1] + gauge_element->unk4A, D_L00_0015F760, D_L00_0015F764, 0x80); + draw_rotated_hud_sprite(w, + screen_position[0] + gauge_element->unk48, + screen_position[1] + gauge_element->unk4A, + D_L00_0015F760, + D_L00_0015F764, + 0x80); return gauge_element->w; } @@ -204,7 +209,7 @@ typedef struct { extern int D_L00_0017E504 NOT_SDA; extern int D_L00_0015FA90; -extern int l00_hud_selector_fade_counter_limit_gp __asm__("D_L00_0015F780") __attribute__((sda)); +extern int l00_hud_selector_fade_counter_limit_gp __asm__("D_L00_0015F780") __attribute__((sda)); extern int saved_hud_selector_slot_index_gp __asm__("D_L00_0015FA9C") __attribute__((sda)); extern Ent **D_L00_0015FAC0_c __asm__("D_L00_0015FAC0"); extern int D_L00_0017DC38 NOT_SDA; @@ -435,12 +440,14 @@ int draw_hud_item_selector_panel(HudElem *rec) { unsigned char *counters = rec->cnt; char formatted[80]; - open = convert_integer_to_float(counters[0]) / convert_integer_to_float(l00_hud_selector_fade_counter_limit_gp); + open = convert_integer_to_float(counters[0]) / + convert_integer_to_float(l00_hud_selector_fade_counter_limit_gp); if (1.0f < open) open = 1.0f; else if (open < 0.0f) open = 0.0f; - fade = convert_integer_to_float(counters[1]) / convert_integer_to_float(l00_hud_selector_fade_counter_limit_gp); + fade = convert_integer_to_float(counters[1]) / + convert_integer_to_float(l00_hud_selector_fade_counter_limit_gp); if (1.0f < fade) fade = 1.0f; else if (fade < 0.0f) diff --git a/src/overlays/shared/ui/hud/draw_hud_segment_meter.c b/src/overlays/shared/ui/hud/draw_hud_segment_meter.c index 99437edfc5..634b59762a 100644 --- a/src/overlays/shared/ui/hud/draw_hud_segment_meter.c +++ b/src/overlays/shared/ui/hud/draw_hud_segment_meter.c @@ -11,9 +11,11 @@ #include "rnc/ui/hud.h" extern s32 frame_size __asm__("D_0013E504") NOT_SDA; -extern s32 l06_hud_segment_meter_center_x __asm__("D_L06_0015F8E8") __attribute__((sda)); -extern f32 l06_hud_segment_meter_last_segment_fill_scale __asm__("D_L06_0015F8F0") __attribute__((sda)); -extern f32 l06_hud_segment_meter_first_segment_fill_scale __asm__("D_L06_0015F8F4") __attribute__((sda)); +extern s32 l06_hud_segment_meter_center_x __asm__("D_L06_0015F8E8") __attribute__((sda)); +extern f32 l06_hud_segment_meter_last_segment_fill_scale __asm__("D_L06_0015F8F0") + __attribute__((sda)); +extern f32 l06_hud_segment_meter_first_segment_fill_scale __asm__("D_L06_0015F8F4") + __attribute__((sda)); extern s32 fast_tween_color(s32, s32, f32) __asm__("FUN_001fa6e0"); s32 draw_hud_segment_meter(u8 *p) __asm__("FUN_L06_00249738"); @@ -63,7 +65,8 @@ s32 draw_hud_segment_meter(u8 *meter_state) { x = 0; color = 0x800000ff; if (*(s32 *)(meter_state + 0x74) != 0) { - fill = (f32) * (s32 *)(meter_state + 0x74) / convert_integer_to_float(*(s32 *)(meter_state + 8)); + fill = (f32) * (s32 *)(meter_state + 0x74) / + convert_integer_to_float(*(s32 *)(meter_state + 8)); step = 1.0f / convert_integer_to_float(segments); limit = remaining * step; if (limit < fill) { diff --git a/src/overlays/shared/ui/menus/initialize_pause_menu.c b/src/overlays/shared/ui/menus/initialize_pause_menu.c index 217e70aa49..b8818249e0 100644 --- a/src/overlays/shared/ui/menus/initialize_pause_menu.c +++ b/src/overlays/shared/ui/menus/initialize_pause_menu.c @@ -322,11 +322,14 @@ void initialize_pause_menu(void) { D_L00_0015F578 = 0x2000; vu1_init_chain(); - if (D_L00_001B9CF0.state == 11 || D_L00_001B9CF0.state == PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION) { + if (D_L00_001B9CF0.state == 11 || + D_L00_001B9CF0.state == PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION) { initialize_render_archive_transfer(); } apply_group_entry_adjustment(0); - if (D_L00_001B9CF0.state == 11 || D_L00_001B9CF0.state == PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION || D_L00_001B9CF0.state == 0x12) { + if (D_L00_001B9CF0.state == 11 || + D_L00_001B9CF0.state == PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION || + D_L00_001B9CF0.state == 0x12) { decompress_and_relocate_selected_groups(1); } else { decompress_and_relocate_selected_groups(0); @@ -334,7 +337,8 @@ void initialize_pause_menu(void) { transfer_draw_buffer_chunks(D_L00_001B9CF0.unk10, draw_buffer_address, frame_size << 11); texture_start = gs_texture_allocation_start; D_L00_001B9CF0.saved_texture_start = texture_start; - if (D_L00_001B9CF0.state == 11 || D_L00_001B9CF0.state == PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION) { + if (D_L00_001B9CF0.state == 11 || + D_L00_001B9CF0.state == PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION) { D_L00_001841F0.unk240 = texture_start; texture_region_end = texture_start + 0x40000; D_L00_001841F0.unk244 = texture_region_end; @@ -594,8 +598,10 @@ void update_pause_menu(void) { return; } scene_state = D_L00_001B9CF0.state; - if (scene_state == 0 || scene_state == 0xA || scene_state == PAUSE_MENU_STATE_LEVEL_TRANSITION_ENTRY || scene_state == 0x11 || - scene_state == PAUSE_MENU_STATE_EXIT_GUARDED_ENTRY || scene_state == 0x2D || scene_state == PAUSE_MENU_STATE_PRESERVE_STATE_ENTRY) { + if (scene_state == 0 || scene_state == 0xA || + scene_state == PAUSE_MENU_STATE_LEVEL_TRANSITION_ENTRY || scene_state == 0x11 || + scene_state == PAUSE_MENU_STATE_EXIT_GUARDED_ENTRY || scene_state == 0x2D || + scene_state == PAUSE_MENU_STATE_PRESERVE_STATE_ENTRY) { initialize_pause_menu(); } if ((mode_freeze_flags & 1) && !(level_timer < 8)) { diff --git a/src/overlays/shared/vehicles/fighter_jet_missile.c b/src/overlays/shared/vehicles/fighter_jet_missile.c index 7596ab7291..68769c0b34 100644 --- a/src/overlays/shared/vehicles/fighter_jet_missile.c +++ b/src/overlays/shared/vehicles/fighter_jet_missile.c @@ -164,7 +164,10 @@ void fighter_jet_missile_update(struct Moby *moby) __asm__("FUN_L11_003089d0"); /* Moby class 1009 */ void fighter_jet_missile_update(struct Moby *moby) { - enum { MOBY_STATE_PENDING_REMOVAL = 0xFE } ;MissileVars *missile_vars = (MissileVars *)moby->pvars; + enum { + MOBY_STATE_PENDING_REMOVAL = 0xFE + }; + MissileVars *missile_vars = (MissileVars *)moby->pvars; float previous_missile_position[4]; float look[4]; MissileHit hit; diff --git a/src/overlays/shared/vehicles/fighter_jet_rocket.c b/src/overlays/shared/vehicles/fighter_jet_rocket.c index de41bb590e..ac4607fa45 100644 --- a/src/overlays/shared/vehicles/fighter_jet_rocket.c +++ b/src/overlays/shared/vehicles/fighter_jet_rocket.c @@ -111,9 +111,9 @@ typedef struct Tex { unsigned char *p5C; } Tex; -extern float D_0015ED6C; -extern int collision_line() __asm__("FUN_001efa68"); -extern int FUN_L00_0024f7c8(); +extern float D_0015ED6C; +extern int collision_line() __asm__("FUN_001efa68"); +extern int FUN_L00_0024f7c8(); unsigned char *spawn_particle(void *pos, float *vec, int s, diff --git a/src/overlays/shared/vehicles/giant_clank_charged_blast.c b/src/overlays/shared/vehicles/giant_clank_charged_blast.c index 88eb93e5f2..a273e47e80 100644 --- a/src/overlays/shared/vehicles/giant_clank_charged_blast.c +++ b/src/overlays/shared/vehicles/giant_clank_charged_blast.c @@ -439,8 +439,9 @@ void giant_clank_charged_blast_update(Moby29FF90 *moby) { int i; for (i = 0; i < 12; i++) { - Part29FF90 *blast_center_particle = (Part29FF90 *)spawn_mode_controlled_rotating_alpha_fade_particle( - moby->pos, D_L15_0015F580, 0x7F, moby); + Part29FF90 *blast_center_particle = + (Part29FF90 *)spawn_mode_controlled_rotating_alpha_fade_particle( + moby->pos, D_L15_0015F580, 0x7F, moby); if (blast_center_particle != 0) { PartSub29FF90 *particle_subrecord = &blast_center_particle->sub; @@ -452,7 +453,8 @@ void giant_clank_charged_blast_update(Moby29FF90 *moby) { } blast_center_particle->fC = blast_center_particle->fC * r; blast_center_particle->fA = scale_game_frames(2); - particle_subrecord->f10 = 1.0f / convert_integer_to_float(blast_center_particle->fA); + particle_subrecord->f10 = + 1.0f / convert_integer_to_float(blast_center_particle->fA); particle_subrecord->f18 = 0x7F7F7F; particle_subrecord->f16 = 3; } diff --git a/src/overlays/shared/vehicles/giant_clank_missile.c b/src/overlays/shared/vehicles/giant_clank_missile.c index d3ebdc784a..853cac0df2 100644 --- a/src/overlays/shared/vehicles/giant_clank_missile.c +++ b/src/overlays/shared/vehicles/giant_clank_missile.c @@ -64,7 +64,15 @@ char *spawn_giant_clank_missile(void *owner, char *spawn_giant_clank_missile( - void *firing_moby, void *spawn_position, float fallback_yaw, float fallback_pitch, float target_height_offset, char *target_moby, float rz, float ry) { + void *firing_moby, + void *spawn_position, + float fallback_yaw, + float fallback_pitch, + float target_height_offset, + char *target_moby, + float rz, + + float ry) { char *spawned_missile; char *missile_spawn_data; BoltVector aim_direction_or_collision_start; @@ -82,7 +90,13 @@ char *spawn_giant_clank_missile( if (target_moby == 0) { build_spherical_offset(&aim_direction_or_collision_start, D_0015ED6C * 20.0f, rz, ry); auto_aim_position.q = *(Q_2aa998 *)spawn_position; - target_moby = select_auto_aim_target_moby(firing_moby, &auto_aim_position, &aim_direction_or_collision_start, &fallback_yaw, &fallback_pitch, &target_height_offset, 0.34906584f); + target_moby = select_auto_aim_target_moby(firing_moby, + &auto_aim_position, + &aim_direction_or_collision_start, + &fallback_yaw, + &fallback_pitch, + &target_height_offset, + 0.34906584f); } *(void **)(missile_spawn_data + 0x10) = firing_moby; qcopy(spawned_missile + 0x10, spawn_position); @@ -99,7 +113,8 @@ char *spawn_giant_clank_missile( if (target_aim_bounds[0xB] != 0) *(int *)(missile_spawn_data + 0x38) = 0; if (target_aim_bounds[0xC] != 0) - *(float *)(missile_spawn_data + 0x34) = (float)target_aim_bounds[0xC] * D_0015ED6C; + *(float *)(missile_spawn_data + 0x34) = + (float)target_aim_bounds[0xC] * D_0015ED6C; } } *(float *)(missile_spawn_data + 0x2C) = fallback_yaw; @@ -124,7 +139,11 @@ char *spawn_giant_clank_missile( } aim_direction_or_collision_start.q = ((BoltOwner *)firing_moby)->position.q; aim_direction_or_collision_start.f[2] = ((float *)spawn_position)[2]; - if (FUN_001efa68(&aim_direction_or_collision_start, spawn_position, 0, *(int *)(((char *)&D_001413D0)), 0) != 0) { + if (FUN_001efa68(&aim_direction_or_collision_start, + spawn_position, + 0, + *(int *)(((char *)&D_001413D0)), + 0) != 0) { spawned_missile[0xBC] = 1; qcopy(spawned_missile + 0x10, &D_L00_00173E60); } @@ -260,7 +279,8 @@ extern void FUN_L00_001ffd48(void *, void *, float); extern void FUN_L00_001ffe20(void *, void *, void *); extern void FUN_L00_0025a9f8(void *, void *, void *, int, int, int, int, int, float, float, float); extern void mine_spawn_drops(void *, void *) __asm__("FUN_L00_0025f800"); -extern void spawn_particle_alt_9768(void *pos, void *vel, int color, int tag, int life, float size) __asm__("FUN_L00_0026a4c8"); +extern void spawn_particle_alt_9768( + void *pos, void *vel, int color, int tag, int life, float size) __asm__("FUN_L00_0026a4c8"); extern void spawn_particle(void *, void *, int, int, float, int, int, float, int, int) __asm__("FUN_L00_0026a9f0"); extern void spawn_burst(void *, void *, int, int, int, int, float) __asm__("FUN_L00_0026cbb0"); extern void FUN_L00_002ac910(char *, char *, int, int, float, int, int, int, int); @@ -307,7 +327,9 @@ void giant_clank_missile_update(M_29E8A0 *missile_moby) { { float velocity_inheritance_frames_remaining = convert_integer_to_float(missile_data->f3C); float velocity_inheritance_frames_total = convert_integer_to_float(missile_data->f3E); - fast_vec_scale(up, ((char *)&D_0013F490), velocity_inheritance_frames_remaining / velocity_inheritance_frames_total); + fast_vec_scale(up, + ((char *)&D_0013F490), + velocity_inheritance_frames_remaining / velocity_inheritance_frames_total); } { float delta[4]; @@ -336,18 +358,25 @@ void giant_clank_missile_update(M_29E8A0 *missile_moby) { tp[2] = tp[2] + missile_data->zoff; fast_vec_sub(delta, tp, missile_moby->pos); if (missile_data->f38 != 0) { - float intercept_quadratic_coefficient, intercept_linear_coefficient, c, intercept_time_plus_root, intercept_time_minus_root, - discriminant_sqrt; + float intercept_quadratic_coefficient, intercept_linear_coefficient, c, + intercept_time_plus_root, intercept_time_minus_root, discriminant_sqrt; fast_vec_sub(dv, tp, missile_data->v); FUN_L00_001ff2c0(ip, dv, up); qcopy(missile_data->v, tp); c = FUN_L00_001ff430(dv); - intercept_linear_coefficient = (dv[0] * delta[0] + dv[1] * delta[1] + dv[2] * delta[2]) * -2.0f; + intercept_linear_coefficient = + (dv[0] * delta[0] + dv[1] * delta[1] + dv[2] * delta[2]) * -2.0f; intercept_quadratic_coefficient = missile_data->speed * missile_data->speed - c; c = -FUN_L00_001ff430(delta); - discriminant_sqrt = square_root(intercept_linear_coefficient * intercept_linear_coefficient - intercept_quadratic_coefficient * 4.0f * c); - intercept_time_plus_root = (-intercept_linear_coefficient + discriminant_sqrt) / (intercept_quadratic_coefficient + intercept_quadratic_coefficient); - intercept_time_minus_root = (-intercept_linear_coefficient - discriminant_sqrt) / (intercept_quadratic_coefficient + intercept_quadratic_coefficient); + discriminant_sqrt = + square_root(intercept_linear_coefficient * intercept_linear_coefficient - + intercept_quadratic_coefficient * 4.0f * c); + intercept_time_plus_root = + (-intercept_linear_coefficient + discriminant_sqrt) / + (intercept_quadratic_coefficient + intercept_quadratic_coefficient); + intercept_time_minus_root = + (-intercept_linear_coefficient - discriminant_sqrt) / + (intercept_quadratic_coefficient + intercept_quadratic_coefficient); if (intercept_time_plus_root > 0.0f && intercept_time_minus_root > 0.0f) { if (intercept_time_minus_root < intercept_time_plus_root) intercept_time = intercept_time_plus_root; diff --git a/src/overlays/shared/vehicles/giant_clank_pad.c b/src/overlays/shared/vehicles/giant_clank_pad.c index ed15e3c4e9..035eba9a61 100644 --- a/src/overlays/shared/vehicles/giant_clank_pad.c +++ b/src/overlays/shared/vehicles/giant_clank_pad.c @@ -68,7 +68,8 @@ void giant_clank_pad_update(struct Moby *moby) { hero.state.current != 0x1d) { if (hero.vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) { try_set_help_message(4, 0x3aa4); - } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && current_level_index != 0x12) { + } else if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK && + current_level_index != 0x12) { try_set_help_message(4, 0x3aa5); } if (!(((u32)pad_pressed_lui) & 0x10)) diff --git a/src/overlays/shared/vehicles/gunship.c b/src/overlays/shared/vehicles/gunship.c index 90f6cbc245..ecef6e1262 100644 --- a/src/overlays/shared/vehicles/gunship.c +++ b/src/overlays/shared/vehicles/gunship.c @@ -225,7 +225,8 @@ void gunship_update(struct Moby *moby) { return; } path_cursor = &v->path; - if (moby->group != 0xFF && moby->state != GUNSHIP_PATH_STATE_INITIALIZE && moby->state != GUNSHIP_PATH_STATE_WAIT_FOR_RESUME_TIMER) { + if (moby->group != 0xFF && moby->state != GUNSHIP_PATH_STATE_INITIALIZE && + moby->state != GUNSHIP_PATH_STATE_WAIT_FOR_RESUME_TIMER) { s32 bad = 0; get_first_moby_in_group(&it, moby->group, 0, 0); if (it == moby) { @@ -253,8 +254,8 @@ void gunship_update(struct Moby *moby) { } if ((moby->oclass == 0x33 || moby->oclass == 0x46A || moby->oclass == 0x473 || moby->oclass == 0x474) && - (level_frame_count & 7) == (((s32)moby >> 8) & 7) && v->unk13A <= 0 && moby->state != GUNSHIP_PATH_STATE_INITIALIZE && - FUN_L00_0028d8c0(moby, v->unk11E) == 0) { + (level_frame_count & 7) == (((s32)moby >> 8) & 7) && v->unk13A <= 0 && + moby->state != GUNSHIP_PATH_STATE_INITIALIZE && FUN_L00_0028d8c0(moby, v->unk11E) == 0) { v->unk11E = allocate_voice_for_target_entry(0, 4, moby); } switch ((s16)(moby->oclass - 0x33)) { diff --git a/src/overlays/shared/vehicles/hoverboard.c b/src/overlays/shared/vehicles/hoverboard.c index 5f343e5b90..da6500cd21 100644 --- a/src/overlays/shared/vehicles/hoverboard.c +++ b/src/overlays/shared/vehicles/hoverboard.c @@ -95,20 +95,38 @@ void hoverboard_update(unsigned char *moby) { effect_position[3] = (float)hoverboard_effect_displacement_w_gp; if ((unsigned char)MOBY(moby)->command == 0) { int size = random_int_between(scale_game_frames(10), scale_game_frames(13)); - spawn_effect( - position, effect_position, l05_hoverboard_effect_initial_color, l05_hoverboard_effect_color_endpoint, size, 15, 15, 1); + spawn_effect(position, + effect_position, + l05_hoverboard_effect_initial_color, + l05_hoverboard_effect_color_endpoint, + size, + 15, + 15, + 1); MOBY(moby)->command = 0; return; } fast_vec_scale(second_position, delta, 0.920f); { int size = random_int_between(scale_game_frames(15), scale_game_frames(18)); - spawn_effect(position, second_position, 0x5032f0d2, l05_hoverboard_effect_color_endpoint, size, 30, 20, 1); + spawn_effect(position, + second_position, + 0x5032f0d2, + l05_hoverboard_effect_color_endpoint, + size, + 30, + 20, + 1); } { int size = random_int_between(scale_game_frames(8), scale_game_frames(17)); - FUN_L00_0026cbb0( - position, effect_position, l05_hoverboard_effect_initial_color, l05_hoverboard_effect_color_endpoint, size, 1, 15000.0f); + FUN_L00_0026cbb0(position, + effect_position, + l05_hoverboard_effect_initial_color, + l05_hoverboard_effect_color_endpoint, + size, + 1, + 15000.0f); } } MOBY(moby)->command = 0; diff --git a/src/overlays/shared/vehicles/ship_rocket.c b/src/overlays/shared/vehicles/ship_rocket.c index 4e40d7c35e..c80d508c40 100644 --- a/src/overlays/shared/vehicles/ship_rocket.c +++ b/src/overlays/shared/vehicles/ship_rocket.c @@ -55,7 +55,11 @@ void ship_rocket_update(struct Moby *moby) __asm__("FUN_L11_003094f8"); /* Moby class 1034 */ void ship_rocket_update(struct Moby *moby) { - enum { MOBY_STATE_PENDING_REMOVAL_BELOW_BOUNDARY = 0xfd , MOBY_STATE_PENDING_REMOVAL_AT_OR_ABOVE_BOUNDARY = 0xfe } ;Missile_94f8 *rocket_vars = (Missile_94f8 *)moby->pvars; + enum { + MOBY_STATE_PENDING_REMOVAL_BELOW_BOUNDARY = 0xfd, + MOBY_STATE_PENDING_REMOVAL_AT_OR_ABOVE_BOUNDARY = 0xfe + }; + Missile_94f8 *rocket_vars = (Missile_94f8 *)moby->pvars; Vec4f *pos; Vec4 previous_pos, spray, offset, velocity, random; float fraction; @@ -118,7 +122,8 @@ void ship_rocket_update(struct Moby *moby) { } pos = &moby->pos; target = rocket_vars->target; - if (target != 0 && target->state != MOBY_STATE_PENDING_REMOVAL_AT_OR_ABOVE_BOUNDARY && target->state != MOBY_STATE_PENDING_REMOVAL_BELOW_BOUNDARY && + if (target != 0 && target->state != MOBY_STATE_PENDING_REMOVAL_AT_OR_ABOVE_BOUNDARY && + target->state != MOBY_STATE_PENDING_REMOVAL_BELOW_BOUNDARY && fast_vec_dist(&rocket_vars->target_pos, &target->pos) < 3.0f) { moby->rot.z = fast_arc_tan(rocket_vars->target->pos.x - moby->pos.x, rocket_vars->target->pos.y - moby->pos.y); diff --git a/src/overlays/shared/vehicles/veldin_ship.c b/src/overlays/shared/vehicles/veldin_ship.c index 4354ac7317..6d5811f0e3 100644 --- a/src/overlays/shared/vehicles/veldin_ship.c +++ b/src/overlays/shared/vehicles/veldin_ship.c @@ -107,7 +107,8 @@ void veldin_ship_draw(struct Moby *moby) { reflection.z += 1.0f; reflection_projection_factor = square_root(reflection.z + reflection.z); reflection_projection_factor += reflection_projection_factor; - if (moby->state == VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING || *(s32 *)(ship_render_state + 0x40) == 0) { + if (moby->state == VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING || + *(s32 *)(ship_render_state + 0x40) == 0) { ship_reflection_uvs[i][0] = reflection.x / reflection_projection_factor + 0.5f; ship_reflection_uvs[i][1] = reflection.y / reflection_projection_factor + 0.5f; } else { diff --git a/src/overlays/shared/vendor/draw_vendor_purchase_text.c b/src/overlays/shared/vendor/draw_vendor_purchase_text.c index 82872c2a3b..602b306400 100644 --- a/src/overlays/shared/vendor/draw_vendor_purchase_text.c +++ b/src/overlays/shared/vendor/draw_vendor_purchase_text.c @@ -132,8 +132,8 @@ typedef struct { } HeightGridLayout; extern HeightGridLayout l00_pool_height_grid_layout __asm__("D_L00_001CA880"); -extern s32 l00_pool_height_write_bank_index __asm__("D_L00_00161218") __attribute__((sda)); -extern s32 l00_pool_height_additive_read_bank_index __asm__("D_L00_00161220") __attribute__((sda)); +extern s32 l00_pool_height_write_bank_index __asm__("D_L00_00161218") __attribute__((sda)); +extern s32 l00_pool_height_additive_read_bank_index __asm__("D_L00_00161220") __attribute__((sda)); /* Splash on the pool height tiles: raises the heights around (x, z) and copies the edges into the neighbour tiles. */ void pool_splash(HeightTile *tile, @@ -157,7 +157,8 @@ void pool_splash( for (i = 0; i < count; i++) { float tile_z = tile->z + l00_pool_height_grid_layout.origin_z; float cell_z = (z - tile_z) / l00_pool_height_grid_layout.cell_height; - float cell_x = (x - (tile->x + l00_pool_height_grid_layout.origin_x)) / l00_pool_height_grid_layout.cell_width; + float cell_x = (x - (tile->x + l00_pool_height_grid_layout.origin_x)) / + l00_pool_height_grid_layout.cell_width; int row_first, row_last, col_first, col_last; float row_z; @@ -176,8 +177,8 @@ void pool_splash( row_z = tile_z + l00_pool_height_grid_layout.cell_height * (float)row_first; for (row = row_first; row <= row_last; row++) { - float col_x = - (tile->x + l00_pool_height_grid_layout.origin_x) + l00_pool_height_grid_layout.cell_width * (float)col_first; + float col_x = (tile->x + l00_pool_height_grid_layout.origin_x) + + l00_pool_height_grid_layout.cell_width * (float)col_first; int col; for (col = col_first; col <= col_last; col++) { @@ -191,7 +192,8 @@ void pool_splash( } if (mode == POOL_SPLASH_KEEP_GREATER_MAGNITUDE) { float magnitude = absolute_float(height); - if (magnitude < absolute_float(tile->heights[l00_pool_height_write_bank_index][row][col])) { + if (magnitude < + absolute_float(tile->heights[l00_pool_height_write_bank_index][row][col])) { height = tile->heights[l00_pool_height_write_bank_index][row][col]; } } else { @@ -212,10 +214,12 @@ void pool_splash( } if (col < 2 && tile->neighbours[1] != 0xFF) { if (col == 0) { - tiles[tile->neighbours[1]].heights[l00_pool_height_write_bank_index][19][row] = + tiles[tile->neighbours[1]] + .heights[l00_pool_height_write_bank_index][19][row] = tile->heights[l00_pool_height_write_bank_index][row][0]; } else { - tiles[tile->neighbours[1]].heights[l00_pool_height_write_bank_index][21][row] = + tiles[tile->neighbours[1]] + .heights[l00_pool_height_write_bank_index][21][row] = tile->heights[l00_pool_height_write_bank_index][row][col]; } } diff --git a/src/overlays/shared/vendor/vendor.c b/src/overlays/shared/vendor/vendor.c index 8ef248e878..6668001293 100644 --- a/src/overlays/shared/vendor/vendor.c +++ b/src/overlays/shared/vendor/vendor.c @@ -345,7 +345,8 @@ void vendor_update(P_2a57a8 *vendor_moby) { } add_draw_callback(FUN_L00_002a5040_2a57a8, vendor_moby); build_axis_rotation_quaternion((u8 *)q + 0x20, 2, vendor_manipulator_rotation_phase); - build_axis_rotation_quaternion((u8 *)q + 0x60, 2, vendor_manipulator_counter_rotation_phase); + build_axis_rotation_quaternion( + (u8 *)q + 0x60, 2, vendor_manipulator_counter_rotation_phase); vendor_manipulator_rotation_phase = fast_add_rotations(vendor_manipulator_rotation_phase, 0.01f); vendor_manipulator_counter_rotation_phase = @@ -368,7 +369,8 @@ void vendor_update(P_2a57a8 *vendor_moby) { interaction_allowed = 1; help_message_allowed = 1; build_axis_rotation_quaternion((u8 *)q + 0x20, 2, vendor_manipulator_rotation_phase); - build_axis_rotation_quaternion((u8 *)q + 0x60, 2, vendor_manipulator_counter_rotation_phase); + build_axis_rotation_quaternion( + (u8 *)q + 0x60, 2, vendor_manipulator_counter_rotation_phase); vendor_manipulator_rotation_phase = fast_add_rotations(vendor_manipulator_rotation_phase, 0.01f); vendor_manipulator_counter_rotation_phase = diff --git a/src/overlays/shared/vendor/vendor_menu.c b/src/overlays/shared/vendor/vendor_menu.c index d051f84f45..61ad6e2099 100644 --- a/src/overlays/shared/vendor/vendor_menu.c +++ b/src/overlays/shared/vendor/vendor_menu.c @@ -1080,7 +1080,8 @@ void update_vendor_purchase(void) { ammo_bought_stats[CUR_ITEM.item] += k; handle_vendor_auxiliary_moby_event(3); D_0015ED98 = D_0015ED98 - purchase_cost; - build_vendor_menu_rows(vendor_menu.mode != VENDOR_MENU_MODE_EXISTING_VENDOR); + build_vendor_menu_rows(vendor_menu.mode != + VENDOR_MENU_MODE_EXISTING_VENDOR); set_scrolling_status_message(get_help_message_text(0x4F5F)); allocate_voice_for_target_entry(7, 0, vendor_menu.vendor_moby); } else { @@ -1182,7 +1183,8 @@ void update_vendor_menu(void) { switch (vendor_menu.state) { case VENDOR_MENU_OPENING: case VENDOR_MENU_CLOSING: - if (vendor_menu.mode == VENDOR_MENU_MODE_EXISTING_VENDOR || vendor_menu.state == VENDOR_MENU_CLOSING) { + if (vendor_menu.mode == VENDOR_MENU_MODE_EXISTING_VENDOR || + vendor_menu.state == VENDOR_MENU_CLOSING) { if ((g_debug_menu.update_flags & 2) || ((g_debug_menu.update_flags & 0x10) && (((u32)pad_pressed_lui) & 0x200))) { reset_frame_counters(); @@ -1211,7 +1213,8 @@ void update_vendor_menu(void) { fade_level = 0.0f; } vendor_menu.frames++; - if (vendor_menu.frames >= scale_game_frames(40) || vendor_menu.mode != VENDOR_MENU_MODE_EXISTING_VENDOR) { + if (vendor_menu.frames >= scale_game_frames(40) || + vendor_menu.mode != VENDOR_MENU_MODE_EXISTING_VENDOR) { fade_level = 0.0f; vendor_menu.unk0C = 1; vendor_menu.state = VENDOR_MENU_OPEN; @@ -1224,13 +1227,15 @@ void update_vendor_menu(void) { } } else if (vendor_menu_state == VENDOR_MENU_CLOSING) { ok = 0; - if (vendor_menu.mode == VENDOR_MENU_MODE_EXISTING_VENDOR && vendor_menu.purchased_item >= 0) { + if (vendor_menu.mode == VENDOR_MENU_MODE_EXISTING_VENDOR && + vendor_menu.purchased_item >= 0) { if (vendor_exit_cutscene_ids_by_item[vendor_menu.purchased_item] >= 0) { ok = 1; } } vendor_menu.frames++; - if (vendor_menu.frames >= scale_game_frames(40) || vendor_menu.mode != VENDOR_MENU_MODE_EXISTING_VENDOR) { + if (vendor_menu.frames >= scale_game_frames(40) || + vendor_menu.mode != VENDOR_MENU_MODE_EXISTING_VENDOR) { FUN_00212f90(vendor_menu.vendor_moby, 1, 0, 8); row = vendor_slots; for (k = 0; k < 4; k++) { @@ -1371,9 +1376,11 @@ void update_vendor_menu(void) { &vendor_menu.menu_mobys[3].pos, &position_contribution_scratch); vendor_menu.frames++; - if (vendor_menu.purchase_state == VENDOR_PURCHASE_INACTIVE && l00_vendor_close_pending == 0) { + if (vendor_menu.purchase_state == VENDOR_PURCHASE_INACTIVE && + l00_vendor_close_pending == 0) { if (vendor_menu.row_count < 8) { - if ((controller_state.pressed_unmasked & 0x2000) && !(l00_vendor_previous_pressed_buttons & 0x2000)) { + if ((controller_state.pressed_unmasked & 0x2000) && + !(l00_vendor_previous_pressed_buttons & 0x2000)) { if (vendor_menu.cursor < vendor_menu.row_count - 1) { D_L00_00161E38 = 1; handle_vendor_auxiliary_moby_event(0); @@ -1396,7 +1403,8 @@ void update_vendor_menu(void) { } } } - if ((controller_state.pressed_unmasked & 0x8000) && !(l00_vendor_previous_pressed_buttons & 0x8000)) { + if ((controller_state.pressed_unmasked & 0x8000) && + !(l00_vendor_previous_pressed_buttons & 0x8000)) { if (vendor_menu.cursor > 0) { D_L00_00161E38 = 1; handle_vendor_auxiliary_moby_event(0); @@ -1420,7 +1428,8 @@ void update_vendor_menu(void) { } } } else { - if ((controller_state.pressed_unmasked & 0x2000) && !(l00_vendor_previous_pressed_buttons & 0x2000)) { + if ((controller_state.pressed_unmasked & 0x2000) && + !(l00_vendor_previous_pressed_buttons & 0x2000)) { if (vendor_menu.scroll <= 0x38) { D_L00_00161E38 = 1; vendor_menu.scroll += 0x38; @@ -1448,7 +1457,8 @@ void update_vendor_menu(void) { } } } - if ((controller_state.pressed_unmasked & 0x8000) && !(l00_vendor_previous_pressed_buttons & 0x8000)) { + if ((controller_state.pressed_unmasked & 0x8000) && + !(l00_vendor_previous_pressed_buttons & 0x8000)) { if (vendor_menu.scroll >= -0x38) { D_L00_00161E38 = 1; vendor_menu.scroll -= 0x38; @@ -1477,7 +1487,8 @@ void update_vendor_menu(void) { } } } - if ((controller_state.pressed_unmasked & 0x40) && !(l00_vendor_previous_pressed_buttons & 0x40) && + if ((controller_state.pressed_unmasked & 0x40) && + !(l00_vendor_previous_pressed_buttons & 0x40) && CUR_ITEM.state == VENDOR_ROW_PURCHASE_REQUEST_ENABLED) { vendor_menu.purchase_state = VENDOR_PURCHASE_INITIALIZE; allocate_voice_for_target_entry(0, 0, vendor_menu.vendor_moby); diff --git a/src/overlays/shared/weapons/bomb_glove_bomb.c b/src/overlays/shared/weapons/bomb_glove_bomb.c index b799bd2499..135ce06f0a 100644 --- a/src/overlays/shared/weapons/bomb_glove_bomb.c +++ b/src/overlays/shared/weapons/bomb_glove_bomb.c @@ -1069,7 +1069,8 @@ int predict_throw_landing(LandingVars *v, M910 *thrown_moby, int mode) { if (!FUN_L00_002603d0_2ad410(coll_hit.moby)) goto return_zero; } - if (mode != THROW_LANDING_MODE_SKIP_LINKED_MOBY_MARKER || !coll_hit.moby || !FUN_L00_002603d0_2ad410(coll_hit.moby)) + if (mode != THROW_LANDING_MODE_SKIP_LINKED_MOBY_MARKER || !coll_hit.moby || + !FUN_L00_002603d0_2ad410(coll_hit.moby)) add_draw_callback(draw_bomb_landing_marker, thrown_moby); if (!object_hit && v->last_hit) { if (v->last_hit->state == 0xfe) { @@ -1173,8 +1174,8 @@ void bomb_update(BombMoby *bomb_moby) { v2.f[3] = random_float_between(*(float *)&D_L00_00161414, *(float *)&D_L00_00161418); spark_primary_color = fast_tween_color(*(int *)&bomb_spark_primary_color_start, - *(int *)&bomb_spark_primary_color_end, - random_float_between(0.0f, 1.0f)); + *(int *)&bomb_spark_primary_color_end, + random_float_between(0.0f, 1.0f)); spark_secondary_color = fast_tween_color(*(int *)&bomb_spark_secondary_color_start, *(int *)&bomb_spark_secondary_color_end, @@ -1416,14 +1417,16 @@ void bomb_update(BombMoby *bomb_moby) { for (i = 0; i < blast_effect_count; i++) { float spd = s * random_float_between(8.0f, 10.0f) * frame_time_macro - g * frame_time_macro; - Colors6 blast_effect_primary_palette = l00_bomb_blast_effect_primary_palette; + Colors6 blast_effect_primary_palette = + l00_bomb_blast_effect_primary_palette; Colors6 blast_effect_secondary_palette = l00_bomb_blast_effect_secondary_palette; FUN_L00_0026a9f0_2adb30( &bomb_moby->pos, &blast_velocity, - swap_packed_color_channels(blast_effect_primary_palette.c[random_integer_below(6)], - (unsigned char)item_text_variant[0xA]), + swap_packed_color_channels( + blast_effect_primary_palette.c[random_integer_below(6)], + (unsigned char)item_text_variant[0xA]), swap_packed_color_channels( blast_effect_secondary_palette.c[random_integer_below(6)], (unsigned char)item_text_variant[0xA]), diff --git a/src/overlays/shared/weapons/decoy.c b/src/overlays/shared/weapons/decoy.c index 358faf19e0..c43b96b239 100644 --- a/src/overlays/shared/weapons/decoy.c +++ b/src/overlays/shared/weapons/decoy.c @@ -347,7 +347,12 @@ s32 predict_thrown_moby_landing(ThrowVars *throw_vars, s32 mode) __asm__("FUN_L00_002c3af8"); s32 predict_thrown_moby_landing(ThrowVars *throw_vars, struct Moby *thrown_moby, s32 mode) { - enum { LANDING_REQUIRE_MOBY_PVARS_LINK = 0 , DECOY_HELD = 1 , LANDING_SKIP_LINKED_MOBY_DRAW = 2 } ;Vec4 predicted_position, predicted_velocity, position_scratch, q, ground_probe_position; + enum { + LANDING_REQUIRE_MOBY_PVARS_LINK = 0, + DECOY_HELD = 1, + LANDING_SKIP_LINKED_MOBY_DRAW = 2 + }; + Vec4 predicted_position, predicted_velocity, position_scratch, q, ground_probe_position; s32 prediction_countdown; s32 found = 0; s32 i; @@ -444,7 +449,8 @@ s32 predict_thrown_moby_landing(ThrowVars *throw_vars, struct Moby *thrown_moby, if (FUN_L00_002603d0(coll_hit.moby) == 0) goto ret0; } - if (mode != LANDING_SKIP_LINKED_MOBY_DRAW || coll_hit.moby == 0 || !FUN_L00_002603d0(coll_hit.moby)) + if (mode != LANDING_SKIP_LINKED_MOBY_DRAW || coll_hit.moby == 0 || + !FUN_L00_002603d0(coll_hit.moby)) add_draw_callback(draw_moby_oscillating_textured_quads, thrown_moby); throw_vars->normal.q = coll_hit_normal.q; fast_vec_sub(&position_scratch, &throw_vars->landing, &D_L00_00166DC0); diff --git a/src/overlays/shared/weapons/decoy_glove.c b/src/overlays/shared/weapons/decoy_glove.c index 6103f35b56..2fbb5b0c21 100644 --- a/src/overlays/shared/weapons/decoy_glove.c +++ b/src/overlays/shared/weapons/decoy_glove.c @@ -103,10 +103,10 @@ void decoy_glove_aim_throw(int collision_arg, Moby_2D3608 *carrier, float *posit Vec_2D3608 direction, aim, launch, origin_copy, endpoint; Moby_2D3608 *target; float *output; - float aim_slope_or_extension_scale, distance, heading, vertical, pitch, length, fall_time; - int hit; - float range; - float *anchor_ptr = anchor; + float aim_slope_or_extension_scale, distance, heading, vertical, pitch, length, fall_time; + int hit; + float range; + float *anchor_ptr = anchor; *(u128_2D3608 *)anchor_ptr = *(u128_2D3608 *)position; copy_matrix3x4(rotation, l00_camera.unk0); @@ -160,7 +160,8 @@ void decoy_glove_aim_throw(int collision_arg, Moby_2D3608 *carrier, float *posit } fall_time = square_root(D_0015ED70 * 9.0f * ((controller_state.held & 5) ? 3.5f : 2.5f) * 0.5f); - distance = (fall_time + fall_time) * fall_time * (1.0f - aim_slope_or_extension_scale) / (D_0015ED70 * 9.0f); + distance = (fall_time + fall_time) * fall_time * (1.0f - aim_slope_or_extension_scale) / + (D_0015ED70 * 9.0f); vertical = aim_slope_or_extension_scale * distance; if (0.0f < distance) { launch[0] = func_001F9F90_2D3608(heading) * distance; @@ -176,8 +177,10 @@ void decoy_glove_aim_throw(int collision_arg, Moby_2D3608 *carrier, float *posit } if (hit == 0) { aim_slope_or_extension_scale = 5.0f; - aim[0] = func_001F9F90_2D3608(heading) * distance * aim_slope_or_extension_scale; - aim[1] = func_001F9FA8_2D3608(heading) * distance * aim_slope_or_extension_scale; + aim[0] = + func_001F9F90_2D3608(heading) * distance * aim_slope_or_extension_scale; + aim[1] = + func_001F9FA8_2D3608(heading) * distance * aim_slope_or_extension_scale; aim[2] = vertical * aim_slope_or_extension_scale; fast_vec_add(aim, aim, g_debug_camera.position); } diff --git a/src/overlays/shared/weapons/doom_bot.c b/src/overlays/shared/weapons/doom_bot.c index 1606b38bce..fe3c00467d 100644 --- a/src/overlays/shared/weapons/doom_bot.c +++ b/src/overlays/shared/weapons/doom_bot.c @@ -456,7 +456,8 @@ void doom_bot_update(struct Moby *moby) { } else clearance = 5.0f; } - if (moby->state == DOOM_BOT_MOVE_HIGH_TURN_RATE && old_state == DOOM_BOT_MOVE_LOW_TURN_RATE) { + if (moby->state == DOOM_BOT_MOVE_HIGH_TURN_RATE && + old_state == DOOM_BOT_MOVE_LOW_TURN_RATE) { moby->state = DOOM_BOT_WAIT_FOR_TRANSITION_ANIMATION; if (moby->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); diff --git a/src/overlays/shared/weapons/drone.c b/src/overlays/shared/weapons/drone.c index 42f8108a5e..4d7128935a 100644 --- a/src/overlays/shared/weapons/drone.c +++ b/src/overlays/shared/weapons/drone.c @@ -351,7 +351,16 @@ void drone_update(struct Moby *updated_moby) __asm__("FUN_L00_002ce358"); /* Moby class 479 */ void drone_update(struct Moby *updated_moby) { - enum { DRONE_STATE_ORBIT = 2 , DRONE_STATE_PURSUE_TARGET = 3 , DRONE_STATE_FADE = 4 , DRONE_STATE_REMOVE = 5 } ; enum { MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE} ;DroneVars *drone_vars = (DroneVars *)updated_moby->pvars; + enum { + DRONE_STATE_ORBIT = 2, + DRONE_STATE_PURSUE_TARGET = 3, + DRONE_STATE_FADE = 4, + DRONE_STATE_REMOVE = 5 + }; + enum { + MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE + }; + DroneVars *drone_vars = (DroneVars *)updated_moby->pvars; Vec4 collision_data[1], old_pos; Vec4 direction, rotated; Vec4 target_pos, matrix[4]; @@ -416,7 +425,8 @@ void drone_update(struct Moby *updated_moby) { drone = ((DroneSlots *)&hero)->slots[i]; if (drone != 0) { struct Moby *drone_target = *(struct Moby **)(drone->pvars + 0x30); - if (drone_target == 0 || drone_target->state == MOBY_STATE_MARKED_FOR_REMOVAL || + if (drone_target == 0 || + drone_target->state == MOBY_STATE_MARKED_FOR_REMOVAL || drone_target->state == 0xFD) { f32 candidate_distance = vector_distance_xy(&drone->pos, &old_pos); if (candidate_distance < distance) { @@ -609,8 +619,8 @@ state3: { updated_moby->collision = pclass->collision; func_L00_002CF328_2CF808(updated_moby); target = drone_vars->target; - if (target != 0 && target->oclass == drone_vars->target_oclass && target->state != MOBY_STATE_MARKED_FOR_REMOVAL && - target->state != 0xFD) { + if (target != 0 && target->oclass == drone_vars->target_oclass && + target->state != MOBY_STATE_MARKED_FOR_REMOVAL && target->state != 0xFD) { char *h = get_moby_target_info(target); qcopy(&target_pos, &drone_vars->target->pos); if (h != 0) @@ -625,8 +635,8 @@ state3: { qcopy(&collision_data[0], &updated_moby->pos); if (coll_sphere(0.25f, &collision_data[0], 0, updated_moby)) { struct Moby *hm = (struct Moby *)coll_hit.moby; - if (!hm || hm->state == MOBY_STATE_MARKED_FOR_REMOVAL || hm->state == 0xFD || hm != drone_vars->target || - hm->oclass == 0) { + if (!hm || hm->state == MOBY_STATE_MARKED_FOR_REMOVAL || hm->state == 0xFD || + hm != drone_vars->target || hm->oclass == 0) { qcopy(&updated_moby->pos, &coll_hit_position); } else { s32 cat2 = hm->pclass ? *(u8 *)((u8 *)hm->pclass + 0x46) : 0; diff --git a/src/overlays/shared/weapons/effect_slots_fire.c b/src/overlays/shared/weapons/effect_slots_fire.c index 2a41c7e534..3d516727de 100644 --- a/src/overlays/shared/weapons/effect_slots_fire.c +++ b/src/overlays/shared/weapons/effect_slots_fire.c @@ -43,11 +43,11 @@ extern float D_L02_00174460[]; extern float FUN_L04_001f1978(float); extern float fast_vec_dist(void *, void *); extern int D_L02_0015F5CC MACRO_ADDR; -extern float l02_effect_particle_travel_step_limit __asm__("D_L02_001600D0") __attribute__((sda)); -extern int l02_effect_alternate_particle_count __asm__("D_L02_001600D4") __attribute__((sda)); -extern int l02_effect_default_particle_count __asm__("D_L02_001600D8") __attribute__((sda)); -extern float l02_effect_particle_full_travel_spread __asm__("D_L02_001600DC") __attribute__((sda)); -extern float l02_effect_particle_zero_travel_spread __asm__("D_L02_001600E0") __attribute__((sda)); +extern float l02_effect_particle_travel_step_limit __asm__("D_L02_001600D0") __attribute__((sda)); +extern int l02_effect_alternate_particle_count __asm__("D_L02_001600D4") __attribute__((sda)); +extern int l02_effect_default_particle_count __asm__("D_L02_001600D8") __attribute__((sda)); +extern float l02_effect_particle_full_travel_spread __asm__("D_L02_001600DC") __attribute__((sda)); +extern float l02_effect_particle_zero_travel_spread __asm__("D_L02_001600E0") __attribute__((sda)); void effect_slots_fire(char *slots, float *position, @@ -104,7 +104,9 @@ void effect_slots_fire(char *slots, float *position, float *direction, float dis random_vector( offset, 0.0f, - (((l02_effect_particle_full_travel_spread) - (l02_effect_particle_zero_travel_spread)) * (travel / distance) + (l02_effect_particle_zero_travel_spread)) * + (((l02_effect_particle_full_travel_spread) - (l02_effect_particle_zero_travel_spread)) * + (travel / distance) + + (l02_effect_particle_zero_travel_spread)) * frame_time_macro); fast_vec_add(offset, offset, adjusted); fast_vec_scale(velocity, adjusted, random_float_between(0.0f, 1.0f)); diff --git a/src/overlays/shared/weapons/glove_of_doom_bomb.c b/src/overlays/shared/weapons/glove_of_doom_bomb.c index 588be21529..0051ef1c42 100644 --- a/src/overlays/shared/weapons/glove_of_doom_bomb.c +++ b/src/overlays/shared/weapons/glove_of_doom_bomb.c @@ -61,7 +61,12 @@ s32 predict_doom_bot_spawner_landing(ThrowVars *throw_vars, s32 mode) __asm__("FUN_L00_002c8440"); s32 predict_doom_bot_spawner_landing(ThrowVars *throw_vars, struct Moby *thrown_moby, s32 mode) { - enum { DOOM_LANDING_MODE_REQUIRE_LINKED_MOBY = 0 , THROWN_MOBY_STATE_GROW_TO_QUARTER_SCALE = 1 , DOOM_LANDING_MODE_SKIP_LINKED_MOBY_DRAW_CALLBACK = 2 } ;Vec4 simulated_position, simulated_velocity, position_scratch, q, landing_probe_position; + enum { + DOOM_LANDING_MODE_REQUIRE_LINKED_MOBY = 0, + THROWN_MOBY_STATE_GROW_TO_QUARTER_SCALE = 1, + DOOM_LANDING_MODE_SKIP_LINKED_MOBY_DRAW_CALLBACK = 2 + }; + Vec4 simulated_position, simulated_velocity, position_scratch, q, landing_probe_position; s32 prediction_timer; s32 found = 0; s32 i; @@ -162,7 +167,8 @@ s32 predict_doom_bot_spawner_landing(ThrowVars *throw_vars, struct Moby *thrown_ if (get_moby_pvars_link(coll_hit.moby) == 0) goto ret0; } - if (mode != DOOM_LANDING_MODE_SKIP_LINKED_MOBY_DRAW_CALLBACK || coll_hit.moby == 0 || !get_moby_pvars_link(coll_hit.moby)) + if (mode != DOOM_LANDING_MODE_SKIP_LINKED_MOBY_DRAW_CALLBACK || coll_hit.moby == 0 || + !get_moby_pvars_link(coll_hit.moby)) add_draw_callback(FUN_L00_002c7df8_2c8440, thrown_moby); throw_vars->normal.q = coll_hit_normal.q; fast_vec_sub(&position_scratch, &throw_vars->landing, &g_debug_camera_lui); diff --git a/src/overlays/shared/weapons/gold_devastator_missile.c b/src/overlays/shared/weapons/gold_devastator_missile.c index 71b8264bcf..14e6b2285e 100644 --- a/src/overlays/shared/weapons/gold_devastator_missile.c +++ b/src/overlays/shared/weapons/gold_devastator_missile.c @@ -174,7 +174,8 @@ extern void FUN_L00_001ff290_c(void *, void *, void *) __asm__("FUN_L00_001ff290 extern int collision1688(void *, void *, int, void *, void *) __asm__("FUN_001efa68"); extern void FUN_L00_001ffd48_c(void *, void *, float) __asm__("FUN_L00_001ffd48"); extern void FUN_L00_001ffe20_c(void *, void *, void *) __asm__("FUN_L00_001ffe20"); -extern void spawn_particle_alt_9768(void *, void *, int, int, float, int) __asm__("FUN_L00_0026a4c8"); +extern void +spawn_particle_alt_9768(void *, void *, int, int, float, int) __asm__("FUN_L00_0026a4c8"); extern E D_0013E520; extern char *active_mobies[] __asm__("D_L00_001ABA00"); diff --git a/src/overlays/shared/weapons/metal_detector.c b/src/overlays/shared/weapons/metal_detector.c index 5e4ad28986..f8a3da2039 100644 --- a/src/overlays/shared/weapons/metal_detector.c +++ b/src/overlays/shared/weapons/metal_detector.c @@ -373,7 +373,8 @@ void metal_detector_update(struct Moby *moby) { } target_moby = hero.metal_detector_target; if (target_moby != 0 && target_moby->oclass == 0x25D && - target_moby->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && target_moby->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && + target_moby->state != MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END && + target_moby->state != MOBY_STATE_REMOVAL_BELOW_INSTANCE_END && hero.detector_target_dist < 1.0f) { tv = (TargetVars2d2ee8 *)target_moby->pvars; while (tv->count > 0) { diff --git a/src/overlays/shared/weapons/mine.c b/src/overlays/shared/weapons/mine.c index 72e3ffb3c4..747b7c2a86 100644 --- a/src/overlays/shared/weapons/mine.c +++ b/src/overlays/shared/weapons/mine.c @@ -62,12 +62,13 @@ extern int FUN_L00_001f0d60(float, void *, int, void *); extern int collect_mobies_in_sphere(void *, int, void *, void *, float) __asm__("FUN_L00_001f2868"); extern int hud_counter_update(int, int, float) __asm__("FUN_L00_002371e0"); extern int FUN_L00_00257b90(int, int); -extern int move_moby_xy_with_collision_constraints(void *, void *, void *, float, float, float, float, int) __asm__("FUN_L00_00258490"); -extern int FUN_L00_00260400(void *, void *, void *, void *, void *, void *); -extern int random_integer_below_cf(void *, void *, float, float) __asm__("FUN_L00_0026f080"); -extern int voice_is_playing(void *, int) __asm__("FUN_L00_0028d8c0"); -extern s32 is_moby_in_class_range_500_to_540(s32) __asm__("FUN_L00_0025e3b8"); -extern unsigned swap_packed_color_channels(unsigned c, int mask) __asm__("FUN_L00_0025c0e8"); +extern int move_moby_xy_with_collision_constraints( + void *, void *, void *, float, float, float, float, int) __asm__("FUN_L00_00258490"); +extern int FUN_L00_00260400(void *, void *, void *, void *, void *, void *); +extern int random_integer_below_cf(void *, void *, float, float) __asm__("FUN_L00_0026f080"); +extern int voice_is_playing(void *, int) __asm__("FUN_L00_0028d8c0"); +extern s32 is_moby_in_class_range_500_to_540(s32) __asm__("FUN_L00_0025e3b8"); +extern unsigned swap_packed_color_channels(unsigned c, int mask) __asm__("FUN_L00_0025c0e8"); extern unsigned char *FUN_002141f8_cf(unsigned char *) __asm__("FUN_L00_002603d0"); extern void *find_moby_hit(void *, int, int) __asm__("FUN_L00_0025a420"); extern void *spawn_shrinking_effect_particle_with_gravity_and_secondary_spawns( @@ -512,7 +513,14 @@ void initialize_moby_motion_at_position(V_2aa008 *requested_position, int predict_mine_impact(char *trajectory_state, char *moby, int mode) __asm__("FUN_L00_002aa2a8"); int predict_mine_impact(char *trajectory_state, char *moby, int mode) { - enum { MINE_STATE_OWNER_ATTACHED = 0 } ; enum { MINE_PREDICTION_REQUIRE_LINKED_MOBY_HIT = 0 , MINE_PREDICTION_HIDE_LINKED_MOBY_HIT_MARKER = 2} ;float trajectory_position[4]; + enum { + MINE_STATE_OWNER_ATTACHED = 0 + }; + enum { + MINE_PREDICTION_REQUIRE_LINKED_MOBY_HIT = 0, + MINE_PREDICTION_HIDE_LINKED_MOBY_HIT_MARKER = 2 + }; + float trajectory_position[4]; float B[4]; float C[4]; float box[4]; @@ -541,7 +549,8 @@ int predict_mine_impact(char *trajectory_state, char *moby, int mode) { trajectory_position[2] = trajectory_position[2] + 0.49082f; qcopy(B, trajectory_state); if (*(int *)(hero_state + 0x2FC) != 0 && - FUN_L00_002603d0_u((void *)*(int *)(hero_state + 0x2FC)) != 0 && mode != MINE_PREDICTION_REQUIRE_LINKED_MOBY_HIT) { + FUN_L00_002603d0_u((void *)*(int *)(hero_state + 0x2FC)) != 0 && + mode != MINE_PREDICTION_REQUIRE_LINKED_MOBY_HIT) { fast_vec_add(B, B, hero_state + 0x100); } x = scale_game_frames(0x78); @@ -591,7 +600,8 @@ int predict_mine_impact(char *trajectory_state, char *moby, int mode) { if (FUN_L00_002603d0_u(coll_hit_moby) == 0) return 0; } - if (mode != MINE_PREDICTION_HIDE_LINKED_MOBY_HIT_MARKER || coll_hit_moby == 0 || FUN_L00_002603d0_u(coll_hit_moby) == 0) { + if (mode != MINE_PREDICTION_HIDE_LINKED_MOBY_HIT_MARKER || coll_hit_moby == 0 || + FUN_L00_002603d0_u(coll_hit_moby) == 0) { add_draw_callback(FUN_L00_002a9c50_c, moby); } { @@ -651,7 +661,8 @@ void mine_update(M910 *mine_moby) { mark_moby_for_removal(mine_moby); return; } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && mine_moby->state == MINE_STATE_OWNER_ATTACHED) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && + mine_moby->state == MINE_STATE_OWNER_ATTACHED) { mark_moby_for_removal(mine_moby); return; } @@ -1322,7 +1333,9 @@ void mine_update(M910 *mine_moby) { r[1] = random_float_between(frame_time * -0.5f, frame_time * 0.5f) * sc; r[2] = random_float_between(frame_time * 4.0f, tbl[kind]) * sc; *(OvlQuad *)n = *(OvlQuad *)r; - rr = random_float_between(0.0f, kind == MINE_DEBRIS_FIXED_LIFETIME ? 0.5f : 0.25f) * sc; + rr = random_float_between( + 0.0f, kind == MINE_DEBRIS_FIXED_LIFETIME ? 0.5f : 0.25f) * + sc; ang = random_angle_radians(); r[0] = fast_cos(ang) * rr; r[1] = fast_sin(ang) * rr; diff --git a/src/overlays/shared/weapons/morphoray.c b/src/overlays/shared/weapons/morphoray.c index eae0406dc9..758d178ef8 100644 --- a/src/overlays/shared/weapons/morphoray.c +++ b/src/overlays/shared/weapons/morphoray.c @@ -232,44 +232,47 @@ extern float D_L00_001616DC_gp __asm__("D_L00_001616DC") __attrib extern int D_L00_00161818; extern int D_L00_00161824; extern float D_L00_001616F0_gp __asm__("D_L00_001616F0") __attribute__((sda)); -extern int l00_beam_target_bend_after_node_index __asm__("D_L00_001616F4") __attribute__((sda)); -extern float l00_beam_rail_wave_phase_increment __asm__("D_L00_001616F8") __attribute__((sda)); -extern float l00_beam_rail_wave_phase_step_per_node __asm__("D_L00_001616FC") __attribute__((sda)); -extern float D_L00_00161704_gp __asm__("D_L00_00161704") __attribute__((sda)); -extern float l00_beam_ring_start_radius __asm__("D_L00_00161708") __attribute__((sda)); -extern float l00_beam_ring_end_radius __asm__("D_L00_0016170C") __attribute__((sda)); -extern float l00_beam_rail_wave_start_amplitude __asm__("D_L00_0016172C") __attribute__((sda)); -extern float l00_beam_rail_wave_end_amplitude __asm__("D_L00_00161730") __attribute__((sda)); -extern float l00_beam_origin_particle_speed __asm__("D_L00_00161734") __attribute__((sda)); -extern float l00_beam_origin_particle_angular_spread __asm__("D_L00_0016173C") __attribute__((sda)); -extern float l00_beam_origin_particle_basis_offset_length __asm__("D_L00_00161740") __attribute__((sda)); -extern float l00_beam_pulse_travel_speed __asm__("D_L00_00161748") __attribute__((sda)); -extern int l00_beam_pulse_lifetime_frames __asm__("D_L00_0016174C") __attribute__((sda)); -extern int l00_beam_pulse_alpha_fade_remaining_frames_threshold __asm__("D_L00_00161750") __attribute__((sda)); -extern float l00_beam_pulse_end_corner_scale __asm__("D_L00_00161758") __attribute__((sda)); -extern float l00_beam_pulse_start_corner_scale __asm__("D_L00_0016175C") __attribute__((sda)); -extern float l00_beam_pulse_alpha_decrement_per_update __asm__("D_L00_00161768") __attribute__((sda)); -extern signed char D_L00_00161763_macro[] __asm__("D_L00_00161763") MACRO_ADDR; -extern float D_L00_001617CC_macro __asm__("D_L00_001617CC") MACRO_ADDR; -extern int D_L00_00161824_macro __asm__("D_L00_00161824") MACRO_ADDR; -extern float D_0015ED6C_gp __asm__("D_0015ED6C") MACRO_ADDR; -extern int D_L00_001617D8_macro[3] __asm__("D_L00_001617D8") MACRO_ADDR; -extern float D_L00_001618B8_2BE3A8[3] __asm__("D_L00_001617E8") MACRO_ADDR; -extern float D_L00_001617F8_macro[3] __asm__("D_L00_001617F8") MACRO_ADDR; -extern float D_L00_001618D8_2BE3A8[3] __asm__("D_L00_00161808") MACRO_ADDR; -extern int D_L00_001618E8_2BE3A8[3] __asm__("D_L00_00161818") MACRO_ADDR; -extern Vec_2BE3A8 beam_rail_a_points[12] __asm__("D_L00_001DC020"); -extern Vec_2BE3A8 beam_rail_b_points[12] __asm__("D_L00_001DC0E0"); -extern Vec_2BE3A8 beam_pulse_positions[3] __asm__("D_L00_001DD0A0"); -extern Vec_2BE3A8 D_L00_00173F60_2BE3A8 __asm__("D_L00_00173E60"); -extern Tab l00_beam_origin_particle_color_palette __asm__("D_L00_001E9AB0"); -extern u8 D_0013E535 NOT_SDA; -extern float D_L00_00161718 __attribute__((sda)); -extern float D_L00_00161720 __attribute__((sda)); -extern float D_L00_00161724 __attribute__((sda)); -extern int D_L00_00161798 __attribute__((sda)); -extern OvlQuad D_L00_001DC060[][20] NOT_SDA; -extern OvlQuad D_L00_001DC1A0[][20] NOT_SDA; +extern int l00_beam_target_bend_after_node_index __asm__("D_L00_001616F4") __attribute__((sda)); +extern float l00_beam_rail_wave_phase_increment __asm__("D_L00_001616F8") __attribute__((sda)); +extern float l00_beam_rail_wave_phase_step_per_node __asm__("D_L00_001616FC") __attribute__((sda)); +extern float D_L00_00161704_gp __asm__("D_L00_00161704") __attribute__((sda)); +extern float l00_beam_ring_start_radius __asm__("D_L00_00161708") __attribute__((sda)); +extern float l00_beam_ring_end_radius __asm__("D_L00_0016170C") __attribute__((sda)); +extern float l00_beam_rail_wave_start_amplitude __asm__("D_L00_0016172C") __attribute__((sda)); +extern float l00_beam_rail_wave_end_amplitude __asm__("D_L00_00161730") __attribute__((sda)); +extern float l00_beam_origin_particle_speed __asm__("D_L00_00161734") __attribute__((sda)); +extern float l00_beam_origin_particle_angular_spread __asm__("D_L00_0016173C") __attribute__((sda)); +extern float l00_beam_origin_particle_basis_offset_length __asm__("D_L00_00161740") + __attribute__((sda)); +extern float l00_beam_pulse_travel_speed __asm__("D_L00_00161748") __attribute__((sda)); +extern int l00_beam_pulse_lifetime_frames __asm__("D_L00_0016174C") __attribute__((sda)); +extern int l00_beam_pulse_alpha_fade_remaining_frames_threshold __asm__("D_L00_00161750") + __attribute__((sda)); +extern float l00_beam_pulse_end_corner_scale __asm__("D_L00_00161758") __attribute__((sda)); +extern float l00_beam_pulse_start_corner_scale __asm__("D_L00_0016175C") __attribute__((sda)); +extern float l00_beam_pulse_alpha_decrement_per_update __asm__("D_L00_00161768") + __attribute__((sda)); +extern signed char D_L00_00161763_macro[] __asm__("D_L00_00161763") MACRO_ADDR; +extern float D_L00_001617CC_macro __asm__("D_L00_001617CC") MACRO_ADDR; +extern int D_L00_00161824_macro __asm__("D_L00_00161824") MACRO_ADDR; +extern float D_0015ED6C_gp __asm__("D_0015ED6C") MACRO_ADDR; +extern int D_L00_001617D8_macro[3] __asm__("D_L00_001617D8") MACRO_ADDR; +extern float D_L00_001618B8_2BE3A8[3] __asm__("D_L00_001617E8") MACRO_ADDR; +extern float D_L00_001617F8_macro[3] __asm__("D_L00_001617F8") MACRO_ADDR; +extern float D_L00_001618D8_2BE3A8[3] __asm__("D_L00_00161808") MACRO_ADDR; +extern int D_L00_001618E8_2BE3A8[3] __asm__("D_L00_00161818") MACRO_ADDR; +extern Vec_2BE3A8 beam_rail_a_points[12] __asm__("D_L00_001DC020"); +extern Vec_2BE3A8 beam_rail_b_points[12] __asm__("D_L00_001DC0E0"); +extern Vec_2BE3A8 beam_pulse_positions[3] __asm__("D_L00_001DD0A0"); +extern Vec_2BE3A8 D_L00_00173F60_2BE3A8 __asm__("D_L00_00173E60"); +extern Tab l00_beam_origin_particle_color_palette __asm__("D_L00_001E9AB0"); +extern u8 D_0013E535 NOT_SDA; +extern float D_L00_00161718 __attribute__((sda)); +extern float D_L00_00161720 __attribute__((sda)); +extern float D_L00_00161724 __attribute__((sda)); +extern int D_L00_00161798 __attribute__((sda)); +extern OvlQuad D_L00_001DC060[][20] NOT_SDA; +extern OvlQuad D_L00_001DC1A0[][20] NOT_SDA; extern int beam_rail_first_pass_base_vertex_color_gp __asm__("D_L00_00161780") __attribute__((sda)); extern int beam_rail_first_pass_texture_index_gp __asm__("D_L00_001617A4") __attribute__((sda)); extern int beam_rail_second_pass_texture_index_gp __asm__("D_L00_001617A8") __attribute__((sda)); @@ -1808,7 +1811,8 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { func_L00_001FF4B0_2BE3A8(&side, &side, l00_beam_ring_start_radius + - (l00_beam_ring_end_radius - l00_beam_ring_start_radius) * progress); + (l00_beam_ring_end_radius - l00_beam_ring_start_radius) * + progress); { Vec_2BE3A8 ring; Vec_2BE3A8 fwd; @@ -1829,9 +1833,10 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { func_L00_001FF4B0_2BE3A8(&out, &side, 1.0f); func_001F9CA0_2BE3A8(&up, &out, &fwd); wave_width = l00_beam_rail_wave_start_amplitude; - wave_width = wave_width + (l00_beam_rail_wave_end_amplitude - wave_width) * progress; - factor = - normalize_angle(D_L00_001617D0 + l00_beam_rail_wave_phase_step_per_node * func_001FA888_2BE3A8(i)); + wave_width = + wave_width + (l00_beam_rail_wave_end_amplitude - wave_width) * progress; + factor = normalize_angle(D_L00_001617D0 + l00_beam_rail_wave_phase_step_per_node * + func_001FA888_2BE3A8(i)); wave_offset.y = wave_width * func_001F9FA8_2BE3A8(factor); wave_width = wave_width * func_001F9F90_2BE3A8(factor); wave_offset.z = wave_width; @@ -1892,10 +1897,12 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { 0.003f); } func_001F9BF0_2BE3A8(&beam_segment_direction, &beam_nodes[1], &beam_nodes[0]); - func_L00_001FF4B0_2BE3A8( - &beam_segment_direction, &beam_segment_direction, l00_beam_origin_particle_speed * frame_scale); + func_L00_001FF4B0_2BE3A8(&beam_segment_direction, + &beam_segment_direction, + l00_beam_origin_particle_speed * frame_scale); if (random_integer_below(2) == 0) { - func_L00_001FF4B0_2BE3A8(&side, &moby->rot_row1, l00_beam_origin_particle_basis_offset_length); + func_L00_001FF4B0_2BE3A8( + &side, &moby->rot_row1, l00_beam_origin_particle_basis_offset_length); func_001F9BD8_2BE3A8(&point, &beam_nodes[0], &side); { Tab colors; @@ -1905,12 +1912,14 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { colors = l00_beam_origin_particle_color_palette; color = colors.c[random_integer_below(5)]; wave_width = randf_sym(0.0f, l00_beam_origin_particle_angular_spread); - build_look_at_matrix( - &out, &beam_segment_direction, D_0013F5E0_r, randf_sym(0.0f, l00_beam_origin_particle_angular_spread)); + build_look_at_matrix(&out, + &beam_segment_direction, + D_0013F5E0_r, + randf_sym(0.0f, l00_beam_origin_particle_angular_spread)); func_001F9CA0_2BE3A8(&up, &beam_segment_direction, D_0013F5E0_r); build_look_at_matrix(&out, &out, &up, wave_width); - node_index = - func_001FA898_2BE3A8(beam_length * 1.2f / (l00_beam_origin_particle_speed * frame_scale)); + node_index = func_001FA898_2BE3A8(beam_length * 1.2f / + (l00_beam_origin_particle_speed * frame_scale)); if (beam_effect_state->target != 0) { node_index = node_index * 3; } @@ -1967,7 +1976,8 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { continue; } if (D_L00_001617D8_macro[pulse] < l00_beam_pulse_alpha_fade_remaining_frames_threshold) { - D_L00_001618B8_2BE3A8[pulse] = D_L00_001618B8_2BE3A8[pulse] - l00_beam_pulse_alpha_decrement_per_update; + D_L00_001618B8_2BE3A8[pulse] = + D_L00_001618B8_2BE3A8[pulse] - l00_beam_pulse_alpha_decrement_per_update; } dt = l00_beam_pulse_travel_speed * D_0015ED6C_gp; travelled = D_L00_001617F8_macro[pulse] + dt; @@ -1978,7 +1988,8 @@ void update_beam_ring_rail_and_pulse_effects(struct Moby *moby) { ratio = 1.0f; } D_L00_001618D8_2BE3A8[pulse] = - l00_beam_pulse_start_corner_scale + (l00_beam_pulse_end_corner_scale - l00_beam_pulse_start_corner_scale) * ratio; + l00_beam_pulse_start_corner_scale + + (l00_beam_pulse_end_corner_scale - l00_beam_pulse_start_corner_scale) * ratio; if (max_length <= travelled) { func_001F9C30_2BE3A8(&side, &beam_pulse_directions[pulse], dt); func_001F9BD8_2BE3A8(&beam_pulse_positions[pulse], &beam_pulse_positions[pulse], &side); diff --git a/src/overlays/shared/weapons/morphoray_chicken.c b/src/overlays/shared/weapons/morphoray_chicken.c index d20fd35e66..ca61370b02 100644 --- a/src/overlays/shared/weapons/morphoray_chicken.c +++ b/src/overlays/shared/weapons/morphoray_chicken.c @@ -174,20 +174,21 @@ void spawn_explosion(char *m, extern void send_blast_hits(void *, void *, void *, int, int, int, int, int, float, float, float) __asm__("FUN_L00_0025a9f8"); unsigned char *spawn_feather_moby(int unused, void *pos, float *vel) __asm__("FUN_L00_002cbf68"); -extern int move_moby_xy_with_collision_constraints(void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); -extern void FUN_L00_00258278(void *, float *, float, float, float, float); -extern float FUN_L00_00259710(void *); -extern int FUN_L00_002dc9f0(void *, void *); -extern float D_L00_0015F5D0; -extern float D_L00_0015F5D4; -extern int chicken_manipulator_joint __asm__("D_L00_00161850") __attribute__((sda)); -float feather_pitch_deg __asm__("D_L00_00161858") = 7e+01f; -float feather_speed_min __asm__("D_L00_0016185C") = 5.0f; -float feather_speed_max __asm__("D_L00_00161860") = 9.0f; -float feather_height __asm__("D_L00_00161864") = 0.25f; -float feather_radius_min __asm__("D_L00_00161868") = 0; -float feather_radius_max __asm__("D_L00_0016186C") = 0.35f; -extern char D_L00_00177F00[]; +extern int move_moby_xy_with_collision_constraints( + void *, void *, void *, int, float, float, float, float) __asm__("FUN_L00_00258490"); +extern void FUN_L00_00258278(void *, float *, float, float, float, float); +extern float FUN_L00_00259710(void *); +extern int FUN_L00_002dc9f0(void *, void *); +extern float D_L00_0015F5D0; +extern float D_L00_0015F5D4; +extern int chicken_manipulator_joint __asm__("D_L00_00161850") __attribute__((sda)); +float feather_pitch_deg __asm__("D_L00_00161858") = 7e+01f; +float feather_speed_min __asm__("D_L00_0016185C") = 5.0f; +float feather_speed_max __asm__("D_L00_00161860") = 9.0f; +float feather_height __asm__("D_L00_00161864") = 0.25f; +float feather_radius_min __asm__("D_L00_00161868") = 0; +float feather_radius_max __asm__("D_L00_0016186C") = 0.35f; +extern char D_L00_00177F00[]; extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); @@ -319,7 +320,8 @@ struct Moby *spawn_morphoray_chicken(State *source_state) { fill_transfer_words(moby_vars, 0, 0x20); previous_slot_moby = D_L00_001DD100[D_L00_00161854]; if (previous_slot_moby != NULL && previous_slot_moby->oclass == 0x10E && - previous_slot_moby->state != MOBY_STATE_SPAWN_POOL_REMOVAL && previous_slot_moby->state != MOBY_STATE_NON_SPAWN_POOL_REMOVAL) { + previous_slot_moby->state != MOBY_STATE_SPAWN_POOL_REMOVAL && + previous_slot_moby->state != MOBY_STATE_NON_SPAWN_POOL_REMOVAL) { if (previous_slot_moby->state == CHICKEN_STATE_EMIT_FEATHERS) { moby_vars->unk78 = yaw_cosine_scratch; spawned_moby->flags &= ~0x20; diff --git a/src/overlays/shared/weapons/suckcannon.c b/src/overlays/shared/weapons/suckcannon.c index 992d742971..579a8eb411 100644 --- a/src/overlays/shared/weapons/suckcannon.c +++ b/src/overlays/shared/weapons/suckcannon.c @@ -1436,7 +1436,8 @@ void suckcannon_update(SuckMoby *suck_cannon_moby) { 5); cannon = suck_cannon_moby->data; slot_released = ((SuckHero *)&hero)->slot_state == 3; - if ((u8)suck_cannon_moby->state != SUCKCANNON_STATE_SUCTION_ACTIVE && (u8)suck_cannon_moby->state != SUCKCANNON_STATE_INITIALIZE) + if ((u8)suck_cannon_moby->state != SUCKCANNON_STATE_SUCTION_ACTIVE && + (u8)suck_cannon_moby->state != SUCKCANNON_STATE_INITIALIZE) suck_beam_queue_draw((int)suck_cannon_moby); refresh_suck_cannon_slots(); switch ((u8)suck_cannon_moby->state) { @@ -2845,7 +2846,8 @@ void suck_beam_build(char *cannon_moby, char *suction_origin) { D_L00_00161B84 = 1.7f; suck_beam_reset_pending = 0; hero_state = hero.state.current; - if ((hero_state == HERO_STATE_LOOK_RELEASE_WAIT || hero_state == HERO_STATE_LOOK) && (hero.moby->flags & 1)) { + if ((hero_state == HERO_STATE_LOOK_RELEASE_WAIT || hero_state == HERO_STATE_LOOK) && + (hero.moby->flags & 1)) { qcopy((char *)beam_initialization_vectors, D_L00_00166FD0); qcopy((char *)beam_initialization_vectors + 0x10, D_L00_00166FD0 + 0x10); qcopy((char *)beam_initialization_vectors + 0x20, D_L00_00166FD0 + 0x20); @@ -2957,8 +2959,8 @@ void suck_beam_update(void *moby, void *position) { fast_vec_add(&start, &start, &step); transform_vector_by_basis(&end, &(*(V41 *)D_L00_00161B70), orientation); fast_vec_add(&end, &end, &step); - beam_step_blend_fraction = - (float)l00_suck_beam_step_blend_elapsed_frames / convert_integer_to_float(scale_game_frames(60)); + beam_step_blend_fraction = (float)l00_suck_beam_step_blend_elapsed_frames / + convert_integer_to_float(scale_game_frames(60)); l00_suck_beam_step_blend_elapsed_frames++; step.f.x = start.f.x + (end.f.x - start.f.x) * beam_step_blend_fraction; step.f.y = start.f.y + (end.f.y - start.f.y) * beam_step_blend_fraction; @@ -3108,7 +3110,8 @@ void suck_beam_update(void *moby, void *position) { } if (D_L00_001E4C80_lui[i].p) { fast_vec_sub(&tmp_a, - l00_suck_beam_previous_segment_positions + D_L00_001E4C80_lui[i].idx * 16, + l00_suck_beam_previous_segment_positions + + D_L00_001E4C80_lui[i].idx * 16, D_L00_001E5F40 + D_L00_001E4C80_lui[i].idx * 16); length = fast_vec_length(&tmp_a); D_L00_001E4C80_lui[i].f += D_L00_001E4C80_lui[i].speed; @@ -3121,7 +3124,8 @@ void suck_beam_update(void *moby, void *position) { } else { D_L00_001E4C80_lui[i].f -= length; fast_vec_sub(&tmp_a, - l00_suck_beam_previous_segment_positions + D_L00_001E4C80_lui[i].idx * 16, + l00_suck_beam_previous_segment_positions + + D_L00_001E4C80_lui[i].idx * 16, D_L00_001E5F40 + D_L00_001E4C80_lui[i].idx * 16); length = fast_vec_length(&tmp_a); } @@ -3159,7 +3163,8 @@ void suck_beam_update(void *moby, void *position) { fast_vec_sub(&tmp_c, (char *)((V41 *)D_L00_001E5EE0) + D_L00_001E4C80_lui[i].idx * 320 + j * 16, - l00_suck_beam_previous_segment_positions + D_L00_001E4C80_lui[i].idx * 16); + l00_suck_beam_previous_segment_positions + + D_L00_001E4C80_lui[i].idx * 16); interpolate_vector(&motion, &tmp_b, &tmp_c, amount); j = (j + 19) % 20; fast_vec_sub(&tmp_d, @@ -3169,7 +3174,8 @@ void suck_beam_update(void *moby, void *position) { fast_vec_sub(&tmp_e, (char *)((V41 *)D_L00_001E5EE0) + D_L00_001E4C80_lui[i].idx * 320 + j * 16, - l00_suck_beam_previous_segment_positions + D_L00_001E4C80_lui[i].idx * 16); + l00_suck_beam_previous_segment_positions + + D_L00_001E4C80_lui[i].idx * 16); interpolate_vector(&interp, &tmp_d, &tmp_e, amount); interpolate_vector(&motion, &motion, &interp, D_L00_001E4C80_lui[i].phase); D_L00_001E4C80_lui[i].phase += D_L00_001E4C80_lui[i].phase_step; diff --git a/src/overlays/shared/weapons/swingshot_hook.c b/src/overlays/shared/weapons/swingshot_hook.c index ce04afa262..50660338ad 100644 --- a/src/overlays/shared/weapons/swingshot_hook.c +++ b/src/overlays/shared/weapons/swingshot_hook.c @@ -69,7 +69,8 @@ void swingshot_hook_update(unsigned char *hook_moby) { if (hook_vars == 0) return; owner_moby = hook_vars[0]; - if (owner_moby == 0 || owner_moby->oclass != 0xD0 || owner_moby->state == MOBY_STATE_MARKED_FOR_REMOVAL || + if (owner_moby == 0 || owner_moby->oclass != 0xD0 || + owner_moby->state == MOBY_STATE_MARKED_FOR_REMOVAL || owner_moby->state == MOBY_STATE_REMOVAL_PENDING || *(unsigned char **)(((unsigned char *)owner_moby->pvars) + 0x14) != hook_moby) { goto kill; diff --git a/src/overlays/shared/weapons/tesla_claw.c b/src/overlays/shared/weapons/tesla_claw.c index f4d322ee9f..d7e47e4517 100644 --- a/src/overlays/shared/weapons/tesla_claw.c +++ b/src/overlays/shared/weapons/tesla_claw.c @@ -515,8 +515,10 @@ void tesla_claw_update(struct Moby *tesla_claw_moby) { if ((unsigned int)hero.state.control_mode < 2 || hero.state.control_mode == 9) help_request(0x4E30, 0x81); } - if ((controller_state.held & hero.items[0].button_mask) && tesla_claw_moby->state != TESLA_CLAW_STATE_FINISHED && - tesla_claw_moby->state != TESLA_CLAW_STATE_INITIALIZE && !hero.item_use_locked && hero.state.current != 0x72) { + if ((controller_state.held & hero.items[0].button_mask) && + tesla_claw_moby->state != TESLA_CLAW_STATE_FINISHED && + tesla_claw_moby->state != TESLA_CLAW_STATE_INITIALIZE && !hero.item_use_locked && + hero.state.current != 0x72) { if (tesla_claw_vars->timer == 0) { if (ready > 0) { if (fast_dec_timer_s16(&tesla_claw_vars->tick)) { @@ -692,7 +694,8 @@ void tesla_claw_update(struct Moby *tesla_claw_moby) { firing_start_stats->uses++; if (scale_game_frames(D_0015EEA4) / 600 > firing_start_stats->longest) firing_start_stats->longest = scale_game_frames(D_0015EEA4) / 600; - firing_start_stats->levels = (firing_start_stats->levels | (1 << current_level_index)) | 0x80000000; + firing_start_stats->levels = + (firing_start_stats->levels | (1 << current_level_index)) | 0x80000000; start_equipped_item_animation(); tesla_claw_moby->state = TESLA_CLAW_STATE_FIRING; } else { diff --git a/src/overlays/shared/weapons/turret_rocket.c b/src/overlays/shared/weapons/turret_rocket.c index 2751948213..0d01953dec 100644 --- a/src/overlays/shared/weapons/turret_rocket.c +++ b/src/overlays/shared/weapons/turret_rocket.c @@ -151,13 +151,16 @@ char *spawn_turret_rocket(int firing_moby, float *position, float *rotation, int 1, 20000.0f); particle_frame_count = truncate_float_to_s32(FUN_L08_00211a20(random_float_between( - (float)l08_turret_rocket_spark_first_frame_count_base, (float)l08_turret_rocket_spark_first_frame_count_base * 1.2f))); + (float)l08_turret_rocket_spark_first_frame_count_base, + (float)l08_turret_rocket_spark_first_frame_count_base * 1.2f))); particle_second_frame_count = truncate_float_to_s32(FUN_L08_00211a20(random_float_between( - (float)l08_turret_rocket_spark_second_frame_count_base, (float)l08_turret_rocket_spark_second_frame_count_base * 1.2f))); + (float)l08_turret_rocket_spark_second_frame_count_base, + (float)l08_turret_rocket_spark_second_frame_count_base * 1.2f))); particle_third_frame_count = truncate_float_to_s32(FUN_L08_00211a20(random_float_between( - (float)l08_turret_rocket_spark_third_frame_count_base, (float)l08_turret_rocket_spark_third_frame_count_base * 1.5f))); + (float)l08_turret_rocket_spark_third_frame_count_base, + (float)l08_turret_rocket_spark_third_frame_count_base * 1.5f))); spawn_spark(&MOBY(moby)->pos, velocity_ptr, offset_ptr, @@ -221,11 +224,14 @@ void turret_rocket_update(char *moby) { offset[3] = homing_projectile_trail_secondary_motion_w_gp; i++; particle_frame_count = truncate_float_to_s32(scale_game_frames_002e8210( - random_float_between((float)l08_turret_rocket_spark_first_frame_count_base, (float)l08_turret_rocket_spark_first_frame_count_base * 1.2f))); + random_float_between((float)l08_turret_rocket_spark_first_frame_count_base, + (float)l08_turret_rocket_spark_first_frame_count_base * 1.2f))); particle_second_frame_count = truncate_float_to_s32(scale_game_frames_002e8210( - random_float_between((float)l08_turret_rocket_spark_second_frame_count_base, (float)l08_turret_rocket_spark_second_frame_count_base * 1.2f))); + random_float_between((float)l08_turret_rocket_spark_second_frame_count_base, + (float)l08_turret_rocket_spark_second_frame_count_base * 1.2f))); particle_third_frame_count = truncate_float_to_s32(scale_game_frames_002e8210( - random_float_between((float)l08_turret_rocket_spark_third_frame_count_base, (float)l08_turret_rocket_spark_third_frame_count_base * 1.5f))); + random_float_between((float)l08_turret_rocket_spark_third_frame_count_base, + (float)l08_turret_rocket_spark_third_frame_count_base * 1.5f))); spawn_spark(position, velocity, offset, diff --git a/src/overlays/shared/weapons/visibomb_missile.c b/src/overlays/shared/weapons/visibomb_missile.c index 970f6a5269..bbc3d846cf 100644 --- a/src/overlays/shared/weapons/visibomb_missile.c +++ b/src/overlays/shared/weapons/visibomb_missile.c @@ -934,15 +934,17 @@ void visibomb_missile_update(struct Moby *missile_moby) { { struct Moby *skip = missile_moby; build_axis_rotation_quaternion(&missile_vars->f24->pos, - 1, - -(missile_vars->f1C * 0.5f + absolute_float(missile_vars->f18 / 3.0f) + - (missile_vars->f18 - missile_moby->rot.x) * 1.1f) * - 0.7f); + 1, + -(missile_vars->f1C * 0.5f + + absolute_float(missile_vars->f18 / 3.0f) + + (missile_vars->f18 - missile_moby->rot.x) * 1.1f) * + 0.7f); build_axis_rotation_quaternion(&missile_vars->f28->pos, - 1, - -(missile_vars->f1C * 0.5f + absolute_float(missile_vars->f18 / 3.0f) - - (missile_vars->f18 - missile_moby->rot.x) * 1.1f) * - 0.7f); + 1, + -(missile_vars->f1C * 0.5f + + absolute_float(missile_vars->f18 / 3.0f) - + (missile_vars->f18 - missile_moby->rot.x) * 1.1f) * + 0.7f); ev.moby = missile_moby; ev.flags = 0x830000; ev.f1C = 6.0f; diff --git a/src/overlays/shared/weapons/wrench.c b/src/overlays/shared/weapons/wrench.c index e45c96c012..c7b6adabf2 100644 --- a/src/overlays/shared/weapons/wrench.c +++ b/src/overlays/shared/weapons/wrench.c @@ -690,8 +690,11 @@ void wrench_update(WrenchMoby *wrench_moby) { FUN_L00_002a7c70_c((char *)wrench_moby); { int current_state = wrench_hero()->state; - if (current_state != HERO_STATE_WRENCH_COMBO && current_state != HERO_STATE_WAIT_FOR_ANIMATION_THEN_IDLE && current_state != HERO_STATE_GRIND_ATTACK && - current_state != HERO_STATE_ATTACK_RECORD_FRAME_EXIT_WAIT && current_state != HERO_STATE_WRENCH_SLAM) { + if (current_state != HERO_STATE_WRENCH_COMBO && + current_state != HERO_STATE_WAIT_FOR_ANIMATION_THEN_IDLE && + current_state != HERO_STATE_GRIND_ATTACK && + current_state != HERO_STATE_ATTACK_RECORD_FRAME_EXIT_WAIT && + current_state != HERO_STATE_WRENCH_SLAM) { int current = wrench_moby->current_animation; if ((unsigned int)current >= 3 && wrench_moby->current_animation < 6) blend_moby_animation(wrench_moby, 1, 0, scale_game_frames(4)); diff --git a/src/overlays/shared/world/load_level_gameplay.c b/src/overlays/shared/world/load_level_gameplay.c index f31fe86fab..b00b56f2c6 100644 --- a/src/overlays/shared/world/load_level_gameplay.c +++ b/src/overlays/shared/world/load_level_gameplay.c @@ -93,10 +93,13 @@ void print_moby_class_sizes(int *moby_class_record_cursor, int moby_class_record entries[i].size = 0; } else { if (moby_class_record_cursor[8] != 0) { - entries[i].size = convert_integer_to_float(moby_class_record_cursor[8] - moby_class_record_cursor[0]) * 0.0009765625f; + entries[i].size = convert_integer_to_float(moby_class_record_cursor[8] - + moby_class_record_cursor[0]) * + 0.0009765625f; } else { - entries[i].size = - convert_integer_to_float(moby_class_record_cursor[0x10] - moby_class_record_cursor[0]) * 0.0009765625f; + entries[i].size = convert_integer_to_float(moby_class_record_cursor[0x10] - + moby_class_record_cursor[0]) * + 0.0009765625f; } entries[i + 1].class_id = -1.0f; entries[i + 1].size = 0; diff --git a/src/rendering/debug/draw_debug_profiler.c b/src/rendering/debug/draw_debug_profiler.c index 7e25cba35b..4ece0321f5 100644 --- a/src/rendering/debug/draw_debug_profiler.c +++ b/src/rendering/debug/draw_debug_profiler.c @@ -181,7 +181,8 @@ void draw_debug_profiler(void) { } append_dma_tag(0x02080000); setup_gif_paging(0); - if ((draw_enable_mask & 0x20) && draw_config.unk30 != 0 && font_state != FONT_STATE_EFFECTS_DATA) { + if ((draw_enable_mask & 0x20) && draw_config.unk30 != 0 && + font_state != FONT_STATE_EFFECTS_DATA) { vu1_add_data_ref(D_0010FAA0, D_0010FA90[0]); font_state = FONT_STATE_EFFECTS_DATA; } diff --git a/src/rendering/frame/render_level_frame.c b/src/rendering/frame/render_level_frame.c index 6dd558318a..7979041733 100644 --- a/src/rendering/frame/render_level_frame.c +++ b/src/rendering/frame/render_level_frame.c @@ -90,7 +90,8 @@ void render_level_frame(void) { if ((current_level_index != 0) && ((current_level_index != 1) || (level_available[3] != 0))) { render_environment_mapped_object(D_0018CC98[0]); } - if ((memory_card_state.state >= MEMCARD_REQUEST_FORMAT) || (memory_card_state.pending_state >= MEMCARD_QUERY_INFO)) { + if ((memory_card_state.state >= MEMCARD_REQUEST_FORMAT) || + (memory_card_state.pending_state >= MEMCARD_QUERY_INFO)) { vu1_add_g_sregister(0x47, 0x3004B); quad_extent = 272.0f; texture = get_effect_texture(2); diff --git a/src/rendering/mobys/render_environment_mapped_object.c b/src/rendering/mobys/render_environment_mapped_object.c index 2943343fca..bc33d40c4e 100644 --- a/src/rendering/mobys/render_environment_mapped_object.c +++ b/src/rendering/mobys/render_environment_mapped_object.c @@ -103,7 +103,8 @@ void render_environment_mapped_object(EnvironmentMappedObject *mesh_object) { if (game_mode == 6 && ship_substate[0] == 4) { mapping_enabled = 0; } - if (mapping_enabled != 0 || environment_mapping_uv_refresh_state == ENVIRONMENT_MAPPING_UV_REFRESH_PENDING) { + if (mapping_enabled != 0 || + environment_mapping_uv_refresh_state == ENVIRONMENT_MAPPING_UV_REFRESH_PENDING) { environment_mapping_was_active_gp = 1; fast_dec_timer(&D_001604AC); transition_fraction = convert_integer_to_float(D_001604AC) / @@ -123,7 +124,8 @@ void render_environment_mapped_object(EnvironmentMappedObject *mesh_object) { fast_vec_normalize(reflection, reflection, 1.0f); reflection[2] += 1.0f; sphere_denominator = square_root(reflection[2] * 2.0f) * 2.0f; - if (environment_mapping_uv_refresh_state == ENVIRONMENT_MAPPING_UV_REFRESH_PENDING || D_001604AC == 0) { + if (environment_mapping_uv_refresh_state == ENVIRONMENT_MAPPING_UV_REFRESH_PENDING || + D_001604AC == 0) { environment_mapping_vertex_uvs[element_index][0] = reflection[0] / sphere_denominator + 0.5f; environment_mapping_vertex_uvs[element_index][1] = diff --git a/src/sdk/mpeg/picture/_pictureData0.c b/src/sdk/mpeg/picture/_pictureData0.c index 3dbfe80d47..5cd7397f5d 100644 --- a/src/sdk/mpeg/picture/_pictureData0.c +++ b/src/sdk/mpeg/picture/_pictureData0.c @@ -38,7 +38,8 @@ s32 _pictureData0(MpegDec *decoder) { } do { decode_status = _slice0(decoder, mbs); - } while (decode_status == DECODE_STATUS_SLICE_DECODE_ERROR || decode_status == DECODE_STATUS_SLICE_LOOKAHEAD_STOP); + } while (decode_status == DECODE_STATUS_SLICE_DECODE_ERROR || + decode_status == DECODE_STATUS_SLICE_LOOKAHEAD_STOP); _waitIpuIdle(decoder); if (_waitBdecOut(decoder) == 0) { decode_status = DECODE_STATUS_ABORT_PICTURE; @@ -48,7 +49,8 @@ s32 _pictureData0(MpegDec *decoder) { if (decode_status == DECODE_STATUS_SUCCESS) { _doMC(decoder, decoder->unk810 == 0); } - if (decode_status == DECODE_STATUS_SLICE_DECODE_ERROR || decode_status == DECODE_STATUS_ABORT_PICTURE) { + if (decode_status == DECODE_STATUS_SLICE_DECODE_ERROR || + decode_status == DECODE_STATUS_ABORT_PICTURE) { _Error(decoder, skip_to_next_picture_error_message); } return decode_status == DECODE_STATUS_SUCCESS; diff --git a/src/sdk/mpeg/ref_images/_updateRefImage.c b/src/sdk/mpeg/ref_images/_updateRefImage.c index b9227a744d..679a6546a8 100644 --- a/src/sdk/mpeg/ref_images/_updateRefImage.c +++ b/src/sdk/mpeg/ref_images/_updateRefImage.c @@ -139,13 +139,15 @@ s32 UpdateMpegReferenceImages(struct MpegReferenceState *state, s32 force_reorde state->selected_top_field = state->previous_top_field; state->selected_bottom_field = state->previous_bottom_field; if (state->picture_structure == 3) { - if (state->coding_type != MPEG_PICTURE_CODING_TYPE_P || state->current_frame->status == 1) { + if (state->coding_type != MPEG_PICTURE_CODING_TYPE_P || + state->current_frame->status == 1) { references_ready = 1; } } else { predicted_field = (state->picture_structure == 1) ? state->selected_bottom_field : state->selected_top_field; - if (state->coding_type != MPEG_PICTURE_CODING_TYPE_P || (force_reorder != 0 && predicted_field->status == MPEG_REFERENCE_STATUS_READY) || + if (state->coding_type != MPEG_PICTURE_CODING_TYPE_P || + (force_reorder != 0 && predicted_field->status == MPEG_REFERENCE_STATUS_READY) || (state->current_top_field->status == 1 && state->current_bottom_field->status == 1)) { references_ready = 1; diff --git a/src/sdk/mpeg/ref_images/disprefimagefield.c b/src/sdk/mpeg/ref_images/disprefimagefield.c index 44d188fb88..3809d893a3 100644 --- a/src/sdk/mpeg/ref_images/disprefimagefield.c +++ b/src/sdk/mpeg/ref_images/disprefimagefield.c @@ -129,7 +129,8 @@ void PrepareMpegPictureFieldTransfers(struct MpegFieldTransferState *state, state->horizontal_offset1 = secondary->horizontal_offset1; state->vertical_offset0 = primary->vertical_offset0; state->vertical_offset1 = secondary->vertical_offset1; - if (_isOutSizeOK(state, first_field_ref_image) && first_field_ref_image->status == MPEG_PICTURE_STATUS_OUTPUT_READY && + if (_isOutSizeOK(state, first_field_ref_image) && + first_field_ref_image->status == MPEG_PICTURE_STATUS_OUTPUT_READY && second_field_ref_image->status == MPEG_PICTURE_STATUS_OUTPUT_READY) { first_field_ref_image->macroblock_height *= 2; if (state->decoder_initialized) diff --git a/src/ui/menus/item_preview/update_menu_preview_class_pose.c b/src/ui/menus/item_preview/update_menu_preview_class_pose.c index be599f3209..f1edd7f7bd 100644 --- a/src/ui/menus/item_preview/update_menu_preview_class_pose.c +++ b/src/ui/menus/item_preview/update_menu_preview_class_pose.c @@ -33,7 +33,10 @@ extern void attach_manipulator(int, int, void *) __asm__("FUN_0020cb void update_menu_preview_class_pose(void *preview) __asm__("FUN_00224b70"); void update_menu_preview_class_pose(void *preview) { - enum { PREVIEW_BINDING_STATE_RESET = 0 } ;PauseMoby *moby = preview; + enum { + PREVIEW_BINDING_STATE_RESET = 0 + }; + PauseMoby *moby = preview; struct Moby *anim = preview; f32 transform[16]; s32 source_moby_address = (s32)((struct MenuScreen *)*moby->vars)->data.preview.moby; diff --git a/src/ui/menus/save_data/draw_checking_memory_card_data_menu.c b/src/ui/menus/save_data/draw_checking_memory_card_data_menu.c index 8d0af3a6ad..705eefdb1c 100644 --- a/src/ui/menus/save_data/draw_checking_memory_card_data_menu.c +++ b/src/ui/menus/save_data/draw_checking_memory_card_data_menu.c @@ -44,7 +44,8 @@ s32 draw_checking_memory_card_data_menu(struct MenuScreen *menu) { if (memory_card_state.card[0].type != 2) { goto done; } - if (memory_card_state.state < MEMCARD_REQUEST_FORMAT && memory_card_state.pending_state < MEMCARD_QUERY_INFO) { + if (memory_card_state.state < MEMCARD_REQUEST_FORMAT && + memory_card_state.pending_state < MEMCARD_QUERY_INFO) { goto done; } setup_gif_paging(0); diff --git a/src/ui/menus/save_data/draw_save_slot_list.c b/src/ui/menus/save_data/draw_save_slot_list.c index d696e759ce..dc3812ff0c 100644 --- a/src/ui/menus/save_data/draw_save_slot_list.c +++ b/src/ui/menus/save_data/draw_save_slot_list.c @@ -54,15 +54,16 @@ s32 draw_save_slot_list(SaveMenu *menu) { inner_right = width - 3; inner_top = y - 1; inner_bottom = y + 0x31; - if (memory_card_state.state < MEMCARD_REQUEST_FORMAT && memory_card_state.pending_state < MEMCARD_QUERY_INFO && - menu->selected_slot == i) { + if (memory_card_state.state < MEMCARD_REQUEST_FORMAT && + memory_card_state.pending_state < MEMCARD_QUERY_INFO && menu->selected_slot == i) { append_screen_rect_packet(0, highlight_top, width, highlight_bottom, 0x8020FFFF, 0); append_screen_rect_packet( 3, inner_top, inner_right, inner_bottom, panel_clear_color, 0); } append_screen_rect_packet(3, inner_top, inner_right, inner_bottom, 0x80303030, 0); slot = &memory_card_state.card[0].entries[i]; - if (memory_card_state.state >= MEMCARD_REQUEST_FORMAT || memory_card_state.pending_state >= MEMCARD_QUERY_INFO || + if (memory_card_state.state >= MEMCARD_REQUEST_FORMAT || + memory_card_state.pending_state >= MEMCARD_QUERY_INFO || memory_card_state.card[0].type != 2) { y += 0x30; } else { diff --git a/src/ui/menus/save_data/loading_data_menu.c b/src/ui/menus/save_data/loading_data_menu.c index 20ba8e1ba3..7d012dc169 100644 --- a/src/ui/menus/save_data/loading_data_menu.c +++ b/src/ui/menus/save_data/loading_data_menu.c @@ -44,7 +44,8 @@ s32 loading_data_menu(struct LoadMenuDescriptor *menu) { s32 scaled_volume_70; previous_save_slot = menu->selected_save_slot; if (menu_system.card_op_pending != 0) { - if ((memory_card_state.state < MEMCARD_REQUEST_FORMAT) && (memory_card_state.pending_state < MEMCARD_QUERY_INFO)) { + if ((memory_card_state.state < MEMCARD_REQUEST_FORMAT) && + (memory_card_state.pending_state < MEMCARD_QUERY_INFO)) { menu_system.card_op_pending = 0; if (memory_card_state.err != 0) { mode_freeze_flags |= 0x100; @@ -84,7 +85,8 @@ s32 loading_data_menu(struct LoadMenuDescriptor *menu) { menu_system.next = menu_system.current->back; return 0; } - if (((memory_card_state.state < MEMCARD_REQUEST_FORMAT) && (memory_card_state.pending_state < MEMCARD_QUERY_INFO)) && + if (((memory_card_state.state < MEMCARD_REQUEST_FORMAT) && + (memory_card_state.pending_state < MEMCARD_QUERY_INFO)) && (memory_card_state.card[0].type == 2)) { if (menu->flags & 1) { buttons = controller_state.raw_pressed; diff --git a/src/ui/menus/save_data/save_card_state_create_save_pending.c b/src/ui/menus/save_data/save_card_state_create_save_pending.c index 16e9907eac..b9d391cb1b 100644 --- a/src/ui/menus/save_data/save_card_state_create_save_pending.c +++ b/src/ui/menus/save_data/save_card_state_create_save_pending.c @@ -6,7 +6,8 @@ void save_card_state_create_save_pending(void) __asm__("FUN_00208d20"); void save_card_state_create_save_pending(void) { struct MemoryCardState *card_state = &memory_card_state; - if (card_state->state == MEMCARD_DISPATCH_PENDING_OPERATION && card_state->pending_state < MEMCARD_QUERY_INFO) { + if (card_state->state == MEMCARD_DISPATCH_PENDING_OPERATION && + card_state->pending_state < MEMCARD_QUERY_INFO) { card_state->pending_state = MEMCARD_BEGIN_CREATE_SAVE_DIRECTORY; card_state->pending_card = 0; mode_freeze_state = 0xF; diff --git a/src/ui/menus/save_data/save_card_state_saving.c b/src/ui/menus/save_data/save_card_state_saving.c index 5488bb7931..cb88570e89 100644 --- a/src/ui/menus/save_data/save_card_state_saving.c +++ b/src/ui/menus/save_data/save_card_state_saving.c @@ -16,7 +16,8 @@ void save_card_state_saving(void) __asm__("FUN_00208f28"); void save_card_state_saving(void) { s32 flags; - if ((memory_card_state.state < MEMCARD_REQUEST_FORMAT) && (memory_card_state.pending_state < MEMCARD_QUERY_INFO)) { + if ((memory_card_state.state < MEMCARD_REQUEST_FORMAT) && + (memory_card_state.pending_state < MEMCARD_QUERY_INFO)) { if (memory_card_state.err != 0) { mode_freeze_init(3, 0); mode_freeze_state = 0x15; diff --git a/src/ui/menus/stream_image/update_menu_stream_image.c b/src/ui/menus/stream_image/update_menu_stream_image.c index e332201a7b..2cf7c01045 100644 --- a/src/ui/menus/stream_image/update_menu_stream_image.c +++ b/src/ui/menus/stream_image/update_menu_stream_image.c @@ -56,7 +56,8 @@ s32 update_menu_stream_image(struct MenuScreen *stream) { if (selected_entry_index >= 5) { selected_entry_index = 4; } - if (memory_card_state.state < MEMCARD_REQUEST_FORMAT && memory_card_state.pending_state < MEMCARD_QUERY_INFO) { + if (memory_card_state.state < MEMCARD_REQUEST_FORMAT && + memory_card_state.pending_state < MEMCARD_QUERY_INFO) { if (stream->data.stream.state == -1) { stream->data.stream.state = 0; } diff --git a/src/ui/menus/widgets/draw_menu_item_grid.c b/src/ui/menus/widgets/draw_menu_item_grid.c index 178fad5db6..392e14ba0f 100644 --- a/src/ui/menus/widgets/draw_menu_item_grid.c +++ b/src/ui/menus/widgets/draw_menu_item_grid.c @@ -110,7 +110,8 @@ s32 draw_menu_item_grid(struct MenuScreen *grid) { append_screen_rect_packet( left - 0x10, top - 0x10, right + 0x10, bottom + 0x10, panel_clear_color, 1); } - if (cell->kind == MENU_GRID_CELL_EQUIPPABLE_ITEM ? item_available[cell->id] : alternate_item_available[cell->id]) { + if (cell->kind == MENU_GRID_CELL_EQUIPPABLE_ITEM ? item_available[cell->id] + : alternate_item_available[cell->id]) { frame_offset = 0; if ((u16)cell->kind == MENU_GRID_CELL_EQUIPPABLE_ITEM) { id = cell->id; diff --git a/src/ui/menus/widgets/draw_menu_selection_text.c b/src/ui/menus/widgets/draw_menu_selection_text.c index 760b652681..1c5a160217 100644 --- a/src/ui/menus/widgets/draw_menu_selection_text.c +++ b/src/ui/menus/widgets/draw_menu_selection_text.c @@ -27,7 +27,8 @@ s32 draw_menu_selection_text(struct MenuScreen *menu) { *((s32 *)((((u8 *)card_state) - (-(menu_system.current->focus->data.save.slot * 0x1C))) + 0x20)); setup_gif_paging(0); - if (((card_state->state < MEMCARD_REQUEST_FORMAT) && (card_state->pending_state < MEMCARD_QUERY_INFO)) && + if (((card_state->state < MEMCARD_REQUEST_FORMAT) && + (card_state->pending_state < MEMCARD_QUERY_INFO)) && (card_state->card[0].type == 2)) { if (entry_index == (-1)) { height = menu->height; diff --git a/src/ui/menus/widgets/enter_menu_help_text.c b/src/ui/menus/widgets/enter_menu_help_text.c index e74884dfd8..93678f6d4b 100644 --- a/src/ui/menus/widgets/enter_menu_help_text.c +++ b/src/ui/menus/widgets/enter_menu_help_text.c @@ -17,7 +17,10 @@ extern s32 start_audio_stream_read(s32, s32, s32) __asm__("FUN_00216788"); s32 enter_menu_help_text(struct MenuScreen *menu) __asm__("FUN_0021d1f8"); s32 enter_menu_help_text(struct MenuScreen *menu) { - enum { CD_READ_STATE_IDLE = 0 } ;s32 i; + enum { + CD_READ_STATE_IDLE = 0 + }; + s32 i; struct MenuSystem *menu_system_state; initialize_menu_stream_buffers(1); diff --git a/src/ui/text/link_localized_display_text.c b/src/ui/text/link_localized_display_text.c index da3e9ef5f4..58464f492e 100644 --- a/src/ui/text/link_localized_display_text.c +++ b/src/ui/text/link_localized_display_text.c @@ -18,7 +18,10 @@ void link_localized_display_text(void) __asm__("FUN_001fdd58"); void link_localized_display_text(void) { /* win is unsigned (lhu) but w/h are signed: the narrowing gives the sll 16 / sra 17 shift-by-one retail has instead of a plain sra. */ - enum { HELP_STATE_DISPLAY_START_DELAY = 1 } ;u16 win[16]; + enum { + HELP_STATE_DISPLAY_START_DELAY = 1 + }; + u16 win[16]; HelpState *box; void *text; s32 screenY; From 806935c989f41d9dd6ba6e7909e7c1a464868eb2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 12:00:47 +0000 Subject: [PATCH 1340/1502] decomp: reuse upstream Morph-O-Ray state names after rebase --- src/overlays/l14/mobys/morphoray_pickup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l14/mobys/morphoray_pickup.c b/src/overlays/l14/mobys/morphoray_pickup.c index 9c0434fec3..bcf3728cca 100644 --- a/src/overlays/l14/mobys/morphoray_pickup.c +++ b/src/overlays/l14/mobys/morphoray_pickup.c @@ -70,7 +70,7 @@ void morphoray_pickup_update(struct Moby *moby) { moby->rot.y = -1.5707964f; moby->pos.z = D_L14_00174568[0] + morphoray_ground_height_offset_gp; qcopy(morphoray_pvars, moby_bytes + 0x10); - moby->state = MORPHORAY_WAIT_FOR_HERO; + moby->state = MORPHORAY_PICKUP_WAIT_FOR_HERO; break; case MORPHORAY_PICKUP_WAIT_FOR_HERO: *(f32 *)(moby_bytes + 0x48) = @@ -91,7 +91,7 @@ void morphoray_pickup_update(struct Moby *moby) { *(s32 *)(morphoray_pvars + 0x18) = 0; grant_inventory_item(0x15, 1); start_scene(6); - moby->state = MORPHORAY_WAIT_TO_REMOVE; + moby->state = MORPHORAY_PICKUP_WAIT_TO_REMOVE; break; case MORPHORAY_PICKUP_WAIT_TO_REMOVE: if (D_L14_0015F5C4 != state) { From a58551a0e33a01083ec71d73d7dadfca08be5cf9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 12:25:31 +0000 Subject: [PATCH 1341/1502] decomp: retain named global declarations after upstream rebase --- src/overlays/l14/mobys/blarg_heavy_interceptor.c | 6 ++++-- src/overlays/l18/mobys/drek_fight_missile.c | 3 ++- src/overlays/shared/enemies/large_amoeboid.c | 6 ++++-- src/overlays/shared/enemies/scoutbot.c | 8 ++++---- src/overlays/shared/weapons/turret_rocket.c | 9 ++++++--- src/ui/menus/system/setup_menu_display_text.c | 2 +- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/overlays/l14/mobys/blarg_heavy_interceptor.c b/src/overlays/l14/mobys/blarg_heavy_interceptor.c index a6f5e9b54e..792705c0a2 100644 --- a/src/overlays/l14/mobys/blarg_heavy_interceptor.c +++ b/src/overlays/l14/mobys/blarg_heavy_interceptor.c @@ -172,9 +172,11 @@ extern char D_L14_0015F580[] MACRO_ADDR; #include "rnc/overlay/l14/mobys/blarg_heavy_interceptor_data/blarg_heavy_interceptor_update.h" -extern f32 D_L14_001613A0_gp __asm__("D_L14_001613A0") __attribute__((sda)); +extern f32 l14_blarg_heavy_interceptor_path_easing_error_gain __asm__("D_L14_001613A0") + __attribute__((sda)); -extern f32 D_L14_001613A4_gp __asm__("D_L14_001613A4") __attribute__((sda)); +extern f32 l14_blarg_heavy_interceptor_path_easing_damping_coefficient __asm__("D_L14_001613A4") + __attribute__((sda)); extern Vec4 D_L14_00174560; diff --git a/src/overlays/l18/mobys/drek_fight_missile.c b/src/overlays/l18/mobys/drek_fight_missile.c index 0a067a3099..bc852819aa 100644 --- a/src/overlays/l18/mobys/drek_fight_missile.c +++ b/src/overlays/l18/mobys/drek_fight_missile.c @@ -60,7 +60,8 @@ extern int update_drek_fight_missile_wander_movement(char *moby, float *vec) __asm__("FUN_L18_002f0120"); extern s32 random_integer_below(s32) __asm__("FUN_00213260"); extern short l18_drek_missile_roll_rate_degrees_gp __asm__("D_L18_00162210") __attribute__((sda)); -extern short D_L18_00162214_gp __asm__("D_L18_00162214") __attribute__((sda)); +extern short l18_drek_missile_wander_horizontal_speed_gp __asm__("D_L18_00162214") + __attribute__((sda)); extern short l18_drek_missile_dive_speed_gp __asm__("D_L18_00162218") __attribute__((sda)); extern short l18_drek_missile_wander_to_dive_random_bound_gp __asm__("D_L18_00162234") __attribute__((sda)); diff --git a/src/overlays/shared/enemies/large_amoeboid.c b/src/overlays/shared/enemies/large_amoeboid.c index b876c5b47c..833883686a 100644 --- a/src/overlays/shared/enemies/large_amoeboid.c +++ b/src/overlays/shared/enemies/large_amoeboid.c @@ -153,8 +153,10 @@ extern void trooper_start_knockback(void *, void *, float, int, int, int) __asm__("FUN_L00_0025c558"); extern float D_0013F420[]; extern int D_001413D0[]; -extern const float D_L01_001619A0_gp __asm__("D_L01_001619A0") __attribute__((sda)); -extern const float D_L01_001619A4_gp __asm__("D_L01_001619A4") __attribute__((sda)); +extern const float l01_smaller_amoeboid_knockback_xy_scale __asm__("D_L01_001619A0") + __attribute__((sda)); +extern const float l01_smaller_amoeboid_knockback_z_scale __asm__("D_L01_001619A4") + __attribute__((sda)); extern const float frame_time_macro __asm__("D_0015ED6C"); extern short *l01_moby_index_lists_by_group[] __asm__("D_L01_001ABCC0"); diff --git a/src/overlays/shared/enemies/scoutbot.c b/src/overlays/shared/enemies/scoutbot.c index 7548398620..54ecfef544 100644 --- a/src/overlays/shared/enemies/scoutbot.c +++ b/src/overlays/shared/enemies/scoutbot.c @@ -150,10 +150,10 @@ func_L00_00260FB0_f(char *, void *, float, int, int, void *, int) __asm__("FUN_L extern void scale_vector_002d3878(float, void *) __asm__("FUN_L00_0025f730"); extern void draw_geometry_quad(void *, void *, int) __asm__("FUN_001f7d30"); extern float D_L08_00161894_lui __asm__("D_L08_00161894") NOT_SDA; -extern u32 D_00151878_gp __asm__("D_00151878") __attribute__((sda)); -extern u32 D_0015187C_gp __asm__("D_0015187C") __attribute__((sda)); -extern u32 D_00151880_gp __asm__("D_00151880") __attribute__((sda)); -extern u32 D_00151884_gp __asm__("D_00151884") __attribute__((sda)); +extern u32 scoutbot_target_beam_vertex_0_color __asm__("D_00151878") __attribute__((sda)); +extern u32 scoutbot_target_beam_vertex_1_color __asm__("D_0015187C") __attribute__((sda)); +extern u32 scoutbot_target_beam_vertex_2_color __asm__("D_00151880") __attribute__((sda)); +extern u32 scoutbot_target_beam_vertex_3_color __asm__("D_00151884") __attribute__((sda)); void draw_target_beam(struct Moby *moby) __asm__("FUN_L08_002d3878"); extern float scoutbot_probe_correction_target_position[] __asm__("D_L08_00174670"); diff --git a/src/overlays/shared/weapons/turret_rocket.c b/src/overlays/shared/weapons/turret_rocket.c index 0d01953dec..a6312d9987 100644 --- a/src/overlays/shared/weapons/turret_rocket.c +++ b/src/overlays/shared/weapons/turret_rocket.c @@ -33,9 +33,12 @@ extern void spawn_spark(void *, void *, void *, int, int, int, int, int, int) __asm__("FUN_00218888"); extern int D_L08_0015F5CC __asm__("D_L08_0015F5CC"); -extern int D_L08_00161D08_gp __asm__("D_L08_00161D08") __attribute__((sda)); -extern int D_L08_00161D0C_gp __asm__("D_L08_00161D0C") __attribute__((sda)); -extern int D_L08_00161D10_gp __asm__("D_L08_00161D10") __attribute__((sda)); +extern int l08_turret_rocket_spark_first_frame_count_base __asm__("D_L08_00161D08") + __attribute__((sda)); +extern int l08_turret_rocket_spark_second_frame_count_base __asm__("D_L08_00161D0C") + __attribute__((sda)); +extern int l08_turret_rocket_spark_third_frame_count_base __asm__("D_L08_00161D10") + __attribute__((sda)); extern float moby_creation_default_timer_frames_gp __asm__("D_L08_00161CD8") __attribute__((sda)); extern float moby_creation_particle_count_limit_gp __asm__("D_L08_00161CE0") __attribute__((sda)); diff --git a/src/ui/menus/system/setup_menu_display_text.c b/src/ui/menus/system/setup_menu_display_text.c index bab66e5a74..a05d6ddedc 100644 --- a/src/ui/menus/system/setup_menu_display_text.c +++ b/src/ui/menus/system/setup_menu_display_text.c @@ -11,7 +11,7 @@ extern void setup_gif_paging(int) __asm__("func_001F4280"); extern void do_gif_paging(void) __asm__("func_001F4398"); extern void draw_moby_list(void *, int) __asm__("func_0020D330"); extern void *get_help_message_text(int) __asm__("func_001FDD10"); -extern const float D_001602A4_gp __asm__("D_001602A4") __attribute__((sda)); +extern const float setup_menu_moby_camera_y_offset __asm__("D_001602A4") __attribute__((sda)); extern char setup_menu_text_format[] __asm__("D_001602A8"); extern int menu_display_value_by_level[] __asm__("D_001E0888"); From b5516caffb47e8031f244811b8cf9603556c5fe4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 12:34:04 +0000 Subject: [PATCH 1342/1502] decomp: keep the alien queen private-data binding consistent --- src/overlays/l06/mobys/alien_queen.c | 168 ++++++++++++++------------- 1 file changed, 89 insertions(+), 79 deletions(-) diff --git a/src/overlays/l06/mobys/alien_queen.c b/src/overlays/l06/mobys/alien_queen.c index 091c270f30..f6de927781 100644 --- a/src/overlays/l06/mobys/alien_queen.c +++ b/src/overlays/l06/mobys/alien_queen.c @@ -412,45 +412,50 @@ void alien_queen_update(unsigned char *moby) { float step[4]; FUN_L06_002fa9c0_c(moby); - target = data->target; - func_L00_00264B40_q(moby, *(int *)&D_L06_00161EF0, 1.9f, &data->unk130); + target = alien_queen_update_vars->target; + func_L00_00264B40_q(moby, *(int *)&D_L06_00161EF0, 1.9f, &alien_queen_update_vars->unk130); if ((unsigned char)moby[0x31] != 0 && fast_vec_dist(moby + 0x10, D_L06_00167540_q) < 45.0f) { func_L00_0025B178_q(moby); moby[0x7F] = 0x24; } if ((unsigned char)moby[0x20] >= 3 && (unsigned char)moby[0x20] <= 13) { - data->animation_update = queue_animation_update(0x16, - 0xFFFF, - func_L00_00236710_q, - func_L00_00236830_q, - func_L06_0024A080_q, - &data->unk110, - 0x1EF); + alien_queen_update_vars->animation_update = + queue_animation_update(0x16, + 0xFFFF, + func_L00_00236710_q, + func_L00_00236830_q, + func_L06_0024A080_q, + &alien_queen_update_vars->unk110, + 0x1EF); } switch ((unsigned char)moby[0x20]) { case ALIEN_QUEEN_STATE_INITIALIZE: { int *path; - data->health = 30.0f; - data->max_health = 0x1E; - data->unk29 = 1; - data->unk28 = 3; - data->unk2E = 1; - data->unk58 = truncate_float_to_s32(14.0f); - data->unk5A = truncate_float_to_s32(18.4f); - data->timer_120 = scale_game_frames(0x4B0); - data->unk178 = 0; - qcopy(data->unkC0, moby + 0x10); - data->animation_update = -1; - data->unk114 = *D_L06_001B0C30_q[data->path]; - path = D_L06_001B0C30_q[data->path]; - lerp_vector(data->path_midpoint, path + 4, (char *)path + ((*path / 2) * 16 + 16), 0.5f); - data->path_midpoint[3] = vector_distance_xy(data->unkC0, data->path_midpoint); - data->unk128 = random_angle_radians(); - data->timer_12C = scale_game_frames(0x1E); + alien_queen_update_vars->health = 30.0f; + alien_queen_update_vars->max_health = 0x1E; + alien_queen_update_vars->unk29 = 1; + alien_queen_update_vars->unk28 = 3; + alien_queen_update_vars->unk2E = 1; + alien_queen_update_vars->unk58 = truncate_float_to_s32(14.0f); + alien_queen_update_vars->unk5A = truncate_float_to_s32(18.4f); + alien_queen_update_vars->timer_120 = scale_game_frames(0x4B0); + alien_queen_update_vars->unk178 = 0; + qcopy(alien_queen_update_vars->unkC0, moby + 0x10); + alien_queen_update_vars->animation_update = -1; + alien_queen_update_vars->unk114 = *D_L06_001B0C30_q[alien_queen_update_vars->path]; + path = D_L06_001B0C30_q[alien_queen_update_vars->path]; + lerp_vector(alien_queen_update_vars->path_midpoint, + path + 4, + (char *)path + ((*path / 2) * 16 + 16), + 0.5f); + alien_queen_update_vars->path_midpoint[3] = vector_distance_xy( + alien_queen_update_vars->unkC0, alien_queen_update_vars->path_midpoint); + alien_queen_update_vars->unk128 = random_angle_radians(); + alien_queen_update_vars->timer_12C = scale_game_frames(0x1E); MOBY(moby)->collision = 0; MOBY(moby)->flags = (MOBY(moby)->flags | 0x4001) & 0xEFFF; MOBY(moby)->pos.z = MOBY(moby)->pos.z + 17.5f; - set_moby_list_state_18(data->state18_list); + set_moby_list_state_18(alien_queen_update_vars->state18_list); if (menu_item_enabled_19_lui[4] != 0 && D_0013D4FD_q[8] == 0) { mark_moby_for_removal(moby); return; @@ -459,21 +464,22 @@ void alien_queen_update(unsigned char *moby) { break; } case ALIEN_QUEEN_STATE_WAIT_TO_START_INTRO: - if (data->unkB4 == 2) + if (alien_queen_update_vars->unkB4 == 2) return; if (*(short *)(target + 0xA6) != 0) return; - if (data->unk170 == 0) { - data->unk170 = 1; - data->timer_12C = scale_game_frames(10); + if (alien_queen_update_vars->unk170 == 0) { + alien_queen_update_vars->unk170 = 1; + alien_queen_update_vars->timer_12C = scale_game_frames(10); break; } - if (data->timer_12C != 0) + if (alien_queen_update_vars->timer_12C != 0) return; - func_L06_002F6818_q(level_mobys_q + (data->unkFC << 8)); - func_L06_002F6818_q(level_mobys_q + (data->unk100 << 8)); - set_listed_alien_queen_sliders_state_2_and_data_28_to_one(data->slider_list); - data->unk170 = 0; + func_L06_002F6818_q(level_mobys_q + (alien_queen_update_vars->unkFC << 8)); + func_L06_002F6818_q(level_mobys_q + (alien_queen_update_vars->unk100 << 8)); + set_listed_alien_queen_sliders_state_2_and_data_28_to_one( + alien_queen_update_vars->slider_list); + alien_queen_update_vars->unk170 = 0; moby[0x20] = 2; MOBY(moby)->collision = MOBY(moby)->pclass->collision; MOBY(moby)->flags = (MOBY(moby)->flags | 0x1000) & 0xFFFE; @@ -484,16 +490,17 @@ void alien_queen_update(unsigned char *moby) { return; case ALIEN_QUEEN_STATE_INTRO: { float gravity = frame_time_sq * 30.0f; - MOBY(moby)->pos.z = MOBY(moby)->pos.z + data->z_velocity; - data->z_velocity = data->z_velocity - gravity; + MOBY(moby)->pos.z = MOBY(moby)->pos.z + alien_queen_update_vars->z_velocity; + alien_queen_update_vars->z_velocity = alien_queen_update_vars->z_velocity - gravity; if ((unsigned char)moby[0x53] == 8) { - if (absolute_float((MOBY(moby)->pos.z - data->unkC0[2]) / data->z_velocity) <= 6.0f && + if (absolute_float((MOBY(moby)->pos.z - alien_queen_update_vars->unkC0[2]) / + alien_queen_update_vars->z_velocity) <= 6.0f && (unsigned char)moby[0x53] != 9) { blend_moby_animation(moby, 9, 0, scale_game_frames(5)); } } else { - if (MOBY(moby)->pos.z < data->unkC0[2]) { - MOBY(moby)->pos.z = data->unkC0[2]; + if (MOBY(moby)->pos.z < alien_queen_update_vars->unkC0[2]) { + MOBY(moby)->pos.z = alien_queen_update_vars->unkC0[2]; } if (MOBY(moby)->anim_time == 0.0f && (moby[0x70] & 2)) { if ((unsigned char)moby[0x53] == 9) { @@ -523,7 +530,7 @@ void alien_queen_update(unsigned char *moby) { case ALIEN_QUEEN_STATE_SECOND_RECOVERY_CAMERA: if ((unsigned char)moby[0x53] == 6 && MOBY(moby)->anim_time == 0.0f && (moby[0x70] & 2)) { blend_moby_animation(moby, 1, 0, scale_game_frames(0x14)); - clear_moby_list_state_18(data->state18_list); + clear_moby_list_state_18(alien_queen_update_vars->state18_list); } if (FUN_L06_002fba28(moby) != 0) { moby[0x20] = 6; @@ -535,18 +542,18 @@ void alien_queen_update(unsigned char *moby) { case ALIEN_QUEEN_STATE_GROUP_RECOVERY_ORBIT: func_L06_002FD0B8_q(moby); if (((unsigned char)moby[0x20] == 4 && - check_all_listed_frog_states_fe_fd_or_10(data->frog_list) != 0) || + check_all_listed_frog_states_fe_fd_or_10(alien_queen_update_vars->frog_list) != 0) || ((unsigned char)moby[0x20] == 6 && - count_active_moby_group_members(data->state18_list, -1) == 0)) { + count_active_moby_group_members(alien_queen_update_vars->state18_list, -1) == 0)) { moby[0x20] = 8; - data->timer_120 = scale_game_frames(0x4B0); + alien_queen_update_vars->timer_120 = scale_game_frames(0x4B0); if ((unsigned char)moby[0x53] != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(0x14)); } } return; case ALIEN_QUEEN_STATE_WAIT_TO_APPROACH_TARGET: - if (data->unkB4 == 2) + if (alien_queen_update_vars->unkB4 == 2) break; moby[0x20] = 8; if ((unsigned char)moby[0x53] == 3) @@ -562,32 +569,32 @@ void alien_queen_update(unsigned char *moby) { approach_angle((float *)&MOBY(moby)->rot.z, fast_arc_tan(*(float *)(target + 0x10) - MOBY(moby)->pos.x, *(float *)(target + 0x14) - MOBY(moby)->pos.y), - (float *)&data->unkE0, + (float *)&alien_queen_update_vars->unkE0, frame_time_sq * 6.2831855f, frame_time_sq * 6.2831855f, frame_time * 3.1415927f); if (turn < 0.7853982f && *(float *)&l06_alien_queen_attack_distance < dist) { - approach_value(&data->unkE8, + approach_value(&alien_queen_update_vars->unkE8, *(float *)&l06_alien_queen_movement_speed * frame_time, alien_queen_movement_acceleration_gp * frame_time_sq); } else if (dist < *(float *)&l06_alien_queen_retreat_distance) { - approach_value(&data->unkE8, + approach_value(&alien_queen_update_vars->unkE8, -(*(float *)&l06_alien_queen_movement_speed * frame_time), alien_queen_movement_acceleration_gp * frame_time_sq); } else { - approach_value(&data->unkE8, 0.0f, frame_time_sq * 8.0f); + approach_value(&alien_queen_update_vars->unkE8, 0.0f, frame_time_sq * 8.0f); } fast_vec_sub(step, target + 0x10, moby + 0x10); step[2] = 0.0f; - fast_vec_normalize(step, step, data->unkE8); + fast_vec_normalize(step, step, alien_queen_update_vars->unkE8); fast_vec_add(moby + 0x10, moby + 0x10, step); - func_L00_00262DF0_q(data->path, moby + 0x10, 1.0f, moby + 0x10); - if (data->unkB4 == 2) { + func_L00_00262DF0_q(alien_queen_update_vars->path, moby + 0x10, 1.0f, moby + 0x10); + if (alien_queen_update_vars->unkB4 == 2) { moby[0x20] = 0xD; break; } - if (fast_dec_timer(&data->timer_120) != 0) { - data->timer_120 = scale_game_frames(0x168); + if (fast_dec_timer(&alien_queen_update_vars->timer_120) != 0) { + alien_queen_update_vars->timer_120 = scale_game_frames(0x168); moby[0x20] = 0xC; break; } @@ -604,8 +611,8 @@ void alien_queen_update(unsigned char *moby) { } case ALIEN_QUEEN_STATE_TIMED_ORBIT: func_L06_002FD0B8_q(moby); - if (fast_dec_timer(&data->timer_120) != 0) { - data->timer_120 = scale_game_frames(0x4B0); + if (fast_dec_timer(&alien_queen_update_vars->timer_120) != 0) { + alien_queen_update_vars->timer_120 = scale_game_frames(0x4B0); moby[0x20] = 0xB; moby[0xBC] = 7; if ((unsigned char)moby[0x53] != 6) { @@ -614,10 +621,10 @@ void alien_queen_update(unsigned char *moby) { } return; case ALIEN_QUEEN_STATE_ATTACK_WINDUP: - fast_dec_timer(&data->timer_120); + fast_dec_timer(&alien_queen_update_vars->timer_120); approach_angle((float *)&MOBY(moby)->rot.z, MOBY(moby)->rot.z, - (float *)&data->unkE0, + (float *)&alien_queen_update_vars->unkE0, frame_time_sq * 6.2831855f, frame_time_sq * 6.2831855f, frame_time * 3.1415927f); @@ -632,7 +639,7 @@ void alien_queen_update(unsigned char *moby) { case ALIEN_QUEEN_STATE_ATTACK_HIT_QUERIES: { QueenProbe probe; float hit_query_position[4]; - fast_dec_timer(&data->timer_120); + fast_dec_timer(&alien_queen_update_vars->timer_120); if (1.0f < compute_interpolated_record_value(moby) && compute_interpolated_record_value(moby) < 8.0f) { step[0] = fast_cos(MOBY(moby)->rot.z) * 0.45f; @@ -679,26 +686,27 @@ void alien_queen_update(unsigned char *moby) { return; case ALIEN_QUEEN_STATE_RETURN_HOME: { char *pos = (char *)moby + 0x10; - char *home = data->unkC0; + char *home = alien_queen_update_vars->unkC0; float dist = vector_distance_xy(pos, home); float turn = fast_difference_between_rotations( MOBY(moby)->rot.z, - fast_arc_tan(data->unkC0[0] - MOBY(moby)->pos.x, data->unkC0[1] - MOBY(moby)->pos.y)); - approach_angle( - (float *)&MOBY(moby)->rot.z, - fast_arc_tan(data->unkC0[0] - MOBY(moby)->pos.x, data->unkC0[1] - MOBY(moby)->pos.y), - (float *)&data->unkE0, - frame_time_sq * 6.2831855f, - frame_time_sq * 6.2831855f, - frame_time * 3.1415927f); + fast_arc_tan(alien_queen_update_vars->unkC0[0] - MOBY(moby)->pos.x, + alien_queen_update_vars->unkC0[1] - MOBY(moby)->pos.y)); + approach_angle((float *)&MOBY(moby)->rot.z, + fast_arc_tan(alien_queen_update_vars->unkC0[0] - MOBY(moby)->pos.x, + alien_queen_update_vars->unkC0[1] - MOBY(moby)->pos.y), + (float *)&alien_queen_update_vars->unkE0, + frame_time_sq * 6.2831855f, + frame_time_sq * 6.2831855f, + frame_time * 3.1415927f); if (turn < 0.7853982f) { fast_vec_sub(step, home, pos); step[2] = 0.0f; fast_vec_normalize(step, step, *(float *)&l06_alien_queen_movement_speed * frame_time); fast_vec_add(pos, pos, step); - func_L00_00262DF0_q(data->path, pos, 1.0f, pos); + func_L00_00262DF0_q(alien_queen_update_vars->path, pos, 1.0f, pos); } - if (data->unkB4 != 2) { + if (alien_queen_update_vars->unkB4 != 2) { moby[0x20] = 7; break; } @@ -714,11 +722,12 @@ void alien_queen_update(unsigned char *moby) { case ALIEN_QUEEN_STATE_DEATH: { unsigned char *flag; menu_item_enabled_19_lui[4] = 1; - data->unk110 = 0; + alien_queen_update_vars->unk110 = 0; moby[0x30] = 0xFF; - if (data->unk2E == 2) { - func_L06_002F6790_q(level_mobys_q + (data->unk100 << 8)); - set_listed_alien_queen_sliders_state_2_and_clear_data_28(data->slider_list); + if (alien_queen_update_vars->unk2E == 2) { + func_L06_002F6790_q(level_mobys_q + (alien_queen_update_vars->unk100 << 8)); + set_listed_alien_queen_sliders_state_2_and_clear_data_28( + alien_queen_update_vars->slider_list); MOBY(moby)->flags |= 1; moby[0x20] = 0xF; moby[0x31] = 0; @@ -735,8 +744,9 @@ void alien_queen_update(unsigned char *moby) { step[2] = step[2] + 1.0f; func_L00_00260460_q(moby, step, -1, 2.0f, 20.0f); spawn_moby_break_fragments(moby, 0x6A2, 1, 0x6A3, 3, 6, 2); - func_L06_002F6790_q(level_mobys_q + (data->unk100 << 8)); - set_listed_alien_queen_sliders_state_2_and_clear_data_28(data->slider_list); + func_L06_002F6790_q(level_mobys_q + (alien_queen_update_vars->unk100 << 8)); + set_listed_alien_queen_sliders_state_2_and_clear_data_28( + alien_queen_update_vars->slider_list); moby[0x20] = 0xF; if ((unsigned char)moby[0x53] != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(0x14)); @@ -744,7 +754,7 @@ void alien_queen_update(unsigned char *moby) { MOBY(moby)->collision = 0; moby[0x31] = 0; MOBY(moby)->flags |= 1; - if (data->unk178 != 0) + if (alien_queen_update_vars->unk178 != 0) return; flag = D_0013D407_q + 1; if (flag[0xA] != 0) @@ -767,7 +777,7 @@ void alien_queen_update(unsigned char *moby) { } } if (level_game_mode_q == 2) { - func_L06_002F6790_q(level_mobys_q + (data->unkFC << 8)); + func_L06_002F6790_q(level_mobys_q + (alien_queen_update_vars->unkFC << 8)); mark_moby_for_removal(moby); } break; From 80d584a9930b0fe4c5944ebbb8a5ed2aa8f089c8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 12:38:15 +0000 Subject: [PATCH 1343/1502] decomp: preserve consistent private-data bindings after type updates --- .../shared/enemies/blarg_paratrooper.c | 131 +++++++------ src/overlays/shared/enemies/frog.c | 179 ++++++++++-------- src/overlays/shared/enemies/scoutbot.c | 41 ++-- 3 files changed, 189 insertions(+), 162 deletions(-) diff --git a/src/overlays/shared/enemies/blarg_paratrooper.c b/src/overlays/shared/enemies/blarg_paratrooper.c index 726580e624..5e0e96a37c 100644 --- a/src/overlays/shared/enemies/blarg_paratrooper.c +++ b/src/overlays/shared/enemies/blarg_paratrooper.c @@ -609,7 +609,7 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { PARATROOPER_HIT_REACTION_RECOVERY_KNOCKBACK = 3, PARATROOPER_HIT_REACTION_NONE = 11 }; - Paratrooper302618 *data; + Paratrooper302618 *paratrooper_instance_state; char *target, *child, *attached, *chased; float pos[4] __attribute__((aligned(16))); float matrix[16] __attribute__((aligned(16))); @@ -624,37 +624,38 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { float timer_scale = D_L08_001621B0 * frame_time; ((Moby *)moby)->scale = *(float *)(((char *)MOBY(moby)->pclass) + 0x24) * l08_paratrooper_model_scale_multiplier; - data->unkF4 = timer_scale; + paratrooper_instance_state->unkF4 = timer_scale; } - if (data->f1F8 == 0) { + if (paratrooper_instance_state->f1F8 == 0) { child = create_moby(0x401); - data->f1F8 = child; + paratrooper_instance_state->f1F8 = child; if (child != 0) { *(short *)(child + 0x32) = 0x40; - *(unsigned char *)(data->f1F8 + 0x30) = 0x40; - *(unsigned char *)(data->f1F8 + 0x31) = 1; - *(unsigned short *)(data->f1F8 + 0x34) |= 0x100; + *(unsigned char *)(paratrooper_instance_state->f1F8 + 0x30) = 0x40; + *(unsigned char *)(paratrooper_instance_state->f1F8 + 0x31) = 1; + *(unsigned short *)(paratrooper_instance_state->f1F8 + 0x34) |= 0x100; moby_point_position(moby, 4, pos); - qcopy(data->f1F8 + 0x10, pos); + qcopy(paratrooper_instance_state->f1F8 + 0x10, pos); } MOBY(moby)->flags |= 0x1000; } else { moby_point_position(moby, 4, pos); build_moby_bone_transform(moby, 4, matrix); - copy_matrix3x4(data->f1F8 + 0xc0, matrix); - attached = data->f1F8; + copy_matrix3x4(paratrooper_instance_state->f1F8 + 0xc0, matrix); + attached = paratrooper_instance_state->f1F8; qcopy(attached + 0x10, pos); update_entity(attached); } damage = 0.0f; target = find_moby_hit(moby, 0x330000, 0); - reaction = resolve_moby_hit_response(moby, target, &data->health, 0, &hit_state, &damage, 0, 4); + reaction = resolve_moby_hit_response( + moby, target, ¶trooper_instance_state->health, 0, &hit_state, &damage, 0, 4); if (hit_state != 1 && MOBY(moby)->state != 11) { { - float health = data->health - damage; - data->health = health; + float health = paratrooper_instance_state->health - damage; + paratrooper_instance_state->health = health; if (*(short *)(*(char **)(target + 0x20) + 0xa6) == 0x47) reaction = 3; if (health <= 0.0f) @@ -664,12 +665,12 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { turn = truncate_float_to_s32(512.0f); { float pose_scale = D_L08_00162184 * frame_time_sq; - data->unk90 = turn; - data->unk98 = 0.5f; - data->unk94 = 9; - data->unk80 = pose_scale; + paratrooper_instance_state->unk90 = turn; + paratrooper_instance_state->unk98 = 0.5f; + paratrooper_instance_state->unk94 = 9; + paratrooper_instance_state->unk80 = pose_scale; } - data->unkAD = 0; + paratrooper_instance_state->unkAD = 0; if ((unsigned)reaction < 12) { switch (reaction) { @@ -678,7 +679,7 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { break; case 9: case 10: - data->unk67 = 0xfa; + paratrooper_instance_state->unk67 = 0xfa; break; case PARATROOPER_HIT_REACTION_RECOVERY_KNOCKBACK: case 4: @@ -688,10 +689,10 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { case 8: { float pose_scale = l08_paratrooper_recovery_knockback_xy_speed * frame_time; float timer_scale = frame_time * 3.0f; - data->unk88 = pose_scale; - data->unk8C = timer_scale; - data->unkC0 = 5.0f; - data->unkC4 = 10.0f; + paratrooper_instance_state->unk88 = pose_scale; + paratrooper_instance_state->unk8C = timer_scale; + paratrooper_instance_state->unkC0 = 5.0f; + paratrooper_instance_state->unkC4 = 10.0f; } { char *hit_moby = *(char **)(target + 0x20); @@ -701,11 +702,14 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { angle = fast_arc_tan(dx, dy); *(u128 *)pos = *(u128 *)(target + 0x10); knock_angle = angle; - trooper_knockback_arc( - pos, &knock_angle, (float *)(&data->unk88), (float *)(&data->unk8C)); - trooper_start_knockback(moby, &data->unk70, knock_angle, 8, 1, 0); + trooper_knockback_arc(pos, + &knock_angle, + (float *)(¶trooper_instance_state->unk88), + (float *)(¶trooper_instance_state->unk8C)); + trooper_start_knockback( + moby, ¶trooper_instance_state->unk70, knock_angle, 8, 1, 0); MOBY(moby)->state = 10; - data->unk67 = 0x78; + paratrooper_instance_state->unk67 = 0x78; break; case PARATROOPER_HIT_REACTION_LETHAL: case PARATROOPER_HIT_REACTION_DEATH_KNOCKBACK: { @@ -719,13 +723,13 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { pose_scale = pose_rate * frame_time_sq; timer_scale = timer_rate * step; angle_scale = angle_rate * step; - data->unk98 = 0.25f; - data->unk8C = angle_scale; - data->unk80 = pose_scale; - data->unk88 = timer_scale; - data->unkC0 = 11.0f; - data->unkC4 = push_limit; - data->unk90 = 0x200; + paratrooper_instance_state->unk98 = 0.25f; + paratrooper_instance_state->unk8C = angle_scale; + paratrooper_instance_state->unk80 = pose_scale; + paratrooper_instance_state->unk88 = timer_scale; + paratrooper_instance_state->unkC0 = 11.0f; + paratrooper_instance_state->unkC4 = push_limit; + paratrooper_instance_state->unk90 = 0x200; } { char *hit_moby = *(char **)(target + 0x20); @@ -735,57 +739,66 @@ void update_blarg_paratrooper_damage_and_state(char *moby) { angle = fast_arc_tan(dx, dy); *(u128 *)pos = *(u128 *)(target + 0x10); second_knock_angle = angle; - trooper_knockback_arc( - pos, &second_knock_angle, (float *)(&data->unk88), (float *)(&data->unk8C)); - trooper_start_knockback(moby, &data->unk70, second_knock_angle, 12, 1, 0); + trooper_knockback_arc(pos, + &second_knock_angle, + (float *)(¶trooper_instance_state->unk88), + (float *)(¶trooper_instance_state->unk8C)); + trooper_start_knockback( + moby, ¶trooper_instance_state->unk70, second_knock_angle, 12, 1, 0); MOBY(moby)->state = 11; - data->unk67 = 0xf0; + paratrooper_instance_state->unk67 = 0xf0; spawn_randomized_bolt_drop(moby, 2, 3, 0, -1); break; default: break; } } - trooper_anim_update(moby, &data->unk60); + trooper_anim_update(moby, ¶trooper_instance_state->unk60); } MOBY(moby)->hit_slot = 0xff; - trooper_anim_finish(moby, &data->unk60); + trooper_anim_finish(moby, ¶trooper_instance_state->unk60); - if (data->unk38 != 0) { + if (paratrooper_instance_state->unk38 != 0) { angle = random_float_between(180.0f, 240.0f); angle = scale_time(angle); - data->unk1D8 = (short)truncate_float_to_s32(angle); - data->unk38 = 0; + paratrooper_instance_state->unk1D8 = (short)truncate_float_to_s32(angle); + paratrooper_instance_state->unk38 = 0; } - fast_dec_timer_s16((short *)(&data->unk1D8)); - if (data->unk1D8 != 0) - data->unk1DC = data->unk1E4 + 6.0f; + fast_dec_timer_s16((short *)(¶trooper_instance_state->unk1D8)); + if (paratrooper_instance_state->unk1D8 != 0) + paratrooper_instance_state->unk1DC = paratrooper_instance_state->unk1E4 + 6.0f; else - data->unk1DC = data->unk1E4; + paratrooper_instance_state->unk1DC = paratrooper_instance_state->unk1E4; if (random_integer_below(4) == 0) { { - char *path = ((char *)l08_paths[data->f1D0]); - reaction = activate_effect_l08( - moby, &data->unk120, data->unk1DC, 0, 0, path + 0x10, *(int *)path); + char *path = ((char *)l08_paths[paratrooper_instance_state->f1D0]); + reaction = activate_effect_l08(moby, + ¶trooper_instance_state->unk120, + paratrooper_instance_state->unk1DC, + 0, + 0, + path + 0x10, + *(int *)path); } if (reaction != 2) { - distance = vector_distance_xy(&MOBY(moby)->pos, &data->unk120); - if (data->unk1DC < distance || 3.0f < absolute_float(MOBY(moby)->pos.z - data->unk128)) - data->f164 = 2; + distance = vector_distance_xy(&MOBY(moby)->pos, ¶trooper_instance_state->unk120); + if (paratrooper_instance_state->unk1DC < distance || + 3.0f < absolute_float(MOBY(moby)->pos.z - paratrooper_instance_state->unk128)) + paratrooper_instance_state->f164 = 2; } } else { - chased = data->f160; + chased = paratrooper_instance_state->f160; if (chased != 0 && *(unsigned char *)(chased + 0x20) != 0xfe && *(unsigned char *)(chased + 0x20) != 0xfd) { - qcopy(&data->unk120, chased + 0x10); + qcopy(¶trooper_instance_state->unk120, chased + 0x10); } else { - data->f160 = 0; - data->f164 = 2; + paratrooper_instance_state->f160 = 0; + paratrooper_instance_state->f164 = 2; } } - if (*(int *)&data->f160 == 0) - data->f160 = (char *)hero.moby; + if (*(int *)¶trooper_instance_state->f160 == 0) + paratrooper_instance_state->f160 = (char *)hero.moby; state = MOBY(moby)->state; if (state == 0 || state == 5 || state == 7 || state == 4) { diff --git a/src/overlays/shared/enemies/frog.c b/src/overlays/shared/enemies/frog.c index ba3707bf5a..14004b10bb 100644 --- a/src/overlays/shared/enemies/frog.c +++ b/src/overlays/shared/enemies/frog.c @@ -275,79 +275,79 @@ void frog_update(unsigned char *moby) { } mode = D_L06_0015F5C4; if (mode == 2 && ((MOBY(moby)->flags ^ 1) & 1)) { - data->unk1EA = 1; + frog_instance_vars->unk1EA = 1; MOBY(moby)->flags |= 0x41; - } else if (mode == 0 && data->unk1EA != 0) { - data->unk1EA = 0; + } else if (mode == 0 && frog_instance_vars->unk1EA != 0) { + frog_instance_vars->unk1EA = 0; MOBY(moby)->flags &= 0xFFBE; } if (MOBY(moby)->state != 0x10) { if (*(int *)&D_L06_0015FDF8 != 0) { - if (data->unk242 == 0) + if (frog_instance_vars->unk242 == 0) return; } else { - if (data->unk242 != 0) + if (frog_instance_vars->unk242 != 0) return; } } - FUN_L00_00263ac8(2.1f, (int)moby, 1, (unsigned char *)(&data->unk250)); + FUN_L00_00263ac8(2.1f, (int)moby, 1, (unsigned char *)(&frog_instance_vars->unk250)); update_frog_health_respawn_and_target(moby); if (MOBY(moby)->visible != 0 && fast_vec_dist(&MOBY(moby)->pos, D_L06_00167540) < 14.0f) { FUN_L00_0025a120(moby); MOBY(moby)->shadow_range = 0xB; } - target = data->unk1C0; + target = frog_instance_vars->unk1C0; switch (MOBY(moby)->state) { case FROG_STATE_INITIALIZE: { float wait; int spawn_count = l06_frog_frame_slot_assignment_count; - int divisor = data->unk240; - data->unk20A = spawn_count % 8; + int divisor = frog_instance_vars->unk240; + frog_instance_vars->unk20A = spawn_count % 8; l06_frog_frame_slot_assignment_count = spawn_count + 1; if (divisor != 0) { MOBY(moby)->unkB4 = MOBY(moby)->unkB4 / divisor; } MOBY(moby)->flags |= 0x100; - data->unk58 = truncate_float_to_s32(8.0f); - data->unk5A = truncate_float_to_s32(3.2f); - qcopy(&data->unk210, &MOBY(moby)->pos); - qcopy(&data->unk230, &MOBY(moby)->pos); - qcopy(&data->unk220, moby + 0x40); - data->path_point = 0; + frog_instance_vars->unk58 = truncate_float_to_s32(8.0f); + frog_instance_vars->unk5A = truncate_float_to_s32(3.2f); + qcopy(&frog_instance_vars->unk210, &MOBY(moby)->pos); + qcopy(&frog_instance_vars->unk230, &MOBY(moby)->pos); + qcopy(&frog_instance_vars->unk220, moby + 0x40); + frog_instance_vars->path_point = 0; wait = random_float_between(0.5f, 3.0f); - data->unk130 = D_0015ED70 * 20.0f; - data->unk148 = 0; - data->unk134 = 0; - data->unk140 = 0x200; - data->unk244 = wait; - data->unk248 = random_angle_radians(); - data->unkD0 = D_L06_00161BF0; - data->unk29 = 1; - if (data->unk200 != 0) { + frog_instance_vars->unk130 = D_0015ED70 * 20.0f; + frog_instance_vars->unk148 = 0; + frog_instance_vars->unk134 = 0; + frog_instance_vars->unk140 = 0x200; + frog_instance_vars->unk244 = wait; + frog_instance_vars->unk248 = random_angle_radians(); + frog_instance_vars->unkD0 = D_L06_00161BF0; + frog_instance_vars->unk29 = 1; + if (frog_instance_vars->unk200 != 0) { char *child; MOBY(moby)->state = 1; child = create_moby(0x1F4); - data->child = child; + frog_instance_vars->child = child; if (child == 0) { mark_moby_for_removal(moby); return; } *(long *)(child + 0x38) = ((long)MOBY(moby)->spawn_frame); - *(unsigned short *)(data->child + 0x34) |= 0x4002; + *(unsigned short *)(frog_instance_vars->child + 0x34) |= 0x4002; { - char *child = data->child; + char *child = frog_instance_vars->child; qcopy(child + 0x10, &MOBY(moby)->pos); qcopy(child + 0x40, moby + 0x40); *(short *)(child + 0x32) = 0x40; } - (data->child)[0x31] = 1; - update_entity(data->child); + (frog_instance_vars->child)[0x31] = 1; + update_entity(frog_instance_vars->child); MOBY(moby)->flags |= 0x41; - } else if (data->unk202 != 0) { + } else if (frog_instance_vars->unk202 != 0) { MOBY(moby)->state = 0xF; MOBY(moby)->collision = 0; MOBY(moby)->flags = (MOBY(moby)->flags | 0x41) & 0xEFFF; - } else if (data->path_index >= 0) { + } else if (frog_instance_vars->path_index >= 0) { MOBY(moby)->state = 3; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, 0); @@ -376,7 +376,8 @@ void frog_update(unsigned char *moby) { fast_vec_sub(A, target + 0x10, &MOBY(moby)->pos); probe_frog_local_z_collision((char *)moby); blend_frog_rotation_to_facing_frame((char *)moby, (float *)D_L06_00174600, A); - if (vector_distance_xy(((char *)&D_0013F3D0), &MOBY(moby)->pos) < data->unk24C) { + if (vector_distance_xy(((char *)&D_0013F3D0), &MOBY(moby)->pos) < + frog_instance_vars->unk24C) { MOBY(moby)->state = 4; if (MOBY(moby)->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(5)); @@ -385,46 +386,53 @@ void frog_update(unsigned char *moby) { case FROG_STATE_FOLLOW_PATH: { int *path; int point_count; - qcopy(B, (char *)D_L06_001B0C30[data->path_index] + data->path_point * 16 + 0x10); + qcopy(B, + (char *)D_L06_001B0C30[frog_instance_vars->path_index] + + frog_instance_vars->path_point * 16 + 0x10); fast_vec_sub(A, B, &MOBY(moby)->pos); probe_frog_local_z_collision((char *)moby); blend_frog_rotation_to_facing_frame((char *)moby, (float *)D_L06_00174600, A); - fast_vec_normalize(C, moby + 0xC0, data->unk1E4 * D_0015ED6C_gp); + fast_vec_normalize(C, moby + 0xC0, frog_instance_vars->unk1E4 * D_0015ED6C_gp); FUN_L06_002e9b60_c(moby, C, 0, 0.3f, 0.3f); transform_vector_by_basis(A, A, moby + 0xC0); if (vector_length_xy(A) < 0.5f) { float return_speed; float home_distance_xy; - path = D_L06_001B0C30[data->path_index]; + path = D_L06_001B0C30[frog_instance_vars->path_index]; point_count = *path; - if (data->path_point < point_count - 2) { - data->path_point = data->path_point + 1; + if (frog_instance_vars->path_point < point_count - 2) { + frog_instance_vars->path_point = frog_instance_vars->path_point + 1; return; } - qcopy(&data->unk210, (char *)path + point_count * 16); - qcopy(&data->unk230, &data->unk210); - home_distance_xy = vector_distance_xy(&MOBY(moby)->pos, &data->unk210); + qcopy(&frog_instance_vars->unk210, (char *)path + point_count * 16); + qcopy(&frog_instance_vars->unk230, &frog_instance_vars->unk210); + home_distance_xy = vector_distance_xy(&MOBY(moby)->pos, &frog_instance_vars->unk210); return_speed = home_distance_xy / (float)scale_game_frames(30); - data->unk138 = return_speed; - data->unk13C = - FUN_L00_0025abf0(&MOBY(moby)->pos, &data->unk210, 0, return_speed, -data->unk130); - data->unk15D = 3; - data->unk144 = 5; - trooper_start_knockback(moby, - &data->motion, - 2, - 1, - 0, - fast_arc_tan(data->unk210[0] - MOBY(moby)->pos.x, - data->unk210[1] - MOBY(moby)->pos.y)); + frog_instance_vars->unk138 = return_speed; + frog_instance_vars->unk13C = FUN_L00_0025abf0(&MOBY(moby)->pos, + &frog_instance_vars->unk210, + 0, + return_speed, + -frog_instance_vars->unk130); + frog_instance_vars->unk15D = 3; + frog_instance_vars->unk144 = 5; + trooper_start_knockback( + moby, + &frog_instance_vars->motion, + 2, + 1, + 0, + fast_arc_tan(frog_instance_vars->unk210[0] - MOBY(moby)->pos.x, + frog_instance_vars->unk210[1] - MOBY(moby)->pos.y)); MOBY(moby)->state = 5; } break; } case FROG_STATE_JUMP_TO_HOME: set_vector_unit_z(A); - blend_frog_rotation_to_facing_frame((char *)moby, A, (float *)(&data->motion)); - if (step_moby_motion(moby, &data->motion) & 1) { + blend_frog_rotation_to_facing_frame( + (char *)moby, A, (float *)(&frog_instance_vars->motion)); + if (step_moby_motion(moby, &frog_instance_vars->motion) & 1) { MOBY(moby)->state = 7; if (MOBY(moby)->prev_seq != 3) blend_moby_animation(moby, 3, 0, 1); @@ -433,7 +441,7 @@ void frog_update(unsigned char *moby) { } break; case FROG_STATE_AIRBORNE_MOTION: { - int hit = step_moby_motion(moby, &data->motion); + int hit = step_moby_motion(moby, &frog_instance_vars->motion); if (hit & 1) { MOBY(moby)->state = 7; if (MOBY(moby)->prev_seq != 3) @@ -456,33 +464,35 @@ void frog_update(unsigned char *moby) { break; case FROG_STATE_WANDER: if (MOBY(moby)->visible != 0) { - if (fast_vec_dist(&MOBY(moby)->pos, &data->unk230) < 0.05f || - fast_dec_timer((int *)(&data->unk1FC)) != 0) { + if (fast_vec_dist(&MOBY(moby)->pos, &frog_instance_vars->unk230) < 0.05f || + fast_dec_timer((int *)(&frog_instance_vars->unk1FC)) != 0) { float angle = random_angle_radians(); float radius = random_float_between(0.5f, 2.0f); A[0] = fast_cos(angle) * radius; A[1] = fast_sin(angle) * radius; A[2] = 0.0f; - fast_vec_add(&data->unk230, &data->unk210, A); - data->unk1FC = + fast_vec_add(&frog_instance_vars->unk230, &frog_instance_vars->unk210, A); + frog_instance_vars->unk1FC = scale_game_frames(truncate_float_to_s32(random_float_between(45.0f, 75.0f))); } - fast_vec_sub(C, &data->unk230, &MOBY(moby)->pos); + fast_vec_sub(C, &frog_instance_vars->unk230, &MOBY(moby)->pos); probe_frog_local_z_collision((char *)moby); blend_frog_rotation_to_facing_frame((char *)moby, (float *)D_L06_00174600, C); - fast_vec_normalize(B, moby + 0xC0, data->unk1E4 * D_0015ED6C_gp); + fast_vec_normalize(B, moby + 0xC0, frog_instance_vars->unk1E4 * D_0015ED6C_gp); FUN_L06_002e9b60_c(moby, B, 1, 0.3f, 0.3f); } - if (data->unk1C4 != 2 && random_integer_below(9) == 0) { - data->turn_angle = - random_float_between(-data->turn_range_degrees, data->turn_range_degrees) * + if (frog_instance_vars->unk1C4 != 2 && random_integer_below(9) == 0) { + frog_instance_vars->turn_angle = + random_float_between(-frog_instance_vars->turn_range_degrees, + frog_instance_vars->turn_range_degrees) * 0.017453292f; MOBY(moby)->state = 9; if (MOBY(moby)->prev_seq != 4) blend_moby_animation(moby, 4, 0, 0); - } else if (data->unk1E8 != 0) { - data->turn_angle = - random_float_between(-data->turn_range_degrees, data->turn_range_degrees) * + } else if (frog_instance_vars->unk1E8 != 0) { + frog_instance_vars->turn_angle = + random_float_between(-frog_instance_vars->turn_range_degrees, + frog_instance_vars->turn_range_degrees) * 0.017453292f; MOBY(moby)->state = 10; if (MOBY(moby)->prev_seq != 4) @@ -493,19 +503,19 @@ void frog_update(unsigned char *moby) { float angle = fast_add_rotations(fast_arc_tan(*(float *)(target + 0x10) - MOBY(moby)->pos.x, *(float *)(target + 0x14) - MOBY(moby)->pos.y), - data->turn_angle); + frog_instance_vars->turn_angle); B[0] = fast_cos(angle); B[1] = fast_sin(angle); B[2] = 0.0f; probe_frog_local_z_collision((char *)moby); blend_frog_rotation_to_facing_frame((char *)moby, (float *)D_L06_00174600, B); - fast_vec_normalize(A, moby + 0xC0, data->unk1E4 * D_0015ED6C_gp); + fast_vec_normalize(A, moby + 0xC0, frog_instance_vars->unk1E4 * D_0015ED6C_gp); FUN_L06_002e9b60_c(moby, A, 1, 0.3f, 0.3f); if (vector_distance_xy(&MOBY(moby)->pos, target + 0x10) < 2.0f) { MOBY(moby)->state = 0xC; if (MOBY(moby)->prev_seq != 5) blend_moby_animation(moby, 5, 4, scale_game_frames(10)); - } else if (data->unk1C4 == 2) { + } else if (frog_instance_vars->unk1C4 == 2) { MOBY(moby)->state = 0xD; } break; @@ -515,7 +525,7 @@ void frog_update(unsigned char *moby) { float angle = fast_add_rotations(fast_arc_tan(*(float *)(target + 0x10) - MOBY(moby)->pos.x, *(float *)(target + 0x14) - MOBY(moby)->pos.y), - data->turn_angle); + frog_instance_vars->turn_angle); qcopy(C, &MOBY(moby)->pos); B[0] = fast_cos(angle); B[1] = fast_sin(angle); @@ -523,13 +533,13 @@ void frog_update(unsigned char *moby) { near = 0; probe_frog_local_z_collision((char *)moby); blend_frog_rotation_to_facing_frame((char *)moby, (float *)D_L06_00174600, B); - fast_vec_normalize(A, moby + 0xC0, data->unk1E4 * D_0015ED6C_gp); + fast_vec_normalize(A, moby + 0xC0, frog_instance_vars->unk1E4 * D_0015ED6C_gp); FUN_L06_002e9b60_c(moby, A, 1, 0.3f, 0.3f); - if (FUN_L00_00261b48(data->unk1EC, &MOBY(moby)->pos, target + 0x10, D) != 0 && - fast_vec_dist(&MOBY(moby)->pos, D) < data->unk244) { + if (FUN_L00_00261b48(frog_instance_vars->unk1EC, &MOBY(moby)->pos, target + 0x10, D) != 0 && + fast_vec_dist(&MOBY(moby)->pos, D) < frog_instance_vars->unk244) { near = 1; } - if (data->unk1E8 == 0) { + if (frog_instance_vars->unk1E8 == 0) { MOBY(moby)->state = 0xD; } else if (near) { MOBY(moby)->state = 0xB; @@ -560,7 +570,10 @@ void frog_update(unsigned char *moby) { wait = compute_interpolated_record_value(moby); if (MOBY(moby)->seq == MOBY(moby)->prev_seq && wait >= 10.0f && wait <= 15.0f && *(int *)(((char *)&camera_secondary_mode)) != 0x51) { - fast_vec_normalize(A, moby + 0xC0, (data->unk1E4 + data->unk1E4) * D_0015ED6C_gp); + fast_vec_normalize(A, + moby + 0xC0, + (frog_instance_vars->unk1E4 + frog_instance_vars->unk1E4) * + D_0015ED6C_gp); FUN_L06_002e9b60_c(moby, A, 1, 0.3f, 0.3f); collect_mobies_in_sphere_at_moby_point(moby, 0, 1, 0.333f, 1.0f, 1.0f, 0, 1, 0); return; @@ -574,27 +587,27 @@ void frog_update(unsigned char *moby) { break; } case FROG_STATE_RETURN_HOME: - fast_vec_sub(B, &data->unk210, &MOBY(moby)->pos); + fast_vec_sub(B, &frog_instance_vars->unk210, &MOBY(moby)->pos); probe_frog_local_z_collision((char *)moby); blend_frog_rotation_to_facing_frame((char *)moby, (float *)D_L06_00174600, B); - fast_vec_normalize(A, moby + 0xC0, data->unk1E4 * D_0015ED6C_gp); + fast_vec_normalize(A, moby + 0xC0, frog_instance_vars->unk1E4 * D_0015ED6C_gp); FUN_L06_002e9b60_c(moby, A, 1, 0.3f, 0.3f); - if (vector_distance_xy(&MOBY(moby)->pos, &data->unk210) < 2.0f) { + if (vector_distance_xy(&MOBY(moby)->pos, &frog_instance_vars->unk210) < 2.0f) { MOBY(moby)->state = 8; if (MOBY(moby)->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); - } else if (data->unk1C4 != 2) { + } else if (frog_instance_vars->unk1C4 != 2) { MOBY(moby)->state = 9; - } else if (data->unk1E8 != 0) { + } else if (frog_instance_vars->unk1E8 != 0) { MOBY(moby)->state = 0xA; } break; case FROG_STATE_SUCK_CANNON_HELD: - if (FUN_L00_002dc9f0(moby, &data->motion) != 0) { + if (FUN_L00_002dc9f0(moby, &frog_instance_vars->motion) != 0) { MOBY(moby)->state = 8; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); - data->unkC8 = 0; + frog_instance_vars->unkC8 = 0; } break; } diff --git a/src/overlays/shared/enemies/scoutbot.c b/src/overlays/shared/enemies/scoutbot.c index 54ecfef544..56641c2f86 100644 --- a/src/overlays/shared/enemies/scoutbot.c +++ b/src/overlays/shared/enemies/scoutbot.c @@ -484,9 +484,10 @@ void draw_target_beam(struct Moby *moby) { pk.uv[6] = 1.0f; pk.uv[7] = 1.0f; moby_point_position(moby, 2, &beam_origin_position); - fast_vec_sub(&delta, data->unk218 + 0x10, &beam_origin_position); + fast_vec_sub(&delta, scoutbot_private_vars->unk218 + 0x10, &beam_origin_position); scale_vector_002d3878(3.0f, &delta); - delta.v[2] = (*(float *)(data->unk218 + 0x18) + 0.25f) - beam_origin_position.v[2]; + delta.v[2] = + (*(float *)(scoutbot_private_vars->unk218 + 0x18) + 0.25f) - beam_origin_position.v[2]; delta.v[3] = 1.0f; length = fast_vec_length(&delta); clear_u64_value(&angles); @@ -499,15 +500,15 @@ void draw_target_beam(struct Moby *moby) { clear_u64_value(&pk.vertices[0]); pk.vertices[0].v[2] = D_L08_00161894_lui; pk.vertices[0].v[3] = 1.0f; - qcopy(&pk.vertices[1], &data->unk1D0); - pk.vertices[1].v[0] = length * data->unk1D0[3]; + qcopy(&pk.vertices[1], &scoutbot_private_vars->unk1D0); + pk.vertices[1].v[0] = length * scoutbot_private_vars->unk1D0[3]; pk.vertices[1].v[2] += -0.25f; pk.vertices[1].v[3] = 1.0f; clear_u64_value(&pk.vertices[2]); pk.vertices[2].v[2] = 0.0f; pk.vertices[2].v[3] = 1.0f; - qcopy(&pk.vertices[3], &data->unk1D0); - pk.vertices[3].v[0] = length * data->unk1D0[3]; + qcopy(&pk.vertices[3], &scoutbot_private_vars->unk1D0); + pk.vertices[3].v[0] = length * scoutbot_private_vars->unk1D0[3]; pk.vertices[3].v[2] += 0.25f; pk.vertices[3].v[3] = 1.0f; draw_geometry_quad(pk.vertices, matrix, 1); @@ -524,20 +525,20 @@ void draw_target_beam(struct Moby *moby) { } draw_geometry_quad(pk.vertices, matrix, 1); - qcopy(&pk.vertices[0], &data->unk1D0); - pk.vertices[0].v[0] = length * data->unk1D0[3]; + qcopy(&pk.vertices[0], &scoutbot_private_vars->unk1D0); + pk.vertices[0].v[0] = length * scoutbot_private_vars->unk1D0[3]; pk.vertices[0].v[2] += -0.25f; pk.vertices[0].v[3] = 1.0f; - qcopy(&pk.vertices[1], &data->unk1E0); - pk.vertices[1].v[0] = length * data->unk1E0[3]; + qcopy(&pk.vertices[1], &scoutbot_private_vars->unk1E0); + pk.vertices[1].v[0] = length * scoutbot_private_vars->unk1E0[3]; pk.vertices[1].v[2] += -0.25f; pk.vertices[1].v[3] = 1.0f; - qcopy(&pk.vertices[2], &data->unk1D0); - pk.vertices[2].v[0] = length * data->unk1D0[3]; + qcopy(&pk.vertices[2], &scoutbot_private_vars->unk1D0); + pk.vertices[2].v[0] = length * scoutbot_private_vars->unk1D0[3]; pk.vertices[2].v[2] += 0.25f; pk.vertices[2].v[3] = 1.0f; - qcopy(&pk.vertices[3], &data->unk1E0); - pk.vertices[3].v[0] = length * data->unk1E0[3]; + qcopy(&pk.vertices[3], &scoutbot_private_vars->unk1E0); + pk.vertices[3].v[0] = length * scoutbot_private_vars->unk1E0[3]; pk.vertices[3].v[2] += 0.25f; pk.vertices[3].v[3] = 1.0f; draw_geometry_quad(pk.vertices, matrix, 1); @@ -555,20 +556,20 @@ void draw_target_beam(struct Moby *moby) { } draw_geometry_quad(pk.vertices, matrix, 1); - qcopy(&pk.vertices[0], &data->unk1E0); - pk.vertices[0].v[0] = length * data->unk1E0[3]; + qcopy(&pk.vertices[0], &scoutbot_private_vars->unk1E0); + pk.vertices[0].v[0] = length * scoutbot_private_vars->unk1E0[3]; pk.vertices[0].v[2] += -0.25f; pk.vertices[0].v[3] = 1.0f; clear_u64_value(&pk.vertices[1]); - pk.vertices[1].v[0] = length * data->unk1D0[3] * 3.0f; + pk.vertices[1].v[0] = length * scoutbot_private_vars->unk1D0[3] * 3.0f; pk.vertices[1].v[2] += D_L08_00161894_lui; pk.vertices[1].v[3] = 1.0f; - qcopy(&pk.vertices[2], &data->unk1E0); - pk.vertices[2].v[0] = length * data->unk1E0[3]; + qcopy(&pk.vertices[2], &scoutbot_private_vars->unk1E0); + pk.vertices[2].v[0] = length * scoutbot_private_vars->unk1E0[3]; pk.vertices[2].v[2] += 0.25f; pk.vertices[2].v[3] = 1.0f; clear_u64_value(&pk.vertices[3]); - pk.vertices[3].v[0] = length * data->unk1D0[3] * 3.0f; + pk.vertices[3].v[0] = length * scoutbot_private_vars->unk1D0[3] * 3.0f; pk.vertices[3].v[2] = 0.0f; pk.vertices[3].v[3] = 1.0f; draw_geometry_quad(pk.vertices, matrix, 1); From 72abe644c07c7b232ec1da75419b9f1cb882e339 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 12:46:46 +0000 Subject: [PATCH 1344/1502] decomp: clarify names in start_camera_blend domain_0_value_1 -> CAMERA_TRANSITION_PHASE_SEED_FROM_SOURCE: The selector transition->mode is the halfword at cam_trans_state (retail 0x001ec8b4), identified as g_nCameraTransitionPhase in the prepared decompilation. Comparison with 1 at 0x001ec8c0/0x001ec8d4 selects the branch that copies source+0x30 into blend or saved orbit position and extracts source rotation (0x001ec8e8-0x001ec92c), or derives orbit angles from source+0x30 and extracts its rotation (0x001ec9a4-0x001ec9bc). Other phases instead transfer existing solver state at 0x001ec9e4-0x001eca30. Thus 1 denotes source-seeding within the camera transition phase domain, separate from the requested kind byte and Hero enums. domain_1_value_0 -> CAMERA_TRANSITION_KIND_BLEND: Retail 0x001eca34 loads requested kind at cam_trans_state+3, 0x001eca4c stores it as active kind at +2, and 0x001eca48 branches on zero. The zero path 0x001eca50-0x001eca88 initializes the authoritative C CameraBlend: clears position/rotation progress, installs configured rates and copies current position/rotation to starting values. The nonzero path initializes CameraOrbit frame count and reciprocal at 0x001eca94-0x001ecac8. Therefore transition->kind == 0 selects the blend solver, not a hero state or Boolean domain. g -> orbit_reference_hero: The authoritative C declares struct Hero *g = &hero. Retail 0x001ec948 forms the hero base, then 0x001ec950/0x001ec964/0x001ec97c load its moby at +0x2080. The moby's +0xC0/+0xD0/+0xE0 basis rows are normalized at 0x001ec95c/0x001ec974/0x001ec98c into the three orbit direction arrays passed to compute_camera_angles at 0x001ec998-0x001ec9b0. This hero supplies the reference basis for the orbit calculation. --- src/camera/start_camera_blend.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/camera/start_camera_blend.c b/src/camera/start_camera_blend.c index 564ff78f14..42e1e79a06 100644 --- a/src/camera/start_camera_blend.c +++ b/src/camera/start_camera_blend.c @@ -17,13 +17,17 @@ extern void extract_matrix_rotation_quaternion(void *, void *) __asm__("func_00 void start_camera_blend(struct UpdateCam *source) __asm__("FUN_001ec8a0"); void start_camera_blend(struct UpdateCam *source) { + enum { + CAMERA_TRANSITION_KIND_BLEND = 0, + CAMERA_TRANSITION_PHASE_SEED_FROM_SOURCE = 1 + }; struct CameraTransition *transition = &cam_trans_state; char orbit_reference_direction[16]; char orbit_yaw_side_direction[16]; char orbit_axis[16]; unsigned char sub; - if (transition->mode == 1) { + if (transition->mode == CAMERA_TRANSITION_PHASE_SEED_FROM_SOURCE) { sub = transition->requested_kind; if (sub == 0) { qcopy(transition->blend.position, &source->pos); @@ -33,11 +37,11 @@ void start_camera_blend(struct UpdateCam *source) { extract_matrix_rotation_quaternion(transition->orbit.saved_rotation, source); capture_camera_orientation(); } else { - struct Hero *g = &hero; + struct Hero *orbit_reference_hero = &hero; - fast_vec_normalize(orbit_reference_direction, &g->moby->rot_row0, 1.0f); - fast_vec_normalize(orbit_yaw_side_direction, &g->moby->rot_row1, 1.0f); - fast_vec_normalize(orbit_axis, &g->moby->rot_row2, 1.0f); + fast_vec_normalize(orbit_reference_direction, &orbit_reference_hero->moby->rot_row0, 1.0f); + fast_vec_normalize(orbit_yaw_side_direction, &orbit_reference_hero->moby->rot_row1, 1.0f); + fast_vec_normalize(orbit_axis, &orbit_reference_hero->moby->rot_row2, 1.0f); /* PreviewCamera.current_camera, reached from this base. */ compute_camera_angles(transition->orbit.angles, &source->pos, @@ -62,7 +66,7 @@ void start_camera_blend(struct UpdateCam *source) { } cam_trans_state_lui = 3; transition->kind = transition->requested_kind; - if (transition->kind == 0) { + if (transition->kind == CAMERA_TRANSITION_KIND_BLEND) { struct CameraBlend *blend = &transition->blend; blend->position_rate = blend->configured_position_rate; From 5bd49cd41bd583c4a31c924fde3f835ee48f1998 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 13:00:30 +0000 Subject: [PATCH 1345/1502] decomp: clarify names in draw_help a -> closing_half_height: Bound source subtracts (frame_half_height-8)*timer/8 from frame_half_height. Retail 0x001fec38/0x001fec4c/0x001fec50/0x001fec84/0x001fec8c computes this vertical extent; 0x001fec94/0x001feca0 passes center_y +/- extent to draw_ui_frame. Original Ghidra case 7 agrees. a -> transition_half_width: Bound source computes (help_state.half_width-32)*timer/8+32. Retail 0x001fea64-0x001feaac computes this from +0x08; 0x001feab8-0x001feac4 uses it as center_x +/- extent and stores frame_half_width at +0x18. Original Ghidra case 3 agrees. b -> closing_half_width: Bound source subtracts (frame_half_width-8)*timer/8 from frame_half_width. Retail 0x001fec48/0x001fec58/0x001fec60/0x001fec88/0x001fec90 computes this horizontal extent; 0x001fec98/0x001feca8 passes center_x +/- extent to draw_ui_frame. Original Ghidra case 7 agrees. b -> transition_half_height: Bound source computes (help_state.half_height-32)*timer/8+32. Retail 0x001fea6c-0x001feab0 computes this from +0x0c; 0x001feab4/0x001feac0 forms center_y +/- extent and 0x001feacc stores frame_half_height at +0x1c. Original Ghidra case 3 agrees. domain_0_value_0 -> HELP_INACTIVE: Retail 0x001fe990 loads D_001996D0, the same help_state.state used by the dispatch at 0x001fe9cc-0x001fe9ec; 0x001fe9a0 returns immediately when it is zero. Bound source describes drawing only when a state is active and tests help_state.state == 0 before all rendering. Thus zero is the inactive help rendering state. domain_1_value_4 -> HELP_TEXT_FADE_IN: The comparison reads help_state.state, exactly the selector whose existing local enum defines HELP_TEXT_FADE_IN=4. Retail 0x001feb80-0x001feba0 reloads the same D_001996D0 and tests 4, then builds timer<<29 | 0xFFA888 as the text color passed at 0x001fec0c-0x001fec18. Reuse the established member for the identical state domain. domain_2_value_6 -> HELP_TEXT_FADE_OUT: The comparison reads help_state.state, exactly the selector whose existing local enum defines HELP_TEXT_FADE_OUT=6. Retail 0x001feba4-0x001febc0 tests that same state for 6 and forms (4-timer)<<29 | 0xFFA888, feeding the text renderer at 0x001fec0c-0x001fec18. Reuse the established member for the identical state domain. --- src/ui/help/draw_help.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/ui/help/draw_help.c b/src/ui/help/draw_help.c index 2cb8792295..3cde62de80 100644 --- a/src/ui/help/draw_help.c +++ b/src/ui/help/draw_help.c @@ -36,7 +36,10 @@ void draw_help(void) { HELP_TEXT_FADE_OUT = 6, HELP_FRAME_CLOSING = 7 }; - if (help_state.state == 0) { + enum { + HELP_INACTIVE = 0 + }; + if (help_state.state == HELP_INACTIVE) { return; } if (help_state.started == 0) { @@ -66,16 +69,16 @@ void draw_help(void) { break; case HELP_PROMPT_FRAME_TRANSITION: if (D_0015EF1D_b) { - int a = (help_state.half_width - 0x20) * help_state.timer / 8 + 0x20; - int b = (help_state.half_height - 0x20) * help_state.timer / 8 + 0x20; + int transition_half_width = (help_state.half_width - 0x20) * help_state.timer / 8 + 0x20; + int transition_half_height = (help_state.half_height - 0x20) * help_state.timer / 8 + 0x20; int alpha; - help_state.frame_half_width = a; - help_state.frame_half_height = b; - draw_ui_frame(help_state.center_y - b, - help_state.center_y + b, - help_state.center_x - a, - help_state.center_x + a, + help_state.frame_half_width = transition_half_width; + help_state.frame_half_height = transition_half_height; + draw_ui_frame(help_state.center_y - transition_half_height, + help_state.center_y + transition_half_height, + help_state.center_x - transition_half_width, + help_state.center_x + transition_half_width, 0x60); alpha = (8 - help_state.timer) * 16; if (alpha < 0) { @@ -108,9 +111,9 @@ void draw_help(void) { help_state.center_x - help_state.half_width, help_state.center_x + help_state.half_width, 0x60); - if (help_state.state == 4) { + if (help_state.state == HELP_TEXT_FADE_IN) { col = 0xFFA888 | (help_state.timer << 29); - } else if (help_state.state == 6) { + } else if (help_state.state == HELP_TEXT_FADE_OUT) { col = ((4 - help_state.timer) << 29) | 0xFFA888; } text = help_msgs[help_state.msg].text; @@ -121,15 +124,15 @@ void draw_help(void) { break; case HELP_FRAME_CLOSING: if (D_0015EF1D_b) { - int b = help_state.frame_half_width - + int closing_half_width = help_state.frame_half_width - (help_state.frame_half_width - 8) * help_state.timer / 8; - int a = help_state.frame_half_height - + int closing_half_height = help_state.frame_half_height - (help_state.frame_half_height - 8) * help_state.timer / 8; - draw_ui_frame(help_state.center_y - a, - help_state.center_y + a, - help_state.center_x - b, - help_state.center_x + b, + draw_ui_frame(help_state.center_y - closing_half_height, + help_state.center_y + closing_half_height, + help_state.center_x - closing_half_width, + help_state.center_x + closing_half_width, (8 - help_state.timer) * 12); } break; From 95afb58dfcf5f08de2503f690a01ab83dcca8e89 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 13:00:30 +0000 Subject: [PATCH 1346/1502] decomp: clarify names in update_instance_attachment_points_and_lengths vars -> attachment_points_and_lengths: Source declares vars as struct AttachmentVars *, loads it from instance->pvars, and accesses points, first_length and second_length. Retail 0x0023a334 loads s0 from instance+0x78; 0x0023a35c/0x0023a360 passes it as the output of the four-point transform. Subtractions at 0x0023a36c and 0x0023a380 use s0+0x10 and s0+0x20 relative to s0, and length results are stored at s0+0x40 and s0+0x44 at 0x0023a398/0x0023a39c. The original Ghidra decompilation confirms this same point array and cached-length data flow. --- ...update_instance_attachment_points_and_lengths.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/mobys/update_instance_attachment_points_and_lengths.c b/src/mobys/update_instance_attachment_points_and_lengths.c index 54c0e7f9de..e8ff214b69 100644 --- a/src/mobys/update_instance_attachment_points_and_lengths.c +++ b/src/mobys/update_instance_attachment_points_and_lengths.c @@ -21,14 +21,14 @@ void update_instance_attachment_points_and_lengths(struct Moby *instance) __asm_ void update_instance_attachment_points_and_lengths(struct Moby *instance) { u8 offsets[0x30]; - struct AttachmentVars *vars; - vars = (struct AttachmentVars *)instance->pvars; + struct AttachmentVars *attachment_points_and_lengths; + attachment_points_and_lengths = (struct AttachmentVars *)instance->pvars; *(struct Pair64 *)(offsets + 0x20) = *(struct Pair64 *)attachment_point_indices; - transform_scaled_vertex_batch(instance, 4, offsets + 0x20, vars); - fast_vec_sub(offsets, vars->points[1], vars); - fast_vec_sub(offsets + 0x10, vars->points[2], vars); - vars->first_length = fast_vec_length(offsets); - vars->second_length = fast_vec_length(offsets + 0x10); + transform_scaled_vertex_batch(instance, 4, offsets + 0x20, attachment_points_and_lengths); + fast_vec_sub(offsets, attachment_points_and_lengths->points[1], attachment_points_and_lengths); + fast_vec_sub(offsets + 0x10, attachment_points_and_lengths->points[2], attachment_points_and_lengths); + attachment_points_and_lengths->first_length = fast_vec_length(offsets); + attachment_points_and_lengths->second_length = fast_vec_length(offsets + 0x10); } extern __typeof__(update_instance_attachment_points_and_lengths) func_0023A318 From c436b7c11fd52aa3dfdef66abeeee40678a847d1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 13:21:54 +0000 Subject: [PATCH 1347/1502] decomp: clarify names in create_class_5c3_moby domain_0_value_0 -> CLASS_5C3_STATE_INITIAL: Retail 0x002d419c-0x002d41a8 allocates class 0x5C3 and retains the new moby in s1. The allocation-success branch at 0x002d41ac guards initialization; 0x002d41d8 (sb zero,0x20(s1)) explicitly selects its state before the created object is returned at 0x002d4244. Authoritative typed C identifies +0x20 as MOBY(moby)->state. Thus zero is the initial state selected for this class during creation, without claiming any later gameplay behavior. --- src/overlays/shared/hero/create_class_5c3_moby.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/create_class_5c3_moby.c b/src/overlays/shared/hero/create_class_5c3_moby.c index 4b4bd73371..b7a1ef442d 100644 --- a/src/overlays/shared/hero/create_class_5c3_moby.c +++ b/src/overlays/shared/hero/create_class_5c3_moby.c @@ -18,6 +18,9 @@ char *create_class_5c3_moby(int source_item_moby, float initial_rotation_z, float initial_rotation_y) { + enum { + CLASS_5C3_STATE_INITIAL = 0 + }; char *moby = (char *)create_moby(0x5C3); if (moby != 0) { char *moby_vars = ((char *)MOBY(moby)->pvars); @@ -26,7 +29,7 @@ char *create_class_5c3_moby(int source_item_moby, MOBY(moby)->visible = 1; MOBY(moby)->rot.z = initial_rotation_z; MOBY(moby)->rot.y = initial_rotation_y; - MOBY(moby)->state = 0; + MOBY(moby)->state = CLASS_5C3_STATE_INITIAL; *(int *)moby_vars = source_item_moby; qcopy(&MOBY(moby)->pos, initial_position); *(float *)(moby_vars + 0x10) = frame_time * 30.0f * 0.7f; From 8d277b724a546ded9021474d90e8901c83d6f5c0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 13:21:55 +0000 Subject: [PATCH 1348/1502] decomp: clarify names in spawn_on_path domain_0_value_1 -> AMMO_PICKUP_WAIT_FOR_COLLECTION: Retail 0x002c52ec loads ItemDef.ammo_pickup_cls (+0x3A of the weapon-indexed 0x4C entry), 0x002c52f8 creates that ammunition pickup, and 0x002c5328 stores 1 to its Moby.state at +0x31 (a1 loaded with 1 at 0x002c5308). In the authoritative weapon_ammo.c snapshot c766df9d341a88ac6b31ab86b6ef135cda11a24a0d5a917c374ffadc6aa5d358, devestator_ammo_update explicitly names this same pickup state AMMO_PICKUP_WAIT_FOR_COLLECTION = 1. Its branch waits for the timer and velocity to settle, checks hero reach and ammunition capacity, adds ammunition and transitions to AMMO_PICKUP_COLLECTED. The spawned object's pvars amount/weapon at +0/+8 and resting_height at +0x28 match that updater's AmmoPickup layout, proving this is the same pickup state domain. Reuse that established member name for this assignment. --- src/overlays/shared/pickups/weapon_ammo.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/pickups/weapon_ammo.c b/src/overlays/shared/pickups/weapon_ammo.c index 3449e50849..27c6472174 100644 --- a/src/overlays/shared/pickups/weapon_ammo.c +++ b/src/overlays/shared/pickups/weapon_ammo.c @@ -91,6 +91,9 @@ int D_L18_001618A8 = 0; unsigned char *spawn_on_path(u128 *a, int b, int c, int d) __asm__("FUN_L00_002c52a8"); unsigned char *spawn_on_path(u128 *spawn_position, int weapon_index, int ammo_amount, int d) { + enum { + AMMO_PICKUP_WAIT_FOR_COLLECTION = 1 + }; unsigned char *spawned_moby = 0; { ItemDef *spawn_config_entry = (ItemDef *)(weapon_index * 0x4C + (u8 *)item_defs_lui); @@ -103,7 +106,7 @@ unsigned char *spawn_on_path(u128 *spawn_position, int weapon_index, int ammo_am MOBY(spawned_moby)->draw_dist = 0xff; moby_vars = *(int **)(spawned_moby + 0x78); MOBY(spawned_moby)->visible = 1; - MOBY(spawned_moby)->state = 1; + MOBY(spawned_moby)->state = AMMO_PICKUP_WAIT_FOR_COLLECTION; MOBY(spawned_moby)->command = 0; qcopy(&MOBY(spawned_moby)->pos, spawn_position); if (ammo_amount == -1) From ed4df50e915298f7fbd03a4beda930c94e6d1cae Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 13:21:55 +0000 Subject: [PATCH 1349/1502] decomp: clarify names in spawn_class_221_moby domain_0_value_0 -> CLASS_221_INITIAL_STATE: Retail 0x002c4610 loads class 0x221 for create_moby, 0x002c4624 retains the new instance in s1, and 0x002c4628 bypasses all initialization on NULL. At 0x002c46c8, sb zero,0x20(s1) sets that instance's state to 0 before update_entity at 0x002c46dc. Original Ghidra *(undefined1 *)(iVar7 + 0x20) = 0 and authoritative C MOBY(spawned_moby)->state = 0 agree: this is the initial state selected by class-0x221 creation, without claiming its handler semantics. --- src/overlays/shared/enemies/bomb_spawner.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/bomb_spawner.c b/src/overlays/shared/enemies/bomb_spawner.c index 1a136654df..ad69885be6 100644 --- a/src/overlays/shared/enemies/bomb_spawner.c +++ b/src/overlays/shared/enemies/bomb_spawner.c @@ -565,6 +565,9 @@ void bomb_spawner_update(struct Moby *moby) { char *spawn_class_221_moby( char *spawning_moby, float *pos, float *launch_velocity, short ang, int spawn_options) { + enum { + CLASS_221_INITIAL_STATE = 0 + }; char *spawned_moby; char *moby_pvars; spawned_moby = create_moby(0x221); @@ -581,7 +584,7 @@ char *spawn_class_221_moby( MOBY(spawned_moby)->update_dist = (*(unsigned char **)(moby_pvars + 0x10))[0x30]; MOBY(spawned_moby)->draw_dist = *(unsigned short *)(*(char **)(moby_pvars + 0x10) + 0x32); MOBY(spawned_moby)->visible = 1; - MOBY(spawned_moby)->state = 0; + MOBY(spawned_moby)->state = CLASS_221_INITIAL_STATE; MOBY(spawned_moby)->scale = *(float *)(((char *)MOBY(spawned_moby)->pclass) + 0x24) * 0.001f; *(int *)(moby_pvars + 0x1C) = spawn_options; From 218b3aaa91430a222ec4ad2d68b050ba57d391ad Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 13:21:55 +0000 Subject: [PATCH 1350/1502] decomp: clarify names in walloper_update domain_0_value_2 -> WALLOPER_STATE_ANIMATION_DRIVEN_EFFECTS: Retail 0x002bb5c4 reads the incoming walloper moby's state byte at s8+0x20; 0x002bb5cc loads 2 and the zero-state path stores it to that identical byte at 0x002bb5ec. The comparison at 0x002bb5d0-0x002bb5d4 dispatches that same state 2 to 0x002bb654. Source already names this selector's case 2 WALLOPER_STATE_ANIMATION_DRIVEN_EFFECTS. Its branch reads the moby's interpolated record, enables arcs and updates alpha at 0x002bb664-0x002bb750, or resets countdowns and blends animation at 0x002bb754-0x002bb78c. Thus the assignment must reuse the existing member of this exact local walloper state domain. --- src/overlays/shared/weapons/walloper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/walloper.c b/src/overlays/shared/weapons/walloper.c index d2db7d00f1..790769c148 100644 --- a/src/overlays/shared/weapons/walloper.c +++ b/src/overlays/shared/weapons/walloper.c @@ -748,7 +748,7 @@ void walloper_update(char *walloper_moby) { } switch (MOBY(walloper_moby)->state) { case WALLOPER_STATE_INITIALIZE: - MOBY(walloper_moby)->state = 2; + MOBY(walloper_moby)->state = WALLOPER_STATE_ANIMATION_DRIVEN_EFFECTS; for (arc_init_index = 0; arc_init_index < 10; arc_init_index++) { D_L00_001DBEC0[arc_init_index] = 0; D_L00_001DBEF0[arc_init_index] = 2; From e60ccafbdaa0c58425a25f04f57b616334fe21ec Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 13:21:55 +0000 Subject: [PATCH 1351/1502] decomp: clarify names in breakable_window_update domain_0_value_1 -> WAIT_FOR_LINKED_MOBY_TRIGGER: Retail 0x002ffd14-0x002ffd20 initializes draw selection and stores 1 to moby+0x20. The same byte is loaded at 0x002ffcdc for dispatch; its case 1 at 0x002ffd24-0x002ffd50 waits on linked moby byte +0xbc or the -1 override. Thus this assignment enters the existing local WAIT_FOR_LINKED_MOBY_TRIGGER case, not the unrelated TRUE domain. domain_1_value_2 -> WAIT_CAMERA_START_DELAY: Retail 0x002ffd70-0x002ffd90 selects 2 in moby+0x20 when hero distance is below 32 and initializes pvars+0x24 with scale_game_frames(30). Dispatch reads that same moby byte at 0x002ffcdc; existing case WAIT_CAMERA_START_DELAY calls the countdown helper at 0x002ffda8-0x002ffdb0 before camera setup. Reuse the same local state member. domain_2_value_4 -> WAIT_FOR_NEARBY_HERO: After spawn_moby_breakup_effect at 0x002ffd94, retail 0x002ffd9c-0x002ffda4 stores 4 to moby+0x20, the byte used for this function's state dispatch. Existing case WAIT_FOR_NEARBY_HERO at 0x0030017c-0x003001a4 waits until distance between moby position and hero D_0013F3D0 is below 16 before updating the cuboid and advancing. This is the identical local enum domain. domain_3_value_3 -> BLEND_CAMERA_TO_HERO: Retail 0x002ffda8-0x002ffdbc stores 3 to the dispatched moby+0x20 byte only after the start countdown expires, then initializes camera setup and pvars blend progress. Existing case BLEND_CAMERA_TO_HERO reads this same state and advances progress at 0x0030005c-0x00300080, interpolates position/rotation at 0x00300148/0x0030015c and applies camera setters at 0x00300164/0x0030016c. Reuse that existing local member. --- src/overlays/l06/mobys/breakable_window.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l06/mobys/breakable_window.c b/src/overlays/l06/mobys/breakable_window.c index 1aa7b08238..15a8192d0e 100644 --- a/src/overlays/l06/mobys/breakable_window.c +++ b/src/overlays/l06/mobys/breakable_window.c @@ -578,7 +578,7 @@ void breakable_window_update(char *moby) { switch ((unsigned char)MOBY(moby)->state) { case INITIALIZE_DRAW_SELECTION: camera_sequence_and_draw_vars[1] = 1; - MOBY(moby)->state = 1; + MOBY(moby)->state = WAIT_FOR_LINKED_MOBY_TRIGGER; break; case WAIT_FOR_LINKED_MOBY_TRIGGER: if ((camera_sequence_and_draw_vars[2] < 0 || @@ -588,11 +588,11 @@ void breakable_window_update(char *moby) { break; } if (vector_distance_xy(moby + 0x10, D_0013F3D0) < 32.0f) { - MOBY(moby)->state = 2; + MOBY(moby)->state = WAIT_CAMERA_START_DELAY; camera_sequence_and_draw_vars[9] = scale_game_frames(30); } else { spawn_moby_breakup_effect(moby); - MOBY(moby)->state = 4; + MOBY(moby)->state = WAIT_FOR_NEARBY_HERO; } break; case WAIT_CAMERA_START_DELAY: @@ -600,7 +600,7 @@ void breakable_window_update(char *moby) { { int state; int base; - MOBY(moby)->state = 3; + MOBY(moby)->state = BLEND_CAMERA_TO_HERO; scripted_camera_sequence_active = 1; D_L06_0015F408 = 0x12; state = camera_sequence_and_draw_vars[5]; From 357da64fd2224218291d43ab7c59f974de7bf792 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 13:22:04 +0000 Subject: [PATCH 1352/1502] decomp: clarify names in homing_spark_draw D_L18_00161EF8 -> l18_homing_spark_quad_colors: In homing_spark_draw, retail 0x002ea3d0-0x002ea3e4 computes gp-0x4d08 (D_L18_00161EF8) plus quad index times four and saves that color-word address. For quad zero, 0x002ea4b4-0x002ea4d4 loads the first word, passes it and its 0xFFFFFF-masked form to the color tween helper with pvars+0x24, then stores the returned color at packet+0x40. For quads 1-3, 0x002ea4d8-0x002ea4e0 copies the indexed word directly to packet color; the four-corner loop advances the color destination by four at 0x002ea4f4/0x002ea4f8. This exactly matches source pkt[0].color[j] interpolation and pkt[i].color[j] indexed reads, proving the level-18 homing spark quad color role while preserving the scalar extern and assembler identity. --- src/overlays/l18/mobys/drek_boss_electric_ball.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l18/mobys/drek_boss_electric_ball.c b/src/overlays/l18/mobys/drek_boss_electric_ball.c index ed555e11c0..8e5d5edd28 100644 --- a/src/overlays/l18/mobys/drek_boss_electric_ball.c +++ b/src/overlays/l18/mobys/drek_boss_electric_ball.c @@ -211,7 +211,7 @@ extern int l18_homing_spark_blend_subtrahend_selector __asm__("D_L18_00161EE8") extern int l18_homing_spark_blend_alpha_factor_selector __asm__("D_L18_00161EEC") __attribute__((sda)); extern int l18_homing_spark_blend_addend_selector __asm__("D_L18_00161EF0") __attribute__((sda)); -extern int D_L18_00161EF8 __attribute__((sda)); +extern int l18_homing_spark_quad_colors __asm__("D_L18_00161EF8") __attribute__((sda)); extern int l18_homing_spark_quad_texture_ids __asm__("D_L18_00161F08") __attribute__((sda)); extern void fast_draw_quad_real(void *, void *, int) __asm__("FUN_001f7d30"); @@ -278,11 +278,11 @@ void homing_spark_draw(char *moby) { pkt[i].uv[j][1] = homing_spark_quad_uvs[j][1]; if (i == 0) { pkt[0].color[j] = - fast_tween_color_c(D_L18_00161EF8 & 0xFFFFFF, - D_L18_00161EF8, + fast_tween_color_c(l18_homing_spark_quad_colors & 0xFFFFFF, + l18_homing_spark_quad_colors, *(float *)(homing_spark_private_vars + 0x24)); } else { - pkt[i].color[j] = ((int *)&(*(short *)&D_L18_00161EF8))[i]; + pkt[i].color[j] = ((int *)&(*(short *)&l18_homing_spark_quad_colors))[i]; } qcopy(pkt[i].vtx[j], homing_spark_quad_vertices[i][j]); } From 860def9ee19b65cca814c4f2d000e6c694aa554b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 13:22:04 +0000 Subject: [PATCH 1353/1502] decomp: clarify names in hero_set_state b -> entry_animation_mode: The authoritative hero_set_state(int requested_state,int b) uses b to gate entry animation setup throughout its cases. Retail 0x002166a0 retains a1 in s4; 0x002168d8 skips IDLE animation selection when s4 is zero, while 0x00216900-0x00216930 supplies timing/animation to set_hero_animation at 0x00219f84. DYING similarly tests s4 at 0x00216a18 before animation 0x45; shared jump setup tests it at 0x00218fb0; held-item attack tests it at 0x0021961c before hero and item animations. Original Ghidra param_2 zero tests corroborate these flows. At 0x002166b0-0x002166b8 and 0x002166c4-0x002166dc the same integer must equal 2 to pass death-mode/special transition locks, proving a mode rather than merely a Boolean animation flag. --- src/overlays/l03/hero/hero_set_state.c | 114 ++++++++++++------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/src/overlays/l03/hero/hero_set_state.c b/src/overlays/l03/hero/hero_set_state.c index 83ef216f81..a5de3e4d27 100644 --- a/src/overlays/l03/hero/hero_set_state.c +++ b/src/overlays/l03/hero/hero_set_state.c @@ -68,17 +68,17 @@ extern int hero_set_state(int, int) __asm__("FUN_L03_00216648"); extern char level03_hero_trail_jump_velocity_keys[] __asm__("D_L03_0017C020"); extern char level03_hero_water_surface_jump_velocity_keys[] __asm__("D_L03_0017C060"); -int hero_set_state(int requested_state, int b) { +int hero_set_state(int requested_state, int entry_animation_mode) { int previous_state_step; char *moby; int old20A7; { struct Hero *p = &hero; if (p->state.control_mode == 0x14 && - (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || entry_animation_mode != 2)) return 0; } - if ((D_L03_0015F5C4 == 2 || D_L03_0015F5C4 == 6) && b != 2) + if ((D_L03_0015F5C4 == 2 || D_L03_0015F5C4 == 6) && entry_animation_mode != 2) return 0; { struct Hero *p = &hero; @@ -150,7 +150,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; q->rand_timer.range = 0x68; } - if (b) { + if (entry_animation_mode) { if (get_hero_idle_animation_index(0) == 0x54) { set_hero_animation( get_hero_idle_animation_index(0), 0, (float)scale_game_frames(0x12)); @@ -166,7 +166,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; clear_u64_value(&p->motion.momentum); p->rand_timer.range = 0x68; - if (b) { + if (entry_animation_mode) { if (get_hero_idle_animation_index(0) == 0x54) { set_hero_animation( get_hero_idle_animation_index(0), 0, (float)scale_game_frames(0x12)); @@ -192,7 +192,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x14; p->unk2284 = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0x45, 0, (float)scale_game_frames(0xC)); break; } @@ -203,7 +203,7 @@ int hero_set_state(int requested_state, int b) { p->health.hp = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); FUN_L00_0025f730(&p->motion.momentum, frame_time * 3.5f); - if (b) + if (entry_animation_mode) set_hero_animation(0x7C, 0, (float)scale_game_frames(0xC)); break; } @@ -219,7 +219,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->unk6A0 = 0; p->unk690 = p->motion.pos.f[2] - p->unk69C; - if (b) + if (entry_animation_mode) set_hero_animation(0x74, 0, (float)scale_game_frames(0xB)); break; } @@ -241,7 +241,7 @@ int hero_set_state(int requested_state, int b) { q->rand_timer.range = 0x68; q->unk8E0 = 0; n = scale_game_frames(0xC); - if (b) + if (entry_animation_mode) set_hero_animation(0x3B, 0, (float)n); } break; @@ -262,7 +262,7 @@ int hero_set_state(int requested_state, int b) { n = scale_game_frames(0xB); if (p->state.prev == 0x33) n = scale_game_frames(0xF); - if (b) + if (entry_animation_mode) set_hero_animation(0x3D, 0, (float)n); break; } @@ -279,7 +279,7 @@ int hero_set_state(int requested_state, int b) { t = -2; if (p->state.prev != 0x35) t = n; - if (b) + if (entry_animation_mode) set_hero_animation(0x3C, 0, (float)t); break; } @@ -352,7 +352,7 @@ int hero_set_state(int requested_state, int b) { s->motion.momentum.f[2] = 0.0f; FUN_L00_0025f730(&s->motion.momentum, frame_time * 5.5f); s->rand_timer.range = 0x68; - if (b) + if (entry_animation_mode) set_hero_animation(0x3A, 0, (float)scale_game_frames(0x16)); } break; @@ -376,7 +376,7 @@ int hero_set_state(int requested_state, int b) { int t = scale_game_frames(0x4D); struct Hero *q = &hero; q->invulnerable_frames = t; - if (b) { + if (entry_animation_mode) { if (q->state.current == 0x75) { set_hero_animation(0x70, 3, -3.0f); } else { @@ -400,7 +400,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->drown_sink_speed = 0; p->unk698 = scale_game_frames(0x2D); p->rand_timer.range = 0x68; - if (b) + if (entry_animation_mode) set_hero_animation(0x65, 0, (float)scale_game_frames(0x11)); break; } @@ -440,7 +440,7 @@ int hero_set_state(int requested_state, int b) { v = (char *)&hero.motion.momentum; qcopy(v, v - 0x40); } - if (b) + if (entry_animation_mode) set_hero_animation(0x5F, 0, (float)scale_game_frames(0xA)); break; } @@ -451,7 +451,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->health.hp = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0x80, 0, (float)scale_game_frames(0xA)); break; } @@ -463,7 +463,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&D_L03_0015F688 = scale_game_frames(0x3C); if (p->unk20AA == 0) { t = get_hero_idle_animation_index(1); - if (p->moby->prev_seq != t && b) { + if (p->moby->prev_seq != t && entry_animation_mode) { set_hero_animation(t, 0, (float)scale_game_frames(0x12)); } } @@ -552,7 +552,7 @@ int hero_set_state(int requested_state, int b) { scale_game_frames(5) < u->rail_land_frames) n = scale_game_frames(0xD); } - if (b) { + if (entry_animation_mode) { struct Hero *v = &hero; set_hero_animation(v->state.step + 3, D_L03_0015F6D8[v->state.step], (float)n); } @@ -568,7 +568,7 @@ int hero_set_state(int requested_state, int b) { p->item_use_locked = 1; if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); - if (b) { + if (entry_animation_mode) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { @@ -587,7 +587,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; fill_transfer_words((char *)p + 0x9D0, 0, 0x20); qcopy(&p->motion.momentum, &p->motion.displacement); - if (b) + if (entry_animation_mode) set_hero_animation(0x64, 0, (float)scale_game_frames(0xF)); break; } @@ -609,7 +609,7 @@ int hero_set_state(int requested_state, int b) { } return 0; } - if (b) { + if (entry_animation_mode) { struct Hero *q = &hero; float d = q->anim_frame; int id = 6; @@ -626,7 +626,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = gravity_length_xy((float *)v); qcopy(&p->motion.momentum, v); - if (b) { + if (entry_animation_mode) { int id = 6; float d = p->anim_frame; if (return_hero_animation_id_unchanged(MOBY(moby)->seq) == 4 && 3.0f < d && d < 16.0f) @@ -653,7 +653,7 @@ int hero_set_state(int requested_state, int b) { FUN_L00_0025f730(&q->motion.momentum, frame_time * 7.0f); if (frame_time * 3.5f < q->motion.forward_speed) allocate_hero_voice_for_entry(0xC, 0); - if (b) { + if (entry_animation_mode) { if (q->moby->seq == get_hero_idle_animation_index(0)) { set_hero_animation(0xD, 2, (float)scale_game_frames(9)); } else { @@ -680,7 +680,7 @@ int hero_set_state(int requested_state, int b) { } p->motion.move_yaw = fast_arc_tan(p->grapple_target->pos.x - p->motion.pos.f[0], p->grapple_target->pos.y - p->motion.pos.f[1]); - if (b) { + if (entry_animation_mode) { set_hero_animation(0x2F, 2, (float)scale_game_frames(5)); hero_queue_sequence(0xA, 0xE); } @@ -693,7 +693,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->grapple_pull_speed = 0; p->grapple_pull_ending = 0; p->item_use_locked = 1; - if (b) + if (entry_animation_mode) set_hero_animation(0x30, 1, (float)scale_game_frames(0xA)); break; } @@ -705,7 +705,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->grapple_pull_speed = 0; p->grapple_pull_ending = 0; p->tether_radius = fast_vec_dist(&p->motion.pos, &p->grapple_target->pos); - if (b) + if (entry_animation_mode) set_hero_animation(0x30, 1, (float)scale_game_frames(5)); break; } @@ -761,7 +761,7 @@ int hero_set_state(int requested_state, int b) { } else if (q->state.prev_control_mode == 2) { q->swing_gravity = q->fall_state_gravity; } - if (b) { + if (entry_animation_mode) { set_hero_animation(0x34, 0, (float)scale_game_frames(0xB)); { struct Hero *r = &hero; @@ -777,7 +777,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 7; clear_u64_value(&p->motion.rot_spring_vel); qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0xB, 0, (float)scale_game_frames(0xF)); break; } @@ -789,7 +789,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->past_apex = 0; p->rise_fall_land_frames = 0; p->rise_fall_gravity = frame_time_sq * 100.0f; - if (b) + if (entry_animation_mode) set_hero_animation(0x2A, 0, (float)scale_game_frames(6)); break; } @@ -830,7 +830,7 @@ int hero_set_state(int requested_state, int b) { p->unk4F0 = p->smoothed_ground_z; } p->item_select_blocked = 1; - if (b) { + if (entry_animation_mode) { if (frame_time * 3.5f < p->motion.flat_speed) { set_hero_animation(0x20, 0, (float)scale_game_frames(9)); } else { @@ -845,7 +845,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0xD; p->item_select_blocked = 1; p->rand_timer.range = 0x68; - if (b) + if (entry_animation_mode) set_hero_animation(0x21, 0, (float)scale_game_frames(6)); break; } @@ -854,7 +854,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 3; p->unk2284 = 0xD; p->item_select_blocked = 1; - if (b) + if (entry_animation_mode) set_hero_animation(0x24, 0, (float)scale_game_frames(6)); break; } @@ -863,7 +863,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 3; p->unk2284 = 0xD; p->item_select_blocked = 1; - if (b) + if (entry_animation_mode) set_hero_animation(0x25, 0, (float)scale_game_frames(6)); break; } @@ -872,7 +872,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 2; p->unk2284 = 0; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0xB, 0, (float)scale_game_frames(0xC)); break; } @@ -896,7 +896,7 @@ int hero_set_state(int requested_state, int b) { q->rand_timer.range = 0x68; q->state.step = 0; qcopy(&q->motion.velocity, &q->motion.resolved_velocity); - if (b) { + if (entry_animation_mode) { if (q->vehicle_mode == 3) { set_hero_animation(6, 0, (float)scale_game_frames(8)); return 1; @@ -922,7 +922,7 @@ int hero_set_state(int requested_state, int b) { scale_hero_motion(frame_time * 4.5f / p->motion.speed_xy); } qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) { + if (entry_animation_mode) { set_hero_animation(0x13, 0, (float)animation_timing_value); } break; @@ -937,7 +937,7 @@ int hero_set_state(int requested_state, int b) { scale_hero_motion(frame_time * 4.5f / p->motion.speed_xy); } qcopy(&p->motion.velocity, &p->motion.displacement); - if (b) { + if (entry_animation_mode) { set_hero_animation(0x13, 0, (float)animation_timing); } break; @@ -1246,7 +1246,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; if (q->fall_start_distance == 0.0f) q->fall_start_distance = q->unk430 * 1.5f; - if (b) { + if (entry_animation_mode) { int s = q->state.current; if (s == 7) { set_hero_animation(7, 0, (float)scale_game_frames(5)); @@ -1336,7 +1336,7 @@ int hero_set_state(int requested_state, int b) { update_hero_target_heading(8.0f, 1.0471976f, -1.0f); *(int *)&q->slam_descending = 0; q->items[0].timer = 0xA; - if (b) { + if (entry_animation_mode) { char *m; int n = scale_game_frames(0xB); if (q->state.prev == 0xB && scale_game_frames(0x2A) > q->state.prev_timer) @@ -1373,7 +1373,7 @@ int hero_set_state(int requested_state, int b) { q->saved_item[0] = 0; update_hero_target_heading(14.0f, 0.5235988f, -1.0f); q->unkA7C = q->unkA7C == 0; - if (b) { + if (entry_animation_mode) { int n = scale_game_frames(0xA); if (q->moby->prev_seq == 0x1A) n = scale_game_frames(3); @@ -1388,7 +1388,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; if (((void *)q->items[0].moby) == 0) break; - if (b) { + if (entry_animation_mode) { set_hero_animation(0x67, 4, -1.0f); blend_moby_animation(((void *)q->items[0].moby), 3, 4, -1); } @@ -1419,7 +1419,7 @@ int hero_set_state(int requested_state, int b) { r->attack_record = k; } update_hero_target_heading(5.0f, 0.7853982f, 0.7853982f); - if (b) { + if (entry_animation_mode) { char *m; int j = 0; int n; @@ -1450,7 +1450,7 @@ int hero_set_state(int requested_state, int b) { } case HERO_STATE_ANIMATION_RECOVERY_WITH_JUMP_CANCEL: { struct Hero *q; - if (b) + if (entry_animation_mode) set_hero_animation(0x2C, 7, (float)scale_game_frames(9)); q = &hero; if (q->items[0].item_id == 0xA && ((char *)q->throw_target) != 0) { @@ -1469,7 +1469,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0xA; p->unk2284 = 0; p->ground_speed = frame_time * 9.0f; - if (b) { + if (entry_animation_mode) { char *m; HeroTableRow2C *e = &D_L03_0017BD28[p->attack_record]; int k = e->kind; @@ -1490,7 +1490,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->pushback_yaw = fast_add_rotations(p->motion.rot.f[2], 3.1415927f); p->ground_speed = frame_time * 9.0f; - if (b) + if (entry_animation_mode) set_hero_animation(0x29, 5, (float)scale_game_frames(8)); break; } @@ -1512,7 +1512,7 @@ int hero_set_state(int requested_state, int b) { { struct Hero *q = &hero; q->invulnerable_frames = scale_game_frames(0x4D); - if (b) { + if (entry_animation_mode) { set_hero_animation(0x10, 3, -3.0f); q->moby->anim_time = level03_hero_animation_blend_curves[q->anim_blend_curve] [(q->anim_blend_step)++]; @@ -1524,7 +1524,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 0; p->unk2284 = 0; - if (b) + if (entry_animation_mode) set_hero_animation(0, 0, (float)scale_game_frames(0xE)); break; } @@ -1532,7 +1532,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 0; p->unk2284 = 0; - if (b) { + if (entry_animation_mode) { set_hero_animation(4, 0, (float)scale_game_frames(7)); hero_queue_sequence(0xE, 0x22); } @@ -1543,7 +1543,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 2; p->unk2284 = 0; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(6, 0, (float)scale_game_frames(0xC)); break; } @@ -1554,7 +1554,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(6, 0, (float)scale_game_frames(7)); break; } @@ -1571,7 +1571,7 @@ int hero_set_state(int requested_state, int b) { if (frame_time * 1.5f < planar_speed) hero_base->ground_speed = frame_time * 1.5f; hero_base->unk3B8 = 0; - if (b) + if (entry_animation_mode) set_hero_animation(1, 0, (float)scale_game_frames(8)); } break; @@ -1581,7 +1581,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x14; p->unk2284 = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(3, 0, (float)scale_game_frames(0xC)); break; } @@ -1594,7 +1594,7 @@ int hero_set_state(int requested_state, int b) { FUN_L00_0025f730(&p->motion.velocity, frame_time * 5.0f); hero_change_health(1); p->invulnerable_frames = scale_game_frames(0x4D); - if (b) { + if (entry_animation_mode) { set_hero_animation(2, 3, -3.0f); p->moby->anim_time = level03_hero_animation_blend_curves[p->anim_blend_curve][(p->anim_blend_step)++]; @@ -1615,7 +1615,7 @@ int hero_set_state(int requested_state, int b) { clear_u64_value(&p->motion.velocity); clear_u64_value(&p->motion.displacement); p->motion.velocity.f[2] = frame_time * 10.0f; - if (b) + if (entry_animation_mode) set_hero_animation(0x10, 2, -3.0f); break; } @@ -1667,7 +1667,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->tilt_disabled = 1; p->item_use_locked = 1; - if (b) + if (entry_animation_mode) set_hero_animation(get_hero_idle_animation_index(0), 0, -1.0f); break; } @@ -1678,7 +1678,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->item_use_locked = 1; clear_u64_value(&p->motion.velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0xB, 0, -1.0f); break; } @@ -1702,7 +1702,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x18; p->item_use_locked = 1; cancel_hero_item_animation(); - if (b) + if (entry_animation_mode) set_hero_animation(get_hero_idle_animation_index(0), 0, -1.0f); break; } From 8da764d9f16db291b64598605a696b77a6da0861 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 13:22:04 +0000 Subject: [PATCH 1354/1502] decomp: clarify names in hero_set_state b -> entry_animation_mode: Rename parameter b to entry_animation_mode. Authoritative src/overlays/l15/hero/hero_set_state.c SHA-256 d0baf1f4229ff1f3d6ac0bd30a36e596b2ce520ee6adf98242bfa3fcff0aaefd and prepared original retail Ghidra decompilation AND instructions were reviewed. Original param_2 is retained from a1 in s4 at 0x00216c90. Its zero tests skip optional state-entry animation: IDLE at 0x00216ec8 skips to 0x0021aa18, whereas nonzero reaches get_hero_help_value and set_hero_animation at 0x0021a958; DYING at 0x00217008 similarly gates animation 0x45; shared jump setup at 0x00219558 gates the state-specific animation selections. Source if(b) blocks also gate associated item blends and queued sequences. Value 2 additionally passes the dying-control-mode gate at 0x00216ca0..0x00216ca8 and global transition gate at 0x00216cb4..0x00216ccc. Thus this is an integer entry-animation mode with an override value, not a boolean or an animation ID. The self-call at 0x00217cc8 passes zero then explicitly sets the animation at 0x00217cfc, corroborating suppression of optional entry animation. --- src/overlays/l15/hero/hero_set_state.c | 130 ++++++++++++------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/src/overlays/l15/hero/hero_set_state.c b/src/overlays/l15/hero/hero_set_state.c index 18e9f8abc8..60a746cf1e 100644 --- a/src/overlays/l15/hero/hero_set_state.c +++ b/src/overlays/l15/hero/hero_set_state.c @@ -68,17 +68,17 @@ extern int hero_set_state(int, int) __asm__("FUN_L15_00216c38"); extern char hero_trail_jump_velocity_keys[] __asm__("D_L15_0017C520"); extern char hero_deep_water_jump_velocity_keys[] __asm__("D_L15_0017C560"); -int hero_set_state(int requested_state, int b) { +int hero_set_state(int requested_state, int entry_animation_mode) { int saved_state_step; char *moby; int old20A7; { struct Hero *p = &hero; if (p->state.control_mode == 0x14 && - (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || entry_animation_mode != 2)) return 0; } - if ((D_L15_0015F5C4 == 2 || D_L15_0015F5C4 == 6) && b != 2) + if ((D_L15_0015F5C4 == 2 || D_L15_0015F5C4 == 6) && entry_animation_mode != 2) return 0; { struct Hero *p = &hero; @@ -150,7 +150,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; q->rand_timer.range = 0x68; } - if (b) { + if (entry_animation_mode) { if (get_hero_help_value(0) == 0x54) { set_hero_animation(get_hero_help_value(0), 0, (float)scale_game_frames(0x12)); } else { @@ -165,7 +165,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; clear_u64_value(&p->motion.momentum); p->rand_timer.range = 0x68; - if (b) { + if (entry_animation_mode) { if (get_hero_help_value(0) == 0x54) { set_hero_animation(get_hero_help_value(0), 0, (float)scale_game_frames(0x12)); } else { @@ -190,7 +190,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x14; p->unk2284 = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0x45, 0, (float)scale_game_frames(0xC)); break; } @@ -212,7 +212,7 @@ int hero_set_state(int requested_state, int b) { q->rand_timer.range = 0x68; q->unk8E0 = 0; n = scale_game_frames(0xC); - if (b) + if (entry_animation_mode) set_hero_animation(0x3B, 0, (float)n); } break; @@ -233,7 +233,7 @@ int hero_set_state(int requested_state, int b) { n = scale_game_frames(0xB); if (p->state.prev == 0x33) n = scale_game_frames(0xF); - if (b) + if (entry_animation_mode) set_hero_animation(0x3D, 0, (float)n); break; } @@ -250,7 +250,7 @@ int hero_set_state(int requested_state, int b) { t = -2; if (p->state.prev != 0x35) t = n; - if (b) + if (entry_animation_mode) set_hero_animation(0x3C, 0, (float)t); break; } @@ -323,7 +323,7 @@ int hero_set_state(int requested_state, int b) { s->motion.momentum.f[2] = 0.0f; FUN_L00_0025f730(&s->motion.momentum, frame_time * 5.5f); s->rand_timer.range = 0x68; - if (b) + if (entry_animation_mode) set_hero_animation(0x3A, 0, (float)scale_game_frames(0x16)); } break; @@ -347,7 +347,7 @@ int hero_set_state(int requested_state, int b) { int t = scale_game_frames(0x4D); struct Hero *q = &hero; q->invulnerable_frames = t; - if (b) { + if (entry_animation_mode) { if (q->state.current == 0x75) { set_hero_animation(0x70, 3, -3.0f); } else { @@ -370,7 +370,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->drown_sink_speed = 0; p->unk698 = scale_game_frames(0x2D); p->rand_timer.range = 0x68; - if (b) + if (entry_animation_mode) set_hero_animation(0x65, 0, (float)scale_game_frames(0x11)); break; } @@ -410,7 +410,7 @@ int hero_set_state(int requested_state, int b) { v = (char *)&hero.motion.momentum; qcopy(v, v - 0x40); } - if (b) + if (entry_animation_mode) set_hero_animation(0x5F, 0, (float)scale_game_frames(0xA)); break; } @@ -421,7 +421,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->health.hp = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0x80, 0, (float)scale_game_frames(0xA)); break; } @@ -433,7 +433,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&D_L15_0015F688 = scale_game_frames(0x3C); if (p->unk20AA == 0) { t = get_hero_help_value(1); - if (p->moby->prev_seq != t && b) { + if (p->moby->prev_seq != t && entry_animation_mode) { set_hero_animation(t, 0, (float)scale_game_frames(0x12)); } } @@ -522,7 +522,7 @@ int hero_set_state(int requested_state, int b) { scale_game_frames(5) < u->rail_land_frames) n = scale_game_frames(0xD); } - if (b) { + if (entry_animation_mode) { struct Hero *v = &hero; set_hero_animation(v->state.step + 3, D_L15_0015F6D8[v->state.step], (float)n); } @@ -538,7 +538,7 @@ int hero_set_state(int requested_state, int b) { p->item_use_locked = 1; if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); - if (b) { + if (entry_animation_mode) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { @@ -557,7 +557,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; fill_transfer_words((char *)p + 0x9D0, 0, 0x20); qcopy(&p->motion.momentum, &p->motion.displacement); - if (b) + if (entry_animation_mode) set_hero_animation(0x64, 0, (float)scale_game_frames(0xF)); break; } @@ -578,7 +578,7 @@ int hero_set_state(int requested_state, int b) { } return 0; } - if (b) { + if (entry_animation_mode) { struct Hero *q = &hero; float d = q->anim_frame; int id = 6; @@ -595,7 +595,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = gravity_length_xy((float *)v); qcopy(&p->motion.momentum, v); - if (b) { + if (entry_animation_mode) { int id = 6; float d = p->anim_frame; if (return_hero_animation_id_unchanged(MOBY(moby)->seq) == 4 && 3.0f < d && d < 16.0f) @@ -622,7 +622,7 @@ int hero_set_state(int requested_state, int b) { FUN_L00_0025f730(&q->motion.momentum, frame_time * 7.0f); if (frame_time * 3.5f < q->motion.forward_speed) allocate_hero_voice_for_entry(0xC, 0); - if (b) { + if (entry_animation_mode) { if (q->moby->seq == get_hero_help_value(0)) { set_hero_animation(0xD, 2, (float)scale_game_frames(9)); } else { @@ -649,7 +649,7 @@ int hero_set_state(int requested_state, int b) { } p->motion.move_yaw = fast_arc_tan(p->grapple_target->pos.x - p->motion.pos.f[0], p->grapple_target->pos.y - p->motion.pos.f[1]); - if (b) { + if (entry_animation_mode) { set_hero_animation(0x2F, 2, (float)scale_game_frames(5)); hero_queue_sequence(0xA, 0xE); } @@ -662,7 +662,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->grapple_pull_speed = 0; p->grapple_pull_ending = 0; p->item_use_locked = 1; - if (b) + if (entry_animation_mode) set_hero_animation(0x30, 1, (float)scale_game_frames(0xA)); break; } @@ -674,7 +674,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->grapple_pull_speed = 0; p->grapple_pull_ending = 0; p->tether_radius = fast_vec_dist(&p->motion.pos, &p->grapple_target->pos); - if (b) + if (entry_animation_mode) set_hero_animation(0x30, 1, (float)scale_game_frames(5)); break; } @@ -730,7 +730,7 @@ int hero_set_state(int requested_state, int b) { } else if (q->state.prev_control_mode == 2) { q->swing_gravity = q->fall_state_gravity; } - if (b) { + if (entry_animation_mode) { set_hero_animation(0x34, 0, (float)scale_game_frames(0xB)); { struct Hero *r = &hero; @@ -746,7 +746,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 7; clear_u64_value(&p->motion.rot_spring_vel); qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0xB, 0, (float)scale_game_frames(0xF)); break; } @@ -758,7 +758,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->past_apex = 0; p->rise_fall_land_frames = 0; p->rise_fall_gravity = frame_time_sq * 100.0f; - if (b) + if (entry_animation_mode) set_hero_animation(0x2A, 0, (float)scale_game_frames(6)); break; } @@ -773,7 +773,7 @@ int hero_set_state(int requested_state, int b) { p->unk4F0 = p->smoothed_ground_z; } p->item_select_blocked = 1; - if (b) { + if (entry_animation_mode) { if (frame_time * 3.5f < p->motion.flat_speed) { set_hero_animation(0x20, 0, (float)scale_game_frames(9)); } else { @@ -788,7 +788,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0xD; p->item_select_blocked = 1; p->rand_timer.range = 0x68; - if (b) + if (entry_animation_mode) set_hero_animation(0x21, 0, (float)scale_game_frames(6)); break; } @@ -797,7 +797,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 3; p->unk2284 = 0xD; p->item_select_blocked = 1; - if (b) + if (entry_animation_mode) set_hero_animation(0x24, 0, (float)scale_game_frames(6)); break; } @@ -806,7 +806,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 3; p->unk2284 = 0xD; p->item_select_blocked = 1; - if (b) + if (entry_animation_mode) set_hero_animation(0x25, 0, (float)scale_game_frames(6)); break; } @@ -815,7 +815,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 2; p->unk2284 = 0; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0xB, 0, (float)scale_game_frames(0xC)); break; } @@ -839,7 +839,7 @@ int hero_set_state(int requested_state, int b) { q->rand_timer.range = 0x68; q->state.step = 0; qcopy(&q->motion.velocity, &q->motion.resolved_velocity); - if (b) { + if (entry_animation_mode) { if (q->vehicle_mode == 3) { set_hero_animation(6, 0, (float)scale_game_frames(8)); return 1; @@ -865,7 +865,7 @@ int hero_set_state(int requested_state, int b) { scale_hero_motion(frame_time * 4.5f / p->motion.speed_xy); } qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) { + if (entry_animation_mode) { set_hero_animation(0x13, 0, (float)animation_blend_selector); } break; @@ -880,7 +880,7 @@ int hero_set_state(int requested_state, int b) { scale_hero_motion(frame_time * 4.5f / p->motion.speed_xy); } qcopy(&p->motion.velocity, &p->motion.displacement); - if (b) { + if (entry_animation_mode) { set_hero_animation(0x13, 0, (float)animation_blend_selector); } break; @@ -1226,7 +1226,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; if (q->fall_start_distance == 0.0f) q->fall_start_distance = q->unk430 * 1.5f; - if (b) { + if (entry_animation_mode) { int s = q->state.current; if (s == 7) { set_hero_animation(7, 0, (float)scale_game_frames(5)); @@ -1320,7 +1320,7 @@ int hero_set_state(int requested_state, int b) { update_hero_target_heading(8.0f, 1.0471976f, -1.0f); *(int *)&q->slam_descending = 0; q->items[0].timer = 0xA; - if (b) { + if (entry_animation_mode) { char *m; int n = scale_game_frames(0xB); if (q->state.prev == 0xB && scale_game_frames(0x2A) > q->state.prev_timer) @@ -1357,7 +1357,7 @@ int hero_set_state(int requested_state, int b) { q->saved_item[0] = 0; update_hero_target_heading(14.0f, 0.5235988f, -1.0f); q->unkA7C = q->unkA7C == 0; - if (b) { + if (entry_animation_mode) { int n = scale_game_frames(0xA); if (q->moby->prev_seq == 0x1A) n = scale_game_frames(3); @@ -1372,7 +1372,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; if (((void *)q->items[0].moby) == 0) break; - if (b) { + if (entry_animation_mode) { set_hero_animation(0x67, 4, -1.0f); blend_moby_animation(((void *)q->items[0].moby), 3, 4, -1); } @@ -1403,7 +1403,7 @@ int hero_set_state(int requested_state, int b) { r->attack_record = k; } update_hero_target_heading(5.0f, 0.7853982f, 0.7853982f); - if (b) { + if (entry_animation_mode) { char *m; int j = 0; int n; @@ -1434,7 +1434,7 @@ int hero_set_state(int requested_state, int b) { } case HERO_STATE_ANIMATION_RECOVERY_WITH_JUMP_CANCEL: { struct Hero *q; - if (b) + if (entry_animation_mode) set_hero_animation(0x2C, 7, (float)scale_game_frames(9)); q = &hero; if (q->items[0].item_id == 0xA && ((char *)q->throw_target) != 0) { @@ -1453,7 +1453,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0xA; p->unk2284 = 0; p->ground_speed = frame_time * 9.0f; - if (b) { + if (entry_animation_mode) { char *m; HeroTableRow2C *e = &D_L15_0017C228[p->attack_record]; int k = e->kind; @@ -1474,7 +1474,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->pushback_yaw = fast_add_rotations(p->motion.rot.f[2], 3.1415927f); p->ground_speed = frame_time * 9.0f; - if (b) + if (entry_animation_mode) set_hero_animation(0x29, 5, (float)scale_game_frames(8)); break; } @@ -1496,7 +1496,7 @@ int hero_set_state(int requested_state, int b) { { struct Hero *q = &hero; q->invulnerable_frames = scale_game_frames(0x4D); - if (b) { + if (entry_animation_mode) { set_hero_animation(0x10, 3, -3.0f); q->moby->anim_time = hero_hurt_animation_blend_samples[q->anim_blend_curve][(q->anim_blend_step)++]; @@ -1521,7 +1521,7 @@ int hero_set_state(int requested_state, int b) { r->rand_timer.range = 0x68; r->target_speed = 0.0f; r->ground_speed = 0.0f; - if (b) + if (entry_animation_mode) set_hero_animation(0x71, 0, (float)scale_game_frames(8)); } break; @@ -1535,7 +1535,7 @@ int hero_set_state(int requested_state, int b) { p->collision_off_frames = 0x2710; allocate_hero_voice_for_entry(9, 0); p->rand_timer.range = 0x68; - if (b) + if (entry_animation_mode) set_hero_animation(0x71, 0, (float)scale_game_frames(8)); break; } @@ -1543,7 +1543,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 0; p->unk2284 = 0; - if (b) + if (entry_animation_mode) set_hero_animation(0, 0, (float)scale_game_frames(0xF)); break; } @@ -1563,7 +1563,7 @@ int hero_set_state(int requested_state, int b) { int n = scale_game_frames(7); if (r->state.prev == 0x60) n = scale_game_frames(0xD); - if (b) + if (entry_animation_mode) set_hero_animation(r->attack_record + 9, 1, (float)n); } break; @@ -1572,7 +1572,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 6; p->unk2284 = 0; - if (b) + if (entry_animation_mode) set_hero_animation(0xC, 0, (float)scale_game_frames(8)); break; } @@ -1580,7 +1580,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 6; p->unk2284 = 0; - if (b) + if (entry_animation_mode) set_hero_animation(8, 0, (float)scale_game_frames(8)); break; } @@ -1591,7 +1591,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) { + if (entry_animation_mode) { if (2.5f < p->ground_distance) { set_hero_animation(5, 0, (float)scale_game_frames(8)); } else { @@ -1606,7 +1606,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = vector_length_xy(&p->motion.resolved_velocity); p->unk3B8 = 0; - if (b) + if (entry_animation_mode) set_hero_animation(3, 0x12, (float)scale_game_frames(8)); break; } @@ -1615,7 +1615,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x14; p->unk2284 = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(7, 0, (float)scale_game_frames(0xC)); break; } @@ -1627,7 +1627,7 @@ int hero_set_state(int requested_state, int b) { qcopy(&p->motion.velocity, &p->motion.resolved_velocity); FUN_L00_0025f730(&p->motion.velocity, frame_time * 7.0f); p->invulnerable_frames = scale_game_frames(0x4D); - if (b) { + if (entry_animation_mode) { set_hero_animation(6, 3, -3.0f); p->moby->anim_time = hero_hurt_animation_blend_samples[p->anim_blend_curve][(p->anim_blend_step)++]; @@ -1638,7 +1638,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 0; p->unk2284 = 0; - if (b) + if (entry_animation_mode) set_hero_animation(0, 0, (float)scale_game_frames(0xE)); break; } @@ -1646,7 +1646,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 0; p->unk2284 = 0; - if (b) { + if (entry_animation_mode) { set_hero_animation(4, 0, (float)scale_game_frames(7)); hero_queue_sequence(0xE, 0x22); } @@ -1657,7 +1657,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 2; p->unk2284 = 0; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(6, 0, (float)scale_game_frames(0xC)); break; } @@ -1668,7 +1668,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(6, 0, (float)scale_game_frames(7)); break; } @@ -1685,7 +1685,7 @@ int hero_set_state(int requested_state, int b) { if (frame_time * 1.5f < planar_speed) hero_base->ground_speed = frame_time * 1.5f; hero_base->unk3B8 = 0; - if (b) + if (entry_animation_mode) set_hero_animation(1, 0, (float)scale_game_frames(8)); } break; @@ -1695,7 +1695,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x14; p->unk2284 = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(3, 0, (float)scale_game_frames(0xC)); break; } @@ -1708,7 +1708,7 @@ int hero_set_state(int requested_state, int b) { FUN_L00_0025f730(&p->motion.velocity, frame_time * 5.0f); hero_change_health(1); p->invulnerable_frames = scale_game_frames(0x4D); - if (b) { + if (entry_animation_mode) { set_hero_animation(2, 3, -3.0f); p->moby->anim_time = hero_hurt_animation_blend_samples[p->anim_blend_curve][(p->anim_blend_step)++]; @@ -1729,7 +1729,7 @@ int hero_set_state(int requested_state, int b) { clear_u64_value(&p->motion.velocity); clear_u64_value(&p->motion.displacement); p->motion.velocity.f[2] = frame_time * 10.0f; - if (b) + if (entry_animation_mode) set_hero_animation(0x10, 2, -3.0f); break; } @@ -1780,7 +1780,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->tilt_disabled = 1; p->item_use_locked = 1; - if (b) + if (entry_animation_mode) set_hero_animation(get_hero_help_value(0), 0, -1.0f); break; } @@ -1791,7 +1791,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->item_use_locked = 1; clear_u64_value(&p->motion.velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0xB, 0, -1.0f); break; } @@ -1815,7 +1815,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x18; p->item_use_locked = 1; cancel_hero_item_animation(); - if (b) + if (entry_animation_mode) set_hero_animation(get_hero_help_value(0), 0, -1.0f); break; } From 1adb964314e51068573fd2465e7c0833b88baa3e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 13:41:22 +0000 Subject: [PATCH 1355/1502] overlay: name resolve_hero_pending_path_clearance --- src/overlays/l02/hero/update_hero_state_motion.c | 4 ++-- src/overlays/l05/hero/apply_hero_ground_material_effects.c | 4 ++-- src/overlays/l16/hero/apply_hero_ground_material_effects.c | 4 ++-- src/overlays/shared/hero/hero_frame_update.c | 4 ++-- src/overlays/shared/hero/hero_switch_item.c | 4 ++-- src/overlays/shared/hero/set_hero_animation.c | 4 ++-- .../shared/hero/update_hero_vehicle_attachments_and_effects.c | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/overlays/l02/hero/update_hero_state_motion.c b/src/overlays/l02/hero/update_hero_state_motion.c index e59ecab0a4..43ff4b4739 100644 --- a/src/overlays/l02/hero/update_hero_state_motion.c +++ b/src/overlays/l02/hero/update_hero_state_motion.c @@ -570,7 +570,7 @@ typedef union { f32 f[4]; } V_222270; -extern void FUN_L00_002347c0(void); +extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void FUN_L00_00233810(f32 *, f32 *, f32); extern void FUN_L00_002334d0(f32 *, f32 *, f32); extern s32 coll1_222270(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); @@ -593,7 +593,7 @@ s32 resolve_hero_position_collisions(s32 mode) { qcopy(&pre_collision_position, &hero.motion.pos.q); clear_u64_value(&collision_probe_offset); if (hero.path_constrain_pending != 0) { - FUN_L00_002347c0(); + resolve_hero_pending_path_clearance(); hero.path_constrain_pending = 0; } if (hero.state.control_mode != 0x11) { diff --git a/src/overlays/l05/hero/apply_hero_ground_material_effects.c b/src/overlays/l05/hero/apply_hero_ground_material_effects.c index 3407b9679d..cd85b6bd2a 100644 --- a/src/overlays/l05/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l05/hero/apply_hero_ground_material_effects.c @@ -381,7 +381,7 @@ typedef union { f32 f[4]; } V_2133a8; -extern void FUN_L00_002347c0(void); +extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); extern void FUN_L00_00233810(void *, void *, f32); extern void FUN_L00_002334d0(void *, void *, f32); @@ -405,7 +405,7 @@ s32 resolve_hero_position_collisions(s32 mode) { qcopy(&initial_position, &hero.motion.pos.q); clear_u64_value(&collision_query_offset); if (hero.path_constrain_pending != 0) { - FUN_L00_002347c0(); + resolve_hero_pending_path_clearance(); hero.path_constrain_pending = 0; } if (hero.state.control_mode != 0x11) { diff --git a/src/overlays/l16/hero/apply_hero_ground_material_effects.c b/src/overlays/l16/hero/apply_hero_ground_material_effects.c index 3af666de02..a0b279e176 100644 --- a/src/overlays/l16/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l16/hero/apply_hero_ground_material_effects.c @@ -398,7 +398,7 @@ typedef union { f32 f[4]; } V_2133a8; -extern void FUN_L00_002347c0(void); +extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); extern void FUN_L00_00233810(void *, void *, f32); extern void FUN_L00_002334d0(void *, void *, f32); @@ -422,7 +422,7 @@ s32 resolve_hero_position_collisions(s32 mode) { qcopy(&pre_collision_position, &hero.motion.pos.q); clear_u64_value(&collision_position_offset); if (hero.path_constrain_pending != 0) { - FUN_L00_002347c0(); + resolve_hero_pending_path_clearance(); hero.path_constrain_pending = 0; } if (hero.state.control_mode != 0x11) { diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index fc1345dfe4..b4e811a17e 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -1340,7 +1340,7 @@ typedef union { f32 f[4]; } V_233940; -extern void FUN_L00_002347c0(void); +extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void FUN_L00_00233810(void *, void *, f32); extern void FUN_L00_002334d0(void *, void *, f32); extern s32 coll_sphere(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); @@ -1362,7 +1362,7 @@ s32 resolve_hero_position_with_collision_queries(s32 mode) { qcopy(&pre_collision_position, &hero.motion.pos.q); clear_u64_value(&collision_query_offset); if (hero.path_constrain_pending != 0) { - FUN_L00_002347c0(); + resolve_hero_pending_path_clearance(); hero.path_constrain_pending = 0; } if (hero.state.control_mode != 0x11) { diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 8bf51dbbf5..7a5354c342 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -3651,7 +3651,7 @@ typedef union { f32 f[4]; } V_2133a8; -extern void FUN_L00_002347c0(void); +extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void FUN_L00_00233810(void *, void *, f32); extern void FUN_L00_002334d0(void *, void *, f32); extern s32 coll_sphere(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); @@ -3676,7 +3676,7 @@ s32 resolve_hero_current_position_collisions(s32 mode) { qcopy(&pre_collision_position, &hero.motion.pos.q); clear_u64_value(&collision_probe_offset); if (hero.path_constrain_pending != 0) { - FUN_L00_002347c0(); + resolve_hero_pending_path_clearance(); hero.path_constrain_pending = 0; } if (hero.state.control_mode != 0x11) { diff --git a/src/overlays/shared/hero/set_hero_animation.c b/src/overlays/shared/hero/set_hero_animation.c index 3207f80cb7..0b7511e0ce 100644 --- a/src/overlays/shared/hero/set_hero_animation.c +++ b/src/overlays/shared/hero/set_hero_animation.c @@ -1693,9 +1693,9 @@ extern int resolve_point_path_segment_clearance(int, void *, void *, float) __asm__("FUN_L00_00262030"); /* Sets the short at &hero.unk1F6 to 4 when FUN_L00_00262030 succeeds. */ -void FUN_L00_002347c0(void); +void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); -void FUN_L00_002347c0(void) { +void resolve_hero_pending_path_clearance(void) { struct Hero *hero_path_clearance_state = &hero; if (resolve_point_path_segment_clearance(hero_path_clearance_state->path_constrain_pending, diff --git a/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c b/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c index a619a7e629..c2f63a7542 100644 --- a/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c +++ b/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c @@ -552,7 +552,7 @@ typedef union { } V_22a1d0; extern OvlVec4 coll_hit_pos __asm__("D_L06_001745F0") NOT_SDA; /* position after push-out of the last collision query */ -extern void FUN_L00_002347c0(void); +extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void FUN_L00_00233810(void *, void *, f32); extern void FUN_L00_002334d0(void *, void *, f32); extern s32 coll_sphere(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); @@ -574,7 +574,7 @@ s32 resolve_hero_position_collisions(s32 mode) { qcopy(&pre_collision_position, &hero.motion.pos.q); clear_u64_value(&collision_query_offset); if (hero.path_constrain_pending != 0) { - FUN_L00_002347c0(); + resolve_hero_pending_path_clearance(); hero.path_constrain_pending = 0; } if (hero.state.control_mode != 0x11) { From ade6a403616dcfd8df76d2f72603771814803f4e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:01:14 +0000 Subject: [PATCH 1356/1502] decomp: clarify names in test_dummy_on_hoverboard_update domain_0_value_1 -> HOVERBOARD_DUMMY_STATE_WAIT_FOR_RACE: Retail 0x002d0698 loads 1 and 0x002d06a4 stores it to s3+0x20 after path, heading and speed initialization. The selector loads that exact byte at 0x002d0500 and branches on 1 to 0x002d06a8, which waits for hero control_mode 22. This is the existing local WAIT_FOR_RACE domain member. domain_1_value_2 -> HOVERBOARD_DUMMY_STATE_RACING: Retail 0x002d0728 loads 2 and 0x002d0734 stores it to s3+0x20 after the race-mode gate and motion initialization. The same byte is the switch selector at 0x002d0500; its value 2 enters path following, jump, ground motion and effects at 0x002d07e4. Reuse the local RACING member. domain_2_value_0 -> HOVERBOARD_DUMMY_STATE_INITIALIZE: Retail 0x002d0740-0x002d0748 checks race control mode in the reactivation branch and stores zero to s3+0x20 when race mode has ended. That is the same selector byte loaded at 0x002d0500; zero dispatches to path and position initialization at 0x002d053c. Reuse local INITIALIZE. domain_3_value_2 -> HOVERBOARD_DUMMY_STATE_RACING: Retail 0x002d0750-0x002d07b8 waits beyond 240 scaled frames and tests the camera angle. At 0x002d07d0 it writes s4, which the selector dispatch set to 2 at 0x002d0510, into s3+0x20 while restoring collision. This returns the same moby selector to the existing RACING branch. domain_4_value_0 -> HOVERBOARD_DUMMY_STATE_INITIALIZE: Retail 0x002d07f0-0x002d0800 reads hero control mode, tests against 22 and writes zero to s3+0x20 if racing mode has ended. This exact byte selects the switch at 0x002d0500, with zero entering initialization at 0x002d053c. Reuse the existing local INITIALIZE member. domain_5_value_3 -> HOVERBOARD_DUMMY_STATE_WAIT_FOR_REACTIVATION: Retail hit branch 0x002d0810-0x002d0904 emits explosion/fragments, clears the reactivation timer at s2+0x2F2, loads 3 at 0x002d08e0 and writes it to s3+0x20 at 0x002d08f0 while disabling collision. The selector dispatch sends 3 to the delayed collision-restoration branch at 0x002d0738. Reuse local WAIT_FOR_REACTIVATION. --- src/overlays/l16/mobys/test_dummy_on_hoverboard.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l16/mobys/test_dummy_on_hoverboard.c b/src/overlays/l16/mobys/test_dummy_on_hoverboard.c index c3b20d0994..8251369793 100644 --- a/src/overlays/l16/mobys/test_dummy_on_hoverboard.c +++ b/src/overlays/l16/mobys/test_dummy_on_hoverboard.c @@ -609,7 +609,7 @@ void test_dummy_on_hoverboard_update(unsigned char *moby) { } hoverboard_dummy_data->unk2E8 = random_angle_radians(); hoverboard_dummy_data->unk29 = 0; - MOBY(moby)->state = 1; + MOBY(moby)->state = HOVERBOARD_DUMMY_STATE_WAIT_FOR_RACE; break; } case HOVERBOARD_DUMMY_STATE_WAIT_FOR_RACE: @@ -628,12 +628,12 @@ void test_dummy_on_hoverboard_update(unsigned char *moby) { MOBY(moby)->flags |= 0x8000; } MOBY(moby)->hit_slot = 255; - MOBY(moby)->state = 2; + MOBY(moby)->state = HOVERBOARD_DUMMY_STATE_RACING; } break; case HOVERBOARD_DUMMY_STATE_WAIT_FOR_REACTIVATION: if (hero.state.control_mode != 22) { - MOBY(moby)->state = 0; + MOBY(moby)->state = HOVERBOARD_DUMMY_STATE_INITIALIZE; } else { int count = *(unsigned short *)&hoverboard_dummy_data->unk2F2 + 1; short timer = count; @@ -649,7 +649,7 @@ void test_dummy_on_hoverboard_update(unsigned char *moby) { MOBY(moby)->collision = MOBY(moby)->pclass->collision; MOBY(moby)->flags &= ~0x41; MOBY(moby)->hit_slot = 255; - MOBY(moby)->state = 2; + MOBY(moby)->state = HOVERBOARD_DUMMY_STATE_RACING; } } } @@ -657,7 +657,7 @@ void test_dummy_on_hoverboard_update(unsigned char *moby) { case HOVERBOARD_DUMMY_STATE_RACING: hero_base = ((char *)&hero); if (*(int *)(hero_base + 0x208C) != 22) { - MOBY(moby)->state = 0; + MOBY(moby)->state = HOVERBOARD_DUMMY_STATE_INITIALIZE; break; } if (find_moby_hit(moby, mask, 0)) { @@ -685,7 +685,7 @@ void test_dummy_on_hoverboard_update(unsigned char *moby) { spawn_moby_break_fragments(moby, 0x6FA, 1, 0x6FB, 1, 1, 0); hoverboard_dummy_data->unk2F2 = 0; *(int *)(hero_base + 0x8A8) += 250; - MOBY(moby)->state = 3; + MOBY(moby)->state = HOVERBOARD_DUMMY_STATE_WAIT_FOR_REACTIVATION; MOBY(moby)->collision = 0; MOBY(moby)->flags |= 0x41; break; From 134e1518a9f27b57e48c1e97dc468eecdefd3e8f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:01:14 +0000 Subject: [PATCH 1357/1502] decomp: clarify names in extermitank_update domain_0_value_1 -> EXTERMITANK_FOLLOW_PATH: Retail 003045f8 stores s0=1 to owner s4+0x20 after initializing path pointer +0xd0 and copying the first node at 003045d8-003045ec. The same owner state byte is loaded at 00304404 and value 1 dispatches at 0030440c to 0030469c, the existing EXTERMITANK_FOLLOW_PATH case implementing signed-direction path movement. Reuse its existing local enum member. domain_1_value_2 -> EXTERMITANK_FIRE_PARTICLES: Retail 00304854-00304858 writes 2 to s4+0x20 after hero distance/height/path checks and an unobstructed collision line. That exact owner state byte feeds dispatch 00304404/0030442c to 00304968, existing EXTERMITANK_FIRE_PARTICLES case, which moves on the path and executes particle spawn loops at 00304c94 and 00304f54. This is the same local enum domain, not a hero or control mode. domain_2_value_1 -> EXTERMITANK_FOLLOW_PATH: Retail 00304f98-0030502c exits firing when hero distance, height, path containment or collision-line tests fail; 00305050-00305054 writes 1 to the same owner s4+0x20 state byte dispatched at 00304404/0030440c into 0030469c. The destination is the existing EXTERMITANK_FOLLOW_PATH case with signed path-node movement and no emission loops; reuse that local enum member. --- src/overlays/l05/mobys/extermitank.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l05/mobys/extermitank.c b/src/overlays/l05/mobys/extermitank.c index b8a4e8cf95..94995f5120 100644 --- a/src/overlays/l05/mobys/extermitank.c +++ b/src/overlays/l05/mobys/extermitank.c @@ -231,7 +231,7 @@ void extermitank_update(unsigned char *moby) { extermitank_vars->unkD0 = ((char *)l05_paths[extermitank_vars->unkD4]); extermitank_vars->unkC0 = 1; qcopy(moby + 0x10, extermitank_vars->unkD0 + 0x10); - MOBY(moby)->state = 1; + MOBY(moby)->state = EXTERMITANK_FOLLOW_PATH; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, 0); extermitank_vars->unk94 = D_L05_00161AF8 * D_0015ED6C_gp; @@ -289,7 +289,7 @@ void extermitank_update(unsigned char *moby) { if (collision_line(origin_position, h + 0x50, 2, moby, 0) == 0) { if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, 3); - MOBY(moby)->state = 2; + MOBY(moby)->state = EXTERMITANK_FIRE_PARTICLES; } } } @@ -471,7 +471,7 @@ void extermitank_update(unsigned char *moby) { collision_line(working_position, D_0013E533 + 0xEED, 2, moby, 0) != 0) { if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, 3); - MOBY(moby)->state = 1; + MOBY(moby)->state = EXTERMITANK_FOLLOW_PATH; } { char *g = ((char *)&D_0013F350); From b5bdb5658ae43c90852c4d89d9cb1f8c68df93ab Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:01:14 +0000 Subject: [PATCH 1358/1502] decomp: clarify names in l01_hero_set_state b -> animation_setup_mode: Retail 0x0023cff0 saves second argument a1 in s4. At 0x0023d228, s4==0 skips idle entry animation selection to 0x00240458; otherwise 0x0023d230-0x0023d280 selects get_hero_idle_animation_index(0) and calls set_hero_animation at 0x00240398. The same s4 gating controls dying (0x0023d368), fall (0x0023e664), jump (0x0023f3c4) and paired held-item animation setup (0x0023fa30-0x0023fa58). Original Ghidra uses param_2 for these guards; authoritative C uses b. Retail 0x0023d000-0x0023d028 additionally treats 2 as the override for the restricted state-change gates, proving an integer setup mode rather than a pure boolean. The recursive stop-to-idle call at 0x0023e128 passes a1=0 then sets its animation explicitly at 0x0023e15c; supplied vehicle-entry and item-input callers pass 1 for ordinary entry animation setup. --- src/overlays/l01/hero/hero_set_state.c | 104 ++++++++++++------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/src/overlays/l01/hero/hero_set_state.c b/src/overlays/l01/hero/hero_set_state.c index cc8a7ed6a5..89788d99bb 100644 --- a/src/overlays/l01/hero/hero_set_state.c +++ b/src/overlays/l01/hero/hero_set_state.c @@ -68,17 +68,17 @@ extern int l01_hero_set_state(int, int) __asm__("FUN_L01_0023cf98"); extern char level_01_transform_trail_jump_velocity_keys[] __asm__("D_L01_0017C3A0"); extern char level_01_water_surface_jump_velocity_keys[] __asm__("D_L01_0017C3E0"); -int l01_hero_set_state(int requested_state, int b) { +int l01_hero_set_state(int requested_state, int animation_setup_mode) { int saved_state_step; char *moby; int old20A7; { struct Hero *p = &hero; if (p->state.control_mode == 0x14 && - (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || animation_setup_mode != 2)) return 0; } - if ((cutscene_mode == 2 || cutscene_mode == 6) && b != 2) + if ((cutscene_mode == 2 || cutscene_mode == 6) && animation_setup_mode != 2) return 0; { struct Hero *p = &hero; @@ -150,7 +150,7 @@ int l01_hero_set_state(int requested_state, int b) { struct Hero *q = &hero; q->rand_timer.range = 0x68; } - if (b) { + if (animation_setup_mode) { if (get_hero_idle_animation_index(0) == 0x54) { set_hero_animation( get_hero_idle_animation_index(0), 0, (float)scale_game_frames(0x12)); @@ -166,7 +166,7 @@ int l01_hero_set_state(int requested_state, int b) { p->unk2284 = 0; clear_u64_value(&p->motion.momentum); p->rand_timer.range = 0x68; - if (b) { + if (animation_setup_mode) { if (get_hero_idle_animation_index(0) == 0x54) { set_hero_animation( get_hero_idle_animation_index(0), 0, (float)scale_game_frames(0x12)); @@ -192,7 +192,7 @@ int l01_hero_set_state(int requested_state, int b) { p->state.control_mode = 0x14; p->unk2284 = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (animation_setup_mode) set_hero_animation(0x45, 0, (float)scale_game_frames(0xC)); break; } @@ -203,7 +203,7 @@ int l01_hero_set_state(int requested_state, int b) { p->health.hp = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); FUN_L00_0025f730(&p->motion.momentum, frame_time * 3.5f); - if (b) + if (animation_setup_mode) set_hero_animation(0x7C, 0, (float)scale_game_frames(0xC)); break; } @@ -219,7 +219,7 @@ int l01_hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->unk6A0 = 0; p->unk690 = p->motion.pos.f[2] - p->unk69C; - if (b) + if (animation_setup_mode) set_hero_animation(0x74, 0, (float)scale_game_frames(0xB)); break; } @@ -241,7 +241,7 @@ int l01_hero_set_state(int requested_state, int b) { q->rand_timer.range = 0x68; q->unk8E0 = 0; n = scale_game_frames(0xC); - if (b) + if (animation_setup_mode) set_hero_animation(0x3B, 0, (float)n); } break; @@ -262,7 +262,7 @@ int l01_hero_set_state(int requested_state, int b) { n = scale_game_frames(0xB); if (p->state.prev == 0x33) n = scale_game_frames(0xF); - if (b) + if (animation_setup_mode) set_hero_animation(0x3D, 0, (float)n); break; } @@ -277,7 +277,7 @@ int l01_hero_set_state(int requested_state, int b) { n = scale_game_frames(0x23); if (p->state.prev == 0x35) n = -2; - if (b) + if (animation_setup_mode) set_hero_animation(0x3C, 0, (float)n); break; } @@ -345,7 +345,7 @@ int l01_hero_set_state(int requested_state, int b) { s->motion.momentum.f[2] = 0.0f; FUN_L00_0025f730(&s->motion.momentum, frame_time * 5.5f); s->rand_timer.range = 0x68; - if (b) + if (animation_setup_mode) set_hero_animation(0x3A, 0, (float)scale_game_frames(0x16)); } break; @@ -369,7 +369,7 @@ int l01_hero_set_state(int requested_state, int b) { int t = scale_game_frames(0x4D); struct Hero *q = &hero; q->invulnerable_frames = t; - if (b) { + if (animation_setup_mode) { if (q->state.current == 0x75) { set_hero_animation(0x70, 3, -3.0f); } else { @@ -393,7 +393,7 @@ int l01_hero_set_state(int requested_state, int b) { *(int *)&p->drown_sink_speed = 0; p->unk698 = scale_game_frames(0x2D); p->rand_timer.range = 0x68; - if (b) + if (animation_setup_mode) set_hero_animation(0x65, 0, (float)scale_game_frames(0x11)); break; } @@ -435,7 +435,7 @@ int l01_hero_set_state(int requested_state, int b) { char *v = (char *)&hero.motion.momentum; qcopy(v, v - 0x40); } - if (b) + if (animation_setup_mode) set_hero_animation(0x5F, 0, (float)scale_game_frames(0xA)); break; } @@ -446,7 +446,7 @@ int l01_hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->health.hp = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (animation_setup_mode) set_hero_animation(0x80, 0, (float)scale_game_frames(0xA)); break; } @@ -458,7 +458,7 @@ int l01_hero_set_state(int requested_state, int b) { *(int *)&D_L01_0015F688 = scale_game_frames(0x3C); if (p->unk20AA == 0) { t = get_hero_idle_animation_index(1); - if (p->moby->prev_seq != t && b) { + if (p->moby->prev_seq != t && animation_setup_mode) { set_hero_animation(t, 0, (float)scale_game_frames(0x12)); } } @@ -547,7 +547,7 @@ int l01_hero_set_state(int requested_state, int b) { scale_game_frames(5) < u->rail_land_frames) n = scale_game_frames(0xD); } - if (b) { + if (animation_setup_mode) { struct Hero *v = &hero; set_hero_animation(v->state.step + 3, D_L01_0015F6D8[v->state.step], (float)n); } @@ -563,7 +563,7 @@ int l01_hero_set_state(int requested_state, int b) { p->item_use_locked = 1; if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); - if (b) { + if (animation_setup_mode) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { @@ -582,7 +582,7 @@ int l01_hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; fill_transfer_words((char *)p + 0x9D0, 0, 0x20); qcopy(&p->motion.momentum, &p->motion.displacement); - if (b) + if (animation_setup_mode) set_hero_animation(0x64, 0, (float)scale_game_frames(0xF)); break; } @@ -604,7 +604,7 @@ int l01_hero_set_state(int requested_state, int b) { } return 0; } - if (b) { + if (animation_setup_mode) { struct Hero *q = &hero; float d = q->anim_frame; int id = 6; @@ -621,7 +621,7 @@ int l01_hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = gravity_length_xy((float *)v); qcopy(&p->motion.momentum, v); - if (b) { + if (animation_setup_mode) { int id = 6; float d = p->anim_frame; if (return_hero_animation_id_unchanged(MOBY(moby)->seq) == 4 && 3.0f < d && d < 16.0f) @@ -648,7 +648,7 @@ int l01_hero_set_state(int requested_state, int b) { FUN_L00_0025f730(&q->motion.momentum, frame_time * 7.0f); if (frame_time * 3.5f < q->motion.forward_speed) allocate_hero_voice_for_entry(0xC, 0); - if (b) { + if (animation_setup_mode) { if (q->moby->seq == get_hero_idle_animation_index(0)) { set_hero_animation(0xD, 2, (float)scale_game_frames(9)); } else { @@ -667,7 +667,7 @@ int l01_hero_set_state(int requested_state, int b) { *(int *)&p->past_apex = 0; p->rise_fall_land_frames = 0; p->rise_fall_gravity = frame_time_sq * 100.0f; - if (b) + if (animation_setup_mode) set_hero_animation(0x2A, 0, (float)scale_game_frames(6)); break; } @@ -682,7 +682,7 @@ int l01_hero_set_state(int requested_state, int b) { p->unk4F0 = p->smoothed_ground_z; } p->item_select_blocked = 1; - if (b) { + if (animation_setup_mode) { if (frame_time * 3.5f < p->motion.flat_speed) { set_hero_animation(0x20, 0, (float)scale_game_frames(9)); } else { @@ -697,7 +697,7 @@ int l01_hero_set_state(int requested_state, int b) { p->unk2284 = 0xD; p->item_select_blocked = 1; p->rand_timer.range = 0x68; - if (b) + if (animation_setup_mode) set_hero_animation(0x21, 0, (float)scale_game_frames(6)); break; } @@ -706,7 +706,7 @@ int l01_hero_set_state(int requested_state, int b) { p->state.control_mode = 3; p->unk2284 = 0xD; p->item_select_blocked = 1; - if (b) + if (animation_setup_mode) set_hero_animation(0x24, 0, (float)scale_game_frames(6)); break; } @@ -715,7 +715,7 @@ int l01_hero_set_state(int requested_state, int b) { p->state.control_mode = 3; p->unk2284 = 0xD; p->item_select_blocked = 1; - if (b) + if (animation_setup_mode) set_hero_animation(0x25, 0, (float)scale_game_frames(6)); break; } @@ -724,7 +724,7 @@ int l01_hero_set_state(int requested_state, int b) { p->state.control_mode = 2; p->unk2284 = 0; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (animation_setup_mode) set_hero_animation(0xB, 0, (float)scale_game_frames(0xC)); break; } @@ -748,7 +748,7 @@ int l01_hero_set_state(int requested_state, int b) { q->rand_timer.range = 0x68; q->state.step = 0; qcopy(&q->motion.velocity, &q->motion.resolved_velocity); - if (b) { + if (animation_setup_mode) { if (q->vehicle_mode == 3) { set_hero_animation(6, 0, (float)scale_game_frames(8)); return 1; @@ -774,7 +774,7 @@ int l01_hero_set_state(int requested_state, int b) { scale_hero_motion(frame_time * 4.5f / p->motion.speed_xy); } qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) { + if (animation_setup_mode) { set_hero_animation(0x13, 0, (float)animation_timing_override); } break; @@ -789,7 +789,7 @@ int l01_hero_set_state(int requested_state, int b) { scale_hero_motion(frame_time * 4.5f / p->motion.speed_xy); } qcopy(&p->motion.velocity, &p->motion.displacement); - if (b) { + if (animation_setup_mode) { set_hero_animation(0x13, 0, (float)animation_timing_override); } break; @@ -1098,7 +1098,7 @@ int l01_hero_set_state(int requested_state, int b) { struct Hero *q = &hero; if (q->fall_start_distance == 0.0f) q->fall_start_distance = q->unk430 * 1.5f; - if (b) { + if (animation_setup_mode) { int s = q->state.current; if (s == 7) { set_hero_animation(7, 0, (float)scale_game_frames(5)); @@ -1188,7 +1188,7 @@ int l01_hero_set_state(int requested_state, int b) { update_hero_target_heading(8.0f, 1.0471976f, -1.0f); *(int *)&q->slam_descending = 0; q->items[0].timer = 0xA; - if (b) { + if (animation_setup_mode) { char *m; int n = scale_game_frames(0xB); if (q->state.prev == 0xB && scale_game_frames(0x2A) > q->state.prev_timer) @@ -1226,7 +1226,7 @@ int l01_hero_set_state(int requested_state, int b) { q->saved_item[0] = 0; update_hero_target_heading(14.0f, 0.5235988f, -1.0f); q->unkA7C = q->unkA7C == 0; - if (b) { + if (animation_setup_mode) { int n = scale_game_frames(0xA); if (q->moby->prev_seq == 0x1A) n = scale_game_frames(3); @@ -1241,7 +1241,7 @@ int l01_hero_set_state(int requested_state, int b) { struct Hero *q = &hero; if (((void *)q->items[0].moby) == 0) break; - if (b) { + if (animation_setup_mode) { set_hero_animation(0x67, 4, -1.0f); blend_moby_animation(((void *)q->items[0].moby), 3, 4, -1); } @@ -1272,7 +1272,7 @@ int l01_hero_set_state(int requested_state, int b) { r->attack_record = k; } update_hero_target_heading(5.0f, 0.7853982f, 0.7853982f); - if (b) { + if (animation_setup_mode) { char *m; int j = 0; int n; @@ -1303,7 +1303,7 @@ int l01_hero_set_state(int requested_state, int b) { } case HERO_STATE_ANIMATION_RECOVERY_WITH_JUMP_CANCEL: { struct Hero *q; - if (b) + if (animation_setup_mode) set_hero_animation(0x2C, 7, (float)scale_game_frames(9)); q = &hero; if (q->items[0].item_id == 0xA && ((char *)q->throw_target) != 0) { @@ -1322,7 +1322,7 @@ int l01_hero_set_state(int requested_state, int b) { p->state.control_mode = 0xA; p->unk2284 = 0; p->ground_speed = frame_time * 9.0f; - if (b) { + if (animation_setup_mode) { char *m; HeroTableRow2C *e = &D_L01_0017C0A8[p->attack_record]; int k = e->kind; @@ -1343,7 +1343,7 @@ int l01_hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->pushback_yaw = fast_add_rotations(p->motion.rot.f[2], 3.1415927f); p->ground_speed = frame_time * 9.0f; - if (b) + if (animation_setup_mode) set_hero_animation(0x29, 5, (float)scale_game_frames(8)); break; } @@ -1365,7 +1365,7 @@ int l01_hero_set_state(int requested_state, int b) { { struct Hero *q = &hero; q->invulnerable_frames = scale_game_frames(0x4D); - if (b) { + if (animation_setup_mode) { set_hero_animation(0x10, 3, -3.0f); q->moby->anim_time = level_01_hero_animation_blend_curves[q->anim_blend_curve] [(q->anim_blend_step)++]; @@ -1377,7 +1377,7 @@ int l01_hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 0; p->unk2284 = 0; - if (b) + if (animation_setup_mode) set_hero_animation(0, 0, (float)scale_game_frames(0xE)); break; } @@ -1385,7 +1385,7 @@ int l01_hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 0; p->unk2284 = 0; - if (b) { + if (animation_setup_mode) { set_hero_animation(4, 0, (float)scale_game_frames(7)); hero_queue_sequence(0xE, 0x22); } @@ -1396,7 +1396,7 @@ int l01_hero_set_state(int requested_state, int b) { p->state.control_mode = 2; p->unk2284 = 0; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (animation_setup_mode) set_hero_animation(6, 0, (float)scale_game_frames(0xC)); break; } @@ -1407,7 +1407,7 @@ int l01_hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (animation_setup_mode) set_hero_animation(6, 0, (float)scale_game_frames(7)); break; } @@ -1424,7 +1424,7 @@ int l01_hero_set_state(int requested_state, int b) { if (frame_time * 1.5f < planar_speed) hero_base->ground_speed = frame_time * 1.5f; hero_base->unk3B8 = 0; - if (b) + if (animation_setup_mode) set_hero_animation(1, 0, (float)scale_game_frames(8)); } break; @@ -1434,7 +1434,7 @@ int l01_hero_set_state(int requested_state, int b) { p->state.control_mode = 0x14; p->unk2284 = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (animation_setup_mode) set_hero_animation(3, 0, (float)scale_game_frames(0xC)); break; } @@ -1447,7 +1447,7 @@ int l01_hero_set_state(int requested_state, int b) { FUN_L00_0025f730(&p->motion.velocity, frame_time * 5.0f); hero_change_health(1); p->invulnerable_frames = scale_game_frames(0x4D); - if (b) { + if (animation_setup_mode) { set_hero_animation(2, 3, -3.0f); p->moby->anim_time = level_01_hero_animation_blend_curves[p->anim_blend_curve][(p->anim_blend_step)++]; @@ -1468,7 +1468,7 @@ int l01_hero_set_state(int requested_state, int b) { clear_u64_value(&p->motion.velocity); clear_u64_value(&p->motion.displacement); p->motion.velocity.f[2] = frame_time * 10.0f; - if (b) + if (animation_setup_mode) set_hero_animation(0x10, 2, -3.0f); break; } @@ -1520,7 +1520,7 @@ int l01_hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->tilt_disabled = 1; p->item_use_locked = 1; - if (b) + if (animation_setup_mode) set_hero_animation(get_hero_idle_animation_index(0), 0, -1.0f); break; } @@ -1531,7 +1531,7 @@ int l01_hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->item_use_locked = 1; clear_u64_value(&p->motion.velocity); - if (b) + if (animation_setup_mode) set_hero_animation(0xB, 0, -1.0f); break; } @@ -1555,7 +1555,7 @@ int l01_hero_set_state(int requested_state, int b) { p->state.control_mode = 0x18; p->item_use_locked = 1; cancel_hero_item_animation(); - if (b) + if (animation_setup_mode) set_hero_animation(get_hero_idle_animation_index(0), 0, -1.0f); break; } From 37a3348a7219349c8c65fe56d15e6379d8451925 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:01:14 +0000 Subject: [PATCH 1359/1502] decomp: clarify names in hero_set_state b -> animation_update_mode: b -> animation_update_mode in hero_set_state. Retail 0x0022ffb0 preserves the second int argument a1 in s4. At 0x00230228, zero s4 skips IDLE's conditional animation selection and set_hero_animation; 0x00230368 similarly gates DYING animation, 0x00232388 gates jump animation selection, and 0x00232800 gates paired hero/wrench animation setup. At 0x00233050-0x00233064 it gates hurt animation and subsequent blend-progress initialization. Original Ghidra param_2 zero tests and authoritative C if(b) blocks agree. Retail 0x0022ffc0-0x0022ffc8 and 0x0022ffd4-0x0022ffec additionally require this argument to equal 2 to pass the dying/special transition guards. Thus it is an integer animation-update mode with a special guard override, not a Boolean or animation ID; preserve its int type and all values. --- src/overlays/l14/hero/hero_set_state.c | 104 ++++++++++++------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/src/overlays/l14/hero/hero_set_state.c b/src/overlays/l14/hero/hero_set_state.c index c42130564d..a0836bfe88 100644 --- a/src/overlays/l14/hero/hero_set_state.c +++ b/src/overlays/l14/hero/hero_set_state.c @@ -64,7 +64,7 @@ extern void clear_moby_transform_history(void *o) __asm__("FUN_L00_00262840"); extern int hero_set_state(int, int) __asm__("FUN_L14_0022ff58"); extern char level14_transform_trail_jump_velocity_keys[] __asm__("D_L14_0017C620"); -int hero_set_state(int requested_state, int b) { +int hero_set_state(int requested_state, int animation_update_mode) { int saved_state_step; char *moby; int old20A7; @@ -72,10 +72,10 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->state.control_mode == 0x14 && - (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || animation_update_mode != 2)) return 0; } - if ((D_L14_0015F5C4 == 2 || D_L14_0015F5C4 == 6) && b != 2) + if ((D_L14_0015F5C4 == 2 || D_L14_0015F5C4 == 6) && animation_update_mode != 2) return 0; { struct Hero *p = &hero; @@ -154,7 +154,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; q->rand_timer.range = 0x68; } - if (b) { + if (animation_update_mode) { if (hero_get_gadget_anim_id(0) == 0x54) { set_hero_animation(hero_get_gadget_anim_id(0), 0, (float)scale_game_frames(0x12)); } else { @@ -169,7 +169,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; clear_u64_value(&p->motion.momentum); p->rand_timer.range = 0x68; - if (b) { + if (animation_update_mode) { if (hero_get_gadget_anim_id(0) == 0x54) { set_hero_animation(hero_get_gadget_anim_id(0), 0, (float)scale_game_frames(0x12)); } else { @@ -194,7 +194,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x14; p->unk2284 = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (animation_update_mode) set_hero_animation(0x45, 0, (float)scale_game_frames(0xC)); break; } @@ -205,7 +205,7 @@ int hero_set_state(int requested_state, int b) { p->health.hp = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); FUN_L00_0025f730(&p->motion.momentum, frame_time * 3.5f); - if (b) + if (animation_update_mode) set_hero_animation(0x7C, 0, (float)scale_game_frames(0xC)); break; } @@ -221,7 +221,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->unk6A0 = 0; p->unk690 = p->motion.pos.f[2] - p->unk69C; - if (b) + if (animation_update_mode) set_hero_animation(0x74, 0, (float)scale_game_frames(0xB)); break; } @@ -233,7 +233,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&D_L14_0015F688 = scale_game_frames(0x3C); if (p->unk20AA == 0) { t = hero_get_gadget_anim_id(1); - if (p->moby->prev_seq != t && b) { + if (p->moby->prev_seq != t && animation_update_mode) { set_hero_animation(t, 0, (float)scale_game_frames(0x12)); } } @@ -331,7 +331,7 @@ int hero_set_state(int requested_state, int b) { scale_game_frames(5) < u->rail_land_frames) n = scale_game_frames(0xD); } - if (b) { + if (animation_update_mode) { struct Hero *v = &hero; set_hero_animation(v->state.step + 3, D_L14_0015F6D8[v->state.step], (float)n); } @@ -343,7 +343,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 1; p->unk2284 = 0; - if (b) { + if (animation_update_mode) { if (p->state.prev == 4) { set_hero_animation(0x5E, 2, (float)scale_game_frames(5)); } else { @@ -360,7 +360,7 @@ int hero_set_state(int requested_state, int b) { p->item_use_locked = 1; if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); - if (b) { + if (animation_update_mode) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { @@ -393,7 +393,7 @@ int hero_set_state(int requested_state, int b) { } return 0; } - if (b) { + if (animation_update_mode) { struct Hero *q = &hero; float d = q->anim_frame; int id = 6; @@ -410,7 +410,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = gravity_length_xy((float *)v); qcopy(&p->motion.momentum, v); - if (b) { + if (animation_update_mode) { int id = 6; float d = p->anim_frame; if (return_hero_animation_id_unchanged(MOBY(moby)->seq) == 4 && 3.0f < d && d < 16.0f) @@ -437,7 +437,7 @@ int hero_set_state(int requested_state, int b) { FUN_L00_0025f730(&q->motion.momentum, frame_time * 7.0f); if (frame_time * 3.5f < q->motion.forward_speed) allocate_hero_voice_for_entry(0xC, 0); - if (b) { + if (animation_update_mode) { if (q->moby->seq == hero_get_gadget_anim_id(0)) { set_hero_animation(0xD, 2, (float)scale_game_frames(9)); } else { @@ -464,7 +464,7 @@ int hero_set_state(int requested_state, int b) { } p->motion.move_yaw = fast_arc_tan(p->grapple_target->pos.x - p->motion.pos.f[0], p->grapple_target->pos.y - p->motion.pos.f[1]); - if (b) { + if (animation_update_mode) { set_hero_animation(0x2F, 2, (float)scale_game_frames(5)); hero_queue_sequence(0xA, 0xE); } @@ -477,7 +477,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->grapple_pull_speed = 0; p->grapple_pull_ending = 0; p->item_use_locked = 1; - if (b) + if (animation_update_mode) set_hero_animation(0x30, 1, (float)scale_game_frames(0xA)); break; } @@ -489,7 +489,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->grapple_pull_speed = 0; p->grapple_pull_ending = 0; p->tether_radius = fast_vec_dist(&p->motion.pos, &p->grapple_target->pos); - if (b) + if (animation_update_mode) set_hero_animation(0x30, 1, (float)scale_game_frames(5)); break; } @@ -545,7 +545,7 @@ int hero_set_state(int requested_state, int b) { } else if (q->state.prev_control_mode == 2) { q->swing_gravity = q->fall_state_gravity; } - if (b) { + if (animation_update_mode) { set_hero_animation(0x34, 0, (float)scale_game_frames(0xB)); { struct Hero *r = &hero; @@ -561,7 +561,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 7; clear_u64_value(&p->motion.rot_spring_vel); qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (animation_update_mode) set_hero_animation(0xB, 0, (float)scale_game_frames(0xF)); break; } @@ -573,7 +573,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->past_apex = 0; p->rise_fall_land_frames = 0; p->rise_fall_gravity = frame_time_sq * 100.0f; - if (b) + if (animation_update_mode) set_hero_animation(0x2A, 0, (float)scale_game_frames(6)); break; } @@ -628,7 +628,7 @@ int hero_set_state(int requested_state, int b) { } } } - if (b) { + if (animation_update_mode) { struct Hero *r = &hero; set_hero_animation(r->grind_anim_variant + 0x31, 0, (float)scale_game_frames(6)); } @@ -645,7 +645,7 @@ int hero_set_state(int requested_state, int b) { p->unk4F0 = p->smoothed_ground_z; } p->item_select_blocked = 1; - if (b) { + if (animation_update_mode) { if (frame_time * 3.5f < p->motion.flat_speed) { set_hero_animation(0x20, 0, (float)scale_game_frames(9)); } else { @@ -660,7 +660,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0xD; p->item_select_blocked = 1; p->rand_timer.range = 0x68; - if (b) + if (animation_update_mode) set_hero_animation(0x21, 0, (float)scale_game_frames(6)); break; } @@ -669,7 +669,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 3; p->unk2284 = 0xD; p->item_select_blocked = 1; - if (b) + if (animation_update_mode) set_hero_animation(0x24, 0, (float)scale_game_frames(6)); break; } @@ -678,7 +678,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 3; p->unk2284 = 0xD; p->item_select_blocked = 1; - if (b) + if (animation_update_mode) set_hero_animation(0x25, 0, (float)scale_game_frames(6)); break; } @@ -687,7 +687,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 2; p->unk2284 = 0; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (animation_update_mode) set_hero_animation(0xB, 0, (float)scale_game_frames(0xC)); break; } @@ -711,7 +711,7 @@ int hero_set_state(int requested_state, int b) { q->rand_timer.range = 0x68; q->state.step = 0; qcopy(&q->motion.velocity, &q->motion.resolved_velocity); - if (b) { + if (animation_update_mode) { if (q->vehicle_mode == 3) { set_hero_animation(6, 0, (float)scale_game_frames(8)); return 1; @@ -737,7 +737,7 @@ int hero_set_state(int requested_state, int b) { scale_hero_motion(frame_time * 4.5f / p->motion.speed_xy); } qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) { + if (animation_update_mode) { set_hero_animation(0x13, 0, (float)animation_timing_preset_selector); } break; @@ -752,7 +752,7 @@ int hero_set_state(int requested_state, int b) { scale_hero_motion(frame_time * 4.5f / p->motion.speed_xy); } qcopy(&p->motion.velocity, &p->motion.displacement); - if (b) { + if (animation_update_mode) { set_hero_animation(0x13, 0, (float)animation_timing_selector); } break; @@ -1075,7 +1075,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; if (q->fall_start_distance == 0.0f) q->fall_start_distance = q->unk430 * 1.5f; - if (b) { + if (animation_update_mode) { int s = q->state.current; if (s == 7) { set_hero_animation(7, 0, (float)scale_game_frames(5)); @@ -1174,7 +1174,7 @@ int hero_set_state(int requested_state, int b) { update_hero_target_heading(8.0f, 1.0471976f, -1.0f); *(int *)&q->slam_descending = 0; q->items[0].timer = 0xA; - if (b) { + if (animation_update_mode) { char *m; int n = scale_game_frames(0xB); if (q->state.prev == 0xB && scale_game_frames(0x2A) > q->state.prev_timer) @@ -1212,7 +1212,7 @@ int hero_set_state(int requested_state, int b) { q->saved_item[0] = 0; update_hero_target_heading(14.0f, 0.5235988f, -1.0f); q->unkA7C = q->unkA7C == 0; - if (b) { + if (animation_update_mode) { int n = scale_game_frames(0xA); if (q->moby->prev_seq == 0x1A) n = scale_game_frames(3); @@ -1227,7 +1227,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; if (((void *)q->items[0].moby) == 0) break; - if (b) { + if (animation_update_mode) { set_hero_animation(0x67, 4, -1.0f); blend_moby_animation(((void *)q->items[0].moby), 3, 4, -1); } @@ -1258,7 +1258,7 @@ int hero_set_state(int requested_state, int b) { r->attack_record = k; } update_hero_target_heading(5.0f, 0.7853982f, 0.7853982f); - if (b) { + if (animation_update_mode) { char *m; int j = 0; int n; @@ -1289,7 +1289,7 @@ int hero_set_state(int requested_state, int b) { } case HERO_STATE_ANIMATION_RECOVERY_WITH_JUMP_CANCEL: { struct Hero *q; - if (b) + if (animation_update_mode) set_hero_animation(0x2C, 7, (float)scale_game_frames(9)); q = &hero; if (q->items[0].item_id == 0xA && ((char *)q->throw_target) != 0) { @@ -1318,7 +1318,7 @@ int hero_set_state(int requested_state, int b) { { struct Hero *q = &hero; int e = D_L14_0017C328[q->attack_record].kind; - if (b) { + if (animation_update_mode) { char *m; int z = e == 0; int n = scale_game_frames(5); @@ -1339,7 +1339,7 @@ int hero_set_state(int requested_state, int b) { } else { p->attack_record = 0; } - if (b) { + if (animation_update_mode) { struct Hero *q = &hero; char *m; int n = scale_game_frames(4); @@ -1355,7 +1355,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0xA; p->unk2284 = 0; p->ground_speed = frame_time * 9.0f; - if (b) { + if (animation_update_mode) { char *m; HeroTableRow2C *e = &D_L14_0017C328[p->attack_record]; int k = e->kind; @@ -1376,7 +1376,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->pushback_yaw = fast_add_rotations(p->motion.rot.f[2], 3.1415927f); p->ground_speed = frame_time * 9.0f; - if (b) + if (animation_update_mode) set_hero_animation(0x29, 5, (float)scale_game_frames(8)); break; } @@ -1398,7 +1398,7 @@ int hero_set_state(int requested_state, int b) { { struct Hero *q = &hero; q->invulnerable_frames = scale_game_frames(0x4D); - if (b) { + if (animation_update_mode) { set_hero_animation(0x10, 3, -3.0f); q->moby->anim_time = level14_hero_animation_blend_curves[q->anim_blend_curve] [(q->anim_blend_step)++]; @@ -1410,7 +1410,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 0; p->unk2284 = 0; - if (b) + if (animation_update_mode) set_hero_animation(0, 0, (float)scale_game_frames(0xE)); break; } @@ -1418,7 +1418,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 0; p->unk2284 = 0; - if (b) { + if (animation_update_mode) { set_hero_animation(4, 0, (float)scale_game_frames(7)); hero_queue_sequence(0xE, 0x22); } @@ -1429,7 +1429,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 2; p->unk2284 = 0; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (animation_update_mode) set_hero_animation(6, 0, (float)scale_game_frames(0xC)); break; } @@ -1440,7 +1440,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (animation_update_mode) set_hero_animation(6, 0, (float)scale_game_frames(7)); break; } @@ -1457,7 +1457,7 @@ int hero_set_state(int requested_state, int b) { if (frame_time * 1.5f < planar_speed) hero_base->ground_speed = frame_time * 1.5f; hero_base->unk3B8 = 0; - if (b) + if (animation_update_mode) set_hero_animation(1, 0, (float)scale_game_frames(8)); } break; @@ -1467,7 +1467,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x14; p->unk2284 = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (animation_update_mode) set_hero_animation(3, 0, (float)scale_game_frames(0xC)); break; } @@ -1480,7 +1480,7 @@ int hero_set_state(int requested_state, int b) { FUN_L00_0025f730(&p->motion.velocity, frame_time * 5.0f); hero_change_health(1); p->invulnerable_frames = scale_game_frames(0x4D); - if (b) { + if (animation_update_mode) { set_hero_animation(2, 3, -3.0f); p->moby->anim_time = level14_hero_animation_blend_curves[p->anim_blend_curve][(p->anim_blend_step)++]; @@ -1501,7 +1501,7 @@ int hero_set_state(int requested_state, int b) { clear_u64_value(&p->motion.velocity); clear_u64_value(&p->motion.displacement); p->motion.velocity.f[2] = frame_time * 10.0f; - if (b) + if (animation_update_mode) set_hero_animation(0x10, 2, -3.0f); break; } @@ -1552,7 +1552,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->tilt_disabled = 1; p->item_use_locked = 1; - if (b) + if (animation_update_mode) set_hero_animation(hero_get_gadget_anim_id(0), 0, -1.0f); break; } @@ -1563,7 +1563,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->item_use_locked = 1; clear_u64_value(&p->motion.velocity); - if (b) + if (animation_update_mode) set_hero_animation(0xB, 0, -1.0f); break; } @@ -1573,7 +1573,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x18; p->item_use_locked = 1; cancel_hero_item_animation(); - if (b) + if (animation_update_mode) set_hero_animation(hero_get_gadget_anim_id(0), 0, -1.0f); break; } From 1606305f3e64f27604135f73b5f6009d6763143d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:01:15 +0000 Subject: [PATCH 1360/1502] decomp: clarify names in extermibot_update domain_10_value_7 -> EXTERMIBOT_AIM_BEFORE_STRIKE: 00302734-00302764 tests target XY distance below 3, stores 7 to moby+20 and arms timer pvars+2D0. Existing AIM_BEFORE_STRIKE case uses that same timer at 00302aac-00302ac4 to enter STRIKE_TARGET. domain_11_value_10 -> EXTERMIBOT_RETURN_TO_START: Source APPROACH_TARGET_DIRECTLY enters state 10 when pvars+2B0 is zero; retail 00302728-0030272c branches to store 10 at 00302a04-00302a0c. Same moby+20 selector dispatches RETURN_TO_START, walking toward saved pvars+270 at 003030b4. domain_12_value_10 -> EXTERMIBOT_RETURN_TO_START: 00302790-003027a4 detects expired pvars+2B0, clears movement speed and stores 10 to moby+20. The existing RETURN_TO_START case for that selector walks toward the initialization position pvars+270 and checks arrival at 003030b4-003030f8. domain_13_value_7 -> EXTERMIBOT_AIM_BEFORE_STRIKE: 003027d0-00302800 tests target XY range below 3, stores 7 to selector moby+20 and scales pre-strike delay into pvars+2D0. Existing AIM_BEFORE_STRIKE case turns toward target and decrements that timer before striking. domain_14_value_1 -> EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH: 0030282c-00302888 tests configured activation triggers, restores draw distance and flag 1000, and stores 1 to moby+20. That is the byte read by the switch for the existing IDLE_AND_CHECK_TARGET_PATH case. domain_15_value_2 -> EXTERMIBOT_WANDER_NEAR_START: 003028b0-00302900 builds a random goal relative to saved pvars+270, sets the wander timer, saves state 15 in moby+BC and stores 2 to moby+20. Existing WANDER_NEAR_START case moves toward this goal then restores saved state. domain_16_value_7 -> EXTERMIBOT_AIM_BEFORE_STRIKE: 00302930-003029c4 follows the target then checks XY distance below 3 and heading error below pi/4, stores 7 to moby+20 and arms pvars+2D0. This selector dispatches existing AIM_BEFORE_STRIKE, which consumes that timer. domain_18_value_10 -> EXTERMIBOT_RETURN_TO_START: 003029f4-00302a0c loads pvars+164 mode, compares it with 2 and stores 10 to moby+20 when equal. This state selector already has RETURN_TO_START case 10, whose 003030b4-003030f8 walks toward saved start pvars+270. domain_19_value_8 -> EXTERMIBOT_STRIKE_TARGET: 00302aac-00302ac4 decrements pre-strike timer and on expiration stores 8 to selector moby+20 and clears the timer. Existing STRIKE_TARGET case 00302e40-00302f90 performs the animation/range/facing/height-gated target interaction. domain_1_value_15 -> EXTERMIBOT_WAIT_FOR_ACTIVATION_TRIGGER: 0030219c-003021c0 loads the configured trigger indices at pvars+2B8, clears flag 1000 and stores 15 to moby+20; that same byte selects the existing WAIT_FOR_ACTIVATION_TRIGGER case at 0030282c, which tests linked-moby/clip-volume activation. domain_20_value_9 -> EXTERMIBOT_RECOVER_AFTER_STRIKE: 00302f94-00302fb0 tests animation completion bit 2 and stores 9 to moby+20 after strike. Same state byte selects existing RECOVER_AFTER_STRIKE case at 00302fcc, which waits for animation then re-aims or follows target. domain_21_value_7 -> EXTERMIBOT_AIM_BEFORE_STRIKE: 00302fdc-00303054 checks recovery completion, target range below 3 and facing error below pi/12, stores 7 to moby+20 and resets pvars+2D0. This is the existing AIM_BEFORE_STRIKE selector and countdown, not animation sequence 7. domain_22_value_4 -> EXTERMIBOT_FOLLOW_TARGET: 00303080-00303088 clears speed and stores 4 to moby+20 when recovery cannot immediately re-aim. That same selector dispatches existing FOLLOW_TARGET case 00302930-00302950, which invokes the path walker toward target+10. domain_23_value_1 -> EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH: 003030b4-003030f8 walks toward saved start pvars+270, tests XY distance below 1 and stores 1 to moby+20 upon arrival. Existing IDLE_AND_CHECK_TARGET_PATH is case 1 of that exact selector, with idle animation 0. domain_25_value_4 -> EXTERMIBOT_FOLLOW_TARGET: 00303104-00303120 compares pvars+164 with 2 and otherwise stores 4 to moby+20 during return-to-start. Existing FOLLOW_TARGET case of this same selector walks toward target+10 at 00302930-00302950. domain_26_value_6 -> EXTERMIBOT_APPROACH_TARGET_DIRECTLY: 0030313c-0030314c tests active pvars+2B0 after mode 2 and stores 6 to moby+20. Existing APPROACH_TARGET_DIRECTLY case for this byte accelerates speed and steers directly toward target coordinates at 0030257c-003026a8. domain_27_value_4 -> EXTERMIBOT_FOLLOW_TARGET: 00303150-003031ac advances nonlethal knockback and tests follow_path success, then stores 4 to moby+20. Existing FOLLOW_TARGET case is selected by this same byte and invokes the walker toward target at 00302930-00302950. domain_28_value_1 -> EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH: 00303200-00303218 tests animation completion bit 2 and stores 1 to moby+20, with animation 0 selected afterward. This selector's existing IDLE_AND_CHECK_TARGET_PATH case at 0030221c resumes idle/path-check behavior. domain_2_value_1 -> EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH: 003021e0-00302200 stores 1 to moby+20 and selects animation 0 when initialization needs no trigger. The switch reads this same state byte at 0030204c; its existing IDLE_AND_CHECK_TARGET_PATH case checks a path to target at 0030221c-00302350. domain_4_value_4 -> EXTERMIBOT_FOLLOW_TARGET: 00302264-003022dc tests follow_path success toward target+10, configures offset heading and stores 4 to moby+20. The same state byte dispatches the existing FOLLOW_TARGET case, whose 00302930-00302950 walker call uses target position. domain_7_value_6 -> EXTERMIBOT_APPROACH_TARGET_DIRECTLY: 00302314-00302338 checks pvars+164 mode 2 and active pvars+2B0 then stores 6 to moby+20. This is the switch selector byte; existing APPROACH_TARGET_DIRECTLY case 0030257c-003026a8 accelerates and moves directly toward target. domain_8_value_2 -> EXTERMIBOT_WANDER_NEAR_START: 00302384-003023cc builds a random goal around saved pvars+270, saves the current state in moby+BC and stores 2 to selector moby+20. Existing WANDER_NEAR_START case moves to this goal and restores +BC at 00302564-00302570. domain_9_value_5 -> EXTERMIBOT_WAIT_FOR_TARGET_IN_STRIKE_RANGE: 003026c4-0030270c tests a path intersection output within 1.5 units and stores 5 to selector moby+20. Existing WAIT_FOR_TARGET_IN_STRIKE_RANGE case 00302790-00302828 waits until target XY distance is below 3 before aiming. --- src/overlays/l05/mobys/extermibot.c | 46 ++++++++++++++--------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/overlays/l05/mobys/extermibot.c b/src/overlays/l05/mobys/extermibot.c index 881af0dda4..cbad38a810 100644 --- a/src/overlays/l05/mobys/extermibot.c +++ b/src/overlays/l05/mobys/extermibot.c @@ -209,11 +209,11 @@ void extermibot_update(unsigned char *moby) { MOBY(moby)->draw_dist = 0; } else if (*(long *)&moby_data->unk2B8 != -1) { MOBY(moby)->flags &= 0xEFFF; - MOBY(moby)->state = 0xF; + MOBY(moby)->state = EXTERMIBOT_WAIT_FOR_ACTIVATION_TRIGGER; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, 0); } else { - MOBY(moby)->state = 1; + MOBY(moby)->state = EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, 0); } @@ -233,7 +233,7 @@ void extermibot_update(unsigned char *moby) { } moby_data->unk294 = moby_data->unk298 * 0.017453292f; moby_data->unk2AC = scale_game_frames((int)random_float_between(30.0f, 90.0f)); - MOBY(moby)->state = 4; + MOBY(moby)->state = EXTERMIBOT_FOLLOW_TARGET; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } else { @@ -241,7 +241,7 @@ void extermibot_update(unsigned char *moby) { } } if (moby_data->mode == 2 && moby_data->unk2B0 != 0) { - MOBY(moby)->state = 6; + MOBY(moby)->state = EXTERMIBOT_APPROACH_TARGET_DIRECTLY; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } else if (MOBY(moby)->anim_flags & 2) { @@ -251,7 +251,7 @@ void extermibot_update(unsigned char *moby) { fast_vec_add(moby_data->goal, moby_data->goal, &moby_data->unk270); moby_data->unk2D2 = 0; MOBY(moby)->command = MOBY(moby)->state; - MOBY(moby)->state = 2; + MOBY(moby)->state = EXTERMIBOT_WANDER_NEAR_START; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } else if (MOBY(moby)->prev_seq != 0) { @@ -328,29 +328,29 @@ void extermibot_update(unsigned char *moby) { near = 1; } if (near) { - MOBY(moby)->state = 5; + MOBY(moby)->state = EXTERMIBOT_WAIT_FOR_TARGET_IN_STRIKE_RANGE; if (MOBY(moby)->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(20)); } else if (moby_data->unk2B0 != 0) { if (vector_distance_xy(moby_position, target_moby + 0x10) < 3.0f) { - MOBY(moby)->state = 7; + MOBY(moby)->state = EXTERMIBOT_AIM_BEFORE_STRIKE; moby_data->unk2D0 = scale_game_frames(extermibot_pre_strike_delay_frames_gp); if (MOBY(moby)->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(10)); } } else { - MOBY(moby)->state = 10; + MOBY(moby)->state = EXTERMIBOT_RETURN_TO_START; } break; } case EXTERMIBOT_WAIT_FOR_TARGET_IN_STRIKE_RANGE: if (moby_data->unk2B0 == 0) { moby_data->speed = 0.0f; - MOBY(moby)->state = 10; + MOBY(moby)->state = EXTERMIBOT_RETURN_TO_START; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(20)); } else if (vector_distance_xy(moby + 0x10, target_moby + 0x10) < 3.0f) { - MOBY(moby)->state = 7; + MOBY(moby)->state = EXTERMIBOT_AIM_BEFORE_STRIKE; moby_data->unk2D0 = scale_game_frames(extermibot_pre_strike_delay_frames_gp); if (MOBY(moby)->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(10)); @@ -363,7 +363,7 @@ void extermibot_update(unsigned char *moby) { is_point_inside_clip_volume(((char *)D_0013F3D0), moby_data->unk2BC) != 0)) { MOBY(moby)->draw_dist = 0x40; MOBY(moby)->flags |= 0x1000; - MOBY(moby)->state = 1; + MOBY(moby)->state = EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH; } else if (MOBY(moby)->anim_flags & 2) { if (random_integer_below(0xFF) & 1) { FUN_L00_00257d78(moby_data->goal, 0.0f, 4.0f); @@ -371,7 +371,7 @@ void extermibot_update(unsigned char *moby) { fast_vec_add(moby_data->goal, moby_data->goal, &moby_data->unk270); moby_data->unk2D2 = scale_game_frames(0x5A); MOBY(moby)->command = MOBY(moby)->state; - MOBY(moby)->state = 2; + MOBY(moby)->state = EXTERMIBOT_WANDER_NEAR_START; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } else if (MOBY(moby)->prev_seq != 0) { @@ -387,13 +387,13 @@ void extermibot_update(unsigned char *moby) { MOBY(moby)->rot.z, fast_arc_tan(MOBY(target_moby)->pos.x - MOBY(moby)->pos.x, MOBY(target_moby)->pos.y - MOBY(moby)->pos.y)) < 0.7853982f) { - MOBY(moby)->state = 7; + MOBY(moby)->state = EXTERMIBOT_AIM_BEFORE_STRIKE; moby_data->unk2D0 = scale_game_frames(extermibot_pre_strike_delay_frames_gp); if (MOBY(moby)->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(10)); } if (moby_data->mode == 2) { - MOBY(moby)->state = 10; + MOBY(moby)->state = EXTERMIBOT_RETURN_TO_START; } break; } @@ -412,7 +412,7 @@ void extermibot_update(unsigned char *moby) { } if (fast_dec_timer_s16(&moby_data->unk2D0) != 0) { float a; - MOBY(moby)->state = 8; + MOBY(moby)->state = EXTERMIBOT_STRIKE_TARGET; moby_data->unk2D0 = 0; if (MOBY(moby)->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(1)); @@ -519,7 +519,7 @@ void extermibot_update(unsigned char *moby) { 1.0f); } if (MOBY(moby)->anim_flags & 2) { - MOBY(moby)->state = 9; + MOBY(moby)->state = EXTERMIBOT_RECOVER_AFTER_STRIKE; if (MOBY(moby)->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); } @@ -532,13 +532,13 @@ void extermibot_update(unsigned char *moby) { MOBY(moby)->rot.z, fast_arc_tan(MOBY(target_moby)->pos.x - MOBY(moby)->pos.x, MOBY(target_moby)->pos.y - MOBY(moby)->pos.y)) < 0.2617994f) { - MOBY(moby)->state = 7; + MOBY(moby)->state = EXTERMIBOT_AIM_BEFORE_STRIKE; moby_data->unk2D0 = scale_game_frames(extermibot_pre_strike_delay_frames_gp); if (MOBY(moby)->prev_seq != 7) blend_moby_animation(moby, 7, 0, scale_game_frames(5)); } else { moby_data->speed = 0.0f; - MOBY(moby)->state = 4; + MOBY(moby)->state = EXTERMIBOT_FOLLOW_TARGET; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -547,15 +547,15 @@ void extermibot_update(unsigned char *moby) { case EXTERMIBOT_RETURN_TO_START: FUN_L05_00303b08_c((struct Moby *)moby, (s32)(&moby_data->unk270), 0.0f); if (vector_distance_xy(moby + 0x10, &moby_data->unk270) < 1.0f) { - MOBY(moby)->state = 1; + MOBY(moby)->state = EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(3)); } else if (moby_data->mode != 2) { - MOBY(moby)->state = 4; + MOBY(moby)->state = EXTERMIBOT_FOLLOW_TARGET; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(3)); } else if (moby_data->unk2B0 != 0) { - MOBY(moby)->state = 6; + MOBY(moby)->state = EXTERMIBOT_APPROACH_TARGET_DIRECTLY; } break; case EXTERMIBOT_NONLETHAL_KNOCKBACK: @@ -567,7 +567,7 @@ void extermibot_update(unsigned char *moby) { (s32)(&moby_data->unk270), path_goal_or_facing_vector, (D_L05_00161A98) * 0.4f) != 0) { - MOBY(moby)->state = 4; + MOBY(moby)->state = EXTERMIBOT_FOLLOW_TARGET; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); break; @@ -583,7 +583,7 @@ void extermibot_update(unsigned char *moby) { break; case EXTERMIBOT_WAIT_FOR_ANIMATION_BEFORE_IDLE: if (MOBY(moby)->anim_flags & 2) { - MOBY(moby)->state = 1; + MOBY(moby)->state = EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } From 45345b126494e94d63da1b20aa8bfee6668ff885 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:01:15 +0000 Subject: [PATCH 1361/1502] decomp: clarify names in spawn_ship_pickup domain_0_value_0 -> SHIP_PICKUP_INITIALIZE: Retail 0x002e1c64 creates the requested moby; s0 retains its returned pointer and 0x002e1c90 stores zero at s0+0x20, the source MOBY(moby)->state. The supplied blarg_ship_update caller spawns classes 0xE0/0xE4, and authoritative adjacent ammocrate_update handles classes 224/228 using the same MOBY state selector, with SHIP_PICKUP_INITIALIZE = 0. That branch initializes scale or hides/disables the pickup and advances activation. Thus this store enters that established pickup initialization state, not a hero state. --- src/overlays/shared/pickups/fighter_jet_crate.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/pickups/fighter_jet_crate.c b/src/overlays/shared/pickups/fighter_jet_crate.c index 62e497a931..cc2b3bbe47 100644 --- a/src/overlays/shared/pickups/fighter_jet_crate.c +++ b/src/overlays/shared/pickups/fighter_jet_crate.c @@ -27,12 +27,15 @@ extern char *create_moby(int); unsigned char *spawn_ship_pickup(char *position, int moby_class) __asm__("FUN_L13_002e1c50"); unsigned char *spawn_ship_pickup(char *position, int moby_class) { + enum { + SHIP_PICKUP_INITIALIZE = 0 + }; unsigned char *moby = create_moby(moby_class); if (moby != 0) { MOBY(moby)->update_dist = 0xFF; MOBY(moby)->draw_dist = 0xFF; MOBY(moby)->visible = 1; - MOBY(moby)->state = 0; + MOBY(moby)->state = SHIP_PICKUP_INITIALIZE; MOBY(moby)->command = 0; qcopy(&MOBY(moby)->pos, position); update_entity(moby); From 7a120ca7f2795d7d0d8a426f48918cdcc564abd2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:01:15 +0000 Subject: [PATCH 1362/1502] decomp: clarify names in reset_electric_water_switch domain_0_value_1 -> ELECTRIC_WATER_SWITCH_RESET: The source snapshot c6027068c1566b12a7fb2525cc97ea0f6223a906320547a9333e4b756ae46b77 assigns 1 to MOBY(moby)->state inside reset_electric_water_switch. Retail 0x002d95b8 loads 1, 0x002d95c8 stores it to moby+0x20, and 0x002d95bc..0x002d95d0 increases moby position.z at +0x18 by 1.5. electric_water_update calls this helper for linked switches during initialization and timed reset, parallel to resetting class-0x33e switches to state 1. Thus this is the electric-water switch reset destination state; it is not a hero state or water-controller state. --- src/overlays/shared/props/electric_water.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/props/electric_water.c b/src/overlays/shared/props/electric_water.c index ef4eceb4cf..bf3b934521 100644 --- a/src/overlays/shared/props/electric_water.c +++ b/src/overlays/shared/props/electric_water.c @@ -1193,8 +1193,11 @@ extern int is_moby_class_23e_in_state_14(void *) __asm__("FUN_L03_002c6c60"); void reset_electric_water_switch(char *moby) __asm__("FUN_L15_002d95a0"); void reset_electric_water_switch(char *moby) { + enum { + ELECTRIC_WATER_SWITCH_RESET = 1 + }; if (is_moby_class_23e_in_state_14(moby)) { - MOBY(moby)->state = 1; + MOBY(moby)->state = ELECTRIC_WATER_SWITCH_RESET; MOBY(moby)->pos.z += 1.5f; } } From 0e308dfc37991ef4e82bfdeaa65c3e53f9849004 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:01:15 +0000 Subject: [PATCH 1363/1502] decomp: clarify names in set_novalis_bolt_crank_completion_flags domain_0_value_5 -> BOLT_CRANK_DONE: Retail 0x002e0c08 loads the state byte at a0+0x20 and 0x002e0c0c..0x002e0c10 compares it with 5, after class 0x118 and save ID 0x34 checks. bolt_crank_update passes this same Moby at 0x002e1a84, after restoring completion at 0x002e0dcc or finishing lowering at 0x002e1a70. The authoritative C expresses both state writes with local enum BoltCrankState member BOLT_CRANK_DONE=5, sets progress to 1.0f and calls this helper at done. Thus this selector is that exact bolt-crank Moby.state domain. domain_1_value_5 -> BOLT_CRANK_DONE: Retail 0x002e0c4c loads the same a0+0x20 Moby state byte and 0x002e0c48/0x002e0c50 tests 5 after class 0x118 and save ID 0x35 checks, gating the flag store at 0x002e0c58. The same Moby comes from bolt_crank_update at 0x002e1a84; its restored-completion and lowering-finished state writes at 0x002e0dcc and 0x002e1a70 correspond to BOLT_CRANK_DONE in the source enum BoltCrankState. Reuse that canonical member for this second completion test. --- src/overlays/shared/props/bolt_crank.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/props/bolt_crank.c b/src/overlays/shared/props/bolt_crank.c index f3aeea2ff5..353b06cf7c 100644 --- a/src/overlays/shared/props/bolt_crank.c +++ b/src/overlays/shared/props/bolt_crank.c @@ -74,12 +74,12 @@ void set_novalis_bolt_crank_completion_flags(char *moby) { if (level != 1) return; if (((short)MOBY(moby)->save_id) == 0x34 && MOBY(moby)->oclass == 0x118 && - (unsigned char)MOBY(moby)->state == 5) { + (unsigned char)MOBY(moby)->state == BOLT_CRANK_DONE) { menu_item_enabled_0 = level; level = D_0015ED84; } if (level == 1 && ((short)MOBY(moby)->save_id) == 0x35 && MOBY(moby)->oclass == 0x118 && - (unsigned char)MOBY(moby)->state == 5) { + (unsigned char)MOBY(moby)->state == BOLT_CRANK_DONE) { menu_item_enabled_1_lui = level; } } From 9de9da858e087101622ec3d3bfef8639c7f3adae Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:21:20 +0000 Subject: [PATCH 1364/1502] decomp: clarify names in spawn_giant_clank_charged_blast domain_0_value_0 -> GIANT_CLANK_CHARGED_BLAST_CHARGING: Retail 0x002a9aa4/0x002a9ab8 allocates class 0x5F3 into s1; 0x002a9af4 stores zero to that object's current-state byte +0x20, and 0x002a9b3c stores the same object in D_L00_001613C8. In authoritative source, remove_giant_clank_charged_blast reads this identical tracked pointer, checks class 0x5F3, and permits removal only when tracked_moby->state equals the existing local enum GIANT_CLANK_CHARGED_BLAST_CHARGING=0. Thus spawn initializes the same class-specific current-state domain to its already named charging member. The charged-blast update source corroborates charging behavior with particle emission and light buildup before transition to expanding blast; Hero constants are separate domains. --- src/overlays/shared/vehicles/giant_clank_charged_blast.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/vehicles/giant_clank_charged_blast.c b/src/overlays/shared/vehicles/giant_clank_charged_blast.c index a273e47e80..54d5cf87c7 100644 --- a/src/overlays/shared/vehicles/giant_clank_charged_blast.c +++ b/src/overlays/shared/vehicles/giant_clank_charged_blast.c @@ -34,10 +34,13 @@ void *spawn_giant_clank_charged_blast(int unused, float *spawn_position) __asm__("FUN_L00_002a9aa0"); void *spawn_giant_clank_charged_blast(int unused, float *spawn_position) { + enum { + GIANT_CLANK_CHARGED_BLAST_CHARGING = 0 + }; char *spawned_moby = create_moby(0x5F3); if (spawned_moby != 0 && *(int *)&D_L00_001613C8_gp == 0) { char *moby_vars; - MOBY(spawned_moby)->state = 0; + MOBY(spawned_moby)->state = GIANT_CLANK_CHARGED_BLAST_CHARGING; MOBY(spawned_moby)->update_dist = 0xFF; MOBY(spawned_moby)->draw_dist = 0xFF; MOBY(spawned_moby)->visible = 1; From 4b4fb5d5047eccbaa926ac2ae82281066205b2fe Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:30:44 +0000 Subject: [PATCH 1365/1502] decomp: clarify names in gadgebot_update domain_0_value_8 -> GADGEBOT_IDLE: Initialization stores 8 to this gadgebot Moby's state at 0x002fbbf0 and disables visibility/collision at 0x002fbc74-0x002fbc80. The supplied same-file launch_first_idle_group_class_0772_moby tests this exact class's state against GADGEBOT_IDLE=8 before launching it; hide_moby_and_clear_collision also establishes that name for the same Moby state domain. domain_1_value_2 -> GADGEBOT_WAIT_TO_APPROACH: Landing clamps Moby Z to the ground probe and stores 2 to Moby+0x20 at 0x002fbd00-0x002fbd08. This is the same field dispatched at 0x002fbbbc and named GADGEBOT_WAIT_TO_APPROACH=2 in the existing local enum, whose handler at 0x002fbd5c waits on the target distance before entering approach. domain_2_value_6 -> GADGEBOT_EXPLODE: The launch branch below minimum Z loads 6 at 0x002fbd30 and stores it to Moby+0x20 at 0x002fbd38. This is the same state selector dispatched at 0x002fbbbc, with existing local GADGEBOT_EXPLODE=6 invoking the explosion at 0x002fc004 before disabling collision. domain_3_value_2 -> GADGEBOT_WAIT_TO_APPROACH: On suction helper completion, 0x002fbd4c-0x002fbd58 stores 2 to Moby+0x20 and clears pvars+0x138. This is the existing local state domain GADGEBOT_WAIT_TO_APPROACH=2, corroborated by update_moby_suck_cannon_state restoring that same member after suction ends. domain_4_value_3 -> GADGEBOT_APPROACH_TARGET: The WAIT_TO_APPROACH handler gates mode 2 on target XY distance greater than 10 at 0x002fbd5c-0x002fbd84, then reaches the shared store of 3 to Moby+0x20 at 0x002fbf54. Existing local GADGEBOT_APPROACH_TARGET=3 dispatches the target movement call at 0x002fbd94. domain_5_value_2 -> GADGEBOT_WAIT_TO_APPROACH: After move_gadgebot_toward_target returns distance, mode 2 and distance below 5 cause 0x002fbdcc-0x002fbdd0 to store 2 to Moby+0x20. The selector is the existing local gadgebot state domain, whose GADGEBOT_WAIT_TO_APPROACH=2 handler waits before resuming target approach. domain_6_value_4 -> GADGEBOT_FACE_TARGET: Target distance below 1.5 causes 0x002fbe04-0x002fbe14 to store 4 to Moby+0x20. Existing local GADGEBOT_FACE_TARGET=4 dispatches 0x002fbe48-0x002fbe98, computing target XY displacement and approaching its angle at Moby+0x48. domain_7_value_2 -> GADGEBOT_WAIT_TO_APPROACH: In FACE_TARGET, the animation flag and mode-2 tests reach 0x002fbef4-0x002fbf08, which stores 2 to the same Moby+0x20 state field used by the dispatch. Existing GADGEBOT_WAIT_TO_APPROACH=2 names its target-distance waiting handler; this is not the separate pvars+0x1C4 target-mode domain. domain_8_value_3 -> GADGEBOT_APPROACH_TARGET: In FACE_TARGET with target mode other than 2, target XY distance above 2.5 reaches 0x002fbf44-0x002fbf54 and stores 3 to Moby+0x20. Existing local GADGEBOT_APPROACH_TARGET=3 dispatches move_gadgebot_toward_target on pvars+0x180; the store uses that exact state domain. domain_9_value_8 -> GADGEBOT_IDLE: After the explosion call at 0x002fc004, 0x002fc00c-0x002fc018 stores 8 to Moby+0x20 and 0x002fc038-0x002fc048 disables collision and active flags. Supplied same-file launcher tests this exact class's state as GADGEBOT_IDLE=8 before reactivation, and hide_moby_and_clear_collision enters that same idle state. --- src/overlays/l18/mobys/gadgebot.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/overlays/l18/mobys/gadgebot.c b/src/overlays/l18/mobys/gadgebot.c index 9a2e7b67b0..b5a6110ec9 100644 --- a/src/overlays/l18/mobys/gadgebot.c +++ b/src/overlays/l18/mobys/gadgebot.c @@ -82,6 +82,9 @@ void gadgebot_update(unsigned char *moby) { GADGEBOT_EXPLODE = 6, GADGEBOT_SUCK_CANNON_SUCTION = 7 }; + enum { + GADGEBOT_IDLE = 8 + }; char position_scratch[16]; unsigned char *moby_vars = ((unsigned char *)MOBY(moby)->pvars); unsigned char *moby_transform_ptr; @@ -89,7 +92,7 @@ void gadgebot_update(unsigned char *moby) { switch (MOBY(moby)->state) { case GADGEBOT_INITIALIZE: { unsigned short moby_flags; - MOBY(moby)->state = 8; + MOBY(moby)->state = GADGEBOT_IDLE; if (random_integer_below(2)) MOBY(moby)->flags |= 0x8000; else @@ -125,17 +128,17 @@ void gadgebot_update(unsigned char *moby) { r = probe_ground_height(position_scratch, 0, 0.5f); if (MOBY(moby)->pos.z < r) { MOBY(moby)->pos.z = r; - MOBY(moby)->state = 2; + MOBY(moby)->state = GADGEBOT_WAIT_TO_APPROACH; if (MOBY(moby)->prev_seq) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } else if (MOBY(moby)->pos.z < launch_gravity_and_minimum_z) { - MOBY(moby)->state = 6; + MOBY(moby)->state = GADGEBOT_EXPLODE; } break; } case GADGEBOT_SUCK_CANNON_SUCTION: if (FUN_L00_002dc9f0(moby, moby_vars + 0x70)) { - MOBY(moby)->state = 2; + MOBY(moby)->state = GADGEBOT_WAIT_TO_APPROACH; *(short *)(moby_vars + 0x138) = 0; } break; @@ -144,7 +147,7 @@ void gadgebot_update(unsigned char *moby) { if (!(10.0f < vector_distance_xy(moby + 0x10, moby_vars + 0x180))) break; } - MOBY(moby)->state = 3; + MOBY(moby)->state = GADGEBOT_APPROACH_TARGET; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); break; @@ -153,13 +156,13 @@ void gadgebot_update(unsigned char *moby) { *(QVd058 *)position_scratch = *(QVd058 *)(moby_vars + 0x180); target_distance = move_gadgebot_toward_target(moby, position_scratch); if (*(int *)(moby_vars + 0x1C4) == 2 && target_distance < 5.0f) { - MOBY(moby)->state = 2; + MOBY(moby)->state = GADGEBOT_WAIT_TO_APPROACH; if (MOBY(moby)->prev_seq) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); break; } if (target_distance < 1.5f) { - MOBY(moby)->state = 4; + MOBY(moby)->state = GADGEBOT_FACE_TARGET; if (MOBY(moby)->prev_seq != 2) { int animation_frame_index = (int)gadgebot_sequence_2_start_frame_gp; blend_moby_animation(moby, 2, animation_frame_index, scale_game_frames(5)); @@ -181,14 +184,14 @@ void gadgebot_update(unsigned char *moby) { collect_mobies_in_sphere_at_moby_point(moby, 0.5f, 1.0f, 1.0f, 1, 1, 0, 1, 0); if (MOBY(moby)->anim_flags & 2) { if (*(int *)(moby_vars + 0x1C4) == 2) { - MOBY(moby)->state = 2; + MOBY(moby)->state = GADGEBOT_WAIT_TO_APPROACH; if (MOBY(moby)->prev_seq) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); break; } if (!(2.5f < vector_distance_xy(moby + 0x10, moby_vars + 0x180))) break; - MOBY(moby)->state = 3; + MOBY(moby)->state = GADGEBOT_APPROACH_TARGET; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); break; @@ -219,7 +222,7 @@ void gadgebot_update(unsigned char *moby) { 1, -1, 0); - MOBY(moby)->state = 8; + MOBY(moby)->state = GADGEBOT_IDLE; if (MOBY(moby)->prev_seq) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); MOBY(moby)->collision = 0; From 6c38b93ea2f5a669783849079650641de826e36f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:30:44 +0000 Subject: [PATCH 1366/1502] decomp: clarify names in hero_set_state b -> animation_request_mode: Retail 0x00230b90 preserves second int argument a1 in s4. At 0x00230dc8, s4==0 skips optional idle animation selection and setter calls at 0x00230dd0..0x00230e20; dying entry similarly tests s4 at 0x00230f08 before selecting animation 0x45 at 0x00230f10..0x00230f28. Original Ghidra uses param_2==0 for these gates and authoritative C uses if(b) around set_hero_animation. Retail 0x00230ba0..0x00230ba8 and 0x00230bb4..0x00230bcc also require this same mode to equal 2 to admit the permitted dying override request or bypass level-game-mode restrictions. The recursive idle call at 0x00231d54..0x00231d58 passes zero and explicitly sets animation afterward at 0x00231d64..0x00231d8c, confirming optional entry-animation request control. --- src/overlays/l08/hero/hero_set_state.c | 122 ++++++++++++------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/src/overlays/l08/hero/hero_set_state.c b/src/overlays/l08/hero/hero_set_state.c index b5954e7a12..e3bc906afa 100644 --- a/src/overlays/l08/hero/hero_set_state.c +++ b/src/overlays/l08/hero/hero_set_state.c @@ -68,7 +68,7 @@ extern int hero_set_state(int, int) __asm__("FUN_L08_00230b38"); extern char hero_water_surface_jump_velocity_keys[] __asm__("D_L08_0017C760"); extern char hero_transform_trail_jump_velocity_keys[] __asm__("D_L08_0017C720"); -int hero_set_state(int requested_state, int b) { +int hero_set_state(int requested_state, int animation_request_mode) { int previous_state_step; char *moby; int old20A7; @@ -76,10 +76,10 @@ int hero_set_state(int requested_state, int b) { { struct Hero *p = &hero; if (p->state.control_mode == 0x14 && - (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || animation_request_mode != 2)) return 0; } - if ((level_game_mode == 2 || level_game_mode == 6) && b != 2) + if ((level_game_mode == 2 || level_game_mode == 6) && animation_request_mode != 2) return 0; { struct Hero *p = &hero; @@ -151,7 +151,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; q->rand_timer.range = 0x68; } - if (b) { + if (animation_request_mode) { if (get_hero_idle_animation_index(0) == 0x54) { set_hero_animation( get_hero_idle_animation_index(0), 0, (float)scale_game_frames(0x12)); @@ -167,7 +167,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; clear_u64_value(&p->motion.momentum); p->rand_timer.range = 0x68; - if (b) { + if (animation_request_mode) { if (get_hero_idle_animation_index(0) == 0x54) { set_hero_animation( get_hero_idle_animation_index(0), 0, (float)scale_game_frames(0x12)); @@ -193,7 +193,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x14; p->unk2284 = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (animation_request_mode) set_hero_animation(0x45, 0, (float)scale_game_frames(0xC)); break; } @@ -204,7 +204,7 @@ int hero_set_state(int requested_state, int b) { p->health.hp = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); FUN_L00_0025f730(&p->motion.momentum, frame_time * 3.5f); - if (b) + if (animation_request_mode) set_hero_animation(0x7C, 0, (float)scale_game_frames(0xC)); break; } @@ -220,7 +220,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->unk6A0 = 0; p->unk690 = p->motion.pos.f[2] - p->unk69C; - if (b) + if (animation_request_mode) set_hero_animation(0x74, 0, (float)scale_game_frames(0xB)); break; } @@ -242,7 +242,7 @@ int hero_set_state(int requested_state, int b) { q->rand_timer.range = 0x68; q->unk8E0 = 0; n = scale_game_frames(0xC); - if (b) + if (animation_request_mode) set_hero_animation(0x3B, 0, (float)n); } break; @@ -263,7 +263,7 @@ int hero_set_state(int requested_state, int b) { n = scale_game_frames(0xB); if (p->state.prev == 0x33) n = scale_game_frames(0xF); - if (b) + if (animation_request_mode) set_hero_animation(0x3D, 0, (float)n); break; } @@ -280,7 +280,7 @@ int hero_set_state(int requested_state, int b) { t = -2; if (p->state.prev != 0x35) t = n; - if (b) + if (animation_request_mode) set_hero_animation(0x3C, 0, (float)t); break; } @@ -353,7 +353,7 @@ int hero_set_state(int requested_state, int b) { s->motion.momentum.f[2] = 0.0f; FUN_L00_0025f730(&s->motion.momentum, frame_time * 5.5f); s->rand_timer.range = 0x68; - if (b) + if (animation_request_mode) set_hero_animation(0x3A, 0, (float)scale_game_frames(0x16)); } break; @@ -377,7 +377,7 @@ int hero_set_state(int requested_state, int b) { int t = scale_game_frames(0x4D); struct Hero *q = &hero; q->invulnerable_frames = t; - if (b) { + if (animation_request_mode) { if (q->state.current == 0x75) { set_hero_animation(0x70, 3, -3.0f); } else { @@ -400,7 +400,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->drown_sink_speed = 0; p->unk698 = scale_game_frames(0x2D); p->rand_timer.range = 0x68; - if (b) + if (animation_request_mode) set_hero_animation(0x65, 0, (float)scale_game_frames(0x11)); break; } @@ -440,7 +440,7 @@ int hero_set_state(int requested_state, int b) { v = (char *)&hero.motion.momentum; qcopy(v, v - 0x40); } - if (b) + if (animation_request_mode) set_hero_animation(0x5F, 0, (float)scale_game_frames(0xA)); break; } @@ -451,7 +451,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->health.hp = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (animation_request_mode) set_hero_animation(0x80, 0, (float)scale_game_frames(0xA)); break; } @@ -463,7 +463,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&D_L08_0015F688 = scale_game_frames(0x3C); if (p->unk20AA == 0) { t = get_hero_idle_animation_index(1); - if (p->moby->prev_seq != t && b) { + if (p->moby->prev_seq != t && animation_request_mode) { set_hero_animation(t, 0, (float)scale_game_frames(0x12)); } } @@ -555,7 +555,7 @@ int hero_set_state(int requested_state, int b) { scale_game_frames(5) < u->rail_land_frames) n = scale_game_frames(0xD); } - if (b) { + if (animation_request_mode) { struct Hero *v = &hero; set_hero_animation(v->state.step + 3, D_L08_0015F6D8[v->state.step], (float)n); } @@ -567,7 +567,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 1; p->unk2284 = 0; - if (b) { + if (animation_request_mode) { if (p->state.prev == 4) { set_hero_animation(0x5E, 2, (float)scale_game_frames(5)); } else { @@ -584,7 +584,7 @@ int hero_set_state(int requested_state, int b) { p->item_use_locked = 1; if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); - if (b) { + if (animation_request_mode) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { @@ -603,7 +603,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; fill_transfer_words((char *)p + 0x9D0, 0, 0x20); qcopy(&p->motion.momentum, &p->motion.displacement); - if (b) + if (animation_request_mode) set_hero_animation(0x64, 0, (float)scale_game_frames(0xF)); break; } @@ -625,7 +625,7 @@ int hero_set_state(int requested_state, int b) { } return 0; } - if (b) { + if (animation_request_mode) { struct Hero *q = &hero; float d = q->anim_frame; int id = 6; @@ -642,7 +642,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = gravity_length_xy((float *)v); qcopy(&p->motion.momentum, v); - if (b) { + if (animation_request_mode) { int id = 6; float d = p->anim_frame; if (return_hero_animation_id_unchanged(MOBY(moby)->seq) == 4 && 3.0f < d && d < 16.0f) @@ -669,7 +669,7 @@ int hero_set_state(int requested_state, int b) { FUN_L00_0025f730(&q->motion.momentum, frame_time * 7.0f); if (frame_time * 3.5f < q->motion.forward_speed) allocate_hero_voice_for_entry(0xC, 0); - if (b) { + if (animation_request_mode) { if (q->moby->seq == get_hero_idle_animation_index(0)) { set_hero_animation(0xD, 2, (float)scale_game_frames(9)); } else { @@ -696,7 +696,7 @@ int hero_set_state(int requested_state, int b) { } p->motion.move_yaw = fast_arc_tan(p->grapple_target->pos.x - p->motion.pos.f[0], p->grapple_target->pos.y - p->motion.pos.f[1]); - if (b) { + if (animation_request_mode) { set_hero_animation(0x2F, 2, (float)scale_game_frames(5)); hero_queue_sequence(0xA, 0xE); } @@ -709,7 +709,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->grapple_pull_speed = 0; p->grapple_pull_ending = 0; p->item_use_locked = 1; - if (b) + if (animation_request_mode) set_hero_animation(0x30, 1, (float)scale_game_frames(0xA)); break; } @@ -721,7 +721,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->grapple_pull_speed = 0; p->grapple_pull_ending = 0; p->tether_radius = fast_vec_dist(&p->motion.pos, &p->grapple_target->pos); - if (b) + if (animation_request_mode) set_hero_animation(0x30, 1, (float)scale_game_frames(5)); break; } @@ -777,7 +777,7 @@ int hero_set_state(int requested_state, int b) { } else if (q->state.prev_control_mode == 2) { q->swing_gravity = q->fall_state_gravity; } - if (b) { + if (animation_request_mode) { set_hero_animation(0x34, 0, (float)scale_game_frames(0xB)); { struct Hero *r = &hero; @@ -793,7 +793,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 7; clear_u64_value(&p->motion.rot_spring_vel); qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (animation_request_mode) set_hero_animation(0xB, 0, (float)scale_game_frames(0xF)); break; } @@ -805,7 +805,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->past_apex = 0; p->rise_fall_land_frames = 0; p->rise_fall_gravity = frame_time_sq * 100.0f; - if (b) + if (animation_request_mode) set_hero_animation(0x2A, 0, (float)scale_game_frames(6)); break; } @@ -855,7 +855,7 @@ int hero_set_state(int requested_state, int b) { } } } - if (b) { + if (animation_request_mode) { struct Hero *r = &hero; set_hero_animation(r->grind_anim_variant + 0x31, 0, (float)scale_game_frames(6)); } @@ -872,7 +872,7 @@ int hero_set_state(int requested_state, int b) { p->unk4F0 = p->smoothed_ground_z; } p->item_select_blocked = 1; - if (b) { + if (animation_request_mode) { if (frame_time * 3.5f < p->motion.flat_speed) { set_hero_animation(0x20, 0, (float)scale_game_frames(9)); } else { @@ -887,7 +887,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0xD; p->item_select_blocked = 1; p->rand_timer.range = 0x68; - if (b) + if (animation_request_mode) set_hero_animation(0x21, 0, (float)scale_game_frames(6)); break; } @@ -896,7 +896,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 3; p->unk2284 = 0xD; p->item_select_blocked = 1; - if (b) + if (animation_request_mode) set_hero_animation(0x24, 0, (float)scale_game_frames(6)); break; } @@ -905,7 +905,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 3; p->unk2284 = 0xD; p->item_select_blocked = 1; - if (b) + if (animation_request_mode) set_hero_animation(0x25, 0, (float)scale_game_frames(6)); break; } @@ -914,7 +914,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 2; p->unk2284 = 0; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (animation_request_mode) set_hero_animation(0xB, 0, (float)scale_game_frames(0xC)); break; } @@ -938,7 +938,7 @@ int hero_set_state(int requested_state, int b) { q->rand_timer.range = 0x68; q->state.step = 0; qcopy(&q->motion.velocity, &q->motion.resolved_velocity); - if (b) { + if (animation_request_mode) { if (q->vehicle_mode == 3) { set_hero_animation(6, 0, (float)scale_game_frames(8)); return 1; @@ -964,7 +964,7 @@ int hero_set_state(int requested_state, int b) { scale_hero_motion(frame_time * 4.5f / p->motion.speed_xy); } qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) { + if (animation_request_mode) { set_hero_animation(0x13, 0, (float)animation_timing_profile_selector); } break; @@ -979,7 +979,7 @@ int hero_set_state(int requested_state, int b) { scale_hero_motion(frame_time * 4.5f / p->motion.speed_xy); } qcopy(&p->motion.velocity, &p->motion.displacement); - if (b) { + if (animation_request_mode) { set_hero_animation(0x13, 0, (float)animation_timing_selector); } break; @@ -1331,7 +1331,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; if (q->fall_start_distance == 0.0f) q->fall_start_distance = q->unk430 * 1.5f; - if (b) { + if (animation_request_mode) { int s = q->state.current; if (s == 7) { set_hero_animation(7, 0, (float)scale_game_frames(5)); @@ -1432,7 +1432,7 @@ int hero_set_state(int requested_state, int b) { update_hero_target_heading(8.0f, 1.0471976f, -1.0f); *(int *)&q->slam_descending = 0; q->items[0].timer = 0xA; - if (b) { + if (animation_request_mode) { char *m; int n = scale_game_frames(0xB); if (q->state.prev == 0xB && scale_game_frames(0x2A) > q->state.prev_timer) @@ -1469,7 +1469,7 @@ int hero_set_state(int requested_state, int b) { q->saved_item[0] = 0; update_hero_target_heading(14.0f, 0.5235988f, -1.0f); q->unkA7C = q->unkA7C == 0; - if (b) { + if (animation_request_mode) { int n = scale_game_frames(0xA); if (q->moby->prev_seq == 0x1A) n = scale_game_frames(3); @@ -1484,7 +1484,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; if (((void *)q->items[0].moby) == 0) break; - if (b) { + if (animation_request_mode) { set_hero_animation(0x67, 4, -1.0f); blend_moby_animation(((void *)q->items[0].moby), 3, 4, -1); } @@ -1515,7 +1515,7 @@ int hero_set_state(int requested_state, int b) { r->attack_record = k; } update_hero_target_heading(5.0f, 0.7853982f, 0.7853982f); - if (b) { + if (animation_request_mode) { char *m; int j = 0; int n; @@ -1546,7 +1546,7 @@ int hero_set_state(int requested_state, int b) { } case HERO_STATE_ANIMATION_RECOVERY_WITH_JUMP_CANCEL: { struct Hero *q; - if (b) + if (animation_request_mode) set_hero_animation(0x2C, 7, (float)scale_game_frames(9)); q = &hero; if (q->items[0].item_id == 0xA && ((char *)q->throw_target) != 0) { @@ -1575,7 +1575,7 @@ int hero_set_state(int requested_state, int b) { { struct Hero *q = &hero; int e = D_L08_0017C428[q->attack_record].kind; - if (b) { + if (animation_request_mode) { char *m; int z = e == 0; int n = scale_game_frames(5); @@ -1596,7 +1596,7 @@ int hero_set_state(int requested_state, int b) { } else { p->attack_record = 0; } - if (b) { + if (animation_request_mode) { struct Hero *q = &hero; char *m; int n = scale_game_frames(4); @@ -1612,7 +1612,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0xA; p->unk2284 = 0; p->ground_speed = frame_time * 9.0f; - if (b) { + if (animation_request_mode) { char *m; HeroTableRow2C *e = &D_L08_0017C428[p->attack_record]; int k = e->kind; @@ -1633,7 +1633,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->pushback_yaw = fast_add_rotations(p->motion.rot.f[2], 3.1415927f); p->ground_speed = frame_time * 9.0f; - if (b) + if (animation_request_mode) set_hero_animation(0x29, 5, (float)scale_game_frames(8)); break; } @@ -1655,7 +1655,7 @@ int hero_set_state(int requested_state, int b) { { struct Hero *q = &hero; q->invulnerable_frames = scale_game_frames(0x4D); - if (b) { + if (animation_request_mode) { set_hero_animation(0x10, 3, -3.0f); q->moby->anim_time = hero_animation_blend_curves[q->anim_blend_curve][(q->anim_blend_step)++]; @@ -1667,7 +1667,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 0; p->unk2284 = 0; - if (b) + if (animation_request_mode) set_hero_animation(0, 0, (float)scale_game_frames(0xE)); break; } @@ -1675,7 +1675,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 0; p->unk2284 = 0; - if (b) { + if (animation_request_mode) { set_hero_animation(4, 0, (float)scale_game_frames(7)); hero_queue_sequence(0xE, 0x22); } @@ -1686,7 +1686,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 2; p->unk2284 = 0; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (animation_request_mode) set_hero_animation(6, 0, (float)scale_game_frames(0xC)); break; } @@ -1697,7 +1697,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (animation_request_mode) set_hero_animation(6, 0, (float)scale_game_frames(7)); break; } @@ -1714,7 +1714,7 @@ int hero_set_state(int requested_state, int b) { if (frame_time * 1.5f < planar_speed) hero_base->ground_speed = frame_time * 1.5f; hero_base->unk3B8 = 0; - if (b) + if (animation_request_mode) set_hero_animation(1, 0, (float)scale_game_frames(8)); } break; @@ -1724,7 +1724,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x14; p->unk2284 = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (animation_request_mode) set_hero_animation(3, 0, (float)scale_game_frames(0xC)); break; } @@ -1737,7 +1737,7 @@ int hero_set_state(int requested_state, int b) { FUN_L00_0025f730(&p->motion.velocity, frame_time * 5.0f); hero_change_health(1); p->invulnerable_frames = scale_game_frames(0x4D); - if (b) { + if (animation_request_mode) { set_hero_animation(2, 3, -3.0f); p->moby->anim_time = hero_animation_blend_curves[p->anim_blend_curve][(p->anim_blend_step)++]; @@ -1758,7 +1758,7 @@ int hero_set_state(int requested_state, int b) { clear_u64_value(&p->motion.velocity); clear_u64_value(&p->motion.displacement); p->motion.velocity.f[2] = frame_time * 10.0f; - if (b) + if (animation_request_mode) set_hero_animation(0x10, 2, -3.0f); break; } @@ -1810,7 +1810,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->tilt_disabled = 1; p->item_use_locked = 1; - if (b) + if (animation_request_mode) set_hero_animation(get_hero_idle_animation_index(0), 0, -1.0f); break; } @@ -1821,7 +1821,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->item_use_locked = 1; clear_u64_value(&p->motion.velocity); - if (b) + if (animation_request_mode) set_hero_animation(0xB, 0, -1.0f); break; } @@ -1845,7 +1845,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x18; p->item_use_locked = 1; cancel_hero_item_animation(); - if (b) + if (animation_request_mode) set_hero_animation(get_hero_idle_animation_index(0), 0, -1.0f); break; } From bdff07ef4b84fe9276264ba86399338f307520d3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:32:24 +0000 Subject: [PATCH 1367/1502] decomp: clarify names in hero_set_state b -> entry_animation_mode: Retail 0x0022b780 saves second argument a1 in s4. Tests of s4 at 0x0022b9b8, 0x0022baf8, 0x0022d754 and 0x0022e308 skip conditional state-entry animation setup to 0x0022e944 when zero; nonzero reaches set_hero_animation at 0x0022e8f8 or case-specific calls, including hurt blend setup. Original Ghidra param_2 tests and authoritative if(b) branches agree. At 0x0022b790..0x0022b798 and 0x0022b7a4..0x0022b7bc, value 2 also permits the guarded state request. Thus this is an integer entry-animation mode, not merely a boolean. Supplied transition source calls hero_set_state(HERO_STATE_IDLE,0) before explicitly selecting an animation; ordinary state changes use 1. --- src/overlays/l02/hero/hero_set_state.c | 104 ++++++++++++------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/src/overlays/l02/hero/hero_set_state.c b/src/overlays/l02/hero/hero_set_state.c index 05305e4593..2c3ad4aaec 100644 --- a/src/overlays/l02/hero/hero_set_state.c +++ b/src/overlays/l02/hero/hero_set_state.c @@ -69,17 +69,17 @@ extern void blend_moby_animation(void *, int, int, int) __asm__("FUN_00212f90"); extern int hero_set_state(int, int) __asm__("FUN_L02_0022b728"); extern char level02_hero_transform_trail_jump_velocity_keys[] __asm__("D_L02_0017C520"); -int hero_set_state(int requested_state, int b) { +int hero_set_state(int requested_state, int entry_animation_mode) { int saved_state_step; char *moby; int old20A7; { struct Hero *p = &hero; if (p->state.control_mode == 0x14 && - (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || b != 2)) + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || entry_animation_mode != 2)) return 0; } - if ((level_game_mode == 2 || level_game_mode == 6) && b != 2) + if ((level_game_mode == 2 || level_game_mode == 6) && entry_animation_mode != 2) return 0; { struct Hero *p = &hero; @@ -151,7 +151,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; q->rand_timer.range = 0x68; } - if (b) { + if (entry_animation_mode) { if (get_hero_idle_animation_index(0) == 0x54) { set_hero_animation( get_hero_idle_animation_index(0), 0, (float)scale_game_frames(0x12)); @@ -167,7 +167,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; clear_u64_value(&p->motion.momentum); p->rand_timer.range = 0x68; - if (b) { + if (entry_animation_mode) { if (get_hero_idle_animation_index(0) == 0x54) { set_hero_animation( get_hero_idle_animation_index(0), 0, (float)scale_game_frames(0x12)); @@ -193,7 +193,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x14; p->unk2284 = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0x45, 0, (float)scale_game_frames(0xC)); break; } @@ -204,7 +204,7 @@ int hero_set_state(int requested_state, int b) { p->health.hp = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); FUN_L00_0025f730(&p->motion.momentum, frame_time * 3.5f); - if (b) + if (entry_animation_mode) set_hero_animation(0x7C, 0, (float)scale_game_frames(0xC)); break; } @@ -220,7 +220,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->unk6A0 = 0; p->unk690 = p->motion.pos.f[2] - p->unk69C; - if (b) + if (entry_animation_mode) set_hero_animation(0x74, 0, (float)scale_game_frames(0xB)); break; } @@ -232,7 +232,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&D_L02_0015F688 = scale_game_frames(0x3C); if (p->unk20AA == 0) { t = get_hero_idle_animation_index(1); - if (p->moby->prev_seq != t && b) { + if (p->moby->prev_seq != t && entry_animation_mode) { set_hero_animation(t, 0, (float)scale_game_frames(0x12)); } } @@ -321,7 +321,7 @@ int hero_set_state(int requested_state, int b) { scale_game_frames(5) < u->rail_land_frames) n = scale_game_frames(0xD); } - if (b) { + if (entry_animation_mode) { struct Hero *v = &hero; set_hero_animation(v->state.step + 3, D_L02_0015F6D8[v->state.step], (float)n); } @@ -333,7 +333,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 1; p->unk2284 = 0; - if (b) { + if (entry_animation_mode) { if (p->state.prev == 4) { set_hero_animation(0x5E, 2, (float)scale_game_frames(5)); } else { @@ -350,7 +350,7 @@ int hero_set_state(int requested_state, int b) { p->item_use_locked = 1; if (p->vehicle_mode == HERO_VEHICLE_MODE_ON_FOOT) cancel_hero_item_animation(); - if (b) { + if (entry_animation_mode) { if (p->vehicle_mode == 3) { set_hero_animation(1, 0, (float)scale_game_frames(8)); } else if (p->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { @@ -380,7 +380,7 @@ int hero_set_state(int requested_state, int b) { } return 0; } - if (b) { + if (entry_animation_mode) { struct Hero *q = &hero; float d = q->anim_frame; int id = 6; @@ -397,7 +397,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->ground_speed = gravity_length_xy((float *)v); qcopy(&p->motion.momentum, v); - if (b) { + if (entry_animation_mode) { int id = 6; float d = p->anim_frame; if (return_hero_animation_id_unchanged(MOBY(moby)->seq) == 4 && 3.0f < d && d < 16.0f) @@ -424,7 +424,7 @@ int hero_set_state(int requested_state, int b) { FUN_L00_0025f730(&q->motion.momentum, frame_time * 7.0f); if (frame_time * 3.5f < q->motion.forward_speed) allocate_hero_voice_for_entry(0xC, 0); - if (b) { + if (entry_animation_mode) { if (q->moby->seq == get_hero_idle_animation_index(0)) { set_hero_animation(0xD, 2, (float)scale_game_frames(9)); } else { @@ -451,7 +451,7 @@ int hero_set_state(int requested_state, int b) { } p->motion.move_yaw = fast_arc_tan(p->grapple_target->pos.x - p->motion.pos.f[0], p->grapple_target->pos.y - p->motion.pos.f[1]); - if (b) { + if (entry_animation_mode) { set_hero_animation(0x2F, 2, (float)scale_game_frames(5)); hero_queue_sequence(0xA, 0xE); } @@ -464,7 +464,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->grapple_pull_speed = 0; p->grapple_pull_ending = 0; p->item_use_locked = 1; - if (b) + if (entry_animation_mode) set_hero_animation(0x30, 1, (float)scale_game_frames(0xA)); break; } @@ -476,7 +476,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->grapple_pull_speed = 0; p->grapple_pull_ending = 0; p->tether_radius = fast_vec_dist(&p->motion.pos, &p->grapple_target->pos); - if (b) + if (entry_animation_mode) set_hero_animation(0x30, 1, (float)scale_game_frames(5)); break; } @@ -532,7 +532,7 @@ int hero_set_state(int requested_state, int b) { } else if (q->state.prev_control_mode == 2) { q->swing_gravity = q->fall_state_gravity; } - if (b) { + if (entry_animation_mode) { set_hero_animation(0x34, 0, (float)scale_game_frames(0xB)); { struct Hero *r = &hero; @@ -548,7 +548,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 7; clear_u64_value(&p->motion.rot_spring_vel); qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0xB, 0, (float)scale_game_frames(0xF)); break; } @@ -560,7 +560,7 @@ int hero_set_state(int requested_state, int b) { *(int *)&p->past_apex = 0; p->rise_fall_land_frames = 0; p->rise_fall_gravity = frame_time_sq * 100.0f; - if (b) + if (entry_animation_mode) set_hero_animation(0x2A, 0, (float)scale_game_frames(6)); break; } @@ -575,7 +575,7 @@ int hero_set_state(int requested_state, int b) { p->unk4F0 = p->smoothed_ground_z; } p->item_select_blocked = 1; - if (b) { + if (entry_animation_mode) { if (frame_time * 3.5f < p->motion.flat_speed) { set_hero_animation(0x20, 0, (float)scale_game_frames(9)); } else { @@ -590,7 +590,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0xD; p->item_select_blocked = 1; p->rand_timer.range = 0x68; - if (b) + if (entry_animation_mode) set_hero_animation(0x21, 0, (float)scale_game_frames(6)); break; } @@ -599,7 +599,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 3; p->unk2284 = 0xD; p->item_select_blocked = 1; - if (b) + if (entry_animation_mode) set_hero_animation(0x24, 0, (float)scale_game_frames(6)); break; } @@ -608,7 +608,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 3; p->unk2284 = 0xD; p->item_select_blocked = 1; - if (b) + if (entry_animation_mode) set_hero_animation(0x25, 0, (float)scale_game_frames(6)); break; } @@ -617,7 +617,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 2; p->unk2284 = 0; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0xB, 0, (float)scale_game_frames(0xC)); break; } @@ -641,7 +641,7 @@ int hero_set_state(int requested_state, int b) { q->rand_timer.range = 0x68; q->state.step = 0; qcopy(&q->motion.velocity, &q->motion.resolved_velocity); - if (b) { + if (entry_animation_mode) { if (q->vehicle_mode == 3) { set_hero_animation(6, 0, (float)scale_game_frames(8)); return 1; @@ -667,7 +667,7 @@ int hero_set_state(int requested_state, int b) { scale_hero_motion(frame_time * 4.5f / p->motion.speed_xy); } qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) { + if (entry_animation_mode) { set_hero_animation(0x13, 0, (float)animation_timing_selector); } break; @@ -682,7 +682,7 @@ int hero_set_state(int requested_state, int b) { scale_hero_motion(frame_time * 4.5f / p->motion.speed_xy); } qcopy(&p->motion.velocity, &p->motion.displacement); - if (b) { + if (entry_animation_mode) { set_hero_animation(0x13, 0, (float)animation_timing_selector); } break; @@ -983,7 +983,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; if (q->fall_start_distance == 0.0f) q->fall_start_distance = q->unk430 * 1.5f; - if (b) { + if (entry_animation_mode) { int s = q->state.current; if (s == 7) { set_hero_animation(7, 0, (float)scale_game_frames(5)); @@ -1073,7 +1073,7 @@ int hero_set_state(int requested_state, int b) { update_hero_target_heading(8.0f, 1.0471976f, -1.0f); *(int *)&q->slam_descending = 0; q->items[0].timer = 0xA; - if (b) { + if (entry_animation_mode) { char *m; int n = scale_game_frames(0xB); if (q->state.prev == 0xB && scale_game_frames(0x2A) > q->state.prev_timer) @@ -1111,7 +1111,7 @@ int hero_set_state(int requested_state, int b) { q->saved_item[0] = 0; update_hero_target_heading(14.0f, 0.5235988f, -1.0f); q->unkA7C = q->unkA7C == 0; - if (b) { + if (entry_animation_mode) { int n = scale_game_frames(0xA); if (q->moby->prev_seq == 0x1A) n = scale_game_frames(3); @@ -1126,7 +1126,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *q = &hero; if (((void *)q->items[0].moby) == 0) break; - if (b) { + if (entry_animation_mode) { set_hero_animation(0x67, 4, -1.0f); blend_moby_animation(((void *)q->items[0].moby), 3, 4, -1); } @@ -1157,7 +1157,7 @@ int hero_set_state(int requested_state, int b) { r->attack_record = k; } update_hero_target_heading(5.0f, 0.7853982f, 0.7853982f); - if (b) { + if (entry_animation_mode) { char *m; int j = 0; int n; @@ -1188,7 +1188,7 @@ int hero_set_state(int requested_state, int b) { } case HERO_STATE_ANIMATION_RECOVERY_WITH_JUMP_CANCEL: { struct Hero *q; - if (b) + if (entry_animation_mode) set_hero_animation(0x2C, 7, (float)scale_game_frames(9)); q = &hero; if (q->items[0].item_id == 0xA && ((char *)q->throw_target) != 0) { @@ -1217,7 +1217,7 @@ int hero_set_state(int requested_state, int b) { { struct Hero *q = &hero; int e = D_L02_0017C228[q->attack_record].kind; - if (b) { + if (entry_animation_mode) { char *m; int z = e == 0; int n = scale_game_frames(5); @@ -1234,7 +1234,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0xA; p->unk2284 = 0; p->ground_speed = frame_time * 9.0f; - if (b) { + if (entry_animation_mode) { char *m; HeroTableRow2C *e = &D_L02_0017C228[p->attack_record]; int k = e->kind; @@ -1255,7 +1255,7 @@ int hero_set_state(int requested_state, int b) { p->unk2284 = 0; p->pushback_yaw = fast_add_rotations(p->motion.rot.f[2], 3.1415927f); p->ground_speed = frame_time * 9.0f; - if (b) + if (entry_animation_mode) set_hero_animation(0x29, 5, (float)scale_game_frames(8)); break; } @@ -1277,7 +1277,7 @@ int hero_set_state(int requested_state, int b) { { struct Hero *q = &hero; q->invulnerable_frames = scale_game_frames(0x4D); - if (b) { + if (entry_animation_mode) { set_hero_animation(0x10, 3, -3.0f); q->moby->anim_time = hero_animation_blend_curve_samples[q->anim_blend_curve][(q->anim_blend_step)++]; @@ -1302,7 +1302,7 @@ int hero_set_state(int requested_state, int b) { r->rand_timer.range = 0x68; r->target_speed = 0.0f; r->ground_speed = 0.0f; - if (b) + if (entry_animation_mode) set_hero_animation(0x71, 0, (float)scale_game_frames(8)); } break; @@ -1316,7 +1316,7 @@ int hero_set_state(int requested_state, int b) { p->collision_off_frames = 0x2710; allocate_hero_voice_for_entry(9, 0); p->rand_timer.range = 0x68; - if (b) + if (entry_animation_mode) set_hero_animation(0x71, 0, (float)scale_game_frames(8)); break; } @@ -1324,7 +1324,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 0; p->unk2284 = 0; - if (b) + if (entry_animation_mode) set_hero_animation(0, 0, (float)scale_game_frames(0xE)); break; } @@ -1332,7 +1332,7 @@ int hero_set_state(int requested_state, int b) { struct Hero *p = &hero; p->state.control_mode = 0; p->unk2284 = 0; - if (b) { + if (entry_animation_mode) { set_hero_animation(4, 0, (float)scale_game_frames(7)); hero_queue_sequence(0xE, 0x22); } @@ -1343,7 +1343,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 2; p->unk2284 = 0; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(6, 0, (float)scale_game_frames(0xC)); break; } @@ -1354,7 +1354,7 @@ int hero_set_state(int requested_state, int b) { p->fall_state_gravity = frame_time_sq * 24.0f; p->stickless_decel = frame_time_sq * 7.0f; qcopy(&p->motion.velocity, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(6, 0, (float)scale_game_frames(7)); break; } @@ -1371,7 +1371,7 @@ int hero_set_state(int requested_state, int b) { if (frame_time * 1.5f < planar_speed) hero_base->ground_speed = frame_time * 1.5f; hero_base->unk3B8 = 0; - if (b) + if (entry_animation_mode) set_hero_animation(1, 0, (float)scale_game_frames(8)); } break; @@ -1381,7 +1381,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x14; p->unk2284 = 0; qcopy(&p->motion.momentum, &p->motion.resolved_velocity); - if (b) + if (entry_animation_mode) set_hero_animation(3, 0, (float)scale_game_frames(0xC)); break; } @@ -1394,7 +1394,7 @@ int hero_set_state(int requested_state, int b) { FUN_L00_0025f730(&p->motion.velocity, frame_time * 5.0f); hero_change_health(1); p->invulnerable_frames = scale_game_frames(0x4D); - if (b) { + if (entry_animation_mode) { set_hero_animation(2, 3, -3.0f); p->moby->anim_time = hero_animation_blend_curve_samples[p->anim_blend_curve][(p->anim_blend_step)++]; @@ -1415,7 +1415,7 @@ int hero_set_state(int requested_state, int b) { clear_u64_value(&p->motion.velocity); clear_u64_value(&p->motion.displacement); p->motion.velocity.f[2] = frame_time * 10.0f; - if (b) + if (entry_animation_mode) set_hero_animation(0x10, 2, -3.0f); break; } @@ -1467,7 +1467,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->tilt_disabled = 1; p->item_use_locked = 1; - if (b) + if (entry_animation_mode) set_hero_animation(get_hero_idle_animation_index(0), 0, -1.0f); break; } @@ -1478,7 +1478,7 @@ int hero_set_state(int requested_state, int b) { p->item_select_blocked = 1; p->item_use_locked = 1; clear_u64_value(&p->motion.velocity); - if (b) + if (entry_animation_mode) set_hero_animation(0xB, 0, -1.0f); break; } @@ -1488,7 +1488,7 @@ int hero_set_state(int requested_state, int b) { p->state.control_mode = 0x18; p->item_use_locked = 1; cancel_hero_item_animation(); - if (b) + if (entry_animation_mode) set_hero_animation(get_hero_idle_animation_index(0), 0, -1.0f); break; } From 2b81d2de3eee3300c9f2aef5d84f718d66fe53c6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:32:24 +0000 Subject: [PATCH 1368/1502] decomp: clarify names in hero_update_movement t2 -> swim_usage_time_bucket: The unique s32 t2 in the shared swimming block receives scale_game_frames(D_0015EEA4)/600 and is compared to usage_stats.stat[11].latest_time_bucket. Retail 0x0021874c-0x00218774 loads the frame source, calls 0x001fef20, divides by 0x258 and compares the quotient with the unsigned halfword at usage_stats+0x5a. Retail 0x00218780-0x0021879c recomputes and stores that bucket when larger. Original Ghidra confirms iVar12/600 compared with uRam001418a2 and stored there, proving a swim-usage time bucket. --- src/overlays/shared/hero/hero_update_movement.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/hero/hero_update_movement.c b/src/overlays/shared/hero/hero_update_movement.c index 9311fc312f..a2e76270c2 100644 --- a/src/overlays/shared/hero/hero_update_movement.c +++ b/src/overlays/shared/hero/hero_update_movement.c @@ -549,13 +549,13 @@ void hero_update_movement(void) { if (PD.held & 0x40) { hero.jump_button_frames++; if (PD.analog[10] > 0.75f) { - s32 t2; + s32 swim_usage_time_bucket; if (++hero.swim_hard_press_frames > scale_game_frames(90) && usage_stats.stat[11].count < 0xFFFF) { usage_stats.stat[11].count++; } - t2 = scale_game_frames(D_0015EEA4) / 600; - if (usage_stats.stat[11].latest_time_bucket < t2) { + swim_usage_time_bucket = scale_game_frames(D_0015EEA4) / 600; + if (usage_stats.stat[11].latest_time_bucket < swim_usage_time_bucket) { usage_stats.stat[11].latest_time_bucket = scale_game_frames(D_0015EEA4) / 600; } From b19442765fe28d4381d61dc73817ed2ff35b43a4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:32:24 +0000 Subject: [PATCH 1369/1502] decomp: clarify names in spawn_sentrybot_projectile domain_0_value_0 -> SENTRYBOT_PROJECTILE_STATE_FLYING: Retail spawn_sentrybot_projectile creates class 0x3A6 at 0x002e45a4/0x002e45a8 and keeps the result in s1; 0x002e45e0 sb zero,0x20(s1) assigns Moby.state=0. The authoritative current source (src/overlays/shared/enemies/sentrybot_projectile.c, SHA-256 7a787092857fb5dfb46e5bc64239647e65ed5ae75d2121228ff2670ea2903857) shows sentrybot_projectile_update returning for state!=0, while state zero spins rot.x, adds the private velocity vector to position, checks swept collision/sphere/timer and commits next_position. The spawner initializes this velocity from direction_vector scaled by 5.0f (retail 0x002e45f8-0x002e460c) and derives flight orientation (0x002e4634-0x002e4664), proving the projectile-specific flying state rather than a boolean or generic shared state. --- src/overlays/shared/enemies/sentrybot_projectile.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/sentrybot_projectile.c b/src/overlays/shared/enemies/sentrybot_projectile.c index 7f6d4429e8..bd0065a322 100644 --- a/src/overlays/shared/enemies/sentrybot_projectile.c +++ b/src/overlays/shared/enemies/sentrybot_projectile.c @@ -68,13 +68,16 @@ char *spawn_sentrybot_projectile(char *source_moby, char *pos) __asm__("FUN_L15_002e4580"); char *spawn_sentrybot_projectile(char *source_moby, float *direction_vector, char *spawn_position) { + enum { + SENTRYBOT_PROJECTILE_STATE_FLYING = 0 + }; char *spawned_moby = create_moby(0x3A6); if (spawned_moby != 0) { char *moby_vars; MOBY(spawned_moby)->update_dist = 0xFF; MOBY(spawned_moby)->draw_dist = 0xFF; MOBY(spawned_moby)->visible = 1; - MOBY(spawned_moby)->state = 0; + MOBY(spawned_moby)->state = SENTRYBOT_PROJECTILE_STATE_FLYING; MOBY(spawned_moby)->spawn_frame = ((long)MOBY(source_moby)->spawn_frame); MOBY(spawned_moby)->scale = MOBY(spawned_moby)->scale * 20.0f; qcopy(&MOBY(spawned_moby)->pos, spawn_position); From 295c264c71fcfd018ebb10f4244e7d49fd593fd0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:32:25 +0000 Subject: [PATCH 1370/1502] decomp: clarify names in voice_update_callback domain_0_value_0 -> VOICE_SLOT_FREE: Authoritative src/audio/sound/voice_update_callback.c (SHA-256 b9c6bdb9cba76561d716b635c9c8daf3bf4e8e181f17700d1d84d90587488d8c) types voice as VoiceSlot*. Retail 0x0022ddec stores handle at offset 0; 0x0022dde8 skips cleanup for a nonzero handle. Only for a zero handle, 0x0022ddf0 clears the state byte at offset 4, and 0x0022ddf4/0x0022ddf8 clear owner and owner_context. Thus the assigned zero is the unowned, free VoiceSlot state, matching the supplied existing VOICE_SLOT_FREE=0 in this voice-slot domain, rather than a Boolean or null-pointer domain. --- src/audio/sound/voice_update_callback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/sound/voice_update_callback.c b/src/audio/sound/voice_update_callback.c index fdc46f4be9..813af24c8c 100644 --- a/src/audio/sound/voice_update_callback.c +++ b/src/audio/sound/voice_update_callback.c @@ -10,7 +10,7 @@ void voice_update_callback(int handle, long voice_state_address) { if (handle == 0) { voice->owner = 0; voice->owner_context = 0; - voice->state = 0; + voice->state = VOICE_SLOT_FREE; } } } From 71f8c9368ce416e349fe4b26beda02848a2820e1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:32:25 +0000 Subject: [PATCH 1371/1502] decomp: clarify names in save_camera_vectors domain_0_value_0 -> CAMERA_TRANSITION_PRIMARY_SOLVER: Source snapshot src/camera/save_camera_vectors.c SHA-256 43be4aadb9aedca53954f48b5e96d19118b9d38ef97e76c7c897d80002d4a956 binds transition to cam_trans_state. Retail 0x001ec804 loads its +2 selector and 0x001ec808 skips the entire copy when nonzero. The original retail Ghidra identifies that byte as g_bCameraUseAlternateTransition, and the zero branch copies primary current position (+0x50) to alternate position (+0xc0) at 0x001ec810-0x001ec81c and primary current rotation (+0x60) to alternate destination rotation (+0xd0) at 0x001ec844-0x001ec850. Thus zero selects the primary solver whose vectors must be saved for the alternate solver; this is the current solver selector, distinct from the +3 requested mode. --- src/camera/save_camera_vectors.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/camera/save_camera_vectors.c b/src/camera/save_camera_vectors.c index 34c87cba13..e7745f7167 100644 --- a/src/camera/save_camera_vectors.c +++ b/src/camera/save_camera_vectors.c @@ -7,8 +7,11 @@ void save_camera_vectors(void) __asm__("FUN_001ec7f0"); void save_camera_vectors(void) { + enum { + CAMERA_TRANSITION_PRIMARY_SOLVER = 0 + }; struct CameraTransition *transition = &cam_trans_state; - if (transition->kind == 0) { + if (transition->kind == CAMERA_TRANSITION_PRIMARY_SOLVER) { qcopy(transition->orbit.saved_position, transition->blend.position); if (transition->requested_kind == 2) { fast_vec_add( From 957286a74631c11cd80d99393edcb92ceed860ad Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:32:25 +0000 Subject: [PATCH 1372/1502] decomp: clarify names in spawn_swingshot_hook domain_0_value_0 -> HOOK_INITIAL_ANIMATION: Retail 0x002c6fa4/0x002c6fa8 allocates class 0xd1, retained in s0 at 0x002c6fac; 0x002c7044 writes zero to that hook's state byte at +0x20 after selecting animation 0 at 0x002c7028..0x002c7034. The authoritative source's swingshot_hook_update switches on MOBY(hook_moby)->state with existing HOOK_INITIAL_ANIMATION=0; this case waits for anim_flags & 2, blends to idle animation 1 and advances the same state to 1. This proves the spawn assignment initializes the hook initial-animation state, not an owner control mode. --- src/overlays/shared/weapons/swingshot_hook.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/swingshot_hook.c b/src/overlays/shared/weapons/swingshot_hook.c index 50660338ad..89ab40e8d0 100644 --- a/src/overlays/shared/weapons/swingshot_hook.c +++ b/src/overlays/shared/weapons/swingshot_hook.c @@ -19,6 +19,9 @@ unsigned char *spawn_swingshot_hook(unsigned char *owner_moby, float initial_hook_speed) __asm__("FUN_L00_002c6f88"); unsigned char *spawn_swingshot_hook(unsigned char *owner_moby, float initial_hook_speed) { + enum { + HOOK_INITIAL_ANIMATION = 0 + }; unsigned char *spawned_moby = create_moby(0xd1); if (spawned_moby) { char *moby_vars = *(char **)(spawned_moby + 0x78); @@ -35,7 +38,7 @@ unsigned char *spawn_swingshot_hook(unsigned char *owner_moby, float initial_hoo if (MOBY(spawned_moby)->prev_seq) blend_moby_animation(spawned_moby, 0, 0, scale_game_frames(10)); update_entity(spawned_moby); - MOBY(spawned_moby)->state = 0; + MOBY(spawned_moby)->state = HOOK_INITIAL_ANIMATION; MOBY(spawned_moby)->flags |= 4; } return spawned_moby; From 5dde7017b9768e331b471192d0c8e7997a02173e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:32:25 +0000 Subject: [PATCH 1373/1502] decomp: clarify names in enter_streamed_moby_screen domain_1_value_3 -> STREAMED_MOBY_SCREEN_STATE_SETUP_FAILED: In enter_streamed_moby_screen, screen->state maps to +0x34(s0). Retail 0x00225598 calls create_menu_preview_moby(0x7a5); 0x002255a4 branches on a null result to 0x0022562c, which loads 3 and stores it to +0x34 at 0x00225630. The original Ghidra and authoritative C agree that this assignment records failure to create the required preview moby during screen setup. domain_2_value_3 -> STREAMED_MOBY_SCREEN_STATE_SETUP_FAILED: Retail 0x00225634 calls acquire_menu_stream_buffer with argument 1; 0x00225640 stores the returned address in screen +0x3c. At 0x0022563c a nonzero return skips the failure assignment; a zero result reaches 0x00225644/0x00225648, storing 3 in the same screen->state field at +0x34. Original Ghidra and authoritative C prove this is the same screen-setup failure state as the preview-moby failure branch. --- src/ui/menus/streamed_moby/enter_streamed_moby_screen.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ui/menus/streamed_moby/enter_streamed_moby_screen.c b/src/ui/menus/streamed_moby/enter_streamed_moby_screen.c index e679a0d540..879d2c674b 100644 --- a/src/ui/menus/streamed_moby/enter_streamed_moby_screen.c +++ b/src/ui/menus/streamed_moby/enter_streamed_moby_screen.c @@ -11,6 +11,9 @@ extern void helper_moby_update_noop(struct Moby *) __asm__("func_00225AB int enter_streamed_moby_screen(struct MenuStreamedMobyScreen *screen) __asm__("FUN_00225588"); int enter_streamed_moby_screen(struct MenuStreamedMobyScreen *screen) { + enum { + STREAMED_MOBY_SCREEN_STATE_SETUP_FAILED = 3 + }; struct Moby *preview_moby; int stream_buffer_address; preview_moby = create_menu_preview_moby(0x7A5); @@ -30,12 +33,12 @@ int enter_streamed_moby_screen(struct MenuStreamedMobyScreen *screen) { *(int *)(moby_sidecar + 4) = 0; *(int *)(moby_sidecar + 8) = 0; } else { - screen->state = 3; + screen->state = STREAMED_MOBY_SCREEN_STATE_SETUP_FAILED; } stream_buffer_address = acquire_menu_stream_buffer(1); screen->buffer = stream_buffer_address; if (stream_buffer_address == 0) { - screen->state = 3; + screen->state = STREAMED_MOBY_SCREEN_STATE_SETUP_FAILED; } return 0; } From 94077f23144cca079ddae56a9f361ebc1d8de449 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:34:36 +0000 Subject: [PATCH 1374/1502] decomp: clarify names in voice_start_callback domain_2_value_0 -> VOICE_SLOT_FREE: The authoritative source casts the second callback argument to VoiceSlot * and assigns voice->state = 0 only when the callback handle is zero, also clearing voice->owner and voice->owner_context. Retail 0x0022dda4 stores the handle at +0; the zero-handle branch at 0x0022dda0 reaches 0x0022ddc0-0x0022ddc8, clearing the same slot's state byte at +4 and ownership words at +0x18/+0x1c. This released voice-slot state matches the established VOICE_SLOT_FREE=0 constant in this domain, beyond numeric equality. --- src/audio/sound/voice_start_callback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/sound/voice_start_callback.c b/src/audio/sound/voice_start_callback.c index 755ecbaf60..dd03306ac5 100644 --- a/src/audio/sound/voice_start_callback.c +++ b/src/audio/sound/voice_start_callback.c @@ -14,7 +14,7 @@ void voice_start_callback(int handle, long voice_record_address) { } else { voice->owner = 0; voice->owner_context = 0; - voice->state = 0; + voice->state = VOICE_SLOT_FREE; } } } From 9695fea1c727a26b0fbd0976cf64793e9a18dd57 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:34:36 +0000 Subject: [PATCH 1375/1502] decomp: clarify names in cancel_suck_cannon_suction_and_set_moby_state_9 domain_0_value_9 -> MOBY_STATE_SUCK_CANNON_ACTIVE: Retail 0x002d57e0 preserves the moby a0 in s0; 0x002d57e4 loads 9 and 0x002d57ec stores it to moby+0x20 after jal cancel_suck_cannon_suction at 0x002d57dc. The SHA-bound source's neighboring process_suck_cannon_suction_and_update_moby_state defines MOBY_STATE_SUCK_CANNON_ACTIVE=0x9 for exactly MOBY(moby)->state, assigning 9 when suction_result is nonzero and restoring 5 when it becomes zero. Reuse this same moby-field domain member. Checked helper 0x002dbe50 reads the original object's +0x20 byte for removal checks, whereas 0x002dbe64 and 0x002dbefc read/write a different pointer's +0x68 halfword, proving that the suction-record states are separate. This enemy state is not proven to belong to HeroStateId. --- src/overlays/shared/enemies/horny_toad.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/horny_toad.c b/src/overlays/shared/enemies/horny_toad.c index 203bb47ee5..e61d6227f7 100644 --- a/src/overlays/shared/enemies/horny_toad.c +++ b/src/overlays/shared/enemies/horny_toad.c @@ -654,8 +654,11 @@ extern int cancel_suck_cannon_suction(void *) __asm__("FUN_L00_002dbe20"); int cancel_suck_cannon_suction_and_set_moby_state_9(char *moby) __asm__("FUN_L00_002d57d0"); int cancel_suck_cannon_suction_and_set_moby_state_9(char *moby) { + enum { + MOBY_STATE_SUCK_CANNON_ACTIVE = 0x9 + }; int helper_result = cancel_suck_cannon_suction(moby); - MOBY(moby)->state = 0x9; + MOBY(moby)->state = MOBY_STATE_SUCK_CANNON_ACTIVE; return helper_result; } From 7edf2c0e74703d16e33c76b3ebb78611bab448d4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:34:36 +0000 Subject: [PATCH 1376/1502] decomp: clarify names in update_moby_suck_cannon_storage_state domain_0_value_16 -> FROG_STATE_SUCK_CANNON_HELD: Retail 0x002ea6cc loads the moby's state byte at s0+0x20 and 0x002ea6d0 compares it with 16 after the store_moby_in_suck_cannon result is nonzero. Before entering this state, 0x002ea6e0 saves the previous state at +0xBC. The authoritative frog.c frog_update switch names this same MOBY(moby)->state value FROG_STATE_SUCK_CANNON_HELD; adjacent update_moby_grab_state uses that canonical frog-domain member for the identical held-state comparison. domain_1_value_16 -> FROG_STATE_SUCK_CANNON_HELD: Retail 0x002ea6b8 calls the checked store_moby_in_suck_cannon helper; its saved result at 0x002ea6c0 controls the nonzero branch. At 0x002ea6d8, sb v1,0x20(s0) assigns 16 to the same moby's state and 0x002ea6e0 saves its former state at +0xBC. The source frog_update and update_moby_grab_state explicitly establish FROG_STATE_SUCK_CANNON_HELD=16 in this frog state domain. domain_2_value_16 -> FROG_STATE_SUCK_CANNON_HELD: When the store helper returns zero, retail 0x002ea6e4 loads the same moby's state at +0x20 and 0x002ea6ec tests it against 16 before release to 8. This matches adjacent update_moby_grab_state's zero-result comparison against FROG_STATE_SUCK_CANNON_HELD and the frog_update switch's named state-16 branch, which handles suck-cannon-held motion. domain_3_value_8 -> FROG_STATE_WANDER: Retail 0x002ea6f4 loads 8 and 0x002ea700 writes it to moby state +0x20 only after a zero storage result and current state 16; 0x002ea704-0x002ea71c optionally blend animation 0. The same release sequence in source update_moby_grab_state assigns FROG_STATE_WANDER=8. Source frog_update also names its state-8 switch branch FROG_STATE_WANDER and implements random nearby goals and movement there, proving the frog domain rather than the unrelated hero state-8 constant. --- src/overlays/shared/enemies/frog.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/enemies/frog.c b/src/overlays/shared/enemies/frog.c index 14004b10bb..dc7e240b06 100644 --- a/src/overlays/shared/enemies/frog.c +++ b/src/overlays/shared/enemies/frog.c @@ -1006,14 +1006,18 @@ int update_moby_grab_state(struct Moby *moby) { int update_moby_suck_cannon_storage_state(unsigned char *moby) __asm__("FUN_L06_002ea6a8"); int update_moby_suck_cannon_storage_state(unsigned char *moby) { + enum { + FROG_STATE_WANDER = 8, + FROG_STATE_SUCK_CANNON_HELD = 0x10 + }; int suck_cannon_store_result = store_moby_in_suck_cannon(moby); if (suck_cannon_store_result != 0) { - if (MOBY(moby)->state != 0x10) { + if (MOBY(moby)->state != FROG_STATE_SUCK_CANNON_HELD) { MOBY(moby)->command = MOBY(moby)->state; - MOBY(moby)->state = 0x10; + MOBY(moby)->state = FROG_STATE_SUCK_CANNON_HELD; } - } else if (MOBY(moby)->state == 0x10) { - MOBY(moby)->state = 8; + } else if (MOBY(moby)->state == FROG_STATE_SUCK_CANNON_HELD) { + MOBY(moby)->state = FROG_STATE_WANDER; if (MOBY(moby)->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } From f3d6349c065dbb1740ab90331a9239126385c269 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:34:37 +0000 Subject: [PATCH 1377/1502] decomp: clarify names in compute_nanotech_ball_slot_position domain_0_value_2 -> NANOTECH_BALL_STATE_DETACHED_PICKUP: Retail 0x002d8864 retains the first Moby argument in s3; 0x002d88ac loads its state byte at +0x20, and 0x002d88a8/0x002d88b0 compare it with 2 before the slot-offset length helper at 0x002d88c0. The supplied original Ghidra decompilation confirms param_1+0x20 == 2. The authoritative source (src/overlays/shared/pickups/nanotech_ball.c, SHA-256 bf58e76c98499826ddf336cb1c702088f1059e26127ad6e532bf0e1b7e68a699) shows nanotech_ball_update passes that same moby to this function in its eight-slot loop. Its local state enum defines NANOTECH_BALL_STATE_DETACHED_PICKUP = 2; it assigns that member when the owner is dead or self, performs grounding/fall and slot scale updates in that state, and transitions to COLLECTING when the hero can collect it. Thus this comparison belongs to the same nanotech ball Moby state domain and reuses its established member, rather than any equal-valued hero constant. --- src/overlays/shared/pickups/nanotech_ball.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/pickups/nanotech_ball.c b/src/overlays/shared/pickups/nanotech_ball.c index 279bafff79..b4279173c9 100644 --- a/src/overlays/shared/pickups/nanotech_ball.c +++ b/src/overlays/shared/pickups/nanotech_ball.c @@ -1203,13 +1203,16 @@ void compute_nanotech_ball_slot_position(unsigned char *moby, int i) __asm__("FUN_L00_002d8850"); void compute_nanotech_ball_slot_position(unsigned char *moby, float *out_slot_position, int i) { + enum { + NANOTECH_BALL_STATE_DETACHED_PICKUP = 2 + }; u128 slot_offset; M_002d8850 *moby_data = ((M_002d8850 *)MOBY(moby)->pvars); char *e; build_look_at_matrix( &slot_offset, &D_L00_001E3CA0_002d8850[i], &moby_data->p20, moby_data->p20.f[3]); e = moby_data->e[i]; - if (e && MOBY(moby)->state == 2) + if (e && MOBY(moby)->state == NANOTECH_BALL_STATE_DETACHED_PICKUP) FUN_001f9bf8_002d8850(&slot_offset, &slot_offset, *(float *)(e + 0x28)); fast_vec_add(out_slot_position, &moby_data->p10, &slot_offset); out_slot_position[2] += moby_data->f0_002d8850; From 913096a6b7346285bcc0e3f1351847a57be71a37 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:34:37 +0000 Subject: [PATCH 1378/1502] decomp: clarify names in initialize_moby_launch_motion domain_0_value_1 -> MOBY_LAUNCH_STATE_MOVING: In initialize_moby_launch_motion, retail 0031864c loads 1 and 00318660 stores it to the moby's state byte at a0+0x20. The same initialization copies initial_motion_step to pvars+0x30 (00318668-70), local_rotation_offset to +0x10 (00318674-7c), and initializes lifetime and angular increments (00318680-003186dc). The supplied original retail plate explicitly identifies this as moving state 1 and identifies blarg_gun_update at 003186f8 as integrating these fields with gravity/collision response and subsequent fading. This proves the launch-motion moving state rather than a Boolean TRUE or a control/request state. --- src/overlays/shared/mobys/initialize_moby_launch_motion.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/mobys/initialize_moby_launch_motion.c b/src/overlays/shared/mobys/initialize_moby_launch_motion.c index abbdd6a654..1f4fee40a6 100644 --- a/src/overlays/shared/mobys/initialize_moby_launch_motion.c +++ b/src/overlays/shared/mobys/initialize_moby_launch_motion.c @@ -26,8 +26,11 @@ void initialize_moby_launch_motion(char *moby, void *local_rotation_offset, int lifetime_frames) { + enum { + MOBY_LAUNCH_STATE_MOVING = 1 + }; Dat *moby_vars = ((Dat *)MOBY(moby)->pvars); - MOBY(moby)->state = 1; + MOBY(moby)->state = MOBY_LAUNCH_STATE_MOVING; qcopy((char *)moby_vars + 0x30, initial_motion_step); qcopy((char *)moby_vars + 0x10, local_rotation_offset); moby_vars->id = scale_game_frames(lifetime_frames); From 54a86d00675c0ee09595f86abab1125ebcd43f42 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:37:21 +0000 Subject: [PATCH 1379/1502] decomp: clarify names in prepare_sentrybot_alarm domain_1_value_2 -> SENTRYBOT_ALARM_PREPARING: The authoritative source prepare_sentrybot_alarm is called with the moby selected by sentrybot_instance_data->alarm_moby_index in transition and approach states. Retail 0x002cbbb8 loads that alarm moby's state at +0x20; 0x002cbbc4 loads 2 and 0x002cbbd0 stores it to the same state field before 0x002cbbe8 starts animation 1 with the scaled 10-frame blend. Thus 2 is the alarm preparation state entered by this preparation routine; the name makes no claim about the animation's visual content or a Hero/sentrybot shared enum. --- src/overlays/shared/enemies/sentrybot.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/sentrybot.c b/src/overlays/shared/enemies/sentrybot.c index d33ba0584a..0549ab2622 100644 --- a/src/overlays/shared/enemies/sentrybot.c +++ b/src/overlays/shared/enemies/sentrybot.c @@ -1836,9 +1836,12 @@ void set_sentrybot_alarm_duration(char *moby, int duration_frames) { /* Ported from rac1-decomp (src/overlays/shared/vendor_00298BB8.c: func_L15_002CCF30), where it is exact; names translated to the US level program. */ void prepare_sentrybot_alarm(unsigned char *moby) { + enum { + SENTRYBOT_ALARM_PREPARING = 2 + }; char *alarm_moby_data = ((char *)MOBY(moby)->pvars); if (MOBY(moby)->state == 1) { - MOBY(moby)->state = 2; + MOBY(moby)->state = SENTRYBOT_ALARM_PREPARING; if (MOBY(moby)->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } From 69151f06ac4840c076ace0feb61406a0fc4516fe Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:37:21 +0000 Subject: [PATCH 1380/1502] decomp: clarify names in vendor_orb_update domain_0_value_1 -> VENDOR_ORB_ROTATE: Authoritative src/overlays/shared/vendor/vendor_orb.c SHA-256 02a0c55ab9c61a5bb809f306463af40601a14f37351f8aed1fd8de0302347d2c declares VENDOR_ORB_ROTATE=1 for switch(MOBY(moby)->state). Retail 0x002df748 reads that state byte at s0+0x20; 0x002df768 loads 1 and 0x002df770 stores it to the same byte during initialization. Retail 0x002df754-0x002df758 compares that byte to 1 and branches to 0x002df798, whose frame-scaled angular updates at 0x002df7b0-0x002df7e8 implement the existing VENDOR_ORB_ROTATE case. Original Ghidra decompilation independently shows the write to owner+0x20 and subsequent ==1 rotation branch. This reuses the exact selector's existing state constant, rather than unrelated TRUE=1. --- src/overlays/shared/vendor/vendor_orb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/vendor/vendor_orb.c b/src/overlays/shared/vendor/vendor_orb.c index bcc9914fcf..9ea72e904b 100644 --- a/src/overlays/shared/vendor/vendor_orb.c +++ b/src/overlays/shared/vendor/vendor_orb.c @@ -43,7 +43,7 @@ void vendor_orb_update(unsigned char *moby) { float rotation_step_radians; switch (MOBY(moby)->state) { case VENDOR_ORB_INITIALIZE: - MOBY(moby)->state = 1; + MOBY(moby)->state = VENDOR_ORB_ROTATE; MOBY(moby)->unk73 = 0x20; *(float *)(manipulator + 0x40) = random_angle_radians(); attach_manipulator(moby, 1, manipulator); From d2244ad5e3b4fdc445fa5e177f192c0e0a207ce3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:37:22 +0000 Subject: [PATCH 1381/1502] decomp: clarify names in extermibot_update domain_0_value_12 -> EXTERMIBOT_HIDDEN_BELOW_START: Retail 00302084-00302098 saves initial moby+10 position to pvars+270. In initialization, nonzero pvars+2B4 leads through 00302164-00302198: store 12 to moby+20 (same state selector loaded at 0030204c), clear draw distance +32, visible +31 and collision +94, clear flag 1000, and subtract 20 from pos.z. Original Ghidra case 0 and authoritative C agree. Name describes this hidden placement below the saved start only; later activation/lifecycle is not inferred. domain_1_value_2 -> EXTERMIBOT_TARGET_PATH_UNAVAILABLE: 0030221c-00302224 compares pvars+164 with 2 to skip the target-path attempt while unavailable. This is the s32 pvars+0x164 mode, not the moby+0x20 state. Checked walker 00303b48 loads the same moby pvars; 00303b74 calls follow_path with destination a1, and 00303b7c-00303b88 stores 2 at pvars+164 only on zero return. Supplied current move_extermibot_along_path names that same domain member EXTERMIBOT_TARGET_PATH_UNAVAILABLE. domain_2_value_2 -> EXTERMIBOT_TARGET_PATH_UNAVAILABLE: 00302264 calls follow_path from own position to target+10; 0030226c-00302270 writes 2 to pvars+164 on zero return. This is the s32 pvars+0x164 mode, not the moby+0x20 state. Checked walker 00303b48 loads the same moby pvars; 00303b74 calls follow_path with destination a1, and 00303b7c-00303b88 stores 2 at pvars+164 only on zero return. Supplied current move_extermibot_along_path names that same domain member EXTERMIBOT_TARGET_PATH_UNAVAILABLE. domain_3_value_2 -> EXTERMIBOT_TARGET_PATH_UNAVAILABLE: 00302314-00302338 compares pvars+164 with 2, then tests +2B0 before entering APPROACH_TARGET_DIRECTLY instead of path following. This is the s32 pvars+0x164 mode, not the moby+0x20 state. Checked walker 00303b48 loads the same moby pvars; 00303b74 calls follow_path with destination a1, and 00303b7c-00303b88 stores 2 at pvars+164 only on zero return. Supplied current move_extermibot_along_path names that same domain member EXTERMIBOT_TARGET_PATH_UNAVAILABLE. domain_4_value_2 -> EXTERMIBOT_TARGET_PATH_UNAVAILABLE: 0030294c calls the checked walker toward target+10; 003029f4-00302a0c tests pvars+164==2 and enters RETURN_TO_START. This is the s32 pvars+0x164 mode, not the moby+0x20 state. Checked walker 00303b48 loads the same moby pvars; 00303b74 calls follow_path with destination a1, and 00303b7c-00303b88 stores 2 at pvars+164 only on zero return. Supplied current move_extermibot_along_path names that same domain member EXTERMIBOT_TARGET_PATH_UNAVAILABLE. domain_5_value_2 -> EXTERMIBOT_TARGET_PATH_UNAVAILABLE: 00303104-00303120 tests pvars+164 against 2 during RETURN_TO_START; a different mode resumes FOLLOW_TARGET, while 2 retains return/direct-approach fallback. This is the s32 pvars+0x164 mode, not the moby+0x20 state. Checked walker 00303b48 loads the same moby pvars; 00303b74 calls follow_path with destination a1, and 00303b7c-00303b88 stores 2 at pvars+164 only on zero return. Supplied current move_extermibot_along_path names that same domain member EXTERMIBOT_TARGET_PATH_UNAVAILABLE. --- src/overlays/l05/mobys/extermibot.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/overlays/l05/mobys/extermibot.c b/src/overlays/l05/mobys/extermibot.c index cbad38a810..796cea36cb 100644 --- a/src/overlays/l05/mobys/extermibot.c +++ b/src/overlays/l05/mobys/extermibot.c @@ -141,6 +141,10 @@ void extermibot_update(unsigned char *moby) { EXTERMIBOT_DEATH_KNOCKBACK = 14, EXTERMIBOT_WAIT_FOR_ACTIVATION_TRIGGER = 15 }; + enum { + EXTERMIBOT_TARGET_PATH_UNAVAILABLE = 2, + EXTERMIBOT_HIDDEN_BELOW_START = 0xC + }; ExtermibotVars *moby_data = (ExtermibotVars *)MOBY(moby)->pvars; char *target_moby; float path_goal_or_facing_vector[4]; @@ -201,7 +205,7 @@ void extermibot_update(unsigned char *moby) { MOBY(moby)->flags &= 0x7FFF; } if (moby_data->unk2B4 != 0) { - MOBY(moby)->state = 0xC; + MOBY(moby)->state = EXTERMIBOT_HIDDEN_BELOW_START; MOBY(moby)->visible = 0; MOBY(moby)->collision = 0; MOBY(moby)->flags &= 0xEFFF; @@ -220,7 +224,7 @@ void extermibot_update(unsigned char *moby) { build_symmetric_adjacency_masks(&moby_data->path, 1, moby_data->path_pos); break; case EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH: - if (moby_data->mode != 2 && random_integer_below(9) == 0) { + if (moby_data->mode != EXTERMIBOT_TARGET_PATH_UNAVAILABLE && random_integer_below(9) == 0) { if (follow_path(&moby_data->path, 1, moby_data->path_pos, @@ -237,10 +241,10 @@ void extermibot_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } else { - moby_data->mode = 2; + moby_data->mode = EXTERMIBOT_TARGET_PATH_UNAVAILABLE; } } - if (moby_data->mode == 2 && moby_data->unk2B0 != 0) { + if (moby_data->mode == EXTERMIBOT_TARGET_PATH_UNAVAILABLE && moby_data->unk2B0 != 0) { MOBY(moby)->state = EXTERMIBOT_APPROACH_TARGET_DIRECTLY; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); @@ -392,7 +396,7 @@ void extermibot_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(10)); } - if (moby_data->mode == 2) { + if (moby_data->mode == EXTERMIBOT_TARGET_PATH_UNAVAILABLE) { MOBY(moby)->state = EXTERMIBOT_RETURN_TO_START; } break; @@ -550,7 +554,7 @@ void extermibot_update(unsigned char *moby) { MOBY(moby)->state = EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(3)); - } else if (moby_data->mode != 2) { + } else if (moby_data->mode != EXTERMIBOT_TARGET_PATH_UNAVAILABLE) { MOBY(moby)->state = EXTERMIBOT_FOLLOW_TARGET; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(3)); From 6f2543a80627c92cea6462410d3873cec078f3c5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:37:22 +0000 Subject: [PATCH 1382/1502] decomp: clarify names in hoverboard_ring_update domain_0_value_1 -> HOVERBOARD_RING_STATE_ACTIVE: In authoritative hoverboard_ring.c (SHA-256 1ef7df8c2d5951759c0c9cc739199c1de1429445b0837e2dcaee0870720c72e3), the local enum already defines HOVERBOARD_RING_STATE_ACTIVE=1 and switches on moby byte +0x20. Retail 0031abfc reads +0x20; 0031ac04/0031ac08 compare that same byte with 1 and enter the recurring sphere-test/effect branch at 0031ac38. The INIT branch loads a0=1 at 0031ac20 and stores it to the identical +0x20 byte at 0031ac2c, matching the original Ghidra assignment *(undefined1 *)(iVar3 + 0x20)=1. Therefore this assignment selects the existing local ACTIVE state, rather than any unrelated hero mode. --- src/overlays/shared/props/hoverboard_ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/props/hoverboard_ring.c b/src/overlays/shared/props/hoverboard_ring.c index 92b49c27da..07f5e74dc7 100644 --- a/src/overlays/shared/props/hoverboard_ring.c +++ b/src/overlays/shared/props/hoverboard_ring.c @@ -33,7 +33,7 @@ void hoverboard_ring_update(char *moby) { case HOVERBOARD_RING_STATE_INIT: ((unsigned char *)moby)[0x30] = 0x80; MOBY(moby)->flags |= 0x41; - MOBY(moby)->state = 1; + MOBY(moby)->state = HOVERBOARD_RING_STATE_ACTIVE; break; case HOVERBOARD_RING_STATE_ACTIVE: { float bounding_sphere[4]; From df10a35e3da704262a19b13eec4f5c24598c806f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:37:22 +0000 Subject: [PATCH 1383/1502] decomp: clarify names in restore_saved_hero_moby_and_clear_vehicle_mode domain_0_value_2 -> HERO_VEHICLE_MODE_GIANT_CLANK: Retail 0x00208cac/0x00208cc0 constructs hero base 0x0013F350; 0x00208cc8 reads its byte at +0x20A4 and 0x00208cb4/0x00208ccc compares it to 2 before animation teardown. Original Ghidra cRam001413f4 agrees. The authoritative typed source binds this exact byte to Hero.vehicle_mode. In the same source, update_hero_smoothing_parameters switches on hero.vehicle_mode using HERO_VEHICLE_MODE_GIANT_CLANK, and update_hero_timers_and_auxiliary_state uses that same member for enlarged body-center/reach handling. The supplied shared HeroVehicleMode enum canonically assigns this member 2; this is the vehicle selector domain, distinct from current state, control mode and gravity. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00208cf4 reconstructs the same hero base 0x0013F350 and 0x00208d00 stores zero to +0x20A4, exactly the Hero.vehicle_mode assignment in the authoritative source and cRam001413f4 reset in original Ghidra. Subsequent 0x00208d30-0x00208d44 restores the saved hero Moby to active slot +0x2080 and copies hero position into it, proving exit from vehicle mode. The source's update_hero_smoothing_parameters switches on the identical hero.vehicle_mode field with HERO_VEHICLE_MODE_ON_FOOT, and supplied hero_set_state uses that member to restore normal Moby collision behavior. HeroVehicleMode canonically defines ON_FOOT as 0; reuse this established selector-domain member. --- .../shared/hero/update_hero_and_vehicle_mode_effects.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/update_hero_and_vehicle_mode_effects.c b/src/overlays/shared/hero/update_hero_and_vehicle_mode_effects.c index f19a3f8e1f..f143527cae 100644 --- a/src/overlays/shared/hero/update_hero_and_vehicle_mode_effects.c +++ b/src/overlays/shared/hero/update_hero_and_vehicle_mode_effects.c @@ -243,7 +243,7 @@ void restore_saved_hero_moby_and_clear_vehicle_mode(void) { int flag_clear_target; void *moby_to_remove; char *restored_hero_moby; - if (hero_state_for_vehicle_exit->vehicle_mode == 2) { + if (hero_state_for_vehicle_exit->vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { int animation_parameter_value = hero_state_for_vehicle_exit->unk1634; if (animation_parameter_value != -1) { set_animation_parameter(animation_parameter_value, 0); @@ -253,7 +253,7 @@ void restore_saved_hero_moby_and_clear_vehicle_mode(void) { reset_hero_easing_records(); hero_state_bytes = (struct Hero *)(((unsigned char *)&D_0013E533) + 0xE1D); flag_clear_target = *(int *)&hero_state_bytes->unkA84; - hero_state_bytes->vehicle_mode = 0; + hero_state_bytes->vehicle_mode = HERO_VEHICLE_MODE_ON_FOOT; if (flag_clear_target != 0) { *(unsigned short *)(flag_clear_target + 0x34) &= 0xFFF9; } From 46c5b73de4abd0049d814da4b213f020ad16268b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:39:23 +0000 Subject: [PATCH 1384/1502] decomp: clarify names in spawn_timed_projected_sprite_effect domain_0_value_1 -> SPRITE_EFFECT_STATE_ANIMATE: Retail 0x0030bf2c-0x0030bf3c creates and null-checks class 0x76A; 0x0030bf68 loads 1 and 0x0030bf78 stores it at that moby's +0x20 state field, matching MOBY(effect_moby)->state = 1 in the authoritative SHA-256 c63dd0cb3bba746f765a8a133f8bfb6b5ddff4eb260b5f87a01d16558a457fe9 source. The same file's timed_sprite_effect_update switches on moby->state and already names value 1 SPRITE_EFFECT_STATE_ANIMATE: that branch schedules draw_projected_fading_quad, adds pvars[1] to progress pvars[0], and removes the moby above 2.0. The spawner supplies that progress increment as 2.0/float(duration_updates) at pvars+4 (retail 0x0030bf50-0x0030bf74). Thus this is the same effect animation state, not a boolean TRUE or shuttle control state. --- src/overlays/shared/rendering/effects/timed_sprite_effect.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/rendering/effects/timed_sprite_effect.c b/src/overlays/shared/rendering/effects/timed_sprite_effect.c index 1d3e56b517..c9f833d119 100644 --- a/src/overlays/shared/rendering/effects/timed_sprite_effect.c +++ b/src/overlays/shared/rendering/effects/timed_sprite_effect.c @@ -60,6 +60,9 @@ void spawn_timed_projected_sprite_effect(char *world_position, int start_color, int end_color) { + enum { + SPRITE_EFFECT_STATE_ANIMATE = 1 + }; OvlQuad position_copy; char *vp = (char *)&position_copy; unsigned char *effect_moby; @@ -74,7 +77,7 @@ void spawn_timed_projected_sprite_effect(char *world_position, *(int *)(effect_data + 0x8) = start_color; *(float *)(effect_data + 0x4) = 2.0f / duration_as_float; MOBY(effect_moby)->update_dist = 0xFF; - MOBY(effect_moby)->state = 1; + MOBY(effect_moby)->state = SPRITE_EFFECT_STATE_ANIMATE; } } From debe7ea71276f60b30e5bffc47748aa4b1479747 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:39:23 +0000 Subject: [PATCH 1385/1502] decomp: clarify names in spawn_blarg_elite_commando_rocket domain_0_value_0 -> BLARG_ELITE_COMMANDO_ROCKET_STATE_FLYING: Authoritative source src/overlays/shared/enemies/blarg_elite_commando_rocket.c (SHA-256 0715ef28d8ebc336a5959484b542a6acd93c724904d362d38d7d0c268fbe3811) assigns zero to MOBY(moby)->state after create_moby(0x31). Original Ghidra confirms *(undefined1 *)(iVar6 + 0x20) = 0, and retail 0x002a09cc retains the allocated rocket in s1 followed by sb zero,0x20(s1) at 0x002a0a00. In the same authoritative source, blarg_elite_commando_rocket_update returns when this rocket moby state is nonzero; state zero therefore permits rotation, adding rocket_data velocity to position, collision and lifetime checks, position commit and rocket trail spawning. This proves the flying state of the class-0x31 rocket, a separate domain from the listed hero state/gravity/vehicle constants. --- src/overlays/shared/enemies/blarg_elite_commando_rocket.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/blarg_elite_commando_rocket.c b/src/overlays/shared/enemies/blarg_elite_commando_rocket.c index e24cc096a4..7cab247339 100644 --- a/src/overlays/shared/enemies/blarg_elite_commando_rocket.c +++ b/src/overlays/shared/enemies/blarg_elite_commando_rocket.c @@ -173,6 +173,9 @@ char *spawn_blarg_elite_commando_rocket(char *firing_commando_moby, float *initial_movement_vector, char *spawn_position) { + enum { + BLARG_ELITE_COMMANDO_ROCKET_STATE_FLYING = 0 + }; char *moby = create_moby(0x31); if (moby != 0) { char *spawned_rocket_data; @@ -181,7 +184,7 @@ char *spawn_blarg_elite_commando_rocket(char *firing_commando_moby, ((unsigned char *)moby)[0x30] = 0xFF; MOBY(moby)->draw_dist = 0xFF; MOBY(moby)->visible = 1; - MOBY(moby)->state = 0; + MOBY(moby)->state = BLARG_ELITE_COMMANDO_ROCKET_STATE_FLYING; MOBY(moby)->spawn_frame = *(unsigned long *)(firing_commando_moby + 0x38); MOBY(moby)->scale = MOBY(moby)->scale * 3.0f; qcopy(&MOBY(moby)->pos, spawn_position); From 02b0b5b17d2482f9099c298507a86d1040819701 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:39:23 +0000 Subject: [PATCH 1386/1502] decomp: clarify names in spawn_bolt_thief_mine domain_0_value_0 -> FLOAT_MINE_INITIALIZE: Retail 0x002ffb14 loads class 0x3A5 for create_moby; its return is saved in s1 at 0x002ffb24. Instruction 0x002ffbc4 (sb zero,0x20(s1)) assigns that created mine's state, corroborated by original Ghidra *(undefined1 *)(iVar6 + 0x20) = 0. The authoritative source's bolt_thief_mine_update switches on the same Moby state and already names 0 FLOAT_MINE_INITIALIZE: it initializes rest_z, handles the spawner link and transitions to FLOAT_MINE_ACTIVE. Thus this assignment enters that same floating-mine initialization domain, rather than any equal-valued Hero constant. --- src/overlays/shared/enemies/bolt_thief_mine.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/bolt_thief_mine.c b/src/overlays/shared/enemies/bolt_thief_mine.c index 5ccec5dffc..7ae6bf1e18 100644 --- a/src/overlays/shared/enemies/bolt_thief_mine.c +++ b/src/overlays/shared/enemies/bolt_thief_mine.c @@ -206,6 +206,9 @@ unsigned char *spawn_bolt_thief_mine(unsigned char *owner, char *spawn_position) __asm__("FUN_L14_002ffaf8"); unsigned char *spawn_bolt_thief_mine(unsigned char *spawning_moby, char *spawn_position) { + enum { + FLOAT_MINE_INITIALIZE = 0 + }; unsigned char *spawned_moby = create_moby(0x3A5); if (spawned_moby != 0) { char *spawned_vars = ((char *)MOBY(spawned_moby)->pvars); @@ -218,7 +221,7 @@ unsigned char *spawn_bolt_thief_mine(unsigned char *spawning_moby, char *spawn_p *(float *)(spawned_vars + 0x18) = random_float_between(0.00349065848f, 0.00698131695f); qcopy(&MOBY(spawned_moby)->pos, spawn_position); MOBY(spawned_moby)->rot.z = MOBY(spawning_moby)->rot.z; - MOBY(spawned_moby)->state = 0; + MOBY(spawned_moby)->state = FLOAT_MINE_INITIALIZE; MOBY(spawned_moby)->update_dist = 0xFF; MOBY(spawned_moby)->draw_dist = 0xFF; MOBY(spawned_moby)->visible = 1; From aa396e1a1e0eaf0c25736d44c9929c135b61136b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:39:23 +0000 Subject: [PATCH 1387/1502] decomp: clarify names in update_menu_preview_animation_pose domain_0_value_0 -> MENU_PREVIEW_ANIMATION_COUNTDOWN_EXPIRED: In the bound source SHA-256 7269b17d67367eed892b08286001d58cad30e549ddad78e8d286065de784fdb7, --anim->state is compared with zero only for class 0x25F and seq 6. Retail 0x0022500c loads byte +0x20, 0x00225010 decrements it, 0x00225014 masks to a byte, and 0x00225018 branches on nonzero while 0x0022501c stores the decrement. At zero, 0x00225020-0x0022503c requests selector 1 with duration 10 unless already selected; the nonzero branch retains selector 6. Original Ghidra likewise shows bLifecycle_state decremented and zero selecting that duration-ten transition. Thus zero denotes expiry of this animation countdown; it is not the unrelated MENU_ACTION_DISABLED domain. --- .../menus/item_preview/update_menu_preview_animation_pose.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/menus/item_preview/update_menu_preview_animation_pose.c b/src/ui/menus/item_preview/update_menu_preview_animation_pose.c index aeb29097d8..cebcd6c554 100644 --- a/src/ui/menus/item_preview/update_menu_preview_animation_pose.c +++ b/src/ui/menus/item_preview/update_menu_preview_animation_pose.c @@ -14,6 +14,9 @@ extern void blend_moby_animation(void *, int, int, int) __asm__("func_00212F90") void update_menu_preview_animation_pose(void *preview) __asm__("FUN_00224fc0"); void update_menu_preview_animation_pose(void *preview) { + enum { + MENU_PREVIEW_ANIMATION_COUNTDOWN_EXPIRED = 0 + }; PauseMoby *moby = preview; struct Moby *anim = (struct Moby *)moby; f32 transform[16]; @@ -22,7 +25,7 @@ void update_menu_preview_animation_pose(void *preview) { if (anim->anim_flags & 2) { if (moby->oclass == 0x25F) { if (anim->seq == 6) { - if (--anim->state == 0) { + if (--anim->state == MENU_PREVIEW_ANIMATION_COUNTDOWN_EXPIRED) { if (anim->prev_seq != 1) { blend_moby_animation(moby, 1, 0, 10); } From 864a1270e0342be04cb4d69c859e7db73c974f4d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:39:23 +0000 Subject: [PATCH 1388/1502] decomp: clarify names in release_glove_of_doom_held_moby domain_0_value_2 -> GLOVE_HELD_MOBY_RELEASED: SHA-256-bound glove_of_doom.c caller glove_of_doom_update passes glove_carrier_vars->held to release_glove_of_doom_held_moby during GLOVE_RELEASE_HELD_MOBY and clears held immediately afterward. Retail 0x002c82fc saves that second argument in s4; 0x002c8318-0x002c8320 installs its initial velocity through +0x78, 0x002c8354-0x002c835c installs its release position at +0x10, and 0x002c8414/0x002c841c unconditionally stores 2 into its state byte at +0x20 after optional collision adjustment. Original retail decompilation independently shows *(undefined1 *)(param_2 + 0x20) = 2. This proves the held object's released state, distinct from the carrier and Hero domains. --- src/overlays/shared/weapons/glove_of_doom.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/glove_of_doom.c b/src/overlays/shared/weapons/glove_of_doom.c index 6c25a27f45..526c2e4ff1 100644 --- a/src/overlays/shared/weapons/glove_of_doom.c +++ b/src/overlays/shared/weapons/glove_of_doom.c @@ -455,6 +455,9 @@ void release_glove_of_doom_held_moby(Vec4_2c82f0 *release_position, u8 *released_moby, void *initial_velocity) { + enum { + GLOVE_HELD_MOBY_RELEASED = 2 + }; char *q = *(char **)(released_moby + 0x78); struct Hero *P; char *released_moby_position, *collision_reference_moby; @@ -485,5 +488,5 @@ void release_glove_of_doom_held_moby(Vec4_2c82f0 *release_position, reflect_vector(q, q, collision_hit_cursor); FUN_001f9a68_002c82f0(q, q, 0.6f); } - MOBY(released_moby)->state = 2; + MOBY(released_moby)->state = GLOVE_HELD_MOBY_RELEASED; } From 6f417aafc9351ada595c2e3ee7d454d41f49f2e8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:39:23 +0000 Subject: [PATCH 1389/1502] decomp: clarify names in spawn_armed_transport_rocket domain_0_value_0 -> ARMED_TRANSPORT_ROCKET_STATE_FLYING: Retail 0x002a0df4-0x002a0e04 allocates class 0x32 into s1, and 0x002a0e34 (sb zero,0x20(s1)) assigns its Moby.state, matching original Ghidra *(undefined1 *)(iVar6 + 0x20) = 0 and authoritative spawn source. The same authoritative file's armed_transport_rocket_update declares ARMED_TRANSPORT_ROCKET_STATE_FLYING = 0 and gates trail emission, target steering, position integration and collision impact/removal on rocket_moby->state equaling that member. Its pvars offsets +0x10 target, +0x24 movement length, +0x28/+0x2c angle offsets and +0x20/+0x30 blend ticks match the spawn initialization, establishing the same rocket state domain rather than any hero zero-valued enum. --- src/overlays/shared/enemies/armed_transport_rocket.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/armed_transport_rocket.c b/src/overlays/shared/enemies/armed_transport_rocket.c index 82c84cbec0..2ae64126b2 100644 --- a/src/overlays/shared/enemies/armed_transport_rocket.c +++ b/src/overlays/shared/enemies/armed_transport_rocket.c @@ -137,6 +137,9 @@ char *spawn_armed_transport_rocket(char *spawning_moby, int blend_duration_ticks, float unused) { + enum { + ARMED_TRANSPORT_ROCKET_STATE_FLYING = 0 + }; char *spawned_moby = (char *)create_moby(0x32); char *moby_data; float initial_movement_length, x, random_angle_radians, y; @@ -144,7 +147,7 @@ char *spawn_armed_transport_rocket(char *spawning_moby, MOBY(spawned_moby)->update_dist = 0xFF; MOBY(spawned_moby)->draw_dist = 0xFF; MOBY(spawned_moby)->visible = 1; - MOBY(spawned_moby)->state = 0; + MOBY(spawned_moby)->state = ARMED_TRANSPORT_ROCKET_STATE_FLYING; MOBY(spawned_moby)->spawn_frame = *(unsigned long *)(spawning_moby + 0x38); MOBY(spawned_moby)->scale = MOBY(spawned_moby)->scale * 3.0f; qcopy(&MOBY(spawned_moby)->pos, spawn_position); From b0df48e12c884e6516d2b4a7103cd786dc1f6cea Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:39:24 +0000 Subject: [PATCH 1390/1502] decomp: clarify names in child_carrier_update domain_0_value_1 -> UPDATE_TRANSFORM_FROM_HISTORY: The authoritative source switches on MOBY(moby)->state and assigns 1 to that exact selector in INITIALIZE_TRANSFORM_HISTORY; the same local enum already defines UPDATE_TRANSFORM_FROM_HISTORY = 1. Retail 0x002fa74c loads moby+0x20, 0x002fa758-0x002fa75c compares it with 1 and branches to 0x002fa788, while 0x002fa76c-0x002fa774 stores 1 into that same byte. The state-1 branch at 0x002fa788-0x002fa7b4 subtracts saved position (pvars+0x60) from current position and calls update_entity_matrix using saved rotation (pvars+0x70); 0x002fa82c-0x002fa838 refreshes that history. The original retail decompilation agrees. This proves reuse of the existing state member rather than TRUE or a different numeric domain. --- src/overlays/l18/mobys/child_carrier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l18/mobys/child_carrier.c b/src/overlays/l18/mobys/child_carrier.c index 576c28ffbf..9e20eb8bfe 100644 --- a/src/overlays/l18/mobys/child_carrier.c +++ b/src/overlays/l18/mobys/child_carrier.c @@ -36,7 +36,7 @@ void child_carrier_update(char *moby) { char *child; switch (MOBY(moby)->state) { case INITIALIZE_TRANSFORM_HISTORY: - MOBY(moby)->state = 1; + MOBY(moby)->state = UPDATE_TRANSFORM_FROM_HISTORY; break; case UPDATE_TRANSFORM_FROM_HISTORY: fast_vec_sub(position_delta, moby + 0x10, transform_and_child_vars->unk60); From 3de789a2105b36437ffb2d1f9e45eda06b578a90 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:41:24 +0000 Subject: [PATCH 1391/1502] overlay: name add_hero_up_offset --- .../l01/hero/update_hero_motion_for_current_state.c | 4 ++-- src/overlays/l02/hero/update_hero_state_motion.c | 4 ++-- .../l03/hero/update_hero_motion_for_current_state.c | 4 ++-- .../l05/hero/apply_hero_ground_material_effects.c | 4 ++-- src/overlays/l05/hero/update_hero_motion_by_state.c | 4 ++-- .../l06/hero/update_hero_motion_for_current_state.c | 4 ++-- .../l08/hero/update_hero_motion_for_current_state.c | 4 ++-- src/overlays/l11/hero/update_hero_motion_by_state.c | 4 ++-- .../l12/hero/update_hero_motion_for_current_state.c | 4 ++-- src/overlays/l14/hero/update_hero_motion_by_state.c | 4 ++-- .../l15/hero/update_hero_motion_for_current_state.c | 4 ++-- .../l16/hero/apply_hero_ground_material_effects.c | 4 ++-- .../l16/hero/update_hero_motion_for_current_state.c | 6 +++--- .../l17/hero/update_hero_motion_for_current_state.c | 4 ++-- .../l18/hero/update_hero_motion_for_current_state.c | 4 ++-- src/overlays/shared/hero/hero_frame_update.c | 4 ++-- src/overlays/shared/hero/hero_move_state_velocity.c | 6 +++--- src/overlays/shared/hero/hero_switch_item.c | 8 ++++---- src/overlays/shared/hero/hero_update_movement.c | 4 ++-- src/overlays/shared/hero/set_hero_animation.c | 4 ++-- .../hero/update_hero_vehicle_attachments_and_effects.c | 4 ++-- 21 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/overlays/l01/hero/update_hero_motion_for_current_state.c b/src/overlays/l01/hero/update_hero_motion_for_current_state.c index 4e2cda5cbf..04ec1872e8 100644 --- a/src/overlays/l01/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l01/hero/update_hero_motion_for_current_state.c @@ -394,7 +394,7 @@ extern int scale_game_frames(int); #include "rnc/overlay/shared/world/level_labels.h" extern s32 D_L01_0015F68C __attribute__((sda)); -extern void FUN_001efa68_cf(float *, float *, float) __asm__("FUN_L00_00233810"); +extern void add_hero_up_offset(float *, float *, float) __asm__("FUN_L00_00233810"); extern void rotate_hero_about_fixed_local_pivot(float, float, float) __asm__("FUN_L00_002091d8"); extern void emit_hero_periodic_surface_effect(int, int) __asm__("FUN_L00_00209540"); extern void emit_hero_periodic_surface_particles(int, int) __asm__("FUN_L00_00209848"); @@ -2070,7 +2070,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.state_timer < scale_game_frames(0xA) && hero.stick_magnitude > 0.2f) { qcopy(vector_and_hit_scratch[0], hero.motion.pos.f); - FUN_001efa68_cf(vector_and_hit_scratch[0], vector_and_hit_scratch[0], 0.5f); + add_hero_up_offset(vector_and_hit_scratch[0], vector_and_hit_scratch[0], 0.5f); qcopy(vector_and_hit_scratch[1], vector_and_hit_scratch[0]); vector_and_hit_scratch[1][0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; vector_and_hit_scratch[1][1] += fast_sin(hero.motion.rot.f[2]) * 0.85f; diff --git a/src/overlays/l02/hero/update_hero_state_motion.c b/src/overlays/l02/hero/update_hero_state_motion.c index 43ff4b4739..ffe3e3f67a 100644 --- a/src/overlays/l02/hero/update_hero_state_motion.c +++ b/src/overlays/l02/hero/update_hero_state_motion.c @@ -571,7 +571,7 @@ typedef union { } V_222270; extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); -extern void FUN_L00_00233810(f32 *, f32 *, f32); +extern void add_hero_up_offset(f32 *, f32 *, f32) __asm__("FUN_L00_00233810"); extern void FUN_L00_002334d0(f32 *, f32 *, f32); extern s32 coll1_222270(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); extern s32 rig_probe(void *, s32, f32, s32, f32) __asm__("FUN_L00_001f19a0"); @@ -599,7 +599,7 @@ s32 resolve_hero_position_collisions(s32 mode) { if (hero.state.control_mode != 0x11) { if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN || hero.unk1F8 != 0) { if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0) { - FUN_L00_00233810(&collision_probe_offset, &collision_probe_offset, 0.6f); + add_hero_up_offset(&collision_probe_offset, &collision_probe_offset, 0.6f); } else { FUN_L00_002334d0( &collision_probe_offset, &collision_probe_offset, -hero.capsule_bottom); diff --git a/src/overlays/l03/hero/update_hero_motion_for_current_state.c b/src/overlays/l03/hero/update_hero_motion_for_current_state.c index f4e177c594..63026109fe 100644 --- a/src/overlays/l03/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l03/hero/update_hero_motion_for_current_state.c @@ -276,7 +276,7 @@ struct PlayerSpeedTuning { extern struct PlayerSpeedTuning D_L03_0017BEB8; extern s32 allocate_hero_voice_for_entry(s32, s32) __asm__("FUN_L00_00216de8"); extern void add_hero_forward_offset(void *, void *, f32) __asm__("FUN_L00_00233708"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern s32 collision_line(void *, void *, s32, struct MobyView *, s32) __asm__("FUN_001efa68"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); extern s32 is_moby_in_class_range_500_to_540(s32) __asm__("FUN_L00_0025e3b8"); @@ -2214,7 +2214,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&spatial_scratch_or_hit_descriptor, &hero.motion.pos); - FUN_L00_00233810( + add_hero_up_offset( &spatial_scratch_or_hit_descriptor, &spatial_scratch_or_hit_descriptor, 0.5f); qcopy(&v10, &spatial_scratch_or_hit_descriptor); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; diff --git a/src/overlays/l05/hero/apply_hero_ground_material_effects.c b/src/overlays/l05/hero/apply_hero_ground_material_effects.c index cd85b6bd2a..4cd5fc9607 100644 --- a/src/overlays/l05/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l05/hero/apply_hero_ground_material_effects.c @@ -383,7 +383,7 @@ typedef union { extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern void FUN_L00_002334d0(void *, void *, f32); extern s32 coll_sphere(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); extern s32 rig_probe(void *, s32, f32, s32, f32) __asm__("FUN_L00_001f19a0"); @@ -415,7 +415,7 @@ s32 resolve_hero_position_collisions(s32 mode) { } else if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN || hero.unk1F8 != 0) { if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0 || (unsigned)(hero.state.control_mode - 0x15) < 2) { - FUN_L00_00233810(&collision_query_offset, &collision_query_offset, 0.6f); + add_hero_up_offset(&collision_query_offset, &collision_query_offset, 0.6f); } else { FUN_L00_002334d0( &collision_query_offset, &collision_query_offset, -hero.capsule_bottom); diff --git a/src/overlays/l05/hero/update_hero_motion_by_state.c b/src/overlays/l05/hero/update_hero_motion_by_state.c index 340f6f9f7b..dd22ba40d4 100644 --- a/src/overlays/l05/hero/update_hero_motion_by_state.c +++ b/src/overlays/l05/hero/update_hero_motion_by_state.c @@ -229,7 +229,7 @@ struct PlayerSpeedTuning { extern struct PlayerSpeedTuning D_L05_0017C218; extern s32 allocate_hero_voice_for_entry(s32, s32) __asm__("FUN_L00_00216de8"); extern void add_hero_forward_offset(void *, void *, f32) __asm__("FUN_L00_00233708"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern s32 collision_line(void *, void *, s32, struct MobyView *, s32) __asm__("FUN_001efa68"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); extern s32 is_moby_in_class_range_500_to_540(s32) __asm__("FUN_L00_0025e3b8"); @@ -2812,7 +2812,7 @@ void update_hero_motion_by_state(void) { } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&vector_and_hit_scratch, &hero.motion.pos); - FUN_L00_00233810(&vector_and_hit_scratch, &vector_and_hit_scratch, 0.5f); + add_hero_up_offset(&vector_and_hit_scratch, &vector_and_hit_scratch, 0.5f); qcopy(&v10, &vector_and_hit_scratch); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; v10.f[1] += fast_sin(hero.motion.rot.f[2]) * 0.85f; diff --git a/src/overlays/l06/hero/update_hero_motion_for_current_state.c b/src/overlays/l06/hero/update_hero_motion_for_current_state.c index c118de126d..fa4f9845bb 100644 --- a/src/overlays/l06/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l06/hero/update_hero_motion_for_current_state.c @@ -975,7 +975,7 @@ struct PlayerSpeedTuning { extern struct PlayerSpeedTuning D_L06_0017C538_c __asm__("D_L06_0017C538"); extern s32 allocate_hero_voice_for_entry(s32, s32) __asm__("FUN_L00_00216de8"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern s32 FUN_001efa68_c(void *, void *, s32, struct MobyView *, s32) __asm__("FUN_001efa68"); extern void update_hero_motion_response_parameters(void) __asm__("FUN_L00_00215b68"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); @@ -2752,7 +2752,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&vector_or_hit_descriptor_scratch, &hero.motion.pos); - FUN_L00_00233810( + add_hero_up_offset( &vector_or_hit_descriptor_scratch, &vector_or_hit_descriptor_scratch, 0.5f); qcopy(&v10, &vector_or_hit_descriptor_scratch); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; diff --git a/src/overlays/l08/hero/update_hero_motion_for_current_state.c b/src/overlays/l08/hero/update_hero_motion_for_current_state.c index ee43223601..9fe2c85ab7 100644 --- a/src/overlays/l08/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l08/hero/update_hero_motion_for_current_state.c @@ -343,7 +343,7 @@ struct PlayerSpeedTuning { extern struct PlayerSpeedTuning D_L08_0017C5B8; extern s32 allocate_hero_voice_for_entry(s32, s32) __asm__("FUN_L00_00216de8"); extern void add_hero_forward_offset(void *, void *, f32) __asm__("FUN_L00_00233708"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern s32 collision_line(void *, void *, s32, struct MobyView *, s32) __asm__("FUN_001efa68"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); extern s32 is_moby_in_class_range_500_to_540(s32) __asm__("FUN_L00_0025e3b8"); @@ -2648,7 +2648,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&vector_and_attack_descriptor_scratch, &hero.motion.pos); - FUN_L00_00233810(&vector_and_attack_descriptor_scratch, + add_hero_up_offset(&vector_and_attack_descriptor_scratch, &vector_and_attack_descriptor_scratch, 0.5f); qcopy(&v10, &vector_and_attack_descriptor_scratch); diff --git a/src/overlays/l11/hero/update_hero_motion_by_state.c b/src/overlays/l11/hero/update_hero_motion_by_state.c index 49d015c6c8..d8947d2b5b 100644 --- a/src/overlays/l11/hero/update_hero_motion_by_state.c +++ b/src/overlays/l11/hero/update_hero_motion_by_state.c @@ -328,7 +328,7 @@ struct PlayerSpeedTuning { extern struct PlayerSpeedTuning D_L11_0017C7B8; extern s32 allocate_hero_voice_for_entry(s32, s32) __asm__("FUN_L00_00216de8"); extern void add_hero_forward_offset(void *, void *, f32) __asm__("FUN_L00_00233708"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern s32 collision_line(void *, void *, s32, struct MobyView *, s32) __asm__("FUN_001efa68"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); extern s32 is_moby_in_class_range_500_to_540(s32) __asm__("FUN_L00_0025e3b8"); @@ -2120,7 +2120,7 @@ void update_hero_motion_by_state(void) { } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&vector_and_hit_descriptor_head_scratch, &hero.motion.pos); - FUN_L00_00233810(&vector_and_hit_descriptor_head_scratch, + add_hero_up_offset(&vector_and_hit_descriptor_head_scratch, &vector_and_hit_descriptor_head_scratch, 0.5f); qcopy(&v10, &vector_and_hit_descriptor_head_scratch); diff --git a/src/overlays/l12/hero/update_hero_motion_for_current_state.c b/src/overlays/l12/hero/update_hero_motion_for_current_state.c index 600d2a7a26..2999025d66 100644 --- a/src/overlays/l12/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l12/hero/update_hero_motion_for_current_state.c @@ -615,7 +615,7 @@ struct PlayerSpeedTuning { extern struct PlayerSpeedTuning D_L12_0017C238; extern s32 allocate_hero_voice_for_entry(s32, s32) __asm__("FUN_L00_00216de8"); extern void add_hero_forward_offset(void *, void *, f32) __asm__("FUN_L00_00233708"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern s32 collision_line(void *, void *, s32, struct MobyView *, s32) __asm__("FUN_001efa68"); extern s32 D_0013CB14[]; extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); @@ -2582,7 +2582,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&geometry_and_hit_descriptor_scratch, &hero.motion.pos); - FUN_L00_00233810(&geometry_and_hit_descriptor_scratch, + add_hero_up_offset(&geometry_and_hit_descriptor_scratch, &geometry_and_hit_descriptor_scratch, 0.5f); qcopy(&v10, &geometry_and_hit_descriptor_scratch); diff --git a/src/overlays/l14/hero/update_hero_motion_by_state.c b/src/overlays/l14/hero/update_hero_motion_by_state.c index 9becdf6e03..55a9ba9c09 100644 --- a/src/overlays/l14/hero/update_hero_motion_by_state.c +++ b/src/overlays/l14/hero/update_hero_motion_by_state.c @@ -484,7 +484,7 @@ struct PlayerSpeedTuning { extern struct PlayerSpeedTuning D_L14_0017C4B8; extern s32 allocate_hero_voice_for_entry(s32, s32) __asm__("FUN_L00_00216de8"); extern void add_hero_forward_offset(void *, void *, f32) __asm__("FUN_L00_00233708"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern s32 collision_line(void *, void *, s32, struct MobyView *, s32) __asm__("FUN_001efa68"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); extern s32 is_moby_in_class_range_500_to_540(s32) __asm__("FUN_L00_0025e3b8"); @@ -2366,7 +2366,7 @@ void update_hero_motion_by_state(void) { } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&vector_and_descriptor_scratch, &hero.motion.pos); - FUN_L00_00233810( + add_hero_up_offset( &vector_and_descriptor_scratch, &vector_and_descriptor_scratch, 0.5f); qcopy(&v10, &vector_and_descriptor_scratch); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; diff --git a/src/overlays/l15/hero/update_hero_motion_for_current_state.c b/src/overlays/l15/hero/update_hero_motion_for_current_state.c index 7a73639d1b..99c57084d1 100644 --- a/src/overlays/l15/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l15/hero/update_hero_motion_for_current_state.c @@ -539,7 +539,7 @@ struct PlayerSpeedTuning { extern struct PlayerSpeedTuning D_L15_0017C3B8; extern void add_hero_forward_offset(void *, void *, f32) __asm__("FUN_L00_00233708"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern s32 collision_line(void *, void *, s32, struct MobyView *, s32) __asm__("FUN_001efa68"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); extern s32 is_moby_in_class_range_500_to_540(s32) __asm__("FUN_L00_0025e3b8"); @@ -2370,7 +2370,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&spatial_or_hit_descriptor_work, &hero.motion.pos); - FUN_L00_00233810( + add_hero_up_offset( &spatial_or_hit_descriptor_work, &spatial_or_hit_descriptor_work, 0.5f); qcopy(&v10, &spatial_or_hit_descriptor_work); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; diff --git a/src/overlays/l16/hero/apply_hero_ground_material_effects.c b/src/overlays/l16/hero/apply_hero_ground_material_effects.c index a0b279e176..10ebf16442 100644 --- a/src/overlays/l16/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l16/hero/apply_hero_ground_material_effects.c @@ -400,7 +400,7 @@ typedef union { extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern void FUN_L00_002334d0(void *, void *, f32); extern s32 coll1_2133a8(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); extern s32 rig_probe(void *, s32, f32, s32, f32) __asm__("FUN_L00_001f19a0"); @@ -433,7 +433,7 @@ s32 resolve_hero_position_collisions(s32 mode) { } else if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN || hero.unk1F8 != 0) { if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0 || (unsigned)(hero.state.control_mode - 0x15) < 2) { - FUN_L00_00233810(&collision_position_offset, &collision_position_offset, 0.6f); + add_hero_up_offset(&collision_position_offset, &collision_position_offset, 0.6f); } else { FUN_L00_002334d0( &collision_position_offset, &collision_position_offset, -hero.capsule_bottom); diff --git a/src/overlays/l16/hero/update_hero_motion_for_current_state.c b/src/overlays/l16/hero/update_hero_motion_for_current_state.c index 0b768f8d5b..e3bc627d74 100644 --- a/src/overlays/l16/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l16/hero/update_hero_motion_for_current_state.c @@ -233,7 +233,7 @@ struct PlayerSpeedTuning { extern struct PlayerSpeedTuning D_L16_0017C218; extern s32 allocate_hero_voice_for_entry(s32, s32) __asm__("FUN_L00_00216de8"); extern void add_hero_forward_offset(void *, void *, f32) __asm__("FUN_L00_00233708"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern s32 collision_line(void *, void *, s32, struct MobyView *, s32) __asm__("FUN_001efa68"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); extern s32 is_moby_in_class_range_500_to_540(s32) __asm__("FUN_L00_0025e3b8"); @@ -970,7 +970,7 @@ void update_hero_motion_for_current_state(void) { hero.board_vertical_speed += t; } gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_00233810( + add_hero_up_offset( &hero.motion.velocity, &hero.motion.velocity, hero.board_vertical_speed); hero.air_frames.s = 1; } @@ -2948,7 +2948,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&primary_vector_scratch, &hero.motion.pos); - FUN_L00_00233810(&primary_vector_scratch, &primary_vector_scratch, 0.5f); + add_hero_up_offset(&primary_vector_scratch, &primary_vector_scratch, 0.5f); qcopy(&v10, &primary_vector_scratch); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; v10.f[1] += fast_sin(hero.motion.rot.f[2]) * 0.85f; diff --git a/src/overlays/l17/hero/update_hero_motion_for_current_state.c b/src/overlays/l17/hero/update_hero_motion_for_current_state.c index 33812a25b0..ab3a24e530 100644 --- a/src/overlays/l17/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l17/hero/update_hero_motion_for_current_state.c @@ -218,7 +218,7 @@ struct PlayerSpeedTuning { extern struct PlayerSpeedTuning D_L17_0017C6B8; extern s32 allocate_hero_voice_for_entry(s32, s32) __asm__("FUN_L00_00216de8"); extern void add_hero_forward_offset(void *, void *, f32) __asm__("FUN_L00_00233708"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern s32 collision_line(void *, void *, s32, struct MobyView *, s32) __asm__("FUN_001efa68"); extern void update_hero_motion_response_parameters(void) __asm__("FUN_L00_00215b68"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); @@ -2691,7 +2691,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&scratch_vector, &hero.motion.pos); - FUN_L00_00233810(&scratch_vector, &scratch_vector, 0.5f); + add_hero_up_offset(&scratch_vector, &scratch_vector, 0.5f); qcopy(&v10, &scratch_vector); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; v10.f[1] += fast_sin(hero.motion.rot.f[2]) * 0.85f; diff --git a/src/overlays/l18/hero/update_hero_motion_for_current_state.c b/src/overlays/l18/hero/update_hero_motion_for_current_state.c index cbb82489c9..5f7ee34e8b 100644 --- a/src/overlays/l18/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l18/hero/update_hero_motion_for_current_state.c @@ -217,7 +217,7 @@ struct PlayerSpeedTuning { extern struct PlayerSpeedTuning D_L18_0017C7B8; extern s32 allocate_hero_voice_for_entry(s32, s32) __asm__("FUN_L00_00216de8"); extern void add_hero_forward_offset(void *, void *, f32) __asm__("FUN_L00_00233708"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern s32 collision_line(void *, void *, s32, struct MobyView *, s32) __asm__("FUN_001efa68"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); extern s32 is_moby_in_class_range_500_to_540(s32) __asm__("FUN_L00_0025e3b8"); @@ -2560,7 +2560,7 @@ void update_hero_motion_for_current_state(void) { } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&general_vector_or_hit_descriptor_scratch, &hero.motion.pos); - FUN_L00_00233810(&general_vector_or_hit_descriptor_scratch, + add_hero_up_offset(&general_vector_or_hit_descriptor_scratch, &general_vector_or_hit_descriptor_scratch, 0.5f); qcopy(&v10, &general_vector_or_hit_descriptor_scratch); diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index b4e811a17e..6de3a5222e 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -1341,7 +1341,7 @@ typedef union { } V_233940; extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern void FUN_L00_002334d0(void *, void *, f32); extern s32 coll_sphere(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); extern s32 coll3_233940(void *, f32) __asm__("FUN_L00_001f3170"); @@ -1368,7 +1368,7 @@ s32 resolve_hero_position_with_collision_queries(s32 mode) { if (hero.state.control_mode != 0x11) { if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN || hero.unk1F8 != 0) { if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0) { - FUN_L00_00233810(&collision_query_offset, &collision_query_offset, 0.6f); + add_hero_up_offset(&collision_query_offset, &collision_query_offset, 0.6f); } else { FUN_L00_002334d0( &collision_query_offset, &collision_query_offset, -hero.capsule_bottom); diff --git a/src/overlays/shared/hero/hero_move_state_velocity.c b/src/overlays/shared/hero/hero_move_state_velocity.c index abd7659f79..d4d09c1ae7 100644 --- a/src/overlays/shared/hero/hero_move_state_velocity.c +++ b/src/overlays/shared/hero/hero_move_state_velocity.c @@ -1063,7 +1063,7 @@ extern unsigned char coll_hit[] __asm__("D_L00_00173E40") __attribute__((section void FUN_001f9a68_217118(void *, float, void *) __asm__("FUN_001f9a68"); void add_hero_forward_offset(void *, void *, float) __asm__("FUN_L00_00233708"); void FUN_001f9a10_217118(void *, void *, void *) __asm__("FUN_001f9a10"); -void FUN_L00_00233810_217118(void *, void *, float) __asm__("FUN_L00_00233810"); +void add_hero_up_offset(void *, void *, float) __asm__("FUN_L00_00233810"); int FUN_L00_001efc70_217118(void *, void *, int, void *, int) __asm__("FUN_L00_001efc70"); float compute_gravity_relative_vector_inclination(void *) __asm__("FUN_L00_00233d30"); void scale_hero_motion(float) __asm__("FUN_L00_00213de8"); @@ -1102,14 +1102,14 @@ void stop_hero_motion_without_forward_support(float velocity_scale, float planar gravity_set_z(collision_query_position, collision_query_position, 0.0f); FUN_001f9a10_217118(collision_query_position, collision_query_position, (&hero.motion.pos)); qcopy(collision_query_second_position, collision_query_position); - FUN_L00_00233810_217118(collision_query_position, collision_query_position, 0.3f); + add_hero_up_offset(collision_query_position, collision_query_position, 0.3f); P = ((char *)&hero); k = -0.2f; if (*(int *)(P + 0x2084) == 0x20) k = -0.35f; if (P[0x20A4] == 2) k = -0.7f; - FUN_L00_00233810_217118(collision_query_second_position, collision_query_second_position, k); + add_hero_up_offset(collision_query_second_position, collision_query_second_position, k); final_call_enabled = 1.0f; if (FUN_L00_001efc70_217118(collision_query_position, collision_query_second_position, diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 7a5354c342..1a77ed5e26 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -3652,7 +3652,7 @@ typedef union { } V_2133a8; extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern void FUN_L00_002334d0(void *, void *, f32); extern s32 coll_sphere(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); extern s32 rig_probe(void *, s32, f32, s32, f32) __asm__("FUN_L00_001f19a0"); @@ -3682,7 +3682,7 @@ s32 resolve_hero_current_position_collisions(s32 mode) { if (hero.state.control_mode != 0x11) { if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN || hero.unk1F8 != 0) { if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0) { - FUN_L00_00233810(&collision_probe_offset, &collision_probe_offset, 0.6f); + add_hero_up_offset(&collision_probe_offset, &collision_probe_offset, 0.6f); } else { FUN_L00_002334d0( &collision_probe_offset, &collision_probe_offset, -hero.capsule_bottom); @@ -4248,7 +4248,7 @@ void hero_integrate_velocity(void) { } } if (!(hero.state_timer < hero.takeoff_frame) && 0.0f < hero.unk428) { - FUN_L00_00233810(&hero.motion.velocity, &hero.motion.velocity, hero.unk428); + add_hero_up_offset(&hero.motion.velocity, &hero.motion.velocity, hero.unk428); hero.unk42C += hero.unk428; hero.unk428 = 0.0f; } @@ -4273,7 +4273,7 @@ void hero_integrate_velocity(void) { velocity_curve->value += velocity_curve->keys[velocity_curve->key].delta * frame_time_sq; } - FUN_L00_00233810(&hero_velocity, &hero_velocity, velocity_curve->value); + add_hero_up_offset(&hero_velocity, &hero_velocity, velocity_curve->value); } } } diff --git a/src/overlays/shared/hero/hero_update_movement.c b/src/overlays/shared/hero/hero_update_movement.c index a2e76270c2..00754231c5 100644 --- a/src/overlays/shared/hero/hero_update_movement.c +++ b/src/overlays/shared/hero/hero_update_movement.c @@ -182,7 +182,7 @@ struct PlayerSpeedTuning { extern struct PlayerSpeedTuning D_L00_0017BDB8; extern s32 allocate_hero_voice_for_entry(s32, s32) __asm__("FUN_L00_00216de8"); extern void add_hero_forward_offset(void *, void *, f32) __asm__("FUN_L00_00233708"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern s32 collision_line(void *, void *, s32, struct MobyView *, s32) __asm__("FUN_001efa68"); extern void update_hero_motion_response_parameters(void) __asm__("FUN_L00_00215b68"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); @@ -2766,7 +2766,7 @@ void hero_update_movement(void) { } if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&movement_and_hit_descriptor_scratch, &hero.motion.pos); - FUN_L00_00233810(&movement_and_hit_descriptor_scratch, + add_hero_up_offset(&movement_and_hit_descriptor_scratch, &movement_and_hit_descriptor_scratch, 0.5f); qcopy(&v10, &movement_and_hit_descriptor_scratch); diff --git a/src/overlays/shared/hero/set_hero_animation.c b/src/overlays/shared/hero/set_hero_animation.c index 0b7511e0ce..dbabca6ec6 100644 --- a/src/overlays/shared/hero/set_hero_animation.c +++ b/src/overlays/shared/hero/set_hero_animation.c @@ -1079,9 +1079,9 @@ typedef struct { f32 v[4]; } V00233810 __attribute__((aligned(16))); -void FUN_L00_00233810(f32 *out, f32 *in, f32 z); +void add_hero_up_offset(f32 *out, f32 *in, f32 z) __asm__("FUN_L00_00233810"); -void FUN_L00_00233810(f32 *gravity_offset_adjusted_vector, f32 *in, f32 z) { +void add_hero_up_offset(f32 *gravity_offset_adjusted_vector, f32 *in, f32 z) { struct Hero *hero_base = &hero; M00233810 moby_rotation_matrix; V00233810 offset_vector; diff --git a/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c b/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c index c2f63a7542..7781049c93 100644 --- a/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c +++ b/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c @@ -553,7 +553,7 @@ typedef union { extern OvlVec4 coll_hit_pos __asm__("D_L06_001745F0") NOT_SDA; /* position after push-out of the last collision query */ extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); -extern void FUN_L00_00233810(void *, void *, f32); +extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); extern void FUN_L00_002334d0(void *, void *, f32); extern s32 coll_sphere(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); extern s32 rig_probe(void *, s32, f32, s32, f32) __asm__("FUN_L00_001f19a0"); @@ -580,7 +580,7 @@ s32 resolve_hero_position_collisions(s32 mode) { if (hero.state.control_mode != 0x11) { if (hero.gravity_mode != HERO_GRAVITY_WORLD_DOWN || hero.unk1F8 != 0) { if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0) { - FUN_L00_00233810(&collision_query_offset, &collision_query_offset, 0.6f); + add_hero_up_offset(&collision_query_offset, &collision_query_offset, 0.6f); } else { FUN_L00_002334d0( &collision_query_offset, &collision_query_offset, -hero.capsule_bottom); From 4569fbcd10da4a6b6c89af742b5ee0dc020136a3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:41:24 +0000 Subject: [PATCH 1392/1502] decomp: clarify names in help_draw_prompt domain_0_value_1 -> HELP_STATE_FRAME_EXPAND: The authoritative source compares help_state.state, mapped to DAT_001996d0 by retail loads at 0x001fe8e4 and branches 0x001fe8ec/0x001fe8f4. Checked direct caller FUN_001fe980 reads that same state at 0x001fe990 and dispatches state 1 to 0x001fe9f4. At 0x001fea00..0x001fea24 it loads timer from state+4, computes (timer << 2)+8, stores both frame half extents at state+0x18/+0x1c, and passes center +/- those extents to draw_ui_frame at 0x001fea28. This is the help frame expansion phase, distinct from the prompt and text phases in the same dispatch. domain_1_value_7 -> HELP_STATE_FRAME_COLLAPSE: The comparison at retail 0x001fe8f4 uses the same DAT_001996d0/help_state.state selector as checked caller FUN_001fe980. Its state 7 branch at 0x001fec28 loads saved frame half extents at state+0x1c/+0x18 and timer at state+4 (0x001fec38..0x001fec48). Instructions through 0x001fec90 compute each extent minus ((extent-8)*timer)/8, contracting toward half extent 8 as timer advances; 0x001fec5c/0x001fec68 compute opacity (8-timer)*12. Center +/- contracted extents and that opacity go to draw_ui_frame at 0x001feca4, proving a help frame collapse rendering phase. --- src/ui/help/help_draw_prompt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ui/help/help_draw_prompt.c b/src/ui/help/help_draw_prompt.c index 9ea29958c2..da3922a64e 100644 --- a/src/ui/help/help_draw_prompt.c +++ b/src/ui/help/help_draw_prompt.c @@ -8,6 +8,10 @@ extern s32 draw_ui_frame() __asm__("func_001F5F18"); void help_draw_prompt(void) __asm__("FUN_001fe898"); void help_draw_prompt(void) { + enum { + HELP_STATE_FRAME_EXPAND = 1, + HELP_STATE_FRAME_COLLAPSE = 7 + }; s32 alpha; help_state.frame_half_width = 0x20; @@ -17,7 +21,7 @@ void help_draw_prompt(void) { help_state.center_x - 0x20, help_state.center_x + 0x20, 0x60); - if (help_state.state == 1 || help_state.state == 7) { + if (help_state.state == HELP_STATE_FRAME_EXPAND || help_state.state == HELP_STATE_FRAME_COLLAPSE) { alpha = help_state.timer * 21; } else { alpha = 0x7E; From eb26941b4086dfc3791182afb6adc4df38b9d36e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:41:24 +0000 Subject: [PATCH 1393/1502] decomp: clarify names in spawn_mine domain_0_value_0 -> MINE_STATE_OWNER_ATTACHED: Retail 0x002a9eec/0x002a9ef8 creates class 0x4A and keeps the moby in s1; 0x002a9f3c stores zero to its state byte at s1+0x20, exactly the assignment in spawn_mine. 0x002a9f40 stores the owner reference at pvars+0x30. The authoritative mine.c already calls this same mine state MINE_STATE_OWNER_ATTACHED=0 in mine_update and predict_mine_impact: the zero-state update builds the owner's bone transform and copies it to the mine, then returns before free motion. The mine_glove_update caller stores spawn_mine's result in held and copies its grip position to that held mine. This is the mine moby state domain, not any hero, vehicle or prediction-mode domain. --- src/overlays/shared/weapons/mine.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/mine.c b/src/overlays/shared/weapons/mine.c index 747b7c2a86..35746fcf59 100644 --- a/src/overlays/shared/weapons/mine.c +++ b/src/overlays/shared/weapons/mine.c @@ -403,6 +403,9 @@ s32 FUN_L00_002603d0_2aa008(void *) __asm__("FUN_L00_002603d0"); unsigned char *spawn_mine(int owner, OvlQuad *pos) __asm__("FUN_L00_002a9ed0"); unsigned char *spawn_mine(int mine_owner_moby, OvlQuad *spawn_position) { + enum { + MINE_STATE_OWNER_ATTACHED = 0 + }; unsigned char *mine_moby = create_moby(0x4A); if (mine_moby) { MineVars *mine_vars = (MineVars *)MOBY(mine_moby)->pvars; @@ -410,7 +413,7 @@ unsigned char *spawn_mine(int mine_owner_moby, OvlQuad *spawn_position) { MOBY(mine_moby)->draw_dist = 0x7F; MOBY(mine_moby)->visible = 1; MOBY(mine_moby)->scale = MOBY(mine_moby)->scale * 0.5f; - MOBY(mine_moby)->state = 0; + MOBY(mine_moby)->state = MINE_STATE_OWNER_ATTACHED; mine_vars->unk30 = mine_owner_moby; mine_vars->unk36 = 0; mine_vars->unk78 = 0; From 0fa2cf69d4e76b13b9d78280904d2711715d0f3e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:41:24 +0000 Subject: [PATCH 1394/1502] decomp: clarify names in spawn_bomb domain_0_value_0 -> BOMB_STATE_HELD: Retail 0x002ace98 allocates class 0x79, preserves its moby in s1, and 0x002acf24 writes zero to that moby's state byte +0x20; original Ghidra has the identical store. The supplied bomb_glove_update caller assigns spawn_bomb(moby, &bomb_glove_vars->grip) to held, maintains its position at grip, then calls launch_bomb when releasing it. In the authoritative source, launch_bomb changes the same bomb state byte to 1. predict_throw_landing already names state zero BOMB_STATE_HELD and uses it for a not-yet-launched trajectory from the hero's holding offset. Thus this selector is the bomb moby state domain and zero is its held state, independently of equal-valued HeroStateId/vehicle/gravity constants. --- src/overlays/shared/weapons/bomb_glove_bomb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/bomb_glove_bomb.c b/src/overlays/shared/weapons/bomb_glove_bomb.c index 135ce06f0a..50a47f93b8 100644 --- a/src/overlays/shared/weapons/bomb_glove_bomb.c +++ b/src/overlays/shared/weapons/bomb_glove_bomb.c @@ -805,6 +805,9 @@ void draw_bomb_landing_marker(M_2acbf0_002acbf0 *moby) { unsigned char *spawn_bomb(int owner, void *pos) __asm__("FUN_L00_002ace70"); unsigned char *spawn_bomb(int bomb_holder_moby, void *spawn_position) { + enum { + BOMB_STATE_HELD = 0 + }; unsigned char *bomb_moby = create_moby(0x79); if (bomb_moby) { V_2ace70 u, random_rotation; @@ -819,7 +822,7 @@ unsigned char *spawn_bomb(int bomb_holder_moby, void *spawn_position) { MOBY(bomb_moby)->update_dist = 0xFF; MOBY(bomb_moby)->draw_dist = 0xFF; MOBY(bomb_moby)->visible = 1; - MOBY(bomb_moby)->state = 0; + MOBY(bomb_moby)->state = BOMB_STATE_HELD; *(int *)(v + 0x50) = bomb_holder_moby; *(short *)(v + 0x56) = 0; *(short *)(v + 0x6A) = 0; From cfc7456627342b51cea6d8f73d2720c843b70e33 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:43:39 +0000 Subject: [PATCH 1395/1502] decomp: clarify names in spawn_paratrooper_projectile domain_0_value_1 -> FIRE_BOLT_STATE_FLYING: Retail 0x003071cc..0x003071d8 creates class 0x50C and retains the returned moby in s1; 0x003071e0 loads 1 and 0x003071f8 stores it to that moby's state byte +0x20. Original Ghidra agrees: *(undefined1 *)(iVar6 + 0x20) = 1. Authoritative source binds this store to MOBY(spawned_moby)->state and identifies the same class's adjacent fire_bolt_update selector as ((unsigned char *)fire_bolt)[0x20]. That update already declares FIRE_BOLT_STATE_FLYING = 1; its branch copies the previous position, adds private velocity to position, tests collisions and lifetime, and transitions to burst/removal state 2. Thus this is initialization of the existing flying-state domain, rather than boolean TRUE or burst_mode. --- src/overlays/shared/enemies/paratrooper_fire_bolt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/paratrooper_fire_bolt.c b/src/overlays/shared/enemies/paratrooper_fire_bolt.c index 12f8c44e8a..4c5657e106 100644 --- a/src/overlays/shared/enemies/paratrooper_fire_bolt.c +++ b/src/overlays/shared/enemies/paratrooper_fire_bolt.c @@ -29,6 +29,9 @@ char *spawn_paratrooper_projectile(char *initial_velocity, int lifetime_frames, int burst_mode) { + enum { + FIRE_BOLT_STATE_FLYING = 1 + }; char *spawned_moby = create_moby(0x50C); if (spawned_moby != 0) { char *moby_data; @@ -36,7 +39,7 @@ char *spawn_paratrooper_projectile(char *initial_velocity, MOBY(spawned_moby)->draw_dist = 0x7E; moby_data = ((char *)MOBY(spawned_moby)->pvars); MOBY(spawned_moby)->visible = 1; - MOBY(spawned_moby)->state = 1; + MOBY(spawned_moby)->state = FIRE_BOLT_STATE_FLYING; qcopy(&MOBY(spawned_moby)->pos, spawn_position); qcopy(moby_data, initial_velocity); *(int *)(moby_data + 0x18) = scale_game_frames(lifetime_frames); From 84d8a7c8146fca983bddb24daaaae489fb6ab933 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:43:39 +0000 Subject: [PATCH 1396/1502] decomp: clarify names in moby_wobble_update domain_0_value_1 -> MOBY_WOBBLE_STATE_ANIMATE: Retail 0x0030c0c4 reads the moby state byte at +0x20; 0x0030c0d0-0x0030c0d4 dispatch value 1 to 0x0030c18c. Initialization ends at 0x0030c180-0x0030c188 by storing 1 to that same +0x20 byte. The target branch queues draw_moby_wobble_quads, advances both angular phases and applies sine-driven rotations through 0x0030c1fc. Authoritative source already names this same selector's case 1 MOBY_WOBBLE_STATE_ANIMATE, proving canonical member reuse for the assignment rather than numeric coincidence. --- src/overlays/shared/props/lamp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/props/lamp.c b/src/overlays/shared/props/lamp.c index d1d34ec741..87a9a0fc67 100644 --- a/src/overlays/shared/props/lamp.c +++ b/src/overlays/shared/props/lamp.c @@ -81,7 +81,7 @@ void moby_wobble_update(unsigned char *moby) { wobble_vars->unk4C = randf_sym(lo, hi); set_moby_color(moby, 0x80, 0x80, 0x80); attach_manipulator((char *)moby, 0, wobble_vars); - MOBY(moby)->state = 1; + MOBY(moby)->state = MOBY_WOBBLE_STATE_ANIMATE; break; case MOBY_WOBBLE_STATE_ANIMATE: { float k = 0.5235988f; From 7cd4805251dc2257de525325e60c4bdebf877e38 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:43:39 +0000 Subject: [PATCH 1397/1502] decomp: clarify names in start_snagglebeast_turn_toward_target domain_0_value_7 -> SNAGGLEBEAST_TURN_TOWARD_TARGET: Retail 0x00313e60/0x00313e68 saves the Snagglebeast moby's current state byte at moby+0x20 into vars+0x1F4; 0x00313e6c-0x00313e78 saves resume animation, fixed-target flag and target vector. Retail 0x00313f2c loads 7 and 0x00313f38 stores it to the same moby+0x20 state byte, after choosing turning animation 3 or 14. The authoritative source's snagglebeast_update switches on MOBY(moby)->state and already names member 7 SNAGGLEBEAST_TURN_TOWARD_TARGET. That case consumes these saved fields, rotates toward turn_target, and restores turn_saved_state and turn_resume_animation after alignment, proving the exact same Snagglebeast state domain and established member. --- src/overlays/l07/mobys/snagglebeast.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l07/mobys/snagglebeast.c b/src/overlays/l07/mobys/snagglebeast.c index 0e3c3f55cb..3c348392c7 100644 --- a/src/overlays/l07/mobys/snagglebeast.c +++ b/src/overlays/l07/mobys/snagglebeast.c @@ -766,6 +766,9 @@ int start_snagglebeast_turn_toward_target(unsigned char *moby, int resume_animation, int use_fixed_target_position) { + enum { + SNAGGLEBEAST_TURN_TOWARD_TARGET = 7 + }; float target_heading = fast_arc_tan(target_position[0] - MOBY(moby)->pos.x, target_position[1] - MOBY(moby)->pos.y); if (moby_vars->turn_start_angle < @@ -788,7 +791,7 @@ int start_snagglebeast_turn_toward_target(unsigned char *moby, blend_moby_animation(moby, 0xE, r, random_int_between(0xF, 0x14)); } } - MOBY(moby)->state = 7; + MOBY(moby)->state = SNAGGLEBEAST_TURN_TOWARD_TARGET; return 1; } return 0; From a0ed699f04387610a3480eca831ccdd6ca54f10e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:43:39 +0000 Subject: [PATCH 1398/1502] decomp: clarify names in apply_resort_owner_movement domain_0_value_4 -> RESORT_OWNER_FOLLOW_HERO: Retail 0x002d134c preserves the resort-owner argument in s2, and 0x002d13a4 loads its current state byte at +0x20. The subtraction by 4 and unsigned <3 test at 0x002d13a8-0x002d13b0 implement the source state range 4..6. The same moby passes from resort_owner_update through state actions, movement and transitions. The source ResortOwnerState enum names 4 RESORT_OWNER_FOLLOW_HERO; its transition branch follows hero.motion.pos and enters 4 after the hero exceeds 6 units. Reuse this exact current-state member for the lower bound. domain_1_value_6 -> RESORT_OWNER_MOVE_TO_PATH_POINT: Retail 0x002d13a4 reads current Moby.state from the resort-owner argument +0x20; 0x002d13a8 subtracts 4 and 0x002d13ac tests unsigned <3, proving the inclusive upper bound 6 on the same selector. The source ResortOwnerState enum names 6 RESORT_OWNER_MOVE_TO_PATH_POINT. Its state-transition case requests l11_cuboids[points[leg]].pos as the destination and tests arrival before advancing gate/path progression. This is the resort owner's current-state domain, so the existing member is the proven upper bound. domain_2_value_7 -> RESORT_OWNER_JUMP_TO_TARGET: Retail 0x002d13a4 loads the resort-owner current state at moby+0x20, then 0x002d13b8-0x002d13bc compare that byte to 7; only afterward do 0x002d13c4-0x002d13cc separately test pvars+0x15C against 3. The source ResortOwnerState enum names current state 7 RESORT_OWNER_JUMP_TO_TARGET. Its state-action branch computes target-minus-position movement at the jump animation window and applies vertical acceleration; the transition branch enters next_state when animation ends. Reuse the existing resort-owner jump member, not HERO_STATE_JUMP or a request-state constant. --- src/overlays/l11/mobys/resort_owner.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l11/mobys/resort_owner.c b/src/overlays/l11/mobys/resort_owner.c index 7a1693084a..da12b1bef6 100644 --- a/src/overlays/l11/mobys/resort_owner.c +++ b/src/overlays/l11/mobys/resort_owner.c @@ -267,8 +267,8 @@ void apply_resort_owner_movement(void *mp) { qcopy(A, moby + 0x10); qcopy(B, moby_vars->unk130); FUN_L00_00258830((int)moby, (int)B, 0.5f, 0.3f, 0.0f, 0x10); - if ((MOBY(moby)->state >= 4 && MOBY(moby)->state <= 6) || - (MOBY(moby)->state == 7 && moby_vars->unk15C == 3)) { + if ((MOBY(moby)->state >= RESORT_OWNER_FOLLOW_HERO && MOBY(moby)->state <= RESORT_OWNER_MOVE_TO_PATH_POINT) || + (MOBY(moby)->state == RESORT_OWNER_JUMP_TO_TARGET && moby_vars->unk15C == 3)) { resolve_point_path_segment_xy_clearance( 0.3f, *(void **)((u8 *)moby_vars + 0x60 - -(*(int *)&moby_vars->unk158 * 4)), From 4b780bdd9b1672106aeba69641eabab1d67a1185 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:43:39 +0000 Subject: [PATCH 1399/1502] decomp: clarify names in handle_gadgebot_hit_knockback domain_0_value_9 -> GADGEBOT_UPDATE_KNOCKBACK: Retail 0x002f3654 retains the incoming Gadgebot pointer in s2; 0x002f3668 loads its current-state byte at +0x20 and 0x002f366c skips hit handling when equal to s5=9 (loaded at 0x002f364c). The same pointer is supplied by gadgebot_update, whose existing GADGEBOT_UPDATE_KNOCKBACK=9 case steps vars+0x80 via step_moby_motion. This guard prevents restarting that knockback state; it is the Gadgebot state domain, not HeroStateId. domain_1_value_9 -> GADGEBOT_UPDATE_KNOCKBACK: Retail 0x002f3670 loads this Gadgebot's pvars; 0x002f36dc forms vars+0x80, initialized at 0x002f3724 and passed with the same Gadgebot pointer to trooper_start_knockback at 0x002f375c. After initialization, 0x002f379c stores s5=9 to that moby's current-state byte +0x20. The caller gadgebot_update already defines GADGEBOT_UPDATE_KNOCKBACK=9 and handles that state by stepping the identical vars+0x80 motion block, proving reuse of this established constant. --- src/overlays/shared/enemies/gadgebot.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/gadgebot.c b/src/overlays/shared/enemies/gadgebot.c index 80a0c38c59..a23ac8c1bb 100644 --- a/src/overlays/shared/enemies/gadgebot.c +++ b/src/overlays/shared/enemies/gadgebot.c @@ -1623,8 +1623,11 @@ int process_gadgebot_interactions(char *moby, int flag) { void handle_gadgebot_hit_knockback(unsigned char *moby) __asm__("FUN_L06_002f3640"); void handle_gadgebot_hit_knockback(unsigned char *moby) { + enum { + GADGEBOT_UPDATE_KNOCKBACK = 9 + }; char *state = ((char *)MOBY(moby)->pvars); - if (MOBY(moby)->state != 9 && MOBY(moby)->seq != 2 && MOBY(moby)->prev_seq != 2) { + if (MOBY(moby)->state != GADGEBOT_UPDATE_KNOCKBACK && MOBY(moby)->seq != 2 && MOBY(moby)->prev_seq != 2) { char *target = find_moby_hit(moby, 0x330001, 0); if (target != 0) { Q hit_vector_copy; @@ -1651,7 +1654,7 @@ void handle_gadgebot_hit_knockback(unsigned char *moby) { *(float *)(state + 0xCC) = doubled_frame_time; } FUN_0022da68(2, 0, moby); - MOBY(moby)->state = 9; + MOBY(moby)->state = GADGEBOT_UPDATE_KNOCKBACK; } } } From 0d321dae740e368fe59302eb2f5ed63b7bf1abad Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:45:24 +0000 Subject: [PATCH 1400/1502] decomp: clarify names in updraft_vent_update domain_0_value_1 -> MOBY_UPDATE_ACTIVE: Retail 0x002e9048 loads the moby's state byte +0x20 into s2; 0x002e9050-0x002e9054 dispatch value 1 to the active branch at 0x002e9080. Initialization loads 1 at 0x002e9068 and stores it to that same +0x20 state byte at 0x002e906c. The authoritative source names that selector's case 1 MOBY_UPDATE_ACTIVE in its existing local enum; its branch performs hero proximity/local-box processing and queues the draw callback at 0x002e9184-0x002e9190. Thus this assignment enters that exact existing update phase, rather than a hero-state, gravity or vehicle domain. --- src/overlays/shared/props/updraft_vent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/props/updraft_vent.c b/src/overlays/shared/props/updraft_vent.c index c75a05f08d..7df8b1ee44 100644 --- a/src/overlays/shared/props/updraft_vent.c +++ b/src/overlays/shared/props/updraft_vent.c @@ -32,7 +32,7 @@ void updraft_vent_update(unsigned char *moby) { unsigned int update_state = MOBY(moby)->state; switch (update_state) { case MOBY_UPDATE_INITIALIZE: - MOBY(moby)->state = 1; + MOBY(moby)->state = MOBY_UPDATE_ACTIVE; MOBY(moby)->flags |= 1; MOBY(moby)->visible = 0; break; From 3f72cc45d196ed758224c3cc5a358f3f8352b26d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:45:25 +0000 Subject: [PATCH 1401/1502] decomp: clarify names in spawn_level_13_homing_rocket domain_0_value_0 -> HOMING_ROCKET_STATE_INITIAL: Retail 0x002c13f4/0x002c13fc allocates class 0x52, 0x002c1404 retains that newly created moby in s0, and the successful-allocation branch reaches 0x002c142c: sb zero,0x20(s0). Original Ghidra likewise writes zero to iVar7+0x20. The SHA-bound authoritative C identifies this exact byte as MOBY(moby)->state within spawn_level_13_homing_rocket, alongside visibility and distance initialization before update_entity at 0x002c14c4. Thus zero is the initial state explicitly selected for the spawned homing rocket. The name asserts only that proven initial-state role, without claiming an unproved flight subphase or equating zero with FALSE/NULL. --- src/overlays/l13/mobys/homing_rocket.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l13/mobys/homing_rocket.c b/src/overlays/l13/mobys/homing_rocket.c index dd32ddf0e9..6dcd83e3de 100644 --- a/src/overlays/l13/mobys/homing_rocket.c +++ b/src/overlays/l13/mobys/homing_rocket.c @@ -43,13 +43,16 @@ unsigned char *spawn_level_13_homing_rocket(char *owner_moby, float scale, float max_speed) { + enum { + HOMING_ROCKET_STATE_INITIAL = 0 + }; unsigned char *moby = (unsigned char *)create_moby(0x52); if (moby != 0) { Level13HomingRocketVars *homing_rocket_vars = (Level13HomingRocketVars *)MOBY(moby)->pvars; MOBY(moby)->update_dist = 0xFF; MOBY(moby)->draw_dist = 0xFF; MOBY(moby)->visible = 1; - MOBY(moby)->state = 0; + MOBY(moby)->state = HOMING_ROCKET_STATE_INITIAL; homing_rocket_vars->unk24 = target; homing_rocket_vars->unk20 = owner_moby; qcopy(moby + 0x10, rocket_spawn_position); From 7337d38268b41fb86e3b7e44c2d5f2c972486a04 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:45:25 +0000 Subject: [PATCH 1402/1502] decomp: clarify names in update_all_point_lights domain_0_value_0 -> POINT_LIGHT_LINK_INACTIVE: The authoritative slot->link_state != 0 test corresponds to retail 0x00201b08-0x00201b10: lw from -0x10(s1) followed by beql zero skips distance testing, sphere copying and both create/refresh calls. s1 is the cached sphere in the 0x30-byte point-light slot, proving zero is the inactive link-update state rather than a generic FALSE token. domain_1_value_1 -> POINT_LIGHT_LINK_PENDING_CREATION: Retail 0x00201a60 loads s5=1; 0x00201b38-0x00201b48 compares the same slot state to s5 and calls create_point_light (0x00201ba8) with s3, the light index. After this call 0x00201b50 writes 2 to that state. The helper at 0x00201bc0-0x00201c08 indexes the matching slot/definition and 0x00201c7c-0x00201ce8 builds render-record light-index links, proving state 1 awaits link creation. domain_2_value_2 -> POINT_LIGHT_LINK_CREATED: Retail 0x00201a68 loads s4=2; after create_point_light at 0x00201b44 returns, the branch delay store at 0x00201b50 writes s4 into the same -0x10(s1) link_state field. Helper evidence 0x00201c7c-0x00201ce8 shows creation populating render-record light links. This is the post-creation state that subsequently takes the refresh branch. domain_3_value_2 -> POINT_LIGHT_LINK_CREATED: Retail 0x00201b54 compares the slot state with s4=2 and 0x00201b5c calls refresh_point_light with the same s3 light index. This field is exactly the one assigned 2 after create_point_light at 0x00201b50; supplied refresh_point_light source detaches then recreates links, proving the comparison reuses the post-creation member of the same link-state domain. --- src/rendering/lights/update_all_point_lights.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/rendering/lights/update_all_point_lights.c b/src/rendering/lights/update_all_point_lights.c index 2c060f54cc..231413c14a 100644 --- a/src/rendering/lights/update_all_point_lights.c +++ b/src/rendering/lights/update_all_point_lights.c @@ -27,6 +27,11 @@ extern void refresh_point_light(int) __asm__("FUN_00201f58"); void update_all_point_lights(void) __asm__("FUN_00201a28"); void update_all_point_lights(void) { + enum { + POINT_LIGHT_LINK_INACTIVE = 0, + POINT_LIGHT_LINK_PENDING_CREATION = 1, + POINT_LIGHT_LINK_CREATED = 2 + }; struct DirectionalLight *lights = (struct DirectionalLight *)dir_lights; float lighting_direction_angle; int light_index; @@ -44,12 +49,12 @@ void update_all_point_lights(void) { struct PointLight *light = &point_lights[light_index]; struct PointLightSlot *slot = &((struct PointLightSlot *)point_light_data)[light_index]; - if (slot->link_state != 0 && fast_vec_dist(light->sphere, slot->linked_sphere) > 8.0f) { + if (slot->link_state != POINT_LIGHT_LINK_INACTIVE && fast_vec_dist(light->sphere, slot->linked_sphere) > 8.0f) { qcopy(slot->linked_sphere, light->sphere); - if (slot->link_state == 1) { + if (slot->link_state == POINT_LIGHT_LINK_PENDING_CREATION) { create_point_light(light_index); - slot->link_state = 2; - } else if (slot->link_state == 2) { + slot->link_state = POINT_LIGHT_LINK_CREATED; + } else if (slot->link_state == POINT_LIGHT_LINK_CREATED) { refresh_point_light(light_index); } } From 7054d78be83283f8fd77ef3fe076111aebc0326b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:45:25 +0000 Subject: [PATCH 1403/1502] decomp: clarify names in breakaway_piece_update domain_0_value_1 -> UPDATE_BOBBING_HEIGHT: The authoritative C reads MOBY(moby)->state into the switch selector and declares UPDATE_BOBBING_HEIGHT = 1. Retail 0x00300e0c loads that same byte at moby+0x20; 0x00300e20 sets a0=1 and 0x00300e24 branches on equality to the bobbing branch at 0x00300e74. Initialization saves moby Z to pvars+0xC at 0x00300e5c-0x00300e68, then 0x00300e70 stores a0=1 back to the same moby+0x20 field. The destination branch restores saved Z or computes baseline plus amplitude times sine at 0x00300e88-0x00300ee4. This proves reuse of the existing local state member, rather than TRUE or another numeric domain. --- src/overlays/l06/mobys/breakaway_piece.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l06/mobys/breakaway_piece.c b/src/overlays/l06/mobys/breakaway_piece.c index 9be0ca6550..b8f8932434 100644 --- a/src/overlays/l06/mobys/breakaway_piece.c +++ b/src/overlays/l06/mobys/breakaway_piece.c @@ -37,7 +37,7 @@ void breakaway_piece_update(char *moby) { MOBY(moby)->draw_dist = 0x200; ((unsigned char *)moby)[0x30] = 0xFF; bobbing_and_motion_vars->unkC = MOBY(moby)->pos.z; - MOBY(moby)->state = 1; + MOBY(moby)->state = UPDATE_BOBBING_HEIGHT; break; case UPDATE_BOBBING_HEIGHT: if (*(int *)(D_0013E533 + 0x2EA1) == 0x72) { From 25b11c7276a424eee02322ef5f0579924218daef Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:45:25 +0000 Subject: [PATCH 1404/1502] decomp: clarify names in count_group_gadgebots_not_in_state_8 domain_0_value_8 -> GADGEBOT_IDLE: Retail 0x002fc81c-0x002fc828 resolves a group entry to a 0x100-byte moby record and checks class 0x772; 0x002fc834-0x002fc83c reads that record's state at +0x20 and skips counting when it equals 8. The authoritative gadgebot.c launcher resolves the same D_L18_001AC240/D_L18_0015FFD8 group records, tests class 0x772 and moby->state == GADGEBOT_IDLE (8), then activates the moby as GADGEBOT_LAUNCH_FLIGHT. gadgebot_update initializes and returns exploded mobys to GADGEBOT_IDLE, and hide_moby_and_clear_collision assigns this same idle state while hiding the moby and clearing collision. This proves the comparison uses the existing gadgebot idle state, not the equal-valued hero land state. --- src/overlays/l18/mobys/gadgebot.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l18/mobys/gadgebot.c b/src/overlays/l18/mobys/gadgebot.c index b5a6110ec9..9e6da5a1e8 100644 --- a/src/overlays/l18/mobys/gadgebot.c +++ b/src/overlays/l18/mobys/gadgebot.c @@ -525,6 +525,9 @@ int launch_first_idle_group_class_0772_moby(int group, void *from, void *to, flo short count_group_gadgebots_not_in_state_8(int group_index) __asm__("FUN_L18_002fc7e0"); short count_group_gadgebots_not_in_state_8(int group_index) { + enum { + GADGEBOT_IDLE = 8 + }; unsigned short *group_moby_entry = (unsigned short *)D_L18_001AC240[group_index]; short n = 0; int moby_table_address; @@ -534,7 +537,7 @@ short count_group_gadgebots_not_in_state_8(int group_index) { while (1) { unsigned char *moby = (unsigned char *)(moby_table_address + ((group_moby_entry[0] & 0x7FFF) << 8)); - if (MOBY(moby)->oclass == 0x772 && MOBY(moby)->state != 8) + if (MOBY(moby)->oclass == 0x772 && MOBY(moby)->state != GADGEBOT_IDLE) n++; if ((short)*group_moby_entry++ < 0) return n; From 0487cd308478182d6b5101e47e9d5994712b9797 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:47:51 +0000 Subject: [PATCH 1405/1502] decomp: clarify names in camera_activation_check_priority domain_0_value_0 -> CAMERA_TRANSITION_PRIORITY_GATED: Retail 0x001ec228 saves current in s0. At 0x001ec2b8-0x001ec2c0, its signed halfword +0x7e is tested: nonzero immediately accepts; zero reaches 0x001ec2c4-0x001ec2d0, requiring unsigned candidate priority +0x7c to exceed current priority. Thus zero identifies the current-camera transition state in which priority gates replacement, distinct from candidate activation rule +0x74. domain_1_value_0 -> CAMERA_TRANSITION_PRIORITY_GATED: Retail clip-volume branch 0x001ec2f0-0x001ec308 loads the same current s0 +0x7e transition halfword. Nonzero skips the priority gate to the volume test; zero executes unsigned candidate/current priority comparison and rejects unless the candidate is greater. This is the same priority-gated transition value as at 0x001ec2b8, not a clip-volume activation rule. domain_2_value_0 -> CAMERA_TRANSITION_PRIORITY_GATED: Retail listener-group branch 0x001ec348-0x001ec360 tests the same current-camera s0 +0x7e transition halfword. Nonzero jumps past the priority comparison to 0x001ec368; zero requires candidate priority to exceed current priority or rejects. This directly establishes the same priority-gated zero value used in the other two current->transition_state comparisons. --- src/camera/camera_activation_check_priority.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/camera/camera_activation_check_priority.c b/src/camera/camera_activation_check_priority.c index 9e32090a7d..61e213db4f 100644 --- a/src/camera/camera_activation_check_priority.c +++ b/src/camera/camera_activation_check_priority.c @@ -37,6 +37,9 @@ int camera_activation_check_priority(struct UpdateCam *candidate, struct UpdateC enum { CAMERA_COMPARE_ACCEPT = 1 }; + enum { + CAMERA_TRANSITION_PRIORITY_GATED = 0 + }; struct CameraActivation *activation = (struct CameraActivation *)&candidate->state; if (candidate->active == 0) { @@ -64,7 +67,7 @@ int camera_activation_check_priority(struct UpdateCam *candidate, struct UpdateC if (current == 0) { return 1; } - if (current->transition_state != 0) { + if (current->transition_state != CAMERA_TRANSITION_PRIORITY_GATED) { return 1; } if (activation->priority > current->active) { @@ -74,7 +77,7 @@ int camera_activation_check_priority(struct UpdateCam *candidate, struct UpdateC case CAMERA_ACTIVATION_IN_CLIP_VOLUME: { char *camera_descriptor_bytes = (char *)D_0015EF90[candidate->descriptor_index].unk1C; - if (current != 0 && current->transition_state == 0 && + if (current != 0 && current->transition_state == CAMERA_TRANSITION_PRIORITY_GATED && !(activation->priority > current->active)) { return 0; } @@ -90,7 +93,7 @@ int camera_activation_check_priority(struct UpdateCam *candidate, struct UpdateC if (listener_group != hero_state->unk2284) { return 0; } - if (current->transition_state == 0 && !(activation->priority > current->active)) { + if (current->transition_state == CAMERA_TRANSITION_PRIORITY_GATED && !(activation->priority > current->active)) { return 0; } if (listener_group != 3) { From ffe08c554a814c11fde202b7a4dba4e3c89b0a80 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:47:56 +0000 Subject: [PATCH 1406/1502] overlay: name set_hero_item_moby_flag_bit0 --- include/rnc/overlay/shared/hero/set_hero_animation.h | 2 +- src/overlays/l15/mobys/quartu_cutscene_trigger.c | 3 ++- .../shared/cutscenes/update_cutscene_playback.c | 4 ++-- .../game/initialize_level_transition_with_audio.c | 3 ++- src/overlays/shared/hero/hero_frame_update.c | 4 ++-- src/overlays/shared/hero/hero_idle_sequence.c | 10 ++++++---- src/overlays/shared/hero/hero_switch_item.c | 4 ++-- src/overlays/shared/hero/set_hero_animation.c | 4 ++-- src/overlays/shared/vendor/initialize_vendor_screen.c | 3 ++- src/overlays/shared/vendor/vendor_menu.c | 4 ++-- 10 files changed, 23 insertions(+), 18 deletions(-) diff --git a/include/rnc/overlay/shared/hero/set_hero_animation.h b/include/rnc/overlay/shared/hero/set_hero_animation.h index f31b2d7e64..75f548c6f4 100644 --- a/include/rnc/overlay/shared/hero/set_hero_animation.h +++ b/include/rnc/overlay/shared/hero/set_hero_animation.h @@ -12,7 +12,7 @@ void show_health_hud(void) __asm__("FUN_L00_00234e00"); s32 get_ammo(s32) __asm__("FUN_L00_00233e98"); s32 get_hero_target_pose_status(void) __asm__("FUN_L00_00233f38"); -void FUN_L00_00232fe8(void); +void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); void FUN_L00_002330d0(void); s32 use_ammo(s32, s32) __asm__("FUN_L00_00233db8"); diff --git a/src/overlays/l15/mobys/quartu_cutscene_trigger.c b/src/overlays/l15/mobys/quartu_cutscene_trigger.c index 61a6894bde..fa7ca3bdf6 100644 --- a/src/overlays/l15/mobys/quartu_cutscene_trigger.c +++ b/src/overlays/l15/mobys/quartu_cutscene_trigger.c @@ -11,6 +11,7 @@ #include "rnc/overlay/shared/game/queue_planet_unlock_message.h" #include "rnc/overlay/shared/game/unlock_planet.h" #include "rnc/overlay/shared/hero/set_hero_animation.h" +void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); #include "rnc/rendering/clip_volume.h" extern int D_L15_0015F5C4; @@ -63,7 +64,7 @@ void quartu_cutscene_trigger_update(struct Moby *moby) { start_scene(3); moby->state = CUTSCENE_TRIGGER_WAIT_FOR_FIRST_SCENE; jet_clear_persistent(moby->mission); - FUN_L00_00232fe8(); + set_hero_item_moby_flag_bit0(); break; case CUTSCENE_TRIGGER_WAIT_FOR_FIRST_SCENE: if (D_L15_0015F5C4 != 2) { diff --git a/src/overlays/shared/cutscenes/update_cutscene_playback.c b/src/overlays/shared/cutscenes/update_cutscene_playback.c index ba7a8b65a7..80e6aed93a 100644 --- a/src/overlays/shared/cutscenes/update_cutscene_playback.c +++ b/src/overlays/shared/cutscenes/update_cutscene_playback.c @@ -391,7 +391,7 @@ void music_pause(int) __asm__("FUN_00216050"); extern int update_audio_stream_until_idle(int) __asm__("FUN_002168a8"); void fill_transfer_words(void *, int, int) __asm__("FUN_001f97e8"); void clear_active_help_record(void) __asm__("FUN_L00_002039a0"); -void FUN_L00_00232fe8(void); +void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); int start_cutscene_chunk_read(int) __asm__("FUN_L00_002451b8"); void update_world_object_animation(void) __asm__("FUN_00204790"); void sound_update(void) __asm__("FUN_0022ca50"); @@ -433,7 +433,7 @@ void start_scene(int scene_id) { D_L00_0015F400 = 0; hero_set_state(100, 2); hero.unk20A5 = 1; - FUN_L00_00232fe8(); + set_hero_item_moby_flag_bit0(); if (active_scene_trigger.moby) active_scene_trigger.moby->flags |= 1; if (D_L00_001B9CF0.unkEC) diff --git a/src/overlays/shared/game/initialize_level_transition_with_audio.c b/src/overlays/shared/game/initialize_level_transition_with_audio.c index 34da3737ca..81cf2d25f4 100644 --- a/src/overlays/shared/game/initialize_level_transition_with_audio.c +++ b/src/overlays/shared/game/initialize_level_transition_with_audio.c @@ -14,6 +14,7 @@ #include "rnc/world/loaders/parse_space_scene_chunk.h" #include "rnc/audio/voices/sound_update.h" #include "rnc/overlay/shared/hero/set_hero_animation.h" +void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); #include "rnc/overlay/shared/mobys.h" #include "rnc/overlay/shared/streaming.h" #include "rnc/overlay/shared/ui/help/help_request.h" @@ -139,7 +140,7 @@ void initialize_level_transition_with_audio(int audio_selection_mode) { D_L00_0015F400 = 0; hero_set_state(100, 2); D_001413F5_lui = 1; - FUN_L00_00232fe8(); + set_hero_item_moby_flag_bit0(); D_0013E030_28e9c8.x0->flags |= 1; for (moby = D_L00_0015FFDC_28e9c8; moby->st != 0xFF; moby++) { if (!(moby->st & 0x80) && (moby->type == 0x4A || moby->type == 0xCB)) diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index 6de3a5222e..069d2fef77 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -729,7 +729,7 @@ extern void release_and_clear_hero_voice_slots(void) __asm__("FUN_L00_00206c08") extern void cancel_hero_item_animation(void) __asm__("FUN_L00_0020e698"); extern void hero_update_items() __asm__("FUN_L00_00210748"); extern void clear_hero_queued_animation(void) __asm__("FUN_L00_00232628"); -extern void FUN_L00_00232fe8(void); +extern void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); extern void clear_moby_transform_history(char *o) __asm__("FUN_L00_00262840"); extern void update_hero_collision_dimensions(void) __asm__("FUN_L01_00231ae0"); @@ -746,7 +746,7 @@ void enter_hero_vehicle_mode_and_set_moby(int vehicle_mode, int initial_state, i *(int *)&hero_state_base->moby = *(int *)&hero_state_base->unkA88; clear_moby_transform_history(&hero_state_base->trail.pos); hero_state_base->moby->collision_disable = -1; - FUN_L00_00232fe8(); + set_hero_item_moby_flag_bit0(); release_and_clear_hero_voice_slots(); reset_hero_easing_records(); *(char *)&hero_state_base->vehicle_mode = vehicle_mode; diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index 0e20d2e7a3..be54b90a3e 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -1911,8 +1911,10 @@ void update_hero_and_equipped_item_glows(void) { } } } +extern void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); -extern void FUN_L00_00232fe8(void); + +extern void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); extern void FUN_L00_002330d0(void); extern void apply_hero_vertical_oscillation(void) __asm__("FUN_L00_002078a8"); extern void apply_hero_rotation_oscillation(void) __asm__("FUN_L00_002079e8"); @@ -1928,7 +1930,7 @@ void update_hero_moby(void) { hero.moby->hit_slot = 0xFF; if (hero.unk20A5) { - FUN_L00_00232fe8(); + set_hero_item_moby_flag_bit0(); } else { FUN_L00_002330d0(); } @@ -1974,7 +1976,7 @@ void update_hero_moby(void) { extern void set_hero_moby_flag_bit0(void) __asm__("FUN_L00_00233210"); extern void clear_hero_moby_flag_bit0(void) __asm__("FUN_L00_00233248"); -extern void FUN_L00_00232fe8_00208a10(void) __asm__("FUN_L00_00232fe8"); +extern void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); extern void set_moby_local_table_entry(void *, int, void *, float, float) __asm__("FUN_L00_0024eed8"); @@ -1987,7 +1989,7 @@ void update_hero_vehicle_moby(void) { } else { clear_hero_moby_flag_bit0(); } - FUN_L00_00232fe8_00208a10(); + set_hero_item_moby_flag_bit0(); hero.moby->hit_slot = 0xFF; hero_moby = ((unsigned char *)hero.moby); qcopy(&MOBY(hero_moby)->pos, &hero.motion.pos); diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 1a77ed5e26..557bb158c5 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -2326,7 +2326,7 @@ void update_hero_equipped_items(void) { } void clear_moby_transform_history(void *) __asm__("FUN_L00_00262840"); -void FUN_L00_00232fe8_210a08(void) __asm__("FUN_L00_00232fe8"); +void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); void reset_hero_easing_records(void) __asm__("FUN_L00_00205538"); void update_hero_collision_capsule_dimensions(void) __asm__("FUN_L00_00211380"); void clear_hero_queued_animation(void) __asm__("FUN_L00_00232628"); @@ -2345,7 +2345,7 @@ void enter_hero_vehicle_mode(int mode, int requested_state, char *vehicle_moby) hero_state->moby = (struct Moby *)hero_state->unkA88; clear_moby_transform_history(&hero_state->trail); hero_state->moby->collision_disable = -1; - FUN_L00_00232fe8_210a08(); + set_hero_item_moby_flag_bit0(); release_and_clear_hero_voice_slots(); reset_hero_easing_records(); hero_state->vehicle_mode = mode; diff --git a/src/overlays/shared/hero/set_hero_animation.c b/src/overlays/shared/hero/set_hero_animation.c index dbabca6ec6..9a0217306b 100644 --- a/src/overlays/shared/hero/set_hero_animation.c +++ b/src/overlays/shared/hero/set_hero_animation.c @@ -703,9 +703,9 @@ typedef struct { extern int D_L00_0015F5C4; -void FUN_L00_00232fe8(void); +void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); -void FUN_L00_00232fe8(void) { +void set_hero_item_moby_flag_bit0(void) { struct Hero *hero_item_flag_state = &hero; struct Hero *tail; struct Hero *last; diff --git a/src/overlays/shared/vendor/initialize_vendor_screen.c b/src/overlays/shared/vendor/initialize_vendor_screen.c index e2f37e262e..7023d462cc 100644 --- a/src/overlays/shared/vendor/initialize_vendor_screen.c +++ b/src/overlays/shared/vendor/initialize_vendor_screen.c @@ -18,6 +18,7 @@ #include "rnc/audio/voices/sound_update.h" #include "rnc/overlay/shared/hero/hero_switch_item.h" #include "rnc/overlay/shared/hero/set_hero_animation.h" +void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); #include "rnc/overlay/shared/streaming.h" #include "rnc/overlay/shared/ui/help/help_request.h" @@ -81,7 +82,7 @@ void initialize_vendor_screen(char *vendor_moby, int lvl) { l01_hero_set_state(100, 1); *(char *)&hero_state->item_use_locked = 1; *(char *)&hero_state->unk20A5 = 1; - FUN_L00_00232fe8(); + set_hero_item_moby_flag_bit0(); transform_vector_by_basis(sc, &vendor_camera_local_position_offset, vendor_moby + 0xC0); fast_vec_add(sc, sc, &MOBY(vendor_moby)->pos); *(float *)(vendor_screen_state + 0xC8) = probe_ground_height(sc, 0, 0.5f); diff --git a/src/overlays/shared/vendor/vendor_menu.c b/src/overlays/shared/vendor/vendor_menu.c index 61ad6e2099..ee3fee1a6d 100644 --- a/src/overlays/shared/vendor/vendor_menu.c +++ b/src/overlays/shared/vendor/vendor_menu.c @@ -345,7 +345,7 @@ extern void snd_flush_sound_commands(void) __asm__("FUN_0012dc80"); extern void reset_hud_and_suspend_weapon_updates(void) __asm__("FUN_L00_0023aef8"); extern void initialize_numeric_hud_timer_and_base_dimensions(void) __asm__("FUN_L00_0023a760"); extern void draw_weapon_ammo_hud_panel(void) __asm__("FUN_L00_0023a7a8"); -extern void FUN_L00_00232fe8_29a6b0(void) __asm__("FUN_L00_00232fe8"); +extern void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); typedef unsigned int Q_29a6b0 __attribute__((mode(TI), aligned(16))); extern u8 vendor_extra[] __asm__("D_L00_001CA6E0"); @@ -452,7 +452,7 @@ void open_vendor_menu(void *vendor_moby_arg) { hero_set_state(100, 1); D_0013F350[0x20AC] = 1; D_0013F350[0x20A5] = 1; - FUN_L00_00232fe8_29a6b0(); + set_hero_item_moby_flag_bit0(); if (vendor_menu.mode != VENDOR_MENU_MODE_EXISTING_VENDOR) { set_moby_animation(vendor_moby, 3, 0); } else { From a7797d6e5dd5fb0b8fcb237ba1bab69f96bd31c3 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:47:57 +0000 Subject: [PATCH 1407/1502] decomp: clarify names in spawn_crate_debris domain_0_value_0 -> NANOTECH_CRATE_FRAGMENT_BOUNCING: Retail 0x002af904 retains create_moby's result in s1, and 0x002af930 executes sb zero,0x20(s1); original retail Ghidra likewise writes zero to iVar8+0x20. The authoritative spawn source maps this exact store to MOBY(debris_moby)->state = 0. In the same supplied source, M_2afa48 places b20 at offset 0x20 and nanotech_crate_fragment_update switches on fragment_moby->b20 with existing NANOTECH_CRATE_FRAGMENT_BOUNCING = 0. That branch gates collision response on the bounce count, decrements it, reflects velocity and damps it, while state 1 shrinks and fades the fragment. Matching private-data offsets +0x0C (bounce count), +0x0E (timer) and +0x10 (velocity) further tie the initializer to this update state domain. Thus this is the established bouncing state, not an unrelated zero-valued control. --- src/overlays/shared/pickups/crate_fragment.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/pickups/crate_fragment.c b/src/overlays/shared/pickups/crate_fragment.c index 7b0decff96..1904761e2b 100644 --- a/src/overlays/shared/pickups/crate_fragment.c +++ b/src/overlays/shared/pickups/crate_fragment.c @@ -144,6 +144,9 @@ unsigned char *spawn_crate_debris(unsigned char *debris_source_moby, float lo, float hi) { + enum { + NANOTECH_CRATE_FRAGMENT_BOUNCING = 0 + }; unsigned char *debris_moby = create_moby(type); if (debris_moby) { V_2af8b0 *debris_data = ((V_2af8b0 *)MOBY(debris_moby)->pvars); @@ -153,7 +156,7 @@ unsigned char *spawn_crate_debris(unsigned char *debris_source_moby, MOBY(debris_moby)->draw_dist = 0x7E; MOBY(debris_moby)->visible = 1; MOBY(debris_moby)->spawn_frame = *(long *)(debris_source_moby + 0x38); - MOBY(debris_moby)->state = 0; + MOBY(debris_moby)->state = NANOTECH_CRATE_FRAGMENT_BOUNCING; MOBY(debris_moby)->rot.x = random_angle_radians(); MOBY(debris_moby)->rot.y = random_angle_radians(); MOBY(debris_moby)->rot.z = random_angle_radians(); From 8c7f79b9fe9a9268c08bd8e21a2e9963b9d0a135 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:59:33 +0000 Subject: [PATCH 1408/1502] decomp: clarify names in spawn_fighter_jet_rocket domain_0_value_0 -> FIGHTER_JET_ROCKET_STATE_INITIAL: Retail 0x002e6a94..0x002e6aa0 allocates class 0x127 and retains the returned rocket in s0; after the allocation-success branch, 0x002e6ac8 (sb zero,0x20(s0)) unconditionally installs its initial moby state. Authoritative source SHA-256 d60e0dead45e398ae36956e7a57b2c3ea81782c78a1f1b9150b164ca81dd9101 identifies this exact store as MOBY(moby)->state = 0 in spawn_fighter_jet_rocket. Original retail Ghidra corroborates the byte store to allocated moby+0x20. This occurs before movement initialization at 0x002e6b38, initial position advancement at 0x002e6b68, and update_entity at 0x002e6ba8, proving INITIAL as the spawner-installed state without claiming a wider state lifecycle. --- src/overlays/shared/vehicles/fighter_jet_rocket.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/vehicles/fighter_jet_rocket.c b/src/overlays/shared/vehicles/fighter_jet_rocket.c index ac4607fa45..9368b37b0f 100644 --- a/src/overlays/shared/vehicles/fighter_jet_rocket.c +++ b/src/overlays/shared/vehicles/fighter_jet_rocket.c @@ -34,13 +34,16 @@ unsigned char *spawn_fighter_jet_rocket(struct Moby *firing_moby, int lifetime_frames, float scale) { + enum { + FIGHTER_JET_ROCKET_STATE_INITIAL = 0 + }; unsigned char *moby = create_moby(0x127); if (moby != 0) { char *rocket_private_state = ((char *)MOBY(moby)->pvars); MOBY(moby)->update_dist = 0xFF; MOBY(moby)->draw_dist = 0xFF; MOBY(moby)->visible = 1; - MOBY(moby)->state = 0; + MOBY(moby)->state = FIGHTER_JET_ROCKET_STATE_INITIAL; *(char **)(rocket_private_state + 0x20) = firing_moby; *(char **)(rocket_private_state + 0x24) = target; qcopy(&MOBY(moby)->pos, spawn_position); From 25bd43602b3be7c81ca9ad896d0e49146262195a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:59:33 +0000 Subject: [PATCH 1409/1502] decomp: clarify names in floating_platform_update domain_0_value_1 -> FLOATING_PLATFORM_UPDATE_ROCKING: Retail 0x0030be00 loads the state byte at moby+0x20; 0x0030be0c-0x0030be10 compares that same byte to 1 and branches to 0x0030be68, the source's existing FLOATING_PLATFORM_UPDATE_ROCKING case. Initialization seeds timer and phases, then 0x0030be5c loads 1 and 0x0030be64 stores it to the identical state byte. Thus this assignment enters that exact local enum domain/member, whose branch advances phases and stores sine-based rotations at 0x0030bf2c/0x0030bf58. --- src/overlays/l05/mobys/floating_platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l05/mobys/floating_platform.c b/src/overlays/l05/mobys/floating_platform.c index d14a73b8e2..25a99e95fc 100644 --- a/src/overlays/l05/mobys/floating_platform.c +++ b/src/overlays/l05/mobys/floating_platform.c @@ -62,7 +62,7 @@ void floating_platform_update(unsigned char *moby) { (float)floating_platform_voice_interval_max_gp))); floating_platform_vars->unk60 = random_angle_radians(); floating_platform_vars->unk6C = random_angle_radians(); - MOBY(moby)->state = 1; + MOBY(moby)->state = FLOATING_PLATFORM_UPDATE_ROCKING; break; case FLOATING_PLATFORM_UPDATE_ROCKING: if (fast_dec_timer(&floating_platform_vars->timer_78)) { From b84cc0706152bdae79d7fc921f8b97095bf92c2f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:59:33 +0000 Subject: [PATCH 1410/1502] decomp: clarify names in gadgebot_spawn_container_update domain_0_value_1 -> GADGEBOT_CONTAINER_PULSE_AND_HANDLE_HITS: Retail 0x002d85c4 loads moby+0x20 into v1; 0x002d85cc loads a0=1 and 0x002d85d0 selects the pulse/hit branch when v1 equals a0. For state zero, 0x002d85e4 branches to 0x002d8604 and its delay slot at 0x002d8608 stores that same a0=1 into moby+0x20. This is exactly MOBY(moby)->state, whose existing local enum case GADGEBOT_CONTAINER_PULSE_AND_HANDLE_HITS=1 performs the 150-frame color pulse at 0x002d860c-0x002d86b0 and hit handling at 0x002d86ac-0x002d86bc. Reuse that same-domain member for the activation assignment. --- src/overlays/shared/enemies/gadgebot_spawn_container.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/gadgebot_spawn_container.c b/src/overlays/shared/enemies/gadgebot_spawn_container.c index 6ab438f20a..7badf1210d 100644 --- a/src/overlays/shared/enemies/gadgebot_spawn_container.c +++ b/src/overlays/shared/enemies/gadgebot_spawn_container.c @@ -187,7 +187,7 @@ void gadgebot_spawn_container_update(unsigned char *moby) { MOBY(moby)->hit_slot = 0xFF; switch (MOBY(moby)->state) { case GADGEBOT_CONTAINER_ACTIVATE: - MOBY(moby)->state = 1; + MOBY(moby)->state = GADGEBOT_CONTAINER_PULSE_AND_HANDLE_HITS; break; case GADGEBOT_CONTAINER_PULSE_AND_HANDLE_HITS: frame_count_snapshot = level_frame_count; From cd8ccb7da37b3456074026477c89e8a1f839ca9a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:59:33 +0000 Subject: [PATCH 1411/1502] decomp: clarify names in update_hero_frame domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x00228884 constructs hero base 0x0013F350; lbu at 0x002288E4 reads +0x20A4 (0x001413F4), identified by the authoritative struct Hero source as vehicle_mode. At 0x0022890C zero branches into the ordinary hero update chain; nonzero calls hero_frame_update at 0x00228914. The supplied hero_frame_update tests the same hero.vehicle_mode against HERO_VEHICLE_MODE_ON_FOOT, and exit_hero_vehicle_mode_and_restore_moby writes zero while restoring the ordinary hero moby. This proves the HeroVehicleMode domain and its canonical zero member from include/rnc/hero/hero_state.h, rather than equating it with a current-state or control-mode ID. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x0022894C reloads lbu v0,0x20A4(s0) from hero base 0x0013F350 immediately after update_hero_state_machine (0x00228944); bne at 0x00228950 exits on nonzero and zero continues the ordinary on-foot easing, equipment and world-matrix pipeline. This is exactly the same Hero.vehicle_mode selector as the earlier dispatch, not state.current (+0x2084) or state.control_mode (+0x208C). Supplied hero_frame_update already uses HERO_VEHICLE_MODE_ON_FOOT for this field and vehicle exit restores zero, proving reuse of canonical HeroVehicleMode member HERO_VEHICLE_MODE_ON_FOOT = 0. --- src/overlays/shared/hero/hero_frame_update.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index 069d2fef77..258ba15878 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -242,7 +242,7 @@ void update_hero_frame(void) { } hero_state_base->unk1EB2 = 0; hero_state_base->unk1EB0 = 0; - if (hero_state_base->vehicle_mode != 0) { + if (hero_state_base->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { hero_frame_update(); return; } @@ -251,7 +251,7 @@ void update_hero_frame(void) { update_hero_ground_material_effects(); update_hero_ledge_probe(); update_hero_state_machine(); - if (hero_state_base->vehicle_mode != 0) { + if (hero_state_base->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { return; } update_hero_delayed_voice_requests(); From 135535395e2134c079f88e96871b1fcca7d68f12 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:59:33 +0000 Subject: [PATCH 1412/1502] decomp: clarify names in linked_moby_states_update domain_0_value_1 -> STATE_ACTIVE: The source's local enum defines STATE_ACTIVE=1 and dispatches switch(MOBY(source_moby)->state) through case STATE_ACTIVE. Retail preserves source_moby in s2 at 0x002b3464, loads its state byte +0x20 at 0x002b3470 and compares it with 1 at 0x002b347c-0x002b3480 to enter the recurring update body at 0x002b34f4. The initialization branch loads 1 at 0x002b3490 and stores it to that identical +0x20(s2) state field at 0x002b3498 before initializing counters and four linked references. Original Ghidra likewise writes param_1-derived +0x20=1 and tests the same byte against 1. This proves reuse of STATE_ACTIVE in this exact local state domain, rather than merely matching a numeric value. --- src/overlays/shared/weapons/linked_moby_states_update.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/linked_moby_states_update.c b/src/overlays/shared/weapons/linked_moby_states_update.c index b89eafb3e3..578eb6afaf 100644 --- a/src/overlays/shared/weapons/linked_moby_states_update.c +++ b/src/overlays/shared/weapons/linked_moby_states_update.c @@ -70,7 +70,7 @@ void linked_moby_states_update(unsigned char *source_moby) { int matching_owned_record, i; switch (MOBY(source_moby)->state) { case STATE_INITIALIZE: - MOBY(source_moby)->state = 1; + MOBY(source_moby)->state = STATE_ACTIVE; moby_vars->w4 = linked_moby_selection_delay_gp; moby_vars->w8 = 3; moby_vars->p[0] = moby_table + (moby_vars->idx[0] << 8); From 6a95c59fb8fb22b82ebea7255b8d97c33b2492db Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:59:33 +0000 Subject: [PATCH 1413/1502] decomp: clarify names in prop_breakup_update domain_0_value_1 -> MOBY_STATE_WAIT_FOR_HIT: Retail 0x00309870 keeps breakup_moby in s1; 0x00309898 loads its state byte at +0x20 for dispatch. The zero-state path writes 1 to precisely that byte at 0x003098d4. Dispatch of that byte equal to 1 at 0x0030989c reaches the nonnull hit/positive +0x2C gate at 0x003098d8-0x003098fc. Thus this assignment enters the existing local MOBY_STATE_WAIT_FOR_HIT case in the authoritative C, proving domain identity by the same object and offset, not merely numeric equality. domain_1_value_2 -> MOBY_STATE_SPAWN_AND_REMOVE: Retail 0x003098d8-0x003098f8 tests the find_moby_hit result and its positive float at +0x2C; 0x00309900 loads 2 and 0x00309908 stores it to breakup_moby state +0x20. The same byte is read at 0x00309898 and dispatched for value 2 at 0x003098c0 to 0x0030990c, which spawns classes 0x679/0x67A/0x67B, attempts 0x678, then removes the original moby at 0x00309a00. This is exactly the existing local MOBY_STATE_SPAWN_AND_REMOVE switch member. --- src/overlays/shared/props/breakable_prop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/props/breakable_prop.c b/src/overlays/shared/props/breakable_prop.c index 4894b7532e..1520c3088f 100644 --- a/src/overlays/shared/props/breakable_prop.c +++ b/src/overlays/shared/props/breakable_prop.c @@ -45,14 +45,14 @@ void prop_breakup_update(char *breakup_moby) { struct Moby *hit_moby = find_moby_hit(breakup_moby, 0x10000, 0); switch (((unsigned char *)breakup_moby)[0x20]) { case MOBY_STATE_INITIALIZE: - MOBY(breakup_moby)->state = 1; + MOBY(breakup_moby)->state = MOBY_STATE_WAIT_FOR_HIT; break; case MOBY_STATE_WAIT_FOR_HIT: if (hit_moby != 0 && hit_moby->scale > 0.0f) { flag = 1; } if (flag) { - MOBY(breakup_moby)->state = 2; + MOBY(breakup_moby)->state = MOBY_STATE_SPAWN_AND_REMOVE; } break; case MOBY_STATE_SPAWN_AND_REMOVE: { From cb07a89e59e65e5a619cf04e40b380b62c664f51 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:59:33 +0000 Subject: [PATCH 1414/1502] decomp: clarify names in begin_sentrybot_turn_toward_heading domain_0_value_8 -> SENTRYBOT_TURN_AROUND: Retail 0x002998A4 binds s1 to the sentrybot moby argument; 0x00299918-20 writes 8 to its state byte at +0x20 after the negated rotation difference exceeds +/-2.0943952 radians. 0x00299924-4C wraps positive turn_delta by -2*pi and 0x00299954-74 selects animation 12. The same moby's state switch in supplied sentrybot_update already names 8 SENTRYBOT_TURN_AROUND and uses sentrybot_turn_around_heading_offsets_degrees for animation 12, then restores stored next state/animation on completion. domain_1_value_6 -> SENTRYBOT_TURN_NEGATIVE_HEADING_DELTA: Retail 0x00299978-94 compares the negated rotation difference f2 against -0.7853982; the taken negative-delta branch stores 6 at sentrybot moby s1+0x20 in 0x002999A4 and selects animation 10 at 0x002999BC. Supplied sentrybot_update consumes this same MOBY(moby)->state, already names 6 SENTRYBOT_TURN_NEGATIVE_HEADING_DELTA, and associates animation 10 with sentrybot_negative_heading_delta_offsets_degrees. This proves the sentrybot state domain rather than HeroStateId. domain_2_value_7 -> SENTRYBOT_TURN_POSITIVE_HEADING_DELTA: Retail 0x002999C0-D8 tests 0.7853982 < heading delta f2; 0x002999EC stores 7 into sentrybot moby s1+0x20 and 0x00299A00 selects animation 11. Supplied sentrybot_update switches on this same moby state byte, already names 7 SENTRYBOT_TURN_POSITIVE_HEADING_DELTA, and maps animation 11 to sentrybot_positive_heading_delta_offsets_degrees before restoring the stored next state at animation completion. The assignment belongs to the sentrybot state domain. --- src/overlays/shared/enemies/sentrybot.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/sentrybot.c b/src/overlays/shared/enemies/sentrybot.c index 0549ab2622..2f4b3f42bb 100644 --- a/src/overlays/shared/enemies/sentrybot.c +++ b/src/overlays/shared/enemies/sentrybot.c @@ -1225,6 +1225,11 @@ int begin_sentrybot_turn_toward_heading( int next_animation, float angle) { + enum { + SENTRYBOT_TURN_NEGATIVE_HEADING_DELTA = 6, + SENTRYBOT_TURN_POSITIVE_HEADING_DELTA = 7, + SENTRYBOT_TURN_AROUND = 8 + }; float heading_delta = -fast_subtract_rotations(MOBY(moby)->rot.z, angle); float stored_heading_delta; int turn_required = 1; @@ -1235,7 +1240,7 @@ int begin_sentrybot_turn_toward_heading( moby_data->unk15C = next_state; moby_data->unk15D = next_animation; if (heading_delta > 2.0943952f || heading_delta < -2.0943952f) { - MOBY(moby)->state = 8; + MOBY(moby)->state = SENTRYBOT_TURN_AROUND; stored_heading_delta = moby_data->turn_delta; if (stored_heading_delta > 0.0f) { moby_data->turn_delta = stored_heading_delta + -6.2831855f; @@ -1245,13 +1250,13 @@ int begin_sentrybot_turn_toward_heading( } } else if (heading_delta < -0.7853982f) { - MOBY(moby)->state = 6; + MOBY(moby)->state = SENTRYBOT_TURN_NEGATIVE_HEADING_DELTA; if (MOBY(moby)->prev_seq != 0xA) { blend_moby_animation(moby, 0xA, 0, scale_game_frames(10)); } } else if (heading_delta > 0.7853982f) { - MOBY(moby)->state = 7; + MOBY(moby)->state = SENTRYBOT_TURN_POSITIVE_HEADING_DELTA; if (MOBY(moby)->prev_seq != 0xB) { blend_moby_animation(moby, 0xB, 0, scale_game_frames(10)); } From 1a69fde4504676a3476ea42584801689e9019218 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:59:33 +0000 Subject: [PATCH 1415/1502] decomp: clarify names in pterodactyl_update domain_0_value_1 -> PTERODACTYL_FOLLOW_PATH: Authoritative source src/overlays/shared/props/pterodactyl.c SHA-256 70031f0b6957a91b705abc0f9bd8f4c006b50474ae84b49fc79eea2103d9982c declares PTERODACTYL_FOLLOW_PATH = 1 for switch (MOBY(moby)->state). Retail 002e3ab4 loads that same state byte at +0x20; 002e3acc-002e3ad0 compares it to 1 and branches to path sampling at 002e3b9c. Initialization loads 1 at 002e3b70 and stores it to the identical byte at 002e3b84, then falls through to that handler. The original Ghidra decompilation independently shows the +0x20 assignment and case-1 dispatch. Sampling position/rotation and advancing/wrapping path progress at 002e3b9c-002e3c0c proves reuse of the existing state member, rather than a merely equal-valued boolean or control constant. --- src/overlays/shared/props/pterodactyl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/props/pterodactyl.c b/src/overlays/shared/props/pterodactyl.c index c05cf414e0..a38cada8b2 100644 --- a/src/overlays/shared/props/pterodactyl.c +++ b/src/overlays/shared/props/pterodactyl.c @@ -55,7 +55,7 @@ void pterodactyl_update(unsigned char *moby) { moby_data->i70 = absolute_float(first_segment_length - first_to_last_distance) < 0.1f; } moby_data->f6C = moby_data->f68 * (float)*path; - MOBY(moby)->state = 1; + MOBY(moby)->state = PTERODACTYL_FOLLOW_PATH; MOBY(moby)->scale *= pterodactyl_scale_multiplier_gp; MOBY(moby)->update_dist = 0xFF; case PTERODACTYL_FOLLOW_PATH: From 2dd4b43e7786dad6f7400c24bb3915f40740ba41 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:01:35 +0000 Subject: [PATCH 1416/1502] decomp: clarify names in update_hero_frame_pipeline domain_0_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002002fc/0x0020030c establishes Hero base 0x0013f350; 0x0020036c loads its byte at +0x20a4 (0x001413f4), mapped by the authoritative C to hero_state->vehicle_mode. At 0x00200394 a zero byte enters advance_hero_animation and the normal hero pipeline; nonzero calls hero_frame_update at 0x0020039c and returns. The supplied update_hero_state_machine context uses this same hero.vehicle_mode selector with HERO_VEHICLE_MODE_ON_FOOT and HERO_VEHICLE_MODE_CLANK, proving the HeroVehicleMode domain. Reuse its canonical zero member HERO_VEHICLE_MODE_ON_FOOT from include/rnc/hero/hero_state.h. domain_1_value_0 -> HERO_VEHICLE_MODE_ON_FOOT: Retail 0x002003dc reloads the identical Hero base+0x20a4 vehicle_mode byte immediately after update_hero_state_machine (jal 0x0021c668 at 0x002003d4). The bne against zero at 0x002003e0 returns for nonzero modes; zero continues the on-foot pipeline at 0x002003e8. Authoritative C names this field hero_state->vehicle_mode, and supplied state-machine context compares hero.vehicle_mode directly with canonical HeroVehicleMode members ON_FOOT and CLANK. Thus this second gate reuses HERO_VEHICLE_MODE_ON_FOOT=0 in that same shared enum, independently of control_mode/current-state fields at +0x208c/+0x2084. --- src/overlays/shared/hero/update_hero_frame_pipeline.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/hero/update_hero_frame_pipeline.c b/src/overlays/shared/hero/update_hero_frame_pipeline.c index aaed16f457..12c0585c95 100644 --- a/src/overlays/shared/hero/update_hero_frame_pipeline.c +++ b/src/overlays/shared/hero/update_hero_frame_pipeline.c @@ -34,7 +34,7 @@ void update_hero_frame_pipeline(void) { } hero_state->unk1EB2 = 0; hero_state->unk1EB0 = 0; - if (hero_state->vehicle_mode != 0) { + if (hero_state->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { hero_frame_update(); return; } @@ -44,7 +44,7 @@ void update_hero_frame_pipeline(void) { update_hero_ledge_probe(); update_hero_offset_rail_candidate(); update_hero_state_machine(); - if (hero_state->vehicle_mode != 0) { + if (hero_state->vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT) { return; } update_hero_delayed_voice_requests(); From 34f23851f55912773f853ad9faa7d9a5e817ba39 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:01:35 +0000 Subject: [PATCH 1417/1502] decomp: clarify names in sentrybot_projectile_update domain_0_value_0 -> SENTRYBOT_PROJECTILE_STATE_FLYING: Retail 0x002e43a8 loads the entity state byte at s2+0x20 and 0x002e43bc returns when nonzero. Only zero executes rotation at 0x002e43e4, position-plus-velocity at 0x002e43f8, collision/lifetime checks and position commit at 0x002e450c-0x002e4510. The authoritative source's spawn_sentrybot_projectile creates class 0x3A6 and explicitly assigns MOBY(spawned_moby)->state = SENTRYBOT_PROJECTILE_STATE_FLYING (local enum value 0), initializes velocity/timer/source in the same private block, then calls update_entity. Both assignment and comparison operate on the same class's Moby state field, proving reuse of this established state-domain name rather than FALSE or NULL. --- src/overlays/shared/enemies/sentrybot_projectile.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/sentrybot_projectile.c b/src/overlays/shared/enemies/sentrybot_projectile.c index bd0065a322..9324cb35e2 100644 --- a/src/overlays/shared/enemies/sentrybot_projectile.c +++ b/src/overlays/shared/enemies/sentrybot_projectile.c @@ -29,6 +29,9 @@ void sentrybot_projectile_update(unsigned char *moby) __asm__("FUN_L15_002e4380" /* Moby class 934 */ void sentrybot_projectile_update(unsigned char *moby) { + enum { + SENTRYBOT_PROJECTILE_STATE_FLYING = 0 + }; char *moby_vars = ((char *)MOBY(moby)->pvars); float next_position[4]; char col[0x30]; @@ -37,7 +40,7 @@ void sentrybot_projectile_update(unsigned char *moby) { mark_moby_for_removal(moby); return; } - if (MOBY(moby)->state != 0) + if (MOBY(moby)->state != SENTRYBOT_PROJECTILE_STATE_FLYING) return; MOBY(moby)->rot.x = fast_add_rotations(MOBY(moby)->rot.x, frame_time * 6.2831855f); fast_vec_add(next_position, &MOBY(moby)->pos, moby_vars); From 4e7c13a9e98c86bfa1a0a938b35a44a6876ca907 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:01:35 +0000 Subject: [PATCH 1418/1502] decomp: clarify names in memcard_save_data domain_0_value_3 -> MEMCARD_REQUEST_FORMAT: Retail 0020b238 loads +D4 from the D_0013D290 MemoryCardState base, and 0020b23c-0020b240 tests operation state <3 before permitting save preparation. Original Ghidra identifies this word as g_nMemoryCardOperationState; source maps it to card_state->state. The supplied memory_card_state.h domain explicitly assigns state/pending_state to MemoryCardOperation, whose canonical value 3 is MEMCARD_REQUEST_FORMAT. This names the existing comparison boundary, not a format request made here. domain_1_value_0 -> MEMCARD_QUERY_INFO: Retail 0020b248-0020b24c loads the +DC pending-operation word from the same MemoryCardState base and skips preparation when it is nonnegative. Original Ghidra calls it g_nPendingMemoryCardOperationState; source uses card_state->pending_state. The supplied shared-header declaration assigns this field to MemoryCardOperation, with MEMCARD_QUERY_INFO as canonical value 0. This is the lower nonnegative operation boundary, while negative values mean no pending operation. domain_2_value_0 -> LEVEL_VISIT_UNVISITED: Retail 0020b25c initializes s2 to zero; 0020b27c replaces it with g_abLevelVisitState[param_2] when an override level is supplied. At 0020b280-0020b28c a zero visit byte is changed to one for serialization, and 0020b368 restores saved s2. Source saved_visit_state holds this saved level-visit byte, so its zero initializer is the same unvisited value used by the following zero comparison, in a domain separate from memory-card operations. domain_3_value_0 -> LEVEL_VISIT_UNVISITED: Retail 0020b274-0020b27c reads the byte at level_visit_state plus the supplied level index into s2. The branch at 0020b280 skips the store for nonzero bytes; 0020b288-0020b28c changes only zero to one. Source names this array level_visit_state and restores the saved byte after memcard_prepare_data, proving zero denotes the unvisited state temporarily marked visited in the save snapshot. Reuse the same separate visit-domain constant as the initializer. domain_4_value_0 -> MEMCARD_QUERY_INFO: After serializing save data, retail 0020b374-0020b378 reads +DC from MemoryCardState and queues a new operation only when this pending-operation word is negative. Source maps the word to card_state->pending_state, and original Ghidra names it g_nPendingMemoryCardOperationState. The supplied shared header assigns it to MemoryCardOperation; MEMCARD_QUERY_INFO=0 is the canonical lower nonnegative operation boundary, matching the earlier >=0 gate. domain_5_value_15 -> MEMCARD_BEGIN_UPDATE_SAVE: Retail 0020b330 and 0020b348 prepare game and level save buffers; 0020b374-0020b388 then writes 15 to the negative +DC pending-operation field, and 0020b380/0020b38c copies active_card (+C0) to pending_card (+E0). Original Ghidra identifies +DC as pending memory-card operation state, and supplied memory_card_state.h assigns state/pending_state to MemoryCardOperation. Its canonical member MEMCARD_BEGIN_UPDATE_SAVE=15 describes this queued save operation; the independent create-step value 15 does not apply. domain_6_value_15 -> MEMCARD_BEGIN_UPDATE_SAVE: Retail 0020b390-0020b39c reconstructs D_0013D290, loads the +DC pending-operation word, and returns whether it equals 15 via xori/sltiu. This is the same field assigned 15 at 0020b384-0020b388 after save-buffer preparation. Source memory_card_state.pending_state and original Ghidra g_nPendingMemoryCardOperationState prove the shared MemoryCardOperation domain, whose canonical member is MEMCARD_BEGIN_UPDATE_SAVE. Reuse that member for both assignment and success comparison. --- src/save/memcard_save_data.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/save/memcard_save_data.c b/src/save/memcard_save_data.c index 10d2b571db..f01834a0ca 100644 --- a/src/save/memcard_save_data.c +++ b/src/save/memcard_save_data.c @@ -26,6 +26,9 @@ int memcard_save_data(int slot, int flags) __asm__("FUN_0020b178"); extern s32 current_bolt_count_macro __asm__("D_0015ED98") MACRO_ADDR; int memcard_save_data(int slot, int flags) { + enum { + LEVEL_VISIT_UNVISITED = 0 + }; unsigned char saved_visit_state; sceCdReadClock(D_0015EE98); @@ -48,18 +51,18 @@ int memcard_save_data(int slot, int flags) { if (slot == 0) { mode_freeze_flags |= 0x200; } - if (card_state->state >= 3) { + if (card_state->state >= MEMCARD_REQUEST_FORMAT) { goto done; } - if (card_state->pending_state >= 0) { + if (card_state->pending_state >= MEMCARD_QUERY_INFO) { goto done; } card_state->record_index = current_level_index; - saved_visit_state = 0; + saved_visit_state = LEVEL_VISIT_UNVISITED; if (flags >= 0) { current_level_index = flags; saved_visit_state = level_visit_state[flags]; - if (saved_visit_state == 0) { + if (saved_visit_state == LEVEL_VISIT_UNVISITED) { level_visit_state[flags] = 1; } } @@ -84,13 +87,13 @@ int memcard_save_data(int slot, int flags) { level_visit_state[current_level_index] = saved_visit_state; current_level_index = card_state->record_index; } - if (card_state->pending_state < 0) { - card_state->pending_state = 0xF; + if (card_state->pending_state < MEMCARD_QUERY_INFO) { + card_state->pending_state = MEMCARD_BEGIN_UPDATE_SAVE; card_state->pending_card = card_state->active_card; } } done: - return memory_card_state.pending_state == 0xF; + return memory_card_state.pending_state == MEMCARD_BEGIN_UPDATE_SAVE; } extern __typeof__(memcard_save_data) func_0020B178 __attribute__((alias("FUN_0020b178"))); From 88bba9064283c0d2194e5a374b8e4133df2ac823 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:01:35 +0000 Subject: [PATCH 1419/1502] decomp: clarify names in release_moby_with_collision_check domain_0_value_4 -> DECOY_PRE_REMOVAL_DELAY: Retail 0x002c3894 preserves moby a1 in s2; 0x002c3998-0x002c39a8 writes 4 to s2+0x20 and a scaled 30-frame timer to pvars+0x44 after zeroing velocity at 0x002c3994. The authoritative decoy_update names the same MOBY(moby)->state value DECOY_PRE_REMOVAL_DELAY; its state-4 branch decrements that timer then selects 5 for shrinking/removal. This proves the decoy state domain rather than HeroStateId. domain_1_value_2 -> DECOY_THROWN_MOVEMENT: Retail 0x002c397c branches on a clear collision_line result to 0x002c3ac4-0x002c3ac8, writing 2 to the released moby's state byte s2+0x20 while retaining initial velocity at pvars+0x10. In the authoritative source decoy_update consumes that same state field as DECOY_THROWN_MOVEMENT=2, subtracts gravity from pvars+0x18 and passes pvars+0x10 to the movement/collision helper. The selector is a decoy moby state, not hero current state or vehicle mode. --- src/overlays/shared/weapons/decoy.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/decoy.c b/src/overlays/shared/weapons/decoy.c index c43b96b239..7f2269114d 100644 --- a/src/overlays/shared/weapons/decoy.c +++ b/src/overlays/shared/weapons/decoy.c @@ -278,6 +278,10 @@ void release_moby_with_collision_check(float *release_position, char *moby, void *initial_velocity) { + enum { + DECOY_THROWN_MOVEMENT = 2, + DECOY_PRE_REMOVAL_DELAY = 4 + }; float collision_start[4], collision_normal[4], rotated_normal[4]; char *state = *(char **)(moby + 0x78); struct Hero *camera; @@ -301,7 +305,7 @@ void release_moby_with_collision_check(float *release_position, float smoothing; qcopy(&MOBY(moby)->pos, D_00173F60_alias); qzero(state + 0x10); - MOBY(moby)->state = 4; + MOBY(moby)->state = DECOY_PRE_REMOVAL_DELAY; *(short *)(state + 0x44) = scale_game_frames_c(30); MOBY(moby)->pos.z = ((S173E40 *)D_L00_00173E40)->height; qcopy(collision_normal, ((S173E40 *)D_L00_00173E40)->vector); @@ -332,7 +336,7 @@ void release_moby_with_collision_check(float *release_position, fast_subtract_rotations(*(float *)(state + 0x50), MOBY(moby)->rot.y) * (frame_scale * smoothing)); } else - MOBY(moby)->state = 2; + MOBY(moby)->state = DECOY_THROWN_MOVEMENT; } /* From 1549c118d468b5d211094d4b2954701d1b4dc335 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:01:35 +0000 Subject: [PATCH 1420/1502] decomp: clarify names in smoke_trail_projectile_update domain_0_value_2 -> BURST_AND_REMOVE: The source assigns MOBY(moby)->state after collision_line reports contact. Retail 002edc34 loads 2 and 002edc38 stores it to 0x20(s3), the same byte loaded at 002eda28 and compared to 2 at 002eda34-002eda38. That branch enters 002edc54, calling cart_burst at 002edc6c then mark_moby_for_removal at 002edc74, exactly the existing local BURST_AND_REMOVE=2 case. domain_1_value_2 -> BURST_AND_REMOVE: The source assigns MOBY(moby)->state when fast_dec_timer(moby_vars+0x14) is nonzero. Retail 002edc3c-002edc50 calls the countdown helper, loads 2 at 002edc48 and stores it into 0x20(s3) at 002edc50. This is the identical state byte read at 002eda28; its value-2 branch reaches cart_burst and mark_moby_for_removal at 002edc6c/002edc74, proving reuse of local BURST_AND_REMOVE=2. --- src/overlays/shared/enemies/smoke_trail_projectile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/enemies/smoke_trail_projectile.c b/src/overlays/shared/enemies/smoke_trail_projectile.c index 3e067ff001..6e11719393 100644 --- a/src/overlays/shared/enemies/smoke_trail_projectile.c +++ b/src/overlays/shared/enemies/smoke_trail_projectile.c @@ -89,10 +89,10 @@ void smoke_trail_projectile_update(char *moby) { hit_descriptor.b18 = 0; record_moby_hit(*(void **)(collision_result + 0x18), &hit_descriptor); } - MOBY(moby)->state = 2; + MOBY(moby)->state = BURST_AND_REMOVE; } if (fast_dec_timer(moby_vars + 0x14) != 0) - MOBY(moby)->state = 2; + MOBY(moby)->state = BURST_AND_REMOVE; break; case BURST_AND_REMOVE: cart_burst(moby, &MOBY(moby)->pos, -1, 0.25f, 13.0f); From ef180bda80570aca692449f68ec73a9aaacf4127 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:01:35 +0000 Subject: [PATCH 1421/1502] decomp: clarify names in spawn_devastator_missile domain_0_value_0 -> DEVASTATOR_MISSILE_STATE_FLYING: Retail 0x002afcbc-0x002afccc allocates class 0x99 into s1; 0x002afcfc stores zero to that missile's state byte at +0x20. The following 0x002afd00-0x002afe58 initializes launch position, target, guidance yaw/pitch, speed, lifetime and turn timers before returning the launched missile. The authoritative same-class gold_devastator_missile_update consumes these fields to steer and advance the missile position, with collision, expiry and removal handling. Thus zero denotes the initialized flying missile state, rather than an idle hero state or control selector. --- src/overlays/shared/weapons/gold_devastator_missile.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/weapons/gold_devastator_missile.c b/src/overlays/shared/weapons/gold_devastator_missile.c index 14e6b2285e..49a5e5b1e8 100644 --- a/src/overlays/shared/weapons/gold_devastator_missile.c +++ b/src/overlays/shared/weapons/gold_devastator_missile.c @@ -414,6 +414,9 @@ unsigned char *spawn_devastator_missile(unsigned char *missile_source_moby, float initial_yaw, float initial_pitch) { + enum { + DEVASTATOR_MISSILE_STATE_FLYING = 0 + }; V_2afc70 collision_start; unsigned char *missile_moby; GoldDevastatorMissileVars *missile_data; @@ -430,7 +433,7 @@ unsigned char *spawn_devastator_missile(unsigned char *missile_source_moby, MOBY(missile_moby)->visible = 1; MOBY(missile_moby)->rot.z = initial_yaw; MOBY(missile_moby)->rot.y = initial_pitch; - MOBY(missile_moby)->state = 0; + MOBY(missile_moby)->state = DEVASTATOR_MISSILE_STATE_FLYING; missile_data->unk10 = missile_source_moby; qcopy(&MOBY(missile_moby)->pos, spawn_position); default_desired_speed = frame_time * 20.0f; From 506251dbe40b6c9331a29f495456d3d50bcfff51 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:01:36 +0000 Subject: [PATCH 1422/1502] decomp: clarify names in swingshot_versatarget_update domain_0_value_2 -> VERSATARGET_STATE_INACTIVE: The authoritative source maps MOBY(moby)->state to the switch state byte at moby+0x20. Retail 0x002e04f4 loads 2 and 0x002e0500 stores it to 0x20(s2), the same byte loaded at 0x002e0470 and dispatched at 0x002e0498 to the existing VERSATARGET_STATE_INACTIVE case. This path sets flags 0x41 and skips ACTIVE facing/effects until the inactive branch resets the state. domain_1_value_1 -> VERSATARGET_STATE_ACTIVE: Retail 0x002e0528 loads 1 and 0x002e0530 stores it at 0x20(s2) after color/setup calls. The same byte is loaded at 0x002e0470; comparison with 1 at 0x002e0474 enters 0x002e0534, matching the authoritative source's existing VERSATARGET_STATE_ACTIVE case with hero facing, particles and camera update. Thus this assignment uses the exact existing versatarget state domain. domain_2_value_0 -> VERSATARGET_STATE_INITIALIZE: Retail 0x002e06f4-0x002e0700 clears flags 0x41, resets pvars+0x30 to -1 and stores zero to 0x20(s2). This is the same moby state byte loaded at 0x002e0470 and dispatched for zero at 0x002e0488 to 0x002e04a8, the authoritative source's VERSATARGET_STATE_INITIALIZE case. The assignment returns the inactive object to the existing initialization path. --- src/overlays/shared/props/swingshot_versatarget.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/props/swingshot_versatarget.c b/src/overlays/shared/props/swingshot_versatarget.c index 44eec1bdc6..bf73e9ab70 100644 --- a/src/overlays/shared/props/swingshot_versatarget.c +++ b/src/overlays/shared/props/swingshot_versatarget.c @@ -53,12 +53,12 @@ void swingshot_versatarget_update(char *moby) { ((unsigned char *)linked_moby)[0x20] != 0xFE && ((unsigned char *)linked_moby)[0x20] != 0xFD)) { ((unsigned char *)moby)[0x30] = 0xFF; - MOBY(moby)->state = 2; + MOBY(moby)->state = VERSATARGET_STATE_INACTIVE; MOBY(moby)->flags |= 0x41; } else { set_moby_color(moby, 0xC0, 0xC0, 0xC0); func_L02_002FBB10_c(moby); - MOBY(moby)->state = 1; + MOBY(moby)->state = VERSATARGET_STATE_ACTIVE; } break; case VERSATARGET_STATE_ACTIVE: @@ -113,7 +113,7 @@ void swingshot_versatarget_update(char *moby) { ((unsigned char *)linked_moby)[0x20] == 0xFD))) { MOBY(moby)->flags &= 0xFFBE; *(int *)(moby_data + 0x30) = -1; - MOBY(moby)->state = 0; + MOBY(moby)->state = VERSATARGET_STATE_INITIALIZE; } break; } From d7d2b9996040959e7cdc6a94d0fe5d2219e01a3d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:03:42 +0000 Subject: [PATCH 1423/1502] decomp: clarify names in floating_platform_update domain_0_value_1 -> FLOATING_PLATFORM_UPDATE_MOTION: In the bound source snapshot, MOBY(moby)->state = 1 occurs in FLOATING_PLATFORM_INITIALIZE, while the same moby byte +0x20 selects the existing FLOATING_PLATFORM_UPDATE_MOTION = 1 case. Retail 002cddf8 loads unsigned byte 0x20(s1); 002cde10-002cde14 compares it with 1 and branches to 002cdeb4. Initialization loads 1 at 002cde5c and stores it to that identical byte at 002cde78. Original Ghidra likewise writes *(undefined1 *)(iVar5+0x20)=1 and then dispatches byte 1 to cosine bob, ring animation and position-Z updates (002cdeb4-002cdff0). Thus the assignment belongs to the existing local state domain and must reuse FLOATING_PLATFORM_UPDATE_MOTION. --- src/overlays/l04/mobys/floating_platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l04/mobys/floating_platform.c b/src/overlays/l04/mobys/floating_platform.c index fa046084bc..169248d2f1 100644 --- a/src/overlays/l04/mobys/floating_platform.c +++ b/src/overlays/l04/mobys/floating_platform.c @@ -41,7 +41,7 @@ void floating_platform_update(char *moby) { case FLOATING_PLATFORM_INITIALIZE: { int i; MOBY(moby)->anim_speed = random_float_between(0.5f, 0.8f); - MOBY(moby)->state = 1; + MOBY(moby)->state = FLOATING_PLATFORM_UPDATE_MOTION; *(float *)(platform_vars + 0x220) = MOBY(moby)->pos.z + 15.0f; ((unsigned char *)moby)[0x30] = 0xFF; *(short *)(platform_vars + 0x3E) = 0xD; From 08153e0e91b29611ab68ad9b876bb1fe94f827e1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:03:42 +0000 Subject: [PATCH 1424/1502] decomp: clarify names in energy_sphere_holder_update domain_0_value_2 -> ENERGY_SPHERE_HOLDER_COMPLETED: Retail 0x002f72a8 reads holder state at +0x20, the same selector as the existing local enum. At 0x002f72fc-0x002f7348 a set saved bit, subject to the level-10 exception, bypasses sphere allocation, sets command +0xbc to 1 and stores 2 to holder +0x20. The same state is reached when the linked child becomes negative and completion bits are set at 0x002f7490-0x002f7518; values other than 0 and 1 return without active processing. domain_1_value_1 -> ENERGY_SPHERE_HOLDER_HANDLE_HITS_AND_UPDATE_BEAM: Retail 0x002f7354 loads s1=1 and 0x002f73d4 stores it to holder +0x20 after linking the allocated child at pvars+0x40. This is the exact byte read at 0x002f72a8 and compared with 1 at 0x002f72b4-0x002f72b8 to enter hit handling at 0x002f7454 and beam updating at 0x002f751c. Therefore reuse the existing local enum member for this selector, rather than TRUE. domain_2_value_2 -> ENERGY_SPHERE_HOLDER_COMPLETED: Retail 0x002f7490-0x002f7498 loads the linked sphere from holder pvars+0x40 and tests its signed state at +0x20. The negative branch stores 2 to the holder state at 0x002f74a4, sets command to 1, and ORs the holder save-id bit into both the persistent table and energy_sphere_holder_completion_bits at 0x002f74e8-0x002f7518. This is the same completion state used by the saved-bit initialization bypass. --- src/overlays/shared/props/energy_sphere_holder.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/props/energy_sphere_holder.c b/src/overlays/shared/props/energy_sphere_holder.c index 0c74600154..4d2d1a01b6 100644 --- a/src/overlays/shared/props/energy_sphere_holder.c +++ b/src/overlays/shared/props/energy_sphere_holder.c @@ -68,6 +68,9 @@ void energy_sphere_holder_update(char *holder_moby) { ENERGY_SPHERE_HOLDER_INITIALIZE = 0, ENERGY_SPHERE_HOLDER_HANDLE_HITS_AND_UPDATE_BEAM = 1 }; + enum { + ENERGY_SPHERE_HOLDER_COMPLETED = 2 + }; char *holder_vars = ((char *)MOBY(holder_moby)->pvars); char *spawned_moby; unsigned char *visited_table; @@ -80,7 +83,7 @@ void energy_sphere_holder_update(char *holder_moby) { (current_level_index != 10 || (visited_table = (unsigned char *)((char *)visited52), (visited_table + ((unsigned char *)holder_moby)[0xB0]))[0xA0] == 0xFF)) { - MOBY(holder_moby)->state = 2; + MOBY(holder_moby)->state = ENERGY_SPHERE_HOLDER_COMPLETED; MOBY(holder_moby)->command = 1; break; } @@ -96,7 +99,7 @@ void energy_sphere_holder_update(char *holder_moby) { MOBY(spawned_moby)->rot.z = random_angle_radians(); MOBY(spawned_moby)->pos.z += 0.85f; *(char **)(holder_vars + 0x40) = spawned_moby; - MOBY(holder_moby)->state = 1; + MOBY(holder_moby)->state = ENERGY_SPHERE_HOLDER_HANDLE_HITS_AND_UPDATE_BEAM; initialize_energy_sphere_holder_vars(holder_moby); *(int *)(current_level_index * 256 + ((short)MOBY(holder_moby)->save_id >> 5) * 4 + (char *)D_0014C190_257218) &= ~(1 << (MOBY(holder_moby)->save_id & 0x1F)); @@ -116,7 +119,7 @@ void energy_sphere_holder_update(char *holder_moby) { } if ((*(char **)(holder_vars + 0x40))[0x20] < 0) { MOBY(holder_moby)->command = 1; - MOBY(holder_moby)->state = 2; + MOBY(holder_moby)->state = ENERGY_SPHERE_HOLDER_COMPLETED; *(int *)(current_level_index * 256 + ((short)MOBY(holder_moby)->save_id >> 5) * 4 + (char *)D_0014C190_257218) |= 1 << (MOBY(holder_moby)->save_id & 0x1F); energy_sphere_holder_completion_bits[(short)MOBY(holder_moby)->save_id >> 5] |= From 2bd4cbe43d112a8f88ededc38d5041865f29c5e9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:03:42 +0000 Subject: [PATCH 1425/1502] decomp: clarify names in crane_arm_update domain_0_value_1 -> CRANE_ARM_WAIT_DELAY: The bound source assigns MOBY(moby)->state = 1 in CRANE_ARM_INITIALIZE. Retail 0x002ec1f8 reads the selector from s0+0x20 and 0x002ec1fc dispatches value 1 to 0x002ec258, the existing CRANE_ARM_WAIT_DELAY branch. Initialization stores s1=1 to the identical field at 0x002ec24c and seeds its delay at 0x002ec450-0x002ec460, proving reuse of that state member. domain_1_value_2 -> CRANE_ARM_WAIT_ANIMATION_FLAG: After delay expiry and animation selection, the bound source assigns MOBY(moby)->state = 2. Retail 0x002ec394-0x002ec39c stores value 2 at s0+0x20 (also on default paths at 0x002ec2f8/0x002ec308). The same selector is loaded at 0x002ec1f8; value 2 dispatches at 0x002ec220 to 0x002ec3a0-0x002ec3a8, which waits on animation flags mask 2. This is the existing CRANE_ARM_WAIT_ANIMATION_FLAG state, not sequence 2. domain_2_value_1 -> CRANE_ARM_WAIT_DELAY: The bound source assigns MOBY(moby)->state = 1 after the CRANE_ARM_WAIT_ANIMATION_FLAG branch selects the subsequent animation. Retail 0x002ec444 loads 1 and 0x002ec44c stores it to s0+0x20, then 0x002ec450-0x002ec460 reseeds the delay byte at +0xBC. The selector read at 0x002ec1f8 dispatches value 1 at 0x002ec1fc to the existing CRANE_ARM_WAIT_DELAY branch at 0x002ec258, proving the same-domain canonical member. --- src/overlays/l12/mobys/crane_arm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l12/mobys/crane_arm.c b/src/overlays/l12/mobys/crane_arm.c index e3a64ad288..50561b84c0 100644 --- a/src/overlays/l12/mobys/crane_arm.c +++ b/src/overlays/l12/mobys/crane_arm.c @@ -40,7 +40,7 @@ void crane_arm_update(unsigned char *moby) { case CRANE_ARM_INITIALIZE: if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, 0); - MOBY(moby)->state = 1; + MOBY(moby)->state = CRANE_ARM_WAIT_DELAY; MOBY(moby)->command = random_integer_below(scale_game_frames(0xB4)); break; case CRANE_ARM_WAIT_DELAY: @@ -69,7 +69,7 @@ void crane_arm_update(unsigned char *moby) { blend_moby_animation(moby, 6, 0, 0); break; } - MOBY(moby)->state = 2; + MOBY(moby)->state = CRANE_ARM_WAIT_ANIMATION_FLAG; } break; case CRANE_ARM_WAIT_ANIMATION_FLAG: @@ -89,7 +89,7 @@ void crane_arm_update(unsigned char *moby) { blend_moby_animation(moby, 2, 0, 0); break; } - MOBY(moby)->state = 1; + MOBY(moby)->state = CRANE_ARM_WAIT_DELAY; MOBY(moby)->command = random_integer_below(scale_game_frames(0xB4)); } break; From 08a084cc95ace2d456e1b59e597c40798af84d8c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:03:42 +0000 Subject: [PATCH 1426/1502] decomp: clarify names in cutscene_trigger_update domain_0_value_1 -> CUTSCENE_TRIGGER_WAIT_FOR_TRIGGER: Retail 002fb654 stores s2=1 into moby+0x20 after configuration validation and frame scaling at 002fb614-002fb64c. The same byte is loaded at 002fb5d8 and value 1 dispatches to 002fb664, the existing CUTSCENE_TRIGGER_WAIT_FOR_TRIGGER case in the bound C, which tests saved flags and hero volume entry. domain_1_value_1 -> CUTSCENE_TRIGGER_WAIT_FOR_TRIGGER: Retail 002fb67c-002fb684 tests the saved cleared byte and stores s2=1 at moby+0x20 on the nonzero path. Original Ghidra shows the same state assignment. This preserves the state dispatched at 002fb5dc to the wait-for-trigger branch 002fb664, already named CUTSCENE_TRIGGER_WAIT_FOR_TRIGGER in the local enum. domain_2_value_1 -> CUTSCENE_TRIGGER_WAIT_FOR_TRIGGER: Retail 002fb6b0-002fb6c8 extracts the save-id bit and stores s2=1 at moby+0x20 when set, then exits. The switch reads this identical state byte at 002fb5d8 and dispatches 1 to 002fb664. The bound C already names that case CUTSCENE_TRIGGER_WAIT_FOR_TRIGGER; this assignment keeps that state without starting the camera. domain_3_value_2 -> CUTSCENE_TRIGGER_ACTIVE: Retail 002fb7b8 loads v1=2 and 002fb7c4 stores it at moby+0x20 after the camera/mount setup and cutscene_active=1 store at 002fb7c0. That byte dispatches value 2 to 002fb808, which maintains camera vectors or terminates the sequence. This is the existing local CUTSCENE_TRIGGER_ACTIVE member, independently corroborated by original Ghidra. domain_4_value_3 -> CUTSCENE_TRIGGER_WAIT_FOR_REARM: Retail 002fb830-002fb864 ends the mount, requests hero idle, clears cutscene_active, loads 3 and stores it at moby+0x20. Value 3 dispatches to 002fb880, where command byte +0xBC must equal 1 before state returns to 1. This matches the existing local CUTSCENE_TRIGGER_WAIT_FOR_REARM case, not a hero-state constant. --- src/overlays/shared/cutscenes/cutscene_trigger.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/cutscenes/cutscene_trigger.c b/src/overlays/shared/cutscenes/cutscene_trigger.c index acca839f0d..2502d8cea1 100644 --- a/src/overlays/shared/cutscenes/cutscene_trigger.c +++ b/src/overlays/shared/cutscenes/cutscene_trigger.c @@ -112,7 +112,7 @@ void cutscene_trigger_update(char *moby) { return; } trigger_vars->unk2C = scale_game_frames(trigger_vars->unk2C); - MOBY(moby)->state = 1; + MOBY(moby)->state = CUTSCENE_TRIGGER_WAIT_FOR_TRIGGER; { int ff = 0xFF; MOBY(moby)->draw_dist = ff; @@ -122,14 +122,14 @@ void cutscene_trigger_update(char *moby) { case CUTSCENE_TRIGGER_WAIT_FOR_TRIGGER: { char *hero_position; if (l01_save_state.cleared[(short)MOBY(moby)->save_id] != 0) { - MOBY(moby)->state = 1; + MOBY(moby)->state = CUTSCENE_TRIGGER_WAIT_FOR_TRIGGER; break; } if ((*(int *)((((short)MOBY(moby)->save_id >> 5) << 2) + (D_0015ED84 << 8) + (char *)D_0014C190_257218) >> (MOBY(moby)->save_id & 0x1F)) & 1) { - MOBY(moby)->state = 1; + MOBY(moby)->state = CUTSCENE_TRIGGER_WAIT_FOR_TRIGGER; break; } hero_position = (char *)&hero.motion.pos; @@ -151,7 +151,7 @@ void cutscene_trigger_update(char *moby) { jet_mount(&o->pos, &o->rot, 0, 0, 0); } cutscene_active = 1; - MOBY(moby)->state = 2; + MOBY(moby)->state = CUTSCENE_TRIGGER_ACTIVE; MOBY(moby)->command = 1; { int o = trigger_vars->unk24 << 7; @@ -170,7 +170,7 @@ void cutscene_trigger_update(char *moby) { } request_hero_idle_state_for_vehicle_mode(); cutscene_active = 0; - MOBY(moby)->state = 3; + MOBY(moby)->state = CUTSCENE_TRIGGER_WAIT_FOR_REARM; MOBY(moby)->command = 0; } else { set_camera_position(trigger_vars); From 74c5890d33386b65b0e2fe02bd162e9dc2c055ca Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:05:33 +0000 Subject: [PATCH 1427/1502] decomp: clarify names in configurable_particle_emitter_update domain_0_value_1 -> EFFECT_STATE_EMIT_BURST_PARTICLES: Source snapshot 5832b1eacc58e4b07703f7b837c6648b595894d2f7a69c18efd58cddc4f01a07 assigns MOBY(moby)->state in EFFECT_MODE_BURST_PARTICLES. Retail 0x002ea268 branches on pvars mode zero to 0x002ea288; 0x002ea28c stores 1 to object+0x20. That same byte is loaded at 0x002ea214 and dispatches at 0x002ea218 to burst helper calls 0x002ea348/0x002ea39c. This is the existing outer EFFECT_STATE_EMIT_BURST_PARTICLES member, not the separate mode enum. domain_1_value_2 -> EFFECT_STATE_UPDATE_WITH_GROUND_HEIGHT: Retail mode-one branch 0x002ea258 enters ground-height caching at 0x002ea290. Probe calls 0x002ea2e0/0x002ea30c store heights to path point+0x1c or pvars+0x88; 0x002ea318-0x002ea320 stores 2 to object+0x20. The same state byte loaded at 0x002ea214 selects 0x002ea3bc via 0x002ea23c, where 0x002ea3cc-0x002ea3dc or 0x002ea420-0x002ea430 passes cached height to FUN_L10_002eaa08. Reuse source's existing EFFECT_STATE_UPDATE_WITH_GROUND_HEIGHT outer-state member. domain_2_value_3 -> EFFECT_STATE_EMIT_TIMED_PARTICLES: Retail 0x002ea278 selects pvars mode 2 and 0x002ea324-0x002ea32c stores 3 to object+0x20, exactly the byte loaded by outer state dispatch at 0x002ea214. Its comparison at 0x002ea244 enters 0x002ea454 and calls FUN_L10_002ea7b0 at 0x002ea468/0x002ea4ac with emission position and short timer. Source names this branch EFFECT_STATE_EMIT_TIMED_PARTICLES; reuse that member for the assignment rather than the distinct EFFECT_MODE_TIMED_PARTICLES value. --- src/overlays/l10/mobys/configurable_particle_emitter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l10/mobys/configurable_particle_emitter.c b/src/overlays/l10/mobys/configurable_particle_emitter.c index ea5db4f33e..84e20ca28f 100644 --- a/src/overlays/l10/mobys/configurable_particle_emitter.c +++ b/src/overlays/l10/mobys/configurable_particle_emitter.c @@ -46,7 +46,7 @@ void configurable_particle_emitter_update(char *moby) { case EFFECT_STATE_INITIALIZE: switch (*(int *)effect_pvars) { case EFFECT_MODE_BURST_PARTICLES: - MOBY(moby)->state = 1; + MOBY(moby)->state = EFFECT_STATE_EMIT_BURST_PARTICLES; break; case EFFECT_MODE_CACHE_GROUND_HEIGHT: if (*(int *)(effect_pvars + 4) != -1) { @@ -66,10 +66,10 @@ void configurable_particle_emitter_update(char *moby) { } } else *(float *)(effect_pvars + 0x88) = probe_ground_height(moby + 0x10, 0, 0.5f); - MOBY(moby)->state = 2; + MOBY(moby)->state = EFFECT_STATE_UPDATE_WITH_GROUND_HEIGHT; break; case EFFECT_MODE_TIMED_PARTICLES: - MOBY(moby)->state = 3; + MOBY(moby)->state = EFFECT_STATE_EMIT_TIMED_PARTICLES; break; } break; From daa37097d6aff08763ddad8b4887b4eadcfe1e40 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:05:33 +0000 Subject: [PATCH 1428/1502] decomp: clarify names in helicopter_update domain_0_value_1 -> HELICOPTER_FOLLOW_PATH: Retail 0x002ebf0c loads the helicopter moby's state byte at s4+0x20; 0x002ebf14/0x002ebf18 compare it with 1 and dispatch to 0x002ebfd4. That branch computes neighboring path nodes, advances the current node at 0x002ec100, and moves the moby toward the next node at 0x002ec128-0x002ec158. Initialization selects/stores the path at 0x002ebf58-0x002ebf5c, copies the initial node to position at 0x002ebf7c-0x002ebf80, and stores 1 to the identical state byte at 0x002ebf90/0x002ebfbc. The authoritative C already names the consuming case HELICOPTER_FOLLOW_PATH = 1, proving canonical same-selector reuse for this assignment rather than any hero or boolean domain. --- src/overlays/l12/mobys/helicopter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l12/mobys/helicopter.c b/src/overlays/l12/mobys/helicopter.c index 8bdc927790..d907221a7d 100644 --- a/src/overlays/l12/mobys/helicopter.c +++ b/src/overlays/l12/mobys/helicopter.c @@ -171,7 +171,7 @@ void helicopter_update(char *moby) { moby_vars->unk30 = 1.4f; moby_vars->unk2B = 1; moby_vars->unk60 = initial_node_index; - MOBY(moby)->state = 1; + MOBY(moby)->state = HELICOPTER_FOLLOW_PATH; MOBY(moby)->draw_dist = 0xAA; MOBY(moby)->flags |= 0x1000; } From 2ae91030ac7ea7d409625143451a03a77e500c95 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:05:40 +0000 Subject: [PATCH 1429/1502] overlay: name add_hero_gravity_offset --- .../update_hero_motion_for_current_state.c | 70 +++++----- .../l02/hero/update_hero_state_motion.c | 86 ++++++------ .../update_hero_motion_for_current_state.c | 78 +++++------ .../hero/apply_hero_ground_material_effects.c | 8 +- .../l05/hero/update_hero_motion_by_state.c | 80 +++++------ .../update_hero_motion_for_current_state.c | 96 ++++++------- .../update_hero_motion_for_current_state.c | 82 +++++------ .../l11/hero/update_hero_motion_by_state.c | 78 +++++------ .../update_hero_motion_for_current_state.c | 86 ++++++------ .../l14/hero/update_hero_motion_by_state.c | 86 ++++++------ .../update_hero_motion_for_current_state.c | 104 +++++++------- .../hero/apply_hero_ground_material_effects.c | 8 +- .../update_hero_motion_for_current_state.c | 88 ++++++------ .../update_hero_motion_for_current_state.c | 104 +++++++------- .../update_hero_motion_for_current_state.c | 108 +++++++-------- src/overlays/shared/hero/hero_frame_update.c | 4 +- src/overlays/shared/hero/hero_switch_item.c | 8 +- .../shared/hero/hero_update_movement.c | 130 +++++++++--------- src/overlays/shared/hero/set_hero_animation.c | 4 +- ...ate_hero_vehicle_attachments_and_effects.c | 4 +- 20 files changed, 656 insertions(+), 656 deletions(-) diff --git a/src/overlays/l01/hero/update_hero_motion_for_current_state.c b/src/overlays/l01/hero/update_hero_motion_for_current_state.c index 04ec1872e8..72c6280bea 100644 --- a/src/overlays/l01/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l01/hero/update_hero_motion_for_current_state.c @@ -421,7 +421,7 @@ extern void stop_hero_motion_without_forward_support(float, float) __asm__("FUN_ extern void emit_filtered_entry_sparkles(int, int) __asm__("FUN_L00_00217368"); extern void launch_hero_wrench(void) __asm__("FUN_L00_00217658"); extern void set_hero_animation(int, int, float) __asm__("FUN_L00_002323b8"); -extern void FUN_L00_002334d0(float *, float *, float); +extern void add_hero_gravity_offset(float *, float *, float) __asm__("FUN_L00_002334d0"); extern void offset_hero_position_against_gravity(float *, float *, float) __asm__("FUN_L00_002336e8"); extern void add_hero_forward_offset(void *, void *, float) __asm__("FUN_L00_00233708"); @@ -592,10 +592,10 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && ((unsigned char *)item_available)[0x1C] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity.f, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); if (((Moby *)hero.ground_moby) != 0) { qcopy(hero.motion.pos.f, hero.ground_point.f); @@ -606,12 +606,12 @@ void update_hero_motion_for_current_state(void) { } else { clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0(hero.motion.velocity.f, + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } @@ -1137,11 +1137,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(hero.motion.velocity.f); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.displacement.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } if (anim != -1 && hero.moby->seq != 0x36) { set_hero_animation(anim, 0, frames); @@ -1170,7 +1170,7 @@ void update_hero_motion_for_current_state(void) { fast_cos_cf(&z, a, b); FUN_L00_00233b20(hero.motion.velocity.f, hero.motion.velocity.f, z); } else if (hero.state_timer > window_end) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.velocity.f, hero.rise_fall_gravity); if (FUN_L00_00233a78(hero.motion.velocity.f) < 0.0f) { hero.past_apex = 1.0f; @@ -1264,7 +1264,7 @@ void update_hero_motion_for_current_state(void) { fast_cos_cf(&z, v, acc); FUN_L00_00233b20(hero.motion.velocity.f, hero.motion.velocity.f, z); } else if (hero.state_timer > window_end) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 130.0f); if (FUN_L00_00233a78(hero.motion.velocity.f) < 0.0f) { hero.slam_descending = 1.0f; @@ -1335,10 +1335,10 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_WRENCH_COMBO: { @@ -1438,10 +1438,10 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); } break; @@ -1561,11 +1561,11 @@ void update_hero_motion_for_current_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity.f, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_ANIMATION_RECOVERY_WITH_JUMP_CANCEL: @@ -1686,11 +1686,11 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_VOICE_SLOT_CLEANUP_IDLE_EXIT: @@ -1842,7 +1842,7 @@ void update_hero_motion_for_current_state(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -1853,7 +1853,7 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); if (FUN_L00_00233a78(hero.motion.velocity.f) < -(frame_time * 50.0f)) { FUN_L00_00233b20(hero.motion.velocity.f, hero.motion.velocity.f, -(frame_time * 50.0f)); } @@ -1873,7 +1873,7 @@ void update_hero_motion_for_current_state(void) { hero.motion.velocity.f, hero.motion.velocity.f); } - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); if (FUN_L00_00233a78(hero.motion.velocity.f) < -(frame_time * 50.0f)) { FUN_L00_00233b20(hero.motion.velocity.f, hero.motion.velocity.f, -(frame_time * 50.0f)); } @@ -1917,7 +1917,7 @@ void update_hero_motion_for_current_state(void) { clip_hero_horizontal_velocity(1); if (fast) { FUN_L00_002338d0(hero.motion.velocity.f, hero.motion.velocity.f); - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, a * 0.72f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, a * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -1962,7 +1962,7 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); FUN_L00_002338d0(hero.motion.velocity.f, hero.motion.velocity.f); - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, v * 0.72f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, v * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { fast_cos_cf(&hero.smoothed_ground_z, hero.motion.pos.f[2], frame_time * 4.0f); } @@ -2166,7 +2166,7 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(hero.motion.velocity.f, hero.motion.velocity.f, len); - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, 0.004f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, 0.004f); } break; case HERO_STATE_APPROACH_TARGET_POSE: { float len; @@ -2217,11 +2217,11 @@ void update_hero_motion_for_current_state(void) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.displacement.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_BRAKE_AT_TARGET_POSITION: { @@ -2233,11 +2233,11 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.displacement.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_FIDGET: @@ -2255,18 +2255,18 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -2274,7 +2274,7 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { update_hero_airborne_planar_motion(); } - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 21.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2304,11 +2304,11 @@ void update_hero_motion_for_current_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_VEHICLE_MODE_3_HURT: { @@ -2324,10 +2324,10 @@ void update_hero_motion_for_current_state(void) { hero.motion.velocity.f); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity.f, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, 0.004f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, 0.004f); } } break; case HERO_STATE_CANCEL_ITEM_WITH_OPTIONAL_IDLE_ANIMATION: diff --git a/src/overlays/l02/hero/update_hero_state_motion.c b/src/overlays/l02/hero/update_hero_state_motion.c index ffe3e3f67a..8e347c628c 100644 --- a/src/overlays/l02/hero/update_hero_state_motion.c +++ b/src/overlays/l02/hero/update_hero_state_motion.c @@ -572,7 +572,7 @@ typedef union { extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void add_hero_up_offset(f32 *, f32 *, f32) __asm__("FUN_L00_00233810"); -extern void FUN_L00_002334d0(f32 *, f32 *, f32); +extern void add_hero_gravity_offset(f32 *, f32 *, f32) __asm__("FUN_L00_002334d0"); extern s32 coll1_222270(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); extern s32 rig_probe(void *, s32, f32, s32, f32) __asm__("FUN_L00_001f19a0"); extern s32 coll3_222270(void *, f32) __asm__("FUN_L00_001f3170"); @@ -601,7 +601,7 @@ s32 resolve_hero_position_collisions(s32 mode) { if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0) { add_hero_up_offset(&collision_probe_offset, &collision_probe_offset, 0.6f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &collision_probe_offset, &collision_probe_offset, -hero.capsule_bottom); } } else { @@ -746,7 +746,7 @@ extern void stop_hero_motion_without_forward_support(float, float) __asm__("FUN_ extern void emit_filtered_entry_sparkles(int, int) __asm__("FUN_L00_00217368"); extern void launch_hero_wrench(void) __asm__("FUN_L00_00217658"); extern void set_hero_animation(int, int, float) __asm__("FUN_L00_002323b8"); -extern void FUN_L00_002334d0(float *dst, float *src, float h); +extern void add_hero_gravity_offset(float *dst, float *src, float h) __asm__("FUN_L00_002334d0"); extern void offset_hero_position_against_gravity(float *, float *, float) __asm__("FUN_L00_002336e8"); extern void allocate_hero_voice_for_entry(int, int) __asm__("FUN_L00_00216de8"); @@ -917,10 +917,10 @@ void update_hero_state_motion(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && ((unsigned char *)item_available)[0x1C] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity.f, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); if (((Moby *)hero.ground_moby) != 0) { qcopy(hero.motion.pos.f, hero.ground_point.f); @@ -931,12 +931,12 @@ void update_hero_state_motion(void) { } else { clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0(hero.motion.velocity.f, + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } @@ -1001,11 +1001,11 @@ void update_hero_state_motion(void) { clear_u64_value(hero.motion.velocity.f); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.displacement.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } if (anim != -1 && hero.moby->seq != 0x36) { set_hero_animation(anim, 0, frames); @@ -1021,11 +1021,11 @@ void update_hero_state_motion(void) { clear_u64_value(hero.motion.velocity.f); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity.f, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } if (hero.grapple_target != 0) { hero.motion.move_yaw = fast_arc_tan(hero.grapple_target->pos.x - moby->pos.x, @@ -1192,13 +1192,13 @@ void update_hero_state_motion(void) { if (vector_distance_xy(hero.motion.pos.f, &hero.swing_target_moby->pos) < hero.unk9A0 * 1.57f || hero.ground_distance > 1.5f) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.displacement.f, frame_time_sq * 40.0f); if (hero.swing_entry_push != 0 && gravity_z(hero.motion.velocity.f) > 0.0f) { fast_vec_sub(motion_geometry_scratch[3], hero.motion.pos.f, &hero.swing_target_moby->pos); - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 57.0f); } } @@ -1337,7 +1337,7 @@ void update_hero_state_motion(void) { approach_value(&z, a, b); gravity_set_z(hero.motion.velocity.f, hero.motion.velocity.f, z); } else if (hero.state_timer > window_end) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.velocity.f, hero.rise_fall_gravity); if (gravity_z(hero.motion.velocity.f) < 0.0f) { hero.past_apex = 1.0f; @@ -1434,7 +1434,7 @@ void update_hero_state_motion(void) { approach_value(&z, v, acc); gravity_set_z(hero.motion.velocity.f, hero.motion.velocity.f, z); } else if (hero.state_timer > window_end) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 130.0f); if (gravity_z(hero.motion.velocity.f) < 0.0f) { hero.slam_descending = 1.0f; @@ -1504,10 +1504,10 @@ void update_hero_state_motion(void) { speed_step(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_WRENCH_COMBO: { @@ -1607,10 +1607,10 @@ void update_hero_state_motion(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); } break; @@ -1730,11 +1730,11 @@ void update_hero_state_motion(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity.f, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_ANIMATION_RECOVERY_WITH_JUMP_CANCEL: @@ -1792,10 +1792,10 @@ void update_hero_state_motion(void) { hero.air_frames.s = 0; } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity.f, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_RUN: @@ -1885,11 +1885,11 @@ void update_hero_state_motion(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_LEDGE_HANG_ENTRY: @@ -1968,7 +1968,7 @@ void update_hero_state_motion(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -2007,7 +2007,7 @@ void update_hero_state_motion(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); if (gravity_z(hero.motion.velocity.f) < -(frame_time * 50.0f)) { gravity_set_z(hero.motion.velocity.f, hero.motion.velocity.f, -(frame_time * 50.0f)); } @@ -2028,7 +2028,7 @@ void update_hero_state_motion(void) { hero.motion.velocity.f, hero.motion.velocity.f); } - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); if (gravity_z(hero.motion.velocity.f) < -(frame_time * 50.0f)) { gravity_set_z(hero.motion.velocity.f, hero.motion.velocity.f, -(frame_time * 50.0f)); } @@ -2072,7 +2072,7 @@ void update_hero_state_motion(void) { clip_hero_horizontal_velocity(1); if (fast) { gravity_flatten(hero.motion.velocity.f, hero.motion.velocity.f); - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, a * 0.72f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, a * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -2117,7 +2117,7 @@ void update_hero_state_motion(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); gravity_flatten(hero.motion.velocity.f, hero.motion.velocity.f); - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, v * 0.72f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, v * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { approach_value(&hero.smoothed_ground_z, hero.motion.pos.f[2], frame_time * 4.0f); } @@ -2294,7 +2294,7 @@ void update_hero_state_motion(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(hero.motion.velocity.f, hero.motion.velocity.f, len); - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, 0.004f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, 0.004f); } break; case HERO_STATE_APPROACH_TARGET_POSE: { float len; @@ -2345,11 +2345,11 @@ void update_hero_state_motion(void) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.displacement.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_BRAKE_AT_TARGET_POSITION: { @@ -2361,11 +2361,11 @@ void update_hero_state_motion(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.displacement.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_FIDGET: @@ -2394,18 +2394,18 @@ void update_hero_state_motion(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -2413,7 +2413,7 @@ void update_hero_state_motion(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 21.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2443,11 +2443,11 @@ void update_hero_state_motion(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_VEHICLE_MODE_3_HURT: { @@ -2463,10 +2463,10 @@ void update_hero_state_motion(void) { hero.motion.velocity.f); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity.f, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(hero.motion.velocity.f, hero.motion.velocity.f, 0.004f); + add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, 0.004f); } } break; case HERO_STATE_CANCEL_ITEM_WITH_OPTIONAL_IDLE_ANIMATION: diff --git a/src/overlays/l03/hero/update_hero_motion_for_current_state.c b/src/overlays/l03/hero/update_hero_motion_for_current_state.c index 63026109fe..3c637cbd8a 100644 --- a/src/overlays/l03/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l03/hero/update_hero_motion_for_current_state.c @@ -197,7 +197,7 @@ extern void adjust_hero_animation_speed_for_target_frame(f32, f32, f32, f32) __asm__("FUN_L00_00208f20"); extern void speed_step(f32, f32) __asm__("FUN_L00_00212088"); extern void reduce_and_apply_hero_planar_velocity_addend(f32) __asm__("FUN_L00_00216710"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern void clip_hero_horizontal_velocity(s32) __asm__("FUN_L01_00232978"); extern void correct_hero_airborne_wall_velocity(void) __asm__("FUN_L00_002121c0"); extern void spawn_hero_radial_particle_burst(void) __asm__("FUN_L00_00217450"); @@ -442,10 +442,10 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && D_0013D4DC[0] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); if (hero.ground_moby != NULL) { qcopy(&hero.motion.pos, &hero.ground_point); @@ -456,11 +456,11 @@ void update_hero_motion_for_current_state(void) { } else { clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -933,11 +933,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && MV(hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -955,11 +955,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (MV(hero.grapple_target) != NULL) { hero.motion.move_yaw = @@ -1130,13 +1130,13 @@ void update_hero_motion_for_current_state(void) { if (vector_distance_xy(&hero.motion.pos, &MV(hero.swing_target_moby)->u10.v10) < hero.unk9A0 * 1.57f || hero.ground_distance > 1.5f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 40.0f); if (hero.swing_entry_push != 0 && gravity_z(&hero.motion.velocity) > 0.0f) { fast_vec_sub(&motion_offset_or_position, &hero.motion.pos, &MV(hero.swing_target_moby)->u10.v10); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 57.0f); } } @@ -1250,7 +1250,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1335,7 +1335,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1397,10 +1397,10 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1494,10 +1494,10 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1611,11 +1611,11 @@ void update_hero_motion_for_current_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1726,11 +1726,11 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1966,7 +1966,7 @@ void update_hero_motion_for_current_state(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -2003,7 +2003,7 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2020,7 +2020,7 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2064,7 +2064,7 @@ void update_hero_motion_for_current_state(void) { clip_hero_horizontal_velocity(1); if (big) { gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -2110,7 +2110,7 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { approach_value(&hero.smoothed_ground_z, hero.motion.pos.f[2], frame_time * 4.0f); } @@ -2297,7 +2297,7 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, l); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); break; } case HERO_STATE_APPROACH_TARGET_POSE: { @@ -2348,11 +2348,11 @@ void update_hero_motion_for_current_state(void) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2365,11 +2365,11 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2387,18 +2387,18 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -2406,7 +2406,7 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2435,11 +2435,11 @@ void update_hero_motion_for_current_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2454,10 +2454,10 @@ void update_hero_motion_for_current_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } diff --git a/src/overlays/l05/hero/apply_hero_ground_material_effects.c b/src/overlays/l05/hero/apply_hero_ground_material_effects.c index 4cd5fc9607..4ed35313ee 100644 --- a/src/overlays/l05/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l05/hero/apply_hero_ground_material_effects.c @@ -157,7 +157,7 @@ void FUN_001f9a68_c(void *, void *, f32) __asm__("FUN_001f9a68"); void FUN_001f9bf8_c(void *, void *, f32) __asm__("FUN_001f9bf8"); void compute_rotated_vector_angles(void *, void *) __asm__("FUN_L00_00216078"); void transform_hero_polar_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_002335c8"); -void FUN_L00_002334d0(void *, void *, f32); +void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern CollisionHit HH __asm__("D_L05_00174240") NOT_SDA; #define HI(o) (*(s32 *)(D_L05_00174240 + (o))) @@ -262,7 +262,7 @@ void update_hero_ground_contact(void) { if (is_moby_in_class_range_500_to_540(HH.moby)) { hero.on_flagged_ground_moby = 1; if ((u32)(hero.state.control_mode - 0x15) < 2) { - FUN_L00_002334d0((u8 *)&HH.point, (u8 *)&HH.point, 1.0f); + add_hero_gravity_offset((u8 *)&HH.point, (u8 *)&HH.point, 1.0f); } } hit_moby_record = get_moby_target_info(HH.moby); @@ -384,7 +384,7 @@ typedef union { extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern s32 coll_sphere(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); extern s32 rig_probe(void *, s32, f32, s32, f32) __asm__("FUN_L00_001f19a0"); extern s32 FUN_L00_001f3170(void *, f32); @@ -417,7 +417,7 @@ s32 resolve_hero_position_collisions(s32 mode) { (unsigned)(hero.state.control_mode - 0x15) < 2) { add_hero_up_offset(&collision_query_offset, &collision_query_offset, 0.6f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &collision_query_offset, &collision_query_offset, -hero.capsule_bottom); } } else { diff --git a/src/overlays/l05/hero/update_hero_motion_by_state.c b/src/overlays/l05/hero/update_hero_motion_by_state.c index dd22ba40d4..81b7cfbd3b 100644 --- a/src/overlays/l05/hero/update_hero_motion_by_state.c +++ b/src/overlays/l05/hero/update_hero_motion_by_state.c @@ -136,7 +136,7 @@ extern void adjust_hero_animation_speed_for_target_frame(f32, f32, f32, f32) __asm__("FUN_L00_00208f20"); extern void speed_step(f32, f32) __asm__("FUN_L00_00212088"); extern void reduce_and_apply_hero_planar_velocity_addend(f32) __asm__("FUN_L00_00216710"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern void clip_hero_horizontal_velocity(s32) __asm__("FUN_L01_00232978"); extern void correct_hero_airborne_wall_velocity(void) __asm__("FUN_L00_002121c0"); extern void spawn_hero_radial_particle_burst(void) __asm__("FUN_L00_00217450"); @@ -398,10 +398,10 @@ void update_hero_motion_by_state(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && D_0013D4DC[0] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); if (hero.ground_moby != NULL) { qcopy(&hero.motion.pos, &hero.ground_point); @@ -412,11 +412,11 @@ void update_hero_motion_by_state(void) { } else { clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -1128,7 +1128,7 @@ void update_hero_motion_by_state(void) { approach_value(&len, 0.0f, frame_time_sq * 15.0f); set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, len); sp = frame_time_sq * 27.0f; - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.resolved_velocity_z, sp); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.resolved_velocity_z, sp); n = truncate_float_to_s32(predict_hero_trajectory_intercept_time(60.0f, sp, -1.0f)); k = 16; if (n != 0 && (f32)k - hero.anim_frame > 1.0f) { @@ -1205,11 +1205,11 @@ void update_hero_motion_by_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1228,11 +1228,11 @@ void update_hero_motion_by_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1400,13 +1400,13 @@ void update_hero_motion_by_state(void) { &((struct MobyView *)hero.swing_target_moby)->u10.v10) < hero.unk9A0 * 1.57f || hero.ground_distance > 1.5f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 40.0f); if (hero.swing_entry_push != 0 && gravity_z(&hero.motion.velocity) > 0.0f) { fast_vec_sub(&rotation_and_motion_scratch[3], &hero.motion.pos, &((struct MobyView *)hero.swing_target_moby)->u10.v10); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 57.0f); } } @@ -1529,7 +1529,7 @@ void update_hero_motion_by_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1621,7 +1621,7 @@ void update_hero_motion_by_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1683,10 +1683,10 @@ void update_hero_motion_by_state(void) { speed_step(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1783,10 +1783,10 @@ void update_hero_motion_by_state(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1894,11 +1894,11 @@ void update_hero_motion_by_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2009,11 +2009,11 @@ void update_hero_motion_by_state(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2565,7 +2565,7 @@ void update_hero_motion_by_state(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -2602,7 +2602,7 @@ void update_hero_motion_by_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2619,7 +2619,7 @@ void update_hero_motion_by_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2663,7 +2663,7 @@ void update_hero_motion_by_state(void) { clip_hero_horizontal_velocity(1); if (big) { gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -2708,7 +2708,7 @@ void update_hero_motion_by_state(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { approach_value(&hero.smoothed_ground_z, hero.motion.pos.f[2], frame_time * 4.0f); } @@ -2897,7 +2897,7 @@ void update_hero_motion_by_state(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, l); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); break; } case HERO_STATE_APPROACH_TARGET_POSE: { @@ -2948,11 +2948,11 @@ void update_hero_motion_by_state(void) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2965,11 +2965,11 @@ void update_hero_motion_by_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -3005,18 +3005,18 @@ void update_hero_motion_by_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -3024,7 +3024,7 @@ void update_hero_motion_by_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -3053,11 +3053,11 @@ void update_hero_motion_by_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3074,10 +3074,10 @@ void update_hero_motion_by_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } diff --git a/src/overlays/l06/hero/update_hero_motion_for_current_state.c b/src/overlays/l06/hero/update_hero_motion_for_current_state.c index fa4f9845bb..99caa17b0d 100644 --- a/src/overlays/l06/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l06/hero/update_hero_motion_for_current_state.c @@ -892,7 +892,7 @@ extern void adjust_hero_animation_speed_for_target_frame(f32, f32, f32, f32) __asm__("FUN_L00_00208f20"); extern void FUN_L00_00212088(f32, f32); extern void reduce_and_apply_hero_planar_velocity_addend(f32) __asm__("FUN_L00_00216710"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern void adjust_hero_velocity_from_collision_probes(s32) __asm__("FUN_L06_002291d0"); extern void correct_hero_airborne_wall_velocity(void) __asm__("FUN_L00_002121c0"); extern void spawn_hero_radial_particle_burst(void) __asm__("FUN_L00_00217450"); @@ -1144,10 +1144,10 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && D_0013D4DC[0] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); if (hero.ground_moby != NULL) { qcopy(&hero.motion.pos, &hero.ground_point); @@ -1158,11 +1158,11 @@ void update_hero_motion_for_current_state(void) { } else { adjust_hero_velocity_from_collision_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -1226,11 +1226,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1249,11 +1249,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1426,13 +1426,13 @@ void update_hero_motion_for_current_state(void) { &((struct MobyView *)hero.swing_target_moby)->u10.v10) < hero.unk9A0 * 1.57f || hero.ground_distance > 1.5f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 40.0f); if (hero.swing_entry_push != 0 && gravity_z(&hero.motion.velocity) > 0.0f) { FUN_001f9a28_c(&position_or_delta_scratch, &hero.motion.pos, &((struct MobyView *)hero.swing_target_moby)->u10.v10); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 57.0f); } } @@ -1552,7 +1552,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1638,7 +1638,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1704,10 +1704,10 @@ void update_hero_motion_for_current_state(void) { FUN_L00_00212088(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1804,10 +1804,10 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1918,11 +1918,11 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_velocity_from_collision_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2020,11 +2020,11 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2520,7 +2520,7 @@ void update_hero_motion_for_current_state(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = D_0015ED6C_c * 5.5f; FUN_L01_00234358(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -2557,7 +2557,7 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, D_0015ED6C_c * 0.0f); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(D_0015ED6C_c * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(D_0015ED6C_c * 50.0f)); } @@ -2574,7 +2574,7 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(D_0015ED6C_c * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(D_0015ED6C_c * 50.0f)); } @@ -2618,7 +2618,7 @@ void update_hero_motion_for_current_state(void) { adjust_hero_velocity_from_collision_probes(1); if (big) { gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -2665,7 +2665,7 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { approach_value(&hero.smoothed_ground_z, hero.motion.pos.f[2], D_0015ED6C_c * 4.0f); } @@ -2838,7 +2838,7 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, l); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); break; } case HERO_STATE_APPROACH_TARGET_POSE: { @@ -2890,11 +2890,11 @@ void update_hero_motion_for_current_state(void) { adjust_hero_velocity_from_collision_probes(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2907,11 +2907,11 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); adjust_hero_velocity_from_collision_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2936,11 +2936,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); adjust_hero_velocity_from_collision_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_1_ATTACK: { @@ -3014,14 +3014,14 @@ void update_hero_motion_for_current_state(void) { FUN_L00_00212088(frame_time_sq * 15.0f, frame_time_sq * 7.0f); set_planar_vel(99999.0f); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); break; } case HERO_STATE_VEHICLE_MODE_1_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = D_0015ED6C_c * 5.5f; FUN_L01_00234358(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_1_FALL: @@ -3029,7 +3029,7 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { update_hero_airborne_planar_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); if (hero.motion.velocity.f[2] < D_0015ED6C_c * -10.0f) { hero.motion.velocity.f[2] = D_0015ED6C_c * -10.0f; } @@ -3065,11 +3065,11 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_velocity_from_collision_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3084,10 +3084,10 @@ void update_hero_motion_for_current_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } @@ -3161,18 +3161,18 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); adjust_hero_velocity_from_collision_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = D_0015ED6C_c * 5.5f; FUN_L01_00234358(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -3180,7 +3180,7 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { update_hero_airborne_planar_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < D_0015ED6C_c * -15.0f) { hero.motion.velocity.f[2] = D_0015ED6C_c * -15.0f; } @@ -3210,11 +3210,11 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_velocity_from_collision_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3229,10 +3229,10 @@ void update_hero_motion_for_current_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } diff --git a/src/overlays/l08/hero/update_hero_motion_for_current_state.c b/src/overlays/l08/hero/update_hero_motion_for_current_state.c index 9fe2c85ab7..9c3c7702a6 100644 --- a/src/overlays/l08/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l08/hero/update_hero_motion_for_current_state.c @@ -264,7 +264,7 @@ extern void adjust_hero_animation_speed_for_target_frame(f32, f32, f32, f32) __asm__("FUN_L00_00208f20"); extern void speed_step(f32, f32) __asm__("FUN_L00_00212088"); extern void reduce_and_apply_hero_planar_velocity_addend(f32) __asm__("FUN_L00_00216710"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern void clip_hero_horizontal_velocity(s32) __asm__("FUN_L01_00232978"); extern void correct_hero_airborne_wall_velocity(void) __asm__("FUN_L00_002121c0"); extern void spawn_hero_radial_particle_burst(void) __asm__("FUN_L00_00217450"); @@ -511,10 +511,10 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && D_0013D4DC[0] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); if (hero.ground_moby != NULL) { qcopy(&hero.motion.pos, &hero.ground_point); @@ -525,11 +525,11 @@ void update_hero_motion_for_current_state(void) { } else { clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -1004,11 +1004,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && MV(hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1026,11 +1026,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (MV(hero.grapple_target) != NULL) { hero.motion.move_yaw = @@ -1198,13 +1198,13 @@ void update_hero_motion_for_current_state(void) { if (vector_distance_xy(&hero.motion.pos, &MV(hero.swing_target_moby)->u10.v10) < hero.unk9A0 * 1.57f || hero.ground_distance > 1.5f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 40.0f); if (hero.swing_entry_push != 0 && gravity_z(&hero.motion.velocity) > 0.0f) { fast_vec_sub(&movement_vector_scratch, &hero.motion.pos, &MV(hero.swing_target_moby)->u10.v10); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 57.0f); } } @@ -1318,7 +1318,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1404,7 +1404,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1466,10 +1466,10 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1563,10 +1563,10 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1680,11 +1680,11 @@ void update_hero_motion_for_current_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1742,10 +1742,10 @@ void update_hero_motion_for_current_state(void) { hero.air_frames.s = 0; } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1839,11 +1839,11 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2401,7 +2401,7 @@ void update_hero_motion_for_current_state(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -2438,7 +2438,7 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2455,7 +2455,7 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2499,7 +2499,7 @@ void update_hero_motion_for_current_state(void) { clip_hero_horizontal_velocity(1); if (big) { gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -2544,7 +2544,7 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { approach_value(&hero.smoothed_ground_z, hero.motion.pos.f[2], frame_time * 4.0f); } @@ -2732,7 +2732,7 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, l); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); break; } case HERO_STATE_APPROACH_TARGET_POSE: { @@ -2783,11 +2783,11 @@ void update_hero_motion_for_current_state(void) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2800,11 +2800,11 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2822,18 +2822,18 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -2841,7 +2841,7 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2870,11 +2870,11 @@ void update_hero_motion_for_current_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2891,10 +2891,10 @@ void update_hero_motion_for_current_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } diff --git a/src/overlays/l11/hero/update_hero_motion_by_state.c b/src/overlays/l11/hero/update_hero_motion_by_state.c index d8947d2b5b..9680137ae3 100644 --- a/src/overlays/l11/hero/update_hero_motion_by_state.c +++ b/src/overlays/l11/hero/update_hero_motion_by_state.c @@ -246,7 +246,7 @@ extern void adjust_hero_animation_speed_for_target_frame(f32, f32, f32, f32) __asm__("FUN_L00_00208f20"); extern void speed_step(f32, f32) __asm__("FUN_L00_00212088"); extern void reduce_and_apply_hero_planar_velocity_addend(f32) __asm__("FUN_L00_00216710"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern void clip_hero_horizontal_velocity(s32) __asm__("FUN_L01_00232978"); extern void correct_hero_airborne_wall_velocity(void) __asm__("FUN_L00_002121c0"); extern void spawn_hero_radial_particle_burst(void) __asm__("FUN_L00_00217450"); @@ -494,10 +494,10 @@ void update_hero_motion_by_state(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && D_0013D4DC[0] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); if (hero.ground_moby != NULL) { qcopy(&hero.motion.pos, &hero.ground_point); @@ -508,11 +508,11 @@ void update_hero_motion_by_state(void) { } else { clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -1011,11 +1011,11 @@ void update_hero_motion_by_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && MV(hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1033,11 +1033,11 @@ void update_hero_motion_by_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (MV(hero.grapple_target) != NULL) { hero.motion.move_yaw = @@ -1204,13 +1204,13 @@ void update_hero_motion_by_state(void) { if (vector_distance_xy(&hero.motion.pos, &MV(hero.swing_target_moby)->u10.v10) < hero.unk9A0 * 1.57f || hero.ground_distance > 1.5f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 40.0f); if (hero.swing_entry_push != 0 && gravity_z(&hero.motion.velocity) > 0.0f) { fast_vec_sub(&motion_vector_scratch, &hero.motion.pos, &MV(hero.swing_target_moby)->u10.v10); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 57.0f); } } @@ -1323,7 +1323,7 @@ void update_hero_motion_by_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1407,7 +1407,7 @@ void update_hero_motion_by_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1469,10 +1469,10 @@ void update_hero_motion_by_state(void) { speed_step(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1566,10 +1566,10 @@ void update_hero_motion_by_state(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1680,11 +1680,11 @@ void update_hero_motion_by_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1795,11 +1795,11 @@ void update_hero_motion_by_state(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1873,7 +1873,7 @@ void update_hero_motion_by_state(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -1910,7 +1910,7 @@ void update_hero_motion_by_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -1927,7 +1927,7 @@ void update_hero_motion_by_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -1971,7 +1971,7 @@ void update_hero_motion_by_state(void) { clip_hero_horizontal_velocity(1); if (big) { gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -2016,7 +2016,7 @@ void update_hero_motion_by_state(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { approach_value(&hero.smoothed_ground_z, hero.motion.pos.f[2], frame_time * 4.0f); } @@ -2204,7 +2204,7 @@ void update_hero_motion_by_state(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, l); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); break; } case HERO_STATE_APPROACH_TARGET_POSE: { @@ -2255,11 +2255,11 @@ void update_hero_motion_by_state(void) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2272,11 +2272,11 @@ void update_hero_motion_by_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2294,18 +2294,18 @@ void update_hero_motion_by_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -2313,7 +2313,7 @@ void update_hero_motion_by_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2342,11 +2342,11 @@ void update_hero_motion_by_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2361,10 +2361,10 @@ void update_hero_motion_by_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } diff --git a/src/overlays/l12/hero/update_hero_motion_for_current_state.c b/src/overlays/l12/hero/update_hero_motion_for_current_state.c index 2999025d66..903cf8848e 100644 --- a/src/overlays/l12/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l12/hero/update_hero_motion_for_current_state.c @@ -530,7 +530,7 @@ extern void adjust_hero_animation_speed_for_target_frame(f32, f32, f32, f32) __asm__("FUN_L00_00208f20"); extern void speed_step(f32, f32) __asm__("FUN_L00_00212088"); extern void reduce_and_apply_hero_planar_velocity_addend(f32) __asm__("FUN_L00_00216710"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern void clip_hero_horizontal_velocity(s32) __asm__("FUN_L01_00232978"); extern void correct_hero_airborne_wall_velocity(void) __asm__("FUN_L00_002121c0"); extern void spawn_hero_radial_particle_burst(void) __asm__("FUN_L00_00217450"); @@ -790,10 +790,10 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && D_0013D4DC[0] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); if (hero.ground_moby != NULL) { qcopy(&hero.motion.pos, &hero.ground_point); @@ -804,11 +804,11 @@ void update_hero_motion_for_current_state(void) { } else { clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -1307,11 +1307,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && MV(hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1329,11 +1329,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (MV(hero.grapple_target) != NULL) { hero.motion.move_yaw = @@ -1503,13 +1503,13 @@ void update_hero_motion_for_current_state(void) { if (vector_distance_xy(&hero.motion.pos, &MV(hero.swing_target_moby)->u10.v10) < hero.unk9A0 * 1.57f || hero.ground_distance > 1.5f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 40.0f); if (hero.swing_entry_push != 0 && gravity_z(&hero.motion.velocity) > 0.0f) { fast_vec_sub(&movement_vector_scratch, &hero.motion.pos, &MV(hero.swing_target_moby)->u10.v10); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 57.0f); } } @@ -1623,7 +1623,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1724,7 +1724,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1799,10 +1799,10 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -1902,10 +1902,10 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -2030,11 +2030,11 @@ void update_hero_motion_for_current_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2092,10 +2092,10 @@ void update_hero_motion_for_current_state(void) { hero.air_frames.s = 0; } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2189,11 +2189,11 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2235,11 +2235,11 @@ void update_hero_motion_for_current_state(void) { AN.f110 = s * m; } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); } else { hero.motion.velocity.f[2] = 0.0f; - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); } break; } @@ -2317,7 +2317,7 @@ void update_hero_motion_for_current_state(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; steer_hero_planar_velocity(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -2354,7 +2354,7 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2371,7 +2371,7 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2421,7 +2421,7 @@ void update_hero_motion_for_current_state(void) { clip_hero_horizontal_velocity(1); if (big) { gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -2466,7 +2466,7 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { approach_value(&hero.smoothed_ground_z, hero.motion.pos.f[2], frame_time * 4.0f); } @@ -2667,7 +2667,7 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, l); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); break; } case HERO_STATE_APPROACH_TARGET_POSE: { @@ -2718,11 +2718,11 @@ void update_hero_motion_for_current_state(void) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2735,11 +2735,11 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2757,18 +2757,18 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; steer_hero_planar_velocity(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -2776,7 +2776,7 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_movement(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2805,11 +2805,11 @@ void update_hero_motion_for_current_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2826,10 +2826,10 @@ void update_hero_motion_for_current_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } diff --git a/src/overlays/l14/hero/update_hero_motion_by_state.c b/src/overlays/l14/hero/update_hero_motion_by_state.c index 55a9ba9c09..3b86a28abd 100644 --- a/src/overlays/l14/hero/update_hero_motion_by_state.c +++ b/src/overlays/l14/hero/update_hero_motion_by_state.c @@ -404,7 +404,7 @@ extern void adjust_hero_animation_speed_for_target_frame(f32, f32, f32, f32) __asm__("FUN_L00_00208f20"); extern void speed_step(f32, f32) __asm__("FUN_L00_00212088"); extern void reduce_and_apply_hero_planar_velocity_addend(f32) __asm__("FUN_L00_00216710"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern void clip_hero_horizontal_velocity(s32) __asm__("FUN_L01_00232978"); extern void correct_hero_airborne_wall_velocity(void) __asm__("FUN_L00_002121c0"); extern void spawn_hero_radial_particle_burst(void) __asm__("FUN_L00_00217450"); @@ -656,10 +656,10 @@ void update_hero_motion_by_state(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && D_0013D4DC[0] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); if (hero.ground_moby != NULL) { qcopy(&hero.motion.pos, &hero.ground_point); @@ -670,11 +670,11 @@ void update_hero_motion_by_state(void) { } else { clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -734,11 +734,11 @@ void update_hero_motion_by_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && MV(hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -756,11 +756,11 @@ void update_hero_motion_by_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (MV(hero.grapple_target) != NULL) { hero.motion.move_yaw = @@ -922,13 +922,13 @@ void update_hero_motion_by_state(void) { if (vector_distance_xy(&hero.motion.pos, &MV(hero.swing_target_moby)->u10.v10) < hero.unk9A0 * 1.57f || hero.ground_distance > 1.5f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 40.0f); if (hero.swing_entry_push != 0 && gravity_z(&hero.motion.velocity) > 0.0f) { fast_vec_sub(&motion_vector_scratch, &hero.motion.pos, &MV(hero.swing_target_moby)->u10.v10); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 57.0f); } } @@ -1041,7 +1041,7 @@ void update_hero_motion_by_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1140,7 +1140,7 @@ void update_hero_motion_by_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1215,10 +1215,10 @@ void update_hero_motion_by_state(void) { speed_step(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -1318,10 +1318,10 @@ void update_hero_motion_by_state(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1437,11 +1437,11 @@ void update_hero_motion_by_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1498,10 +1498,10 @@ void update_hero_motion_by_state(void) { hero.air_frames.s = 0; } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1582,11 +1582,11 @@ void update_hero_motion_by_state(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1628,11 +1628,11 @@ void update_hero_motion_by_state(void) { AN.f110 = s * m; } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); } else { hero.motion.velocity.f[2] = 0.0f; - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); } break; } @@ -2117,7 +2117,7 @@ void update_hero_motion_by_state(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; steer_hero_planar_velocity(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -2154,7 +2154,7 @@ void update_hero_motion_by_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2171,7 +2171,7 @@ void update_hero_motion_by_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2221,7 +2221,7 @@ void update_hero_motion_by_state(void) { clip_hero_horizontal_velocity(1); if (big) { gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -2267,7 +2267,7 @@ void update_hero_motion_by_state(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { approach_value(&hero.smoothed_ground_z, hero.motion.pos.f[2], frame_time * 4.0f); } @@ -2442,7 +2442,7 @@ void update_hero_motion_by_state(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, l); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); break; } case HERO_STATE_APPROACH_TARGET_POSE: { @@ -2493,11 +2493,11 @@ void update_hero_motion_by_state(void) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2510,11 +2510,11 @@ void update_hero_motion_by_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2532,18 +2532,18 @@ void update_hero_motion_by_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; steer_hero_planar_velocity(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -2551,7 +2551,7 @@ void update_hero_motion_by_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_movement(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2580,11 +2580,11 @@ void update_hero_motion_by_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2601,10 +2601,10 @@ void update_hero_motion_by_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } diff --git a/src/overlays/l15/hero/update_hero_motion_for_current_state.c b/src/overlays/l15/hero/update_hero_motion_for_current_state.c index 99c57084d1..7ddbd74aef 100644 --- a/src/overlays/l15/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l15/hero/update_hero_motion_for_current_state.c @@ -458,7 +458,7 @@ extern void adjust_hero_animation_speed_for_target_frame(f32, f32, f32, f32) __asm__("FUN_L00_00208f20"); extern void speed_step(f32, f32) __asm__("FUN_L00_00212088"); extern void reduce_and_apply_hero_planar_velocity_addend(f32) __asm__("FUN_L00_00216710"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern void adjust_hero_planar_velocity_from_probes(s32) __asm__("FUN_L15_0020a328"); extern void correct_hero_airborne_wall_velocity(void) __asm__("FUN_L00_002121c0"); extern void spawn_hero_radial_particle_burst(void) __asm__("FUN_L00_00217450"); @@ -718,10 +718,10 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && D_0013D4DC[0] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); if (hero.ground_moby != NULL) { qcopy(&hero.motion.pos, &hero.ground_point); @@ -732,11 +732,11 @@ void update_hero_motion_for_current_state(void) { } else { adjust_hero_planar_velocity_from_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -1170,11 +1170,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1193,11 +1193,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1364,13 +1364,13 @@ void update_hero_motion_for_current_state(void) { &((struct MobyView *)hero.swing_target_moby)->u10.v10) < hero.unk9A0 * 1.57f || hero.ground_distance > 1.5f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 40.0f); if (hero.swing_entry_push != 0 && gravity_z(&hero.motion.velocity) > 0.0f) { fast_vec_sub(&motion_work_vector, &hero.motion.pos, &((struct MobyView *)hero.swing_target_moby)->u10.v10); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 57.0f); } } @@ -1487,7 +1487,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1579,7 +1579,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1641,10 +1641,10 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1741,10 +1741,10 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1858,11 +1858,11 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_planar_velocity_from_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1973,11 +1973,11 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2123,7 +2123,7 @@ void update_hero_motion_for_current_state(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -2160,7 +2160,7 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2177,7 +2177,7 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2221,7 +2221,7 @@ void update_hero_motion_for_current_state(void) { adjust_hero_planar_velocity_from_probes(1); if (big) { gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -2266,7 +2266,7 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { approach_value(&hero.smoothed_ground_z, hero.motion.pos.f[2], frame_time * 4.0f); } @@ -2455,7 +2455,7 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, l); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); break; } case HERO_STATE_APPROACH_TARGET_POSE: { @@ -2506,11 +2506,11 @@ void update_hero_motion_for_current_state(void) { adjust_hero_planar_velocity_from_probes(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2523,11 +2523,11 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); adjust_hero_planar_velocity_from_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2557,11 +2557,11 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); adjust_hero_planar_velocity_from_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_2_REPEATABLE_SQUARE_ACTION: @@ -2665,10 +2665,10 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_planar_velocity_from_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -2689,11 +2689,11 @@ void update_hero_motion_for_current_state(void) { } } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_WAIT_FOR_CIRCLE_RELEASE_AND_ANIMATION: { @@ -2725,11 +2725,11 @@ void update_hero_motion_for_current_state(void) { } } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2749,7 +2749,7 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); if (hero.motion.velocity.f[2] < frame_time * -10.0f) { hero.motion.velocity.f[2] = frame_time * -10.0f; } @@ -2817,11 +2817,11 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_planar_velocity_from_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2836,10 +2836,10 @@ void update_hero_motion_for_current_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } @@ -2854,18 +2854,18 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); adjust_hero_planar_velocity_from_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -2873,7 +2873,7 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2902,11 +2902,11 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_planar_velocity_from_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2921,10 +2921,10 @@ void update_hero_motion_for_current_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } diff --git a/src/overlays/l16/hero/apply_hero_ground_material_effects.c b/src/overlays/l16/hero/apply_hero_ground_material_effects.c index 10ebf16442..bf508491c9 100644 --- a/src/overlays/l16/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l16/hero/apply_hero_ground_material_effects.c @@ -187,7 +187,7 @@ void sceVu0Normalize(void *, void *) __asm__("FUN_00125180"); f32 compute_gravity_relative_vector_inclination(void *) __asm__("FUN_L00_00233d30"); void compute_rotated_vector_angles(void *, void *) __asm__("FUN_L00_00216078"); void transform_hero_polar_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_002335c8"); -void FUN_L00_002334d0(void *, void *, f32); +void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern CollisionHit HH __asm__("D_L16_00174240") NOT_SDA; #define HI(o) (*(s32 *)(D_L16_00174240 + (o))) @@ -278,7 +278,7 @@ void update_hero_ground_contact(void) { if (is_moby_in_class_range_500_to_540(HH.moby)) { hero.on_flagged_ground_moby = 1; if ((u32)(hero.state.control_mode - 0x15) < 2) { - FUN_L00_002334d0((u8 *)&HH.point, (u8 *)&HH.point, 1.0f); + add_hero_gravity_offset((u8 *)&HH.point, (u8 *)&HH.point, 1.0f); } } hit_moby_record = get_moby_target_info(HH.moby); @@ -401,7 +401,7 @@ typedef union { extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void transform_hero_local_offset_to_world(void *, f32, f32, f32) __asm__("FUN_L00_00233660"); extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern s32 coll1_2133a8(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); extern s32 rig_probe(void *, s32, f32, s32, f32) __asm__("FUN_L00_001f19a0"); extern s32 FUN_L00_001f3170(void *, f32); @@ -435,7 +435,7 @@ s32 resolve_hero_position_collisions(s32 mode) { (unsigned)(hero.state.control_mode - 0x15) < 2) { add_hero_up_offset(&collision_position_offset, &collision_position_offset, 0.6f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &collision_position_offset, &collision_position_offset, -hero.capsule_bottom); } } else { diff --git a/src/overlays/l16/hero/update_hero_motion_for_current_state.c b/src/overlays/l16/hero/update_hero_motion_for_current_state.c index e3bc627d74..c173bd6079 100644 --- a/src/overlays/l16/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l16/hero/update_hero_motion_for_current_state.c @@ -143,7 +143,7 @@ extern void adjust_hero_animation_speed_for_target_frame(f32, f32, f32, f32) __asm__("FUN_L00_00208f20"); extern void speed_step(f32, f32) __asm__("FUN_L00_00212088"); extern void reduce_and_apply_hero_planar_velocity_addend(f32) __asm__("FUN_L00_00216710"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern void clip_hero_horizontal_velocity(s32) __asm__("FUN_L01_00232978"); extern void correct_hero_airborne_wall_velocity(void) __asm__("FUN_L00_002121c0"); extern void spawn_hero_radial_particle_burst(void) __asm__("FUN_L00_00217450"); @@ -401,10 +401,10 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && D_0013D4DC[0] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); if (hero.ground_moby != NULL) { qcopy(&hero.motion.pos, &hero.ground_point); @@ -415,11 +415,11 @@ void update_hero_motion_for_current_state(void) { } else { clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -1024,10 +1024,10 @@ void update_hero_motion_for_current_state(void) { if (hero.air_frames.s != 0) { gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); hero.board_vertical_speed = hero.board_vertical_speed - hero.board_gravity; - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, -hero.board_vertical_speed); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 20.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 20.0f); } break; } @@ -1283,7 +1283,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&len, 0.0f, frame_time_sq * 15.0f); set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, len); sp = frame_time_sq * 27.0f; - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.resolved_velocity_z, sp); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.resolved_velocity_z, sp); n = truncate_float_to_s32(predict_hero_trajectory_intercept_time(60.0f, sp, -1.0f)); k = 16; if (n != 0 && (f32)k - hero.anim_frame > 1.0f) { @@ -1336,11 +1336,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1359,11 +1359,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1524,13 +1524,13 @@ void update_hero_motion_for_current_state(void) { &((struct MobyView *)hero.swing_target_moby)->u10.v10) < hero.unk9A0 * 1.57f || hero.ground_distance > 1.5f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 40.0f); if (hero.swing_entry_push != 0 && gravity_z(&hero.motion.velocity) > 0.0f) { fast_vec_sub(&matrix_vector_workspace[3], &hero.motion.pos, &((struct MobyView *)hero.swing_target_moby)->u10.v10); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 57.0f); } } @@ -1650,7 +1650,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1736,7 +1736,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1798,10 +1798,10 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1898,10 +1898,10 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -2005,11 +2005,11 @@ void update_hero_motion_for_current_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2065,10 +2065,10 @@ void update_hero_motion_for_current_state(void) { hero.air_frames.s = 0; } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2162,11 +2162,11 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2701,7 +2701,7 @@ void update_hero_motion_for_current_state(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -2738,7 +2738,7 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2755,7 +2755,7 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2799,7 +2799,7 @@ void update_hero_motion_for_current_state(void) { clip_hero_horizontal_velocity(1); if (big) { gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -2844,7 +2844,7 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { approach_value(&hero.smoothed_ground_z, hero.motion.pos.f[2], frame_time * 4.0f); } @@ -3029,7 +3029,7 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, l); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); break; } case HERO_STATE_APPROACH_TARGET_POSE: { @@ -3080,11 +3080,11 @@ void update_hero_motion_for_current_state(void) { clip_hero_horizontal_velocity(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3097,11 +3097,11 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -3119,18 +3119,18 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -3138,7 +3138,7 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -3167,11 +3167,11 @@ void update_hero_motion_for_current_state(void) { } clip_hero_horizontal_velocity(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3186,10 +3186,10 @@ void update_hero_motion_for_current_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } diff --git a/src/overlays/l17/hero/update_hero_motion_for_current_state.c b/src/overlays/l17/hero/update_hero_motion_for_current_state.c index ab3a24e530..be7f1bfccb 100644 --- a/src/overlays/l17/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l17/hero/update_hero_motion_for_current_state.c @@ -138,7 +138,7 @@ extern void adjust_hero_animation_speed_for_target_frame(f32, f32, f32, f32) __asm__("FUN_L00_00208f20"); extern void speed_step(f32, f32) __asm__("FUN_L00_00212088"); extern void reduce_and_apply_hero_planar_velocity_addend(f32) __asm__("FUN_L00_00216710"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern void adjust_hero_velocity_from_collision_probes(s32) __asm__("FUN_L06_002291d0"); extern void correct_hero_airborne_wall_velocity(void) __asm__("FUN_L00_002121c0"); extern void spawn_hero_radial_particle_burst(void) __asm__("FUN_L00_00217450"); @@ -395,10 +395,10 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && D_0013D4DC[0] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); if (hero.ground_moby != NULL) { qcopy(&hero.motion.pos, &hero.ground_point); @@ -409,11 +409,11 @@ void update_hero_motion_for_current_state(void) { } else { adjust_hero_velocity_from_collision_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -899,11 +899,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -922,11 +922,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1083,13 +1083,13 @@ void update_hero_motion_for_current_state(void) { &((struct MobyView *)hero.swing_target_moby)->u10.v10) < hero.unk9A0 * 1.57f || hero.ground_distance > 1.5f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 40.0f); if (hero.swing_entry_push != 0 && gravity_z(&hero.motion.velocity) > 0.0f) { fast_vec_sub(&temporary_vector, &hero.motion.pos, &((struct MobyView *)hero.swing_target_moby)->u10.v10); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 57.0f); } } @@ -1206,7 +1206,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1308,7 +1308,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1383,10 +1383,10 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -1489,10 +1489,10 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1607,11 +1607,11 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_velocity_from_collision_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1666,10 +1666,10 @@ void update_hero_motion_for_current_state(void) { hero.air_frames.s = 0; } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1763,11 +1763,11 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1809,11 +1809,11 @@ void update_hero_motion_for_current_state(void) { AN.f110 = s * m; } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); } else { hero.motion.velocity.f[2] = 0.0f; - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); } break; } @@ -2426,7 +2426,7 @@ void update_hero_motion_for_current_state(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; steer_hero_planar_velocity(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -2463,7 +2463,7 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2480,7 +2480,7 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2530,7 +2530,7 @@ void update_hero_motion_for_current_state(void) { adjust_hero_velocity_from_collision_probes(1); if (big) { gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -2575,7 +2575,7 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { approach_value(&hero.smoothed_ground_z, hero.motion.pos.f[2], frame_time * 4.0f); } @@ -2780,7 +2780,7 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, l); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); break; } case HERO_STATE_APPROACH_TARGET_POSE: { @@ -2829,11 +2829,11 @@ void update_hero_motion_for_current_state(void) { adjust_hero_velocity_from_collision_probes(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2846,11 +2846,11 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); adjust_hero_velocity_from_collision_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2888,11 +2888,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); adjust_hero_velocity_from_collision_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_1_ATTACK: { @@ -2958,14 +2958,14 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 15.0f, frame_time_sq * 7.0f); set_planar_vel(99999.0f); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); break; } case HERO_STATE_VEHICLE_MODE_1_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; steer_hero_planar_velocity(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_1_FALL: @@ -2973,7 +2973,7 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_move_state_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); if (hero.motion.velocity.f[2] < frame_time * -10.0f) { hero.motion.velocity.f[2] = frame_time * -10.0f; } @@ -3005,11 +3005,11 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_velocity_from_collision_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3024,10 +3024,10 @@ void update_hero_motion_for_current_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } @@ -3098,18 +3098,18 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); adjust_hero_velocity_from_collision_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; steer_hero_planar_velocity(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -3117,7 +3117,7 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_move_state_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -3146,11 +3146,11 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_velocity_from_collision_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3165,10 +3165,10 @@ void update_hero_motion_for_current_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } diff --git a/src/overlays/l18/hero/update_hero_motion_for_current_state.c b/src/overlays/l18/hero/update_hero_motion_for_current_state.c index 5f7ee34e8b..731178543e 100644 --- a/src/overlays/l18/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l18/hero/update_hero_motion_for_current_state.c @@ -138,7 +138,7 @@ extern void adjust_hero_animation_speed_for_target_frame(f32, f32, f32, f32) __asm__("FUN_L00_00208f20"); extern void speed_step(f32, f32) __asm__("FUN_L00_00212088"); extern void reduce_and_apply_hero_planar_velocity_addend(f32) __asm__("FUN_L00_00216710"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern void adjust_hero_planar_velocity_from_probes(s32) __asm__("FUN_L15_0020a328"); extern void correct_hero_airborne_wall_velocity(void) __asm__("FUN_L00_002121c0"); extern void spawn_hero_radial_particle_burst(void) __asm__("FUN_L00_00217450"); @@ -392,10 +392,10 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && D_0013D4DC[0] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); if (hero.ground_moby != NULL) { qcopy(&hero.motion.pos, &hero.ground_point); @@ -406,11 +406,11 @@ void update_hero_motion_for_current_state(void) { } else { adjust_hero_planar_velocity_from_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -872,11 +872,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -895,11 +895,11 @@ void update_hero_motion_for_current_state(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1076,13 +1076,13 @@ void update_hero_motion_for_current_state(void) { &((struct MobyView *)hero.swing_target_moby)->u10.v10) < hero.unk9A0 * 1.57f || hero.ground_distance > 1.5f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 40.0f); if (hero.swing_entry_push != 0 && gravity_z(&hero.motion.velocity) > 0.0f) { fast_vec_sub(&position_or_displacement_scratch, &hero.motion.pos, &((struct MobyView *)hero.swing_target_moby)->u10.v10); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 57.0f); } } @@ -1207,7 +1207,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1306,7 +1306,7 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1368,10 +1368,10 @@ void update_hero_motion_for_current_state(void) { speed_step(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1468,10 +1468,10 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1585,11 +1585,11 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_planar_velocity_from_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1647,10 +1647,10 @@ void update_hero_motion_for_current_state(void) { hero.air_frames.s = 0; } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1744,11 +1744,11 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2313,7 +2313,7 @@ void update_hero_motion_for_current_state(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -2350,7 +2350,7 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2367,7 +2367,7 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2411,7 +2411,7 @@ void update_hero_motion_for_current_state(void) { adjust_hero_planar_velocity_from_probes(1); if (big) { gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -2456,7 +2456,7 @@ void update_hero_motion_for_current_state(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { approach_value(&hero.smoothed_ground_z, hero.motion.pos.f[2], frame_time * 4.0f); } @@ -2650,7 +2650,7 @@ void update_hero_motion_for_current_state(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, l); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); break; } case HERO_STATE_APPROACH_TARGET_POSE: { @@ -2702,11 +2702,11 @@ void update_hero_motion_for_current_state(void) { adjust_hero_planar_velocity_from_probes(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2720,11 +2720,11 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); adjust_hero_planar_velocity_from_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2754,11 +2754,11 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); adjust_hero_planar_velocity_from_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_2_REPEATABLE_SQUARE_ACTION: @@ -2862,10 +2862,10 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_planar_velocity_from_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -2887,11 +2887,11 @@ void update_hero_motion_for_current_state(void) { } } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_WAIT_FOR_CIRCLE_RELEASE_AND_ANIMATION: { @@ -2925,11 +2925,11 @@ void update_hero_motion_for_current_state(void) { } } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2949,7 +2949,7 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); if (hero.motion.velocity.f[2] < frame_time * -10.0f) { hero.motion.velocity.f[2] = frame_time * -10.0f; } @@ -3017,11 +3017,11 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_planar_velocity_from_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3036,10 +3036,10 @@ void update_hero_motion_for_current_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } @@ -3054,18 +3054,18 @@ void update_hero_motion_for_current_state(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); adjust_hero_planar_velocity_from_probes(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; air_accel(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -3073,7 +3073,7 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -3102,11 +3102,11 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_planar_velocity_from_probes(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3121,10 +3121,10 @@ void update_hero_motion_for_current_state(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index 258ba15878..d07c4c2e12 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -1342,7 +1342,7 @@ typedef union { extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern s32 coll_sphere(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); extern s32 coll3_233940(void *, f32) __asm__("FUN_L00_001f3170"); extern u128_233940 D_L01_001742F0[] NOT_SDA; @@ -1370,7 +1370,7 @@ s32 resolve_hero_position_with_collision_queries(s32 mode) { if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0) { add_hero_up_offset(&collision_query_offset, &collision_query_offset, 0.6f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &collision_query_offset, &collision_query_offset, -hero.capsule_bottom); } } else { diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 557bb158c5..07be762039 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -3653,7 +3653,7 @@ typedef union { extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern s32 coll_sphere(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); extern s32 rig_probe(void *, s32, f32, s32, f32) __asm__("FUN_L00_001f19a0"); extern s32 FUN_L00_001f3170(void *, f32); @@ -3684,7 +3684,7 @@ s32 resolve_hero_current_position_collisions(s32 mode) { if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0) { add_hero_up_offset(&collision_probe_offset, &collision_probe_offset, 0.6f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &collision_probe_offset, &collision_probe_offset, -hero.capsule_bottom); } } else { @@ -4285,9 +4285,9 @@ void hero_integrate_velocity(void) { } if (hero.state_timer < hero.takeoff_frame) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, 0.0f); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 48.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 48.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.jump_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.jump_gravity); z = gravity_z(&hero.motion.velocity); movement_gravity_axis_velocity = gravity_z(&hero.motion.resolved_velocity); floor = movement_gravity_axis_velocity - 0.1f; diff --git a/src/overlays/shared/hero/hero_update_movement.c b/src/overlays/shared/hero/hero_update_movement.c index 00754231c5..cbd017f83b 100644 --- a/src/overlays/shared/hero/hero_update_movement.c +++ b/src/overlays/shared/hero/hero_update_movement.c @@ -96,7 +96,7 @@ extern void adjust_hero_animation_speed_for_target_frame(f32, f32, f32, f32) __asm__("FUN_L00_00208f20"); extern void speed_step(f32, f32) __asm__("FUN_L00_00212088"); extern void reduce_and_apply_hero_planar_velocity_addend(f32) __asm__("FUN_L00_00216710"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern void clip_hero_velocity_against_probed_surfaces(s32) __asm__("FUN_L00_00212318"); extern void correct_hero_airborne_wall_velocity(void) __asm__("FUN_L00_002121c0"); extern void spawn_hero_radial_particle_burst(void) __asm__("FUN_L00_00217450"); @@ -367,10 +367,10 @@ void hero_update_movement(void) { reduce_and_apply_hero_planar_velocity_addend(speed); if (hero.on_magnet_ground != 0 && D_0013D4DC[0] != 0) { if (hero.ground_distance > 0.2f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); if (hero.ground_moby != NULL) { qcopy(&hero.motion.pos, &hero.ground_point); @@ -381,11 +381,11 @@ void hero_update_movement(void) { } else { clip_hero_velocity_against_probed_surfaces(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -891,11 +891,11 @@ void hero_update_movement(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -914,11 +914,11 @@ void hero_update_movement(void) { clear_u64_value(&hero.motion.velocity); reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1091,13 +1091,13 @@ void hero_update_movement(void) { &((struct MobyView *)hero.swing_target_moby)->u10.v10) < hero.unk9A0 * 1.57f || hero.ground_distance > 1.5f) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 40.0f); if (hero.swing_entry_push != 0 && gravity_z(&hero.motion.velocity) > 0.0f) { fast_vec_sub(&movement_vector_scratch, &hero.motion.pos, &((struct MobyView *)hero.swing_target_moby)->u10.v10); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 57.0f); } } @@ -1217,7 +1217,7 @@ void hero_update_movement(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (fall_start_frame < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1326,7 +1326,7 @@ void hero_update_movement(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (fall_start_frame < hero.state_timer) { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1401,10 +1401,10 @@ void hero_update_movement(void) { speed_step(frame_time_sq * 37.0f, frame_time_sq * 28.0f); set_planar_vel(99999.0f); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } } @@ -1507,10 +1507,10 @@ void hero_update_movement(void) { set_planar_vel(99999.0f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1633,11 +1633,11 @@ void hero_update_movement(void) { } clip_hero_velocity_against_probed_surfaces(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1695,10 +1695,10 @@ void hero_update_movement(void) { hero.air_frames.s = 0; } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1792,11 +1792,11 @@ void hero_update_movement(void) { stop_hero_motion_without_forward_support(5.0f, 0.2f); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1838,11 +1838,11 @@ void hero_update_movement(void) { hero_eases[1].rot_target.f[0] = s * m; } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); } else { hero.motion.velocity.f[2] = 0.0f; - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); } break; } @@ -2501,7 +2501,7 @@ void hero_update_movement(void) { hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; steer_hero_planar_velocity(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_FALL: @@ -2538,7 +2538,7 @@ void hero_update_movement(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2555,7 +2555,7 @@ void hero_update_movement(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2605,7 +2605,7 @@ void hero_update_movement(void) { clip_hero_velocity_against_probed_surfaces(1); if (big) { gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); hero.ground_spring_velocity = hero.motion.velocity.f[2]; } else { vendor_spring(&hero.motion.pos.f[2], @@ -2650,7 +2650,7 @@ void hero_update_movement(void) { set_planar_vel(99999.0f); adjust_hero_pose_targets_from_motion(); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); if (hero.motion.pos.f[2] < hero.smoothed_ground_z) { approach_value(&hero.smoothed_ground_z, hero.motion.pos.f[2], frame_time * 4.0f); } @@ -2861,7 +2861,7 @@ void hero_update_movement(void) { stop_hero_motion_without_forward_support(3.7f, 0.0f); } set_vector_length_xy(&hero.motion.velocity, &hero.motion.velocity, l); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); break; } case HERO_STATE_APPROACH_TARGET_POSE: { @@ -2912,11 +2912,11 @@ void hero_update_movement(void) { clip_hero_velocity_against_probed_surfaces(1); } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2929,11 +2929,11 @@ void hero_update_movement(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.0f); clip_hero_velocity_against_probed_surfaces(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2971,11 +2971,11 @@ void hero_update_movement(void) { clear_u64_value(&hero.motion.velocity); clip_hero_velocity_against_probed_surfaces(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_1_ATTACK: { @@ -3051,14 +3051,14 @@ void hero_update_movement(void) { speed_step(frame_time_sq * 15.0f, frame_time_sq * 7.0f); set_planar_vel(99999.0f); gravity_flatten(&hero.motion.velocity, &hero.motion.velocity); - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, sp * 0.72f); break; } case HERO_STATE_VEHICLE_MODE_1_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; steer_hero_planar_velocity(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_1_FALL: @@ -3066,7 +3066,7 @@ void hero_update_movement(void) { if (hero.move_lock_timer == 0) { hero_move_state_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); if (hero.motion.velocity.f[2] < frame_time * -10.0f) { hero.motion.velocity.f[2] = frame_time * -10.0f; } @@ -3098,11 +3098,11 @@ void hero_update_movement(void) { } clip_hero_velocity_against_probed_surfaces(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3117,10 +3117,10 @@ void hero_update_movement(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } @@ -3192,11 +3192,11 @@ void hero_update_movement(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); clip_hero_velocity_against_probed_surfaces(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_2_REPEATABLE_SQUARE_ACTION: @@ -3297,10 +3297,10 @@ void hero_update_movement(void) { } clip_hero_velocity_against_probed_surfaces(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -3321,11 +3321,11 @@ void hero_update_movement(void) { } } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_WAIT_FOR_CIRCLE_RELEASE_AND_ANIMATION: { @@ -3357,11 +3357,11 @@ void hero_update_movement(void) { } } if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3381,7 +3381,7 @@ void hero_update_movement(void) { if (hero.move_lock_timer == 0) { hero_move_state_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); if (hero.motion.velocity.f[2] < frame_time * -10.0f) { hero.motion.velocity.f[2] = frame_time * -10.0f; } @@ -3449,11 +3449,11 @@ void hero_update_movement(void) { } clip_hero_velocity_against_probed_surfaces(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3468,10 +3468,10 @@ void hero_update_movement(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } @@ -3486,18 +3486,18 @@ void hero_update_movement(void) { reduce_and_apply_hero_planar_velocity_addend(frame_time_sq * 12.6f); clip_hero_velocity_against_probed_surfaces(0); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: hero.motion.move_yaw = hero.downhill_yaw; hero.target_speed = frame_time * 5.5f; steer_hero_planar_velocity(frame_time_sq * 25.0f); - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 18.0f); break; case HERO_STATE_VEHICLE_MODE_3_FALL: @@ -3505,7 +3505,7 @@ void hero_update_movement(void) { if (hero.move_lock_timer == 0) { hero_move_state_velocity(); } - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -3534,11 +3534,11 @@ void hero_update_movement(void) { } clip_hero_velocity_against_probed_surfaces(1); if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3553,10 +3553,10 @@ void hero_update_movement(void) { FUN_L00_001ff600(len, &hero.motion.velocity, &hero.motion.velocity); hero.motion.velocity.f[2] = 0.0f; if (hero.air_frames.s != 0) { - FUN_L00_002334d0( + add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - FUN_L00_002334d0(&hero.motion.velocity, &hero.motion.velocity, 0.004f); + add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, 0.004f); } break; } diff --git a/src/overlays/shared/hero/set_hero_animation.c b/src/overlays/shared/hero/set_hero_animation.c index 9a0217306b..eb53b21b1a 100644 --- a/src/overlays/shared/hero/set_hero_animation.c +++ b/src/overlays/shared/hero/set_hero_animation.c @@ -935,9 +935,9 @@ typedef struct { f32 v[4]; } V002334d0 __attribute__((aligned(16))); -void FUN_L00_002334d0(f32 *out, f32 *in, f32 k); +void add_hero_gravity_offset(f32 *out, f32 *in, f32 k) __asm__("FUN_L00_002334d0"); -void FUN_L00_002334d0(f32 *gravity_adjusted_vector, f32 *in, f32 k) { +void add_hero_gravity_offset(f32 *gravity_adjusted_vector, f32 *in, f32 k) { struct Hero *hero_base = &hero; V002334d0 offset_vector; switch (hero_base->gravity_mode) { diff --git a/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c b/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c index 7781049c93..bb1f61f0c8 100644 --- a/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c +++ b/src/overlays/shared/hero/update_hero_vehicle_attachments_and_effects.c @@ -554,7 +554,7 @@ typedef union { extern OvlVec4 coll_hit_pos __asm__("D_L06_001745F0") NOT_SDA; /* position after push-out of the last collision query */ extern void resolve_hero_pending_path_clearance(void) __asm__("FUN_L00_002347c0"); extern void add_hero_up_offset(void *, void *, f32) __asm__("FUN_L00_00233810"); -extern void FUN_L00_002334d0(void *, void *, f32); +extern void add_hero_gravity_offset(void *, void *, f32) __asm__("FUN_L00_002334d0"); extern s32 coll_sphere(void *, s32, s32, f32) __asm__("FUN_L00_001f0d60"); extern s32 rig_probe(void *, s32, f32, s32, f32) __asm__("FUN_L00_001f19a0"); extern s32 coll3_22a1d0(void *, f32) __asm__("FUN_L00_001f3170"); @@ -582,7 +582,7 @@ s32 resolve_hero_position_collisions(s32 mode) { if (hero.gravity_mode == HERO_GRAVITY_OPPOSITE_GROUND_NORMAL || hero.unk1F8 != 0) { add_hero_up_offset(&collision_query_offset, &collision_query_offset, 0.6f); } else { - FUN_L00_002334d0( + add_hero_gravity_offset( &collision_query_offset, &collision_query_offset, -hero.capsule_bottom); } } else { From 100c326e0d5807b54144f90031f620ff66360279 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:05:40 +0000 Subject: [PATCH 1430/1502] decomp: clarify names in flickering_point_light_update domain_0_value_1 -> EFFECT_STATE_UPDATE: Retail 0030b640 loads moby state byte +0x20; 0030b64c..0030b650 compares it with 1 and branches to recurring update code at 0030b70c. Initialization scales quads and initializes the slot at 0030b660..0030b6d4, then 0030b6ec/0030b700 loads 1 and 0030b708 stores it to that same +0x20 byte. Bound C dispatches state=MOBY(moby)->state through existing local enum EFFECT_STATE_UPDATE=1, so the assignment enters that exact established state domain, not Boolean TRUE. --- src/overlays/shared/props/flickering_point_light.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/props/flickering_point_light.c b/src/overlays/shared/props/flickering_point_light.c index ee79473e8e..95b33c3a14 100644 --- a/src/overlays/shared/props/flickering_point_light.c +++ b/src/overlays/shared/props/flickering_point_light.c @@ -59,7 +59,7 @@ void flickering_point_light_update(u8 *moby) { *(s32 *)(effect_vars + 0x68) = -1; if (MOBY(moby)->update_dist < truncate_float_to_s32(*(f32 *)(effect_vars + 0x5c)) + 4) MOBY(moby)->update_dist = truncate_float_to_s32(*(f32 *)(effect_vars + 0x5c)) + 4; - MOBY(moby)->state = 1; + MOBY(moby)->state = EFFECT_STATE_UPDATE; return; case EFFECT_STATE_UPDATE: break; From 433e942e26345af66c54940db85e084af67e87ae Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:05:41 +0000 Subject: [PATCH 1431/1502] decomp: clarify names in decoy_glove_update domain_0_value_3 -> DECOY_GLOVE_RELEASE_DECOY: Retail 0x002d2878..0x002d287c stores 3 into moby+0x20 after voice allocation and ammo consumption. The same byte is the switch selector at 0x002d2898; its existing DECOY_GLOVE_RELEASE_DECOY case releases vars+0x50 through 0x002c3888 at 0x002d29a0 and clears the held target. domain_1_value_1 -> DECOY_GLOVE_WAIT_FOR_MOBY_FLAG: In initialization, retail 0x002d28c4..0x002d28d8 tests moby+0x70 mask 2 and stores 1 into moby+0x20 when clear. This is the exact byte selected at 0x002d2898 and named DECOY_GLOVE_WAIT_FOR_MOBY_FLAG in the existing local enum and switch; that case waits for the same flag at 0x002d28dc..0x002d28f0. domain_2_value_2 -> DECOY_GLOVE_TARGET_FOLLOW_AND_SPAWN: The initialization flag-set path loads 2 at 0x002d28d0 and stores it to moby+0x20 at 0x002d28d8. This is the switch selector loaded at 0x002d2898, whose existing case DECOY_GLOVE_TARGET_FOLLOW_AND_SPAWN breaks into the common target-position copy or conditional spawn at 0x002d2a08..0x002d2a60. domain_3_value_2 -> DECOY_GLOVE_TARGET_FOLLOW_AND_SPAWN: The existing DECOY_GLOVE_WAIT_FOR_MOBY_FLAG case tests moby+0x70 mask 2 at 0x002d28dc..0x002d28e4, then stores 2 to the switch-selector byte moby+0x20 at 0x002d28f0. It enters the existing same-domain DECOY_GLOVE_TARGET_FOLLOW_AND_SPAWN case, which reaches common target follow and conditional spawning. domain_4_value_4 -> DECOY_GLOVE_WAIT_AFTER_RELEASE: Retail release and empty-target sound paths converge at 0x002d29c0..0x002d29d4, store 4 into moby+0x20 and set vars+0x54 to scaled 20 frames. That exact selector byte dispatches the existing DECOY_GLOVE_WAIT_AFTER_RELEASE case at 0x002d29d8, which retains state until hero state and item animation permit returning to 2. domain_5_value_2 -> DECOY_GLOVE_TARGET_FOLLOW_AND_SPAWN: In existing DECOY_GLOVE_WAIT_AFTER_RELEASE, retail 0x002d29d8..0x002d29fc checks hero state against 0x23 and item animation flag, then loads 2 and stores it into moby+0x20 at 0x002d2a04. This selector is the same byte read by the decoy-glove switch, so the assignment reuses its existing DECOY_GLOVE_TARGET_FOLLOW_AND_SPAWN member. domain_6_value_6 -> DECOY_GLOVE_SKIP_TARGET_FOLLOW_AND_SPAWN: The existing DECOY_GLOVE_ENTER_SKIP_TARGET_FOLLOW_AND_SPAWN case loads 6 at 0x002d2a00 and stores it to moby+0x20 at 0x002d2a04. On subsequent dispatch of that same byte at 0x002d2898, existing case DECOY_GLOVE_SKIP_TARGET_FOLLOW_AND_SPAWN returns before common target copy/spawn; the entry case itself still reaches common code. --- src/overlays/shared/weapons/decoy_glove.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/weapons/decoy_glove.c b/src/overlays/shared/weapons/decoy_glove.c index 2fbb5b0c21..8d2f661223 100644 --- a/src/overlays/shared/weapons/decoy_glove.c +++ b/src/overlays/shared/weapons/decoy_glove.c @@ -278,7 +278,7 @@ void decoy_glove_update(unsigned char *moby) { L3D10: allocate_hero_voice_for_entry(0x1A, 0); use_ammo(-1, 1); - MOBY(moby)->state = 3; + MOBY(moby)->state = DECOY_GLOVE_RELEASE_DECOY; L3D34: *(u128_D3B20 *)&loc = *(u128_D3B20 *)(&glove_vars->unk40); decoy_glove_aim_throw((int)moby, (void *)glove_vars, (float *)&loc); @@ -287,12 +287,12 @@ void decoy_glove_update(unsigned char *moby) { case DECOY_GLOVE_INITIALIZE: *(int *)&glove_vars->unk50 = 0; if (!(MOBY(moby)->anim_flags & 2)) - MOBY(moby)->state = 1; + MOBY(moby)->state = DECOY_GLOVE_WAIT_FOR_MOBY_FLAG; else - MOBY(moby)->state = 2; + MOBY(moby)->state = DECOY_GLOVE_TARGET_FOLLOW_AND_SPAWN; case DECOY_GLOVE_WAIT_FOR_MOBY_FLAG: if (MOBY(moby)->anim_flags & 2) - MOBY(moby)->state = 2; + MOBY(moby)->state = DECOY_GLOVE_TARGET_FOLLOW_AND_SPAWN; break; case DECOY_GLOVE_TARGET_FOLLOW_AND_SPAWN: break; @@ -312,17 +312,17 @@ void decoy_glove_update(unsigned char *moby) { } else { allocate_voice_for_target_entry(0, 0, (int)moby); } - MOBY(moby)->state = 4; + MOBY(moby)->state = DECOY_GLOVE_WAIT_AFTER_RELEASE; glove_vars->unk54 = scale_game_frames(0x14); break; case DECOY_GLOVE_WAIT_AFTER_RELEASE: { struct Hero *h = &hero; if (h->state.current != 0x23 && h->item_anim_active == 0) - MOBY(moby)->state = 2; + MOBY(moby)->state = DECOY_GLOVE_TARGET_FOLLOW_AND_SPAWN; break; } case DECOY_GLOVE_ENTER_SKIP_TARGET_FOLLOW_AND_SPAWN: - MOBY(moby)->state = 6; + MOBY(moby)->state = DECOY_GLOVE_SKIP_TARGET_FOLLOW_AND_SPAWN; break; case DECOY_GLOVE_SKIP_TARGET_FOLLOW_AND_SPAWN: return; From 22af156d923e232c7ec141369d32303a7ad77029 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:05:41 +0000 Subject: [PATCH 1432/1502] decomp: clarify names in sand_shark_nest_update domain_0_value_0 -> SAND_SHARK_NEST_INITIALIZE: Retail 0x002dcb60 loads signed moby+0x20 and 0x002dcb64 branches on negative; 0x002dcbb0 loads the same byte for the state switch. Source uses this exact MOBY(moby)->state domain with SAND_SHARK_NEST_INITIALIZE=0 as its lowest defined state, so this guard reuses that existing zero boundary without naming negative states. domain_1_value_1 -> SAND_SHARK_NEST_WAIT_FOR_SPAWN: Retail initialization writes 1 to moby+0x20 at 0x002dcc0c-0x002dcc18 and scales delay into pvars+0xD8 at 0x002dcc24-0x002dcc3c. The same state byte selects the source SAND_SHARK_NEST_WAIT_FOR_SPAWN=1 branch, which decrements that timer at 0x002dcc64 before checking shark availability. domain_2_value_2 -> SAND_SHARK_NEST_LAUNCH_SAND_SHARK: Retail 0x002dcc64-0x002dcc90 checks the spawn timer and FUN_L02_002dd2a8 availability, then writes 2 to the same moby+0x20 state selector. Existing source SAND_SHARK_NEST_LAUNCH_SAND_SHARK=2 handles animation progress 12 and invokes launch_sand_shark at 0x002dcde8 with the selected shark and launch vectors. domain_3_value_1 -> SAND_SHARK_NEST_WAIT_FOR_SPAWN: In the source launch-state branch, retail 0x002dccbc-0x002dccd4 tests animation flag 2 and writes 1 to moby+0x20 when it completes, then restores animation 0. This is the identical selector whose existing SAND_SHARK_NEST_WAIT_FOR_SPAWN=1 branch at 0x002dcc64 waits for the next spawn timer. domain_4_value_1 -> SAND_SHARK_NEST_WAIT_FOR_SPAWN: Source HIT_RECOVERY calls step_moby_motion; retail 0x002dcdf8-0x002dce1c then tests animation flag 2 and writes 1 to the same moby+0x20 state selector before restoring animation 0. That selector's existing SAND_SHARK_NEST_WAIT_FOR_SPAWN=1 branch decrements the spawn timer at 0x002dcc64. --- src/overlays/l02/mobys/sand_shark_nest.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l02/mobys/sand_shark_nest.c b/src/overlays/l02/mobys/sand_shark_nest.c index 550dda5a05..30ab9a6f65 100644 --- a/src/overlays/l02/mobys/sand_shark_nest.c +++ b/src/overlays/l02/mobys/sand_shark_nest.c @@ -158,7 +158,7 @@ void sand_shark_nest_update(unsigned char *moby) { OvlVec4 launch_position; handle_sand_shark_nest_damage((struct Moby *)moby); - if ((signed char)MOBY(moby)->state < 0) { + if ((signed char)MOBY(moby)->state < SAND_SHARK_NEST_INITIALIZE) { return; } if (MOBY(moby)->visible != 0 && fast_vec_dist(moby + 0x10, D_L02_001673C0) < 28.0f) { @@ -171,7 +171,7 @@ void sand_shark_nest_update(unsigned char *moby) { if (MOBY(moby)->unkB4 <= 0) { MOBY(moby)->unkB4 = 1; } - MOBY(moby)->state = 1; + MOBY(moby)->state = SAND_SHARK_NEST_WAIT_FOR_SPAWN; nest_vars->f20 = 3.0f; nest_vars->s24 = 3; nest_vars->b2E = 1; @@ -183,7 +183,7 @@ void sand_shark_nest_update(unsigned char *moby) { case SAND_SHARK_NEST_WAIT_FOR_SPAWN: if (fast_dec_timer(&nest_vars->timer)) { if (FUN_L02_002dd2a8_c(moby)) { - MOBY(moby)->state = 2; + MOBY(moby)->state = SAND_SHARK_NEST_LAUNCH_SAND_SHARK; if (MOBY(moby)->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -194,7 +194,7 @@ void sand_shark_nest_update(unsigned char *moby) { break; case SAND_SHARK_NEST_LAUNCH_SAND_SHARK: if (MOBY(moby)->anim_flags & 2) { - MOBY(moby)->state = 1; + MOBY(moby)->state = SAND_SHARK_NEST_WAIT_FOR_SPAWN; if (MOBY(moby)->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } @@ -228,7 +228,7 @@ void sand_shark_nest_update(unsigned char *moby) { case SAND_SHARK_NEST_HIT_RECOVERY: step_moby_motion(moby, nest_vars->anim); if (MOBY(moby)->anim_flags & 2) { - MOBY(moby)->state = 1; + MOBY(moby)->state = SAND_SHARK_NEST_WAIT_FOR_SPAWN; if (MOBY(moby)->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(20)); } From 299e476c1a3257b61730f3e2ca10c6ebd6e5707e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:07:55 +0000 Subject: [PATCH 1433/1502] decomp: clarify names in linked_switch_group_update domain_0_value_1 -> MONITOR_LINKED_GROUP_HITS: Retail 0x002e4570-0x002e4578 stores 1 into current moby s3+0x20 after group initialization. This is the identical state byte loaded at 0x002e4498 for the switch whose existing case 1 is MONITOR_LINKED_GROUP_HITS; its handler reports qualifying hits at 0x002e457c-0x002e45f8. domain_1_value_2 -> WAIT_FOR_LINKED_GROUP_COMPLETION: Retail 0x002e45fc-0x002e4604 loads current moby s3+0x20 and compares it with 2 before comparing reported count +0x7A with total +0x7B at 0x002e460c-0x002e4618. It is the same selector as the existing WAIT_FOR_LINKED_GROUP_COMPLETION case, not a control/request value. domain_2_value_4 -> UPDATE_OPENED_STATE: Retail 0x002e4660-0x002e4668 stores 4 into current moby s3+0x20 following count completion, group-state broadcast 4 and the opened diagnostic at 0x002e4620-0x002e465c. The same state byte selects the existing UPDATE_OPENED_STATE case at 0x002e47a8, which handles opened expiry and feedback. domain_3_value_3 -> RESET_HIT_STATE: Retail 0x002e4674-0x002e46c4 handles completion timeout, clears hit latch/count, broadcasts group state 3, prints failed and stores 3 to current moby s3+0x20. That exact switch selector's existing RESET_HIT_STATE case at 0x002e476c restores health and monitoring. domain_4_value_1 -> MONITOR_LINKED_GROUP_HITS: Retail reset handler 0x002e476c-0x002e47a4 restores neutral color, clears hit count/latch, converts initial health to float, and stores 1 to current moby s3+0x20. That byte is the switch selector with existing MONITOR_LINKED_GROUP_HITS case 1, reentering the qualifying-hit handler. domain_5_value_3 -> RESET_HIT_STATE: Retail 0x002e47c0-0x002e4810 handles opened timer expiry, clears hit count/latch, broadcasts state 3 and prints the closed diagnostic before storing 3 to current moby s3+0x20. This is the identical selector handled by existing RESET_HIT_STATE case 3 at 0x002e476c-0x002e47a4. --- src/overlays/l13/mobys/linked_switch_group.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l13/mobys/linked_switch_group.c b/src/overlays/l13/mobys/linked_switch_group.c index ee47ddcd6e..599bfa5a92 100644 --- a/src/overlays/l13/mobys/linked_switch_group.c +++ b/src/overlays/l13/mobys/linked_switch_group.c @@ -166,7 +166,7 @@ void linked_switch_group_update(char *moby) { switch_vars->unk76 = 0; set_moby_color(moby, 0x80, 0x80, 0x80); - MOBY(moby)->state = 1; + MOBY(moby)->state = MONITOR_LINKED_GROUP_HITS; break; case MONITOR_LINKED_GROUP_HITS: case WAIT_FOR_LINKED_GROUP_COMPLETION: @@ -187,14 +187,14 @@ void linked_switch_group_update(char *moby) { set_moby_color(moby, 0, 0xFF, 0); switch_vars->unk74 = 1; } - if ((unsigned char)MOBY(moby)->state == 2) { + if ((unsigned char)MOBY(moby)->state == WAIT_FOR_LINKED_GROUP_COMPLETION) { if (switch_vars->unk7A >= switch_vars->unk7B) { set_moby_list_state((unsigned char)MOBY(moby)->group, 4); allocate_voice_for_target_entry(1, 0, moby); switch_vars->unk70 = switch_vars->unk84; debug_print( D_L13_001F4D90, ((short)MOBY(moby)->save_id), MOBY(moby)->oclass, frame_count); - MOBY(moby)->state = 4; + MOBY(moby)->state = UPDATE_OPENED_STATE; } else { if (switch_vars->unk7C >= 0) { if (fast_dec_timer_s16(&switch_vars->unk70) != 0) { @@ -207,7 +207,7 @@ void linked_switch_group_update(char *moby) { ((short)MOBY(moby)->save_id), MOBY(moby)->oclass, frame_count); - MOBY(moby)->state = 3; + MOBY(moby)->state = RESET_HIT_STATE; } else if (fast_dec_timer_s16(&switch_vars->unk72) != 0) { allocate_voice_for_target_entry(0, 0, moby); switch_vars->unk72 = MIN(scale_game_frames(0x2D), @@ -224,7 +224,7 @@ void linked_switch_group_update(char *moby) { switch_vars->unk7A = 0; switch_vars->unk74 = 0; switch_vars->unk20 = (float)switch_vars->unk24; - MOBY(moby)->state = 1; + MOBY(moby)->state = MONITOR_LINKED_GROUP_HITS; break; case UPDATE_OPENED_STATE: @@ -239,7 +239,7 @@ void linked_switch_group_update(char *moby) { ((short)MOBY(moby)->save_id), MOBY(moby)->oclass, frame_count); - MOBY(moby)->state = 3; + MOBY(moby)->state = RESET_HIT_STATE; } else if (fast_dec_timer_s16(&switch_vars->unk72) != 0) { allocate_voice_for_target_entry(0, 0, moby); switch_vars->unk72 = From 9c19499a6b98130c6eeee36d06876e89d3edd350 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:07:55 +0000 Subject: [PATCH 1434/1502] decomp: clarify names in destroy_gadgebot_spawn_container domain_0_value_2 -> GADGEBOT_CONTAINER_WAIT_FOR_REMOVAL: Retail 0x002d8188 saves the container argument in s1; 0x002d84b4 loads v1=2 and 0x002d84c8 stores it to 0x20(s1), the authoritative source's MOBY(moby)->state. The same moby reaches destroy_gadgebot_spawn_container from gadgebot_spawn_container_update's non-null hit branch. That update switches on this exact state field and already names value 2 GADGEBOT_CONTAINER_WAIT_FOR_REMOVAL: its branch tests the timer at moby+0xBC and calls mark_moby_for_removal. Retail 0x002d84cc-0x002d84d4 initializes this timer with scale_game_frames(15), proving this assignment enters the existing removal-wait state rather than any hero enum domain. --- src/overlays/shared/enemies/gadgebot_spawn_container.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/gadgebot_spawn_container.c b/src/overlays/shared/enemies/gadgebot_spawn_container.c index 7badf1210d..e3ccdfd7a0 100644 --- a/src/overlays/shared/enemies/gadgebot_spawn_container.c +++ b/src/overlays/shared/enemies/gadgebot_spawn_container.c @@ -87,6 +87,9 @@ static inline void transform_point(float *dst, float *src, float (*m)[4]) { void destroy_gadgebot_spawn_container(void *moby_ptr, void *target_ptr) __asm__("FUN_L06_002d8178"); void destroy_gadgebot_spawn_container(void *moby_ptr, void *target_ptr) { + enum { + GADGEBOT_CONTAINER_WAIT_FOR_REMOVAL = 2 + }; int i; int j; char *moby = moby_ptr; @@ -144,7 +147,7 @@ void destroy_gadgebot_spawn_container(void *moby_ptr, void *target_ptr) { } } MOBY(moby)->collision = 0; - MOBY(moby)->state = 2; + MOBY(moby)->state = GADGEBOT_CONTAINER_WAIT_FOR_REMOVAL; MOBY(moby)->flags |= 1; MOBY(moby)->command = (unsigned char)scale_game_frames(15); } From ddfa2d3e5f0c4e79e4821528c310cfde17a2a5fa Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:07:55 +0000 Subject: [PATCH 1435/1502] decomp: clarify names in update_blarg_elite_commando_joint_aim domain_0_value_2 -> COMMANDO_PURSUIT_MODE_DISABLED: Authoritative source src/overlays/shared/enemies/blarg_elite_commando.c SHA-256 88ccf445529ce4d511397ebaa1c519a3a250b97311458c09fb0287e176de8cec identifies pvars+0x114 as pursuit_mode. Retail 0x002d45c4 loads pvars, 0x002d45c8 loads +0x114, and 0x002d45cc branches on 2 to 0x002d485c, bypassing all target-angle recomputation while retaining all three update_joint_animation calls. Bounded retail sibling evidence a81335e0a6cc4898b44bfb2cc00802cd proves 2 is stored to this same +0x114 at 0x002d3d00 when hero mode is 22, and at 0x002d3d84 when target XY distance exceeds the pursuit range (comparison 0x002d3d74). The embedded caller source uses pursuit_mode == 2 for timed patrol-node movement, while pursuit_mode != 2 selects attack-node or rocket-fire preparation. Together these prove disabled pursuit/combat targeting, separate from the moby state at +0x20 and all Hero enums. --- src/overlays/shared/enemies/blarg_elite_commando.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/blarg_elite_commando.c b/src/overlays/shared/enemies/blarg_elite_commando.c index 237fecbb6f..b08d5ef748 100644 --- a/src/overlays/shared/enemies/blarg_elite_commando.c +++ b/src/overlays/shared/enemies/blarg_elite_commando.c @@ -853,9 +853,12 @@ void emit_blarg_elite_commando_death_particles(void *moby) { /* Aim paired joints toward the owner or player, then smooth their rotations. */ /* Ported from rac1-decomp (src/overlays/shared/vendor_002A1B58.c: func_L16_002D5958), where it is exact; names translated to the US level program. */ void update_blarg_elite_commando_joint_aim(char *commando_moby) { + enum { + COMMANDO_PURSUIT_MODE_DISABLED = 2 + }; float position[4], target[4], matrix[16], delta[4], aim[4], aimDelta[4], velocity[4]; L16DamageData *commando_data = (L16DamageData *)MOBY(commando_moby)->pvars; - if (commando_data->pursuit_mode != 2) { + if (commando_data->pursuit_mode != COMMANDO_PURSUIT_MODE_DISABLED) { float *savedTarget, *savedMatrix; float yaw, pitch; qcopy(position, &MOBY(commando_moby)->pos); From d7fc1b9eb3b3fd9cd5dec353a0eb7d5eb8d8acfe Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:07:56 +0000 Subject: [PATCH 1436/1502] decomp: clarify names in render_data_processor_linked_effect domain_0_value_2 -> MOBY_STATE_ACTIVE_WITHOUT_SOUND: Authoritative src/overlays/l10/mobys/data_processor_linked_effect.c SHA-256 44286b8b1660d99f9dc2b500c692284efe9d4fa65f28b775a377ff3b3aa7cdb2 defines MOBY_STATE_ACTIVE_WITHOUT_SOUND=2 in data_processor_linked_effect_update and switches on this effect moby's state; that branch decrements timer_34, releases its voice, sets voice=-1 and queues render_data_processor_linked_effect with the same moby. Root retail 0x002da6d8 saves that moby; 0x002daa64 loads it, 0x002daa74 reads its state at +0x20, 0x002daa78-0x002daa7c compares 2. Equal branch 0x002daa84-0x002daac4 loads the same pvars timer at +0x34 and replaces quad alpha by timer*255/scaled fade duration. Original Ghidra likewise tests *(char *)(iStack_130+0x20)==2 and uses pfStack_12c[0xd]. This is the linked-effect update state, not any supplied Hero enum. --- src/overlays/l10/mobys/data_processor_linked_effect.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l10/mobys/data_processor_linked_effect.c b/src/overlays/l10/mobys/data_processor_linked_effect.c index 61ffba0128..39c0fcf201 100644 --- a/src/overlays/l10/mobys/data_processor_linked_effect.c +++ b/src/overlays/l10/mobys/data_processor_linked_effect.c @@ -183,6 +183,9 @@ extern int D_L10_00161D64; extern int D_L10_00161D68; void render_data_processor_linked_effect(u8 *moby) { + enum { + MOBY_STATE_ACTIVE_WITHOUT_SOUND = 2 + }; DataProcessorLinkedEffectVars *linked_effect_render_vars = (DataProcessorLinkedEffectVars *)MOBY(moby)->pvars; char *linked_processor_vars = @@ -300,7 +303,7 @@ void render_data_processor_linked_effect(u8 *moby) { (color & 0xffffff) + (truncate_float_to_s32(fade * fade * convert_integer_to_float((int)color >> 24)) << 24); - if (MOBY(moby)->state == 2) { + if (MOBY(moby)->state == MOBY_STATE_ACTIVE_WITHOUT_SOUND) { float alpha = convert_integer_to_float(linked_effect_render_vars->timer_34); float duration = scale_time(data_processor_linked_effect_fade_duration_seconds_gp * 60.0f); From 45bbb4adacc1cb82d6678936a4157e893de92e52 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:07:56 +0000 Subject: [PATCH 1437/1502] decomp: clarify names in process_blarg_space_commando_hits domain_0_value_16 -> BLARG_COMMANDO_STATE_DEATH_KNOCKBACK: Retail 0x002feb50 preserves the input moby in s2; 0x002fec40 loads its state byte at s2+0x20 and 0x002fec44-0x002fec48 bypasses further hit handling when it equals 16. This is the same byte written at 0x002fedb0 on fatal responses. Authoritative blarg_space_commando_update calls this function on that moby before switching moby->state; its established BLARG_COMMANDO_STATE_DEATH_KNOCKBACK=16 steps velocity and explodes/removes the moby on contact. Reuse that commando state name, not HeroStateId. domain_1_value_15 -> BLARG_COMMANDO_STATE_KNOCKBACK: Original retail decompilation groups hit responses 3-10 in the branch at 0x002fed18; li v0,15 followed by sb v0,0x20(s2) at 0x002fed20 writes the input commando's Moby.state. The branch initializes scaled 60-frame knockback and calls trooper_start_knockback at 0x002fed94 with pvars+0x60. The authoritative caller dispatches that same moby state using established BLARG_COMMANDO_STATE_KNOCKBACK=15, steps its velocity and returns to action selection on hit&0x40. This proves reuse of the commando state constant. domain_2_value_16 -> BLARG_COMMANDO_STATE_DEATH_KNOCKBACK: Retail 0x002feda8 loads 16 and 0x002fedb0 stores it to s2+0x20, the same Moby.state byte read by the earlier guard. Original decompilation places this write in hit responses 1/2; health depletion forces response 1 at 0x002fecd0. The arm starts fatal knockback at 0x002fee44 and attempts ten fragment spawns. The authoritative caller switches this same moby's state under established BLARG_COMMANDO_STATE_DEATH_KNOCKBACK=16, then explodes and removes it after motion contact, proving this exact state domain and canonical name. --- src/overlays/shared/enemies/blarg_space_commando.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/blarg_space_commando.c b/src/overlays/shared/enemies/blarg_space_commando.c index 0134edba01..808e0bdebb 100644 --- a/src/overlays/shared/enemies/blarg_space_commando.c +++ b/src/overlays/shared/enemies/blarg_space_commando.c @@ -592,6 +592,10 @@ void process_blarg_space_commando_hits(char *moby) { SIXTY_FRAME_KNOCKBACK_HIT_RESPONSE = 10, HIT_RESPONSE_PRESERVING_MOBY_STATE = 11 }; + enum { + BLARG_COMMANDO_STATE_KNOCKBACK = 0xF, + BLARG_COMMANDO_STATE_DEATH_KNOCKBACK = 0x10 + }; extern unsigned char D_0013D408[]; char *commando_state; char *hit_record; @@ -620,7 +624,7 @@ void process_blarg_space_commando_hits(char *moby) { hit_record = find_moby_hit(moby, 0x330000, 0); hit_response_index = resolve_moby_hit_response(moby, hit_record, commando_state + 0x20, 0, &hit, &dt, 0, 4); - if (hit != 1 && (unsigned char)MOBY(moby)->state != 0x10) { + if (hit != 1 && (unsigned char)MOBY(moby)->state != BLARG_COMMANDO_STATE_DEATH_KNOCKBACK) { if (current_level_index_gp == 0xA && hit_record != 0 && *(char **)(hit_record + 0x20) != 0 && *(short *)(*(char **)(hit_record + 0x20) + 0xA6) == 0x31A && D_0013D408[0x11] == 0) { @@ -646,7 +650,7 @@ void process_blarg_space_commando_hits(char *moby) { char *q; int knockback_frames; float b, a; - MOBY(moby)->state = 0xF; + MOBY(moby)->state = BLARG_COMMANDO_STATE_KNOCKBACK; q = commando_state + 0x60; knockback_frames = scale_game_frames(0x3C); a = nonfatal_knockback_horizontal_speed_gp * D_0015ED6C; @@ -670,7 +674,7 @@ void process_blarg_space_commando_hits(char *moby) { case FRAGMENTING_FATAL_HIT_RESPONSE: { char *q; float a, b; - MOBY(moby)->state = 0x10; + MOBY(moby)->state = BLARG_COMMANDO_STATE_DEATH_KNOCKBACK; q = commando_state + 0x60; a = fatal_knockback_horizontal_speed_gp * D_0015ED6C; b = fatal_knockback_vertical_speed_gp * D_0015ED6C; From ea85f6b6c33ea9a48646a8b6f56894b80598a312 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:07:56 +0000 Subject: [PATCH 1438/1502] decomp: clarify names in taxi_platform_update domain_0_value_0 -> TAXI_PLATFORM_STATE_UNINITIALIZED: In bound source src/overlays/l07/mobys/taxi_platform.c SHA-256 415ea1686fd3a792add186e8184abc5f59dc56470407fdb082a251e53ce27bd7, MOBY(moby)->state == 0 gates one-time setup. Original retail Ghidra tests param_1+0x20 against zero; retail 0x002cd314-0x002cd318 loads that byte and skips setup when nonzero. The gated block initializes pvars, sets initial command and progress, copies the selected path endpoint, clears timers/motion, and invalidates the voice slot before setting this same state byte to 1 at 0x002cd3a0. Thus zero denotes uninitialized taxi-platform state, distinct from command at moby+0xBC and hero state domains. domain_1_value_1 -> TAXI_PLATFORM_STATE_INITIALIZED: Original retail Ghidra writes *(undefined1 *)(param_1+0x20)=1 in the setup block, matching MOBY(moby)->state = 1 in the authoritative C. Retail 0x002cd38c loads a0=1 and 0x002cd3a0 stores it to 0x20(s3), after endpoint placement and timer/progress resets; setup also initializes draw/update distances and voice-slot sentinel through 0x002cd3b0. On subsequent calls 0x002cd314-0x002cd318 tests the same byte and bypasses setup when nonzero. One therefore marks completed taxi-platform initialization; boarding and movement remain independently selected by moby+0xBC, so neither taxi command nor HeroStateId members apply. --- src/overlays/l07/mobys/taxi_platform.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l07/mobys/taxi_platform.c b/src/overlays/l07/mobys/taxi_platform.c index 758ed3a483..4ef84d5ba3 100644 --- a/src/overlays/l07/mobys/taxi_platform.c +++ b/src/overlays/l07/mobys/taxi_platform.c @@ -40,6 +40,10 @@ s32 allocate_voice_for_target_entry(s32 entry_index, /* Moby class 38 */ void taxi_platform_update(unsigned char *moby) { + enum { + TAXI_PLATFORM_STATE_UNINITIALIZED = 0, + TAXI_PLATFORM_STATE_INITIALIZED = 1 + }; char *taxi_platform_vars = ((char *)MOBY(moby)->pvars); char *path; float orig[4], delta[4], path_segment_offset[4]; @@ -49,7 +53,7 @@ void taxi_platform_update(unsigned char *moby) { path = D_L07_001B0530[*(int *)(taxi_platform_vars + 0xB4)]; qcopy(orig, moby + 0x10); fast_dec_timer_s16(taxi_platform_vars + 0xBA); - if (MOBY(moby)->state == 0) { + if (MOBY(moby)->state == TAXI_PLATFORM_STATE_UNINITIALIZED) { float f; char *pts; taxi_platform_vars[0x28] = 4; @@ -66,7 +70,7 @@ void taxi_platform_update(unsigned char *moby) { *(short *)(taxi_platform_vars + 0xBA) = 0; *(int *)(taxi_platform_vars + 0xA8) = 0; *(int *)(taxi_platform_vars + 0xBC) = 0; - MOBY(moby)->state = 1; + MOBY(moby)->state = TAXI_PLATFORM_STATE_INITIALIZED; MOBY(moby)->update_dist = 0xFF; MOBY(moby)->draw_dist = 0xFF; *(int *)(taxi_platform_vars + 0xC4) = -1; From e987aaf2a6e1e67bfa8851772d45f756d82e0103 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:07:56 +0000 Subject: [PATCH 1439/1502] decomp: clarify names in moving_platform_small_update domain_0_value_1 -> PLATFORM_EASED_ENDPOINT_TRAVEL: Source initialization resets easing_frames and computes glide_speed before assigning MOBY(moby)->state=1. Retail 0x00294d80 loads 1 and 0x00294d98 branches to the state-byte store at 0x0029512c. That same byte is loaded at 0x00294c74 for the switch; existing case PLATFORM_EASED_ENDPOINT_TRAVEL computes quadratic endpoint travel at 0x00294da0-0x00294ec4. Thus this assignment uses that existing state domain/member. domain_1_value_2 -> PLATFORM_PAUSE_BEFORE_EASED_TRAVEL: After eased endpoint travel completes, retail 0x00294ed8-0x00294ee4 reverses direction, releases the loop voice, then 0x00294f2c loads 2 for the state-byte store at 0x00295108 and initializes wait_timer at 0x0029510c-0x00295118. Existing source case PLATFORM_PAUSE_BEFORE_EASED_TRAVEL reads that same moby+0x20 selector and decrements wait_timer before restarting eased travel. domain_2_value_1 -> PLATFORM_EASED_ENDPOINT_TRAVEL: In existing source case PLATFORM_PAUSE_BEFORE_EASED_TRAVEL, expiration of wait_timer resets easing_frames and assigns state 1. Retail 0x00294f30-0x00294f44 checks the timer, loads 1, clears pvars+0x10c and branches to the moby+0x20 store at 0x0029512c. This is the same selector read at 0x00294c74 and handled by existing PLATFORM_EASED_ENDPOINT_TRAVEL. domain_3_value_4 -> PLATFORM_PAUSE_BEFORE_NODE_TRAVEL: Source node travel assigns state 4 only after a configured node/end arrival with positive wait_frames, then initializes wait_timer. Retail arrival checks at 0x00295090-0x002950b8 lead through voice release to loading 4 at 0x00295100 and storing moby+0x20 at 0x00295108. Existing case PLATFORM_PAUSE_BEFORE_NODE_TRAVEL handles that same selector by waiting on pvars+0xe8 before returning to node travel. domain_4_value_3 -> PLATFORM_FOLLOW_PATH_NODES: Source case PLATFORM_PAUSE_BEFORE_NODE_TRAVEL assigns state 3 when wait_timer expires. Retail 0x0029511c-0x00295128 checks pvars+0xe8, loads 3 and falls through to the moby+0x20 store at 0x0029512c. The switch reads this identical byte at 0x00294c74; existing PLATFORM_FOLLOW_PATH_NODES advances a modulo node index and moves toward path nodes at 0x00294f48-0x002950a4. --- src/overlays/l03/mobys/moving_platform_small.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l03/mobys/moving_platform_small.c b/src/overlays/l03/mobys/moving_platform_small.c index bb99435e89..db5139eeac 100644 --- a/src/overlays/l03/mobys/moving_platform_small.c +++ b/src/overlays/l03/mobys/moving_platform_small.c @@ -110,7 +110,7 @@ void moving_platform_small_update(char *moby) { platform_pvars->unk110 * 4.0f / convert_integer_to_float(easing_frame_count * scale_game_frames(240)); platform_pvars->easing_frames = 0; - MOBY(moby)->state = 1; + MOBY(moby)->state = PLATFORM_EASED_ENDPOINT_TRAVEL; } break; case PLATFORM_EASED_ENDPOINT_TRAVEL: @@ -149,14 +149,14 @@ void moving_platform_small_update(char *moby) { } } platform_pvars->voice = -1; - MOBY(moby)->state = 2; + MOBY(moby)->state = PLATFORM_PAUSE_BEFORE_EASED_TRAVEL; platform_pvars->wait_timer = scale_game_frames(platform_pvars->wait_frames); } break; case PLATFORM_PAUSE_BEFORE_EASED_TRAVEL: if (fast_dec_timer(&platform_pvars->wait_timer)) { platform_pvars->easing_frames = 0; - MOBY(moby)->state = 1; + MOBY(moby)->state = PLATFORM_EASED_ENDPOINT_TRAVEL; } break; case PLATFORM_FOLLOW_PATH_NODES: @@ -206,14 +206,14 @@ void moving_platform_small_update(char *moby) { } } platform_pvars->voice = -1; - MOBY(moby)->state = 4; + MOBY(moby)->state = PLATFORM_PAUSE_BEFORE_NODE_TRAVEL; platform_pvars->wait_timer = scale_game_frames(platform_pvars->wait_frames); } } break; case PLATFORM_PAUSE_BEFORE_NODE_TRAVEL: if (fast_dec_timer(&platform_pvars->wait_timer)) { - MOBY(moby)->state = 3; + MOBY(moby)->state = PLATFORM_FOLLOW_PATH_NODES; } break; } From d58a8832487383aa0274644ea2ccbe38ac977481 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:09:57 +0000 Subject: [PATCH 1440/1502] decomp: clarify names in bot_door_lock_update domain_0_value_1 -> BOT_DOOR_LOCK_STATE_ACTIVE: Retail 0x00307de8 loads the state byte at moby+0x20; 0x00307dec dispatches value 1 to 0x00307e48, the existing BOT_DOOR_LOCK_STATE_ACTIVE case. Initialization copies the count and seeds phases at 0x00307e20-0x00307e34, then 0x00307e38 stores s0=1 to that identical state byte. Thus this assignment enters the same enum domain and canonical ACTIVE member. domain_1_value_2 -> BOT_DOOR_LOCK_STATE_SHRINK_EFFECT: After count/persistence completion checks and four linked-target activations at 0x003082b8-0x0030831c, retail 0x00308320 loads 2 and 0x00308328 stores it to moby+0x20. The same byte is loaded at 0x00307de8 and value 2 dispatches at 0x00307e10 to 0x0030832c, the existing BOT_DOOR_LOCK_STATE_SHRINK_EFFECT case, which decreases horizontal scale, clamps zero and queues glow only while positive. Reuse that canonical member for this state assignment. --- src/overlays/shared/props/bot_door_lock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/props/bot_door_lock.c b/src/overlays/shared/props/bot_door_lock.c index e4a25a5ce1..c0b25b9b3d 100644 --- a/src/overlays/shared/props/bot_door_lock.c +++ b/src/overlays/shared/props/bot_door_lock.c @@ -249,7 +249,7 @@ void bot_door_lock_update(char *moby) { idata[5] = idata[4]; bot_door_lock_data[6] = random_angle_radians(); bot_door_lock_data[10] = random_angle_radians(); - MOBY(moby)->state = 1; + MOBY(moby)->state = BOT_DOOR_LOCK_STATE_ACTIVE; bot_door_lock_data[9] = bot_door_lock_max_effect_horizontal_scale_gp; return; case BOT_DOOR_LOCK_STATE_ACTIVE: @@ -322,7 +322,7 @@ void bot_door_lock_update(char *moby) { activate_bot_door_lock_target( (unsigned char *)moby, (unsigned char *)(level_mobys_q + idata[i] * 0x100)); } - MOBY(moby)->state = 2; + MOBY(moby)->state = BOT_DOOR_LOCK_STATE_SHRINK_EFFECT; } break; case BOT_DOOR_LOCK_STATE_SHRINK_EFFECT: From 15b494ccf2e6dc73e06d9b3003108124d4ea19b2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:09:57 +0000 Subject: [PATCH 1441/1502] decomp: clarify names in spawn_decoy domain_0_value_0 -> DECOY_INITIALIZE: Retail 0x002c3608-0x002c3614 creates class 0xCB/0x76C and retains the new moby in s0; 0x002c363c stores zero to its state byte +0x20. Authoritative decoy.c decoy_update explicitly handles those same classes and switches on MOBY(moby)->state with canonical DECOY_INITIALIZE = 0, initializing timer/collision fields and advancing to DECOY_HELD. Thus this assignment enters the existing decoy initialization state domain. domain_1_value_5 -> DECOY_WAIT_TO_SHRINK: Retail 0x002c3774-0x002c3788 filters listed mobys to classes 0xCB/0x76C, loads their state byte at +0x20, and 0x002c378c tests that byte below 5. This is the same decoy state field switched on in authoritative decoy_update, whose canonical DECOY_WAIT_TO_SHRINK = 5 waits on animation/timer before transitioning to DECOY_SHRINK_FOR_REMOVAL = 6. Retail 0x002c37c4-0x002c37cc removes the selected eligible decoy from the list and writes state 6, confirming removal-state ordering. Reuse the existing decoy-domain member as the exclusive threshold. --- src/overlays/shared/weapons/decoy.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/weapons/decoy.c b/src/overlays/shared/weapons/decoy.c index 7f2269114d..fd9101f2e5 100644 --- a/src/overlays/shared/weapons/decoy.c +++ b/src/overlays/shared/weapons/decoy.c @@ -202,6 +202,10 @@ void destroy_decoy_with_particles(unsigned char *moby) { u8 *spawn_decoy(s32 value, u128 *position, u128 *other_position) __asm__("FUN_L00_002c35c0"); u8 *spawn_decoy(s32 owner_moby, u128 *position, u128 *other_position) { + enum { + DECOY_INITIALIZE = 0, + DECOY_WAIT_TO_SHRINK = 5 + }; u8 *flags = item_text_variant; u8 *spawned_moby; u8 *decoy_vars; @@ -217,7 +221,7 @@ u8 *spawn_decoy(s32 owner_moby, u128 *position, u128 *other_position) { *(u16 *)(spawned_moby + 0x32) = 0xff; MOBY(spawned_moby)->visible = 1; decoy_vars = *(u8 **)(spawned_moby + 0x78); - MOBY(spawned_moby)->state = 0; + MOBY(spawned_moby)->state = DECOY_INITIALIZE; qcopy(&MOBY(spawned_moby)->pos, position); qcopy(decoy_vars + 0x10, other_position); speed = frame_scale * -0.5f; @@ -240,7 +244,7 @@ u8 *spawn_decoy(s32 owner_moby, u128 *position, u128 *other_position) { u8 *listed_moby = (u8 *)(moby_table + (D_L00_001B0830_lui[i] << 8)); if (listed_moby != 0 && (MOBY(listed_moby)->oclass == 0xcb || MOBY(listed_moby)->oclass == 0x76c) && - MOBY(listed_moby)->state < 5) { + MOBY(listed_moby)->state < DECOY_WAIT_TO_SHRINK) { current_value = *(s32 *)(*(u8 **)(listed_moby + 0x78) + 0x54); if (best_value <= current_value) { candidate = listed_moby; From 7402a31c538b9ead3a95d9fb2ea9a85a99984fec Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:09:57 +0000 Subject: [PATCH 1442/1502] decomp: clarify names in spawner_update domain_0_value_1 -> SPAWNER_STATE_SPAWN: The authoritative source declares SPAWNER_STATE_SPAWN = 1 in spawner_update and switches on MOBY(moby)->state. Retail 0x0030abc4 loads that same moby +0x20 byte, and 0x0030abc8-0x0030abcc compares it to 1 and branches to the timer/target/egg-spawning handler at 0x0030ac34. After initialization enumerates and removes existing mobys at 0x0030abfc-0x0030ac24, 0x0030ac28 loads 1 and 0x0030ac30 stores it to the identical +0x20 state byte. Thus this assignment enters the existing SPAWNER_STATE_SPAWN domain member, rather than a separate control or request domain. --- src/overlays/shared/enemies/spawner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/spawner.c b/src/overlays/shared/enemies/spawner.c index e773a15fa5..25165891e3 100644 --- a/src/overlays/shared/enemies/spawner.c +++ b/src/overlays/shared/enemies/spawner.c @@ -162,7 +162,7 @@ void spawner_update(char *moby) { while (get_first_moby_in_group(&moby_to_remove, spawner_vars->unk94, 0, 0) == 0) { mark_moby_for_removal((void *)moby_to_remove); } - MOBY(moby)->state = 1; + MOBY(moby)->state = SPAWNER_STATE_SPAWN; return; } case SPAWNER_STATE_SPAWN: { From 38bb7bebbc1745c9653d430f7dfe0d4d27c25a2f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:11:58 +0000 Subject: [PATCH 1443/1502] decomp: clarify names in advance_alternate_camera_transition domain_0_value_2 -> CAMERA_TRANSITION_KIND_STORED_FOCUS_ORBIT: The bound source tests cam_trans_state.kind. Retail 0x001ecd68 loads its byte from 0x001871b2; 0x001ecd6c-0x001ecd70 compares it with 2. On equality, 0x001ecd78-0x001ecd88 copies the stored focus at 0x0013f3d0, 0x001ecd90-0x001ecda8 copies orbit axes from transition +0x20/+0x30, and 0x001ecdb8/0x001ecdd8 cross those axes and compute destination orbit angles/distance from target_camera +0x30 relative to that stored focus. The original Ghidra decompilation independently shows this same mode-two stored-focus orbit derivation. The other branch copies target_camera +0x30 as focus and normalizes hero axes, confirming that this is a camera transition kind distinguished by its stored-focus orbit behavior, unrelated to the supplied hero enum domains. --- src/camera/advance_alternate_camera_transition.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/camera/advance_alternate_camera_transition.c b/src/camera/advance_alternate_camera_transition.c index 81cdee2b1d..49d5a1ffa4 100644 --- a/src/camera/advance_alternate_camera_transition.c +++ b/src/camera/advance_alternate_camera_transition.c @@ -38,6 +38,9 @@ int advance_alternate_camera_transition(char *target_camera, struct CameraOrbit *orbit) __asm__("FUN_001eccd8"); int advance_alternate_camera_transition(char *target_camera, struct CameraOrbit *orbit) { + enum { + CAMERA_TRANSITION_KIND_STORED_FOCUS_ORBIT = 2 + }; CameraVector orbit_angles; CameraVector forward_axis; CameraVector horizontal_axis; @@ -66,7 +69,7 @@ int advance_alternate_camera_transition(char *target_camera, struct CameraOrbit } step = 1.0f / cosine_interpolate( 1.0f, (f32)orbit->start_count, (f32)orbit->frames * orbit->frame_step); - if (cam_trans_state.kind == 2) { + if (cam_trans_state.kind == CAMERA_TRANSITION_KIND_STORED_FOCUS_ORBIT) { qcopy(&focus_position, D_0013F3D0); qcopy(&forward_axis, orbit->forward); qcopy(&vertical_axis, orbit->up); From 8b7272a4773d5fb1551b45dc40f82ace7a13e40e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:11:58 +0000 Subject: [PATCH 1444/1502] decomp: clarify names in novalis_elevator_update domain_0_value_0 -> NOVALIS_ELEVATOR_UNINITIALIZED: Retail 0x002ba094 loads the byte at moby+0x20 and 0x002ba098 skips setup when nonzero. Its zero branch 0x002ba0a0-0x002ba130 initializes private fields, copies configured command from elevator_vars+0xA0 to moby+0xBC, selects initial progress and path endpoint, clears timers/motion, and resets the voice slot. Original Ghidra and authoritative C both show this as the one-time initialization guard, distinct from the command selector. domain_1_value_1 -> NOVALIS_ELEVATOR_INITIALIZED: Retail 0x002ba10c loads a0=1 and 0x002ba120 stores that byte to moby+0x20 after initial path position, progress and timer setup. The same byte is tested at 0x002ba094-0x002ba098 to bypass this block on subsequent updates. Original Ghidra writes param_1+0x20=1 and authoritative C writes MOBY(moby)->state=1; this marks completion of elevator setup, separate from path command at +0xBC. --- src/overlays/shared/props/novalis_elevator.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/props/novalis_elevator.c b/src/overlays/shared/props/novalis_elevator.c index 7d57548099..9bb1710463 100644 --- a/src/overlays/shared/props/novalis_elevator.c +++ b/src/overlays/shared/props/novalis_elevator.c @@ -31,6 +31,10 @@ void novalis_elevator_update(unsigned char *moby) { NOVALIS_ELEVATOR_WAIT_AT_PATH_START = 1, NOVALIS_ELEVATOR_TRAVERSE_PATH = 2 }; + enum { + NOVALIS_ELEVATOR_UNINITIALIZED = 0, + NOVALIS_ELEVATOR_INITIALIZED = 1 + }; char *elevator_vars = ((char *)MOBY(moby)->pvars); char *path; float orig[4], delta[4], segment_offset[4]; @@ -71,7 +75,7 @@ void novalis_elevator_update(unsigned char *moby) { } qcopy(orig, &MOBY(moby)->pos); fast_dec_timer_s16(elevator_vars + 0xBA); - if (MOBY(moby)->state == 0) { + if (MOBY(moby)->state == NOVALIS_ELEVATOR_UNINITIALIZED) { float f; char *pts; elevator_vars[0x28] = 4; @@ -88,7 +92,7 @@ void novalis_elevator_update(unsigned char *moby) { *(short *)(elevator_vars + 0xBA) = 0; *(int *)(elevator_vars + 0xA8) = 0; *(int *)(elevator_vars + 0xBC) = 0; - MOBY(moby)->state = 1; + MOBY(moby)->state = NOVALIS_ELEVATOR_INITIALIZED; MOBY(moby)->update_dist = 0xFF; MOBY(moby)->draw_dist = 0xFF; *(int *)(elevator_vars + 0xC4) = -1; From 213103db6841177fa7dba2913496fd7c399746d8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:11:59 +0000 Subject: [PATCH 1445/1502] decomp: clarify names in elevator_update domain_0_value_0 -> ELEVATOR_MOBY_STATE_UNINITIALIZED: Retail 0030350c loads the moby state byte at s3+0x20; 00303510 skips initialization when it is nonzero. The zero path at 00303518-003035a8 initializes elevator variables, copies the configured command from vars+0xA0 to moby+0xBC, sets progress and initial path-node position, clears timers and motion increments, sets visibility distances and invalidates the voice slot. Original Ghidra likewise guards this setup with *(char *)(param_1+0x20)==0. This proves an uninitialized moby state, separate from the travel command selector at +0xBC. domain_1_value_1 -> ELEVATOR_MOBY_STATE_INITIALIZED: Within the zero-state initialization path, retail 00303584 loads a0=1 and 00303598 stores it to the same moby state byte at s3+0x20 tested at 0030350c-00303510. This follows initial path-position selection/copy at 00303538-0030357c and clearing timers and motion state at 00303580-00303590; subsequent updates with this nonzero state skip that setup. Original Ghidra writes *(undefined1 *)(param_1+0x20)=1 in that block. The value records completed initialization, not path-start command 1 at moby+0xBC. --- src/overlays/l09/mobys/elevator.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l09/mobys/elevator.c b/src/overlays/l09/mobys/elevator.c index 487f4dfd4a..9fac9c0ca6 100644 --- a/src/overlays/l09/mobys/elevator.c +++ b/src/overlays/l09/mobys/elevator.c @@ -39,6 +39,10 @@ void elevator_update(unsigned char *moby) { ELEVATOR_STATE_AT_PATH_START = 1, ELEVATOR_STATE_MOVING = 2 }; + enum { + ELEVATOR_MOBY_STATE_UNINITIALIZED = 0, + ELEVATOR_MOBY_STATE_INITIALIZED = 1 + }; char *elevator_vars = *(char **)(moby + 0x78); char *path; float orig[4], delta[4], segment_offset[4]; @@ -66,7 +70,7 @@ void elevator_update(unsigned char *moby) { } qcopy(orig, moby + 0x10); fast_dec_timer_s16(elevator_vars + 0xBA); - if (MOBY(moby)->state == 0) { + if (MOBY(moby)->state == ELEVATOR_MOBY_STATE_UNINITIALIZED) { float f; char *pts; elevator_vars[0x28] = 4; @@ -83,7 +87,7 @@ void elevator_update(unsigned char *moby) { *(short *)(elevator_vars + 0xBA) = 0; *(int *)(elevator_vars + 0xA8) = 0; *(int *)(elevator_vars + 0xBC) = 0; - MOBY(moby)->state = 1; + MOBY(moby)->state = ELEVATOR_MOBY_STATE_INITIALIZED; MOBY(moby)->update_dist = 0xFF; MOBY(moby)->draw_dist = 0xFF; *(int *)(elevator_vars + 0xC4) = -1; From 880f2139a7f7dd0d9e5803934b4e2e8a1f3e2e07 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:11:59 +0000 Subject: [PATCH 1446/1502] decomp: clarify names in hovering_rocket_attacker_update domain_0_value_5 -> WAIT_TO_MOVE_TO_TABLE_POINT: Initialization at 002c26b8-002c26d4 selects 5 when pvars+D4 is not -1 and stores it to moby+0x20. The outer switch reads that same byte at 002c25e4; its existing WAIT_TO_MOVE_TO_TABLE_POINT=5 branch at 002c26f8 waits on B4 before entering table-point movement. This reuses the outer-state member, not command member SELECT_ATTACK_RESTART_OR_EXIT. domain_1_value_2 -> TRACK_TARGET_BEFORE_ATTACK: 002c26c4-002c26d4 selects 2 for D4==-1 during initialization and stores it to moby+0x20, the byte read by the outer switch at 002c25e4. Existing TRACK_TARGET_BEFORE_ATTACK=2 at 002c2828-002c28c8 computes target XY yaw and gates attack entry. The destination is the same outer-state domain, not the command byte at +BC. domain_2_value_6 -> MOVE_TO_TABLE_POINT: WAIT_TO_MOVE_TO_TABLE_POINT at 002c26f8-002c270c waits while pvars+B4 equals 2, otherwise loads 6 at 002c2704 and branches to the store at 002c2d08 into moby+0x20. The outer switch reads this byte and existing MOVE_TO_TABLE_POINT=6 at 002c2710-002c2824 approaches the D4-indexed table point. domain_3_value_2 -> TRACK_TARGET_BEFORE_ATTACK: After table-point distance<0.1 and movement scalar<0.01 checks at 002c27cc-002c27f8, 002c281c loads 2 and 002c2820 branches to 002c2d08 to store moby+0x20, clearing command at 002c2824. Thus arrival enters the outer switch's established TRACK_TARGET_BEFORE_ATTACK=2, whose branch computes and approaches target XY yaw at 002c2828-002c2888. domain_4_value_4 -> UPDATE_ATTACK_SEQUENCE: The TRACK_TARGET_BEFORE_ATTACK branch at 002c288c-002c28c8 passes the B4 gate, resets EC, selects command/animation 1 and reaches 002c2d04-002c2d08, loading 4 and storing moby+0x20. This is the same byte used by the outer switch; established UPDATE_ATTACK_SEQUENCE=4 at 002c28cc performs tracking and dispatches the separate command byte +BC at 002c293c. domain_5_value_2 -> TRACK_TARGET_BEFORE_ATTACK: In WAIT_TO_COMPLETE_ATTACK_EXIT_SEQUENCE, 002c2bb4-002c2bec waits for animation completion, checks B4==2, restores animation 0 and stores s0=2 to moby+0x20 at 002c2bec; command is cleared separately at 002c2bf4. The state byte is read by the outer switch at 002c25e4, so this reuses TRACK_TARGET_BEFORE_ATTACK=2 rather than an equal-valued command constant. domain_6_value_4 -> UPDATE_ATTACK_SEQUENCE: WAIT_TO_RESUME_ATTACK_SEQUENCE at 002c2cd0-002c2d08 waits for animation completion and restores animation from command +BC, then loads 4 at 002c2d04 and writes moby+0x20 at 002c2d08. This is the outer switch selector read at 002c25e4, whose existing UPDATE_ATTACK_SEQUENCE=4 branch tracks target yaw and resumes the command-driven attack sequence. --- src/overlays/l13/mobys/hovering_rocket_attacker.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l13/mobys/hovering_rocket_attacker.c b/src/overlays/l13/mobys/hovering_rocket_attacker.c index 91d72c746e..4a7471c613 100644 --- a/src/overlays/l13/mobys/hovering_rocket_attacker.c +++ b/src/overlays/l13/mobys/hovering_rocket_attacker.c @@ -147,9 +147,9 @@ void hovering_rocket_attacker_update(unsigned char *moby) { moby_data->rocket0 = create_attached_rocket(moby, 0); moby_data->rocket1 = create_attached_rocket(moby, 1); if (moby_data->unkD4 != -1) - MOBY(moby)->state = 5; + MOBY(moby)->state = WAIT_TO_MOVE_TO_TABLE_POINT; else - MOBY(moby)->state = 2; + MOBY(moby)->state = TRACK_TARGET_BEFORE_ATTACK; moby_data->unk100[0] = random_angle_radians(); moby_data->unk100[2] = random_angle_radians(); moby_data->unk100[3] = random_angle_radians(); @@ -159,7 +159,7 @@ void hovering_rocket_attacker_update(unsigned char *moby) { if (moby_data->unkB4 == 2) return; MOBY(moby)->command = 0; - MOBY(moby)->state = 6; + MOBY(moby)->state = MOVE_TO_TABLE_POINT; break; case MOVE_TO_TABLE_POINT: index = moby_data->unkD4 * 128; @@ -180,7 +180,7 @@ void hovering_rocket_attacker_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, 10); MOBY(moby)->command = 0; - MOBY(moby)->state = 2; + MOBY(moby)->state = TRACK_TARGET_BEFORE_ATTACK; } break; case TRACK_TARGET_BEFORE_ATTACK: @@ -199,7 +199,7 @@ void hovering_rocket_attacker_update(unsigned char *moby) { MOBY(moby)->command = 1; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, 0); - MOBY(moby)->state = 4; + MOBY(moby)->state = UPDATE_ATTACK_SEQUENCE; break; case UPDATE_ATTACK_SEQUENCE: moby_yaw = (float *)&MOBY(moby)->rot.z; @@ -294,7 +294,7 @@ void hovering_rocket_attacker_update(unsigned char *moby) { if (moby_data->unkB4 == 2) { if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, 2); - MOBY(moby)->state = 2; + MOBY(moby)->state = TRACK_TARGET_BEFORE_ATTACK; MOBY(moby)->command = 0; break; } @@ -336,7 +336,7 @@ void hovering_rocket_attacker_update(unsigned char *moby) { return; if (MOBY(moby)->prev_seq != MOBY(moby)->command) blend_moby_animation(moby, MOBY(moby)->command, 0, 10); - MOBY(moby)->state = 4; + MOBY(moby)->state = UPDATE_ATTACK_SEQUENCE; break; } } From 662b7e2c9d0723982e639c105e20b7281353a9a0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:11:59 +0000 Subject: [PATCH 1447/1502] decomp: clarify names in is_moby_in_state_one domain_0_value_1 -> NANOTECH_BALL_STATE_FOLLOW_OWNER: At 0x002d8128 lbu v0,0x20(a0) reads the input Moby.state byte; xori 1 at 0x002d812c and sltiu 1 at 0x002d8134 implement equality to 1, agreeing with original retail Ghidra. The checked retail draw caller at 0x002d9810 passes its unchanged param_1 to FUN_002d8128 and gates owner-basis quad rendering. Authoritative src/overlays/shared/pickups/nanotech_ball.c SHA-256 c3c55c0cecea568fd711663c1ee5144a9700511f7742d0e2471180c947aa5442 defines NANOTECH_BALL_STATE_FOLLOW_OWNER = 1 in nanotech_ball_update, switches on that same Moby.state field, copies owner->pos into moby->pos in this state, and transitions to DETACHED_PICKUP when owner state is negative or owner == moby. Thus reuse the established nanotech ball state member, not unrelated Hero enum members of value 1. --- src/overlays/shared/pickups/nanotech_ball.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/pickups/nanotech_ball.c b/src/overlays/shared/pickups/nanotech_ball.c index b4279173c9..82138de543 100644 --- a/src/overlays/shared/pickups/nanotech_ball.c +++ b/src/overlays/shared/pickups/nanotech_ball.c @@ -1006,7 +1006,10 @@ float D_L18_00161E2C = 1.125f; int is_moby_in_state_one(unsigned char *moby) __asm__("FUN_L00_002d8128"); int is_moby_in_state_one(unsigned char *moby) { - return MOBY(moby)->state == 1; + enum { + NANOTECH_BALL_STATE_FOLLOW_OWNER = 1 + }; + return MOBY(moby)->state == NANOTECH_BALL_STATE_FOLLOW_OWNER; } /* Creates a class 0x326 moby linked to p at p's position; 0 when p's state is negative. */ From 0322170770fba9157d2cfd2068f366984ef7c012 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:11:59 +0000 Subject: [PATCH 1448/1502] decomp: clarify names in red_ship_1_update domain_0_value_2 -> RED_SHIP_WAIT_FOR_PATH: Source assigns MOBY(moby)->state=2 when pm+0x14 path id is -1. Retail 0x0029DEB8-0x0029DED0 tests that id and stores 2 at s3+0x20, the same byte dispatched at 0x0029DD30-0x0029DD5C. Its existing RED_SHIP_WAIT_FOR_PATH branch at 0x0029E144 waits for a valid path id before returning to initialization. domain_1_value_3 -> RED_SHIP_WAIT_FOR_MOVEMENT_TIMER: After spline initialization retail 0x0029E120-0x0029E130 reads the signed pvars+0x12C movement timer and stores 3 at moby+0x20 if positive. Dispatch of this same byte sends 3 to 0x0029E19C-0x0029E1A8, which decrements that timer and then stores movement state 1. This matches the existing RED_SHIP_WAIT_FOR_MOVEMENT_TIMER case. domain_2_value_1 -> RED_SHIP_FOLLOW_PATH_SPLINE: When the initialization timer is not positive, retail 0x0029E134-0x0029E140 clears pvars+0x14A and writes 1 to moby+0x20. The same state byte is read at 0x0029DD30 and value 1 branches to 0x0029E1B4, where nodes advance and the Hermite spline is evaluated through 0x0029E29C. This is the existing RED_SHIP_FOLLOW_PATH_SPLINE case. domain_3_value_0 -> RED_SHIP_INITIALIZE: Within the existing RED_SHIP_WAIT_FOR_PATH case, retail 0x0029E144-0x0029E150 tests path id at s4+0x14 against -1 and writes zero to moby+0x20 when a path is available. The dispatch 0x0029DD30-0x0029DD44 reads the identical byte and routes zero to initialization at 0x0029DD6C, which sets up the path descriptor and spline. Reuse RED_SHIP_INITIALIZE. domain_4_value_1 -> RED_SHIP_FOLLOW_PATH_SPLINE: In the existing RED_SHIP_WAIT_FOR_MOVEMENT_TIMER branch, retail 0x0029E19C-0x0029E1A8 calls the decrement helper on pvars+0x12C and writes s0=1 to moby+0x20 on completion; s0 was set at 0x0029DD24. Dispatch at 0x0029DD30-0x0029DD34 sends this byte value 1 to the spline movement branch at 0x0029E1B4, matching RED_SHIP_FOLLOW_PATH_SPLINE. --- src/overlays/l03/mobys/red_ship_1.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/l03/mobys/red_ship_1.c b/src/overlays/l03/mobys/red_ship_1.c index 31362cbad0..304a5309fb 100644 --- a/src/overlays/l03/mobys/red_ship_1.c +++ b/src/overlays/l03/mobys/red_ship_1.c @@ -645,7 +645,7 @@ void red_ship_1_update(char *moby) { random_float_between(-1.0f, 1.0f) * spline_moby_pvars->unk144 / 1000.0f; } if (*(int *)(pm + 0x14) == -1) { - MOBY(moby)->state = 2; + MOBY(moby)->state = RED_SHIP_WAIT_FOR_PATH; break; } moby_position = moby + 0x10; @@ -702,15 +702,15 @@ void red_ship_1_update(char *moby) { compute_sampled_spline_path_lengths( pm, 0, moby, spline_moby_pvars->unk104, spline_moby_pvars->unk108); if (spline_moby_pvars->timer_12C > 0) { - MOBY(moby)->state = 3; + MOBY(moby)->state = RED_SHIP_WAIT_FOR_MOVEMENT_TIMER; } else { spline_moby_pvars->unk14A = 0; - MOBY(moby)->state = 1; + MOBY(moby)->state = RED_SHIP_FOLLOW_PATH_SPLINE; } break; case RED_SHIP_WAIT_FOR_PATH: if (*(int *)(pm + 0x14) != -1) { - MOBY(moby)->state = 0; + MOBY(moby)->state = RED_SHIP_INITIALIZE; } voice_slot_index = spline_moby_pvars->unk150; if (voice_slot_index != -1) { @@ -723,7 +723,7 @@ void red_ship_1_update(char *moby) { break; case RED_SHIP_WAIT_FOR_MOVEMENT_TIMER: if (fast_dec_timer_s16(&spline_moby_pvars->timer_12C)) { - MOBY(moby)->state = 1; + MOBY(moby)->state = RED_SHIP_FOLLOW_PATH_SPLINE; } break; case RED_SHIP_FOLLOW_PATH_SPLINE: From 03ef8a5da323d114c131c44b6b6af56a4978d084 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:11:59 +0000 Subject: [PATCH 1449/1502] decomp: clarify names in spiderbot_update domain_0_value_1 -> SPIDERBOT_CIRCULAR_MOTION: Authoritative spiderbot.c SHA-256 37d99cce97fbf795834756605f2e6ded6bc2c104f9ebf2feabbb6b00ef59ca68 already defines SPIDERBOT_CIRCULAR_MOTION=1 for switch(MOBY(moby)->state). Retail 002a6f30 stores 1 through sb a1,0x20(s4); 002a6eb0 reads that exact byte and 002a6eb4 dispatches 1 to 002a6f7c. That branch advances phase, rotates a fixed radius and adds the saved origin at 002a7038-002a7060. Original Ghidra also shows this state write and dispatch. This reuses the same state domain, not the separate control at s3+0x20. domain_1_value_2 -> SPIDERBOT_ARC_OSCILLATION: The authoritative source already defines SPIDERBOT_ARC_OSCILLATION=2 on the MOBY(moby)->state switch. Retail 002a6f4c loads 2 and 002a6f54 stores it into 0x20(s4), the byte loaded at 002a6eb0 and tested against 2 at 002a6ed8 to enter 002a70c4. This branch computes old/new cosine-driven angles at 002a70f4-002a719c, rotates the negative-radius vector at 002a7200 and writes origin plus offset at 002a7228. Original Ghidra confirms identical byte storage and branch behavior, proving reuse of the existing current-state member. domain_2_value_3 -> SPIDERBOT_LINEAR_OSCILLATION: The authoritative source defines SPIDERBOT_LINEAR_OSCILLATION=3 for this same MOBY(moby)->state switch. Retail 002a6f48 loads 3 on the control<3 path and 002a6f68 stores it at 0x20(s4); 002a6eb0 reads that state byte and 002a6ee0 dispatches 3 to 002a7288. The branch calculates cosine times configured displacement before/after phase advance (002a72a0,002a72f8), builds a spherical offset at 002a7340 and adds origin before storing position at 002a736c. Original Ghidra agrees, proving the existing linear-oscillation state member applies to this assignment. --- src/overlays/shared/enemies/spiderbot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/enemies/spiderbot.c b/src/overlays/shared/enemies/spiderbot.c index 6b89e566ce..15fa0a460a 100644 --- a/src/overlays/shared/enemies/spiderbot.c +++ b/src/overlays/shared/enemies/spiderbot.c @@ -96,13 +96,13 @@ void spiderbot_update(unsigned char *moby) { MOBY(moby)->anim_speed = moby_data->unk30 / 1.5f; moby_data->unk28 = moby_data->unk28 * 0.017453292f; if (moby_data->unk20 == 0) { - MOBY(moby)->state = 1; + MOBY(moby)->state = SPIDERBOT_CIRCULAR_MOTION; moby_data->unk2C = MOBY(moby)->rot.z; } else if (moby_data->unk20 >= 3) { - MOBY(moby)->state = 2; + MOBY(moby)->state = SPIDERBOT_ARC_OSCILLATION; moby_data->unk2C = MOBY(moby)->rot.z; } else { - MOBY(moby)->state = 3; + MOBY(moby)->state = SPIDERBOT_LINEAR_OSCILLATION; } break; case SPIDERBOT_CIRCULAR_MOTION: { From 3331b4d659670cf4313730a767a63e28f2a8707a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:14:23 +0000 Subject: [PATCH 1450/1502] overlay: name update_hero_item_moby_flags --- include/rnc/overlay/shared/hero/set_hero_animation.h | 2 +- src/overlays/l15/mobys/quartu_cutscene_trigger.c | 3 ++- src/overlays/shared/cutscenes/update_cutscene_playback.c | 4 ++-- src/overlays/shared/hero/hero_idle_sequence.c | 4 ++-- src/overlays/shared/hero/set_hero_animation.c | 4 ++-- src/overlays/shared/vendor/vendor_menu.c | 8 ++++---- 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/rnc/overlay/shared/hero/set_hero_animation.h b/include/rnc/overlay/shared/hero/set_hero_animation.h index 75f548c6f4..400adfb4fb 100644 --- a/include/rnc/overlay/shared/hero/set_hero_animation.h +++ b/include/rnc/overlay/shared/hero/set_hero_animation.h @@ -13,7 +13,7 @@ void show_health_hud(void) __asm__("FUN_L00_00234e00"); s32 get_ammo(s32) __asm__("FUN_L00_00233e98"); s32 get_hero_target_pose_status(void) __asm__("FUN_L00_00233f38"); void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); -void FUN_L00_002330d0(void); +void update_hero_item_moby_flags(void) __asm__("FUN_L00_002330d0"); s32 use_ammo(s32, s32) __asm__("FUN_L00_00233db8"); #endif /* LOMBYTE_RNC_OVERLAY_SHARED_HERO_SET_HERO_ANIMATION_H */ diff --git a/src/overlays/l15/mobys/quartu_cutscene_trigger.c b/src/overlays/l15/mobys/quartu_cutscene_trigger.c index fa7ca3bdf6..51b7445556 100644 --- a/src/overlays/l15/mobys/quartu_cutscene_trigger.c +++ b/src/overlays/l15/mobys/quartu_cutscene_trigger.c @@ -11,6 +11,7 @@ #include "rnc/overlay/shared/game/queue_planet_unlock_message.h" #include "rnc/overlay/shared/game/unlock_planet.h" #include "rnc/overlay/shared/hero/set_hero_animation.h" +void update_hero_item_moby_flags(void) __asm__("FUN_L00_002330d0"); void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); #include "rnc/rendering/clip_volume.h" @@ -76,7 +77,7 @@ void quartu_cutscene_trigger_update(struct Moby *moby) { if (D_L15_0015F5C4 != 2) { start_scene(4); moby->state = CUTSCENE_TRIGGER_FINALIZE_AND_SAVE; - FUN_L00_002330d0(); + update_hero_item_moby_flags(); if (trigger_data->unk4 != -1) { char *o = D_L15_001600EC + (trigger_data->unk4 << 7); set_race_camera(o + 0x30, o + 0x70, 0, 1); diff --git a/src/overlays/shared/cutscenes/update_cutscene_playback.c b/src/overlays/shared/cutscenes/update_cutscene_playback.c index 80e6aed93a..fcc4644961 100644 --- a/src/overlays/shared/cutscenes/update_cutscene_playback.c +++ b/src/overlays/shared/cutscenes/update_cutscene_playback.c @@ -498,7 +498,7 @@ extern float D_L00_0016CAF0_lui __asm__("D_L00_0016CAF0") NOT_SDA; extern O_298b18 *D_L00_0015FFDC_298b18 __asm__("D_L00_0015FFDC"); extern C_298b18 D_L00_0016C860_298b18 __asm__("D_L00_0016C860") NOT_SDA; void select_level_vu_chain(void) __asm__("FUN_002335a0"); -void FUN_L00_002330d0(void); +void update_hero_item_moby_flags(void) __asm__("FUN_L00_002330d0"); void set_race_camera(void *, void *, int, int) __asm__("FUN_L00_00216f90"); void process_menu_entry(F_298b18 *, void *, int) __asm__("FUN_00216c48"); void music_set_active_track_value(int) __asm__("FUN_L00_00265880"); @@ -534,7 +534,7 @@ void finish_cutscene(void) { if (2.0f < hero_candidate_z && absolute_float(hero.motion.pos.f[2] - hero_candidate_z) < 4.5f) hero.motion.pos.f[2] = hero_candidate_z; hero.unk20A5 = 0; - FUN_L00_002330d0(); + update_hero_item_moby_flags(); if (D_L00_0016C860_298b18.x46) { f = probe_ground_height(D_L00_0016C860_298b18.v, 0, 0.5f); if (2.0f < f && absolute_float(D_L00_0016C860_298b18.x18 - f) < 2.0f) diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index be54b90a3e..bbf4d8729f 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -1915,7 +1915,7 @@ extern void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); extern void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); -extern void FUN_L00_002330d0(void); +extern void update_hero_item_moby_flags(void) __asm__("FUN_L00_002330d0"); extern void apply_hero_vertical_oscillation(void) __asm__("FUN_L00_002078a8"); extern void apply_hero_rotation_oscillation(void) __asm__("FUN_L00_002079e8"); extern void offset_hero_position_against_gravity(void *, void *, float) __asm__("FUN_L00_002336e8"); @@ -1932,7 +1932,7 @@ void update_hero_moby(void) { if (hero.unk20A5) { set_hero_item_moby_flag_bit0(); } else { - FUN_L00_002330d0(); + update_hero_item_moby_flags(); } qcopy(&hero.moby->pos, &hero.motion.pos); apply_hero_vertical_oscillation(); diff --git a/src/overlays/shared/hero/set_hero_animation.c b/src/overlays/shared/hero/set_hero_animation.c index eb53b21b1a..b47fc31b37 100644 --- a/src/overlays/shared/hero/set_hero_animation.c +++ b/src/overlays/shared/hero/set_hero_animation.c @@ -750,9 +750,9 @@ void set_hero_item_moby_flag_bit0(void) { block, as retail re-forms it from the saved %hi before each one. */ /* Ported from rac1-decomp (src/overlays/shared/help_00232560.c: func_L00_00233950), where it is exact; names translated to the US level program. */ -void FUN_L00_002330d0(void); +void update_hero_item_moby_flags(void) __asm__("FUN_L00_002330d0"); -void FUN_L00_002330d0(void) { +void update_hero_item_moby_flags(void) { struct Hero *hero_item_flag_clear_state = &hero; struct Hero *blk2; struct Hero *blk3; diff --git a/src/overlays/shared/vendor/vendor_menu.c b/src/overlays/shared/vendor/vendor_menu.c index ee3fee1a6d..30fffbf1cf 100644 --- a/src/overlays/shared/vendor/vendor_menu.c +++ b/src/overlays/shared/vendor/vendor_menu.c @@ -504,7 +504,7 @@ typedef struct { float x, y, z, w; } __attribute__((aligned(16))) Vec4_29ab70; -extern void FUN_L00_002330d0(void); +extern void update_hero_item_moby_flags(void) __asm__("FUN_L00_002330d0"); extern void decrement_resource_counter(void) __asm__("FUN_001ff768"); extern void music_unpause(void) __asm__("FUN_00216088"); extern int vendor_close_hero_local_offset_gp __asm__("D_L00_00161070") __attribute__((sda)); @@ -525,7 +525,7 @@ void close_vendor_menu(int exit_cutscene_completed) { D_L00_0015F5C4 = 0; hero_set_state(HERO_STATE_IDLE, 1); hero.unk20A5 = 0; - FUN_L00_002330d0(); + update_hero_item_moby_flags(); if (*(int *)(vendor_state_base + 0x40) == 0) { transform_vector_by_basis(&world_position, &vendor_close_hero_local_offset_gp, @@ -637,7 +637,7 @@ void start_vendor_exit_cutscene(void) { } extern int D_L00_0015F5D8; -void FUN_L00_002330d0(void); +void update_hero_item_moby_flags(void) __asm__("FUN_L00_002330d0"); void restore_hero_after_vendor_exit_cutscene(void) __asm__("FUN_L00_0029af80"); void restore_hero_after_vendor_exit_cutscene(void) { @@ -648,7 +648,7 @@ void restore_hero_after_vendor_exit_cutscene(void) { D_L00_0015F5C4 = 0; hero_set_state(HERO_STATE_IDLE, 1); hero.unk20A5 = 0; - FUN_L00_002330d0(); + update_hero_item_moby_flags(); vendor_state_base = (char *)&vendor_menu; transform_vector_by_basis(&world_position, &vendor_exit_hero_local_offset_gp, From 082c6059281507469921e65449e2a96d16fa6e7a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:14:23 +0000 Subject: [PATCH 1451/1502] decomp: clarify names in explosion_light_update domain_0_value_0 -> EXPLOSION_LIGHT_STATE_UNINITIALIZED: The authoritative source tests MOBY(moby)->state == 0 before initializing anchor_pos, light_slot=-1, period timers, normalized initial colors, radius and attachment. Retail 002d3a50 loads the moby state byte at s1+0x20 and 002d3a54 skips this entire setup when nonzero; 002d3a64-002d3b48 perform setup. Original Ghidra shows the same zero-state initialization block. The supplied mine_camera_blast source creates class 0x27F and assigns state zero, confirming this is its uninitialized state. domain_1_value_1 -> EXPLOSION_LIGHT_STATE_INITIALIZED: Retail 002d3b40 loads 1 and 002d3b4c stores it into the same moby state byte s1+0x20 after initialization of timers, colors, radius, attachment and rate magnitudes; original Ghidra likewise assigns *(iVar12+0x20)=1 at the end of the initialization block. On later calls 002d3a50-002d3a58 skip that block for this nonzero state. Source then processes command/start-delay at 002d3b50-002d3b60, proving initialized rather than necessarily active or light-slot allocated. --- src/overlays/shared/rendering/effects/explosion_light.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/rendering/effects/explosion_light.c b/src/overlays/shared/rendering/effects/explosion_light.c index 915d08f08d..63bfbbc1b6 100644 --- a/src/overlays/shared/rendering/effects/explosion_light.c +++ b/src/overlays/shared/rendering/effects/explosion_light.c @@ -147,6 +147,10 @@ void explosion_light_update(unsigned char *moby) __asm__("FUN_L00_002d3a10"); /* Moby class 639 */ void explosion_light_update(unsigned char *moby) { + enum { + EXPLOSION_LIGHT_STATE_UNINITIALIZED = 0, + EXPLOSION_LIGHT_STATE_INITIALIZED = 1 + }; ExplosionLightVars *animated_point_light_vars; Vx tp; Vx base_position; @@ -166,7 +170,7 @@ void explosion_light_update(unsigned char *moby) { radius_reset_this_update = 0; if (animated_point_light_vars == 0) return; - if (MOBY(moby)->state == 0) { + if (MOBY(moby)->state == EXPLOSION_LIGHT_STATE_UNINITIALIZED) { unsigned char b1c; MOBY(moby)->update_dist = 0xFF; b1c = animated_point_light_vars->start_delay; @@ -199,7 +203,7 @@ void explosion_light_update(unsigned char *moby) { if (animated_point_light_vars->radius_fall_rate < 0.0f) animated_point_light_vars->radius_fall_rate = -animated_point_light_vars->radius_fall_rate; - MOBY(moby)->state = 1; + MOBY(moby)->state = EXPLOSION_LIGHT_STATE_INITIALIZED; } if (MOBY(moby)->command != 0) { MOBY(moby)->command = MOBY(moby)->command - 1; From 0a28b4953dd8739d8833949a73628a7bf3534aa7 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:25:38 +0000 Subject: [PATCH 1452/1502] decomp: clarify names in robot_dog_update domain_0_value_1 -> ROBOT_DOG_WAIT_FOR_ACTIVATION: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c5c6c-002c5c74 stores state 1 during initialization after saving home; case 1 waits for path/group/clip/proximity activation or a nearby target. domain_10_value_4 -> ROBOT_DOG_CHASE_TARGET: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c63a8-002c6424 checks linked partner availability/release, clears the path index, initializes the chase timer and stores state 4; existing case 4 pursues selected target. domain_11_value_7 -> ROBOT_DOG_RETURN_HOME: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c663c-002c6660 observes animation flag bit 2 after melee, restores movement speed and stores state 7; existing case 7 steers toward saved home and uses the +0x244 cooldown. domain_12_value_1 -> ROBOT_DOG_WAIT_FOR_ACTIVATION: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c6734-002c675c compares XY distance to saved home against 1.0 and stores state 1 on arrival, selecting animation 1; existing case 1 waits for activation. domain_13_value_6 -> ROBOT_DOG_MELEE_ATTACK: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c6778-002c6804 checks that cooldown +0x244 is zero and target distance satisfies the same attack threshold, then stores state 6 and selects melee animation 5. domain_14_value_4 -> ROBOT_DOG_CHASE_TARGET: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c6828-002c684c calls falling motion on pvars+0x120 and stores state 4 when result & 0x60 is nonzero, selecting animation 3; existing case 4 steers and moves toward selected target. domain_15_value_0 -> ROBOT_DOG_INITIALIZE: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c6874-002c6890 waits for the helper to return nonzero, stores zero to moby+0x20 and clears pvars+0xC8; existing case 0 saves home and initializes movement, health and timers. domain_1_value_2 -> ROBOT_DOG_WAIT_FOR_PARTNER_RELEASE: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c5d78-002c5db8 stores state 2 when partner index +0x248 exists and path index +0x270 is -1; case 2 waits for the linked partner predicate before entering chase. domain_2_value_5 -> ROBOT_DOG_FOLLOW_PATH: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c5ea8-002c5eb0 clears path progress +0x278 and stores state 5 after activation; case 5 advances 16-byte path nodes at 002c6274-002c631c. domain_3_value_3 -> ROBOT_DOG_TURN_TO_TARGET: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c5edc-002c5f30 gates activation by target/home distance and height, then stores state 3; case 3 computes target XY bearing and spring-turns at 002c6004-002c6050. domain_4_value_4 -> ROBOT_DOG_CHASE_TARGET: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c5fb8-002c5fec initializes the chase timer and stores state 4 after the partner wait; case 4 turns toward selected target and moves forward at 002c60b0-002c613c. domain_5_value_4 -> ROBOT_DOG_CHASE_TARGET: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c6054-002c6098 checks animation flag bit 2, initializes the chase timer and stores state 4 after turning; case 4 steers and advances toward the selected target. domain_6_value_6 -> ROBOT_DOG_MELEE_ATTACK: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c617c-002c61fc compares target XY distance against the attack threshold and stores state 6, selecting animation 5; case 6 applies a forward melee effect at frame 25 within heading/height/distance gates. domain_7_value_7 -> ROBOT_DOG_RETURN_HOME: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c6220-002c6270 stores state 7 when target exceeds the saved-home activation radius or height gate; case 7 steers toward pvars+0x200 and exits within one unit. domain_8_value_1 -> ROBOT_DOG_WAIT_FOR_ACTIVATION: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c6320-002c6330 clears the completed path index to -1 and stores state 1; the existing case 1 implements activation waiting with an idle animation. domain_9_value_2 -> ROBOT_DOG_WAIT_FOR_PARTNER_RELEASE: This store targets moby+0x20, the same current-state byte loaded by the switch at 002c5c1c; the bound source switch already uses the corresponding ROBOT_DOG enum member. 002c635c-002c6394 tests remaining partner index +0x248 after path completion, selects animation 0 and stores state 2; case 2 waits on that linked partner. --- src/overlays/l03/mobys/robot_dog.c | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/overlays/l03/mobys/robot_dog.c b/src/overlays/l03/mobys/robot_dog.c index 20356a1061..d7030172bc 100644 --- a/src/overlays/l03/mobys/robot_dog.c +++ b/src/overlays/l03/mobys/robot_dog.c @@ -177,7 +177,7 @@ void robot_dog_update(char *moby) { case ROBOT_DOG_INITIALIZE: MOBY(moby)->flags |= 0x1000; qcopy(robot_dog_state->home, moby + 0x10); - MOBY(moby)->state = 1; + MOBY(moby)->state = ROBOT_DOG_WAIT_FOR_ACTIVATION; MOBY(moby)->shadow_range = 0x18; robot_dog_state->f20 = 1.0f; robot_dog_state->b29 = 0; @@ -209,7 +209,7 @@ void robot_dog_update(char *moby) { if (((unsigned char *)moby)[0x53] != 0) { blend_moby_animation(moby, 0, 0, 0); } - MOBY(moby)->state = 2; + MOBY(moby)->state = ROBOT_DOG_WAIT_FOR_PARTNER_RELEASE; } else if (((unsigned char *)moby)[0x53] != 1) { blend_moby_animation(moby, 1, 0, 0); } @@ -227,7 +227,7 @@ void robot_dog_update(char *moby) { (fast_vec_dist(&selected_target, moby + 0x10) < robot_dog_state->f274 && absolute_float(selected_target.pos[2] - MOBY(moby)->pos.z) < 4.0f)) { robot_dog_state->i278 = 0; - MOBY(moby)->state = 5; + MOBY(moby)->state = ROBOT_DOG_FOLLOW_PATH; if (((unsigned char *)moby)[0x53] != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } @@ -235,7 +235,7 @@ void robot_dog_update(char *moby) { } else if (random_integer_below(14) == 0 && fast_vec_dist(&selected_target, robot_dog_state->home) < robot_dog_state->f230 && absolute_float(selected_target.pos[2] - MOBY(moby)->pos.z) < 3.0f) { - MOBY(moby)->state = 3; + MOBY(moby)->state = ROBOT_DOG_TURN_TO_TARGET; if (((unsigned char *)moby)[0x53] != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(10)); } @@ -251,7 +251,7 @@ void robot_dog_update(char *moby) { ((unsigned char *)partner_moby)[0x20] == 0xFD || can_release_linked_robot_dog((struct Moby *)partner_moby)) { robot_dog_state->i23C = scale_game_frames((int)random_float_between(30.0f, 90.0f)); - MOBY(moby)->state = 4; + MOBY(moby)->state = ROBOT_DOG_CHASE_TARGET; if (((unsigned char *)moby)[0x53] != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } @@ -269,7 +269,7 @@ void robot_dog_update(char *moby) { 0.1f); if (((unsigned char *)moby)[0x70] & 2) { robot_dog_state->i23C = scale_game_frames((int)random_float_between(30.0f, 90.0f)); - MOBY(moby)->state = 4; + MOBY(moby)->state = ROBOT_DOG_CHASE_TARGET; if (((unsigned char *)moby)[0x53] != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } @@ -295,13 +295,13 @@ void robot_dog_update(char *moby) { if (target_distance < robot_dog_state->f234 * frame_time * 0.5f * FUN_L04_001f1978(40.0f) + robot_dog_state->f234 * frame_time * FUN_L04_001f1978(10.0f) + 1.5f) { - MOBY(moby)->state = 6; + MOBY(moby)->state = ROBOT_DOG_MELEE_ATTACK; if (((unsigned char *)moby)[0x53] != 5) { blend_moby_animation(moby, 5, 0, truncate_float_to_s32(FUN_L04_001f1978(10.0f))); } } else if (robot_dog_state->f230 < fast_vec_dist(&selected_target, robot_dog_state->home) || absolute_float(selected_target.pos[2] - MOBY(moby)->pos.z) > 3.0f) { - MOBY(moby)->state = 7; + MOBY(moby)->state = ROBOT_DOG_RETURN_HOME; } break; case ROBOT_DOG_FOLLOW_PATH: @@ -320,7 +320,7 @@ void robot_dog_update(char *moby) { robot_dog_state->i278++; } else { robot_dog_state->i270 = -1; - MOBY(moby)->state = 1; + MOBY(moby)->state = ROBOT_DOG_WAIT_FOR_ACTIVATION; if (((unsigned char *)moby)[0x53] != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } @@ -328,7 +328,7 @@ void robot_dog_update(char *moby) { if (((unsigned char *)moby)[0x53] != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } - MOBY(moby)->state = 2; + MOBY(moby)->state = ROBOT_DOG_WAIT_FOR_PARTNER_RELEASE; } } } @@ -341,7 +341,7 @@ void robot_dog_update(char *moby) { can_release_linked_robot_dog((struct Moby *)partner_moby)) { robot_dog_state->i270 = -1; robot_dog_state->i23C = scale_game_frames((int)random_float_between(30.0f, 90.0f)); - MOBY(moby)->state = 4; + MOBY(moby)->state = ROBOT_DOG_CHASE_TARGET; if (((unsigned char *)moby)[0x53] != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } @@ -382,7 +382,7 @@ void robot_dog_update(char *moby) { spawn_nearby_effect(selected_target.obj, moby, 1, at, push, 1.0f); } else if (((unsigned char *)moby)[0x70] & 2) { robot_dog_state->f1A4 = robot_dog_state->f234 * frame_time; - MOBY(moby)->state = 7; + MOBY(moby)->state = ROBOT_DOG_RETURN_HOME; if (((unsigned char *)moby)[0x53] != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(3)); } @@ -404,7 +404,7 @@ void robot_dog_update(char *moby) { forward_vector_or_path_point[2] = 0.0f; FUN_L00_00258b50(moby, &robot_dog_state->i180, forward_vector_or_path_point, push, 1.0f); if (vector_distance_xy(moby + 0x10, robot_dog_state->home) < 1.0f) { - MOBY(moby)->state = 1; + MOBY(moby)->state = ROBOT_DOG_WAIT_FOR_ACTIVATION; if (((unsigned char *)moby)[0x53] != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(3)); } @@ -413,7 +413,7 @@ void robot_dog_update(char *moby) { if (target_distance < robot_dog_state->f234 * frame_time * 0.5f * FUN_L04_001f1978(40.0f) + robot_dog_state->f234 * frame_time * FUN_L04_001f1978(10.0f) + 1.5f) { - MOBY(moby)->state = 6; + MOBY(moby)->state = ROBOT_DOG_MELEE_ATTACK; if (((unsigned char *)moby)[0x53] != 5) { blend_moby_animation( moby, 5, 0, truncate_float_to_s32(FUN_L04_001f1978(10.0f))); @@ -423,7 +423,7 @@ void robot_dog_update(char *moby) { break; case ROBOT_DOG_FALL_RECOVERY: if (step_moby_motion(moby, robot_dog_state->m120) & 0x60) { - MOBY(moby)->state = 4; + MOBY(moby)->state = ROBOT_DOG_CHASE_TARGET; if (((unsigned char *)moby)[0x53] != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } @@ -432,7 +432,7 @@ void robot_dog_update(char *moby) { goto low; case ROBOT_DOG_WAIT_TO_REINITIALIZE: if (FUN_L00_002dc9f0(moby, robot_dog_state->m120)) { - MOBY(moby)->state = 0; + MOBY(moby)->state = ROBOT_DOG_INITIALIZE; robot_dog_state->sC8 = 0; } break; From 38255d37c2dd9017461025c982b718574f60ed33 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:25:38 +0000 Subject: [PATCH 1453/1502] decomp: clarify names in cancel_moby_suction_and_save_state domain_0_value_16 -> FROG_STATE_SUCK_CANNON_HELD: Retail 0x002ea7dc loads the frog moby's state byte at s0+0x20; 0x002ea7e0 loads 16, 0x002ea7e4 compares that same state, and 0x002ea7ec writes 16 back to +0x20 while 0x002ea7f0 saves previous_state at +0xBC. The authoritative assigned function already compares previous_state against local FROG_STATE_SUCK_CANNON_HELD=0x10. frog_update switches on the same MOBY(moby)->state with that member, and adjacent grab/storage handlers save the prior state and assign that member to the same field. Thus this assignment reuses the established frog current-state constant, not an equal-valued hero or suction-record constant. --- src/overlays/shared/enemies/frog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/frog.c b/src/overlays/shared/enemies/frog.c index dc7e240b06..147776d5ac 100644 --- a/src/overlays/shared/enemies/frog.c +++ b/src/overlays/shared/enemies/frog.c @@ -1037,7 +1037,7 @@ s32 cancel_moby_suction_and_save_state(unsigned char *moby) { previous_state = MOBY(moby)->state; if (previous_state != FROG_STATE_SUCK_CANNON_HELD) { MOBY(moby)->command = previous_state; - MOBY(moby)->state = 0x10; + MOBY(moby)->state = FROG_STATE_SUCK_CANNON_HELD; } return helper_result; } From 98dc12bc752ddb09f3b53bfcabdd6e2c69ea9b85 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:25:38 +0000 Subject: [PATCH 1454/1502] decomp: clarify names in command_falling_platform_update domain_0_value_2 -> PLATFORM_TIMED_SWAY_BEFORE_FALL: Retail 00311360-00311384 tests command byte +0xBC, then 00311374 writes 2 to the platform's +0x20 state byte and loads pvars +0xBD into timer +0xAC. That same state byte selects the switch at 00311384-003113a4; case 2 at 00311538-003115d8 sways, decrements the timer and enters falling state 3. Reuse its existing local PLATFORM_TIMED_SWAY_BEFORE_FALL member; command bytes remain a separate domain. domain_1_value_1 -> PLATFORM_COMMAND_GATED_SWAY: Initialization at 003113ac-00311418 caches rotations and writes 1 to moby+0x20 at 0031140c. This is the byte loaded for the platform switch at 00311384. Its existing case PLATFORM_COMMAND_GATED_SWAY at 00311470-00311534 gates on command +0xBC==1 and applies sine/cosine offsets to saved rotations, proving the assignment uses that existing member. domain_2_value_5 -> PLATFORM_HEIGHT_RECOVERY_AND_SWAY: After the visited-item path lowers platform z by five at 00311444-00311458, a nonzero recovery flag pvars+0xBC causes 00311464-0031146c to write 5 to moby+0x20. The same byte selects the existing PLATFORM_HEIGHT_RECOVERY_AND_SWAY case at 003116f4-00311a58, restoring toward pvars+0xB8 and applying sway. Reuse that platform state member. domain_3_value_3 -> PLATFORM_TILT_AND_FALL: The timed-sway case calls the decrement helper on pvars+0xAC at 003115a8-003115b0 and, on expiry, 003115d0-003115d8 writes 3 to moby+0x20. The switch reads that same state byte; existing case PLATFORM_TILT_AND_FALL at 003115dc-00311684 increments tilt, lowers z and integrates vertical velocity. Thus this transition reuses PLATFORM_TILT_AND_FALL. domain_4_value_4 -> PLATFORM_PARENT_GATED_RECOVERY_SETUP: In the fall case 00311658-00311684 tests z below pvars+0xB8 minus 15, requires the recovery flag and clears vertical velocity before writing 4 to moby+0x20. That switch byte's existing PLATFORM_PARENT_GATED_RECOVERY_SETUP case at 00311698-003116f0 gates on parent fields, seeds velocity/phases and enters recovery state 5, proving the existing state member applies. domain_5_value_5 -> PLATFORM_HEIGHT_RECOVERY_AND_SWAY: Parent-gated setup at 00311698-003116d8 initializes vertical velocity and sway phases; 003116dc-003116e0 writes 5 to the platform state byte moby+0x20, then clears tilt and timer. The same state byte selects existing PLATFORM_HEIGHT_RECOVERY_AND_SWAY at 003116f4-00311a58, whose height recovery and hero-relative sway consume that setup. Reuse the existing member. --- src/overlays/l07/mobys/command_falling_platform.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l07/mobys/command_falling_platform.c b/src/overlays/l07/mobys/command_falling_platform.c index df6b03f1e0..7136f98264 100644 --- a/src/overlays/l07/mobys/command_falling_platform.c +++ b/src/overlays/l07/mobys/command_falling_platform.c @@ -92,7 +92,7 @@ void command_falling_platform_update(char *moby) { parent_data = *(char **)(parent + 0x78); } if (((unsigned char *)moby)[0xBC] == 2) { - MOBY(moby)->state = 2; + MOBY(moby)->state = PLATFORM_TIMED_SWAY_BEFORE_FALL; MOBY(moby)->command = 3; falling_platform_vars->unkAC = falling_platform_vars->unkBD; } @@ -108,7 +108,7 @@ void command_falling_platform_update(char *moby) { falling_platform_vars->saved_rot_x = MOBY(moby)->rot.x; falling_platform_vars->saved_rot_y = MOBY(moby)->rot.y; falling_platform_vars->unkC8 = -1; - MOBY(moby)->state = 1; + MOBY(moby)->state = PLATFORM_COMMAND_GATED_SWAY; MOBY(moby)->command = 0; if (((unsigned char *)moby)[0xB0] != 0xFF) { if (visited52[((unsigned char *)moby)[0xB0] + current_level_index * 16] != 0xFF) @@ -118,7 +118,7 @@ void command_falling_platform_update(char *moby) { mark_moby_for_removal(moby); return; } - MOBY(moby)->state = 5; + MOBY(moby)->state = PLATFORM_HEIGHT_RECOVERY_AND_SWAY; } break; case PLATFORM_COMMAND_GATED_SWAY: @@ -156,7 +156,7 @@ void command_falling_platform_update(char *moby) { parent_data[0x19D] = falling_platform_vars->unkBF; parent[0x20] = 12; } - MOBY(moby)->state = 3; + MOBY(moby)->state = PLATFORM_TILT_AND_FALL; break; case PLATFORM_TILT_AND_FALL: speed = 1.3962634f; @@ -175,7 +175,7 @@ void command_falling_platform_update(char *moby) { break; if (falling_platform_vars->unkBC != 0) { falling_platform_vars->fall_speed = 0.0f; - MOBY(moby)->state = 4; + MOBY(moby)->state = PLATFORM_PARENT_GATED_RECOVERY_SETUP; } else { mark_moby_for_removal(moby); return; @@ -188,7 +188,7 @@ void command_falling_platform_update(char *moby) { falling_platform_vars->fall_speed = random_float_between(frame_time, frame_time * 4.0f); falling_platform_vars->unkC0 = random_angle_radians(); falling_platform_vars->unkC4 = random_angle_radians(); - MOBY(moby)->state = 5; + MOBY(moby)->state = PLATFORM_HEIGHT_RECOVERY_AND_SWAY; MOBY(moby)->rot.x = 0.0f; MOBY(moby)->rot.y = 0.0f; falling_platform_vars->unkAC = 0; From 5442f793656dd292ac61cc57cde93fca854249ee Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:25:38 +0000 Subject: [PATCH 1455/1502] decomp: clarify names in update_planetbuster_maximus_guns domain_0_value_4 -> PLANETBUSTER_DROP_PARTS_AND_TRANSITION: Authoritative src/overlays/l12/mobys/planetbuster_maximus_part.c SHA-256 f7420efead61841176be88b50fc9e004758c7537b207f34fcc2133be9f57f206 defines PLANETBUSTER_DROP_PARTS_AND_TRANSITION=4 in planetbuster_maximus_part_update's switch on MOBY(moby)->state. Retail 003062d8..00306308 tests aggregate owner pvars+0x5FC depletion and D_L12_00161F04==0, then stores 4 to the saved owner argument+0x20 and resets command at +0xBC. Caller evidence request 825bcdf4ea4f46a684196cc43dbfe452 confirms 003069dc retains its argument in s2, 00306a44..00306a64 dispatches the same +0x20 state byte, and 00307278..0030727c passes that owner to this gun updater. The source state-4 branch initializes detached parts and performs camera transition; retail 00307288..003074ec operates camera points and separate command byte, while 00307594..00307614 removes linked entries and calls detached-part initialization/update. Thus this assignment enters the caller's existing Planetbuster state, with no connection to hero state 4. --- src/overlays/l12/mobys/planetbuster_maximus_part.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l12/mobys/planetbuster_maximus_part.c b/src/overlays/l12/mobys/planetbuster_maximus_part.c index 28f8ba4d16..3ac17acded 100644 --- a/src/overlays/l12/mobys/planetbuster_maximus_part.c +++ b/src/overlays/l12/mobys/planetbuster_maximus_part.c @@ -82,6 +82,9 @@ extern int D_L12_00161F24 __attribute__((sda)); void update_planetbuster_maximus_guns(char *moby) __asm__("FUN_L12_003054b0"); void update_planetbuster_maximus_guns(char *moby) { + enum { + PLANETBUSTER_DROP_PARTS_AND_TRANSITION = 4 + }; char *owner_data = ((char *)MOBY(moby)->pvars); int i; float position_buffer[4]; @@ -397,7 +400,7 @@ void update_planetbuster_maximus_guns(char *moby) { update_planetbuster_maximus_detached_parts(moby); if (*(short *)(owner_data + 0x5FC) <= 0 && D_L12_00161F04_gp == 0) { D_L12_00161F24 = 1; - MOBY(moby)->state = 4; + MOBY(moby)->state = PLANETBUSTER_DROP_PARTS_AND_TRANSITION; MOBY(moby)->command = 0; } } From 485caa76e64f71d45defdd9a50d8494530fc404f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:25:39 +0000 Subject: [PATCH 1456/1502] decomp: clarify names in process_suck_cannon_suction_and_update_moby_state domain_1_value_9 -> MOBY_STATE_SUCK_CANNON_ACTIVE: Retail 0x002d56ec calls process_moby_suck_cannon_suction with the incoming moby saved in s0 at 0x002d56f0. The nonzero helper result branches at 0x002d56f8 to sb v0,0x20(s0) at 0x002d5714 with v0=9 from 0x002d56fc. On the zero path, 0x002d5700/04/08 compares that exact same state byte against 9 before resetting it to 5. The SHA-bound source already names this comparison MOBY_STATE_SUCK_CANNON_ACTIVE=0x9 in this function, proving reuse for the assignment to the identical selector MOBY(moby)->state; this is not a HeroStateId or suction-record substate. --- src/overlays/shared/enemies/horny_toad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/horny_toad.c b/src/overlays/shared/enemies/horny_toad.c index e61d6227f7..5a61ea76aa 100644 --- a/src/overlays/shared/enemies/horny_toad.c +++ b/src/overlays/shared/enemies/horny_toad.c @@ -643,7 +643,7 @@ int process_suck_cannon_suction_and_update_moby_state(char *moby) { if (MOBY(moby)->state == MOBY_STATE_SUCK_CANNON_ACTIVE) MOBY(moby)->state = 0x5; } else { - MOBY(moby)->state = 0x9; + MOBY(moby)->state = MOBY_STATE_SUCK_CANNON_ACTIVE; } return suction_result; } From 4bcdf77fce8fedc0881e2baa91d3d2a01c25df5a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:27:39 +0000 Subject: [PATCH 1457/1502] decomp: clarify names in ocean_umbris_update domain_0_value_1 -> OCEAN_UMBRIS_QUEUE_DRAW_OUTSIDE_CLIP_VOLUME: Retail 0x0030d450 reads state byte 0x20(s0); 0x0030d458-0x0030d45c compare it to 1 and branch to 0x0030d498. Initialization loads v1=1 at 0x0030d484 and stores it into that identical state byte at 0x0030d494. Thus the assignment enters the existing local enum case OCEAN_UMBRIS_QUEUE_DRAW_OUTSIDE_CLIP_VOLUME, whose 0x0030d498-0x0030d4c0 path checks the pvars-selected clip volume and queues the draw callback only for a zero containment result. This is identical selector/storage data flow, not numeric equivalence with an unrelated domain. --- src/overlays/l07/mobys/ocean_umbris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/l07/mobys/ocean_umbris.c b/src/overlays/l07/mobys/ocean_umbris.c index c107b886bf..e3150ddf56 100644 --- a/src/overlays/l07/mobys/ocean_umbris.c +++ b/src/overlays/l07/mobys/ocean_umbris.c @@ -23,7 +23,7 @@ void ocean_umbris_update(unsigned char *moby) { switch (MOBY(moby)->state) { case OCEAN_UMBRIS_INITIALIZE: prepare_scaled_table_with_byte_128(ocean_umbris_scaled_table, 0.66666669f); - MOBY(moby)->state = 1; + MOBY(moby)->state = OCEAN_UMBRIS_QUEUE_DRAW_OUTSIDE_CLIP_VOLUME; MOBY(moby)->update_dist = 0xFF; break; case OCEAN_UMBRIS_QUEUE_DRAW_OUTSIDE_CLIP_VOLUME: From c8e28fadf6447fd8d638ac704449523dc93a622c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:29:36 +0000 Subject: [PATCH 1458/1502] decomp: clarify names in prepare_sentrybot_alarm domain_0_value_1 -> SENTRYBOT_ALARM_AWAITING_PREPARATION: Caller sentrybot_update passes the moby selected by alarm_moby_index to prepare_sentrybot_alarm in transition/approach states. Retail 0x002cbbb8-0x002cbbbc tests this linked alarm's +0x20 state against 1; 0x002cbbd0 changes that state to 2, already named SENTRYBOT_ALARM_PREPARING, and 0x002cbbe8 blends animation 1 over 10 scaled frames if needed. Thus 1 is the alarm state awaiting this preparation transition; this is an alarm-moby domain, not HeroStateId. --- src/overlays/shared/enemies/sentrybot.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/sentrybot.c b/src/overlays/shared/enemies/sentrybot.c index 2f4b3f42bb..17257e7038 100644 --- a/src/overlays/shared/enemies/sentrybot.c +++ b/src/overlays/shared/enemies/sentrybot.c @@ -1844,8 +1844,11 @@ void prepare_sentrybot_alarm(unsigned char *moby) { enum { SENTRYBOT_ALARM_PREPARING = 2 }; + enum { + SENTRYBOT_ALARM_AWAITING_PREPARATION = 1 + }; char *alarm_moby_data = ((char *)MOBY(moby)->pvars); - if (MOBY(moby)->state == 1) { + if (MOBY(moby)->state == SENTRYBOT_ALARM_AWAITING_PREPARATION) { MOBY(moby)->state = SENTRYBOT_ALARM_PREPARING; if (MOBY(moby)->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); From 6ae224fd479a9cc8e2211c16821c80fbf14b90cb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:29:36 +0000 Subject: [PATCH 1459/1502] decomp: clarify names in update_camera_blend domain_0_value_0 -> CAMERA_TRANSITION_KIND_PRIMARY: In source snapshot f026270553560b1bbd66636898e33502a58c44b1dc647bb39192cd235ce6ad3f, transition->kind == 0 selects step_camera_blend(to_cam, &transition->blend). Retail 0x001ed2c8 loads the selector byte at s1+2, and 0x001ed2cc branches on nonzero to the alternate solver at 0x001ed2e8; zero falls through to primary solver 0x001ecaf8 at 0x001ed2d4 with state s1+0x10. Thus zero denotes the primary transition kind, independently of the phase halfword. domain_1_value_0 -> CAMERA_TRANSITION_KIND_PRIMARY: Source transition->kind = 0 resets the same selector used by the primary-versus-alternate branch. Retail completion check at 0x001ed2f0 skips resets on zero solver return; completion clears s1+2 with sb zero at 0x001ed344, or the publication-suppressed path at 0x001ed300. The next selector test at 0x001ed2c8-0x001ed2d4 therefore chooses the primary solver. This is the same primary-kind member as the comparison, separate from sh zero at 0x001ed348 clearing the phase. --- src/camera/update_camera_blend.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/camera/update_camera_blend.c b/src/camera/update_camera_blend.c index 5c69876c6b..0813905d39 100644 --- a/src/camera/update_camera_blend.c +++ b/src/camera/update_camera_blend.c @@ -18,10 +18,13 @@ void update_camera_blend(char *to_cam) { enum { CAMERA_TRANSITION_PHASE_IDLE = 0 }; + enum { + CAMERA_TRANSITION_KIND_PRIMARY = 0 + }; struct CameraTransition *transition = &cam_trans_state; int transition_complete; - if (transition->kind == 0) { + if (transition->kind == CAMERA_TRANSITION_KIND_PRIMARY) { transition_complete = step_camera_blend(to_cam, &transition->blend); } else { transition_complete = advance_alternate_camera_transition(to_cam, &transition->orbit); @@ -34,7 +37,7 @@ void update_camera_blend(char *to_cam) { qcopy(camera_rows - 0x210, to_cam + 0x30); } transition->mode = CAMERA_TRANSITION_PHASE_IDLE; - transition->kind = 0; + transition->kind = CAMERA_TRANSITION_KIND_PRIMARY; } } From 693d53e3d54ad561bbbde99fa80094fa615661a5 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:31:24 +0000 Subject: [PATCH 1460/1502] decomp: clarify names in spawn_barrier_replacement domain_0_value_255 -> BARRIER_REPLACEMENT_DRAW_DISTANCE: Authoritative source assigns 0xFF to unsigned char state and immediately writes state to MOBY(moby)->draw_dist. Retail 0x00308234 calls the allocator, 0x0030823c saves its returned replacement in s0, and 0x00308240 checks for NULL. At 0x00308244 v1 receives 255 and 0x0030824c stores it with sh v1,0x32(s0), matching original Ghidra's halfword initialization. Actual moby state is independently cleared at +0x20 by 0x00308264. Thus this literal specifies the replacement moby's draw distance, with no inference of state membership, distance units, maximum, or disabled-culling semantics. --- src/overlays/l09/mobys/barrier.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l09/mobys/barrier.c b/src/overlays/l09/mobys/barrier.c index d5ca816448..66d4266a5e 100644 --- a/src/overlays/l09/mobys/barrier.c +++ b/src/overlays/l09/mobys/barrier.c @@ -71,11 +71,14 @@ extern void func_L00_0025F4A8_309688(void *, void barrier_update(Moby *moby) __asm__("FUN_L09_003082d8"); char *spawn_barrier_replacement(struct Moby *source_moby, int spawned_moby_class) { + enum { + BARRIER_REPLACEMENT_DRAW_DISTANCE = 0xFF + }; char *moby = create_moby(spawned_moby_class); if (moby != 0) { unsigned char state; ((unsigned char *)moby)[0x30] = 0xFF; - state = 0xFF; + state = BARRIER_REPLACEMENT_DRAW_DISTANCE; MOBY(moby)->draw_dist = state; moby[0x31] = 1; moby[0x20] = 0; From dd08808e2b3a033fcb30a5d6d3b2613572eaa9f8 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:37:43 +0000 Subject: [PATCH 1461/1502] decomp: clarify names in update_menu_preview_animation_transform domain_0_value_0 -> ANIMATION_BINDING_FRAME_AND_CLIP_RESET: Assigned retail 0x00224dec sw zero,0x50(s1) clears bytes +0x50..+0x53 before both binding pointers are set at 0x00224df0/0x00224df4 and blend is cleared at 0x00224df8. Checked helper advance_resident_object_animation (evidence request 077bb71d26664f978efa4d390585a573) reads +0x50/+0x51 at 0x0020d5d8/0x0020d5e4 as frame indices, increments and wraps the secondary index at 0x0020d658..0x0020d698, and indexes the frame-pointer array at descriptor +0x1c. It reads +0x52/+0x53 at 0x0020d590/0x0020d598 as clip selectors; +0x53 selects a resource descriptor via selector*4+resource+0x48 at 0x0020d5fc..0x0020d61c. Thus the packed zero resets both frame indices and clip selectors; it is not a boolean or MenuTextAction value. --- .../item_preview/update_menu_preview_animation_transform.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/menus/item_preview/update_menu_preview_animation_transform.c b/src/ui/menus/item_preview/update_menu_preview_animation_transform.c index ea4304e7ab..7b39f51132 100644 --- a/src/ui/menus/item_preview/update_menu_preview_animation_transform.c +++ b/src/ui/menus/item_preview/update_menu_preview_animation_transform.c @@ -17,6 +17,9 @@ extern void noop_callback_s(void *, void *, int, int, int) __asm__("func_001E948 void update_menu_preview_animation_transform(PauseMoby *moby) __asm__("FUN_00224d28"); void update_menu_preview_animation_transform(PauseMoby *moby) { + enum { + ANIMATION_BINDING_FRAME_AND_CLIP_RESET = 0 + }; f32 transform[16]; s32 source_moby_address = (s32)((struct MenuScreen *)*moby->vars)->data.preview.moby; @@ -40,7 +43,7 @@ void update_menu_preview_animation_transform(PauseMoby *moby) { 0, source_moby_address); } - moby->binding_state = 0; + moby->binding_state = ANIMATION_BINDING_FRAME_AND_CLIP_RESET; moby->primary_binding = (char *)menu_item_info; moby->binding_blend_word = 0; moby->secondary_binding = (char *)menu_item_info; From fa7d6e228b3efb68f655c63ee64c32b1bee9bcc4 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:37:43 +0000 Subject: [PATCH 1462/1502] decomp: clarify names in set_hero_item_moby_flag_bit0 domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: In the SHA-bound current source, tail is assigned &hero and the selector is tail->vehicle_mode. Retail 0x00233048 reconstitutes hero at 0x0013f350; 0x00233054/0x00233064 loads its byte +0x20a4, 0x00233068 loads 1, and 0x0023306c branches on inequality. Only equality reaches the optional hero+0x1624 Moby flag update at 0x00233074-0x00233088. Original Ghidra independently shows cRam001413f4 == '\x01', the same hero+0x20a4 address. This is the Hero vehicle_mode field, not state.current or gravity_mode. The supplied include/rnc/hero/hero_state.h HeroVehicleMode domain canonically names value 1 HERO_VEHICLE_MODE_CLANK, so reuse that member. --- src/overlays/shared/hero/set_hero_animation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/set_hero_animation.c b/src/overlays/shared/hero/set_hero_animation.c index b47fc31b37..c912d0214f 100644 --- a/src/overlays/shared/hero/set_hero_animation.c +++ b/src/overlays/shared/hero/set_hero_animation.c @@ -726,7 +726,7 @@ void set_hero_item_moby_flag_bit0(void) { if (hero_flag_target != 0) { *(unsigned short *)(hero_flag_target + 0x34) |= 1; } - if (tail->vehicle_mode == 1) { + if (tail->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero_flag_target = ((char *)tail->unk1624); if (hero_flag_target != 0) { *(unsigned short *)(hero_flag_target + 0x34) |= 1; From b46aab29126d96b275e2bf5ee649874a80e5c384 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:45:21 +0000 Subject: [PATCH 1463/1502] decomp: clarify names in update_hero_item_moby_flags domain_0_value_1 -> HERO_VEHICLE_MODE_CLANK: Retail 0x0023314c loads the byte at hero (0x0013f350)+0x20a4; 0x00233150-0x00233154 compares it with 1, enabling the +0x1624 pointer load and clearing its object's flag halfword +0x34 at 0x0023315c-0x00233170. The authoritative C binds that same byte to blk2->vehicle_mode, proving the HeroVehicleMode selector rather than HeroStateId or HeroGravityMode. In the same supplied source, set_hero_item_moby_flag_bit0 tests the identical hero.vehicle_mode field against canonical HERO_VEHICLE_MODE_CLANK and accesses the same unk1624 pointer to set the inverse bit. The supplied include/rnc/hero/hero_state.h enum domain defines HERO_VEHICLE_MODE_CLANK = 1. Reuse that established member for the inverse flag-clearing path. --- src/overlays/shared/hero/set_hero_animation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/hero/set_hero_animation.c b/src/overlays/shared/hero/set_hero_animation.c index c912d0214f..78014982b8 100644 --- a/src/overlays/shared/hero/set_hero_animation.c +++ b/src/overlays/shared/hero/set_hero_animation.c @@ -774,7 +774,7 @@ void update_hero_item_moby_flags(void) { if (hero_flag_target != 0) { *(unsigned short *)(hero_flag_target + 0x34) &= ~1; } - if (blk2->vehicle_mode == 1) { + if (blk2->vehicle_mode == HERO_VEHICLE_MODE_CLANK) { hero_flag_target = *(char **)&blk2->unk1624; if (hero_flag_target != 0) { *(unsigned short *)(hero_flag_target + 0x34) &= ~1; From 055e30f84cd7706ecce01e07771b01417c485e0f Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:47:04 +0000 Subject: [PATCH 1464/1502] decomp: clarify names in beam_slots_update domain_0_value_1 -> SLOT_UPDATE_STATE_PROCESS_SLOTS: In the authoritative beam_slots.c snapshot (SHA-256 2872ef56821dd0a11c6679d4ba0ee6b15c085832e8dd763dc087f26559075af5), the assignment MOBY(moby)->state = 1 targets the exact field switched on by case SLOT_UPDATE_STATE_PROCESS_SLOTS. Retail 0x003039ec preserves a0 as s4; 0x00303a08 loads byte +0x20(s4), and 0x00303a10-0x00303a14 compares that byte with 1 to enter the three-slot processing loop at 0x00303a68. After clearing the three state/object pairs, 0x00303a54 loads v1=1 and 0x00303a64 stores v1 to the same +0x20(s4). Original Ghidra likewise stores 1 to iVar6+0x20 then dispatches its value 1 to slot processing. Thus the existing outer-controller enum member applies; per-beam slot state and Hero constants are separate domains. --- src/overlays/shared/rendering/effects/beam_slots.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/rendering/effects/beam_slots.c b/src/overlays/shared/rendering/effects/beam_slots.c index 8c04749224..fba72101cb 100644 --- a/src/overlays/shared/rendering/effects/beam_slots.c +++ b/src/overlays/shared/rendering/effects/beam_slots.c @@ -51,7 +51,7 @@ void beam_slots_update(unsigned char *moby) { D_L14_00162148[j] = 0; D_L14_001621D8[j] = 0; } - MOBY(moby)->state = 1; + MOBY(moby)->state = SLOT_UPDATE_STATE_PROCESS_SLOTS; MOBY(moby)->update_dist = 0xFF; break; case SLOT_UPDATE_STATE_PROCESS_SLOTS: From 2381ea7bd73d7e3af2acb26bd01857469b3f9b87 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:47:05 +0000 Subject: [PATCH 1465/1502] decomp: clarify names in activate_first_inactive_group_moby domain_0_value_2 -> GROUP_MOBY_STATE_ACTIVATING: Authoritative sentrybot_alarm.c SHA-256 87eba3472fdadf9514384ae1bfe7ce0b365a5e884e9eeddb72565b1fc486900c and original retail Ghidra agree: 0x002a28b0-0x002a28bc resolves a masked group entry to a 0x100-stride moby, 0x002a28c0-0x002a28c4 accepts only its inactive state 1, and 0x002a28cc-0x002a28d8 stores 2 to that same +0x20 state byte. The accepted member receives animation reset, collision restoration, random heading offset, scaled 60-frame timer, supplied position and hero-facing heading at 0x002a28dc-0x002a2980, then returns success. Established activate_first_inactive_group_moby and its sentrybot_alarm_update RELEASE_GROUP_MOBYS caller prove this is the activation-entry state of a released group member, in the same local domain as GROUP_MOBY_STATE_INACTIVE; it is not a Hero state or controller mode. --- src/overlays/shared/enemies/sentrybot_alarm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/sentrybot_alarm.c b/src/overlays/shared/enemies/sentrybot_alarm.c index 24dadc6f3a..bb1b2ac95d 100644 --- a/src/overlays/shared/enemies/sentrybot_alarm.c +++ b/src/overlays/shared/enemies/sentrybot_alarm.c @@ -58,6 +58,9 @@ int activate_first_inactive_group_moby(int moby_group_index, void *pos) { enum { GROUP_MOBY_STATE_INACTIVE = 1 }; + enum { + GROUP_MOBY_STATE_ACTIVATING = 2 + }; short *group_moby_entry = (short *)D_L15_001ABE40[moby_group_index]; struct Hero *hero_data = &hero; do { @@ -66,7 +69,7 @@ int activate_first_inactive_group_moby(int moby_group_index, void *pos) { unsigned char state = MOBY(listed_moby)->state; if (state == GROUP_MOBY_STATE_INACTIVE) { char *activated_moby_data; - MOBY(listed_moby)->state = 2; + MOBY(listed_moby)->state = GROUP_MOBY_STATE_ACTIVATING; if (MOBY(listed_moby)->prev_seq != 0) blend_moby_animation(listed_moby, 0, 0, 0); MOBY(listed_moby)->flags |= 1; From 39e8182f321fef61b3bf59801202acfac14fbd2c Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:49:10 +0000 Subject: [PATCH 1466/1502] decomp: clarify names in update_camera domain_0_value_0 -> CAMERA_TRANSITION_KIND_PRIMARY: The source assigns cam_trans_state.kind at retail 0x001edae4 (sb zero to 0x001871b2), separate from the phase halfword at 0x001871b0. Checked helper 0x001ed2b0 reads that exact byte at 0x001ed2c8, branches on nonzero at 0x001ed2cc to the alternate solver 0x001eccd8, and for zero calls advance_primary_camera_transition at 0x001ed2d4 (0x001ecaf8). Thus zero selects the primary transition kind, not the idle phase. domain_1_value_3 -> CAMERA_TRANSITION_PHASE_BLENDING: camera is anchored at 0x00186f40; camera->transition_mode at +0x270 is the same phase halfword 0x001871b0 cleared to CAMERA_TRANSITION_PHASE_IDLE. Retail 0x001edb34-0x001edb48 compares that halfword to 3 and calls update_camera_blend (0x001ed2b0) with current_camera from +0x180; other phases directly copy the target transform. The checked helper advances the primary or alternate transition at 0x001ed2d4/0x001ed2e8, retains the phase while incomplete (0x001ed2f0), and on completion publishes the target and clears the phase at 0x001ed348. Thus 3 denotes the blending phase in this exact phase domain. --- src/camera/update_camera.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/camera/update_camera.c b/src/camera/update_camera.c index 2cc13d45c8..dd2be1a649 100644 --- a/src/camera/update_camera.c +++ b/src/camera/update_camera.c @@ -33,6 +33,10 @@ void update_camera(void) { enum { CAMERA_TRANSITION_PHASE_IDLE = 0 }; + enum { + CAMERA_TRANSITION_KIND_PRIMARY = 0, + CAMERA_TRANSITION_PHASE_BLENDING = 3 + }; struct PreviewCamera *camera; struct UpdateCam *target; char *camera_shake_base; @@ -43,7 +47,7 @@ void update_camera(void) { return; } cam_trans_state.mode = CAMERA_TRANSITION_PHASE_IDLE; - cam_trans_state.kind = 0; + cam_trans_state.kind = CAMERA_TRANSITION_KIND_PRIMARY; } camera = &preview_camera; camera->frame_count++; @@ -55,7 +59,7 @@ void update_camera(void) { if ((unsigned short)(*(unsigned short *)&camera->transition_mode - 1) < 2) { start_camera_blend(camera->previous_camera); } - if (camera->transition_mode == 3) { + if (camera->transition_mode == CAMERA_TRANSITION_PHASE_BLENDING) { update_camera_blend((char *)target); } else { struct OcclCamState *occlusion = &occl_cam_state; From 339ba31801447e6672f6d6a95dd9d228861f36ef Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:49:10 +0000 Subject: [PATCH 1467/1502] decomp: clarify names in respawn_volume_update domain_0_value_1 -> CHECK_HERO_TRIGGER_VOLUMES: The authoritative respawn_volume.c snapshot (SHA-256 3104281533e1c1b1c613abc7e5242b5abbc4d63745da8ee6cadb9df4acc48864) switches on moby byte +0x20 and names value 1 CHECK_HERO_TRIGGER_VOLUMES. Retail 0x002f7950 reads that exact byte, 0x002f795c-0x002f7960 dispatches value 1 to 0x002f7984, and initialization loads 1 at 0x002f7970 then stores it to the same moby +0x20 at 0x002f7980. Original Ghidra likewise assigns *(param_1+0x20)=1 and tests that byte for 1 before scanning the two volume arrays. Thus the assignment enters the existing local monitor state, whose branch checks hero trigger volumes; it does not belong to any Hero state, gravity or vehicle-mode enum. --- src/overlays/shared/props/respawn_volume.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/props/respawn_volume.c b/src/overlays/shared/props/respawn_volume.c index d606f35a0d..76fb920d29 100644 --- a/src/overlays/shared/props/respawn_volume.c +++ b/src/overlays/shared/props/respawn_volume.c @@ -29,7 +29,7 @@ void respawn_volume_update(char *moby) { int j; switch (((unsigned char *)moby)[0x20]) { case INITIALIZE_TRIGGER_MONITOR: - MOBY(moby)->state = 1; + MOBY(moby)->state = CHECK_HERO_TRIGGER_VOLUMES; ((unsigned char *)moby)[0x30] = 0xFF; return; case CHECK_HERO_TRIGGER_VOLUMES: From 84c942d488566272330709c75be7fa344ad6fb5e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:50:59 +0000 Subject: [PATCH 1468/1502] decomp: clarify names in alien_snapper_spawner_update domain_0_value_1 -> WAIT_FOR_ANIMATION_SIGNAL: Retail 0x002fdab0 stores 1 into this moby's state byte at s1+0x20 after the hero-volume test. The same byte is loaded at 0x002fda54 and state 1 branches at 0x002fda58 to 0x002fdac0, where +0x70 bit 2 gates progress. This is the existing local WAIT_FOR_ANIMATION_SIGNAL domain, not a hero state. domain_1_value_2 -> ACTIVATE_LISTED_MOBYS_AT_INTERVAL: Retail 0x002fdad0-0x002fdae0 stores 2 into s1+0x20 when the list selector at s2+0 is nonnegative. Dispatch of this same state byte at 0x002fda7c reaches 0x002fdb1c: decrement the +8 countdown, traverse D_L06_001ABFC0 and call activate_state_15_moby_at_position, then reload scale_game_frames(20) on success. This matches the existing local member ACTIVATE_LISTED_MOBYS_AT_INTERVAL. domain_2_value_3 -> ACTIVATION_SEQUENCE_FINISHED: Retail 0x002fdad0-0x002fdae0 chooses and stores 3 at s1+0x20 when the activation-list selector is negative after the animation signal. Dispatch at 0x002fda54-0x002fda88 handles only 0, 1 and 2; state 3 returns without further sequence processing. The other store of 3 at 0x002fdbac likewise ends processing when no listed moby is activated, proving a shared activation-sequence terminal state. domain_3_value_3 -> ACTIVATION_SEQUENCE_FINISHED: Retail 0x002fdb34 initializes activation success to zero; 0x002fdb70 branches on helper success to set it to one. Null lists or traversal without success reach 0x002fdb84-0x002fdb98 and store 3 into this moby's state byte at 0x002fdbac. Subsequent dispatch at 0x002fda54-0x002fda88 returns for 3, ending this activation sequence, matching the no-list terminal assignment at 0x002fdadc-0x002fdae0. --- src/overlays/l06/mobys/alien_snapper_spawner.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/overlays/l06/mobys/alien_snapper_spawner.c b/src/overlays/l06/mobys/alien_snapper_spawner.c index e9a616657f..93adcb3bb3 100644 --- a/src/overlays/l06/mobys/alien_snapper_spawner.c +++ b/src/overlays/l06/mobys/alien_snapper_spawner.c @@ -23,11 +23,14 @@ void alien_snapper_spawner_update(char *moby) { WAIT_FOR_ANIMATION_SIGNAL = 1, ACTIVATE_LISTED_MOBYS_AT_INTERVAL = 2 }; + enum { + ACTIVATION_SEQUENCE_FINISHED = 3 + }; int *moby_vars = ((int *)MOBY(moby)->pvars); switch (((unsigned char *)moby)[0x20]) { case WAIT_FOR_HERO_IN_CLIP_VOLUME: if (moby_vars[1] >= 0 && is_point_inside_clip_volume(&hero.motion.pos, moby_vars[1])) { - MOBY(moby)->state = 1; + MOBY(moby)->state = WAIT_FOR_ANIMATION_SIGNAL; if (((unsigned char *)moby)[0x53] != 1) { blend_moby_animation(moby, 1, 0, 5); } @@ -36,9 +39,9 @@ void alien_snapper_spawner_update(char *moby) { case WAIT_FOR_ANIMATION_SIGNAL: if (MOBY(moby)->anim_flags & 2) { if (moby_vars[0] >= 0) { - MOBY(moby)->state = 2; + MOBY(moby)->state = ACTIVATE_LISTED_MOBYS_AT_INTERVAL; } else { - MOBY(moby)->state = 3; + MOBY(moby)->state = ACTIVATION_SEQUENCE_FINISHED; } if (((unsigned char *)moby)[0x53] != 2) { blend_moby_animation(moby, 2, 0, 5); @@ -64,7 +67,7 @@ void alien_snapper_spawner_update(char *moby) { if (found != 0.0f) { moby_vars[2] = scale_game_frames(0x14); } else { - MOBY(moby)->state = 3; + MOBY(moby)->state = ACTIVATION_SEQUENCE_FINISHED; } } break; From 9a3d2001ec99639d0b60607fd21f06a37565425b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:52:52 +0000 Subject: [PATCH 1469/1502] decomp: clarify names in blarg_elite_commando_rocket_update domain_0_value_0 -> BLARG_ELITE_COMMANDO_ROCKET_STATE_FLYING: Authoritative source SHA-256 a753921a8cebfbbfece1ab2de47c7c93bc89684a0d1dcbd640409a242d6f8e8d already declares BLARG_ELITE_COMMANDO_ROCKET_STATE_FLYING = 0 inside spawn_blarg_elite_commando_rocket and assigns it to the newly created class-0x31 moby's state. This update consumes that same rocket moby state: retail 0x0029ac3c preserves a0 in s2, 0x0029acac loads state byte +0x20(s2), and 0x0029acb0 returns for nonzero. Original Ghidra cVar1 == '\0' guards velocity addition at 0x0029acf4, collision testing at 0x0029ad84, position copy at 0x0029addc-0x0029ade0 and rocket trail at 0x0029ade4. These operations prove the flying-state domain and reuse the established rocket state name, rather than an equal-valued hero selector constant. --- src/overlays/shared/enemies/blarg_elite_commando_rocket.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/blarg_elite_commando_rocket.c b/src/overlays/shared/enemies/blarg_elite_commando_rocket.c index 7cab247339..ad449c5fff 100644 --- a/src/overlays/shared/enemies/blarg_elite_commando_rocket.c +++ b/src/overlays/shared/enemies/blarg_elite_commando_rocket.c @@ -72,6 +72,9 @@ void blarg_elite_commando_rocket_update(unsigned char *m) __asm__("FUN_L15_0029a /* Moby class 49 */ void blarg_elite_commando_rocket_update(unsigned char *moby) { + enum { + BLARG_ELITE_COMMANDO_ROCKET_STATE_FLYING = 0 + }; char *rocket_data = ((char *)MOBY(moby)->pvars); float rocket_next_position[4]; float back[4]; @@ -83,7 +86,7 @@ void blarg_elite_commando_rocket_update(unsigned char *moby) { *(int *)(rocket_data + 0x10) = 1; } } - if (MOBY(moby)->state != 0) + if (MOBY(moby)->state != BLARG_ELITE_COMMANDO_ROCKET_STATE_FLYING) return; collision_setup_value = 1.0f; MOBY(moby)->rot.x = fast_add_rotations(MOBY(moby)->rot.x, D_0015ED6C * 6.2831855f); From 5996b18daaa5fa388a459fe588093edbb387b7a9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:57:06 +0000 Subject: [PATCH 1470/1502] decomp: clarify names in billboard_projectile_update domain_0_value_2 -> TIMED_REMOVAL: Retail 002c75d4 reads state from 0x20(s1); 002c75ec-002c75f0 dispatches value 2 to 002c76e0. After countdown expiry at 002c76a8-002c76b0, 002c76b8-002c76c0 reloads pvars[0] with scale_game_frames(30), and 002c76c4-002c76c8 stores 2 to that identical 0x20(s1) state byte. The selected state decrements that timer at 002c76e0, removes the moby at 002c76f0 on expiry, otherwise scales remaining lifetime into byte +0x23 at 002c7700-002c7730. Authoritative C already names this same switch branch TIMED_REMOVAL = 2; reuse that member for the transition assignment, not a different numeric domain. --- src/overlays/shared/enemies/billboard_projectile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/overlays/shared/enemies/billboard_projectile.c b/src/overlays/shared/enemies/billboard_projectile.c index 104e1bab7f..75654730fc 100644 --- a/src/overlays/shared/enemies/billboard_projectile.c +++ b/src/overlays/shared/enemies/billboard_projectile.c @@ -108,7 +108,7 @@ void billboard_projectile_update(char *moby) { } if (fast_dec_timer(motion_lifetime_vars)) { motion_lifetime_vars[0] = scale_game_frames(0x1e); - MOBY(moby)->state = 2; + MOBY(moby)->state = TIMED_REMOVAL; if (motion_lifetime_vars[4] != 0) motion_lifetime_vars[4] = 0; } From 04067755396c7d356af004b3ceae041647f746fc Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:58:55 +0000 Subject: [PATCH 1471/1502] decomp: clarify names in electric_beam_update domain_0_value_0 -> BEAM_STATE_INITIALIZE: Retail 0x003015e8-0x003015ec loads the beam moby's state byte at s1+0x20 and skips culling when zero. The same byte is loaded at 0x0030162c and zero dispatches to initialization at 0x00301644/0x0030166c. The source names this selector's zero case BEAM_STATE_INITIALIZE; reuse that member for its pre-dispatch comparison. domain_1_value_2 -> BEAM_STATE_WAIT_FOR_TIMED_PULSE: Retail initialization at 0x00301674-0x00301684 scales pvars+0xC into phase timer pvars+0x10, then writes 2 to the same moby state byte s1+0x20 read by dispatch at 0x0030162c. Dispatch for 2 reaches 0x003016e4, which waits on that timer before starting a pulse. Source already names that exact selector case BEAM_STATE_WAIT_FOR_TIMED_PULSE. domain_2_value_3 -> BEAM_STATE_REPEAT_PULSES: Retail 0x003016e4-0x00301708 handles the state-2 timer expiry: it writes 3 at 0x003016f4 to moby state s1+0x20, reloads the phase timer from pvars+4, and starts a pulse. State-3 dispatch at 0x0030165c reaches 0x00301714, whose unexpired phase regenerates pulses when pvars+0x12 is zero at 0x00301748-0x00301754. Reuse its existing source case BEAM_STATE_REPEAT_PULSES. domain_3_value_2 -> BEAM_STATE_WAIT_FOR_TIMED_PULSE: Retail 0x00301640 establishes s2=2 for the state-2/state-3 dispatch path. On repeating-phase timer expiry, 0x00301724-0x00301734 tests pvars+6, writes s2 to moby state s1+0x20 when nonzero, then selects pvars+6 as the reloaded wait duration. This returns to the same state-2 timer-wait branch at 0x003016e4; reuse the existing BEAM_STATE_WAIT_FOR_TIMED_PULSE member. --- src/overlays/shared/props/electric_beam.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/shared/props/electric_beam.c b/src/overlays/shared/props/electric_beam.c index 2496cfcde2..b8f8ae710d 100644 --- a/src/overlays/shared/props/electric_beam.c +++ b/src/overlays/shared/props/electric_beam.c @@ -64,7 +64,7 @@ void electric_beam_update(unsigned char *moby) { float beam_culling_sphere[4] __attribute__((aligned(16))); int beam_state; int phase_duration_frames; - if (MOBY(moby)->state != 0) { + if (MOBY(moby)->state != BEAM_STATE_INITIALIZE) { qcopy(beam_culling_sphere, &MOBY(moby)->pos); beam_culling_sphere[3] = beam_vars->f624; if (fast_bsphere_check(beam_culling_sphere, 52.0f) < 0) { @@ -79,7 +79,7 @@ void electric_beam_update(unsigned char *moby) { case BEAM_STATE_INITIALIZE: start_electric_beam_pulse((char *)moby); beam_vars->s10 = scale_game_frames(beam_vars->wC); - MOBY(moby)->state = 2; + MOBY(moby)->state = BEAM_STATE_WAIT_FOR_TIMED_PULSE; beam_vars->f624 = fast_vec_length(&l14_cuboids[beam_vars->w0].axes[1]); beam_vars->s8 = 1; beam_vars->sA = 1; @@ -94,7 +94,7 @@ void electric_beam_update(unsigned char *moby) { break; case BEAM_STATE_WAIT_FOR_TIMED_PULSE: if (fast_dec_timer_s16(&beam_vars->s10) != 0) { - MOBY(moby)->state = 3; + MOBY(moby)->state = BEAM_STATE_REPEAT_PULSES; beam_vars->s10 = scale_game_frames(beam_vars->s4); start_electric_beam_pulse((char *)moby); } @@ -102,7 +102,7 @@ void electric_beam_update(unsigned char *moby) { case BEAM_STATE_REPEAT_PULSES: if (fast_dec_timer_s16(&beam_vars->s10) != 0) { if (beam_vars->s6 != 0) { - MOBY(moby)->state = 2; + MOBY(moby)->state = BEAM_STATE_WAIT_FOR_TIMED_PULSE; phase_duration_frames = beam_vars->s6; } else { phase_duration_frames = beam_vars->s4; From 3fcd8da7f8df738095ac9f3b4c959452b0259817 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 15:58:55 +0000 Subject: [PATCH 1472/1502] decomp: clarify names in update_moby_hit_stats_and_state domain_0_value_4 -> BLARG_SHIP_INACTIVE: Retail 0x0031a1d8 preserves the argument moby in s0; 0x0031a390-398 checks its state byte at +0x20 against 5. When hero state is not 0x32, 0x0031a3b0 loads 4 and 0x0031a3b8 stores it to that same moby+0x20, while 0x0031a3c0 clears collision at +0x94 and 0x0031a3bc/c4 sets flags bit 1. Original Ghidra shows the same state/collision/flags stores. Supplied level-11 and level-17 blarg_ship_update pass moby to update_moby_hit_stats_and_state and then switch on moby->state; both establish BLARG_SHIP_INACTIVE=4 and use that state with collision=0 and flags|=1 during initialization. Thus this is the ship's inactive state, not HERO_STATE_CROUCH. domain_1_value_6 -> BLARG_SHIP_BURST_AND_DEACTIVATE: Retail 0x0031a3d0-3dc passes the argument moby's +0x10 position and the same moby to coll_sphere. On a nonzero return, 0x0031a3e4 loads 6 and 0x0031a3f4 stores it to s0+0x20, followed by animation 1 blending at 0x0031a3f8-410 unless already active. Original Ghidra shows the identical state store and blend. The same function's hit path already selects BLARG_SHIP_BURST_AND_DEACTIVATE=6 and writes the same moby state byte at 0x0031a368 with the same animation transition. Supplied level-11 and level-17 blarg_ship_update call this helper on their moby and switch on its state with BLARG_SHIP_BURST_AND_DEACTIVATE=6. Reuse that existing local enum member; this is not HERO_STATE_FALL. --- src/overlays/shared/props/thruster_pack_lock.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/shared/props/thruster_pack_lock.c b/src/overlays/shared/props/thruster_pack_lock.c index a3153e1ccf..cbc813cba9 100644 --- a/src/overlays/shared/props/thruster_pack_lock.c +++ b/src/overlays/shared/props/thruster_pack_lock.c @@ -745,6 +745,9 @@ void update_moby_hit_stats_and_state(char *moby) { BLARG_SHIP_BURST_AND_WAIT_TO_REACTIVATE = 2, BLARG_SHIP_BURST_AND_DEACTIVATE = 6 }; + enum { + BLARG_SHIP_INACTIVE = 4 + }; char *moby_vars = ((char *)MOBY(moby)->pvars); char *hit_record = find_moby_hit(moby, 0x330000, 0); struct Hero *player_hero; @@ -793,12 +796,12 @@ void update_moby_hit_stats_and_state(char *moby) { } else if (((unsigned char *)moby)[0x20] == 5) { struct Hero *hero_for_state_check = &hero; if (hero_for_state_check->state.current != 0x32) { - MOBY(moby)->state = 4; + MOBY(moby)->state = BLARG_SHIP_INACTIVE; MOBY(moby)->collision = 0; MOBY(moby)->flags |= 1; } if (coll_sphere(1.0f, &MOBY(moby)->pos, 0, moby)) { - MOBY(moby)->state = 6; + MOBY(moby)->state = BLARG_SHIP_BURST_AND_DEACTIVATE; if (((unsigned char *)moby)[0x53] != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } From 953f2a879132644d01bb67a643525df35c311739 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:00:33 +0000 Subject: [PATCH 1473/1502] decomp: clarify names in swingshot_hook_update domain_0_value_1 -> HOOK_IDLE_ANIMATION: Retail 002c7100 reads hook state at s0+0x20 for the named switch. Initial animation completion loads s1=1 at 002c7134 and stores it to that same byte at 002c71d0, entering the existing HOOK_IDLE_ANIMATION case, not an owner-state domain. domain_1_value_3 -> HOOK_LAUNCH_ANIMATION: Within hook idle, retail 002c7164 tests the owner's state separately, then 002c7174 loads s1=3 and 002c71d0 writes hook s0+0x20. This is the exact selector read at 002c7100 for existing HOOK_LAUNCH_ANIMATION; sequence 3 is selected at 002c7194. domain_2_value_2 -> HOOK_REMOVAL_ANIMATION: Retail 002c7198 recognizes owner state 8, selects hook sequence 2 at 002c71bc, and stores s1=2 to hook s0+0x20 at 002c71d0. That same hook selector's existing HOOK_REMOVAL_ANIMATION branch at 002c71dc waits for completion before removal at 002c71ec. domain_3_value_4 -> HOOK_FLIGHT_ANIMATION: After hook launch completion, retail 002c7208 loads s1=4 and writes hook s0+0x20 at 002c7214 or shared 002c72fc after selecting sequence 4. This is the same byte switched at 002c7100, whose existing case 4 is HOOK_FLIGHT_ANIMATION, independent of the owner selector. domain_4_value_5 -> HOOK_ATTACHED_ANIMATION: Retail 002c7230-002c7240 tests owner states 3..5 through a separate pointer. It then loads s1=5 at 002c7244 and writes hook s0+0x20 at 002c7250 or 002c72fc after sequence 5 selection. This enters existing HOOK_ATTACHED_ANIMATION on the hook's own switch selector. domain_5_value_7 -> HOOK_RETURN_ANIMATION: Retail 002c727c-002c728c tests owner states 6/7, then loads s1=7 at 002c7290 and selects sequence 7 at 002c72bc if required. The store at 002c72fc targets hook s0+0x20, the exact switch selector for existing HOOK_RETURN_ANIMATION, rather than naming the owner state values. domain_6_value_1 -> HOOK_IDLE_ANIMATION: Retail hook return completion at 002c72c0-002c72c8 falls into the default reset at 002c72d0. It loads s1=1 at 002c72d4, selects sequence 1 if needed, and stores to hook s0+0x20 at 002c72dc or 002c72fc, returning to the existing HOOK_IDLE_ANIMATION case of that same selector. --- src/overlays/shared/weapons/swingshot_hook.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/weapons/swingshot_hook.c b/src/overlays/shared/weapons/swingshot_hook.c index 89ab40e8d0..1887e9f231 100644 --- a/src/overlays/shared/weapons/swingshot_hook.c +++ b/src/overlays/shared/weapons/swingshot_hook.c @@ -88,7 +88,7 @@ void swingshot_hook_update(unsigned char *hook_moby) { if (MOBY(hook_moby)->anim_flags & 2) { if (MOBY(hook_moby)->prev_seq != 1) blend_moby_animation(hook_moby, 1, 0, FUN_001f96f8_2c7070(10)); - MOBY(hook_moby)->state = 1; + MOBY(hook_moby)->state = HOOK_IDLE_ANIMATION; MOBY(hook_moby)->anim_speed = 1.0f; } break; @@ -96,12 +96,12 @@ void swingshot_hook_update(unsigned char *hook_moby) { if (hook_vars[0][0x20] == 2) { if (MOBY(hook_moby)->prev_seq != 3) blend_moby_animation(hook_moby, 3, 0, FUN_001f96f8_2c7070(10)); - MOBY(hook_moby)->state = 3; + MOBY(hook_moby)->state = HOOK_LAUNCH_ANIMATION; MOBY(hook_moby)->anim_speed = 1.0f; } else if (hook_vars[0][0x20] == 8) { if (MOBY(hook_moby)->prev_seq != 2) blend_moby_animation(hook_moby, 2, 0, FUN_001f96f8_2c7070(10)); - MOBY(hook_moby)->state = 2; + MOBY(hook_moby)->state = HOOK_REMOVAL_ANIMATION; MOBY(hook_moby)->anim_speed = 1.0f; } break; @@ -116,14 +116,14 @@ void swingshot_hook_update(unsigned char *hook_moby) { if (MOBY(hook_moby)->anim_flags & 2) { if (MOBY(hook_moby)->prev_seq != 4) blend_moby_animation(hook_moby, 4, 0, FUN_001f96f8_2c7070(10)); - MOBY(hook_moby)->state = 4; + MOBY(hook_moby)->state = HOOK_FLIGHT_ANIMATION; } break; case HOOK_FLIGHT_ANIMATION: if ((unsigned char)(hook_vars[0][0x20] - 3) < 3) { if (MOBY(hook_moby)->prev_seq != 5) blend_moby_animation(hook_moby, 5, 0, FUN_001f96f8_2c7070(10)); - MOBY(hook_moby)->state = 5; + MOBY(hook_moby)->state = HOOK_ATTACHED_ANIMATION; } break; case HOOK_ATTACHED_ANIMATION: @@ -133,7 +133,7 @@ void swingshot_hook_update(unsigned char *hook_moby) { MOBY(hook_moby)->anim_speed = 1.0f; if (MOBY(hook_moby)->prev_seq != 7) blend_moby_animation(hook_moby, 7, 0, FUN_001f96f8_2c7070(10)); - MOBY(hook_moby)->state = 7; + MOBY(hook_moby)->state = HOOK_RETURN_ANIMATION; } break; case HOOK_SKIP_ANIMATION_TRANSITIONS: @@ -144,7 +144,7 @@ void swingshot_hook_update(unsigned char *hook_moby) { default: if (MOBY(hook_moby)->prev_seq != 1) blend_moby_animation(hook_moby, 1, 0, FUN_001f96f8_2c7070(10)); - MOBY(hook_moby)->state = 1; + MOBY(hook_moby)->state = HOOK_IDLE_ANIMATION; break; } refresh_moby_spatial_bounds_from_basis(hook_moby); From 7e99ddd0ec45cd47c6f4af36e0cfdb025eccad66 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:00:34 +0000 Subject: [PATCH 1474/1502] decomp: clarify names in fighter_jet_update domain_0_value_101 -> FIGHTER_JET_STATE_DESTROYED: The bound fighter_jet_update source assigns 0x65 to MOBY(moby)->state on a non-null find_moby_hit result. Retail 0x002f4508-0x002f4510 first rejects an already-0x65 moby, and 0x002f4570 stores s4=0x65 into the same moby+0x20 state byte. The immediately following path calls source-named spawn_explosion at 0x002f45d4, invokes the break-effect helper at 0x002f45e4, removes four valid child mobys at 0x002f45f0-0x002f4610, and calls mark_moby_for_removal on the fighter jet itself at 0x002f4614-0x002f4618. The no-hit branch also skips gunship_update for this state at 0x002f4624-0x002f4634. These state-byte writes and guards prove the fighter jet destroyed state rather than a control/request mode. --- src/overlays/l01/mobys/fighter_jet.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l01/mobys/fighter_jet.c b/src/overlays/l01/mobys/fighter_jet.c index acc786908c..e7fac55dbb 100644 --- a/src/overlays/l01/mobys/fighter_jet.c +++ b/src/overlays/l01/mobys/fighter_jet.c @@ -67,6 +67,9 @@ void fighter_jet_update(char *moby) __asm__("FUN_L01_002f4428"); /* Moby class 660 */ void fighter_jet_update(char *moby) { + enum { + FIGHTER_JET_STATE_DESTROYED = 0x65 + }; float hit_dir[4]; float hit_vec[4]; char *fighter_jet_vars = *(char **)(moby + 0x78); @@ -102,7 +105,7 @@ void fighter_jet_update(char *moby) { queue_dialogue_message(0x53D6, -1); } fast_vec_sub(hit_vec, fighter_jet_vars + 0xD0, fighter_jet_vars + 0xE0); - MOBY(moby)->state = 0x65; + MOBY(moby)->state = FIGHTER_JET_STATE_DESTROYED; *(u128 *)hit_dir = *(u128 *)hit_vec; spawn_explosion(moby, hit_dir, From bf4ff8ec2142733e51ccb7502d82fb7ca7dcf008 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:05:02 +0000 Subject: [PATCH 1475/1502] decomp: clarify names in spawn_linked_hitbox_contact_effects domain_0_value_254 -> MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF: Retail 0x002c9aac loads candidate Moby.state at +0x20 and 0x002c9ab0-0x002c9ab4 excludes 0xFE. Checked caller 0x002c9c70 calls root at 0x002ca018 and established mark_moby_for_removal at 0x002ca040/48. That sibling compares its Moby pointer unsigned against pointer 0x0015ffdc at 0x002415f0, selects 0xFE for at-or-above at 0x00241604, and stores it to the same +0x20 state byte at 0x00241608. Authoritative source caller already names this exact Moby.state value MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF; reuse is supported by matching domain and removal assignment, not numeric equality alone. domain_1_value_253 -> MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF: Retail 0x002c9aac loads candidate Moby.state at +0x20 and 0x002c9ab8-0x002c9abc excludes 0xFD. Checked caller invokes both root and established mark_moby_for_removal at 0x002ca018 and 0x002ca040/48. Removal sibling 0x002415e4 loads pointer 0x0015ffdc; unsigned comparison 0x002415f0 takes the below-cutoff path selecting 0xFD at 0x00241600 and storing to Moby.state +0x20 at 0x00241608. This proves reuse of the source caller's existing MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF constant in the same state domain. --- src/overlays/l10/mobys/linked_moby_hitbox.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/overlays/l10/mobys/linked_moby_hitbox.c b/src/overlays/l10/mobys/linked_moby_hitbox.c index 0494ee8883..8b02b27a36 100644 --- a/src/overlays/l10/mobys/linked_moby_hitbox.c +++ b/src/overlays/l10/mobys/linked_moby_hitbox.c @@ -40,6 +40,10 @@ void spawn_linked_hitbox_contact_effects(struct Moby *moby, HitBox *box) __asm__("FUN_L10_002c9958"); void spawn_linked_hitbox_contact_effects(struct Moby *moby, HitBox *box) { + enum { + MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF = 0xFD, + MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF = 0xFE + }; OvlVec4 moby_rotation_basis[3]; OvlVec4 center; OvlVec4 delta; @@ -73,8 +77,8 @@ void spawn_linked_hitbox_contact_effects(struct Moby *moby, HitBox *box) { for (i = 0; i < count; i++) { struct Moby *hitbox_candidate_moby = found[i]; - if (hitbox_candidate_moby == 0 || hitbox_candidate_moby->state == 0xFE || - hitbox_candidate_moby->state == 0xFD) { + if (hitbox_candidate_moby == 0 || hitbox_candidate_moby->state == MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF || + hitbox_candidate_moby->state == MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF) { continue; } fast_vec_sub(&delta, &hitbox_candidate_moby->pos, &moby->pos); From 4d156938213e6a7b0dd1bb38e78bdeb602115043 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:06:48 +0000 Subject: [PATCH 1476/1502] decomp: clarify names in sandmouse_house_update domain_0_value_0 -> SANDMOUSE_HOUSE_INITIALIZE: Retail 0x002f2b8c-0x002f2b90 tests the house state byte at s0+0x20 against zero before yaw springing. The same byte feeds the jump table at 0x002f2bf4-0x002f2c14; its existing case zero is SANDMOUSE_HOUSE_INITIALIZE, which captures yaw at 0x002f2c44-0x002f2c54. domain_10_value_1 -> SANDMOUSE_HOUSE_WAIT_FOR_INITIAL_COMMAND: Retail 0x002f2e64-0x002f2ea0 completes restoration, selects animation 0 if necessary and writes 1 to house state +0x20. Initialization writes the same state at 0x002f2c4c; existing case 1 waits for the initial command at 0x002f2c58-0x002f2c64. domain_1_value_1 -> SANDMOUSE_HOUSE_WAIT_FOR_INITIAL_COMMAND: Initialization stores 1 into the same house state byte +0x20 at 0x002f2c48-0x002f2c4c. Existing case SANDMOUSE_HOUSE_WAIT_FOR_INITIAL_COMMAND selects that byte value and waits for command +0xBC in 3..5 at 0x002f2c58-0x002f2c64. domain_2_value_2 -> SANDMOUSE_HOUSE_WAIT_FOR_INITIAL_COMMAND_ANIMATION_END: Retail 0x002f2c58-0x002f2c98 accepts initial command 3..5, selects animation 1, then supplies state 2 to the common +0x20 store at 0x002f2ea0. Existing case 2 waits for animation flags +0x70 bit 2 at 0x002f2c9c-0x002f2ca4. domain_3_value_3 -> SANDMOUSE_HOUSE_WAIT_FOR_FOLLOWUP_COMMAND: Retail 0x002f2c9c-0x002f2cd8 completes the initial-command animation, selects animation 2 and writes state 3 through 0x002f2ea0. Existing case 3, on this same +0x20 selector, waits for followup commands at 0x002f2cdc-0x002f2d3c. domain_4_value_4 -> SANDMOUSE_HOUSE_WAIT_FOR_FOLLOWUP_COMMAND_ANIMATION_END: Retail 0x002f2cdc-0x002f2d1c accepts command 4/5, selects animation 3 and supplies state 4 to the common +0x20 store. Existing case 4 is the followup-animation wait, testing +0x70 bit 2 at 0x002f2d40-0x002f2d48. domain_5_value_7 -> SANDMOUSE_HOUSE_RESTORE_INITIAL_ANIMATION: In source case WAIT_FOR_FOLLOWUP_COMMAND, commands 7/1 route via retail 0x002f2d20-0x002f2d3c to 0x002f2e00-0x002f2e30, selecting animation 6 and storing 7 at +0x20. Existing house case 7 restores animation 0 after completion at 0x002f2e64-0x002f2ea0. domain_6_value_5 -> SANDMOUSE_HOUSE_WAIT_FOR_POST_FOLLOWUP_COMMAND: Retail 0x002f2d40-0x002f2d7c waits for followup animation completion, selects animation 4 and supplies state 5 to the +0x20 store. The existing case 5 on this same selector waits for post-followup commands 3/6/7/1 at 0x002f2d80-0x002f2da0. domain_7_value_6 -> SANDMOUSE_HOUSE_WAIT_FOR_POST_FOLLOWUP_COMMAND_ANIMATION_END: Retail 0x002f2d80-0x002f2dd8 accepts post-followup commands 3/6/7/1, selects animation 5 and supplies state 6 to +0x20. Existing case 6 tests animation completion at 0x002f2ddc-0x002f2de4 before choosing its next transition. domain_8_value_7 -> SANDMOUSE_HOUSE_RESTORE_INITIAL_ANIMATION: In source case WAIT_FOR_POST_FOLLOWUP_COMMAND_ANIMATION_END, completion plus command 7/1 routes through retail 0x002f2dec-0x002f2e30 to animation 6 and a store of 7 at +0x20. Existing house case 7 restores initialization animation 0 at 0x002f2e64-0x002f2ea0. domain_9_value_3 -> SANDMOUSE_HOUSE_WAIT_FOR_FOLLOWUP_COMMAND: The other branch of completed state 6 selects animation 2 and supplies state 3 at retail 0x002f2e34-0x002f2e60 for the common +0x20 store. This is the same selector and animation/state pair reached at 0x002f2cd8; existing case 3 waits for followup commands. --- src/overlays/shared/enemies/sandmouse_house.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/overlays/shared/enemies/sandmouse_house.c b/src/overlays/shared/enemies/sandmouse_house.c index ccf6348854..547beda85e 100644 --- a/src/overlays/shared/enemies/sandmouse_house.c +++ b/src/overlays/shared/enemies/sandmouse_house.c @@ -32,7 +32,7 @@ void sandmouse_house_update(unsigned char *moby) { return; house_vars = ((char *)MOBY(moby)->pvars); if (house_vars != 0) { - if (MOBY(moby)->state != 0) { + if (MOBY(moby)->state != SANDMOUSE_HOUSE_INITIALIZE) { if (D_0013D4C5 != 0) { if (hero.items[2].item_id == 5) { float yaw_response_scale = D_0015ED70_lui; @@ -51,7 +51,7 @@ void sandmouse_house_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(0)); } - MOBY(moby)->state = 1; + MOBY(moby)->state = SANDMOUSE_HOUSE_WAIT_FOR_INITIAL_COMMAND; *(float *)house_vars = MOBY(moby)->rot.z; break; case SANDMOUSE_HOUSE_WAIT_FOR_INITIAL_COMMAND: @@ -59,7 +59,7 @@ void sandmouse_house_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 1) { blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } - MOBY(moby)->state = 2; + MOBY(moby)->state = SANDMOUSE_HOUSE_WAIT_FOR_INITIAL_COMMAND_ANIMATION_END; } break; case SANDMOUSE_HOUSE_WAIT_FOR_INITIAL_COMMAND_ANIMATION_END: @@ -67,7 +67,7 @@ void sandmouse_house_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(3)); } - MOBY(moby)->state = 3; + MOBY(moby)->state = SANDMOUSE_HOUSE_WAIT_FOR_FOLLOWUP_COMMAND; } break; case SANDMOUSE_HOUSE_WAIT_FOR_FOLLOWUP_COMMAND: @@ -75,12 +75,12 @@ void sandmouse_house_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 3) { blend_moby_animation(moby, 3, 0, scale_game_frames(3)); } - MOBY(moby)->state = 4; + MOBY(moby)->state = SANDMOUSE_HOUSE_WAIT_FOR_FOLLOWUP_COMMAND_ANIMATION_END; } else if (MOBY(moby)->command == 7 || MOBY(moby)->command == 1) { if (MOBY(moby)->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(3)); } - MOBY(moby)->state = 7; + MOBY(moby)->state = SANDMOUSE_HOUSE_RESTORE_INITIAL_ANIMATION; } break; case SANDMOUSE_HOUSE_WAIT_FOR_FOLLOWUP_COMMAND_ANIMATION_END: @@ -88,7 +88,7 @@ void sandmouse_house_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 4) { blend_moby_animation(moby, 4, 0, scale_game_frames(3)); } - MOBY(moby)->state = 5; + MOBY(moby)->state = SANDMOUSE_HOUSE_WAIT_FOR_POST_FOLLOWUP_COMMAND; } break; case SANDMOUSE_HOUSE_WAIT_FOR_POST_FOLLOWUP_COMMAND: @@ -97,7 +97,7 @@ void sandmouse_house_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 5) { blend_moby_animation(moby, 5, 0, scale_game_frames(3)); } - MOBY(moby)->state = 6; + MOBY(moby)->state = SANDMOUSE_HOUSE_WAIT_FOR_POST_FOLLOWUP_COMMAND_ANIMATION_END; } break; case SANDMOUSE_HOUSE_WAIT_FOR_POST_FOLLOWUP_COMMAND_ANIMATION_END: @@ -106,12 +106,12 @@ void sandmouse_house_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 6) { blend_moby_animation(moby, 6, 0, scale_game_frames(3)); } - MOBY(moby)->state = 7; + MOBY(moby)->state = SANDMOUSE_HOUSE_RESTORE_INITIAL_ANIMATION; } else { if (MOBY(moby)->prev_seq != 2) { blend_moby_animation(moby, 2, 0, scale_game_frames(3)); } - MOBY(moby)->state = 3; + MOBY(moby)->state = SANDMOUSE_HOUSE_WAIT_FOR_FOLLOWUP_COMMAND; } } break; @@ -120,7 +120,7 @@ void sandmouse_house_update(unsigned char *moby) { if (MOBY(moby)->prev_seq != 0) { blend_moby_animation(moby, 0, 0, scale_game_frames(3)); } - MOBY(moby)->state = 1; + MOBY(moby)->state = SANDMOUSE_HOUSE_WAIT_FOR_INITIAL_COMMAND; } break; case 8: From c837762eb4977fb60d0b4bbc26ee4679d16d9c4a Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:06:49 +0000 Subject: [PATCH 1477/1502] decomp: clarify names in update_moby_proximity_interaction domain_0_value_42 -> PROXIMITY_MOBY_STATE_FOLLOWUP_SCENES: Retail 0x0028e190 retains the moby argument in s1; 0x0028e1a0 loads its state byte at +0x20 and 0x0028e1a4 branches on 42 to 0x0028e424. That branch tests one-time bytes at 0x0013D388+0x48..+0x4B and runs start_scene(4), start_scene(5), queue_scene_movie_with_game_language(11), or start_scene(6), setting each byte afterward (0x0028e43c-0x0028e4fc). This proves the follow-up-scenes state of this moby, not shared hero state 42. domain_1_value_42 -> PROXIMITY_MOBY_STATE_FOLLOWUP_SCENES: Retail 0x0028e3e0 loads 42 and 0x0028e3e8 stores it to +0x20 of the same moby retained in s1. This occurs after proximity/help/input acceptance and level 10 plus Clank vehicle-mode checks, then sets moby flags 0x41 and calls start_scene(9) at 0x0028e3ec-0x0028e3f8. The next update's exact same state-byte comparison at 0x0028e1a0-0x0028e1a4 selects the follow-up scene sequence at 0x0028e424-0x0028e4fc, proving reuse of PROXIMITY_MOBY_STATE_FOLLOWUP_SCENES. domain_2_value_0 -> PROXIMITY_MOBY_STATE_INTERACTIVE: After the state-42 branch has no eligible follow-up scene, retail 0x0028e504 stores zero to moby+0x20 and 0x0028e50c-0x0028e510 clears flags 0x41, restoring the previously suppressed interaction. On subsequent calls, 0x0028e1a0-0x0028e1a4 sends this zero state through the proximity tests (0x0028e284-0x0028e390) and help/input interaction gate (0x0028e394-0x0028e3c0). The authoritative source identifies this field as MOBY(moby)->state, proving the interactive state of this moby rather than HERO_STATE_IDLE or another equal-valued domain. --- .../shared/mobys/update_moby_proximity_interaction.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/mobys/update_moby_proximity_interaction.c b/src/overlays/shared/mobys/update_moby_proximity_interaction.c index 0988c02ad8..cf5b531699 100644 --- a/src/overlays/shared/mobys/update_moby_proximity_interaction.c +++ b/src/overlays/shared/mobys/update_moby_proximity_interaction.c @@ -28,6 +28,10 @@ extern void draw_light_flare() __asm__("func_0022DF40"); void update_moby_proximity_interaction(unsigned char *moby) __asm__("FUN_L00_0028e180"); void update_moby_proximity_interaction(unsigned char *moby) { + enum { + PROXIMITY_MOBY_STATE_INTERACTIVE = 0, + PROXIMITY_MOBY_STATE_FOLLOWUP_SCENES = 0x2A + }; char *proximity_state_data = ((char *)MOBY(moby)->pvars); float *moby_position; float proximity_test_position[4]; @@ -35,7 +39,7 @@ void update_moby_proximity_interaction(unsigned char *moby) { int one; unsigned char *hero_position_or_scene_flags; - if (MOBY(moby)->state != 0x2A) { + if (MOBY(moby)->state != PROXIMITY_MOBY_STATE_FOLLOWUP_SCENES) { if (MOBY(moby)->visible != 0) { MOBY(moby)->command += 2; color_pulse_intensity = @@ -84,7 +88,7 @@ void update_moby_proximity_interaction(unsigned char *moby) { int help_message_accepted = try_set_help_message(2, 0x53E4) != 0; if ((pad_pressed_words[0] & 0x10) && help_message_accepted) { if (current_level_index == 10 && hero.vehicle_mode == HERO_VEHICLE_MODE_CLANK) { - MOBY(moby)->state = 0x2A; + MOBY(moby)->state = PROXIMITY_MOBY_STATE_FOLLOWUP_SCENES; MOBY(moby)->flags |= 0x41; start_scene(9); } else { @@ -116,7 +120,7 @@ void update_moby_proximity_interaction(unsigned char *moby) { start_scene(6); hero_position_or_scene_flags[0x4B] = 1; } else { - MOBY(moby)->state = 0; + MOBY(moby)->state = PROXIMITY_MOBY_STATE_INTERACTIVE; MOBY(moby)->flags &= 0xFFBE; one = 1; ship_index[1] = one; From 0a2de529f12ccd81a3792ea31d199bf673ef2165 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:08:29 +0000 Subject: [PATCH 1478/1502] decomp: clarify names in update_bolt_grounded_pose domain_1_value_1 -> BOLT_FALLING: Retail 0x002a6e00 retains input bolt a0 in s4; 0x002a711c loads 1 and 0x002a7128 stores it to that same bolt's current-state byte at +0x20. Original Ghidra likewise assigns *(undefined1 *)(iVar7 + 0x20)=1. The gated branch resets spin at pvars+0x30, sets quaternion w=1, initializes velocity at +0x20, adds it to bolt position and clears ground_moby at 0x002a71cc. Authoritative bolt_update declares BOLT_FALLING=1, handles that state with gravity, velocity integration and collision/settling, and calls this function with the same Bolt in BOLT_IDLE and BOLT_SETTLING. spawn_bolt_by_value also uses BOLT_FALLING=1 for newly airborne bolts. Thus this is the established bolt current-state member, unrelated to HeroStateId, HeroGravityMode, HeroVehicleMode or TRUE. --- src/overlays/shared/pickups/bolt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/shared/pickups/bolt.c b/src/overlays/shared/pickups/bolt.c index 4691e4fc88..a98fd6cdc9 100644 --- a/src/overlays/shared/pickups/bolt.c +++ b/src/overlays/shared/pickups/bolt.c @@ -542,6 +542,9 @@ void update_bolt_grounded_pose(char *moby, void *base_position_output, void *bas enum { BOLT_IDLE = 3 }; + enum { + BOLT_FALLING = 1 + }; char *grounded_bolt_vars = ((char *)MOBY(moby)->pvars); float local_rotation_basis[12]; float base_rotation_basis[12]; @@ -632,7 +635,7 @@ void update_bolt_grounded_pose(char *moby, void *base_position_output, void *bas coll_sphere(ground_collision_radius, &MOBY(moby)->pos, 0x22, moby) == 0; } if (should_detach_from_ground) { - MOBY(moby)->state = 1; + MOBY(moby)->state = BOLT_FALLING; clear_u64_value(grounded_bolt_vars + 0x30); *(float *)(grounded_bolt_vars + 0x3C) = 1.0f; x = FUN_L00_002603d0_c(*(char **)(grounded_bolt_vars + 0x5C)); From 68707b8d1fcc638635cd9c625daa6b6cd5326fbb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:10:15 +0000 Subject: [PATCH 1479/1502] decomp: clarify names in path_following_moby_update domain_0_value_1 -> MOBY_STATE_FOLLOW_PATH: Retail loads the selector from moby+0x20 at 0x002de894; comparison with 1 at 0x002de8a4 enters path sampling at 0x002de950. Initialization computes progress/increment and height offset at 0x002de924-0x002de940, then stores s5=1 into that same state byte at 0x002de948 and falls through to sampling. Thus this assignment selects the existing local MOBY_STATE_FOLLOW_PATH member, not the independent loop argument 1. domain_1_value_2 -> MOBY_STATE_FALLING: Retail 0x002dec40-0x002dec44 stores 2 into moby+0x20 after the hit path seeds velocity from frame displacement at 0x002deba4-0x002debbc and adds upward velocity at 0x002dec18. The same byte is the switch selector at 0x002de894; dispatch of 2 at 0x002de8c8 enters gravity subtraction and position integration at 0x002de9c4-0x002dea38. This proves reuse of existing local MOBY_STATE_FALLING, also already used by the hit guard. --- src/overlays/l08/mobys/path_following_moby.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlays/l08/mobys/path_following_moby.c b/src/overlays/l08/mobys/path_following_moby.c index f5e971a303..2788d966d9 100644 --- a/src/overlays/l08/mobys/path_following_moby.c +++ b/src/overlays/l08/mobys/path_following_moby.c @@ -135,7 +135,7 @@ void path_following_moby_update(char *moby) { moby_vars->unk4 = moby_vars->unk4 * (float)*path; moby_vars->unkC = randf_sym(0.0f, 5.0f); } - MOBY(moby)->state = 1; + MOBY(moby)->state = MOBY_STATE_FOLLOW_PATH; MOBY(moby)->update_dist = 0xFF; case MOBY_STATE_FOLLOW_PATH: { float path_point_count; @@ -224,7 +224,7 @@ void path_following_moby_update(char *moby) { 1, -1, 0); - MOBY(moby)->state = 2; + MOBY(moby)->state = MOBY_STATE_FALLING; } MOBY(moby)->hit_slot = 0xFF; if (MOBY(moby)->visible != 0) { From a86f6019f3b832ab0ce7e2fb91e4a3ab0a29947e Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:10:15 +0000 Subject: [PATCH 1480/1502] decomp: clarify names in door_update domain_0_value_1 -> DOOR_WAIT_TO_MOVE_TO_OFFSET_POSITION: Retail 00310e54 loads the door selector from s2+0x20; 00310e7c-00310eb4 saves the initial position, clears progress and writes 1 to that same field at 00310eac. This enters the existing local enum's waiting branch at 00310eb8, which gates offset movement on the linked moby's configured state. domain_10_value_4 -> DOOR_RETURN_TO_INITIAL_POSITION: Retail 003110e4-00311118 requires a valid linked moby whose state matches door data+0x18. It clears progress at 00311128, optionally plays sound, and loads 4 at 0031113c for the s2+0x20 store at 0031129c. This enters the existing DOOR_RETURN_TO_INITIAL_POSITION selector branch, which applies negative offset motion and restores the saved position. domain_13_value_2 -> DOOR_MOVE_TO_OFFSET_POSITION: Within the return branch, retail 00311160-00311194 checks missing/invalid linked moby or linked state equal to data+0x14. The selected reversal path loads 2 at 003111b8 and stores to the door selector s2+0x20 at 0031129c. The same field is switched at 00310e54, and its existing DOOR_MOVE_TO_OFFSET_POSITION branch advances toward the configured offset. domain_14_value_1 -> DOOR_WAIT_TO_MOVE_TO_OFFSET_POSITION: Retail 0031124c-00311260 detects completed return and copies saved initial position from s1 to door position s2+0x10. After sound/status handling it loads 1 at 00311298 and stores to s2+0x20 at 0031129c. This re-enters the existing DOOR_WAIT_TO_MOVE_TO_OFFSET_POSITION branch on the identical door-state selector. domain_3_value_2 -> DOOR_MOVE_TO_OFFSET_POSITION: Retail case 1 initializes offset length from door data+0x1c/+0x20/+0x24 at 00310f14-00310f50, then loads 2 at 00310f64 and stores it to s2+0x20 at 0031129c. That same selector dispatches to the existing DOOR_MOVE_TO_OFFSET_POSITION case, whose 00310ffc-00311078 path advances position and decrements remaining distance. domain_6_value_4 -> DOOR_RETURN_TO_INITIAL_POSITION: In the offset movement branch, retail 00310f8c-00310fc0 tests linked moby+0x20 against door data+0x18. On equality it plays the movement sound and loads 4 at 00310fe0, storing to door s2+0x20 at 0031129c. This is the same selector as the existing DOOR_RETURN_TO_INITIAL_POSITION case, whose reverse step and saved-position restore occur at 003111bc-00311260. domain_7_value_3 -> DOOR_WAIT_TO_RETURN_TO_INITIAL_POSITION: Retail 00311068-00311088 detects completed offset travel and sets position to saved initial position plus transformed offset. It clears progress and writes 3 to door s2+0x20 at 0031108c-00311094, entering the existing DOOR_WAIT_TO_RETURN_TO_INITIAL_POSITION branch at 003110c0, which waits for linked state data+0x18. --- src/overlays/shared/props/door.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/props/door.c b/src/overlays/shared/props/door.c index 9379cf06a0..02118e7c8d 100644 --- a/src/overlays/shared/props/door.c +++ b/src/overlays/shared/props/door.c @@ -57,7 +57,7 @@ void door_update(u8 *moby) { qcopy(door_data, &MOBY(moby)->pos); if (door_data->unk38 != -1) D_L07_00184528[door_data->unk38] = 0; - MOBY(moby)->state = 1; + MOBY(moby)->state = DOOR_WAIT_TO_MOVE_TO_OFFSET_POSITION; *(s32 *)&door_data->unkC = 0; return; case DOOR_WAIT_TO_MOVE_TO_OFFSET_POSITION: @@ -77,7 +77,7 @@ void door_update(u8 *moby) { door_data->unkC = fast_vec_length(vectors); if (door_data->sound_entry != -1) allocate_voice_for_target_entry(door_data->sound_entry, 0, moby); - MOBY(moby)->state = 2; + MOBY(moby)->state = DOOR_MOVE_TO_OFFSET_POSITION; return; case DOOR_MOVE_TO_OFFSET_POSITION: if (door_data->unk38 != -1) @@ -88,7 +88,7 @@ void door_update(u8 *moby) { MOBY(linked_moby)->state != 0xfd && MOBY(linked_moby)->state == door_data->unk18) { if (door_data->sound_entry != -1) allocate_voice_for_target_entry(door_data->sound_entry, 0, moby); - MOBY(moby)->state = 4; + MOBY(moby)->state = DOOR_RETURN_TO_INITIAL_POSITION; return; } } @@ -105,7 +105,7 @@ void door_update(u8 *moby) { return; fast_vec_add(&MOBY(moby)->pos, door_data, vectors); door_data->unkC = 0.0f; - MOBY(moby)->state = 3; + MOBY(moby)->state = DOOR_WAIT_TO_RETURN_TO_INITIAL_POSITION; if (door_data->unk34 != -1) allocate_voice_for_target_entry(door_data->sound_entry, 0, moby); return; @@ -121,7 +121,7 @@ void door_update(u8 *moby) { *(s32 *)&door_data->unkC = 0; if (door_data->sound_entry != -1) allocate_voice_for_target_entry(door_data->sound_entry, 0, moby); - MOBY(moby)->state = 4; + MOBY(moby)->state = DOOR_RETURN_TO_INITIAL_POSITION; return; case DOOR_RETURN_TO_INITIAL_POSITION: if (door_data->unk38 != -1) @@ -132,7 +132,7 @@ void door_update(u8 *moby) { MOBY(linked_moby)->state == door_data->unk14) { if (door_data->sound_entry != -1) allocate_voice_for_target_entry(door_data->sound_entry, 0, moby); - MOBY(moby)->state = 2; + MOBY(moby)->state = DOOR_MOVE_TO_OFFSET_POSITION; } else { *(quadword *)(vectors + 4) = 0; vectors[4] = door_data->unk1C; @@ -151,7 +151,7 @@ void door_update(u8 *moby) { allocate_voice_for_target_entry(door_data->unk34, 0, moby); if (door_data->unk38 != -1) D_L07_00184528[door_data->unk38] = 0; - MOBY(moby)->state = 1; + MOBY(moby)->state = DOOR_WAIT_TO_MOVE_TO_OFFSET_POSITION; } break; case 5: From 442414b40cc98ab9cb0042c5cbcbeaf1f28ae992 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:14:42 +0000 Subject: [PATCH 1481/1502] decomp: clarify names in bridge_update domain_0_value_1 -> BRIDGE_WAIT_TO_MOVE_TO_OFFSET_POSITION: Retail 0x0031afd8-0x0031afdc stores 1 to 0x20(s4), the same moby state byte loaded at 0x0031af78 for the switch. Initialization saves the starting position and clears progress; established case 1 waits for the linked-state condition before outbound travel. domain_10_value_4 -> BRIDGE_RETURN_TO_INITIAL_POSITION: Retail 0x0031b1e0-0x0031b244 checks the linked state against bridge_data+0xb8 while waiting at the offset position, clears progress and loads 4 for the shared moby+0x20 store at 0x0031b398. The same byte selects established return-to-initial-position case 4. domain_13_value_2 -> BRIDGE_MOVE_TO_OFFSET_POSITION: Retail 0x0031b248-0x0031b2a4 checks the outbound linked-state condition during return travel and loads 2 for the shared store to moby+0x20 at 0x0031b398. This is the same selector loaded at 0x0031af78 and already names case 2 BRIDGE_MOVE_TO_OFFSET_POSITION, resuming outbound motion. domain_14_value_1 -> BRIDGE_WAIT_TO_MOVE_TO_OFFSET_POSITION: Retail 0x0031b354-0x0031b35c restores bridge_data+0xa0 into the moby position on return completion; 0x0031b390 clears the optional flag and 0x0031b394-0x0031b398 stores 1 to moby+0x20. This is the same bridge selector whose established case 1 waits before moving to the offset position. domain_3_value_2 -> BRIDGE_MOVE_TO_OFFSET_POSITION: Retail 0x0031b028-0x0031b064 initializes travel distance from configured offset +0xbc/+0xc0/+0xc4, then 0x0031b074 loads 2 for the shared store to moby+0x20 at 0x0031b398. This is the exact selector of established BRIDGE_MOVE_TO_OFFSET_POSITION case 2. domain_6_value_4 -> BRIDGE_RETURN_TO_INITIAL_POSITION: Retail 0x0031b080-0x0031b0b8 checks linked moby state against bridge_data+0xb8 while outbound, then 0x0031b0d4 loads 4 for the moby+0x20 store at 0x0031b398. The same selector dispatches established return case 4, which applies negative travel and restores the saved initial position. domain_7_value_3 -> BRIDGE_WAIT_TO_RETURN_TO_INITIAL_POSITION: Retail 0x0031b180-0x0031b1bc snaps position to saved initial position plus transformed offset, clears progress, sets the optional flag and stores 3 directly to moby+0x20. That byte is the switch selector; established case 3 waits for the linked return condition before entering return state 4. --- src/overlays/shared/props/bridge.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/shared/props/bridge.c b/src/overlays/shared/props/bridge.c index ab2ebf0f84..079d42319f 100644 --- a/src/overlays/shared/props/bridge.c +++ b/src/overlays/shared/props/bridge.c @@ -66,7 +66,7 @@ void bridge_update(u8 *moby) { qcopy(&bridge_data->unkA0, &MOBY(moby)->pos); if (bridge_data->unkD8 != -1) D_L07_00184528[bridge_data->unkD8] = 0; - MOBY(moby)->state = 1; + MOBY(moby)->state = BRIDGE_WAIT_TO_MOVE_TO_OFFSET_POSITION; *(s32 *)&bridge_data->unkA0[3] = 0; break; case BRIDGE_WAIT_TO_MOVE_TO_OFFSET_POSITION: @@ -85,7 +85,7 @@ void bridge_update(u8 *moby) { bridge_data->unkA0[3] = fast_vec_length(vectors); if (bridge_data->unkD0 != -1) allocate_voice_for_target_entry(bridge_data->unkD0, 0, moby); - MOBY(moby)->state = 2; + MOBY(moby)->state = BRIDGE_MOVE_TO_OFFSET_POSITION; break; case BRIDGE_MOVE_TO_OFFSET_POSITION: if (bridge_data->unkB0 != -1) { @@ -95,7 +95,7 @@ void bridge_update(u8 *moby) { MOBY(linked_state_moby)->state == bridge_data->unkB8) { if (bridge_data->unkD0 != -1) allocate_voice_for_target_entry(bridge_data->unkD0, 0, moby); - MOBY(moby)->state = 4; + MOBY(moby)->state = BRIDGE_RETURN_TO_INITIAL_POSITION; break; } } @@ -113,7 +113,7 @@ void bridge_update(u8 *moby) { bridge_data->unkA0[3] = 0.0f; if (bridge_data->unkD8 != -1) D_L07_00184528[bridge_data->unkD8] = 1; - MOBY(moby)->state = 3; + MOBY(moby)->state = BRIDGE_WAIT_TO_RETURN_TO_INITIAL_POSITION; if (bridge_data->unkD4 != -1) allocate_voice_for_target_entry(bridge_data->unkD0, 0, moby); } @@ -127,7 +127,7 @@ void bridge_update(u8 *moby) { *(s32 *)&bridge_data->unkA0[3] = 0; if (bridge_data->unkD0 != -1) allocate_voice_for_target_entry(bridge_data->unkD0, 0, moby); - MOBY(moby)->state = 4; + MOBY(moby)->state = BRIDGE_RETURN_TO_INITIAL_POSITION; } } break; @@ -138,7 +138,7 @@ void bridge_update(u8 *moby) { MOBY(linked_state_moby)->state == bridge_data->unkB4) { if (bridge_data->unkD0 != -1) allocate_voice_for_target_entry(bridge_data->unkD0, 0, moby); - MOBY(moby)->state = 2; + MOBY(moby)->state = BRIDGE_MOVE_TO_OFFSET_POSITION; } else { *(quadword *)(vectors + 4) = 0; vectors[4] = bridge_data->unkBC; @@ -156,7 +156,7 @@ void bridge_update(u8 *moby) { allocate_voice_for_target_entry(bridge_data->unkD4, 0, moby); if (bridge_data->unkD8 != -1) D_L07_00184528[bridge_data->unkD8] = 0; - MOBY(moby)->state = 1; + MOBY(moby)->state = BRIDGE_WAIT_TO_MOVE_TO_OFFSET_POSITION; } } break; From abfa4f250a4ae99b25e48a60f0b24802097c29b6 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:16:34 +0000 Subject: [PATCH 1482/1502] decomp: clarify names in linked_spark_emitter_update domain_0_value_1 -> EMIT_SPARKS: The selector is this emitter's own MOBY(moby)->state, loaded from +0x20 at retail 0x002a2c34. Initialization stores 1 to the same byte at 0x002a2ce4 after the save/kill checks pass. The dispatch at 0x002a2c38 branches on 1 to 0x002a2cfc, whose body emits sixteen sparks through 0x002647f0 at 0x002a3034. Thus this assignment enters the existing local EMIT_SPARKS=1 case, not an unrelated boolean or shared state domain. domain_1_value_3 -> EFFECT_DISABLED: Retail 0x002a2c98 and 0x002a2cd8 send initialization to 0x002a2ce8 when the cleared/save or kill-bit checks prevent emission. 0x002a2ce8-0x002a2cf8 stores 3 to this emitter's state byte +0x20, sets command to 0xFF and clears collision. The dispatcher at 0x002a2c34-0x002a2c68 handles only 0, 1 and 2; state 3 returns without spark emission or draw-callback registration. EFFECT_DISABLED names that observed terminal inactive effect state. domain_2_value_3 -> EFFECT_DISABLED: In the existing WAIT_FOR_EFFECT_TIMEOUT case, retail 0x002a30c0-0x002a30d4 increments pvars+0x14 and tests its prior value against 0x3D. At timeout 0x002a30d8-0x002a30e0 stores 3 to the same moby+0x20 state byte dispatched at 0x002a2c34; it skips the draw callback otherwise scheduled at 0x002a30f0. State 3 is unhandled and returns on later updates, matching the disabled state selected by initialization at 0x002a2cec. Reuse EFFECT_DISABLED for both assignments in this same emitter-state domain. --- src/overlays/shared/props/linked_spark_emitter.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/overlays/shared/props/linked_spark_emitter.c b/src/overlays/shared/props/linked_spark_emitter.c index 35ddcf6526..779540489b 100644 --- a/src/overlays/shared/props/linked_spark_emitter.c +++ b/src/overlays/shared/props/linked_spark_emitter.c @@ -74,6 +74,9 @@ void linked_spark_emitter_update(unsigned char *moby) { EMIT_SPARKS = 1, WAIT_FOR_EFFECT_TIMEOUT = 2 }; + enum { + EFFECT_DISABLED = 3 + }; unsigned char *moby_data = ((unsigned char *)MOBY(moby)->pvars); float V[4]; float W[16]; @@ -91,11 +94,11 @@ void linked_spark_emitter_update(unsigned char *moby) { (((*(int *)(D_0014C190 + (((short)id >> 5) * 4) + (D_0015ED84 << 8)) >> (id & 0x1F)) ^ 1) & 1)) { - MOBY(moby)->state = 1; + MOBY(moby)->state = EMIT_SPARKS; } else { MOBY(moby)->command = 0xFF; MOBY(moby)->collision = 0; - MOBY(moby)->state = 3; + MOBY(moby)->state = EFFECT_DISABLED; } break; } @@ -165,7 +168,7 @@ void linked_spark_emitter_update(unsigned char *moby) { } case WAIT_FOR_EFFECT_TIMEOUT: if ((*(int *)(moby_data + 0x14))++ >= 0x3D) { - MOBY(moby)->state = 3; + MOBY(moby)->state = EFFECT_DISABLED; } else { qzero(moby_data); add_draw_callback(func_L15_002A4318_2A3DD0, moby); From dce1716504a0ec169a21ec309c1f0f9c6d6d3e40 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:16:34 +0000 Subject: [PATCH 1483/1502] decomp: clarify names in timed_activation_pads_update domain_0_value_6 -> PAD_INITIALIZE_FLASHING: Source SHA-256 21fe678af80e7a179327988ed7228bca304df07006564290bc2c69f9a0d9c31a compares MOBY(moby)->state, the same byte at moby+0x20 used by the outer PAD_* switch. Retail 0030bfc8-0030bfcc loads that byte and tests it below 6. Existing PAD_INITIALIZE_FLASHING=6 is that domain's boundary: 0030c3cc-0030c3f4 initializes the flash timer and phase and enters state 7. This reuses the established state member, not a nested flash-phase constant. domain_1_value_3 -> PAD_WAIT_TO_ENTER_FLASH_ACTIVATION_WAIT: In source case PAD_ADVANCE_TO_FLASH_ACTIVATION_GATE, assignment to MOBY(moby)->state writes the outer pad-state selector. Retail 0030c334 branches to the common sb v0,0x20(s2) at 0030c4d8, with 0030c338 loading 3. Dispatch of that same byte at 0030c248-0030c268 reaches state 3, whose 0030c33c activation gate and 0030c36c-0030c374 state-4 request match existing PAD_WAIT_TO_ENTER_FLASH_ACTIVATION_WAIT=3. domain_2_value_5 -> PAD_WAIT_FOR_FLASH_ACTIVATION: Source case PAD_ENTER_FLASH_ACTIVATION_WAIT assigns the same MOBY(moby)->state byte consumed by the outer switch. Retail 0030c380 branches to byte store 0030c4d8 and delay slot 0030c384 loads 5. State 5 at 0030c388 waits for activation flag s5, then sets pad data+8, applies green and requests state 6 at 0030c3ac-0030c3b0. Thus the assignment reuses existing outer-state member PAD_WAIT_FOR_FLASH_ACTIVATION=5. domain_3_value_7 -> PAD_UPDATE_FLASHING: Source case PAD_INITIALIZE_FLASHING initializes pad_data->unkC and unkE and assigns MOBY(moby)->state=7. Retail 0030c3cc-0030c3ec initializes the short timer, clears phase and applies pale green; 0030c3f0-0030c3f4 loads 7 and branches to sb at moby+0x20 in 0030c4d8. This exact outer selector dispatches existing PAD_UPDATE_FLASHING=7, whose 0030c434-0030c4b8 reloads the flash timer and alternates colors. domain_4_value_1 -> PAD_WAIT_FOR_ACTIVATION: Source case PAD_RESET_TO_ACTIVATION_WAIT assigns MOBY(moby)->state=1 after gray color and clearing command. Retail 0030c4bc-0030c4d8 applies gray, loads 1, clears moby+0xBC and stores 1 to moby+0x20. That same outer switch byte dispatches existing PAD_WAIT_FOR_ACTIVATION=1 at 0030c2a4, clearing pad data+8 and waiting at 0030c2bc for activation before starting the duration timer. PAD_FLASH_APPLY_WHITE=1 belongs to separate pad_data->unkE and is not applicable. --- src/overlays/shared/props/timed_activation_pads.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/props/timed_activation_pads.c b/src/overlays/shared/props/timed_activation_pads.c index dd2357be8e..f6a005d787 100644 --- a/src/overlays/shared/props/timed_activation_pads.c +++ b/src/overlays/shared/props/timed_activation_pads.c @@ -63,7 +63,7 @@ void timed_activation_pads_update(unsigned char *moby) { return; flag = 0; - if (MOBY(moby)->state < 6) { + if (MOBY(moby)->state < PAD_INITIALIZE_FLASHING) { if (MOBY(moby)->mission != 0xFF) { if (visited52[MOBY(moby)->mission + (current_level_index << 4)] == 0xFF) set_moby_list_state(MOBY(moby)->group, 6); @@ -137,7 +137,7 @@ void timed_activation_pads_update(unsigned char *moby) { } break; case PAD_ADVANCE_TO_FLASH_ACTIVATION_GATE: - MOBY(moby)->state = 3; + MOBY(moby)->state = PAD_WAIT_TO_ENTER_FLASH_ACTIVATION_WAIT; break; case PAD_WAIT_TO_ENTER_FLASH_ACTIVATION_WAIT: if (flag) { @@ -148,7 +148,7 @@ void timed_activation_pads_update(unsigned char *moby) { } break; case PAD_ENTER_FLASH_ACTIVATION_WAIT: - MOBY(moby)->state = 5; + MOBY(moby)->state = PAD_WAIT_FOR_FLASH_ACTIVATION; break; case PAD_WAIT_FOR_FLASH_ACTIVATION: if (flag) { @@ -162,7 +162,7 @@ void timed_activation_pads_update(unsigned char *moby) { pad_data->unkC = func_001F9850_30D370(0x14); pad_data->unkE = 0; glow_n(moby, 0x80, 0xFF, 0x80); - MOBY(moby)->state = 7; + MOBY(moby)->state = PAD_UPDATE_FLASHING; break; case PAD_UPDATE_FLASHING: if (MOBY(moby)->mission != 0xFF) { @@ -189,7 +189,7 @@ void timed_activation_pads_update(unsigned char *moby) { case PAD_RESET_TO_ACTIVATION_WAIT: glow_n(moby, 0x80, 0x80, 0x80); MOBY(moby)->command = 0; - MOBY(moby)->state = 1; + MOBY(moby)->state = PAD_WAIT_FOR_ACTIVATION; break; case 9: break; From 3d9bc9cfc21d2ab290fb15e1ea69a0a2c3c12e70 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:16:34 +0000 Subject: [PATCH 1484/1502] decomp: clarify names in update_hovering_rocket_attacker_common domain_0_value_0 -> UPDATE_INITIALIZE: Assigned retail 0x002c2d54-0x002c2d58 tests moby/s2+0x20 and returns for zero. Checked caller request df81b031ab914b94b0be2dff887265ba calls common at 0x002c25dc, then loads the same moby+0x20 at 0x002c25e4 for dispatch. Authoritative caller C names zero UPDATE_INITIALIZE; its initialization branch 0x002c2610-0x002c26f4 copies hover center, initializes health, creates rockets and selects the next state. This proves the same state domain, independently of HIT_REACTION_NONE. domain_1_value_7 -> WAIT_TO_RESUME_ATTACK_SEQUENCE: Retail 0x002c30d4 loads s0=7; after damage subtraction, positive health takes 0x002c3114-0x002c3118 and stores s0 to moby/s2+0x20. Original Ghidra and authoritative C agree. Checked caller df81b031ab914b94b0be2dff887265ba loads that same byte after the common call at 0x002c25dc. Authoritative caller names state 7 WAIT_TO_RESUME_ATTACK_SEQUENCE: 0x002c2cd0-0x002c2d08 waits for animation flag 2, restores command animation and stores state 4 to resume attack dispatch. This is not hit-reaction code 7. domain_2_value_8 -> EMIT_EFFECT_AND_REMOVE: Original Ghidra and authoritative C map lethal/remove reactions to retail 0x002c315c-0x002c3178, calling removal preparation and storing 8 to moby/s2+0x20. Checked caller df81b031ab914b94b0be2dff887265ba dispatches the same byte after common at 0x002c25dc. Its established state 8 EMIT_EFFECT_AND_REMOVE branch at 0x002c2c28-0x002c2cc4 emits an effect, removes both attached rockets if present, then removes the moby. Thus this assignment uses the caller state domain, not equal-valued hit reaction 8. domain_3_value_4 -> UPDATE_ATTACK_SEQUENCE: Retail 0x002c31a0-0x002c31c4 loads moby/s2+0x20 and compares it with 4, selecting target range 50 instead of 40. Original Ghidra and authoritative C show this state comparison. Checked caller df81b031ab914b94b0be2dff887265ba loads the identical byte at 0x002c25e4 after invoking common. Authoritative caller names state 4 UPDATE_ATTACK_SEQUENCE; its 0x002c28cc-0x002c2c24 body aims toward the target, dispatches the separate command byte at +0xBC and alternates rocket launches. This proves domain membership rather than numeric equality with hit-reaction 4. domain_4_value_5 -> WAIT_TO_MOVE_TO_TABLE_POINT: Retail 0x002c325c-0x002c3264 compares moby/s2+0x20 with 5 and skips the visibility line probe when equal. Original Ghidra and authoritative C agree. Checked caller df81b031ab914b94b0be2dff887265ba dispatches this same state byte after common; authoritative caller names 5 WAIT_TO_MOVE_TO_TABLE_POINT. Initialization chooses 5 when data+0xD4 is not -1 at 0x002c26b8-0x002c26d4; its wait branch 0x002c26f8-0x002c270c waits while data+0xB4==2 and otherwise selects state 6, whose following branch moves toward the table/cuboid point. This is separate from command 5 and hit-reaction 5. --- .../l13/mobys/hovering_rocket_attacker.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/overlays/l13/mobys/hovering_rocket_attacker.c b/src/overlays/l13/mobys/hovering_rocket_attacker.c index 4a7471c613..0c5d2450e1 100644 --- a/src/overlays/l13/mobys/hovering_rocket_attacker.c +++ b/src/overlays/l13/mobys/hovering_rocket_attacker.c @@ -386,6 +386,13 @@ void update_hovering_rocket_attacker_common(unsigned char *moby) { enum { TARGET_SELECTION_NO_TARGET = 2 }; + enum { + UPDATE_INITIALIZE = 0, + UPDATE_ATTACK_SEQUENCE = 4, + WAIT_TO_MOVE_TO_TABLE_POINT = 5, + WAIT_TO_RESUME_ATTACK_SEQUENCE = 7, + EMIT_EFFECT_AND_REMOVE = 8 + }; HoveringRocketAttackerVars *moby_data; char *hit_record; int hit_reaction_code; @@ -400,7 +407,7 @@ void update_hovering_rocket_attacker_common(unsigned char *moby) { float z[4]; moby_data = ((unsigned char *)MOBY(moby)->pvars); - if (MOBY(moby)->state == 0) + if (MOBY(moby)->state == UPDATE_INITIALIZE) return; if (moby_data->unk110 == -1 || voice_is_playing(moby, moby_data->unk110) == 0) { moby_data->unk110 = -1; @@ -499,7 +506,7 @@ void update_hovering_rocket_attacker_common(unsigned char *moby) { if (moby_data->health <= 0.0f) { hit_reaction_code = 1; } else { - MOBY(moby)->state = 7; + MOBY(moby)->state = WAIT_TO_RESUME_ATTACK_SEQUENCE; } switch (hit_reaction_code) { case HIT_REACTION_HIGH_INTERPOLATION_TARGET: @@ -517,7 +524,7 @@ void update_hovering_rocket_attacker_common(unsigned char *moby) { case HIT_REACTION_LETHAL: case HIT_REACTION_REMOVE: FUN_L00_00257470(moby, 0, -1); - MOBY(moby)->state = 8; + MOBY(moby)->state = EMIT_EFFECT_AND_REMOVE; moby_data->unk67 = 0xF0; break; case HIT_REACTION_NONE: @@ -529,7 +536,7 @@ void update_hovering_rocket_attacker_common(unsigned char *moby) { } MOBY(moby)->hit_slot = 0xFF; trooper_anim_finish(moby, &moby_data->anim_state); - if (MOBY(moby)->state == 4) { + if (MOBY(moby)->state == UPDATE_ATTACK_SEQUENCE) { moby_data->unkD8 = 50.0f; } else { moby_data->unkD8 = 40.0f; @@ -548,7 +555,7 @@ void update_hovering_rocket_attacker_common(unsigned char *moby) { if (moby_data->unkD8 < vector_distance_xy(moby + 0x10, moby_data->unk70) || 8.0f < absolute_float(MOBY(moby)->pos.z - moby_data->unk70[2])) { moby_data->unkB4 = 2; - } else if (MOBY(moby)->state != 5 && + } else if (MOBY(moby)->state != WAIT_TO_MOVE_TO_TABLE_POINT && collision_line(moby + 0x10, D_0013F350 + 0xD0, 2, moby, 0) != 0) { moby_data->unkB4 = 2; } From 74a40bfd64a4b95dbf3f54d426c82752e5404d20 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:18:13 +0000 Subject: [PATCH 1485/1502] decomp: clarify names in switchable_beam_barrier_update domain_0_value_1 -> WAIT_FOR_LINKED_MOBY: Retail 0x00304acc stores 1 at this moby's +0x20 when pvars+0xF10 is not -1, disabling collision. Dispatch 0x00304a34-0x00304a38 reads that same state byte and enters 0x00304ae0, which indexes the linked moby and waits on its class/state. This is the existing local WAIT_FOR_LINKED_MOBY domain member. domain_1_value_2 -> UPDATE_VECTOR_STREAMS: Initialization without a linked index branches at 0x00304ad8 with v0=2 (0x00304adc) to the state-byte store 0x00304fc4. That same +0x20 state is dispatched at 0x00304a5c to 0x00304b2c, the four-stream audio/collision/vector update branch already named UPDATE_VECTOR_STREAMS. domain_2_value_2 -> UPDATE_VECTOR_STREAMS: After the linked moby wait clears, 0x00304b14 loads 2 and 0x00304b1c stores it at this moby's +0x20; 0x00304b28 restores class collision. Dispatch of the identical byte at 0x00304a5c selects the four timed vector-stream update at 0x00304b2c, reusing existing UPDATE_VECTOR_STREAMS. domain_3_value_3 -> EMIT_PARTICLE_BURST: When the linked +0xBC flag is nonzero, 0x00304d80 loads 3 and 0x00304d88 stores it at this moby's +0x20, with collision disabled and stream voice released. The same state byte dispatches at 0x00304a64 to 0x00304dec, whose four transforms each emit 50 particles. Reuse existing EMIT_PARTICLE_BURST. domain_4_value_4 -> PARTICLE_BURST_COMPLETE: Retail 0x00304fa8 finishes the 50-particle inner loop and 0x00304fb4-0x00304fb8 finishes all four transforms, then 0x00304fc0-0x00304fc4 stores 4 into the same moby+0x20 state byte. Dispatch 0x00304a34-0x00304a6c handles only 0..3, so this marks completed particle emission and prevents another burst in this updater; no broader destruction lifecycle is asserted. --- src/overlays/l06/mobys/switchable_beam_barrier.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/overlays/l06/mobys/switchable_beam_barrier.c b/src/overlays/l06/mobys/switchable_beam_barrier.c index bc4d454de4..f02cbf16df 100644 --- a/src/overlays/l06/mobys/switchable_beam_barrier.c +++ b/src/overlays/l06/mobys/switchable_beam_barrier.c @@ -64,6 +64,9 @@ void switchable_beam_barrier_update(char *moby) { UPDATE_VECTOR_STREAMS = 2, EMIT_PARTICLE_BURST = 3 }; + enum { + PARTICLE_BURST_COMPLETE = 4 + }; Data_305E38 *vector_stream_vars = ((Data_305E38 *)MOBY(moby)->pvars); union { float tmp[30][4]; @@ -86,10 +89,10 @@ void switchable_beam_barrier_update(char *moby) { vector_stream_vars->timer[0] = 0; vector_stream_vars->f18 = -1; if (vector_stream_vars->f10 != -1) { - MOBY(moby)->state = 1; + MOBY(moby)->state = WAIT_FOR_LINKED_MOBY; MOBY(moby)->collision = 0; } else { - MOBY(moby)->state = 2; + MOBY(moby)->state = UPDATE_VECTOR_STREAMS; } break; case WAIT_FOR_LINKED_MOBY: { @@ -97,7 +100,7 @@ void switchable_beam_barrier_update(char *moby) { if (*(short *)(e + 0xA6) == 0x463 && (unsigned char)e[0x20] < 3) { return; } - MOBY(moby)->state = 2; + MOBY(moby)->state = UPDATE_VECTOR_STREAMS; MOBY(moby)->collision = MOBY(moby)->pclass->collision; break; } @@ -154,7 +157,7 @@ void switchable_beam_barrier_update(char *moby) { *(unsigned char *)(level_mobys_q + 0xBC + (vector_stream_vars->f14 << 8)) != 0) { int voice_slot_index; MOBY(moby)->collision = 0; - MOBY(moby)->state = 3; + MOBY(moby)->state = EMIT_PARTICLE_BURST; voice_slot_index = vector_stream_vars->f18; if (voice_slot_index != -1) { char *e = ((char *)&voice_pool) + voice_slot_index * 0x70; @@ -209,7 +212,7 @@ void switchable_beam_barrier_update(char *moby) { 0); } } - MOBY(moby)->state = 4; + MOBY(moby)->state = PARTICLE_BURST_COMPLETE; break; } } From a8d155588da29d22129a341c403aaa85ad20e154 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:19:55 +0000 Subject: [PATCH 1486/1502] decomp: clarify names in split_door_update domain_0_value_1 -> WAIT_FOR_HERO_IN_CLIP_VOLUME: Retail 0x002fc0b0-0x002fc0c0 writes 1 to parent s4+0x20 after initialization when the configured clip-volume index is nonnegative. This is the identical byte loaded for dispatch at 0x002fc000; case 1 at 0x002fc12c-0x002fc140 tests hero.motion.pos against that clip volume and returns until inside. Reuse the existing same-selector WAIT_FOR_HERO_IN_CLIP_VOLUME member. domain_2_value_5 -> WAIT_FOR_RESET: Retail 0x002fc0d8-0x002fc120 places parent and child at opposing fixed offsets, then 0x002fc124-0x002fc128 routes value 5 to the shared state store at 0x002fc568, writing s4+0x20, the dispatch byte at 0x002fc000. Its case 5 at 0x002fc56c-0x002fc590 waits for reset enable before restoring transforms; reuse existing WAIT_FOR_RESET. domain_3_value_4 -> ANIMATE_PAIR_WITH_TIMED_PHASES: Retail 0x002fc150-0x002fc164 stores 4 to parent s4+0x20 and initializes the scaled phase countdown after the case-1 hero clip-volume test. The dispatch reads this same state byte at 0x002fc000; case 4 at 0x002fc2d8-0x002fc524 interpolates paired distances/rotations and changes command phase on timer expiry. Reuse existing ANIMATE_PAIR_WITH_TIMED_PHASES. domain_4_value_3 -> MOVE_PAIR_TO_FIXED_OFFSETS: Retail 0x002fc184-0x002fc188 directly stores 3 to s4+0x20 when the activated door has no group. That same byte selects case 3 through 0x002fc000-0x002fc024; 0x002fc1a4-0x002fc294 advances parent/child distances toward fixed targets and writes opposing offsets around the saved origin. Reuse existing MOVE_PAIR_TO_FIXED_OFFSETS. domain_5_value_5 -> WAIT_FOR_RESET: Retail case 3 checks both interpolated distances against fixed targets with strict <0.01 tests at 0x002fc2a0-0x002fc2cc, then branches through 0x002fc558-0x002fc568 to store 5 in s4+0x20. This is the dispatch byte read at 0x002fc000; case 5 waits for reset enable at 0x002fc56c-0x002fc580. Reuse existing WAIT_FOR_RESET. domain_6_value_5 -> WAIT_FOR_RESET: Retail case 4 checks parent/child phase distances against configured targets at 0x002fc528-0x002fc554; successful strict <0.01 tests load 5 at 0x002fc560 and store it at 0x002fc568 to s4+0x20. That is the dispatch selector at 0x002fc000, whose case 5 waits for reset enable before restoring transforms. Reuse existing WAIT_FOR_RESET. domain_7_value_1 -> WAIT_FOR_HERO_IN_CLIP_VOLUME: Retail reset branch 0x002fc588-0x002fc590 clears the separate command byte s4+0xbc and stores 1 in state byte s4+0x20, then restores paired transforms at 0x002fc594-0x002fc5cc. The state byte dispatch at 0x002fc000 selects case 1, whose 0x002fc12c-0x002fc140 clip-volume test waits for hero entry. Reuse existing WAIT_FOR_HERO_IN_CLIP_VOLUME. --- src/overlays/l06/mobys/split_door.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlays/l06/mobys/split_door.c b/src/overlays/l06/mobys/split_door.c index 234b8dfad9..86416cf8a4 100644 --- a/src/overlays/l06/mobys/split_door.c +++ b/src/overlays/l06/mobys/split_door.c @@ -119,7 +119,7 @@ void split_door_update(char *moby) { qcopy(child, moby + 0x10); qcopy(child + 0x30, moby + 0x40); if (*(int *)pair_transform_vars >= 0) { - MOBY(moby)->state = 1; + MOBY(moby)->state = WAIT_FOR_HERO_IN_CLIP_VOLUME; return; } if (pair_transform_vars->unk4 == 2) { @@ -134,18 +134,18 @@ void split_door_update(char *moby) { fast_vec_add( pair_transform_vars->unk40 + 0x10, &pair_transform_vars->unk10, position_offset); update_entity(pair_transform_vars->unk40); - MOBY(moby)->state = 5; + MOBY(moby)->state = WAIT_FOR_RESET; return; case WAIT_FOR_HERO_IN_CLIP_VOLUME: if (!is_point_inside_clip_volume(&hero.motion.pos, *(int *)pair_transform_vars)) return; if (pair_transform_vars->unk4 == 1) { - MOBY(moby)->state = 4; + MOBY(moby)->state = ANIMATE_PAIR_WITH_TIMED_PHASES; pair_transform_vars->timer_4C = scale_game_frames(0x14); } else if ((unsigned char)MOBY(moby)->group != 0xff) { set_moby_list_state((unsigned char)MOBY(moby)->group, 3); } else { - MOBY(moby)->state = 3; + MOBY(moby)->state = MOVE_PAIR_TO_FIXED_OFFSETS; } allocate_voice_for_target_entry(0, 0, (int)pair_transform_vars->unk40); return; @@ -174,7 +174,7 @@ void split_door_update(char *moby) { update_entity(pair_transform_vars->unk40); if (absolute_float(parent_distance - moby_pair_parent_fixed_distance_gp) < 0.01f && absolute_float(child_distance - moby_pair_child_fixed_distance_gp) < 0.01f) - MOBY(moby)->state = 5; + MOBY(moby)->state = WAIT_FOR_RESET; return; case ANIMATE_PAIR_WITH_TIMED_PHASES: target_delta = fast_vec_dist(moby + 0x10, &pair_transform_vars->unk10); @@ -272,14 +272,14 @@ void split_door_update(char *moby) { target_delta = moby_pair_parent_phase_target_distance_gp; if (absolute_float(phase_a - target_delta) < 0.01f) { if (absolute_float(phase_b - moby_pair_child_phase_target_distance_gp) < 0.01f) - MOBY(moby)->state = 5; + MOBY(moby)->state = WAIT_FOR_RESET; } return; case WAIT_FOR_RESET: if (moby_pair_reset_enabled_gp == 0.0f) return; MOBY(moby)->command = 0; - MOBY(moby)->state = 1; + MOBY(moby)->state = WAIT_FOR_HERO_IN_CLIP_VOLUME; qcopy(moby + 0x10, &pair_transform_vars->unk10); qcopy(moby + 0x40, pair_transform_vars->unk20); child = pair_transform_vars->unk40 + 0x10; From 5348605076b6e921b615546ce1aead6aa976a7b2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:19:55 +0000 Subject: [PATCH 1487/1502] decomp: clarify names in ammocrate_update domain_0_value_4 -> SHIP_PICKUP_ACTIVE: At 0x002e1d38-0x002e1d54 the immediate-activation flag selects full class scale and stores 4 to pickup s2+0x20, the same byte dispatched at 0x002e1cfc. Existing case SHIP_PICKUP_ACTIVE handles that value. domain_1_value_1 -> SHIP_PICKUP_SELECT_ACTIVATION_GATE: At 0x002e1d58-0x002e1d88 initialization hides the pickup, disables collision, sets one-tenth class scale and stores 1 to s2+0x20. That same switch selector enters existing SHIP_PICKUP_SELECT_ACTIVATION_GATE. domain_2_value_2 -> SHIP_PICKUP_WAIT_FOR_TARGET_STATE: At 0x002e1d8c-0x002e1da0 private target index != -1 stores 2 to pickup s2+0x20. Existing case 2 computes moby_base + index*0x100 and waits on target state, proving SHIP_PICKUP_WAIT_FOR_TARGET_STATE. domain_3_value_3 -> SHIP_PICKUP_WAIT_FOR_ACTIVATION_TIMER: At 0x002e1d94 the absent target index branches to 0x002e1dec-0x002e1df4, storing 3 into the pickup switch byte s2+0x20. Existing case SHIP_PICKUP_WAIT_FOR_ACTIVATION_TIMER checks timer configuration and decrements private timer +0x10. domain_4_value_3 -> SHIP_PICKUP_WAIT_FOR_ACTIVATION_TIMER: At 0x002e1da4-0x002e1df4 satisfying or bypassing the target-state gate stores 3 to pickup s2+0x20. This is the switch byte whose existing SHIP_PICKUP_WAIT_FOR_ACTIVATION_TIMER branch checks private +8 and timer +0x10. domain_5_value_4 -> SHIP_PICKUP_ACTIVE: At 0x002e1df8-0x002e1e18 an absent or expired activation timer stores 4 to pickup s2+0x20; subsequent code enables visibility/collision. The same selector's existing SHIP_PICKUP_ACTIVE case rotates and collects the pickup. domain_6_value_4 -> SHIP_PICKUP_ACTIVE: At 0x002e1e1c-0x002e1e48 the pickup s2+0x20 is compared against 4 before enabling collision and visibility. It reads the identical state byte used by the switch and by the preceding activation store, proving existing SHIP_PICKUP_ACTIVE. domain_7_value_5 -> SHIP_PICKUP_COLLECTED_SHRINKING: Retail 0x002e2028-0x002e2104 clears pickup collision, awards capped ship ammo/HP by pickup class and stores 5 to s2+0x20. Existing SHIP_PICKUP_COLLECTED_SHRINKING for that selector approaches one-percent class scale and rotates faster. domain_8_value_6 -> SHIP_PICKUP_REMOVE_OR_RESET: At 0x002e21e8-0x002e2204 scale below five percent of class scale stores 6 to pickup s2+0x20. Existing SHIP_PICKUP_REMOVE_OR_RESET reads private byte +0xd and either removes the pickup or resets visibility, scale and timer. domain_9_value_1 -> SHIP_PICKUP_SELECT_ACTIVATION_GATE: At 0x002e2224-0x002e225c reset hides the pickup, disables collision, restores one-tenth scale, reloads timer +0x10 from +8 and stores 1 to pickup s2+0x20. Existing SHIP_PICKUP_SELECT_ACTIVATION_GATE then chooses target-state or timer gating. --- .../shared/pickups/fighter_jet_crate.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/overlays/shared/pickups/fighter_jet_crate.c b/src/overlays/shared/pickups/fighter_jet_crate.c index cc2b3bbe47..47aefb3dfc 100644 --- a/src/overlays/shared/pickups/fighter_jet_crate.c +++ b/src/overlays/shared/pickups/fighter_jet_crate.c @@ -74,22 +74,22 @@ void ammocrate_update(char *moby) { case SHIP_PICKUP_INITIALIZE: if (*((unsigned char *)pickup_private_state + 0xc) != 0) { MOBY(moby)->scale = *(float *)(((char *)MOBY(moby)->pclass) + 0x24); - MOBY(moby)->state = 4; + MOBY(moby)->state = SHIP_PICKUP_ACTIVE; break; } MOBY(moby)->collision = 0; MOBY(moby)->visible = 0; MOBY(moby)->flags |= 1; start_size = *(float *)(((char *)MOBY(moby)->pclass) + 0x24); - MOBY(moby)->state = 1; + MOBY(moby)->state = SHIP_PICKUP_SELECT_ACTIVATION_GATE; MOBY(moby)->scale = start_size * 0.1f; break; case SHIP_PICKUP_SELECT_ACTIVATION_GATE: if (pickup_private_state[0] != -1) { - MOBY(moby)->state = 2; + MOBY(moby)->state = SHIP_PICKUP_WAIT_FOR_TARGET_STATE; break; } - MOBY(moby)->state = 3; + MOBY(moby)->state = SHIP_PICKUP_WAIT_FOR_ACTIVATION_TIMER; break; case SHIP_PICKUP_WAIT_FOR_TARGET_STATE: { int target_index = pickup_private_state[0]; @@ -100,14 +100,14 @@ void ammocrate_update(char *moby) { pickup_private_state[1] != -1 && target->state != pickup_private_state[1]) { goto frame_tail; } - MOBY(moby)->state = 3; + MOBY(moby)->state = SHIP_PICKUP_WAIT_FOR_ACTIVATION_TIMER; break; } case SHIP_PICKUP_WAIT_FOR_ACTIVATION_TIMER: if (pickup_private_state[2] == -1 || fast_dec_timer(pickup_private_state + 4)) { - MOBY(moby)->state = 4; + MOBY(moby)->state = SHIP_PICKUP_ACTIVE; } - if ((unsigned char)MOBY(moby)->state != 4) + if ((unsigned char)MOBY(moby)->state != SHIP_PICKUP_ACTIVE) goto frame_tail; MOBY(moby)->collision = *(int *)(((char *)MOBY(moby)->pclass) + 0x10); MOBY(moby)->visible = 1; @@ -170,7 +170,7 @@ void ammocrate_update(char *moby) { if (hero.ship_hp_max < hero.ship_hp) hero.ship_hp = hero.ship_hp_max; collected: - MOBY(moby)->state = 5; + MOBY(moby)->state = SHIP_PICKUP_COLLECTED_SHRINKING; break; } else if (distance < 40.0f && (MOBY(moby)->visible) != 0) { float step = 0.8f / square_root(distance); @@ -185,7 +185,7 @@ void ammocrate_update(char *moby) { MOBY(moby)->scale += (*(float *)(((char *)MOBY(moby)->pclass) + 0x24) * 0.01f - MOBY(moby)->scale) * 0.3f; if (MOBY(moby)->scale < *(float *)(((char *)MOBY(moby)->pclass) + 0x24) * 0.05f) - MOBY(moby)->state = 6; + MOBY(moby)->state = SHIP_PICKUP_REMOVE_OR_RESET; break; } case SHIP_PICKUP_REMOVE_OR_RESET: @@ -198,7 +198,7 @@ void ammocrate_update(char *moby) { MOBY(moby)->flags |= 1; MOBY(moby)->scale = *(float *)(((char *)MOBY(moby)->pclass) + 0x24) * 0.1f; pickup_private_state[4] = pickup_private_state[2]; - MOBY(moby)->state = 1; + MOBY(moby)->state = SHIP_PICKUP_SELECT_ACTIVATION_GATE; break; } frame_tail: From cba33f4a451756c1e8bd3dd66f238fcc3d7261e1 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:19:55 +0000 Subject: [PATCH 1488/1502] decomp: clarify names in floating_ship_piece_update domain_0_value_1 -> PLATFORM_STATE_WAIT_FOR_LINK_REMOVAL: Retail 0x003091c4 preserves input moby in s4; 0x00309234 reads its +0x20 state and 0x0030923c dispatches value 1 to linked-moby waiting at 0x0030930c. Initialization with a valid +0x8C link lowers the platform five units and stores 1 to the identical s4+0x20 field at 0x003092e0-0x003092ec. This is the exact selector domain already named PLATFORM_STATE_WAIT_FOR_LINK_REMOVAL in the local enum. domain_1_value_2 -> PLATFORM_STATE_ACTIVE: Retail initialization checks vars+0x8C against -1 at 0x00309290-0x00309294; its missing-link diagnostic path at 0x003092f0-0x00309308 loads 2 and reaches the state-byte store at 0x00309344 to s4+0x20. That same byte is read at 0x00309234 and value 2 dispatches at 0x00309260 to active sinking, tilt, restoration and wobble at 0x00309348 onward. Reuse the local enum's PLATFORM_STATE_ACTIVE for this same state domain. domain_4_value_2 -> PLATFORM_STATE_ACTIVE: Retail wait handler at 0x0030930c-0x00309334 tests the indexed linked moby and reaches 0x0030933c-0x00309344 when it is absent or has state 0xFE/0xFD; it loads 2 and stores it to this platform's s4+0x20 state byte. The dispatcher reads that exact field at 0x00309234 and branches for 2 at 0x00309260 to 0x00309348, the existing PLATFORM_STATE_ACTIVE branch. This assignment reuses the established local platform state member. --- src/overlays/l09/mobys/floating_ship_piece.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l09/mobys/floating_ship_piece.c b/src/overlays/l09/mobys/floating_ship_piece.c index 300797094e..34a8589627 100644 --- a/src/overlays/l09/mobys/floating_ship_piece.c +++ b/src/overlays/l09/mobys/floating_ship_piece.c @@ -85,11 +85,11 @@ void floating_ship_piece_update(char *moby) { MOBY(moby)->pos.z = start_z - 5.0f; MOBY(moby)->rot.x = random_float_between(-1.57079637f, 1.57079637f); MOBY(moby)->rot.y = random_float_between(-1.57079637f, 1.57079637f); - MOBY(moby)->state = 1; + MOBY(moby)->state = PLATFORM_STATE_WAIT_FOR_LINK_REMOVAL; } else { func_001E9730_30A560( D_L09_00209518_30A560, *(short *)(moby + 0xB2), MOBY(moby)->oclass); - MOBY(moby)->state = 2; + MOBY(moby)->state = PLATFORM_STATE_ACTIVE; } break; case PLATFORM_STATE_WAIT_FOR_LINK_REMOVAL: @@ -105,7 +105,7 @@ void floating_ship_piece_update(char *moby) { break; } set2: - MOBY(moby)->state = 2; + MOBY(moby)->state = PLATFORM_STATE_ACTIVE; break; case PLATFORM_STATE_ACTIVE: if (hero.air_frames.s == 0 && ((char *)hero.ground_moby) == moby) { From 3fbb0d7cd4ef019cc1f9173d362f3d4027a1035b Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:19:55 +0000 Subject: [PATCH 1489/1502] decomp: clarify names in update_sentrybot_hit_response_and_target_visibility domain_0_value_0 -> SENTRYBOT_INITIALIZE: Retail 0029a584 retains the sentrybot moby in s2; 0029a598..0029a59c loads its state byte at +0x20 and returns when zero. The checked sentrybot_update caller passes this same moby, and the authoritative source switches on that same MOBY(moby)->state with SENTRYBOT_INITIALIZE=0, initializing health, home position and patrol/link state. Thus this is the sentrybot initialization state, not hero idle or a hit-response selector. domain_1_value_23 -> SENTRYBOT_DEATH_KNOCKBACK: Retail 0029a608..0029a610 loads the sentrybot moby's +0x20 state byte and skips new hit reactions when it equals 23. The same function enters that state after death knockback at 0029a854..0029a85c. Authoritative sentrybot_update switches on the same moby's state and names 23 SENTRYBOT_DEATH_KNOCKBACK; its branch steps knockback motion then bursts, releases linked objects and removes the moby. Reuse that established state member for this comparison. domain_2_value_21 -> SENTRYBOT_RECOVERABLE_KNOCKBACK: Retail 0029a6cc..0029a77c initializes recoverable knockback velocities, computes direction away from the hit source, and starts knockback animation 7. At 0029a780..0029a788 it stores 21 to +0x20 of the same sentrybot moby passed by sentrybot_update. The authoritative caller's switch on MOBY(moby)->state names 21 SENTRYBOT_RECOVERABLE_KNOCKBACK and permits recovery to active states after motion/ground checks. This assignment belongs to that sentrybot state domain. domain_3_value_23 -> SENTRYBOT_DEATH_KNOCKBACK: Retail 0029a794..0029a850 initializes death knockback velocities, clears the instance flag and starts knockback animation 8; 0029a854..0029a85c stores 23 into sentrybot moby+0x20. This is the same state field switched on by authoritative sentrybot_update, whose existing SENTRYBOT_DEATH_KNOCKBACK=23 branch steps motion, bursts and removes the moby. Reuse the same member as the earlier reaction-suppression comparison. domain_4_value_16 -> SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM: Retail 0029aa40..0029aa58 compares the sentrybot's +0x20 state byte with 16 and accepts stored line-of-sight without the normal heading/height restriction. The checked caller passes this same sentrybot; its authoritative state switch names 16 SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM. That branch waits for animation completion, then enters 17 and animation 4; state 17 emits using the negated selected-joint direction. Reuse the established member of this same sentrybot state selector. domain_5_value_17 -> SENTRYBOT_EMIT_WITH_NEGATIVE_JOINT_AIM: Retail 0029aa40..0029aa58 loads moby+0x20 and compares with 17 as the second state bypassing normal heading/height visibility restrictions. Authoritative sentrybot_update receives this same moby and names state 17 SENTRYBOT_EMIT_WITH_NEGATIVE_JOINT_AIM. Its branch computes a projectile vector from selected joint 3 using negative sentrybot_emission_vector_speed_gp*frame_time and emits during the animation window. This proves reuse of that sentrybot state member, independently of equal-valued hero states. --- src/overlays/shared/enemies/sentrybot.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/overlays/shared/enemies/sentrybot.c b/src/overlays/shared/enemies/sentrybot.c index 17257e7038..8b3d1035ae 100644 --- a/src/overlays/shared/enemies/sentrybot.c +++ b/src/overlays/shared/enemies/sentrybot.c @@ -1572,6 +1572,13 @@ void update_sentrybot_hit_response_and_target_visibility(void *sentrybot_moby, i enum { HIT_STATUS_SKIP_REACTION = 1 }; + enum { + SENTRYBOT_INITIALIZE = 0, + SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM = 0x10, + SENTRYBOT_EMIT_WITH_NEGATIVE_JOINT_AIM = 0x11, + SENTRYBOT_RECOVERABLE_KNOCKBACK = 0x15, + SENTRYBOT_DEATH_KNOCKBACK = 0x17 + }; unsigned char *moby = sentrybot_moby; SentrybotVars *sentrybot_data = (SentrybotVars *)MOBY(moby)->pvars; char *hit; @@ -1587,14 +1594,14 @@ void update_sentrybot_hit_response_and_target_visibility(void *sentrybot_moby, i int group; unsigned char seen; - if (MOBY(moby)->state == 0) + if (MOBY(moby)->state == SENTRYBOT_INITIALIZE) return; MOBY(moby)->scale = *(float *)(((char *)MOBY(moby)->pclass) + 0x24) * sentrybot_class_scale_multiplier_gp; impact = 0.0f; hit = FUN_L00_0025a420(moby, 0x330000, 0); code = resolve_moby_hit_response(moby, hit, &sentrybot_data->health, 0, &kind, &impact, 0, 4); - if (kind != HIT_STATUS_SKIP_REACTION && MOBY(moby)->state != 0x17) { + if (kind != HIT_STATUS_SKIP_REACTION && MOBY(moby)->state != SENTRYBOT_DEATH_KNOCKBACK) { if ((unsigned char)D_001413F4[0] == 0) alert_visible_group_sentrybots(moby); sentrybot_data->health -= impact; @@ -1655,7 +1662,7 @@ void update_sentrybot_hit_response_and_target_visibility(void *sentrybot_moby, i &sentrybot_data->knockback.horizontal_speed, &sentrybot_data->knockback.vertical_speed); trooper_start_knockback(moby, &sentrybot_data->knockback, 7, 1, 0, angle); - MOBY(moby)->state = 0x15; + MOBY(moby)->state = SENTRYBOT_RECOVERABLE_KNOCKBACK; MOBY(moby)->command = 2; sentrybot_data->unk67 = 0x78; break; @@ -1694,7 +1701,7 @@ void update_sentrybot_hit_response_and_target_visibility(void *sentrybot_moby, i &sentrybot_data->knockback.horizontal_speed, &sentrybot_data->knockback.vertical_speed); trooper_start_knockback(moby, &sentrybot_data->knockback, 8, 1, 0, fall_angle); - MOBY(moby)->state = 0x17; + MOBY(moby)->state = SENTRYBOT_DEATH_KNOCKBACK; MOBY(moby)->command = 2; sentrybot_data->unk67 = 0xF0; break; @@ -1734,7 +1741,7 @@ void update_sentrybot_hit_response_and_target_visibility(void *sentrybot_moby, i if ((fast_difference_between_rotations(MOBY(moby)->rot.z, target_angle) < 1.5707964f && (sentrybot_target_visibility_height_check_gate[0] == 0 || absolute_float(MOBY(moby)->pos.z - sentrybot_data->unkD0[2]) < 4.0f)) || - MOBY(moby)->state == 0x10 || MOBY(moby)->state == 0x11) { + MOBY(moby)->state == SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM || MOBY(moby)->state == SENTRYBOT_EMIT_WITH_NEGATIVE_JOINT_AIM) { seen = sentrybot_data->has_line_of_sight; } if (sentrybot_data->unk114 == 1) From aa4e4761d3cec4ce3ad9b34d5c60e7187a9dd203 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:21:44 +0000 Subject: [PATCH 1490/1502] decomp: clarify names in handle_extermitank_hits_and_sync_children domain_0_value_3 -> EXTERMITANK_REMOVE: Retail 0030518c preserves the recipient moby in s8; 003052a4 loads 3 and 003052a8..003052ac loads its state byte at +0x20 and branches to 00305694 when equal, skipping damage/destruction processing. In the authoritative source, extermitank_update passes this same moby to this handler before switching on MOBY(moby)->state; its established EXTERMITANK_REMOVE=3 branch marks children at pvars+0x184/+0x188 and the parent for removal. Thus this is the Extermitank removal state, not HeroStateId. domain_1_value_3 -> EXTERMITANK_REMOVE: Retail 003052b4..003052dc subtracts damage and enters the destruction branch at 003052fc when positive-health/positive-damage continuation fails; after removal bookkeeping and three explosions, 0030550c loads 3 and 00305514 stores it to +0x20(s8), the same recipient moby's state byte tested at 003052a8. Authoritative caller extermitank_update calls this handler before its switch on this same MOBY(moby)->state; established EXTERMITANK_REMOVE=3 removes both child mobies and parent. The assignment therefore enters that existing removal state. --- src/overlays/l05/mobys/extermitank.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/overlays/l05/mobys/extermitank.c b/src/overlays/l05/mobys/extermitank.c index 94995f5120..0e845cc25f 100644 --- a/src/overlays/l05/mobys/extermitank.c +++ b/src/overlays/l05/mobys/extermitank.c @@ -540,6 +540,9 @@ void handle_extermitank_hits_and_sync_children(char *moby) { enum { MOBY_HIT_RESPONSE_SKIP_DAMAGE = 1 }; + enum { + EXTERMITANK_REMOVE = 3 + }; ExtermitankVars *extermitank_hit_sync_vars = (ExtermitankVars *)MOBY(moby)->pvars; char *first; char *second; @@ -574,7 +577,7 @@ void handle_extermitank_hits_and_sync_children(char *moby) { resolve_moby_hit_response( moby, hit, &extermitank_hit_sync_vars->health, 0, &hit_processing_status, &remaining, 0, 4); if (hit_processing_status == MOBY_HIT_RESPONSE_SKIP_DAMAGE || - (unsigned char)MOBY(moby)->state == 3) + (unsigned char)MOBY(moby)->state == EXTERMITANK_REMOVE) goto mark_children; { extermitank_hit_sync_vars->health -= remaining; @@ -650,7 +653,7 @@ void handle_extermitank_hits_and_sync_children(char *moby) { -1, 0); extermitank_hit_sync_vars->unk19E = scale_game_frames(D_L05_00161B74); - MOBY(moby)->state = 3; + MOBY(moby)->state = EXTERMITANK_REMOVE; clear_u64_value(effect_data); *(float *)(effect_data + 8) = extermitank_hit_sync_vars->unk194; spawn_particle_305178(moby, From 2e051fd57b40fc3c1ee6079f605caf5d922e2323 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:23:21 +0000 Subject: [PATCH 1491/1502] decomp: clarify names in bombomatic_update domain_0_value_1 -> BOMBOMATIC_WAIT_TO_LAUNCH: Retail 0x0030d750 sets s2=1; 0x0030d7f8 stores s2 to moby state +0x20 after initialization sets deadline pvars+0xB4 at 0x0030d7e0. The same byte is loaded at 0x0030d76c and value 1 dispatches at 0x0030d770 to 0x0030d804, which waits for that deadline. Authoritative C names that exact switch case BOMBOMATIC_WAIT_TO_LAUNCH=1, proving reuse within the same state domain. domain_1_value_2 -> BOMBOMATIC_LAUNCH_BURST: Retail 0x0030d804..0x0030d84c checks the wait deadline, sets a scaled 180-frame burst deadline, clears launch timer +0xB8 and counter +0xBA, initializes heading +0xBC, then stores 2 to moby+0x20. The same byte dispatches value 2 at 0x0030d790 to 0x0030d850, whose seven-frame timer gates projectile spawn 0x0030daec. Authoritative C already names this exact state switch case BOMBOMATIC_LAUNCH_BURST=2. domain_2_value_1 -> BOMBOMATIC_WAIT_TO_LAUNCH: Retail 0x0030db00..0x0030db34 checks the burst deadline, computes a scaled 120-frame delay, writes the next deadline to pvars+0xB4, and stores 1 to moby+0x20. On the next update 0x0030d76c..0x0030d770 reads that same state byte and dispatches 1 to the deadline-wait branch 0x0030d804. Authoritative C already names that switch case BOMBOMATIC_WAIT_TO_LAUNCH=1, so this is the return to the same waiting state. --- src/overlays/l07/mobys/bombomatic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlays/l07/mobys/bombomatic.c b/src/overlays/l07/mobys/bombomatic.c index fe90637e37..b8347e9382 100644 --- a/src/overlays/l07/mobys/bombomatic.c +++ b/src/overlays/l07/mobys/bombomatic.c @@ -344,7 +344,7 @@ void bombomatic_update(char *moby) { attach_manipulator(moby, 0, &moby_data->manipulator_70); *(int *)&moby_data->unkC0 = 0; allocate_voice_for_target_entry(0, 4, (int)moby); - MOBY(moby)->state = 1; + MOBY(moby)->state = BOMBOMATIC_WAIT_TO_LAUNCH; moby_data->unkC4 = 0; break; } @@ -355,7 +355,7 @@ void bombomatic_update(char *moby) { moby_data->timer_B8 = 0; moby_data->unkBC = random_angle_radians(); moby_data->unkBA = 0; - MOBY(moby)->state = 2; + MOBY(moby)->state = BOMBOMATIC_LAUNCH_BURST; } break; } @@ -414,7 +414,7 @@ void bombomatic_update(char *moby) { if (moby_data->unkB4 <= D_L07_0015F5CC) { int r9 = scale_game_frames(0x78); moby_data->unkB4 = D_L07_0015F5CC + r9; - MOBY(moby)->state = 1; + MOBY(moby)->state = BOMBOMATIC_WAIT_TO_LAUNCH; } break; } From 765d68ab346b8c2001ad8227709149186ced5634 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:25:01 +0000 Subject: [PATCH 1492/1502] decomp: clarify names in rocket_strike_fighter_update domain_0_value_255 -> ROCKET_STRIKE_FIGHTER_MISSION_COMPLETE: Authoritative src/overlays/l14/mobys/rocket_strike_fighter.c SHA-256 47a68f45eb64ef8e47877658fbe02bff8558df70b9c677d811a87d6262082579 explicitly describes activation once three missions are done and declares mission[3] as the missions that must be complete. Retail 0x002fced8-0x002fcef0 loads visited52[mission[0]+current_level_index*16] as an unsigned byte; 0x002fcee4/0x002fcef4 requires 255. Loads from pvars+0x9c and +0xa0 must equal that byte at 0x002fcf0c and 0x002fcf24. Original retail decompilation agrees on all three -1 byte tests. Success continues through hero/clip/camera checks and restores fighter/rocket flags, sets FOLLOW_PATH and activates the flythrough at 0x002fd0c8-0x002fd0f4. Thus 0xFF is the required completed-mission status in this gate, not a Moby state ID. --- src/overlays/l14/mobys/rocket_strike_fighter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/l14/mobys/rocket_strike_fighter.c b/src/overlays/l14/mobys/rocket_strike_fighter.c index 1c1f42aba9..a88caf8f71 100644 --- a/src/overlays/l14/mobys/rocket_strike_fighter.c +++ b/src/overlays/l14/mobys/rocket_strike_fighter.c @@ -90,6 +90,9 @@ void rocket_strike_fighter_update(struct Moby *moby) { ROCKET_STRIKE_FIGHTER_STATE_FOLLOW_PATH = 2, ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN = 3 }; + enum { + ROCKET_STRIKE_FIGHTER_MISSION_COMPLETE = 0xFF + }; RocketStrikeFighterVars *moby_vars = (RocketStrikeFighterVars *)moby->pvars; Vec4 target_view_point_or_rocket_offset; Vec4 rocket_position; @@ -165,7 +168,7 @@ void rocket_strike_fighter_update(struct Moby *moby) { case ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS: { int lvl = current_level_index * 16; u8 first_mission_state = visited52[moby_vars->mission[0] + lvl]; - if (first_mission_state == 0xFF) { + if (first_mission_state == ROCKET_STRIKE_FIGHTER_MISSION_COMPLETE) { u8 second_mission_state = visited52[moby_vars->mission[1] + lvl]; if (second_mission_state == first_mission_state) { u8 x = visited52[moby_vars->mission[2] + lvl]; From 5733ac5748241225cb9a4473648fc34c43e340a0 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:25:01 +0000 Subject: [PATCH 1493/1502] decomp: clarify names in machinegun_turret_update domain_0_value_2 -> TURRET_HIT_SPIN: Retail 0x0031a2b4-0x0031a2bc loads byte 0x20(s2) and compares it below 2 before admitting hit contact. The identical byte selects the turret switch at 0x0031a360-0x0031a380; its existing local TURRET_HIT_SPIN=2 is therefore the canonical boundary, not an animation or control value. domain_1_value_2 -> TURRET_HIT_SPIN: Retail 0x0031a2e0 sets s0=2 and 0x0031a348 stores s0 to byte 0x20(s2) after hit contact and a scaled 60-frame timer. That exact byte is dispatched at 0x0031a360; case TURRET_HIT_SPIN rotates heading at 0x0031a7dc-0x0031a7f4. Reuse the established state member. domain_2_value_1 -> TURRET_SWEEP_AND_FIRE: Initialization sets s0=1 at 0x0031a4a4 and branches to 0x0031a9c0, which stores it to byte 0x20(s2), the switch selector. Initialization has set sweep bounds, saved height and firing bookkeeping; the existing TURRET_SWEEP_AND_FIRE=1 branch at 0x0031a4f8-0x0031a794 sweeps and emits projectiles. domain_3_value_3 -> TURRET_LOWER_AND_REALIGN: After hit-spin timer expiry, retail 0x0031a808-0x0031a810 sets a scaled 180-frame timer, then 0x0031a814-0x0031a81c stores 3 to byte 0x20(s2). This switch field selects existing TURRET_LOWER_AND_REALIGN=3, whose 0x0031a85c-0x0031a908 branch lowers Z and realigns sweep heading. domain_4_value_4 -> TURRET_RESTORE_HEIGHT: The lower/realign branch expires its timer at 0x0031a90c-0x0031a914 and stores 4 to byte 0x20(s2) at 0x0031a948-0x0031a950. The same switch selector's existing TURRET_RESTORE_HEIGHT=4 branch at 0x0031a954-0x0031a99c raises Z to saved height and restores flag 0x1000. domain_5_value_1 -> TURRET_SWEEP_AND_FIRE: At restoration completion retail 0x0031a990 loads s0=1, clamps Z to saved height and restores flag 0x1000; 0x0031a9c0 stores s0 to byte 0x20(s2). This is the same turret switch selector, returning to existing TURRET_SWEEP_AND_FIRE=1 at 0x0031a4f8, which resumes sweep and timed projectile emission. --- src/overlays/l07/mobys/machinegun_turret.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/overlays/l07/mobys/machinegun_turret.c b/src/overlays/l07/mobys/machinegun_turret.c index 4122ba354d..1d61ae0dfc 100644 --- a/src/overlays/l07/mobys/machinegun_turret.c +++ b/src/overlays/l07/mobys/machinegun_turret.c @@ -90,7 +90,7 @@ void machinegun_turret_update(unsigned char *moby) { animation = &turret_instance_vars->anim_state; hit = find_moby_hit(moby, 0x230000, 0); resolve_moby_hit_response((void *)moby, (MobyHit *)hit, collision, 0, contact, 0, 0, 4); - if ((u8)MOBY(moby)->state < 2 && contact[0] > 1) { + if ((u8)MOBY(moby)->state < TURRET_HIT_SPIN && contact[0] > 1) { FUN_0022da68(1, 0, moby); FUN_L00_00257470(moby, 0, -1); MOBY(moby)->flags &= 0xefff; @@ -100,7 +100,7 @@ void machinegun_turret_update(unsigned char *moby) { turret_instance_vars->unk7C = scale_game_frames(60); if ((u8)MOBY(moby)->prev_seq != 2) FUN_00212f90(moby, 2, 0, 5); - MOBY(moby)->state = 2; + MOBY(moby)->state = TURRET_HIT_SPIN; } MOBY(moby)->hit_slot = 0xff; trooper_anim_finish(moby, animation); @@ -136,7 +136,7 @@ void machinegun_turret_update(unsigned char *moby) { turret_instance_vars->unk9C = turret_instance_vars->unk94; if ((u8)MOBY(moby)->prev_seq != 1) FUN_00212f90(moby, 1, 0, 0); - MOBY(moby)->state = 1; + MOBY(moby)->state = TURRET_SWEEP_AND_FIRE; break; case TURRET_SWEEP_AND_FIRE: if ((u8)MOBY(moby)->seq != 1 && ((u8)MOBY(moby)->anim_flags & 2) != 0 && @@ -210,7 +210,7 @@ void machinegun_turret_update(unsigned char *moby) { if (fast_dec_timer_s16(&turret_instance_vars->unk7C) == 0) return; turret_instance_vars->unk7C = scale_game_frames(180); - MOBY(moby)->state = 3; + MOBY(moby)->state = TURRET_LOWER_AND_REALIGN; break; case TURRET_LOWER_AND_REALIGN: if ((u8)MOBY(moby)->seq != 4 && ((u8)MOBY(moby)->anim_flags & 2) && @@ -232,7 +232,7 @@ void machinegun_turret_update(unsigned char *moby) { FUN_0022da68(2, 0, moby); if ((u8)MOBY(moby)->prev_seq != 3) FUN_00212f90(moby, 3, 0, 5); - MOBY(moby)->state = 4; + MOBY(moby)->state = TURRET_RESTORE_HEIGHT; } break; case TURRET_RESTORE_HEIGHT: @@ -244,7 +244,7 @@ void machinegun_turret_update(unsigned char *moby) { MOBY(moby)->flags |= 0x1000; if ((u8)MOBY(moby)->prev_seq != 1) FUN_00212f90(moby, 1, 0, 5); - MOBY(moby)->state = 1; + MOBY(moby)->state = TURRET_SWEEP_AND_FIRE; break; case 5: break; From 416d7c8e1f5b0df583fd26eb8182a3ffd0017af2 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:29:19 +0000 Subject: [PATCH 1494/1502] decomp: clarify names in armed_transport_update domain_0_value_6 -> ARMED_TRANSPORT_STATE_TRACK_TARGET: The retail object is a0 saved in s3 at 0x002e22e4; lbu at 0x002e2308 selects the switch from byte s3+0x20, which authoritative C maps to MOBY(transport_moby)->state. This assignment writes that same byte and therefore uses the existing function-local armed transport state enum, not HeroStateId or vehicle/control modes. At 0x002e23c0 a missing first path branches to 0x002e2770-0x002e2778, storing 6. Existing case 6 computes target XY bearing and eases yaw at 0x002e27c8-0x002e2818. domain_10_value_7 -> ARMED_TRANSPORT_STATE_SPAWN_DIRECTED_MOBY: The retail object is a0 saved in s3 at 0x002e22e4; lbu at 0x002e2308 selects the switch from byte s3+0x20, which authoritative C maps to MOBY(transport_moby)->state. This assignment writes that same byte and therefore uses the existing function-local armed transport state enum, not HeroStateId or vehicle/control modes. At 0x002e2854-0x002e2874 the elapsed private+0x164 timer and private+0xB4 != 2 cause a store of 7. Existing case 7 obtains point 1, forms scaled target-minus-point direction and invokes the directed moby creation helper at 0x002e28e4. domain_11_value_6 -> ARMED_TRANSPORT_STATE_TRACK_TARGET: The retail object is a0 saved in s3 at 0x002e22e4; lbu at 0x002e2308 selects the switch from byte s3+0x20, which authoritative C maps to MOBY(transport_moby)->state. This assignment writes that same byte and therefore uses the existing function-local armed transport state enum, not HeroStateId or vehicle/control modes. At 0x002e28ec-0x002e28f8 the directed-spawn branch stores 6 after the creation call, then resets private+0x164 to scaled 180 frames. Existing case 6 resumes target-bearing yaw tracking and checks that timer. domain_1_value_1 -> ARMED_TRANSPORT_STATE_WAIT_FOR_ACTIVATION: The retail object is a0 saved in s3 at 0x002e22e4; lbu at 0x002e2308 selects the switch from byte s3+0x20, which authoritative C maps to MOBY(transport_moby)->state. This assignment writes that same byte and therefore uses the existing function-local armed transport state enum, not HeroStateId or vehicle/control modes. At 0x002e2400-0x002e2404 initialization stores 1 after copying the first path point; it hides the object and disables collision. Existing case 1 at 0x002e2420-0x002e2468 waits on the global gate and optional hero-in-region test. domain_2_value_2 -> ARMED_TRANSPORT_STATE_FOLLOW_FIRST_PATH: The retail object is a0 saved in s3 at 0x002e22e4; lbu at 0x002e2308 selects the switch from byte s3+0x20, which authoritative C maps to MOBY(transport_moby)->state. This assignment writes that same byte and therefore uses the existing function-local armed transport state enum, not HeroStateId or vehicle/control modes. At 0x002e2470-0x002e2474 successful activation stores 2. Existing case 2 loads private+0xD8 at 0x002e24f8 and calls advance_armed_transport_along_path at 0x002e25c4 using that first path. domain_3_value_3 -> ARMED_TRANSPORT_STATE_RELEASE_PASSENGERS: The retail object is a0 saved in s3 at 0x002e22e4; lbu at 0x002e2308 selects the switch from byte s3+0x20, which authoritative C maps to MOBY(transport_moby)->state. This assignment writes that same byte and therefore uses the existing function-local armed transport state enum, not HeroStateId or vehicle/control modes. At 0x002e25d4-0x002e25e0 completion of the first path with an occupied passenger slot stores 3. Existing case 3 scans private+0xC0 slots and releases a passenger through 0x002d3de0 at 0x002e2acc, then clears the slot. domain_4_value_6 -> ARMED_TRANSPORT_STATE_TRACK_TARGET: The retail object is a0 saved in s3 at 0x002e22e4; lbu at 0x002e2308 selects the switch from byte s3+0x20, which authoritative C maps to MOBY(transport_moby)->state. This assignment writes that same byte and therefore uses the existing function-local armed transport state enum, not HeroStateId or vehicle/control modes. At 0x002e25e4-0x002e25ec first-path completion without passengers and without private+0xDC second path branches to 0x002e2770-0x002e2778, storing 6. Existing case 6 eases yaw toward tracked XY bearing. domain_5_value_4 -> ARMED_TRANSPORT_STATE_ALIGN_SECOND_PATH: The retail object is a0 saved in s3 at 0x002e22e4; lbu at 0x002e2308 selects the switch from byte s3+0x20, which authoritative C maps to MOBY(transport_moby)->state. This assignment writes that same byte and therefore uses the existing function-local armed transport state enum, not HeroStateId or vehicle/control modes. At 0x002e25e4-0x002e25f8 first-path completion without passengers but with private+0xDC second path stores 4. Existing case 4 reads that path's first heading at 0x002e26a8 and eases transport yaw toward it before proceeding. domain_6_value_4 -> ARMED_TRANSPORT_STATE_ALIGN_SECOND_PATH: The retail object is a0 saved in s3 at 0x002e22e4; lbu at 0x002e2308 selects the switch from byte s3+0x20, which authoritative C maps to MOBY(transport_moby)->state. This assignment writes that same byte and therefore uses the existing function-local armed transport state enum, not HeroStateId or vehicle/control modes. At 0x002e263c-0x002e2648 the exhausted passenger-slot scan stores 4 when private+0xDC is present. Existing case 4 at 0x002e2668-0x002e26c4 resolves that second path and aligns transport yaw to its first heading. domain_7_value_6 -> ARMED_TRANSPORT_STATE_TRACK_TARGET: The retail object is a0 saved in s3 at 0x002e22e4; lbu at 0x002e2308 selects the switch from byte s3+0x20, which authoritative C maps to MOBY(transport_moby)->state. This assignment writes that same byte and therefore uses the existing function-local armed transport state enum, not HeroStateId or vehicle/control modes. At 0x002e263c-0x002e2644 the exhausted passenger-slot scan stores 6 when private+0xDC is -1. Existing case 6 at 0x002e27c8-0x002e2818 computes bearing from tracked XY minus object XY and eases yaw toward it. domain_8_value_5 -> ARMED_TRANSPORT_STATE_FOLLOW_SECOND_PATH: The retail object is a0 saved in s3 at 0x002e22e4; lbu at 0x002e2308 selects the switch from byte s3+0x20, which authoritative C maps to MOBY(transport_moby)->state. This assignment writes that same byte and therefore uses the existing function-local armed transport state enum, not HeroStateId or vehicle/control modes. At 0x002e26d8-0x002e26e8 yaw difference below 0.01 stores 5 and resets progress. Existing case 5 resolves private+0xDC at 0x002e273c-0x002e2758 and calls advance_armed_transport_along_path on that second path. domain_9_value_6 -> ARMED_TRANSPORT_STATE_TRACK_TARGET: The retail object is a0 saved in s3 at 0x002e22e4; lbu at 0x002e2308 selects the switch from byte s3+0x20, which authoritative C maps to MOBY(transport_moby)->state. This assignment writes that same byte and therefore uses the existing function-local armed transport state enum, not HeroStateId or vehicle/control modes. At 0x002e275c-0x002e2778 second-path completion with private+0xD0 present falls through to store 6. Existing case 6 computes tracked-position bearing and eases yaw at 0x002e27c8-0x002e2818. --- src/overlays/shared/enemies/armed_transport.c | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/overlays/shared/enemies/armed_transport.c b/src/overlays/shared/enemies/armed_transport.c index 7eb2c4881b..720551c238 100644 --- a/src/overlays/shared/enemies/armed_transport.c +++ b/src/overlays/shared/enemies/armed_transport.c @@ -195,13 +195,13 @@ void armed_transport_update(char *transport_moby) { transport_data->unk170[0] = speed; transport_data->unk194 = MOBY(transport_moby)->pos.z; if (transport_data->path_index == -1) { - MOBY(transport_moby)->state = 6; + MOBY(transport_moby)->state = ARMED_TRANSPORT_STATE_TRACK_TARGET; break; } path = D_L16_001B0930[transport_data->path_index]; transport_data->unk170[1] = fast_vec_dist(path + 0x10, path + 0x20); qcopy(&MOBY(transport_moby)->pos, path + 0x10); - MOBY(transport_moby)->state = 1; + MOBY(transport_moby)->state = ARMED_TRANSPORT_STATE_WAIT_FOR_ACTIVATION; MOBY(transport_moby)->visible = 0; MOBY(transport_moby)->collision = 0; MOBY(transport_moby)->flags = (MOBY(transport_moby)->flags | 1) & 0xEFFF; @@ -215,7 +215,7 @@ void armed_transport_update(char *transport_moby) { point_in_path_xy(hero.motion.pos.f, D_L16_001B0930[transport_data->unkD4] + 0x10, *(int *)D_L16_001B0930[transport_data->unkD4]))) { - MOBY(transport_moby)->state = 2; + MOBY(transport_moby)->state = ARMED_TRANSPORT_STATE_FOLLOW_FIRST_PATH; MOBY(transport_moby)->flags &= 0xFFFE; MOBY(transport_moby)->visible = 1; MOBY(transport_moby)->collision = @@ -256,11 +256,11 @@ void armed_transport_update(char *transport_moby) { } if (advance_armed_transport_along_path(transport_moby, path)) { if (loaded) { - MOBY(transport_moby)->state = 3; + MOBY(transport_moby)->state = ARMED_TRANSPORT_STATE_RELEASE_PASSENGERS; } else if (transport_data->unkDC == -1) { - MOBY(transport_moby)->state = 6; + MOBY(transport_moby)->state = ARMED_TRANSPORT_STATE_TRACK_TARGET; } else { - MOBY(transport_moby)->state = 4; + MOBY(transport_moby)->state = ARMED_TRANSPORT_STATE_ALIGN_SECOND_PATH; } } break; @@ -288,9 +288,9 @@ void armed_transport_update(char *transport_moby) { } if (i == 3) { if (transport_data->unkDC != -1) { - MOBY(transport_moby)->state = 4; + MOBY(transport_moby)->state = ARMED_TRANSPORT_STATE_ALIGN_SECOND_PATH; } else { - MOBY(transport_moby)->state = 6; + MOBY(transport_moby)->state = ARMED_TRANSPORT_STATE_TRACK_TARGET; } } } @@ -306,7 +306,7 @@ void armed_transport_update(char *transport_moby) { frame_time_sq * 6.2831855f, frame_time * 6.2831855f); if (fast_difference_between_rotations(MOBY(transport_moby)->rot.z, heading) < 0.01f) { - MOBY(transport_moby)->state = 5; + MOBY(transport_moby)->state = ARMED_TRANSPORT_STATE_FOLLOW_SECOND_PATH; transport_data->path_point = 0; transport_data->unk16C = 0; } @@ -325,7 +325,7 @@ void armed_transport_update(char *transport_moby) { mark_moby_for_removal(transport_moby); return; } - MOBY(transport_moby)->state = 6; + MOBY(transport_moby)->state = ARMED_TRANSPORT_STATE_TRACK_TARGET; } break; case ARMED_TRANSPORT_STATE_TRACK_TARGET: { @@ -353,7 +353,7 @@ void armed_transport_update(char *transport_moby) { frame_time_sq * 1.5707964f, frame_time * 6.2831855f); if (fast_dec_timer((int *)(&transport_data->unk164)) && transport_data->unkB4 != 2) - MOBY(transport_moby)->state = 7; + MOBY(transport_moby)->state = ARMED_TRANSPORT_STATE_SPAWN_DIRECTED_MOBY; break; } case ARMED_TRANSPORT_STATE_SPAWN_DIRECTED_MOBY: @@ -367,7 +367,7 @@ void armed_transport_update(char *transport_moby) { vector.f, &transport_data->unk70, scale_game_frames(45)); - MOBY(transport_moby)->state = 6; + MOBY(transport_moby)->state = ARMED_TRANSPORT_STATE_TRACK_TARGET; transport_data->unk164 = scale_game_frames(180); break; case ARMED_TRANSPORT_STATE_DYING: { From 7bd91e1d6a6e5e0fb4428f5664fcd123be3785bb Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:31:00 +0000 Subject: [PATCH 1495/1502] decomp: clarify names in planetbuster_maximus_part_update domain_0_value_1 -> PLANETBUSTER_WAIT_FOR_PATH_TRIGGER: Retail 00306c08 loads 1 and 00306c14 stores it to moby+0x20 after linked-part/path initialization. The identical byte is loaded at 00306a44 for the outer state dispatch. Authoritative source already names that dispatch case PLANETBUSTER_WAIT_FOR_PATH_TRIGGER; original Ghidra case 1 gates height/visibility and waits for the clip-volume/global trigger at 00306e64..00306e80. domain_1_value_2 -> PLANETBUSTER_FOLLOW_PATH: Retail 00306e64..00306e80 tests pvars+0x5EC clip volume or D_L12_00161F00, then 00306ed0/00306ed8 stores 2 to moby+0x20. This is the same outer switch byte read at 00306a44, whose existing source case is PLANETBUSTER_FOLLOW_PATH. Original Ghidra case 2 and 00306fe8..00307044 compute waypoint modulo, normalize displacement and add it to moby position. domain_2_value_3 -> PLANETBUSTER_POST_PATH_GUN_UPDATE: Retail 00306f6c..00306fa8 approaches path speed pvars+0x5F0 to zero near path count minus 11; 00306fb4/00306fbc stores 3 to moby+0x20 when zero. The same outer switch has existing source case PLANETBUSTER_POST_PATH_GUN_UPDATE, matching original Ghidra case 3 and retail 0030718c..0030727c yaw/oscillation, linked-transform and gun updates. domain_3_value_1 -> PLANETBUSTER_WAIT_FOR_PATH_TRIGGER: The source's lower bound reads MOBY(moby)->state, the same +0x20 byte as its named outer cases. Retail 00307620..0030762c loads that byte, subtracts 1 and tests unsigned less than 3, implementing states 1 through 3 before voice allocation. Thus the lower endpoint is the existing PLANETBUSTER_WAIT_FOR_PATH_TRIGGER member, not the separate +0xBC transition interpolation command. domain_4_value_3 -> PLANETBUSTER_POST_PATH_GUN_UPDATE: The source's upper bound reads MOBY(moby)->state at +0x20. Retail 00307620..0030762c implements the inclusive 1..3 range by unsigned (state-1)<3 and branches to voice allocation at 00307640..00307654. Its upper endpoint is the same state 3 dispatched as the existing PLANETBUSTER_POST_PATH_GUN_UPDATE case; it is unrelated to HeroStateId despite equal numeric values. --- src/overlays/l12/mobys/planetbuster_maximus_part.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlays/l12/mobys/planetbuster_maximus_part.c b/src/overlays/l12/mobys/planetbuster_maximus_part.c index 3ac17acded..886f3f401f 100644 --- a/src/overlays/l12/mobys/planetbuster_maximus_part.c +++ b/src/overlays/l12/mobys/planetbuster_maximus_part.c @@ -740,7 +740,7 @@ void planetbuster_maximus_part_update(char *moby) { D_L12_001FB688[j] = 0; moby_data->unk604 = -1; moby_data->unk5FC = 100; - MOBY(moby)->state = 1; + MOBY(moby)->state = PLANETBUSTER_WAIT_FOR_PATH_TRIGGER; } break; case PLANETBUSTER_WAIT_FOR_PATH_TRIGGER: { @@ -806,7 +806,7 @@ void planetbuster_maximus_part_update(char *moby) { ((unsigned char *)D_L12_0015FFD8_gp + (*(int *)((u8 *)moby_data + k * 0x30 + 0x20) << 8))[0xA4] = 0xFF; } - MOBY(moby)->state = 2; + MOBY(moby)->state = PLANETBUSTER_FOLLOW_PATH; } break; } @@ -831,7 +831,7 @@ void planetbuster_maximus_part_update(char *moby) { } else { approach_value(&moby_data->unk5F0, 0.0f, frame_time_sq_macro * 8.0f); if (moby_data->unk5F0 == 0.0f) { - MOBY(moby)->state = 3; + MOBY(moby)->state = PLANETBUSTER_POST_PATH_GUN_UPDATE; break; } } @@ -981,7 +981,7 @@ void planetbuster_maximus_part_update(char *moby) { break; } update_planetbuster_maximus_glow_color(moby); - if ((unsigned char)MOBY(moby)->state >= 1 && (unsigned char)MOBY(moby)->state <= 3) { + if ((unsigned char)MOBY(moby)->state >= PLANETBUSTER_WAIT_FOR_PATH_TRIGGER && (unsigned char)MOBY(moby)->state <= PLANETBUSTER_POST_PATH_GUN_UPDATE) { if (moby_data->unk604 == -1) moby_data->unk604 = allocate_voice_for_target_entry(0, 4, moby); } else { From 80209c3701a2e2e0b2a34e3f148e1a630d764c83 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:31:00 +0000 Subject: [PATCH 1496/1502] decomp: clarify names in blarg_elite_commando_update domain_0_value_10 -> COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM: Retail 0x002d2f3c loads 10 and 0x002d2f4c stores it to s2+0x20, the same commando state byte dispatched at 0x002d2d68-0x002d2d88. Its existing case composes parent basis, position and heading at 0x002d2f7c-0x002d2fd8; reuse the local canonical member. domain_10_value_4 -> COMMANDO_STATE_PREPARE_ROCKET_FIRE: Retail 0x002d3570-0x002d3598 stores 4 to Moby+0x20 after attack-node distance is below 0.01 or pvars+0x2dc expires, then blends animation 2. This exact selector already names case 4 COMMANDO_STATE_PREPARE_ROCKET_FIRE; that case turns to target before entering FIRE_ROCKETS. domain_11_value_2 -> COMMANDO_STATE_IDLE: Retail 0x002d3610-0x002d362c tests recovery completion bit at Moby+0x70 and stores 2 to Moby+0x20 at the source idle label. Initialization without a parent also branches here at 0x002d2f38. Both enter existing COMMANDO_STATE_IDLE, with animation-0 blend when needed. domain_1_value_2 -> COMMANDO_STATE_IDLE: Retail 0x002d30dc tests saved-position distance below 1.0; 0x002d30e8-0x002d30f0 stores 2 to Moby+0x20. This is the selector of existing COMMANDO_STATE_IDLE, whose body decrements timers and dispatches patrol or attack at 0x002d30f4 onward. domain_2_value_2 -> COMMANDO_PURSUIT_MODE_DISABLED: Retail 0x002d3100-0x002d3104 compares pvars+0x114 with 2, distinct from Moby state +0x20. Checked helper request a4c4fe35fced428f88c84fd213c7c0ca loads the same pvars from Moby+0x78 at 0x002d38e0 and stores 2 to +0x114 at 0x002d3d00 for mode 22 or 0x002d3d84 when target distance exceeds range. This suppresses attack transitions and selects timed patrol. Supplied update_blarg_elite_commando_joint_aim already calls this exact field/value COMMANDO_PURSUIT_MODE_DISABLED; reuse that separate pursuit-domain member. domain_3_value_7 -> COMMANDO_STATE_MOVE_TO_ATTACK_NODE: Retail 0x002d3120-0x002d3138 stores 7 to Moby+0x20 after idle's attack countdown, then advances pvars+0x300 node and selects movement animation. Existing case COMMANDO_STATE_MOVE_TO_ATTACK_NODE at 0x002d3520 moves to that node and enters rocket preparation on arrival or timeout. domain_4_value_4 -> COMMANDO_STATE_PREPARE_ROCKET_FIRE: Retail 0x002d3190-0x002d319c stores 4 to Moby+0x20 after idle's random gate, then blends animation 2. It selects existing COMMANDO_STATE_PREPARE_ROCKET_FIRE, whose 0x002d3320-0x002d3394 target-facing branch enters established firing state 5. domain_5_value_3 -> COMMANDO_STATE_MOVE_TO_PATROL_NODE: Retail 0x002d31d4-0x002d31fc advances the path node and stores 3 to Moby+0x20 on the pursuit-disabled idle path; 0x002d3200 seeds patrol timer. Existing COMMANDO_STATE_MOVE_TO_PATROL_NODE moves toward that table node at 0x002d3214-0x002d3244 and returns idle on arrival or timeout. domain_6_value_2 -> COMMANDO_STATE_IDLE: Retail 0x002d325c-0x002d3284 stores 2 to Moby+0x20 when patrol-node distance is below 0.01; the source's first assignment in MOVE_TO_PATROL_NODE is this arrival path. It selects existing COMMANDO_STATE_IDLE and blends animation 0. domain_7_value_2 -> COMMANDO_STATE_IDLE: The source's second assignment in MOVE_TO_PATROL_NODE is the timer-expiry path. Retail 0x002d326c-0x002d3284 tests pvars+0x302 expiry and shares the store of 2 to Moby+0x20 and animation-0 blend with the arrival path. Both select existing COMMANDO_STATE_IDLE. domain_8_value_5 -> COMMANDO_STATE_FIRE_ROCKETS: Retail 0x002d3378-0x002d3394 tests Moby+0x70 bit 2 then stores 5 to the dispatched Moby+0x20 state. Existing COMMANDO_STATE_FIRE_ROCKETS at 0x002d33b0 onward aims at target and creates rockets at animation windows through 0x002d349c; reuse the canonical local member. domain_9_value_2 -> COMMANDO_STATE_IDLE: Retail 0x002d34c4-0x002d34ec increments pvars+0x2de and, after three firing cycles, stores 2 to Moby+0x20. It blends animation 0, seeds the 60-frame countdown and clears the cycle count at 0x002d34f0-0x002d351c, selecting existing COMMANDO_STATE_IDLE. --- .../shared/enemies/blarg_elite_commando.c | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/overlays/shared/enemies/blarg_elite_commando.c b/src/overlays/shared/enemies/blarg_elite_commando.c index b08d5ef748..14c39be21f 100644 --- a/src/overlays/shared/enemies/blarg_elite_commando.c +++ b/src/overlays/shared/enemies/blarg_elite_commando.c @@ -219,6 +219,9 @@ void blarg_elite_commando_update(char *commando_moby) { COMMANDO_STATE_FATAL_FALL = 9, COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM = 10 }; + enum { + COMMANDO_PURSUIT_MODE_DISABLED = 2 + }; float target[4], scratch_vector[4], delta[4]; L16DamageData *commando_data = (L16DamageData *)MOBY(commando_moby)->pvars; char *source, *aim_target_moby; @@ -269,7 +272,7 @@ void blarg_elite_commando_update(char *commando_moby) { qcopy(&commando_data->unk2B0, position); } if (commando_data->unk128) { - MOBY(commando_moby)->state = 10; + MOBY(commando_moby)->state = COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM; MOBY(commando_moby)->visible = 0; MOBY(commando_moby)->flags = (MOBY(commando_moby)->flags | 1) & 0xEFFF; MOBY(commando_moby)->collision = 0; @@ -310,21 +313,21 @@ void blarg_elite_commando_update(char *commando_moby) { if (((unsigned char *)commando_moby)[0x53] != 0) blend_moby_animation(commando_moby, 0, 0, scale_game_frames(10)); if (distance < 1.0f) - MOBY(commando_moby)->state = 2; + MOBY(commando_moby)->state = COMMANDO_STATE_IDLE; } break; case COMMANDO_STATE_IDLE: fast_dec_timer_s16(&commando_data->unk2DC); - if (commando_data->pursuit_mode != 2) { + if (commando_data->pursuit_mode != COMMANDO_PURSUIT_MODE_DISABLED) { if (commando_data->unk2DC == 0) { if (commando_data->unk120 >= 0) { - MOBY(commando_moby)->state = 7; + MOBY(commando_moby)->state = COMMANDO_STATE_MOVE_TO_ATTACK_NODE; commando_data->unk2DC = truncate_float_to_s32(scale_time(random_float_between(30.0f, 90.0f))); commando_data->unk300 = (commando_data->unk300 + 1) % 2; select_blarg_elite_commando_movement_animation(commando_moby); } else if (!random_integer_below(20)) { - MOBY(commando_moby)->state = 4; + MOBY(commando_moby)->state = COMMANDO_STATE_PREPARE_ROCKET_FIRE; if (((unsigned char *)commando_moby)[0x53] != 2) { blend_moby_animation(commando_moby, 2, 0, scale_game_frames(10)); } @@ -333,7 +336,7 @@ void blarg_elite_commando_update(char *commando_moby) { } else if (fast_dec_timer_s16(&commando_data->unk302)) { if (commando_data->unk120 >= 0) { commando_data->unk300 = (commando_data->unk300 + 1) % 2; - MOBY(commando_moby)->state = 3; + MOBY(commando_moby)->state = COMMANDO_STATE_MOVE_TO_PATROL_NODE; commando_data->unk302 = scale_game_frames(180); select_blarg_elite_commando_movement_animation(commando_moby); } @@ -345,13 +348,13 @@ void blarg_elite_commando_update(char *commando_moby) { (commando_data->unk300 * 16 + 0x10), 1); if (path_distance < 0.01f) { - MOBY(commando_moby)->state = 2; + MOBY(commando_moby)->state = COMMANDO_STATE_IDLE; if (((unsigned char *)commando_moby)[0x53] != 0) blend_moby_animation(commando_moby, 0, 0, scale_game_frames(10)); commando_data->unk302 = truncate_float_to_s32(scale_time(random_float_between(180.0f, 360.0f))); } else if (fast_dec_timer_s16(&commando_data->unk302)) { - MOBY(commando_moby)->state = 2; + MOBY(commando_moby)->state = COMMANDO_STATE_IDLE; if (((unsigned char *)commando_moby)[0x53] != 0) blend_moby_animation(commando_moby, 0, 0, scale_game_frames(10)); commando_data->unk302 = @@ -376,7 +379,7 @@ void blarg_elite_commando_update(char *commando_moby) { frame_time_sq * 12.566371f, frame_time * 12.566371f); if (((unsigned char *)commando_moby)[0x70] & 2) { - MOBY(commando_moby)->state = 5; + MOBY(commando_moby)->state = COMMANDO_STATE_FIRE_ROCKETS; if (((unsigned char *)commando_moby)[0x53] != 3) { blend_moby_animation(commando_moby, 3, 0, scale_game_frames(10)); } @@ -403,7 +406,7 @@ void blarg_elite_commando_update(char *commando_moby) { int count = commando_data->unk2DE + 1; commando_data->unk2DE = count; if ((short)count >= 3) { - MOBY(commando_moby)->state = 2; + MOBY(commando_moby)->state = COMMANDO_STATE_IDLE; if (((unsigned char *)commando_moby)[0x53] != 0) blend_moby_animation(commando_moby, 0, 0, scale_game_frames(10)); commando_data->unk2DC = scale_game_frames(60); @@ -418,7 +421,7 @@ void blarg_elite_commando_update(char *commando_moby) { 1); fast_dec_timer_s16(&commando_data->unk2DC); if (distance < 0.01f || commando_data->unk2DC == 0) { - MOBY(commando_moby)->state = 4; + MOBY(commando_moby)->state = COMMANDO_STATE_PREPARE_ROCKET_FIRE; if (((unsigned char *)commando_moby)[0x53] != 2) blend_moby_animation(commando_moby, 2, 0, scale_game_frames(30)); } @@ -431,7 +434,7 @@ void blarg_elite_commando_update(char *commando_moby) { case COMMANDO_STATE_KNOCKBACK_RECOVERY: if (((unsigned char *)commando_moby)[0x70] & 2) { idle: - MOBY(commando_moby)->state = 2; + MOBY(commando_moby)->state = COMMANDO_STATE_IDLE; if (((unsigned char *)commando_moby)[0x53] != 0) { ticks = 10; animate_idle: From e6d2bcbe1310d03b9eaf9367930d4b7bb66b2e22 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:32:48 +0000 Subject: [PATCH 1497/1502] decomp: clarify names in decoy_update domain_0_value_1 -> DECOY_HELD: Retail 0x002c4498..0x002c44a0 loads moby byte +0x20 and compares with 1 before removal when the equipped item is absent or not class 0x232. This is the identical selector used by existing case DECOY_HELD; its 0x002c4614..0x002c464c branch retains the decoy while its holder and equipped item remain valid. domain_1_value_1 -> DECOY_HELD: Retail 0x002c44cc..0x002c44d4 compares 1 against the same moby byte +0x20 dispatched at 0x002c45cc..0x002c45ec. Nonzero hero vehicle mode removes the held decoy. Existing local DECOY_HELD=1 names this exact selector, independently of the separate hero vehicle domain. domain_2_value_2 -> DECOY_THROWN_MOVEMENT: Retail 0x002c4514..0x002c451c loads moby +0x20 and tests unsigned state <2 to gate flags 0x41. The same byte selects existing DECOY_THROWN_MOVEMENT=2 at the switch; that branch applies gravity at 0x002c46cc..0x002c46dc and collision movement at 0x002c4800. The constant is the threshold excluding thrown and subsequent states. domain_3_value_1 -> DECOY_HELD: Original Ghidra case 0 stores 1 to param_1+0x20, exactly retail li v0,1 / sb v0,0x20(s1) at 0x002c45f4..0x002c45fc. This enters the existing DECOY_HELD branch of the same selector, which clears timer +0x44 and checks holder +0x40 and equipped item at 0x002c4614..0x002c464c. domain_4_value_3 -> DECOY_SETTLED_MOVEMENT: Retail 0x002c4a70 clears the thrown velocity, then 0x002c4a74..0x002c4a84 stores 3 to the same moby state byte +0x20 and initializes timer +0x44; 0x002c4a98 snaps to collision height. Existing DECOY_SETTLED_MOVEMENT=3 is the matching switch member, whose branch handles ground motion and supporting mobies. domain_5_value_4 -> DECOY_PRE_REMOVAL_DELAY: Retail 0x002c4ee4..0x002c4eec loads moby state +0x20 and branches on 4 to 0x002c5098. Authoritative C expresses its inverse as state !=4. This is the same selector as existing DECOY_PRE_REMOVAL_DELAY=4: its branch restores scale, decrements +0x44 and moves to wait-to-shrink at 0x002c50d0..0x002c5120. domain_6_value_5 -> DECOY_WAIT_TO_SHRINK: Retail 0x002c50d0..0x002c50d8 tests timer +0x44; after list removal, 0x002c5118..0x002c5120 stores 5 to moby +0x20. This enters existing DECOY_WAIT_TO_SHRINK=5 on the same switch selector, whose retail 0x002c5178..0x002c51ac waits for timer expiry or animation flag bit 2 before selecting shrink state 6. domain_7_value_6 -> DECOY_SHRINK_FOR_REMOVAL: Retail 0x002c5188..0x002c51ac selects 6 and stores it to moby state +0x20 when the timer expires or animation bit 2 is set. Existing DECOY_SHRINK_FOR_REMOVAL=6 names the same switch branch: retail 0x002c520c..0x002c5258 reduces scale and removes the moby below 10 percent of class scale. domain_8_value_0 -> DECOY_INITIALIZE: Original Ghidra default stores zero to param_1+0x20, matching sb zero,0x20(s1) at retail 0x002c5264. This is the exact byte dispatched by the function's switch and initialized by supplied spawn_decoy. Existing DECOY_INITIALIZE=0 resets timers and flags before entering DECOY_HELD at 0x002c45f4..0x002c4610. --- src/overlays/shared/weapons/decoy.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/shared/weapons/decoy.c b/src/overlays/shared/weapons/decoy.c index fd9101f2e5..7caf30df6a 100644 --- a/src/overlays/shared/weapons/decoy.c +++ b/src/overlays/shared/weapons/decoy.c @@ -580,18 +580,18 @@ void decoy_update(char *moby) { return; } if ((hero.items[0].moby == 0 || hero.items[0].moby->oclass != 0x232) && - (u8)MOBY(moby)->state == 1) { + (u8)MOBY(moby)->state == DECOY_HELD) { mine_spawn_drops(moby, D_L00_001B0830_lui); mark_moby_for_removal(moby); return; } - if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && (u8)MOBY(moby)->state == 1) { + if (hero.vehicle_mode != HERO_VEHICLE_MODE_ON_FOOT && (u8)MOBY(moby)->state == DECOY_HELD) { mine_spawn_drops(moby, D_L00_001B0830_lui); mark_moby_for_removal(moby); return; } ++decoy_instance_vars->unk54; - if (hero.unk20A5 != 0 && (u8)MOBY(moby)->state < 2) + if (hero.unk20A5 != 0 && (u8)MOBY(moby)->state < DECOY_THROWN_MOVEMENT) MOBY(moby)->flags |= 0x41; else MOBY(moby)->flags &= 0xffbe; @@ -605,7 +605,7 @@ void decoy_update(char *moby) { } switch ((u8)MOBY(moby)->state) { case DECOY_INITIALIZE: - MOBY(moby)->state = 1; + MOBY(moby)->state = DECOY_HELD; decoy_instance_vars->unk44 = 0; MOBY(moby)->collision_disable = -1; decoy_instance_vars->unk6C = 0; @@ -687,7 +687,7 @@ void decoy_update(char *moby) { *(int *)(moby + 0x94) = *(int *)(*(char **)(moby + 0x24) + 0x10); MOBY(moby)->collision_disable = 0; qzero(&decoy_instance_vars->unk10); - MOBY(moby)->state = 3; + MOBY(moby)->state = DECOY_SETTLED_MOVEMENT; decoy_instance_vars->unk44 = FUN_001fef20_2c4380(600); MOBY(moby)->pos.z = coll_hit.point.f[2]; qcopy(scratch.x, &coll_hit.normal_x); @@ -815,7 +815,7 @@ void decoy_update(char *moby) { blend_moby_animation(moby, 2, 0, FUN_001fef20_2c4380(10)); MOBY(moby)->anim_speed = random_float_between(0.7f, 1.05f); } - if ((u8)MOBY(moby)->state != 4) { + if ((u8)MOBY(moby)->state != DECOY_PRE_REMOVAL_DELAY) { len = probe_ground_height(&MOBY(moby)->pos, 0, 0.5f); if (len != 0.0f) { destroy_decoy_on_selected_materials(moby); @@ -861,7 +861,7 @@ void decoy_update(char *moby) { if (((u8 *)moby)[0x53]) blend_moby_animation(moby, 0, 0, FUN_001fef20_2c4380(60)); mine_spawn_drops(moby, D_L00_001B0830_lui); - MOBY(moby)->state = 5; + MOBY(moby)->state = DECOY_WAIT_TO_SHRINK; } } break; @@ -873,7 +873,7 @@ void decoy_update(char *moby) { if (MOBY(moby)->anim_flags & 2) *(int *)(moby + 0x58) = 0; if (fast_dec_timer_s16(&decoy_instance_vars->unk44) || (MOBY(moby)->anim_flags & 2)) - MOBY(moby)->state = 6; + MOBY(moby)->state = DECOY_SHRINK_FOR_REMOVAL; break; case DECOY_SHRINK_FOR_REMOVAL: { float len; @@ -891,6 +891,6 @@ void decoy_update(char *moby) { } case DECOY_RESET_TO_INITIALIZE: default: - MOBY(moby)->state = 0; + MOBY(moby)->state = DECOY_INITIALIZE; } } From acf3e44ed49d81950dcb3002fe0567649a000096 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:34:35 +0000 Subject: [PATCH 1498/1502] decomp: clarify names in sentrybot_update domain_0_value_21 -> SENTRYBOT_RECOVERABLE_KNOCKBACK: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00297abc-00297ac0 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_RECOVERABLE_KNOCKBACK member, not an equal-valued hero, animation or target-mode member. The established recoverable-knockback case steps motion with data+0x70 and permits material/height-gated recovery. domain_10_value_3 -> SENTRYBOT_PATROL_PAUSE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00297ed0-00297ee4 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_PATROL_PAUSE member, not an equal-valued hero, animation or target-mode member. The established patrol-pause case decrements data+0x14c before turning toward the next patrol point. domain_11_value_5 -> SENTRYBOT_DEACTIVATE_LINKED_MOBYS_AFTER_ANIMATION: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00297f34-00297f40 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_DEACTIVATE_LINKED_MOBYS_AFTER_ANIMATION member, not an equal-valued hero, animation or target-mode member. The established case waits for animation completion, deactivates indexed linked mobys, then restores saved patrol state. domain_12_value_3 -> SENTRYBOT_PATROL_PAUSE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00297ea0/00297f80 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_PATROL_PAUSE member, not an equal-valued hero, animation or target-mode member. The established patrol-pause case decrements data+0x14c before turning toward the next patrol point. domain_13_value_16 -> SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298040-00298050 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM member, not an equal-valued hero, animation or target-mode member. The established negative-joint-aim wait case waits for animation completion before selecting state 17 and animation 4. domain_14_value_11 -> SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 0029806c-00298070 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION member, not an equal-valued hero, animation or target-mode member. The established transition-animation case waits for moby+0x70 bit 2, then restores continuation state and animation from data+0x15c/+0x15d. domain_15_value_2 -> SENTRYBOT_PATROL_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298080-00298094 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_PATROL_IDLE member, not an equal-valued hero, animation or target-mode member. The established patrol-idle case arms a pause timer; patrol arrival and animation completion restore this same state with animation 0. domain_16_value_16 -> SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 002981f8-00298208 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM member, not an equal-valued hero, animation or target-mode member. The established negative-joint-aim wait case waits for animation completion before selecting state 17 and animation 4. domain_17_value_11 -> SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298224-00298228 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION member, not an equal-valued hero, animation or target-mode member. The established transition-animation case waits for moby+0x70 bit 2, then restores continuation state and animation from data+0x15c/+0x15d. domain_18_value_2 -> SENTRYBOT_PATROL_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 002983b4-002983c4 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_PATROL_IDLE member, not an equal-valued hero, animation or target-mode member. The established patrol-idle case arms a pause timer; patrol arrival and animation completion restore this same state with animation 0. domain_19_value_16 -> SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 0029840c-0029841c compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM member, not an equal-valued hero, animation or target-mode member. The established negative-joint-aim wait case waits for animation completion before selecting state 17 and animation 4. domain_1_value_23 -> SENTRYBOT_DEATH_KNOCKBACK: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00297ac4-00297ac8 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_DEATH_KNOCKBACK member, not an equal-valued hero, animation or target-mode member. The established death-knockback case steps motion with data+0x70 and bursts/removes the moby on flags 0x160. domain_20_value_11 -> SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298438-0029843c compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION member, not an equal-valued hero, animation or target-mode member. The established transition-animation case waits for moby+0x70 bit 2, then restores continuation state and animation from data+0x15c/+0x15d. domain_21_value_13 -> SENTRYBOT_PATROL_MOVE_FAST: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 0029848c-0029849c compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_PATROL_MOVE_FAST member, not an equal-valued hero, animation or target-mode member. The established fast-patrol case selects the indexed patrol point and moves at frame_time*3.5 before marking arrival. domain_22_value_11 -> SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 002993d8-002993e0 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION member, not an equal-valued hero, animation or target-mode member. The established transition-animation case waits for moby+0x70 bit 2, then restores continuation state and animation from data+0x15c/+0x15d. domain_23_value_5 -> SENTRYBOT_DEACTIVATE_LINKED_MOBYS_AFTER_ANIMATION: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298510-0029851c compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_DEACTIVATE_LINKED_MOBYS_AFTER_ANIMATION member, not an equal-valued hero, animation or target-mode member. The established case waits for animation completion, deactivates indexed linked mobys, then restores saved patrol state. domain_24_value_12 -> SENTRYBOT_ALERT_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 002985f0-00298600 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_ALERT_IDLE member, not an equal-valued hero, animation or target-mode member. The established alert-idle case chooses return-home, target response or fast patrol; arrivals use idle animation 0. domain_25_value_16 -> SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298658-00298668 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM member, not an equal-valued hero, animation or target-mode member. The established negative-joint-aim wait case waits for animation completion before selecting state 17 and animation 4. domain_26_value_11 -> SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298684-00298688 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION member, not an equal-valued hero, animation or target-mode member. The established transition-animation case waits for moby+0x70 bit 2, then restores continuation state and animation from data+0x15c/+0x15d. domain_27_value_9 -> SENTRYBOT_RETURN_HOME: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298698/00299274-00299284 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_RETURN_HOME member, not an equal-valued hero, animation or target-mode member. The established return-home case moves to the spawn position saved at data+0x160 at frame_time*2. domain_28_value_12 -> SENTRYBOT_ALERT_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298874-0029887c compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_ALERT_IDLE member, not an equal-valued hero, animation or target-mode member. The established alert-idle case chooses return-home, target response or fast patrol; arrivals use idle animation 0. domain_29_value_12 -> SENTRYBOT_ALERT_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 002988d0-002988dc compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_ALERT_IDLE member, not an equal-valued hero, animation or target-mode member. The established alert-idle case chooses return-home, target response or fast patrol; arrivals use idle animation 0. domain_2_value_2 -> SENTRYBOT_PATROL_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00297c2c-00297c74 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_PATROL_IDLE member, not an equal-valued hero, animation or target-mode member. The established patrol-idle case arms a pause timer; patrol arrival and animation completion restore this same state with animation 0. domain_30_value_14 -> SENTRYBOT_APPROACH_LINKED_MOBY: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298930-00298940 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_APPROACH_LINKED_MOBY member, not an equal-valued hero, animation or target-mode member. The established approach case resolves data+0x128, computes a destination 1.5 short of that linked moby and moves toward it. domain_31_value_15 -> SENTRYBOT_ACTIVATE_LINKED_MOBY: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298a38-00298a4c compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_ACTIVATE_LINKED_MOBY member, not an equal-valued hero, animation or target-mode member. The established activation case calls the alarm-duration helper on data+0x128 at animation frame >=12 and completion. domain_32_value_12 -> SENTRYBOT_ALERT_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298b2c-00298b38 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_ALERT_IDLE member, not an equal-valued hero, animation or target-mode member. The established alert-idle case chooses return-home, target response or fast patrol; arrivals use idle animation 0. domain_33_value_19 -> SENTRYBOT_EMIT_WITH_POSITIVE_JOINT_AIM: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298b28/00298b54-00298b58 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_EMIT_WITH_POSITIVE_JOINT_AIM member, not an equal-valued hero, animation or target-mode member. The established emission case selects joint 2, positively scales the nominal matrix axis and emits during frames [0.85,3). domain_34_value_12 -> SENTRYBOT_ALERT_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298bb4-00298bc0 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_ALERT_IDLE member, not an equal-valued hero, animation or target-mode member. The established alert-idle case chooses return-home, target response or fast patrol; arrivals use idle animation 0. domain_35_value_17 -> SENTRYBOT_EMIT_WITH_NEGATIVE_JOINT_AIM: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298bb0/00298bdc-00298be0 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_EMIT_WITH_NEGATIVE_JOINT_AIM member, not an equal-valued hero, animation or target-mode member. The established emission case selects joint 3, negates the nominal matrix-axis scale and emits during frames [0.85,3). domain_36_value_12 -> SENTRYBOT_ALERT_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298dc8/00299160-0029916c compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_ALERT_IDLE member, not an equal-valued hero, animation or target-mode member. The established alert-idle case chooses return-home, target response or fast patrol; arrivals use idle animation 0. domain_37_value_14 -> SENTRYBOT_APPROACH_LINKED_MOBY: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298e00-00298e10 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_APPROACH_LINKED_MOBY member, not an equal-valued hero, animation or target-mode member. The established approach case resolves data+0x128, computes a destination 1.5 short of that linked moby and moves toward it. domain_38_value_12 -> SENTRYBOT_ALERT_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298e90-00298e98/00299160-0029916c compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_ALERT_IDLE member, not an equal-valued hero, animation or target-mode member. The established alert-idle case chooses return-home, target response or fast patrol; arrivals use idle animation 0. domain_39_value_16 -> SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00298e9c-00298eac compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM member, not an equal-valued hero, animation or target-mode member. The established negative-joint-aim wait case waits for animation completion before selecting state 17 and animation 4. domain_3_value_1 -> SENTRYBOT_WAIT_FOR_LINKED_MOBY: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00297c84-00297cc0 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_LINKED_MOBY member, not an equal-valued hero, animation or target-mode member. Initialization selects this state when a linked_moby slot exists; its established case waits for a linked object's state >= 2. domain_40_value_12 -> SENTRYBOT_ALERT_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00299088/00299160-0029916c compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_ALERT_IDLE member, not an equal-valued hero, animation or target-mode member. The established alert-idle case chooses return-home, target response or fast patrol; arrivals use idle animation 0. domain_41_value_14 -> SENTRYBOT_APPROACH_LINKED_MOBY: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 002990c0-002990d0 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_APPROACH_LINKED_MOBY member, not an equal-valued hero, animation or target-mode member. The established approach case resolves data+0x128, computes a destination 1.5 short of that linked moby and moves toward it. domain_42_value_12 -> SENTRYBOT_ALERT_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00299150-0029916c compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_ALERT_IDLE member, not an equal-valued hero, animation or target-mode member. The established alert-idle case chooses return-home, target response or fast patrol; arrivals use idle animation 0. domain_43_value_18 -> SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_POSITIVE_JOINT_AIM: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 0029915c/00299194-002991a0 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_POSITIVE_JOINT_AIM member, not an equal-valued hero, animation or target-mode member. The established positive-joint-aim wait case waits for animation completion before selecting state 19 and animation 6. domain_44_value_9 -> SENTRYBOT_RETURN_HOME: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 002991dc-002991ec compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_RETURN_HOME member, not an equal-valued hero, animation or target-mode member. The established return-home case moves to the spawn position saved at data+0x160 at frame_time*2. domain_45_value_9 -> SENTRYBOT_RETURN_HOME: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00299274-00299284 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_RETURN_HOME member, not an equal-valued hero, animation or target-mode member. The established return-home case moves to the spawn position saved at data+0x160 at frame_time*2. domain_46_value_13 -> SENTRYBOT_PATROL_MOVE_FAST: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 002993ac-002993bc compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_PATROL_MOVE_FAST member, not an equal-valued hero, animation or target-mode member. The established fast-patrol case selects the indexed patrol point and moves at frame_time*3.5 before marking arrival. domain_47_value_11 -> SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 002993d8-002993e0 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION member, not an equal-valued hero, animation or target-mode member. The established transition-animation case waits for moby+0x70 bit 2, then restores continuation state and animation from data+0x15c/+0x15d. domain_48_value_12 -> SENTRYBOT_ALERT_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 002994a0-002994ac compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_ALERT_IDLE member, not an equal-valued hero, animation or target-mode member. The established alert-idle case chooses return-home, target response or fast patrol; arrivals use idle animation 0. domain_49_value_16 -> SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 002994d4-002994e4 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM member, not an equal-valued hero, animation or target-mode member. The established negative-joint-aim wait case waits for animation completion before selecting state 17 and animation 4. domain_4_value_2 -> SENTRYBOT_PATROL_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00297d24-00297d2c compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_PATROL_IDLE member, not an equal-valued hero, animation or target-mode member. The established patrol-idle case arms a pause timer; patrol arrival and animation completion restore this same state with animation 0. domain_50_value_11 -> SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00299504-00299508 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION member, not an equal-valued hero, animation or target-mode member. The established transition-animation case waits for moby+0x70 bit 2, then restores continuation state and animation from data+0x15c/+0x15d. domain_5_value_16 -> SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00297d50-00297d60 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM member, not an equal-valued hero, animation or target-mode member. The established negative-joint-aim wait case waits for animation completion before selecting state 17 and animation 4. domain_6_value_11 -> SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00297d7c-00297d80 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION member, not an equal-valued hero, animation or target-mode member. The established transition-animation case waits for moby+0x70 bit 2, then restores continuation state and animation from data+0x15c/+0x15d. domain_7_value_13 -> SENTRYBOT_PATROL_MOVE_FAST: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00297e14-00297e24 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_PATROL_MOVE_FAST member, not an equal-valued hero, animation or target-mode member. The established fast-patrol case selects the indexed patrol point and moves at frame_time*3.5 before marking arrival. domain_8_value_11 -> SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 002993d8-002993e0 compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION member, not an equal-valued hero, animation or target-mode member. The established transition-animation case waits for moby+0x70 bit 2, then restores continuation state and animation from data+0x15c/+0x15d. domain_9_value_2 -> SENTRYBOT_PATROL_IDLE: Authoritative sentrybot.c SHA-256 578802efa53934667081df431113ee0e627c3ac4d9ee9e6fd4ee4a1eef1e4795 identifies this token as MOBY(moby)->state. Original retail Ghidra and instructions 00297e94-00297e9c compare or store the state byte at 0x20(s2); s2 is the input moby (002979e8), also dispatched at 00297bd0-00297bf0. Reuse the existing function-local SENTRYBOT_PATROL_IDLE member, not an equal-valued hero, animation or target-mode member. The established patrol-idle case arms a pause timer; patrol arrival and animation completion restore this same state with animation 0. --- src/overlays/shared/enemies/sentrybot.c | 100 ++++++++++++------------ 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/src/overlays/shared/enemies/sentrybot.c b/src/overlays/shared/enemies/sentrybot.c index 8b3d1035ae..0945c88a32 100644 --- a/src/overlays/shared/enemies/sentrybot.c +++ b/src/overlays/shared/enemies/sentrybot.c @@ -320,7 +320,7 @@ void sentrybot_update(unsigned char *moby) { } } update_sentrybot_hit_response_and_target_visibility(moby, flag); - if (flag != 0 && MOBY(moby)->state != 0x15 && MOBY(moby)->state != 0x17) { + if (flag != 0 && MOBY(moby)->state != SENTRYBOT_RECOVERABLE_KNOCKBACK && MOBY(moby)->state != SENTRYBOT_DEATH_KNOCKBACK) { MOBY(moby)->collision = 0; MOBY(moby)->flags = (MOBY(moby)->flags | 0x41) & 0xEFFF; return; @@ -363,13 +363,13 @@ void sentrybot_update(unsigned char *moby) { if (sentrybot_instance_data->unk148 < 5) sentrybot_instance_data->unk148 = 5; sentrybot_instance_data->unk144 = 1; - MOBY(moby)->state = 2; + MOBY(moby)->state = SENTRYBOT_PATROL_IDLE; MOBY(moby)->flags |= 0x1000; { int i; for (i = 0; i < 4; i++) { if (sentrybot_instance_data->linked_moby[i] != -1) { - MOBY(moby)->state = 1; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_LINKED_MOBY; break; } } @@ -381,7 +381,7 @@ void sentrybot_update(unsigned char *moby) { for (i = 0; i < 4; i++) { if (((unsigned char *)((sentrybot_instance_data->linked_moby[i] << 8) + (int)l15_moby_array))[0x20] >= 2) { - MOBY(moby)->state = 2; + MOBY(moby)->state = SENTRYBOT_PATROL_IDLE; break; } } @@ -392,12 +392,12 @@ void sentrybot_update(unsigned char *moby) { if (sentrybot_instance_data->unk114 != 2) { MOBY(moby)->command = 1; if (sentrybot_instance_data->unk15F != 0) { - MOBY(moby)->state = 0x10; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM; if (MOBY(moby)->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } else { sentrybot_instance_data->unk15F = 1; - MOBY(moby)->state = 0xB; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION; sentrybot_instance_data->unk15C = 0x10; sentrybot_instance_data->unk15D = 3; if (MOBY(moby)->prev_seq != 1) @@ -421,12 +421,12 @@ void sentrybot_update(unsigned char *moby) { sentrybot_instance_data->unk144 = 0; MOBY(moby)->command = 1; if (sentrybot_instance_data->unk15F != 0) { - MOBY(moby)->state = 0xD; + MOBY(moby)->state = SENTRYBOT_PATROL_MOVE_FAST; if (MOBY(moby)->prev_seq != 0xE) blend_moby_animation(moby, 0xE, 0, scale_game_frames(10)); } else { sentrybot_instance_data->unk15F = 1; - MOBY(moby)->state = 0xB; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION; sentrybot_instance_data->unk15C = 0xD; sentrybot_instance_data->unk15D = 0xE; if (MOBY(moby)->prev_seq != 1) @@ -451,13 +451,13 @@ void sentrybot_update(unsigned char *moby) { (float *)(sentrybot_instance_data->attention_target + 0x10), (void *)0xA, (void *)0xF); - } else if (MOBY(moby)->state == 2) { + } else if (MOBY(moby)->state == SENTRYBOT_PATROL_IDLE) { if (sentrybot_instance_data->unk124 != -1) { if (sentrybot_instance_data->unk144 == 0 || can_sentrybot_advance_patrol(moby) != 0) { sentrybot_instance_data->unk14C = scale_game_frames(sentrybot_instance_data->unk148); - MOBY(moby)->state = 3; + MOBY(moby)->state = SENTRYBOT_PATROL_PAUSE; } } else if (sentrybot_instance_data->unk158 != 0 && hero.state.current == 0x59) { if (sentrybot_instance_data->unk150 != -1 || @@ -465,7 +465,7 @@ void sentrybot_update(unsigned char *moby) { (sentrybot_instance_data->unk154 == 0 && random_integer_below(0x78) == 0)) { sentrybot_instance_data->unk15D = 0; sentrybot_instance_data->unk15C = 2; - MOBY(moby)->state = 5; + MOBY(moby)->state = SENTRYBOT_DEACTIVATE_LINKED_MOBYS_AFTER_ANIMATION; if (MOBY(moby)->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(10)); } @@ -473,7 +473,7 @@ void sentrybot_update(unsigned char *moby) { begin_sentrybot_turn_toward_heading( moby, sentrybot_instance_data, 2, 0, sentrybot_instance_data->home_yaw); } - } else if (MOBY(moby)->state == 3) { + } else if (MOBY(moby)->state == SENTRYBOT_PATROL_PAUSE) { if (fast_dec_timer(&sentrybot_instance_data->unk14C) != 0) { if (sentrybot_instance_data->unk144 != 0) { sentrybot_instance_data->patrol_point = @@ -495,19 +495,19 @@ void sentrybot_update(unsigned char *moby) { if (sentrybot_instance_data->unk114 != 2) { MOBY(moby)->command = 1; if (sentrybot_instance_data->unk15F != 0) { - MOBY(moby)->state = 0x10; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM; if (MOBY(moby)->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } else { sentrybot_instance_data->unk15F = 1; - MOBY(moby)->state = 0xB; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION; sentrybot_instance_data->unk15C = 0x10; sentrybot_instance_data->unk15D = 3; if (MOBY(moby)->prev_seq != 1) blend_moby_animation(moby, 1, 0, scale_game_frames(10)); } } else if (MOBY(moby)->anim_flags & 2) { - MOBY(moby)->state = 2; + MOBY(moby)->state = SENTRYBOT_PATROL_IDLE; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); sentrybot_instance_data->unk196 = scale_game_frames(0x168); @@ -550,12 +550,12 @@ void sentrybot_update(unsigned char *moby) { sentrybot_instance_data->unkD0[1] - MOBY(moby)->pos.y)) < 0.5235988f) { MOBY(moby)->command = 1; if (sentrybot_instance_data->unk15F != 0) { - MOBY(moby)->state = 0x10; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM; if (MOBY(moby)->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } else { sentrybot_instance_data->unk15F = 1; - MOBY(moby)->state = 0xB; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION; sentrybot_instance_data->unk15C = 0x10; sentrybot_instance_data->unk15D = 3; if (MOBY(moby)->prev_seq != 1) @@ -606,19 +606,19 @@ void sentrybot_update(unsigned char *moby) { (float *)((char *)D_L15_001B0AB0[sentrybot_instance_data->unk124] + (sentrybot_instance_data->patrol_point * 0x10 + 0x10)), sp)) { - MOBY(moby)->state = 2; + MOBY(moby)->state = SENTRYBOT_PATROL_IDLE; sentrybot_instance_data->unk144 = 1; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } else if (sentrybot_instance_data->unk114 != 2) { MOBY(moby)->command = 1; if (sentrybot_instance_data->unk15F != 0) { - MOBY(moby)->state = 0x10; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM; if (MOBY(moby)->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } else { sentrybot_instance_data->unk15F = 1; - MOBY(moby)->state = 0xB; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION; sentrybot_instance_data->unk15C = 0x10; sentrybot_instance_data->unk15D = 3; if (MOBY(moby)->prev_seq != 1) @@ -636,12 +636,12 @@ void sentrybot_update(unsigned char *moby) { sentrybot_instance_data->unk14C = scale_game_frames(0x3C); MOBY(moby)->command = 1; if (sentrybot_instance_data->unk15F != 0) { - MOBY(moby)->state = 0xD; + MOBY(moby)->state = SENTRYBOT_PATROL_MOVE_FAST; if (MOBY(moby)->prev_seq != 0xE) blend_moby_animation(moby, 0xE, 0, scale_game_frames(10)); } else { sentrybot_instance_data->unk15F = 1; - MOBY(moby)->state = 0xB; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION; sentrybot_instance_data->unk15C = 0xD; sentrybot_instance_data->unk15D = 0xE; if (MOBY(moby)->prev_seq != 1) @@ -660,7 +660,7 @@ void sentrybot_update(unsigned char *moby) { sentrybot_instance_data->unk154 == 0) { sentrybot_instance_data->unk15C = MOBY(moby)->state; sentrybot_instance_data->unk15D = 0xD; - MOBY(moby)->state = 5; + MOBY(moby)->state = SENTRYBOT_DEACTIVATE_LINKED_MOBYS_AFTER_ANIMATION; if (MOBY(moby)->prev_seq != 2) blend_moby_animation(moby, 2, 0, scale_game_frames(10)); } @@ -685,19 +685,19 @@ void sentrybot_update(unsigned char *moby) { (float *)((char *)D_L15_001B0AB0[sentrybot_instance_data->unk124] + (sentrybot_instance_data->patrol_point * 0x10 + 0x10)), sp)) { - MOBY(moby)->state = 0xC; + MOBY(moby)->state = SENTRYBOT_ALERT_IDLE; sentrybot_instance_data->unk144 = 1; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } else if (sentrybot_instance_data->unk114 != 2 && sentrybot_instance_data->unk15B == 0) { MOBY(moby)->command = 1; if (sentrybot_instance_data->unk15F != 0) { - MOBY(moby)->state = 0x10; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM; if (MOBY(moby)->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } else { sentrybot_instance_data->unk15F = 1; - MOBY(moby)->state = 0xB; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION; sentrybot_instance_data->unk15C = 0x10; sentrybot_instance_data->unk15D = 3; if (MOBY(moby)->prev_seq != 1) @@ -706,7 +706,7 @@ void sentrybot_update(unsigned char *moby) { } else if (sentrybot_instance_data->alert_timer != 0) { sentrybot_instance_data->unk14C = scale_game_frames(0x3C); } else { - MOBY(moby)->state = 9; + MOBY(moby)->state = SENTRYBOT_RETURN_HOME; if (MOBY(moby)->prev_seq != 0xD) blend_moby_animation(moby, 0xD, 0, scale_game_frames(10)); if (sentrybot_instance_data->alarm_moby_index != -1) { @@ -770,7 +770,7 @@ void sentrybot_update(unsigned char *moby) { (void *)0x10, (void *)3); } else { - MOBY(moby)->state = 0xC; + MOBY(moby)->state = SENTRYBOT_ALERT_IDLE; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } @@ -784,7 +784,7 @@ void sentrybot_update(unsigned char *moby) { } if (MOBY(moby)->anim_flags & 2) { if (hero.state.current == 0x65) { - MOBY(moby)->state = 0xC; + MOBY(moby)->state = SENTRYBOT_ALERT_IDLE; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } else { @@ -795,7 +795,7 @@ void sentrybot_update(unsigned char *moby) { 0x78) + 8) == 0 && can_sentrybot_approach_linked_moby(moby) != 0) { - MOBY(moby)->state = 0xE; + MOBY(moby)->state = SENTRYBOT_APPROACH_LINKED_MOBY; if (MOBY(moby)->prev_seq != 0xE) blend_moby_animation(moby, 0xE, 0, scale_game_frames(0x14)); } else if (sentrybot_instance_data->unk15C == 0x10) { @@ -826,7 +826,7 @@ void sentrybot_update(unsigned char *moby) { fast_vec_normalize(va, va, fast_vec_length(va) - 1.5f); fast_vec_add(va, va, &MOBY(moby)->pos); if (move_sentrybot_toward_point((char *)moby, va, frame_time * 4.0f)) { - MOBY(moby)->state = 0xF; + MOBY(moby)->state = SENTRYBOT_ACTIVATE_LINKED_MOBY; if (MOBY(moby)->prev_seq != 9) blend_moby_animation(moby, 9, 0, scale_game_frames(10)); } @@ -855,11 +855,11 @@ void sentrybot_update(unsigned char *moby) { alert_visible_group_sentrybots(moby); if (MOBY(moby)->anim_flags & 2) { if (hero.state.current == 0x65) { - MOBY(moby)->state = 0xC; + MOBY(moby)->state = SENTRYBOT_ALERT_IDLE; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } else { - MOBY(moby)->state = 0x13; + MOBY(moby)->state = SENTRYBOT_EMIT_WITH_POSITIVE_JOINT_AIM; sentrybot_instance_data->unk19E = 0; if (MOBY(moby)->prev_seq != 6) blend_moby_animation(moby, 6, 0, scale_game_frames(10)); @@ -872,11 +872,11 @@ void sentrybot_update(unsigned char *moby) { alert_visible_group_sentrybots(moby); if (MOBY(moby)->anim_flags & 2) { if (hero.state.current == 0x65) { - MOBY(moby)->state = 0xC; + MOBY(moby)->state = SENTRYBOT_ALERT_IDLE; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } else { - MOBY(moby)->state = 0x11; + MOBY(moby)->state = SENTRYBOT_EMIT_WITH_NEGATIVE_JOINT_AIM; sentrybot_instance_data->unk19E = 0; if (MOBY(moby)->prev_seq != 4) blend_moby_animation(moby, 4, 0, scale_game_frames(10)); @@ -918,7 +918,7 @@ void sentrybot_update(unsigned char *moby) { } if (MOBY(moby)->anim_flags & 2) { if (hero.state.current == 0x65) { - MOBY(moby)->state = 0xC; + MOBY(moby)->state = SENTRYBOT_ALERT_IDLE; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } else if (sentrybot_instance_data->alarm_moby_index != -1 && @@ -928,7 +928,7 @@ void sentrybot_update(unsigned char *moby) { 0x78) + 8) == 0 && can_sentrybot_approach_linked_moby(moby) != 0) { - MOBY(moby)->state = 0xE; + MOBY(moby)->state = SENTRYBOT_APPROACH_LINKED_MOBY; if (MOBY(moby)->prev_seq != 0xE) blend_moby_animation(moby, 0xE, 0, scale_game_frames(0x14)); } else if (fast_difference_between_rotations( @@ -942,11 +942,11 @@ void sentrybot_update(unsigned char *moby) { (void *)0x10, (void *)3); } else if (sentrybot_instance_data->unk114 == 2) { - MOBY(moby)->state = 0xC; + MOBY(moby)->state = SENTRYBOT_ALERT_IDLE; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } else { - MOBY(moby)->state = 0x10; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM; if (MOBY(moby)->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } @@ -988,7 +988,7 @@ void sentrybot_update(unsigned char *moby) { } if (MOBY(moby)->anim_flags & 2) { if (hero.state.current == 0x65) { - MOBY(moby)->state = 0xC; + MOBY(moby)->state = SENTRYBOT_ALERT_IDLE; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } else if (sentrybot_instance_data->alarm_moby_index != -1 && @@ -998,7 +998,7 @@ void sentrybot_update(unsigned char *moby) { 0x78) + 8) == 0 && can_sentrybot_approach_linked_moby(moby) != 0) { - MOBY(moby)->state = 0xE; + MOBY(moby)->state = SENTRYBOT_APPROACH_LINKED_MOBY; if (MOBY(moby)->prev_seq != 0xE) blend_moby_animation(moby, 0xE, 0, scale_game_frames(0x14)); } else if (fast_difference_between_rotations( @@ -1012,11 +1012,11 @@ void sentrybot_update(unsigned char *moby) { (void *)0x12, (void *)5); } else if (sentrybot_instance_data->unk114 == 2) { - MOBY(moby)->state = 0xC; + MOBY(moby)->state = SENTRYBOT_ALERT_IDLE; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } else { - MOBY(moby)->state = 0x12; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_POSITIVE_JOINT_AIM; if (MOBY(moby)->prev_seq != 5) blend_moby_animation(moby, 5, 0, scale_game_frames(10)); } @@ -1025,7 +1025,7 @@ void sentrybot_update(unsigned char *moby) { break; case SENTRYBOT_ALERT_IDLE: if (hero.state.current == 0x65) { - MOBY(moby)->state = 9; + MOBY(moby)->state = SENTRYBOT_RETURN_HOME; if (MOBY(moby)->prev_seq != 0xD) blend_moby_animation(moby, 0xD, 0, scale_game_frames(10)); if (sentrybot_instance_data->alarm_moby_index != -1) { @@ -1045,7 +1045,7 @@ void sentrybot_update(unsigned char *moby) { (void *)0x10, (void *)3); } else if (sentrybot_instance_data->alert_timer == 0) { - MOBY(moby)->state = 9; + MOBY(moby)->state = SENTRYBOT_RETURN_HOME; if (MOBY(moby)->prev_seq != 0xD) blend_moby_animation(moby, 0xD, 0, scale_game_frames(10)); if (sentrybot_instance_data->alarm_moby_index != -1) { @@ -1080,12 +1080,12 @@ void sentrybot_update(unsigned char *moby) { sentrybot_instance_data->unk14C = scale_game_frames(0x3C); MOBY(moby)->command = 1; if (sentrybot_instance_data->unk15F != 0) { - MOBY(moby)->state = 0xD; + MOBY(moby)->state = SENTRYBOT_PATROL_MOVE_FAST; if (MOBY(moby)->prev_seq != 0xE) blend_moby_animation(moby, 0xE, 0, scale_game_frames(10)); } else { sentrybot_instance_data->unk15F = 1; - MOBY(moby)->state = 0xB; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION; sentrybot_instance_data->unk15C = 0xD; sentrybot_instance_data->unk15D = 0xE; if (MOBY(moby)->prev_seq != 1) @@ -1101,18 +1101,18 @@ void sentrybot_update(unsigned char *moby) { if (collision_hit_material() == -1 && sentrybot_instance_data->home_pos[2] - 5.0f < MOBY(moby)->pos.z) { if (hero.state.current == 0x65) { - MOBY(moby)->state = 0xC; + MOBY(moby)->state = SENTRYBOT_ALERT_IDLE; if (MOBY(moby)->prev_seq != 0) blend_moby_animation(moby, 0, 0, scale_game_frames(10)); } else { MOBY(moby)->command = 1; if (sentrybot_instance_data->unk15F != 0) { - MOBY(moby)->state = 0x10; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM; if (MOBY(moby)->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } else { sentrybot_instance_data->unk15F = 1; - MOBY(moby)->state = 0xB; + MOBY(moby)->state = SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION; sentrybot_instance_data->unk15C = 0x10; sentrybot_instance_data->unk15D = 3; if (MOBY(moby)->prev_seq != 1) From dcc77cdde30c9edb40bbbb631adaff6ad8648fb9 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 17:51:54 +0000 Subject: [PATCH 1499/1502] decomp: format naming changes after upstream rebase --- src/camera/camera_activation_check_priority.c | 3 +- src/camera/start_camera_blend.c | 6 +- ...e_instance_attachment_points_and_lengths.c | 3 +- src/overlays/l00/mobys/veldin_robot_enemy.c | 30 +++---- src/overlays/l01/hero/hero_set_state.c | 3 +- .../update_hero_motion_for_current_state.c | 40 +++++---- src/overlays/l01/mobys/pool_bubbles.c | 10 +-- src/overlays/l02/hero/hero_set_state.c | 3 +- .../l02/hero/update_hero_state_motion.c | 70 +++++++++------- src/overlays/l02/mobys/sand_shark.c | 65 +++++++-------- src/overlays/l02/mobys/sand_shark_nest.c | 19 ++--- src/overlays/l03/hero/hero_set_state.c | 3 +- .../update_hero_motion_for_current_state.c | 45 ++++++---- src/overlays/l03/mobys/kerwan_path_enemy.c | 45 ++++------ src/overlays/l03/mobys/mine_layer.c | 21 ++--- src/overlays/l03/mobys/red_ship_1.c | 16 ++-- src/overlays/l03/mobys/robot_dog.c | 43 ++++------ src/overlays/l04/mobys/circular_saw_enemy.c | 32 +++---- src/overlays/l04/mobys/leg_walker.c | 10 +-- .../hero/apply_hero_ground_material_effects.c | 24 +++--- .../l05/hero/update_hero_motion_by_state.c | 45 ++++++---- src/overlays/l05/mobys/extermibot.c | 51 +++++------- src/overlays/l05/mobys/extermitank.c | 16 ++-- src/overlays/l05/mobys/hoverboard_girl.c | 10 +-- src/overlays/l05/mobys/scenery_ship.c | 14 ++-- .../update_hero_motion_for_current_state.c | 68 +++++++++------ src/overlays/l06/mobys/alien_queen.c | 42 +++++----- src/overlays/l06/mobys/alien_snapper.c | 47 +++++------ src/overlays/l07/mobys/sharkigator.c | 44 +++++----- src/overlays/l07/mobys/snagglebeast.c | 42 +++++----- src/overlays/l08/hero/hero_set_state.c | 3 +- .../update_hero_motion_for_current_state.c | 52 ++++++++---- src/overlays/l08/mobys/bomber_tank.c | 25 +++--- src/overlays/l08/mobys/heavy_gunship.c | 18 ++-- src/overlays/l08/mobys/rocket.c | 22 +++-- src/overlays/l08/mobys/shrub.c | 18 ++-- src/overlays/l09/mobys/refueling_station.c | 16 ++-- src/overlays/l10/mobys/blarg_ship.c | 29 +++---- src/overlays/l10/mobys/darter.c | 34 ++++---- .../l10/mobys/data_processor_linked_effect.c | 14 ++-- src/overlays/l10/mobys/linked_moby_hitbox.c | 16 ++-- src/overlays/l10/mobys/screamer.c | 31 ++++--- src/overlays/l10/mobys/toxic_crab.c | 39 ++++----- .../l11/hero/update_hero_motion_by_state.c | 49 +++++++---- src/overlays/l11/mobys/energy_sphere.c | 12 ++- src/overlays/l11/mobys/jet_fighter.c | 27 +++--- src/overlays/l11/mobys/owner_linked_moby.c | 19 ++--- src/overlays/l11/mobys/pokitaru_boat.c | 20 ++--- src/overlays/l11/mobys/psytcopus.c | 23 +++-- src/overlays/l11/mobys/puffoid.c | 83 ++++++------------- src/overlays/l11/mobys/resort_owner.c | 3 +- .../update_hero_motion_for_current_state.c | 69 ++++++++------- src/overlays/l12/mobys/blarg_helicopter.c | 23 +++-- src/overlays/l12/mobys/blarg_trooper.c | 31 +++---- src/overlays/l12/mobys/homing_mine_spawner.c | 20 ++--- src/overlays/l12/mobys/hoven_anklebiter.c | 64 +++++--------- .../l12/mobys/planetbuster_maximus_part.c | 21 +++-- src/overlays/l12/mobys/rocket.c | 12 ++- src/overlays/l13/mobys/asteroid.c | 18 ++-- src/overlays/l13/mobys/blarg_gunner.c | 17 ++-- src/overlays/l13/mobys/blarg_space_commando.c | 37 ++++----- src/overlays/l13/mobys/blarg_space_fighter.c | 20 ++--- src/overlays/l13/mobys/blarg_turret.c | 18 ++-- src/overlays/l13/mobys/elevator.c | 24 +++--- src/overlays/l13/mobys/fighter_jet.c | 27 +++--- src/overlays/l13/mobys/forcefield_tower.c | 14 ++-- .../l13/mobys/hovering_rocket_attacker.c | 26 +++--- src/overlays/l13/mobys/lift.c | 24 +++--- src/overlays/l13/mobys/qwarks_starfighter.c | 56 +++++-------- src/overlays/l14/hero/hero_set_state.c | 3 +- .../l14/hero/update_hero_motion_by_state.c | 48 +++++++---- .../l14/mobys/blarg_heavy_interceptor.c | 31 +++---- src/overlays/l14/mobys/bolt_thief.c | 22 +++-- src/overlays/l14/mobys/enemy_fighter.c | 15 ++-- src/overlays/l14/mobys/flying_car.c | 16 ++-- src/overlays/l14/mobys/machinegun_turret.c | 36 ++++---- src/overlays/l14/mobys/minibomber.c | 45 +++------- .../l14/mobys/rocket_strike_fighter.c | 18 ++-- src/overlays/l14/mobys/taxi.c | 25 +++--- src/overlays/l15/hero/hero_set_state.c | 3 +- .../update_hero_motion_for_current_state.c | 63 +++++++++----- src/overlays/l15/mobys/helicopter.c | 28 +++---- .../l15/mobys/quartu_cutscene_trigger.c | 2 + src/overlays/l15/mobys/ultramech_unlimited.c | 36 ++++---- .../hero/apply_hero_ground_material_effects.c | 24 +++--- .../update_hero_motion_for_current_state.c | 51 ++++++++---- src/overlays/l16/mobys/bolt_thief.c | 22 +++-- src/overlays/l16/mobys/chicken_relocator.c | 12 ++- src/overlays/l16/mobys/chomper.c | 21 ++--- src/overlays/l16/mobys/test_dummy.c | 35 ++++---- .../update_hero_motion_for_current_state.c | 57 ++++++++----- src/overlays/l17/mobys/dreks_fleet_turret.c | 23 +++-- src/overlays/l17/mobys/fighter_jet.c | 79 +++++++++--------- .../update_hero_motion_for_current_state.c | 70 ++++++++++------ src/overlays/l18/mobys/camera_transition.c | 12 ++- .../l18/mobys/drek_boss_electric_ball.c | 13 ++- src/overlays/l18/mobys/falling_moby_group.c | 22 ++--- src/overlays/l18/mobys/floating_platform.c | 30 ++----- src/overlays/l18/mobys/gadgebot.c | 49 +++-------- src/overlays/l18/mobys/mine.c | 31 +++---- .../l18/mobys/thruster_pack_lock_red.c | 18 ++-- src/overlays/shared/camera/grindrail_camera.c | 17 ++-- .../shared/camera/hoverboard_camera.c | 15 ++-- .../shared/camera/swing_volume_camera.c | 22 ++--- src/overlays/shared/enemies/armed_transport.c | 26 +++--- .../shared/enemies/armed_transport_rocket.c | 10 +-- .../shared/enemies/blarg_elite_commando.c | 42 ++++------ .../enemies/blarg_elite_commando_rocket.c | 10 +-- .../shared/enemies/blarg_helicopter.c | 21 ++--- .../shared/enemies/blarg_space_commando.c | 35 ++++---- src/overlays/shared/enemies/bolt_thief_mine.c | 14 ++-- .../shared/enemies/bomb_spawner_bomb.c | 13 ++- src/overlays/shared/enemies/frog.c | 47 ++++------- src/overlays/shared/enemies/gadgebot.c | 45 ++++------ .../shared/enemies/gadgebot_spawn_container.c | 14 ++-- .../shared/enemies/ground_melee_enemy.c | 33 ++++---- src/overlays/shared/enemies/horny_toad.c | 10 +-- src/overlays/shared/enemies/large_amoeboid.c | 49 ++++------- .../shared/enemies/paratrooper_fire_bolt.c | 12 ++- .../shared/enemies/path_or_ballistic_debris.c | 12 ++- src/overlays/shared/enemies/plasmabot.c | 43 ++++------ src/overlays/shared/enemies/plasmabot_hatch.c | 26 +++--- src/overlays/shared/enemies/sand_mouse.c | 26 +++--- src/overlays/shared/enemies/sandmouse.c | 24 +++--- src/overlays/shared/enemies/scoutbot.c | 27 +++--- src/overlays/shared/enemies/seeker.c | 27 +++--- src/overlays/shared/enemies/sentrybot.c | 72 +++++++--------- .../shared/enemies/sentrybot_projectile.c | 10 +-- src/overlays/shared/enemies/spawner.c | 14 ++-- .../initialize_level_transition_with_audio.c | 2 + src/overlays/shared/hero/hero_frame_update.c | 32 +++---- src/overlays/shared/hero/hero_idle_sequence.c | 2 +- src/overlays/shared/hero/hero_switch_item.c | 15 ++-- .../shared/hero/hero_update_movement.c | 79 ++++++++++++------ src/overlays/shared/pickups/bolt.c | 28 ++----- src/overlays/shared/pickups/crate.c | 25 +++--- src/overlays/shared/pickups/crate_fragment.c | 12 ++- .../shared/pickups/fighter_jet_crate.c | 22 +++-- src/overlays/shared/pickups/gold_bolt.c | 17 ++-- src/overlays/shared/pickups/nanotech_ball.c | 21 ++--- src/overlays/shared/pickups/weapon_ammo.c | 21 ++--- src/overlays/shared/props/hydrodisplacer.c | 20 ++--- src/overlays/shared/props/teleporter.c | 24 +++--- .../rendering/debug/update_debug_menu.c | 16 ++-- .../rendering/effects/timed_sprite_effect.c | 12 ++- .../streaming/load_scene_chunks_with_fade.c | 10 +-- .../shared/ui/menus/initialize_pause_menu.c | 35 ++++---- .../vehicles/giant_clank_charged_blast.c | 10 +-- src/overlays/shared/vehicles/veldin_ship.c | 14 ++-- .../shared/vendor/initialize_vendor_screen.c | 2 + src/overlays/shared/vendor/vendor_menu.c | 42 ++++------ src/overlays/shared/weapons/bomb_glove_bomb.c | 12 ++- src/overlays/shared/weapons/decoy.c | 36 +++----- .../shared/weapons/doom_bot_movement.c | 10 +-- .../shared/weapons/glove_of_doom_bomb.c | 24 +++--- src/overlays/shared/weapons/mine.c | 19 ++--- .../shared/weapons/morphoray_chicken.c | 29 ++----- src/overlays/shared/weapons/pyrocitor.c | 18 ++-- src/overlays/shared/weapons/swingshot_hook.c | 24 +++--- .../shared/weapons/thruster_pack_flame.c | 18 ++-- .../lights/update_all_point_lights.c | 3 +- src/ui/help/draw_help.c | 10 ++- src/ui/help/help_draw_prompt.c | 3 +- 163 files changed, 1955 insertions(+), 2332 deletions(-) diff --git a/src/camera/camera_activation_check_priority.c b/src/camera/camera_activation_check_priority.c index 61e213db4f..c957200651 100644 --- a/src/camera/camera_activation_check_priority.c +++ b/src/camera/camera_activation_check_priority.c @@ -93,7 +93,8 @@ int camera_activation_check_priority(struct UpdateCam *candidate, struct UpdateC if (listener_group != hero_state->unk2284) { return 0; } - if (current->transition_state == CAMERA_TRANSITION_PRIORITY_GATED && !(activation->priority > current->active)) { + if (current->transition_state == CAMERA_TRANSITION_PRIORITY_GATED && + !(activation->priority > current->active)) { return 0; } if (listener_group != 3) { diff --git a/src/camera/start_camera_blend.c b/src/camera/start_camera_blend.c index 42e1e79a06..b361de0c31 100644 --- a/src/camera/start_camera_blend.c +++ b/src/camera/start_camera_blend.c @@ -39,8 +39,10 @@ void start_camera_blend(struct UpdateCam *source) { } else { struct Hero *orbit_reference_hero = &hero; - fast_vec_normalize(orbit_reference_direction, &orbit_reference_hero->moby->rot_row0, 1.0f); - fast_vec_normalize(orbit_yaw_side_direction, &orbit_reference_hero->moby->rot_row1, 1.0f); + fast_vec_normalize( + orbit_reference_direction, &orbit_reference_hero->moby->rot_row0, 1.0f); + fast_vec_normalize( + orbit_yaw_side_direction, &orbit_reference_hero->moby->rot_row1, 1.0f); fast_vec_normalize(orbit_axis, &orbit_reference_hero->moby->rot_row2, 1.0f); /* PreviewCamera.current_camera, reached from this base. */ compute_camera_angles(transition->orbit.angles, diff --git a/src/mobys/update_instance_attachment_points_and_lengths.c b/src/mobys/update_instance_attachment_points_and_lengths.c index e8ff214b69..b3275c7e6b 100644 --- a/src/mobys/update_instance_attachment_points_and_lengths.c +++ b/src/mobys/update_instance_attachment_points_and_lengths.c @@ -26,7 +26,8 @@ void update_instance_attachment_points_and_lengths(struct Moby *instance) { *(struct Pair64 *)(offsets + 0x20) = *(struct Pair64 *)attachment_point_indices; transform_scaled_vertex_batch(instance, 4, offsets + 0x20, attachment_points_and_lengths); fast_vec_sub(offsets, attachment_points_and_lengths->points[1], attachment_points_and_lengths); - fast_vec_sub(offsets + 0x10, attachment_points_and_lengths->points[2], attachment_points_and_lengths); + fast_vec_sub( + offsets + 0x10, attachment_points_and_lengths->points[2], attachment_points_and_lengths); attachment_points_and_lengths->first_length = fast_vec_length(offsets); attachment_points_and_lengths->second_length = fast_vec_length(offsets + 0x10); } diff --git a/src/overlays/l00/mobys/veldin_robot_enemy.c b/src/overlays/l00/mobys/veldin_robot_enemy.c index c400c345ff..7c3ae43a65 100644 --- a/src/overlays/l00/mobys/veldin_robot_enemy.c +++ b/src/overlays/l00/mobys/veldin_robot_enemy.c @@ -25,6 +25,18 @@ #include "rnc/overlay/shared/world/collision.h" #include "rnc/overlay/l00/mobys/veldin_robot_enemy_globals.h" +enum { + VELDIN_ROBOT_STATE_INITIALIZE = 0, + VELDIN_ROBOT_STATE_WAIT_TO_FOLLOW_PATH = 1, + VELDIN_ROBOT_STATE_FOLLOW_PATH = 2, + VELDIN_ROBOT_STATE_FACE_TARGET = 3, + VELDIN_ROBOT_STATE_WAIT_TO_START_COLLISION_PROBES = 4, + VELDIN_ROBOT_STATE_PROCESS_COLLISION_PROBES = 5, + VELDIN_ROBOT_STATE_WAIT_TO_RETURN_TO_FACE_TARGET = 6, + VELDIN_ROBOT_STATE_DAMAGE_KNOCKBACK = 7, + VELDIN_ROBOT_STATE_DEATH_KNOCKBACK = 8 +}; + typedef union { u128 q; f32 f[4]; @@ -170,17 +182,6 @@ void veldin_robot_enemy_update(ElectroidMoby *moby) __asm__("FUN_L00_002e0 /* Moby class 1440 */ void veldin_robot_enemy_update(ElectroidMoby *moby) { - enum { - VELDIN_ROBOT_STATE_INITIALIZE = 0, - VELDIN_ROBOT_STATE_WAIT_TO_FOLLOW_PATH = 1, - VELDIN_ROBOT_STATE_FOLLOW_PATH = 2, - VELDIN_ROBOT_STATE_FACE_TARGET = 3, - VELDIN_ROBOT_STATE_WAIT_TO_START_COLLISION_PROBES = 4, - VELDIN_ROBOT_STATE_PROCESS_COLLISION_PROBES = 5, - VELDIN_ROBOT_STATE_WAIT_TO_RETURN_TO_FACE_TARGET = 6, - VELDIN_ROBOT_STATE_DAMAGE_KNOCKBACK = 7, - VELDIN_ROBOT_STATE_DEATH_KNOCKBACK = 8 - }; ElectroidVars *vars; ElectroidMoby *target; Path *path; @@ -436,13 +437,6 @@ f32 veldin_robot_knockback_xy_scale_gp __asm__("D_L00_00161BDC") = 1e+01 f32 veldin_robot_knockback_z_scale_gp __asm__("D_L00_00161BE0") = 9.5f; void update_veldin_robot_damage_and_targeting(ElectroidMoby *moby) { - enum { - VELDIN_ROBOT_STATE_INITIALIZE = 0, - VELDIN_ROBOT_STATE_WAIT_TO_FOLLOW_PATH = 1, - VELDIN_ROBOT_STATE_PROCESS_COLLISION_PROBES = 5, - VELDIN_ROBOT_STATE_DAMAGE_KNOCKBACK = 7, - VELDIN_ROBOT_STATE_DEATH_KNOCKBACK = 8 - }; ElectroidVars *vars; void *anim; ElectroidHit *coll; diff --git a/src/overlays/l01/hero/hero_set_state.c b/src/overlays/l01/hero/hero_set_state.c index 89788d99bb..d4b383aeb7 100644 --- a/src/overlays/l01/hero/hero_set_state.c +++ b/src/overlays/l01/hero/hero_set_state.c @@ -75,7 +75,8 @@ int l01_hero_set_state(int requested_state, int animation_setup_mode) { { struct Hero *p = &hero; if (p->state.control_mode == 0x14 && - (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || animation_setup_mode != 2)) + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || + animation_setup_mode != 2)) return 0; } if ((cutscene_mode == 2 || cutscene_mode == 6) && animation_setup_mode != 2) diff --git a/src/overlays/l01/hero/update_hero_motion_for_current_state.c b/src/overlays/l01/hero/update_hero_motion_for_current_state.c index 72c6280bea..eafef45818 100644 --- a/src/overlays/l01/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l01/hero/update_hero_motion_for_current_state.c @@ -607,8 +607,8 @@ void update_hero_motion_for_current_state(void) { clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { add_hero_gravity_offset(hero.motion.velocity.f, - hero.motion.resolved_velocity_z.f, - frame_time_sq * 25.0f); + hero.motion.resolved_velocity_z.f, + frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { add_hero_gravity_offset( @@ -1141,7 +1141,8 @@ void update_hero_motion_for_current_state(void) { hero.motion.velocity.f, hero.motion.displacement.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } if (anim != -1 && hero.moby->seq != 0x36) { set_hero_animation(anim, 0, frames); @@ -1338,7 +1339,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_WRENCH_COMBO: { @@ -1441,7 +1443,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); } break; @@ -1565,7 +1568,8 @@ void update_hero_motion_for_current_state(void) { hero.motion.velocity.f, hero.motion.resolved_velocity.f, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_ANIMATION_RECOVERY_WITH_JUMP_CANCEL: @@ -1690,7 +1694,8 @@ void update_hero_motion_for_current_state(void) { hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_VOICE_SLOT_CLEANUP_IDLE_EXIT: @@ -1853,7 +1858,8 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); if (FUN_L00_00233a78(hero.motion.velocity.f) < -(frame_time * 50.0f)) { FUN_L00_00233b20(hero.motion.velocity.f, hero.motion.velocity.f, -(frame_time * 50.0f)); } @@ -1873,7 +1879,8 @@ void update_hero_motion_for_current_state(void) { hero.motion.velocity.f, hero.motion.velocity.f); } - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); if (FUN_L00_00233a78(hero.motion.velocity.f) < -(frame_time * 50.0f)) { FUN_L00_00233b20(hero.motion.velocity.f, hero.motion.velocity.f, -(frame_time * 50.0f)); } @@ -2221,7 +2228,8 @@ void update_hero_motion_for_current_state(void) { hero.motion.velocity.f, hero.motion.displacement.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_BRAKE_AT_TARGET_POSITION: { @@ -2237,7 +2245,8 @@ void update_hero_motion_for_current_state(void) { hero.motion.velocity.f, hero.motion.displacement.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_FIDGET: @@ -2259,7 +2268,8 @@ void update_hero_motion_for_current_state(void) { hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -2274,7 +2284,8 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { update_hero_airborne_planar_motion(); } - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 21.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2308,7 +2319,8 @@ void update_hero_motion_for_current_state(void) { hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_VEHICLE_MODE_3_HURT: { diff --git a/src/overlays/l01/mobys/pool_bubbles.c b/src/overlays/l01/mobys/pool_bubbles.c index aa1d433e5b..f0300d27e4 100644 --- a/src/overlays/l01/mobys/pool_bubbles.c +++ b/src/overlays/l01/mobys/pool_bubbles.c @@ -9,6 +9,10 @@ #include "rnc/math/random.h" #include "rnc/overlay/shared/rendering/effects/create_part.h" +enum { + POOL_BUBBLE_PARTICLE_KIND = 0x48 +}; + typedef struct { u128 pos; f32 size; @@ -34,9 +38,6 @@ extern u8 *pool_bubble_texture_table[] __asm__("D_L01_001B25E0"); Particle *pool_bubble(u128 *pos, u128 *vel, f32 f) __asm__("FUN_L01_00287b00"); Particle *pool_bubble(u128 *pos, u128 *motion_position_source, f32 scale) { - enum { - POOL_BUBBLE_PARTICLE_KIND = 0x48 - }; Particle *particle; s32 gray_channel; u32 col; @@ -63,9 +64,6 @@ extern u8 *pool_bubbles_texture_table[] __asm__("D_L01_001B25E4"); Particle *pool_bubbles(u128 *pos, u128 *dir, f32 scale, f32 speed) __asm__("FUN_L01_00287c80"); Particle *pool_bubbles(u128 *pos, u128 *motion_position_source, f32 scale, f32 speed) { - enum { - POOL_BUBBLE_PARTICLE_KIND = 0x48 - }; Particle *particle; PartMotion *m; f32 random_spin; diff --git a/src/overlays/l02/hero/hero_set_state.c b/src/overlays/l02/hero/hero_set_state.c index 2c3ad4aaec..164deeda39 100644 --- a/src/overlays/l02/hero/hero_set_state.c +++ b/src/overlays/l02/hero/hero_set_state.c @@ -76,7 +76,8 @@ int hero_set_state(int requested_state, int entry_animation_mode) { { struct Hero *p = &hero; if (p->state.control_mode == 0x14 && - (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || entry_animation_mode != 2)) + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || + entry_animation_mode != 2)) return 0; } if ((level_game_mode == 2 || level_game_mode == 6) && entry_animation_mode != 2) diff --git a/src/overlays/l02/hero/update_hero_state_motion.c b/src/overlays/l02/hero/update_hero_state_motion.c index 8e347c628c..e05f6a0b72 100644 --- a/src/overlays/l02/hero/update_hero_state_motion.c +++ b/src/overlays/l02/hero/update_hero_state_motion.c @@ -35,13 +35,6 @@ extern int hero_set_state(int, int) __asm__("FUN_L02_0022b728"); void process_hero_ground_material_effects(void) __asm__("FUN_L02_0021b698"); void process_hero_ground_material_effects(void) { - enum { - GROUND_MATERIAL_MAGNETIC = 2, - GROUND_MATERIAL_SINK_TRIGGER = 0xD - }; - enum { - GROUND_MATERIAL_SINK_SURFACE_TRIGGER = 3 - }; struct Hero *hero_state = &hero; int keep = hero_state->ground_sound_class; int saved_ground_type = hero_state->ground_type; @@ -153,6 +146,16 @@ void process_hero_ground_material_effects(void) { } #include "qcopy.h" + +enum { + GROUND_MATERIAL_MAGNETIC = 2, + GROUND_MATERIAL_SINK_TRIGGER = 0xD +}; + +enum { + GROUND_MATERIAL_WATER_SURFACE_TRIGGER = 0, + GROUND_MATERIAL_SINK_SURFACE_TRIGGER = 3 +}; #define G hero /* Same source as the exact FUN_L08_00222800, with only the 0x16 animation in mode 0 and no 0xF exit. */ @@ -339,13 +342,6 @@ extern CollisionHit HH __asm__("D_L02_00174440") NOT_SDA; void update_hero_ground_contact(void) __asm__("FUN_L02_002216a0"); void update_hero_ground_contact(void) { - enum { - GROUND_MATERIAL_SINK_TRIGGER = 0xD - }; - enum { - GROUND_MATERIAL_WATER_SURFACE_TRIGGER = 0, - GROUND_MATERIAL_SINK_SURFACE_TRIGGER = 3 - }; V collision_ray_end, collision_ray_start, ground_geometry_scratch, probe_ray_start, unused_probe_point, probe_surface_angles, normalized_probe_hit_normal; f32 f; @@ -932,8 +928,8 @@ void update_hero_state_motion(void) { clip_hero_horizontal_velocity(0); if (hero.air_frames.s != 0) { add_hero_gravity_offset(hero.motion.velocity.f, - hero.motion.resolved_velocity_z.f, - frame_time_sq * 25.0f); + hero.motion.resolved_velocity_z.f, + frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { add_hero_gravity_offset( @@ -1005,7 +1001,8 @@ void update_hero_state_motion(void) { hero.motion.velocity.f, hero.motion.displacement.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } if (anim != -1 && hero.moby->seq != 0x36) { set_hero_animation(anim, 0, frames); @@ -1025,7 +1022,8 @@ void update_hero_state_motion(void) { hero.motion.velocity.f, hero.motion.resolved_velocity.f, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } if (hero.grapple_target != 0) { hero.motion.move_yaw = fast_arc_tan(hero.grapple_target->pos.x - moby->pos.x, @@ -1507,7 +1505,8 @@ void update_hero_state_motion(void) { add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_WRENCH_COMBO: { @@ -1610,7 +1609,8 @@ void update_hero_state_motion(void) { add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); } break; @@ -1734,7 +1734,8 @@ void update_hero_state_motion(void) { hero.motion.velocity.f, hero.motion.resolved_velocity.f, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_ANIMATION_RECOVERY_WITH_JUMP_CANCEL: @@ -1795,7 +1796,8 @@ void update_hero_state_motion(void) { add_hero_gravity_offset( hero.motion.velocity.f, hero.motion.resolved_velocity.f, frame_time_sq * 24.0f); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_RUN: @@ -1889,7 +1891,8 @@ void update_hero_state_motion(void) { hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_LEDGE_HANG_ENTRY: @@ -2007,7 +2010,8 @@ void update_hero_state_motion(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); if (gravity_z(hero.motion.velocity.f) < -(frame_time * 50.0f)) { gravity_set_z(hero.motion.velocity.f, hero.motion.velocity.f, -(frame_time * 50.0f)); } @@ -2028,7 +2032,8 @@ void update_hero_state_motion(void) { hero.motion.velocity.f, hero.motion.velocity.f); } - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, hero.fall_state_gravity); if (gravity_z(hero.motion.velocity.f) < -(frame_time * 50.0f)) { gravity_set_z(hero.motion.velocity.f, hero.motion.velocity.f, -(frame_time * 50.0f)); } @@ -2349,7 +2354,8 @@ void update_hero_state_motion(void) { hero.motion.velocity.f, hero.motion.displacement.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_BRAKE_AT_TARGET_POSITION: { @@ -2365,7 +2371,8 @@ void update_hero_state_motion(void) { hero.motion.velocity.f, hero.motion.displacement.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_FIDGET: @@ -2398,7 +2405,8 @@ void update_hero_state_motion(void) { hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -2413,7 +2421,8 @@ void update_hero_state_motion(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 21.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2447,7 +2456,8 @@ void update_hero_state_motion(void) { hero.motion.velocity.f, hero.motion.resolved_velocity_z.f, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); + add_hero_gravity_offset( + hero.motion.velocity.f, hero.motion.velocity.f, frame_time_sq * 54.0f); } } break; case HERO_STATE_VEHICLE_MODE_3_HURT: { diff --git a/src/overlays/l02/mobys/sand_shark.c b/src/overlays/l02/mobys/sand_shark.c index bc4b8be230..02bfcdc0c2 100644 --- a/src/overlays/l02/mobys/sand_shark.c +++ b/src/overlays/l02/mobys/sand_shark.c @@ -262,33 +262,6 @@ void sand_shark_update(struct Moby *moby) __asm__("FUN_L02_002d3e50"); /* Moby class 580 */ void sand_shark_update(struct Moby *moby) { - enum { - SAND_SHARK_INITIALIZE = 0, - SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET = 1, - SAND_SHARK_WANDER_AROUND_HOME = 2, - SAND_SHARK_WAIT_FOR_TARGET_IN_VOLUME = 3, - SAND_SHARK_APPROACH_TARGET = 5, - SAND_SHARK_CLOSE_RANGE_ATTACK = 6, - SAND_SHARK_RETURN_HOME = 7, - SAND_SHARK_KNOCKBACK_UNTIL_LANDING = 8, - SAND_SHARK_SUCK_CANNON_INTERACTION = 9, - SAND_SHARK_WAIT_FOR_HERO_LAUNCH_TRIGGER = 12, - SAND_SHARK_BALLISTIC_FLIGHT = 13, - SAND_SHARK_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK = 14, - SAND_SHARK_FACE_TARGET = 15, - SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_HEIGHT_OFFSET = 17, - SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET = 18, - SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET = 19, - SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME = 20, - SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK = 21, - SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET = 22, - SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET = 23, - SAND_SHARK_DEATH_KNOCKBACK = 24, - SAND_SHARK_FADE_OUT = 25, - SAND_SHARK_INACTIVE_WAIT_FOR_RELAUNCH = 26, - SAND_SHARK_BALLISTIC_FLIGHT_WITH_PARTICLES = 27, - SAND_SHARK_WAIT_FOR_LINKED_MOBY_BEFORE_INITIALIZE = 29 - }; enum { SAND_SHARK_LANDED_AFTER_KNOCKBACK = 0xB }; @@ -1234,6 +1207,34 @@ typedef struct { #include "rnc/overlay/l02/mobys/sand_shark_data/handle_sand_shark_damage_and_targeting.h" +enum { + SAND_SHARK_INITIALIZE = 0, + SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET = 1, + SAND_SHARK_WANDER_AROUND_HOME = 2, + SAND_SHARK_WAIT_FOR_TARGET_IN_VOLUME = 3, + SAND_SHARK_APPROACH_TARGET = 5, + SAND_SHARK_CLOSE_RANGE_ATTACK = 6, + SAND_SHARK_RETURN_HOME = 7, + SAND_SHARK_KNOCKBACK_UNTIL_LANDING = 8, + SAND_SHARK_SUCK_CANNON_INTERACTION = 9, + SAND_SHARK_WAIT_FOR_HERO_LAUNCH_TRIGGER = 12, + SAND_SHARK_BALLISTIC_FLIGHT = 13, + SAND_SHARK_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK = 14, + SAND_SHARK_FACE_TARGET = 15, + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_HEIGHT_OFFSET = 17, + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET = 18, + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET = 19, + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME = 20, + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK = 21, + SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET = 22, + SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET = 23, + SAND_SHARK_DEATH_KNOCKBACK = 24, + SAND_SHARK_FADE_OUT = 25, + SAND_SHARK_INACTIVE_WAIT_FOR_RELAUNCH = 26, + SAND_SHARK_BALLISTIC_FLIGHT_WITH_PARTICLES = 27, + SAND_SHARK_WAIT_FOR_LINKED_MOBY_BEFORE_INITIALIZE = 29 +}; + extern int *D_L02_001B0AB0_5c88[] __asm__("D_L02_001B0AB0"); extern void trooper_knockback_arc(void *, float *, void *, void *) __asm__("FUN_L00_0025ab48"); extern int FUN_L00_0025ff38(float, void *, void *, int, int, void *, int); @@ -1357,10 +1358,6 @@ extern void *store_moby_in_suck_cannon(void *) __asm__("FUN_L00_002dbb20"); void *handle_sand_shark_suck_cannon_storage(struct Moby *moby) __asm__("FUN_L02_002d6210"); void *handle_sand_shark_suck_cannon_storage(struct Moby *moby) { - enum { - SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET = 1, - SAND_SHARK_SUCK_CANNON_INTERACTION = 9 - }; void *helper_result = store_moby_in_suck_cannon(moby); if (helper_result) { int spawner_moby_index; @@ -1382,9 +1379,6 @@ void *handle_sand_shark_suck_cannon_storage(struct Moby *moby) { void prepare_sand_shark_for_relaunch_or_remove(struct Moby *moby) __asm__("FUN_L02_002d6340"); void prepare_sand_shark_for_relaunch_or_remove(struct Moby *moby) { - enum { - SAND_SHARK_INACTIVE_WAIT_FOR_RELAUNCH = 0x1A - }; char *sand_shark_private_vars = (char *)moby->pvars; int selected_class_29c_moby = select_group_class_29c_moby(moby); *(int *)(sand_shark_private_vars + 0x27C) = selected_class_29c_moby; @@ -1408,9 +1402,6 @@ extern int point_in_path_xy(void *, void *, int) __asm__("FUN_L00_00259740"); void begin_sand_shark_return_home_if_outside_path(struct Moby *moby) __asm__("FUN_L02_002d63c0"); void begin_sand_shark_return_home_if_outside_path(struct Moby *moby) { - enum { - SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET = 0x12 - }; char *sand_shark_instance_vars = (char *)moby->pvars; char *configured_path = D_L02_001B0AB0[*(int *)(sand_shark_instance_vars + 0x290)]; if (point_in_path_xy(&moby->pos, configured_path + 0x10, *(int *)configured_path) == 0) { diff --git a/src/overlays/l02/mobys/sand_shark_nest.c b/src/overlays/l02/mobys/sand_shark_nest.c index 30ab9a6f65..2e147c353d 100644 --- a/src/overlays/l02/mobys/sand_shark_nest.c +++ b/src/overlays/l02/mobys/sand_shark_nest.c @@ -26,6 +26,14 @@ extern void trooper_anim_finish(void *, void *) __asm__("FUN_L00_0025d538"); #include "qcopy.h" +enum { + SAND_SHARK_NEST_INITIALIZE = 0, + SAND_SHARK_NEST_WAIT_FOR_SPAWN = 1, + SAND_SHARK_NEST_LAUNCH_SAND_SHARK = 2, + SAND_SHARK_NEST_HIT_RECOVERY = 3, + SAND_SHARK_NEST_DEATH_KNOCKBACK = 4 +}; + /* Ported from rac1-decomp (src/overlays/l02_aridia/vendor_002A59D8.c: func_L02_002D7550), where it is exact; names translated to the US level program. */ void launch_sand_shark(struct Moby *moby, @@ -144,13 +152,6 @@ void sand_shark_nest_update(unsigned char *moby) __asm__("FUN_L02_002dcb38"); /* Moby class 668 */ void sand_shark_nest_update(unsigned char *moby) { - enum { - SAND_SHARK_NEST_INITIALIZE = 0, - SAND_SHARK_NEST_WAIT_FOR_SPAWN = 1, - SAND_SHARK_NEST_LAUNCH_SAND_SHARK = 2, - SAND_SHARK_NEST_HIT_RECOVERY = 3, - SAND_SHARK_NEST_DEATH_KNOCKBACK = 4 - }; Varscb38 *nest_vars = ((Varscb38 *)MOBY(moby)->pvars); char *launched_shark; int spawn_delay_factor; @@ -310,10 +311,6 @@ extern int hit_reaction(void *, void *, void *, int, int *, float *, int, int) __asm__("FUN_L00_0025a478"); void handle_sand_shark_nest_damage(struct Moby *moby) { - enum { - SAND_SHARK_NEST_HIT_RECOVERY = 3, - SAND_SHARK_NEST_DEATH_KNOCKBACK = 4 - }; char *nest_vars = (char *)moby->pvars; float hit_knockback_vector[4]; int hit; diff --git a/src/overlays/l03/hero/hero_set_state.c b/src/overlays/l03/hero/hero_set_state.c index a5de3e4d27..3c3faba792 100644 --- a/src/overlays/l03/hero/hero_set_state.c +++ b/src/overlays/l03/hero/hero_set_state.c @@ -75,7 +75,8 @@ int hero_set_state(int requested_state, int entry_animation_mode) { { struct Hero *p = &hero; if (p->state.control_mode == 0x14 && - (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || entry_animation_mode != 2)) + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || + entry_animation_mode != 2)) return 0; } if ((D_L03_0015F5C4 == 2 || D_L03_0015F5C4 == 6) && entry_animation_mode != 2) diff --git a/src/overlays/l03/hero/update_hero_motion_for_current_state.c b/src/overlays/l03/hero/update_hero_motion_for_current_state.c index 3c637cbd8a..a497c13e25 100644 --- a/src/overlays/l03/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l03/hero/update_hero_motion_for_current_state.c @@ -937,7 +937,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && MV(hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -959,7 +960,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (MV(hero.grapple_target) != NULL) { hero.motion.move_yaw = @@ -1250,7 +1252,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1335,7 +1338,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1400,7 +1404,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1497,7 +1502,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1615,7 +1621,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1730,7 +1737,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2003,7 +2011,8 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2020,7 +2029,8 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2352,7 +2362,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2369,7 +2380,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2391,7 +2403,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -2406,7 +2419,8 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2439,7 +2453,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } diff --git a/src/overlays/l03/mobys/kerwan_path_enemy.c b/src/overlays/l03/mobys/kerwan_path_enemy.c index 37d5e0d737..39d12b1695 100644 --- a/src/overlays/l03/mobys/kerwan_path_enemy.c +++ b/src/overlays/l03/mobys/kerwan_path_enemy.c @@ -43,9 +43,6 @@ int try_start_kerwan_path_enemy_heading_turn(float desired_heading, struct Moby *moby, struct Moby *target) { - enum { - ENEMY_TURN_TO_HEADING = 0xC - }; KerwanPathEnemyVars *enemy_pvars = (KerwanPathEnemyVars *)moby->pvars; int linked_moby_index; float heading_delta; @@ -365,9 +362,6 @@ void axis_angle_rotation_to_euler(AxisAngleQuad *axis, AxisAngleQuad *point, flo int is_kerwan_path_enemy_in_state_9(struct Moby *moby) __asm__("FUN_L03_002c6d58"); int is_kerwan_path_enemy_in_state_9(struct Moby *moby) { - enum { - ENEMY_FOLLOW_ALTERNATE_PATH = 0x9 - }; if (moby && moby->state != 0xFE && moby->state != 0xFD && moby->oclass == 0x23e && moby->state == ENEMY_FOLLOW_ALTERNATE_PATH) { return 1; @@ -379,23 +373,6 @@ void kerwan_path_enemy_update(Moby2C8398 *m) __asm__("FUN_L03_002c6fd0"); /* Moby class 574 */ void kerwan_path_enemy_update(Moby2C8398 *m) { - enum { - ENEMY_INITIALIZE = 0, - ENEMY_WAIT_FOR_ACTIVATION = 1, - ENEMY_WAIT_FOR_LINKED_MOBY = 2, - ENEMY_PROJECTILE_ATTACK_WINDUP = 4, - ENEMY_PROJECTILE_ATTACK = 5, - ENEMY_MELEE_ATTACK = 6, - ENEMY_MOVE_TO_PATH_NODE = 7, - ENEMY_FOLLOW_PATH_TO_END = 8, - ENEMY_FOLLOW_ALTERNATE_PATH = 9, - ENEMY_KNOCKBACK_RECOVERY = 10, - ENEMY_FALL_UNDER_GRAVITY = 11, - ENEMY_TURN_TO_HEADING = 12, - ENEMY_DEATH_KNOCKBACK = 13, - ENEMY_HIDDEN_AT_PATH_START = 14, - ENEMY_RESPAWN_AT_PATH_START = 15 - }; enum { ENEMY_ANIM_LOCOMOTION = 1, ENEMY_ANIM_HEADING_TURN = 9 @@ -1472,6 +1449,24 @@ extern float D_L03_001618E0 __attribute__((sda)); #include "rnc/overlay/l03/mobys/kerwan_path_enemy_data/update_kerwan_path_enemy_hit_reaction.h" +enum { + ENEMY_INITIALIZE = 0, + ENEMY_WAIT_FOR_ACTIVATION = 1, + ENEMY_WAIT_FOR_LINKED_MOBY = 2, + ENEMY_PROJECTILE_ATTACK_WINDUP = 4, + ENEMY_PROJECTILE_ATTACK = 5, + ENEMY_MELEE_ATTACK = 6, + ENEMY_MOVE_TO_PATH_NODE = 7, + ENEMY_FOLLOW_PATH_TO_END = 8, + ENEMY_FOLLOW_ALTERNATE_PATH = 0x9, + ENEMY_KNOCKBACK_RECOVERY = 10, + ENEMY_FALL_UNDER_GRAVITY = 11, + ENEMY_TURN_TO_HEADING = 0xC, + ENEMY_DEATH_KNOCKBACK = 13, + ENEMY_HIDDEN_AT_PATH_START = 14, + ENEMY_RESPAWN_AT_PATH_START = 15 +}; + extern int resolve_moby_hit_response(void *, void *, void *, int, int *, float *, int, int) __asm__("FUN_00213928"); extern void set_moby_animation(void *, int, int) __asm__("FUN_00212ed8"); @@ -1495,10 +1490,6 @@ void update_kerwan_path_enemy_hit_reaction(Moby2C8398 *moby) { NO_KNOCKBACK_HIT_RESPONSE = 12, ZERO_DAMAGE_NO_KNOCKBACK_RESPONSE = 13 }; - enum { - ENEMY_KNOCKBACK_RECOVERY = 10, - ENEMY_DEATH_KNOCKBACK = 0xD - }; enum { HIT_REACTION_SUPPRESSED = 1 }; diff --git a/src/overlays/l03/mobys/mine_layer.c b/src/overlays/l03/mobys/mine_layer.c index 78fbf567ca..0086ee70bb 100644 --- a/src/overlays/l03/mobys/mine_layer.c +++ b/src/overlays/l03/mobys/mine_layer.c @@ -124,14 +124,6 @@ void mine_layer_update(struct Moby *m) __asm__("FUN_L03_002c9eb8"); /* Moby class 578 */ void mine_layer_update(struct Moby *mine_layer_moby) { - enum { - MINE_LAYER_INITIALIZE = 0, - MINE_LAYER_FACE_TARGET_AND_WAIT_FOR_RANGE = 1, - MINE_LAYER_WAIT_FOR_ANIMATION_BEFORE_PATROL = 2, - MINE_LAYER_PATROL_AND_FIRE = 3, - MINE_LAYER_KNOCKBACK_AND_RECOVER = 4, - MINE_LAYER_KNOCKBACK_UNTIL_EXPLOSION = 5 - }; TrooperVars *mine_layer_vars = (TrooperVars *)mine_layer_moby->pvars; TrooperPatrol *pt; LevelPath *path; @@ -376,6 +368,15 @@ extern f32 mine_layer_nonlethal_knockback_speed_scale_gp __asm__("D_L03_001618FC #include "rnc/overlay/l03/mobys/mine_layer_data/handle_mine_layer_damage.h" +enum { + MINE_LAYER_INITIALIZE = 0, + MINE_LAYER_FACE_TARGET_AND_WAIT_FOR_RANGE = 1, + MINE_LAYER_WAIT_FOR_ANIMATION_BEFORE_PATROL = 2, + MINE_LAYER_PATROL_AND_FIRE = 3, + MINE_LAYER_KNOCKBACK_AND_RECOVER = 4, + MINE_LAYER_KNOCKBACK_UNTIL_EXPLOSION = 5 +}; + extern TrooperHit *trooper_find_hit(struct Moby *, s32, s32) __asm__("FUN_L00_0025a420"); extern s32 resolve_moby_hit_response( struct Moby *, TrooperHit *, f32 *, s32, s32 *, f32 *, s32, s32) __asm__("FUN_00213928"); @@ -396,10 +397,6 @@ void handle_mine_layer_damage(struct Moby *damaged_moby) { TROOPER_DAMAGE_LONG_KNOCKBACK_ALTERNATE = 5, TROOPER_DAMAGE_SHORT_KNOCKBACK_ALTERNATE = 6 }; - enum { - MINE_LAYER_KNOCKBACK_AND_RECOVER = 4, - MINE_LAYER_KNOCKBACK_UNTIL_EXPLOSION = 5 - }; TrooperVars *trooper_vars = (TrooperVars *)damaged_moby->pvars; TrooperHit *hit_record; Vec4 at; diff --git a/src/overlays/l03/mobys/red_ship_1.c b/src/overlays/l03/mobys/red_ship_1.c index 304a5309fb..baa3f38caf 100644 --- a/src/overlays/l03/mobys/red_ship_1.c +++ b/src/overlays/l03/mobys/red_ship_1.c @@ -24,6 +24,13 @@ #include "rnc/audio/voice_pool.h" #include "rnc/game/item_state.h" +enum { + RED_SHIP_INITIALIZE = 0, + RED_SHIP_FOLLOW_PATH_SPLINE = 1, + RED_SHIP_WAIT_FOR_PATH = 2, + RED_SHIP_WAIT_FOR_MOVEMENT_TIMER = 3 +}; + /* Ported from rac1-decomp (src/overlays/l03_kerwan/vendor_00293720.c: func_L03_0029DB88), where it is exact; names translated to the US level program. */ extern int D_L03_0015F5CC; /* no foreign declaration */ @@ -61,9 +68,6 @@ void add_moby_rotation_based_offsets(struct Moby *moby, float *position) { void maintain_emitter_sound_voice(struct Moby *moby) __asm__("FUN_L03_0029c9d0"); void maintain_emitter_sound_voice(struct Moby *moby) { - enum { - RED_SHIP_INITIALIZE = 0 - }; char *emitter_pvars = (char *)moby->pvars; if (moby->state == RED_SHIP_INITIALIZE) { *(int *)(emitter_pvars + 0x150) = -1; @@ -545,12 +549,6 @@ typedef struct RedShip1Vars { * steering, banking and spawning its hit/smoke effects; state 2 waits without a path, 3 waits a timer. */ /* Moby classes 75, 115-120, 132, 795 */ void red_ship_1_update(char *moby) { - enum { - RED_SHIP_INITIALIZE = 0, - RED_SHIP_FOLLOW_PATH_SPLINE = 1, - RED_SHIP_WAIT_FOR_PATH = 2, - RED_SHIP_WAIT_FOR_MOVEMENT_TIMER = 3 - }; float zero[4]; float old_rot[4]; float old_pos[4]; diff --git a/src/overlays/l03/mobys/robot_dog.c b/src/overlays/l03/mobys/robot_dog.c index d7030172bc..26e1648daf 100644 --- a/src/overlays/l03/mobys/robot_dog.c +++ b/src/overlays/l03/mobys/robot_dog.c @@ -17,17 +17,29 @@ #include "rnc/overlay/shared/world/level_path.h" #include "rnc/overlay/l03/mobys/robot_dog.h" +enum { + ROBOT_DOG_INITIALIZE = 0, + ROBOT_DOG_WAIT_FOR_ACTIVATION = 1, + ROBOT_DOG_WAIT_FOR_PARTNER_RELEASE = 2, + ROBOT_DOG_TURN_TO_TARGET = 3, + ROBOT_DOG_CHASE_TARGET = 4, + ROBOT_DOG_FOLLOW_PATH = 5, + ROBOT_DOG_MELEE_ATTACK = 6, + ROBOT_DOG_RETURN_HOME = 7, + ROBOT_DOG_FALL_RECOVERY = 8, + ROBOT_DOG_WAIT_TO_REINITIALIZE = 9, + ROBOT_DOG_DEATH_FALL = 21 +}; + +enum { + MOBY_STATE_PENDING_REMOVAL = 0xFE +}; + /* Ported from rac1-decomp (src/overlays/l03_kerwan/vendor_00293720.c: func_L03_002C6F40), where it is exact; names translated to the US level program. */ int is_robot_dog_in_state_5(struct Moby *moby) __asm__("FUN_L03_002c5b78"); int is_robot_dog_in_state_5(struct Moby *moby) { - enum { - ROBOT_DOG_FOLLOW_PATH = 5 - }; - enum { - MOBY_STATE_PENDING_REMOVAL = 0xFE - }; if (moby && moby->state != MOBY_STATE_PENDING_REMOVAL && moby->state != 0xFD && moby->oclass == 0x23D && moby->state == ROBOT_DOG_FOLLOW_PATH) { return 1; @@ -141,19 +153,6 @@ void robot_dog_update(char *moby) __asm__("FUN_L03_002c5bb8"); /* Moby class 573 */ void robot_dog_update(char *moby) { - enum { - ROBOT_DOG_INITIALIZE = 0, - ROBOT_DOG_WAIT_FOR_ACTIVATION = 1, - ROBOT_DOG_WAIT_FOR_PARTNER_RELEASE = 2, - ROBOT_DOG_TURN_TO_TARGET = 3, - ROBOT_DOG_CHASE_TARGET = 4, - ROBOT_DOG_FOLLOW_PATH = 5, - ROBOT_DOG_MELEE_ATTACK = 6, - ROBOT_DOG_RETURN_HOME = 7, - ROBOT_DOG_FALL_RECOVERY = 8, - ROBOT_DOG_WAIT_TO_REINITIALIZE = 9, - ROBOT_DOG_DEATH_FALL = 21 - }; Tgt2c5bb8 selected_target; float forward_vector_or_path_point[4]; float push[4]; @@ -494,9 +493,6 @@ extern void FUN_L01_0026e090(int, int); extern void trooper_set_knockback(float *, float, float) __asm__("FUN_L03_00250a78"); void update_robot_dog_hit_reaction(struct Moby *moby) { - enum { - ROBOT_DOG_DEATH_FALL = 21 - }; float vector[4]; int hit_reaction_code; float damage; @@ -550,9 +546,6 @@ void update_robot_dog_hit_reaction(struct Moby *moby) { /* Ported from rac1-decomp (src/overlays/l03_kerwan/vendor_00293720.c: func_L03_002C8068), where it is exact; names translated to the US level program. */ int can_release_linked_robot_dog(struct Moby *moby) { - enum { - MOBY_STATE_PENDING_REMOVAL = 0xFE - }; unsigned char state; char *partner_pvars; partner_pvars = (char *)moby->pvars; diff --git a/src/overlays/l04/mobys/circular_saw_enemy.c b/src/overlays/l04/mobys/circular_saw_enemy.c index e81e41b742..7284a2750c 100644 --- a/src/overlays/l04/mobys/circular_saw_enemy.c +++ b/src/overlays/l04/mobys/circular_saw_enemy.c @@ -22,6 +22,19 @@ #include "rnc/rendering/clip_volume.h" #include "rnc/world/collision/ground_probe.h" +enum { + CIRCULAR_SAW_STATE_INITIALIZE = 0, + CIRCULAR_SAW_STATE_IDLE = 1, + CIRCULAR_SAW_STATE_JUMP = 2, + CIRCULAR_SAW_STATE_CHASE_TARGET = 3, + CIRCULAR_SAW_STATE_FOLLOW_PATH = 4, + CIRCULAR_SAW_STATE_POINT_ATTACK = 5, + CIRCULAR_SAW_STATE_HIT_RECOVERY = 6, + CIRCULAR_SAW_STATE_MELEE_ATTACK = 7, + CIRCULAR_SAW_STATE_DYING = 8, + CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED = 9 +}; + /* The engine-sound fields of the moby's pvars. */ typedef struct { /* 0x000 */ u8 pad0[0x230]; @@ -49,9 +62,6 @@ void update_circular_saw_engine_sound(struct Moby *moby) { CIRCULAR_SAW_ANIM_ALERT = 6, CIRCULAR_SAW_ANIM_ATTACK = 7 }; - enum { - CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED = 9 - }; EngineSoundVars *engine_sound_vars = (EngineSoundVars *)moby->pvars; f32 volume; f32 pitch; @@ -484,18 +494,6 @@ void circular_saw_enemy_update(M_35F0 *moby) __asm__("FUN_L04_002c2270"); /* Moby class 340 */ void circular_saw_enemy_update(M_35F0 *moby) { - enum { - CIRCULAR_SAW_STATE_INITIALIZE = 0, - CIRCULAR_SAW_STATE_IDLE = 1, - CIRCULAR_SAW_STATE_JUMP = 2, - CIRCULAR_SAW_STATE_CHASE_TARGET = 3, - CIRCULAR_SAW_STATE_FOLLOW_PATH = 4, - CIRCULAR_SAW_STATE_POINT_ATTACK = 5, - CIRCULAR_SAW_STATE_HIT_RECOVERY = 6, - CIRCULAR_SAW_STATE_MELEE_ATTACK = 7, - CIRCULAR_SAW_STATE_DYING = 8, - CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED = 9 - }; enum { CIRCULAR_SAW_HIT_REACTION_NONE = 0, CIRCULAR_SAW_HIT_REACTION_FATAL = 1, @@ -1152,10 +1150,6 @@ int launch_circular_saw_enemy_from_suck_cannon(struct Moby *moby, int launch_position_source, float launch_position_offset) { - enum { - CIRCULAR_SAW_STATE_IDLE = 1, - CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED = 0x9 - }; char *moby_callback_result = get_moby_suck_cannon_record(moby); int hit_processing_result = launch_suck_cannon_projectile( moby, input_quad_address, launch_position_source, launch_position_offset); diff --git a/src/overlays/l04/mobys/leg_walker.c b/src/overlays/l04/mobys/leg_walker.c index c54a4ea65f..fe6b72164b 100644 --- a/src/overlays/l04/mobys/leg_walker.c +++ b/src/overlays/l04/mobys/leg_walker.c @@ -61,9 +61,6 @@ extern float FUN_L04_001f1978(float); void initialize_leg_rig(struct Moby *moby, LegRig *rig) __asm__("FUN_L04_002923b8"); void initialize_leg_rig(struct Moby *moby, LegRig *rig) { - enum { - LEG_RIG_FALLBACK_GAIT_MASK = 5 - }; int joints[6]; float matrix[4][4]; int i; @@ -178,6 +175,10 @@ float probe_leg_rig_ground_height(float *pos) __asm__("FUN_L04_002922d0"); #include "rnc/overlay/shared/world/collision.h" +enum { + LEG_RIG_FALLBACK_GAIT_MASK = 5 +}; + extern CollisionHit coll_hit __asm__("D_L04_00173FC0"); int update_leg_rig_height_and_tilt(StMoby *moby, Steer *steer_state) __asm__("FUN_L04_00292828"); @@ -572,9 +573,6 @@ extern int rig_pick_mode(struct Moby *m, LegRig *rig, float t) __asm__("FUN_L04_ void reset_leg_rig_from_animation(struct Moby *moby, LegRig *rig) __asm__("FUN_L04_00295de8"); void reset_leg_rig_from_animation(struct Moby *moby, LegRig *rig) { - enum { - LEG_RIG_FALLBACK_GAIT_MASK = 5 - }; int joints[6]; float mtx[4][4]; float animation_time; diff --git a/src/overlays/l05/hero/apply_hero_ground_material_effects.c b/src/overlays/l05/hero/apply_hero_ground_material_effects.c index 4ed35313ee..72c0748647 100644 --- a/src/overlays/l05/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l05/hero/apply_hero_ground_material_effects.c @@ -20,14 +20,6 @@ extern int hero_set_state(int, int) __asm__("FUN_L05_0024cee8"); void apply_hero_ground_material_effects(void) __asm__("FUN_L05_00239fc0"); void apply_hero_ground_material_effects(void) { - enum { - GROUND_MATERIAL_WATER = 0, - GROUND_MATERIAL_MAGNET = 2, - GROUND_MATERIAL_FIXED_SHALLOW_WATER = 14 - }; - enum { - GROUND_MATERIAL_SINK_TRIGGER = 13 - }; u8 save = hero.ground_sound_class; s16 saved_ground_type = hero.ground_type; f32 water_depth; @@ -166,12 +158,6 @@ extern CollisionHit HH __asm__("D_L05_00174240") NOT_SDA; void update_hero_ground_contact(void) __asm__("FUN_L05_002402a8"); void update_hero_ground_contact(void) { - enum { - GROUND_MATERIAL_WATER = 0 - }; - enum { - GROUND_MATERIAL_SINK_TRIGGER = 0xD - }; enum { GROUND_MATERIAL_SINK_SURFACE_PROBE_THROUGH = 3, GROUND_MATERIAL_SINK_SURFACE_CONTACT_BYPASS = 0xB @@ -376,6 +362,16 @@ typedef unsigned int u128_2133a8 __attribute__((mode(TI), aligned(16))); #include "rnc/math/fast_math.h" +enum { + GROUND_MATERIAL_WATER = 0, + GROUND_MATERIAL_MAGNET = 2, + GROUND_MATERIAL_FIXED_SHALLOW_WATER = 14 +}; + +enum { + GROUND_MATERIAL_SINK_TRIGGER = 13 +}; + typedef union { u128_2133a8 q; f32 f[4]; diff --git a/src/overlays/l05/hero/update_hero_motion_by_state.c b/src/overlays/l05/hero/update_hero_motion_by_state.c index 81b7cfbd3b..dfb92d1cc9 100644 --- a/src/overlays/l05/hero/update_hero_motion_by_state.c +++ b/src/overlays/l05/hero/update_hero_motion_by_state.c @@ -1209,7 +1209,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1232,7 +1233,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1529,7 +1531,8 @@ void update_hero_motion_by_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1621,7 +1624,8 @@ void update_hero_motion_by_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1686,7 +1690,8 @@ void update_hero_motion_by_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1786,7 +1791,8 @@ void update_hero_motion_by_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1898,7 +1904,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2013,7 +2020,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2602,7 +2610,8 @@ void update_hero_motion_by_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2619,7 +2628,8 @@ void update_hero_motion_by_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2952,7 +2962,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2969,7 +2980,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -3009,7 +3021,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -3024,7 +3037,8 @@ void update_hero_motion_by_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -3057,7 +3071,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } diff --git a/src/overlays/l05/mobys/extermibot.c b/src/overlays/l05/mobys/extermibot.c index 796cea36cb..5e7af92501 100644 --- a/src/overlays/l05/mobys/extermibot.c +++ b/src/overlays/l05/mobys/extermibot.c @@ -125,26 +125,6 @@ typedef struct ExtermibotVars { /* Moby class 623 */ void extermibot_update(unsigned char *moby) { - enum { - EXTERMIBOT_INITIALIZE = 0, - EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH = 1, - EXTERMIBOT_WANDER_NEAR_START = 2, - EXTERMIBOT_FOLLOW_TARGET = 4, - EXTERMIBOT_WAIT_FOR_TARGET_IN_STRIKE_RANGE = 5, - EXTERMIBOT_APPROACH_TARGET_DIRECTLY = 6, - EXTERMIBOT_AIM_BEFORE_STRIKE = 7, - EXTERMIBOT_STRIKE_TARGET = 8, - EXTERMIBOT_RECOVER_AFTER_STRIKE = 9, - EXTERMIBOT_RETURN_TO_START = 10, - EXTERMIBOT_NONLETHAL_KNOCKBACK = 11, - EXTERMIBOT_WAIT_FOR_ANIMATION_BEFORE_IDLE = 13, - EXTERMIBOT_DEATH_KNOCKBACK = 14, - EXTERMIBOT_WAIT_FOR_ACTIVATION_TRIGGER = 15 - }; - enum { - EXTERMIBOT_TARGET_PATH_UNAVAILABLE = 2, - EXTERMIBOT_HIDDEN_BELOW_START = 0xC - }; ExtermibotVars *moby_data = (ExtermibotVars *)MOBY(moby)->pvars; char *target_moby; float path_goal_or_facing_vector[4]; @@ -722,6 +702,29 @@ extern float D_L05_00161A98_gp __asm__("D_L05_00161A98") __attribute__((sda)); #include "rnc/overlay/l05/mobys/extermibot_data/handle_extermibot_hits_and_update_targeting.h" +enum { + EXTERMIBOT_INITIALIZE = 0, + EXTERMIBOT_HIT_STATUS_SKIP_RESPONSE = 1, + EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH = 1, + EXTERMIBOT_WANDER_NEAR_START = 2, + EXTERMIBOT_FOLLOW_TARGET = 4, + EXTERMIBOT_WAIT_FOR_TARGET_IN_STRIKE_RANGE = 5, + EXTERMIBOT_APPROACH_TARGET_DIRECTLY = 6, + EXTERMIBOT_AIM_BEFORE_STRIKE = 7, + EXTERMIBOT_STRIKE_TARGET = 8, + EXTERMIBOT_RECOVER_AFTER_STRIKE = 9, + EXTERMIBOT_RETURN_TO_START = 10, + EXTERMIBOT_NONLETHAL_KNOCKBACK = 11, + EXTERMIBOT_WAIT_FOR_ANIMATION_BEFORE_IDLE = 13, + EXTERMIBOT_DEATH_KNOCKBACK = 14, + EXTERMIBOT_WAIT_FOR_ACTIVATION_TRIGGER = 15 +}; + +enum { + EXTERMIBOT_TARGET_PATH_UNAVAILABLE = 2, + EXTERMIBOT_HIDDEN_BELOW_START = 0xC +}; + extern Hit_3047E8 *func_L00_0025B478_3047E8(void *, int, int) __asm__("FUN_L00_0025a420"); extern int collision_line(void *, void *, int, void *, void *) __asm__("FUN_001efa68"); extern int resolve_moby_hit_response(void *, void *, void *, int, int *, float *, int, int) __asm__("FUN_00213928"); @@ -758,11 +761,6 @@ void handle_extermibot_hits_and_update_targeting(Moby *moby) { EXTERMIBOT_HIT_FLASH_ONLY = 10, EXTERMIBOT_HIT_NO_REACTION = 11 }; - enum { - EXTERMIBOT_HIT_STATUS_SKIP_RESPONSE = 1, - EXTERMIBOT_NONLETHAL_KNOCKBACK = 11, - EXTERMIBOT_DEATH_KNOCKBACK = 14 - }; Vec_3047E8 working_vector; Vec_3047E8 hit_test_endpoint; int collision_hit_status; @@ -976,9 +974,6 @@ extern f32 FUN_L05_00304058_u(s32, void *, void *, f32) __asm__("FUN_L05_0030405 void move_extermibot_along_path(struct Moby *moby, s32 node, f32 side) __asm__("FUN_L05_00303b08"); void move_extermibot_along_path(struct Moby *moby, s32 destination_position, f32 side) { - enum { - EXTERMIBOT_TARGET_PATH_UNAVAILABLE = 2 - }; PathWalkerVars *walker_vars = (PathWalkerVars *)moby->pvars; Vec4f facing_direction, movement_displacement, goal; f32 offset_heading; diff --git a/src/overlays/l05/mobys/extermitank.c b/src/overlays/l05/mobys/extermitank.c index 0e845cc25f..e16981d696 100644 --- a/src/overlays/l05/mobys/extermitank.c +++ b/src/overlays/l05/mobys/extermitank.c @@ -72,6 +72,13 @@ extern float extermitank_secondary_particle_vector_b_xy_scale_gp __asm__("D_L05_ #include "rnc/overlay/l05/mobys/extermitank_data/extermitank_update.h" +enum { + EXTERMITANK_INITIALIZE = 0, + EXTERMITANK_FOLLOW_PATH = 1, + EXTERMITANK_FIRE_PARTICLES = 2, + EXTERMITANK_REMOVE = 3 +}; + extern float extermitank_secondary_particle_vector_b_spread_degrees_gp __asm__("D_L05_00161B68") __attribute__((sda)); extern float extermitank_secondary_particle_vector_a_spread_degrees_gp __asm__("D_L05_00161B6C") @@ -152,12 +159,6 @@ typedef struct ExtermitankVars { /* Moby class 625 */ void extermitank_update(unsigned char *moby) { - enum { - EXTERMITANK_INITIALIZE = 0, - EXTERMITANK_FOLLOW_PATH = 1, - EXTERMITANK_FIRE_PARTICLES = 2, - EXTERMITANK_REMOVE = 3 - }; ExtermitankVars *extermitank_vars = (ExtermitankVars *)MOBY(moby)->pvars; float origin_position[4]; float particle_vector_a[4]; @@ -540,9 +541,6 @@ void handle_extermitank_hits_and_sync_children(char *moby) { enum { MOBY_HIT_RESPONSE_SKIP_DAMAGE = 1 }; - enum { - EXTERMITANK_REMOVE = 3 - }; ExtermitankVars *extermitank_hit_sync_vars = (ExtermitankVars *)MOBY(moby)->pvars; char *first; char *second; diff --git a/src/overlays/l05/mobys/hoverboard_girl.c b/src/overlays/l05/mobys/hoverboard_girl.c index 5a8eea6436..65121beb13 100644 --- a/src/overlays/l05/mobys/hoverboard_girl.c +++ b/src/overlays/l05/mobys/hoverboard_girl.c @@ -19,6 +19,10 @@ #include "rnc/mobys/attach_manipulator.h" #include "rnc/mobys/moby.h" +enum { + GAME_MODE_CUTSCENE = 2 +}; + /* Hoverboard girl (class record hoverboard_girl), Rilgar / Blackwater City. * The update counts player action 11 at frame 15 when she faces the player. * Its two breast manipulators also carry the effect into cutscene instances. */ @@ -164,9 +168,6 @@ extern unsigned char D_L05_0017C8A0[]; * of the girl's class. */ /* Ported from rac1-decomp (src/overlays/l05_rilgar/vendor_0030EB68.c: func_L05_00317E58), where it is exact; names translated to the US level program. */ void update_hoverboard_girl_cutscene_instances(HoverboardGirlMoby *girl) { - enum { - GAME_MODE_CUTSCENE = 2 - }; char *reference_moby = (char *)girl; if (game_mode == GAME_MODE_CUTSCENE && (D_0015EDB0[0] != 0 || breast_growth_count_gp != 0)) { @@ -202,9 +203,6 @@ void hoverboard_girl_update(HoverboardGirlMoby *moby) { HOVERBOARD_GIRL_STATE_UPDATE_DIALOGUE = 1, HOVERBOARD_GIRL_STATE_WAIT_TO_RESUME_DIALOGUE = 3 }; - enum { - GAME_MODE_CUTSCENE = 2 - }; HoverboardGirlState *state = moby->data; HoverboardGirlVector target_position; HoverboardGirlVector head_position; diff --git a/src/overlays/l05/mobys/scenery_ship.c b/src/overlays/l05/mobys/scenery_ship.c index 864c1cf075..cca054ab7e 100644 --- a/src/overlays/l05/mobys/scenery_ship.c +++ b/src/overlays/l05/mobys/scenery_ship.c @@ -127,6 +127,12 @@ extern float D_0015ED70; #include "rnc/overlay/l05/mobys/scenery_ship_data/scenery_ship_update.h" +enum { + SCENERY_SHIP_INITIALIZE = 0, + SCENERY_SHIP_FOLLOW_PATH = 1, + SCENERY_SHIP_SPAWN_EFFECTS_AND_REMOVE = 2 +}; + int D_L05_001613D8 = 0x80000080; int D_L05_001613DC = 0x80202020; float D_L05_001613E0 = 5.0f; @@ -161,11 +167,6 @@ extern float fast_vec_dist(void *, void *); /* Moby class 79 */ void scenery_ship_update(char *moby) { - enum { - SCENERY_SHIP_INITIALIZE = 0, - SCENERY_SHIP_FOLLOW_PATH = 1, - SCENERY_SHIP_SPAWN_EFFECTS_AND_REMOVE = 2 - }; Data_2D8388 *scenery_ship_instance_vars = ((Data_2D8388 *)MOBY(moby)->pvars); char *hit; char *path; @@ -412,9 +413,6 @@ typedef struct Moby Moby; /* Builds 16 fading glow quads, then draws three ribbons of quads for each linked moby of class 0x4F in view. */ void draw_group_scenery_ship_trails(struct Moby *moby) { - enum { - SCENERY_SHIP_FOLLOW_PATH = 1 - }; L05GlowPacket packet[16]; float matrix[8]; float center[4]; diff --git a/src/overlays/l06/hero/update_hero_motion_for_current_state.c b/src/overlays/l06/hero/update_hero_motion_for_current_state.c index 99caa17b0d..db6ad1e293 100644 --- a/src/overlays/l06/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l06/hero/update_hero_motion_for_current_state.c @@ -34,10 +34,6 @@ float absolute_float(float input) __asm__("func_001F99C0"); void apply_hero_ground_material_response(void) __asm__("FUN_L06_00222fb8"); void apply_hero_ground_material_response(void) { - enum { - HERO_GROUND_MATERIAL_MAGNETIC = 2, - HERO_GROUND_MATERIAL_SINK_SURFACE = 0xD - }; enum { HERO_GROUND_MATERIAL_SLIP_SURFACE = 8 }; @@ -424,10 +420,6 @@ extern struct Hero hero_lui __asm__("D_0013F350") NOT_SDA; void update_hero_ground_contact(void) __asm__("FUN_L06_00229650"); void update_hero_ground_contact(void) { - enum { - HERO_GROUND_MATERIAL_WATER = 0, - HERO_GROUND_MATERIAL_SINK_SURFACE = 0xD - }; V collision_ray_end, ground_ray_start, ground_offset_or_angles, surface_probe_start, unused_surface_probe_point, hit_surface_angles, normalized_hit_normal; f32 f; @@ -948,6 +940,12 @@ extern struct HeroTableRow2C D_L06_0017C3A8[]; #include "rnc/overlay/shared/camera/level_camera.h" +enum { + HERO_GROUND_MATERIAL_WATER = 0, + HERO_GROUND_MATERIAL_MAGNETIC = 2, + HERO_GROUND_MATERIAL_SINK_SURFACE = 0xD +}; + extern void gravity_set_z(void *, void *, f32) __asm__("FUN_L00_00233b20"); extern void offset_hero_position_against_gravity(void *, void *, f32) __asm__("FUN_L00_002336e8"); extern void @@ -1230,7 +1228,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1253,7 +1252,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1552,7 +1552,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1638,7 +1639,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1707,7 +1709,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1807,7 +1810,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1922,7 +1926,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2024,7 +2029,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2557,7 +2563,8 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, D_0015ED6C_c * 0.0f); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(D_0015ED6C_c * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(D_0015ED6C_c * 50.0f)); } @@ -2574,7 +2581,8 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(D_0015ED6C_c * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(D_0015ED6C_c * 50.0f)); } @@ -2894,7 +2902,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2911,7 +2920,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2940,7 +2950,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_1_ATTACK: { @@ -3029,7 +3040,8 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { update_hero_airborne_planar_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); if (hero.motion.velocity.f[2] < D_0015ED6C_c * -10.0f) { hero.motion.velocity.f[2] = D_0015ED6C_c * -10.0f; } @@ -3069,7 +3081,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3165,7 +3178,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -3180,7 +3194,8 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { update_hero_airborne_planar_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < D_0015ED6C_c * -15.0f) { hero.motion.velocity.f[2] = D_0015ED6C_c * -15.0f; } @@ -3214,7 +3229,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } diff --git a/src/overlays/l06/mobys/alien_queen.c b/src/overlays/l06/mobys/alien_queen.c index f6de927781..bbb5a1e267 100644 --- a/src/overlays/l06/mobys/alien_queen.c +++ b/src/overlays/l06/mobys/alien_queen.c @@ -183,6 +183,26 @@ void update_alien_queen_hit_response_and_recovery(char *moby) __asm__("FUN_L06_0 #include "sda.h" +enum { + ALIEN_QUEEN_STATE_INITIALIZE = 0, + ALIEN_QUEEN_STATE_WAIT_TO_START_INTRO = 1, + HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1, + ALIEN_QUEEN_STATE_INTRO = 2, + ALIEN_QUEEN_STATE_FIRST_RECOVERY_CAMERA = 3, + ALIEN_QUEEN_STATE_FROG_RECOVERY_ORBIT = 4, + ALIEN_QUEEN_STATE_SECOND_RECOVERY_CAMERA = 5, + ALIEN_QUEEN_STATE_GROUP_RECOVERY_ORBIT = 6, + ALIEN_QUEEN_STATE_WAIT_TO_APPROACH_TARGET = 7, + ALIEN_QUEEN_STATE_APPROACH_TARGET = 8, + ALIEN_QUEEN_STATE_ATTACK_WINDUP = 9, + ALIEN_QUEEN_STATE_ATTACK_HIT_QUERIES = 10, + ALIEN_QUEEN_STATE_WAIT_FOR_ORBIT_ANIMATION_END = 11, + ALIEN_QUEEN_STATE_TIMED_ORBIT = 12, + ALIEN_QUEEN_STATE_RETURN_HOME = 13, + ALIEN_QUEEN_STATE_DEATH = 14, + ALIEN_QUEEN_STATE_POST_DEATH = 15 +}; + /* Ported from rac1-decomp (src/overlays/l06_blarg/vendor_002B5990.c: func_L06_002FC578), where it is exact; names translated to the US level program. */ extern int *D_L06_001B0FB0[] __asm__("D_L06_001B0C30"); void start_alien_queen_intro(char *moby) __asm__("FUN_L06_002fb148"); @@ -389,24 +409,6 @@ typedef struct AlienQueenVars { /* Moby class 1051 */ void alien_queen_update(unsigned char *moby) { - enum { - ALIEN_QUEEN_STATE_INITIALIZE = 0, - ALIEN_QUEEN_STATE_WAIT_TO_START_INTRO = 1, - ALIEN_QUEEN_STATE_INTRO = 2, - ALIEN_QUEEN_STATE_FIRST_RECOVERY_CAMERA = 3, - ALIEN_QUEEN_STATE_FROG_RECOVERY_ORBIT = 4, - ALIEN_QUEEN_STATE_SECOND_RECOVERY_CAMERA = 5, - ALIEN_QUEEN_STATE_GROUP_RECOVERY_ORBIT = 6, - ALIEN_QUEEN_STATE_WAIT_TO_APPROACH_TARGET = 7, - ALIEN_QUEEN_STATE_APPROACH_TARGET = 8, - ALIEN_QUEEN_STATE_ATTACK_WINDUP = 9, - ALIEN_QUEEN_STATE_ATTACK_HIT_QUERIES = 10, - ALIEN_QUEEN_STATE_WAIT_FOR_ORBIT_ANIMATION_END = 11, - ALIEN_QUEEN_STATE_TIMED_ORBIT = 12, - ALIEN_QUEEN_STATE_RETURN_HOME = 13, - ALIEN_QUEEN_STATE_DEATH = 14, - ALIEN_QUEEN_STATE_POST_DEATH = 15 - }; AlienQueenVars *alien_queen_update_vars = (AlienQueenVars *)MOBY(moby)->pvars; char *target; float step[4]; @@ -806,10 +808,6 @@ void update_alien_queen_hit_response_and_recovery(char *moby) { REDUCED_DAMAGE_SOURCE_CLASS = 0x131, DAMAGE_BOOSTING_SOURCE_CLASS = 0x33B }; - enum { - ALIEN_QUEEN_STATE_INITIALIZE = 0, - HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1 - }; AlienQueenVars *alien_queen_hit_recovery_vars; char *hit; int hit_status; diff --git a/src/overlays/l06/mobys/alien_snapper.c b/src/overlays/l06/mobys/alien_snapper.c index a70f8e7133..a1cec52ce3 100644 --- a/src/overlays/l06/mobys/alien_snapper.c +++ b/src/overlays/l06/mobys/alien_snapper.c @@ -244,31 +244,32 @@ extern int *D_L06_001B0FB0_2FA618[] __asm__("D_L06_001B0C30"); #include "sda.h" +enum { + ALIEN_SNAPPER_STATE_INITIALIZE = 0, + ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION = 1, + ALIEN_SNAPPER_STATE_ACTIVATION_SEQUENCE = 2, + ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER = 3, + ALIEN_SNAPPER_STATE_PREPARE_HOME_NODE_JUMP = 4, + ALIEN_SNAPPER_STATE_JUMP_TO_HOME_NODE = 5, + ALIEN_SNAPPER_STATE_FACE_GOAL_AND_WAIT = 6, + ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH = 7, + ALIEN_SNAPPER_STATE_APPROACH_TARGET = 8, + ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET = 9, + ALIEN_SNAPPER_STATE_WAIT_FOR_REPOSITION_ANIMATION = 10, + ALIEN_SNAPPER_STATE_BITE_TARGET = 11, + ALIEN_SNAPPER_STATE_RETURN_HOME = 12, + ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET = 13, + ALIEN_SNAPPER_STATE_HIT_KNOCKBACK = 14, + ALIEN_SNAPPER_STATE_FACE_HERO = 15, + ALIEN_SNAPPER_STATE_BITE_HERO = 16, + ALIEN_SNAPPER_STATE_DEATH_MOTION = 17 +}; + extern f32 approach_angle(f32 *angle, f32 target, f32 *vel, f32, f32, f32) __asm__("FUN_L00_0025be00"); /* Moby class 1048 */ void alien_snapper_update(Moby *moby) { - enum { - ALIEN_SNAPPER_STATE_INITIALIZE = 0, - ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION = 1, - ALIEN_SNAPPER_STATE_ACTIVATION_SEQUENCE = 2, - ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER = 3, - ALIEN_SNAPPER_STATE_PREPARE_HOME_NODE_JUMP = 4, - ALIEN_SNAPPER_STATE_JUMP_TO_HOME_NODE = 5, - ALIEN_SNAPPER_STATE_FACE_GOAL_AND_WAIT = 6, - ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH = 7, - ALIEN_SNAPPER_STATE_APPROACH_TARGET = 8, - ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET = 9, - ALIEN_SNAPPER_STATE_WAIT_FOR_REPOSITION_ANIMATION = 10, - ALIEN_SNAPPER_STATE_BITE_TARGET = 11, - ALIEN_SNAPPER_STATE_RETURN_HOME = 12, - ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET = 13, - ALIEN_SNAPPER_STATE_HIT_KNOCKBACK = 14, - ALIEN_SNAPPER_STATE_FACE_HERO = 15, - ALIEN_SNAPPER_STATE_BITE_HERO = 16, - ALIEN_SNAPPER_STATE_DEATH_MOTION = 17 - }; enum { ALIEN_SNAPPER_ANIM_ACTIVATION = 3, ALIEN_SNAPPER_ANIM_HOME_NODE_JUMP_WINDUP = 6 @@ -780,12 +781,6 @@ void update_alien_snapper_hit_response_and_targeting(Moby *moby) { SNAPPER_RETURN_HOME = 12, SNAPPER_RETREAT_FROM_TARGET = 13 }; - enum { - ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION = 1, - ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER = 3, - ALIEN_SNAPPER_STATE_HIT_KNOCKBACK = 14, - ALIEN_SNAPPER_STATE_DEATH_MOTION = 0x11 - }; BlargVars *snapper_vars = (struct BlargVars *)moby->pvars; int hit; float damage; diff --git a/src/overlays/l07/mobys/sharkigator.c b/src/overlays/l07/mobys/sharkigator.c index 35c67949ba..b2b2ca3f94 100644 --- a/src/overlays/l07/mobys/sharkigator.c +++ b/src/overlays/l07/mobys/sharkigator.c @@ -119,6 +119,26 @@ extern s32 random_integer_below(s32) __asm__("func_00213260"); #include "qzero.h" +enum { + SHARKIGATOR_INITIALIZE = 0, + SHARKIGATOR_SWIM_IDLE = 1, + SHARKIGATOR_SWIM_WANDER = 2, + SHARKIGATOR_TARGET_PURSUIT = 4, + SHARKIGATOR_TARGET_LUNGE_INTERPOLATION = 5, + SHARKIGATOR_POST_LUNGE_PATH_FOLLOW = 6, + SHARKIGATOR_GRAVITY_IDLE = 7, + SHARKIGATOR_GRAVITY_WANDER = 8, + SHARKIGATOR_TARGET_APPROACH = 9, + SHARKIGATOR_TARGET_CONTACT_ATTACK = 10, + SHARKIGATOR_TARGET_CONTACT_RECOIL_RECOVERY = 11, + SHARKIGATOR_HIT_KNOCKBACK_RECOVERY = 0xC, + SHARKIGATOR_HIT_ANIMATION_RECOVERY = 0xD, + SHARKIGATOR_DEATH_FALL_AND_REMOVE = 0xE, + SHARKIGATOR_SMALL_WATER_GAP_GRAVITY_IDLE = 15, + SHARKIGATOR_DAMPED_GRAVITY_RECOVERY = 16, + SHARKIGATOR_DAMPED_RECOVERY = 17 +}; + extern int D_L07_0015F5CC MACRO_ADDR; extern void FUN_L00_0024f7c8(void *, int, void *); extern void FUN_L00_00257470(void *, int, int); @@ -420,11 +440,6 @@ void handle_sharkigator_hit(struct Moby *moby, char *x, float *hp) { SHARKIGATOR_ALTERNATE_HIT_ANIMATION_RESPONSE = 10, HIT_REACTION_NO_ANIMATION_RESPONSE = 11 }; - enum { - SHARKIGATOR_HIT_KNOCKBACK_RECOVERY = 0xC, - SHARKIGATOR_HIT_ANIMATION_RECOVERY = 0xD, - SHARKIGATOR_DEATH_FALL_AND_REMOVE = 0xE - }; char *hit_record; int hit; int hit_reaction_result; @@ -766,25 +781,6 @@ int test_other_group_moby_state_range(unsigned char *moby, int lower, int upper) /* Moby class 1059 */ void sharkigator_update(unsigned char *moby) { - enum { - SHARKIGATOR_INITIALIZE = 0, - SHARKIGATOR_SWIM_IDLE = 1, - SHARKIGATOR_SWIM_WANDER = 2, - SHARKIGATOR_TARGET_PURSUIT = 4, - SHARKIGATOR_TARGET_LUNGE_INTERPOLATION = 5, - SHARKIGATOR_POST_LUNGE_PATH_FOLLOW = 6, - SHARKIGATOR_GRAVITY_IDLE = 7, - SHARKIGATOR_GRAVITY_WANDER = 8, - SHARKIGATOR_TARGET_APPROACH = 9, - SHARKIGATOR_TARGET_CONTACT_ATTACK = 10, - SHARKIGATOR_TARGET_CONTACT_RECOIL_RECOVERY = 11, - SHARKIGATOR_HIT_KNOCKBACK_RECOVERY = 12, - SHARKIGATOR_HIT_ANIMATION_RECOVERY = 13, - SHARKIGATOR_DEATH_FALL_AND_REMOVE = 14, - SHARKIGATOR_SMALL_WATER_GAP_GRAVITY_IDLE = 15, - SHARKIGATOR_DAMPED_GRAVITY_RECOVERY = 16, - SHARKIGATOR_DAMPED_RECOVERY = 17 - }; enum { WALKER_TARGET_HERO = 0, WALKER_TARGET_NONE = 2, diff --git a/src/overlays/l07/mobys/snagglebeast.c b/src/overlays/l07/mobys/snagglebeast.c index 3c348392c7..33b3f4747c 100644 --- a/src/overlays/l07/mobys/snagglebeast.c +++ b/src/overlays/l07/mobys/snagglebeast.c @@ -766,9 +766,6 @@ int start_snagglebeast_turn_toward_target(unsigned char *moby, int resume_animation, int use_fixed_target_position) { - enum { - SNAGGLEBEAST_TURN_TOWARD_TARGET = 7 - }; float target_heading = fast_arc_tan(target_position[0] - MOBY(moby)->pos.x, target_position[1] - MOBY(moby)->pos.y); if (moby_vars->turn_start_angle < @@ -949,25 +946,6 @@ void snagglebeast_update(unsigned char *moby) __asm__("FUN_L07_00314150" /* Moby class 1106 */ void snagglebeast_update(unsigned char *moby) { - enum { - SNAGGLEBEAST_INITIALIZE = 0, - SNAGGLEBEAST_IDLE = 1, - SNAGGLEBEAST_ALTERNATING_JOINT_EMISSION_BURST = 2, - SNAGGLEBEAST_TRIPLE_SPAWN_ATTACK = 3, - SNAGGLEBEAST_SWEEP_BEAM_ATTACK = 4, - SNAGGLEBEAST_CHASE_TARGET = 5, - SNAGGLEBEAST_CHASE_AFTER_TRANSFORM_RESTORE = 6, - SNAGGLEBEAST_TURN_TOWARD_TARGET = 7, - SNAGGLEBEAST_CAPTURE_HERO_AND_DRAIN_AMMO = 8, - SNAGGLEBEAST_ROPE_ATTACK = 9, - SNAGGLEBEAST_DEATH_EXPLOSION = 10, - SNAGGLEBEAST_WAIT_AFTER_HEALTH_THRESHOLD_HIT = 11, - SNAGGLEBEAST_START_TIMED_DAMAGE_SEQUENCE = 12, - SNAGGLEBEAST_WAIT_BEFORE_TIMED_DAMAGE = 13, - SNAGGLEBEAST_APPLY_TIMED_DAMAGE_AND_SELECT_PATH = 14, - SNAGGLEBEAST_RESTORE_TRANSFORM_AND_RESUME_CHASE = 15, - SNAGGLEBEAST_POST_DEATH_CLEANUP = 16 - }; enum { SNAGGLEBEAST_ROPE_START_ATTACK_ANIMATION = 0, SNAGGLEBEAST_ROPE_WAIT_FOR_ORIGIN_FRAME = 1, @@ -2425,6 +2403,26 @@ extern int D_L07_00161B84; #include "rnc/overlay/l07/mobys/snagglebeast_globals.h" +enum { + SNAGGLEBEAST_INITIALIZE = 0, + SNAGGLEBEAST_IDLE = 1, + SNAGGLEBEAST_ALTERNATING_JOINT_EMISSION_BURST = 2, + SNAGGLEBEAST_TRIPLE_SPAWN_ATTACK = 3, + SNAGGLEBEAST_SWEEP_BEAM_ATTACK = 4, + SNAGGLEBEAST_CHASE_TARGET = 5, + SNAGGLEBEAST_CHASE_AFTER_TRANSFORM_RESTORE = 6, + SNAGGLEBEAST_TURN_TOWARD_TARGET = 7, + SNAGGLEBEAST_CAPTURE_HERO_AND_DRAIN_AMMO = 8, + SNAGGLEBEAST_ROPE_ATTACK = 9, + SNAGGLEBEAST_DEATH_EXPLOSION = 10, + SNAGGLEBEAST_WAIT_AFTER_HEALTH_THRESHOLD_HIT = 11, + SNAGGLEBEAST_START_TIMED_DAMAGE_SEQUENCE = 12, + SNAGGLEBEAST_WAIT_BEFORE_TIMED_DAMAGE = 13, + SNAGGLEBEAST_APPLY_TIMED_DAMAGE_AND_SELECT_PATH = 14, + SNAGGLEBEAST_RESTORE_TRANSFORM_AND_RESUME_CHASE = 15, + SNAGGLEBEAST_POST_DEATH_CLEANUP = 16 +}; + extern char D_L07_00161B90[] MACRO_ADDR; extern char D_L07_00161BA0[] MACRO_ADDR; extern RopeVec rope_previous_points[] __asm__("D_L07_0020DAF0"); diff --git a/src/overlays/l08/hero/hero_set_state.c b/src/overlays/l08/hero/hero_set_state.c index e3bc906afa..4c7f997d7a 100644 --- a/src/overlays/l08/hero/hero_set_state.c +++ b/src/overlays/l08/hero/hero_set_state.c @@ -76,7 +76,8 @@ int hero_set_state(int requested_state, int animation_request_mode) { { struct Hero *p = &hero; if (p->state.control_mode == 0x14 && - (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || animation_request_mode != 2)) + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || + animation_request_mode != 2)) return 0; } if ((level_game_mode == 2 || level_game_mode == 6) && animation_request_mode != 2) diff --git a/src/overlays/l08/hero/update_hero_motion_for_current_state.c b/src/overlays/l08/hero/update_hero_motion_for_current_state.c index 9c3c7702a6..6b6b2907ae 100644 --- a/src/overlays/l08/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l08/hero/update_hero_motion_for_current_state.c @@ -1008,7 +1008,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && MV(hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1030,7 +1031,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (MV(hero.grapple_target) != NULL) { hero.motion.move_yaw = @@ -1318,7 +1320,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1404,7 +1407,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1469,7 +1473,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1566,7 +1571,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1684,7 +1690,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1745,7 +1752,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1843,7 +1851,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2438,7 +2447,8 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2455,7 +2465,8 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2649,8 +2660,8 @@ void update_hero_motion_for_current_state(void) { if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&vector_and_attack_descriptor_scratch, &hero.motion.pos); add_hero_up_offset(&vector_and_attack_descriptor_scratch, - &vector_and_attack_descriptor_scratch, - 0.5f); + &vector_and_attack_descriptor_scratch, + 0.5f); qcopy(&v10, &vector_and_attack_descriptor_scratch); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; v10.f[1] += fast_sin(hero.motion.rot.f[2]) * 0.85f; @@ -2787,7 +2798,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2804,7 +2816,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2826,7 +2839,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -2841,7 +2855,8 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2874,7 +2889,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } diff --git a/src/overlays/l08/mobys/bomber_tank.c b/src/overlays/l08/mobys/bomber_tank.c index 47346809d1..c527473b2b 100644 --- a/src/overlays/l08/mobys/bomber_tank.c +++ b/src/overlays/l08/mobys/bomber_tank.c @@ -130,17 +130,6 @@ void bomber_tank_update(Moby *moby) __asm__("FUN_L08_002d42d8"); /* Moby class 253 */ void bomber_tank_update(Moby *moby) { - enum { - BOMBER_TANK_STATE_INITIALIZE = 0, - BOMBER_TANK_STATE_FOLLOW_PATH_AND_FIRE = 3, - BOMBER_TANK_STATE_FOLLOW_PATH = 6, - BOMBER_TANK_STATE_WAIT_FOR_TRIGGER = 11, - BOMBER_TANK_STATE_SCATTER_GROUP_AND_ACTIVATE = 14, - BOMBER_TANK_STATE_DAMAGED_FOLLOW_PATH = 99 - }; - enum { - BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM = 2 - }; float old_pos[4]; float old_rot[4]; float velocity[4]; @@ -421,10 +410,6 @@ extern int bomber_tank_part_3_destroyed_by_class_661_gp __asm__("D_L08_0015F5B8" __attribute__((sda)); void update_bomber_tank_damage_and_aim(Moby *moby) { - enum { - BOMBER_TANK_STATE_INITIALIZE = 0, - BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM = 2 - }; Data *bomber_tank_damage_and_aim_vars = (Data *)moby->pvars; Hit_2D5FA8 *source; Hit_2D5FA8 *part_a_source; @@ -857,6 +842,16 @@ extern float bomber_tank_joint_particle_horizontal_spread_range_end_gp __asm__(" #include "rnc/overlay/l08/mobys/bomber_tank_data/spawn_bomber_tank_joint_particles.h" +enum { + BOMBER_TANK_STATE_INITIALIZE = 0, + BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM = 2, + BOMBER_TANK_STATE_FOLLOW_PATH_AND_FIRE = 3, + BOMBER_TANK_STATE_FOLLOW_PATH = 6, + BOMBER_TANK_STATE_WAIT_FOR_TRIGGER = 11, + BOMBER_TANK_STATE_SCATTER_GROUP_AND_ACTIVATE = 14, + BOMBER_TANK_STATE_DAMAGED_FOLLOW_PATH = 99 +}; + extern void build_moby_bone_transform(int, int, void *) __asm__("func_0020CCA8"); extern void func_L00_001FF4B0_2D6C58(void *, void *, float) __asm__("FUN_001f9bf8"); extern float func_001F9F90_2D6C58(float) __asm__("FUN_001f9dc8"); diff --git a/src/overlays/l08/mobys/heavy_gunship.c b/src/overlays/l08/mobys/heavy_gunship.c index 82d4dbdd32..595b18b69d 100644 --- a/src/overlays/l08/mobys/heavy_gunship.c +++ b/src/overlays/l08/mobys/heavy_gunship.c @@ -20,6 +20,14 @@ #include "rnc/overlay/shared/mobys/evaluate_moby_animation_pose.h" #include "rnc/overlay/l08/mobys/rocket.h" +enum { + HEAVY_GUNSHIP_INITIALIZE = 0, + HEAVY_GUNSHIP_FOLLOW_PRIMARY_PATH = 1, + HEAVY_GUNSHIP_FOLLOW_SECONDARY_PATH = 2, + HEAVY_GUNSHIP_START_PRIMARY_PATH = 3, + HEAVY_GUNSHIP_DISPERSE_AND_REMOVE = 99 +}; + /* Pvars of the heavy gunship. */ typedef struct { SwarmPathFollower follow[2]; /* 0x00: [0] cruising (state 1), [1] circling (state 2) */ @@ -119,9 +127,6 @@ void spawn_heavy_gunship_parts(struct Moby *moby) { void process_heavy_gunship_part_hits(struct Moby *moby) __asm__("FUN_L08_002e9758"); void process_heavy_gunship_part_hits(struct Moby *moby) { - enum { - HEAVY_GUNSHIP_DISPERSE_AND_REMOVE = 99 - }; int selected = 0; char *linked_part_hit_vars = (char *)moby->pvars; SwarmPart *slots = (SwarmPart *)(linked_part_hit_vars + 0x60); @@ -255,13 +260,6 @@ void heavy_gunship_update(struct Moby *moby) __asm__("FUN_L08_002e9b70"); /* Moby class 463 */ void heavy_gunship_update(struct Moby *moby) { - enum { - HEAVY_GUNSHIP_INITIALIZE = 0, - HEAVY_GUNSHIP_FOLLOW_PRIMARY_PATH = 1, - HEAVY_GUNSHIP_FOLLOW_SECONDARY_PATH = 2, - HEAVY_GUNSHIP_START_PRIMARY_PATH = 3, - HEAVY_GUNSHIP_DISPERSE_AND_REMOVE = 0x63 - }; enum { HEAVY_GUNSHIP_PART_DETACHED = 1 }; diff --git a/src/overlays/l08/mobys/rocket.c b/src/overlays/l08/mobys/rocket.c index f80eced611..7360e706b4 100644 --- a/src/overlays/l08/mobys/rocket.c +++ b/src/overlays/l08/mobys/rocket.c @@ -148,6 +148,16 @@ extern int D_L08_0015F5C4_macro __asm__("D_L08_0015F5C4") MACRO_ADDR; #include "rnc/overlay/l08/mobys/rocket_data/rocket_update.h" +enum { + ROCKET_STATE_INITIALIZE = 0, + ROCKET_STATE_APPROACH_TARGET_OFFSET = 1, + ROCKET_STATE_HOME_TOWARD_TARGET = 2, + ROCKET_STATE_WAIT_FOR_ACTIVATION = 3, + ROCKET_STATE_FOLLOW_ROUTE = 4, + ROCKET_STATE_FLY_CONFIGURED_HEADING = 5, + ROCKET_STATE_EXPLODE_AND_REMOVE = 6 +}; + extern unsigned int D_L08_0015FFDC MACRO_ADDR; extern void FUN_L00_00262cf0(void *, void *, float, float, float); extern void spawn_effect(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); @@ -167,15 +177,6 @@ void spawn_rocket_explosion_and_debris(char *moby, /* Moby class 435 */ void rocket_update(M46 *moby) { - enum { - ROCKET_STATE_INITIALIZE = 0, - ROCKET_STATE_APPROACH_TARGET_OFFSET = 1, - ROCKET_STATE_HOME_TOWARD_TARGET = 2, - ROCKET_STATE_WAIT_FOR_ACTIVATION = 3, - ROCKET_STATE_FOLLOW_ROUTE = 4, - ROCKET_STATE_FLY_CONFIGURED_HEADING = 5, - ROCKET_STATE_EXPLODE_AND_REMOVE = 6 - }; enum { LINKED_CLASS_NEGATIVE_X_POSITIVE_Y_POSITIVE_Z_LAUNCH_OFFSET = 0, LINKED_CLASS_NEGATIVE_X_POSITIVE_Y_NEGATIVE_Z_LAUNCH_OFFSET = 1, @@ -556,9 +557,6 @@ typedef struct RocketVars { } RocketVars; struct Moby *spawn_rocket(void *pos, struct Moby *target, void *velocity, float pitch, float yaw) { - enum { - ROCKET_STATE_APPROACH_TARGET_OFFSET = 1 - }; struct Moby *moby = create_moby(0x1B3); RocketVars *projectile_vars; float *reference; diff --git a/src/overlays/l08/mobys/shrub.c b/src/overlays/l08/mobys/shrub.c index 9dd9017df7..08e1c75679 100644 --- a/src/overlays/l08/mobys/shrub.c +++ b/src/overlays/l08/mobys/shrub.c @@ -32,6 +32,14 @@ extern u8 D_0014C050[]; #include "rnc/overlay/shared/world/swarm_path.h" +enum { + SHRUB_INITIALIZE = 0, + SHRUB_FOLLOW_PRIMARY_PATH_AND_FIRE_AT_TARGET = 1, + SHRUB_FOLLOW_SECONDARY_PATH_AND_FIRE_RANDOMLY = 2, + SHRUB_BEGIN_PRIMARY_PATH = 3, + SHRUB_BREAK_APART_AND_REMOVE = 0x63 +}; + extern struct Moby *D_L08_0015FFD8; extern f32 scale_time(f32) __asm__("FUN_001f96b0"); extern void FUN_L00_00258278(struct Moby *, f32, f32 *, f32, f32, f32); @@ -104,9 +112,6 @@ void spawn_shrub_parts(char *moby) { } void process_shrub_part_hits(struct Moby *parent_moby) { - enum { - SHRUB_BREAK_APART_AND_REMOVE = 0x63 - }; char *shrub_hit_vars = ((char *)parent_moby->pvars); char *shrub_part_entry_address = shrub_hit_vars + 0x60; char **part_entry_cursor = (char **)shrub_part_entry_address; @@ -217,13 +222,6 @@ void update_shrub_parts(struct Moby *parent_moby) { /* Moby class 462 */ void shrub_update(struct Moby *moby) { - enum { - SHRUB_INITIALIZE = 0, - SHRUB_FOLLOW_PRIMARY_PATH_AND_FIRE_AT_TARGET = 1, - SHRUB_FOLLOW_SECONDARY_PATH_AND_FIRE_RANDOMLY = 2, - SHRUB_BEGIN_PRIMARY_PATH = 3, - SHRUB_BREAK_APART_AND_REMOVE = 0x63 - }; enum { SHRUB_PART_RELEASED = 1 }; diff --git a/src/overlays/l09/mobys/refueling_station.c b/src/overlays/l09/mobys/refueling_station.c index 9b0b9cffa7..0d1daf6c72 100644 --- a/src/overlays/l09/mobys/refueling_station.c +++ b/src/overlays/l09/mobys/refueling_station.c @@ -11,6 +11,13 @@ #include "rnc/overlay/shared/mobys/find_moby_hit.h" #include "rnc/mobys/moby.h" +enum { + REFUELING_STATION_STATE_INITIALIZE = 0, + REFUELING_STATION_STATE_WAIT_COMMAND = 1, + REFUELING_STATION_STATE_EXPLOSION_DELAY = 2, + REFUELING_STATION_STATE_EXPLODE = 3 +}; + /* Damage source returned by find_moby_hit. */ typedef struct { u8 pad0[0x2C]; @@ -96,9 +103,6 @@ void handle_refueling_station_damage(struct Moby *moby, DAMAGE_RESULT_UNAVAILABLE = 0, DAMAGE_RESULT_NO_HIT_OR_SUPPRESSED_RESPONSE = 11 }; - enum { - REFUELING_STATION_STATE_EXPLODE = 3 - }; enum { MOBY_STATE_REMOVAL_PENDING_BELOW_ADDRESS_BOUNDARY = 0xFD, MOBY_STATE_REMOVAL_PENDING_AT_OR_ABOVE_ADDRESS_BOUNDARY = 0xFE @@ -171,12 +175,6 @@ typedef struct RefuelingStationVars { /* Moby class 1172 */ void refueling_station_update(struct Moby *moby) { - enum { - REFUELING_STATION_STATE_INITIALIZE = 0, - REFUELING_STATION_STATE_WAIT_COMMAND = 1, - REFUELING_STATION_STATE_EXPLOSION_DELAY = 2, - REFUELING_STATION_STATE_EXPLODE = 3 - }; RefuelingStationVars *station_vars = (RefuelingStationVars *)moby->pvars; float explosion_offset[4]; unsigned char *removal_check_base; diff --git a/src/overlays/l10/mobys/blarg_ship.c b/src/overlays/l10/mobys/blarg_ship.c index 0bbdc8aee5..a2edbfd81f 100644 --- a/src/overlays/l10/mobys/blarg_ship.c +++ b/src/overlays/l10/mobys/blarg_ship.c @@ -135,6 +135,19 @@ extern int D_L10_00161EE4 __attribute__((sda)); #include "rnc/overlay/l10/mobys/blarg_ship_globals.h" +enum { + BLARG_SHIP_STATE_INITIALIZE = 0, + BLARG_SHIP_STATE_WAIT_FOR_TARGET_IN_VOLUME = 1, + HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1, + BLARG_SHIP_STATE_RISE_TO_ENTRY_PATH = 2, + BLARG_SHIP_STATE_FOLLOW_ENTRY_PATH = 3, + BLARG_SHIP_STATE_FIRE_AT_TARGET = 4, + BLARG_SHIP_STATE_FIRE_COOLDOWN = 5, + BLARG_SHIP_STATE_FLY_AWAY = 6, + BLARG_SHIP_STATE_HIT_REACTION = 7, + BLARG_SHIP_STATE_EXPLODE = 8 +}; + float blarg_ship_rocket_speed_gp __asm__("D_L10_00161EE8") = 32.0f; float blarg_ship_firing_animation_speed_gp __asm__("D_L10_00161EEC") = 2.0f; extern unsigned char D_0013D4CB[]; @@ -178,17 +191,6 @@ void blarg_ship_update(Ship_5E48 *m) __asm__("FUN_L10_002e4a88"); /* Moby class 1229 */ void blarg_ship_update(Ship_5E48 *ship) { - enum { - BLARG_SHIP_STATE_INITIALIZE = 0, - BLARG_SHIP_STATE_WAIT_FOR_TARGET_IN_VOLUME = 1, - BLARG_SHIP_STATE_RISE_TO_ENTRY_PATH = 2, - BLARG_SHIP_STATE_FOLLOW_ENTRY_PATH = 3, - BLARG_SHIP_STATE_FIRE_AT_TARGET = 4, - BLARG_SHIP_STATE_FIRE_COOLDOWN = 5, - BLARG_SHIP_STATE_FLY_AWAY = 6, - BLARG_SHIP_STATE_HIT_REACTION = 7, - BLARG_SHIP_STATE_EXPLODE = 8 - }; ShipD_5E48 *d = ship->d; Ship_5E48 *tgt; AlignedVec4f A; @@ -487,11 +489,6 @@ void update_blarg_ship_hit_reactions_and_targeting(struct Moby *moby) { COLOR_EFFECT_ONLY_HIT_RESPONSE = 12, NO_REACTION_HIT_RESPONSE = 13 }; - enum { - HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1, - BLARG_SHIP_STATE_HIT_REACTION = 7, - BLARG_SHIP_STATE_EXPLODE = 8 - }; BlargShipVars *pvars = (BlargShipVars *)moby->pvars; char *ship_hit_record = find_moby_hit(moby, 0x370000, 0); int ship_hit_processing_status; diff --git a/src/overlays/l10/mobys/darter.c b/src/overlays/l10/mobys/darter.c index 29755e89ef..ac08aa0bec 100644 --- a/src/overlays/l10/mobys/darter.c +++ b/src/overlays/l10/mobys/darter.c @@ -125,21 +125,6 @@ void darter_update(Moby *moby) __asm__("FUN_L10_002e01a8"); /* Moby class 1199 */ void darter_update(Moby *moby) { - enum { - DARTER_STATE_INITIALIZE = 0, - DARTER_STATE_RISE_TO_HOME_HEIGHT = 2, - DARTER_STATE_WANDER = 3, - DARTER_STATE_WAIT_BETWEEN_WANDER_GOALS = 4, - DARTER_STATE_RETURN_HOME = 5, - DARTER_STATE_ATTACK_WINDUP = 6, - DARTER_STATE_DIVE_TOWARD_TARGET = 7, - DARTER_STATE_DIVE_ATTACK = 8, - DARTER_STATE_CUBOID_PATROL = 9, - DARTER_STATE_CUBOID_APPROACH_TARGET = 10, - DARTER_STATE_CUBOID_CHARGE_ATTACK = 11, - DARTER_STATE_CUBOID_RETURN_HOME = 12, - DARTER_STATE_DYING = 13 - }; enum { DARTER_SPAWN_HOME_WANDER = 0, DARTER_SPAWN_REMOVE = 1, @@ -667,9 +652,6 @@ extern void trooper_anim_update(void *m, void *p) __asm__("FUN_L00_0025d458"); #include "rnc/data_labels.h" void update_darter_hit_reactions_and_targeting(struct Moby *moby) { - enum { - DARTER_STATE_DYING = 13 - }; enum { TARGET_SELECTION_DEFAULT_REJECTED_NO_REPLACEMENT = 2 }; @@ -784,6 +766,22 @@ void update_darter_hit_reactions_and_targeting(struct Moby *moby) { #include "rnc/overlay/l10/mobys/darter_globals.h" +enum { + DARTER_STATE_INITIALIZE = 0, + DARTER_STATE_RISE_TO_HOME_HEIGHT = 2, + DARTER_STATE_WANDER = 3, + DARTER_STATE_WAIT_BETWEEN_WANDER_GOALS = 4, + DARTER_STATE_RETURN_HOME = 5, + DARTER_STATE_ATTACK_WINDUP = 6, + DARTER_STATE_DIVE_TOWARD_TARGET = 7, + DARTER_STATE_DIVE_ATTACK = 8, + DARTER_STATE_CUBOID_PATROL = 9, + DARTER_STATE_CUBOID_APPROACH_TARGET = 10, + DARTER_STATE_CUBOID_CHARGE_ATTACK = 11, + DARTER_STATE_CUBOID_RETURN_HOME = 12, + DARTER_STATE_DYING = 13 +}; + int moby_group_command_frames_gp __asm__("D_L10_00161E00") = 5; void set_moby_group_command_frames(struct Moby *moby) __asm__("FUN_L10_002e1cb0"); /* Stores a value into each table entry listed for this moby's index. */ diff --git a/src/overlays/l10/mobys/data_processor_linked_effect.c b/src/overlays/l10/mobys/data_processor_linked_effect.c index 39c0fcf201..68ca5f4bba 100644 --- a/src/overlays/l10/mobys/data_processor_linked_effect.c +++ b/src/overlays/l10/mobys/data_processor_linked_effect.c @@ -54,11 +54,6 @@ typedef struct DataProcessorLinkedEffectVars { /* Moby class 1067 */ void data_processor_linked_effect_update(struct Moby *moby) { - enum { - MOBY_STATE_INITIALIZE = 0, - MOBY_STATE_ACTIVE_WITH_SOUND = 1, - MOBY_STATE_ACTIVE_WITHOUT_SOUND = 2 - }; DataProcessorLinkedEffectVars *linked_effect_vars = (DataProcessorLinkedEffectVars *)moby->pvars; union { @@ -170,6 +165,12 @@ extern s32 fast_tween_color(s32, s32, f32) __asm__("FUN_001fa6e0"); #include "rnc/overlay/l10/mobys/data_processor_linked_effect_data/render_data_processor_linked_effect.h" +enum { + MOBY_STATE_INITIALIZE = 0, + MOBY_STATE_ACTIVE_WITH_SOUND = 1, + MOBY_STATE_ACTIVE_WITHOUT_SOUND = 2 +}; + extern int data_processor_linked_effect_color_at_zero_progress_gp __asm__("D_L10_00161C90") __attribute__((sda)); extern int data_processor_linked_effect_color_at_full_progress_gp __asm__("D_L10_00161C94") @@ -183,9 +184,6 @@ extern int D_L10_00161D64; extern int D_L10_00161D68; void render_data_processor_linked_effect(u8 *moby) { - enum { - MOBY_STATE_ACTIVE_WITHOUT_SOUND = 2 - }; DataProcessorLinkedEffectVars *linked_effect_render_vars = (DataProcessorLinkedEffectVars *)MOBY(moby)->pvars; char *linked_processor_vars = diff --git a/src/overlays/l10/mobys/linked_moby_hitbox.c b/src/overlays/l10/mobys/linked_moby_hitbox.c index 8b02b27a36..5594b4f990 100644 --- a/src/overlays/l10/mobys/linked_moby_hitbox.c +++ b/src/overlays/l10/mobys/linked_moby_hitbox.c @@ -21,6 +21,11 @@ extern struct Moby *D_L10_0015FFD8; #include "qzero.h" +enum { + MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF = 0xFD, + MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF = 0xFE +}; + /* Box a moby sweeps through: hits other mobys inside it (FUN_L10_002c9958) */ typedef struct { f32 width; /* 0x00: extent along the moby's x */ @@ -40,10 +45,6 @@ void spawn_linked_hitbox_contact_effects(struct Moby *moby, HitBox *box) __asm__("FUN_L10_002c9958"); void spawn_linked_hitbox_contact_effects(struct Moby *moby, HitBox *box) { - enum { - MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF = 0xFD, - MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF = 0xFE - }; OvlVec4 moby_rotation_basis[3]; OvlVec4 center; OvlVec4 delta; @@ -77,7 +78,8 @@ void spawn_linked_hitbox_contact_effects(struct Moby *moby, HitBox *box) { for (i = 0; i < count; i++) { struct Moby *hitbox_candidate_moby = found[i]; - if (hitbox_candidate_moby == 0 || hitbox_candidate_moby->state == MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF || + if (hitbox_candidate_moby == 0 || + hitbox_candidate_moby->state == MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF || hitbox_candidate_moby->state == MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF) { continue; } @@ -150,10 +152,6 @@ void linked_moby_hitbox_update(struct Moby *moby) { LINKED_HITBOX_STATE_WAIT_FOR_TARGET_STATE_OR_TIMER = 2, LINKED_HITBOX_STATE_REMOVE = 3 }; - enum { - MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF = 0xfd, - MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF = 0xfe - }; LinkedMobyHitboxVars *linked_hitbox_vars = (LinkedMobyHitboxVars *)moby->pvars; int differences = 0; struct Moby *target = 0; diff --git a/src/overlays/l10/mobys/screamer.c b/src/overlays/l10/mobys/screamer.c index 68f7aa1e37..f980dcc83d 100644 --- a/src/overlays/l10/mobys/screamer.c +++ b/src/overlays/l10/mobys/screamer.c @@ -89,19 +89,6 @@ extern float fast_vec_dist(void *, void *); /* Moby class 1196 */ void screamer_update(Moby *moby) { - enum { - SCREAMER_STATE_INITIALIZE = 0, - SCREAMER_STATE_WAIT_FOR_ACTIVATION = 1, - SCREAMER_STATE_WAIT_TO_RISE = 2, - SCREAMER_STATE_RISE_FROM_HOME = 4, - SCREAMER_STATE_FOLLOW_PATH = 5, - SCREAMER_STATE_FACE_LEADER_AT_WAYPOINT = 6, - SCREAMER_STATE_IDLE_AT_HOME = 7, - SCREAMER_STATE_RETURN_HOME = 8, - SCREAMER_STATE_WAIT_TO_WANDER = 9, - SCREAMER_STATE_WANDER = 10, - SCREAMER_STATE_DEATH_KNOCKBACK = 11 - }; float waypoint[6]; D_2E0630 *screamer_data = (D_2E0630 *)moby->pvars; Moby *leader; @@ -384,11 +371,21 @@ extern void trooper_anim_update(void *m, void *p) __asm__("FUN_L00_0025d458"); #include "rnc/data_labels.h" +enum { + SCREAMER_STATE_INITIALIZE = 0, + SCREAMER_STATE_WAIT_FOR_ACTIVATION = 1, + SCREAMER_STATE_WAIT_TO_RISE = 2, + SCREAMER_STATE_RISE_FROM_HOME = 4, + SCREAMER_STATE_FOLLOW_PATH = 5, + SCREAMER_STATE_FACE_LEADER_AT_WAYPOINT = 6, + SCREAMER_STATE_IDLE_AT_HOME = 7, + SCREAMER_STATE_RETURN_HOME = 8, + SCREAMER_STATE_WAIT_TO_WANDER = 9, + SCREAMER_STATE_WANDER = 10, + SCREAMER_STATE_DEATH_KNOCKBACK = 11 +}; + void update_screamer_hit_reactions_and_targeting(struct Moby *moby) { - enum { - SCREAMER_STATE_WAIT_FOR_ACTIVATION = 1, - SCREAMER_STATE_DEATH_KNOCKBACK = 11 - }; enum { TARGET_SELECTION_DEFAULT_TARGET_EXCLUDED = 2 }; diff --git a/src/overlays/l10/mobys/toxic_crab.c b/src/overlays/l10/mobys/toxic_crab.c index 9c8baca487..4bfa9b99ec 100644 --- a/src/overlays/l10/mobys/toxic_crab.c +++ b/src/overlays/l10/mobys/toxic_crab.c @@ -218,21 +218,6 @@ extern float fast_vec_dist(void *, void *); /* Moby class 1202 */ void toxic_crab_update(Moby2E30F8 *m) { - enum { - TOXIC_CRAB_STATE_INITIALIZE = 0, - TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION = 1, - TOXIC_CRAB_STATE_ACTIVATE = 2, - TOXIC_CRAB_STATE_FACE_TRACKED_POSITION = 3, - TOXIC_CRAB_STATE_WAIT_TO_PURSUE = 4, - TOXIC_CRAB_STATE_PURSUE_TARGET = 5, - TOXIC_CRAB_STATE_PAUSE_PURSUIT = 6, - TOXIC_CRAB_STATE_MELEE_ATTACK = 7, - TOXIC_CRAB_STATE_RETURN_HOME = 8, - TOXIC_CRAB_STATE_BACK_AWAY_FROM_TARGET = 9, - TOXIC_CRAB_STATE_HIT_KNOCKBACK = 10, - TOXIC_CRAB_STATE_DEATH_EFFECTS = 11, - TOXIC_CRAB_STATE_FALL_TO_DEATH = 12 - }; enum { MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE }; @@ -1018,6 +1003,22 @@ typedef struct Hit_2E52B0 { #include "rnc/overlay/l10/mobys/toxic_crab_globals.h" +enum { + TOXIC_CRAB_STATE_INITIALIZE = 0, + TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION = 1, + TOXIC_CRAB_STATE_ACTIVATE = 2, + TOXIC_CRAB_STATE_FACE_TRACKED_POSITION = 3, + TOXIC_CRAB_STATE_WAIT_TO_PURSUE = 4, + TOXIC_CRAB_STATE_PURSUE_TARGET = 5, + TOXIC_CRAB_STATE_PAUSE_PURSUIT = 6, + TOXIC_CRAB_STATE_MELEE_ATTACK = 7, + TOXIC_CRAB_STATE_RETURN_HOME = 8, + TOXIC_CRAB_STATE_BACK_AWAY_FROM_TARGET = 9, + TOXIC_CRAB_STATE_HIT_KNOCKBACK = 10, + TOXIC_CRAB_STATE_DEATH_EFFECTS = 11, + TOXIC_CRAB_STATE_FALL_TO_DEATH = 12 +}; + extern float toxic_crab_hit_knockback_gravity_gp __asm__("D_L10_00161E2C") __attribute__((sda)); extern void func_L10_002E14F8_2E52B0(void *) __asm__("FUN_L10_002e0138"); extern float func_001F9878_2E52B0(float) __asm__("FUN_001f96b0"); @@ -1041,14 +1042,6 @@ void update_toxic_crab_hit_reactions_and_targeting(void *mv) { ARC_ADJUSTED_KNOCKBACK_HIT_RESPONSE = 10, SUPPRESSED_HIT_RESPONSE = 11 }; - enum { - TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION = 1, - TOXIC_CRAB_STATE_ACTIVATE = 2, - TOXIC_CRAB_STATE_RETURN_HOME = 8, - TOXIC_CRAB_STATE_HIT_KNOCKBACK = 10, - TOXIC_CRAB_STATE_DEATH_EFFECTS = 0xB, - TOXIC_CRAB_STATE_FALL_TO_DEATH = 0xC - }; Moby *moby = mv; AlignedVec4f vA; AlignedVec4f vB; diff --git a/src/overlays/l11/hero/update_hero_motion_by_state.c b/src/overlays/l11/hero/update_hero_motion_by_state.c index 9680137ae3..57d5b67c3b 100644 --- a/src/overlays/l11/hero/update_hero_motion_by_state.c +++ b/src/overlays/l11/hero/update_hero_motion_by_state.c @@ -1015,7 +1015,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && MV(hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1037,7 +1038,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (MV(hero.grapple_target) != NULL) { hero.motion.move_yaw = @@ -1323,7 +1325,8 @@ void update_hero_motion_by_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1407,7 +1410,8 @@ void update_hero_motion_by_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1472,7 +1476,8 @@ void update_hero_motion_by_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1569,7 +1574,8 @@ void update_hero_motion_by_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1684,7 +1690,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1799,7 +1806,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1910,7 +1918,8 @@ void update_hero_motion_by_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -1927,7 +1936,8 @@ void update_hero_motion_by_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2121,8 +2131,8 @@ void update_hero_motion_by_state(void) { if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&vector_and_hit_descriptor_head_scratch, &hero.motion.pos); add_hero_up_offset(&vector_and_hit_descriptor_head_scratch, - &vector_and_hit_descriptor_head_scratch, - 0.5f); + &vector_and_hit_descriptor_head_scratch, + 0.5f); qcopy(&v10, &vector_and_hit_descriptor_head_scratch); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; v10.f[1] += fast_sin(hero.motion.rot.f[2]) * 0.85f; @@ -2259,7 +2269,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2276,7 +2287,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2298,7 +2310,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -2313,7 +2326,8 @@ void update_hero_motion_by_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2346,7 +2360,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } diff --git a/src/overlays/l11/mobys/energy_sphere.c b/src/overlays/l11/mobys/energy_sphere.c index 77ba0fe935..daae5c2d69 100644 --- a/src/overlays/l11/mobys/energy_sphere.c +++ b/src/overlays/l11/mobys/energy_sphere.c @@ -14,6 +14,11 @@ #include "rnc/rendering/effects/spawn_spark.h" #include "rnc/world/collision/collision_line.h" +enum { + ENERGY_SPHERE_APPROACH_SCALE_AND_REMOVE = 1, + ENERGY_SPHERE_MOVE_AND_DETONATE = 2 +}; + extern float frame_scale_inv_macro[] __asm__("D_0015ED68") MACRO_ADDR; extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); /* Ported from rac1-decomp (src/overlays/l11_pokitaru/vendor_00312BD8.c: func_L11_00319FA0), where it is exact; names translated to the US level program. */ @@ -47,10 +52,6 @@ extern int scale_game_frames(int); /* Moby class 1297 */ void energy_sphere_update(unsigned char *moby) { - enum { - ENERGY_SPHERE_APPROACH_SCALE_AND_REMOVE = 1, - ENERGY_SPHERE_MOVE_AND_DETONATE = 2 - }; char *energy_sphere_private_vars = ((char *)MOBY(moby)->pvars); float previous_position[4]; float *vp; @@ -169,9 +170,6 @@ void set_moby_position_and_refresh_removal_timer(struct Moby *moby, void *new_po void set_moby_state_two_data_and_timer(struct Moby *moby, void *src) __asm__("FUN_L11_00318e98"); void set_moby_state_two_data_and_timer(struct Moby *moby, void *movement_step) { - enum { - ENERGY_SPHERE_MOVE_AND_DETONATE = 2 - }; char *moby_vars; moby->state = ENERGY_SPHERE_MOVE_AND_DETONATE; moby_vars = (char *)moby->pvars; diff --git a/src/overlays/l11/mobys/jet_fighter.c b/src/overlays/l11/mobys/jet_fighter.c index 052e0bfe63..f8e24c96ee 100644 --- a/src/overlays/l11/mobys/jet_fighter.c +++ b/src/overlays/l11/mobys/jet_fighter.c @@ -355,9 +355,6 @@ void draw_ship_hud(struct Moby *moby) __asm__("FUN_L11_00311d50"); extern void draw_ship_hud(); void draw_ship_hud(struct Moby *moby) { - enum { - JET_FIGHTER_STATE_DELAYED_EXIT = 8 - }; ShipVars *ship_hud_vars = (ShipVars *)moby->pvars; short *list; void *found[12]; @@ -873,9 +870,6 @@ void update_player_ship_flight(struct Moby *ship_moby, ShipVars_2838 *ship_vars) __asm__("FUN_L11_00312838"); void update_player_ship_flight(struct Moby *ship_moby, ShipVars_2838 *ship_vars) { - enum { - JET_FIGHTER_STATE_WAIT_FOR_RESPAWN = 7 - }; W4_2838 ship_position_before_movement; W4_2838 death_explosion_velocity; UQ_2838 up; @@ -1229,6 +1223,17 @@ unsigned char l11_jet_fighter_max_ammo __asm__("D_L11_00162058") = 0x14; #include "rnc/overlay/l11/mobys/jet_fighter_data/jet_fighter_update.h" +enum { + JET_FIGHTER_STATE_INITIALIZE = 0, + JET_FIGHTER_STATE_WAIT_FOR_BOARDING = 1, + JET_FIGHTER_STATE_BOARD = 2, + JET_FIGHTER_STATE_FLIGHT = 4, + JET_FIGHTER_STATE_DISMOUNT = 5, + JET_FIGHTER_STATE_WAIT_FOR_RESPAWN = 7, + JET_FIGHTER_STATE_DELAYED_EXIT = 8, + JET_FIGHTER_STATE_INACTIVE = 9 +}; + extern float D_L11_00162078 __attribute__((sda)); int D_L11_00162168 = 180; extern float D_L11_0016D4F0_a[] __asm__("D_L11_0016D4F0"); @@ -1248,16 +1253,6 @@ void jet_fighter_update(struct Moby *moby) __asm__("FUN_L11_00313290"); /* Moby class 1242 */ void jet_fighter_update(struct Moby *moby) { - enum { - JET_FIGHTER_STATE_INITIALIZE = 0, - JET_FIGHTER_STATE_WAIT_FOR_BOARDING = 1, - JET_FIGHTER_STATE_BOARD = 2, - JET_FIGHTER_STATE_FLIGHT = 4, - JET_FIGHTER_STATE_DISMOUNT = 5, - JET_FIGHTER_STATE_WAIT_FOR_RESPAWN = 7, - JET_FIGHTER_STATE_DELAYED_EXIT = 8, - JET_FIGHTER_STATE_INACTIVE = 9 - }; ShipVars_2838 *ship_vars; ShipHit_3290 *hit; W4_2838 ship_velocity_scratch; diff --git a/src/overlays/l11/mobys/owner_linked_moby.c b/src/overlays/l11/mobys/owner_linked_moby.c index e4a2a76166..01905405f2 100644 --- a/src/overlays/l11/mobys/owner_linked_moby.c +++ b/src/overlays/l11/mobys/owner_linked_moby.c @@ -9,6 +9,14 @@ #include "rnc/game/interpolated_record.h" #include "rnc/mobys/animation/blend_moby_animation.h" +enum { + LINKED_MOBY_STATE_START_ANIMATION = 0, + LINKED_MOBY_STATE_WAIT_FOR_ANIMATION_FLAG = 1, + LINKED_MOBY_STATE_HANDLE_HITS = 2, + LINKED_MOBY_STATE_FADE_OUT = 3, + LINKED_MOBY_STATE_REMOVE = 4 +}; + /* Runs the moby's hit timer: on a hit it either finishes the stun or counts it down and plays the hurt animation. */ extern char *find_moby_hit(void *, int, int) __asm__("FUN_L00_0025a420"); extern int fptodp(float) __asm__("FUN_00120478"); @@ -36,10 +44,6 @@ void handle_owner_linked_moby_hits(struct Moby *moby, unsigned char *private_dat HIT_REACTION_KNOCKBACK_AND_CANCEL_PROJECTILE = 4, HIT_REACTION_NO_RESPONSE = 11 }; - enum { - LINKED_MOBY_STATE_FADE_OUT = 3, - LINKED_MOBY_STATE_REMOVE = 4 - }; enum { HIT_STATUS_DAMAGE_PROCESSING_THRESHOLD = 2 }; @@ -102,13 +106,6 @@ typedef struct OwnerLinkedMobyVars { /* Moby class 1219 */ void owner_linked_moby_update(struct Moby *moby) { - enum { - LINKED_MOBY_STATE_START_ANIMATION = 0, - LINKED_MOBY_STATE_WAIT_FOR_ANIMATION_FLAG = 1, - LINKED_MOBY_STATE_HANDLE_HITS = 2, - LINKED_MOBY_STATE_FADE_OUT = 3, - LINKED_MOBY_STATE_REMOVE = 4 - }; enum { MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE }; diff --git a/src/overlays/l11/mobys/pokitaru_boat.c b/src/overlays/l11/mobys/pokitaru_boat.c index 004b6b4532..283eaf150d 100644 --- a/src/overlays/l11/mobys/pokitaru_boat.c +++ b/src/overlays/l11/mobys/pokitaru_boat.c @@ -86,18 +86,19 @@ extern float pokitaru_boat_max_turn_speed_degrees_gp __asm__("D_L11_00161DDC") _ #include "rnc/overlay/l11/mobys/pokitaru_boat_data/pokitaru_boat_update.h" +enum { + POKITARU_BOAT_INITIALIZE = 0, + POKITARU_BOAT_WAIT_FOR_ACTIVATION = 1, + POKITARU_BOAT_FOLLOW_PATH = 2, + POKITARU_BOAT_WAIT_FOR_GROUP_CLEAR = 3, + POKITARU_BOAT_RISE_ABOVE_PATH = 4, + POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO = 5 +}; + void pokitaru_boat_update(struct Moby *moby) __asm__("FUN_L11_00309ac0"); /* Moby class 1075 */ void pokitaru_boat_update(struct Moby *moby) { - enum { - POKITARU_BOAT_INITIALIZE = 0, - POKITARU_BOAT_WAIT_FOR_ACTIVATION = 1, - POKITARU_BOAT_FOLLOW_PATH = 2, - POKITARU_BOAT_WAIT_FOR_GROUP_CLEAR = 3, - POKITARU_BOAT_RISE_ABOVE_PATH = 4, - POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO = 5 - }; struct PokPv *boat_vars = (struct PokPv *)moby->pvars; float start_pos[4]; float start_rot[4]; @@ -330,9 +331,6 @@ struct DataA500 { }; void update_pokitaru_boat_joint_effects(struct Moby *moby) { - enum { - POKITARU_BOAT_WAIT_FOR_ACTIVATION = 1 - }; struct DataA500 *moby_vars = (struct DataA500 *)moby->pvars; float joint_world_position[4]; float pos[4]; diff --git a/src/overlays/l11/mobys/psytcopus.c b/src/overlays/l11/mobys/psytcopus.c index ed0770a3af..667263bf79 100644 --- a/src/overlays/l11/mobys/psytcopus.c +++ b/src/overlays/l11/mobys/psytcopus.c @@ -92,6 +92,16 @@ FUN_L00_0025f3e8_p(struct Moby *, void *, int, float, float) __asm__("FUN_L00_00 #include "rnc/overlay/l11/mobys/psytcopus_data/psytcopus_update.h" +enum { + PSYTCOPUS_STATE_INITIALIZE = 0, + PSYTCOPUS_STATE_FACE_PLAYER = 3, + PSYTCOPUS_STATE_CREATE_PROJECTILE = 4, + PSYTCOPUS_STATE_FIRE_PROJECTILE = 5, + PSYTCOPUS_STATE_ATTACK_RECOVERY = 6, + PSYTCOPUS_STATE_KNOCKBACK = 7, + PSYTCOPUS_STATE_DEATH_KNOCKBACK = 8 +}; + extern float D_L11_00161F9C __attribute__((sda)); extern void set_moby_position_and_refresh_removal_timer(void *, void *) __asm__("FUN_L11_00318e78"); extern void FUN_L00_0025ab48_p(void *, float *, float *, float *) __asm__("FUN_L00_0025ab48"); @@ -109,15 +119,6 @@ void psytcopus_update(struct Moby *m) __asm__("FUN_L11_00310180"); /* Moby class 1231 */ void psytcopus_update(struct Moby *psytcopus) { - enum { - PSYTCOPUS_STATE_INITIALIZE = 0, - PSYTCOPUS_STATE_FACE_PLAYER = 3, - PSYTCOPUS_STATE_CREATE_PROJECTILE = 4, - PSYTCOPUS_STATE_FIRE_PROJECTILE = 5, - PSYTCOPUS_STATE_ATTACK_RECOVERY = 6, - PSYTCOPUS_STATE_KNOCKBACK = 7, - PSYTCOPUS_STATE_DEATH_KNOCKBACK = 8 - }; struct PokiPathVars *psytcopus_vars = (struct PokiPathVars *)psytcopus->pvars; struct Moby *target; Vec4f projectile_vector_scratch; @@ -276,10 +277,6 @@ void handle_psytcopus_hits(struct Moby *psytcopus) { HIT_REACTION_HURT_WITHOUT_STATE_CHANGE = 10, HIT_REACTION_NO_RESPONSE = 11 }; - enum { - PSYTCOPUS_STATE_KNOCKBACK = 7, - PSYTCOPUS_STATE_DEATH_KNOCKBACK = 8 - }; struct PokiPathVars *psytcopus_vars = (struct PokiPathVars *)psytcopus->pvars; Vec4f projectile_and_hit_vector_scratch; int hits; diff --git a/src/overlays/l11/mobys/puffoid.c b/src/overlays/l11/mobys/puffoid.c index c50933d32d..119c0f64e9 100644 --- a/src/overlays/l11/mobys/puffoid.c +++ b/src/overlays/l11/mobys/puffoid.c @@ -108,29 +108,6 @@ void puffoid_update(struct Moby *moby) __asm__("FUN_L11_00314318"); /* Moby class 1246 */ void puffoid_update(struct Moby *moby) { - enum { - PUFFOID_STATE_INITIALIZE = 0, - PUFFOID_STATE_WAIT_FOR_HOME_JUMP = 1, - PUFFOID_STATE_IDLE = 2, - PUFFOID_STATE_WANDER_NEAR_HOME = 3, - PUFFOID_STATE_CHASE_TARGET = 4, - PUFFOID_STATE_SPRAY_ATTACK = 5, - PUFFOID_STATE_RETURN_HOME = 6, - PUFFOID_STATE_JUMP_HOME = 7, - PUFFOID_STATE_JUMP_THEN_WAIT_FOR_HOME_JUMP = 8, - PUFFOID_STATE_KNOCKBACK = 9, - PUFFOID_STATE_REPOSITION_AND_FACE_TARGET = 10, - PUFFOID_STATE_DEATH_KNOCKBACK = 11, - PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP = 12, - PUFFOID_STATE_CARRIER_JUMP = 13, - PUFFOID_STATE_CARRIER_IDLE = 14, - PUFFOID_STATE_CARRIER_CHASE_TARGET = 15, - PUFFOID_STATE_CARRIER_SPRAY_ATTACK = 16, - PUFFOID_STATE_CARRIER_KNOCKBACK = 17, - PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK = 18, - PUFFOID_STATE_FOLLOW_PATH = 19, - PUFFOID_STATE_WAIT_TO_RESUME_COMMAND = 20 - }; enum { PUFFOID_PATH_ANIM_TRAVEL = 4, PUFFOID_PATH_ANIM_ENTER_SPRAY_ATTACK = 5, @@ -680,6 +657,30 @@ extern float puffoid_death_knockback_vertical_scale_gp __asm__("D_L11_001622DC") #include "rnc/overlay/l11/mobys/puffoid_data/update_puffoid_damage_and_path_goal.h" +enum { + PUFFOID_STATE_INITIALIZE = 0, + PUFFOID_STATE_WAIT_FOR_HOME_JUMP = 1, + PUFFOID_STATE_IDLE = 2, + PUFFOID_STATE_WANDER_NEAR_HOME = 3, + PUFFOID_STATE_CHASE_TARGET = 4, + PUFFOID_STATE_SPRAY_ATTACK = 5, + PUFFOID_STATE_RETURN_HOME = 6, + PUFFOID_STATE_JUMP_HOME = 7, + PUFFOID_STATE_JUMP_THEN_WAIT_FOR_HOME_JUMP = 8, + PUFFOID_STATE_KNOCKBACK = 9, + PUFFOID_STATE_REPOSITION_AND_FACE_TARGET = 10, + PUFFOID_STATE_DEATH_KNOCKBACK = 11, + PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP = 12, + PUFFOID_STATE_CARRIER_JUMP = 13, + PUFFOID_STATE_CARRIER_IDLE = 14, + PUFFOID_STATE_CARRIER_CHASE_TARGET = 15, + PUFFOID_STATE_CARRIER_SPRAY_ATTACK = 16, + PUFFOID_STATE_CARRIER_KNOCKBACK = 17, + PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK = 18, + PUFFOID_STATE_FOLLOW_PATH = 19, + PUFFOID_STATE_WAIT_TO_RESUME_COMMAND = 20 +}; + extern float l11_puffoid_horizontal_speed_limit __asm__("D_L11_001622FC") __attribute__((sda)); /* Private variables of the moby FUN_L11_00315968 updates (only the fields it uses). */ @@ -760,19 +761,6 @@ void update_puffoid_damage_and_path_goal(struct Moby *moby) { HIT_RESPONSE_NON_KNOCKBACK_REACTION_ALTERNATE = 10, HIT_RESPONSE_COOLDOWN_NO_KNOCKBACK = 11 }; - enum { - PUFFOID_STATE_INITIALIZE = 0, - PUFFOID_STATE_WAIT_FOR_HOME_JUMP = 1, - PUFFOID_STATE_IDLE = 2, - PUFFOID_STATE_WANDER_NEAR_HOME = 3, - PUFFOID_STATE_KNOCKBACK = 9, - PUFFOID_STATE_REPOSITION_AND_FACE_TARGET = 0xA, - PUFFOID_STATE_DEATH_KNOCKBACK = 0xB, - PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP = 0xC, - PUFFOID_STATE_CARRIER_JUMP = 0xD, - PUFFOID_STATE_CARRIER_KNOCKBACK = 0x11, - PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK = 0x12 - }; enum { HIT_PROCESSING_SKIP_DAMAGE_AND_REACTION = 1 }; @@ -970,10 +958,6 @@ extern short *D_L11_001AC240[]; short count_group_puffoids_in_states_13_to_17(struct Moby *self) __asm__("FUN_L11_00316090"); short count_group_puffoids_in_states_13_to_17(struct Moby *group_source_moby) { - enum { - PUFFOID_STATE_CARRIER_JUMP = 13, - PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK = 18 - }; unsigned short *moby_list_entry; short matching_moby_count; char *level_moby_array_base; @@ -1003,12 +987,6 @@ short count_group_puffoids_in_states_13_to_17(struct Moby *group_source_moby) { s32 is_moby_in_bob_target_exclusion_state(const u8 *moby) __asm__("FUN_L11_00316128"); s32 is_moby_in_bob_target_exclusion_state(const u8 *moby) { - enum { - PUFFOID_STATE_DEATH_KNOCKBACK = 0xB, - PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP = 0xC, - PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK = 0x12, - PUFFOID_STATE_WAIT_TO_RESUME_COMMAND = 0x14 - }; u32 moby_state = moby[0x20]; if (moby_state == PUFFOID_STATE_WAIT_TO_RESUME_COMMAND || moby_state == PUFFOID_STATE_DEATH_KNOCKBACK || @@ -1025,16 +1003,6 @@ extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); int process_puffoid_suck_cannon_suction(struct Moby *moby) __asm__("FUN_L11_00316160"); int process_puffoid_suck_cannon_suction(struct Moby *moby) { - enum { - PUFFOID_STATE_IDLE = 2, - PUFFOID_STATE_CHASE_TARGET = 4, - PUFFOID_STATE_SPRAY_ATTACK = 5, - PUFFOID_STATE_RETURN_HOME = 6, - PUFFOID_STATE_CARRIER_IDLE = 0xE, - PUFFOID_STATE_CARRIER_CHASE_TARGET = 0xF, - PUFFOID_STATE_CARRIER_SPRAY_ATTACK = 0x10, - PUFFOID_STATE_WAIT_TO_RESUME_COMMAND = 0x14 - }; int grab_check_result = process_moby_suck_cannon_suction(moby); if (grab_check_result != 0) { if (moby->state == PUFFOID_STATE_IDLE || moby->state == PUFFOID_STATE_CHASE_TARGET || @@ -1063,9 +1031,6 @@ extern void *store_moby_in_suck_cannon(void *) __asm__("FUN_L00_002dbb20"); void *moby_park_state_on_find(struct Moby *arg) __asm__("FUN_L11_00316210"); void *moby_park_state_on_find(struct Moby *suction_moby) { - enum { - PUFFOID_STATE_WAIT_TO_RESUME_COMMAND = 0x14 - }; void *found = store_moby_in_suck_cannon(suction_moby); if (found != 0) { unsigned char state = suction_moby->state; diff --git a/src/overlays/l11/mobys/resort_owner.c b/src/overlays/l11/mobys/resort_owner.c index da12b1bef6..840939c00c 100644 --- a/src/overlays/l11/mobys/resort_owner.c +++ b/src/overlays/l11/mobys/resort_owner.c @@ -267,7 +267,8 @@ void apply_resort_owner_movement(void *mp) { qcopy(A, moby + 0x10); qcopy(B, moby_vars->unk130); FUN_L00_00258830((int)moby, (int)B, 0.5f, 0.3f, 0.0f, 0x10); - if ((MOBY(moby)->state >= RESORT_OWNER_FOLLOW_HERO && MOBY(moby)->state <= RESORT_OWNER_MOVE_TO_PATH_POINT) || + if ((MOBY(moby)->state >= RESORT_OWNER_FOLLOW_HERO && + MOBY(moby)->state <= RESORT_OWNER_MOVE_TO_PATH_POINT) || (MOBY(moby)->state == RESORT_OWNER_JUMP_TO_TARGET && moby_vars->unk15C == 3)) { resolve_point_path_segment_xy_clearance( 0.3f, diff --git a/src/overlays/l12/hero/update_hero_motion_for_current_state.c b/src/overlays/l12/hero/update_hero_motion_for_current_state.c index 903cf8848e..e95e9e2ace 100644 --- a/src/overlays/l12/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l12/hero/update_hero_motion_for_current_state.c @@ -31,12 +31,6 @@ float absolute_float(float input) __asm__("func_001F99C0"); void update_hero_ground_material_flags(void) __asm__("FUN_L12_0022de30"); void update_hero_ground_material_flags(void) { - enum { - GROUND_MATERIAL_WATER = 0, - GROUND_MATERIAL_MAGNET = 2, - GROUND_MATERIAL_ICE = 7, - GROUND_MATERIAL_SINK_TRIGGER = 0xD - }; struct Hero *hero_for_ground_flags_update = &hero; unsigned char saved; int state; @@ -213,10 +207,6 @@ extern CollisionHit D_L12_001742C0_lui __asm__("D_L12_001742C0") NOT_SDA; void update_hero_ground_contact_and_gravity(void) __asm__("FUN_L12_00233e80"); void update_hero_ground_contact_and_gravity(void) { - enum { - GROUND_MATERIAL_WATER = 0, - GROUND_MATERIAL_SINK_TRIGGER = 0xD - }; V collision_ray_second_endpoint, ground_ray_first_endpoint, ground_geometry_scratch, ground_probe_first_endpoint, unused_ground_probe_output, hit_surface_angles, normalized_hit_normal; @@ -415,6 +405,13 @@ void update_hero_ground_contact_and_gravity(void) { #include "rnc/math/vector.h" #include "rnc/math/fast_math.h" +enum { + GROUND_MATERIAL_WATER = 0, + GROUND_MATERIAL_MAGNET = 2, + GROUND_MATERIAL_ICE = 7, + GROUND_MATERIAL_SINK_TRIGGER = 0xD +}; + struct MobyView { u8 pad0[0xC]; f32 fC; @@ -1311,7 +1308,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && MV(hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1333,7 +1331,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (MV(hero.grapple_target) != NULL) { hero.motion.move_yaw = @@ -1623,7 +1622,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1724,7 +1724,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1905,7 +1906,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -2034,7 +2036,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2095,7 +2098,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2193,7 +2197,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2239,7 +2244,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); } else { hero.motion.velocity.f[2] = 0.0f; - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); } break; } @@ -2354,7 +2360,8 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2371,7 +2378,8 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2583,8 +2591,8 @@ void update_hero_motion_for_current_state(void) { if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&geometry_and_hit_descriptor_scratch, &hero.motion.pos); add_hero_up_offset(&geometry_and_hit_descriptor_scratch, - &geometry_and_hit_descriptor_scratch, - 0.5f); + &geometry_and_hit_descriptor_scratch, + 0.5f); qcopy(&v10, &geometry_and_hit_descriptor_scratch); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; v10.f[1] += fast_sin(hero.motion.rot.f[2]) * 0.85f; @@ -2722,7 +2730,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2739,7 +2748,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2761,7 +2771,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -2776,7 +2787,8 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_movement(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2809,7 +2821,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } diff --git a/src/overlays/l12/mobys/blarg_helicopter.c b/src/overlays/l12/mobys/blarg_helicopter.c index c6e2a996b8..d6132651b6 100644 --- a/src/overlays/l12/mobys/blarg_helicopter.c +++ b/src/overlays/l12/mobys/blarg_helicopter.c @@ -88,6 +88,16 @@ extern int D_L12_001619A0 __attribute__((sda)); #include "rnc/game/game_globals.h" #include "rnc/audio/voice_pool.h" +enum { + BLARG_HELICOPTER_INITIALIZE = 0, + BLARG_HELICOPTER_WAIT_FOR_ACTIVATION = 1, + BLARG_HELICOPTER_FOLLOW_INITIAL_PATH = 2, + BLARG_HELICOPTER_AIM_AND_FIRE = 3, + BLARG_HELICOPTER_MOVE_BETWEEN_PATH_ENDPOINTS = 4, + BLARG_HELICOPTER_KNOCKBACK = 5, + BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET = 6 +}; + extern unsigned char D_0013E550[]; extern unsigned char D_0013D4CB NOT_SDA; extern unsigned short D_00141C50 NOT_SDA; @@ -161,15 +171,6 @@ typedef struct BlargHelicopterVars { /* Moby class 326 */ void blarg_helicopter_update(struct Moby *moby) { - enum { - BLARG_HELICOPTER_INITIALIZE = 0, - BLARG_HELICOPTER_WAIT_FOR_ACTIVATION = 1, - BLARG_HELICOPTER_FOLLOW_INITIAL_PATH = 2, - BLARG_HELICOPTER_AIM_AND_FIRE = 3, - BLARG_HELICOPTER_MOVE_BETWEEN_PATH_ENDPOINTS = 4, - BLARG_HELICOPTER_KNOCKBACK = 5, - BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET = 6 - }; BlargHelicopterVars *blarg_helicopter_vars = (BlargHelicopterVars *)moby->pvars; struct Moby *child; float target[20] __attribute__((aligned(16))); @@ -634,10 +635,6 @@ extern void trooper_anim_update(void *m, short *p) __asm__("FUN_L00_0025d458"); extern void trooper_anim_finish(void *, void *) __asm__("FUN_L00_0025d538"); void process_blarg_helicopter_hits(struct Moby *moby) { - enum { - BLARG_HELICOPTER_KNOCKBACK = 5, - BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET = 6 - }; enum { HIT_PROCESSING_SKIP_HIT = 1 }; diff --git a/src/overlays/l12/mobys/blarg_trooper.c b/src/overlays/l12/mobys/blarg_trooper.c index 99f359d4f7..c04f7ed598 100644 --- a/src/overlays/l12/mobys/blarg_trooper.c +++ b/src/overlays/l12/mobys/blarg_trooper.c @@ -48,6 +48,19 @@ extern int point_in_path_xy(void *, void *, int) __asm__("FUN_L00_00259740"); #include "rnc/overlay/shared/world/level_globals.h" +enum { + BLARG_TROOPER_INITIALIZE = 0, + BLARG_TROOPER_FOLLOW_WAYPOINTS = 1, + BLARG_TROOPER_WAIT_FOR_ACTIVATION = 2, + BLARG_TROOPER_APPROACH_TARGET = 3, + BLARG_TROOPER_KNOCKBACK_RECOVERY = 4, + BLARG_TROOPER_PREPARE_SHOT = 5, + BLARG_TROOPER_FIRE_PROJECTILE = 6, + BLARG_TROOPER_WAIT_BETWEEN_SHOTS = 7, + BLARG_TROOPER_RETURN_HOME = 8, + BLARG_TROOPER_DEATH_FALL = 9 +}; + extern s32 count_active_moby_group_members(s32, s32) __asm__("FUN_L01_0026e008"); extern void trooper_knockback_arc(void *, f32 *, f32 *, f32 *) __asm__("FUN_L00_0025ab48"); extern float fast_subtract_rotations(float, float); @@ -162,18 +175,6 @@ extern s32 is_point_inside_clip_volume(void *, s32) __asm__("FUN_00214720"); /* Moby classes 294, 427 */ void blarg_trooper_update(struct Moby *moby) { - enum { - BLARG_TROOPER_INITIALIZE = 0, - BLARG_TROOPER_FOLLOW_WAYPOINTS = 1, - BLARG_TROOPER_WAIT_FOR_ACTIVATION = 2, - BLARG_TROOPER_APPROACH_TARGET = 3, - BLARG_TROOPER_KNOCKBACK_RECOVERY = 4, - BLARG_TROOPER_PREPARE_SHOT = 5, - BLARG_TROOPER_FIRE_PROJECTILE = 6, - BLARG_TROOPER_WAIT_BETWEEN_SHOTS = 7, - BLARG_TROOPER_RETURN_HOME = 8, - BLARG_TROOPER_DEATH_FALL = 9 - }; TargetReport combat_target_report; Vec4 query_position_or_projectile_origin; Vec4 delta; @@ -568,12 +569,6 @@ extern void anim_update_e81e0(struct Moby *, void *) __asm__("FUN_L00_0025d538") more members, hands off inside its clip volume, and takes hits from other classes (dying, or staggering back). */ void process_blarg_trooper_damage_and_alerts(struct Moby *moby) { - enum { - BLARG_TROOPER_INITIALIZE = 0, - BLARG_TROOPER_WAIT_FOR_ACTIVATION = 2, - BLARG_TROOPER_KNOCKBACK_RECOVERY = 4, - BLARG_TROOPER_DEATH_FALL = 9 - }; BlargTrooperVars *trooper_damage_alert_vars = (BlargTrooperVars *)moby->pvars; Vec4 help_direction_or_hit_position; s32 hit; diff --git a/src/overlays/l12/mobys/homing_mine_spawner.c b/src/overlays/l12/mobys/homing_mine_spawner.c index b0a46b4e08..fb7c63d285 100644 --- a/src/overlays/l12/mobys/homing_mine_spawner.c +++ b/src/overlays/l12/mobys/homing_mine_spawner.c @@ -17,6 +17,15 @@ #include "rnc/overlay/shared/mobys/evaluate_moby_animation_pose.h" #include "rnc/overlay/shared/rendering/effects/update_three_phase_effect_particle.h" +enum { + HOMING_MINE_SPAWNER_CLEAR_LINKED_MOBYS = 0, + HOMING_MINE_SPAWNER_WAIT_FOR_PROXIMITY = 1, + HOMING_MINE_SPAWNER_WAIT_FOR_PRESPAWN_ANIMATION = 2, + HOMING_MINE_SPAWNER_SPAWN_LINKED_MOBYS = 3, + HOMING_MINE_SPAWNER_WAIT_FOR_POSTSPAWN_ANIMATION = 4, + HOMING_MINE_SPAWNER_SPAWN_SEQUENCE_COMPLETE = 5 +}; + typedef struct Moby Moby; /* Spawns the next linked moby at this one's spot, sets it up and gives it a random spin. */ @@ -92,14 +101,6 @@ void homing_mine_spawner_update(struct Moby *m) __asm__("FUN_L12_00307840"); /* Moby class 1281 */ void homing_mine_spawner_update(struct Moby *spawner) { - enum { - HOMING_MINE_SPAWNER_CLEAR_LINKED_MOBYS = 0, - HOMING_MINE_SPAWNER_WAIT_FOR_PROXIMITY = 1, - HOMING_MINE_SPAWNER_WAIT_FOR_PRESPAWN_ANIMATION = 2, - HOMING_MINE_SPAWNER_SPAWN_LINKED_MOBYS = 3, - HOMING_MINE_SPAWNER_WAIT_FOR_POSTSPAWN_ANIMATION = 4, - HOMING_MINE_SPAWNER_SPAWN_SEQUENCE_COMPLETE = 5 - }; HomingMineSpawnerVars *spawner_data = (HomingMineSpawnerVars *)spawner->pvars; int *slots; int i; @@ -173,9 +174,6 @@ extern char D_0013E533[]; extern int select_moby_combat_target(char *, char *, float) __asm__("FUN_L00_0025fcb8"); void update_homing_mine_spawner_target(struct Moby *spawner) { - enum { - HOMING_MINE_SPAWNER_CLEAR_LINKED_MOBYS = 0 - }; HomingMineSpawnerVars *spawner_data = (HomingMineSpawnerVars *)spawner->pvars; char *pad; if (spawner->state != HOMING_MINE_SPAWNER_CLEAR_LINKED_MOBYS) { diff --git a/src/overlays/l12/mobys/hoven_anklebiter.c b/src/overlays/l12/mobys/hoven_anklebiter.c index f8a1bf4595..ee237620e7 100644 --- a/src/overlays/l12/mobys/hoven_anklebiter.c +++ b/src/overlays/l12/mobys/hoven_anklebiter.c @@ -31,13 +31,6 @@ extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); int process_hoven_anklebiter_suck_cannon_suction(struct Moby *moby) __asm__("FUN_L12_002e16b8"); int process_hoven_anklebiter_suck_cannon_suction(struct Moby *moby) { - enum { - ANKLEBITER_IDLE = 1, - ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME = 8, - ANKLEBITER_DORMANT = 9, - ANKLEBITER_WAIT_FOR_LEAP_TRIGGER = 11, - ANKLEBITER_ACTIVATE_FROM_DORMANCY = 13 - }; int active; if (moby->state == ANKLEBITER_DORMANT || moby->state == ANKLEBITER_WAIT_FOR_LEAP_TRIGGER || moby->state == ANKLEBITER_ACTIVATE_FROM_DORMANCY) @@ -59,10 +52,6 @@ extern int store_moby_in_suck_cannon(void *) __asm__("FUN_L00_002dbb20"); int store_hoven_anklebiter_in_suck_cannon(struct Moby *a) __asm__("FUN_L12_002e1758"); int store_hoven_anklebiter_in_suck_cannon(struct Moby *carried_moby) { - enum { - ANKLEBITER_IDLE = 1, - ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME = 0x8 - }; int suck_cannon_store_result = store_moby_in_suck_cannon(carried_moby); if (suck_cannon_store_result == 0) { if (carried_moby->state == ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME) @@ -79,11 +68,6 @@ int store_hoven_anklebiter_in_suck_cannon(struct Moby *carried_moby) { int cancel_hoven_anklebiter_suck_cannon_suction(struct Moby *moby) __asm__("FUN_L12_002e17f8"); int cancel_hoven_anklebiter_suck_cannon_suction(struct Moby *moby) { - enum { - ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME = 8, - ANKLEBITER_DORMANT = 9, - ANKLEBITER_WAIT_FOR_LEAP_TRIGGER = 11 - }; int was_stored_in_suck_cannon = cancel_suck_cannon_suction(moby); if (moby->state == ANKLEBITER_DORMANT || moby->state == ANKLEBITER_WAIT_FOR_LEAP_TRIGGER) { return 0; @@ -289,24 +273,6 @@ extern float fast_subtract_rotations(float, float); /* Moby class 238 */ void hoven_anklebiter_update(AnklebiterMoby *moby) { - enum { - ANKLEBITER_INITIALIZE = 0, - ANKLEBITER_IDLE = 1, - ANKLEBITER_FACE_TARGET_BEFORE_PURSUIT = 3, - ANKLEBITER_PURSUE_TARGET = 4, - ANKLEBITER_MELEE_ATTACK = 5, - ANKLEBITER_RETURN_HOME = 6, - ANKLEBITER_KNOCKBACK_FALL = 7, - ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME = 8, - ANKLEBITER_DORMANT = 9, - ANKLEBITER_RECOVER_AFTER_KNOCKBACK = 10, - ANKLEBITER_WAIT_FOR_LEAP_TRIGGER = 11, - ANKLEBITER_LEAP_TO_HOME = 12, - ANKLEBITER_ACTIVATE_FROM_DORMANCY = 13, - ANKLEBITER_LAND_AFTER_LEAP = 14, - ANKLEBITER_DEATH_EFFECTS_AND_REMOVE = 15, - ANKLEBITER_DEATH_FALL = 99 - }; enum { ANKLEBITER_LEAP_TO_HOME_MOTION_FLAGS = 5 }; @@ -770,9 +736,6 @@ extern int fast_tween_color(int, int, float) __asm__("FUN_001fa6e0"); void spawn_hoven_anklebiter_death_sparks(struct Moby *moby) __asm__("FUN_L12_002e3098"); void spawn_hoven_anklebiter_death_sparks(struct Moby *moby) { - enum { - ANKLEBITER_DEATH_EFFECTS_AND_REMOVE = 15 - }; float pos[4]; float spark_launch_velocity[4]; float gravity_adjusted_spark_velocity[4]; @@ -908,19 +871,30 @@ extern void anim_update_e3528(struct Moby *, void *) __asm__("FUN_L00_0025d538") #include "rnc/overlay/l12/mobys/hoven_anklebiter_data/process_hoven_anklebiter_damage_and_alerts.h" +enum { + ANKLEBITER_INITIALIZE = 0, + ANKLEBITER_IDLE = 1, + ANKLEBITER_FACE_TARGET_BEFORE_PURSUIT = 3, + ANKLEBITER_PURSUE_TARGET = 4, + ANKLEBITER_MELEE_ATTACK = 5, + ANKLEBITER_RETURN_HOME = 6, + ANKLEBITER_KNOCKBACK_FALL = 7, + ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME = 8, + ANKLEBITER_DORMANT = 9, + ANKLEBITER_RECOVER_AFTER_KNOCKBACK = 10, + ANKLEBITER_WAIT_FOR_LEAP_TRIGGER = 11, + ANKLEBITER_LEAP_TO_HOME = 12, + ANKLEBITER_ACTIVATE_FROM_DORMANCY = 13, + ANKLEBITER_LAND_AFTER_LEAP = 14, + ANKLEBITER_DEATH_EFFECTS_AND_REMOVE = 15, + ANKLEBITER_DEATH_FALL = 99 +}; + /* Damage and alert step of the Hoven anklebiter: refreshes its speed while alerted, now and then calls for help behind itself, and takes hits (dying, or staggering back). */ void process_hoven_anklebiter_damage_and_alerts(struct Moby *moby) __asm__("FUN_L12_002e3528"); void process_hoven_anklebiter_damage_and_alerts(struct Moby *moby) { - enum { - ANKLEBITER_INITIALIZE = 0, - ANKLEBITER_KNOCKBACK_FALL = 7, - ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME = 8, - ANKLEBITER_DORMANT = 9, - ANKLEBITER_WAIT_FOR_LEAP_TRIGGER = 0xB, - ANKLEBITER_DEATH_FALL = 0x63 - }; AnklebiterVars *anklebiter_vars = (AnklebiterVars *)moby->pvars; Vec4 help_direction_or_hit_position; s32 hit; diff --git a/src/overlays/l12/mobys/planetbuster_maximus_part.c b/src/overlays/l12/mobys/planetbuster_maximus_part.c index 886f3f401f..bc839a7ffb 100644 --- a/src/overlays/l12/mobys/planetbuster_maximus_part.c +++ b/src/overlays/l12/mobys/planetbuster_maximus_part.c @@ -82,9 +82,6 @@ extern int D_L12_00161F24 __attribute__((sda)); void update_planetbuster_maximus_guns(char *moby) __asm__("FUN_L12_003054b0"); void update_planetbuster_maximus_guns(char *moby) { - enum { - PLANETBUSTER_DROP_PARTS_AND_TRANSITION = 4 - }; char *owner_data = ((char *)MOBY(moby)->pvars); int i; float position_buffer[4]; @@ -639,6 +636,14 @@ extern float planetbuster_maximus_rotation_oscillation_amplitude_gp __asm__("D_L #include "rnc/game/game_globals.h" +enum { + PLANETBUSTER_INITIALIZE_LINKED_PARTS = 0, + PLANETBUSTER_WAIT_FOR_PATH_TRIGGER = 1, + PLANETBUSTER_FOLLOW_PATH = 2, + PLANETBUSTER_POST_PATH_GUN_UPDATE = 3, + PLANETBUSTER_DROP_PARTS_AND_TRANSITION = 4 +}; + extern void FUN_L00_00258278(char *moby, float target, float *vel, float k, float d, float max); extern void vendor_spring(float *, float *, float, float, float, float) __asm__("FUN_L00_0025b8c0"); extern void update_moby_vertical_oscillation(float, float, char *, float *, float *) __asm__("FUN_L00_00262b00"); @@ -684,13 +689,6 @@ typedef struct PlanetbusterMaximusVars { /* Moby class 1274 */ void planetbuster_maximus_part_update(char *moby) { - enum { - PLANETBUSTER_INITIALIZE_LINKED_PARTS = 0, - PLANETBUSTER_WAIT_FOR_PATH_TRIGGER = 1, - PLANETBUSTER_FOLLOW_PATH = 2, - PLANETBUSTER_POST_PATH_GUN_UPDATE = 3, - PLANETBUSTER_DROP_PARTS_AND_TRANSITION = 4 - }; enum { PLANETBUSTER_TRANSITION_SETUP = 0, PLANETBUSTER_TRANSITION_INTERPOLATE = 1, @@ -981,7 +979,8 @@ void planetbuster_maximus_part_update(char *moby) { break; } update_planetbuster_maximus_glow_color(moby); - if ((unsigned char)MOBY(moby)->state >= PLANETBUSTER_WAIT_FOR_PATH_TRIGGER && (unsigned char)MOBY(moby)->state <= PLANETBUSTER_POST_PATH_GUN_UPDATE) { + if ((unsigned char)MOBY(moby)->state >= PLANETBUSTER_WAIT_FOR_PATH_TRIGGER && + (unsigned char)MOBY(moby)->state <= PLANETBUSTER_POST_PATH_GUN_UPDATE) { if (moby_data->unk604 == -1) moby_data->unk604 = allocate_voice_for_target_entry(0, 4, moby); } else { diff --git a/src/overlays/l12/mobys/rocket.c b/src/overlays/l12/mobys/rocket.c index 8e1b850d06..d298ad6154 100644 --- a/src/overlays/l12/mobys/rocket.c +++ b/src/overlays/l12/mobys/rocket.c @@ -19,6 +19,11 @@ #include "qcopy.h" +enum { + ROCKET_STATE_FLYING = 1, + ROCKET_STATE_DETONATE = 2 +}; + extern float fast_cos(float); extern float fast_sin(float); @@ -42,9 +47,6 @@ char *spawn_rocket(char *initial_velocity, float nominal_speed, float f2) { - enum { - ROCKET_STATE_FLYING = 1 - }; struct Moby *moby = (struct Moby *)create_moby(0x199); if (moby != 0) { char *rocket_vars; @@ -118,10 +120,6 @@ void rocket_update(struct Moby *moby) __asm__("FUN_L12_002ece00"); /* Moby classes 409, 435 */ void rocket_update(struct Moby *moby) { - enum { - ROCKET_STATE_FLYING = 1, - ROCKET_STATE_DETONATE = 2 - }; ShotVars *rocket_state = (ShotVars *)moby->pvars; float old_pos[4]; float side[4]; diff --git a/src/overlays/l13/mobys/asteroid.c b/src/overlays/l13/mobys/asteroid.c index 151fdfe45b..e545a2317e 100644 --- a/src/overlays/l13/mobys/asteroid.c +++ b/src/overlays/l13/mobys/asteroid.c @@ -17,6 +17,14 @@ #include "rnc/overlay/shared/math/random/random_int_between.h" #include "rnc/sdk/libc/stdlib.h" +enum { + ASTEROID_INITIALIZE = 0, + ASTEROID_WAIT_TO_LAUNCH = 1, + ASTEROID_MOVE_AND_COLLIDE = 2, + ASTEROID_RESET_AT_HOME = 3, + ASTEROID_WAIT_TO_RESPAWN = 4 +}; + enum AsteroidSpinAxis { SPIN_AXIS_X = 0x0, SPIN_AXIS_Y = 0x1, @@ -144,9 +152,6 @@ void process_asteroid_hit(struct Moby *moby, float scale_ratio) __asm__("FUN_L13_002e1348"); void process_asteroid_hit(struct Moby *moby, char *blob_data, float scale_ratio) { - enum { - ASTEROID_WAIT_TO_RESPAWN = 4 - }; float split_velocity[4]; float split_spawn_position[4]; float nearby_effect_scale = scale_ratio * 7.0f; @@ -241,13 +246,6 @@ void asteroid_update(struct Moby *moby) __asm__("FUN_L13_002e1638"); /* Moby classes 212, 1412 */ void asteroid_update(struct Moby *moby) { - enum { - ASTEROID_INITIALIZE = 0, - ASTEROID_WAIT_TO_LAUNCH = 1, - ASTEROID_MOVE_AND_COLLIDE = 2, - ASTEROID_RESET_AT_HOME = 3, - ASTEROID_WAIT_TO_RESPAWN = 4 - }; struct BlobVars *asteroid_vars = (struct BlobVars *)moby->pvars; f32 distance = fast_vec_dist(&moby->pos, &hero_pos); f32 size; diff --git a/src/overlays/l13/mobys/blarg_gunner.c b/src/overlays/l13/mobys/blarg_gunner.c index f7b54ef764..317e3373f7 100644 --- a/src/overlays/l13/mobys/blarg_gunner.c +++ b/src/overlays/l13/mobys/blarg_gunner.c @@ -18,6 +18,12 @@ #include "qcopy.h" #include "rnc/overlay/shared/math/random/random_int_between.h" +enum { + BLARG_GUNNER_STATE_INITIALIZE = 0, + BLARG_GUNNER_STATE_ACTIVE = 1, + BLARG_GUNNER_STATE_DESTROY = 2 +}; + extern void FUN_L00_00257470(void *, int, int); extern void spawn_explosion(void *, @@ -64,9 +70,6 @@ extern void copy_hero_moby_field_38(struct Moby *moby) __asm__("FUN_L00_0025d1b8 struct Moby *spawn_blarg_turret_child(struct Moby *parent) __asm__("FUN_L13_002b4958"); struct Moby *spawn_blarg_turret_child(struct Moby *parent) { - enum { - BLARG_GUNNER_STATE_INITIALIZE = 0 - }; struct Moby *child_moby; Vars *child_vars; @@ -111,9 +114,6 @@ void process_blarg_gunner_hits(struct Moby *moby, char *moby_vars) { enum { HIT_REACTION_NONE = 11 }; - enum { - BLARG_GUNNER_STATE_DESTROY = 2 - }; float *tm = (float *)(moby_vars + 0x20); char *hit_record; int k; @@ -218,11 +218,6 @@ void blarg_gunner_update(struct Moby *moby) __asm__("FUN_L13_002b4c80"); /* Moby class 36 */ void blarg_gunner_update(struct Moby *moby) { - enum { - BLARG_GUNNER_STATE_INITIALIZE = 0, - BLARG_GUNNER_STATE_ACTIVE = 1, - BLARG_GUNNER_STATE_DESTROY = 2 - }; unsigned char *moby_vars = moby->pvars; float explosion_offset[4]; float explosion_spawn_position[4]; diff --git a/src/overlays/l13/mobys/blarg_space_commando.c b/src/overlays/l13/mobys/blarg_space_commando.c index eca7f2186e..a2a6603b8e 100644 --- a/src/overlays/l13/mobys/blarg_space_commando.c +++ b/src/overlays/l13/mobys/blarg_space_commando.c @@ -171,21 +171,6 @@ void blarg_space_commando_update(struct Moby *moby) __asm__("FUN_L13_00307e98"); /* Moby class 1262 */ void blarg_space_commando_update(struct Moby *moby) { - enum { - BLARG_SPACE_COMMANDO_INITIALIZE = 0, - BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION = 1, - BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION = 2, - BLARG_SPACE_COMMANDO_SELECT_ACTION_AFTER_ANIMATION = 3, - BLARG_SPACE_COMMANDO_FACE_TARGET_AND_WAIT_FOR_TIMER = 4, - BLARG_SPACE_COMMANDO_FACE_TARGET_AND_PROBE_DURING_ANIMATION = 5, - BLARG_SPACE_COMMANDO_RESUME_SAVED_STATE_AFTER_ANIMATION = 6, - BLARG_SPACE_COMMANDO_APPROACH_TARGET_WITH_TURN_OFFSET = 7, - BLARG_SPACE_COMMANDO_APPROACH_TARGET_UNTIL_BLOCKED_OR_NEAR = 11, - BLARG_SPACE_COMMANDO_PROBE_DURING_ANIMATION_THEN_RESUME_APPROACH = 12, - BLARG_SPACE_COMMANDO_RETURN_HOME = 13, - BLARG_SPACE_COMMANDO_KNOCKBACK = 15, - BLARG_SPACE_COMMANDO_DYING = 16 - }; Vars_309330 *blarg_space_commando_vars = (Vars_309330 *)moby->pvars; struct Moby *target; Vec4 point; @@ -574,6 +559,23 @@ extern f32 D_L13_00161E58 __attribute__((sda)); #include "rnc/overlay/shared/world/level_labels.h" +enum { + BLARG_SPACE_COMMANDO_INITIALIZE = 0, + BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION = 1, + HIT_STATUS_SKIP_DAMAGE_PROCESSING = 1, + BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION = 2, + BLARG_SPACE_COMMANDO_SELECT_ACTION_AFTER_ANIMATION = 3, + BLARG_SPACE_COMMANDO_FACE_TARGET_AND_WAIT_FOR_TIMER = 4, + BLARG_SPACE_COMMANDO_FACE_TARGET_AND_PROBE_DURING_ANIMATION = 5, + BLARG_SPACE_COMMANDO_RESUME_SAVED_STATE_AFTER_ANIMATION = 6, + BLARG_SPACE_COMMANDO_APPROACH_TARGET_WITH_TURN_OFFSET = 7, + BLARG_SPACE_COMMANDO_APPROACH_TARGET_UNTIL_BLOCKED_OR_NEAR = 11, + BLARG_SPACE_COMMANDO_PROBE_DURING_ANIMATION_THEN_RESUME_APPROACH = 12, + BLARG_SPACE_COMMANDO_RETURN_HOME = 13, + BLARG_SPACE_COMMANDO_KNOCKBACK = 15, + BLARG_SPACE_COMMANDO_DYING = 16 +}; + extern char D_L13_00160680[] MACRO_ADDR; extern s32 D_001413D0_lui[] __asm__("D_001413D0") NOT_SDA; @@ -609,11 +611,6 @@ void update_blarg_space_commando_damage_targeting_and_ground_motion(struct Moby GROUND_MATERIAL_KILLS_WALKER_WITH_EXPLOSION = 11, GROUND_MATERIAL_EXPLODES_WALKER = 13 }; - enum { - HIT_STATUS_SKIP_DAMAGE_PROCESSING = 1, - BLARG_SPACE_COMMANDO_KNOCKBACK = 0xF, - BLARG_SPACE_COMMANDO_DYING = 0x10 - }; enum { TARGET_MODE_NO_ELIGIBLE_TARGET = 2 }; diff --git a/src/overlays/l13/mobys/blarg_space_fighter.c b/src/overlays/l13/mobys/blarg_space_fighter.c index 93b00aa68e..9adb928290 100644 --- a/src/overlays/l13/mobys/blarg_space_fighter.c +++ b/src/overlays/l13/mobys/blarg_space_fighter.c @@ -49,6 +49,15 @@ extern char D_00140940[]; #include "rnc/overlay/l13/effect_suppression_levels.h" +enum { + FIGHTER_INITIALIZE = 0, + FIGHTER_WAIT_TO_JOIN_PATH = 1, + FIGHTER_FOLLOW_PATH_AND_ATTACK = 2, + HIT_PROCESSING_DAMAGE_THRESHOLD = 2, + FIGHTER_EMIT_DESTRUCTION_EFFECTS = 3, + FIGHTER_WAIT_TO_REINITIALIZE = 4 +}; + extern float random_float_between(float, float) __asm__("FUN_002132a8"); extern void trooper_anim_update(void *, short *) __asm__("FUN_L00_0025d458"); @@ -83,10 +92,6 @@ void process_blarg_space_fighter_damage(struct Moby *moby, unsigned char *moby_d HIT_REACTION_HIGH_INTERPOLATION_TARGET_ALTERNATE = 10, HIT_REACTION_NO_HIT = 11 }; - enum { - HIT_PROCESSING_DAMAGE_THRESHOLD = 2, - FIGHTER_EMIT_DESTRUCTION_EFFECTS = 3 - }; if (moby->state != FIGHTER_EMIT_DESTRUCTION_EFFECTS) { int hit_processing_status; float hit_position_offset[4]; @@ -527,13 +532,6 @@ void blarg_space_fighter_update(Moby_2C56B0 *moby) __asm__("FUN_L13_002c4428"); /* Moby class 111 */ void blarg_space_fighter_update(Moby_2C56B0 *moby) { - enum { - FIGHTER_INITIALIZE = 0, - FIGHTER_WAIT_TO_JOIN_PATH = 1, - FIGHTER_FOLLOW_PATH_AND_ATTACK = 2, - FIGHTER_EMIT_DESTRUCTION_EFFECTS = 3, - FIGHTER_WAIT_TO_REINITIALIZE = 4 - }; enum { FIGHTER_ATTACK_WAIT_TO_FIRE = 0, FIGHTER_ATTACK_FIRE = 1, diff --git a/src/overlays/l13/mobys/blarg_turret.c b/src/overlays/l13/mobys/blarg_turret.c index 7c46fdf515..c56cc9c13b 100644 --- a/src/overlays/l13/mobys/blarg_turret.c +++ b/src/overlays/l13/mobys/blarg_turret.c @@ -25,6 +25,14 @@ #include "qcopy.h" #include "rnc/overlay/l13/mobys/gemlik_projectile.h" +enum { + BLARG_TURRET_STATE_INITIALIZE = 0, + BLARG_TURRET_STATE_WAIT_FOR_TARGET = 1, + BLARG_TURRET_STATE_TRACK_TARGET = 3, + BLARG_TURRET_STATE_DESTROY = 4, + BLARG_TURRET_STATE_DESTRUCTION_DELAY = 5 +}; + typedef struct { float x, y, z, w; } __attribute__((aligned(16))) V4_2B5368; @@ -108,13 +116,6 @@ void blarg_turret_update(Moby_2B5368 *m) __asm__("FUN_L13_002b41b8"); /* Moby class 29 */ void blarg_turret_update(Moby_2B5368 *turret_moby) { - enum { - BLARG_TURRET_STATE_INITIALIZE = 0, - BLARG_TURRET_STATE_WAIT_FOR_TARGET = 1, - BLARG_TURRET_STATE_TRACK_TARGET = 3, - BLARG_TURRET_STATE_DESTROY = 4, - BLARG_TURRET_STATE_DESTRUCTION_DELAY = 5 - }; Data *data = turret_moby->data; Moby_2B5368 *target_moby; Moby_2B5368 *gun; @@ -300,9 +301,6 @@ extern int select_moby_combat_target(void *, void *, float) __asm__("FUN_L00_002 void update_blarg_turret_target_and_state(struct Moby *moby) __asm__("FUN_L13_002b48d8"); void update_blarg_turret_target_and_state(struct Moby *moby) { - enum { - BLARG_TURRET_STATE_TRACK_TARGET = 3 - }; char *turret_vars = (char *)moby->pvars; float distance; if (moby->state == BLARG_TURRET_STATE_TRACK_TARGET) diff --git a/src/overlays/l13/mobys/elevator.c b/src/overlays/l13/mobys/elevator.c index f826049821..8fe3903099 100644 --- a/src/overlays/l13/mobys/elevator.c +++ b/src/overlays/l13/mobys/elevator.c @@ -20,6 +20,17 @@ #include "rnc/math/interpolation/advance_accelerated_scalar.h" #include "rnc/overlay/shared/camera/scripted_camera.h" +enum { + ELEVATOR_STATE_INITIALIZE = 0, + ELEVATOR_STATE_BLEND_CAMERA = 1, + ELEVATOR_STATE_MOVE_TO_TOP = 2, + ELEVATOR_STATE_MOVE_TO_BOTTOM = 3, + ELEVATOR_STATE_WAIT_AT_TOP = 4, + ELEVATOR_STATE_WAIT_AT_BOTTOM = 5, + ELEVATOR_STATE_WAIT_FOR_HERO_EXIT_AT_TOP = 6, + ELEVATOR_STATE_WAIT_FOR_HERO_EXIT_AT_BOTTOM = 7 +}; + typedef struct { u8 pad0[0x20]; u8 path[0x40]; /* 0x20: passed to update_entity_matrix with the moved delta */ @@ -56,16 +67,6 @@ void elevator_update(struct Moby *moby) __asm__("FUN_L13_002b39e0"); /* Moby classes 21, 244 */ void elevator_update(struct Moby *moby) { - enum { - ELEVATOR_STATE_INITIALIZE = 0, - ELEVATOR_STATE_BLEND_CAMERA = 1, - ELEVATOR_STATE_MOVE_TO_TOP = 2, - ELEVATOR_STATE_MOVE_TO_BOTTOM = 3, - ELEVATOR_STATE_WAIT_AT_TOP = 4, - ELEVATOR_STATE_WAIT_AT_BOTTOM = 5, - ELEVATOR_STATE_WAIT_FOR_HERO_EXIT_AT_TOP = 6, - ELEVATOR_STATE_WAIT_FOR_HERO_EXIT_AT_BOTTOM = 7 - }; LiftVars *elevator_vars = (LiftVars *)moby->pvars; float delta[4]; float rot[4]; @@ -234,9 +235,6 @@ void compute_elevator_camera_pose(struct Moby *moby, float *camera_position, float *camera_rotation) { - enum { - ELEVATOR_STATE_MOVE_TO_TOP = 2 - }; float camera_offset_azimuth = moby->rot.z; float horizontal_offset_radius = 2.5f; float z = 1.5f; diff --git a/src/overlays/l13/mobys/fighter_jet.c b/src/overlays/l13/mobys/fighter_jet.c index 9efd2a9ee9..873c11c462 100644 --- a/src/overlays/l13/mobys/fighter_jet.c +++ b/src/overlays/l13/mobys/fighter_jet.c @@ -1216,10 +1216,6 @@ extern void update_view_context(void) __asm__("FUN_001f2d98"); void update_fighter_jet_flight(void *moby_arg, void *data_arg) __asm__("FUN_L13_002ba178"); void update_fighter_jet_flight(void *moby_arg, void *data_arg) { - enum { - FIGHTER_JET_STATE_MOUNT_PLAYER = 2, - FIGHTER_JET_STATE_STOP_DEATH_SOUNDS = 6 - }; FlightMoby *moby = moby_arg; FlightData *jet_flight_state = data_arg; FlightVec old_pos; @@ -1716,6 +1712,18 @@ extern JetCamera jet_camera47 __asm__("D_L13_00166F80"); #include "rnc/overlay/l13/mobys/fighter_jet_data/fighter_jet_update.h" +enum { + FIGHTER_JET_STATE_INITIALIZE = 0, + FIGHTER_JET_STATE_WAIT_FOR_ENTRY = 1, + FIGHTER_JET_STATE_MOUNT_PLAYER = 2, + FIGHTER_JET_STATE_FLIGHT = 4, + FIGHTER_JET_STATE_EXIT_PLAYER = 5, + FIGHTER_JET_STATE_STOP_DEATH_SOUNDS = 6, + FIGHTER_JET_STATE_WAIT_FOR_DEATH_RESET = 7, + FIGHTER_JET_STATE_FORCED_EXIT = 8, + FIGHTER_JET_STATE_DELETE = 9 +}; + extern JetTexture l13_texture_descriptors[] __asm__("D_L13_0016D480"); extern unsigned int l13_texture_palette_data_base __asm__("D_L13_0015F420"); @@ -1766,17 +1774,6 @@ void fighter_jet_update(Jet *m) __asm__("FUN_L13_002bb068"); /* Moby class 69 */ void fighter_jet_update(Jet *jet_moby) { - enum { - FIGHTER_JET_STATE_INITIALIZE = 0, - FIGHTER_JET_STATE_WAIT_FOR_ENTRY = 1, - FIGHTER_JET_STATE_MOUNT_PLAYER = 2, - FIGHTER_JET_STATE_FLIGHT = 4, - FIGHTER_JET_STATE_EXIT_PLAYER = 5, - FIGHTER_JET_STATE_STOP_DEATH_SOUNDS = 6, - FIGHTER_JET_STATE_WAIT_FOR_DEATH_RESET = 7, - FIGHTER_JET_STATE_FORCED_EXIT = 8, - FIGHTER_JET_STATE_DELETE = 9 - }; JetData *jet_data; JetVec impulse; int state, initial_state; diff --git a/src/overlays/l13/mobys/forcefield_tower.c b/src/overlays/l13/mobys/forcefield_tower.c index 11fb46fdbd..b9bcbe71a8 100644 --- a/src/overlays/l13/mobys/forcefield_tower.c +++ b/src/overlays/l13/mobys/forcefield_tower.c @@ -30,6 +30,12 @@ extern void mark_moby_for_removal(void *) __asm__("FUN_0020c828"); #include "rnc/overlay/l13/effect_suppression_levels.h" +enum { + TOWER_STATE_INITIALIZE = 0, + TOWER_STATE_ACTIVE = 1, + TOWER_STATE_DESTRUCTION = 2 +}; + extern float random_float_between(float, float) __asm__("FUN_002132a8"); extern void FUN_L00_00257470(struct Moby *, int, int); @@ -262,9 +268,6 @@ void process_forcefield_tower_damage(struct Moby *moby, unsigned char *moby_data HIT_REACTION_HIGH_INTERPOLATION_TARGET_ALTERNATE = 10, HIT_REACTION_NO_HIT = 11 }; - enum { - TOWER_STATE_DESTRUCTION = 2 - }; char *hit_record; int hit; float position[4]; @@ -376,11 +379,6 @@ void forcefield_tower_update(struct Moby *moby) __asm__("FUN_L13_002cefc0"); /* Moby class 170 */ void forcefield_tower_update(struct Moby *moby) { - enum { - TOWER_STATE_INITIALIZE = 0, - TOWER_STATE_ACTIVE = 1, - TOWER_STATE_DESTRUCTION = 2 - }; enum { TOWER_DESTRUCTION_WAIT_FOR_POINT_1_EFFECT = 0, TOWER_DESTRUCTION_WAIT_FOR_POINT_2_EFFECT = 1, diff --git a/src/overlays/l13/mobys/hovering_rocket_attacker.c b/src/overlays/l13/mobys/hovering_rocket_attacker.c index 0c5d2450e1..fa6e689f50 100644 --- a/src/overlays/l13/mobys/hovering_rocket_attacker.c +++ b/src/overlays/l13/mobys/hovering_rocket_attacker.c @@ -102,15 +102,6 @@ typedef struct HoveringRocketAttackerVars { /* Moby class 101 */ void hovering_rocket_attacker_update(unsigned char *moby) { - enum { - UPDATE_INITIALIZE = 0x0, - TRACK_TARGET_BEFORE_ATTACK = 0x2, - UPDATE_ATTACK_SEQUENCE = 0x4, - WAIT_TO_MOVE_TO_TABLE_POINT = 0x5, - MOVE_TO_TABLE_POINT = 0x6, - WAIT_TO_RESUME_ATTACK_SEQUENCE = 7, - EMIT_EFFECT_AND_REMOVE = 0x8 - }; enum { START_ATTACK_ANIMATION_SEQUENCE = 0, WAIT_FOR_ATTACK_START_ANIMATION = 1, @@ -365,6 +356,16 @@ extern char *D_L13_001B07B0[]; #include "rnc/overlay/shared/world/level_labels.h" +enum { + UPDATE_INITIALIZE = 0x0, + TRACK_TARGET_BEFORE_ATTACK = 0x2, + UPDATE_ATTACK_SEQUENCE = 0x4, + WAIT_TO_MOVE_TO_TABLE_POINT = 0x5, + MOVE_TO_TABLE_POINT = 0x6, + WAIT_TO_RESUME_ATTACK_SEQUENCE = 7, + EMIT_EFFECT_AND_REMOVE = 0x8 +}; + extern float hovering_rocket_attacker_scale_multiplier_gp __asm__("D_L13_00161490") __attribute__((sda)); @@ -386,13 +387,6 @@ void update_hovering_rocket_attacker_common(unsigned char *moby) { enum { TARGET_SELECTION_NO_TARGET = 2 }; - enum { - UPDATE_INITIALIZE = 0, - UPDATE_ATTACK_SEQUENCE = 4, - WAIT_TO_MOVE_TO_TABLE_POINT = 5, - WAIT_TO_RESUME_ATTACK_SEQUENCE = 7, - EMIT_EFFECT_AND_REMOVE = 8 - }; HoveringRocketAttackerVars *moby_data; char *hit_record; int hit_reaction_code; diff --git a/src/overlays/l13/mobys/lift.c b/src/overlays/l13/mobys/lift.c index f3f9148234..3eefedee24 100644 --- a/src/overlays/l13/mobys/lift.c +++ b/src/overlays/l13/mobys/lift.c @@ -15,6 +15,17 @@ #include "rnc/math/interpolation/advance_accelerated_scalar.h" #include "rnc/math/random.h" +enum { + LIFT_INITIALIZE = 0, + LIFT_BLEND_TO_MOUNT_TRANSFORM = 1, + LIFT_MOVE_TO_TOP = 2, + LIFT_MOVE_TO_BOTTOM = 3, + LIFT_IDLE_AT_TOP = 4, + LIFT_IDLE_AT_BOTTOM = 5, + LIFT_WAIT_AT_TOP_FOR_HERO_TO_LEAVE = 6, + LIFT_WAIT_AT_BOTTOM_FOR_HERO_TO_LEAVE = 7 +}; + extern float D_0015ED6C; extern char D_0013E533[]; @@ -49,16 +60,6 @@ void lift_update(struct Moby *moby) __asm__("FUN_L13_0030a6d8"); /* Moby class 1270 */ void lift_update(struct Moby *moby) { - enum { - LIFT_INITIALIZE = 0, - LIFT_BLEND_TO_MOUNT_TRANSFORM = 1, - LIFT_MOVE_TO_TOP = 2, - LIFT_MOVE_TO_BOTTOM = 3, - LIFT_IDLE_AT_TOP = 4, - LIFT_IDLE_AT_BOTTOM = 5, - LIFT_WAIT_AT_TOP_FOR_HERO_TO_LEAVE = 6, - LIFT_WAIT_AT_BOTTOM_FOR_HERO_TO_LEAVE = 7 - }; LiftVarsA6D8 *lift_vars = (LiftVarsA6D8 *)moby->pvars; float delta[4]; float rot[4]; @@ -207,9 +208,6 @@ void lift_update(struct Moby *moby) { } void compute_lift_mount_transform(struct Moby *moby, float *mount_position, float *mount_rotation) { - enum { - LIFT_MOVE_TO_TOP = 2 - }; float mount_offset_angle, k; char *mount_facing_target_base; clear_u64_value(mount_rotation); diff --git a/src/overlays/l13/mobys/qwarks_starfighter.c b/src/overlays/l13/mobys/qwarks_starfighter.c index 101071f529..6fdf2cac8c 100644 --- a/src/overlays/l13/mobys/qwarks_starfighter.c +++ b/src/overlays/l13/mobys/qwarks_starfighter.c @@ -34,6 +34,25 @@ #include "rnc/overlay/shared/math/quad.h" #include "rnc/overlay/l13/mobys/qwarks_starfighter_shield.h" +enum { + ATTACHMENT_DAMAGE_NONE = 0, + STARFIGHTER_STATE_INITIALIZE = 0, + ATTACHMENT_DAMAGE_APPLIED = 1, + STARFIGHTER_STATE_WAIT_FOR_HERO_SHIP = 1, + ATTACHMENT_DAMAGE_STAGE_ADVANCED = 2, + STARFIGHTER_STATE_FOLLOW_INITIAL_PATH = 2, + ATTACHMENT_DAMAGE_LETHAL = 3, + STARFIGHTER_STATE_FOLLOW_COMMAND_PATH = 3, + STARFIGHTER_STATE_FOLLOW_COMMAND_PATH_WITH_TIMED_VOLLEY = 4, + STARFIGHTER_STATE_TRACTOR_BEAM = 5, + STARFIGHTER_STATE_OWNER_UNAVAILABLE = 6, + STARFIGHTER_STATE_DEATH_FLIGHT = 7, + STARFIGHTER_STATE_EXPLODE_AND_REMOVE = 8, + STARFIGHTER_STATE_RESET = 9, + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE +}; + extern f32 random_float_between(f32, f32) __asm__("FUN_002132a8"); extern float D_0015ED6C; @@ -245,11 +264,6 @@ void update_moby_joint_attachments(struct Moby *parent_moby, char *attachment_data) __asm__("FUN_L13_002e8d28"); void update_moby_joint_attachments(struct Moby *parent_moby, char *attachment_data) { - enum { - STARFIGHTER_STATE_TRACTOR_BEAM = 5, - MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, - MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE - }; int i; int attachment_joint_index; char *attached_moby; @@ -371,9 +385,6 @@ int advance_moby_along_selected_path(struct Moby *moby, int path_slot_index, int aim) { - enum { - STARFIGHTER_STATE_TRACTOR_BEAM = 5 - }; char *path = D_L13_001B07B0[*(int *)(&moby_data[path_slot_index << 2] + 0xB0)]; float distance_from_previous_node, seg, segment_distance_shortfall, steering_blend_factor, yaw, pitch; @@ -548,9 +559,6 @@ void begin_starfighter_death_sequence(struct Moby *moby, char *starfighter_moby_data, int *remaining_health) { - enum { - STARFIGHTER_STATE_DEATH_FLIGHT = 7 - }; int path_ids = (int)starfighter_moby_data + 0xB0; struct Moby *mobys; float dx; @@ -725,16 +733,6 @@ void process_moby_attachment_damage(Moby_2EAE80 *moby, Data_2EAE80 *moby_data) { CHILD_HIT_HALF_DAMAGE = 0x127, CHILD_HIT_FIXED_DAMAGE = 0x3F1 }; - enum { - ATTACHMENT_DAMAGE_NONE = 0, - ATTACHMENT_DAMAGE_APPLIED = 1, - ATTACHMENT_DAMAGE_STAGE_ADVANCED = 2, - ATTACHMENT_DAMAGE_LETHAL = 3, - STARFIGHTER_STATE_FOLLOW_COMMAND_PATH_WITH_TIMED_VOLLEY = 4, - STARFIGHTER_STATE_TRACTOR_BEAM = 5, - STARFIGHTER_STATE_OWNER_UNAVAILABLE = 6, - STARFIGHTER_STATE_DEATH_FLIGHT = 7 - }; int hit; int rf; int mode; @@ -1620,22 +1618,6 @@ void qwarks_starfighter_update(Moby388 *moby) __asm__("FUN_L13_002eb098"); /* Moby class 388 */ void qwarks_starfighter_update(Moby388 *moby) { - enum { - STARFIGHTER_STATE_INITIALIZE = 0, - STARFIGHTER_STATE_WAIT_FOR_HERO_SHIP = 1, - STARFIGHTER_STATE_FOLLOW_INITIAL_PATH = 2, - STARFIGHTER_STATE_FOLLOW_COMMAND_PATH = 3, - STARFIGHTER_STATE_FOLLOW_COMMAND_PATH_WITH_TIMED_VOLLEY = 4, - STARFIGHTER_STATE_TRACTOR_BEAM = 5, - STARFIGHTER_STATE_OWNER_UNAVAILABLE = 6, - STARFIGHTER_STATE_DEATH_FLIGHT = 7, - STARFIGHTER_STATE_EXPLODE_AND_REMOVE = 8, - STARFIGHTER_STATE_RESET = 9 - }; - enum { - MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, - MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE - }; enum { STARFIGHTER_SHIELD_STATE_DEACTIVATE_REQUESTED = 3 }; diff --git a/src/overlays/l14/hero/hero_set_state.c b/src/overlays/l14/hero/hero_set_state.c index a0836bfe88..5c772c011d 100644 --- a/src/overlays/l14/hero/hero_set_state.c +++ b/src/overlays/l14/hero/hero_set_state.c @@ -72,7 +72,8 @@ int hero_set_state(int requested_state, int animation_update_mode) { { struct Hero *p = &hero; if (p->state.control_mode == 0x14 && - (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || animation_update_mode != 2)) + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || + animation_update_mode != 2)) return 0; } if ((D_L14_0015F5C4 == 2 || D_L14_0015F5C4 == 6) && animation_update_mode != 2) diff --git a/src/overlays/l14/hero/update_hero_motion_by_state.c b/src/overlays/l14/hero/update_hero_motion_by_state.c index 3b86a28abd..987e9fe9c0 100644 --- a/src/overlays/l14/hero/update_hero_motion_by_state.c +++ b/src/overlays/l14/hero/update_hero_motion_by_state.c @@ -738,7 +738,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && MV(hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -760,7 +761,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (MV(hero.grapple_target) != NULL) { hero.motion.move_yaw = @@ -1041,7 +1043,8 @@ void update_hero_motion_by_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1140,7 +1143,8 @@ void update_hero_motion_by_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1321,7 +1325,8 @@ void update_hero_motion_by_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1441,7 +1446,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1501,7 +1507,8 @@ void update_hero_motion_by_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1586,7 +1593,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1632,7 +1640,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); } else { hero.motion.velocity.f[2] = 0.0f; - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); } break; } @@ -2154,7 +2163,8 @@ void update_hero_motion_by_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2171,7 +2181,8 @@ void update_hero_motion_by_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2497,7 +2508,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2514,7 +2526,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2536,7 +2549,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -2551,7 +2565,8 @@ void update_hero_motion_by_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_movement(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2584,7 +2599,8 @@ void update_hero_motion_by_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } diff --git a/src/overlays/l14/mobys/blarg_heavy_interceptor.c b/src/overlays/l14/mobys/blarg_heavy_interceptor.c index 792705c0a2..76b1bab070 100644 --- a/src/overlays/l14/mobys/blarg_heavy_interceptor.c +++ b/src/overlays/l14/mobys/blarg_heavy_interceptor.c @@ -172,6 +172,18 @@ extern char D_L14_0015F580[] MACRO_ADDR; #include "rnc/overlay/l14/mobys/blarg_heavy_interceptor_data/blarg_heavy_interceptor_update.h" +enum { + INTERCEPTOR_STATE_INITIALIZE = 0, + INTERCEPTOR_STATE_PATROL_AND_SCAN = 1, + INTERCEPTOR_STATE_ALERT_GROUP = 2, + INTERCEPTOR_STATE_TRACK_TARGET = 3, + INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY = 4, + INTERCEPTOR_STATE_FOLLOW_RETURN_PATH = 5, + INTERCEPTOR_STATE_REJOIN_PATROL = 6, + INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL = 7, + INTERCEPTOR_STATE_DEATH_FALL = 9 +}; + extern f32 l14_blarg_heavy_interceptor_path_easing_error_gain __asm__("D_L14_001613A0") __attribute__((sda)); @@ -250,17 +262,6 @@ typedef struct BlargHeavyInterceptorVars { /* Moby class 8 */ void blarg_heavy_interceptor_update(struct Moby *moby) { - enum { - INTERCEPTOR_STATE_INITIALIZE = 0, - INTERCEPTOR_STATE_PATROL_AND_SCAN = 1, - INTERCEPTOR_STATE_ALERT_GROUP = 2, - INTERCEPTOR_STATE_TRACK_TARGET = 3, - INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY = 4, - INTERCEPTOR_STATE_FOLLOW_RETURN_PATH = 5, - INTERCEPTOR_STATE_REJOIN_PATROL = 6, - INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL = 7, - INTERCEPTOR_STATE_DEATH_FALL = 9 - }; enum { INTERCEPTOR_STATE_GROUP_EFFECTS_CONTROLLER = 8 }; @@ -797,11 +798,6 @@ void process_blarg_heavy_interceptor_hit_reactions(struct Moby *moby) { HIT_REACTION_LOW_RED_FLASH_AND_HIT_ANIMATION = 10, HIT_REACTION_NONE = 11 }; - enum { - INTERCEPTOR_STATE_PATROL_AND_SCAN = 1, - INTERCEPTOR_STATE_ALERT_GROUP = 2, - INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL = 7 - }; enum { HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE = 1 }; @@ -1718,9 +1714,6 @@ update_moby_rotation_oscillation(u8 *, u8 *, u8 *, f32, f32, f32) __asm__("FUN_L void update_blarg_heavy_interceptor_oscillation_and_patrol_heading(struct Moby *moby) __asm__("FUN_L14_002aea08"); void update_blarg_heavy_interceptor_oscillation_and_patrol_heading(struct Moby *moby) { - enum { - INTERCEPTOR_STATE_PATROL_AND_SCAN = 1 - }; BlargHeavyInterceptorVars *interceptor_private_vars = (BlargHeavyInterceptorVars *)moby->pvars; f32 heading_offset; update_moby_vertical_oscillation( diff --git a/src/overlays/l14/mobys/bolt_thief.c b/src/overlays/l14/mobys/bolt_thief.c index 2b41bc9729..92be37570e 100644 --- a/src/overlays/l14/mobys/bolt_thief.c +++ b/src/overlays/l14/mobys/bolt_thief.c @@ -19,6 +19,16 @@ #include "rnc/overlay/shared/world/level_path.h" #include "rnc/overlay/l14/mobys/bolt_thief_globals.h" +enum { + BOLT_THIEF_STATE_INITIALIZE = 0, + BOLT_THIEF_STATE_FACE_HERO = 1, + BOLT_THIEF_STATE_WAIT_FOR_TRIGGER = 2, + BOLT_THIEF_STATE_SETTLE_AT_PATH_END = 3, + BOLT_THIEF_STATE_FOLLOW_PRIMARY_PATH = 4, + BOLT_THIEF_STATE_FOLLOW_SECONDARY_PATH = 5, + BOLT_THIEF_STATE_KNOCKBACK = 6 +}; + typedef struct { char pad00[0x60]; char effect[7]; /* 0x60: record func_L00_0025E590 updates */ @@ -116,15 +126,6 @@ void bolt_thief_update(L16CrateMoby *moby) __asm__("FUN_L14_002fe2a0"); /* Moby class 923 */ void bolt_thief_update(L16CrateMoby *moby) { - enum { - BOLT_THIEF_STATE_INITIALIZE = 0, - BOLT_THIEF_STATE_FACE_HERO = 1, - BOLT_THIEF_STATE_WAIT_FOR_TRIGGER = 2, - BOLT_THIEF_STATE_SETTLE_AT_PATH_END = 3, - BOLT_THIEF_STATE_FOLLOW_PRIMARY_PATH = 4, - BOLT_THIEF_STATE_FOLLOW_SECONDARY_PATH = 5, - BOLT_THIEF_STATE_KNOCKBACK = 6 - }; enum { BOLT_THIEF_MODE_PATH_LOOP_WITH_LINKED_CHILD = 0, BOLT_THIEF_MODE_PRIMARY_PATH_THEN_FACE_HERO = 1, @@ -339,9 +340,6 @@ typedef struct BoltThiefVars { } BoltThiefVars; int update_bolt_thief_path_movement(struct Moby *moby) { - enum { - BOLT_THIEF_STATE_FOLLOW_SECONDARY_PATH = 5 - }; float pos[4]; float delta[4]; BoltThiefVars *bolt_thief_state = (BoltThiefVars *)moby->pvars; diff --git a/src/overlays/l14/mobys/enemy_fighter.c b/src/overlays/l14/mobys/enemy_fighter.c index 79a60851ad..f868d2b0f8 100644 --- a/src/overlays/l14/mobys/enemy_fighter.c +++ b/src/overlays/l14/mobys/enemy_fighter.c @@ -62,11 +62,6 @@ void enemy_fighter_update(struct Moby *moby) __asm__("FUN_L14_002fc0f0"); /* Moby class 908 */ void enemy_fighter_update(struct Moby *moby) { - enum { - ENEMY_FIGHTER_STATE_INITIALIZE = 0, - ENEMY_FIGHTER_STATE_FOLLOW_PATH = 1, - ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN = 2 - }; EnemyFighterVars *enemy_fighter_vars = (EnemyFighterVars *)moby->pvars; int hit = find_moby_hit(moby, 0x800000, 0); int index; @@ -144,15 +139,17 @@ void enemy_fighter_update(struct Moby *moby) { #include "rnc/overlay/l14/mobys/enemy_fighter_data/spawn_enemy_fighter_exhaust.h" +enum { + ENEMY_FIGHTER_STATE_INITIALIZE = 0, + ENEMY_FIGHTER_STATE_FOLLOW_PATH = 1, + ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN = 2 +}; + extern char D_L14_0015F580[] MACRO_ADDR; extern int exhaust_ftoi(float) __asm__("FUN_001fa6d0"); void spawn_enemy_fighter_exhaust(struct Moby *emitter_moby) { - enum { - ENEMY_FIGHTER_STATE_INITIALIZE = 0, - ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN = 2 - }; Vec4 step; Vec4 pos; Vec4 paired_exhaust_origin; diff --git a/src/overlays/l14/mobys/flying_car.c b/src/overlays/l14/mobys/flying_car.c index a9443b489f..7a5dc461ed 100644 --- a/src/overlays/l14/mobys/flying_car.c +++ b/src/overlays/l14/mobys/flying_car.c @@ -21,6 +21,13 @@ void seed_linked_record_for_flying_car(u8 *flying_car_moby) __asm__("FUN_L14_003 #include "rnc/overlay/l14/mobys/flying_car_globals.h" +enum { + FLYING_CAR_INITIALIZE = 0, + FLYING_CAR_WAIT_FOR_TRIGGER = 1, + FLYING_CAR_FOLLOW_PATH = 2, + FLYING_CAR_WAIT_FOR_PATH_RESET = 3 +}; + int voice_is_playing(int a, int i) __asm__("FUN_L00_0028d8c0"); typedef struct { @@ -115,12 +122,6 @@ void flying_car_update(struct Moby *m) __asm__("FUN_L14_00306ee0"); /* Moby class 1417 */ void flying_car_update(struct Moby *flying_car_moby) { - enum { - FLYING_CAR_INITIALIZE = 0, - FLYING_CAR_WAIT_FOR_TRIGGER = 1, - FLYING_CAR_FOLLOW_PATH = 2, - FLYING_CAR_WAIT_FOR_PATH_RESET = 3 - }; Data_6ee0 *flying_car_data = (Data_6ee0 *)flying_car_moby->pvars; Vec4f attached_part_offset_component __attribute__((aligned(16))); char *hit; @@ -335,9 +336,6 @@ extern f32 vendor_spring(f32 *, f32 *, f32, f32, f32, f32) __asm__("FUN_L00_0025 int update_flying_car_path_motion(struct Moby *moby) __asm__("FUN_L14_00307620"); int update_flying_car_path_motion(struct Moby *moby) { - enum { - FLYING_CAR_WAIT_FOR_PATH_RESET = 3 - }; float pos[4]; float delta[4]; char *flying_car_data = (char *)moby->pvars; diff --git a/src/overlays/l14/mobys/machinegun_turret.c b/src/overlays/l14/mobys/machinegun_turret.c index f2dbc62bc6..cb966b705b 100644 --- a/src/overlays/l14/mobys/machinegun_turret.c +++ b/src/overlays/l14/mobys/machinegun_turret.c @@ -17,6 +17,22 @@ #include "rnc/overlay/l14/mobys/flying_bolt.h" #include "rnc/overlay/shared/world/level_labels.h" +enum { + MOBY_SELECTION_HERO_FALLBACK = 0, + MOBY_SELECTION_DISTANCE_CANDIDATE = 1, + MOBY_SELECTION_NO_TARGET = 2 +}; + +enum { + TURRET_STATE_INITIALIZE = 0, + TURRET_STATE_WAIT_FOR_ACTIVATION = 1, + TURRET_STATE_DEPLOY = 2, + TURRET_STATE_WAIT_FOR_TARGET = 3, + TURRET_STATE_AIM_AND_FIRE = 4, + TURRET_STATE_RETRACT = 5, + TURRET_STATE_DESTROY = 6 +}; + extern int hit_reaction(void *, void *, void *, int, void *, void *, int, int) __asm__("FUN_L00_0025a478"); @@ -106,11 +122,6 @@ int select_moby_by_xy_distance(char *selection_reference, float best) __asm__("FUN_L14_00268038"); int select_moby_by_xy_distance(char *selection_reference, char *selection_output, float best) { - enum { - MOBY_SELECTION_HERO_FALLBACK = 0, - MOBY_SELECTION_DISTANCE_CANDIDATE = 1, - MOBY_SELECTION_NO_TARGET = 2 - }; struct Hero *hero = &hero_lui; char *selected_moby; char *candidate_moby; @@ -219,22 +230,10 @@ void machinegun_turret_update(char *moby) __asm__("FUN_L14_002b3bf0"); /* Moby class 30 */ void machinegun_turret_update(char *moby) { - enum { - TURRET_STATE_INITIALIZE = 0, - TURRET_STATE_WAIT_FOR_ACTIVATION = 1, - TURRET_STATE_DEPLOY = 2, - TURRET_STATE_WAIT_FOR_TARGET = 3, - TURRET_STATE_AIM_AND_FIRE = 4, - TURRET_STATE_RETRACT = 5, - TURRET_STATE_DESTROY = 6 - }; enum { TURRET_SPAWN_CENTER = 0, TURRET_SPAWN_UNNEGATED_OFFSET = 1 }; - enum { - MOBY_SELECTION_NO_TARGET = 2 - }; MachinegunTurretVars *machinegun_turret_private_vars; float target_point_scratch[4]; float spawn_position[4]; @@ -519,9 +518,6 @@ void process_machinegun_turret_hit_reactions(struct Moby *moby) { HIT_REACTION_LOW_RED_FLASH_AND_HIT_ANIMATION = 10, HIT_REACTION_NONE = 11 }; - enum { - TURRET_STATE_DESTROY = 6 - }; MachinegunTurretVars *moby_vars = (MachinegunTurretVars *)moby->pvars; int loc0; float damage_amount = 0.0f; diff --git a/src/overlays/l14/mobys/minibomber.c b/src/overlays/l14/mobys/minibomber.c index df0c568821..8702ea9e87 100644 --- a/src/overlays/l14/mobys/minibomber.c +++ b/src/overlays/l14/mobys/minibomber.c @@ -22,6 +22,18 @@ #include "rnc/overlay/l14/mobys/puff.h" #include "rnc/overlay/l14/mobys/minibomber_globals.h" +enum { + MINIBOMBER_STATE_INITIALIZE = 0, + MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH = 1, + MINIBOMBER_STATE_FOLLOW_INTRO_OR_EXIT_PATH = 2, + MINIBOMBER_STATE_RETRACE_INTRO_OR_EXIT_PATH = 3, + MINIBOMBER_STATE_HOLD_AT_PATH_END = 4, + MINIBOMBER_STATE_AIM_AT_BOMB_POINT = 5, + MINIBOMBER_STATE_RELEASE_BOMB = 6, + MINIBOMBER_STATE_TRAVERSE_PATH = 7, + MINIBOMBER_STATE_DESTROY = 9 +}; + extern void release_voice_slot(s32 idx) __asm__("FUN_0022d798"); extern void FUN_L00_0025a120(void *); @@ -264,17 +276,6 @@ void minibomber_update(Moby_2B5938 *moby) __asm__("FUN_L14_002b46e8"); /* Moby class 31 */ void minibomber_update(Moby_2B5938 *moby) { - enum { - MINIBOMBER_STATE_INITIALIZE = 0, - MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH = 1, - MINIBOMBER_STATE_FOLLOW_INTRO_OR_EXIT_PATH = 2, - MINIBOMBER_STATE_RETRACE_INTRO_OR_EXIT_PATH = 3, - MINIBOMBER_STATE_HOLD_AT_PATH_END = 4, - MINIBOMBER_STATE_AIM_AT_BOMB_POINT = 5, - MINIBOMBER_STATE_RELEASE_BOMB = 6, - MINIBOMBER_STATE_TRAVERSE_PATH = 7, - MINIBOMBER_STATE_DESTROY = 9 - }; Data *d = moby->d; float v[12]; float *path_endpoint_target_position; @@ -654,10 +655,6 @@ void process_minibomber_hit_reactions(struct Moby *hit_owner_moby) { HIT_REACTION_FLASH_RED = 10, HIT_REACTION_NONE = 11 }; - enum { - MINIBOMBER_STATE_INITIALIZE = 0, - MINIBOMBER_STATE_DESTROY = 9 - }; unsigned char *moby_vars = hit_owner_moby->pvars; int loc0; float damage_amount; @@ -736,12 +733,6 @@ extern short minibomber_rotation_oscillation_second_phase_increment_gp __asm__(" void update_minibomber_oscillation(struct Moby *moby) __asm__("FUN_L14_002b5428"); void update_minibomber_oscillation(struct Moby *moby) { - enum { - MINIBOMBER_STATE_INITIALIZE = 0, - MINIBOMBER_STATE_WAIT_TO_FOLLOW_PATH = 1, - MINIBOMBER_STATE_TRAVERSE_PATH = 7, - MINIBOMBER_STATE_DESTROY = 9 - }; int raw = moby->state; unsigned char state = raw; char *minibomber_instance_vars = (char *)moby->pvars; @@ -784,10 +775,6 @@ extern int FUN_L00_0025ff38(float a, char *m, char *b, int c, int d, int *e, int void update_minibomber_target(struct Moby *moby) __asm__("FUN_L14_002b5530"); void update_minibomber_target(struct Moby *moby) { - enum { - MINIBOMBER_STATE_INITIALIZE = 0, - MINIBOMBER_STATE_DESTROY = 9 - }; char *minibomber_private_vars = (char *)moby->pvars; if (moby->state != MINIBOMBER_STATE_INITIALIZE && moby->state != MINIBOMBER_STATE_DESTROY) { int *bound_path = ((int *)l14_paths[*(int *)(minibomber_private_vars + 0xD4)]); @@ -900,10 +887,6 @@ void ease_minibomber_position_and_heading(char *moby, float heading_velocity_damping, float heading_velocity_limit) { - enum { - MINIBOMBER_STATE_HOLD_AT_PATH_END = 4, - MINIBOMBER_STATE_RELEASE_BOMB = 6 - }; int minibomber_private_vars_base; int moby_state = MOBY(moby)->state & 0xFF; if ((moby_state >= MINIBOMBER_STATE_HOLD_AT_PATH_END && @@ -1138,10 +1121,6 @@ void initialize_minibomber_path_following(struct Moby *moby) { void emit_minibomber_exhaust_puffs(struct Moby *moby) __asm__("FUN_L14_002b5dd8"); void emit_minibomber_exhaust_puffs(struct Moby *moby) { - enum { - MINIBOMBER_STATE_FOLLOW_INTRO_OR_EXIT_PATH = 2, - MINIBOMBER_STATE_DESTROY = 9 - }; float exhaust_position_offset[4]; float pos[4]; int i; diff --git a/src/overlays/l14/mobys/rocket_strike_fighter.c b/src/overlays/l14/mobys/rocket_strike_fighter.c index a88caf8f71..5165f0128f 100644 --- a/src/overlays/l14/mobys/rocket_strike_fighter.c +++ b/src/overlays/l14/mobys/rocket_strike_fighter.c @@ -84,12 +84,6 @@ void rocket_strike_fighter_update(struct Moby *moby) __asm__("FUN_L14_002fcbb0") /* Moby class 921 */ void rocket_strike_fighter_update(struct Moby *moby) { - enum { - ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE = 0, - ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS = 1, - ROCKET_STRIKE_FIGHTER_STATE_FOLLOW_PATH = 2, - ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN = 3 - }; enum { ROCKET_STRIKE_FIGHTER_MISSION_COMPLETE = 0xFF }; @@ -274,12 +268,14 @@ extern f32 rocket_strike_fighter_exhaust_grey_puff_row0_offset_gp __asm__("D_L14 #include "rnc/overlay/l14/mobys/rocket_strike_fighter_data/spawn_rocket_strike_fighter_exhaust.h" +enum { + ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE = 0, + ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS = 1, + ROCKET_STRIKE_FIGHTER_STATE_FOLLOW_PATH = 2, + ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN = 3 +}; + void spawn_rocket_strike_fighter_exhaust(struct Moby *moby) { - enum { - ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE = 0, - ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS = 1, - ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN = 3 - }; Vec4 step; Vec4 pos; Vec4 common_exhaust_origin; diff --git a/src/overlays/l14/mobys/taxi.c b/src/overlays/l14/mobys/taxi.c index ea15abfd63..4ddc1439cd 100644 --- a/src/overlays/l14/mobys/taxi.c +++ b/src/overlays/l14/mobys/taxi.c @@ -29,6 +29,16 @@ extern float cubic_hermite_scalar(float, float, float, float, float) __asm__("FU #include "rnc/overlay/l14/mobys/taxi_globals.h" +enum { + TAXI_STATE_INITIALIZE = 0, + TAXI_STATE_WAIT_AT_STOP = 1, + TAXI_STATE_BLEND_STOP_TO_PATH_START = 3, + TAXI_STATE_FOLLOW_PATH = 4, + TAXI_STATE_BLEND_PATH_END_TO_STOP = 5, + TAXI_STATE_WAIT_FOR_ITEM_GATE = 6, + TAXI_STATE_BLEND_SAVED_POSE_TO_PATH_START = 7 +}; + typedef struct { u8 pad0[0x20]; u8 spring[0x40]; /* 0x20 */ @@ -84,15 +94,6 @@ void taxi_update(struct Moby *moby) __asm__("FUN_L14_002f0538"); /* Moby class 712 */ void taxi_update(struct Moby *moby) { - enum { - TAXI_STATE_INITIALIZE = 0, - TAXI_STATE_WAIT_AT_STOP = 1, - TAXI_STATE_BLEND_STOP_TO_PATH_START = 3, - TAXI_STATE_FOLLOW_PATH = 4, - TAXI_STATE_BLEND_PATH_END_TO_STOP = 5, - TAXI_STATE_WAIT_FOR_ITEM_GATE = 6, - TAXI_STATE_BLEND_SAVED_POSE_TO_PATH_START = 7 - }; enum { TAXI_STATE_HIDDEN = 2 }; @@ -385,9 +386,6 @@ struct L14PickVars { }; void initialize_taxi_stop_from_position(struct Moby *moby) { - enum { - TAXI_STATE_WAIT_AT_STOP = 1 - }; struct L14PickVars *taxi_vars = (struct L14PickVars *)moby->pvars; int i; taxi_vars->picked = -1; @@ -473,9 +471,6 @@ struct Moby *find_group_moby_by_tag(struct Moby *moby, int tag) { extern void try_set_help_message(int, int) __asm__("FUN_00215130"); void request_taxi_stop_prompt(struct Moby *moby) { - enum { - TAXI_STATE_BLEND_PATH_END_TO_STOP = 5 - }; char *taxi_prompt_vars = (char *)moby->pvars; int taxi_stop_index = *(short *)(taxi_prompt_vars + 0xB4); if (moby->state == TAXI_STATE_BLEND_PATH_END_TO_STOP) { diff --git a/src/overlays/l15/hero/hero_set_state.c b/src/overlays/l15/hero/hero_set_state.c index 60a746cf1e..5e0da8f815 100644 --- a/src/overlays/l15/hero/hero_set_state.c +++ b/src/overlays/l15/hero/hero_set_state.c @@ -75,7 +75,8 @@ int hero_set_state(int requested_state, int entry_animation_mode) { { struct Hero *p = &hero; if (p->state.control_mode == 0x14 && - (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || entry_animation_mode != 2)) + (requested_state != HERO_STATE_IDLE_ANIMATION_WITH_DYING_OVERRIDE || + entry_animation_mode != 2)) return 0; } if ((D_L15_0015F5C4 == 2 || D_L15_0015F5C4 == 6) && entry_animation_mode != 2) diff --git a/src/overlays/l15/hero/update_hero_motion_for_current_state.c b/src/overlays/l15/hero/update_hero_motion_for_current_state.c index 7ddbd74aef..066fcba351 100644 --- a/src/overlays/l15/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l15/hero/update_hero_motion_for_current_state.c @@ -1174,7 +1174,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1197,7 +1198,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1487,7 +1489,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1579,7 +1582,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1644,7 +1648,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1744,7 +1749,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1862,7 +1868,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1977,7 +1984,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2160,7 +2168,8 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2177,7 +2186,8 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2510,7 +2520,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2527,7 +2538,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2561,7 +2573,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_2_REPEATABLE_SQUARE_ACTION: @@ -2668,7 +2681,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -2693,7 +2707,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_WAIT_FOR_CIRCLE_RELEASE_AND_ANIMATION: { @@ -2729,7 +2744,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2749,7 +2765,8 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); if (hero.motion.velocity.f[2] < frame_time * -10.0f) { hero.motion.velocity.f[2] = frame_time * -10.0f; } @@ -2821,7 +2838,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2858,7 +2876,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -2873,7 +2892,8 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -2906,7 +2926,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } diff --git a/src/overlays/l15/mobys/helicopter.c b/src/overlays/l15/mobys/helicopter.c index ea705c285e..89968cdacb 100644 --- a/src/overlays/l15/mobys/helicopter.c +++ b/src/overlays/l15/mobys/helicopter.c @@ -21,6 +21,18 @@ #include "rnc/overlay/l15/mobys/helicopter_globals.h" #include "rnc/overlay/shared/math/quad.h" +enum { + HELICOPTER_INITIALIZE = 0, + HELICOPTER_WAIT_FOR_ACTIVATION = 1, + HELICOPTER_FOLLOW_ENTRY_PATH = 2, + HELICOPTER_APPROACH_AREA_PATH = 3, + HELICOPTER_HOLD_POSITION_WAIT_FOR_TARGET = 4, + HELICOPTER_ENGAGE_AND_FIRE = 5, + HELICOPTER_RECOIL = 6, + HELICOPTER_DEATH_EFFECTS = 7, + HELICOPTER_DEAD_WAIT_FOR_RESET = 0x40 +}; + extern char D_L15_001673C0[]; extern char D_0014C190[]; @@ -388,17 +400,6 @@ void helicopter_update(struct Moby *moby) __asm__("FUN_L15_002c5630"); /* Moby class 233 */ void helicopter_update(struct Moby *moby) { - enum { - HELICOPTER_INITIALIZE = 0, - HELICOPTER_WAIT_FOR_ACTIVATION = 1, - HELICOPTER_FOLLOW_ENTRY_PATH = 2, - HELICOPTER_APPROACH_AREA_PATH = 3, - HELICOPTER_HOLD_POSITION_WAIT_FOR_TARGET = 4, - HELICOPTER_ENGAGE_AND_FIRE = 5, - HELICOPTER_RECOIL = 6, - HELICOPTER_DEATH_EFFECTS = 7, - HELICOPTER_DEAD_WAIT_FOR_RESET = 0x40 - }; enum { HELICOPTER_GOAL_UNAVAILABLE = 2 }; @@ -892,11 +893,6 @@ extern void trooper_anim_update(void *m, short *p) __asm__("FUN_L00_0025d458"); extern void trooper_anim_finish(void *, void *) __asm__("FUN_L00_0025d538"); void process_helicopter_hits(struct Moby *moby) { - enum { - HELICOPTER_RECOIL = 6, - HELICOPTER_DEATH_EFFECTS = 7, - HELICOPTER_DEAD_WAIT_FOR_RESET = 0x40 - }; enum { HIT_REACTION_SKIP_DAMAGE = 1 }; diff --git a/src/overlays/l15/mobys/quartu_cutscene_trigger.c b/src/overlays/l15/mobys/quartu_cutscene_trigger.c index 51b7445556..d47619aaa6 100644 --- a/src/overlays/l15/mobys/quartu_cutscene_trigger.c +++ b/src/overlays/l15/mobys/quartu_cutscene_trigger.c @@ -11,8 +11,10 @@ #include "rnc/overlay/shared/game/queue_planet_unlock_message.h" #include "rnc/overlay/shared/game/unlock_planet.h" #include "rnc/overlay/shared/hero/set_hero_animation.h" + void update_hero_item_moby_flags(void) __asm__("FUN_L00_002330d0"); void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); + #include "rnc/rendering/clip_volume.h" extern int D_L15_0015F5C4; diff --git a/src/overlays/l15/mobys/ultramech_unlimited.c b/src/overlays/l15/mobys/ultramech_unlimited.c index c0913bd415..7b8a92e228 100644 --- a/src/overlays/l15/mobys/ultramech_unlimited.c +++ b/src/overlays/l15/mobys/ultramech_unlimited.c @@ -269,20 +269,6 @@ void ultramech_unlimited_update(UMoby *m) __asm__("FUN_L15_002cf3a8"); /* Moby class 491 */ void ultramech_unlimited_update(UMoby *ultramech_moby) { - enum { - ULTRAMECH_INITIALIZE = 0, - ULTRAMECH_WAIT_FOR_ACTIVATION = 1, - ULTRAMECH_FOLLOW_ENTRY_PATH = 2, - ULTRAMECH_BALLISTIC_PATH_MOVE = 3, - ULTRAMECH_AIM_AND_SELECT_ATTACK = 4, - ULTRAMECH_FIRE_BURST = 5, - ULTRAMECH_WAIT_BETWEEN_BURSTS = 6, - ULTRAMECH_APPROACH_TARGET = 7, - ULTRAMECH_MELEE_ATTACK = 8, - ULTRAMECH_KNOCKBACK_RECOVERY = 9, - ULTRAMECH_DEATH_EFFECTS = 10, - ULTRAMECH_DEAD_WAIT_FOR_RESET = 0x40 - }; Vec4 vector_or_hit_descriptor; Vec4 position_or_motion_vector; Vec4 vector_arithmetic_result; @@ -926,6 +912,21 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { #include "rnc/overlay/l15/mobys/ultramech_unlimited_data/process_ultramech_hits_and_update_target.h" +enum { + ULTRAMECH_INITIALIZE = 0, + ULTRAMECH_WAIT_FOR_ACTIVATION = 1, + ULTRAMECH_FOLLOW_ENTRY_PATH = 2, + ULTRAMECH_BALLISTIC_PATH_MOVE = 3, + ULTRAMECH_AIM_AND_SELECT_ATTACK = 4, + ULTRAMECH_FIRE_BURST = 5, + ULTRAMECH_WAIT_BETWEEN_BURSTS = 6, + ULTRAMECH_APPROACH_TARGET = 7, + ULTRAMECH_MELEE_ATTACK = 8, + ULTRAMECH_KNOCKBACK_RECOVERY = 9, + ULTRAMECH_DEATH_EFFECTS = 10, + ULTRAMECH_DEAD_WAIT_FOR_RESET = 0x40 +}; + extern float ultramech_pre_hit_scale_multiplier_gp __asm__("D_L15_00161B2C") __attribute__((sda)); extern float ultramech_post_hit_scale_multiplier_gp __asm__("D_L15_00161B30") __attribute__((sda)); @@ -987,13 +988,6 @@ void process_ultramech_hits_and_update_target(void *ultramech_instance) { HIT_REACTION_DAMAGE_WITHOUT_KNOCKBACK_ALTERNATE = 10, HIT_REACTION_NONE = 11 }; - enum { - ULTRAMECH_WAIT_FOR_ACTIVATION = 1, - ULTRAMECH_FOLLOW_ENTRY_PATH = 2, - ULTRAMECH_KNOCKBACK_RECOVERY = 9, - ULTRAMECH_DEATH_EFFECTS = 10, - ULTRAMECH_DEAD_WAIT_FOR_RESET = 0x40 - }; enum { HIT_CLASSIFICATION_NO_DAMAGE = 1 }; diff --git a/src/overlays/l16/hero/apply_hero_ground_material_effects.c b/src/overlays/l16/hero/apply_hero_ground_material_effects.c index bf508491c9..0aad4458dd 100644 --- a/src/overlays/l16/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l16/hero/apply_hero_ground_material_effects.c @@ -26,14 +26,6 @@ extern int hero_set_state(int, int) __asm__("FUN_L16_0021e398"); void apply_hero_ground_material_effects(void) __asm__("FUN_L16_002097a0"); void apply_hero_ground_material_effects(void) { - enum { - GROUND_MATERIAL_WATER = 0, - GROUND_MATERIAL_MAGNET = 2 - }; - enum { - GROUND_MATERIAL_SINK_TRIGGER = 0xD, - GROUND_MATERIAL_FIXED_WATER_DEPTH = 0xE - }; struct Hero *hero_data = &hero; int keep = hero_data->ground_sound_class; int saved_ground_type = hero_data->ground_type; @@ -150,6 +142,16 @@ void apply_hero_ground_material_effects(void) { #include "qcopy.h" #include "rnc/overlay/shared/math/quad.h" +enum { + GROUND_MATERIAL_WATER = 0, + GROUND_MATERIAL_MAGNET = 2 +}; + +enum { + GROUND_MATERIAL_SINK_TRIGGER = 0xD, + GROUND_MATERIAL_FIXED_WATER_DEPTH = 0xE +}; + /* Ported from rac1-decomp (src/overlays/l16_kalebo3/help_00209D98.c: func_L16_0020FEC8), where it is exact; names translated to the US level program. */ extern void FUN_L00_0025f730(void *a, float x); @@ -196,12 +198,6 @@ extern CollisionHit HH __asm__("D_L16_00174240") NOT_SDA; void update_hero_ground_contact(void) __asm__("FUN_L16_0020ffb0"); void update_hero_ground_contact(void) { - enum { - GROUND_MATERIAL_WATER = 0 - }; - enum { - GROUND_MATERIAL_SINK_TRIGGER = 0xD - }; V_u collision_ray_endpoint, ground_probe_endpoint, ground_offset_or_angles, side_probe_endpoint, unused_side_probe_endpoint, probe_surface_angles, normalized_hit_normal; f32 f; diff --git a/src/overlays/l16/hero/update_hero_motion_for_current_state.c b/src/overlays/l16/hero/update_hero_motion_for_current_state.c index c173bd6079..e0dc43af8f 100644 --- a/src/overlays/l16/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l16/hero/update_hero_motion_for_current_state.c @@ -1027,7 +1027,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.velocity, -hero.board_vertical_speed); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 20.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 20.0f); } break; } @@ -1340,7 +1341,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -1363,7 +1365,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1650,7 +1653,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1736,7 +1740,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1801,7 +1806,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1901,7 +1907,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -2009,7 +2016,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2068,7 +2076,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2166,7 +2175,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2738,7 +2748,8 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2755,7 +2766,8 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -3084,7 +3096,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3101,7 +3114,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -3123,7 +3137,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -3138,7 +3153,8 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -3171,7 +3187,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } diff --git a/src/overlays/l16/mobys/bolt_thief.c b/src/overlays/l16/mobys/bolt_thief.c index c21df9f50e..c05a1d2edb 100644 --- a/src/overlays/l16/mobys/bolt_thief.c +++ b/src/overlays/l16/mobys/bolt_thief.c @@ -137,15 +137,6 @@ void bolt_thief_update(L16CrateMoby *moby) __asm__("FUN_L16_002e37a0"); /* Moby classes 452, 1401 */ void bolt_thief_update(L16CrateMoby *moby) { - enum { - BOLT_THIEF_INITIALIZE = 0, - BOLT_THIEF_FACE_HERO = 1, - BOLT_THIEF_WAIT_FOR_HERO_TRIGGER = 2, - BOLT_THIEF_SETTLE_AT_PATH_END = 3, - BOLT_THIEF_FOLLOW_PRIMARY_PATH = 4, - BOLT_THIEF_FOLLOW_OTHER_PATH = 5, - BOLT_THIEF_KNOCKBACK = 6 - }; enum { BOLT_THIEF_MODE_LINKED_MOBY_PATH_CYCLE = 0, BOLT_THIEF_MODE_SINGLE_PATH_THEN_FACE_HERO = 1, @@ -343,6 +334,16 @@ void bolt_thief_update(L16CrateMoby *moby) { #include "rnc/overlay/l16/mobys/bolt_thief_globals.h" +enum { + BOLT_THIEF_INITIALIZE = 0, + BOLT_THIEF_FACE_HERO = 1, + BOLT_THIEF_WAIT_FOR_HERO_TRIGGER = 2, + BOLT_THIEF_SETTLE_AT_PATH_END = 3, + BOLT_THIEF_FOLLOW_PRIMARY_PATH = 4, + BOLT_THIEF_FOLLOW_OTHER_PATH = 5, + BOLT_THIEF_KNOCKBACK = 6 +}; + extern float bolt_thief_path_speed_gp __asm__("D_L16_00161D90") __attribute__((sda)); extern float D_L16_00161D94_gp __asm__("D_L16_00161D94") __attribute__((sda)); extern float D_L16_00161D98_gp __asm__("D_L16_00161D98") __attribute__((sda)); @@ -350,9 +351,6 @@ extern int FUN_L00_0025d808_path54(char *, float *, float *, float *, int, float) __asm__("FUN_L00_0025d808"); int advance_bolt_thief_path(struct Moby *moby) { - enum { - BOLT_THIEF_FOLLOW_OTHER_PATH = 5 - }; float pos[4]; float delta[4]; char *bolt_thief_path_data = (char *)moby->pvars; diff --git a/src/overlays/l16/mobys/chicken_relocator.c b/src/overlays/l16/mobys/chicken_relocator.c index 44be6ebcb8..6726d8eb8c 100644 --- a/src/overlays/l16/mobys/chicken_relocator.c +++ b/src/overlays/l16/mobys/chicken_relocator.c @@ -59,6 +59,11 @@ extern void build_spherical_offset(float, float, float, void *) __asm__("FUN_00 #include "rnc/overlay/l16/mobys/chicken_relocator_globals.h" +enum { + TARGET_REPOSITION_STATE_REQUESTABLE = 1, + TARGET_REPOSITION_STATE_REQUESTED = 7 +}; + extern float reposition_effect_velocity_elevation_degrees_gp __asm__("D_L16_001618E8") __attribute__((sda)); extern float reposition_effect_velocity_scale_range_start_gp __asm__("D_L16_001618EC") @@ -154,10 +159,6 @@ int is_moby_in_state_6(Level16VendorMoby *moby) { void request_target_reposition(struct Moby *moby) __asm__("FUN_L16_002e0de0"); void request_target_reposition(struct Moby *moby) { - enum { - TARGET_REPOSITION_STATE_REQUESTABLE = 1, - TARGET_REPOSITION_STATE_REQUESTED = 7 - }; int state = TARGET_REPOSITION_STATE_REQUESTABLE; if (moby->state == state) { allocate_voice_for_target_entry(0, 0, moby); @@ -171,9 +172,6 @@ void request_target_reposition(struct Moby *moby) { int get_target_reposition_status(char *moby_or_private_data) __asm__("FUN_L16_002e0e28"); int get_target_reposition_status(char *moby_or_private_data) { - enum { - TARGET_REPOSITION_STATE_REQUESTED = 7 - }; unsigned char moby_state = moby_or_private_data[0x20]; moby_or_private_data = *(char **)(moby_or_private_data + 0x78); if (moby_state == TARGET_REPOSITION_STATE_REQUESTED || moby_state == 8) { diff --git a/src/overlays/l16/mobys/chomper.c b/src/overlays/l16/mobys/chomper.c index dcac5ba835..a0b3d8b1f0 100644 --- a/src/overlays/l16/mobys/chomper.c +++ b/src/overlays/l16/mobys/chomper.c @@ -91,14 +91,6 @@ typedef struct ChomperVars { /* Moby class 1445 */ void chomper_update(struct Moby *chomper_moby) { - enum { - CHOMPER_INITIALIZE = 0, - CHOMPER_WAIT_TO_APPROACH_TARGET = 1, - CHOMPER_APPROACH_TARGET = 4, - CHOMPER_FACE_TARGET = 5, - CHOMPER_RETURN_HOME = 6, - CHOMPER_KNOCKBACK = 8 - }; ChomperVars *chomper_data = (ChomperVars *)chomper_moby->pvars; update_chomper_hit_reaction_and_target(chomper_moby); FUN_L00_00263ac8(2.1f, (int)chomper_moby, 1, &chomper_data->unk220); @@ -244,6 +236,15 @@ typedef struct { #include "rnc/overlay/l16/mobys/chomper_globals.h" +enum { + CHOMPER_INITIALIZE = 0, + CHOMPER_WAIT_TO_APPROACH_TARGET = 1, + CHOMPER_APPROACH_TARGET = 4, + CHOMPER_FACE_TARGET = 5, + CHOMPER_RETURN_HOME = 6, + CHOMPER_KNOCKBACK = 8 +}; + extern float chomper_knockback_horizontal_speed_approach_rate_gp __asm__("D_L16_00161E58") __attribute__((sda)); extern float chomper_knockback_gravity_gp __asm__("D_L16_00161E54") __attribute__((sda)); @@ -254,10 +255,6 @@ extern void trooper_knockback_arc(void *, float *, void *, void *) __asm__("FUN extern void trooper_anim_update(void *m, short *p) __asm__("FUN_L00_0025d458"); void update_chomper_hit_reaction_and_target(void *chomper_instance) { - enum { - CHOMPER_INITIALIZE = 0, - CHOMPER_KNOCKBACK = 8 - }; L16PursuitMoby *chomper_moby = chomper_instance; L16PursuitData *pursuit_data = chomper_moby->data; char *hit; diff --git a/src/overlays/l16/mobys/test_dummy.c b/src/overlays/l16/mobys/test_dummy.c index e6ff7d0b86..e7391da55a 100644 --- a/src/overlays/l16/mobys/test_dummy.c +++ b/src/overlays/l16/mobys/test_dummy.c @@ -127,20 +127,6 @@ void test_dummy_update(unsigned char *m) __asm__("FUN_L16_002cddb8"); /* Moby class 541 */ void test_dummy_update(unsigned char *moby) { - enum { - TEST_DUMMY_STATE_INITIALIZE = 0, - TEST_DUMMY_STATE_IDLE = 1, - TEST_DUMMY_STATE_APPROACH_FIRST_PATH_NODE = 2, - TEST_DUMMY_STATE_APPROACH_THROW_NODE = 3, - TEST_DUMMY_STATE_THROW_AT_TARGET = 4, - TEST_DUMMY_STATE_MOVE_ALONG_PATH = 5, - TEST_DUMMY_STATE_TURN_TO_NEXT_PATH_NODE = 6, - TEST_DUMMY_STATE_APPROACH_SPRAY_NODE = 7, - TEST_DUMMY_STATE_SPRAY_FROM_CHILD = 8, - TEST_DUMMY_STATE_TURN_AND_RESUME_SAVED_STATE = 9, - TEST_DUMMY_STATE_BURST = 10, - TEST_DUMMY_STATE_RESPAWN = 11 - }; enum { TEST_DUMMY_KIND_THROWER = 0, TEST_DUMMY_KIND_PATH_MOVER = 1, @@ -532,12 +518,6 @@ extern void mark_moby_for_removal_c2(void *) __asm__("func_0020C828"); /* Per-frame update of a hit-point moby: handles a hit (respawn at the spawn point or removal when out of lives) and its state timers. */ void update_test_dummy_damage_and_respawn(void *moby) { - enum { - TEST_DUMMY_STATE_IDLE = 1, - TEST_DUMMY_STATE_TURN_AND_RESUME_SAVED_STATE = 9, - TEST_DUMMY_STATE_BURST = 10, - TEST_DUMMY_STATE_RESPAWN = 11 - }; enum { HIT_REACTION_STATUS_NO_DAMAGE = 1 }; @@ -694,6 +674,21 @@ extern char *D_L16_0015FFD8; extern void add_draw_callback(void (*)(void), void *) __asm__("FUN_001f4600"); #include "rnc/overlay/l16/mobys/test_dummy_globals.h" + +enum { + TEST_DUMMY_STATE_INITIALIZE = 0, + TEST_DUMMY_STATE_IDLE = 1, + TEST_DUMMY_STATE_APPROACH_FIRST_PATH_NODE = 2, + TEST_DUMMY_STATE_APPROACH_THROW_NODE = 3, + TEST_DUMMY_STATE_THROW_AT_TARGET = 4, + TEST_DUMMY_STATE_MOVE_ALONG_PATH = 5, + TEST_DUMMY_STATE_TURN_TO_NEXT_PATH_NODE = 6, + TEST_DUMMY_STATE_APPROACH_SPRAY_NODE = 7, + TEST_DUMMY_STATE_SPRAY_FROM_CHILD = 8, + TEST_DUMMY_STATE_TURN_AND_RESUME_SAVED_STATE = 9, + TEST_DUMMY_STATE_BURST = 10, + TEST_DUMMY_STATE_RESPAWN = 11 +}; /* spins the level's rotating parts by the current angle and queues the draw callback */ /* Ported from rac1-decomp (src/overlays/l16_kalebo3/vendor_002A50F0.c: func_L16_002D0238), where it is exact; names translated to the US level program. */ diff --git a/src/overlays/l17/hero/update_hero_motion_for_current_state.c b/src/overlays/l17/hero/update_hero_motion_for_current_state.c index be7f1bfccb..16646456d1 100644 --- a/src/overlays/l17/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l17/hero/update_hero_motion_for_current_state.c @@ -903,7 +903,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -926,7 +927,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1206,7 +1208,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1308,7 +1311,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1492,7 +1496,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1611,7 +1616,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1669,7 +1675,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1767,7 +1774,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1813,7 +1821,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); } else { hero.motion.velocity.f[2] = 0.0f; - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); } break; } @@ -2463,7 +2472,8 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2480,7 +2490,8 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2833,7 +2844,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2850,7 +2862,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2892,7 +2905,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_1_ATTACK: { @@ -2973,7 +2987,8 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_move_state_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); if (hero.motion.velocity.f[2] < frame_time * -10.0f) { hero.motion.velocity.f[2] = frame_time * -10.0f; } @@ -3009,7 +3024,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3102,7 +3118,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -3117,7 +3134,8 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_move_state_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -3150,7 +3168,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } diff --git a/src/overlays/l17/mobys/dreks_fleet_turret.c b/src/overlays/l17/mobys/dreks_fleet_turret.c index d529de15d6..4aa1f34884 100644 --- a/src/overlays/l17/mobys/dreks_fleet_turret.c +++ b/src/overlays/l17/mobys/dreks_fleet_turret.c @@ -20,6 +20,16 @@ #include "qzero.h" #include "rnc/overlay/l17/mobys.h" +enum { + FLEET_TURRET_INITIALIZE = 0, + FLEET_TURRET_DEPLETED = 1, + FLEET_TURRET_WAIT_FOR_TARGET = 1, + FLEET_TURRET_AIM_AND_FIRE_AT_ZONE = 2, + FLEET_TURRET_AIM_AND_FIRE_AT_HERO_SHIP = 3, + FLEET_TURRET_DESTROY = 4, + FLEET_TURRET_NOT_DEPLETED = 0xB +}; + extern int hit_reaction(void *, void *, void *, int, void *, void *, int, int) __asm__("FUN_L00_0025a478"); extern void trooper_anim_update(void *m, short *p) __asm__("FUN_L00_0025d458"); @@ -88,13 +98,6 @@ void dreks_fleet_turret_update(struct Moby *m) __asm__("FUN_L17_002cb310"); /* Moby class 347 */ void dreks_fleet_turret_update(struct Moby *turret_moby) { - enum { - FLEET_TURRET_INITIALIZE = 0, - FLEET_TURRET_WAIT_FOR_TARGET = 1, - FLEET_TURRET_AIM_AND_FIRE_AT_ZONE = 2, - FLEET_TURRET_AIM_AND_FIRE_AT_HERO_SHIP = 3, - FLEET_TURRET_DESTROY = 4 - }; float targeting_vector_scratch[4]; float from[4]; Vars347 *turret_vars = (Vars347 *)turret_moby->pvars; @@ -295,12 +298,6 @@ void dreks_fleet_turret_update(struct Moby *turret_moby) { void process_dreks_fleet_turret_hits(struct Moby *turret_moby) __asm__("FUN_L17_002cbc10"); void process_dreks_fleet_turret_hits(struct Moby *turret_moby) { - enum { - FLEET_TURRET_INITIALIZE = 0, - FLEET_TURRET_DEPLETED = 1, - FLEET_TURRET_DESTROY = 4, - FLEET_TURRET_NOT_DEPLETED = 0xB - }; enum { HIT_REACTION_NO_DAMAGE = 1 }; diff --git a/src/overlays/l17/mobys/fighter_jet.c b/src/overlays/l17/mobys/fighter_jet.c index 5f8266079a..0444c32583 100644 --- a/src/overlays/l17/mobys/fighter_jet.c +++ b/src/overlays/l17/mobys/fighter_jet.c @@ -771,9 +771,6 @@ extern int font_print_center_small(int, int, long, void *, int) __asm__("FUN_00 void draw_fighter_jet_hud(struct Moby *moby) __asm__("FUN_L17_002eb9a8"); void draw_fighter_jet_hud(struct Moby *moby) { - enum { - FIGHTER_JET_STATE_VICTORY_EXIT = 8 - }; char *ship_vars = (char *)moby->pvars; char *screen_dimensions; int locked_target_screen_x; @@ -1197,36 +1194,33 @@ void update_fighter_jet_flight(FighterJetMoby *ship_moby, FighterJetVars *ship_vars) __asm__("FUN_L17_002ec360"); void update_fighter_jet_flight(FighterJetMoby *ship_moby, FighterJetVars *ship_vars) { - enum { - FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY = 7 - }; - sceVu0FVECTOR pre_movement_ship_position; - sceVu0FVECTOR death_explosion_velocity; - UQ_c4 movement_delta; - sceVu0FVECTOR side; - UQ_c4 up; - sceVu0FVECTOR camera_rotation; - sceVu0FVECTOR target; - sceVu0FVECTOR target_record_sum_or_camera_local_offset; - float horizontal_steering_input; - float vertical_steering_input; - float ka; - float kb; - float lenA; - float lenB; - float distance_to_default_target; - float target_height_distance, target_height_distance_for_moby_pitch; - float x, y; - float half_fov, tn; - float ratio; - float collision_adjusted_pitch; - float k; + sceVu0FVECTOR pre_movement_ship_position; + sceVu0FVECTOR death_explosion_velocity; + UQ_c4 movement_delta; + sceVu0FVECTOR side; + UQ_c4 up; + sceVu0FVECTOR camera_rotation; + sceVu0FVECTOR target; + sceVu0FVECTOR target_record_sum_or_camera_local_offset; + float horizontal_steering_input; + float vertical_steering_input; + float ka; + float kb; + float lenA; + float lenB; + float distance_to_default_target; + float target_height_distance, target_height_distance_for_moby_pitch; + float x, y; + float half_fov, tn; + float ratio; + float collision_adjusted_pitch; + float k; struct PadState *pad; - struct Hero *steering_input_hero; - char *e; - char *collision_result; - int voice_slot_index; - int hc; + struct Hero *steering_input_hero; + char *e; + char *collision_result; + int voice_slot_index; + int hc; movement_delta.q = 0; up.q = 0; @@ -1742,6 +1736,17 @@ extern void FUN_L17_0021e530(int, int); #include "rnc/overlay/l17/mobys/fighter_jet_data/fighter_jet_update.h" +enum { + FIGHTER_JET_STATE_INITIALIZE = 0, + FIGHTER_JET_STATE_WAIT_FOR_BOARDING = 1, + FIGHTER_JET_STATE_BOARDING_FADE = 2, + FIGHTER_JET_STATE_PILOTED_FLIGHT = 4, + FIGHTER_JET_STATE_DISMOUNT = 5, + FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY = 7, + FIGHTER_JET_STATE_VICTORY_EXIT = 8, + FIGHTER_JET_STATE_FADE_THEN_REMOVE = 9 +}; + extern int D_L17_0015F608; extern char *fighter_jet_hp_bar_clut_lookup_base __asm__("D_L17_0015F420"); extern ShipLevelEntry l17_fighter_jet_hp_bar_clut_entries[] __asm__("D_L17_0016DA80"); @@ -1749,16 +1754,6 @@ void fighter_jet_update(ShipMoby *moby) __asm__("FUN_L17_002ed0 /* Moby class 1379 */ void fighter_jet_update(ShipMoby *moby) { - enum { - FIGHTER_JET_STATE_INITIALIZE = 0, - FIGHTER_JET_STATE_WAIT_FOR_BOARDING = 1, - FIGHTER_JET_STATE_BOARDING_FADE = 2, - FIGHTER_JET_STATE_PILOTED_FLIGHT = 4, - FIGHTER_JET_STATE_DISMOUNT = 5, - FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY = 7, - FIGHTER_JET_STATE_VICTORY_EXIT = 8, - FIGHTER_JET_STATE_FADE_THEN_REMOVE = 9 - }; ShipVars *ship_vars; ShipHit *hit; sceVu0FVECTOR dir; diff --git a/src/overlays/l18/hero/update_hero_motion_for_current_state.c b/src/overlays/l18/hero/update_hero_motion_for_current_state.c index 731178543e..a7dea1b0d9 100644 --- a/src/overlays/l18/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l18/hero/update_hero_motion_for_current_state.c @@ -876,7 +876,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -899,7 +900,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1207,7 +1209,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1306,7 +1309,8 @@ void update_hero_motion_for_current_state(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (window_end < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1371,7 +1375,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1471,7 +1476,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1589,7 +1595,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1650,7 +1657,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1748,7 +1756,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2350,7 +2359,8 @@ void update_hero_motion_for_current_state(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2367,7 +2377,8 @@ void update_hero_motion_for_current_state(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2561,8 +2572,8 @@ void update_hero_motion_for_current_state(void) { if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&general_vector_or_hit_descriptor_scratch, &hero.motion.pos); add_hero_up_offset(&general_vector_or_hit_descriptor_scratch, - &general_vector_or_hit_descriptor_scratch, - 0.5f); + &general_vector_or_hit_descriptor_scratch, + 0.5f); qcopy(&v10, &general_vector_or_hit_descriptor_scratch); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; v10.f[1] += fast_sin(hero.motion.rot.f[2]) * 0.85f; @@ -2706,7 +2717,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2724,7 +2736,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2758,7 +2771,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_2_REPEATABLE_SQUARE_ACTION: @@ -2865,7 +2879,8 @@ void update_hero_motion_for_current_state(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -2891,7 +2906,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_WAIT_FOR_CIRCLE_RELEASE_AND_ANIMATION: { @@ -2929,7 +2945,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2949,7 +2966,8 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); if (hero.motion.velocity.f[2] < frame_time * -10.0f) { hero.motion.velocity.f[2] = frame_time * -10.0f; } @@ -3021,7 +3039,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3058,7 +3077,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -3073,7 +3093,8 @@ void update_hero_motion_for_current_state(void) { if (hero.move_lock_timer == 0) { hero_update_hop_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -3106,7 +3127,8 @@ void update_hero_motion_for_current_state(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } diff --git a/src/overlays/l18/mobys/camera_transition.c b/src/overlays/l18/mobys/camera_transition.c index 621ad5f09c..cf35ecd05c 100644 --- a/src/overlays/l18/mobys/camera_transition.c +++ b/src/overlays/l18/mobys/camera_transition.c @@ -222,6 +222,11 @@ void boss_camera_transition_update(struct Moby *moby) { #include "qcopy.h" +enum { + CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP = 2, + CAMERA_TRANSITION_STATE_INTERPOLATE_TRANSITION = 3 +}; + extern int scale_game_frames(int); /* Ported from rac1-decomp (src/overlays/l18_veldin2/vendor_002A8400.c: func_L18_002E0E90), where it is exact; names translated to the US level program. */ @@ -246,9 +251,6 @@ void start_camera_transition(struct Moby *moby, int transition_delay_frames, int transition_mode) { - enum { - CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP = 2 - }; BossCameraTransitionVars *position_rotation_transition_vars = (BossCameraTransitionVars *)moby->pvars; *(int *)&position_rotation_transition_vars->unk60 = 0; @@ -290,10 +292,6 @@ float get_camera_transition_progress(Level18VendorFloatMoby *moby) { s32 classify_moby_state_two_or_three(const u8 *moby) __asm__("FUN_L18_002dfba0"); s32 classify_moby_state_two_or_three(const u8 *moby) { - enum { - CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP = 2, - CAMERA_TRANSITION_STATE_INTERPOLATE_TRANSITION = 3 - }; u32 state = MOBY(moby)->state; s32 state_classification = 2; diff --git a/src/overlays/l18/mobys/drek_boss_electric_ball.c b/src/overlays/l18/mobys/drek_boss_electric_ball.c index 8e5d5edd28..61833860c8 100644 --- a/src/overlays/l18/mobys/drek_boss_electric_ball.c +++ b/src/overlays/l18/mobys/drek_boss_electric_ball.c @@ -54,10 +54,6 @@ void drek_boss_electric_ball_update(struct Moby *moby) __asm__("FUN_L18_ /* Moby class 983 */ void drek_boss_electric_ball_update(struct Moby *moby) { - enum { - STATE_TIMED_REMOVAL_WAIT = 0, - STATE_TRAVEL_TO_TARGET = 1 - }; float *moby_vars = (float *)moby->pvars; float updated_rotation_angle = fast_add_rotations( moby_vars[0xB], target_effect_first_rotation_rate_degrees_gp * DEG_TO_RAD * frame_time); @@ -145,10 +141,6 @@ void refresh_moby_position_and_activate(struct Moby *moby, void refresh_moby_position_and_activate( struct Moby *moby, void *moby_position, void *position, int active, float speed) { - enum { - STATE_TIMED_REMOVAL_WAIT = 0, - STATE_TRAVEL_TO_TARGET = 1 - }; char *refreshed_moby_private_vars = (char *)moby->pvars; qcopy(&moby->pos, moby_position); *(int *)(refreshed_moby_private_vars + 0x28) = scale_game_frames(5); @@ -708,6 +700,11 @@ extern s32 D_L18_00162054_gp __asm__("D_L18_00162054") __attribute__((sda)); #include "rnc/overlay/l18/mobys/drek_boss_electric_ball_data/update_electric_bolt_geometry_and_particles.h" +enum { + STATE_TIMED_REMOVAL_WAIT = 0, + STATE_TRAVEL_TO_TARGET = 1 +}; + extern float primary_bolt_random_step_blend_weight_gp __asm__("D_L18_0016208C") __attribute__((sda)); extern short D_L18_001620B8[] MACRO_ADDR; diff --git a/src/overlays/l18/mobys/falling_moby_group.c b/src/overlays/l18/mobys/falling_moby_group.c index 2f83a342e5..040f2559fd 100644 --- a/src/overlays/l18/mobys/falling_moby_group.c +++ b/src/overlays/l18/mobys/falling_moby_group.c @@ -94,14 +94,6 @@ void falling_moby_group_update(struct Moby *moby) __asm__("FUN_L18_002f16f0"); /* Moby class 1381 */ void falling_moby_group_update(struct Moby *moby) { - enum { - MOBY_INITIALIZE = 0, - MOBY_APPROACH_TARGET_TRANSFORM = 2, - MOBY_FALL_AND_REMOVE = 4 - }; - enum { - FALLING_MOBY_GROUP_AWAIT_ACTIVATION = 1 - }; VData *moby_vars = (VData *)moby->pvars; if (moby_vars) { float initial_acceleration_step = group_transform_initial_acceleration_gp * frame_time_sq; @@ -251,13 +243,16 @@ extern void mark_block_entries_within_transform_xy_bounds(int, int) __asm__("FUN #include "rnc/overlay/l18/mobys/falling_moby_group.h" +enum { + MOBY_INITIALIZE = 0, + FALLING_MOBY_GROUP_AWAIT_ACTIVATION = 1, + MOBY_APPROACH_TARGET_TRANSFORM = 2, + MOBY_FALL_AND_REMOVE = 4 +}; + void activate_drek_boss_class_0565_moby(struct Moby *moby) __asm__("FUN_L18_002f1c38"); void activate_drek_boss_class_0565_moby(struct Moby *moby) { - enum { - FALLING_MOBY_GROUP_AWAIT_ACTIVATION = 1, - MOBY_APPROACH_TARGET_TRANSFORM = 2 - }; char *state = (char *)moby->pvars; if (moby->oclass == 0x565 && moby->state == FALLING_MOBY_GROUP_AWAIT_ACTIVATION) { if (*(int *)(state + 0xC) != -1) { @@ -294,9 +289,6 @@ typedef struct L18VD_1cc8 { void reset_drek_boss_falling_moby_group(L18VM_1cc8 *moby) __asm__("FUN_L18_002f1cc8"); void reset_drek_boss_falling_moby_group(L18VM_1cc8 *moby) { - enum { - FALLING_MOBY_GROUP_AWAIT_ACTIVATION = 1 - }; L18VD_1cc8 *data = moby->data; if (moby->class_id == 0x565) { moby->state = FALLING_MOBY_GROUP_AWAIT_ACTIVATION; diff --git a/src/overlays/l18/mobys/floating_platform.c b/src/overlays/l18/mobys/floating_platform.c index 5ae0ec6eb6..c706a5c364 100644 --- a/src/overlays/l18/mobys/floating_platform.c +++ b/src/overlays/l18/mobys/floating_platform.c @@ -37,6 +37,15 @@ extern float floating_platform_sink_trigger_distance_gp __asm__("D_L18_00161A5C" #include "rnc/overlay/l18/mobys/floating_platform_data/floating_platform_update.h" +enum { + STATE_INITIALIZE = 0, + STATE_WAIT_FOR_TILT_REQUEST = 1, + STATE_WAIT_FOR_SINK_REQUEST = 2, + STATE_TILT_DELAY = 3, + STATE_WAIT_FOR_SINK_TRIGGER = 4, + STATE_SINKING = 5 +}; + extern int D_L18_001623A8 __attribute__((sda)); void spawn_floating_platform_sparks(struct Moby *moby) __asm__("FUN_L18_002d88b8"); @@ -49,14 +58,6 @@ void floating_platform_update(struct Moby *moby) __asm__("FUN_L18_002d82c0"); /* Moby classes 481, 587, 810 */ void floating_platform_update(struct Moby *moby) { - enum { - STATE_INITIALIZE = 0, - STATE_WAIT_FOR_TILT_REQUEST = 1, - STATE_WAIT_FOR_SINK_REQUEST = 2, - STATE_TILT_DELAY = 3, - STATE_WAIT_FOR_SINK_TRIGGER = 4, - STATE_SINKING = 5 - }; char *floating_platform_update_private_vars; float delta[4] __attribute__((aligned(16))); float old_rot[4] __attribute__((aligned(16))); @@ -188,10 +189,6 @@ extern float floating_platform_bob_amplitude_gp __asm__("D_L18_00161A48") __attr extern float floating_platform_bob_phase_rate_gp __asm__("D_L18_00161A4C") __attribute__((sda)); void update_floating_platform_tilt_and_bob(struct Moby *moby) { - enum { - STATE_WAIT_FOR_SINK_TRIGGER = 4, - STATE_SINKING = 5 - }; char *floating_platform_private_vars = (char *)moby->pvars; float unclamped_rotation_y = fast_add_rotations(moby->rot.y, *(float *)(floating_platform_private_vars + 0x6C)); @@ -233,11 +230,6 @@ typedef struct { int request_floating_platform_sink(Level18State *platform_moby) __asm__("FUN_L18_002d8858"); int request_floating_platform_sink(Level18State *platform_moby) { - enum { - STATE_WAIT_FOR_TILT_REQUEST = 1, - STATE_WAIT_FOR_SINK_REQUEST = 2, - STATE_SINKING = 5 - }; if (platform_moby->state == STATE_WAIT_FOR_TILT_REQUEST) { return 1; } @@ -256,10 +248,6 @@ int request_floating_platform_tilt(struct Moby *platform_moby, int tilt_delay_frames, int scaled_frame_count) { - enum { - STATE_WAIT_FOR_TILT_REQUEST = 1, - STATE_TILT_DELAY = 3 - }; int *platform_vars = (int *)platform_moby->pvars; if (platform_moby->state == STATE_WAIT_FOR_TILT_REQUEST) { platform_moby->state = STATE_TILT_DELAY; diff --git a/src/overlays/l18/mobys/gadgebot.c b/src/overlays/l18/mobys/gadgebot.c index 9e6da5a1e8..2587e38508 100644 --- a/src/overlays/l18/mobys/gadgebot.c +++ b/src/overlays/l18/mobys/gadgebot.c @@ -72,19 +72,6 @@ void gadgebot_update(unsigned char *m) __asm__("FUN_L18_002fbb98"); /* Moby class 1906 */ void gadgebot_update(unsigned char *moby) { - enum { - GADGEBOT_INITIALIZE = 0, - GADGEBOT_LAUNCH_FLIGHT = 1, - GADGEBOT_WAIT_TO_APPROACH = 2, - GADGEBOT_APPROACH_TARGET = 3, - GADGEBOT_FACE_TARGET = 4, - GADGEBOT_DEATH_FALL = 5, - GADGEBOT_EXPLODE = 6, - GADGEBOT_SUCK_CANNON_SUCTION = 7 - }; - enum { - GADGEBOT_IDLE = 8 - }; char position_scratch[16]; unsigned char *moby_vars = ((unsigned char *)MOBY(moby)->pvars); unsigned char *moby_transform_ptr; @@ -300,17 +287,21 @@ extern float gadgebot_glow_state_4_or_5_phase_speed_degrees_per_second_gp __asm_ #include "rnc/overlay/l18/mobys/gadgebot_data/update_gadgebot_damage_target_and_glow.h" +enum { + GADGEBOT_INITIALIZE = 0, + GADGEBOT_LAUNCH_FLIGHT = 1, + GADGEBOT_TARGET_HERO = 2, + GADGEBOT_WAIT_TO_APPROACH = 2, + GADGEBOT_APPROACH_TARGET = 3, + GADGEBOT_FACE_TARGET = 4, + GADGEBOT_DEATH_FALL = 5, + GADGEBOT_EXPLODE = 6, + GADGEBOT_SUCK_CANNON_SUCTION = 7, + GADGEBOT_IDLE = 8 +}; + /* Sentry update: spins and tints the moby, takes hits (knockback, then a fall), and follows its path toward the hero. */ void update_gadgebot_damage_target_and_glow(struct Moby *moby) { - enum { - GADGEBOT_INITIALIZE = 0, - GADGEBOT_TARGET_HERO = 2, - GADGEBOT_FACE_TARGET = 4, - GADGEBOT_DEATH_FALL = 5, - GADGEBOT_EXPLODE = 6, - GADGEBOT_SUCK_CANNON_SUCTION = 7, - GADGEBOT_IDLE = 8 - }; SentryVars_c100 *sentry_vars = (SentryVars_c100 *)moby->pvars; union { u128 q; @@ -484,10 +475,6 @@ int launch_first_idle_group_class_0772_moby(int group, float speed) __asm__("FUN_L18_002fc668"); int launch_first_idle_group_class_0772_moby(int group, void *from, void *to, float speed) { - enum { - GADGEBOT_LAUNCH_FLIGHT = 1, - GADGEBOT_IDLE = 8 - }; unsigned short *group_moby_entry = (unsigned short *)D_L18_001AC240[group]; struct Moby *table; struct Moby *moby; @@ -525,9 +512,6 @@ int launch_first_idle_group_class_0772_moby(int group, void *from, void *to, flo short count_group_gadgebots_not_in_state_8(int group_index) __asm__("FUN_L18_002fc7e0"); short count_group_gadgebots_not_in_state_8(int group_index) { - enum { - GADGEBOT_IDLE = 8 - }; unsigned short *group_moby_entry = (unsigned short *)D_L18_001AC240[group_index]; short n = 0; int moby_table_address; @@ -661,10 +645,6 @@ int update_moby_suck_cannon_state(struct Moby *a) __asm__("FUN_L18_002fcbb0"); /* Method: holds the gadgebot in state 7 while the suck cannon pulls it, and puts it back to state 2 when it lets go. */ int update_moby_suck_cannon_state(struct Moby *moby) { - enum { - GADGEBOT_WAIT_TO_APPROACH = 0x2, - GADGEBOT_SUCK_CANNON_SUCTION = 0x7 - }; int suction_result = process_moby_suck_cannon_suction(moby); if (suction_result == 0) { if (moby->state == GADGEBOT_SUCK_CANNON_SUCTION) @@ -679,9 +659,6 @@ void hide_moby_and_clear_collision(struct Moby *moby) __asm__("FUN_L18_002fcd00" /* Method: sends the gadgebot back to its idle state 8, hidden and without collision. */ void hide_moby_and_clear_collision(struct Moby *moby) { - enum { - GADGEBOT_IDLE = 0x8 - }; unsigned short flags; moby->state = GADGEBOT_IDLE; if (moby->prev_seq != 0) { diff --git a/src/overlays/l18/mobys/mine.c b/src/overlays/l18/mobys/mine.c index 08c604f55d..b13f100423 100644 --- a/src/overlays/l18/mobys/mine.c +++ b/src/overlays/l18/mobys/mine.c @@ -36,16 +36,6 @@ void moby_568_update(struct Moby *moby) __asm__("FUN_L18_002d5918"); /* Moby class 568 */ void moby_568_update(struct Moby *moby) { - enum { - STATE_INITIALIZE = 0, - STATE_BALLISTIC_FLIGHT = 1, - STATE_POST_FLIGHT_SETTLING = 2, - STATE_APPROACH_NEARBY_TARGET = 3, - STATE_WAIT_TO_RESUME_APPROACH = 4 - }; - enum { - STATE_INACTIVE = 5 - }; char *class_238_update_private_vars = (char *)moby->pvars; float settling_displacement_or_steering_increment[4]; update_mine_detonation(moby); @@ -153,6 +143,18 @@ void moby_568_update(struct Moby *moby) { #include "sda.h" +enum { + STATE_INITIALIZE = 0, + STATE_BALLISTIC_FLIGHT = 1, + STATE_POST_FLIGHT_SETTLING = 2, + STATE_APPROACH_NEARBY_TARGET = 3, + STATE_WAIT_TO_RESUME_APPROACH = 4 +}; + +enum { + STATE_INACTIVE = 5 +}; + extern void allocate_voice_for_target_entry(int, int, int) __asm__("FUN_0022da68"); /* Ported from rac1-decomp (src/overlays/l18_veldin2/vendor_002A8400.c: func_L18_002D70E8), where it is exact; names translated to the US level program. */ @@ -373,9 +375,6 @@ extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); int update_moby_state_pause(struct Moby *moby) __asm__("FUN_L18_002d6108"); int update_moby_state_pause(struct Moby *moby) { - enum { - STATE_WAIT_TO_RESUME_APPROACH = 4 - }; char *moby_vars = (char *)moby->pvars; int state_pause_result = process_moby_suck_cannon_suction(moby); if (state_pause_result != 0) { @@ -407,9 +406,6 @@ extern int store_moby_in_suck_cannon(struct Moby *) __asm__("FUN_L00_002dbb20"); int moby_hold_state_while_active(struct Moby *moby) __asm__("FUN_L18_002d6190"); int moby_hold_state_while_active(struct Moby *moby) { - enum { - STATE_WAIT_TO_RESUME_APPROACH = 4 - }; int active = store_moby_in_suck_cannon(moby); if (active != 0) { moby->state = STATE_WAIT_TO_RESUME_APPROACH; @@ -424,9 +420,6 @@ int moby_hold_state_while_active(struct Moby *moby) { void hide_moby_and_disable_collision(struct Moby *moby) __asm__("FUN_L18_002d6280"); void hide_moby_and_disable_collision(struct Moby *moby) { - enum { - STATE_INACTIVE = 5 - }; unsigned short flags; moby->state = STATE_INACTIVE; if (moby->prev_seq != 0) { diff --git a/src/overlays/l18/mobys/thruster_pack_lock_red.c b/src/overlays/l18/mobys/thruster_pack_lock_red.c index 1950a93151..280dbaa98d 100644 --- a/src/overlays/l18/mobys/thruster_pack_lock_red.c +++ b/src/overlays/l18/mobys/thruster_pack_lock_red.c @@ -20,6 +20,12 @@ #include "rnc/math/random.h" #include "rnc/ui/frames/draw_ui_frame.h" +enum { + THRUSTER_PACK_LOCK_RED_STATE_APPROACH_CONFIGURED_HEIGHT = 1, + THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER = 2, + THRUSTER_PACK_LOCK_RED_STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT = 3 +}; + extern int scale_game_frames(int); extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); @@ -162,9 +168,6 @@ s32 allocate_voice_for_group_entry(s32 group_entry_index, void request_thruster_pack_lock_red_wait(struct Moby *moby, int value) __asm__("FUN_L18_002d7f68"); void request_thruster_pack_lock_red_wait(struct Moby *moby, int wait_duration_frames) { - enum { - THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER = 2 - }; char *red_lock_vars = (char *)moby->pvars; if (moby->state != THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER) { moby->state = THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER; @@ -179,10 +182,6 @@ void request_thruster_pack_lock_red_wait(struct Moby *moby, int wait_duration_fr void end_thruster_pack_lock_red_wait(struct Moby *moby) __asm__("FUN_L18_002d7fd0"); void end_thruster_pack_lock_red_wait(struct Moby *moby) { - enum { - THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER = 2, - THRUSTER_PACK_LOCK_RED_STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT = 3 - }; int *red_lock_private_vars = (int *)moby->pvars; if (moby->state == THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER) { int voice_slot_index; @@ -203,11 +202,6 @@ void end_thruster_pack_lock_red_wait(struct Moby *moby) { int poll_moby_state_and_rearm(struct Moby *moby) __asm__("FUN_L18_002d8050"); int poll_moby_state_and_rearm(struct Moby *moby) { - enum { - THRUSTER_PACK_LOCK_RED_STATE_APPROACH_CONFIGURED_HEIGHT = 1, - THRUSTER_PACK_LOCK_RED_STATE_WAIT_FOR_GROUNDED_HERO_TRIGGER = 2, - THRUSTER_PACK_LOCK_RED_STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT = 3 - }; int *moby_private_vars = (int *)moby->pvars; if (moby->state == THRUSTER_PACK_LOCK_RED_STATE_POST_WAIT_APPROACH_CONFIGURED_HEIGHT) { moby->state = THRUSTER_PACK_LOCK_RED_STATE_APPROACH_CONFIGURED_HEIGHT; diff --git a/src/overlays/shared/camera/grindrail_camera.c b/src/overlays/shared/camera/grindrail_camera.c index da0e347c3f..2a52f08a30 100644 --- a/src/overlays/shared/camera/grindrail_camera.c +++ b/src/overlays/shared/camera/grindrail_camera.c @@ -11,6 +11,12 @@ #include "rnc/camera/camera_spring.h" #include "sda.h" +enum { + CAMERA_PRESET_KIND_RAIL_SEGMENT_SYNC = 0, + CAMERA_PRESET_KIND_MAPPED_PATHS = 2, + CAMERA_PRESET_KIND_GRINDRAIL_PATH = 3 +}; + /* Camera blocks FUN_L01_00314e98 resets (camera + 0x70 and its preset row in l01_camera_preset_rows) */ typedef struct { Vec4 pos; /* 0x00 */ @@ -115,10 +121,6 @@ extern s32 FUN_L00_0025df68(void *, void *, void *, s32 *, f32 *, s void reset_camera_state_and_prepare_preset_paths(Camera *destination_camera) __asm__("FUN_L01_00314e98"); void reset_camera_state_and_prepare_preset_paths(Camera *destination_camera) { - enum { - CAMERA_PRESET_KIND_MAPPED_PATHS = 2, - CAMERA_PRESET_KIND_GRINDRAIL_PATH = 3 - }; Vec4 at; s32 seg; f32 path_fraction_or_length; @@ -311,10 +313,6 @@ extern int current_level_index_macro __asm__("D_0015ED84") MACRO_ADDR; void update_camera_position_and_orientation_from_paths(Cam *cam) __asm__("FUN_L01_00315358"); void update_camera_position_and_orientation_from_paths(Cam *camera_to_update) { - enum { - CAMERA_PRESET_KIND_RAIL_SEGMENT_SYNC = 0, - CAMERA_PRESET_KIND_MAPPED_PATHS = 2 - }; float camera_goal[4]; float look_offset[4]; float look_dir[4]; @@ -550,9 +548,6 @@ extern OvlVec4 D_0013F3D0_315de0 __asm__("D_0013F3D0"); void initialize_camera_transform_and_paths(Camera *destination_camera) __asm__("FUN_L01_00315de0"); void initialize_camera_transform_and_paths(Camera *destination_camera) { - enum { - CAMERA_PRESET_KIND_GRINDRAIL_PATH = 3 - }; CameraPresetRow *rows = l01_camera_preset_rows; Camera *source_camera = D_L01_00167284; CameraPreset *camera_preset = rows[destination_camera->preset].preset; diff --git a/src/overlays/shared/camera/hoverboard_camera.c b/src/overlays/shared/camera/hoverboard_camera.c index e30796dfc9..e913ab8bd8 100644 --- a/src/overlays/shared/camera/hoverboard_camera.c +++ b/src/overlays/shared/camera/hoverboard_camera.c @@ -16,6 +16,11 @@ #include "rnc/overlay/shared/camera/init_camera_system.h" #include "rnc/camera/camera_spring.h" +enum { + CAMERA_ORBIT_MODE_FOLLOW = 0, + CAMERA_ORBIT_MODE_ORBITING = 1 +}; + /* Sets up a moby's vector from the level table and clamps its height for the current state. */ /* Ported from rac1-decomp (src/overlays/shared/vendor_002CF2C0.c: func_L05_0032A868), where it is exact; names translated to the US level program. */ @@ -243,9 +248,6 @@ extern CameraPresetRow *D_L05_0015EF50; void reset_hero_follow_camera_from_preset(Camera *camera_to_reset) __asm__("FUN_L05_003296e0"); void reset_hero_follow_camera_from_preset(Camera *camera_to_reset) { - enum { - CAMERA_ORBIT_MODE_FOLLOW = 0 - }; CameraPreset *preset = D_L05_0015EF50[camera_to_reset->preset].preset; CameraOrbit *orbit_state; CameraFocus *focus; @@ -314,10 +316,6 @@ extern float FUN_001ebd78(void *, float, float, float, float, float); void update_hero_follow_camera_orbit(Camera *cam) __asm__("FUN_L05_003298d8"); void update_hero_follow_camera_orbit(Camera *hero_follow_camera) { - enum { - CAMERA_ORBIT_MODE_FOLLOW = 0, - CAMERA_ORBIT_MODE_ORBITING = 1 - }; Vec4 up; Vec4 side; Vec4 fwd; @@ -482,9 +480,6 @@ extern float D_L05_00174278 NOT_SDA; void update_orbit_camera_position(Camera_32B1F8 *camera) __asm__("FUN_L05_00329ce8"); void update_orbit_camera_position(Camera_32B1F8 *camera) { - enum { - CAMERA_ORBIT_MODE_FOLLOW = 0 - }; V_32B1F8 down; V_32B1F8 focus; V_32B1F8 rel; diff --git a/src/overlays/shared/camera/swing_volume_camera.c b/src/overlays/shared/camera/swing_volume_camera.c index c4b0bf0ae4..7fb4235947 100644 --- a/src/overlays/shared/camera/swing_volume_camera.c +++ b/src/overlays/shared/camera/swing_volume_camera.c @@ -15,6 +15,14 @@ #include "rnc/overlay/shared/rendering/culling/test_point_in_transformed_unit_cylinder.h" #include "rnc/rendering/clip_volume.h" +enum { + SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END = 1, + SWING_CAMERA_TYPE_ONE_FRAME_SWING = 3, + SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST = 4, + SWING_CAMERA_TYPE_SNAP_ON_ENTRY = 5, + SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END = 10 +}; + typedef float CameraVec[4] __attribute__((aligned(16))); /* Parameters of a swing camera. */ @@ -90,9 +98,6 @@ f32 D_L17_001677B4 NOT_SDA = 0; s32 volume_camera_swing_active(struct UpdateCam *cam) __asm__("FUN_L00_002ec7e8"); s32 volume_camera_swing_active(struct UpdateCam *swing_camera_record) { - enum { - SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST = 4 - }; SwingCameraParams *params; s32 forced = 0; u16 type; @@ -133,13 +138,6 @@ s32 volume_camera_swing_active(struct UpdateCam *swing_camera_record) { void volume_camera_swing(struct UpdateCam *cam) __asm__("FUN_L00_002ec988"); void volume_camera_swing(struct UpdateCam *swing_camera_record) { - enum { - SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END = 1, - SWING_CAMERA_TYPE_ONE_FRAME_SWING = 3, - SWING_CAMERA_TYPE_RETAIN_ON_CAMERA_REQUEST = 4, - SWING_CAMERA_TYPE_SNAP_ON_ENTRY = 5, - SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END = 10 - }; enum { SWING_CAMERA_TYPE_REQUIRE_ZERO_FOLLOW_MODE = 6, SWING_CAMERA_TYPE_REQUIRE_NONZERO_FOLLOW_MODE = 8, @@ -382,10 +380,6 @@ void volume_camera_swing(struct UpdateCam *swing_camera_record) { s32 volume_camera_swing_check(struct UpdateCam *cam) __asm__("FUN_L00_002ed230"); s32 volume_camera_swing_check(struct UpdateCam *swing_camera_record) { - enum { - SWING_CAMERA_TYPE_SLIDE_RELEASE_ANGLE_AT_END = 1, - SWING_CAMERA_TYPE_SLIDE_KEEP_ANGLE_AT_END = 10 - }; SwingCameraParams *params = camera_descriptors[swing_camera_record->descriptor_index].params; if (params->l_buttons_end == 1 && params->done != 0) return 0; diff --git a/src/overlays/shared/enemies/armed_transport.c b/src/overlays/shared/enemies/armed_transport.c index 720551c238..913403455a 100644 --- a/src/overlays/shared/enemies/armed_transport.c +++ b/src/overlays/shared/enemies/armed_transport.c @@ -17,6 +17,18 @@ #include "rnc/overlay/shared/mobys/test_path_segment_strict_crossing.h" #include "rnc/overlay/shared/math/random/random_int_between.h" +enum { + ARMED_TRANSPORT_STATE_INITIALIZE = 0, + ARMED_TRANSPORT_STATE_WAIT_FOR_ACTIVATION = 1, + ARMED_TRANSPORT_STATE_FOLLOW_FIRST_PATH = 2, + ARMED_TRANSPORT_STATE_RELEASE_PASSENGERS = 3, + ARMED_TRANSPORT_STATE_ALIGN_SECOND_PATH = 4, + ARMED_TRANSPORT_STATE_FOLLOW_SECOND_PATH = 5, + ARMED_TRANSPORT_STATE_TRACK_TARGET = 6, + ARMED_TRANSPORT_STATE_SPAWN_DIRECTED_MOBY = 7, + ARMED_TRANSPORT_STATE_DYING = 8 +}; + typedef struct ArmedTransportVars { u8 pad0[0x20]; f32 health; @@ -160,17 +172,6 @@ void armed_transport_update(char *m) __asm__("FUN_L16_002e22d8"); /* Moby class 1356 */ void armed_transport_update(char *transport_moby) { - enum { - ARMED_TRANSPORT_STATE_INITIALIZE = 0, - ARMED_TRANSPORT_STATE_WAIT_FOR_ACTIVATION = 1, - ARMED_TRANSPORT_STATE_FOLLOW_FIRST_PATH = 2, - ARMED_TRANSPORT_STATE_RELEASE_PASSENGERS = 3, - ARMED_TRANSPORT_STATE_ALIGN_SECOND_PATH = 4, - ARMED_TRANSPORT_STATE_FOLLOW_SECOND_PATH = 5, - ARMED_TRANSPORT_STATE_TRACK_TARGET = 6, - ARMED_TRANSPORT_STATE_SPAWN_DIRECTED_MOBY = 7, - ARMED_TRANSPORT_STATE_DYING = 8 - }; L16TransportVector vector, rotation; ArmedTransportVars *transport_data = (ArmedTransportVars *)MOBY(transport_moby)->pvars; @@ -444,9 +445,6 @@ void armed_transport_update(char *transport_moby) { /* Update interaction ownership, damage responses and pursuit tracking. */ void update_armed_transport_damage_and_targeting(struct Moby *transport_moby) { - enum { - ARMED_TRANSPORT_STATE_DYING = 8 - }; enum { HIT_REACTION_STATUS_SKIP_DAMAGE_RESPONSE = 1 }; diff --git a/src/overlays/shared/enemies/armed_transport_rocket.c b/src/overlays/shared/enemies/armed_transport_rocket.c index 2ae64126b2..2a27f34b6e 100644 --- a/src/overlays/shared/enemies/armed_transport_rocket.c +++ b/src/overlays/shared/enemies/armed_transport_rocket.c @@ -11,6 +11,10 @@ #include "rnc/math/random.h" #include "rnc/overlay/shared/enemies/blarg_elite_commando_rocket.h" +enum { + ARMED_TRANSPORT_ROCKET_STATE_FLYING = 0 +}; + extern char *create_moby(int); extern int trooper_play_sound(int, int, int, int) __asm__("FUN_L00_0028dc90"); extern void @@ -55,9 +59,6 @@ void armed_transport_rocket_update(char *m) __asm__("FUN_L16_002a0a98"); /* Moby class 50 */ void armed_transport_rocket_update(char *rocket_moby) { - enum { - ARMED_TRANSPORT_ROCKET_STATE_FLYING = 0 - }; float desired[4], next_position[4], delta[4], blend[4]; char *rocket_data = ((char *)MOBY(rocket_moby)->pvars); void *remaining; @@ -137,9 +138,6 @@ char *spawn_armed_transport_rocket(char *spawning_moby, int blend_duration_ticks, float unused) { - enum { - ARMED_TRANSPORT_ROCKET_STATE_FLYING = 0 - }; char *spawned_moby = (char *)create_moby(0x32); char *moby_data; float initial_movement_length, x, random_angle_radians, y; diff --git a/src/overlays/shared/enemies/blarg_elite_commando.c b/src/overlays/shared/enemies/blarg_elite_commando.c index 14c39be21f..5e6337434a 100644 --- a/src/overlays/shared/enemies/blarg_elite_commando.c +++ b/src/overlays/shared/enemies/blarg_elite_commando.c @@ -23,6 +23,23 @@ #include "rnc/overlay/shared/math/random/random_int_between.h" #include "rnc/overlay/shared/rendering/effects/update_three_phase_effect_particle.h" +enum { + COMMANDO_PURSUIT_MODE_DISABLED = 2 +}; + +enum { + COMMANDO_STATE_INITIALIZE = 0, + COMMANDO_STATE_RETURN_TO_INITIAL_POSITION = 1, + COMMANDO_STATE_IDLE = 2, + COMMANDO_STATE_MOVE_TO_PATROL_NODE = 3, + COMMANDO_STATE_PREPARE_ROCKET_FIRE = 4, + COMMANDO_STATE_FIRE_ROCKETS = 5, + COMMANDO_STATE_MOVE_TO_ATTACK_NODE = 7, + COMMANDO_STATE_KNOCKBACK_RECOVERY = 8, + COMMANDO_STATE_FATAL_FALL = 9, + COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM = 10 +}; + typedef struct L16DamageData { u8 pad0[0x20]; float health; @@ -207,21 +224,6 @@ void blarg_elite_commando_update(char *m) __asm__("FUN_L16_002d2cf0"); /* Moby class 638 */ void blarg_elite_commando_update(char *commando_moby) { - enum { - COMMANDO_STATE_INITIALIZE = 0, - COMMANDO_STATE_RETURN_TO_INITIAL_POSITION = 1, - COMMANDO_STATE_IDLE = 2, - COMMANDO_STATE_MOVE_TO_PATROL_NODE = 3, - COMMANDO_STATE_PREPARE_ROCKET_FIRE = 4, - COMMANDO_STATE_FIRE_ROCKETS = 5, - COMMANDO_STATE_MOVE_TO_ATTACK_NODE = 7, - COMMANDO_STATE_KNOCKBACK_RECOVERY = 8, - COMMANDO_STATE_FATAL_FALL = 9, - COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM = 10 - }; - enum { - COMMANDO_PURSUIT_MODE_DISABLED = 2 - }; float target[4], scratch_vector[4], delta[4]; L16DamageData *commando_data = (L16DamageData *)MOBY(commando_moby)->pvars; char *source, *aim_target_moby; @@ -684,10 +686,6 @@ void start_blarg_elite_commando_return_to_initial_position( void start_blarg_elite_commando_return_to_initial_position(struct Moby *moby, int return_countdown_ticks) { - enum { - COMMANDO_STATE_RETURN_TO_INITIAL_POSITION = 1, - COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM = 10 - }; L16DamageData *commando_data = (L16DamageData *)moby->pvars; if (moby->state == COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM) { moby->state = COMMANDO_STATE_RETURN_TO_INITIAL_POSITION; @@ -856,9 +854,6 @@ void emit_blarg_elite_commando_death_particles(void *moby) { /* Aim paired joints toward the owner or player, then smooth their rotations. */ /* Ported from rac1-decomp (src/overlays/shared/vendor_002A1B58.c: func_L16_002D5958), where it is exact; names translated to the US level program. */ void update_blarg_elite_commando_joint_aim(char *commando_moby) { - enum { - COMMANDO_PURSUIT_MODE_DISABLED = 2 - }; float position[4], target[4], matrix[16], delta[4], aim[4], aimDelta[4], velocity[4]; L16DamageData *commando_data = (L16DamageData *)MOBY(commando_moby)->pvars; if (commando_data->pursuit_mode != COMMANDO_PURSUIT_MODE_DISABLED) { @@ -924,9 +919,6 @@ void update_blarg_elite_commando_joint_aim(char *commando_moby) { /* Emit randomized joint particles while the moby is active. */ /* Ported from rac1-decomp (src/overlays/shared/vendor_002A1B58.c: func_L16_002D5CD0), where it is exact; names translated to the US level program. */ void emit_blarg_elite_commando_joint_sparks(char *commando_moby) { - enum { - COMMANDO_STATE_FOLLOW_PARENT_TRANSFORM = 10 - }; float matrix[16], velocity[4], acceleration[4], scatter[4]; int i; if (MOBY(commando_moby)->visible == 0 || diff --git a/src/overlays/shared/enemies/blarg_elite_commando_rocket.c b/src/overlays/shared/enemies/blarg_elite_commando_rocket.c index ad449c5fff..97fd7775ea 100644 --- a/src/overlays/shared/enemies/blarg_elite_commando_rocket.c +++ b/src/overlays/shared/enemies/blarg_elite_commando_rocket.c @@ -12,6 +12,10 @@ #include "sda.h" #include "rnc/overlay/shared/enemies/blarg_elite_commando_rocket_data/spawn_rocket_trail_spark.h" +enum { + BLARG_ELITE_COMMANDO_ROCKET_STATE_FLYING = 0 +}; + extern int scale_game_frames(int); extern float scale_time(float) __asm__("FUN_001f96b0"); @@ -72,9 +76,6 @@ void blarg_elite_commando_rocket_update(unsigned char *m) __asm__("FUN_L15_0029a /* Moby class 49 */ void blarg_elite_commando_rocket_update(unsigned char *moby) { - enum { - BLARG_ELITE_COMMANDO_ROCKET_STATE_FLYING = 0 - }; char *rocket_data = ((char *)MOBY(moby)->pvars); float rocket_next_position[4]; float back[4]; @@ -176,9 +177,6 @@ char *spawn_blarg_elite_commando_rocket(char *firing_commando_moby, float *initial_movement_vector, char *spawn_position) { - enum { - BLARG_ELITE_COMMANDO_ROCKET_STATE_FLYING = 0 - }; char *moby = create_moby(0x31); if (moby != 0) { char *spawned_rocket_data; diff --git a/src/overlays/shared/enemies/blarg_helicopter.c b/src/overlays/shared/enemies/blarg_helicopter.c index c0d67448c2..4d75d18575 100644 --- a/src/overlays/shared/enemies/blarg_helicopter.c +++ b/src/overlays/shared/enemies/blarg_helicopter.c @@ -17,6 +17,15 @@ #include "rnc/overlay/shared/world/level_path.h" #include "rnc/math/random.h" +enum { + BLARG_HELICOPTER_INITIALIZE = 0, + BLARG_HELICOPTER_ACTIVATION_PATH = 1, + BLARG_HELICOPTER_PATROL_AND_ATTACK = 2, + BLARG_HELICOPTER_EXIT = 3, + BLARG_HELICOPTER_TIMED_REACTION = 4, + BLARG_HELICOPTER_DESTROY = 5 +}; + typedef float HVec49_2CDDC8[4] __attribute__((aligned(16))); typedef unsigned int HQuad49_2CDDC8 __attribute__((mode(TI))); @@ -200,14 +209,6 @@ void blarg_helicopter_update(HMob49 *moby) __asm__("FUN_L03_002cca00"); /* Moby classes 326, 631 */ void blarg_helicopter_update(HMob49 *moby) { - enum { - BLARG_HELICOPTER_INITIALIZE = 0, - BLARG_HELICOPTER_ACTIVATION_PATH = 1, - BLARG_HELICOPTER_PATROL_AND_ATTACK = 2, - BLARG_HELICOPTER_EXIT = 3, - BLARG_HELICOPTER_TIMED_REACTION = 4, - BLARG_HELICOPTER_DESTROY = 5 - }; enum { MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 253, MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 254 @@ -862,10 +863,6 @@ void blarg_helicopter_update(HMob49 *moby) { /* Ported from rac1-decomp (src/overlays/shared/vendor_00292AC0.c: func_L03_002CF600), where it is exact; names translated to the US level program. */ void handle_blarg_helicopter_hits(char *helicopter_moby) { - enum { - BLARG_HELICOPTER_TIMED_REACTION = 4, - BLARG_HELICOPTER_DESTROY = 5 - }; enum { HIT_REACTION_SKIP_DAMAGE = 1 }; diff --git a/src/overlays/shared/enemies/blarg_space_commando.c b/src/overlays/shared/enemies/blarg_space_commando.c index 808e0bdebb..e9458e85e8 100644 --- a/src/overlays/shared/enemies/blarg_space_commando.c +++ b/src/overlays/shared/enemies/blarg_space_commando.c @@ -129,21 +129,6 @@ void blarg_space_commando_update(struct Moby *moby) __asm__("FUN_L06_002fdbd0"); /* Moby class 1068 */ void blarg_space_commando_update(struct Moby *moby) { - enum { - BLARG_COMMANDO_STATE_INITIALIZE = 0, - BLARG_COMMANDO_STATE_SELECT_ACTION = 1, - BLARG_COMMANDO_STATE_RANGED_ATTACK_WINDUP = 2, - BLARG_COMMANDO_STATE_RANGED_ATTACK_RECOVERY = 3, - BLARG_COMMANDO_STATE_RANGED_ATTACK_COOLDOWN = 4, - BLARG_COMMANDO_STATE_MELEE_ATTACK = 5, - BLARG_COMMANDO_STATE_MELEE_RECOVERY = 6, - BLARG_COMMANDO_STATE_CHASE_TARGET = 11, - BLARG_COMMANDO_STATE_CHASE_MELEE_ATTACK = 12, - BLARG_COMMANDO_STATE_RETURN_HOME = 13, - BLARG_COMMANDO_STATE_APPROACH_ROUTE_DESTINATION = 14, - BLARG_COMMANDO_STATE_KNOCKBACK = 15, - BLARG_COMMANDO_STATE_DEATH_KNOCKBACK = 16 - }; Moby1068Vars *blarg_commando_state = (Moby1068Vars *)moby->pvars; struct Moby *target; s32 *route; @@ -555,6 +540,22 @@ extern char *FUN_L06_00300c60_c(int unused, char *pa, char *pb) __asm__("FUN_L06 #include "rnc/data_labels.h" +enum { + BLARG_COMMANDO_STATE_INITIALIZE = 0, + BLARG_COMMANDO_STATE_SELECT_ACTION = 1, + BLARG_COMMANDO_STATE_RANGED_ATTACK_WINDUP = 2, + BLARG_COMMANDO_STATE_RANGED_ATTACK_RECOVERY = 3, + BLARG_COMMANDO_STATE_RANGED_ATTACK_COOLDOWN = 4, + BLARG_COMMANDO_STATE_MELEE_ATTACK = 5, + BLARG_COMMANDO_STATE_MELEE_RECOVERY = 6, + BLARG_COMMANDO_STATE_CHASE_TARGET = 11, + BLARG_COMMANDO_STATE_CHASE_MELEE_ATTACK = 12, + BLARG_COMMANDO_STATE_RETURN_HOME = 13, + BLARG_COMMANDO_STATE_APPROACH_ROUTE_DESTINATION = 14, + BLARG_COMMANDO_STATE_KNOCKBACK = 15, + BLARG_COMMANDO_STATE_DEATH_KNOCKBACK = 16 +}; + extern f32 D_0015ED6C; extern float FUN_L04_001f1978(float); extern float randf_sym(float lo, float hi) __asm__("FUN_L00_00257c48"); @@ -592,10 +593,6 @@ void process_blarg_space_commando_hits(char *moby) { SIXTY_FRAME_KNOCKBACK_HIT_RESPONSE = 10, HIT_RESPONSE_PRESERVING_MOBY_STATE = 11 }; - enum { - BLARG_COMMANDO_STATE_KNOCKBACK = 0xF, - BLARG_COMMANDO_STATE_DEATH_KNOCKBACK = 0x10 - }; extern unsigned char D_0013D408[]; char *commando_state; char *hit_record; diff --git a/src/overlays/shared/enemies/bolt_thief_mine.c b/src/overlays/shared/enemies/bolt_thief_mine.c index 7ae6bf1e18..1a31476932 100644 --- a/src/overlays/shared/enemies/bolt_thief_mine.c +++ b/src/overlays/shared/enemies/bolt_thief_mine.c @@ -41,6 +41,12 @@ extern char *floating_mine_respawn_address_limit __asm__("D_L14_0015FFDC"); #include "rnc/overlay/shared/enemies/bolt_thief_mine_data/bolt_thief_mine_update.h" +enum { + FLOAT_MINE_INITIALIZE = 0, + FLOAT_MINE_ACTIVE = 1, + FLOAT_MINE_WAIT_OFFSCREEN_RESPAWN = 2 +}; + extern float probe_ground_height(float, void *, int) __asm__("FUN_00213508"); extern int resolve_moby_hit_response( struct Moby *, MobyHit *, HitInfo *, int, int *, int, int, int) __asm__("FUN_00213928"); @@ -68,11 +74,6 @@ void bolt_thief_mine_update(struct Moby *moby) __asm__("FUN_L14_002ff640"); /* Moby class 933 */ void bolt_thief_mine_update(struct Moby *moby) { - enum { - FLOAT_MINE_INITIALIZE = 0, - FLOAT_MINE_ACTIVE = 1, - FLOAT_MINE_WAIT_OFFSCREEN_RESPAWN = 2 - }; FloatMineVars *floating_mine_private_vars = (FloatMineVars *)moby->pvars; union { HitInfo info; @@ -206,9 +207,6 @@ unsigned char *spawn_bolt_thief_mine(unsigned char *owner, char *spawn_position) __asm__("FUN_L14_002ffaf8"); unsigned char *spawn_bolt_thief_mine(unsigned char *spawning_moby, char *spawn_position) { - enum { - FLOAT_MINE_INITIALIZE = 0 - }; unsigned char *spawned_moby = create_moby(0x3A5); if (spawned_moby != 0) { char *spawned_vars = ((char *)MOBY(spawned_moby)->pvars); diff --git a/src/overlays/shared/enemies/bomb_spawner_bomb.c b/src/overlays/shared/enemies/bomb_spawner_bomb.c index df5928ad3a..46c67787af 100644 --- a/src/overlays/shared/enemies/bomb_spawner_bomb.c +++ b/src/overlays/shared/enemies/bomb_spawner_bomb.c @@ -18,6 +18,11 @@ #include "rnc/mobys/moby_spawn.h" #include "rnc/overlay/shared/rendering/effects/spawn_explosion.h" +enum { + MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, + MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE +}; + /* Class header fields the spawner copies into a fresh moby. */ typedef struct { u8 pad0[0xF]; @@ -80,10 +85,6 @@ struct Moby *revive_spawner_pooled_child(struct Moby *spawner_moby, Vec4 *at, s3 enum { SPAWNER_CHILD_STATE_INITIAL = 0 }; - enum { - MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, - MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE - }; Vec4 pos; Vec4 *spawn_position_source; Spawner *spawner_data; @@ -203,10 +204,6 @@ void bomb_spawner_bomb_update(struct Moby *moby) { SPAWNER_BOMB_STATE_SPAWN_CHILD = 1, SPAWNER_BOMB_STATE_SHRINKING = 2 }; - enum { - MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xfd, - MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xfe - }; float *bomb_runtime; Vec4 *pos; struct Moby *other; diff --git a/src/overlays/shared/enemies/frog.c b/src/overlays/shared/enemies/frog.c index 147776d5ac..ac30a43815 100644 --- a/src/overlays/shared/enemies/frog.c +++ b/src/overlays/shared/enemies/frog.c @@ -21,6 +21,23 @@ #include "rnc/overlay/shared/enemies/frog_data/spawn_moby_directional_spark_bursts_2.h" #include "rnc/overlay/shared/enemies/frog_data/spawn_moby_directional_spark_bursts.h" +enum { + FROG_STATE_INITIALIZE = 0, + FROG_STATE_WAIT_WITH_CHILD = 1, + FROG_STATE_WAIT_TO_FOLLOW_PATH = 3, + FROG_STATE_FOLLOW_PATH = 4, + FROG_STATE_JUMP_TO_HOME = 5, + FROG_STATE_AIRBORNE_MOTION = 6, + FROG_STATE_LANDING_ANIMATION = 7, + FROG_STATE_WANDER = 8, + FROG_STATE_APPROACH_TARGET = 9, + FROG_STATE_BLINKING_APPROACH_TARGET = 10, + FROG_STATE_APPROACH_PAUSE = 11, + FROG_STATE_ATTACK = 12, + FROG_STATE_RETURN_HOME = 13, + FROG_STATE_SUCK_CANNON_HELD = 16 +}; + typedef struct FrogVars { u8 pad0[0x29]; s8 unk29; @@ -245,22 +262,6 @@ void frog_update(unsigned char *moby) __asm__("FUN_L06_002e8678"); /* Moby class 827 */ void frog_update(unsigned char *moby) { - enum { - FROG_STATE_INITIALIZE = 0, - FROG_STATE_WAIT_WITH_CHILD = 1, - FROG_STATE_WAIT_TO_FOLLOW_PATH = 3, - FROG_STATE_FOLLOW_PATH = 4, - FROG_STATE_JUMP_TO_HOME = 5, - FROG_STATE_AIRBORNE_MOTION = 6, - FROG_STATE_LANDING_ANIMATION = 7, - FROG_STATE_WANDER = 8, - FROG_STATE_APPROACH_TARGET = 9, - FROG_STATE_BLINKING_APPROACH_TARGET = 10, - FROG_STATE_APPROACH_PAUSE = 11, - FROG_STATE_ATTACK = 12, - FROG_STATE_RETURN_HOME = 13, - FROG_STATE_SUCK_CANNON_HELD = 16 - }; float A[4] __attribute__((aligned(16))); float B[4] __attribute__((aligned(16))); float C[4] __attribute__((aligned(16))); @@ -974,13 +975,6 @@ void spawn_moby_death_effect_burst(char *moby) { int update_moby_grab_state(struct Moby *moby) __asm__("FUN_L06_002ea5e0"); int update_moby_grab_state(struct Moby *moby) { - enum { - FROG_STATE_WANDER = 8, - FROG_STATE_APPROACH_TARGET = 9, - FROG_STATE_ATTACK = 0xC, - FROG_STATE_RETURN_HOME = 0xD, - FROG_STATE_SUCK_CANNON_HELD = 0x10 - }; int grab_check_result = process_moby_suck_cannon_suction(moby); if (grab_check_result != 0) { if (moby->state == FROG_STATE_WANDER || moby->state == FROG_STATE_APPROACH_TARGET || @@ -1006,10 +1000,6 @@ int update_moby_grab_state(struct Moby *moby) { int update_moby_suck_cannon_storage_state(unsigned char *moby) __asm__("FUN_L06_002ea6a8"); int update_moby_suck_cannon_storage_state(unsigned char *moby) { - enum { - FROG_STATE_WANDER = 8, - FROG_STATE_SUCK_CANNON_HELD = 0x10 - }; int suck_cannon_store_result = store_moby_in_suck_cannon(moby); if (suck_cannon_store_result != 0) { if (MOBY(moby)->state != FROG_STATE_SUCK_CANNON_HELD) { @@ -1028,9 +1018,6 @@ int update_moby_suck_cannon_storage_state(unsigned char *moby) { s32 cancel_moby_suction_and_save_state(unsigned char *moby) __asm__("FUN_L06_002ea7c8"); s32 cancel_moby_suction_and_save_state(unsigned char *moby) { - enum { - FROG_STATE_SUCK_CANNON_HELD = 0x10 - }; u8 previous_state; s32 helper_result; helper_result = cancel_suck_cannon_suction(moby); diff --git a/src/overlays/shared/enemies/gadgebot.c b/src/overlays/shared/enemies/gadgebot.c index a23ac8c1bb..4c5cf7a4a4 100644 --- a/src/overlays/shared/enemies/gadgebot.c +++ b/src/overlays/shared/enemies/gadgebot.c @@ -25,6 +25,22 @@ #include "rnc/overlay/shared/enemies/gadgebot_spawn_pad.h" #include "rnc/overlay/shared/math/random/random_int_between.h" +enum { + GADGEBOT_ABSORPTION_DISABLED = 2 +}; + +enum { + GADGEBOT_INITIALIZE = 0, + GADGEBOT_WAIT_FOR_SPAWN_PAD = 1, + GADGEBOT_WANDER_NEAR_HOME = 2, + GADGEBOT_FOLLOW_HERO = 3, + GADGEBOT_STAND_AND_FACE_HERO = 4, + GADGEBOT_SEEK_AND_ATTACK_TARGET = 5, + GADGEBOT_SEEK_INTERACTION_TARGET = 7, + GADGEBOT_ABSORB_INTO_OWNER = 8, + GADGEBOT_UPDATE_KNOCKBACK = 9 +}; + #define GB_FLAG (*(unsigned char *)0x15EDB3) #define PVARS(p) (*(char **)((p) + 0x78)) #define S16(p, current_target) (*(short *)((p) + (current_target))) @@ -297,17 +313,6 @@ void gadgebot_update(GbMoby *moby) __asm__("FUN_L06_002f0040"); /* Moby classes 857, 1906 */ void gadgebot_update(GbMoby *moby) { - enum { - GADGEBOT_INITIALIZE = 0, - GADGEBOT_WAIT_FOR_SPAWN_PAD = 1, - GADGEBOT_WANDER_NEAR_HOME = 2, - GADGEBOT_FOLLOW_HERO = 3, - GADGEBOT_STAND_AND_FACE_HERO = 4, - GADGEBOT_SEEK_AND_ATTACK_TARGET = 5, - GADGEBOT_SEEK_INTERACTION_TARGET = 7, - GADGEBOT_ABSORB_INTO_OWNER = 8, - GADGEBOT_UPDATE_KNOCKBACK = 9 - }; enum { GADGEBOT_ATTACK_SEEK_AND_APPROACH_TARGET = 1, GADGEBOT_ATTACK_STRIKE = 2, @@ -1370,9 +1375,6 @@ void assign_gadgebot_attack_targets(void) { } void select_nearest_gadgebot_interaction_target(void *moby_arg) { - enum { - GADGEBOT_ABSORPTION_DISABLED = 2 - }; GbMoby *moby = moby_arg; GbVars *gadgebot_vars = moby->vars; GbMoby *candidate; @@ -1431,9 +1433,6 @@ int process_gadgebot_interaction_candidate( int process_gadgebot_interaction_candidate( char *ctx, char *ow, char *moby, int flag, int *interaction_status_out) { - enum { - GADGEBOT_ABSORPTION_DISABLED = 2 - }; float candidate_position[4]; float vB[4]; float vA[4]; @@ -1623,11 +1622,9 @@ int process_gadgebot_interactions(char *moby, int flag) { void handle_gadgebot_hit_knockback(unsigned char *moby) __asm__("FUN_L06_002f3640"); void handle_gadgebot_hit_knockback(unsigned char *moby) { - enum { - GADGEBOT_UPDATE_KNOCKBACK = 9 - }; char *state = ((char *)MOBY(moby)->pvars); - if (MOBY(moby)->state != GADGEBOT_UPDATE_KNOCKBACK && MOBY(moby)->seq != 2 && MOBY(moby)->prev_seq != 2) { + if (MOBY(moby)->state != GADGEBOT_UPDATE_KNOCKBACK && MOBY(moby)->seq != 2 && + MOBY(moby)->prev_seq != 2) { char *target = find_moby_hit(moby, 0x330001, 0); if (target != 0) { Q hit_vector_copy; @@ -1691,12 +1688,6 @@ void draw_gadgebot_group_glow_effects(char *group_reference_moby) { } void update_gadgebot_glow_effects(char *moby) { - enum { - GADGEBOT_FOLLOW_HERO = 3, - GADGEBOT_SEEK_AND_ATTACK_TARGET = 5, - GADGEBOT_SEEK_INTERACTION_TARGET = 7, - GADGEBOT_UPDATE_KNOCKBACK = 9 - }; char *moby_vars; int tint; int i; diff --git a/src/overlays/shared/enemies/gadgebot_spawn_container.c b/src/overlays/shared/enemies/gadgebot_spawn_container.c index e3ccdfd7a0..845eee438e 100644 --- a/src/overlays/shared/enemies/gadgebot_spawn_container.c +++ b/src/overlays/shared/enemies/gadgebot_spawn_container.c @@ -13,6 +13,12 @@ #include "rnc/overlay/shared/math/random/random_int_between.h" #include "rnc/overlay/shared/props.h" +enum { + GADGEBOT_CONTAINER_ACTIVATE = 0, + GADGEBOT_CONTAINER_PULSE_AND_HANDLE_HITS = 1, + GADGEBOT_CONTAINER_WAIT_FOR_REMOVAL = 2 +}; + typedef struct { float corner[4][4]; int color[4]; @@ -87,9 +93,6 @@ static inline void transform_point(float *dst, float *src, float (*m)[4]) { void destroy_gadgebot_spawn_container(void *moby_ptr, void *target_ptr) __asm__("FUN_L06_002d8178"); void destroy_gadgebot_spawn_container(void *moby_ptr, void *target_ptr) { - enum { - GADGEBOT_CONTAINER_WAIT_FOR_REMOVAL = 2 - }; int i; int j; char *moby = moby_ptr; @@ -177,11 +180,6 @@ void gadgebot_spawn_container_update(unsigned char *moby) __asm__("FUN_L06_002d8 /* Moby class 302 */ void gadgebot_spawn_container_update(unsigned char *moby) { - enum { - GADGEBOT_CONTAINER_ACTIVATE = 0, - GADGEBOT_CONTAINER_PULSE_AND_HANDLE_HITS = 1, - GADGEBOT_CONTAINER_WAIT_FOR_REMOVAL = 2 - }; char *hit_record = find_moby_hit(moby, 0x10000, 0); float raised_position_snapshot[4]; int frame_count_snapshot; diff --git a/src/overlays/shared/enemies/ground_melee_enemy.c b/src/overlays/shared/enemies/ground_melee_enemy.c index 7885368c84..16a39101ab 100644 --- a/src/overlays/shared/enemies/ground_melee_enemy.c +++ b/src/overlays/shared/enemies/ground_melee_enemy.c @@ -21,6 +21,21 @@ #include "rnc/overlay/shared/mobys/count_active_moby_group_members.h" #include "rnc/sdk/libc/stdlib.h" +enum { + GROUND_ENEMY_STATE_INITIALIZE = 0, + GROUND_ENEMY_STATE_IDLE = 1, + GROUND_ENEMY_STATE_ALERT_TURN = 2, + GROUND_ENEMY_STATE_CHASE = 3, + GROUND_ENEMY_STATE_MELEE_ATTACK = 4, + GROUND_ENEMY_STATE_RETURN_HOME = 5, + GROUND_ENEMY_STATE_HURT_KNOCKBACK = 6, + GROUND_ENEMY_STATE_RECOVER_TO_IDLE = 0x7, + GROUND_ENEMY_STATE_HURT_RECOVERY = 9, + GROUND_ENEMY_STATE_BLOCKED_RETURN_HOME = 12, + GROUND_ENEMY_STATE_LEASHED_FORWARD_WALK = 13, + GROUND_ENEMY_STATE_FATAL_KNOCKBACK = 99 +}; + /* Ground enemy update: damage reaction, leash and wake checks, then its chase / attack / return state machine. */ /* Ported from rac1-decomp (src/overlays/shared/vendor_002C6B30.c: func_L09_002E39E0), where it is exact; names translated to the US level program. */ @@ -160,10 +175,6 @@ extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); int moby_hold_state_if_grabbed(struct Moby *a) __asm__("FUN_L01_002f1c78"); int moby_hold_state_if_grabbed(struct Moby *suction_moby) { - enum { - GROUND_ENEMY_STATE_IDLE = 1, - GROUND_ENEMY_STATE_RECOVER_TO_IDLE = 0x7 - }; int suction_result = process_moby_suck_cannon_suction(suction_moby); if (suction_result == 0) { if (suction_moby->state == GROUND_ENEMY_STATE_RECOVER_TO_IDLE) @@ -202,20 +213,6 @@ void ground_melee_enemy_update(Moby *moby) __asm__("FUN_L09_002e27d8"); /* Moby class 193 */ void ground_melee_enemy_update(Moby *moby) { - enum { - GROUND_ENEMY_STATE_INITIALIZE = 0, - GROUND_ENEMY_STATE_IDLE = 1, - GROUND_ENEMY_STATE_ALERT_TURN = 2, - GROUND_ENEMY_STATE_CHASE = 3, - GROUND_ENEMY_STATE_MELEE_ATTACK = 4, - GROUND_ENEMY_STATE_RETURN_HOME = 5, - GROUND_ENEMY_STATE_HURT_KNOCKBACK = 6, - GROUND_ENEMY_STATE_RECOVER_TO_IDLE = 7, - GROUND_ENEMY_STATE_HURT_RECOVERY = 9, - GROUND_ENEMY_STATE_BLOCKED_RETURN_HOME = 12, - GROUND_ENEMY_STATE_LEASHED_FORWARD_WALK = 13, - GROUND_ENEMY_STATE_FATAL_KNOCKBACK = 99 - }; V_2E39E0 previous; Target_2E39E0 query; V_2E39E0 step; diff --git a/src/overlays/shared/enemies/horny_toad.c b/src/overlays/shared/enemies/horny_toad.c index 5a61ea76aa..9a39e4bd89 100644 --- a/src/overlays/shared/enemies/horny_toad.c +++ b/src/overlays/shared/enemies/horny_toad.c @@ -20,6 +20,10 @@ #include "rnc/rendering/debug/debug_menu.h" #include "rnc/overlay/shared/math/quad.h" +enum { + MOBY_STATE_SUCK_CANNON_ACTIVE = 0x9 +}; + typedef struct HornyToadVars { u8 pad0[0x1f4]; f32 unk1F4[4]; @@ -635,9 +639,6 @@ extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); int process_suck_cannon_suction_and_update_moby_state(char *a) __asm__("FUN_L00_002d56e0"); int process_suck_cannon_suction_and_update_moby_state(char *moby) { - enum { - MOBY_STATE_SUCK_CANNON_ACTIVE = 0x9 - }; int suction_result = process_moby_suck_cannon_suction(moby); if (suction_result == 0) { if (MOBY(moby)->state == MOBY_STATE_SUCK_CANNON_ACTIVE) @@ -654,9 +655,6 @@ extern int cancel_suck_cannon_suction(void *) __asm__("FUN_L00_002dbe20"); int cancel_suck_cannon_suction_and_set_moby_state_9(char *moby) __asm__("FUN_L00_002d57d0"); int cancel_suck_cannon_suction_and_set_moby_state_9(char *moby) { - enum { - MOBY_STATE_SUCK_CANNON_ACTIVE = 0x9 - }; int helper_result = cancel_suck_cannon_suction(moby); MOBY(moby)->state = MOBY_STATE_SUCK_CANNON_ACTIVE; return helper_result; diff --git a/src/overlays/shared/enemies/large_amoeboid.c b/src/overlays/shared/enemies/large_amoeboid.c index 833883686a..00ebd75d25 100644 --- a/src/overlays/shared/enemies/large_amoeboid.c +++ b/src/overlays/shared/enemies/large_amoeboid.c @@ -23,6 +23,23 @@ #include "rnc/overlay/shared/enemies/large_amoeboid_data/spawn_amoeboid_burst_sparks_2.h" #include "rnc/overlay/shared/enemies/large_amoeboid_data/spawn_amoeboid_burst_sparks.h" +enum { + LARGE_AMOEBOID_INITIALIZE = 0, + LARGE_AMOEBOID_TRY_ACQUIRE_TARGET_PATH = 1, + LARGE_AMOEBOID_MOVE_TOWARD_STORED_POSITION = 2, + LARGE_AMOEBOID_WAIT_FOR_PATH_ACQUISITION_ANIMATION_END = 3, + LARGE_AMOEBOID_FOLLOW_PATH_TO_TARGET = 4, + LARGE_AMOEBOID_RETURN_TO_STORED_POSITION = 5, + LARGE_AMOEBOID_LUNGE_AT_TARGET = 6, + LARGE_AMOEBOID_WAIT_FOR_ANIMATION_BEFORE_RESUMING_PATH = 7, + LARGE_AMOEBOID_PROCESS_KNOCKBACK = 8, + LARGE_AMOEBOID_WAIT_FOR_ANIMATION_BEFORE_RESTARTING_PATH = 9, + LARGE_AMOEBOID_WAIT_FOR_ACTIVATION_VOLUME = 13, + LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION = 14, + LARGE_AMOEBOID_MOVE_DIRECTLY_TOWARD_TARGET = 15, + LARGE_AMOEBOID_WAIT_WHILE_BLOCKED = 16 +}; + typedef struct LargeAmoeboidVars { u8 pad0[0x20]; f32 health; @@ -222,22 +239,6 @@ void large_amoeboid_update(unsigned char *moby) __asm__("FUN_L01_002edca0"); /* Moby classes 572, 865, 866 */ void large_amoeboid_update(unsigned char *moby) { - enum { - LARGE_AMOEBOID_INITIALIZE = 0, - LARGE_AMOEBOID_TRY_ACQUIRE_TARGET_PATH = 1, - LARGE_AMOEBOID_MOVE_TOWARD_STORED_POSITION = 2, - LARGE_AMOEBOID_WAIT_FOR_PATH_ACQUISITION_ANIMATION_END = 3, - LARGE_AMOEBOID_FOLLOW_PATH_TO_TARGET = 4, - LARGE_AMOEBOID_RETURN_TO_STORED_POSITION = 5, - LARGE_AMOEBOID_LUNGE_AT_TARGET = 6, - LARGE_AMOEBOID_WAIT_FOR_ANIMATION_BEFORE_RESUMING_PATH = 7, - LARGE_AMOEBOID_PROCESS_KNOCKBACK = 8, - LARGE_AMOEBOID_WAIT_FOR_ANIMATION_BEFORE_RESTARTING_PATH = 9, - LARGE_AMOEBOID_WAIT_FOR_ACTIVATION_VOLUME = 13, - LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION = 14, - LARGE_AMOEBOID_MOVE_DIRECTLY_TOWARD_TARGET = 15, - LARGE_AMOEBOID_WAIT_WHILE_BLOCKED = 16 - }; enum { LARGE_AMOEBOID_LARGE_VARIANT = 0x23c, LARGE_AMOEBOID_MEDIUM_VARIANT = 0x361, @@ -657,10 +658,6 @@ void large_amoeboid_update(unsigned char *moby) { /* Ported from rac1-decomp (src/overlays/shared/vendor_002B90A8.c: func_L01_002F0040), where it is exact; names translated to the US level program. */ void process_amoeboid_hits_and_update_targeting(char *moby) { - enum { - LARGE_AMOEBOID_INITIALIZE = 0, - LARGE_AMOEBOID_PROCESS_KNOCKBACK = 8 - }; V_2F0040 scratch_vector; V_2F0040 line_test_endpoint; int flag; @@ -1095,11 +1092,6 @@ void spawn_amoeboid_burst_sparks(unsigned char *moby, f32 *mode) { int process_amoeboid_suck_cannon_suction(struct Moby *moby) __asm__("FUN_L01_002efa88"); int process_amoeboid_suck_cannon_suction(struct Moby *moby) { - enum { - LARGE_AMOEBOID_TRY_ACQUIRE_TARGET_PATH = 1, - LARGE_AMOEBOID_PROCESS_KNOCKBACK = 8, - LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION = 0xE - }; int suction_result = process_moby_suck_cannon_suction(moby); if (suction_result != 0) { if (moby->oclass != 0x362) { @@ -1122,10 +1114,6 @@ extern int store_moby_in_suck_cannon(void *) __asm__("FUN_L00_002dbb20"); int moby_hold_state_if_found(struct Moby *a) __asm__("FUN_L01_002efaf8"); int moby_hold_state_if_found(struct Moby *target_moby) { - enum { - LARGE_AMOEBOID_TRY_ACQUIRE_TARGET_PATH = 1, - LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION = 0xe - }; int suck_cannon_store_result = store_moby_in_suck_cannon(target_moby); if (suck_cannon_store_result == 0) { if (target_moby->state == LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION) @@ -1142,9 +1130,6 @@ extern int cancel_suck_cannon_suction(void *) __asm__("FUN_L00_002dbe20"); int cancel_suck_cannon_suction_and_set_state_14(struct Moby *moby) __asm__("FUN_L01_002efb98"); int cancel_suck_cannon_suction_and_set_state_14(struct Moby *moby) { - enum { - LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION = 0xe - }; int helper_result = cancel_suck_cannon_suction(moby); moby->state = LARGE_AMOEBOID_PROCESS_SUCK_CANNON_INTERACTION; return helper_result; diff --git a/src/overlays/shared/enemies/paratrooper_fire_bolt.c b/src/overlays/shared/enemies/paratrooper_fire_bolt.c index 4c5657e106..af59de05ef 100644 --- a/src/overlays/shared/enemies/paratrooper_fire_bolt.c +++ b/src/overlays/shared/enemies/paratrooper_fire_bolt.c @@ -12,6 +12,11 @@ #include "rnc/overlay/shared/math/vu0_vector_ops.h" #include "rnc/overlay/shared/mobys/evaluate_moby_animation_pose.h" +enum { + FIRE_BOLT_STATE_FLYING = 1, + FIRE_BOLT_STATE_BURST_AND_REMOVE = 2 +}; + /* Ported from rac1-decomp (src/overlays/shared/vendor_002D3DF8.c: func_L08_00308650), where it is exact; names translated to the US level program. */ extern char *create_moby(int); @@ -29,9 +34,6 @@ char *spawn_paratrooper_projectile(char *initial_velocity, int lifetime_frames, int burst_mode) { - enum { - FIRE_BOLT_STATE_FLYING = 1 - }; char *spawned_moby = create_moby(0x50C); if (spawned_moby != 0) { char *moby_data; @@ -67,10 +69,6 @@ void fire_bolt_update(char *fire_bolt) __asm__("FUN_L08_00307298"); /* Moby class 1292 */ void fire_bolt_update(char *fire_bolt) { - enum { - FIRE_BOLT_STATE_FLYING = 1, - FIRE_BOLT_STATE_BURST_AND_REMOVE = 2 - }; char *bolt_data = *(char **)(fire_bolt + 0x78); float previous_position[4]; float sc[4]; diff --git a/src/overlays/shared/enemies/path_or_ballistic_debris.c b/src/overlays/shared/enemies/path_or_ballistic_debris.c index 16e880f8e5..bcfc8b9bb9 100644 --- a/src/overlays/shared/enemies/path_or_ballistic_debris.c +++ b/src/overlays/shared/enemies/path_or_ballistic_debris.c @@ -19,6 +19,11 @@ #include "qcopy.h" #include "rnc/overlay/shared/rendering/effects/update_three_phase_effect_particle.h" +enum { + DEBRIS_STATE_FOLLOW_PATH = 0, + DEBRIS_STATE_BALLISTIC = 1 +}; + extern float D_0015ED60; extern s32 coll_sphere(f32, void *, s32, void *) __asm__("FUN_L00_001f0d60"); extern int sample_path(void *, void *, void *, void *, int, float) __asm__("FUN_L00_0025d808"); @@ -69,9 +74,6 @@ void path_or_ballistic_debris_update(struct Moby *moby) __asm__("FUN_L14_002dfd1 /* Moby class 403 */ void path_or_ballistic_debris_update(struct Moby *moby) { - enum { - DEBRIS_STATE_FOLLOW_PATH = 0 - }; Data *debris_private_vars = (Data *)moby->pvars; Vec4 probe; f32 position_offset[4]; @@ -297,10 +299,6 @@ extern Particle_2E17B8 *func_L00_0026DEA0_2E17B8( void *, float, float, float, int, void *, float, int) __asm__("FUN_L00_0026d000"); void emit_debris_trail_particles(Moby *moby) { - enum { - DEBRIS_STATE_FOLLOW_PATH = 0, - DEBRIS_STATE_BALLISTIC = 1 - }; Vec4_2E17B8 pos; Vec4_2E17B8 emission_axis_offset; Vec4_2E17B8 particle_initial_velocity; diff --git a/src/overlays/shared/enemies/plasmabot.c b/src/overlays/shared/enemies/plasmabot.c index e8ccacf837..698072146f 100644 --- a/src/overlays/shared/enemies/plasmabot.c +++ b/src/overlays/shared/enemies/plasmabot.c @@ -334,22 +334,6 @@ void plasmabot_update(char *moby) __asm__("FUN_L14_002b17d8"); /* Moby class 28 */ void plasmabot_update(char *moby) { - enum { - PLASMABOT_INITIALIZE = 0, - PLASMABOT_WAIT_TO_START_PATH_TRAVERSAL = 1, - PLASMABOT_START_PATH_TRAVERSAL = 2, - PLASMABOT_FOLLOW_PATH_FORWARD = 3, - PLASMABOT_AIM_AT_TARGET = 4, - PLASMABOT_WAIT_ANIMATION_BEFORE_AIM_SWEEP = 5, - PLASMABOT_SWEEP_AIM_AND_TRACE_LINE = 6, - PLASMABOT_WAIT_ANIMATION_BEFORE_AIM = 7, - PLASMABOT_FOLLOW_PATH_BACKWARD = 8, - PLASMABOT_RETURN_TO_PATH_START = 9, - PLASMABOT_WAIT_ANIMATION_BEFORE_RESUMING_AIM = 10, - PLASMABOT_FALL_THEN_EXPLODE = 11, - PLASMABOT_SPAWN_DEBRIS_AND_REMOVE = 12, - PLASMABOT_FACE_TARGET_AND_WAIT = 13 - }; PlasmabotVars *plasmabot_update_private_vars; char *plasmabot_aim_target_moby; int state; @@ -832,6 +816,24 @@ extern u8 D_L14_0015F580[] MACRO_ADDR; #include "rnc/overlay/shared/enemies/plasmabot_data/update_plasmabot_visual_effects.h" +enum { + PLASMABOT_INITIALIZE = 0, + HIT_KIND_SKIP_DAMAGE_AND_REACTION = 1, + PLASMABOT_WAIT_TO_START_PATH_TRAVERSAL = 1, + PLASMABOT_START_PATH_TRAVERSAL = 2, + PLASMABOT_FOLLOW_PATH_FORWARD = 3, + PLASMABOT_AIM_AT_TARGET = 4, + PLASMABOT_WAIT_ANIMATION_BEFORE_AIM_SWEEP = 5, + PLASMABOT_SWEEP_AIM_AND_TRACE_LINE = 6, + PLASMABOT_WAIT_ANIMATION_BEFORE_AIM = 7, + PLASMABOT_FOLLOW_PATH_BACKWARD = 8, + PLASMABOT_RETURN_TO_PATH_START = 9, + PLASMABOT_WAIT_ANIMATION_BEFORE_RESUMING_AIM = 10, + PLASMABOT_FALL_THEN_EXPLODE = 11, + PLASMABOT_SPAWN_DEBRIS_AND_REMOVE = 12, + PLASMABOT_FACE_TARGET_AND_WAIT = 13 +}; + extern void FUN_L14_002b3a20_c(struct Moby *) __asm__("FUN_L14_002b3a20"); extern void FUN_L14_002b2928_u(struct Moby *) __asm__("FUN_L14_002b2928"); @@ -1089,12 +1091,6 @@ void process_plasmabot_hit_reaction(struct Moby *moby) { HIT_REACTION_STAGGER = 3, HIT_REACTION_NONE = 11 }; - enum { - HIT_KIND_SKIP_DAMAGE_AND_REACTION = 1, - PLASMABOT_WAIT_ANIMATION_BEFORE_RESUMING_AIM = 0xA, - PLASMABOT_FALL_THEN_EXPLODE = 0xB, - PLASMABOT_SPAWN_DEBRIS_AND_REMOVE = 0xC - }; PlasmabotVars *state = (PlasmabotVars *)moby->pvars; int hit_kind; float damage; @@ -1323,9 +1319,6 @@ extern char *D_L14_0015FFD8; int check_listed_plasmabots_not_starting_path_traversal(unsigned char *source_moby) __asm__("FUN_L14_002b39a0"); int check_listed_plasmabots_not_starting_path_traversal(unsigned char *source_moby) { - enum { - PLASMABOT_START_PATH_TRAVERSAL = 2 - }; unsigned short *moby_list_entry; if (*(volatile unsigned char *)(source_moby + 0x21) == 0xFF || (moby_list_entry = (unsigned short *)D_L14_001ABF40[MOBY(source_moby)->group]) == 0) diff --git a/src/overlays/shared/enemies/plasmabot_hatch.c b/src/overlays/shared/enemies/plasmabot_hatch.c index e68424c678..98e79b3de6 100644 --- a/src/overlays/shared/enemies/plasmabot_hatch.c +++ b/src/overlays/shared/enemies/plasmabot_hatch.c @@ -10,6 +10,17 @@ #include "rnc/mobys/animation/set_moby_animation.h" #include "qcopy.h" +enum { + HATCH_WAIT_ACTIVATION = 0, + HATCH_WAIT_ACTIVATION_DELAY = 1, + HATCH_WAIT_ACTIVATION_ANIMATION = 2, + HATCH_WAIT_ACTIVATION_GATE_CLEAR = 3, + HATCH_IDLE_AFTER_ACTIVATION_GATE_CLEAR = 4, + HATCH_WAIT_ANIMATION_BEFORE_RESET_DELAY = 5, + HATCH_WAIT_RESET_DELAY = 6, + HATCH_WAIT_RESET_ANIMATION = 7 +}; + extern u8 *D_L14_00167500 NOT_SDA; extern char *D_L14_ffd0_e_macro[] __asm__("D_L14_0015FFD0") MACRO_ADDR; @@ -17,16 +28,6 @@ void plasmabot_hatch_update(struct Moby *moby) __asm__("FUN_L14_002d96e0"); /* Moby class 250 */ void plasmabot_hatch_update(struct Moby *moby) { - enum { - HATCH_WAIT_ACTIVATION = 0, - HATCH_WAIT_ACTIVATION_DELAY = 1, - HATCH_WAIT_ACTIVATION_ANIMATION = 2, - HATCH_WAIT_ACTIVATION_GATE_CLEAR = 3, - HATCH_IDLE_AFTER_ACTIVATION_GATE_CLEAR = 4, - HATCH_WAIT_ANIMATION_BEFORE_RESET_DELAY = 5, - HATCH_WAIT_RESET_DELAY = 6, - HATCH_WAIT_RESET_ANIMATION = 7 - }; char *hatch_private_vars = (char *)moby->pvars; if (hero.vehicle_mode == HERO_VEHICLE_MODE_GIANT_CLANK) { moby->collision = 0; @@ -103,11 +104,6 @@ typedef struct { int refresh_plasmabot_hatch_reset_delay(int i) __asm__("FUN_L14_002d9870"); int refresh_plasmabot_hatch_reset_delay(int i) { - enum { - HATCH_WAIT_ACTIVATION = 0, - HATCH_WAIT_ANIMATION_BEFORE_RESET_DELAY = 5, - HATCH_WAIT_RESET_DELAY = 6 - }; struct Moby *moby = (unsigned char *)(D_L14_ffd0_e_macro[2] + i * 256); int *hatch_vars = ((int *)moby->pvars); int hatch_reset_delay_active = 0; diff --git a/src/overlays/shared/enemies/sand_mouse.c b/src/overlays/shared/enemies/sand_mouse.c index a01ae5f508..426b2459ad 100644 --- a/src/overlays/shared/enemies/sand_mouse.c +++ b/src/overlays/shared/enemies/sand_mouse.c @@ -25,6 +25,18 @@ #include "rnc/overlay/shared/enemies/sand_mouse_data/sand_mouse_update.h" #include "rnc/world/collision/collision_line.h" +enum { + SAND_MOUSE_INITIALIZE = 0, + SAND_MOUSE_WAIT_FOR_HERO_IN_VOLUME = 1, + SAND_MOUSE_WAIT_FOR_PARENT_READY = 2, + SAND_MOUSE_MOVE_TOWARD_HERO = 3, + SAND_MOUSE_BEGIN_FOLLOW_HERO = 4, + SAND_MOUSE_FOLLOW_HERO = 5, + SAND_MOUSE_FADE_OUT_AND_RESET_HOME = 6, + SAND_MOUSE_DAMP_VELOCITY_BEFORE_RETURN = 19, + SAND_MOUSE_RETURN_TO_PARENT = 20 +}; + typedef struct { float a[4]; } Vs __attribute__((aligned(16))); @@ -349,9 +361,6 @@ void update_hover_moby_steering(struct Moby *moby, char *movement_state) { HOVER_FACE_GOAL_AND_WAIT = 0, HOVER_MOVE_TOWARD_GOAL = 2 }; - enum { - SAND_MOUSE_FADE_OUT_AND_RESET_HOME = 6 - }; Vec4 velocity_adjustment; f32 reference_distance, direction_yaw, movement_magnitude, ground, near; s32 hit; @@ -489,17 +498,6 @@ void sand_mouse_update(struct Moby *moby) __asm__("FUN_L01_002e3f20"); /* Moby class 437 */ void sand_mouse_update(struct Moby *moby) { - enum { - SAND_MOUSE_INITIALIZE = 0, - SAND_MOUSE_WAIT_FOR_HERO_IN_VOLUME = 1, - SAND_MOUSE_WAIT_FOR_PARENT_READY = 2, - SAND_MOUSE_MOVE_TOWARD_HERO = 3, - SAND_MOUSE_BEGIN_FOLLOW_HERO = 4, - SAND_MOUSE_FOLLOW_HERO = 5, - SAND_MOUSE_FADE_OUT_AND_RESET_HOME = 6, - SAND_MOUSE_DAMP_VELOCITY_BEFORE_RETURN = 19, - SAND_MOUSE_RETURN_TO_PARENT = 20 - }; Data *sand_mouse_vars; float va[4]; float vb[4]; diff --git a/src/overlays/shared/enemies/sandmouse.c b/src/overlays/shared/enemies/sandmouse.c index 9405574b2d..0acfdea342 100644 --- a/src/overlays/shared/enemies/sandmouse.c +++ b/src/overlays/shared/enemies/sandmouse.c @@ -19,6 +19,17 @@ #include "rnc/overlay/shared/world/collision.h" #include "rnc/overlay/shared/game/level_save_state.h" +enum { + SANDMOUSE_STATE_INITIALIZE = 0, + SANDMOUSE_STATE_WAIT_FOR_ACTIVATION = 1, + SANDMOUSE_STATE_WAIT_FOR_LINK = 2, + SANDMOUSE_STATE_MOVE_TO_GOAL = 3, + SANDMOUSE_STATE_BEGIN_FOLLOW_HERO_AND_FIRE = 4, + SANDMOUSE_STATE_FOLLOW_HERO_AND_FIRE = 5, + SANDMOUSE_STATE_FADE_OUT = 6, + SANDMOUSE_STATE_RESET = 7 +}; + extern void mark_moby_for_removal(void *) __asm__("FUN_0020c828"); /* offset a position by two camera-relative vectors, then raise z by 1 */ @@ -289,9 +300,6 @@ void update_sandmouse_hover_movement(struct Moby *moby, struct HoverVars *hover_ HOVER_COMMAND_FACE_GOAL = 0, HOVER_COMMAND_MOVE_TO_GOAL = 2 }; - enum { - SANDMOUSE_STATE_FADE_OUT = 6 - }; Vec4 steering_correction; f32 reference_distance; f32 k; @@ -533,16 +541,6 @@ void sandmouse_update(Moby *m) __asm__("FUN_L01_0030df40"); /* Moby class 1818 */ void sandmouse_update(Moby *sandmouse_moby) { - enum { - SANDMOUSE_STATE_INITIALIZE = 0, - SANDMOUSE_STATE_WAIT_FOR_ACTIVATION = 1, - SANDMOUSE_STATE_WAIT_FOR_LINK = 2, - SANDMOUSE_STATE_MOVE_TO_GOAL = 3, - SANDMOUSE_STATE_BEGIN_FOLLOW_HERO_AND_FIRE = 4, - SANDMOUSE_STATE_FOLLOW_HERO_AND_FIRE = 5, - SANDMOUSE_STATE_FADE_OUT = 6, - SANDMOUSE_STATE_RESET = 7 - }; Pv *sandmouse_vars; f32 goal_bearing_yaw; int dv; diff --git a/src/overlays/shared/enemies/scoutbot.c b/src/overlays/shared/enemies/scoutbot.c index 56641c2f86..0e2c8b0f8f 100644 --- a/src/overlays/shared/enemies/scoutbot.c +++ b/src/overlays/shared/enemies/scoutbot.c @@ -21,6 +21,17 @@ #include "rnc/overlay/shared/world/level_path.h" #include "rnc/overlay/shared/math/quad.h" +enum { + SCOUTBOT_STATE_INITIALIZE = 0, + SCOUTBOT_STATE_IDLE = 1, + SCOUTBOT_STATE_APPROACH_TARGET = 2, + SCOUTBOT_STATE_RETURN_HOME = 3, + SCOUTBOT_STATE_ATTACK = 4, + SCOUTBOT_STATE_WAIT_FOR_VOICE = 6, + SCOUTBOT_STATE_MOVE_TO_WANDER_GOAL = 7, + SCOUTBOT_STATE_EXPLODE_AND_REMOVE = 0x63 +}; + typedef struct ScoutbotVars { u8 pad0[0x20]; f32 unk20[4]; @@ -176,16 +187,6 @@ void scoutbot_update(Moby *moby) __asm__("FUN_L08_002d2af0"); /* Moby class 252 */ void scoutbot_update(Moby *moby) { - enum { - SCOUTBOT_STATE_INITIALIZE = 0, - SCOUTBOT_STATE_IDLE = 1, - SCOUTBOT_STATE_APPROACH_TARGET = 2, - SCOUTBOT_STATE_RETURN_HOME = 3, - SCOUTBOT_STATE_ATTACK = 4, - SCOUTBOT_STATE_WAIT_FOR_VOICE = 6, - SCOUTBOT_STATE_MOVE_TO_WANDER_GOAL = 7, - SCOUTBOT_STATE_EXPLODE_AND_REMOVE = 0x63 - }; Data_3DF8 *scoutbot_instance_vars = (struct Data_3DF8 *)moby->pvars; float target_pos[4]; float offset[4]; @@ -416,9 +417,6 @@ void scoutbot_update(Moby *moby) { /* Ported from rac1-decomp (src/overlays/shared/vendor_002D3DF8.c: func_L08_002D49E8), where it is exact; names translated to the US level program. */ void update_scoutbot_health_and_target(struct Moby *moby) { - enum { - SCOUTBOT_STATE_EXPLODE_AND_REMOVE = 0x63 - }; ScoutbotVars *scoutbot_pvars = (ScoutbotVars *)moby->pvars; int hit; float dmg; @@ -648,9 +646,6 @@ void update_scoutbot_movement(struct Moby *moby) { void *enter_scoutbot_return_home_state(struct Moby *moby) __asm__("FUN_L08_002d4050"); void *enter_scoutbot_return_home_state(struct Moby *moby) { - enum { - SCOUTBOT_STATE_RETURN_HOME = 3 - }; void *suction_cancel_status = cancel_suck_cannon_suction(moby); ScoutbotVars *scoutbot_data = (ScoutbotVars *)moby->pvars; moby->state = SCOUTBOT_STATE_RETURN_HOME; diff --git a/src/overlays/shared/enemies/seeker.c b/src/overlays/shared/enemies/seeker.c index 21e45adb02..034f6c373a 100644 --- a/src/overlays/shared/enemies/seeker.c +++ b/src/overlays/shared/enemies/seeker.c @@ -92,16 +92,6 @@ void seeker_update(struct Moby *moby) __asm__("FUN_L09_002c5990"); /* Moby class 52 */ void seeker_update(struct Moby *moby) { - enum { - SEEKER_STATE_INITIALIZE = 0, - SEEKER_STATE_IDLE_HOVER = 1, - SEEKER_STATE_CHASE = 2, - SEEKER_STATE_CHASE_ANIMATION_WAIT = 3, - SEEKER_STATE_TIMED_CHASE = 4, - SEEKER_STATE_HURT_KNOCKBACK = 5, - SEEKER_STATE_FATAL_KNOCKBACK = 6, - SEEKER_STATE_EXPLODE = 7 - }; enum { SEEKER_DISPATCH_MODE_SKIP_STATE_UPDATE = 2 }; @@ -398,6 +388,17 @@ extern float D_0015ED70; #include "rnc/overlay/shared/enemies/seeker_data/update_seeker_damage_and_target.h" +enum { + SEEKER_STATE_INITIALIZE = 0, + SEEKER_STATE_IDLE_HOVER = 1, + SEEKER_STATE_CHASE = 2, + SEEKER_STATE_CHASE_ANIMATION_WAIT = 3, + SEEKER_STATE_TIMED_CHASE = 4, + SEEKER_STATE_HURT_KNOCKBACK = 5, + SEEKER_STATE_FATAL_KNOCKBACK = 6, + SEEKER_STATE_EXPLODE = 7 +}; + extern float D_L09_0016140C __attribute__((sda)); extern int scale_time() __asm__("FUN_001f96b0"); extern void FUN_L00_00257470_c(void *, int, int) __asm__("FUN_L00_00257470"); @@ -436,12 +437,6 @@ void update_seeker_damage_and_target(Moby *moby) { RESPONSE_REACTION_ONLY = 9, RESPONSE_NO_REACTION = 11 }; - enum { - SEEKER_STATE_INITIALIZE = 0, - SEEKER_STATE_HURT_KNOCKBACK = 5, - SEEKER_STATE_FATAL_KNOCKBACK = 6, - SEEKER_STATE_EXPLODE = 7 - }; enum { SEEKER_TARGET_STATUS_LOST = 2 }; diff --git a/src/overlays/shared/enemies/sentrybot.c b/src/overlays/shared/enemies/sentrybot.c index 0945c88a32..ddcc79da98 100644 --- a/src/overlays/shared/enemies/sentrybot.c +++ b/src/overlays/shared/enemies/sentrybot.c @@ -23,6 +23,32 @@ #include "rnc/overlay/shared/enemies/sentrybot_data/update_sentrybot_hit_response_and_target_visibility.h" #include "rnc/overlay/shared/mobys/animation_start.h" +enum { + SENTRYBOT_INITIALIZE = 0, + SENTRYBOT_WAIT_FOR_LINKED_MOBY = 1, + SENTRYBOT_PATROL_IDLE = 2, + SENTRYBOT_PATROL_PAUSE = 3, + SENTRYBOT_PATROL_MOVE = 4, + SENTRYBOT_DEACTIVATE_LINKED_MOBYS_AFTER_ANIMATION = 5, + SENTRYBOT_TURN_NEGATIVE_HEADING_DELTA = 6, + SENTRYBOT_TURN_POSITIVE_HEADING_DELTA = 7, + SENTRYBOT_TURN_AROUND = 8, + SENTRYBOT_RETURN_HOME = 9, + SENTRYBOT_WAIT_FOR_ANIMATION_THEN_PATROL_IDLE = 10, + SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION = 11, + SENTRYBOT_ALERT_IDLE = 12, + SENTRYBOT_PATROL_MOVE_FAST = 13, + SENTRYBOT_APPROACH_LINKED_MOBY = 14, + SENTRYBOT_ACTIVATE_LINKED_MOBY = 15, + SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM = 16, + SENTRYBOT_EMIT_WITH_NEGATIVE_JOINT_AIM = 17, + SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_POSITIVE_JOINT_AIM = 18, + SENTRYBOT_EMIT_WITH_POSITIVE_JOINT_AIM = 19, + SENTRYBOT_RETURN_HOME_FAST = 20, + SENTRYBOT_RECOVERABLE_KNOCKBACK = 21, + SENTRYBOT_DEATH_KNOCKBACK = 23 +}; + typedef struct { char pad0[0x2084]; int f2084; @@ -247,31 +273,6 @@ void sentrybot_update(unsigned char *moby) __asm__("FUN_L15_002979d8"); /* Moby class 44 */ void sentrybot_update(unsigned char *moby) { - enum { - SENTRYBOT_INITIALIZE = 0, - SENTRYBOT_WAIT_FOR_LINKED_MOBY = 1, - SENTRYBOT_PATROL_IDLE = 2, - SENTRYBOT_PATROL_PAUSE = 3, - SENTRYBOT_PATROL_MOVE = 4, - SENTRYBOT_DEACTIVATE_LINKED_MOBYS_AFTER_ANIMATION = 5, - SENTRYBOT_TURN_NEGATIVE_HEADING_DELTA = 6, - SENTRYBOT_TURN_POSITIVE_HEADING_DELTA = 7, - SENTRYBOT_TURN_AROUND = 8, - SENTRYBOT_RETURN_HOME = 9, - SENTRYBOT_WAIT_FOR_ANIMATION_THEN_PATROL_IDLE = 10, - SENTRYBOT_WAIT_FOR_TRANSITION_ANIMATION = 11, - SENTRYBOT_ALERT_IDLE = 12, - SENTRYBOT_PATROL_MOVE_FAST = 13, - SENTRYBOT_APPROACH_LINKED_MOBY = 14, - SENTRYBOT_ACTIVATE_LINKED_MOBY = 15, - SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM = 16, - SENTRYBOT_EMIT_WITH_NEGATIVE_JOINT_AIM = 17, - SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_POSITIVE_JOINT_AIM = 18, - SENTRYBOT_EMIT_WITH_POSITIVE_JOINT_AIM = 19, - SENTRYBOT_RETURN_HOME_FAST = 20, - SENTRYBOT_RECOVERABLE_KNOCKBACK = 21, - SENTRYBOT_DEATH_KNOCKBACK = 23 - }; enum { SENTRYBOT_ANIM_TURN_NEGATIVE_HEADING_DELTA = 10, SENTRYBOT_ANIM_TURN_POSITIVE_HEADING_DELTA = 11, @@ -320,7 +321,8 @@ void sentrybot_update(unsigned char *moby) { } } update_sentrybot_hit_response_and_target_visibility(moby, flag); - if (flag != 0 && MOBY(moby)->state != SENTRYBOT_RECOVERABLE_KNOCKBACK && MOBY(moby)->state != SENTRYBOT_DEATH_KNOCKBACK) { + if (flag != 0 && MOBY(moby)->state != SENTRYBOT_RECOVERABLE_KNOCKBACK && + MOBY(moby)->state != SENTRYBOT_DEATH_KNOCKBACK) { MOBY(moby)->collision = 0; MOBY(moby)->flags = (MOBY(moby)->flags | 0x41) & 0xEFFF; return; @@ -1107,7 +1109,8 @@ void sentrybot_update(unsigned char *moby) { } else { MOBY(moby)->command = 1; if (sentrybot_instance_data->unk15F != 0) { - MOBY(moby)->state = SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM; + MOBY(moby)->state = + SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM; if (MOBY(moby)->prev_seq != 3) blend_moby_animation(moby, 3, 0, scale_game_frames(10)); } else { @@ -1225,11 +1228,6 @@ int begin_sentrybot_turn_toward_heading( int next_animation, float angle) { - enum { - SENTRYBOT_TURN_NEGATIVE_HEADING_DELTA = 6, - SENTRYBOT_TURN_POSITIVE_HEADING_DELTA = 7, - SENTRYBOT_TURN_AROUND = 8 - }; float heading_delta = -fast_subtract_rotations(MOBY(moby)->rot.z, angle); float stored_heading_delta; int turn_required = 1; @@ -1572,13 +1570,6 @@ void update_sentrybot_hit_response_and_target_visibility(void *sentrybot_moby, i enum { HIT_STATUS_SKIP_REACTION = 1 }; - enum { - SENTRYBOT_INITIALIZE = 0, - SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM = 0x10, - SENTRYBOT_EMIT_WITH_NEGATIVE_JOINT_AIM = 0x11, - SENTRYBOT_RECOVERABLE_KNOCKBACK = 0x15, - SENTRYBOT_DEATH_KNOCKBACK = 0x17 - }; unsigned char *moby = sentrybot_moby; SentrybotVars *sentrybot_data = (SentrybotVars *)MOBY(moby)->pvars; char *hit; @@ -1741,7 +1732,8 @@ void update_sentrybot_hit_response_and_target_visibility(void *sentrybot_moby, i if ((fast_difference_between_rotations(MOBY(moby)->rot.z, target_angle) < 1.5707964f && (sentrybot_target_visibility_height_check_gate[0] == 0 || absolute_float(MOBY(moby)->pos.z - sentrybot_data->unkD0[2]) < 4.0f)) || - MOBY(moby)->state == SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM || MOBY(moby)->state == SENTRYBOT_EMIT_WITH_NEGATIVE_JOINT_AIM) { + MOBY(moby)->state == SENTRYBOT_WAIT_FOR_ANIMATION_THEN_EMIT_WITH_NEGATIVE_JOINT_AIM || + MOBY(moby)->state == SENTRYBOT_EMIT_WITH_NEGATIVE_JOINT_AIM) { seen = sentrybot_data->has_line_of_sight; } if (sentrybot_data->unk114 == 1) diff --git a/src/overlays/shared/enemies/sentrybot_projectile.c b/src/overlays/shared/enemies/sentrybot_projectile.c index 9324cb35e2..d3f61adc4a 100644 --- a/src/overlays/shared/enemies/sentrybot_projectile.c +++ b/src/overlays/shared/enemies/sentrybot_projectile.c @@ -9,6 +9,10 @@ #include "qcopy.h" #include "rnc/math/fast_math.h" +enum { + SENTRYBOT_PROJECTILE_STATE_FLYING = 0 +}; + extern char *spawn_source_attached_fading_effect_particle( char *src, int col, int w, int v, float x) __asm__("FUN_L00_0026daa0"); extern char *create_moby(int); @@ -29,9 +33,6 @@ void sentrybot_projectile_update(unsigned char *moby) __asm__("FUN_L15_002e4380" /* Moby class 934 */ void sentrybot_projectile_update(unsigned char *moby) { - enum { - SENTRYBOT_PROJECTILE_STATE_FLYING = 0 - }; char *moby_vars = ((char *)MOBY(moby)->pvars); float next_position[4]; char col[0x30]; @@ -71,9 +72,6 @@ char *spawn_sentrybot_projectile(char *source_moby, char *pos) __asm__("FUN_L15_002e4580"); char *spawn_sentrybot_projectile(char *source_moby, float *direction_vector, char *spawn_position) { - enum { - SENTRYBOT_PROJECTILE_STATE_FLYING = 0 - }; char *spawned_moby = create_moby(0x3A6); if (spawned_moby != 0) { char *moby_vars; diff --git a/src/overlays/shared/enemies/spawner.c b/src/overlays/shared/enemies/spawner.c index 25165891e3..301333d7de 100644 --- a/src/overlays/shared/enemies/spawner.c +++ b/src/overlays/shared/enemies/spawner.c @@ -19,6 +19,12 @@ #include "rnc/overlay/shared/enemies/spawner_egg.h" #include "rnc/overlay/shared/math/random.h" +enum { + SPAWNER_STATE_INITIALIZE = 0, + SPAWNER_STATE_SPAWN = 1, + SPAWNER_STATE_EXPLODE = 2 +}; + typedef struct SpawnerVars { u8 pad0[0x20]; f32 unk20; @@ -87,9 +93,6 @@ extern f32 frame_time_sq_macro __asm__("D_0015ED70") MACRO_ADDR; void process_spawner_hit_record(struct Moby *moby, char *spawner_vars) __asm__("FUN_L09_0030a9e8"); void process_spawner_hit_record(struct Moby *moby, char *spawner_vars) { - enum { - SPAWNER_STATE_EXPLODE = 2 - }; char *moby_record; int record_processing_status; float remaining_value; @@ -144,11 +147,6 @@ void spawner_update(char *moby) __asm__("FUN_L09_0030ab80"); /* Moby class 1885 */ void spawner_update(char *moby) { - enum { - SPAWNER_STATE_INITIALIZE = 0, - SPAWNER_STATE_SPAWN = 1, - SPAWNER_STATE_EXPLODE = 2 - }; SpawnerVars *spawner_vars = (SpawnerVars *)MOBY(moby)->pvars; float target[4]; float launch_velocity[4]; diff --git a/src/overlays/shared/game/initialize_level_transition_with_audio.c b/src/overlays/shared/game/initialize_level_transition_with_audio.c index 81cf2d25f4..0465ed0b2a 100644 --- a/src/overlays/shared/game/initialize_level_transition_with_audio.c +++ b/src/overlays/shared/game/initialize_level_transition_with_audio.c @@ -14,7 +14,9 @@ #include "rnc/world/loaders/parse_space_scene_chunk.h" #include "rnc/audio/voices/sound_update.h" #include "rnc/overlay/shared/hero/set_hero_animation.h" + void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); + #include "rnc/overlay/shared/mobys.h" #include "rnc/overlay/shared/streaming.h" #include "rnc/overlay/shared/ui/help/help_request.h" diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index d07c4c2e12..e05eed68cd 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -330,13 +330,6 @@ extern int l01_hero_set_state(int, int) __asm__("FUN_L01_0023cf98"); extern void exit_hero_vehicle_mode_if_mode_three(void) __asm__("FUN_L00_0020b930"); void update_hero_ground_material_effects(void) { - enum { - GROUND_MATERIAL_WATER = 0, - GROUND_MATERIAL_MAGNETIC = 2 - }; - enum { - GROUND_MATERIAL_SINK_TRIGGER = 0xD - }; struct Hero *hero_ptr = &hero; int saved_ground_type; int x; @@ -824,9 +817,6 @@ extern OvlMobyEntry40 l01_moby_hit_response_entries[] __asm__("D_L01_00178580"); s32 process_hero_hit_response(s32 apply_state_and_motion_response) __asm__("FUN_L01_00231580"); s32 process_hero_hit_response(s32 apply_state_and_motion_response) { - enum { - CUTSCENE_MODE_INACTIVE = 0 - }; u8 *hero_moby; OvlMobyEntry40 *hero_moby_entry; u8 *mob; @@ -1148,12 +1138,6 @@ extern CollisionHit HH __asm__("D_L01_001742C0") NOT_SDA; void update_hero_ground_contact_and_gravity(void) __asm__("FUN_L01_00232dc0"); void update_hero_ground_contact_and_gravity(void) { - enum { - GROUND_MATERIAL_WATER = 0 - }; - enum { - GROUND_MATERIAL_SINK_TRIGGER = 0xD - }; V collision_ray_end, ground_ray_start, ground_delta_or_angles, side_ray_start, unused_side_probe_point, side_hit_angles, normalized_side_hit_normal; f32 f; @@ -1439,6 +1423,19 @@ s32 resolve_hero_position_with_collision_queries(s32 mode) { #include "rnc/sdk/eetypes.h" #include "rnc/input/pad_state.h" +enum { + GROUND_MATERIAL_WATER = 0, + GROUND_MATERIAL_MAGNETIC = 2 +}; + +enum { + GROUND_MATERIAL_SINK_TRIGGER = 0xD +}; + +enum { + CUTSCENE_MODE_INACTIVE = 0 +}; + typedef struct { s32 w0; u8 pad4[0x70 - 4]; @@ -1458,9 +1455,6 @@ extern Entry70 l01_countdown_timer_records[] __asm__("D_L01_00179D70"); void update_hero_timers_and_vehicle_transitions(void) __asm__("FUN_L01_0023c710"); void update_hero_timers_and_vehicle_transitions(void) { - enum { - CUTSCENE_MODE_INACTIVE = 0 - }; Vec4 sum; Vec4 sample_delta; struct Moby *vehicle_moby; diff --git a/src/overlays/shared/hero/hero_idle_sequence.c b/src/overlays/shared/hero/hero_idle_sequence.c index bbf4d8729f..53ba5ce23a 100644 --- a/src/overlays/shared/hero/hero_idle_sequence.c +++ b/src/overlays/shared/hero/hero_idle_sequence.c @@ -1911,8 +1911,8 @@ void update_hero_and_equipped_item_glows(void) { } } } -extern void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); +extern void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); extern void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); extern void update_hero_item_moby_flags(void) __asm__("FUN_L00_002330d0"); diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index 07be762039..aca1c39648 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -404,9 +404,6 @@ s32 hero_slot_moby(s32 i) { int hero_slot_item_id(int i) __asm__("FUN_L00_0020d498"); int hero_slot_item_id(int i) { - enum { - HERO_ITEM_SLOT_STATE_READY = 2 - }; /* hero shifted by i slots, so items[0] is slot i */ struct Hero *slot_owner = (struct Hero *)(((char *)&hero) + i * sizeof(struct HeroItemSlot)); switch (slot_owner->items[0].state) { @@ -2253,10 +2250,6 @@ extern s32 D_L00_0015F3F8; void hero_update_items(void) __asm__("FUN_L00_00210748"); void hero_update_items(void) { - enum { - HERO_ITEM_SLOT_STATE_READY = 2, - HERO_ITEM_SLOT_STATE_REMOVING = 3 - }; int i; int k; struct Moby *moby; @@ -4169,6 +4162,11 @@ void air_accel(f32 step) { #include "rnc/math/fast_math.h" +enum { + HERO_ITEM_SLOT_STATE_READY = 2, + HERO_ITEM_SLOT_STATE_REMOVING = 3 +}; + extern int nearest_rail_point() __asm__("FUN_L00_0020cd08"); extern char hero_pos[] __asm__("D_0013F3D0"); @@ -4285,7 +4283,8 @@ void hero_integrate_velocity(void) { } if (hero.state_timer < hero.takeoff_frame) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, 0.0f); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 48.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 48.0f); } else { add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.jump_gravity); z = gravity_z(&hero.motion.velocity); diff --git a/src/overlays/shared/hero/hero_update_movement.c b/src/overlays/shared/hero/hero_update_movement.c index cbd017f83b..dcf211db94 100644 --- a/src/overlays/shared/hero/hero_update_movement.c +++ b/src/overlays/shared/hero/hero_update_movement.c @@ -895,7 +895,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if (anim != -1 && ((struct MobyView *)hero.moby)->b52 != 0x36) { set_hero_animation(anim, 0, frames); @@ -918,7 +919,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } if ((struct MobyView *)hero.grapple_target != NULL) { hero.motion.move_yaw = @@ -1217,7 +1219,8 @@ void hero_update_movement(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (fall_start_frame < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.rise_fall_gravity); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.past_apex = 1.0f; } @@ -1326,7 +1329,8 @@ void hero_update_movement(void) { approach_value(&h, r, mx); gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, h); } else if (fall_start_frame < hero.state_timer) { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 130.0f); if (gravity_z(&hero.motion.velocity) < 0.0f) { hero.slam_descending = 1.0f; } @@ -1510,7 +1514,8 @@ void hero_update_movement(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -1637,7 +1642,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1698,7 +1704,8 @@ void hero_update_movement(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity, frame_time_sq * 24.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1796,7 +1803,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -1842,7 +1850,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); } else { hero.motion.velocity.f[2] = 0.0f; - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 150.0f); } break; } @@ -2538,7 +2547,8 @@ void hero_update_movement(void) { } adjust_hero_pose_targets_from_motion(); build_scaled_hero_move_impulse(0.7f, frame_time * 0.0f); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2555,7 +2565,8 @@ void hero_update_movement(void) { len = vector_length_xy(&hero.motion.velocity); FUN_L00_001ff600( frame_scale * -0.100000024f * len + len, &hero.motion.velocity, &hero.motion.velocity); - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, hero.fall_state_gravity); if (gravity_z(&hero.motion.velocity) < -(frame_time * 50.0f)) { gravity_set_z(&hero.motion.velocity, &hero.motion.velocity, -(frame_time * 50.0f)); } @@ -2767,8 +2778,8 @@ void hero_update_movement(void) { if (hero.state_timer < scale_game_frames(10) && hero.stick_magnitude > 0.2f) { qcopy(&movement_and_hit_descriptor_scratch, &hero.motion.pos); add_hero_up_offset(&movement_and_hit_descriptor_scratch, - &movement_and_hit_descriptor_scratch, - 0.5f); + &movement_and_hit_descriptor_scratch, + 0.5f); qcopy(&v10, &movement_and_hit_descriptor_scratch); v10.f[0] += fast_cos(hero.motion.rot.f[2]) * 0.85f; v10.f[1] += fast_sin(hero.motion.rot.f[2]) * 0.85f; @@ -2916,7 +2927,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -2933,7 +2945,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.displacement, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_FIDGET: @@ -2975,7 +2988,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_1_ATTACK: { @@ -3066,7 +3080,8 @@ void hero_update_movement(void) { if (hero.move_lock_timer == 0) { hero_move_state_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); if (hero.motion.velocity.f[2] < frame_time * -10.0f) { hero.motion.velocity.f[2] = frame_time * -10.0f; } @@ -3102,7 +3117,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3196,7 +3212,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_2_REPEATABLE_SQUARE_ACTION: @@ -3300,7 +3317,8 @@ void hero_update_movement(void) { add_hero_gravity_offset( &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } stop_hero_motion_without_forward_support(3.7f, 0.0f); break; @@ -3325,7 +3343,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_WAIT_FOR_CIRCLE_RELEASE_AND_ANIMATION: { @@ -3361,7 +3380,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3381,7 +3401,8 @@ void hero_update_movement(void) { if (hero.move_lock_timer == 0) { hero_move_state_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 12.0f); if (hero.motion.velocity.f[2] < frame_time * -10.0f) { hero.motion.velocity.f[2] = frame_time * -10.0f; } @@ -3453,7 +3474,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } @@ -3490,7 +3512,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; case HERO_STATE_VEHICLE_MODE_3_SLIP: @@ -3505,7 +3528,8 @@ void hero_update_movement(void) { if (hero.move_lock_timer == 0) { hero_move_state_velocity(); } - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 21.0f); if (hero.motion.velocity.f[2] < frame_time * -15.0f) { hero.motion.velocity.f[2] = frame_time * -15.0f; } @@ -3538,7 +3562,8 @@ void hero_update_movement(void) { &hero.motion.velocity, &hero.motion.resolved_velocity_z, frame_time_sq * 25.0f); correct_hero_airborne_wall_velocity(); } else { - add_hero_gravity_offset(&hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); + add_hero_gravity_offset( + &hero.motion.velocity, &hero.motion.velocity, frame_time_sq * 54.0f); } break; } diff --git a/src/overlays/shared/pickups/bolt.c b/src/overlays/shared/pickups/bolt.c index a98fd6cdc9..b4ef3aa11e 100644 --- a/src/overlays/shared/pickups/bolt.c +++ b/src/overlays/shared/pickups/bolt.c @@ -21,6 +21,14 @@ #include "qcopy.h" #include "rnc/overlay/shared/world/collision.h" +enum { + BOLT_INITIALIZE = 0x0, + BOLT_FALLING = 0x1, + BOLT_SETTLING = 0x2, + BOLT_IDLE = 0x3, + BOLT_MOVE_TO_HERO = 0x4 +}; + typedef struct { u8 pad0[0x24]; f32 scale; /* 0x24 */ @@ -174,13 +182,6 @@ void bolt_update(Bolt *obj) __asm__("FUN_L00_002a5dd8"); /* Moby classes 13-16 */ void bolt_update(Bolt *bolt_moby) { - enum { - BOLT_INITIALIZE = 0x0, - BOLT_FALLING = 0x1, - BOLT_SETTLING = 0x2, - BOLT_IDLE = 0x3, - BOLT_MOVE_TO_HERO = 0x4 - }; BoltVars *v = bolt_moby->vars; Vec4 geometry_scratch; Vec4 vector_scratch; @@ -539,12 +540,6 @@ void collect_bolt(struct Moby *bolt) { void update_bolt_grounded_pose(char *moby, void *out1, void *out2) __asm__("FUN_L00_002a6de8"); void update_bolt_grounded_pose(char *moby, void *base_position_output, void *base_rotation_output) { - enum { - BOLT_IDLE = 3 - }; - enum { - BOLT_FALLING = 1 - }; char *grounded_bolt_vars = ((char *)MOBY(moby)->pvars); float local_rotation_basis[12]; float base_rotation_basis[12]; @@ -665,10 +660,6 @@ int begin_bolt_attraction(void *ov, float attraction_yaw_angle, float attraction_pitch_angle) { - enum { - BOLT_IDLE = 3, - BOLT_MOVE_TO_HERO = 4 - }; char *bolt_moby = ov; char *target_moby = tv; char *bolt_vars = ((char *)MOBY(bolt_moby)->pvars); @@ -745,9 +736,6 @@ struct Moby *spawn_bolt_by_value( BOLT_VALUE_TWENTY = 20, BOLT_VALUE_FIFTY = 50 }; - enum { - BOLT_FALLING = 1 - }; f32 spin_axis[4] __attribute__((aligned(16))); f32 bolt_to_source_offset[4] __attribute__((aligned(16))); struct Moby *spawned_bolt; diff --git a/src/overlays/shared/pickups/crate.c b/src/overlays/shared/pickups/crate.c index 5368aebfce..b81d5aa0ee 100644 --- a/src/overlays/shared/pickups/crate.c +++ b/src/overlays/shared/pickups/crate.c @@ -22,6 +22,16 @@ #include "rnc/overlay/shared/camera/level_camera.h" #include "rnc/rendering/debug/debug_menu.h" +enum { + CRATE_STATE_INITIALIZE = 0, + CRATE_STATE_PROCESS_HITS = 1, + CRATE_STATE_CLASS_CHANGE_COOLDOWN = 2, + CRATE_STATE_BROKEN = 3, + CRATE_STATE_REACTIVATION_DELAY = 4, + CRATE_STATE_DETONATION_COUNTDOWN = 5, + CRATE_STATE_WAIT_RESPAWN = 6 +}; + /* Class header view: pclass + 0xE and + 0x10. */ typedef struct { u8 pad00[0xE]; @@ -248,15 +258,6 @@ void crate_update(struct Moby *moby) __asm__("FUN_L00_002cf218"); /* Moby classes 500-502, 505, 511 */ void crate_update(struct Moby *moby) { - enum { - CRATE_STATE_INITIALIZE = 0, - CRATE_STATE_PROCESS_HITS = 1, - CRATE_STATE_CLASS_CHANGE_COOLDOWN = 2, - CRATE_STATE_BROKEN = 3, - CRATE_STATE_REACTIVATION_DELAY = 4, - CRATE_STATE_DETONATION_COUNTDOWN = 5, - CRATE_STATE_WAIT_RESPAWN = 6 - }; Burst burst; Vec4f at; s32 hitKind; @@ -1022,9 +1023,6 @@ void break_crate(M2d1428 *moby, s32 hit, s32 source) { CRATE_VARIANT_FINAL_DAMAGE_STAGE = 10, CRATE_VARIANT_CONDITIONAL_RESPAWN_START = 11 }; - enum { - CRATE_STATE_BROKEN = 3 - }; enum { CRATE_DEBRIS_FALLBACK_BASE = 0x95, CRATE_DEBRIS_MISSION_THRESHOLD_GATED_BASE = 0x15C, @@ -1251,9 +1249,6 @@ void update_crate_stack_motion(M2d1428 *moby) { CRATE_STATE_BREAKABLE = 1, CRATE_STATE_IMPACT_TRIGGERED = 5 }; - enum { - CRATE_STATE_INITIALIZE = 0 - }; O2d1428 *vars; M2d1428 *chain_cursor, *parent_moby, *next; V2d1428 collision_start, collision_end, landing_position, hero_local_offset, diff --git a/src/overlays/shared/pickups/crate_fragment.c b/src/overlays/shared/pickups/crate_fragment.c index 1904761e2b..d90f62217e 100644 --- a/src/overlays/shared/pickups/crate_fragment.c +++ b/src/overlays/shared/pickups/crate_fragment.c @@ -12,6 +12,11 @@ #include "rnc/overlay/shared/world/collision.h" #include "rnc/overlay/shared/math/random/random_int_between.h" +enum { + NANOTECH_CRATE_FRAGMENT_BOUNCING = 0, + NANOTECH_CRATE_FRAGMENT_FADING = 1 +}; + typedef struct { void *o; float f4, f8; @@ -144,9 +149,6 @@ unsigned char *spawn_crate_debris(unsigned char *debris_source_moby, float lo, float hi) { - enum { - NANOTECH_CRATE_FRAGMENT_BOUNCING = 0 - }; unsigned char *debris_moby = create_moby(type); if (debris_moby) { V_2af8b0 *debris_data = ((V_2af8b0 *)MOBY(debris_moby)->pvars); @@ -188,10 +190,6 @@ void nanotech_crate_fragment_update(M_2afa48 *m) __asm__("FUN_L00_002afa48"); /* Moby classes 149, 348, 349, 354-359, 363, 364 */ void nanotech_crate_fragment_update(M_2afa48 *fragment_moby) { - enum { - NANOTECH_CRATE_FRAGMENT_BOUNCING = 0, - NANOTECH_CRATE_FRAGMENT_FADING = 1 - }; PV *pv = fragment_moby->pv; u128 pre_motion_position; u128 *hit_normal; diff --git a/src/overlays/shared/pickups/fighter_jet_crate.c b/src/overlays/shared/pickups/fighter_jet_crate.c index 47aefb3dfc..0a4db05fd0 100644 --- a/src/overlays/shared/pickups/fighter_jet_crate.c +++ b/src/overlays/shared/pickups/fighter_jet_crate.c @@ -12,6 +12,16 @@ #include "rnc/globals.h" #include "rnc/overlay/shared/world/level_labels.h" +enum { + SHIP_PICKUP_INITIALIZE = 0, + SHIP_PICKUP_SELECT_ACTIVATION_GATE = 1, + SHIP_PICKUP_WAIT_FOR_TARGET_STATE = 2, + SHIP_PICKUP_WAIT_FOR_ACTIVATION_TIMER = 3, + SHIP_PICKUP_ACTIVE = 4, + SHIP_PICKUP_COLLECTED_SHRINKING = 5, + SHIP_PICKUP_REMOVE_OR_RESET = 6 +}; + extern int D_L13_00174158_lui __asm__("D_L13_00174158") NOT_SDA; extern int coll_sphere(float, void *, int, void *) __asm__("FUN_L00_001f0d60"); @@ -27,9 +37,6 @@ extern char *create_moby(int); unsigned char *spawn_ship_pickup(char *position, int moby_class) __asm__("FUN_L13_002e1c50"); unsigned char *spawn_ship_pickup(char *position, int moby_class) { - enum { - SHIP_PICKUP_INITIALIZE = 0 - }; unsigned char *moby = create_moby(moby_class); if (moby != 0) { MOBY(moby)->update_dist = 0xFF; @@ -48,15 +55,6 @@ void ammocrate_update(char *moby) __asm__("FUN_L13_002e1cc8"); /* Moby classes 224, 228 */ void ammocrate_update(char *moby) { - enum { - SHIP_PICKUP_INITIALIZE = 0, - SHIP_PICKUP_SELECT_ACTIVATION_GATE = 1, - SHIP_PICKUP_WAIT_FOR_TARGET_STATE = 2, - SHIP_PICKUP_WAIT_FOR_ACTIVATION_TIMER = 3, - SHIP_PICKUP_ACTIVE = 4, - SHIP_PICKUP_COLLECTED_SHRINKING = 5, - SHIP_PICKUP_REMOVE_OR_RESET = 6 - }; enum { MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xfd, MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xfe diff --git a/src/overlays/shared/pickups/gold_bolt.c b/src/overlays/shared/pickups/gold_bolt.c index 6d196deecc..6102fd31fb 100644 --- a/src/overlays/shared/pickups/gold_bolt.c +++ b/src/overlays/shared/pickups/gold_bolt.c @@ -23,6 +23,12 @@ #include "rnc/game/options.h" #include "rnc/overlay/shared/hero/hero_frame_update.h" +enum { + GOLD_BOLT_INITIALIZE = 0, + GOLD_BOLT_WAIT_FOR_PICKUP = 1, + GOLD_BOLT_PICKUP_CUTSCENE = 2 +}; + typedef struct { s32 id; /* collected flag index (D_0014BEC0 + level * 4), -1 none */ u8 pad4[8]; @@ -470,11 +476,6 @@ void gold_bolt_update(struct Moby *moby) __asm__("FUN_L01_00307ca0"); /* Moby class 1134 */ void gold_bolt_update(struct Moby *moby) { - enum { - GOLD_BOLT_INITIALIZE = 0, - GOLD_BOLT_WAIT_FOR_PICKUP = 1, - GOLD_BOLT_PICKUP_CUTSCENE = 2 - }; Vars *gold_bolt_instance_vars = (Vars *)moby->pvars; struct Hero *hero_ptr; Vec4f at; @@ -623,9 +624,6 @@ void gold_bolt_update(struct Moby *moby) { void update_gold_bolt_visuals(struct Moby *moby) __asm__("FUN_L01_00308380"); void update_gold_bolt_visuals(struct Moby *moby) { - enum { - GOLD_BOLT_WAIT_FOR_PICKUP = 1 - }; char *gold_bolt_visual_vars = (char *)moby->pvars; float updated_rotation_z; float bobbing_sine; @@ -790,9 +788,6 @@ void update_gold_bolt_pickup_camera(struct Moby *moby) { void spawn_gold_bolt_particles(struct Moby *moby) __asm__("FUN_L01_003089f0"); void spawn_gold_bolt_particles(struct Moby *moby) { - enum { - GOLD_BOLT_WAIT_FOR_PICKUP = 1 - }; float v[4]; float particle_velocity[4]; float u[4]; diff --git a/src/overlays/shared/pickups/nanotech_ball.c b/src/overlays/shared/pickups/nanotech_ball.c index 82138de543..82f86b1d7b 100644 --- a/src/overlays/shared/pickups/nanotech_ball.c +++ b/src/overlays/shared/pickups/nanotech_ball.c @@ -23,6 +23,14 @@ #include "rnc/overlay/shared/math/random/random_vector.h" #include "rnc/ui/text/font/font_queue_vu_state.h" +enum { + NANOTECH_BALL_STATE_INITIALIZE = 0, + NANOTECH_BALL_STATE_FOLLOW_OWNER = 1, + NANOTECH_BALL_STATE_DETACHED_PICKUP = 2, + NANOTECH_BALL_STATE_COLLECTING = 3, + NANOTECH_BALL_STATE_BASIS_ONLY = 4 +}; + typedef struct { char pad[0x10]; OvlQuad q; @@ -1006,9 +1014,6 @@ float D_L18_00161E2C = 1.125f; int is_moby_in_state_one(unsigned char *moby) __asm__("FUN_L00_002d8128"); int is_moby_in_state_one(unsigned char *moby) { - enum { - NANOTECH_BALL_STATE_FOLLOW_OWNER = 1 - }; return MOBY(moby)->state == NANOTECH_BALL_STATE_FOLLOW_OWNER; } @@ -1206,9 +1211,6 @@ void compute_nanotech_ball_slot_position(unsigned char *moby, int i) __asm__("FUN_L00_002d8850"); void compute_nanotech_ball_slot_position(unsigned char *moby, float *out_slot_position, int i) { - enum { - NANOTECH_BALL_STATE_DETACHED_PICKUP = 2 - }; u128 slot_offset; M_002d8850 *moby_data = ((M_002d8850 *)MOBY(moby)->pvars); char *e; @@ -1252,13 +1254,6 @@ void nanotech_ball_update(Moby *moby) __asm__("FUN_L00_002d89f0"); /* Moby class 806 */ void nanotech_ball_update(Moby *moby) { - enum { - NANOTECH_BALL_STATE_INITIALIZE = 0, - NANOTECH_BALL_STATE_FOLLOW_OWNER = 1, - NANOTECH_BALL_STATE_DETACHED_PICKUP = 2, - NANOTECH_BALL_STATE_COLLECTING = 3, - NANOTECH_BALL_STATE_BASIS_ONLY = 4 - }; V_2D9EA0 slot_rotation_basis_or_cull_position_or_start_tangent, rotated_slot_offset_or_particle_position, v20, collection_target_or_end_tangent, cross_product_or_particle_midpoint, half_displacement_or_spark_position, slot_curve_offset; diff --git a/src/overlays/shared/pickups/weapon_ammo.c b/src/overlays/shared/pickups/weapon_ammo.c index 27c6472174..9986ab34c6 100644 --- a/src/overlays/shared/pickups/weapon_ammo.c +++ b/src/overlays/shared/pickups/weapon_ammo.c @@ -15,6 +15,14 @@ #include "rnc/globals.h" #include "rnc/overlay/shared/mobys/select_auto_aim_target_moby.h" +enum { + AMMO_PICKUP_INITIALIZE = 0, + AMMO_PICKUP_WAIT_FOR_COLLECTION = 1, + AMMO_PICKUP_COLLECTED = 2, + AMMO_PICKUP_PULSE_ALPHA = 3, + AMMO_PICKUP_RESTORE_SCALE = 4 +}; + typedef struct { float x; float y; @@ -91,9 +99,6 @@ int D_L18_001618A8 = 0; unsigned char *spawn_on_path(u128 *a, int b, int c, int d) __asm__("FUN_L00_002c52a8"); unsigned char *spawn_on_path(u128 *spawn_position, int weapon_index, int ammo_amount, int d) { - enum { - AMMO_PICKUP_WAIT_FOR_COLLECTION = 1 - }; unsigned char *spawned_moby = 0; { ItemDef *spawn_config_entry = (ItemDef *)(weapon_index * 0x4C + (u8 *)item_defs_lui); @@ -129,13 +134,6 @@ void devestator_ammo_update(struct Moby *m) __asm__("FUN_L00_002c53c0"); /* Moby classes 204, 213, 214, 222, 223, 225, 226, 1006, 1438, 1447, 1449 */ void devestator_ammo_update(struct Moby *pickup_moby) { - enum { - AMMO_PICKUP_INITIALIZE = 0, - AMMO_PICKUP_WAIT_FOR_COLLECTION = 1, - AMMO_PICKUP_COLLECTED = 2, - AMMO_PICKUP_PULSE_ALPHA = 3, - AMMO_PICKUP_RESTORE_SCALE = 4 - }; AmmoPickup *pickup_vars; unsigned int state; FxVec position; @@ -343,9 +341,6 @@ void devestator_ammo_update(struct Moby *pickup_moby) { int try_collect_ammo_pickup(struct Moby *pickup_moby) __asm__("FUN_L00_002c5be8"); int try_collect_ammo_pickup(struct Moby *pickup_moby) { - enum { - AMMO_PICKUP_COLLECTED = 2 - }; int *pickup_vars = ((int *)pickup_moby->pvars); int before; float excess_ammo_amount; diff --git a/src/overlays/shared/props/hydrodisplacer.c b/src/overlays/shared/props/hydrodisplacer.c index bfd0f7a2c8..1539835f9c 100644 --- a/src/overlays/shared/props/hydrodisplacer.c +++ b/src/overlays/shared/props/hydrodisplacer.c @@ -20,6 +20,15 @@ #include "rnc/input/pad_globals.h" #include "rnc/math/interpolation/advance_accelerated_scalar.h" +enum { + HYDRODISPLACER_INITIALIZE = 0, + HYDRODISPLACER_WAIT_FOR_ANIMATION_FLAG = 1, + HYDRODISPLACER_WAIT_FOR_ACTIVATION = 2, + HYDRODISPLACER_WAIT_FOR_HERO_FLAG = 3, + HYDRODISPLACER_CAMERA_TRANSITION = 4, + HYDRODISPLACER_WAIT_FOR_TIMER = 5 +}; + typedef struct Hero Hero; typedef struct Moby Moby; @@ -102,14 +111,6 @@ void hydrodisplacer_update(Moby *moby) __asm__("FUN_L00_002df9a0"); /* Moby class 1251 */ void hydrodisplacer_update(Moby *moby) { - enum { - HYDRODISPLACER_INITIALIZE = 0, - HYDRODISPLACER_WAIT_FOR_ANIMATION_FLAG = 1, - HYDRODISPLACER_WAIT_FOR_ACTIVATION = 2, - HYDRODISPLACER_WAIT_FOR_HERO_FLAG = 3, - HYDRODISPLACER_CAMERA_TRANSITION = 4, - HYDRODISPLACER_WAIT_FOR_TIMER = 5 - }; enum { HYDRODISPLACER_CAMERA_PREPARE_INTERPOLATION = 0, HYDRODISPLACER_CAMERA_INTERPOLATE = 1, @@ -381,9 +382,6 @@ s32 test_hydrodisplacer_activation_flag(void) { /* Moby state 4: clears two globals, calls 002eac18(3); control mode 0x13: calls 002223f8(0, 1). */ void end_hydrodisplacer_interaction(char *moby) { - enum { - HYDRODISPLACER_CAMERA_TRANSITION = 4 - }; if (MOBY(moby)->state == HYDRODISPLACER_CAMERA_TRANSITION) { hydrodisplacer_camera_active = 0; *(int *)&D_L00_0015F3FC = 0; diff --git a/src/overlays/shared/props/teleporter.c b/src/overlays/shared/props/teleporter.c index 750f58e710..1d3c994096 100644 --- a/src/overlays/shared/props/teleporter.c +++ b/src/overlays/shared/props/teleporter.c @@ -21,6 +21,17 @@ #include "rnc/game/item_state.h" #include "rnc/overlay/shared/world/level_labels.h" +enum { + TELEPORTER_INITIALIZE = 0, + TELEPORTER_WAIT_FOR_USE = 1, + TELEPORTER_PREPARE_TRANSFER = 2, + TELEPORTER_TRANSFER_TO_DESTINATION = 3, + TELEPORTER_RETURN_TO_IDLE = 4, + TELEPORTER_ENTER_WAIT_FOR_USE = 6, + TELEPORTER_EFFECT_CYCLE_PREPARE = 7, + TELEPORTER_EFFECT_CYCLE_RETURN_TO_IDLE = 8 +}; + typedef struct TeleporterVars { u8 pad0[0x4]; s32 unk4; @@ -232,9 +243,6 @@ float D_L18_001621D0 = 1.0f; void activate_teleporter_and_record_state(struct Moby *moby) __asm__("FUN_L01_00308b28"); void activate_teleporter_and_record_state(struct Moby *moby) { - enum { - TELEPORTER_WAIT_FOR_USE = 1 - }; int level_bitset_byte_offset = D_0015ED84 << 8; unsigned char moby_group_index; *(int *)((u8 *)D_0014C190 + (((short)moby->save_id >> 5) * 4 + level_bitset_byte_offset)) |= @@ -252,16 +260,6 @@ void teleporter_update(struct Moby *moby) __asm__("FUN_L01_00308bd8"); /* Moby class 1135 */ void teleporter_update(struct Moby *moby) { - enum { - TELEPORTER_INITIALIZE = 0, - TELEPORTER_WAIT_FOR_USE = 1, - TELEPORTER_PREPARE_TRANSFER = 2, - TELEPORTER_TRANSFER_TO_DESTINATION = 3, - TELEPORTER_RETURN_TO_IDLE = 4, - TELEPORTER_ENTER_WAIT_FOR_USE = 6, - TELEPORTER_EFFECT_CYCLE_PREPARE = 7, - TELEPORTER_EFFECT_CYCLE_RETURN_TO_IDLE = 8 - }; enum { TELEPORTER_WAIT_FOR_ACTIVATION = 5 }; diff --git a/src/overlays/shared/rendering/debug/update_debug_menu.c b/src/overlays/shared/rendering/debug/update_debug_menu.c index 77eb72ac3c..f2b955b9b7 100644 --- a/src/overlays/shared/rendering/debug/update_debug_menu.c +++ b/src/overlays/shared/rendering/debug/update_debug_menu.c @@ -187,9 +187,6 @@ static inline void copy_vector3(f32 *dst, f32 *src) { void update_debug_camera(void) __asm__("FUN_L00_001f3aa0"); void update_debug_camera(void) { - enum { - DEBUG_CONTROL_MODE_CAPTURE_HERO_CAMERA_OFFSET = 2 - }; struct PadStateWords *pad; DebugMenuState *menu; int moved; @@ -457,6 +454,13 @@ extern u8 D_L00_0016CA40[]; #define level_view_context (*(LevelViewContext *)D_L00_0016CA40) #include "rnc/overlay/shared/hero/item_defs.h" +enum { + DEBUG_CONTROL_MODE_ENABLE_LOW_FOUR_UPDATE_FLAGS = 0, + DEBUG_CONTROL_MODE_CLEAR_UPDATE_FLAGS = 1, + DEBUG_CONTROL_MODE_CAPTURE_HERO_CAMERA_OFFSET = 2, + DEBUG_CONTROL_MODE_ENABLE_SECOND_AND_THIRD_UPDATE_FLAGS = 3 +}; + /* 13 item ids, declared as 8 bytes: the most gas reaches through $gp, as retail does. */ extern u8 debug_menu_item_ids[8] __asm__("D_L00_0015EFD0") __attribute__((sda)); /* Declared as 1 byte so the add_sample path forms its address through $gp, as retail does. */ @@ -505,12 +509,6 @@ void update_debug_menu(void) { DEBUG_OPTION_ROW_SCENE_INDEX = 9, DEBUG_OPTION_ROW_SEGMENT_INDEX = 10 }; - enum { - DEBUG_CONTROL_MODE_ENABLE_LOW_FOUR_UPDATE_FLAGS = 0, - DEBUG_CONTROL_MODE_CLEAR_UPDATE_FLAGS = 1, - DEBUG_CONTROL_MODE_CAPTURE_HERO_CAMERA_OFFSET = 2, - DEBUG_CONTROL_MODE_ENABLE_SECOND_AND_THIRD_UPDATE_FLAGS = 3 - }; enum { DEBUG_OCCLUSION_MODE_COUNT = 3, DEBUG_COLLISION_MODE_COUNT = 3, diff --git a/src/overlays/shared/rendering/effects/timed_sprite_effect.c b/src/overlays/shared/rendering/effects/timed_sprite_effect.c index c9f833d119..b1a5aa5610 100644 --- a/src/overlays/shared/rendering/effects/timed_sprite_effect.c +++ b/src/overlays/shared/rendering/effects/timed_sprite_effect.c @@ -10,6 +10,11 @@ #include "rnc/overlay/shared/mobys/entities.h" #include "qcopy.h" +enum { + SPRITE_EFFECT_STATE_REMOVE = 0, + SPRITE_EFFECT_STATE_ANIMATE = 1 +}; + extern char *create_moby(int) __asm__("FUN_0020c4f8"); extern void mark_moby_for_removal(void *) __asm__("FUN_0020c828"); extern u32 fast_tween_color(f32, s32, s32) __asm__("FUN_001fa6e0"); @@ -31,10 +36,6 @@ void timed_sprite_effect_update(struct Moby *moby) __asm__("FUN_L06_0030be60"); /* Moby class 1898 */ void timed_sprite_effect_update(struct Moby *moby) { - enum { - SPRITE_EFFECT_STATE_REMOVE = 0, - SPRITE_EFFECT_STATE_ANIMATE = 1 - }; float *effect_data = ((float *)moby->pvars); switch ((unsigned char)((char)moby->state)) { case SPRITE_EFFECT_STATE_REMOVE: @@ -60,9 +61,6 @@ void spawn_timed_projected_sprite_effect(char *world_position, int start_color, int end_color) { - enum { - SPRITE_EFFECT_STATE_ANIMATE = 1 - }; OvlQuad position_copy; char *vp = (char *)&position_copy; unsigned char *effect_moby; diff --git a/src/overlays/shared/streaming/load_scene_chunks_with_fade.c b/src/overlays/shared/streaming/load_scene_chunks_with_fade.c index 55bc0ce153..0dc110d0a1 100644 --- a/src/overlays/shared/streaming/load_scene_chunks_with_fade.c +++ b/src/overlays/shared/streaming/load_scene_chunks_with_fade.c @@ -6,6 +6,10 @@ #include "rnc/rendering/effects/fade_to_black.h" #include "rnc/audio/streaming/update_audio_stream_until_idle.h" +enum { + PAL_MODE_DISABLED = 0 +}; + typedef struct { u8 pad[0x5C]; u8 *buf; @@ -17,9 +21,6 @@ void start_audio_stream_read(void *, s32, s32) __asm__("FUN_00216788"); void load_scene_chunks_with_fade(s32 i) __asm__("FUN_L00_002454c8"); void load_scene_chunks_with_fade(s32 i) { - enum { - PAL_MODE_DISABLED = 0 - }; s32 pointer_index; s32 *offset_entry; if (pal_mode == PAL_MODE_DISABLED) { @@ -56,9 +57,6 @@ void load_chunks_with_optional_fade(s32 i, s32 fade_frame_count) __asm__("FUN_L0 void load_chunks_with_optional_fade(s32 i, s32 p) __asm__("FUN_L00_00245610"); void load_chunks_with_optional_fade(s32 i, s32 fade_frame_count) { - enum { - PAL_MODE_DISABLED = 0 - }; s32 pointer_index; s32 *offset_entry; if (pal_mode == PAL_MODE_DISABLED) { diff --git a/src/overlays/shared/ui/menus/initialize_pause_menu.c b/src/overlays/shared/ui/menus/initialize_pause_menu.c index b8818249e0..3c028e4d0a 100644 --- a/src/overlays/shared/ui/menus/initialize_pause_menu.c +++ b/src/overlays/shared/ui/menus/initialize_pause_menu.c @@ -183,6 +183,20 @@ extern int D_L00_00173E00[]; #include "rnc/overlay/shared/camera/level_camera.h" +enum { + PAUSE_MENU_PENDING_STATE_CLEARED = 0, + SCENE_STATE_DEFAULT = 2, + PAUSE_MENU_STATE_EXIT_GUARDED = 0x22 +}; + +enum { + PAUSE_MENU_STATE_PAGE_TRANSITION = 1, + PAUSE_MENU_STATE_LEVEL_TRANSITION_ENTRY = 0xE, + PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION = 0x14, + PAUSE_MENU_STATE_EXIT_GUARDED_ENTRY = 0x21, + PAUSE_MENU_STATE_PRESERVE_STATE_ENTRY = 0x23 +}; + extern s32 frame_size __asm__("D_0013E504") NOT_SDA; extern void reset_active_camera_position_and_basis(void) __asm__("FUN_00218d10"); extern s32 sce_gs_sync_v(s32) __asm__("FUN_00122298"); @@ -193,11 +207,6 @@ extern void FUN_L00_002df638(Ent *); /* Ported from rac1-decomp (src/overlays/shared/pause_00277208.c: func_L00_00277208). */ void initialize_pause_menu(void) { - enum { - PAUSE_MENU_PENDING_STATE_CLEARED = 0, - SCENE_STATE_DEFAULT = 2, - PAUSE_MENU_STATE_EXIT_GUARDED = 0x22 - }; enum { PAUSE_MENU_STATE_LEVEL_TRANSITION_ON_ACTION = 15 }; @@ -393,9 +402,6 @@ void initialize_pause_menu(void) { /* Closes the scene once its progress reaches 10: releases its objects, restores the hero's items and HUD bank, deletes the 14 scene mobies, shows the health and bolt HUD, enters state 0x14. */ void close_pause_menu(void) { - enum { - PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION = 0x14 - }; s32 i; s32 value; s32 handle; @@ -492,16 +498,6 @@ void close_pause_menu(void) { void update_pause_menu(void) __asm__("FUN_L00_00276bd0"); void update_pause_menu(void) { - enum { - SCENE_STATE_DEFAULT = 2 - }; - enum { - PAUSE_MENU_STATE_PAGE_TRANSITION = 1, - PAUSE_MENU_STATE_LEVEL_TRANSITION_ENTRY = 0xE, - PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION = 0x14, - PAUSE_MENU_STATE_EXIT_GUARDED_ENTRY = 0x21, - PAUSE_MENU_STATE_PRESERVE_STATE_ENTRY = 0x23 - }; Own *owner; Own *u8p; Mth *active_callback_object; @@ -730,9 +726,6 @@ extern void draw_menu_flashing_panel(int) __asm__("FUN_00223e28"); void draw_pause_menu_pages(int transfer_only) __asm__("FUN_L00_002772c0"); void draw_pause_menu_pages(int transfer_only) { - enum { - PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION = 0x14 - }; u128 corners[4]; u128 pad[5]; u128 box[2]; diff --git a/src/overlays/shared/vehicles/giant_clank_charged_blast.c b/src/overlays/shared/vehicles/giant_clank_charged_blast.c index 54d5cf87c7..c2b41fc355 100644 --- a/src/overlays/shared/vehicles/giant_clank_charged_blast.c +++ b/src/overlays/shared/vehicles/giant_clank_charged_blast.c @@ -12,6 +12,10 @@ #include "rnc/overlay/shared/math/vu0_vector_ops.h" #include "sda.h" +enum { + GIANT_CLANK_CHARGED_BLAST_CHARGING = 0 +}; + extern int D_L00_0015F320; extern int D_L00_0015F330; extern int allocate_packed_color_point_light_slot(float *pos, @@ -34,9 +38,6 @@ void *spawn_giant_clank_charged_blast(int unused, float *spawn_position) __asm__("FUN_L00_002a9aa0"); void *spawn_giant_clank_charged_blast(int unused, float *spawn_position) { - enum { - GIANT_CLANK_CHARGED_BLAST_CHARGING = 0 - }; char *spawned_moby = create_moby(0x5F3); if (spawned_moby != 0 && *(int *)&D_L00_001613C8_gp == 0) { char *moby_vars; @@ -88,9 +89,6 @@ void set_giant_clank_charged_blast_position(void *unused_creation_arg, OvlQuad * void remove_giant_clank_charged_blast(void) __asm__("FUN_L00_002a9be0"); void remove_giant_clank_charged_blast(void) { - enum { - GIANT_CLANK_CHARGED_BLAST_CHARGING = 0 - }; struct Moby *tracked_moby = *(char **)&D_L00_001613C8_gp; if (tracked_moby != 0) { if (tracked_moby->oclass == 0x5F3) { diff --git a/src/overlays/shared/vehicles/veldin_ship.c b/src/overlays/shared/vehicles/veldin_ship.c index 6d5811f0e3..d7175b43dd 100644 --- a/src/overlays/shared/vehicles/veldin_ship.c +++ b/src/overlays/shared/vehicles/veldin_ship.c @@ -10,6 +10,12 @@ #include "rnc/overlay/shared/camera/level_camera.h" #include "rnc/rendering/debug/debug_menu.h" +enum { + VELDIN_SHIP_STATE_UNINITIALIZED = 0, + VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING = 1, + VELDIN_SHIP_STATE_REFLECTION_INITIALIZED = 2 +}; + typedef struct { u128 points[4]; u32 colors[4]; @@ -69,10 +75,6 @@ extern s32 veldin_ship_visibility_selector[] __asm__("D_L00_0016C890"); void veldin_ship_draw(struct Moby *moby) __asm__("FUN_L00_002d19b0"); void veldin_ship_draw(struct Moby *moby) { - enum { - VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING = 1, - VELDIN_SHIP_STATE_REFLECTION_INITIALIZED = 2 - }; Quad_2d19b0 quad; Vec_2d19b0 normal, reflection, view; u8 *ship_render_state = ((u8 *)moby->pvars); @@ -150,10 +152,6 @@ void veldin_ship_update(M2d1e80 *m) __asm__("FUN_L00_002d1e80"); /* Moby class 530 */ void veldin_ship_update(M2d1e80 *moby) { - enum { - VELDIN_SHIP_STATE_UNINITIALIZED = 0, - VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING = 1 - }; s32 *ship_vars = moby->vars; if (moby->state == VELDIN_SHIP_STATE_UNINITIALIZED) { moby->state = VELDIN_SHIP_STATE_REFLECTION_INIT_PENDING; diff --git a/src/overlays/shared/vendor/initialize_vendor_screen.c b/src/overlays/shared/vendor/initialize_vendor_screen.c index 7023d462cc..a19df2d4e8 100644 --- a/src/overlays/shared/vendor/initialize_vendor_screen.c +++ b/src/overlays/shared/vendor/initialize_vendor_screen.c @@ -18,7 +18,9 @@ #include "rnc/audio/voices/sound_update.h" #include "rnc/overlay/shared/hero/hero_switch_item.h" #include "rnc/overlay/shared/hero/set_hero_animation.h" + void set_hero_item_moby_flag_bit0(void) __asm__("FUN_L00_00232fe8"); + #include "rnc/overlay/shared/streaming.h" #include "rnc/overlay/shared/ui/help/help_request.h" diff --git a/src/overlays/shared/vendor/vendor_menu.c b/src/overlays/shared/vendor/vendor_menu.c index 30fffbf1cf..e284d8720e 100644 --- a/src/overlays/shared/vendor/vendor_menu.c +++ b/src/overlays/shared/vendor/vendor_menu.c @@ -362,12 +362,6 @@ extern f32 frame_scale_macro __asm__("D_0015ED60") MACRO_ADDR; void open_vendor_menu(void *) __asm__("FUN_L00_0029a6b0"); void open_vendor_menu(void *vendor_moby_arg) { - enum { - VENDOR_PURCHASE_INACTIVE = 0, - VENDOR_MENU_MODE_EXISTING_VENDOR = 0, - VENDOR_MENU_OPENING = 0, - VENDOR_MENU_MODE_SPAWNED_VENDOR = 1 - }; VendorMoby_29a6b0 *vendor_moby = vendor_moby_arg; s32 i; Vec4 *vector_destination_cursor; @@ -570,9 +564,6 @@ extern void sce_gs_sync_v(s32) __asm__("FUN_00122298"); void start_vendor_exit_cutscene(void) __asm__("FUN_L00_0029ad08"); void start_vendor_exit_cutscene(void) { - enum { - VENDOR_MENU_EXIT_CUTSCENE = 3 - }; enum { SECONDARY_MUSIC_STREAM_READY_TO_CONTINUE = 3 }; @@ -868,6 +859,20 @@ extern u8 vendor_part_update_label[] __asm__("D_L00_00161148"); #include "rnc/overlay/shared/vendor/vendor_menu_data/update_vendor_purchase_2.h" #include "rnc/overlay/shared/vendor/vendor_menu_data/update_vendor_purchase.h" +enum { + VENDOR_MENU_MODE_EXISTING_VENDOR = 0, + VENDOR_MENU_OPENING = 0, + VENDOR_PURCHASE_INACTIVE = 0, + VENDOR_MENU_MODE_SPAWNED_VENDOR = 1, + VENDOR_MENU_OPEN = 1, + VENDOR_PURCHASE_INITIALIZE = 1, + VENDOR_MENU_CLOSING = 2, + VENDOR_PURCHASE_AWAIT_INPUT = 2, + VENDOR_MENU_EXIT_CUTSCENE = 3, + VENDOR_PURCHASE_WAIT_DECISION_ANIMATION = 3, + VENDOR_PURCHASE_FINALIZE = 4 +}; + extern f32 D_L00_00161E24; extern s32 D_L00_00161E38; extern Vec4 D_L00_00165F80[3]; @@ -905,14 +910,6 @@ extern void set_scrolling_status_message(int) __asm__("FUN_00237e90"); #define CUR_TB (D_L00_001C40B0[CUR_ITEM.item]) void update_vendor_purchase(void) { - enum { - VENDOR_PURCHASE_INACTIVE = 0, - VENDOR_MENU_MODE_EXISTING_VENDOR = 0, - VENDOR_PURCHASE_INITIALIZE = 1, - VENDOR_PURCHASE_AWAIT_INPUT = 2, - VENDOR_PURCHASE_WAIT_DECISION_ANIMATION = 3, - VENDOR_PURCHASE_FINALIZE = 4 - }; u128 lv; s32 purchase_state; s32 purchase_cost, k, last_row_index; @@ -1142,17 +1139,6 @@ void update_vendor_purchase(void) { void update_vendor_menu(void) __asm__("FUN_L00_0029c648"); void update_vendor_menu(void) { - enum { - VENDOR_MENU_OPENING = 0, - VENDOR_MENU_OPEN = 1, - VENDOR_MENU_CLOSING = 2, - VENDOR_MENU_EXIT_CUTSCENE = 3 - }; - enum { - VENDOR_MENU_MODE_EXISTING_VENDOR = 0, - VENDOR_PURCHASE_INACTIVE = 0, - VENDOR_PURCHASE_INITIALIZE = 1 - }; enum { VENDOR_ROW_PURCHASE_REQUEST_ENABLED = 0 }; diff --git a/src/overlays/shared/weapons/bomb_glove_bomb.c b/src/overlays/shared/weapons/bomb_glove_bomb.c index 50a47f93b8..507dcceea1 100644 --- a/src/overlays/shared/weapons/bomb_glove_bomb.c +++ b/src/overlays/shared/weapons/bomb_glove_bomb.c @@ -21,6 +21,11 @@ #include "rnc/overlay/shared/weapons/mine.h" #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" +enum { + BOMB_STATE_HELD = 0, + THROW_LANDING_MODE_SKIP_LINKED_MOBY_MARKER = 2 +}; + typedef struct { char p0[0x80]; float pos[4]; @@ -805,9 +810,6 @@ void draw_bomb_landing_marker(M_2acbf0_002acbf0 *moby) { unsigned char *spawn_bomb(int owner, void *pos) __asm__("FUN_L00_002ace70"); unsigned char *spawn_bomb(int bomb_holder_moby, void *spawn_position) { - enum { - BOMB_STATE_HELD = 0 - }; unsigned char *bomb_moby = create_moby(0x79); if (bomb_moby) { V_2ace70 u, random_rotation; @@ -938,10 +940,6 @@ void launch_bomb(float *pos, unsigned char *moby, float *velocity) { int predict_throw_landing(LandingVars *v, M910 *thrown_moby, int mode) __asm__("FUN_L00_002ad410"); int predict_throw_landing(LandingVars *v, M910 *thrown_moby, int mode) { - enum { - BOMB_STATE_HELD = 0, - THROW_LANDING_MODE_SKIP_LINKED_MOBY_MARKER = 2 - }; U910 position, velocity, previous, hero_position, offset, start; int timer; int object_hit; diff --git a/src/overlays/shared/weapons/decoy.c b/src/overlays/shared/weapons/decoy.c index 7caf30df6a..8764cc5c5a 100644 --- a/src/overlays/shared/weapons/decoy.c +++ b/src/overlays/shared/weapons/decoy.c @@ -22,6 +22,19 @@ #include "qzero.h" #include "rnc/runtime/callbacks/add_draw_callback.h" +enum { + DECOY_INITIALIZE = 0, + LANDING_REQUIRE_MOBY_PVARS_LINK = 0, + DECOY_HELD = 1, + DECOY_THROWN_MOVEMENT = 2, + LANDING_SKIP_LINKED_MOBY_DRAW = 2, + DECOY_SETTLED_MOVEMENT = 3, + DECOY_PRE_REMOVAL_DELAY = 4, + DECOY_WAIT_TO_SHRINK = 5, + DECOY_SHRINK_FOR_REMOVAL = 6, + DECOY_RESET_TO_INITIALIZE = 7 +}; + typedef struct DecoyVars { u8 pad0[0x10]; f32 unk10[4]; @@ -202,10 +215,6 @@ void destroy_decoy_with_particles(unsigned char *moby) { u8 *spawn_decoy(s32 value, u128 *position, u128 *other_position) __asm__("FUN_L00_002c35c0"); u8 *spawn_decoy(s32 owner_moby, u128 *position, u128 *other_position) { - enum { - DECOY_INITIALIZE = 0, - DECOY_WAIT_TO_SHRINK = 5 - }; u8 *flags = item_text_variant; u8 *spawned_moby; u8 *decoy_vars; @@ -282,10 +291,6 @@ void release_moby_with_collision_check(float *release_position, char *moby, void *initial_velocity) { - enum { - DECOY_THROWN_MOVEMENT = 2, - DECOY_PRE_REMOVAL_DELAY = 4 - }; float collision_start[4], collision_normal[4], rotated_normal[4]; char *state = *(char **)(moby + 0x78); struct Hero *camera; @@ -355,11 +360,6 @@ s32 predict_thrown_moby_landing(ThrowVars *throw_vars, s32 mode) __asm__("FUN_L00_002c3af8"); s32 predict_thrown_moby_landing(ThrowVars *throw_vars, struct Moby *thrown_moby, s32 mode) { - enum { - LANDING_REQUIRE_MOBY_PVARS_LINK = 0, - DECOY_HELD = 1, - LANDING_SKIP_LINKED_MOBY_DRAW = 2 - }; Vec4 predicted_position, predicted_velocity, position_scratch, q, ground_probe_position; s32 prediction_countdown; s32 found = 0; @@ -547,16 +547,6 @@ void decoy_update(char *moby) __asm__("FUN_L00_002c4380"); /* Moby classes 203, 1900 */ void decoy_update(char *moby) { - enum { - DECOY_INITIALIZE = 0, - DECOY_HELD = 1, - DECOY_THROWN_MOVEMENT = 2, - DECOY_SETTLED_MOVEMENT = 3, - DECOY_PRE_REMOVAL_DELAY = 4, - DECOY_WAIT_TO_SHRINK = 5, - DECOY_SHRINK_FOR_REMOVAL = 6, - DECOY_RESET_TO_INITIALIZE = 7 - }; int active = ((unsigned char *)&D_0013E533)[6]; DecoyVars *decoy_instance_vars = (DecoyVars *)(*(char **)(moby + 0x78)); char *target; diff --git a/src/overlays/shared/weapons/doom_bot_movement.c b/src/overlays/shared/weapons/doom_bot_movement.c index f5b7bcb0c9..acaeeb67dc 100644 --- a/src/overlays/shared/weapons/doom_bot_movement.c +++ b/src/overlays/shared/weapons/doom_bot_movement.c @@ -10,6 +10,10 @@ #include "qzero.h" #include "rnc/overlay/shared/math/interpolation/spring_turn.h" +enum { + COLLISION_MATERIAL_WATER = 0 +}; + typedef struct { float x, y, z, w; } Vx __attribute__((aligned(16))); @@ -225,9 +229,6 @@ float probe_moby_landing_height(Vec4_2bec80 *probe_position, void *probing_moby) __asm__("FUN_L00_002bec80"); float probe_moby_landing_height(Vec4_2bec80 *probe_position, void *probing_moby) { - enum { - COLLISION_MATERIAL_WATER = 0 - }; Vec4_2bec80 lower_probe_point, upper_probe_point; float f, unclamped_lower_z; qcopy(&lower_probe_point, probe_position); @@ -665,9 +666,6 @@ int try_start_moby_hop(Mob_2C0CF8 *moby, Blk *block, void *target, int check_lin int compute_moby_state_from_vertical_probe(unsigned char *moby) __asm__("FUN_L00_002bfec8"); int compute_moby_state_from_vertical_probe(unsigned char *moby) { - enum { - COLLISION_MATERIAL_WATER = 0 - }; enum { DOOM_BOT_DETONATE = 11 }; diff --git a/src/overlays/shared/weapons/glove_of_doom_bomb.c b/src/overlays/shared/weapons/glove_of_doom_bomb.c index 0051ef1c42..b7d62d0bb1 100644 --- a/src/overlays/shared/weapons/glove_of_doom_bomb.c +++ b/src/overlays/shared/weapons/glove_of_doom_bomb.c @@ -15,6 +15,17 @@ #include "rnc/overlay/shared/rendering/effects/update_three_phase_effect_particle.h" #include "rnc/overlay/shared/weapons.h" +enum { + DOOM_LANDING_MODE_REQUIRE_LINKED_MOBY = 0, + THROWN_MOBY_STATE_INITIALIZE = 0, + THROWN_MOBY_STATE_GROW_TO_QUARTER_SCALE = 1, + DOOM_LANDING_MODE_SKIP_LINKED_MOBY_DRAW_CALLBACK = 2, + THROWN_MOBY_STATE_MOVE_WITH_COLLISION = 2, + THROWN_MOBY_STATE_SPAWN_SEQUENCE = 3, + THROWN_MOBY_STATE_FADE_OUT = 4, + THROWN_MOBY_STATE_RESET_TO_INITIALIZE = 5 +}; + /* Vars of a thrown moby, as ThrowVars in trespasser.c without its first 0x10 bytes. */ typedef struct { Vec4 vel; /* 0x00: velocity per step */ @@ -61,11 +72,6 @@ s32 predict_doom_bot_spawner_landing(ThrowVars *throw_vars, s32 mode) __asm__("FUN_L00_002c8440"); s32 predict_doom_bot_spawner_landing(ThrowVars *throw_vars, struct Moby *thrown_moby, s32 mode) { - enum { - DOOM_LANDING_MODE_REQUIRE_LINKED_MOBY = 0, - THROWN_MOBY_STATE_GROW_TO_QUARTER_SCALE = 1, - DOOM_LANDING_MODE_SKIP_LINKED_MOBY_DRAW_CALLBACK = 2 - }; Vec4 simulated_position, simulated_velocity, position_scratch, q, landing_probe_position; s32 prediction_timer; s32 found = 0; @@ -187,14 +193,6 @@ void doom_bot_spawner_update(struct Moby *thrown_moby) __asm__("FUN_L00_002c89e8 /* Moby class 230 */ void doom_bot_spawner_update(struct Moby *thrown_moby) { - enum { - THROWN_MOBY_STATE_INITIALIZE = 0, - THROWN_MOBY_STATE_GROW_TO_QUARTER_SCALE = 1, - THROWN_MOBY_STATE_MOVE_WITH_COLLISION = 2, - THROWN_MOBY_STATE_SPAWN_SEQUENCE = 3, - THROWN_MOBY_STATE_FADE_OUT = 4, - THROWN_MOBY_STATE_RESET_TO_INITIALIZE = 5 - }; Vec4 next_pos, start, end, probe; ThrowVars *spawner_throw_vars; struct Moby *population_scan_moby; diff --git a/src/overlays/shared/weapons/mine.c b/src/overlays/shared/weapons/mine.c index 35746fcf59..ba3374f1f9 100644 --- a/src/overlays/shared/weapons/mine.c +++ b/src/overlays/shared/weapons/mine.c @@ -24,6 +24,13 @@ #include "rnc/runtime/callbacks/add_draw_callback.h" #include "rnc/world/collision/collision_hit_material.h" +enum { + MINE_STATE_OWNER_ATTACHED = 0, + MINE_HOMING_RISE_PHASE = 1, + MINE_STATE_FREE_MOTION = 1, + MINE_HOMING_FALL_PHASE = 2 +}; + typedef struct MineVars { u8 pad0[0x30]; s32 unk30; @@ -403,9 +410,6 @@ s32 FUN_L00_002603d0_2aa008(void *) __asm__("FUN_L00_002603d0"); unsigned char *spawn_mine(int owner, OvlQuad *pos) __asm__("FUN_L00_002a9ed0"); unsigned char *spawn_mine(int mine_owner_moby, OvlQuad *spawn_position) { - enum { - MINE_STATE_OWNER_ATTACHED = 0 - }; unsigned char *mine_moby = create_moby(0x4A); if (mine_moby) { MineVars *mine_vars = (MineVars *)MOBY(mine_moby)->pvars; @@ -516,9 +520,6 @@ void initialize_moby_motion_at_position(V_2aa008 *requested_position, int predict_mine_impact(char *trajectory_state, char *moby, int mode) __asm__("FUN_L00_002aa2a8"); int predict_mine_impact(char *trajectory_state, char *moby, int mode) { - enum { - MINE_STATE_OWNER_ATTACHED = 0 - }; enum { MINE_PREDICTION_REQUIRE_LINKED_MOBY_HIT = 0, MINE_PREDICTION_HIDE_LINKED_MOBY_HIT_MARKER = 2 @@ -632,12 +633,6 @@ void mine_update(M910 *mine_moby) { MINE_DEBRIS_SHORT_LIVED = 2, MINE_DEBRIS_SPHERICAL_VELOCITY = 3 }; - enum { - MINE_STATE_OWNER_ATTACHED = 0, - MINE_STATE_FREE_MOTION = 1, - MINE_HOMING_RISE_PHASE = 1, - MINE_HOMING_FALL_PHASE = 2 - }; B910 camera_blast_parameters = l00_mine_camera_blast_parameters; B910 alternate_camera_blast_parameters = l00_mine_alternate_camera_blast_parameters; U910 collision_response_velocity; diff --git a/src/overlays/shared/weapons/morphoray_chicken.c b/src/overlays/shared/weapons/morphoray_chicken.c index ca61370b02..d19e853076 100644 --- a/src/overlays/shared/weapons/morphoray_chicken.c +++ b/src/overlays/shared/weapons/morphoray_chicken.c @@ -17,6 +17,15 @@ #include "rnc/overlay/shared/math/random/random_int_between.h" #include "rnc/math/fast_math.h" +enum { + CHICKEN_STATE_INITIALIZE = 0, + CHICKEN_STATE_IDLE = 1, + CHICKEN_STATE_TURN_AWAY_FROM_HERO = 2, + CHICKEN_STATE_FLEE_FROM_HERO = 3, + CHICKEN_STATE_CLOSE_RANGE_FLEE_FROM_HERO = 4, + CHICKEN_STATE_EMIT_FEATHERS = 5 +}; + typedef union { u128 q; f32 f[4]; @@ -234,10 +243,6 @@ void reset_morphoray_chicken_slot_defaults(char *morphoray_chicken_slot_record) struct Moby *spawn_morphoray_chicken(State *source_state) __asm__("FUN_L00_002c9348"); struct Moby *spawn_morphoray_chicken(State *source_state) { - enum { - CHICKEN_STATE_IDLE = 1, - CHICKEN_STATE_EMIT_FEATHERS = 5 - }; enum { MOBY_STATE_NON_SPAWN_POOL_REMOVAL = 0xFD, MOBY_STATE_SPAWN_POOL_REMOVAL = 0xFE @@ -359,14 +364,6 @@ void morphoray_chicken_update(Moby *chicken_moby) __asm__("FUN_L00_002c97e0"); /* Moby class 270 */ void morphoray_chicken_update(Moby *chicken_moby) { - enum { - CHICKEN_STATE_INITIALIZE = 0, - CHICKEN_STATE_IDLE = 1, - CHICKEN_STATE_TURN_AWAY_FROM_HERO = 2, - CHICKEN_STATE_FLEE_FROM_HERO = 3, - CHICKEN_STATE_CLOSE_RANGE_FLEE_FROM_HERO = 4, - CHICKEN_STATE_EMIT_FEATHERS = 5 - }; enum { CHICKEN_STATE_DEAD = 6 }; @@ -828,10 +825,6 @@ void morphoray_chicken_update(Moby *chicken_moby) { int moby_set_state_from_check(struct Moby *a) __asm__("FUN_L00_002cadc0"); int moby_set_state_from_check(struct Moby *checked_moby) { - enum { - CHICKEN_STATE_IDLE = 1, - CHICKEN_STATE_EMIT_FEATHERS = 5 - }; int suction_result = process_moby_suck_cannon_suction(checked_moby); if (suction_result == 0) { if (checked_moby->state == CHICKEN_STATE_EMIT_FEATHERS) @@ -855,10 +848,6 @@ int launch_suck_cannon_projectile_and_update_moby_state(struct Moby *moby, int target_moby, float target_height_offset) { - enum { - CHICKEN_STATE_IDLE = 1, - CHICKEN_STATE_EMIT_FEATHERS = 5 - }; char *class_callback_data = get_moby_suck_cannon_record(moby); int projectile_launch_result = launch_suck_cannon_projectile( moby, launch_vector_address, target_moby, target_height_offset); diff --git a/src/overlays/shared/weapons/pyrocitor.c b/src/overlays/shared/weapons/pyrocitor.c index f10dd83db1..ac9c0711cc 100644 --- a/src/overlays/shared/weapons/pyrocitor.c +++ b/src/overlays/shared/weapons/pyrocitor.c @@ -18,6 +18,14 @@ #include "rnc/overlay/shared/camera/level_camera.h" #include "rnc/overlay/shared/weapons/devastator.h" +enum { + PYROCITOR_STATE_INITIALIZE = 0, + PYROCITOR_STATE_WAIT_FOR_READY = 1, + PYROCITOR_STATE_READY = 2, + PYROCITOR_STATE_FIRING = 3, + PYROCITOR_STATE_CLEANUP = 4 +}; + /* Ported from rac1-decomp (nonmatching/shared/func_L00_002B8AE8.c: func_L00_002B8AE8). */ typedef struct PyrocitorVars { struct Moby *other; @@ -518,12 +526,6 @@ void pyrocitor_update(struct Moby *moby) __asm__("FUN_L00_002b77f0"); /* Moby class 176 */ void pyrocitor_update(struct Moby *moby) { - enum { - PYROCITOR_STATE_INITIALIZE = 0, - PYROCITOR_STATE_WAIT_FOR_READY = 1, - PYROCITOR_STATE_READY = 2, - PYROCITOR_STATE_FIRING = 3 - }; PyrocitorVars *pyrocitor_vars = (PyrocitorVars *)moby->pvars; Vec_2b2100 pos, light_offset_and_flame_velocity, light_color_and_flame_origin, endpoint, particle_pos, random_vec; @@ -742,10 +744,6 @@ void pyrocitor_update(struct Moby *moby) { void update_pyrocitor_usage_and_cleanup(struct Moby *pyrocitor_moby) __asm__("FUN_L00_002b8230"); void update_pyrocitor_usage_and_cleanup(struct Moby *pyrocitor_moby) { - enum { - PYROCITOR_STATE_FIRING = 3, - PYROCITOR_STATE_CLEANUP = 4 - }; unsigned char *pyrocitor_vars = ((unsigned char *)pyrocitor_moby->pvars); struct UsageStats *P; unsigned char *voice; diff --git a/src/overlays/shared/weapons/swingshot_hook.c b/src/overlays/shared/weapons/swingshot_hook.c index 1887e9f231..384ab07359 100644 --- a/src/overlays/shared/weapons/swingshot_hook.c +++ b/src/overlays/shared/weapons/swingshot_hook.c @@ -10,6 +10,17 @@ #include "rnc/overlay/shared/rendering/set_moby_color.h" #include "rnc/overlay/shared/mobys/evaluate_moby_animation_pose.h" +enum { + HOOK_INITIAL_ANIMATION = 0, + HOOK_IDLE_ANIMATION = 1, + HOOK_REMOVAL_ANIMATION = 2, + HOOK_LAUNCH_ANIMATION = 3, + HOOK_FLIGHT_ANIMATION = 4, + HOOK_ATTACHED_ANIMATION = 5, + HOOK_SKIP_ANIMATION_TRANSITIONS = 6, + HOOK_RETURN_ANIMATION = 7 +}; + extern int scale_game_frames(int) __asm__("FUN_001f96f8"); int FUN_001f96f8_2c7070(int) __asm__("FUN_001f96f8"); @@ -19,9 +30,6 @@ unsigned char *spawn_swingshot_hook(unsigned char *owner_moby, float initial_hook_speed) __asm__("FUN_L00_002c6f88"); unsigned char *spawn_swingshot_hook(unsigned char *owner_moby, float initial_hook_speed) { - enum { - HOOK_INITIAL_ANIMATION = 0 - }; unsigned char *spawned_moby = create_moby(0xd1); if (spawned_moby) { char *moby_vars = *(char **)(spawned_moby + 0x78); @@ -48,16 +56,6 @@ void swingshot_hook_update(unsigned char *m) __asm__("FUN_L00_002c7070"); /* Moby class 209 */ void swingshot_hook_update(unsigned char *hook_moby) { - enum { - HOOK_INITIAL_ANIMATION = 0, - HOOK_IDLE_ANIMATION = 1, - HOOK_REMOVAL_ANIMATION = 2, - HOOK_LAUNCH_ANIMATION = 3, - HOOK_FLIGHT_ANIMATION = 4, - HOOK_ATTACHED_ANIMATION = 5, - HOOK_SKIP_ANIMATION_TRANSITIONS = 6, - HOOK_RETURN_ANIMATION = 7 - }; enum { MOBY_STATE_MARKED_FOR_REMOVAL = 0xFE }; diff --git a/src/overlays/shared/weapons/thruster_pack_flame.c b/src/overlays/shared/weapons/thruster_pack_flame.c index fdda257547..cedf69fd5d 100644 --- a/src/overlays/shared/weapons/thruster_pack_flame.c +++ b/src/overlays/shared/weapons/thruster_pack_flame.c @@ -16,6 +16,14 @@ #include "rnc/overlay/shared/hero/hero_switch_item.h" #include "rnc/ui/text/font/font_queue_vu_state.h" +enum { + STATE_INITIALIZE = 0, + STATE_WAIT_FOR_BEAM = 1, + STATE_BEAM_GROW = 2, + STATE_BEAM_ACTIVE = 3, + STATE_BEAM_SHRINK = 4 +}; + #define BEAM_QUAD_YZ \ { \ {0.0f, -2.0f, 2.0f, 1.0f}, {0.0f, -2.0f, -2.0f, 1.0f}, {0.0f, 2.0f, 2.0f, 1.0f}, { \ @@ -847,9 +855,6 @@ void emit_beam_trail_particles(X *x) { char *spawn_thruster_pack_flame(int instance_index) __asm__("FUN_L00_002b4138"); char *spawn_thruster_pack_flame(int instance_index) { - enum { - STATE_INITIALIZE = 0 - }; char *spawned_moby = create_moby(0xA7); if (spawned_moby != 0) { int *moby_vars = ((int *)MOBY(spawned_moby)->pvars); @@ -869,13 +874,6 @@ void thruster_pack_flame_update(void *moby) __asm__("FUN_L00_002b4198"); /* Moby class 167 */ void thruster_pack_flame_update(void *moby) { - enum { - STATE_INITIALIZE = 0, - STATE_WAIT_FOR_BEAM = 1, - STATE_BEAM_GROW = 2, - STATE_BEAM_ACTIVE = 3, - STATE_BEAM_SHRINK = 4 - }; O_4198 *beam_moby = (O_4198 *)moby; V_4198 *v = beam_moby->v; s32 flag = 0; diff --git a/src/rendering/lights/update_all_point_lights.c b/src/rendering/lights/update_all_point_lights.c index 231413c14a..377f2e4831 100644 --- a/src/rendering/lights/update_all_point_lights.c +++ b/src/rendering/lights/update_all_point_lights.c @@ -49,7 +49,8 @@ void update_all_point_lights(void) { struct PointLight *light = &point_lights[light_index]; struct PointLightSlot *slot = &((struct PointLightSlot *)point_light_data)[light_index]; - if (slot->link_state != POINT_LIGHT_LINK_INACTIVE && fast_vec_dist(light->sphere, slot->linked_sphere) > 8.0f) { + if (slot->link_state != POINT_LIGHT_LINK_INACTIVE && + fast_vec_dist(light->sphere, slot->linked_sphere) > 8.0f) { qcopy(slot->linked_sphere, light->sphere); if (slot->link_state == POINT_LIGHT_LINK_PENDING_CREATION) { create_point_light(light_index); diff --git a/src/ui/help/draw_help.c b/src/ui/help/draw_help.c index 3cde62de80..ae0a9a74fa 100644 --- a/src/ui/help/draw_help.c +++ b/src/ui/help/draw_help.c @@ -69,8 +69,10 @@ void draw_help(void) { break; case HELP_PROMPT_FRAME_TRANSITION: if (D_0015EF1D_b) { - int transition_half_width = (help_state.half_width - 0x20) * help_state.timer / 8 + 0x20; - int transition_half_height = (help_state.half_height - 0x20) * help_state.timer / 8 + 0x20; + int transition_half_width = + (help_state.half_width - 0x20) * help_state.timer / 8 + 0x20; + int transition_half_height = + (help_state.half_height - 0x20) * help_state.timer / 8 + 0x20; int alpha; help_state.frame_half_width = transition_half_width; @@ -125,9 +127,9 @@ void draw_help(void) { case HELP_FRAME_CLOSING: if (D_0015EF1D_b) { int closing_half_width = help_state.frame_half_width - - (help_state.frame_half_width - 8) * help_state.timer / 8; + (help_state.frame_half_width - 8) * help_state.timer / 8; int closing_half_height = help_state.frame_half_height - - (help_state.frame_half_height - 8) * help_state.timer / 8; + (help_state.frame_half_height - 8) * help_state.timer / 8; draw_ui_frame(help_state.center_y - closing_half_height, help_state.center_y + closing_half_height, diff --git a/src/ui/help/help_draw_prompt.c b/src/ui/help/help_draw_prompt.c index da3922a64e..7f4a46ece1 100644 --- a/src/ui/help/help_draw_prompt.c +++ b/src/ui/help/help_draw_prompt.c @@ -21,7 +21,8 @@ void help_draw_prompt(void) { help_state.center_x - 0x20, help_state.center_x + 0x20, 0x60); - if (help_state.state == HELP_STATE_FRAME_EXPAND || help_state.state == HELP_STATE_FRAME_COLLAPSE) { + if (help_state.state == HELP_STATE_FRAME_EXPAND || + help_state.state == HELP_STATE_FRAME_COLLAPSE) { alpha = help_state.timer * 21; } else { alpha = 0x7E; From bd44892f380b2a8becc5cea9e075e6dc63b3e640 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 17:53:08 +0000 Subject: [PATCH 1500/1502] decomp: format naming changes after upstream rebase --- src/overlays/l06/mobys/alien_queen.c | 5 ++++- src/overlays/l10/mobys/blarg_ship.c | 5 ++++- src/overlays/l13/mobys/blarg_space_commando.c | 5 ++++- src/overlays/l13/mobys/blarg_space_fighter.c | 5 ++++- src/overlays/l13/mobys/qwarks_starfighter.c | 14 ++++++++++---- src/overlays/l18/mobys/falling_moby_group.c | 5 ++++- src/overlays/shared/enemies/plasmabot.c | 5 ++++- .../shared/ui/menus/initialize_pause_menu.c | 5 ++++- src/overlays/shared/weapons/bomb_glove_bomb.c | 5 ++++- src/overlays/shared/weapons/decoy.c | 7 +++++-- src/overlays/shared/weapons/glove_of_doom_bomb.c | 5 ++++- 11 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/overlays/l06/mobys/alien_queen.c b/src/overlays/l06/mobys/alien_queen.c index bbb5a1e267..aa33cd93b8 100644 --- a/src/overlays/l06/mobys/alien_queen.c +++ b/src/overlays/l06/mobys/alien_queen.c @@ -186,7 +186,6 @@ void update_alien_queen_hit_response_and_recovery(char *moby) __asm__("FUN_L06_0 enum { ALIEN_QUEEN_STATE_INITIALIZE = 0, ALIEN_QUEEN_STATE_WAIT_TO_START_INTRO = 1, - HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1, ALIEN_QUEEN_STATE_INTRO = 2, ALIEN_QUEEN_STATE_FIRST_RECOVERY_CAMERA = 3, ALIEN_QUEEN_STATE_FROG_RECOVERY_ORBIT = 4, @@ -203,6 +202,10 @@ enum { ALIEN_QUEEN_STATE_POST_DEATH = 15 }; +enum { + HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1 +}; + /* Ported from rac1-decomp (src/overlays/l06_blarg/vendor_002B5990.c: func_L06_002FC578), where it is exact; names translated to the US level program. */ extern int *D_L06_001B0FB0[] __asm__("D_L06_001B0C30"); void start_alien_queen_intro(char *moby) __asm__("FUN_L06_002fb148"); diff --git a/src/overlays/l10/mobys/blarg_ship.c b/src/overlays/l10/mobys/blarg_ship.c index a2edbfd81f..a8aaea5fe6 100644 --- a/src/overlays/l10/mobys/blarg_ship.c +++ b/src/overlays/l10/mobys/blarg_ship.c @@ -138,7 +138,6 @@ extern int D_L10_00161EE4 __attribute__((sda)); enum { BLARG_SHIP_STATE_INITIALIZE = 0, BLARG_SHIP_STATE_WAIT_FOR_TARGET_IN_VOLUME = 1, - HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1, BLARG_SHIP_STATE_RISE_TO_ENTRY_PATH = 2, BLARG_SHIP_STATE_FOLLOW_ENTRY_PATH = 3, BLARG_SHIP_STATE_FIRE_AT_TARGET = 4, @@ -148,6 +147,10 @@ enum { BLARG_SHIP_STATE_EXPLODE = 8 }; +enum { + HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1 +}; + float blarg_ship_rocket_speed_gp __asm__("D_L10_00161EE8") = 32.0f; float blarg_ship_firing_animation_speed_gp __asm__("D_L10_00161EEC") = 2.0f; extern unsigned char D_0013D4CB[]; diff --git a/src/overlays/l13/mobys/blarg_space_commando.c b/src/overlays/l13/mobys/blarg_space_commando.c index a2a6603b8e..2370c1bab8 100644 --- a/src/overlays/l13/mobys/blarg_space_commando.c +++ b/src/overlays/l13/mobys/blarg_space_commando.c @@ -562,7 +562,6 @@ extern f32 D_L13_00161E58 __attribute__((sda)); enum { BLARG_SPACE_COMMANDO_INITIALIZE = 0, BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION = 1, - HIT_STATUS_SKIP_DAMAGE_PROCESSING = 1, BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION = 2, BLARG_SPACE_COMMANDO_SELECT_ACTION_AFTER_ANIMATION = 3, BLARG_SPACE_COMMANDO_FACE_TARGET_AND_WAIT_FOR_TIMER = 4, @@ -576,6 +575,10 @@ enum { BLARG_SPACE_COMMANDO_DYING = 16 }; +enum { + HIT_STATUS_SKIP_DAMAGE_PROCESSING = 1 +}; + extern char D_L13_00160680[] MACRO_ADDR; extern s32 D_001413D0_lui[] __asm__("D_001413D0") NOT_SDA; diff --git a/src/overlays/l13/mobys/blarg_space_fighter.c b/src/overlays/l13/mobys/blarg_space_fighter.c index 9adb928290..bb8532f192 100644 --- a/src/overlays/l13/mobys/blarg_space_fighter.c +++ b/src/overlays/l13/mobys/blarg_space_fighter.c @@ -53,11 +53,14 @@ enum { FIGHTER_INITIALIZE = 0, FIGHTER_WAIT_TO_JOIN_PATH = 1, FIGHTER_FOLLOW_PATH_AND_ATTACK = 2, - HIT_PROCESSING_DAMAGE_THRESHOLD = 2, FIGHTER_EMIT_DESTRUCTION_EFFECTS = 3, FIGHTER_WAIT_TO_REINITIALIZE = 4 }; +enum { + HIT_PROCESSING_DAMAGE_THRESHOLD = 2 +}; + extern float random_float_between(float, float) __asm__("FUN_002132a8"); extern void trooper_anim_update(void *, short *) __asm__("FUN_L00_0025d458"); diff --git a/src/overlays/l13/mobys/qwarks_starfighter.c b/src/overlays/l13/mobys/qwarks_starfighter.c index 6fdf2cac8c..cf5f5de99f 100644 --- a/src/overlays/l13/mobys/qwarks_starfighter.c +++ b/src/overlays/l13/mobys/qwarks_starfighter.c @@ -36,19 +36,25 @@ enum { ATTACHMENT_DAMAGE_NONE = 0, - STARFIGHTER_STATE_INITIALIZE = 0, ATTACHMENT_DAMAGE_APPLIED = 1, - STARFIGHTER_STATE_WAIT_FOR_HERO_SHIP = 1, ATTACHMENT_DAMAGE_STAGE_ADVANCED = 2, + ATTACHMENT_DAMAGE_LETHAL = 3 +}; + +enum { + STARFIGHTER_STATE_INITIALIZE = 0, + STARFIGHTER_STATE_WAIT_FOR_HERO_SHIP = 1, STARFIGHTER_STATE_FOLLOW_INITIAL_PATH = 2, - ATTACHMENT_DAMAGE_LETHAL = 3, STARFIGHTER_STATE_FOLLOW_COMMAND_PATH = 3, STARFIGHTER_STATE_FOLLOW_COMMAND_PATH_WITH_TIMED_VOLLEY = 4, STARFIGHTER_STATE_TRACTOR_BEAM = 5, STARFIGHTER_STATE_OWNER_UNAVAILABLE = 6, STARFIGHTER_STATE_DEATH_FLIGHT = 7, STARFIGHTER_STATE_EXPLODE_AND_REMOVE = 8, - STARFIGHTER_STATE_RESET = 9, + STARFIGHTER_STATE_RESET = 9 +}; + +enum { MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE }; diff --git a/src/overlays/l18/mobys/falling_moby_group.c b/src/overlays/l18/mobys/falling_moby_group.c index 040f2559fd..a88e8dfa76 100644 --- a/src/overlays/l18/mobys/falling_moby_group.c +++ b/src/overlays/l18/mobys/falling_moby_group.c @@ -245,11 +245,14 @@ extern void mark_block_entries_within_transform_xy_bounds(int, int) __asm__("FUN enum { MOBY_INITIALIZE = 0, - FALLING_MOBY_GROUP_AWAIT_ACTIVATION = 1, MOBY_APPROACH_TARGET_TRANSFORM = 2, MOBY_FALL_AND_REMOVE = 4 }; +enum { + FALLING_MOBY_GROUP_AWAIT_ACTIVATION = 1 +}; + void activate_drek_boss_class_0565_moby(struct Moby *moby) __asm__("FUN_L18_002f1c38"); void activate_drek_boss_class_0565_moby(struct Moby *moby) { diff --git a/src/overlays/shared/enemies/plasmabot.c b/src/overlays/shared/enemies/plasmabot.c index 698072146f..51090fac48 100644 --- a/src/overlays/shared/enemies/plasmabot.c +++ b/src/overlays/shared/enemies/plasmabot.c @@ -818,7 +818,6 @@ extern u8 D_L14_0015F580[] MACRO_ADDR; enum { PLASMABOT_INITIALIZE = 0, - HIT_KIND_SKIP_DAMAGE_AND_REACTION = 1, PLASMABOT_WAIT_TO_START_PATH_TRAVERSAL = 1, PLASMABOT_START_PATH_TRAVERSAL = 2, PLASMABOT_FOLLOW_PATH_FORWARD = 3, @@ -834,6 +833,10 @@ enum { PLASMABOT_FACE_TARGET_AND_WAIT = 13 }; +enum { + HIT_KIND_SKIP_DAMAGE_AND_REACTION = 1 +}; + extern void FUN_L14_002b3a20_c(struct Moby *) __asm__("FUN_L14_002b3a20"); extern void FUN_L14_002b2928_u(struct Moby *) __asm__("FUN_L14_002b2928"); diff --git a/src/overlays/shared/ui/menus/initialize_pause_menu.c b/src/overlays/shared/ui/menus/initialize_pause_menu.c index 3c028e4d0a..dbbc120861 100644 --- a/src/overlays/shared/ui/menus/initialize_pause_menu.c +++ b/src/overlays/shared/ui/menus/initialize_pause_menu.c @@ -185,10 +185,13 @@ extern int D_L00_00173E00[]; enum { PAUSE_MENU_PENDING_STATE_CLEARED = 0, - SCENE_STATE_DEFAULT = 2, PAUSE_MENU_STATE_EXIT_GUARDED = 0x22 }; +enum { + SCENE_STATE_DEFAULT = 2 +}; + enum { PAUSE_MENU_STATE_PAGE_TRANSITION = 1, PAUSE_MENU_STATE_LEVEL_TRANSITION_ENTRY = 0xE, diff --git a/src/overlays/shared/weapons/bomb_glove_bomb.c b/src/overlays/shared/weapons/bomb_glove_bomb.c index 507dcceea1..db446b3622 100644 --- a/src/overlays/shared/weapons/bomb_glove_bomb.c +++ b/src/overlays/shared/weapons/bomb_glove_bomb.c @@ -22,7 +22,10 @@ #include "rnc/overlay/shared/weapons/bomb_glove_bomb.h" enum { - BOMB_STATE_HELD = 0, + BOMB_STATE_HELD = 0 +}; + +enum { THROW_LANDING_MODE_SKIP_LINKED_MOBY_MARKER = 2 }; diff --git a/src/overlays/shared/weapons/decoy.c b/src/overlays/shared/weapons/decoy.c index 8764cc5c5a..b4bc9f1778 100644 --- a/src/overlays/shared/weapons/decoy.c +++ b/src/overlays/shared/weapons/decoy.c @@ -24,10 +24,8 @@ enum { DECOY_INITIALIZE = 0, - LANDING_REQUIRE_MOBY_PVARS_LINK = 0, DECOY_HELD = 1, DECOY_THROWN_MOVEMENT = 2, - LANDING_SKIP_LINKED_MOBY_DRAW = 2, DECOY_SETTLED_MOVEMENT = 3, DECOY_PRE_REMOVAL_DELAY = 4, DECOY_WAIT_TO_SHRINK = 5, @@ -35,6 +33,11 @@ enum { DECOY_RESET_TO_INITIALIZE = 7 }; +enum { + LANDING_REQUIRE_MOBY_PVARS_LINK = 0, + LANDING_SKIP_LINKED_MOBY_DRAW = 2 +}; + typedef struct DecoyVars { u8 pad0[0x10]; f32 unk10[4]; diff --git a/src/overlays/shared/weapons/glove_of_doom_bomb.c b/src/overlays/shared/weapons/glove_of_doom_bomb.c index b7d62d0bb1..7f3e94303c 100644 --- a/src/overlays/shared/weapons/glove_of_doom_bomb.c +++ b/src/overlays/shared/weapons/glove_of_doom_bomb.c @@ -17,9 +17,12 @@ enum { DOOM_LANDING_MODE_REQUIRE_LINKED_MOBY = 0, + DOOM_LANDING_MODE_SKIP_LINKED_MOBY_DRAW_CALLBACK = 2 +}; + +enum { THROWN_MOBY_STATE_INITIALIZE = 0, THROWN_MOBY_STATE_GROW_TO_QUARTER_SCALE = 1, - DOOM_LANDING_MODE_SKIP_LINKED_MOBY_DRAW_CALLBACK = 2, THROWN_MOBY_STATE_MOVE_WITH_COLLISION = 2, THROWN_MOBY_STATE_SPAWN_SEQUENCE = 3, THROWN_MOBY_STATE_FADE_OUT = 4, From bcfd117ba705aece7e4297f4d52225e472bcec6d Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 17:54:21 +0000 Subject: [PATCH 1501/1502] decomp: format naming changes after upstream rebase --- .../l02/hero/update_hero_state_motion.c | 19 ++++--- src/overlays/l02/mobys/sand_shark.c | 56 +++++++++---------- src/overlays/l02/mobys/sand_shark_nest.c | 16 +++--- src/overlays/l03/mobys/kerwan_path_enemy.c | 36 ++++++------ src/overlays/l03/mobys/mine_layer.c | 18 +++--- src/overlays/l03/mobys/red_ship_1.c | 4 +- src/overlays/l03/mobys/robot_dog.c | 4 +- src/overlays/l04/mobys/circular_saw_enemy.c | 2 +- src/overlays/l04/mobys/leg_walker.c | 8 +-- .../hero/apply_hero_ground_material_effects.c | 20 +++---- src/overlays/l05/mobys/extermibot.c | 46 +++++++-------- src/overlays/l05/mobys/extermitank.c | 14 ++--- src/overlays/l05/mobys/hoverboard_girl.c | 6 +- src/overlays/l05/mobys/scenery_ship.c | 12 ++-- .../update_hero_motion_for_current_state.c | 12 ++-- src/overlays/l06/mobys/alien_queen.c | 46 +++++++-------- src/overlays/l06/mobys/alien_snapper.c | 42 +++++++------- src/overlays/l07/mobys/sharkigator.c | 40 ++++++------- src/overlays/l07/mobys/snagglebeast.c | 40 ++++++------- src/overlays/l08/mobys/bomber_tank.c | 20 +++---- src/overlays/l08/mobys/heavy_gunship.c | 2 +- src/overlays/l08/mobys/rocket.c | 20 +++---- src/overlays/l08/mobys/shrub.c | 16 +++--- src/overlays/l09/mobys/refueling_station.c | 2 +- src/overlays/l10/mobys/blarg_ship.c | 32 +++++------ src/overlays/l10/mobys/darter.c | 32 +++++------ .../l10/mobys/data_processor_linked_effect.c | 12 ++-- src/overlays/l10/mobys/linked_moby_hitbox.c | 10 ++-- src/overlays/l10/mobys/screamer.c | 28 +++++----- src/overlays/l10/mobys/toxic_crab.c | 32 +++++------ src/overlays/l11/mobys/jet_fighter.c | 22 ++++---- src/overlays/l11/mobys/owner_linked_moby.c | 2 +- src/overlays/l11/mobys/pokitaru_boat.c | 18 +++--- src/overlays/l11/mobys/psytcopus.c | 20 +++---- src/overlays/l11/mobys/puffoid.c | 48 ++++++++-------- .../update_hero_motion_for_current_state.c | 14 ++--- src/overlays/l12/mobys/blarg_helicopter.c | 20 +++---- src/overlays/l12/mobys/blarg_trooper.c | 26 ++++----- src/overlays/l12/mobys/hoven_anklebiter.c | 38 ++++++------- .../l12/mobys/planetbuster_maximus_part.c | 16 +++--- src/overlays/l13/mobys/blarg_gunner.c | 12 ++-- src/overlays/l13/mobys/blarg_space_commando.c | 40 ++++++------- src/overlays/l13/mobys/blarg_space_fighter.c | 24 ++++---- src/overlays/l13/mobys/blarg_turret.c | 16 +++--- src/overlays/l13/mobys/elevator.c | 20 +++---- src/overlays/l13/mobys/fighter_jet.c | 24 ++++---- src/overlays/l13/mobys/forcefield_tower.c | 12 ++-- .../l13/mobys/hovering_rocket_attacker.c | 20 +++---- .../l14/mobys/blarg_heavy_interceptor.c | 24 ++++---- src/overlays/l14/mobys/enemy_fighter.c | 12 ++-- src/overlays/l14/mobys/flying_car.c | 12 ++-- .../l14/mobys/rocket_strike_fighter.c | 14 ++--- src/overlays/l14/mobys/taxi.c | 20 +++---- src/overlays/l15/mobys/ultramech_unlimited.c | 30 +++++----- .../hero/apply_hero_ground_material_effects.c | 20 +++---- src/overlays/l16/mobys/bolt_thief.c | 20 +++---- src/overlays/l16/mobys/chicken_relocator.c | 10 ++-- src/overlays/l16/mobys/chomper.c | 18 +++--- src/overlays/l16/mobys/test_dummy.c | 29 +++++----- src/overlays/l17/mobys/fighter_jet.c | 22 ++++---- src/overlays/l18/mobys/camera_transition.c | 10 ++-- .../l18/mobys/drek_boss_electric_ball.c | 10 ++-- src/overlays/l18/mobys/falling_moby_group.c | 20 +++---- src/overlays/l18/mobys/floating_platform.c | 18 +++--- src/overlays/l18/mobys/gadgebot.c | 26 ++++----- src/overlays/l18/mobys/mine.c | 24 ++++---- src/overlays/shared/camera/grindrail_camera.c | 2 +- .../shared/camera/hoverboard_camera.c | 6 +- .../shared/enemies/blarg_space_commando.c | 32 +++++------ src/overlays/shared/enemies/bolt_thief_mine.c | 12 ++-- .../shared/enemies/bomb_spawner_bomb.c | 2 +- .../shared/enemies/ground_melee_enemy.c | 6 +- .../shared/enemies/paratrooper_fire_bolt.c | 4 +- src/overlays/shared/enemies/plasmabot.c | 42 +++++++------- src/overlays/shared/enemies/seeker.c | 22 ++++---- src/overlays/shared/hero/hero_frame_update.c | 26 ++++----- src/overlays/shared/hero/hero_switch_item.c | 10 ++-- src/overlays/shared/pickups/crate.c | 2 +- .../rendering/debug/update_debug_menu.c | 14 ++--- .../shared/ui/menus/initialize_pause_menu.c | 34 +++++------ src/overlays/shared/vendor/vendor_menu.c | 28 +++++----- .../shared/weapons/glove_of_doom_bomb.c | 2 +- src/overlays/shared/weapons/pyrocitor.c | 2 +- 83 files changed, 813 insertions(+), 811 deletions(-) diff --git a/src/overlays/l02/hero/update_hero_state_motion.c b/src/overlays/l02/hero/update_hero_state_motion.c index e05f6a0b72..c381521e81 100644 --- a/src/overlays/l02/hero/update_hero_state_motion.c +++ b/src/overlays/l02/hero/update_hero_state_motion.c @@ -26,6 +26,16 @@ #include "rnc/world/collision/collision_hit_material.h" /* Same source as the exact FUN_L16_002097a0, with a state 3 flag (0x12E6) and its own landing checks (as FUN_L18_00213b40, without states 0, 4 and 0xE). */ +enum { + GROUND_MATERIAL_MAGNETIC = 2, + GROUND_MATERIAL_SINK_TRIGGER = 0xD +}; + +enum { + GROUND_MATERIAL_WATER_SURFACE_TRIGGER = 0, + GROUND_MATERIAL_SINK_SURFACE_TRIGGER = 3 +}; + extern int D_0015ED84_c __asm__("D_0015ED84"); extern int D_0015ED84_d __asm__("D_0015ED84"); extern int coll_sphere(float, void *, int, void *) __asm__("FUN_L00_001f0d60"); @@ -147,15 +157,6 @@ void process_hero_ground_material_effects(void) { #include "qcopy.h" -enum { - GROUND_MATERIAL_MAGNETIC = 2, - GROUND_MATERIAL_SINK_TRIGGER = 0xD -}; - -enum { - GROUND_MATERIAL_WATER_SURFACE_TRIGGER = 0, - GROUND_MATERIAL_SINK_SURFACE_TRIGGER = 3 -}; #define G hero /* Same source as the exact FUN_L08_00222800, with only the 0x16 animation in mode 0 and no 0xF exit. */ diff --git a/src/overlays/l02/mobys/sand_shark.c b/src/overlays/l02/mobys/sand_shark.c index 02bfcdc0c2..560b7a6a20 100644 --- a/src/overlays/l02/mobys/sand_shark.c +++ b/src/overlays/l02/mobys/sand_shark.c @@ -17,6 +17,34 @@ #include "rnc/rendering/clip_volume.h" #include "rnc/world/collision/ground_probe.h" +enum { + SAND_SHARK_INITIALIZE = 0, + SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET = 1, + SAND_SHARK_WANDER_AROUND_HOME = 2, + SAND_SHARK_WAIT_FOR_TARGET_IN_VOLUME = 3, + SAND_SHARK_APPROACH_TARGET = 5, + SAND_SHARK_CLOSE_RANGE_ATTACK = 6, + SAND_SHARK_RETURN_HOME = 7, + SAND_SHARK_KNOCKBACK_UNTIL_LANDING = 8, + SAND_SHARK_SUCK_CANNON_INTERACTION = 9, + SAND_SHARK_WAIT_FOR_HERO_LAUNCH_TRIGGER = 12, + SAND_SHARK_BALLISTIC_FLIGHT = 13, + SAND_SHARK_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK = 14, + SAND_SHARK_FACE_TARGET = 15, + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_HEIGHT_OFFSET = 17, + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET = 18, + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET = 19, + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME = 20, + SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK = 21, + SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET = 22, + SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET = 23, + SAND_SHARK_DEATH_KNOCKBACK = 24, + SAND_SHARK_FADE_OUT = 25, + SAND_SHARK_INACTIVE_WAIT_FOR_RELAUNCH = 26, + SAND_SHARK_BALLISTIC_FLIGHT_WITH_PARTICLES = 27, + SAND_SHARK_WAIT_FOR_LINKED_MOBY_BEFORE_INITIALIZE = 29 +}; + extern float sand_shark_dust_vertical_velocity_scale_gp __asm__("D_L02_001619D4") __attribute__((sda)); extern float sand_shark_dust_position_jitter_radius_gp __asm__("D_L02_001619DC") @@ -1207,34 +1235,6 @@ typedef struct { #include "rnc/overlay/l02/mobys/sand_shark_data/handle_sand_shark_damage_and_targeting.h" -enum { - SAND_SHARK_INITIALIZE = 0, - SAND_SHARK_BEGIN_RETURN_HOME_WITH_HEIGHT_OFFSET = 1, - SAND_SHARK_WANDER_AROUND_HOME = 2, - SAND_SHARK_WAIT_FOR_TARGET_IN_VOLUME = 3, - SAND_SHARK_APPROACH_TARGET = 5, - SAND_SHARK_CLOSE_RANGE_ATTACK = 6, - SAND_SHARK_RETURN_HOME = 7, - SAND_SHARK_KNOCKBACK_UNTIL_LANDING = 8, - SAND_SHARK_SUCK_CANNON_INTERACTION = 9, - SAND_SHARK_WAIT_FOR_HERO_LAUNCH_TRIGGER = 12, - SAND_SHARK_BALLISTIC_FLIGHT = 13, - SAND_SHARK_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK = 14, - SAND_SHARK_FACE_TARGET = 15, - SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_HEIGHT_OFFSET = 17, - SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME_WITH_HEIGHT_OFFSET = 18, - SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET = 19, - SAND_SHARK_ALIGN_TO_GROUND_BEFORE_RETURN_HOME = 20, - SAND_SHARK_ALIGN_TO_GROUND_BEFORE_APPROACH_TARGET_WITH_PATH_PROXIMITY_CHECK = 21, - SAND_SHARK_APPROACH_TARGET_WITH_HEIGHT_OFFSET = 22, - SAND_SHARK_RETURN_HOME_WITH_HEIGHT_OFFSET = 23, - SAND_SHARK_DEATH_KNOCKBACK = 24, - SAND_SHARK_FADE_OUT = 25, - SAND_SHARK_INACTIVE_WAIT_FOR_RELAUNCH = 26, - SAND_SHARK_BALLISTIC_FLIGHT_WITH_PARTICLES = 27, - SAND_SHARK_WAIT_FOR_LINKED_MOBY_BEFORE_INITIALIZE = 29 -}; - extern int *D_L02_001B0AB0_5c88[] __asm__("D_L02_001B0AB0"); extern void trooper_knockback_arc(void *, float *, void *, void *) __asm__("FUN_L00_0025ab48"); extern int FUN_L00_0025ff38(float, void *, void *, int, int, void *, int); diff --git a/src/overlays/l02/mobys/sand_shark_nest.c b/src/overlays/l02/mobys/sand_shark_nest.c index 2e147c353d..2654bfd9ce 100644 --- a/src/overlays/l02/mobys/sand_shark_nest.c +++ b/src/overlays/l02/mobys/sand_shark_nest.c @@ -8,6 +8,14 @@ #include "rnc/mobys/animation/blend_moby_animation.h" #include "rnc/overlay/shared/mobys/evaluate_moby_animation_pose.h" +enum { + SAND_SHARK_NEST_INITIALIZE = 0, + SAND_SHARK_NEST_WAIT_FOR_SPAWN = 1, + SAND_SHARK_NEST_LAUNCH_SAND_SHARK = 2, + SAND_SHARK_NEST_HIT_RECOVERY = 3, + SAND_SHARK_NEST_DEATH_KNOCKBACK = 4 +}; + extern float D_0015ED6C; extern int step_moby_motion(void *, void *) __asm__("FUN_L00_0025c698"); @@ -26,14 +34,6 @@ extern void trooper_anim_finish(void *, void *) __asm__("FUN_L00_0025d538"); #include "qcopy.h" -enum { - SAND_SHARK_NEST_INITIALIZE = 0, - SAND_SHARK_NEST_WAIT_FOR_SPAWN = 1, - SAND_SHARK_NEST_LAUNCH_SAND_SHARK = 2, - SAND_SHARK_NEST_HIT_RECOVERY = 3, - SAND_SHARK_NEST_DEATH_KNOCKBACK = 4 -}; - /* Ported from rac1-decomp (src/overlays/l02_aridia/vendor_002A59D8.c: func_L02_002D7550), where it is exact; names translated to the US level program. */ void launch_sand_shark(struct Moby *moby, diff --git a/src/overlays/l03/mobys/kerwan_path_enemy.c b/src/overlays/l03/mobys/kerwan_path_enemy.c index 39d12b1695..a0e6ad1fbc 100644 --- a/src/overlays/l03/mobys/kerwan_path_enemy.c +++ b/src/overlays/l03/mobys/kerwan_path_enemy.c @@ -22,6 +22,24 @@ #include "rnc/overlay/l03/mobys/homing_rocket.h" #include "rnc/overlay/l03/mobys/robot_dog.h" +enum { + ENEMY_INITIALIZE = 0, + ENEMY_WAIT_FOR_ACTIVATION = 1, + ENEMY_WAIT_FOR_LINKED_MOBY = 2, + ENEMY_PROJECTILE_ATTACK_WINDUP = 4, + ENEMY_PROJECTILE_ATTACK = 5, + ENEMY_MELEE_ATTACK = 6, + ENEMY_MOVE_TO_PATH_NODE = 7, + ENEMY_FOLLOW_PATH_TO_END = 8, + ENEMY_FOLLOW_ALTERNATE_PATH = 0x9, + ENEMY_KNOCKBACK_RECOVERY = 10, + ENEMY_FALL_UNDER_GRAVITY = 11, + ENEMY_TURN_TO_HEADING = 0xC, + ENEMY_DEATH_KNOCKBACK = 13, + ENEMY_HIDDEN_AT_PATH_START = 14, + ENEMY_RESPAWN_AT_PATH_START = 15 +}; + extern void blend_moby_animation(void *, int, int, int) __asm__("FUN_00212f90"); /* Ported from rac1-decomp (src/overlays/l03_kerwan/vendor_00293720.c: func_L03_002C81E0), where it is exact; names translated to the US level program. */ @@ -1449,24 +1467,6 @@ extern float D_L03_001618E0 __attribute__((sda)); #include "rnc/overlay/l03/mobys/kerwan_path_enemy_data/update_kerwan_path_enemy_hit_reaction.h" -enum { - ENEMY_INITIALIZE = 0, - ENEMY_WAIT_FOR_ACTIVATION = 1, - ENEMY_WAIT_FOR_LINKED_MOBY = 2, - ENEMY_PROJECTILE_ATTACK_WINDUP = 4, - ENEMY_PROJECTILE_ATTACK = 5, - ENEMY_MELEE_ATTACK = 6, - ENEMY_MOVE_TO_PATH_NODE = 7, - ENEMY_FOLLOW_PATH_TO_END = 8, - ENEMY_FOLLOW_ALTERNATE_PATH = 0x9, - ENEMY_KNOCKBACK_RECOVERY = 10, - ENEMY_FALL_UNDER_GRAVITY = 11, - ENEMY_TURN_TO_HEADING = 0xC, - ENEMY_DEATH_KNOCKBACK = 13, - ENEMY_HIDDEN_AT_PATH_START = 14, - ENEMY_RESPAWN_AT_PATH_START = 15 -}; - extern int resolve_moby_hit_response(void *, void *, void *, int, int *, float *, int, int) __asm__("FUN_00213928"); extern void set_moby_animation(void *, int, int) __asm__("FUN_00212ed8"); diff --git a/src/overlays/l03/mobys/mine_layer.c b/src/overlays/l03/mobys/mine_layer.c index 0086ee70bb..e099e9f6ff 100644 --- a/src/overlays/l03/mobys/mine_layer.c +++ b/src/overlays/l03/mobys/mine_layer.c @@ -15,6 +15,15 @@ #include "rnc/overlay/l03/mobys/mine_layer_globals.h" /* Patrol state of the l03 trooper: walks back and forth along a rail path. */ +enum { + MINE_LAYER_INITIALIZE = 0, + MINE_LAYER_FACE_TARGET_AND_WAIT_FOR_RANGE = 1, + MINE_LAYER_WAIT_FOR_ANIMATION_BEFORE_PATROL = 2, + MINE_LAYER_PATROL_AND_FIRE = 3, + MINE_LAYER_KNOCKBACK_AND_RECOVER = 4, + MINE_LAYER_KNOCKBACK_UNTIL_EXPLOSION = 5 +}; + typedef struct { s32 idx; /* 0x00: path point it is walking to */ s8 dir; /* 0x04: +1 or -1 */ @@ -368,15 +377,6 @@ extern f32 mine_layer_nonlethal_knockback_speed_scale_gp __asm__("D_L03_001618FC #include "rnc/overlay/l03/mobys/mine_layer_data/handle_mine_layer_damage.h" -enum { - MINE_LAYER_INITIALIZE = 0, - MINE_LAYER_FACE_TARGET_AND_WAIT_FOR_RANGE = 1, - MINE_LAYER_WAIT_FOR_ANIMATION_BEFORE_PATROL = 2, - MINE_LAYER_PATROL_AND_FIRE = 3, - MINE_LAYER_KNOCKBACK_AND_RECOVER = 4, - MINE_LAYER_KNOCKBACK_UNTIL_EXPLOSION = 5 -}; - extern TrooperHit *trooper_find_hit(struct Moby *, s32, s32) __asm__("FUN_L00_0025a420"); extern s32 resolve_moby_hit_response( struct Moby *, TrooperHit *, f32 *, s32, s32 *, f32 *, s32, s32) __asm__("FUN_00213928"); diff --git a/src/overlays/l03/mobys/red_ship_1.c b/src/overlays/l03/mobys/red_ship_1.c index baa3f38caf..b2cb1933f4 100644 --- a/src/overlays/l03/mobys/red_ship_1.c +++ b/src/overlays/l03/mobys/red_ship_1.c @@ -24,6 +24,8 @@ #include "rnc/audio/voice_pool.h" #include "rnc/game/item_state.h" +/* Ported from rac1-decomp (src/overlays/l03_kerwan/vendor_00293720.c: func_L03_0029DB88), where it is exact; names translated to the US level program. */ + enum { RED_SHIP_INITIALIZE = 0, RED_SHIP_FOLLOW_PATH_SPLINE = 1, @@ -31,8 +33,6 @@ enum { RED_SHIP_WAIT_FOR_MOVEMENT_TIMER = 3 }; -/* Ported from rac1-decomp (src/overlays/l03_kerwan/vendor_00293720.c: func_L03_0029DB88), where it is exact; names translated to the US level program. */ - extern int D_L03_0015F5CC; /* no foreign declaration */ /* Builds two scaled offset vectors from the moby's matrix and adds them to out. */ diff --git a/src/overlays/l03/mobys/robot_dog.c b/src/overlays/l03/mobys/robot_dog.c index 26e1648daf..9eeee3c0b2 100644 --- a/src/overlays/l03/mobys/robot_dog.c +++ b/src/overlays/l03/mobys/robot_dog.c @@ -17,6 +17,8 @@ #include "rnc/overlay/shared/world/level_path.h" #include "rnc/overlay/l03/mobys/robot_dog.h" +/* Ported from rac1-decomp (src/overlays/l03_kerwan/vendor_00293720.c: func_L03_002C6F40), where it is exact; names translated to the US level program. */ + enum { ROBOT_DOG_INITIALIZE = 0, ROBOT_DOG_WAIT_FOR_ACTIVATION = 1, @@ -35,8 +37,6 @@ enum { MOBY_STATE_PENDING_REMOVAL = 0xFE }; -/* Ported from rac1-decomp (src/overlays/l03_kerwan/vendor_00293720.c: func_L03_002C6F40), where it is exact; names translated to the US level program. */ - int is_robot_dog_in_state_5(struct Moby *moby) __asm__("FUN_L03_002c5b78"); int is_robot_dog_in_state_5(struct Moby *moby) { diff --git a/src/overlays/l04/mobys/circular_saw_enemy.c b/src/overlays/l04/mobys/circular_saw_enemy.c index 7284a2750c..2fcfcc1892 100644 --- a/src/overlays/l04/mobys/circular_saw_enemy.c +++ b/src/overlays/l04/mobys/circular_saw_enemy.c @@ -22,6 +22,7 @@ #include "rnc/rendering/clip_volume.h" #include "rnc/world/collision/ground_probe.h" +/* The engine-sound fields of the moby's pvars. */ enum { CIRCULAR_SAW_STATE_INITIALIZE = 0, CIRCULAR_SAW_STATE_IDLE = 1, @@ -35,7 +36,6 @@ enum { CIRCULAR_SAW_STATE_SUCK_CANNON_CONTROLLED = 9 }; -/* The engine-sound fields of the moby's pvars. */ typedef struct { /* 0x000 */ u8 pad0[0x230]; /* 0x230 */ f32 volume; diff --git a/src/overlays/l04/mobys/leg_walker.c b/src/overlays/l04/mobys/leg_walker.c index fe6b72164b..748bec76b8 100644 --- a/src/overlays/l04/mobys/leg_walker.c +++ b/src/overlays/l04/mobys/leg_walker.c @@ -20,6 +20,10 @@ /* Ported from rac1-decomp (src/overlays/l04_eudora/vuchain_00293490.c: func_L04_00293490), where it is exact; names translated to the US level program. */ +enum { + LEG_RIG_FALLBACK_GAIT_MASK = 5 +}; + extern float D_L04_00173FE8 NOT_SDA; float probe_leg_rig_ground_height(float *probe_origin) __asm__("FUN_L04_002922d0"); @@ -175,10 +179,6 @@ float probe_leg_rig_ground_height(float *pos) __asm__("FUN_L04_002922d0"); #include "rnc/overlay/shared/world/collision.h" -enum { - LEG_RIG_FALLBACK_GAIT_MASK = 5 -}; - extern CollisionHit coll_hit __asm__("D_L04_00173FC0"); int update_leg_rig_height_and_tilt(StMoby *moby, Steer *steer_state) __asm__("FUN_L04_00292828"); diff --git a/src/overlays/l05/hero/apply_hero_ground_material_effects.c b/src/overlays/l05/hero/apply_hero_ground_material_effects.c index 72c0748647..ed7644f146 100644 --- a/src/overlays/l05/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l05/hero/apply_hero_ground_material_effects.c @@ -13,6 +13,16 @@ #include "rnc/overlay/shared/rendering/effects/spawn_explosion.h" #include "rnc/world/collision/collision_hit_material.h" +enum { + GROUND_MATERIAL_WATER = 0, + GROUND_MATERIAL_MAGNET = 2, + GROUND_MATERIAL_FIXED_SHALLOW_WATER = 14 +}; + +enum { + GROUND_MATERIAL_SINK_TRIGGER = 13 +}; + int FUN_L00_001f0d60_239fc0(void *, int, int, f32) __asm__("FUN_L00_001f0d60"); f32 absolute_float(f32) __asm__("func_001F99C0"); void exit_hero_vehicle_mode_if_mode_three(void) __asm__("FUN_L00_0020b930"); @@ -362,16 +372,6 @@ typedef unsigned int u128_2133a8 __attribute__((mode(TI), aligned(16))); #include "rnc/math/fast_math.h" -enum { - GROUND_MATERIAL_WATER = 0, - GROUND_MATERIAL_MAGNET = 2, - GROUND_MATERIAL_FIXED_SHALLOW_WATER = 14 -}; - -enum { - GROUND_MATERIAL_SINK_TRIGGER = 13 -}; - typedef union { u128_2133a8 q; f32 f[4]; diff --git a/src/overlays/l05/mobys/extermibot.c b/src/overlays/l05/mobys/extermibot.c index 5e7af92501..1b02c8273c 100644 --- a/src/overlays/l05/mobys/extermibot.c +++ b/src/overlays/l05/mobys/extermibot.c @@ -9,6 +9,29 @@ #include "rnc/overlay/shared/mobys/build_symmetric_adjacency_masks.h" #include "qcopy.h" +enum { + EXTERMIBOT_INITIALIZE = 0, + EXTERMIBOT_HIT_STATUS_SKIP_RESPONSE = 1, + EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH = 1, + EXTERMIBOT_WANDER_NEAR_START = 2, + EXTERMIBOT_FOLLOW_TARGET = 4, + EXTERMIBOT_WAIT_FOR_TARGET_IN_STRIKE_RANGE = 5, + EXTERMIBOT_APPROACH_TARGET_DIRECTLY = 6, + EXTERMIBOT_AIM_BEFORE_STRIKE = 7, + EXTERMIBOT_STRIKE_TARGET = 8, + EXTERMIBOT_RECOVER_AFTER_STRIKE = 9, + EXTERMIBOT_RETURN_TO_START = 10, + EXTERMIBOT_NONLETHAL_KNOCKBACK = 11, + EXTERMIBOT_WAIT_FOR_ANIMATION_BEFORE_IDLE = 13, + EXTERMIBOT_DEATH_KNOCKBACK = 14, + EXTERMIBOT_WAIT_FOR_ACTIVATION_TRIGGER = 15 +}; + +enum { + EXTERMIBOT_TARGET_PATH_UNAVAILABLE = 2, + EXTERMIBOT_HIDDEN_BELOW_START = 0xC +}; + extern int scale_game_frames(int) __asm__("FUN_001f96f8"); extern void blend_moby_animation(void *, int, int, int) __asm__("FUN_00212f90"); extern int random_integer_below(int) __asm__("FUN_00213260"); @@ -702,29 +725,6 @@ extern float D_L05_00161A98_gp __asm__("D_L05_00161A98") __attribute__((sda)); #include "rnc/overlay/l05/mobys/extermibot_data/handle_extermibot_hits_and_update_targeting.h" -enum { - EXTERMIBOT_INITIALIZE = 0, - EXTERMIBOT_HIT_STATUS_SKIP_RESPONSE = 1, - EXTERMIBOT_IDLE_AND_CHECK_TARGET_PATH = 1, - EXTERMIBOT_WANDER_NEAR_START = 2, - EXTERMIBOT_FOLLOW_TARGET = 4, - EXTERMIBOT_WAIT_FOR_TARGET_IN_STRIKE_RANGE = 5, - EXTERMIBOT_APPROACH_TARGET_DIRECTLY = 6, - EXTERMIBOT_AIM_BEFORE_STRIKE = 7, - EXTERMIBOT_STRIKE_TARGET = 8, - EXTERMIBOT_RECOVER_AFTER_STRIKE = 9, - EXTERMIBOT_RETURN_TO_START = 10, - EXTERMIBOT_NONLETHAL_KNOCKBACK = 11, - EXTERMIBOT_WAIT_FOR_ANIMATION_BEFORE_IDLE = 13, - EXTERMIBOT_DEATH_KNOCKBACK = 14, - EXTERMIBOT_WAIT_FOR_ACTIVATION_TRIGGER = 15 -}; - -enum { - EXTERMIBOT_TARGET_PATH_UNAVAILABLE = 2, - EXTERMIBOT_HIDDEN_BELOW_START = 0xC -}; - extern Hit_3047E8 *func_L00_0025B478_3047E8(void *, int, int) __asm__("FUN_L00_0025a420"); extern int collision_line(void *, void *, int, void *, void *) __asm__("FUN_001efa68"); extern int resolve_moby_hit_response(void *, void *, void *, int, int *, float *, int, int) __asm__("FUN_00213928"); diff --git a/src/overlays/l05/mobys/extermitank.c b/src/overlays/l05/mobys/extermitank.c index e16981d696..3daef698ff 100644 --- a/src/overlays/l05/mobys/extermitank.c +++ b/src/overlays/l05/mobys/extermitank.c @@ -11,6 +11,13 @@ #include "qcopy.h" #include "rnc/overlay/l05/mobys/extermitank_globals.h" +enum { + EXTERMITANK_INITIALIZE = 0, + EXTERMITANK_FOLLOW_PATH = 1, + EXTERMITANK_FIRE_PARTICLES = 2, + EXTERMITANK_REMOVE = 3 +}; + extern char D_0013E533[]; extern int scale_game_frames(int) __asm__("FUN_001f96f8"); extern void *create_moby() __asm__("FUN_0020c4f8"); @@ -72,13 +79,6 @@ extern float extermitank_secondary_particle_vector_b_xy_scale_gp __asm__("D_L05_ #include "rnc/overlay/l05/mobys/extermitank_data/extermitank_update.h" -enum { - EXTERMITANK_INITIALIZE = 0, - EXTERMITANK_FOLLOW_PATH = 1, - EXTERMITANK_FIRE_PARTICLES = 2, - EXTERMITANK_REMOVE = 3 -}; - extern float extermitank_secondary_particle_vector_b_spread_degrees_gp __asm__("D_L05_00161B68") __attribute__((sda)); extern float extermitank_secondary_particle_vector_a_spread_degrees_gp __asm__("D_L05_00161B6C") diff --git a/src/overlays/l05/mobys/hoverboard_girl.c b/src/overlays/l05/mobys/hoverboard_girl.c index 65121beb13..48f69c9fab 100644 --- a/src/overlays/l05/mobys/hoverboard_girl.c +++ b/src/overlays/l05/mobys/hoverboard_girl.c @@ -19,13 +19,13 @@ #include "rnc/mobys/attach_manipulator.h" #include "rnc/mobys/moby.h" +/* Hoverboard girl (class record hoverboard_girl), Rilgar / Blackwater City. + * The update counts player action 11 at frame 15 when she faces the player. + * Its two breast manipulators also carry the effect into cutscene instances. */ enum { GAME_MODE_CUTSCENE = 2 }; -/* Hoverboard girl (class record hoverboard_girl), Rilgar / Blackwater City. - * The update counts player action 11 at frame 15 when she faces the player. - * Its two breast manipulators also carry the effect into cutscene instances. */ typedef union { u128 quadword; f32 component[4]; diff --git a/src/overlays/l05/mobys/scenery_ship.c b/src/overlays/l05/mobys/scenery_ship.c index cca054ab7e..b7995c116d 100644 --- a/src/overlays/l05/mobys/scenery_ship.c +++ b/src/overlays/l05/mobys/scenery_ship.c @@ -16,6 +16,12 @@ /* Ported from rac1-decomp (src/overlays/l05_rilgar/vendor_002D28D0.c: func_L05_002D8190), where it is exact; names translated to the US level program. */ +enum { + SCENERY_SHIP_INITIALIZE = 0, + SCENERY_SHIP_FOLLOW_PATH = 1, + SCENERY_SHIP_SPAWN_EFFECTS_AND_REMOVE = 2 +}; + extern int get_first_moby_in_group(int *, int, int, int) __asm__("FUN_L00_002591d0"); extern int get_next_moby_in_group(int *, int, int, int) __asm__("FUN_L00_002592b8"); extern void draw_offset_textured_effect_quad(void *, int, float, float) __asm__("FUN_L00_00263618"); @@ -127,12 +133,6 @@ extern float D_0015ED70; #include "rnc/overlay/l05/mobys/scenery_ship_data/scenery_ship_update.h" -enum { - SCENERY_SHIP_INITIALIZE = 0, - SCENERY_SHIP_FOLLOW_PATH = 1, - SCENERY_SHIP_SPAWN_EFFECTS_AND_REMOVE = 2 -}; - int D_L05_001613D8 = 0x80000080; int D_L05_001613DC = 0x80202020; float D_L05_001613E0 = 5.0f; diff --git a/src/overlays/l06/hero/update_hero_motion_for_current_state.c b/src/overlays/l06/hero/update_hero_motion_for_current_state.c index db6ad1e293..aa15aa4243 100644 --- a/src/overlays/l06/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l06/hero/update_hero_motion_for_current_state.c @@ -27,6 +27,12 @@ /* Ported from rac1-decomp (src/overlays/l06_blarg/help_00223630.c: func_L06_00223630), where it is exact; names translated to the US level program. */ +enum { + HERO_GROUND_MATERIAL_WATER = 0, + HERO_GROUND_MATERIAL_MAGNETIC = 2, + HERO_GROUND_MATERIAL_SINK_SURFACE = 0xD +}; + extern void exit_hero_vehicle_mode_if_mode_three(void) __asm__("FUN_L00_0020b930"); extern int hero_set_state(int, int) __asm__("FUN_L06_002356a0"); float absolute_float(float input) __asm__("func_001F99C0"); @@ -940,12 +946,6 @@ extern struct HeroTableRow2C D_L06_0017C3A8[]; #include "rnc/overlay/shared/camera/level_camera.h" -enum { - HERO_GROUND_MATERIAL_WATER = 0, - HERO_GROUND_MATERIAL_MAGNETIC = 2, - HERO_GROUND_MATERIAL_SINK_SURFACE = 0xD -}; - extern void gravity_set_z(void *, void *, f32) __asm__("FUN_L00_00233b20"); extern void offset_hero_position_against_gravity(void *, void *, f32) __asm__("FUN_L00_002336e8"); extern void diff --git a/src/overlays/l06/mobys/alien_queen.c b/src/overlays/l06/mobys/alien_queen.c index aa33cd93b8..cde0a1166c 100644 --- a/src/overlays/l06/mobys/alien_queen.c +++ b/src/overlays/l06/mobys/alien_queen.c @@ -24,6 +24,29 @@ #include "rnc/overlay/l06/hero/hero_set_state.h" #include "rnc/overlay/shared/camera.h" +enum { + ALIEN_QUEEN_STATE_INITIALIZE = 0, + ALIEN_QUEEN_STATE_WAIT_TO_START_INTRO = 1, + ALIEN_QUEEN_STATE_INTRO = 2, + ALIEN_QUEEN_STATE_FIRST_RECOVERY_CAMERA = 3, + ALIEN_QUEEN_STATE_FROG_RECOVERY_ORBIT = 4, + ALIEN_QUEEN_STATE_SECOND_RECOVERY_CAMERA = 5, + ALIEN_QUEEN_STATE_GROUP_RECOVERY_ORBIT = 6, + ALIEN_QUEEN_STATE_WAIT_TO_APPROACH_TARGET = 7, + ALIEN_QUEEN_STATE_APPROACH_TARGET = 8, + ALIEN_QUEEN_STATE_ATTACK_WINDUP = 9, + ALIEN_QUEEN_STATE_ATTACK_HIT_QUERIES = 10, + ALIEN_QUEEN_STATE_WAIT_FOR_ORBIT_ANIMATION_END = 11, + ALIEN_QUEEN_STATE_TIMED_ORBIT = 12, + ALIEN_QUEEN_STATE_RETURN_HOME = 13, + ALIEN_QUEEN_STATE_DEATH = 14, + ALIEN_QUEEN_STATE_POST_DEATH = 15 +}; + +enum { + HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1 +}; + extern int D_L06_001ABFC0[]; extern int D_L06_0015FFD8_d __asm__("D_L06_0015FFD8"); @@ -183,29 +206,6 @@ void update_alien_queen_hit_response_and_recovery(char *moby) __asm__("FUN_L06_0 #include "sda.h" -enum { - ALIEN_QUEEN_STATE_INITIALIZE = 0, - ALIEN_QUEEN_STATE_WAIT_TO_START_INTRO = 1, - ALIEN_QUEEN_STATE_INTRO = 2, - ALIEN_QUEEN_STATE_FIRST_RECOVERY_CAMERA = 3, - ALIEN_QUEEN_STATE_FROG_RECOVERY_ORBIT = 4, - ALIEN_QUEEN_STATE_SECOND_RECOVERY_CAMERA = 5, - ALIEN_QUEEN_STATE_GROUP_RECOVERY_ORBIT = 6, - ALIEN_QUEEN_STATE_WAIT_TO_APPROACH_TARGET = 7, - ALIEN_QUEEN_STATE_APPROACH_TARGET = 8, - ALIEN_QUEEN_STATE_ATTACK_WINDUP = 9, - ALIEN_QUEEN_STATE_ATTACK_HIT_QUERIES = 10, - ALIEN_QUEEN_STATE_WAIT_FOR_ORBIT_ANIMATION_END = 11, - ALIEN_QUEEN_STATE_TIMED_ORBIT = 12, - ALIEN_QUEEN_STATE_RETURN_HOME = 13, - ALIEN_QUEEN_STATE_DEATH = 14, - ALIEN_QUEEN_STATE_POST_DEATH = 15 -}; - -enum { - HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1 -}; - /* Ported from rac1-decomp (src/overlays/l06_blarg/vendor_002B5990.c: func_L06_002FC578), where it is exact; names translated to the US level program. */ extern int *D_L06_001B0FB0[] __asm__("D_L06_001B0C30"); void start_alien_queen_intro(char *moby) __asm__("FUN_L06_002fb148"); diff --git a/src/overlays/l06/mobys/alien_snapper.c b/src/overlays/l06/mobys/alien_snapper.c index a1cec52ce3..2678dbc082 100644 --- a/src/overlays/l06/mobys/alien_snapper.c +++ b/src/overlays/l06/mobys/alien_snapper.c @@ -16,6 +16,27 @@ #include "rnc/overlay/shared/mobys/test_path_segment_strict_crossing.h" #include "rnc/rendering/clip_volume.h" +enum { + ALIEN_SNAPPER_STATE_INITIALIZE = 0, + ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION = 1, + ALIEN_SNAPPER_STATE_ACTIVATION_SEQUENCE = 2, + ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER = 3, + ALIEN_SNAPPER_STATE_PREPARE_HOME_NODE_JUMP = 4, + ALIEN_SNAPPER_STATE_JUMP_TO_HOME_NODE = 5, + ALIEN_SNAPPER_STATE_FACE_GOAL_AND_WAIT = 6, + ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH = 7, + ALIEN_SNAPPER_STATE_APPROACH_TARGET = 8, + ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET = 9, + ALIEN_SNAPPER_STATE_WAIT_FOR_REPOSITION_ANIMATION = 10, + ALIEN_SNAPPER_STATE_BITE_TARGET = 11, + ALIEN_SNAPPER_STATE_RETURN_HOME = 12, + ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET = 13, + ALIEN_SNAPPER_STATE_HIT_KNOCKBACK = 14, + ALIEN_SNAPPER_STATE_FACE_HERO = 15, + ALIEN_SNAPPER_STATE_BITE_HERO = 16, + ALIEN_SNAPPER_STATE_DEATH_MOTION = 17 +}; + extern int D_L06_001ABFC0[]; /* 0x002f9698, 96 bytes. @@ -244,27 +265,6 @@ extern int *D_L06_001B0FB0_2FA618[] __asm__("D_L06_001B0C30"); #include "sda.h" -enum { - ALIEN_SNAPPER_STATE_INITIALIZE = 0, - ALIEN_SNAPPER_STATE_WAIT_FOR_ACTIVATION = 1, - ALIEN_SNAPPER_STATE_ACTIVATION_SEQUENCE = 2, - ALIEN_SNAPPER_STATE_WAIT_FOR_CLIP_TRIGGER = 3, - ALIEN_SNAPPER_STATE_PREPARE_HOME_NODE_JUMP = 4, - ALIEN_SNAPPER_STATE_JUMP_TO_HOME_NODE = 5, - ALIEN_SNAPPER_STATE_FACE_GOAL_AND_WAIT = 6, - ALIEN_SNAPPER_STATE_WAIT_TO_APPROACH = 7, - ALIEN_SNAPPER_STATE_APPROACH_TARGET = 8, - ALIEN_SNAPPER_STATE_REPOSITION_AROUND_TARGET = 9, - ALIEN_SNAPPER_STATE_WAIT_FOR_REPOSITION_ANIMATION = 10, - ALIEN_SNAPPER_STATE_BITE_TARGET = 11, - ALIEN_SNAPPER_STATE_RETURN_HOME = 12, - ALIEN_SNAPPER_STATE_RETREAT_FROM_TARGET = 13, - ALIEN_SNAPPER_STATE_HIT_KNOCKBACK = 14, - ALIEN_SNAPPER_STATE_FACE_HERO = 15, - ALIEN_SNAPPER_STATE_BITE_HERO = 16, - ALIEN_SNAPPER_STATE_DEATH_MOTION = 17 -}; - extern f32 approach_angle(f32 *angle, f32 target, f32 *vel, f32, f32, f32) __asm__("FUN_L00_0025be00"); diff --git a/src/overlays/l07/mobys/sharkigator.c b/src/overlays/l07/mobys/sharkigator.c index b2b2ca3f94..dc5b3a1b40 100644 --- a/src/overlays/l07/mobys/sharkigator.c +++ b/src/overlays/l07/mobys/sharkigator.c @@ -12,6 +12,26 @@ #include "rnc/overlay/shared/world/level_labels.h" #include "rnc/mobys/animation/blend_moby_animation.h" +enum { + SHARKIGATOR_INITIALIZE = 0, + SHARKIGATOR_SWIM_IDLE = 1, + SHARKIGATOR_SWIM_WANDER = 2, + SHARKIGATOR_TARGET_PURSUIT = 4, + SHARKIGATOR_TARGET_LUNGE_INTERPOLATION = 5, + SHARKIGATOR_POST_LUNGE_PATH_FOLLOW = 6, + SHARKIGATOR_GRAVITY_IDLE = 7, + SHARKIGATOR_GRAVITY_WANDER = 8, + SHARKIGATOR_TARGET_APPROACH = 9, + SHARKIGATOR_TARGET_CONTACT_ATTACK = 10, + SHARKIGATOR_TARGET_CONTACT_RECOIL_RECOVERY = 11, + SHARKIGATOR_HIT_KNOCKBACK_RECOVERY = 0xC, + SHARKIGATOR_HIT_ANIMATION_RECOVERY = 0xD, + SHARKIGATOR_DEATH_FALL_AND_REMOVE = 0xE, + SHARKIGATOR_SMALL_WATER_GAP_GRAVITY_IDLE = 15, + SHARKIGATOR_DAMPED_GRAVITY_RECOVERY = 16, + SHARKIGATOR_DAMPED_RECOVERY = 17 +}; + extern void make_hit_descriptor(char *arg, int a, int b, void *src, float scale) __asm__("FUN_L00_00259888"); extern float random_angle_radians(void) __asm__("FUN_00213308"); @@ -119,26 +139,6 @@ extern s32 random_integer_below(s32) __asm__("func_00213260"); #include "qzero.h" -enum { - SHARKIGATOR_INITIALIZE = 0, - SHARKIGATOR_SWIM_IDLE = 1, - SHARKIGATOR_SWIM_WANDER = 2, - SHARKIGATOR_TARGET_PURSUIT = 4, - SHARKIGATOR_TARGET_LUNGE_INTERPOLATION = 5, - SHARKIGATOR_POST_LUNGE_PATH_FOLLOW = 6, - SHARKIGATOR_GRAVITY_IDLE = 7, - SHARKIGATOR_GRAVITY_WANDER = 8, - SHARKIGATOR_TARGET_APPROACH = 9, - SHARKIGATOR_TARGET_CONTACT_ATTACK = 10, - SHARKIGATOR_TARGET_CONTACT_RECOIL_RECOVERY = 11, - SHARKIGATOR_HIT_KNOCKBACK_RECOVERY = 0xC, - SHARKIGATOR_HIT_ANIMATION_RECOVERY = 0xD, - SHARKIGATOR_DEATH_FALL_AND_REMOVE = 0xE, - SHARKIGATOR_SMALL_WATER_GAP_GRAVITY_IDLE = 15, - SHARKIGATOR_DAMPED_GRAVITY_RECOVERY = 16, - SHARKIGATOR_DAMPED_RECOVERY = 17 -}; - extern int D_L07_0015F5CC MACRO_ADDR; extern void FUN_L00_0024f7c8(void *, int, void *); extern void FUN_L00_00257470(void *, int, int); diff --git a/src/overlays/l07/mobys/snagglebeast.c b/src/overlays/l07/mobys/snagglebeast.c index 33b3f4747c..4da29cc31a 100644 --- a/src/overlays/l07/mobys/snagglebeast.c +++ b/src/overlays/l07/mobys/snagglebeast.c @@ -42,6 +42,26 @@ #include "rnc/overlay/shared/math/split_float_fraction.h" /* Ported from rac1-decomp (src/overlays/l07_umbris/effect_00313D28.c: func_L07_00313D28). */ +enum { + SNAGGLEBEAST_INITIALIZE = 0, + SNAGGLEBEAST_IDLE = 1, + SNAGGLEBEAST_ALTERNATING_JOINT_EMISSION_BURST = 2, + SNAGGLEBEAST_TRIPLE_SPAWN_ATTACK = 3, + SNAGGLEBEAST_SWEEP_BEAM_ATTACK = 4, + SNAGGLEBEAST_CHASE_TARGET = 5, + SNAGGLEBEAST_CHASE_AFTER_TRANSFORM_RESTORE = 6, + SNAGGLEBEAST_TURN_TOWARD_TARGET = 7, + SNAGGLEBEAST_CAPTURE_HERO_AND_DRAIN_AMMO = 8, + SNAGGLEBEAST_ROPE_ATTACK = 9, + SNAGGLEBEAST_DEATH_EXPLOSION = 10, + SNAGGLEBEAST_WAIT_AFTER_HEALTH_THRESHOLD_HIT = 11, + SNAGGLEBEAST_START_TIMED_DAMAGE_SEQUENCE = 12, + SNAGGLEBEAST_WAIT_BEFORE_TIMED_DAMAGE = 13, + SNAGGLEBEAST_APPLY_TIMED_DAMAGE_AND_SELECT_PATH = 14, + SNAGGLEBEAST_RESTORE_TRANSFORM_AND_RESUME_CHASE = 15, + SNAGGLEBEAST_POST_DEATH_CLEANUP = 16 +}; + extern s32 level_frame_count __asm__("D_L07_0015F5CC"); /* [4] is depth_buffer_address. */ @@ -2403,26 +2423,6 @@ extern int D_L07_00161B84; #include "rnc/overlay/l07/mobys/snagglebeast_globals.h" -enum { - SNAGGLEBEAST_INITIALIZE = 0, - SNAGGLEBEAST_IDLE = 1, - SNAGGLEBEAST_ALTERNATING_JOINT_EMISSION_BURST = 2, - SNAGGLEBEAST_TRIPLE_SPAWN_ATTACK = 3, - SNAGGLEBEAST_SWEEP_BEAM_ATTACK = 4, - SNAGGLEBEAST_CHASE_TARGET = 5, - SNAGGLEBEAST_CHASE_AFTER_TRANSFORM_RESTORE = 6, - SNAGGLEBEAST_TURN_TOWARD_TARGET = 7, - SNAGGLEBEAST_CAPTURE_HERO_AND_DRAIN_AMMO = 8, - SNAGGLEBEAST_ROPE_ATTACK = 9, - SNAGGLEBEAST_DEATH_EXPLOSION = 10, - SNAGGLEBEAST_WAIT_AFTER_HEALTH_THRESHOLD_HIT = 11, - SNAGGLEBEAST_START_TIMED_DAMAGE_SEQUENCE = 12, - SNAGGLEBEAST_WAIT_BEFORE_TIMED_DAMAGE = 13, - SNAGGLEBEAST_APPLY_TIMED_DAMAGE_AND_SELECT_PATH = 14, - SNAGGLEBEAST_RESTORE_TRANSFORM_AND_RESUME_CHASE = 15, - SNAGGLEBEAST_POST_DEATH_CLEANUP = 16 -}; - extern char D_L07_00161B90[] MACRO_ADDR; extern char D_L07_00161BA0[] MACRO_ADDR; extern RopeVec rope_previous_points[] __asm__("D_L07_0020DAF0"); diff --git a/src/overlays/l08/mobys/bomber_tank.c b/src/overlays/l08/mobys/bomber_tank.c index c527473b2b..60878eb424 100644 --- a/src/overlays/l08/mobys/bomber_tank.c +++ b/src/overlays/l08/mobys/bomber_tank.c @@ -31,6 +31,16 @@ #include "qcopy.h" /* Level 8 moby update (class 152): state machine that steers the moby toward the hero and fires its event. */ +enum { + BOMBER_TANK_STATE_INITIALIZE = 0, + BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM = 2, + BOMBER_TANK_STATE_FOLLOW_PATH_AND_FIRE = 3, + BOMBER_TANK_STATE_FOLLOW_PATH = 6, + BOMBER_TANK_STATE_WAIT_FOR_TRIGGER = 11, + BOMBER_TANK_STATE_SCATTER_GROUP_AND_ACTIVATE = 14, + BOMBER_TANK_STATE_DAMAGED_FOLLOW_PATH = 99 +}; + typedef struct Moby Moby; extern float D_0015ED70; extern int D_0015ED84; @@ -842,16 +852,6 @@ extern float bomber_tank_joint_particle_horizontal_spread_range_end_gp __asm__(" #include "rnc/overlay/l08/mobys/bomber_tank_data/spawn_bomber_tank_joint_particles.h" -enum { - BOMBER_TANK_STATE_INITIALIZE = 0, - BOMBER_TANK_MODE_INHIBIT_ACTIVATION_AND_TARGET_AIM = 2, - BOMBER_TANK_STATE_FOLLOW_PATH_AND_FIRE = 3, - BOMBER_TANK_STATE_FOLLOW_PATH = 6, - BOMBER_TANK_STATE_WAIT_FOR_TRIGGER = 11, - BOMBER_TANK_STATE_SCATTER_GROUP_AND_ACTIVATE = 14, - BOMBER_TANK_STATE_DAMAGED_FOLLOW_PATH = 99 -}; - extern void build_moby_bone_transform(int, int, void *) __asm__("func_0020CCA8"); extern void func_L00_001FF4B0_2D6C58(void *, void *, float) __asm__("FUN_001f9bf8"); extern float func_001F9F90_2D6C58(float) __asm__("FUN_001f9dc8"); diff --git a/src/overlays/l08/mobys/heavy_gunship.c b/src/overlays/l08/mobys/heavy_gunship.c index 595b18b69d..47827f2f51 100644 --- a/src/overlays/l08/mobys/heavy_gunship.c +++ b/src/overlays/l08/mobys/heavy_gunship.c @@ -20,6 +20,7 @@ #include "rnc/overlay/shared/mobys/evaluate_moby_animation_pose.h" #include "rnc/overlay/l08/mobys/rocket.h" +/* Pvars of the heavy gunship. */ enum { HEAVY_GUNSHIP_INITIALIZE = 0, HEAVY_GUNSHIP_FOLLOW_PRIMARY_PATH = 1, @@ -28,7 +29,6 @@ enum { HEAVY_GUNSHIP_DISPERSE_AND_REMOVE = 99 }; -/* Pvars of the heavy gunship. */ typedef struct { SwarmPathFollower follow[2]; /* 0x00: [0] cruising (state 1), [1] circling (state 2) */ SwarmPart root; /* 0x60 */ diff --git a/src/overlays/l08/mobys/rocket.c b/src/overlays/l08/mobys/rocket.c index 7360e706b4..c19e2f21aa 100644 --- a/src/overlays/l08/mobys/rocket.c +++ b/src/overlays/l08/mobys/rocket.c @@ -16,6 +16,16 @@ #include "qcopy.h" #include "rnc/overlay/shared/world/level_path.h" +enum { + ROCKET_STATE_INITIALIZE = 0, + ROCKET_STATE_APPROACH_TARGET_OFFSET = 1, + ROCKET_STATE_HOME_TOWARD_TARGET = 2, + ROCKET_STATE_WAIT_FOR_ACTIVATION = 3, + ROCKET_STATE_FOLLOW_ROUTE = 4, + ROCKET_STATE_FLY_CONFIGURED_HEADING = 5, + ROCKET_STATE_EXPLODE_AND_REMOVE = 6 +}; + extern int FUN_L08_002025d0(void *, int, int, void *, int); extern void mark_moby_for_removal(void *) __asm__("func_0020C828"); @@ -148,16 +158,6 @@ extern int D_L08_0015F5C4_macro __asm__("D_L08_0015F5C4") MACRO_ADDR; #include "rnc/overlay/l08/mobys/rocket_data/rocket_update.h" -enum { - ROCKET_STATE_INITIALIZE = 0, - ROCKET_STATE_APPROACH_TARGET_OFFSET = 1, - ROCKET_STATE_HOME_TOWARD_TARGET = 2, - ROCKET_STATE_WAIT_FOR_ACTIVATION = 3, - ROCKET_STATE_FOLLOW_ROUTE = 4, - ROCKET_STATE_FLY_CONFIGURED_HEADING = 5, - ROCKET_STATE_EXPLODE_AND_REMOVE = 6 -}; - extern unsigned int D_L08_0015FFDC MACRO_ADDR; extern void FUN_L00_00262cf0(void *, void *, float, float, float); extern void spawn_effect(void *, void *, int, int, int, int, int, int) __asm__("FUN_L00_00269958"); diff --git a/src/overlays/l08/mobys/shrub.c b/src/overlays/l08/mobys/shrub.c index 08e1c75679..2f2858d6fa 100644 --- a/src/overlays/l08/mobys/shrub.c +++ b/src/overlays/l08/mobys/shrub.c @@ -20,6 +20,14 @@ /* spawns the child mobys this object owns and fills its part table */ /* Ported from rac1-decomp (src/overlays/l08_batalia/vendor_002E0258.c: func_L08_002E9B60), where it is exact; names translated to the US level program. */ +enum { + SHRUB_INITIALIZE = 0, + SHRUB_FOLLOW_PRIMARY_PATH_AND_FIRE_AT_TARGET = 1, + SHRUB_FOLLOW_SECONDARY_PATH_AND_FIRE_RANDOMLY = 2, + SHRUB_BEGIN_PRIMARY_PATH = 3, + SHRUB_BREAK_APART_AND_REMOVE = 0x63 +}; + extern int FUN_L08_002e1c98_c() __asm__("FUN_L08_002e1c98"); void spawn_shrub_parts(char *moby) __asm__("FUN_L08_002e8788"); @@ -32,14 +40,6 @@ extern u8 D_0014C050[]; #include "rnc/overlay/shared/world/swarm_path.h" -enum { - SHRUB_INITIALIZE = 0, - SHRUB_FOLLOW_PRIMARY_PATH_AND_FIRE_AT_TARGET = 1, - SHRUB_FOLLOW_SECONDARY_PATH_AND_FIRE_RANDOMLY = 2, - SHRUB_BEGIN_PRIMARY_PATH = 3, - SHRUB_BREAK_APART_AND_REMOVE = 0x63 -}; - extern struct Moby *D_L08_0015FFD8; extern f32 scale_time(f32) __asm__("FUN_001f96b0"); extern void FUN_L00_00258278(struct Moby *, f32, f32 *, f32, f32, f32); diff --git a/src/overlays/l09/mobys/refueling_station.c b/src/overlays/l09/mobys/refueling_station.c index 0d1daf6c72..3690245b70 100644 --- a/src/overlays/l09/mobys/refueling_station.c +++ b/src/overlays/l09/mobys/refueling_station.c @@ -11,6 +11,7 @@ #include "rnc/overlay/shared/mobys/find_moby_hit.h" #include "rnc/mobys/moby.h" +/* Damage source returned by find_moby_hit. */ enum { REFUELING_STATION_STATE_INITIALIZE = 0, REFUELING_STATION_STATE_WAIT_COMMAND = 1, @@ -18,7 +19,6 @@ enum { REFUELING_STATION_STATE_EXPLODE = 3 }; -/* Damage source returned by find_moby_hit. */ typedef struct { u8 pad0[0x2C]; f32 damage; diff --git a/src/overlays/l10/mobys/blarg_ship.c b/src/overlays/l10/mobys/blarg_ship.c index a8aaea5fe6..9175d17f69 100644 --- a/src/overlays/l10/mobys/blarg_ship.c +++ b/src/overlays/l10/mobys/blarg_ship.c @@ -21,6 +21,22 @@ #include "rnc/overlay/shared/world/level_path.h" #include "rnc/overlay/l10/mobys/aligned_vector.h" +enum { + BLARG_SHIP_STATE_INITIALIZE = 0, + BLARG_SHIP_STATE_WAIT_FOR_TARGET_IN_VOLUME = 1, + BLARG_SHIP_STATE_RISE_TO_ENTRY_PATH = 2, + BLARG_SHIP_STATE_FOLLOW_ENTRY_PATH = 3, + BLARG_SHIP_STATE_FIRE_AT_TARGET = 4, + BLARG_SHIP_STATE_FIRE_COOLDOWN = 5, + BLARG_SHIP_STATE_FLY_AWAY = 6, + BLARG_SHIP_STATE_HIT_REACTION = 7, + BLARG_SHIP_STATE_EXPLODE = 8 +}; + +enum { + HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1 +}; + typedef struct Moby Moby; extern float D_0015ED6C; extern float D_0015ED6C, D_0015ED70; @@ -135,22 +151,6 @@ extern int D_L10_00161EE4 __attribute__((sda)); #include "rnc/overlay/l10/mobys/blarg_ship_globals.h" -enum { - BLARG_SHIP_STATE_INITIALIZE = 0, - BLARG_SHIP_STATE_WAIT_FOR_TARGET_IN_VOLUME = 1, - BLARG_SHIP_STATE_RISE_TO_ENTRY_PATH = 2, - BLARG_SHIP_STATE_FOLLOW_ENTRY_PATH = 3, - BLARG_SHIP_STATE_FIRE_AT_TARGET = 4, - BLARG_SHIP_STATE_FIRE_COOLDOWN = 5, - BLARG_SHIP_STATE_FLY_AWAY = 6, - BLARG_SHIP_STATE_HIT_REACTION = 7, - BLARG_SHIP_STATE_EXPLODE = 8 -}; - -enum { - HIT_STATUS_SKIP_DAMAGE_AND_REACTION = 1 -}; - float blarg_ship_rocket_speed_gp __asm__("D_L10_00161EE8") = 32.0f; float blarg_ship_firing_animation_speed_gp __asm__("D_L10_00161EEC") = 2.0f; extern unsigned char D_0013D4CB[]; diff --git a/src/overlays/l10/mobys/darter.c b/src/overlays/l10/mobys/darter.c index ac08aa0bec..ea32ffa7dc 100644 --- a/src/overlays/l10/mobys/darter.c +++ b/src/overlays/l10/mobys/darter.c @@ -22,6 +22,22 @@ #include "rnc/overlay/shared/world/level_path.h" #include "rnc/overlay/l10/mobys/aligned_vector.h" +enum { + DARTER_STATE_INITIALIZE = 0, + DARTER_STATE_RISE_TO_HOME_HEIGHT = 2, + DARTER_STATE_WANDER = 3, + DARTER_STATE_WAIT_BETWEEN_WANDER_GOALS = 4, + DARTER_STATE_RETURN_HOME = 5, + DARTER_STATE_ATTACK_WINDUP = 6, + DARTER_STATE_DIVE_TOWARD_TARGET = 7, + DARTER_STATE_DIVE_ATTACK = 8, + DARTER_STATE_CUBOID_PATROL = 9, + DARTER_STATE_CUBOID_APPROACH_TARGET = 10, + DARTER_STATE_CUBOID_CHARGE_ATTACK = 11, + DARTER_STATE_CUBOID_RETURN_HOME = 12, + DARTER_STATE_DYING = 13 +}; + typedef struct Moby Moby; extern struct Moby *D_L10_0015FFD0_macro[] __asm__("D_L10_0015FFD0") MACRO_ADDR; extern float D_0015ED6C; @@ -766,22 +782,6 @@ void update_darter_hit_reactions_and_targeting(struct Moby *moby) { #include "rnc/overlay/l10/mobys/darter_globals.h" -enum { - DARTER_STATE_INITIALIZE = 0, - DARTER_STATE_RISE_TO_HOME_HEIGHT = 2, - DARTER_STATE_WANDER = 3, - DARTER_STATE_WAIT_BETWEEN_WANDER_GOALS = 4, - DARTER_STATE_RETURN_HOME = 5, - DARTER_STATE_ATTACK_WINDUP = 6, - DARTER_STATE_DIVE_TOWARD_TARGET = 7, - DARTER_STATE_DIVE_ATTACK = 8, - DARTER_STATE_CUBOID_PATROL = 9, - DARTER_STATE_CUBOID_APPROACH_TARGET = 10, - DARTER_STATE_CUBOID_CHARGE_ATTACK = 11, - DARTER_STATE_CUBOID_RETURN_HOME = 12, - DARTER_STATE_DYING = 13 -}; - int moby_group_command_frames_gp __asm__("D_L10_00161E00") = 5; void set_moby_group_command_frames(struct Moby *moby) __asm__("FUN_L10_002e1cb0"); /* Stores a value into each table entry listed for this moby's index. */ diff --git a/src/overlays/l10/mobys/data_processor_linked_effect.c b/src/overlays/l10/mobys/data_processor_linked_effect.c index 68ca5f4bba..c07e787bd4 100644 --- a/src/overlays/l10/mobys/data_processor_linked_effect.c +++ b/src/overlays/l10/mobys/data_processor_linked_effect.c @@ -18,6 +18,12 @@ #include "rnc/overlay/shared/math/quad.h" #include "rnc/audio/voice_pool.h" +enum { + MOBY_STATE_INITIALIZE = 0, + MOBY_STATE_ACTIVE_WITH_SOUND = 1, + MOBY_STATE_ACTIVE_WITHOUT_SOUND = 2 +}; + extern int debug_print() __asm__("FUN_001e93b0"); extern float scale_time(float) __asm__("FUN_001f96b0"); @@ -165,12 +171,6 @@ extern s32 fast_tween_color(s32, s32, f32) __asm__("FUN_001fa6e0"); #include "rnc/overlay/l10/mobys/data_processor_linked_effect_data/render_data_processor_linked_effect.h" -enum { - MOBY_STATE_INITIALIZE = 0, - MOBY_STATE_ACTIVE_WITH_SOUND = 1, - MOBY_STATE_ACTIVE_WITHOUT_SOUND = 2 -}; - extern int data_processor_linked_effect_color_at_zero_progress_gp __asm__("D_L10_00161C90") __attribute__((sda)); extern int data_processor_linked_effect_color_at_full_progress_gp __asm__("D_L10_00161C94") diff --git a/src/overlays/l10/mobys/linked_moby_hitbox.c b/src/overlays/l10/mobys/linked_moby_hitbox.c index 5594b4f990..de6a64904a 100644 --- a/src/overlays/l10/mobys/linked_moby_hitbox.c +++ b/src/overlays/l10/mobys/linked_moby_hitbox.c @@ -14,6 +14,11 @@ #include "rnc/overlay/shared/math/quad.h" #include "rnc/overlay/shared/mobys.h" +enum { + MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF = 0xFD, + MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF = 0xFE +}; + extern int debug_print() __asm__("FUN_001e93b0"); extern char *D_L10_0015FFD8_p __asm__("D_L10_0015FFD8"); @@ -21,11 +26,6 @@ extern struct Moby *D_L10_0015FFD8; #include "qzero.h" -enum { - MOBY_STATE_REMOVAL_MARKER_BELOW_CUTOFF = 0xFD, - MOBY_STATE_REMOVAL_MARKER_AT_OR_ABOVE_CUTOFF = 0xFE -}; - /* Box a moby sweeps through: hits other mobys inside it (FUN_L10_002c9958) */ typedef struct { f32 width; /* 0x00: extent along the moby's x */ diff --git a/src/overlays/l10/mobys/screamer.c b/src/overlays/l10/mobys/screamer.c index f980dcc83d..986ff05b07 100644 --- a/src/overlays/l10/mobys/screamer.c +++ b/src/overlays/l10/mobys/screamer.c @@ -23,6 +23,20 @@ /* Update function for moby class 1196 (screamer) on level 10: follows its path, turns to its target, wanders. */ /* Ported from rac1-decomp (src/overlays/l10_orxon/vendor_00296BD8.c: func_L10_002E0630), where it is exact; names translated to the US level program. */ +enum { + SCREAMER_STATE_INITIALIZE = 0, + SCREAMER_STATE_WAIT_FOR_ACTIVATION = 1, + SCREAMER_STATE_WAIT_TO_RISE = 2, + SCREAMER_STATE_RISE_FROM_HOME = 4, + SCREAMER_STATE_FOLLOW_PATH = 5, + SCREAMER_STATE_FACE_LEADER_AT_WAYPOINT = 6, + SCREAMER_STATE_IDLE_AT_HOME = 7, + SCREAMER_STATE_RETURN_HOME = 8, + SCREAMER_STATE_WAIT_TO_WANDER = 9, + SCREAMER_STATE_WANDER = 10, + SCREAMER_STATE_DEATH_KNOCKBACK = 11 +}; + typedef struct Moby Moby; typedef struct D_2E0630 { @@ -371,20 +385,6 @@ extern void trooper_anim_update(void *m, void *p) __asm__("FUN_L00_0025d458"); #include "rnc/data_labels.h" -enum { - SCREAMER_STATE_INITIALIZE = 0, - SCREAMER_STATE_WAIT_FOR_ACTIVATION = 1, - SCREAMER_STATE_WAIT_TO_RISE = 2, - SCREAMER_STATE_RISE_FROM_HOME = 4, - SCREAMER_STATE_FOLLOW_PATH = 5, - SCREAMER_STATE_FACE_LEADER_AT_WAYPOINT = 6, - SCREAMER_STATE_IDLE_AT_HOME = 7, - SCREAMER_STATE_RETURN_HOME = 8, - SCREAMER_STATE_WAIT_TO_WANDER = 9, - SCREAMER_STATE_WANDER = 10, - SCREAMER_STATE_DEATH_KNOCKBACK = 11 -}; - void update_screamer_hit_reactions_and_targeting(struct Moby *moby) { enum { TARGET_SELECTION_DEFAULT_TARGET_EXCLUDED = 2 diff --git a/src/overlays/l10/mobys/toxic_crab.c b/src/overlays/l10/mobys/toxic_crab.c index 4bfa9b99ec..e511c16312 100644 --- a/src/overlays/l10/mobys/toxic_crab.c +++ b/src/overlays/l10/mobys/toxic_crab.c @@ -31,6 +31,22 @@ #include "rnc/mobys/resolve_moby_hit_response.h" #include "rnc/audio/voices/allocate_voice_for_bank_entry.h" +enum { + TOXIC_CRAB_STATE_INITIALIZE = 0, + TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION = 1, + TOXIC_CRAB_STATE_ACTIVATE = 2, + TOXIC_CRAB_STATE_FACE_TRACKED_POSITION = 3, + TOXIC_CRAB_STATE_WAIT_TO_PURSUE = 4, + TOXIC_CRAB_STATE_PURSUE_TARGET = 5, + TOXIC_CRAB_STATE_PAUSE_PURSUIT = 6, + TOXIC_CRAB_STATE_MELEE_ATTACK = 7, + TOXIC_CRAB_STATE_RETURN_HOME = 8, + TOXIC_CRAB_STATE_BACK_AWAY_FROM_TARGET = 9, + TOXIC_CRAB_STATE_HIT_KNOCKBACK = 10, + TOXIC_CRAB_STATE_DEATH_EFFECTS = 11, + TOXIC_CRAB_STATE_FALL_TO_DEATH = 12 +}; + typedef struct Moby Moby; extern struct Moby *D_L10_0015FFD0_macro[] __asm__("D_L10_0015FFD0") MACRO_ADDR; extern float D_0015ED6C; @@ -1003,22 +1019,6 @@ typedef struct Hit_2E52B0 { #include "rnc/overlay/l10/mobys/toxic_crab_globals.h" -enum { - TOXIC_CRAB_STATE_INITIALIZE = 0, - TOXIC_CRAB_STATE_WAIT_FOR_ACTIVATION = 1, - TOXIC_CRAB_STATE_ACTIVATE = 2, - TOXIC_CRAB_STATE_FACE_TRACKED_POSITION = 3, - TOXIC_CRAB_STATE_WAIT_TO_PURSUE = 4, - TOXIC_CRAB_STATE_PURSUE_TARGET = 5, - TOXIC_CRAB_STATE_PAUSE_PURSUIT = 6, - TOXIC_CRAB_STATE_MELEE_ATTACK = 7, - TOXIC_CRAB_STATE_RETURN_HOME = 8, - TOXIC_CRAB_STATE_BACK_AWAY_FROM_TARGET = 9, - TOXIC_CRAB_STATE_HIT_KNOCKBACK = 10, - TOXIC_CRAB_STATE_DEATH_EFFECTS = 11, - TOXIC_CRAB_STATE_FALL_TO_DEATH = 12 -}; - extern float toxic_crab_hit_knockback_gravity_gp __asm__("D_L10_00161E2C") __attribute__((sda)); extern void func_L10_002E14F8_2E52B0(void *) __asm__("FUN_L10_002e0138"); extern float func_001F9878_2E52B0(float) __asm__("FUN_001f96b0"); diff --git a/src/overlays/l11/mobys/jet_fighter.c b/src/overlays/l11/mobys/jet_fighter.c index f8e24c96ee..6c50ddd2f2 100644 --- a/src/overlays/l11/mobys/jet_fighter.c +++ b/src/overlays/l11/mobys/jet_fighter.c @@ -26,6 +26,17 @@ #include "rnc/rendering/view/update_view_context.h" #include "rnc/ui/help/try_set_help_message.h" +enum { + JET_FIGHTER_STATE_INITIALIZE = 0, + JET_FIGHTER_STATE_WAIT_FOR_BOARDING = 1, + JET_FIGHTER_STATE_BOARD = 2, + JET_FIGHTER_STATE_FLIGHT = 4, + JET_FIGHTER_STATE_DISMOUNT = 5, + JET_FIGHTER_STATE_WAIT_FOR_RESPAWN = 7, + JET_FIGHTER_STATE_DELAYED_EXIT = 8, + JET_FIGHTER_STATE_INACTIVE = 9 +}; + extern float D_L11_0015F580[] MACRO_ADDR; extern float D_L11_0015F3FC; @@ -1223,17 +1234,6 @@ unsigned char l11_jet_fighter_max_ammo __asm__("D_L11_00162058") = 0x14; #include "rnc/overlay/l11/mobys/jet_fighter_data/jet_fighter_update.h" -enum { - JET_FIGHTER_STATE_INITIALIZE = 0, - JET_FIGHTER_STATE_WAIT_FOR_BOARDING = 1, - JET_FIGHTER_STATE_BOARD = 2, - JET_FIGHTER_STATE_FLIGHT = 4, - JET_FIGHTER_STATE_DISMOUNT = 5, - JET_FIGHTER_STATE_WAIT_FOR_RESPAWN = 7, - JET_FIGHTER_STATE_DELAYED_EXIT = 8, - JET_FIGHTER_STATE_INACTIVE = 9 -}; - extern float D_L11_00162078 __attribute__((sda)); int D_L11_00162168 = 180; extern float D_L11_0016D4F0_a[] __asm__("D_L11_0016D4F0"); diff --git a/src/overlays/l11/mobys/owner_linked_moby.c b/src/overlays/l11/mobys/owner_linked_moby.c index 01905405f2..7ab4c9ce38 100644 --- a/src/overlays/l11/mobys/owner_linked_moby.c +++ b/src/overlays/l11/mobys/owner_linked_moby.c @@ -9,6 +9,7 @@ #include "rnc/game/interpolated_record.h" #include "rnc/mobys/animation/blend_moby_animation.h" +/* Runs the moby's hit timer: on a hit it either finishes the stun or counts it down and plays the hurt animation. */ enum { LINKED_MOBY_STATE_START_ANIMATION = 0, LINKED_MOBY_STATE_WAIT_FOR_ANIMATION_FLAG = 1, @@ -17,7 +18,6 @@ enum { LINKED_MOBY_STATE_REMOVE = 4 }; -/* Runs the moby's hit timer: on a hit it either finishes the stun or counts it down and plays the hurt animation. */ extern char *find_moby_hit(void *, int, int) __asm__("FUN_L00_0025a420"); extern int fptodp(float) __asm__("FUN_00120478"); extern void print_fe50(char *, int, int) __asm__("FUN_001e93b0"); diff --git a/src/overlays/l11/mobys/pokitaru_boat.c b/src/overlays/l11/mobys/pokitaru_boat.c index 283eaf150d..c70c48642a 100644 --- a/src/overlays/l11/mobys/pokitaru_boat.c +++ b/src/overlays/l11/mobys/pokitaru_boat.c @@ -23,6 +23,15 @@ #include "rnc/camera/follow_cam.h" #include "rnc/math/random.h" +enum { + POKITARU_BOAT_INITIALIZE = 0, + POKITARU_BOAT_WAIT_FOR_ACTIVATION = 1, + POKITARU_BOAT_FOLLOW_PATH = 2, + POKITARU_BOAT_WAIT_FOR_GROUP_CLEAR = 3, + POKITARU_BOAT_RISE_ABOVE_PATH = 4, + POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO = 5 +}; + extern float approach_angle(float *p, float a, float *v, float b, float c, float d) __asm__("FUN_L00_0025be00"); extern float random_float_between(float, float) __asm__("FUN_002132a8"); @@ -86,15 +95,6 @@ extern float pokitaru_boat_max_turn_speed_degrees_gp __asm__("D_L11_00161DDC") _ #include "rnc/overlay/l11/mobys/pokitaru_boat_data/pokitaru_boat_update.h" -enum { - POKITARU_BOAT_INITIALIZE = 0, - POKITARU_BOAT_WAIT_FOR_ACTIVATION = 1, - POKITARU_BOAT_FOLLOW_PATH = 2, - POKITARU_BOAT_WAIT_FOR_GROUP_CLEAR = 3, - POKITARU_BOAT_RISE_ABOVE_PATH = 4, - POKITARU_BOAT_ADJUST_HEIGHT_FOR_HERO = 5 -}; - void pokitaru_boat_update(struct Moby *moby) __asm__("FUN_L11_00309ac0"); /* Moby class 1075 */ diff --git a/src/overlays/l11/mobys/psytcopus.c b/src/overlays/l11/mobys/psytcopus.c index 667263bf79..928b42357c 100644 --- a/src/overlays/l11/mobys/psytcopus.c +++ b/src/overlays/l11/mobys/psytcopus.c @@ -11,6 +11,16 @@ #include "rnc/mobys/moby_spawn.h" #include "rnc/mobys/animation/blend_moby_animation.h" +enum { + PSYTCOPUS_STATE_INITIALIZE = 0, + PSYTCOPUS_STATE_FACE_PLAYER = 3, + PSYTCOPUS_STATE_CREATE_PROJECTILE = 4, + PSYTCOPUS_STATE_FIRE_PROJECTILE = 5, + PSYTCOPUS_STATE_ATTACK_RECOVERY = 6, + PSYTCOPUS_STATE_KNOCKBACK = 7, + PSYTCOPUS_STATE_DEATH_KNOCKBACK = 8 +}; + extern float approach_angle(float *p, float a, float *v, float b, float c, float d) __asm__("FUN_L00_0025be00"); extern char *find_moby_hit(void *, int, int) __asm__("FUN_L00_0025a420"); @@ -92,16 +102,6 @@ FUN_L00_0025f3e8_p(struct Moby *, void *, int, float, float) __asm__("FUN_L00_00 #include "rnc/overlay/l11/mobys/psytcopus_data/psytcopus_update.h" -enum { - PSYTCOPUS_STATE_INITIALIZE = 0, - PSYTCOPUS_STATE_FACE_PLAYER = 3, - PSYTCOPUS_STATE_CREATE_PROJECTILE = 4, - PSYTCOPUS_STATE_FIRE_PROJECTILE = 5, - PSYTCOPUS_STATE_ATTACK_RECOVERY = 6, - PSYTCOPUS_STATE_KNOCKBACK = 7, - PSYTCOPUS_STATE_DEATH_KNOCKBACK = 8 -}; - extern float D_L11_00161F9C __attribute__((sda)); extern void set_moby_position_and_refresh_removal_timer(void *, void *) __asm__("FUN_L11_00318e78"); extern void FUN_L00_0025ab48_p(void *, float *, float *, float *) __asm__("FUN_L00_0025ab48"); diff --git a/src/overlays/l11/mobys/puffoid.c b/src/overlays/l11/mobys/puffoid.c index 119c0f64e9..d1a715d5e2 100644 --- a/src/overlays/l11/mobys/puffoid.c +++ b/src/overlays/l11/mobys/puffoid.c @@ -22,6 +22,30 @@ #include "rnc/overlay/shared/math/interpolation/compute_directed_angle_delta.h" /* pvars of the class 0x4DE creature run by puffoid_update. */ +enum { + PUFFOID_STATE_INITIALIZE = 0, + PUFFOID_STATE_WAIT_FOR_HOME_JUMP = 1, + PUFFOID_STATE_IDLE = 2, + PUFFOID_STATE_WANDER_NEAR_HOME = 3, + PUFFOID_STATE_CHASE_TARGET = 4, + PUFFOID_STATE_SPRAY_ATTACK = 5, + PUFFOID_STATE_RETURN_HOME = 6, + PUFFOID_STATE_JUMP_HOME = 7, + PUFFOID_STATE_JUMP_THEN_WAIT_FOR_HOME_JUMP = 8, + PUFFOID_STATE_KNOCKBACK = 9, + PUFFOID_STATE_REPOSITION_AND_FACE_TARGET = 10, + PUFFOID_STATE_DEATH_KNOCKBACK = 11, + PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP = 12, + PUFFOID_STATE_CARRIER_JUMP = 13, + PUFFOID_STATE_CARRIER_IDLE = 14, + PUFFOID_STATE_CARRIER_CHASE_TARGET = 15, + PUFFOID_STATE_CARRIER_SPRAY_ATTACK = 16, + PUFFOID_STATE_CARRIER_KNOCKBACK = 17, + PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK = 18, + PUFFOID_STATE_FOLLOW_PATH = 19, + PUFFOID_STATE_WAIT_TO_RESUME_COMMAND = 20 +}; + typedef struct { u8 pad00[0x20]; f32 unk20; /* 0x20 */ @@ -657,30 +681,6 @@ extern float puffoid_death_knockback_vertical_scale_gp __asm__("D_L11_001622DC") #include "rnc/overlay/l11/mobys/puffoid_data/update_puffoid_damage_and_path_goal.h" -enum { - PUFFOID_STATE_INITIALIZE = 0, - PUFFOID_STATE_WAIT_FOR_HOME_JUMP = 1, - PUFFOID_STATE_IDLE = 2, - PUFFOID_STATE_WANDER_NEAR_HOME = 3, - PUFFOID_STATE_CHASE_TARGET = 4, - PUFFOID_STATE_SPRAY_ATTACK = 5, - PUFFOID_STATE_RETURN_HOME = 6, - PUFFOID_STATE_JUMP_HOME = 7, - PUFFOID_STATE_JUMP_THEN_WAIT_FOR_HOME_JUMP = 8, - PUFFOID_STATE_KNOCKBACK = 9, - PUFFOID_STATE_REPOSITION_AND_FACE_TARGET = 10, - PUFFOID_STATE_DEATH_KNOCKBACK = 11, - PUFFOID_STATE_WAIT_FOR_CARRIER_JUMP = 12, - PUFFOID_STATE_CARRIER_JUMP = 13, - PUFFOID_STATE_CARRIER_IDLE = 14, - PUFFOID_STATE_CARRIER_CHASE_TARGET = 15, - PUFFOID_STATE_CARRIER_SPRAY_ATTACK = 16, - PUFFOID_STATE_CARRIER_KNOCKBACK = 17, - PUFFOID_STATE_CARRIER_DEATH_KNOCKBACK = 18, - PUFFOID_STATE_FOLLOW_PATH = 19, - PUFFOID_STATE_WAIT_TO_RESUME_COMMAND = 20 -}; - extern float l11_puffoid_horizontal_speed_limit __asm__("D_L11_001622FC") __attribute__((sda)); /* Private variables of the moby FUN_L11_00315968 updates (only the fields it uses). */ diff --git a/src/overlays/l12/hero/update_hero_motion_for_current_state.c b/src/overlays/l12/hero/update_hero_motion_for_current_state.c index e95e9e2ace..d7fbdc307c 100644 --- a/src/overlays/l12/hero/update_hero_motion_for_current_state.c +++ b/src/overlays/l12/hero/update_hero_motion_for_current_state.c @@ -24,6 +24,13 @@ #include "rnc/world/collision/collision_hit_material.h" /* Per-frame update of the player state flags from the current state; same source as FUN_L11_0023c7a0 with states 2 and 7 and without the water check. */ +enum { + GROUND_MATERIAL_WATER = 0, + GROUND_MATERIAL_MAGNET = 2, + GROUND_MATERIAL_ICE = 7, + GROUND_MATERIAL_SINK_TRIGGER = 0xD +}; + extern void exit_hero_vehicle_mode_if_mode_three(void) __asm__("FUN_L00_0020b930"); extern int hero_set_state(int, int) __asm__("FUN_L12_002400d0"); float absolute_float(float input) __asm__("func_001F99C0"); @@ -405,13 +412,6 @@ void update_hero_ground_contact_and_gravity(void) { #include "rnc/math/vector.h" #include "rnc/math/fast_math.h" -enum { - GROUND_MATERIAL_WATER = 0, - GROUND_MATERIAL_MAGNET = 2, - GROUND_MATERIAL_ICE = 7, - GROUND_MATERIAL_SINK_TRIGGER = 0xD -}; - struct MobyView { u8 pad0[0xC]; f32 fC; diff --git a/src/overlays/l12/mobys/blarg_helicopter.c b/src/overlays/l12/mobys/blarg_helicopter.c index d6132651b6..ed649869ab 100644 --- a/src/overlays/l12/mobys/blarg_helicopter.c +++ b/src/overlays/l12/mobys/blarg_helicopter.c @@ -12,6 +12,16 @@ #include "rnc/math/random.h" #include "rnc/mobys/moby_spawn.h" +enum { + BLARG_HELICOPTER_INITIALIZE = 0, + BLARG_HELICOPTER_WAIT_FOR_ACTIVATION = 1, + BLARG_HELICOPTER_FOLLOW_INITIAL_PATH = 2, + BLARG_HELICOPTER_AIM_AND_FIRE = 3, + BLARG_HELICOPTER_MOVE_BETWEEN_PATH_ENDPOINTS = 4, + BLARG_HELICOPTER_KNOCKBACK = 5, + BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET = 6 +}; + extern char D_L12_00167240[]; #include "rnc/overlay/shared/world/level_path.h" @@ -88,16 +98,6 @@ extern int D_L12_001619A0 __attribute__((sda)); #include "rnc/game/game_globals.h" #include "rnc/audio/voice_pool.h" -enum { - BLARG_HELICOPTER_INITIALIZE = 0, - BLARG_HELICOPTER_WAIT_FOR_ACTIVATION = 1, - BLARG_HELICOPTER_FOLLOW_INITIAL_PATH = 2, - BLARG_HELICOPTER_AIM_AND_FIRE = 3, - BLARG_HELICOPTER_MOVE_BETWEEN_PATH_ENDPOINTS = 4, - BLARG_HELICOPTER_KNOCKBACK = 5, - BLARG_HELICOPTER_EXPLODE_AND_REMOVE_OR_RESET = 6 -}; - extern unsigned char D_0013E550[]; extern unsigned char D_0013D4CB NOT_SDA; extern unsigned short D_00141C50 NOT_SDA; diff --git a/src/overlays/l12/mobys/blarg_trooper.c b/src/overlays/l12/mobys/blarg_trooper.c index c04f7ed598..02ed23f2d0 100644 --- a/src/overlays/l12/mobys/blarg_trooper.c +++ b/src/overlays/l12/mobys/blarg_trooper.c @@ -16,6 +16,19 @@ #include "rnc/overlay/l12/mobys/miner.h" #include "rnc/mobys/resolve_moby_hit_response.h" +enum { + BLARG_TROOPER_INITIALIZE = 0, + BLARG_TROOPER_FOLLOW_WAYPOINTS = 1, + BLARG_TROOPER_WAIT_FOR_ACTIVATION = 2, + BLARG_TROOPER_APPROACH_TARGET = 3, + BLARG_TROOPER_KNOCKBACK_RECOVERY = 4, + BLARG_TROOPER_PREPARE_SHOT = 5, + BLARG_TROOPER_FIRE_PROJECTILE = 6, + BLARG_TROOPER_WAIT_BETWEEN_SHOTS = 7, + BLARG_TROOPER_RETURN_HOME = 8, + BLARG_TROOPER_DEATH_FALL = 9 +}; + extern char D_L12_00167240[]; #include "rnc/overlay/shared/world/level_path.h" @@ -48,19 +61,6 @@ extern int point_in_path_xy(void *, void *, int) __asm__("FUN_L00_00259740"); #include "rnc/overlay/shared/world/level_globals.h" -enum { - BLARG_TROOPER_INITIALIZE = 0, - BLARG_TROOPER_FOLLOW_WAYPOINTS = 1, - BLARG_TROOPER_WAIT_FOR_ACTIVATION = 2, - BLARG_TROOPER_APPROACH_TARGET = 3, - BLARG_TROOPER_KNOCKBACK_RECOVERY = 4, - BLARG_TROOPER_PREPARE_SHOT = 5, - BLARG_TROOPER_FIRE_PROJECTILE = 6, - BLARG_TROOPER_WAIT_BETWEEN_SHOTS = 7, - BLARG_TROOPER_RETURN_HOME = 8, - BLARG_TROOPER_DEATH_FALL = 9 -}; - extern s32 count_active_moby_group_members(s32, s32) __asm__("FUN_L01_0026e008"); extern void trooper_knockback_arc(void *, f32 *, f32 *, f32 *) __asm__("FUN_L00_0025ab48"); extern float fast_subtract_rotations(float, float); diff --git a/src/overlays/l12/mobys/hoven_anklebiter.c b/src/overlays/l12/mobys/hoven_anklebiter.c index ee237620e7..f8eaec66c5 100644 --- a/src/overlays/l12/mobys/hoven_anklebiter.c +++ b/src/overlays/l12/mobys/hoven_anklebiter.c @@ -26,6 +26,25 @@ /* Suck cannon suction method: state 8 while sucked (alerting its group), back to 1 when released; no suction in states 9, 11 and 13. */ /* Ported from rac1-decomp (src/overlays/l12_hoven/vendor_002C0310.c: func_L12_002E29C8), where it is exact; names translated to the US level program. */ +enum { + ANKLEBITER_INITIALIZE = 0, + ANKLEBITER_IDLE = 1, + ANKLEBITER_FACE_TARGET_BEFORE_PURSUIT = 3, + ANKLEBITER_PURSUE_TARGET = 4, + ANKLEBITER_MELEE_ATTACK = 5, + ANKLEBITER_RETURN_HOME = 6, + ANKLEBITER_KNOCKBACK_FALL = 7, + ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME = 8, + ANKLEBITER_DORMANT = 9, + ANKLEBITER_RECOVER_AFTER_KNOCKBACK = 10, + ANKLEBITER_WAIT_FOR_LEAP_TRIGGER = 11, + ANKLEBITER_LEAP_TO_HOME = 12, + ANKLEBITER_ACTIVATE_FROM_DORMANCY = 13, + ANKLEBITER_LAND_AFTER_LEAP = 14, + ANKLEBITER_DEATH_EFFECTS_AND_REMOVE = 15, + ANKLEBITER_DEATH_FALL = 99 +}; + extern int process_moby_suck_cannon_suction(void *) __asm__("FUN_L00_002db8f8"); int process_hoven_anklebiter_suck_cannon_suction(struct Moby *moby) __asm__("FUN_L12_002e16b8"); @@ -871,25 +890,6 @@ extern void anim_update_e3528(struct Moby *, void *) __asm__("FUN_L00_0025d538") #include "rnc/overlay/l12/mobys/hoven_anklebiter_data/process_hoven_anklebiter_damage_and_alerts.h" -enum { - ANKLEBITER_INITIALIZE = 0, - ANKLEBITER_IDLE = 1, - ANKLEBITER_FACE_TARGET_BEFORE_PURSUIT = 3, - ANKLEBITER_PURSUE_TARGET = 4, - ANKLEBITER_MELEE_ATTACK = 5, - ANKLEBITER_RETURN_HOME = 6, - ANKLEBITER_KNOCKBACK_FALL = 7, - ANKLEBITER_CONTROLLED_MOTION_UNTIL_RETURN_HOME = 8, - ANKLEBITER_DORMANT = 9, - ANKLEBITER_RECOVER_AFTER_KNOCKBACK = 10, - ANKLEBITER_WAIT_FOR_LEAP_TRIGGER = 11, - ANKLEBITER_LEAP_TO_HOME = 12, - ANKLEBITER_ACTIVATE_FROM_DORMANCY = 13, - ANKLEBITER_LAND_AFTER_LEAP = 14, - ANKLEBITER_DEATH_EFFECTS_AND_REMOVE = 15, - ANKLEBITER_DEATH_FALL = 99 -}; - /* Damage and alert step of the Hoven anklebiter: refreshes its speed while alerted, now and then calls for help behind itself, and takes hits (dying, or staggering back). */ void process_hoven_anklebiter_damage_and_alerts(struct Moby *moby) __asm__("FUN_L12_002e3528"); diff --git a/src/overlays/l12/mobys/planetbuster_maximus_part.c b/src/overlays/l12/mobys/planetbuster_maximus_part.c index bc839a7ffb..09a8430e07 100644 --- a/src/overlays/l12/mobys/planetbuster_maximus_part.c +++ b/src/overlays/l12/mobys/planetbuster_maximus_part.c @@ -26,6 +26,14 @@ #include "rnc/overlay/shared/mobys/capture_linked_moby_relative_transforms.h" #include "rnc/overlay/shared/world/level_path.h" +enum { + PLANETBUSTER_INITIALIZE_LINKED_PARTS = 0, + PLANETBUSTER_WAIT_FOR_PATH_TRIGGER = 1, + PLANETBUSTER_FOLLOW_PATH = 2, + PLANETBUSTER_POST_PATH_GUN_UPDATE = 3, + PLANETBUSTER_DROP_PARTS_AND_TRANSITION = 4 +}; + typedef struct Moby Moby; extern float D_0015ED6C; @@ -636,14 +644,6 @@ extern float planetbuster_maximus_rotation_oscillation_amplitude_gp __asm__("D_L #include "rnc/game/game_globals.h" -enum { - PLANETBUSTER_INITIALIZE_LINKED_PARTS = 0, - PLANETBUSTER_WAIT_FOR_PATH_TRIGGER = 1, - PLANETBUSTER_FOLLOW_PATH = 2, - PLANETBUSTER_POST_PATH_GUN_UPDATE = 3, - PLANETBUSTER_DROP_PARTS_AND_TRANSITION = 4 -}; - extern void FUN_L00_00258278(char *moby, float target, float *vel, float k, float d, float max); extern void vendor_spring(float *, float *, float, float, float, float) __asm__("FUN_L00_0025b8c0"); extern void update_moby_vertical_oscillation(float, float, char *, float *, float *) __asm__("FUN_L00_00262b00"); diff --git a/src/overlays/l13/mobys/blarg_gunner.c b/src/overlays/l13/mobys/blarg_gunner.c index 317e3373f7..3334794589 100644 --- a/src/overlays/l13/mobys/blarg_gunner.c +++ b/src/overlays/l13/mobys/blarg_gunner.c @@ -9,6 +9,12 @@ #include "rnc/overlay/shared/mobys/find_moby_hit.h" #include "rnc/overlay/shared/mobys/moby_point_position.h" +enum { + BLARG_GUNNER_STATE_INITIALIZE = 0, + BLARG_GUNNER_STATE_ACTIVE = 1, + BLARG_GUNNER_STATE_DESTROY = 2 +}; + #ifndef NOT_SDA #define NOT_SDA __attribute__((section(".data"))) #endif @@ -18,12 +24,6 @@ #include "qcopy.h" #include "rnc/overlay/shared/math/random/random_int_between.h" -enum { - BLARG_GUNNER_STATE_INITIALIZE = 0, - BLARG_GUNNER_STATE_ACTIVE = 1, - BLARG_GUNNER_STATE_DESTROY = 2 -}; - extern void FUN_L00_00257470(void *, int, int); extern void spawn_explosion(void *, diff --git a/src/overlays/l13/mobys/blarg_space_commando.c b/src/overlays/l13/mobys/blarg_space_commando.c index 2370c1bab8..d4e1dcb889 100644 --- a/src/overlays/l13/mobys/blarg_space_commando.c +++ b/src/overlays/l13/mobys/blarg_space_commando.c @@ -23,6 +23,26 @@ #include "rnc/rendering/vu1_registers.h" #include "rnc/rendering/effect_texture.h" +enum { + BLARG_SPACE_COMMANDO_INITIALIZE = 0, + BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION = 1, + BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION = 2, + BLARG_SPACE_COMMANDO_SELECT_ACTION_AFTER_ANIMATION = 3, + BLARG_SPACE_COMMANDO_FACE_TARGET_AND_WAIT_FOR_TIMER = 4, + BLARG_SPACE_COMMANDO_FACE_TARGET_AND_PROBE_DURING_ANIMATION = 5, + BLARG_SPACE_COMMANDO_RESUME_SAVED_STATE_AFTER_ANIMATION = 6, + BLARG_SPACE_COMMANDO_APPROACH_TARGET_WITH_TURN_OFFSET = 7, + BLARG_SPACE_COMMANDO_APPROACH_TARGET_UNTIL_BLOCKED_OR_NEAR = 11, + BLARG_SPACE_COMMANDO_PROBE_DURING_ANIMATION_THEN_RESUME_APPROACH = 12, + BLARG_SPACE_COMMANDO_RETURN_HOME = 13, + BLARG_SPACE_COMMANDO_KNOCKBACK = 15, + BLARG_SPACE_COMMANDO_DYING = 16 +}; + +enum { + HIT_STATUS_SKIP_DAMAGE_PROCESSING = 1 +}; + extern void mark_moby_for_removal(void *) __asm__("FUN_0020c828"); extern CollisionHit coll_hit_1638 __asm__("D_L13_00174140"); @@ -559,26 +579,6 @@ extern f32 D_L13_00161E58 __attribute__((sda)); #include "rnc/overlay/shared/world/level_labels.h" -enum { - BLARG_SPACE_COMMANDO_INITIALIZE = 0, - BLARG_SPACE_COMMANDO_FACE_TARGET_AND_SELECT_ACTION = 1, - BLARG_SPACE_COMMANDO_ENTER_ACTION_SELECTION_AFTER_ANIMATION = 2, - BLARG_SPACE_COMMANDO_SELECT_ACTION_AFTER_ANIMATION = 3, - BLARG_SPACE_COMMANDO_FACE_TARGET_AND_WAIT_FOR_TIMER = 4, - BLARG_SPACE_COMMANDO_FACE_TARGET_AND_PROBE_DURING_ANIMATION = 5, - BLARG_SPACE_COMMANDO_RESUME_SAVED_STATE_AFTER_ANIMATION = 6, - BLARG_SPACE_COMMANDO_APPROACH_TARGET_WITH_TURN_OFFSET = 7, - BLARG_SPACE_COMMANDO_APPROACH_TARGET_UNTIL_BLOCKED_OR_NEAR = 11, - BLARG_SPACE_COMMANDO_PROBE_DURING_ANIMATION_THEN_RESUME_APPROACH = 12, - BLARG_SPACE_COMMANDO_RETURN_HOME = 13, - BLARG_SPACE_COMMANDO_KNOCKBACK = 15, - BLARG_SPACE_COMMANDO_DYING = 16 -}; - -enum { - HIT_STATUS_SKIP_DAMAGE_PROCESSING = 1 -}; - extern char D_L13_00160680[] MACRO_ADDR; extern s32 D_001413D0_lui[] __asm__("D_001413D0") NOT_SDA; diff --git a/src/overlays/l13/mobys/blarg_space_fighter.c b/src/overlays/l13/mobys/blarg_space_fighter.c index bb8532f192..e22358b057 100644 --- a/src/overlays/l13/mobys/blarg_space_fighter.c +++ b/src/overlays/l13/mobys/blarg_space_fighter.c @@ -14,6 +14,18 @@ #include "rnc/overlay/shared/rendering/effects/spawn_explosion.h" #include "rnc/sdk/libc/stdlib.h" +enum { + FIGHTER_INITIALIZE = 0, + FIGHTER_WAIT_TO_JOIN_PATH = 1, + FIGHTER_FOLLOW_PATH_AND_ATTACK = 2, + FIGHTER_EMIT_DESTRUCTION_EFFECTS = 3, + FIGHTER_WAIT_TO_REINITIALIZE = 4 +}; + +enum { + HIT_PROCESSING_DAMAGE_THRESHOLD = 2 +}; + extern char *find_moby_hit(void *, int, int) __asm__("FUN_L00_0025a420"); extern char D_0013F350[]; @@ -49,18 +61,6 @@ extern char D_00140940[]; #include "rnc/overlay/l13/effect_suppression_levels.h" -enum { - FIGHTER_INITIALIZE = 0, - FIGHTER_WAIT_TO_JOIN_PATH = 1, - FIGHTER_FOLLOW_PATH_AND_ATTACK = 2, - FIGHTER_EMIT_DESTRUCTION_EFFECTS = 3, - FIGHTER_WAIT_TO_REINITIALIZE = 4 -}; - -enum { - HIT_PROCESSING_DAMAGE_THRESHOLD = 2 -}; - extern float random_float_between(float, float) __asm__("FUN_002132a8"); extern void trooper_anim_update(void *, short *) __asm__("FUN_L00_0025d458"); diff --git a/src/overlays/l13/mobys/blarg_turret.c b/src/overlays/l13/mobys/blarg_turret.c index c56cc9c13b..13bdcc705c 100644 --- a/src/overlays/l13/mobys/blarg_turret.c +++ b/src/overlays/l13/mobys/blarg_turret.c @@ -16,6 +16,14 @@ #include "rnc/overlay/shared/math/random/random_vector.h" #include "rnc/overlay/l13/mobys/blarg_turret_globals.h" +enum { + BLARG_TURRET_STATE_INITIALIZE = 0, + BLARG_TURRET_STATE_WAIT_FOR_TARGET = 1, + BLARG_TURRET_STATE_TRACK_TARGET = 3, + BLARG_TURRET_STATE_DESTROY = 4, + BLARG_TURRET_STATE_DESTRUCTION_DELAY = 5 +}; + #ifndef NOT_SDA #define NOT_SDA __attribute__((section(".data"))) #endif @@ -25,14 +33,6 @@ #include "qcopy.h" #include "rnc/overlay/l13/mobys/gemlik_projectile.h" -enum { - BLARG_TURRET_STATE_INITIALIZE = 0, - BLARG_TURRET_STATE_WAIT_FOR_TARGET = 1, - BLARG_TURRET_STATE_TRACK_TARGET = 3, - BLARG_TURRET_STATE_DESTROY = 4, - BLARG_TURRET_STATE_DESTRUCTION_DELAY = 5 -}; - typedef struct { float x, y, z, w; } __attribute__((aligned(16))) V4_2B5368; diff --git a/src/overlays/l13/mobys/elevator.c b/src/overlays/l13/mobys/elevator.c index 8fe3903099..a9acf8ffe7 100644 --- a/src/overlays/l13/mobys/elevator.c +++ b/src/overlays/l13/mobys/elevator.c @@ -10,16 +10,6 @@ #include "rnc/overlay/shared/audio/voices/voice_is_playing.h" #include "rnc/overlay/shared/hero/hero_set_state.h" -#ifndef NOT_SDA -#define NOT_SDA __attribute__((section(".data"))) -#endif -#ifndef MACRO_ADDR -#define MACRO_ADDR __attribute__((section(".sdata"))) -#endif -#include "qcopy.h" -#include "rnc/math/interpolation/advance_accelerated_scalar.h" -#include "rnc/overlay/shared/camera/scripted_camera.h" - enum { ELEVATOR_STATE_INITIALIZE = 0, ELEVATOR_STATE_BLEND_CAMERA = 1, @@ -31,6 +21,16 @@ enum { ELEVATOR_STATE_WAIT_FOR_HERO_EXIT_AT_BOTTOM = 7 }; +#ifndef NOT_SDA +#define NOT_SDA __attribute__((section(".data"))) +#endif +#ifndef MACRO_ADDR +#define MACRO_ADDR __attribute__((section(".sdata"))) +#endif +#include "qcopy.h" +#include "rnc/math/interpolation/advance_accelerated_scalar.h" +#include "rnc/overlay/shared/camera/scripted_camera.h" + typedef struct { u8 pad0[0x20]; u8 path[0x40]; /* 0x20: passed to update_entity_matrix with the moved delta */ diff --git a/src/overlays/l13/mobys/fighter_jet.c b/src/overlays/l13/mobys/fighter_jet.c index 873c11c462..853d0bb33b 100644 --- a/src/overlays/l13/mobys/fighter_jet.c +++ b/src/overlays/l13/mobys/fighter_jet.c @@ -21,6 +21,18 @@ #include "rnc/audio/voice_pool.h" #include "rnc/rendering/effect_texture.h" +enum { + FIGHTER_JET_STATE_INITIALIZE = 0, + FIGHTER_JET_STATE_WAIT_FOR_ENTRY = 1, + FIGHTER_JET_STATE_MOUNT_PLAYER = 2, + FIGHTER_JET_STATE_FLIGHT = 4, + FIGHTER_JET_STATE_EXIT_PLAYER = 5, + FIGHTER_JET_STATE_STOP_DEATH_SOUNDS = 6, + FIGHTER_JET_STATE_WAIT_FOR_DEATH_RESET = 7, + FIGHTER_JET_STATE_FORCED_EXIT = 8, + FIGHTER_JET_STATE_DELETE = 9 +}; + #ifndef NOT_SDA #define NOT_SDA __attribute__((section(".data"))) #endif @@ -1712,18 +1724,6 @@ extern JetCamera jet_camera47 __asm__("D_L13_00166F80"); #include "rnc/overlay/l13/mobys/fighter_jet_data/fighter_jet_update.h" -enum { - FIGHTER_JET_STATE_INITIALIZE = 0, - FIGHTER_JET_STATE_WAIT_FOR_ENTRY = 1, - FIGHTER_JET_STATE_MOUNT_PLAYER = 2, - FIGHTER_JET_STATE_FLIGHT = 4, - FIGHTER_JET_STATE_EXIT_PLAYER = 5, - FIGHTER_JET_STATE_STOP_DEATH_SOUNDS = 6, - FIGHTER_JET_STATE_WAIT_FOR_DEATH_RESET = 7, - FIGHTER_JET_STATE_FORCED_EXIT = 8, - FIGHTER_JET_STATE_DELETE = 9 -}; - extern JetTexture l13_texture_descriptors[] __asm__("D_L13_0016D480"); extern unsigned int l13_texture_palette_data_base __asm__("D_L13_0015F420"); diff --git a/src/overlays/l13/mobys/forcefield_tower.c b/src/overlays/l13/mobys/forcefield_tower.c index b9bcbe71a8..03e7798b3d 100644 --- a/src/overlays/l13/mobys/forcefield_tower.c +++ b/src/overlays/l13/mobys/forcefield_tower.c @@ -18,6 +18,12 @@ #include "rnc/overlay/shared/math/random/random_int_between.h" #include "rnc/sdk/debug.h" +enum { + TOWER_STATE_INITIALIZE = 0, + TOWER_STATE_ACTIVE = 1, + TOWER_STATE_DESTRUCTION = 2 +}; + extern char *find_moby_hit(void *, int, int) __asm__("FUN_L00_0025a420"); extern f32 random_float_between(f32, f32) __asm__("FUN_002132a8"); @@ -30,12 +36,6 @@ extern void mark_moby_for_removal(void *) __asm__("FUN_0020c828"); #include "rnc/overlay/l13/effect_suppression_levels.h" -enum { - TOWER_STATE_INITIALIZE = 0, - TOWER_STATE_ACTIVE = 1, - TOWER_STATE_DESTRUCTION = 2 -}; - extern float random_float_between(float, float) __asm__("FUN_002132a8"); extern void FUN_L00_00257470(struct Moby *, int, int); diff --git a/src/overlays/l13/mobys/hovering_rocket_attacker.c b/src/overlays/l13/mobys/hovering_rocket_attacker.c index fa6e689f50..c1fd5f9dea 100644 --- a/src/overlays/l13/mobys/hovering_rocket_attacker.c +++ b/src/overlays/l13/mobys/hovering_rocket_attacker.c @@ -16,6 +16,16 @@ #include "rnc/overlay/shared/audio/voices/voice_is_playing.h" #include "rnc/overlay/shared/math/random/random_int_between.h" +enum { + UPDATE_INITIALIZE = 0x0, + TRACK_TARGET_BEFORE_ATTACK = 0x2, + UPDATE_ATTACK_SEQUENCE = 0x4, + WAIT_TO_MOVE_TO_TABLE_POINT = 0x5, + MOVE_TO_TABLE_POINT = 0x6, + WAIT_TO_RESUME_ATTACK_SEQUENCE = 7, + EMIT_EFFECT_AND_REMOVE = 0x8 +}; + extern char D_0013F350[]; extern f32 random_float_between(f32, f32) __asm__("FUN_002132a8"); @@ -356,16 +366,6 @@ extern char *D_L13_001B07B0[]; #include "rnc/overlay/shared/world/level_labels.h" -enum { - UPDATE_INITIALIZE = 0x0, - TRACK_TARGET_BEFORE_ATTACK = 0x2, - UPDATE_ATTACK_SEQUENCE = 0x4, - WAIT_TO_MOVE_TO_TABLE_POINT = 0x5, - MOVE_TO_TABLE_POINT = 0x6, - WAIT_TO_RESUME_ATTACK_SEQUENCE = 7, - EMIT_EFFECT_AND_REMOVE = 0x8 -}; - extern float hovering_rocket_attacker_scale_multiplier_gp __asm__("D_L13_00161490") __attribute__((sda)); diff --git a/src/overlays/l14/mobys/blarg_heavy_interceptor.c b/src/overlays/l14/mobys/blarg_heavy_interceptor.c index 76b1bab070..7b96578c7e 100644 --- a/src/overlays/l14/mobys/blarg_heavy_interceptor.c +++ b/src/overlays/l14/mobys/blarg_heavy_interceptor.c @@ -21,6 +21,18 @@ #include "sda.h" #include "rnc/overlay/l14/mobys/blarg_heavy_interceptor_globals.h" +enum { + INTERCEPTOR_STATE_INITIALIZE = 0, + INTERCEPTOR_STATE_PATROL_AND_SCAN = 1, + INTERCEPTOR_STATE_ALERT_GROUP = 2, + INTERCEPTOR_STATE_TRACK_TARGET = 3, + INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY = 4, + INTERCEPTOR_STATE_FOLLOW_RETURN_PATH = 5, + INTERCEPTOR_STATE_REJOIN_PATROL = 6, + INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL = 7, + INTERCEPTOR_STATE_DEATH_FALL = 9 +}; + extern u16 *D_L14_001ABF40_u[] __asm__("D_L14_001ABF40"); extern u8 *D_L14_0015FFD8; @@ -172,18 +184,6 @@ extern char D_L14_0015F580[] MACRO_ADDR; #include "rnc/overlay/l14/mobys/blarg_heavy_interceptor_data/blarg_heavy_interceptor_update.h" -enum { - INTERCEPTOR_STATE_INITIALIZE = 0, - INTERCEPTOR_STATE_PATROL_AND_SCAN = 1, - INTERCEPTOR_STATE_ALERT_GROUP = 2, - INTERCEPTOR_STATE_TRACK_TARGET = 3, - INTERCEPTOR_STATE_WAIT_FOR_GROUP_READY = 4, - INTERCEPTOR_STATE_FOLLOW_RETURN_PATH = 5, - INTERCEPTOR_STATE_REJOIN_PATROL = 6, - INTERCEPTOR_STATE_INITIALIZE_DEATH_FALL = 7, - INTERCEPTOR_STATE_DEATH_FALL = 9 -}; - extern f32 l14_blarg_heavy_interceptor_path_easing_error_gain __asm__("D_L14_001613A0") __attribute__((sda)); diff --git a/src/overlays/l14/mobys/enemy_fighter.c b/src/overlays/l14/mobys/enemy_fighter.c index f868d2b0f8..ae1ff5974c 100644 --- a/src/overlays/l14/mobys/enemy_fighter.c +++ b/src/overlays/l14/mobys/enemy_fighter.c @@ -15,6 +15,12 @@ #include "rnc/overlay/l14/mobys/puff.h" #include "rnc/overlay/l14/mobys/enemy_fighter.h" +enum { + ENEMY_FIGHTER_STATE_INITIALIZE = 0, + ENEMY_FIGHTER_STATE_FOLLOW_PATH = 1, + ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN = 2 +}; + extern void debug_print(const char *, short) __asm__("FUN_001e93b0"); extern void mark_moby_for_removal(void *) __asm__("FUN_0020c828"); @@ -139,12 +145,6 @@ void enemy_fighter_update(struct Moby *moby) { #include "rnc/overlay/l14/mobys/enemy_fighter_data/spawn_enemy_fighter_exhaust.h" -enum { - ENEMY_FIGHTER_STATE_INITIALIZE = 0, - ENEMY_FIGHTER_STATE_FOLLOW_PATH = 1, - ENEMY_FIGHTER_STATE_WAIT_FOR_RESPAWN = 2 -}; - extern char D_L14_0015F580[] MACRO_ADDR; extern int exhaust_ftoi(float) __asm__("FUN_001fa6d0"); diff --git a/src/overlays/l14/mobys/flying_car.c b/src/overlays/l14/mobys/flying_car.c index 7a5dc461ed..2bb0155620 100644 --- a/src/overlays/l14/mobys/flying_car.c +++ b/src/overlays/l14/mobys/flying_car.c @@ -15,12 +15,6 @@ #include "rnc/audio/voice_pool.h" #include "rnc/camera/update_cam.h" -extern u8 *D_L14_00167500 NOT_SDA; - -void seed_linked_record_for_flying_car(u8 *flying_car_moby) __asm__("FUN_L14_003135b8"); - -#include "rnc/overlay/l14/mobys/flying_car_globals.h" - enum { FLYING_CAR_INITIALIZE = 0, FLYING_CAR_WAIT_FOR_TRIGGER = 1, @@ -28,6 +22,12 @@ enum { FLYING_CAR_WAIT_FOR_PATH_RESET = 3 }; +extern u8 *D_L14_00167500 NOT_SDA; + +void seed_linked_record_for_flying_car(u8 *flying_car_moby) __asm__("FUN_L14_003135b8"); + +#include "rnc/overlay/l14/mobys/flying_car_globals.h" + int voice_is_playing(int a, int i) __asm__("FUN_L00_0028d8c0"); typedef struct { diff --git a/src/overlays/l14/mobys/rocket_strike_fighter.c b/src/overlays/l14/mobys/rocket_strike_fighter.c index 5165f0128f..71339c7035 100644 --- a/src/overlays/l14/mobys/rocket_strike_fighter.c +++ b/src/overlays/l14/mobys/rocket_strike_fighter.c @@ -29,6 +29,13 @@ #include "rnc/overlay/shared/rendering/effects/spawn_explosion.h" #include "rnc/overlay/shared/vendor.h" +enum { + ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE = 0, + ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS = 1, + ROCKET_STRIKE_FIGHTER_STATE_FOLLOW_PATH = 2, + ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN = 3 +}; + extern float vector_length_xy(void *); extern void debug_print(const char *, short) __asm__("FUN_001e93b0"); @@ -268,13 +275,6 @@ extern f32 rocket_strike_fighter_exhaust_grey_puff_row0_offset_gp __asm__("D_L14 #include "rnc/overlay/l14/mobys/rocket_strike_fighter_data/spawn_rocket_strike_fighter_exhaust.h" -enum { - ROCKET_STRIKE_FIGHTER_STATE_INITIALIZE = 0, - ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_MISSIONS = 1, - ROCKET_STRIKE_FIGHTER_STATE_FOLLOW_PATH = 2, - ROCKET_STRIKE_FIGHTER_STATE_WAIT_FOR_RESPAWN = 3 -}; - void spawn_rocket_strike_fighter_exhaust(struct Moby *moby) { Vec4 step; Vec4 pos; diff --git a/src/overlays/l14/mobys/taxi.c b/src/overlays/l14/mobys/taxi.c index 4ddc1439cd..9799fc2f82 100644 --- a/src/overlays/l14/mobys/taxi.c +++ b/src/overlays/l14/mobys/taxi.c @@ -18,6 +18,16 @@ #include "rnc/overlay/shared/cutscenes/update_npc_dialogue.h" #include "rnc/overlay/shared/world/cuboid.h" +enum { + TAXI_STATE_INITIALIZE = 0, + TAXI_STATE_WAIT_AT_STOP = 1, + TAXI_STATE_BLEND_STOP_TO_PATH_START = 3, + TAXI_STATE_FOLLOW_PATH = 4, + TAXI_STATE_BLEND_PATH_END_TO_STOP = 5, + TAXI_STATE_WAIT_FOR_ITEM_GATE = 6, + TAXI_STATE_BLEND_SAVED_POSE_TO_PATH_START = 7 +}; + enum TaxiStop { TAXI_STOP_RETURN_HUB = 0x0, TAXI_STOP_HUB_OUTBOUND_DESTINATION = 0x1, @@ -29,16 +39,6 @@ extern float cubic_hermite_scalar(float, float, float, float, float) __asm__("FU #include "rnc/overlay/l14/mobys/taxi_globals.h" -enum { - TAXI_STATE_INITIALIZE = 0, - TAXI_STATE_WAIT_AT_STOP = 1, - TAXI_STATE_BLEND_STOP_TO_PATH_START = 3, - TAXI_STATE_FOLLOW_PATH = 4, - TAXI_STATE_BLEND_PATH_END_TO_STOP = 5, - TAXI_STATE_WAIT_FOR_ITEM_GATE = 6, - TAXI_STATE_BLEND_SAVED_POSE_TO_PATH_START = 7 -}; - typedef struct { u8 pad0[0x20]; u8 spring[0x40]; /* 0x20 */ diff --git a/src/overlays/l15/mobys/ultramech_unlimited.c b/src/overlays/l15/mobys/ultramech_unlimited.c index 7b8a92e228..a4f1af65f6 100644 --- a/src/overlays/l15/mobys/ultramech_unlimited.c +++ b/src/overlays/l15/mobys/ultramech_unlimited.c @@ -24,6 +24,21 @@ #include "rnc/overlay/shared/world/level_path.h" #include "rnc/overlay/l15/mobys/ultramech_unlimited_globals.h" +enum { + ULTRAMECH_INITIALIZE = 0, + ULTRAMECH_WAIT_FOR_ACTIVATION = 1, + ULTRAMECH_FOLLOW_ENTRY_PATH = 2, + ULTRAMECH_BALLISTIC_PATH_MOVE = 3, + ULTRAMECH_AIM_AND_SELECT_ATTACK = 4, + ULTRAMECH_FIRE_BURST = 5, + ULTRAMECH_WAIT_BETWEEN_BURSTS = 6, + ULTRAMECH_APPROACH_TARGET = 7, + ULTRAMECH_MELEE_ATTACK = 8, + ULTRAMECH_KNOCKBACK_RECOVERY = 9, + ULTRAMECH_DEATH_EFFECTS = 10, + ULTRAMECH_DEAD_WAIT_FOR_RESET = 0x40 +}; + extern char D_0014C190[]; extern int D_L15_001BAAD0[]; @@ -912,21 +927,6 @@ void ultramech_unlimited_update(UMoby *ultramech_moby) { #include "rnc/overlay/l15/mobys/ultramech_unlimited_data/process_ultramech_hits_and_update_target.h" -enum { - ULTRAMECH_INITIALIZE = 0, - ULTRAMECH_WAIT_FOR_ACTIVATION = 1, - ULTRAMECH_FOLLOW_ENTRY_PATH = 2, - ULTRAMECH_BALLISTIC_PATH_MOVE = 3, - ULTRAMECH_AIM_AND_SELECT_ATTACK = 4, - ULTRAMECH_FIRE_BURST = 5, - ULTRAMECH_WAIT_BETWEEN_BURSTS = 6, - ULTRAMECH_APPROACH_TARGET = 7, - ULTRAMECH_MELEE_ATTACK = 8, - ULTRAMECH_KNOCKBACK_RECOVERY = 9, - ULTRAMECH_DEATH_EFFECTS = 10, - ULTRAMECH_DEAD_WAIT_FOR_RESET = 0x40 -}; - extern float ultramech_pre_hit_scale_multiplier_gp __asm__("D_L15_00161B2C") __attribute__((sda)); extern float ultramech_post_hit_scale_multiplier_gp __asm__("D_L15_00161B30") __attribute__((sda)); diff --git a/src/overlays/l16/hero/apply_hero_ground_material_effects.c b/src/overlays/l16/hero/apply_hero_ground_material_effects.c index 0aad4458dd..494a387a55 100644 --- a/src/overlays/l16/hero/apply_hero_ground_material_effects.c +++ b/src/overlays/l16/hero/apply_hero_ground_material_effects.c @@ -19,6 +19,16 @@ /* Per-frame update of the pickup/hit state flags from the state code. */ /* Ported from rac1-decomp (src/overlays/l16_kalebo3/help_00209D98.c: func_L16_00209D98), where it is exact; names translated to the US level program. */ +enum { + GROUND_MATERIAL_WATER = 0, + GROUND_MATERIAL_MAGNET = 2 +}; + +enum { + GROUND_MATERIAL_SINK_TRIGGER = 0xD, + GROUND_MATERIAL_FIXED_WATER_DEPTH = 0xE +}; + extern int coll_sphere(float, void *, int, void *) __asm__("FUN_L00_001f0d60"); extern void exit_hero_vehicle_mode_if_mode_three(void) __asm__("FUN_L00_0020b930"); extern int hero_set_state(int, int) __asm__("FUN_L16_0021e398"); @@ -142,16 +152,6 @@ void apply_hero_ground_material_effects(void) { #include "qcopy.h" #include "rnc/overlay/shared/math/quad.h" -enum { - GROUND_MATERIAL_WATER = 0, - GROUND_MATERIAL_MAGNET = 2 -}; - -enum { - GROUND_MATERIAL_SINK_TRIGGER = 0xD, - GROUND_MATERIAL_FIXED_WATER_DEPTH = 0xE -}; - /* Ported from rac1-decomp (src/overlays/l16_kalebo3/help_00209D98.c: func_L16_0020FEC8), where it is exact; names translated to the US level program. */ extern void FUN_L00_0025f730(void *a, float x); diff --git a/src/overlays/l16/mobys/bolt_thief.c b/src/overlays/l16/mobys/bolt_thief.c index c05a1d2edb..a6a5339012 100644 --- a/src/overlays/l16/mobys/bolt_thief.c +++ b/src/overlays/l16/mobys/bolt_thief.c @@ -37,6 +37,16 @@ #include "rnc/ui/text/font/font_queue_vu_state.h" #include "rnc/rendering/clip_volume.h" +enum { + BOLT_THIEF_INITIALIZE = 0, + BOLT_THIEF_FACE_HERO = 1, + BOLT_THIEF_WAIT_FOR_HERO_TRIGGER = 2, + BOLT_THIEF_SETTLE_AT_PATH_END = 3, + BOLT_THIEF_FOLLOW_PRIMARY_PATH = 4, + BOLT_THIEF_FOLLOW_OTHER_PATH = 5, + BOLT_THIEF_KNOCKBACK = 6 +}; + extern int scale_game_frames(int); /* Update of the crate platform: hit reaction, then its seven states. */ @@ -334,16 +344,6 @@ void bolt_thief_update(L16CrateMoby *moby) { #include "rnc/overlay/l16/mobys/bolt_thief_globals.h" -enum { - BOLT_THIEF_INITIALIZE = 0, - BOLT_THIEF_FACE_HERO = 1, - BOLT_THIEF_WAIT_FOR_HERO_TRIGGER = 2, - BOLT_THIEF_SETTLE_AT_PATH_END = 3, - BOLT_THIEF_FOLLOW_PRIMARY_PATH = 4, - BOLT_THIEF_FOLLOW_OTHER_PATH = 5, - BOLT_THIEF_KNOCKBACK = 6 -}; - extern float bolt_thief_path_speed_gp __asm__("D_L16_00161D90") __attribute__((sda)); extern float D_L16_00161D94_gp __asm__("D_L16_00161D94") __attribute__((sda)); extern float D_L16_00161D98_gp __asm__("D_L16_00161D98") __attribute__((sda)); diff --git a/src/overlays/l16/mobys/chicken_relocator.c b/src/overlays/l16/mobys/chicken_relocator.c index 6726d8eb8c..702464443f 100644 --- a/src/overlays/l16/mobys/chicken_relocator.c +++ b/src/overlays/l16/mobys/chicken_relocator.c @@ -43,6 +43,11 @@ #include "rnc/ui/text/font/font_queue_vu_state.h" #include "rnc/world/collision/ground_probe.h" +enum { + TARGET_REPOSITION_STATE_REQUESTABLE = 1, + TARGET_REPOSITION_STATE_REQUESTED = 7 +}; + extern float D_0015ED6C; #include "rnc/overlay/shared/math/quad.h" @@ -59,11 +64,6 @@ extern void build_spherical_offset(float, float, float, void *) __asm__("FUN_00 #include "rnc/overlay/l16/mobys/chicken_relocator_globals.h" -enum { - TARGET_REPOSITION_STATE_REQUESTABLE = 1, - TARGET_REPOSITION_STATE_REQUESTED = 7 -}; - extern float reposition_effect_velocity_elevation_degrees_gp __asm__("D_L16_001618E8") __attribute__((sda)); extern float reposition_effect_velocity_scale_range_start_gp __asm__("D_L16_001618EC") diff --git a/src/overlays/l16/mobys/chomper.c b/src/overlays/l16/mobys/chomper.c index a0b3d8b1f0..a18891a639 100644 --- a/src/overlays/l16/mobys/chomper.c +++ b/src/overlays/l16/mobys/chomper.c @@ -36,6 +36,15 @@ #include "rnc/overlay/shared/game/unlock_planet.h" #include "rnc/ui/text/font/font_queue_vu_state.h" +enum { + CHOMPER_INITIALIZE = 0, + CHOMPER_WAIT_TO_APPROACH_TARGET = 1, + CHOMPER_APPROACH_TARGET = 4, + CHOMPER_FACE_TARGET = 5, + CHOMPER_RETURN_HOME = 6, + CHOMPER_KNOCKBACK = 8 +}; + extern int scale_game_frames(int); extern float frame_time, D_0015EE70; extern void FUN_L00_00257470(void *, int, int); @@ -236,15 +245,6 @@ typedef struct { #include "rnc/overlay/l16/mobys/chomper_globals.h" -enum { - CHOMPER_INITIALIZE = 0, - CHOMPER_WAIT_TO_APPROACH_TARGET = 1, - CHOMPER_APPROACH_TARGET = 4, - CHOMPER_FACE_TARGET = 5, - CHOMPER_RETURN_HOME = 6, - CHOMPER_KNOCKBACK = 8 -}; - extern float chomper_knockback_horizontal_speed_approach_rate_gp __asm__("D_L16_00161E58") __attribute__((sda)); extern float chomper_knockback_gravity_gp __asm__("D_L16_00161E54") __attribute__((sda)); diff --git a/src/overlays/l16/mobys/test_dummy.c b/src/overlays/l16/mobys/test_dummy.c index e7391da55a..55fead4bc3 100644 --- a/src/overlays/l16/mobys/test_dummy.c +++ b/src/overlays/l16/mobys/test_dummy.c @@ -20,6 +20,21 @@ #include "qcopy.h" +enum { + TEST_DUMMY_STATE_INITIALIZE = 0, + TEST_DUMMY_STATE_IDLE = 1, + TEST_DUMMY_STATE_APPROACH_FIRST_PATH_NODE = 2, + TEST_DUMMY_STATE_APPROACH_THROW_NODE = 3, + TEST_DUMMY_STATE_THROW_AT_TARGET = 4, + TEST_DUMMY_STATE_MOVE_ALONG_PATH = 5, + TEST_DUMMY_STATE_TURN_TO_NEXT_PATH_NODE = 6, + TEST_DUMMY_STATE_APPROACH_SPRAY_NODE = 7, + TEST_DUMMY_STATE_SPRAY_FROM_CHILD = 8, + TEST_DUMMY_STATE_TURN_AND_RESUME_SAVED_STATE = 9, + TEST_DUMMY_STATE_BURST = 10, + TEST_DUMMY_STATE_RESPAWN = 11 +}; + extern char *create_moby(int); extern char *create_moby(int) __asm__("FUN_0020c4f8"); @@ -675,20 +690,6 @@ extern void add_draw_callback(void (*)(void), void *) __asm__("FUN_001f4600"); #include "rnc/overlay/l16/mobys/test_dummy_globals.h" -enum { - TEST_DUMMY_STATE_INITIALIZE = 0, - TEST_DUMMY_STATE_IDLE = 1, - TEST_DUMMY_STATE_APPROACH_FIRST_PATH_NODE = 2, - TEST_DUMMY_STATE_APPROACH_THROW_NODE = 3, - TEST_DUMMY_STATE_THROW_AT_TARGET = 4, - TEST_DUMMY_STATE_MOVE_ALONG_PATH = 5, - TEST_DUMMY_STATE_TURN_TO_NEXT_PATH_NODE = 6, - TEST_DUMMY_STATE_APPROACH_SPRAY_NODE = 7, - TEST_DUMMY_STATE_SPRAY_FROM_CHILD = 8, - TEST_DUMMY_STATE_TURN_AND_RESUME_SAVED_STATE = 9, - TEST_DUMMY_STATE_BURST = 10, - TEST_DUMMY_STATE_RESPAWN = 11 -}; /* spins the level's rotating parts by the current angle and queues the draw callback */ /* Ported from rac1-decomp (src/overlays/l16_kalebo3/vendor_002A50F0.c: func_L16_002D0238), where it is exact; names translated to the US level program. */ diff --git a/src/overlays/l17/mobys/fighter_jet.c b/src/overlays/l17/mobys/fighter_jet.c index 0444c32583..172f34f4bd 100644 --- a/src/overlays/l17/mobys/fighter_jet.c +++ b/src/overlays/l17/mobys/fighter_jet.c @@ -46,6 +46,17 @@ collision restores the class collision or clears it; -1 leaves that one alone. */ /* Ported from rac1-decomp (src/overlays/l17/mobyutil_00254B40.c: func_L17_00254B40), where it is exact; names translated to the US level program. */ +enum { + FIGHTER_JET_STATE_INITIALIZE = 0, + FIGHTER_JET_STATE_WAIT_FOR_BOARDING = 1, + FIGHTER_JET_STATE_BOARDING_FADE = 2, + FIGHTER_JET_STATE_PILOTED_FLIGHT = 4, + FIGHTER_JET_STATE_DISMOUNT = 5, + FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY = 7, + FIGHTER_JET_STATE_VICTORY_EXIT = 8, + FIGHTER_JET_STATE_FADE_THEN_REMOVE = 9 +}; + typedef struct { char pad0[0x10]; int value; @@ -1736,17 +1747,6 @@ extern void FUN_L17_0021e530(int, int); #include "rnc/overlay/l17/mobys/fighter_jet_data/fighter_jet_update.h" -enum { - FIGHTER_JET_STATE_INITIALIZE = 0, - FIGHTER_JET_STATE_WAIT_FOR_BOARDING = 1, - FIGHTER_JET_STATE_BOARDING_FADE = 2, - FIGHTER_JET_STATE_PILOTED_FLIGHT = 4, - FIGHTER_JET_STATE_DISMOUNT = 5, - FIGHTER_JET_STATE_DEATH_RESPAWN_DELAY = 7, - FIGHTER_JET_STATE_VICTORY_EXIT = 8, - FIGHTER_JET_STATE_FADE_THEN_REMOVE = 9 -}; - extern int D_L17_0015F608; extern char *fighter_jet_hp_bar_clut_lookup_base __asm__("D_L17_0015F420"); extern ShipLevelEntry l17_fighter_jet_hp_bar_clut_entries[] __asm__("D_L17_0016DA80"); diff --git a/src/overlays/l18/mobys/camera_transition.c b/src/overlays/l18/mobys/camera_transition.c index cf35ecd05c..5b640a2a81 100644 --- a/src/overlays/l18/mobys/camera_transition.c +++ b/src/overlays/l18/mobys/camera_transition.c @@ -21,6 +21,11 @@ #include "rnc/math/interpolation/advance_accelerated_scalar.h" #include "rnc/overlay/shared/camera/scripted_camera.h" +enum { + CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP = 2, + CAMERA_TRANSITION_STATE_INTERPOLATE_TRANSITION = 3 +}; + extern f32 approach_value(f32 *, f32, f32) __asm__("FUN_00213ed8"); extern int help_request(int, int) __asm__("FUN_L00_00203908"); @@ -222,11 +227,6 @@ void boss_camera_transition_update(struct Moby *moby) { #include "qcopy.h" -enum { - CAMERA_TRANSITION_STATE_PRE_TRANSITION_RAMP_UP = 2, - CAMERA_TRANSITION_STATE_INTERPOLATE_TRANSITION = 3 -}; - extern int scale_game_frames(int); /* Ported from rac1-decomp (src/overlays/l18_veldin2/vendor_002A8400.c: func_L18_002E0E90), where it is exact; names translated to the US level program. */ diff --git a/src/overlays/l18/mobys/drek_boss_electric_ball.c b/src/overlays/l18/mobys/drek_boss_electric_ball.c index 61833860c8..747e62b2fd 100644 --- a/src/overlays/l18/mobys/drek_boss_electric_ball.c +++ b/src/overlays/l18/mobys/drek_boss_electric_ball.c @@ -21,6 +21,11 @@ #include "rnc/rendering/view/build_look_at_matrix.h" #include "rnc/world/collision/ground_probe.h" +enum { + STATE_TIMED_REMOVAL_WAIT = 0, + STATE_TRAVEL_TO_TARGET = 1 +}; + extern void add_draw_callback(void (*)(void), void *) __asm__("FUN_001f4600"); #include "qcopy.h" @@ -700,11 +705,6 @@ extern s32 D_L18_00162054_gp __asm__("D_L18_00162054") __attribute__((sda)); #include "rnc/overlay/l18/mobys/drek_boss_electric_ball_data/update_electric_bolt_geometry_and_particles.h" -enum { - STATE_TIMED_REMOVAL_WAIT = 0, - STATE_TRAVEL_TO_TARGET = 1 -}; - extern float primary_bolt_random_step_blend_weight_gp __asm__("D_L18_0016208C") __attribute__((sda)); extern short D_L18_001620B8[] MACRO_ADDR; diff --git a/src/overlays/l18/mobys/falling_moby_group.c b/src/overlays/l18/mobys/falling_moby_group.c index a88e8dfa76..bbce54df35 100644 --- a/src/overlays/l18/mobys/falling_moby_group.c +++ b/src/overlays/l18/mobys/falling_moby_group.c @@ -35,6 +35,16 @@ #include "rnc/math/random.h" #include "rnc/overlay/l18/mobys.h" +enum { + MOBY_INITIALIZE = 0, + MOBY_APPROACH_TARGET_TRANSFORM = 2, + MOBY_FALL_AND_REMOVE = 4 +}; + +enum { + FALLING_MOBY_GROUP_AWAIT_ACTIVATION = 1 +}; + extern void mark_moby_for_removal(void *) __asm__("FUN_0020c828"); extern short *D_L18_001AC240[]; @@ -243,16 +253,6 @@ extern void mark_block_entries_within_transform_xy_bounds(int, int) __asm__("FUN #include "rnc/overlay/l18/mobys/falling_moby_group.h" -enum { - MOBY_INITIALIZE = 0, - MOBY_APPROACH_TARGET_TRANSFORM = 2, - MOBY_FALL_AND_REMOVE = 4 -}; - -enum { - FALLING_MOBY_GROUP_AWAIT_ACTIVATION = 1 -}; - void activate_drek_boss_class_0565_moby(struct Moby *moby) __asm__("FUN_L18_002f1c38"); void activate_drek_boss_class_0565_moby(struct Moby *moby) { diff --git a/src/overlays/l18/mobys/floating_platform.c b/src/overlays/l18/mobys/floating_platform.c index c706a5c364..e2ab9d1c42 100644 --- a/src/overlays/l18/mobys/floating_platform.c +++ b/src/overlays/l18/mobys/floating_platform.c @@ -20,6 +20,15 @@ #include "rnc/overlay/l18/hero.h" #include "rnc/overlay/shared/math/random/random_int_between.h" +enum { + STATE_INITIALIZE = 0, + STATE_WAIT_FOR_TILT_REQUEST = 1, + STATE_WAIT_FOR_SINK_REQUEST = 2, + STATE_TILT_DELAY = 3, + STATE_WAIT_FOR_SINK_TRIGGER = 4, + STATE_SINKING = 5 +}; + void update_floating_platform_tilt_and_bob(struct Moby *moby) __asm__("FUN_L18_002d8710"); #include "qcopy.h" @@ -37,15 +46,6 @@ extern float floating_platform_sink_trigger_distance_gp __asm__("D_L18_00161A5C" #include "rnc/overlay/l18/mobys/floating_platform_data/floating_platform_update.h" -enum { - STATE_INITIALIZE = 0, - STATE_WAIT_FOR_TILT_REQUEST = 1, - STATE_WAIT_FOR_SINK_REQUEST = 2, - STATE_TILT_DELAY = 3, - STATE_WAIT_FOR_SINK_TRIGGER = 4, - STATE_SINKING = 5 -}; - extern int D_L18_001623A8 __attribute__((sda)); void spawn_floating_platform_sparks(struct Moby *moby) __asm__("FUN_L18_002d88b8"); diff --git a/src/overlays/l18/mobys/gadgebot.c b/src/overlays/l18/mobys/gadgebot.c index 2587e38508..3cfba0d785 100644 --- a/src/overlays/l18/mobys/gadgebot.c +++ b/src/overlays/l18/mobys/gadgebot.c @@ -19,6 +19,19 @@ #include "rnc/math_consts.h" #include "rnc/overlay/shared/world/level_labels.h" +enum { + GADGEBOT_INITIALIZE = 0, + GADGEBOT_LAUNCH_FLIGHT = 1, + GADGEBOT_TARGET_HERO = 2, + GADGEBOT_WAIT_TO_APPROACH = 2, + GADGEBOT_APPROACH_TARGET = 3, + GADGEBOT_FACE_TARGET = 4, + GADGEBOT_DEATH_FALL = 5, + GADGEBOT_EXPLODE = 6, + GADGEBOT_SUCK_CANNON_SUCTION = 7, + GADGEBOT_IDLE = 8 +}; + extern int D_L18_0015F5C4; extern unsigned char *D_L18_0015FFD8; extern s32 random_integer_below(s32) __asm__("FUN_00213260"); @@ -287,19 +300,6 @@ extern float gadgebot_glow_state_4_or_5_phase_speed_degrees_per_second_gp __asm_ #include "rnc/overlay/l18/mobys/gadgebot_data/update_gadgebot_damage_target_and_glow.h" -enum { - GADGEBOT_INITIALIZE = 0, - GADGEBOT_LAUNCH_FLIGHT = 1, - GADGEBOT_TARGET_HERO = 2, - GADGEBOT_WAIT_TO_APPROACH = 2, - GADGEBOT_APPROACH_TARGET = 3, - GADGEBOT_FACE_TARGET = 4, - GADGEBOT_DEATH_FALL = 5, - GADGEBOT_EXPLODE = 6, - GADGEBOT_SUCK_CANNON_SUCTION = 7, - GADGEBOT_IDLE = 8 -}; - /* Sentry update: spins and tints the moby, takes hits (knockback, then a fall), and follows its path toward the hero. */ void update_gadgebot_damage_target_and_glow(struct Moby *moby) { SentryVars_c100 *sentry_vars = (SentryVars_c100 *)moby->pvars; diff --git a/src/overlays/l18/mobys/mine.c b/src/overlays/l18/mobys/mine.c index b13f100423..b9b045524e 100644 --- a/src/overlays/l18/mobys/mine.c +++ b/src/overlays/l18/mobys/mine.c @@ -18,6 +18,18 @@ #include "qcopy.h" +enum { + STATE_INITIALIZE = 0, + STATE_BALLISTIC_FLIGHT = 1, + STATE_POST_FLIGHT_SETTLING = 2, + STATE_APPROACH_NEARBY_TARGET = 3, + STATE_WAIT_TO_RESUME_APPROACH = 4 +}; + +enum { + STATE_INACTIVE = 5 +}; + extern int scale_game_frames(int); /* Moby update: hovers, drifts toward the player and plays its animations by state. */ @@ -143,18 +155,6 @@ void moby_568_update(struct Moby *moby) { #include "sda.h" -enum { - STATE_INITIALIZE = 0, - STATE_BALLISTIC_FLIGHT = 1, - STATE_POST_FLIGHT_SETTLING = 2, - STATE_APPROACH_NEARBY_TARGET = 3, - STATE_WAIT_TO_RESUME_APPROACH = 4 -}; - -enum { - STATE_INACTIVE = 5 -}; - extern void allocate_voice_for_target_entry(int, int, int) __asm__("FUN_0022da68"); /* Ported from rac1-decomp (src/overlays/l18_veldin2/vendor_002A8400.c: func_L18_002D70E8), where it is exact; names translated to the US level program. */ diff --git a/src/overlays/shared/camera/grindrail_camera.c b/src/overlays/shared/camera/grindrail_camera.c index 2a52f08a30..52ad041c74 100644 --- a/src/overlays/shared/camera/grindrail_camera.c +++ b/src/overlays/shared/camera/grindrail_camera.c @@ -11,13 +11,13 @@ #include "rnc/camera/camera_spring.h" #include "sda.h" +/* Camera blocks FUN_L01_00314e98 resets (camera + 0x70 and its preset row in l01_camera_preset_rows) */ enum { CAMERA_PRESET_KIND_RAIL_SEGMENT_SYNC = 0, CAMERA_PRESET_KIND_MAPPED_PATHS = 2, CAMERA_PRESET_KIND_GRINDRAIL_PATH = 3 }; -/* Camera blocks FUN_L01_00314e98 resets (camera + 0x70 and its preset row in l01_camera_preset_rows) */ typedef struct { Vec4 pos; /* 0x00 */ u8 pad10[0x30]; diff --git a/src/overlays/shared/camera/hoverboard_camera.c b/src/overlays/shared/camera/hoverboard_camera.c index e913ab8bd8..e3a42e64c1 100644 --- a/src/overlays/shared/camera/hoverboard_camera.c +++ b/src/overlays/shared/camera/hoverboard_camera.c @@ -16,14 +16,14 @@ #include "rnc/overlay/shared/camera/init_camera_system.h" #include "rnc/camera/camera_spring.h" +/* Sets up a moby's vector from the level table and clamps its height for the current state. */ +/* Ported from rac1-decomp (src/overlays/shared/vendor_002CF2C0.c: func_L05_0032A868), where it is exact; names translated to the US level program. */ + enum { CAMERA_ORBIT_MODE_FOLLOW = 0, CAMERA_ORBIT_MODE_ORBITING = 1 }; -/* Sets up a moby's vector from the level table and clamps its height for the current state. */ -/* Ported from rac1-decomp (src/overlays/shared/vendor_002CF2C0.c: func_L05_0032A868), where it is exact; names translated to the US level program. */ - void update_hero_follow_camera_focus(char *moby) __asm__("FUN_L05_00329358"); void update_hero_follow_camera_focus(char *moby) { diff --git a/src/overlays/shared/enemies/blarg_space_commando.c b/src/overlays/shared/enemies/blarg_space_commando.c index e9458e85e8..c096d6b189 100644 --- a/src/overlays/shared/enemies/blarg_space_commando.c +++ b/src/overlays/shared/enemies/blarg_space_commando.c @@ -17,6 +17,22 @@ #include "rnc/mobys/animation/blend_moby_animation.h" /* Movement controller block at vars + 0xC0 (FUN_L01_0026d930 init, FUN_L00_00258b50 step). */ +enum { + BLARG_COMMANDO_STATE_INITIALIZE = 0, + BLARG_COMMANDO_STATE_SELECT_ACTION = 1, + BLARG_COMMANDO_STATE_RANGED_ATTACK_WINDUP = 2, + BLARG_COMMANDO_STATE_RANGED_ATTACK_RECOVERY = 3, + BLARG_COMMANDO_STATE_RANGED_ATTACK_COOLDOWN = 4, + BLARG_COMMANDO_STATE_MELEE_ATTACK = 5, + BLARG_COMMANDO_STATE_MELEE_RECOVERY = 6, + BLARG_COMMANDO_STATE_CHASE_TARGET = 11, + BLARG_COMMANDO_STATE_CHASE_MELEE_ATTACK = 12, + BLARG_COMMANDO_STATE_RETURN_HOME = 13, + BLARG_COMMANDO_STATE_APPROACH_ROUTE_DESTINATION = 14, + BLARG_COMMANDO_STATE_KNOCKBACK = 15, + BLARG_COMMANDO_STATE_DEATH_KNOCKBACK = 16 +}; + typedef struct { s32 unk0; f32 unk4; @@ -540,22 +556,6 @@ extern char *FUN_L06_00300c60_c(int unused, char *pa, char *pb) __asm__("FUN_L06 #include "rnc/data_labels.h" -enum { - BLARG_COMMANDO_STATE_INITIALIZE = 0, - BLARG_COMMANDO_STATE_SELECT_ACTION = 1, - BLARG_COMMANDO_STATE_RANGED_ATTACK_WINDUP = 2, - BLARG_COMMANDO_STATE_RANGED_ATTACK_RECOVERY = 3, - BLARG_COMMANDO_STATE_RANGED_ATTACK_COOLDOWN = 4, - BLARG_COMMANDO_STATE_MELEE_ATTACK = 5, - BLARG_COMMANDO_STATE_MELEE_RECOVERY = 6, - BLARG_COMMANDO_STATE_CHASE_TARGET = 11, - BLARG_COMMANDO_STATE_CHASE_MELEE_ATTACK = 12, - BLARG_COMMANDO_STATE_RETURN_HOME = 13, - BLARG_COMMANDO_STATE_APPROACH_ROUTE_DESTINATION = 14, - BLARG_COMMANDO_STATE_KNOCKBACK = 15, - BLARG_COMMANDO_STATE_DEATH_KNOCKBACK = 16 -}; - extern f32 D_0015ED6C; extern float FUN_L04_001f1978(float); extern float randf_sym(float lo, float hi) __asm__("FUN_L00_00257c48"); diff --git a/src/overlays/shared/enemies/bolt_thief_mine.c b/src/overlays/shared/enemies/bolt_thief_mine.c index 1a31476932..a070f9d659 100644 --- a/src/overlays/shared/enemies/bolt_thief_mine.c +++ b/src/overlays/shared/enemies/bolt_thief_mine.c @@ -13,6 +13,12 @@ #include "rnc/mobys/moby_spawn.h" #include "qcopy.h" +enum { + FLOAT_MINE_INITIALIZE = 0, + FLOAT_MINE_ACTIVE = 1, + FLOAT_MINE_WAIT_OFFSCREEN_RESPAWN = 2 +}; + typedef struct { struct Moby *link; float rest_z; @@ -41,12 +47,6 @@ extern char *floating_mine_respawn_address_limit __asm__("D_L14_0015FFDC"); #include "rnc/overlay/shared/enemies/bolt_thief_mine_data/bolt_thief_mine_update.h" -enum { - FLOAT_MINE_INITIALIZE = 0, - FLOAT_MINE_ACTIVE = 1, - FLOAT_MINE_WAIT_OFFSCREEN_RESPAWN = 2 -}; - extern float probe_ground_height(float, void *, int) __asm__("FUN_00213508"); extern int resolve_moby_hit_response( struct Moby *, MobyHit *, HitInfo *, int, int *, int, int, int) __asm__("FUN_00213928"); diff --git a/src/overlays/shared/enemies/bomb_spawner_bomb.c b/src/overlays/shared/enemies/bomb_spawner_bomb.c index 46c67787af..1009325561 100644 --- a/src/overlays/shared/enemies/bomb_spawner_bomb.c +++ b/src/overlays/shared/enemies/bomb_spawner_bomb.c @@ -18,12 +18,12 @@ #include "rnc/mobys/moby_spawn.h" #include "rnc/overlay/shared/rendering/effects/spawn_explosion.h" +/* Class header fields the spawner copies into a fresh moby. */ enum { MOBY_STATE_REMOVAL_BELOW_INSTANCE_END = 0xFD, MOBY_STATE_REMOVAL_AT_OR_ABOVE_INSTANCE_END = 0xFE }; -/* Class header fields the spawner copies into a fresh moby. */ typedef struct { u8 pad0[0xF]; u8 always_draw; /* 0x0F */ diff --git a/src/overlays/shared/enemies/ground_melee_enemy.c b/src/overlays/shared/enemies/ground_melee_enemy.c index 16a39101ab..fd68ffa342 100644 --- a/src/overlays/shared/enemies/ground_melee_enemy.c +++ b/src/overlays/shared/enemies/ground_melee_enemy.c @@ -21,6 +21,9 @@ #include "rnc/overlay/shared/mobys/count_active_moby_group_members.h" #include "rnc/sdk/libc/stdlib.h" +/* Ground enemy update: damage reaction, leash and wake checks, then its chase / attack / return state machine. */ +/* Ported from rac1-decomp (src/overlays/shared/vendor_002C6B30.c: func_L09_002E39E0), where it is exact; names translated to the US level program. */ + enum { GROUND_ENEMY_STATE_INITIALIZE = 0, GROUND_ENEMY_STATE_IDLE = 1, @@ -36,9 +39,6 @@ enum { GROUND_ENEMY_STATE_FATAL_KNOCKBACK = 99 }; -/* Ground enemy update: damage reaction, leash and wake checks, then its chase / attack / return state machine. */ -/* Ported from rac1-decomp (src/overlays/shared/vendor_002C6B30.c: func_L09_002E39E0), where it is exact; names translated to the US level program. */ - typedef struct Moby Moby; typedef struct Hero Hero; diff --git a/src/overlays/shared/enemies/paratrooper_fire_bolt.c b/src/overlays/shared/enemies/paratrooper_fire_bolt.c index af59de05ef..cb3378fb6e 100644 --- a/src/overlays/shared/enemies/paratrooper_fire_bolt.c +++ b/src/overlays/shared/enemies/paratrooper_fire_bolt.c @@ -12,13 +12,13 @@ #include "rnc/overlay/shared/math/vu0_vector_ops.h" #include "rnc/overlay/shared/mobys/evaluate_moby_animation_pose.h" +/* Ported from rac1-decomp (src/overlays/shared/vendor_002D3DF8.c: func_L08_00308650), where it is exact; names translated to the US level program. */ + enum { FIRE_BOLT_STATE_FLYING = 1, FIRE_BOLT_STATE_BURST_AND_REMOVE = 2 }; -/* Ported from rac1-decomp (src/overlays/shared/vendor_002D3DF8.c: func_L08_00308650), where it is exact; names translated to the US level program. */ - extern char *create_moby(int); char *spawn_paratrooper_projectile(char *initial_velocity, diff --git a/src/overlays/shared/enemies/plasmabot.c b/src/overlays/shared/enemies/plasmabot.c index 51090fac48..8ac217a5d3 100644 --- a/src/overlays/shared/enemies/plasmabot.c +++ b/src/overlays/shared/enemies/plasmabot.c @@ -33,6 +33,27 @@ /* Ported from rac1-decomp (src/overlays/shared/vendor_002B2A28.c: func_L14_002B44B8), where it is exact; names translated to the US level program. */ +enum { + PLASMABOT_INITIALIZE = 0, + PLASMABOT_WAIT_TO_START_PATH_TRAVERSAL = 1, + PLASMABOT_START_PATH_TRAVERSAL = 2, + PLASMABOT_FOLLOW_PATH_FORWARD = 3, + PLASMABOT_AIM_AT_TARGET = 4, + PLASMABOT_WAIT_ANIMATION_BEFORE_AIM_SWEEP = 5, + PLASMABOT_SWEEP_AIM_AND_TRACE_LINE = 6, + PLASMABOT_WAIT_ANIMATION_BEFORE_AIM = 7, + PLASMABOT_FOLLOW_PATH_BACKWARD = 8, + PLASMABOT_RETURN_TO_PATH_START = 9, + PLASMABOT_WAIT_ANIMATION_BEFORE_RESUMING_AIM = 10, + PLASMABOT_FALL_THEN_EXPLODE = 11, + PLASMABOT_SPAWN_DEBRIS_AND_REMOVE = 12, + PLASMABOT_FACE_TARGET_AND_WAIT = 13 +}; + +enum { + HIT_KIND_SKIP_DAMAGE_AND_REACTION = 1 +}; + typedef struct PlasmabotVars { u8 pad0[0x20]; f32 health; @@ -816,27 +837,6 @@ extern u8 D_L14_0015F580[] MACRO_ADDR; #include "rnc/overlay/shared/enemies/plasmabot_data/update_plasmabot_visual_effects.h" -enum { - PLASMABOT_INITIALIZE = 0, - PLASMABOT_WAIT_TO_START_PATH_TRAVERSAL = 1, - PLASMABOT_START_PATH_TRAVERSAL = 2, - PLASMABOT_FOLLOW_PATH_FORWARD = 3, - PLASMABOT_AIM_AT_TARGET = 4, - PLASMABOT_WAIT_ANIMATION_BEFORE_AIM_SWEEP = 5, - PLASMABOT_SWEEP_AIM_AND_TRACE_LINE = 6, - PLASMABOT_WAIT_ANIMATION_BEFORE_AIM = 7, - PLASMABOT_FOLLOW_PATH_BACKWARD = 8, - PLASMABOT_RETURN_TO_PATH_START = 9, - PLASMABOT_WAIT_ANIMATION_BEFORE_RESUMING_AIM = 10, - PLASMABOT_FALL_THEN_EXPLODE = 11, - PLASMABOT_SPAWN_DEBRIS_AND_REMOVE = 12, - PLASMABOT_FACE_TARGET_AND_WAIT = 13 -}; - -enum { - HIT_KIND_SKIP_DAMAGE_AND_REACTION = 1 -}; - extern void FUN_L14_002b3a20_c(struct Moby *) __asm__("FUN_L14_002b3a20"); extern void FUN_L14_002b2928_u(struct Moby *) __asm__("FUN_L14_002b2928"); diff --git a/src/overlays/shared/enemies/seeker.c b/src/overlays/shared/enemies/seeker.c index 034f6c373a..2685ff7126 100644 --- a/src/overlays/shared/enemies/seeker.c +++ b/src/overlays/shared/enemies/seeker.c @@ -17,6 +17,17 @@ #include "rnc/mobys/resolve_moby_hit_response.h" /* Per-instance variables of the oClass 52 moby (moby->pvars). */ +enum { + SEEKER_STATE_INITIALIZE = 0, + SEEKER_STATE_IDLE_HOVER = 1, + SEEKER_STATE_CHASE = 2, + SEEKER_STATE_CHASE_ANIMATION_WAIT = 3, + SEEKER_STATE_TIMED_CHASE = 4, + SEEKER_STATE_HURT_KNOCKBACK = 5, + SEEKER_STATE_FATAL_KNOCKBACK = 6, + SEEKER_STATE_EXPLODE = 7 +}; + typedef struct { u8 pad0[0x20]; f32 unk20; @@ -388,17 +399,6 @@ extern float D_0015ED70; #include "rnc/overlay/shared/enemies/seeker_data/update_seeker_damage_and_target.h" -enum { - SEEKER_STATE_INITIALIZE = 0, - SEEKER_STATE_IDLE_HOVER = 1, - SEEKER_STATE_CHASE = 2, - SEEKER_STATE_CHASE_ANIMATION_WAIT = 3, - SEEKER_STATE_TIMED_CHASE = 4, - SEEKER_STATE_HURT_KNOCKBACK = 5, - SEEKER_STATE_FATAL_KNOCKBACK = 6, - SEEKER_STATE_EXPLODE = 7 -}; - extern float D_L09_0016140C __attribute__((sda)); extern int scale_time() __asm__("FUN_001f96b0"); extern void FUN_L00_00257470_c(void *, int, int) __asm__("FUN_L00_00257470"); diff --git a/src/overlays/shared/hero/hero_frame_update.c b/src/overlays/shared/hero/hero_frame_update.c index e05eed68cd..3202a8bcb2 100644 --- a/src/overlays/shared/hero/hero_frame_update.c +++ b/src/overlays/shared/hero/hero_frame_update.c @@ -25,6 +25,19 @@ /* Looks up the value of the current help record, or 0/0x54 in the special cases. */ /* Ported from rac1-decomp (src/overlays/shared/help_002274A8.c: func_L01_002274A8), where it is exact; names translated to the US level program. */ +enum { + GROUND_MATERIAL_WATER = 0, + GROUND_MATERIAL_MAGNETIC = 2 +}; + +enum { + GROUND_MATERIAL_SINK_TRIGGER = 0xD +}; + +enum { + CUTSCENE_MODE_INACTIVE = 0 +}; + extern int hero_slot_item_id(int) __asm__("FUN_L00_0020d498"); extern unsigned char D_0013E533[]; @@ -1423,19 +1436,6 @@ s32 resolve_hero_position_with_collision_queries(s32 mode) { #include "rnc/sdk/eetypes.h" #include "rnc/input/pad_state.h" -enum { - GROUND_MATERIAL_WATER = 0, - GROUND_MATERIAL_MAGNETIC = 2 -}; - -enum { - GROUND_MATERIAL_SINK_TRIGGER = 0xD -}; - -enum { - CUTSCENE_MODE_INACTIVE = 0 -}; - typedef struct { s32 w0; u8 pad4[0x70 - 4]; diff --git a/src/overlays/shared/hero/hero_switch_item.c b/src/overlays/shared/hero/hero_switch_item.c index aca1c39648..d8b15692db 100644 --- a/src/overlays/shared/hero/hero_switch_item.c +++ b/src/overlays/shared/hero/hero_switch_item.c @@ -32,6 +32,11 @@ #include "rnc/overlay/shared/mobys/evaluate_moby_animation_pose.h" #include "rnc/world/collision/collision_hit_material.h" +enum { + HERO_ITEM_SLOT_STATE_READY = 2, + HERO_ITEM_SLOT_STATE_REMOVING = 3 +}; + extern CollisionHit coll_hit __asm__("D_L00_00173E40") NOT_SDA; /* line query from -> to; fills the collision hit record, nonzero on a hit */ extern int @@ -4162,11 +4167,6 @@ void air_accel(f32 step) { #include "rnc/math/fast_math.h" -enum { - HERO_ITEM_SLOT_STATE_READY = 2, - HERO_ITEM_SLOT_STATE_REMOVING = 3 -}; - extern int nearest_rail_point() __asm__("FUN_L00_0020cd08"); extern char hero_pos[] __asm__("D_0013F3D0"); diff --git a/src/overlays/shared/pickups/crate.c b/src/overlays/shared/pickups/crate.c index b81d5aa0ee..46302e4cd7 100644 --- a/src/overlays/shared/pickups/crate.c +++ b/src/overlays/shared/pickups/crate.c @@ -22,6 +22,7 @@ #include "rnc/overlay/shared/camera/level_camera.h" #include "rnc/rendering/debug/debug_menu.h" +/* Class header view: pclass + 0xE and + 0x10. */ enum { CRATE_STATE_INITIALIZE = 0, CRATE_STATE_PROCESS_HITS = 1, @@ -32,7 +33,6 @@ enum { CRATE_STATE_WAIT_RESPAWN = 6 }; -/* Class header view: pclass + 0xE and + 0x10. */ typedef struct { u8 pad00[0xE]; u8 unkE; diff --git a/src/overlays/shared/rendering/debug/update_debug_menu.c b/src/overlays/shared/rendering/debug/update_debug_menu.c index f2b955b9b7..675240c817 100644 --- a/src/overlays/shared/rendering/debug/update_debug_menu.c +++ b/src/overlays/shared/rendering/debug/update_debug_menu.c @@ -20,6 +20,13 @@ #include "rnc/sdk/storage/fileio.h" #include "rnc/sdk/storage/fileio/sceopen.h" +enum { + DEBUG_CONTROL_MODE_ENABLE_LOW_FOUR_UPDATE_FLAGS = 0, + DEBUG_CONTROL_MODE_CLEAR_UPDATE_FLAGS = 1, + DEBUG_CONTROL_MODE_CAPTURE_HERO_CAMERA_OFFSET = 2, + DEBUG_CONTROL_MODE_ENABLE_SECOND_AND_THIRD_UPDATE_FLAGS = 3 +}; + typedef struct { s32 a, b, c, d; } E001f36f8; @@ -454,13 +461,6 @@ extern u8 D_L00_0016CA40[]; #define level_view_context (*(LevelViewContext *)D_L00_0016CA40) #include "rnc/overlay/shared/hero/item_defs.h" -enum { - DEBUG_CONTROL_MODE_ENABLE_LOW_FOUR_UPDATE_FLAGS = 0, - DEBUG_CONTROL_MODE_CLEAR_UPDATE_FLAGS = 1, - DEBUG_CONTROL_MODE_CAPTURE_HERO_CAMERA_OFFSET = 2, - DEBUG_CONTROL_MODE_ENABLE_SECOND_AND_THIRD_UPDATE_FLAGS = 3 -}; - /* 13 item ids, declared as 8 bytes: the most gas reaches through $gp, as retail does. */ extern u8 debug_menu_item_ids[8] __asm__("D_L00_0015EFD0") __attribute__((sda)); /* Declared as 1 byte so the add_sample path forms its address through $gp, as retail does. */ diff --git a/src/overlays/shared/ui/menus/initialize_pause_menu.c b/src/overlays/shared/ui/menus/initialize_pause_menu.c index dbbc120861..49bb1ad501 100644 --- a/src/overlays/shared/ui/menus/initialize_pause_menu.c +++ b/src/overlays/shared/ui/menus/initialize_pause_menu.c @@ -42,6 +42,23 @@ #include "rnc/ui/menus/item_preview/create_menu_preview_moby.h" #include "rnc/ui/menus/stream_buffers/initialize_menu_stream_buffers.h" +enum { + PAUSE_MENU_PENDING_STATE_CLEARED = 0, + PAUSE_MENU_STATE_EXIT_GUARDED = 0x22 +}; + +enum { + SCENE_STATE_DEFAULT = 2 +}; + +enum { + PAUSE_MENU_STATE_PAGE_TRANSITION = 1, + PAUSE_MENU_STATE_LEVEL_TRANSITION_ENTRY = 0xE, + PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION = 0x14, + PAUSE_MENU_STATE_EXIT_GUARDED_ENTRY = 0x21, + PAUSE_MENU_STATE_PRESERVE_STATE_ENTRY = 0x23 +}; + typedef unsigned int u128d __attribute__((mode(TI), aligned(16))); typedef union { @@ -183,23 +200,6 @@ extern int D_L00_00173E00[]; #include "rnc/overlay/shared/camera/level_camera.h" -enum { - PAUSE_MENU_PENDING_STATE_CLEARED = 0, - PAUSE_MENU_STATE_EXIT_GUARDED = 0x22 -}; - -enum { - SCENE_STATE_DEFAULT = 2 -}; - -enum { - PAUSE_MENU_STATE_PAGE_TRANSITION = 1, - PAUSE_MENU_STATE_LEVEL_TRANSITION_ENTRY = 0xE, - PAUSE_MENU_STATE_RESTORE_GAMEPLAY_AND_DISPATCH_ACTION = 0x14, - PAUSE_MENU_STATE_EXIT_GUARDED_ENTRY = 0x21, - PAUSE_MENU_STATE_PRESERVE_STATE_ENTRY = 0x23 -}; - extern s32 frame_size __asm__("D_0013E504") NOT_SDA; extern void reset_active_camera_position_and_basis(void) __asm__("FUN_00218d10"); extern s32 sce_gs_sync_v(s32) __asm__("FUN_00122298"); diff --git a/src/overlays/shared/vendor/vendor_menu.c b/src/overlays/shared/vendor/vendor_menu.c index e284d8720e..1c02e303bd 100644 --- a/src/overlays/shared/vendor/vendor_menu.c +++ b/src/overlays/shared/vendor/vendor_menu.c @@ -48,6 +48,20 @@ #include "rnc/overlay/shared/camera/level_camera.h" /* Clears D_L00_0015F424..0015F434, D_L00_0017E504[0] and D_L00_0015F2F0/2F4. */ +enum { + VENDOR_MENU_MODE_EXISTING_VENDOR = 0, + VENDOR_MENU_OPENING = 0, + VENDOR_PURCHASE_INACTIVE = 0, + VENDOR_MENU_MODE_SPAWNED_VENDOR = 1, + VENDOR_MENU_OPEN = 1, + VENDOR_PURCHASE_INITIALIZE = 1, + VENDOR_MENU_CLOSING = 2, + VENDOR_PURCHASE_AWAIT_INPUT = 2, + VENDOR_MENU_EXIT_CUTSCENE = 3, + VENDOR_PURCHASE_WAIT_DECISION_ANIMATION = 3, + VENDOR_PURCHASE_FINALIZE = 4 +}; + void reset_frame_counters(void) __asm__("FUN_L00_00297e30"); void update_game_frame_and_idle_counters(void) __asm__("FUN_L00_00297e70"); @@ -859,20 +873,6 @@ extern u8 vendor_part_update_label[] __asm__("D_L00_00161148"); #include "rnc/overlay/shared/vendor/vendor_menu_data/update_vendor_purchase_2.h" #include "rnc/overlay/shared/vendor/vendor_menu_data/update_vendor_purchase.h" -enum { - VENDOR_MENU_MODE_EXISTING_VENDOR = 0, - VENDOR_MENU_OPENING = 0, - VENDOR_PURCHASE_INACTIVE = 0, - VENDOR_MENU_MODE_SPAWNED_VENDOR = 1, - VENDOR_MENU_OPEN = 1, - VENDOR_PURCHASE_INITIALIZE = 1, - VENDOR_MENU_CLOSING = 2, - VENDOR_PURCHASE_AWAIT_INPUT = 2, - VENDOR_MENU_EXIT_CUTSCENE = 3, - VENDOR_PURCHASE_WAIT_DECISION_ANIMATION = 3, - VENDOR_PURCHASE_FINALIZE = 4 -}; - extern f32 D_L00_00161E24; extern s32 D_L00_00161E38; extern Vec4 D_L00_00165F80[3]; diff --git a/src/overlays/shared/weapons/glove_of_doom_bomb.c b/src/overlays/shared/weapons/glove_of_doom_bomb.c index 7f3e94303c..3d26884163 100644 --- a/src/overlays/shared/weapons/glove_of_doom_bomb.c +++ b/src/overlays/shared/weapons/glove_of_doom_bomb.c @@ -15,6 +15,7 @@ #include "rnc/overlay/shared/rendering/effects/update_three_phase_effect_particle.h" #include "rnc/overlay/shared/weapons.h" +/* Vars of a thrown moby, as ThrowVars in trespasser.c without its first 0x10 bytes. */ enum { DOOM_LANDING_MODE_REQUIRE_LINKED_MOBY = 0, DOOM_LANDING_MODE_SKIP_LINKED_MOBY_DRAW_CALLBACK = 2 @@ -29,7 +30,6 @@ enum { THROWN_MOBY_STATE_RESET_TO_INITIALIZE = 5 }; -/* Vars of a thrown moby, as ThrowVars in trespasser.c without its first 0x10 bytes. */ typedef struct { Vec4 vel; /* 0x00: velocity per step */ Vec4 landing; /* 0x10: predicted landing point */ diff --git a/src/overlays/shared/weapons/pyrocitor.c b/src/overlays/shared/weapons/pyrocitor.c index ac9c0711cc..6019a58bb8 100644 --- a/src/overlays/shared/weapons/pyrocitor.c +++ b/src/overlays/shared/weapons/pyrocitor.c @@ -18,6 +18,7 @@ #include "rnc/overlay/shared/camera/level_camera.h" #include "rnc/overlay/shared/weapons/devastator.h" +/* Ported from rac1-decomp (nonmatching/shared/func_L00_002B8AE8.c: func_L00_002B8AE8). */ enum { PYROCITOR_STATE_INITIALIZE = 0, PYROCITOR_STATE_WAIT_FOR_READY = 1, @@ -26,7 +27,6 @@ enum { PYROCITOR_STATE_CLEANUP = 4 }; -/* Ported from rac1-decomp (nonmatching/shared/func_L00_002B8AE8.c: func_L00_002B8AE8). */ typedef struct PyrocitorVars { struct Moby *other; char pad4[0x40]; From d663255939f7e785c2b84da1079dac31fcd6ec41 Mon Sep 17 00:00:00 2001 From: Ben Perry <7693062+ben-perry@users.noreply.github.com> Date: Sun, 1 Nov 2026 18:38:27 +0000 Subject: [PATCH 1502/1502] decomp: format controller input rebase resolutions --- src/overlays/l17/mobys/fighter_jet.c | 52 +++++++++---------- src/overlays/shared/props/trespasser_pad.c | 2 +- .../rendering/debug/update_debug_menu.c | 6 ++- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/overlays/l17/mobys/fighter_jet.c b/src/overlays/l17/mobys/fighter_jet.c index 172f34f4bd..7c16fc8de5 100644 --- a/src/overlays/l17/mobys/fighter_jet.c +++ b/src/overlays/l17/mobys/fighter_jet.c @@ -1205,33 +1205,33 @@ void update_fighter_jet_flight(FighterJetMoby *ship_moby, FighterJetVars *ship_vars) __asm__("FUN_L17_002ec360"); void update_fighter_jet_flight(FighterJetMoby *ship_moby, FighterJetVars *ship_vars) { - sceVu0FVECTOR pre_movement_ship_position; - sceVu0FVECTOR death_explosion_velocity; - UQ_c4 movement_delta; - sceVu0FVECTOR side; - UQ_c4 up; - sceVu0FVECTOR camera_rotation; - sceVu0FVECTOR target; - sceVu0FVECTOR target_record_sum_or_camera_local_offset; - float horizontal_steering_input; - float vertical_steering_input; - float ka; - float kb; - float lenA; - float lenB; - float distance_to_default_target; - float target_height_distance, target_height_distance_for_moby_pitch; - float x, y; - float half_fov, tn; - float ratio; - float collision_adjusted_pitch; - float k; + sceVu0FVECTOR pre_movement_ship_position; + sceVu0FVECTOR death_explosion_velocity; + UQ_c4 movement_delta; + sceVu0FVECTOR side; + UQ_c4 up; + sceVu0FVECTOR camera_rotation; + sceVu0FVECTOR target; + sceVu0FVECTOR target_record_sum_or_camera_local_offset; + float horizontal_steering_input; + float vertical_steering_input; + float ka; + float kb; + float lenA; + float lenB; + float distance_to_default_target; + float target_height_distance, target_height_distance_for_moby_pitch; + float x, y; + float half_fov, tn; + float ratio; + float collision_adjusted_pitch; + float k; struct PadState *pad; - struct Hero *steering_input_hero; - char *e; - char *collision_result; - int voice_slot_index; - int hc; + struct Hero *steering_input_hero; + char *e; + char *collision_result; + int voice_slot_index; + int hc; movement_delta.q = 0; up.q = 0; diff --git a/src/overlays/shared/props/trespasser_pad.c b/src/overlays/shared/props/trespasser_pad.c index 8511fbb02d..5aa3299127 100644 --- a/src/overlays/shared/props/trespasser_pad.c +++ b/src/overlays/shared/props/trespasser_pad.c @@ -119,7 +119,7 @@ extern int l02_tresspasser_pad_without_tool_glow_color __asm__("D_L02_00161AA4") __attribute__((sda)); extern int l02_tresspasser_pad_tool_equipped_glow_color __asm__("D_L02_00161AA0") __attribute__((sda)); -extern char D_0013E633_2D9F08[] __asm__("D_0013E533"); +extern char D_0013E633_2D9F08[] __asm__("D_0013E533"); extern void func_L00_002607A8_d92f0(void *a, float x) __asm__("FUN_L00_0025f730"); diff --git a/src/overlays/shared/rendering/debug/update_debug_menu.c b/src/overlays/shared/rendering/debug/update_debug_menu.c index 675240c817..429a13c152 100644 --- a/src/overlays/shared/rendering/debug/update_debug_menu.c +++ b/src/overlays/shared/rendering/debug/update_debug_menu.c @@ -592,8 +592,10 @@ void update_debug_menu(void) { g_debug_menu.control_mode = DEBUG_CONTROL_MODE_ENABLE_LOW_FOUR_UPDATE_FLAGS; } if (controller_words.buttons.w.pressed & 0x10) { - if (--g_debug_menu.control_mode < DEBUG_CONTROL_MODE_ENABLE_LOW_FOUR_UPDATE_FLAGS) - g_debug_menu.control_mode = DEBUG_CONTROL_MODE_ENABLE_SECOND_AND_THIRD_UPDATE_FLAGS; + if (--g_debug_menu.control_mode < + DEBUG_CONTROL_MODE_ENABLE_LOW_FOUR_UPDATE_FLAGS) + g_debug_menu.control_mode = + DEBUG_CONTROL_MODE_ENABLE_SECOND_AND_THIRD_UPDATE_FLAGS; } switch (g_debug_menu.control_mode) { case DEBUG_CONTROL_MODE_ENABLE_LOW_FOUR_UPDATE_FLAGS: