typedef struct
{
char Signature[4];
int DirOffset;
int DirLength;
} pakHeader;
typedef struct
{
char FileName[56];
int FilePosition;
int FileLength;
} pakEntry;
FILE *file;
pakHeader Header;
pakEntry *Entry;
int NumFiles;
bool OpenPAK(char FileName[])
{
// Open a PAK file in binary mode for reading
file = fopen(FileName, "rb");
fread(&Header, sizeof(Header), 1, file);
if (strncmp(Header.Signature, "PACK", 4))
fclose(file);
NumFiles = (Header.DirLength / 64);
Entry = new pakEntry[NumFiles];
fseek(file, Header.DirOffset, SEEK_SET);
fread(Entry, sizeof(pakEntry), NumFiles, file);
for (int i = 0; i < NumFiles; i++)
{
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.pszText = Entry.FileName;
SendMessage(hListView, LVM_INSERTITEM, 0, (LPARAM) &lvItem);
lvItem.iItem = 0;
lvItem.iSubItem = 3;
lvItem.pszText = (char *) Entry.FileLength;
SendMessage(hListView, LVM_SETITEMTEXT, 0, (LPARAM) &lvItem);
}
return true;
}
void ExtractPAK(char FileName[])
{
int *ByteArray;
ByteArray = new int[Entry[1].FileLength];
fseek(file, Entry[1].FilePosition, SEEK_SET);
fread(&ByteArray, sizeof(ByteArray), 1, file);
file = fopen(FileName, "wb");
fwrite(&ByteArray, sizeof(ByteArray), 1, file);
}
🔒 Locked
Extracting files
Advertisement
Original Post
I have written code to open and show the contents of a Quake 2 PAK file into a listview control. I can show them but what I want to know is how can I extract the contents of the first file? Below is the code and my attempt at trying to figure out the extract code. Any help is appreciated!
Instead of using an int array to store the data being read in try using a void* instead - you can use malloc() to allocate the memory or alternative you could use an unsigned char array.
Your also going to need to store details of each entry in the PAK file - a vector of pakEntry's will do the job. You'll then want to loop through NumEntries - 1 times and compare the filename passed in against the value in the vector at the current index. If the stings match seek to the files offset and read in the required amount of data, then you can write it back out to disk.
Your also going to need to store details of each entry in the PAK file - a vector of pakEntry's will do the job. You'll then want to loop through NumEntries - 1 times and compare the filename passed in against the value in the vector at the current index. If the stings match seek to the files offset and read in the required amount of data, then you can write it back out to disk.
Here's the Read() method from my own reader:
m_PakEntries is a vector of pakEntry objects which is created when the PAK is opened, m_PakFile is a FILE* handle to the PAK file.
The return values are members of an enum containing different return codes.
Im not entirely sure but the reason why your code is only writing four bytes may be due to sizeof(ByteArray) returning the size of the pointer (4 bytes) and not the actual amount of memory allocated, this can be solved using an unsigned char array then using the length of the file as the value when allocating the memory and writing the data
int CQuake2Pak::ReadFile(const string &FileName, void **FileBuffer, unsigned long &FileSize){ //make sure the file has previously been opened if(!m_PakFile) return Q2P_FILE_NOT_OPEN; //locate the file in the entries list for(unsigned int i = 0; i < m_NumEntries; i++) { if(FileName == m_PakEntries.m_FileName) { fseek(m_PakFile, m_PakEntries.m_FilePos, SEEK_SET); //setup file buffer *FileBuffer = malloc(m_PakEntries.m_FileLength); if(!*FileBuffer) return Q2P_OUT_OF_MEMORY; //read the file in if(fread(*FileBuffer, m_PakEntries.m_FileLength, 1, m_PakFile) != 1) return Q2P_READ_ERROR; else { FileSize = m_PakEntries.m_FileLength; return Q2P_SUCCESS; } } } //file not found return Q2P_FILE_NOT_FOUND;}m_PakEntries is a vector of pakEntry objects which is created when the PAK is opened, m_PakFile is a FILE* handle to the PAK file.
The return values are members of an enum containing different return codes.
Im not entirely sure but the reason why your code is only writing four bytes may be due to sizeof(ByteArray) returning the size of the pointer (4 bytes) and not the actual amount of memory allocated, this can be solved using an unsigned char array then using the length of the file as the value when allocating the memory and writing the data
The problem you have is with telling fwrite() how many bytes to write out, you already know how many bytes to write as it's one of the fields in pakEntry so you need to change the call to fwrite to something like this:
This will ensure that your writing the correct number of bytes out to to the file.
fwrite((void*)&ByteArray, Entry[1].FileLength, 1, file);This will ensure that your writing the correct number of bytes out to to the file.
Well before I extract the file, I should be writing to ascii and not binary correct?
So I should remove the "b" ?
and make it:
hmmm, still doesn't work properly...
So I should remove the "b" ?
file = fopen(FileName, "wb");fwrite(&ByteArray, sizeof(ByteArray), 1, file);and make it:
file = fopen(FileName, "w");fwrite(&ByteArray, sizeof(ByteArray), 1, file);hmmm, still doesn't work properly...
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement