#pragma once
#include <WTypes.h>
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
#define __INTEL_BYTE_ORDER__ 1
#endif
class FArchive
{
public:
// FArchive interface.
virtual ~FArchive()
{
}
virtual void Serialize(void* V, INT Length)
{
}
virtual void SerializeBits(void* V, INT LengthBits)
{
Serialize(V, (LengthBits + 7) / 8);
if (IsLoading())
((BYTE*)V)[LengthBits / 8] &= ((1 << (LengthBits & 7)) - 1);
}
virtual void SerializeInt(DWORD& Value, DWORD Max)
{
*this << *(DWORD*)Value;
}
virtual void Preload(void* Object)
{
}
virtual void CountBytes(SIZE_T InNum, SIZE_T InMax)
{
}
virtual FArchive& operator<<(class FName& N)
{
return *this;
}
virtual FArchive& operator<<(class UObject*& Res)
{
return *this;
}
virtual INT MapName(FName* Name)
{
return 0;
}
virtual INT MapObject(UObject* Object)
{
return 0;
}
virtual INT Tell()
{
return -1;
}
virtual INT TotalSize()
{
return -1;
}
virtual BOOL AtEnd()
{
INT Pos = Tell();
return Pos != -1 && Pos >= TotalSize();
}
virtual BOOL AtStopper()
{
BOOL res = FALSE;
INT Size = TotalSize();
if (Size != -1)
{
if (ArStopper != -1 && Size >= ArStopper)
res = TRUE;
}
return res;
}
virtual void SetStopper(INT Stopper)
{
ArStopper = Stopper;
}
virtual void Seek(INT InPos)
{
}
virtual void AttachLazyLoader(void* LazyLoader)
{
}
virtual void DetachLazyLoader(void* LazyLoader)
{
}
virtual void AttachRoughLoader(void* RoughLoader)
{
}
virtual void DetachRoughLoader(void* RoughLoader)
{
}
virtual void Precache(INT HintCount)
{
}
virtual void Flush()
{
}
virtual BOOL Close()
{
return !ArIsError;
}
virtual BOOL GetError()
{
return ArIsError;
}
virtual INT GetCurrentEncryptVersion()
{
return 0;
}
// Hardcoded datatype routines that may not be overridden.
FArchive& ByteOrderSerialize(void* V, INT Length)
{
#if __INTEL_BYTE_ORDER__
Serialize(V, Length);
#else
if( ArIsPersistent )
{
// Transferring between memory and file, so flip the byte order.
for( INT i=Length-1; i>=0; i-- )
Serialize( (BYTE*)V + i, 1 );
}
else
{
// Transferring around within memory, so keep the byte order.
Serialize( V, Length );
}
#endif
return *this;
}
// Constructor.
FArchive()
: ArVer(/*PACKAGE_FILE_VERSION*/0x7B)
, ArNetVer(/*ENGINE_NEGOTIATION_VERSION*/0x7D0)
, ArLicenseeVer(/*PACKAGE_FILE_VERSION_LICENSEE*/0x1E)
, ArIsLoading(0)
, ArIsSaving(0)
, ArIsTrans(0)
, ArIsPersistent(0)
, ArIsError(0)
, ArForEdit(0)
, ArForClient(0)
, ArForServer(0)
, ArUnk1(0)
, ArStopper(-1)
{
}
// Status accessors.
INT Ver()
{
return ArVer;
}
INT NetVer()
{
return ArNetVer & 0x7fffffff;
}
INT LicenseeVer()
{
return ArLicenseeVer;
}
BOOL IsLoading()
{
return ArIsLoading;
}
BOOL IsSaving()
{
return ArIsSaving;
}
BOOL IsTrans()
{
return ArIsTrans;
}
BOOL IsNet()
{
return (ArNetVer & 0x80000000) != 0;
}
BOOL IsPersistent()
{
return ArIsPersistent;
}
BOOL IsError()
{
return ArIsError;
}
BOOL ForEdit()
{
return ArForEdit;
}
BOOL ForClient()
{
return ArForClient;
}
BOOL ForServer()
{
return ArForServer;
}
// Friend archivers.
friend FArchive& operator<<(FArchive& Ar, PCHAR& C)
{
Ar.Serialize(&C, 1);
return Ar;
}
friend FArchive& operator<<(FArchive& Ar, BYTE& B)
{
Ar.Serialize(&B, 1);
return Ar;
}
friend FArchive& operator<<(FArchive& Ar, CHAR& B)
{
Ar.Serialize(&B, 1);
return Ar;
}
friend FArchive& operator<<(FArchive& Ar, WORD& W)
{
Ar.ByteOrderSerialize(&W, sizeof(W));
return Ar;
}
friend FArchive& operator<<(FArchive& Ar, SHORT& S)
{
Ar.ByteOrderSerialize(&S, sizeof(S));
return Ar;
}
friend FArchive& operator<<(FArchive& Ar, DWORD& D)
{
Ar.ByteOrderSerialize(&D, sizeof(D));
return Ar;
}
friend FArchive& operator<<(FArchive& Ar, INT& I)
{
Ar.ByteOrderSerialize(&I, sizeof(I));
return Ar;
}
friend FArchive& operator<<(FArchive& Ar, FLOAT& F)
{
Ar.ByteOrderSerialize(&F, sizeof(F));
return Ar;
}
friend FArchive& operator<<(FArchive& Ar, DWORD64& Q)
{
Ar.ByteOrderSerialize(&Q, sizeof(Q));
return Ar;
}
friend FArchive& operator<<(FArchive& Ar, long long& S)
{
Ar.ByteOrderSerialize(&S, sizeof(S));
return Ar;
}
friend FArchive& operator<<(FArchive& Ar, /*FTime*/INT& F);
public:
// Status variables.
INT ArVer;
INT ArNetVer;
INT ArLicenseeVer;
BOOL ArIsLoading;
BOOL ArIsSaving;
BOOL ArIsTrans;
BOOL ArIsPersistent;
BOOL ArForEdit;
BOOL ArForClient;
BOOL ArForServer;
BOOL ArIsError;
BOOL ArUnk1;
INT ArStopper;
};
class FArchiveFileReader : public FArchive
{
public:
FArchiveFileReader(HANDLE InFile, void* InError, INT InSize)
: File(InFile)
, Error(InError)
, Size(InSize)
, Pos(0)
, BufferBase(0)
, BufferCount(0)
, SleepFactor(0.0f)
{
SetFilePointer(File, 0, 0, FILE_BEGIN);
ArIsLoading = ArIsPersistent = 1;
}
~FArchiveFileReader()
{
if (File)
{
FArchiveFileReader::Close();
}
}
void Precache(INT HintCount) override
{
BufferBase = Pos;
BufferCount = min( min( HintCount, (INT)(ARRAYSIZE(Buffer) - (Pos & (ARRAYSIZE(Buffer)-1))) ), Size-Pos );
if (!ReadFile(File, Buffer, BufferCount) && BufferCount != 0)
{
ArIsError = 1;
//Error->Logf( TEXT("fread failed: BufferCount=%i"), BufferCount );
return;
}
}
void Seek(INT InPos) override
{
//assert(InPos >= 0);
//assert(InPos <= Size);
if (SetFilePointer(File, InPos, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
{
ArIsError = 1;
//Error->Logf( TEXT("Seek failed: %i/%i: %i"), InPos, Size, Pos );
}
Pos = InPos;
BufferBase = Pos;
BufferCount = 0;
}
INT Tell() override
{
return Pos;
}
INT TotalSize() override
{
return Size;
}
BOOL Close() override
{
if (File)
CloseHandle(File);
File = NULL;
return !ArIsError;
}
void Serialize(void* V, INT Length) override
{
while (Length > 0)
{
INT Copy = min( Length, BufferBase+BufferCount-Pos );
if (Copy == 0)
{
if (Length >= ARRAYSIZE(Buffer))
{
if (!ReadFile(File, V, Length))
{
ArIsError = 1;
//Error->Logf( TEXT("fread failed: Length=%i"), Length );
}
Pos += Length;
BufferBase += Length;
return;
}
Precache(MAXINT);
Copy = min( Length, BufferBase + BufferCount - Pos );
if (Copy <= 0)
{
ArIsError = 1;
//Error->Logf( TEXT("ReadFile beyond EOF %i+%i/%i"), Pos, Length, Size );
}
if (ArIsError)
return;
}
::memcpy(V, Buffer + Pos - BufferBase, Copy);
Pos += Copy;
Length -= Copy;
V = (BYTE*)V + Copy;
}
}
BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead)
{
DWORD dwRead = 0;
BOOL readOk = ::ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, &dwRead, 0) && nNumberOfBytesToRead == dwRead;
return readOk;
}
public:
HANDLE File;
void* Error;
INT Size;
INT Pos;
INT BufferBase;
INT BufferCount;
float SleepFactor;
BYTE Buffer[1024];
};
extern wchar_t GLineage2Ver[12];
DWORD Get121Key(const wchar_t* FileName);
class FL2FileDecryptArchive : public FArchive
{
public:
FL2FileDecryptArchive(HANDLE InFile, void* InError, INT InSize, const wchar_t* FileName) : ArchiveFileReader(nullptr), CryptVer(0), HeaderSize(0), CryptKey(0xAC)
{
FArchiveFileReader* reader = new FArchiveFileReader(InFile, InError, GetFileSize(InFile, 0));
ArchiveFileReader = reader;
if (InSize <= 0x18)
{
ArchiveFileReader->Seek(0);
}
else
{
for (int i = 0; i < 11; ++i)
{
wchar_t c;
ArchiveFileReader->Serialize(&c, sizeof(c));
if (c != GLineage2Ver[i])
{
ArchiveFileReader->Seek(0);
return;
}
}
wchar_t buf_ver[3];
ArchiveFileReader->Serialize(&buf_ver[0], sizeof(wchar_t));
ArchiveFileReader->Serialize(&buf_ver[1], sizeof(wchar_t));
ArchiveFileReader->Serialize(&buf_ver[2], sizeof(wchar_t));
long ver = wcstol(buf_ver, 0, 10);
CryptVer = ver;
HeaderSize = 28;
if (CryptVer == 111)
{
CryptKey = 0xAC;
}
else if (CryptVer == 121)
{
CryptKey = static_cast<BYTE>(Get121Key(FileName));
}
else
{
CryptKey = 0;
}
}
}
~FL2FileDecryptArchive()
{
if(ArchiveFileReader)
{
delete ArchiveFileReader;
ArchiveFileReader = 0;
}
}
void Serialize(void* V, INT Length) override
{
int ver = CryptVer;
if (ver > 212)
{
if (ver != 311 && ver - 411 > 2)
return;
ArchiveFileReader->Serialize(V, Length);
return;
}
if (ver >= 211 || !ver)
{
ArchiveFileReader->Serialize(V, Length);
return;
}
if (ver == 111 || ver == 121)
{
ArchiveFileReader->Serialize(V, Length);
for (int i = 0; i < Length; ++i)
*((BYTE*)V + i) ^= this->CryptKey;
}
}
INT Tell() override
{
int ver = CryptVer;
if (ver > 212)
{
if (ver != 311 && ver - 411 > 2)
return -1;
return ArchiveFileReader->Tell() - this->HeaderSize;
}
if (ver >= 211)
return ArchiveFileReader->Tell() - this->HeaderSize;
if (!ver)
return ArchiveFileReader->Tell();
if (ver == 111 || ver == 121)
return ArchiveFileReader->Tell() - this->HeaderSize;
return -1;
}
INT TotalSize() override
{
int ver = CryptVer;
if (ver > 212)
{
if (ver != 311 && ver - 411 > 2)
return -1;
return ArchiveFileReader->TotalSize() - this->HeaderSize;
}
if (ver >= 211)
return ArchiveFileReader->TotalSize() - this->HeaderSize;
if (!ver)
return ArchiveFileReader->TotalSize();
if (ver == 111 || ver == 121)
return ArchiveFileReader->TotalSize() - this->HeaderSize;
return -1;
}
void Seek(INT InPos) override
{
int ver = this->CryptVer;
if (ver > 212)
{
if (ver != 311 && ver - 411 > 2)
return;
ArchiveFileReader->Seek(InPos + this->HeaderSize);
return;
}
if (ver >= 211)
{
ArchiveFileReader->Seek(InPos + this->HeaderSize);
return;
}
if (!ver)
{
ArchiveFileReader->Seek(InPos);
return;
}
if (ver == 111 || ver == 121)
ArchiveFileReader->Seek(InPos + this->HeaderSize);
}
void Precache(INT HintCount) override
{
int ver = this->CryptVer;
if (ver > 212)
{
if (ver != 311 && (unsigned int)(ver - 411) > 2)
return;
ArchiveFileReader->Precache(HintCount);
return;
}
if (ver >= 211 || !ver)
{
ArchiveFileReader->Precache(HintCount);
}
else if (ver == 111 || ver == 121)
{
ArchiveFileReader->Precache(HintCount);
}
}
BOOL Close() override
{
int ver = this->CryptVer;
if (ver > 212)
{
if (ver != 311 && (unsigned int)(ver - 411) > 2)
return ArForServer == 0;
return ArchiveFileReader->Close();
}
if (ver >= 211 || !ver)
{
return ArchiveFileReader->Close();
}
if (ver == 111 || ver == 121)
{
return ArchiveFileReader->Close();
}
return ArForServer == 0;
}
INT GetCurrentEncryptVersion() override
{
return CryptVer;
}
public:
FArchiveFileReader* ArchiveFileReader;
int CryptVer;
int HeaderSize;
BYTE CryptKey;
};