mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-01-18 14:41:40 +00:00
Merge branch 'master' into scripting
Conflicts: src/actor.h src/g_hexen/a_clericstaff.cpp src/p_enemy.cpp src/p_interaction.cpp src/p_local.h src/p_mobj.cpp src/thingdef/thingdef_codeptr.cpp
This commit is contained in:
commit
bf747075e8
179 changed files with 10307 additions and 4814 deletions
|
@ -1203,10 +1203,6 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\helpers\tarray.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="it"
|
||||
|
|
219
lzma/C/7z.h
219
lzma/C/7z.h
|
@ -1,89 +1,57 @@
|
|||
/* 7z.h -- 7z interface
|
||||
2010-03-11 : Igor Pavlov : Public domain */
|
||||
2015-11-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_H
|
||||
#define __7Z_H
|
||||
|
||||
#include "7zBuf.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define k7zStartHeaderSize 0x20
|
||||
#define k7zSignatureSize 6
|
||||
extern Byte k7zSignature[k7zSignatureSize];
|
||||
#define k7zMajorVersion 0
|
||||
|
||||
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
|
||||
};
|
||||
extern const Byte k7zSignature[k7zSignatureSize];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 NumInStreams;
|
||||
UInt32 NumOutStreams;
|
||||
UInt64 MethodID;
|
||||
CBuf Props;
|
||||
} CSzCoderInfo;
|
||||
const Byte *Data;
|
||||
size_t Size;
|
||||
} CSzData;
|
||||
|
||||
void SzCoderInfo_Init(CSzCoderInfo *p);
|
||||
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
|
||||
/* CSzCoderInfo & CSzFolder support only default methods */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t PropsOffset;
|
||||
UInt32 MethodID;
|
||||
Byte NumStreams;
|
||||
Byte PropsSize;
|
||||
} CSzCoderInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 InIndex;
|
||||
UInt32 OutIndex;
|
||||
} CSzBindPair;
|
||||
} CSzBond;
|
||||
|
||||
#define SZ_NUM_CODERS_IN_FOLDER_MAX 4
|
||||
#define SZ_NUM_BONDS_IN_FOLDER_MAX 3
|
||||
#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzCoderInfo *Coders;
|
||||
CSzBindPair *BindPairs;
|
||||
UInt32 *PackStreams;
|
||||
UInt64 *UnpackSizes;
|
||||
UInt32 NumCoders;
|
||||
UInt32 NumBindPairs;
|
||||
UInt32 NumBonds;
|
||||
UInt32 NumPackStreams;
|
||||
int UnpackCRCDefined;
|
||||
UInt32 UnpackCRC;
|
||||
|
||||
UInt32 NumUnpackStreams;
|
||||
UInt32 UnpackStream;
|
||||
UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];
|
||||
CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX];
|
||||
CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];
|
||||
} 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);
|
||||
|
||||
SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
|
||||
ILookInStream *stream, UInt64 startPos,
|
||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
||||
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -93,38 +61,97 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
CNtfsFileTime MTime;
|
||||
UInt64 Size;
|
||||
UInt32 Crc;
|
||||
UInt32 Attrib;
|
||||
Byte HasStream;
|
||||
Byte IsDir;
|
||||
Byte IsAnti;
|
||||
Byte CrcDefined;
|
||||
Byte MTimeDefined;
|
||||
Byte AttribDefined;
|
||||
} CSzFileItem;
|
||||
|
||||
void SzFile_Init(CSzFileItem *p);
|
||||
Byte *Defs; /* MSB 0 bit numbering */
|
||||
UInt32 *Vals;
|
||||
} CSzBitUi32s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte *Defs; /* MSB 0 bit numbering */
|
||||
// UInt64 *Vals;
|
||||
CNtfsFileTime *Vals;
|
||||
} CSzBitUi64s;
|
||||
|
||||
#define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)
|
||||
|
||||
#define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt64 *PackSizes;
|
||||
Byte *PackCRCsDefined;
|
||||
UInt32 *PackCRCs;
|
||||
CSzFolder *Folders;
|
||||
CSzFileItem *Files;
|
||||
UInt32 NumPackStreams;
|
||||
UInt32 NumFolders;
|
||||
UInt32 NumFiles;
|
||||
|
||||
UInt64 *PackPositions; // NumPackStreams + 1
|
||||
CSzBitUi32s FolderCRCs; // NumFolders
|
||||
|
||||
size_t *FoCodersOffsets; // NumFolders + 1
|
||||
UInt32 *FoStartPackStreamIndex; // NumFolders + 1
|
||||
UInt32 *FoToCoderUnpackSizes; // NumFolders + 1
|
||||
Byte *FoToMainUnpackSizeIndex; // NumFolders
|
||||
UInt64 *CoderUnpackSizes; // for all coders in all folders
|
||||
|
||||
Byte *CodersData;
|
||||
} CSzAr;
|
||||
|
||||
void SzAr_Init(CSzAr *p);
|
||||
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
||||
UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex);
|
||||
|
||||
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
|
||||
ILookInStream *stream, UInt64 startPos,
|
||||
Byte *outBuffer, size_t outSize,
|
||||
ISzAlloc *allocMain);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzAr db;
|
||||
|
||||
UInt64 startPosAfterHeader;
|
||||
UInt64 dataPos;
|
||||
|
||||
UInt32 NumFiles;
|
||||
|
||||
UInt64 *UnpackPositions; // NumFiles + 1
|
||||
// Byte *IsEmptyFiles;
|
||||
Byte *IsDirs;
|
||||
CSzBitUi32s CRCs;
|
||||
|
||||
CSzBitUi32s Attribs;
|
||||
// CSzBitUi32s Parents;
|
||||
CSzBitUi64s MTime;
|
||||
CSzBitUi64s CTime;
|
||||
|
||||
UInt32 *FolderToFile; // NumFolders + 1
|
||||
UInt32 *FileToFolder; // NumFiles
|
||||
|
||||
size_t *FileNameOffsets; /* in 2-byte steps */
|
||||
Byte *FileNames; /* UTF-16-LE */
|
||||
} CSzArEx;
|
||||
|
||||
#define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i))
|
||||
|
||||
#define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i])
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
if dest == NULL, the return value specifies the required size of the buffer,
|
||||
in 16-bit characters, including the null-terminating character.
|
||||
if dest != NULL, the return value specifies the number of 16-bit characters that
|
||||
are written to the dest, including the null-terminating character. */
|
||||
|
||||
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
|
||||
|
||||
/*
|
||||
size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex);
|
||||
UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
SzExtract extracts file from archive
|
||||
SzArEx_Extract extracts file from archive
|
||||
|
||||
*outBuffer must be 0 before first call for each new archive.
|
||||
|
||||
|
@ -143,35 +170,6 @@ void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
|||
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzAr db;
|
||||
|
||||
UInt64 startPosAfterHeader;
|
||||
UInt64 dataPos;
|
||||
|
||||
UInt32 *FolderStartPackStreamIndex;
|
||||
UInt64 *PackStreamStartPositions;
|
||||
UInt32 *FolderStartFileIndex;
|
||||
UInt32 *FileIndexToFolderIndexMap;
|
||||
|
||||
size_t *FileNameOffsets; /* in 2-byte steps */
|
||||
CBuf FileNames; /* UTF-16-LE */
|
||||
} 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);
|
||||
|
||||
/*
|
||||
if dest == NULL, the return value specifies the required size of the buffer,
|
||||
in 16-bit characters, including the null-terminating character.
|
||||
if dest != NULL, the return value specifies the number of 16-bit characters that
|
||||
are written to the dest, including the null-terminating character. */
|
||||
|
||||
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
|
||||
|
||||
SRes SzArEx_Extract(
|
||||
const CSzArEx *db,
|
||||
ILookInStream *inStream,
|
||||
|
@ -196,7 +194,8 @@ SZ_ERROR_INPUT_EOF
|
|||
SZ_ERROR_FAIL
|
||||
*/
|
||||
|
||||
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
||||
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
|
||||
ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
|
|
1770
lzma/C/7zArcIn.c
Normal file
1770
lzma/C/7zArcIn.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
|||
/* 7zBuf.c -- Byte Buffer
|
||||
2008-03-28
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2013-01-21 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "7zBuf.h"
|
||||
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
/* 7zBuf.h -- Byte Buffer
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_BUF_H
|
||||
#define __7Z_BUF_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -32,8 +30,6 @@ 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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,29 +1,35 @@
|
|||
/* 7zCrc.c -- CRC32 init
|
||||
2010-12-01 : Igor Pavlov : Public domain */
|
||||
2015-03-10 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "7zCrc.h"
|
||||
#include "CpuArch.h"
|
||||
|
||||
#define kCrcPoly 0xEDB88320
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
#ifdef MY_CPU_LE
|
||||
#define CRC_NUM_TABLES 8
|
||||
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
#elif defined(MY_CPU_LE)
|
||||
#define CRC_NUM_TABLES 4
|
||||
#else
|
||||
#define CRC_NUM_TABLES 5
|
||||
#define CRC_NUM_TABLES 9
|
||||
|
||||
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
#endif
|
||||
|
||||
#ifndef MY_CPU_BE
|
||||
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
#endif
|
||||
|
||||
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
|
||||
static CRC_FUNC g_CrcUpdate;
|
||||
CRC_FUNC g_CrcUpdateT4;
|
||||
CRC_FUNC g_CrcUpdateT8;
|
||||
CRC_FUNC g_CrcUpdate;
|
||||
|
||||
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
||||
|
@ -36,6 +42,17 @@ UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
|||
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
|
||||
}
|
||||
|
||||
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
const Byte *pEnd = p + size;
|
||||
for (; p != pEnd; p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable()
|
||||
{
|
||||
UInt32 i;
|
||||
|
@ -52,22 +69,43 @@ void MY_FAST_CALL CrcGenerateTable()
|
|||
UInt32 r = g_CrcTable[i - 256];
|
||||
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
||||
}
|
||||
|
||||
#if CRC_NUM_TABLES < 4
|
||||
|
||||
g_CrcUpdate = CrcUpdateT1;
|
||||
|
||||
#else
|
||||
|
||||
#ifdef MY_CPU_LE
|
||||
|
||||
g_CrcUpdate = CrcUpdateT4;
|
||||
g_CrcUpdateT4 = CrcUpdateT4;
|
||||
g_CrcUpdate = CrcUpdateT4;
|
||||
|
||||
#if CRC_NUM_TABLES >= 8
|
||||
g_CrcUpdateT8 = CrcUpdateT8;
|
||||
|
||||
#if CRC_NUM_TABLES == 8
|
||||
if (!CPU_Is_InOrder())
|
||||
g_CrcUpdate = CrcUpdateT8;
|
||||
#endif
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
if (!CPU_Is_InOrder())
|
||||
g_CrcUpdate = CrcUpdateT8;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
{
|
||||
#ifndef MY_CPU_BE
|
||||
UInt32 k = 1;
|
||||
if (*(const Byte *)&k == 1)
|
||||
UInt32 k = 0x01020304;
|
||||
const Byte *p = (const Byte *)&k;
|
||||
if (p[0] == 4 && p[1] == 3)
|
||||
{
|
||||
g_CrcUpdateT4 = CrcUpdateT4;
|
||||
g_CrcUpdate = CrcUpdateT4;
|
||||
#if CRC_NUM_TABLES >= 8
|
||||
g_CrcUpdateT8 = CrcUpdateT8;
|
||||
// g_CrcUpdate = CrcUpdateT8;
|
||||
#endif
|
||||
}
|
||||
else if (p[0] != 1 || p[1] != 2)
|
||||
g_CrcUpdate = CrcUpdateT1;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
|
@ -76,8 +114,15 @@ void MY_FAST_CALL CrcGenerateTable()
|
|||
UInt32 x = g_CrcTable[i - 256];
|
||||
g_CrcTable[i] = CRC_UINT32_SWAP(x);
|
||||
}
|
||||
g_CrcUpdateT4 = CrcUpdateT1_BeT4;
|
||||
g_CrcUpdate = CrcUpdateT1_BeT4;
|
||||
#if CRC_NUM_TABLES >= 8
|
||||
g_CrcUpdateT8 = CrcUpdateT1_BeT8;
|
||||
// g_CrcUpdate = CrcUpdateT1_BeT8;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/* 7zCrc.h -- CRC32 calculation
|
||||
2009-11-21 : Igor Pavlov : Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_CRC_H
|
||||
#define __7Z_CRC_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
/* 7zCrcOpt.c -- CRC32 calculation
|
||||
2010-12-01 : Igor Pavlov : Public domain */
|
||||
2015-03-01 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "CpuArch.h"
|
||||
|
||||
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
#ifndef MY_CPU_BE
|
||||
|
||||
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
|
@ -16,10 +18,10 @@ UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const U
|
|||
{
|
||||
v ^= *(const UInt32 *)p;
|
||||
v =
|
||||
table[0x300 + (v & 0xFF)] ^
|
||||
table[0x200 + ((v >> 8) & 0xFF)] ^
|
||||
table[0x100 + ((v >> 16) & 0xFF)] ^
|
||||
table[0x000 + ((v >> 24))];
|
||||
table[0x300 + ((v ) & 0xFF)]
|
||||
^ table[0x200 + ((v >> 8) & 0xFF)]
|
||||
^ table[0x100 + ((v >> 16) & 0xFF)]
|
||||
^ table[0x000 + ((v >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
|
@ -28,7 +30,28 @@ UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const U
|
|||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
return CrcUpdateT4(v, data, size, table);
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
for (; size >= 8; size -= 8, p += 8)
|
||||
{
|
||||
UInt32 d;
|
||||
v ^= *(const UInt32 *)p;
|
||||
v =
|
||||
table[0x700 + ((v ) & 0xFF)]
|
||||
^ table[0x600 + ((v >> 8) & 0xFF)]
|
||||
^ table[0x500 + ((v >> 16) & 0xFF)]
|
||||
^ table[0x400 + ((v >> 24))];
|
||||
d = *((const UInt32 *)p + 1);
|
||||
v ^=
|
||||
table[0x300 + ((d ) & 0xFF)]
|
||||
^ table[0x200 + ((d >> 8) & 0xFF)]
|
||||
^ table[0x100 + ((d >> 16) & 0xFF)]
|
||||
^ table[0x000 + ((d >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -38,27 +61,55 @@ UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const U
|
|||
|
||||
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
|
||||
|
||||
#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8))
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
v = CRC_UINT32_SWAP(v);
|
||||
table += 0x100;
|
||||
v = CRC_UINT32_SWAP(v);
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
for (; size >= 4; size -= 4, p += 4)
|
||||
{
|
||||
v ^= *(const UInt32 *)p;
|
||||
v =
|
||||
table[0x000 + (v & 0xFF)] ^
|
||||
table[0x100 + ((v >> 8) & 0xFF)] ^
|
||||
table[0x200 + ((v >> 16) & 0xFF)] ^
|
||||
table[0x300 + ((v >> 24))];
|
||||
table[0x000 + ((v ) & 0xFF)]
|
||||
^ table[0x100 + ((v >> 8) & 0xFF)]
|
||||
^ table[0x200 + ((v >> 16) & 0xFF)]
|
||||
^ table[0x300 + ((v >> 24))];
|
||||
}
|
||||
table -= 0x100;
|
||||
v = CRC_UINT32_SWAP(v);
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
return CRC_UINT32_SWAP(v);
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
table += 0x100;
|
||||
v = CRC_UINT32_SWAP(v);
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
for (; size >= 8; size -= 8, p += 8)
|
||||
{
|
||||
UInt32 d;
|
||||
v ^= *(const UInt32 *)p;
|
||||
v =
|
||||
table[0x400 + ((v ) & 0xFF)]
|
||||
^ table[0x500 + ((v >> 8) & 0xFF)]
|
||||
^ table[0x600 + ((v >> 16) & 0xFF)]
|
||||
^ table[0x700 + ((v >> 24))];
|
||||
d = *((const UInt32 *)p + 1);
|
||||
v ^=
|
||||
table[0x000 + ((d ) & 0xFF)]
|
||||
^ table[0x100 + ((d >> 8) & 0xFF)]
|
||||
^ table[0x200 + ((d >> 16) & 0xFF)]
|
||||
^ table[0x300 + ((d >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
return CRC_UINT32_SWAP(v);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
355
lzma/C/7zDec.c
355
lzma/C/7zDec.c
|
@ -1,15 +1,19 @@
|
|||
/* 7zDec.c -- Decoding from 7z folder
|
||||
2010-11-02 : Igor Pavlov : Public domain */
|
||||
2015-11-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* #define _7ZIP_PPMD_SUPPPORT */
|
||||
|
||||
#include "7z.h"
|
||||
#include "7zCrc.h"
|
||||
|
||||
#include "Bcj2.h"
|
||||
#include "Bra.h"
|
||||
#include "CpuArch.h"
|
||||
#include "Delta.h"
|
||||
#include "LzmaDec.h"
|
||||
#include "Lzma2Dec.h"
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
|
@ -17,14 +21,17 @@
|
|||
#endif
|
||||
|
||||
#define k_Copy 0
|
||||
#define k_Delta 3
|
||||
#define k_LZMA2 0x21
|
||||
#define k_LZMA 0x30101
|
||||
#define k_BCJ 0x03030103
|
||||
#define k_PPC 0x03030205
|
||||
#define k_ARM 0x03030501
|
||||
#define k_ARMT 0x03030701
|
||||
#define k_SPARC 0x03030805
|
||||
#define k_BCJ2 0x0303011B
|
||||
#define k_BCJ 0x3030103
|
||||
#define k_BCJ2 0x303011B
|
||||
#define k_PPC 0x3030205
|
||||
#define k_IA64 0x3030401
|
||||
#define k_ARM 0x3030501
|
||||
#define k_ARMT 0x3030701
|
||||
#define k_SPARC 0x3030805
|
||||
|
||||
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
|
||||
|
@ -63,7 +70,7 @@ static Byte ReadByte(void *pp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
||||
static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
||||
{
|
||||
CPpmd7 ppmd;
|
||||
|
@ -77,12 +84,12 @@ static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt
|
|||
s.res = SZ_OK;
|
||||
s.processed = 0;
|
||||
|
||||
if (coder->Props.size != 5)
|
||||
if (propsSize != 5)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
{
|
||||
unsigned order = coder->Props.data[0];
|
||||
UInt32 memSize = GetUi32(coder->Props.data + 1);
|
||||
unsigned order = props[0];
|
||||
UInt32 memSize = GetUi32(props + 1);
|
||||
if (order < PPMD7_MIN_ORDER ||
|
||||
order > PPMD7_MAX_ORDER ||
|
||||
memSize < PPMD7_MIN_MEM_SIZE ||
|
||||
|
@ -124,25 +131,25 @@ static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt
|
|||
#endif
|
||||
|
||||
|
||||
static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
||||
static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, 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));
|
||||
RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain));
|
||||
state.dic = outBuffer;
|
||||
state.dicBufSize = outSize;
|
||||
LzmaDec_Init(&state);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte *inBuf = NULL;
|
||||
const void *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
|
||||
res = inStream->Look(inStream, &inBuf, &lookahead);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
|
@ -154,14 +161,23 @@ static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt
|
|||
inSize -= inProcessed;
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
|
||||
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
if (state.dicBufSize != outSize || lookahead != 0 ||
|
||||
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
|
||||
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
|
||||
if (outSize != state.dicPos || inSize != 0)
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
break;
|
||||
|
||||
if (inProcessed == 0 && dicPos == state.dicPos)
|
||||
{
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
res = inStream->Skip((void *)inStream, inProcessed);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
@ -172,27 +188,30 @@ static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt
|
|||
return res;
|
||||
}
|
||||
|
||||
static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
||||
|
||||
#ifndef _7Z_NO_METHOD_LZMA2
|
||||
|
||||
static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
||||
{
|
||||
CLzma2Dec state;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
Lzma2Dec_Construct(&state);
|
||||
if (coder->Props.size != 1)
|
||||
if (propsSize != 1)
|
||||
return SZ_ERROR_DATA;
|
||||
RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain));
|
||||
RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain));
|
||||
state.decoder.dic = outBuffer;
|
||||
state.decoder.dicBufSize = outSize;
|
||||
Lzma2Dec_Init(&state);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte *inBuf = NULL;
|
||||
const void *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
|
||||
res = inStream->Look(inStream, &inBuf, &lookahead);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
|
@ -204,13 +223,20 @@ static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inS
|
|||
inSize -= inProcessed;
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
|
||||
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
|
||||
(status != LZMA_STATUS_FINISHED_WITH_MARK))
|
||||
if (outSize != state.decoder.dicPos || inSize != 0)
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
if (inProcessed == 0 && dicPos == state.decoder.dicPos)
|
||||
{
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
res = inStream->Skip((void *)inStream, inProcessed);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
@ -221,15 +247,18 @@ static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inS
|
|||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
|
||||
{
|
||||
while (inSize > 0)
|
||||
{
|
||||
void *inBuf;
|
||||
const void *inBuf;
|
||||
size_t curSize = (1 << 18);
|
||||
if (curSize > inSize)
|
||||
curSize = (size_t)inSize;
|
||||
RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));
|
||||
RINOK(inStream->Look(inStream, &inBuf, &curSize));
|
||||
if (curSize == 0)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
memcpy(outBuffer, inBuf, curSize);
|
||||
|
@ -242,11 +271,13 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
|
|||
|
||||
static Bool IS_MAIN_METHOD(UInt32 m)
|
||||
{
|
||||
switch(m)
|
||||
switch (m)
|
||||
{
|
||||
case k_Copy:
|
||||
case k_LZMA:
|
||||
#ifndef _7Z_NO_METHOD_LZMA2
|
||||
case k_LZMA2:
|
||||
#endif
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
case k_PPMD:
|
||||
#endif
|
||||
|
@ -258,13 +289,12 @@ static Bool IS_MAIN_METHOD(UInt32 m)
|
|||
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
|
||||
{
|
||||
return
|
||||
c->NumInStreams == 1 &&
|
||||
c->NumOutStreams == 1 &&
|
||||
c->MethodID <= (UInt32)0xFFFFFFFF &&
|
||||
IS_MAIN_METHOD((UInt32)c->MethodID);
|
||||
c->NumStreams == 1
|
||||
/* && c->MethodID <= (UInt32)0xFFFFFFFF */
|
||||
&& IS_MAIN_METHOD((UInt32)c->MethodID);
|
||||
}
|
||||
|
||||
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
|
||||
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4)
|
||||
|
||||
static SRes CheckSupportedFolder(const CSzFolder *f)
|
||||
{
|
||||
|
@ -274,65 +304,73 @@ static SRes CheckSupportedFolder(const CSzFolder *f)
|
|||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (f->NumCoders == 1)
|
||||
{
|
||||
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
|
||||
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _7Z_NO_METHODS_FILTERS
|
||||
|
||||
if (f->NumCoders == 2)
|
||||
{
|
||||
CSzCoderInfo *c = &f->Coders[1];
|
||||
if (c->MethodID > (UInt32)0xFFFFFFFF ||
|
||||
c->NumInStreams != 1 ||
|
||||
c->NumOutStreams != 1 ||
|
||||
f->NumPackStreams != 1 ||
|
||||
f->PackStreams[0] != 0 ||
|
||||
f->NumBindPairs != 1 ||
|
||||
f->BindPairs[0].InIndex != 1 ||
|
||||
f->BindPairs[0].OutIndex != 0)
|
||||
const CSzCoderInfo *c = &f->Coders[1];
|
||||
if (
|
||||
/* c->MethodID > (UInt32)0xFFFFFFFF || */
|
||||
c->NumStreams != 1
|
||||
|| f->NumPackStreams != 1
|
||||
|| f->PackStreams[0] != 0
|
||||
|| f->NumBonds != 1
|
||||
|| f->Bonds[0].InIndex != 1
|
||||
|| f->Bonds[0].OutIndex != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
switch ((UInt32)c->MethodID)
|
||||
{
|
||||
case k_Delta:
|
||||
case k_BCJ:
|
||||
case k_PPC:
|
||||
case k_IA64:
|
||||
case k_SPARC:
|
||||
case k_ARM:
|
||||
case k_ARMT:
|
||||
break;
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (f->NumCoders == 4)
|
||||
{
|
||||
if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||
|
||||
!IS_SUPPORTED_CODER(&f->Coders[2]) ||
|
||||
!IS_BCJ2(&f->Coders[3]))
|
||||
if (!IS_SUPPORTED_CODER(&f->Coders[1])
|
||||
|| !IS_SUPPORTED_CODER(&f->Coders[2])
|
||||
|| !IS_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)
|
||||
if (f->NumPackStreams != 4
|
||||
|| f->PackStreams[0] != 2
|
||||
|| f->PackStreams[1] != 6
|
||||
|| f->PackStreams[2] != 1
|
||||
|| f->PackStreams[3] != 0
|
||||
|| f->NumBonds != 3
|
||||
|| f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0
|
||||
|| f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1
|
||||
|| f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static UInt64 GetSum(const UInt64 *values, UInt32 index)
|
||||
{
|
||||
UInt64 sum = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < index; i++)
|
||||
sum += values[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
|
||||
|
||||
static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
|
||||
static SRes SzFolder_Decode2(const CSzFolder *folder,
|
||||
const Byte *propsData,
|
||||
const UInt64 *unpackSizes,
|
||||
const UInt64 *packPositions,
|
||||
ILookInStream *inStream, UInt64 startPos,
|
||||
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
|
||||
Byte *tempBuf[])
|
||||
|
@ -346,7 +384,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
|
|||
|
||||
for (ci = 0; ci < folder->NumCoders; ci++)
|
||||
{
|
||||
CSzCoderInfo *coder = &folder->Coders[ci];
|
||||
const CSzCoderInfo *coder = &folder->Coders[ci];
|
||||
|
||||
if (IS_MAIN_METHOD((UInt32)coder->MethodID))
|
||||
{
|
||||
|
@ -358,7 +396,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
|
|||
if (folder->NumCoders == 4)
|
||||
{
|
||||
UInt32 indices[] = { 3, 2, 0 };
|
||||
UInt64 unpackSize = folder->UnpackSizes[ci];
|
||||
UInt64 unpackSize = unpackSizes[ci];
|
||||
si = indices[ci];
|
||||
if (ci < 2)
|
||||
{
|
||||
|
@ -367,7 +405,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
|
|||
if (outSizeCur != unpackSize)
|
||||
return SZ_ERROR_MEM;
|
||||
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
|
||||
if (temp == 0 && outSizeCur != 0)
|
||||
if (!temp && outSizeCur != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
outBufCur = tempBuf[1 - ci] = temp;
|
||||
tempSizes[1 - ci] = outSizeCur;
|
||||
|
@ -382,8 +420,8 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
|
|||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
offset = GetSum(packSizes, si);
|
||||
inSize = packSizes[si];
|
||||
offset = packPositions[si];
|
||||
inSize = packPositions[si + 1] - offset;
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
|
||||
if (coder->MethodID == k_Copy)
|
||||
|
@ -394,77 +432,160 @@ static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
|
|||
}
|
||||
else if (coder->MethodID == k_LZMA)
|
||||
{
|
||||
RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
#ifndef _7Z_NO_METHOD_LZMA2
|
||||
else if (coder->MethodID == k_LZMA2)
|
||||
{
|
||||
RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
else if (coder->MethodID == k_PPMD)
|
||||
{
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
#else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
#endif
|
||||
RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ2)
|
||||
{
|
||||
UInt64 offset = GetSum(packSizes, 1);
|
||||
UInt64 s3Size = packSizes[1];
|
||||
SRes res;
|
||||
UInt64 offset = packPositions[1];
|
||||
UInt64 s3Size = packPositions[2] - offset;
|
||||
|
||||
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)
|
||||
if (!tempBuf[2] && tempSizes[2] != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
|
||||
RINOK(res)
|
||||
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2]));
|
||||
|
||||
if ((tempSizes[0] & 3) != 0 ||
|
||||
(tempSizes[1] & 3) != 0 ||
|
||||
tempSize3 + tempSizes[0] + tempSizes[1] != outSize)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
res = Bcj2_Decode(
|
||||
tempBuf3, tempSize3,
|
||||
tempBuf[0], tempSizes[0],
|
||||
tempBuf[1], tempSizes[1],
|
||||
tempBuf[2], tempSizes[2],
|
||||
outBuffer, outSize);
|
||||
RINOK(res)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ci != 1)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
switch(coder->MethodID)
|
||||
{
|
||||
case k_BCJ:
|
||||
CBcj2Dec p;
|
||||
|
||||
p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3;
|
||||
p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0];
|
||||
p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1];
|
||||
p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2];
|
||||
|
||||
p.dest = outBuffer;
|
||||
p.destLim = outBuffer + outSize;
|
||||
|
||||
Bcj2Dec_Init(&p);
|
||||
RINOK(Bcj2Dec_Decode(&p));
|
||||
|
||||
{
|
||||
UInt32 state;
|
||||
x86_Convert_Init(state);
|
||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
||||
break;
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; i++)
|
||||
if (p.bufs[i] != p.lims[i])
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
if (!Bcj2Dec_IsFinished(&p))
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
if (p.dest != p.destLim
|
||||
|| p.state != BCJ2_STREAM_MAIN)
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
CASE_BRA_CONV(ARM)
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
#ifndef _7Z_NO_METHODS_FILTERS
|
||||
else if (ci == 1)
|
||||
{
|
||||
if (coder->MethodID == k_Delta)
|
||||
{
|
||||
if (coder->PropsSize != 1)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
{
|
||||
Byte state[DELTA_STATE_SIZE];
|
||||
Delta_Init(state);
|
||||
Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (coder->PropsSize != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
switch (coder->MethodID)
|
||||
{
|
||||
case k_BCJ:
|
||||
{
|
||||
UInt32 state;
|
||||
x86_Convert_Init(state);
|
||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
||||
break;
|
||||
}
|
||||
CASE_BRA_CONV(PPC)
|
||||
CASE_BRA_CONV(IA64)
|
||||
CASE_BRA_CONV(SPARC)
|
||||
CASE_BRA_CONV(ARM)
|
||||
CASE_BRA_CONV(ARMT)
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
|
||||
|
||||
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
|
||||
ILookInStream *inStream, UInt64 startPos,
|
||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
||||
Byte *outBuffer, size_t outSize,
|
||||
ISzAlloc *allocMain)
|
||||
{
|
||||
Byte *tempBuf[3] = { 0, 0, 0};
|
||||
int i;
|
||||
SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos,
|
||||
outBuffer, (SizeT)outSize, allocMain, tempBuf);
|
||||
for (i = 0; i < 3; i++)
|
||||
IAlloc_Free(allocMain, tempBuf[i]);
|
||||
return res;
|
||||
SRes res;
|
||||
CSzFolder folder;
|
||||
CSzData sd;
|
||||
|
||||
const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
|
||||
sd.Data = data;
|
||||
sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex];
|
||||
|
||||
res = SzGetNextFolderItem(&folder, &sd);
|
||||
|
||||
if (res != SZ_OK)
|
||||
return res;
|
||||
|
||||
if (sd.Size != 0
|
||||
|| folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex]
|
||||
|| outSize != SzAr_GetFolderUnpackSize(p, folderIndex))
|
||||
return SZ_ERROR_FAIL;
|
||||
{
|
||||
unsigned i;
|
||||
Byte *tempBuf[3] = { 0, 0, 0};
|
||||
|
||||
res = SzFolder_Decode2(&folder, data,
|
||||
&p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]],
|
||||
p->PackPositions + p->FoStartPackStreamIndex[folderIndex],
|
||||
inStream, startPos,
|
||||
outBuffer, (SizeT)outSize, allocMain, tempBuf);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
IAlloc_Free(allocMain, tempBuf[i]);
|
||||
|
||||
if (res == SZ_OK)
|
||||
if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex))
|
||||
if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex])
|
||||
res = SZ_ERROR_CRC;
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
1402
lzma/C/7zIn.c
1402
lzma/C/7zIn.c
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,11 @@
|
|||
/* 7zStream.c -- 7z Stream functions
|
||||
2010-03-11 : Igor Pavlov : Public domain */
|
||||
2013-11-12 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
{
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
/* Types.h -- Basic types
|
||||
2010-10-09 : Igor Pavlov : Public domain */
|
||||
/* 7zTypes.h -- Basic types
|
||||
2013-11-12 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_TYPES_H
|
||||
#define __7Z_TYPES_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef EXTERN_C_BEGIN
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN_C_BEGIN extern "C" {
|
||||
|
@ -44,6 +44,7 @@ typedef int SRes;
|
|||
|
||||
#ifdef _WIN32
|
||||
typedef DWORD WRes;
|
||||
/* typedef unsigned WRes; */
|
||||
#else
|
||||
typedef int WRes;
|
||||
#endif
|
||||
|
@ -116,6 +117,7 @@ typedef int Bool;
|
|||
|
||||
#else
|
||||
|
||||
#define MY_NO_INLINE
|
||||
#define MY_CDECL
|
||||
#define MY_FAST_CALL
|
||||
|
|
@ -1,8 +1,19 @@
|
|||
#define MY_VER_MAJOR 9
|
||||
#define MY_VER_MINOR 22
|
||||
#define MY_VER_BUILD 00
|
||||
#define MY_VERSION "9.22 beta"
|
||||
#define MY_7ZIP_VERSION "9.22 beta"
|
||||
#define MY_DATE "2011-04-18"
|
||||
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
|
||||
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE
|
||||
#define MY_VER_MAJOR 15
|
||||
#define MY_VER_MINOR 14
|
||||
#define MY_VER_BUILD 0
|
||||
#define MY_VERSION_NUMBERS "15.14"
|
||||
#define MY_VERSION "15.14"
|
||||
#define MY_DATE "2015-12-31"
|
||||
#undef MY_COPYRIGHT
|
||||
#undef MY_VERSION_COPYRIGHT_DATE
|
||||
#define MY_AUTHOR_NAME "Igor Pavlov"
|
||||
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
|
||||
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2015 Igor Pavlov"
|
||||
|
||||
#ifdef USE_COPYRIGHT_CR
|
||||
#define MY_COPYRIGHT MY_COPYRIGHT_CR
|
||||
#else
|
||||
#define MY_COPYRIGHT MY_COPYRIGHT_PD
|
||||
#endif
|
||||
|
||||
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " : " MY_COPYRIGHT " : " MY_DATE
|
||||
|
|
334
lzma/C/Bcj2.c
334
lzma/C/Bcj2.c
|
@ -1,132 +1,256 @@
|
|||
/* Bcj2.c -- Converter for x86 code (BCJ2)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
|
||||
2015-08-01 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "Bcj2.h"
|
||||
#include "CpuArch.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 kTopValue ((UInt32)1 << 24)
|
||||
#define kNumModelBits 11
|
||||
#define kBitModelTotal (1 << kNumModelBits)
|
||||
#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 _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound)
|
||||
#define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
|
||||
#define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits));
|
||||
|
||||
#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)
|
||||
void Bcj2Dec_Init(CBcj2Dec *p)
|
||||
{
|
||||
CProb p[256 + 2];
|
||||
SizeT inPos = 0, outPos = 0;
|
||||
unsigned i;
|
||||
|
||||
const Byte *buffer, *bufferLim;
|
||||
UInt32 range, code;
|
||||
Byte prevByte = 0;
|
||||
p->state = BCJ2_DEC_STATE_OK;
|
||||
p->ip = 0;
|
||||
p->temp[3] = 0;
|
||||
p->range = 0;
|
||||
p->code = 0;
|
||||
for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)
|
||||
p->probs[i] = kBitModelTotal >> 1;
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
|
||||
p[i] = kBitModelTotal >> 1;
|
||||
SRes Bcj2Dec_Decode(CBcj2Dec *p)
|
||||
{
|
||||
if (p->range <= 5)
|
||||
{
|
||||
p->state = BCJ2_DEC_STATE_OK;
|
||||
for (; p->range != 5; p->range++)
|
||||
{
|
||||
if (p->range == 1 && p->code != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
|
||||
{
|
||||
p->state = BCJ2_STREAM_RC;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
buffer = buf3;
|
||||
bufferLim = buffer + size3;
|
||||
RC_INIT2
|
||||
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||
}
|
||||
|
||||
if (p->code == 0xFFFFFFFF)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
p->range = 0xFFFFFFFF;
|
||||
}
|
||||
else if (p->state >= BCJ2_DEC_STATE_ORIG_0)
|
||||
{
|
||||
while (p->state <= BCJ2_DEC_STATE_ORIG_3)
|
||||
{
|
||||
Byte *dest = p->dest;
|
||||
if (dest == p->destLim)
|
||||
return SZ_OK;
|
||||
*dest = p->temp[p->state++ - BCJ2_DEC_STATE_ORIG_0];
|
||||
p->dest = dest + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (outSize == 0)
|
||||
return SZ_OK;
|
||||
/*
|
||||
if (BCJ2_IS_32BIT_STREAM(p->state))
|
||||
{
|
||||
const Byte *cur = p->bufs[p->state];
|
||||
if (cur == p->lims[p->state])
|
||||
return SZ_OK;
|
||||
p->bufs[p->state] = cur + 4;
|
||||
|
||||
{
|
||||
UInt32 val;
|
||||
Byte *dest;
|
||||
SizeT rem;
|
||||
|
||||
p->ip += 4;
|
||||
val = GetBe32(cur) - p->ip;
|
||||
dest = p->dest;
|
||||
rem = p->destLim - dest;
|
||||
if (rem < 4)
|
||||
{
|
||||
SizeT i;
|
||||
SetUi32(p->temp, val);
|
||||
for (i = 0; i < rem; i++)
|
||||
dest[i] = p->temp[i];
|
||||
p->dest = dest + rem;
|
||||
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
|
||||
return SZ_OK;
|
||||
}
|
||||
SetUi32(dest, val);
|
||||
p->temp[3] = (Byte)(val >> 24);
|
||||
p->dest = dest + 4;
|
||||
p->state = BCJ2_DEC_STATE_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;
|
||||
}
|
||||
if (BCJ2_IS_32BIT_STREAM(p->state))
|
||||
p->state = BCJ2_DEC_STATE_OK;
|
||||
else
|
||||
{
|
||||
UInt32 dest;
|
||||
const Byte *v;
|
||||
UPDATE_1(prob)
|
||||
if (b == 0xE8)
|
||||
if (p->range < kTopValue)
|
||||
{
|
||||
v = buf1;
|
||||
if (size1 < 4)
|
||||
return SZ_ERROR_DATA;
|
||||
buf1 += 4;
|
||||
size1 -= 4;
|
||||
if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
|
||||
{
|
||||
p->state = BCJ2_STREAM_RC;
|
||||
return SZ_OK;
|
||||
}
|
||||
p->range <<= 8;
|
||||
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
v = buf2;
|
||||
if (size2 < 4)
|
||||
return SZ_ERROR_DATA;
|
||||
buf2 += 4;
|
||||
size2 -= 4;
|
||||
const Byte *src = p->bufs[BCJ2_STREAM_MAIN];
|
||||
const Byte *srcLim;
|
||||
Byte *dest;
|
||||
SizeT num = p->lims[BCJ2_STREAM_MAIN] - src;
|
||||
|
||||
if (num == 0)
|
||||
{
|
||||
p->state = BCJ2_STREAM_MAIN;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
dest = p->dest;
|
||||
if (num > (SizeT)(p->destLim - dest))
|
||||
{
|
||||
num = p->destLim - dest;
|
||||
if (num == 0)
|
||||
{
|
||||
p->state = BCJ2_DEC_STATE_ORIG;
|
||||
return SZ_OK;
|
||||
}
|
||||
}
|
||||
|
||||
srcLim = src + num;
|
||||
|
||||
if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80)
|
||||
*dest = src[0];
|
||||
else for (;;)
|
||||
{
|
||||
Byte b = *src;
|
||||
*dest = b;
|
||||
if (b != 0x0F)
|
||||
{
|
||||
if ((b & 0xFE) == 0xE8)
|
||||
break;
|
||||
dest++;
|
||||
if (++src != srcLim)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
dest++;
|
||||
if (++src == srcLim)
|
||||
break;
|
||||
if ((*src & 0xF0) != 0x80)
|
||||
continue;
|
||||
*dest = *src;
|
||||
break;
|
||||
}
|
||||
|
||||
num = src - p->bufs[BCJ2_STREAM_MAIN];
|
||||
|
||||
if (src == srcLim)
|
||||
{
|
||||
p->temp[3] = src[-1];
|
||||
p->bufs[BCJ2_STREAM_MAIN] = src;
|
||||
p->ip += (UInt32)num;
|
||||
p->dest += num;
|
||||
p->state =
|
||||
p->bufs[BCJ2_STREAM_MAIN] ==
|
||||
p->lims[BCJ2_STREAM_MAIN] ?
|
||||
(unsigned)BCJ2_STREAM_MAIN :
|
||||
(unsigned)BCJ2_DEC_STATE_ORIG;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
{
|
||||
UInt32 bound, ttt;
|
||||
CProb *prob;
|
||||
Byte b = src[0];
|
||||
Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]);
|
||||
|
||||
p->temp[3] = b;
|
||||
p->bufs[BCJ2_STREAM_MAIN] = src + 1;
|
||||
num++;
|
||||
p->ip += (UInt32)num;
|
||||
p->dest += num;
|
||||
|
||||
prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0));
|
||||
|
||||
_IF_BIT_0
|
||||
{
|
||||
_UPDATE_0
|
||||
continue;
|
||||
}
|
||||
_UPDATE_1
|
||||
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
{
|
||||
UInt32 val;
|
||||
unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
|
||||
const Byte *cur = p->bufs[cj];
|
||||
Byte *dest;
|
||||
SizeT rem;
|
||||
|
||||
if (cur == p->lims[cj])
|
||||
{
|
||||
p->state = cj;
|
||||
break;
|
||||
outBuf[outPos++] = (Byte)(dest >> 8);
|
||||
if (outPos == outSize)
|
||||
}
|
||||
|
||||
val = GetBe32(cur);
|
||||
p->bufs[cj] = cur + 4;
|
||||
|
||||
p->ip += 4;
|
||||
val -= p->ip;
|
||||
dest = p->dest;
|
||||
rem = p->destLim - dest;
|
||||
|
||||
if (rem < 4)
|
||||
{
|
||||
SizeT i;
|
||||
SetUi32(p->temp, val);
|
||||
for (i = 0; i < rem; i++)
|
||||
dest[i] = p->temp[i];
|
||||
p->dest = dest + rem;
|
||||
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
|
||||
break;
|
||||
outBuf[outPos++] = (Byte)(dest >> 16);
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
|
||||
}
|
||||
|
||||
SetUi32(dest, val);
|
||||
p->temp[3] = (Byte)(val >> 24);
|
||||
p->dest = dest + 4;
|
||||
}
|
||||
}
|
||||
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
|
||||
|
||||
if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])
|
||||
{
|
||||
p->range <<= 8;
|
||||
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||
}
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
|
|
160
lzma/C/Bcj2.h
160
lzma/C/Bcj2.h
|
@ -1,38 +1,146 @@
|
|||
/* Bcj2.h -- Converter for x86 code (BCJ2)
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
/* Bcj2.h -- BCJ2 Converter for x86 code
|
||||
2014-11-10 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BCJ2_H
|
||||
#define __BCJ2_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define BCJ2_NUM_STREAMS 4
|
||||
|
||||
enum
|
||||
{
|
||||
BCJ2_STREAM_MAIN,
|
||||
BCJ2_STREAM_CALL,
|
||||
BCJ2_STREAM_JUMP,
|
||||
BCJ2_STREAM_RC
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS,
|
||||
BCJ2_DEC_STATE_ORIG_1,
|
||||
BCJ2_DEC_STATE_ORIG_2,
|
||||
BCJ2_DEC_STATE_ORIG_3,
|
||||
|
||||
BCJ2_DEC_STATE_ORIG,
|
||||
BCJ2_DEC_STATE_OK
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS,
|
||||
BCJ2_ENC_STATE_OK
|
||||
};
|
||||
|
||||
|
||||
#define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP)
|
||||
|
||||
/*
|
||||
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
|
||||
CBcj2Dec / CBcj2Enc
|
||||
bufs sizes:
|
||||
BUF_SIZE(n) = lims[n] - bufs[n]
|
||||
bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4:
|
||||
(BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0
|
||||
(BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0
|
||||
*/
|
||||
|
||||
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);
|
||||
/*
|
||||
CBcj2Dec:
|
||||
dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions:
|
||||
bufs[BCJ2_STREAM_MAIN] >= dest &&
|
||||
bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv +
|
||||
BUF_SIZE(BCJ2_STREAM_CALL) +
|
||||
BUF_SIZE(BCJ2_STREAM_JUMP)
|
||||
tempReserv = 0 : for first call of Bcj2Dec_Decode
|
||||
tempReserv = 4 : for any other calls of Bcj2Dec_Decode
|
||||
overlap with offset = 1 is not allowed
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
const Byte *bufs[BCJ2_NUM_STREAMS];
|
||||
const Byte *lims[BCJ2_NUM_STREAMS];
|
||||
Byte *dest;
|
||||
const Byte *destLim;
|
||||
|
||||
unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */
|
||||
|
||||
UInt32 ip;
|
||||
Byte temp[4];
|
||||
UInt32 range;
|
||||
UInt32 code;
|
||||
UInt16 probs[2 + 256];
|
||||
} CBcj2Dec;
|
||||
|
||||
void Bcj2Dec_Init(CBcj2Dec *p);
|
||||
|
||||
/* Returns: SZ_OK or SZ_ERROR_DATA */
|
||||
SRes Bcj2Dec_Decode(CBcj2Dec *p);
|
||||
|
||||
#define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0)
|
||||
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BCJ2_ENC_FINISH_MODE_CONTINUE,
|
||||
BCJ2_ENC_FINISH_MODE_END_BLOCK,
|
||||
BCJ2_ENC_FINISH_MODE_END_STREAM
|
||||
} EBcj2Enc_FinishMode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte *bufs[BCJ2_NUM_STREAMS];
|
||||
const Byte *lims[BCJ2_NUM_STREAMS];
|
||||
const Byte *src;
|
||||
const Byte *srcLim;
|
||||
|
||||
unsigned state;
|
||||
EBcj2Enc_FinishMode finishMode;
|
||||
|
||||
Byte prevByte;
|
||||
|
||||
Byte cache;
|
||||
UInt32 range;
|
||||
UInt64 low;
|
||||
UInt64 cacheSize;
|
||||
|
||||
UInt32 ip;
|
||||
|
||||
/* 32-bit ralative offset in JUMP/CALL commands is
|
||||
- (mod 4 GB) in 32-bit mode
|
||||
- signed Int32 in 64-bit mode
|
||||
We use (mod 4 GB) check for fileSize.
|
||||
Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */
|
||||
UInt32 fileIp;
|
||||
UInt32 fileSize; /* (fileSize <= ((UInt32)1 << 31)), 0 means no_limit */
|
||||
UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)), 0 means desable_conversion */
|
||||
|
||||
UInt32 tempTarget;
|
||||
unsigned tempPos;
|
||||
Byte temp[4 * 2];
|
||||
|
||||
unsigned flushPos;
|
||||
|
||||
UInt16 probs[2 + 256];
|
||||
} CBcj2Enc;
|
||||
|
||||
void Bcj2Enc_Init(CBcj2Enc *p);
|
||||
void Bcj2Enc_Encode(CBcj2Enc *p);
|
||||
|
||||
#define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos)
|
||||
#define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5)
|
||||
|
||||
|
||||
#define BCJ2_RELAT_LIMIT_NUM_BITS 26
|
||||
#define BCJ2_RELAT_LIMIT ((UInt32)1 << BCJ2_RELAT_LIMIT_NUM_BITS)
|
||||
|
||||
/* limit for CBcj2Enc::fileSize variable */
|
||||
#define BCJ2_FileSize_MAX ((UInt32)1 << 31)
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/* Bra.c -- Converters for RISC code
|
||||
2010-04-16 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "Bra.h"
|
||||
|
||||
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||
|
|
12
lzma/C/Bra.h
12
lzma/C/Bra.h
|
@ -1,14 +1,12 @@
|
|||
/* Bra.h -- Branch converters for executables
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BRA_H
|
||||
#define __BRA_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/*
|
||||
These functions convert relative addresses to absolute addresses
|
||||
|
@ -61,8 +59,6 @@ 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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,85 +1,82 @@
|
|||
/* Bra86.c -- Converter for x86 code (BCJ)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2013-11-12 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#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};
|
||||
#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0)
|
||||
|
||||
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
|
||||
{
|
||||
SizeT bufferPos = 0, prevPosT;
|
||||
UInt32 prevMask = *state & 0x7;
|
||||
SizeT pos = 0;
|
||||
UInt32 mask = *state & 7;
|
||||
if (size < 5)
|
||||
return 0;
|
||||
size -= 4;
|
||||
ip += 5;
|
||||
prevPosT = (SizeT)0 - 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte *p = data + bufferPos;
|
||||
Byte *limit = data + size - 4;
|
||||
Byte *p = data + pos;
|
||||
const Byte *limit = data + size;
|
||||
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)
|
||||
SizeT d = (SizeT)(p - data - pos);
|
||||
pos = (SizeT)(p - data);
|
||||
if (p >= limit)
|
||||
{
|
||||
Byte b = p[4 - kMaskToBitNumber[prevMask]];
|
||||
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
|
||||
*state = (d > 2 ? 0 : mask >> (unsigned)d);
|
||||
return pos;
|
||||
}
|
||||
if (d > 2)
|
||||
mask = 0;
|
||||
else
|
||||
{
|
||||
mask >>= (unsigned)d;
|
||||
if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(mask >> 1) + 1])))
|
||||
{
|
||||
prevPosT = bufferPos;
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
mask = (mask >> 1) | 4;
|
||||
pos++;
|
||||
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 (;;)
|
||||
UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
|
||||
UInt32 cur = ip + (UInt32)pos;
|
||||
pos += 5;
|
||||
if (encoding)
|
||||
v += cur;
|
||||
else
|
||||
v -= cur;
|
||||
if (mask != 0)
|
||||
{
|
||||
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);
|
||||
unsigned sh = (mask & 6) << 2;
|
||||
if (Test86MSByte((Byte)(v >> sh)))
|
||||
{
|
||||
v ^= (((UInt32)0x100 << sh) - 1);
|
||||
if (encoding)
|
||||
v += cur;
|
||||
else
|
||||
v -= cur;
|
||||
}
|
||||
mask = 0;
|
||||
}
|
||||
p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
|
||||
p[3] = (Byte)(dest >> 16);
|
||||
p[2] = (Byte)(dest >> 8);
|
||||
p[1] = (Byte)dest;
|
||||
bufferPos += 5;
|
||||
p[1] = (Byte)v;
|
||||
p[2] = (Byte)(v >> 8);
|
||||
p[3] = (Byte)(v >> 16);
|
||||
p[4] = (Byte)(0 - ((v >> 24) & 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
mask = (mask >> 1) | 4;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
prevPosT = bufferPos - prevPosT;
|
||||
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
|
||||
return bufferPos;
|
||||
}
|
||||
|
|
69
lzma/C/BraIA64.c
Normal file
69
lzma/C/BraIA64.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* BraIA64.c -- Converter for IA-64 code
|
||||
2013-11-12 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "Bra.h"
|
||||
|
||||
static const Byte kBranchTable[32] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 4, 6, 6, 0, 0, 7, 7,
|
||||
4, 4, 0, 0, 4, 4, 0, 0
|
||||
};
|
||||
|
||||
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||
{
|
||||
SizeT i;
|
||||
if (size < 16)
|
||||
return 0;
|
||||
size -= 16;
|
||||
for (i = 0; i <= size; i += 16)
|
||||
{
|
||||
UInt32 instrTemplate = data[i] & 0x1F;
|
||||
UInt32 mask = kBranchTable[instrTemplate];
|
||||
UInt32 bitPos = 5;
|
||||
int slot;
|
||||
for (slot = 0; slot < 3; slot++, bitPos += 41)
|
||||
{
|
||||
UInt32 bytePos, bitRes;
|
||||
UInt64 instruction, instNorm;
|
||||
int j;
|
||||
if (((mask >> slot) & 1) == 0)
|
||||
continue;
|
||||
bytePos = (bitPos >> 3);
|
||||
bitRes = bitPos & 0x7;
|
||||
instruction = 0;
|
||||
for (j = 0; j < 6; j++)
|
||||
instruction += (UInt64)data[i + j + bytePos] << (8 * j);
|
||||
|
||||
instNorm = instruction >> bitRes;
|
||||
if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0)
|
||||
{
|
||||
UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF);
|
||||
UInt32 dest;
|
||||
src |= ((UInt32)(instNorm >> 36) & 1) << 20;
|
||||
|
||||
src <<= 4;
|
||||
|
||||
if (encoding)
|
||||
dest = ip + (UInt32)i + src;
|
||||
else
|
||||
dest = src - (ip + (UInt32)i);
|
||||
|
||||
dest >>= 4;
|
||||
|
||||
instNorm &= ~((UInt64)(0x8FFFFF) << 13);
|
||||
instNorm |= ((UInt64)(dest & 0xFFFFF) << 13);
|
||||
instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20));
|
||||
|
||||
instruction &= (1 << bitRes) - 1;
|
||||
instruction |= (instNorm << bitRes);
|
||||
for (j = 0; j < 6; j++)
|
||||
data[i + j + bytePos] = (Byte)(instruction >> (8 * j));
|
||||
}
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
32
lzma/C/Compiler.h
Normal file
32
lzma/C/Compiler.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/* Compiler.h
|
||||
2015-08-02 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_COMPILER_H
|
||||
#define __7Z_COMPILER_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#ifdef UNDER_CE
|
||||
#define RPC_NO_WINDOWS_H
|
||||
/* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */
|
||||
#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
|
||||
#pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int
|
||||
#endif
|
||||
|
||||
#if _MSC_VER >= 1300
|
||||
#pragma warning(disable : 4996) // This function or variable may be unsafe
|
||||
#else
|
||||
#pragma warning(disable : 4511) // copy constructor could not be generated
|
||||
#pragma warning(disable : 4512) // assignment operator could not be generated
|
||||
#pragma warning(disable : 4514) // unreferenced inline function has been removed
|
||||
#pragma warning(disable : 4702) // unreachable code
|
||||
#pragma warning(disable : 4710) // not inlined
|
||||
#pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define UNUSED_VAR(x) (void)x;
|
||||
/* #define UNUSED_VAR(x) x=x; */
|
||||
|
||||
#endif
|
|
@ -1,5 +1,7 @@
|
|||
/* CpuArch.c -- CPU specific code
|
||||
2010-10-26: Igor Pavlov : Public domain */
|
||||
2015-03-25: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "CpuArch.h"
|
||||
|
||||
|
@ -9,6 +11,10 @@
|
|||
#define USE_ASM
|
||||
#endif
|
||||
|
||||
#if !defined(USE_ASM) && _MSC_VER >= 1500
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#if defined(USE_ASM) && !defined(MY_CPU_AMD64)
|
||||
static UInt32 CheckFlag(UInt32 flag)
|
||||
{
|
||||
|
@ -48,7 +54,7 @@ static UInt32 CheckFlag(UInt32 flag)
|
|||
#define CHECK_CPUID_IS_SUPPORTED
|
||||
#endif
|
||||
|
||||
static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
|
||||
void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
|
||||
{
|
||||
#ifdef USE_ASM
|
||||
|
||||
|
@ -70,28 +76,20 @@ static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
|
|||
*c = c2;
|
||||
*d = d2;
|
||||
|
||||
#elif defined __PIC__ && defined __i386__
|
||||
|
||||
/* GCC or Clang WITH position-independent code generation, i386 only */
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"xchgl %%ebx, %1\n"
|
||||
"cpuid\n"
|
||||
"xchgl %%ebx, %1\n"
|
||||
: "=a" (*a) ,
|
||||
"=r" (*b) ,
|
||||
"=c" (*c) ,
|
||||
"=d" (*d)
|
||||
: "0" (function)) ;
|
||||
|
||||
#else
|
||||
|
||||
/* GCC or Clang WITHOUT position-independent code generation, or x86_64 */
|
||||
|
||||
__asm__ __volatile__ (
|
||||
#if defined(MY_CPU_X86) && defined(__PIC__)
|
||||
"mov %%ebx, %%edi;"
|
||||
"cpuid;"
|
||||
"xchgl %%ebx, %%edi;"
|
||||
: "=a" (*a) ,
|
||||
"=D" (*b) ,
|
||||
#else
|
||||
"cpuid"
|
||||
: "=a" (*a) ,
|
||||
"=b" (*b) ,
|
||||
#endif
|
||||
"=c" (*c) ,
|
||||
"=d" (*d)
|
||||
: "0" (function)) ;
|
||||
|
@ -118,7 +116,7 @@ Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
|
|||
return True;
|
||||
}
|
||||
|
||||
static UInt32 kVendors[][3] =
|
||||
static const UInt32 kVendors[][3] =
|
||||
{
|
||||
{ 0x756E6547, 0x49656E69, 0x6C65746E},
|
||||
{ 0x68747541, 0x69746E65, 0x444D4163},
|
||||
|
@ -146,12 +144,22 @@ Bool CPU_Is_InOrder()
|
|||
UInt32 family, model;
|
||||
if (!x86cpuid_CheckAndRead(&p))
|
||||
return True;
|
||||
family = x86cpuid_GetFamily(&p);
|
||||
model = x86cpuid_GetModel(&p);
|
||||
|
||||
family = x86cpuid_GetFamily(p.ver);
|
||||
model = x86cpuid_GetModel(p.ver);
|
||||
|
||||
firm = x86cpuid_GetFirm(&p);
|
||||
|
||||
switch (firm)
|
||||
{
|
||||
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C));
|
||||
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (
|
||||
/* In-Order Atom CPU */
|
||||
model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */
|
||||
|| model == 0x26 /* 45 nm, Z6xx */
|
||||
|| model == 0x27 /* 32 nm, Z2460 */
|
||||
|| model == 0x35 /* 32 nm, Z2760 */
|
||||
|| model == 0x36 /* 32 nm, N2xxx, D2xxx */
|
||||
)));
|
||||
case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
|
||||
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
|
||||
}
|
||||
|
@ -159,6 +167,7 @@ Bool CPU_Is_InOrder()
|
|||
}
|
||||
|
||||
#if !defined(MY_CPU_AMD64) && defined(_WIN32)
|
||||
#include <windows.h>
|
||||
static Bool CPU_Sys_Is_SSE_Supported()
|
||||
{
|
||||
OSVERSIONINFO vi;
|
||||
|
|
149
lzma/C/CpuArch.h
149
lzma/C/CpuArch.h
|
@ -1,27 +1,34 @@
|
|||
/* CpuArch.h -- CPU specific code
|
||||
2010-12-01: Igor Pavlov : Public domain */
|
||||
2015-12-01: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __CPU_ARCH_H
|
||||
#define __CPU_ARCH_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/*
|
||||
MY_CPU_LE means that CPU is LITTLE ENDIAN.
|
||||
If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN).
|
||||
MY_CPU_BE means that CPU is BIG ENDIAN.
|
||||
If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform.
|
||||
|
||||
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
|
||||
If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.
|
||||
*/
|
||||
|
||||
#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
|
||||
#define MY_CPU_AMD64
|
||||
#if defined(_M_X64) \
|
||||
|| defined(_M_AMD64) \
|
||||
|| defined(__x86_64__) \
|
||||
|| defined(__AMD64__) \
|
||||
|| defined(__amd64__)
|
||||
#define MY_CPU_AMD64
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_AMD64) || defined(_M_IA64)
|
||||
#define MY_CPU_64BIT
|
||||
#if defined(MY_CPU_AMD64) \
|
||||
|| defined(_M_IA64) \
|
||||
|| defined(__AARCH64EL__) \
|
||||
|| defined(__AARCH64EB__)
|
||||
#define MY_CPU_64BIT
|
||||
#endif
|
||||
|
||||
#if defined(_M_IX86) || defined(__i386__)
|
||||
|
@ -32,8 +39,13 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
|
|||
#define MY_CPU_X86_OR_AMD64
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_X86) || defined(_M_ARM)
|
||||
#define MY_CPU_32BIT
|
||||
#if defined(MY_CPU_X86) \
|
||||
|| defined(_M_ARM) \
|
||||
|| defined(__ARMEL__) \
|
||||
|| defined(__THUMBEL__) \
|
||||
|| defined(__ARMEB__) \
|
||||
|| defined(__THUMBEB__)
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(_M_ARM)
|
||||
|
@ -44,34 +56,63 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
|
|||
#define MY_CPU_IA64_LE
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64)
|
||||
#define MY_CPU_LE_UNALIGN
|
||||
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||
|| defined(MY_CPU_ARM_LE) \
|
||||
|| defined(MY_CPU_IA64_LE) \
|
||||
|| defined(__LITTLE_ENDIAN__) \
|
||||
|| defined(__ARMEL__) \
|
||||
|| defined(__THUMBEL__) \
|
||||
|| defined(__AARCH64EL__) \
|
||||
|| defined(__MIPSEL__) \
|
||||
|| defined(__MIPSEL) \
|
||||
|| defined(_MIPSEL) \
|
||||
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||
#define MY_CPU_LE
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)
|
||||
#define MY_CPU_LE
|
||||
#endif
|
||||
|
||||
#if defined(__BIG_ENDIAN__) || defined(__m68k__) || defined(__ARMEB__) || defined(__MIPSEB__)
|
||||
#define MY_CPU_BE
|
||||
#if defined(__BIG_ENDIAN__) \
|
||||
|| defined(__ARMEB__) \
|
||||
|| defined(__THUMBEB__) \
|
||||
|| defined(__AARCH64EB__) \
|
||||
|| defined(__MIPSEB__) \
|
||||
|| defined(__MIPSEB) \
|
||||
|| defined(_MIPSEB) \
|
||||
|| defined(__m68k__) \
|
||||
|| defined(__s390__) \
|
||||
|| defined(__s390x__) \
|
||||
|| defined(__zarch__) \
|
||||
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
#define MY_CPU_BE
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
|
||||
Stop_Compiling_Bad_Endian
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MY_CPU_LE
|
||||
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||
/* || defined(__AARCH64EL__) */
|
||||
#define MY_CPU_LE_UNALIGN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MY_CPU_LE_UNALIGN
|
||||
|
||||
#define GetUi16(p) (*(const UInt16 *)(p))
|
||||
#define GetUi32(p) (*(const UInt32 *)(p))
|
||||
#define GetUi64(p) (*(const UInt64 *)(p))
|
||||
#define SetUi16(p, d) *(UInt16 *)(p) = (d);
|
||||
#define SetUi32(p, d) *(UInt32 *)(p) = (d);
|
||||
#define SetUi64(p, d) *(UInt64 *)(p) = (d);
|
||||
#define GetUi16(p) (*(const UInt16 *)(const void *)(p))
|
||||
#define GetUi32(p) (*(const UInt32 *)(const void *)(p))
|
||||
#define GetUi64(p) (*(const UInt64 *)(const void *)(p))
|
||||
|
||||
#define SetUi16(p, v) { *(UInt16 *)(p) = (v); }
|
||||
#define SetUi32(p, v) { *(UInt32 *)(p) = (v); }
|
||||
#define SetUi64(p, v) { *(UInt64 *)(p) = (v); }
|
||||
|
||||
#else
|
||||
|
||||
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
|
||||
#define GetUi16(p) ( (UInt16) ( \
|
||||
((const Byte *)(p))[0] | \
|
||||
((UInt16)((const Byte *)(p))[1] << 8) ))
|
||||
|
||||
#define GetUi32(p) ( \
|
||||
((const Byte *)(p))[0] | \
|
||||
|
@ -81,29 +122,43 @@ Stop_Compiling_Bad_Endian
|
|||
|
||||
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
|
||||
|
||||
#define SetUi16(p, d) { UInt32 _x_ = (d); \
|
||||
((Byte *)(p))[0] = (Byte)_x_; \
|
||||
((Byte *)(p))[1] = (Byte)(_x_ >> 8); }
|
||||
#define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
|
||||
_ppp_[0] = (Byte)_vvv_; \
|
||||
_ppp_[1] = (Byte)(_vvv_ >> 8); }
|
||||
|
||||
#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); }
|
||||
#define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
|
||||
_ppp_[0] = (Byte)_vvv_; \
|
||||
_ppp_[1] = (Byte)(_vvv_ >> 8); \
|
||||
_ppp_[2] = (Byte)(_vvv_ >> 16); \
|
||||
_ppp_[3] = (Byte)(_vvv_ >> 24); }
|
||||
|
||||
#define SetUi64(p, d) { UInt64 _x64_ = (d); \
|
||||
SetUi32(p, (UInt32)_x64_); \
|
||||
SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
|
||||
#define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \
|
||||
SetUi32(_ppp2_ , (UInt32)_vvv2_); \
|
||||
SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); }
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
|
||||
|
||||
#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300)
|
||||
|
||||
/* Note: we use bswap instruction, that is unsupported in 386 cpu */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#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))
|
||||
|
||||
#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v)
|
||||
|
||||
#elif defined(MY_CPU_LE_UNALIGN) && defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
|
||||
|
||||
#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p))
|
||||
#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p))
|
||||
|
||||
#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v)
|
||||
|
||||
#else
|
||||
|
||||
#define GetBe32(p) ( \
|
||||
|
@ -114,9 +169,19 @@ Stop_Compiling_Bad_Endian
|
|||
|
||||
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
|
||||
|
||||
#define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
|
||||
_ppp_[0] = (Byte)(_vvv_ >> 24); \
|
||||
_ppp_[1] = (Byte)(_vvv_ >> 16); \
|
||||
_ppp_[2] = (Byte)(_vvv_ >> 8); \
|
||||
_ppp_[3] = (Byte)_vvv_; }
|
||||
|
||||
#endif
|
||||
|
||||
#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
|
||||
|
||||
#define GetBe16(p) ( (UInt16) ( \
|
||||
((UInt16)((const Byte *)(p))[0] << 8) | \
|
||||
((const Byte *)(p))[1] ))
|
||||
|
||||
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
|
@ -138,12 +203,14 @@ enum
|
|||
CPU_FIRM_VIA
|
||||
};
|
||||
|
||||
void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);
|
||||
|
||||
Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
|
||||
int x86cpuid_GetFirm(const Cx86cpuid *p);
|
||||
|
||||
#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)
|
||||
#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)
|
||||
#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)
|
||||
#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))
|
||||
#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
|
||||
#define x86cpuid_GetStepping(ver) (ver & 0xF)
|
||||
|
||||
Bool CPU_Is_InOrder();
|
||||
Bool CPU_Is_Aes_Supported();
|
||||
|
|
64
lzma/C/Delta.c
Normal file
64
lzma/C/Delta.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* Delta.c -- Delta converter
|
||||
2009-05-26 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "Delta.h"
|
||||
|
||||
void Delta_Init(Byte *state)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < DELTA_STATE_SIZE; i++)
|
||||
state[i] = 0;
|
||||
}
|
||||
|
||||
static void MyMemCpy(Byte *dest, const Byte *src, unsigned size)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < size; i++)
|
||||
dest[i] = src[i];
|
||||
}
|
||||
|
||||
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||
{
|
||||
Byte buf[DELTA_STATE_SIZE];
|
||||
unsigned j = 0;
|
||||
MyMemCpy(buf, state, delta);
|
||||
{
|
||||
SizeT i;
|
||||
for (i = 0; i < size;)
|
||||
{
|
||||
for (j = 0; j < delta && i < size; i++, j++)
|
||||
{
|
||||
Byte b = data[i];
|
||||
data[i] = (Byte)(b - buf[j]);
|
||||
buf[j] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j == delta)
|
||||
j = 0;
|
||||
MyMemCpy(state, buf + j, delta - j);
|
||||
MyMemCpy(state + delta - j, buf, j);
|
||||
}
|
||||
|
||||
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||
{
|
||||
Byte buf[DELTA_STATE_SIZE];
|
||||
unsigned j = 0;
|
||||
MyMemCpy(buf, state, delta);
|
||||
{
|
||||
SizeT i;
|
||||
for (i = 0; i < size;)
|
||||
{
|
||||
for (j = 0; j < delta && i < size; i++, j++)
|
||||
{
|
||||
buf[j] = data[i] = (Byte)(buf[j] + data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j == delta)
|
||||
j = 0;
|
||||
MyMemCpy(state, buf + j, delta - j);
|
||||
MyMemCpy(state + delta - j, buf, j);
|
||||
}
|
19
lzma/C/Delta.h
Normal file
19
lzma/C/Delta.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/* Delta.h -- Delta converter
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __DELTA_H
|
||||
#define __DELTA_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define DELTA_STATE_SIZE 256
|
||||
|
||||
void Delta_Init(Byte *state);
|
||||
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size);
|
||||
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
499
lzma/C/LzFind.c
499
lzma/C/LzFind.c
|
@ -1,5 +1,7 @@
|
|||
/* LzFind.c -- Match finder for LZ algorithms
|
||||
2009-04-22 : Igor Pavlov : Public domain */
|
||||
2015-10-15 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -9,8 +11,8 @@
|
|||
#define kEmptyHashValue 0
|
||||
#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
|
||||
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
|
||||
#define kNormalizeMask (~(kNormalizeStepMin - 1))
|
||||
#define kMaxHistorySize ((UInt32)3 << 30)
|
||||
#define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))
|
||||
#define kMaxHistorySize ((UInt32)7 << 29)
|
||||
|
||||
#define kStartMaxLen 3
|
||||
|
||||
|
@ -19,7 +21,7 @@ static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
|
|||
if (!p->directInput)
|
||||
{
|
||||
alloc->Free(alloc, p->bufferBase);
|
||||
p->bufferBase = 0;
|
||||
p->bufferBase = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,17 +35,16 @@ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *a
|
|||
p->blockSize = blockSize;
|
||||
return 1;
|
||||
}
|
||||
if (p->bufferBase == 0 || p->blockSize != blockSize)
|
||||
if (!p->bufferBase || p->blockSize != blockSize)
|
||||
{
|
||||
LzInWindow_Free(p, alloc);
|
||||
p->blockSize = blockSize;
|
||||
p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
|
||||
}
|
||||
return (p->bufferBase != 0);
|
||||
return (p->bufferBase != NULL);
|
||||
}
|
||||
|
||||
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
|
||||
Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
|
||||
|
||||
UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
|
||||
|
||||
|
@ -58,9 +59,12 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
|
|||
{
|
||||
if (p->streamEndWasReached || p->result != SZ_OK)
|
||||
return;
|
||||
|
||||
/* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */
|
||||
|
||||
if (p->directInput)
|
||||
{
|
||||
UInt32 curSize = 0xFFFFFFFF - p->streamPos;
|
||||
UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos);
|
||||
if (curSize > p->directInputRem)
|
||||
curSize = (UInt32)p->directInputRem;
|
||||
p->directInputRem -= curSize;
|
||||
|
@ -69,12 +73,14 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
|
|||
p->streamEndWasReached = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte *dest = p->buffer + (p->streamPos - p->pos);
|
||||
size_t size = (p->bufferBase + p->blockSize - dest);
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
p->result = p->stream->Read(p->stream, dest, &size);
|
||||
if (p->result != SZ_OK)
|
||||
return;
|
||||
|
@ -92,8 +98,8 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
|
|||
void MatchFinder_MoveBlock(CMatchFinder *p)
|
||||
{
|
||||
memmove(p->bufferBase,
|
||||
p->buffer - p->keepSizeBefore,
|
||||
(size_t)(p->streamPos - p->pos + p->keepSizeBefore));
|
||||
p->buffer - p->keepSizeBefore,
|
||||
(size_t)(p->streamPos - p->pos) + p->keepSizeBefore);
|
||||
p->buffer = p->bufferBase + p->keepSizeBefore;
|
||||
}
|
||||
|
||||
|
@ -133,15 +139,15 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
|
|||
void MatchFinder_Construct(CMatchFinder *p)
|
||||
{
|
||||
UInt32 i;
|
||||
p->bufferBase = 0;
|
||||
p->bufferBase = NULL;
|
||||
p->directInput = 0;
|
||||
p->hash = 0;
|
||||
p->hash = NULL;
|
||||
MatchFinder_SetDefaultSettings(p);
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
UInt32 r = i;
|
||||
int j;
|
||||
unsigned j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
p->crc[i] = r;
|
||||
|
@ -151,7 +157,7 @@ void MatchFinder_Construct(CMatchFinder *p)
|
|||
static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->hash);
|
||||
p->hash = 0;
|
||||
p->hash = NULL;
|
||||
}
|
||||
|
||||
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
|
||||
|
@ -160,11 +166,11 @@ void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
|
|||
LzInWindow_Free(p, alloc);
|
||||
}
|
||||
|
||||
static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
|
||||
static CLzRef* AllocRefs(size_t num, ISzAlloc *alloc)
|
||||
{
|
||||
size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
|
||||
if (sizeInBytes / sizeof(CLzRef) != num)
|
||||
return 0;
|
||||
return NULL;
|
||||
return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
|
||||
}
|
||||
|
||||
|
@ -173,19 +179,24 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
|||
ISzAlloc *alloc)
|
||||
{
|
||||
UInt32 sizeReserv;
|
||||
|
||||
if (historySize > kMaxHistorySize)
|
||||
{
|
||||
MatchFinder_Free(p, alloc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sizeReserv = historySize >> 1;
|
||||
if (historySize > ((UInt32)2 << 30))
|
||||
sizeReserv = historySize >> 2;
|
||||
if (historySize >= ((UInt32)3 << 30)) sizeReserv = historySize >> 3;
|
||||
else if (historySize >= ((UInt32)2 << 30)) sizeReserv = historySize >> 2;
|
||||
|
||||
sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
|
||||
|
||||
p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
|
||||
p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
|
||||
|
||||
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
|
||||
|
||||
if (LzInWindow_Create(p, sizeReserv, alloc))
|
||||
{
|
||||
UInt32 newCyclicBufferSize = historySize + 1;
|
||||
|
@ -210,6 +221,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
|||
hs = (1 << 24) - 1;
|
||||
else
|
||||
hs >>= 1;
|
||||
/* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */
|
||||
}
|
||||
}
|
||||
p->hashMask = hs;
|
||||
|
@ -221,24 +233,32 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
|||
}
|
||||
|
||||
{
|
||||
UInt32 prevSize = p->hashSizeSum + p->numSons;
|
||||
UInt32 newSize;
|
||||
size_t newSize;
|
||||
size_t numSons;
|
||||
p->historySize = historySize;
|
||||
p->hashSizeSum = hs;
|
||||
p->cyclicBufferSize = newCyclicBufferSize;
|
||||
p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
|
||||
newSize = p->hashSizeSum + p->numSons;
|
||||
if (p->hash != 0 && prevSize == newSize)
|
||||
|
||||
numSons = newCyclicBufferSize;
|
||||
if (p->btMode)
|
||||
numSons <<= 1;
|
||||
newSize = hs + numSons;
|
||||
|
||||
if (p->hash && p->numRefs == newSize)
|
||||
return 1;
|
||||
|
||||
MatchFinder_FreeThisClassMemory(p, alloc);
|
||||
p->numRefs = newSize;
|
||||
p->hash = AllocRefs(newSize, alloc);
|
||||
if (p->hash != 0)
|
||||
|
||||
if (p->hash)
|
||||
{
|
||||
p->son = p->hash + p->hashSizeSum;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MatchFinder_Free(p, alloc);
|
||||
return 0;
|
||||
}
|
||||
|
@ -247,9 +267,11 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
|
|||
{
|
||||
UInt32 limit = kMaxValForNormalize - p->pos;
|
||||
UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
|
||||
|
||||
if (limit2 < limit)
|
||||
limit = limit2;
|
||||
limit2 = p->streamPos - p->pos;
|
||||
|
||||
if (limit2 <= p->keepSizeAfter)
|
||||
{
|
||||
if (limit2 > 0)
|
||||
|
@ -257,8 +279,10 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
|
|||
}
|
||||
else
|
||||
limit2 -= p->keepSizeAfter;
|
||||
|
||||
if (limit2 < limit)
|
||||
limit = limit2;
|
||||
|
||||
{
|
||||
UInt32 lenLimit = p->streamPos - p->pos;
|
||||
if (lenLimit > p->matchMaxLen)
|
||||
|
@ -268,28 +292,39 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
|
|||
p->posLimit = p->pos + limit;
|
||||
}
|
||||
|
||||
void MatchFinder_Init(CMatchFinder *p)
|
||||
void MatchFinder_Init_2(CMatchFinder *p, int readData)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < p->hashSizeSum; i++)
|
||||
p->hash[i] = kEmptyHashValue;
|
||||
UInt32 *hash = p->hash;
|
||||
UInt32 num = p->hashSizeSum;
|
||||
for (i = 0; i < num; i++)
|
||||
hash[i] = kEmptyHashValue;
|
||||
|
||||
p->cyclicBufferPos = 0;
|
||||
p->buffer = p->bufferBase;
|
||||
p->pos = p->streamPos = p->cyclicBufferSize;
|
||||
p->result = SZ_OK;
|
||||
p->streamEndWasReached = 0;
|
||||
MatchFinder_ReadBlock(p);
|
||||
|
||||
if (readData)
|
||||
MatchFinder_ReadBlock(p);
|
||||
|
||||
MatchFinder_SetLimits(p);
|
||||
}
|
||||
|
||||
void MatchFinder_Init(CMatchFinder *p)
|
||||
{
|
||||
MatchFinder_Init_2(p, True);
|
||||
}
|
||||
|
||||
static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
|
||||
{
|
||||
return (p->pos - p->historySize - 1) & kNormalizeMask;
|
||||
}
|
||||
|
||||
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
|
||||
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems)
|
||||
{
|
||||
UInt32 i;
|
||||
size_t i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
UInt32 value = items[i];
|
||||
|
@ -304,7 +339,7 @@ void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
|
|||
static void MatchFinder_Normalize(CMatchFinder *p)
|
||||
{
|
||||
UInt32 subValue = MatchFinder_GetSubValue(p);
|
||||
MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
|
||||
MatchFinder_Normalize3(subValue, p->hash, p->numRefs);
|
||||
MatchFinder_ReduceOffsets(p, subValue);
|
||||
}
|
||||
|
||||
|
@ -465,7 +500,7 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
|
|||
static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
|
||||
|
||||
#define GET_MATCHES_HEADER2(minLen, ret_op) \
|
||||
UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
|
||||
UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
|
||||
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
|
||||
cur = p->buffer;
|
||||
|
||||
|
@ -481,13 +516,20 @@ static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
|
|||
#define SKIP_FOOTER \
|
||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
|
||||
|
||||
#define UPDATE_maxLen { \
|
||||
ptrdiff_t diff = (ptrdiff_t)0 - d2; \
|
||||
const Byte *c = cur + maxLen; \
|
||||
const Byte *lim = cur + lenLimit; \
|
||||
for (; c != lim; c++) if (*(c + diff) != *c) break; \
|
||||
maxLen = (UInt32)(c - cur); }
|
||||
|
||||
static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 offset;
|
||||
GET_MATCHES_HEADER(2)
|
||||
HASH2_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
curMatch = p->hash[hv];
|
||||
p->hash[hv] = p->pos;
|
||||
offset = 0;
|
||||
GET_MATCHES_FOOTER(offset, 1)
|
||||
}
|
||||
|
@ -497,35 +539,38 @@ UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|||
UInt32 offset;
|
||||
GET_MATCHES_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
curMatch = p->hash[hv];
|
||||
p->hash[hv] = p->pos;
|
||||
offset = 0;
|
||||
GET_MATCHES_FOOTER(offset, 2)
|
||||
}
|
||||
|
||||
static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 hash2Value, delta2, maxLen, offset;
|
||||
UInt32 h2, d2, maxLen, offset, pos;
|
||||
UInt32 *hash;
|
||||
GET_MATCHES_HEADER(3)
|
||||
|
||||
HASH3_CALC;
|
||||
|
||||
delta2 = p->pos - p->hash[hash2Value];
|
||||
curMatch = p->hash[kFix3HashSize + hashValue];
|
||||
|
||||
p->hash[hash2Value] =
|
||||
p->hash[kFix3HashSize + hashValue] = p->pos;
|
||||
hash = p->hash;
|
||||
pos = p->pos;
|
||||
|
||||
d2 = pos - hash[h2];
|
||||
|
||||
curMatch = hash[kFix3HashSize + hv];
|
||||
|
||||
hash[h2] = pos;
|
||||
hash[kFix3HashSize + hv] = pos;
|
||||
|
||||
maxLen = 2;
|
||||
offset = 0;
|
||||
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||
|
||||
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
|
||||
{
|
||||
for (; maxLen != lenLimit; maxLen++)
|
||||
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
||||
break;
|
||||
UPDATE_maxLen
|
||||
distances[0] = maxLen;
|
||||
distances[1] = delta2 - 1;
|
||||
distances[1] = d2 - 1;
|
||||
offset = 2;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
|
@ -533,44 +578,51 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
|
||||
GET_MATCHES_FOOTER(offset, maxLen)
|
||||
}
|
||||
|
||||
static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
|
||||
UInt32 h2, h3, d2, d3, maxLen, offset, pos;
|
||||
UInt32 *hash;
|
||||
GET_MATCHES_HEADER(4)
|
||||
|
||||
HASH4_CALC;
|
||||
|
||||
delta2 = p->pos - p->hash[ hash2Value];
|
||||
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
|
||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||
|
||||
p->hash[ hash2Value] =
|
||||
p->hash[kFix3HashSize + hash3Value] =
|
||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||
hash = p->hash;
|
||||
pos = p->pos;
|
||||
|
||||
maxLen = 1;
|
||||
d2 = pos - hash[ h2];
|
||||
d3 = pos - hash[kFix3HashSize + h3];
|
||||
|
||||
curMatch = hash[kFix4HashSize + hv];
|
||||
|
||||
hash[ h2] = pos;
|
||||
hash[kFix3HashSize + h3] = pos;
|
||||
hash[kFix4HashSize + hv] = pos;
|
||||
|
||||
maxLen = 0;
|
||||
offset = 0;
|
||||
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||
|
||||
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
|
||||
{
|
||||
distances[0] = maxLen = 2;
|
||||
distances[1] = delta2 - 1;
|
||||
distances[1] = d2 - 1;
|
||||
offset = 2;
|
||||
}
|
||||
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
|
||||
|
||||
if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
|
||||
{
|
||||
maxLen = 3;
|
||||
distances[offset + 1] = delta3 - 1;
|
||||
distances[offset + 1] = d3 - 1;
|
||||
offset += 2;
|
||||
delta2 = delta3;
|
||||
d2 = d3;
|
||||
}
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
for (; maxLen != lenLimit; maxLen++)
|
||||
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
||||
break;
|
||||
UPDATE_maxLen
|
||||
distances[offset - 2] = maxLen;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
|
@ -578,46 +630,131 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxLen < 3)
|
||||
maxLen = 3;
|
||||
|
||||
GET_MATCHES_FOOTER(offset, maxLen)
|
||||
}
|
||||
|
||||
/*
|
||||
static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos;
|
||||
UInt32 *hash;
|
||||
GET_MATCHES_HEADER(5)
|
||||
|
||||
HASH5_CALC;
|
||||
|
||||
hash = p->hash;
|
||||
pos = p->pos;
|
||||
|
||||
d2 = pos - hash[ h2];
|
||||
d3 = pos - hash[kFix3HashSize + h3];
|
||||
d4 = pos - hash[kFix4HashSize + h4];
|
||||
|
||||
curMatch = hash[kFix5HashSize + hv];
|
||||
|
||||
hash[ h2] = pos;
|
||||
hash[kFix3HashSize + h3] = pos;
|
||||
hash[kFix4HashSize + h4] = pos;
|
||||
hash[kFix5HashSize + hv] = pos;
|
||||
|
||||
maxLen = 0;
|
||||
offset = 0;
|
||||
|
||||
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
|
||||
{
|
||||
distances[0] = maxLen = 2;
|
||||
distances[1] = d2 - 1;
|
||||
offset = 2;
|
||||
if (*(cur - d2 + 2) == cur[2])
|
||||
distances[0] = maxLen = 3;
|
||||
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
|
||||
{
|
||||
distances[2] = maxLen = 3;
|
||||
distances[3] = d3 - 1;
|
||||
offset = 4;
|
||||
d2 = d3;
|
||||
}
|
||||
}
|
||||
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
|
||||
{
|
||||
distances[0] = maxLen = 3;
|
||||
distances[1] = d3 - 1;
|
||||
offset = 2;
|
||||
d2 = d3;
|
||||
}
|
||||
|
||||
if (d2 != d4 && d4 < p->cyclicBufferSize
|
||||
&& *(cur - d4) == *cur
|
||||
&& *(cur - d4 + 3) == *(cur + 3))
|
||||
{
|
||||
maxLen = 4;
|
||||
distances[offset + 1] = d4 - 1;
|
||||
offset += 2;
|
||||
d2 = d4;
|
||||
}
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
UPDATE_maxLen
|
||||
distances[offset - 2] = maxLen;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
|
||||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxLen < 4)
|
||||
maxLen = 4;
|
||||
|
||||
GET_MATCHES_FOOTER(offset, maxLen)
|
||||
}
|
||||
*/
|
||||
|
||||
static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
|
||||
UInt32 h2, h3, d2, d3, maxLen, offset, pos;
|
||||
UInt32 *hash;
|
||||
GET_MATCHES_HEADER(4)
|
||||
|
||||
HASH4_CALC;
|
||||
|
||||
delta2 = p->pos - p->hash[ hash2Value];
|
||||
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
|
||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||
hash = p->hash;
|
||||
pos = p->pos;
|
||||
|
||||
d2 = pos - hash[ h2];
|
||||
d3 = pos - hash[kFix3HashSize + h3];
|
||||
|
||||
curMatch = hash[kFix4HashSize + hv];
|
||||
|
||||
p->hash[ hash2Value] =
|
||||
p->hash[kFix3HashSize + hash3Value] =
|
||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||
hash[ h2] = pos;
|
||||
hash[kFix3HashSize + h3] = pos;
|
||||
hash[kFix4HashSize + hv] = pos;
|
||||
|
||||
maxLen = 1;
|
||||
maxLen = 0;
|
||||
offset = 0;
|
||||
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||
|
||||
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
|
||||
{
|
||||
distances[0] = maxLen = 2;
|
||||
distances[1] = delta2 - 1;
|
||||
distances[1] = d2 - 1;
|
||||
offset = 2;
|
||||
}
|
||||
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
|
||||
|
||||
if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
|
||||
{
|
||||
maxLen = 3;
|
||||
distances[offset + 1] = delta3 - 1;
|
||||
distances[offset + 1] = d3 - 1;
|
||||
offset += 2;
|
||||
delta2 = delta3;
|
||||
d2 = d3;
|
||||
}
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
for (; maxLen != lenLimit; maxLen++)
|
||||
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
||||
break;
|
||||
UPDATE_maxLen
|
||||
distances[offset - 2] = maxLen;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
|
@ -625,22 +762,103 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxLen < 3)
|
||||
maxLen = 3;
|
||||
|
||||
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
||||
distances + offset, maxLen) - (distances));
|
||||
distances + offset, maxLen) - (distances));
|
||||
MOVE_POS_RET
|
||||
}
|
||||
|
||||
/*
|
||||
static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos
|
||||
UInt32 *hash;
|
||||
GET_MATCHES_HEADER(5)
|
||||
|
||||
HASH5_CALC;
|
||||
|
||||
hash = p->hash;
|
||||
pos = p->pos;
|
||||
|
||||
d2 = pos - hash[ h2];
|
||||
d3 = pos - hash[kFix3HashSize + h3];
|
||||
d4 = pos - hash[kFix4HashSize + h4];
|
||||
|
||||
curMatch = hash[kFix5HashSize + hv];
|
||||
|
||||
hash[ h2] = pos;
|
||||
hash[kFix3HashSize + h3] = pos;
|
||||
hash[kFix4HashSize + h4] = pos;
|
||||
hash[kFix5HashSize + hv] = pos;
|
||||
|
||||
maxLen = 0;
|
||||
offset = 0;
|
||||
|
||||
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
|
||||
{
|
||||
distances[0] = maxLen = 2;
|
||||
distances[1] = d2 - 1;
|
||||
offset = 2;
|
||||
if (*(cur - d2 + 2) == cur[2])
|
||||
distances[0] = maxLen = 3;
|
||||
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
|
||||
{
|
||||
distances[2] = maxLen = 3;
|
||||
distances[3] = d3 - 1;
|
||||
offset = 4;
|
||||
d2 = d3;
|
||||
}
|
||||
}
|
||||
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
|
||||
{
|
||||
distances[0] = maxLen = 3;
|
||||
distances[1] = d3 - 1;
|
||||
offset = 2;
|
||||
d2 = d3;
|
||||
}
|
||||
|
||||
if (d2 != d4 && d4 < p->cyclicBufferSize
|
||||
&& *(cur - d4) == *cur
|
||||
&& *(cur - d4 + 3) == *(cur + 3))
|
||||
{
|
||||
maxLen = 4;
|
||||
distances[offset + 1] = d4 - 1;
|
||||
offset += 2;
|
||||
d2 = d4;
|
||||
}
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
UPDATE_maxLen
|
||||
distances[offset - 2] = maxLen;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxLen < 4)
|
||||
maxLen = 4;
|
||||
|
||||
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
||||
distances + offset, maxLen) - (distances));
|
||||
MOVE_POS_RET
|
||||
}
|
||||
*/
|
||||
|
||||
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 offset;
|
||||
GET_MATCHES_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
curMatch = p->hash[hv];
|
||||
p->hash[hv] = p->pos;
|
||||
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
||||
distances, 2) - (distances));
|
||||
distances, 2) - (distances));
|
||||
MOVE_POS_RET
|
||||
}
|
||||
|
||||
|
@ -650,8 +868,8 @@ static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
|||
{
|
||||
SKIP_HEADER(2)
|
||||
HASH2_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
curMatch = p->hash[hv];
|
||||
p->hash[hv] = p->pos;
|
||||
SKIP_FOOTER
|
||||
}
|
||||
while (--num != 0);
|
||||
|
@ -663,8 +881,8 @@ void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
|||
{
|
||||
SKIP_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
curMatch = p->hash[hv];
|
||||
p->hash[hv] = p->pos;
|
||||
SKIP_FOOTER
|
||||
}
|
||||
while (--num != 0);
|
||||
|
@ -674,12 +892,14 @@ static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
|||
{
|
||||
do
|
||||
{
|
||||
UInt32 hash2Value;
|
||||
UInt32 h2;
|
||||
UInt32 *hash;
|
||||
SKIP_HEADER(3)
|
||||
HASH3_CALC;
|
||||
curMatch = p->hash[kFix3HashSize + hashValue];
|
||||
p->hash[hash2Value] =
|
||||
p->hash[kFix3HashSize + hashValue] = p->pos;
|
||||
hash = p->hash;
|
||||
curMatch = hash[kFix3HashSize + hv];
|
||||
hash[h2] =
|
||||
hash[kFix3HashSize + hv] = p->pos;
|
||||
SKIP_FOOTER
|
||||
}
|
||||
while (--num != 0);
|
||||
|
@ -689,43 +909,90 @@ static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
|||
{
|
||||
do
|
||||
{
|
||||
UInt32 hash2Value, hash3Value;
|
||||
UInt32 h2, h3;
|
||||
UInt32 *hash;
|
||||
SKIP_HEADER(4)
|
||||
HASH4_CALC;
|
||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||
p->hash[ hash2Value] =
|
||||
p->hash[kFix3HashSize + hash3Value] = p->pos;
|
||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||
hash = p->hash;
|
||||
curMatch = hash[kFix4HashSize + hv];
|
||||
hash[ h2] =
|
||||
hash[kFix3HashSize + h3] =
|
||||
hash[kFix4HashSize + hv] = p->pos;
|
||||
SKIP_FOOTER
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||
{
|
||||
do
|
||||
{
|
||||
UInt32 h2, h3, h4;
|
||||
UInt32 *hash;
|
||||
SKIP_HEADER(5)
|
||||
HASH5_CALC;
|
||||
hash = p->hash;
|
||||
curMatch = hash[kFix5HashSize + hv];
|
||||
hash[ h2] =
|
||||
hash[kFix3HashSize + h3] =
|
||||
hash[kFix4HashSize + h4] =
|
||||
hash[kFix5HashSize + hv] = p->pos;
|
||||
SKIP_FOOTER
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
*/
|
||||
|
||||
static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||
{
|
||||
do
|
||||
{
|
||||
UInt32 hash2Value, hash3Value;
|
||||
UInt32 h2, h3;
|
||||
UInt32 *hash;
|
||||
SKIP_HEADER(4)
|
||||
HASH4_CALC;
|
||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||
p->hash[ hash2Value] =
|
||||
p->hash[kFix3HashSize + hash3Value] =
|
||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||
hash = p->hash;
|
||||
curMatch = hash[kFix4HashSize + hv];
|
||||
hash[ h2] =
|
||||
hash[kFix3HashSize + h3] =
|
||||
hash[kFix4HashSize + hv] = p->pos;
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||
{
|
||||
do
|
||||
{
|
||||
UInt32 h2, h3, h4;
|
||||
UInt32 *hash;
|
||||
SKIP_HEADER(5)
|
||||
HASH5_CALC;
|
||||
hash = p->hash;
|
||||
curMatch = p->hash[kFix5HashSize + hv];
|
||||
hash[ h2] =
|
||||
hash[kFix3HashSize + h3] =
|
||||
hash[kFix4HashSize + h4] =
|
||||
hash[kFix5HashSize + hv] = p->pos;
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
*/
|
||||
|
||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||
{
|
||||
do
|
||||
{
|
||||
SKIP_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
curMatch = p->hash[hv];
|
||||
p->hash[hv] = p->pos;
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS
|
||||
}
|
||||
|
@ -735,13 +1002,22 @@ void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
|||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
|
||||
{
|
||||
vTable->Init = (Mf_Init_Func)MatchFinder_Init;
|
||||
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
|
||||
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
|
||||
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
|
||||
if (!p->btMode)
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
|
||||
/* if (p->numHashBytes <= 4) */
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (p->numHashBytes == 2)
|
||||
{
|
||||
|
@ -753,9 +1029,16 @@ void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
|
|||
vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
|
||||
}
|
||||
else
|
||||
else /* if (p->numHashBytes == 4) */
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
/* LzFind.h -- Match finder for LZ algorithms
|
||||
2009-04-22 : Igor Pavlov : Public domain */
|
||||
2015-10-15 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZ_FIND_H
|
||||
#define __LZ_FIND_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
typedef UInt32 CLzRef;
|
||||
|
||||
|
@ -23,6 +21,11 @@ typedef struct _CMatchFinder
|
|||
UInt32 cyclicBufferPos;
|
||||
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
|
||||
|
||||
Byte streamEndWasReached;
|
||||
Byte btMode;
|
||||
Byte bigHash;
|
||||
Byte directInput;
|
||||
|
||||
UInt32 matchMaxLen;
|
||||
CLzRef *hash;
|
||||
CLzRef *son;
|
||||
|
@ -31,30 +34,30 @@ typedef struct _CMatchFinder
|
|||
|
||||
Byte *bufferBase;
|
||||
ISeqInStream *stream;
|
||||
int streamEndWasReached;
|
||||
|
||||
|
||||
UInt32 blockSize;
|
||||
UInt32 keepSizeBefore;
|
||||
UInt32 keepSizeAfter;
|
||||
|
||||
UInt32 numHashBytes;
|
||||
int directInput;
|
||||
size_t directInputRem;
|
||||
int btMode;
|
||||
int bigHash;
|
||||
UInt32 historySize;
|
||||
UInt32 fixedHashSize;
|
||||
UInt32 hashSizeSum;
|
||||
UInt32 numSons;
|
||||
SRes result;
|
||||
UInt32 crc[256];
|
||||
size_t numRefs;
|
||||
} CMatchFinder;
|
||||
|
||||
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
|
||||
#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
|
||||
|
||||
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
|
||||
|
||||
#define Inline_MatchFinder_IsFinishedOK(p) \
|
||||
((p)->streamEndWasReached \
|
||||
&& (p)->streamPos == (p)->pos \
|
||||
&& (!(p)->directInput || (p)->directInputRem == 0))
|
||||
|
||||
int MatchFinder_NeedMove(CMatchFinder *p);
|
||||
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
|
||||
void MatchFinder_MoveBlock(CMatchFinder *p);
|
||||
|
@ -70,7 +73,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
|||
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
|
||||
ISzAlloc *alloc);
|
||||
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
|
||||
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
|
||||
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems);
|
||||
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
|
||||
|
||||
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
|
||||
|
@ -84,7 +87,6 @@ Conditions:
|
|||
*/
|
||||
|
||||
typedef void (*Mf_Init_Func)(void *object);
|
||||
typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
|
||||
typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
|
||||
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
|
||||
typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
|
||||
|
@ -93,7 +95,6 @@ typedef void (*Mf_Skip_Func)(void *object, UInt32);
|
|||
typedef struct _IMatchFinder
|
||||
{
|
||||
Mf_Init_Func Init;
|
||||
Mf_GetIndexByte_Func GetIndexByte;
|
||||
Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
|
||||
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
|
||||
Mf_GetMatches_Func GetMatches;
|
||||
|
@ -102,14 +103,15 @@ typedef struct _IMatchFinder
|
|||
|
||||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
|
||||
|
||||
void MatchFinder_Init_2(CMatchFinder *p, int readData);
|
||||
void MatchFinder_Init(CMatchFinder *p);
|
||||
|
||||
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||
|
||||
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
|
||||
2009-09-20 : Igor Pavlov : Public domain */
|
||||
2015-10-15 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "LzHash.h"
|
||||
|
||||
#include "LzFindMt.h"
|
||||
|
||||
void MtSync_Construct(CMtSync *p)
|
||||
static void MtSync_Construct(CMtSync *p)
|
||||
{
|
||||
p->wasCreated = False;
|
||||
p->csWasInitialized = False;
|
||||
|
@ -18,7 +20,7 @@ void MtSync_Construct(CMtSync *p)
|
|||
Semaphore_Construct(&p->filledSemaphore);
|
||||
}
|
||||
|
||||
void MtSync_GetNextBlock(CMtSync *p)
|
||||
static void MtSync_GetNextBlock(CMtSync *p)
|
||||
{
|
||||
if (p->needStart)
|
||||
{
|
||||
|
@ -46,7 +48,7 @@ void MtSync_GetNextBlock(CMtSync *p)
|
|||
|
||||
/* MtSync_StopWriting must be called if Writing was started */
|
||||
|
||||
void MtSync_StopWriting(CMtSync *p)
|
||||
static void MtSync_StopWriting(CMtSync *p)
|
||||
{
|
||||
UInt32 myNumBlocks = p->numProcessedBlocks;
|
||||
if (!Thread_WasCreated(&p->thread) || p->needStart)
|
||||
|
@ -69,7 +71,7 @@ void MtSync_StopWriting(CMtSync *p)
|
|||
p->needStart = True;
|
||||
}
|
||||
|
||||
void MtSync_Destruct(CMtSync *p)
|
||||
static void MtSync_Destruct(CMtSync *p)
|
||||
{
|
||||
if (Thread_WasCreated(&p->thread))
|
||||
{
|
||||
|
@ -97,7 +99,7 @@ void MtSync_Destruct(CMtSync *p)
|
|||
|
||||
#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
|
||||
|
||||
static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
|
||||
static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks)
|
||||
{
|
||||
if (p->wasCreated)
|
||||
return SZ_OK;
|
||||
|
@ -119,7 +121,7 @@ static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void
|
|||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
|
||||
static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks)
|
||||
{
|
||||
SRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
|
||||
if (res != SZ_OK)
|
||||
|
@ -132,20 +134,20 @@ void MtSync_Init(CMtSync *p) { p->needStart = True; }
|
|||
#define kMtMaxValForNormalize 0xFFFFFFFF
|
||||
|
||||
#define DEF_GetHeads2(name, v, action) \
|
||||
static void GetHeads ## name(const Byte *p, UInt32 pos, \
|
||||
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
|
||||
{ action; for (; numHeads != 0; numHeads--) { \
|
||||
const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
|
||||
static void GetHeads ## name(const Byte *p, UInt32 pos, \
|
||||
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
|
||||
{ action; for (; numHeads != 0; numHeads--) { \
|
||||
const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
|
||||
|
||||
#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)
|
||||
|
||||
DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; )
|
||||
DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), UNUSED_VAR(hashMask); UNUSED_VAR(crc); )
|
||||
DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
|
||||
DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)
|
||||
DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
|
||||
/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */
|
||||
|
||||
void HashThreadFunc(CMatchFinderMt *mt)
|
||||
static void HashThreadFunc(CMatchFinderMt *mt)
|
||||
{
|
||||
CMtSync *p = &mt->hashSync;
|
||||
for (;;)
|
||||
|
@ -171,12 +173,12 @@ void HashThreadFunc(CMatchFinderMt *mt)
|
|||
CriticalSection_Enter(&mt->btSync.cs);
|
||||
CriticalSection_Enter(&mt->hashSync.cs);
|
||||
{
|
||||
const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);
|
||||
const Byte *afterPtr;
|
||||
const Byte *beforePtr = Inline_MatchFinder_GetPointerToCurrentPos(mf);
|
||||
ptrdiff_t offset;
|
||||
MatchFinder_MoveBlock(mf);
|
||||
afterPtr = MatchFinder_GetPointerToCurrentPos(mf);
|
||||
mt->pointerToCurPos -= beforePtr - afterPtr;
|
||||
mt->buffer -= beforePtr - afterPtr;
|
||||
offset = beforePtr - Inline_MatchFinder_GetPointerToCurrentPos(mf);
|
||||
mt->pointerToCurPos -= offset;
|
||||
mt->buffer -= offset;
|
||||
}
|
||||
CriticalSection_Leave(&mt->btSync.cs);
|
||||
CriticalSection_Leave(&mt->hashSync.cs);
|
||||
|
@ -190,7 +192,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
|
|||
{
|
||||
UInt32 subValue = (mf->pos - mf->historySize - 1);
|
||||
MatchFinder_ReduceOffsets(mf, subValue);
|
||||
MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);
|
||||
MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1);
|
||||
}
|
||||
{
|
||||
UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;
|
||||
|
@ -215,7 +217,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
|
|||
}
|
||||
}
|
||||
|
||||
void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
|
||||
static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
|
||||
{
|
||||
MtSync_GetNextBlock(&p->hashSync);
|
||||
p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
|
||||
|
@ -231,7 +233,7 @@ void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
|
|||
|
||||
#define NO_INLINE MY_FAST_CALL
|
||||
|
||||
Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||
static Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
||||
UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
|
||||
{
|
||||
|
@ -308,12 +310,14 @@ Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CL
|
|||
|
||||
#endif
|
||||
|
||||
void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
{
|
||||
UInt32 numProcessed = 0;
|
||||
UInt32 curPos = 2;
|
||||
UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
|
||||
|
||||
distances[1] = p->hashNumAvail;
|
||||
|
||||
while (curPos < limit)
|
||||
{
|
||||
if (p->hashBufPos == p->hashBufPosLimit)
|
||||
|
@ -322,9 +326,11 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|||
distances[1] = numProcessed + p->hashNumAvail;
|
||||
if (p->hashNumAvail >= p->numHashBytes)
|
||||
continue;
|
||||
distances[0] = curPos + p->hashNumAvail;
|
||||
distances += curPos;
|
||||
for (; p->hashNumAvail != 0; p->hashNumAvail--)
|
||||
distances[curPos++] = 0;
|
||||
break;
|
||||
*distances++ = 0;
|
||||
return;
|
||||
}
|
||||
{
|
||||
UInt32 size = p->hashBufPosLimit - p->hashBufPos;
|
||||
|
@ -341,13 +347,14 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|||
if (size2 < size)
|
||||
size = size2;
|
||||
}
|
||||
|
||||
#ifndef MFMT_GM_INLINE
|
||||
while (curPos < limit && size-- != 0)
|
||||
{
|
||||
UInt32 *startDistances = distances + curPos;
|
||||
UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
|
||||
pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
||||
startDistances + 1, p->numHashBytes - 1) - startDistances);
|
||||
pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
||||
startDistances + 1, p->numHashBytes - 1) - startDistances);
|
||||
*startDistances = num - 1;
|
||||
curPos += num;
|
||||
cyclicBufferPos++;
|
||||
|
@ -358,7 +365,7 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|||
{
|
||||
UInt32 posRes;
|
||||
curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
||||
distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
|
||||
distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos), size, &posRes);
|
||||
p->hashBufPos += posRes - pos;
|
||||
cyclicBufferPos += posRes - pos;
|
||||
p->buffer += posRes - pos;
|
||||
|
@ -374,10 +381,11 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|||
p->cyclicBufferPos = cyclicBufferPos;
|
||||
}
|
||||
}
|
||||
|
||||
distances[0] = curPos;
|
||||
}
|
||||
|
||||
void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
|
||||
static void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
|
||||
{
|
||||
CMtSync *sync = &p->hashSync;
|
||||
if (!sync->needStart)
|
||||
|
@ -391,7 +399,7 @@ void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
|
|||
if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
|
||||
{
|
||||
UInt32 subValue = p->pos - p->cyclicBufferSize;
|
||||
MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);
|
||||
MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2);
|
||||
p->pos -= subValue;
|
||||
}
|
||||
|
||||
|
@ -430,15 +438,15 @@ void BtThreadFunc(CMatchFinderMt *mt)
|
|||
|
||||
void MatchFinderMt_Construct(CMatchFinderMt *p)
|
||||
{
|
||||
p->hashBuf = 0;
|
||||
p->hashBuf = NULL;
|
||||
MtSync_Construct(&p->hashSync);
|
||||
MtSync_Construct(&p->btSync);
|
||||
}
|
||||
|
||||
void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
|
||||
static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->hashBuf);
|
||||
p->hashBuf = 0;
|
||||
p->hashBuf = NULL;
|
||||
}
|
||||
|
||||
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
|
||||
|
@ -451,14 +459,15 @@ void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
|
|||
#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
|
||||
#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
|
||||
|
||||
static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
|
||||
static unsigned MY_STD_CALL BtThreadFunc2(void *p)
|
||||
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
|
||||
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p)
|
||||
{
|
||||
Byte allocaDummy[0x180];
|
||||
int i = 0;
|
||||
unsigned i = 0;
|
||||
for (i = 0; i < 16; i++)
|
||||
allocaDummy[i] = (Byte)i;
|
||||
BtThreadFunc((CMatchFinderMt *)p);
|
||||
allocaDummy[i] = (Byte)0;
|
||||
if (allocaDummy[0] == 0)
|
||||
BtThreadFunc((CMatchFinderMt *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -469,10 +478,10 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB
|
|||
p->historySize = historySize;
|
||||
if (kMtBtBlockSize <= matchMaxLen * 4)
|
||||
return SZ_ERROR_PARAM;
|
||||
if (p->hashBuf == 0)
|
||||
if (!p->hashBuf)
|
||||
{
|
||||
p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
|
||||
if (p->hashBuf == 0)
|
||||
if (!p->hashBuf)
|
||||
return SZ_ERROR_MEM;
|
||||
p->btBuf = p->hashBuf + kHashBufferSize;
|
||||
}
|
||||
|
@ -492,8 +501,11 @@ void MatchFinderMt_Init(CMatchFinderMt *p)
|
|||
CMatchFinder *mf = p->MatchFinder;
|
||||
p->btBufPos = p->btBufPosLimit = 0;
|
||||
p->hashBufPos = p->hashBufPosLimit = 0;
|
||||
MatchFinder_Init(mf);
|
||||
p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);
|
||||
|
||||
/* Init without data reading. We don't want to read data in this thread */
|
||||
MatchFinder_Init_2(mf, False);
|
||||
|
||||
p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf);
|
||||
p->btNumAvailBytes = 0;
|
||||
p->lzPos = p->historySize + 1;
|
||||
|
||||
|
@ -518,13 +530,13 @@ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
|
|||
/* p->MatchFinder->ReleaseStream(); */
|
||||
}
|
||||
|
||||
void MatchFinderMt_Normalize(CMatchFinderMt *p)
|
||||
static void MatchFinderMt_Normalize(CMatchFinderMt *p)
|
||||
{
|
||||
MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);
|
||||
p->lzPos = p->historySize + 1;
|
||||
}
|
||||
|
||||
void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
|
||||
static void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
|
||||
{
|
||||
UInt32 blockIndex;
|
||||
MtSync_GetNextBlock(&p->btSync);
|
||||
|
@ -536,34 +548,29 @@ void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
|
|||
MatchFinderMt_Normalize(p);
|
||||
}
|
||||
|
||||
const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
|
||||
static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
|
||||
{
|
||||
return p->pointerToCurPos;
|
||||
}
|
||||
|
||||
#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
|
||||
|
||||
UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
|
||||
static UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
|
||||
{
|
||||
GET_NEXT_BLOCK_IF_REQUIRED;
|
||||
return p->btNumAvailBytes;
|
||||
}
|
||||
|
||||
Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)
|
||||
static UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||
{
|
||||
return p->pointerToCurPos[index];
|
||||
}
|
||||
|
||||
UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||
{
|
||||
UInt32 hash2Value, curMatch2;
|
||||
UInt32 h2, curMatch2;
|
||||
UInt32 *hash = p->hash;
|
||||
const Byte *cur = p->pointerToCurPos;
|
||||
UInt32 lzPos = p->lzPos;
|
||||
MT_HASH2_CALC
|
||||
|
||||
curMatch2 = hash[hash2Value];
|
||||
hash[hash2Value] = lzPos;
|
||||
curMatch2 = hash[h2];
|
||||
hash[h2] = lzPos;
|
||||
|
||||
if (curMatch2 >= matchMinPos)
|
||||
if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
||||
|
@ -571,23 +578,23 @@ UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
|||
*distances++ = 2;
|
||||
*distances++ = lzPos - curMatch2 - 1;
|
||||
}
|
||||
|
||||
return distances;
|
||||
}
|
||||
|
||||
UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||
static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||
{
|
||||
UInt32 hash2Value, hash3Value, curMatch2, curMatch3;
|
||||
UInt32 h2, h3, curMatch2, curMatch3;
|
||||
UInt32 *hash = p->hash;
|
||||
const Byte *cur = p->pointerToCurPos;
|
||||
UInt32 lzPos = p->lzPos;
|
||||
MT_HASH3_CALC
|
||||
|
||||
curMatch2 = hash[ hash2Value];
|
||||
curMatch3 = hash[kFix3HashSize + hash3Value];
|
||||
curMatch2 = hash[ h2];
|
||||
curMatch3 = hash[kFix3HashSize + h3];
|
||||
|
||||
hash[ hash2Value] =
|
||||
hash[kFix3HashSize + hash3Value] =
|
||||
lzPos;
|
||||
hash[ h2] = lzPos;
|
||||
hash[kFix3HashSize + h3] = lzPos;
|
||||
|
||||
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
||||
{
|
||||
|
@ -600,43 +607,45 @@ UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
|||
distances[0] = 2;
|
||||
distances += 2;
|
||||
}
|
||||
|
||||
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
|
||||
{
|
||||
*distances++ = 3;
|
||||
*distances++ = lzPos - curMatch3 - 1;
|
||||
}
|
||||
|
||||
return distances;
|
||||
}
|
||||
|
||||
/*
|
||||
UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||
static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||
{
|
||||
UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
|
||||
UInt32 h2, h3, h4, curMatch2, curMatch3, curMatch4;
|
||||
UInt32 *hash = p->hash;
|
||||
const Byte *cur = p->pointerToCurPos;
|
||||
UInt32 lzPos = p->lzPos;
|
||||
MT_HASH4_CALC
|
||||
|
||||
curMatch2 = hash[ hash2Value];
|
||||
curMatch3 = hash[kFix3HashSize + hash3Value];
|
||||
curMatch4 = hash[kFix4HashSize + hash4Value];
|
||||
curMatch2 = hash[ h2];
|
||||
curMatch3 = hash[kFix3HashSize + h3];
|
||||
curMatch4 = hash[kFix4HashSize + h4];
|
||||
|
||||
hash[ hash2Value] =
|
||||
hash[kFix3HashSize + hash3Value] =
|
||||
hash[kFix4HashSize + hash4Value] =
|
||||
lzPos;
|
||||
hash[ h2] = lzPos;
|
||||
hash[kFix3HashSize + h3] = lzPos;
|
||||
hash[kFix4HashSize + h4] = lzPos;
|
||||
|
||||
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
||||
{
|
||||
distances[1] = lzPos - curMatch2 - 1;
|
||||
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
|
||||
{
|
||||
distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
|
||||
distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
|
||||
return distances + 2;
|
||||
}
|
||||
distances[0] = 2;
|
||||
distances += 2;
|
||||
}
|
||||
|
||||
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
|
||||
{
|
||||
distances[1] = lzPos - curMatch3 - 1;
|
||||
|
@ -658,13 +667,14 @@ UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
|||
*distances++ = 4;
|
||||
*distances++ = lzPos - curMatch4 - 1;
|
||||
}
|
||||
|
||||
return distances;
|
||||
}
|
||||
*/
|
||||
|
||||
#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
|
||||
|
||||
UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
static UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
{
|
||||
const UInt32 *btBuf = p->btBuf + p->btBufPos;
|
||||
UInt32 len = *btBuf++;
|
||||
|
@ -682,7 +692,7 @@ UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|||
return len;
|
||||
}
|
||||
|
||||
UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
static UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||
{
|
||||
const UInt32 *btBuf = p->btBuf + p->btBufPos;
|
||||
UInt32 len = *btBuf++;
|
||||
|
@ -690,6 +700,7 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|||
|
||||
if (len == 0)
|
||||
{
|
||||
/* change for bt5 ! */
|
||||
if (p->btNumAvailBytes-- >= 4)
|
||||
len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
|
||||
}
|
||||
|
@ -705,7 +716,7 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|||
*distances2++ = *btBuf++;
|
||||
}
|
||||
while ((len -= 2) != 0);
|
||||
len = (UInt32)(distances2 - (distances));
|
||||
len = (UInt32)(distances2 - (distances));
|
||||
}
|
||||
INCREASE_LZ_POS
|
||||
return len;
|
||||
|
@ -715,41 +726,41 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|||
#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
|
||||
#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);
|
||||
|
||||
void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
static void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
{
|
||||
SKIP_HEADER2_MT { p->btNumAvailBytes--;
|
||||
SKIP_FOOTER_MT
|
||||
}
|
||||
|
||||
void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
static void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
{
|
||||
SKIP_HEADER_MT(2)
|
||||
UInt32 hash2Value;
|
||||
UInt32 h2;
|
||||
MT_HASH2_CALC
|
||||
hash[hash2Value] = p->lzPos;
|
||||
hash[h2] = p->lzPos;
|
||||
SKIP_FOOTER_MT
|
||||
}
|
||||
|
||||
void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
{
|
||||
SKIP_HEADER_MT(3)
|
||||
UInt32 hash2Value, hash3Value;
|
||||
UInt32 h2, h3;
|
||||
MT_HASH3_CALC
|
||||
hash[kFix3HashSize + hash3Value] =
|
||||
hash[ hash2Value] =
|
||||
hash[kFix3HashSize + h3] =
|
||||
hash[ h2] =
|
||||
p->lzPos;
|
||||
SKIP_FOOTER_MT
|
||||
}
|
||||
|
||||
/*
|
||||
void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
|
||||
{
|
||||
SKIP_HEADER_MT(4)
|
||||
UInt32 hash2Value, hash3Value, hash4Value;
|
||||
UInt32 h2, h3, h4;
|
||||
MT_HASH4_CALC
|
||||
hash[kFix4HashSize + hash4Value] =
|
||||
hash[kFix3HashSize + hash3Value] =
|
||||
hash[ hash2Value] =
|
||||
hash[kFix4HashSize + h4] =
|
||||
hash[kFix3HashSize + h3] =
|
||||
hash[ h2] =
|
||||
p->lzPos;
|
||||
SKIP_FOOTER_MT
|
||||
}
|
||||
|
@ -758,11 +769,11 @@ void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
|
|||
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
|
||||
{
|
||||
vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
|
||||
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
|
||||
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
|
||||
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
|
||||
switch(p->MatchFinder->numHashBytes)
|
||||
|
||||
switch (p->MatchFinder->numHashBytes)
|
||||
{
|
||||
case 2:
|
||||
p->GetHeadsFunc = GetHeads2;
|
||||
|
@ -778,7 +789,6 @@ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
|
|||
default:
|
||||
/* case 4: */
|
||||
p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
|
||||
/* p->GetHeadsFunc = GetHeads4; */
|
||||
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
|
||||
vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
|
||||
break;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
2015-05-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZ_FIND_MT_H
|
||||
#define __LZ_FIND_MT_H
|
||||
|
@ -7,9 +7,7 @@
|
|||
#include "LzFind.h"
|
||||
#include "Threads.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define kMtHashBlockSize (1 << 13)
|
||||
#define kMtHashNumBlocks (1 << 3)
|
||||
|
@ -77,7 +75,7 @@ typedef struct _CMatchFinderMt
|
|||
UInt32 matchMaxLen;
|
||||
UInt32 numHashBytes;
|
||||
UInt32 pos;
|
||||
Byte *buffer;
|
||||
const Byte *buffer;
|
||||
UInt32 cyclicBufferPos;
|
||||
UInt32 cyclicBufferSize; /* it must be historySize + 1 */
|
||||
UInt32 cutValue;
|
||||
|
@ -98,8 +96,6 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB
|
|||
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
|
||||
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* LzHash.h -- HASH functions for LZ algorithms
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
2015-04-12 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZ_HASH_H
|
||||
#define __LZ_HASH_H
|
||||
|
@ -12,43 +12,46 @@
|
|||
#define kFix4HashSize (kHash2Size + kHash3Size)
|
||||
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
|
||||
|
||||
#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
|
||||
#define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8);
|
||||
|
||||
#define HASH3_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
|
||||
|
||||
#define HASH4_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
||||
hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
temp ^= ((UInt32)cur[2] << 8); \
|
||||
h3 = temp & (kHash3Size - 1); \
|
||||
hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
|
||||
|
||||
#define HASH5_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
||||
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
|
||||
hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
|
||||
hash4Value &= (kHash4Size - 1); }
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
temp ^= ((UInt32)cur[2] << 8); \
|
||||
h3 = temp & (kHash3Size - 1); \
|
||||
temp ^= (p->crc[cur[3]] << 5); \
|
||||
h4 = temp & (kHash4Size - 1); \
|
||||
hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; }
|
||||
|
||||
/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
|
||||
#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
|
||||
/* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
|
||||
#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
|
||||
|
||||
|
||||
#define MT_HASH2_CALC \
|
||||
hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
|
||||
h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
|
||||
|
||||
#define MT_HASH3_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
|
||||
|
||||
#define MT_HASH4_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
||||
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
temp ^= ((UInt32)cur[2] << 8); \
|
||||
h3 = temp & (kHash3Size - 1); \
|
||||
h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
/* Lzma2Dec.c -- LZMA2 Decoder
|
||||
2010-12-15 : Igor Pavlov : Public domain */
|
||||
2015-11-09 : Igor Pavlov : Public domain */
|
||||
|
||||
/* #define SHOW_DEBUG_INFO */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#ifdef SHOW_DEBUG_INFO
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
@ -97,12 +99,12 @@ void Lzma2Dec_Init(CLzma2Dec *p)
|
|||
|
||||
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||
{
|
||||
switch(p->state)
|
||||
switch (p->state)
|
||||
{
|
||||
case LZMA2_STATE_CONTROL:
|
||||
p->control = b;
|
||||
PRF(printf("\n %4X ", p->decoder.dicPos));
|
||||
PRF(printf(" %2X", b));
|
||||
PRF(printf("\n %4X ", (unsigned)p->decoder.dicPos));
|
||||
PRF(printf(" %2X", (unsigned)b));
|
||||
if (p->control == 0)
|
||||
return LZMA2_STATE_FINISHED;
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
|
@ -122,7 +124,7 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
|||
case LZMA2_STATE_UNPACK1:
|
||||
p->unpackSize |= (UInt32)b;
|
||||
p->unpackSize++;
|
||||
PRF(printf(" %8d", p->unpackSize));
|
||||
PRF(printf(" %8u", (unsigned)p->unpackSize));
|
||||
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
||||
|
||||
case LZMA2_STATE_PACK0:
|
||||
|
@ -132,13 +134,13 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
|||
case LZMA2_STATE_PACK1:
|
||||
p->packSize |= (UInt32)b;
|
||||
p->packSize++;
|
||||
PRF(printf(" %8d", p->packSize));
|
||||
PRF(printf(" %8u", (unsigned)p->packSize));
|
||||
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
|
||||
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
|
||||
|
||||
case LZMA2_STATE_PROP:
|
||||
{
|
||||
int lc, lp;
|
||||
unsigned lc, lp;
|
||||
if (b >= (9 * 5 * 5))
|
||||
return LZMA2_STATE_ERROR;
|
||||
lc = b % 9;
|
||||
|
@ -177,13 +179,16 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
|||
while (p->state != LZMA2_STATE_FINISHED)
|
||||
{
|
||||
SizeT dicPos = p->decoder.dicPos;
|
||||
|
||||
if (p->state == LZMA2_STATE_ERROR)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
|
||||
{
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||
{
|
||||
if (*srcLen == inSize)
|
||||
|
@ -193,8 +198,15 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
|||
}
|
||||
(*srcLen)++;
|
||||
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||
|
||||
if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
|
||||
{
|
||||
p->state = LZMA2_STATE_ERROR;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
SizeT destSizeCur = dicLimit - dicPos;
|
||||
SizeT srcSizeCur = inSize - *srcLen;
|
||||
|
@ -220,7 +232,10 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
|||
if (initDic)
|
||||
p->needInitProp = p->needInitState = True;
|
||||
else if (p->needInitDic)
|
||||
{
|
||||
p->state = LZMA2_STATE_ERROR;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
p->needInitDic = False;
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
|
||||
}
|
||||
|
@ -229,7 +244,10 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
|||
srcSizeCur = destSizeCur;
|
||||
|
||||
if (srcSizeCur == 0)
|
||||
{
|
||||
p->state = LZMA2_STATE_ERROR;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
|
||||
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
|
||||
|
||||
|
@ -245,17 +263,21 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
|||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
int mode = LZMA2_GET_LZMA_MODE(p);
|
||||
unsigned mode = LZMA2_GET_LZMA_MODE(p);
|
||||
Bool initDic = (mode == 3);
|
||||
Bool initState = (mode > 0);
|
||||
Bool initState = (mode != 0);
|
||||
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
|
||||
{
|
||||
p->state = LZMA2_STATE_ERROR;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
|
||||
p->needInitDic = False;
|
||||
p->needInitState = False;
|
||||
p->state = LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
|
||||
if (srcSizeCur > p->packSize)
|
||||
srcSizeCur = (SizeT)p->packSize;
|
||||
|
||||
|
@ -274,16 +296,22 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
|||
|
||||
if (srcSizeCur == 0 && outSizeProcessed == 0)
|
||||
{
|
||||
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
|
||||
p->unpackSize != 0 || p->packSize != 0)
|
||||
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
|| p->unpackSize != 0
|
||||
|| p->packSize != 0)
|
||||
{
|
||||
p->state = LZMA2_STATE_ERROR;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
}
|
||||
|
||||
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
/* Lzma2Dec.h -- LZMA2 Decoder
|
||||
2009-05-03 : Igor Pavlov : Public domain */
|
||||
2015-05-13 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA2_DEC_H
|
||||
#define __LZMA2_DEC_H
|
||||
|
||||
#include "LzmaDec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* ---------- State Interface ---------- */
|
||||
|
||||
|
@ -17,7 +15,7 @@ typedef struct
|
|||
CLzmaDec decoder;
|
||||
UInt32 packSize;
|
||||
UInt32 unpackSize;
|
||||
int state;
|
||||
unsigned state;
|
||||
Byte control;
|
||||
Bool needInitDic;
|
||||
Bool needInitState;
|
||||
|
@ -77,8 +75,6 @@ Returns:
|
|||
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
229
lzma/C/LzmaDec.c
229
lzma/C/LzmaDec.c
|
@ -1,5 +1,7 @@
|
|||
/* LzmaDec.c -- LZMA Decoder
|
||||
2010-12-15 : Igor Pavlov : Public domain */
|
||||
2015-06-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "LzmaDec.h"
|
||||
|
||||
|
@ -44,6 +46,13 @@
|
|||
i -= 0x40; }
|
||||
#endif
|
||||
|
||||
#define NORMAL_LITER_DEC GET_BIT(prob + symbol, symbol)
|
||||
#define MATCHED_LITER_DEC \
|
||||
matchByte <<= 1; \
|
||||
bit = (matchByte & offs); \
|
||||
probLit = prob + offs + bit + symbol; \
|
||||
GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
|
||||
|
||||
#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
|
||||
|
||||
#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
|
||||
|
@ -105,14 +114,14 @@
|
|||
#define Literal (RepLenCoder + kNumLenProbs)
|
||||
|
||||
#define LZMA_BASE_SIZE 1846
|
||||
#define LZMA_LIT_SIZE 768
|
||||
|
||||
#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
|
||||
#define LZMA_LIT_SIZE 0x300
|
||||
|
||||
#if Literal != LZMA_BASE_SIZE
|
||||
StopCompilingDueBUG
|
||||
#endif
|
||||
|
||||
#define LzmaProps_GetNumProbs(p) (Literal + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
|
||||
|
||||
#define LZMA_DIC_MIN (1 << 12)
|
||||
|
||||
/* First LZMA-symbol is always decoded.
|
||||
|
@ -124,8 +133,8 @@ Out:
|
|||
p->remainLen:
|
||||
< kMatchSpecLenStart : normal remain
|
||||
= kMatchSpecLenStart : finished
|
||||
= kMatchSpecLenStart + 1 : Flush marker
|
||||
= kMatchSpecLenStart + 2 : State Init Marker
|
||||
= kMatchSpecLenStart + 1 : Flush marker (unused now)
|
||||
= kMatchSpecLenStart + 2 : State Init Marker (unused now)
|
||||
*/
|
||||
|
||||
static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
|
||||
|
@ -163,38 +172,62 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
|||
unsigned symbol;
|
||||
UPDATE_0(prob);
|
||||
prob = probs + Literal;
|
||||
if (checkDicSize != 0 || processedPos != 0)
|
||||
prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
|
||||
(dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
|
||||
if (processedPos != 0 || checkDicSize != 0)
|
||||
prob += ((UInt32)LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
|
||||
(dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
|
||||
processedPos++;
|
||||
|
||||
if (state < kNumLitStates)
|
||||
{
|
||||
state -= (state < 4) ? state : 3;
|
||||
symbol = 1;
|
||||
do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
|
||||
#ifdef _LZMA_SIZE_OPT
|
||||
do { NORMAL_LITER_DEC } while (symbol < 0x100);
|
||||
#else
|
||||
NORMAL_LITER_DEC
|
||||
NORMAL_LITER_DEC
|
||||
NORMAL_LITER_DEC
|
||||
NORMAL_LITER_DEC
|
||||
NORMAL_LITER_DEC
|
||||
NORMAL_LITER_DEC
|
||||
NORMAL_LITER_DEC
|
||||
NORMAL_LITER_DEC
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
|
||||
unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
|
||||
unsigned offs = 0x100;
|
||||
state -= (state < 10) ? 3 : 6;
|
||||
symbol = 1;
|
||||
#ifdef _LZMA_SIZE_OPT
|
||||
do
|
||||
{
|
||||
unsigned bit;
|
||||
CLzmaProb *probLit;
|
||||
matchByte <<= 1;
|
||||
bit = (matchByte & offs);
|
||||
probLit = prob + offs + bit + symbol;
|
||||
GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
|
||||
MATCHED_LITER_DEC
|
||||
}
|
||||
while (symbol < 0x100);
|
||||
#else
|
||||
{
|
||||
unsigned bit;
|
||||
CLzmaProb *probLit;
|
||||
MATCHED_LITER_DEC
|
||||
MATCHED_LITER_DEC
|
||||
MATCHED_LITER_DEC
|
||||
MATCHED_LITER_DEC
|
||||
MATCHED_LITER_DEC
|
||||
MATCHED_LITER_DEC
|
||||
MATCHED_LITER_DEC
|
||||
MATCHED_LITER_DEC
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
dic[dicPos++] = (Byte)symbol;
|
||||
processedPos++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
UPDATE_1(prob);
|
||||
prob = probs + IsRep + state;
|
||||
|
@ -217,7 +250,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
|||
IF_BIT_0(prob)
|
||||
{
|
||||
UPDATE_0(prob);
|
||||
dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
|
||||
dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
|
||||
dicPos++;
|
||||
processedPos++;
|
||||
state = state < kNumLitStates ? 9 : 11;
|
||||
|
@ -258,6 +291,8 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
|||
state = state < kNumLitStates ? 8 : 11;
|
||||
prob = probs + RepLenCoder;
|
||||
}
|
||||
|
||||
#ifdef _LZMA_SIZE_OPT
|
||||
{
|
||||
unsigned limit, offset;
|
||||
CLzmaProb *probLen = prob + LenChoice;
|
||||
|
@ -290,6 +325,42 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
|||
TREE_DECODE(probLen, limit, len);
|
||||
len += offset;
|
||||
}
|
||||
#else
|
||||
{
|
||||
CLzmaProb *probLen = prob + LenChoice;
|
||||
IF_BIT_0(probLen)
|
||||
{
|
||||
UPDATE_0(probLen);
|
||||
probLen = prob + LenLow + (posState << kLenNumLowBits);
|
||||
len = 1;
|
||||
TREE_GET_BIT(probLen, len);
|
||||
TREE_GET_BIT(probLen, len);
|
||||
TREE_GET_BIT(probLen, len);
|
||||
len -= 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1(probLen);
|
||||
probLen = prob + LenChoice2;
|
||||
IF_BIT_0(probLen)
|
||||
{
|
||||
UPDATE_0(probLen);
|
||||
probLen = prob + LenMid + (posState << kLenNumMidBits);
|
||||
len = 1;
|
||||
TREE_GET_BIT(probLen, len);
|
||||
TREE_GET_BIT(probLen, len);
|
||||
TREE_GET_BIT(probLen, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1(probLen);
|
||||
probLen = prob + LenHigh;
|
||||
TREE_DECODE(probLen, (1 << kLenNumHighBits), len);
|
||||
len += kLenNumLowSymbols + kLenNumMidSymbols;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (state >= kNumStates)
|
||||
{
|
||||
|
@ -300,7 +371,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
|||
if (distance >= kStartPosModelIndex)
|
||||
{
|
||||
unsigned posSlot = (unsigned)distance;
|
||||
int numDirectBits = (int)(((distance >> 1) - 1));
|
||||
unsigned numDirectBits = (unsigned)(((distance >> 1) - 1));
|
||||
distance = (2 | (distance & 1));
|
||||
if (posSlot < kEndPosModelIndex)
|
||||
{
|
||||
|
@ -359,6 +430,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
rep3 = rep2;
|
||||
rep2 = rep1;
|
||||
rep1 = rep0;
|
||||
|
@ -366,26 +438,39 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
|||
if (checkDicSize == 0)
|
||||
{
|
||||
if (distance >= processedPos)
|
||||
{
|
||||
p->dicPos = dicPos;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
else if (distance >= checkDicSize)
|
||||
{
|
||||
p->dicPos = dicPos;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
|
||||
}
|
||||
|
||||
len += kMatchMinLen;
|
||||
|
||||
if (limit == dicPos)
|
||||
return SZ_ERROR_DATA;
|
||||
{
|
||||
SizeT rem = limit - dicPos;
|
||||
unsigned curLen = ((rem < len) ? (unsigned)rem : len);
|
||||
SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
|
||||
SizeT rem;
|
||||
unsigned curLen;
|
||||
SizeT pos;
|
||||
|
||||
if ((rem = limit - dicPos) == 0)
|
||||
{
|
||||
p->dicPos = dicPos;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
|
||||
curLen = ((rem < len) ? (unsigned)rem : len);
|
||||
pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
|
||||
|
||||
processedPos += curLen;
|
||||
|
||||
len -= curLen;
|
||||
if (pos + curLen <= dicBufSize)
|
||||
if (curLen <= dicBufSize - pos)
|
||||
{
|
||||
Byte *dest = dic + dicPos;
|
||||
ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
|
||||
|
@ -409,7 +494,9 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
|||
}
|
||||
}
|
||||
while (dicPos < limit && buf < bufLimit);
|
||||
|
||||
NORMALIZE;
|
||||
|
||||
p->buf = buf;
|
||||
p->range = range;
|
||||
p->code = code;
|
||||
|
@ -433,9 +520,10 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
|
|||
SizeT dicPos = p->dicPos;
|
||||
SizeT dicBufSize = p->dicBufSize;
|
||||
unsigned len = p->remainLen;
|
||||
UInt32 rep0 = p->reps[0];
|
||||
if (limit - dicPos < len)
|
||||
len = (unsigned)(limit - dicPos);
|
||||
SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */
|
||||
SizeT rem = limit - dicPos;
|
||||
if (rem < len)
|
||||
len = (unsigned)(rem);
|
||||
|
||||
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
|
||||
p->checkDicSize = p->prop.dicSize;
|
||||
|
@ -445,7 +533,7 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
|
|||
while (len != 0)
|
||||
{
|
||||
len--;
|
||||
dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
|
||||
dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
|
||||
dicPos++;
|
||||
}
|
||||
p->dicPos = dicPos;
|
||||
|
@ -463,17 +551,19 @@ static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte
|
|||
if (limit - p->dicPos > rem)
|
||||
limit2 = p->dicPos + rem;
|
||||
}
|
||||
|
||||
RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
|
||||
if (p->processedPos >= p->prop.dicSize)
|
||||
|
||||
if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)
|
||||
p->checkDicSize = p->prop.dicSize;
|
||||
|
||||
LzmaDec_WriteRem(p, limit);
|
||||
}
|
||||
while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
|
||||
|
||||
if (p->remainLen > kMatchSpecLenStart)
|
||||
{
|
||||
p->remainLen = kMatchSpecLenStart;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -490,12 +580,12 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
|||
UInt32 range = p->range;
|
||||
UInt32 code = p->code;
|
||||
const Byte *bufLimit = buf + inSize;
|
||||
CLzmaProb *probs = p->probs;
|
||||
const CLzmaProb *probs = p->probs;
|
||||
unsigned state = p->state;
|
||||
ELzmaDummy res;
|
||||
|
||||
{
|
||||
CLzmaProb *prob;
|
||||
const CLzmaProb *prob;
|
||||
UInt32 bound;
|
||||
unsigned ttt;
|
||||
unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
|
||||
|
@ -509,9 +599,9 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
|||
|
||||
prob = probs + Literal;
|
||||
if (p->checkDicSize != 0 || p->processedPos != 0)
|
||||
prob += (LZMA_LIT_SIZE *
|
||||
((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
|
||||
(p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
|
||||
prob += ((UInt32)LZMA_LIT_SIZE *
|
||||
((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
|
||||
(p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
|
||||
|
||||
if (state < kNumLitStates)
|
||||
{
|
||||
|
@ -521,13 +611,13 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
|||
else
|
||||
{
|
||||
unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
|
||||
((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
|
||||
(p->dicPos < p->reps[0] ? p->dicBufSize : 0)];
|
||||
unsigned offs = 0x100;
|
||||
unsigned symbol = 1;
|
||||
do
|
||||
{
|
||||
unsigned bit;
|
||||
CLzmaProb *probLit;
|
||||
const CLzmaProb *probLit;
|
||||
matchByte <<= 1;
|
||||
bit = (matchByte & offs);
|
||||
probLit = prob + offs + bit + symbol;
|
||||
|
@ -597,7 +687,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
|||
}
|
||||
{
|
||||
unsigned limit, offset;
|
||||
CLzmaProb *probLen = prob + LenChoice;
|
||||
const CLzmaProb *probLen = prob + LenChoice;
|
||||
IF_BIT_0_CHECK(probLen)
|
||||
{
|
||||
UPDATE_0_CHECK;
|
||||
|
@ -637,7 +727,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
|||
TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
|
||||
if (posSlot >= kStartPosModelIndex)
|
||||
{
|
||||
int numDirectBits = ((posSlot >> 1) - 1);
|
||||
unsigned numDirectBits = ((posSlot >> 1) - 1);
|
||||
|
||||
/* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
|
||||
|
||||
|
@ -676,13 +766,6 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
|||
}
|
||||
|
||||
|
||||
static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
|
||||
{
|
||||
p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
|
||||
p->range = 0xFFFFFFFF;
|
||||
p->needFlush = 0;
|
||||
}
|
||||
|
||||
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
|
||||
{
|
||||
p->needFlush = 1;
|
||||
|
@ -707,8 +790,8 @@ void LzmaDec_Init(CLzmaDec *p)
|
|||
|
||||
static void LzmaDec_InitStateReal(CLzmaDec *p)
|
||||
{
|
||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
|
||||
UInt32 i;
|
||||
SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);
|
||||
SizeT i;
|
||||
CLzmaProb *probs = p->probs;
|
||||
for (i = 0; i < numProbs; i++)
|
||||
probs[i] = kBitModelTotal >> 1;
|
||||
|
@ -730,7 +813,7 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
|
|||
{
|
||||
int checkEndMarkNow;
|
||||
|
||||
if (p->needFlush != 0)
|
||||
if (p->needFlush)
|
||||
{
|
||||
for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
|
||||
p->tempBuf[p->tempBufSize++] = *src++;
|
||||
|
@ -741,8 +824,13 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
|
|||
}
|
||||
if (p->tempBuf[0] != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
LzmaDec_InitRc(p, p->tempBuf);
|
||||
p->code =
|
||||
((UInt32)p->tempBuf[1] << 24)
|
||||
| ((UInt32)p->tempBuf[2] << 16)
|
||||
| ((UInt32)p->tempBuf[3] << 8)
|
||||
| ((UInt32)p->tempBuf[4]);
|
||||
p->range = 0xFFFFFFFF;
|
||||
p->needFlush = 0;
|
||||
p->tempBufSize = 0;
|
||||
}
|
||||
|
||||
|
@ -826,7 +914,16 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
|
|||
p->buf = p->tempBuf;
|
||||
if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
|
||||
|
||||
{
|
||||
unsigned kkk = (unsigned)(p->buf - p->tempBuf);
|
||||
if (rem < kkk)
|
||||
return SZ_ERROR_FAIL; /* some internal error */
|
||||
rem -= kkk;
|
||||
if (lookAhead < rem)
|
||||
return SZ_ERROR_FAIL; /* some internal error */
|
||||
lookAhead -= rem;
|
||||
}
|
||||
(*srcLen) += lookAhead;
|
||||
src += lookAhead;
|
||||
inSize -= lookAhead;
|
||||
|
@ -881,13 +978,13 @@ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *sr
|
|||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->probs);
|
||||
p->probs = 0;
|
||||
p->probs = NULL;
|
||||
}
|
||||
|
||||
static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->dic);
|
||||
p->dic = 0;
|
||||
p->dic = NULL;
|
||||
}
|
||||
|
||||
void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
|
||||
|
@ -925,12 +1022,12 @@ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
|
|||
static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
|
||||
{
|
||||
UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
|
||||
if (p->probs == 0 || numProbs != p->numProbs)
|
||||
if (!p->probs || numProbs != p->numProbs)
|
||||
{
|
||||
LzmaDec_FreeProbs(p, alloc);
|
||||
p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
|
||||
p->numProbs = numProbs;
|
||||
if (p->probs == 0)
|
||||
if (!p->probs)
|
||||
return SZ_ERROR_MEM;
|
||||
}
|
||||
return SZ_OK;
|
||||
|
@ -951,12 +1048,22 @@ SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAll
|
|||
SizeT dicBufSize;
|
||||
RINOK(LzmaProps_Decode(&propNew, props, propsSize));
|
||||
RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
|
||||
dicBufSize = propNew.dicSize;
|
||||
if (p->dic == 0 || dicBufSize != p->dicBufSize)
|
||||
|
||||
{
|
||||
UInt32 dictSize = propNew.dicSize;
|
||||
SizeT mask = ((UInt32)1 << 12) - 1;
|
||||
if (dictSize >= ((UInt32)1 << 30)) mask = ((UInt32)1 << 22) - 1;
|
||||
else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1;;
|
||||
dicBufSize = ((SizeT)dictSize + mask) & ~mask;
|
||||
if (dicBufSize < dictSize)
|
||||
dicBufSize = dictSize;
|
||||
}
|
||||
|
||||
if (!p->dic || dicBufSize != p->dicBufSize)
|
||||
{
|
||||
LzmaDec_FreeDict(p, alloc);
|
||||
p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
|
||||
if (p->dic == 0)
|
||||
if (!p->dic)
|
||||
{
|
||||
LzmaDec_FreeProbs(p, alloc);
|
||||
return SZ_ERROR_MEM;
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
/* LzmaDec.h -- LZMA Decoder
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA_DEC_H
|
||||
#define __LZMA_DEC_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* #define _LZMA_PROB32 */
|
||||
/* _LZMA_PROB32 can increase the speed on some CPUs,
|
||||
|
@ -224,8 +222,6 @@ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
|||
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||
ELzmaStatus *status, ISzAlloc *alloc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
344
lzma/C/LzmaEnc.c
344
lzma/C/LzmaEnc.c
|
@ -1,5 +1,7 @@
|
|||
/* LzmaEnc.c -- LZMA Encoder
|
||||
2011-01-27 : Igor Pavlov : Public domain */
|
||||
2015-11-08 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -18,9 +20,12 @@
|
|||
#endif
|
||||
|
||||
#ifdef SHOW_STAT
|
||||
static int ttt = 0;
|
||||
static unsigned g_STAT_OFFSET = 0;
|
||||
#endif
|
||||
|
||||
#define kMaxHistorySize ((UInt32)3 << 29)
|
||||
/* #define kMaxHistorySize ((UInt32)7 << 29) */
|
||||
|
||||
#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
|
||||
|
||||
#define kBlockSize (9 << 10)
|
||||
|
@ -46,7 +51,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p)
|
|||
{
|
||||
p->level = 5;
|
||||
p->dictSize = p->mc = 0;
|
||||
p->reduceSize = (UInt32)(Int32)-1;
|
||||
p->reduceSize = (UInt64)(Int64)-1;
|
||||
p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
|
||||
p->writeEndMark = 0;
|
||||
}
|
||||
|
@ -56,24 +61,28 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
|
|||
int level = p->level;
|
||||
if (level < 0) level = 5;
|
||||
p->level = level;
|
||||
|
||||
if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
|
||||
if (p->dictSize > p->reduceSize)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 15; i <= 30; i++)
|
||||
for (i = 11; i <= 30; i++)
|
||||
{
|
||||
if (p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }
|
||||
if (p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }
|
||||
if ((UInt32)p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }
|
||||
if ((UInt32)p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }
|
||||
}
|
||||
}
|
||||
|
||||
if (p->lc < 0) p->lc = 3;
|
||||
if (p->lp < 0) p->lp = 0;
|
||||
if (p->pb < 0) p->pb = 2;
|
||||
|
||||
if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
|
||||
if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
|
||||
if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
|
||||
if (p->numHashBytes < 0) p->numHashBytes = 4;
|
||||
if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
|
||||
if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
|
||||
|
||||
if (p->numThreads < 0)
|
||||
p->numThreads =
|
||||
#ifndef _7ZIP_ST
|
||||
|
@ -90,17 +99,18 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
|
|||
return props.dictSize;
|
||||
}
|
||||
|
||||
#if (_MSC_VER >= 1400)
|
||||
/* BSR code is fast for some new CPUs */
|
||||
/* #define LZMA_LOG_BSR */
|
||||
/* Define it for Intel's CPU */
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LZMA_LOG_BSR
|
||||
|
||||
#define kDicLogSizeMaxCompress 30
|
||||
#define kDicLogSizeMaxCompress 32
|
||||
|
||||
#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
|
||||
|
||||
UInt32 GetPosSlot1(UInt32 pos)
|
||||
static UInt32 GetPosSlot1(UInt32 pos)
|
||||
{
|
||||
UInt32 res;
|
||||
BSR2_RET(pos, res);
|
||||
|
@ -111,27 +121,44 @@ UInt32 GetPosSlot1(UInt32 pos)
|
|||
|
||||
#else
|
||||
|
||||
#define kNumLogBits (9 + (int)sizeof(size_t) / 2)
|
||||
#define kNumLogBits (9 + sizeof(size_t) / 2)
|
||||
/* #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) */
|
||||
|
||||
#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
|
||||
|
||||
void LzmaEnc_FastPosInit(Byte *g_FastPos)
|
||||
static void LzmaEnc_FastPosInit(Byte *g_FastPos)
|
||||
{
|
||||
int c = 2, slotFast;
|
||||
unsigned slot;
|
||||
g_FastPos[0] = 0;
|
||||
g_FastPos[1] = 1;
|
||||
g_FastPos += 2;
|
||||
|
||||
for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
|
||||
for (slot = 2; slot < kNumLogBits * 2; slot++)
|
||||
{
|
||||
UInt32 k = (1 << ((slotFast >> 1) - 1));
|
||||
UInt32 j;
|
||||
for (j = 0; j < k; j++, c++)
|
||||
g_FastPos[c] = (Byte)slotFast;
|
||||
size_t k = ((size_t)1 << ((slot >> 1) - 1));
|
||||
size_t j;
|
||||
for (j = 0; j < k; j++)
|
||||
g_FastPos[j] = (Byte)slot;
|
||||
g_FastPos += k;
|
||||
}
|
||||
}
|
||||
|
||||
/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */
|
||||
/*
|
||||
#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
|
||||
(0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
|
||||
res = p->g_FastPos[pos >> i] + (i * 2); }
|
||||
*/
|
||||
|
||||
/*
|
||||
#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
|
||||
(0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \
|
||||
res = p->g_FastPos[pos >> i] + (i * 2); }
|
||||
*/
|
||||
|
||||
#define BSR2_RET(pos, res) { UInt32 i = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \
|
||||
res = p->g_FastPos[pos >> i] + (i * 2); }
|
||||
|
||||
/*
|
||||
#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
|
||||
p->g_FastPos[pos >> 6] + 12 : \
|
||||
|
@ -211,6 +238,7 @@ typedef struct
|
|||
|
||||
#define kNumStates 12
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzmaProb choice;
|
||||
|
@ -220,14 +248,16 @@ typedef struct
|
|||
CLzmaProb high[kLenNumHighSymbols];
|
||||
} CLenEnc;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLenEnc p;
|
||||
UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
|
||||
UInt32 tableSize;
|
||||
UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
|
||||
UInt32 counters[LZMA_NUM_PB_STATES_MAX];
|
||||
} CLenPriceEnc;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 range;
|
||||
|
@ -242,10 +272,14 @@ typedef struct
|
|||
SRes res;
|
||||
} CRangeEnc;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzmaProb *litProbs;
|
||||
|
||||
UInt32 state;
|
||||
UInt32 reps[LZMA_NUM_REPS];
|
||||
|
||||
CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
|
||||
CLzmaProb isRep[kNumStates];
|
||||
CLzmaProb isRepG0[kNumStates];
|
||||
|
@ -259,15 +293,49 @@ typedef struct
|
|||
|
||||
CLenPriceEnc lenEnc;
|
||||
CLenPriceEnc repLenEnc;
|
||||
|
||||
UInt32 reps[LZMA_NUM_REPS];
|
||||
UInt32 state;
|
||||
} CSaveState;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IMatchFinder matchFinder;
|
||||
void *matchFinderObj;
|
||||
IMatchFinder matchFinder;
|
||||
|
||||
UInt32 optimumEndIndex;
|
||||
UInt32 optimumCurrentIndex;
|
||||
|
||||
UInt32 longestMatchLength;
|
||||
UInt32 numPairs;
|
||||
UInt32 numAvail;
|
||||
|
||||
UInt32 numFastBytes;
|
||||
UInt32 additionalOffset;
|
||||
UInt32 reps[LZMA_NUM_REPS];
|
||||
UInt32 state;
|
||||
|
||||
unsigned lc, lp, pb;
|
||||
unsigned lpMask, pbMask;
|
||||
unsigned lclp;
|
||||
|
||||
CLzmaProb *litProbs;
|
||||
|
||||
Bool fastMode;
|
||||
Bool writeEndMark;
|
||||
Bool finished;
|
||||
Bool multiThread;
|
||||
Bool needInit;
|
||||
|
||||
UInt64 nowPos64;
|
||||
|
||||
UInt32 matchPriceCount;
|
||||
UInt32 alignPriceCount;
|
||||
|
||||
UInt32 distTableSize;
|
||||
|
||||
UInt32 dictSize;
|
||||
SRes result;
|
||||
|
||||
CRangeEnc rc;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
Bool mtMode;
|
||||
|
@ -280,12 +348,6 @@ typedef struct
|
|||
Byte pad[128];
|
||||
#endif
|
||||
|
||||
UInt32 optimumEndIndex;
|
||||
UInt32 optimumCurrentIndex;
|
||||
|
||||
UInt32 longestMatchLength;
|
||||
UInt32 numPairs;
|
||||
UInt32 numAvail;
|
||||
COptimal opt[kNumOpts];
|
||||
|
||||
#ifndef LZMA_LOG_BSR
|
||||
|
@ -294,22 +356,10 @@ typedef struct
|
|||
|
||||
UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
|
||||
UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
|
||||
UInt32 numFastBytes;
|
||||
UInt32 additionalOffset;
|
||||
UInt32 reps[LZMA_NUM_REPS];
|
||||
UInt32 state;
|
||||
|
||||
UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
|
||||
UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
|
||||
UInt32 alignPrices[kAlignTableSize];
|
||||
UInt32 alignPriceCount;
|
||||
|
||||
UInt32 distTableSize;
|
||||
|
||||
unsigned lc, lp, pb;
|
||||
unsigned lpMask, pbMask;
|
||||
|
||||
CLzmaProb *litProbs;
|
||||
|
||||
CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
|
||||
CLzmaProb isRep[kNumStates];
|
||||
|
@ -325,26 +375,14 @@ typedef struct
|
|||
CLenPriceEnc lenEnc;
|
||||
CLenPriceEnc repLenEnc;
|
||||
|
||||
unsigned lclp;
|
||||
|
||||
Bool fastMode;
|
||||
|
||||
CRangeEnc rc;
|
||||
|
||||
Bool writeEndMark;
|
||||
UInt64 nowPos64;
|
||||
UInt32 matchPriceCount;
|
||||
Bool finished;
|
||||
Bool multiThread;
|
||||
|
||||
SRes result;
|
||||
UInt32 dictSize;
|
||||
|
||||
int needInit;
|
||||
|
||||
CSaveState saveState;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
Byte pad2[128];
|
||||
#endif
|
||||
} CLzmaEnc;
|
||||
|
||||
|
||||
void LzmaEnc_SaveState(CLzmaEncHandle pp)
|
||||
{
|
||||
CLzmaEnc *p = (CLzmaEnc *)pp;
|
||||
|
@ -368,7 +406,7 @@ void LzmaEnc_SaveState(CLzmaEncHandle pp)
|
|||
memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
|
||||
memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
|
||||
memcpy(dest->reps, p->reps, sizeof(p->reps));
|
||||
memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
|
||||
memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb));
|
||||
}
|
||||
|
||||
void LzmaEnc_RestoreState(CLzmaEncHandle pp)
|
||||
|
@ -394,7 +432,7 @@ void LzmaEnc_RestoreState(CLzmaEncHandle pp)
|
|||
memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
|
||||
memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
|
||||
memcpy(dest->reps, p->reps, sizeof(p->reps));
|
||||
memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));
|
||||
memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb));
|
||||
}
|
||||
|
||||
SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
|
||||
|
@ -403,9 +441,13 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
|
|||
CLzmaEncProps props = *props2;
|
||||
LzmaEncProps_Normalize(&props);
|
||||
|
||||
if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||
|
||||
props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30))
|
||||
if (props.lc > LZMA_LC_MAX
|
||||
|| props.lp > LZMA_LP_MAX
|
||||
|| props.pb > LZMA_PB_MAX
|
||||
|| props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress)
|
||||
|| props.dictSize > kMaxHistorySize)
|
||||
return SZ_ERROR_PARAM;
|
||||
|
||||
p->dictSize = props.dictSize;
|
||||
{
|
||||
unsigned fb = props.fb;
|
||||
|
@ -419,7 +461,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
|
|||
p->lp = props.lp;
|
||||
p->pb = props.pb;
|
||||
p->fastMode = (props.algo == 0);
|
||||
p->matchFinderBase.btMode = props.btMode;
|
||||
p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0);
|
||||
{
|
||||
UInt32 numHashBytes = 4;
|
||||
if (props.btMode)
|
||||
|
@ -463,8 +505,8 @@ static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11,
|
|||
|
||||
static void RangeEnc_Construct(CRangeEnc *p)
|
||||
{
|
||||
p->outStream = 0;
|
||||
p->bufBase = 0;
|
||||
p->outStream = NULL;
|
||||
p->bufBase = NULL;
|
||||
}
|
||||
|
||||
#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
|
||||
|
@ -472,10 +514,10 @@ static void RangeEnc_Construct(CRangeEnc *p)
|
|||
#define RC_BUF_SIZE (1 << 16)
|
||||
static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
|
||||
{
|
||||
if (p->bufBase == 0)
|
||||
if (!p->bufBase)
|
||||
{
|
||||
p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
|
||||
if (p->bufBase == 0)
|
||||
if (!p->bufBase)
|
||||
return 0;
|
||||
p->bufLim = p->bufBase + RC_BUF_SIZE;
|
||||
}
|
||||
|
@ -516,7 +558,7 @@ static void RangeEnc_FlushStream(CRangeEnc *p)
|
|||
|
||||
static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
|
||||
{
|
||||
if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)
|
||||
if ((UInt32)p->low < (UInt32)0xFF000000 || (unsigned)(p->low >> 32) != 0)
|
||||
{
|
||||
Byte temp = p->cache;
|
||||
do
|
||||
|
@ -542,7 +584,7 @@ static void RangeEnc_FlushData(CRangeEnc *p)
|
|||
RangeEnc_ShiftLow(p);
|
||||
}
|
||||
|
||||
static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)
|
||||
static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, unsigned numBits)
|
||||
{
|
||||
do
|
||||
{
|
||||
|
@ -605,7 +647,7 @@ static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol,
|
|||
while (symbol < 0x10000);
|
||||
}
|
||||
|
||||
void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
|
||||
static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
|
||||
|
@ -641,7 +683,7 @@ void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
|
|||
#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
|
||||
#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
|
||||
|
||||
static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
|
||||
static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, const UInt32 *ProbPrices)
|
||||
{
|
||||
UInt32 price = 0;
|
||||
symbol |= 0x100;
|
||||
|
@ -654,7 +696,7 @@ static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *Pro
|
|||
return price;
|
||||
}
|
||||
|
||||
static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
|
||||
static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, const UInt32 *ProbPrices)
|
||||
{
|
||||
UInt32 price = 0;
|
||||
UInt32 offs = 0x100;
|
||||
|
@ -698,7 +740,7 @@ static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLeve
|
|||
}
|
||||
}
|
||||
|
||||
static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
|
||||
static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, const UInt32 *ProbPrices)
|
||||
{
|
||||
UInt32 price = 0;
|
||||
symbol |= (1 << numBitLevels);
|
||||
|
@ -710,7 +752,7 @@ static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 s
|
|||
return price;
|
||||
}
|
||||
|
||||
static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
|
||||
static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, const UInt32 *ProbPrices)
|
||||
{
|
||||
UInt32 price = 0;
|
||||
UInt32 m = 1;
|
||||
|
@ -761,7 +803,7 @@ static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posSt
|
|||
}
|
||||
}
|
||||
|
||||
static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
|
||||
static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, const UInt32 *ProbPrices)
|
||||
{
|
||||
UInt32 a0 = GET_PRICE_0a(p->choice);
|
||||
UInt32 a1 = GET_PRICE_1a(p->choice);
|
||||
|
@ -784,20 +826,20 @@ static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UIn
|
|||
prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
|
||||
}
|
||||
|
||||
static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
|
||||
static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, const UInt32 *ProbPrices)
|
||||
{
|
||||
LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
|
||||
p->counters[posState] = p->tableSize;
|
||||
}
|
||||
|
||||
static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
|
||||
static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, const UInt32 *ProbPrices)
|
||||
{
|
||||
UInt32 posState;
|
||||
for (posState = 0; posState < numPosStates; posState++)
|
||||
LenPriceEnc_UpdateTable(p, posState, ProbPrices);
|
||||
}
|
||||
|
||||
static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
|
||||
static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, const UInt32 *ProbPrices)
|
||||
{
|
||||
LenEnc_Encode(&p->p, rc, symbol, posState);
|
||||
if (updatePrice)
|
||||
|
@ -811,9 +853,10 @@ static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32
|
|||
static void MovePos(CLzmaEnc *p, UInt32 num)
|
||||
{
|
||||
#ifdef SHOW_STAT
|
||||
ttt += num;
|
||||
printf("\n MovePos %d", num);
|
||||
g_STAT_OFFSET += num;
|
||||
printf("\n MovePos %u", num);
|
||||
#endif
|
||||
|
||||
if (num != 0)
|
||||
{
|
||||
p->additionalOffset += num;
|
||||
|
@ -826,28 +869,32 @@ static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
|
|||
UInt32 lenRes = 0, numPairs;
|
||||
p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
|
||||
numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
|
||||
|
||||
#ifdef SHOW_STAT
|
||||
printf("\n i = %d numPairs = %d ", ttt, numPairs / 2);
|
||||
ttt++;
|
||||
printf("\n i = %u numPairs = %u ", g_STAT_OFFSET, numPairs / 2);
|
||||
g_STAT_OFFSET++;
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < numPairs; i += 2)
|
||||
printf("%2d %6d | ", p->matches[i], p->matches[i + 1]);
|
||||
printf("%2u %6u | ", p->matches[i], p->matches[i + 1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (numPairs > 0)
|
||||
{
|
||||
lenRes = p->matches[numPairs - 2];
|
||||
if (lenRes == p->numFastBytes)
|
||||
{
|
||||
const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
|
||||
UInt32 distance = p->matches[numPairs - 1] + 1;
|
||||
UInt32 numAvail = p->numAvail;
|
||||
if (numAvail > LZMA_MATCH_LEN_MAX)
|
||||
numAvail = LZMA_MATCH_LEN_MAX;
|
||||
{
|
||||
const Byte *pby2 = pby - distance;
|
||||
for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
|
||||
const Byte *pbyCur = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
|
||||
const Byte *pby = pbyCur + lenRes;
|
||||
ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[numPairs - 1];
|
||||
const Byte *pbyLim = pbyCur + numAvail;
|
||||
for (; pby != pbyLim && *pby == pby[dif]; pby++);
|
||||
lenRes = (UInt32)(pby - pbyCur);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -932,7 +979,7 @@ static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
|
|||
return p->optimumCurrentIndex;
|
||||
}
|
||||
|
||||
#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
|
||||
#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * (UInt32)0x300)
|
||||
|
||||
static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
|
||||
{
|
||||
|
@ -976,7 +1023,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
|
|||
UInt32 lenTest;
|
||||
const Byte *data2;
|
||||
reps[i] = p->reps[i];
|
||||
data2 = data - (reps[i] + 1);
|
||||
data2 = data - reps[i] - 1;
|
||||
if (data[0] != data2[0] || data[1] != data2[1])
|
||||
{
|
||||
repLens[i] = 0;
|
||||
|
@ -1120,12 +1167,12 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
|
|||
cur = 0;
|
||||
|
||||
#ifdef SHOW_STAT2
|
||||
if (position >= 0)
|
||||
/* if (position >= 0) */
|
||||
{
|
||||
unsigned i;
|
||||
printf("\n pos = %4X", position);
|
||||
for (i = cur; i <= lenEnd; i++)
|
||||
printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);
|
||||
printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1277,7 +1324,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
|
|||
/* try Literal + rep0 */
|
||||
UInt32 temp;
|
||||
UInt32 lenTest2;
|
||||
const Byte *data2 = data - (reps[0] + 1);
|
||||
const Byte *data2 = data - reps[0] - 1;
|
||||
UInt32 limit = p->numFastBytes + 1;
|
||||
if (limit > numAvailFull)
|
||||
limit = numAvailFull;
|
||||
|
@ -1320,7 +1367,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
|
|||
UInt32 lenTest;
|
||||
UInt32 lenTestTemp;
|
||||
UInt32 price;
|
||||
const Byte *data2 = data - (reps[repIndex] + 1);
|
||||
const Byte *data2 = data - reps[repIndex] - 1;
|
||||
if (data[0] != data2[0] || data[1] != data2[1])
|
||||
continue;
|
||||
for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
|
||||
|
@ -1350,13 +1397,13 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
|
|||
{
|
||||
UInt32 lenTest2 = lenTest + 1;
|
||||
UInt32 limit = lenTest2 + p->numFastBytes;
|
||||
UInt32 nextRepMatchPrice;
|
||||
if (limit > numAvailFull)
|
||||
limit = numAvailFull;
|
||||
for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
|
||||
lenTest2 -= lenTest + 1;
|
||||
if (lenTest2 >= 2)
|
||||
{
|
||||
UInt32 nextRepMatchPrice;
|
||||
UInt32 state2 = kRepNextStates[state];
|
||||
UInt32 posStateNext = (position + lenTest) & p->pbMask;
|
||||
UInt32 curAndLenCharPrice =
|
||||
|
@ -1437,16 +1484,16 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
|
|||
if (/*_maxMode && */lenTest == matches[offs])
|
||||
{
|
||||
/* Try Match + Literal + Rep0 */
|
||||
const Byte *data2 = data - (curBack + 1);
|
||||
const Byte *data2 = data - curBack - 1;
|
||||
UInt32 lenTest2 = lenTest + 1;
|
||||
UInt32 limit = lenTest2 + p->numFastBytes;
|
||||
UInt32 nextRepMatchPrice;
|
||||
if (limit > numAvailFull)
|
||||
limit = numAvailFull;
|
||||
for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
|
||||
lenTest2 -= lenTest + 1;
|
||||
if (lenTest2 >= 2)
|
||||
{
|
||||
UInt32 nextRepMatchPrice;
|
||||
UInt32 state2 = kMatchNextStates[state];
|
||||
UInt32 posStateNext = (position + lenTest) & p->pbMask;
|
||||
UInt32 curAndLenCharPrice = curAndLenPrice +
|
||||
|
@ -1520,7 +1567,7 @@ static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
|
|||
for (i = 0; i < LZMA_NUM_REPS; i++)
|
||||
{
|
||||
UInt32 len;
|
||||
const Byte *data2 = data - (p->reps[i] + 1);
|
||||
const Byte *data2 = data - p->reps[i] - 1;
|
||||
if (data[0] != data2[0] || data[1] != data2[1])
|
||||
continue;
|
||||
for (len = 2; len < numAvail && data[len] == data2[len]; len++);
|
||||
|
@ -1589,7 +1636,7 @@ static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
|
|||
for (i = 0; i < LZMA_NUM_REPS; i++)
|
||||
{
|
||||
UInt32 len, limit;
|
||||
const Byte *data2 = data - (p->reps[i] + 1);
|
||||
const Byte *data2 = data - p->reps[i] - 1;
|
||||
if (data[0] != data2[0] || data[1] != data2[1])
|
||||
continue;
|
||||
limit = mainLen - 1;
|
||||
|
@ -1685,6 +1732,7 @@ void LzmaEnc_Construct(CLzmaEnc *p)
|
|||
{
|
||||
RangeEnc_Construct(&p->rc);
|
||||
MatchFinder_Construct(&p->matchFinderBase);
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
MatchFinderMt_Construct(&p->matchFinderMt);
|
||||
p->matchFinderMt.MatchFinder = &p->matchFinderBase;
|
||||
|
@ -1701,15 +1749,15 @@ void LzmaEnc_Construct(CLzmaEnc *p)
|
|||
#endif
|
||||
|
||||
LzmaEnc_InitPriceTables(p->ProbPrices);
|
||||
p->litProbs = 0;
|
||||
p->saveState.litProbs = 0;
|
||||
p->litProbs = NULL;
|
||||
p->saveState.litProbs = NULL;
|
||||
}
|
||||
|
||||
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
|
||||
{
|
||||
void *p;
|
||||
p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
|
||||
if (p != 0)
|
||||
if (p)
|
||||
LzmaEnc_Construct((CLzmaEnc *)p);
|
||||
return p;
|
||||
}
|
||||
|
@ -1718,8 +1766,8 @@ void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
|
|||
{
|
||||
alloc->Free(alloc, p->litProbs);
|
||||
alloc->Free(alloc, p->saveState.litProbs);
|
||||
p->litProbs = 0;
|
||||
p->saveState.litProbs = 0;
|
||||
p->litProbs = NULL;
|
||||
p->saveState.litProbs = NULL;
|
||||
}
|
||||
|
||||
void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
|
||||
|
@ -1727,6 +1775,7 @@ void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
|
|||
#ifndef _7ZIP_ST
|
||||
MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
|
||||
#endif
|
||||
|
||||
MatchFinder_Free(&p->matchFinderBase, allocBig);
|
||||
LzmaEnc_FreeLits(p, alloc);
|
||||
RangeEnc_Free(&p->rc, alloc);
|
||||
|
@ -1763,7 +1812,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
|
|||
ReadMatchDistances(p, &numPairs);
|
||||
RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
|
||||
p->state = kLiteralNextStates[p->state];
|
||||
curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);
|
||||
curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);
|
||||
LitEnc_Encode(&p->rc, p->litProbs, curByte);
|
||||
p->additionalOffset--;
|
||||
nowPos32++;
|
||||
|
@ -1780,7 +1829,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
|
|||
len = GetOptimum(p, nowPos32, &pos);
|
||||
|
||||
#ifdef SHOW_STAT2
|
||||
printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos);
|
||||
printf("\n pos = %4X, len = %u pos = %u", nowPos32, len, pos);
|
||||
#endif
|
||||
|
||||
posState = nowPos32 & p->pbMask;
|
||||
|
@ -1889,7 +1938,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
|
|||
RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
|
||||
break;
|
||||
}
|
||||
else if (processed >= (1 << 15))
|
||||
else if (processed >= (1 << 17))
|
||||
{
|
||||
p->nowPos64 += nowPos32 - startPos32;
|
||||
return CheckErrors(p);
|
||||
|
@ -1905,22 +1954,21 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
|
|||
static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
|
||||
{
|
||||
UInt32 beforeSize = kNumOpts;
|
||||
Bool btMode;
|
||||
if (!RangeEnc_Alloc(&p->rc, alloc))
|
||||
return SZ_ERROR_MEM;
|
||||
btMode = (p->matchFinderBase.btMode != 0);
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
p->mtMode = (p->multiThread && !p->fastMode && btMode);
|
||||
p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0));
|
||||
#endif
|
||||
|
||||
{
|
||||
unsigned lclp = p->lc + p->lp;
|
||||
if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
|
||||
if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
|
||||
{
|
||||
LzmaEnc_FreeLits(p, alloc);
|
||||
p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
|
||||
p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
|
||||
if (p->litProbs == 0 || p->saveState.litProbs == 0)
|
||||
p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
|
||||
p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
|
||||
if (!p->litProbs || !p->saveState.litProbs)
|
||||
{
|
||||
LzmaEnc_FreeLits(p, alloc);
|
||||
return SZ_ERROR_MEM;
|
||||
|
@ -1929,7 +1977,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
|
|||
}
|
||||
}
|
||||
|
||||
p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);
|
||||
p->matchFinderBase.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);
|
||||
|
||||
if (beforeSize + p->dictSize < keepWindowSize)
|
||||
beforeSize = keepWindowSize - p->dictSize;
|
||||
|
@ -1949,6 +1997,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
|
|||
p->matchFinderObj = &p->matchFinderBase;
|
||||
MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
|
||||
}
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
|
@ -1977,9 +2026,10 @@ void LzmaEnc_Init(CLzmaEnc *p)
|
|||
}
|
||||
|
||||
{
|
||||
UInt32 num = 0x300 << (p->lp + p->lc);
|
||||
UInt32 num = (UInt32)0x300 << (p->lp + p->lc);
|
||||
CLzmaProb *probs = p->litProbs;
|
||||
for (i = 0; i < num; i++)
|
||||
p->litProbs[i] = kProbInitValue;
|
||||
probs[i] = kProbInitValue;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -2086,10 +2136,11 @@ void LzmaEnc_Finish(CLzmaEncHandle pp)
|
|||
if (p->mtMode)
|
||||
MatchFinderMt_ReleaseStream(&p->matchFinderMt);
|
||||
#else
|
||||
(void)pp;
|
||||
UNUSED_VAR(pp);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqOutStream funcTable;
|
||||
|
@ -2119,12 +2170,14 @@ UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
|
|||
return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
|
||||
}
|
||||
|
||||
|
||||
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
|
||||
{
|
||||
const CLzmaEnc *p = (CLzmaEnc *)pp;
|
||||
return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
|
||||
}
|
||||
|
||||
|
||||
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
|
||||
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
|
||||
{
|
||||
|
@ -2159,23 +2212,23 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
|
||||
{
|
||||
SRes res = SZ_OK;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
Byte allocaDummy[0x300];
|
||||
int i = 0;
|
||||
for (i = 0; i < 16; i++)
|
||||
allocaDummy[i] = (Byte)i;
|
||||
allocaDummy[0] = 0;
|
||||
allocaDummy[1] = allocaDummy[0];
|
||||
#endif
|
||||
|
||||
for (;;)
|
||||
{
|
||||
res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
|
||||
if (res != SZ_OK || p->finished != 0)
|
||||
if (res != SZ_OK || p->finished)
|
||||
break;
|
||||
if (progress != 0)
|
||||
if (progress)
|
||||
{
|
||||
res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
|
||||
if (res != SZ_OK)
|
||||
|
@ -2185,10 +2238,19 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
LzmaEnc_Finish(p);
|
||||
|
||||
/*
|
||||
if (res == S_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))
|
||||
res = SZ_ERROR_FAIL;
|
||||
}
|
||||
*/
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
|
||||
ISzAlloc *alloc, ISzAlloc *allocBig)
|
||||
{
|
||||
|
@ -2196,28 +2258,27 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i
|
|||
return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
|
||||
}
|
||||
|
||||
|
||||
SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
|
||||
{
|
||||
CLzmaEnc *p = (CLzmaEnc *)pp;
|
||||
int i;
|
||||
unsigned i;
|
||||
UInt32 dictSize = p->dictSize;
|
||||
if (*size < LZMA_PROPS_SIZE)
|
||||
return SZ_ERROR_PARAM;
|
||||
*size = LZMA_PROPS_SIZE;
|
||||
props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
|
||||
|
||||
for (i = 11; i <= 30; i++)
|
||||
if (dictSize >= ((UInt32)1 << 22))
|
||||
{
|
||||
if (dictSize <= ((UInt32)2 << i))
|
||||
{
|
||||
dictSize = (2 << i);
|
||||
break;
|
||||
}
|
||||
if (dictSize <= ((UInt32)3 << i))
|
||||
{
|
||||
dictSize = (3 << i);
|
||||
break;
|
||||
}
|
||||
UInt32 kDictMask = ((UInt32)1 << 20) - 1;
|
||||
if (dictSize < (UInt32)0xFFFFFFFF - kDictMask)
|
||||
dictSize = (dictSize + kDictMask) & ~kDictMask;
|
||||
}
|
||||
else for (i = 11; i <= 30; i++)
|
||||
{
|
||||
if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; }
|
||||
if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; }
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
|
@ -2225,6 +2286,7 @@ SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
|
|||
return SZ_OK;
|
||||
}
|
||||
|
||||
|
||||
SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
|
||||
{
|
||||
|
@ -2233,19 +2295,22 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte
|
|||
|
||||
CSeqOutStreamBuf outStream;
|
||||
|
||||
LzmaEnc_SetInputBuf(p, src, srcLen);
|
||||
|
||||
outStream.funcTable.Write = MyWrite;
|
||||
outStream.data = dest;
|
||||
outStream.rem = *destLen;
|
||||
outStream.overflow = False;
|
||||
|
||||
p->writeEndMark = writeEndMark;
|
||||
|
||||
p->rc.outStream = &outStream.funcTable;
|
||||
|
||||
res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
|
||||
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
res = LzmaEnc_Encode2(p, progress);
|
||||
if (res == SZ_OK && p->nowPos64 != srcLen)
|
||||
res = SZ_ERROR_FAIL;
|
||||
}
|
||||
|
||||
*destLen -= outStream.rem;
|
||||
if (outStream.overflow)
|
||||
|
@ -2253,13 +2318,14 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
|
||||
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
|
||||
{
|
||||
CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
|
||||
SRes res;
|
||||
if (p == 0)
|
||||
if (!p)
|
||||
return SZ_ERROR_MEM;
|
||||
|
||||
res = LzmaEnc_SetProps(p, props);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/* LzmaEnc.h -- LZMA Encoder
|
||||
2011-01-27 : Igor Pavlov : Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA_ENC_H
|
||||
#define __LZMA_ENC_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
|
@ -16,7 +16,7 @@ typedef struct _CLzmaEncProps
|
|||
UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
|
||||
(1 << 12) <= dictSize <= (1 << 30) for 64-bit version
|
||||
default = (1 << 24) */
|
||||
UInt32 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF.
|
||||
UInt64 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF.
|
||||
Encoder uses this value to reduce dictionary size */
|
||||
int lc; /* 0 <= lc <= 8, default = 3 */
|
||||
int lp; /* 0 <= lp <= 4, default = 0 */
|
||||
|
|
85
lzma/C/Ppmd.h
Normal file
85
lzma/C/Ppmd.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/* Ppmd.h -- PPMD codec common code
|
||||
2013-01-18 : Igor Pavlov : Public domain
|
||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||
|
||||
#ifndef __PPMD_H
|
||||
#define __PPMD_H
|
||||
|
||||
#include "CpuArch.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#ifdef MY_CPU_32BIT
|
||||
#define PPMD_32BIT
|
||||
#endif
|
||||
|
||||
#define PPMD_INT_BITS 7
|
||||
#define PPMD_PERIOD_BITS 7
|
||||
#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))
|
||||
|
||||
#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))
|
||||
#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)
|
||||
#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))
|
||||
#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))
|
||||
|
||||
#define PPMD_N1 4
|
||||
#define PPMD_N2 4
|
||||
#define PPMD_N3 4
|
||||
#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
|
||||
#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */
|
||||
|
||||
/* SEE-contexts for PPM-contexts with masked symbols */
|
||||
typedef struct
|
||||
{
|
||||
UInt16 Summ; /* Freq */
|
||||
Byte Shift; /* Speed of Freq change; low Shift is for fast change */
|
||||
Byte Count; /* Count to next change of Shift */
|
||||
} CPpmd_See;
|
||||
|
||||
#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
|
||||
{ (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte Symbol;
|
||||
Byte Freq;
|
||||
UInt16 SuccessorLow;
|
||||
UInt16 SuccessorHigh;
|
||||
} CPpmd_State;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
CPpmd_State *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd_State_Ref;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
void *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd_Void_Ref;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
Byte *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd_Byte_Ref;
|
||||
|
||||
#define PPMD_SetAllBitsIn256Bytes(p) \
|
||||
{ unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \
|
||||
p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }}
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
710
lzma/C/Ppmd7.c
Normal file
710
lzma/C/Ppmd7.c
Normal file
|
@ -0,0 +1,710 @@
|
|||
/* Ppmd7.c -- PPMdH codec
|
||||
2015-09-28 : Igor Pavlov : Public domain
|
||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Ppmd7.h"
|
||||
|
||||
const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
|
||||
static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
|
||||
|
||||
#define MAX_FREQ 124
|
||||
#define UNIT_SIZE 12
|
||||
|
||||
#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
|
||||
#define U2I(nu) (p->Units2Indx[(nu) - 1])
|
||||
#define I2U(indx) (p->Indx2Units[indx])
|
||||
|
||||
#ifdef PPMD_32BIT
|
||||
#define REF(ptr) (ptr)
|
||||
#else
|
||||
#define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
|
||||
#endif
|
||||
|
||||
#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
|
||||
|
||||
#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
|
||||
#define STATS(ctx) Ppmd7_GetStats(p, ctx)
|
||||
#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
|
||||
#define SUFFIX(ctx) CTX((ctx)->Suffix)
|
||||
|
||||
typedef CPpmd7_Context * CTX_PTR;
|
||||
|
||||
struct CPpmd7_Node_;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
struct CPpmd7_Node_ *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd7_Node_Ref;
|
||||
|
||||
typedef struct CPpmd7_Node_
|
||||
{
|
||||
UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */
|
||||
UInt16 NU;
|
||||
CPpmd7_Node_Ref Next; /* must be at offset >= 4 */
|
||||
CPpmd7_Node_Ref Prev;
|
||||
} CPpmd7_Node;
|
||||
|
||||
#ifdef PPMD_32BIT
|
||||
#define NODE(ptr) (ptr)
|
||||
#else
|
||||
#define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))
|
||||
#endif
|
||||
|
||||
void Ppmd7_Construct(CPpmd7 *p)
|
||||
{
|
||||
unsigned i, k, m;
|
||||
|
||||
p->Base = 0;
|
||||
|
||||
for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
|
||||
{
|
||||
unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
|
||||
do { p->Units2Indx[k++] = (Byte)i; } while (--step);
|
||||
p->Indx2Units[i] = (Byte)k;
|
||||
}
|
||||
|
||||
p->NS2BSIndx[0] = (0 << 1);
|
||||
p->NS2BSIndx[1] = (1 << 1);
|
||||
memset(p->NS2BSIndx + 2, (2 << 1), 9);
|
||||
memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
p->NS2Indx[i] = (Byte)i;
|
||||
for (m = i, k = 1; i < 256; i++)
|
||||
{
|
||||
p->NS2Indx[i] = (Byte)m;
|
||||
if (--k == 0)
|
||||
k = (++m) - 2;
|
||||
}
|
||||
|
||||
memset(p->HB2Flag, 0, 0x40);
|
||||
memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
|
||||
}
|
||||
|
||||
void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->Base);
|
||||
p->Size = 0;
|
||||
p->Base = 0;
|
||||
}
|
||||
|
||||
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
|
||||
{
|
||||
if (p->Base == 0 || p->Size != size)
|
||||
{
|
||||
Ppmd7_Free(p, alloc);
|
||||
p->AlignOffset =
|
||||
#ifdef PPMD_32BIT
|
||||
(4 - size) & 3;
|
||||
#else
|
||||
4 - (size & 3);
|
||||
#endif
|
||||
if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size
|
||||
#ifndef PPMD_32BIT
|
||||
+ UNIT_SIZE
|
||||
#endif
|
||||
)) == 0)
|
||||
return False;
|
||||
p->Size = size;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
static void InsertNode(CPpmd7 *p, void *node, unsigned indx)
|
||||
{
|
||||
*((CPpmd_Void_Ref *)node) = p->FreeList[indx];
|
||||
p->FreeList[indx] = REF(node);
|
||||
}
|
||||
|
||||
static void *RemoveNode(CPpmd7 *p, unsigned indx)
|
||||
{
|
||||
CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
|
||||
p->FreeList[indx] = *node;
|
||||
return node;
|
||||
}
|
||||
|
||||
static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
|
||||
{
|
||||
unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
|
||||
ptr = (Byte *)ptr + U2B(I2U(newIndx));
|
||||
if (I2U(i = U2I(nu)) != nu)
|
||||
{
|
||||
unsigned k = I2U(--i);
|
||||
InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
|
||||
}
|
||||
InsertNode(p, ptr, i);
|
||||
}
|
||||
|
||||
static void GlueFreeBlocks(CPpmd7 *p)
|
||||
{
|
||||
#ifdef PPMD_32BIT
|
||||
CPpmd7_Node headItem;
|
||||
CPpmd7_Node_Ref head = &headItem;
|
||||
#else
|
||||
CPpmd7_Node_Ref head = p->AlignOffset + p->Size;
|
||||
#endif
|
||||
|
||||
CPpmd7_Node_Ref n = head;
|
||||
unsigned i;
|
||||
|
||||
p->GlueCount = 255;
|
||||
|
||||
/* create doubly-linked list of free blocks */
|
||||
for (i = 0; i < PPMD_NUM_INDEXES; i++)
|
||||
{
|
||||
UInt16 nu = I2U(i);
|
||||
CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];
|
||||
p->FreeList[i] = 0;
|
||||
while (next != 0)
|
||||
{
|
||||
CPpmd7_Node *node = NODE(next);
|
||||
node->Next = n;
|
||||
n = NODE(n)->Prev = next;
|
||||
next = *(const CPpmd7_Node_Ref *)node;
|
||||
node->Stamp = 0;
|
||||
node->NU = (UInt16)nu;
|
||||
}
|
||||
}
|
||||
NODE(head)->Stamp = 1;
|
||||
NODE(head)->Next = n;
|
||||
NODE(n)->Prev = head;
|
||||
if (p->LoUnit != p->HiUnit)
|
||||
((CPpmd7_Node *)p->LoUnit)->Stamp = 1;
|
||||
|
||||
/* Glue free blocks */
|
||||
while (n != head)
|
||||
{
|
||||
CPpmd7_Node *node = NODE(n);
|
||||
UInt32 nu = (UInt32)node->NU;
|
||||
for (;;)
|
||||
{
|
||||
CPpmd7_Node *node2 = NODE(n) + nu;
|
||||
nu += node2->NU;
|
||||
if (node2->Stamp != 0 || nu >= 0x10000)
|
||||
break;
|
||||
NODE(node2->Prev)->Next = node2->Next;
|
||||
NODE(node2->Next)->Prev = node2->Prev;
|
||||
node->NU = (UInt16)nu;
|
||||
}
|
||||
n = node->Next;
|
||||
}
|
||||
|
||||
/* Fill lists of free blocks */
|
||||
for (n = NODE(head)->Next; n != head;)
|
||||
{
|
||||
CPpmd7_Node *node = NODE(n);
|
||||
unsigned nu;
|
||||
CPpmd7_Node_Ref next = node->Next;
|
||||
for (nu = node->NU; nu > 128; nu -= 128, node += 128)
|
||||
InsertNode(p, node, PPMD_NUM_INDEXES - 1);
|
||||
if (I2U(i = U2I(nu)) != nu)
|
||||
{
|
||||
unsigned k = I2U(--i);
|
||||
InsertNode(p, node + k, nu - k - 1);
|
||||
}
|
||||
InsertNode(p, node, i);
|
||||
n = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)
|
||||
{
|
||||
unsigned i;
|
||||
void *retVal;
|
||||
if (p->GlueCount == 0)
|
||||
{
|
||||
GlueFreeBlocks(p);
|
||||
if (p->FreeList[indx] != 0)
|
||||
return RemoveNode(p, indx);
|
||||
}
|
||||
i = indx;
|
||||
do
|
||||
{
|
||||
if (++i == PPMD_NUM_INDEXES)
|
||||
{
|
||||
UInt32 numBytes = U2B(I2U(indx));
|
||||
p->GlueCount--;
|
||||
return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
|
||||
}
|
||||
}
|
||||
while (p->FreeList[i] == 0);
|
||||
retVal = RemoveNode(p, i);
|
||||
SplitBlock(p, retVal, i, indx);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static void *AllocUnits(CPpmd7 *p, unsigned indx)
|
||||
{
|
||||
UInt32 numBytes;
|
||||
if (p->FreeList[indx] != 0)
|
||||
return RemoveNode(p, indx);
|
||||
numBytes = U2B(I2U(indx));
|
||||
if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
|
||||
{
|
||||
void *retVal = p->LoUnit;
|
||||
p->LoUnit += numBytes;
|
||||
return retVal;
|
||||
}
|
||||
return AllocUnitsRare(p, indx);
|
||||
}
|
||||
|
||||
#define MyMem12Cpy(dest, src, num) \
|
||||
{ UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
|
||||
do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while (--n); }
|
||||
|
||||
static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
|
||||
{
|
||||
unsigned i0 = U2I(oldNU);
|
||||
unsigned i1 = U2I(newNU);
|
||||
if (i0 == i1)
|
||||
return oldPtr;
|
||||
if (p->FreeList[i1] != 0)
|
||||
{
|
||||
void *ptr = RemoveNode(p, i1);
|
||||
MyMem12Cpy(ptr, oldPtr, newNU);
|
||||
InsertNode(p, oldPtr, i0);
|
||||
return ptr;
|
||||
}
|
||||
SplitBlock(p, oldPtr, i0, i1);
|
||||
return oldPtr;
|
||||
}
|
||||
|
||||
#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
|
||||
|
||||
static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
|
||||
{
|
||||
(p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
|
||||
(p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
|
||||
}
|
||||
|
||||
static void RestartModel(CPpmd7 *p)
|
||||
{
|
||||
unsigned i, k, m;
|
||||
|
||||
memset(p->FreeList, 0, sizeof(p->FreeList));
|
||||
p->Text = p->Base + p->AlignOffset;
|
||||
p->HiUnit = p->Text + p->Size;
|
||||
p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
|
||||
p->GlueCount = 0;
|
||||
|
||||
p->OrderFall = p->MaxOrder;
|
||||
p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
|
||||
p->PrevSuccess = 0;
|
||||
|
||||
p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
|
||||
p->MinContext->Suffix = 0;
|
||||
p->MinContext->NumStats = 256;
|
||||
p->MinContext->SummFreq = 256 + 1;
|
||||
p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
|
||||
p->LoUnit += U2B(256 / 2);
|
||||
p->MinContext->Stats = REF(p->FoundState);
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
CPpmd_State *s = &p->FoundState[i];
|
||||
s->Symbol = (Byte)i;
|
||||
s->Freq = 1;
|
||||
SetSuccessor(s, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
for (k = 0; k < 8; k++)
|
||||
{
|
||||
UInt16 *dest = p->BinSumm[i] + k;
|
||||
UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));
|
||||
for (m = 0; m < 64; m += 8)
|
||||
dest[m] = val;
|
||||
}
|
||||
|
||||
for (i = 0; i < 25; i++)
|
||||
for (k = 0; k < 16; k++)
|
||||
{
|
||||
CPpmd_See *s = &p->See[i][k];
|
||||
s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));
|
||||
s->Count = 4;
|
||||
}
|
||||
}
|
||||
|
||||
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
|
||||
{
|
||||
p->MaxOrder = maxOrder;
|
||||
RestartModel(p);
|
||||
p->DummySee.Shift = PPMD_PERIOD_BITS;
|
||||
p->DummySee.Summ = 0; /* unused */
|
||||
p->DummySee.Count = 64; /* unused */
|
||||
}
|
||||
|
||||
static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
|
||||
{
|
||||
CPpmd_State upState;
|
||||
CTX_PTR c = p->MinContext;
|
||||
CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
|
||||
CPpmd_State *ps[PPMD7_MAX_ORDER];
|
||||
unsigned numPs = 0;
|
||||
|
||||
if (!skip)
|
||||
ps[numPs++] = p->FoundState;
|
||||
|
||||
while (c->Suffix)
|
||||
{
|
||||
CPpmd_Void_Ref successor;
|
||||
CPpmd_State *s;
|
||||
c = SUFFIX(c);
|
||||
if (c->NumStats != 1)
|
||||
{
|
||||
for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
|
||||
}
|
||||
else
|
||||
s = ONE_STATE(c);
|
||||
successor = SUCCESSOR(s);
|
||||
if (successor != upBranch)
|
||||
{
|
||||
c = CTX(successor);
|
||||
if (numPs == 0)
|
||||
return c;
|
||||
break;
|
||||
}
|
||||
ps[numPs++] = s;
|
||||
}
|
||||
|
||||
upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);
|
||||
SetSuccessor(&upState, upBranch + 1);
|
||||
|
||||
if (c->NumStats == 1)
|
||||
upState.Freq = ONE_STATE(c)->Freq;
|
||||
else
|
||||
{
|
||||
UInt32 cf, s0;
|
||||
CPpmd_State *s;
|
||||
for (s = STATS(c); s->Symbol != upState.Symbol; s++);
|
||||
cf = s->Freq - 1;
|
||||
s0 = c->SummFreq - c->NumStats - cf;
|
||||
upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* Create Child */
|
||||
CTX_PTR c1; /* = AllocContext(p); */
|
||||
if (p->HiUnit != p->LoUnit)
|
||||
c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
|
||||
else if (p->FreeList[0] != 0)
|
||||
c1 = (CTX_PTR)RemoveNode(p, 0);
|
||||
else
|
||||
{
|
||||
c1 = (CTX_PTR)AllocUnitsRare(p, 0);
|
||||
if (!c1)
|
||||
return NULL;
|
||||
}
|
||||
c1->NumStats = 1;
|
||||
*ONE_STATE(c1) = upState;
|
||||
c1->Suffix = REF(c);
|
||||
SetSuccessor(ps[--numPs], REF(c1));
|
||||
c = c1;
|
||||
}
|
||||
while (numPs != 0);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
|
||||
{
|
||||
CPpmd_State tmp = *t1;
|
||||
*t1 = *t2;
|
||||
*t2 = tmp;
|
||||
}
|
||||
|
||||
static void UpdateModel(CPpmd7 *p)
|
||||
{
|
||||
CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
|
||||
CTX_PTR c;
|
||||
unsigned s0, ns;
|
||||
|
||||
if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
|
||||
{
|
||||
c = SUFFIX(p->MinContext);
|
||||
|
||||
if (c->NumStats == 1)
|
||||
{
|
||||
CPpmd_State *s = ONE_STATE(c);
|
||||
if (s->Freq < 32)
|
||||
s->Freq++;
|
||||
}
|
||||
else
|
||||
{
|
||||
CPpmd_State *s = STATS(c);
|
||||
if (s->Symbol != p->FoundState->Symbol)
|
||||
{
|
||||
do { s++; } while (s->Symbol != p->FoundState->Symbol);
|
||||
if (s[0].Freq >= s[-1].Freq)
|
||||
{
|
||||
SwapStates(&s[0], &s[-1]);
|
||||
s--;
|
||||
}
|
||||
}
|
||||
if (s->Freq < MAX_FREQ - 9)
|
||||
{
|
||||
s->Freq += 2;
|
||||
c->SummFreq += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p->OrderFall == 0)
|
||||
{
|
||||
p->MinContext = p->MaxContext = CreateSuccessors(p, True);
|
||||
if (p->MinContext == 0)
|
||||
{
|
||||
RestartModel(p);
|
||||
return;
|
||||
}
|
||||
SetSuccessor(p->FoundState, REF(p->MinContext));
|
||||
return;
|
||||
}
|
||||
|
||||
*p->Text++ = p->FoundState->Symbol;
|
||||
successor = REF(p->Text);
|
||||
if (p->Text >= p->UnitsStart)
|
||||
{
|
||||
RestartModel(p);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fSuccessor)
|
||||
{
|
||||
if (fSuccessor <= successor)
|
||||
{
|
||||
CTX_PTR cs = CreateSuccessors(p, False);
|
||||
if (cs == NULL)
|
||||
{
|
||||
RestartModel(p);
|
||||
return;
|
||||
}
|
||||
fSuccessor = REF(cs);
|
||||
}
|
||||
if (--p->OrderFall == 0)
|
||||
{
|
||||
successor = fSuccessor;
|
||||
p->Text -= (p->MaxContext != p->MinContext);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSuccessor(p->FoundState, successor);
|
||||
fSuccessor = REF(p->MinContext);
|
||||
}
|
||||
|
||||
s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);
|
||||
|
||||
for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))
|
||||
{
|
||||
unsigned ns1;
|
||||
UInt32 cf, sf;
|
||||
if ((ns1 = c->NumStats) != 1)
|
||||
{
|
||||
if ((ns1 & 1) == 0)
|
||||
{
|
||||
/* Expand for one UNIT */
|
||||
unsigned oldNU = ns1 >> 1;
|
||||
unsigned i = U2I(oldNU);
|
||||
if (i != U2I(oldNU + 1))
|
||||
{
|
||||
void *ptr = AllocUnits(p, i + 1);
|
||||
void *oldPtr;
|
||||
if (!ptr)
|
||||
{
|
||||
RestartModel(p);
|
||||
return;
|
||||
}
|
||||
oldPtr = STATS(c);
|
||||
MyMem12Cpy(ptr, oldPtr, oldNU);
|
||||
InsertNode(p, oldPtr, i);
|
||||
c->Stats = STATS_REF(ptr);
|
||||
}
|
||||
}
|
||||
c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);
|
||||
if (!s)
|
||||
{
|
||||
RestartModel(p);
|
||||
return;
|
||||
}
|
||||
*s = *ONE_STATE(c);
|
||||
c->Stats = REF(s);
|
||||
if (s->Freq < MAX_FREQ / 4 - 1)
|
||||
s->Freq <<= 1;
|
||||
else
|
||||
s->Freq = MAX_FREQ - 4;
|
||||
c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));
|
||||
}
|
||||
cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);
|
||||
sf = (UInt32)s0 + c->SummFreq;
|
||||
if (cf < 6 * sf)
|
||||
{
|
||||
cf = 1 + (cf > sf) + (cf >= 4 * sf);
|
||||
c->SummFreq += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
|
||||
c->SummFreq = (UInt16)(c->SummFreq + cf);
|
||||
}
|
||||
{
|
||||
CPpmd_State *s = STATS(c) + ns1;
|
||||
SetSuccessor(s, successor);
|
||||
s->Symbol = p->FoundState->Symbol;
|
||||
s->Freq = (Byte)cf;
|
||||
c->NumStats = (UInt16)(ns1 + 1);
|
||||
}
|
||||
}
|
||||
p->MaxContext = p->MinContext = CTX(fSuccessor);
|
||||
}
|
||||
|
||||
static void Rescale(CPpmd7 *p)
|
||||
{
|
||||
unsigned i, adder, sumFreq, escFreq;
|
||||
CPpmd_State *stats = STATS(p->MinContext);
|
||||
CPpmd_State *s = p->FoundState;
|
||||
{
|
||||
CPpmd_State tmp = *s;
|
||||
for (; s != stats; s--)
|
||||
s[0] = s[-1];
|
||||
*s = tmp;
|
||||
}
|
||||
escFreq = p->MinContext->SummFreq - s->Freq;
|
||||
s->Freq += 4;
|
||||
adder = (p->OrderFall != 0);
|
||||
s->Freq = (Byte)((s->Freq + adder) >> 1);
|
||||
sumFreq = s->Freq;
|
||||
|
||||
i = p->MinContext->NumStats - 1;
|
||||
do
|
||||
{
|
||||
escFreq -= (++s)->Freq;
|
||||
s->Freq = (Byte)((s->Freq + adder) >> 1);
|
||||
sumFreq += s->Freq;
|
||||
if (s[0].Freq > s[-1].Freq)
|
||||
{
|
||||
CPpmd_State *s1 = s;
|
||||
CPpmd_State tmp = *s1;
|
||||
do
|
||||
s1[0] = s1[-1];
|
||||
while (--s1 != stats && tmp.Freq > s1[-1].Freq);
|
||||
*s1 = tmp;
|
||||
}
|
||||
}
|
||||
while (--i);
|
||||
|
||||
if (s->Freq == 0)
|
||||
{
|
||||
unsigned numStats = p->MinContext->NumStats;
|
||||
unsigned n0, n1;
|
||||
do { i++; } while ((--s)->Freq == 0);
|
||||
escFreq += i;
|
||||
p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);
|
||||
if (p->MinContext->NumStats == 1)
|
||||
{
|
||||
CPpmd_State tmp = *stats;
|
||||
do
|
||||
{
|
||||
tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));
|
||||
escFreq >>= 1;
|
||||
}
|
||||
while (escFreq > 1);
|
||||
InsertNode(p, stats, U2I(((numStats + 1) >> 1)));
|
||||
*(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
|
||||
return;
|
||||
}
|
||||
n0 = (numStats + 1) >> 1;
|
||||
n1 = (p->MinContext->NumStats + 1) >> 1;
|
||||
if (n0 != n1)
|
||||
p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
|
||||
}
|
||||
p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
|
||||
p->FoundState = STATS(p->MinContext);
|
||||
}
|
||||
|
||||
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
|
||||
{
|
||||
CPpmd_See *see;
|
||||
unsigned nonMasked = p->MinContext->NumStats - numMasked;
|
||||
if (p->MinContext->NumStats != 256)
|
||||
{
|
||||
see = p->See[p->NS2Indx[nonMasked - 1]] +
|
||||
(nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
|
||||
2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
|
||||
4 * (numMasked > nonMasked) +
|
||||
p->HiBitsFlag;
|
||||
{
|
||||
unsigned r = (see->Summ >> see->Shift);
|
||||
see->Summ = (UInt16)(see->Summ - r);
|
||||
*escFreq = r + (r == 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
see = &p->DummySee;
|
||||
*escFreq = 1;
|
||||
}
|
||||
return see;
|
||||
}
|
||||
|
||||
static void NextContext(CPpmd7 *p)
|
||||
{
|
||||
CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
|
||||
if (p->OrderFall == 0 && (Byte *)c > p->Text)
|
||||
p->MinContext = p->MaxContext = c;
|
||||
else
|
||||
UpdateModel(p);
|
||||
}
|
||||
|
||||
void Ppmd7_Update1(CPpmd7 *p)
|
||||
{
|
||||
CPpmd_State *s = p->FoundState;
|
||||
s->Freq += 4;
|
||||
p->MinContext->SummFreq += 4;
|
||||
if (s[0].Freq > s[-1].Freq)
|
||||
{
|
||||
SwapStates(&s[0], &s[-1]);
|
||||
p->FoundState = --s;
|
||||
if (s->Freq > MAX_FREQ)
|
||||
Rescale(p);
|
||||
}
|
||||
NextContext(p);
|
||||
}
|
||||
|
||||
void Ppmd7_Update1_0(CPpmd7 *p)
|
||||
{
|
||||
p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);
|
||||
p->RunLength += p->PrevSuccess;
|
||||
p->MinContext->SummFreq += 4;
|
||||
if ((p->FoundState->Freq += 4) > MAX_FREQ)
|
||||
Rescale(p);
|
||||
NextContext(p);
|
||||
}
|
||||
|
||||
void Ppmd7_UpdateBin(CPpmd7 *p)
|
||||
{
|
||||
p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));
|
||||
p->PrevSuccess = 1;
|
||||
p->RunLength++;
|
||||
NextContext(p);
|
||||
}
|
||||
|
||||
void Ppmd7_Update2(CPpmd7 *p)
|
||||
{
|
||||
p->MinContext->SummFreq += 4;
|
||||
if ((p->FoundState->Freq += 4) > MAX_FREQ)
|
||||
Rescale(p);
|
||||
p->RunLength = p->InitRL;
|
||||
UpdateModel(p);
|
||||
}
|
140
lzma/C/Ppmd7.h
Normal file
140
lzma/C/Ppmd7.h
Normal file
|
@ -0,0 +1,140 @@
|
|||
/* Ppmd7.h -- PPMdH compression codec
|
||||
2010-03-12 : Igor Pavlov : Public domain
|
||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||
|
||||
/* This code supports virtual RangeDecoder and includes the implementation
|
||||
of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H.
|
||||
If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */
|
||||
|
||||
#ifndef __PPMD7_H
|
||||
#define __PPMD7_H
|
||||
|
||||
#include "Ppmd.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define PPMD7_MIN_ORDER 2
|
||||
#define PPMD7_MAX_ORDER 64
|
||||
|
||||
#define PPMD7_MIN_MEM_SIZE (1 << 11)
|
||||
#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)
|
||||
|
||||
struct CPpmd7_Context_;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
struct CPpmd7_Context_ *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd7_Context_Ref;
|
||||
|
||||
typedef struct CPpmd7_Context_
|
||||
{
|
||||
UInt16 NumStats;
|
||||
UInt16 SummFreq;
|
||||
CPpmd_State_Ref Stats;
|
||||
CPpmd7_Context_Ref Suffix;
|
||||
} CPpmd7_Context;
|
||||
|
||||
#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CPpmd7_Context *MinContext, *MaxContext;
|
||||
CPpmd_State *FoundState;
|
||||
unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag;
|
||||
Int32 RunLength, InitRL; /* must be 32-bit at least */
|
||||
|
||||
UInt32 Size;
|
||||
UInt32 GlueCount;
|
||||
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
|
||||
UInt32 AlignOffset;
|
||||
|
||||
Byte Indx2Units[PPMD_NUM_INDEXES];
|
||||
Byte Units2Indx[128];
|
||||
CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
|
||||
Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
|
||||
CPpmd_See DummySee, See[25][16];
|
||||
UInt16 BinSumm[128][64];
|
||||
} CPpmd7;
|
||||
|
||||
void Ppmd7_Construct(CPpmd7 *p);
|
||||
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);
|
||||
void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc);
|
||||
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);
|
||||
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
|
||||
|
||||
|
||||
/* ---------- Internal Functions ---------- */
|
||||
|
||||
extern const Byte PPMD7_kExpEscape[16];
|
||||
|
||||
#ifdef PPMD_32BIT
|
||||
#define Ppmd7_GetPtr(p, ptr) (ptr)
|
||||
#define Ppmd7_GetContext(p, ptr) (ptr)
|
||||
#define Ppmd7_GetStats(p, ctx) ((ctx)->Stats)
|
||||
#else
|
||||
#define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
|
||||
#define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs)))
|
||||
#define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats)))
|
||||
#endif
|
||||
|
||||
void Ppmd7_Update1(CPpmd7 *p);
|
||||
void Ppmd7_Update1_0(CPpmd7 *p);
|
||||
void Ppmd7_Update2(CPpmd7 *p);
|
||||
void Ppmd7_UpdateBin(CPpmd7 *p);
|
||||
|
||||
#define Ppmd7_GetBinSumm(p) \
|
||||
&p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
|
||||
p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
|
||||
(p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
|
||||
2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \
|
||||
((p->RunLength >> 26) & 0x20)]
|
||||
|
||||
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);
|
||||
|
||||
|
||||
/* ---------- Decode ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 (*GetThreshold)(void *p, UInt32 total);
|
||||
void (*Decode)(void *p, UInt32 start, UInt32 size);
|
||||
UInt32 (*DecodeBit)(void *p, UInt32 size0);
|
||||
} IPpmd7_RangeDec;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IPpmd7_RangeDec p;
|
||||
UInt32 Range;
|
||||
UInt32 Code;
|
||||
IByteIn *Stream;
|
||||
} CPpmd7z_RangeDec;
|
||||
|
||||
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p);
|
||||
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p);
|
||||
#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
|
||||
|
||||
int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc);
|
||||
|
||||
|
||||
/* ---------- Encode ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt64 Low;
|
||||
UInt32 Range;
|
||||
Byte Cache;
|
||||
UInt64 CacheSize;
|
||||
IByteOut *Stream;
|
||||
} CPpmd7z_RangeEnc;
|
||||
|
||||
void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p);
|
||||
void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p);
|
||||
|
||||
void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
189
lzma/C/Ppmd7Dec.c
Normal file
189
lzma/C/Ppmd7Dec.c
Normal file
|
@ -0,0 +1,189 @@
|
|||
/* Ppmd7Dec.c -- PPMdH Decoder
|
||||
2010-03-12 : Igor Pavlov : Public domain
|
||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "Ppmd7.h"
|
||||
|
||||
#define kTopValue (1 << 24)
|
||||
|
||||
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
|
||||
{
|
||||
unsigned i;
|
||||
p->Code = 0;
|
||||
p->Range = 0xFFFFFFFF;
|
||||
if (p->Stream->Read((void *)p->Stream) != 0)
|
||||
return False;
|
||||
for (i = 0; i < 4; i++)
|
||||
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
|
||||
return (p->Code < 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
static UInt32 Range_GetThreshold(void *pp, UInt32 total)
|
||||
{
|
||||
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
|
||||
return (p->Code) / (p->Range /= total);
|
||||
}
|
||||
|
||||
static void Range_Normalize(CPpmd7z_RangeDec *p)
|
||||
{
|
||||
if (p->Range < kTopValue)
|
||||
{
|
||||
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
|
||||
p->Range <<= 8;
|
||||
if (p->Range < kTopValue)
|
||||
{
|
||||
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
|
||||
p->Range <<= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Range_Decode(void *pp, UInt32 start, UInt32 size)
|
||||
{
|
||||
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
|
||||
p->Code -= start * p->Range;
|
||||
p->Range *= size;
|
||||
Range_Normalize(p);
|
||||
}
|
||||
|
||||
static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
|
||||
{
|
||||
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
|
||||
UInt32 newBound = (p->Range >> 14) * size0;
|
||||
UInt32 symbol;
|
||||
if (p->Code < newBound)
|
||||
{
|
||||
symbol = 0;
|
||||
p->Range = newBound;
|
||||
}
|
||||
else
|
||||
{
|
||||
symbol = 1;
|
||||
p->Code -= newBound;
|
||||
p->Range -= newBound;
|
||||
}
|
||||
Range_Normalize(p);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
|
||||
{
|
||||
p->p.GetThreshold = Range_GetThreshold;
|
||||
p->p.Decode = Range_Decode;
|
||||
p->p.DecodeBit = Range_DecodeBit;
|
||||
}
|
||||
|
||||
|
||||
#define MASK(sym) ((signed char *)charMask)[sym]
|
||||
|
||||
int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)
|
||||
{
|
||||
size_t charMask[256 / sizeof(size_t)];
|
||||
if (p->MinContext->NumStats != 1)
|
||||
{
|
||||
CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
|
||||
unsigned i;
|
||||
UInt32 count, hiCnt;
|
||||
if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
|
||||
{
|
||||
Byte symbol;
|
||||
rc->Decode(rc, 0, s->Freq);
|
||||
p->FoundState = s;
|
||||
symbol = s->Symbol;
|
||||
Ppmd7_Update1_0(p);
|
||||
return symbol;
|
||||
}
|
||||
p->PrevSuccess = 0;
|
||||
i = p->MinContext->NumStats - 1;
|
||||
do
|
||||
{
|
||||
if ((hiCnt += (++s)->Freq) > count)
|
||||
{
|
||||
Byte symbol;
|
||||
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
|
||||
p->FoundState = s;
|
||||
symbol = s->Symbol;
|
||||
Ppmd7_Update1(p);
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
while (--i);
|
||||
if (count >= p->MinContext->SummFreq)
|
||||
return -2;
|
||||
p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
|
||||
rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
|
||||
PPMD_SetAllBitsIn256Bytes(charMask);
|
||||
MASK(s->Symbol) = 0;
|
||||
i = p->MinContext->NumStats - 1;
|
||||
do { MASK((--s)->Symbol) = 0; } while (--i);
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt16 *prob = Ppmd7_GetBinSumm(p);
|
||||
if (rc->DecodeBit(rc, *prob) == 0)
|
||||
{
|
||||
Byte symbol;
|
||||
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
|
||||
symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
|
||||
Ppmd7_UpdateBin(p);
|
||||
return symbol;
|
||||
}
|
||||
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
|
||||
p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
|
||||
PPMD_SetAllBitsIn256Bytes(charMask);
|
||||
MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
|
||||
p->PrevSuccess = 0;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
CPpmd_State *ps[256], *s;
|
||||
UInt32 freqSum, count, hiCnt;
|
||||
CPpmd_See *see;
|
||||
unsigned i, num, numMasked = p->MinContext->NumStats;
|
||||
do
|
||||
{
|
||||
p->OrderFall++;
|
||||
if (!p->MinContext->Suffix)
|
||||
return -1;
|
||||
p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
|
||||
}
|
||||
while (p->MinContext->NumStats == numMasked);
|
||||
hiCnt = 0;
|
||||
s = Ppmd7_GetStats(p, p->MinContext);
|
||||
i = 0;
|
||||
num = p->MinContext->NumStats - numMasked;
|
||||
do
|
||||
{
|
||||
int k = (int)(MASK(s->Symbol));
|
||||
hiCnt += (s->Freq & k);
|
||||
ps[i] = s++;
|
||||
i -= k;
|
||||
}
|
||||
while (i != num);
|
||||
|
||||
see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
|
||||
freqSum += hiCnt;
|
||||
count = rc->GetThreshold(rc, freqSum);
|
||||
|
||||
if (count < hiCnt)
|
||||
{
|
||||
Byte symbol;
|
||||
CPpmd_State **pps = ps;
|
||||
for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
|
||||
s = *pps;
|
||||
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
|
||||
Ppmd_See_Update(see);
|
||||
p->FoundState = s;
|
||||
symbol = s->Symbol;
|
||||
Ppmd7_Update2(p);
|
||||
return symbol;
|
||||
}
|
||||
if (count >= freqSum)
|
||||
return -2;
|
||||
rc->Decode(rc, hiCnt, freqSum - hiCnt);
|
||||
see->Summ = (UInt16)(see->Summ + freqSum);
|
||||
do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
|
||||
}
|
||||
}
|
10
lzma/C/Precomp.h
Normal file
10
lzma/C/Precomp.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* Precomp.h -- StdAfx
|
||||
2013-11-12 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_PRECOMP_H
|
||||
#define __7Z_PRECOMP_H
|
||||
|
||||
#include "Compiler.h"
|
||||
/* #include "7zTypes.h" */
|
||||
|
||||
#endif
|
|
@ -1,7 +1,9 @@
|
|||
/* Threads.c -- multithreading library
|
||||
2009-09-20 : Igor Pavlov : Public domain */
|
||||
2014-09-21 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
#include "Precomp.h"
|
||||
|
||||
#ifndef UNDER_CE
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
|
@ -29,14 +31,21 @@ WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE)
|
|||
|
||||
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
|
||||
{
|
||||
unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
|
||||
*p =
|
||||
#ifdef UNDER_CE
|
||||
CreateThread(0, 0, func, param, 0, &threadId);
|
||||
#else
|
||||
(HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);
|
||||
#endif
|
||||
/* maybe we must use errno here, but probably GetLastError() is also OK. */
|
||||
/* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
|
||||
|
||||
#ifdef UNDER_CE
|
||||
|
||||
DWORD threadId;
|
||||
*p = CreateThread(0, 0, func, param, 0, &threadId);
|
||||
|
||||
#else
|
||||
|
||||
unsigned threadId;
|
||||
*p = (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);
|
||||
|
||||
#endif
|
||||
|
||||
/* maybe we must use errno here, but probably GetLastError() is also OK. */
|
||||
return HandleToWRes(*p);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
/* Threads.h -- multithreading library
|
||||
2009-03-27 : Igor Pavlov : Public domain */
|
||||
2013-11-12 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_THREADS_H
|
||||
#define __7Z_THREADS_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
WRes HandlePtr_Close(HANDLE *h);
|
||||
WRes Handle_WaitObject(HANDLE h);
|
||||
|
||||
|
@ -18,7 +20,15 @@ typedef HANDLE CThread;
|
|||
#define Thread_WasCreated(p) (*(p) != NULL)
|
||||
#define Thread_Close(p) HandlePtr_Close(p)
|
||||
#define Thread_Wait(p) Handle_WaitObject(*(p))
|
||||
typedef unsigned THREAD_FUNC_RET_TYPE;
|
||||
|
||||
typedef
|
||||
#ifdef UNDER_CE
|
||||
DWORD
|
||||
#else
|
||||
unsigned
|
||||
#endif
|
||||
THREAD_FUNC_RET_TYPE;
|
||||
|
||||
#define THREAD_FUNC_CALL_TYPE MY_STD_CALL
|
||||
#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
|
||||
typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
|
||||
|
@ -52,8 +62,6 @@ WRes CriticalSection_Init(CCriticalSection *p);
|
|||
#define CriticalSection_Enter(p) EnterCriticalSection(p)
|
||||
#define CriticalSection_Leave(p) LeaveCriticalSection(p)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,21 +6,27 @@ if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE )
|
|||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" )
|
||||
endif( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE )
|
||||
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_7ZIP_PPMD_SUPPPORT" )
|
||||
|
||||
set( LZMA_FILES
|
||||
C/7zArcIn.c
|
||||
C/7zBuf.c
|
||||
C/7zCrc.c
|
||||
C/7zCrcOpt.c
|
||||
C/7zDec.c
|
||||
C/7zIn.c
|
||||
C/7zStream.c
|
||||
C/Bcj2.c
|
||||
C/Bra.c
|
||||
C/Bra86.c
|
||||
C/BraIA64.c
|
||||
C/CpuArch.c
|
||||
C/Delta.c
|
||||
C/LzFind.c
|
||||
C/Lzma2Dec.c
|
||||
C/LzmaDec.c
|
||||
C/LzmaEnc.c )
|
||||
C/LzmaEnc.c
|
||||
C/Ppmd7.c
|
||||
C/Ppmd7Dec.c )
|
||||
|
||||
if( WIN32 )
|
||||
set( LZMA_FILES ${LZMA_FILES} C/LzFindMt.c C/Threads.c )
|
||||
|
|
|
@ -1,6 +1,62 @@
|
|||
HISTORY of the LZMA SDK
|
||||
-----------------------
|
||||
|
||||
15.12 2015-11-19
|
||||
-------------------------
|
||||
- The BUG in C version of 7z decoder was fixed:
|
||||
7zDec.c : SzDecodeLzma2()
|
||||
7z decoder could mistakenly report about decoding error for some 7z archives
|
||||
that use LZMA2 compression method.
|
||||
The probability to get that mistaken decoding error report was about
|
||||
one error per 16384 solid blocks for solid blocks larger than 16 KB (compressed size).
|
||||
- The BUG (in 9.26-15.11) in C version of 7z decoder was fixed:
|
||||
7zArcIn.c : SzReadHeader2()
|
||||
7z decoder worked incorrectly for 7z archives that contain
|
||||
empty solid blocks, that can be placed to 7z archive, if some file is
|
||||
unavailable for reading during archive creation.
|
||||
|
||||
|
||||
15.09 beta 2015-10-16
|
||||
-------------------------
|
||||
- The BUG in LZMA / LZMA2 encoding code was fixed.
|
||||
The BUG in LzFind.c::MatchFinder_ReadBlock() function.
|
||||
If input data size is larger than (4 GiB - dictionary_size),
|
||||
the following code worked incorrectly:
|
||||
- LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions
|
||||
for compressing from memory to memory.
|
||||
That BUG is not related to LZMA encoder version that works via streams.
|
||||
- LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly, if
|
||||
default value of chunk size (CLzma2EncProps::blockSize) is changed
|
||||
to value larger than (4 GiB - dictionary_size).
|
||||
|
||||
|
||||
9.38 beta 2015-01-03
|
||||
-------------------------
|
||||
- The BUG in 9.31-9.37 was fixed:
|
||||
IArchiveGetRawProps interface was disabled for 7z archives.
|
||||
- The BUG in 9.26-9.36 was fixed:
|
||||
Some code in CPP\7zip\Archive\7z\ worked correctly only under Windows.
|
||||
|
||||
|
||||
9.36 beta 2014-12-26
|
||||
-------------------------
|
||||
- The BUG in command line version was fixed:
|
||||
7-Zip created temporary archive in current folder during update archive
|
||||
operation, if -w{Path} switch was not specified.
|
||||
The fixed 7-Zip creates temporary archive in folder that contains updated archive.
|
||||
- The BUG in 9.33-9.35 was fixed:
|
||||
7-Zip silently ignored file reading errors during 7z or gz archive creation,
|
||||
and the created archive contained only part of file that was read before error.
|
||||
The fixed 7-Zip stops archive creation and it reports about error.
|
||||
|
||||
|
||||
9.35 beta 2014-12-07
|
||||
-------------------------
|
||||
- 7zr.exe now support AES encryption.
|
||||
- SFX mudules were added to LZMA SDK
|
||||
- Some bugs were fixed.
|
||||
|
||||
|
||||
9.21 beta 2011-04-11
|
||||
-------------------------
|
||||
- New class FString for file names at file systems.
|
||||
|
|
451
lzma/lzma.txt
451
lzma/lzma.txt
|
@ -1,18 +1,27 @@
|
|||
LZMA SDK 9.22
|
||||
-------------
|
||||
LZMA SDK 15.13
|
||||
--------------
|
||||
|
||||
LZMA SDK provides the documentation, samples, header files, libraries,
|
||||
and tools you need to develop applications that use LZMA compression.
|
||||
|
||||
LZMA is default and general compression method of 7z format
|
||||
in 7-Zip compression program (www.7-zip.org). LZMA provides high
|
||||
compression ratio and very fast decompression.
|
||||
LZMA SDK provides the documentation, samples, header files,
|
||||
libraries, and tools you need to develop applications that
|
||||
use 7z / LZMA / LZMA2 / XZ compression.
|
||||
|
||||
LZMA is an improved version of famous LZ77 compression algorithm.
|
||||
It was improved in way of maximum increasing of compression ratio,
|
||||
keeping high decompression speed and low memory requirements for
|
||||
decompressing.
|
||||
|
||||
LZMA2 is a LZMA based compression method. LZMA2 provides better
|
||||
multithreading support for compression than LZMA and some other improvements.
|
||||
|
||||
7z is a file format for data compression and file archiving.
|
||||
7z is a main file format for 7-Zip compression program (www.7-zip.org).
|
||||
7z format supports different compression methods: LZMA, LZMA2 and others.
|
||||
7z also supports AES-256 based encryption.
|
||||
|
||||
XZ is a file format for data compression that uses LZMA2 compression.
|
||||
XZ format provides additional features: SHA/CRC check, filters for
|
||||
improved compression ratio, splitting to blocks and streams,
|
||||
|
||||
|
||||
|
||||
LICENSE
|
||||
|
@ -24,8 +33,9 @@ Some code in LZMA SDK is based on public domain code from another developers:
|
|||
1) PPMd var.H (2001): Dmitry Shkarin
|
||||
2) SHA-256: Wei Dai (Crypto++ library)
|
||||
|
||||
You can copy, modify, distribute and perform LZMA SDK code, even for commercial purposes,
|
||||
all without asking permission.
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute the
|
||||
original LZMA SDK code, either in source code form or as a compiled binary, for
|
||||
any purpose, commercial or non-commercial, and by any means.
|
||||
|
||||
LZMA SDK code is compatible with open source licenses, for example, you can
|
||||
include it to GNU GPL or GNU LGPL code.
|
||||
|
@ -34,10 +44,20 @@ include it to GNU GPL or GNU LGPL code.
|
|||
LZMA SDK Contents
|
||||
-----------------
|
||||
|
||||
LZMA SDK includes:
|
||||
Source code:
|
||||
|
||||
- ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing
|
||||
- Compiled file->file LZMA compressing/decompressing program for Windows system
|
||||
- C / C++ / C# / Java - LZMA compression and decompression
|
||||
- C / C++ - LZMA2 compression and decompression
|
||||
- C / C++ - XZ compression and decompression
|
||||
- C - 7z decompression
|
||||
- C++ - 7z compression and decompression
|
||||
- C - small SFXs for installers (7z decompression)
|
||||
- C++ - SFXs and SFXs for installers (7z decompression)
|
||||
|
||||
Precomiled binaries:
|
||||
|
||||
- console programs for lzma / 7z / xz compression and decompression
|
||||
- SFX modules for installers.
|
||||
|
||||
|
||||
UNIX/Linux version
|
||||
|
@ -51,70 +71,94 @@ In some UNIX/Linux versions you must compile LZMA with static libraries.
|
|||
To compile with static libraries, you can use
|
||||
LIB = -lm -static
|
||||
|
||||
Also you can use p7zip (port of 7-Zip for POSIX systems like Unix or Linux):
|
||||
|
||||
http://p7zip.sourceforge.net/
|
||||
|
||||
|
||||
Files
|
||||
---------------------
|
||||
lzma.txt - LZMA SDK description (this file)
|
||||
7zFormat.txt - 7z Format description
|
||||
7zC.txt - 7z ANSI-C Decoder description
|
||||
methods.txt - Compression method IDs for .7z
|
||||
lzma.exe - Compiled file->file LZMA encoder/decoder for Windows
|
||||
7zr.exe - 7-Zip with 7z/lzma/xz support.
|
||||
history.txt - history of the LZMA SDK
|
||||
-----
|
||||
|
||||
DOC/7zC.txt - 7z ANSI-C Decoder description
|
||||
DOC/7zFormat.txt - 7z Format description
|
||||
DOC/installer.txt - information about 7-Zip for installers
|
||||
DOC/lzma.txt - LZMA compression description
|
||||
DOC/lzma-sdk.txt - LZMA SDK description (this file)
|
||||
DOC/lzma-history.txt - history of LZMA SDK
|
||||
DOC/lzma-specification.txt - Specification of LZMA
|
||||
DOC/Methods.txt - Compression method IDs for .7z
|
||||
|
||||
bin/installer/ - example script to create installer that uses SFX module,
|
||||
|
||||
bin/7zdec.exe - simplified 7z archive decoder
|
||||
bin/7zr.exe - 7-Zip console program (reduced version)
|
||||
bin/x64/7zr.exe - 7-Zip console program (reduced version) (x64 version)
|
||||
bin/lzma.exe - file->file LZMA encoder/decoder for Windows
|
||||
bin/7zS2.sfx - small SFX module for installers (GUI version)
|
||||
bin/7zS2con.sfx - small SFX module for installers (Console version)
|
||||
bin/7zSD.sfx - SFX module for installers.
|
||||
|
||||
|
||||
7zDec.exe
|
||||
---------
|
||||
7zDec.exe is simplified 7z archive decoder.
|
||||
It supports only LZMA, LZMA2, and PPMd methods.
|
||||
7zDec decodes whole solid block from 7z archive to RAM.
|
||||
The RAM consumption can be high.
|
||||
|
||||
|
||||
|
||||
|
||||
Source code structure
|
||||
---------------------
|
||||
|
||||
C/ - C files
|
||||
7zCrc*.* - CRC code
|
||||
Alloc.* - Memory allocation functions
|
||||
Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code
|
||||
LzFind.* - Match finder for LZ (LZMA) encoders
|
||||
LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding
|
||||
LzHash.h - Additional file for LZ match finder
|
||||
LzmaDec.* - LZMA decoding
|
||||
LzmaEnc.* - LZMA encoding
|
||||
LzmaLib.* - LZMA Library for DLL calling
|
||||
Types.h - Basic types for another .c files
|
||||
Threads.* - The code for multithreading.
|
||||
|
||||
LzmaLib - LZMA Library (.DLL for Windows)
|
||||
|
||||
LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder).
|
||||
Asm/ - asm files (optimized code for CRC calculation and Intel-AES encryption)
|
||||
|
||||
Archive - files related to archiving
|
||||
7z - 7z ANSI-C Decoder
|
||||
C/ - C files (compression / decompression and other)
|
||||
Util/
|
||||
7z - 7z decoder program (decoding 7z files)
|
||||
Lzma - LZMA program (file->file LZMA encoder/decoder).
|
||||
LzmaLib - LZMA library (.DLL for Windows)
|
||||
SfxSetup - small SFX module for installers
|
||||
|
||||
CPP/ -- CPP files
|
||||
|
||||
Common - common files for C++ projects
|
||||
Windows - common files for Windows related code
|
||||
|
||||
7zip - files related to 7-Zip Project
|
||||
|
||||
Common - common files for 7-Zip
|
||||
|
||||
Compress - files related to compression/decompression
|
||||
7zip - files related to 7-Zip
|
||||
|
||||
Archive - files related to archiving
|
||||
|
||||
Common - common files for archive handling
|
||||
7z - 7z C++ Encoder/Decoder
|
||||
|
||||
Bundles - Modules that are bundles of other modules
|
||||
Bundles - Modules that are bundles of other modules (files)
|
||||
|
||||
Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2
|
||||
LzmaCon - lzma.exe: LZMA compression/decompression
|
||||
Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2
|
||||
Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2.
|
||||
Alone7z - 7zr.exe: Standalone 7-Zip console program (reduced version)
|
||||
Format7zExtractR - 7zxr.dll: Reduced version of 7z DLL: extracting from 7z/LZMA/BCJ/BCJ2.
|
||||
Format7zR - 7zr.dll: Reduced version of 7z DLL: extracting/compressing to 7z/LZMA/BCJ/BCJ2
|
||||
LzmaCon - lzma.exe: LZMA compression/decompression
|
||||
LzmaSpec - example code for LZMA Specification
|
||||
SFXCon - 7zCon.sfx: Console 7z SFX module
|
||||
SFXSetup - 7zS.sfx: 7z SFX module for installers
|
||||
SFXWin - 7z.sfx: GUI 7z SFX module
|
||||
|
||||
UI - User Interface files
|
||||
Common - common files for 7-Zip
|
||||
|
||||
Compress - files for compression/decompression
|
||||
|
||||
Crypto - files for encryption / decompression
|
||||
|
||||
UI - User Interface files
|
||||
|
||||
Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll
|
||||
Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll
|
||||
Common - Common UI files
|
||||
Console - Code for console archiver
|
||||
|
||||
Console - Code for console program (7z.exe)
|
||||
Explorer - Some code from 7-Zip Shell extension
|
||||
FileManager - Some GUI code from 7-Zip File Manager
|
||||
GUI - Some GUI code from 7-Zip
|
||||
|
||||
|
||||
CS/ - C# files
|
||||
|
@ -134,8 +178,9 @@ Java/ - Java files
|
|||
RangeCoder - Range Coder (special code of compression/decompression)
|
||||
|
||||
|
||||
C/C++ source code of LZMA SDK is part of 7-Zip project.
|
||||
7-Zip source code can be downloaded from 7-Zip's SourceForge page:
|
||||
Note:
|
||||
Asm / C / C++ source code of LZMA SDK is part of 7-Zip's source code.
|
||||
7-Zip's source code can be downloaded from 7-Zip's SourceForge page:
|
||||
|
||||
http://sourceforge.net/projects/sevenzip/
|
||||
|
||||
|
@ -146,8 +191,8 @@ LZMA features
|
|||
- Variable dictionary size (up to 1 GB)
|
||||
- Estimated compressing speed: about 2 MB/s on 2 GHz CPU
|
||||
- Estimated decompressing speed:
|
||||
- 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64
|
||||
- 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC
|
||||
- 20-30 MB/s on modern 2 GHz cpu
|
||||
- 1-2 MB/s on 200 MHz simple RISC cpu: (ARM, MIPS, PowerPC)
|
||||
- Small memory requirements for decompressing (16 KB + DictionarySize)
|
||||
- Small code size for decompressing: 5-8 KB
|
||||
|
||||
|
@ -156,7 +201,7 @@ implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions).
|
|||
|
||||
Some critical operations that affect the speed of LZMA decompression:
|
||||
1) 32*16 bit integer multiply
|
||||
2) Misspredicted branches (penalty mostly depends from pipeline length)
|
||||
2) Mispredicted branches (penalty mostly depends from pipeline length)
|
||||
3) 32-bit shift and arithmetic operations
|
||||
|
||||
The speed of LZMA decompressing mostly depends from CPU speed.
|
||||
|
@ -304,298 +349,6 @@ compressible.
|
|||
For some ISAs (for example, for MIPS) it's impossible to get gain from such filter.
|
||||
|
||||
|
||||
LZMA compressed file format
|
||||
---------------------------
|
||||
Offset Size Description
|
||||
0 1 Special LZMA properties (lc,lp, pb in encoded form)
|
||||
1 4 Dictionary size (little endian)
|
||||
5 8 Uncompressed size (little endian). -1 means unknown size
|
||||
13 Compressed data
|
||||
|
||||
|
||||
ANSI-C LZMA Decoder
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58.
|
||||
If you want to use old interfaces you can download previous version of LZMA SDK
|
||||
from sourceforge.net site.
|
||||
|
||||
To use ANSI-C LZMA Decoder you need the following files:
|
||||
1) LzmaDec.h + LzmaDec.c + Types.h
|
||||
LzmaUtil/LzmaUtil.c is example application that uses these files.
|
||||
|
||||
|
||||
Memory requirements for LZMA decoding
|
||||
-------------------------------------
|
||||
|
||||
Stack usage of LZMA decoding function for local variables is not
|
||||
larger than 200-400 bytes.
|
||||
|
||||
LZMA Decoder uses dictionary buffer and internal state structure.
|
||||
Internal state structure consumes
|
||||
state_size = (4 + (1.5 << (lc + lp))) KB
|
||||
by default (lc=3, lp=0), state_size = 16 KB.
|
||||
|
||||
|
||||
How To decompress data
|
||||
----------------------
|
||||
|
||||
LZMA Decoder (ANSI-C version) now supports 2 interfaces:
|
||||
1) Single-call Decompressing
|
||||
2) Multi-call State Decompressing (zlib-like interface)
|
||||
|
||||
You must use external allocator:
|
||||
Example:
|
||||
void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }
|
||||
void SzFree(void *p, void *address) { p = p; free(address); }
|
||||
ISzAlloc alloc = { SzAlloc, SzFree };
|
||||
|
||||
You can use p = p; operator to disable compiler warnings.
|
||||
|
||||
|
||||
Single-call Decompressing
|
||||
-------------------------
|
||||
When to use: RAM->RAM decompressing
|
||||
Compile files: LzmaDec.h + LzmaDec.c + Types.h
|
||||
Compile defines: no defines
|
||||
Memory Requirements:
|
||||
- Input buffer: compressed size
|
||||
- Output buffer: uncompressed size
|
||||
- LZMA Internal Structures: state_size (16 KB for default settings)
|
||||
|
||||
Interface:
|
||||
int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||
ELzmaStatus *status, ISzAlloc *alloc);
|
||||
In:
|
||||
dest - output data
|
||||
destLen - output data size
|
||||
src - input data
|
||||
srcLen - input data size
|
||||
propData - LZMA properties (5 bytes)
|
||||
propSize - size of propData buffer (5 bytes)
|
||||
finishMode - It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
You can use LZMA_FINISH_END, when you know that
|
||||
current output buffer covers last bytes of stream.
|
||||
alloc - Memory allocator.
|
||||
|
||||
Out:
|
||||
destLen - processed output size
|
||||
srcLen - processed input size
|
||||
|
||||
Output:
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||
|
||||
If LZMA decoder sees end_marker before reaching output limit, it returns OK result,
|
||||
and output value of destLen will be less than output buffer size limit.
|
||||
|
||||
You can use multiple checks to test data integrity after full decompression:
|
||||
1) Check Result and "status" variable.
|
||||
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
|
||||
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
||||
You must use correct finish mode in that case. */
|
||||
|
||||
|
||||
Multi-call State Decompressing (zlib-like interface)
|
||||
----------------------------------------------------
|
||||
|
||||
When to use: file->file decompressing
|
||||
Compile files: LzmaDec.h + LzmaDec.c + Types.h
|
||||
|
||||
Memory Requirements:
|
||||
- Buffer for input stream: any size (for example, 16 KB)
|
||||
- Buffer for output stream: any size (for example, 16 KB)
|
||||
- LZMA Internal Structures: state_size (16 KB for default settings)
|
||||
- LZMA dictionary (dictionary size is encoded in LZMA properties header)
|
||||
|
||||
1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header:
|
||||
unsigned char header[LZMA_PROPS_SIZE + 8];
|
||||
ReadFile(inFile, header, sizeof(header)
|
||||
|
||||
2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties
|
||||
|
||||
CLzmaDec state;
|
||||
LzmaDec_Constr(&state);
|
||||
res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);
|
||||
if (res != SZ_OK)
|
||||
return res;
|
||||
|
||||
3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop
|
||||
|
||||
LzmaDec_Init(&state);
|
||||
for (;;)
|
||||
{
|
||||
...
|
||||
int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
4) Free all allocated structures
|
||||
LzmaDec_Free(&state, &g_Alloc);
|
||||
|
||||
For full code example, look at C/LzmaUtil/LzmaUtil.c code.
|
||||
|
||||
|
||||
How To compress data
|
||||
--------------------
|
||||
|
||||
Compile files: LzmaEnc.h + LzmaEnc.c + Types.h +
|
||||
LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h
|
||||
|
||||
Memory Requirements:
|
||||
- (dictSize * 11.5 + 6 MB) + state_size
|
||||
|
||||
Lzma Encoder can use two memory allocators:
|
||||
1) alloc - for small arrays.
|
||||
2) allocBig - for big arrays.
|
||||
|
||||
For example, you can use Large RAM Pages (2 MB) in allocBig allocator for
|
||||
better compression speed. Note that Windows has bad implementation for
|
||||
Large RAM Pages.
|
||||
It's OK to use same allocator for alloc and allocBig.
|
||||
|
||||
|
||||
Single-call Compression with callbacks
|
||||
--------------------------------------
|
||||
|
||||
Check C/LzmaUtil/LzmaUtil.c as example,
|
||||
|
||||
When to use: file->file decompressing
|
||||
|
||||
1) you must implement callback structures for interfaces:
|
||||
ISeqInStream
|
||||
ISeqOutStream
|
||||
ICompressProgress
|
||||
ISzAlloc
|
||||
|
||||
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
CFileSeqInStream inStream;
|
||||
CFileSeqOutStream outStream;
|
||||
|
||||
inStream.funcTable.Read = MyRead;
|
||||
inStream.file = inFile;
|
||||
outStream.funcTable.Write = MyWrite;
|
||||
outStream.file = outFile;
|
||||
|
||||
|
||||
2) Create CLzmaEncHandle object;
|
||||
|
||||
CLzmaEncHandle enc;
|
||||
|
||||
enc = LzmaEnc_Create(&g_Alloc);
|
||||
if (enc == 0)
|
||||
return SZ_ERROR_MEM;
|
||||
|
||||
|
||||
3) initialize CLzmaEncProps properties;
|
||||
|
||||
LzmaEncProps_Init(&props);
|
||||
|
||||
Then you can change some properties in that structure.
|
||||
|
||||
4) Send LZMA properties to LZMA Encoder
|
||||
|
||||
res = LzmaEnc_SetProps(enc, &props);
|
||||
|
||||
5) Write encoded properties to header
|
||||
|
||||
Byte header[LZMA_PROPS_SIZE + 8];
|
||||
size_t headerSize = LZMA_PROPS_SIZE;
|
||||
UInt64 fileSize;
|
||||
int i;
|
||||
|
||||
res = LzmaEnc_WriteProperties(enc, header, &headerSize);
|
||||
fileSize = MyGetFileLength(inFile);
|
||||
for (i = 0; i < 8; i++)
|
||||
header[headerSize++] = (Byte)(fileSize >> (8 * i));
|
||||
MyWriteFileAndCheck(outFile, header, headerSize)
|
||||
|
||||
6) Call encoding function:
|
||||
res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable,
|
||||
NULL, &g_Alloc, &g_Alloc);
|
||||
|
||||
7) Destroy LZMA Encoder Object
|
||||
LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
|
||||
|
||||
|
||||
If callback function return some error code, LzmaEnc_Encode also returns that code
|
||||
or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS.
|
||||
|
||||
|
||||
Single-call RAM->RAM Compression
|
||||
--------------------------------
|
||||
|
||||
Single-call RAM->RAM Compression is similar to Compression with callbacks,
|
||||
but you provide pointers to buffers instead of pointers to stream callbacks:
|
||||
|
||||
HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||
CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
|
||||
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
|
||||
Return code:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater
|
||||
SZ_ERROR_OUTPUT_EOF - output buffer overflow
|
||||
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||
|
||||
|
||||
|
||||
Defines
|
||||
-------
|
||||
|
||||
_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code.
|
||||
|
||||
_LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for
|
||||
some structures will be doubled in that case.
|
||||
|
||||
_LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit.
|
||||
|
||||
_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type.
|
||||
|
||||
|
||||
_7ZIP_PPMD_SUPPPORT - Define it if you don't want to support PPMD method in AMSI-C .7z decoder.
|
||||
|
||||
|
||||
C++ LZMA Encoder/Decoder
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
C++ LZMA code use COM-like interfaces. So if you want to use it,
|
||||
you can study basics of COM/OLE.
|
||||
C++ LZMA code is just wrapper over ANSI-C code.
|
||||
|
||||
|
||||
C++ Notes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling),
|
||||
you must check that you correctly work with "new" operator.
|
||||
7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator.
|
||||
So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator:
|
||||
operator new(size_t size)
|
||||
{
|
||||
void *p = ::malloc(size);
|
||||
if (p == 0)
|
||||
throw CNewException();
|
||||
return p;
|
||||
}
|
||||
If you use MSCV that throws exception for "new" operator, you can compile without
|
||||
"NewHandler.cpp". So standard exception will be used. Actually some code of
|
||||
7-Zip catches any exception in internal code and converts it to HRESULT code.
|
||||
So you don't need to catch CNewException, if you call COM interfaces of 7-Zip.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8,00"
|
||||
Version="8.00"
|
||||
Name="lzmalib"
|
||||
ProjectGUID="{6EB27E78-7C7A-4F08-8E19-957E8EB3A20F}"
|
||||
RootNamespace="lzmalib"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
|
@ -287,6 +286,10 @@
|
|||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\C\7zArcIn.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\7zBuf.c"
|
||||
>
|
||||
|
@ -303,10 +306,6 @@
|
|||
RelativePath=".\C\7zDec.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\7zIn.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\7zStream.c"
|
||||
>
|
||||
|
@ -323,10 +322,18 @@
|
|||
RelativePath=".\C\Bra86.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\BraIA64.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\CpuArch.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Delta.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\LzFind.c"
|
||||
>
|
||||
|
@ -347,6 +354,14 @@
|
|||
RelativePath=".\C\LzmaEnc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Ppmd7.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Ppmd7Dec.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Threads.c"
|
||||
>
|
||||
|
@ -381,10 +396,18 @@
|
|||
RelativePath=".\C\Bra.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Compiler.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\CpuArch.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Delta.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\LzFind.h"
|
||||
>
|
||||
|
@ -409,6 +432,18 @@
|
|||
RelativePath=".\C\LzmaEnc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Ppmd.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Ppmd7.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Precomp.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\C\Threads.h"
|
||||
>
|
||||
|
|
|
@ -203,7 +203,18 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
|||
// sound sequence thing in the sector will override this property.
|
||||
hidden = <bool>; // if true this sector will not be drawn on the textured automap.
|
||||
waterzone = <bool>; // Sector is under water and swimmable
|
||||
moreids = <string>; // Additional sector IDs/tags, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
|
||||
moreids = <string>; // Additional sector IDs/tags, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
|
||||
damageamount = <int>; // Amount of damage inflicted by this sector, default = 0. If this is 0, all other damage properties will be ignored.
|
||||
// Setting damage through these properties will override any damage set through 'special'.
|
||||
// Setting damageamount to a negative value will create a healing sector.
|
||||
damagetype = <string>; // Damage type for sector damage, Default = "None". (generic damage)
|
||||
damageinterval = <int>; // Interval in tics between damage application, default = 32.
|
||||
leakiness = <int>; // Probability of leaking through radiation suit (0 = never, 256 = always), default = 0.
|
||||
damageterraineffect = <bool>; // Will spawn a terrain splash when damage is inflicted. Default = false.
|
||||
damagehazard = <bool>; // Changes damage model to Strife's delayed damage for the given sector. Default = false.
|
||||
floorterrain = <string>; // Sets the terrain for the sector's floor. Default = 'use the flat texture's terrain definition.'
|
||||
ceilingterrain = <string>; // Sets the terrain for the sector's ceiling. Default = 'use the flat texture's terrain definition.'
|
||||
|
||||
|
||||
* Note about dropactors
|
||||
|
||||
|
@ -377,6 +388,10 @@ Changed language describing the DIALOGUE lump to mention USDF as an option.
|
|||
1.25 19.04.2015
|
||||
Added 'moreids' for linedefs and sectors.
|
||||
|
||||
1.26 05.01.2016
|
||||
added clarification about character encoding
|
||||
added sector damage properties.
|
||||
|
||||
===============================================================================
|
||||
EOF
|
||||
===============================================================================
|
||||
|
|
|
@ -591,9 +591,7 @@ set( PLAT_WIN32_SOURCES
|
|||
set( PLAT_POSIX_SOURCES
|
||||
posix/i_cd.cpp
|
||||
posix/i_movie.cpp
|
||||
posix/i_steam.cpp
|
||||
posix/i_system.cpp
|
||||
posix/st_start.cpp )
|
||||
posix/i_steam.cpp )
|
||||
set( PLAT_SDL_SOURCES
|
||||
posix/sdl/crashcatcher.c
|
||||
posix/sdl/hardware.cpp
|
||||
|
@ -601,8 +599,10 @@ set( PLAT_SDL_SOURCES
|
|||
posix/sdl/i_input.cpp
|
||||
posix/sdl/i_joystick.cpp
|
||||
posix/sdl/i_main.cpp
|
||||
posix/sdl/i_system.cpp
|
||||
posix/sdl/i_timer.cpp
|
||||
posix/sdl/sdlvideo.cpp )
|
||||
posix/sdl/sdlvideo.cpp
|
||||
posix/sdl/st_start.cpp )
|
||||
set( PLAT_OSX_SOURCES
|
||||
posix/osx/iwadpicker_cocoa.mm
|
||||
posix/osx/zdoom.icns )
|
||||
|
@ -611,8 +611,11 @@ set( PLAT_COCOA_SOURCES
|
|||
posix/cocoa/i_input.mm
|
||||
posix/cocoa/i_joystick.cpp
|
||||
posix/cocoa/i_main.mm
|
||||
posix/cocoa/i_system.mm
|
||||
posix/cocoa/i_timer.cpp
|
||||
posix/cocoa/i_video.mm )
|
||||
posix/cocoa/i_video.mm
|
||||
posix/cocoa/st_console.mm
|
||||
posix/cocoa/st_start.mm )
|
||||
|
||||
if( WIN32 )
|
||||
set( SYSTEM_SOURCES_DIR win32 )
|
||||
|
@ -1005,6 +1008,8 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
|||
wi_stuff.cpp
|
||||
zstrformat.cpp
|
||||
zstring.cpp
|
||||
GuillotineBinPack.cpp
|
||||
SkylineBinPack.cpp
|
||||
g_doom/a_doommisc.cpp
|
||||
g_heretic/a_hereticmisc.cpp
|
||||
g_hexen/a_hexenmisc.cpp
|
||||
|
|
634
src/GuillotineBinPack.cpp
Normal file
634
src/GuillotineBinPack.cpp
Normal file
|
@ -0,0 +1,634 @@
|
|||
/** @file GuillotineBinPack.cpp
|
||||
@author Jukka Jylänki
|
||||
|
||||
@brief Implements different bin packer algorithms that use the GUILLOTINE data structure.
|
||||
|
||||
This work is released to Public Domain, do whatever you want with it.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <limits.h>
|
||||
#include "templates.h"
|
||||
#include "GuillotineBinPack.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
GuillotineBinPack::GuillotineBinPack()
|
||||
:binWidth(0),
|
||||
binHeight(0)
|
||||
{
|
||||
}
|
||||
|
||||
GuillotineBinPack::GuillotineBinPack(int width, int height)
|
||||
{
|
||||
Init(width, height);
|
||||
}
|
||||
|
||||
void GuillotineBinPack::Init(int width, int height)
|
||||
{
|
||||
binWidth = width;
|
||||
binHeight = height;
|
||||
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Clear();
|
||||
#endif
|
||||
|
||||
// Clear any memory of previously packed rectangles.
|
||||
usedRectangles.Clear();
|
||||
|
||||
// We start with a single big free rectangle that spans the whole bin.
|
||||
Rect n;
|
||||
n.x = 0;
|
||||
n.y = 0;
|
||||
n.width = width;
|
||||
n.height = height;
|
||||
|
||||
freeRectangles.Clear();
|
||||
freeRectangles.Push(n);
|
||||
}
|
||||
|
||||
void GuillotineBinPack::Insert(TArray<RectSize> &rects, TArray<Rect> &dst, bool merge,
|
||||
FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
|
||||
{
|
||||
dst.Clear();
|
||||
|
||||
// Remember variables about the best packing choice we have made so far during the iteration process.
|
||||
int bestFreeRect = 0;
|
||||
int bestRect = 0;
|
||||
bool bestFlipped = false;
|
||||
|
||||
// Pack rectangles one at a time until we have cleared the rects array of all rectangles.
|
||||
// rects will get destroyed in the process.
|
||||
while(rects.Size() > 0)
|
||||
{
|
||||
// Stores the penalty score of the best rectangle placement - bigger=worse, smaller=better.
|
||||
int bestScore = INT_MAX;
|
||||
|
||||
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
|
||||
{
|
||||
for(unsigned j = 0; j < rects.Size(); ++j)
|
||||
{
|
||||
// If this rectangle is a perfect match, we pick it instantly.
|
||||
if (rects[j].width == freeRectangles[i].width && rects[j].height == freeRectangles[i].height)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = false;
|
||||
bestScore = INT_MIN;
|
||||
i = freeRectangles.Size(); // Force a jump out of the outer loop as well - we got an instant fit.
|
||||
break;
|
||||
}
|
||||
// If flipping this rectangle is a perfect match, pick that then.
|
||||
else if (rects[j].height == freeRectangles[i].width && rects[j].width == freeRectangles[i].height)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = true;
|
||||
bestScore = INT_MIN;
|
||||
i = freeRectangles.Size(); // Force a jump out of the outer loop as well - we got an instant fit.
|
||||
break;
|
||||
}
|
||||
// Try if we can fit the rectangle upright.
|
||||
else if (rects[j].width <= freeRectangles[i].width && rects[j].height <= freeRectangles[i].height)
|
||||
{
|
||||
int score = ScoreByHeuristic(rects[j].width, rects[j].height, freeRectangles[i], rectChoice);
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = false;
|
||||
bestScore = score;
|
||||
}
|
||||
}
|
||||
// If not, then perhaps flipping sideways will make it fit?
|
||||
else if (rects[j].height <= freeRectangles[i].width && rects[j].width <= freeRectangles[i].height)
|
||||
{
|
||||
int score = ScoreByHeuristic(rects[j].height, rects[j].width, freeRectangles[i], rectChoice);
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = true;
|
||||
bestScore = score;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't manage to find any rectangle to pack, abort.
|
||||
if (bestScore == INT_MAX)
|
||||
return;
|
||||
|
||||
// Otherwise, we're good to go and do the actual packing.
|
||||
Rect newNode;
|
||||
newNode.x = freeRectangles[bestFreeRect].x;
|
||||
newNode.y = freeRectangles[bestFreeRect].y;
|
||||
newNode.width = rects[bestRect].width;
|
||||
newNode.height = rects[bestRect].height;
|
||||
|
||||
if (bestFlipped)
|
||||
std::swap(newNode.width, newNode.height);
|
||||
|
||||
// Remove the free space we lost in the bin.
|
||||
SplitFreeRectByHeuristic(freeRectangles[bestFreeRect], newNode, splitMethod);
|
||||
freeRectangles.Delete(bestFreeRect);
|
||||
|
||||
// Remove the rectangle we just packed from the input list.
|
||||
rects.Delete(bestRect);
|
||||
|
||||
// Perform a Rectangle Merge step if desired.
|
||||
if (merge)
|
||||
MergeFreeList();
|
||||
|
||||
// Remember the new used rectangle.
|
||||
usedRectangles.Push(newNode);
|
||||
|
||||
// Check that we're really producing correct packings here.
|
||||
assert(disjointRects.Add(newNode) == true);
|
||||
}
|
||||
}
|
||||
|
||||
/// @return True if r fits inside freeRect (possibly rotated).
|
||||
bool Fits(const RectSize &r, const Rect &freeRect)
|
||||
{
|
||||
return (r.width <= freeRect.width && r.height <= freeRect.height) ||
|
||||
(r.height <= freeRect.width && r.width <= freeRect.height);
|
||||
}
|
||||
|
||||
/// @return True if r fits perfectly inside freeRect, i.e. the leftover area is 0.
|
||||
bool FitsPerfectly(const RectSize &r, const Rect &freeRect)
|
||||
{
|
||||
return (r.width == freeRect.width && r.height == freeRect.height) ||
|
||||
(r.height == freeRect.width && r.width == freeRect.height);
|
||||
}
|
||||
|
||||
/*
|
||||
// A helper function for GUILLOTINE-MAXFITTING. Counts how many rectangles fit into the given rectangle
|
||||
// after it has been split.
|
||||
void CountNumFitting(const Rect &freeRect, int width, int height, const TArray<RectSize> &rects,
|
||||
int usedRectIndex, bool splitHorizontal, int &score1, int &score2)
|
||||
{
|
||||
const int w = freeRect.width - width;
|
||||
const int h = freeRect.height - height;
|
||||
|
||||
Rect bottom;
|
||||
bottom.x = freeRect.x;
|
||||
bottom.y = freeRect.y + height;
|
||||
bottom.height = h;
|
||||
|
||||
Rect right;
|
||||
right.x = freeRect.x + width;
|
||||
right.y = freeRect.y;
|
||||
right.width = w;
|
||||
|
||||
if (splitHorizontal)
|
||||
{
|
||||
bottom.width = freeRect.width;
|
||||
right.height = height;
|
||||
}
|
||||
else // Split vertically
|
||||
{
|
||||
bottom.width = width;
|
||||
right.height = freeRect.height;
|
||||
}
|
||||
|
||||
int fitBottom = 0;
|
||||
int fitRight = 0;
|
||||
for(size_t i = 0; i < rects.size(); ++i)
|
||||
if (i != usedRectIndex)
|
||||
{
|
||||
if (FitsPerfectly(rects[i], bottom))
|
||||
fitBottom |= 0x10000000;
|
||||
if (FitsPerfectly(rects[i], right))
|
||||
fitRight |= 0x10000000;
|
||||
|
||||
if (Fits(rects[i], bottom))
|
||||
++fitBottom;
|
||||
if (Fits(rects[i], right))
|
||||
++fitRight;
|
||||
}
|
||||
|
||||
score1 = min(fitBottom, fitRight);
|
||||
score2 = max(fitBottom, fitRight);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
// Implements GUILLOTINE-MAXFITTING, an experimental heuristic that's really cool but didn't quite work in practice.
|
||||
void GuillotineBinPack::InsertMaxFitting(TArray<RectSize> &rects, TArray<Rect> &dst, bool merge,
|
||||
FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
|
||||
{
|
||||
dst.clear();
|
||||
int bestRect = 0;
|
||||
bool bestFlipped = false;
|
||||
bool bestSplitHorizontal = false;
|
||||
|
||||
// Pick rectangles one at a time and pack the one that leaves the most choices still open.
|
||||
while(rects.size() > 0 && freeRectangles.size() > 0)
|
||||
{
|
||||
int bestScore1 = -1;
|
||||
int bestScore2 = -1;
|
||||
|
||||
///\todo Different sort predicates.
|
||||
clb::sort::QuickSort(&freeRectangles[0], freeRectangles.size(), CompareRectShortSide);
|
||||
|
||||
Rect &freeRect = freeRectangles[0];
|
||||
|
||||
for(size_t j = 0; j < rects.size(); ++j)
|
||||
{
|
||||
int score1;
|
||||
int score2;
|
||||
|
||||
if (rects[j].width == freeRect.width && rects[j].height == freeRect.height)
|
||||
{
|
||||
bestRect = j;
|
||||
bestFlipped = false;
|
||||
bestScore1 = bestScore2 = std::numeric_limits<int>::max();
|
||||
break;
|
||||
}
|
||||
else if (rects[j].width <= freeRect.width && rects[j].height <= freeRect.height)
|
||||
{
|
||||
CountNumFitting(freeRect, rects[j].width, rects[j].height, rects, j, false, score1, score2);
|
||||
|
||||
if (score1 > bestScore1 || (score1 == bestScore1 && score2 > bestScore2))
|
||||
{
|
||||
bestRect = j;
|
||||
bestScore1 = score1;
|
||||
bestScore2 = score2;
|
||||
bestFlipped = false;
|
||||
bestSplitHorizontal = false;
|
||||
}
|
||||
|
||||
CountNumFitting(freeRect, rects[j].width, rects[j].height, rects, j, true, score1, score2);
|
||||
|
||||
if (score1 > bestScore1 || (score1 == bestScore1 && score2 > bestScore2))
|
||||
{
|
||||
bestRect = j;
|
||||
bestScore1 = score1;
|
||||
bestScore2 = score2;
|
||||
bestFlipped = false;
|
||||
bestSplitHorizontal = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rects[j].height == freeRect.width && rects[j].width == freeRect.height)
|
||||
{
|
||||
bestRect = j;
|
||||
bestFlipped = true;
|
||||
bestScore1 = bestScore2 = std::numeric_limits<int>::max();
|
||||
break;
|
||||
}
|
||||
else if (rects[j].height <= freeRect.width && rects[j].width <= freeRect.height)
|
||||
{
|
||||
CountNumFitting(freeRect, rects[j].height, rects[j].width, rects, j, false, score1, score2);
|
||||
|
||||
if (score1 > bestScore1 || (score1 == bestScore1 && score2 > bestScore2))
|
||||
{
|
||||
bestRect = j;
|
||||
bestScore1 = score1;
|
||||
bestScore2 = score2;
|
||||
bestFlipped = true;
|
||||
bestSplitHorizontal = false;
|
||||
}
|
||||
|
||||
CountNumFitting(freeRect, rects[j].height, rects[j].width, rects, j, true, score1, score2);
|
||||
|
||||
if (score1 > bestScore1 || (score1 == bestScore1 && score2 > bestScore2))
|
||||
{
|
||||
bestRect = j;
|
||||
bestScore1 = score1;
|
||||
bestScore2 = score2;
|
||||
bestFlipped = true;
|
||||
bestSplitHorizontal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestScore1 >= 0)
|
||||
{
|
||||
Rect newNode;
|
||||
newNode.x = freeRect.x;
|
||||
newNode.y = freeRect.y;
|
||||
newNode.width = rects[bestRect].width;
|
||||
newNode.height = rects[bestRect].height;
|
||||
if (bestFlipped)
|
||||
std::swap(newNode.width, newNode.height);
|
||||
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
SplitFreeRectAlongAxis(freeRect, newNode, bestSplitHorizontal);
|
||||
|
||||
rects.erase(rects.begin() + bestRect);
|
||||
|
||||
if (merge)
|
||||
MergeFreeList();
|
||||
|
||||
usedRectangles.push_back(newNode);
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Add(newNode);
|
||||
#endif
|
||||
}
|
||||
|
||||
freeRectangles.erase(freeRectangles.begin());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
Rect GuillotineBinPack::Insert(int width, int height, bool merge, FreeRectChoiceHeuristic rectChoice,
|
||||
GuillotineSplitHeuristic splitMethod)
|
||||
{
|
||||
// Find where to put the new rectangle.
|
||||
int freeNodeIndex = 0;
|
||||
Rect newRect = FindPositionForNewNode(width, height, rectChoice, &freeNodeIndex);
|
||||
|
||||
// Abort if we didn't have enough space in the bin.
|
||||
if (newRect.height == 0)
|
||||
return newRect;
|
||||
|
||||
// Remove the space that was just consumed by the new rectangle.
|
||||
SplitFreeRectByHeuristic(freeRectangles[freeNodeIndex], newRect, splitMethod);
|
||||
freeRectangles.Delete(freeNodeIndex);
|
||||
|
||||
// Perform a Rectangle Merge step if desired.
|
||||
if (merge)
|
||||
MergeFreeList();
|
||||
|
||||
// Remember the new used rectangle.
|
||||
usedRectangles.Push(newRect);
|
||||
|
||||
// Check that we're really producing correct packings here.
|
||||
assert(disjointRects.Add(newRect) == true);
|
||||
|
||||
return newRect;
|
||||
}
|
||||
|
||||
/// Computes the ratio of used surface area to the total bin area.
|
||||
float GuillotineBinPack::Occupancy() const
|
||||
{
|
||||
///\todo The occupancy rate could be cached/tracked incrementally instead
|
||||
/// of looping through the list of packed rectangles here.
|
||||
unsigned long usedSurfaceArea = 0;
|
||||
for(unsigned i = 0; i < usedRectangles.Size(); ++i)
|
||||
usedSurfaceArea += usedRectangles[i].width * usedRectangles[i].height;
|
||||
|
||||
return (float)usedSurfaceArea / (binWidth * binHeight);
|
||||
}
|
||||
|
||||
/// Returns the heuristic score value for placing a rectangle of size width*height into freeRect. Does not try to rotate.
|
||||
int GuillotineBinPack::ScoreByHeuristic(int width, int height, const Rect &freeRect, FreeRectChoiceHeuristic rectChoice)
|
||||
{
|
||||
switch(rectChoice)
|
||||
{
|
||||
case RectBestAreaFit: return ScoreBestAreaFit(width, height, freeRect);
|
||||
case RectBestShortSideFit: return ScoreBestShortSideFit(width, height, freeRect);
|
||||
case RectBestLongSideFit: return ScoreBestLongSideFit(width, height, freeRect);
|
||||
case RectWorstAreaFit: return ScoreWorstAreaFit(width, height, freeRect);
|
||||
case RectWorstShortSideFit: return ScoreWorstShortSideFit(width, height, freeRect);
|
||||
case RectWorstLongSideFit: return ScoreWorstLongSideFit(width, height, freeRect);
|
||||
default: assert(false); return INT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
int GuillotineBinPack::ScoreBestAreaFit(int width, int height, const Rect &freeRect)
|
||||
{
|
||||
return freeRect.width * freeRect.height - width * height;
|
||||
}
|
||||
|
||||
int GuillotineBinPack::ScoreBestShortSideFit(int width, int height, const Rect &freeRect)
|
||||
{
|
||||
int leftoverHoriz = abs(freeRect.width - width);
|
||||
int leftoverVert = abs(freeRect.height - height);
|
||||
int leftover = MIN(leftoverHoriz, leftoverVert);
|
||||
return leftover;
|
||||
}
|
||||
|
||||
int GuillotineBinPack::ScoreBestLongSideFit(int width, int height, const Rect &freeRect)
|
||||
{
|
||||
int leftoverHoriz = abs(freeRect.width - width);
|
||||
int leftoverVert = abs(freeRect.height - height);
|
||||
int leftover = MAX(leftoverHoriz, leftoverVert);
|
||||
return leftover;
|
||||
}
|
||||
|
||||
int GuillotineBinPack::ScoreWorstAreaFit(int width, int height, const Rect &freeRect)
|
||||
{
|
||||
return -ScoreBestAreaFit(width, height, freeRect);
|
||||
}
|
||||
|
||||
int GuillotineBinPack::ScoreWorstShortSideFit(int width, int height, const Rect &freeRect)
|
||||
{
|
||||
return -ScoreBestShortSideFit(width, height, freeRect);
|
||||
}
|
||||
|
||||
int GuillotineBinPack::ScoreWorstLongSideFit(int width, int height, const Rect &freeRect)
|
||||
{
|
||||
return -ScoreBestLongSideFit(width, height, freeRect);
|
||||
}
|
||||
|
||||
Rect GuillotineBinPack::FindPositionForNewNode(int width, int height, FreeRectChoiceHeuristic rectChoice, int *nodeIndex)
|
||||
{
|
||||
Rect bestNode;
|
||||
memset(&bestNode, 0, sizeof(Rect));
|
||||
|
||||
int bestScore = INT_MAX;
|
||||
|
||||
/// Try each free rectangle to find the best one for placement.
|
||||
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
|
||||
{
|
||||
// If this is a perfect fit upright, choose it immediately.
|
||||
if (width == freeRectangles[i].width && height == freeRectangles[i].height)
|
||||
{
|
||||
bestNode.x = freeRectangles[i].x;
|
||||
bestNode.y = freeRectangles[i].y;
|
||||
bestNode.width = width;
|
||||
bestNode.height = height;
|
||||
bestScore = INT_MIN;
|
||||
*nodeIndex = i;
|
||||
assert(disjointRects.Disjoint(bestNode));
|
||||
break;
|
||||
}
|
||||
// If this is a perfect fit sideways, choose it.
|
||||
/* else if (height == freeRectangles[i].width && width == freeRectangles[i].height)
|
||||
{
|
||||
bestNode.x = freeRectangles[i].x;
|
||||
bestNode.y = freeRectangles[i].y;
|
||||
bestNode.width = height;
|
||||
bestNode.height = width;
|
||||
bestScore = INT_MIN;
|
||||
*nodeIndex = i;
|
||||
assert(disjointRects.Disjoint(bestNode));
|
||||
break;
|
||||
}
|
||||
*/ // Does the rectangle fit upright?
|
||||
else if (width <= freeRectangles[i].width && height <= freeRectangles[i].height)
|
||||
{
|
||||
int score = ScoreByHeuristic(width, height, freeRectangles[i], rectChoice);
|
||||
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestNode.x = freeRectangles[i].x;
|
||||
bestNode.y = freeRectangles[i].y;
|
||||
bestNode.width = width;
|
||||
bestNode.height = height;
|
||||
bestScore = score;
|
||||
*nodeIndex = i;
|
||||
assert(disjointRects.Disjoint(bestNode));
|
||||
}
|
||||
}
|
||||
// Does the rectangle fit sideways?
|
||||
/* else if (height <= freeRectangles[i].width && width <= freeRectangles[i].height)
|
||||
{
|
||||
int score = ScoreByHeuristic(height, width, freeRectangles[i], rectChoice);
|
||||
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestNode.x = freeRectangles[i].x;
|
||||
bestNode.y = freeRectangles[i].y;
|
||||
bestNode.width = height;
|
||||
bestNode.height = width;
|
||||
bestScore = score;
|
||||
*nodeIndex = i;
|
||||
assert(disjointRects.Disjoint(bestNode));
|
||||
}
|
||||
}
|
||||
*/ }
|
||||
return bestNode;
|
||||
}
|
||||
|
||||
void GuillotineBinPack::SplitFreeRectByHeuristic(const Rect &freeRect, const Rect &placedRect, GuillotineSplitHeuristic method)
|
||||
{
|
||||
// Compute the lengths of the leftover area.
|
||||
const int w = freeRect.width - placedRect.width;
|
||||
const int h = freeRect.height - placedRect.height;
|
||||
|
||||
// Placing placedRect into freeRect results in an L-shaped free area, which must be split into
|
||||
// two disjoint rectangles. This can be achieved with by splitting the L-shape using a single line.
|
||||
// We have two choices: horizontal or vertical.
|
||||
|
||||
// Use the given heuristic to decide which choice to make.
|
||||
|
||||
bool splitHorizontal;
|
||||
switch(method)
|
||||
{
|
||||
case SplitShorterLeftoverAxis:
|
||||
// Split along the shorter leftover axis.
|
||||
splitHorizontal = (w <= h);
|
||||
break;
|
||||
case SplitLongerLeftoverAxis:
|
||||
// Split along the longer leftover axis.
|
||||
splitHorizontal = (w > h);
|
||||
break;
|
||||
case SplitMinimizeArea:
|
||||
// Maximize the larger area == minimize the smaller area.
|
||||
// Tries to make the single bigger rectangle.
|
||||
splitHorizontal = (placedRect.width * h > w * placedRect.height);
|
||||
break;
|
||||
case SplitMaximizeArea:
|
||||
// Maximize the smaller area == minimize the larger area.
|
||||
// Tries to make the rectangles more even-sized.
|
||||
splitHorizontal = (placedRect.width * h <= w * placedRect.height);
|
||||
break;
|
||||
case SplitShorterAxis:
|
||||
// Split along the shorter total axis.
|
||||
splitHorizontal = (freeRect.width <= freeRect.height);
|
||||
break;
|
||||
case SplitLongerAxis:
|
||||
// Split along the longer total axis.
|
||||
splitHorizontal = (freeRect.width > freeRect.height);
|
||||
break;
|
||||
default:
|
||||
splitHorizontal = true;
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// Perform the actual split.
|
||||
SplitFreeRectAlongAxis(freeRect, placedRect, splitHorizontal);
|
||||
}
|
||||
|
||||
/// This function will add the two generated rectangles into the freeRectangles array. The caller is expected to
|
||||
/// remove the original rectangle from the freeRectangles array after that.
|
||||
void GuillotineBinPack::SplitFreeRectAlongAxis(const Rect &freeRect, const Rect &placedRect, bool splitHorizontal)
|
||||
{
|
||||
// Form the two new rectangles.
|
||||
Rect bottom;
|
||||
bottom.x = freeRect.x;
|
||||
bottom.y = freeRect.y + placedRect.height;
|
||||
bottom.height = freeRect.height - placedRect.height;
|
||||
|
||||
Rect right;
|
||||
right.x = freeRect.x + placedRect.width;
|
||||
right.y = freeRect.y;
|
||||
right.width = freeRect.width - placedRect.width;
|
||||
|
||||
if (splitHorizontal)
|
||||
{
|
||||
bottom.width = freeRect.width;
|
||||
right.height = placedRect.height;
|
||||
}
|
||||
else // Split vertically
|
||||
{
|
||||
bottom.width = placedRect.width;
|
||||
right.height = freeRect.height;
|
||||
}
|
||||
|
||||
// Add the new rectangles into the free rectangle pool if they weren't degenerate.
|
||||
if (bottom.width > 0 && bottom.height > 0)
|
||||
freeRectangles.Push(bottom);
|
||||
if (right.width > 0 && right.height > 0)
|
||||
freeRectangles.Push(right);
|
||||
|
||||
assert(disjointRects.Disjoint(bottom));
|
||||
assert(disjointRects.Disjoint(right));
|
||||
}
|
||||
|
||||
void GuillotineBinPack::MergeFreeList()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
DisjointRectCollection test;
|
||||
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
|
||||
assert(test.Add(freeRectangles[i]) == true);
|
||||
#endif
|
||||
|
||||
// Do a Theta(n^2) loop to see if any pair of free rectangles could me merged into one.
|
||||
// Note that we miss any opportunities to merge three rectangles into one. (should call this function again to detect that)
|
||||
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
|
||||
for(unsigned j = i+1; j < freeRectangles.Size(); ++j)
|
||||
{
|
||||
if (freeRectangles[i].width == freeRectangles[j].width && freeRectangles[i].x == freeRectangles[j].x)
|
||||
{
|
||||
if (freeRectangles[i].y == freeRectangles[j].y + freeRectangles[j].height)
|
||||
{
|
||||
freeRectangles[i].y -= freeRectangles[j].height;
|
||||
freeRectangles[i].height += freeRectangles[j].height;
|
||||
freeRectangles.Delete(j);
|
||||
--j;
|
||||
}
|
||||
else if (freeRectangles[i].y + freeRectangles[i].height == freeRectangles[j].y)
|
||||
{
|
||||
freeRectangles[i].height += freeRectangles[j].height;
|
||||
freeRectangles.Delete(j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
else if (freeRectangles[i].height == freeRectangles[j].height && freeRectangles[i].y == freeRectangles[j].y)
|
||||
{
|
||||
if (freeRectangles[i].x == freeRectangles[j].x + freeRectangles[j].width)
|
||||
{
|
||||
freeRectangles[i].x -= freeRectangles[j].width;
|
||||
freeRectangles[i].width += freeRectangles[j].width;
|
||||
freeRectangles.Delete(j);
|
||||
--j;
|
||||
}
|
||||
else if (freeRectangles[i].x + freeRectangles[i].width == freeRectangles[j].x)
|
||||
{
|
||||
freeRectangles[i].width += freeRectangles[j].width;
|
||||
freeRectangles.Delete(j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
test.Clear();
|
||||
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
|
||||
assert(test.Add(freeRectangles[i]) == true);
|
||||
#endif
|
||||
}
|
135
src/GuillotineBinPack.h
Normal file
135
src/GuillotineBinPack.h
Normal file
|
@ -0,0 +1,135 @@
|
|||
/** @file GuillotineBinPack.h
|
||||
@author Jukka Jylänki
|
||||
|
||||
@brief Implements different bin packer algorithms that use the GUILLOTINE data structure.
|
||||
|
||||
This work is released to Public Domain, do whatever you want with it.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "tarray.h"
|
||||
|
||||
#include "Rect.h"
|
||||
|
||||
/** GuillotineBinPack implements different variants of bin packer algorithms that use the GUILLOTINE data structure
|
||||
to keep track of the free space of the bin where rectangles may be placed. */
|
||||
class GuillotineBinPack
|
||||
{
|
||||
public:
|
||||
/// The initial bin size will be (0,0). Call Init to set the bin size.
|
||||
GuillotineBinPack();
|
||||
|
||||
/// Initializes a new bin of the given size.
|
||||
GuillotineBinPack(int width, int height);
|
||||
|
||||
/// (Re)initializes the packer to an empty bin of width x height units. Call whenever
|
||||
/// you need to restart with a new bin.
|
||||
void Init(int width, int height);
|
||||
|
||||
/// Specifies the different choice heuristics that can be used when deciding which of the free subrectangles
|
||||
/// to place the to-be-packed rectangle into.
|
||||
enum FreeRectChoiceHeuristic
|
||||
{
|
||||
RectBestAreaFit, ///< -BAF
|
||||
RectBestShortSideFit, ///< -BSSF
|
||||
RectBestLongSideFit, ///< -BLSF
|
||||
RectWorstAreaFit, ///< -WAF
|
||||
RectWorstShortSideFit, ///< -WSSF
|
||||
RectWorstLongSideFit ///< -WLSF
|
||||
};
|
||||
|
||||
/// Specifies the different choice heuristics that can be used when the packer needs to decide whether to
|
||||
/// subdivide the remaining free space in horizontal or vertical direction.
|
||||
enum GuillotineSplitHeuristic
|
||||
{
|
||||
SplitShorterLeftoverAxis, ///< -SLAS
|
||||
SplitLongerLeftoverAxis, ///< -LLAS
|
||||
SplitMinimizeArea, ///< -MINAS, Try to make a single big rectangle at the expense of making the other small.
|
||||
SplitMaximizeArea, ///< -MAXAS, Try to make both remaining rectangles as even-sized as possible.
|
||||
SplitShorterAxis, ///< -SAS
|
||||
SplitLongerAxis ///< -LAS
|
||||
};
|
||||
|
||||
/// Inserts a single rectangle into the bin. The packer might rotate the rectangle, in which case the returned
|
||||
/// struct will have the width and height values swapped.
|
||||
/// @param merge If true, performs free Rectangle Merge procedure after packing the new rectangle. This procedure
|
||||
/// tries to defragment the list of disjoint free rectangles to improve packing performance, but also takes up
|
||||
/// some extra time.
|
||||
/// @param rectChoice The free rectangle choice heuristic rule to use.
|
||||
/// @param splitMethod The free rectangle split heuristic rule to use.
|
||||
Rect Insert(int width, int height, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod);
|
||||
|
||||
/// Inserts a list of rectangles into the bin.
|
||||
/// @param rects The list of rectangles to add. This list will be destroyed in the packing process.
|
||||
/// @param dst The outputted list of rectangles. Note that the indices will not correspond to the input indices.
|
||||
/// @param merge If true, performs Rectangle Merge operations during the packing process.
|
||||
/// @param rectChoice The free rectangle choice heuristic rule to use.
|
||||
/// @param splitMethod The free rectangle split heuristic rule to use.
|
||||
void Insert(TArray<RectSize> &rects, TArray<Rect> &dst, bool merge,
|
||||
FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod);
|
||||
|
||||
// Implements GUILLOTINE-MAXFITTING, an experimental heuristic that's really cool but didn't quite work in practice.
|
||||
// void InsertMaxFitting(TArray<RectSize> &rects, TArray<Rect> &dst, bool merge,
|
||||
// FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod);
|
||||
|
||||
/// Computes the ratio of used/total surface area. 0.00 means no space is yet used, 1.00 means the whole bin is used.
|
||||
float Occupancy() const;
|
||||
|
||||
/// Returns the internal list of disjoint rectangles that track the free area of the bin. You may alter this vector
|
||||
/// any way desired, as long as the end result still is a list of disjoint rectangles.
|
||||
TArray<Rect> &GetFreeRectangles() { return freeRectangles; }
|
||||
|
||||
/// Returns the list of packed rectangles. You may alter this vector at will, for example, you can move a Rect from
|
||||
/// this list to the Free Rectangles list to free up space on-the-fly, but notice that this causes fragmentation.
|
||||
TArray<Rect> &GetUsedRectangles() { return usedRectangles; }
|
||||
|
||||
/// Performs a Rectangle Merge operation. This procedure looks for adjacent free rectangles and merges them if they
|
||||
/// can be represented with a single rectangle. Takes up Theta(|freeRectangles|^2) time.
|
||||
void MergeFreeList();
|
||||
|
||||
#ifdef _DEBUG
|
||||
void DelDisjoint(const Rect &r) { disjointRects.Del(r); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
int binWidth;
|
||||
int binHeight;
|
||||
|
||||
/// Stores a list of all the rectangles that we have packed so far. This is used only to compute the Occupancy ratio,
|
||||
/// so if you want to have the packer consume less memory, this can be removed.
|
||||
TArray<Rect> usedRectangles;
|
||||
|
||||
/// Stores a list of rectangles that represents the free area of the bin. This rectangles in this list are disjoint.
|
||||
TArray<Rect> freeRectangles;
|
||||
|
||||
#ifdef _DEBUG
|
||||
/// Used to track that the packer produces proper packings.
|
||||
DisjointRectCollection disjointRects;
|
||||
#endif
|
||||
|
||||
/// Goes through the list of free rectangles and finds the best one to place a rectangle of given size into.
|
||||
/// Running time is Theta(|freeRectangles|).
|
||||
/// @param nodeIndex [out] The index of the free rectangle in the freeRectangles array into which the new
|
||||
/// rect was placed.
|
||||
/// @return A Rect structure that represents the placement of the new rect into the best free rectangle.
|
||||
Rect FindPositionForNewNode(int width, int height, FreeRectChoiceHeuristic rectChoice, int *nodeIndex);
|
||||
|
||||
static int ScoreByHeuristic(int width, int height, const Rect &freeRect, FreeRectChoiceHeuristic rectChoice);
|
||||
// The following functions compute (penalty) score values if a rect of the given size was placed into the
|
||||
// given free rectangle. In these score values, smaller is better.
|
||||
|
||||
static int ScoreBestAreaFit(int width, int height, const Rect &freeRect);
|
||||
static int ScoreBestShortSideFit(int width, int height, const Rect &freeRect);
|
||||
static int ScoreBestLongSideFit(int width, int height, const Rect &freeRect);
|
||||
|
||||
static int ScoreWorstAreaFit(int width, int height, const Rect &freeRect);
|
||||
static int ScoreWorstShortSideFit(int width, int height, const Rect &freeRect);
|
||||
static int ScoreWorstLongSideFit(int width, int height, const Rect &freeRect);
|
||||
|
||||
/// Splits the given L-shaped free rectangle into two new free rectangles after placedRect has been placed into it.
|
||||
/// Determines the split axis by using the given heuristic.
|
||||
void SplitFreeRectByHeuristic(const Rect &freeRect, const Rect &placedRect, GuillotineSplitHeuristic method);
|
||||
|
||||
/// Splits the given L-shaped free rectangle into two new free rectangles along the given fixed split axis.
|
||||
void SplitFreeRectAlongAxis(const Rect &freeRect, const Rect &placedRect, bool splitHorizontal);
|
||||
};
|
94
src/Rect.h
Normal file
94
src/Rect.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/** @file Rect.h
|
||||
@author Jukka Jylänki
|
||||
|
||||
This work is released to Public Domain, do whatever you want with it.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct RectSize
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
struct Rect
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
/// Performs a lexicographic compare on (rect short side, rect long side).
|
||||
/// @return -1 if the smaller side of a is shorter than the smaller side of b, 1 if the other way around.
|
||||
/// If they are equal, the larger side length is used as a tie-breaker.
|
||||
/// If the rectangles are of same size, returns 0.
|
||||
int CompareRectShortSide(const Rect &a, const Rect &b);
|
||||
|
||||
/// Performs a lexicographic compare on (x, y, width, height).
|
||||
int NodeSortCmp(const Rect &a, const Rect &b);
|
||||
|
||||
/// Returns true if a is contained in b.
|
||||
bool IsContainedIn(const Rect &a, const Rect &b);
|
||||
|
||||
#ifdef _DEBUG
|
||||
class DisjointRectCollection
|
||||
{
|
||||
public:
|
||||
TArray<Rect> rects;
|
||||
|
||||
bool Add(const Rect &r)
|
||||
{
|
||||
// Degenerate rectangles are ignored.
|
||||
if (r.width == 0 || r.height == 0)
|
||||
return true;
|
||||
|
||||
if (!Disjoint(r))
|
||||
return false;
|
||||
rects.Push(r);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Del(const Rect &r)
|
||||
{
|
||||
for(unsigned i = 0; i < rects.Size(); ++i)
|
||||
{
|
||||
if(r.x == rects[i].x && r.y == rects[i].y && r.width == rects[i].width && r.height == rects[i].height)
|
||||
{
|
||||
rects.Delete(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
rects.Clear();
|
||||
}
|
||||
|
||||
bool Disjoint(const Rect &r) const
|
||||
{
|
||||
// Degenerate rectangles are ignored.
|
||||
if (r.width == 0 || r.height == 0)
|
||||
return true;
|
||||
|
||||
for(unsigned i = 0; i < rects.Size(); ++i)
|
||||
if (!Disjoint(rects[i], r))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Disjoint(const Rect &a, const Rect &b)
|
||||
{
|
||||
if (a.x + a.width <= b.x ||
|
||||
b.x + b.width <= a.x ||
|
||||
a.y + a.height <= b.y ||
|
||||
b.y + b.height <= a.y)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
#endif
|
398
src/SkylineBinPack.cpp
Normal file
398
src/SkylineBinPack.cpp
Normal file
|
@ -0,0 +1,398 @@
|
|||
/** @file SkylineBinPack.cpp
|
||||
@author Jukka Jylänki
|
||||
|
||||
@brief Implements different bin packer algorithms that use the SKYLINE data structure.
|
||||
|
||||
This work is released to Public Domain, do whatever you want with it.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <limits.h>
|
||||
#include "templates.h"
|
||||
|
||||
#include "SkylineBinPack.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
SkylineBinPack::SkylineBinPack()
|
||||
:binWidth(0),
|
||||
binHeight(0)
|
||||
{
|
||||
}
|
||||
|
||||
SkylineBinPack::SkylineBinPack(int width, int height, bool useWasteMap)
|
||||
{
|
||||
Init(width, height, useWasteMap);
|
||||
}
|
||||
|
||||
void SkylineBinPack::Init(int width, int height, bool useWasteMap_)
|
||||
{
|
||||
binWidth = width;
|
||||
binHeight = height;
|
||||
|
||||
useWasteMap = useWasteMap_;
|
||||
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Clear();
|
||||
#endif
|
||||
|
||||
usedSurfaceArea = 0;
|
||||
skyLine.Clear();
|
||||
SkylineNode node;
|
||||
node.x = 0;
|
||||
node.y = 0;
|
||||
node.width = binWidth;
|
||||
skyLine.Push(node);
|
||||
|
||||
if (useWasteMap)
|
||||
{
|
||||
wasteMap.Init(width, height);
|
||||
wasteMap.GetFreeRectangles().Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void SkylineBinPack::Insert(TArray<RectSize> &rects, TArray<Rect> &dst)
|
||||
{
|
||||
dst.Clear();
|
||||
|
||||
while(rects.Size() > 0)
|
||||
{
|
||||
Rect bestNode;
|
||||
int bestScore1 = INT_MAX;
|
||||
int bestScore2 = INT_MAX;
|
||||
int bestSkylineIndex = -1;
|
||||
int bestRectIndex = -1;
|
||||
for(unsigned i = 0; i < rects.Size(); ++i)
|
||||
{
|
||||
Rect newNode;
|
||||
int score1;
|
||||
int score2;
|
||||
int index;
|
||||
newNode = FindPositionForNewNodeMinWaste(rects[i].width, rects[i].height, score2, score1, index);
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
if (newNode.height != 0)
|
||||
{
|
||||
if (score1 < bestScore1 || (score1 == bestScore1 && score2 < bestScore2))
|
||||
{
|
||||
bestNode = newNode;
|
||||
bestScore1 = score1;
|
||||
bestScore2 = score2;
|
||||
bestSkylineIndex = index;
|
||||
bestRectIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestRectIndex == -1)
|
||||
return;
|
||||
|
||||
// Perform the actual packing.
|
||||
assert(disjointRects.Disjoint(bestNode));
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Add(bestNode);
|
||||
#endif
|
||||
AddSkylineLevel(bestSkylineIndex, bestNode);
|
||||
usedSurfaceArea += rects[bestRectIndex].width * rects[bestRectIndex].height;
|
||||
rects.Delete(bestRectIndex);
|
||||
dst.Push(bestNode);
|
||||
}
|
||||
}
|
||||
|
||||
Rect SkylineBinPack::Insert(int width, int height)
|
||||
{
|
||||
// First try to pack this rectangle into the waste map, if it fits.
|
||||
Rect node = wasteMap.Insert(width, height, true, GuillotineBinPack::RectBestShortSideFit,
|
||||
GuillotineBinPack::SplitMaximizeArea);
|
||||
assert(disjointRects.Disjoint(node));
|
||||
|
||||
if (node.height != 0)
|
||||
{
|
||||
Rect newNode;
|
||||
newNode.x = node.x;
|
||||
newNode.y = node.y;
|
||||
newNode.width = node.width;
|
||||
newNode.height = node.height;
|
||||
usedSurfaceArea += width * height;
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Add(newNode);
|
||||
#endif
|
||||
return newNode;
|
||||
}
|
||||
|
||||
return InsertBottomLeft(width, height);
|
||||
}
|
||||
|
||||
bool SkylineBinPack::RectangleFits(int skylineNodeIndex, int width, int height, int &y) const
|
||||
{
|
||||
int x = skyLine[skylineNodeIndex].x;
|
||||
if (x + width > binWidth)
|
||||
return false;
|
||||
int widthLeft = width;
|
||||
int i = skylineNodeIndex;
|
||||
y = skyLine[skylineNodeIndex].y;
|
||||
while(widthLeft > 0)
|
||||
{
|
||||
y = MAX(y, skyLine[i].y);
|
||||
if (y + height > binHeight)
|
||||
return false;
|
||||
widthLeft -= skyLine[i].width;
|
||||
++i;
|
||||
assert(i < (int)skyLine.Size() || widthLeft <= 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int SkylineBinPack::ComputeWastedArea(int skylineNodeIndex, int width, int height, int y) const
|
||||
{
|
||||
int wastedArea = 0;
|
||||
const int rectLeft = skyLine[skylineNodeIndex].x;
|
||||
const int rectRight = rectLeft + width;
|
||||
for(; skylineNodeIndex < (int)skyLine.Size() && skyLine[skylineNodeIndex].x < rectRight; ++skylineNodeIndex)
|
||||
{
|
||||
if (skyLine[skylineNodeIndex].x >= rectRight || skyLine[skylineNodeIndex].x + skyLine[skylineNodeIndex].width <= rectLeft)
|
||||
break;
|
||||
|
||||
int leftSide = skyLine[skylineNodeIndex].x;
|
||||
int rightSide = MIN(rectRight, leftSide + skyLine[skylineNodeIndex].width);
|
||||
assert(y >= skyLine[skylineNodeIndex].y);
|
||||
wastedArea += (rightSide - leftSide) * (y - skyLine[skylineNodeIndex].y);
|
||||
}
|
||||
return wastedArea;
|
||||
}
|
||||
|
||||
bool SkylineBinPack::RectangleFits(int skylineNodeIndex, int width, int height, int &y, int &wastedArea) const
|
||||
{
|
||||
bool fits = RectangleFits(skylineNodeIndex, width, height, y);
|
||||
if (fits)
|
||||
wastedArea = ComputeWastedArea(skylineNodeIndex, width, height, y);
|
||||
|
||||
return fits;
|
||||
}
|
||||
|
||||
void SkylineBinPack::AddWasteMapArea(int skylineNodeIndex, int width, int height, int y)
|
||||
{
|
||||
int wastedArea = 0;
|
||||
const int rectLeft = skyLine[skylineNodeIndex].x;
|
||||
const int rectRight = rectLeft + width;
|
||||
for(; skylineNodeIndex < (int)skyLine.Size() && skyLine[skylineNodeIndex].x < rectRight; ++skylineNodeIndex)
|
||||
{
|
||||
if (skyLine[skylineNodeIndex].x >= rectRight || skyLine[skylineNodeIndex].x + skyLine[skylineNodeIndex].width <= rectLeft)
|
||||
break;
|
||||
|
||||
int leftSide = skyLine[skylineNodeIndex].x;
|
||||
int rightSide = MIN(rectRight, leftSide + skyLine[skylineNodeIndex].width);
|
||||
assert(y >= skyLine[skylineNodeIndex].y);
|
||||
|
||||
Rect waste;
|
||||
waste.x = leftSide;
|
||||
waste.y = skyLine[skylineNodeIndex].y;
|
||||
waste.width = rightSide - leftSide;
|
||||
waste.height = y - skyLine[skylineNodeIndex].y;
|
||||
|
||||
assert(disjointRects.Disjoint(waste));
|
||||
wasteMap.GetFreeRectangles().Push(waste);
|
||||
}
|
||||
}
|
||||
|
||||
void SkylineBinPack::AddWaste(const Rect &waste)
|
||||
{
|
||||
wasteMap.GetFreeRectangles().Push(waste);
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Del(waste);
|
||||
wasteMap.DelDisjoint(waste);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SkylineBinPack::AddSkylineLevel(int skylineNodeIndex, const Rect &rect)
|
||||
{
|
||||
// First track all wasted areas and mark them into the waste map if we're using one.
|
||||
if (useWasteMap)
|
||||
AddWasteMapArea(skylineNodeIndex, rect.width, rect.height, rect.y);
|
||||
|
||||
SkylineNode newNode;
|
||||
newNode.x = rect.x;
|
||||
newNode.y = rect.y + rect.height;
|
||||
newNode.width = rect.width;
|
||||
skyLine.Insert(skylineNodeIndex, newNode);
|
||||
|
||||
assert(newNode.x + newNode.width <= binWidth);
|
||||
assert(newNode.y <= binHeight);
|
||||
|
||||
for(unsigned i = skylineNodeIndex+1; i < skyLine.Size(); ++i)
|
||||
{
|
||||
assert(skyLine[i-1].x <= skyLine[i].x);
|
||||
|
||||
if (skyLine[i].x < skyLine[i-1].x + skyLine[i-1].width)
|
||||
{
|
||||
int shrink = skyLine[i-1].x + skyLine[i-1].width - skyLine[i].x;
|
||||
|
||||
skyLine[i].x += shrink;
|
||||
skyLine[i].width -= shrink;
|
||||
|
||||
if (skyLine[i].width <= 0)
|
||||
{
|
||||
skyLine.Delete(i);
|
||||
--i;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
MergeSkylines();
|
||||
}
|
||||
|
||||
void SkylineBinPack::MergeSkylines()
|
||||
{
|
||||
for(unsigned i = 0; i < skyLine.Size()-1; ++i)
|
||||
if (skyLine[i].y == skyLine[i+1].y)
|
||||
{
|
||||
skyLine[i].width += skyLine[i+1].width;
|
||||
skyLine.Delete(i+1);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
Rect SkylineBinPack::InsertBottomLeft(int width, int height)
|
||||
{
|
||||
int bestHeight;
|
||||
int bestWidth;
|
||||
int bestIndex;
|
||||
Rect newNode = FindPositionForNewNodeBottomLeft(width, height, bestHeight, bestWidth, bestIndex);
|
||||
|
||||
if (bestIndex != -1)
|
||||
{
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
// Perform the actual packing.
|
||||
AddSkylineLevel(bestIndex, newNode);
|
||||
|
||||
usedSurfaceArea += width * height;
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Add(newNode);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
memset(&newNode, 0, sizeof(Rect));
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
Rect SkylineBinPack::FindPositionForNewNodeBottomLeft(int width, int height, int &bestHeight, int &bestWidth, int &bestIndex) const
|
||||
{
|
||||
bestHeight = INT_MAX;
|
||||
bestIndex = -1;
|
||||
// Used to break ties if there are nodes at the same level. Then pick the narrowest one.
|
||||
bestWidth = INT_MAX;
|
||||
Rect newNode = { 0, 0, 0, 0 };
|
||||
for(unsigned i = 0; i < skyLine.Size(); ++i)
|
||||
{
|
||||
int y;
|
||||
if (RectangleFits(i, width, height, y))
|
||||
{
|
||||
if (y + height < bestHeight || (y + height == bestHeight && skyLine[i].width < bestWidth))
|
||||
{
|
||||
bestHeight = y + height;
|
||||
bestIndex = i;
|
||||
bestWidth = skyLine[i].width;
|
||||
newNode.x = skyLine[i].x;
|
||||
newNode.y = y;
|
||||
newNode.width = width;
|
||||
newNode.height = height;
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
}
|
||||
}
|
||||
/* if (RectangleFits(i, height, width, y))
|
||||
{
|
||||
if (y + width < bestHeight || (y + width == bestHeight && skyLine[i].width < bestWidth))
|
||||
{
|
||||
bestHeight = y + width;
|
||||
bestIndex = i;
|
||||
bestWidth = skyLine[i].width;
|
||||
newNode.x = skyLine[i].x;
|
||||
newNode.y = y;
|
||||
newNode.width = height;
|
||||
newNode.height = width;
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
}
|
||||
}
|
||||
*/ }
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
Rect SkylineBinPack::InsertMinWaste(int width, int height)
|
||||
{
|
||||
int bestHeight;
|
||||
int bestWastedArea;
|
||||
int bestIndex;
|
||||
Rect newNode = FindPositionForNewNodeMinWaste(width, height, bestHeight, bestWastedArea, bestIndex);
|
||||
|
||||
if (bestIndex != -1)
|
||||
{
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
// Perform the actual packing.
|
||||
AddSkylineLevel(bestIndex, newNode);
|
||||
|
||||
usedSurfaceArea += width * height;
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Add(newNode);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
memset(&newNode, 0, sizeof(newNode));
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
Rect SkylineBinPack::FindPositionForNewNodeMinWaste(int width, int height, int &bestHeight, int &bestWastedArea, int &bestIndex) const
|
||||
{
|
||||
bestHeight = INT_MAX;
|
||||
bestWastedArea = INT_MAX;
|
||||
bestIndex = -1;
|
||||
Rect newNode;
|
||||
memset(&newNode, 0, sizeof(newNode));
|
||||
for(unsigned i = 0; i < skyLine.Size(); ++i)
|
||||
{
|
||||
int y;
|
||||
int wastedArea;
|
||||
|
||||
if (RectangleFits(i, width, height, y, wastedArea))
|
||||
{
|
||||
if (wastedArea < bestWastedArea || (wastedArea == bestWastedArea && y + height < bestHeight))
|
||||
{
|
||||
bestHeight = y + height;
|
||||
bestWastedArea = wastedArea;
|
||||
bestIndex = i;
|
||||
newNode.x = skyLine[i].x;
|
||||
newNode.y = y;
|
||||
newNode.width = width;
|
||||
newNode.height = height;
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
}
|
||||
}
|
||||
/* if (RectangleFits(i, height, width, y, wastedArea))
|
||||
{
|
||||
if (wastedArea < bestWastedArea || (wastedArea == bestWastedArea && y + width < bestHeight))
|
||||
{
|
||||
bestHeight = y + width;
|
||||
bestWastedArea = wastedArea;
|
||||
bestIndex = i;
|
||||
newNode.x = skyLine[i].x;
|
||||
newNode.y = y;
|
||||
newNode.width = height;
|
||||
newNode.height = width;
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/// Computes the ratio of used surface area.
|
||||
float SkylineBinPack::Occupancy() const
|
||||
{
|
||||
return (float)usedSurfaceArea / (binWidth * binHeight);
|
||||
}
|
91
src/SkylineBinPack.h
Normal file
91
src/SkylineBinPack.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/** @file SkylineBinPack.h
|
||||
@author Jukka Jylänki
|
||||
|
||||
@brief Implements different bin packer algorithms that use the SKYLINE data structure.
|
||||
|
||||
This work is released to Public Domain, do whatever you want with it.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "tarray.h"
|
||||
|
||||
#include "Rect.h"
|
||||
#include "GuillotineBinPack.h"
|
||||
|
||||
/** Implements bin packing algorithms that use the SKYLINE data structure to store the bin contents. Uses
|
||||
GuillotineBinPack as the waste map. */
|
||||
class SkylineBinPack
|
||||
{
|
||||
public:
|
||||
/// Instantiates a bin of size (0,0). Call Init to create a new bin.
|
||||
SkylineBinPack();
|
||||
|
||||
/// Instantiates a bin of the given size.
|
||||
SkylineBinPack(int binWidth, int binHeight, bool useWasteMap);
|
||||
|
||||
/// (Re)initializes the packer to an empty bin of width x height units. Call whenever
|
||||
/// you need to restart with a new bin.
|
||||
void Init(int binWidth, int binHeight, bool useWasteMap);
|
||||
|
||||
/// Inserts the given list of rectangles in an offline/batch mode, possibly rotated.
|
||||
/// @param rects The list of rectangles to insert. This vector will be destroyed in the process.
|
||||
/// @param dst [out] This list will contain the packed rectangles. The indices will not correspond to that of rects.
|
||||
/// @param method The rectangle placement rule to use when packing.
|
||||
void Insert(TArray<RectSize> &rects, TArray<Rect> &dst);
|
||||
|
||||
/// Inserts a single rectangle into the bin, possibly rotated.
|
||||
Rect Insert(int width, int height);
|
||||
|
||||
/// Adds a rectangle to the waste list. It must have been previously returned by
|
||||
/// Insert or the results are undefined.
|
||||
void AddWaste(const Rect &rect);
|
||||
|
||||
/// Computes the ratio of used surface area to the total bin area.
|
||||
float Occupancy() const;
|
||||
|
||||
private:
|
||||
int binWidth;
|
||||
int binHeight;
|
||||
|
||||
#ifdef _DEBUG
|
||||
DisjointRectCollection disjointRects;
|
||||
#endif
|
||||
|
||||
/// Represents a single level (a horizontal line) of the skyline/horizon/envelope.
|
||||
struct SkylineNode
|
||||
{
|
||||
/// The starting x-coordinate (leftmost).
|
||||
int x;
|
||||
|
||||
/// The y-coordinate of the skyline level line.
|
||||
int y;
|
||||
|
||||
/// The line width. The ending coordinate (inclusive) will be x+width-1.
|
||||
int width;
|
||||
};
|
||||
|
||||
TArray<SkylineNode> skyLine;
|
||||
|
||||
unsigned long usedSurfaceArea;
|
||||
|
||||
/// If true, we use the GuillotineBinPack structure to recover wasted areas into a waste map.
|
||||
bool useWasteMap;
|
||||
GuillotineBinPack wasteMap;
|
||||
|
||||
Rect InsertBottomLeft(int width, int height);
|
||||
Rect InsertMinWaste(int width, int height);
|
||||
|
||||
Rect FindPositionForNewNodeBottomLeft(int width, int height, int &bestHeight, int &bestWidth, int &bestIndex) const;
|
||||
Rect FindPositionForNewNodeMinWaste(int width, int height, int &bestHeight, int &bestWastedArea, int &bestIndex) const;
|
||||
|
||||
bool RectangleFits(int skylineNodeIndex, int width, int height, int &y) const;
|
||||
bool RectangleFits(int skylineNodeIndex, int width, int height, int &y, int &wastedArea) const;
|
||||
int ComputeWastedArea(int skylineNodeIndex, int width, int height, int y) const;
|
||||
|
||||
void AddWasteMapArea(int skylineNodeIndex, int width, int height, int y);
|
||||
|
||||
void AddSkylineLevel(int skylineNodeIndex, const Rect &rect);
|
||||
|
||||
/// Merges all skyline nodes that are at the same level.
|
||||
void MergeSkylines();
|
||||
};
|
160
src/actor.h
160
src/actor.h
|
@ -569,6 +569,36 @@ struct line_t;
|
|||
struct secplane_t;
|
||||
struct FStrifeDialogueNode;
|
||||
|
||||
struct fixedvec3
|
||||
{
|
||||
fixed_t x, y, z;
|
||||
|
||||
operator FVector3()
|
||||
{
|
||||
return FVector3(FIXED2FLOAT(x), FIXED2FLOAT(y), FIXED2FLOAT(z));
|
||||
}
|
||||
|
||||
operator TVector3<double>()
|
||||
{
|
||||
return TVector3<double>(FIXED2DBL(x), FIXED2DBL(y), FIXED2DBL(z));
|
||||
}
|
||||
};
|
||||
|
||||
struct fixedvec2
|
||||
{
|
||||
fixed_t x, y;
|
||||
|
||||
operator FVector2()
|
||||
{
|
||||
return FVector2(FIXED2FLOAT(x), FIXED2FLOAT(y));
|
||||
}
|
||||
|
||||
operator TVector2<double>()
|
||||
{
|
||||
return TVector2<double>(FIXED2DBL(x), FIXED2DBL(y));
|
||||
}
|
||||
};
|
||||
|
||||
class DDropItem : public DObject
|
||||
{
|
||||
DECLARE_CLASS(DDropItem, DObject)
|
||||
|
@ -580,6 +610,10 @@ public:
|
|||
int Amount;
|
||||
};
|
||||
|
||||
fixed_t P_AproxDistance (fixed_t dx, fixed_t dy); // since we cannot include p_local here...
|
||||
angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2); // same reason here with r_defs.h
|
||||
|
||||
|
||||
// Map Object definition.
|
||||
class AActor : public DThinker
|
||||
{
|
||||
|
@ -823,6 +857,90 @@ public:
|
|||
return bloodcls;
|
||||
}
|
||||
|
||||
// 'absolute' is reserved for a linked portal implementation which needs
|
||||
// to distinguish between portal-aware and portal-unaware distance calculation.
|
||||
fixed_t AproxDistance(AActor *other, bool absolute = false)
|
||||
{
|
||||
return P_AproxDistance(x - other->x, y - other->y);
|
||||
}
|
||||
|
||||
// same with 'ref' here.
|
||||
fixed_t AproxDistance(fixed_t otherx, fixed_t othery, AActor *ref = NULL)
|
||||
{
|
||||
return P_AproxDistance(x - otherx, y - othery);
|
||||
}
|
||||
|
||||
fixed_t AproxDistance(AActor *other, fixed_t xadd, fixed_t yadd, bool absolute = false)
|
||||
{
|
||||
return P_AproxDistance(x - other->x + xadd, y - other->y + yadd);
|
||||
}
|
||||
|
||||
fixed_t AproxDistance3D(AActor *other, bool absolute = false)
|
||||
{
|
||||
return P_AproxDistance(AproxDistance(other), z - other->z);
|
||||
}
|
||||
|
||||
// more precise, but slower version, being used in a few places
|
||||
fixed_t Distance2D(AActor *other, bool absolute = false)
|
||||
{
|
||||
return xs_RoundToInt(FVector2(x - other->x, y - other->y).Length());
|
||||
}
|
||||
|
||||
// a full 3D version of the above
|
||||
fixed_t Distance3D(AActor *other, bool absolute = false)
|
||||
{
|
||||
return xs_RoundToInt(FVector3(x - other->x, y - other->y, z - other->z).Length());
|
||||
}
|
||||
|
||||
angle_t AngleTo(AActor *other, bool absolute = false) const
|
||||
{
|
||||
return R_PointToAngle2(x, y, other->x, other->y);
|
||||
}
|
||||
|
||||
angle_t AngleTo(AActor *other, fixed_t oxofs, fixed_t oyofs, bool absolute = false) const
|
||||
{
|
||||
return R_PointToAngle2(x, y, other->x + oxofs, other->y + oyofs);
|
||||
}
|
||||
|
||||
fixed_t AngleTo(fixed_t otherx, fixed_t othery, AActor *ref = NULL)
|
||||
{
|
||||
return R_PointToAngle2(x, y, otherx, othery);
|
||||
}
|
||||
|
||||
fixed_t AngleXYTo(fixed_t myx, fixed_t myy, AActor *other, bool absolute = false)
|
||||
{
|
||||
return R_PointToAngle2(myx, myy, other->x, other->y);
|
||||
}
|
||||
|
||||
fixedvec2 Vec2To(AActor *other) const
|
||||
{
|
||||
fixedvec2 ret = { other->x - x, other->y - y };
|
||||
return ret;
|
||||
}
|
||||
|
||||
fixedvec3 Vec3To(AActor *other) const
|
||||
{
|
||||
fixedvec3 ret = { other->x - x, other->y - y, other->z - z };
|
||||
return ret;
|
||||
}
|
||||
|
||||
fixedvec2 Vec2Offset(fixed_t dx, fixed_t dy) const
|
||||
{
|
||||
fixedvec2 ret = { x + dx, y + dy };
|
||||
return ret;
|
||||
}
|
||||
|
||||
fixedvec3 Vec3Offset(fixed_t dx, fixed_t dy, fixed_t dz) const
|
||||
{
|
||||
fixedvec3 ret = { x + dx, y + dy, z + dz };
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Move(fixed_t dx, fixed_t dy, fixed_t dz)
|
||||
{
|
||||
SetOrigin(x + dx, y + dy, z + dz, true);
|
||||
}
|
||||
|
||||
inline void SetFriendPlayer(player_t *player);
|
||||
|
||||
bool IsVisibleToPlayer() const;
|
||||
|
@ -866,6 +984,7 @@ public:
|
|||
|
||||
struct sector_t *floorsector;
|
||||
FTextureID floorpic; // contacted sec floorpic
|
||||
int floorterrain;
|
||||
struct sector_t *ceilingsector;
|
||||
FTextureID ceilingpic; // contacted sec ceilingpic
|
||||
fixed_t radius, height; // for movement checking
|
||||
|
@ -1039,7 +1158,7 @@ public:
|
|||
void LinkToWorld (sector_t *sector);
|
||||
void UnlinkFromWorld ();
|
||||
void AdjustFloorClip ();
|
||||
void SetOrigin (fixed_t x, fixed_t y, fixed_t z);
|
||||
void SetOrigin (fixed_t x, fixed_t y, fixed_t z, bool moving = false);
|
||||
bool InStateSequence(FState * newstate, FState * basestate);
|
||||
int GetTics(FState * newstate);
|
||||
bool SetState (FState *newstate, bool nofunction=false);
|
||||
|
@ -1068,6 +1187,24 @@ public:
|
|||
}
|
||||
|
||||
bool HasSpecialDeathStates () const;
|
||||
|
||||
fixed_t X() const
|
||||
{
|
||||
return x;
|
||||
}
|
||||
fixed_t Y() const
|
||||
{
|
||||
return y;
|
||||
}
|
||||
fixed_t Z() const
|
||||
{
|
||||
return z;
|
||||
}
|
||||
void SetZ(fixed_t newz)
|
||||
{
|
||||
z = newz;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class FActorIterator
|
||||
|
@ -1140,15 +1277,36 @@ inline AActor *Spawn (PClassActor *type, fixed_t x, fixed_t y, fixed_t z, replac
|
|||
{
|
||||
return AActor::StaticSpawn (type, x, y, z, allowreplacement);
|
||||
}
|
||||
inline AActor *Spawn (PClassActor *type, const fixedvec3 &pos, replace_t allowreplacement)
|
||||
{
|
||||
return AActor::StaticSpawn (type, pos.x, pos.y, pos.z, allowreplacement);
|
||||
}
|
||||
|
||||
AActor *Spawn (const char *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement);
|
||||
AActor *Spawn (FName classname, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement);
|
||||
|
||||
inline AActor *Spawn (const char *type, const fixedvec3 &pos, replace_t allowreplacement)
|
||||
{
|
||||
return Spawn (type, pos.x, pos.y, pos.z, allowreplacement);
|
||||
}
|
||||
|
||||
inline AActor *Spawn (FName classname, const fixedvec3 &pos, replace_t allowreplacement)
|
||||
{
|
||||
return Spawn (classname, pos.x, pos.y, pos.z, allowreplacement);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline T *Spawn (fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement)
|
||||
{
|
||||
return static_cast<T *>(AActor::StaticSpawn (RUNTIME_TEMPLATE_CLASS(T), x, y, z, allowreplacement));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T *Spawn (const fixedvec3 &pos, replace_t allowreplacement)
|
||||
{
|
||||
return static_cast<T *>(AActor::StaticSpawn (RUNTIME_CLASS(T), pos.x, pos.y, pos.z, allowreplacement));
|
||||
}
|
||||
|
||||
void PrintMiscActorInfo(AActor * query);
|
||||
|
||||
|
|
|
@ -998,8 +998,8 @@ void AM_restoreScaleAndLoc ()
|
|||
}
|
||||
else
|
||||
{
|
||||
m_x = (players[consoleplayer].camera->x >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (players[consoleplayer].camera->y >> FRACTOMAPBITS)- m_h/2;
|
||||
m_x = (players[consoleplayer].camera->X() >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (players[consoleplayer].camera->Y() >> FRACTOMAPBITS)- m_h/2;
|
||||
}
|
||||
m_x2 = m_x + m_w;
|
||||
m_y2 = m_y + m_h;
|
||||
|
@ -1249,8 +1249,8 @@ void AM_initVariables ()
|
|||
if (playeringame[pnum])
|
||||
break;
|
||||
assert(pnum >= 0 && pnum < MAXPLAYERS);
|
||||
m_x = (players[pnum].camera->x >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (players[pnum].camera->y >> FRACTOMAPBITS) - m_h/2;
|
||||
m_x = (players[pnum].camera->X() >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (players[pnum].camera->Y() >> FRACTOMAPBITS) - m_h/2;
|
||||
AM_changeWindowLoc();
|
||||
|
||||
// for saving & restoring
|
||||
|
@ -1571,25 +1571,25 @@ void AM_doFollowPlayer ()
|
|||
fixed_t sx, sy;
|
||||
|
||||
if (players[consoleplayer].camera != NULL &&
|
||||
(f_oldloc.x != players[consoleplayer].camera->x ||
|
||||
f_oldloc.y != players[consoleplayer].camera->y))
|
||||
(f_oldloc.x != players[consoleplayer].camera->X() ||
|
||||
f_oldloc.y != players[consoleplayer].camera->Y()))
|
||||
{
|
||||
m_x = (players[consoleplayer].camera->x >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (players[consoleplayer].camera->y >> FRACTOMAPBITS) - m_h/2;
|
||||
m_x = (players[consoleplayer].camera->X() >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (players[consoleplayer].camera->Y() >> FRACTOMAPBITS) - m_h/2;
|
||||
m_x2 = m_x + m_w;
|
||||
m_y2 = m_y + m_h;
|
||||
|
||||
// do the parallax parchment scrolling.
|
||||
sx = (players[consoleplayer].camera->x - f_oldloc.x) >> FRACTOMAPBITS;
|
||||
sy = (f_oldloc.y - players[consoleplayer].camera->y) >> FRACTOMAPBITS;
|
||||
sx = (players[consoleplayer].camera->X() - f_oldloc.x) >> FRACTOMAPBITS;
|
||||
sy = (f_oldloc.y - players[consoleplayer].camera->Y()) >> FRACTOMAPBITS;
|
||||
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
|
||||
{
|
||||
AM_rotate (&sx, &sy, players[consoleplayer].camera->angle - ANG90);
|
||||
}
|
||||
AM_ScrollParchment (sx, sy);
|
||||
|
||||
f_oldloc.x = players[consoleplayer].camera->x;
|
||||
f_oldloc.y = players[consoleplayer].camera->y;
|
||||
f_oldloc.x = players[consoleplayer].camera->X();
|
||||
f_oldloc.y = players[consoleplayer].camera->Y();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2071,17 +2071,17 @@ static bool AM_CheckSecret(line_t *line)
|
|||
{
|
||||
if (line->frontsector != NULL)
|
||||
{
|
||||
if (line->frontsector->secretsector)
|
||||
if (line->frontsector->wasSecret())
|
||||
{
|
||||
if (am_map_secrets!=0 && !(line->frontsector->special&SECRET_MASK)) return true;
|
||||
if (am_map_secrets!=0 && !line->frontsector->isSecret()) return true;
|
||||
if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true;
|
||||
}
|
||||
}
|
||||
if (line->backsector != NULL)
|
||||
{
|
||||
if (line->backsector->secretsector)
|
||||
if (line->backsector->wasSecret())
|
||||
{
|
||||
if (am_map_secrets!=0 && !(line->backsector->special&SECRET_MASK)) return true;
|
||||
if (am_map_secrets!=0 && !line->backsector->isSecret()) return true;
|
||||
if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true;
|
||||
}
|
||||
}
|
||||
|
@ -2612,8 +2612,8 @@ void AM_drawPlayers ()
|
|||
mline_t *arrow;
|
||||
int numarrowlines;
|
||||
|
||||
pt.x = players[consoleplayer].camera->x >> FRACTOMAPBITS;
|
||||
pt.y = players[consoleplayer].camera->y >> FRACTOMAPBITS;
|
||||
pt.x = players[consoleplayer].camera->X() >> FRACTOMAPBITS;
|
||||
pt.y = players[consoleplayer].camera->Y() >> FRACTOMAPBITS;
|
||||
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
|
||||
{
|
||||
angle = ANG90;
|
||||
|
@ -2675,8 +2675,8 @@ void AM_drawPlayers ()
|
|||
|
||||
if (p->mo != NULL)
|
||||
{
|
||||
pt.x = p->mo->x >> FRACTOMAPBITS;
|
||||
pt.y = p->mo->y >> FRACTOMAPBITS;
|
||||
pt.x = p->mo->X() >> FRACTOMAPBITS;
|
||||
pt.y = p->mo->Y() >> FRACTOMAPBITS;
|
||||
angle = p->mo->angle;
|
||||
|
||||
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
|
||||
|
@ -2707,8 +2707,8 @@ void AM_drawKeys ()
|
|||
|
||||
while ((key = it.Next()) != NULL)
|
||||
{
|
||||
p.x = key->x >> FRACTOMAPBITS;
|
||||
p.y = key->y >> FRACTOMAPBITS;
|
||||
p.x = key->X() >> FRACTOMAPBITS;
|
||||
p.y = key->Y() >> FRACTOMAPBITS;
|
||||
angle = key->angle;
|
||||
|
||||
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
|
||||
|
@ -2752,8 +2752,8 @@ void AM_drawThings ()
|
|||
{
|
||||
if (am_cheat > 0 || !(t->flags6 & MF6_NOTONAUTOMAP))
|
||||
{
|
||||
p.x = t->x >> FRACTOMAPBITS;
|
||||
p.y = t->y >> FRACTOMAPBITS;
|
||||
p.x = t->X() >> FRACTOMAPBITS;
|
||||
p.y = t->Y() >> FRACTOMAPBITS;
|
||||
|
||||
if (am_showthingsprites > 0 && t->sprite > 0)
|
||||
{
|
||||
|
@ -2979,7 +2979,7 @@ void AM_drawAuthorMarkers ()
|
|||
marked->subsector->flags & SSECF_DRAWN :
|
||||
marked->Sector->MoreFlags & SECF_DRAWN)))
|
||||
{
|
||||
DrawMarker (tex, marked->x >> FRACTOMAPBITS, marked->y >> FRACTOMAPBITS, 0,
|
||||
DrawMarker (tex, marked->X() >> FRACTOMAPBITS, marked->Y() >> FRACTOMAPBITS, 0,
|
||||
flip, mark->scaleX, mark->scaleY, mark->Translation,
|
||||
mark->alpha, mark->fillcolor, mark->RenderStyle);
|
||||
}
|
||||
|
|
|
@ -30,17 +30,17 @@ bool DBot::Reachable (AActor *rtarget)
|
|||
if (player->mo == rtarget)
|
||||
return false;
|
||||
|
||||
if ((rtarget->Sector->ceilingplane.ZatPoint (rtarget->x, rtarget->y) -
|
||||
rtarget->Sector->floorplane.ZatPoint (rtarget->x, rtarget->y))
|
||||
if ((rtarget->Sector->ceilingplane.ZatPoint (rtarget) -
|
||||
rtarget->Sector->floorplane.ZatPoint (rtarget))
|
||||
< player->mo->height) //Where rtarget is, player->mo can't be.
|
||||
return false;
|
||||
|
||||
sector_t *last_s = player->mo->Sector;
|
||||
fixed_t last_z = last_s->floorplane.ZatPoint (player->mo->x, player->mo->y);
|
||||
fixed_t estimated_dist = P_AproxDistance (player->mo->x - rtarget->x, player->mo->y - rtarget->y);
|
||||
fixed_t last_z = last_s->floorplane.ZatPoint (player->mo);
|
||||
fixed_t estimated_dist = player->mo->AproxDistance(rtarget);
|
||||
bool reachable = true;
|
||||
|
||||
FPathTraverse it(player->mo->x+player->mo->velx, player->mo->y+player->mo->vely, rtarget->x, rtarget->y, PT_ADDLINES|PT_ADDTHINGS);
|
||||
FPathTraverse it(player->mo->X()+player->mo->velx, player->mo->Y()+player->mo->vely, rtarget->X(), rtarget->Y(), PT_ADDLINES|PT_ADDTHINGS);
|
||||
intercept_t *in;
|
||||
while ((in = it.Next()))
|
||||
{
|
||||
|
@ -96,7 +96,7 @@ bool DBot::Reachable (AActor *rtarget)
|
|||
thing = in->d.thing;
|
||||
if (thing == player->mo) //Can't reach self in this case.
|
||||
continue;
|
||||
if (thing == rtarget && (rtarget->Sector->floorplane.ZatPoint (rtarget->x, rtarget->y) <= (last_z+MAXMOVEHEIGHT)))
|
||||
if (thing == rtarget && (rtarget->Sector->floorplane.ZatPoint (rtarget) <= (last_z+MAXMOVEHEIGHT)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ bool DBot::Check_LOS (AActor *to, angle_t vangle)
|
|||
if (vangle == 0)
|
||||
return false; //Looker seems to be blind.
|
||||
|
||||
return absangle(R_PointToAngle2 (player->mo->x, player->mo->y, to->x, to->y) - player->mo->angle) <= vangle/2;
|
||||
return absangle(player->mo->AngleTo(to) - player->mo->angle) <= vangle/2;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
@ -165,10 +165,8 @@ void DBot::Dofire (ticcmd_t *cmd)
|
|||
//MAKEME: Decrease the rocket suicides even more.
|
||||
|
||||
no_fire = true;
|
||||
//angle = R_PointToAngle2(player->mo->x, player->mo->y, player->enemy->x, player->enemy->y);
|
||||
//Distance to enemy.
|
||||
dist = P_AproxDistance ((player->mo->x + player->mo->velx) - (enemy->x + enemy->velx),
|
||||
(player->mo->y + player->mo->vely) - (enemy->y + enemy->vely));
|
||||
dist = player->mo->AproxDistance(enemy, player->mo->velx - enemy->velx, player->mo->vely - enemy->vely);
|
||||
|
||||
//FIRE EACH TYPE OF WEAPON DIFFERENT: Here should all the different weapons go.
|
||||
if (player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON)
|
||||
|
@ -219,17 +217,17 @@ void DBot::Dofire (ticcmd_t *cmd)
|
|||
}
|
||||
// prediction aiming
|
||||
shootmissile:
|
||||
dist = P_AproxDistance (player->mo->x - enemy->x, player->mo->y - enemy->y);
|
||||
dist = player->mo->AproxDistance (enemy);
|
||||
m = dist / GetDefaultByType (player->ReadyWeapon->ProjectileType)->Speed;
|
||||
bglobal.SetBodyAt (enemy->x + enemy->velx*m*2, enemy->y + enemy->vely*m*2, enemy->z, 1);
|
||||
angle = R_PointToAngle2 (player->mo->x, player->mo->y, bglobal.body1->x, bglobal.body1->y);
|
||||
bglobal.SetBodyAt (enemy->X() + enemy->velx*m*2, enemy->Y() + enemy->vely*m*2, enemy->Z(), 1);
|
||||
angle = player->mo->AngleTo(bglobal.body1);
|
||||
if (Check_LOS (enemy, SHOOTFOV))
|
||||
no_fire = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Other weapons, mostly instant hit stuff.
|
||||
angle = R_PointToAngle2 (player->mo->x, player->mo->y, enemy->x, enemy->y);
|
||||
angle = player->mo->AngleTo(enemy);
|
||||
aiming_penalty = 0;
|
||||
if (enemy->flags & MF_SHADOW)
|
||||
aiming_penalty += (pr_botdofire()%25)+10;
|
||||
|
@ -265,7 +263,6 @@ shootmissile:
|
|||
cmd->ucmd.buttons |= BT_ATTACK;
|
||||
}
|
||||
//Prevents bot from jerking, when firing automatic things with low skill.
|
||||
//player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->enemy->x, player->enemy->y);
|
||||
}
|
||||
|
||||
bool FCajunMaster::IsLeader (player_t *player)
|
||||
|
@ -331,8 +328,7 @@ AActor *DBot::Choose_Mate ()
|
|||
{
|
||||
if (P_CheckSight (player->mo, client->mo, SF_IGNOREVISIBILITY))
|
||||
{
|
||||
test = P_AproxDistance (client->mo->x - player->mo->x,
|
||||
client->mo->y - player->mo->y);
|
||||
test = client->mo->AproxDistance(player->mo);
|
||||
|
||||
if (test < closest_dist)
|
||||
{
|
||||
|
@ -402,8 +398,7 @@ AActor *DBot::Find_enemy ()
|
|||
if (Check_LOS (client->mo, vangle)) //Here's a strange one, when bot is standing still, the P_CheckSight within Check_LOS almost always returns false. tought it should be the same checksight as below but.. (below works) something must be fuckin wierd screded up.
|
||||
//if(P_CheckSight(player->mo, players[count].mo))
|
||||
{
|
||||
temp = P_AproxDistance (client->mo->x - player->mo->x,
|
||||
client->mo->y - player->mo->y);
|
||||
temp = client->mo->AproxDistance(player->mo);
|
||||
|
||||
//Too dark?
|
||||
if (temp > DARK_DIST &&
|
||||
|
@ -432,7 +427,7 @@ void FCajunMaster::SetBodyAt (fixed_t x, fixed_t y, fixed_t z, int hostnum)
|
|||
{
|
||||
if (body1)
|
||||
{
|
||||
body1->SetOrigin (x, y, z);
|
||||
body1->SetOrigin (x, y, z, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -443,7 +438,7 @@ void FCajunMaster::SetBodyAt (fixed_t x, fixed_t y, fixed_t z, int hostnum)
|
|||
{
|
||||
if (body2)
|
||||
{
|
||||
body2->SetOrigin (x, y, z);
|
||||
body2->SetOrigin (x, y, z, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -464,16 +459,13 @@ void FCajunMaster::SetBodyAt (fixed_t x, fixed_t y, fixed_t z, int hostnum)
|
|||
//Emulates missile travel. Returns distance travelled.
|
||||
fixed_t FCajunMaster::FakeFire (AActor *source, AActor *dest, ticcmd_t *cmd)
|
||||
{
|
||||
AActor *th = Spawn ("CajunTrace", source->x, source->y, source->z + 4*8*FRACUNIT, NO_REPLACE);
|
||||
AActor *th = Spawn ("CajunTrace", source->X(), source->Y(), source->Z() + 4*8*FRACUNIT, NO_REPLACE);
|
||||
|
||||
th->target = source; // where it came from
|
||||
|
||||
float speed = (float)th->Speed;
|
||||
|
||||
FVector3 velocity;
|
||||
velocity[0] = FIXED2FLOAT(dest->x - source->x);
|
||||
velocity[1] = FIXED2FLOAT(dest->y - source->y);
|
||||
velocity[2] = FIXED2FLOAT(dest->z - source->z);
|
||||
TVector3<double> velocity = source->Vec3To(dest);
|
||||
velocity.MakeUnit();
|
||||
th->velx = FLOAT2FIXED(velocity[0] * speed);
|
||||
th->vely = FLOAT2FIXED(velocity[1] * speed);
|
||||
|
@ -484,8 +476,8 @@ fixed_t FCajunMaster::FakeFire (AActor *source, AActor *dest, ticcmd_t *cmd)
|
|||
while (dist < SAFE_SELF_MISDIST)
|
||||
{
|
||||
dist += th->Speed;
|
||||
th->SetOrigin (th->x + th->velx, th->y + th->vely, th->z + th->velz);
|
||||
if (!CleanAhead (th, th->x, th->y, cmd))
|
||||
th->Move(th->velx, th->vely, th->velz);
|
||||
if (!CleanAhead (th, th->X(), th->Y(), cmd))
|
||||
break;
|
||||
}
|
||||
th->Destroy ();
|
||||
|
@ -499,30 +491,30 @@ angle_t DBot::FireRox (AActor *enemy, ticcmd_t *cmd)
|
|||
AActor *actor;
|
||||
int m;
|
||||
|
||||
bglobal.SetBodyAt (player->mo->x + FixedMul(player->mo->velx, 5*FRACUNIT),
|
||||
player->mo->y + FixedMul(player->mo->vely, 5*FRACUNIT),
|
||||
player->mo->z + (player->mo->height / 2), 2);
|
||||
bglobal.SetBodyAt (player->mo->X() + FixedMul(player->mo->velx, 5*FRACUNIT),
|
||||
player->mo->Y() + FixedMul(player->mo->vely, 5*FRACUNIT),
|
||||
player->mo->Z() + (player->mo->height / 2), 2);
|
||||
|
||||
actor = bglobal.body2;
|
||||
|
||||
dist = P_AproxDistance (actor->x-enemy->x, actor->y-enemy->y);
|
||||
dist = actor->AproxDistance (enemy);
|
||||
if (dist < SAFE_SELF_MISDIST)
|
||||
return 0;
|
||||
//Predict.
|
||||
m = (((dist+1)/FRACUNIT) / GetDefaultByName("Rocket")->Speed);
|
||||
|
||||
bglobal.SetBodyAt (enemy->x + FixedMul(enemy->velx, (m+2*FRACUNIT)),
|
||||
enemy->y + FixedMul(enemy->vely, (m+2*FRACUNIT)), ONFLOORZ, 1);
|
||||
bglobal.SetBodyAt (enemy->X() + FixedMul(enemy->velx, (m+2*FRACUNIT)),
|
||||
enemy->Y() + FixedMul(enemy->vely, (m+2*FRACUNIT)), ONFLOORZ, 1);
|
||||
|
||||
//try the predicted location
|
||||
if (P_CheckSight (actor, bglobal.body1, SF_IGNOREVISIBILITY)) //See the predicted location, so give a test missile
|
||||
{
|
||||
FCheckPosition tm;
|
||||
if (bglobal.SafeCheckPosition (player->mo, actor->x, actor->y, tm))
|
||||
if (bglobal.SafeCheckPosition (player->mo, actor->X(), actor->Y(), tm))
|
||||
{
|
||||
if (bglobal.FakeFire (actor, bglobal.body1, cmd) >= SAFE_SELF_MISDIST)
|
||||
{
|
||||
ang = R_PointToAngle2 (actor->x, actor->y, bglobal.body1->x, bglobal.body1->y);
|
||||
ang = actor->AngleTo(bglobal.body1);
|
||||
return ang;
|
||||
}
|
||||
}
|
||||
|
@ -532,7 +524,7 @@ angle_t DBot::FireRox (AActor *enemy, ticcmd_t *cmd)
|
|||
{
|
||||
if (bglobal.FakeFire (player->mo, enemy, cmd) >= SAFE_SELF_MISDIST)
|
||||
{
|
||||
ang = R_PointToAngle2(player->mo->x, player->mo->y, enemy->x, enemy->y);
|
||||
ang = player->mo->AngleTo(enemy);
|
||||
return ang;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -423,8 +423,8 @@ void FCajunMaster::RemoveAllBots (bool fromlist)
|
|||
}
|
||||
}
|
||||
}
|
||||
FBehavior::StaticStartTypedScripts (SCRIPT_Disconnect, players[i].mo, true, i, true);
|
||||
ClearPlayer (i, !fromlist);
|
||||
FBehavior::StaticStartTypedScripts (SCRIPT_Disconnect, NULL, true, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ void DBot::Roam (ticcmd_t *cmd)
|
|||
|
||||
if (Reachable(dest))
|
||||
{ // Straight towards it.
|
||||
angle = R_PointToAngle2(player->mo->x, player->mo->y, dest->x, dest->y);
|
||||
angle = player->mo->AngleTo(dest);
|
||||
}
|
||||
else if (player->mo->movedir < 8) // turn towards movement direction if not there yet
|
||||
{
|
||||
|
@ -67,8 +67,8 @@ bool DBot::Move (ticcmd_t *cmd)
|
|||
if ((unsigned)player->mo->movedir >= 8)
|
||||
I_Error ("Weird bot movedir!");
|
||||
|
||||
tryx = player->mo->x + 8*xspeed[player->mo->movedir];
|
||||
tryy = player->mo->y + 8*yspeed[player->mo->movedir];
|
||||
tryx = player->mo->X() + 8*xspeed[player->mo->movedir];
|
||||
tryy = player->mo->Y() + 8*yspeed[player->mo->movedir];
|
||||
|
||||
try_ok = bglobal.CleanAhead (player->mo, tryx, tryy, cmd);
|
||||
|
||||
|
@ -124,9 +124,6 @@ bool DBot::TryWalk (ticcmd_t *cmd)
|
|||
|
||||
void DBot::NewChaseDir (ticcmd_t *cmd)
|
||||
{
|
||||
fixed_t deltax;
|
||||
fixed_t deltay;
|
||||
|
||||
dirtype_t d[3];
|
||||
|
||||
int tdir;
|
||||
|
@ -145,19 +142,18 @@ void DBot::NewChaseDir (ticcmd_t *cmd)
|
|||
olddir = (dirtype_t)player->mo->movedir;
|
||||
turnaround = opposite[olddir];
|
||||
|
||||
deltax = dest->x - player->mo->x;
|
||||
deltay = dest->y - player->mo->y;
|
||||
fixedvec2 delta = player->mo->Vec2To(dest);
|
||||
|
||||
if (deltax > 10*FRACUNIT)
|
||||
if (delta.x > 10*FRACUNIT)
|
||||
d[1] = DI_EAST;
|
||||
else if (deltax < -10*FRACUNIT)
|
||||
else if (delta.x < -10*FRACUNIT)
|
||||
d[1] = DI_WEST;
|
||||
else
|
||||
d[1] = DI_NODIR;
|
||||
|
||||
if (deltay < -10*FRACUNIT)
|
||||
if (delta.y < -10*FRACUNIT)
|
||||
d[2] = DI_SOUTH;
|
||||
else if (deltay > 10*FRACUNIT)
|
||||
else if (delta.y > 10*FRACUNIT)
|
||||
d[2] = DI_NORTH;
|
||||
else
|
||||
d[2] = DI_NODIR;
|
||||
|
@ -165,14 +161,14 @@ void DBot::NewChaseDir (ticcmd_t *cmd)
|
|||
// try direct route
|
||||
if (d[1] != DI_NODIR && d[2] != DI_NODIR)
|
||||
{
|
||||
player->mo->movedir = diags[((deltay<0)<<1)+(deltax>0)];
|
||||
player->mo->movedir = diags[((delta.y<0)<<1)+(delta.x>0)];
|
||||
if (player->mo->movedir != turnaround && TryWalk(cmd))
|
||||
return;
|
||||
}
|
||||
|
||||
// try other directions
|
||||
if (pr_botnewchasedir() > 200
|
||||
|| abs(deltay)>abs(deltax))
|
||||
|| abs(delta.y)>abs(delta.x))
|
||||
{
|
||||
tdir=d[1];
|
||||
d[1]=d[2];
|
||||
|
@ -282,7 +278,7 @@ bool FCajunMaster::CleanAhead (AActor *thing, fixed_t x, fixed_t y, ticcmd_t *cm
|
|||
|
||||
|
||||
if ( !(thing->flags & MF_TELEPORT) &&
|
||||
tm.ceilingz - thing->z < thing->height)
|
||||
tm.ceilingz - thing->Z() < thing->height)
|
||||
return false; // mobj must lower itself to fit
|
||||
|
||||
// jump out of water
|
||||
|
@ -290,7 +286,7 @@ bool FCajunMaster::CleanAhead (AActor *thing, fixed_t x, fixed_t y, ticcmd_t *cm
|
|||
// maxstep=37*FRACUNIT;
|
||||
|
||||
if ( !(thing->flags & MF_TELEPORT) &&
|
||||
(tm.floorz - thing->z > maxstep ) )
|
||||
(tm.floorz - thing->Z() > maxstep ) )
|
||||
return false; // too big a step up
|
||||
|
||||
|
||||
|
@ -346,28 +342,13 @@ void DBot::Pitch (AActor *target)
|
|||
double aim;
|
||||
double diff;
|
||||
|
||||
diff = target->z - player->mo->z;
|
||||
aim = atan (diff / (double)P_AproxDistance (player->mo->x - target->x, player->mo->y - target->y));
|
||||
diff = target->Z() - player->mo->Z();
|
||||
aim = atan(diff / (double)player->mo->AproxDistance(target));
|
||||
player->mo->pitch = -(int)(aim * ANGLE_180/M_PI);
|
||||
}
|
||||
|
||||
//Checks if a sector is dangerous.
|
||||
bool FCajunMaster::IsDangerous (sector_t *sec)
|
||||
{
|
||||
int special;
|
||||
|
||||
return
|
||||
sec->damage
|
||||
|| sec->special & DAMAGE_MASK
|
||||
|| (special = sec->special & 0xff, special == dLight_Strobe_Hurt)
|
||||
|| special == dDamage_Hellslime
|
||||
|| special == dDamage_Nukage
|
||||
|| special == dDamage_End
|
||||
|| special == dDamage_SuperHellslime
|
||||
|| special == dDamage_LavaWimpy
|
||||
|| special == dDamage_LavaHefty
|
||||
|| special == dScroll_EastLavaDamage
|
||||
|| special == sLight_Strobe_Hurt
|
||||
|| special == Damage_InstantDeath
|
||||
|| special == sDamage_SuperHellslime;
|
||||
return sec->damageamount > 0;
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
|
|||
int r;
|
||||
|
||||
stuck = false;
|
||||
dist = dest ? P_AproxDistance(player->mo->x-dest->x, player->mo->y-dest->y) : 0;
|
||||
dist = dest ? player->mo->AproxDistance(dest) : 0;
|
||||
|
||||
if (missile &&
|
||||
((!missile->velx || !missile->vely) || !Check_LOS(missile, SHOOTFOV*3/2)))
|
||||
|
@ -96,14 +96,14 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
|
|||
player->mo->pitch += 80;
|
||||
|
||||
//HOW TO MOVE:
|
||||
if (missile && (P_AproxDistance(player->mo->x-missile->x, player->mo->y-missile->y)<AVOID_DIST)) //try avoid missile got from P_Mobj.c thinking part.
|
||||
if (missile && (player->mo->AproxDistance(missile)<AVOID_DIST)) //try avoid missile got from P_Mobj.c thinking part.
|
||||
{
|
||||
Pitch (missile);
|
||||
angle = R_PointToAngle2(player->mo->x, player->mo->y, missile->x, missile->y);
|
||||
angle = player->mo->AngleTo(missile);
|
||||
cmd->ucmd.sidemove = sleft ? -SIDERUN : SIDERUN;
|
||||
cmd->ucmd.forwardmove = -FORWARDRUN; //Back IS best.
|
||||
|
||||
if ((P_AproxDistance(player->mo->x-oldx, player->mo->y-oldy)<50000)
|
||||
if ((player->mo->AproxDistance(oldx, oldy)<50000)
|
||||
&& t_strafe<=0)
|
||||
{
|
||||
t_strafe = 5;
|
||||
|
@ -156,7 +156,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
|
|||
t_fight = AFTERTICS;
|
||||
|
||||
if (t_strafe <= 0 &&
|
||||
(P_AproxDistance(player->mo->x-oldx, player->mo->y-oldy)<50000
|
||||
(player->mo->AproxDistance(oldx, oldy)<50000
|
||||
|| ((pr_botmove()%30)==10))
|
||||
)
|
||||
{
|
||||
|
@ -165,10 +165,10 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
|
|||
sleft = !sleft;
|
||||
}
|
||||
|
||||
angle = R_PointToAngle2(player->mo->x, player->mo->y, enemy->x, enemy->y);
|
||||
angle = player->mo->AngleTo(enemy);
|
||||
|
||||
if (player->ReadyWeapon == NULL ||
|
||||
P_AproxDistance(player->mo->x-enemy->x, player->mo->y-enemy->y) >
|
||||
player->mo->AproxDistance(enemy) >
|
||||
player->ReadyWeapon->MoveCombatDist)
|
||||
{
|
||||
// If a monster, use lower speed (just for cooler apperance while strafing down doomed monster)
|
||||
|
@ -206,9 +206,9 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
|
|||
goto roam;
|
||||
}
|
||||
|
||||
angle = R_PointToAngle2(player->mo->x, player->mo->y, mate->x, mate->y);
|
||||
angle = player->mo->AngleTo(mate);
|
||||
|
||||
matedist = P_AproxDistance(player->mo->x - mate->x, player->mo->y - mate->y);
|
||||
matedist = player->mo->AproxDistance(mate);
|
||||
if (matedist > (FRIEND_DIST*2))
|
||||
cmd->ucmd.forwardmove = FORWARDRUN;
|
||||
else if (matedist > FRIEND_DIST)
|
||||
|
@ -241,7 +241,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
|
|||
(pr_botmove()%100)>skill.isp) && player->ReadyWeapon != NULL && !(player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
|
||||
dest = enemy;//Dont let enemy kill the bot by supressive fire. So charge enemy.
|
||||
else //hide while t_fight, but keep view at enemy.
|
||||
angle = R_PointToAngle2(player->mo->x, player->mo->y, enemy->x, enemy->y);
|
||||
angle = player->mo->AngleTo(enemy);
|
||||
} //Just a monster, so kill it.
|
||||
else
|
||||
dest = enemy;
|
||||
|
@ -303,8 +303,8 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
|
|||
if (t_fight<(AFTERTICS/2))
|
||||
player->mo->flags |= MF_DROPOFF;
|
||||
|
||||
oldx = player->mo->x;
|
||||
oldy = player->mo->y;
|
||||
oldx = player->mo->X();
|
||||
oldy = player->mo->Y();
|
||||
}
|
||||
|
||||
//BOT_WhatToGet
|
||||
|
|
|
@ -942,7 +942,7 @@ static void PrintFilteredActorList(const ActorTypeChecker IsActorType, const cha
|
|||
{
|
||||
Printf ("%s at (%d,%d,%d)\n",
|
||||
mo->GetClass()->TypeName.GetChars(),
|
||||
mo->x >> FRACBITS, mo->y >> FRACBITS, mo->z >> FRACBITS);
|
||||
mo->X() >> FRACBITS, mo->Y() >> FRACBITS, mo->Z() >> FRACBITS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1082,7 +1082,7 @@ CCMD(currentpos)
|
|||
{
|
||||
AActor *mo = players[consoleplayer].mo;
|
||||
Printf("Current player position: (%1.3f,%1.3f,%1.3f), angle: %1.3f, floorheight: %1.3f, sector:%d, lightlevel: %d\n",
|
||||
FIXED2FLOAT(mo->x), FIXED2FLOAT(mo->y), FIXED2FLOAT(mo->z), mo->angle/float(ANGLE_1), FIXED2FLOAT(mo->floorz), mo->Sector->sectornum, mo->Sector->lightlevel);
|
||||
FIXED2FLOAT(mo->X()), FIXED2FLOAT(mo->Y()), FIXED2FLOAT(mo->Z()), mo->angle/float(ANGLE_1), FIXED2FLOAT(mo->floorz), mo->Sector->sectornum, mo->Sector->lightlevel);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1132,11 +1132,8 @@ static void PrintSecretString(const char *string, bool thislevel)
|
|||
if (*string == ';') string++;
|
||||
if (thislevel && secnum >= 0 && secnum < numsectors)
|
||||
{
|
||||
if (sectors[secnum].secretsector)
|
||||
{
|
||||
if ((sectors[secnum].special & SECRET_MASK)) colstr = TEXTCOLOR_RED;
|
||||
else colstr = TEXTCOLOR_GREEN;
|
||||
}
|
||||
if (sectors[secnum].isSecret()) colstr = TEXTCOLOR_RED;
|
||||
else if (sectors[secnum].wasSecret()) colstr = TEXTCOLOR_GREEN;
|
||||
else colstr = TEXTCOLOR_ORANGE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3091,7 +3091,7 @@ bool ADehackedPickup::TryPickup (AActor *&toucher)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
RealPickup = static_cast<AInventory *>(Spawn (type, x, y, z, NO_REPLACE));
|
||||
RealPickup = static_cast<AInventory *>(Spawn (type, X(), Y(), Z(), NO_REPLACE));
|
||||
if (RealPickup != NULL)
|
||||
{
|
||||
// The internally spawned item should never count towards statistics.
|
||||
|
|
|
@ -2319,10 +2319,12 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
|||
else
|
||||
{
|
||||
const AActor *def = GetDefaultByType (typeinfo);
|
||||
AActor *spawned = Spawn (typeinfo,
|
||||
source->x + FixedMul (def->radius * 2 + source->radius, finecosine[source->angle>>ANGLETOFINESHIFT]),
|
||||
source->y + FixedMul (def->radius * 2 + source->radius, finesine[source->angle>>ANGLETOFINESHIFT]),
|
||||
source->z + 8 * FRACUNIT, ALLOW_REPLACE);
|
||||
fixedvec3 spawnpos = source->Vec3Offset(
|
||||
FixedMul (def->radius * 2 + source->radius, finecosine[source->angle>>ANGLETOFINESHIFT]),
|
||||
FixedMul (def->radius * 2 + source->radius, finesine[source->angle>>ANGLETOFINESHIFT]),
|
||||
8 * FRACUNIT);
|
||||
|
||||
AActor *spawned = Spawn (typeinfo, spawnpos, ALLOW_REPLACE);
|
||||
if (spawned != NULL)
|
||||
{
|
||||
if (type == DEM_SUMMONFRIEND || type == DEM_SUMMONFRIEND2 || type == DEM_SUMMONMBF)
|
||||
|
@ -2373,8 +2375,8 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
|||
|
||||
s = ReadString (stream);
|
||||
|
||||
if (Trace (players[player].mo->x, players[player].mo->y,
|
||||
players[player].mo->z + players[player].mo->height - (players[player].mo->height>>2),
|
||||
if (Trace (players[player].mo->X(), players[player].mo->Y(),
|
||||
players[player].mo->Z() + players[player].mo->height - (players[player].mo->height>>2),
|
||||
players[player].mo->Sector,
|
||||
vx, vy, vz, 172*FRACUNIT, 0, ML_BLOCKEVERYTHING, players[player].mo,
|
||||
trace, TRACE_NoSky))
|
||||
|
|
|
@ -443,6 +443,8 @@ public:
|
|||
int killcount, itemcount, secretcount; // for intermission
|
||||
int damagecount, bonuscount;// for screen flashing
|
||||
int hazardcount; // for delayed Strife damage
|
||||
int hazardinterval; // Frequency of damage infliction
|
||||
FName hazardtype; // Damage type of last hazardous damage encounter.
|
||||
int poisoncount; // screen flash for poison damage
|
||||
FName poisontype; // type of poison damage to apply
|
||||
FName poisonpaintype; // type of Pain state to enter for poison damage
|
||||
|
|
|
@ -388,8 +388,8 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld)
|
|||
#define SECTOR_CHECK(f,t) \
|
||||
if (sectors[i].f.p == static_cast<t *>(old)) { sectors[i].f = static_cast<t *>(notOld); changed++; }
|
||||
SECTOR_CHECK( SoundTarget, AActor );
|
||||
SECTOR_CHECK( CeilingSkyBox, ASkyViewpoint );
|
||||
SECTOR_CHECK( FloorSkyBox, ASkyViewpoint );
|
||||
SECTOR_CHECK( SkyBoxes[sector_t::ceiling], ASkyViewpoint );
|
||||
SECTOR_CHECK( SkyBoxes[sector_t::floor], ASkyViewpoint );
|
||||
SECTOR_CHECK( SecActTarget, ASectorAction );
|
||||
SECTOR_CHECK( floordata, DSectorEffect );
|
||||
SECTOR_CHECK( ceilingdata, DSectorEffect );
|
||||
|
|
|
@ -677,8 +677,8 @@ size_t DSectorMarker::PropagateMark()
|
|||
{
|
||||
sector_t *sec = §ors[SecNum + i];
|
||||
GC::Mark(sec->SoundTarget);
|
||||
GC::Mark(sec->CeilingSkyBox);
|
||||
GC::Mark(sec->FloorSkyBox);
|
||||
GC::Mark(sec->SkyBoxes[sector_t::ceiling]);
|
||||
GC::Mark(sec->SkyBoxes[sector_t::floor]);
|
||||
GC::Mark(sec->SecActTarget);
|
||||
GC::Mark(sec->floordata);
|
||||
GC::Mark(sec->ceilingdata);
|
||||
|
|
|
@ -3145,8 +3145,8 @@ void FParser::SF_MoveCamera(void)
|
|||
}
|
||||
|
||||
// set step variables based on distance and speed
|
||||
mobjangle = R_PointToAngle2(cam->x, cam->y, target->x, target->y);
|
||||
xydist = R_PointToDist2(target->x - cam->x, target->y - cam->y);
|
||||
mobjangle = cam->AngleTo(target);
|
||||
xydist = cam->Distance2D(target);
|
||||
|
||||
xstep = FixedMul(finecosine[mobjangle >> ANGLETOFINESHIFT], movespeed);
|
||||
ystep = FixedMul(finesine[mobjangle >> ANGLETOFINESHIFT], movespeed);
|
||||
|
@ -4323,44 +4323,12 @@ void FParser::SF_KillInSector()
|
|||
//==========================================================================
|
||||
//
|
||||
// new for GZDoom: Sets a sector's type
|
||||
// (Sure, this is not particularly useful. But having it made it possible
|
||||
// to fix a few annoying bugs in some old maps ;) )
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FParser::SF_SectorType(void)
|
||||
{
|
||||
int tagnum, secnum;
|
||||
sector_t *sector;
|
||||
|
||||
if (CheckArgs(1))
|
||||
{
|
||||
tagnum = intvalue(t_argv[0]);
|
||||
|
||||
// argv is sector tag
|
||||
secnum = T_FindFirstSectorFromTag(tagnum);
|
||||
|
||||
if(secnum < 0)
|
||||
{ script_error("sector not found with tagnum %i\n", tagnum); return;}
|
||||
|
||||
sector = §ors[secnum];
|
||||
|
||||
if(t_argc > 1)
|
||||
{
|
||||
int i = -1;
|
||||
int spec = intvalue(t_argv[1]);
|
||||
|
||||
// set all sectors with tag
|
||||
FSSectorTagIterator itr(tagnum);
|
||||
while ((i = itr.Next()) >= 0)
|
||||
{
|
||||
sectors[i].special = spec;
|
||||
}
|
||||
}
|
||||
|
||||
t_return.type = svt_int;
|
||||
t_return.value.i = sector->special;
|
||||
}
|
||||
// I don't think this was ever used publicly so I'm not going to bother fixing it.
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -87,7 +87,6 @@ DEFINE_MAP_OPTION(fs_nocheckposition, false)
|
|||
{
|
||||
FFsOptions *opt = info->GetOptData<FFsOptions>("fragglescript");
|
||||
|
||||
parse.ParseAssign();
|
||||
if (parse.CheckAssign())
|
||||
{
|
||||
parse.sc.MustGetNumber();
|
||||
|
|
|
@ -61,10 +61,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Punch)
|
|||
if (linetarget)
|
||||
{
|
||||
S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM);
|
||||
self->angle = R_PointToAngle2 (self->x,
|
||||
self->y,
|
||||
linetarget->x,
|
||||
linetarget->y);
|
||||
self->angle = self->AngleTo(linetarget);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -235,8 +232,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
|
|||
// turn to face target
|
||||
if (!(flags & SF_NOTURN))
|
||||
{
|
||||
angle = R_PointToAngle2(self->x, self->y,
|
||||
linetarget->x, linetarget->y);
|
||||
angle = self->AngleTo(linetarget);
|
||||
if (angle - self->angle > ANG180)
|
||||
{
|
||||
if (angle - self->angle < (angle_t)(-ANG90 / 20))
|
||||
|
|
|
@ -36,7 +36,7 @@ void A_SkullAttack(AActor *self, fixed_t speed)
|
|||
an = self->angle >> ANGLETOFINESHIFT;
|
||||
self->velx = FixedMul (speed, finecosine[an]);
|
||||
self->vely = FixedMul (speed, finesine[an]);
|
||||
dist = P_AproxDistance (dest->x - self->x, dest->y - self->y);
|
||||
dist = self->AproxDistance (dest);
|
||||
dist = dist / speed;
|
||||
|
||||
if (dist < 1)
|
||||
|
|
|
@ -112,7 +112,7 @@ void A_PainShootSkull (AActor *self, angle_t angle, PClassActor *spawntype, int
|
|||
box.Top() < ld->bbox[BOXBOTTOM] ||
|
||||
box.Bottom() > ld->bbox[BOXTOP]))
|
||||
{
|
||||
if (P_PointOnLineSide(self->x,self->y,ld) != P_PointOnLineSide(x,y,ld))
|
||||
if (P_PointOnLineSidePrecise(self->x,self->y,ld) != P_PointOnLineSidePrecise(x,y,ld))
|
||||
return; // line blocks trajectory // ^
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer)
|
|||
return 0;
|
||||
|
||||
// change angle
|
||||
exact = R_PointToAngle2 (self->x, self->y, dest->x, dest->y);
|
||||
exact = self->AngleTo(dest);
|
||||
|
||||
if (exact != self->angle)
|
||||
{
|
||||
|
@ -107,10 +107,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer)
|
|||
if (!(self->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)))
|
||||
{
|
||||
// change slope
|
||||
dist = P_AproxDistance (dest->x - self->x,
|
||||
dest->y - self->y);
|
||||
|
||||
dist = dist / self->Speed;
|
||||
dist = self->AproxDistance (dest) / self->Speed;
|
||||
|
||||
if (dist < 1)
|
||||
dist = 1;
|
||||
|
|
|
@ -293,7 +293,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Saw)
|
|||
S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM);
|
||||
|
||||
// turn to face target
|
||||
angle = R_PointToAngle2 (self->x, self->y, linetarget->x, linetarget->y);
|
||||
angle = self->AngleTo(linetarget);
|
||||
if (angle - self->angle > ANG180)
|
||||
{
|
||||
if (angle - self->angle < (angle_t)(-ANG90/20))
|
||||
|
@ -344,7 +344,8 @@ static void MarinePunch(AActor *self, int damagemul)
|
|||
if (linetarget)
|
||||
{
|
||||
S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM);
|
||||
self->angle = R_PointToAngle2 (self->x, self->y, linetarget->x, linetarget->y);
|
||||
self->angle = self->AngleTo(linetarget);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ struct MapinfoEdMapItem
|
|||
{
|
||||
FName classname; // DECORATE is read after MAPINFO so we do not have the actual classes available here yet.
|
||||
short special;
|
||||
bool argsdefined;
|
||||
signed char argsdefined;
|
||||
int args[5];
|
||||
// These are for error reporting. We must store the file information because it's no longer available when these items get resolved.
|
||||
FString filename;
|
||||
|
@ -181,14 +181,14 @@ void FMapInfoParser::ParseDoomEdNums()
|
|||
editem.special = -1;
|
||||
}
|
||||
memset(editem.args, 0, sizeof(editem.args));
|
||||
editem.argsdefined = false;
|
||||
editem.argsdefined = 0;
|
||||
|
||||
int minargs = 0;
|
||||
int maxargs = 5;
|
||||
FString specialname;
|
||||
if (sc.CheckString(","))
|
||||
{
|
||||
editem.argsdefined = true; // mark args as used - if this is done we need to prevent assignment of map args in P_SpawnMapThing.
|
||||
editem.argsdefined = 5; // mark args as used - if this is done we need to prevent assignment of map args in P_SpawnMapThing.
|
||||
if (editem.special < 0) editem.special = 0;
|
||||
if (!sc.CheckNumber())
|
||||
{
|
||||
|
@ -221,7 +221,14 @@ void FMapInfoParser::ParseDoomEdNums()
|
|||
editem.args[i] = sc.Number;
|
||||
i++;
|
||||
if (!sc.CheckString(",")) break;
|
||||
// special check for the ambient sounds which combine the arg being set here with the ones on the mapthing.
|
||||
if (sc.CheckString("+"))
|
||||
{
|
||||
editem.argsdefined = i;
|
||||
break;
|
||||
}
|
||||
sc.MustGetNumber();
|
||||
|
||||
}
|
||||
if (specialname.IsNotEmpty() && (i < minargs || i > maxargs))
|
||||
{
|
||||
|
|
|
@ -1179,7 +1179,7 @@ void G_Ticker ()
|
|||
}
|
||||
if (players[i].mo)
|
||||
{
|
||||
DWORD sum = rngsum + players[i].mo->x + players[i].mo->y + players[i].mo->z
|
||||
DWORD sum = rngsum + players[i].mo->X() + players[i].mo->Y() + players[i].mo->Z()
|
||||
+ players[i].mo->angle + players[i].mo->pitch;
|
||||
sum ^= players[i].health;
|
||||
consistancy[i][buf] = sum;
|
||||
|
@ -1438,13 +1438,13 @@ bool G_CheckSpot (int playernum, FPlayerStart *mthing)
|
|||
if (!players[playernum].mo)
|
||||
{ // first spawn of level, before corpses
|
||||
for (i = 0; i < playernum; i++)
|
||||
if (players[i].mo && players[i].mo->x == x && players[i].mo->y == y)
|
||||
if (players[i].mo && players[i].mo->X() == x && players[i].mo->Y() == y)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
oldz = players[playernum].mo->z; // [RH] Need to save corpse's z-height
|
||||
players[playernum].mo->z = z; // [RH] Checks are now full 3-D
|
||||
oldz = players[playernum].mo->Z(); // [RH] Need to save corpse's z-height
|
||||
players[playernum].mo->SetZ(z); // [RH] Checks are now full 3-D
|
||||
|
||||
// killough 4/2/98: fix bug where P_CheckPosition() uses a non-solid
|
||||
// corpse to detect collisions with other players in DM starts
|
||||
|
@ -1456,7 +1456,7 @@ bool G_CheckSpot (int playernum, FPlayerStart *mthing)
|
|||
players[playernum].mo->flags |= MF_SOLID;
|
||||
i = P_CheckPosition(players[playernum].mo, x, y);
|
||||
players[playernum].mo->flags &= ~MF_SOLID;
|
||||
players[playernum].mo->z = oldz; // [RH] Restore corpse's height
|
||||
players[playernum].mo->SetZ(oldz); // [RH] Restore corpse's height
|
||||
if (!i)
|
||||
return false;
|
||||
|
||||
|
@ -1482,8 +1482,7 @@ static fixed_t PlayersRangeFromSpot (FPlayerStart *spot)
|
|||
if (!playeringame[i] || !players[i].mo || players[i].health <= 0)
|
||||
continue;
|
||||
|
||||
distance = P_AproxDistance (players[i].mo->x - spot->x,
|
||||
players[i].mo->y - spot->y);
|
||||
distance = players[i].mo->AproxDistance (spot->x, spot->y);
|
||||
|
||||
if (distance < closest)
|
||||
closest = distance;
|
||||
|
@ -1716,6 +1715,8 @@ void G_DoPlayerPop(int playernum)
|
|||
|
||||
// [RH] Make the player disappear
|
||||
FBehavior::StaticStopMyScripts(players[playernum].mo);
|
||||
// [RH] Let the scripts know the player left
|
||||
FBehavior::StaticStartTypedScripts(SCRIPT_Disconnect, players[playernum].mo, true, playernum, true);
|
||||
if (players[playernum].mo != NULL)
|
||||
{
|
||||
P_DisconnectEffect(players[playernum].mo);
|
||||
|
@ -1729,8 +1730,6 @@ void G_DoPlayerPop(int playernum)
|
|||
players[playernum].mo = NULL;
|
||||
players[playernum].camera = NULL;
|
||||
}
|
||||
// [RH] Let the scripts know the player left
|
||||
FBehavior::StaticStartTypedScripts(SCRIPT_Disconnect, NULL, true, playernum);
|
||||
}
|
||||
|
||||
void G_ScreenShot (char *filename)
|
||||
|
|
|
@ -189,8 +189,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1)
|
|||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &linetarget);
|
||||
if (linetarget)
|
||||
{
|
||||
player->mo->angle = R_PointToAngle2 (player->mo->x,
|
||||
player->mo->y, linetarget->x, linetarget->y);
|
||||
player->mo->angle = player->mo->AngleTo(linetarget);
|
||||
}
|
||||
P_PlayPeck (player->mo);
|
||||
player->chickenPeck = 12;
|
||||
|
@ -225,8 +224,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL2)
|
|||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &linetarget);
|
||||
if (linetarget)
|
||||
{
|
||||
player->mo->angle = R_PointToAngle2 (player->mo->x,
|
||||
player->mo->y, linetarget->x, linetarget->y);
|
||||
player->mo->angle = player->mo->AngleTo(linetarget);
|
||||
}
|
||||
P_PlayPeck (player->mo);
|
||||
player->chickenPeck = 12;
|
||||
|
|
|
@ -94,8 +94,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StaffAttack)
|
|||
{
|
||||
//S_StartSound(player->mo, sfx_stfhit);
|
||||
// turn to face target
|
||||
self->angle = R_PointToAngle2 (self->x,
|
||||
self->y, linetarget->x, linetarget->y);
|
||||
self->angle = self->AngleTo(linetarget);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -325,8 +324,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack)
|
|||
S_Sound (self, CHAN_AUTO, "weapons/gauntletshit", 1, ATTN_NORM);
|
||||
}
|
||||
// turn to face target
|
||||
angle = R_PointToAngle2 (self->x, self->y,
|
||||
linetarget->x, linetarget->y);
|
||||
angle = self->AngleTo(linetarget);
|
||||
if (angle-self->angle > ANG180)
|
||||
{
|
||||
if ((int)(angle-self->angle) < -ANG90/20)
|
||||
|
@ -684,8 +682,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact)
|
|||
}
|
||||
else
|
||||
{ // Seek
|
||||
angle = R_PointToAngle2(self->x, self->y,
|
||||
target->x, target->y);
|
||||
self->angle = self->AngleTo(target);
|
||||
newAngle = true;
|
||||
}
|
||||
}
|
||||
|
@ -698,8 +695,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact)
|
|||
if (linetarget && self->target != linetarget)
|
||||
{
|
||||
self->tracer = linetarget;
|
||||
angle = R_PointToAngle2 (self->x, self->y,
|
||||
linetarget->x, linetarget->y);
|
||||
angle = self->AngleTo(linetarget);
|
||||
newAngle = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1163,7 +1159,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_HideInCeiling)
|
|||
F3DFloor * rover = self->Sector->e->XFloor.ffloors[i];
|
||||
if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
if ((foo = rover->bottom.plane->ZatPoint(self->x, self->y)) >= (self->z + self->height))
|
||||
if ((foo = rover->bottom.plane->ZatPoint(self)) >= (self->z + self->height))
|
||||
{
|
||||
self->z = foo + 4*FRACUNIT;
|
||||
self->bouncecount = i;
|
||||
|
|
|
@ -93,8 +93,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichAttack)
|
|||
P_TraceBleed (newdam > 0 ? newdam : damage, target, self);
|
||||
return 0;
|
||||
}
|
||||
dist = P_AproxDistance (self->x-target->x, self->y-target->y)
|
||||
> 8*64*FRACUNIT;
|
||||
dist = self->AproxDistance (target) > 8*64*FRACUNIT;
|
||||
randAttack = pr_atk ();
|
||||
if (randAttack < atkResolve1[dist])
|
||||
{ // Ice ball
|
||||
|
|
|
@ -33,13 +33,13 @@ void BlastActor (AActor *victim, fixed_t strength, fixed_t speed, AActor *Owner,
|
|||
return;
|
||||
}
|
||||
|
||||
angle = R_PointToAngle2 (Owner->x, Owner->y, victim->x, victim->y);
|
||||
angle = Owner->AngleTo(victim);
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
victim->velx = FixedMul (speed, finecosine[angle]);
|
||||
victim->vely = FixedMul (speed, finesine[angle]);
|
||||
|
||||
// Spawn blast puff
|
||||
ang = R_PointToAngle2 (victim->x, victim->y, Owner->x, Owner->y);
|
||||
ang = victim->AngleTo(Owner);
|
||||
ang >>= ANGLETOFINESHIFT;
|
||||
x = victim->x + FixedMul (victim->radius+FRACUNIT, finecosine[ang]);
|
||||
y = victim->y + FixedMul (victim->radius+FRACUNIT, finesine[ang]);
|
||||
|
@ -145,7 +145,7 @@ DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_Blast)
|
|||
{ // Must be monster, player, missile, touchy or vulnerable
|
||||
continue;
|
||||
}
|
||||
dist = P_AproxDistance (self->x - mo->x, self->y - mo->y);
|
||||
dist = self->AproxDistance (mo);
|
||||
if (dist > radius)
|
||||
{ // Out of range
|
||||
continue;
|
||||
|
|
|
@ -274,14 +274,12 @@ static void CHolyTailFollow (AActor *actor, fixed_t dist)
|
|||
child = actor->tracer;
|
||||
if (child)
|
||||
{
|
||||
an = R_PointToAngle2(actor->x, actor->y, child->x,
|
||||
child->y)>>ANGLETOFINESHIFT;
|
||||
oldDistance = P_AproxDistance (child->x-actor->x, child->y-actor->y);
|
||||
an = actor->AngleTo(child) >> ANGLETOFINESHIFT;
|
||||
oldDistance = child->AproxDistance (actor);
|
||||
if (P_TryMove (child, actor->x+FixedMul(dist, finecosine[an]),
|
||||
actor->y+FixedMul(dist, finesine[an]), true))
|
||||
{
|
||||
newDistance = P_AproxDistance (child->x-actor->x,
|
||||
child->y-actor->y)-FRACUNIT;
|
||||
newDistance = child->AproxDistance (actor)-FRACUNIT;
|
||||
if (oldDistance < FRACUNIT)
|
||||
{
|
||||
if (child->z < actor->z)
|
||||
|
@ -440,7 +438,7 @@ static void CHolySeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax)
|
|||
deltaZ = -15*FRACUNIT;
|
||||
}
|
||||
}
|
||||
dist = P_AproxDistance (target->x-actor->x, target->y-actor->y);
|
||||
dist = actor->AproxDistance (target);
|
||||
dist = dist / actor->Speed;
|
||||
if (dist < 1)
|
||||
{
|
||||
|
|
|
@ -77,7 +77,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
|
|||
P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, puff, false, &linetarget);
|
||||
if (linetarget != NULL)
|
||||
{
|
||||
pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, linetarget->x, linetarget->y);
|
||||
pmo->angle = pmo->AngleTo(linetarget);
|
||||
if (((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0))|| linetarget->flags3&MF3_ISMONSTER)
|
||||
&& (!(linetarget->flags2&(MF2_DORMANT|MF2_INVULNERABLE))))
|
||||
{
|
||||
|
@ -107,7 +107,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
|
|||
P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, puff, false, &linetarget);
|
||||
if (linetarget != NULL)
|
||||
{
|
||||
pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, linetarget->x, linetarget->y);
|
||||
pmo->angle = pmo->AngleTo(linetarget);
|
||||
if ((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER)
|
||||
{
|
||||
newLife = player->health+(damage>>4);
|
||||
|
|
|
@ -59,28 +59,21 @@ static void DragonSeek (AActor *actor, angle_t thresh, angle_t turnMax)
|
|||
angle = actor->angle>>ANGLETOFINESHIFT;
|
||||
actor->velx = FixedMul (actor->Speed, finecosine[angle]);
|
||||
actor->vely = FixedMul (actor->Speed, finesine[angle]);
|
||||
dist = actor->AproxDistance (target) / actor->Speed;
|
||||
if (actor->z+actor->height < target->z ||
|
||||
target->z+target->height < actor->z)
|
||||
{
|
||||
dist = P_AproxDistance(target->x-actor->x, target->y-actor->y);
|
||||
dist = dist/actor->Speed;
|
||||
if (dist < 1)
|
||||
{
|
||||
dist = 1;
|
||||
}
|
||||
actor->velz = (target->z - actor->z)/dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
dist = P_AproxDistance (target->x-actor->x, target->y-actor->y);
|
||||
dist = dist/actor->Speed;
|
||||
}
|
||||
if (target->flags&MF_SHOOTABLE && pr_dragonseek() < 64)
|
||||
{ // attack the destination mobj if it's attackable
|
||||
AActor *oldTarget;
|
||||
|
||||
if (absangle(actor->angle-R_PointToAngle2(actor->x, actor->y,
|
||||
target->x, target->y)) < ANGLE_45/2)
|
||||
if (absangle(actor->angle - actor->AngleTo(target)) < ANGLE_45/2)
|
||||
{
|
||||
oldTarget = actor->target;
|
||||
actor->target = target;
|
||||
|
@ -105,8 +98,7 @@ static void DragonSeek (AActor *actor, angle_t thresh, angle_t turnMax)
|
|||
{
|
||||
AActor *bestActor = NULL;
|
||||
bestAngle = ANGLE_MAX;
|
||||
angleToTarget = R_PointToAngle2(actor->x, actor->y,
|
||||
actor->target->x, actor->target->y);
|
||||
angleToTarget = actor->AngleTo(actor->target);
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (!target->args[i])
|
||||
|
@ -119,8 +111,7 @@ static void DragonSeek (AActor *actor, angle_t thresh, angle_t turnMax)
|
|||
{
|
||||
continue;
|
||||
}
|
||||
angleToSpot = R_PointToAngle2(actor->x, actor->y,
|
||||
mo->x, mo->y);
|
||||
angleToSpot = actor->AngleTo(mo);
|
||||
if (absangle(angleToSpot-angleToTarget) < bestAngle)
|
||||
{
|
||||
bestAngle = absangle(angleToSpot-angleToTarget);
|
||||
|
@ -201,8 +192,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DragonFlight)
|
|||
self->target = NULL;
|
||||
return 0;
|
||||
}
|
||||
angle = R_PointToAngle2(self->x, self->y, self->target->x,
|
||||
self->target->y);
|
||||
angle = self->AngleTo(self->target);
|
||||
if (absangle(self->angle-angle) < ANGLE_45/2 && self->CheckMeleeRange())
|
||||
{
|
||||
int damage = pr_dragonflight.HitDice (8);
|
||||
|
|
|
@ -30,7 +30,7 @@ void AdjustPlayerAngle (AActor *pmo, AActor *linetarget)
|
|||
angle_t angle;
|
||||
int difference;
|
||||
|
||||
angle = R_PointToAngle2 (pmo->x, pmo->y, linetarget->x, linetarget->y);
|
||||
angle = pmo->AngleTo(linetarget);
|
||||
difference = (int)angle - (int)pmo->angle;
|
||||
if (abs(difference) > MAX_ANGLE_ADJUST)
|
||||
{
|
||||
|
|
|
@ -169,12 +169,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_FiredChase)
|
|||
{
|
||||
self->special2 = 0;
|
||||
self->velx = self->vely = 0;
|
||||
dist = P_AproxDistance (self->x - target->x, self->y - target->y);
|
||||
dist = self->AproxDistance (target);
|
||||
if (dist < FIREDEMON_ATTACK_RANGE)
|
||||
{
|
||||
if (pr_firedemonchase() < 30)
|
||||
{
|
||||
ang = R_PointToAngle2 (self->x, self->y, target->x, target->y);
|
||||
ang = self->AngleTo(target);
|
||||
if (pr_firedemonchase() < 128)
|
||||
ang += ANGLE_90;
|
||||
else
|
||||
|
|
|
@ -84,7 +84,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FlyBuzz)
|
|||
return 0;
|
||||
}
|
||||
|
||||
angle_t ang = R_PointToAngle2(self->x, self->y, targ->x, targ->y);
|
||||
angle_t ang = self->AngleTo(targ);
|
||||
self->angle = ang;
|
||||
self->args[0]++;
|
||||
ang >>= ANGLETOFINESHIFT;
|
||||
|
|
|
@ -42,7 +42,7 @@ bool AArtiHealingRadius::Use (bool pickup)
|
|||
if (playeringame[i] &&
|
||||
players[i].mo != NULL &&
|
||||
players[i].mo->health > 0 &&
|
||||
P_AproxDistance (players[i].mo->x - Owner->x, players[i].mo->y - Owner->y) <= HEAL_RADIUS_DIST)
|
||||
players[i].mo->AproxDistance (Owner) <= HEAL_RADIUS_DIST)
|
||||
{
|
||||
// Q: Is it worth it to make this selectable as a player property?
|
||||
// A: Probably not - but it sure doesn't hurt.
|
||||
|
|
|
@ -674,8 +674,7 @@ void A_SorcOffense2(AActor *actor)
|
|||
if (mo)
|
||||
{
|
||||
mo->special2 = 35*5/2; // 5 seconds
|
||||
dist = P_AproxDistance(dest->x - mo->x, dest->y - mo->y);
|
||||
dist = dist/mo->Speed;
|
||||
dist = mo->AproxDistance(dest) / mo->Speed;
|
||||
if(dist < 1) dist = 1;
|
||||
mo->velz = (dest->z - mo->z) / dist;
|
||||
}
|
||||
|
|
|
@ -117,8 +117,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PotteryCheck)
|
|||
if (playeringame[i])
|
||||
{
|
||||
AActor *pmo = players[i].mo;
|
||||
if (P_CheckSight (self, pmo) && (absangle(R_PointToAngle2 (pmo->x,
|
||||
pmo->y, self->x, self->y) - pmo->angle) <= ANGLE_45))
|
||||
if (P_CheckSight (self, pmo) && (absangle(pmo->AngleTo(self) - pmo->angle) <= ANGLE_45))
|
||||
{ // Previous state (pottery bit waiting state)
|
||||
self->SetState (self->state - 1);
|
||||
return 0;
|
||||
|
|
|
@ -409,8 +409,7 @@ void A_KSpiritSeeker (AActor *actor, angle_t thresh, angle_t turnMax)
|
|||
deltaZ = -15*FRACUNIT;
|
||||
}
|
||||
}
|
||||
dist = P_AproxDistance (target->x-actor->x, target->y-actor->y);
|
||||
dist = dist/actor->Speed;
|
||||
dist = actor->AproxDistance (target) / actor->Speed;
|
||||
if (dist < 1)
|
||||
{
|
||||
dist = 1;
|
||||
|
@ -516,7 +515,7 @@ AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
|
|||
z -= source->floorclip;
|
||||
th = Spawn (type, x, y, z, ALLOW_REPLACE);
|
||||
th->target = source; // Originator
|
||||
an = R_PointToAngle2(x, y, dest->x, dest->y);
|
||||
an = source->AngleXYTo(x, y, dest);
|
||||
if (dest->flags & MF_SHADOW)
|
||||
{ // Invisible target
|
||||
an += pr_kmissile.Random2()<<21;
|
||||
|
@ -525,8 +524,7 @@ AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
|
|||
an >>= ANGLETOFINESHIFT;
|
||||
th->velx = FixedMul (th->Speed, finecosine[an]);
|
||||
th->vely = FixedMul (th->Speed, finesine[an]);
|
||||
dist = P_AproxDistance (dest->x - x, dest->y - y);
|
||||
dist = dist/th->Speed;
|
||||
dist = dest->AproxDistance (x, y, source) / th->Speed;
|
||||
if (dist < 1)
|
||||
{
|
||||
dist = 1;
|
||||
|
|
|
@ -195,7 +195,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightningClip)
|
|||
}
|
||||
else
|
||||
{
|
||||
self->angle = R_PointToAngle2(self->x, self->y, target->x, target->y);
|
||||
self->angle = self->AngleTo(target);
|
||||
self->velx = 0;
|
||||
self->vely = 0;
|
||||
P_ThrustMobj (self, self->angle, self->Speed>>1);
|
||||
|
|
|
@ -1232,6 +1232,7 @@ void G_FinishTravel ()
|
|||
pawn->dropoffz = pawndup->dropoffz;
|
||||
pawn->floorsector = pawndup->floorsector;
|
||||
pawn->floorpic = pawndup->floorpic;
|
||||
pawn->floorterrain = pawndup->floorterrain;
|
||||
pawn->ceilingsector = pawndup->ceilingsector;
|
||||
pawn->ceilingpic = pawndup->ceilingpic;
|
||||
pawn->floorclip = pawndup->floorclip;
|
||||
|
|
|
@ -193,7 +193,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDecide)
|
|||
{
|
||||
S_Sound (self, CHAN_WEAPON, "minotaur/sight", 1, ATTN_NORM);
|
||||
}
|
||||
dist = P_AproxDistance (self->x-target->x, self->y-target->y);
|
||||
dist = self->AproxDistance (target);
|
||||
if (target->z+target->height > self->z
|
||||
&& target->z+target->height < self->z+self->height
|
||||
&& dist < (friendly ? 16*64*FRACUNIT : 8*64*FRACUNIT)
|
||||
|
@ -413,7 +413,7 @@ void P_MinotaurSlam (AActor *source, AActor *target)
|
|||
fixed_t thrust;
|
||||
int damage;
|
||||
|
||||
angle = R_PointToAngle2 (source->x, source->y, target->x, target->y);
|
||||
angle = source->AngleTo(target);
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
thrust = 16*FRACUNIT+(pr_minotaurslam()<<10);
|
||||
target->velx += FixedMul (thrust, finecosine[angle]);
|
||||
|
@ -517,7 +517,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurLook)
|
|||
mo = player->mo;
|
||||
if (mo == master) continue;
|
||||
if (mo->health <= 0) continue;
|
||||
dist = P_AproxDistance(self->x - mo->x, self->y - mo->y);
|
||||
dist = self->AproxDistance(mo);
|
||||
if (dist > MINOTAUR_LOOK_DIST) continue;
|
||||
self->target = mo;
|
||||
break;
|
||||
|
@ -542,7 +542,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurLook)
|
|||
if (!(mo->flags3 & MF3_ISMONSTER)) continue;
|
||||
if (mo->health <= 0) continue;
|
||||
if (!(mo->flags & MF_SHOOTABLE)) continue;
|
||||
dist = P_AproxDistance (self->x - mo->x, self->y - mo->y);
|
||||
dist = self->AproxDistance(mo);
|
||||
if (dist > MINOTAUR_LOOK_DIST) continue;
|
||||
if ((mo == master) || (mo == self)) continue;
|
||||
if ((mo->flags5 & MF5_SUMMONEDMONSTER) && (mo->tracer == master)) continue;
|
||||
|
|
|
@ -139,7 +139,7 @@ void DLightningThinker::LightningFlash ()
|
|||
for (i = numsectors, j = 0; i > 0; --i, ++j, ++tempSec)
|
||||
{
|
||||
// allow combination of the lightning sector specials with bit masks
|
||||
int special = tempSec->special & 0xff;
|
||||
int special = tempSec->special;
|
||||
if (tempSec->GetTexture(sector_t::ceiling) == skyflatnum
|
||||
|| special == Light_IndoorLightning1
|
||||
|| special == Light_IndoorLightning2
|
||||
|
|
|
@ -129,7 +129,7 @@ void DEarthquake::Tick ()
|
|||
AActor *victim = players[i].mo;
|
||||
fixed_t dist;
|
||||
|
||||
dist = P_AproxDistance (victim->x - m_Spot->x, victim->y - m_Spot->y);
|
||||
dist = m_Spot->AproxDistance (victim, true);
|
||||
// Check if in damage radius
|
||||
if (dist < m_DamageRadius && victim->z <= victim->floorz)
|
||||
{
|
||||
|
@ -242,8 +242,7 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, FQuakeJiggers &jigger
|
|||
{
|
||||
if (quake->m_Spot != NULL)
|
||||
{
|
||||
fixed_t dist = P_AproxDistance (victim->x - quake->m_Spot->x,
|
||||
victim->y - quake->m_Spot->y);
|
||||
fixed_t dist = quake->m_Spot->AproxDistance (victim, true);
|
||||
if (dist < quake->m_TremorRadius)
|
||||
{
|
||||
++count;
|
||||
|
|
|
@ -100,6 +100,20 @@ public:
|
|||
TObjPtr<ASkyViewpoint> Mate;
|
||||
};
|
||||
|
||||
// For an EE compatible linedef based definition.
|
||||
class ASkyCamCompat : public ASkyViewpoint
|
||||
{
|
||||
DECLARE_CLASS (ASkyCamCompat, ASkyViewpoint)
|
||||
|
||||
public:
|
||||
void BeginPlay ()
|
||||
{
|
||||
// Do not call the SkyViewpoint's super method because it would trash our setup
|
||||
AActor::BeginPlay();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class AStackPoint : public ASkyViewpoint
|
||||
{
|
||||
DECLARE_CLASS (AStackPoint, ASkyViewpoint)
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "p_local.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "farchive.h"
|
||||
#include "r_sky.h"
|
||||
|
||||
// arg0 = Visibility*4 for this skybox
|
||||
|
||||
|
@ -66,13 +67,13 @@ void ASkyViewpoint::Destroy ()
|
|||
// remove all sector references to ourselves.
|
||||
for (int i = 0; i <numsectors; i++)
|
||||
{
|
||||
if (sectors[i].FloorSkyBox == this)
|
||||
if (sectors[i].SkyBoxes[sector_t::floor] == this)
|
||||
{
|
||||
sectors[i].FloorSkyBox = NULL;
|
||||
sectors[i].SkyBoxes[sector_t::floor] = NULL;
|
||||
}
|
||||
if (sectors[i].CeilingSkyBox == this)
|
||||
if (sectors[i].SkyBoxes[sector_t::ceiling] == this)
|
||||
{
|
||||
sectors[i].CeilingSkyBox = NULL;
|
||||
sectors[i].SkyBoxes[sector_t::ceiling] = NULL;
|
||||
}
|
||||
}
|
||||
if (level.DefaultSkybox == this)
|
||||
|
@ -82,65 +83,8 @@ void ASkyViewpoint::Destroy ()
|
|||
Super::Destroy();
|
||||
}
|
||||
|
||||
// For an RR compatible linedef based definition. This searches the viewpoint's sector
|
||||
// for a skybox line special, gets its tag and transfers the skybox to all tagged sectors.
|
||||
class ASkyCamCompat : public ASkyViewpoint
|
||||
{
|
||||
DECLARE_CLASS (ASkyCamCompat, ASkyViewpoint)
|
||||
public:
|
||||
void BeginPlay ();
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS (ASkyCamCompat)
|
||||
|
||||
extern FTextureID skyflatnum;
|
||||
|
||||
void ASkyCamCompat::BeginPlay ()
|
||||
{
|
||||
if (Sector == NULL)
|
||||
{
|
||||
Printf("Sector not initialized for SkyCamCompat\n");
|
||||
Sector = P_PointInSector(x, y);
|
||||
}
|
||||
if (Sector)
|
||||
{
|
||||
line_t * refline = NULL;
|
||||
for (short i = 0; i < Sector->linecount; i++)
|
||||
{
|
||||
refline = Sector->lines[i];
|
||||
if (refline->special == Sector_SetPortal && refline->args[1] == 2)
|
||||
{
|
||||
// We found the setup linedef for this skybox, so let's use it for our init.
|
||||
int skybox_id = refline->args[0];
|
||||
|
||||
// Then, change the alpha
|
||||
alpha = refline->args[4];
|
||||
|
||||
// Finally, skyboxify all tagged sectors
|
||||
// This involves changing their texture to the sky flat, because while
|
||||
// EE works with any texture for its skybox portals, ZDoom doesn't.
|
||||
FSectorTagIterator it(skybox_id);
|
||||
int secnum;
|
||||
while ((secnum = it.Next()) >= 0)
|
||||
{
|
||||
// plane: 0=floor, 1=ceiling, 2=both
|
||||
if (refline->args[2] == 1 || refline->args[2] == 2)
|
||||
{
|
||||
sectors[secnum].CeilingSkyBox = this;
|
||||
sectors[secnum].SetTexture(sector_t::ceiling, skyflatnum, false);
|
||||
}
|
||||
if (refline->args[2] == 0 || refline->args[2] == 2)
|
||||
{
|
||||
sectors[secnum].FloorSkyBox = this;
|
||||
sectors[secnum].SetTexture(sector_t::floor, skyflatnum, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Do not call the SkyViewpoint's super method because it would trash our setup
|
||||
AActor::BeginPlay();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
@ -185,12 +129,12 @@ void ASkyPicker::PostBeginPlay ()
|
|||
{
|
||||
if (0 == (args[1] & 2))
|
||||
{
|
||||
Sector->CeilingSkyBox = box;
|
||||
Sector->SkyBoxes[sector_t::ceiling] = box;
|
||||
if (box == NULL) Sector->MoreFlags |= SECF_NOCEILINGSKYBOX; // sector should ignore the level's default skybox
|
||||
}
|
||||
if (0 == (args[1] & 1))
|
||||
{
|
||||
Sector->FloorSkyBox = box;
|
||||
Sector->SkyBoxes[sector_t::floor] = box;
|
||||
if (box == NULL) Sector->MoreFlags |= SECF_NOFLOORSKYBOX; // sector should ignore the level's default skybox
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ struct FSpotList
|
|||
|
||||
while (true)
|
||||
{
|
||||
distance = P_AproxDistance(Spots[i]->x - x, Spots[i]->y - y);
|
||||
distance = Spots[i]->AproxDistance(x, y);
|
||||
|
||||
if ((distance >= mindist) && ((maxdist == 0) || (distance <= maxdist))) break;
|
||||
|
||||
|
|
|
@ -366,7 +366,7 @@ int FMugShot::UpdateState(player_t *player, StateFlags stateflags)
|
|||
if (player->mo != NULL)
|
||||
{
|
||||
// The next 12 lines are from the Doom statusbar code.
|
||||
badguyangle = R_PointToAngle2(player->mo->x, player->mo->y, player->attacker->x, player->attacker->y);
|
||||
badguyangle = player->mo->AngleTo(player->attacker);
|
||||
if (badguyangle > player->mo->angle)
|
||||
{
|
||||
// whether right or left
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
|
||||
static bool CrusaderCheckRange (AActor *self)
|
||||
{
|
||||
if (P_CheckSight (self, self->target) && self->reactiontime == 0)
|
||||
if (self->reactiontime == 0 && P_CheckSight (self, self->target))
|
||||
{
|
||||
return P_AproxDistance (self->x - self->target->x, self->y - self->target->y) < 264*FRACUNIT;
|
||||
return self->AproxDistance (self->target) < 264*FRACUNIT;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ bool InquisitorCheckDistance (AActor *self)
|
|||
{
|
||||
if (self->reactiontime == 0 && P_CheckSight (self, self->target))
|
||||
{
|
||||
return P_AproxDistance (self->x - self->target->x, self->y - self->target->y) < 264*FRACUNIT;
|
||||
return self->AproxDistance (self->target) < 264*FRACUNIT;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_InquisitorJump)
|
|||
speed = self->Speed * 2/3;
|
||||
self->velx += FixedMul (speed, finecosine[an]);
|
||||
self->vely += FixedMul (speed, finesine[an]);
|
||||
dist = P_AproxDistance (self->target->x - self->x, self->target->y - self->y);
|
||||
dist = self->AproxDistance (self->target);
|
||||
dist /= speed;
|
||||
if (dist < 1)
|
||||
{
|
||||
|
|
|
@ -104,7 +104,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer2)
|
|||
return 0;
|
||||
|
||||
// change angle
|
||||
exact = R_PointToAngle2 (self->x, self->y, dest->x, dest->y);
|
||||
exact = self->AngleTo(dest);
|
||||
|
||||
if (exact != self->angle)
|
||||
{
|
||||
|
@ -129,8 +129,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer2)
|
|||
if (!(self->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)))
|
||||
{
|
||||
// change slope
|
||||
dist = P_AproxDistance (dest->x - self->x, dest->y - self->y);
|
||||
dist /= self->Speed;
|
||||
dist = self->AproxDistance (dest) / self->Speed;
|
||||
|
||||
if (dist < 1)
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue