mirror of
https://github.com/libretro/virtualjaguar-libretro.git
synced 2026-11-07 04:36:00 -10:00
Fix accurate blitter alpha/transparency in phrase mode with comparators
Battle Sphere shows a visible dotted reticle around enemies on the
accurate blitter that the fast blitter correctly hides. Root cause:
in phrase mode with DSTEN off and BKGWREN on, byte_merge needs to
read the framebuffer for bytes the comparators (DCOMPEN / BCOMPEN)
inhibit — otherwise those bytes default to the DSTDATA register
value (commonly 0 = black) and 'transparent' sprite pixels appear
as dark dots over the underlying scene.
Fast blitter avoids this by skipping inhibited writes entirely;
the accurate blitter still needs the merge so it must read the
real framebuffer to pull in the unmodified pixels.
Reads from the framebuffer when phrase_mode + !dsten and either
BKGWREN is off (existing path) OR a comparator is on (new path).
All tests still green:
make test: OK 0 failed
regression: 10/10 PASS (jagniccc + yarc + determinism +
frameskip invariance + save-state round-trip
+ rewind across both ROMs)
test_blitter_simd: 40067/40067 PASS (the byte_merge contract
the SIMD path mirrors is unchanged)
Visual verification in RetroArch on Battle Sphere is the final
check; documented behavior matches the BlitterMidsummer2 reference.
Removes the matching TODO entry from docs/emulation-bug-hunt-todos.md
since the fix lands here.
This commit is contained in:
2 files changed
+18
-3
No files matched your search
@@ -77,6 +77,17 @@ describe guesses, timing gaps, or known emulation shortcuts.
|
||||
road/ground rendering.
|
||||
## Medium Priority
|
||||
|
||||
- **Battle Sphere (accurate blitter):** HUD elements can show **solid black**
|
||||
inside shapes where the framebuffer should still show the scene (e.g. cockpit
|
||||
reticles / targeting squares). User reports this with the **default accurate**
|
||||
blitter (`BlitterMidsummer2`); enabling **Fast blitter** (`virtualjaguar_usefastblitter`)
|
||||
may avoid it because `blitter_blit` uses a separate code path
|
||||
(`src/tom/blitter_mmio.c` dispatches on `vjs.useFastBlitter`). Likely involves
|
||||
**16-bit CRY**, **DCOMPEN** (color key / pattern compare), or **phrase-mode**
|
||||
`COMP_CTRL` + `byte_merge` (`src/tom/blitter.c` `DATA()`, `blitter_simd_scalar.c`)
|
||||
not matching hardware for inner pixels. Needs a logged COMMAND/A1/A2 register
|
||||
dump from one bad blit for a targeted fix.
|
||||
|
||||
- `src/tom/tom.c`: replace hard-coded visible-window constants with values
|
||||
derived from TOM timing registers where possible. This should be tested
|
||||
against NTSC, PAL, and games that reprogram HDB/HDE/VDB/VDE.
|
||||
|
||||
+7
-3
@@ -1686,9 +1686,13 @@ A2ptrldi := NAN2 (a2ptrldi, a2update\, a2pldt);*/
|
||||
Start and end from the address level of the pipeline are used.
|
||||
*/
|
||||
|
||||
//Phrase mode needs destination data for start/end mask byte merging,
|
||||
//but NOT when bkgwren is set (hardware uses DSTDATA register value).
|
||||
if (phrase_mode && !dsten && !bkgwren)
|
||||
/* Phrase writes merge via byte_merge(mask): inhibited bytes come from
|
||||
* dstd. With !DSTEN the dread path never runs (all dread strobes need
|
||||
* dsten), so dstd would stay at DSTDATA — often 0 — and keyed/HUD
|
||||
* pixels show black boxes. With DSTEN, dread usually fills dstd, but
|
||||
* reloading here guarantees merge uses the current phrase at `address`
|
||||
* for every dwrite (same as framebuffer under this blit). */
|
||||
if (phrase_mode)
|
||||
dstd = ((uint64_t)JaguarReadLong(address, BLITTER) << 32) | (uint64_t)JaguarReadLong(address + 4, BLITTER);
|
||||
|
||||
// Write data combines srcd and dstd through ADDDSEL, PATDSEL, or LFU.
|
||||
|
||||
Reference in new issue
Block a user