From 00d4d6428c2b5e755816a9cf4fc2089b81926a6b Mon Sep 17 00:00:00 2001 From: cecilarmitais Date: Sun, 16 Aug 2026 14:42:05 -0700 Subject: [PATCH] Decomp the last four DSE track-event handlers in arm9 Decompile from asm: DseTrackEvent_WaitUntilFadeout 0x0207199C DseTrackEvent_EndTrack 0x020719C8 DseTrackEvent_SubLoopBegin 0x02071A1C DseTrackEvent_SubLoopEnd 0x02071A5C This empties asm/main_0207199C.s and asm/main_02071A1C.s, so both files and their .inc are removed rather than split, and the handlers merge into the adjacent sources added by the previous commit. EndTrack confirms the second parameter's type, which the previous commit could only infer from the dispatcher: it writes 1 to the byte at offset 3 of that argument, which is field_0x0.has_looped in struct dse_sequence. A track that reaches the end of its main loop setting has_looped is consistent, and no other struct in dse.h places a byte with that meaning at offset 3. SubLoopBegin and SubLoopEnd index track->loop_stack, the existing struct dse_sub_loop[4] at offset 0x24 with a 12-byte stride, which is what the asm's multiply by 0xc computes. SubLoopEnd needed two changes past the obvious form. Its index and count locals are int, not u8: at byte width the compiler inserts and rX, rX, #0xff after each decrement, which the target does not have. And the early return has to be the fall-through path -- written as an early return the compiler if-converts the tail into predicated stores, where the target branches with bxeq lr. Inverting the condition, so the longer body sits inside the if, produces the branch. DseVoice_CountNumActiveInChannel and DseChannel_DeallocateVoices are still asm; their prototypes are provisional and declared in this file's header. Neither was declared anywhere else in the tree. No comments are added to any pmd-sky file. Authored by Claude (Opus 5) under human direction. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. Co-Authored-By: Claude Opus 5 --- asm/include/main_0207199C.inc | 3 --- asm/include/main_02071A1C.inc | 1 - asm/main_0207199C.s | 44 ----------------------------------- asm/main_02071A1C.s | 43 ---------------------------------- include/main_0207191C.h | 5 ++++ include/main_02071A14.h | 2 ++ main.lsf | 2 -- src/main_0207191C.c | 25 ++++++++++++++++++++ src/main_02071A14.c | 30 ++++++++++++++++++++++++ 9 files changed, 62 insertions(+), 93 deletions(-) delete mode 100644 asm/include/main_0207199C.inc delete mode 100644 asm/include/main_02071A1C.inc delete mode 100644 asm/main_0207199C.s delete mode 100644 asm/main_02071A1C.s diff --git a/asm/include/main_0207199C.inc b/asm/include/main_0207199C.inc deleted file mode 100644 index 9ae0e81b..00000000 --- a/asm/include/main_0207199C.inc +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once -.public DseChannel_DeallocateVoices -.public DseVoice_CountNumActiveInChannel diff --git a/asm/include/main_02071A1C.inc b/asm/include/main_02071A1C.inc deleted file mode 100644 index 6f70f09b..00000000 --- a/asm/include/main_02071A1C.inc +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/asm/main_0207199C.s b/asm/main_0207199C.s deleted file mode 100644 index ab82df9e..00000000 --- a/asm/main_0207199C.s +++ /dev/null @@ -1,44 +0,0 @@ - .include "asm/macros.inc" - .include "main_0207199C.inc" - - .text - - arm_func_start DseTrackEvent_WaitUntilFadeout -DseTrackEvent_WaitUntilFadeout: ; 0x0207199C - stmdb sp!, {r3, r4, r5, lr} - mov r5, r0 - mov r0, r3 - mov r4, r2 - bl DseVoice_CountNumActiveInChannel - cmp r0, #0 - ldrgtb r0, [r5], #-1 - addle r5, r5, #1 - strgt r0, [r4, #0xc] - mov r0, r5 - ldmia sp!, {r3, r4, r5, pc} - arm_func_end DseTrackEvent_WaitUntilFadeout - - arm_func_start DseTrackEvent_EndTrack -DseTrackEvent_EndTrack: ; 0x020719C8 - stmdb sp!, {r4, lr} - ldr ip, [r2, #0x20] - mov r4, r0 - cmp ip, #0 - bne _020719F4 - mov r1, #0 - mov r0, r3 - strb r1, [r2, #2] - sub r4, r4, #1 - bl DseChannel_DeallocateVoices - b _02071A0C -_020719F4: - ldrh r3, [r2, #0xa] - mov r0, #1 - add r3, r3, #1 - strh r3, [r2, #0xa] - strb r0, [r1, #3] - ldr r4, [r2, #0x20] -_02071A0C: - mov r0, r4 - ldmia sp!, {r4, pc} - arm_func_end DseTrackEvent_EndTrack diff --git a/asm/main_02071A1C.s b/asm/main_02071A1C.s deleted file mode 100644 index 3540365d..00000000 --- a/asm/main_02071A1C.s +++ /dev/null @@ -1,43 +0,0 @@ - .include "asm/macros.inc" - .include "main_02071A1C.inc" - - .text - - arm_func_start DseTrackEvent_SubLoopBegin -DseTrackEvent_SubLoopBegin: ; 0x02071A1C - stmdb sp!, {r4, lr} - ldrb r4, [r2, #6] - mov r1, #0xc - ldrb lr, [r0], #1 - smulbb r1, r4, r1 - add r3, r2, #0x24 - str r0, [r3, r1] - add ip, r3, r1 - mov r1, #0 - str r1, [ip, #4] - strb lr, [ip, #8] - ldrb r3, [r2, #4] - add r1, r4, #1 - strb r3, [ip, #9] - strb r1, [r2, #6] - ldmia sp!, {r4, pc} - arm_func_end DseTrackEvent_SubLoopBegin - - arm_func_start DseTrackEvent_SubLoopEnd -DseTrackEvent_SubLoopEnd: ; 0x02071A5C - ldrb ip, [r2, #6] - add r3, r2, #0x24 - mov r1, #0xc - sub ip, ip, #1 - mla r3, ip, r1, r3 - ldrb r1, [r3, #8] - subs r1, r1, #1 - streqb ip, [r2, #6] - bxeq lr - str r0, [r3, #4] - strb r1, [r3, #8] - ldrb r0, [r3, #9] - strb r0, [r2, #4] - ldr r0, [r3] - bx lr - arm_func_end DseTrackEvent_SubLoopEnd diff --git a/include/main_0207191C.h b/include/main_0207191C.h index 2ea455e6..071acbec 100644 --- a/include/main_0207191C.h +++ b/include/main_0207191C.h @@ -3,11 +3,16 @@ #include "dse.h" +s32 DseVoice_CountNumActiveInChannel(struct dse_channel* channel); +void DseChannel_DeallocateVoices(struct dse_channel* channel); + u8* DseTrackEvent_Invalid(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel); u8* DseTrackEvent_WaitSame(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel); u8* DseTrackEvent_WaitDelta(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel); u8* DseTrackEvent_Wait8(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel); u8* DseTrackEvent_Wait16(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel); u8* DseTrackEvent_Wait24(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel); +u8* DseTrackEvent_WaitUntilFadeout(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel); +u8* DseTrackEvent_EndTrack(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel); #endif diff --git a/include/main_02071A14.h b/include/main_02071A14.h index 8d60902a..23b64b82 100644 --- a/include/main_02071A14.h +++ b/include/main_02071A14.h @@ -4,5 +4,7 @@ #include "dse.h" u8* DseTrackEvent_MainLoopBegin(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel); +u8* DseTrackEvent_SubLoopBegin(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel); +u8* DseTrackEvent_SubLoopEnd(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel); #endif diff --git a/main.lsf b/main.lsf index f1fc03fb..c6d2bfe2 100644 --- a/main.lsf +++ b/main.lsf @@ -253,9 +253,7 @@ Static main Object src/main_0206C98C.o Object asm/main_0206C9BC.o Object src/main_0207191C.o - Object asm/main_0207199C.o Object src/main_02071A14.o - Object asm/main_02071A1C.o Object lib/DSE/src/main_02071A98.o Object lib/DSE/asm/main_02071AC0.o Object lib/DSE/src/main_02071BF4.o diff --git a/src/main_0207191C.c b/src/main_0207191C.c index 113d1551..0591eeef 100644 --- a/src/main_0207191C.c +++ b/src/main_0207191C.c @@ -41,3 +41,28 @@ u8* DseTrackEvent_Wait24(u8* position, struct dse_sequence* seq, struct dse_trac track->wait_ticks_left = track->previous_wait_ticks; return position; } + +u8* DseTrackEvent_WaitUntilFadeout(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel) +{ + if (DseVoice_CountNumActiveInChannel(channel) > 0) { + track->wait_ticks_left = *position; + position--; + } else { + position++; + } + return position; +} + +u8* DseTrackEvent_EndTrack(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel) +{ + if (track->loop_start == NULL) { + track->is_playing = FALSE; + position--; + DseChannel_DeallocateVoices(channel); + } else { + track->main_loop_count++; + seq->field_0x0.has_looped = TRUE; + position = track->loop_start; + } + return position; +} diff --git a/src/main_02071A14.c b/src/main_02071A14.c index 0897e298..dc93343b 100644 --- a/src/main_02071A14.c +++ b/src/main_02071A14.c @@ -5,3 +5,33 @@ u8* DseTrackEvent_MainLoopBegin(u8* position, struct dse_sequence* seq, struct d track->loop_start = position; return position; } + +u8* DseTrackEvent_SubLoopBegin(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel) +{ + u8 idx = track->loop_stack_index; + u8 count = *position++; + struct dse_sub_loop* loop = &track->loop_stack[idx]; + + loop->start = position; + loop->end = NULL; + loop->count = count; + loop->octave = track->current_octave; + track->loop_stack_index = idx + 1; + return position; +} + +u8* DseTrackEvent_SubLoopEnd(u8* position, struct dse_sequence* seq, struct dse_track* track, struct dse_channel* channel) +{ + int idx = track->loop_stack_index - 1; + struct dse_sub_loop* loop = &track->loop_stack[idx]; + int count = loop->count - 1; + + if (count != 0) { + loop->end = position; + loop->count = count; + track->current_octave = loop->octave; + return loop->start; + } + track->loop_stack_index = idx; + return position; +}