CTEX file format

  • Thread starter tiddy
  • 7 comments
  • 1,097 views
5
United States
United States
I'm trying to parse texture data from CARCADE.DAT and CAR.DAT but stuck with it. I've seen there are some other modders and reverse engineers are sitting here.

The texture data consists of 4 bit indices to the palette and therefore the maximum index is 0xF. But palette has a size of 0xFF as I understand it. Which is much bigger than the maximum possible index. What is the trick behind color choosing from those 4 bit indices?

Probably there must be a palette ID for each pixel
 
Last edited:
This is (despite the name) an implementation of reading and writing the car texture format for both GT1 and GT2, if it's useful to see it in code.

The format includes 16 different 16-colour palettes per car colour, then each face of the 3D model includes the ID of which palette it expects to be used to draw it. There are also a couple of special cases - palette 0 is used for the wheels (with the model seemingly generated at runtime with a set UV mapping), and the brake light faces use both the specified palette and the palette after that to represent unlit and lit states. Each pixel of the texture then indexes into that 16-colour palette.

This means that the textures are intrinsically linked to the models, so there is no way to render one without the other, which is a bit of a pain for writing tools! In theory, it's even possible to reuse one part of the texture with multiple palettes by specifying a different palette ID on each face that is UV mapped to it, but in practice this is very rarely done (and probably never done deliberately).
 
This is (despite the name) an implementation of reading and writing the car texture format for both GT1 and GT2, if it's useful to see it in code.

The format includes 16 different 16-colour palettes per car colour, then each face of the 3D model includes the ID of which palette it expects to be used to draw it. There are also a couple of special cases - palette 0 is used for the wheels (with the model seemingly generated at runtime with a set UV mapping), and the brake light faces use both the specified palette and the palette after that to represent unlit and lit states. Each pixel of the texture then indexes into that 16-colour palette.

This means that the textures are intrinsically linked to the models, so there is no way to render one without the other, which is a bit of a pain for writing tools! In theory, it's even possible to reuse one part of the texture with multiple palettes by specifying a different palette ID on each face that is UV mapped to it, but in practice this is very rarely done (and probably never done deliberately).

Everything is clear now. Thank you for such detailed information!
Yep, model and texture are linked together then. But it should not be a big deal.
 
In theory, it's even possible to reuse one part of the texture with multiple palettes by specifying a different palette ID on each face that is UV mapped to it, but in practice this is very rarely done (and probably never done deliberately).
It actually has been done once, on this early/beta racing model of the Civic SiR (EG) where the yellow stripe is made by having a color-swapped polygon, made by having a duplicate of the black side color palette in gold.
That is however the only instance of PD using that method, which is understandable, because you technically sacrifice a palette for this effect. But it's interesting.


1703439697146.png

1703439686440.png
 
i ran into another issue. Whenever 4bit color index equals to zero - color is wrong. Looks like i should manually spread out normal pixels over this grey zone in horizontal direction. But i'm not sure. Why did they do that?
1703711674167.png
 
Last edited:
i ran into another issue. Whenever 4bit color index equals to zero - color is wrong. Looks like i should manually spread out normal pixels over this grey zone in horizontal direction. But i'm not sure. Why did they do that?

That doesn't make much sense to me I'm afraid - the textures are a simple bitmap with a single palette index per pixel. Is it possible that you're reading them in the wrong way, or reading the colours wrong (they're BGR555)? Those grey areas on your render aren't flat colours, nor do they even match up with the shading of the texture.

gt1-nsx.png


edit: Er, this is probably an obvious question, but... you have decompressed the files before trying to use them, right?
 
Last edited:
Ok, thank you. I decompressed them indeed. I wouldn't see anything reasonable otherwise. But maybe my lzss implementation does something wrong.

upd: yes, that was broken decompressor. Now the textures are fine.
This is the code in c if someone need it:
C++:
void decompress_lzss_gt(uint8_t* dst, size_t dst_size, const uint8_t* src, size_t src_size) {
    size_t src_pos = 0, dst_pos = 0;
    while(src_pos < src_size) {
        uint8_t flags = src[src_pos++]; // next block
        for(auto i = 8; i && src_pos < src_size; i--, flags >>= 1) {

            // compressed
            if(flags & 0x01) {
                uint16_t len = src[src_pos++] + 3u; // compress less than 3 bytes is pointless
                uint16_t offset = src[src_pos++];
                if(offset & 0x80) { // multibyte flag
                    offset = ((offset & 0x7F) << 8) + src[src_pos++];
                }
                offset += 1; // data length byte
                for(; len--; dst_pos++) dst[dst_pos] = dst[dst_pos - offset];

            // uncompressed
            } else {
                dst[dst_pos++] = src[src_pos++];
            }
        }
    }
}
 
Last edited:
Now they're pretty much loaded. Still little texture artifacts here and there, but overall it looks good.

All the cars from carcade.dat & car.dat :
34.png

38.png

40.png
 
Last edited:
Back