mirror of
https://notabug.org/scuti/lib3ddevil1
synced 2024-11-25 00:09:36 +05:30
Merge branch 'python/finalize' of https://git.teknik.io/scuti/lib3ddevil1 into feature/documentation
This commit is contained in:
commit
8b1142e31d
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,9 +1,11 @@
|
|||||||
# Files from compilation and tests
|
# Files from compilation and tests
|
||||||
*.o
|
*.o
|
||||||
|
*.so
|
||||||
|
*.gch
|
||||||
*.exe
|
*.exe
|
||||||
*.stackdump
|
*.stackdump
|
||||||
*.log
|
*.log
|
||||||
devil1test
|
__pycache__
|
||||||
demo-extractpld
|
demo-extractpld
|
||||||
demo-extracttexture
|
demo-extracttexture
|
||||||
demo-extractmesh
|
demo-extractmesh
|
||||||
|
23
Makefile
23
Makefile
@ -1,21 +1,30 @@
|
|||||||
|
CC=gcc
|
||||||
|
CFLAGS=-I"include" -Wall -fPIC #-g
|
||||||
|
LDFLAGS=-shared
|
||||||
|
TARGET=lib3ddevil1.so
|
||||||
PEX=demo-extractpld
|
PEX=demo-extractpld
|
||||||
TEX=demo-extracttexture
|
TEX=demo-extracttexture
|
||||||
MEX=demo-extractmesh
|
MEX=demo-extractmesh
|
||||||
|
OBJ=devil1pld.o devil1tex.o devil1geo.o
|
||||||
|
|
||||||
CC=gcc
|
all: $(TARGET) demos
|
||||||
CFLAGS= -I"include" -Wall
|
|
||||||
|
|
||||||
all: pld texture mesh
|
$(TARGET): $(OBJ)
|
||||||
|
$(LINK.cc) $(LDFLAGS) $^ -o $@
|
||||||
|
|
||||||
pld: devil1pld.o devil1tex.o devil1geo.o
|
|
||||||
|
demos: pld texture mesh
|
||||||
|
|
||||||
|
pld: $(OBJ)
|
||||||
$(CC) $^ demo/extractpld.c $(CFLAGS) -o $(PEX)
|
$(CC) $^ demo/extractpld.c $(CFLAGS) -o $(PEX)
|
||||||
|
|
||||||
texture: devil1pld.o devil1tex.o devil1geo.o
|
texture: $(OBJ)
|
||||||
$(CC) $^ demo/extracttexture.c $(CFLAGS) -o $(TEX)
|
$(CC) $^ demo/extracttexture.c $(CFLAGS) -o $(TEX)
|
||||||
|
|
||||||
mesh: devil1pld.o devil1tex.o devil1geo.o
|
mesh: $(OBJ)
|
||||||
$(CC) $^ demo/extractmesh.c $(CFLAGS) -o $(MEX)
|
$(CC) $^ demo/extractmesh.c $(CFLAGS) -o $(MEX)
|
||||||
|
|
||||||
|
|
||||||
devil1pld.o: src/devil1pld.c
|
devil1pld.o: src/devil1pld.c
|
||||||
$(CC) -c $^ $(CFLAGS)
|
$(CC) -c $^ $(CFLAGS)
|
||||||
|
|
||||||
@ -26,4 +35,4 @@ devil1geo.o: src/devil1geo.c
|
|||||||
$(CC) -c $^ $(CFLAGS)
|
$(CC) -c $^ $(CFLAGS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm *.o $(EX) $(PEX) $(TEX) $(MEX)
|
rm *.o $(TARGET) $(PEX) $(TEX) $(MEX)
|
||||||
|
18
bindings/__init__.py
Normal file
18
bindings/__init__.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import ctypes, os, sys
|
||||||
|
|
||||||
|
def loadlibc():
|
||||||
|
sharedlib = './lib3ddevil1.so'
|
||||||
|
libc = None
|
||||||
|
os.environ['PATH'] = os.path.abspath(
|
||||||
|
os.path.join(
|
||||||
|
os.path.dirname(__file__), "../")) \
|
||||||
|
+ ';' \
|
||||||
|
+ os.environ['PATH']
|
||||||
|
try:
|
||||||
|
libc = ctypes.cdll.LoadLibrary(sharedlib)
|
||||||
|
except OSError as e:
|
||||||
|
print("Error loading dynamically linked library.\nOSError: " + str(e))
|
||||||
|
raise RuntimeError("Couldn't load %s" % sharedlib)
|
||||||
|
return libc
|
||||||
|
|
||||||
|
libc = loadlibc()
|
134
bindings/__test__.py
Executable file
134
bindings/__test__.py
Executable file
@ -0,0 +1,134 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
from py3devil1pld import pyPldHeader
|
||||||
|
from py3devil1tex import pyTexturePack, pyTextureBatchDescriptor, pyTextureBatch
|
||||||
|
from py3devil1geo import pyGeoHeader, pyMeshHeader, pyMesh
|
||||||
|
|
||||||
|
#print(libc)
|
||||||
|
|
||||||
|
#--------------------------------------+
|
||||||
|
# Regular Python
|
||||||
|
#--------------------------------------+
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
def pldtest(devil1pld, pldheader):
|
||||||
|
with open("pl01.pld", "rb") as f:
|
||||||
|
data = f.read()
|
||||||
|
devil1pld.getheader(ctypes.byref(pldheader), data)
|
||||||
|
devil1pld.printheader(ctypes.byref(pldheader))
|
||||||
|
# for offset in pldheader.getoffsets():
|
||||||
|
# print(hex(offset))
|
||||||
|
|
||||||
|
def textest(devil1tex, texheader):
|
||||||
|
print("texture test")
|
||||||
|
with open("pl01.pld_1.txp", "rb") as f:
|
||||||
|
data = f.read()
|
||||||
|
# texheader = ctypes.cast(data, ctypes.POINTER(TexturePack))
|
||||||
|
th = ctypes.pointer(texheader)
|
||||||
|
devil1tex.getheader(ctypes.byref(th), data)
|
||||||
|
devil1tex.printheader(th)
|
||||||
|
batchdesc = TextureBatchDescriptor()
|
||||||
|
bd = ctypes.pointer(batchdesc)
|
||||||
|
print("\nbatch descriptor:")
|
||||||
|
devil1tex.getbatchdesc(ctypes.byref(bd), 1, data, len(data))
|
||||||
|
devil1tex.printbatchdesc(bd)
|
||||||
|
print(bd.contents.textureSize)
|
||||||
|
|
||||||
|
def geotest(devil1geo, geoheader):
|
||||||
|
print("geo test")
|
||||||
|
with open("pl00.pld_0", "rb") as f:
|
||||||
|
data = f.read()
|
||||||
|
# geoheader = ctypes.cast(data, ctypes.POINTER(Header))
|
||||||
|
gh = ctypes.pointer(geoheader)
|
||||||
|
devil1geo.getheader(ctypes.byref(gh), data)
|
||||||
|
devil1geo.printheader(gh)
|
||||||
|
meshheader = MeshHeader()
|
||||||
|
mh = ctypes.pointer(meshheader)
|
||||||
|
devil1geo.getmeshheader(ctypes.byref(mh), 1, data)
|
||||||
|
devil1geo.printmeshheader(mh)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
sharedlib='./lib3ddevil1.so'
|
||||||
|
libc = ctypes.cdll.LoadLibrary(sharedlib)
|
||||||
|
if (not libc):
|
||||||
|
print("Couldn't load %s" % sharedlib)
|
||||||
|
return 1
|
||||||
|
print("OK")
|
||||||
|
|
||||||
|
pldfn = Devil1PLD_FN.in_dll(libc, "DEVIL1PLD")
|
||||||
|
pldh = pyPldHeader()
|
||||||
|
pldtest(pldfn, pldh)
|
||||||
|
|
||||||
|
texfn = Devil1TEX_FN.in_dll(libc, "DEVIL1TEX")
|
||||||
|
texh = TexturePack()
|
||||||
|
textest(texfn, texh)
|
||||||
|
|
||||||
|
geofn = Devil1GEO_FN.in_dll(libc, "DEVIL1GEO")
|
||||||
|
geoh = Header()
|
||||||
|
geotest(geofn, geoh)
|
||||||
|
|
||||||
|
def mainx():
|
||||||
|
with open("pl01.pld", "rb") as f:
|
||||||
|
data = f.read()
|
||||||
|
pld = pyPldHeader(data)
|
||||||
|
pld.show()
|
||||||
|
pld2 = pyPldHeader()
|
||||||
|
pld2.show()
|
||||||
|
|
||||||
|
with open("pl01.pld_1.txp", "rb") as f:
|
||||||
|
data = f.read()
|
||||||
|
txp = pyTexturePack(data)
|
||||||
|
txp.show()
|
||||||
|
print(txp.getbatchnumber())
|
||||||
|
print(txp.getfirstbatchoffset())
|
||||||
|
tbd = pyTextureBatchDescriptor(1, data)
|
||||||
|
tbd.show()
|
||||||
|
print(tbd.gettexturesize())
|
||||||
|
#tx = pyTextures(0, tbd.gettexno(), data)
|
||||||
|
tx = pyTextureBatch(0, data)
|
||||||
|
ts = tx.gettextures()
|
||||||
|
for i in range(0, 10):
|
||||||
|
print(ts[0].data[i])
|
||||||
|
|
||||||
|
with open("pl00.pld_0", "rb") as f:
|
||||||
|
data = f.read()
|
||||||
|
gh = pyGeoHeader(data)
|
||||||
|
gh.show()
|
||||||
|
print("-------------")
|
||||||
|
print(gh.getnummesh())
|
||||||
|
print(gh.getunknownb())
|
||||||
|
print(gh.getunknownc())
|
||||||
|
print(gh.getunknownd())
|
||||||
|
print(gh.getpadding())
|
||||||
|
print(gh.getunknownoffset())
|
||||||
|
mh = pyMeshHeader(3, data)
|
||||||
|
print("-------------")
|
||||||
|
try:
|
||||||
|
mh = pyMeshHeader(87, data)
|
||||||
|
except RuntimeError as e:
|
||||||
|
print(str(e))
|
||||||
|
try:
|
||||||
|
mh = pyMesh(87, data)
|
||||||
|
except RuntimeError as e:
|
||||||
|
print(str(e))
|
||||||
|
print("-------------")
|
||||||
|
mh.show()
|
||||||
|
m = pyMesh(0, data)
|
||||||
|
m.show()
|
||||||
|
# p = m.getpositions()
|
||||||
|
# print("positions:")
|
||||||
|
# for point in p:
|
||||||
|
# print(point)
|
||||||
|
# n = m.getnormals()
|
||||||
|
# print("normals:")
|
||||||
|
# for point in n:
|
||||||
|
# print(point)
|
||||||
|
# u = m.getuvs()
|
||||||
|
# print("uvs:")
|
||||||
|
# for point in u:
|
||||||
|
# print(point)
|
||||||
|
dbatch = m.getbatchdata()
|
||||||
|
print(hex(dbatch.numVertex))
|
||||||
|
print(hex(dbatch.padding))
|
||||||
|
#---------------------------------------+
|
||||||
|
# main()
|
||||||
|
mainx()
|
254
bindings/py3devil1geo.py
Normal file
254
bindings/py3devil1geo.py
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
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 Header(ctypes.Structure):
|
||||||
|
_pack_ = 1
|
||||||
|
_fields_ = [
|
||||||
|
("numMesh", ctypes.c_ubyte),
|
||||||
|
("unknownNumberB", ctypes.c_ubyte),
|
||||||
|
("unknownNumberC", ctypes.c_ubyte),
|
||||||
|
("unknownNumberD", ctypes.c_ubyte),
|
||||||
|
("padding", ctypes.c_int),
|
||||||
|
("unknownOffset", ctypes.c_ulonglong)
|
||||||
|
]
|
||||||
|
|
||||||
|
class MeshHeader(ctypes.Structure):
|
||||||
|
_pack_ = 1
|
||||||
|
_fields_ = [
|
||||||
|
("numBatch", ctypes.c_short),
|
||||||
|
("numVertex", ctypes.c_short),
|
||||||
|
("u", ctypes.c_uint),
|
||||||
|
("offsetBatches", ctypes.c_ulonglong),
|
||||||
|
("flags", ctypes.c_ulonglong)
|
||||||
|
]
|
||||||
|
|
||||||
|
class Coordinate(ctypes.Structure):
|
||||||
|
_pack_ = 1
|
||||||
|
_fields_ = [
|
||||||
|
("x", ctypes.c_float),
|
||||||
|
("y", ctypes.c_float),
|
||||||
|
("z", ctypes.c_float)
|
||||||
|
]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "(%s, %s, %s)" % (str(self.x), str(self.y), str(self.z))
|
||||||
|
|
||||||
|
class UVs(ctypes.Structure):
|
||||||
|
_pack_ = 1
|
||||||
|
_fields_ = [
|
||||||
|
("u", ctypes.c_short),
|
||||||
|
("v", ctypes.c_short)
|
||||||
|
]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "(%s, %s)" % (str(self.u), str(self.v))
|
||||||
|
|
||||||
|
class BoneIndexes(ctypes.Structure):
|
||||||
|
_pack_ = 1
|
||||||
|
_fields_ = [
|
||||||
|
("indexes", ctypes.c_ubyte * 4),
|
||||||
|
]
|
||||||
|
|
||||||
|
class BoneWeights(ctypes.Structure):
|
||||||
|
_pack_ = 1
|
||||||
|
_fields_ = [
|
||||||
|
("weights", ctypes.c_short)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class BatchData(ctypes.Structure):
|
||||||
|
_pack_ = 1
|
||||||
|
_fields_ = [
|
||||||
|
("numVertex", ctypes.c_short),
|
||||||
|
("uB", ctypes.c_short),
|
||||||
|
("padding", ctypes.c_uint),
|
||||||
|
("offsetPositions", ctypes.c_ulonglong),
|
||||||
|
("offsetNormals", ctypes.c_ulonglong),
|
||||||
|
("offsetUVs", ctypes.c_ulonglong),
|
||||||
|
("offsetBoneIndexes", ctypes.c_ulonglong),
|
||||||
|
("offsetBoneWeights", ctypes.c_ulonglong),
|
||||||
|
("offsets", ctypes.c_ulonglong)
|
||||||
|
]
|
||||||
|
|
||||||
|
class VertexData(ctypes.Structure):
|
||||||
|
_pack_ = 1
|
||||||
|
_fields_ = [
|
||||||
|
("positions", ctypes.POINTER(Coordinate)),
|
||||||
|
("normals", ctypes.POINTER(Coordinate)),
|
||||||
|
("u", ctypes.POINTER(UVs)),
|
||||||
|
("bi", ctypes.POINTER(BoneIndexes)),
|
||||||
|
("bw", ctypes.POINTER(BoneWeights))
|
||||||
|
]
|
||||||
|
|
||||||
|
class Batch(ctypes.Structure):
|
||||||
|
_pack_ = 1
|
||||||
|
_fields_ = [
|
||||||
|
("bd", ctypes.POINTER(BatchData)),
|
||||||
|
("vd", VertexData)
|
||||||
|
]
|
||||||
|
|
||||||
|
class Mesh(ctypes.Structure):
|
||||||
|
_pack_ = 1
|
||||||
|
_fields_ = [
|
||||||
|
("b", ctypes.POINTER(Batch))
|
||||||
|
]
|
||||||
|
|
||||||
|
class Devil1GEO_FN(ctypes.Structure):
|
||||||
|
_fields_ = [
|
||||||
|
("printheader", ctypes.CFUNCTYPE(
|
||||||
|
None,
|
||||||
|
ctypes.POINTER(Header))),
|
||||||
|
("printmeshheader", ctypes.CFUNCTYPE(
|
||||||
|
None,
|
||||||
|
ctypes.POINTER(MeshHeader))),
|
||||||
|
("printbatch", ctypes.CFUNCTYPE(
|
||||||
|
None,
|
||||||
|
ctypes.POINTER(Batch))),
|
||||||
|
("printcoordinate", ctypes.CFUNCTYPE(
|
||||||
|
None,
|
||||||
|
ctypes.POINTER(Coordinate))),
|
||||||
|
("getheader", ctypes.CFUNCTYPE(
|
||||||
|
ctypes.c_bool,
|
||||||
|
ctypes.POINTER(ctypes.POINTER(Header)),
|
||||||
|
ctypes.c_char_p)),
|
||||||
|
("getmeshheader", ctypes.CFUNCTYPE(
|
||||||
|
ctypes.c_bool,
|
||||||
|
ctypes.POINTER(ctypes.POINTER(MeshHeader)),
|
||||||
|
ctypes.c_uint,
|
||||||
|
ctypes.c_char_p)),
|
||||||
|
("getbatch", ctypes.CFUNCTYPE(
|
||||||
|
ctypes.c_bool,
|
||||||
|
ctypes.POINTER(Batch),
|
||||||
|
ctypes.c_uint,
|
||||||
|
ctypes.c_char_p)),
|
||||||
|
("getmesh", ctypes.CFUNCTYPE(
|
||||||
|
ctypes.c_bool,
|
||||||
|
ctypes.POINTER(Mesh),
|
||||||
|
ctypes.c_uint,
|
||||||
|
ctypes.c_char_p,
|
||||||
|
ctypes.c_uint))
|
||||||
|
]
|
||||||
|
|
||||||
|
devil1geo = Devil1GEO_FN.in_dll(libc, "DEVIL1GEO")
|
||||||
|
del libc
|
||||||
|
|
||||||
|
#--------------------------------------+
|
||||||
|
# Pythonic Object
|
||||||
|
#--------------------------------------+
|
||||||
|
|
||||||
|
class pyGeoHeader:
|
||||||
|
def __init__(self, filedata):
|
||||||
|
self.cstruct = ctypes.pointer(Header())
|
||||||
|
ptrofptr = ctypes.byref(self.cstruct)
|
||||||
|
if filedata:
|
||||||
|
if not devil1geo.getheader(ptrofptr, filedata):
|
||||||
|
raise RuntimeError("failed to get geometry file header")
|
||||||
|
return
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
devil1geo.printheader(self.cstruct)
|
||||||
|
|
||||||
|
def getnummesh(self):
|
||||||
|
return self.cstruct.contents.numMesh
|
||||||
|
|
||||||
|
def getunknownb(self):
|
||||||
|
return self.cstruct.contents.unknownNumberB
|
||||||
|
|
||||||
|
def getunknownc(self):
|
||||||
|
return self.cstruct.contents.unknownNumberC
|
||||||
|
|
||||||
|
def getunknownd(self):
|
||||||
|
return self.cstruct.contents.unknownNumberD
|
||||||
|
|
||||||
|
def getpadding(self):
|
||||||
|
return hex(self.cstruct.contents.padding)
|
||||||
|
|
||||||
|
def getunknownoffset(self):
|
||||||
|
return hex(self.cstruct.contents.unknownOffset)
|
||||||
|
|
||||||
|
|
||||||
|
class pyMeshHeader:
|
||||||
|
def __init__(self, i, filedata):
|
||||||
|
self.cstruct = ctypes.pointer(MeshHeader())
|
||||||
|
ptrofptr = ctypes.byref(self.cstruct)
|
||||||
|
if filedata:
|
||||||
|
if not devil1geo.getmeshheader(ptrofptr, i, filedata):
|
||||||
|
raise RuntimeError("failed to get mesh header #" + str(i))
|
||||||
|
return
|
||||||
|
pass
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
devil1geo.printmeshheader(self.cstruct)
|
||||||
|
|
||||||
|
def getnumbatch(self):
|
||||||
|
return self.cstruct.contents.numBatch
|
||||||
|
|
||||||
|
def getnumvertex(self):
|
||||||
|
return self.cstruct.contents.numVertex
|
||||||
|
|
||||||
|
def getunknown(self):
|
||||||
|
return hex(self.cstruct.contents.u)
|
||||||
|
|
||||||
|
def getoffsetbatches(self):
|
||||||
|
return self.cstruct.contents.offsetBatches
|
||||||
|
|
||||||
|
def getflags(self):
|
||||||
|
return self.cstruct.contents.flags
|
||||||
|
|
||||||
|
class pyMesh:
|
||||||
|
def __init__(self, i, filedata):
|
||||||
|
self.cstruct = Mesh()
|
||||||
|
if filedata:
|
||||||
|
mh = pyMeshHeader(i, filedata)
|
||||||
|
# allocate memory for the size of batch * number of batches
|
||||||
|
memsize = ctypes.sizeof(Batch) * mh.getnumbatch()
|
||||||
|
self.cstruct.b = ctypes.cast(
|
||||||
|
ctypes.create_string_buffer(memsize),
|
||||||
|
ctypes.POINTER(Batch))
|
||||||
|
if not devil1geo.getmesh(
|
||||||
|
ctypes.byref(self.cstruct),
|
||||||
|
i,
|
||||||
|
filedata,
|
||||||
|
len(filedata)):
|
||||||
|
raise RuntimeError("failed to get mesh")
|
||||||
|
del mh, memsize
|
||||||
|
return
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
if self.cstruct.b:
|
||||||
|
devil1geo.printbatch(self.cstruct.b)
|
||||||
|
else:
|
||||||
|
print("nothing to show")
|
||||||
|
|
||||||
|
def getbatchdata(self):
|
||||||
|
return self.cstruct.b.contents.bd.contents
|
||||||
|
|
||||||
|
def getpositions(self):
|
||||||
|
length = self.cstruct.b.contents.bd.contents.numVertex
|
||||||
|
return self.cstruct.b.contents.vd.positions[:length]
|
||||||
|
|
||||||
|
def getnormals(self):
|
||||||
|
length = self.cstruct.b.contents.bd.contents.numVertex
|
||||||
|
return self.cstruct.b.contents.vd.normals[:length]
|
||||||
|
|
||||||
|
def getuvs(self):
|
||||||
|
length = self.cstruct.b.contents.bd.contents.numVertex
|
||||||
|
return self.cstruct.b.contents.vd.u[:length]
|
||||||
|
|
||||||
|
def getboneindexes(self):
|
||||||
|
length = self.cstruct.b.contents.bd.contents.numVertex
|
||||||
|
return self.cstruct.b.contents.vd.bi[:length]
|
||||||
|
|
||||||
|
def getboneweights(self):
|
||||||
|
length = self.cstruct.b.contents.bd.contents.numVertex
|
||||||
|
return self.cstruct.b.contents.vd.bw[:length]
|
66
bindings/py3devil1pld.py
Normal file
66
bindings/py3devil1pld.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import ctypes
|
||||||
|
import os, sys
|
||||||
|
# This is the folder containing the whole library.
|
||||||
|
sys.path.append(
|
||||||
|
os.path.abspath(
|
||||||
|
os.path.join(
|
||||||
|
os.path.dirname(__file__), "../../")))
|
||||||
|
from lib3ddevil1.bindings import libc
|
||||||
|
del os, sys
|
||||||
|
|
||||||
|
#--------------------------------------+
|
||||||
|
# Basic Struct
|
||||||
|
#--------------------------------------+
|
||||||
|
|
||||||
|
class PldHeader(ctypes.Structure):
|
||||||
|
_pack_ = 1
|
||||||
|
_fields_ = [
|
||||||
|
("numOffset", ctypes.c_int),
|
||||||
|
("offsets", ctypes.POINTER(ctypes.c_int))
|
||||||
|
]
|
||||||
|
|
||||||
|
class Devil1PLD_FN(ctypes.Structure):
|
||||||
|
_fields_ = [
|
||||||
|
("getheader" , ctypes.CFUNCTYPE(
|
||||||
|
ctypes.c_bool,
|
||||||
|
ctypes.POINTER(PldHeader),
|
||||||
|
ctypes.c_char_p)),
|
||||||
|
("sizeofsector", ctypes.CFUNCTYPE(
|
||||||
|
ctypes.c_int,
|
||||||
|
ctypes.POINTER(PldHeader),
|
||||||
|
ctypes.c_int)),
|
||||||
|
("printheader" , ctypes.CFUNCTYPE(None,
|
||||||
|
ctypes.POINTER(PldHeader)))
|
||||||
|
]
|
||||||
|
|
||||||
|
devil1pld = Devil1PLD_FN.in_dll(libc, "DEVIL1PLD")
|
||||||
|
del libc
|
||||||
|
|
||||||
|
#--------------------------------------+
|
||||||
|
# Pythonic Object
|
||||||
|
#--------------------------------------+
|
||||||
|
|
||||||
|
class pyPldHeader:
|
||||||
|
def __init__(self, filedata = None):
|
||||||
|
# Store C Struct in order to call C functions
|
||||||
|
self.cstruct = PldHeader()
|
||||||
|
if filedata:
|
||||||
|
if not devil1pld.getheader(ctypes.byref(self.cstruct), filedata):
|
||||||
|
raise RuntimeError("failed to get .pld header")
|
||||||
|
self.eof = len(filedata)
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
devil1pld.printheader(ctypes.byref(self.cstruct))
|
||||||
|
return
|
||||||
|
|
||||||
|
def getnumoffsets(self):
|
||||||
|
return self.cstruct.numOffsets
|
||||||
|
|
||||||
|
# return pythonic list of offsets
|
||||||
|
def getoffsets(self):
|
||||||
|
return self.cstruct.offsets[:self.cstruct.numOffset]
|
||||||
|
|
||||||
|
def sizeofsector(self, i):
|
||||||
|
ptr = ctypes.byref(self.cstruct)
|
||||||
|
return devil1pld.sizeofsector(ptr, i, self.eof)
|
||||||
|
|
153
bindings/py3devil1tex.py
Normal file
153
bindings/py3devil1tex.py
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
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()
|
||||||
|
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]
|
||||||
|
|
@ -59,10 +59,10 @@ void writemesh(const struct MeshHeader *mh,
|
|||||||
void extractmeshes(const char *filedata,
|
void extractmeshes(const char *filedata,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
unsigned int filesize) {
|
unsigned int filesize) {
|
||||||
if (filedata == NULL || filesize <= 0) {
|
struct Header *h = NULL;
|
||||||
|
if (!(DEVIL1GEO.getheader(&h, filedata))|| filesize <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct Header *h = (struct Header*)filedata;
|
|
||||||
struct MeshHeader *mh = NULL;
|
struct MeshHeader *mh = NULL;
|
||||||
struct Mesh m;
|
struct Mesh m;
|
||||||
m.b = NULL;
|
m.b = NULL;
|
||||||
|
@ -8,10 +8,9 @@ void extracttextures(const char *filedata,
|
|||||||
struct Texture *t = NULL;
|
struct Texture *t = NULL;
|
||||||
struct TextureBatchDescriptor *d = NULL;
|
struct TextureBatchDescriptor *d = NULL;
|
||||||
char * fmt = NULL;
|
char * fmt = NULL;
|
||||||
if (filedata == NULL || filesize == 0) {
|
if (!(DEVIL1TEX.getheader(&p, filedata)) || filesize == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
p = (struct TexturePack*)filedata;
|
|
||||||
fmt = (char*)malloc(strlen(filename) + 3 + 4);
|
fmt = (char*)malloc(strlen(filename) + 3 + 4);
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
|
@ -85,6 +85,9 @@ typedef struct {
|
|||||||
// input: pointer to struct
|
// input: pointer to struct
|
||||||
void (* const printcoordinate)(struct Coordinate*, unsigned int);
|
void (* const printcoordinate)(struct Coordinate*, unsigned int);
|
||||||
|
|
||||||
|
// input: pointer to struct, file data
|
||||||
|
bool (* const getheader) (struct Header**, const char*);
|
||||||
|
|
||||||
// input: pointer of pointer to struct, order, file data
|
// input: pointer of pointer to struct, order, file data
|
||||||
// ** = 'pass by reference' of a pointer to struct
|
// ** = 'pass by reference' of a pointer to struct
|
||||||
bool (* const getmeshheader) (struct MeshHeader**,
|
bool (* const getmeshheader) (struct MeshHeader**,
|
||||||
@ -96,11 +99,11 @@ typedef struct {
|
|||||||
unsigned int offset,
|
unsigned int offset,
|
||||||
const char * const);
|
const char * const);
|
||||||
|
|
||||||
// input: pointer to struct, order, file data
|
// input: pointer to struct, order, file data, file size
|
||||||
bool (* const getmesh) (struct Mesh*,
|
bool (* const getmesh) (struct Mesh*,
|
||||||
unsigned int i,
|
unsigned int i,
|
||||||
const char*,
|
const char*,
|
||||||
unsigned int filesize);
|
unsigned int);
|
||||||
} fn_devil1geo;
|
} fn_devil1geo;
|
||||||
extern fn_devil1geo const DEVIL1GEO;
|
extern fn_devil1geo const DEVIL1GEO;
|
||||||
|
|
||||||
|
@ -45,6 +45,9 @@ typedef struct {
|
|||||||
// input: pointer to struct
|
// input: pointer to struct
|
||||||
void (* const printbatchdesc)(struct TextureBatchDescriptor*);
|
void (* const printbatchdesc)(struct TextureBatchDescriptor*);
|
||||||
|
|
||||||
|
// input: pointer to struct, file data
|
||||||
|
bool (* const getheader) (struct TexturePack**, const char*);
|
||||||
|
|
||||||
// input: pointer of pointer to struct, order, file data, file size
|
// input: pointer of pointer to struct, order, file data, file size
|
||||||
// ** = 'pass by reference' of a pointer to struct
|
// ** = 'pass by reference' of a pointer to struct
|
||||||
bool (* const getbatchdesc) (struct TextureBatchDescriptor**,
|
bool (* const getbatchdesc) (struct TextureBatchDescriptor**,
|
||||||
|
@ -9,6 +9,7 @@ static void printmeshbatch(struct Batch*);
|
|||||||
|
|
||||||
static void printcoordinate(struct Coordinate*, unsigned int);
|
static void printcoordinate(struct Coordinate*, unsigned int);
|
||||||
|
|
||||||
|
static bool getgheader(struct Header**, const char*);
|
||||||
|
|
||||||
static bool getmeshheader(struct MeshHeader**, unsigned int i, const char * const);
|
static bool getmeshheader(struct MeshHeader**, unsigned int i, const char * const);
|
||||||
|
|
||||||
@ -20,6 +21,7 @@ fn_devil1geo const DEVIL1GEO = {printgheader,
|
|||||||
printmeshheader,
|
printmeshheader,
|
||||||
printmeshbatch,
|
printmeshbatch,
|
||||||
printcoordinate,
|
printcoordinate,
|
||||||
|
getgheader,
|
||||||
getmeshheader,
|
getmeshheader,
|
||||||
getmeshbatch,
|
getmeshbatch,
|
||||||
getmesh};
|
getmesh};
|
||||||
@ -74,14 +76,22 @@ static void printcoordinate(struct Coordinate *p, unsigned int count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool getgheader(struct Header** h, const char* filedata) {
|
||||||
|
if (filedata == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
(*h) = (struct Header*)filedata;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool getmeshheader(struct MeshHeader **hs,
|
static bool getmeshheader(struct MeshHeader **hs,
|
||||||
unsigned int i,
|
unsigned int i,
|
||||||
const char * const filedata) {
|
const char * const filedata) {
|
||||||
bool done = false;
|
bool done = false;
|
||||||
if (hs == NULL || filedata == NULL) {
|
struct Header *h = NULL;
|
||||||
|
if (hs == NULL || !(getgheader(&h, filedata))) {
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
struct Header *h = (struct Header*)filedata;
|
|
||||||
if (h -> numMesh < i) {
|
if (h -> numMesh < i) {
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,10 @@ static void printtph(struct TexturePack*);
|
|||||||
// Print Texture Batch Descriptor.
|
// Print Texture Batch Descriptor.
|
||||||
static void printtbd(struct TextureBatchDescriptor*);
|
static void printtbd(struct TextureBatchDescriptor*);
|
||||||
|
|
||||||
// Get Texture Batch Descriptor.
|
// Get Texture Pack Header
|
||||||
|
static inline bool getpackheader(struct TexturePack**, const char*);
|
||||||
|
|
||||||
|
// Get Texture Batch Descriptor.
|
||||||
static bool gettexdescriptor(struct TextureBatchDescriptor**,
|
static bool gettexdescriptor(struct TextureBatchDescriptor**,
|
||||||
unsigned int,
|
unsigned int,
|
||||||
const char *,
|
const char *,
|
||||||
@ -30,6 +32,7 @@ static bool unpacktexbatch(struct Texture*,
|
|||||||
|
|
||||||
fn_devil1tex const DEVIL1TEX = {printtph,
|
fn_devil1tex const DEVIL1TEX = {printtph,
|
||||||
printtbd,
|
printtbd,
|
||||||
|
getpackheader,
|
||||||
gettexdescriptor,
|
gettexdescriptor,
|
||||||
gettexbatch,
|
gettexbatch,
|
||||||
unpacktexbatch};
|
unpacktexbatch};
|
||||||
@ -55,6 +58,14 @@ static void printtbd(struct TextureBatchDescriptor *bd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline static bool getpackheader(struct TexturePack** p, const char *filedata) {
|
||||||
|
if (filedata == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
(*p) = (struct TexturePack*)filedata;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool gettexdescriptor(struct TextureBatchDescriptor **descriptor,
|
static bool gettexdescriptor(struct TextureBatchDescriptor **descriptor,
|
||||||
unsigned int i,
|
unsigned int i,
|
||||||
const char *filedata,
|
const char *filedata,
|
||||||
@ -75,10 +86,9 @@ static bool gettexbatch(struct TextureBatch **batch,
|
|||||||
const char *filedata,
|
const char *filedata,
|
||||||
unsigned int filesize) {
|
unsigned int filesize) {
|
||||||
struct TexturePack *p = NULL;
|
struct TexturePack *p = NULL;
|
||||||
if (filedata == NULL) { // no data to get batch from.
|
if (!(getpackheader(&p, filedata))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
p = (struct TexturePack*)filedata;
|
|
||||||
if (i > p -> batchNumber) { // no such batch in texture pack
|
if (i > p -> batchNumber) { // no such batch in texture pack
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user