From b6947d8f11d6a8061b9de08d377b7ed9b165c50d Mon Sep 17 00:00:00 2001 From: _ <_> Date: Sat, 21 Apr 2018 04:29:13 -0700 Subject: [PATCH 01/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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 b45ab07aa5344cf2fc7e6c6f48bd83fdce23583d Mon Sep 17 00:00:00 2001 From: _ <_> Date: Thu, 17 May 2018 21:54:34 -0700 Subject: [PATCH 12/14] 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 549105e5367730edc991551602abf96088ee18d1 Mon Sep 17 00:00:00 2001 From: _ <_> Date: Fri, 18 May 2018 01:48:10 -0700 Subject: [PATCH 13/14] 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 14/14] 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: