Conflicts:
	src/CMakeLists.txt
This commit is contained in:
Christoph Oelckers 2016-01-12 11:23:45 +01:00
commit aa69c39ff1
64 changed files with 7044 additions and 3259 deletions

View file

@ -1203,10 +1203,6 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\helpers\tarray.c"
>
</File>
</Filter>
<Filter
Name="it"

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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"

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -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;
}
}

File diff suppressed because it is too large Load diff

View file

@ -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)
{

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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
View 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
View 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

View file

@ -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;

View file

@ -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
View 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
View 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

View file

@ -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;
}
*/
}

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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
View 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
View 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
View 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
View 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
View 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

View file

@ -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);
}

View file

@ -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

View file

@ -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 )

View file

@ -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.

View file

@ -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.
---

View file

@ -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"
>

View file

@ -621,9 +621,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
@ -631,9 +629,11 @@ 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/sdlglvideo.cpp )
posix/sdl/sdlglvideo.cpp
posix/sdl/st_start.cpp )
set( PLAT_OSX_SOURCES
posix/osx/iwadpicker_cocoa.mm
posix/osx/zdoom.icns )
@ -642,8 +642,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 )

View file

@ -7,6 +7,7 @@
*/
#include <cassert>
#include <limits.h>
#include "templates.h"
#include "GuillotineBinPack.h"

View file

@ -7,6 +7,7 @@
*/
#include <cassert>
#include <limits.h>
#include "templates.h"
#include "SkylineBinPack.h"

View file

@ -31,6 +31,9 @@
**
*/
#ifndef COCOA_I_COMMON_INCLUDED
#define COCOA_I_COMMON_INCLUDED
#import <AppKit/AppKit.h>
@ -50,12 +53,23 @@ struct RenderBufferOptions
extern RenderBufferOptions rbOpts;
// Version of AppKit framework we are interested in
// The following values are needed to build with earlier SDKs
#define AppKit10_4 824
#define AppKit10_5 949
#define AppKit10_6 1038
#define AppKit10_7 1138
@interface NSWindow(ExitAppOnClose)
- (void)exitAppOnClose;
@end
inline bool I_IsHiDPISupported()
{
// The following value shoud be equal to NSAppKitVersionNumber10_7
// and it's hard-coded in order to build on earlier SDKs
return NSAppKitVersionNumber >= 1138;
return NSAppKitVersionNumber >= AppKit10_7;
}
void I_ProcessEvent(NSEvent* event);
@ -169,3 +183,5 @@ typedef NSInteger NSApplicationActivationPolicy;
@end
#endif // prior to 10.7
#endif // COCOA_I_COMMON_INCLUDED

View file

@ -47,6 +47,7 @@
#include "i_system.h"
#include "m_argv.h"
#include "s_sound.h"
#include "st_console.h"
#include "version.h"
#undef Class
@ -125,18 +126,7 @@ void Mac_I_FatalError(const char* const message)
{
I_SetMainWindowVisible(false);
const CFStringRef errorString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault,
message, kCFStringEncodingASCII, kCFAllocatorNull);
if (NULL != errorString)
{
CFOptionFlags dummy;
CFUserNotificationDisplayAlert( 0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL,
CFSTR("Fatal Error"), errorString, CFSTR("Exit"), NULL, NULL, &dummy);
CFRelease(errorString);
}
FConsoleWindow::GetInstance().ShowFatalError(message);
}
@ -315,6 +305,9 @@ ApplicationController* appCtrl;
[[NSRunLoop currentRunLoop] addTimer:timer
forMode:NSDefaultRunLoopMode];
FConsoleWindow::CreateInstance();
atterm(FConsoleWindow::DeleteInstance);
exit(OriginalMain(s_argc, s_argv));
}

384
src/posix/cocoa/i_system.mm Normal file
View file

@ -0,0 +1,384 @@
/*
** i_system.mm
**
**---------------------------------------------------------------------------
** Copyright 2012-2015 Alexey Lysiuk
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "i_common.h"
#include <fnmatch.h>
#include <unistd.h>
#include <sys/stat.h>
#include "d_ticcmd.h"
#include "doomdef.h"
#include "doomerrors.h"
#include "doomstat.h"
#include "g_game.h"
#include "gameconfigfile.h"
#include "i_sound.h"
#include "i_system.h"
#include "st_console.h"
#include "v_text.h"
#include "x86.h"
EXTERN_CVAR(String, language)
DWORD LanguageIDs[4];
int (*I_GetTime)(bool saveMS);
int (*I_WaitForTic)(int);
void (*I_FreezeTime)(bool frozen);
void I_Tactile(int /*on*/, int /*off*/, int /*total*/)
{
}
ticcmd_t* I_BaseTiccmd()
{
static ticcmd_t emptycmd;
return &emptycmd;
}
void I_WaitVBL(const int count)
{
// I_WaitVBL is never used to actually synchronize to the
// vertical blank. Instead, it's used for delay purposes.
usleep(1000000 * count / 70);
}
//
// SetLanguageIDs
//
void SetLanguageIDs()
{
size_t langlen = strlen(language);
DWORD lang = (langlen < 2 || langlen > 3)
? MAKE_ID('e', 'n', 'u', '\0')
: MAKE_ID(language[0], language[1], language[2], '\0');
LanguageIDs[3] = LanguageIDs[2] = LanguageIDs[1] = LanguageIDs[0] = lang;
}
void I_InitTimer();
void I_ShutdownTimer();
void I_Init(void)
{
CheckCPUID(&CPU);
DumpCPUInfo(&CPU);
atterm(I_ShutdownSound);
I_InitSound();
I_InitTimer();
}
static int has_exited;
void I_Quit()
{
has_exited = 1; // Prevent infinitely recursive exits -- killough
if (demorecording)
{
G_CheckDemoStatus();
}
C_DeinitConsole();
I_ShutdownTimer();
}
extern FILE* Logfile;
bool gameisdead;
void STACK_ARGS I_FatalError(const char* const error, ...)
{
static bool alreadyThrown = false;
gameisdead = true;
if (!alreadyThrown) // ignore all but the first message -- killough
{
alreadyThrown = true;
char errortext[MAX_ERRORTEXT];
int index;
va_list argptr;
va_start(argptr, error);
index = vsnprintf(errortext, MAX_ERRORTEXT, error, argptr);
va_end(argptr);
extern void Mac_I_FatalError(const char*);
Mac_I_FatalError(errortext);
// Record error to log (if logging)
if (Logfile)
{
fprintf(Logfile, "\n**** DIED WITH FATAL ERROR:\n%s\n", errortext);
fflush(Logfile);
}
fprintf(stderr, "%s\n", errortext);
exit(-1);
}
if (!has_exited) // If it hasn't exited yet, exit now -- killough
{
has_exited = 1; // Prevent infinitely recursive exits -- killough
exit(-1);
}
}
void STACK_ARGS I_Error(const char* const error, ...)
{
va_list argptr;
char errortext[MAX_ERRORTEXT];
va_start(argptr, error);
vsnprintf(errortext, MAX_ERRORTEXT, error, argptr);
va_end(argptr);
throw CRecoverableError(errortext);
}
void I_SetIWADInfo()
{
}
void I_PrintStr(const char* const message)
{
FConsoleWindow::GetInstance().AddText(message);
// Strip out any color escape sequences before writing to output
char* const copy = new char[strlen(message) + 1];
const char* srcp = message;
char* dstp = copy;
while ('\0' != *srcp)
{
if (TEXTCOLOR_ESCAPE == *srcp)
{
if ('\0' != srcp[1])
{
srcp += 2;
}
else
{
break;
}
}
else if (0x1d == *srcp || 0x1f == *srcp) // Opening and closing bar character
{
*dstp++ = '-';
*srcp++;
}
else if (0x1e == *srcp) // Middle bar character
{
*dstp++ = '=';
*srcp++;
}
else
{
*dstp++ = *srcp++;
}
}
*dstp = '\0';
fputs(copy, stdout);
delete[] copy;
fflush(stdout);
}
int I_PickIWad(WadStuff* const wads, const int numwads, const bool showwin, const int defaultiwad)
{
if (!showwin)
{
return defaultiwad;
}
I_SetMainWindowVisible(false);
extern int I_PickIWad_Cocoa(WadStuff*, int, bool, int);
const int result = I_PickIWad_Cocoa(wads, numwads, showwin, defaultiwad);
I_SetMainWindowVisible(true);
return result;
}
bool I_WriteIniFailed()
{
printf("The config file %s could not be saved:\n%s\n", GameConfig->GetPathName(), strerror(errno));
return false; // return true to retry
}
static const char *pattern;
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
static int matchfile(struct dirent *ent)
#else
static int matchfile(const struct dirent *ent)
#endif
{
return fnmatch(pattern, ent->d_name, FNM_NOESCAPE) == 0;
}
void* I_FindFirst(const char* const filespec, findstate_t* const fileinfo)
{
FString dir;
const char* const slash = strrchr(filespec, '/');
if (slash)
{
pattern = slash+1;
dir = FString(filespec, slash - filespec + 1);
}
else
{
pattern = filespec;
dir = ".";
}
fileinfo->current = 0;
fileinfo->count = scandir(dir.GetChars(), &fileinfo->namelist, matchfile, alphasort);
if (fileinfo->count > 0)
{
return fileinfo;
}
return (void*)-1;
}
int I_FindNext(void* const handle, findstate_t* const fileinfo)
{
findstate_t* const state = static_cast<findstate_t*>(handle);
if (state->current < fileinfo->count)
{
return ++state->current < fileinfo->count ? 0 : -1;
}
return -1;
}
int I_FindClose(void* const handle)
{
findstate_t* const state = static_cast<findstate_t*>(handle);
if (handle != (void*)-1 && state->count > 0)
{
for (int i = 0; i < state->count; ++i)
{
free(state->namelist[i]);
}
free(state->namelist);
state->namelist = NULL;
state->count = 0;
}
return 0;
}
int I_FindAttr(findstate_t* const fileinfo)
{
dirent* const ent = fileinfo->namelist[fileinfo->current];
struct stat buf;
if (stat(ent->d_name, &buf) == 0)
{
return S_ISDIR(buf.st_mode) ? FA_DIREC : 0;
}
return 0;
}
static NSString* GetPasteboardStringType()
{
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
return NSStringPboardType;
#else // 10.6 or higher
return NSAppKitVersionNumber < AppKit10_6
? NSStringPboardType
: NSPasteboardTypeString;
#endif // before 10.6
}
void I_PutInClipboard(const char* const string)
{
NSPasteboard* const pasteBoard = [NSPasteboard generalPasteboard];
[pasteBoard clearContents];
[pasteBoard setString:[NSString stringWithUTF8String:string]
forType:GetPasteboardStringType()];
}
FString I_GetFromClipboard(bool returnNothing)
{
if (returnNothing)
{
return FString();
}
NSPasteboard* const pasteBoard = [NSPasteboard generalPasteboard];
NSString* const value = [pasteBoard stringForType:GetPasteboardStringType()];
return FString([value UTF8String]);
}
unsigned int I_MakeRNGSeed()
{
return static_cast<unsigned int>(arc4random());
}
TArray<FString> I_GetGogPaths()
{
// GOG's Doom games are Windows only at the moment
return TArray<FString>();
}

View file

@ -47,6 +47,7 @@
#include "m_argv.h"
#include "r_renderer.h"
#include "r_swrenderer.h"
#include "st_console.h"
#include "stats.h"
#include "textures.h"
#include "v_palette.h"
@ -58,6 +59,18 @@
#undef Class
@implementation NSWindow(ExitAppOnClose)
- (void)exitAppOnClose
{
NSButton* closeButton = [self standardWindowButton:NSWindowCloseButton];
[closeButton setAction:@selector(terminate:)];
[closeButton setTarget:NSApp];
}
@end
EXTERN_CVAR(Bool, ticker )
EXTERN_CVAR(Bool, vid_vsync)
EXTERN_CVAR(Bool, vid_hidpi)
@ -407,7 +420,7 @@ CocoaVideo::CocoaVideo(const int multisample)
attributes[i++] = NSOpenGLPFAStencilSize;
attributes[i++] = NSOpenGLPixelFormatAttribute(8);
if (!vid_autoswitch)
if (NSAppKitVersionNumber >= AppKit10_5 && !vid_autoswitch)
{
attributes[i++] = NSOpenGLPFAAllowOfflineRenderers;
}
@ -433,6 +446,8 @@ CocoaVideo::CocoaVideo(const int multisample)
[[glView openGLContext] makeCurrentContext];
[m_window setContentView:glView];
FConsoleWindow::GetInstance().Show(false);
}
void CocoaVideo::StartModeIterator(const int bits, const bool fullscreen)
@ -555,16 +570,15 @@ void CocoaVideo::SetWindowVisible(bool visible)
{
[video->m_window orderOut:nil];
}
I_SetNativeMouse(!visible);
}
}
static bool HasModernFullscreenAPI()
{
// The following value shoud be equal to NSAppKitVersionNumber10_6
// and it's hard-coded in order to build on earlier SDKs
return NSAppKitVersionNumber >= 1038;
return NSAppKitVersionNumber >= AppKit10_6;
}
void CocoaVideo::SetStyleMask(const NSUInteger styleMask)
@ -662,10 +676,7 @@ void CocoaVideo::SetWindowedMode(const int width, const int height)
[m_window setContentSize:windowSize];
[m_window center];
NSButton* closeButton = [m_window standardWindowButton:NSWindowCloseButton];
[closeButton setAction:@selector(terminate:)];
[closeButton setTarget:NSApp];
[m_window exitAppOnClose];
}
void CocoaVideo::SetMode(const int width, const int height, const bool fullscreen, const bool hiDPI)
@ -1211,7 +1222,7 @@ bool I_SetCursor(FTexture* cursorpic)
// Create image from representation and set it as cursor
NSData* imageData = [bitmapImageRep representationUsingType:NSPNGFileType
properties:nil];
properties:[NSDictionary dictionary]];
NSImage* cursorImage = [[NSImage alloc] initWithData:imageData];
cursor = [[NSCursor alloc] initWithImage:cursorImage
@ -1239,5 +1250,4 @@ NSSize I_GetContentViewSize(const NSWindow* const window)
void I_SetMainWindowVisible(bool visible)
{
CocoaVideo::SetWindowVisible(visible);
I_SetNativeMouse(!visible);
}

View file

@ -0,0 +1,95 @@
/*
** st_console.h
**
**---------------------------------------------------------------------------
** Copyright 2015 Alexey Lysiuk
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#ifndef COCOA_ST_CONSOLE_INCLUDED
#define COCOA_ST_CONSOLE_INCLUDED
@class NSButton;
@class NSProgressIndicator;
@class NSScrollView;
@class NSTextField;
@class NSTextView;
@class NSView;
@class NSWindow;
struct PalEntry;
class FConsoleWindow
{
public:
static FConsoleWindow& GetInstance();
static void CreateInstance();
static void DeleteInstance();
void Show(bool visible);
void ShowFatalError(const char* message);
void AddText(const char* message);
void SetTitleText();
void SetProgressBar(bool visible);
// FStartupScreen functionality
void Progress(int current, int maximum);
void NetInit(const char* message, int playerCount);
void NetProgress(int count);
void NetDone();
private:
NSWindow* m_window;
NSTextView* m_textView;
NSScrollView* m_scrollView;
NSProgressIndicator* m_progressBar;
NSView* m_netView;
NSTextField* m_netMessageText;
NSTextField* m_netCountText;
NSProgressIndicator* m_netProgressBar;
NSButton* m_netAbortButton;
unsigned int m_characterCount;
int m_netCurPos;
int m_netMaxPos;
FConsoleWindow();
~FConsoleWindow();
void ExpandTextView(float height);
void AddText(const PalEntry& color, const char* message);
};
#endif // COCOA_ST_CONSOLE_INCLUDED

View file

@ -0,0 +1,504 @@
/*
** st_console.mm
**
**---------------------------------------------------------------------------
** Copyright 2015 Alexey Lysiuk
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "i_common.h"
#include "d_main.h"
#include "i_system.h"
#include "st_console.h"
#include "v_text.h"
#include "version.h"
static NSColor* RGB(const BYTE red, const BYTE green, const BYTE blue)
{
return [NSColor colorWithCalibratedRed:red / 255.0f
green:green / 255.0f
blue:blue / 255.0f
alpha:1.0f];
}
static NSColor* RGB(const PalEntry& color)
{
return RGB(color.r, color.g, color.b);
}
static NSColor* RGB(const DWORD color)
{
return RGB(PalEntry(color));
}
static const CGFloat PROGRESS_BAR_HEIGHT = 18.0f;
static const CGFloat NET_VIEW_HEIGHT = 88.0f;
FConsoleWindow::FConsoleWindow()
: m_window([NSWindow alloc])
, m_textView([NSTextView alloc])
, m_scrollView([NSScrollView alloc])
, m_progressBar(nil)
, m_netView(nil)
, m_netMessageText(nil)
, m_netCountText(nil)
, m_netProgressBar(nil)
, m_netAbortButton(nil)
, m_characterCount(0)
, m_netCurPos(0)
, m_netMaxPos(0)
{
const CGFloat initialWidth = 512.0f;
const CGFloat initialHeight = 384.0f;
const NSRect initialRect = NSMakeRect(0.0f, 0.0f, initialWidth, initialHeight);
[m_textView initWithFrame:initialRect];
[m_textView setEditable:NO];
[m_textView setBackgroundColor:RGB(70, 70, 70)];
[m_textView setMinSize:NSMakeSize(0.0f, initialHeight)];
[m_textView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
[m_textView setVerticallyResizable:YES];
[m_textView setHorizontallyResizable:NO];
[m_textView setAutoresizingMask:NSViewWidthSizable];
NSTextContainer* const textContainer = [m_textView textContainer];
[textContainer setContainerSize:NSMakeSize(initialWidth, FLT_MAX)];
[textContainer setWidthTracksTextView:YES];
[m_scrollView initWithFrame:NSMakeRect(0.0f, 0.0f, initialWidth, initialHeight)];
[m_scrollView setBorderType:NSNoBorder];
[m_scrollView setHasVerticalScroller:YES];
[m_scrollView setHasHorizontalScroller:NO];
[m_scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[m_scrollView setDocumentView:m_textView];
NSString* const title = [NSString stringWithFormat:@"%s %s - Console", GAMESIG, GetVersionString()];
[m_window initWithContentRect:initialRect
styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[m_window setMinSize:[m_window frame].size];
[m_window setShowsResizeIndicator:NO];
[m_window setTitle:title];
[m_window center];
[m_window exitAppOnClose];
[[m_window contentView] addSubview:m_scrollView];
[m_window makeKeyAndOrderFront:nil];
}
FConsoleWindow::~FConsoleWindow()
{
[m_window close];
}
static FConsoleWindow* s_instance;
void FConsoleWindow::CreateInstance()
{
assert(NULL == s_instance);
s_instance = new FConsoleWindow;
}
void FConsoleWindow::DeleteInstance()
{
assert(NULL != s_instance);
delete s_instance;
s_instance = NULL;
}
FConsoleWindow& FConsoleWindow::GetInstance()
{
assert(NULL != s_instance);
return *s_instance;
}
void FConsoleWindow::Show(const bool visible)
{
if (visible)
{
[m_window orderFront:nil];
}
else
{
[m_window orderOut:nil];
}
}
void FConsoleWindow::ShowFatalError(const char* const message)
{
SetProgressBar(false);
NetDone();
const CGFloat textViewWidth = [m_scrollView frame].size.width;
ExpandTextView(-32.0f);
NSButton* quitButton = [[NSButton alloc] initWithFrame:NSMakeRect(textViewWidth - 76.0f, 0.0f, 72.0f, 30.0f)];
[quitButton setAutoresizingMask:NSViewMinXMargin];
[quitButton setBezelStyle:NSRoundedBezelStyle];
[quitButton setTitle:@"Quit"];
[quitButton setKeyEquivalent:@"\r"];
[quitButton setTarget:NSApp];
[quitButton setAction:@selector(terminate:)];
NSView* quitPanel = [[NSView alloc] initWithFrame:NSMakeRect(0.0f, 0.0f, textViewWidth, 32.0f)];
[quitPanel setAutoresizingMask:NSViewWidthSizable];
[quitPanel addSubview:quitButton];
[[m_window contentView] addSubview:quitPanel];
[m_window orderFront:nil];
AddText(PalEntry(255, 0, 0), "\nExecution could not continue.\n");
AddText(PalEntry(255, 255, 170), message);
AddText("\n");
[NSApp runModalForWindow:m_window];
}
void FConsoleWindow::AddText(const char* message)
{
PalEntry color(223, 223, 223);
char buffer[1024] = {};
size_t pos = 0;
bool reset = false;
while (*message != '\0')
{
if ((TEXTCOLOR_ESCAPE == *message && 0 != pos)
|| (pos == sizeof buffer - 1)
|| reset)
{
buffer[pos] = '\0';
pos = 0;
reset = false;
AddText(color, buffer);
}
#define CHECK_BUFFER_SPACE \
if (pos >= sizeof buffer - 3) { reset = true; continue; }
if (TEXTCOLOR_ESCAPE == *message)
{
const BYTE* colorID = reinterpret_cast<const BYTE*>(message) + 1;
if ('\0' == colorID)
{
break;
}
const EColorRange range = V_ParseFontColor(colorID, CR_UNTRANSLATED, CR_YELLOW);
if (range != CR_UNDEFINED)
{
color = V_LogColorFromColorRange(range);
}
message += 2;
}
else if (0x1d == *message) // Opening bar character
{
CHECK_BUFFER_SPACE;
// Insert BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT
buffer[pos++] = '\xe2';
buffer[pos++] = '\x95';
buffer[pos++] = '\xbc';
++message;
}
else if (0x1e == *message) // Middle bar character
{
CHECK_BUFFER_SPACE;
// Insert BOX DRAWINGS HEAVY HORIZONTAL
buffer[pos++] = '\xe2';
buffer[pos++] = '\x94';
buffer[pos++] = '\x81';
++message;
}
else if (0x1f == *message) // Closing bar character
{
CHECK_BUFFER_SPACE;
// Insert BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT
buffer[pos++] = '\xe2';
buffer[pos++] = '\x95';
buffer[pos++] = '\xbe';
++message;
}
else
{
buffer[pos++] = *message++;
}
#undef CHECK_BUFFER_SPACE
}
if (0 != pos)
{
buffer[pos] = '\0';
AddText(color, buffer);
}
if ([m_window isVisible])
{
[m_textView scrollRangeToVisible:NSMakeRange(m_characterCount, 0)];
[[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode];
}
}
void FConsoleWindow::AddText(const PalEntry& color, const char* const message)
{
NSString* const text = [NSString stringWithUTF8String:message];
NSDictionary* const attributes = [NSDictionary dictionaryWithObjectsAndKeys:
[NSFont systemFontOfSize:14.0f], NSFontAttributeName,
RGB(color), NSForegroundColorAttributeName,
nil];
NSAttributedString* const formattedText =
[[NSAttributedString alloc] initWithString:text
attributes:attributes];
[[m_textView textStorage] appendAttributedString:formattedText];
m_characterCount += [text length];
}
void FConsoleWindow::SetTitleText()
{
static const CGFloat TITLE_TEXT_HEIGHT = 32.0f;
NSRect textViewFrame = [m_scrollView frame];
textViewFrame.size.height -= TITLE_TEXT_HEIGHT;
[m_scrollView setFrame:textViewFrame];
const NSRect titleTextRect = NSMakeRect(
0.0f,
textViewFrame.origin.y + textViewFrame.size.height,
textViewFrame.size.width,
TITLE_TEXT_HEIGHT);
NSTextField* titleText = [[NSTextField alloc] initWithFrame:titleTextRect];
[titleText setStringValue:[NSString stringWithUTF8String:DoomStartupInfo.Name]];
[titleText setAlignment:NSCenterTextAlignment];
[titleText setTextColor:RGB(DoomStartupInfo.FgColor)];
[titleText setBackgroundColor:RGB(DoomStartupInfo.BkColor)];
[titleText setFont:[NSFont fontWithName:@"Trebuchet MS Bold" size:18.0f]];
[titleText setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin];
[titleText setSelectable:NO];
[titleText setBordered:NO];
[[m_window contentView] addSubview:titleText];
}
void FConsoleWindow::SetProgressBar(const bool visible)
{
if ( (!visible && nil == m_progressBar)
|| (visible && nil != m_progressBar))
{
return;
}
if (visible)
{
ExpandTextView(-PROGRESS_BAR_HEIGHT);
m_progressBar = [[NSProgressIndicator alloc] initWithFrame:NSMakeRect(2.0f, 0.0f, 508.0f, 16.0f)];
[m_progressBar setIndeterminate:NO];
[m_progressBar setAutoresizingMask:NSViewWidthSizable];
[[m_window contentView] addSubview:m_progressBar];
}
else
{
ExpandTextView(PROGRESS_BAR_HEIGHT);
[m_progressBar removeFromSuperview];
[m_progressBar release];
m_progressBar = nil;
}
}
void FConsoleWindow::ExpandTextView(const float height)
{
NSRect textFrame = [m_scrollView frame];
textFrame.origin.y -= height;
textFrame.size.height += height;
[m_scrollView setFrame:textFrame];
}
void FConsoleWindow::Progress(const int current, const int maximum)
{
if (nil == m_progressBar)
{
return;
}
static unsigned int previousTime = I_MSTime();
unsigned int currentTime = I_MSTime();
if (currentTime - previousTime > 33) // approx. 30 FPS
{
previousTime = currentTime;
[m_progressBar setMaxValue:maximum];
[m_progressBar setDoubleValue:current];
[[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode];
}
}
void FConsoleWindow::NetInit(const char* const message, const int playerCount)
{
if (nil == m_netView)
{
SetProgressBar(false);
ExpandTextView(-NET_VIEW_HEIGHT);
// Message like 'Waiting for players' or 'Contacting host'
m_netMessageText = [[NSTextField alloc] initWithFrame:NSMakeRect(12.0f, 64.0f, 400.0f, 16.0f)];
[m_netMessageText setAutoresizingMask:NSViewWidthSizable];
[m_netMessageText setDrawsBackground:NO];
[m_netMessageText setSelectable:NO];
[m_netMessageText setBordered:NO];
// Text with connected/total players count
m_netCountText = [[NSTextField alloc] initWithFrame:NSMakeRect(428.0f, 64.0f, 72.0f, 16.0f)];
[m_netCountText setAutoresizingMask:NSViewMinXMargin];
[m_netCountText setAlignment:NSRightTextAlignment];
[m_netCountText setDrawsBackground:NO];
[m_netCountText setSelectable:NO];
[m_netCountText setBordered:NO];
// Connection progress
m_netProgressBar = [[NSProgressIndicator alloc] initWithFrame:NSMakeRect(12.0f, 40.0f, 488.0f, 16.0f)];
[m_netProgressBar setAutoresizingMask:NSViewWidthSizable];
[m_netProgressBar setMaxValue:playerCount];
if (0 == playerCount)
{
// Joining game
[m_netProgressBar setIndeterminate:YES];
[m_netProgressBar startAnimation:nil];
}
else
{
// Hosting game
[m_netProgressBar setIndeterminate:NO];
}
// Cancel network game button
m_netAbortButton = [[NSButton alloc] initWithFrame:NSMakeRect(432.0f, 8.0f, 72.0f, 28.0f)];
[m_netAbortButton setAutoresizingMask:NSViewMinXMargin];
[m_netAbortButton setBezelStyle:NSRoundedBezelStyle];
[m_netAbortButton setTitle:@"Cancel"];
[m_netAbortButton setKeyEquivalent:@"\r"];
[m_netAbortButton setTarget:NSApp];
[m_netAbortButton setAction:@selector(terminate:)];
// Panel for controls above
m_netView = [[NSView alloc] initWithFrame:NSMakeRect(0.0f, 0.0f, 512.0f, NET_VIEW_HEIGHT)];
[m_netView setAutoresizingMask:NSViewWidthSizable];
[m_netView addSubview:m_netMessageText];
[m_netView addSubview:m_netCountText];
[m_netView addSubview:m_netProgressBar];
[m_netView addSubview:m_netAbortButton];
NSRect windowRect = [m_window frame];
windowRect.origin.y -= NET_VIEW_HEIGHT;
windowRect.size.height += NET_VIEW_HEIGHT;
[m_window setFrame:windowRect display:YES];
[[m_window contentView] addSubview:m_netView];
}
[m_netMessageText setStringValue:[NSString stringWithUTF8String:message]];
m_netCurPos = 0;
m_netMaxPos = playerCount;
NetProgress(1); // You always know about yourself
}
void FConsoleWindow::NetProgress(const int count)
{
if (0 == count)
{
++m_netCurPos;
}
else
{
m_netCurPos = count;
}
if (nil == m_netView)
{
return;
}
if (m_netMaxPos > 1)
{
[m_netCountText setStringValue:[NSString stringWithFormat:@"%d / %d", m_netCurPos, m_netMaxPos]];
[m_netProgressBar setDoubleValue:MIN(m_netCurPos, m_netMaxPos)];
}
}
void FConsoleWindow::NetDone()
{
if (nil != m_netView)
{
ExpandTextView(NET_VIEW_HEIGHT);
[m_netView removeFromSuperview];
[m_netView release];
m_netView = nil;
// Released by m_netView
m_netMessageText = nil;
m_netCountText = nil;
m_netProgressBar = nil;
m_netAbortButton = nil;
}
}

192
src/posix/cocoa/st_start.mm Normal file
View file

@ -0,0 +1,192 @@
/*
** st_start.mm
**
**---------------------------------------------------------------------------
** Copyright 2015 Alexey Lysiuk
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include <unistd.h>
#import <Foundation/NSRunLoop.h>
#include "c_cvars.h"
#include "st_console.h"
#include "st_start.h"
#include "v_text.h"
FStartupScreen *StartScreen;
CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 0)
{
self = 0;
}
else if (self > 2)
{
self = 2;
}
}
// ---------------------------------------------------------------------------
class FBasicStartupScreen : public FStartupScreen
{
public:
FBasicStartupScreen(int maxProgress, bool showBar);
~FBasicStartupScreen();
virtual void Progress();
virtual void NetInit(const char* message, int playerCount);
virtual void NetProgress(int count);
virtual void NetMessage(const char *format, ...);
virtual void NetDone();
virtual bool NetLoop(bool (*timerCallback)(void*), void* userData);
};
FBasicStartupScreen::FBasicStartupScreen(int maxProgress, bool showBar)
: FStartupScreen(maxProgress)
{
FConsoleWindow& consoleWindow = FConsoleWindow::GetInstance();
consoleWindow.SetProgressBar(true);
consoleWindow.SetTitleText();
#if 0
// Testing code, please do not remove
consoleWindow.AddText("----------------------------------------------------------------\n");
consoleWindow.AddText("1234567890 !@#$%^&*() ,<.>/?;:'\" [{]}\\| `~-_=+ "
"This is very very very long message needed to trigger word wrapping...\n\n");
consoleWindow.AddText("Multiline...\n\tmessage...\n\t\twith...\n\t\t\ttabs.\n\n");
consoleWindow.AddText(TEXTCOLOR_BRICK "TEXTCOLOR_BRICK\n" TEXTCOLOR_TAN "TEXTCOLOR_TAN\n");
consoleWindow.AddText(TEXTCOLOR_GRAY "TEXTCOLOR_GRAY & TEXTCOLOR_GREY\n");
consoleWindow.AddText(TEXTCOLOR_GREEN "TEXTCOLOR_GREEN\n" TEXTCOLOR_BROWN "TEXTCOLOR_BROWN\n");
consoleWindow.AddText(TEXTCOLOR_GOLD "TEXTCOLOR_GOLD\n" TEXTCOLOR_RED "TEXTCOLOR_RED\n");
consoleWindow.AddText(TEXTCOLOR_BLUE "TEXTCOLOR_BLUE\n" TEXTCOLOR_ORANGE "TEXTCOLOR_ORANGE\n");
consoleWindow.AddText(TEXTCOLOR_WHITE "TEXTCOLOR_WHITE\n" TEXTCOLOR_YELLOW "TEXTCOLOR_YELLOW\n");
consoleWindow.AddText(TEXTCOLOR_UNTRANSLATED "TEXTCOLOR_UNTRANSLATED\n");
consoleWindow.AddText(TEXTCOLOR_BLACK "TEXTCOLOR_BLACK\n" TEXTCOLOR_LIGHTBLUE "TEXTCOLOR_LIGHTBLUE\n");
consoleWindow.AddText(TEXTCOLOR_CREAM "TEXTCOLOR_CREAM\n" TEXTCOLOR_OLIVE "TEXTCOLOR_OLIVE\n");
consoleWindow.AddText(TEXTCOLOR_DARKGREEN "TEXTCOLOR_DARKGREEN\n" TEXTCOLOR_DARKRED "TEXTCOLOR_DARKRED\n");
consoleWindow.AddText(TEXTCOLOR_DARKBROWN "TEXTCOLOR_DARKBROWN\n" TEXTCOLOR_PURPLE "TEXTCOLOR_PURPLE\n");
consoleWindow.AddText(TEXTCOLOR_DARKGRAY "TEXTCOLOR_DARKGRAY\n" TEXTCOLOR_CYAN "TEXTCOLOR_CYAN\n");
consoleWindow.AddText(TEXTCOLOR_NORMAL "TEXTCOLOR_NORMAL\n" TEXTCOLOR_BOLD "TEXTCOLOR_BOLD\n");
consoleWindow.AddText(TEXTCOLOR_CHAT "TEXTCOLOR_CHAT\n" TEXTCOLOR_TEAMCHAT "TEXTCOLOR_TEAMCHAT\n");
consoleWindow.AddText("----------------------------------------------------------------\n");
#endif // _DEBUG
}
FBasicStartupScreen::~FBasicStartupScreen()
{
FConsoleWindow::GetInstance().SetProgressBar(false);
}
void FBasicStartupScreen::Progress()
{
if (CurPos < MaxPos)
{
++CurPos;
}
FConsoleWindow::GetInstance().Progress(CurPos, MaxPos);
}
void FBasicStartupScreen::NetInit(const char* const message, const int playerCount)
{
FConsoleWindow::GetInstance().NetInit(message, playerCount);
}
void FBasicStartupScreen::NetProgress(const int count)
{
FConsoleWindow::GetInstance().NetProgress(count);
}
void FBasicStartupScreen::NetMessage(const char* const format, ...)
{
va_list args;
va_start(args, format);
FString message;
message.VFormat(format, args);
va_end(args);
Printf("%s\n", message.GetChars());
}
void FBasicStartupScreen::NetDone()
{
FConsoleWindow::GetInstance().NetDone();
}
bool FBasicStartupScreen::NetLoop(bool (*timerCallback)(void*), void* const userData)
{
while (true)
{
if (timerCallback(userData))
{
break;
}
[[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode];
// Do not poll to often
usleep(50000);
}
return true;
}
// ---------------------------------------------------------------------------
FStartupScreen *FStartupScreen::CreateInstance(const int maxProgress)
{
return new FBasicStartupScreen(maxProgress, true);
}
// ---------------------------------------------------------------------------
void ST_Endoom()
{
extern void I_ShutdownJoysticks();
I_ShutdownJoysticks();
exit(0);
}

View file

@ -462,20 +462,14 @@ static void RestartWithParameters(const char* iwadPath, NSString* parameters)
[pool release];
}
void I_SetMainWindowVisible(bool visible);
// Simple wrapper so we can call this from outside.
int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
I_SetMainWindowVisible(false);
IWADPicker *picker = [IWADPicker alloc];
int ret = [picker pickIWad:wads num:numwads showWindow:showwin defaultWad:defaultiwad];
I_SetMainWindowVisible(true);
NSString* parametersToAppend = [picker commandLineParameters];
osx_additional_parameters = [parametersToAppend UTF8String];

View file

@ -54,8 +54,3 @@ bool I_SetCursor(FTexture *cursorpic)
}
return true;
}
void I_SetMainWindowVisible(bool visible)
{
}

View file

@ -252,25 +252,26 @@ bool F7ZFile::Open(bool quiet)
}
return false;
}
NumLumps = Archive->DB.db.NumFiles;
CSzArEx* const archPtr = &Archive->DB;
NumLumps = archPtr->NumFiles;
Lumps = new F7ZLump[NumLumps];
F7ZLump *lump_p = Lumps;
TArray<UInt16> nameUTF16;
TArray<char> nameASCII;
for (DWORD i = 0; i < NumLumps; ++i)
{
CSzFileItem *file = &Archive->DB.db.Files[i];
// skip Directories
if (file->IsDir)
if (SzArEx_IsDir(archPtr, i))
{
skipped++;
continue;
}
const size_t nameLength = SzArEx_GetFileNameUtf16(&Archive->DB, i, NULL);
const size_t nameLength = SzArEx_GetFileNameUtf16(archPtr, i, NULL);
if (0 == nameLength)
{
@ -280,7 +281,7 @@ bool F7ZFile::Open(bool quiet)
nameUTF16.Resize((unsigned)nameLength);
nameASCII.Resize((unsigned)nameLength);
SzArEx_GetFileNameUtf16(&Archive->DB, i, &nameUTF16[0]);
SzArEx_GetFileNameUtf16(archPtr, i, &nameUTF16[0]);
for (size_t c = 0; c < nameLength; ++c)
{
nameASCII[c] = static_cast<char>(nameUTF16[c]);
@ -291,7 +292,7 @@ bool F7ZFile::Open(bool quiet)
name.ToLower();
lump_p->LumpNameSetup(name);
lump_p->LumpSize = int(file->Size);
lump_p->LumpSize = static_cast<int>(SzArEx_GetFileSize(archPtr, i));
lump_p->Owner = this;
lump_p->Flags = LUMPF_ZIPFILE;
lump_p->Position = i;

View file

@ -27,14 +27,14 @@
#ifndef __COMMON_H
#define __COMMON_H
#define SAMPLE_16BIT 0x01
#define SAMPLE_UNSIGNED 0x02
#define SAMPLE_LOOP 0x04
#define SAMPLE_PINGPONG 0x08
#define SAMPLE_REVERSE 0x10
#define SAMPLE_SUSTAIN 0x20
#define SAMPLE_ENVELOPE 0x40
#define SAMPLE_CLAMPED 0x80
#define SAMPLE_16BIT 0x01
#define SAMPLE_UNSIGNED 0x02
#define SAMPLE_LOOP 0x04
#define SAMPLE_PINGPONG 0x08
#define SAMPLE_REVERSE 0x10
#define SAMPLE_SUSTAIN 0x20
#define SAMPLE_ENVELOPE 0x40
#define SAMPLE_CLAMPED 0x80
#ifdef DEBUG_SAMPLES
#define SAMPLE_CONVERT_DEBUG(dx) printf("\r%s\n",dx)
@ -45,19 +45,19 @@
extern unsigned short int _WM_SampleRate;
struct _sample {
unsigned long int data_length;
unsigned long int loop_start;
unsigned long int loop_end;
unsigned long int loop_size;
unsigned int data_length;
unsigned int loop_start;
unsigned int loop_end;
unsigned int loop_size;
unsigned char loop_fraction;
unsigned short int rate;
unsigned long int freq_low;
unsigned long int freq_high;
unsigned long int freq_root;
unsigned short rate;
unsigned int freq_low;
unsigned int freq_high;
unsigned int freq_root;
unsigned char modes;
signed long int env_rate[7];
signed long int env_target[7];
unsigned long int inc_div;
signed int env_rate[7];
signed int env_target[7];
unsigned int inc_div;
signed short *data;
struct _sample *next;
};

View file

@ -1,31 +1,26 @@
/*
gus_pat.c
Midi Wavetable Processing library
Copyright (C) Chris Ison 2001-2011
Copyright (C) Bret Curtis 2013-2014
This file is part of WildMIDI.
WildMIDI is free software: you can redistribute and/or modify the player
under the terms of the GNU General Public License and you can redistribute
and/or modify the library under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, either version 3 of
the licenses, or(at your option) any later version.
WildMIDI is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
the GNU Lesser General Public License for more details.
You should have received a copy of the GNU General Public License and the
GNU Lesser General Public License along with WildMIDI. If not, see
<http://www.gnu.org/licenses/>.
* gus_pat.c -- Midi Wavetable Processing library
*
* Copyright (C) WildMIDI Developers 2001-2015
*
* This file is part of WildMIDI.
*
* WildMIDI is free software: you can redistribute and/or modify the player
* under the terms of the GNU General Public License and you can redistribute
* and/or modify the library under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of
* the licenses, or(at your option) any later version.
*
* WildMIDI is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
* the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License and the
* GNU Lesser General Public License along with WildMIDI. If not, see
* <http://www.gnu.org/licenses/>.
*/
//#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@ -737,6 +732,8 @@ struct _sample * _WM_load_gus_pat(const char *filename, int fix_release) {
};
unsigned long int tmp_loop;
/*unused*/fix_release;
SAMPLE_CONVERT_DEBUG(__FUNCTION__); SAMPLE_CONVERT_DEBUG(filename);
if ((gus_patch = _WM_BufferFile(filename, &gus_size)) == NULL) {
@ -839,17 +836,80 @@ struct _sample * _WM_load_gus_pat(const char *filename, int fix_release) {
/*
FIXME: Experimental Hacky Fix
This looks for "dodgy" release envelope settings that faulty editors
may have set and attempts to corrects it.
if (fix_release)
Lets make this automatic ...
*/
if (fix_release) {
if (env_time_table[gus_patch[gus_ptr + 40]]
< env_time_table[gus_patch[gus_ptr + 41]]) {
unsigned char tmp_hack_rate = gus_patch[gus_ptr + 41];
gus_patch[gus_ptr + 41] = gus_patch[gus_ptr + 40];
gus_patch[gus_ptr + 40] = tmp_hack_rate;
{
/*
After studying faulty gus_pats this way may work better
Testing to determine if any further adjustments are required
*/
if (env_time_table[gus_patch[gus_ptr + 40]] < env_time_table[gus_patch[gus_ptr + 41]]) {
unsigned char tmp_hack_rate = 0;
if (env_time_table[gus_patch[gus_ptr + 41]] < env_time_table[gus_patch[gus_ptr + 42]]) {
// 1 2 3
tmp_hack_rate = gus_patch[gus_ptr + 40];
gus_patch[gus_ptr + 40] = gus_patch[gus_ptr + 42];
gus_patch[gus_ptr + 42] = tmp_hack_rate;
} else if (env_time_table[gus_patch[gus_ptr + 41]] == env_time_table[gus_patch[gus_ptr + 42]]) {
// 1 2 2
tmp_hack_rate = gus_patch[gus_ptr + 40];
gus_patch[gus_ptr + 40] = gus_patch[gus_ptr + 42];
gus_patch[gus_ptr + 41] = gus_patch[gus_ptr + 42];
gus_patch[gus_ptr + 42] = tmp_hack_rate;
} else {
if (env_time_table[gus_patch[gus_ptr + 40]] < env_time_table[gus_patch[gus_ptr + 42]]) {
// 1 3 2
tmp_hack_rate = gus_patch[gus_ptr + 40];
gus_patch[gus_ptr + 40] = gus_patch[gus_ptr + 41];
gus_patch[gus_ptr + 41] = gus_patch[gus_ptr + 42];
gus_patch[gus_ptr + 42] = tmp_hack_rate;
} else {
// 2 3 1 or 1 2 1
tmp_hack_rate = gus_patch[gus_ptr + 40];
gus_patch[gus_ptr + 40] = gus_patch[gus_ptr + 41];
gus_patch[gus_ptr + 41] = tmp_hack_rate;
}
}
} else if (env_time_table[gus_patch[gus_ptr + 41]] < env_time_table[gus_patch[gus_ptr + 42]]) {
unsigned char tmp_hack_rate = 0;
if (env_time_table[gus_patch[gus_ptr + 40]] < env_time_table[gus_patch[gus_ptr + 42]]) {
// 2 1 3
tmp_hack_rate = gus_patch[gus_ptr + 40];
gus_patch[gus_ptr + 40] = gus_patch[gus_ptr + 42];
gus_patch[gus_ptr + 42] = gus_patch[gus_ptr + 41];
gus_patch[gus_ptr + 41] = tmp_hack_rate;
} else {
// 3 1 2
tmp_hack_rate = gus_patch[gus_ptr + 41];
gus_patch[gus_ptr + 41] = gus_patch[gus_ptr + 42];
gus_patch[gus_ptr + 42] = tmp_hack_rate;
}
}
#if 0
if ((env_time_table[gus_patch[gus_ptr + 40]] < env_time_table[gus_patch[gus_ptr + 41]]) && (env_time_table[gus_patch[gus_ptr + 41]] == env_time_table[gus_patch[gus_ptr + 42]])) {
uint8_t tmp_hack_rate = 0;
tmp_hack_rate = gus_patch[gus_ptr + 41];
gus_patch[gus_ptr + 41] = gus_patch[gus_ptr + 40];
gus_patch[gus_ptr + 42] = gus_patch[gus_ptr + 40];
gus_patch[gus_ptr + 40] = tmp_hack_rate;
tmp_hack_rate = gus_patch[gus_ptr + 47];
gus_patch[gus_ptr + 47] = gus_patch[gus_ptr + 46];
gus_patch[gus_ptr + 48] = gus_patch[gus_ptr + 46];
gus_patch[gus_ptr + 46] = tmp_hack_rate;
}
#endif
}
for (i = 0; i < 6; i++) {
GUSPAT_INT_DEBUG("Envelope #",i);
if (gus_sample->modes & SAMPLE_ENVELOPE) {
unsigned char env_rate = gus_patch[gus_ptr + 37 + i];
gus_sample->env_target[i] = 16448 * gus_patch[gus_ptr + 43 + i];
@ -886,6 +946,27 @@ struct _sample * _WM_load_gus_pat(const char *filename, int fix_release) {
return NULL;
}
/*
Test and set decay expected decay time after a note off
NOTE: This sets samples for full range decay
*/
if (gus_sample->modes & SAMPLE_ENVELOPE) {
double samples_f = 0.0;
if (gus_sample->modes & SAMPLE_CLAMPED) {
samples_f = (4194301.0 - (float)gus_sample->env_target[5]) / gus_sample->env_rate[5];
} else {
if (gus_sample->modes & SAMPLE_SUSTAIN) {
samples_f = (4194301.0 - (float)gus_sample->env_target[3]) / gus_sample->env_rate[3];
samples_f += (float)(gus_sample->env_target[3] - gus_sample->env_target[4]) / gus_sample->env_rate[4];
} else {
samples_f = (4194301.0 - (float)gus_sample->env_target[4]) / gus_sample->env_rate[4];
}
samples_f += (float)(gus_sample->env_target[4] - gus_sample->env_target[5]) / gus_sample->env_rate[5];
}
samples_f += (float)gus_sample->env_target[5] / gus_sample->env_rate[6];
}
gus_ptr += tmp_cnt;
gus_sample->loop_start = (gus_sample->loop_start << 10)
| (((gus_sample->loop_fraction & 0x0f) << 10) / 16);

View file

@ -116,36 +116,24 @@ struct _note {
unsigned char velocity;
struct _patch *patch;
struct _sample *sample;
unsigned long int sample_pos;
unsigned long int sample_inc;
signed long int env_inc;
unsigned int sample_pos;
unsigned int sample_inc;
signed int env_inc;
unsigned char env;
signed long int env_level;
signed int env_level;
unsigned char modes;
unsigned char hold;
unsigned char active;
struct _note *replay;
struct _note *next;
unsigned long int vol_lvl;
unsigned int left_mix_volume;
unsigned int right_mix_volume;
unsigned char is_off;
};
struct _miditrack {
unsigned long int length;
unsigned long int ptr;
unsigned long int delta;
unsigned char running_event;
unsigned char EOT;
};
struct _mdi_patches {
struct _patch *patch;
struct _mdi_patch *next;
};
struct _event_data {
unsigned char channel;
unsigned long int data;
unsigned int data;
};
struct _mdi {
@ -286,30 +274,70 @@ static signed short int lin_volume[] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72,
878, 886, 894, 903, 911, 919, 927, 935, 943, 951, 959, 967, 975, 983,
991, 999, 1007, 1015, 1024 };
/* f: pow(( VOLUME / 127.0 ), 2.0 ) * 1024.0 */
static signed short int sqr_volume[] = { 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 9,
10, 12, 14, 16, 18, 20, 22, 25, 27, 30, 33, 36, 39, 42, 46, 49, 53, 57,
61, 65, 69, 73, 77, 82, 86, 91, 96, 101, 106, 111, 117, 122, 128, 134,
140, 146, 152, 158, 165, 171, 178, 185, 192, 199, 206, 213, 221, 228,
236, 244, 251, 260, 268, 276, 284, 293, 302, 311, 320, 329, 338, 347,
357, 366, 376, 386, 396, 406, 416, 426, 437, 447, 458, 469, 480, 491,
502, 514, 525, 537, 549, 560, 572, 585, 597, 609, 622, 634, 647, 660,
673, 686, 699, 713, 726, 740, 754, 768, 782, 796, 810, 825, 839, 854,
869, 884, 899, 914, 929, 944, 960, 976, 992, 1007, 1024 };
/* f: As per midi 2 standard */
static float dBm_volume[] = { -999999.999999f, -84.15214884f, -72.11094901f,
-65.06729865f, -60.06974919f, -56.19334866f, -53.02609882f, -50.34822724f,
-48.02854936f, -45.98244846f, -44.15214884f, -42.49644143f, -40.984899f,
-39.59441475f, -38.30702741f, -37.10849848f, -35.98734953f, -34.93419198f,
-33.94124863f, -33.0020048f, -32.11094901f, -31.26337705f, -30.45524161f,
-29.6830354f, -28.94369917f, -28.23454849f, -27.55321492f, -26.89759827f,
-26.26582758f, -25.65622892f, -25.06729865f, -24.49768108f, -23.94614971f,
-23.41159124f, -22.89299216f, -22.38942706f, -21.90004881f, -21.42407988f,
-20.96080497f, -20.50956456f, -20.06974919f, -19.64079457f, -19.22217722f,
-18.81341062f, -18.41404178f, -18.02364829f, -17.64183557f, -17.26823452f,
-16.90249934f, -16.54430564f, -16.19334866f, -15.84934179f, -15.51201509f,
-15.18111405f, -14.85639845f, -14.53764126f, -14.22462776f, -13.91715461f,
-13.6150291f, -13.31806837f, -13.02609882f, -12.73895544f, -12.45648126f,
-12.17852686f, -11.90494988f, -11.63561457f, -11.37039142f, -11.10915673f,
-10.85179233f, -10.59818521f, -10.34822724f, -10.10181489f, -9.858848981f,
-9.619234433f, -9.382880049f, -9.149698303f, -8.919605147f, -8.692519831f,
-8.468364731f, -8.247065187f, -8.028549359f, -7.812748083f, -7.599594743f,
-7.389025143f, -7.180977396f, -6.97539181f, -6.772210788f, -6.571378733f,
-6.372841952f, -6.176548572f, -5.982448461f, -5.790493145f, -5.600635744f,
-5.412830896f, -5.227034694f, -5.043204627f, -4.861299517f, -4.681279468f,
-4.503105811f, -4.326741054f, -4.152148838f, -3.979293887f, -3.808141968f,
-3.63865985f, -3.470815266f, -3.304576875f, -3.139914228f, -2.976797731f,
-2.815198619f, -2.655088921f, -2.496441432f, -2.339229687f, -2.183427931f,
-2.029011099f, -1.875954785f, -1.724235224f, -1.573829269f, -1.424714368f,
-1.276868546f, -1.130270383f, -0.9848989963f, -0.8407340256f, -0.6977556112f,
-0.5559443807f, -0.4152814317f, -0.2757483179f, -0.1373270335f, 0 };
/* f: pow(( VOLUME / 127.0 ), 0.5 ) * 1024.0 */
static signed short int pan_volume[] = { 0, 90, 128, 157, 181, 203, 222, 240,
257, 272, 287, 301, 314, 327, 339, 351, 363, 374, 385, 396, 406, 416,
426, 435, 445, 454, 463, 472, 480, 489, 497, 505, 514, 521, 529, 537,
545, 552, 560, 567, 574, 581, 588, 595, 602, 609, 616, 622, 629, 636,
642, 648, 655, 661, 667, 673, 679, 686, 692, 697, 703, 709, 715, 721,
726, 732, 738, 743, 749, 754, 760, 765, 771, 776, 781, 786, 792, 797,
802, 807, 812, 817, 822, 827, 832, 837, 842, 847, 852, 857, 862, 866,
871, 876, 880, 885, 890, 894, 899, 904, 908, 913, 917, 922, 926, 931,
935, 939, 944, 948, 953, 957, 961, 965, 970, 974, 978, 982, 987, 991,
995, 999, 1003, 1007, 1011, 1015, 1019, 1024 };
/* f: As per midi 2 standard */
static float dBm_pan_volume[127] = {
-999999.999999f, -87.6945020928f, -73.8331126923f, -65.7264009888f,
-59.9763864074f, -55.5181788833f, -51.8774481743f, -48.8011722841f,
-46.1383198371f, -43.7914727130f, -41.6941147218f, -39.7988027954f,
-38.0705069530f, -36.4826252703f, -35.0144798827f, -33.6496789707f,
-32.3750084716f, -31.1796603753f, -30.0546819321f, -28.9925739783f,
-27.9869924122f, -27.0325225804f, -26.1245061976f, -25.2589067713f,
-24.4322036893f, -23.6413079424f, -22.8834943857f, -22.1563467917f,
-21.4577129008f, -20.7856673630f, -20.1384809653f, -19.5145949062f,
-18.9125991563f, -18.3312141503f, -17.7692752119f, -17.2257192381f,
-16.6995732597f, -16.1899445690f, -15.6960121652f, -15.2170193110f,
-14.7522670314f, -14.3011084168f, -13.8629436112f, -13.4372153915f,
-13.0234052546f, -12.6210299451f, -12.2296383638f, -11.8488088095f,
-11.4781465116f, -11.1172814164f, -10.7658661983f, -10.4235744668f,
-10.0900991491f, -9.7651510261f, -9.4484574055f, -9.1397609172f,
-8.8388184168f, -8.5453999868f, -8.2592880250f, -7.9802764101f,
-7.7081697387f, -7.4427826248f, -7.1839390567f, -6.9314718056f,
-6.6852218807f, -6.4450380272f, -6.2107762624f, -5.9822994468f,
-5.7594768878f, -5.5421839719f, -5.3303018237f, -5.1237169899f,
-4.9223211445f, -4.7260108155f, -4.5346871303f, -4.3482555779f,
-4.1666257875f, -3.9897113219f, -3.8174294843f, -3.6497011373f,
-3.4864505345f, -3.3276051620f, -3.1730955900f, -3.0228553340f,
-2.8768207245f, -2.7349307844f, -2.5971271143f, -2.4633537845f,
-2.3335572335f, -2.2076861725f, -2.0856914960f, -1.9675261968f,
-1.8531452871f, -1.7425057233f, -1.6355663356f, -1.5322877618f,
-1.4326323846f, -1.3365642732f, -1.2440491272f, -1.1550542250f,
-1.0695483746f, -0.9875018671f, -0.9088864335f, -0.8336752037f,
-0.7618426682f, -0.6933646420f, -0.6282182304f, -0.5663817981f,
-0.5078349388f, -0.4525584478f, -0.4005342959f, -0.3517456058f,
-0.3061766293f, -0.2638127266f, -0.2246403475f, -0.1886470134f,
-0.1558213016f, -0.1261528303f, -0.0996322457f, -0.0762512098f,
-0.0560023899f, -0.0388794497f, -0.0248770409f, -0.0139907967f,
-0.0062173263f, -0.0015542108f, 0.0000000000f };
static unsigned long int freq_table[] = { 837201792, 837685632, 838169728,
static unsigned int freq_table[] = { 837201792, 837685632, 838169728,
838653568, 839138240, 839623232, 840108480, 840593984, 841079680,
841565184, 842051648, 842538240, 843025152, 843512320, 843999232,
844486976, 844975040, 845463360, 845951936, 846440320, 846929536,
@ -1191,7 +1219,6 @@ static int load_sample(struct _patch *sample_patch) {
samp_max = tmp_sample->data[i];
if (tmp_sample->data[i] < samp_min)
samp_min = tmp_sample->data[i];
}
if (samp_max > tmp_max)
tmp_max = samp_max;
@ -1386,47 +1413,121 @@ get_sample_data(struct _patch *sample_patch, unsigned long int freq) {
return return_sample;
}
/* Should be called in any function that effects note volumes */
void _WM_AdjustNoteVolumes(struct _mdi *mdi, unsigned char ch, struct _note *nte) {
double premix_dBm;
double premix_lin;
unsigned char pan_ofs;
double premix_dBm_left;
double premix_dBm_right;
double premix_left;
double premix_right;
double volume_adj;
unsigned vol_ofs;
/*
Pointless CPU heating checks to shoosh up a compiler
*/
if (ch > 0x0f) ch = 0x0f;
pan_ofs = mdi->channel[ch].balance + mdi->channel[ch].pan - 64;
vol_ofs = (nte->velocity * ((mdi->channel[ch].expression * mdi->channel[ch].volume) / 127)) / 127;
/*
This value is to reduce the chance of clipping.
Higher value means lower overall volume,
Lower value means higher overall volume.
NOTE: The lower the value the higher the chance of clipping.
FIXME: Still needs tuning. Clipping heard at a value of 3.75
*/
#define VOL_DIVISOR 4.0
volume_adj = ((float)WM_MasterVolume / 1024.0) / VOL_DIVISOR;
// Pan 0 and 1 are both hard left so 64 can be centered
if (pan_ofs > 127) pan_ofs = 127;
if (--pan_ofs < 0) pan_ofs = 0;
premix_dBm_left = dBm_pan_volume[126-pan_ofs];
premix_dBm_right = dBm_pan_volume[pan_ofs];
if (mdi->info.mixer_options & WM_MO_LOG_VOLUME) {
premix_dBm = dBm_volume[vol_ofs];
premix_dBm_left += premix_dBm;
premix_dBm_right += premix_dBm;
premix_left = (pow(10.0,(premix_dBm_left / 20.0))) * volume_adj;
premix_right = (pow(10.0,(premix_dBm_right / 20.0))) * volume_adj;
} else {
premix_lin = (float)(lin_volume[vol_ofs]) / 1024.0;
premix_left = premix_lin * pow(10.0, (premix_dBm_left / 20)) * volume_adj;
premix_right = premix_lin * pow(10.0, (premix_dBm_right / 20)) * volume_adj;
}
nte->left_mix_volume = (int)(premix_left * 1024.0);
nte->right_mix_volume = (int)(premix_right * 1024.0);
}
/* Should be called in any function that effects channel volumes */
/* Calling this function with a value > 15 will make it adjust notes on all channels */
void _WM_AdjustChannelVolumes(struct _mdi *mdi, unsigned char ch) {
struct _note *nte = mdi->note;
if (nte != NULL) {
do {
if (ch <= 15) {
if ((nte->noteid >> 8) == ch) {
goto _DO_ADJUST;
}
} else {
_DO_ADJUST:
_WM_AdjustNoteVolumes(mdi, ch, nte);
if (nte->replay) _WM_AdjustNoteVolumes(mdi, ch, nte->replay);
}
nte = nte->next;
} while (nte != NULL);
}
}
static void do_note_off_extra(struct _note *nte) {
nte->is_off = 0;
if (nte->hold) {
nte->hold |= HOLD_OFF;
} else {
if (!(nte->modes & SAMPLE_ENVELOPE)) {
if (nte->modes & SAMPLE_LOOP) {
nte->modes ^= SAMPLE_LOOP;
}
nte->env_inc = 0;
} else if (nte->modes & SAMPLE_CLAMPED) {
if (nte->env < 5) {
nte->env = 5;
if (nte->env_level > nte->sample->env_target[5]) {
nte->env_inc = -nte->sample->env_rate[5];
} else {
nte->env_inc = nte->sample->env_rate[5];
}
}
#if 1
} else if (nte->modes & SAMPLE_SUSTAIN) {
if (nte->env < 3) {
nte->env = 3;
if (nte->env_level > nte->sample->env_target[3]) {
nte->env_inc = -nte->sample->env_rate[3];
} else {
nte->env_inc = nte->sample->env_rate[3];
}
}
#endif
} else if (nte->env < 4) {
nte->env = 4;
if (nte->env_level > nte->sample->env_target[4]) {
nte->env_inc = -nte->sample->env_rate[4];
if (!(nte->modes & SAMPLE_ENVELOPE)) {
if (nte->modes & SAMPLE_LOOP) {
nte->modes ^= SAMPLE_LOOP;
}
nte->env_inc = 0;
} else if (nte->hold) {
nte->hold |= HOLD_OFF;
} else if (nte->modes & SAMPLE_SUSTAIN) {
if (nte->env < 3) {
nte->env = 3;
if (nte->env_level > nte->sample->env_target[3]) {
nte->env_inc = -nte->sample->env_rate[3];
} else {
nte->env_inc = nte->sample->env_rate[4];
nte->env_inc = nte->sample->env_rate[3];
}
}
} else if (nte->modes & SAMPLE_CLAMPED) {
if (nte->env < 5) {
nte->env = 5;
if (nte->env_level > nte->sample->env_target[5]) {
nte->env_inc = -nte->sample->env_rate[5];
} else {
nte->env_inc = nte->sample->env_rate[5];
}
}
} else if (nte->env < 4) {
nte->env = 4;
if (nte->env_level > nte->sample->env_target[4]) {
nte->env_inc = -nte->sample->env_rate[4];
} else {
nte->env_inc = nte->sample->env_rate[4];
}
}
}
@ -1447,7 +1548,10 @@ static void do_note_off(struct _mdi *mdi, struct _event_data *data) {
return;
}
if (nte->env == 0) {
if ((nte->modes & SAMPLE_ENVELOPE) && (nte->env == 0)) {
// This is a fix for notes that end before the
// initial step of the envelope has completed
// making it impossible to hear them at times.
nte->is_off = 1;
} else {
do_note_off_extra(nte);
@ -1475,24 +1579,6 @@ static inline unsigned long int get_inc(struct _mdi *mdi, struct _note *nte) {
/ nte->sample->inc_div));
}
static inline unsigned long int get_volume(struct _mdi *mdi, unsigned char ch,
struct _note *nte) {
signed long int volume;
if (mdi->info.mixer_options & WM_MO_LOG_VOLUME) {
volume = (sqr_volume[mdi->channel[ch].volume]
* sqr_volume[mdi->channel[ch].expression]
* sqr_volume[nte->velocity]) / 1048576;
} else {
volume = (lin_volume[mdi->channel[ch].volume]
* lin_volume[mdi->channel[ch].expression]
* lin_volume[nte->velocity]) / 1048576;
}
volume = volume * nte->patch->amp / 100;
return (volume);
}
static void do_note_on(struct _mdi *mdi, struct _event_data *data) {
struct _note *nte;
struct _note *prev_nte;
@ -1502,7 +1588,7 @@ static void do_note_on(struct _mdi *mdi, struct _event_data *data) {
struct _sample *sample;
unsigned char ch = data->channel;
unsigned char note = (unsigned char)(data->data >> 8);
unsigned char velocity = (data->data & 0xFF);
unsigned char velocity = (unsigned char)(data->data & 0xFF);
if (velocity == 0x00) {
do_note_off(mdi, data);
@ -1580,9 +1666,9 @@ static void do_note_on(struct _mdi *mdi, struct _event_data *data) {
nte->env_level = 0;
nte->modes = sample->modes;
nte->hold = mdi->channel[ch].hold;
nte->vol_lvl = get_volume(mdi, ch, nte);
nte->replay = NULL;
nte->is_off = 0;
_WM_AdjustNoteVolumes(mdi, ch, nte);
}
static void do_aftertouch(struct _mdi *mdi, struct _event_data *data) {
@ -1599,40 +1685,14 @@ static void do_aftertouch(struct _mdi *mdi, struct _event_data *data) {
}
}
nte->velocity = data->data & 0xff;
nte->vol_lvl = get_volume(mdi, ch, nte);
nte->velocity = (unsigned char)data->data;
_WM_AdjustNoteVolumes(mdi, ch, nte);
if (nte->replay) {
nte->replay->velocity = data->data & 0xff;
nte->replay->vol_lvl = get_volume(mdi, ch, nte->replay);
nte->replay->velocity = (unsigned char)data->data;
_WM_AdjustNoteVolumes(mdi, ch, nte->replay);
}
}
static void do_pan_adjust(struct _mdi *mdi, unsigned char ch) {
signed short int pan_adjust = mdi->channel[ch].balance
+ mdi->channel[ch].pan;
signed short int left, right;
int amp = 32;
if (pan_adjust > 63) {
pan_adjust = 63;
} else if (pan_adjust < -64) {
pan_adjust = -64;
}
pan_adjust += 64;
/* if (mdi->info.mixer_options & WM_MO_LOG_VOLUME) {*/
left = (pan_volume[127 - pan_adjust] * WM_MasterVolume * amp) / 1048576;
right = (pan_volume[pan_adjust] * WM_MasterVolume * amp) / 1048576;
/* } else {
left = (lin_volume[127 - pan_adjust] * WM_MasterVolume * amp) / 1048576;
right= (lin_volume[pan_adjust] * WM_MasterVolume * amp) / 1048576;
}*/
mdi->channel[ch].left_adjust = left;
mdi->channel[ch].right_adjust = right;
}
static void do_control_bank_select(struct _mdi *mdi, struct _event_data *data) {
unsigned char ch = data->channel;
mdi->channel[ch].bank = (unsigned char)data->data;
@ -1658,33 +1718,22 @@ static void do_control_channel_volume(struct _mdi *mdi,
unsigned char ch = data->channel;
mdi->channel[ch].volume = (unsigned char)data->data;
if (note_data) {
do {
if ((note_data->noteid >> 8) == ch) {
note_data->vol_lvl = get_volume(mdi, ch, note_data);
if (note_data->replay)
note_data->replay->vol_lvl = get_volume(mdi, ch,
note_data->replay);
}
note_data = note_data->next;
} while (note_data);
}
_WM_AdjustChannelVolumes(mdi, ch);
}
static void do_control_channel_balance(struct _mdi *mdi,
struct _event_data *data) {
unsigned char ch = data->channel;
mdi->channel[ch].balance = (signed char)(data->data - 64);
do_pan_adjust(mdi, ch);
mdi->channel[ch].balance = (signed char)(data->data);
_WM_AdjustChannelVolumes(mdi, ch);
}
static void do_control_channel_pan(struct _mdi *mdi, struct _event_data *data) {
unsigned char ch = data->channel;
mdi->channel[ch].pan = (signed char)(data->data - 64);
do_pan_adjust(mdi, ch);
mdi->channel[ch].pan = (signed char)(data->data);
_WM_AdjustChannelVolumes(mdi, ch);
}
static void do_control_channel_expression(struct _mdi *mdi,
@ -1693,18 +1742,7 @@ static void do_control_channel_expression(struct _mdi *mdi,
unsigned char ch = data->channel;
mdi->channel[ch].expression = (unsigned char)data->data;
if (note_data) {
do {
if ((note_data->noteid >> 8) == ch) {
note_data->vol_lvl = get_volume(mdi, ch, note_data);
if (note_data->replay)
note_data->replay->vol_lvl = get_volume(mdi, ch,
note_data->replay);
}
note_data = note_data->next;
} while (note_data);
}
_WM_AdjustChannelVolumes(mdi, ch);
}
static void do_control_data_entry_fine(struct _mdi *mdi,
@ -1794,9 +1832,19 @@ static void do_control_data_decrement(struct _mdi *mdi,
mdi->channel[ch].pitch_range--;
}
}
static void do_control_non_registered_param(struct _mdi *mdi,
static void do_control_non_registered_param_fine(struct _mdi *mdi,
struct _event_data *data) {
unsigned char ch = data->channel;
mdi->channel[ch].reg_data = (mdi->channel[ch].reg_data & 0x3F80)
| data->data;
mdi->channel[ch].reg_non = 1;
}
static void do_control_non_registered_param_course(struct _mdi *mdi,
struct _event_data *data) {
unsigned char ch = data->channel;
mdi->channel[ch].reg_data = (mdi->channel[ch].reg_data & 0x7F)
| (data->data << 7);
mdi->channel[ch].reg_non = 1;
}
@ -1841,33 +1889,13 @@ static void do_control_channel_controllers_off(struct _mdi *mdi,
mdi->channel[ch].expression = 127;
mdi->channel[ch].pressure = 127;
mdi->channel[ch].volume = 100;
mdi->channel[ch].pan = 0;
mdi->channel[ch].balance = 0;
mdi->channel[ch].reg_data = 0xffff;
mdi->channel[ch].pitch_range = 200;
mdi->channel[ch].pitch = 0;
mdi->channel[ch].pitch_adjust = 0;
mdi->channel[ch].hold = 0;
do_pan_adjust(mdi, ch);
if (note_data) {
do {
if ((note_data->noteid >> 8) == ch) {
note_data->sample_inc = get_inc(mdi, note_data);
note_data->velocity = 0;
note_data->vol_lvl = get_volume(mdi, ch, note_data);
note_data->hold = 0;
if (note_data->replay) {
note_data->replay->velocity = (unsigned char)data->data;
note_data->replay->vol_lvl = get_volume(mdi, ch,
note_data->replay);
}
}
note_data = note_data->next;
} while (note_data);
}
_WM_AdjustChannelVolumes(mdi, ch);
}
static void do_control_channel_notes_off(struct _mdi *mdi,
@ -1919,20 +1947,16 @@ static void do_channel_pressure(struct _mdi *mdi, struct _event_data *data) {
MIDI_EVENT_DEBUG(__FUNCTION__,ch);
if (note_data) {
do {
if ((note_data->noteid >> 8) == ch) {
note_data->velocity = (unsigned char)data->data;
note_data->vol_lvl = get_volume(mdi, ch, note_data);
if (note_data->replay) {
note_data->replay->velocity = (unsigned char)data->data;
note_data->replay->vol_lvl = get_volume(mdi, ch,
note_data->replay);
}
while (note_data) {
if ((note_data->noteid >> 8) == ch) {
note_data->velocity = (unsigned char)data->data;
_WM_AdjustNoteVolumes(mdi, ch, note_data);
if (note_data->replay) {
note_data->replay->velocity = (unsigned char)data->data;
_WM_AdjustNoteVolumes(mdi, ch, note_data->replay);
}
note_data = note_data->next;
} while (note_data);
}
note_data = note_data->next;
}
}
@ -1976,7 +2000,7 @@ static void do_sysex_roland_drum_track(struct _mdi *mdi,
}
}
static void do_sysex_roland_reset(struct _mdi *mdi, struct _event_data *data) {
static void do_sysex_gm_reset(struct _mdi *mdi, struct _event_data *data) {
int i;
for (i = 0; i < 16; i++) {
mdi->channel[i].bank = 0;
@ -1989,20 +2013,29 @@ static void do_sysex_roland_reset(struct _mdi *mdi, struct _event_data *data) {
mdi->channel[i].volume = 100;
mdi->channel[i].pressure = 127;
mdi->channel[i].expression = 127;
mdi->channel[i].balance = 0;
mdi->channel[i].pan = 0;
mdi->channel[i].left_adjust = 1;
mdi->channel[i].right_adjust = 1;
mdi->channel[i].balance = 64;
mdi->channel[i].pan = 64;
mdi->channel[i].pitch = 0;
mdi->channel[i].pitch_range = 200;
mdi->channel[i].reg_data = 0xFFFF;
mdi->channel[i].isdrum = 0;
do_pan_adjust(mdi, i);
}
/* I would not expect notes to be active when this event
triggers but we'll adjust active notes as well just in case */
_WM_AdjustChannelVolumes(mdi,16); // A setting > 15 adjusts all channels
mdi->channel[9].isdrum = 1;
UNUSED(data); /* NOOP, to please the compiler gods */
}
static void do_sysex_roland_reset(struct _mdi *mdi, struct _event_data *data) {
do_sysex_gm_reset(mdi, data);
}
static void do_sysex_yamaha_reset(struct _mdi *mdi, struct _event_data *data) {
do_sysex_gm_reset(mdi, data);
}
static int add_handle(void * handle) {
struct _hndl *tmp_handle = NULL;
@ -2084,56 +2117,11 @@ static void freeMDI(struct _mdi *mdi) {
free(mdi);
}
static unsigned long int get_decay_samples(struct _patch *patch, unsigned char note) {
struct _sample *sample = NULL;
unsigned long int freq = 0;
unsigned long int decay_samples = 0;
if (patch == NULL)
return 0;
/* first get the freq we need so we can check the right sample */
if (patch->patchid & 0x80) {
/* is a drum patch */
if (patch->note) {
freq = freq_table[(patch->note % 12) * 100]
>> (10 - (patch->note / 12));
} else {
freq = freq_table[(note % 12) * 100] >> (10 - (note / 12));
}
} else {
freq = freq_table[(note % 12) * 100] >> (10 - (note / 12));
}
/* get the sample */
sample = get_sample_data(patch, (freq / 100));
if (sample == NULL)
return 0;
if (patch->patchid & 0x80) {
float sratedata = ((float) sample->rate / (float) _WM_SampleRate)
* (float) (sample->data_length >> 10);
decay_samples = (unsigned long int) sratedata;
/* printf("Drums (%i / %i) * %lu = %f\n", sample->rate, _WM_SampleRate, (sample->data_length >> 10), sratedata);*/
} else if (sample->modes & SAMPLE_CLAMPED) {
decay_samples = (4194303 / sample->env_rate[5]);
/* printf("clamped 4194303 / %lu = %lu\n", sample->env_rate[5], decay_samples);*/
} else {
decay_samples =
((4194303 - sample->env_target[4]) / sample->env_rate[4])
+ (sample->env_target[4] / sample->env_rate[5]);
/* printf("NOT clamped ((4194303 - %lu) / %lu) + (%lu / %lu)) = %lu\n", sample->env_target[4], sample->env_rate[4], sample->env_target[4], sample->env_rate[5], decay_samples);*/
}
return decay_samples;
}
static int *WM_Mix_Linear(midi * handle, int * buffer, unsigned long int count)
{
struct _mdi *mdi = (struct _mdi *)handle;
unsigned long int data_pos;
signed int premix, left_mix, right_mix;
signed int vol_mul;
struct _note *note_data = NULL;
do {
@ -2147,20 +2135,11 @@ static int *WM_Mix_Linear(midi * handle, int * buffer, unsigned long int count)
* ===================
*/
data_pos = note_data->sample_pos >> FPBITS;
vol_mul = ((note_data->vol_lvl
* (note_data->env_level >> 12)) >> FPBITS);
premix = ((note_data->sample->data[data_pos] + (((note_data->sample->data[data_pos + 1] - note_data->sample->data[data_pos]) * (int)(note_data->sample_pos & FPMASK)) / 1024)) * (note_data->env_level >> 12)) / 1024;
premix = (note_data->sample->data[data_pos]
+ ((note_data->sample->data[data_pos + 1]
- note_data->sample->data[data_pos])
* (signed long int) (note_data->sample_pos
& FPMASK)>> FPBITS)) * vol_mul
/ 1024;
left_mix += premix
* mdi->channel[note_data->noteid >> 8].left_adjust;
right_mix += premix
* mdi->channel[note_data->noteid >> 8].right_adjust;
left_mix += (premix * (int)note_data->left_mix_volume) / 1024;
right_mix += (premix * (int)note_data->right_mix_volume) / 1024;
/*
* ========================
@ -2168,19 +2147,16 @@ static int *WM_Mix_Linear(midi * handle, int * buffer, unsigned long int count)
* ========================
*/
note_data->sample_pos += note_data->sample_inc;
if (note_data->sample_pos > note_data->sample->loop_end) {
if (note_data->modes & SAMPLE_LOOP) {
if (note_data->modes & SAMPLE_LOOP) {
if (note_data->sample_pos > note_data->sample->loop_end) {
note_data->sample_pos =
note_data->sample->loop_start
+ ((note_data->sample_pos
- note_data->sample->loop_start)
% note_data->sample->loop_size);
} else if (note_data->sample_pos >= note_data->sample->data_length) {
if (note_data->replay == NULL) {
goto KILL_NOTE;
}
goto RESTART_NOTE;
note_data->sample->loop_start
+ ((note_data->sample_pos
- note_data->sample->loop_start)
% note_data->sample->loop_size);
}
} else if (note_data->sample_pos >= note_data->sample->data_length) {
goto END_THIS_NOTE;
}
if (note_data->env_inc == 0) {
@ -2189,35 +2165,32 @@ static int *WM_Mix_Linear(midi * handle, int * buffer, unsigned long int count)
}
note_data->env_level += note_data->env_inc;
if (note_data->env_level > 4194304) {
note_data->env_level =
note_data->sample->env_target[note_data->env];
}
if (((note_data->env_inc < 0)
&& (note_data->env_level
> note_data->sample->env_target[note_data->env]))
|| ((note_data->env_inc > 0)
&& (note_data->env_level
< note_data->sample->env_target[note_data->env])))
{
note_data = note_data->next;
continue;
if (note_data->env_inc < 0) {
if (note_data->env_level > note_data->sample->env_target[note_data->env]) {
note_data = note_data->next;
continue;
}
} else if (note_data->env_inc > 0) {
if (note_data->env_level < note_data->sample->env_target[note_data->env]) {
note_data = note_data->next;
continue;
}
}
// Yes could have a condition here but
// it would create another bottleneck
note_data->env_level =
note_data->sample->env_target[note_data->env];
switch (note_data->env) {
case 0:
#if 0
if (!(note_data->modes & SAMPLE_ENVELOPE)) {
note_data->env_inc = 0;
note_data = note_data->next;
continue;
}
#endif
break;
case 2:
if (note_data->modes & SAMPLE_SUSTAIN) {
if (note_data->modes & SAMPLE_SUSTAIN /*|| note_data->hold*/) {
note_data->env_inc = 0;
note_data = note_data->next;
continue;
@ -2236,7 +2209,7 @@ static int *WM_Mix_Linear(midi * handle, int * buffer, unsigned long int count)
break;
case 5:
if (note_data->env_level == 0) {
goto KILL_NOTE;
goto END_THIS_NOTE;
}
/* sample release */
if (note_data->modes & SAMPLE_LOOP)
@ -2245,8 +2218,9 @@ static int *WM_Mix_Linear(midi * handle, int * buffer, unsigned long int count)
note_data = note_data->next;
continue;
case 6:
END_THIS_NOTE:
if (note_data->replay != NULL) {
RESTART_NOTE: note_data->active = 0;
note_data->active = 0;
{
struct _note *prev_note = NULL;
struct _note *nte_array = mdi->note;
@ -2267,7 +2241,7 @@ static int *WM_Mix_Linear(midi * handle, int * buffer, unsigned long int count)
note_data->active = 1;
}
} else {
KILL_NOTE: note_data->active = 0;
note_data->active = 0;
{
struct _note *prev_note = NULL;
struct _note *nte_array = mdi->note;
@ -2312,10 +2286,7 @@ static int *WM_Mix_Linear(midi * handle, int * buffer, unsigned long int count)
* mix the channels together
* =========================
*/
left_mix /= 1024;
right_mix /= 1024;
}
*buffer++ = left_mix;
*buffer++ = right_mix;
} while (--count);
@ -2329,7 +2300,6 @@ static int *WM_Mix_Gauss(midi * handle, int * buffer, unsigned long int count)
struct _mdi *mdi = (struct _mdi *)handle;
unsigned long int data_pos;
signed int premix, left_mix, right_mix;
signed int vol_mul;
struct _note *note_data = NULL;
signed short int *sptr;
double y, xd;
@ -2348,8 +2318,6 @@ static int *WM_Mix_Gauss(midi * handle, int * buffer, unsigned long int count)
* ===================
*/
data_pos = note_data->sample_pos >> FPBITS;
vol_mul = ((note_data->vol_lvl
* (note_data->env_level >> 12)) >> FPBITS);
/* check to see if we're near one of the ends */
left = data_pos;
@ -2389,12 +2357,10 @@ static int *WM_Mix_Gauss(midi * handle, int * buffer, unsigned long int count)
} while (gptr <= gend);
}
premix = (long) (y * vol_mul / 1024);
premix = (int)((y * (note_data->env_level >> 12)) / 1024);
left_mix += premix
* mdi->channel[note_data->noteid >> 8].left_adjust;
right_mix += premix
* mdi->channel[note_data->noteid >> 8].right_adjust;
left_mix += (premix * (int)note_data->left_mix_volume) / 1024;
right_mix += (premix * (int)note_data->right_mix_volume) / 1024;
/*
* ========================
@ -2411,10 +2377,7 @@ static int *WM_Mix_Gauss(midi * handle, int * buffer, unsigned long int count)
- note_data->sample->loop_start)
% note_data->sample->loop_size);
} else if (note_data->sample_pos >= note_data->sample->data_length) {
if (note_data->replay == NULL) {
goto KILL_NOTE;
}
goto RESTART_NOTE;
goto END_THIS_NOTE;
}
}
@ -2424,33 +2387,32 @@ static int *WM_Mix_Gauss(midi * handle, int * buffer, unsigned long int count)
}
note_data->env_level += note_data->env_inc;
if (note_data->env_level > 4194304) {
note_data->env_level =
note_data->sample->env_target[note_data->env];
}
if (
((note_data->env_inc < 0)
&& (note_data->env_level
> note_data->sample->env_target[note_data->env]))
|| ((note_data->env_inc > 0)
&& (note_data->env_level
< note_data->sample->env_target[note_data->env]))
) {
note_data = note_data->next;
continue;
if (note_data->env_inc < 0) {
if (note_data->env_level
> note_data->sample->env_target[note_data->env]) {
note_data = note_data->next;
continue;
}
} else if (note_data->env_inc > 0) {
if (note_data->env_level
< note_data->sample->env_target[note_data->env]) {
note_data = note_data->next;
continue;
}
}
// Yes could have a condition here but
// it would create another bottleneck
note_data->env_level =
note_data->sample->env_target[note_data->env];
switch (note_data->env) {
case 0:
#if 0
if (!(note_data->modes & SAMPLE_ENVELOPE)) {
note_data->env_inc = 0;
note_data = note_data->next;
continue;
}
#endif
break;
case 2:
if (note_data->modes & SAMPLE_SUSTAIN) {
@ -2472,7 +2434,7 @@ static int *WM_Mix_Gauss(midi * handle, int * buffer, unsigned long int count)
break;
case 5:
if (note_data->env_level == 0) {
goto KILL_NOTE;
goto END_THIS_NOTE;
}
/* sample release */
if (note_data->modes & SAMPLE_LOOP)
@ -2481,8 +2443,9 @@ static int *WM_Mix_Gauss(midi * handle, int * buffer, unsigned long int count)
note_data = note_data->next;
continue;
case 6:
END_THIS_NOTE:
if (note_data->replay != NULL) {
RESTART_NOTE: note_data->active = 0;
note_data->active = 0;
{
struct _note *prev_note = NULL;
struct _note *nte_array = mdi->note;
@ -2503,7 +2466,7 @@ static int *WM_Mix_Gauss(midi * handle, int * buffer, unsigned long int count)
note_data->active = 1;
}
} else {
KILL_NOTE: note_data->active = 0;
note_data->active = 0;
{
struct _note *prev_note = NULL;
struct _note *nte_array = mdi->note;
@ -2548,10 +2511,7 @@ static int *WM_Mix_Gauss(midi * handle, int * buffer, unsigned long int count)
* mix the channels together
* =========================
*/
left_mix /= 1024;
right_mix /= 1024;
}
*buffer++ = left_mix;
*buffer++ = right_mix;
} while (--count);
@ -2644,16 +2604,6 @@ WM_SYMBOL int WildMidi_MasterVolume(unsigned char master_volume) {
WM_MasterVolume = lin_volume[master_volume];
if (tmp_handle) {
while (tmp_handle) {
mdi = (struct _mdi *) tmp_handle->handle;
for (i = 0; i < 16; i++) {
do_pan_adjust(mdi, i);
}
tmp_handle = tmp_handle->next;
}
}
return 0;
}
@ -2734,7 +2684,6 @@ midi *WildMidi_NewMidi() {
WM_SYMBOL int WildMidi_SetOption(midi * handle, unsigned short int options,
unsigned short int setting) {
struct _mdi *mdi;
int i;
if (!WM_Initialized) {
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0);
@ -2765,22 +2714,8 @@ WM_SYMBOL int WildMidi_SetOption(midi * handle, unsigned short int options,
| (options & setting));
if (options & WM_MO_LOG_VOLUME) {
struct _note *note_data = mdi->note;
for (i = 0; i < 16; i++) {
do_pan_adjust(mdi, i);
}
if (note_data) {
do {
note_data->vol_lvl = get_volume(mdi, (note_data->noteid >> 8),
note_data);
if (note_data->replay)
note_data->replay->vol_lvl = get_volume(mdi,
(note_data->noteid >> 8), note_data->replay);
note_data = note_data->next;
} while (note_data);
}
_WM_AdjustChannelVolumes(mdi, 16); // Settings greater than 15
// adjust all channels
} else if (options & WM_MO_REVERB) {
_WM_reset_reverb(mdi->reverb);
}
@ -2905,23 +2840,23 @@ void WildMidi_Renderer::ShortEvent(int status, int parm1, int parm2)
ev.data = parm2;
switch (parm1)
{
case 0: do_control_bank_select(mdi, &ev); break;
case 6: do_control_data_entry_course(mdi, &ev); break; // [sic]
case 7: do_control_channel_volume(mdi, &ev); break;
case 8: do_control_channel_balance(mdi, &ev); break;
case 10: do_control_channel_pan(mdi, &ev); break;
case 11: do_control_channel_expression(mdi, &ev); break;
case 38: do_control_data_entry_fine(mdi, &ev); break;
case 64: do_control_channel_hold(mdi, &ev); break;
case 96: do_control_data_increment(mdi, &ev); break;
case 97: do_control_data_decrement(mdi, &ev); break;
case 98:
case 99: do_control_non_registered_param(mdi, &ev); break;
case 100: do_control_registered_param_fine(mdi, &ev); break;
case 101: do_control_registered_param_course(mdi, &ev); break; // [sic]
case 120: do_control_channel_sound_off(mdi, &ev); break;
case 121: do_control_channel_controllers_off(mdi, &ev); break;
case 123: do_control_channel_notes_off(mdi, &ev); break;
case 0: do_control_bank_select(mdi, &ev); break;
case 6: do_control_data_entry_course(mdi, &ev); break; // [sic]
case 7: do_control_channel_volume(mdi, &ev); break;
case 8: do_control_channel_balance(mdi, &ev); break;
case 10: do_control_channel_pan(mdi, &ev); break;
case 11: do_control_channel_expression(mdi, &ev); break;
case 38: do_control_data_entry_fine(mdi, &ev); break;
case 64: do_control_channel_hold(mdi, &ev); break;
case 96: do_control_data_increment(mdi, &ev); break;
case 97: do_control_data_decrement(mdi, &ev); break;
case 98: do_control_non_registered_param_fine(mdi, &ev); break;
case 99: do_control_non_registered_param_course(mdi, &ev); break; // [sic]
case 100: do_control_registered_param_fine(mdi, &ev); break;
case 101: do_control_registered_param_course(mdi, &ev); break; // [sic]
case 120: do_control_channel_sound_off(mdi, &ev); break;
case 121: do_control_channel_controllers_off(mdi, &ev); break;
case 123: do_control_channel_notes_off(mdi, &ev); break;
}
}
}
@ -2967,6 +2902,20 @@ void WildMidi_Renderer::LongEvent(const unsigned char *data, int len)
}
}
}
// For non-Roland Sysex messages */
else
{
const unsigned char gm_reset[] = { 0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7 };
const unsigned char yamaha_reset[] = { 0xf0, 0x43, 0x10, 0x4c, 0x00, 0x00, 0x7e, 0x00, 0xf7};
if (len == 6 && memcmp(gm_reset, data, 6) == 0)
{
do_sysex_gm_reset((_mdi *)handle, NULL);
}
else if (len == 9 && memcmp(yamaha_reset, data, 9) == 0)
{
do_sysex_yamaha_reset((_mdi *)handle, NULL);
}
}
}
void WildMidi_Renderer::ComputeOutput(float *fbuffer, int len)