Repository navigation
Voodoo: Fix nccTable0 Q2 writes landing in the I2 coefficient - #7926
Merged
Merged
Conversation
The SST_nccTable0_Q2 case assigned nccTable[tmu][0].i[2] instead of q[2], so the Q2 chroma coefficient of NCC table 0 was never stored and i[2] ended up holding whichever of the two registers the driver wrote last. Every other NCC case in the function, including the table 1 twin SST_nccTable1_Q2, writes its own component. voodoo_update_ncc() reads i[] and q[] independently, so 64 of the 256 decoded entries of table 0 always came out with the wrong colour, and 112 of 256 in the usual I before Q write order, for Y4I2Q2 and A8Y4I2Q2 textures.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Textures in the NCC (YIQ) compressed formats decoded through NCC table 0 come out with the wrong colours on the emulated Voodoo. Table 1 is fine, so the same texture looks right or wrong depending only on which table the game selected through TEXTUREMODE_NCC_SEL.
The cause is in
voodoo_reg_writel(). TheSST_nccTable0_Q2case assignsvoodoo->nccTable[tmu][0].i[2]instead ofq[2](src/video/vid_voodoo_reg.c:1152 and :1156). I2 (0x33c) and Q2 (0x34c) are two different registers (src/include/86box/vid_voodoo_regs.h:234 and :238), but both cases writei[2], so nothing in the tree ever writesnccTable[tmu][0].q[2]. Two things go wrong: the Q2 coefficient of table 0 keeps its reset value of zero, andi[2]ends up holding whichever of the two registers the driver wrote last. Every other NCC case in the function writes its own component, including the table 1 twin at src/video/vid_voodoo_reg.c:1337.voodoo_update_ncc()indexesi[]andq[]independently, withi = (col >> 2) & 3andq = col & 3(src/video/vid_voodoo_display.c:65-66). So table 0 decodes wrong in at least the 64 entries with Q index 2, which lose the Q2 coefficient whatever the driver does. When the driver writes I0 to I3 before Q0 to Q3,i[2]is clobbered as well and 112 of the 256 entries are wrong: 64 with Q index 2, 64 with I index 2, 16 of them shared. That table is whatvoodoo_use_texture()uses for TEX_Y4I2Q2 and TEX_A8Y4I2Q2 (src/video/vid_voodoo_texture.c:336 and :428). The path is shared by Voodoo 1, Voodoo 2, Banshee and Voodoo 3.The change is two characters on two lines,
i[2]toq[2], matching the shape of the table 1 case. The fall-through chain above it is untouched: it is the bit 31 texture palette write path and it is correct.How I checked it.
clang -fsyntax-only -Wall -Wextra -std=gnu11on src/video/vid_voodoo_reg.c is silent both before and after the change, so no new diagnostics, and clang-format with the repo style leaves the changed hunk alone.I did not run this in the emulator, as I have no Qt build here, so the argument is at code level with table 1 as the in-tree control. I built a standalone harness that extracts the NCC register switch,
voodoo_update_ncc()and the register offsets verbatim from the tree, writes the same Y, I and Q coefficients to both tables, and compares the two decoded 256 entry lookups. Before the change 112 of 256 entries differ between table 0 and table 1 in I then Q write order, and 64 of 256 in Q then I order; after it, 0 differ in either order. Writing the same registers again with bit 31 set gives the same palette checksum before and after, so the palette path is unaffected.Checklist
References
The evidence is in the tree. The SST register map gives each NCC table twelve distinct registers, Y0 to Y3 at 0x324 to 0x330, I0 to I3 at 0x334 to 0x340 and Q0 to Q3 at 0x344 to 0x350 (src/include/86box/vid_voodoo_regs.h:228-239), and
voodoo_update_ncc()indexesi[]andq[]from separate bit fields of the texel, so an I coefficient sitting in a Q slot is not a harmless aliasing (src/video/vid_voodoo_display.c:65-66). The table 1 block is the control:SST_nccTable1_Q2already writesq[2](src/video/vid_voodoo_reg.c:1337).