This section has a bunch of textures
Offset | Type | Description |
---|---|---|
0x0 | uint16 | Number of textures |
0x2 | uint16 | Number of CLUTs (color lookup tables) |
Immediately following the header (at offset 0x4 from the start of the file) is an array of texture descriptors.
Offset | Type | Description |
---|---|---|
0x0 | uint32 | Image Data Pointer (relative to header) |
0x4 | uint32 | Palette Data Pointer (relative to header) (might be null) |
0x8 | uint16 | Image height |
0xa | uint16 | Image width |
0xc | bool | Edge LOD enable (?) |
0xd | uint8 | Min LOD (?) |
0xe | uint8 | Max LOD (?) |
0xf | bool | Unpacked? |
0x10 | byte[7] | Unknown/padding |
0x17 | uint8 | Image format |
0x18 | uint16 | Palette entry count |
0x1a | uint8 | Palette format |
0x1b | byte[5] | Unknown/padding |
This is probably a version of the TEX0 format. I extract the textures by shuffling around the data to create a valid TPL file and then converting it to a png with wimgt. I don't know where the LODBias, wrapS, wrapT, minFilter, and magFilter are in the header, so I assume they're 0.
def toFile(self, path):
dataLength = self.height * self.width * {0:4,1:8,2:8,3:16,4:16,5:16,6:32,8:4,9:8,10:16,14:4}[self.format] >> 3
hasPalette = self.paletteDataPtr > 0
fname = path + '.tpl'
pngname = path + '.png'
out = open(fname, 'wb')
# TEXPalette
out.write(itb(0x0020AF30, 4))
out.write(itb(1, 4))
out.write(itb(0xC, 4))
# TEXDescriptor
out.write(itb(0x14, 4))
if hasPalette:
out.write(itb(0x38, 4))
else:
out.write(itb(0, 4))
# TEXHeader
out.write(itb(self.height, 2))
out.write(itb(self.width, 2))
out.write(itb(self.format, 4))
out.write(itb(0x40 + hasPalette * 0x20, 4))
out.write(itb(self.wrapS, 4))
out.write(itb(self.wrapT, 4))
out.write(itb(self.minFilter, 4))
out.write(itb(self.magFilter, 4))
out.write(itb(self.LODBias, 4))
out.write(itb(self.edgeLODEnable, 1))
out.write(itb(self.minLOD, 1))
out.write(itb(self.maxLOD, 1))
out.write(itb(self.unpacked, 1))
paletteDataLen = self.paletteEntries * 2
paletteDataOffset = 0
paletteDataPad = 0
if hasPalette:
paletteDataOffset = 0x60 + dataLength
mod = paletteDataOffset % 0x20
if mod != 0:
paletteDataPad = 0x20 - mod
paletteDataOffset += paletteDataPad
# Palette header
out.write(itb(self.paletteEntries, 2))
out.write(itb(1, 1))
out.write(itb(0, 1))
out.write(itb(self.paletteFormat, 4))
out.write(itb(paletteDataOffset, 4))
# Pad to multiple of 0x20 (0x40 or 0x60 here)
out.write(itb(0, 0x8 + hasPalette * 0x14))
self.parent.seek(self.dataPtr)
out.write(self.parent.read(dataLength))
if hasPalette:
out.write(itb(0, paletteDataPad))
self.parent.seek(self.paletteDataPtr)
out.write(self.parent.read(paletteDataLen))
out.close()
os.system('wimgt decode -q -d ' + pngname + ' ' + fname)
os.remove(fname)