C8 Texture-Tlut-Hash remains constant when the transparency flag is used.
~~C8 textures have the option to use the value 255 as alpha if the color palette is smaller than 255 colors,~~
Some C8 textures use the value 255 for pixels outside the texture when the color palette is smaller than that,
dolphin does not take this into account so the textures pallet is calculated too large and data is hashed that doesn't belong to the pallet causing the tlut hash to change every time.
when calculating the pallet size, if the value 255 is only added when the pallet is already 254 large, the pallet will be calculated correctly.
This change doesn't seem to affect existing texture packs because it only affects the tlut hash of textures that use the ~~alpha flag~~ 255 for pixels out of the image and without this fix they have a hash that keeps changing, so some packs use the wildcard "$" character to get around this and they are still recognized without problems.
This is the same problem as described here https://bugs.dolphin-emu.org/issues/11358
Yeah I'm not convinced about the correctness of this code, but this is an interesting observation anyway. We can probably fix this now that we know why it happens.
If all 256 values are used, I believe this sets the max at 254 if the last 255 byte happens before the first 254 byte.
yeah that's possible, with an additional variable we could fix this. For example like this:
// The value 255 can be used as a transparency flag if the tlut is smaller than 255.
bool if_max = false;
for (size_t i = 0; i < m_texture_size; i++)
{
const u32 texture_byte = m_ptr[i];
min = std::min(min, texture_byte);
if (texture_byte != 255)
max = std::max(max, texture_byte);
else
if_max = true;
}
// Does the tlut array have the max size or is the transparency flag used?
if (if_max && max == 254)
max = 255;
break;
Yeah I'm not convinced about the correctness of this code, but this is an interesting observation anyway. We can probably fix this now that we know why it happens.
I came across this some time ago while I was developing the TextureExtraction tool.
the example is from zelda twilight princess and is located at res\Layout\itemicon\timg\st_pachinko.bti
for this file the TLUT array is 384 large and the values 0-382 are actually used.
I wasn't able to find any code in dolphin's texture decoder that handles this; it just always reads from the TLUT:
https://github.com/dolphin-emu/dolphin/blob/0291d2c45f000a04191be3c68603ebd0cbffdf6b/Source/Core/VideoCommon/TextureDecoder_x64.cpp#L98-L105
Perhaps twilight princess specifically behaves this way, but I suspect it's game logic that's responsible for it, not actual hardware behavior.
There are also cases where an alpha value of 0 still behaves differently for different color values; one example would be using alpha as a height value instead of a transparency value (which is done by Rogue Squadron). Though I don't think there are many situations where TLUTs would be used with that too.
I only know of nintendo games that use this, but I could search some games with the TextureExtraction tool to tell exactly how many games and textures are affected.
The example also does not use a C8 IA8 but a C8 RGB5A3
I have tested a few games with the TextureExtraction tool and it seems to only affect Zelda games.
- Twilight Princess 51 textures
- Wind Waker 17 textures
- Link's Crossbow Training 4 textures
- Four Swords Adventures 81 textures
Update: The 255 values are not a alpha flag, they are outside the textures, so they not play a role in converting the image. so it only affects C8 textures with an odd block size where the pixels outside the image have been given a value greater than the pallet.