From b6947d8f11d6a8061b9de08d377b7ed9b165c50d Mon Sep 17 00:00:00 2001 From: _ <_> Date: Sat, 21 Apr 2018 04:29:13 -0700 Subject: [PATCH 01/38] Adjustment on readme on building --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 808cf2b..71778ff 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,16 @@ A C library for handling Devil May Cry 1 HD Collection PC file formats. -#### Build Demos -Run `make` +#### Build +Run `make` to build demos. + +Include the appropriate files in your build system. Reference the Makefile for an example of building with GCC. + #### Compiler(s) Developed and tested with the following compilers. + * mingw-w64, GCC 6.4.0 * gcc version 7.1.1 20170528 From 23405ca83eae3177bc1a2d35bd1a2966b44ca1f7 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Sun, 22 Apr 2018 17:37:35 -0700 Subject: [PATCH 02/38] Added document for pld component --- docs/doc-pld.txt | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 docs/doc-pld.txt diff --git a/docs/doc-pld.txt b/docs/doc-pld.txt new file mode 100644 index 0000000..0e53808 --- /dev/null +++ b/docs/doc-pld.txt @@ -0,0 +1,56 @@ + +devil1pld.h / devil1pld.c + Handles .pld files. + +File Format + PLDs are simple packages of different files, and do not contain a table + of contents. The header consists only of the number of files packaged + and the offsets from the beginning of the .pld that marks the starting + location of the file. + +Functions + All functions are static but exposed by a function pointer in a constant + struct called DEVIL1PLD. For example, clients call functions using + DEVIL1PLD.getheader(..., ...); + + bool getheader(struct PldHeader*, const char*); + Places file header into the struct pointed at by the first parameter + from the information given in by the second parameter. + + inputs: pointer to a struct, pointer to file data + Neither parameter should be NULL. + + output: true or false, whether or not operation succeeds or fails. + Will return false if one or both of the parameters are NULL + pointers. + Will return false if the attribute numOffset is less than 0- + i.e file is not valid. + + int sizeofsector(struct PldHeader*, unsigned int i, unsigned int max); + Returns the size of the i-th file packed in the pld. + + inputs: pointer to a struct, i-th element in pld, file size + + output: (-1), [0, maximum value of int) + -1 indicates an invalid input. + + void printheader(struct PldHeader*); + Shows contents of a PLD header in standard output. + + inputs: pointer of a struct + +Example logic to iterate through a .pld + { + ... + // Get information about the file + struct PldHeader h; + DEVIL1PLD.getheader(&h, data); + + unsigned int i; + for (i = 0; i < h.numOffset; i++) { + const char *currentfile = filedata + h.offset[i]; + ... + } + ... + + } From d6ef6e3dc5cb744acbb5774cf759f400c96609fe Mon Sep 17 00:00:00 2001 From: _ <_> Date: Sun, 22 Apr 2018 17:59:52 -0700 Subject: [PATCH 03/38] Added brief overview --- docs/doc-overview.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 docs/doc-overview.txt diff --git a/docs/doc-overview.txt b/docs/doc-overview.txt new file mode 100644 index 0000000..786583b --- /dev/null +++ b/docs/doc-overview.txt @@ -0,0 +1,23 @@ + +lib3ddevil1 +A C library for handling Devil May Cry 1 HD Collection PC file formats. +These formats are little endian. + +Design/Restrictions + Library functions do not: + - allocate memory on the heap + - operate on files + - convert endianness + +Pseudo-Namespaces + Library functions are callable through a struct of function pointers. + For example: + // Print header of a .pld file. + DEVIL1PLD.printheader(...); + + // Print header of a texture pack. + DEVIL1TEX.printheader(...); + + // Print header of a mesh pack. + DEVIL1GEO.printheader(...); + From 4bed12289b7bf931dcd8143541ff8d8717e7c8ee Mon Sep 17 00:00:00 2001 From: <> Date: Wed, 25 Apr 2018 03:58:33 -0700 Subject: [PATCH 04/38] Added docs for texture component --- docs/doc-tex.txt | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 docs/doc-tex.txt diff --git a/docs/doc-tex.txt b/docs/doc-tex.txt new file mode 100644 index 0000000..0b05d3e --- /dev/null +++ b/docs/doc-tex.txt @@ -0,0 +1,99 @@ + +devil1tex.h / devil1tex.c + Handles texture packages. + +Functions + All functions are static but exposed by a function pointer in a constant + struct called DEVIL1TEX. For example, clients call functions using + DEVIL1TEX.printheader(...); + + + void printheader(struct TexturePack*); + Prints the attributes and values of a header to standard output. + + input: pointer to a TexturePack struct. + + void printbatchdesc(struct TextureBatchDescriptor*); + Prints the attributes and values if a TextureBatchDescriptor to + standard output. + + bool getbatchdesc(struct TextureBatchDescriptor**, + unsigned int, + const char *, + unsigned int); + Retrieves the i-th TextureBatchDescriptor from a buffer. + + input: + Pointer to a pointer of TextureBatchDescriptor. + This is pass by reference of a pointer to the function. + The pointer to TextureBatchDescriptor can be NULL and will be + set to point to a region in the const char*. + + unsigned int, the i-th instance of a TextureBatchDescriptor in + the const char*. + + const char*, the buffer containing the whole texture pack file. + + unsigned int, the size of the buffer. + + output: + true when successfully retrieving a pointer to + TextureBatchDescriptor. + + false when unsuccesful in retrieving a pointer to + TextureBatchDescriptor; failed checks against segmentation + faults. + When const char* (buffer) is NULL. + + When the location of the TextureBatchDescriptor will exceed + the size of a buffer. + + bool getbatch(struct TextureBatch**, + unsigned int, + const char* + unsigned int); + Retrieves i-th instance of a TextureBatch from a buffer. + + input: + Pointer to a pointer of TextureBatch. + This is pass by reference of a pointer to the function. + The pointer to a TextureBatch can be NULL and will be set to + point to a region in the const char*. + + unsigned int, the i-th instance of a TextureBatch in the + const char*. + + const char*, the buffer containing the whole texture pack file. + + unsigned int, the size of the buffer. + + output: + true on success. + + false when failing checks against segmentation faults. + When const char* is NULL. + + When the location of the Texture Batch will exceed the size + of the buffer. + + bool gettextures(struct Texture*, + unsigned int, + const char*, + unsigned int); + Retrieves textures of the i-th batch from a buffer. + + input: + Pointer to Texture. This can be an array of Textures. + This parameter can not be NULL. + + unsigned int, the i-th instance the TextureBatch containing + the files. + + const char*, the buffer containing the whole texture pack file. + + unsigned int, size of the buffer. + + output: + true on success. + + false when failing checks against segmentation faults. From b2ddc14a6322ea7634c9df7e6e561b91bb0f2be1 Mon Sep 17 00:00:00 2001 From: <> Date: Wed, 25 Apr 2018 04:12:48 -0700 Subject: [PATCH 05/38] Added example of getting all textures --- docs/doc-tex.txt | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docs/doc-tex.txt b/docs/doc-tex.txt index 0b05d3e..cbb09c4 100644 --- a/docs/doc-tex.txt +++ b/docs/doc-tex.txt @@ -97,3 +97,32 @@ Functions true on success. false when failing checks against segmentation faults. + +Example logic to extract all textures: + { + // After reading the file in... + // Need to know how many batches are in the package. + struct TexturePack *p = (struct TexturePack*)filedata; + + // Need to know about each batch in the package. + struct TextureBatchDescriptor *d = NULL; + + struct Texture *t = NULL; + + unsigned int i; + for (i = 0; i < p -> batchNumber; i++) { + DEVIL1TEX.getbatchdesc(&d, i, filedata, filesize); + + // Batch descriptor tells how many textures are in the batch. + t = (struct Texture*) + malloc(sizeof(struct Texture) * (d -> texNumber)); + DEVIL1TEX.gettextures(t, i, filedata, filesize); + + // There are now textures in 't'. + for (j = 0; j < d -> texNumber; j++) { + // Do whatever you want with however many of them there are. + } + + } + } + From eca26f20590e3ae54c639532991889e83cb1f997 Mon Sep 17 00:00:00 2001 From: <> Date: Wed, 25 Apr 2018 04:49:15 -0700 Subject: [PATCH 06/38] Added docs for geo component --- docs/doc-geo.txt | 101 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 docs/doc-geo.txt diff --git a/docs/doc-geo.txt b/docs/doc-geo.txt new file mode 100644 index 0000000..9b8251f --- /dev/null +++ b/docs/doc-geo.txt @@ -0,0 +1,101 @@ + +devil1geo.h / devil1geo.c + Handles files containing geometry. + +Functions + void printheader(struct Header*); + Show attributes and values of a Header for the package. + + input: pointer to Header, pass by reference of a struct. + Can not be NULL. + + void printmeshheader(struct MeshHeader*); + Show attributes and values of a MeshHeader. + + input: pointer to MeshHeader, pass by reference of a struct. + Can not be NULL. + + void printbatch(struct Batch*); + Show attribute and values of a Batch and three sample position + coordinates. + + input: pointer to Batch, pass by reference of a struct. + Can not be NULL. + + void printcoordinate(struct Coordinate*, unsigned int); + + input: + pointer to array of Coordinates. + Can not be NULL. + + unsigned int, for quantity of coordinates to be printed. + + + bool getmeshheader(struct MeshHeader**, + unsigned int, + const char * const); + Retrives the i-th MeshHeader in a buffer. + + input: + Pointer of a pointer to MeshHeader. + Pass by reference of a pointer to the function. + The pointer of MeshHeader can be NULL and will be set to point to + a region in the buffer. + + unsigned int, the i-th instance of MeshHeader in the buffer. + + const char*, the buffer containing the whole mesh package. + + output: + true on success. + + false when failing checks against segmentation faults. + If parameter 'struct MeshHeader**' is NULL. + If parameter 'const char*' is NULL. + + bool getbatch(struct Batch*, + unsigned int offset, + const char * const); + Retrives the i-th Batch in a buffer. + + input: + Pointer to a Batch. + Pass by reference of a struct to the function. + Can not be NULL. + + unsigned int, the i-th instance of Batch in the buffer. + + const char*, the buffer containing the whole mesh package. + + output: + true on success. + + false when failing checks against segmentation faults. + If parameter 'struct Batch*' is NULL. + If parameter 'const char*' is NULL. + + bool getmesh(struct Mesh*, + unsigned int, + const char*, + unsigned int); + Retrives the i-th Mesh in a buffer. + + input: + Pointer to mesh. + Pass by reference of a struct to the function. + + unsigned int, the i-th instance of Mesh in the buffer. + + const char*, the buffer containing the whole mesh package. + + output: + true on success. + + false when failing checks against segmentation faults. + If parameter 'struct Mesh*' is NULL. + If attribute 'b' of parameter 'struct Mesh' is NULL. + if parameter 'const char*' is NULL. + When file size is detected to be too small for a given i-th + Mesh. + + \ No newline at end of file From bc6b2081e079b5bd3aed1d98a80dab3cc60686f0 Mon Sep 17 00:00:00 2001 From: <> Date: Wed, 25 Apr 2018 04:49:39 -0700 Subject: [PATCH 07/38] Added small description of texture file format --- docs/doc-tex.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/doc-tex.txt b/docs/doc-tex.txt index cbb09c4..e52a878 100644 --- a/docs/doc-tex.txt +++ b/docs/doc-tex.txt @@ -2,6 +2,10 @@ devil1tex.h / devil1tex.c Handles texture packages. +File Format + Texture packags can be identified with a string "\0 2 3 T" as a starting + tag. + Functions All functions are static but exposed by a function pointer in a constant struct called DEVIL1TEX. For example, clients call functions using From 063a091d7f67b1d6e76d0021a4c79c01bbe6a69f Mon Sep 17 00:00:00 2001 From: <> Date: Wed, 25 Apr 2018 04:55:03 -0700 Subject: [PATCH 08/38] Added example for geo component --- docs/doc-geo.txt | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/doc-geo.txt b/docs/doc-geo.txt index 9b8251f..26b5085 100644 --- a/docs/doc-geo.txt +++ b/docs/doc-geo.txt @@ -98,4 +98,30 @@ Functions When file size is detected to be too small for a given i-th Mesh. - \ No newline at end of file +Example logic to interact with all meshes: + { + // After the file has been read in. + + // Need to know how many meshes are in the file. + struct Header *h = (struct Header*)filedata; + + // Need to know about a specific mesh (how many batches). + struct MeshHeader *mh = NULL; + + // Need to hold information about mesh. + struct Mesh m; + // As a precaution - empty for now. + m.b = NULL; + + unsigned int i; + for (i = 0; i < h -> numMesh; i++) { + DEVIL1GEO.getmeshheader(&mh, i, filedata); + // Allocate space to hold batch data. + m.b = (struct Batch*)malloc(sizeof(struct Batch) * (mh -> numBatch)); + if (m.b != NULL) { + DEVIL1GEO.getmesh(&m, i, filedata, filesize); + // Do whatever you want with the mesh. + free(m.b); + } + } + From e9fa07b695d37a77b018395287ebefd3fd7c7d0c Mon Sep 17 00:00:00 2001 From: <> Date: Wed, 25 Apr 2018 04:56:37 -0700 Subject: [PATCH 09/38] Minor adjustments --- docs/doc-tex.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/doc-tex.txt b/docs/doc-tex.txt index e52a878..5ce4387 100644 --- a/docs/doc-tex.txt +++ b/docs/doc-tex.txt @@ -102,7 +102,7 @@ Functions false when failing checks against segmentation faults. -Example logic to extract all textures: +Example logic to interact with all textures: { // After reading the file in... // Need to know how many batches are in the package. @@ -124,9 +124,9 @@ Example logic to extract all textures: // There are now textures in 't'. for (j = 0; j < d -> texNumber; j++) { - // Do whatever you want with however many of them there are. + // Do whatever you want with however many textures there are. } - + free(t); } } From 012abafa270d707c2c34c7320a94171dcc6f7b48 Mon Sep 17 00:00:00 2001 From: <> Date: Wed, 25 Apr 2018 04:59:00 -0700 Subject: [PATCH 10/38] Added segment about the namespace --- docs/doc-geo.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/doc-geo.txt b/docs/doc-geo.txt index 26b5085..e3ed31e 100644 --- a/docs/doc-geo.txt +++ b/docs/doc-geo.txt @@ -3,6 +3,10 @@ devil1geo.h / devil1geo.c Handles files containing geometry. Functions + All functions are static but exposed by a function pointer in a constant + struct called DEVIL1GEO. For example, clients call functions using + DEVIL1GEO.printheader(...); + void printheader(struct Header*); Show attributes and values of a Header for the package. From 295b826e365ba616c67ea06a9d2512f160da548b Mon Sep 17 00:00:00 2001 From: <> Date: Wed, 25 Apr 2018 05:06:09 -0700 Subject: [PATCH 11/38] Added missing description for printcoordinate() --- docs/doc-geo.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/doc-geo.txt b/docs/doc-geo.txt index e3ed31e..7de2fb6 100644 --- a/docs/doc-geo.txt +++ b/docs/doc-geo.txt @@ -27,7 +27,8 @@ Functions Can not be NULL. void printcoordinate(struct Coordinate*, unsigned int); - + Show a specified quantity of Coordinates. + input: pointer to array of Coordinates. Can not be NULL. From d8e1c451564c1aede9f15e31d3f68180bdbc6973 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Tue, 15 May 2018 12:42:16 -0700 Subject: [PATCH 12/38] split python file into parts --- bindings/main.py | 121 +++++++++ bindings/py3devil1.py | 546 --------------------------------------- bindings/py3devil1geo.py | 254 ++++++++++++++++++ bindings/py3devil1pld.py | 65 +++++ bindings/py3devil1tex.py | 144 +++++++++++ 5 files changed, 584 insertions(+), 546 deletions(-) create mode 100644 bindings/main.py delete mode 100755 bindings/py3devil1.py create mode 100644 bindings/py3devil1geo.py create mode 100644 bindings/py3devil1pld.py create mode 100644 bindings/py3devil1tex.py diff --git a/bindings/main.py b/bindings/main.py new file mode 100644 index 0000000..c88aa65 --- /dev/null +++ b/bindings/main.py @@ -0,0 +1,121 @@ +from py3devil1pld import * +from py3devil1tex import * +from py3devil1geo import * + +#--------------------------------------+ +# 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 = PldHeader() + 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 = 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() diff --git a/bindings/py3devil1.py b/bindings/py3devil1.py deleted file mode 100755 index d63c10b..0000000 --- a/bindings/py3devil1.py +++ /dev/null @@ -1,546 +0,0 @@ -#!/usr/bin/python3 -import ctypes, sys - -#--------------------------------------+ -# Devil 1: PLD Base -#--------------------------------------+ - -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))) - ] - -#--------------------------------------+ -# Devil 1: TEX Base -#--------------------------------------+ - -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)) - ] - -#--------------------------------------+ -# Devil 1: GEO Base -#--------------------------------------+ - -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( - None, - 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)) - ] - -#--------------------------------------+ -# 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 -#--------------------------------------+ -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 = PldHeader() - 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 = 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() - diff --git a/bindings/py3devil1geo.py b/bindings/py3devil1geo.py new file mode 100644 index 0000000..939c282 --- /dev/null +++ b/bindings/py3devil1geo.py @@ -0,0 +1,254 @@ +#!/usr/bin/python3 +import ctypes, sys + +sharedlib = './lib3ddevil1.so' +libc = ctypes.cdll.LoadLibrary(sharedlib) +if not libc: + print("Couldn't load %s" % sharedlib) + sys.exit() +del sys + +print("\nlib3ddevil1 loaded.") + +#--------------------------------------+ +# 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( + None, + 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") + +#--------------------------------------+ +# Pythonic Object +#--------------------------------------+ + +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] diff --git a/bindings/py3devil1pld.py b/bindings/py3devil1pld.py new file mode 100644 index 0000000..ad66826 --- /dev/null +++ b/bindings/py3devil1pld.py @@ -0,0 +1,65 @@ +#!/usr/bin/python3 +import ctypes, sys + +sharedlib = './lib3ddevil1.so' +libc = ctypes.cdll.LoadLibrary(sharedlib) +if not libc: + print("Couldn't load %s" % sharedlib) + sys.exit() +del sys +print("\nlib3ddevil1 loaded.") + +#--------------------------------------+ +# 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") + +#--------------------------------------+ +# Pythonic Object +#--------------------------------------+ + +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) + diff --git a/bindings/py3devil1tex.py b/bindings/py3devil1tex.py new file mode 100644 index 0000000..0fa32a9 --- /dev/null +++ b/bindings/py3devil1tex.py @@ -0,0 +1,144 @@ +#!/usr/bin/python3 +import ctypes, sys + +sharedlib = './lib3ddevil1.so' +libc = ctypes.cdll.LoadLibrary(sharedlib) +if not libc: + print("Couldn't load %s" % sharedlib) + sys.exit() +del sys + +print("\nlib3ddevil1 loaded.") + +#--------------------------------------+ +# 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") + +#--------------------------------------+ +# Pythonic Object +#--------------------------------------+ + +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] + From 2c44adf7a2ab98414ea2264b6d899fdc2c7be343 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Tue, 15 May 2018 15:04:53 -0700 Subject: [PATCH 13/38] Moved out repeated code to __init__ & .so loaded once only --- bindings/__init__.py | 13 +++++++++++++ bindings/main.py | 8 +++++--- bindings/py3devil1geo.py | 13 +++---------- bindings/py3devil1pld.py | 12 +++--------- bindings/py3devil1tex.py | 13 +++---------- 5 files changed, 27 insertions(+), 32 deletions(-) diff --git a/bindings/__init__.py b/bindings/__init__.py index e69de29..7262a68 100644 --- a/bindings/__init__.py +++ b/bindings/__init__.py @@ -0,0 +1,13 @@ +import sys, ctypes + +sharedlib = './lib3ddevil1.so' +libc = ctypes.cdll.LoadLibrary(sharedlib) +if not libc: + print("Couldn't load %s" % sharedlib) + sys.exit() + +# Observe how many times the .so is loaded. +print("\nlib3ddevil1 loaded.") + +# Don't need these anymore +del sys, sharedlib diff --git a/bindings/main.py b/bindings/main.py index c88aa65..290f681 100644 --- a/bindings/main.py +++ b/bindings/main.py @@ -1,6 +1,8 @@ -from py3devil1pld import * -from py3devil1tex import * -from py3devil1geo import * +from py3devil1pld import PLDHeader +from py3devil1tex import TEXturePack, TEXtureBatchDescriptor, TEXtureBatch +from py3devil1geo import GEOHeader, MEShHeader, MEsh + +#print(libc) #--------------------------------------+ # Regular Python diff --git a/bindings/py3devil1geo.py b/bindings/py3devil1geo.py index 939c282..065b11a 100644 --- a/bindings/py3devil1geo.py +++ b/bindings/py3devil1geo.py @@ -1,14 +1,6 @@ #!/usr/bin/python3 -import ctypes, sys - -sharedlib = './lib3ddevil1.so' -libc = ctypes.cdll.LoadLibrary(sharedlib) -if not libc: - print("Couldn't load %s" % sharedlib) - sys.exit() -del sys - -print("\nlib3ddevil1 loaded.") +import ctypes +from __init__ import libc #--------------------------------------+ # Basic Struct @@ -143,6 +135,7 @@ class Devil1GEO_FN(ctypes.Structure): ] devil1geo = Devil1GEO_FN.in_dll(libc, "DEVIL1GEO") +del libc #--------------------------------------+ # Pythonic Object diff --git a/bindings/py3devil1pld.py b/bindings/py3devil1pld.py index ad66826..c02943c 100644 --- a/bindings/py3devil1pld.py +++ b/bindings/py3devil1pld.py @@ -1,13 +1,6 @@ #!/usr/bin/python3 -import ctypes, sys - -sharedlib = './lib3ddevil1.so' -libc = ctypes.cdll.LoadLibrary(sharedlib) -if not libc: - print("Couldn't load %s" % sharedlib) - sys.exit() -del sys -print("\nlib3ddevil1 loaded.") +import ctypes +from __init__ import libc #--------------------------------------+ # Basic Struct @@ -35,6 +28,7 @@ class Devil1PLD_FN(ctypes.Structure): ] devil1pld = Devil1PLD_FN.in_dll(libc, "DEVIL1PLD") +del libc #--------------------------------------+ # Pythonic Object diff --git a/bindings/py3devil1tex.py b/bindings/py3devil1tex.py index 0fa32a9..67fb1a2 100644 --- a/bindings/py3devil1tex.py +++ b/bindings/py3devil1tex.py @@ -1,14 +1,6 @@ #!/usr/bin/python3 -import ctypes, sys - -sharedlib = './lib3ddevil1.so' -libc = ctypes.cdll.LoadLibrary(sharedlib) -if not libc: - print("Couldn't load %s" % sharedlib) - sys.exit() -del sys - -print("\nlib3ddevil1 loaded.") +import ctypes +from __init__ import libc #--------------------------------------+ # Basic Struct @@ -82,6 +74,7 @@ class Devil1TEX_FN(ctypes.Structure): ] devil1tex = Devil1TEX_FN.in_dll(libc, "DEVIL1TEX") +del libc #--------------------------------------+ # Pythonic Object From 42e2d88734f6fb62cbca86d1a0c5ce469d043527 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Tue, 15 May 2018 17:35:24 -0700 Subject: [PATCH 14/38] Fixed importing from external directory --- bindings/py3devil1geo.py | 2 +- bindings/py3devil1pld.py | 2 +- bindings/py3devil1tex.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bindings/py3devil1geo.py b/bindings/py3devil1geo.py index 065b11a..7d5ca1b 100644 --- a/bindings/py3devil1geo.py +++ b/bindings/py3devil1geo.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 import ctypes -from __init__ import libc +from .__init__ import libc #--------------------------------------+ # Basic Struct diff --git a/bindings/py3devil1pld.py b/bindings/py3devil1pld.py index c02943c..c8fd904 100644 --- a/bindings/py3devil1pld.py +++ b/bindings/py3devil1pld.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 import ctypes -from __init__ import libc +from .__init__ import libc #--------------------------------------+ # Basic Struct diff --git a/bindings/py3devil1tex.py b/bindings/py3devil1tex.py index 67fb1a2..7ad661a 100644 --- a/bindings/py3devil1tex.py +++ b/bindings/py3devil1tex.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 import ctypes -from __init__ import libc +from .__init__ import libc #--------------------------------------+ # Basic Struct From a5abb9d24f93800b895e9a20a7d88842a19bc2aa Mon Sep 17 00:00:00 2001 From: _ <_> Date: Wed, 16 May 2018 20:18:37 -0700 Subject: [PATCH 15/38] Added final names for pld component --- bindings/main.py | 6 +++--- bindings/py3devil1pld.py | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bindings/main.py b/bindings/main.py index 290f681..8659ea2 100644 --- a/bindings/main.py +++ b/bindings/main.py @@ -1,4 +1,4 @@ -from py3devil1pld import PLDHeader +from py3devil1pld import PldHeader from py3devil1tex import TEXturePack, TEXtureBatchDescriptor, TEXtureBatch from py3devil1geo import GEOHeader, MEShHeader, MEsh @@ -68,9 +68,9 @@ if __name__ == "__main__": def mainx(): with open("pl01.pld", "rb") as f: data = f.read() - pld = PLDHeader(data) + pld = PldHeader(data) pld.show() - pld2 = PLDHeader() + pld2 = PldHeader() pld2.show() with open("pl01.pld_1.txp", "rb") as f: diff --git a/bindings/py3devil1pld.py b/bindings/py3devil1pld.py index c8fd904..8bc6c5d 100644 --- a/bindings/py3devil1pld.py +++ b/bindings/py3devil1pld.py @@ -6,7 +6,7 @@ from .__init__ import libc # Basic Struct #--------------------------------------+ -class PldHeader(ctypes.Structure): +class _PldHeader_(ctypes.Structure): _pack_ = 1 _fields_ = [ ("numOffset", ctypes.c_int), @@ -17,14 +17,14 @@ class Devil1PLD_FN(ctypes.Structure): _fields_ = [ ("getheader" , ctypes.CFUNCTYPE( ctypes.c_bool, - ctypes.POINTER(PldHeader), + ctypes.POINTER(_PldHeader_), ctypes.c_char_p)), ("sizeofsector", ctypes.CFUNCTYPE( ctypes.c_int, - ctypes.POINTER(PldHeader), + ctypes.POINTER(_PldHeader_), ctypes.c_int)), ("printheader" , ctypes.CFUNCTYPE(None, - ctypes.POINTER(PldHeader))) + ctypes.POINTER(_PldHeader_))) ] devil1pld = Devil1PLD_FN.in_dll(libc, "DEVIL1PLD") @@ -34,10 +34,10 @@ del libc # Pythonic Object #--------------------------------------+ -class PLDHeader: +class PldHeader: def __init__(self, filedata = None): # Store C Struct in order to call C functions - self.cstruct = PldHeader() + self.cstruct = _PldHeader_() if filedata: devil1pld.getheader(ctypes.byref(self.cstruct), filedata) self.eof = len(filedata) From 43afe7bf70b24d5d7bbf9312ee85b1932108a065 Mon Sep 17 00:00:00 2001 From: surkeh Date: Wed, 16 May 2018 22:10:46 -0700 Subject: [PATCH 16/38] Cleanup: #!s, prints, exceptions, more consistent naming --- Makefile | 2 +- bindings/__init__.py | 6 +----- bindings/{main.py => __test__.py} | 27 ++++++++++++++------------- bindings/py3devil1geo.py | 11 +++++------ bindings/py3devil1pld.py | 14 +++++++------- bindings/py3devil1tex.py | 11 +++++------ 6 files changed, 33 insertions(+), 38 deletions(-) rename bindings/{main.py => __test__.py} (86%) mode change 100644 => 100755 diff --git a/Makefile b/Makefile index ee67998..9b199fb 100644 --- a/Makefile +++ b/Makefile @@ -35,4 +35,4 @@ devil1geo.o: src/devil1geo.c $(CC) -c $^ $(CFLAGS) clean: - rm *.o *.gch $(TARGET) $(PEX) $(TEX) $(MEX) + rm *.o $(TARGET) $(PEX) $(TEX) $(MEX) diff --git a/bindings/__init__.py b/bindings/__init__.py index 7262a68..dbbc6dc 100644 --- a/bindings/__init__.py +++ b/bindings/__init__.py @@ -3,11 +3,7 @@ import sys, ctypes sharedlib = './lib3ddevil1.so' libc = ctypes.cdll.LoadLibrary(sharedlib) if not libc: - print("Couldn't load %s" % sharedlib) - sys.exit() - -# Observe how many times the .so is loaded. -print("\nlib3ddevil1 loaded.") + raise SystemExit("Couldn't load %s" % sharedlib) # Don't need these anymore del sys, sharedlib diff --git a/bindings/main.py b/bindings/__test__.py old mode 100644 new mode 100755 similarity index 86% rename from bindings/main.py rename to bindings/__test__.py index 8659ea2..3953c65 --- a/bindings/main.py +++ b/bindings/__test__.py @@ -1,6 +1,7 @@ -from py3devil1pld import PldHeader -from py3devil1tex import TEXturePack, TEXtureBatchDescriptor, TEXtureBatch -from py3devil1geo import GEOHeader, MEShHeader, MEsh +#!/usr/bin/python3 +from py3devil1pld import pyPldHeader +from py3devil1tex import pyTexturePack, pyTextureBatchDescriptor, pyTextureBatch +from py3devil1geo import pyGeoHeader, pyMeshHeader, pyMesh #print(libc) @@ -54,7 +55,7 @@ if __name__ == "__main__": print("OK") pldfn = Devil1PLD_FN.in_dll(libc, "DEVIL1PLD") - pldh = PldHeader() + pldh = pyPldHeader() pldtest(pldfn, pldh) texfn = Devil1TEX_FN.in_dll(libc, "DEVIL1TEX") @@ -68,29 +69,29 @@ if __name__ == "__main__": def mainx(): with open("pl01.pld", "rb") as f: data = f.read() - pld = PldHeader(data) + pld = pyPldHeader(data) pld.show() - pld2 = PldHeader() + pld2 = pyPldHeader() pld2.show() with open("pl01.pld_1.txp", "rb") as f: data = f.read() - txp = TEXturePack(data) + txp = pyTexturePack(data) txp.show() print(txp.getbatchno()) print(txp.getfirstbatchoffset()) - tbd = TEXtureBatchDescriptor(1, data) + tbd = pyTextureBatchDescriptor(1, data) tbd.show() print(tbd.gettexturesize()) - #tx = TEXtures(0, tbd.gettexno(), data) - tx = TEXtureBatch(0, data) + #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 = GEOHeader(data) + gh = pyGeoHeader(data) gh.show() print("-------------") print(gh.getmeshno()) @@ -99,9 +100,9 @@ if __name__ == "__main__": print(gh.getunknownd()) print(gh.getpadding()) print(gh.getunknownoffset()) - mh = MEShHeader(3, data) + mh = pyMeshHeader(3, data) mh.show() - m = MEsh(0, data) + m = pyMesh(0, data) m.show() # p = m.getpositions() # print("positions:") diff --git a/bindings/py3devil1geo.py b/bindings/py3devil1geo.py index 7d5ca1b..7388053 100644 --- a/bindings/py3devil1geo.py +++ b/bindings/py3devil1geo.py @@ -1,6 +1,5 @@ -#!/usr/bin/python3 import ctypes -from .__init__ import libc +from __init__ import libc #--------------------------------------+ # Basic Struct @@ -141,7 +140,7 @@ del libc # Pythonic Object #--------------------------------------+ -class GEOHeader: +class pyGeoHeader: def __init__(self, filedata): self.cstruct = ctypes.pointer(Header()) ptrofptr = ctypes.byref(self.cstruct) @@ -171,7 +170,7 @@ class GEOHeader: return hex(self.cstruct.contents.unknownOffset) -class MEShHeader: +class pyMeshHeader: def __init__(self, i, filedata): self.cstruct = ctypes.pointer(MeshHeader()) ptrofptr = ctypes.byref(self.cstruct) @@ -198,11 +197,11 @@ class MEShHeader: def getflags(self): return self.cstruct.contents.flags -class MEsh: +class pyMesh: def __init__(self, i, filedata): self.cstruct = Mesh() if filedata: - mh = MEShHeader(i, filedata) + mh = pyMeshHeader(i, filedata) # allocate memory for the size of batch * number of batches memsize = ctypes.sizeof(Batch) * mh.getbatchno() self.cstruct.b = ctypes.cast( diff --git a/bindings/py3devil1pld.py b/bindings/py3devil1pld.py index 8bc6c5d..958f8bd 100644 --- a/bindings/py3devil1pld.py +++ b/bindings/py3devil1pld.py @@ -1,12 +1,12 @@ #!/usr/bin/python3 import ctypes -from .__init__ import libc +from __init__ import libc #--------------------------------------+ # Basic Struct #--------------------------------------+ -class _PldHeader_(ctypes.Structure): +class PldHeader(ctypes.Structure): _pack_ = 1 _fields_ = [ ("numOffset", ctypes.c_int), @@ -17,14 +17,14 @@ class Devil1PLD_FN(ctypes.Structure): _fields_ = [ ("getheader" , ctypes.CFUNCTYPE( ctypes.c_bool, - ctypes.POINTER(_PldHeader_), + ctypes.POINTER(PldHeader), ctypes.c_char_p)), ("sizeofsector", ctypes.CFUNCTYPE( ctypes.c_int, - ctypes.POINTER(_PldHeader_), + ctypes.POINTER(PldHeader), ctypes.c_int)), ("printheader" , ctypes.CFUNCTYPE(None, - ctypes.POINTER(_PldHeader_))) + ctypes.POINTER(PldHeader))) ] devil1pld = Devil1PLD_FN.in_dll(libc, "DEVIL1PLD") @@ -34,10 +34,10 @@ del libc # Pythonic Object #--------------------------------------+ -class PldHeader: +class pyPldHeader: def __init__(self, filedata = None): # Store C Struct in order to call C functions - self.cstruct = _PldHeader_() + self.cstruct = PldHeader() if filedata: devil1pld.getheader(ctypes.byref(self.cstruct), filedata) self.eof = len(filedata) diff --git a/bindings/py3devil1tex.py b/bindings/py3devil1tex.py index 7ad661a..32aeb7f 100644 --- a/bindings/py3devil1tex.py +++ b/bindings/py3devil1tex.py @@ -1,6 +1,5 @@ -#!/usr/bin/python3 import ctypes -from .__init__ import libc +from __init__ import libc #--------------------------------------+ # Basic Struct @@ -80,7 +79,7 @@ del libc # Pythonic Object #--------------------------------------+ -class TEXturePack: +class pyTexturePack: def __init__(self, filedata): self.cstruct = ctypes.pointer(TexturePack()) devil1tex.getheader(ctypes.byref(self.cstruct), filedata) @@ -95,7 +94,7 @@ class TEXturePack: def getfirstbatchoffset(self): return self.cstruct.contents.firstBatchOffset -class TEXtureBatchDescriptor: +class pyTextureBatchDescriptor: def __init__(self, i, filedata): self.cstruct = ctypes.pointer(TextureBatchDescriptor()) ptrofptr = ctypes.byref(self.cstruct) @@ -118,12 +117,12 @@ class TEXtureBatchDescriptor: def gettexturesize(self): return self.cstruct.contents.textureSize -class TEXtureBatch: +class pyTextureBatch: def __init__(self, i, filedata): self.cstruct = TextureBatch() if filedata: self.cstruct.batch = None - tbd = TEXtureBatchDescriptor(i, filedata) + tbd = pyTextureBatchDescriptor(i, filedata) self.amount = tbd.gettexno() memsize = self.amount * tbd.gettexturesize() self.cstruct.batch = ctypes.cast( From 6ffe6f57ece7fbe246a0281390f9bd789668decb Mon Sep 17 00:00:00 2001 From: surkeh Date: Wed, 16 May 2018 22:32:43 -0700 Subject: [PATCH 17/38] Raise exception if python mesh fails to extract meshes --- bindings/py3devil1geo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/py3devil1geo.py b/bindings/py3devil1geo.py index 7388053..4102565 100644 --- a/bindings/py3devil1geo.py +++ b/bindings/py3devil1geo.py @@ -212,7 +212,7 @@ class pyMesh: i, filedata, len(filedata)): - print("failed to get mesh") + raise RuntimeError("failed to get mesh") del mh, memsize return From f4e5dfa269c9761094aea9bfa09294c5190ef9e4 Mon Sep 17 00:00:00 2001 From: surkeh Date: Thu, 17 May 2018 00:02:17 -0700 Subject: [PATCH 18/38] removed stray #! --- bindings/py3devil1pld.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bindings/py3devil1pld.py b/bindings/py3devil1pld.py index 958f8bd..bb4d54c 100644 --- a/bindings/py3devil1pld.py +++ b/bindings/py3devil1pld.py @@ -1,4 +1,3 @@ -#!/usr/bin/python3 import ctypes from __init__ import libc From 4b574f94563f5cc873b4df494403ae1436d5c075 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 11:08:58 -0700 Subject: [PATCH 19/38] Added raise RuntimeError blocks for all pyobjects in geo --- bindings/py3devil1geo.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bindings/py3devil1geo.py b/bindings/py3devil1geo.py index 4102565..fabf65d 100644 --- a/bindings/py3devil1geo.py +++ b/bindings/py3devil1geo.py @@ -145,7 +145,8 @@ class pyGeoHeader: self.cstruct = ctypes.pointer(Header()) ptrofptr = ctypes.byref(self.cstruct) if filedata: - devil1geo.getheader(ptrofptr, filedata) + if not devil1geo.getheader(ptrofptr, filedata): + raise RuntimeError("failed to get geometry file header") return def show(self): @@ -175,7 +176,8 @@ class pyMeshHeader: self.cstruct = ctypes.pointer(MeshHeader()) ptrofptr = ctypes.byref(self.cstruct) if filedata: - devil1geo.getmeshheader(ptrofptr, i, filedata) + if not devil1geo.getmeshheader(ptrofptr, i, filedata): + raise RuntimeError("failed to get mesh header #" + str(i)) return pass From 2c3aba370fc45ecf4e71086ad78f9c69a77164af Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 11:14:24 -0700 Subject: [PATCH 20/38] Corrected return value for geo's getheader --- bindings/py3devil1geo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/py3devil1geo.py b/bindings/py3devil1geo.py index fabf65d..e1bdd9e 100644 --- a/bindings/py3devil1geo.py +++ b/bindings/py3devil1geo.py @@ -112,7 +112,7 @@ class Devil1GEO_FN(ctypes.Structure): None, ctypes.POINTER(Coordinate))), ("getheader", ctypes.CFUNCTYPE( - None, + ctypes.c_bool, ctypes.POINTER(ctypes.POINTER(Header)), ctypes.c_char_p)), ("getmeshheader", ctypes.CFUNCTYPE( From 201df8d366c099cc9d45319fe52c3d3a7818ed34 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 11:26:01 -0700 Subject: [PATCH 21/38] Tested exceptions thrown --- bindings/__test__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bindings/__test__.py b/bindings/__test__.py index 3953c65..b3bf85d 100755 --- a/bindings/__test__.py +++ b/bindings/__test__.py @@ -101,6 +101,16 @@ if __name__ == "__main__": 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() From cef4720e42d2b0d21cb3a35b51c0843f44789129 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 11:35:19 -0700 Subject: [PATCH 22/38] Added exceptions for pld getheader() --- bindings/py3devil1pld.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bindings/py3devil1pld.py b/bindings/py3devil1pld.py index bb4d54c..62ed79b 100644 --- a/bindings/py3devil1pld.py +++ b/bindings/py3devil1pld.py @@ -38,7 +38,8 @@ class pyPldHeader: # Store C Struct in order to call C functions self.cstruct = PldHeader() if filedata: - devil1pld.getheader(ctypes.byref(self.cstruct), filedata) + if not devil1pld.getheader(ctypes.byref(self.cstruct), filedata): + raise RuntimeError("failed to get .pld header") self.eof = len(filedata) def show(self): From 53ec9b04748bd1e7d9e7faeb7a6e3cbbd8498059 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 11:35:43 -0700 Subject: [PATCH 23/38] Added exceptions for textures objects --- bindings/py3devil1tex.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/bindings/py3devil1tex.py b/bindings/py3devil1tex.py index 32aeb7f..6300ed1 100644 --- a/bindings/py3devil1tex.py +++ b/bindings/py3devil1tex.py @@ -82,7 +82,8 @@ del libc class pyTexturePack: def __init__(self, filedata): self.cstruct = ctypes.pointer(TexturePack()) - devil1tex.getheader(ctypes.byref(self.cstruct), filedata) + if not devil1tex.getheader(ctypes.byref(self.cstruct), filedata): + raise RuntimeError("failed to get texture pack header") return def show(self): @@ -99,7 +100,12 @@ class pyTextureBatchDescriptor: self.cstruct = ctypes.pointer(TextureBatchDescriptor()) ptrofptr = ctypes.byref(self.cstruct) if filedata: - devil1tex.getbatchdesc(ptrofptr, i, filedata, len(filedata)) + if not devil1tex.getbatchdesc( + ptrofptr, + i, + filedata, + len(filedata)): + raise RuntimeError("failed to get texturebatchdescriptor #" + str(i)) return def show(self): @@ -128,7 +134,12 @@ class pyTextureBatch: self.cstruct.batch = ctypes.cast( ctypes.create_string_buffer(memsize), ctypes.POINTER(Texture)) - devil1tex.gettextures(self.cstruct.batch, i, filedata, len(filedata)) + 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): From a2d91cd56b317f91a96d4b494762fe5e75153258 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 12:01:16 -0700 Subject: [PATCH 24/38] Handled exception where .so can not be loaded. --- bindings/__init__.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bindings/__init__.py b/bindings/__init__.py index dbbc6dc..a5d2c47 100644 --- a/bindings/__init__.py +++ b/bindings/__init__.py @@ -1,9 +1,11 @@ -import sys, ctypes +import ctypes sharedlib = './lib3ddevil1.so' -libc = ctypes.cdll.LoadLibrary(sharedlib) -if not libc: +try: + libc = ctypes.cdll.LoadLibrary(sharedlib) +except OSError as e: + print("Error loading dynamically linked library.\nOSError: " + str(e)) raise SystemExit("Couldn't load %s" % sharedlib) # Don't need these anymore -del sys, sharedlib +del sharedlib From 360de0dea55f86c52abd24c5e1e03d9a790f2a8e Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 14:00:52 -0700 Subject: [PATCH 25/38] declared function where del sharedlib is not needed anymore --- bindings/__init__.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/bindings/__init__.py b/bindings/__init__.py index a5d2c47..b49dc36 100644 --- a/bindings/__init__.py +++ b/bindings/__init__.py @@ -1,11 +1,12 @@ import ctypes -sharedlib = './lib3ddevil1.so' -try: - libc = ctypes.cdll.LoadLibrary(sharedlib) -except OSError as e: - print("Error loading dynamically linked library.\nOSError: " + str(e)) - raise SystemExit("Couldn't load %s" % sharedlib) +def loadlibc(): + sharedlib = './lib3ddevil1.so' + libc = None + try: + libc = ctypes.cdll.LoadLibrary(sharedlib) + except OSError as e: + print("Error loading dynamically linked library.\nOSError: " + str(e)) + raise SystemExit("Couldn't load %s" % sharedlib) -# Don't need these anymore -del sharedlib +libc = loadlibc() \ No newline at end of file From 911a1ad840010ea8d8f8c5e422b14ba3287c8423 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 15:07:17 -0700 Subject: [PATCH 26/38] Added return statement for fn in __init__ --- bindings/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bindings/__init__.py b/bindings/__init__.py index b49dc36..6a1ff15 100644 --- a/bindings/__init__.py +++ b/bindings/__init__.py @@ -8,5 +8,6 @@ def loadlibc(): except OSError as e: print("Error loading dynamically linked library.\nOSError: " + str(e)) raise SystemExit("Couldn't load %s" % sharedlib) + return libc libc = loadlibc() \ No newline at end of file From 9b9f0bd6ee316b78a824e3e2a7b37103cfb48b92 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 15:20:39 -0700 Subject: [PATCH 27/38] Fixed issues caused by importing from __init__ statements --- bindings/py3devil1geo.py | 8 +++++++- bindings/py3devil1pld.py | 9 ++++++++- bindings/py3devil1tex.py | 8 +++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/bindings/py3devil1geo.py b/bindings/py3devil1geo.py index e1bdd9e..5757b6a 100644 --- a/bindings/py3devil1geo.py +++ b/bindings/py3devil1geo.py @@ -1,5 +1,11 @@ import ctypes -from __init__ import libc +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 diff --git a/bindings/py3devil1pld.py b/bindings/py3devil1pld.py index 62ed79b..a16c8c5 100644 --- a/bindings/py3devil1pld.py +++ b/bindings/py3devil1pld.py @@ -1,5 +1,12 @@ import ctypes -from __init__ import libc +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 diff --git a/bindings/py3devil1tex.py b/bindings/py3devil1tex.py index 6300ed1..4c67368 100644 --- a/bindings/py3devil1tex.py +++ b/bindings/py3devil1tex.py @@ -1,5 +1,11 @@ import ctypes -from __init__ import libc +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 From e63ddfb8383a1fd753a1cb1287a9a24eb64e2bc8 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 15:28:28 -0700 Subject: [PATCH 28/38] Added library to path to search for .so --- bindings/__init__.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/bindings/__init__.py b/bindings/__init__.py index 6a1ff15..9675198 100644 --- a/bindings/__init__.py +++ b/bindings/__init__.py @@ -1,8 +1,13 @@ -import ctypes +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: @@ -10,4 +15,4 @@ def loadlibc(): raise SystemExit("Couldn't load %s" % sharedlib) return libc -libc = loadlibc() \ No newline at end of file +libc = loadlibc() From 058e395735553c0768983ee1d15edf1f13ffa00e Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 16:30:01 -0700 Subject: [PATCH 29/38] Added consistent naming for methods for geo --- bindings/__test__.py | 2 +- bindings/py3devil1geo.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bindings/__test__.py b/bindings/__test__.py index b3bf85d..df445d8 100755 --- a/bindings/__test__.py +++ b/bindings/__test__.py @@ -94,7 +94,7 @@ if __name__ == "__main__": gh = pyGeoHeader(data) gh.show() print("-------------") - print(gh.getmeshno()) + print(gh.getnummesh()) print(gh.getunknownb()) print(gh.getunknownc()) print(gh.getunknownd()) diff --git a/bindings/py3devil1geo.py b/bindings/py3devil1geo.py index 5757b6a..43c4803 100644 --- a/bindings/py3devil1geo.py +++ b/bindings/py3devil1geo.py @@ -158,7 +158,7 @@ class pyGeoHeader: def show(self): devil1geo.printheader(self.cstruct) - def getmeshno(self): + def getnummesh(self): return self.cstruct.contents.numMesh def getunknownb(self): @@ -190,7 +190,7 @@ class pyMeshHeader: def show(self): devil1geo.printmeshheader(self.cstruct) - def getbatchno(self): + def getnumbatch(self): return self.cstruct.contents.numBatch def getnumvertex(self): @@ -211,7 +211,7 @@ class pyMesh: if filedata: mh = pyMeshHeader(i, filedata) # allocate memory for the size of batch * number of batches - memsize = ctypes.sizeof(Batch) * mh.getbatchno() + memsize = ctypes.sizeof(Batch) * mh.getnumbatch() self.cstruct.b = ctypes.cast( ctypes.create_string_buffer(memsize), ctypes.POINTER(Batch)) From 6b5931c9799a619af02a5cc809c01f4081726504 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 16:34:07 -0700 Subject: [PATCH 30/38] Added consistent names for methods for textures --- bindings/py3devil1tex.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/py3devil1tex.py b/bindings/py3devil1tex.py index 4c67368..6125cdd 100644 --- a/bindings/py3devil1tex.py +++ b/bindings/py3devil1tex.py @@ -95,7 +95,7 @@ class pyTexturePack: def show(self): devil1tex.printheader(self.cstruct) - def getbatchno(self): + def getbatchnumber(self): return self.cstruct.contents.batchNumber def getfirstbatchoffset(self): @@ -123,7 +123,7 @@ class pyTextureBatchDescriptor: def gethash(self): return self.cstruct.contents.hash - def gettexno(self): + def gettexnumber(self): return self.cstruct.contents.texNumber def gettexturesize(self): From 95836e0dfa4bafa631948827acc3ddd2c83b2227 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 16:46:13 -0700 Subject: [PATCH 31/38] Fixed unupdated name --- bindings/py3devil1tex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/py3devil1tex.py b/bindings/py3devil1tex.py index 6125cdd..1e77a24 100644 --- a/bindings/py3devil1tex.py +++ b/bindings/py3devil1tex.py @@ -135,7 +135,7 @@ class pyTextureBatch: if filedata: self.cstruct.batch = None tbd = pyTextureBatchDescriptor(i, filedata) - self.amount = tbd.gettexno() + self.amount = tbd.gettexnumber() memsize = self.amount * tbd.gettexturesize() self.cstruct.batch = ctypes.cast( ctypes.create_string_buffer(memsize), From 979c5f4aaadcb3817aae840d7a9ca8e4fcec9f7a Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 16:46:45 -0700 Subject: [PATCH 32/38] Updated fn call in test --- bindings/__test__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/__test__.py b/bindings/__test__.py index df445d8..7550080 100755 --- a/bindings/__test__.py +++ b/bindings/__test__.py @@ -78,7 +78,7 @@ if __name__ == "__main__": data = f.read() txp = pyTexturePack(data) txp.show() - print(txp.getbatchno()) + print(txp.getbatchnumber()) print(txp.getfirstbatchoffset()) tbd = pyTextureBatchDescriptor(1, data) tbd.show() From e63154cd7f8cfbb940a172bd0fd48ebe3386e8d5 Mon Sep 17 00:00:00 2001 From: surkeh Date: Thu, 17 May 2018 16:58:45 -0700 Subject: [PATCH 33/38] Changed SystemExit exception to RuntimeError --- bindings/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/__init__.py b/bindings/__init__.py index 9675198..ee86a27 100644 --- a/bindings/__init__.py +++ b/bindings/__init__.py @@ -12,7 +12,7 @@ def loadlibc(): libc = ctypes.cdll.LoadLibrary(sharedlib) except OSError as e: print("Error loading dynamically linked library.\nOSError: " + str(e)) - raise SystemExit("Couldn't load %s" % sharedlib) + raise RuntimeError("Couldn't load %s" % sharedlib) return libc libc = loadlibc() From b45ab07aa5344cf2fc7e6c6f48bd83fdce23583d Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 21:54:34 -0700 Subject: [PATCH 34/38] Wrote documentation for the python interface --- docs/doc-python.txt | 242 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 docs/doc-python.txt diff --git a/docs/doc-python.txt b/docs/doc-python.txt new file mode 100644 index 0000000..53cbe15 --- /dev/null +++ b/docs/doc-python.txt @@ -0,0 +1,242 @@ + +lib3ddevil1/bindings +Python interface to C library functions of lib3ddevil1. + +This component uses ctypes thus it must access a compiled .so file (internally +a .dll for Windows). The .so may be located in the top level of the library +directory or any directory in the environment variable's path. + +Note that there are two categories of objects in each python interface. One is +derived from ctypes.Structure, and the other is a pythonic object. The former +is for internal use and requires knowledge of both python, C, and ctypes. The +latter is to be used by python users. + +Functions and Objects + class pyPldHeader + def __init__(self, filedata = None): + parameters: file data, is a single line list of data. + + This function may raise RuntimeError when it fails to initialize + based on file data. + + def show(self): + This prints the contents of the object. + + def getnumoffsets(self): + This returns the attribute numOffsets of a PldHeader. + See details of the C struct in doc-pld.txt. + + def getoffsets(self): + This returns a pythonic list of offsets. + The offsets can be accessed via list comprehensions. + + def sizeofsector(self, i): + parameter: i, an integer. + This returns the size of the i-th sector in the .pld. + + If the result is -1, then specified i is out of range. + + class PyTexturePack + def __init__(self, filedata): + parameters: file data, a single line list of data. + + This function may raise RuntimeError when it fails to initialize + based on file data. + + See details of the C struct in doc-tex.txt. + + def show(self): + This prints the contents of the object. + + def getbatchnumber(self): + This returns the attribute 'batchNumber'. + + def getfirstbatchoffset(self): + This returns the attribute 'firstBatchOffset'. + + class pyTextureBatchDescriptor: + def __init__(self, i, filedata): + parameters: i, for i-th instance of TextureBatchDescriptor. + filedata, a single line list of data. + + This function may raise RuntimeError when it fails to initialize + based on file data. + + See details of the C struct in doc-tex.txt. + + def show(self): + This prints the contents of the object. + + def getbatchidx(self): + This returns the attribute 'batchidx'. + + def gethash(self): + This returns the attribute 'hash'. + + def gettexnumber(self): + This returns the attribute 'texNumber'. + + def gettexturesize(self): + This returns the attribute 'textureSize'. + + class pyTextureBatch: + def __init__(self, i, filedata): + parameters: i, for i-th instance of TextureBatch. + file data, a single line list of data. + + This function may raise RuntimeError when it fails to initialize + based on file data. + + See details of the C struct in doc-tex.txt. + + def gettextures(self): + This returns a pythonic list of texture data. + The textures can be accessed via list comprehensions. + + class pyGeoHeader: + def __init__(self, filedata): + parameters: file data, a single line list of data. + + This function may raise RuntimeError when it fails to initialize + based on file data. + + See details of the C struct in doc-geo.txt. + + def show(self): + This prints the contents of the object. + + def getnummesh(self): + This returns the attribute 'numMesh'. + + def getunknownb(self): + This returns the attribute 'unknownNumberB'. + + def getunknownc(self): + This returns the attribute 'unknownNumberC'. + + def getunknownd(self): + This returns the attribute 'unknownNumberD'. + + def getpadding(self): + This returns the attribute 'padding'. + + def getunknownoffset(self): + This returns the attribute 'unknownOffset'. + + class pyMeshHeader: + def __init__(self, i, filedata): + + def show(self): + This prints the contents of the object. + + def getnumbatch(self): + This returns the attribute 'numBatch'. + + def getnumvertex(self): + This returns the attribute 'numVertex'. + + def getunknown(self): + This returns the attribute 'u'. + + def getoffsetbatches(self): + This returns the attribute 'offsetBatches'. + + def getflags(self): + This returns the attribute 'flags'. + + class pyMesh: + def __init__(self, i, filedata): + parameters: i, for i-th instance of Mesh. + filedata, a single line list of data. + + This function may raise RuntimeError when it fails to initialize + based on file data. + + See details of the C struct in doc-geo.txt. + + def show(self): + This prints the contents of the object. + + def getbatchdata(self): + This returns the attribute 'bd'. + It is a object without methods, and it's attributes are + conventionally accessed with the '.' operator. + + def getpositions(self): + This returns a pythonic list of 'positions'. + The positions can be accessed with list comprehensions. + + A position is a object 'Coordinate' without methods. + The attributes are x, y, and z to be accessed with the + '.' operator. + + def getnormals(self): + This returns a pythonic list of 'normals'. + The normals can be accessed with list comprehensions. + + A normal is a object 'Coordinate' without methods. + The attributes are x, y, and z to be accessed with the + '.' operator. + + def getuvs(self): + This returns a pythonic list of 'u'. + The UVs can be accessed with list comprehensions. + + A UV has two attributes, 'u' and 'v'. + + def getboneindexes(self): + This returns a pythonic list of 'bi'. + The bone indices can be accessed with list comprehensions. + + A bone index is a fixed length array of 4 elements, unsigned byte. + + def getboneweights(self): + This returns a pythonic list of 'bw'. + The bone weights can be accessed with list comprehensions. + + A bone weight is effectively an integer in python. + +Example Logic: Extract Pld's + with open("pl01.pld", "rb") as f: + data = f.read() + pld = pyPldHeader(data) + filename = "demonstrate" + i = 0 + for offset in pld.getoffsets(): + with open(filename + str(i), "wb") as fw: + end = offset + pld.sizeofsector(i) + chunk = data[offset:end] + fw.write(chunk) + i += 1 + +Example Logic: Extract Textures + from ctypes import * + with open("pl01.pld_1.txp", "rb") as f: + data = f.read() + tx = pyTextureBatch(0, data) + filename = "texture" + i = 0 + bd = pyTextureBatchDescriptor(i, data) + size = bd.gettexturesize() + for texture in tx.gettextures(): + with open(filename + str(i) + ".dds", "wb") as fw: + image = cast(texture.data, POINTER(c_ubyte * size))[0] + fw.write(image) + i += 1 + +Example Logic: Iterate through all MeshHeaders and Meshes: + with open("pl00.pld_0", "rb") as f: + # Get data to extract from. + data = f.read() + # We want to know how many meshes are in the file. + gh = pyGeoHeader(data) + # Show each MeshHeader + for i in range(0, gh.getnummesh()): + mh = pyMeshHeader(i, data) + mh.show() + # Get each Mesh + for i in range(0, gh.getnummesh()): + m = pyMesh(i, data) + m.show() + # Whatever you do with each of them is up to you. + From 52de706a96760419a6b634281d02e022ccb9d437 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 22:44:00 -0700 Subject: [PATCH 35/38] gettextures() returns list of writable byte arrays --- bindings/py3devil1tex.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/bindings/py3devil1tex.py b/bindings/py3devil1tex.py index 1e77a24..dccf093 100644 --- a/bindings/py3devil1tex.py +++ b/bindings/py3devil1tex.py @@ -136,7 +136,8 @@ class pyTextureBatch: self.cstruct.batch = None tbd = pyTextureBatchDescriptor(i, filedata) self.amount = tbd.gettexnumber() - memsize = self.amount * tbd.gettexturesize() + self.size = tbd.gettexturesize() + memsize = self.amount * self.size self.cstruct.batch = ctypes.cast( ctypes.create_string_buffer(memsize), ctypes.POINTER(Texture)) @@ -149,5 +150,12 @@ class pyTextureBatch: return def gettextures(self): - return self.cstruct.batch[:self.amount] + 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 From 549105e5367730edc991551602abf96088ee18d1 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Fri, 18 May 2018 01:48:10 -0700 Subject: [PATCH 36/38] Updated example for current version of python interface --- docs/doc-python.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/doc-python.txt b/docs/doc-python.txt index 53cbe15..0c813a0 100644 --- a/docs/doc-python.txt +++ b/docs/doc-python.txt @@ -220,8 +220,7 @@ Example Logic: Extract Textures size = bd.gettexturesize() for texture in tx.gettextures(): with open(filename + str(i) + ".dds", "wb") as fw: - image = cast(texture.data, POINTER(c_ubyte * size))[0] - fw.write(image) + fw.write(texture) i += 1 Example Logic: Iterate through all MeshHeaders and Meshes: From f34289def982afe760808daa9af06a183ddeeaaa Mon Sep 17 00:00:00 2001 From: _ <_> Date: Fri, 18 May 2018 01:58:18 -0700 Subject: [PATCH 37/38] Updated texture example to iterate through all textures. --- docs/doc-python.txt | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/doc-python.txt b/docs/doc-python.txt index 0c813a0..6324206 100644 --- a/docs/doc-python.txt +++ b/docs/doc-python.txt @@ -209,19 +209,21 @@ Example Logic: Extract Pld's fw.write(chunk) i += 1 -Example Logic: Extract Textures - from ctypes import * +Example Logic: Extract Textures from a Single Batch with open("pl01.pld_1.txp", "rb") as f: data = f.read() - tx = pyTextureBatch(0, data) - filename = "texture" - i = 0 - bd = pyTextureBatchDescriptor(i, data) - size = bd.gettexturesize() - for texture in tx.gettextures(): - with open(filename + str(i) + ".dds", "wb") as fw: - fw.write(texture) - i += 1 + tp = pyTexturePack(data) + filename = "texture" # part 1 of output file name + id = 0 # part 2 of output file name + # Iterate through all of the batches in the package. + for i in range(0, tp.getbatchnumber()): + # Get a batch. + tx = pyTextureBatch(i, data) + # Iterate through all textures in batch. + for texture in tx.gettextures(): + with open(filename + str(id) + ".dds", "wb") as fw: + fw.write(texture) + id += 1 Example Logic: Iterate through all MeshHeaders and Meshes: with open("pl00.pld_0", "rb") as f: From 27a43e5943b0f268ffd4b47516faae3086fe3627 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Fri, 18 May 2018 16:49:06 -0700 Subject: [PATCH 38/38] Removed path manipulations for single absolute path to build location of .so --- bindings/__init__.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/bindings/__init__.py b/bindings/__init__.py index ee86a27..75322a0 100644 --- a/bindings/__init__.py +++ b/bindings/__init__.py @@ -1,13 +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'] +# os.environ['PATH'] = os.path.abspath( +# os.path.join( +# os.path.dirname(__file__), "../")) \ +# + ';' \ +# + os.environ['PATH'] + # __file__ is this __init__.py + # This assumes that the repo's directory has not been modified + # and that + so = '/lib3ddevil1.so' + libdir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../")) + sharedlib = libdir + so try: libc = ctypes.cdll.LoadLibrary(sharedlib) except OSError as e: