mirror of
https://notabug.org/scuti/lib3ddevil1
synced 2024-11-25 00:09:36 +05:30
162 lines
5.3 KiB
Python
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
|
|
|