lib3ddevil1/bindings/py3devil1tex.py

162 lines
5.3 KiB
Python

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 getbatchnumber(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 gettexnumber(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.gettexnumber()
self.size = tbd.gettexturesize()
memsize = self.amount * self.size
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):
ptrs = self.cstruct.batch[:self.amount]
textures = []
for ptr in ptrs:
texture = ctypes.cast(ptr.data,
ctypes.POINTER(
ctypes.c_ubyte * self.size))[0]
textures.append(texture)
return textures