I've been reading an old Sega doc (Not sure if I'm allowed to link that here or not, but it would help so I can show my understanding), the description for Texconv as well as some some forum posts. I think I get how VQ-compressed textures work for the most part. Basically the texture has two parts; the "Code-Block" overhead which has 256 entries of 64-bit words (2KB in size) and for 16BPP, every 64-bit word contains 4 lots of 16bpp colours that correspond to a "2 * 2" set of texels (And for PAL8BPP its 8 texels entries ("4 * 2") and PAL4BPP its 16 ("4 * 4") entries). The "Index" section has `height * width` bytes of entries ("/2" for PAL8BPP and "/4" for PAL4BPP) where each byte contains a value that corresponds to one of the 256 code-block entries which correspondes to a "2 by 2" of texels.
The first question: I know compression can only be used on twiddled (No stride) textures, I see in the docs its says the 2 by 2 texel block is laided out in a backwards N shape (In other words, its twiddled) I can't tell if this means the "already twiddled 2 by 2 block" is Re-arranged again or if this is just a reminder that the texture *is* twiddled.
The second question: I came up with a "Compressed size" formula thats `2048 + (height * width / 2 / 2 (And further divisions for palettes as mentioned before))`Bytes. When ignoring the 16-byte Dtex header mostly every dtex file I compressed obeyed this formula, but I noticed an exception when I tried to compress small textures (Less than 32 by 32) that I don't understand. Before you say, I know unless you're doing the "Small-VQ" hack/trick its generally not a good idea to compress a texture thats smaller than 64 by 64 because the 2KB code-block overhead + indexes take up more space than the uncompressed texture, but because I'm making a converter and want to support any dtex file I need to account for this. Anyways, these were my results from my tests
For the 8 by 8 image (16 by 16 has the same compressed sizes) 4BPP insta Uncompressed: 48 B = 16-byte header + (8 * 8 * 0.5)Byte body Compressed: 2096 B = 16-byte header + 2048-byte code book + (8 * 8 / 4 / 4)Byte texture-index = 2060 != 2096 8BPP insta Uncompressed: 80 B = 16-byte header + (8 * 8 * 1)Byte body Compressed: 2096 B = 16-byte header + 2048-byte code book + (8 * 8 / 4 / 2)Byte texture-index = 2072 != 2096 RGB565 insta Uncompressed: 144 B = 16-byte header + (8 * 8 * 2)Byte body Compressed: 2096 B = 16-byte header + 2048-byte code book + (8 * 8 / 2 / 2)Byte texture-index = 2080 != 2096 For a 32 by 32 image 4BPP insta Uncompressed: 528 B = 16-byte header + (8 * 8 * 0.5)Byte body Compressed: 2128 B = 16-byte header + 2048-byte code book + (32 * 32 / 4 / 4 = 64)Byte texture-index = 2128 8BPP insta Uncompressed: 1040 B = 16-byte header + (8 * 8 * 1)Byte body Compressed: 2192 B = 16-byte header + 2048-byte code book + (32 * 32 / 4 / 2 = 128)Byte texture-index = 2192
"Normally, when dealing with textures that are 32 × 32 or smaller, it is necessary to group several into a size of at least 64 × 64 before compressing them."
I've included a zip file containing my source PNGs and all the dtex files I used in this test
The third question: The Sega docs kept saying you can't make rectangular compressed textures because they won't work. However Tvspelsfreak de-confirmed this when he added support for this and it works on hardware. I've already got uncompressed twiddled rectangle support, would there be any other tricks I need to look out for with rectangular textures? I'm fairly sure a 8 by 64 would still trigger the thing from the second question, but other than that I'd imagine everything else would be fine
The last question: With compressed PAL8BPP textures, I said before each index represents a "4 by 2" texel section. Which one is width and which is height?