3 Commits

Author SHA1 Message Date
AnonymousRandomPerson
f59becd3f6 Synced from pmdsky-debug 2026-08-22 20:45:50 -04:00
cecilarmitais
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>
2026-08-17 04:42:41 -07:00
cecilarmitais
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>
2026-08-17 03:51:32 -07:00