Skip to content

decomp: clarify fields, parameters and state names (batch 38) - #281

Draft
pezzadev wants to merge 657 commits into
lombyte-project:mainfrom
pezzadev:decompilerizer-batch-38
Draft

pezzadev wants to merge 657 commits into
lombyte-project:mainfrom
pezzadev:decompilerizer-batch-38

Conversation

@pezzadev

Copy link
Copy Markdown
Collaborator

Before

Many already-matching functions still use generic parameter, local and field names, and compare states or selectors with numeric literals.

After

Clarify names across camera and hero behavior, enemy and weapon updates, menu and memory-card handling, audio, and SDK routines. Name supported state and selector values, reuse shared hero/moby enums, and keep sand-shark relaunch and target-selection states in separate enum domains.

Examples include peckbot and flying-car private fields, follow-camera height/orbit state, hero item animation parameters, memory-card requests, and sceClose/sceIpuRestartDMA locals. New camera/HUD global declarations live in headers.

Retain upstream implementations and canonical names when rebasing. Preserve linked symbol labels, layouts and numeric values. This is readability work; it does not increase byte-matching coverage.

Verification

  • make elf ends with PASS: reconstructed boot ELF matches retail
  • make overlays ends with PASS
  • make check passes
  • Cleanup rules and pull-request title checked against main

