import ctypes import os, sys sys.path.append( os.path.abspath( os.path.join( os.path.dirname(__file__), "../../"))) from lib3ddevil1.bindings import libc del os, sys #--------------------------------------+ # Basic Struct #--------------------------------------+ class TexturePack(ctypes.Structure): _pack_ = 1 _fields_ = [ ("id", ctypes.c_char * 4), # fixed length 4, reverse order ("batchNumber", ctypes.c_int), ("firstBatchOffset", ctypes.c_int), ("unknownA", ctypes.c_int) ] class TextureBatchDescriptor(ctypes.Structure): _pack_ = 1 _fields_ = [ ("batchIdx", ctypes.c_int), ("hash", ctypes.c_int), ("texNumber", ctypes.c_int), ("unknownA", ctypes.c_int * 8), ("textureSize", ctypes.c_int), ("unknownB", ctypes.c_int * 30) ] class Texture(ctypes.Structure): _pack_ = 1 _fields_ = [ ("data", ctypes.POINTER(ctypes.c_ubyte)) ] class TextureBatch(ctypes.Structure): _pack_ = 1 _fields_ = [ ("batch", ctypes.POINTER(Texture)) ] class Devil1TEX_FN(ctypes.Structure): _fields_ = [ ("printheader", ctypes.CFUNCTYPE( None, ctypes.POINTER(TexturePack))), ("printbatchdesc", ctypes.CFUNCTYPE( None, ctypes.POINTER(TextureBatchDescriptor))), ("getheader", ctypes.CFUNCTYPE( ctypes.c_bool, ctypes.POINTER( ctypes.POINTER(TexturePack)), ctypes.c_char_p)), ("getbatchdesc", ctypes.CFUNCTYPE( ctypes.c_bool, ctypes.POINTER( ctypes.POINTER(TextureBatchDescriptor)), ctypes.c_uint, ctypes.c_char_p, ctypes.c_uint)), ("getbatch", ctypes.CFUNCTYPE( ctypes.c_bool, ctypes.POINTER( ctypes.POINTER(TextureBatch)), ctypes.c_uint, ctypes.c_char_p, ctypes.c_uint)), ("gettextures", ctypes.CFUNCTYPE( ctypes.c_bool, ctypes.POINTER(Texture), ctypes.c_uint, ctypes.c_char_p, ctypes.c_uint)) ] devil1tex = Devil1TEX_FN.in_dll(libc, "DEVIL1TEX") del libc #--------------------------------------+ # Pythonic Object #--------------------------------------+ class pyTexturePack: def __init__(self, filedata): self.cstruct = ctypes.pointer(TexturePack()) if not devil1tex.getheader(ctypes.byref(self.cstruct), filedata): raise RuntimeError("failed to get texture pack header") return def show(self): devil1tex.printheader(self.cstruct) def getbatchno(self): return self.cstruct.contents.batchNumber def getfirstbatchoffset(self): return self.cstruct.contents.firstBatchOffset class pyTextureBatchDescriptor: def __init__(self, i, filedata): self.cstruct = ctypes.pointer(TextureBatchDescriptor()) ptrofptr = ctypes.byref(self.cstruct) if filedata: if not devil1tex.getbatchdesc( ptrofptr, i, filedata, len(filedata)): raise RuntimeError("failed to get texturebatchdescriptor #" + str(i)) return def show(self): devil1tex.printbatchdesc(self.cstruct) def getbatchidx(self): return self.cstruct.contents.batchIdx def gethash(self): return self.cstruct.contents.hash def gettexno(self): return self.cstruct.contents.texNumber def gettexturesize(self): return self.cstruct.contents.textureSize class pyTextureBatch: def __init__(self, i, filedata): self.cstruct = TextureBatch() if filedata: self.cstruct.batch = None tbd = pyTextureBatchDescriptor(i, filedata) self.amount = tbd.gettexno() memsize = self.amount * tbd.gettexturesize() self.cstruct.batch = ctypes.cast( ctypes.create_string_buffer(memsize), ctypes.POINTER(Texture)) if not devil1tex.gettextures( self.cstruct.batch, i, filedata, len(filedata)): raise RuntimeError("failed to get textures of batch #" + str(i)) return def gettextures(self): return self.cstruct.batch[:self.amount]