wdf file format

Junior Spellweaver
Joined
Jun 15, 2009
Messages
107
Reaction score
37
in case someone wants to mess with cflyff maps:
cflyff wdf file format. dont really want to start explaining. heres the code:P
Seems like it doesnt contain any filenames...

Code:
#include <stdio.h>

void decode(unsigned char *p, int h)
{
	for(int a=0;a<h;a++)
	{
		p[a]^=(unsigned char)194;
		p[a]=(p[a]<<4)|(p[a]>>4);
	}
}

int main(int argc, char* argv[])
{
	char fname[256];
	FILE *f1, *f2;
	char *p;
	int *fsizes, *startpos;
	int a,b,n,h;
	

	f1=fopen(argv[1], "rb");

	fseek(f1, 4, SEEK_SET);
	fread(&n, 1, 4, f1);	//number of files
	fsizes=new int[n];
	startpos=new int[n];
	
	fread(&a, 1, 4, f1);	//offset of file table
	fseek(f1, a, SEEK_SET);

	h=0;
	for(a=0;a<n;a++)
	{
		fread(&b, 1, 4, f1);
		fread(&startpos[a], 1, 4, f1);
		fread(&fsizes[a], 1, 4, f1);
		fread(&b, 1, 4, f1);
		h+=fsizes[a];
	}

	char *guess[12]={"DAT","dds", "wav", "lnd", "voq", "tga", "bmp", "sp", "jpg", "rt", "mp3", "LND"};
	
	for(a=0;a<n;a++)
	{
		fseek(f1, startpos[a], SEEK_SET);
		fread(&b, 1, 4, f1);
		switch(b)
		{
			case 0x20534444: b=1; break;	//DDS
			case 0x46464952: b=2; break;	//WAVE
			case 0xd736a713: b=4; break;	//voq
			case 0x00020000: b=5; break;	//tga
			case 0x65636152: b=9; break;	//
			case 0xe0ffd8ff: b=8; break;	//
			default:
				if((b&0xffff)==0x4d42)b=6;
				else if((b&0xffff)==0x5053)b=7;
				else if((b&0xffff)==0x4449)b=10;
				else if((b&0xffff)==0xfbff)b=10;
				else if((b&0xff)==2)b=3;
				else if((b&0xff)==1)b=11;	//sometimes its lnd, sometimes its not...
				else
				{
					b=0;
//					printf("unknown type %d %c\n", (int)ch, ch);
				}
		};
		
		sprintf(fname, "F%d.%s", a, guess[b]);
		f2=fopen(fname, "w+b");

		p=new char[fsizes[a]];
		fseek(f1, startpos[a], SEEK_SET);
		fread(p, 1, fsizes[a], f1);
		if(b==4)decode((unsigned char*)p, fsizes[a]);
		fwrite(p, 1, fsizes[a], f2);
		delete[] p;
		fclose(f2);
	}

	fclose(f1);
	delete[] fsizes;
	delete[] startpos;
	printf("%d files\n%d bytes\n", n, h);

	return 0;
};

as for the lnd files, they are preatty similar.
the first 3 integers (version, x, y) are skipped, only 1 character is there, wich is constant 2.
the water-heigth table's size is 0x500 instead of 0x300
couldnt find the texture id-s, and theres no model or sfx data at the end of the file.

EDIT:
- better file extension guessing
- decodes voq files
 
Last edited:
it apears to be coded in C++

il see if I can figure out what to do with it

unfortuneatly it seams it doesnt not think to find wld/Dyo/rgn/o3d

oh well its still a step forward
 
I made some changes to it, you don't have to say "It's noob coded", because I AM pretty noob in C++.

-More checking.
-Able to create seperate directories for each file type. (-s)
-Able to see every file being extracted. (-v)
-WD1 files get _wd1 at the end of their foldername.
-You can disable VOQ decoding. (-n)

Code:
#include <stdio.h>
#include <direct.h>
#include <iostream>
#include <string>
#include <io.h>
#include <sys/stat.h>

using namespace std;

void decode(unsigned char *p, int h)
{
	for(int a=0;a<h;a++)
	{
		p[a]^=(unsigned char)194;
		p[a]=(p[a]<<4)|(p[a]>>4);
	}
}

