docs(issues): #37 — Investigation 2 narrows bug to SubPalette coverage gaps

Five parallel agents + dat probes ruled out:
- byte-level decode primitive (matches ACViewer)
- polygon emission (no ST_DOUBLE / Surface.Type & 6 issues)
- per-PART texture-override scoping (correctly per-MeshRef'd)
- SubPalette indexing convention (full-size 2048 palettes, *8 wire un-pack
  is single-applied)

Smoking gun: for +Acdream the server sends 10 SubPaletteSwap ranges that
overlay palette indices [0..320), [576..1024), [1392..1488), [1728..1920).
The complement — [320..576), [1024..1392), [1488..1728), [1920..2048) —
is NOT overlaid. Base palette 0x0400007E at those indices has
red/skin tones. Coat texture UVs sampling those non-overlaid indices
render as visible "skin stub at top of coat".

Either ACE sends incomplete SubPaletteSwap data, or retail does extra
client-side ClothingTable computation we (and ACE) don't.

Diagnostic harness now lives at tools/InspectCoatTex/Program.cs;
GameWindow's DUMP_CLOTHING also probes runtime SubPalette dat sizes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-05 14:45:50 +02:00
parent a3f53c2644
commit 5937ebe1c5
3 changed files with 368 additions and 16 deletions

View file

@ -310,22 +310,35 @@ What we confirmed (data is correct):
matches ACME's `StaticObjectManager.cs:256-258` and retail decomp's
`Frame::combine` at `0x00518FD0`.
**Remaining hypothesis space (untested):**
**Investigation 2 (2026-05-04, 5 parallel agents + dat probes):**
1. **Texture decode produces skin pixels** for `0x05001AFE/0x05001AFC`
where ACME / retail produces coat pixels. Compare our SurfaceDecoder
against ACME's `TextureHelpers.cs` for INDEX16 / palette-indexed
chains.
2. **Polygon-to-surface mapping off-by-one.** Specific polygons of
part 9 reference an unintended surface. Add a dump: for each polygon
in gfx 0x0100120D, print `PosSurface` index + the resolved Surface id.
3. **Multi-layer texture composition retail does and we skip.** AC's
"ApplyCloth" or similar layered texture step. Grep
`acclient_2013_pseudo_c.txt` for `BlendBaseLayer`, `LayerSurfaces`,
any composition method that combines multiple textures into one.
4. **UV mapping bug.** Part 9's polygon UVs map to a skin region of
the coat texture. Dump per-vertex UV vs vertex Z; if a high-Z vertex
has UV.v near a skin region, that's the source.
ALL of the obvious hypotheses ruled out:
- **Byte-level decode primitive matches ACViewer.** INDEX16/P8/DXT/BGRA paths are byte-identical.
- **Polygon emission matches retail.** All 43 polygons of gfx `0x0100120D` are `SidesType=0` (ST_SINGLE), all surfaces are `Base1Image` — NO ST_DOUBLE polygons we'd be missing, NO surfaces lacking the `Type & 6` bits that retail's `DrawPolyInternal` skips.
- **Per-PART texture-override scoping is correct.** `resolvedOverridesByPart[partIdx]` gets per-MeshRef'd; not a global flat map (Agent 3's claim was wrong).
- **SubPalettes are full-size (Colors.Count=2048) palettes.** Our `subPal.Colors[idx]` indexing matches ACViewer's `newPalette.Colors[j + offset]`.
- **The `*8` wire un-pack is correctly single-applied** (parser stores raw bytes; ComposePalette multiplies once).
**The actual smoking gun (Investigation 2):**
For `+Acdream` the server sends 10 SubPaletteSwap ranges that overlay palette indices:
`[0..320)`, `[576..1024)`, `[1392..1488)`, `[1728..1920)`. **The complement — indices `[320..576)`, `[1024..1392)`, `[1488..1728)`, `[1920..2048)` — is NOT overlaid.** Base palette `0x0400007E` at those indices contains the original red/skin tones (sampled values: `0x46 0x22 0x04`, `0x4A 0x28 0x09`, etc).
If the coat texture's UVs at the upper region map to texel-bytes whose palette index lands in one of those non-overlaid ranges, those pixels render with base-palette skin tones. That's the visible "skin stub at the top of the coat".
**Working hypothesis:** either
1. ACE sends incomplete SubPalette ranges (retail-original would cover the full palette)
2. Retail does *additional* client-side compute that ACE pre-resolves wrongly
3. The base palette `0x0400007E` itself is supposed to have coat colors at those indices in retail's interpretation (different palette decode)
**Next investigation (deferred):**
- Diff ACE's `WorldObject_Networking.cs` CharGen ObjDesc construction against retail's
`ClothingTable::BuildObjDesc` (`acclient_2013_pseudo_c.txt:436261`). Check if ACE
actually walks every CloSubPaletteRange in the chosen PaletteTemplate, or skips some.
- RenderDoc capture: confirm which texel/palette-index the upper-region polygons sample.
- `tools/InspectCoatTex/Program.cs` is the diagnostic harness — extend it.
**Files (diagnostic env vars committed for next-session reuse):**