All pastes #352915 Raw Edit

Something

public cpp v1 · immutable
·published 2007-02-13 02:13 UTC
rendered paste body
#include <iostream>// Windows only probably#include <direct.h>#include "DAT1.h"using namespace std;DAT1::DAT1(){	directoryCount = 0;	unknown1 = 0;	unknown2 = 0;	unknown3 = 0;	directoryBlockSize = 0;	directories = NULL;}DAT1::~DAT1(){	if (directories != NULL)	{		for (unsigned int i = 0; i < directoryCount; i++)		{			delete[] directories[i].files;		}	}		DAT1Stream.close();}void DAT1::loadDAT1File(string filename){	DAT1Stream.open(filename.c_str(),ios::in | ios::binary);	// Read the unknown values out of the header	DAT1Stream.read((char *)&directoryCount,sizeof(directoryCount));	DAT1Stream.read((char *)&unknown1,sizeof(unknown1));		DAT1Stream.read((char *)&unknown2,sizeof(unknown2));	// Should be 0, not putting in a die check unless usefulness is shown	DAT1Stream.read((char *)&unknown3,sizeof(unknown3));	// Swap out endian order (should check endian order perhaps)	directoryCount = (directoryCount>>24) | 		((directoryCount<<8) & 0x00FF0000) |        ((directoryCount>>8) & 0x0000FF00) |        (directoryCount<<24);	unknown1 = (unknown1>>24) | 		((unknown1<<8) & 0x00FF0000) |        ((unknown1>>8) & 0x0000FF00) |        (unknown1<<24);;;	unknown2 = (unknown2>>24) | 		((unknown2<<8) & 0x00FF0000) |        ((unknown2>>8) & 0x0000FF00) |        (unknown2<<24);	unknown3 = (unknown3>>24) | 		((unknown3<<8) & 0x00FF0000) |        ((unknown3>>8) & 0x0000FF00) |        (unknown3<<24);	// Allocate an array of Directories	directories = new DAT1Directory[directoryCount];		// Now we're at the directory name blocks	// There is a single byte containing each	// Directory name length	char ctmpstr[256]; // Max possible chars per directory	for (unsigned int i=0; i < directoryCount;i++)	{		// Don't need to manually NULL terminate C string		memset(ctmpstr,0,sizeof(ctmpstr));		DAT1Stream.read((char *)&directories[i].size,sizeof(directories[i].size));		DAT1Stream.read((char *)&ctmpstr,directories[i].size);		directories[i].name = ctmpstr;	}	for (unsigned int i=0; i < directoryCount; i++)	{		// Get the directory header		DAT1Stream.read((char *)&directories[i].numFiles,sizeof(directories[i].numFiles));		DAT1Stream.read((char *)&directories[i].unknown1,sizeof(directories[i].unknown1));		DAT1Stream.read((char *)&directories[i].unknown2,sizeof(directories[i].unknown2));		DAT1Stream.read((char *)&directories[i].unknown3,sizeof(directories[i].unknown3));		// Fix endianness (should be conditional for big endian systems)		directories[i].numFiles = (directories[i].numFiles>>24) | 		((directories[i].numFiles<<8) & 0x00FF0000) |        ((directories[i].numFiles>>8) & 0x0000FF00) |        (directories[i].numFiles<<24);		directories[i].unknown1 = (directories[i].unknown1>>24) | 		((directories[i].unknown1<<8) & 0x00FF0000) |        ((directories[i].unknown1>>8) & 0x0000FF00) |        (directories[i].unknown1<<24);		directories[i].unknown2 = (directories[i].unknown2>>24) | 		((directories[i].unknown2<<8) & 0x00FF0000) |        ((directories[i].unknown2>>8) & 0x0000FF00) |        (directories[i].unknown2<<24);		directories[i].unknown3 = (directories[i].unknown3>>24) | 		((directories[i].unknown3<<8) & 0x00FF0000) |        ((directories[i].unknown3>>8) & 0x0000FF00) |        (directories[i].unknown3<<24);		// Allocate enough file classes for each file		directories[i].files = new DAT1File[directories[i].numFiles];		// Now enumerate the files in the directory		for (unsigned int j = 0; j < directories[i].numFiles; j++)		{			// Don't need to manually NULL terminate C string			memset(ctmpstr,0,sizeof(ctmpstr));			// Get filename length and filename, store it in tmp str			DAT1Stream.read((char *)&directories[i].files[j].size,sizeof(directories[i].files[j].size));			DAT1Stream.read((char *)&ctmpstr,directories[i].files[j].size);						// Strick it in the class			directories[i].files[j].filename = ctmpstr;			// Escape the name									while ((pos = directories[i].name.find("\\",oldpos)) != string::npos)			{				static string::size_type pos    = 0;				static 				cout << "pos = " << pos << " oldpos = " << oldpos << " Substring = " << directories[i].name.substr(pos,(pos-oldpos)) << endl;				oldpos = pos;				oldpos += 2;				cout << "oldpos = " << oldpos << endl;			}						/*				while (((pos = directories[i].name.find("\\",oldpos)) != string::npos))			{				cout << "pos = " << pos << " oldpos = " << oldpos << " Substring = " << directories[i].name.substr(pos,(pos-oldpos)) << endl;				directories[i].escapedName.append(directories[i].name.substr(pos,(pos-oldpos)));				directories[i].escapedName.append("\\");				oldpos = pos;				oldpos += 1;			}*/			// Get the integers			DAT1Stream.read((char *)&directories[i].files[j].attributes,sizeof(directories[i].files[j].attributes));			DAT1Stream.read((char *)&directories[i].files[j].offset,sizeof(directories[i].files[j].offset));			DAT1Stream.read((char *)&directories[i].files[j].uncompressedSize,sizeof(directories[i].files[j].uncompressedSize));			DAT1Stream.read((char *)&directories[i].files[j].compressedSize,sizeof(directories[i].files[j].compressedSize));			// Swap endian order			directories[i].files[j].attributes = (directories[i].files[j].attributes>>24) | 		                           ((directories[i].files[j].attributes<<8) & 0x00FF0000) |                                   ((directories[i].files[j].attributes>>8) & 0x0000FF00) |                                   (directories[i].files[j].attributes<<24);			directories[i].files[j].offset = (directories[i].files[j].offset>>24) | 		                           ((directories[i].files[j].offset<<8) & 0x00FF0000) |                                   ((directories[i].files[j].offset>>8) & 0x0000FF00) |                                   (directories[i].files[j].offset<<24);			directories[i].files[j].uncompressedSize = (directories[i].files[j].uncompressedSize>>24) | 		                           ((directories[i].files[j].uncompressedSize<<8) & 0x00FF0000) |                                   ((directories[i].files[j].uncompressedSize>>8) & 0x0000FF00) |                                   (directories[i].files[j].uncompressedSize<<24);;			directories[i].files[j].compressedSize = (directories[i].files[j].compressedSize>>24) | 		                           ((directories[i].files[j].compressedSize<<8) & 0x00FF0000) |                                   ((directories[i].files[j].compressedSize>>8) & 0x0000FF00) |                                   (directories[i].files[j].compressedSize<<24);;		}	}	return;}void DAT1::decompressFile(string inFile, string outFile){	ofstream fout(outFile.c_str(),ios::out | ios::binary);	DAT1File *datFile = NULL;	for (unsigned int i=0; i < directoryCount; i++)	{		for (unsigned int j=0; j < directories[i].numFiles; j++)		{			if (directories[i].files[j].filename == inFile)			{				datFile = &directories[i].files[j];				break;			}		}	}	if (datFile == NULL)	{		cout << "Could not find file " << inFile  << endl;		return;	} 	DAT1Stream.seekg(datFile->offset);	int filesize = (datFile->compressedSize) ? datFile->compressedSize : datFile->uncompressedSize;	//printf("Offset: 0x%0x Size: %0d\n",datFile->offset,filesize);	if (!datFile->compressedSize)	{		char *buf = new char[filesize];		DAT1Stream.read((char *)buf,filesize);		fout.write((char *)buf, filesize);		fout.close();		return;	}	// We need to decompress the LZSS compression	int windowSize = 4096;	char *dict = new char[4096];	// Fill dictionary with spaces	memset(dict,'\0x20',4096);		int offset = 0;	unsigned int O = 0;	unsigned char L = 0;	unsigned char FLAGS = 0;	unsigned char byte = 0;	short N = 0;	// 0. Set dictionary offset to D-18	offset = windowSize - 18;		// 1. If at the end of file, exit.	while(filesize > 0)	{		// 2. Read N (2 bytes == word) from input.		// The absolute value of N is how many bytes of data to read (if N=0, exit)		DAT1Stream.read((char *)&N,sizeof(N));		filesize-=sizeof(N);		// Flip endianness		N = (N>>8) | (N<<8);		if (N == 0)			return;		// 2.1. If N < 0, read the absolute value 		// of N bytes from input and write to output (do not put into dictionary). Go to 1.		if (N < 0)		{			char *output = new char[N*-1];			DAT1Stream.read((char *)output,N*-1);			filesize -= N*-1;			fout.write((char *)output,N*-1);			continue;		}		// 2.2. If N > 0, clear dictionary, repeat below until N bytes have been read from input,		// and then go to 1.		if (N > 0)		{			// Clear dictionary (with spaces, not null)			memset(dict,'\0x20',4096);			while (N > 0)			{				if (filesize == 0)					break;								// 2.2.1. Read FLAGS (1 byte) from input. Repeat below 8 times.				DAT1Stream.read((char *)&FLAGS,sizeof(FLAGS));				filesize -= sizeof(FLAGS);				N-=sizeof(FLAGS);				// Repeat 8 times				for (int i=0;i<8 && N > 0;i++,FLAGS = FLAGS>>1)				{					// 2.2.1.1. If FLAGS *is not* a modulus of 2 (& 1 != 0), 					//read 1 byte from input, write to output, then go to 2.2.1.3.					if ((FLAGS & 1) != 0)					{						DAT1Stream.read((char *)&byte, sizeof(byte));						filesize--;						N--;						fout << byte;												dict[offset] = byte;						if (offset == (windowSize-1))							offset = 0;						else							offset++;					} else { // 2.2.1.2. If FLAGS *is* a modulus of 2 (& 1 == 0)						O = L = 0;						// 2.2.1.2.1. Read O (1 byte) and L (1 byte) from input.						DAT1Stream.read((char *)&O,1);						DAT1Stream.read((char *)&L,1);						filesize -= 2;						N-=2;						// 2.2.1.2.2. Take away the High-nibble (first 4 bits) from L and prepend it to O;						O = (unsigned int)((((unsigned int)L>>4)<<8) | (unsigned int)O);						L <<= 4;						L >>= 4;						//fout << endl << "O = " << (int)O << " L = " << (int)L << " offset[" << (int)O << "] = \"" << (char)dict[O] << "\" offset = " << (int)offset << endl;						for (int m=0;m<(L+3);m++)						{							dict[offset] = dict[O];							if (offset == (windowSize-1))								offset = 0;							else								offset++;							fout << dict[O];														if (O == (windowSize-1))								O = 0;							else 								O++;						}					}				}			}				}	}	fout.close();}void DAT1::decompress(){	ofstream fout;	int filesize = 0;	for (unsigned int i=0; i < directoryCount; i++)	{		if (directories[i].name != ".")		{			cout << "Creating: " << directories[i].escapedName << endl;									_mkdir(directories[i].escapedName.c_str());		}		for (unsigned int j=0; j < directories[i].numFiles; j++)		{				cout << "Extracting " << directories[i].escapedName + "\\" + directories[i].files[j].filename << endl;			decompressFile(directories[i].files[j].filename,"DATA\\" + directories[i].files[j].filename);			/*			char *buf = new char[filesize];			DAT1Stream.read((char *)buf,filesize);			fout.write((char *)buf, filesize);			fout.close();						delete[] buf;*/		}	}}void DAT1::printDAT1Info(string inFilename){	ofstream Boo(inFilename.c_str(),ios::out);	Boo << "[Header Information]" << endl;	Boo << "Directory Count: " << directoryCount << endl;	Boo << "Unknown #1: " << unknown1 << endl;	Boo << "Unknown #2: " << unknown2 << endl;	Boo << "Unknown #3: " << unknown3 << endl;	Boo << "Directory Block Size: " << directoryBlockSize << endl;	Boo << endl;	Boo << "[Directories]" << endl;	for (unsigned int i=0; i < directoryCount; i++)	{		Boo << "Directory Name: " << directories[i].name << endl;		Boo << "Number of files: " << directories[i].numFiles << endl;		for (unsigned int j=0; j < directories[i].numFiles; j++)		{			Boo << "File Name: " << directories[i].files[j].filename << endl;		}	}	Boo.close();}