You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
3.8 KiB
136 lines
3.8 KiB
8 years ago
|
//++ BulliT
|
||
|
|
||
|
#include "agglobal.h"
|
||
|
#include "agpak.h"
|
||
|
|
||
|
typedef struct
|
||
|
{ unsigned char magic[4]; // Name of the new WAD format
|
||
|
long diroffset; // Position of WAD directory from start of file
|
||
|
long dirsize; // Number of entries * 0x40 (64 char)
|
||
|
} pakheader_t;
|
||
|
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
unsigned char filename[0x38]; // Name of the file, Unix style, with extension,
|
||
|
// 50 chars, padded with '\0'.
|
||
|
long offset; // Position of the entry in PACK file
|
||
|
long size; // Size of the entry in PACK file
|
||
|
} pakentry_t;
|
||
|
|
||
|
|
||
|
AgPak::AgPak()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
bool AgPak::GetEntries(const AgString& sPakfile, const AgString& sSearch1, const AgString& sSearch2, AgStringList& lstEntries)
|
||
|
{
|
||
|
AgString sSearchString1;
|
||
|
AgString sSearchString2;
|
||
|
sSearchString1 = sSearch1;
|
||
|
sSearchString2 = sSearch2;
|
||
|
AgToLower(sSearchString1);
|
||
|
AgToLower(sSearchString2);
|
||
|
|
||
|
pakheader_t Header;
|
||
|
DWORD dwRead = 0;
|
||
|
HANDLE h = CreateFile(sPakfile.c_str(),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,0);
|
||
|
|
||
|
//Read header.
|
||
|
if (!ReadFile(h,(void*)&Header,sizeof(Header),&dwRead,NULL))
|
||
|
return false;
|
||
|
if (sizeof(Header) != dwRead)
|
||
|
return false;
|
||
|
|
||
|
//Move to directory list.
|
||
|
SetFilePointer(h,Header.diroffset,NULL,FILE_BEGIN);
|
||
|
|
||
|
//Allocate array of entries.
|
||
|
pakentry_t* pEntries = (pakentry_t*)malloc(Header.dirsize);
|
||
|
|
||
|
//Read the entries.
|
||
|
if (!ReadFile(h,(void*)pEntries,Header.dirsize,&dwRead,NULL))
|
||
|
{
|
||
|
free(pEntries);
|
||
|
CloseHandle(h);
|
||
|
return false;
|
||
|
}
|
||
|
CloseHandle(h);
|
||
|
|
||
|
if (Header.dirsize != (long)dwRead)
|
||
|
{
|
||
|
free(pEntries);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//Calc number of entries.
|
||
|
int iEntries = Header.dirsize / sizeof(pakentry_t);
|
||
|
|
||
|
//Read directory listing
|
||
|
for (int i = 0; i < iEntries; i++)
|
||
|
{
|
||
|
AgString sFilename;
|
||
|
sFilename = (const char*)pEntries[i].filename;
|
||
|
AgToLower(sFilename);
|
||
|
|
||
|
if (0 != sSearchString1.length())
|
||
|
{
|
||
|
//Check if the file contains the search1 string.
|
||
|
if (NPOS != sFilename.find(sSearchString1))
|
||
|
{
|
||
|
if (0 != sSearchString2.length())
|
||
|
{
|
||
|
if (NPOS != sFilename.find(sSearchString2))
|
||
|
lstEntries.push_back(sFilename);
|
||
|
}
|
||
|
else
|
||
|
lstEntries.push_back(sFilename);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Add all files
|
||
|
lstEntries.push_back(sFilename);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
free((void*)pEntries);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Quake PAK Format
|
||
|
|
||
|
Figured out by Pete McCormick (petra@force.net) I am not responsible for any damage this does, enjoy,
|
||
|
and please email me any comments!
|
||
|
Pete
|
||
|
|
||
|
=Format=
|
||
|
Header
|
||
|
(4 unsigned chars) signature = 'PACK'
|
||
|
(4 unsigned chars, int) directory offeset
|
||
|
(4 unsigned chars, int) directory lenght
|
||
|
|
||
|
Directory
|
||
|
(56 unsigned chars, char) file name
|
||
|
(4 unsigned chars, int) file position
|
||
|
(4 unsigned chars, int) file lenght
|
||
|
|
||
|
File at each position (? unsigned chars, char) file data
|
||
|
Description - The signature must be present in all PAKs; it's the way Quake knows its a real PAK file.
|
||
|
The directory offset is where the directory listing starts, and the lenght is its lenght.
|
||
|
In the actuall directory listing, the three options, 56 unsigned chars of a name,
|
||
|
the files position and lenght, are repeating until the running total of the length (increment by 64) is reached.
|
||
|
If the directory lenght mod 64 is not a even number, you know their is something wrong.
|
||
|
And directories are just handled by a making the name something like "/foobar/yeahs.txt". Short and simple.
|
||
|
|
||
|
Tips - Put the directory entry at the end of the file, so if you added a file,
|
||
|
you'd just rewrite the small directory entry instead of all the data.
|
||
|
|
||
|
Limits - Unknown file limit. Don't create too many though :) I would think around a 1000,
|
||
|
prehaps 2000 (in which case, 2048 would be reasonible)
|
||
|
*/
|
||
|
|
||
|
//-- Martin Webrant
|