📄 pakstuff.cpp
字号:
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include "io.h"
#include "pakstuff.h"
#include "unzip.h"
//#include "cmdlib.h"
#include "str.h"
int m_nPAKIndex;
FILE* pakfile[16];
struct PACKDirectory pakdir;
PACKDirPtr pakdirptr = &pakdir;
UInt16 dirsize;
boolean pakopen = false;
int f_type;
DIRECTORY *paktextures = NULL;
boolean HavePakColormap;
UInt32 PakColormapOffset;
UInt32 PakColormapSize;
DIRECTORY *dirhead = NULL;
boolean g_bPK3 = false;
char g_strBasePath[1024];
struct PK3FileInfo
{
unzFile m_zFile;
char *m_pName;
unz_s m_zInfo;
long m_lSize;
~PK3FileInfo()
{
delete []m_pName;
}
bool operator ==(const PK3FileInfo& rhs) const { return strcmp(m_pName, rhs.m_pName) == 0; }
};
#define __PATHSEPERATOR '/'
#define LOG_PAKFAIL
#ifdef LOG_PAKFAIL
class LogFile
{
public:
FILE *m_pFile;
LogFile(const char* pName)
{
m_pFile = fopen(pName, "w");
}
~LogFile()
{
if (m_pFile)
{
fclose(m_pFile);
}
}
void Log(const char *pFormat, ...)
{
va_list arg_ptr;
va_start(arg_ptr, pFormat);
fprintf(m_pFile, pFormat, arg_ptr);
va_end(arg_ptr);
}
};
LogFile g_LogFile("c:\\paklog.txt");
#endif
template <class T> class StrPtr : public Str
{
protected:
T* m_pPtr;
StrPtr()
{
m_pPtr = NULL;
}
StrPtr(const char *pStr, T *p) : Str(pStr)
{
m_pPtr = p;
}
T* Ptr()
{
return m_pPtr;
}
T& Ref()
{
return *m_pPtr;
}
};
// PtrList
// a list of ptrs
//
template <class T> class PtrList
{
protected:
T *m_pPtr;
PtrList *m_pNext;
public:
PtrList()
{
m_pNext = NULL;
m_pPtr = NULL;
}
PtrList(T *ip)
{
m_pNext = NULL;
m_pPtr = ip;
}
~PtrList()
{
delete m_pPtr;
}
PtrList* Next()
{
return m_pNext;
}
void Add(T *ip)
{
PtrList *pl = this;
while (pl && pl->m_pNext)
{
pl = pl->Next();
}
pl->m_pNext = new PtrList(ip);
}
void Remove()
{
PtrList *p = m_pNext;
if (p)
{
while (p->m_pNext != this && p->m_pNext != NULL)
{
p = p->m_pNext;
}
if (p->m_pNext == this)
{
p->m_pNext = m_pNext;
}
}
}
virtual PtrList* Find(T *ip)
{
PtrList *p = m_pNext;
while (p)
{
if (*p->m_pPtr == *ip)
{
return p;
}
p = p->m_pNext;
}
return NULL;
}
// remove vp from the list
void Remove(T *ip)
{
PtrList *p = Find(ip);
if (p)
{
p->Remove();
}
}
T* Ptr()
{
return m_pPtr;
}
T& Ref()
{
return *m_pPtr;
}
void RemoveAll()
{
PtrList *p = m_pNext;
while (p)
{
PtrList *p2 = p;
p = p->m_pNext;
delete p2;
}
}
};
typedef PtrList<unzFile> ZFileList;
typedef PtrList<Str> StrList;
typedef PtrList<PK3FileInfo> PK3List;
StrList g_PK3TexturePaths;
PK3List g_PK3Files;
ZFileList g_zFiles;
#define WORK_LEN 1024
#define TEXTURE_PATH "textures"
#define PATH_SEPERATORS "/\\:\0"
char* __StrDup(char* pStr)
{
if (pStr)
{
return strcpy(new char[strlen(pStr)+1], pStr);
}
return NULL;
}
char* __StrDup(const char* pStr)
{
if (pStr)
{
return strcpy(new char[strlen(pStr)+1], pStr);
}
return NULL;
}
#define MEM_BLOCKSIZE 4096
void* __qblockmalloc(size_t nSize)
{
void *b;
// round up to threshold
int nAllocSize = nSize % MEM_BLOCKSIZE;
if ( nAllocSize > 0)
{
nSize += MEM_BLOCKSIZE - nAllocSize;
}
b = malloc(nSize + 1);
memset (b, 0, nSize);
return b;
}
void* __qmalloc (size_t nSize)
{
void *b;
b = malloc(nSize + 1);
memset (b, 0, nSize);
return b;
}
/*
====================
Extract file parts
====================
*/
void __ExtractFilePath (const char *path, char *dest)
{
const char *src;
src = path + strlen(path) - 1;
//
// back up until a \ or the start
//
while (src != path && *(src-1) != __PATHSEPERATOR)
src--;
memcpy (dest, path, src-path);
dest[src-path] = 0;
}
void __ExtractFileName (const char *path, char *dest)
{
const char *src;
src = path + strlen(path) - 1;
//
// back up until a \ or the start
//
while (src != path && *(src-1) != '/'
&& *(src-1) != '\\' )
src--;
while (*src)
{
*dest++ = *src++;
}
*dest = 0;
}
void __ExtractFileBase (const char *path, char *dest)
{
const char *src;
src = path + strlen(path) - 1;
//
// back up until a \ or the start
//
while (src != path && *(src-1) != '/'
&& *(src-1) != '\\' )
src--;
while (*src && *src != '.')
{
*dest++ = *src++;
}
*dest = 0;
}
void __ExtractFileExtension (const char *path, char *dest)
{
const char *src;
src = path + strlen(path) - 1;
//
// back up until a . or the start
//
while (src != path && *(src-1) != '.')
src--;
if (src == path)
{
*dest = 0; // no extension
return;
}
strcpy (dest,src);
}
void __ConvertDOSToUnixName( char *dst, const char *src )
{
while ( *src )
{
if ( *src == '\\' )
*dst = '/';
else
*dst = *src;
dst++; src++;
}
*dst = 0;
}
void AddSlash(Str& str)
{
int nLen = str.GetLength();
if (nLen > 0)
{
if (str[nLen-1] != '\\' && str[nLen-1] != '/')
str += '\\';
}
}
void FindReplace(Str& strContents, const char* pTag, const char* pValue)
{
if (strcmp(pTag, pValue) == 0)
return;
for (int nPos = strContents.Find(pTag); nPos >= 0; nPos = strContents.Find(pTag))
{
int nRightLen = strContents.GetLength() - strlen(pTag) - nPos;
Str strLeft(strContents.Left(nPos));
Str strRight(strContents.Right(nRightLen));
strLeft += pValue;
strLeft += strRight;
strContents = strLeft;
}
}
void ProgError(char *errstr, ...)
{
va_list args;
va_start(args, errstr);
printf("\nProgram Error: *** ");
vprintf(errstr, args);
printf(" ***\n");
va_end(args);
exit(5);
}
boolean ReadBytes(FILE *file, void *addr, UInt32 size)
{
while (size > 0x8000)
{
if (fread(addr, 1, 0x8000, file) != 0x8000)
return false;
addr = (char *)addr + 0x8000;
size -= 0x8000;
}
if (fread(addr, 1, size, file) != size)
return false;
return true;
}
int ReadMagic(FILE *file)
{
UInt8 buf[4];
if (ReadBytes(file, buf, 4) == FALSE)
return FTYPE_ERROR;
if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "IWAD", 4))
return FTYPE_IWAD;
if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "PWAD", 4))
return FTYPE_PWAD;
if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "PACK", 4))
return FTYPE_PACK;
if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "WAD2", 4))
return FTYPE_WAD2;
if (buf[0] == 0x17 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0)
return FTYPE_BSP;
if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "IDPO", 4))
return FTYPE_MODEL;
if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "IDSP", 4))
return FTYPE_SPRITE;
if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "RIFF", 4))
return FTYPE_WAV;
if (!strncmp(reinterpret_cast<const char*>(&buf[0]), ".snd", 4))
return FTYPE_AU;
if (buf[0] == 'P')
{
if (buf[1] == '1')
return FTYPE_PBM_ASC;
if (buf[1] == '2')
return FTYPE_PGM_ASC;
if (buf[1] == '3')
return FTYPE_PPM_ASC;
if (buf[1] == '4')
return FTYPE_PBM_RAW;
if (buf[1] == '5')
return FTYPE_PGM_RAW;
if (buf[1] == '6')
return FTYPE_PPM_RAW;
}
if (buf[0] == 'B' && buf[1] == 'M')
return FTYPE_BMP;
if (!strncmp(reinterpret_cast<const char*>(&buf[0]), "GIF8", 4))
return FTYPE_GIF;
if (buf[0] == 0x0a && buf[1] == 0x05 && buf[2] == 0x01 && buf[3] == 0x08)
return FTYPE_PCX;
return FTYPE_UNKNOWN;
}
FILE *OpenFileReadMagic(const char *filename, int *ftype_r)
{
FILE *f;
*ftype_r = FTYPE_ERROR;
if ((f = fopen(filename, "rb")) == NULL)
return NULL;
*ftype_r = ReadMagic(f);
if (*ftype_r == FTYPE_ERROR)
{
fclose(f);
return NULL;
}
return f;
}
boolean WriteBytes(FILE *file, void *addr, UInt32 size)
{
while (size > 0x8000)
{
if (fwrite(addr, 1, 0x8000, file) != 0x8000)
return FALSE;
addr = (char *)addr + 0x8000;
size -= 0x8000;
}
if (fwrite(addr, 1, size, file) != size)
return FALSE;
return TRUE;
}
char *ConvertFilePath(char *filename)
{
char *cp;
if (filename == NULL)
ProgError("BUG: cannot convert a NULL pathname");
for (cp = filename; *cp; cp++)
if (*cp == '/' || *cp == '\\')
{
#ifdef QEU_DOS
*cp = '\\';
#else
*cp = '/';
#endif
}
return filename;
}
/*
* Read the PACK directory into memory. The optional offset to the
* start of the PACK file is given in "offset". The number of files in
* the directory is returned in *dirsize_r.
*/
PACKDirPtr ReadPACKDirectory(FILE *packfile, UInt32 offset, UInt16 *dirsize_r)
{
PACKDirPtr dir;
UInt32 pos, size;
UInt16 max, i;
*dirsize_r = 0;
if (packfile == NULL)
return NULL;
if ((fseek(packfile, offset, SEEK_SET) < 0)
|| (ReadMagic(packfile) != FTYPE_PACK)
|| (ReadInt32(packfile, &pos) == FALSE)
|| (ReadInt32(packfile, &size) == FALSE)
|| (size == 0L)
|| (size / sizeof(struct PACKDirectory) > 65535L)
|| (fseek(packfile, offset + pos, SEEK_SET) < 0))
return NULL;
dir = (PACKDirPtr)__qmalloc(size);
max = (UInt16)(size / sizeof(struct PACKDirectory));
for (i = 0; i < max; i++)
{
if (ReadBytes(packfile, &dir[i], sizeof(struct PACKDirectory)) == FALSE)
{
free(dir);
return NULL;
}
ConvertFilePath(dir[i].name);
dir[i].offset = SwapInt32(dir[i].offset);
dir[i].size = SwapInt32(dir[i].size);
}
*dirsize_r = max;
return dir;
}
/*
* Print the contents of the PACK directory in "outf".
*/
void DumpPACKDirectory(FILE *outf, PACKDirPtr dir, UInt16 dirsize)
{
UInt16 i;
UInt32 sum;
char buf[57];
if (outf == NULL || dir == NULL || dirsize == 0)
return;
fprintf(outf, "num offset size file name\n");
fprintf(outf, " (hex) (dec)\n");
sum = 0L;
for (i = 0; i < dirsize; i++)
{
if(!strnicmp(dir[i].name, "textures", 8))
{
strncpy(buf, dir[i].name, 56);
buf[56] = '\0';
fprintf(outf, "%3u 0x%08lx %6ld %s\n",
i, dir[i].offset, dir[i].size, buf);
sum += dir[i].size;
}
}
fprintf(outf, "\nTotal size for %3u entries: %7lu bytes.\n", dirsize, sum);
fprintf(outf, "Size of the PACK directory: %7lu bytes.\n",
(UInt32)dirsize * (UInt32)sizeof(struct PACKDirectory));
fprintf(outf, "Total (header + data + dir): %7lu bytes.\n",
12L + sum + (UInt32)dirsize * (UInt32)sizeof(struct PACKDirectory));
}
void ClearFileList(FILELIST **list)
{
FILELIST *temp;
while(*list)
{
temp = *list;
*list = (*list)->next;
free(temp);
}
}
void ClearDirList(DIRLIST **list)
{
DIRLIST *temp;
while(*list)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -