diff --git a/bindings/py3devil1.py b/bindings/py3devil1.py index 82bb2a0..d63c10b 100755 --- a/bindings/py3devil1.py +++ b/bindings/py3devil1.py @@ -1,8 +1,8 @@ #!/usr/bin/python3 -import ctypes +import ctypes, sys #--------------------------------------+ -# Devil 1: PLD +# Devil 1: PLD Base #--------------------------------------+ class PldHeader(ctypes.Structure): @@ -12,12 +12,6 @@ class PldHeader(ctypes.Structure): ("offsets", ctypes.POINTER(ctypes.c_int)) ] - def getoffsets(self): - pyoffsets = [] - for i in range(0, self.numOffset): - pyoffsets.append(self.offsets[i]) - return pyoffsets - class Devil1PLD_FN(ctypes.Structure): _fields_ = [ ("getheader" , ctypes.CFUNCTYPE( @@ -33,7 +27,7 @@ class Devil1PLD_FN(ctypes.Structure): ] #--------------------------------------+ -# Devil 1: TEX +# Devil 1: TEX Base #--------------------------------------+ class TexturePack(ctypes.Structure): @@ -59,7 +53,7 @@ class TextureBatchDescriptor(ctypes.Structure): class Texture(ctypes.Structure): _pack_ = 1 _fields_ = [ - ("data", ctypes.c_ubyte) + ("data", ctypes.POINTER(ctypes.c_ubyte)) ] class TextureBatch(ctypes.Structure): @@ -95,7 +89,7 @@ class Devil1TEX_FN(ctypes.Structure): ctypes.c_uint, ctypes.c_char_p, ctypes.c_uint)), - ("gettexture", ctypes.CFUNCTYPE( + ("gettextures", ctypes.CFUNCTYPE( ctypes.c_bool, ctypes.POINTER(Texture), ctypes.c_uint, @@ -104,7 +98,7 @@ class Devil1TEX_FN(ctypes.Structure): ] #--------------------------------------+ -# Devil 1: GEO +# Devil 1: GEO Base #--------------------------------------+ class Header(ctypes.Structure): @@ -136,6 +130,9 @@ class Coordinate(ctypes.Structure): ("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_ = [ @@ -143,6 +140,9 @@ class UVs(ctypes.Structure): ("v", ctypes.c_short) ] + def __str__(self): + return "(%s, %s)" % (str(self.u), str(self.v)) + class BoneIndexes(ctypes.Structure): _pack_ = 1 _fields_ = [ @@ -229,6 +229,204 @@ class Devil1GEO_FN(ctypes.Structure): ctypes.c_uint)) ] +#--------------------------------------+ +# Python Objs +#--------------------------------------+ + +sharedlib = './lib3ddevil1.so' +libc = ctypes.cdll.LoadLibrary(sharedlib) +if not libc: + print("Couldn't load %s" % sharedlib) + sys.exit() +del sys +print("\nlib3ddevil1 loaded.") +devil1pld = Devil1PLD_FN.in_dll(libc, "DEVIL1PLD") +devil1tex = Devil1TEX_FN.in_dll(libc, "DEVIL1TEX") +devil1geo = Devil1GEO_FN.in_dll(libc, "DEVIL1GEO") + +class PLDHeader: + def __init__(self, filedata = None): + # Store C Struct in order to call C functions + self.cstruct = PldHeader() + if filedata: + devil1pld.getheader(ctypes.byref(self.cstruct), filedata) + 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) + +class TEXturePack: + def __init__(self, filedata): + self.cstruct = ctypes.pointer(TexturePack()) + devil1tex.getheader(ctypes.byref(self.cstruct), filedata) + 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 TEXtureBatchDescriptor: + def __init__(self, i, filedata): + self.cstruct = ctypes.pointer(TextureBatchDescriptor()) + ptrofptr = ctypes.byref(self.cstruct) + if filedata: + devil1tex.getbatchdesc(ptrofptr, i, filedata, len(filedata)) + 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 TEXtureBatch: + def __init__(self, i, filedata): + self.cstruct = TextureBatch() + if filedata: + self.cstruct.batch = None + tbd = TEXtureBatchDescriptor(i, filedata) + self.amount = tbd.gettexno() + memsize = self.amount * tbd.gettexturesize() + self.cstruct.batch = ctypes.cast( + ctypes.create_string_buffer(memsize), + ctypes.POINTER(Texture)) + devil1tex.gettextures(self.cstruct.batch, i, filedata, len(filedata)) + return + + def gettextures(self): + return self.cstruct.batch[:self.amount] + +class GEOHeader: + def __init__(self, filedata): + self.cstruct = ctypes.pointer(Header()) + ptrofptr = ctypes.byref(self.cstruct) + if filedata: + devil1geo.getheader(ptrofptr, filedata) + return + + def show(self): + devil1geo.printheader(self.cstruct) + + def getmeshno(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 MEShHeader: + def __init__(self, i, filedata): + self.cstruct = ctypes.pointer(MeshHeader()) + ptrofptr = ctypes.byref(self.cstruct) + if filedata: + devil1geo.getmeshheader(ptrofptr, i, filedata) + return + pass + + def show(self): + devil1geo.printmeshheader(self.cstruct) + + def getbatchno(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 MEsh: + def __init__(self, i, filedata): + self.cstruct = Mesh() + if filedata: + mh = MEShHeader(i, filedata) + # allocate memory for the size of batch * number of batches + memsize = ctypes.sizeof(Batch) * mh.getbatchno() + 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)): + print("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] + #--------------------------------------+ # Regular Python #--------------------------------------+ @@ -238,10 +436,11 @@ if __name__ == "__main__": data = f.read() devil1pld.getheader(ctypes.byref(pldheader), data) devil1pld.printheader(ctypes.byref(pldheader)) - for offset in pldheader.getoffsets(): - print(hex(offset)) + # 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)) @@ -252,8 +451,11 @@ if __name__ == "__main__": 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)) @@ -285,6 +487,60 @@ if __name__ == "__main__": geoh = Header() geotest(geofn, geoh) -#---------------------------------------+ - main() + def mainx(): + with open("pl01.pld", "rb") as f: + data = f.read() + pld = PLDHeader(data) + pld.show() + pld2 = PLDHeader() + pld2.show() + + with open("pl01.pld_1.txp", "rb") as f: + data = f.read() + txp = TEXturePack(data) + txp.show() + print(txp.getbatchno()) + print(txp.getfirstbatchoffset()) + tbd = TEXtureBatchDescriptor(1, data) + tbd.show() + print(tbd.gettexturesize()) + #tx = TEXtures(0, tbd.gettexno(), data) + tx = TEXtureBatch(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 = GEOHeader(data) + gh.show() + print("-------------") + print(gh.getmeshno()) + print(gh.getunknownb()) + print(gh.getunknownc()) + print(gh.getunknownd()) + print(gh.getpadding()) + print(gh.getunknownoffset()) + mh = MEShHeader(3, data) + mh.show() + m = MEsh(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()