offset -> slot_reuse_delay_frames: The third s32 parameter arrives in a2: retail 0x002efc20 and 0x002efc50 add it to the loaded level_frame_count, then 0x002efc28/0x002efc54 store that sum into the expired slot. Comparisons at 0x002efc14/0x002efc44 require the prior slot deadline to be below the current frame. The supplied robosquawker_update caller passes slot_reuse_delay_frames computed as scale_game_frames(1) * 60.0f, confirming the delay is measured in frames.
count -> timeout_countdown: In src/sdk/dma/wait_dma.c (SHA-256 b540ef2b5d6d1e431d09340438824441852b17aa90a3700d39707f7690946fcc), signed count is initialized to 0x1000000 and predecremented while *chcr & 0x100 remains set. Retail 0x00122f14 initializes s1, 0x00122f34 and 0x00122f5c decrement it, and 0x00122f38 tests its sign. Negative values reach scePrintf("libdma: sync timeout\n") at 0x00122f40 and sceDmaPause at 0x00122f48. Original Ghidra iVar1 has the same countdown and timeout flow, proving timeout_countdown.
count -> saved_frame_count: Authoritative C assigns count = decoder->frame_count once. Retail 0x0012c150 loads decoder +0x118 into a2 before either branch: _Error at 0x0012c158 receives it unchanged; 0x0012c174 and 0x0012c17c subtract one for the field/frame display paths at 0x0012c198 and 0x0012c180. This proves a saved frame-count value, consistent with _sceMpegFlush reading decoder->frame_count after _lastFrame.
size -> allocation_size_bytes: In hud_heap_alloc, retail 0x001ff2a8 saves incoming a0 in s0. At 0x001ff2b4-0x001ff2c0 the heap end minus cursor address is compared with s0. At 0x001ff2d0/0x001ff2dc (s0 + 15) & 0xfffffff0 rounds this byte quantity to 16 bytes, and 0x001ff2e0-0x001ff2e4 adds it directly to the heap cursor. Original Ghidra param_1 has the same comparison and cursor increment; source size is both the requested and then aligned allocation size in bytes.
count -> collected_bolt_count: In the SHA-256-bound count_gold_bolts source, s32 count starts at zero and increments only for D_0014BEC0[row * 4 + k] != 0. Retail 0x00215294 initializes a2 to zero; 0x002152b8 loads a collection-flag byte, 0x002152bc computes a2+1, and 0x002152d0 conditionally commits that increment only when the byte is nonzero. The supplied original Ghidra names this table g_bGold_bolt_collected. The 20-by-4 scan accumulates collected bolts and 0x002152e4-0x002152fc clamps the returned total to [0,40].
size -> buffer_element_count: In authoritative src/movies/decoder/video_input/vi_buf_create.c (SHA-256 4d948793a2a0b0b7e7e3b9731608fee5618bcb21ad79f9d28e8a684c381731ea), size is assigned to ViBuf.n and multiplied by VIBUF_ELM_SIZE (2048) for ViBuf.buffSize. Original retail Ghidra likewise stores param_4 in puVar2[2] and param_4 << 0xb in puVar2[6]. Retail 0x0023bc80 shifts the fourth argument a3 left 11 bits, 0x0023bc88 stores the byte capacity at +0x18, and 0x0023bc98 stores the unscaled count at +0x08. Thus it is the buffer element count, each element contributing 2048 bytes.
offset -> minute_delta: In the authoritative src/sdk/time/adjust_time.c snapshot (SHA-256 44ad3e01b0e235d665f7b68ee39dd5938f34dd813cbebf51247ab503d2c288d7), offset is s32 and added to the decoded byte at time+2. Retail 0x0012d660 saves a1 in s0; 0x0012d664 loads clock+2, identified as bMinute in the original Ghidra decompilation; 0x0012d668 adds it to s0. Negative totals add 60 and call decrement_clock_hour at 0x0012d6a8; totals above 60 subtract 60 and call increment_clock_hour at 0x0012d688. The supplied sceScfGetLocalTimefromRTC caller passes time_zone + summer_minutes, with summer_minutes computed using 60. These operations prove a signed minute delta.
count -> remaining_decimal_places: In the authoritative src/math/round_float_to_decimal_places.c snapshot (SHA-256 5cb4576927e4c385b10120fa66a8ca93e7f2350ceac72575ce6ea78b9753d454), s32 count is initialized from decimal_places, checked positive, decremented once per decimal_scale_factor *= 10, and tested for zero. Retail a0 is checked at 0x00214c54, decremented at 0x00214c60, and tested at 0x00214c74 while the delay-slot multiplication at 0x00214c78 multiplies the scale by ten. The prepared original Ghidra decompilation shows the same decrementing decimal_places loop. Thus this local is remaining_decimal_places.
size -> transfer_quadwords: In the bound source (SHA-256 808531fbb20b079efeca8d3769623af8eef3577323052362d3c6c7335776f3ee), size is added to slot_offset_quadwords for the slot_limit_quadwords check and multiplied by 16 into req[2]. Retail a3/param_4 is added to a2 at 0x00293d60 and compared against the selected slot bound at 0x00293d6c. At 0x00293d84 a3 is shifted left four bits, then stored at request +8 at 0x00293d90 before sceSifSetDma at 0x00293da0. Thus the parameter measures transfer length in 16-byte quadwords.
count -> point_count: In the SHA-256-bound source, count is loaded from *(int *)path_record, used in (i + 1) % count for next_point_index, and bounds i while each point is addressed at path_record + 0x10 + i * 16. Retail 0x0030eb54 loads v1 from 0(s2), 0x0030eb6c divides the successor index by v1, 0x0030eb80-0x0030eb90 addresses the remainder-selected point, and 0x0030eba0-0x0030eba8 reloads that same header word and compares the incremented point index against it. Original Ghidra *piVar4 and iVar3 % iVar5 show the same point-count flow.
count -> point_count: Incoming a1 is retained in s1 at 0x0020cd64, tested as signed positive at 0x0020cd80, decremented once at 0x0020cd9c per scale/basis/translation sequence, and tested again at 0x0020cdc4. The point cursor advances by 0x10 at 0x0020cdc0. Supplied callers pass 3 for transformed_panel_vertices[3] and 6 for pts[6][4], proving this counts points rather than bytes.
count -> polls_since_callback: In src/sdk/ipu/wait_ipu_idle.c (SHA-256 2c817d815b9a3f2377c8b6802ad5fbdc6586a5cf5b47346aa6e497feae3be432), count starts at zero, increments while IPU_CTRL at 0x10002010 satisfies the busy mask, and resets after DispatchMpegCallbackNoData. Retail 0x0012847c initializes a0; 0x001284b0 compares its saved value against 0x1389, 0x001284b8 increments it, and 0x001284bc invokes the callback followed by zeroing at 0x001284c4. The original Ghidra iVar3 has the same polling-counter role. At 0x001284c0 a0 transiently receives ctx+0x858's contents as the callback argument, matching the source's reuse of count.
size -> requested_byte_count: Retail 0x0023ba78 saves incoming a2 in s3; 0x0023ba80 computes s3 >> 11 into s2, passed as sceCdRead sector count at 0x0023baa0/0x0023baac. The data-pattern byte is zero at 0x0023bab0, selecting 2048-byte sectors in the supplied sceCdRead source. Original Ghidra likewise computes dwSectorCount = (int)param_3 >> 0xb. At 0x0023bac4/0x0023bad4 the original requested count is returned on the synchronous branch, matching source returned_byte_count = size.
count -> point_count: Retail 0x001f3054 copies a2 to s2; 0x001f3070 skips the scan when s2 <= 0. The index s0 increments once per distance comparison and 0x001f30a8 tests s0 < s2, while 0x001f30b0 advances the point pointer by 0x10 bytes. Source loops i < count over points + i * 0x10; steer_child_moby supplies &path[1] and path[0].n, proving this is a point count.
size -> max_bytes: In src/sdk/deci2/sce_tty_read.c (SHA-256 04fe95e41a58ffc6a0ad59aec6f86b0c98263436f080c6f1b0ce1464d3606330), size bounds i in the loop copying one byte to destination[i]. Retail 0x00119910 preserves a1 in s2; 0x0011991c skips copying for a nonpositive bound; 0x00119968-0x0011996c copies one byte, 0x00119930 increments the copied-byte index, and 0x00119998 compares that index against s2. LF/CR tests at 0x00119980 and 0x00119988 allow earlier return. Original Ghidra nCapacity and the supplied read caller passing max_bytes confirm this is the maximum bytes to copy.
size -> level_record_bytes: In the bound source, s32 size receives memcard_prepare_data(cursor, index, mc_leveldata) and is added to the u8 *cursor. Retail 0x0020ac18 passes the record index in a1, 0x0020ac1c selects mc_leveldata at 0x001a07c0 in a2, and 0x0020ac20 calls 0x0020ad78; 0x0020ac28 adds returned v0 to output cursor s2. The original decompilation likewise adds this return to its output address. Thus this is the byte extent of the prepared level record in the 20-record loop.
size -> initialized_scale: In the authoritative C initialization case, float size = moby->scale * 4.0f is used only by moby->scale = size. Original retail Ghidra shows the same multiply and store at param_1+0x2c. Retail 0x002e88fc loads scale from 0x2c(s0), 0x002e8904-0x002e8908 supplies 4.0, 0x002e891c multiplies, and 0x002e892c stores the initialized scale back to 0x2c(s0).
count -> component_countdown: The single source count binding controls both gather and scatter of row_vector's three float components. Retail 0x00214158 and 0x00214198 initializes a0 to 2; 0x00214164 and 0x002141a4 decrements it after each component load, and bgez at 0x00214174/0x002141b4 repeats through three transfers until -1. Thus this is the signed component-transfer loop countdown, reused before and after unit normalization.
offset -> row_byte_offset: In source SHA-256 633abb577b110f9dd0e69831c5627e965f5ccf2be3884d08c37c311c033a4bbf, offset = i * 4 is added to (u8 *)matrix_base for both gather and scatter. Retail 0x00214144/0x002141c8 shifts the row index by 2 into s0, and 0x00214154/0x00214190 adds s0 to saved matrix base s1. The three outer iterations select row byte offsets 0, 4 and 8; inner matrix accesses stride 16 bytes.
size -> transfer_byte_count: Incoming a2 is saved in s2 at 0x0023af34 and stored at sp+8 at 0x0023af54, the length word of the SIF DMA descriptor whose source and destination occupy sp+0 and sp+4. sceSifSetDma submits this descriptor at 0x0023af60. After completion polling, 0x0023af98 passes the same s2 as a0 to 0x0012f148. Original Ghidra likewise assigns param_3 to uStack_58 and forwards it to notify_mpeg_audio_rpc_transfer; current C assigns size to descriptor[2] and forwards it to snd_update_movie_adpcm. This proves the transferred byte count.
size1 -> first_destination_byte_count: In audio_dec_begin_put, s32 *size1 corresponds to retail a2 / Ghidra param_3. At 0x0023ad94 it receives 0x28-hdrCount beside first_destination=hdr+hdrCount; 0x0023adb4 returns dec->size beside data; 0x0023adec returns size-count beside data+put; 0x0023ae04 returns size-put when wrapping. The u8 header arithmetic and data offsets establish the first destination span length in bytes.
size2 -> second_destination_byte_count: In audio_dec_begin_put, s32 *size2 corresponds to retail t0 / Ghidra param_5. At 0x0023ada8 it receives dec->size beside second_destination=data; 0x0023adc0 writes zero beside NULL; 0x0023ae24 writes (size-count)-(size-put) beside the wrapped second_destination=data at 0x0023ae0c. Thus it is the byte length of the second writable destination span, zero when absent.
size -> byte_count: Retail parameter three (Ghidra param_3, a2) is increased by 0x3fff at 0x002a0f1c and masked with -0x4000 at 0x002a0f24/0x002a0f40, matching source left = (size + 0x3FFF) & ~0x3FFF. The rounded remainder s0 decreases by 0x4000 at 0x002a0f78 while the shared source/destination byte offset s1 increases by 0x4000 at 0x002a0f90 and is added to both byte addresses at 0x002a0f4c and 0x002a0f84. Thus size is the requested byte count before chunk rounding, rather than a chunk count or dimension.
size0 -> expected_game_span_bytes: Source initializes size0 with memcard_get_data_size(mc_gamedata) and compares it with MemoryCardSaveSizes.main_size. Retail 0x002092a8/0x002092b8 supplies 0x001a04c0 to the call at 0x002092c8; 0x002092dc preserves its return in s1 and 0x002092e0/0x002092e4 compares the first saved header word against s1. That validated header word advances the u8 save cursor at 0x0020931c after game-data restoration. Original Ghidra iVar1 likewise computes the expected first span and checks *param_1.
size1 -> expected_level_span_bytes: Source initializes size1 with memcard_get_data_size(mc_leveldata), checks MemoryCardSaveSizes.record_size against it, and adds size1 to the u8 save cursor after each of 20 level restores. Retail 0x002092d4 supplies 0x001a07c0 to the call at 0x002092d8; 0x002092e8 preserves its result in s3, 0x002092ec/0x002092f0 compares the second header word against s3, and 0x00209344 adds s3 to the input cursor for the next level record. Original Ghidra iVar2 has the same check and stride.
size -> sector_count: In the SHA-256-bound load_level_gameplay.c snapshot, both PAL and standard branches assign size = sectors[i+1] - sectors[i] and pass it as the third argument to start_audio_stream_read(buf, start, size). Retail 0x00245238/0x0024523c loads these consecutive sector boundaries, 0x00245240 subtracts them into a2, 0x00245244 gates on a positive count, and 0x00245250 calls the stream reader with that count still in a2. Thus this s32 is the chunk's sector count, not an unspecified size.
count -> dma_busy_poll_count: In the authoritative src/sdk/graph/sce_gs_put_draw_env.c snapshot (SHA-256 99abded6ed337e146bff88e4c8827199dcdf07c28b7c36763b7bece4a5d1c986), u32 count is initialized to zero and incremented only inside the loop polling bit 0x100 of GIF DMA CHCR at 0x1000A000. Retail 0x001221d0 clears a0; 0x001221e8 compares its old value against 0x01000000, and 0x001221f0 increments it. The repeated CHCR read/test at 0x001221f4-0x001221fc continues while busy. Exceeding the threshold branches to 0x00122250, prints the DMA Ch.2 timeout diagnostic and returns -1. The original Ghidra uVar3 follows this same counter flow, proving a DMA busy-poll iteration count.
count -> requested_bit_count: In the SHA-256-bound _peepBit source, count is compared with ctx->available_bit_count and selects the returned leading bits through (u32)ctx->bit_window >> (0x20 - count). Retail 0x00128740 saves a1 into s2; 0x00128744-0x0012874c compares the available width at +0x83c against s2; 0x00128808 and 0x00128814 negate s2 and logically shift the window. Original Ghidra calls it nBitCount. Supplied _extensionAndUserData passes 32 to inspect a start code and _mbAddressIncrement passes 0xB to inspect an eleven-bit code.
count -> texture_record_count: Retail 0x00202814 retains argument a1 in s2; 0x00202824 skips nonpositive counts and 0x002028a8/0x002028b0 increments the resident record index and compares it with s2. Each iteration reads four consecutive 32-bit words at 0x00202838/48/58/68, advances the source 16 bytes and writes one 16-byte resident texture definition. Authoritative C uses count solely as that loop bound; the caller passes header->pointCount beside header->points, and prepared Ghidra identifies nSourceCount of ResidentIndexedTextureSource records.
count -> remaining_run_nibbles: In src/ui/map/coverage/decode_map_rle_row.c (SHA-256 fd961100860a185dc8348113df909713dd2f0753feb17362e7e6b7967ae17500), count corresponds to original Ghidra uVar9 and retail t1. Instructions 0x002068fc-0x00206904 initialize it to 256 or the packed run repeat count. At 0x00206918 it decreases by one when filling the pending high nibble, while 0x00206930-0x00206944 emit a byte containing two copies of the run nibble and decrease it by two. A residual -1 selects the low-nibble correction at 0x00206954-0x0020695c. Thus it tracks remaining decoded run nibbles, rather than compressed bytes or the number of runs.
offset -> read_byte_count: Source offset loads ring_buffer->read_bytes. Retail 0x0023be60 loads +0x14 into a1; 0x0023be70-0x0023be78 adds it to the block-derived byte position before modulo, and 0x0023be8c-0x0023be90 subtracts it from block-derived available bytes. Original Ghidra param_1[5] participates in both byte calculations, proving the read-byte count role without inferring its lifecycle.
size -> ring_capacity_bytes: Source size loads ring_buffer->buff_size. Retail 0x0023be6c loads +0x18 into v1, used as the divisor at 0x0023be84 for a position computed in bytes after <<11. At 0x0023be98 and 0x0023bec8-0x0023bed0 this capacity minus the byte write position bounds the first writable span. Original Ghidra iVar2 has the same modulo and wrap-boundary role.
count -> collected_mission_count: Authoritative C initializes count to zero, indexes mission_ids[count] and the corresponding mask bit, increments only within the branch that emits a mission ID, and returns count. Original Ghidra uVar7 has the same increment and return. Retail 0x0020bc04 initializes t3 to zero; 0x0020bcc4 uses t3 for the output mask bit; 0x0020bc90/0x0020bcb0 write the emitted ID, 0x0020bcd8 advances its output pointer, and 0x0020bcf0 increments t3 only on that emission path. Skipped nodes bypass that increment, and 0x0020bd28 returns t3. Thus this is the collected mission entry count, not the number of nodes visited.
size -> video_input_block_count: Retail 0x0023caec preserves incoming sixth argument t1 in s3; 0x0023cb90 forwards s3 in a3 to vi_buf_create at 0x0023cb98 with &vd->vi_buf (vd+0x48). Helper 0x0023bc98 stores a3 at buffer-record +8, while 0x0023bc80 shifts a3 left 11 and 0x0023bc88 stores the resulting byte capacity at +0x18. Its input backing address is stored separately at +0 by 0x0023bc64. Thus size counts the video input buffer's 2048-byte blocks, rather than bytes or MPEG workspace capacity.
offset -> wander_or_effect_vector: The sole float offset[4] in scoutbot_update maps to retail sp+0x30. At 002d2db8-002d2dec its XY components are cos/sin(random heading)*radius in [0,3] and Z=0; fast_vec_add adds it to pvars+0x1C0 home to produce +0x1F0 wander_goal. At 002d341c-002d3474 the same storage holds cos/sin(moby->rot.z)*0.2 with Z=0 and is passed as the vector argument to spawn_nearby_effect. At 002d3598-002d35c4 it receives moby->pos with Z raised by 1, then 002d360c-002d3620 passes it as explode_3DF8's position. Thus wander_or_effect_vector names all proven uses, including the absolute explosion position that bare offset obscures.
offset -> hero_seat_offset: Authoritative turret_update copies seat into hero.motion.pos. Retail 00304d48-00304d4c copies sp+0 to hero position 0013f3d0; 00304d84-00304db4 constructs sp+0x10 XYZ as cos(hero yaw)*-0.7, sin(hero yaw)*-0.7, zero and passes it as a2 to fast_vec_add with hero position as input/output. Original Ghidra fStack_120/fStack_11c/uStack_118 confirms this displacement from the copied seat. This is the sole use of source Vec4 offset.
offset -> occlusion_history_pool_offset: Authoritative C declares offset once as slot_index * (s32)sizeof(VoiceSlot) + 0xB4, adds history_offset to it, and uses the sum with repeat_index to index ((u8 *)&voice_pool), copying the selected occlusion_history byte into the next five history bytes. Retail 0x0022d218-0x0022d240 multiplies the slot index by 0x70 into s2 and forms s7=s2+0xB4. At 0x0022d25c-0x0022d284 the history displacement is added to s7 and then s8 (the pool base 0x0013e550), before incrementing the destination by one; 0x0022d290-0x0022d2a8 copies the byte five times. Original Ghidra likewise identifies the destination as the selected slot's aReserved_10 + history displacement + 0x34. Thus this binding measures bytes from the pool origin to this slot's occlusion-history start.
count -> updated_fire_cycle_count: In COMMANDO_STATE_FIRE_ROCKETS the source initializes count from commando_data->rocket_fire_cycle_count + 1, stores it back, and compares (short)count against 3. Retail 0x002d34ac-0x002d34bc gates this on animation window 10; 0x002d34c4 loads pvars+0x2DE, 0x002d34c8 increments it, 0x002d34cc-0x002d34d4 sign-extends and compares against 3, and 0x002d34dc stores it. Reaching three enters IDLE, seeds cooldown, and clears the field at 0x002d351c. Thus this local is the updated firing-cycle count, not an individual rocket count.
count -> reactivation_elapsed_frames: In the wait-for-reactivation case, source count is the unsigned 16-bit reactivation_timer_frames plus one, written back to that field and converted to short timer for the scale_game_frames(240) gate. Retail 0x002d074c loads +0x2F2, 0x002d0754 increments it, 0x002d075c stores it, and 0x002d0758/0x002d0764 sign-extend the short for comparison at 0x002d0768. Ghidra sVar5 records the same increment and gate; hit handling resets +0x2F2 at 0x002d08dc.
offset -> competitor_speed_offset: Source offset is race_competitor_index multiplied by time*1.55f and is added to both normal_speed_target and boost_speed_target. Retail 0x002d05d4-0x002d0600 converts private +0x2CC to float and multiplies it by the time-scaled 1.55 factor; additions at 0x002d0604/0x002d0608 feed the +0x2B8/+0x2B4 speed target stores at 0x002d060c/0x002d0610. Original Ghidra fVar18 shows this same shared additive speed adjustment.
count -> exclusion_entry_count: Retail 002ce42c initializes s6 to zero. For each valid slot drone, 002ce4a4-002ce4b0 loads its pvars+0x30 target, increments s6 and writes the next hero+0x1FFC exclusion entry. At 002ce4fc-002ce530 s6 starts the suffix-clear index; 002ce540 passes this exclusions array to target selection. At 002ce68c-002ce69c s6*4 indexes the next exclusion slot for the newly assigned target. Original decompilation iVar22 has these same uses. Current C count indexes exclusions[count], increments after each entry, initializes exclusion_clear_index, and indexes the appended assignment; exclusion_entry_count names the populated prefix length, including null entries.
offset -> ring_radial_offset: In the authoritative C, this RopeVec is first cross(normal, step), then dotted with cross(normal, previous segment direction) to choose normal orientation. Retail 00318508..0031854c writes that vector through stack+0x120 (pointer saved at 00317f00..00317f28). The same stack+0x120 buffer is loaded at 00318624, filled by scaling the C700 ring profile by the segment radius at 00318668..0031867c, transformed by the side/perpendicular/normal basis at 00318680..0031868c, and added to the rope point at 00318690..003186a4 to produce rope_grid[i][column]. Thus it is a radial displacement from the rope center to a ring vertex, with an earlier radial orientation-test use.
size -> converted_field_byte_count: In the authoritative source src/sdk/libc/stdio/_vfprintf_r.c (SHA-256 dd60879518495cb9e5e33aaf2f2d6d47ea9064c2a6421e61c6cdb3fa1dfba5ae), size is 1 for %c, strlen(cp) or bounded memchr(cp,0,prec)-cp for %s, and conversion_buffer+BUF-cp for integer digits. Retail s5 receives 1 at 0x001171c0, the bounded string length at 0x001174b8/0x001174c4 or strlen result at 0x001174dc, and the backward-generated digit span at 0x001176d8. Float paths 0x00117348-0x001173c8 compute the corresponding formatted content length including decimal point and exponent. Original Ghidra pcVar5 carries this quantity into LAB_001176f8, where it is compared with integer precision before sign/prefix expansion. Retail 0x0011799c subtracts s5 from integer precision for leading zeroes, and 0x00117a6c stores s5 directly as the non-floating I/O vector byte length. Thus converted_field_byte_count identifies the counted entity and byte unit, excluding separately emitted prefixes and padding.
size -> sample_file_byte_count: In the authoritative C capture branch, size receives sceLseek(fd, 0, 2) for the occlusion_samples_file_name file. Retail 001f5750..001f5760 calls sceLseek with zero offset/end origin and saves its result in s1. 001f5764..001f576c checks it against 0x100000; 001f5784..001f5790 passes s1 as sceRead's byte length into occlusion_samples. 001f5794..001f57ac divides s1 by 12 and stores occlusion_sample_count. Original Ghidra shows the identical lVar9 seek/read/divide flow, proving this is the sample file byte count.
size -> impact_scale_multiplier: Authoritative C initializes this float to convert_integer_to_float(D_0013E520.bB)+1.0f. Retail 0x002b0578-0x002b0594 loads byte 0x0013e52b, converts it and keeps the sum in f24 (original Ghidra fVar18). At 0x002b0e28-0x002b0e40 twice f24 is the radius passed to collect_mobies_in_sphere. The same multiplier scales impact-particle velocities at 0x002b1020-0x002b1028 and 0x002b1690-0x002b1698, shrinking-particle scale by 40000 at 0x002b111c-0x002b1134, debris scale by 200000 at 0x002b16dc-0x002b16f4, and glow scale by four at 0x002b1798-0x002b17b0. Thus it is a shared impact scale multiplier, not an individual particle size or byte quantity.
offset -> secondary_beam_horizontal_offset: Authoritative src/overlays/shared/weapons/tesla_claw_beam.c SHA-256 3cac07b0c822aa96f95d6d47fc6ae02572a8cb22df50001c162668f07debf425 constructs offset XY from cos/sin of delta heading plus pi/2, scaled by secondary_beam_horizontal_wave_amplitude*cos(side_phase), and sets Z=0. Retail 002b9e7c..002b9ec8 computes these components at sp+0xa0/+0xa4/+0xa8; 002b9ed8..002b9eec caches the vector in 001db890[seg] and adds it to secondary point s5. The later arm at 002b9f44..002b9f50 loads the cached vector for seg into the same local. Thus it holds the secondary beam's horizontal displacement vector.
size -> fade_particle_size: In the authoritative fade-out branch, size receives random_float_between(sandmouse_fade_particle_min_size_gp, sandmouse_fade_particle_max_size_gp) and is passed to the particle creation helper. Retail 0030ecc4 and 0030ecd0 load those bounds into f12/f13, 0030eccc calls the random float helper, and 0030ecd8 forwards f0 as f12 to the particle helper at 0030ed08. Original Ghidra case 6 shows the same result flow; supplied checked helper findings at 00287374 and 002873f4..00287408 retain, scale and store initial particle size.
count -> spawned_beam_particle_count: Retail 002de8d8 initializes stack+0x19c to zero before the 200-record update loop. At 002de900-002de914, an empty particle record is eligible only while this counter is below five. The spawn_puff result at 002deb00-002deb1c is stored in the beam record; only its non-null branch increments stack+0x19c at 002deb3c-002deb44. The separate spark success counter uses stack+0x1a0 at 002dea5c-002dea7c. Thus count measures successful tracked beam-particle spawns in this invocation, not active particles or attempted allocations.
offset -> mounted_hero_position_offset: The sole source float offset[4] is used only in the command==1 anchoring block. Retail 0x002e03b4-0x002e03c8 copies cannon position and rotation to hero motion; 0x002e03e0-0x002e03f8 computes cos/sin(hero yaw)*-0.7 into stack +0x10/+0x14, 0x002e03fc zeros its z, and 0x002e0400-0x002e0410 passes that vector to fast_vec_add with hero motion position as both destination and first operand. It is the heading-dependent displacement applied to the mounted hero's position, distinct from subsequent dismount positioning.
size -> puff_size: In the death-fall puff loop, source float size receives random_float_between(40000.0f, 100000.0f) and is passed exclusively to the size argument of FUN_L00_0026d000_c618. Retail 0x002ad708..0x002ad728 loads these bounds, calls 0x002600e8 and saves f0 in f20; 0x002ad758 moves f20 into f15 for the puff spawn at 0x002ad770. Original Ghidra case 9 tracks the same random result as uVar17 into func_0x00274c88, corroborating the puff-specific size role.
count -> loaded_moby_count: count -> loaded_moby_count: In the authoritative C hdr->f44 block this int starts at zero, is written to moby_index_remap[i] and selects moby_table + count only in the non-skipped branch. Retail 0x0024282c clears sp+0x18; 0x00242a54-0x00242a70 loads that count, stores its low halfword into the file-order remap and multiplies it by 0x100 to select the MobyInst passed to init_moby_instance. Only the retained branch reaches 0x00242c34-0x00242c38 to increment it. 0x00242c5c-0x00242c84 uses the final count to set the loaded-table end and its 0xFF sentinel. Original Ghidra iStack_e8 and source count agree. This counts loaded file mobies, excluding skipped records and the separate reserved n2 slots.
count -> collected_moby_count: In DOOM_BOT_DETONATE, count receives collect_mobies_in_sphere(&moby->pos, speed, 0x15, moby, 0). Retail 002c137c calls 001f2868; 002c1398 moves its v0 return directly to a3 for send_blast_hits at 002c13bc, alongside collection storage D_L00_00177F00 in a2 (002c138c/002c13a0). Original Ghidra likewise passes uVar6 from FUN_001f2868 into FUN_0025a9f8. This is the collected moby count consumed by blast-hit dispatch, and its sole assignment/use in the authoritative C establishes the local's entity domain.
offset -> attachment_point_offset: In SHARKIGATOR_TARGET_LUNGE_INTERPOLATION, retail 0031019c..003101c0 obtains moby attachment point index 0 in sp+0x70 and subtracts moby position s2+0x10 into sp+0x80. At 00310268..00310278 this same vector is subtracted from target.pos to form the moby-position goal. Current C expresses fast_vec_sub(offset, point, mpos) and fast_vec_sub(goal, &target, offset), proving attachment-point displacement from the moby position.
size -> particle_size: Retail 0030f9d4..0030fa08 calls random_float_between with 1.5f and 2.4f and retains its float return in f22; 0030fa58 moves it into f12 for particle spawn 0030fa68. Current C passes size as the first float argument to the established spawn_moving_resizing_height_snapped_alpha_fade_particle after adjusting point coordinates. This proves the randomized particle-size input without claiming radius, diameter or units.
offset -> hero_motion_prediction_offset: Within SNAGGLEBEAST_SWEEP_BEAM_ATTACK, retail 003155f0..00315604 copies hero+0x100 (0013f450) to projection at sp+0xe0 and clears its Z. 00315608..00315624 scales that horizontal hero-motion vector by scale_game_frames(0x28) into sp+0xc0, the C local offset (Ghidra auStack_130). 00315678..003156a4 subtracts the current sweep midpoint-relative displacement from this vector and adds the correction to both sweep endpoints. Thus offset is the horizontal hero-motion prediction displacement used to shift the beam sweep.
timer194 -> triple_spawn_attack_ready: Retail 00314380..0031438c passes instance+0x194 to fast_dec_timer_s16 and converts its return to boolean s3 (Ghidra bVar3). Phase handling suppresses s3 at 00314554/00314584/0031459c/003145b4. Its true branch at 00314c68..00314cd8 starts animation 4 and stores main state 3, the established SNAGGLEBEAST_TRIPLE_SPAWN_ATTACK; the shared chase branch 00315c0c..00315c60 does the same. Attack completion reloads the countdown at 003152c8/003152e4. The C uses this local only as that attack-readiness gate, not as a timer quantity.
offset -> effect_position_or_beam_step: offset -> effect_position_or_beam_step: The sole float[4] local corresponds to original Ghidra fStack_110 at sp+0x20. Retail 0x002eb9ac-0x002eb9e0 subtracts tractor endpoint (+0x80) from hero position, normalizes the vector to frame_time*40 and adds it to the endpoint. 0x002eb9ec-0x002eb9f8 also copies hero position into this storage. During capture, 0x002ebd64-0x002ebdd8 forms ray_start minus endpoint, bounds the movement step and adds it to the endpoint. In death flight, 0x002ec354-0x002ec3e0 accumulates random basis displacements onto moby position in the same storage and passes it as cart_burst position. Finally 0x002eca88-0x002ecb24 transforms a basis vector, normalizes to 7, subtracts it from moby position, sets W=50 and allocates or updates the point-light position. Authoritative C matches these uses. The new name identifies its alternating position and beam-step roles instead of implying it always holds an offset.
domain_0_value_2 -> MINE_DETONATION_HIT_STATUS_MIN: Authoritative source SHA-256 41e9792092fe264d26c832752b805749f7680c4a8b9d9e0150ed3ad1031c480c passes &hit_status as resolve_moby_hit_response's fifth argument. Retail 0x002ff868 supplies sp+0x70 in t0; 0x002ff874 calls checked level-14 helper 0x002628a0. The helper preserves t0 in s3 at 0x002628b0, initializes *s3 to 0 at 0x002628f8, writes 1 on the no-hit path at 0x002629d4, and writes 2 for selected hit responses via 0x00262c60-0x00262c68 (with special branches writing 3/4 at 0x00262c28-0x00262c38 and suppression potentially writing 1 at 0x00262d74-0x00262d78). The caller loads this output at 0x002ff87c and tests <2 at 0x002ff880; outputs at least 2 pass to the non-null hit and class-0x283 exclusion before explosion calls 0x002ff93c/0x002ff9a8. Original Ghidra aiStack_70[0] < 2 confirms the same gate. Thus 2 is proven as this mine's minimum detonation hit status, not a mine state, hero mode, response return code or damage guarantee.
@github-actions