int direxists (string directory)
{
	if (_access( directory.c_str(), 0) == 0 )
    {
        struct stat status;
        stat(directory.c_str(), &status);

        if (status.st_mode & S_IFDIR)
        {
            return 1; //directory exists
        }
        else
        {
            return 2; //directory is a file
        }
    }
    else
    {
        return 0; //directory doesn't exist
    }
}

int main(int argc, char* argv[])
{
	int filegiven = 0;
	int sep = 0;
	int wd1 = 0;
	int decvoq = 1;
	int v = 0;
	for (int i = 0; i < argc; i++)
	{
		if (strstr(argv[i], "-s"))
		{
			sep = 1;
		}
		if (strstr(argv[i], "-n"))
		{
			decvoq = 0;
		}
		if (strstr(argv[i], "-v"))
		{
			v = 1;
		}
		if (strstr(argv[i], ".wdf"))
		{
			filegiven = 1;
		}
		else if (strstr(argv[i], ".wd1"))
		{
			filegiven = 1;
			wd1 = 1;
		}
		if (strstr(argv[i], "-help"))
		{
			cout << "Usage: wdfextract <WDFFile> [-v] [-s] [-help]" << "\n";
			cout << "  <WDFFile>" << "\t\t" << "Path to WDF/WD1 file" << "\n";
			cout << "  -v" << "\t\t\t" << "More verbose output" << "\n";
			cout << "  -s" << "\t\t\t" << "Make seperate folders for each filetype" << "\n";
			cout << "  -help" << "\t\t\t" << "Show this message" << "\n";
			cout << "  -n" << "\t\t\t" << "Disable VOQ decoding" << "\n";
			return 0;
		}
	}
	if (filegiven == 0 || argc <= 1)
	{
			cout << "No WDF/WD1 file specified!\n\n";
			cout << "Usage: wdfextract <WDFFile> [-v] [-s] [-help]" << "\n";
			cout << "  <WDFFile>" << "\t\t" << "Path to WDF/WD1 file" << "\n";
			cout << "  -v" << "\t\t\t" << "More verbose output" << "\n";
			cout << "  -s" << "\t\t\t" << "Make seperate folders for each filetype" << "\n";
			cout << "  -help" << "\t\t\t" << "Show this message" << "\n";
			cout << "  -n" << "\t\t\t" << "Disable VOQ decoding" << "\n";
			return 1;
	}
	

	char fname[256];
	FILE *f1, *f2;
	char *p;
	int *fsizes, *startpos;
	int a,b,n,h;

	string dir = ".\\";

	dir += argv[1];
	dir.replace(dir.size() - 4,4,"");
	if (wd1 == 1)
	{
		dir = dir + "_wd1";
	}

	const char* cdir = dir.c_str();

	if (direxists(cdir))
	{
		_rmdir(cdir);
	}

	_mkdir(cdir);
	_chdir(cdir);

	string file = "..\\";
	file += argv[1];

	const char* cfile = file.c_str();

	fopen_s(&f1, cfile, "rb");

	fseek(f1, 4, SEEK_SET);
	fread(&n, 1, 4, f1);	//number of files
	fsizes=new int[n];
	startpos=new int[n];
	
	fread(&a, 1, 4, f1);	//offset of file table
	fseek(f1, a, SEEK_SET);

	h=0;
	for(a=0;a<n;a++)
	{
		fread(&b, 1, 4, f1);
		fread(&startpos[a], 1, 4, f1);
		fread(&fsizes[a], 1, 4, f1);
		fread(&b, 1, 4, f1);
		h+=fsizes[a];
	}

	char *guess[12]={"DAT","dds", "wav", "lnd", "voq", "tga", "bmp", "sp", "jpg", "rt", "mp3", "LND"};
	int aguess[12]={0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //only needed when sep == 1

	cout << "\n";

	for(a=0;a<n;a++)
	{
		if (sep == 1 && a != 0)
		{
			_chdir("..\\");
		}

		fseek(f1, startpos[a], SEEK_SET);
		fread(&b, 1, 4, f1);
		switch(b)
		{
			case 0x20534444: b=1; break;			//DDS
			case 0x46464952: b=2; break;			//WAVE
			case 0xd736a713: b=4; break;			//VOQ
			case 0x00020000: b=5; break;			//TGA
			case 0x65636152: b=9; break;			//RT
			case 0xe0ffd8ff: b=8; break;			//JPG
			default:
				if((b&0xffff)==0x4d42)b=6;			//BMP
				else if((b&0xffff)==0x5053)b=7;		//SP
				else if((b&0xffff)==0x4449)b=10;	//MP3
				else if((b&0xffff)==0xfbff)b=10;	//MP3
				else if((b&0xff)==2)b=3;			//LND
				else if((b&0xff)==1)b=11;			//sometimes its LND, sometimes its not...
				else
				{
					b=0;
					if (v == 1) printf("unknown type %d %c\n", (int)b, b);
				}
		};

		if (sep == 1)
		{
			aguess[b] = aguess[b] + 1;
			sprintf_s(fname, "F%d.%s", aguess[b], guess[b]);
		}
		else
		{
			sprintf_s(fname, "F%d.%s", a, guess[b]);
		}


		if (v == 1)
		{
			cout << "Extracting: " << fname << "\n";
		}

		if (direxists(guess[b]) && sep == 1)
		{
			_rmdir(guess[b]);
		}

		if (sep == 1)
		{
			_mkdir(guess[b]);
			_chdir(guess[b]);
		}

		fopen_s(&f2, fname, "w+b");
		p=new char[fsizes[a]];
		fseek(f1, startpos[a], SEEK_SET);
		fread(p, 1, fsizes[a], f1);
		if (decvoq == 1)
		{
			if(b==4)decode((unsigned char*)p, fsizes[a]);
		}
		fwrite(p, 1, fsizes[a], f2);
		delete[] p;
		fclose(f2);
	}

	fclose(f1);
	delete[] fsizes;
	delete[] startpos;
	printf("%d files (%d bytes) extracted!", n, h);

	return 0;
}
 
Last edited:
I made some changes to it, you don't have to say "It's noob coded", because I AM pretty noob in C++.

-More checking.
-Able to create seperate directories for each file type. (-s)
-Able to see every file being extracted. (-v)
-WD1 files get _wd1 at the end of their name.
-You can disable VOQ decoding. (-n)

Code:
#include <stdio.h>
#include <direct.h>
#include <iostream>
#include <string>
#include <io.h>
#include <sys/stat.h>

using namespace std;

void decode(unsigned char *p, int h)
{
    for(int a=0;a<h;a++)
    {
        p[a]^=(unsigned char)194;
        p[a]=(p[a]<<4)|(p[a]>>4);
    }
}

int direxists (string directory)
{
    if (_access( directory.c_str(), 0) == 0 )
    {
        struct stat status;
        stat(directory.c_str(), &status);

        if (status.st_mode & S_IFDIR)
        {
            return 1; //directory exists
        }
        else
        {
            return 2; //directory is a file
        }
    }
    else
    {
        return 0; //directory doesn't exist
    }
}

int main(int argc, char* argv[])
{
    int filegiven = 0;
    int sep = 0;
    int wd1 = 0;
    int decvoq = 1;
    int v = 0;
    for (int i = 0; i < argc; i++)
    {
        if (strstr(argv[i], "-s"))
        {
            sep = 1;
        }
        if (strstr(argv[i], "-n"))
        {
            decvoq = 0;
        }
        if (strstr(argv[i], "-v"))
        {
            v = 1;
        }
        if (strstr(argv[i], ".wdf"))
        {
            filegiven = 1;
        }
        else if (strstr(argv[i], ".wd1"))
        {
            filegiven = 1;
            wd1 = 1;
        }
        if (strstr(argv[i], "-help"))
        {
            cout << "Usage: wdfextract <WDFFile> [-v] [-s] [-help]" << "\n";
            cout << "  <WDFFile>" << "\t\t" << "Path to WDF/WD1 file" << "\n";
            cout << "  -v" << "\t\t\t" << "More verbose output" << "\n";
            cout << "  -s" << "\t\t\t" << "Make seperate folders for each filetype" << "\n";
            cout << "  -help" << "\t\t\t" << "Show this message" << "\n";
            cout << "  -n" << "\t\t\t" << "Disable VOQ decoding" << "\n";
            return 0;
        }
    }
    if (filegiven == 0 || argc <= 1)
    {
            cout << "No WDF/WD1 file specified!\n\n";
            cout << "Usage: wdfextract <WDFFile> [-v] [-s] [-help]" << "\n";
            cout << "  <WDFFile>" << "\t\t" << "Path to WDF/WD1 file" << "\n";
            cout << "  -v" << "\t\t\t" << "More verbose output" << "\n";
            cout << "  -s" << "\t\t\t" << "Make seperate folders for each filetype" << "\n";
            cout << "  -help" << "\t\t\t" << "Show this message" << "\n";
            cout << "  -n" << "\t\t\t" << "Disable VOQ decoding" << "\n";
            return 1;
    }
    

    char fname[256];
    FILE *f1, *f2;
    char *p;
    int *fsizes, *startpos;
    int a,b,n,h;

    string dir = ".\\";

    dir += argv[1];
    dir.replace(dir.size() - 4,4,"");
    if (wd1 == 1)
    {
        dir = dir + "_wd1";
    }

    const char* cdir = dir.c_str();

    if (direxists(cdir))
    {
        _rmdir(cdir);
    }

    _mkdir(cdir);
    _chdir(cdir);

    string file = "..\\";
    file += argv[1];

    const char* cfile = file.c_str();

    fopen_s(&f1, cfile, "rb");

    fseek(f1, 4, SEEK_SET);
    fread(&n, 1, 4, f1);    //number of files
    fsizes=new int[n];
    startpos=new int[n];
    
    fread(&a, 1, 4, f1);    //offset of file table
    fseek(f1, a, SEEK_SET);

    h=0;
    for(a=0;a<n;a++)
    {
        fread(&b, 1, 4, f1);
        fread(&startpos[a], 1, 4, f1);
        fread(&fsizes[a], 1, 4, f1);
        fread(&b, 1, 4, f1);
        h+=fsizes[a];
    }

    char *guess[12]={"DAT","dds", "wav", "lnd", "voq", "tga", "bmp", "sp", "jpg", "rt", "mp3", "LND"};
    int aguess[12]={0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //only needed when sep == 1

    cout << "\n";

    for(a=0;a<n;a++)
    {
        if (sep == 1 && a != 0)
        {
            _chdir("..\\");
        }

        fseek(f1, startpos[a], SEEK_SET);
        fread(&b, 1, 4, f1);
        switch(b)
        {
            case 0x20534444: b=1; break;            //DDS
            case 0x46464952: b=2; break;            //WAVE
            case 0xd736a713: b=4; break;            //VOQ
            case 0x00020000: b=5; break;            //TGA
            case 0x65636152: b=9; break;            //RT
            case 0xe0ffd8ff: b=8; break;            //JPG
            default:
                if((b&0xffff)==0x4d42)b=6;            //BMP
                else if((b&0xffff)==0x5053)b=7;        //SP
                else if((b&0xffff)==0x4449)b=10;    //MP3
                else if((b&0xffff)==0xfbff)b=10;    //MP3
                else if((b&0xff)==2)b=3;            //LND
                else if((b&0xff)==1)b=11;            //sometimes its LND, sometimes its not...
                else
                {
                    b=0;
                    if (v == 1) printf("unknown type %d %c\n", (int)b, b);
                }
        };

        if (sep == 1)
        {
            aguess[b] = aguess[b] + 1;
            sprintf_s(fname, "F%d.%s", aguess[b], guess[b]);
        }
        else
        {
            sprintf_s(fname, "F%d.%s", a, guess[b]);
        }


        if (v == 1)
        {
            cout << "Extracting: " << fname << "\n";
        }

        if (direxists(guess[b]) && sep == 1)
        {
            _rmdir(guess[b]);
        }

        if (sep == 1)
        {
            _mkdir(guess[b]);
            _chdir(guess[b]);
        }

        fopen_s(&f2, fname, "w+b");
        p=new char[fsizes[a]];
        fseek(f1, startpos[a], SEEK_SET);
        fread(p, 1, fsizes[a], f1);
        if (decvoq == 1)
        {
            if(b==4)decode((unsigned char*)p, fsizes[a]);
        }
        fwrite(p, 1, fsizes[a], f2);
        delete[] p;
        fclose(f2);
    }

    fclose(f1);
    delete[] fsizes;
    delete[] startpos;
    printf("%d files (%d bytes) extracted!", n, h);

    return 0;
}
Holy **** another actual programmer.
+1
 
Back