mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
85876ec7cb
Real GPU copies the texpage attribute word carried inside every textured polygon (GP0 0x24-0x3F, texture bit set) into the draw-mode state (GPUSTAT bits 0-8), exactly like GP0(E1) bits 0-8 — Beetle runs SetTPage(CB[4 + ((cc>>4)&1)] >> 16) on every such command (beetle-psx mednafen/psx/gpu.cpp:1070). So the polygon's OWN word (not the last E1) selects its semi-transparency mode, and later rect/sprite prims (which carry no texpage word) consume the state the polygon left behind. We fetched texels from the prim's page but blended with the stale E1 global, and never updated the page state rects depend on. Effect: additive glows blended with whatever mode the last E1 happened to set, flipping bright light halos into dark/black blobs intermittently (OT bucket order decides which prim precedes, hence camera/distance dependence). Proven on Ape Escape attract frame 60052: nine op-0x2E firework quads at the artifact coordinates carry prim mode 1 (B+F) while the last E1 set mode 0 (B/2+F/2) — rendered as dark maroon blobs; Beetle renders the same beat as bright fireworks. Post-fix sweep shows siren-hat glow halos, MONKEY PARK marquee bloom, and lava glow restored across two full attract cycles. Poly words do not touch dither/draw-to-display (E1-only bits 9-10) nor texture-disable (bit 11 latches only under GP1(09h) allow-change). All backends inherit the fix via gr_set_semi_transparency / current_texpage(). Faithful-core fix for all titles; documented as D12 in accuracy/axis5_gpu.md (the audit had marked semi-transparency FAITHFUL — the modes were, their state source was not). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>