Copy link
Copy Markdown

Decompilation progress

C_EXACT Change Matched bytes Functions C_FUZZY
All code 100.00 % — 3,547,932 / 3,547,932 B (—) 4,244 / 4,244 (—) 100.00 %
Boot executable 100.00 % — 354,504 / 354,504 B (—) 1,230 / 1,230 (—) 100.00 %
Game 100.00 % — 264,872 / 264,872 B (—) 850 / 850 (—) 100.00 %
SDK 100.00 % — 89,632 / 89,632 B (—) 380 / 380 (—) 100.00 %
Level overlays 100.00 % — 3,193,428 / 3,193,428 B (—) 3,014 / 3,014 (—) 100.00 %
Shared level code 100.00 % — 1,130,492 / 1,130,492 B (—) 1,583 / 1,583 (—) 100.00 %
Per-level code 100.00 % — 2,062,936 / 2,062,936 B (—) 1,431 / 1,431 (—) 100.00 %
Data in C Change Matched bytes
All data 77.18 % — 9,596,104 / 12,433,372 B (—)
Boot executable 38.55 % — 269,525 / 699,136 B (—)
Level overlays 79.48 % — 9,326,579 / 11,734,236 B (—)

No function changed its match state compared with main (5497cf4).

Compared with main (5497cf4). C_FUZZY uses main's last measurement.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant