Skip to content

Decomp we object4 - #72

Merged
roengstrom merged 9 commits into
mainfrom
decomp-we_object4
Aug 23, 2026
Merged

Decomp we object4#72
roengstrom merged 9 commits into
mainfrom
decomp-we_object4

Conversation

@roengstrom

Copy link
Copy Markdown
Owner

No description provided.

func_800A9300  particle renderer: steps and projects every live slot in the
               D_800D9CB0 pool, sizes the sprite from the slot's 4.12 scale,
               and emits a TILE or POLY_FT4 into the scene's OT.
func_800A8C1C  colour-zone palette blender: walks the D_800C9EE8 zone list and
               fades the five palette stops and the GTE colour matrix towards
               whichever zone the camera is inside, via GTE INTPL.
func_800A7590  backdrop OT linker: pushes the D_800D42D0 record pool and the
               fixed prims onto two bone slots of the ordering table.
func_800A64DC  strip sub-OT builder: expands four VRAM strips per band into two
               depth-cued copies and packs a DR_MOVE into every sub-slot, then
               chains each record's slots into a mini ordering table.
func_800A6BE0  strip-pool primer: stages each band's strips into scratch VRAM,
               builds the draw environments and quads, and points every DR_LOAD
               at its 1x1 source pixel.
func_800AB06C  kind-11 particle spawner at a fixed world position.

All six are dead code in the retail build -- no jal in any remaining assembly,
no C caller, and their addresses appear nowhere in world.bin, which also covers
dispatch tables. They are documented as such, and the reachability notes on the
functions already in this file were corrected to match: func_800A9CC0 is now
called from C, and func_800A6A74 was never called at all.

Types the decomp settled:

  Slot30 +0x10 was padding but is an SVECTOR holding the camera-relative
  position; +0x20 was proj_x/y/z but is the per-tick velocity the spawner
  seeds and func_800A9CC0 integrates; +0x2C was "life" but is a 4.12 scale
  that spawns at PARTICLE_SCALE_ONE (= 1.0). SLOT_FLAG_JITTER_LIFE is renamed
  SLOT_FLAG_JITTER_SCALE to match, confirmed against func_800AC0A0.

  KindParams grows from two known fields to the full per-kind sprite
  descriptor: texture u/v, CLUT, size, prim kind, colour, frame count and
  divisor, scale rate, billboard shape and velocity increment.

  func_800A9CC0's second parameter was typed WorldParticle * -- the call site
  proves it is a KindParams *. WorldParticle was a duplicate view of Slot30
  and is deleted.

  TILE::w,h and SPRT::w,h were u16 where the SDK declares short; the target
  reads them with lh, so the unsigned form cost the match.

