This commit is contained in:
Amazed 2021-02-09 16:09:13 +01:00
parent 1d36b5e5b4
commit 4f45346980
2 changed files with 262 additions and 0 deletions

View File

@ -25,6 +25,15 @@ def read_bytes(fp, 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):
i = 0
j = 0

253
skn.py Normal file
View 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()