skn
This commit is contained in:
parent
1d36b5e5b4
commit
4f45346980
@ -25,6 +25,15 @@ def read_bytes(fp, size):
|
|||||||
return bytes(struct.unpack('<' + str(size) + 'B', fp.read(size)))
|
return bytes(struct.unpack('<' + str(size) + 'B', fp.read(size)))
|
||||||
|
|
||||||
|
|
||||||
|
def read_string_until_none(fp) -> str:
|
||||||
|
s = ""
|
||||||
|
c = read_byte(fp)
|
||||||
|
while c != 0x00:
|
||||||
|
s += chr(c)
|
||||||
|
c = read_byte(fp)
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
def decompress(compressed_bytes, original_size: int):
|
def decompress(compressed_bytes, original_size: int):
|
||||||
i = 0
|
i = 0
|
||||||
j = 0
|
j = 0
|
||||||
|
253
skn.py
Normal file
253
skn.py
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
from lib.fileutils import *
|
||||||
|
|
||||||
|
NAM_FlagHasHandles = (1 << 0)
|
||||||
|
NAM_FlagCaseInsensitive = (1 << 1)
|
||||||
|
|
||||||
|
|
||||||
|
class MAP_KeyContext:
|
||||||
|
def __init__(self):
|
||||||
|
self.context = 0
|
||||||
|
self.ppLUT = 0
|
||||||
|
self.reserve = 0
|
||||||
|
self.pData = 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse(cls, b):
|
||||||
|
r = cls()
|
||||||
|
r.context = read_int(b)
|
||||||
|
r.ppLUT = read_int(b)
|
||||||
|
r.reserve = read_int(b)
|
||||||
|
r.pData = read_int(b)
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
class MAP_Mapper:
|
||||||
|
def __init__(self):
|
||||||
|
self.pMemgroup = 0
|
||||||
|
self.MemBaseSize = 0
|
||||||
|
self.MemBlocks = 0
|
||||||
|
self.MemSize = 0
|
||||||
|
self.MemFree = 0
|
||||||
|
self.pMem = 0
|
||||||
|
self.MaxMappings = 0
|
||||||
|
self.TotalMappings = 0
|
||||||
|
self.TotalKeys = 0
|
||||||
|
self.pKeyContexts = 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse(cls, b):
|
||||||
|
r = cls()
|
||||||
|
r.pMemgroup = read_int(b)
|
||||||
|
r.MemBaseSize = read_int(b)
|
||||||
|
r.MemBlocks = read_int(b)
|
||||||
|
r.MemSize = read_int(b)
|
||||||
|
r.MemFree = read_int(b)
|
||||||
|
r.pMem = read_int(b)
|
||||||
|
r.MaxMappings = read_int(b)
|
||||||
|
r.TotalMappings = read_int(b)
|
||||||
|
r.TotalKeys = read_int(b)
|
||||||
|
r.pKeyContexts = read_int(b)
|
||||||
|
return r
|
||||||
|
|
||||||
|
class MAP_Mapping:
|
||||||
|
def __init__(self):
|
||||||
|
self.index = 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse(cls, b):
|
||||||
|
r = cls()
|
||||||
|
r.index = read_short(b)
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def read_int_and_print(n, b):
|
||||||
|
a = read_int(b)
|
||||||
|
print("%s=%s" % (n, a))
|
||||||
|
return a
|
||||||
|
|
||||||
|
|
||||||
|
def read_float_and_print(n, b):
|
||||||
|
a = read_float(b)
|
||||||
|
print("%s=%s" % (n, a))
|
||||||
|
return a
|
||||||
|
|
||||||
|
|
||||||
|
def read_byte_and_print(n, b):
|
||||||
|
a = read_byte(b)
|
||||||
|
print("%s=%s" % (n, a))
|
||||||
|
return a
|
||||||
|
|
||||||
|
|
||||||
|
def read_short_and_print(n, b):
|
||||||
|
a = read_short(b)
|
||||||
|
print("%s=%s" % (n, a))
|
||||||
|
return a
|
||||||
|
|
||||||
|
|
||||||
|
class MAP_MemGroup:
|
||||||
|
def __init__(self):
|
||||||
|
self.mem = 0
|
||||||
|
self.memgroup = 0
|
||||||
|
self.memlist = 0
|
||||||
|
self.total_size = 0
|
||||||
|
self.total_blocks = 0
|
||||||
|
self.base = 0
|
||||||
|
|
||||||
|
|
||||||
|
class MAP_Image:
|
||||||
|
def __init__(self):
|
||||||
|
self.size = 0
|
||||||
|
self.memgroupoffset = 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ANM_Skin:
|
||||||
|
def __init__(self):
|
||||||
|
self.custom = 0
|
||||||
|
self.file_version = 0
|
||||||
|
self.image = 0
|
||||||
|
self.memgroup = 0
|
||||||
|
self.node_dictionary = 0
|
||||||
|
self.tree_dictionary = 0
|
||||||
|
self.default_obj_dictionnary = 0
|
||||||
|
self.total_number_trees = 0
|
||||||
|
self.total_number_objs = 0
|
||||||
|
self.total_number_clusters = 0
|
||||||
|
self.name = 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse(cls, b):
|
||||||
|
print("MAP_Image")
|
||||||
|
read_int_and_print("size", b)
|
||||||
|
ret = b.tell()
|
||||||
|
memgroupoffset = read_int_and_print("memgroupoffset", b)
|
||||||
|
|
||||||
|
b.seek(memgroupoffset)
|
||||||
|
|
||||||
|
print("MAP_MemGroup")
|
||||||
|
print("\tMAP_Mem")
|
||||||
|
read_int_and_print("\tNode", b)
|
||||||
|
read_int_and_print("\tSize", b)
|
||||||
|
read_int_and_print("\tFlags", b)
|
||||||
|
|
||||||
|
read_int_and_print("pMemGroup", b)
|
||||||
|
read_int_and_print("MemList", b)
|
||||||
|
read_int_and_print("TotalSize", b)
|
||||||
|
read_int_and_print("TotalBlocks", b)
|
||||||
|
base = read_int_and_print("pBase", b)
|
||||||
|
|
||||||
|
b.seek(base)
|
||||||
|
print("=========")
|
||||||
|
print("ANM_Skin")
|
||||||
|
read_int_and_print("pCustom", b)
|
||||||
|
read_int_and_print("FileVersion", b)
|
||||||
|
read_int_and_print("pImage", b)
|
||||||
|
read_int_and_print("pMemGroup", b)
|
||||||
|
read_int_and_print("pNodeDictionary", b)
|
||||||
|
tree = read_int_and_print("pTreeDictionary", b)
|
||||||
|
defaultobj = read_int_and_print("pDefaultObjDictionary", b)
|
||||||
|
read_int_and_print("TotalNumberOfTrees", b)
|
||||||
|
read_int_and_print("TotalNumberOfObjs", b)
|
||||||
|
read_int_and_print("TotalNumberOfClusters", b)
|
||||||
|
print(read_string_until_none(b))
|
||||||
|
print("=========")
|
||||||
|
|
||||||
|
print("ANM_Skin->pTreeDictionary NAM_Dictionary")
|
||||||
|
b.seek(defaultobj)
|
||||||
|
read_int_and_print("pMemGroup", b)
|
||||||
|
namemapper = read_int_and_print("pNameMapper", b)
|
||||||
|
flags = read_int_and_print("Flags", b)
|
||||||
|
print("Flags: NAM_FlagHasHandles: %s, NAM_FlagCaseInsensitive: %s" % (flags & NAM_FlagHasHandles, flags & NAM_FlagCaseInsensitive))
|
||||||
|
namehandle = read_short_and_print("NameHandle", b)
|
||||||
|
|
||||||
|
|
||||||
|
print("MAP_Image->ANM_Skin->NAM_Dictionnary->MAP_Mapper")
|
||||||
|
b.seek(namemapper)
|
||||||
|
pMemGroup = read_int_and_print("pMemGroup", b)
|
||||||
|
read_int_and_print("MemBaseSize", b)
|
||||||
|
read_int_and_print("MemBlocks", b)
|
||||||
|
read_int_and_print("MemSize", b)
|
||||||
|
read_int_and_print("MemFree", b)
|
||||||
|
mem = read_int_and_print("pMem", b)
|
||||||
|
read_int_and_print("MaxMappings", b)
|
||||||
|
totalmappings = read_int_and_print("TotalMappings", b)
|
||||||
|
read_int_and_print("TotalKeys", b)
|
||||||
|
pKeyContexts = read_int_and_print("pKeyContexts", b)
|
||||||
|
|
||||||
|
print("MAP_Image->ANM_Skin->NAM_Dictionnary->MAP_Mapper->MAP_KeyContext NAM_STRING_KEY")
|
||||||
|
b.seek(pKeyContexts)
|
||||||
|
print("\tMAP_Image->ANM_Skin->NAM_Dictionnary->MAP_Mapper->MAP_KeyContext NAM_STRING_KEY->MAP_BinSearchContext")
|
||||||
|
read_int_and_print("\tSize", b)
|
||||||
|
read_int_and_print("\tpCallback", b)
|
||||||
|
read_int_and_print("\tIndex", b)
|
||||||
|
read_int_and_print("\tTest", b)
|
||||||
|
pLUTNAM_STRING_KEY = read_int_and_print("pLUT", b)
|
||||||
|
read_int_and_print("Reserve", b)
|
||||||
|
read_int_and_print("pData", b)
|
||||||
|
|
||||||
|
def showdictbyindex(i):
|
||||||
|
assert(0 <= i < totalmappings)
|
||||||
|
print("LUT NAM_STRING_KEY")
|
||||||
|
b.seek(pLUTNAM_STRING_KEY)
|
||||||
|
pind0_string = read_int_and_print("LUT NAM_STRING_KEY[0]", b)
|
||||||
|
for _ in range(i):
|
||||||
|
pind0_string = read_int_and_print("LUT NAM_STRING_KEY[0]", b)
|
||||||
|
print("NAM_StringData")
|
||||||
|
b.seek(pind0_string)
|
||||||
|
print("BELOW IS CUSTOM vv")
|
||||||
|
pptr = read_short_and_print("pPtr->ANM_Obj", b)
|
||||||
|
pptr2 = read_short_and_print("pPtr2->ANM_Obj", b)
|
||||||
|
val = read_int_and_print("Value", b)
|
||||||
|
print(b.tell())
|
||||||
|
print(read_string_until_none(b))
|
||||||
|
|
||||||
|
b.seek(val)
|
||||||
|
read_int_and_print("ANM_Obj->Custom", b)
|
||||||
|
read_int_and_print("ANM_Obj->Skin", b)
|
||||||
|
read_int_and_print("ANM_Obj->ZeroCluster", b)
|
||||||
|
total_vertices = read_int_and_print("ANM_Obj->TotalNumberOfVertices", b)
|
||||||
|
num_clusters = read_int_and_print("ANM_Obj->NumberOfClusters", b)
|
||||||
|
clusters = read_int_and_print("ANM_Obj->Clusters", b)
|
||||||
|
|
||||||
|
SEEN_VERTICES_INDEX = []
|
||||||
|
|
||||||
|
b.seek(clusters)
|
||||||
|
for i in range(num_clusters):
|
||||||
|
print("READING CLUSTER %s" % i)
|
||||||
|
read_int_and_print("ANM_Cluster->Custom", b)
|
||||||
|
read_int_and_print("ANM_Cluster->Obj", b)
|
||||||
|
read_int_and_print("ANM_Cluster->Handle", b)
|
||||||
|
print("ANM_Cluster->BoundingBox")
|
||||||
|
print("ANM_BoundingBox->Box[0]")
|
||||||
|
read_float_and_print("X", b)
|
||||||
|
read_float_and_print("Y", b)
|
||||||
|
read_float_and_print("Z", b)
|
||||||
|
print("ANM_BoundingBox->Box[1]")
|
||||||
|
read_float_and_print("X", b)
|
||||||
|
read_float_and_print("Y", b)
|
||||||
|
read_float_and_print("Z", b)
|
||||||
|
numverts = read_int_and_print("ANM_Cluster->NumberOfVertices", b)
|
||||||
|
|
||||||
|
for _ in range(numverts):
|
||||||
|
read_float_and_print("X", b)
|
||||||
|
read_float_and_print("Y", b)
|
||||||
|
read_float_and_print("Z", b)
|
||||||
|
vindex = read_int_and_print("Index", b)
|
||||||
|
# read_int_and_print("Weight", b)
|
||||||
|
assert(vindex not in SEEN_VERTICES_INDEX)
|
||||||
|
SEEN_VERTICES_INDEX.append(vindex)
|
||||||
|
|
||||||
|
read_int_and_print("Unk", b)
|
||||||
|
read_int_and_print("Unk", b)
|
||||||
|
print("%s vertices in this cluster (vs %s reported)" % (len(SEEN_VERTICES_INDEX), total_vertices))
|
||||||
|
showdictbyindex(2)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/mc_l0.skn", "rb") as fp:
|
||||||
|
# with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/dust.skn", "rb") as fp:
|
||||||
|
ANM_Skin.parse(fp)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user