mirror of
https://github.com/pret/pmd-sky.git
synced 2026-09-28 21:31:17 -05:00
f85044d37f07201e824cba7b6188cef2bbeac6fb
1509 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f85044d37f |
Drop 49 unneeded util.h includes from generated headers
The landing script added `#include "util.h"` to every header it generated, across this whole branch. That was never necessary for most of them: u8/u32/s32 and the rest of the base types are typedef'd in lib/include/nitro/types.h, which every translation unit already has through `-prefix global.mch`. 283 of the 460 headers in the tree that name u32 do not include util.h and build fine. util.h owns bool8, bool32, fx32_8, ufx32_8 and struct fixed_point/rgba/vec2_16 -- a header naming any of those genuinely needs it, and 61 of the 110 do. The other 49 carried it for nothing and are cleaned up here. Removal is .c-aware: util.h is kept wherever the header's paired source names a util.h-owned symbol and does not include util.h itself, so nothing loses it transitively. No functional change; verified byte-identical. 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 <noreply@anthropic.com> |
||
|
|
a6ce70e56b |
Decomp 50 functions in five themed groups
Fourth 5x10 batch.
overlay-11 shop/menu loaders 10 LoadCroagunkSwapShopOverlay .. ov11_0230CE1C
animation-table getters 10 ov10_022BFE54 .. ov10_022BFF30
move-animation flag readers 10 ov10_022BFD58 .. ov10_022BFE3C
overlay_01 menu accessors 10 ov01_0233755C .. ov01_02337624
sound veneers + playing checks 10 sub_02017B70 .. IsMePlaying
None carries a region conditional -- checked per function, not per file -- so US
alone verifies this commit. Four destination files, one .s split in total.
A bitfield read is not the same as the equivalent shift expression. Dwci_Entry-
style `(x << 28) >> 28` is folded by MWCC into `and #0xF`, while the target keeps
both shifts; declaring the member `u32 f : 4` emits them. That finding came from
the overlay_02 group, which is NOT in this commit -- see below.
GetMoveAnimation returns a 0x18-byte element of MOVE_ANIMATION_INFO. The five
flag readers in the third group index field_0x8 of that same element, so both
groups share one struct move_anim_info rather than the placeholder the flag
readers were first written against; all seven were re-scored against the unified
type.
ov10_022BFE6C needs `if (cond) { ...; return TRUE; } return FALSE;` -- the
inverted arrangement predicates the pointer load instead of branching (1100).
A sixth group of ten (Dwci_ChangeScene .. Dwci_Language__02339674, overlay_02)
matched at score 0 and is NOT landed. Extracting from asm/overlay_02.s breaks
OVY_2's checksum on its own: bisecting to a single three-instruction function
still fails, so the C is not implicated. Splitting that file also leaves four
symbols (SoAlloc, SoFree, ov02_0232FD28, ov02_0232FD40) undeclared in the tail,
which the stock extract_function.py does not carry across. Left for a separate
investigation.
Authored by Claude (Opus 5) under human direction. All fifty verified at score 0.
Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
c34d1196f2 |
Decomp 50 functions in five themed groups
Third 5x10 batch: fifty located as five groups of ten before any matching, all fifty matched, one build, one commit. Dwci account bitfield accessors 10 Dwci_Acc_SetMaskBits .. Dwci_Acc_GetFlags overlay-11 menu/overlay loaders 10 ov11_0230CB88 .. LoadRecycleShopOverlayResume _020B0B6C accessors + copies 10 sub_0206C0D8 .. sub_0206C19C overlay-11 veneers 10 ov11_022E9A78 .. ov11_022E9B5C main_02065C84 wrappers 10 sub_020663C8 .. sub_020664AC Each group is a contiguous run, costing one .s split apiece. None of the fifty carries a region conditional -- checked per function, not per file -- so US alone verifies this commit. The two 8-byte copy loops need an UNSIGNED counter. With s32, `--n != 0` emits sub followed by cmp and scores 505; with u32 it fuses into the target's single subs. A struct assignment through a cast also scores 0 but needs a new type. ov11_0230CB88 passes an argument to EntryOverlay13, which this tree already has decompiled and matching as `void EntryOverlay13(void)`. Dropping the argument scores 220 -- the target saves r0 into r4 across the InitMenu call specifically to pass it. Retail's caller evidently had a prototype its definition did not match; reproducing that needs the two declarations to disagree across translation units, so this file declares `extern void EntryOverlay13(s32 a);` locally. Dwci_Acc_GetUserId and Dwci_Acc_GetFriendKey return 64-bit values; the tell is the pair of no-op `orr rX, rX, #0` instructions MWCC emits assembling a u64 across r0/r1. GetUserId's high half is field_0x0 masked to 0x7FF, which agrees with Dwci_Acc_SetUserId passing that same mask to Dwci_Acc_SetMaskBits. New placeholder structs: unk_022DB0E0, unk_020B0B70, unk_02388FC0, unk_023890A0. Authored by Claude (Opus 5) under human direction. All fifty verified at score 0. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e865b69791 |
Decomp 49 functions in five themed groups
Second 5x10 batch: located as five groups of ten before any matching, then all matched, then one build, then one commit. inventory menu window accessors 10 ov10_022BCC7C .. ov10_022BCDBC file/ROM transfer + bag init 10 FileRom_StopDataTransfer .. sub_0200CAE4 overlay_16 + secret bazaar 10 ov16_0238CC94 .. TalkToSecretBazaarNpcWithYesNoMenu Gt2 socket/connection accessors 10 Gt2GetConnectionState .. Gt2SetConnectionData forwarding veneers at +4 9 sub_0202613C .. sub_020261E4 Each group is a contiguous run, which costs one .s split apiece rather than one per function: after the first extraction the next function is at the head of the remainder and merges into the source just created. None of the 49 carries a region conditional -- checked per function, not per file -- so US alone verifies. GetDamageSource returns s16. The lsl #16 / asr #16 before its return is the return conversion, not a cast in the body; s16 return with an s32 parameter scores 0, while returning s32 and casting scores 510 in the shape the target does not use. ov29_022F05B4 needed its two arms in the other source order -- the fourth instance of MWCC letting the first arm written fall through. TalkToSecretBazaarNpcStandard and ov29_022F0618 differ only by `mov r3, #0` versus `mov ip, #0`. r3 is the fourth argument register: the Standard variant passes 0 for it, the other forwards its own. Same callee, different arity. IsInventoryMenuActive returns s32, not bool8 -- bool8 adds an and #0xff the target lacks. struct unk_0202AAA8's field_0xA4[0xF4] is split to expose field_0xF8. New placeholder structs: unk_020AF360, unk_0238CE40, unk_02026130, unk_0230E3E8 and unk_0230E420 (the Gt2 connection and socket are distinct types -- remote IP sits at offset 0, local IP at 4). A fiftieth was prepared and not landed: sub_0202614C stands at 300. The target materialises &v into r3 before the first store and moves it to r1; six spellings (struct by value, a pointer local, storing through the pointer, an array, a reversed store order, a hoisted destination) all compute the address after the stores instead. Authored by Claude (Opus 5) under human direction. All 49 verified at score 0. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
7658e4f92e |
Decomp 50 functions in five themed groups
Located as five groups of ten before any matching was attempted, then all fifty matched, then one build, then one commit. overlay_04/06 global accessors 10 ov04_0233CA80 .. ov06_0233CAA8 hardware register bit-fields 10 sub_02009BE8 .. sub_02009D20 save reset / play timer 10 sub_020483B8 .. sub_0204F9E0 sound veneers + window accessors 10 sub_02017C90 .. sub_02030A74 dungeon fixed-room / item 10 CloseFixedBin .. GenerateStandardItem Every group is a contiguous run at a file head or tail, so extract_function merges each function into an adjacent source instead of splitting a .s. None of the fifty carries a region conditional -- checked per function, not per file -- so US alone verifies this commit. Twelve of the fifty are interworking tail-call veneers (ldr ip, =f; bx ip). That falls straight out of an ordinary forwarding call, and survives both argument reordering (GenerateStandardItem) and a computed argument (sub_020483B8). Nothing in the tree had a veneer decompiled, so the shape was proven on one before the other forty-nine were written. Their parameter lists are guesses: a veneer forwards registers untouched, so the emitted code is identical for any arity and the match constrains nothing. sub_020483D8 returns its callee's result. It sat at 40 through five spellings with the pointer one register low; the target never reuses r0 after the call because that value is the return value. Adding `return ok;` gives 0, and the return is invisible in the asm because the value is already in place. Two type corrections found by probing: the Are*Allowed family compares the dungeon id unsigned (bcc, not blt -- 200 signed), and the register setters need a u32 intermediate, since a u16 local forces a lsl/lsr truncation the target lacks (615). New placeholder structs: unk_0233F660, unk_0233EEE0, unk_020AFEF4, unk_02030A50. src/main_02017C80.c's existing PlaySeByIdVolume(s32, s32) declaration is kept in preference to this commit's; both affected functions were re-scored against it and still match. Authored by Claude (Opus 5) under human direction. All fifty verified at score 0. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5ffad87a1b |
Decomp five leftover single-function asm files
Eleventh cleanup sweep. Five asm files and their includes removed: asm/main_0205B6CC.s sub_0205B6CC asm/main_0202C75C.s sub_0202C75C asm/overlay_29_0232CDA4.s DoMoveOneShot asm/overlay_29_0232A078.s DoMoveNightShade asm/overlay_29_023016D8.s DisplayRunAwayIfTriggered All five merged into an adjacent source rather than splitting one. None carries a region conditional, so US alone verifies this commit. sub_0205B6CC is a 64-bit unsigned >= 2 (cmp/cmpeq/movhs) on a value at offset 0xC. A u64 member sits there: MWCC aligns long long to 4, not 8. Rebuilding the value from two u32s scores 200, and `> 1` in place of `>= 2` scores 310. sub_0202C75C uses struct unk_0202C5E0, the collection-menu window struct its neighbours already use; GetWindowIdSelectedMenuItemIdx immediately before it already spells the same `GetWindowContents(window_id) + 4`. field_0x1AC[6] covered 0x1B0/0x1B1 and is split into three members. DoMoveOneShot and DoMoveNightShade are twins staging eleven arguments for CalcDamageFixedWrapper, which had no declaration in the tree. The only obstacle was the temporary holding GetMoveType's result: as enum type_id, -enum min sizes it to a byte and emits an and #0xff the target lacks (950); as s32, 0. DisplayRunAwayIfTriggered needs Min(999, max_hp), not Min(max_hp, 999) -- Min is a static inline, so the argument order is not free (200). That exact expression in that exact order already sat in the NONMATCHING block of AiMovement in dungeon_ai_movement.c; the guess was right and had never been confirmed. include/main_02042AF8.h's provisional `s32 sub_0202C75C(s8 a);` is retired in favour of the real header. It was written from the one call site, which passes an s8 field; the parameter is a window id. A sixth was prepared and not landed: FixedPoint64ToInt (asm/main_02001CB0.s) stands at 225. The target keeps an arithmetically redundant & 0xFFFF0000, and whether MWCC folds it away is decided by which side of the | the masked term is written on -- masked second folds it (735), masked first keeps it (225). Writing it first is also what makes it evaluate first, and the target needs it preserved but evaluated second; ten spellings found none that does both. Spelling it as a real 64-bit shift scores 1020. Authored by Claude (Opus 5) under human direction. All five verified at score 0. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
159235da43 |
Decomp five leftover single-function asm files
Tenth cleanup sweep. Five asm files and their includes removed:
asm/overlay_29_0232CE7C.s DoMoveReviver
asm/overlay_29_02327940.s DoMoveRapidSpin
asm/overlay_29_022EFA74.s TryActivateIqBooster
asm/main_02027AA0.s sub_02027AA0
asm/main_020568DC.s sub_020568DC
All five merged into an adjacent source rather than splitting one. Four of the
five carry a region conditional, so all three ROMs were built; sub_020568DC is
the exception and US alone would have covered it.
TryActivateIqBooster sat at 60 with r6/r7/r8 rotated one place and every
differing row an r-marked register swap. Moving the IQ local's declaration ahead
of the other two takes it to 0. This contradicts the MATCHING_TIPS entry claiming
declaration order never moves callee-saved assignment; that measurement was on
SetLeaderAction's ~75 locals, where register pressure decides the colouring. On
four locals with no pressure, first-definition order is what is left.
DoMoveRapidSpin sets its return to 1 before the random-outcome call, so a failed
random check still returns TRUE. The early-return spelling scores 570; a result
variable set inside the damage branch scores 0.
sub_02027AA0's region difference is not an offset shift: JP writes slot 3 where
the others write slot 0 and vice versa, mirrored for the second case. The rodata
a few symbols away corroborates it -- _020AFD94 and _020AFD98 are defined in
swapped order under the same #ifdef.
sub_020568DC follows GetAppointedLeaderMemberIdx, which lives in the file it
merged into and is the same function specialised to the active team. The
(&t->number_active_team_members_main)[team] idiom is already used by three
existing files.
DoMoveReviver was on the stalled list from
|
||
|
|
19c62d4b1f |
Decomp five leftover single-function asm files; fix three stale declarations
Ninth cleanup sweep. Five asm files and their includes removed: asm/overlay_29_0231E990.s ShouldTryEatItem asm/overlay_29_0232D378.s DoMoveGuardSwap asm/overlay_29_0232A490.s DoMoveSwallow asm/overlay_29_02329674.s DoMoveHelpingHand asm/main_0205B738.s sub_0205B738 All five merged into an adjacent source rather than splitting one. Three declarations the tree already carried are contradicted by these bytes and are corrected here, touching five files this sweep did not otherwise decompile: SubstitutePlaceholderStringTags took `u8 *string_id` in four files and `int a` in a fifth. DoMoveGuardSwap passes a literal 1, which no pointer parameter can take without a cast; the existing call sites all passed 0, which is why nothing caught it. The four are now s32, agreeing with the one that was already an integer. TryIncreaseHp took `s16 hp` in two files. DoMoveSwallow loads its argument from a word array and passes it untouched -- s16 inserts a sign extension and scores 210, s32 scores 0. The two existing call sites load s16 data with ldrsh, so the value is already extended and the wider declaration is byte-neutral for them. ShouldTryEatItem's parameter is signed: the range check emits blt/ble, while enum item_id under -enum min compares unsigned and scores 400. s16 matches the adjacent IsItemValidVeneer and every caller's ldrsh. DoMoveSwallow also needed its two arms in the other source order, the same rule as sub_02009DCC last sweep: MWCC lets the first arm written fall through. sub_0205B738's copy at +0xB0 is element [1] of struct0, not a member: 0xB0 is sizeof(struct unkStruct_020B0A54), as sub_0205B77C (a * 176 + ...) and sub_0205B7C8 (MemsetSimple(..., 0xB0)) already say. Reading it as a member and appending one scored 0 on a scratch but changed the struct's size, and with it the stride in three neighbours and the copy length in a fourth -- 29 binaries moved. No header change is needed; the array spelling also scores 0. Three of the five log a message whose id differs between US and JP by no constant offset, so each is a file-scope #ifdef JAPAN define, as dungeon_ai.c and dungeon_projectile_throw.c already do. Authored by Claude (Opus 5) under human direction. All five verified at score 0. Three carry region conditionals, so this was confirmed by matching builds of all three ROMs: US, EU and JP. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
8cfb04e1a4 |
Decomp five leftover single-function asm files
Eighth cleanup sweep. Five asm files and their includes removed:
asm/overlay_29_0230F840.s TeamMemberHasExclusiveItemEffectActive
asm/overlay_29_023276E8.s DoMoveTickle
asm/overlay_29_0232C538.s DoMoveSwitchPositions
asm/overlay_29_022FF8C8.s GetMobilityTypeAfterIqSkills
asm/overlay_29_0233861C.s UpdateShouldBoostHiddenStairsSpawnChance
All five merged into an adjacent source rather than splitting one.
DoMoveTickle was the stall recorded on
|
||
|
|
4d2a484c28 |
Decomp five leftover single-function asm files
Seventh cleanup sweep. Five asm files and their includes removed: asm/overlay_29_0232E400.s DoMoveWakeUpSlap asm/main_0204317C.s FreeUnkStorageStruct0x18c0 asm/main_02009DCC.s sub_02009DCC asm/main_020018A4.s sub_020018A4 asm/main_0200C4CC.s sub_0200C4CC All five merged into an adjacent source rather than splitting one, so the sweep removes five files and adds none. DoMoveWakeUpSlap doubles the damage multiplier when the target is in any of the three sleep-class states, then ends the status. EndSleepClassStatus takes five arguments here, not four: the target loads r2=0, r3=1 and pushes a third flag on the stack. sub_020018A4 rounds a 64-bit value up to the next multiple of 0x100 and returns the high 56 bits. The `and r2, r1, #0` that opens it is the high half of a 64-bit `x & 0xFF`, not a separate test. sub_02009DCC clears one bit of a 5-bit mask per non-zero entry in five byte arrays at stride 5, then merges it into DISPCNT for the requested engine. The zero-engine arm has to come first in the source or the wrong arm is predicated. sub_0200C4CC copies 232 bytes out of _02094C18, whose size is fixed by the gap to _02094D00. Field types forced by the access widths in main_02042AF8.h: struct unk_02043148's field_0x0 becomes s32 and field_0x7D5 splits into two s8s plus padding; struct unk_020AFEE0's field_0xC becomes s32, which was the last differing row in FreeUnkStorageStruct0x18c0. struct unk_02094C18 is new. Its member is u32[0x3A] rather than u8[0xE8] because the copy's alignment, and so its instruction shape, comes from the member type. Authored by Claude (Opus 5) under human direction. All five verified at score 0. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
658a92a802 |
Decomp four leftover single-function asm files
Sixth cleanup sweep. Four asm files and their includes removed: asm/overlay_29_02328A74.s DoMoveDamagePoison40 asm/overlay_29_02329FE0.s DoMoveMudSlap asm/overlay_29_0232B820.s DoMoveMistBall asm/main_0200F18C.s GetEquivItemIndex The three move effects share DoMoveBubble's shape: deal damage, and on a random outcome apply a secondary effect, returning whether damage landed rather than whether the effect did. The result variable doubles as an argument in two of them -- MistBall passes it as both the stage count and the checkProtected flag, MudSlap passes 0 as the chance. GetEquivItemIndex walks the 50 bag slots with a cursor, testing each item's exists flag as `(flags & 1) != 0` so the boolify emits tst/movne/moveq, and returns the index of the first equivalent item or -1. A fifth was prepared and not landed: GetNextIqSkill (asm/main_02058F24.s) sits at 30, the whole difference being that the target keeps its skill-list cursor in lr where the candidate uses r5. Four spellings tried -- hoisting the value local, moving the cursor declaration, a group temporary, and a while loop -- all 30 or worse. Authored by Claude (Opus 5) under human direction. All four verified at score 0. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
78b52f9d63 |
Decomp five more leftover single-function asm files
Fifth cleanup sweep; five more asm files and their includes removed: asm/overlay_29_023491C4.s IsOutlawOrChallengeRequestFloor asm/main_0202AAE8.s sub_0202AAE8 asm/main_0202BC60.s sub_0202BC60 asm/overlay_29_023261A0.s DoMoveBubble asm/main_0205BCC4.s sub_0205BCC4 sub_0202AAE8 and sub_0202BC60 are the same function over different window states: check unk_0202AAA8::field_0x19C against a set, then set two flags, clear field_0x1A4, call sub_0202830C with -5 and advance the state. Both write a byte at 0x1A1 that the struct covered only as padding after field_0x1A0, so that gap is now named field_0x1A1 with field_0x1A2[2] holding the remainder -- same total size. Three spellings that mattered: - IsOutlawOrChallengeRequestFloor is three ORed predicates and only matches with each operand written `!= 0`; a plain || scores 300 and early returns 1300. - DoMoveBubble returns whether damage was dealt, not whether the speed drop landed, so the result is funnelled through one variable which is also passed as LowerSpeed's stage count. - sub_0205BCC4 must not hoist the destination pointer above its NULL check; a local shared by both branches scores 830, one declared inside the else branch matches. Authored by Claude (Opus 5) under human direction. All five verified at score 0. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
901ba2aa8f |
Decomp five more leftover single-function asm files
Fourth cleanup sweep; five more asm files and their includes removed: asm/overlay_29_0232B8E4.s DoMoveCalmMind asm/overlay_29_0232D22C.s DoMoveHammerArm asm/overlay_29_023495E8.s IsDestinationFloorWithFleeingOutlaw asm/overlay_29_023492D4.s IsLegendaryChallengeFloor asm/main_02030850.s CloseAdvancedTextBox2 The two mission predicates merged into files that already declared IsCurrentMissionType and IsCurrentMissionTypeExact with enum mission_type parameters, so they use those declarations and the MISSION_* enumerators rather than fresh externs with integer types. IsLegendaryChallengeFloor's floor check is a byte subtraction written `+ 0xFF`, the same encoding DoMoveGust needed. Both predicates only match written as a nested `if` that falls through to a single return; the early-return spellings score 610 and 405. CloseAdvancedTextBox2 uses the existing sub_0202836C, sub_0202812C, DeleteWindow and MemFree declarations; only sub_020288DC needed a provisional extern. Authored by Claude (Opus 5) under human direction. All five verified at score 0. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
0587a6efcb |
Correct SetActionUseMovePlayer's parameter types; retire the last stale extern
The previous commit left src/overlay_29_022F0EDC.c carrying a provisional
`extern s32 SetActionUseMovePlayer();` because replacing it with the real header
broke three modules. The cause was not the return type, which is void, but the
parameters: the function was landed as (struct action_data*, u8, u8), and a u8
parameter makes every caller truncate.
SetLeaderAction's call site in retail passes GetTeamMemberIndex's result
unchanged and sign-extends the move index to 16 bits:
mov r1, r0
mov r2, r4, lsl #0x10
mov r2, r2, asr #0x10
bl SetActionUseMovePlayer
so the parameters are s32 and s16. The callee's own body cannot distinguish
u8, s16 or s32 -- it stores both with strb, and all three score 0 against it --
which is why the wrong types went unnoticed when it was landed.
With (struct action_data*, s32, s16) both functions match and the provisional
extern is deleted in favour of the header, leaving one declaration in the tree.
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 <noreply@anthropic.com>
|
||
|
|
ec25edd9dd |
Decomp five more leftover single-function asm files
Third cleanup sweep; five more asm files and their includes removed: asm/overlay_29_023021F0.s UpdateIqSkillsWrapper asm/overlay_29_022EBC98.s SetActionUseMovePlayer asm/overlay_29_02349658.s ov29_02349658 asm/main_0205EBF0.s sub_0205EBF0 asm/overlay_29_022F52B0.s ov29_022F52B0 SetActionUseMovePlayer sets ACTION_USE_MOVE_PLAYER and then two action_parameters[].action_use_idx fields, using the enumerator and struct that already exist. sub_0205EBF0 indexes mission_deliver_list::unk18, the struct src/main_0205C73C.c already uses, rather than a fresh placeholder. NOT done, deliberately: src/overlay_29_022F0EDC.c still carries the provisional `extern s32 SetActionUseMovePlayer();`. Replacing it with an include of the real header, which declares the function void, breaks the ROM -- SetLeaderAction's match depends on the s32 form. The two declarations therefore still disagree. That is a real defect in one of the two, not a formality, and it is left alone rather than papered over; see the reasoning note. ov29_022F52B0 is a bare veneer with no argument setup, so its arity is not evidenced by anything and void(void) is a guess. Authored by Claude (Opus 5) under human direction. All five verified at score 0. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
80d0e710e0 |
Decomp five more leftover single-function asm files
Second cleanup sweep. Each was the only function left in its own asm file, so each removes an asm file and its include: asm/overlay_29_0234B0CC.s SetMessageLogPreprocessorArgsStringToName asm/overlay_29_023268CC.s DoMoveSmokescreen asm/overlay_29_02325F74.s DoMoveMorningSun asm/overlay_29_02326E20.s DoMoveGust asm/overlay_29_022EA980.s GenerateDungeonRngSeed Two needed a second reading: - DoMoveGust doubles the damage multiplier when the defender's bide_class_status.bide is 7 or 8. The target tests it as a byte with `add #0xF9`, so the source adds 0xF9 rather than subtracting 7; `- 7` compiles to `sub #7` and does not match. - GenerateDungeonRngSeed runs the LCG twice, stores the second result back to prng_state::preseed, and returns the two halves recombined. The operand order in the final or-expression decides whether the mask or the shift is scheduled first; taking the shifted half first matches. Authored by Claude (Opus 5) under human direction. All five verified at score 0. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b088fd5f27 |
Decomp five leftover single-function asm files
Each of these was the only function left in its own asm file -- fragments left behind when earlier work split a larger file around them. Decompiling them removes five asm files and their includes outright: asm/main_0204FD38.s IncrementNbSteals asm/overlay_29_022EAC78.s ov29_022EAC78 asm/overlay_29_0234B010.s ov29_0234B010 asm/main_0202BCDC.s IsAdvancedMenuActive asm/main_02030A2C.s SetWindowTitle IncrementNbSteals and ov29_022EAC78 are empty in retail -- a single bx lr. Their signatures are not evidenced by anything and are written void(void). IsAdvancedMenuActive reads unk_0202AAA8::field_0x1A0, the same field and the same shape as CheckParentMenuField0x1A0 next door. SetWindowTitle writes a halfword at offset 0x20 of the same struct, which was inside the opaque field_0x9[0x97] placeholder. That array is split into field_0x9[0x17] / u16 field_0x20 / field_0x22[0x7E] -- same total size, and nothing indexed the placeholder. Authored by Claude (Opus 5) under human direction. All five verified at score 0. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
25d5994bdf |
Decomp ten dungeon utilities; drop a provisional GetLeaderMonster extern
GetLeaderMonster, SetDungeonRngPreseed, GetDungeonRngPreseed, SetDungeonRngPreseed23Bit, FindClosestUnoccupiedTileWithin2, FindFarthestUnoccupiedTileWithin2, FindUnoccupiedTileWithin3, FixedRoomActionParamToDirection, ov29_022E9FC0 and ov29_022E9FD0. The three preseed accessors read and write prng_state::preseed at offset 8, using the struct dg_random.h already defines. SetDungeonRngPreseed23Bit sets bit 0 and masks the top byte, which is where its name comes from. GetLeaderMonster merged into dg_uty.h alongside GetLeader, so the provisional `extern struct monster *GetLeaderMonster();` that src/overlay_29_022F0EDC.c carried is removed -- that file already includes dg_uty.h, which now declares it properly with a (void) parameter list. The three FindNearbyUnoccupiedTile wrappers pass a displacement table and a count (0x19 within 2, 0x31 within 3). That helper and its tables are undeclared in the tree, so their prototypes are written from these call sites and are provisional. Authored by Claude (Opus 5) under human direction. All ten verified at score 0. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
185c390e56 |
Decomp ten message-log accessors in overlay_29
SetMessageLogGroupStartFlag, GetMessageLogPreprocessorArgs, InitMessageLogPreprocessorArgs, SetMessageLogPreprocessorArgsFlagVal, SetPreprocessorArgsIdVal, SetMessageLogPreprocessorArgsNumberVal, SetMessageLogPreprocessorArgsString, SetMessageLogPreprocessorArgsSpeakerId, SetMessageLogPreprocessorArgsSpeakerId0x30000 and ov29_0234AFFC. All reach a preprocessor-argument block through MESSAGE_LOG_INFO, a 12-byte global holding a flag byte and a pointer. The block is the existing struct preprocessor_args from main_0200C4FC.h: its member offsets -- id_vals at +0x10, number_vals at +0x24, strings at +0x38, speaker_id at +0x4C -- land exactly on the asm's 0xCAC, 0xCC0, 0xCD4 and 0xCE8 relative to the 0xC9C base. Ten independent accessors agreeing with that layout is corroboration of the existing struct rather than a new claim. The global itself gets a placeholder, struct unk_023537CC, named for its address; only its flag byte and pointer are known. Authored by Claude (Opus 5) under human direction. All ten verified at score 0 (eleven candidates matched; ten landed). Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
1bcd98523f |
Decomp the eight stat helpers deferred last batch; make StatIndex globals const
The previous commit dropped eight functions whose only difference from the target was instruction order: retail loads the stat global before materialising the constant destined for the stack, the candidate after. The cause is aliasing. Declared as plain externs, MWCC must assume the stores to [sp] can affect the global, so the load cannot move above them. Declaring the globals const frees it, and all eight match: DoMoveGrowl, DoMoveLowerDefense1, DoMoveFeatherDance, DoMoveFakeTears, DoMoveMetalSound, DoMoveScreech, DoMoveCharm and DoMoveHealOrder. Also LogMessageQuiet and LogMessageWithPopup, which pass FALSE/TRUE to LogMessage. Every existing `extern struct StatIndex` in src/ is const-ified to match, since the globals cannot be const in one translation unit and not another. Thirteen files touched; the functions already landed against them still match, which is independent confirmation of the reading. DoMoveMetalSound lowers by 3 stages, not the 2 assumed when it was first written; the asm says `mov r3, #3`. Authored by Claude (Opus 5) under human direction. All ten verified at score 0. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
c433875956 |
Decomp 42 small dungeon-mode functions in overlay_29
Landed as one batch after verifying every function individually, rather than in groups of ten. Five clusters: - Sound and effect veneers that tail-call a shared helper with fixed ids: PlaySeByIdIfShouldDisplayEntity, PlayEffectAnimationPos, PlayEffectAnimationPixelPos, ChangeMonsterAnimation and ov29_022E67E4. - Four DoMoveDamage__* wrappers plus DoMoveVacuumCut, all `return DealDamage(...) != 0`. - DoMoveExpose, DoMoveSport, DoMoveMirrorMove, DoMoveMiracleEye, DoMoveNightmare, DoMoveSureShot, DoMoveFeint and DoMoveRockPolish, which branch or sequence two calls rather than forwarding once. - Minimap byte accessors over GetMinimapData, and GetTileTerrain. - Wrappers whose argument setup evidences the callee arity: ShouldDisplayEntityWrapper, UseSingleUseItemSelf, CalcSpeedStageWrapper, GenerateCleanItem and three ov29_* forwarders. Eight further candidates were prepared and are deliberately NOT included: DoMoveHealOrder, DoMoveScreech, DoMoveCharm, DoMoveGrowl, DoMoveLowerDefense1, DoMoveFakeTears, DoMoveFeatherDance and DoMoveMetalSound. Each passes a constant on the stack to a six-argument stat helper, and each differs from the target only in instruction *order*: retail loads the stat global before materialising the constant, the candidate after. Same instructions, same count. They stay in asm. Authored by Claude (Opus 5) under human direction. All 42 verified at score 0 individually before landing; confirmed together by a single matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
6174b66bdb |
Decomp nine more move effects and DebugRecruitingEnabled
DoMoveLowerAccuracy1, DoMoveSweetScent, DoMoveNastyPlot, DoMoveSwordsDance, DoMoveTailGlow, DoMoveBlowback, DoMoveHiddenPower, DoMoveDecoy, DoMovePsychoShift and DebugRecruitingEnabled. Five more stat handlers use the StatIndex helpers from move_orb_effects.h. The rest depart from the template: - DoMoveBlowback passes the attacker's own action.direction, read through GetEntInfo. - DoMoveHiddenPower forwards move and item_id to DealDamage with a 0x100 multiplier, its fifth argument on the stack. - DoMoveDecoy passes three constants, the last on the stack. - DoMovePsychoShift guards on attacker != defender before transferring. DebugRecruitingEnabled returns TRUE unconditionally; dungeon_recruitment.h already declares it, so the signature is not a guess. Authored by Claude (Opus 5) under human direction. All ten matched on the first candidate. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
ba4d07a4b1 |
Decomp ten stat-boost move effects; drop a conflicting Boost*Stat extern
DoMoveTag0x1AB, DoMoveDoubleTeam, DoMoveMinimize, DoMoveAmnesia, DoMoveBoostAttack1, DoMoveBoostDefense1, DoMoveBoostDefense2, DoMoveDefenseCurl, DoMoveGrowth and DoMoveFamish. Eight forward to BoostOffensiveStat / BoostDefensiveStat / BoostHitChanceStat with ATK_STAT_IDX or SPATK_STAT_IDX and a stage count. These take struct StatIndex by value, per move_orb_effects.h, which is why the asm loads the global's word into r2. src/overlay_29_0232E250.c declared those globals as s32 and BoostDefensiveStat with an (s32, s16) tail, both contradicting move_orb_effects.h. Since the two declarations lived in different translation units the compiler never saw the disagreement and the ROM still matched. Replaced with an include of the canonical header; DoMoveDefendOrder is unchanged and still matches. Authored by Claude (Opus 5) under human direction. All ten matched on the first candidate once the canonical StatIndex signature was used. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e029b3cbd6 |
Decomp the dungeon RNG mode setters and nine sound helpers in overlay_29
DungeonRngSetPrimary, DungeonRngSetSecondary and DungeonRngUnsetSecondary write prng_state::use_secondary and ::idx_secondary, using the struct dg_random.h already defines and the extern src/dg_random.c already uses. No new types. PlayLevelUpSound, PlayDungeonTipSound__022EB63C, PlayDungeonTipSound__022EB66C, ov29_022EAC9C and ov29_022EACAC each tail-call sub_02017C50 with a fixed id (1, 7, 7, 0, 5). PlaySeByIdIfNotSilence and PlayMeByIdIfNot998 guard on a sentinel before forwarding -- 0x3F00 and 998 respectively, the latter matching the name. sub_02017C74 keeps the signature src/overlay_25_init.c already declares for it. Authored by Claude (Opus 5) under human direction. All ten matched on the first candidate. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
14d9204c54 |
Decomp the last ten simple move-effect wrappers in overlay_29
DoMoveHealBlock, DoMoveEmbargo, DoMoveGravity, DoMoveMagnetRise, DoMoveTrickRoom, DoMovePowerTrick, DoMoveInvisify, DoMoveMetalBurst, DoMoveGrudge and DoMoveDamageStealItem. This exhausts the forward-and-return-TRUE family. Three depart from the template: - DoMoveInvisify passes the attacker as both arguments (mov r1, r0), so Invisify targets the user rather than the defender. - DoMoveGrudge and DoMoveDamageStealItem are tail calls rather than call-then-return-TRUE, so they are written `return f(...)`. DoMoveDamageStealItem forwards its own four arguments unchanged to DoMoveTakeaway, which is still asm. DoMoveMetalBurst passes 15 to SetReflectStatus, a third distinct value for that selector after 4 (Counter) and 10 (Rebound). Authored by Claude (Opus 5) under human direction. All ten matched on the first candidate. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
80e48105c3 |
Decomp ten more move-effect wrappers in overlay_29
DoMoveShocker, DoMoveOneRoom, DoMoveHurl, DoMoveMobile, DoMoveSeeStairs, DoMoveLongToss, DoMovePierce, DoMoveAquaRing, DoMoveGastroAcid and DoMoveLuckyChant -- the same forward-and-return-TRUE template as the previous batches. All ten helpers are undeclared in the tree and take provisional externs written from the call site. Authored by Claude (Opus 5) under human direction. All ten matched on the first candidate. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
edd80366e3 |
Decomp ten more move-effect wrappers in overlay_29
DoMoveRebound, DoMoveStayAway, DoMovePowerEars, DoMoveSlowDown, DoMoveSearchlight, DoMovePetrify, DoMovePounce, DoMoveTrawl, DoMoveDrought and DoMoveHpGauge. Two of them give a second data point for a helper argument seen earlier: SetReflectStatus takes 10 here where DoMoveCounter passes 4, and TryWarp takes 1 where DoMoveWarp passes 0. Both third arguments are therefore selectors of some kind; nothing here establishes what they select. DoMoveSlowDown forwards to LowerSpeed with the same arguments as DoMoveLowerSpeed1. The remaining helpers are undeclared in the tree and take provisional externs written from the call site. Authored by Claude (Opus 5) under human direction. All ten matched on the first candidate. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
dada4f8dbb |
Decomp ten more move-effect wrappers in overlay_29
DoMoveWrap, DoMoveMagicCoat, DoMoveProtect, DoMoveDestinyBond, DoMoveMirrorCoat, DoMoveSnatch, DoMoveReflect, DoMoveSeeTrap, DoMoveScan and DoMoveNoMove. Nine forward to a two-argument helper and return TRUE; DoMoveNoMove passes a third argument of 0. None of the ten helpers is declared in the tree, so each takes a provisional extern written from its call site. DoMoveSeeTrap and DoMoveScan forward to RevealTrapsNearby and RevealItems, the first helpers in this family that are not TryInflict*Status. Authored by Claude (Opus 5) under human direction. All ten matched on the first candidate. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
7c02eea61b |
Decomp ten more move-effect wrappers in overlay_29
DoMoveLowerSpeed1, DoMoveParalyze__02328230, DoMoveParalyze__0232B434, DoMoveConfuse, DoMovePoison, DoMoveToxic, DoMoveCurse, DoMoveWarp, DoMoveLightScreen and DoMovePerishSong -- the same shape as the previous two batches. Three forward to helpers already declared in move_orb_effects.h (LowerSpeed and TryInflictParalysisStatus), which fixes their argument meanings. The rest take provisional externs written from the call site; TryWarp's third and fourth parameters are left unnamed because nothing establishes what they are. DoMoveParalyze__02328230 and DoMoveParalyze__0232B434 join DoMoveParalyze__02326E80 from an earlier batch: three separate wrappers around TryInflictParalysisStatus with identical arguments. Authored by Claude (Opus 5) under human direction. All ten matched on the first candidate. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
14f8c5116c |
Decomp ten more move-effect wrappers in overlay_29
DoMoveEndure, DoMoveUproar, DoMoveMist, DoMoveSafeguard, DoMoveTaunt, DoMoveConversion2, DoMoveBlock, DoMoveWish, DoMoveIngrain and DoMoveSetDamage -- the same shape as the previous batch: forward to one status helper and return TRUE. All ten helpers are undeclared in the tree, so each takes a provisional extern written from its call site. DoMoveBlock forwards to TryInflictShadowHoldStatus, the same helper DoMoveShadowHold uses, with the same argument. Authored by Claude (Opus 5) under human direction. All ten matched on the first candidate. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None carries a region conditional, so US alone is sufficient. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
f504e6ded3 |
Decomp ten move-effect wrappers in overlay_29
DoMoveVitalThrow, DoMoveHealStatus, DoMoveEncore, DoMoveStringShot, DoMoveFocusEnergy, DoMoveCounter, DoMoveParalyze__02326E80, DoMoveShadowHold, DoMoveHaze and DoMoveBoostSpeed1 -- each a thin wrapper that forwards to one status or stat helper and returns TRUE, following DoMoveDefendOrder's shape. Three helpers were already declared in move_orb_effects.h, which fixes the meaning of their constant arguments; the other seven take provisional externs written from the call site. Authored by Claude (Opus 5) under human direction. All ten matched on the first candidate against a context preprocessed from the real headers. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. None of the ten carries a region conditional, so US alone is sufficient here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
883be16336 |
Make SetLeaderAction match EU and JP
Two region-conditional calls the US build cannot see: - SetDecoyAiTracker(GetLeader()) is US/EU only. Its declaration in overlay_29_022FB538.h already sits inside #ifndef JAPAN, so calling it unconditionally broke the JP build at compile time, not just at the checksum. - ov29_022F2FE4() is an extra call EU makes after ov29_022E0B44() in the tail block, from an #ifdef EUROPE in the asm that the previous commit missed. The remaining region differences in the replaced asm need no source change. Two are struct-layout consequences that dungeon.h already models. The other three looked like swapped constants but are immediate encodability: in each region the value that is a single-instruction ARM immediate is materialized inline and the other is derived from the pooled 0xBA3 and cached in a stack slot. 0xBA0 and 0x8E0 encode; 0xBA1 and 0x8DF do not, and the JP offset of -0x2C1 swaps which of the pair is which. This corrects the previous commit, which stated that JP was expected not to match and that EU was unaffected. EU was in fact broken by it, and JP needed one guarded call rather than a rewrite. Authored by Claude (Opus 5) under human direction. Confirmed by matching builds of all three targets: build/pmdsky.us/pmdsky.us.nds: OK, build/pmdsky.eu/pmdsky.eu.nds: OK, build/pmdsky.jp/pmdsky.jp.nds: OK. EU and JP were verified matching at the parent commit as well, so both are gains rather than a pre-existing state. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e8823a888e |
Decomp SetLeaderAction in overlay_29
Split asm/overlay_29_022F05B4.s at 0x022F2B3C; add src/overlay_29_022F0EDC.c and its header, and both objects to main.lsf. Type corrections the match required: - dungeon.field_0x1d8 / field_0x1dc: paired u16 fields -> struct position - dungeon.field_0x614: u32 -> s32, tested >= 0 - display_data.leader_target_direction_mirror: enum direction_id -> u8; the enum type folds the stored 0xFF to -1 and drops retail's mov r0, #0xff - CanMonsterMoveInDirection's direction parameter: u16 -> s32; a u16 parameter narrows the argument at the new call site, where retail passes it unchanged Authored by Claude (Opus 5) under human direction. Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK. Not verified: the JP target, which is expected not to match -- the replaced asm carries JAPAN-specific variants beyond the message-id offset. Two volatile stand-ins remain in the new source, and this translation unit declares DUNGEON_PTR as a scalar where other files declare it as an array; the two are not byte-interchangeable here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
ac3e23890e |
Decomp ten more dungeon-state accessors in overlay_29
Decompile from asm: IsMarowakTrainingMaze ov29_022EAEFC FixedRoomIsSubstituteRoom ov29_022EAF20 IsSecretRoom SetUnkMusicFlag IsDungeonEndReasonFailure ov29_0234969C ChangeDungeonMusic ov29_023496B0 All ten reach struct dungeon through DUNGEON_PTR and every offset lands on a named field: id at 0x748, hidden_outlaw_defeated_message at 0x2, unk_music_flag at 0x792, dungeon_music_playing_id and field_0x2cb00 at 0x2CB06 and 0x2CB00, gen_info.fixed_room_id at 0x40DA, and fainted_monster_dungeon_end_reason at 0x2CA66. No new types. The constants resolve to existing enumerators that corroborate the function names rather than being chosen to fit them: FIXED_SUBSTITUTE_ROOM is 110 and FIXED_SECRET_ROOM is 113, which is what FixedRoomIsSubstituteRoom and IsSecretRoom compare against; DAMAGE_SOURCE_ESCAPE is 633, the 0x279 in IsDungeonEndReasonFailure. IsMarowakTrainingMaze tests the range DUNGEON_NORMAL_FLY_MAZE to DUNGEON_EXPLORER_MAZE inclusive, 180 to 190. IsDungeonEndReasonFailure reads its union member through an explicit (s16) cast. enum damage_source_non_move declares no negative enumerator, so under -enum min it is unsigned and compiles to ldrh with an unsigned comparison, where the target has ldrsh and a signed one. The cast is local and reversible; adding a sentinel to a shared enum, as was done for monster_id earlier on this branch, would not be. Two of the ten merged into src/run_dungeon_1.c, which already declares DUNGEON_PTR as an array and reaches it as DUNGEON_PTR[0]. They follow that file's convention rather than introducing a second spelling; both forms were checked on a scratch and produce identical bytes. 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 <noreply@anthropic.com> |
||
|
|
bb3a61e8fe |
Decomp ten dungeon-state accessors in overlay_29
Decompile from asm:
GetForcedLossReason GetHiddenStairsField
SetForcedLossReason SetHiddenStairsField
AreLateGameTrapsEnabledWrapper GetHiddenFloorField
GetSuccessfulExitTracker SetHiddenFloorField
SetDungeonEscapeFields GetMinimapData
All ten read or write struct dungeon through DUNGEON_PTR, and every offset lands
on a field dungeon.h already names: forced_loss_reason at 0x14,
successful_exit_tracker at 0x18, end_floor_no_death_check_flag at 0x8,
minimap_display_data at 0x1A264, and three fields of gen_info at 0x40C4 --
hidden_stairs_type, hidden_floor_type and fixed_room_id. No new types.
These are verified against the preprocessed dungeon.h context built in the
previous commit rather than a hand-written struct, which is why nine of the ten
matched on the first candidate instead of appearing to and then failing the
build. The setup cost of that context is now paid, so any overlay_29 function
reaching DUNGEON_PTR is cheap to verify; a scan finds 59 more small ones.
GetMinimapData needed the null check written as a conditional expression rather
than an if with an early return. The target predicates the whole thing --
addne twice for the non-null path, then moveq for the null one -- where the
statement form branches. That is the same predicate-ordering effect recorded on
the LFO handlers in
|
||
|
|
5c895f8a1d |
Decomp nine mission predicates against a faithful scratch context
Decompile from asm: IsOutlawMonsterHouseFloor IsDestinationFloorWithMonster IsGoldenChamber MissionTargetEnemyIsDefeated IsJirachiChallengeFloor SetMissionTargetEnemyDefeated IsDestinationFloorWithFixedRoom IsDestinationFloorWithHiddenOutlaw GetMissionEnemyMinionGroup These are the functions the two previous commits could not land. The obstacle was the scratch context, not the C, and this commit is the result of replacing it. The context is now the real headers rather than a hand-written struct: mwccarm -E over a file including global.pch, dungeon.h and mission.h, with LM_LICENSE_FILE set, gives 14500 lines reproducing what the build actually sees. Two things that took finding. global.pch is required -- without it util.h fails at typedef s32 fx32_8, because s32 comes from nitro.h, which the build supplies through -prefix rather than through any include in dungeon.h. And -E consumes every macro, so TRUE, FALSE and NULL have to be restored by hand afterwards; their values are taken from lib/include/nitro/types.h, NULL being ((void *)0) on the C branch. Against that context the earlier verdicts change. All eight functions landed in the two previous commits still score 0, which is the check that the new oracle agrees with the build. Eight of the thirteen unlanded ones score 0 unchanged and are landed here as written. GetMissionEnemyMinionGroup does not: the real headers let the compiler fold the +1 of enemy_species[index + 1] into the load displacement, one instruction shorter than the target. Binding index + 1 to a local first blocks the fold and scores 0, which is what is landed. Four remain unmatched and are genuinely unmatched rather than mis-measured: IsCurrentMissionType and IsCurrentMissionTypeExact at 515, where the target branches to separate return blocks and every spelling tried so far produces predicated moves; GetItemToRetrieve at 665 and GetItemToDeliver at 1530. Their scores are identical under both contexts, so the context was never their problem. The mission_type arguments use the enumerators from mission.h -- ARREST_OUTLAW, EXPLORE_WITH_CLIENT, TAKE_ITEM_FROM_OUTLAW and CHALLENGE_REQUEST -- because the build rejects the implicit conversion from int. The values agree with the function names rather than being chosen to fit them. 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 <noreply@anthropic.com> |
||
|
|
0fbdb57210 |
Decomp four more mission accessors; find the cause of the batch failure
Decompile from asm: ov29_02349688 0x02349688 SetTargetMonsterNotFoundFlag 0x023496C4 GetTargetMonsterNotFoundFlag 0x023496D8 GetMissionTargetEnemy 0x02349620 The first three read and write the two dungeon flags at 0x1 and 0x3; GetMissionTargetEnemy returns enemy_species[0]. No new types. The previous commit left thirteen functions unlanded because they failed four checksums with no compile error, and recorded the elimination so far. Bisecting found a one-function reproducer, GetMissionEnemyMinionGroup, and disassembling the object the real build emits identifies the cause. The scratch and the real build disagree, and the scratch was wrong. For enemy_species[index + 1] the target computes the index first -- add r0, r0, #1, then add r0, r1, r0, lsl #1, then add #0x700 and ldrsh [r0, #0x6e]. The real build folds the constant into the displacement instead, giving add r0, r1, r0, lsl #1, add #0x700, ldrsh [r0, #0x70], one instruction shorter and the same address. Same compiler, same flags, same C: the difference is the context. The scratch used a cut-down struct dungeon carrying only the offsets these functions touch, and against that struct the compiler emits the target's form; against the real header it folds. That invalidates the scratch verification for the whole cluster, not just this function. Score 0 against an invented struct is not evidence about a build that uses the real one, even when every offset and size matches -- and they do, which was confirmed separately by compile-time assertions against the real headers. So the thirteen are not near-matches to iterate on; they need re-verifying against a faithful context before any C is judged. A preprocessed context is obtainable -- mwccarm -E on a file including dungeon.h and mission.h, with LM_LICENSE_FILE set, yields 9200 lines that reproduce the real build's view -- but that output does not yet compile as scratch context on its own, failing at a typedef, so wiring it up is unfinished. The four here were each verified by a matching build rather than by the scratch: three of them alone, GetMissionTargetEnemy alone, and all four together. 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 <noreply@anthropic.com> |
||
|
|
dfbb82363f |
Decomp four mission-destination accessors in overlay_29
Decompile from asm:
ov29_02349188 0x02349188
GetMissionDestination 0x023491A4
ov29_023491B8 0x023491B8
IsDestinationFloor 0x02349208
All four reach DUNGEON_PTR->mission_destination, whose type is already fully
described in dungeon_mode.h. No new types.
This is the surviving part of a larger batch. Seventeen functions from this
cluster reached score 0 on a scratch; these four build matching in the tree and
the other thirteen do not, failing four checksums -- main, OVY_10, OVY_29 and
OVY_31 -- with no compile error. The thirteen are not in this commit.
What is known about that failure, so the next attempt does not repeat the work.
The struct layout is not the cause: compile-time assertions against the real
headers confirm mission_destination at 0x760, the two dungeon flags at 0x1 and
0x3, target_enemy_is_defeated at 0x1B, fixed_room_id at 0x16, enemy_species at
0xE, and sizeof(enum mission_type) == 1 and sizeof(enum monster_id) == 2 -- all
the offsets the scratch context assumed. A build of HEAD with no changes is
clean, so the regression is in the batch. Landing these four alone is clean.
Adding nine more, none of which use a mission_type enumerator, reproduces the
failure, which rules out the enumerator conversions that were the initial
suspicion. No pre-existing declaration of any of the seventeen names exists
elsewhere in the tree.
That main.sbin fails alongside the overlay points at something structural rather
than at a function body -- most likely the overlay size or the symbol exports in
the regenerated .inc files, since extract_function.py rewrites the .public list
when it splits an overlay .s. The byte-level diff of OVY_29 against a clean build
is the next step, using the cmp -l technique that located the rodata problem in
|
||
|
|
26611d6672 |
Decomp seventeen storage-selection accessors
Decompile from asm, all reaching UNK_STORAGE_STRUCT_0X14: sub_02043148 sub_0204329C sub_020433E0 ClearStorageSelectedItemTable sub_0204316C sub_02043380 sub_02043400 CountSelectedStorageItems sub_02043218 sub_02043398 sub_02043434 GetFirstSelectedStorageItemIndex sub_0204322C sub_020433C0 sub_02043468 sub_0204323C sub_02043254 struct unk_020AFEE0 was introduced two dozen commits ago holding only the pointer at 0x8 and filler before it. Its first eight bytes are now split into what these functions read: halfwords at 0x0 and 0x2 and a pointer at 0x4, with a word at 0x10 added past the existing end. Nothing that already used field_0x8 moves. The object behind that pointer is new, and its size is derived rather than guessed. Its s16 array at 0x4 is bounded by 0x3e8 in three separate loops, which is 1000 entries and ends at 0x7D3; the signed byte the collection-menu wrappers read sits at 0x7D4, immediately after it. Two further fields at 0x910 and 0x18BC come from sub_020430F4. Filling the gaps brings the struct to exactly 0x18C0, which is the size in upstream's own name for its allocator, InitUnkStorageStruct0x18c0. That agreement is the reason the layout is worth trusting; the field names remain placeholders because nothing here establishes meaning. Fourteen of the seventeen matched on the first candidate. The other three are loops whose index and pointer landed in swapped registers, with every instruction otherwise correct, and all three were closed by reordering the local declarations -- the same effect recorded in the previous two commits. All orderings were enumerated rather than guessed: two locals for sub_02043254 and GetFirstSelectedStorageItemIndex, three for CountSelectedStorageItems. Eight callees remain asm and their prototypes are provisional, declared in the shared header rather than repeated per file. None of them was declared anywhere else in the tree. Two are typed from evidence rather than convention: IsCollectionMenuActive and IsCollectionMenuState3 return bool8 because both callers mask with and r0, r0, #0xff. sub_020430F4 was attempted and is not included. It reaches the same struct and its two extra fields are what sized it, but it stands at 495 after correcting sub_0202C654 to the four arguments the target passes -- the fourth is a zero in r3 that the first reading missed. Left in asm rather than landed as a near-match. 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 <noreply@anthropic.com> |
||
|
|
72b366b366 |
Decomp SetPokemonBattled and GetNbItemAcquired
Decompile from asm: SetPokemonBattled 0x0204FE58 GetNbItemAcquired 0x020503CC SetPokemonBattled is the battled counterpart of SetPokemonJoined, already decompiled in src/main_0204FDFC.c, and merges into that file beside it. It differs only in which completion flag it sets and which flag array it indexes, so the existing function is the template rather than anything derived here. GetNbItemAcquired counts the set bits of items_acquired_flags across 0x580 entries. The pointer is hoisted to a local because the target loads it once before the loop, and the word and bit indices use signed division and remainder, which is what produces the asr/lsr/ror sequences the target has. Both matched on the first candidate. Seven adventure-log functions remain in asm. Four are large -- ComputeSpecialCounters at 144 instructions, CopyLogTo at 122, CopyLogFrom at 120 and ClearAdventureLogStruct at 74. The other three are not large but index the region at 0x260 as an array spanning special_challenge_flags and the five sentry_duty_game_points that follow it, mixing signed and unsigned division of the same index within one function; expressing that without either misdescribing the struct or writing something the compiler will not reproduce needs more care than this batch had left. 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 <noreply@anthropic.com> |
||
|
|
4f46fed938 |
Decomp thirty adventure-log accessors
Decompile from asm, all of them accessors on ADVENTURE_LOG_PTR: SetAdventureLogStructLocation SetAdventureLogCompleted IncrementNbEvolutions SetAdventureLogDungeonFloor GetAdventureLogCompleted GetNbEvolutions GetAdventureLogDungeonFloor IsAdventureLogNotEmpty IncrementNbEggsHatched IncrementNbDungeonsCleared GetNbDungeonsCleared GetNbEggsHatched IncrementNbFriendRescues GetNbFriendRescues GetNbPokemonJoined GetNbMovesLearned SetVictoriesOnOneFloor GetVictoriesOnOneFloor GetNbPokemonBattled IncrementNbBigTreasureWins SetNbBigTreasureWins GetNbBigTreasureWins SetNbRecycled GetNbRecycled IncrementNbSkyGiftsSent SetNbSkyGiftsSent GetNbSkyGiftsSent IncrementNbFainted GetNbFainted GetSentryDutyGamePoints No new types. struct adventure_log already exists in include/adventure_log.h with every field these touch named and offset-commented, and struct dungeon_floor_pair in dungeon.h; every offset in the asm lands on a named field. That header is the reason a batch this size was tractable: the only modelling needed was reading which field each function touches. Two orderings decided four of the thirty, both instances of the rule added to MATCHING_TIPS in the previous commit. IsAdventureLogNotEmpty needed its loop index declared before the pointer local, not after -- with the pointer first the two land in swapped registers, at 35. The three Set functions needed the completion-flag write placed before the clamp rather than after: written in the obvious order the clamp is emitted ahead of the first pointer load and the two literal-pool words come out reversed, at 250 each. Reordering the statement fixed all three. The counters clamp at 0x000F423F, decimal 999999, and each function sets one bit of completion_flags[0]. The exact shape differs per function and is reproduced rather than normalised: three increment then clamp, two clamp then increment, and the three setters write the flag before storing the value. Those differences are what the target does. The clamp comparisons are signed even though the fields are u32, so each is written with an explicit (s32) cast rather than retyping a shared struct. ADVENTURE_LOG_PTR and _022AB69C move into adventure_log.h. src/main_0204FDFC.c declared the pointer itself, from before any of this was decompiled; that line is replaced by the header it already includes, and the object rebuilds unchanged. Nine adventure-log functions remain in asm and are not in this commit: ClearAdventureLogStruct, ComputeSpecialCounters, CopyLogTo, CopyLogFrom, SetItemAcquired, GetNbItemAcquired, SetChallengeLetterCleared, SetPokemonBattled and SetSentryDutyGamePoints. 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 <noreply@anthropic.com> |
||
|
|
59c4a95e44 |
Decomp the volume and pan fade track events
Decompile from asm: DseTrackEvent_VolumeFade 0x020723C0 DseTrackEvent_PanFade 0x02072668 Both were deferred near-matches. Each reads a signed byte as the fade target and a little-endian pair as its duration in ticks, writes the target, and then either snaps current to it when the duration is zero, zeroes the duration when there is nothing to travel, or divides the distance by the duration to get the per-tick delta. The two differ only in which struct dse_fade they address -- volume at 0x2c, pan at 0x3c -- both of which already exist in dse.h. What closed them was declaration order, and in the opposite direction to the obvious one. The target loads ptr_next_byte[2] first, then [0] and [1]; writing the target expression first, so that its load comes first in the source, leaves the loads in ascending address order at score 620. Declaring ticks first and the target second emits them in the target's order and scores 0. So for this scheduler the later-declared expression's loads are issued first, and the fix is to write the declarations in the reverse of the order the asm reads them. Seven other spellings of the same two statements were tried -- explicit locals for each byte in the target's load order, s8/s16/s32 intermediates, an inline cast, and a pointer-cast subscript -- and every one of them stayed at 620. Only the declaration swap moves it. The lib/DSE headers extract_function.py generates do not include dse.h, so both were given it; every other header in that directory already does. Three deferred DSE functions remain, and this commit does not close them. DseTrackEvent_TuningFade is the same family with a bend fade plus the SetTuning tail; hoisting container out of channel before the flag test takes it from 935 to 760, which is progress and not a match. DseTrackEvent_SetupKeyBendLfo is unchanged in substance: its instructions have matched for some time and only register assignment differs. All 120 orderings of its five byte locals were tried this time, along with eleven structural variants, and the best is 55 rather than the 65 it sat at; the earlier note suggested exhaustive permutation as the untried move, and it has now been tried and does not close it. 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 <noreply@anthropic.com> |
||
|
|
702c4c85fe |
Decomp DeleteWindow and seven window state helpers
Decompile from asm: sub_02027A08 0x02027A08 sub_0202811C 0x0202811C sub_02028080 0x02028080 sub_0202812C 0x0202812C sub_020280C0 0x020280C0 DeleteWindow 0x02028194 sub_0202810C 0x0202810C sub_0202822C 0x0202822C DeleteWindow explains _022A7A74, which the previous commit landed two accessors for without knowing what it held. On deleting a window it walks the other nineteen, and for every active one on the same background takes base_tile + width * height, keeping the largest and a floor of 1, then stores that at _022A7A74[bg_id]. So the pair is a next-free-tile watermark per background, which also explains NewWindowScreenCheck setting the entry to 1 when a background has no windows left: that resets the allocator. Four of the eight return their callee's result rather than void, and only one of them shows it. sub_020280C0 never touches r0 after calling sub_02027E30, which is only consistent with r0 staying live to the return; typed void it scored 90, typed s32 it scores 5, and the 5 is the literal-pool naming described below. sub_0202810C and sub_0202811C are tail calls that score 0 either way, so their own bytes settle nothing; they are typed s32 to match, and a reviewer should read those two as following the family rather than as read off the target. DeleteWindow needed two things past the obvious form. The background comparison is bg == p->template.bg_id, not the reverse, which is worth 5 on its own. And its four locals have to be declared i, top, p, bg: every one of the 24 orders was tried, they range from 0 to 140, and only that one reaches 0. The instructions were already identical at 35 -- the entire remaining difference was which register held bg and which held i. sub_0202812C and sub_02027A08 land at 10, and sub_020280C0 at 5, all of it the literal-pool symbol naming: the target writes _022A8990, _022A8992 and _022A88E4 where C indexing WINDOW_LIST emits WINDOW_LIST+0xb4, +0xb6 and +0x8. Same address, identical bytes once linked, at a flat 5 per word. The check for this is in MATCHING_TIPS; the build is what settles it. struct unk_020AFD4C is introduced for the 12-byte object at that address, sized by the gap to _020AFD58. Only its word at 0x8 is touched here, a bitmask that five of these functions set a bit in, indexed by bg_id. DeleteWindow had a provisional declaration in include/main_0202AAA8.h from the menu commits, with three decompiled callers. That is replaced by an include of the new header and all three objects rebuild. sub_0202836C now has a fifth declaration in the tree, and the existing four do not agree: overlay_15 says int, overlay_24_end says s32, and overlay_24_init and overlay_25_init say s8. It is declared s32 here, in the caller's own header rather than in window.h, so that no overlay including window.h sees a conflicting one. They should collapse into a single header when the callee lands. No comments are added to any pmd-sky file. Authored by Claude (Opus 5) under human direction. Confirmed by a matching build with the three DeleteWindow callers rebuilt: build/pmdsky.us/pmdsky.us.nds: OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
7f6977e268 |
Decomp ten window accessors, including UpdateWindow and ClearWindow
Decompile from asm: sub_02027624 0x02027624 ClearWindow 0x02027B58 UpdateWindow 0x02027AF0 sub_0202825C 0x0202825C sub_02027B1C 0x02027B1C sub_02028270 0x02028270 sub_020282C8 0x020282C8 sub_020282F4 0x020282F4 sub_0202830C 0x0202830C sub_02028324 0x02028324 Four bss symbols these functions index at stride 0xE0 are aliases into WINDOW_LIST[0], not separate objects: _022A88E4 is +0x8, _022A88F0 is +0x14, _022A88F8 is +0x1C and _022A8994 is +0xB8. The block from WINDOW_LIST to the end of _022A8994 measures 0xB8 + 0x10C8 = 0x1180 = 20 * 0xE0, and every one of those boundaries falls on a field boundary of the Window layout added earlier. That is independent corroboration of the layout, from the linker rather than from the struct definition. Five of the ten do not reach score 0 on a scratch, and are landed anyway. Their instructions all match; the only difference is the literal-pool word, which the target names _022A8994 where C indexing WINDOW_LIST emits WINDOW_LIST+0xb8. Same address, same relocation target, identical bytes once linked -- the scratch diff compares symbol names, at a flat 5 per word, so ClearWindow and sub_02027B1C report 10 and the three single-literal ones report 5. The matching build is what settles it. Which literal appears is decided by whether the index is constant. A constant offset keeps the base symbol in the pool and puts the offset in the instruction; a variable index folds the offset into the pool word because the index has to be scaled separately. That rule cost a build here: NewWindowScreenCheck stores to _022A7A6C at #8 and #0xa, and rewriting those two lines as _022A7A74[0] and [1] to remove an apparent duplicate changed the pool word and failed main.sbin, with no compile error and no overlay cascade. It is reverted, and both declarations are kept, because the target keeps both. sub_020282C8 writes width*8 and height*8 through an out parameter. It reuses Point rather than adding a second two-s32 struct; the layout is identical and the type already exists, but a size is not a coordinate, so read that as structural reuse and not as a claim about meaning. Two prototypes in the tree contradicted the ones landing here and are replaced with includes: overlay_31_02382820.c declared UpdateWindow itself, and overlay_31_02383880.c declared sub_020282F4 taking s8. Both objects are rebuilt to confirm the retyping is byte-neutral rather than assumed. Two more are left alone and are worth a later pass. overlay_13_0238BDA8.c declares UpdateWindow and sub_02027B1C taking s8, and overlay_25_init.c declares both taking char *; the second is a genuine mistyping, since the value it passes is a window id, but correcting it means retyping ov25_0238B414's own parameter and its callers, which is a larger change than this batch. The s8 declaration in overlay_13 carries an upstream annotation identifying sub_02027B1C, which is worth keeping in place rather than deleting to make a byte-neutral edit. No comments are added to any pmd-sky file. Authored by Claude (Opus 5) under human direction. Confirmed by a matching build with both overlay_31 objects rebuilt: build/pmdsky.us/pmdsky.us.nds: OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b6faa49387 |
Decomp NewWindowScreenCheck, SetScreenWindowsColor and the palette getter
Decompile from asm: NewWindowScreenCheck 0x02027648 GetPaletteBaseAddress__020278A8 0x020278A8 SetScreenWindowsColor 0x02027A80 NewWindowScreenCheck counts the active windows on each background before delegating to NewWindow, and sets a flag when either screen has none. It reads is_active as a signed byte at 0xB6 and bg_id at 0x8, both named by the Window layout added in the previous commit, so the loop reads as what it does. It walks with a cursor rather than indexing. Indexing WINDOW_LIST[i] emits an mla per iteration; the target advances a pointer by 0xE0 at the bottom of the loop. Its two counters also have to be assigned in the order sub then main -- declaration order alone was not enough, and every permutation of the four locals left between 20 and 95. SetScreenWindowsColor's colour parameter is s32, not u8, and that distinction is not visible in its own bytes: both score 0 against it, because the store is a strb either way. It is visible one level up. SetBothScreensWindowsColor, landed matching in the previous commit, passes its argument straight through; a u8 parameter makes the compiler truncate at that call site, which changes an object that already matched, changes the size of main.sbin, and shifts every overlay after it. The first build of this batch failed 33 checksums for that reason, with no compile error and nothing wrong in the function being added. GetPaletteBaseAddress__020278A8 reads through _020AFC70, which include/ main_02064FFC.h already declares as u8 *. It is declared the same way here rather than being given a second, differently typed declaration. 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 <noreply@anthropic.com> |
||
|
|
30ea1f34f0 |
Replace the Window placeholder with its real layout
struct Window was landed two commits ago as mostly filler: the fields those
functions happened to touch, and padding to reach the 0xE0 stride GetWindow
indexes by. This replaces it with the full 0xE0 layout, supplied by the project
maintainer, together with the four types it is built from -- WindowTemplate,
WindowBlock, WindowTile and CursorParams, plus Point.
Four things the layout has to satisfy, and does:
sizeof is 0xE0, the stride GetWindow multiplies by.
is_active is an s8 at 0xB6, which is where DeleteWindow does ldrnesb.
WindowTemplate.width is at 0x06, where the previous partial struct, inherited
from overlay_31_02382820.h, already had width.
x, y, width and height at 0x04 through 0x07 account for GetWindowRectangle
exactly: it writes y*8, y*8 + height*8, x*8 and x*8 + width*8, so its output
is top, bottom, left, right. That function is rewritten against the named
fields rather than shifting anonymous bytes.
Three choices worth noting for review. The struct keeps its tag, so both
struct Window and Window resolve and no existing use changes. GetWindowContents
still returns void * rather than the u32 the field is typed as, because all 22
of its callers assign the result to a pointer; the cast is a no-op and avoids 22
integer-to-pointer conversions. And width moving inside the template means
overlay_31_02382820.c reads window2->template.width, the one source change the
layout forces.
The field names here are the maintainer's, not derived in this commit. The
offsets and widths are checkable against the asm; the names are not, and should
be read as supplied rather than proven.
No comments are added to any pmd-sky file.
Authored by Claude (Opus 5) under human direction, from a struct definition
supplied by the maintainer. Confirmed by a matching build with
overlay_31_02382820.o rebuilt: build/pmdsky.us/pmdsky.us.nds: OK.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
643fd53bcf |
Decomp GetWindowContents, GetWindowRectangle and SetBothScreensWindowsColor
Decompile from asm: SetBothScreensWindowsColor 0x02027A80 GetWindowRectangle 0x02028284 GetWindowContents 0x0202833C GetWindowContents is the function the menu accessors landed over the last several commits all call. It reads the pointer at 0xC of a WINDOW_LIST entry, and its callers cast that to whichever menu layout they use. struct Window gains the fields these two touch: bytes at 0x4, 0x5, 0x7 and 0x8 around the existing width at 0x6, and the pointer at 0xC. The trailing padding shrinks to keep the entry at 0xE0, which is the stride GetWindow indexes by. GetWindowRectangle converts four of those bytes into a rectangle in pixels, multiplying each by 8, writing top and bottom from 0x5 and 0x7 and left and right from 0x4 and width. Its out parameter has no existing type and becomes struct unk_02028284. GetWindowContents needed the entry address bound to a pointer local. Returning WINDOW_LIST[window_id].field_0xC folds the field offset into the literal pool entry, giving a .word WINDOW_LIST+0xc and an indexed load; the target keeps WINDOW_LIST as the literal and reaches the field with mla plus ldr [r1, #0xc]. SetScreenWindowsColor is still asm and had no declaration in the tree, so its prototype is provisional. 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 <noreply@anthropic.com> |
||
|
|
aade0cdfc8 |
Decomp GetWindow; retype overlay_31's window callbacks as ids
Decompile from asm: GetWindow 0x020275F8 It indexes WINDOW_LIST with a stride of 0xE0, so its argument is a window id rather than a pointer, and its result is the address of one entry. overlay_31_02382820.c declared it as taking a struct Window * and passed one, which cannot be what the target computes: multiplying a pointer by 0xE0 and adding it to WINDOW_LIST is meaningless. The value it passes is an id, and the same value goes to DrawTextInWindow and UpdateWindow, so those take ids too. This retypes the three window callbacks and both of those prototypes accordingly, along with the callback type CreateTextBox stores. That retyping is byte-neutral -- a pointer and an id both travel in r0 -- but overlay_31_02382820.o was already matching, so it is rebuilt here to confirm rather than assumed. struct Window keeps its existing return type and gains padding to its real 0xE0 size, which is what lets &WINDOW_LIST[id] stride correctly. Its first seven bytes are unchanged, so the width field overlay_31 reads is where it was. The struct moves from the overlay's header into include/window.h, which already exists and is where a main-binary function returning one can reach it; the overlay includes it rather than the main binary including an overlay header. No comments are added to any pmd-sky file. Authored by Claude (Opus 5) under human direction. Confirmed by a matching build with overlay_31_02382820.o rebuilt: build/pmdsky.us/pmdsky.us.nds: OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
2472ad54f7 |
Decomp four allocation, keyboard and area-name accessors
Decompile from asm: AllocUnkBagStruct 0x02042B98 FreeUnkBagStruct 0x02042BBC SetAreaNameBoxState3 0x0202FD3C GetKeyboardStringResult 0x0203755C AllocUnkBagStruct and FreeUnkBagStruct manage the pointer at offset 8 of UNK_STORAGE_STRUCT_0XC, the field the selection accessors in the previous commit read. The allocation is 0xC8 bytes, which is 0x32 words -- the same count ClearBagSelectedItemTable zeroes and the same inventory size the bag walkers use. MemAlloc is still asm and has no owning header, so its prototype is provisional and declared beside the caller, matching the signature overlay_31_02382820.c already uses. That is now a second declaration of it; both should collapse into one header when MemAlloc lands. SetAreaNameBoxState3 writes a word at 0xA0 of the window contents, so the filler before 0x198 in struct unk_0202AAA8 is split to expose it. Nothing after it moves. GetKeyboardStringResult reads through the unnamed pointer _020AFDF0, which keeps its placeholder name, into a word at 0xF8 of whatever it points at. GetWindow was looked at and deliberately left in asm. It indexes WINDOW_LIST with a stride of 0xE0, so its argument is an index, but overlay_31_02382820.c declares it as taking a struct Window * and passes one. Landing it correctly means retyping that caller, and struct Window there describes only its first 7 bytes, so the two disagree about more than this function. 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 <noreply@anthropic.com> |
||
|
|
80c33c3540 |
Decomp six storage-selection and notify-note accessors
Decompile from asm: ClearBagSelectedItemTable 0x02042AF8 IsBagItemIndexSelected 0x02042B84 IsStorageItemIndexSelected 0x02043568 GetNotifyNote 0x020484A0 SetNotifyNote 0x020484B0 EventFlagBackupVeneer 0x02048758 UNK_STORAGE_STRUCT_0XC and UNK_STORAGE_STRUCT_0X14 already carry those names in asm. Only their field at offset 8 is touched here, a pointer to an array, so they are typed with placeholder structs holding that field and filler before it. The element widths come from the loads: words for the bag table, bytes for the storage one. Their struct names use the globals' own addresses, 0x020AFED4 and 0x020AFEE0, derived by walking back from UNK_STORAGE_STRUCT_0X8_PTR_1, which sits at the labelled address 0x020AFEF4, through the two definitions' byte counts. That is arithmetic on the data rather than a lookup, and a reviewer may want to confirm it; nothing in this commit depends on the names being right, only on the layout. ClearBagSelectedItemTable zeroes 0x32 entries, the same count the bag walkers in earlier commits use for an inventory. EventFlagBackup is still asm and had no declaration in the tree, so its prototype is provisional. 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 <noreply@anthropic.com> |