Skip to content

Drive the dormant overrideTexture path from host hi-res texture lookups - #5

Open
vjravenlight wants to merge 2 commits into
SlickAmogus:masterfrom
vjravenlight:feat/hires-override-hook
Open

Drive the dormant overrideTexture path from host hi-res texture lookups#5
vjravenlight wants to merge 2 commits into
SlickAmogus:masterfrom
vjravenlight:feat/hires-override-hook

Conversation

@vjravenlight

Copy link
Copy Markdown

Companion to SlickAmogus/silent-hill-decomp's hi-res texture override system (pc_port/src/hires_override.c): the game has been registering hi-res replacement textures since that file landed, but nothing ever drew them — HiresOverride_LookupByTpageClut had no callers.

PsyCross already contains the perfect delivery mechanism: the DR_PSYX_TEX / overrideTexture path (forces a TF_32_BIT_RGBA split and binds a plain RGBA texture with the direct-sample shader) — but no host ever emits that packet, so it was dormant. This PR feeds it from the host's override table:

  • ApplyHiresOverride(tpage, clut) before AddSplit in POLY_FT3/FT4/GT3/GT4 and SPRT/SPRT_8/SPRT_16. Since textureId is already part of the split key, batches open and close exactly at matching prims — no batching rework.
  • The lookup is a weak stub in PsyX_GPU.cpp; hosts that don't provide the strong symbol (REDRIVER2 etc.) link unchanged and the hook is a no-op returning 0.
  • overrideTextureWidth/Height are fed the original TIM's native pixel size, so the prim's tpage-relative UVs map 0..1 over the replacement regardless of its upscale factor.
  • ClearSplits() resets the override so it can't leak across frames.
  • gte_shader_32_rgba gains if (fragColor.a < 0.5) discard; — PSX colour-0 transparency for overrides. Opaque prims ignore GL blending, so transparent texels must discard; authored soft alpha ≥ 0.5 still blends on semi-transparent prims (SRC_ALPHA carries the STP-style 50% blend).

Tested end-to-end with the SH1 port: a PNG override registered for the boot-logo TIM renders in-game (see the game-side PR in silent-hill-decomp, which adds PNG loading + discovery).

Known v1 limitation: a surface wider than one tpage (e.g. a 320px background drawn as two tpage-sized prims) samples the whole override from each prim (UV origin per tpage, not per TIM). Single-tpage textures — items, characters, HUD sprites — map correctly. A follow-up can thread the tpage→TIM origin offset through a uniform.

🤖 Generated with Claude Code

The DR_PSYX_TEX / overrideTexture mechanism (TF_32_BIT_RGBA split +
direct-sample shader) was never emitted by any host. Feed it per textured
prim from HiresOverride_LookupByTpageClut (weak stub here; strong table
lives host-side), so registered hi-res replacements actually draw:

- ApplyHiresOverride() before AddSplit in POLY_FT3/FT4/GT3/GT4 and
  SPRT/SPRT_8/SPRT_16. textureId is already part of the split key, so
  batches open/close exactly at matching prims.
- overrideTextureWidth/Height carry the ORIGINAL TIM native pixel size,
  so tpage-relative UVs map 0..1 across any upscale factor.
- Reset the override in ClearSplits so it cannot leak across frames.
- gte_shader_32_rgba: discard alpha < 0.5 — PSX colour-0 transparency
  for overrides (opaque prims ignore blending, holes must discard);
  authored soft alpha above the cutoff still blends on semi-trans prims.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Prim UVs restart at each tpage, so a TIM spanning several tpages (320px
backgrounds, the boot logos) drew every chunk sampling the override from
x=0 - the image duplicated per chunk. The lookup now also returns the
tpage origin position inside the replaced TIM (native texels); it rides
the split in drawenv.tw.x/y (tw.w/h already carry the size), is part of
the split-keep key so two chunks of the same override cannot share one
uniform, and lands in the 32-bit shader as u_texOffset added to the UVs
before texelSize normalization. Removes the known v1 limitation from
the original hook commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vjravenlight

Copy link
Copy Markdown
Author

Follow-up pushed: the known v1 limitation (multi-tpage surfaces duplicating the override per chunk) is now fixed - the lookup returns the tpage origin's offset inside the replaced TIM and the 32-bit shader adds it via a new u_texOffset uniform (split-keyed so chunks can't share one uniform value). Builds clean, boots and runs; in-game visual pass on a wide background pending.

SlickAmogus pushed a commit that referenced this pull request Jul 10, 2026
…lookups

Port of PR #5 onto current master. Textured prims (POLY_FT3/FT4, GT3/GT4,
SPRT/8/16) now consult a host-provided HiresOverride_LookupByTpageClut
(weak stub here, so non-SH hosts link unchanged) and route through the
existing TF_32_BIT_RGBA override path when the host registered a
replacement for the prim's tpage/clut.

- overrideTextureOffsetX/Y + u_texOffset uniform: shifts tpage-relative
  UVs when the prim's tpage sits partway into the replaced TIM (multi-
  tpage surfaces draw as several prims whose UVs restart per tpage).
- Splits additionally key on the offset (carried in drawenv.tw.x/y, which
  were dead for splits; tw.w/h were already repurposed) so two chunks of
  one override texture can't batch into one offset uniform.
- gte_shader_32_rgba: alpha<0.5 discard for PSX colour-0/PNG-hole
  transparency on opaque prims; soft alpha >=0.5 still blends on
  semi-transparent prims.
- Beyond the PR: DR_PSYX_TEX packet state is tracked separately and
  restored on lookup miss / ClearSplits, so that path keeps its exact
  persist-until-changed semantics instead of being zeroed per prim.

Byte-identical when the host registers no overrides: lookup returns 0,
all override state stays 0, split boundaries and bound shaders unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FuUfmVsV1UrMpoBqRmUhMv
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.

2 participants