Initial commit: the original DAT2 v2.32

This commit is contained in:
NovaRain
2023-04-01 20:46:51 +08:00
commit 13f100fbfc
26 changed files with 4122 additions and 0 deletions
BIN
View File
Binary file not shown.
+991
View File
File diff suppressed because it is too large Load Diff
+91
View File
@@ -0,0 +1,91 @@
#pragma once
#include "DatFileBase.h"
// CFileList1
class CFileList1 : public CObject {
public:
CFileList1();
virtual ~CFileList1();
DECLARE_DYNAMIC(CFileList1)
virtual void Serialize(CArchive& ar);
INT_PTR GetSize() const;
DWORD GetLength();
INT_PTR Add(const CFileDescriptorBase& newElement);
void RemoveAt(INT_PTR nIndex);
CFileDescriptorBase& operator [] (INT_PTR nIndex);
CFileDescriptorBase operator [] (INT_PTR nIndex) const;
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
private:
// Assignment and copy not allowed
CFileList1(const CFileList1&);
CFileList1& operator = (const CFileList1&);
private:
// CFileDescriptorBaseArray
typedef CArray<CFileDescriptorBase, const CFileDescriptorBase&> CFileDescriptorBaseArray;
// CFileTreeItem
class CFileTreeItem {
public:
CFileTreeItem();
CFileTreeItem(const CFileTreeItem& item);
public:
CFileTreeItem& operator = (const CFileTreeItem& item);
public:
CString m_strDirectoryName;
CFileDescriptorBaseArray m_FileList;
};
// CFileTree
typedef CArray<CFileTreeItem, const CFileTreeItem&> CFileTree;
CFileTree m_FileTree;
};
// CDatFile1
class CDatFile1 : public CDatFileBase {
public:
CDatFile1();
virtual ~CDatFile1();
DECLARE_DYNAMIC(CDatFile1)
virtual BOOL Open(LPCTSTR lpszFileName, UINT nOpenFlags);
virtual void Close();
virtual void Flush();
virtual INT_PTR GetFileCount();
virtual CFileDescriptorBase operator [] (INT_PTR nIndex) const;
virtual INT_PTR FindNext();
virtual BOOL Inflate(CArchive& ar);
virtual BOOL Deflate(CArchive& ar, DWORD dwLength, LPCTSTR lpszName, int level);
virtual BOOL Delete();
virtual BOOL Shrink(void (*pCallback)(INT_PTR nIndex));
private:
void FreeSpaceForCatalog();
private:
// Restricted operations
CDatFile1(const CDatFile1&);
CDatFile1& operator = (const CDatFile1&);
virtual void Serialize(CArchive&) {};
private:
CFileList1 m_FileList;
};
+868
View File
File diff suppressed because it is too large Load Diff
+90
View File
@@ -0,0 +1,90 @@
#pragma once
#include "DatFileBase.h"
// CFileDescriptor2
class CFileDescriptor2 : public CFileDescriptorBase {
public:
CFileDescriptor2();
CFileDescriptor2(const CFileDescriptor2& item);
virtual ~CFileDescriptor2();
DECLARE_DYNAMIC(CFileDescriptor2)
virtual void Serialize(CArchive& ar);
int GetSize() const;
CFileDescriptor2& operator = (const CFileDescriptor2& item);
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
};
// CFileList2
class CFileList2 : public CObject {
public:
CFileList2();
virtual ~CFileList2();
DECLARE_DYNAMIC(CFileList2)
virtual void Serialize(CArchive& ar);
INT_PTR GetSize() const;
INT_PTR Add(const CFileDescriptor2& newElement);
void RemoveAt(INT_PTR nIndex);
CFileDescriptor2& operator [] (INT_PTR nIndex);
CFileDescriptor2 operator [] (INT_PTR nIndex) const;
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
private:
// Assignment and copy not allowed
CFileList2(const CFileList2&);
CFileList2& operator = (const CFileList2&);
private:
typedef CArray<CFileDescriptor2> CFileDescriptor2Array;
CFileDescriptor2Array m_FileList;
};
// CDatFile2
class CDatFile2 : public CDatFileBase {
public:
CDatFile2();
virtual ~CDatFile2();
DECLARE_DYNAMIC(CDatFile2)
virtual BOOL Open(LPCTSTR lpszFileName, UINT nOpenFlags);
virtual void Close();
virtual void Flush();
virtual INT_PTR GetFileCount();
virtual CFileDescriptorBase operator [](INT_PTR nIndex) const;
virtual INT_PTR FindNext();
virtual BOOL Inflate(CArchive& ar);
virtual BOOL Deflate(CArchive& ar, DWORD dwLength, LPCTSTR lpszName, int level);
virtual BOOL Delete();
virtual BOOL Shrink(void (*pCallback)(INT_PTR nIndex));
private:
// Restricted operations
CDatFile2(const CDatFile2&);
CDatFile2& operator = (const CDatFile2&);
virtual void Serialize(CArchive&) {};
private:
CFileList2 m_FileList;
};
+163
View File
@@ -0,0 +1,163 @@
// DatFile.cpp : implementation file
//
#include "stdafx.h"
#include "DatFileBase.h"
#include ".\datfilebase.h"
#if defined(_UNICODE) || defined(UNICODE)
#error UNICODE not supported
#endif
// Utility function
CString MakeLower(CString str)
{
return str.MakeLower();
}
// CFileDescriptorBase
IMPLEMENT_DYNAMIC(CFileDescriptorBase, CObject)
CFileDescriptorBase::CFileDescriptorBase() :
m_strFileName(""),
m_nType(0),
m_dwFileLength(0),
m_dwPackedFileLength(0),
m_dwOffset(0)
{
}
CFileDescriptorBase::CFileDescriptorBase(const CFileDescriptorBase& item) :
m_strFileName(item.m_strFileName),
m_nType(item.m_nType),
m_dwFileLength(item.m_dwFileLength),
m_dwPackedFileLength(item.m_dwPackedFileLength),
m_dwOffset(item.m_dwOffset)
{
}
CFileDescriptorBase::~CFileDescriptorBase()
{
}
CFileDescriptorBase& CFileDescriptorBase::operator = (const CFileDescriptorBase& item)
{
if (&item != this) {
m_strFileName = item.m_strFileName;
m_nType = item.m_nType;
m_dwFileLength = item.m_dwFileLength;
m_dwPackedFileLength = item.m_dwPackedFileLength;
m_dwOffset = item.m_dwOffset;
}
return (*this);
}
void CFileDescriptorBase::Serialize(CArchive& ar)
{
ASSERT(FALSE);
}
#ifdef _DEBUG
void CFileDescriptorBase::AssertValid() const
{
CObject::AssertValid();
ASSERT(!m_strFileName.IsEmpty());
ASSERT(m_nType <= 1);
ASSERT(m_dwFileLength != 0);
ASSERT(m_dwPackedFileLength != 0);
ASSERT(m_dwPackedFileLength >= m_dwFileLength);
}
void CFileDescriptorBase::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << "File name length:\t" << m_strFileName.GetLength() << "\n";
dc << "File name:\t\t\t" << m_strFileName << "\n";
dc << "Type:\t\t\t\t" << m_nType << "\n";
dc << "File length:\t\t\t" << m_dwFileLength << " (";
dc.DumpAsHex(m_dwFileLength);
dc << ")\n";
dc << "Packed file length:\t" << m_dwPackedFileLength << " (";
dc.DumpAsHex(m_dwPackedFileLength);
dc << ")\n";
dc << "Offset:\t\t\t\t" << m_dwOffset << " (";
dc.DumpAsHex(m_dwOffset);
dc << ")\n";
}
#endif
// CDatFileBase
IMPLEMENT_DYNAMIC(CDatFileBase, CObject)
CDatFileBase::CDatFileBase() :
m_strPattern("*"),
m_bNeedFlush(FALSE),
m_nCurrent(-1)
{
}
CDatFileBase::~CDatFileBase()
{
}
DWORD CDatFileBase::GetLength(void)
{
return DWORD(m_Dat.GetLength());
}
INT_PTR CDatFileBase::FindFirst(LPCTSTR lpszPattern)
{
m_strPattern = lpszPattern;
m_nCurrent = -1;
return FindNext();
}
INT_PTR CDatFileBase::GetCurrentFileIndex()
{
return m_nCurrent;
}
CString CDatFileBase::GetFindFilePattern()
{
return m_strPattern;
}
BOOL CDatFileBase::MatchPattern(LPCTSTR lpszString, LPCTSTR lpszPattern, BOOL bCaseSensitive)
{
char c, p;
for(; ;) {
switch(p = ConvertCase(*lpszPattern++, bCaseSensitive)) {
case 0: // end of lpszPattern
return *lpszString ? FALSE : TRUE; // if end of lpszString TRUE
case '*':
while (*lpszString) { // match zero or more char
if (MatchPattern(lpszString++, lpszPattern, bCaseSensitive))
return TRUE;
}
return MatchPattern (lpszString, lpszPattern, bCaseSensitive );
case '?':
if (*lpszString++ == 0) // match any one char
return FALSE; // not end of lpszString
break;
default:
c = ConvertCase(*lpszString++, bCaseSensitive);
if (c != p) // check for exact char
return FALSE; // not a match
break;
}
}
}
char CDatFileBase::ConvertCase(char c, BOOL bCaseSensetive)
{
return bCaseSensetive ? c : char(CharUpper(LPTSTR(c)));
}
+71
View File
@@ -0,0 +1,71 @@
#pragma once
// CFileDescriptorBase
class CFileDescriptorBase : public CObject {
public:
CFileDescriptorBase();
CFileDescriptorBase(const CFileDescriptorBase& item);
virtual ~CFileDescriptorBase();
DECLARE_DYNAMIC(CFileDescriptorBase)
virtual void Serialize(CArchive& ar);
CFileDescriptorBase& operator = (const CFileDescriptorBase& item);
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
public:
CString m_strFileName;
BYTE m_nType;
DWORD m_dwFileLength;
DWORD m_dwPackedFileLength;
DWORD m_dwOffset;
};
// CDatFileBase
class CDatFileBase : public CObject {
public:
CDatFileBase();
virtual ~CDatFileBase();
DECLARE_DYNAMIC(CDatFileBase)
virtual BOOL Open(LPCTSTR lpszFileName, UINT nOpenFlags) = 0;
virtual void Close() = 0;
virtual void Flush() = 0;
DWORD GetLength();
virtual INT_PTR GetFileCount() = 0;
virtual CFileDescriptorBase operator [](INT_PTR nIndex) const = 0;
INT_PTR FindFirst(LPCTSTR lpszPattern);
virtual INT_PTR FindNext() = 0;
INT_PTR GetCurrentFileIndex();
CString GetFindFilePattern();
virtual BOOL Inflate(CArchive& ar) = 0;
virtual BOOL Deflate(CArchive& ar, DWORD dwLength, LPCTSTR lpszName, int level) = 0;
virtual BOOL Delete() = 0;
virtual BOOL Shrink(void (*pCallback)(INT_PTR nIndex)) = 0;
protected:
BOOL MatchPattern(LPCTSTR lpszString, LPCTSTR lpszPattern, BOOL bCaseSensitive);
char ConvertCase(char c, BOOL bCaseSensetive);
protected:
CString m_strPattern;
CFile m_Dat;
BOOL m_bNeedFlush;
INT_PTR m_nCurrent;
};
// Utility function
CString MakeLower(CString str);
+304
View File
@@ -0,0 +1,304 @@
#include "stdafx.h"
#define N 4096 /* size of ring buffer */
#define F 18 /* upper limit for match_length */
#define THRESHOLD 2 /* encode string into position and length if match_length is greater than this */
#define NIL N /* index for root of binary search trees */
//unsigned long int textsize = 0; /* text size counter */
//unsigned long int codesize = 0; /* code size counter */
BYTE text_buf[N + F - 1]; /* Ring buffer of size N, with extra F-1 bytes to facilitate string comparison */
int match_position; /* Longest match. These are set by the InsertNode() procedure. */
int match_length;
int lson[N + 1]; /* left children */
int rson[N + 257]; /* right children */
int dad[N + 1]; /* parents -- These constitute binary search trees. */
void InitTree()
{
int i;
for(i = N + 1; i <= N + 256; i++) {
rson[i] = NIL;
}
for(i = 0; i < N; i++) {
dad[i] = NIL;
}
}
void InsertNode(int r)
{
int i;
int p;
int cmp;
BYTE* key;
cmp = 1;
key = &text_buf[r];
p = N + 1 + key[0];
rson[r] = lson[r] = NIL;
match_length = 0;
for( ; ; ) {
if (cmp >= 0) {
if (rson[p] != NIL) {
p = rson[p];
}
else {
rson[p] = r;
dad[r] = p;
return;
}
}
else {
if (lson[p] != NIL) {
p = lson[p];
}
else {
lson[p] = r;
dad[r] = p;
return;
}
}
for (i = 1; i < F; i++) {
if ((cmp = key[i] - text_buf[p + i]) != 0) {
break;
}
}
if (i > match_length) {
match_position = p;
if ((match_length = i) >= F) {
break;
}
}
}
dad[r] = dad[p];
lson[r] = lson[p];
rson[r] = rson[p];
dad[lson[p]] = r;
dad[rson[p]] = r;
if (rson[dad[p]] == p) {
rson[dad[p]] = r;
}
else {
lson[dad[p]] = r;
}
dad[p] = NIL; /* remove p */
}
void DeleteNode(int p)
{
int q;
if (dad[p] == NIL) {
return; /* not in tree */
}
if (rson[p] == NIL) {
q = lson[p];
}
else if (lson[p] == NIL) {
q = rson[p];
}
else {
q = lson[p];
if (rson[q] != NIL) {
do {
q = rson[q];
} while (rson[q] != NIL);
rson[dad[q]] = lson[q];
dad[lson[q]] = dad[q];
lson[q] = lson[p];
dad[lson[p]] = q;
}
rson[q] = rson[p];
dad[rson[p]] = q;
}
dad[q] = dad[p];
if (rson[dad[p]] == p) {
rson[dad[p]] = q;
}
else {
lson[dad[p]] = q;
}
dad[p] = NIL;
}
#define GETBYTE() ((dwInputCurrent < dwInputLength) ? int(buffer[dwInputCurrent++]) & 0xFF : (-1))
void LZSSEncodeBuffer(BYTE* buffer, DWORD dwInputLength, CFile& fileOut)
{
ASSERT(buffer);
int i;
int c;
int len;
int r;
int s;
int last_match_length;
int code_buf_ptr;
BYTE code_buf[17];
BYTE mask;
DWORD dwInputCurrent = 0;
InitTree();
code_buf[0] = 0;
code_buf_ptr = mask = 1;
s = 0;
r = N - F;
for(i = s; i < r; i++) {
text_buf[i] = ' ';
}
for(len = 0; len < F && (c = GETBYTE()) != (-1); len++) {
text_buf[r + len] = c;
}
if (len == 0) {
return;
}
for(i = 1; i <= F; i++) {
InsertNode(r - i);
}
InsertNode(r);
do {
if (match_length > len) {
match_length = len;
}
if (match_length <= THRESHOLD) {
match_length = 1;
code_buf[0] |= mask;
code_buf[code_buf_ptr++] = text_buf[r];
}
else {
code_buf[code_buf_ptr++] = (BYTE) match_position;
code_buf[code_buf_ptr++] = (BYTE)(((match_position >> 4) & 0xf0) | (match_length - (THRESHOLD + 1)));
}
if ((mask <<= 1) == 0) {
for (i = 0; i < code_buf_ptr; i++) {
fileOut.Write(code_buf + i, 1);
}
code_buf[0] = 0;
code_buf_ptr = mask = 1;
}
last_match_length = match_length;
for (i = 0; i < last_match_length && (c = GETBYTE()) != (-1); i++) {
DeleteNode(s);
text_buf[s] = c;
if (s < F - 1) {
text_buf[s + N] = c;
}
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
InsertNode(r);
}
while (i++ < last_match_length) {
DeleteNode(s);
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
if (--len) {
InsertNode(r);
}
}
} while(len > 0);
if (code_buf_ptr > 1) {
for (i = 0; i < code_buf_ptr; i++) {
fileOut.Write(code_buf + i, 1);
}
}
}
void LZSSDecodeBuffer(BYTE* buffer, DWORD dwInputLength, CArchive& arOut)
{
ASSERT(buffer);
int i;
int j;
int k;
int r;
int c;
unsigned int flags;
DWORD dwInputCurrent = 0;
for (i = 0; i < N - F; i++) {
text_buf[i] = ' ';
}
r = N - F;
flags = 0;
for ( ; ; ) {
if (((flags >>= 1) & 256) == 0) {
if ((c = GETBYTE()) == (-1)) {
break;
}
flags = c | 0xff00; /* uses higher byte cleverly */
} /* to count eight */
if (flags & 1) {
if ((c = GETBYTE()) == (-1)) {
break;
}
arOut.Write(&c, 1);
text_buf[r++] = c;
r &= (N - 1);
}
else {
if ((i = GETBYTE()) == (-1)) {
break;
}
if ((j = GETBYTE()) == (-1)) {
break;
}
i |= ((j & 0xf0) << 4);
j = (j & 0x0f) + THRESHOLD;
for (k = 0; k <= j; k++) {
c = text_buf[(i + k) & (N - 1)];
arOut.Write(&c, 1);
text_buf[r++] = c;
r &= (N - 1);
}
}
}
}
+7
View File
@@ -0,0 +1,7 @@
#ifndef LZ77C_H
#define LZ77C_H
void LZSSEncodeBuffer(BYTE* buffer, DWORD dwInputLength, CFile& fileOut);
void LZSSDecodeBuffer(BYTE* buffer, DWORD dwInputLength, CArchive& arOut);
#endif /* LZ77C_H */
+98
View File
@@ -0,0 +1,98 @@
#include "stdafx.h"
#include "dat2.h"
#include "Util.h"
extern CString g_strTargetDir;
DWORD g_dwTotalAdded;
BOOL ProcessTree(CString strPattern, CString strRoot, BOOL bRecursive)
{
BOOL bResult = TRUE;
CString strPath = ExtractFilePath(strPattern);
CString strFilePattern = ExtractFileName(strPattern);
WIN32_FIND_DATA fd;
HANDLE hSearchHandle = FindFirstFile(strPattern, &fd);
if (hSearchHandle != INVALID_HANDLE_VALUE) {
do {
if (CString(fd.cFileName) != CString(_T(".")) &&
CString(fd.cFileName) != CString(_T(".."))) {
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (bRecursive) {
ProcessTree(strPath + fd.cFileName + "\\" + strFilePattern,
strRoot.IsEmpty() ? fd.cFileName : strRoot + "\\" + fd.cFileName, // + _T("\\"),
bRecursive);
}
}
else {
CFile fileIn;
if (fileIn.Open(strPath + fd.cFileName, CFile::modeRead | CFile::shareDenyWrite)) {
CArchive arIn(&fileIn, CArchive::load);
CString strFileDescriptorName = g_strTargetDir;
strFileDescriptorName += strRoot.IsEmpty() ? fd.cFileName : strRoot + _T("\\") + fd.cFileName;
printf("Adding: %s", strFileDescriptorName);
if (g_pDatFile->Deflate(arIn, DWORD(fileIn.GetLength()),
strFileDescriptorName, g_nCompressMethod)) {
printf("\n");
g_dwTotalAdded++;
}
else {
printf(" Error!!!\n");
bResult = FALSE;
break;
}
}
else {
bResult = FALSE;
break;
}
}
}
} while(FindNextFile(hSearchHandle, &fd));
FindClose(hSearchHandle);
return bResult;
}
else {
return FALSE;
}
}
int OnAdd()
{
g_dwTotalAdded = 0;
if (g_pDatFile->Open(g_strDatFileName, CFile::modeCreate | CFile::modeNoTruncate | CFile::modeReadWrite | CFile::shareDenyWrite)) {
for(INT_PTR j = 0; j < g_FileList.GetCount(); j++) {
CString strRoot = ExtractFilePath(g_FileList[j], FALSE);
if (strRoot[0] == '\\') {
strRoot = strRoot.Right(strRoot.GetLength() - 1);
}
if (strRoot.Right(1) == '\\') {
strRoot = strRoot.Left(strRoot.GetLength() - 1);
}
if (!ProcessTree(g_FileList[j], strRoot, g_bRecurseIntoDir)) {
return 4;
}
}
printf("----------\n");
printf("%u file(s) added\n", g_dwTotalAdded);
return 0;
}
else {
printf("Error: Unable open file %s\n", LPCTSTR(g_strDatFileName));
return 1;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "stdafx.h"
#include "dat2.h"
int OnDelete()
{
CFileDescriptorBase descriptor;
DWORD dwTotalDeleted = 0;
for(INT_PTR j = 0; j < g_FileList.GetCount(); j++) {
if (g_pDatFile->FindFirst(g_FileList[j]) != -1) {
do {
descriptor = (*g_pDatFile)[g_pDatFile->GetCurrentFileIndex()];
printf("Deleting: %s", descriptor.m_strFileName);
if (g_pDatFile->Delete()) {
dwTotalDeleted++;
printf("\n");
}
else {
printf(" Error!!!\n");
return 2;
}
} while(g_pDatFile->FindNext() != -1);
}
}
printf("----------\n");
printf("%u file(s) deleted\n", dwTotalDeleted);
return 0;
}
+69
View File
@@ -0,0 +1,69 @@
#include "stdafx.h"
#include "dat2.h"
#include "Util.h"
int OnExtract()
{
CFileDescriptorBase descriptor;
DWORD dwTotalExtracted = 0;
CString strDirectory;
CString strFileName;
int nLastSlashPos;
CString strOutFileName;
CFile fileOut;
// Create output directory
if (!g_strOutFolder.IsEmpty()) {
if (!ForceCreateDirectory(g_strOutFolder)) {
printf("Error: Unable create output directory\n");
return 3;
}
}
for(INT_PTR j = 0; j < g_FileList.GetCount(); j++) {
if (g_pDatFile->FindFirst(g_FileList[j]) != -1) {
do {
descriptor = (*g_pDatFile)[g_pDatFile->GetCurrentFileIndex()];
printf("Extracting: %s", descriptor.m_strFileName);
nLastSlashPos = descriptor.m_strFileName.ReverseFind('\\');
strDirectory = descriptor.m_strFileName.Left(nLastSlashPos + 1);
strFileName = descriptor.m_strFileName.Right(descriptor.m_strFileName.GetLength() - nLastSlashPos - 1);
if (g_bExtractWithoutPaths) {
strOutFileName = g_strOutFolder + strFileName;
}
else {
if (!ForceCreateDirectory(g_strOutFolder + strDirectory)) {
return 3;
}
strOutFileName = g_strOutFolder + strDirectory + strFileName;
}
if (fileOut.Open(strOutFileName, CFile::modeCreate | CFile::modeWrite)) {
CArchive arOut(&fileOut, CArchive::store);
if (g_pDatFile->Inflate(arOut)) {
dwTotalExtracted++;
printf("\n");
}
else {
printf(" Error!!!\n");
return 3;
}
}
else {
printf(" Error!!! Unable open out file %s\n", strOutFileName);
return 3;
}
fileOut.Close();
} while(g_pDatFile->FindNext() != -1);
}
}
printf("----------\n");
printf("%u file(s) extracted\n", dwTotalExtracted);
return 0;
}
+28
View File
@@ -0,0 +1,28 @@
#include "stdafx.h"
#include "dat2.h"
int OnList()
{
CFileDescriptorBase descriptor;
DWORD dwTotalSize = 0;
printf(" Length Packed Type Name\n");
printf(" ---------- ----------- -------- ---------------\n");
for(INT_PTR i = 0; i < g_pDatFile->GetFileCount(); i++) {
descriptor = (*g_pDatFile)[i];
dwTotalSize += descriptor.m_dwFileLength;
printf("%11u %11u %s %s\n",
descriptor.m_dwFileLength,
descriptor.m_dwPackedFileLength,
(descriptor.m_nType) ? "Packed" : "Stored",
descriptor.m_strFileName);
}
printf(" ---------- ---------------\n");
printf("%11u %u file(s)\n",
dwTotalSize,
DWORD(g_pDatFile->GetFileCount()));
return 0;
}
+31
View File
@@ -0,0 +1,31 @@
#include "stdafx.h"
#include "dat2.h"
DWORD dwTotalMoved = 0;
void OutInfo(INT_PTR nIndex)
{
CFileDescriptorBase descriptor;
descriptor = (*g_pDatFile)[nIndex];
dwTotalMoved++;
printf("Moving: %s\n", descriptor.m_strFileName);
}
int OnShrink()
{
DWORD dwOldLength = g_pDatFile->GetLength();
if (g_pDatFile->Shrink(OutInfo)) {
printf("----------\n");
printf("%u file(s) moved. Old size: %u bytes. New size: %u bytes \n", dwTotalMoved, dwOldLength, g_pDatFile->GetLength());
return 0;
}
else {
printf("Error: Unable shrink file\n");
return 5;
}
}
+15
View File
@@ -0,0 +1,15 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by dat2.rc
//
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
+177
View File
@@ -0,0 +1,177 @@
#include "stdafx.h"
#include "Util.h"
CString ExtractFilePath(const CString& strFileName, BOOL bIncludeDrive)
{
CString strDrive;
CString strDirectory;
LPTSTR lpszDrive = strDrive.GetBufferSetLength(_MAX_DRIVE);
LPTSTR lpszDirectory = strDirectory.GetBufferSetLength(_MAX_DIR);
_splitpath(strFileName, lpszDrive, lpszDirectory, NULL, NULL);
strDrive.ReleaseBuffer();
strDirectory.ReleaseBuffer();
if (bIncludeDrive) {
return (strDrive + strDirectory);
}
else {
return strDirectory;
}
}
CString ExtractFileName(const CString& strFileName)
{
CString strName;
CString strExtension;
LPTSTR lpszName = strName.GetBufferSetLength(_MAX_FNAME);
LPTSTR lpszExtension = strExtension.GetBufferSetLength(_MAX_EXT);
_splitpath(strFileName, NULL, NULL, lpszName, lpszExtension);
strName.ReleaseBuffer();
strExtension.ReleaseBuffer();
return (strName + strExtension);
}
BOOL DirectoryExist(const CString& strDirectory)
{
DWORD dwResult = ::GetFileAttributes(strDirectory);
return ((dwResult != INVALID_FILE_ATTRIBUTES) &&
((dwResult & FILE_ATTRIBUTE_DIRECTORY) != 0));
}
BOOL ForceCreateDirectory(CString strDirectory)
{
if (strDirectory.GetLength() == 0) {
return TRUE;
}
if (strDirectory.Right(1) == _T("\\")) {
strDirectory = strDirectory.Left(strDirectory.GetLength() - 1);
}
if ((strDirectory.GetLength() < 3) ||
DirectoryExist(strDirectory) ||
(ExtractFilePath(strDirectory) == strDirectory)) {
return TRUE;
}
return (ForceCreateDirectory(ExtractFilePath(strDirectory)) &&
::CreateDirectory(strDirectory, NULL));
}
UINT ReadMSBWord(CArchive& ar, WORD& wValue)
{
BYTE* pBuffer = reinterpret_cast<BYTE*>(&wValue);
return (ar.Read(pBuffer + 1, 1) + ar.Read(pBuffer, 1));
}
UINT ReadMSBDWord(CArchive& ar, DWORD& dwValue)
{
BYTE* pBuffer = reinterpret_cast<BYTE*>(&dwValue);
return (ar.Read(pBuffer + 3, 1) + ar.Read(pBuffer + 2, 1) +
ar.Read(pBuffer + 1, 1) + ar.Read(pBuffer, 1));
}
UINT ReadMSBWord(CFile& file, WORD& wValue)
{
BYTE* pBuffer = reinterpret_cast<BYTE*>(&wValue);
return (file.Read(pBuffer + 1, 1) + file.Read(pBuffer, 1));
}
UINT ReadMSBDWord(CFile& file, DWORD& dwValue)
{
BYTE* pBuffer = reinterpret_cast<BYTE*>(&dwValue);
return (file.Read(pBuffer + 3, 1) + file.Read(pBuffer + 2, 1) +
file.Read(pBuffer + 1, 1) + file.Read(pBuffer, 1));
}
BOOL ReadString(CArchive& ar, CString& strString)
{
BYTE nStrLength;
if (ar.Read(&nStrLength, 1) != 1) {
return FALSE;
}
LPTSTR lpszString = strString.GetBufferSetLength(nStrLength + 1);
DWORD dwRead = ar.Read(lpszString, nStrLength);
strString.ReleaseBuffer(nStrLength);
if (dwRead != nStrLength) {
return FALSE;
}
else {
return TRUE;
}
}
BOOL ReadString(CFile& file, CString& strString)
{
BYTE nStrLength;
if (file.Read(&nStrLength, 1) != 1) {
return FALSE;
}
LPTSTR lpszString = strString.GetBufferSetLength(nStrLength + 1);
DWORD dwRead = file.Read(lpszString, nStrLength);
strString.ReleaseBuffer(nStrLength);
if (dwRead != nStrLength) {
return FALSE;
}
else {
return TRUE;
}
}
void WriteMSBWord(CArchive& ar, WORD wValue)
{
BYTE* pBuffer = reinterpret_cast<BYTE*>(&wValue);
ar.Write(pBuffer + 1, 1);
ar.Write(pBuffer, 1);
}
void WriteMSBDWord(CArchive& ar, DWORD dwValue)
{
BYTE* pBuffer = reinterpret_cast<BYTE*>(&dwValue);
ar.Write(pBuffer + 3, 1);
ar.Write(pBuffer + 2, 1);
ar.Write(pBuffer + 1, 1);
ar.Write(pBuffer, 1);
}
void WriteMSBWord(CFile& file, WORD wValue)
{
BYTE* pBuffer = reinterpret_cast<BYTE*>(&wValue);
file.Write(pBuffer + 1, 1);
file.Write(pBuffer, 1);
}
void WriteMSBDWord(CFile& file, DWORD dwValue)
{
BYTE* pBuffer = reinterpret_cast<BYTE*>(&dwValue);
file.Write(pBuffer + 3, 1);
file.Write(pBuffer + 2, 1);
file.Write(pBuffer + 1, 1);
file.Write(pBuffer, 1);
}
void WriteString(CArchive& ar, CString& strString)
{
BYTE nStrLength = BYTE(strString.GetLength());
ar.Write(&nStrLength, 1);
ar.Write(LPCTSTR(strString), nStrLength);
}
void WriteString(CFile& file, CString& strString)
{
BYTE nStrLength = BYTE(strString.GetLength());
file.Write(&nStrLength, 1);
file.Write(LPCTSTR(strString), nStrLength);
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
CString ExtractFileName(const CString& strFileName);
CString ExtractFilePath(const CString& strFileName, BOOL bIncludeDrive = TRUE);
BOOL DirectoryExist(const CString& strDirectory);
BOOL ForceCreateDirectory(CString strDirectory);
UINT ReadMSBWord(CArchive& ar, WORD& wValue);
UINT ReadMSBDWord(CArchive& ar, DWORD& dwValue);
UINT ReadMSBWord(CFile& file, WORD& wValue);
UINT ReadMSBDWord(CFile& file, DWORD& dwValue);
BOOL ReadString(CArchive& ar, CString& strString);
BOOL ReadString(CFile& file, CString& strString);
void WriteMSBWord(CArchive& ar, WORD wValue);
void WriteMSBDWord(CArchive& ar, DWORD dwValue);
void WriteMSBWord(CFile& file, WORD wValue);
void WriteMSBDWord(CFile& file, DWORD dwValue);
void WriteString(CArchive& ar, CString& strString);
void WriteString(CFile& file, CString& strString);
+219
View File
@@ -0,0 +1,219 @@
// XGetopt.cpp Version 1.2
//
// Author: Hans Dietrich
// hdietrich2@hotmail.com
//
// Description:
// XGetopt.cpp implements getopt(), a function to parse command lines.
//
// History
// Version 1.2 - 2003 May 17
// - Added Unicode support
//
// Version 1.1 - 2002 March 10
// - Added example to XGetopt.cpp module header
//
// This software is released into the public domain.
// You are free to use it in any way you like.
//
// This software is provided "as is" with no expressed
// or implied warranty. I accept no liability for any
// damage or loss of business that this software may cause.
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// if you are using precompiled headers then include this line:
#include "stdafx.h"
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// if you are not using precompiled headers then include these lines:
//#include <windows.h>
//#include <stdio.h>
//#include <tchar.h>
///////////////////////////////////////////////////////////////////////////////
#include "XGetopt.h"
///////////////////////////////////////////////////////////////////////////////
//
// X G e t o p t . c p p
//
//
// NAME
// getopt -- parse command line options
//
// SYNOPSIS
// int getopt(int argc, TCHAR *argv[], TCHAR *optstring)
//
// extern TCHAR *optarg;
// extern int optind;
//
// DESCRIPTION
// The getopt() function parses the command line arguments. Its
// arguments argc and argv are the argument count and array as
// passed into the application on program invocation. In the case
// of Visual C++ programs, argc and argv are available via the
// variables __argc and __argv (double underscores), respectively.
// getopt returns the next option letter in argv that matches a
// letter in optstring. (Note: Unicode programs should use
// __targv instead of __argv. Also, all character and string
// literals should be enclosed in _T( ) ).
//
// optstring is a string of recognized option letters; if a letter
// is followed by a colon, the option is expected to have an argument
// that may or may not be separated from it by white space. optarg
// is set to point to the start of the option argument on return from
// getopt.
//
// Option letters may be combined, e.g., "-ab" is equivalent to
// "-a -b". Option letters are case sensitive.
//
// getopt places in the external variable optind the argv index
// of the next argument to be processed. optind is initialized
// to 0 before the first call to getopt.
//
// When all options have been processed (i.e., up to the first
// non-option argument), getopt returns EOF, optarg will point
// to the argument, and optind will be set to the argv index of
// the argument. If there are no non-option arguments, optarg
// will be set to NULL.
//
// The special option "--" may be used to delimit the end of the
// options; EOF will be returned, and "--" (and everything after it)
// will be skipped.
//
// RETURN VALUE
// For option letters contained in the string optstring, getopt
// will return the option letter. getopt returns a question mark (?)
// when it encounters an option letter not included in optstring.
// EOF is returned when processing is finished.
//
// BUGS
// 1) Long options are not supported.
// 2) The GNU double-colon extension is not supported.
// 3) The environment variable POSIXLY_CORRECT is not supported.
// 4) The + syntax is not supported.
// 5) The automatic permutation of arguments is not supported.
// 6) This implementation of getopt() returns EOF if an error is
// encountered, instead of -1 as the latest standard requires.
//
// EXAMPLE
// BOOL CMyApp::ProcessCommandLine(int argc, TCHAR *argv[])
// {
// int c;
//
// while ((c = getopt(argc, argv, _T("aBn:"))) != EOF)
// {
// switch (c)
// {
// case _T('a'):
// TRACE(_T("option a\n"));
// //
// // set some flag here
// //
// break;
//
// case _T('B'):
// TRACE( _T("option B\n"));
// //
// // set some other flag here
// //
// break;
//
// case _T('n'):
// TRACE(_T("option n: value=%d\n"), atoi(optarg));
// //
// // do something with value here
// //
// break;
//
// case _T('?'):
// TRACE(_T("ERROR: illegal option %s\n"), argv[optind-1]);
// return FALSE;
// break;
//
// default:
// TRACE(_T("WARNING: no handler for option %c\n"), c);
// return FALSE;
// break;
// }
// }
// //
// // check for non-option args here
// //
// return TRUE;
// }
//
///////////////////////////////////////////////////////////////////////////////
TCHAR *optarg; // global argument pointer
int optind = 0; // global argv index
int getopt(int argc, TCHAR *argv[], TCHAR *optstring)
{
static TCHAR *next = NULL;
if (optind == 0)
next = NULL;
optarg = NULL;
if (next == NULL || *next == _T('\0'))
{
if (optind == 0)
optind++;
if (optind >= argc || argv[optind][0] != _T('-') || argv[optind][1] == _T('\0'))
{
optarg = NULL;
if (optind < argc)
optarg = argv[optind];
return EOF;
}
if (_tcscmp(argv[optind], _T("--")) == 0)
{
optind++;
optarg = NULL;
if (optind < argc)
optarg = argv[optind];
return EOF;
}
next = argv[optind];
next++; // skip past -
optind++;
}
TCHAR c = *next++;
TCHAR *cp = _tcschr(optstring, c);
if (cp == NULL || c == _T(':'))
return _T('?');
cp++;
if (*cp == _T(':'))
{
if (*next != _T('\0'))
{
optarg = next;
next = NULL;
}
else if (optind < argc)
{
optarg = argv[optind];
optind++;
}
else
{
return _T('?');
}
}
return c;
}
+23
View File
@@ -0,0 +1,23 @@
// XGetopt.h Version 1.2
//
// Author: Hans Dietrich
// hdietrich2@hotmail.com
//
// This software is released into the public domain.
// You are free to use it in any way you like.
//
// This software is provided "as is" with no expressed
// or implied warranty. I accept no liability for any
// damage or loss of business that this software may cause.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef XGETOPT_H
#define XGETOPT_H
extern int optind, opterr;
extern TCHAR *optarg;
int getopt(int argc, TCHAR *argv[], TCHAR *optstring);
#endif //XGETOPT_H
+320
View File
@@ -0,0 +1,320 @@
// dat2.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "dat2.h"
#include "DatFile1.h"
#include "DatFile2.h"
#include "XGetopt.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif /* _DEBUG */
// Globals
Command g_Command = COMMAND_UNKNOWN;
int g_nCompressMethod = 9;
BOOL g_bRecurseIntoDir = FALSE;
BOOL g_bExtractWithoutPaths = FALSE;
CString g_strOutFolder;
CString g_strDatFileName;
CStringArray g_FileList;
BOOL g_bFallout1Dat = FALSE;
CString g_strTargetDir = "";
// Dat-file
CDatFile1 g_DatFile1;
CDatFile2 g_DatFile2;
CDatFileBase* g_pDatFile = NULL;
// Functions
void PrintUsage(char* lpszFileName);
int ParseCommandLine(int argc, char* argv[]);
// The one and only application object
CWinApp theApp;
int main(int argc, char* argv[])
{
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) {
printf("Fatal Error: MFC initialization failed\n");
return 1;
}
else {
printf("Fallout DAT-files packer/unpacker, version 2.32\n");
printf("Copyright (C) Anchorite (TeamX), 2004-2006\n");
printf("anchorite2001@yandex.ru\n");
printf("\n");
// for(int i = 0; i < argc; i++) {
// printf("argv[%d] = %s\n", i, argv[i]);
// }
if (argc < 3) {
PrintUsage(argv[0]);
return 0;
}
int nResult = ParseCommandLine(argc, argv);
switch(nResult) {
case -1: {
printf("Error: Invalid command\n");
return 1;
}
case -2: {
printf("Error: Name of output directory is omitted\n");
return 1;
}
case -3: {
printf("Error: Name of dat-file is omitted\n");
return 1;
}
case -4: {
printf("Error: List of files is omitted\n");
return 1;
}
case -5: {
printf("Error: Unable open response file\n");
return 1;
}
}
nResult = 0;
UINT nOpenMode;
switch(g_Command) {
case COMMAND_EXTRACT:
nOpenMode = CFile::modeRead | CFile::shareDenyWrite;
break;
case COMMAND_DELETE:
nOpenMode = CFile::modeReadWrite | CFile::shareDenyWrite;
break;
case COMMAND_LIST:
nOpenMode = CFile::modeRead | CFile::shareDenyWrite;
break;
case COMMAND_SHRINK:
nOpenMode = CFile::modeReadWrite | CFile::shareDenyWrite;
}
if (g_Command == COMMAND_ADD) {
if (g_bFallout1Dat) {
g_pDatFile = &g_DatFile1;
}
else {
g_pDatFile = &g_DatFile2;
}
}
else {
if (g_DatFile2.Open(g_strDatFileName, nOpenMode)) {
g_pDatFile = &g_DatFile2;
}
else if (g_DatFile1.Open(g_strDatFileName, nOpenMode)) {
g_pDatFile = &g_DatFile1;
}
else {
printf("Error: Unable open file %s\n", LPCTSTR(g_strDatFileName));
return 1;
}
}
switch(g_Command) {
case COMMAND_ADD:
nResult = OnAdd();
break;
case COMMAND_EXTRACT:
nResult = OnExtract();
break;
case COMMAND_DELETE:
nResult = OnDelete();
break;
case COMMAND_LIST:
nResult = OnList();
break;
case COMMAND_SHRINK:
nResult = OnShrink();
}
printf("\n");
printf("Flushing buffers...\n");
g_pDatFile->Flush();
return nResult;
}
}
void PrintUsage(char* lpszFileName)
{
printf("Usage: %s <command> [options] [-t dir] [-d dir] dat-file [list | @response-file]\n", lpszFileName);
printf("\n");
printf("Commands\n");
printf(" a: Add files to dat-file. Create new if dat-file not exist\n");
printf(" x: Extract files from dat-file\n");
printf(" d: Delete files from dat-file (only info about files)\n");
printf(" l: List files in dat-file\n");
printf(" k: Shrink dat-file\n");
printf("\n");
printf("Options\n");
printf(" -s: create Fallout 1 dat-file\n");
printf(" -r: recurse into directories\n");
printf(" -0..9: Compression method\n");
printf(" (Fallout1: 0 - store, other numbers - compress (default)\n");
printf(" (Fallout2: 0 - store, 1 - best speed, 9 - best compression (default)\n");
printf(" -p: extract without paths\n");
printf(" -d: extract files into specified directory\n");
printf(" -t: add files to specified directory of dat-file\n");
printf(" --: end of options\n");
printf("\n");
}
int ParseCommandLine(int argc, char* argv[])
{
// Command
if (memcmp(argv[1], "a", lstrlen(argv[1])) == 0) {
g_Command = COMMAND_ADD;
}
else if (memcmp(argv[1], "x", lstrlen(argv[1])) == 0) {
g_Command = COMMAND_EXTRACT;
}
else if (memcmp(argv[1], "d", lstrlen(argv[1])) == 0) {
g_Command = COMMAND_DELETE;
}
else if (memcmp(argv[1], "l", lstrlen(argv[1])) == 0) {
g_Command = COMMAND_LIST;
}
else if (memcmp(argv[1], "k", lstrlen(argv[1])) == 0) {
g_Command = COMMAND_SHRINK;
}
else {
return -1;
}
// Options
argc--;
argv++;
int c;
while((c = getopt(argc, argv, "r0123456789pd:st:")) != EOF) {
switch(c) {
case 'r':
g_bRecurseIntoDir = TRUE;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
g_nCompressMethod = c - '0';
break;
case 'p':
g_bExtractWithoutPaths = TRUE;
break;
case 'd':
g_strOutFolder = optarg;
if ((!g_strOutFolder.IsEmpty()) && (g_strOutFolder.Right(1) != "\\")) {
g_strOutFolder += "\\";
}
break;
case 's':
g_bFallout1Dat = TRUE;
break;
case 't':
g_strTargetDir = optarg;
if ((!g_strTargetDir.IsEmpty()) && (g_strTargetDir.Right(1) != "\\")) {
g_strTargetDir += "\\";
}
break;
case '?':
return -2;
default: // No more options
break;
}
}
// Dat-file
if (optind < argc) {
g_strDatFileName = argv[optind];
}
if (g_strDatFileName.IsEmpty()) {
return -3;
}
if ((g_strDatFileName.Right(4).MakeLower() != ".dat") || (g_strDatFileName == ".dat")) {
g_strDatFileName += ".dat";
}
// List of files
CString strArgument;
for(int i = optind + 1; i < argc; i++) {
strArgument = argv[i];
int nArglength = strArgument.GetLength();
if ((i == optind + 1) && (nArglength > 1) && (strArgument[0] == '@')) {
CStdioFile fileResponse;
if (!fileResponse.Open(strArgument.Right(nArglength - 1), CFile::modeRead | CFile::shareDenyWrite | CFile::typeText)) {
return -5;
};
CArchive arResponse(&fileResponse, CArchive::load);
while(arResponse.ReadString(strArgument)) {
if (!strArgument.IsEmpty()) {
g_FileList.Add(strArgument);
}
}
break;
}
else {
g_FileList.Add(strArgument);
}
}
if ((g_FileList.GetSize() == 0)) {
if (g_Command == COMMAND_EXTRACT) {
g_FileList.Add("*");
}
else if ((g_Command != COMMAND_LIST) && (g_Command != COMMAND_SHRINK)) {
return -4;
}
}
// for(int i = 0; i < g_FileList.GetSize(); i++) {
// printf("g_FileList[%d] = %s\n", i, g_FileList[i]);
// }
return 0;
}

Some files were not shown because too many files have changed in this diff Show More