Commit Graph

1558 Commits

Author SHA1 Message Date
cecilarmitais
d387d4e273 Decomp ActivateEndOfTurnEffects; monster::bide_move_id is a 2-byte enum move_id
ActivateEndOfTurnEffects (0x0230FC24, 1235 instructions in US) is the
per-turn status tick: the warp-scarf counter, the leader's belly and
hunger messages, weather damage, Shed Skin and Hydration, the burn, poison,
bad-poison, constriction, wrap, ingrain, curse and leech-seed damage
countdowns, perish song and bide. It is the last of five functions in
asm/overlay_29_0230F9A4.s and the next object in main.lsf is
src/overlay_29_02311010.o, so extract_function.py merges rather than
splits and main.lsf is unchanged.

struct monster declared 0xAC as u8 bide_move_id plus u8 field_0xad. Retail
accesses it with ldrh/strh and stores 0x165 = MOVE_BIDE_UNLEASH, which
does not fit in a byte; enum move_id runs to 558, so -enum min sizes it to
two bytes - the width struct move's own enum move_id id at 0x2 already
has. The field becomes enum move_id and absorbs field_0xad. The struct
size and every later offset are unchanged, no other source reads either
member, and InitMove already takes enum move_id so no cast is needed. This
deviates from pmdsky-debug's u8; the reasoning note linked from the PR has
the evidence.

The 29 callees that are still asm are declared extern in the .c with
prototypes read off their own asm, as the sibling files do, and so are the
24 data symbols - const on the read-only rodata ones, which is what places
their loads correctly.

Region handling: the sound-effect guard in the hunger block is a genuine
three-way fork, EU calling ov29_022E34A8_EU where JP omits the
end_floor_no_death_check_flag test that US performs, and nine message ids
are file-scope defines at US - 0x2C0 under JAPAN. The JP struct and
dungeon offset shifts are absorbed by the headers with no directive.

Locals are generic and declared at function scope. That is not cosmetic:
the allocator's unit is the coalesced web, and the function-scope
declaration list is the only thing that orders it, so the declaration
order is what reproduces retail's register assignment.

Authored by Claude (Opus 5) under human direction. Confirmed by matching
builds of all three regions: build/pmdsky.us/pmdsky.us.nds: OK,
build/pmdsky.eu/pmdsky.eu.nds: OK, build/pmdsky.jp/pmdsky.jp.nds: OK.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 23:12:41 -07:00
cecilarmitais
33d90d0f8d Decomp the fixed-point helper cluster at the end of main_020504BC.s
sub_02050EBC, SubFixedPoint, sub_02050F78, sub_02050FF8 and
BinToDecFixedPoint are the last five functions in asm/main_020504BC.s and
all operate on struct fixed_point (106 instructions). The next object in
main.lsf is src/number_util.o, which already holds their sibling
CeilFixedPoint, so extract_function.py merges rather than splits and
main.lsf is unchanged. They are landed in reverse address order so each
prepends above the last, leaving number_util.c in ascending address order
with CeilFixedPoint last.

sub_02050EBC and sub_02050F78 keep their sub_<addr> names - this is
decompilation, not identification.

A 4-byte struct fixed_point is passed and returned by value in r0, packed
as integer | fractional << 16. The stmdb sp!, {r0, r1, r2, r3} at entry is
MWCC giving the argument registers stack homes so a by-value struct
parameter can be addressed, and writing to the parameter reuses that home,
which is why SubFixedPoint and sub_02050EBC modify their first argument
and return it. The caller-side sub rX, sp, #4 idiom around these calls is
compiler-generated, not a source construct: src/dungeon_ai_movement.c
already emits it from a plain CeilFixedPoint(pokemon_info->belly).

None of the five blocks carries a region directive, so one source serves
all three regions.

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>
2026-09-18 23:12:41 -07:00
cecilarmitais
9097cad39d Use generic local names in the five functions landed since 51c365db
CalcDamage, CalcTypeBasedDamageEffects, ApplyDamage, ApplyDamageAndEffects
and ov11_022ED69C had locals named after what the decompiler inferred them
to mean. A local's meaning is not something the matching build can check,
so every such name is replaced by a type-derived generic one numbered in
declaration order: fixed-point temporaries fp1.., monster pointers mon1..,
scalar values v1.., bool8 flags f1.., pointers p1.. / ent1.. / item1.. /
ls1.., arrays arr / buf. Names that were already generic (i, j, k, n,
result) or are simply the type's own name (diag, weather, tile, member,
entry, spec) are unchanged, and so are all parameters, whose names upstream
syncs from pmdsky-debug. Declaration order is untouched; only identifiers
change, so no object changes.

