mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-29 07:02:03 +00:00
- Added support for 7z archives.
SVN r1545 (trunk)
This commit is contained in:
parent
9040710e62
commit
7e7429e3d2
27 changed files with 3155 additions and 177 deletions
|
@ -1,4 +1,7 @@
|
|||
April 13, 2009 (Changes by Graf Zahl)
|
||||
April 14, 2009
|
||||
- Added support for 7z archives.
|
||||
|
||||
April 13, 2009 (Changes by Graf Zahl)
|
||||
- Added -noautoload option.
|
||||
- Added default Raven automap colors set. Needs to be tested because I can't
|
||||
compare against the DOS version myself.
|
||||
|
|
36
lzma/C/7zBuf.c
Normal file
36
lzma/C/7zBuf.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* 7zBuf.c -- Byte Buffer
|
||||
2008-03-28
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#include "7zBuf.h"
|
||||
|
||||
void Buf_Init(CBuf *p)
|
||||
{
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
}
|
||||
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
|
||||
{
|
||||
p->size = 0;
|
||||
if (size == 0)
|
||||
{
|
||||
p->data = 0;
|
||||
return 1;
|
||||
}
|
||||
p->data = (Byte *)alloc->Alloc(alloc, size);
|
||||
if (p->data != 0)
|
||||
{
|
||||
p->size = size;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Buf_Free(CBuf *p, ISzAlloc *alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->data);
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
}
|
31
lzma/C/7zBuf.h
Normal file
31
lzma/C/7zBuf.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* 7zBuf.h -- Byte Buffer
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_BUF_H
|
||||
#define __7Z_BUF_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte *data;
|
||||
size_t size;
|
||||
} CBuf;
|
||||
|
||||
void Buf_Init(CBuf *p);
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);
|
||||
void Buf_Free(CBuf *p, ISzAlloc *alloc);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte *data;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
} CDynBuf;
|
||||
|
||||
void DynBuf_Construct(CDynBuf *p);
|
||||
void DynBuf_SeekToBeg(CDynBuf *p);
|
||||
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);
|
||||
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);
|
||||
|
||||
#endif
|
35
lzma/C/7zCrc.c
Normal file
35
lzma/C/7zCrc.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* 7zCrc.c -- CRC32 calculation
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#include "7zCrc.h"
|
||||
|
||||
#define kCrcPoly 0xEDB88320
|
||||
UInt32 g_CrcTable[256];
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable(void)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
UInt32 r = i;
|
||||
int j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
g_CrcTable[i] = r;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0 ; size--, p++)
|
||||
v = CRC_UPDATE_BYTE(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
||||
{
|
||||
return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF;
|
||||
}
|
24
lzma/C/7zCrc.h
Normal file
24
lzma/C/7zCrc.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* 7zCrc.h -- CRC32 calculation
|
||||
2008-03-13
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#ifndef __7Z_CRC_H
|
||||
#define __7Z_CRC_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
extern UInt32 g_CrcTable[];
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable(void);
|
||||
|
||||
#define CRC_INIT_VAL 0xFFFFFFFF
|
||||
#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF)
|
||||
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
|
||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
|
||||
|
||||
#endif
|
169
lzma/C/7zStream.c
Normal file
169
lzma/C/7zStream.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
/* 7zStream.c -- 7z Stream functions
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
RINOK(stream->Read(stream, buf, &processed));
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((Byte *)buf + processed);
|
||||
size -= processed;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)
|
||||
{
|
||||
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||
}
|
||||
|
||||
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf)
|
||||
{
|
||||
size_t processed = 1;
|
||||
RINOK(stream->Read(stream, buf, &processed));
|
||||
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
|
||||
}
|
||||
|
||||
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
|
||||
{
|
||||
Int64 t = offset;
|
||||
return stream->Seek(stream, &t, SZ_SEEK_SET);
|
||||
}
|
||||
|
||||
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
|
||||
{
|
||||
void *lookBuf;
|
||||
if (*size == 0)
|
||||
return SZ_OK;
|
||||
RINOK(stream->Look(stream, &lookBuf, size));
|
||||
memcpy(buf, lookBuf, *size);
|
||||
return stream->Skip(stream, *size);
|
||||
}
|
||||
|
||||
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
RINOK(stream->Read(stream, buf, &processed));
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((Byte *)buf + processed);
|
||||
size -= processed;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
|
||||
{
|
||||
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||
}
|
||||
|
||||
static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size)
|
||||
{
|
||||
SRes res = SZ_OK;
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size > 0)
|
||||
{
|
||||
p->pos = 0;
|
||||
size2 = LookToRead_BUF_SIZE;
|
||||
res = p->realStream->Read(p->realStream, p->buf, &size2);
|
||||
p->size = size2;
|
||||
}
|
||||
if (size2 < *size)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size)
|
||||
{
|
||||
SRes res = SZ_OK;
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size > 0)
|
||||
{
|
||||
p->pos = 0;
|
||||
if (*size > LookToRead_BUF_SIZE)
|
||||
*size = LookToRead_BUF_SIZE;
|
||||
res = p->realStream->Read(p->realStream, p->buf, size);
|
||||
size2 = p->size = *size;
|
||||
}
|
||||
if (size2 < *size)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Skip(void *pp, size_t offset)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
p->pos += offset;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
size_t rem = p->size - p->pos;
|
||||
if (rem == 0)
|
||||
return p->realStream->Read(p->realStream, buf, size);
|
||||
if (rem > *size)
|
||||
rem = *size;
|
||||
memcpy(buf, p->buf + p->pos, rem);
|
||||
p->pos += rem;
|
||||
*size = rem;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
p->pos = p->size = 0;
|
||||
return p->realStream->Seek(p->realStream, pos, origin);
|
||||
}
|
||||
|
||||
void LookToRead_CreateVTable(CLookToRead *p, int lookahead)
|
||||
{
|
||||
p->s.Look = lookahead ?
|
||||
LookToRead_Look_Lookahead :
|
||||
LookToRead_Look_Exact;
|
||||
p->s.Skip = LookToRead_Skip;
|
||||
p->s.Read = LookToRead_Read;
|
||||
p->s.Seek = LookToRead_Seek;
|
||||
}
|
||||
|
||||
void LookToRead_Init(CLookToRead *p)
|
||||
{
|
||||
p->pos = p->size = 0;
|
||||
}
|
||||
|
||||
static SRes SecToLook_Read(void *pp, void *buf, size_t *size)
|
||||
{
|
||||
CSecToLook *p = (CSecToLook *)pp;
|
||||
return LookInStream_LookRead(p->realStream, buf, size);
|
||||
}
|
||||
|
||||
void SecToLook_CreateVTable(CSecToLook *p)
|
||||
{
|
||||
p->s.Read = SecToLook_Read;
|
||||
}
|
||||
|
||||
static SRes SecToRead_Read(void *pp, void *buf, size_t *size)
|
||||
{
|
||||
CSecToRead *p = (CSecToRead *)pp;
|
||||
return p->realStream->Read(p->realStream, buf, size);
|
||||
}
|
||||
|
||||
void SecToRead_CreateVTable(CSecToRead *p)
|
||||
{
|
||||
p->s.Read = SecToRead_Read;
|
||||
}
|
254
lzma/C/Archive/7z/7zDecode.c
Normal file
254
lzma/C/Archive/7z/7zDecode.c
Normal file
|
@ -0,0 +1,254 @@
|
|||
/* 7zDecode.c -- Decoding from 7z folder
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../../Bcj2.h"
|
||||
#include "../../Bra.h"
|
||||
#include "../../LzmaDec.h"
|
||||
#include "7zDecode.h"
|
||||
|
||||
#define k_Copy 0
|
||||
#define k_LZMA 0x30101
|
||||
#define k_BCJ 0x03030103
|
||||
#define k_BCJ2 0x0303011B
|
||||
|
||||
static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
||||
{
|
||||
CLzmaDec state;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
LzmaDec_Construct(&state);
|
||||
RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));
|
||||
state.dic = outBuffer;
|
||||
state.dicBufSize = outSize;
|
||||
LzmaDec_Init(&state);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
{
|
||||
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
|
||||
ELzmaStatus status;
|
||||
res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||
lookahead -= inProcessed;
|
||||
inSize -= inProcessed;
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
|
||||
{
|
||||
if (state.dicBufSize != outSize || lookahead != 0 ||
|
||||
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
|
||||
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
res = inStream->Skip((void *)inStream, inProcessed);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LzmaDec_FreeProbs(&state, allocMain);
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
|
||||
{
|
||||
while (inSize > 0)
|
||||
{
|
||||
void *inBuf;
|
||||
size_t curSize = (1 << 18);
|
||||
if (curSize > inSize)
|
||||
curSize = (size_t)inSize;
|
||||
RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize));
|
||||
if (curSize == 0)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
memcpy(outBuffer, inBuf, curSize);
|
||||
outBuffer += curSize;
|
||||
inSize -= curSize;
|
||||
RINOK(inStream->Skip((void *)inStream, curSize));
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA)
|
||||
#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
||||
#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
||||
#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
|
||||
|
||||
SRes CheckSupportedFolder(const CSzFolder *f)
|
||||
{
|
||||
if (f->NumCoders < 1 || f->NumCoders > 4)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (IS_UNSUPPORTED_CODER(f->Coders[0]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (f->NumCoders == 1)
|
||||
{
|
||||
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (f->NumCoders == 2)
|
||||
{
|
||||
if (IS_NO_BCJ(f->Coders[1]) ||
|
||||
f->NumPackStreams != 1 || f->PackStreams[0] != 0 ||
|
||||
f->NumBindPairs != 1 ||
|
||||
f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (f->NumCoders == 4)
|
||||
{
|
||||
if (IS_UNSUPPORTED_CODER(f->Coders[1]) ||
|
||||
IS_UNSUPPORTED_CODER(f->Coders[2]) ||
|
||||
IS_NO_BCJ2(f->Coders[3]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (f->NumPackStreams != 4 ||
|
||||
f->PackStreams[0] != 2 ||
|
||||
f->PackStreams[1] != 6 ||
|
||||
f->PackStreams[2] != 1 ||
|
||||
f->PackStreams[3] != 0 ||
|
||||
f->NumBindPairs != 3 ||
|
||||
f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
|
||||
f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
|
||||
f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
UInt64 GetSum(const UInt64 *values, UInt32 index)
|
||||
{
|
||||
UInt64 sum = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < index; i++)
|
||||
sum += values[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder,
|
||||
ILookInStream *inStream, UInt64 startPos,
|
||||
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
|
||||
Byte *tempBuf[])
|
||||
{
|
||||
UInt32 ci;
|
||||
SizeT tempSizes[3] = { 0, 0, 0};
|
||||
SizeT tempSize3 = 0;
|
||||
Byte *tempBuf3 = 0;
|
||||
|
||||
RINOK(CheckSupportedFolder(folder));
|
||||
|
||||
for (ci = 0; ci < folder->NumCoders; ci++)
|
||||
{
|
||||
CSzCoderInfo *coder = &folder->Coders[ci];
|
||||
|
||||
if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
|
||||
{
|
||||
UInt32 si = 0;
|
||||
UInt64 offset;
|
||||
UInt64 inSize;
|
||||
Byte *outBufCur = outBuffer;
|
||||
SizeT outSizeCur = outSize;
|
||||
if (folder->NumCoders == 4)
|
||||
{
|
||||
UInt32 indices[] = { 3, 2, 0 };
|
||||
UInt64 unpackSize = folder->UnpackSizes[ci];
|
||||
si = indices[ci];
|
||||
if (ci < 2)
|
||||
{
|
||||
Byte *temp;
|
||||
outSizeCur = (SizeT)unpackSize;
|
||||
if (outSizeCur != unpackSize)
|
||||
return SZ_ERROR_MEM;
|
||||
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
|
||||
if (temp == 0 && outSizeCur != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
outBufCur = tempBuf[1 - ci] = temp;
|
||||
tempSizes[1 - ci] = outSizeCur;
|
||||
}
|
||||
else if (ci == 2)
|
||||
{
|
||||
if (unpackSize > outSize) /* check it */
|
||||
return SZ_ERROR_PARAM;
|
||||
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
||||
tempSize3 = outSizeCur = (SizeT)unpackSize;
|
||||
}
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
offset = GetSum(packSizes, si);
|
||||
inSize = packSizes[si];
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
|
||||
if (coder->MethodID == k_Copy)
|
||||
{
|
||||
if (inSize != outSizeCur) /* check it */
|
||||
return SZ_ERROR_DATA;
|
||||
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ)
|
||||
{
|
||||
UInt32 state;
|
||||
if (ci != 1)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
x86_Convert_Init(state);
|
||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ2)
|
||||
{
|
||||
UInt64 offset = GetSum(packSizes, 1);
|
||||
UInt64 s3Size = packSizes[1];
|
||||
SRes res;
|
||||
if (ci != 3)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
tempSizes[2] = (SizeT)s3Size;
|
||||
if (tempSizes[2] != s3Size)
|
||||
return SZ_ERROR_MEM;
|
||||
tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
|
||||
if (tempBuf[2] == 0 && tempSizes[2] != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
|
||||
RINOK(res)
|
||||
|
||||
res = Bcj2_Decode(
|
||||
tempBuf3, tempSize3,
|
||||
tempBuf[0], tempSizes[0],
|
||||
tempBuf[1], tempSizes[1],
|
||||
tempBuf[2], tempSizes[2],
|
||||
outBuffer, outSize);
|
||||
RINOK(res)
|
||||
}
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
|
||||
ILookInStream *inStream, UInt64 startPos,
|
||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
||||
{
|
||||
Byte *tempBuf[3] = { 0, 0, 0};
|
||||
int i;
|
||||
SRes res = SzDecode2(packSizes, folder, inStream, startPos,
|
||||
outBuffer, (SizeT)outSize, allocMain, tempBuf);
|
||||
for (i = 0; i < 3; i++)
|
||||
IAlloc_Free(allocMain, tempBuf[i]);
|
||||
return res;
|
||||
}
|
13
lzma/C/Archive/7z/7zDecode.h
Normal file
13
lzma/C/Archive/7z/7zDecode.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
/* 7zDecode.h -- Decoding from 7z folder
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_DECODE_H
|
||||
#define __7Z_DECODE_H
|
||||
|
||||
#include "7zItem.h"
|
||||
|
||||
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
|
||||
ILookInStream *stream, UInt64 startPos,
|
||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
||||
|
||||
#endif
|
93
lzma/C/Archive/7z/7zExtract.c
Normal file
93
lzma/C/Archive/7z/7zExtract.c
Normal file
|
@ -0,0 +1,93 @@
|
|||
/* 7zExtract.c -- Extracting from 7z archive
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "../../7zCrc.h"
|
||||
#include "7zDecode.h"
|
||||
#include "7zExtract.h"
|
||||
|
||||
SRes SzAr_Extract(
|
||||
const CSzArEx *p,
|
||||
ILookInStream *inStream,
|
||||
UInt32 fileIndex,
|
||||
UInt32 *blockIndex,
|
||||
Byte **outBuffer,
|
||||
size_t *outBufferSize,
|
||||
size_t *offset,
|
||||
size_t *outSizeProcessed,
|
||||
ISzAlloc *allocMain,
|
||||
ISzAlloc *allocTemp)
|
||||
{
|
||||
UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
|
||||
SRes res = SZ_OK;
|
||||
*offset = 0;
|
||||
*outSizeProcessed = 0;
|
||||
if (folderIndex == (UInt32)-1)
|
||||
{
|
||||
IAlloc_Free(allocMain, *outBuffer);
|
||||
*blockIndex = folderIndex;
|
||||
*outBuffer = 0;
|
||||
*outBufferSize = 0;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (*outBuffer == 0 || *blockIndex != folderIndex)
|
||||
{
|
||||
CSzFolder *folder = p->db.Folders + folderIndex;
|
||||
UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
|
||||
size_t unpackSize = (size_t)unpackSizeSpec;
|
||||
UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
|
||||
|
||||
if (unpackSize != unpackSizeSpec)
|
||||
return SZ_ERROR_MEM;
|
||||
*blockIndex = folderIndex;
|
||||
IAlloc_Free(allocMain, *outBuffer);
|
||||
*outBuffer = 0;
|
||||
|
||||
RINOK(LookInStream_SeekTo(inStream, startOffset));
|
||||
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
*outBufferSize = unpackSize;
|
||||
if (unpackSize != 0)
|
||||
{
|
||||
*outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
|
||||
if (*outBuffer == 0)
|
||||
res = SZ_ERROR_MEM;
|
||||
}
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
res = SzDecode(p->db.PackSizes +
|
||||
p->FolderStartPackStreamIndex[folderIndex], folder,
|
||||
inStream, startOffset,
|
||||
*outBuffer, unpackSize, allocTemp);
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
if (folder->UnpackCRCDefined)
|
||||
{
|
||||
if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
|
||||
res = SZ_ERROR_CRC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
UInt32 i;
|
||||
CSzFileItem *fileItem = p->db.Files + fileIndex;
|
||||
*offset = 0;
|
||||
for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
|
||||
*offset += (UInt32)p->db.Files[i].Size;
|
||||
*outSizeProcessed = (size_t)fileItem->Size;
|
||||
if (*offset + *outSizeProcessed > *outBufferSize)
|
||||
return SZ_ERROR_FAIL;
|
||||
{
|
||||
if (fileItem->FileCRCDefined)
|
||||
{
|
||||
if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
|
||||
res = SZ_ERROR_CRC;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
41
lzma/C/Archive/7z/7zExtract.h
Normal file
41
lzma/C/Archive/7z/7zExtract.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* 7zExtract.h -- Extracting from 7z archive
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_EXTRACT_H
|
||||
#define __7Z_EXTRACT_H
|
||||
|
||||
#include "7zIn.h"
|
||||
|
||||
/*
|
||||
SzExtract extracts file from archive
|
||||
|
||||
*outBuffer must be 0 before first call for each new archive.
|
||||
|
||||
Extracting cache:
|
||||
If you need to decompress more than one file, you can send
|
||||
these values from previous call:
|
||||
*blockIndex,
|
||||
*outBuffer,
|
||||
*outBufferSize
|
||||
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
||||
it will increase decompression speed.
|
||||
|
||||
If you use external function, you can declare these 3 cache variables
|
||||
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
||||
|
||||
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
||||
*/
|
||||
|
||||
SRes SzAr_Extract(
|
||||
const CSzArEx *db,
|
||||
ILookInStream *inStream,
|
||||
UInt32 fileIndex, /* index of file */
|
||||
UInt32 *blockIndex, /* index of solid block */
|
||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||
size_t *outBufferSize, /* buffer size for output buffer */
|
||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||
ISzAlloc *allocMain,
|
||||
ISzAlloc *allocTemp);
|
||||
|
||||
#endif
|
6
lzma/C/Archive/7z/7zHeader.c
Normal file
6
lzma/C/Archive/7z/7zHeader.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
/* 7zHeader.c -- 7z Headers
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "7zHeader.h"
|
||||
|
||||
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
57
lzma/C/Archive/7z/7zHeader.h
Normal file
57
lzma/C/Archive/7z/7zHeader.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* 7zHeader.h -- 7z Headers
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_HEADER_H
|
||||
#define __7Z_HEADER_H
|
||||
|
||||
#include "../../Types.h"
|
||||
|
||||
#define k7zSignatureSize 6
|
||||
extern Byte k7zSignature[k7zSignatureSize];
|
||||
|
||||
#define k7zMajorVersion 0
|
||||
|
||||
#define k7zStartHeaderSize 0x20
|
||||
|
||||
enum EIdEnum
|
||||
{
|
||||
k7zIdEnd,
|
||||
|
||||
k7zIdHeader,
|
||||
|
||||
k7zIdArchiveProperties,
|
||||
|
||||
k7zIdAdditionalStreamsInfo,
|
||||
k7zIdMainStreamsInfo,
|
||||
k7zIdFilesInfo,
|
||||
|
||||
k7zIdPackInfo,
|
||||
k7zIdUnpackInfo,
|
||||
k7zIdSubStreamsInfo,
|
||||
|
||||
k7zIdSize,
|
||||
k7zIdCRC,
|
||||
|
||||
k7zIdFolder,
|
||||
|
||||
k7zIdCodersUnpackSize,
|
||||
k7zIdNumUnpackStream,
|
||||
|
||||
k7zIdEmptyStream,
|
||||
k7zIdEmptyFile,
|
||||
k7zIdAnti,
|
||||
|
||||
k7zIdName,
|
||||
k7zIdCTime,
|
||||
k7zIdATime,
|
||||
k7zIdMTime,
|
||||
k7zIdWinAttributes,
|
||||
k7zIdComment,
|
||||
|
||||
k7zIdEncodedHeader,
|
||||
|
||||
k7zIdStartPos,
|
||||
k7zIdDummy
|
||||
};
|
||||
|
||||
#endif
|
1204
lzma/C/Archive/7z/7zIn.c
Normal file
1204
lzma/C/Archive/7z/7zIn.c
Normal file
File diff suppressed because it is too large
Load diff
41
lzma/C/Archive/7z/7zIn.h
Normal file
41
lzma/C/Archive/7z/7zIn.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* 7zIn.h -- 7z Input functions
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_IN_H
|
||||
#define __7Z_IN_H
|
||||
|
||||
#include "7zHeader.h"
|
||||
#include "7zItem.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzAr db;
|
||||
|
||||
UInt64 startPosAfterHeader;
|
||||
UInt64 dataPos;
|
||||
|
||||
UInt32 *FolderStartPackStreamIndex;
|
||||
UInt64 *PackStreamStartPositions;
|
||||
UInt32 *FolderStartFileIndex;
|
||||
UInt32 *FileIndexToFolderIndexMap;
|
||||
} CSzArEx;
|
||||
|
||||
void SzArEx_Init(CSzArEx *p);
|
||||
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
|
||||
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
|
||||
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
|
||||
|
||||
/*
|
||||
Errors:
|
||||
SZ_ERROR_NO_ARCHIVE
|
||||
SZ_ERROR_ARCHIVE
|
||||
SZ_ERROR_UNSUPPORTED
|
||||
SZ_ERROR_MEM
|
||||
SZ_ERROR_CRC
|
||||
SZ_ERROR_INPUT_EOF
|
||||
SZ_ERROR_FAIL
|
||||
*/
|
||||
|
||||
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
||||
|
||||
#endif
|
127
lzma/C/Archive/7z/7zItem.c
Normal file
127
lzma/C/Archive/7z/7zItem.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
/* 7zItem.c -- 7z Items
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "7zItem.h"
|
||||
|
||||
void SzCoderInfo_Init(CSzCoderInfo *p)
|
||||
{
|
||||
Buf_Init(&p->Props);
|
||||
}
|
||||
|
||||
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
|
||||
{
|
||||
Buf_Free(&p->Props, alloc);
|
||||
SzCoderInfo_Init(p);
|
||||
}
|
||||
|
||||
void SzFolder_Init(CSzFolder *p)
|
||||
{
|
||||
p->Coders = 0;
|
||||
p->BindPairs = 0;
|
||||
p->PackStreams = 0;
|
||||
p->UnpackSizes = 0;
|
||||
p->NumCoders = 0;
|
||||
p->NumBindPairs = 0;
|
||||
p->NumPackStreams = 0;
|
||||
p->UnpackCRCDefined = 0;
|
||||
p->UnpackCRC = 0;
|
||||
p->NumUnpackStreams = 0;
|
||||
}
|
||||
|
||||
void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
|
||||
{
|
||||
UInt32 i;
|
||||
if (p->Coders)
|
||||
for (i = 0; i < p->NumCoders; i++)
|
||||
SzCoderInfo_Free(&p->Coders[i], alloc);
|
||||
IAlloc_Free(alloc, p->Coders);
|
||||
IAlloc_Free(alloc, p->BindPairs);
|
||||
IAlloc_Free(alloc, p->PackStreams);
|
||||
IAlloc_Free(alloc, p->UnpackSizes);
|
||||
SzFolder_Init(p);
|
||||
}
|
||||
|
||||
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
|
||||
{
|
||||
UInt32 result = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < p->NumCoders; i++)
|
||||
result += p->Coders[i].NumOutStreams;
|
||||
return result;
|
||||
}
|
||||
|
||||
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < p->NumBindPairs; i++)
|
||||
if (p->BindPairs[i].InIndex == inStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < p->NumBindPairs; i++)
|
||||
if (p->BindPairs[i].OutIndex == outStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
|
||||
{
|
||||
int i = (int)SzFolder_GetNumOutStreams(p);
|
||||
if (i == 0)
|
||||
return 0;
|
||||
for (i--; i >= 0; i--)
|
||||
if (SzFolder_FindBindPairForOutStream(p, i) < 0)
|
||||
return p->UnpackSizes[i];
|
||||
/* throw 1; */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SzFile_Init(CSzFileItem *p)
|
||||
{
|
||||
p->HasStream = 1;
|
||||
p->IsDir = 0;
|
||||
p->IsAnti = 0;
|
||||
p->FileCRCDefined = 0;
|
||||
p->MTimeDefined = 0;
|
||||
p->Name = 0;
|
||||
}
|
||||
|
||||
static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc)
|
||||
{
|
||||
IAlloc_Free(alloc, p->Name);
|
||||
SzFile_Init(p);
|
||||
}
|
||||
|
||||
void SzAr_Init(CSzAr *p)
|
||||
{
|
||||
p->PackSizes = 0;
|
||||
p->PackCRCsDefined = 0;
|
||||
p->PackCRCs = 0;
|
||||
p->Folders = 0;
|
||||
p->Files = 0;
|
||||
p->NumPackStreams = 0;
|
||||
p->NumFolders = 0;
|
||||
p->NumFiles = 0;
|
||||
}
|
||||
|
||||
void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
|
||||
{
|
||||
UInt32 i;
|
||||
if (p->Folders)
|
||||
for (i = 0; i < p->NumFolders; i++)
|
||||
SzFolder_Free(&p->Folders[i], alloc);
|
||||
if (p->Files)
|
||||
for (i = 0; i < p->NumFiles; i++)
|
||||
SzFile_Free(&p->Files[i], alloc);
|
||||
IAlloc_Free(alloc, p->PackSizes);
|
||||
IAlloc_Free(alloc, p->PackCRCsDefined);
|
||||
IAlloc_Free(alloc, p->PackCRCs);
|
||||
IAlloc_Free(alloc, p->Folders);
|
||||
IAlloc_Free(alloc, p->Files);
|
||||
SzAr_Init(p);
|
||||
}
|
84
lzma/C/Archive/7z/7zItem.h
Normal file
84
lzma/C/Archive/7z/7zItem.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/* 7zItem.h -- 7z Items
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_ITEM_H
|
||||
#define __7Z_ITEM_H
|
||||
|
||||
#include "../../7zBuf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 NumInStreams;
|
||||
UInt32 NumOutStreams;
|
||||
UInt64 MethodID;
|
||||
CBuf Props;
|
||||
} CSzCoderInfo;
|
||||
|
||||
void SzCoderInfo_Init(CSzCoderInfo *p);
|
||||
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 InIndex;
|
||||
UInt32 OutIndex;
|
||||
} CBindPair;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzCoderInfo *Coders;
|
||||
CBindPair *BindPairs;
|
||||
UInt32 *PackStreams;
|
||||
UInt64 *UnpackSizes;
|
||||
UInt32 NumCoders;
|
||||
UInt32 NumBindPairs;
|
||||
UInt32 NumPackStreams;
|
||||
int UnpackCRCDefined;
|
||||
UInt32 UnpackCRC;
|
||||
|
||||
UInt32 NumUnpackStreams;
|
||||
} CSzFolder;
|
||||
|
||||
void SzFolder_Init(CSzFolder *p);
|
||||
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
|
||||
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
|
||||
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
|
||||
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
|
||||
|
||||
typedef struct CNtfsFileTime
|
||||
{
|
||||
UInt32 Low;
|
||||
UInt32 High;
|
||||
} CNtfsFileTime;
|
||||
|
||||
typedef struct CSzFileItem
|
||||
{
|
||||
CNtfsFileTime MTime;
|
||||
UInt64 Size;
|
||||
char *Name;
|
||||
UInt32 FileCRC;
|
||||
|
||||
Byte HasStream;
|
||||
Byte IsDir;
|
||||
Byte IsAnti;
|
||||
Byte FileCRCDefined;
|
||||
Byte MTimeDefined;
|
||||
} CSzFileItem;
|
||||
|
||||
void SzFile_Init(CSzFileItem *p);
|
||||
|
||||
typedef struct CSzAr
|
||||
{
|
||||
UInt64 *PackSizes;
|
||||
Byte *PackCRCsDefined;
|
||||
UInt32 *PackCRCs;
|
||||
CSzFolder *Folders;
|
||||
CSzFileItem *Files;
|
||||
UInt32 NumPackStreams;
|
||||
UInt32 NumFolders;
|
||||
UInt32 NumFiles;
|
||||
} CSzAr;
|
||||
|
||||
void SzAr_Init(CSzAr *p);
|
||||
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
||||
|
||||
#endif
|
132
lzma/C/Bcj2.c
Normal file
132
lzma/C/Bcj2.c
Normal file
|
@ -0,0 +1,132 @@
|
|||
/* Bcj2.c -- Converter for x86 code (BCJ2)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Bcj2.h"
|
||||
|
||||
#ifdef _LZMA_PROB32
|
||||
#define CProb UInt32
|
||||
#else
|
||||
#define CProb UInt16
|
||||
#endif
|
||||
|
||||
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
|
||||
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
|
||||
|
||||
#define kNumTopBits 24
|
||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
||||
|
||||
#define kNumBitModelTotalBits 11
|
||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
||||
#define kNumMoveBits 5
|
||||
|
||||
#define RC_READ_BYTE (*buffer++)
|
||||
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
|
||||
#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \
|
||||
{ int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}
|
||||
|
||||
#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }
|
||||
|
||||
#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
|
||||
#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;
|
||||
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;
|
||||
|
||||
int Bcj2_Decode(
|
||||
const Byte *buf0, SizeT size0,
|
||||
const Byte *buf1, SizeT size1,
|
||||
const Byte *buf2, SizeT size2,
|
||||
const Byte *buf3, SizeT size3,
|
||||
Byte *outBuf, SizeT outSize)
|
||||
{
|
||||
CProb p[256 + 2];
|
||||
SizeT inPos = 0, outPos = 0;
|
||||
|
||||
const Byte *buffer, *bufferLim;
|
||||
UInt32 range, code;
|
||||
Byte prevByte = 0;
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
|
||||
p[i] = kBitModelTotal >> 1;
|
||||
|
||||
buffer = buf3;
|
||||
bufferLim = buffer + size3;
|
||||
RC_INIT2
|
||||
|
||||
if (outSize == 0)
|
||||
return SZ_OK;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte b;
|
||||
CProb *prob;
|
||||
UInt32 bound;
|
||||
UInt32 ttt;
|
||||
|
||||
SizeT limit = size0 - inPos;
|
||||
if (outSize - outPos < limit)
|
||||
limit = outSize - outPos;
|
||||
while (limit != 0)
|
||||
{
|
||||
Byte b = buf0[inPos];
|
||||
outBuf[outPos++] = b;
|
||||
if (IsJ(prevByte, b))
|
||||
break;
|
||||
inPos++;
|
||||
prevByte = b;
|
||||
limit--;
|
||||
}
|
||||
|
||||
if (limit == 0 || outPos == outSize)
|
||||
break;
|
||||
|
||||
b = buf0[inPos++];
|
||||
|
||||
if (b == 0xE8)
|
||||
prob = p + prevByte;
|
||||
else if (b == 0xE9)
|
||||
prob = p + 256;
|
||||
else
|
||||
prob = p + 257;
|
||||
|
||||
IF_BIT_0(prob)
|
||||
{
|
||||
UPDATE_0(prob)
|
||||
prevByte = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 dest;
|
||||
const Byte *v;
|
||||
UPDATE_1(prob)
|
||||
if (b == 0xE8)
|
||||
{
|
||||
v = buf1;
|
||||
if (size1 < 4)
|
||||
return SZ_ERROR_DATA;
|
||||
buf1 += 4;
|
||||
size1 -= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = buf2;
|
||||
if (size2 < 4)
|
||||
return SZ_ERROR_DATA;
|
||||
buf2 += 4;
|
||||
size2 -= 4;
|
||||
}
|
||||
dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
|
||||
((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
|
||||
outBuf[outPos++] = (Byte)dest;
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = (Byte)(dest >> 8);
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = (Byte)(dest >> 16);
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
|
||||
}
|
||||
}
|
||||
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
|
||||
}
|
30
lzma/C/Bcj2.h
Normal file
30
lzma/C/Bcj2.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* Bcj2.h -- Converter for x86 code (BCJ2)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BCJ2_H
|
||||
#define __BCJ2_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
/*
|
||||
Conditions:
|
||||
outSize <= FullOutputSize,
|
||||
where FullOutputSize is full size of output stream of x86_2 filter.
|
||||
|
||||
If buf0 overlaps outBuf, there are two required conditions:
|
||||
1) (buf0 >= outBuf)
|
||||
2) (buf0 + size0 >= outBuf + FullOutputSize).
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
SZ_ERROR_DATA - Data error
|
||||
*/
|
||||
|
||||
int Bcj2_Decode(
|
||||
const Byte *buf0, SizeT size0,
|
||||
const Byte *buf1, SizeT size1,
|
||||
const Byte *buf2, SizeT size2,
|
||||
const Byte *buf3, SizeT size3,
|
||||
Byte *outBuf, SizeT outSize);
|
||||
|
||||
#endif
|
60
lzma/C/Bra.h
Normal file
60
lzma/C/Bra.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/* Bra.h -- Branch converters for executables
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BRA_H
|
||||
#define __BRA_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
/*
|
||||
These functions convert relative addresses to absolute addresses
|
||||
in CALL instructions to increase the compression ratio.
|
||||
|
||||
In:
|
||||
data - data buffer
|
||||
size - size of data
|
||||
ip - current virtual Instruction Pinter (IP) value
|
||||
state - state variable for x86 converter
|
||||
encoding - 0 (for decoding), 1 (for encoding)
|
||||
|
||||
Out:
|
||||
state - state variable for x86 converter
|
||||
|
||||
Returns:
|
||||
The number of processed bytes. If you call these functions with multiple calls,
|
||||
you must start next call with first byte after block of processed bytes.
|
||||
|
||||
Type Endian Alignment LookAhead
|
||||
|
||||
x86 little 1 4
|
||||
ARMT little 2 2
|
||||
ARM little 4 0
|
||||
PPC big 4 0
|
||||
SPARC big 4 0
|
||||
IA64 little 16 0
|
||||
|
||||
size must be >= Alignment + LookAhead, if it's not last block.
|
||||
If (size < Alignment + LookAhead), converter returns 0.
|
||||
|
||||
Example:
|
||||
|
||||
UInt32 ip = 0;
|
||||
for ()
|
||||
{
|
||||
; size must be >= Alignment + LookAhead, if it's not last block
|
||||
SizeT processed = Convert(data, size, ip, 1);
|
||||
data += processed;
|
||||
size -= processed;
|
||||
ip += processed;
|
||||
}
|
||||
*/
|
||||
|
||||
#define x86_Convert_Init(state) { state = 0; }
|
||||
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding);
|
||||
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
|
||||
#endif
|
85
lzma/C/Bra86.c
Normal file
85
lzma/C/Bra86.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
/* Bra86.c -- Converter for x86 code (BCJ)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Bra.h"
|
||||
|
||||
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
|
||||
|
||||
const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
|
||||
const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
|
||||
|
||||
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
|
||||
{
|
||||
SizeT bufferPos = 0, prevPosT;
|
||||
UInt32 prevMask = *state & 0x7;
|
||||
if (size < 5)
|
||||
return 0;
|
||||
ip += 5;
|
||||
prevPosT = (SizeT)0 - 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte *p = data + bufferPos;
|
||||
Byte *limit = data + size - 4;
|
||||
for (; p < limit; p++)
|
||||
if ((*p & 0xFE) == 0xE8)
|
||||
break;
|
||||
bufferPos = (SizeT)(p - data);
|
||||
if (p >= limit)
|
||||
break;
|
||||
prevPosT = bufferPos - prevPosT;
|
||||
if (prevPosT > 3)
|
||||
prevMask = 0;
|
||||
else
|
||||
{
|
||||
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
|
||||
if (prevMask != 0)
|
||||
{
|
||||
Byte b = p[4 - kMaskToBitNumber[prevMask]];
|
||||
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
|
||||
{
|
||||
prevPosT = bufferPos;
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
prevPosT = bufferPos;
|
||||
|
||||
if (Test86MSByte(p[4]))
|
||||
{
|
||||
UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
|
||||
UInt32 dest;
|
||||
for (;;)
|
||||
{
|
||||
Byte b;
|
||||
int index;
|
||||
if (encoding)
|
||||
dest = (ip + (UInt32)bufferPos) + src;
|
||||
else
|
||||
dest = src - (ip + (UInt32)bufferPos);
|
||||
if (prevMask == 0)
|
||||
break;
|
||||
index = kMaskToBitNumber[prevMask] * 8;
|
||||
b = (Byte)(dest >> (24 - index));
|
||||
if (!Test86MSByte(b))
|
||||
break;
|
||||
src = dest ^ ((1 << (32 - index)) - 1);
|
||||
}
|
||||
p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
|
||||
p[3] = (Byte)(dest >> 16);
|
||||
p[2] = (Byte)(dest >> 8);
|
||||
p[1] = (Byte)dest;
|
||||
bufferPos += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
}
|
||||
}
|
||||
prevPosT = bufferPos - prevPosT;
|
||||
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
|
||||
return bufferPos;
|
||||
}
|
69
lzma/C/CpuArch.h
Normal file
69
lzma/C/CpuArch.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* CpuArch.h
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#ifndef __CPUARCH_H
|
||||
#define __CPUARCH_H
|
||||
|
||||
/*
|
||||
LITTLE_ENDIAN_UNALIGN means:
|
||||
1) CPU is LITTLE_ENDIAN
|
||||
2) it's allowed to make unaligned memory accesses
|
||||
if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know
|
||||
about these properties of platform.
|
||||
*/
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__)
|
||||
#define LITTLE_ENDIAN_UNALIGN
|
||||
#endif
|
||||
|
||||
#ifdef LITTLE_ENDIAN_UNALIGN
|
||||
|
||||
#define GetUi16(p) (*(const UInt16 *)(p))
|
||||
#define GetUi32(p) (*(const UInt32 *)(p))
|
||||
#define GetUi64(p) (*(const UInt64 *)(p))
|
||||
#define SetUi32(p, d) *(UInt32 *)(p) = (d);
|
||||
|
||||
#else
|
||||
|
||||
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
|
||||
|
||||
#define GetUi32(p) ( \
|
||||
((const Byte *)(p))[0] | \
|
||||
((UInt32)((const Byte *)(p))[1] << 8) | \
|
||||
((UInt32)((const Byte *)(p))[2] << 16) | \
|
||||
((UInt32)((const Byte *)(p))[3] << 24))
|
||||
|
||||
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
|
||||
|
||||
#define SetUi32(p, d) { UInt32 _x_ = (d); \
|
||||
((Byte *)(p))[0] = (Byte)_x_; \
|
||||
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
|
||||
((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
|
||||
((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
|
||||
|
||||
#pragma intrinsic(_byteswap_ulong)
|
||||
#pragma intrinsic(_byteswap_uint64)
|
||||
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
|
||||
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
|
||||
|
||||
#else
|
||||
|
||||
#define GetBe32(p) ( \
|
||||
((UInt32)((const Byte *)(p))[0] << 24) | \
|
||||
((UInt32)((const Byte *)(p))[1] << 16) | \
|
||||
((UInt32)((const Byte *)(p))[2] << 8) | \
|
||||
((const Byte *)(p))[3] )
|
||||
|
||||
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
|
||||
|
||||
#endif
|
||||
|
||||
#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
|
||||
|
||||
#endif
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SZ_OK 0
|
||||
|
||||
#define SZ_ERROR_DATA 1
|
||||
|
@ -197,4 +201,8 @@ typedef struct
|
|||
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
|
||||
#define IAlloc_Free(p, a) (p)->Free((p), a)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,17 @@ if( CMAKE_COMPILER_IS_GNUC )
|
|||
endif( CMAKE_COMPILER_IS_GNUC )
|
||||
|
||||
set( LZMA_FILES
|
||||
C/Archive/7z/7zDecode.c
|
||||
C/Archive/7z/7zExtract.c
|
||||
C/Archive/7z/7zHeader.c
|
||||
C/Archive/7z/7zIn.c
|
||||
C/Archive/7z/7zItem.c
|
||||
C/7zBuf.c
|
||||
C/7zCrc.c
|
||||
C/7zStream.c
|
||||
C/Alloc.c
|
||||
C/Bcj2.c
|
||||
C/Bra86.c
|
||||
C/LzFind.c
|
||||
C/LzFindMt.c
|
||||
C/LzmaDec.c
|
||||
|
|
|
@ -286,10 +286,30 @@
|
|||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\C\7zBuf.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\7zCrc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\7zStream.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Alloc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Bcj2.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Bra86.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\LzFind.c"
|
||||
>
|
||||
|
@ -320,6 +340,14 @@
|
|||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\C\7zBuf.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\7zCrc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\7zVersion.h"
|
||||
>
|
||||
|
@ -328,6 +356,18 @@
|
|||
RelativePath=".\C\Alloc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Bcj2.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Bra.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\CpuArch.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\LzFind.h"
|
||||
>
|
||||
|
@ -361,6 +401,50 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="7z"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\C\Archive\7z\7zDecode.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Archive\7z\7zDecode.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Archive\7z\7zExtract.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Archive\7z\7zExtract.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Archive\7z\7zHeader.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Archive\7z\7zHeader.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Archive\7z\7zIn.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Archive\7z\7zIn.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Archive\7z\7zItem.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Archive\7z\7zItem.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\CMakeLists.txt"
|
||||
>
|
||||
|
|
|
@ -364,7 +364,7 @@ extern "C" void bz_internal_error (int errcode)
|
|||
|
||||
static void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }
|
||||
static void SzFree(void *p, void *address) { p = p; free(address); }
|
||||
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
FileReaderLZMA::FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip)
|
||||
: File(file), SawEOF(false)
|
||||
|
|
625
src/w_wad.cpp
625
src/w_wad.cpp
|
@ -30,10 +30,21 @@
|
|||
#include "templates.h"
|
||||
#include "gi.h"
|
||||
|
||||
extern "C" {
|
||||
#include "Archive/7z/7zHeader.h"
|
||||
#include "Archive/7z/7zExtract.h"
|
||||
#include "Archive/7z/7zIn.h"
|
||||
#include "7zCrc.h"
|
||||
}
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
#define NULL_INDEX (0xffff)
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
extern ISzAlloc g_Alloc;
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
struct rffinfo_t
|
||||
|
@ -81,6 +92,7 @@ union MergedHeader
|
|||
wadinfo_t wad;
|
||||
rffinfo_t rff;
|
||||
grpinfo_t grp;
|
||||
BYTE sevenzip[k7zSignatureSize];
|
||||
};
|
||||
|
||||
|
||||
|
@ -92,32 +104,149 @@ struct FWadCollection::LumpRecord
|
|||
char * fullname; // only valid for files loaded from a .zip file
|
||||
char name[9];
|
||||
BYTE method; // zip compression method
|
||||
BYTE flags;
|
||||
short wadnum;
|
||||
WORD flags;
|
||||
int position;
|
||||
int size;
|
||||
int namespc;
|
||||
int compressedsize;
|
||||
|
||||
void ZipNameSetup(char *name);
|
||||
};
|
||||
|
||||
struct CZDFileInStream
|
||||
{
|
||||
ISeekInStream s;
|
||||
FileReader *File;
|
||||
|
||||
CZDFileInStream(FileReader *_file)
|
||||
{
|
||||
s.Read = Read;
|
||||
s.Seek = Seek;
|
||||
File = _file;
|
||||
}
|
||||
|
||||
static SRes Read(void *pp, void *buf, size_t *size)
|
||||
{
|
||||
CZDFileInStream *p = (CZDFileInStream *)pp;
|
||||
long numread = p->File->Read(buf, (long)*size);
|
||||
if (numread < 0)
|
||||
{
|
||||
*size = 0;
|
||||
return SZ_ERROR_READ;
|
||||
}
|
||||
*size = numread;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes Seek(void *pp, Int64 *pos, ESzSeek origin)
|
||||
{
|
||||
CZDFileInStream *p = (CZDFileInStream *)pp;
|
||||
int move_method;
|
||||
int res;
|
||||
if (origin == SZ_SEEK_SET)
|
||||
{
|
||||
move_method = SEEK_SET;
|
||||
}
|
||||
else if (origin == SZ_SEEK_CUR)
|
||||
{
|
||||
move_method = SEEK_CUR;
|
||||
}
|
||||
else if (origin == SZ_SEEK_END)
|
||||
{
|
||||
move_method = SEEK_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
res = p->File->Seek((long)*pos, move_method);
|
||||
*pos = p->File->Tell();
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
struct C7zArchive
|
||||
{
|
||||
CSzArEx DB;
|
||||
CZDFileInStream ArchiveStream;
|
||||
CLookToRead LookStream;
|
||||
UInt32 BlockIndex;
|
||||
Byte *OutBuffer;
|
||||
size_t OutBufferSize;
|
||||
|
||||
C7zArchive(FileReader *file) : ArchiveStream(file)
|
||||
{
|
||||
if (g_CrcTable[1] == 0)
|
||||
{
|
||||
CrcGenerateTable();
|
||||
}
|
||||
file->Seek(0, SEEK_SET);
|
||||
LookToRead_CreateVTable(&LookStream, false);
|
||||
LookStream.realStream = &ArchiveStream.s;
|
||||
LookToRead_Init(&LookStream);
|
||||
SzArEx_Init(&DB);
|
||||
BlockIndex = 0xFFFFFFFF;
|
||||
OutBuffer = NULL;
|
||||
OutBufferSize = 0;
|
||||
}
|
||||
|
||||
~C7zArchive()
|
||||
{
|
||||
if (OutBuffer != NULL)
|
||||
{
|
||||
IAlloc_Free(&g_Alloc, OutBuffer);
|
||||
}
|
||||
SzArEx_Free(&DB, &g_Alloc);
|
||||
}
|
||||
|
||||
SRes Open()
|
||||
{
|
||||
return SzArEx_Open(&DB, &LookStream.s, &g_Alloc, &g_Alloc);
|
||||
}
|
||||
|
||||
SRes Extract(UInt32 file_index, char *buffer)
|
||||
{
|
||||
size_t offset, out_size_processed;
|
||||
SRes res = SzAr_Extract(&DB, &LookStream.s, file_index,
|
||||
&BlockIndex, &OutBuffer, &OutBufferSize,
|
||||
&offset, &out_size_processed,
|
||||
&g_Alloc, &g_Alloc);
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
memcpy(buffer, OutBuffer + offset, out_size_processed);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
class FWadCollection::WadFileRecord : public FileReader
|
||||
{
|
||||
public:
|
||||
WadFileRecord (FILE *file);
|
||||
WadFileRecord (const char * buffer, int length);
|
||||
WadFileRecord (const char *buffer, int length);
|
||||
~WadFileRecord ();
|
||||
|
||||
long Seek (long offset, int origin);
|
||||
long Read (void *buffer, long len);
|
||||
|
||||
const char * MemoryData;
|
||||
const char *MemoryData;
|
||||
C7zArchive *Archive;
|
||||
|
||||
char *Name;
|
||||
FString Name;
|
||||
DWORD FirstLump;
|
||||
DWORD LastLump;
|
||||
|
||||
};
|
||||
|
||||
struct FEmbeddedWAD
|
||||
{
|
||||
union
|
||||
{
|
||||
C7zArchive *Archive;
|
||||
FZipCentralDirectoryInfo *Zip;
|
||||
};
|
||||
int Position;
|
||||
};
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
|
@ -129,8 +258,6 @@ void W_SysWadInit ();
|
|||
|
||||
static void PrintLastError ();
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
FWadCollection Wads;
|
||||
|
@ -285,7 +412,7 @@ int FWadCollection::AddExternalFile(const char *filename)
|
|||
|
||||
lump.fullname = copystring(filename);
|
||||
memset(lump.name, 0, sizeof(lump.name));
|
||||
lump.wadnum=-1;
|
||||
lump.wadnum = -1;
|
||||
lump.flags = LUMPF_EXTERNAL;
|
||||
lump.position = 0;
|
||||
lump.namespc = ns_global;
|
||||
|
@ -365,7 +492,7 @@ int STACK_ARGS FWadCollection::lumpcmp(const void * a, const void * b)
|
|||
}
|
||||
|
||||
|
||||
void FWadCollection::AddFile (const char *filename, const char * data, int length)
|
||||
void FWadCollection::AddFile (const char *filename, const char *data, int length)
|
||||
{
|
||||
WadFileRecord *wadinfo;
|
||||
MergedHeader header;
|
||||
|
@ -375,10 +502,10 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
|
|||
int startlump;
|
||||
wadlump_t* fileinfo = NULL, *fileinfo2free = NULL;
|
||||
wadlump_t singleinfo;
|
||||
TArray<FZipCentralDirectoryInfo *> EmbeddedWADs;
|
||||
void * directory = NULL;
|
||||
TArray<FEmbeddedWAD> EmbeddedWADs;
|
||||
void *directory = NULL;
|
||||
|
||||
if (length==-1)
|
||||
if (length == -1)
|
||||
{
|
||||
// open the file and add to directory
|
||||
handle = fopen (filename, "rb");
|
||||
|
@ -409,7 +536,7 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
|
|||
return;
|
||||
}
|
||||
|
||||
wadinfo->Name = copystring (filename);
|
||||
wadinfo->Name = filename;
|
||||
|
||||
if (header.magic[0] == IWAD_ID || header.magic[0] == PWAD_ID)
|
||||
{ // This is a WAD file
|
||||
|
@ -516,6 +643,7 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
|
|||
if (centraldir == 0)
|
||||
{
|
||||
Printf("\n%s: ZIP file corrupt!\n", filename);
|
||||
delete wadinfo;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -528,6 +656,7 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
|
|||
info.FirstDisk != 0 || info.DiskNumber != 0)
|
||||
{
|
||||
Printf("\n%s: Multipart Zip files are not supported.\n", filename);
|
||||
delete wadinfo;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -546,7 +675,6 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
|
|||
FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr;
|
||||
|
||||
char name[256];
|
||||
char base[256];
|
||||
|
||||
int len = LittleShort(zip_fh->NameLength);
|
||||
strncpy(name, dirptr + sizeof(FZipCentralDirectoryInfo), MIN<int>(len, 255));
|
||||
|
@ -589,68 +717,24 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
|
|||
// They must be extracted and added separately to the lump list.
|
||||
// WADs in subdirectories are added to the lump directory.
|
||||
// Embedded .zips are ignored for now. But they should be allowed later!
|
||||
char * c = strstr(name, ".wad");
|
||||
if (c && strlen(c)==4 && !strchr(name, '/'))
|
||||
char *c = strstr(name, ".wad");
|
||||
if (c && strlen(c) == 4 && !strchr(name, '/'))
|
||||
{
|
||||
EmbeddedWADs.Push(zip_fh);
|
||||
FEmbeddedWAD embed;
|
||||
embed.Zip = zip_fh;
|
||||
embed.Position = -1;
|
||||
EmbeddedWADs.Push(embed);
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
//ExtractFileBase(name, base);
|
||||
char *lname = strrchr(name,'/');
|
||||
if (!lname) lname = name;
|
||||
else lname++;
|
||||
strcpy(base, lname);
|
||||
char *dot = strrchr(base, '.');
|
||||
if (dot) *dot = 0;
|
||||
uppercopy(lump_p->name, base);
|
||||
lump_p->name[8] = 0;
|
||||
lump_p->fullname = copystring(name);
|
||||
lump_p->ZipNameSetup(name);
|
||||
lump_p->size = LittleLong(zip_fh->UncompressedSize);
|
||||
|
||||
// Map some directories to WAD namespaces.
|
||||
// Note that some of these namespaces don't exist in WADS.
|
||||
// CheckNumForName will handle any request for these namespaces accordingly.
|
||||
lump_p->namespc = !strncmp(name, "flats/", 6) ? ns_flats :
|
||||
!strncmp(name, "textures/", 9) ? ns_newtextures :
|
||||
!strncmp(name, "hires/", 6) ? ns_hires :
|
||||
!strncmp(name, "sprites/", 8) ? ns_sprites :
|
||||
!strncmp(name, "colormaps/", 10) ? ns_colormaps :
|
||||
!strncmp(name, "acs/", 4) ? ns_acslibrary :
|
||||
!strncmp(name, "voices/", 7) ? ns_strifevoices :
|
||||
!strncmp(name, "patches/", 8) ? ns_patches :
|
||||
!strncmp(name, "graphics/", 9) ? ns_graphics :
|
||||
!strncmp(name, "sounds/", 7) ? ns_sounds :
|
||||
!strncmp(name, "music/", 6) ? ns_music :
|
||||
!strchr(name, '/') ? ns_global : -1;
|
||||
|
||||
// Anything that is not in one of these subdirectories or the main directory
|
||||
// should not be accessible through the standard WAD functions but only through
|
||||
// the ones which look for the full name.
|
||||
if (lump_p->namespc == -1)
|
||||
{
|
||||
memset(lump_p->name, 0, 8);
|
||||
}
|
||||
|
||||
lump_p->wadnum = (WORD)Wads.Size();
|
||||
lump_p->flags = (zip_fh->Method != METHOD_STORED) ? LUMPF_COMPRESSED|LUMPF_ZIPFILE : LUMPF_ZIPFILE;
|
||||
lump_p->method = zip_fh->Method;
|
||||
lump_p->compressedsize = LittleLong(zip_fh->CompressedSize);
|
||||
|
||||
// Since '\' can't be used as a file name's part inside a ZIP
|
||||
// we have to work around this for sprites because it is a valid
|
||||
// frame character.
|
||||
if (lump_p->namespc == ns_sprites)
|
||||
{
|
||||
char * c;
|
||||
|
||||
while ((c = (char*)memchr(lump_p->name, '^', 8)))
|
||||
{
|
||||
*c = '\\';
|
||||
}
|
||||
}
|
||||
|
||||
// The start of the file will be determined the first time it is accessed.
|
||||
lump_p->flags |= LUMPF_NEEDFILESTART;
|
||||
lump_p->position = LittleLong(zip_fh->LocalHeaderOffset);
|
||||
|
@ -659,10 +743,91 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
|
|||
// Resize the lump record array to its actual size
|
||||
NumLumps -= skipped;
|
||||
LumpInfo.Resize(NumLumps);
|
||||
Printf (" (%d files)", LittleShort(info.NumEntries) - skipped);
|
||||
|
||||
// Entries in Zips are sorted alphabetically.
|
||||
qsort(&LumpInfo[startlump], NumLumps - startlump, sizeof(LumpRecord), lumpcmp);
|
||||
}
|
||||
else if (memcmp(header.sevenzip, k7zSignature, k7zSignatureSize) == 0)
|
||||
{
|
||||
C7zArchive *arc = new C7zArchive(wadinfo);
|
||||
int skipped = 0;
|
||||
SRes res;
|
||||
|
||||
res = arc->Open();
|
||||
if (res != SZ_OK)
|
||||
{
|
||||
delete arc;
|
||||
delete wadinfo;
|
||||
Printf("\n%s: ", filename);
|
||||
if (res == SZ_ERROR_UNSUPPORTED)
|
||||
{
|
||||
Printf("Decoder does not support this archive\n");
|
||||
}
|
||||
else if (res == SZ_ERROR_MEM)
|
||||
{
|
||||
Printf("Cannot allocate memory\n");
|
||||
}
|
||||
else if (res == SZ_ERROR_CRC)
|
||||
{
|
||||
Printf("CRC error\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("error #%d\n", res);
|
||||
}
|
||||
return;
|
||||
}
|
||||
wadinfo->Archive = arc;
|
||||
NumLumps += arc->DB.db.NumFiles;
|
||||
LumpInfo.Resize(NumLumps);
|
||||
lump_p = &LumpInfo[startlump];
|
||||
|
||||
for (int i = 0; i < arc->DB.db.NumFiles; ++i)
|
||||
{
|
||||
CSzFileItem *file = &arc->DB.db.Files[i];
|
||||
char name[256];
|
||||
|
||||
// skip Directories
|
||||
if (file->IsDir)
|
||||
{
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
strncpy(name, file->Name, countof(name)-1);
|
||||
name[countof(name)-1] = 0;
|
||||
FixPathSeperator(name);
|
||||
strlwr(name);
|
||||
|
||||
// Check for embedded WADs in the root directory.
|
||||
char *c = strstr(name, ".wad");
|
||||
if (c && strlen(c) == 4 && !strchr(name, '/'))
|
||||
{
|
||||
FEmbeddedWAD embed;
|
||||
embed.Archive = arc;
|
||||
embed.Position = i;
|
||||
EmbeddedWADs.Push(embed);
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
lump_p->ZipNameSetup(name);
|
||||
lump_p->size = file->Size;
|
||||
lump_p->wadnum = (WORD)Wads.Size();
|
||||
lump_p->flags = LUMPF_7ZFILE;
|
||||
lump_p->position = i;
|
||||
lump_p->compressedsize = -1;
|
||||
lump_p++;
|
||||
}
|
||||
// Resize the lump record array to its actual size
|
||||
NumLumps -= skipped;
|
||||
LumpInfo.Resize(NumLumps);
|
||||
Printf (" (%u files)", arc->DB.db.NumFiles - skipped);
|
||||
|
||||
// Entries in archives are sorted alphabetically
|
||||
qsort(&LumpInfo[startlump], NumLumps - startlump, sizeof(LumpRecord), lumpcmp);
|
||||
}
|
||||
else
|
||||
{ // This is just a single lump file
|
||||
fileinfo2free = NULL;
|
||||
|
@ -678,7 +843,8 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
|
|||
// Fill in lumpinfo
|
||||
if (header.magic[0] != RFF_ID &&
|
||||
header.magic[0] != ZIP_ID &&
|
||||
(header.magic[0] != GRP_ID_0 || header.magic[1] != GRP_ID_1 || header.magic[2] != GRP_ID_2))
|
||||
(header.magic[0] != GRP_ID_0 || header.magic[1] != GRP_ID_1 || header.magic[2] != GRP_ID_2) &&
|
||||
memcmp(header.sevenzip, k7zSignature, k7zSignatureSize))
|
||||
{
|
||||
LumpInfo.Resize(NumLumps);
|
||||
lump_p = &LumpInfo[startlump];
|
||||
|
@ -717,54 +883,147 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt
|
|||
if (EmbeddedWADs.Size())
|
||||
{
|
||||
char path[256];
|
||||
size_t len;
|
||||
char *buffer;
|
||||
|
||||
mysnprintf(path, countof(path), "%s:", filename);
|
||||
char * wadstr = path+strlen(path);
|
||||
char *wadstr = path + strlen(path);
|
||||
|
||||
for(unsigned int i = 0; i < EmbeddedWADs.Size(); i++)
|
||||
{
|
||||
FZipCentralDirectoryInfo *zip_fh = EmbeddedWADs[i];
|
||||
FZipLocalFileHeader localHeader;
|
||||
FEmbeddedWAD *embed = &EmbeddedWADs[i];
|
||||
|
||||
*wadstr = 0;
|
||||
size_t len = LittleShort(zip_fh->NameLength);
|
||||
if (len + strlen(path) > 255) len = 255 - strlen(path);
|
||||
strncpy(wadstr, ((char*)zip_fh) + sizeof(FZipCentralDirectoryInfo), len);
|
||||
wadstr[len] = 0;
|
||||
|
||||
DWORD size = LittleLong(zip_fh->UncompressedSize);
|
||||
char *buffer = new char[size];
|
||||
|
||||
int position = LittleLong(zip_fh->LocalHeaderOffset) ;
|
||||
|
||||
wadinfo->Seek(position, SEEK_SET);
|
||||
wadinfo->Read(&localHeader, sizeof(localHeader));
|
||||
position += sizeof(FZipLocalFileHeader) + LittleShort(localHeader.ExtraLength) + LittleShort(zip_fh->NameLength);
|
||||
|
||||
wadinfo->Seek(position, SEEK_SET);
|
||||
if (LittleShort(zip_fh->Method) == METHOD_DEFLATE)
|
||||
if (embed->Position == -1)
|
||||
{
|
||||
FileReaderZ frz(*wadinfo, true);
|
||||
frz.Read(buffer, size);
|
||||
}
|
||||
else if (LittleShort(zip_fh->Method) == METHOD_LZMA)
|
||||
{
|
||||
FileReaderLZMA frz(*wadinfo, size, true);
|
||||
frz.Read(buffer, size);
|
||||
}
|
||||
else if (LittleShort(zip_fh->Method) == METHOD_BZIP2)
|
||||
{
|
||||
FileReaderBZ2 frz(*wadinfo);
|
||||
frz.Read(buffer, size);
|
||||
FZipCentralDirectoryInfo *zip_fh = embed->Zip;
|
||||
FZipLocalFileHeader localHeader;
|
||||
|
||||
*wadstr = 0;
|
||||
len = LittleShort(zip_fh->NameLength);
|
||||
if (len + strlen(path) > 255)
|
||||
{
|
||||
len = 255 - strlen(path);
|
||||
}
|
||||
strncpy(wadstr, ((char*)zip_fh) + sizeof(FZipCentralDirectoryInfo), len);
|
||||
wadstr[len] = 0;
|
||||
|
||||
DWORD size = LittleLong(zip_fh->UncompressedSize);
|
||||
buffer = new char[size];
|
||||
|
||||
int position = LittleLong(zip_fh->LocalHeaderOffset);
|
||||
|
||||
wadinfo->Seek(position, SEEK_SET);
|
||||
wadinfo->Read(&localHeader, sizeof(localHeader));
|
||||
position += sizeof(FZipLocalFileHeader) + LittleShort(localHeader.ExtraLength) + LittleShort(zip_fh->NameLength);
|
||||
|
||||
wadinfo->Seek(position, SEEK_SET);
|
||||
if (LittleShort(zip_fh->Method) == METHOD_DEFLATE)
|
||||
{
|
||||
FileReaderZ frz(*wadinfo, true);
|
||||
frz.Read(buffer, size);
|
||||
}
|
||||
else if (LittleShort(zip_fh->Method) == METHOD_LZMA)
|
||||
{
|
||||
FileReaderLZMA frz(*wadinfo, size, true);
|
||||
frz.Read(buffer, size);
|
||||
}
|
||||
else if (LittleShort(zip_fh->Method) == METHOD_BZIP2)
|
||||
{
|
||||
FileReaderBZ2 frz(*wadinfo);
|
||||
frz.Read(buffer, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
wadinfo->Read(buffer, size);
|
||||
}
|
||||
AddFile(path, buffer, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
wadinfo->Read(buffer, size);
|
||||
CSzFileItem *file = &embed->Archive->DB.db.Files[embed->Position];
|
||||
len = strlen(file->Name);
|
||||
if (len + strlen(path) > 255)
|
||||
{
|
||||
len = 255 - strlen(path);
|
||||
}
|
||||
strncpy(wadstr, file->Name, len);
|
||||
wadstr[len] = 0;
|
||||
|
||||
buffer = new char[file->Size];
|
||||
if (embed->Archive->Extract(embed->Position, buffer) == SZ_OK)
|
||||
{
|
||||
AddFile(path, buffer, file->Size);
|
||||
}
|
||||
}
|
||||
AddFile(path, buffer, size);
|
||||
}
|
||||
}
|
||||
if (directory != NULL) free(directory);
|
||||
if (directory != NULL)
|
||||
{
|
||||
free(directory);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FWadCollection :: LumpRecord :: ZipNameSetup
|
||||
//
|
||||
// For lumps from an archive, determine this lump's wad-compatible name,
|
||||
// namespace, and set the fullname.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FWadCollection::LumpRecord::ZipNameSetup(char *iname)
|
||||
{
|
||||
char base[256];
|
||||
char *lname = strrchr(iname,'/');
|
||||
lname = (lname == NULL) ? iname : lname + 1;
|
||||
strcpy(base, lname);
|
||||
char *dot = strrchr(base, '.');
|
||||
if (dot != NULL)
|
||||
{
|
||||
*dot = 0;
|
||||
}
|
||||
uppercopy(name, base);
|
||||
name[8] = 0;
|
||||
fullname = copystring(iname);
|
||||
|
||||
// Map some directories to WAD namespaces.
|
||||
// Note that some of these namespaces don't exist in WADS.
|
||||
// CheckNumForName will handle any request for these namespaces accordingly.
|
||||
namespc = !strncmp(iname, "flats/", 6) ? ns_flats :
|
||||
!strncmp(iname, "textures/", 9) ? ns_newtextures :
|
||||
!strncmp(iname, "hires/", 6) ? ns_hires :
|
||||
!strncmp(iname, "sprites/", 8) ? ns_sprites :
|
||||
!strncmp(iname, "colormaps/", 10) ? ns_colormaps :
|
||||
!strncmp(iname, "acs/", 4) ? ns_acslibrary :
|
||||
!strncmp(iname, "voices/", 7) ? ns_strifevoices :
|
||||
!strncmp(iname, "patches/", 8) ? ns_patches :
|
||||
!strncmp(iname, "graphics/", 9) ? ns_graphics :
|
||||
!strncmp(iname, "sounds/", 7) ? ns_sounds :
|
||||
!strncmp(iname, "music/", 6) ? ns_music :
|
||||
!strchr(iname, '/') ? ns_global :
|
||||
-1;
|
||||
|
||||
// Anything that is not in one of these subdirectories or the main directory
|
||||
// should not be accessible through the standard WAD functions but only through
|
||||
// the ones which look for the full name.
|
||||
if (namespc == -1)
|
||||
{
|
||||
memset(name, 0, 8);
|
||||
}
|
||||
|
||||
// Since '\' can't be used as a file name's part inside a ZIP
|
||||
// we have to work around this for sprites because it is a valid
|
||||
// frame character.
|
||||
else if (namespc == ns_sprites)
|
||||
{
|
||||
char *c;
|
||||
|
||||
while ((c = (char*)memchr(name, '^', 8)))
|
||||
{
|
||||
*c = '\\';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1797,39 +2056,29 @@ FWadLump FWadCollection::OpenLumpNum (int lump)
|
|||
}
|
||||
|
||||
l = &LumpInfo[lump];
|
||||
wad = l->wadnum >= 0? Wads[l->wadnum] : NULL;
|
||||
wad = l->wadnum >= 0 ? Wads[l->wadnum] : NULL;
|
||||
|
||||
if (l->flags & LUMPF_NEEDFILESTART)
|
||||
{
|
||||
SetLumpAddress(l);
|
||||
}
|
||||
|
||||
if (wad != NULL) wad->Seek (l->position, SEEK_SET);
|
||||
if (l->flags & LUMPF_7ZFILE)
|
||||
{
|
||||
// An entry in a .7z file
|
||||
char *buffer = new char[l->size + 1]; // the last byte is used as a reference counter
|
||||
|
||||
if (l->flags & LUMPF_COMPRESSED)
|
||||
}
|
||||
|
||||
if (wad != NULL)
|
||||
{
|
||||
wad->Seek (l->position, SEEK_SET);
|
||||
}
|
||||
|
||||
if (l->flags & (LUMPF_COMPRESSED | LUMPF_7ZFILE))
|
||||
{
|
||||
// A compressed entry in a .zip file
|
||||
char *buffer = new char[l->size + 1]; // the last byte is used as a reference counter
|
||||
buffer[l->size] = 0;
|
||||
if (l->method == METHOD_DEFLATE)
|
||||
{
|
||||
FileReaderZ frz(*wad, true);
|
||||
frz.Read(buffer, l->size);
|
||||
}
|
||||
else if (l->method == METHOD_LZMA)
|
||||
{
|
||||
FileReaderLZMA frz(*wad, l->size, true);
|
||||
frz.Read(buffer, l->size);
|
||||
}
|
||||
else if (l->method == METHOD_BZIP2)
|
||||
{
|
||||
FileReaderBZ2 frz(*wad);
|
||||
frz.Read(buffer, l->size);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0); // Should not get here
|
||||
}
|
||||
char *buffer = ReadZipLump(l);
|
||||
return FWadLump(buffer, l->size, true);
|
||||
}
|
||||
else if (l->flags & LUMPF_EXTERNAL)
|
||||
|
@ -1841,7 +2090,7 @@ FWadLump FWadCollection::OpenLumpNum (int lump)
|
|||
{
|
||||
FString name;
|
||||
|
||||
name.Format("%s/%s", wad->Name, l->fullname);
|
||||
name << wad->Name << '/' << l->fullname;
|
||||
f = fopen(name, "rb");
|
||||
}
|
||||
else
|
||||
|
@ -1898,38 +2147,18 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump)
|
|||
}
|
||||
|
||||
l = &LumpInfo[lump];
|
||||
wad = l->wadnum >= 0? Wads[l->wadnum] : NULL;
|
||||
wad = l->wadnum >= 0 ? Wads[l->wadnum] : NULL;
|
||||
|
||||
if (l->flags & LUMPF_NEEDFILESTART)
|
||||
{
|
||||
SetLumpAddress(l);
|
||||
}
|
||||
|
||||
if (l->flags & LUMPF_COMPRESSED)
|
||||
if (l->flags & (LUMPF_COMPRESSED | LUMPF_7ZFILE))
|
||||
{
|
||||
// A compressed entry in a .zip file
|
||||
int address = wad->Tell(); // read from the existing WadFileRecord without reopening
|
||||
char *buffer = new char[l->size + 1]; // the last byte is used as a reference counter
|
||||
wad->Seek(l->position, SEEK_SET);
|
||||
if (l->method == METHOD_DEFLATE)
|
||||
{
|
||||
FileReaderZ frz(*wad, true);
|
||||
frz.Read(buffer, l->size);
|
||||
}
|
||||
else if (l->method == METHOD_LZMA)
|
||||
{
|
||||
FileReaderLZMA frz(*wad, l->size, true);
|
||||
frz.Read(buffer, l->size);
|
||||
}
|
||||
else if (l->method == METHOD_BZIP2)
|
||||
{
|
||||
FileReaderBZ2 frz(*wad);
|
||||
frz.Read(buffer, l->size);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0); // Should not get here
|
||||
}
|
||||
char *buffer = ReadZipLump(l);
|
||||
wad->Seek(address, SEEK_SET);
|
||||
return new FWadLump(buffer, l->size, true); //... but restore the file pointer afterward!
|
||||
}
|
||||
|
@ -1942,7 +2171,7 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump)
|
|||
{
|
||||
FString name;
|
||||
|
||||
name.Format("%s/%s", wad->Name, l->fullname);
|
||||
name << wad->Name << '/' << l->fullname;
|
||||
f = fopen(name, "rb");
|
||||
}
|
||||
else
|
||||
|
@ -1977,7 +2206,7 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump)
|
|||
f = fopen (wad->Name, "rb");
|
||||
if (f == NULL)
|
||||
{
|
||||
I_Error ("Could not reopen %s\n", wad->Name);
|
||||
I_Error ("Could not reopen %s\n", wad->Name.GetChars());
|
||||
}
|
||||
|
||||
fseek (f, l->position, SEEK_SET);
|
||||
|
@ -1986,6 +2215,50 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump)
|
|||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FWadCollection :: ReadZipLump
|
||||
//
|
||||
// Extracts a compressed file from a zip into memory.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
char *FWadCollection::ReadZipLump(LumpRecord *l)
|
||||
{
|
||||
WadFileRecord *wad = Wads[l->wadnum];
|
||||
char *buffer = new char[l->size + 1]; // the last byte is used as a reference counter
|
||||
buffer[l->size] = 0;
|
||||
|
||||
if (!(l->flags & LUMPF_7ZFILE))
|
||||
{
|
||||
wad->Seek(l->position, SEEK_SET);
|
||||
if (l->method == METHOD_DEFLATE)
|
||||
{
|
||||
FileReaderZ frz(*wad, true);
|
||||
frz.Read(buffer, l->size);
|
||||
}
|
||||
else if (l->method == METHOD_LZMA)
|
||||
{
|
||||
FileReaderLZMA frz(*wad, l->size, true);
|
||||
frz.Read(buffer, l->size);
|
||||
}
|
||||
else if (l->method == METHOD_BZIP2)
|
||||
{
|
||||
FileReaderBZ2 frz(*wad);
|
||||
frz.Read(buffer, l->size);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0); // Should not get here
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wad->Archive->Extract(l->position, buffer);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetFileReader
|
||||
|
@ -2142,7 +2415,7 @@ void FWadCollection::SkinHack (int baselump)
|
|||
"The maps in %s will not be loaded because it has a skin.\n"
|
||||
TEXTCOLOR_BLUE
|
||||
"You should remove the skin from the wad to play these maps.\n",
|
||||
Wads[LumpInfo[baselump].wadnum]->Name);
|
||||
Wads[LumpInfo[baselump].wadnum]->Name.GetChars());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2165,13 +2438,12 @@ void BloodCrypt (void *data, int key, int len)
|
|||
// WadFileRecord ------------------------------------------------------------
|
||||
|
||||
FWadCollection::WadFileRecord::WadFileRecord (FILE *file)
|
||||
: FileReader(file), Name(NULL), FirstLump(0), LastLump(0)
|
||||
: FileReader(file), MemoryData(NULL), Archive(NULL), FirstLump(0), LastLump(0)
|
||||
{
|
||||
MemoryData=NULL;
|
||||
}
|
||||
|
||||
FWadCollection::WadFileRecord::WadFileRecord (const char * mem, int len)
|
||||
: FileReader(), MemoryData(mem), Name(NULL), FirstLump(0), LastLump(0)
|
||||
FWadCollection::WadFileRecord::WadFileRecord (const char *mem, int len)
|
||||
: FileReader(), MemoryData(mem), Archive(NULL), FirstLump(0), LastLump(0)
|
||||
{
|
||||
Length = len;
|
||||
FilePos = StartPos = 0;
|
||||
|
@ -2179,55 +2451,62 @@ FWadCollection::WadFileRecord::WadFileRecord (const char * mem, int len)
|
|||
|
||||
FWadCollection::WadFileRecord::~WadFileRecord ()
|
||||
{
|
||||
if (Name != NULL)
|
||||
{
|
||||
delete[] Name;
|
||||
}
|
||||
if (MemoryData != NULL)
|
||||
{
|
||||
delete [] MemoryData;
|
||||
delete[] MemoryData;
|
||||
}
|
||||
if (Archive != NULL)
|
||||
{
|
||||
delete Archive;
|
||||
}
|
||||
}
|
||||
|
||||
long FWadCollection::WadFileRecord::Seek (long offset, int origin)
|
||||
{
|
||||
if (MemoryData==NULL) return FileReader::Seek(offset, origin);
|
||||
if (MemoryData == NULL)
|
||||
{
|
||||
return FileReader::Seek(offset, origin);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (origin)
|
||||
{
|
||||
case SEEK_CUR:
|
||||
offset+=FilePos;
|
||||
offset += FilePos;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
offset+=Length;
|
||||
offset += Length;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (offset<0) offset=0;
|
||||
else if (offset>Length) offset=Length;
|
||||
FilePos=offset;
|
||||
FilePos = clamp<long>(offset, 0, Length);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
long FWadCollection::WadFileRecord::Read (void *buffer, long len)
|
||||
{
|
||||
if (MemoryData==NULL) return FileReader::Read(buffer, len);
|
||||
if (MemoryData == NULL)
|
||||
{
|
||||
return FileReader::Read(buffer, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FilePos+len>Length) len=Length-FilePos;
|
||||
memcpy(buffer, MemoryData+FilePos, len);
|
||||
FilePos+=len;
|
||||
if (FilePos + len > Length)
|
||||
{
|
||||
len = Length - FilePos;
|
||||
}
|
||||
memcpy(buffer, MemoryData + FilePos, len);
|
||||
FilePos += len;
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
// FWadLump -----------------------------------------------------------------
|
||||
|
||||
// FWadLump -----------------------------------------------------------------
|
||||
|
||||
FWadLump::FWadLump ()
|
||||
: FileReader(), SourceData(NULL), DestroySource(false), Encrypted(false)
|
||||
{
|
||||
|
|
|
@ -69,6 +69,7 @@ enum
|
|||
LUMPF_ZIPFILE = 4, // Inside a Zip file - used to enforce use of special directories insize Zips
|
||||
LUMPF_NEEDFILESTART = 8, // Still need to process local file header to find file start inside a zip
|
||||
LUMPF_EXTERNAL = 16, // Lump is from an external file that won't be kept open permanently
|
||||
LUMPF_7ZFILE = 32, // Inside a 7z archive; position is its index in the archive
|
||||
};
|
||||
|
||||
|
||||
|
@ -168,7 +169,7 @@ public:
|
|||
enum { IWAD_FILENUM = 1 };
|
||||
|
||||
void InitMultipleFiles (wadlist_t **filenames);
|
||||
void AddFile (const char *filename, const char * data=NULL,int length=-1);
|
||||
void AddFile (const char *filename, const char *data=NULL, int length=-1);
|
||||
int CheckIfWadLoaded (const char *name);
|
||||
|
||||
const char *GetWadName (int wadnum) const;
|
||||
|
@ -235,7 +236,7 @@ protected:
|
|||
|
||||
|
||||
TArray<LumpRecord> LumpInfo;
|
||||
TArray<WadFileRecord *>Wads;
|
||||
TArray<WadFileRecord *> Wads;
|
||||
DWORD NumLumps; // Not necessarily the same as LumpInfo.Size()
|
||||
DWORD NumWads;
|
||||
|
||||
|
@ -247,6 +248,8 @@ protected:
|
|||
bool IsMarker (const LumpRecord *lump, const char *marker) const;
|
||||
void FindStrifeTeaserVoices ();
|
||||
|
||||
char *ReadZipLump(LumpRecord *l);
|
||||
|
||||
private:
|
||||
static int STACK_ARGS lumpcmp(const void * a, const void * b);
|
||||
void ScanForFlatHack (int startlump);
|
||||
|
|
Loading…
Reference in a new issue