Merge branch 'feature/documentation' of scuti/lib3ddevil1 into python/finalize

This commit is contained in:
suhrke 2018-05-18 13:06:49 -07:00 committed by Gitea
commit 7b8f8a2e78
6 changed files with 592 additions and 2 deletions

View File

@ -2,12 +2,16 @@
A C library for handling Devil May Cry 1 HD Collection PC file formats. A C library for handling Devil May Cry 1 HD Collection PC file formats.
#### Build Demos #### Build
Run `make` 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) #### Compiler(s)
Developed and tested with the following compilers. Developed and tested with the following compilers.
* mingw-w64, GCC 6.4.0 * mingw-w64, GCC 6.4.0
* gcc version 7.1.1 20170528 * gcc version 7.1.1 20170528

132
docs/doc-geo.txt Normal file
View File

@ -0,0 +1,132 @@
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.
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);
Show a specified quantity of Coordinates.
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.
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);
}
}

23
docs/doc-overview.txt Normal file
View File

@ -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(...);

56
docs/doc-pld.txt Normal file
View File

@ -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];
...
}
...
}

243
docs/doc-python.txt Normal file
View File

@ -0,0 +1,243 @@
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 a Single Batch
with open("pl01.pld_1.txp", "rb") as f:
data = f.read()
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:
# 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.

132
docs/doc-tex.txt Normal file
View File

@ -0,0 +1,132 @@
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
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.
Example logic to interact with 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 textures there are.
}
free(t);
}
}