Authored by Claude (Fable 5.1) under human direction. Confirmed by matching
builds of all three regions after the rename: build/pmdsky.us/pmdsky.us.nds:
OK, build/pmdsky.eu/pmdsky.eu.nds: OK, build/pmdsky.jp/pmdsky.jp.nds: OK.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 23:12:41 -07:00
cecilarmitais
7653350896 Decomp CalcDamage; damage_calc_diag's move_category is 4 bytes, its modifiers unsigned
CalcDamage (0x0230BBAC, 1290 instructions) is the damage formula: stat
stages, item/ability/IQ-skill modifiers, the fixed-point base formula,
CalcTypeBasedDamageEffects, critical hits, Reflect/Light Screen and the
final multipliers, with its diagnostics in DUNGEON_PTR->last_damage_calc.
It is the first of 26 functions in asm/overlay_29_0230BBAC.s and a rodata
object precedes that object in main.lsf, so extract_function.py splits
rather than merges: the function lands in src/overlay_29_0230BBAC.c with
include/overlay_29_0230BBAC.h, the other 25 move to
asm/overlay_29_0230D088.{s,inc}, and main.lsf lists both objects where it
listed one.

struct damage_calc_diag modelled move_category as a 1-byte enum plus
field_0x5/0x6/0x7 padding (3fc6d8bd). Retail writes that field with a
4-byte str (0x0230BDC8) and reads the eight modifier bytes at 0x30..0x37
unsigned (ldrb at 24 sites), so move_category becomes s32 - the struct
stays 0x54 bytes - and the modifiers become u8 (they were s8). No other
source in the tree reads these members. Both deviate from pmdsky-debug's
declarations; the reasoning note linked from the PR has the evidence.

