#39
d3d9: initialize inactive fixed-function light uniforms
RAN EP7's character-selection scene can render flickering magenta barrels and a corrupted sleeve color. The generated fixed-function vertex shader evaluates all eight light slots before masking inactive contributions. Reused uniform-ring storage can contain NaNs, which survive multiplication by zero and corrupt a color channel.
Clear the complete 896-byte light region before packing enabled lights. Active light layout and neighboring constants are preserved. Add a host regression that extracts the production packer and exercises NaN-filled storage with zero through eight active lights.
Validation:
- On the current
ios-portbase, the identical ASan/UBSan check reproduces stale bytes in inactive slot zero. With this patch, all nine active-count cases pass, including active data and bounds checks. - Prior real-device validation on 2026-10-18 used this same patch in Madeira build21 on an iPad Air5/M1, with the default i386 frontend. The matching two-second RAN character-selection capture changed from 6/19 bad barrel frames to 0/19; magenta sleeve pixels were also eliminated. Original texture and alpha bytes were preserved.
- The device-validated build compiled both the i386 frontend and ARM64 object and passed app build/signing checks. This PR preparation reran the host regression; it did not reinstall the app or repeat gameplay.
Host check: python3 tests/d3d9/check_ffp_light_upload.py.