//|=============================================|
//| G3d Extractor "g3dEx.exe" |
//| (C) Matthew Leonard 2003 |
//| |
//| [g3dEx.cpp] |
//|=============================================|
/*
If you modify this source code and distribute the binary the source code also must be included as well as all original copyright notices.
CONTACT INFO
To mail me please use lenny@bwgarage.co.uk
I can also be found on these message boards: http://boards.bwgame.com as lenny_la9
*/
#include <iostream.h>
#include <fstream.h>
#include <direct.h>
#include <string.h>
#include <stdlib.h>
void createDirectory(char *dirName);
int main (void)
{
//make directorys to save textures and meshes too
createDirectory("\\textures");
createDirectory("\\meshes");
//file variables
long currentTexture;
long textureTotal = 0;
long fileSize;
char *fileData;
char ddsHeader []= {'D', 'D', 'S', ' '}; //in the g3d file these 4 bytes indicate the filesize, however in a DDS file the first 4 bytes need to be "DDS ".
fstream fileIn;
fstream fileOut;
fstream fileHeader;
fileIn.open("AllMeshes.g3d", ios::in | ios::binary);
if(fileIn.is_open ())
{
//===============
// High-res textures are first so we extract them
//===============
fileIn.seekg (48, ios::cur); //skip past all the file header info
cout << "Extracting high resolution textures.." << endl;
do
{
fileIn.read((char *) ¤tTexture, 4); // find out the current texture number
if (textureTotal < currentTexture)
textureTotal = currentTexture;
fileIn.seekg (4, ios::cur);
fileIn.read((char *) &fileSize, 4); //read in the texture size
// fileSize -=4;
fileData = new char [fileSize+1]; //dimension memory to hold the texture data
fileIn.read((char *) &fileData[0], sizeof(char) * fileSize);
fileData[fileSize] = '\0';
// ===== Find output dir/ name =====
char chrTex[4]; //hold the texture number as char
itoa(currentTexture, chrTex, 10);
char textureFile[256] = "textures\\";
strcat(textureFile, chrTex);
strcat(textureFile, ".dds");
fileOut.open (textureFile, ios::out | ios::binary);
if (fileOut.is_open ())
{
fileOut.write ((char *) &ddsHeader[0], sizeof(char) * 4);
fileOut.write ((char *) &fileData[0], sizeof(char) * (fileSize-4));
}
delete [] fileData;
fileIn.seekg (36, ios::cur);
fileOut.close ();
} while (currentTexture != 1);
cout << "Completed\n\nExtracting l3d meshes" << endl;
//===============
// Mesh offsets come now, then the actual l3d data.
//===============
//Before doing anything else we read the AllMeshes.h into memory and sort through it to get the names of all meshes.
fileIn.seekg (4136, ios::cur);
long numMeshes;
long *meshOffset;
long currentOffset=0;
long meshInfoOffset;
char l3dHeader[3];
int l3dLength;
fileIn.read((char *) &numMeshes, 4); //read in the texture size
meshInfoOffset = fileIn.tellg();
meshInfoOffset -=8;
meshOffset = new long [numMeshes]; //dimension memory to hold mesh offsets
for (int meshRun = 0; meshRun < numMeshes; meshRun++)
{
fileIn.read((char *) &meshOffset[meshRun], 4); //read in the texture size
}
fileHeader.open("standardmesh.txt", ios::in);
if (fileHeader.is_open ())
{
char meshName[255];
int mshCount = 0;
char meshNumber[255];
fileHeader.getline (meshNumber ,100);
//now read in the actual l3d data
for (meshRun = 0; (meshRun) < numMeshes; meshRun++)
{
//dps tuff for file header name
mshCount ++;
fileHeader.getline (meshName ,100);
//fileHeader >> meshName;
//cout << "mesh" << mshCount << ": " << meshName << "\n";
currentOffset = meshInfoOffset + meshOffset[meshRun];
fileIn.read((char *) &l3dHeader[0], sizeof(char) * 4);
if (l3dHeader[0] != 'L')
if (l3dHeader[1] != '3')
if (l3dHeader[2] != 'D')
if (l3dHeader[3] != '0')
{
cout << "ERROR! Could not find l3d header information.\n";
return 0;
}
//fileIn.seekg(currentOffset, ios::beg);
fileIn.seekg(4, ios::cur); //move forward 4 bytes to get l3d size.
fileIn.read((char *) &l3dLength, 4);
fileData = new char [l3dLength+1]; //dimension memory to hold the l3d data
fileIn.seekg(currentOffset, ios::beg); //now we return to the beginning of the l3d file (move back 8 bytes).
fileIn.read((char *) &fileData[0], sizeof(char) * l3dLength);
// ===== Find output dir/ name =====
char l3dFile[256] = "meshes\\";
strcat(l3dFile, meshName);
strcat(l3dFile, ".l3d");
fileOut.open (l3dFile, ios::out | ios::binary);
if (fileOut.is_open ())
fileOut.write ((char *) &fileData[0], sizeof(char) * l3dLength);
delete [] fileData;
fileOut.close ();
}
}
fileHeader.close ();
// currentOffset += (l3dLength + l3dLength);
// fileIn.seekg(currentOffset, ios::beg);
//===============
// Before finishing, extract the low res textures
//===============
cout << "Completed\n\nExtracting low resolution ('-low') textures.." << endl;
//fileIn.seekg (3, ios::cur);
char lowTexTag[3];
currentTexture = textureTotal;
do
{
fileIn.read((char *) &lowTexTag, 4); // find out the current texture number
if (lowTexTag[0] != 'L')
if (lowTexTag[1] != 'O')
if (lowTexTag[2] != 'W')
{
cout << "invalid low textures\n";
break;
}
fileIn.seekg (44, ios::cur);
fileIn.read((char *) &fileSize, 4); //read in the texture size
fileData = new char [fileSize+1]; //dimension memory to hold the texture data
fileIn.read((char *) &fileData[0], sizeof(char) * fileSize);
fileData[fileSize] = '\0';
// ===== Find output dir/ name =====
char chrTex[4]; //hold the texture number as char
itoa(currentTexture, chrTex, 10);
char textureFile[256] = "textures\\";
strcat(chrTex, "-low");
strcat(textureFile, chrTex);
strcat(textureFile, ".dds");
fileOut.open (textureFile, ios::out | ios::binary);
if (fileOut.is_open ())
{
fileOut.write ((char *) &ddsHeader[0], sizeof(char) * 4);
fileOut.write ((char *) &fileData[0], sizeof(char) * (fileSize-4));
}
delete [] fileData;
//fileIn.seekg (44, ios::cur);
fileOut.close ();
currentTexture --;
//currentOffset -= 4;
currentOffset = fileIn.tellg();
currentOffset -=4;
fileIn.seekg(currentOffset, ios::beg);
} while (currentTexture != 0);
cout << "Completed.\n\n";
}
else
{
cout << "could not open G3D file"; //if we cant open the file, give the user an error message.
return 0;
}
cout << "The contents of the G3D file have been successfulyl extracted to the \\meshes and \\textures folders.\n\n";
// clean up
fileIn.close ();
return 0;
}
void createDirectory(char *dirName)
{
char curDir[255];
char finalDir[255];
getcwd(curDir, 255); //get working directory
strcpy(finalDir, curDir);
strcat(finalDir, dirName);
mkdir(finalDir); //make the new directory
}