Region handling follows the neighbouring files: six
DefenderAbilityIsActive__0230A940 calls take three arguments under JAPAN,
and message ids C53/C54/C55/C57/C58 and DC1 are file-scope defines at
US - 0x2C1 under JAPAN. One difference is real source: the defense-side
apparent_id 0x211/0x218 checks compare the attacker's apparent_id under
JAPAN (the JP-only ldrsh r1, [r6, #4]). EU is identical to US.

The 17 callees that are still asm are declared extern in the .c with
prototypes read off their own asm, as the sibling files do. The spelling
of the ability-multiply block (an s32 calc[2] local, two temps and three
volatile s32 * pointers) is match-derived, each element removing one
measured compiler obstacle; the reasoning note explains it.

Authored by Claude (Fable 5.1) under human direction. Confirmed by
matching builds of all three regions: build/pmdsky.us/pmdsky.us.nds: OK,
build/pmdsky.eu/pmdsky.eu.nds: OK, build/pmdsky.jp/pmdsky.jp.nds: OK,
each also passing main.sha1, filesystem.sha1 and arm7.sha1.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 23:12:41 -07:00
cecilarmitais
38aa265d9d Decomp CalcTypeBasedDamageEffects; pad damage_calc_diag to its real layout
CalcTypeBasedDamageEffects (0x0230AD04, 676 instructions) applies every
type-, ability-, weather- and status-based multiplier to a damage
calculation. It merges into src/type_effectiveness.c, which already held
its callee GetTypeMatchup, so asm/overlay_29_0230AD04.{s,inc} are removed
and main.lsf loses that object with no new object added.

struct damage_calc_diag modelled move_type as a 1-byte enum plus explicit
field_0x1/0x2/0x3 padding, but gave move_category no such padding, so
every member from move_indiv_type_matchups (0x8) to attacker_level (0x16)
compiled below the offset its own comment states. Downstream alignment
before damage_calc re-absorbed the drift, so the struct still totalled
0x54 and no build caught it; the two existing users in the tree both sit
past the re-convergence point. asm/overlay_29_022E0378.s writes 0x188 and
asm/overlay_29_022E335C.s reads 0x184/0x188 with word accesses, so both
fields are four bytes in retail. Adding field_0x5/0x6/0x7 is byte-neutral
for the existing tree.

include/type_effectiveness.h gains overlay_29_02308FBC.h, which defines
the struct unk_02308FE0 its new declaration names.

Region handling follows the neighbouring files: six
DefenderAbilityIsActive__0230A940 calls take three arguments under JAPAN
and four elsewhere, and five message ids are file-scope defines at
US - 0x2C1 under JAPAN. EU is identical to US - the original asm block
carries no EUROPE directive at all.

Authored by Claude (Opus 5) under human direction. Confirmed by matching
builds of all three regions: build/pmdsky.us/pmdsky.us.nds: OK,
build/pmdsky.eu/pmdsky.eu.nds: OK, build/pmdsky.jp/pmdsky.jp.nds: OK,
each also passing main.sha1 and filesystem.sha1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 23:12:40 -07:00
cecilarmitais
5f96316f71 Decomp ApplyDamageAndEffects; ApplyDamage's damage source is signed 16-bit
ApplyDamageAndEffects (617 instructions, overlay 29 at 0x0230863C) lands in
src/overlay_29_02308FBC.c beside ApplyDamage, with all three regions matching.

JAPAN differs in eleven places: ten DefenderAbilityIsActive__0230A940 calls
drop their fourth argument (the header already declares both forms), and the
counter-damage message id is US - 0x2C1, added as MESSAGE_C3F alongside the
existing per-region defines. EUROPE is byte-identical to US.

ApplyDamage's sixth parameter changes from enum damage_source_non_move to
s16. The caller loads it with ldrsh and passes it in a register; the enum is
all-positive so -enum min makes it unsigned 2-byte, which emits ldrh there.
s16 scores 0 on both functions and all three ROMs still match, so this is a
correction to the type rather than a change in behaviour.

New in this commit: struct unk_023535DC for the exclusive-item effect table at
ov29_023535DC (16-byte stride: effect id, argument, handler), and externs for
the ten ov10_022C* activation-chance globals and six overlay callees.

Three constructs are colouring devices rather than recovered source and should
be read as stand-ins: a (u32) cast on the final return, a (s16) cast on the
counter-attack loop's damage-source argument, and *(u8 *)effect as the effect
loop's condition. Each is plain C, and each is load-bearing for the match.

Authored by Claude (Opus 5 and Fable 5) under human direction. Confirmed by
matching builds of all three ROMs: build/pmdsky.us/pmdsky.us.nds: OK,
build/pmdsky.eu/pmdsky.eu.nds: OK, build/pmdsky.jp/pmdsky.jp.nds: OK -- each
also passing main.sha1, so the ARM9 binaries match and not only the packaged
ROMs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 23:12:40 -07:00
cecilarmitais
e0f7191722 ApplyDamage: match the EU and JP builds
Follow-up to ff65ac0e, which decompiled the US branch only. One source now
matches all three regions:

  build/pmdsky.us/pmdsky.us.nds: OK
  build/pmdsky.eu/pmdsky.eu.nds: OK
  build/pmdsky.jp/pmdsky.jp.nds: OK

JAPAN, five source differences:
  - DefenderAbilityIsActive__0230A940 takes three arguments, not four, at six
    call sites. include/overlay_29_0230A994.h already declares this, so the JP
    build failed to compile rather than to match.
  - every message id is US - 0x2C1. Kept as region-conditional #defines at file
    scope, following src/dungeon_ai.c.
  - no UpdateStatusIconFlags call before the HP check.
  - no end_floor_no_death_check_flag guard on the revival-item path.
  - in the reviver-seed block, no ov29_022FBD24; instead ov29_02307DC0 after the
    curse handling.

EUROPE, one behavioural difference: the last arm of the defeat-message ladder
records a flag instead of logging, and the message is emitted later at three
points - the reviver-seed path, the revival-item path, and their else. The two
revival paths log from a different table.

That table is four bytes that exist only in the EUROPE branch of
asm/overlay_29_rodata_02352A6C.s, immediately after ov29_02353218 and carrying
no symbol; the extractor could only render both as raw addresses (0x02353E44 and
0x02353E40). This commit labels it. The label and .global add no bytes, and the
EU checksum is what confirms both references resolve where intended - had either
been wrong, pmdsky.eu.nds would not match.

The name ov29_02353E44 is keyed to the symbol's EUROPE address, which breaks the
file's convention of naming by US address. There is no US address to use: the
data does not exist in that build.

One change was needed for the EU register allocation and is byte-neutral for the
other two builds: `dmon` is now assigned after the wild-enemy test rather than
before it, with that test reading through defender->info. Introducing the
variable later flips which web the allocator colours first and unwinds a
whole-function rotation of three callee-saved registers.

Authored by Claude (Opus 5) under human direction. Confirmed by matching builds
of all three regions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 23:12:40 -07:00
cecilarmitais
eb0db73b1f Decomp ApplyDamage; fix a message-id parameter type and three field types
ApplyDamage (overlay 29, 0x02308FE0). asm/overlay_29_02308FE0.s and its .inc
are removed and the object drops out of main.lsf; the function merges into
src/overlay_29_02308FBC.c alongside EntityIsValid__02308FBC.

Types added: struct unk_02308FE0 (the damage-data argument, in the function's
header), struct unk_023528A4 and struct unk_022C593C (element types for
TYPE_DAMAGE_NEGATING_EXCLUSIVE_ITEM_EFFECTS and ov10_022C593C, local to the .c).

Field types corrected, each required by the match:
  struct monster::bide_damage_tally           u32 -> s32   (clamped with strgt)
  struct monster::field_0x168 / field_0x169   -> s16 field_0x168   (read ldrsh)
  struct dungeon_generation_info::music_table_idx  u16 -> s16      (read ldrsh)

TalkToSecretBazaarNpcStandard, ov29_022F0618, TalkToSecretBazaarNpcWithYesNoMenu
and the TalkToSecretBazaarNpc extern take a message id in their first parameter,
not a struct entity *. Every caller loads a small constant into r0 - 0xC6B from
ApplyDamage, 0xF32/0xF4A/0xF4B/0xF4C in asm/overlay_29_02344178.s. The three
tree functions are one-line forwarders, so their parameter types were
unconstrained; ApplyDamage is the first C caller.

Two things a reviewer should weigh. DUNGEON_PTR is declared scalar here
(extern struct dungeon *DUNGEON_PTR;) rather than the *DUNGEON_PTR[] idiom the
other files use - the array form lets MWCC CSE the load and costs three
instructions. And one read is qualified volatile
(*(volatile u8 *)&dmon->curse_class_status.curse) to reproduce a reload retail
performs with no intervening call; it is standard C and the ROM matches, but it
is a stand-in rather than recovered source, and a struct curse_class_status *
local gets to within one instruction without it.

Only the US branch is decompiled; the original block carries 50 preprocessor
directives including two wholesale #ifdef EUROPE duplications.

Authored by Claude (Opus 5) under human direction. Confirmed by a matching
build: build/pmdsky.us/pmdsky.us.nds: OK (main.sha1 passes, so the ARM9 binary
matches and not only the packaged ROM).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 23:12:40 -07:00
cecilarmitais
c1a61413d6 Decomp ov11_022ED69C; correct BmaHeader field signedness
Decompiles ov11_022ED69C (410 instructions) out of
asm/overlay_11_022ECD24.s. The function was first in that file, so the
remainder splits to asm/overlay_11_022EDD14.s and main.lsf gains
src/overlay_11_022ED69C.o ahead of it.

include/ground_bg.h:

- MapRender 0x1C -> 0x54, adding unk1C/unk24/unk2C (two pointers each)
  and a 0x20 filler. This consumes GroundBg::fillerForNow2[112]
  exactly: 0x210 + 2*0x54 == 0x2B8, so no offset after it moves, and
  ground_bg.c only ever uses mapRender[0].
- GroundBg::unk1FC: four unreferenced u8 -> one s32.
- BmaHeader::numLayers/hasDataLayer/hasCollision: u16 -> s16. Retail
  reads these with ldrsh; the u16 declaration emitted ldrh and produced
  three wrong bytes in OVY_11.sbin. This function is their only reader
  in the tree -- every other use is a strh, identical either way -- so
  no other object changes.
- RGB_Array, the UnkStruct_2324CBC family, the three palette helpers,
  ov11_02320C18 and ov11_02320BF4/BE8 move here from src/ground_bg.c,
  which now includes them rather than redeclaring them.

asm/overlay_11_022ECD24_data.s has its .include repointed at the .inc
that survived the split; extract_function.py deletes the old one without
knowing about sibling objects in the same address range.

ov11_022EE9B0 and ov11_022EE8CC are still asm and are declared
provisionally in include/overlay_11_022ED69C.h from their call sites.

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>
2026-09-18 23:12:40 -07:00
AnonymousRandomPerson
a3d641227a Merge pull request #299 from AnonymousRandomPerson/main
Some checks failed
build / build (push) Has been cancelled
Synced from pmdsky-debug
2026-09-17 19:43:01 -04:00
AnonymousRandomPerson
c5b2361599 Synced from pmdsky-debug 2026-09-16 22:13:55 -04:00
AnonymousRandomPerson
88b7534029 Synced from pmdsky-debug 2026-09-16 19:13:16 -04:00
AnonymousRandomPerson
c0b9172888 Merge pull request #298 from darkruss48/main
Some checks failed
build / build (push) Has been cancelled
Decomp 13 functions, emptying six asm files
2026-09-16 17:48:27 -04:00
darkruss48
4c3524cdeb Address review 2026-09-15 19:14:06 +00:00
darkruss48
0e4b52cea5 Decomp 13 functions, emptying six asm files 2026-09-14 23:01:41 +00:00
AnonymousRandomPerson
c313f0090e Merge pull request #297 from darkruss48/main
Some checks failed
build / build (push) Has been cancelled
Decomp 8 functions, emptying seven asm files
2026-09-10 19:26:02 -04:00
darkruss48
a3fef4c1ac Clean up comments in mai_020527A8.c file
comments cleared
2026-09-10 23:44:39 +02:00
darkruss48
4558d17ea1 Clean up comments in sub_0200EB64 function
comments cleared
2026-09-10 23:41:47 +02:00
darkruss48
2c2c5c2a04 Decomp 8 functions, emptying seven asm files
Confirmed by a matching build: build/pmdsky.us/pmdsky.us.nds: OK.
2026-09-10 21:10:23 +00:00
AnonymousRandomPerson
02e838c934 Merge pull request #296 from AnonymousRandomPerson/main
Some checks failed
build / build (push) Has been cancelled
Synced from pmdsky-debug
2026-09-07 12:34:41 -04:00
AnonymousRandomPerson
db6076849a Rename quicksave symbols according to comments 2026-09-07 00:18:03 -04:00
AnonymousRandomPerson
8a05f6dac5 Synced from pmdsky-debug 2026-09-06 23:42:12 -04:00
AnonymousRandomPerson
f14ee2c91c Merge pull request #292 from SethBarberee/overlay_30
Some checks failed
build / build (push) Has been cancelled
Overlay 30
2026-09-04 23:46:31 -04:00
Seth Barberee
d30c1a4e3d Add initial chars to charmap 2026-09-04 13:13:23 -07:00
Seth Barberee
180541ceb8 finish func decomp of overlay_30 2026-09-04 12:45:57 -07:00
Seth Barberee
97ebe37ae4 more overlay_30 funcs 2026-08-27 08:10:35 -07:00
Seth Barberee
8c39cbea58 more decomp 2026-08-27 08:10:35 -07:00
Seth Barberee
3aa992262a decomp few more saving funcs 2026-08-27 08:10:35 -07:00
Seth Barberee
fcc7009d8b Match few funcs of overlay_30
Thanks to @taxicat for matching ov30_02382874
2026-08-27 08:10:35 -07:00
AnonymousRandomPerson
8588664e24 Merge pull request #295 from AnonymousRandomPerson/main
Some checks failed
build / build (push) Has been cancelled
Add some move effect labels
2026-08-24 22:23:34 -04:00
AnonymousRandomPerson
1527372edd Merge branch 'main' into main 2026-08-24 21:54:22 -04:00
AnonymousRandomPerson
768b41dd19 Add some move effect labels 2026-08-24 21:53:50 -04:00
AnonymousRandomPerson
51c365dbbe Merge pull request #294 from AnonymousRandomPerson/main
Some checks failed
build / build (push) Has been cancelled
Sync some param names with pmdsky-debug
2026-08-23 13:24:16 -04:00
AnonymousRandomPerson
5e0b63660c Fix JP build 2026-08-23 13:05:49 -04:00
AnonymousRandomPerson
cf1fa6f35a Sync some param names with pmdsky-debug 2026-08-23 12:47:25 -04:00
AnonymousRandomPerson
4145bcf47a Merge pull request #293 from AnonymousRandomPerson/main
Some checks failed
build / build (push) Has been cancelled
Synced from pmdsky-debug
2026-08-22 21:03:39 -04:00
AnonymousRandomPerson
f59becd3f6 Synced from pmdsky-debug 2026-08-22 20:45:50 -04:00
AnonymousRandomPerson
440d7b7dcd Merge pull request #291 from CecilArmitais/decomp-continued
Some checks failed
build / build (push) Has been cancelled
Decomp continued
2026-08-21 13:22:34 -04:00
AnonymousRandomPerson
c07a829640 Merge branch 'main' into decomp-continued 2026-08-21 12:54:55 -04:00
cecilarmitais
6425efdd8d Decomp 16 functions, emptying nine asm files
Third cleanup batch. Nine asm/*.s files and their .inc files are removed;
main.lsf drops from 1168 to 1159 objects.

  overlay_29_0234921C  IsCurrentMissionType, IsCurrentMissionTypeExact
  main_02058E8C        DisableAllIqSkills, EnableAllLearnableIqSkills
  main_02058D04        GetLearnableIqSkills
  main_02058C4C        GetUnlockedTactics, GetUnlockedTacticFlags
  main_020307B8        sub_020307B8, sub_020307EC
  overlay_29_02300D50  ov29_02300D50, ov29_02300DC0
  overlay_29_022E28D4  IsValidTargetEntity, CanSeePosition
  main_0206A750        sub_0206A7CC
  overlay_29_022E66D8  ov29_022E66D8, ov29_022E6724

main_0202AAA8.h: the coarse field_0xFC[0x9C] placeholder is split into
field_0xFC[8] / u32 field_0x104 / field_0x108[0x90]. Byte-neutral, and
nothing in the tree referenced the placeholder by name.

Two pre-existing declarations of landed functions are replaced with an
include of the header that now declares them. dungeon_recruitment.c
declared IsCurrentMissionTypeExact as (u32, u32) where it takes
(enum mission_type, u8); both call sites pass enum constants, so the ROM
is unchanged.

TACTICS_UNLOCK_LEVEL_TABLE, sub_02032984 and sub_0204E6FC/0204E770/
0204E780 are declared provisionally at the call site; no header declares
them yet.

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>
2026-08-21 01:41:15 -07:00
cecilarmitais
d9df74f0f6 Decomp 17 functions, emptying eight asm files
Second cleanup batch. Eight files are now gone:

  asm/overlay_29_022E1618.s   asm/main_0202B530.s
  asm/overlay_29_022DC65C.s   asm/main_0205EC38.s
  asm/overlay_29_0232124C.s   asm/main_02051788.s
  asm/main_02042B20.s         asm/main_02065BD8.s

main.lsf falls from 1175 objects to 1167.

Twenty-two functions matched across eleven files, but only seventeen land.
FixedPoint64ToInt, GetSpriteSize and RemoveItemFromKecleonShop1 did not match,
and their files therefore cannot be emptied; landing their already-matched
siblings would have converted two two-function files into two fresh
single-function fragments, so those two are held back as well. This batch
reduces the fragment count without creating any.

Three declarations follow the tree rather than the scratch: ov29_0232119C takes
struct entity * as its first parameter, ov29_023538B4 is already declared as a
u8 array, and ov29_022DC2B8 and ov29_022DC33C are declared u8 * in their
destination file. That last one is inconsistent with poly_text.h, which declares
ov29_022DC2B8 as struct unk_ov29_022DC240_t *; the file already carried the same
split for ov29_022DC240, so its local convention was followed rather than
changing pre-existing code. Worth unifying separately.

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>
2026-08-21 00:56:33 -07:00
cecilarmitais
be41c2f3d5 Decomp 20 functions, emptying six asm fragments
First cleanup batch. All twenty matched at score 0, and every file they came
from is now gone:

  asm/main_0204F9F4.s         2 functions
  asm/main_02017C50.s         4
  asm/overlay_29_02344B44.s   2
  asm/overlay_11_0230CCE0.s   2
  asm/overlay_11_022E9D6C.s   5
  asm/main_0201BEB0.s         5

main.lsf drops from 1181 objects to 1175, the first net reduction on this
branch. Each removal also retires the matching asm/include/*.inc.

Most of these reuse types landed earlier and add nothing: the OAM group reuses
unk_0201BCCC with unk_oam_sub and unk_oam_elem, and the overlay_11 fade group
reuses unk_023890A0 and unk_0238916C. Only unk_0238A098 and unk_023531A4 are
new.

Note for later cleanup work: six of the twenty are the last function in their
file, so emptying it leaves them with no following address and the object-level
size check cannot cover them. On a cleanup batch the matching build carries
more of the verification than usual.

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>
2026-08-21 00:32:47 -07:00
cecilarmitais
f968c89066 Decomp 48 functions in five groups
Ninth 5x10 batch; 48 of 50 matched at score 0 and land here.

  overlay_11_022FD308  LivePerformer accessors
  main_0204CF9C        GLOBAL_PROGRESS_PTR bit-array accessors
  main_020022C4        string, thread and card initialisation
  overlay_11_022E9D6C  screen-fade queries
  main_0203C774        state-machine steps

New placeholder structs: unk_022FE490, unk_022FE498, unk_020AFE60, unk_020AFE70,
unk_0209C7F4, unk_0238916C, unk_0229B004, unk_0229AFC0. The overlay_11 fade
group reuses unk_02388FC0 and unk_023890A0 unchanged.

Two are NOT here. SetPositionInitialLivePerformer sits at 225, where an
address computation is scheduled earlier than the target places it; six
variants moved nothing. sub_020024E4 sits at 35, a two-register swap in a
zero-fill loop, after both declaration orderings, a block scope, an extra
temporary and a while form. Both stay as assembly.

Matching finding, now in docs/MATCHING_TIPS.md: a two-word struct copy emits
the same four instructions as two field assignments but schedules both loads
first, which is what the target has. Writing the fields separately interleaves
load and store, and hoisting them into locals merges the stores into an stm.

The OS wrappers drop their local declarations of nitro functions, which reach
every translation unit through the prefix header and disagreed on return type.
OS_ResetSystem keeps its extern; it is declared in no reachable header.

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>
2026-08-21 00:13:12 -07:00
cecilarmitais
c61f8ec2d7 Decomp 49 functions in five groups
Eighth 5x10 batch; 49 of 50 matched at score 0 and land here.

  overlay_11_022FAC54  LiveObject accessors
  overlay_11_022E46FC  coroutine table and special recruitment
  main_020325AC        further inventory-menu paging
  overlay_17_0238A754  menu state setters
  main_0201BAC8        OAM attribute copying

New placeholder structs: unk_022FD1A0, unk_02324FA0, unk_02320904,
unk_C_ROUTINES, unk_0238BE00, unk_0201BCCC with unk_oam_sub and unk_oam_elem.
struct unk_020332AC gains field_0xBC and field_0xD0, splitting two byte arrays
without changing its size; no already-landed function changes.

GetCoroutineInfo is NOT here. It reaches 30 -- two rows, a register swap between
the base pointer and the record pointer, with every instruction otherwise
identical. Eight structural variants and six declaration orderings were tried;
restructuring around a record pointer took it from 500 to 30 and nothing since
has moved it. It stays as assembly.

Two matching findings, both in docs/MATCHING_TIPS.md. A switch needs a fourth
case before MWCC emits a binary split rather than a flat compare chain, which is
now the second batch where that closed a function. And x == 4 || x == 5 folds
into a range test at every width tried, where the target keeps cmp/cmpne; the
double negation !(x != 4 && x != 5) blocks the fold and keeps the arm order.

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>
2026-08-20 23:04:46 -07:00
cecilarmitais
e6530b4337 Decomp 50 functions in five groups
Seventh 5x10 batch; all fifty matched at score 0.

  overlay_11_022EE5E4  LiveActor accessors
  overlay_11           language and string helpers
  main_020325AC        inventory-menu paging and scaling
  overlay_29_0234B4CC  alert-box wait, portrait init, message log
  overlay_18           further LINK_SHOP_PTR setters

New placeholder structs: unk_022FAB44, unk_020332AC, unk_0234BAC0. struct
unk_0238C950 gains an s8 at offset 4, splitting its leading byte array without
changing its size; no already-landed function changes. struct unk_023537CC is
copied from the neighbouring sources that already define it, and struct iovec
now comes from file.h rather than a local copy.

Seven callees were already declared elsewhere in src/ and are reused verbatim
rather than redeclared: AdvanceFrame, DUNGEON_BUTTON_INPUT, MESSAGE_LOG_INFO,
GetSimpleMenuResult__0202B870, GetLanguage, LoadFileFromRom and
UnkMapRelatedFunc.

docs/MATCHING_TIPS.md gains three entries: a case label sharing default's body
still shapes the compare chain; a masked value promotes to int, so an unsigned
compare needs a cast; and the two malformed disassembly shapes, with the
reachability test that separates a merged block from an ordinary loop.

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>
2026-08-20 15:28:55 -07:00
cecilarmitais
090d9f3159 Decomp 50 functions in five groups
Sixth 5x10 batch; all fifty matched at score 0 and landed.

  overlay_29_022DC694  HEAD  team-stats forwarders, a 10-argument forwarder,
                             and a 22-entry table search
  overlay_29_022E4714  HEAD  PlayEffectAnimationEntity wrappers
  overlay_29_022E37DC  TAIL  same family, merging into overlay_29_022E406C.c
  overlay_18           mid   LINK_SHOP_PTR state setters
  main_020022C4        mid   Nitro OS thread and mutex wrappers

New placeholder structs: unk_022DC694, unk_02353518, unk_0238C950,
unk_020027E8, unk_0229B0E0. The OS wrappers use nitro's own OSThread and
OSMutex types, which every translation unit already has through the prefix
header, rather than private tags.

Two spellings a reviewer should weigh, both recorded in the note:
_0229B0E0 is declared volatile because the target reloads it where any
ordinary spelling is common-subexpression-eliminated, and ov29_022DC78C
matches in byte-offset form rather than array indexing because the target
keeps the offset live in a separate mul.

Group selection now rejects malformed disassembly: 0.4% of asm blocks end
without a return (a .global mid-body split one function in two) and 6.5% are
several functions merged into one block (no .global marks the later entry
points). Neither is decompilable as written.

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>
2026-08-20 15:09:01 -07:00
cecilarmitais
1dea0a2571 Decomp 10 DWC functions into lib/src; they need the SDK build rule
The group from asm/overlay_00_022DB1A4.s that the previous commit could not
land. It does not belong in src/: these are Nintendo Wi-Fi Connection library
functions, and src/** is built with OPTFLAGS -O4,s, which inlines a small callee
whose body is visible in the same translation unit. lib/** is built with
OPTFLAGS_SDK -O4,p, which does not. Landed into lib/src/overlay_00_022DB1A4.c
and listed in main.lsf under OVY_0, all ten are byte-identical to the original
assembly.

A decomp.me scratch cannot see this: it declares every callee extern, so no body
is visible and nothing can be inlined, and the group scored 0 either way.

lib/src was already in LIB_SRC_SUBDIR without existing on disk, so no makefile
change is needed. The object also receives the full defines, not just
GLB_DEFINES; none of these functions carries a region conditional in any case.

docs/MATCHING_TIPS.md carries the mechanism, a minimal reproducer, and a
one-object diagnostic that does not need a full build.

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>
2026-08-20 14:15:03 -07:00
cecilarmitais
c9d0c76608 Decomp 38 functions across four groups; drop a group to an inlining trap
Fifth 5x10 batch. 48 functions matched at score 0; 38 land here.

  overlay_29_022E37DC  -> src/overlay_29_022E406C.c   (new, 10)
  overlay_29_022E41F0  -> src/overlay_29_022E4338.c   (new, 10)
  overlay_11_022E9B84  -> src/overlay_11_022E9A78.c   (merged, 10)
  main_02048764        -> src/main_02048B48.c,
                          src/main_02048BB4.c,
                          src/main_02048CB8.c         (new, 8)

New placeholder structs: unk_020AFF38, unk_022AAE74. Two existing placeholders
in overlay_11_022E9A78.h are refined by this batch's evidence -- u8 field_0x4[8]
becomes s32 field_0x4 + s32 field_0x8, and u8 field_0x0[0x44] gains s16
field_0x14. Both keep their total size and no pre-existing function changed.
overlay_29_022E406C.h and overlay_29_022E4338.h gain dungeon_mode.h, which they
need for struct entity.

The fifth group -- ten DWC functions from asm/overlay_00_022DB1A4.s -- is not
here. All ten scored 0 and still changed OVY_0's size by 16 bytes, failing
main.sbin and OVY_0-OVY_9. A decomp.me scratch declares callees extern, so MWCC
cannot inline them; landing the group into a .c that defines those callees makes
the bodies visible and -O4,s inlines them. The target's calls show retail kept
these in separate translation units. docs/MATCHING_TIPS.md gains an entry with
the mechanism and a one-object diagnostic that does not need a full build.

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>
2026-08-20 03:18:59 -07:00
cecilarmitais
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>
2026-08-20 01:30:22 -07:00
cecilarmitais
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>
2026-08-20 01:07:35 -07:00