Skip to content

Match and link baselib/synth - #3184

Merged
ribbanya merged 19 commits into
doldecomp:masterfrom
MarkMcCaskey:match-synth
Aug 23, 2026
Merged

Match and link baselib/synth#3184
ribbanya merged 19 commits into
doldecomp:masterfrom
MarkMcCaskey:match-synth

Conversation

@MarkMcCaskey

Copy link
Copy Markdown
Collaborator

this TU is the 2nd and 3rd failing reference when trapping all non-100% TUs and HSD_SynthSFXSampleLoadCallback is the 3rd failing function when booting the game with all non-100% functions trapping.

Restore the four-word tail store as a constant-trip loop, advance the
node cursor in bytes, and let LICM hoist the copy shift.

93.37% -> 95.53%.
Use k * 0x40 indexing in the per-entry fixup loop, fold nshift into the
data-size expression, and advance the node cursor before the stream
cursor.

95.53% -> 96.69%.
@decomp-dev

decomp-dev Bot commented Aug 22, 2026

Copy link
Copy Markdown

Report for GALE01 (ff035cf - d0766a6)

📈 Matched code: 90.25% (+0.05%, +2020 bytes)
📈 Linked code: 74.65% (+0.37%, +14340 bytes)
📈 Matched data: 92.96% (+0.09%, +1080 bytes)
📈 Linked data: 78.02% (+0.70%, +8520 bytes)

✅ 5 new matches
Unit Item Bytes Before After
main/sysdolphin/baselib/synth .data +180 80.94% 100.00%
main/sysdolphin/baselib/synth HSD_SynthSFXSampleLoadCallback +71 93.37% 100.00%
main/sysdolphin/baselib/synth HSD_Synth_80389334 +29 97.03% 100.00%
main/sysdolphin/baselib/synth .sbss +16 85.11% 100.00%
main/sysdolphin/baselib/synth .sdata +13 61.54% 100.00%

Replace the two data_pad placeholders with the assertion text pooled by
two mwld-stripped static helpers, define the .sbss objects that were
left extern, order .sdata around HSD_AudioMalloc's assert, and restore
the unreferenced .data tail object.

.data 77.9% -> byte-identical; .sbss/.bss/.sdata2 byte-identical.
Pass &ve directly instead of through a block-local pointer and reserve
the eight bytes that sit between the voice array and ve, which puts the
whole AXSetVoiceVe sequence and the volume envelope stores on the right
slots.
The setup loop reuses the acquire loop's counter and indexes both the
voice array and the per-voice AX blocks directly, so MWCC strength-
reduces the two walkers in the preheader and the counter's zero also
feeds the node's zeroed fields. Hoist the SFX entry struct to file
scope and reach the per-voice blocks through it.

97.03% -> 98.91%.
HSD_Synth_80389334 stores its sfx_id argument at node offset 4, which
the struct declared as a next pointer; HSD_Synth_8038B5AC clears the
same field. Retype it and store through it.

98.91% -> 99.50%.
Splitting the multiply from the header add stops MWCC folding the
round-up constant into the multiply temp, so the header block now
matches the DOL instruction for instruction.
Keep the unaligned size in its own value so the add lands in a fresh
register, and give the shift-up copy loop its own counter. Everything
from the header read to the unrolled copy now matches except one
volatile pair.
initialize.c writes HSD_Synth_804D6018, so it cannot be static here.
Define it in synth.c's data and declare it in synth.h instead of
repeating the extern at the use site.

Linking synth now succeeds and the DOL differs only inside the two
functions that are still short of 100%.
Splitting the round-up into a mask of its own keeps the aligned size out
of the optimiser's temp pool, and declaring the copy counter ahead of
the header read orders the three long-lived values the way the DOL has
them.

HSD_SynthSFXSampleLoadCallback: 32 differing instructions -> 16.
alloc_size plus OSRoundUp32B, as in HSD_SynthSFXHeaderLoadCallback, reproduces the header block exactly and drops the dead sum read. Folding src_idx into the copy loop's initializer leaves the two dead alias homes the frame has room for, and the unsigned source index keeps the four header loads off a strength-reduced walker. 16 -> 7 differing instructions.
The include-cleaner pass on master dropped the transitive path that used to
supply OSHeapHandle to synth.h, so the merged tree failed to compile.
The two cursor updates are independent, but their order decides which pair of
registers the allocator gives each one. Retail stores HSD_Synth_804D7734 first,
which is what makes the node advance keep r0 across the mask; both cursor
relocations in the loop tail now match.
The ITD flag arrives as an int, not a u8. Storing it into the byte-wide field
costs a truncation that the peephole then deletes, but the scheduler has
already spent an integer slot on it -- which is what keeps the argument copy
from landing between the two folded stores. With that slot occupied the node
claims its slot before its id, matching retail.
A logical right shift by two already discards the low bits, so the
`& ~3` was a no-op.
The bucket index is masked in place and both cursors advance by a word
count, which is what the register allocation needs: the in-place mask
emits a record-form `andi.` that the peephole folds into the following
`rlwinm`, and the extra shift in the node advance gives that chain the
height to claim the integer slot the mask frees.
`ninja apply` recovers the compiler's own literal-pool and static names. It
also supersedes a split-era guess at 0x804DE7F0, which the splitter had
carved into two words: it is one 8-byte pooled `double` (`@313`, align 8).
Nothing referenced the phantom second half.
@MarkMcCaskey MarkMcCaskey changed the title Match baselib/synth (WIP) Match and link baselib/synth Aug 23, 2026
@MarkMcCaskey
MarkMcCaskey marked this pull request as ready for review August 23, 2026 18:37
@MarkMcCaskey MarkMcCaskey added the ai-assisted Utilizes a LLM to do the heavy lifting label Aug 23, 2026
@ribbanya
ribbanya merged commit e20c5c9 into doldecomp:master Aug 23, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-assisted Utilizes a LLM to do the heavy lifting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants