TaylorMouse wrote:Char[4] -> S7MF
UInt32 -> Version Minor
UInt32 -> Major Version
Pos 52 -> Length of the names -2
Pos 65 -> start of the names of the maps, textures and the name of the object devided by \0
Don't seem to find the offset of VST0, VST1 and VST2
The UInt32 just in front of VST is always 24
and the number befor that is (I think) a UInt32 that contains the number of vertices..
Weird... could it be compressed ???
in the list there are a lot of NaN ( Not A Number) ???
T.
I think it is a chunk-based format, where each chunk is 16-byte aligned.
I think it should be parsed sequentially, remembering to pad the end of each chunk appropriately.
First you start by reading in the texture names, then you read the VST0, then VST1, maybe VST2, followed by a bunch of indices.
Code: Select all
short[2] chunkID, ?
int chunksize
int structsize
char[4] chunktag
For example, consider M_MF_Musketeer_01.s7m. At offset 224, you read two shorts. Then the chunk size 26808. The struct size is 24, and the chunk ID is VST0
Then you read 26808 bytes, followed by some padding. Note that in the header at offset 12 you get the vert count 1117, and that * 24 = 26808.
Then you read another two shorts, followed by 4468 chunk size, a 4 for struct size, then VST1.
Read in 4468 bytes, then you see more 0 padding to the next 16 bytes. Again, vert count of 1117 * 4 = 4468.
Repeat for VST2. 8936 / 8 = 1117.
Afterwards, there's a chunk with no ID (1st short is a 1), but if we follow the pattern and pad the chunk, we'll come to the next chunk (1st short is a 4), which doesn't have a chunk ID either but you can see that it follows the same chunk struct and this one holds a bunch of indices.
7206 chunk size for faces, short per index, and 7206 / 2 = 3603, which is the integer right after the vert count, so there's your index count.
It might be using half-floats to store a lot of data, I don't know.
The fact that a couple structs aren't following the chunk struct might mean they just hardcode it as TexNames, VST0, VST1, VST2, unk, faces
EDIT:
Ok ya it's a chunk-based format.
The 4-char tag is not really important.
The first short is the chunk type:
1 - VST0
2 - VST1
3 - VST2
4 - faces
5 - that VBIN chunk, skeleton or whatever "Shadow" could refer to
6 - textures
7 - small chunk, not sure
16-byte aligned
Code: Select all
def seek_padding(self, size):
''' 16-byte chunk alignment'''
pad = (16 - (size % 16)) % 16
self.inFile.seek(pad, 1)
def parse_file(self):
'''Main parser method'''
idstring = self.inFile.readBytes(4)
unk, unk, numVerts, numIdx = self.inFile.read('4L')
self.inFile.read('2H')
self.inFile.read('6f')
# chunk based parsing
while not self.inFile.checkEOF():
chunkType, unk = self.inFile.read('2H')
chunkSize = self.inFile.readUInt()
structSize = self.inFile.readUInt()
chunkID = noeStrFromBytes(self.inFile.readBytes(4))
if chunkID == 1:
self.parse_VST0(structSize)
elif chunkID == 2:
self.parse_VST1(structSize)
elif chunkID == 3:
self.parse_VST2(structSize)
elif chunkID == 4:
self.parse_faces(numIdx)
else:
self.inFile.seek(chunkSize, 1)
self.seek_padding(chunkSize)
print(chunkType, chunkSize, chunkID)