SDK additions, all verbatim from Psy-Q - 46/INCLUDE/: gte_sttr,
gte_ReadRotMatrix, gte_ldlvl, gte_ldfc, gte_SetFarColor, gte_lddp, gte_strgb
and gte_intpl (re-encoded as a real COP2 word per this header's convention),
plus DR_MOVE, DR_LOAD, SetDrawMove, SetDrawLoad, SetDrawEnv and setPolyF4.
SetDrawMove, SetDrawLoad and SetDrawEnv also needed adding to
symbols.extern.txt or the overlay fails to link.

Retired three raw names that were really SDK entry points, each of which was
a second declaration of an already-named symbol: func_8003F4A4 is SquareRoot0
(10 sites; the duplicate in common.h is gone), func_800491E8 is DrawPrim, and
func_80041E84 is ratan2 -- which had three declarations under two names and
was misfiled in an overlay header, so it moves to libgte.h beside rsin/rcos.
StoreImage was being called with no declaration at all.

func_800A8C1C keeps a forward goto to reach the shared exit. The structured
alternative costs three instructions and cannot match at any percentage; the
tail-duplication route only reaches 95% because gcc forwards the just-stored
bytes in the default path. Approved deliberately and noted in the source.

rm -rf build asm && make split && make verify: all 25 targets Match.
The world overlay had no bss subsegment, so every translation unit's .bss was
empty and parked at 0x800C8635 while splat handed all 350 addresses above the
loaded image straight to the linker as assignments (D_800D3930 = 0x800D3930).
Under that layout the C file cannot own any of that memory: marking one of
those externs static compiles and links with no diagnostic and silently
produces a mismatched world.bin, because the object lands at the .bss cursor
rather than at its address.

Model the region instead. we_object4 takes 0x800D3510..0x800D4E80 -- the two
strip sub-OT pools, the flat quads, the draw environments and the DR_LOAD
record pool -- as a [.bss, we_object4] subsegment, with splat-owned fillers
either side. Those thirteen objects become static definitions in address
order and leave world.h, which no longer needs to publish four of them; the
comment describing the sub-OT pool layout moves to the definitions it
describes.

Two objects in the block are not accounted for by anything that references
them: 4 bytes at 0x800D398C and 8 at 0x800D3A48. gcc packs .bss flat rather
than re-creating the original's alignment, so without them the section is
0xC short and every bss symbol above the block shifts down -- which surfaces
as byte differences in we_object1's text, nowhere near this file. They are
declared as named padding with their purpose recorded as unknown.

The block totals 0x1970 and ends exactly where D_800D4E80 begins, so
declaration order is address order and resizing one object shifts the rest.

rm -rf build asm && make split && make verify: all 25 targets Match.
@decomp-dev

decomp-dev Bot commented Aug 20, 2026

Copy link
Copy Markdown

Report for SLUS_008.92 (72a11f5 - 9186e72)

📈 Matched code: 42.42% (+1.03%, +11884 bytes)
Total data: 26284 bytes (+6512 bytes)
📈 Matched data: 56.99% (+14.47%, +6572 bytes)

✅ 9 new matches
Unit Item Bytes Before After
ovl/world/we_object4 .bss +6512 100.00% 100.00%
ovl/world/we_object4 func_800AA210 +2872 0.00% 100.00%
ovl/world/we_object4 func_800A9300 +2496 0.00% 100.00%
ovl/world/we_object4 func_800A6BE0 +1916 0.00% 100.00%
ovl/world/we_object4 func_800A8C1C +1592 0.00% 100.00%
ovl/world/we_object4 func_800A7590 +1448 0.00% 100.00%
ovl/world/we_object4 func_800A64DC +944 0.00% 100.00%
ovl/world/we_object4 func_800AB06C +616 0.00% 100.00%
ovl/world/we_object4 .rodata +60 0.00% 100.00%

It is the one of the four functions flagged by the contribution check that
really has no caller outside its own unit -- confirmed against the generated
asm, not just the C sources.

The other three stay as they are: func_800A61CC is called from
bc_object19/func_800D72C8, func_800AAFB8 from bc_object5/func_800AB008, and
func_800AEACC from two places in bc_object6, all still assembly. Making them
static fails the link outright.

make verify: 25/25 Match.
The unit had none, so its 23 externally-called functions were reachable only
by whatever declaration each caller happened to write. The header now owns
them, generated from the definitions rather than retyped, and the unit
includes it.

Only functions with a caller outside the unit are exported -- ten more are
defined here and called from nowhere yet, so they stay unexported rather than
being published on the assumption someone will want them.

Adding prototypes can change codegen where a caller was relying on an
implicit declaration, so this was verified rather than assumed.

make verify: 25/25 Match.
Self-review of the header I just added: five of its 23 prototypes were
already declared elsewhere, so I had left duplicates rather than removed
them. Four -- func_800B0248, func_800B0574, func_800B0600 and func_800B0F7C
-- move out of battle.h, and their four callers include the owner's header
instead.

The fifth is a genuine disagreement rather than a duplicate. bc_object7
defines func_800B0754 with a u16 fourth parameter; bc_object4 declares it
(s32, s32, s32, s32). Taking it from the owner's header makes gcc convert
the argument at the second call site and battle.bin stops matching, so the
original TU evidently saw the wider prototype. The local declaration stays,
with a comment saying why it is not taken from the header -- and the explicit
(u16) cast at the other call site is the workaround that lying prototype
already required.

make verify: 25/25 Match.
Signed-off-by: rengstrom <engstrom.robin@gmail.com>
Signed-off-by: rengstrom <engstrom.robin@gmail.com>
@roengstrom
roengstrom merged commit be7b8c3 into main Aug 23, 2026
1 check passed
@roengstrom
roengstrom deleted the decomp-we_object4 branch August 23, 2026 21:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant