I'm having trouble correcting the file and table offsets in this class I've written. The class is for a DRS file. This file has a header, then a group of table headers (which contain the table entry offsets), then the table entries (which contain the file offsets), and lastly actual files contained within the DRS file. The program that uses this class doesn't use these offsets, but they are needed for the game that uses them.
Code:
/* clsDrs.h */
#include "Globals.h"
#ifndef clsDrs_h
#define clsDrs_h
class clsDrsTableEntry
{
public:
long FileID;
long FileOffset;
long FileSize;
clsDrsTableEntry();
};
class clsDrsTableHeader
{
public:
char FileType;
char ReverseExtension[3];
long TableOffset;
long FileCount;
clsDrsTableHeader();
};
class clsDrs
{
public:
/* Drs Variables */
char Copyright[41]; // These three arrays are one larger than actual size in file (no null character in file)
char Version[5];
char FileType[13];
unsigned long TableCount;
long FirstFileOffset;
vector< clsDrsTableHeader > TableHeaders;
vector< vector< clsDrsTableEntry > > TableEntries;
vector< vector< vector< char > > > TableFiles;
/* Handling Variables */
bool Loaded;
clsDrs();
void AddFile(unsigned int Table, int Index, string FileName, int ID);
void RemoveFile(unsigned int Table, int Index);
void ImportFile(unsigned int Table, int Index, string FileName);
void ExportFile(unsigned int Table, int Index, string FileName);
void ExportFileBatch(unsigned int Table, int Index, string FolderName, string Extension);
void FixOffsets();
bool Read(string FileName, bool Partial = false);
bool Write(string FileName);
void Clear();
};
#endif
/* clsDrs.cpp */
#include "Macros.h"
#include "clsDrs.h"
#include "Globals.h"
clsDrs::clsDrs()
{
memset(Copyright, '\0', 40);
memset(Version, '\0', 4);
memset(FileType, '\0', 12);
TableCount = 0;
FirstFileOffset = 0;
TableHeaders.clear();
TableEntries.clear();
TableFiles.clear();
}
clsDrsTableHeader::clsDrsTableHeader()
{
FileType = 0;
memset(ReverseExtension, '\0', 3);
TableOffset = 0;
FileCount = 0;
}
clsDrsTableEntry::clsDrsTableEntry()
{
FileID = 0;
FileOffset = 0;
FileSize = 0;
}
bool clsDrs::Read(string FileName, bool Partial)
{
FILE * fs;
if(FileExists(FileName.c_str()))
{
if(fs = fopen(FileName.c_str(), "rb"))
{
fread(Copyright, sizeof(char), 40, fs);
fread(Version, sizeof(char), 4, fs);
fread(FileType, sizeof(char), 12, fs);
fread(&TableCount, sizeof(long), 1, fs);
fread(&FirstFileOffset, sizeof(long), 1, fs);
TableHeaders.resize(TableCount);
if(TableCount > 0)
{
fread(&TableHeaders[0], sizeof(clsDrsTableHeader), TableCount, fs);
TableEntries.resize(TableCount);
for(unsigned int loop = 0;loop < TableCount;loop++)
{
TableEntries[loop].resize(TableHeaders[loop].FileCount);
fread(&TableEntries[loop][0], sizeof(clsDrsTableEntry), TableHeaders[loop].FileCount, fs);
}
if(!Partial)
{
TableFiles.resize(TableCount);
for(unsigned int loop = 0;loop < TableCount;loop++)
{
TableFiles[loop].resize(TableHeaders[loop].FileCount);
for(int loop2 = 0;loop2 < TableHeaders[loop].FileCount;loop2++)
{
TableFiles[loop][loop2].resize(TableEntries[loop][loop2].FileSize);
fread(&TableFiles[loop][loop2][0], sizeof(char), TableEntries[loop][loop2].FileSize, fs);
}
}
}
}
fclose(fs);
Loaded = true;
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
bool clsDrs::Write(string FileName)
{
FILE * fs;
if(fs = fopen(FileName.c_str(), "wb"))
{
FixOffsets();
fwrite(Copyright, sizeof(char), 40, fs);
fwrite(Version, sizeof(char), 4, fs);
fwrite(FileType, sizeof(char), 12, fs);
fwrite(&TableCount, sizeof(long), 1, fs);
fwrite(&FirstFileOffset, sizeof(long), 1, fs);
if(TableCount > 0)
{
fwrite(&TableHeaders[0], sizeof(clsDrsTableHeader), TableCount, fs);
for(unsigned int loop = 0;loop < TableCount;loop++)
{
fwrite(&TableEntries[loop][0], sizeof(clsDrsTableEntry), TableHeaders[loop].FileCount, fs);
}
for(unsigned int loop = 0;loop < TableCount;loop++)
{
for(int loop2 = 0;loop2 < TableHeaders[loop].FileCount;loop2++)
{
fwrite(&TableFiles[loop][loop2][0], sizeof(char), TableEntries[loop][loop2].FileSize, fs);
}
}
}
fclose(fs);
return true;
}
else
{
return false;
}
}
void clsDrs::Clear()
{
if(Loaded)
{
TableCount = 0;
TableHeaders.clear();
TableEntries.clear();
TableFiles.clear();
Loaded = false;
}
}
void clsDrs::AddFile(unsigned int Table, int Index, string FileName, int ID)
{
vector<char> Buffer;
clsDrsTableEntry Temp;
FILE * InFile;
int Length;
if((FileExists(FileName.c_str())) && (Table < TableCount) && (Table >= 0))
{
InFile = fopen(FileName.c_str(), "rb");
fseek(InFile, 0, SEEK_END);
Length = ftell(InFile);
rewind(InFile);
Buffer.resize(Length);
fread(&Buffer.front(), sizeof(char), Length, InFile);
fclose(InFile);
Temp.FileID = ID;
Temp.FileSize = Length;
if((Index >= TableHeaders[Table].FileCount) || (Index < 0))
{
TableEntries[Table].push_back(Temp);
TableFiles[Table].push_back(Buffer);
}
else
{
TableEntries[Table].insert(TableEntries[Table].begin() + Index, Temp);
TableFiles[Table].insert(TableFiles[Table].begin() + Index, Buffer);
}
TableHeaders[Table].FileCount++;
}
}
void clsDrs::RemoveFile(unsigned int Table, int Index)
{
if((Table < TableCount) && (Table >= 0))
{
if((Index >= 0) && (Index < TableHeaders[Table].FileCount))
{
TableEntries[Table].erase(TableEntries[Table].begin() + Index);
TableFiles[Table].erase(TableFiles[Table].begin() + Index);
TableHeaders[Table].FileCount--;
}
}
}
void clsDrs::ImportFile(unsigned int Table, int Index, string FileName)
{
vector<char> Buffer;
FILE * InFile;
int Length;
if((FileExists(FileName.c_str())) && (Table < TableCount) && (Table >= 0))
{
InFile = fopen(FileName.c_str(), "rb");
fseek(InFile, 0, SEEK_END);
Length = ftell(InFile);
rewind(InFile);
Buffer.resize(Length);
fread(&Buffer.front(), sizeof(char), Length, InFile);
fclose(InFile);
if((Index < TableHeaders[Table].FileCount) && (Index >= 0))
{
TableEntries[Table][Index].FileSize = Length;
TableFiles[Table][Index] = Buffer;
}
}
}
void clsDrs::ExportFile(unsigned int Table, int Index, string FileName)
{
FILE * OutFile;
if((Index < TableHeaders[Table].FileCount) && (Index >= 0))
{
OutFile = fopen(FileName.c_str(), "wb");
if(OutFile != NULL)
{
fwrite(&TableFiles[Table][Index].front(), sizeof(char), TableEntries[Table][Index].FileSize, OutFile);
fclose(OutFile);
}
}
}
void clsDrs::ExportFileBatch(unsigned int Table, int Index, string FolderName, string Extension)
{
FILE * OutFile;
string Temp;
char Buffer[4];
if((Index < TableHeaders[Table].FileCount) && (Index >= 0))
{
if(Extension.length() > 0)
{
Temp = Extension;
}
else
{
memcpy(Buffer, TableHeaders[Table].ReverseExtension, 3);
Temp = Buffer;
reverse(Temp.end() - 3, Temp.end());
}
OutFile = fopen(string(FolderName + lexical_cast<string>(TableEntries[Table][Index].FileID) + "." + Temp).c_str(), "wb");
if(OutFile != NULL)
{
fwrite(&TableFiles[Table][Index].front(), sizeof(char), TableEntries[Table][Index].FileSize, OutFile);
fclose(OutFile);
}
}
}
void clsDrs::FixOffsets()
{
FILE * fs;
if(fs = tmpfile())
{
fwrite(Copyright, sizeof(char), 40, fs);
fwrite(Version, sizeof(char), 4, fs);
fwrite(FileType, sizeof(char), 12, fs);
fwrite(&TableCount, sizeof(long), 1, fs);
fwrite(&FirstFileOffset, sizeof(long), 1, fs);
if(TableCount > 0)
{
fwrite(&TableHeaders[0], sizeof(clsDrsTableHeader), TableCount, fs);
for(unsigned int loop = 0;loop < TableCount;loop++)
{
for(int loop2 = 0;loop2 < TableHeaders[loop].FileCount;loop2++)
{
TableHeaders[loop].TableOffset = ftell(fs);
fwrite(&TableEntries[loop][loop2], sizeof(clsDrsTableEntry), 1, fs);
}
}
for(unsigned int loop = 0;loop < TableCount;loop++)
{
for(int loop2 = 0;loop2 < TableHeaders[loop].FileCount;loop2++)
{
TableEntries[loop][loop2].FileOffset = ftell(fs);
fwrite(&TableFiles[loop][loop2][0], sizeof(char), TableEntries[loop][loop2].FileSize, fs);
}
}
}
fclose(fs);
FirstFileOffset = TableEntries[0][0].FileOffset;
}
}