diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index f0d4eade8..65dbf8181 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -11,13 +11,19 @@ jobs: matrix: config: - { - name: "Visual Studio 64-bit", + name: "Visual Studio 2022", + os: windows-2022, + extra_options: "-A x64", + build_type: "Release" + } + - { + name: "Visual Studio 2019", os: windows-2019, extra_options: "-A x64", build_type: "Release" } - { - name: "Visual Studio 64-bit", + name: "Visual Studio 2019", os: windows-2019, extra_options: "-A x64", build_type: "Debug" diff --git a/libraries/lzma/C/7z.h b/libraries/lzma/C/7z.h index 6c7886e38..304f75ffc 100644 --- a/libraries/lzma/C/7z.h +++ b/libraries/lzma/C/7z.h @@ -1,5 +1,5 @@ /* 7z.h -- 7z interface -2017-04-03 : Igor Pavlov : Public domain */ +2018-07-02 : Igor Pavlov : Public domain */ #ifndef __7Z_H #define __7Z_H @@ -91,6 +91,8 @@ typedef struct UInt64 *CoderUnpackSizes; // for all coders in all folders Byte *CodersData; + + UInt64 RangeLimit; } CSzAr; UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex); diff --git a/libraries/lzma/C/7zArcIn.c b/libraries/lzma/C/7zArcIn.c index f74d0fad5..0d9dec41e 100644 --- a/libraries/lzma/C/7zArcIn.c +++ b/libraries/lzma/C/7zArcIn.c @@ -1,5 +1,5 @@ /* 7zArcIn.c -- 7z Input functions -2018-12-31 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -75,7 +75,7 @@ static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc) return SZ_OK; } -void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) +static void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL; ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL; @@ -83,7 +83,7 @@ void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) #define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; } -void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc) +static void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL; ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL; @@ -105,6 +105,8 @@ static void SzAr_Init(CSzAr *p) p->CoderUnpackSizes = NULL; p->CodersData = NULL; + + p->RangeLimit = 0; } static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc) @@ -502,7 +504,7 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) return SZ_ERROR_ARCHIVE; if (propsSize >= 0x80) return SZ_ERROR_UNSUPPORTED; - coder->PropsOffset = sd->Data - dataStart; + coder->PropsOffset = (size_t)(sd->Data - dataStart); coder->PropsSize = (Byte)propsSize; sd->Data += (size_t)propsSize; sd->Size -= (size_t)propsSize; @@ -677,7 +679,7 @@ static SRes ReadUnpackInfo(CSzAr *p, { UInt32 numCoders, ci, numInStreams = 0; - p->FoCodersOffsets[fo] = sd.Data - startBufPtr; + p->FoCodersOffsets[fo] = (size_t)(sd.Data - startBufPtr); RINOK(SzReadNumber32(&sd, &numCoders)); if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX) @@ -797,7 +799,7 @@ static SRes ReadUnpackInfo(CSzAr *p, p->FoToCoderUnpackSizes[fo] = numCodersOutStreams; { - size_t dataSize = sd.Data - startBufPtr; + const size_t dataSize = (size_t)(sd.Data - startBufPtr); p->FoStartPackStreamIndex[fo] = packStreamIndex; p->FoCodersOffsets[fo] = dataSize; MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc); @@ -885,7 +887,7 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i)) numSubDigests += numStreams; } - ssi->sdNumSubStreams.Size = sd->Data - ssi->sdNumSubStreams.Data; + ssi->sdNumSubStreams.Size = (size_t)(sd->Data - ssi->sdNumSubStreams.Data); continue; } if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd) @@ -907,7 +909,7 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) { ssi->sdSizes.Data = sd->Data; RINOK(SkipNumbers(sd, numUnpackSizesInData)); - ssi->sdSizes.Size = sd->Data - ssi->sdSizes.Data; + ssi->sdSizes.Size = (size_t)(sd->Data - ssi->sdSizes.Data); RINOK(ReadID(sd, &type)); } @@ -919,7 +921,7 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) { ssi->sdCRCs.Data = sd->Data; RINOK(SkipBitUi32s(sd, numSubDigests)); - ssi->sdCRCs.Size = sd->Data - ssi->sdCRCs.Data; + ssi->sdCRCs.Size = (size_t)(sd->Data - ssi->sdCRCs.Data); } else { @@ -947,7 +949,11 @@ static SRes SzReadStreamsInfo(CSzAr *p, if (type == k7zIdPackInfo) { RINOK(ReadNumber(sd, dataOffset)); + if (*dataOffset > p->RangeLimit) + return SZ_ERROR_ARCHIVE; RINOK(ReadPackInfo(p, sd, alloc)); + if (p->PackPositions[p->NumPackStreams] > p->RangeLimit - *dataOffset) + return SZ_ERROR_ARCHIVE; RINOK(ReadID(sd, &type)); } if (type == k7zIdUnpackInfo) @@ -1028,12 +1034,12 @@ static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size return SZ_ERROR_ARCHIVE; for (p = data + pos; #ifdef _WIN32 - *(const UInt16 *)p != 0 + *(const UInt16 *)(const void *)p != 0 #else p[0] != 0 || p[1] != 0 #endif ; p += 2); - pos = p - data + 2; + pos = (size_t)(p - data) + 2; *offsets++ = (pos >> 1); } while (--numFiles); @@ -1133,6 +1139,8 @@ static SRes SzReadHeader2( SRes res; SzAr_Init(&tempAr); + tempAr.RangeLimit = p->db.RangeLimit; + res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX, p->startPosAfterHeader, &tempAr, allocTemp); *numTempBufs = tempAr.NumFolders; @@ -1526,11 +1534,13 @@ static SRes SzArEx_Open2( nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); - p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; + p->startPosAfterHeader = (UInt64)startArcPos + k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; + p->db.RangeLimit = nextHeaderOffset; + nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; @@ -1543,13 +1553,13 @@ static SRes SzArEx_Open2( { Int64 pos = 0; RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END)); - if ((UInt64)pos < startArcPos + nextHeaderOffset || - (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || - (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) + if ((UInt64)pos < (UInt64)startArcPos + nextHeaderOffset || + (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset || + (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } - RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); + RINOK(LookInStream_SeekTo(inStream, (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset)); if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; @@ -1575,6 +1585,8 @@ static SRes SzArEx_Open2( Buf_Init(&tempBuf); SzAr_Init(&tempAr); + tempAr.RangeLimit = p->db.RangeLimit; + res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp); SzAr_Free(&tempAr, allocTemp); diff --git a/libraries/lzma/C/7zCrc.c b/libraries/lzma/C/7zCrc.c index b4d84f023..f186324dd 100644 --- a/libraries/lzma/C/7zCrc.c +++ b/libraries/lzma/C/7zCrc.c @@ -1,5 +1,5 @@ /* 7zCrc.c -- CRC32 init -2017-06-06 : Igor Pavlov : Public domain */ +2021-04-01 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -26,8 +26,20 @@ typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); +extern CRC_FUNC g_CrcUpdateT4; +CRC_FUNC g_CrcUpdateT4; +extern CRC_FUNC g_CrcUpdateT8; +CRC_FUNC g_CrcUpdateT8; +extern +CRC_FUNC g_CrcUpdateT0_32; +CRC_FUNC g_CrcUpdateT0_32; +extern +CRC_FUNC g_CrcUpdateT0_64; +CRC_FUNC g_CrcUpdateT0_64; +extern +CRC_FUNC g_CrcUpdate; CRC_FUNC g_CrcUpdate; UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; @@ -44,6 +56,7 @@ UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) #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); UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) { const Byte *p = (const Byte *)data; @@ -53,6 +66,166 @@ UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const U return v; } + +/* ---------- hardware CRC ---------- */ + +#ifdef MY_CPU_LE + +#if defined(MY_CPU_ARM_OR_ARM64) + +// #pragma message("ARM*") + + #if defined(_MSC_VER) + #if defined(MY_CPU_ARM64) + #if (_MSC_VER >= 1910) + #define USE_ARM64_CRC + #endif + #endif + #elif (defined(__clang__) && (__clang_major__ >= 3)) \ + || (defined(__GNUC__) && (__GNUC__ > 4)) + #if !defined(__ARM_FEATURE_CRC32) + #define __ARM_FEATURE_CRC32 1 + #if (!defined(__clang__) || (__clang_major__ > 3)) // fix these numbers + #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc"))) + #endif + #endif + #if defined(__ARM_FEATURE_CRC32) + #define USE_ARM64_CRC + #include + #endif + #endif + +#else + +// no hardware CRC + +// #define USE_CRC_EMU + +#ifdef USE_CRC_EMU + +#pragma message("ARM64 CRC emulation") + +MY_FORCE_INLINE +UInt32 __crc32b(UInt32 v, UInt32 data) +{ + const UInt32 *table = g_CrcTable; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); + return v; +} + +MY_FORCE_INLINE +UInt32 __crc32w(UInt32 v, UInt32 data) +{ + const UInt32 *table = g_CrcTable; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + return v; +} + +MY_FORCE_INLINE +UInt32 __crc32d(UInt32 v, UInt64 data) +{ + const UInt32 *table = g_CrcTable; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + return v; +} + +#endif // USE_CRC_EMU + +#endif // defined(MY_CPU_ARM64) && defined(MY_CPU_LE) + + + +#if defined(USE_ARM64_CRC) || defined(USE_CRC_EMU) + +#define T0_32_UNROLL_BYTES (4 * 4) +#define T0_64_UNROLL_BYTES (4 * 8) + +#ifndef ATTRIB_CRC +#define ATTRIB_CRC +#endif +// #pragma message("USE ARM HW CRC") + +ATTRIB_CRC +UInt32 MY_FAST_CALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table); +ATTRIB_CRC +UInt32 MY_FAST_CALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + UNUSED_VAR(table); + + for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_32_UNROLL_BYTES - 1)) != 0; size--) + v = __crc32b(v, *p++); + + if (size >= T0_32_UNROLL_BYTES) + { + const Byte *lim = p + size; + size &= (T0_32_UNROLL_BYTES - 1); + lim -= size; + do + { + v = __crc32w(v, *(const UInt32 *)(const void *)(p)); + v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4; + v = __crc32w(v, *(const UInt32 *)(const void *)(p)); + v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4; + } + while (p != lim); + } + + for (; size != 0; size--) + v = __crc32b(v, *p++); + + return v; +} + +ATTRIB_CRC +UInt32 MY_FAST_CALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table); +ATTRIB_CRC +UInt32 MY_FAST_CALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + UNUSED_VAR(table); + + for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_64_UNROLL_BYTES - 1)) != 0; size--) + v = __crc32b(v, *p++); + + if (size >= T0_64_UNROLL_BYTES) + { + const Byte *lim = p + size; + size &= (T0_64_UNROLL_BYTES - 1); + lim -= size; + do + { + v = __crc32d(v, *(const UInt64 *)(const void *)(p)); + v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8; + v = __crc32d(v, *(const UInt64 *)(const void *)(p)); + v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8; + } + while (p != lim); + } + + for (; size != 0; size--) + v = __crc32b(v, *p++); + + return v; +} + +#endif // defined(USE_ARM64_CRC) || defined(USE_CRC_EMU) + +#endif // MY_CPU_LE + + + + void MY_FAST_CALL CrcGenerateTable() { UInt32 i; @@ -123,6 +296,27 @@ void MY_FAST_CALL CrcGenerateTable() } } #endif + #endif + #ifdef MY_CPU_LE + #ifdef USE_ARM64_CRC + if (CPU_IsSupported_CRC32()) + { + g_CrcUpdateT0_32 = CrcUpdateT0_32; + g_CrcUpdateT0_64 = CrcUpdateT0_64; + g_CrcUpdate = + #if defined(MY_CPU_ARM) + CrcUpdateT0_32; + #else + CrcUpdateT0_64; + #endif + } + #endif + + #ifdef USE_CRC_EMU + g_CrcUpdateT0_32 = CrcUpdateT0_32; + g_CrcUpdateT0_64 = CrcUpdateT0_64; + g_CrcUpdate = CrcUpdateT0_64; + #endif #endif } diff --git a/libraries/lzma/C/7zCrcOpt.c b/libraries/lzma/C/7zCrcOpt.c index 73beba298..69fad9ca2 100644 --- a/libraries/lzma/C/7zCrcOpt.c +++ b/libraries/lzma/C/7zCrcOpt.c @@ -1,5 +1,5 @@ /* 7zCrcOpt.c -- CRC32 calculation -2017-04-03 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -9,6 +9,7 @@ #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); UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) { const Byte *p = (const Byte *)data; @@ -16,7 +17,7 @@ UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const U v = CRC_UPDATE_BYTE_2(v, *p); for (; size >= 4; size -= 4, p += 4) { - v ^= *(const UInt32 *)p; + v ^= *(const UInt32 *)(const void *)p; v = (table + 0x300)[((v ) & 0xFF)] ^ (table + 0x200)[((v >> 8) & 0xFF)] @@ -28,6 +29,7 @@ UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const U return v; } +UInt32 MY_FAST_CALL CrcUpdateT8(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) { const Byte *p = (const Byte *)data; @@ -36,13 +38,13 @@ UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const U for (; size >= 8; size -= 8, p += 8) { UInt32 d; - v ^= *(const UInt32 *)p; + v ^= *(const UInt32 *)(const void *)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); + d = *((const UInt32 *)(const void *)p + 1); v ^= (table + 0x300)[((d ) & 0xFF)] ^ (table + 0x200)[((d >> 8) & 0xFF)] @@ -72,7 +74,7 @@ UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, co v = CRC_UPDATE_BYTE_2_BE(v, *p); for (; size >= 4; size -= 4, p += 4) { - v ^= *(const UInt32 *)p; + v ^= *(const UInt32 *)(const void *)p; v = (table + 0x000)[((v ) & 0xFF)] ^ (table + 0x100)[((v >> 8) & 0xFF)] @@ -94,13 +96,13 @@ UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, co for (; size >= 8; size -= 8, p += 8) { UInt32 d; - v ^= *(const UInt32 *)p; + v ^= *(const UInt32 *)(const void *)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); + d = *((const UInt32 *)(const void *)p + 1); v ^= (table + 0x000)[((d ) & 0xFF)] ^ (table + 0x100)[((d >> 8) & 0xFF)] diff --git a/libraries/lzma/C/7zDec.c b/libraries/lzma/C/7zDec.c index 7c4635211..fbfd016e1 100644 --- a/libraries/lzma/C/7zDec.c +++ b/libraries/lzma/C/7zDec.c @@ -1,5 +1,5 @@ /* 7zDec.c -- Decoding from 7z folder -2019-02-02 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -21,17 +21,20 @@ #endif #define k_Copy 0 -#define k_Delta 3 +#ifndef _7Z_NO_METHOD_LZMA2 #define k_LZMA2 0x21 +#endif #define k_LZMA 0x30101 -#define k_BCJ 0x3030103 #define k_BCJ2 0x303011B +#ifndef _7Z_NO_METHODS_FILTERS +#define k_Delta 3 +#define k_BCJ 0x3030103 #define k_PPC 0x3030205 #define k_IA64 0x3030401 #define k_ARM 0x3030501 #define k_ARMT 0x3030701 #define k_SPARC 0x3030805 - +#endif #ifdef _7ZIP_PPMD_SUPPPORT @@ -56,7 +59,7 @@ static Byte ReadByte(const IByteIn *pp) return *p->cur++; if (p->res == SZ_OK) { - size_t size = p->cur - p->begin; + size_t size = (size_t)(p->cur - p->begin); p->processed += size; p->res = ILookInStream_Skip(p->inStream, size); size = (1 << 25); @@ -101,28 +104,32 @@ static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, c Ppmd7_Init(&ppmd, order); } { - CPpmd7z_RangeDec rc; - Ppmd7z_RangeDec_CreateVTable(&rc); - rc.Stream = &s.vt; - if (!Ppmd7z_RangeDec_Init(&rc)) + ppmd.rc.dec.Stream = &s.vt; + if (!Ppmd7z_RangeDec_Init(&ppmd.rc.dec)) res = SZ_ERROR_DATA; - else if (s.extra) - res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); - else + else if (!s.extra) { - SizeT i; - for (i = 0; i < outSize; i++) + Byte *buf = outBuffer; + const Byte *lim = buf + outSize; + for (; buf != lim; buf++) { - int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.vt); + int sym = Ppmd7z_DecodeSymbol(&ppmd); if (s.extra || sym < 0) break; - outBuffer[i] = (Byte)sym; + *buf = (Byte)sym; } - if (i != outSize) - res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); - else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) + if (buf != lim) res = SZ_ERROR_DATA; + else if (!Ppmd7z_RangeDec_IsFinishedOK(&ppmd.rc.dec)) + { + /* if (Ppmd7z_DecodeSymbol(&ppmd) != PPMD7_SYM_END || !Ppmd7z_RangeDec_IsFinishedOK(&ppmd.rc.dec)) */ + res = SZ_ERROR_DATA; + } } + if (s.extra) + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); + else if (s.processed + (size_t)(s.cur - s.begin) != inSize) + res = SZ_ERROR_DATA; } Ppmd7_Free(&ppmd, allocMain); return res; @@ -365,7 +372,9 @@ static SRes CheckSupportedFolder(const CSzFolder *f) return SZ_ERROR_UNSUPPORTED; } +#ifndef _7Z_NO_METHODS_FILTERS #define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; +#endif static SRes SzFolder_Decode2(const CSzFolder *folder, const Byte *propsData, diff --git a/libraries/lzma/C/7zStream.c b/libraries/lzma/C/7zStream.c index 6b5aa1621..28a14604f 100644 --- a/libraries/lzma/C/7zStream.c +++ b/libraries/lzma/C/7zStream.c @@ -1,5 +1,5 @@ /* 7zStream.c -- 7z Stream functions -2017-04-03 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -37,7 +37,7 @@ SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf) SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset) { - Int64 t = offset; + Int64 t = (Int64)offset; return ILookInStream_Seek(stream, &t, SZ_SEEK_SET); } diff --git a/libraries/lzma/C/7zTypes.h b/libraries/lzma/C/7zTypes.h index 65b3af63c..fe4fde3ff 100644 --- a/libraries/lzma/C/7zTypes.h +++ b/libraries/lzma/C/7zTypes.h @@ -1,11 +1,13 @@ /* 7zTypes.h -- Basic types -2018-08-04 : Igor Pavlov : Public domain */ +2021-12-25 : Igor Pavlov : Public domain */ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H #ifdef _WIN32 /* #include */ +#else +#include #endif #include @@ -43,18 +45,116 @@ EXTERN_C_BEGIN typedef int SRes; +#ifdef _MSC_VER + #if _MSC_VER > 1200 + #define MY_ALIGN(n) __declspec(align(n)) + #else + #define MY_ALIGN(n) + #endif +#else + #define MY_ALIGN(n) __attribute__ ((aligned(n))) +#endif + + #ifdef _WIN32 /* typedef DWORD WRes; */ typedef unsigned WRes; #define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x) -#else +// #define MY_HRES_ERROR__INTERNAL_ERROR MY_SRes_HRESULT_FROM_WRes(ERROR_INTERNAL_ERROR) +#else // _WIN32 + +// #define ENV_HAVE_LSTAT typedef int WRes; -#define MY__FACILITY_WIN32 7 -#define MY__FACILITY__WRes MY__FACILITY_WIN32 -#define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000))) + +// (FACILITY_ERRNO = 0x800) is 7zip's FACILITY constant to represent (errno) errors in HRESULT +#define MY__FACILITY_ERRNO 0x800 +#define MY__FACILITY_WIN32 7 +#define MY__FACILITY__WRes MY__FACILITY_ERRNO + +#define MY_HRESULT_FROM_errno_CONST_ERROR(x) ((HRESULT)( \ + ( (HRESULT)(x) & 0x0000FFFF) \ + | (MY__FACILITY__WRes << 16) \ + | (HRESULT)0x80000000 )) + +#define MY_SRes_HRESULT_FROM_WRes(x) \ + ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : MY_HRESULT_FROM_errno_CONST_ERROR(x)) + +// we call macro HRESULT_FROM_WIN32 for system errors (WRes) that are (errno) +#define HRESULT_FROM_WIN32(x) MY_SRes_HRESULT_FROM_WRes(x) + +/* +#define ERROR_FILE_NOT_FOUND 2L +#define ERROR_ACCESS_DENIED 5L +#define ERROR_NO_MORE_FILES 18L +#define ERROR_LOCK_VIOLATION 33L +#define ERROR_FILE_EXISTS 80L +#define ERROR_DISK_FULL 112L +#define ERROR_NEGATIVE_SEEK 131L +#define ERROR_ALREADY_EXISTS 183L +#define ERROR_DIRECTORY 267L +#define ERROR_TOO_MANY_POSTS 298L + +#define ERROR_INTERNAL_ERROR 1359L +#define ERROR_INVALID_REPARSE_DATA 4392L +#define ERROR_REPARSE_TAG_INVALID 4393L +#define ERROR_REPARSE_TAG_MISMATCH 4394L +*/ + +// we use errno equivalents for some WIN32 errors: + +#define ERROR_INVALID_PARAMETER EINVAL +#define ERROR_INVALID_FUNCTION EINVAL +#define ERROR_ALREADY_EXISTS EEXIST +#define ERROR_FILE_EXISTS EEXIST +#define ERROR_PATH_NOT_FOUND ENOENT +#define ERROR_FILE_NOT_FOUND ENOENT +#define ERROR_DISK_FULL ENOSPC +// #define ERROR_INVALID_HANDLE EBADF + +// we use FACILITY_WIN32 for errors that has no errno equivalent +// Too many posts were made to a semaphore. +#define ERROR_TOO_MANY_POSTS ((HRESULT)0x8007012AL) +#define ERROR_INVALID_REPARSE_DATA ((HRESULT)0x80071128L) +#define ERROR_REPARSE_TAG_INVALID ((HRESULT)0x80071129L) + +// if (MY__FACILITY__WRes != FACILITY_WIN32), +// we use FACILITY_WIN32 for COM errors: +#define E_OUTOFMEMORY ((HRESULT)0x8007000EL) +#define E_INVALIDARG ((HRESULT)0x80070057L) +#define MY__E_ERROR_NEGATIVE_SEEK ((HRESULT)0x80070083L) + +/* +// we can use FACILITY_ERRNO for some COM errors, that have errno equivalents: +#define E_OUTOFMEMORY MY_HRESULT_FROM_errno_CONST_ERROR(ENOMEM) +#define E_INVALIDARG MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL) +#define MY__E_ERROR_NEGATIVE_SEEK MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL) +*/ + +// gcc / clang : (sizeof(long) == sizeof(void*)) in 32/64 bits +typedef long INT_PTR; +typedef unsigned long UINT_PTR; + +#define TEXT(quote) quote + +#define FILE_ATTRIBUTE_READONLY 0x0001 +#define FILE_ATTRIBUTE_HIDDEN 0x0002 +#define FILE_ATTRIBUTE_SYSTEM 0x0004 +#define FILE_ATTRIBUTE_DIRECTORY 0x0010 +#define FILE_ATTRIBUTE_ARCHIVE 0x0020 +#define FILE_ATTRIBUTE_DEVICE 0x0040 +#define FILE_ATTRIBUTE_NORMAL 0x0080 +#define FILE_ATTRIBUTE_TEMPORARY 0x0100 +#define FILE_ATTRIBUTE_SPARSE_FILE 0x0200 +#define FILE_ATTRIBUTE_REPARSE_POINT 0x0400 +#define FILE_ATTRIBUTE_COMPRESSED 0x0800 +#define FILE_ATTRIBUTE_OFFLINE 0x1000 +#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x2000 +#define FILE_ATTRIBUTE_ENCRYPTED 0x4000 + +#define FILE_ATTRIBUTE_UNIX_EXTENSION 0x8000 /* trick for Unix */ #endif @@ -63,6 +163,10 @@ typedef int WRes; #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #endif +#ifndef RINOK_WRes +#define RINOK_WRes(x) { WRes __result__ = (x); if (__result__ != 0) return __result__; } +#endif + typedef unsigned char Byte; typedef short Int16; typedef unsigned short UInt16; @@ -75,6 +179,40 @@ typedef int Int32; typedef unsigned int UInt32; #endif + +#ifndef _WIN32 + +typedef int INT; +typedef Int32 INT32; +typedef unsigned int UINT; +typedef UInt32 UINT32; +typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit for _WIN32 compatibility +typedef UINT32 ULONG; + +#undef DWORD +typedef UINT32 DWORD; + +#define VOID void + +#define HRESULT LONG + +typedef void *LPVOID; +// typedef void VOID; +// typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; +// gcc / clang on Unix : sizeof(long==sizeof(void*) in 32 or 64 bits) +typedef long INT_PTR; +typedef unsigned long UINT_PTR; +typedef long LONG_PTR; +typedef unsigned long DWORD_PTR; + +typedef size_t SIZE_T; + +#endif // _WIN32 + + +#define MY_HRES_ERROR__INTERNAL_ERROR ((HRESULT)0x8007054FL) + + #ifdef _SZ_NO_INT_64 /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. @@ -128,25 +266,37 @@ typedef int BoolInt; #define MY_CDECL __cdecl #define MY_FAST_CALL __fastcall -#else +#else // _MSC_VER -#define MY_NO_INLINE -#define MY_FORCE_INLINE -#define MY_CDECL -#define MY_FAST_CALL - -/* inline keyword : for C++ / C99 */ - -/* GCC, clang: */ -/* -#if defined (__GNUC__) && (__GNUC__ >= 4) -#define MY_FORCE_INLINE __attribute__((always_inline)) +#if (defined(__GNUC__) && (__GNUC__ >= 4)) \ + || (defined(__clang__) && (__clang_major__ >= 4)) \ + || defined(__INTEL_COMPILER) \ + || defined(__xlC__) #define MY_NO_INLINE __attribute__((noinline)) +// #define MY_FORCE_INLINE __attribute__((always_inline)) inline +#else +#define MY_NO_INLINE #endif -*/ +#define MY_FORCE_INLINE + + +#define MY_CDECL + +#if defined(_M_IX86) \ + || defined(__i386__) +// #define MY_FAST_CALL __attribute__((fastcall)) +// #define MY_FAST_CALL __attribute__((cdecl)) +#define MY_FAST_CALL +#elif defined(MY_CPU_AMD64) +// #define MY_FAST_CALL __attribute__((ms_abi)) +#define MY_FAST_CALL +#else +#define MY_FAST_CALL #endif +#endif // _MSC_VER + /* The following interfaces use first parameter as pointer to structure */ @@ -335,12 +485,11 @@ struct ISzAlloc GCC 4.8.1 : classes with non-public variable members" */ -#define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m))) - +#define MY_container_of(ptr, type, m) ((type *)(void *)((char *)(void *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m))) #endif -#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr)) +#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(void *)(ptr)) /* #define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) @@ -353,6 +502,7 @@ struct ISzAlloc */ +#define MY_memset_0_ARRAY(a) memset((a), 0, sizeof(a)) #ifdef _WIN32 diff --git a/libraries/lzma/C/7zVersion.h b/libraries/lzma/C/7zVersion.h index c176823a4..e9363d37b 100644 --- a/libraries/lzma/C/7zVersion.h +++ b/libraries/lzma/C/7zVersion.h @@ -1,7 +1,7 @@ -#define MY_VER_MAJOR 19 -#define MY_VER_MINOR 00 +#define MY_VER_MAJOR 21 +#define MY_VER_MINOR 07 #define MY_VER_BUILD 0 -#define MY_VERSION_NUMBERS "19.00" +#define MY_VERSION_NUMBERS "21.07" #define MY_VERSION MY_VERSION_NUMBERS #ifdef MY_CPU_NAME @@ -10,12 +10,12 @@ #define MY_VERSION_CPU MY_VERSION #endif -#define MY_DATE "2019-02-21" +#define MY_DATE "2021-12-26" #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-2018 Igor Pavlov" +#define MY_COPYRIGHT_CR "Copyright (c) 1999-2021 Igor Pavlov" #ifdef USE_COPYRIGHT_CR #define MY_COPYRIGHT MY_COPYRIGHT_CR diff --git a/libraries/lzma/C/Bcj2.c b/libraries/lzma/C/Bcj2.c index 9a0046a65..c7b956708 100644 --- a/libraries/lzma/C/Bcj2.c +++ b/libraries/lzma/C/Bcj2.c @@ -1,5 +1,5 @@ /* Bcj2.c -- BCJ2 Decoder (Converter for x86 code) -2018-04-28 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -123,7 +123,7 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p) const Byte *src = p->bufs[BCJ2_STREAM_MAIN]; const Byte *srcLim; Byte *dest; - SizeT num = p->lims[BCJ2_STREAM_MAIN] - src; + SizeT num = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - src); if (num == 0) { @@ -134,7 +134,7 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p) dest = p->dest; if (num > (SizeT)(p->destLim - dest)) { - num = p->destLim - dest; + num = (SizeT)(p->destLim - dest); if (num == 0) { p->state = BCJ2_DEC_STATE_ORIG; @@ -168,7 +168,7 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p) break; } - num = src - p->bufs[BCJ2_STREAM_MAIN]; + num = (SizeT)(src - p->bufs[BCJ2_STREAM_MAIN]); if (src == srcLim) { @@ -228,7 +228,7 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p) p->ip += 4; val -= p->ip; dest = p->dest; - rem = p->destLim - dest; + rem = (SizeT)(p->destLim - dest); if (rem < 4) { diff --git a/libraries/lzma/C/Bra.c b/libraries/lzma/C/Bra.c index aed17e330..3b854d9ca 100644 --- a/libraries/lzma/C/Bra.c +++ b/libraries/lzma/C/Bra.c @@ -1,5 +1,5 @@ /* Bra.c -- Converters for RISC code -2017-04-04 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -22,7 +22,7 @@ SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) for (;;) { if (p >= lim) - return p - data; + return (SizeT)(p - data); p += 4; if (p[-1] == 0xEB) break; @@ -43,7 +43,7 @@ SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) for (;;) { if (p >= lim) - return p - data; + return (SizeT)(p - data); p += 4; if (p[-1] == 0xEB) break; @@ -78,7 +78,7 @@ SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { UInt32 b3; if (p > lim) - return p - data; + return (SizeT)(p - data); b1 = p[1]; b3 = p[3]; p += 2; @@ -113,7 +113,7 @@ SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { UInt32 b3; if (p > lim) - return p - data; + return (SizeT)(p - data); b1 = p[1]; b3 = p[3]; p += 2; @@ -162,7 +162,7 @@ SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) for (;;) { if (p >= lim) - return p - data; + return (SizeT)(p - data); p += 4; /* if ((v & 0xFC000003) == 0x48000001) */ if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1) @@ -196,7 +196,7 @@ SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) for (;;) { if (p >= lim) - return p - data; + return (SizeT)(p - data); /* v = GetBe32(p); p += 4; diff --git a/libraries/lzma/C/Bra86.c b/libraries/lzma/C/Bra86.c index 93ed4d762..10a0fbd16 100644 --- a/libraries/lzma/C/Bra86.c +++ b/libraries/lzma/C/Bra86.c @@ -1,5 +1,5 @@ /* Bra86.c -- Converter for x86 code (BCJ) -2017-04-03 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -25,7 +25,7 @@ SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding break; { - SizeT d = (SizeT)(p - data - pos); + SizeT d = (SizeT)(p - data) - pos; pos = (SizeT)(p - data); if (p >= limit) { diff --git a/libraries/lzma/C/Compiler.h b/libraries/lzma/C/Compiler.h index 0cc409d8a..a9816fa5a 100644 --- a/libraries/lzma/C/Compiler.h +++ b/libraries/lzma/C/Compiler.h @@ -1,9 +1,13 @@ /* Compiler.h -2017-04-03 : Igor Pavlov : Public domain */ +2021-01-05 : Igor Pavlov : Public domain */ #ifndef __7Z_COMPILER_H #define __7Z_COMPILER_H + #ifdef __clang__ + #pragma clang diagnostic ignored "-Wunused-private-field" + #endif + #ifdef _MSC_VER #ifdef UNDER_CE @@ -25,6 +29,12 @@ #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information #endif + #ifdef __clang__ + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma clang diagnostic ignored "-Wmicrosoft-exception-spec" + // #pragma clang diagnostic ignored "-Wreserved-id-macro" + #endif + #endif #define UNUSED_VAR(x) (void)x; diff --git a/libraries/lzma/C/CpuArch.c b/libraries/lzma/C/CpuArch.c index 02e482e08..fa9afe397 100644 --- a/libraries/lzma/C/CpuArch.c +++ b/libraries/lzma/C/CpuArch.c @@ -1,5 +1,5 @@ /* CpuArch.c -- CPU specific code -2018-02-18: Igor Pavlov : Public domain */ +2021-07-13 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -55,6 +55,47 @@ static UInt32 CheckFlag(UInt32 flag) #define CHECK_CPUID_IS_SUPPORTED #endif +#ifndef USE_ASM + #ifdef _MSC_VER + #if _MSC_VER >= 1600 + #define MY__cpuidex __cpuidex + #else + +/* + __cpuid (function == 4) requires subfunction number in ECX. + MSDN: The __cpuid intrinsic clears the ECX register before calling the cpuid instruction. + __cpuid() in new MSVC clears ECX. + __cpuid() in old MSVC (14.00) doesn't clear ECX + We still can use __cpuid for low (function) values that don't require ECX, + but __cpuid() in old MSVC will be incorrect for some function values: (function == 4). + So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction, + where ECX value is first parameter for FAST_CALL / NO_INLINE function, + So the caller of MY__cpuidex_HACK() sets ECX as subFunction, and + old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value. + + DON'T remove MY_NO_INLINE and MY_FAST_CALL for MY__cpuidex_HACK() !!! +*/ + +static +MY_NO_INLINE +void MY_FAST_CALL MY__cpuidex_HACK(UInt32 subFunction, int *CPUInfo, UInt32 function) +{ + UNUSED_VAR(subFunction); + __cpuid(CPUInfo, function); +} + + #define MY__cpuidex(info, func, func2) MY__cpuidex_HACK(func2, info, func) + #pragma message("======== MY__cpuidex_HACK WAS USED ========") + #endif + #else + #define MY__cpuidex(info, func, func2) __cpuid(info, func) + #pragma message("======== (INCORRECT ?) cpuid WAS USED ========") + #endif +#endif + + + + void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) { #ifdef USE_ASM @@ -99,18 +140,20 @@ void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) #endif "=c" (*c) , "=d" (*d) - : "0" (function)) ; + : "0" (function), "c"(0) ) ; #endif #else int CPUInfo[4]; - __cpuid(CPUInfo, function); - *a = CPUInfo[0]; - *b = CPUInfo[1]; - *c = CPUInfo[2]; - *d = CPUInfo[3]; + + MY__cpuidex(CPUInfo, (int)function, 0); + + *a = (UInt32)CPUInfo[0]; + *b = (UInt32)CPUInfo[1]; + *c = (UInt32)CPUInfo[2]; + *d = (UInt32)CPUInfo[3]; #endif } @@ -174,7 +217,7 @@ BoolInt CPU_Is_InOrder() } #if !defined(MY_CPU_AMD64) && defined(_WIN32) -#include +#include static BoolInt CPU_Sys_Is_SSE_Supported() { OSVERSIONINFO vi; @@ -188,13 +231,101 @@ static BoolInt CPU_Sys_Is_SSE_Supported() #define CHECK_SYS_SSE_SUPPORT #endif -BoolInt CPU_Is_Aes_Supported() + +static UInt32 X86_CPUID_ECX_Get_Flags() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + if (!x86cpuid_CheckAndRead(&p)) + return 0; + return p.c; +} + +BoolInt CPU_IsSupported_AES() +{ + return (X86_CPUID_ECX_Get_Flags() >> 25) & 1; +} + +BoolInt CPU_IsSupported_SSSE3() +{ + return (X86_CPUID_ECX_Get_Flags() >> 9) & 1; +} + +BoolInt CPU_IsSupported_SSE41() +{ + return (X86_CPUID_ECX_Get_Flags() >> 19) & 1; +} + +BoolInt CPU_IsSupported_SHA() { Cx86cpuid p; CHECK_SYS_SSE_SUPPORT if (!x86cpuid_CheckAndRead(&p)) return False; - return (p.c >> 25) & 1; + + if (p.maxFunc < 7) + return False; + { + UInt32 d[4] = { 0 }; + MyCPUID(7, &d[0], &d[1], &d[2], &d[3]); + return (d[1] >> 29) & 1; + } +} + +// #include + +#ifdef _WIN32 +#include +#endif + +BoolInt CPU_IsSupported_AVX2() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + + #ifdef _WIN32 + #define MY__PF_XSAVE_ENABLED 17 + if (!IsProcessorFeaturePresent(MY__PF_XSAVE_ENABLED)) + return False; + #endif + + if (!x86cpuid_CheckAndRead(&p)) + return False; + if (p.maxFunc < 7) + return False; + { + UInt32 d[4] = { 0 }; + MyCPUID(7, &d[0], &d[1], &d[2], &d[3]); + // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); + return 1 + & (d[1] >> 5); // avx2 + } +} + +BoolInt CPU_IsSupported_VAES_AVX2() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + + #ifdef _WIN32 + #define MY__PF_XSAVE_ENABLED 17 + if (!IsProcessorFeaturePresent(MY__PF_XSAVE_ENABLED)) + return False; + #endif + + if (!x86cpuid_CheckAndRead(&p)) + return False; + if (p.maxFunc < 7) + return False; + { + UInt32 d[4] = { 0 }; + MyCPUID(7, &d[0], &d[1], &d[2], &d[3]); + // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); + return 1 + & (d[1] >> 5) // avx2 + // & (d[1] >> 31) // avx512vl + & (d[2] >> 9); // vaes // VEX-256/EVEX + } } BoolInt CPU_IsSupported_PageGB() @@ -215,4 +346,133 @@ BoolInt CPU_IsSupported_PageGB() } } + +#elif defined(MY_CPU_ARM_OR_ARM64) + +#ifdef _WIN32 + +#include + +BoolInt CPU_IsSupported_CRC32() { return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } +BoolInt CPU_IsSupported_CRYPTO() { return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } +BoolInt CPU_IsSupported_NEON() { return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } + +#else + +#if defined(__APPLE__) + +/* +#include +#include +static void Print_sysctlbyname(const char *name) +{ + size_t bufSize = 256; + char buf[256]; + int res = sysctlbyname(name, &buf, &bufSize, NULL, 0); + { + int i; + printf("\nres = %d : %s : '%s' : bufSize = %d, numeric", res, name, buf, (unsigned)bufSize); + for (i = 0; i < 20; i++) + printf(" %2x", (unsigned)(Byte)buf[i]); + + } +} +*/ + +static BoolInt My_sysctlbyname_Get_BoolInt(const char *name) +{ + UInt32 val = 0; + if (My_sysctlbyname_Get_UInt32(name, &val) == 0 && val == 1) + return 1; + return 0; +} + + /* + Print_sysctlbyname("hw.pagesize"); + Print_sysctlbyname("machdep.cpu.brand_string"); + */ + +BoolInt CPU_IsSupported_CRC32(void) +{ + return My_sysctlbyname_Get_BoolInt("hw.optional.armv8_crc32"); +} + +BoolInt CPU_IsSupported_NEON(void) +{ + return My_sysctlbyname_Get_BoolInt("hw.optional.neon"); +} + +#ifdef MY_CPU_ARM64 +#define APPLE_CRYPTO_SUPPORT_VAL 1 +#else +#define APPLE_CRYPTO_SUPPORT_VAL 0 +#endif + +BoolInt CPU_IsSupported_SHA1(void) { return APPLE_CRYPTO_SUPPORT_VAL; } +BoolInt CPU_IsSupported_SHA2(void) { return APPLE_CRYPTO_SUPPORT_VAL; } +BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; } + + +#else // __APPLE__ + +#include + +#define USE_HWCAP + +#ifdef USE_HWCAP + +#include + + #define MY_HWCAP_CHECK_FUNC_2(name1, name2) \ + BoolInt CPU_IsSupported_ ## name1() { return (getauxval(AT_HWCAP) & (HWCAP_ ## name2)) ? 1 : 0; } + +#ifdef MY_CPU_ARM64 + #define MY_HWCAP_CHECK_FUNC(name) \ + MY_HWCAP_CHECK_FUNC_2(name, name) + MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD) +// MY_HWCAP_CHECK_FUNC (ASIMD) +#elif defined(MY_CPU_ARM) + #define MY_HWCAP_CHECK_FUNC(name) \ + BoolInt CPU_IsSupported_ ## name() { return (getauxval(AT_HWCAP2) & (HWCAP2_ ## name)) ? 1 : 0; } + MY_HWCAP_CHECK_FUNC_2(NEON, NEON) +#endif + +#else // USE_HWCAP + + #define MY_HWCAP_CHECK_FUNC(name) \ + BoolInt CPU_IsSupported_ ## name() { return 0; } + MY_HWCAP_CHECK_FUNC(NEON) + +#endif // USE_HWCAP + +MY_HWCAP_CHECK_FUNC (CRC32) +MY_HWCAP_CHECK_FUNC (SHA1) +MY_HWCAP_CHECK_FUNC (SHA2) +MY_HWCAP_CHECK_FUNC (AES) + +#endif // __APPLE__ +#endif // _WIN32 + +#endif // MY_CPU_ARM_OR_ARM64 + + + +#ifdef __APPLE__ + +#include + +int My_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize) +{ + return sysctlbyname(name, buf, bufSize, NULL, 0); +} + +int My_sysctlbyname_Get_UInt32(const char *name, UInt32 *val) +{ + size_t bufSize = sizeof(*val); + int res = My_sysctlbyname_Get(name, val, &bufSize); + if (res == 0 && bufSize != sizeof(*val)) + return EFAULT; + return res; +} + #endif diff --git a/libraries/lzma/C/CpuArch.h b/libraries/lzma/C/CpuArch.h index bd4293880..529d3a502 100644 --- a/libraries/lzma/C/CpuArch.h +++ b/libraries/lzma/C/CpuArch.h @@ -1,5 +1,5 @@ /* CpuArch.h -- CPU specific code -2018-02-18 : Igor Pavlov : Public domain */ +2021-07-13 : Igor Pavlov : Public domain */ #ifndef __CPU_ARCH_H #define __CPU_ARCH_H @@ -14,6 +14,10 @@ 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. + +MY_CPU_64BIT means that processor can work with 64-bit registers. + MY_CPU_64BIT can be used to select fast code branch + MY_CPU_64BIT doesn't mean that (sizeof(void *) == 8) */ #if defined(_M_X64) \ @@ -24,8 +28,10 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #define MY_CPU_AMD64 #ifdef __ILP32__ #define MY_CPU_NAME "x32" + #define MY_CPU_SIZEOF_POINTER 4 #else #define MY_CPU_NAME "x64" + #define MY_CPU_SIZEOF_POINTER 8 #endif #define MY_CPU_64BIT #endif @@ -35,7 +41,8 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem || defined(__i386__) #define MY_CPU_X86 #define MY_CPU_NAME "x86" - #define MY_CPU_32BIT + /* #define MY_CPU_32BIT */ + #define MY_CPU_SIZEOF_POINTER 4 #endif @@ -59,8 +66,14 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem || defined(__THUMBEL__) \ || defined(__THUMBEB__) #define MY_CPU_ARM - #define MY_CPU_NAME "arm" - #define MY_CPU_32BIT + + #if defined(__thumb__) || defined(__THUMBEL__) || defined(_M_ARMT) + #define MY_CPU_NAME "armt" + #else + #define MY_CPU_NAME "arm" + #endif + /* #define MY_CPU_32BIT */ + #define MY_CPU_SIZEOF_POINTER 4 #endif @@ -84,17 +97,29 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #if defined(__ppc64__) \ - || defined(__powerpc64__) + || defined(__powerpc64__) \ + || defined(__ppc__) \ + || defined(__powerpc__) \ + || defined(__PPC__) \ + || defined(_POWER) + +#if defined(__ppc64__) \ + || defined(__powerpc64__) \ + || defined(_LP64) \ + || defined(__64BIT__) #ifdef __ILP32__ #define MY_CPU_NAME "ppc64-32" + #define MY_CPU_SIZEOF_POINTER 4 #else #define MY_CPU_NAME "ppc64" + #define MY_CPU_SIZEOF_POINTER 8 #endif #define MY_CPU_64BIT -#elif defined(__ppc__) \ - || defined(__powerpc__) +#else #define MY_CPU_NAME "ppc" - #define MY_CPU_32BIT + #define MY_CPU_SIZEOF_POINTER 4 + /* #define MY_CPU_32BIT */ +#endif #endif @@ -111,6 +136,10 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #define MY_CPU_X86_OR_AMD64 #endif +#if defined(MY_CPU_ARM) || defined(MY_CPU_ARM64) +#define MY_CPU_ARM_OR_ARM64 +#endif + #ifdef _WIN32 @@ -170,6 +199,40 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #error Stop_Compiling_Bad_32_64_BIT #endif +#ifdef __SIZEOF_POINTER__ + #ifdef MY_CPU_SIZEOF_POINTER + #if MY_CPU_SIZEOF_POINTER != __SIZEOF_POINTER__ + #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE + #endif + #else + #define MY_CPU_SIZEOF_POINTER __SIZEOF_POINTER__ + #endif +#endif + +#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4) +#if defined (_LP64) + #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE +#endif +#endif + +#ifdef _MSC_VER + #if _MSC_VER >= 1300 + #define MY_CPU_pragma_pack_push_1 __pragma(pack(push, 1)) + #define MY_CPU_pragma_pop __pragma(pack(pop)) + #else + #define MY_CPU_pragma_pack_push_1 + #define MY_CPU_pragma_pop + #endif +#else + #ifdef __xlC__ + #define MY_CPU_pragma_pack_push_1 _Pragma("pack(1)") + #define MY_CPU_pragma_pop _Pragma("pack()") + #else + #define MY_CPU_pragma_pack_push_1 _Pragma("pack(push, 1)") + #define MY_CPU_pragma_pop _Pragma("pack(pop)") + #endif +#endif + #ifndef MY_CPU_NAME #ifdef MY_CPU_LE @@ -189,8 +252,12 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #ifdef MY_CPU_LE #if defined(MY_CPU_X86_OR_AMD64) \ - || defined(MY_CPU_ARM64) \ - || defined(__ARM_FEATURE_UNALIGNED) + || defined(MY_CPU_ARM64) + #define MY_CPU_LE_UNALIGN + #define MY_CPU_LE_UNALIGN_64 + #elif defined(__ARM_FEATURE_UNALIGNED) + /* gcc9 for 32-bit arm can use LDRD instruction that requires 32-bit alignment. + So we can't use unaligned 64-bit operations. */ #define MY_CPU_LE_UNALIGN #endif #endif @@ -200,11 +267,15 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #define GetUi16(p) (*(const UInt16 *)(const void *)(p)) #define GetUi32(p) (*(const UInt32 *)(const void *)(p)) +#ifdef MY_CPU_LE_UNALIGN_64 #define GetUi64(p) (*(const UInt64 *)(const void *)(p)) +#endif -#define SetUi16(p, v) { *(UInt16 *)(p) = (v); } -#define SetUi32(p, v) { *(UInt32 *)(p) = (v); } -#define SetUi64(p, v) { *(UInt64 *)(p) = (v); } +#define SetUi16(p, v) { *(UInt16 *)(void *)(p) = (v); } +#define SetUi32(p, v) { *(UInt32 *)(void *)(p) = (v); } +#ifdef MY_CPU_LE_UNALIGN_64 +#define SetUi64(p, v) { *(UInt64 *)(void *)(p) = (v); } +#endif #else @@ -218,8 +289,6 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem ((UInt32)((const Byte *)(p))[2] << 16) | \ ((UInt32)((const Byte *)(p))[3] << 24)) -#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) - #define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ _ppp_[0] = (Byte)_vvv_; \ _ppp_[1] = (Byte)(_vvv_ >> 8); } @@ -230,19 +299,29 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem _ppp_[2] = (Byte)(_vvv_ >> 16); \ _ppp_[3] = (Byte)(_vvv_ >> 24); } +#endif + + +#ifndef MY_CPU_LE_UNALIGN_64 + +#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) + #define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \ SetUi32(_ppp2_ , (UInt32)_vvv2_); \ SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); } #endif + + + #ifdef __has_builtin #define MY__has_builtin(x) __has_builtin(x) #else #define MY__has_builtin(x) 0 #endif -#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300) +#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ defined(_MSC_VER) && (_MSC_VER >= 1300) /* Note: we use bswap instruction, that is unsupported in 386 cpu */ @@ -253,8 +332,8 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #pragma intrinsic(_byteswap_uint64) /* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */ -#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) -#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) +#define GetBe32(p) _byteswap_ulong (*(const UInt32 *)(const void *)(p)) +#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const void *)(p)) #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v) @@ -262,9 +341,9 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ || (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) ) -/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const Byte *)(p)) */ -#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p)) -#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p)) +/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const void *)(p)) */ +#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const void *)(p)) +#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const void *)(p)) #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v) @@ -325,10 +404,37 @@ int x86cpuid_GetFirm(const Cx86cpuid *p); #define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF)) #define x86cpuid_GetStepping(ver) (ver & 0xF) -BoolInt CPU_Is_InOrder(); -BoolInt CPU_Is_Aes_Supported(); -BoolInt CPU_IsSupported_PageGB(); +BoolInt CPU_Is_InOrder(void); +BoolInt CPU_IsSupported_AES(void); +BoolInt CPU_IsSupported_AVX2(void); +BoolInt CPU_IsSupported_VAES_AVX2(void); +BoolInt CPU_IsSupported_SSSE3(void); +BoolInt CPU_IsSupported_SSE41(void); +BoolInt CPU_IsSupported_SHA(void); +BoolInt CPU_IsSupported_PageGB(void); + +#elif defined(MY_CPU_ARM_OR_ARM64) + +BoolInt CPU_IsSupported_CRC32(void); +BoolInt CPU_IsSupported_NEON(void); + +#if defined(_WIN32) +BoolInt CPU_IsSupported_CRYPTO(void); +#define CPU_IsSupported_SHA1 CPU_IsSupported_CRYPTO +#define CPU_IsSupported_SHA2 CPU_IsSupported_CRYPTO +#define CPU_IsSupported_AES CPU_IsSupported_CRYPTO +#else +BoolInt CPU_IsSupported_SHA1(void); +BoolInt CPU_IsSupported_SHA2(void); +BoolInt CPU_IsSupported_AES(void); +#endif + +#endif + +#if defined(__APPLE__) +int My_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize); +int My_sysctlbyname_Get_UInt32(const char *name, UInt32 *val); #endif EXTERN_C_END diff --git a/libraries/lzma/C/Delta.c b/libraries/lzma/C/Delta.c index e3edd21ed..c4a4499fe 100644 --- a/libraries/lzma/C/Delta.c +++ b/libraries/lzma/C/Delta.c @@ -1,5 +1,5 @@ /* Delta.c -- Delta converter -2009-05-26 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -12,53 +12,158 @@ void Delta_Init(Byte *state) 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); + Byte temp[DELTA_STATE_SIZE]; + + if (size == 0) + return; + { - SizeT i; - for (i = 0; i < size;) + unsigned i = 0; + do + temp[i] = state[i]; + while (++i != delta); + } + + if (size <= delta) + { + unsigned i = 0, k; + do { - for (j = 0; j < delta && i < size; i++, j++) + Byte b = *data; + *data++ = (Byte)(b - temp[i]); + temp[i] = b; + } + while (++i != size); + + k = 0; + + do + { + if (i == delta) + i = 0; + state[k] = temp[i++]; + } + while (++k != delta); + + return; + } + + { + Byte *p = data + size - delta; + { + unsigned i = 0; + do + state[i] = *p++; + while (++i != delta); + } + { + const Byte *lim = data + delta; + ptrdiff_t dif = -(ptrdiff_t)delta; + + if (((ptrdiff_t)size + dif) & 1) { - Byte b = data[i]; - data[i] = (Byte)(b - buf[j]); - buf[j] = b; + --p; *p = (Byte)(*p - p[dif]); } + + while (p != lim) + { + --p; *p = (Byte)(*p - p[dif]); + --p; *p = (Byte)(*p - p[dif]); + } + + dif = -dif; + + do + { + --p; *p = (Byte)(*p - temp[--dif]); + } + while (dif != 0); } } - 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); + unsigned i; + const Byte *lim; + + if (size == 0) + return; + + i = 0; + lim = data + size; + + if (size <= delta) { - SizeT i; - for (i = 0; i < size;) + do + *data = (Byte)(*data + state[i++]); + while (++data != lim); + + for (; delta != i; state++, delta--) + *state = state[i]; + data -= i; + } + else + { + /* + #define B(n) b ## n + #define I(n) Byte B(n) = state[n]; + #define U(n) { B(n) = (Byte)((B(n)) + *data++); data[-1] = (B(n)); } + #define F(n) if (data != lim) { U(n) } + + if (delta == 1) { - for (j = 0; j < delta && i < size; i++, j++) + I(0) + if ((lim - data) & 1) { U(0) } + while (data != lim) { U(0) U(0) } + data -= 1; + } + else if (delta == 2) + { + I(0) I(1) + lim -= 1; while (data < lim) { U(0) U(1) } + lim += 1; F(0) + data -= 2; + } + else if (delta == 3) + { + I(0) I(1) I(2) + lim -= 2; while (data < lim) { U(0) U(1) U(2) } + lim += 2; F(0) F(1) + data -= 3; + } + else if (delta == 4) + { + I(0) I(1) I(2) I(3) + lim -= 3; while (data < lim) { U(0) U(1) U(2) U(3) } + lim += 3; F(0) F(1) F(2) + data -= 4; + } + else + */ + { + do { - buf[j] = data[i] = (Byte)(buf[j] + data[i]); + *data = (Byte)(*data + state[i++]); + data++; + } + while (i != delta); + + { + ptrdiff_t dif = -(ptrdiff_t)delta; + do + *data = (Byte)(*data + data[dif]); + while (++data != lim); + data += dif; } } } - if (j == delta) - j = 0; - MyMemCpy(state, buf + j, delta - j); - MyMemCpy(state + delta - j, buf, j); + + do + *state++ = *data; + while (++data != lim); } diff --git a/libraries/lzma/C/LzFind.c b/libraries/lzma/C/LzFind.c index df55e86c1..1b73c2848 100644 --- a/libraries/lzma/C/LzFind.c +++ b/libraries/lzma/C/LzFind.c @@ -1,20 +1,69 @@ /* LzFind.c -- Match finder for LZ algorithms -2018-07-08 : Igor Pavlov : Public domain */ +2021-11-29 : Igor Pavlov : Public domain */ #include "Precomp.h" #include +// #include +#include "CpuArch.h" #include "LzFind.h" #include "LzHash.h" -#define kEmptyHashValue 0 -#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) -#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ -#define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1)) -#define kMaxHistorySize ((UInt32)7 << 29) +#define kBlockMoveAlign (1 << 7) // alignment for memmove() +#define kBlockSizeAlign (1 << 16) // alignment for block allocation +#define kBlockSizeReserveMin (1 << 24) // it's 1/256 from 4 GB dictinary + +#define kEmptyHashValue 0 + +#define kMaxValForNormalize ((UInt32)0) +// #define kMaxValForNormalize ((UInt32)(1 << 20) + 0xFFF) // for debug + +// #define kNormalizeAlign (1 << 7) // alignment for speculated accesses + +#define GET_AVAIL_BYTES(p) \ + Inline_MatchFinder_GetNumAvailableBytes(p) + + +// #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) +#define kFix5HashSize kFix4HashSize + +/* + HASH2_CALC: + if (hv) match, then cur[0] and cur[1] also match +*/ +#define HASH2_CALC hv = GetUi16(cur); + +// (crc[0 ... 255] & 0xFF) provides one-to-one correspondence to [0 ... 255] + +/* + HASH3_CALC: + if (cur[0]) and (h2) match, then cur[1] also match + if (cur[0]) and (hv) match, then cur[1] and cur[2] also match +*/ +#define HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } + +#define HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + hv = (temp ^ (p->crc[cur[3]] << kLzHash_CrcShift_1)) & p->hashMask; } + +#define HASH5_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + temp ^= (p->crc[cur[3]] << kLzHash_CrcShift_1); \ + /* h4 = temp & p->hash4Mask; */ /* (kHash4Size - 1); */ \ + hv = (temp ^ (p->crc[cur[4]] << kLzHash_CrcShift_2)) & p->hashMask; } + +#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; -#define kStartMaxLen 3 static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc) { @@ -25,46 +74,57 @@ static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc) } } -/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ -static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAllocPtr alloc) +static int LzInWindow_Create2(CMatchFinder *p, UInt32 blockSize, ISzAllocPtr alloc) { - UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; - if (p->directInput) - { - p->blockSize = blockSize; - return 1; - } + if (blockSize == 0) + return 0; if (!p->bufferBase || p->blockSize != blockSize) { + // size_t blockSizeT; LzInWindow_Free(p, alloc); p->blockSize = blockSize; - p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, (size_t)blockSize); + // blockSizeT = blockSize; + + // printf("\nblockSize = 0x%x\n", blockSize); + /* + #if defined _WIN64 + // we can allocate 4GiB, but still use UInt32 for (p->blockSize) + // we use UInt32 type for (p->blockSize), because + // we don't want to wrap over 4 GiB, + // when we use (p->streamPos - p->pos) that is UInt32. + if (blockSize >= (UInt32)0 - (UInt32)kBlockSizeAlign) + { + blockSizeT = ((size_t)1 << 32); + printf("\nchanged to blockSizeT = 4GiB\n"); + } + #endif + */ + + p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, blockSize); + // printf("\nbufferBase = %p\n", p->bufferBase); + // return 0; // for debug } return (p->bufferBase != NULL); } -Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } +static const Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } -UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } +static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return GET_AVAIL_BYTES(p); } -void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) -{ - p->posLimit -= subValue; - p->pos -= subValue; - p->streamPos -= subValue; -} +MY_NO_INLINE 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. */ + /* We use (p->streamPos - p->pos) value. + (p->streamPos < p->pos) is allowed. */ if (p->directInput) { - UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos); + UInt32 curSize = 0xFFFFFFFF - GET_AVAIL_BYTES(p); if (curSize > p->directInputRem) curSize = (UInt32)p->directInputRem; p->directInputRem -= curSize; @@ -76,10 +136,22 @@ static void MatchFinder_ReadBlock(CMatchFinder *p) for (;;) { - Byte *dest = p->buffer + (p->streamPos - p->pos); - size_t size = (p->bufferBase + p->blockSize - dest); + Byte *dest = p->buffer + GET_AVAIL_BYTES(p); + size_t size = (size_t)(p->bufferBase + p->blockSize - dest); if (size == 0) + { + /* we call ReadBlock() after NeedMove() and MoveBlock(). + NeedMove() and MoveBlock() povide more than (keepSizeAfter) + to the end of (blockSize). + So we don't execute this branch in normal code flow. + We can go here, if we will call ReadBlock() before NeedMove(), MoveBlock(). + */ + // p->result = SZ_ERROR_FAIL; // we can show error here return; + } + + // #define kRead 3 + // if (size > kRead) size = kRead; // for debug p->result = ISeqInStream_Read(p->stream, dest, &size); if (p->result != SZ_OK) @@ -90,41 +162,52 @@ static void MatchFinder_ReadBlock(CMatchFinder *p) return; } p->streamPos += (UInt32)size; - if (p->streamPos - p->pos > p->keepSizeAfter) + if (GET_AVAIL_BYTES(p) > p->keepSizeAfter) return; + /* here and in another (p->keepSizeAfter) checks we keep on 1 byte more than was requested by Create() function + (GET_AVAIL_BYTES(p) >= p->keepSizeAfter) - minimal required size */ } + + // on exit: (p->result != SZ_OK || p->streamEndWasReached || GET_AVAIL_BYTES(p) > p->keepSizeAfter) } + + +MY_NO_INLINE void MatchFinder_MoveBlock(CMatchFinder *p) { + const size_t offset = (size_t)(p->buffer - p->bufferBase) - p->keepSizeBefore; + const size_t keepBefore = (offset & (kBlockMoveAlign - 1)) + p->keepSizeBefore; + p->buffer = p->bufferBase + keepBefore; memmove(p->bufferBase, - p->buffer - p->keepSizeBefore, - (size_t)(p->streamPos - p->pos) + p->keepSizeBefore); - p->buffer = p->bufferBase + p->keepSizeBefore; + p->bufferBase + (offset & ~((size_t)kBlockMoveAlign - 1)), + keepBefore + (size_t)GET_AVAIL_BYTES(p)); } +/* We call MoveBlock() before ReadBlock(). + So MoveBlock() can be wasteful operation, if the whole input data + can fit in current block even without calling MoveBlock(). + in important case where (dataSize <= historySize) + condition (p->blockSize > dataSize + p->keepSizeAfter) is met + So there is no MoveBlock() in that case case. +*/ + int MatchFinder_NeedMove(CMatchFinder *p) { if (p->directInput) return 0; - /* if (p->streamEndWasReached) return 0; */ + if (p->streamEndWasReached || p->result != SZ_OK) + return 0; return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) { - if (p->streamEndWasReached) - return; - if (p->keepSizeAfter >= p->streamPos - p->pos) + if (p->keepSizeAfter >= GET_AVAIL_BYTES(p)) MatchFinder_ReadBlock(p); } -static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) -{ - if (MatchFinder_NeedMove(p)) - MatchFinder_MoveBlock(p); - MatchFinder_ReadBlock(p); -} + static void MatchFinder_SetDefaultSettings(CMatchFinder *p) { @@ -175,39 +258,74 @@ static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc) return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes); } +#if (kBlockSizeReserveMin < kBlockSizeAlign * 2) + #error Stop_Compiling_Bad_Reserve +#endif + + + +static UInt32 GetBlockSize(CMatchFinder *p, UInt32 historySize) +{ + UInt32 blockSize = (p->keepSizeBefore + p->keepSizeAfter); + /* + if (historySize > kMaxHistorySize) + return 0; + */ + // printf("\nhistorySize == 0x%x\n", historySize); + + if (p->keepSizeBefore < historySize || blockSize < p->keepSizeBefore) // if 32-bit overflow + return 0; + + { + const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)kBlockSizeAlign; + const UInt32 rem = kBlockSizeMax - blockSize; + const UInt32 reserve = (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2)) + + (1 << 12) + kBlockMoveAlign + kBlockSizeAlign; // do not overflow 32-bit here + if (blockSize >= kBlockSizeMax + || rem < kBlockSizeReserveMin) // we reject settings that will be slow + return 0; + if (reserve >= rem) + blockSize = kBlockSizeMax; + else + { + blockSize += reserve; + blockSize &= ~(UInt32)(kBlockSizeAlign - 1); + } + } + // printf("\n LzFind_blockSize = %x\n", blockSize); + // printf("\n LzFind_blockSize = %d\n", blockSize >> 20); + return blockSize; +} + + int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc) { - UInt32 sizeReserv; - - if (historySize > kMaxHistorySize) - { - MatchFinder_Free(p, alloc); - return 0; - } - - sizeReserv = historySize >> 1; - if (historySize >= ((UInt32)3 << 30)) sizeReserv = historySize >> 3; - else if (historySize >= ((UInt32)2 << 30)) sizeReserv = historySize >> 2; - - sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); - + /* we need one additional byte in (p->keepSizeBefore), + since we use MoveBlock() after (p->pos++) and before dictionary using */ + // keepAddBufferBefore = (UInt32)0xFFFFFFFF - (1 << 22); // for debug 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)) + + keepAddBufferAfter += matchMaxLen; + /* we need (p->keepSizeAfter >= p->numHashBytes) */ + if (keepAddBufferAfter < p->numHashBytes) + keepAddBufferAfter = p->numHashBytes; + // keepAddBufferAfter -= 2; // for debug + p->keepSizeAfter = keepAddBufferAfter; + + if (p->directInput) + p->blockSize = 0; + if (p->directInput || LzInWindow_Create2(p, GetBlockSize(p, historySize), alloc)) { - UInt32 newCyclicBufferSize = historySize + 1; + const UInt32 newCyclicBufferSize = historySize + 1; // do not change it UInt32 hs; p->matchMaxLen = matchMaxLen; { + // UInt32 hs4; p->fixedHashSize = 0; - if (p->numHashBytes == 2) - hs = (1 << 16) - 1; - else + hs = (1 << 16) - 1; + if (p->numHashBytes != 2) { hs = historySize; if (hs > p->expectedDataSize) @@ -218,9 +336,9 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); + // we propagated 16 bits in (hs). Low 16 bits must be set later hs >>= 1; - hs |= 0xFFFF; /* don't change it! It's required for Deflate */ - if (hs > (1 << 24)) + if (hs >= (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; @@ -228,12 +346,30 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, hs >>= 1; /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */ } + + // hs = ((UInt32)1 << 25) - 1; // for test + + // (hash_size >= (1 << 16)) : Required for (numHashBytes > 2) + hs |= (1 << 16) - 1; /* don't change it! */ + + // bt5: we adjust the size with recommended minimum size + if (p->numHashBytes >= 5) + hs |= (256 << kLzHash_CrcShift_2) - 1; } p->hashMask = hs; hs++; + + /* + hs4 = (1 << 20); + if (hs4 > hs) + hs4 = hs; + // hs4 = (1 << 16); // for test + p->hash4Mask = hs4 - 1; + */ + if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; - if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; + // if (p->numHashBytes > 4) p->fixedHashSize += hs4; // kHash4Size; hs += p->fixedHashSize; } @@ -242,13 +378,17 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, size_t numSons; p->historySize = historySize; p->hashSizeSum = hs; - p->cyclicBufferSize = newCyclicBufferSize; + p->cyclicBufferSize = newCyclicBufferSize; // it must be = (historySize + 1) numSons = newCyclicBufferSize; if (p->btMode) numSons <<= 1; newSize = hs + numSons; + // aligned size is not required here, but it can be better for some loops + #define NUM_REFS_ALIGN_MASK 0xF + newSize = (newSize + NUM_REFS_ALIGN_MASK) & ~(size_t)NUM_REFS_ALIGN_MASK; + if (p->hash && p->numRefs == newSize) return 1; @@ -268,33 +408,43 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, return 0; } + static void MatchFinder_SetLimits(CMatchFinder *p) { - UInt32 limit = kMaxValForNormalize - p->pos; - UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; + UInt32 k; + UInt32 n = kMaxValForNormalize - p->pos; + if (n == 0) + n = (UInt32)(Int32)-1; // we allow (pos == 0) at start even with (kMaxValForNormalize == 0) - if (limit2 < limit) - limit = limit2; - limit2 = p->streamPos - p->pos; - - if (limit2 <= p->keepSizeAfter) + k = p->cyclicBufferSize - p->cyclicBufferPos; + if (k < n) + n = k; + + k = GET_AVAIL_BYTES(p); { - if (limit2 > 0) - limit2 = 1; + const UInt32 ksa = p->keepSizeAfter; + UInt32 mm = p->matchMaxLen; + if (k > ksa) + k -= ksa; // we must limit exactly to keepSizeAfter for ReadBlock + else if (k >= mm) + { + // the limitation for (p->lenLimit) update + k -= mm; // optimization : to reduce the number of checks + k++; + // k = 1; // non-optimized version : for debug + } + else + { + mm = k; + if (k != 0) + k = 1; + } + p->lenLimit = mm; } - else - limit2 -= p->keepSizeAfter; + if (k < n) + n = k; - if (limit2 < limit) - limit = limit2; - - { - UInt32 lenLimit = p->streamPos - p->pos; - if (lenLimit > p->matchMaxLen) - lenLimit = p->matchMaxLen; - p->lenLimit = lenLimit; - } - p->posLimit = p->pos + limit; + p->posLimit = p->pos + n; } @@ -302,7 +452,7 @@ void MatchFinder_Init_LowHash(CMatchFinder *p) { size_t i; CLzRef *items = p->hash; - size_t numItems = p->fixedHashSize; + const size_t numItems = p->fixedHashSize; for (i = 0; i < numItems; i++) items[i] = kEmptyHashValue; } @@ -312,72 +462,322 @@ void MatchFinder_Init_HighHash(CMatchFinder *p) { size_t i; CLzRef *items = p->hash + p->fixedHashSize; - size_t numItems = (size_t)p->hashMask + 1; + const size_t numItems = (size_t)p->hashMask + 1; for (i = 0; i < numItems; i++) items[i] = kEmptyHashValue; } -void MatchFinder_Init_3(CMatchFinder *p, int readData) +void MatchFinder_Init_4(CMatchFinder *p) { - p->cyclicBufferPos = 0; p->buffer = p->bufferBase; - p->pos = - p->streamPos = p->cyclicBufferSize; + { + /* kEmptyHashValue = 0 (Zero) is used in hash tables as NO-VALUE marker. + the code in CMatchFinderMt expects (pos = 1) */ + p->pos = + p->streamPos = + 1; // it's smallest optimal value. do not change it + // 0; // for debug + } p->result = SZ_OK; p->streamEndWasReached = 0; - - if (readData) - MatchFinder_ReadBlock(p); - - MatchFinder_SetLimits(p); } +// (CYC_TO_POS_OFFSET == 0) is expected by some optimized code +#define CYC_TO_POS_OFFSET 0 +// #define CYC_TO_POS_OFFSET 1 // for debug + void MatchFinder_Init(CMatchFinder *p) { MatchFinder_Init_HighHash(p); MatchFinder_Init_LowHash(p); - MatchFinder_Init_3(p, True); + MatchFinder_Init_4(p); + // if (readData) + MatchFinder_ReadBlock(p); + + /* if we init (cyclicBufferPos = pos), then we can use one variable + instead of both (cyclicBufferPos) and (pos) : only before (cyclicBufferPos) wrapping */ + p->cyclicBufferPos = (p->pos - CYC_TO_POS_OFFSET); // init with relation to (pos) + // p->cyclicBufferPos = 0; // smallest value + // p->son[0] = p->son[1] = 0; // unused: we can init skipped record for speculated accesses. + MatchFinder_SetLimits(p); } - -static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) + + +#ifdef MY_CPU_X86_OR_AMD64 + #if defined(__clang__) && (__clang_major__ >= 8) \ + || defined(__GNUC__) && (__GNUC__ >= 8) \ + || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900) + #define USE_SATUR_SUB_128 + #define USE_AVX2 + #define ATTRIB_SSE41 __attribute__((__target__("sse4.1"))) + #define ATTRIB_AVX2 __attribute__((__target__("avx2"))) + #elif defined(_MSC_VER) + #if (_MSC_VER >= 1600) + #define USE_SATUR_SUB_128 + #if (_MSC_VER >= 1900) + #define USE_AVX2 + #include // avx + #endif + #endif + #endif + +// #elif defined(MY_CPU_ARM_OR_ARM64) +#elif defined(MY_CPU_ARM64) + + #if defined(__clang__) && (__clang_major__ >= 8) \ + || defined(__GNUC__) && (__GNUC__ >= 8) + #define USE_SATUR_SUB_128 + #ifdef MY_CPU_ARM64 + // #define ATTRIB_SSE41 __attribute__((__target__(""))) + #else + // #define ATTRIB_SSE41 __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) + #endif + + #elif defined(_MSC_VER) + #if (_MSC_VER >= 1910) + #define USE_SATUR_SUB_128 + #endif + #endif + + #if defined(_MSC_VER) && defined(MY_CPU_ARM64) + #include + #else + #include + #endif + +#endif + +/* +#ifndef ATTRIB_SSE41 + #define ATTRIB_SSE41 +#endif +#ifndef ATTRIB_AVX2 + #define ATTRIB_AVX2 +#endif +*/ + +#ifdef USE_SATUR_SUB_128 + +// #define _SHOW_HW_STATUS + +#ifdef _SHOW_HW_STATUS +#include +#define _PRF(x) x +_PRF(;) +#else +#define _PRF(x) +#endif + +#ifdef MY_CPU_ARM_OR_ARM64 + +#ifdef MY_CPU_ARM64 +// #define FORCE_SATUR_SUB_128 +#endif + +typedef uint32x4_t v128; +#define SASUB_128(i) \ + *(v128 *)(void *)(items + (i) * 4) = \ + vsubq_u32(vmaxq_u32(*(const v128 *)(const void *)(items + (i) * 4), sub2), sub2); + +#else + +#include // sse4.1 + +typedef __m128i v128; +#define SASUB_128(i) \ + *(v128 *)(void *)(items + (i) * 4) = \ + _mm_sub_epi32(_mm_max_epu32(*(const v128 *)(const void *)(items + (i) * 4), sub2), sub2); // SSE 4.1 + +#endif + + + +MY_NO_INLINE +static +#ifdef ATTRIB_SSE41 +ATTRIB_SSE41 +#endif +void +MY_FAST_CALL +LzFind_SaturSub_128(UInt32 subValue, CLzRef *items, const CLzRef *lim) { - return (p->pos - p->historySize - 1) & kNormalizeMask; + v128 sub2 = + #ifdef MY_CPU_ARM_OR_ARM64 + vdupq_n_u32(subValue); + #else + _mm_set_epi32((Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue); + #endif + do + { + SASUB_128(0) + SASUB_128(1) + SASUB_128(2) + SASUB_128(3) + items += 4 * 4; + } + while (items != lim); } + + +#ifdef USE_AVX2 + +#include // avx + +#define SASUB_256(i) *(__m256i *)(void *)(items + (i) * 8) = _mm256_sub_epi32(_mm256_max_epu32(*(const __m256i *)(const void *)(items + (i) * 8), sub2), sub2); // AVX2 + +MY_NO_INLINE +static +#ifdef ATTRIB_AVX2 +ATTRIB_AVX2 +#endif +void +MY_FAST_CALL +LzFind_SaturSub_256(UInt32 subValue, CLzRef *items, const CLzRef *lim) +{ + __m256i sub2 = _mm256_set_epi32( + (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue, + (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue); + do + { + SASUB_256(0) + SASUB_256(1) + items += 2 * 8; + } + while (items != lim); +} +#endif // USE_AVX2 + +#ifndef FORCE_SATUR_SUB_128 +typedef void (MY_FAST_CALL *LZFIND_SATUR_SUB_CODE_FUNC)( + UInt32 subValue, CLzRef *items, const CLzRef *lim); +static LZFIND_SATUR_SUB_CODE_FUNC g_LzFind_SaturSub; +#endif // FORCE_SATUR_SUB_128 + +#endif // USE_SATUR_SUB_128 + + +// kEmptyHashValue must be zero +// #define SASUB_32(i) v = items[i]; m = v - subValue; if (v < subValue) m = kEmptyHashValue; items[i] = m; +#define SASUB_32(i) v = items[i]; if (v < subValue) v = subValue; items[i] = v - subValue; + +#ifdef FORCE_SATUR_SUB_128 + +#define DEFAULT_SaturSub LzFind_SaturSub_128 + +#else + +#define DEFAULT_SaturSub LzFind_SaturSub_32 + +MY_NO_INLINE +static +void +MY_FAST_CALL +LzFind_SaturSub_32(UInt32 subValue, CLzRef *items, const CLzRef *lim) +{ + do + { + UInt32 v; + SASUB_32(0) + SASUB_32(1) + SASUB_32(2) + SASUB_32(3) + SASUB_32(4) + SASUB_32(5) + SASUB_32(6) + SASUB_32(7) + items += 8; + } + while (items != lim); +} + +#endif + + +MY_NO_INLINE void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems) { - size_t i; - for (i = 0; i < numItems; i++) + #define K_NORM_ALIGN_BLOCK_SIZE (1 << 6) + + CLzRef *lim; + + for (; numItems != 0 && ((unsigned)(ptrdiff_t)items & (K_NORM_ALIGN_BLOCK_SIZE - 1)) != 0; numItems--) { - UInt32 value = items[i]; - if (value <= subValue) - value = kEmptyHashValue; - else - value -= subValue; - items[i] = value; + UInt32 v; + SASUB_32(0); + items++; + } + + { + #define K_NORM_ALIGN_MASK (K_NORM_ALIGN_BLOCK_SIZE / 4 - 1) + lim = items + (numItems & ~(size_t)K_NORM_ALIGN_MASK); + numItems &= K_NORM_ALIGN_MASK; + if (items != lim) + { + #if defined(USE_SATUR_SUB_128) && !defined(FORCE_SATUR_SUB_128) + if (g_LzFind_SaturSub) + g_LzFind_SaturSub(subValue, items, lim); + else + #endif + DEFAULT_SaturSub(subValue, items, lim); + } + items = lim; + } + + + for (; numItems != 0; numItems--) + { + UInt32 v; + SASUB_32(0); + items++; } } -static void MatchFinder_Normalize(CMatchFinder *p) -{ - UInt32 subValue = MatchFinder_GetSubValue(p); - MatchFinder_Normalize3(subValue, p->hash, p->numRefs); - MatchFinder_ReduceOffsets(p, subValue); -} +// call MatchFinder_CheckLimits() only after (p->pos++) update + MY_NO_INLINE static void MatchFinder_CheckLimits(CMatchFinder *p) { + if (// !p->streamEndWasReached && p->result == SZ_OK && + p->keepSizeAfter == GET_AVAIL_BYTES(p)) + { + // we try to read only in exact state (p->keepSizeAfter == GET_AVAIL_BYTES(p)) + if (MatchFinder_NeedMove(p)) + MatchFinder_MoveBlock(p); + MatchFinder_ReadBlock(p); + } + if (p->pos == kMaxValForNormalize) - MatchFinder_Normalize(p); - if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) - MatchFinder_CheckAndMoveAndRead(p); + if (GET_AVAIL_BYTES(p) >= p->numHashBytes) // optional optimization for last bytes of data. + /* + if we disable normalization for last bytes of data, and + if (data_size == 4 GiB), we don't call wastfull normalization, + but (pos) will be wrapped over Zero (0) in that case. + And we cannot resume later to normal operation + */ + { + // MatchFinder_Normalize(p); + /* after normalization we need (p->pos >= p->historySize + 1); */ + /* we can reduce subValue to aligned value, if want to keep alignment + of (p->pos) and (p->buffer) for speculated accesses. */ + const UInt32 subValue = (p->pos - p->historySize - 1) /* & ~(UInt32)(kNormalizeAlign - 1) */; + // const UInt32 subValue = (1 << 15); // for debug + // printf("\nMatchFinder_Normalize() subValue == 0x%x\n", subValue); + size_t numSonRefs = p->cyclicBufferSize; + if (p->btMode) + numSonRefs <<= 1; + Inline_MatchFinder_ReduceOffsets(p, subValue); + MatchFinder_Normalize3(subValue, p->hash, (size_t)p->hashSizeSum + numSonRefs); + } + if (p->cyclicBufferPos == p->cyclicBufferSize) p->cyclicBufferPos = 0; + MatchFinder_SetLimits(p); } @@ -386,9 +786,9 @@ static void MatchFinder_CheckLimits(CMatchFinder *p) (lenLimit > maxLen) */ MY_FORCE_INLINE -static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, - UInt32 *distances, unsigned maxLen) +static UInt32 * Hc_GetMatchesSpec(size_t lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *d, unsigned maxLen) { /* son[_cyclicBufferPos] = curMatch; @@ -396,7 +796,7 @@ static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) - return distances; + return d; { const Byte *pb = cur - delta; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; @@ -409,10 +809,10 @@ static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos if (maxLen < len) { maxLen = len; - *distances++ = len; - *distances++ = delta - 1; + *d++ = len; + *d++ = delta - 1; if (len == lenLimit) - return distances; + return d; } } } @@ -421,35 +821,41 @@ static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos const Byte *lim = cur + lenLimit; son[_cyclicBufferPos] = curMatch; + do { - UInt32 delta = pos - curMatch; + UInt32 delta; + + if (curMatch == 0) + break; + // if (curMatch2 >= curMatch) return NULL; + delta = pos - curMatch; if (delta >= _cyclicBufferSize) break; { ptrdiff_t diff; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; - diff = (ptrdiff_t)0 - delta; - if (cur[maxLen] == cur[maxLen + diff]) + diff = (ptrdiff_t)0 - (ptrdiff_t)delta; + if (cur[maxLen] == cur[(ptrdiff_t)maxLen + diff]) { const Byte *c = cur; while (*c == c[diff]) { if (++c == lim) { - distances[0] = (UInt32)(lim - cur); - distances[1] = delta - 1; - return distances + 2; + d[0] = (UInt32)(lim - cur); + d[1] = delta - 1; + return d + 2; } } { - unsigned len = (unsigned)(c - cur); + const unsigned len = (unsigned)(c - cur); if (maxLen < len) { maxLen = len; - distances[0] = (UInt32)len; - distances[1] = delta - 1; - distances += 2; + d[0] = (UInt32)len; + d[1] = delta - 1; + d += 2; } } } @@ -457,31 +863,36 @@ static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos } while (--cutValue); - return distances; + return d; } MY_FORCE_INLINE UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, - UInt32 *distances, UInt32 maxLen) + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *d, UInt32 maxLen) { CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); unsigned len0 = 0, len1 = 0; - for (;;) + + UInt32 cmCheck; + + // if (curMatch >= pos) { *ptr0 = *ptr1 = kEmptyHashValue; return NULL; } + + cmCheck = (UInt32)(pos - _cyclicBufferSize); + if ((UInt32)pos <= _cyclicBufferSize) + cmCheck = 0; + + if (cmCheck < curMatch) + do { - UInt32 delta = pos - curMatch; - if (cutValue-- == 0 || delta >= _cyclicBufferSize) - { - *ptr0 = *ptr1 = kEmptyHashValue; - return distances; - } + const UInt32 delta = pos - curMatch; { CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; unsigned len = (len0 < len1 ? len0 : len1); - UInt32 pair0 = pair[0]; + const UInt32 pair0 = pair[0]; if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) @@ -491,48 +902,60 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt if (maxLen < len) { maxLen = (UInt32)len; - *distances++ = (UInt32)len; - *distances++ = delta - 1; + *d++ = (UInt32)len; + *d++ = delta - 1; if (len == lenLimit) { *ptr1 = pair0; *ptr0 = pair[1]; - return distances; + return d; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; + // const UInt32 curMatch2 = pair[1]; + // if (curMatch2 >= curMatch) { *ptr0 = *ptr1 = kEmptyHashValue; return NULL; } + // curMatch = curMatch2; + curMatch = pair[1]; ptr1 = pair + 1; - curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; + curMatch = pair[0]; ptr0 = pair; - curMatch = *ptr0; len0 = len; } } } + while(--cutValue && cmCheck < curMatch); + + *ptr0 = *ptr1 = kEmptyHashValue; + return d; } + static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) { CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); unsigned len0 = 0, len1 = 0; - for (;;) + + UInt32 cmCheck; + + cmCheck = (UInt32)(pos - _cyclicBufferSize); + if ((UInt32)pos <= _cyclicBufferSize) + cmCheck = 0; + + if (// curMatch >= pos || // failure + cmCheck < curMatch) + do { - UInt32 delta = pos - curMatch; - if (cutValue-- == 0 || delta >= _cyclicBufferSize) - { - *ptr0 = *ptr1 = kEmptyHashValue; - return; - } + const UInt32 delta = pos - curMatch; { CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; @@ -554,80 +977,108 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const if (pb[len] < cur[len]) { *ptr1 = curMatch; + curMatch = pair[1]; ptr1 = pair + 1; - curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; + curMatch = pair[0]; ptr0 = pair; - curMatch = *ptr0; len0 = len; } } } + while(--cutValue && cmCheck < curMatch); + + *ptr0 = *ptr1 = kEmptyHashValue; + return; } + #define MOVE_POS \ ++p->cyclicBufferPos; \ p->buffer++; \ - if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); + { const UInt32 pos1 = p->pos + 1; p->pos = pos1; if (pos1 == p->posLimit) MatchFinder_CheckLimits(p); } -#define MOVE_POS_RET MOVE_POS return (UInt32)offset; +#define MOVE_POS_RET MOVE_POS return distances; -static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } +MY_NO_INLINE +static void MatchFinder_MovePos(CMatchFinder *p) +{ + /* we go here at the end of stream data, when (avail < num_hash_bytes) + We don't update sons[cyclicBufferPos << btMode]. + So (sons) record will contain junk. And we cannot resume match searching + to normal operation, even if we will provide more input data in buffer. + p->sons[p->cyclicBufferPos << p->btMode] = 0; // kEmptyHashValue + if (p->btMode) + p->sons[(p->cyclicBufferPos << p->btMode) + 1] = 0; // kEmptyHashValue + */ + MOVE_POS; +} #define GET_MATCHES_HEADER2(minLen, ret_op) \ - unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \ + unsigned lenLimit; UInt32 hv; Byte *cur; UInt32 curMatch; \ lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ cur = p->buffer; -#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) -#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) +#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return distances) +#define SKIP_HEADER(minLen) do { GET_MATCHES_HEADER2(minLen, continue) -#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue +#define MF_PARAMS(p) lenLimit, curMatch, p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue + +#define SKIP_FOOTER SkipMatchesSpec(MF_PARAMS(p)); MOVE_POS; } while (--num); + +#define GET_MATCHES_FOOTER_BASE(_maxLen_, func) \ + distances = func(MF_PARAMS(p), \ + distances, (UInt32)_maxLen_); MOVE_POS_RET; + +#define GET_MATCHES_FOOTER_BT(_maxLen_) \ + GET_MATCHES_FOOTER_BASE(_maxLen_, GetMatchesSpec1) + +#define GET_MATCHES_FOOTER_HC(_maxLen_) \ + GET_MATCHES_FOOTER_BASE(_maxLen_, Hc_GetMatchesSpec) -#define GET_MATCHES_FOOTER(offset, maxLen) \ - offset = (unsigned)(GetMatchesSpec1((UInt32)lenLimit, curMatch, MF_PARAMS(p), \ - distances + offset, (UInt32)maxLen) - distances); MOVE_POS_RET; -#define SKIP_FOOTER \ - SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; #define UPDATE_maxLen { \ - ptrdiff_t diff = (ptrdiff_t)0 - d2; \ + const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)d2; \ const Byte *c = cur + maxLen; \ const Byte *lim = cur + lenLimit; \ for (; c != lim; c++) if (*(c + diff) != *c) break; \ maxLen = (unsigned)(c - cur); } -static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +static UInt32* Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { - unsigned offset; GET_MATCHES_HEADER(2) HASH2_CALC; curMatch = p->hash[hv]; p->hash[hv] = p->pos; - offset = 0; - GET_MATCHES_FOOTER(offset, 1) + GET_MATCHES_FOOTER_BT(1) } -UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { - unsigned offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hv]; p->hash[hv] = p->pos; - offset = 0; - GET_MATCHES_FOOTER(offset, 2) + GET_MATCHES_FOOTER_BT(2) } -static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) + +#define SET_mmm \ + mmm = p->cyclicBufferSize; \ + if (pos < mmm) \ + mmm = pos; + + +static UInt32* Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { + UInt32 mmm; UInt32 h2, d2, pos; - unsigned maxLen, offset; + unsigned maxLen; UInt32 *hash; GET_MATCHES_HEADER(3) @@ -643,29 +1094,32 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) hash[h2] = pos; (hash + kFix3HashSize)[hv] = pos; - maxLen = 2; - offset = 0; + SET_mmm - if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + maxLen = 2; + + if (d2 < mmm && *(cur - d2) == *cur) { UPDATE_maxLen distances[0] = (UInt32)maxLen; distances[1] = d2 - 1; - offset = 2; + distances += 2; if (maxLen == lenLimit) { - SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); + SkipMatchesSpec(MF_PARAMS(p)); MOVE_POS_RET; } } - GET_MATCHES_FOOTER(offset, maxLen) + GET_MATCHES_FOOTER_BT(maxLen) } -static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) + +static UInt32* Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { + UInt32 mmm; UInt32 h2, h3, d2, d3, pos; - unsigned maxLen, offset; + unsigned maxLen; UInt32 *hash; GET_MATCHES_HEADER(4) @@ -676,53 +1130,63 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 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; + SET_mmm + + maxLen = 3; - if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + for (;;) { - maxLen = 2; - distances[0] = 2; - distances[1] = d2 - 1; - offset = 2; - } + if (d2 < mmm && *(cur - d2) == *cur) + { + distances[0] = 2; + distances[1] = d2 - 1; + distances += 2; + if (*(cur - d2 + 2) == cur[2]) + { + // distances[-2] = 3; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + d2 = d3; + distances[1] = d3 - 1; + distances += 2; + } + else + break; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + d2 = d3; + distances[1] = d3 - 1; + distances += 2; + } + else + break; - if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur) - { - maxLen = 3; - distances[(size_t)offset + 1] = d3 - 1; - offset += 2; - d2 = d3; - } - - if (offset != 0) - { UPDATE_maxLen - distances[(size_t)offset - 2] = (UInt32)maxLen; + distances[-2] = (UInt32)maxLen; if (maxLen == lenLimit) { - SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); - MOVE_POS_RET; + SkipMatchesSpec(MF_PARAMS(p)); + MOVE_POS_RET } + break; } - if (maxLen < 3) - maxLen = 3; - - GET_MATCHES_FOOTER(offset, maxLen) + GET_MATCHES_FOOTER_BT(maxLen) } -/* -static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) + +static UInt32* Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { - UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos; + UInt32 mmm; + UInt32 h2, h3, d2, d3, maxLen, pos; UInt32 *hash; GET_MATCHES_HEADER(5) @@ -733,73 +1197,69 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) d2 = pos - hash [h2]; d3 = pos - (hash + kFix3HashSize)[h3]; - d4 = pos - (hash + kFix4HashSize)[h4]; + // d4 = pos - (hash + kFix4HashSize)[h4]; curMatch = (hash + kFix5HashSize)[hv]; hash [h2] = pos; (hash + kFix3HashSize)[h3] = pos; - (hash + kFix4HashSize)[h4] = pos; + // (hash + kFix4HashSize)[h4] = pos; (hash + kFix5HashSize)[hv] = pos; - maxLen = 0; - offset = 0; + SET_mmm - if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + maxLen = 4; + + for (;;) { - 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) + if (d2 < mmm && *(cur - d2) == *cur) { - distances[2] = maxLen = 3; - distances[3] = d3 - 1; - offset = 4; + distances[0] = 2; + distances[1] = d2 - 1; + distances += 2; + if (*(cur - d2 + 2) == cur[2]) + { + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + distances[1] = d3 - 1; + distances += 2; + d2 = d3; + } + else + break; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + distances[1] = d3 - 1; + distances += 2; 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[(size_t)offset + 1] = d4 - 1; - offset += 2; - d2 = d4; - } - - if (offset != 0) - { + else + break; + + distances[-2] = 3; + if (*(cur - d2 + 3) != cur[3]) + break; UPDATE_maxLen - distances[(size_t)offset - 2] = maxLen; + distances[-2] = (UInt32)maxLen; if (maxLen == lenLimit) { - SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + SkipMatchesSpec(MF_PARAMS(p)); MOVE_POS_RET; } + break; } - - if (maxLen < 4) - maxLen = 4; - GET_MATCHES_FOOTER(offset, maxLen) + GET_MATCHES_FOOTER_BT(maxLen) } -*/ -static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) + +static UInt32* Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { + UInt32 mmm; UInt32 h2, h3, d2, d3, pos; - unsigned maxLen, offset; + unsigned maxLen; UInt32 *hash; GET_MATCHES_HEADER(4) @@ -816,48 +1276,57 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) (hash + kFix3HashSize)[h3] = pos; (hash + kFix4HashSize)[hv] = pos; - maxLen = 0; - offset = 0; + SET_mmm - if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) - { - maxLen = 2; - distances[0] = 2; - distances[1] = d2 - 1; - offset = 2; - } - - if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur) - { - maxLen = 3; - distances[(size_t)offset + 1] = d3 - 1; - offset += 2; - d2 = d3; - } - - if (offset != 0) + maxLen = 3; + + for (;;) { + if (d2 < mmm && *(cur - d2) == *cur) + { + distances[0] = 2; + distances[1] = d2 - 1; + distances += 2; + if (*(cur - d2 + 2) == cur[2]) + { + // distances[-2] = 3; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + d2 = d3; + distances[1] = d3 - 1; + distances += 2; + } + else + break; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + d2 = d3; + distances[1] = d3 - 1; + distances += 2; + } + else + break; + UPDATE_maxLen - distances[(size_t)offset - 2] = (UInt32)maxLen; + distances[-2] = (UInt32)maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } + break; } - if (maxLen < 3) - maxLen = 3; - - offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), - distances + offset, maxLen) - (distances)); - MOVE_POS_RET + GET_MATCHES_FOOTER_HC(maxLen); } -/* -static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) + +static UInt32 * Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { - UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos + UInt32 mmm; + UInt32 h2, h3, d2, d3, maxLen, pos; UInt32 *hash; GET_MATCHES_HEADER(5) @@ -865,242 +1334,237 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) hash = p->hash; pos = p->pos; - + d2 = pos - hash [h2]; d3 = pos - (hash + kFix3HashSize)[h3]; - d4 = pos - (hash + kFix4HashSize)[h4]; + // d4 = pos - (hash + kFix4HashSize)[h4]; curMatch = (hash + kFix5HashSize)[hv]; hash [h2] = pos; (hash + kFix3HashSize)[h3] = pos; - (hash + kFix4HashSize)[h4] = pos; + // (hash + kFix4HashSize)[h4] = pos; (hash + kFix5HashSize)[hv] = pos; - maxLen = 0; - offset = 0; + SET_mmm + + maxLen = 4; - if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + for (;;) { - 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) + if (d2 < mmm && *(cur - d2) == *cur) { - distances[2] = maxLen = 3; - distances[3] = d3 - 1; - offset = 4; + distances[0] = 2; + distances[1] = d2 - 1; + distances += 2; + if (*(cur - d2 + 2) == cur[2]) + { + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + distances[1] = d3 - 1; + distances += 2; + d2 = d3; + } + else + break; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + distances[1] = d3 - 1; + distances += 2; 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[(size_t)offset + 1] = d4 - 1; - offset += 2; - d2 = d4; - } - - if (offset != 0) - { + else + break; + + distances[-2] = 3; + if (*(cur - d2 + 3) != cur[3]) + break; UPDATE_maxLen - distances[(size_t)offset - 2] = maxLen; + distances[-2] = maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } + break; } - if (maxLen < 4) - maxLen = 4; - - offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), - distances + offset, maxLen) - (distances)); - MOVE_POS_RET + GET_MATCHES_FOOTER_HC(maxLen); } -*/ -UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) + +UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { - unsigned offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hv]; p->hash[hv] = p->pos; - offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), - distances, 2) - (distances)); - MOVE_POS_RET + GET_MATCHES_FOOTER_HC(2) } + static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do + SKIP_HEADER(2) { - SKIP_HEADER(2) HASH2_CALC; curMatch = p->hash[hv]; p->hash[hv] = p->pos; - SKIP_FOOTER } - while (--num != 0); + SKIP_FOOTER } void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do + SKIP_HEADER(3) { - SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hv]; p->hash[hv] = p->pos; - SKIP_FOOTER } - while (--num != 0); + SKIP_FOOTER } static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do + SKIP_HEADER(3) { UInt32 h2; UInt32 *hash; - SKIP_HEADER(3) HASH3_CALC; hash = p->hash; curMatch = (hash + kFix3HashSize)[hv]; hash[h2] = (hash + kFix3HashSize)[hv] = p->pos; - SKIP_FOOTER } - while (--num != 0); + SKIP_FOOTER } static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do + SKIP_HEADER(4) { UInt32 h2, h3; UInt32 *hash; - SKIP_HEADER(4) HASH4_CALC; hash = p->hash; curMatch = (hash + kFix4HashSize)[hv]; hash [h2] = (hash + kFix3HashSize)[h3] = (hash + kFix4HashSize)[hv] = p->pos; - SKIP_FOOTER } - while (--num != 0); + SKIP_FOOTER } -/* static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do + SKIP_HEADER(5) { - UInt32 h2, h3, h4; + UInt32 h2, h3; UInt32 *hash; - SKIP_HEADER(5) HASH5_CALC; hash = p->hash; curMatch = (hash + kFix5HashSize)[hv]; hash [h2] = (hash + kFix3HashSize)[h3] = - (hash + kFix4HashSize)[h4] = + // (hash + kFix4HashSize)[h4] = (hash + kFix5HashSize)[hv] = p->pos; - SKIP_FOOTER } - while (--num != 0); + SKIP_FOOTER } -*/ + + +#define HC_SKIP_HEADER(minLen) \ + do { if (p->lenLimit < minLen) { MatchFinder_MovePos(p); num--; continue; } { \ + Byte *cur; \ + UInt32 *hash; \ + UInt32 *son; \ + UInt32 pos = p->pos; \ + UInt32 num2 = num; \ + /* (p->pos == p->posLimit) is not allowed here !!! */ \ + { const UInt32 rem = p->posLimit - pos; if (num2 > rem) num2 = rem; } \ + num -= num2; \ + { const UInt32 cycPos = p->cyclicBufferPos; \ + son = p->son + cycPos; \ + p->cyclicBufferPos = cycPos + num2; } \ + cur = p->buffer; \ + hash = p->hash; \ + do { \ + UInt32 curMatch; \ + UInt32 hv; + + +#define HC_SKIP_FOOTER \ + cur++; pos++; *son++ = curMatch; \ + } while (--num2); \ + p->buffer = cur; \ + p->pos = pos; \ + if (pos == p->posLimit) MatchFinder_CheckLimits(p); \ + }} while(num); \ + static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do - { + HC_SKIP_HEADER(4) + UInt32 h2, h3; - UInt32 *hash; - SKIP_HEADER(4) HASH4_CALC; - 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); + (hash + kFix4HashSize)[hv] = pos; + + HC_SKIP_FOOTER } -/* + 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 = hash + kFix5HashSize)[hv]; + HC_SKIP_HEADER(5) + + UInt32 h2, h3; + HASH5_CALC + curMatch = (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); + // (hash + kFix4HashSize)[h4] = + (hash + kFix5HashSize)[hv] = pos; + + HC_SKIP_FOOTER } -*/ + void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do - { - SKIP_HEADER(3) + HC_SKIP_HEADER(3) + HASH_ZIP_CALC; - curMatch = p->hash[hv]; - p->hash[hv] = p->pos; - p->son[p->cyclicBufferPos] = curMatch; - MOVE_POS - } - while (--num != 0); + curMatch = hash[hv]; + hash[hv] = pos; + + HC_SKIP_FOOTER } -void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable) { vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; if (!p->btMode) { - /* if (p->numHashBytes <= 4) */ + 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) { @@ -1112,16 +1576,53 @@ void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; } - else /* if (p->numHashBytes == 4) */ + 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; } - */ +} + + + +void LzFindPrepare() +{ + #ifndef FORCE_SATUR_SUB_128 + #ifdef USE_SATUR_SUB_128 + LZFIND_SATUR_SUB_CODE_FUNC f = NULL; + #ifdef MY_CPU_ARM_OR_ARM64 + { + if (CPU_IsSupported_NEON()) + { + // #pragma message ("=== LzFind NEON") + _PRF(printf("\n=== LzFind NEON\n")); + f = LzFind_SaturSub_128; + } + // f = 0; // for debug + } + #else // MY_CPU_ARM_OR_ARM64 + if (CPU_IsSupported_SSE41()) + { + // #pragma message ("=== LzFind SSE41") + _PRF(printf("\n=== LzFind SSE41\n")); + f = LzFind_SaturSub_128; + + #ifdef USE_AVX2 + if (CPU_IsSupported_AVX2()) + { + // #pragma message ("=== LzFind AVX2") + _PRF(printf("\n=== LzFind AVX2\n")); + f = LzFind_SaturSub_256; + } + #endif + } + #endif // MY_CPU_ARM_OR_ARM64 + g_LzFind_SaturSub = f; + #endif // USE_SATUR_SUB_128 + #endif // FORCE_SATUR_SUB_128 } diff --git a/libraries/lzma/C/LzFind.h b/libraries/lzma/C/LzFind.h index 42c13be15..eea873ff6 100644 --- a/libraries/lzma/C/LzFind.h +++ b/libraries/lzma/C/LzFind.h @@ -1,5 +1,5 @@ /* LzFind.h -- Match finder for LZ algorithms -2017-06-10 : Igor Pavlov : Public domain */ +2021-07-13 : Igor Pavlov : Public domain */ #ifndef __LZ_FIND_H #define __LZ_FIND_H @@ -15,7 +15,7 @@ typedef struct _CMatchFinder Byte *buffer; UInt32 pos; UInt32 posLimit; - UInt32 streamPos; + UInt32 streamPos; /* wrap over Zero is allowed (streamPos < pos). Use (UInt32)(streamPos - pos) */ UInt32 lenLimit; UInt32 cyclicBufferPos; @@ -51,17 +51,19 @@ typedef struct _CMatchFinder UInt64 expectedDataSize; } CMatchFinder; -#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) +#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((const Byte *)(p)->buffer) -#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) +#define Inline_MatchFinder_GetNumAvailableBytes(p) ((UInt32)((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); +/* Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); */ void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_ReadIfRequired(CMatchFinder *p); @@ -76,10 +78,21 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, ISzAllocPtr alloc); void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems); -void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); +// void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); + +/* +#define Inline_MatchFinder_InitPos(p, val) \ + (p)->pos = (val); \ + (p)->streamPos = (val); +*/ + +#define Inline_MatchFinder_ReduceOffsets(p, subValue) \ + (p)->pos -= (subValue); \ + (p)->streamPos -= (subValue); + UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *distances, UInt32 maxLen); /* @@ -91,7 +104,7 @@ Conditions: typedef void (*Mf_Init_Func)(void *object); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); -typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); +typedef UInt32 * (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); typedef struct _IMatchFinder @@ -101,21 +114,23 @@ typedef struct _IMatchFinder Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetMatches_Func GetMatches; Mf_Skip_Func Skip; -} IMatchFinder; +} IMatchFinder2; -void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable); void MatchFinder_Init_LowHash(CMatchFinder *p); void MatchFinder_Init_HighHash(CMatchFinder *p); -void MatchFinder_Init_3(CMatchFinder *p, int readData); +void MatchFinder_Init_4(CMatchFinder *p); void MatchFinder_Init(CMatchFinder *p); -UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); -UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +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); +void LzFindPrepare(void); + EXTERN_C_END #endif diff --git a/libraries/lzma/C/LzFindMt.c b/libraries/lzma/C/LzFindMt.c index bb0f42c30..4e67fc3f2 100644 --- a/libraries/lzma/C/LzFindMt.c +++ b/libraries/lzma/C/LzFindMt.c @@ -1,97 +1,215 @@ /* LzFindMt.c -- multithreaded Match finder for LZ algorithms -2018-12-29 : Igor Pavlov : Public domain */ +2021-12-21 : Igor Pavlov : Public domain */ #include "Precomp.h" -#include "LzHash.h" +// #include +#include "CpuArch.h" + +#include "LzHash.h" #include "LzFindMt.h" +// #define LOG_ITERS + +// #define LOG_THREAD + +#ifdef LOG_THREAD +#include +#define PRF(x) x +#else +#define PRF(x) +#endif + +#ifdef LOG_ITERS +#include +extern UInt64 g_NumIters_Tree; +extern UInt64 g_NumIters_Loop; +extern UInt64 g_NumIters_Bytes; +#define LOG_ITER(x) x +#else +#define LOG_ITER(x) +#endif + +#define kMtHashBlockSize ((UInt32)1 << 17) +#define kMtHashNumBlocks (1 << 1) + +#define GET_HASH_BLOCK_OFFSET(i) (((i) & (kMtHashNumBlocks - 1)) * kMtHashBlockSize) + +#define kMtBtBlockSize ((UInt32)1 << 16) +#define kMtBtNumBlocks (1 << 4) + +#define GET_BT_BLOCK_OFFSET(i) (((i) & (kMtBtNumBlocks - 1)) * (size_t)kMtBtBlockSize) + +/* + HASH functions: + We use raw 8/16 bits from a[1] and a[2], + xored with crc(a[0]) and crc(a[3]). + We check a[0], a[3] only. We don't need to compare a[1] and a[2] in matches. + our crc() function provides one-to-one correspondence for low 8-bit values: + (crc[0...0xFF] & 0xFF) <-> [0...0xFF] +*/ + +#define MF(mt) ((mt)->MatchFinder) +#define MF_CRC (p->crc) + +// #define MF(mt) (&(mt)->MatchFinder) +// #define MF_CRC (p->MatchFinder.crc) + +#define MT_HASH2_CALC \ + h2 = (MF_CRC[cur[0]] ^ cur[1]) & (kHash2Size - 1); + +#define MT_HASH3_CALC { \ + UInt32 temp = MF_CRC[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +/* +#define MT_HASH3_CALC__NO_2 { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +#define __MT_HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + h4 = (temp ^ (p->crc[cur[3]] << kLzHash_CrcShift_1)) & p->hash4Mask; } + // (kHash4Size - 1); +*/ + + +MY_NO_INLINE static void MtSync_Construct(CMtSync *p) { + p->affinity = 0; p->wasCreated = False; p->csWasInitialized = False; p->csWasEntered = False; Thread_Construct(&p->thread); Event_Construct(&p->canStart); - Event_Construct(&p->wasStarted); Event_Construct(&p->wasStopped); Semaphore_Construct(&p->freeSemaphore); Semaphore_Construct(&p->filledSemaphore); } -static void MtSync_GetNextBlock(CMtSync *p) + +#define DEBUG_BUFFER_LOCK // define it to debug lock state + +#ifdef DEBUG_BUFFER_LOCK +#include +#define BUFFER_MUST_BE_LOCKED(p) if (!(p)->csWasEntered) exit(1); +#define BUFFER_MUST_BE_UNLOCKED(p) if ( (p)->csWasEntered) exit(1); +#else +#define BUFFER_MUST_BE_LOCKED(p) +#define BUFFER_MUST_BE_UNLOCKED(p) +#endif + +#define LOCK_BUFFER(p) { \ + BUFFER_MUST_BE_UNLOCKED(p); \ + CriticalSection_Enter(&(p)->cs); \ + (p)->csWasEntered = True; } + +#define UNLOCK_BUFFER(p) { \ + BUFFER_MUST_BE_LOCKED(p); \ + CriticalSection_Leave(&(p)->cs); \ + (p)->csWasEntered = False; } + + +MY_NO_INLINE +static UInt32 MtSync_GetNextBlock(CMtSync *p) { + UInt32 numBlocks = 0; if (p->needStart) { + BUFFER_MUST_BE_UNLOCKED(p) p->numProcessedBlocks = 1; p->needStart = False; p->stopWriting = False; p->exit = False; - Event_Reset(&p->wasStarted); Event_Reset(&p->wasStopped); - Event_Set(&p->canStart); - Event_Wait(&p->wasStarted); - - // if (mt) MatchFinder_Init_LowHash(mt->MatchFinder); } else { - CriticalSection_Leave(&p->cs); - p->csWasEntered = False; - p->numProcessedBlocks++; + UNLOCK_BUFFER(p) + // we free current block + numBlocks = p->numProcessedBlocks++; Semaphore_Release1(&p->freeSemaphore); } + + // buffer is UNLOCKED here Semaphore_Wait(&p->filledSemaphore); - CriticalSection_Enter(&p->cs); - p->csWasEntered = True; + LOCK_BUFFER(p); + return numBlocks; } -/* MtSync_StopWriting must be called if Writing was started */ +/* if Writing (Processing) thread was started, we must call MtSync_StopWriting() */ + +MY_NO_INLINE static void MtSync_StopWriting(CMtSync *p) { - UInt32 myNumBlocks = p->numProcessedBlocks; if (!Thread_WasCreated(&p->thread) || p->needStart) return; - p->stopWriting = True; + + PRF(printf("\nMtSync_StopWriting %p\n", p)); + if (p->csWasEntered) { - CriticalSection_Leave(&p->cs); - p->csWasEntered = False; + /* we don't use buffer in this thread after StopWriting(). + So we UNLOCK buffer. + And we restore default UNLOCKED state for stopped thread */ + UNLOCK_BUFFER(p) } - Semaphore_Release1(&p->freeSemaphore); - - Event_Wait(&p->wasStopped); - while (myNumBlocks++ != p->numProcessedBlocks) - { - Semaphore_Wait(&p->filledSemaphore); - Semaphore_Release1(&p->freeSemaphore); - } + /* We send (p->stopWriting) message and release freeSemaphore + to free current block. + So the thread will see (p->stopWriting) at some + iteration after Wait(freeSemaphore). + The thread doesn't need to fill all avail free blocks, + so we can get fast thread stop. + */ + + p->stopWriting = True; + Semaphore_Release1(&p->freeSemaphore); // check semaphore count !!! + + PRF(printf("\nMtSync_StopWriting %p : Event_Wait(&p->wasStopped)\n", p)); + Event_Wait(&p->wasStopped); + PRF(printf("\nMtSync_StopWriting %p : Event_Wait() finsihed\n", p)); + + /* 21.03 : we don't restore samaphore counters here. + We will recreate and reinit samaphores in next start */ + p->needStart = True; } + +MY_NO_INLINE static void MtSync_Destruct(CMtSync *p) { + PRF(printf("\nMtSync_Destruct %p\n", p)); + if (Thread_WasCreated(&p->thread)) { + /* we want thread to be in Stopped state before sending EXIT command. + note: stop(btSync) will stop (htSync) also */ MtSync_StopWriting(p); + /* thread in Stopped state here : (p->needStart == true) */ p->exit = True; - if (p->needStart) - Event_Set(&p->canStart); - Thread_Wait(&p->thread); - Thread_Close(&p->thread); + // if (p->needStart) // it's (true) + Event_Set(&p->canStart); // we send EXIT command to thread + Thread_Wait_Close(&p->thread); // we wait thread finishing } + if (p->csWasInitialized) { CriticalSection_Delete(&p->cs); p->csWasInitialized = False; } + p->csWasEntered = False; Event_Close(&p->canStart); - Event_Close(&p->wasStarted); Event_Close(&p->wasStopped); Semaphore_Close(&p->freeSemaphore); Semaphore_Close(&p->filledSemaphore); @@ -99,80 +217,251 @@ static void MtSync_Destruct(CMtSync *p) p->wasCreated = False; } -#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } -static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) +// #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } +// we want to get real system error codes here instead of SZ_ERROR_THREAD +#define RINOK_THREAD(x) RINOK(x) + + +// call it before each new file (when new starting is required): +MY_NO_INLINE +static SRes MtSync_Init(CMtSync *p, UInt32 numBlocks) { + WRes wres; + // BUFFER_MUST_BE_UNLOCKED(p) + if (!p->needStart || p->csWasEntered) + return SZ_ERROR_FAIL; + wres = Semaphore_OptCreateInit(&p->freeSemaphore, numBlocks, numBlocks); + if (wres == 0) + wres = Semaphore_OptCreateInit(&p->filledSemaphore, 0, numBlocks); + return MY_SRes_HRESULT_FROM_WRes(wres); +} + + +static WRes MtSync_Create_WRes(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj) +{ + WRes wres; + if (p->wasCreated) return SZ_OK; RINOK_THREAD(CriticalSection_Init(&p->cs)); p->csWasInitialized = True; + p->csWasEntered = False; RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); - RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); - - RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); - RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); p->needStart = True; - - RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj)); + p->exit = True; /* p->exit is unused before (canStart) Event. + But in case of some unexpected code failure we will get fast exit from thread */ + + // return ERROR_TOO_MANY_POSTS; // for debug + // return EINVAL; // for debug + + if (p->affinity != 0) + wres = Thread_Create_With_Affinity(&p->thread, startAddress, obj, (CAffinityMask)p->affinity); + else + wres = Thread_Create(&p->thread, startAddress, obj); + + RINOK_THREAD(wres); p->wasCreated = True; return SZ_OK; } -static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) + +MY_NO_INLINE +static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj) { - SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); - if (res != SZ_OK) - MtSync_Destruct(p); - return res; + const WRes wres = MtSync_Create_WRes(p, startAddress, obj); + if (wres == 0) + return 0; + MtSync_Destruct(p); + return MY_SRes_HRESULT_FROM_WRes(wres); } -void MtSync_Init(CMtSync *p) { p->needStart = True; } + +// ---------- HASH THREAD ---------- #define kMtMaxValForNormalize 0xFFFFFFFF +// #define kMtMaxValForNormalize ((1 << 21)) // for debug +// #define kNormalizeAlign (1 << 7) // alignment for speculated accesses + +#ifdef MY_CPU_LE_UNALIGN + #define GetUi24hi_from32(p) ((UInt32)GetUi32(p) >> 8) +#else + #define GetUi24hi_from32(p) ((p)[1] ^ ((UInt32)(p)[2] << 8) ^ ((UInt32)(p)[3] << 16)) +#endif + +#define GetHeads_DECL(name) \ + static void GetHeads ## name(const Byte *p, UInt32 pos, \ + UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) + +#define GetHeads_LOOP(v) \ + for (; numHeads != 0; numHeads--) { \ + const UInt32 value = (v); \ + p++; \ + *heads++ = pos - hash[value]; \ + hash[value] = pos++; } #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++; } } - + GetHeads_DECL(name) { action \ + GetHeads_LOOP(v) } + #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) -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) */ +DEF_GetHeads2(2, GetUi16(p), UNUSED_VAR(hashMask); UNUSED_VAR(crc); ) +DEF_GetHeads(3, (crc[p[0]] ^ GetUi16(p + 1)) & hashMask) +DEF_GetHeads2(3b, GetUi16(p) ^ ((UInt32)(p)[2] << 16), UNUSED_VAR(hashMask); UNUSED_VAR(crc); ) +// BT3 is not good for crc collisions for big hashMask values. + +/* +GetHeads_DECL(3b) +{ + UNUSED_VAR(hashMask); + UNUSED_VAR(crc); + { + const Byte *pLim = p + numHeads; + if (numHeads == 0) + return; + pLim--; + while (p < pLim) + { + UInt32 v1 = GetUi32(p); + UInt32 v0 = v1 & 0xFFFFFF; + UInt32 h0, h1; + p += 2; + v1 >>= 8; + h0 = hash[v0]; hash[v0] = pos; heads[0] = pos - h0; pos++; + h1 = hash[v1]; hash[v1] = pos; heads[1] = pos - h1; pos++; + heads += 2; + } + if (p == pLim) + { + UInt32 v0 = GetUi16(p) ^ ((UInt32)(p)[2] << 16); + *heads = pos - hash[v0]; + hash[v0] = pos; + } + } +} +*/ + +/* +GetHeads_DECL(4) +{ + unsigned sh = 0; + UNUSED_VAR(crc) + while ((hashMask & 0x80000000) == 0) + { + hashMask <<= 1; + sh++; + } + GetHeads_LOOP((GetUi32(p) * 0xa54a1) >> sh) +} +#define GetHeads4b GetHeads4 +*/ + +#define USE_GetHeads_LOCAL_CRC + +#ifdef USE_GetHeads_LOCAL_CRC + +GetHeads_DECL(4) +{ + UInt32 crc0[256]; + UInt32 crc1[256]; + { + unsigned i; + for (i = 0; i < 256; i++) + { + UInt32 v = crc[i]; + crc0[i] = v & hashMask; + crc1[i] = (v << kLzHash_CrcShift_1) & hashMask; + // crc1[i] = rotlFixed(v, 8) & hashMask; + } + } + GetHeads_LOOP(crc0[p[0]] ^ crc1[p[3]] ^ (UInt32)GetUi16(p+1)) +} + +GetHeads_DECL(4b) +{ + UInt32 crc0[256]; + { + unsigned i; + for (i = 0; i < 256; i++) + crc0[i] = crc[i] & hashMask; + } + GetHeads_LOOP(crc0[p[0]] ^ GetUi24hi_from32(p)) +} + +GetHeads_DECL(5) +{ + UInt32 crc0[256]; + UInt32 crc1[256]; + UInt32 crc2[256]; + { + unsigned i; + for (i = 0; i < 256; i++) + { + UInt32 v = crc[i]; + crc0[i] = v & hashMask; + crc1[i] = (v << kLzHash_CrcShift_1) & hashMask; + crc2[i] = (v << kLzHash_CrcShift_2) & hashMask; + } + } + GetHeads_LOOP(crc0[p[0]] ^ crc1[p[3]] ^ crc2[p[4]] ^ (UInt32)GetUi16(p+1)) +} + +GetHeads_DECL(5b) +{ + UInt32 crc0[256]; + UInt32 crc1[256]; + { + unsigned i; + for (i = 0; i < 256; i++) + { + UInt32 v = crc[i]; + crc0[i] = v & hashMask; + crc1[i] = (v << kLzHash_CrcShift_1) & hashMask; + } + } + GetHeads_LOOP(crc0[p[0]] ^ crc1[p[4]] ^ GetUi24hi_from32(p)) +} + +#else + +DEF_GetHeads(4, (crc[p[0]] ^ (crc[p[3]] << kLzHash_CrcShift_1) ^ (UInt32)GetUi16(p+1)) & hashMask) +DEF_GetHeads(4b, (crc[p[0]] ^ GetUi24hi_from32(p)) & hashMask) +DEF_GetHeads(5, (crc[p[0]] ^ (crc[p[3]] << kLzHash_CrcShift_1) ^ (crc[p[4]] << kLzHash_CrcShift_2) ^ (UInt32)GetUi16(p + 1)) & hashMask) +DEF_GetHeads(5b, (crc[p[0]] ^ (crc[p[4]] << kLzHash_CrcShift_1) ^ GetUi24hi_from32(p)) & hashMask) + +#endif + static void HashThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->hashSync; + PRF(printf("\nHashThreadFunc\n")); + for (;;) { - UInt32 numProcessedBlocks = 0; + UInt32 blockIndex = 0; + PRF(printf("\nHashThreadFunc : Event_Wait(&p->canStart)\n")); Event_Wait(&p->canStart); - Event_Set(&p->wasStarted); + PRF(printf("\nHashThreadFunc : Event_Wait(&p->canStart) : after \n")); + if (p->exit) + { + PRF(printf("\nHashThreadFunc : exit \n")); + return; + } - MatchFinder_Init_HighHash(mt->MatchFinder); + MatchFinder_Init_HighHash(MF(mt)); for (;;) { - if (p->exit) - return; - if (p->stopWriting) - { - p->numProcessedBlocks = numProcessedBlocks; - Event_Set(&p->wasStopped); - break; - } + PRF(printf("Hash thread block = %d pos = %d\n", (unsigned)blockIndex, mt->MatchFinder->pos)); { - CMatchFinder *mf = mt->MatchFinder; + CMatchFinder *mf = MF(mt); if (MatchFinder_NeedMove(mf)) { CriticalSection_Enter(&mt->btSync.cs); @@ -185,194 +474,178 @@ static void HashThreadFunc(CMatchFinderMt *mt) mt->pointerToCurPos -= offset; mt->buffer -= offset; } - CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->hashSync.cs); + CriticalSection_Leave(&mt->btSync.cs); continue; } Semaphore_Wait(&p->freeSemaphore); + if (p->exit) // exit is unexpected here. But we check it here for some failure case + return; + + // for faster stop : we check (p->stopWriting) after Wait(freeSemaphore) + if (p->stopWriting) + break; + MatchFinder_ReadIfRequired(mf); - if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) { - UInt32 subValue = (mf->pos - mf->historySize - 1); - MatchFinder_ReduceOffsets(mf, subValue); - MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1); - } - { - UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; - UInt32 num = mf->streamPos - mf->pos; + UInt32 *heads = mt->hashBuf + GET_HASH_BLOCK_OFFSET(blockIndex++); + UInt32 num = Inline_MatchFinder_GetNumAvailableBytes(mf); heads[0] = 2; heads[1] = num; + + /* heads[1] contains the number of avail bytes: + if (avail < mf->numHashBytes) : + { + it means that stream was finished + HASH_THREAD and BT_TREAD must move position for heads[1] (avail) bytes. + HASH_THREAD doesn't stop, + HASH_THREAD fills only the header (2 numbers) for all next blocks: + {2, NumHashBytes - 1}, {2,0}, {2,0}, ... , {2,0} + } + else + { + HASH_THREAD and BT_TREAD must move position for (heads[0] - 2) bytes; + } + */ + if (num >= mf->numHashBytes) { num = num - mf->numHashBytes + 1; if (num > kMtHashBlockSize - 2) num = kMtHashBlockSize - 2; - mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); + + if (mf->pos > (UInt32)kMtMaxValForNormalize - num) + { + const UInt32 subValue = (mf->pos - mf->historySize - 1); // & ~(UInt32)(kNormalizeAlign - 1); + Inline_MatchFinder_ReduceOffsets(mf, subValue); + MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1); + } + heads[0] = 2 + num; + mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); } - mf->pos += num; + + mf->pos += num; // wrap over zero is allowed at the end of stream mf->buffer += num; } } Semaphore_Release1(&p->filledSemaphore); - } - } + } // for() processing end + + // p->numBlocks_Sent = blockIndex; + Event_Set(&p->wasStopped); + } // for() thread end } -static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) -{ - MtSync_GetNextBlock(&p->hashSync); - p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; - p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; - p->hashNumAvail = p->hashBuf[p->hashBufPos++]; -} -#define kEmptyHashValue 0 + + +// ---------- BT THREAD ---------- + +/* we use one variable instead of two (cyclicBufferPos == pos) before CyclicBuf wrap. + here we define fixed offset of (p->pos) from (p->cyclicBufferPos) */ +#define CYC_TO_POS_OFFSET 0 +// #define CYC_TO_POS_OFFSET 1 // for debug #define MFMT_GM_INLINE #ifdef MFMT_GM_INLINE /* - we use size_t for _cyclicBufferPos instead of UInt32 + we use size_t for (pos) instead of UInt32 to eliminate "movsx" BUG in old MSVC x64 compiler. */ -MY_NO_INLINE -static UInt32 *GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, - size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, - UInt32 *distances, UInt32 _maxLen, const UInt32 *hash, const UInt32 *limit, UInt32 size, UInt32 *posRes) -{ - do - { - UInt32 *_distances = ++distances; - UInt32 delta = *hash++; - CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; - CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); - unsigned len0 = 0, len1 = 0; - UInt32 cutValue = _cutValue; - unsigned maxLen = (unsigned)_maxLen; - - /* - if (size > 1) - { - UInt32 delta = *hash; - if (delta < _cyclicBufferSize) - { - UInt32 cyc1 = _cyclicBufferPos + 1; - CLzRef *pair = son + ((size_t)(cyc1 - delta + ((delta > cyc1) ? _cyclicBufferSize : 0)) << 1); - Byte b = *(cur + 1 - delta); - _distances[0] = pair[0]; - _distances[1] = b; - } - } - */ - if (cutValue == 0 || delta >= _cyclicBufferSize) - { - *ptr0 = *ptr1 = kEmptyHashValue; - } - else - for(;;) - { - { - CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((_cyclicBufferPos < delta) ? _cyclicBufferSize : 0)) << 1); - const Byte *pb = cur - delta; - unsigned len = (len0 < len1 ? len0 : len1); - UInt32 pair0 = *pair; - if (pb[len] == cur[len]) - { - if (++len != lenLimit && pb[len] == cur[len]) - while (++len != lenLimit) - if (pb[len] != cur[len]) - break; - if (maxLen < len) - { - maxLen = len; - *distances++ = (UInt32)len; - *distances++ = delta - 1; - if (len == lenLimit) - { - UInt32 pair1 = pair[1]; - *ptr1 = pair0; - *ptr0 = pair1; - break; - } - } - } - { - UInt32 curMatch = pos - delta; - // delta = pos - *pair; - // delta = pos - pair[((UInt32)pb[len] - (UInt32)cur[len]) >> 31]; - if (pb[len] < cur[len]) - { - delta = pos - pair[1]; - *ptr1 = curMatch; - ptr1 = pair + 1; - len1 = len; - } - else - { - delta = pos - *pair; - *ptr0 = curMatch; - ptr0 = pair; - len0 = len; - } - } - } - if (--cutValue == 0 || delta >= _cyclicBufferSize) - { - *ptr0 = *ptr1 = kEmptyHashValue; - break; - } - } - pos++; - _cyclicBufferPos++; - cur++; - { - UInt32 num = (UInt32)(distances - _distances); - _distances[-1] = num; - } - } - while (distances < limit && --size != 0); - *posRes = pos; - return distances; -} +UInt32 * MY_FAST_CALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, + UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, + UInt32 *posRes); #endif - -static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) +static void BtGetMatches(CMatchFinderMt *p, UInt32 *d) { UInt32 numProcessed = 0; UInt32 curPos = 2; - UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); // * 2 - distances[1] = p->hashNumAvail; + /* GetMatchesSpec() functions don't create (len = 1) + in [len, dist] match pairs, if (p->numHashBytes >= 2) + Also we suppose here that (matchMaxLen >= 2). + So the following code for (reserve) is not required + UInt32 reserve = (p->matchMaxLen * 2); + const UInt32 kNumHashBytes_Max = 5; // BT_HASH_BYTES_MAX + if (reserve < kNumHashBytes_Max - 1) + reserve = kNumHashBytes_Max - 1; + const UInt32 limit = kMtBtBlockSize - (reserve); + */ + + const UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); + + d[1] = p->hashNumAvail; + + if (p->failure_BT) + { + // printf("\n == 1 BtGetMatches() p->failure_BT\n"); + d[0] = 0; + // d[1] = 0; + return; + } while (curPos < limit) { if (p->hashBufPos == p->hashBufPosLimit) { - MatchFinderMt_GetNextBlock_Hash(p); - distances[1] = numProcessed + p->hashNumAvail; - if (p->hashNumAvail >= p->numHashBytes) + // MatchFinderMt_GetNextBlock_Hash(p); + UInt32 avail; + { + const UInt32 bi = MtSync_GetNextBlock(&p->hashSync); + const UInt32 k = GET_HASH_BLOCK_OFFSET(bi); + const UInt32 *h = p->hashBuf + k; + avail = h[1]; + p->hashBufPosLimit = k + h[0]; + p->hashNumAvail = avail; + p->hashBufPos = k + 2; + } + + { + /* we must prevent UInt32 overflow for avail total value, + if avail was increased with new hash block */ + UInt32 availSum = numProcessed + avail; + if (availSum < numProcessed) + availSum = (UInt32)(Int32)-1; + d[1] = availSum; + } + + if (avail >= p->numHashBytes) continue; - distances[0] = curPos + p->hashNumAvail; - distances += curPos; - for (; p->hashNumAvail != 0; p->hashNumAvail--) - *distances++ = 0; + + // if (p->hashBufPos != p->hashBufPosLimit) exit(1); + + /* (avail < p->numHashBytes) + It means that stream was finished. + And (avail) - is a number of remaining bytes, + we fill (d) for (avail) bytes for LZ_THREAD (receiver). + but we don't update (p->pos) and (p->cyclicBufferPos) here in BT_THREAD */ + + /* here we suppose that we have space enough: + (kMtBtBlockSize - curPos >= p->hashNumAvail) */ + p->hashNumAvail = 0; + d[0] = curPos + avail; + d += curPos; + for (; avail != 0; avail--) + *d++ = 0; return; } { UInt32 size = p->hashBufPosLimit - p->hashBufPos; - UInt32 lenLimit = p->matchMaxLen; UInt32 pos = p->pos; UInt32 cyclicBufferPos = p->cyclicBufferPos; + UInt32 lenLimit = p->matchMaxLen; if (lenLimit >= p->hashNumAvail) lenLimit = p->hashNumAvail; { @@ -384,10 +657,18 @@ static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) size = size2; } + if (pos > (UInt32)kMtMaxValForNormalize - size) + { + const UInt32 subValue = (pos - p->cyclicBufferSize); // & ~(UInt32)(kNormalizeAlign - 1); + pos -= subValue; + p->pos = pos; + MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2); + } + #ifndef MFMT_GM_INLINE while (curPos < limit && size-- != 0) { - UInt32 *startDistances = distances + curPos; + UInt32 *startDistances = d + 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); @@ -399,81 +680,112 @@ static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) } #else { - UInt32 posRes; - curPos = (UInt32)(GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, - distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, - distances + limit, - size, &posRes) - distances); - p->hashBufPos += posRes - pos; - cyclicBufferPos += posRes - pos; - p->buffer += posRes - pos; - pos = posRes; + UInt32 posRes = pos; + const UInt32 *d_end; + { + d_end = GetMatchesSpecN_2( + p->buffer + lenLimit - 1, + pos, p->buffer, p->son, p->cutValue, d + curPos, + p->numHashBytes - 1, p->hashBuf + p->hashBufPos, + d + limit, p->hashBuf + p->hashBufPos + size, + cyclicBufferPos, p->cyclicBufferSize, + &posRes); + } + { + if (!d_end) + { + // printf("\n == 2 BtGetMatches() p->failure_BT\n"); + // internal data failure + p->failure_BT = True; + d[0] = 0; + // d[1] = 0; + return; + } + } + curPos = (UInt32)(d_end - d); + { + const UInt32 processed = posRes - pos; + pos = posRes; + p->hashBufPos += processed; + cyclicBufferPos += processed; + p->buffer += processed; + } } #endif - numProcessed += pos - p->pos; - p->hashNumAvail -= pos - p->pos; - p->pos = pos; + { + const UInt32 processed = pos - p->pos; + numProcessed += processed; + p->hashNumAvail -= processed; + p->pos = pos; + } if (cyclicBufferPos == p->cyclicBufferSize) cyclicBufferPos = 0; p->cyclicBufferPos = cyclicBufferPos; } } - distances[0] = curPos; + d[0] = curPos; } + static void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) { CMtSync *sync = &p->hashSync; + + BUFFER_MUST_BE_UNLOCKED(sync) + if (!sync->needStart) { - CriticalSection_Enter(&sync->cs); - sync->csWasEntered = True; + LOCK_BUFFER(sync) } - BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); + BtGetMatches(p, p->btBuf + GET_BT_BLOCK_OFFSET(globalBlockIndex)); + + /* We suppose that we have called GetNextBlock() from start. + So buffer is LOCKED */ - if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) - { - UInt32 subValue = p->pos - p->cyclicBufferSize; - MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2); - p->pos -= subValue; - } - - if (!sync->needStart) - { - CriticalSection_Leave(&sync->cs); - sync->csWasEntered = False; - } + UNLOCK_BUFFER(sync) } -void BtThreadFunc(CMatchFinderMt *mt) + +MY_NO_INLINE +static void BtThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->btSync; for (;;) { UInt32 blockIndex = 0; Event_Wait(&p->canStart); - Event_Set(&p->wasStarted); + for (;;) { + PRF(printf(" BT thread block = %d pos = %d\n", (unsigned)blockIndex, mt->pos)); + /* (p->exit == true) is possible after (p->canStart) at first loop iteration + and is unexpected after more Wait(freeSemaphore) iterations */ if (p->exit) return; - if (p->stopWriting) - { - p->numProcessedBlocks = blockIndex; - MtSync_StopWriting(&mt->hashSync); - Event_Set(&p->wasStopped); - break; - } + Semaphore_Wait(&p->freeSemaphore); + + // for faster stop : we check (p->stopWriting) after Wait(freeSemaphore) + if (p->stopWriting) + break; + BtFillBlock(mt, blockIndex++); + Semaphore_Release1(&p->filledSemaphore); } + + // we stop HASH_THREAD here + MtSync_StopWriting(&mt->hashSync); + + // p->numBlocks_Sent = blockIndex; + Event_Set(&p->wasStopped); } } + void MatchFinderMt_Construct(CMatchFinderMt *p) { p->hashBuf = NULL; @@ -489,16 +801,39 @@ static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAllocPtr alloc) void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc) { - MtSync_Destruct(&p->hashSync); + /* + HASH_THREAD can use CriticalSection(s) btSync.cs and hashSync.cs. + So we must be sure that HASH_THREAD will not use CriticalSection(s) + after deleting CriticalSection here. + + we call ReleaseStream(p) + that calls StopWriting(btSync) + that calls StopWriting(hashSync), if it's required to stop HASH_THREAD. + after StopWriting() it's safe to destruct MtSync(s) in any order */ + + MatchFinderMt_ReleaseStream(p); + MtSync_Destruct(&p->btSync); + MtSync_Destruct(&p->hashSync); + + LOG_ITER( + printf("\nTree %9d * %7d iter = %9d = sum : bytes = %9d\n", + (UInt32)(g_NumIters_Tree / 1000), + (UInt32)(((UInt64)g_NumIters_Loop * 1000) / (g_NumIters_Tree + 1)), + (UInt32)(g_NumIters_Loop / 1000), + (UInt32)(g_NumIters_Bytes / 1000) + )); + MatchFinderMt_FreeMem(p, alloc); } + #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) -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) + +static THREAD_FUNC_DECL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } +static THREAD_FUNC_DECL BtThreadFunc2(void *p) { Byte allocaDummy[0x180]; unsigned i = 0; @@ -509,16 +844,17 @@ static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p) return 0; } + SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc) { - CMatchFinder *mf = p->MatchFinder; + CMatchFinder *mf = MF(p); p->historySize = historySize; if (kMtBtBlockSize <= matchMaxLen * 4) return SZ_ERROR_PARAM; if (!p->hashBuf) { - p->hashBuf = (UInt32 *)ISzAlloc_Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); + p->hashBuf = (UInt32 *)ISzAlloc_Alloc(alloc, ((size_t)kHashBufferSize + (size_t)kBtBufferSize) * sizeof(UInt32)); if (!p->hashBuf) return SZ_ERROR_MEM; p->btBuf = p->hashBuf + kHashBufferSize; @@ -528,253 +864,457 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) return SZ_ERROR_MEM; - RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks)); - RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); + RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p)); + RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p)); return SZ_OK; } -/* Call it after ReleaseStream / SetStream */ + +SRes MatchFinderMt_InitMt(CMatchFinderMt *p) +{ + RINOK(MtSync_Init(&p->hashSync, kMtHashNumBlocks)); + return MtSync_Init(&p->btSync, kMtBtNumBlocks); +} + + static void MatchFinderMt_Init(CMatchFinderMt *p) { - CMatchFinder *mf = p->MatchFinder; + CMatchFinder *mf = MF(p); p->btBufPos = - p->btBufPosLimit = 0; + p->btBufPosLimit = NULL; p->hashBufPos = p->hashBufPosLimit = 0; + p->hashNumAvail = 0; // 21.03 + + p->failure_BT = False; /* Init without data reading. We don't want to read data in this thread */ - MatchFinder_Init_3(mf, False); + MatchFinder_Init_4(mf); + MatchFinder_Init_LowHash(mf); p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf); p->btNumAvailBytes = 0; - p->lzPos = p->historySize + 1; + p->failure_LZ_BT = False; + // p->failure_LZ_LZ = False; + + p->lzPos = + 1; // optimal smallest value + // 0; // for debug: ignores match to start + // kNormalizeAlign; // for debug p->hash = mf->hash; p->fixedHashSize = mf->fixedHashSize; + // p->hash4Mask = mf->hash4Mask; p->crc = mf->crc; + // memcpy(p->crc, mf->crc, sizeof(mf->crc)); p->son = mf->son; p->matchMaxLen = mf->matchMaxLen; p->numHashBytes = mf->numHashBytes; - p->pos = mf->pos; - p->buffer = mf->buffer; - p->cyclicBufferPos = mf->cyclicBufferPos; + + /* (mf->pos) and (mf->streamPos) were already initialized to 1 in MatchFinder_Init_4() */ + // mf->streamPos = mf->pos = 1; // optimal smallest value + // 0; // for debug: ignores match to start + // kNormalizeAlign; // for debug + + /* we must init (p->pos = mf->pos) for BT, because + BT code needs (p->pos == delta_value_for_empty_hash_record == mf->pos) */ + p->pos = mf->pos; // do not change it + + p->cyclicBufferPos = (p->pos - CYC_TO_POS_OFFSET); p->cyclicBufferSize = mf->cyclicBufferSize; + p->buffer = mf->buffer; p->cutValue = mf->cutValue; + // p->son[0] = p->son[1] = 0; // unused: to init skipped record for speculated accesses. } + /* ReleaseStream is required to finish multithreading */ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) { + // Sleep(1); // for debug MtSync_StopWriting(&p->btSync); + // Sleep(200); // for debug /* p->MatchFinder->ReleaseStream(); */ } -static void MatchFinderMt_Normalize(CMatchFinderMt *p) + +MY_NO_INLINE +static UInt32 MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) { - MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); - p->lzPos = p->historySize + 1; + if (p->failure_LZ_BT) + p->btBufPos = p->failureBuf; + else + { + const UInt32 bi = MtSync_GetNextBlock(&p->btSync); + const UInt32 *bt = p->btBuf + GET_BT_BLOCK_OFFSET(bi); + { + const UInt32 numItems = bt[0]; + p->btBufPosLimit = bt + numItems; + p->btNumAvailBytes = bt[1]; + p->btBufPos = bt + 2; + if (numItems < 2 || numItems > kMtBtBlockSize) + { + p->failureBuf[0] = 0; + p->btBufPos = p->failureBuf; + p->btBufPosLimit = p->failureBuf + 1; + p->failure_LZ_BT = True; + // p->btNumAvailBytes = 0; + /* we don't want to decrease AvailBytes, that was load before. + that can be unxepected for the code that have loaded anopther value before */ + } + } + + if (p->lzPos >= (UInt32)kMtMaxValForNormalize - (UInt32)kMtBtBlockSize) + { + /* we don't check (lzPos) over exact avail bytes in (btBuf). + (fixedHashSize) is small, so normalization is fast */ + const UInt32 subValue = (p->lzPos - p->historySize - 1); // & ~(UInt32)(kNormalizeAlign - 1); + p->lzPos -= subValue; + MatchFinder_Normalize3(subValue, p->hash, p->fixedHashSize); + } + } + return p->btNumAvailBytes; } -static void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) -{ - UInt32 blockIndex; - MtSync_GetNextBlock(&p->btSync); - blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); - p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; - p->btBufPosLimit += p->btBuf[p->btBufPos++]; - p->btNumAvailBytes = p->btBuf[p->btBufPos++]; - if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) - MatchFinderMt_Normalize(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); + static UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) { - GET_NEXT_BLOCK_IF_REQUIRED; - return p->btNumAvailBytes; + if (p->btBufPos != p->btBufPosLimit) + return p->btNumAvailBytes; + return MatchFinderMt_GetNextBlock_Bt(p); } -static UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) + +// #define CHECK_FAILURE_LZ(_match_, _pos_) if (_match_ >= _pos_) { p->failure_LZ_LZ = True; return d; } +#define CHECK_FAILURE_LZ(_match_, _pos_) + +static UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) { - UInt32 h2, curMatch2; + UInt32 h2, c2; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; - UInt32 lzPos = p->lzPos; + const UInt32 m = p->lzPos; MT_HASH2_CALC - curMatch2 = hash[h2]; - hash[h2] = lzPos; + c2 = hash[h2]; + hash[h2] = m; - if (curMatch2 >= matchMinPos) - if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + if (c2 >= matchMinPos) + { + CHECK_FAILURE_LZ(c2, m) + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) { - *distances++ = 2; - *distances++ = lzPos - curMatch2 - 1; + *d++ = 2; + *d++ = m - c2 - 1; } + } - return distances; + return d; } -static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) { - UInt32 h2, h3, curMatch2, curMatch3; + UInt32 h2, h3, c2, c3; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; - UInt32 lzPos = p->lzPos; + const UInt32 m = p->lzPos; MT_HASH3_CALC - curMatch2 = hash[ h2]; - curMatch3 = (hash + kFix3HashSize)[h3]; + c2 = hash[h2]; + c3 = (hash + kFix3HashSize)[h3]; - hash[ h2] = lzPos; - (hash + kFix3HashSize)[h3] = lzPos; + hash[h2] = m; + (hash + kFix3HashSize)[h3] = m; - if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + if (c2 >= matchMinPos) { - distances[1] = lzPos - curMatch2 - 1; - if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) + CHECK_FAILURE_LZ(c2, m) + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) { - distances[0] = 3; - return distances + 2; + d[1] = m - c2 - 1; + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2]) + { + d[0] = 3; + return d + 2; + } + d[0] = 2; + d += 2; } - distances[0] = 2; - distances += 2; } - if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) + if (c3 >= matchMinPos) { - *distances++ = 3; - *distances++ = lzPos - curMatch3 - 1; + CHECK_FAILURE_LZ(c3, m) + if (cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0]) + { + *d++ = 3; + *d++ = m - c3 - 1; + } } - return distances; + return d; } -/* -static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) -{ - 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[ h2]; - curMatch3 = (hash + kFix3HashSize)[h3]; - curMatch4 = (hash + kFix4HashSize)[h4]; - - 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; - return distances + 2; - } - distances[0] = 2; - distances += 2; - } - - if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) - { - distances[1] = lzPos - curMatch3 - 1; - if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) - { - distances[0] = 4; - return distances + 2; - } - distances[0] = 3; - distances += 2; - } - - if (curMatch4 >= matchMinPos) - if ( - cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && - cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] - ) - { - *distances++ = 4; - *distances++ = lzPos - curMatch4 - 1; - } - - return distances; -} -*/ #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; -static UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) +/* +static +UInt32* MatchFinderMt_GetMatches_Bt4(CMatchFinderMt *p, UInt32 *d) { - const UInt32 *btBuf = p->btBuf + p->btBufPos; - UInt32 len = *btBuf++; - p->btBufPos += 1 + len; - p->btNumAvailBytes--; + const UInt32 *bt = p->btBufPos; + const UInt32 len = *bt++; + const UInt32 *btLim = bt + len; + UInt32 matchMinPos; + UInt32 avail = p->btNumAvailBytes - 1; + p->btBufPos = btLim; + { - UInt32 i; - for (i = 0; i < len; i += 2) + p->btNumAvailBytes = avail; + + #define BT_HASH_BYTES_MAX 5 + + matchMinPos = p->lzPos; + + if (len != 0) + matchMinPos -= bt[1]; + else if (avail < (BT_HASH_BYTES_MAX - 1) - 1) { - UInt32 v0 = btBuf[0]; - UInt32 v1 = btBuf[1]; - btBuf += 2; - distances[0] = v0; - distances[1] = v1; - distances += 2; + INCREASE_LZ_POS + return d; + } + else + { + const UInt32 hs = p->historySize; + if (matchMinPos > hs) + matchMinPos -= hs; + else + matchMinPos = 1; } } + + for (;;) + { + + UInt32 h2, h3, c2, c3; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 m = p->lzPos; + MT_HASH3_CALC + + c2 = hash[h2]; + c3 = (hash + kFix3HashSize)[h3]; + + hash[h2] = m; + (hash + kFix3HashSize)[h3] = m; + + if (c2 >= matchMinPos && cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) + { + d[1] = m - c2 - 1; + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2]) + { + d[0] = 3; + d += 2; + break; + } + // else + { + d[0] = 2; + d += 2; + } + } + if (c3 >= matchMinPos && cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0]) + { + *d++ = 3; + *d++ = m - c3 - 1; + } + break; + } + + if (len != 0) + { + do + { + const UInt32 v0 = bt[0]; + const UInt32 v1 = bt[1]; + bt += 2; + d[0] = v0; + d[1] = v1; + d += 2; + } + while (bt != btLim); + } INCREASE_LZ_POS - return len; + return d; +} +*/ + + +static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) +{ + UInt32 h2, h3, /* h4, */ c2, c3 /* , c4 */; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + const UInt32 m = p->lzPos; + MT_HASH3_CALC + // MT_HASH4_CALC + c2 = hash[h2]; + c3 = (hash + kFix3HashSize)[h3]; + // c4 = (hash + kFix4HashSize)[h4]; + + hash[h2] = m; + (hash + kFix3HashSize)[h3] = m; + // (hash + kFix4HashSize)[h4] = m; + + #define _USE_H2 + + #ifdef _USE_H2 + if (c2 >= matchMinPos && cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) + { + d[1] = m - c2 - 1; + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2]) + { + // d[0] = (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 3] == cur[3]) ? 4 : 3; + // return d + 2; + + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 3] == cur[3]) + { + d[0] = 4; + return d + 2; + } + d[0] = 3; + d += 2; + + #ifdef _USE_H4 + if (c4 >= matchMinPos) + if ( + cur[(ptrdiff_t)c4 - (ptrdiff_t)m] == cur[0] && + cur[(ptrdiff_t)c4 - (ptrdiff_t)m + 3] == cur[3] + ) + { + *d++ = 4; + *d++ = m - c4 - 1; + } + #endif + return d; + } + d[0] = 2; + d += 2; + } + #endif + + if (c3 >= matchMinPos && cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0]) + { + d[1] = m - c3 - 1; + if (cur[(ptrdiff_t)c3 - (ptrdiff_t)m + 3] == cur[3]) + { + d[0] = 4; + return d + 2; + } + d[0] = 3; + d += 2; + } + + #ifdef _USE_H4 + if (c4 >= matchMinPos) + if ( + cur[(ptrdiff_t)c4 - (ptrdiff_t)m] == cur[0] && + cur[(ptrdiff_t)c4 - (ptrdiff_t)m + 3] == cur[3] + ) + { + *d++ = 4; + *d++ = m - c4 - 1; + } + #endif + + return d; } -static UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) -{ - const UInt32 *btBuf = p->btBuf + p->btBufPos; - UInt32 len = *btBuf++; - p->btBufPos += 1 + len; +static UInt32* MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *d) +{ + const UInt32 *bt = p->btBufPos; + const UInt32 len = *bt++; + const UInt32 *btLim = bt + len; + p->btBufPos = btLim; + p->btNumAvailBytes--; + INCREASE_LZ_POS + { + while (bt != btLim) + { + const UInt32 v0 = bt[0]; + const UInt32 v1 = bt[1]; + bt += 2; + d[0] = v0; + d[1] = v1; + d += 2; + } + } + return d; +} + + + +static UInt32* MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *d) +{ + const UInt32 *bt = p->btBufPos; + UInt32 len = *bt++; + const UInt32 avail = p->btNumAvailBytes - 1; + p->btNumAvailBytes = avail; + p->btBufPos = bt + len; if (len == 0) { - /* change for bt5 ! */ - if (p->btNumAvailBytes-- >= 4) - len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); + #define BT_HASH_BYTES_MAX 5 + if (avail >= (BT_HASH_BYTES_MAX - 1) - 1) + { + UInt32 m = p->lzPos; + if (m > p->historySize) + m -= p->historySize; + else + m = 1; + d = p->MixMatchesFunc(p, m, d); + } } else { - /* Condition: there are matches in btBuf with length < p->numHashBytes */ - UInt32 *distances2; - p->btNumAvailBytes--; - distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); + /* + first match pair from BinTree: (match_len, match_dist), + (match_len >= numHashBytes). + MixMatchesFunc() inserts only hash matches that are nearer than (match_dist) + */ + d = p->MixMatchesFunc(p, p->lzPos - bt[1], d); + // if (d) // check for failure do { - UInt32 v0 = btBuf[0]; - UInt32 v1 = btBuf[1]; - btBuf += 2; - distances2[0] = v0; - distances2[1] = v1; - distances2 += 2; + const UInt32 v0 = bt[0]; + const UInt32 v1 = bt[1]; + bt += 2; + d[0] = v0; + d[1] = v1; + d += 2; } - while ((len -= 2) != 0); - len = (UInt32)(distances2 - (distances)); + while (len -= 2); } INCREASE_LZ_POS - return len; + return d; } #define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED #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); +#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += (size_t)*p->btBufPos + 1; } while (--num != 0); static void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) { @@ -803,12 +1343,16 @@ static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) } /* +// MatchFinderMt4_Skip() is similar to MatchFinderMt3_Skip(). +// The difference is that MatchFinderMt3_Skip() updates hash for last 3 bytes of stream. + static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER_MT(4) - UInt32 h2, h3, h4; - MT_HASH4_CALC - (hash + kFix4HashSize)[h4] = + UInt32 h2, h3; // h4 + MT_HASH3_CALC + // MT_HASH4_CALC + // (hash + kFix4HashSize)[h4] = (hash + kFix3HashSize)[h3] = hash[ h2] = p->lzPos; @@ -816,14 +1360,14 @@ static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) } */ -void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable) { vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; 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 (MF(p)->numHashBytes) { case 2: p->GetHeadsFunc = GetHeads2; @@ -832,22 +1376,25 @@ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; break; case 3: - p->GetHeadsFunc = GetHeads3; + p->GetHeadsFunc = MF(p)->bigHash ? GetHeads3b : GetHeads3; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; break; - default: - /* case 4: */ - p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; + case 4: + p->GetHeadsFunc = MF(p)->bigHash ? GetHeads4b : GetHeads4; + + // it's fast inline version of GetMatches() + // vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches_Bt4; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; break; - /* default: - p->GetHeadsFunc = GetHeads5; + p->GetHeadsFunc = MF(p)->bigHash ? GetHeads5b : GetHeads5; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; - vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; + vTable->Skip = + (Mf_Skip_Func)MatchFinderMt3_Skip; + // (Mf_Skip_Func)MatchFinderMt4_Skip; break; - */ } } diff --git a/libraries/lzma/C/LzFindMt.h b/libraries/lzma/C/LzFindMt.h index ef431e3f5..660b7244d 100644 --- a/libraries/lzma/C/LzFindMt.h +++ b/libraries/lzma/C/LzFindMt.h @@ -1,5 +1,5 @@ /* LzFindMt.h -- multithreaded Match finder for LZ algorithms -2018-07-04 : Igor Pavlov : Public domain */ +2021-07-12 : Igor Pavlov : Public domain */ #ifndef __LZ_FIND_MT_H #define __LZ_FIND_MT_H @@ -9,31 +9,26 @@ EXTERN_C_BEGIN -#define kMtHashBlockSize (1 << 13) -#define kMtHashNumBlocks (1 << 3) -#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) - -#define kMtBtBlockSize (1 << 14) -#define kMtBtNumBlocks (1 << 6) -#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) - typedef struct _CMtSync { + UInt32 numProcessedBlocks; + CThread thread; + UInt64 affinity; + BoolInt wasCreated; BoolInt needStart; + BoolInt csWasInitialized; + BoolInt csWasEntered; + BoolInt exit; BoolInt stopWriting; - CThread thread; CAutoResetEvent canStart; - CAutoResetEvent wasStarted; CAutoResetEvent wasStopped; CSemaphore freeSemaphore; CSemaphore filledSemaphore; - BoolInt csWasInitialized; - BoolInt csWasEntered; CCriticalSection cs; - UInt32 numProcessedBlocks; + // UInt32 numBlocks_Sent; } CMtSync; typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); @@ -49,18 +44,23 @@ typedef struct _CMatchFinderMt /* LZ */ const Byte *pointerToCurPos; UInt32 *btBuf; - UInt32 btBufPos; - UInt32 btBufPosLimit; + const UInt32 *btBufPos; + const UInt32 *btBufPosLimit; UInt32 lzPos; UInt32 btNumAvailBytes; UInt32 *hash; UInt32 fixedHashSize; + // UInt32 hash4Mask; UInt32 historySize; const UInt32 *crc; Mf_Mix_Matches MixMatchesFunc; - + UInt32 failure_LZ_BT; // failure in BT transfered to LZ + // UInt32 failure_LZ_LZ; // failure in LZ tables + UInt32 failureBuf[1]; + // UInt32 crc[256]; + /* LZ + BT */ CMtSync btSync; Byte btDummy[kMtCacheLineDummy]; @@ -70,6 +70,8 @@ typedef struct _CMatchFinderMt UInt32 hashBufPos; UInt32 hashBufPosLimit; UInt32 hashNumAvail; + UInt32 failure_BT; + CLzRef *son; UInt32 matchMaxLen; @@ -77,7 +79,7 @@ typedef struct _CMatchFinderMt UInt32 pos; const Byte *buffer; UInt32 cyclicBufferPos; - UInt32 cyclicBufferSize; /* it must be historySize + 1 */ + UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 cutValue; /* BT + Hash */ @@ -87,13 +89,19 @@ typedef struct _CMatchFinderMt /* Hash */ Mf_GetHeads GetHeadsFunc; CMatchFinder *MatchFinder; + // CMatchFinder MatchFinder; } CMatchFinderMt; +// only for Mt part void MatchFinderMt_Construct(CMatchFinderMt *p); void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc); + SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc); -void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable); + +/* call MatchFinderMt_InitMt() before IMatchFinder::Init() */ +SRes MatchFinderMt_InitMt(CMatchFinderMt *p); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); EXTERN_C_END diff --git a/libraries/lzma/C/LzFindOpt.c b/libraries/lzma/C/LzFindOpt.c new file mode 100644 index 000000000..8ff006e07 --- /dev/null +++ b/libraries/lzma/C/LzFindOpt.c @@ -0,0 +1,578 @@ +/* LzFindOpt.c -- multithreaded Match finder for LZ algorithms +2021-07-13 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" +#include "LzFind.h" + +// #include "LzFindMt.h" + +// #define LOG_ITERS + +// #define LOG_THREAD + +#ifdef LOG_THREAD +#include +#define PRF(x) x +#else +// #define PRF(x) +#endif + +#ifdef LOG_ITERS +#include +UInt64 g_NumIters_Tree; +UInt64 g_NumIters_Loop; +UInt64 g_NumIters_Bytes; +#define LOG_ITER(x) x +#else +#define LOG_ITER(x) +#endif + +// ---------- BT THREAD ---------- + +#define USE_SON_PREFETCH +#define USE_LONG_MATCH_OPT + +#define kEmptyHashValue 0 + +// #define CYC_TO_POS_OFFSET 0 + +// #define CYC_TO_POS_OFFSET 1 // for debug + +/* +MY_NO_INLINE +UInt32 * MY_FAST_CALL GetMatchesSpecN_1(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, + UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, UInt32 *posRes) +{ + do + { + UInt32 delta; + if (hash == size) + break; + delta = *hash++; + + if (delta == 0 || delta > (UInt32)pos) + return NULL; + + lenLimit++; + + if (delta == (UInt32)pos) + { + CLzRef *ptr1 = son + ((size_t)pos << 1) - CYC_TO_POS_OFFSET * 2; + *d++ = 0; + ptr1[0] = kEmptyHashValue; + ptr1[1] = kEmptyHashValue; + } +else +{ + UInt32 *_distances = ++d; + + CLzRef *ptr0 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2 + 1; + CLzRef *ptr1 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2; + + const Byte *len0 = cur, *len1 = cur; + UInt32 cutValue = _cutValue; + const Byte *maxLen = cur + _maxLen; + + for (LOG_ITER(g_NumIters_Tree++);;) + { + LOG_ITER(g_NumIters_Loop++); + { + const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta; + CLzRef *pair = son + ((size_t)(((ptrdiff_t)pos - CYC_TO_POS_OFFSET) + diff) << 1); + const Byte *len = (len0 < len1 ? len0 : len1); + + #ifdef USE_SON_PREFETCH + const UInt32 pair0 = *pair; + #endif + + if (len[diff] == len[0]) + { + if (++len != lenLimit && len[diff] == len[0]) + while (++len != lenLimit) + { + LOG_ITER(g_NumIters_Bytes++); + if (len[diff] != len[0]) + break; + } + if (maxLen < len) + { + maxLen = len; + *d++ = (UInt32)(len - cur); + *d++ = delta - 1; + + if (len == lenLimit) + { + const UInt32 pair1 = pair[1]; + *ptr1 = + #ifdef USE_SON_PREFETCH + pair0; + #else + pair[0]; + #endif + *ptr0 = pair1; + + _distances[-1] = (UInt32)(d - _distances); + + #ifdef USE_LONG_MATCH_OPT + + if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) + break; + + { + for (;;) + { + hash++; + pos++; + cur++; + lenLimit++; + { + CLzRef *ptr = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2; + #if 0 + *(UInt64 *)(void *)ptr = ((const UInt64 *)(const void *)ptr)[diff]; + #else + const UInt32 p0 = ptr[0 + (diff * 2)]; + const UInt32 p1 = ptr[1 + (diff * 2)]; + ptr[0] = p0; + ptr[1] = p1; + // ptr[0] = ptr[0 + (diff * 2)]; + // ptr[1] = ptr[1 + (diff * 2)]; + #endif + } + // PrintSon(son + 2, pos - 1); + // printf("\npos = %x delta = %x\n", pos, delta); + len++; + *d++ = 2; + *d++ = (UInt32)(len - cur); + *d++ = delta - 1; + if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) + break; + } + } + #endif + + break; + } + } + } + + { + const UInt32 curMatch = (UInt32)pos - delta; // (UInt32)(pos + diff); + if (len[diff] < len[0]) + { + delta = pair[1]; + if (delta >= curMatch) + return NULL; + *ptr1 = curMatch; + ptr1 = pair + 1; + len1 = len; + } + else + { + delta = *pair; + if (delta >= curMatch) + return NULL; + *ptr0 = curMatch; + ptr0 = pair; + len0 = len; + } + + delta = (UInt32)pos - delta; + + if (--cutValue == 0 || delta >= pos) + { + *ptr0 = *ptr1 = kEmptyHashValue; + _distances[-1] = (UInt32)(d - _distances); + break; + } + } + } + } // for (tree iterations) +} + pos++; + cur++; + } + while (d < limit); + *posRes = (UInt32)pos; + return d; +} +*/ + +/* define cbs if you use 2 functions. + GetMatchesSpecN_1() : (pos < _cyclicBufferSize) + GetMatchesSpecN_2() : (pos >= _cyclicBufferSize) + + do not define cbs if you use 1 function: + GetMatchesSpecN_2() +*/ + +// #define cbs _cyclicBufferSize + +/* + we use size_t for (pos) and (_cyclicBufferPos_ instead of UInt32 + to eliminate "movsx" BUG in old MSVC x64 compiler. +*/ + +UInt32 * MY_FAST_CALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, + UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, + UInt32 *posRes); + +MY_NO_INLINE +UInt32 * MY_FAST_CALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, + UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, + UInt32 *posRes) +{ + do // while (hash != size) + { + UInt32 delta; + + #ifndef cbs + UInt32 cbs; + #endif + + if (hash == size) + break; + + delta = *hash++; + + if (delta == 0) + return NULL; + + lenLimit++; + + #ifndef cbs + cbs = _cyclicBufferSize; + if ((UInt32)pos < cbs) + { + if (delta > (UInt32)pos) + return NULL; + cbs = (UInt32)pos; + } + #endif + + if (delta >= cbs) + { + CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); + *d++ = 0; + ptr1[0] = kEmptyHashValue; + ptr1[1] = kEmptyHashValue; + } +else +{ + UInt32 *_distances = ++d; + + CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); + + UInt32 cutValue = _cutValue; + const Byte *len0 = cur, *len1 = cur; + const Byte *maxLen = cur + _maxLen; + + // if (cutValue == 0) { *ptr0 = *ptr1 = kEmptyHashValue; } else + for (LOG_ITER(g_NumIters_Tree++);;) + { + LOG_ITER(g_NumIters_Loop++); + { + // SPEC code + CLzRef *pair = son + ((size_t)((ptrdiff_t)_cyclicBufferPos - (ptrdiff_t)delta + + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0) + ) << 1); + + const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta; + const Byte *len = (len0 < len1 ? len0 : len1); + + #ifdef USE_SON_PREFETCH + const UInt32 pair0 = *pair; + #endif + + if (len[diff] == len[0]) + { + if (++len != lenLimit && len[diff] == len[0]) + while (++len != lenLimit) + { + LOG_ITER(g_NumIters_Bytes++); + if (len[diff] != len[0]) + break; + } + if (maxLen < len) + { + maxLen = len; + *d++ = (UInt32)(len - cur); + *d++ = delta - 1; + + if (len == lenLimit) + { + const UInt32 pair1 = pair[1]; + *ptr1 = + #ifdef USE_SON_PREFETCH + pair0; + #else + pair[0]; + #endif + *ptr0 = pair1; + + _distances[-1] = (UInt32)(d - _distances); + + #ifdef USE_LONG_MATCH_OPT + + if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) + break; + + { + for (;;) + { + *d++ = 2; + *d++ = (UInt32)(lenLimit - cur); + *d++ = delta - 1; + cur++; + lenLimit++; + // SPEC + _cyclicBufferPos++; + { + // SPEC code + CLzRef *dest = son + ((size_t)(_cyclicBufferPos) << 1); + const CLzRef *src = dest + ((diff + + (ptrdiff_t)(UInt32)((_cyclicBufferPos < delta) ? cbs : 0)) << 1); + // CLzRef *ptr = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2; + #if 0 + *(UInt64 *)(void *)dest = *((const UInt64 *)(const void *)src); + #else + const UInt32 p0 = src[0]; + const UInt32 p1 = src[1]; + dest[0] = p0; + dest[1] = p1; + #endif + } + pos++; + hash++; + if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) + break; + } // for() end for long matches + } + #endif + + break; // break from TREE iterations + } + } + } + { + const UInt32 curMatch = (UInt32)pos - delta; // (UInt32)(pos + diff); + if (len[diff] < len[0]) + { + delta = pair[1]; + *ptr1 = curMatch; + ptr1 = pair + 1; + len1 = len; + if (delta >= curMatch) + return NULL; + } + else + { + delta = *pair; + *ptr0 = curMatch; + ptr0 = pair; + len0 = len; + if (delta >= curMatch) + return NULL; + } + delta = (UInt32)pos - delta; + + if (--cutValue == 0 || delta >= cbs) + { + *ptr0 = *ptr1 = kEmptyHashValue; + _distances[-1] = (UInt32)(d - _distances); + break; + } + } + } + } // for (tree iterations) +} + pos++; + _cyclicBufferPos++; + cur++; + } + while (d < limit); + *posRes = (UInt32)pos; + return d; +} + + + +/* +typedef UInt32 uint32plus; // size_t + +UInt32 * MY_FAST_CALL GetMatchesSpecN_3(uint32plus lenLimit, size_t pos, const Byte *cur, CLzRef *son, + UInt32 _cutValue, UInt32 *d, uint32plus _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, + UInt32 *posRes) +{ + do // while (hash != size) + { + UInt32 delta; + + #ifndef cbs + UInt32 cbs; + #endif + + if (hash == size) + break; + + delta = *hash++; + + if (delta == 0) + return NULL; + + #ifndef cbs + cbs = _cyclicBufferSize; + if ((UInt32)pos < cbs) + { + if (delta > (UInt32)pos) + return NULL; + cbs = (UInt32)pos; + } + #endif + + if (delta >= cbs) + { + CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); + *d++ = 0; + ptr1[0] = kEmptyHashValue; + ptr1[1] = kEmptyHashValue; + } +else +{ + CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); + UInt32 *_distances = ++d; + uint32plus len0 = 0, len1 = 0; + UInt32 cutValue = _cutValue; + uint32plus maxLen = _maxLen; + // lenLimit++; // const Byte *lenLimit = cur + _lenLimit; + + for (LOG_ITER(g_NumIters_Tree++);;) + { + LOG_ITER(g_NumIters_Loop++); + { + // const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta; + CLzRef *pair = son + ((size_t)((ptrdiff_t)_cyclicBufferPos - delta + + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0) + ) << 1); + const Byte *pb = cur - delta; + uint32plus len = (len0 < len1 ? len0 : len1); + + #ifdef USE_SON_PREFETCH + const UInt32 pair0 = *pair; + #endif + + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + maxLen = len; + *d++ = (UInt32)len; + *d++ = delta - 1; + if (len == lenLimit) + { + { + const UInt32 pair1 = pair[1]; + *ptr0 = pair1; + *ptr1 = + #ifdef USE_SON_PREFETCH + pair0; + #else + pair[0]; + #endif + } + + _distances[-1] = (UInt32)(d - _distances); + + #ifdef USE_LONG_MATCH_OPT + + if (hash == size || *hash != delta || pb[lenLimit] != cur[lenLimit] || d >= limit) + break; + + { + const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta; + for (;;) + { + *d++ = 2; + *d++ = (UInt32)lenLimit; + *d++ = delta - 1; + _cyclicBufferPos++; + { + CLzRef *dest = son + ((size_t)_cyclicBufferPos << 1); + const CLzRef *src = dest + ((diff + + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0)) << 1); + #if 0 + *(UInt64 *)(void *)dest = *((const UInt64 *)(const void *)src); + #else + const UInt32 p0 = src[0]; + const UInt32 p1 = src[1]; + dest[0] = p0; + dest[1] = p1; + #endif + } + hash++; + pos++; + cur++; + pb++; + if (hash == size || *hash != delta || pb[lenLimit] != cur[lenLimit] || d >= limit) + break; + } + } + #endif + + break; + } + } + } + { + const UInt32 curMatch = (UInt32)pos - delta; + if (pb[len] < cur[len]) + { + delta = pair[1]; + *ptr1 = curMatch; + ptr1 = pair + 1; + len1 = len; + } + else + { + delta = *pair; + *ptr0 = curMatch; + ptr0 = pair; + len0 = len; + } + + { + if (delta >= curMatch) + return NULL; + delta = (UInt32)pos - delta; + if (delta >= cbs + // delta >= _cyclicBufferSize || delta >= pos + || --cutValue == 0) + { + *ptr0 = *ptr1 = kEmptyHashValue; + _distances[-1] = (UInt32)(d - _distances); + break; + } + } + } + } + } // for (tree iterations) +} + pos++; + _cyclicBufferPos++; + cur++; + } + while (d < limit); + *posRes = (UInt32)pos; + return d; +} +*/ diff --git a/libraries/lzma/C/LzHash.h b/libraries/lzma/C/LzHash.h index e7c942303..77b898cfa 100644 --- a/libraries/lzma/C/LzHash.h +++ b/libraries/lzma/C/LzHash.h @@ -1,57 +1,34 @@ /* LzHash.h -- HASH functions for LZ algorithms -2015-04-12 : Igor Pavlov : Public domain */ +2019-10-30 : Igor Pavlov : Public domain */ #ifndef __LZ_HASH_H #define __LZ_HASH_H +/* + (kHash2Size >= (1 << 8)) : Required + (kHash3Size >= (1 << 16)) : Required +*/ + #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) -#define kHash4Size (1 << 20) +// #define kHash4Size (1 << 20) #define kFix3HashSize (kHash2Size) #define kFix4HashSize (kHash2Size + kHash3Size) -#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) +// #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) -#define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8); +/* + We use up to 3 crc values for hash: + crc0 + crc1 << Shift_1 + crc2 << Shift_2 + (Shift_1 = 5) and (Shift_2 = 10) is good tradeoff. + Small values for Shift are not good for collision rate. + Big value for Shift_2 increases the minimum size + of hash table, that will be slow for small files. +*/ -#define HASH3_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - h2 = temp & (kHash2Size - 1); \ - hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } - -#define HASH4_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - 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]; \ - 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 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 \ - h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); - -#define MT_HASH3_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[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]; \ - h2 = temp & (kHash2Size - 1); \ - temp ^= ((UInt32)cur[2] << 8); \ - h3 = temp & (kHash3Size - 1); \ - h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } +#define kLzHash_CrcShift_1 5 +#define kLzHash_CrcShift_2 10 #endif diff --git a/libraries/lzma/C/Lzma2Dec.c b/libraries/lzma/C/Lzma2Dec.c index 4e138a4ae..ac970a843 100644 --- a/libraries/lzma/C/Lzma2Dec.c +++ b/libraries/lzma/C/Lzma2Dec.c @@ -1,5 +1,5 @@ /* Lzma2Dec.c -- LZMA2 Decoder -2019-02-02 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ /* #define SHOW_DEBUG_INFO */ @@ -93,7 +93,8 @@ void Lzma2Dec_Init(CLzma2Dec *p) LzmaDec_Init(&p->decoder); } -static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) +// ELzma2State +static unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) { switch (p->state) { diff --git a/libraries/lzma/C/LzmaDec.c b/libraries/lzma/C/LzmaDec.c index ba3e1dd50..d6742e5af 100644 --- a/libraries/lzma/C/LzmaDec.c +++ b/libraries/lzma/C/LzmaDec.c @@ -1,5 +1,5 @@ /* LzmaDec.c -- LZMA Decoder -2018-07-04 : Igor Pavlov : Public domain */ +2021-04-01 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -13,10 +13,12 @@ #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) -#define kNumMoveBits 5 #define RC_INIT_SIZE 5 +#ifndef _LZMA_DEC_OPT + +#define kNumMoveBits 5 #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound) @@ -62,9 +64,10 @@ probLit = prob + (offs + bit + symbol); \ GET_BIT2(probLit, symbol, offs ^= bit; , ;) +#endif // _LZMA_DEC_OPT -#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_INPUT_EOF; range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound) #define UPDATE_0_CHECK range = bound; @@ -114,6 +117,9 @@ #define kMatchMinLen 2 #define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols) +#define kMatchSpecLen_Error_Data (1 << 9) +#define kMatchSpecLen_Error_Fail (kMatchSpecLen_Error_Data - 1) + /* External ASM code needs same CLzmaProb array layout. So don't change it. */ /* (probs_1664) is faster and better for code size at some platforms */ @@ -166,10 +172,12 @@ /* p->remainLen : shows status of LZMA decoder: - < kMatchSpecLenStart : normal remain - = kMatchSpecLenStart : finished - = kMatchSpecLenStart + 1 : need init range coder - = kMatchSpecLenStart + 2 : need init range coder and state + < kMatchSpecLenStart : the number of bytes to be copied with (p->rep0) offset + = kMatchSpecLenStart : the LZMA stream was finished with end mark + = kMatchSpecLenStart + 1 : need init range coder + = kMatchSpecLenStart + 2 : need init range coder and state + = kMatchSpecLen_Error_Fail : Internal Code Failure + = kMatchSpecLen_Error_Data + [0 ... 273] : LZMA Data Error */ /* ---------- LZMA_DECODE_REAL ---------- */ @@ -188,23 +196,31 @@ In: { LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases. So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol - is not END_OF_PAYALOAD_MARKER, then function returns error code. + is not END_OF_PAYALOAD_MARKER, then the function doesn't write any byte to dictionary, + the function returns SZ_OK, and the caller can use (p->remainLen) and (p->reps[0]) later. } Processing: - first LZMA symbol will be decoded in any case - All checks for limits are at the end of main loop, - It will decode new LZMA-symbols while (p->buf < bufLimit && dicPos < limit), + The first LZMA symbol will be decoded in any case. + All main checks for limits are at the end of main loop, + It decodes additional LZMA-symbols while (p->buf < bufLimit && dicPos < limit), RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked. + But if (p->buf < bufLimit), the caller provided at least (LZMA_REQUIRED_INPUT_MAX + 1) bytes for + next iteration before limit (bufLimit + LZMA_REQUIRED_INPUT_MAX), + that is enough for worst case LZMA symbol with one additional RangeCoder normalization for one bit. + So that function never reads bufLimit [LZMA_REQUIRED_INPUT_MAX] byte. Out: RangeCoder is normalized Result: SZ_OK - OK - SZ_ERROR_DATA - Error - p->remainLen: - < kMatchSpecLenStart : normal remain - = kMatchSpecLenStart : finished + p->remainLen: + < kMatchSpecLenStart : the number of bytes to be copied with (p->reps[0]) offset + = kMatchSpecLenStart : the LZMA stream was finished with end mark + + SZ_ERROR_DATA - error, when the MATCH-Symbol refers out of dictionary + p->remainLen : undefined + p->reps[*] : undefined */ @@ -316,11 +332,6 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit else { UPDATE_1(prob); - /* - // that case was checked before with kBadRepCode - if (checkDicSize == 0 && processedPos == 0) - return SZ_ERROR_DATA; - */ prob = probs + IsRepG0 + state; IF_BIT_0(prob) { @@ -329,6 +340,13 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit IF_BIT_0(prob) { UPDATE_0(prob); + + // that case was checked before with kBadRepCode + // if (checkDicSize == 0 && processedPos == 0) { len = kMatchSpecLen_Error_Data + 1; break; } + // The caller doesn't allow (dicPos == limit) case here + // so we don't need the following check: + // if (dicPos == limit) { state = state < kNumLitStates ? 9 : 11; len = 1; break; } + dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; dicPos++; processedPos++; @@ -518,8 +536,10 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize)) { - p->dicPos = dicPos; - return SZ_ERROR_DATA; + len += kMatchSpecLen_Error_Data + kMatchMinLen; + // len = kMatchSpecLen_Error_Data; + // len += kMatchMinLen; + break; } } @@ -532,8 +552,13 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit if ((rem = limit - dicPos) == 0) { - p->dicPos = dicPos; - return SZ_ERROR_DATA; + /* + We stop decoding and return SZ_OK, and we can resume decoding later. + Any error conditions can be tested later in caller code. + For more strict mode we can stop decoding with error + // len += kMatchSpecLen_Error_Data; + */ + break; } curLen = ((rem < len) ? (unsigned)rem : len); @@ -572,7 +597,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit p->buf = buf; p->range = range; p->code = code; - p->remainLen = (UInt32)len; + p->remainLen = (UInt32)len; // & (kMatchSpecLen_Error_Data - 1); // we can write real length for error matches too. p->dicPos = dicPos; p->processedPos = processedPos; p->reps[0] = rep0; @@ -580,40 +605,61 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit p->reps[2] = rep2; p->reps[3] = rep3; p->state = (UInt32)state; - + if (len >= kMatchSpecLen_Error_Data) + return SZ_ERROR_DATA; return SZ_OK; } #endif + + static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) { - if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) + unsigned len = (unsigned)p->remainLen; + if (len == 0 /* || len >= kMatchSpecLenStart */) + return; { - Byte *dic = p->dic; SizeT dicPos = p->dicPos; - SizeT dicBufSize = p->dicBufSize; - unsigned len = (unsigned)p->remainLen; - 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); + Byte *dic; + SizeT dicBufSize; + SizeT rep0; /* we use SizeT to avoid the BUG of VC14 for AMD64 */ + { + SizeT rem = limit - dicPos; + if (rem < len) + { + len = (unsigned)(rem); + if (len == 0) + return; + } + } if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) p->checkDicSize = p->prop.dicSize; p->processedPos += (UInt32)len; p->remainLen -= (UInt32)len; - while (len != 0) + dic = p->dic; + rep0 = p->reps[0]; + dicBufSize = p->dicBufSize; + do { - len--; dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; dicPos++; } + while (--len); p->dicPos = dicPos; } } +/* +At staring of new stream we have one of the following symbols: + - Literal - is allowed + - Non-Rep-Match - is allowed only if it's end marker symbol + - Rep-Match - is not allowed +We use early check of (RangeCoder:Code) over kBadRepCode to simplify main decoding code +*/ + #define kRange0 0xFFFFFFFF #define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)) #define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))) @@ -621,69 +667,77 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) #error Stop_Compiling_Bad_LZMA_Check #endif + +/* +LzmaDec_DecodeReal2(): + It calls LZMA_DECODE_REAL() and it adjusts limit according (p->checkDicSize). + +We correct (p->checkDicSize) after LZMA_DECODE_REAL() and in LzmaDec_WriteRem(), +and we support the following state of (p->checkDicSize): + if (total_processed < p->prop.dicSize) then + { + (total_processed == p->processedPos) + (p->checkDicSize == 0) + } + else + (p->checkDicSize == p->prop.dicSize) +*/ + static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { - do + if (p->checkDicSize == 0) { - SizeT limit2 = limit; - if (p->checkDicSize == 0) - { - UInt32 rem = p->prop.dicSize - p->processedPos; - if (limit - p->dicPos > rem) - limit2 = p->dicPos + rem; - - if (p->processedPos == 0) - if (p->code >= kBadRepCode) - return SZ_ERROR_DATA; - } - - RINOK(LZMA_DECODE_REAL(p, limit2, bufLimit)); - + UInt32 rem = p->prop.dicSize - p->processedPos; + if (limit - p->dicPos > rem) + limit = p->dicPos + rem; + } + { + int res = LZMA_DECODE_REAL(p, limit, bufLimit); if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize) p->checkDicSize = p->prop.dicSize; - - LzmaDec_WriteRem(p, limit); + return res; } - while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); - - return 0; } + + typedef enum { - DUMMY_ERROR, /* unexpected end of input stream */ + DUMMY_INPUT_EOF, /* need more input data */ DUMMY_LIT, DUMMY_MATCH, DUMMY_REP } ELzmaDummy; -static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) + +#define IS_DUMMY_END_MARKER_POSSIBLE(dummyRes) ((dummyRes) == DUMMY_MATCH) + +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, const Byte **bufOut) { UInt32 range = p->range; UInt32 code = p->code; - const Byte *bufLimit = buf + inSize; + const Byte *bufLimit = *bufOut; const CLzmaProb *probs = GET_PROBS; unsigned state = (unsigned)p->state; ELzmaDummy res; + for (;;) { const CLzmaProb *prob; UInt32 bound; unsigned ttt; - unsigned posState = CALC_POS_STATE(p->processedPos, (1 << p->prop.pb) - 1); + unsigned posState = CALC_POS_STATE(p->processedPos, ((unsigned)1 << p->prop.pb) - 1); prob = probs + IsMatch + COMBINED_PS_STATE; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK - /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ - prob = probs + Literal; if (p->checkDicSize != 0 || p->processedPos != 0) 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)))); + ((((p->processedPos) & (((unsigned)1 << (p->prop.lp)) - 1)) << p->prop.lc) + + ((unsigned)p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); if (state < kNumLitStates) { @@ -735,8 +789,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; - NORMALIZE_CHECK; - return DUMMY_REP; + break; } else { @@ -812,8 +865,6 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS { unsigned numDirectBits = ((posSlot >> 1) - 1); - /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ - if (posSlot < kEndPosModelIndex) { prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits); @@ -844,12 +895,15 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS } } } + break; } NORMALIZE_CHECK; + + *bufOut = buf; return res; } - +void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState); void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState) { p->remainLen = kMatchSpecLenStart + 1; @@ -872,16 +926,41 @@ void LzmaDec_Init(CLzmaDec *p) } +/* +LZMA supports optional end_marker. +So the decoder can lookahead for one additional LZMA-Symbol to check end_marker. +That additional LZMA-Symbol can require up to LZMA_REQUIRED_INPUT_MAX bytes in input stream. +When the decoder reaches dicLimit, it looks (finishMode) parameter: + if (finishMode == LZMA_FINISH_ANY), the decoder doesn't lookahead + if (finishMode != LZMA_FINISH_ANY), the decoder lookahead, if end_marker is possible for current position + +When the decoder lookahead, and the lookahead symbol is not end_marker, we have two ways: + 1) Strict mode (default) : the decoder returns SZ_ERROR_DATA. + 2) The relaxed mode (alternative mode) : we could return SZ_OK, and the caller + must check (status) value. The caller can show the error, + if the end of stream is expected, and the (status) is noit + LZMA_STATUS_FINISHED_WITH_MARK or LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK. +*/ + + +#define RETURN__NOT_FINISHED__FOR_FINISH \ + *status = LZMA_STATUS_NOT_FINISHED; \ + return SZ_ERROR_DATA; // for strict mode + // return SZ_OK; // for relaxed mode + + SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; (*srcLen) = 0; - *status = LZMA_STATUS_NOT_SPECIFIED; if (p->remainLen > kMatchSpecLenStart) { + if (p->remainLen > kMatchSpecLenStart + 2) + return p->remainLen == kMatchSpecLen_Error_Fail ? SZ_ERROR_FAIL : SZ_ERROR_DATA; + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) p->tempBuf[p->tempBufSize++] = *src++; if (p->tempBufSize != 0 && p->tempBuf[0] != 0) @@ -896,6 +975,12 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr | ((UInt32)p->tempBuf[2] << 16) | ((UInt32)p->tempBuf[3] << 8) | ((UInt32)p->tempBuf[4]); + + if (p->checkDicSize == 0 + && p->processedPos == 0 + && p->code >= kBadRepCode) + return SZ_ERROR_DATA; + p->range = 0xFFFFFFFF; p->tempBufSize = 0; @@ -913,10 +998,21 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr p->remainLen = 0; } - LzmaDec_WriteRem(p, dicLimit); - - while (p->remainLen != kMatchSpecLenStart) + for (;;) { + if (p->remainLen == kMatchSpecLenStart) + { + if (p->code != 0) + return SZ_ERROR_DATA; + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return SZ_OK; + } + + LzmaDec_WriteRem(p, dicLimit); + + { + // (p->remainLen == 0 || p->dicPos == dicLimit) + int checkEndMarkNow = 0; if (p->dicPos >= dicLimit) @@ -933,92 +1029,174 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr } if (p->remainLen != 0) { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; + RETURN__NOT_FINISHED__FOR_FINISH; } checkEndMarkNow = 1; } + // (p->remainLen == 0) + if (p->tempBufSize == 0) { - SizeT processed; const Byte *bufLimit; + int dummyProcessed = -1; + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { - int dummyRes = LzmaDec_TryDummy(p, src, inSize); - if (dummyRes == DUMMY_ERROR) + const Byte *bufOut = src + inSize; + + ELzmaDummy dummyRes = LzmaDec_TryDummy(p, src, &bufOut); + + if (dummyRes == DUMMY_INPUT_EOF) { - memcpy(p->tempBuf, src, inSize); - p->tempBufSize = (unsigned)inSize; + size_t i; + if (inSize >= LZMA_REQUIRED_INPUT_MAX) + break; (*srcLen) += inSize; + p->tempBufSize = (unsigned)inSize; + for (i = 0; i < inSize; i++) + p->tempBuf[i] = src[i]; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } - if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + + dummyProcessed = (int)(bufOut - src); + if ((unsigned)dummyProcessed > LZMA_REQUIRED_INPUT_MAX) + break; + + if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes)) { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; + unsigned i; + (*srcLen) += (unsigned)dummyProcessed; + p->tempBufSize = (unsigned)dummyProcessed; + for (i = 0; i < (unsigned)dummyProcessed; i++) + p->tempBuf[i] = src[i]; + // p->remainLen = kMatchSpecLen_Error_Data; + RETURN__NOT_FINISHED__FOR_FINISH; } + bufLimit = src; + // we will decode only one iteration } else bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; + p->buf = src; - if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) - return SZ_ERROR_DATA; - processed = (SizeT)(p->buf - src); - (*srcLen) += processed; - src += processed; - inSize -= processed; - } - else - { - unsigned rem = p->tempBufSize, lookAhead = 0; - while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) - p->tempBuf[rem++] = src[lookAhead++]; - p->tempBufSize = rem; - if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { - int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, (SizeT)rem); - if (dummyRes == DUMMY_ERROR) + int res = LzmaDec_DecodeReal2(p, dicLimit, bufLimit); + + SizeT processed = (SizeT)(p->buf - src); + + if (dummyProcessed < 0) { - (*srcLen) += (SizeT)lookAhead; - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; + if (processed > inSize) + break; } - if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + else if ((unsigned)dummyProcessed != processed) + break; + + src += processed; + inSize -= processed; + (*srcLen) += processed; + + if (res != SZ_OK) { - *status = LZMA_STATUS_NOT_FINISHED; + p->remainLen = kMatchSpecLen_Error_Data; return SZ_ERROR_DATA; } } + continue; + } + + { + // we have some data in (p->tempBuf) + // in strict mode: tempBufSize is not enough for one Symbol decoding. + // in relaxed mode: tempBufSize not larger than required for one Symbol decoding. + + unsigned rem = p->tempBufSize; + unsigned ahead = 0; + int dummyProcessed = -1; + + while (rem < LZMA_REQUIRED_INPUT_MAX && ahead < inSize) + p->tempBuf[rem++] = src[ahead++]; + + // ahead - the size of new data copied from (src) to (p->tempBuf) + // rem - the size of temp buffer including new data from (src) + + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + const Byte *bufOut = p->tempBuf + rem; + + ELzmaDummy dummyRes = LzmaDec_TryDummy(p, p->tempBuf, &bufOut); + + if (dummyRes == DUMMY_INPUT_EOF) + { + if (rem >= LZMA_REQUIRED_INPUT_MAX) + break; + p->tempBufSize = rem; + (*srcLen) += (SizeT)ahead; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + dummyProcessed = (int)(bufOut - p->tempBuf); + + if ((unsigned)dummyProcessed < p->tempBufSize) + break; + + if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes)) + { + (*srcLen) += (unsigned)dummyProcessed - p->tempBufSize; + p->tempBufSize = (unsigned)dummyProcessed; + // p->remainLen = kMatchSpecLen_Error_Data; + RETURN__NOT_FINISHED__FOR_FINISH; + } + } + p->buf = p->tempBuf; - if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) - return SZ_ERROR_DATA; { - 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; + // we decode one symbol from (p->tempBuf) here, so the (bufLimit) is equal to (p->buf) + int res = LzmaDec_DecodeReal2(p, dicLimit, p->buf); + + SizeT processed = (SizeT)(p->buf - p->tempBuf); + rem = p->tempBufSize; + + if (dummyProcessed < 0) + { + if (processed > LZMA_REQUIRED_INPUT_MAX) + break; + if (processed < rem) + break; + } + else if ((unsigned)dummyProcessed != processed) + break; + + processed -= rem; + + src += processed; + inSize -= processed; + (*srcLen) += processed; + p->tempBufSize = 0; + + if (res != SZ_OK) + { + p->remainLen = kMatchSpecLen_Error_Data; + return SZ_ERROR_DATA; + } } - (*srcLen) += (SizeT)lookAhead; - src += lookAhead; - inSize -= (SizeT)lookAhead; - p->tempBufSize = 0; } + } } - - if (p->code != 0) - return SZ_ERROR_DATA; - *status = LZMA_STATUS_FINISHED_WITH_MARK; - return SZ_OK; + + /* Some unexpected error: internal error of code, memory corruption or hardware failure */ + p->remainLen = kMatchSpecLen_Error_Fail; + return SZ_ERROR_FAIL; } + SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT outSize = *destLen; diff --git a/libraries/lzma/C/LzmaDec.h b/libraries/lzma/C/LzmaDec.h index 1f0927ab1..6f1296250 100644 --- a/libraries/lzma/C/LzmaDec.h +++ b/libraries/lzma/C/LzmaDec.h @@ -1,5 +1,5 @@ /* LzmaDec.h -- LZMA Decoder -2018-04-21 : Igor Pavlov : Public domain */ +2020-03-19 : Igor Pavlov : Public domain */ #ifndef __LZMA_DEC_H #define __LZMA_DEC_H @@ -181,6 +181,7 @@ Returns: LZMA_STATUS_NEEDS_MORE_INPUT LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error + SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure */ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, @@ -223,6 +224,7 @@ Returns: SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure */ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, diff --git a/libraries/lzma/C/LzmaEnc.c b/libraries/lzma/C/LzmaEnc.c index 46a0db000..b04a7b7b7 100644 --- a/libraries/lzma/C/LzmaEnc.c +++ b/libraries/lzma/C/LzmaEnc.c @@ -1,5 +1,5 @@ /* LzmaEnc.c -- LZMA Encoder -2019-01-10: Igor Pavlov : Public domain */ +2021-11-18: Igor Pavlov : Public domain */ #include "Precomp.h" @@ -12,6 +12,7 @@ #include #endif +#include "CpuArch.h" #include "LzmaEnc.h" #include "LzFind.h" @@ -19,12 +20,25 @@ #include "LzFindMt.h" #endif +/* the following LzmaEnc_* declarations is internal LZMA interface for LZMA2 encoder */ + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize); +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp); +void LzmaEnc_Finish(CLzmaEncHandle pp); +void LzmaEnc_SaveState(CLzmaEncHandle pp); +void LzmaEnc_RestoreState(CLzmaEncHandle pp); + #ifdef SHOW_STAT static unsigned g_STAT_OFFSET = 0; #endif -#define kLzmaMaxHistorySize ((UInt32)3 << 29) -/* #define kLzmaMaxHistorySize ((UInt32)7 << 29) */ +/* for good normalization speed we still reserve 256 MB before 4 GB range */ +#define kLzmaMaxHistorySize ((UInt32)15 << 28) #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) @@ -36,7 +50,7 @@ static unsigned g_STAT_OFFSET = 0; #define kNumMoveReducingBits 4 #define kNumBitPriceShiftBits 4 -#define kBitPrice (1 << kNumBitPriceShiftBits) +// #define kBitPrice (1 << kNumBitPriceShiftBits) #define REP_LEN_COUNT 64 @@ -47,6 +61,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p) 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; + p->affinity = 0; } void LzmaEncProps_Normalize(CLzmaEncProps *p) @@ -55,16 +70,21 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p) if (level < 0) level = 5; p->level = level; - if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level <= 7 ? (1 << 25) : (1 << 26))); + if (p->dictSize == 0) + p->dictSize = + ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) : + ( level <= 6 ? ((UInt32)1 << (level + 19)) : + ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26) + ))); + if (p->dictSize > p->reduceSize) { - unsigned i; - UInt32 reduceSize = (UInt32)p->reduceSize; - for (i = 11; i <= 30; i++) - { - if (reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; } - if (reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; } - } + UInt32 v = (UInt32)p->reduceSize; + const UInt32 kReduceMin = ((UInt32)1 << 12); + if (v < kReduceMin) + v = kReduceMin; + if (p->dictSize > v) + p->dictSize = v; } if (p->lc < 0) p->lc = 3; @@ -74,8 +94,8 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p) 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->numHashBytes < 0) p->numHashBytes = (p->btMode ? 4 : 5); + if (p->mc == 0) p->mc = (16 + ((unsigned)p->fb >> 1)) >> (p->btMode ? 0 : 1); if (p->numThreads < 0) p->numThreads = @@ -93,18 +113,85 @@ 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 */ + +/* +x86/x64: + +BSR: + IF (SRC == 0) ZF = 1, DEST is undefined; + AMD : DEST is unchanged; + IF (SRC != 0) ZF = 0; DEST is index of top non-zero bit + BSR is slow in some processors + +LZCNT: + IF (SRC == 0) CF = 1, DEST is size_in_bits_of_register(src) (32 or 64) + IF (SRC != 0) CF = 0, DEST = num_lead_zero_bits + IF (DEST == 0) ZF = 1; + +LZCNT works only in new processors starting from Haswell. +if LZCNT is not supported by processor, then it's executed as BSR. +LZCNT can be faster than BSR, if supported. +*/ + +// #define LZMA_LOG_BSR + +#if defined(MY_CPU_ARM_OR_ARM64) /* || defined(MY_CPU_X86_OR_AMD64) */ + + #if (defined(__clang__) && (__clang_major__ >= 6)) \ + || (defined(__GNUC__) && (__GNUC__ >= 6)) + #define LZMA_LOG_BSR + #elif defined(_MSC_VER) && (_MSC_VER >= 1300) + // #if defined(MY_CPU_ARM_OR_ARM64) + #define LZMA_LOG_BSR + // #endif + #endif #endif +// #include + #ifdef LZMA_LOG_BSR -#define kDicLogSizeMaxCompress 32 +#if defined(__clang__) \ + || defined(__GNUC__) -#define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); res = (zz + zz) + ((pos >> (zz - 1)) & 1); } +/* + C code: : (30 - __builtin_clz(x)) + gcc9/gcc10 for x64 /x86 : 30 - (bsr(x) xor 31) + clang10 for x64 : 31 + (bsr(x) xor -32) +*/ -static unsigned GetPosSlot1(UInt32 pos) + #define MY_clz(x) ((unsigned)__builtin_clz(x)) + // __lzcnt32 + // __builtin_ia32_lzcnt_u32 + +#else // #if defined(_MSC_VER) + + #ifdef MY_CPU_ARM_OR_ARM64 + + #define MY_clz _CountLeadingZeros + + #else // if defined(MY_CPU_X86_OR_AMD64) + + // #define MY_clz __lzcnt // we can use lzcnt (unsupported by old CPU) + // _BitScanReverse code is not optimal for some MSVC compilers + #define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); zz--; \ + res = (zz + zz) + (pos >> zz); } + + #endif // MY_CPU_X86_OR_AMD64 + +#endif // _MSC_VER + + +#ifndef BSR2_RET + + #define BSR2_RET(pos, res) { unsigned zz = 30 - MY_clz(pos); \ + res = (zz + zz) + (pos >> zz); } + +#endif + + +unsigned GetPosSlot1(UInt32 pos); +unsigned GetPosSlot1(UInt32 pos) { unsigned res; BSR2_RET(pos, res); @@ -113,10 +200,10 @@ static unsigned GetPosSlot1(UInt32 pos) #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } -#else -#define kNumLogBits (9 + sizeof(size_t) / 2) -/* #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) */ +#else // ! LZMA_LOG_BSR + +#define kNumLogBits (11 + sizeof(size_t) / 8 * 3) #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) @@ -163,7 +250,7 @@ static void LzmaEnc_FastPosInit(Byte *g_FastPos) #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); } -#endif +#endif // LZMA_LOG_BSR #define LZMA_NUM_REPS 4 @@ -193,7 +280,7 @@ typedef struct #define kNumLenToPosStates 4 #define kNumPosSlotBits 6 -#define kDicLogSizeMin 0 +// #define kDicLogSizeMin 0 #define kDicLogSizeMax 32 #define kDistTableSizeMax (kDicLogSizeMax * 2) @@ -299,7 +386,7 @@ typedef UInt32 CProbPrice; typedef struct { void *matchFinderObj; - IMatchFinder matchFinder; + IMatchFinder2 matchFinder; unsigned optCur; unsigned optEnd; @@ -344,10 +431,14 @@ typedef struct // begin of CMatchFinderMt is used in LZ thread CMatchFinderMt matchFinderMt; // end of CMatchFinderMt is used in BT and HASH threads + // #else + // CMatchFinder matchFinderBase; #endif - CMatchFinder matchFinderBase; + + // we suppose that we have 8-bytes alignment after CMatchFinder + #ifndef _7ZIP_ST Byte pad[128]; #endif @@ -355,8 +446,10 @@ typedef struct // LZ thread CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; - UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; + // we want {len , dist} pairs to be 8-bytes aligned in matches array + UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2]; + // we want 8-bytes alignment here UInt32 alignPrices[kAlignTableSize]; UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; @@ -385,12 +478,19 @@ typedef struct CSaveState saveState; + // BoolInt mf_Failure; #ifndef _7ZIP_ST Byte pad2[128]; #endif } CLzmaEnc; +#define MFB (p->matchFinderBase) +/* +#ifndef _7ZIP_ST +#define MFB (p->matchFinderMt.MatchFinder) +#endif +*/ #define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr)); @@ -455,41 +555,51 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX - || props.pb > LZMA_PB_MAX - || props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress) - || props.dictSize > kLzmaMaxHistorySize) + || props.pb > LZMA_PB_MAX) return SZ_ERROR_PARAM; + + if (props.dictSize > kLzmaMaxHistorySize) + props.dictSize = kLzmaMaxHistorySize; + + #ifndef LZMA_LOG_BSR + { + const UInt64 dict64 = props.dictSize; + if (dict64 > ((UInt64)1 << kDicLogSizeMaxCompress)) + return SZ_ERROR_PARAM; + } + #endif + p->dictSize = props.dictSize; { - unsigned fb = props.fb; + unsigned fb = (unsigned)props.fb; if (fb < 5) fb = 5; if (fb > LZMA_MATCH_LEN_MAX) fb = LZMA_MATCH_LEN_MAX; p->numFastBytes = fb; } - p->lc = props.lc; - p->lp = props.lp; - p->pb = props.pb; + p->lc = (unsigned)props.lc; + p->lp = (unsigned)props.lp; + p->pb = (unsigned)props.pb; p->fastMode = (props.algo == 0); // p->_maxMode = True; - p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0); + MFB.btMode = (Byte)(props.btMode ? 1 : 0); { unsigned numHashBytes = 4; if (props.btMode) { - if (props.numHashBytes < 2) - numHashBytes = 2; - else if (props.numHashBytes < 4) - numHashBytes = props.numHashBytes; + if (props.numHashBytes < 2) numHashBytes = 2; + else if (props.numHashBytes < 4) numHashBytes = (unsigned)props.numHashBytes; } - p->matchFinderBase.numHashBytes = numHashBytes; + if (props.numHashBytes >= 5) numHashBytes = 5; + + MFB.numHashBytes = numHashBytes; } - p->matchFinderBase.cutValue = props.mc; + MFB.cutValue = props.mc; - p->writeEndMark = props.writeEndMark; + p->writeEndMark = (BoolInt)props.writeEndMark; #ifndef _7ZIP_ST /* @@ -500,6 +610,8 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) } */ p->multiThread = (props.numThreads > 1); + p->matchFinderMt.btSync.affinity = + p->matchFinderMt.hashSync.affinity = props.affinity; #endif return SZ_OK; @@ -509,7 +621,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize) { CLzmaEnc *p = (CLzmaEnc *)pp; - p->matchFinderBase.expectedDataSize = expectedDataSiize; + MFB.expectedDataSize = expectedDataSiize; } @@ -536,8 +648,8 @@ static void RangeEnc_Construct(CRangeEnc *p) p->bufBase = NULL; } -#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) -#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + ((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize) +#define RangeEnc_GetProcessed(p) ( (p)->processed + (size_t)((p)->buf - (p)->bufBase) + (p)->cacheSize) +#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + (size_t)((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize) #define RC_BUF_SIZE (1 << 16) @@ -556,12 +668,11 @@ static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc) static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->bufBase); - p->bufBase = 0; + p->bufBase = NULL; } static void RangeEnc_Init(CRangeEnc *p) { - /* Stream.Init(); */ p->range = 0xFFFFFFFF; p->cache = 0; p->low = 0; @@ -575,12 +686,12 @@ static void RangeEnc_Init(CRangeEnc *p) MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p) { - size_t num; - if (p->res != SZ_OK) - return; - num = p->buf - p->bufBase; - if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num)) - p->res = SZ_ERROR_WRITE; + const size_t num = (size_t)(p->buf - p->bufBase); + if (p->res == SZ_OK) + { + if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num)) + p->res = SZ_ERROR_WRITE; + } p->processed += num; p->buf = p->bufBase; } @@ -656,7 +767,7 @@ static void RangeEnc_FlushData(CRangeEnc *p) range += newBound & mask; \ mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \ mask += ((1 << kNumMoveBits) - 1); \ - ttt += (Int32)(mask - ttt) >> kNumMoveBits; \ + ttt += (UInt32)((Int32)(mask - ttt) >> kNumMoveBits); \ *(prob) = (CLzmaProb)ttt; \ RC_NORM(p) \ } @@ -749,7 +860,7 @@ static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices) bitCount++; } } - ProbPrices[i] = (CProbPrice)((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); + ProbPrices[i] = (CProbPrice)(((unsigned)kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); // printf("\n%3d: %5d", i, ProbPrices[i]); } } @@ -985,7 +1096,11 @@ static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes) p->additionalOffset++; p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); - numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); + { + const UInt32 *d = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); + // if (!d) { p->mf_Failure = True; *numPairsRes = 0; return 0; } + numPairs = (unsigned)(d - p->matches); + } *numPairsRes = numPairs; #ifdef SHOW_STAT @@ -1001,7 +1116,7 @@ static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes) if (numPairs == 0) return 0; { - unsigned len = p->matches[(size_t)numPairs - 2]; + const unsigned len = p->matches[(size_t)numPairs - 2]; if (len != p->numFastBytes) return len; { @@ -1011,7 +1126,7 @@ static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes) { const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; const Byte *p2 = p1 + len; - ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[(size_t)numPairs - 1]; + const ptrdiff_t dif = (ptrdiff_t)-1 - (ptrdiff_t)p->matches[(size_t)numPairs - 1]; const Byte *lim = p1 + numAvail; for (; p2 != lim && *p2 == p2[dif]; p2++) {} @@ -1167,6 +1282,8 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) repLens[i] = len; if (len > repLens[repMaxIndex]) repMaxIndex = i; + if (len == LZMA_MATCH_LEN_MAX) // 21.03 : optimization + break; } if (repLens[repMaxIndex] >= p->numFastBytes) @@ -1179,10 +1296,12 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) } matches = p->matches; + #define MATCHES matches + // #define MATCHES p->matches if (mainLen >= p->numFastBytes) { - p->backRes = matches[(size_t)numPairs - 1] + LZMA_NUM_REPS; + p->backRes = MATCHES[(size_t)numPairs - 1] + LZMA_NUM_REPS; MOVE_POS(p, mainLen - 1) return mainLen; } @@ -1276,13 +1395,13 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) if (len < 2) len = 2; else - while (len > matches[offs]) + while (len > MATCHES[offs]) offs += 2; for (; ; len++) { COptimal *opt; - UInt32 dist = matches[(size_t)offs + 1]; + UInt32 dist = MATCHES[(size_t)offs + 1]; UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len); unsigned lenToPosState = GetLenToPosState(len); @@ -1306,7 +1425,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) opt->extra = 0; } - if (len == matches[offs]) + if (len == MATCHES[offs]) { offs += 2; if (offs == numPairs) @@ -1727,8 +1846,8 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) if (newLen > numAvail) { newLen = numAvail; - for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); - matches[numPairs] = (UInt32)newLen; + for (numPairs = 0; newLen > MATCHES[numPairs]; numPairs += 2); + MATCHES[numPairs] = (UInt32)newLen; numPairs += 2; } @@ -1747,9 +1866,9 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) } offs = 0; - while (startLen > matches[offs]) + while (startLen > MATCHES[offs]) offs += 2; - dist = matches[(size_t)offs + 1]; + dist = MATCHES[(size_t)offs + 1]; // if (dist >= kNumFullDistances) GetPosSlot2(dist, posSlot); @@ -1776,7 +1895,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) } } - if (len == matches[offs]) + if (len == MATCHES[offs]) { // if (p->_maxMode) { // MATCH : LIT : REP_0 @@ -1841,7 +1960,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) offs += 2; if (offs == numPairs) break; - dist = matches[(size_t)offs + 1]; + dist = MATCHES[(size_t)offs + 1]; // if (dist >= kNumFullDistances) GetPosSlot2(dist, posSlot); } @@ -2059,8 +2178,23 @@ static SRes CheckErrors(CLzmaEnc *p) return p->result; if (p->rc.res != SZ_OK) p->result = SZ_ERROR_WRITE; - if (p->matchFinderBase.result != SZ_OK) + + #ifndef _7ZIP_ST + if ( + // p->mf_Failure || + (p->mtMode && + ( // p->matchFinderMt.failure_LZ_LZ || + p->matchFinderMt.failure_LZ_BT)) + ) + { + p->result = MY_HRES_ERROR__INTERNAL_ERROR; + // printf("\nCheckErrors p->matchFinderMt.failureLZ\n"); + } + #endif + + if (MFB.result != SZ_OK) p->result = SZ_ERROR_READ; + if (p->result != SZ_OK) p->finished = True; return p->result; @@ -2198,14 +2332,14 @@ MY_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p) -void LzmaEnc_Construct(CLzmaEnc *p) +static void LzmaEnc_Construct(CLzmaEnc *p) { RangeEnc_Construct(&p->rc); - MatchFinder_Construct(&p->matchFinderBase); + MatchFinder_Construct(&MFB); #ifndef _7ZIP_ST + p->matchFinderMt.MatchFinder = &MFB; MatchFinderMt_Construct(&p->matchFinderMt); - p->matchFinderMt.MatchFinder = &p->matchFinderBase; #endif { @@ -2221,7 +2355,6 @@ void LzmaEnc_Construct(CLzmaEnc *p) LzmaEnc_InitPriceTables(p->ProbPrices); p->litProbs = NULL; p->saveState.litProbs = NULL; - } CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc) @@ -2233,7 +2366,7 @@ CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc) return p; } -void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc) +static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->litProbs); ISzAlloc_Free(alloc, p->saveState.litProbs); @@ -2241,13 +2374,13 @@ void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc) p->saveState.litProbs = NULL; } -void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig) +static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig) { #ifndef _7ZIP_ST MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); #endif - MatchFinder_Free(&p->matchFinderBase, allocBig); + MatchFinder_Free(&MFB, allocBig); LzmaEnc_FreeLits(p, alloc); RangeEnc_Free(&p->rc, alloc); } @@ -2259,11 +2392,18 @@ void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig) } +MY_NO_INLINE static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize) { UInt32 nowPos32, startPos32; if (p->needInit) { + #ifndef _7ZIP_ST + if (p->mtMode) + { + RINOK(MatchFinderMt_InitMt(&p->matchFinderMt)); + } + #endif p->matchFinder.Init(p->matchFinderObj); p->needInit = 0; } @@ -2521,12 +2661,12 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa // { int y; for (y = 0; y < 100; y++) { FillDistancesPrices(p); // }} - LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices); } if (p->repLenEncCounter <= 0) { p->repLenEncCounter = REP_LEN_COUNT; - LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices); } } @@ -2559,11 +2699,13 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) { UInt32 beforeSize = kNumOpts; + UInt32 dictSize; + if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; #ifndef _7ZIP_ST - p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0)); + p->mtMode = (p->multiThread && !p->fastMode && (MFB.btMode != 0)); #endif { @@ -2582,36 +2724,56 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, } } - p->matchFinderBase.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0); + MFB.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0); - if (beforeSize + p->dictSize < keepWindowSize) - beforeSize = keepWindowSize - p->dictSize; + + dictSize = p->dictSize; + if (dictSize == ((UInt32)2 << 30) || + dictSize == ((UInt32)3 << 30)) + { + /* 21.03 : here we reduce the dictionary for 2 reasons: + 1) we don't want 32-bit back_distance matches in decoder for 2 GB dictionary. + 2) we want to elimate useless last MatchFinder_Normalize3() for corner cases, + where data size is aligned for 1 GB: 5/6/8 GB. + That reducing must be >= 1 for such corner cases. */ + dictSize -= 1; + } + + if (beforeSize + dictSize < keepWindowSize) + beforeSize = keepWindowSize - dictSize; + + /* in worst case we can look ahead for + max(LZMA_MATCH_LEN_MAX, numFastBytes + 1 + numFastBytes) bytes. + we send larger value for (keepAfter) to MantchFinder_Create(): + (numFastBytes + LZMA_MATCH_LEN_MAX + 1) + */ #ifndef _7ZIP_ST if (p->mtMode) { - RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, - LZMA_MATCH_LEN_MAX - + 1 /* 18.04 */ + RINOK(MatchFinderMt_Create(&p->matchFinderMt, dictSize, beforeSize, + p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 18.04 */ , allocBig)); p->matchFinderObj = &p->matchFinderMt; - p->matchFinderBase.bigHash = (Byte)( - (p->dictSize > kBigHashDicLimit && p->matchFinderBase.hashMask >= 0xFFFFFF) ? 1 : 0); + MFB.bigHash = (Byte)( + (p->dictSize > kBigHashDicLimit && MFB.hashMask >= 0xFFFFFF) ? 1 : 0); MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); } else #endif { - if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) + if (!MatchFinder_Create(&MFB, dictSize, beforeSize, + p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 21.03 */ + , allocBig)) return SZ_ERROR_MEM; - p->matchFinderObj = &p->matchFinderBase; - MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); + p->matchFinderObj = &MFB; + MatchFinder_CreateVTable(&MFB, &p->matchFinder); } return SZ_OK; } -void LzmaEnc_Init(CLzmaEnc *p) +static void LzmaEnc_Init(CLzmaEnc *p) { unsigned i; p->state = 0; @@ -2675,12 +2837,14 @@ void LzmaEnc_Init(CLzmaEnc *p) p->additionalOffset = 0; - p->pbMask = (1 << p->pb) - 1; + p->pbMask = ((unsigned)1 << p->pb) - 1; p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc); + + // p->mf_Failure = False; } -void LzmaEnc_InitPrices(CLzmaEnc *p) +static void LzmaEnc_InitPrices(CLzmaEnc *p) { if (!p->fastMode) { @@ -2694,8 +2858,8 @@ void LzmaEnc_InitPrices(CLzmaEnc *p) p->repLenEncCounter = REP_LEN_COUNT; - LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices); - LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices); } static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) @@ -2719,7 +2883,7 @@ static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInS ISzAllocPtr alloc, ISzAllocPtr allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; - p->matchFinderBase.stream = inStream; + MFB.stream = inStream; p->needInit = 1; p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); @@ -2730,16 +2894,16 @@ SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISzAllocPtr alloc, ISzAllocPtr allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; - p->matchFinderBase.stream = inStream; + MFB.stream = inStream; p->needInit = 1; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) { - p->matchFinderBase.directInput = 1; - p->matchFinderBase.bufferBase = (Byte *)src; - p->matchFinderBase.directInputRem = srcLen; + MFB.directInput = 1; + MFB.bufferBase = (Byte *)src; + MFB.directInputRem = srcLen; } SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, @@ -2781,19 +2945,23 @@ static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, s size = p->rem; p->overflow = True; } - memcpy(p->data, data, size); - p->rem -= size; - p->data += size; + if (size != 0) + { + memcpy(p->data, data, size); + p->rem -= size; + p->data += size; + } return size; } +/* UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); } - +*/ const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) { @@ -2841,6 +3009,7 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, } +MY_NO_INLINE static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) { SRes res = SZ_OK; @@ -2870,7 +3039,7 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) LzmaEnc_Finish(p); /* - if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase)) + if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&MFB)) res = SZ_ERROR_FAIL; } */ @@ -2889,35 +3058,43 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) { - CLzmaEnc *p = (CLzmaEnc *)pp; - 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); - - if (dictSize >= ((UInt32)1 << 22)) { - 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; } - } + const CLzmaEnc *p = (const CLzmaEnc *)pp; + const UInt32 dictSize = p->dictSize; + UInt32 v; + props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); + + // we write aligned dictionary value to properties for lzma decoder + if (dictSize >= ((UInt32)1 << 21)) + { + const UInt32 kDictMask = ((UInt32)1 << 20) - 1; + v = (dictSize + kDictMask) & ~kDictMask; + if (v < dictSize) + v = dictSize; + } + else + { + unsigned i = 11 * 2; + do + { + v = (UInt32)(2 + (i & 1)) << (i >> 1); + i++; + } + while (v < dictSize); + } - for (i = 0; i < 4; i++) - props[1 + i] = (Byte)(dictSize >> (8 * i)); - return SZ_OK; + SetUi32(props + 1, v); + return SZ_OK; + } } unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp) { - return ((CLzmaEnc *)pp)->writeEndMark; + return (unsigned)((CLzmaEnc *)pp)->writeEndMark; } @@ -2974,3 +3151,15 @@ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, LzmaEnc_Destroy(p, alloc, allocBig); return res; } + + +/* +#ifndef _7ZIP_ST +void LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2]) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + lz_threads[0] = p->matchFinderMt.hashSync.thread; + lz_threads[1] = p->matchFinderMt.btSync.thread; +} +#endif +*/ diff --git a/libraries/lzma/C/LzmaEnc.h b/libraries/lzma/C/LzmaEnc.h index 9194ee576..bc2ed5042 100644 --- a/libraries/lzma/C/LzmaEnc.h +++ b/libraries/lzma/C/LzmaEnc.h @@ -1,5 +1,5 @@ /* LzmaEnc.h -- LZMA Encoder -2017-07-27 : Igor Pavlov : Public domain */ +2019-10-30 : Igor Pavlov : Public domain */ #ifndef __LZMA_ENC_H #define __LZMA_ENC_H @@ -29,6 +29,8 @@ typedef struct _CLzmaEncProps UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1. Encoder uses this value to reduce dictionary size */ + + UInt64 affinity; } CLzmaEncProps; void LzmaEncProps_Init(CLzmaEncProps *p); diff --git a/libraries/lzma/C/Ppmd.h b/libraries/lzma/C/Ppmd.h index a5c1e3ef2..b19879208 100644 --- a/libraries/lzma/C/Ppmd.h +++ b/libraries/lzma/C/Ppmd.h @@ -1,5 +1,5 @@ /* Ppmd.h -- PPMD codec common code -2017-04-03 : Igor Pavlov : Public domain +2021-04-13 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #ifndef __PPMD_H @@ -9,7 +9,16 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ EXTERN_C_BEGIN -#ifdef MY_CPU_32BIT +#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4) +/* + PPMD code always uses 32-bit internal fields in PPMD structures to store internal references in main block. + if (PPMD_32BIT is defined), the PPMD code stores internal pointers to 32-bit reference fields. + if (PPMD_32BIT is NOT defined), the PPMD code stores internal UInt32 offsets to reference fields. + if (pointer size is 64-bit), then (PPMD_32BIT) mode is not allowed, + if (pointer size is 32-bit), then (PPMD_32BIT) mode is optional, + and it's allowed to disable PPMD_32BIT mode even if pointer is 32-bit. + PPMD code works slightly faster in (PPMD_32BIT) mode. +*/ #define PPMD_32BIT #endif @@ -28,7 +37,7 @@ EXTERN_C_BEGIN #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) +MY_CPU_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 */ @@ -40,41 +49,114 @@ typedef struct } 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++); } + { (p)->Summ = (UInt16)((p)->Summ << 1); (p)->Count = (Byte)(3 << (p)->Shift++); } + typedef struct { Byte Symbol; Byte Freq; - UInt16 SuccessorLow; - UInt16 SuccessorHigh; + UInt16 Successor_0; + UInt16 Successor_1; } CPpmd_State; -#pragma pack(pop) +typedef struct CPpmd_State2_ +{ + Byte Symbol; + Byte Freq; +} CPpmd_State2; -typedef - #ifdef PPMD_32BIT - CPpmd_State * - #else - UInt32 - #endif - CPpmd_State_Ref; +typedef struct CPpmd_State4_ +{ + UInt16 Successor_0; + UInt16 Successor_1; +} CPpmd_State4; -typedef - #ifdef PPMD_32BIT - void * - #else - UInt32 - #endif - CPpmd_Void_Ref; +MY_CPU_pragma_pop + +/* + PPMD code can write full CPpmd_State structure data to CPpmd*_Context + at (byte offset = 2) instead of some fields of original CPpmd*_Context structure. + + If we use pointers to different types, but that point to shared + memory space, we can have aliasing problem (strict aliasing). + + XLC compiler in -O2 mode can change the order of memory write instructions + in relation to read instructions, if we have use pointers to different types. + + To solve that aliasing problem we use combined CPpmd*_Context structure + with unions that contain the fields from both structures: + the original CPpmd*_Context and CPpmd_State. + So we can access the fields from both structures via one pointer, + and the compiler doesn't change the order of write instructions + in relation to read instructions. + + If we don't use memory write instructions to shared memory in + some local code, and we use only reading instructions (read only), + then probably it's safe to use pointers to different types for reading. +*/ + + + +#ifdef PPMD_32BIT + + #define Ppmd_Ref_Type(type) type * + #define Ppmd_GetRef(p, ptr) (ptr) + #define Ppmd_GetPtr(p, ptr) (ptr) + #define Ppmd_GetPtr_Type(p, ptr, note_type) (ptr) + +#else + + #define Ppmd_Ref_Type(type) UInt32 + #define Ppmd_GetRef(p, ptr) ((UInt32)((Byte *)(ptr) - (p)->Base)) + #define Ppmd_GetPtr(p, offs) ((void *)((p)->Base + (offs))) + #define Ppmd_GetPtr_Type(p, offs, type) ((type *)Ppmd_GetPtr(p, offs)) + +#endif // PPMD_32BIT + + +typedef Ppmd_Ref_Type(CPpmd_State) CPpmd_State_Ref; +typedef Ppmd_Ref_Type(void) CPpmd_Void_Ref; +typedef Ppmd_Ref_Type(Byte) CPpmd_Byte_Ref; + + +/* +#ifdef MY_CPU_LE_UNALIGN +// the unaligned 32-bit access latency can be too large, if the data is not in L1 cache. +#define Ppmd_GET_SUCCESSOR(p) ((CPpmd_Void_Ref)*(const UInt32 *)(const void *)&(p)->Successor_0) +#define Ppmd_SET_SUCCESSOR(p, v) *(UInt32 *)(void *)(void *)&(p)->Successor_0 = (UInt32)(v) + +#else +*/ + +/* + We can write 16-bit halves to 32-bit (Successor) field in any selected order. + But the native order is more consistent way. + So we use the native order, if LE/BE order can be detected here at compile time. +*/ + +#ifdef MY_CPU_BE + + #define Ppmd_GET_SUCCESSOR(p) \ + ( (CPpmd_Void_Ref) (((UInt32)(p)->Successor_0 << 16) | (p)->Successor_1) ) + + #define Ppmd_SET_SUCCESSOR(p, v) { \ + (p)->Successor_0 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); \ + (p)->Successor_1 = (UInt16)((UInt32)(v) /* & 0xFFFF */); } + +#else + + #define Ppmd_GET_SUCCESSOR(p) \ + ( (CPpmd_Void_Ref) ((p)->Successor_0 | ((UInt32)(p)->Successor_1 << 16)) ) + + #define Ppmd_SET_SUCCESSOR(p, v) { \ + (p)->Successor_0 = (UInt16)((UInt32)(v) /* & 0xFFFF */); \ + (p)->Successor_1 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); } + +#endif + +// #endif -typedef - #ifdef PPMD_32BIT - Byte * - #else - UInt32 - #endif - CPpmd_Byte_Ref; #define PPMD_SetAllBitsIn256Bytes(p) \ { size_t z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \ diff --git a/libraries/lzma/C/Ppmd7.c b/libraries/lzma/C/Ppmd7.c index 470aadccf..cf401cb37 100644 --- a/libraries/lzma/C/Ppmd7.c +++ b/libraries/lzma/C/Ppmd7.c @@ -1,5 +1,5 @@ /* Ppmd7.c -- PPMdH codec -2018-07-04 : Igor Pavlov : Public domain +2021-04-13 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #include "Precomp.h" @@ -8,7 +8,12 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #include "Ppmd7.h" -const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; +/* define PPMD7_ORDER_0_SUPPPORT to suport order-0 mode, unsupported by orignal PPMd var.H. code */ +// #define PPMD7_ORDER_0_SUPPPORT + +MY_ALIGN(16) +static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; +MY_ALIGN(16) static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; #define MAX_FREQ 124 @@ -16,13 +21,10 @@ static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE) #define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1]) -#define I2U(indx) (p->Indx2Units[indx]) +#define I2U(indx) ((unsigned)p->Indx2Units[indx]) +#define I2U_UInt16(indx) ((UInt16)p->Indx2Units[indx]) -#ifdef PPMD_32BIT - #define REF(ptr) (ptr) -#else - #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base)) -#endif +#define REF(ptr) Ppmd_GetRef(p, ptr) #define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr)) @@ -35,13 +37,7 @@ typedef CPpmd7_Context * CTX_PTR; struct CPpmd7_Node_; -typedef - #ifdef PPMD_32BIT - struct CPpmd7_Node_ * - #else - UInt32 - #endif - CPpmd7_Node_Ref; +typedef Ppmd_Ref_Type(struct CPpmd7_Node_) CPpmd7_Node_Ref; typedef struct CPpmd7_Node_ { @@ -51,17 +47,13 @@ typedef struct CPpmd7_Node_ CPpmd7_Node_Ref Prev; } CPpmd7_Node; -#ifdef PPMD_32BIT - #define NODE(ptr) (ptr) -#else - #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs))) -#endif +#define NODE(r) Ppmd_GetPtr_Type(p, r, CPpmd7_Node) void Ppmd7_Construct(CPpmd7 *p) { unsigned i, k, m; - p->Base = 0; + p->Base = NULL; for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) { @@ -77,6 +69,7 @@ void Ppmd7_Construct(CPpmd7 *p) for (i = 0; i < 3; i++) p->NS2Indx[i] = (Byte)i; + for (m = i, k = 1; i < 256; i++) { p->NS2Indx[i] = (Byte)m; @@ -84,54 +77,63 @@ void Ppmd7_Construct(CPpmd7 *p) k = (++m) - 2; } - memset(p->HB2Flag, 0, 0x40); - memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40); + memcpy(p->ExpEscape, PPMD7_kExpEscape, 16); } + void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->Base); p->Size = 0; - p->Base = 0; + p->Base = NULL; } + BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc) { if (!p->Base || p->Size != size) { - size_t size2; Ppmd7_Free(p, alloc); - size2 = 0 - #ifndef PPMD_32BIT - + UNIT_SIZE - #endif - ; - p->AlignOffset = - #ifdef PPMD_32BIT - (4 - size) & 3; - #else - 4 - (size & 3); - #endif - if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size + size2)) == 0) + p->AlignOffset = (4 - size) & 3; + if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size)) == NULL) return False; p->Size = size; } return True; } + + +// ---------- Internal Memory Allocator ---------- + +/* We can use CPpmd7_Node in list of free units (as in Ppmd8) + But we still need one additional list walk pass in GlueFreeBlocks(). + So we use simple CPpmd_Void_Ref instead of CPpmd7_Node in InsertNode() / RemoveNode() +*/ + +#define EMPTY_NODE 0 + + static void InsertNode(CPpmd7 *p, void *node, unsigned indx) { *((CPpmd_Void_Ref *)node) = p->FreeList[indx]; + // ((CPpmd7_Node *)node)->Next = (CPpmd7_Node_Ref)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; + // CPpmd7_Node *node = NODE((CPpmd7_Node_Ref)p->FreeList[indx]); + // p->FreeList[indx] = node->Next; return node; } + static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) { unsigned i, nu = I2U(oldIndx) - I2U(newIndx); @@ -144,123 +146,167 @@ static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) InsertNode(p, ptr, i); } + +/* we use CPpmd7_Node_Union union to solve XLC -O2 strict pointer aliasing problem */ + +typedef union _CPpmd7_Node_Union +{ + CPpmd7_Node Node; + CPpmd7_Node_Ref NextRef; +} CPpmd7_Node_Union; + +/* Original PPmdH (Ppmd7) code uses doubly linked list in GlueFreeBlocks() + we use single linked list similar to Ppmd8 code */ + + 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; - + /* + we use first UInt16 field of 12-bytes UNITs as record type stamp + CPpmd_State { Byte Symbol; Byte Freq; : Freq != 0 + CPpmd7_Context { UInt16 NumStats; : NumStats != 0 + CPpmd7_Node { UInt16 Stamp : Stamp == 0 for free record + : Stamp == 1 for head record and guard + Last 12-bytes UNIT in array is always contains 12-bytes order-0 CPpmd7_Context record. + */ + CPpmd7_Node_Ref head, n = 0; + 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; + + /* we set guard NODE at LoUnit */ if (p->LoUnit != p->HiUnit) - ((CPpmd7_Node *)p->LoUnit)->Stamp = 1; - - /* Glue free blocks */ - while (n != head) + ((CPpmd7_Node *)(void *)p->LoUnit)->Stamp = 1; + { - CPpmd7_Node *node = NODE(n); - UInt32 nu = (UInt32)node->NU; - for (;;) + /* Create list of free blocks. + We still need one additional list walk pass before Glue. */ + unsigned i; + for (i = 0; i < PPMD_NUM_INDEXES; i++) { - 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; + const UInt16 nu = I2U_UInt16(i); + CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i]; + p->FreeList[i] = 0; + while (next != 0) + { + /* Don't change the order of the following commands: */ + CPpmd7_Node_Union *un = (CPpmd7_Node_Union *)NODE(next); + const CPpmd7_Node_Ref tmp = next; + next = un->NextRef; + un->Node.Stamp = EMPTY_NODE; + un->Node.NU = nu; + un->Node.Next = n; + n = tmp; + } } - n = node->Next; } - + + head = n; + /* Glue and Fill must walk the list in same direction */ + { + /* Glue free blocks */ + CPpmd7_Node_Ref *prev = &head; + while (n) + { + CPpmd7_Node *node = NODE(n); + UInt32 nu = node->NU; + n = node->Next; + if (nu == 0) + { + *prev = n; + continue; + } + prev = &node->Next; + for (;;) + { + CPpmd7_Node *node2 = node + nu; + nu += node2->NU; + if (node2->Stamp != EMPTY_NODE || nu >= 0x10000) + break; + node->NU = (UInt16)nu; + node2->NU = 0; + } + } + } + /* Fill lists of free blocks */ - for (n = NODE(head)->Next; n != head;) + for (n = head; n != 0;) { CPpmd7_Node *node = NODE(n); - unsigned nu; - CPpmd7_Node_Ref next = node->Next; - for (nu = node->NU; nu > 128; nu -= 128, node += 128) + UInt32 nu = node->NU; + unsigned i; + n = node->Next; + if (nu == 0) + continue; + for (; 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 + k, (unsigned)nu - k - 1); } InsertNode(p, node, i); - n = next; } } + +MY_NO_INLINE 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)); + Byte *us = p->UnitsStart; p->GlueCount--; - return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL); + return ((UInt32)(us - p->Text) > numBytes) ? (p->UnitsStart = us - numBytes) : NULL; } } while (p->FreeList[i] == 0); - retVal = RemoveNode(p, i); - SplitBlock(p, retVal, i, indx); - return retVal; + + { + void *block = RemoveNode(p, i); + SplitBlock(p, block, i, indx); + return block; + } } + 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; + UInt32 numBytes = U2B(I2U(indx)); + Byte *lo = p->LoUnit; + if ((UInt32)(p->HiUnit - lo) >= numBytes) + { + p->LoUnit = lo + numBytes; + return lo; + } } 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); } +#define MyMem12Cpy(dest, src, num) \ + { UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \ + do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); } + + +/* static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU) { unsigned i0 = U2I(oldNU); @@ -277,20 +323,25 @@ static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU SplitBlock(p, oldPtr, i0, i1); return oldPtr; } +*/ -#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16))) +#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) { - (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF); - (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF); + Ppmd_SET_SUCCESSOR(p, v); } -static void RestartModel(CPpmd7 *p) + + +MY_NO_INLINE +static +void RestartModel(CPpmd7 *p) { - unsigned i, k, m; + unsigned i, k; 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; @@ -300,57 +351,110 @@ static void RestartModel(CPpmd7 *p) 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); + CPpmd7_Context *mc = (CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ + CPpmd_State *s = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */ + + p->LoUnit += U2B(256 / 2); + p->MaxContext = p->MinContext = mc; + p->FoundState = s; + + mc->NumStats = 256; + mc->Union2.SummFreq = 256 + 1; + mc->Union4.Stats = REF(s); + mc->Suffix = 0; + + for (i = 0; i < 256; i++, s++) + { + s->Symbol = (Byte)i; + s->Freq = 1; + SetSuccessor(s, 0); + } + + #ifdef PPMD7_ORDER_0_SUPPPORT + if (p->MaxOrder == 0) + { + CPpmd_Void_Ref r = REF(mc); + s = p->FoundState; + for (i = 0; i < 256; i++, s++) + SetSuccessor(s, r); + return; + } + #endif } for (i = 0; i < 128; i++) + + + for (k = 0; k < 8; k++) { + unsigned m; 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]; + + + + unsigned summ = ((5 * i + 10) << (PPMD_PERIOD_BITS - 4)); + for (k = 0; k < 16; k++, s++) { - CPpmd_See *s = &p->See[i][k]; - s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4)); + s->Summ = (UInt16)summ; + s->Shift = (PPMD_PERIOD_BITS - 4); s->Count = 4; } + } + + p->DummySee.Summ = 0; /* unused */ + p->DummySee.Shift = PPMD_PERIOD_BITS; + p->DummySee.Count = 64; /* unused */ } + 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, BoolInt skip) + + +/* + CreateSuccessors() + It's called when (FoundState->Successor) is RAW-Successor, + that is the link to position in Raw text. + So we create Context records and write the links to + FoundState->Successor and to identical RAW-Successors in suffix + contexts of MinContex. + + The function returns: + if (OrderFall == 0) then MinContext is already at MAX order, + { return pointer to new or existing context of same MAX order } + else + { return pointer to new real context that will be (Order+1) in comparison with MinContext + + also it can return pointer to real context of same order, +*/ + +MY_NO_INLINE +static CTX_PTR CreateSuccessors(CPpmd7 *p) { - CPpmd_State upState; CTX_PTR c = p->MinContext; CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); - CPpmd_State *ps[PPMD7_MAX_ORDER]; + Byte newSym, newFreq; unsigned numPs = 0; - - if (!skip) + CPpmd_State *ps[PPMD7_MAX_ORDER]; + + if (p->OrderFall != 0) ps[numPs++] = p->FoundState; while (c->Suffix) @@ -358,44 +462,70 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p, BoolInt skip) CPpmd_Void_Ref successor; CPpmd_State *s; c = SUFFIX(c); + + if (c->NumStats != 1) { - for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++); + Byte sym = p->FoundState->Symbol; + for (s = STATS(c); s->Symbol != sym; s++); + } else + { s = ONE_STATE(c); + + } successor = SUCCESSOR(s); if (successor != upBranch) { + // (c) is real record Context here, c = CTX(successor); if (numPs == 0) + { + // (c) is real record MAX Order Context here, + // So we don't need to create any new contexts. return c; + } break; } ps[numPs++] = s; } - upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch); - SetSuccessor(&upState, upBranch + 1); + // All created contexts will have single-symbol with new RAW-Successor + // All new RAW-Successors will point to next position in RAW text + // after FoundState->Successor + + newSym = *(const Byte *)Ppmd7_GetPtr(p, upBranch); + upBranch++; + if (c->NumStats == 1) - upState.Freq = ONE_STATE(c)->Freq; + newFreq = 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)))); + for (s = STATS(c); s->Symbol != newSym; s++); + cf = (UInt32)s->Freq - 1; + s0 = (UInt32)c->Union2.SummFreq - c->NumStats - cf; + /* + cf - is frequency of symbol that will be Successor in new context records. + s0 - is commulative frequency sum of another symbols from parent context. + max(newFreq)= (s->Freq + 1), when (s0 == 1) + we have requirement (Ppmd7Context_OneState()->Freq <= 128) in BinSumm[] + so (s->Freq < 128) - is requirement for multi-symbol contexts + */ + newFreq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : (2 * cf + s0 - 1) / (2 * s0) + 1)); } + // Create new single-symbol contexts from low order to high order in loop + do { - /* Create Child */ - CTX_PTR c1; /* = AllocContext(p); */ + CTX_PTR c1; + /* = AllocContext(p); */ if (p->HiUnit != p->LoUnit) - c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); + c1 = (CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); else if (p->FreeList[0] != 0) c1 = (CTX_PTR)RemoveNode(p, 0); else @@ -404,8 +534,11 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p, BoolInt skip) if (!c1) return NULL; } + c1->NumStats = 1; - *ONE_STATE(c1) = upState; + ONE_STATE(c1)->Symbol = newSym; + ONE_STATE(c1)->Freq = newFreq; + SetSuccessor(ONE_STATE(c1), upBranch); c1->Suffix = REF(c); SetSuccessor(ps[--numPs], REF(c1)); c = c1; @@ -415,21 +548,26 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p, BoolInt skip) return c; } -static void SwapStates(CPpmd_State *t1, CPpmd_State *t2) -{ - CPpmd_State tmp = *t1; - *t1 = *t2; - *t2 = tmp; -} -static void UpdateModel(CPpmd7 *p) + +#define SwapStates(s) \ + { CPpmd_State tmp = s[0]; s[0] = s[-1]; s[-1] = tmp; } + + +void Ppmd7_UpdateModel(CPpmd7 *p); +MY_NO_INLINE +void Ppmd7_UpdateModel(CPpmd7 *p) { - CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState); - CTX_PTR c; + CPpmd_Void_Ref maxSuccessor, minSuccessor; + CTX_PTR c, mc; unsigned s0, ns; - + + + if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0) { + /* Update Freqs in Suffix Context */ + c = SUFFIX(p->MinContext); if (c->NumStats == 1) @@ -441,27 +579,39 @@ static void UpdateModel(CPpmd7 *p) else { CPpmd_State *s = STATS(c); - if (s->Symbol != p->FoundState->Symbol) + Byte sym = p->FoundState->Symbol; + + if (s->Symbol != sym) { - do { s++; } while (s->Symbol != p->FoundState->Symbol); + do + { + // s++; if (s->Symbol == sym) break; + s++; + } + while (s->Symbol != sym); + if (s[0].Freq >= s[-1].Freq) { - SwapStates(&s[0], &s[-1]); + SwapStates(s); s--; } } + if (s->Freq < MAX_FREQ - 9) { - s->Freq += 2; - c->SummFreq += 2; + s->Freq = (Byte)(s->Freq + 2); + c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 2); } } } + if (p->OrderFall == 0) { - p->MinContext = p->MaxContext = CreateSuccessors(p, True); - if (p->MinContext == 0) + /* MAX ORDER context */ + /* (FoundState->Successor) is RAW-Successor. */ + p->MaxContext = p->MinContext = CreateSuccessors(p); + if (!p->MinContext) { RestartModel(p); return; @@ -469,45 +619,93 @@ static void UpdateModel(CPpmd7 *p) SetSuccessor(p->FoundState, REF(p->MinContext)); return; } + + + /* NON-MAX ORDER context */ - *p->Text++ = p->FoundState->Symbol; - successor = REF(p->Text); - if (p->Text >= p->UnitsStart) { - RestartModel(p); - return; + Byte *text = p->Text; + *text++ = p->FoundState->Symbol; + p->Text = text; + if (text >= p->UnitsStart) + { + RestartModel(p); + return; + } + maxSuccessor = REF(text); } - if (fSuccessor) + minSuccessor = SUCCESSOR(p->FoundState); + + if (minSuccessor) { - if (fSuccessor <= successor) + // there is Successor for FoundState in MinContext. + // So the next context will be one order higher than MinContext. + + if (minSuccessor <= maxSuccessor) { - CTX_PTR cs = CreateSuccessors(p, False); - if (cs == NULL) + // minSuccessor is RAW-Successor. So we will create real contexts records: + CTX_PTR cs = CreateSuccessors(p); + if (!cs) { RestartModel(p); return; } - fSuccessor = REF(cs); + minSuccessor = REF(cs); } + + // minSuccessor now is real Context pointer that points to existing (Order+1) context + if (--p->OrderFall == 0) { - successor = fSuccessor; + /* + if we move to MaxOrder context, then minSuccessor will be common Succesor for both: + MinContext that is (MaxOrder - 1) + MaxContext that is (MaxOrder) + so we don't need new RAW-Successor, and we can use real minSuccessor + as succssors for both MinContext and MaxContext. + */ + maxSuccessor = minSuccessor; + + /* + if (MaxContext != MinContext) + { + there was order fall from MaxOrder and we don't need current symbol + to transfer some RAW-Succesors to real contexts. + So we roll back pointer in raw data for one position. + } + */ p->Text -= (p->MaxContext != p->MinContext); } } else { - SetSuccessor(p->FoundState, successor); - fSuccessor = REF(p->MinContext); + /* + FoundState has NULL-Successor here. + And only root 0-order context can contain NULL-Successors. + We change Successor in FoundState to RAW-Successor, + And next context will be same 0-order root Context. + */ + SetSuccessor(p->FoundState, maxSuccessor); + minSuccessor = 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)) + + mc = p->MinContext; + c = p->MaxContext; + + p->MaxContext = p->MinContext = CTX(minSuccessor); + + if (c == mc) + return; + + // s0 : is pure Escape Freq + s0 = mc->Union2.SummFreq - (ns = mc->NumStats) - ((unsigned)p->FoundState->Freq - 1); + + do { unsigned ns1; - UInt32 cf, sf; + UInt32 sum; + if ((ns1 = c->NumStats) != 1) { if ((ns1 & 1) == 0) @@ -527,80 +725,127 @@ static void UpdateModel(CPpmd7 *p) oldPtr = STATS(c); MyMem12Cpy(ptr, oldPtr, oldNU); InsertNode(p, oldPtr, i); - c->Stats = STATS_REF(ptr); + c->Union4.Stats = STATS_REF(ptr); } } - c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1))); + sum = c->Union2.SummFreq; + /* max increase of Escape_Freq is 3 here. + total increase of Union2.SummFreq for all symbols is less than 256 here */ + sum += (UInt32)(2 * ns1 < ns) + 2 * ((unsigned)(4 * ns1 <= ns) & (sum <= 8 * ns1)); + /* original PPMdH uses 16-bit variable for (sum) here. + But (sum < 0x9000). So we don't truncate (sum) to 16-bit */ + // sum = (UInt16)sum; } else { + // instead of One-symbol context we create 2-symbol context 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); + { + unsigned freq = c->Union2.State2.Freq; + // s = *ONE_STATE(c); + s->Symbol = c->Union2.State2.Symbol; + s->Successor_0 = c->Union4.State4.Successor_0; + s->Successor_1 = c->Union4.State4.Successor_1; + // SetSuccessor(s, c->Union4.Stats); // call it only for debug purposes to check the order of + // (Successor_0 and Successor_1) in LE/BE. + c->Union4.Stats = REF(s); + if (freq < MAX_FREQ / 4 - 1) + freq <<= 1; + else + freq = MAX_FREQ - 4; + // (max(s->freq) == 120), when we convert from 1-symbol into 2-symbol context + s->Freq = (Byte)freq; + // max(InitEsc = PPMD7_kExpEscape[*]) is 25. So the max(escapeFreq) is 26 here + sum = freq + p->InitEsc + (ns > 3); + } } + { CPpmd_State *s = STATS(c) + ns1; - SetSuccessor(s, successor); + UInt32 cf = 2 * (sum + 6) * (UInt32)p->FoundState->Freq; + UInt32 sf = (UInt32)s0 + sum; s->Symbol = p->FoundState->Symbol; - s->Freq = (Byte)cf; c->NumStats = (UInt16)(ns1 + 1); + SetSuccessor(s, maxSuccessor); + + if (cf < 6 * sf) + { + cf = (UInt32)1 + (cf > sf) + (cf >= 4 * sf); + sum += 3; + /* It can add (0, 1, 2) to Escape_Freq */ + } + else + { + cf = (UInt32)4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); + sum += cf; + } + + c->Union2.SummFreq = (UInt16)sum; + s->Freq = (Byte)cf; } + c = SUFFIX(c); } - p->MaxContext = p->MinContext = CTX(fSuccessor); + while (c != mc); } + + +MY_NO_INLINE static void Rescale(CPpmd7 *p) { unsigned i, adder, sumFreq, escFreq; CPpmd_State *stats = STATS(p->MinContext); CPpmd_State *s = p->FoundState; + + /* Sort the list by Freq */ + if (s != stats) { CPpmd_State tmp = *s; - for (; s != stats; s--) + do s[0] = s[-1]; + while (--s != stats); *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; + escFreq = p->MinContext->Union2.SummFreq - sumFreq; + + /* + if (p->OrderFall == 0), adder = 0 : it's allowed to remove symbol from MAX Order context + if (p->OrderFall != 0), adder = 1 : it's NOT allowed to remove symbol from NON-MAX Order context + */ + + adder = (p->OrderFall != 0); + + #ifdef PPMD7_ORDER_0_SUPPPORT + adder |= (p->MaxOrder == 0); // we don't remove symbols from order-0 context + #endif + + sumFreq = (sumFreq + 4 + adder) >> 1; + i = (unsigned)p->MinContext->NumStats - 1; + s->Freq = (Byte)sumFreq; - 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) + unsigned freq = (++s)->Freq; + escFreq -= freq; + freq = (freq + adder) >> 1; + sumFreq += freq; + s->Freq = (Byte)freq; + if (freq > s[-1].Freq) { + CPpmd_State tmp = *s; CPpmd_State *s1 = s; - CPpmd_State tmp = *s1; do + { s1[0] = s1[-1]; - while (--s1 != stats && tmp.Freq > s1[-1].Freq); + } + while (--s1 != stats && freq > s1[-1].Freq); *s1 = tmp; } } @@ -608,47 +853,89 @@ static void Rescale(CPpmd7 *p) if (s->Freq == 0) { - unsigned numStats = p->MinContext->NumStats; - unsigned n0, n1; - do { i++; } while ((--s)->Freq == 0); + /* Remove all items with Freq == 0 */ + CPpmd7_Context *mc; + unsigned numStats, numStatsNew, n0, n1; + + i = 0; do { i++; } while ((--s)->Freq == 0); + + /* We increase (escFreq) for the number of removed symbols. + So we will have (0.5) increase for Escape_Freq in avarage per + removed symbol after Escape_Freq halving */ escFreq += i; - p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i); - if (p->MinContext->NumStats == 1) + mc = p->MinContext; + numStats = mc->NumStats; + numStatsNew = numStats - i; + mc->NumStats = (UInt16)(numStatsNew); + n0 = (numStats + 1) >> 1; + + if (numStatsNew == 1) { - CPpmd_State tmp = *stats; + /* Create Single-Symbol context */ + unsigned freq = stats->Freq; + do { - tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); escFreq >>= 1; + freq = (freq + 1) >> 1; } while (escFreq > 1); - InsertNode(p, stats, U2I(((numStats + 1) >> 1))); - *(p->FoundState = ONE_STATE(p->MinContext)) = tmp; + + s = ONE_STATE(mc); + *s = *stats; + s->Freq = (Byte)freq; // (freq <= 260 / 4) + p->FoundState = s; + InsertNode(p, stats, U2I(n0)); return; } - n0 = (numStats + 1) >> 1; - n1 = (p->MinContext->NumStats + 1) >> 1; + + n1 = (numStatsNew + 1) >> 1; if (n0 != n1) - p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); + { + // p->MinContext->Union4.Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); + unsigned i0 = U2I(n0); + unsigned i1 = U2I(n1); + if (i0 != i1) + { + if (p->FreeList[i1] != 0) + { + void *ptr = RemoveNode(p, i1); + p->MinContext->Union4.Stats = STATS_REF(ptr); + MyMem12Cpy(ptr, (const void *)stats, n1); + InsertNode(p, stats, i0); + } + else + SplitBlock(p, stats, i0, i1); + } + } + } + { + CPpmd7_Context *mc = p->MinContext; + mc->Union2.SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); + // Escape_Freq halving here + p->FoundState = STATS(mc); } - 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) + const CPpmd7_Context *mc = p->MinContext; + unsigned numStats = mc->NumStats; + if (numStats != 256) { - see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] + - (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) + - 2 * (unsigned)(p->MinContext->SummFreq < 11 * p->MinContext->NumStats) + - 4 * (unsigned)(numMasked > nonMasked) + + unsigned nonMasked = numStats - numMasked; + see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] + + (nonMasked < (unsigned)SUFFIX(mc)->NumStats - numStats) + + 2 * (unsigned)(mc->Union2.SummFreq < 11 * numStats) + + 4 * (unsigned)(numMasked > nonMasked) + p->HiBitsFlag; { - unsigned r = (see->Summ >> see->Shift); - see->Summ = (UInt16)(see->Summ - r); + // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ + unsigned summ = (UInt16)see->Summ; // & 0xFFFF + unsigned r = (summ >> see->Shift); + see->Summ = (UInt16)(summ - r); *escFreq = r + (r == 0); } } @@ -660,53 +947,158 @@ CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq) 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; + if (p->OrderFall == 0 && (const Byte *)c > p->Text) + p->MaxContext = p->MinContext = c; else - UpdateModel(p); + Ppmd7_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) + unsigned freq = s->Freq; + freq += 4; + p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4); + s->Freq = (Byte)freq; + if (freq > s[-1].Freq) { - SwapStates(&s[0], &s[-1]); + SwapStates(s); p->FoundState = --s; - if (s->Freq > MAX_FREQ) + if (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) + CPpmd_State *s = p->FoundState; + CPpmd7_Context *mc = p->MinContext; + unsigned freq = s->Freq; + unsigned summFreq = mc->Union2.SummFreq; + p->PrevSuccess = (2 * freq > summFreq); + p->RunLength += (int)p->PrevSuccess; + mc->Union2.SummFreq = (UInt16)(summFreq + 4); + freq += 4; + s->Freq = (Byte)freq; + if (freq > MAX_FREQ) Rescale(p); NextContext(p); } + +/* void Ppmd7_UpdateBin(CPpmd7 *p) { - p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0)); + unsigned freq = p->FoundState->Freq; + p->FoundState->Freq = (Byte)(freq + (freq < 128)); 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); + CPpmd_State *s = p->FoundState; + unsigned freq = s->Freq; + freq += 4; p->RunLength = p->InitRL; - UpdateModel(p); + p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4); + s->Freq = (Byte)freq; + if (freq > MAX_FREQ) + Rescale(p); + Ppmd7_UpdateModel(p); } + + + +/* +PPMd Memory Map: +{ + [ 0 ] contains subset of original raw text, that is required to create context + records, Some symbols are not written, when max order context was reached + [ Text ] free area + [ UnitsStart ] CPpmd_State vectors and CPpmd7_Context records + [ LoUnit ] free area for CPpmd_State and CPpmd7_Context items +[ HiUnit ] CPpmd7_Context records + [ Size ] end of array +} + +These addresses don't cross at any time. +And the following condtions is true for addresses: + (0 <= Text < UnitsStart <= LoUnit <= HiUnit <= Size) + +Raw text is BYTE--aligned. +the data in block [ UnitsStart ... Size ] contains 12-bytes aligned UNITs. + +Last UNIT of array at offset (Size - 12) is root order-0 CPpmd7_Context record. +The code can free UNITs memory blocks that were allocated to store CPpmd_State vectors. +The code doesn't free UNITs allocated for CPpmd7_Context records. + +The code calls RestartModel(), when there is no free memory for allocation. +And RestartModel() changes the state to orignal start state, with full free block. + + +The code allocates UNITs with the following order: + +Allocation of 1 UNIT for Context record + - from free space (HiUnit) down to (LoUnit) + - from FreeList[0] + - AllocUnitsRare() + +AllocUnits() for CPpmd_State vectors: + - from FreeList[i] + - from free space (LoUnit) up to (HiUnit) + - AllocUnitsRare() + +AllocUnitsRare() + - if (GlueCount == 0) + { Glue lists, GlueCount = 255, allocate from FreeList[i]] } + - loop for all higher sized FreeList[...] lists + - from (UnitsStart - Text), GlueCount-- + - ERROR + + +Each Record with Context contains the CPpmd_State vector, where each +CPpmd_State contains the link to Successor. +There are 3 types of Successor: + 1) NULL-Successor - NULL pointer. NULL-Successor links can be stored + only in 0-order Root Context Record. + We use 0 value as NULL-Successor + 2) RAW-Successor - the link to position in raw text, + that "RAW-Successor" is being created after first + occurrence of new symbol for some existing context record. + (RAW-Successor > 0). + 3) RECORD-Successor - the link to CPpmd7_Context record of (Order+1), + that record is being created when we go via RAW-Successor again. + +For any successors at any time: the following condtions are true for Successor links: +(NULL-Successor < RAW-Successor < UnitsStart <= RECORD-Successor) + + +---------- Symbol Frequency, SummFreq and Range in Range_Coder ---------- + +CPpmd7_Context::SummFreq = Sum(Stats[].Freq) + Escape_Freq + +The PPMd code tries to fulfill the condition: + (SummFreq <= (256 * 128 = RC::kBot)) + +We have (Sum(Stats[].Freq) <= 256 * 124), because of (MAX_FREQ = 124) +So (4 = 128 - 124) is average reserve for Escape_Freq for each symbol. +If (CPpmd_State::Freq) is not aligned for 4, the reserve can be 5, 6 or 7. +SummFreq and Escape_Freq can be changed in Rescale() and *Update*() functions. +Rescale() can remove symbols only from max-order contexts. So Escape_Freq can increase after multiple calls of Rescale() for +max-order context. + +When the PPMd code still break (Total <= RC::Range) condition in range coder, +we have two ways to resolve that problem: + 1) we can report error, if we want to keep compatibility with original PPMd code that has no fix for such cases. + 2) we can reduce (Total) value to (RC::Range) by reducing (Escape_Freq) part of (Total) value. +*/ diff --git a/libraries/lzma/C/Ppmd7.h b/libraries/lzma/C/Ppmd7.h index 610539a04..d31809aeb 100644 --- a/libraries/lzma/C/Ppmd7.h +++ b/libraries/lzma/C/Ppmd7.h @@ -1,10 +1,8 @@ -/* Ppmd7.h -- PPMdH compression codec -2018-07-04 : 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 */ +/* Ppmd7.h -- Ppmd7 (PPMdH) compression codec +2021-04-13 : Igor Pavlov : Public domain +This code is based on: + PPMd var.H (2001): Dmitry Shkarin : Public domain */ + #ifndef __PPMD7_H #define __PPMD7_H @@ -21,23 +19,56 @@ EXTERN_C_BEGIN struct CPpmd7_Context_; -typedef - #ifdef PPMD_32BIT - struct CPpmd7_Context_ * - #else - UInt32 - #endif - CPpmd7_Context_Ref; +typedef Ppmd_Ref_Type(struct CPpmd7_Context_) CPpmd7_Context_Ref; + +// MY_CPU_pragma_pack_push_1 typedef struct CPpmd7_Context_ { UInt16 NumStats; - UInt16 SummFreq; - CPpmd_State_Ref Stats; + + + union + { + UInt16 SummFreq; + CPpmd_State2 State2; + } Union2; + + union + { + CPpmd_State_Ref Stats; + CPpmd_State4 State4; + } Union4; + CPpmd7_Context_Ref Suffix; } CPpmd7_Context; -#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq) +// MY_CPU_pragma_pop + +#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->Union2) + + + + +typedef struct +{ + UInt32 Range; + UInt32 Code; + UInt32 Low; + IByteIn *Stream; +} CPpmd7_RangeDec; + + +typedef struct +{ + UInt32 Range; + Byte Cache; + // Byte _dummy_[3]; + UInt64 Low; + UInt64 CacheSize; + IByteOut *Stream; +} CPpmd7z_RangeEnc; + typedef struct { @@ -48,17 +79,30 @@ typedef struct UInt32 Size; UInt32 GlueCount; - Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart; UInt32 AlignOffset; + Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart; - Byte Indx2Units[PPMD_NUM_INDEXES]; + + + + union + { + CPpmd7_RangeDec dec; + CPpmd7z_RangeEnc enc; + } rc; + + Byte Indx2Units[PPMD_NUM_INDEXES + 2]; // +2 for alignment Byte Units2Indx[128]; CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES]; - Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256]; + + Byte NS2BSIndx[256], NS2Indx[256]; + Byte ExpEscape[16]; CPpmd_See DummySee, See[25][16]; UInt16 BinSumm[128][64]; + // int LastSymbol; } CPpmd7; + void Ppmd7_Construct(CPpmd7 *p); BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc); void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc); @@ -68,74 +112,69 @@ void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder); /* ---------- 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 +#define Ppmd7_GetPtr(p, ptr) Ppmd_GetPtr(p, ptr) +#define Ppmd7_GetContext(p, ptr) Ppmd_GetPtr_Type(p, ptr, CPpmd7_Context) +#define Ppmd7_GetStats(p, ctx) Ppmd_GetPtr_Type(p, (ctx)->Union4.Stats, CPpmd_State) void Ppmd7_Update1(CPpmd7 *p); void Ppmd7_Update1_0(CPpmd7 *p); void Ppmd7_Update2(CPpmd7 *p); -void Ppmd7_UpdateBin(CPpmd7 *p); + +#define PPMD7_HiBitsFlag_3(sym) ((((unsigned)sym + 0xC0) >> (8 - 3)) & (1 << 3)) +#define PPMD7_HiBitsFlag_4(sym) ((((unsigned)sym + 0xC0) >> (8 - 4)) & (1 << 4)) +// #define PPMD7_HiBitsFlag_3(sym) ((sym) < 0x40 ? 0 : (1 << 3)) +// #define PPMD7_HiBitsFlag_4(sym) ((sym) < 0x40 ? 0 : (1 << 4)) #define Ppmd7_GetBinSumm(p) \ - &p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \ - p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \ - (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \ - 2 * p->HB2Flag[(unsigned)Ppmd7Context_OneState(p->MinContext)->Symbol] + \ - ((p->RunLength >> 26) & 0x20)] + &p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1] \ + [ p->PrevSuccess + ((p->RunLength >> 26) & 0x20) \ + + p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] \ + + PPMD7_HiBitsFlag_4(Ppmd7Context_OneState(p->MinContext)->Symbol) \ + + (p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol)) ] CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale); +/* +We support two versions of Ppmd7 (PPMdH) methods that use same CPpmd7 structure: + 1) Ppmd7a_*: original PPMdH + 2) Ppmd7z_*: modified PPMdH with 7z Range Coder +Ppmd7_*: the structures and functions that are common for both versions of PPMd7 (PPMdH) +*/ + /* ---------- Decode ---------- */ -typedef struct IPpmd7_RangeDec IPpmd7_RangeDec; +#define PPMD7_SYM_END (-1) +#define PPMD7_SYM_ERROR (-2) -struct IPpmd7_RangeDec -{ - UInt32 (*GetThreshold)(const IPpmd7_RangeDec *p, UInt32 total); - void (*Decode)(const IPpmd7_RangeDec *p, UInt32 start, UInt32 size); - UInt32 (*DecodeBit)(const IPpmd7_RangeDec *p, UInt32 size0); -}; +/* +You must set (CPpmd7::rc.dec.Stream) before Ppmd7*_RangeDec_Init() -typedef struct -{ - IPpmd7_RangeDec vt; - UInt32 Range; - UInt32 Code; - IByteIn *Stream; -} CPpmd7z_RangeDec; +Ppmd7*_DecodeSymbol() +out: + >= 0 : decoded byte + -1 : PPMD7_SYM_END : End of payload marker + -2 : PPMD7_SYM_ERROR : Data error +*/ -void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p); -BoolInt Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p); +/* Ppmd7a_* : original PPMdH */ +BoolInt Ppmd7a_RangeDec_Init(CPpmd7_RangeDec *p); +#define Ppmd7a_RangeDec_IsFinishedOK(p) ((p)->Code == 0) +int Ppmd7a_DecodeSymbol(CPpmd7 *p); + +/* Ppmd7z_* : modified PPMdH with 7z Range Coder */ +BoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p); #define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0) - -int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc); +int Ppmd7z_DecodeSymbol(CPpmd7 *p); +// Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim); /* ---------- 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); +void Ppmd7z_Init_RangeEnc(CPpmd7 *p); +void Ppmd7z_Flush_RangeEnc(CPpmd7 *p); +// void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol); +void Ppmd7z_EncodeSymbols(CPpmd7 *p, const Byte *buf, const Byte *lim); EXTERN_C_END diff --git a/libraries/lzma/C/Ppmd7Dec.c b/libraries/lzma/C/Ppmd7Dec.c index 311e9f9dd..55d74ff9d 100644 --- a/libraries/lzma/C/Ppmd7Dec.c +++ b/libraries/lzma/C/Ppmd7Dec.c @@ -1,6 +1,8 @@ -/* Ppmd7Dec.c -- PPMdH Decoder -2018-07-04 : Igor Pavlov : Public domain -This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ +/* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder +2021-04-13 : Igor Pavlov : Public domain +This code is based on: + PPMd var.H (2001): Dmitry Shkarin : Public domain */ + #include "Precomp.h" @@ -8,184 +10,288 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #define kTopValue (1 << 24) -BoolInt Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p) + +#define READ_BYTE(p) IByteIn_Read((p)->Stream) + +BoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p) { unsigned i; p->Code = 0; p->Range = 0xFFFFFFFF; - if (IByteIn_Read(p->Stream) != 0) + if (READ_BYTE(p) != 0) return False; for (i = 0; i < 4; i++) - p->Code = (p->Code << 8) | IByteIn_Read(p->Stream); + p->Code = (p->Code << 8) | READ_BYTE(p); return (p->Code < 0xFFFFFFFF); } -#define GET_Ppmd7z_RangeDec CPpmd7z_RangeDec *p = CONTAINER_FROM_VTBL(pp, CPpmd7z_RangeDec, vt); - -static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total) +#define RC_NORM_BASE(p) if ((p)->Range < kTopValue) \ + { (p)->Code = ((p)->Code << 8) | READ_BYTE(p); (p)->Range <<= 8; + +#define RC_NORM_1(p) RC_NORM_BASE(p) } +#define RC_NORM(p) RC_NORM_BASE(p) RC_NORM_BASE(p) }} + +// we must use only one type of Normalization from two: LOCAL or REMOTE +#define RC_NORM_LOCAL(p) // RC_NORM(p) +#define RC_NORM_REMOTE(p) RC_NORM(p) + +#define R (&p->rc.dec) + +MY_FORCE_INLINE +// MY_NO_INLINE +static void RangeDec_Decode(CPpmd7 *p, UInt32 start, UInt32 size) { - GET_Ppmd7z_RangeDec - return p->Code / (p->Range /= total); + + + R->Code -= start * R->Range; + R->Range *= size; + RC_NORM_LOCAL(R) } -static void Range_Normalize(CPpmd7z_RangeDec *p) -{ - if (p->Range < kTopValue) - { - p->Code = (p->Code << 8) | IByteIn_Read(p->Stream); - p->Range <<= 8; - if (p->Range < kTopValue) - { - p->Code = (p->Code << 8) | IByteIn_Read(p->Stream); - p->Range <<= 8; - } - } -} - -static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size) -{ - GET_Ppmd7z_RangeDec - p->Code -= start * p->Range; - p->Range *= size; - Range_Normalize(p); -} - -static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0) -{ - GET_Ppmd7z_RangeDec - 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->vt.GetThreshold = Range_GetThreshold; - p->vt.Decode = Range_Decode; - p->vt.DecodeBit = Range_DecodeBit; -} +#define RC_Decode(start, size) RangeDec_Decode(p, start, size); +#define RC_DecodeFinal(start, size) RC_Decode(start, size) RC_NORM_REMOTE(R) +#define RC_GetThreshold(total) (R->Code / (R->Range /= (total))) -#define MASK(sym) ((signed char *)charMask)[sym] +#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) +typedef CPpmd7_Context * CTX_PTR; +#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) +void Ppmd7_UpdateModel(CPpmd7 *p); -int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc) +#define MASK(sym) ((unsigned char *)charMask)[sym] +// MY_FORCE_INLINE +// static +int Ppmd7z_DecodeSymbol(CPpmd7 *p) { 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)) + UInt32 summFreq = p->MinContext->Union2.SummFreq; + + + + + count = RC_GetThreshold(summFreq); + hiCnt = count; + + if ((Int32)(count -= s->Freq) < 0) { - Byte symbol; - rc->Decode(rc, 0, s->Freq); + Byte sym; + RC_DecodeFinal(0, s->Freq); p->FoundState = s; - symbol = s->Symbol; + sym = s->Symbol; Ppmd7_Update1_0(p); - return symbol; + return sym; } + p->PrevSuccess = 0; - i = p->MinContext->NumStats - 1; + i = (unsigned)p->MinContext->NumStats - 1; + do { - if ((hiCnt += (++s)->Freq) > count) + if ((Int32)(count -= (++s)->Freq) < 0) { - Byte symbol; - rc->Decode(rc, hiCnt - s->Freq, s->Freq); + Byte sym; + RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq); p->FoundState = s; - symbol = s->Symbol; + sym = s->Symbol; Ppmd7_Update1(p); - return symbol; + return sym; } } while (--i); - if (count >= p->MinContext->SummFreq) - return -2; - p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; - rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt); + + if (hiCnt >= summFreq) + return PPMD7_SYM_ERROR; + + hiCnt -= count; + RC_Decode(hiCnt, summFreq - hiCnt); + + p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol); PPMD_SetAllBitsIn256Bytes(charMask); - MASK(s->Symbol) = 0; - i = p->MinContext->NumStats - 1; - do { MASK((--s)->Symbol) = 0; } while (--i); + // i = p->MinContext->NumStats - 1; + // do { MASK((--s)->Symbol) = 0; } while (--i); + { + CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext); + MASK(s->Symbol) = 0; + do + { + unsigned sym0 = s2[0].Symbol; + unsigned sym1 = s2[1].Symbol; + s2 += 2; + MASK(sym0) = 0; + MASK(sym1) = 0; + } + while (s2 < s); + } } else { + CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); UInt16 *prob = Ppmd7_GetBinSumm(p); - if (rc->DecodeBit(rc, *prob) == 0) + UInt32 pr = *prob; + UInt32 size0 = (R->Range >> 14) * pr; + pr = PPMD_UPDATE_PROB_1(pr); + + if (R->Code < size0) { - Byte symbol; - *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); - symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol; - Ppmd7_UpdateBin(p); - return symbol; + Byte sym; + *prob = (UInt16)(pr + (1 << PPMD_INT_BITS)); + + // RangeDec_DecodeBit0(size0); + R->Range = size0; + RC_NORM_1(R) + /* we can use single byte normalization here because of + (min(BinSumm[][]) = 95) > (1 << (14 - 8)) */ + + // sym = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol; + // Ppmd7_UpdateBin(p); + { + unsigned freq = s->Freq; + CTX_PTR c = CTX(SUCCESSOR(s)); + sym = s->Symbol; + p->FoundState = s; + p->PrevSuccess = 1; + p->RunLength++; + s->Freq = (Byte)(freq + (freq < 128)); + // NextContext(p); + if (p->OrderFall == 0 && (const Byte *)c > p->Text) + p->MaxContext = p->MinContext = c; + else + Ppmd7_UpdateModel(p); + } + return sym; } - *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); - p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; + + *prob = (UInt16)pr; + p->InitEsc = p->ExpEscape[pr >> 10]; + + // RangeDec_DecodeBit1(size0); + + R->Code -= size0; + R->Range -= size0; + RC_NORM_LOCAL(R) + PPMD_SetAllBitsIn256Bytes(charMask); MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0; p->PrevSuccess = 0; } + for (;;) { - CPpmd_State *ps[256], *s; + CPpmd_State *s, *s2; UInt32 freqSum, count, hiCnt; + CPpmd_See *see; - unsigned i, num, numMasked = p->MinContext->NumStats; + CPpmd7_Context *mc; + unsigned numMasked; + RC_NORM_REMOTE(R) + mc = p->MinContext; + numMasked = mc->NumStats; + do { p->OrderFall++; - if (!p->MinContext->Suffix) - return -1; - p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); + if (!mc->Suffix) + return PPMD7_SYM_END; + mc = Ppmd7_GetContext(p, mc->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); + while (mc->NumStats == numMasked); + s = Ppmd7_GetStats(p, mc); + + { + unsigned num = mc->NumStats; + unsigned num2 = num / 2; + + num &= 1; + hiCnt = (s->Freq & (unsigned)(MASK(s->Symbol))) & (0 - (UInt32)num); + s += num; + p->MinContext = mc; + + do + { + unsigned sym0 = s[0].Symbol; + unsigned sym1 = s[1].Symbol; + s += 2; + hiCnt += (s[-2].Freq & (unsigned)(MASK(sym0))); + hiCnt += (s[-1].Freq & (unsigned)(MASK(sym1))); + } + while (--num2); + } + see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum); freqSum += hiCnt; - count = rc->GetThreshold(rc, freqSum); + + + + + count = RC_GetThreshold(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); + Byte sym; + + s = Ppmd7_GetStats(p, p->MinContext); + hiCnt = count; + // count -= s->Freq & (unsigned)(MASK(s->Symbol)); + // if ((Int32)count >= 0) + { + for (;;) + { + count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; + // count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; + }; + } + s--; + RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq); + + // new (see->Summ) value can overflow over 16-bits in some rare cases Ppmd_See_Update(see); p->FoundState = s; - symbol = s->Symbol; + sym = s->Symbol; Ppmd7_Update2(p); - return symbol; + return sym; } + if (count >= freqSum) - return -2; - rc->Decode(rc, hiCnt, freqSum - hiCnt); + return PPMD7_SYM_ERROR; + + RC_Decode(hiCnt, freqSum - hiCnt); + + // We increase (see->Summ) for sum of Freqs of all non_Masked symbols. + // new (see->Summ) value can overflow over 16-bits in some rare cases see->Summ = (UInt16)(see->Summ + freqSum); - do { MASK(ps[--i]->Symbol) = 0; } while (i != 0); + + s = Ppmd7_GetStats(p, p->MinContext); + s2 = s + p->MinContext->NumStats; + do + { + MASK(s->Symbol) = 0; + s++; + } + while (s != s2); } } + +/* +Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim) +{ + int sym = 0; + if (buf != lim) + do + { + sym = Ppmd7z_DecodeSymbol(p); + if (sym < 0) + break; + *buf = (Byte)sym; + } + while (++buf < lim); + p->LastSymbol = sym; + return buf; +} +*/ diff --git a/libraries/lzma/C/Threads.c b/libraries/lzma/C/Threads.c index 930ad271b..58eb90ffa 100644 --- a/libraries/lzma/C/Threads.c +++ b/libraries/lzma/C/Threads.c @@ -1,9 +1,11 @@ /* Threads.c -- multithreading library -2017-06-26 : Igor Pavlov : Public domain */ +2021-12-21 : Igor Pavlov : Public domain */ #include "Precomp.h" -#ifndef UNDER_CE +#ifdef _WIN32 + +#ifndef USE_THREADS_CreateThread #include #endif @@ -29,28 +31,103 @@ WRes HandlePtr_Close(HANDLE *p) return 0; } -WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); } +WRes Handle_WaitObject(HANDLE h) +{ + DWORD dw = WaitForSingleObject(h, INFINITE); + /* + (dw) result: + WAIT_OBJECT_0 // 0 + WAIT_ABANDONED // 0x00000080 : is not compatible with Win32 Error space + WAIT_TIMEOUT // 0x00000102 : is compatible with Win32 Error space + WAIT_FAILED // 0xFFFFFFFF + */ + if (dw == WAIT_FAILED) + { + dw = GetLastError(); + if (dw == 0) + return WAIT_FAILED; + } + return (WRes)dw; +} + +#define Thread_Wait(p) Handle_WaitObject(*(p)) + +WRes Thread_Wait_Close(CThread *p) +{ + WRes res = Thread_Wait(p); + WRes res2 = Thread_Close(p); + return (res != 0 ? res : res2); +} WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) { /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ - - #ifdef UNDER_CE - + + #ifdef USE_THREADS_CreateThread + DWORD threadId; - *p = CreateThread(0, 0, func, param, 0, &threadId); - + *p = CreateThread(NULL, 0, func, param, 0, &threadId); + #else - + unsigned threadId; - *p = (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &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); } + +WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) +{ + #ifdef USE_THREADS_CreateThread + + UNUSED_VAR(affinity) + return Thread_Create(p, func, param); + + #else + + /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ + HANDLE h; + WRes wres; + unsigned threadId; + h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId)); + *p = h; + wres = HandleToWRes(h); + if (h) + { + { + // DWORD_PTR prevMask = + SetThreadAffinityMask(h, (DWORD_PTR)affinity); + /* + if (prevMask == 0) + { + // affinity change is non-critical error, so we can ignore it + // wres = GetError(); + } + */ + } + { + DWORD prevSuspendCount = ResumeThread(h); + /* ResumeThread() returns: + 0 : was_not_suspended + 1 : was_resumed + -1 : error + */ + if (prevSuspendCount == (DWORD)-1) + wres = GetError(); + } + } + + /* maybe we must use errno here, but probably GetLastError() is also OK. */ + return wres; + + #endif +} + + static WRes Event_Create(CEvent *p, BOOL manualReset, int signaled) { *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL); @@ -68,10 +145,22 @@ WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEven WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) { + // negative ((LONG)maxCount) is not supported in WIN32::CreateSemaphore() *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL); return HandleToWRes(*p); } +WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount) +{ + // if (Semaphore_IsCreated(p)) + { + WRes wres = Semaphore_Close(p); + if (wres != 0) + return wres; + } + return Semaphore_Create(p, initCount, maxCount); +} + static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); } WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num) @@ -80,7 +169,9 @@ WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } WRes CriticalSection_Init(CCriticalSection *p) { - /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ + /* InitializeCriticalSection() can raise exception: + Windows XP, 2003 : can raise a STATUS_NO_MEMORY exception + Windows Vista+ : no exceptions */ #ifdef _MSC_VER __try #endif @@ -89,7 +180,361 @@ WRes CriticalSection_Init(CCriticalSection *p) /* InitializeCriticalSectionAndSpinCount(p, 0); */ } #ifdef _MSC_VER - __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } + __except (EXCEPTION_EXECUTE_HANDLER) { return ERROR_NOT_ENOUGH_MEMORY; } #endif return 0; } + + + + +#else // _WIN32 + +// ---------- POSIX ---------- + +#ifndef __APPLE__ +#ifndef _7ZIP_AFFINITY_DISABLE +// _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET +#define _GNU_SOURCE +#endif +#endif + +#include "Threads.h" + +#include +#include +#include +#ifdef _7ZIP_AFFINITY_SUPPORTED +// #include +#endif + + +// #include +// #define PRF(p) p +#define PRF(p) + +#define Print(s) PRF(printf("\n%s\n", s)) + +// #include + +WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet) +{ + // new thread in Posix probably inherits affinity from parrent thread + Print("Thread_Create_With_CpuSet"); + + pthread_attr_t attr; + int ret; + // int ret2; + + p->_created = 0; + + RINOK(pthread_attr_init(&attr)); + + ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + if (!ret) + { + if (cpuSet) + { + #ifdef _7ZIP_AFFINITY_SUPPORTED + + /* + printf("\n affinity :"); + unsigned i; + for (i = 0; i < sizeof(*cpuSet) && i < 8; i++) + { + Byte b = *((const Byte *)cpuSet + i); + char temp[32]; + #define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) + temp[0] = GET_HEX_CHAR((b & 0xF)); + temp[1] = GET_HEX_CHAR((b >> 4)); + // temp[0] = GET_HEX_CHAR((b >> 4)); // big-endian + // temp[1] = GET_HEX_CHAR((b & 0xF)); // big-endian + temp[2] = 0; + printf("%s", temp); + } + printf("\n"); + */ + + // ret2 = + pthread_attr_setaffinity_np(&attr, sizeof(*cpuSet), cpuSet); + // if (ret2) ret = ret2; + #endif + } + + ret = pthread_create(&p->_tid, &attr, func, param); + + if (!ret) + { + p->_created = 1; + /* + if (cpuSet) + { + // ret2 = + pthread_setaffinity_np(p->_tid, sizeof(*cpuSet), cpuSet); + // if (ret2) ret = ret2; + } + */ + } + } + // ret2 = + pthread_attr_destroy(&attr); + // if (ret2 != 0) ret = ret2; + return ret; +} + + +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) +{ + return Thread_Create_With_CpuSet(p, func, param, NULL); +} + + +WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) +{ + Print("Thread_Create_WithAffinity"); + CCpuSet cs; + unsigned i; + CpuSet_Zero(&cs); + for (i = 0; i < sizeof(affinity) * 8; i++) + { + if (affinity == 0) + break; + if (affinity & 1) + { + CpuSet_Set(&cs, i); + } + affinity >>= 1; + } + return Thread_Create_With_CpuSet(p, func, param, &cs); +} + + +WRes Thread_Close(CThread *p) +{ + // Print("Thread_Close"); + int ret; + if (!p->_created) + return 0; + + ret = pthread_detach(p->_tid); + p->_tid = 0; + p->_created = 0; + return ret; +} + + +WRes Thread_Wait_Close(CThread *p) +{ + // Print("Thread_Wait_Close"); + void *thread_return; + int ret; + if (!p->_created) + return EINVAL; + + ret = pthread_join(p->_tid, &thread_return); + // probably we can't use that (_tid) after pthread_join(), so we close thread here + p->_created = 0; + p->_tid = 0; + return ret; +} + + + +static WRes Event_Create(CEvent *p, int manualReset, int signaled) +{ + RINOK(pthread_mutex_init(&p->_mutex, NULL)); + RINOK(pthread_cond_init(&p->_cond, NULL)); + p->_manual_reset = manualReset; + p->_state = (signaled ? True : False); + p->_created = 1; + return 0; +} + +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) + { return Event_Create(p, True, signaled); } +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) + { return ManualResetEvent_Create(p, 0); } +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) + { return Event_Create(p, False, signaled); } +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) + { return AutoResetEvent_Create(p, 0); } + + +WRes Event_Set(CEvent *p) +{ + RINOK(pthread_mutex_lock(&p->_mutex)); + p->_state = True; + int res1 = pthread_cond_broadcast(&p->_cond); + int res2 = pthread_mutex_unlock(&p->_mutex); + return (res2 ? res2 : res1); +} + +WRes Event_Reset(CEvent *p) +{ + RINOK(pthread_mutex_lock(&p->_mutex)); + p->_state = False; + return pthread_mutex_unlock(&p->_mutex); +} + +WRes Event_Wait(CEvent *p) +{ + RINOK(pthread_mutex_lock(&p->_mutex)); + while (p->_state == False) + { + // ETIMEDOUT + // ret = + pthread_cond_wait(&p->_cond, &p->_mutex); + // if (ret != 0) break; + } + if (p->_manual_reset == False) + { + p->_state = False; + } + return pthread_mutex_unlock(&p->_mutex); +} + +WRes Event_Close(CEvent *p) +{ + if (!p->_created) + return 0; + p->_created = 0; + { + int res1 = pthread_mutex_destroy(&p->_mutex); + int res2 = pthread_cond_destroy(&p->_cond); + return (res1 ? res1 : res2); + } +} + + +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) +{ + if (initCount > maxCount || maxCount < 1) + return EINVAL; + RINOK(pthread_mutex_init(&p->_mutex, NULL)); + RINOK(pthread_cond_init(&p->_cond, NULL)); + p->_count = initCount; + p->_maxCount = maxCount; + p->_created = 1; + return 0; +} + + +WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount) +{ + if (Semaphore_IsCreated(p)) + { + /* + WRes wres = Semaphore_Close(p); + if (wres != 0) + return wres; + */ + if (initCount > maxCount || maxCount < 1) + return EINVAL; + // return EINVAL; // for debug + p->_count = initCount; + p->_maxCount = maxCount; + return 0; + } + return Semaphore_Create(p, initCount, maxCount); +} + + +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) +{ + UInt32 newCount; + int ret; + + if (releaseCount < 1) + return EINVAL; + + RINOK(pthread_mutex_lock(&p->_mutex)); + + newCount = p->_count + releaseCount; + if (newCount > p->_maxCount) + ret = ERROR_TOO_MANY_POSTS; // EINVAL; + else + { + p->_count = newCount; + ret = pthread_cond_broadcast(&p->_cond); + } + RINOK(pthread_mutex_unlock(&p->_mutex)); + return ret; +} + +WRes Semaphore_Wait(CSemaphore *p) +{ + RINOK(pthread_mutex_lock(&p->_mutex)); + while (p->_count < 1) + { + pthread_cond_wait(&p->_cond, &p->_mutex); + } + p->_count--; + return pthread_mutex_unlock(&p->_mutex); +} + +WRes Semaphore_Close(CSemaphore *p) +{ + if (!p->_created) + return 0; + p->_created = 0; + { + int res1 = pthread_mutex_destroy(&p->_mutex); + int res2 = pthread_cond_destroy(&p->_cond); + return (res1 ? res1 : res2); + } +} + + + +WRes CriticalSection_Init(CCriticalSection *p) +{ + // Print("CriticalSection_Init"); + if (!p) + return EINTR; + return pthread_mutex_init(&p->_mutex, NULL); +} + +void CriticalSection_Enter(CCriticalSection *p) +{ + // Print("CriticalSection_Enter"); + if (p) + { + // int ret = + pthread_mutex_lock(&p->_mutex); + } +} + +void CriticalSection_Leave(CCriticalSection *p) +{ + // Print("CriticalSection_Leave"); + if (p) + { + // int ret = + pthread_mutex_unlock(&p->_mutex); + } +} + +void CriticalSection_Delete(CCriticalSection *p) +{ + // Print("CriticalSection_Delete"); + if (p) + { + // int ret = + pthread_mutex_destroy(&p->_mutex); + } +} + +LONG InterlockedIncrement(LONG volatile *addend) +{ + // Print("InterlockedIncrement"); + #ifdef USE_HACK_UNSAFE_ATOMIC + LONG val = *addend + 1; + *addend = val; + return val; + #else + return __sync_add_and_fetch(addend, 1); + #endif +} + +#endif // _WIN32 diff --git a/libraries/lzma/C/Threads.h b/libraries/lzma/C/Threads.h index e53ace435..89ecb92be 100644 --- a/libraries/lzma/C/Threads.h +++ b/libraries/lzma/C/Threads.h @@ -1,38 +1,139 @@ /* Threads.h -- multithreading library -2017-06-18 : Igor Pavlov : Public domain */ +2021-12-21 : Igor Pavlov : Public domain */ #ifndef __7Z_THREADS_H #define __7Z_THREADS_H #ifdef _WIN32 -#include +#include +#else + +#if defined(__linux__) +#if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__) +#ifndef _7ZIP_AFFINITY_DISABLE +#define _7ZIP_AFFINITY_SUPPORTED +// #pragma message(" ==== _7ZIP_AFFINITY_SUPPORTED") +// #define _GNU_SOURCE +#endif +#endif +#endif + +#include + #endif #include "7zTypes.h" EXTERN_C_BEGIN +#ifdef _WIN32 + WRes HandlePtr_Close(HANDLE *h); WRes Handle_WaitObject(HANDLE h); typedef HANDLE CThread; -#define Thread_Construct(p) *(p) = NULL + +#define Thread_Construct(p) { *(p) = NULL; } #define Thread_WasCreated(p) (*(p) != NULL) #define Thread_Close(p) HandlePtr_Close(p) -#define Thread_Wait(p) Handle_WaitObject(*(p)) +// #define Thread_Wait(p) Handle_WaitObject(*(p)) + +#ifdef UNDER_CE + // if (USE_THREADS_CreateThread is defined), we use _beginthreadex() + // if (USE_THREADS_CreateThread is not definned), we use CreateThread() + #define USE_THREADS_CreateThread +#endif typedef -#ifdef UNDER_CE - DWORD + #ifdef USE_THREADS_CreateThread + DWORD + #else + unsigned + #endif + THREAD_FUNC_RET_TYPE; + +typedef DWORD_PTR CAffinityMask; +typedef DWORD_PTR CCpuSet; + +#define CpuSet_Zero(p) { *(p) = 0; } +#define CpuSet_Set(p, cpu) { *(p) |= ((DWORD_PTR)1 << (cpu)); } + +#else // _WIN32 + +typedef struct _CThread +{ + pthread_t _tid; + int _created; +} CThread; + +#define Thread_Construct(p) { (p)->_tid = 0; (p)->_created = 0; } +#define Thread_WasCreated(p) ((p)->_created != 0) +WRes Thread_Close(CThread *p); +// #define Thread_Wait Thread_Wait_Close + +typedef void * THREAD_FUNC_RET_TYPE; + +typedef UInt64 CAffinityMask; + +#ifdef _7ZIP_AFFINITY_SUPPORTED + +typedef cpu_set_t CCpuSet; +#define CpuSet_Zero(p) CPU_ZERO(p) +#define CpuSet_Set(p, cpu) CPU_SET(cpu, p) +#define CpuSet_IsSet(p, cpu) CPU_ISSET(cpu, p) + #else - unsigned + +typedef UInt64 CCpuSet; +#define CpuSet_Zero(p) { *(p) = 0; } +#define CpuSet_Set(p, cpu) { *(p) |= ((UInt64)1 << (cpu)); } +#define CpuSet_IsSet(p, cpu) ((*(p) & ((UInt64)1 << (cpu))) != 0) + #endif - THREAD_FUNC_RET_TYPE; + + +#endif // _WIN32 + #define THREAD_FUNC_CALL_TYPE MY_STD_CALL -#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE + +#if defined(_WIN32) && defined(__GNUC__) +/* GCC compiler for x86 32-bit uses the rule: + the stack is 16-byte aligned before CALL instruction for function calling. + But only root function main() contains instructions that + set 16-byte alignment for stack pointer. And another functions + just keep alignment, if it was set in some parent function. + + The problem: + if we create new thread in MinGW (GCC) 32-bit x86 via _beginthreadex() or CreateThread(), + the root function of thread doesn't set 16-byte alignment. + And stack frames in all child functions also will be unaligned in that case. + + Here we set (force_align_arg_pointer) attribute for root function of new thread. + Do we need (force_align_arg_pointer) also for another systems? */ + + #define THREAD_FUNC_ATTRIB_ALIGN_ARG __attribute__((force_align_arg_pointer)) + // #define THREAD_FUNC_ATTRIB_ALIGN_ARG // for debug : bad alignment in SSE functions +#else + #define THREAD_FUNC_ATTRIB_ALIGN_ARG +#endif + +#define THREAD_FUNC_DECL THREAD_FUNC_ATTRIB_ALIGN_ARG THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE + typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *); WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param); +WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity); +WRes Thread_Wait_Close(CThread *p); + +#ifdef _WIN32 +#define Thread_Create_With_CpuSet(p, func, param, cs) \ + Thread_Create_With_Affinity(p, func, param, *cs) +#else +WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet); +#endif + + +#ifdef _WIN32 typedef HANDLE CEvent; typedef CEvent CAutoResetEvent; @@ -54,6 +155,7 @@ typedef HANDLE CSemaphore; #define Semaphore_Close(p) HandlePtr_Close(p) #define Semaphore_Wait(p) Handle_WaitObject(*(p)) WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); +WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); WRes Semaphore_Release1(CSemaphore *p); @@ -63,6 +165,68 @@ WRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) + +#else // _WIN32 + +typedef struct _CEvent +{ + int _created; + int _manual_reset; + int _state; + pthread_mutex_t _mutex; + pthread_cond_t _cond; +} CEvent; + +typedef CEvent CAutoResetEvent; +typedef CEvent CManualResetEvent; + +#define Event_Construct(p) (p)->_created = 0 +#define Event_IsCreated(p) ((p)->_created) + +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); +WRes Event_Set(CEvent *p); +WRes Event_Reset(CEvent *p); +WRes Event_Wait(CEvent *p); +WRes Event_Close(CEvent *p); + + +typedef struct _CSemaphore +{ + int _created; + UInt32 _count; + UInt32 _maxCount; + pthread_mutex_t _mutex; + pthread_cond_t _cond; +} CSemaphore; + +#define Semaphore_Construct(p) (p)->_created = 0 +#define Semaphore_IsCreated(p) ((p)->_created) + +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); +WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount); +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); +#define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1) +WRes Semaphore_Wait(CSemaphore *p); +WRes Semaphore_Close(CSemaphore *p); + + +typedef struct _CCriticalSection +{ + pthread_mutex_t _mutex; +} CCriticalSection; + +WRes CriticalSection_Init(CCriticalSection *p); +void CriticalSection_Delete(CCriticalSection *cs); +void CriticalSection_Enter(CCriticalSection *cs); +void CriticalSection_Leave(CCriticalSection *cs); + +LONG InterlockedIncrement(LONG volatile *addend); + +#endif // _WIN32 + EXTERN_C_END #endif diff --git a/libraries/lzma/CMakeLists.txt b/libraries/lzma/CMakeLists.txt index 570265049..2ef5b078f 100644 --- a/libraries/lzma/CMakeLists.txt +++ b/libraries/lzma/CMakeLists.txt @@ -4,7 +4,9 @@ make_release_only() set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_7ZIP_PPMD_SUPPPORT" ) -set( LZMA_FILES +find_package(Threads) + +add_library( lzma STATIC C/7zArcIn.c C/7zBuf.c C/7zCrc.c @@ -18,17 +20,13 @@ set( LZMA_FILES C/CpuArch.c C/Delta.c C/LzFind.c + C/LzFindMt.c + C/LzFindOpt.c C/Lzma2Dec.c C/LzmaDec.c C/LzmaEnc.c C/Ppmd7.c - C/Ppmd7Dec.c ) - -if( WIN32 ) - set( LZMA_FILES ${LZMA_FILES} C/LzFindMt.c C/Threads.c ) -else() - set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_7ZIP_ST" ) -endif() - -add_library( lzma STATIC ${LZMA_FILES} ) -target_link_libraries( lzma ) + C/Ppmd7Dec.c + C/Threads.c +) +target_link_libraries( lzma Threads::Threads ) diff --git a/libraries/lzma/DOC/lzma-history.txt b/libraries/lzma/DOC/lzma-history.txt index 48ee74813..0963c7bf7 100644 --- a/libraries/lzma/DOC/lzma-history.txt +++ b/libraries/lzma/DOC/lzma-history.txt @@ -1,6 +1,80 @@ HISTORY of the LZMA SDK ----------------------- +21.07 2021-12-26 +------------------------- +- New switches: -spm and -im!{file_path} to exclude directories from processing + for specified paths that don't contain path separator character at the end of path. +- The sorting order of files in archives was slightly changed to be more consistent + for cases where the name of some directory is the same as the prefix part of the name + of another directory or file. + + +21.06 2021-11-24 +------------------------- +- Bug in LZMA encoder in file LzmaEnc.c was fixed: + LzmaEnc_MemEncode(), LzmaEncode() and LzmaCompress() could work incorrectly, + if size value for output buffer is smaller than size required for all compressed data. + LzmaEnc_Encode() could work incorrectly, + if callback ISeqOutStream::Write() doesn't write all compressed data. + NCompress::NLzma::CEncoder::Code() could work incorrectly, + if callback ISequentialOutStream::Write() returns error code. +- Bug in versions 21.00-21.05 was fixed: + 7-Zip didn't set attributes of directories during archive extracting. + + +21.04 beta 2021-11-02 +------------------------- +- 7-Zip now reduces the number of working CPU threads for compression, + if RAM size is not enough for compression with big LZMA2 dictionary. +- 7-Zip now can create and check "file.sha256" text files that contain the list + of file names and SHA-256 checksums in format compatible with sha256sum program. + + +21.03 beta 2021-07-20 +------------------------- +- The maximum dictionary size for LZMA/LZMA2 compressing was increased to 4 GB (3840 MiB). +- Minor speed optimizations in LZMA/LZMA2 compressing. + + +21.02 alpha 2021-05-06 +------------------------- +- The command line version of 7-Zip for macOS was released. +- The speed for LZMA and LZMA2 decompression in arm64 versions for macOS and Linux + was increased by 20%-60%. + + +21.01 alpha 2021-03-09 +------------------------- +- The command line version of 7-Zip for Linux was released. +- The improvements for speed of ARM64 version using hardware CPU instructions + for AES, CRC-32, SHA-1 and SHA-256. +- Some bugs were fixed. + + +20.02 alpha 2020-08-08 +------------------------- +- The default number of LZMA2 chunks per solid block in 7z archive was increased to 64. + It allows to increase the compression speed for big 7z archives, if there is a big number + of CPU cores and threads. +- The speed of PPMd compressing/decompressing was increased for 7z archives. +- The new -ssp switch. If the switch -ssp is specified, 7-Zip doesn't allow the system + to modify "Last Access Time" property of source files for archiving and hashing operations. +- Some bugs were fixed. + + +20.00 alpha 2020-02-06 +------------------------- +- 7-Zip now supports new optional match finders for LZMA/LZMA2 compression: bt5 and hc5, + that can work faster than bt4 and hc4 match finders for the data with big redundancy. +- The compression ratio was improved for Fast and Fastest compression levels with the + following default settings: + - Fastest level (-mx1) : hc5 match finder with 256 KB dictionary. + - Fast level (-mx3) : hc5 match finder with 4 MB dictionary. +- Minor speed optimizations in multithreaded LZMA/LZMA2 compression for Normal/Maximum/Ultra + compression levels. + + 19.00 2019-02-21 ------------------------- - Encryption strength for 7z archives was increased: diff --git a/libraries/lzma/DOC/lzma-sdk.txt b/libraries/lzma/DOC/lzma-sdk.txt index b0e14a2e2..9621c8d5d 100644 --- a/libraries/lzma/DOC/lzma-sdk.txt +++ b/libraries/lzma/DOC/lzma-sdk.txt @@ -1,4 +1,4 @@ -LZMA SDK 19.00 +LZMA SDK 21.07 -------------- LZMA SDK provides the documentation, samples, header files, @@ -62,14 +62,61 @@ LZMA SDK Contents UNIX/Linux version ------------------ -To compile C++ version of file->file LZMA encoding, go to directory -CPP/7zip/Bundles/LzmaCon -and call make to recompile it: - make -f makefile.gcc clean all +There are several otpions to compile 7-Zip with different compilers: gcc and clang. +Also 7-Zip code contains two versions for some critical parts of code: in C and in Assembeler. +So if you compile the version with Assembeler code, you will get faster 7-Zip binary. + +7-Zip's assembler code uses the following syntax for different platforms: + +1) x86 and x86-64 (AMD64): MASM syntax. + There are 2 programs that supports MASM syntax in Linux. +' 'Asmc Macro Assembler and JWasm. But JWasm now doesn't support some + cpu instructions used in 7-Zip. + So you must install Asmc Macro Assembler in Linux, if you want to compile fastest version + of 7-Zip x86 and x86-64: + https://github.com/nidud/asmc + +2) arm64: GNU assembler for ARM64 with preprocessor. + That systax of that arm64 assembler code in 7-Zip is supported by GCC and CLANG for ARM64. + +There are different binaries that can be compiled from 7-Zip source. +There are 2 main files in folder for compiling: + makefile - that can be used for compiling Windows version of 7-Zip with nmake command + makefile.gcc - that can be used for compiling Linux/macOS versions of 7-Zip with make command + +At first you must change the current folder to folder that contains `makefile.gcc`: + + cd CPP/7zip/Bundles/Alone7z + +Then you can compile `makefile.gcc` with the command: + + make -j -f makefile.gcc + +Also there are additional "*.mak" files in folder "CPP/7zip/" that can be used to compile +7-Zip binaries with optimized code and optimzing options. + +To compile with GCC without assembler: + cd CPP/7zip/Bundles/Alone7z + make -j -f ../../cmpl_gcc.mak + +To compile with CLANG without assembler: + make -j -f ../../cmpl_clang.mak + +To compile 7-Zip for x86-64 with asmc assembler: + make -j -f ../../cmpl_gcc_x64.mak + +To compile 7-Zip for arm64 with assembler: + make -j -f ../../cmpl_gcc_arm64.mak + +To compile 7-Zip for arm64 for macOS: + make -j -f ../../cmpl_mac_arm64.mak + +Also you can change some compiler options in the mak files: + cmpl_gcc.mak + var_gcc.mak + warn_gcc.mak + -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): diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7b77d97d0..f5fe0a5aa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -937,7 +937,6 @@ set (PCH_SOURCES rendering/hwrenderer/hw_vertexbuilder.cpp rendering/hwrenderer/doom_aabbtree.cpp rendering/hwrenderer/hw_models.cpp - rendering/hwrenderer/hw_postprocessshader.cpp rendering/hwrenderer/hw_precache.cpp rendering/hwrenderer/scene/hw_lighting.cpp rendering/hwrenderer/scene/hw_drawlistadd.cpp @@ -1152,8 +1151,10 @@ set (PCH_SOURCES common/rendering/hwrenderer/data/hw_aabbtree.cpp common/rendering/hwrenderer/data/hw_shadowmap.cpp common/rendering/hwrenderer/data/hw_shaderpatcher.cpp + common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp common/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.cpp + common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp common/rendering/gl_load/gl_interface.cpp common/rendering/gl/gl_renderer.cpp common/rendering/gl/gl_stereo3d.cpp diff --git a/src/common/2d/v_2ddrawer.cpp b/src/common/2d/v_2ddrawer.cpp index 182712349..69ab0d530 100644 --- a/src/common/2d/v_2ddrawer.cpp +++ b/src/common/2d/v_2ddrawer.cpp @@ -749,7 +749,6 @@ void F2DDrawer::AddPoly(FGameTexture *texture, FVector2 *points, int npoints, void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, const unsigned int* ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, int clipx1, int clipy1, int clipx2, int clipy2) { RenderCommand dg; - int method = 0; if (!img || !img->isValid()) return; @@ -835,13 +834,13 @@ void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FGameTextu dg.mFlags = DTF_Wrap; float fs = 1.f / float(flatscale); - bool flipc = false; float sw = GetClassicFlatScalarWidth(); float sh = GetClassicFlatScalarHeight(); switch (local_origin) { + default: case 0: fU1 = float(left) / (float)src->GetDisplayWidth() * fs; fV1 = float(top) / (float)src->GetDisplayHeight() * fs; @@ -994,7 +993,7 @@ void F2DDrawer::AddLine(double x1, double y1, double x2, double y2, int clipx1, dg.mScissor[3] = clipy2 + 1 + int(offset.Y); dg.mFlags |= DTF_Scissor; } - + dg.mType = DrawTypeLines; dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent]; dg.mVertCount = 2; diff --git a/src/common/2d/v_2ddrawer.h b/src/common/2d/v_2ddrawer.h index ab87085f5..623559978 100644 --- a/src/common/2d/v_2ddrawer.h +++ b/src/common/2d/v_2ddrawer.h @@ -101,7 +101,7 @@ public: } }; - + struct RenderCommand { EDrawType mType; @@ -175,7 +175,7 @@ public: public: int fullscreenautoaspect = 3; int cliptop = -1, clipleft = -1, clipwidth = -1, clipheight = -1; - + int AddCommand(RenderCommand *data); void AddIndices(int firstvert, int count, ...); private: @@ -200,8 +200,8 @@ public: void ClearScreen(PalEntry color = 0xff000000); void AddDim(PalEntry color, float damount, int x1, int y1, int w, int h); void AddClear(int left, int top, int right, int bottom, int palcolor, uint32_t color); - - + + void AddLine(double x1, double y1, double x2, double y2, int cx, int cy, int cx2, int cy2, uint32_t color, uint8_t alpha = 255); void AddThickLine(int x1, int y1, int x2, int y2, double thickness, uint32_t color, uint8_t alpha = 255); void AddPixel(int x1, int y1, uint32_t color); diff --git a/src/common/2d/v_draw.cpp b/src/common/2d/v_draw.cpp index 4a99b8cac..1ff348bc7 100644 --- a/src/common/2d/v_draw.cpp +++ b/src/common/2d/v_draw.cpp @@ -144,7 +144,7 @@ int GetUIScale(F2DDrawer *drawer, int altval) // Default should try to scale to 640x400 int vscale = drawer->GetHeight() / 400; int hscale = drawer->GetWidth() / 640; - scaleval = clamp(vscale, 1, hscale); + scaleval = max(1, min(vscale, hscale)); } else scaleval = uiscale; @@ -165,7 +165,7 @@ int GetConScale(F2DDrawer* drawer, int altval) // Default should try to scale to 640x400 int vscale = drawer->GetHeight() / 800; int hscale = drawer->GetWidth() / 1280; - scaleval = clamp(vscale, 1, hscale); + scaleval = max(1, min(vscale, hscale)); } else scaleval = (uiscale+1) / 2; @@ -671,7 +671,6 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double { INTBOOL boolval; int intval; - bool translationset = false; bool fillcolorset = false; if (!fortext) @@ -858,7 +857,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double parms->cleanmode = DTA_Base; parms->virtHeight = ListGetDouble(tags); break; - + case DTA_FullscreenScale: intval = ListGetInt(tags); if (intval >= FSMode_None && intval < FSMode_Max) @@ -1016,10 +1015,16 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double case DTA_CenterOffsetRel: assert(fortext == false); if (fortext) return false; - if (ListGetInt(tags)) + intval = ListGetInt(tags); + if (intval == 1) { - parms->left = img->GetDisplayLeftOffset() + img->GetDisplayWidth() * 0.5; - parms->top = img->GetDisplayTopOffset() + img->GetDisplayHeight() * 0.5; + parms->left = img->GetDisplayLeftOffset() + (img->GetDisplayWidth() * 0.5); + parms->top = img->GetDisplayTopOffset() + (img->GetDisplayHeight() * 0.5); + } + else if (intval == 2) + { + parms->left = img->GetDisplayLeftOffset() + floor(img->GetDisplayWidth() * 0.5); + parms->top = img->GetDisplayTopOffset() + floor(img->GetDisplayHeight() * 0.5); } break; diff --git a/src/common/2d/v_draw.h b/src/common/2d/v_draw.h index a0407179e..fecfc3d9e 100644 --- a/src/common/2d/v_draw.h +++ b/src/common/2d/v_draw.h @@ -36,7 +36,7 @@ enum FSMode_Max, - + // These all use ScaleToFit43, their purpose is to cut down on verbosity because they imply the virtual screen size. FSMode_Predefined = 1000, FSMode_Fit320x200 = 1000, @@ -325,3 +325,5 @@ public: CleanHeight = savedheight; } }; + +void Draw2D(F2DDrawer* drawer, FRenderState& state); diff --git a/src/common/audio/music/i_music.cpp b/src/common/audio/music/i_music.cpp index 26989992d..bc05d4da5 100644 --- a/src/common/audio/music/i_music.cpp +++ b/src/common/audio/music/i_music.cpp @@ -226,7 +226,7 @@ void I_InitMusic(void) nomusic = !!Args->CheckParm("-nomusic") || !!Args->CheckParm("-nosound"); snd_mididevice.Callback(); - + ZMusicCallbacks callbacks{}; callbacks.MessageFunc = zmusic_printfunc; diff --git a/src/common/audio/music/i_soundfont.cpp b/src/common/audio/music/i_soundfont.cpp index a8b4e9fdf..8d928a42c 100644 --- a/src/common/audio/music/i_soundfont.cpp +++ b/src/common/audio/music/i_soundfont.cpp @@ -140,7 +140,7 @@ FileReader FSoundFontReader::Open(const char *name, std::string& filename) ZMusicCustomReader* FSoundFontReader::open_interface(const char* name) { std::string filename; - + FileReader fr = Open(name, filename); if (!fr.isOpen()) return nullptr; auto fri = GetMusicReader(fr); @@ -336,7 +336,7 @@ void FSoundFontManager::ProcessOneFile(const FString &fn) // We already got a soundfont with this name. Do not add again. if (!sfi.mName.CompareNoCase(fb)) return; } - + FileReader fr; if (fr.OpenFile(fn)) { diff --git a/src/common/audio/music/i_soundfont.h b/src/common/audio/music/i_soundfont.h index 9f07b8cc4..ef0295071 100644 --- a/src/common/audio/music/i_soundfont.h +++ b/src/common/audio/music/i_soundfont.h @@ -29,13 +29,13 @@ protected: // When reading from an archive it will always be case insensitive, just like the lump manager. bool mCaseSensitivePaths = false; TArray mPaths; - - + + int pathcmp(const char *p1, const char *p2); - - + + public: - + virtual ~FSoundFontReader() {} virtual FileReader OpenMainConfigFile() = 0; // this is special because it needs to be synthesized for .sf files and set some restrictions for patch sets virtual FString MainConfigFileName() @@ -147,15 +147,15 @@ public: class FSoundFontManager { TArray soundfonts; - + void ProcessOneFile(const FString & fn); - + public: void CollectSoundfonts(); const FSoundFontInfo *FindSoundFont(const char *name, int allowedtypes) const; FSoundFontReader *OpenSoundFont(const char *name, int allowedtypes); const auto &GetList() const { return soundfonts; } // This is for the menu - + }; diff --git a/src/common/audio/music/music.cpp b/src/common/audio/music/music.cpp index 1b36041da..d125bf36d 100644 --- a/src/common/audio/music/music.cpp +++ b/src/common/audio/music/music.cpp @@ -180,7 +180,7 @@ static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata) fbuf[i] = convert[i] * mus_playing.replayGainFactor * (1.f/32768.f); } } - + if (!written) { memset((char*)buff, 0, len); @@ -298,7 +298,7 @@ void S_UpdateMusic () if (mus_playing.handle != nullptr) { ZMusic_Update(mus_playing.handle); - + // [RH] Update music and/or playlist. IsPlaying() must be called // to attempt to reconnect to broken net streams and to advance the // playlist when the current song finishes. @@ -603,13 +603,13 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const { float* sbuf = (float*)readbuffer.Data(); int numsamples = fmt.mBufferSize / 8; - auto index = lbuffer.Reserve(numsamples); + auto addr = lbuffer.Reserve(numsamples); rbuffer.Reserve(numsamples); for (int i = 0; i < numsamples; i++) { - lbuffer[index + i] = sbuf[i * 2] * 32768.f; - rbuffer[index + i] = sbuf[i * 2 + 1] * 32768.f; + lbuffer[addr + i] = sbuf[i * 2] * 32768.f; + rbuffer[addr + i] = sbuf[i * 2 + 1] * 32768.f; } } float accTime = lbuffer.Size() / (float)fmt.mSampleRate; @@ -684,8 +684,6 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) return true; } - int lumpnum = -1; - int length = 0; ZMusic_MusicStream handle = nullptr; MidiDeviceSetting* devp = MidiDevices.CheckKey(musicname); diff --git a/src/common/audio/sound/i_sound.h b/src/common/audio/sound/i_sound.h index 060838edf..da11e9bde 100644 --- a/src/common/audio/sound/i_sound.h +++ b/src/common/audio/sound/i_sound.h @@ -107,7 +107,7 @@ public: // Streaming sounds. virtual SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) = 0; - + // Starts a sound. virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime = 0.f) = 0; virtual FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime = 0.f) = 0; diff --git a/src/common/audio/sound/oalsound.cpp b/src/common/audio/sound/oalsound.cpp index 4ef36cb4d..240b4c8ab 100644 --- a/src/common/audio/sound/oalsound.cpp +++ b/src/common/audio/sound/oalsound.cpp @@ -329,7 +329,6 @@ public: virtual FString GetStats() { FString stats; - size_t pos = 0, len = 0; ALfloat volume; ALint offset; ALint processed; @@ -1676,7 +1675,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) const_cast(env)->Modified = false; } - + // NOTE: Moving into and out of water will undo pitch variations on sounds. if(listener->underwater || env->SoftwareWater) { @@ -1722,7 +1721,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) } else if(WasInWater) { - + WasInWater = false; if(EnvSlot != 0) diff --git a/src/common/audio/sound/s_environment.cpp b/src/common/audio/sound/s_environment.cpp index c5f1a5cf7..7a2dbd9a5 100644 --- a/src/common/audio/sound/s_environment.cpp +++ b/src/common/audio/sound/s_environment.cpp @@ -530,7 +530,7 @@ void S_ReadReverbDef (FScanner &sc) { const ReverbContainer *def; ReverbContainer *newenv; - REVERB_PROPERTIES props; + REVERB_PROPERTIES props = {}; char *name; int id1, id2, i, j; bool inited[NUM_REVERB_FIELDS]; diff --git a/src/common/audio/sound/s_reverbedit.cpp b/src/common/audio/sound/s_reverbedit.cpp index 398d4f2f5..9787ffa8c 100644 --- a/src/common/audio/sound/s_reverbedit.cpp +++ b/src/common/audio/sound/s_reverbedit.cpp @@ -309,7 +309,6 @@ DEFINE_ACTION_FUNCTION(DReverbEdit, GetValue) } } ACTION_RETURN_FLOAT(v); - return 1; } DEFINE_ACTION_FUNCTION(DReverbEdit, SetValue) @@ -337,14 +336,12 @@ DEFINE_ACTION_FUNCTION(DReverbEdit, SetValue) } ACTION_RETURN_FLOAT(v); - return 1; } DEFINE_ACTION_FUNCTION(DReverbEdit, GrayCheck) { PARAM_PROLOGUE; ACTION_RETURN_BOOL(CurrentEnv->Builtin); - return 1; } DEFINE_ACTION_FUNCTION(DReverbEdit, GetSelectedEnvironment) diff --git a/src/common/audio/sound/s_sound.cpp b/src/common/audio/sound/s_sound.cpp index 46119a322..cdd0361c5 100644 --- a/src/common/audio/sound/s_sound.cpp +++ b/src/common/audio/sound/s_sound.cpp @@ -164,7 +164,6 @@ void SoundEngine::CacheSound (sfxinfo_t *sfx) { if (GSnd && !sfx->bTentative) { - sfxinfo_t *orig = sfx; while (!sfx->bRandomHeader && sfx->link != sfxinfo_t::NO_LINK) { sfx = &S_sfx[sfx->link]; @@ -389,7 +388,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, FVector3 pos, vel; FRolloffInfo *rolloff; - if (sound_id <= 0 || volume <= 0 || nosfx || !SoundEnabled() || blockNewSounds) + if (sound_id <= 0 || volume <= 0 || nosfx || !SoundEnabled() || blockNewSounds || (unsigned)sound_id >= S_sfx.Size()) return NULL; // prevent crashes. @@ -403,7 +402,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, { return nullptr; } - + sfx = &S_sfx[sound_id]; // Scale volume according to SNDINFO data. @@ -612,7 +611,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, { chan->Source = source; } - + if (spitch > 0.0) // A_StartSound has top priority over all others. SetPitch(chan, spitch); else if (defpitch > 0.0) // $PitchSet overrides $PitchShift @@ -727,7 +726,7 @@ sfxinfo_t *SoundEngine::LoadSound(sfxinfo_t *sfx) { return sfx; } - + // See if there is another sound already initialized with this lump. If so, // then set this one up as a link, and don't load the sound again. for (i = 0; i < S_sfx.Size(); i++) @@ -831,7 +830,7 @@ bool SoundEngine::CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_ { FSoundChan *chan; int count; - + for (chan = Channels, count = 0; chan != NULL && count < near_limit; chan = chan->NextChan) { if (chan->ChanFlags & CHANF_FORGETTABLE) continue; @@ -1085,13 +1084,14 @@ void SoundEngine::SetPitch(FSoundChan *chan, float pitch) // Is a sound being played by a specific emitter? //========================================================================== -int SoundEngine::GetSoundPlayingInfo (int sourcetype, const void *source, int sound_id) +int SoundEngine::GetSoundPlayingInfo (int sourcetype, const void *source, int sound_id, int chann) { int count = 0; if (sound_id > 0) { for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { + if (chann != -1 && chann != chan->EntChannel) continue; if (chan->OrgID == sound_id && (sourcetype == SOURCE_Any || (chan->SourceType == sourcetype && chan->Source == source))) @@ -1104,6 +1104,7 @@ int SoundEngine::GetSoundPlayingInfo (int sourcetype, const void *source, int so { for (FSoundChan* chan = Channels; chan != NULL; chan = chan->NextChan) { + if (chann != -1 && chann != chan->EntChannel) continue; if ((sourcetype == SOURCE_Any || (chan->SourceType == sourcetype && chan->Source == source))) { count++; diff --git a/src/common/audio/sound/s_soundinternal.h b/src/common/audio/sound/s_soundinternal.h index d35cb524a..f15c994dc 100644 --- a/src/common/audio/sound/s_soundinternal.h +++ b/src/common/audio/sound/s_soundinternal.h @@ -73,7 +73,7 @@ class FSoundID { public: FSoundID() = default; - + static FSoundID byResId(int ndx) { return FSoundID(S_FindSoundByResID(ndx)); @@ -120,7 +120,7 @@ protected: enum EDummy { NoInit }; FSoundID(EDummy) {} }; - + class FSoundIDNoInit : public FSoundID { public: @@ -196,7 +196,7 @@ void S_SetEnvironment (const ReverbContainer *settings); ReverbContainer *S_FindEnvironment (const char *name); ReverbContainer *S_FindEnvironment (int id); void S_AddEnvironment (ReverbContainer *settings); - + class SoundEngine { protected: @@ -249,9 +249,6 @@ public: blockNewSounds = on; } - virtual int SoundSourceIndex(FSoundChan* chan) { return 0; } - virtual void SetSource(FSoundChan* chan, int index) {} - virtual void StopChannel(FSoundChan* chan); sfxinfo_t* LoadSound(sfxinfo_t* sfx); const sfxinfo_t* GetSfx(unsigned snd) @@ -303,7 +300,7 @@ public: bool IsSourcePlayingSomething(int sourcetype, const void* actor, int channel, int sound_id = -1); // Stop and resume music, during game PAUSE. - int GetSoundPlayingInfo(int sourcetype, const void* source, int sound_id); + int GetSoundPlayingInfo(int sourcetype, const void* source, int sound_id, int chan = -1); void UnloadAllSounds(); void Reset(); void MarkUsed(int num); diff --git a/src/common/console/c_bind.cpp b/src/common/console/c_bind.cpp index 1bca5072c..d131cb6ed 100644 --- a/src/common/console/c_bind.cpp +++ b/src/common/console/c_bind.cpp @@ -393,7 +393,7 @@ void FKeyBindings::PerformBind(FCommandLine &argv, const char *msg) else { Printf ("%s:\n", msg); - + for (i = 0; i < NUM_KEYS; i++) { if (!Binds[i].IsEmpty()) @@ -696,7 +696,7 @@ void ReadBindings(int lump, bool override) } continue; } - + // bind destination is optional and is the same as the console command if (sc.Compare("bind")) { diff --git a/src/common/console/c_buttons.cpp b/src/common/console/c_buttons.cpp index 860824ca5..3464553e3 100644 --- a/src/common/console/c_buttons.cpp +++ b/src/common/console/c_buttons.cpp @@ -101,13 +101,13 @@ int ButtonMap::ListActionCommands (const char *pattern) int ButtonMap::FindButtonIndex (const char *key, int funclen) const { if (!key) return -1; - + FName name = funclen == -1? FName(key, true) : FName(key, funclen, true); if (name == NAME_None) return -1; - + auto res = NameToNum.CheckKey(name); if (!res) return -1; - + return *res; } diff --git a/src/common/console/c_commandbuffer.cpp b/src/common/console/c_commandbuffer.cpp index b079d7f76..0c570da14 100644 --- a/src/common/console/c_commandbuffer.cpp +++ b/src/common/console/c_commandbuffer.cpp @@ -299,7 +299,7 @@ void FCommandBuffer::AddString(FString clip) } auto strp = (const uint8_t*)clip.GetChars(); while (auto chr = GetCharFromString(strp)) build += chr; - + if (Text.length() == 0) { Text = build; diff --git a/src/common/console/c_console.cpp b/src/common/console/c_console.cpp index b40708808..483f9a378 100644 --- a/src/common/console/c_console.cpp +++ b/src/common/console/c_console.cpp @@ -331,16 +331,16 @@ void C_DeinitConsole () // at runtime.) for (size_t i = 0; i < countof(Commands); ++i) { - FConsoleCommand *cmd = Commands[i]; + FConsoleCommand *command = Commands[i]; - while (cmd != NULL) + while (command != NULL) { - FConsoleCommand *next = cmd->m_Next; - if (cmd->IsAlias()) + FConsoleCommand *nextcmd = command->m_Next; + if (command->IsAlias()) { - delete cmd; + delete command; } - cmd = next; + command = nextcmd; } } @@ -1027,7 +1027,7 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) TabbedList = false; break; } - + case '`': // Check to see if we have ` bound to the console before accepting // it as a way to close the console. diff --git a/src/common/console/c_consolebuffer.cpp b/src/common/console/c_consolebuffer.cpp index a75a0588c..ea6be80e2 100644 --- a/src/common/console/c_consolebuffer.cpp +++ b/src/common/console/c_consolebuffer.cpp @@ -72,7 +72,7 @@ FConsoleBuffer::FConsoleBuffer() void FConsoleBuffer::AddText(int printlevel, const char *text) { FString build = TEXTCOLOR_TAN; - + if (mAddType == REPLACELINE) { // Just wondering: Do we actually need this case? If so, it may need some work. @@ -85,15 +85,15 @@ void FConsoleBuffer::AddText(int printlevel, const char *text) printlevel = -1; mLastLineNeedsUpdate = true; } - + if (printlevel >= 0 && printlevel != PRINT_HIGH) { if (printlevel == 200) build = TEXTCOLOR_GREEN; else if (printlevel < PRINTLEVELS) build.Format("%c%c", TEXTCOLOR_ESCAPE, PrintColors[printlevel]+'A'); } - + size_t textsize = strlen(text); - + if (text[textsize-1] == '\r') { textsize--; diff --git a/src/common/console/c_consolebuffer.h b/src/common/console/c_consolebuffer.h index 98a42b42e..58bc0edea 100644 --- a/src/common/console/c_consolebuffer.h +++ b/src/common/console/c_consolebuffer.h @@ -56,12 +56,12 @@ class FConsoleBuffer EAddType mAddType; int mTextLines; bool mBufferWasCleared; - + FFont *mLastFont; int mLastDisplayWidth; bool mLastLineNeedsUpdate; - + public: FConsoleBuffer(); void AddText(int printlevel, const char *string); diff --git a/src/common/console/c_cvars.cpp b/src/common/console/c_cvars.cpp index 7e5bd94ba..6510d561e 100644 --- a/src/common/console/c_cvars.cpp +++ b/src/common/console/c_cvars.cpp @@ -333,6 +333,7 @@ UCVarValue FBaseCVar::FromBool (bool value, ECVarType type) break; default: + ret.Int = 0; break; } @@ -363,6 +364,7 @@ UCVarValue FBaseCVar::FromInt (int value, ECVarType type) break; default: + ret.Int = 0; break; } @@ -395,6 +397,7 @@ UCVarValue FBaseCVar::FromFloat (float value, ECVarType type) break; default: + ret.Int = 0; break; } @@ -456,6 +459,7 @@ UCVarValue FBaseCVar::FromString (const char *value, ECVarType type) break; default: + ret.Int = 0; break; } @@ -1426,12 +1430,12 @@ void C_ArchiveCVars (FConfigFile *f, uint32_t filter) cvar = cvar->m_Next; } qsort(cvarlist.Data(), cvarlist.Size(), sizeof(FBaseCVar*), cvarcmp); - for (auto cvar : cvarlist) + for (auto cv : cvarlist) { - const char* const value = (cvar->Flags & CVAR_ISDEFAULT) - ? cvar->GetGenericRep(CVAR_String).String - : cvar->SafeValue.GetChars(); - f->SetValueForKey(cvar->GetName(), value); + const char* const value = (cv->Flags & CVAR_ISDEFAULT) + ? cv->GetGenericRep(CVAR_String).String + : cv->SafeValue.GetChars(); + f->SetValueForKey(cv->GetName(), value); } } @@ -1643,7 +1647,6 @@ CCMD (archivecvar) void C_ListCVarsWithoutDescription() { FBaseCVar* var = CVars; - int count = 0; while (var) { diff --git a/src/common/console/c_cvars.h b/src/common/console/c_cvars.h index abbe31a4b..7d5201a1d 100644 --- a/src/common/console/c_cvars.h +++ b/src/common/console/c_cvars.h @@ -175,7 +175,7 @@ public: static void ResetColors (); // recalc color cvars' indices after screen change static void ListVars (const char *filter, bool plain); - + const FString &GetDescription() const { return Description; }; const FString& GetToggleMessage(int which) { return ToggleMessages[which]; } void SetToggleMessages(const char* on, const char* off) @@ -398,7 +398,7 @@ public: protected: virtual void DoSet (UCVarValue value, ECVarType type); - + static UCVarValue FromInt2 (int value, ECVarType type); static int ToInt2 (UCVarValue value, ECVarType type); }; diff --git a/src/common/console/c_dispatch.cpp b/src/common/console/c_dispatch.cpp index 004c5be3e..7de13e2ea 100644 --- a/src/common/console/c_dispatch.cpp +++ b/src/common/console/c_dispatch.cpp @@ -253,7 +253,7 @@ void C_DoCommand (const char *cmd, int keynum) return; } } - + // Parse it as a normal command // Checking for matching commands follows this search order: // 1. Check the Commands[] hash table @@ -282,8 +282,8 @@ void C_DoCommand (const char *cmd, int keynum) } else { - auto cmd = new FStoredCommand(com, beg); - delayedCommandQueue.AddCommand(cmd); + auto command = new FStoredCommand(com, beg); + delayedCommandQueue.AddCommand(command); } } } @@ -373,8 +373,8 @@ void AddCommandString (const char *text, int keynum) // Note that deferred commands lose track of which key // (if any) they were pressed from. *brkpt = ';'; - auto cmd = new FWaitingCommand(brkpt, tics, UnsafeExecutionContext); - delayedCommandQueue.AddCommand(cmd); + auto command = new FWaitingCommand(brkpt, tics, UnsafeExecutionContext); + delayedCommandQueue.AddCommand(command); } return; } @@ -851,8 +851,8 @@ CCMD (key) for (i = 1; i < argv.argc(); ++i) { - unsigned int key = MakeKey (argv[i]); - Printf (" 0x%08x\n", key); + unsigned int hash = MakeKey (argv[i]); + Printf (" 0x%08x\n", hash); } } } @@ -1014,7 +1014,6 @@ void FExecList::AddPullins(TArray &wads, FConfigFile *config) const FExecList *C_ParseExecFile(const char *file, FExecList *exec) { char cmd[4096]; - int retval = 0; FileReader fr; diff --git a/src/common/console/c_expr.cpp b/src/common/console/c_expr.cpp index d203c8cd5..4a48439b7 100644 --- a/src/common/console/c_expr.cpp +++ b/src/common/console/c_expr.cpp @@ -248,7 +248,7 @@ done: bool IsFloat (const char *str) { const char *pt; - + if (*str == '+' || *str == '-') str++; @@ -367,7 +367,7 @@ static FStringProd *DoubleToString (FProduction *prod) static FDoubleProd *StringToDouble (FProduction *prod) { FDoubleProd *newprod; - + newprod = NewDoubleProd (atof (static_cast(prod)->Value)); M_Free (prod); return newprod; diff --git a/src/common/console/c_notifybufferbase.cpp b/src/common/console/c_notifybufferbase.cpp index e31a8f07c..11be81dd3 100644 --- a/src/common/console/c_notifybufferbase.cpp +++ b/src/common/console/c_notifybufferbase.cpp @@ -126,7 +126,7 @@ void FNotifyBufferBase::Tick() { Text[i].Ticker++; } - + for (i = 0; i < Text.Size(); ++i) { if (Text[i].TimeOut != 0 && Text[i].TimeOut > Text[i].Ticker) diff --git a/src/common/engine/cycler.cpp b/src/common/engine/cycler.cpp index 1d0d28486..1dbf1fce0 100644 --- a/src/common/engine/cycler.cpp +++ b/src/common/engine/cycler.cpp @@ -97,20 +97,20 @@ void FCycler::Update(double diff) { double mult, angle; double step = m_end - m_start; - + if (!m_shouldCycle) { return; } - + m_time += diff; if (m_time >= m_cycle) { m_time = m_cycle; } - + mult = m_time / m_cycle; - + switch (m_cycleType) { case CYCLE_Linear: @@ -149,7 +149,7 @@ void FCycler::Update(double diff) } break; } - + if (m_time == m_cycle) { m_time = 0.; diff --git a/src/common/engine/cycler.h b/src/common/engine/cycler.h index 0b49e644d..a2789f9ca 100644 --- a/src/common/engine/cycler.h +++ b/src/common/engine/cycler.h @@ -23,7 +23,7 @@ public: FCycler() = default; FCycler(const FCycler &other) = default; FCycler &operator=(const FCycler &other) = default; - + void Update(double diff); void SetParams(double start, double end, double cycle, bool update = false); void ShouldCycle(bool sc) { m_shouldCycle = sc; } diff --git a/src/common/engine/d_event.cpp b/src/common/engine/d_event.cpp index 3a779a5fc..dd23c6e0d 100644 --- a/src/common/engine/d_event.cpp +++ b/src/common/engine/d_event.cpp @@ -67,11 +67,21 @@ CVAR(Bool, m_filter, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) void D_ProcessEvents (void) { - event_t *ev; + FixedBitArray keywasdown; + TArray delayedevents; + + keywasdown.Zero(); while (eventtail != eventhead) { - ev = &events[eventtail]; + event_t *ev = &events[eventtail]; eventtail = (eventtail + 1) & (MAXEVENTS - 1); + + if (ev->type == EV_KeyUp && keywasdown[ev->data1]) + { + delayedevents.Push(*ev); + continue; + } + if (ev->type == EV_None) continue; if (ev->type == EV_DeviceChange) @@ -85,7 +95,12 @@ void D_ProcessEvents (void) continue; // menu ate the event } - G_Responder (ev); + if (G_Responder(ev) && ev->type == EV_KeyDown) keywasdown.Set(ev->data1); + } + + for (auto& ev: delayedevents) + { + D_PostEvent(&ev); } } @@ -123,7 +138,7 @@ void D_RemoveNextCharEvent() } } } - + //========================================================================== // diff --git a/src/common/engine/i_net.cpp b/src/common/engine/i_net.cpp index 64fd4acaf..85a1219b0 100644 --- a/src/common/engine/i_net.cpp +++ b/src/common/engine/i_net.cpp @@ -7,7 +7,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, @@ -172,7 +172,7 @@ FString GetPlayerName(int num) SOCKET UDPsocket (void) { SOCKET s; - + // allocate a socket s = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (s == INVALID_SOCKET) @@ -193,7 +193,7 @@ void BindToLocalPort (SOCKET s, u_short port) address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(port); - + v = bind (s, (sockaddr *)&address, sizeof(address)); if (v == SOCKET_ERROR) I_FatalError ("BindToPort: %s", neterror ()); @@ -459,7 +459,7 @@ void StartNetwork (bool autoPort) netgame = true; multiplayer = true; - + // create communication socket mysocket = UDPsocket (); BindToLocalPort (mysocket, autoPort ? 0 : DOOMPORT); @@ -736,7 +736,7 @@ bool HostGame (int i) { // If we send the packets eight times to each guest, // hopefully at least one of them will get through. - for (int i = 8; i != 0; --i) + for (int ii = 8; ii != 0; --ii) { PreSend (&packet, 2, &sendaddress[node]); } @@ -892,7 +892,7 @@ bool JoinGame (int i) SendAbort(); return false; } - + StartScreen->NetMessage ("Total players: %d", doomcom.numnodes); doomcom.id = DOOMCOM_ID; diff --git a/src/common/engine/i_net.h b/src/common/engine/i_net.h index 87d720014..f608f662a 100644 --- a/src/common/engine/i_net.h +++ b/src/common/engine/i_net.h @@ -76,7 +76,7 @@ struct doomcom_t // packet data to be sent uint8_t data[MAX_MSGLEN]; - + }; extern doomcom_t doomcom; diff --git a/src/common/engine/m_joy.h b/src/common/engine/m_joy.h index 016aa78d6..fc99379b0 100644 --- a/src/common/engine/m_joy.h +++ b/src/common/engine/m_joy.h @@ -21,7 +21,7 @@ enum EJoyAxis struct NOVTABLE IJoystickConfig { virtual ~IJoystickConfig() = 0; - + virtual FString GetName() = 0; virtual float GetSensitivity() = 0; virtual void SetSensitivity(float scale) = 0; diff --git a/src/common/engine/namedef.h b/src/common/engine/namedef.h index f2f2ebcc7..cf1b670be 100644 --- a/src/common/engine/namedef.h +++ b/src/common/engine/namedef.h @@ -1,3 +1,5 @@ +// common names + // 'None' must always be the first name. xx(None) xx(Null) @@ -11,34 +13,6 @@ xx(Thinker) xx(Untranslated) -xx(Doom) -xx(Heretic) -xx(Hexen) -xx(Strife) -xx(Raven) - -// blood spawning -xx(Blood) -xx(BloodSplatter) -xx(AxeBlood) -xx(Spray) - -// Invulnerability types -xx(Ghost) -xx(Reflective) - -// Iron Feet types -//xx(Normal) // defined below -xx(Full) - -// Invisibility types -xx(Additive) -xx(Cumulative) -xx(Fuzzy) -xx(Opaque) -xx(Stencil) -xx(AddStencil) - // Render styles xx(Normal) xx(SoulTrans) @@ -55,245 +29,7 @@ xx(ColorBlend) xx(ColorAdd) xx(Multiply) -// Healingradius types -xx(Mana) -xx(Armor) - -// Per-actor sound channels -xx(Auto) -xx(Weapon) -xx(Voice) -xx(Item) -xx(Body) -xx(SoundSlot5) -xx(SoundSlot6) -xx(SoundSlot7) - -// Hexen sound sequence names -xx(Platform) -xx(PlatformMetal) -xx(Silence) -xx(Lava) -xx(Water) -xx(Ice) -xx(Earth) -xx(PlatformMetal2) -xx(DoorNormal) -xx(DoorHeavy) -xx(DoorMetal) -xx(DoorCreak) -xx(DoorMetal2) -xx(Wind) - -xx(PointPusher) -xx(PointPuller) - -xx(UpperStackLookOnly) -xx(LowerStackLookOnly) -xx(StackPoint) -xx(SkyCamCompat) - -xx(BasicArmorBonus) -xx(BasicArmorPickup) -xx(SaveAmount) -xx(SavePercent) -xx(MaxAbsorb) -xx(MaxFullAbsorb) -xx(MaxAmount) -xx(ActualSaveAmount) -xx(ArmorType) -xx(HexenArmor) -xx(Slots) -xx(SlotsIncrement) -xx(InterHubAmount) -xx(Icon) -xx(AltHUDIcon) -xx(PickupFlash) - -xx(BulletPuff) -xx(StrifePuff) -xx(MaulerPuff) - -// Special bosses A_BossDeath knows about -xx(Fatso) -xx(Arachnotron) -xx(BaronOfHell) -xx(Cyberdemon) -xx(SpiderMastermind) -xx(Ironlich) -xx(Minotaur) -xx(Sorcerer2) - -// Bots check this -xx(Megasphere) -xx(MegasphereHealth) - -// Standard player classes -xx(DoomPlayer) -xx(HereticPlayer) -xx(StrifePlayer) -xx(FighterPlayer) -xx(ClericPlayer) -xx(MagePlayer) -xx(ChexPlayer) -xx(ChickenPlayer) -xx(PigPlayer) - -// Flechette names for the different Hexen player classes -xx(ArtiPoisonBag1) -xx(ArtiPoisonBag2) -xx(ArtiPoisonBag3) - -// Strife quests -xx(QuestItem) -xx(Sigil) -xx(GiveSigilPiece) -xx(SetWeapon) -xx(SetSprite) - -// Armor -xx(BasicArmor) - -// Doom ammo types -xx(Clip) - -xx(PuzzleItem) -xx(PuzzleItemNumber) -xx(HealthPickup) -xx(autousemode) -xx(Ammo) -xx(WeaponGiver) -xx(DehackedPickup) -xx(PowerTargeter) -xx(PowerInvulnerable) -xx(PowerStrength) -xx(PowerInvisibility) -xx(PowerIronFeet) -xx(PowerLightAmp) -xx(PowerWeaponLevel2) -xx(PowerFlight) -xx(PowerSpeed) -xx(PowerTorch) -xx(PowerHighJump) -xx(PowerReflection) -xx(PowerDrain) -xx(Reflection) -xx(CustomInventory) -xx(Inventory) -xx(StateProvider) -xx(CallTryPickup) -xx(QuestItem25) -xx(QuestItem28) -xx(PowerDoubleFiringSpeed) -xx(PowerInfiniteAmmo) -xx(PowerBuddha) - -xx(TeleportDest) -xx(TeleportDest2) - -// Standard animator names. -xx(Spawn) -xx(See) -xx(Pain) -xx(Melee) -xx(Missile) -xx(Crash) -xx(Death) -xx(Raise) -xx(Wound) -xx(Heal) -xx(Crush) -xx(Yes) -xx(No) -xx(Greetings) -xx(Idle) -xx(GenericFreezeDeath) -xx(GenericCrush) - -// Bounce state names -xx(Bounce) -xx(Wall) -xx(Floor) -xx(Ceiling) -xx(Creature) - -// Compatible death names for the decorate parser. -xx(XDeath) -xx(Burn) -//xx(Ice) // already defined above -xx(Disintegrate) -xx(Smash) - -// Weapon animator names. -xx(Select) -xx(Deselect) -xx(DeadLowered) -xx(Ready) -xx(Fire) -xx(Hold) -xx(AltFire) -xx(AltHold) -xx(Flash) -xx(AltFlash) -xx(Reload) -xx(Zoom) -xx(User1) -xx(User2) -xx(User3) -xx(User4) - -// State names used by ASwitchableDecoration -xx(Active) -xx(Inactive) - -// State names used by ACustomInventory -xx(Pickup) -xx(Use) -xx(Drop) - -xx(Fist) -//xx(Berserk) -xx(Chainsaw) -xx(Pistol) -xx(Shotgun) -xx(SSG) -xx(Chaingun) -xx(Rocket) -xx(Plasma) -xx(BFG) -//xx(Railgun) -xx(Dagger) - -// Damage types -//xx(Fire) already defined above -//xx(Ice) -//xx(Disintegrate) -xx(Drowning) -xx(Slime) -//xx(Crush) -xx(Telefrag) -xx(Falling) -xx(Suicide) -xx(Exit) -xx(Railgun) -xx(Poison) -xx(Electric) -xx(BFGSplash) -xx(DrainLife) // A weapon like the Sigil that drains your life away. -xx(Massacre) // For death by a cheater! -//(Melee) already defined above, so don't define it again -xx(InstantDeath) // Strife "instant death" -xx(PoisonCloud) // makes monsters howl. -xx(Hitscan) // for normal guns and the like -xx(Quake) - -// Special death name for getting killed excessively. Could be used as -// a damage type if you wanted to force an extreme death. -xx(Extreme) -xx(MDK) -xx(Cast) // 'damage type' for the cast call - -// Special names for thingdef_exp.cpp +// Special names for compiler backend xx(Random) xx(FRandom) xx(Random2) @@ -322,543 +58,19 @@ xx(TanH) xx(Round) xx(ATan2) xx(VectorAngle) -xx(New) -xx(Alpha) -xx(Angle) -xx(Args) -xx(CeilingZ) -xx(FloorZ) -xx(Health) -xx(Pitch) -xx(SpecialName) -xx(Special) -xx(TID) -xx(TIDtoHate) -xx(WaterLevel) -xx(X) -xx(Y) -xx(Z) -xx(XY) -xx(MomX) -xx(MomY) -xx(MomZ) -xx(Threshold) -xx(DefThreshold) -xx(Abs) -xx(TeleportSpecial) -xx(Teleport) -xx(ACS_NamedExecuteWithResult) -xx(CallACS) xx(Sqrt) -xx(CheckClass) -xx(IsPointerEqual) -xx(Pick) -xx(Mass) -xx(VelX) -xx(VelY) -xx(VelZ) -xx(Accuracy) -xx(Stamina) -xx(Radius) -xx(ReactionTime) -xx(MeleeRange) -xx(Speed) -xx(FastSpeed) -xx(HowlSound) -xx(Clamp) -xx(VisibleStartAngle) -xx(VisibleStartPitch) -xx(VisibleEndAngle) -xx(VisibleEndPitch) -xx(Format) -xx(PickupMsg) -xx(Respawnable) -xx(ExplosionDamage) -xx(ExplosionRadius) -xx(DontHurtShooter) +xx(New) -// Various actor names which are used internally -xx(MapSpot) -xx(PatrolPoint) -xx(PatrolSpecial) -xx(Communicator) -xx(PowerScanner) - -// Textmap properties -//xx(X) -//xx(Y) -xx(ZFloor) -xx(ZCeiling) -xx(Height) -//xx(Tid) -//xx(Angle) -xx(Type) -//xx(Special) -xx(Arg0) -xx(Arg1) -xx(Arg2) -xx(Arg3) -xx(Arg4) -xx(Arg0Str) -xx(Arg1Str) -xx(Id) -xx(MoreIds) -xx(V1) -xx(V2) - -xx(Sidefront) -xx(Sideback) -xx(Offsetx) -xx(Offsety) -xx(Texturetop) -xx(Texturebottom) -xx(Texturemiddle) -xx(Sector) -xx(Heightfloor) -xx(Heightceiling) -xx(Lightlevel) -xx(Texturefloor) -xx(Textureceiling) -xx(Nodecals) - -xx(Skill1) -xx(Skill2) -xx(Skill3) -xx(Skill4) -xx(Skill5) -xx(Skill6) -xx(Skill7) -xx(Skill8) -xx(Skill9) -xx(Skill10) -xx(Skill11) -xx(Skill12) -xx(Skill13) -xx(Skill14) -xx(Skill15) -xx(Skill16) -xx(Medium) -xx(Hard) -xx(Ambush) -xx(Dormant) -xx(Class0) -xx(Class1) -xx(Class2) -xx(Class3) -xx(Class4) -xx(Class5) -xx(Class6) -xx(Class7) -xx(Class8) -xx(Class9) -xx(Class10) -xx(Class11) -xx(Class12) -xx(Class13) -xx(Class14) -xx(Class15) -xx(Class16) -xx(Single) -xx(Coop) -xx(Dm) -xx(Translucent) -xx(Invisible) -xx(Friend) -xx(Strifeally) -xx(Standing) -xx(Countsecret) -xx(NoCount) -xx(Score) -xx(Roll) -xx(Scale) -xx(ScaleX) -xx(ScaleY) -xx(FriendlySeeBlocks) -xx(Floatbobphase) -xx(Floatbobstrength) -xx(Target) -xx(Master) -xx(Tracer) - -xx(Blocking) -xx(Blockmonsters) -xx(Twosided) -xx(Dontpegtop) -xx(Dontpegbottom) -xx(Secret) -xx(Blocksound) -xx(Dontdraw) -xx(Mapped) -xx(Monsteractivate) -xx(Blockplayers) -xx(Blockeverything) -xx(Zoneboundary) -xx(Jumpover) -xx(Blockfloaters) -xx(Blocklandmonsters) -xx(Clipmidtex) -xx(Wrapmidtex) -xx(Midtex3d) -xx(Checkswitchrange) -xx(Firstsideonly) -xx(Transparent) -xx(Passuse) -xx(Repeatspecial) -xx(Conversation) -xx(Locknumber) -xx(Midtex3dimpassible) -xx(Revealed) -xx(AutomapStyle) -xx(DrawFullHeight) - -xx(Playercross) -xx(Playeruse) -xx(Playeruseback) -xx(Monstercross) -xx(Impact) -xx(Playerpush) -xx(Missilecross) -xx(Anycross) -xx(Monsteruse) -xx(Monsterpush) - -xx(ZDoom) -xx(ZDoomTranslated) -xx(Vavoom) -xx(GZDoom) -xx(Eternity) - -xx(Xpanningfloor) -xx(Ypanningfloor) -xx(Xpanningceiling) -xx(Ypanningceiling) -xx(Xscalefloor) -xx(Yscalefloor) -xx(Xscaleceiling) -xx(Yscaleceiling) -xx(Rotationfloor) -xx(Rotationceiling) -xx(Lightfloor) -xx(Lightceiling) -xx(Lightfloorabsolute) -xx(Lightceilingabsolute) -xx(Gravity) -xx(Lightcolor) -xx(Fadecolor) -xx(Color_Floor) -xx(Color_Ceiling) -xx(Color_Walltop) -xx(Color_Wallbottom) -xx(Color_Sprites) -xx(ColorAdd_Floor) -xx(ColorAdd_Ceiling) -xx(ColorAdd_Sprites) -xx(ColorAdd_Walls) -xx(NoSkyWalls) -xx(Desaturation) -xx(SoundSequence) -xx(Silent) -xx(Nofallingdamage) -xx(Dropactors) -xx(NoRespawn) -xx(Alphafloor) -xx(Alphaceiling) -xx(Renderstylefloor) -xx(Renderstyleceiling) -xx(Waterzone) -xx(portal_ceil_blocksound) -xx(portal_ceil_disabled) -xx(portal_ceil_nopass) -xx(portal_ceil_norender) -xx(portal_ceil_overlaytype) -xx(portal_ceil_useglobaltex) -xx(portal_floor_blocksound) -xx(portal_floor_disabled) -xx(portal_floor_nopass) -xx(portal_floor_norender) -xx(portal_floor_overlaytype) -xx(portal_floor_useglobaltex) -xx(scroll_ceil_x) -xx(scroll_ceil_y) -xx(scroll_ceil_type) -xx(scroll_floor_x) -xx(scroll_floor_y) -xx(scroll_floor_type) - -xx(offsetx_top) -xx(offsety_top) -xx(offsetx_mid) -xx(offsety_mid) -xx(offsetx_bottom) -xx(offsety_bottom) -xx(scalex_top) -xx(scaley_top) -xx(scalex_mid) -xx(scaley_mid) -xx(scalex_bottom) -xx(scaley_bottom) -xx(light) -xx(lightabsolute) -xx(lightfog) -xx(nofakecontrast) -xx(smoothlighting) -xx(blockprojectiles) -xx(blockuse) -xx(hidden) -xx(blocksight) -xx(blockhitscan) - -xx(nogradient_top) -xx(flipgradient_top) -xx(clampgradient_top) -xx(useowncolors_top) -xx(uppercolor_top) -xx(lowercolor_top) -xx(nogradient_mid) -xx(flipgradient_mid) -xx(clampgradient_mid) -xx(useowncolors_mid) -xx(uppercolor_mid) -xx(lowercolor_mid) -xx(nogradient_bottom) -xx(flipgradient_bottom) -xx(clampgradient_bottom) -xx(useowncolors_bottom) -xx(uppercolor_bottom) -xx(lowercolor_bottom) -xx(useowncoloradd_top) -xx(coloradd_top) -xx(useowncoloradd_mid) -xx(coloradd_mid) -xx(useowncoloradd_bottom) -xx(coloradd_bottom) -xx(colorization_top) -xx(colorization_mid) -xx(colorization_bottom) -xx(colorization_floor) -xx(colorization_ceiling) - -xx(Renderstyle) - -xx(ceilingplane_a) -xx(ceilingplane_b) -xx(ceilingplane_c) -xx(ceilingplane_d) -xx(floorplane_a) -xx(floorplane_b) -xx(floorplane_c) -xx(floorplane_d) -xx(damageamount) -xx(damagetype) -xx(damageinterval) -xx(leakiness) -xx(damageterraineffect) -xx(damagehazard) -xx(floorterrain) -xx(ceilingterrain) -xx(floor_reflect) -xx(ceiling_reflect) -xx(floorglowcolor) -xx(floorglowheight) -xx(ceilingglowcolor) -xx(ceilingglowheight) -xx(fogdensity) xx(Static) xx(Staticconst) -xx(DeathmatchStatusScreen) -xx(CoopStatusScreen) -xx(DoomStatusScreen) -xx(RavenStatusScreen) -xx(DoomStatusScreenSized) -xx(RavenStatusScreenSized) -xx(StatusbarWidget) -xx(StatusbarHead) -xx(StatusbarCondition) -xx(Next) -xx(Prev) -xx(Children) -xx(Owner) -xx(FlameThrower) -xx(HealthFloor) -xx(HealthCeiling) -xx(Health3D) -xx(DamageSpecial) -xx(DeathSpecial) -xx(HealthFloorGroup) -xx(HealthCeilingGroup) -xx(Health3DGroup) -xx(HealthGroup) - -// USDF keywords -xx(Amount) -xx(Text) -xx(Displaycost) -xx(Yesmessage) -xx(Nomessage) -xx(Log) -xx(Giveitem) -xx(Nextpage) -xx(Closedialog) -xx(Cost) -xx(Page) -xx(Count) -xx(Name) -xx(Panel) -xx(Dialog) -xx(Ifitem) -xx(Choice) -xx(Link) -xx(Goodbye) -xx(Require) -xx(Exclude) -xx(Userstring) -xx(Sky) -xx(Pagename) - -// Special menus -xx(Mainmenu) -xx(MainmenuTextOnly) -xx(Episodemenu) -xx(Playerclassmenu) -xx(HexenDefaultPlayerclassmenu) -xx(ListMenuItemBloodDripDrawer) -xx(Skillmenu) -xx(Startgame) -xx(StartgameNoSkill) -xx(StartgameConfirm) -xx(StartgameConfirmed) -xx(Loadgamemenu) -xx(Savegamemenu) -xx(Readthismenu) -xx(Optionsmenu) -xx(OptionsmenuSimple) -xx(OptionsmenuFull) -xx(Quitmenu) -xx(Savemenu) -xx(Playermenu) -xx(EndGameMenu) -xx(IngameMenu) -xx(HelpMenu) -xx(SoundMenu) -xx(ConfirmPlayerReset) -xx(HuntMenu) -xx(WeaponMenu) -xx(TargetMenu) -xx(UsermapMenu) -xx(EngineCredits) -xx(EngineCredits2) -xx(CreditsMenu) -xx(MultiMenu) - -xx(CustomGameMenu) -xx(CustomSubMenu1) -xx(CustomSubMenu2) -xx(CustomSubMenu3) -xx(CustomSubMenu4) -xx(CustomSubMenu5) -xx(CustomSubMenu6) -xx(CustomSubMenu7) - -xx(Playerbox) -xx(Team) -xx(Color) -xx(Red) -xx(Green) -xx(Blue) -xx(Skin) -xx(Gender) -xx(Autoaim) -xx(Switch) -xx(Playerdisplay) -xx(Controlmessage) -xx(Crosshairs) -xx(Colorpickermenu) -xx(Mididevices) -xx(Aldevices) -xx(Alresamplers) -xx(CustomizeControls) -xx(MessageOptions) -xx(AutomapOptions) -xx(ScoreboardOptions) -xx(MapColorMenu) -xx(GameplayOptions) -xx(CompatibilityOptions) -xx(MouseOptions) -xx(JoystickOptions) -xx(SoundOptions) -xx(AdvSoundOptions) -xx(ModReplayerOptions) -xx(VideoOptions) -xx(JoystickConfigMenu) -xx(VMEnterText) -xx(VMTestText) -xx(VideoModeMenu) -xx(res_0) -xx(res_1) -xx(res_2) -xx(res_3) -xx(res_4) -xx(res_5) -xx(res_6) -xx(res_7) -xx(res_8) -xx(res_9) -xx(AlwaysRun) - -// end sequences -xx(Inter_Chess) -xx(Inter_Strife) -xx(Inter_Strife_Good) -xx(Inter_Strife_Sad) -xx(Inter_Strife_Bad) -xx(Inter_Strife_Lose) -xx(Inter_Strife_MAP03) -xx(Inter_Strife_MAP10) -xx(Multiplayer) - -// more stuff -xx(ColorSet) -xx(NeverSwitchOnPickup) -xx(MoveBob) -xx(StillBob) -xx(ClassicFlight) -xx(WBobSpeed) -xx(WBobFire) -xx(PlayerClass) -xx(MonsterClass) -xx(MorphedMonster) -xx(Wi_NoAutostartMap) - -xx(Duration) -xx(MorphStyle) -xx(MorphFlash) -xx(UnMorphFlash) -xx(Powerup) -xx(EffectTics) -xx(PowerupGiver) -xx(BlendColor) -xx(Strength) -xx(Mode) -xx(PowerupType) -xx(PlayerPawn) -xx(Key) - -// Decorate compatibility functions -xx(BuiltinTypeCheck) -xx(BuiltinRandom) -xx(BuiltinRandom2) -xx(BuiltinFRandom) -xx(BuiltinCallLineSpecial) -xx(BuiltinNameToClass) -xx(BuiltinFindMultiNameState) -xx(BuiltinFindSingleNameState) -xx(BuiltinHandleRuntimeState) -xx(BuiltinGetDefault) -xx(BuiltinClassCast) -xx(BuiltinFormat) -xx(Damage) -xx(Noattack) +xy(menu_cursor, "menu/cursor") +xy(menu_choose, "menu/choose") +xy(menu_backup, "menu/backup") +xy(menu_clear, "menu/clear") +xy(menu_dismiss, "menu/dismiss") +xy(menu_change, "menu/change") +xy(menu_advance, "menu/advance") // basic type names xx(Default) @@ -908,11 +120,6 @@ xx(self) xx(invoker) xx(stateinfo) -xx(__decorate_internal_int__) -xx(__decorate_internal_bool__) -xx(__decorate_internal_float__) -xx(ResolveState) - xx(DamageFunction) xx(Length) xx(Unit) @@ -932,46 +139,12 @@ xx(Exists) xx(SetInvalid) xx(SetNull) -xx(A_Punch) -xx(A_FirePistol) -xx(A_FireShotgun) -xx(A_FireShotgun2) -xx(A_FireCGun) -xx(A_FireMissile) -xx(A_Saw) -xx(A_FirePlasma) -xx(A_FireBFG) -xx(A_FireOldBFG) -xx(A_FireRailgun) - // color channels xx(a) xx(r) xx(g) xx(b) -// Special translation names -xx(RainPillar1) -xx(RainPillar2) -xx(RainPillar3) -xx(RainPillar4) -xx(RainPillar5) -xx(RainPillar6) -xx(RainPillar7) -xx(RainPillar8) - -xx(Player1) -xx(Player2) -xx(Player3) -xx(Player4) -xx(Player5) -xx(Player6) -xx(Player7) -xx(Player8) -xx(PlayerChunk) -xx(RestrictedToPlayerClass) -xx(ForbiddenToPlayerClass) - xx(Prototype) xx(Void) xx(Label) @@ -987,6 +160,33 @@ xx(Both) xx(Physical) xx(Visual) +// blacklisted former CVARs (used by common menu code) +xx(snd_waterlp) +xx(snd_output) +xx(snd_output_format) +xx(snd_speakermode) +xx(snd_resampler) +xx(AlwaysRun) + +// menu names +xx(Mainmenu) +xx(Episodemenu) +xx(Skillmenu) +xx(Startgame) +xx(StartgameConfirm) +xx(StartgameConfirmed) +xx(Loadgamemenu) +xx(Savegamemenu) +xx(Optionsmenu) +xx(OptionsmenuSimple) +xx(OptionsmenuFull) +xx(Quitmenu) +xx(Savemenu) +xx(EndGameMenu) +xx(HelpMenu) +xx(SoundMenu) +xx(ConfirmPlayerReset) + xx(OptionMenuItemSubmenu) xx(OptionMenuItemCommand) xx(OptionMenuItemControlBase) @@ -997,20 +197,7 @@ xx(OptionMenuItemColorPicker) xx(OptionMenuItemStaticText) xx(OptionMenuItemStaticTextSwitchable) -// blacklisted former CVARs -xx(snd_waterlp) -xx(snd_output) -xx(snd_output_format) -xx(snd_speakermode) -xx(snd_resampler) - -// ScriptUtil entry points -xx(ScriptUtil) -xx(SetMarineWeapon) -xx(SetMarineSprite) -xx(GiveInventory) -xx(TakeInventory) -xx(ClearInventory) +xx(Color) // Weapon member fields that need direct access xx(Ammo1) @@ -1035,82 +222,18 @@ xx(PickupSound) xx(WeaponScaleX) xx(WeaponScaleY) -// PlayerPawn member fields -xx(ColorRangeStart) -xx(ColorRangeEnd) -xx(InvFirst) -xx(ForwardMove1) -xx(ForwardMove2) -xx(SideMove1) -xx(SideMove2) -xx(Face) -xx(Slot) -xx(SoundClass) -xx(ViewBob) -xx(DamageFade) -xx(MaxHealth) -xx(crouchsprite) -xx(UseRange) -xx(AttackZOffset) -xx(SpawnMask) -xx(ScoreIcon) -xx(ViewHeight) -xx(ViewAngle) -xx(ViewPitch) -xx(ViewRoll) -xx(FallingScreamMinSpeed) -xx(FallingScreamMaxSpeed) -xx(GruntSpeed) -xx(JumpZ) -xx(MugShotMaxHealth) -xx(BonusHealth) -xx(PlayerFlags) -xx(InvSel) -xx(FullHeight) +xx(Mididevices) +xx(Aldevices) +xx(Alresamplers) -xx(BlueCard) -xx(YellowCard) -xx(RedCard) -xx(BlueSkull) -xx(YellowSkull) -xx(RedSkull) -xx(DynamicLight) -xx(SpotInnerAngle) -xx(SpotOuterAngle) -xx(lightflags) -xx(lighttype) -xx(InternalDynamicLight) -xx(_a_chase_default) -xx(MapMarker) -xx(Spawn2) -xx(LevelLocals) -xx(Level) -xx(PlayerTeam) -xx(PlayerColors) -xx(PlayerSkin) -xx(NewPlayerMenu) -xx(AltHud) -xx(GameScreen) -xx(ListM) +// Decorate compatibility functions +xx(BuiltinRandom) +xx(BuiltinRandom2) +xx(BuiltinFRandom) +xx(BuiltinNameToClass) +xx(BuiltinClassCast) -// summary -xx(cwidth) -xx(cheight) -xx(wrapwidth) -xx(scalefactorx) -xx(scalefactory) -xx(scalemode) - -xy(menu_cursor, "menu/cursor") -xy(menu_choose, "menu/choose") -xy(menu_backup, "menu/backup") -xy(menu_clear, "menu/clear") -xy(menu_dismiss, "menu/dismiss") -xy(menu_change, "menu/change") -xy(menu_advance, "menu/advance") - -xx(zoomsize) xx(ScreenJobRunner) -xx(RazeStatusBar) -xx(RipSound) -xx(Archvile) + + + diff --git a/src/common/engine/palettecontainer.cpp b/src/common/engine/palettecontainer.cpp index 73fb2bdb9..9648f2528 100644 --- a/src/common/engine/palettecontainer.cpp +++ b/src/common/engine/palettecontainer.cpp @@ -234,7 +234,7 @@ void PaletteContainer::UpdateTranslation(int trans, FRemapTable* remap) int PaletteContainer::AddTranslation(int slot, FRemapTable* remap, int count) { - uint32_t id; + uint32_t id = 0; for (int i = 0; i < count; i++) { auto newremap = AddRemap(&remap[i]); @@ -265,7 +265,7 @@ FRemapTable *PaletteContainer::TranslationToTable(int translation) unsigned int type = GetTranslationType(translation); unsigned int index = GetTranslationIndex(translation); - if (type < 0 || type >= TranslationTables.Size() || index >= NumTranslations(type)) + if (type >= TranslationTables.Size() || index >= NumTranslations(type)) { return uniqueRemaps[0]; // this is the identity table. } @@ -649,7 +649,6 @@ bool FRemapTable::AddTint(int start, int end, int r, int g, int b, int amount) bool FRemapTable::AddToTranslation(const char *range) { int start,end; - bool desaturated = false; FScanner sc; sc.OpenMem("translation", range, int(strlen(range))); diff --git a/src/common/engine/sc_man.cpp b/src/common/engine/sc_man.cpp index 29b0b445b..bbc209b14 100644 --- a/src/common/engine/sc_man.cpp +++ b/src/common/engine/sc_man.cpp @@ -857,7 +857,7 @@ bool FScanner::CheckFloat (bool evaluate) UnGet(); return false; } - + Float = strtod (String, &stopper); if (*stopper != 0) { @@ -1131,9 +1131,7 @@ FString FScanner::TokenName (int token, const char *string) } else { - FString work; - work.Format ("Unknown(%d)", token); - return work; + work.Format("Unknown(%d)", token); } return work; } diff --git a/src/common/engine/sc_man.h b/src/common/engine/sc_man.h index 1caa177a2..a39b8f5c3 100644 --- a/src/common/engine/sc_man.h +++ b/src/common/engine/sc_man.h @@ -159,7 +159,7 @@ public: { return constants.CheckKey(name); } - + // Token based variant bool CheckValue(bool allowfloat, bool evaluate = true); void MustGetValue(bool allowfloat, bool evaluate = true); diff --git a/src/common/engine/sc_man_scanner.re b/src/common/engine/sc_man_scanner.re index b10f48081..145abea41 100644 --- a/src/common/engine/sc_man_scanner.re +++ b/src/common/engine/sc_man_scanner.re @@ -102,14 +102,14 @@ std2: ":" { RET(':'); } ";" { RET(';'); } "}" { StateMode = 0; StateOptions = false; RET('}'); } - + WSP+ { goto std1; } "\n" { goto newline; } - + TOKS = (NWS\[/":;}]); TOKS* ([/] (TOKS\[*]) TOKS*)* { RET(TK_NonWhitespace); } - + */ } else if (tokens) // A well-defined scanner, based on the c.re example. @@ -222,7 +222,7 @@ std2: 'canraise' { RET(StateOptions ? TK_CanRaise : TK_Identifier); } 'offset' { RET(StateOptions ? TK_Offset : TK_Identifier); } 'light' { RET(StateOptions ? TK_Light : TK_Identifier); } - + /* other DECORATE top level keywords */ '#include' { RET(TK_Include); } diff --git a/src/common/engine/serializer.cpp b/src/common/engine/serializer.cpp index 505bd044d..f42289573 100644 --- a/src/common/engine/serializer.cpp +++ b/src/common/engine/serializer.cpp @@ -290,6 +290,28 @@ bool FSerializer::BeginObject(const char *name) // //========================================================================== +bool FSerializer::HasObject(const char* name) +{ + if (isReading()) + { + auto val = r->FindKey(name); + if (val != nullptr) + { + if (val->IsObject()) + { + return true; + } + } + } + return false; +} + +//========================================================================== +// +// +// +//========================================================================== + void FSerializer::EndObject() { if (isWriting()) @@ -601,7 +623,7 @@ void FSerializer::WriteObjects() void FSerializer::ReadObjects(bool hubtravel) { bool founderrors = false; - + if (isReading() && BeginArray("objects")) { // Do not link any thinker that's being created here. This will be done by deserializing the thinker list later. @@ -619,7 +641,6 @@ void FSerializer::ReadObjects(bool hubtravel) if (BeginObject(nullptr)) { FString clsname; // do not deserialize the class type directly so that we can print appropriate errors. - int pindex = -1; Serialize(*this, "classtype", clsname, nullptr); PClass *cls = PClass::FindClass(clsname); @@ -643,6 +664,7 @@ void FSerializer::ReadObjects(bool hubtravel) if (!founderrors) { // Reset to start; + unsigned size = r->mObjects.Size(); r->mObjects.Last().mIndex = 0; for (unsigned i = 0; i < r->mDObjects.Size(); i++) @@ -652,7 +674,6 @@ void FSerializer::ReadObjects(bool hubtravel) { if (obj != nullptr) { - int pindex = -1; try { obj->SerializeUserVars(*this); @@ -660,6 +681,7 @@ void FSerializer::ReadObjects(bool hubtravel) } catch (CRecoverableError &err) { + r->mObjects.Clamp(size); // close all inner objects. // In case something in here throws an error, let's continue and deal with it later. Printf(TEXTCOLOR_RED "'%s'\n while restoring %s\n", err.GetMessage(), obj ? obj->GetClass()->TypeName.GetChars() : "invalid object"); mErrors++; diff --git a/src/common/engine/serializer.h b/src/common/engine/serializer.h index 400a6f4aa..b114923df 100644 --- a/src/common/engine/serializer.h +++ b/src/common/engine/serializer.h @@ -85,6 +85,7 @@ public: void ReadObjects(bool hubtravel); bool BeginObject(const char *name); void EndObject(); + bool HasObject(const char* name); bool BeginArray(const char *name); void EndArray(); unsigned GetSize(const char *group); @@ -110,7 +111,7 @@ public: { return w != nullptr; } - + bool canSkip() const; template @@ -234,7 +235,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundI FSerializer &Serialize(FSerializer &arc, const char *key, FString &sid, FString *def); FSerializer &Serialize(FSerializer &arc, const char *key, NumericValue &sid, NumericValue *def); -template +template >*/> FSerializer &Serialize(FSerializer &arc, const char *key, T *&value, T **) { DObject *v = static_cast(value); @@ -301,6 +302,11 @@ FSerializer& Serialize(FSerializer& arc, const char* key, FixedBitArray& v return arc.SerializeMemory(key, value.Storage(), value.StorageSize()); } +inline FSerializer& Serialize(FSerializer& arc, const char* key, BitArray& value, BitArray* def) +{ + return arc.SerializeMemory(key, value.Storage().Data(), value.Storage().Size()); +} + template<> FSerializer& Serialize(FSerializer& arc, const char* key, PClass*& clst, PClass** def); template<> FSerializer& Serialize(FSerializer& arc, const char* key, FFont*& font, FFont** def); template<> FSerializer &Serialize(FSerializer &arc, const char *key, Dictionary *&dict, Dictionary **def); diff --git a/src/common/engine/serializer_internal.h b/src/common/engine/serializer_internal.h index e05d5785c..31cf76c1a 100644 --- a/src/common/engine/serializer_internal.h +++ b/src/common/engine/serializer_internal.h @@ -42,7 +42,7 @@ struct FWriter rapidjson::StringBuffer mOutString; TArray mDObjects; TMap mObjectMap; - + FWriter(bool pretty) { if (!pretty) @@ -193,7 +193,7 @@ struct FReader rapidjson::Value *FindKey(const char *key) { FJSONObject &obj = mObjects.Last(); - + if (obj.mObject->IsObject()) { if (key == nullptr) diff --git a/src/common/engine/st_start.h b/src/common/engine/st_start.h index 1456e051c..09eb6ae67 100644 --- a/src/common/engine/st_start.h +++ b/src/common/engine/st_start.h @@ -47,7 +47,7 @@ public: CurPos = 0; NotchPos = 0; } - + virtual ~FStartupScreen() = default; virtual void Progress() {} @@ -98,7 +98,7 @@ public: void AppendStatusLine(const char *status); protected: void SetWindowSize(); - + int ThermX, ThermY, ThermWidth, ThermHeight; int HMsgY, SMsgX; }; diff --git a/src/common/engine/stats.h b/src/common/engine/stats.h index 3e048ac16..735931cb5 100644 --- a/src/common/engine/stats.h +++ b/src/common/engine/stats.h @@ -61,28 +61,28 @@ public: { Sec = 0; } - + void Clock() { timespec ts; - + clock_gettime(CLOCK_MONOTONIC, &ts); Sec -= ts.tv_sec + ts.tv_nsec * 1e-9; } - + void Unclock() { timespec ts; - + clock_gettime(CLOCK_MONOTONIC, &ts); Sec += ts.tv_sec + ts.tv_nsec * 1e-9; } - + double Time() { return Sec; } - + double TimeMS() { return Sec * 1e3; @@ -159,24 +159,24 @@ public: { Counter = 0; } - + void Clock() { int64_t time = rdtsc(); Counter -= time; } - + void Unclock(bool checkvar = true) { int64_t time = rdtsc(); Counter += time; } - + double Time() { return Counter * PerfToSec; } - + double TimeMS() { return Counter * PerfToMillisec; diff --git a/src/common/engine/stringtable.cpp b/src/common/engine/stringtable.cpp index b36e6e409..92819c144 100644 --- a/src/common/engine/stringtable.cpp +++ b/src/common/engine/stringtable.cpp @@ -639,7 +639,7 @@ bool FStringTable::MatchDefaultString(const char *name, const char *content) con // This only compares the first line to avoid problems with bad linefeeds. For the few cases where this feature is needed it is sufficient. auto c = GetLanguageString(name, FStringTable::default_table); if (!c) return false; - + // Check a secondary key, in case the text comparison cannot be done due to needed orthographic fixes (see Harmony's exit text) FStringf checkkey("%s_CHECK", name); auto cc = GetLanguageString(checkkey, FStringTable::default_table); diff --git a/src/common/engine/stringtable.h b/src/common/engine/stringtable.h index 0467b27ed..d75864303 100644 --- a/src/common/engine/stringtable.h +++ b/src/common/engine/stringtable.h @@ -91,7 +91,7 @@ public: allStrings.Insert(override_table, map); UpdateLanguage(nullptr); } - + const char *GetLanguageString(const char *name, uint32_t langtable, int gender = -1) const; bool MatchDefaultString(const char *name, const char *content) const; const char *GetString(const char *name, uint32_t *langtable, int gender = -1) const; @@ -110,7 +110,7 @@ private: StringMacroMap allMacros; LangMap allStrings; TArray> currentLanguageSet; - + void LoadLanguage (int lumpnum, const TArray &buffer); TArray> parseCSV(const TArray &buffer); bool ParseLanguageCSV(int lumpnum, const TArray &buffer); @@ -127,7 +127,7 @@ public: if (*str == '$') return str; return FString("$") + str; } - + static FString MakeMacro(const char *str, size_t len) { if (*str == '$') return FString(str, len); diff --git a/src/common/engine/v_colortables.cpp b/src/common/engine/v_colortables.cpp index 36849862b..b891ff142 100644 --- a/src/common/engine/v_colortables.cpp +++ b/src/common/engine/v_colortables.cpp @@ -57,7 +57,7 @@ ColorTable256k RGB256k; void BuildTransTable (const PalEntry *palette) { int r, g, b; - + // create the RGB555 lookup table for (r = 0; r < 32; r++) for (g = 0; g < 32; g++) @@ -68,16 +68,16 @@ void BuildTransTable (const PalEntry *palette) for (g = 0; g < 64; g++) for (b = 0; b < 64; b++) RGB256k.RGB[r][g][b] = ColorMatcher.Pick ((r<<2)|(r>>4), (g<<2)|(g>>4), (b<<2)|(b>>4)); - + int x, y; - + // create the swizzled palette for (x = 0; x < 65; x++) for (y = 0; y < 256; y++) Col2RGB8[x][y] = (((palette[y].r*x)>>4)<<20) | ((palette[y].g*x)>>4) | (((palette[y].b*x)>>4)<<10); - + // create the swizzled palette with the lsb of red and blue forced to 0 // (for green, a 1 is okay since it never gets added into) for (x = 1; x < 64; x++) @@ -90,7 +90,7 @@ void BuildTransTable (const PalEntry *palette) } Col2RGB8_LessPrecision[0] = Col2RGB8[0]; Col2RGB8_LessPrecision[64] = Col2RGB8[64]; - + // create the inverse swizzled palette for (x = 0; x < 65; x++) for (y = 0; y < 256; y++) diff --git a/src/common/filesystem/file_directory.cpp b/src/common/filesystem/file_directory.cpp index 8c7b57876..80b9f6e57 100644 --- a/src/common/filesystem/file_directory.cpp +++ b/src/common/filesystem/file_directory.cpp @@ -41,8 +41,6 @@ #include "printf.h" #include "findfile.h" - - //========================================================================== // // Zip Lump @@ -120,7 +118,7 @@ int FDirectory::AddDirectory(const char *dirpath) FString dirmatch = dirpath; findstate_t find; dirmatch += '*'; - + handle = I_FindFirst(dirmatch.GetChars(), &find); if (handle == ((void *)(-1))) { diff --git a/src/common/filesystem/file_grp.cpp b/src/common/filesystem/file_grp.cpp index 97f17f17f..7128c1307 100644 --- a/src/common/filesystem/file_grp.cpp +++ b/src/common/filesystem/file_grp.cpp @@ -99,7 +99,7 @@ bool FGrpFile::Open(bool quiet, LumpFilterInfo*) Reader.Read(&header, sizeof(header)); NumLumps = LittleLong(header.NumLumps); - + GrpLump *fileinfo = new GrpLump[NumLumps]; Reader.Read (fileinfo, NumLumps * sizeof(GrpLump)); diff --git a/src/common/filesystem/file_pak.cpp b/src/common/filesystem/file_pak.cpp index 13aafa985..3a868766c 100644 --- a/src/common/filesystem/file_pak.cpp +++ b/src/common/filesystem/file_pak.cpp @@ -95,7 +95,7 @@ bool FPakFile::Open(bool quiet, LumpFilterInfo* filter) Reader.Read(&header, sizeof(header)); NumLumps = LittleLong(header.dirlen) / sizeof(dpackfile_t); header.dirofs = LittleLong(header.dirofs); - + TArray fileinfo(NumLumps, true); Reader.Seek (header.dirofs, FileReader::SeekSet); Reader.Read (fileinfo.Data(), NumLumps * sizeof(dpackfile_t)); diff --git a/src/common/filesystem/file_rff.cpp b/src/common/filesystem/file_rff.cpp index e8c4fce81..3e512b62d 100644 --- a/src/common/filesystem/file_rff.cpp +++ b/src/common/filesystem/file_rff.cpp @@ -221,7 +221,7 @@ int FRFFLump::FillCache() { int cryptlen = min (LumpSize, 256); uint8_t *data = (uint8_t *)Cache; - + for (int i = 0; i < cryptlen; ++i) { data[i] ^= i >> 1; diff --git a/src/common/filesystem/file_wad.cpp b/src/common/filesystem/file_wad.cpp index 054b0721a..8af39b5f8 100644 --- a/src/common/filesystem/file_wad.cpp +++ b/src/common/filesystem/file_wad.cpp @@ -206,7 +206,7 @@ bool FWadFile::Open(bool quiet, LumpFilterInfo*) Lumps[i].LumpSize = isBigEndian ? BigLong(fileinfo[i].Size) : LittleLong(fileinfo[i].Size); Lumps[i].Namespace = ns_global; Lumps[i].Flags = Lumps[i].Compressed ? LUMPF_COMPRESSED | LUMPF_SHORTNAME : LUMPF_SHORTNAME; - + // Check if the lump is within the WAD file and print a warning if not. if (Lumps[i].Position + Lumps[i].LumpSize > wadSize || Lumps[i].Position < 0 || Lumps[i].LumpSize < 0) { @@ -279,7 +279,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name int numstartmarkers = 0, numendmarkers = 0; unsigned int i; TArray markers; - + for(i = 0; i < NumLumps; i++) { if (IsMarker(i, startmarker)) @@ -302,20 +302,20 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", endmarker, startmarker); - + if (flathack) { // We have found no F_START but one or more F_END markers. // mark all lumps before the last F_END marker as potential flats. unsigned int end = markers[markers.Size()-1].index; - for(unsigned int i = 0; i < end; i++) + for(unsigned int ii = 0; ii < end; ii++) { - if (Lumps[i].LumpSize == 4096) + if (Lumps[ii].LumpSize == 4096) { // We can't add this to the flats namespace but // it needs to be flagged for the texture manager. - DPrintf(DMSG_NOTIFY, "Marking %s as potential flat\n", Lumps[i].getName()); - Lumps[i].Flags |= LUMPF_MAYBEFLAT; + DPrintf(DMSG_NOTIFY, "Marking %s as potential flat\n", Lumps[ii].getName()); + Lumps[ii].Flags |= LUMPF_MAYBEFLAT; } } } @@ -428,18 +428,19 @@ void FWadFile::SkinHack () namespc++; } } + // needless to say, this check is entirely useless these days as map names can be more diverse.. if ((lump->getName()[0] == 'M' && lump->getName()[1] == 'A' && lump->getName()[2] == 'P' && lump->getName()[3] >= '0' && lump->getName()[3] <= '9' && lump->getName()[4] >= '0' && lump->getName()[4] <= '9' && - lump->getName()[5] >= '\0') + lump->getName()[5] == '\0') || (lump->getName()[0] == 'E' && lump->getName()[1] >= '0' && lump->getName()[1] <= '9' && lump->getName()[2] == 'M' && lump->getName()[3] >= '0' && lump->getName()[3] <= '9' && - lump->getName()[4] >= '\0')) + lump->getName()[4] == '\0')) { hasmap = true; } diff --git a/src/common/filesystem/file_whres.cpp b/src/common/filesystem/file_whres.cpp index 1c573ad38..969aaafab 100644 --- a/src/common/filesystem/file_whres.cpp +++ b/src/common/filesystem/file_whres.cpp @@ -95,10 +95,10 @@ FWHResFile::FWHResFile(const char *filename, FileReader &file) bool FWHResFile::Open(bool quiet, LumpFilterInfo*) { int directory[1024]; - + Reader.Seek(-4096, FileReader::SeekEnd); Reader.Read(directory, 4096); - + int nl =1024/3; Lumps.Resize(nl); @@ -135,10 +135,10 @@ FResourceFile *CheckWHRes(const char *filename, FileReader &file, bool quiet, Lu { int directory[1024]; int nl =1024/3; - + file.Seek(-4096, FileReader::SeekEnd); file.Read(directory, 4096); - + int checkpos = 0; for(int k = 0; k < nl; k++) { diff --git a/src/common/filesystem/filesystem.cpp b/src/common/filesystem/filesystem.cpp index 47932334d..6e3bea388 100644 --- a/src/common/filesystem/filesystem.cpp +++ b/src/common/filesystem/filesystem.cpp @@ -218,14 +218,13 @@ void FileSystem::InitMultipleFiles (TArray &filenames, bool quiet, Lump for(unsigned i=0;iGetHash().GetChars()); MoveLumpsInFolder(path); } - + NumEntries = FileInfo.Size(); if (NumEntries == 0) { @@ -284,7 +283,7 @@ int FileSystem::AddFromBuffer(const char* name, const char* type, char* data, in FileInfo.Last().resourceId = id; return FileInfo.Size()-1; } - + //========================================================================== // // AddFile @@ -333,7 +332,7 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L startlump = NumEntries; FResourceFile *resfile; - + if (!isdir) resfile = FResourceFile::OpenResourceFile(filename, filereader, quiet, false, filter); else @@ -946,10 +945,10 @@ void FileSystem::MoveLumpsInFolder(const char *path) { return; } - + auto len = strlen(path); auto rfnum = FileInfo.Last().rfnum; - + unsigned i; for (i = 0; i < FileInfo.Size(); i++) { @@ -1022,7 +1021,7 @@ int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, in { if (anyns || lump_p->Namespace == ns_global) { - + for(const char **name = names; *name != NULL; name++) { if (!strnicmp(*name, lump_p->shortName.String, 8)) @@ -1512,7 +1511,7 @@ int FileSystem::GetEntryCount (int rfnum) const noexcept { return 0; } - + return Files[rfnum]->LumpCount(); } @@ -1669,3 +1668,20 @@ FResourceLump* FileSystem::GetFileAt(int no) return FileInfo[no].lump; } +#include "c_dispatch.h" + +CCMD(fs_dir) +{ + int numfiles = fileSystem.GetNumEntries(); + + for (int i = 0; i < numfiles; i++) + { + auto container = fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(i)); + auto fn1 = fileSystem.GetFileFullName(i); + auto fns = fileSystem.GetFileShortName(i); + auto fnid = fileSystem.GetResourceId(i); + auto length = fileSystem.FileLength(i); + bool hidden = fileSystem.FindFile(fn1) != i; + Printf(PRINT_NONOTIFY, "%s%-64s %-15s (%5d) %10d %s %s\n", hidden ? TEXTCOLOR_RED : TEXTCOLOR_UNTRANSLATED, fn1, fns, fnid, length, container, hidden ? "(h)" : ""); + } +} \ No newline at end of file diff --git a/src/common/filesystem/resourcefile.cpp b/src/common/filesystem/resourcefile.cpp index cc2a27345..3b8e39915 100644 --- a/src/common/filesystem/resourcefile.cpp +++ b/src/common/filesystem/resourcefile.cpp @@ -306,11 +306,11 @@ int lumpcmp(const void * a, const void * b) void FResourceFile::GenerateHash() { // hash the lump directory after sorting - + Hash.Format(("%08X-%04X-"), (unsigned)Reader.GetLength(), NumLumps); - + MD5Context md5; - + uint8_t digest[16]; for(uint32_t i = 0; i < NumLumps; i++) { @@ -382,9 +382,9 @@ int FResourceFile::FilterLumps(FString filtername, void *lumps, size_t lumpsize, return 0; } filter << "filter/" << filtername << '/'; - + bool found = FindPrefixRange(filter, lumps, lumpsize, max, start, end); - + // Workaround for old Doom filter names. if (!found && filtername.IndexOf("doom.id.doom") == 0) { @@ -490,7 +490,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize { uint32_t min, max, mid, inside; FResourceLump *lump; - int cmp; + int cmp = 0; end = start = 0; @@ -499,7 +499,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize lumps = (uint8_t *)lumps - lumpsize; // Binary search to find any match at all. - min = 1, max = maxlump; + mid = min = 1, max = maxlump; while (min <= max) { mid = min + (max - min) / 2; diff --git a/src/common/filesystem/resourcefile.h b/src/common/filesystem/resourcefile.h index 5e9276c76..d64c278e8 100644 --- a/src/common/filesystem/resourcefile.h +++ b/src/common/filesystem/resourcefile.h @@ -6,6 +6,7 @@ #include #include "files.h" +#include "zstring.h" struct LumpFilterInfo { diff --git a/src/common/fonts/font.cpp b/src/common/fonts/font.cpp index 9dc4fee33..e554f6366 100644 --- a/src/common/fonts/font.cpp +++ b/src/common/fonts/font.cpp @@ -86,10 +86,10 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla TMap charMap; int minchar = INT_MAX; int maxchar = INT_MIN; - + // Read the font's configuration. // This will not be done for the default fonts, because they are not atomic and the default content does not need it. - + TArray folderdata; if (filetemplate != nullptr) { @@ -97,16 +97,16 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla // If a name template is given, collect data from all resource files. // For anything else, each folder is being treated as an atomic, self-contained unit and mixing from different glyph sets is blocked. fileSystem.GetFilesInFolder(path, folderdata, nametemplate == nullptr); - + //if (nametemplate == nullptr) { FStringf infpath("fonts/%s/font.inf", filetemplate); - + unsigned index = folderdata.FindEx([=](const FolderEntry &entry) { return infpath.CompareNoCase(entry.name) == 0; }); - + if (index < folderdata.Size()) { FScanner sc; @@ -182,7 +182,7 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla } } } - + if (FixedWidth > 0) { ReadSheetFont(folderdata, FixedWidth, FontHeight, Scale); @@ -292,12 +292,12 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla auto position = strtoll(base.GetChars(), &endp, 16); if ((*endp == 0 || (*endp == '.' && position >= '!' && position < 0xffff))) { - auto lump = TexMan.CheckForTexture(entry.name, ETextureType::MiscPatch); - if (lump.isValid()) + auto texlump = TexMan.CheckForTexture(entry.name, ETextureType::MiscPatch); + if (texlump.isValid()) { if ((int)position < minchar) minchar = (int)position; if ((int)position > maxchar) maxchar = (int)position; - auto tex = TexMan.GetGameTexture(lump); + auto tex = TexMan.GetGameTexture(texlump); tex->SetScale((float)Scale.X, (float)Scale.Y); charMap.Insert((int)position, tex); Type = Folder; @@ -313,10 +313,10 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla for (i = 0; i < count; i++) { - auto lump = charMap.CheckKey(FirstChar + i); - if (lump != nullptr) + auto charlump = charMap.CheckKey(FirstChar + i); + if (charlump != nullptr) { - auto pic = *lump; + auto pic = *charlump; if (pic != nullptr) { double fheight = pic->GetDisplayHeight(); @@ -399,8 +399,8 @@ void FFont::ReadSheetFont(TArray &folderdata, int width, int height part[0].OriginY = -height * y; part[0].TexImage = static_cast(tex->GetTexture()); FMultiPatchTexture *image = new FMultiPatchTexture(width, height, part, false, false); - FImageTexture *tex = new FImageTexture(image); - auto gtex = MakeGameTexture(tex, nullptr, ETextureType::FontChar); + FImageTexture *imgtex = new FImageTexture(image); + auto gtex = MakeGameTexture(imgtex, nullptr, ETextureType::FontChar); gtex->SetWorldPanning(true); gtex->SetOffsets(0, 0, 0); gtex->SetOffsets(1, 0, 0); @@ -424,7 +424,6 @@ void FFont::ReadSheetFont(TArray &folderdata, int width, int height LastChar = maxchar; auto count = maxchar - minchar + 1; Chars.Resize(count); - int fontheight = 0; for (int i = 0; i < count; i++) { @@ -560,10 +559,10 @@ FFont *FFont::FindFont (FName name) void RecordTextureColors (FImageSource *pic, uint32_t *usedcolors) { int x; - + auto pixels = pic->GetPalettedPixels(false); auto size = pic->GetWidth() * pic->GetHeight(); - + for(x = 0;x < size; x++) { usedcolors[pixels[x]]++; @@ -728,7 +727,7 @@ int FFont::GetCharCode(int code, bool needpic) const { return code; } - + // Use different substitution logic based on the fonts content: // In a font which has both upper and lower case, prefer unaccented small characters over capital ones. // In a pure upper-case font, do not check for lower case replacements. @@ -806,7 +805,7 @@ FGameTexture *FFont::GetChar (int code, int translation, int *const width) const code -= FirstChar; xmove = Chars[code].XMove; } - + if (width != nullptr) { *width = xmove; diff --git a/src/common/fonts/hexfont.cpp b/src/common/fonts/hexfont.cpp index 612d3d326..3b985619e 100644 --- a/src/common/fonts/hexfont.cpp +++ b/src/common/fonts/hexfont.cpp @@ -266,7 +266,7 @@ int FHexFontChar2::CopyPixels(FBitmap* bmp, int conversion) class FHexFont : public FFont { - + public: //========================================================================== // @@ -283,14 +283,14 @@ public: assert(lump >= 0); FontName = fontname; - + FirstChar = hexdata.FirstChar; LastChar = hexdata.LastChar; FontHeight = 16; SpaceWidth = 9; GlobalKerning = 0; - + Chars.Resize(LastChar - FirstChar + 1); for (int i = FirstChar; i <= LastChar; i++) { @@ -325,7 +325,7 @@ public: else Translations[i] = LuminosityTranslation(i * 2 + 1, minlum, maxlum); } } - + }; diff --git a/src/common/fonts/singlelumpfont.cpp b/src/common/fonts/singlelumpfont.cpp index 7725cdb2d..d3bee25a3 100644 --- a/src/common/fonts/singlelumpfont.cpp +++ b/src/common/fonts/singlelumpfont.cpp @@ -96,7 +96,7 @@ protected: void LoadFON1 (int lump, const uint8_t *data); void LoadFON2 (int lump, const uint8_t *data); void LoadBMF (int lump, const uint8_t *data); - + enum { FONT1, @@ -259,7 +259,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data) LastChar = data[7]; ActiveColors = data[10]+1; RescalePalette = data[9] == 0; - + count = LastChar - FirstChar + 1; Chars.Resize(count); TArray widths2(count, true); @@ -309,9 +309,9 @@ void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data) } Palette[0] = 0; - for (int i = 1; i < ActiveColors; i++) + for (int pp = 1; pp < ActiveColors; pp++) { - Palette[i] = PalEntry(255, palette[i * 3], palette[i * 3 + 1], palette[i * 3 + 2]); + Palette[pp] = PalEntry(255, palette[pp * 3], palette[pp * 3 + 1], palette[pp * 3 + 2]); } data_p = palette + ActiveColors*3; diff --git a/src/common/fonts/specialfont.cpp b/src/common/fonts/specialfont.cpp index b00a19ad3..9c35f2a8a 100644 --- a/src/common/fonts/specialfont.cpp +++ b/src/common/fonts/specialfont.cpp @@ -102,12 +102,12 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FGameTexture if (charlumps[i] != nullptr) { - auto pic = charlumps[i]; - Chars[i].OriginalPic = MakeGameTexture(pic->GetTexture(), nullptr, ETextureType::FontChar); - Chars[i].OriginalPic->CopySize(pic, true); + auto charpic = charlumps[i]; + Chars[i].OriginalPic = MakeGameTexture(charpic->GetTexture(), nullptr, ETextureType::FontChar); + Chars[i].OriginalPic->CopySize(charpic, true); TexMan.AddGameTexture(Chars[i].OriginalPic); Chars[i].XMove = (int)Chars[i].OriginalPic->GetDisplayWidth(); - if (sysCallbacks.FontCharCreated) sysCallbacks.FontCharCreated(pic, Chars[i].OriginalPic); + if (sysCallbacks.FontCharCreated) sysCallbacks.FontCharCreated(charpic, Chars[i].OriginalPic); } else { diff --git a/src/common/fonts/v_font.cpp b/src/common/fonts/v_font.cpp index a9c6d1cf6..28af85202 100644 --- a/src/common/fonts/v_font.cpp +++ b/src/common/fonts/v_font.cpp @@ -106,10 +106,10 @@ FFont *V_GetFont(const char *name, const char *fontlumpname) int lump = -1; int folderfile = -1; - + TArray folderdata; FStringf path("fonts/%s/", name); - + // Use a folder-based font only if it comes from a later file than the single lump version. if (fileSystem.GetFilesInFolder(path, folderdata, true)) { @@ -119,7 +119,7 @@ FFont *V_GetFont(const char *name, const char *fontlumpname) lump = fileSystem.CheckNumForFullName(fontlumpname? fontlumpname : name, true); - + if (lump != -1 && fileSystem.GetFileContainer(lump) >= folderfile) { uint32_t head; @@ -725,9 +725,9 @@ static void CalcDefaultTranslation(FFont* base, int index) auto lum = otherluminosity[i]; if (lum >= 0 && lum <= 1) { - int index = int(lum * 255); - remap[index] = GPalette.BaseColors[i]; - remap[index].a = 255; + int lumidx = int(lum * 255); + remap[lumidx] = GPalette.BaseColors[i]; + remap[lumidx].a = 255; } } @@ -769,7 +769,7 @@ static void CalcDefaultTranslation(FFont* base, int index) lowindex = highindex++; } } - + } //========================================================================== diff --git a/src/common/fonts/v_text.cpp b/src/common/fonts/v_text.cpp index dc182f89d..e9ccb2a50 100644 --- a/src/common/fonts/v_text.cpp +++ b/src/common/fonts/v_text.cpp @@ -88,7 +88,6 @@ TArray V_BreakLines (FFont *font, int maxwidth, const uint8_t *str { if (*string == '[') { - const uint8_t* start = string; while (*string != ']' && *string != '\0') { string++; diff --git a/src/common/menu/joystickmenu.cpp b/src/common/menu/joystickmenu.cpp index 4baea836f..21c667d31 100644 --- a/src/common/menu/joystickmenu.cpp +++ b/src/common/menu/joystickmenu.cpp @@ -160,12 +160,12 @@ void UpdateJoystickMenu(IJoystickConfig *selected) it = opt->GetItem("ConnectMessage2"); if (it != nullptr) it->SetValue(0, !use_joystick); - for (int i = 0; i < (int)Joysticks.Size(); ++i) + for (int ii = 0; ii < (int)Joysticks.Size(); ++ii) { - it = CreateOptionMenuItemJoyConfigMenu(Joysticks[i]->GetName(), Joysticks[i]); + it = CreateOptionMenuItemJoyConfigMenu(Joysticks[ii]->GetName(), Joysticks[ii]); GC::WriteBarrier(opt, it); opt->mItems.Push(it); - if (i == itemnum) opt->mSelectedItem = opt->mItems.Size(); + if (ii == itemnum) opt->mSelectedItem = opt->mItems.Size(); } if (opt->mSelectedItem >= (int)opt->mItems.Size()) { @@ -179,15 +179,15 @@ void UpdateJoystickMenu(IJoystickConfig *selected) auto p = CurrentMenu->PointerVar("mJoy"); if (p != nullptr) { - unsigned i; - for (i = 0; i < Joysticks.Size(); ++i) + unsigned ii; + for (ii = 0; ii < Joysticks.Size(); ++ii) { - if (Joysticks[i] == p) + if (Joysticks[ii] == p) { break; } } - if (i == Joysticks.Size()) + if (ii == Joysticks.Size()) { CurrentMenu->Close(); } diff --git a/src/common/menu/menu.cpp b/src/common/menu/menu.cpp index bbfe2f4a5..89017d67b 100644 --- a/src/common/menu/menu.cpp +++ b/src/common/menu/menu.cpp @@ -271,7 +271,7 @@ DMenu::DMenu(DMenu *parent) DontDim = false; GC::WriteBarrier(this, parent); } - + //============================================================================= // // diff --git a/src/common/menu/menudef.cpp b/src/common/menu/menudef.cpp index f22f9f9b7..7e344c314 100644 --- a/src/common/menu/menudef.cpp +++ b/src/common/menu/menudef.cpp @@ -340,6 +340,10 @@ static void DoParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc, bool &s { desc->mCenter = true; } + else if (sc.Compare("Selecteditem")) + { + desc->mSelectedItem = desc->mItems.Size() - 1; + } else if (sc.Compare("animatedtransition")) { desc->mAnimatedTransition = true; @@ -563,8 +567,8 @@ static void DoParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc, bool &s // NB: index has been incremented, so we're not affecting the newly inserted item here. for (unsigned int i = insertIndex; i < desc->mItems.Size(); i++) { - auto item = desc->mItems[i]; - if (item->GetClass()->IsDescendantOf("ListMenuItemSelectable")) + auto litem = desc->mItems[i]; + if (litem->GetClass()->IsDescendantOf("ListMenuItemSelectable")) { desc->mItems[i]->mYpos += desc->mLinespacing; } @@ -660,9 +664,9 @@ static bool FindMatchingItem(DMenuItemBase *desc) MenuDescriptorList::Pair *pair; while (it.NextPair(pair)) { - for (auto it : pair->Value->mItems) + for (auto item : pair->Value->mItems) { - if (it->mAction == name && GetGroup(it) == grp) return true; + if (item->mAction == name && GetGroup(item) == grp) return true; } } return false; diff --git a/src/common/menu/savegamemanager.cpp b/src/common/menu/savegamemanager.cpp index 935b6dedd..19c80a889 100644 --- a/src/common/menu/savegamemanager.cpp +++ b/src/common/menu/savegamemanager.cpp @@ -151,8 +151,6 @@ int FSavegameManagerBase::InsertSaveNode(FSaveGameNode *node) void FSavegameManagerBase::NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave, bool forceQuicksave) { - FSaveGameNode *node; - if (file.IsEmpty()) return; @@ -180,7 +178,7 @@ void FSavegameManagerBase::NotifyNewSave(const FString &file, const FString &tit } } - node = new FSaveGameNode; + auto node = new FSaveGameNode; node->SaveTitle = title; node->Filename = file; node->bOldVersion = false; diff --git a/src/common/models/model.cpp b/src/common/models/model.cpp index eea099045..e8826d5b8 100644 --- a/src/common/models/model.cpp +++ b/src/common/models/model.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, @@ -98,7 +98,7 @@ static int FindGFXFile(FString & fn) for (const char ** extp=extensions; *extp; extp++) { - int lump = fileSystem.CheckNumForFullName(fn + *extp); + lump = fileSystem.CheckNumForFullName(fn + *extp); if (lump >= best) best = lump; } return best; diff --git a/src/common/models/model_kvx.h b/src/common/models/model_kvx.h index 36db774c7..8d456d52c 100644 --- a/src/common/models/model_kvx.h +++ b/src/common/models/model_kvx.h @@ -48,7 +48,7 @@ protected: unsigned int mNumIndices; TArray mVertices; TArray mIndices; - + void MakeSlabPolys(int x, int y, kvxslab_t *voxptr, FVoxelMap &check); void AddFace(int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3, int x4, int y4, int z4, uint8_t color, FVoxelMap &check); unsigned int AddVertex(FModelVertex &vert, FVoxelMap &check); diff --git a/src/common/models/models_md2.cpp b/src/common/models/models_md2.cpp index c3439faea..8924392a4 100644 --- a/src/common/models/models_md2.cpp +++ b/src/common/models/models_md2.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, @@ -217,10 +217,10 @@ void FDMDModel::LoadGeometry() memcpy(lods[i].triangles, buffer + lodInfo[i].offsetTriangles, lodInfo[i].numTriangles * sizeof(FTriangle)); for (int j = 0; j < lodInfo[i].numTriangles; j++) { - for (int k = 0; k < 3; k++) + for (int kk = 0; kk < 3; kk++) { - lods[i].triangles[j].textureIndices[k] = LittleShort(lods[i].triangles[j].textureIndices[k]); - lods[i].triangles[j].vertexIndices[k] = LittleShort(lods[i].triangles[j].vertexIndices[k]); + lods[i].triangles[j].textureIndices[kk] = LittleShort(lods[i].triangles[j].textureIndices[kk]); + lods[i].triangles[j].vertexIndices[kk] = LittleShort(lods[i].triangles[j].vertexIndices[kk]); } } } @@ -306,7 +306,7 @@ void FDMDModel::BuildVertexBuffer(FModelRenderer *renderer) FTriangle *tri = lods[0].triangles; - for (int i = 0; i < lodInfo[0].numTriangles; i++) + for (int ii = 0; ii < lodInfo[0].numTriangles; ii++) { for (int j = 0; j < 3; j++) { @@ -536,15 +536,15 @@ void FMD2Model::LoadGeometry() } lods[0].triangles = new FTriangle[lodInfo[0].numTriangles]; - + int cnt = lodInfo[0].numTriangles; memcpy(lods[0].triangles, buffer + lodInfo[0].offsetTriangles, sizeof(FTriangle) * cnt); for (int j = 0; j < cnt; j++) { - for (int k = 0; k < 3; k++) + for (int kk = 0; kk < 3; kk++) { - lods[0].triangles[j].textureIndices[k] = LittleShort(lods[0].triangles[j].textureIndices[k]); - lods[0].triangles[j].vertexIndices[k] = LittleShort(lods[0].triangles[j].vertexIndices[k]); + lods[0].triangles[j].textureIndices[kk] = LittleShort(lods[0].triangles[j].textureIndices[kk]); + lods[0].triangles[j].vertexIndices[kk] = LittleShort(lods[0].triangles[j].vertexIndices[kk]); } } } diff --git a/src/common/models/models_md3.cpp b/src/common/models/models_md3.cpp index c40f78e1e..0ec4d700f 100644 --- a/src/common/models/models_md3.cpp +++ b/src/common/models/models_md3.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, @@ -133,7 +133,7 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le auto numFrames = LittleLong(hdr->Num_Frames); auto numSurfaces = LittleLong(hdr->Num_Surfaces); - + numTags = LittleLong(hdr->Num_Tags); md3_frame_t * frm = (md3_frame_t*)(buffer + LittleLong(hdr->Ofs_Frames)); @@ -141,7 +141,7 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le Frames.Resize(numFrames); for (unsigned i = 0; i < numFrames; i++) { - strncpy(Frames[i].Name, frm[i].Name, 16); + strncpy(Frames[i].Name, frm[i].Name, 15); for (int j = 0; j < 3; j++) Frames[i].origin[j] = frm[i].localorigin[j]; } @@ -164,15 +164,15 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le md3_shader_t * shader = (md3_shader_t*)(((char*)ss) + LittleLong(ss->Ofs_Shaders)); s->Skins.Resize(s->numSkins); - for (unsigned i = 0; i < s->numSkins; i++) + for (unsigned ii = 0; ii < s->numSkins; ii++) { // [BB] According to the MD3 spec, Name is supposed to include the full path. // ... and since some tools seem to output backslashes, these need to be replaced with forward slashes to work. - FixPathSeperator(shader[i].Name); - s->Skins[i] = LoadSkin("", shader[i].Name); + FixPathSeperator(shader[ii].Name); + s->Skins[ii] = LoadSkin("", shader[ii].Name); // [BB] Fall back and check if Name is relative. - if (!s->Skins[i].isValid()) - s->Skins[i] = LoadSkin(path, shader[i].Name); + if (!s->Skins[ii].isValid()) + s->Skins[ii] = LoadSkin(path, shader[ii].Name); } } mLumpNum = lumpnum; @@ -203,31 +203,31 @@ void FMD3Model::LoadGeometry() md3_triangle_t * tris = (md3_triangle_t*)(((char*)ss) + LittleLong(ss->Ofs_Triangles)); s->Tris.Resize(s->numTriangles); - for (unsigned i = 0; i < s->numTriangles; i++) for (int j = 0; j < 3; j++) + for (unsigned ii = 0; ii < s->numTriangles; ii++) for (int j = 0; j < 3; j++) { - s->Tris[i].VertIndex[j] = LittleLong(tris[i].vt_index[j]); + s->Tris[ii].VertIndex[j] = LittleLong(tris[ii].vt_index[j]); } // Load texture coordinates md3_texcoord_t * tc = (md3_texcoord_t*)(((char*)ss) + LittleLong(ss->Ofs_Texcoord)); s->Texcoords.Resize(s->numVertices); - for (unsigned i = 0; i < s->numVertices; i++) + for (unsigned ii = 0; ii < s->numVertices; ii++) { - s->Texcoords[i].s = tc[i].s; - s->Texcoords[i].t = tc[i].t; + s->Texcoords[ii].s = tc[ii].s; + s->Texcoords[ii].t = tc[ii].t; } // Load vertices and texture coordinates md3_vertex_t * vt = (md3_vertex_t*)(((char*)ss) + LittleLong(ss->Ofs_XYZNormal)); s->Vertices.Resize(s->numVertices * Frames.Size()); - for (unsigned i = 0; i < s->numVertices * Frames.Size(); i++) + for (unsigned ii = 0; ii < s->numVertices * Frames.Size(); ii++) { - s->Vertices[i].x = LittleShort(vt[i].x) / 64.f; - s->Vertices[i].y = LittleShort(vt[i].y) / 64.f; - s->Vertices[i].z = LittleShort(vt[i].z) / 64.f; - UnpackVector(LittleShort(vt[i].n), s->Vertices[i].nx, s->Vertices[i].ny, s->Vertices[i].nz); + s->Vertices[ii].x = LittleShort(vt[ii].x) / 64.f; + s->Vertices[ii].y = LittleShort(vt[ii].y) / 64.f; + s->Vertices[ii].z = LittleShort(vt[ii].z) / 64.f; + UnpackVector(LittleShort(vt[ii].n), s->Vertices[ii].nx, s->Vertices[ii].ny, s->Vertices[ii].nz); } } } diff --git a/src/common/models/models_ue1.cpp b/src/common/models/models_ue1.cpp index 68be56e61..c7ffe88a9 100644 --- a/src/common/models/models_ue1.cpp +++ b/src/common/models/models_ue1.cpp @@ -1,21 +1,25 @@ // //--------------------------------------------------------------------------- // -// Copyright(C) 2018 Marisa Kirisame -// All rights reserved. +// Copyright (c) 2018-2022 Marisa Kirisame, UnSX Team // -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: // -// This program 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 Lesser General Public License for more details. +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. // -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. // //-------------------------------------------------------------------------- // diff --git a/src/common/models/models_voxel.cpp b/src/common/models/models_voxel.cpp index 809d25400..50fc4df09 100644 --- a/src/common/models/models_voxel.cpp +++ b/src/common/models/models_voxel.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, @@ -100,7 +100,7 @@ TArray FVoxelTexture::CreatePalettedPixels(int conversion) pe.b = (pp[2] << 2) | (pp[2] >> 4); // Alphatexture handling is just for completeness, but rather unlikely to be used ever. Pixels[i] = conversion == luminance ? pe.r : ColorMatcher.Pick(pe); - + } } else @@ -205,7 +205,6 @@ void FVoxelModel::AddFace(int x1, int y1, int z1, int x2, int y2, int z2, int x3 float PivotX = mVoxel->Mips[0].Pivot.X; float PivotY = mVoxel->Mips[0].Pivot.Y; float PivotZ = mVoxel->Mips[0].Pivot.Z; - int h = mVoxel->Mips[0].SizeZ; FModelVertex vert; unsigned int indx[4]; @@ -286,8 +285,8 @@ void FVoxelModel::MakeSlabPolys(int x, int y, kvxslab_t *voxptr, FVoxelMap &chec } if (cull & 32) { - int z = ztop+zleng-1; - AddFace(x+1, y, z+1, x, y, z+1, x+1, y+1, z+1, x, y+1, z+1, voxptr->col[zleng-1], check); + int zz = ztop+zleng-1; + AddFace(x+1, y, zz+1, x, y, zz+1, x+1, y+1, zz+1, x, y+1, zz+1, voxptr->col[zleng-1], check); } } diff --git a/src/common/objects/dobject.cpp b/src/common/objects/dobject.cpp index 8516229de..2ed8279da 100644 --- a/src/common/objects/dobject.cpp +++ b/src/common/objects/dobject.cpp @@ -229,7 +229,6 @@ DObject::DObject () ObjNext = GC::Root; GCNext = nullptr; GC::Root = this; - GC::AllocCount++; } DObject::DObject (PClass *inClass) @@ -239,7 +238,6 @@ DObject::DObject (PClass *inClass) ObjNext = GC::Root; GCNext = nullptr; GC::Root = this; - GC::AllocCount++; } //========================================================================== @@ -267,7 +265,7 @@ DObject::~DObject () Release(); } } - + if (nullptr != type) { type->DestroySpecials(this); @@ -277,7 +275,6 @@ DObject::~DObject () void DObject::Release() { - if (GC::AllocCount > 0) GC::AllocCount--; DObject **probe; // Unlink this object from the GC list. diff --git a/src/common/objects/dobjgc.cpp b/src/common/objects/dobjgc.cpp index 91cfafaef..e407d3d77 100644 --- a/src/common/objects/dobjgc.cpp +++ b/src/common/objects/dobjgc.cpp @@ -3,7 +3,7 @@ ** The garbage collector. Based largely on Lua's. ** **--------------------------------------------------------------------------- -** Copyright 2008 Randy Heit +** Copyright 2008-2022 Marisa Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -82,13 +82,19 @@ ** infinity, where each step performs a full collection.) You can also ** change this value dynamically. */ -#define DEFAULT_GCMUL 400 // GC runs 'quadruple the speed' of memory allocation +#define DEFAULT_GCMUL 200 // GC runs 'double the speed' of memory allocation -// Number of sectors to mark for each step. +// Minimum step size +#define GCSTEPSIZE (sizeof(DObject) * 16) -#define GCSTEPSIZE 1024u +// Maximum number of elements to sweep in a single step #define GCSWEEPMAX 40 -#define GCSWEEPCOST 10 + +// Cost of sweeping one element (the size of a small object divided by +// some adjust for the sweep speed) +#define GCSWEEPCOST (sizeof(DObject) / 4) + +// Cost of calling of one destructor #define GCFINALIZECOST 100 // TYPES ------------------------------------------------------------------- @@ -99,6 +105,8 @@ // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- +static size_t CalcStepSize(); + // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -108,7 +116,6 @@ namespace GC size_t AllocBytes; size_t Threshold; size_t Estimate; -size_t AllocCount; DObject *Gray; DObject *Root; DObject *SoftRoots; @@ -118,11 +125,15 @@ EGCState State = GCS_Pause; int Pause = DEFAULT_GCPAUSE; int StepMul = DEFAULT_GCMUL; int StepCount; -size_t Dept; +uint64_t CheckTime; bool FinalGC; // PRIVATE DATA DEFINITIONS ------------------------------------------------ +static int LastCollectTime; // Time last time collector finished +static size_t LastCollectAlloc; // Memory allocation when collector finished +static size_t MinStepSize; // Cover at least this much memory per step + // CODE -------------------------------------------------------------------- //========================================================================== @@ -161,8 +172,8 @@ size_t PropagateMark() // // SweepList // -// Runs a limited sweep on a list, returning the location where to resume -// the sweep at next time. (FIXME: Horrible Engrish in this description.) +// Runs a limited sweep on a list, returning the position in the list just +// after the last object swept. // //========================================================================== @@ -254,6 +265,26 @@ void MarkArray(DObject **obj, size_t count) } } +//========================================================================== +// +// CalcStepSize +// +// Decide how big a step should be based, depending on how long it took to +// allocate up to the threshold from the amount left after the previous +// collection. +// +//========================================================================== + +static size_t CalcStepSize() +{ + int time_passed = CheckTime - LastCollectTime; + auto alloc = min(LastCollectAlloc, Estimate); + size_t bytes_gained = AllocBytes > alloc ? AllocBytes - alloc : 0; + return (StepMul > 0 && time_passed > 0) + ? std::max(GCSTEPSIZE, bytes_gained / time_passed * StepMul / 100) + : std::numeric_limits::max() / 2; // no limit +} + //========================================================================== // // MarkRoot @@ -310,6 +341,10 @@ static void Atomic() SweepPos = &Root; State = GCS_Sweep; Estimate = AllocBytes; + + // Now that we are about to start a sweep, establish a baseline minimum + // step size for how much memory we want to sweep each CheckGC(). + MinStepSize = CalcStepSize(); } //========================================================================== @@ -354,7 +389,8 @@ static size_t SingleStep() case GCS_Finalize: State = GCS_Pause; // end collection - Dept = 0; + LastCollectAlloc = AllocBytes; + LastCollectTime = CheckTime; return 0; default: @@ -374,29 +410,26 @@ static size_t SingleStep() void Step() { - size_t lim = (GCSTEPSIZE/100) * StepMul; - size_t olim; - if (lim == 0) - { - lim = (~(size_t)0) / 2; // no limit - } - Dept += AllocBytes - Threshold; + // We recalculate a step size in case the rate of allocation went up + // since we started sweeping because we don't want to fall behind. + // However, we also don't want to go slower than what was decided upon + // when the sweep began if the rate of allocation has slowed. + size_t lim = max(CalcStepSize(), MinStepSize); do { - olim = lim; - lim -= SingleStep(); - } while (olim > lim && State != GCS_Pause); - if (State != GCS_Pause) - { - if (Dept < GCSTEPSIZE) + size_t done = SingleStep(); + if (done < lim) { - Threshold = AllocBytes + GCSTEPSIZE; // - lim/StepMul + lim -= done; } else { - Dept -= GCSTEPSIZE; - Threshold = AllocBytes; + lim = 0; } + } while (lim && State != GCS_Pause); + if (State != GCS_Pause) + { + Threshold = AllocBytes; } else { @@ -571,16 +604,13 @@ ADD_STAT(gc) " Sweep ", "Finalize " }; FString out; - out.Format("[%s] Alloc:%6zuK Thresh:%6zuK Est:%6zuK Steps: %d", + out.Format("[%s] Alloc:%6zuK Thresh:%6zuK Est:%6zuK Steps: %d %zuK", StateStrings[GC::State], (GC::AllocBytes + 1023) >> 10, (GC::Threshold + 1023) >> 10, (GC::Estimate + 1023) >> 10, - GC::StepCount); - if (GC::State != GC::GCS_Pause) - { - out.AppendFormat(" %zuK", (GC::Dept + 1023) >> 10); - } + GC::StepCount, + (GC::MinStepSize + 1023) >> 10); return out; } diff --git a/src/common/objects/dobjgc.h b/src/common/objects/dobjgc.h index d01e52cf6..1fd293263 100644 --- a/src/common/objects/dobjgc.h +++ b/src/common/objects/dobjgc.h @@ -43,9 +43,6 @@ namespace GC // Number of bytes currently allocated through M_Malloc/M_Realloc. extern size_t AllocBytes; - // Number of allocated objects since last CheckGC call. - extern size_t AllocCount; - // Amount of memory to allocate before triggering a collection. extern size_t Threshold; @@ -73,6 +70,9 @@ namespace GC // Is this the final collection just before exit? extern bool FinalGC; + // Counts the number of times CheckGC has been called. + extern uint64_t CheckTime; + // Current white value for known-dead objects. static inline uint32_t OtherWhite() { @@ -108,15 +108,11 @@ namespace GC } // Check if it's time to collect, and do a collection step if it is. - static inline bool CheckGC() + static inline void CheckGC() { - AllocCount = 0; + CheckTime++; if (AllocBytes >= Threshold) - { Step(); - return true; - } - return false; } // Forces a collection to start now. @@ -158,6 +154,10 @@ namespace GC { MarkArray((DObject **)(obj), count); } + template void MarkArray(TObjPtr* obj, size_t count) + { + MarkArray((DObject**)(obj), count); + } template void MarkArray(TArray &arr) { MarkArray(&arr[0], arr.Size()); diff --git a/src/common/platform/posix/cocoa/i_input.mm b/src/common/platform/posix/cocoa/i_input.mm index ebda85a2e..f53ae8ebc 100644 --- a/src/common/platform/posix/cocoa/i_input.mm +++ b/src/common/platform/posix/cocoa/i_input.mm @@ -429,7 +429,7 @@ void ProcessKeyboardEventInMenu(NSEvent* theEvent) event.subtype = EV_GUI_Char; event.data1 = realchar; event.data2 = event.data3 & GKM_ALT; - + D_PostEvent(&event); } } @@ -667,9 +667,9 @@ void ProcessMouseWheelEvent(NSEvent* theEvent) { return; } - + event_t event = {}; - + if (GUICapture) { event.type = EV_GUI_Event; @@ -681,7 +681,7 @@ void ProcessMouseWheelEvent(NSEvent* theEvent) event.type = isZeroDelta ? EV_KeyUp : EV_KeyDown; event.data1 = delta > 0.0f ? KEY_MWHEELUP : KEY_MWHEELDOWN; } - + D_PostEvent(&event); } diff --git a/src/common/platform/posix/cocoa/i_joystick.cpp b/src/common/platform/posix/cocoa/i_joystick.cpp index 2bbfedb1d..733380366 100644 --- a/src/common/platform/posix/cocoa/i_joystick.cpp +++ b/src/common/platform/posix/cocoa/i_joystick.cpp @@ -1127,7 +1127,7 @@ void IOKitJoystickManager::AddDevices(const IONotificationPortRef notificationPo } IOObjectRelease(device); - + PostDeviceChangeEvent(); } } diff --git a/src/common/platform/posix/cocoa/i_main.mm b/src/common/platform/posix/cocoa/i_main.mm index 727edef78..382fabb23 100644 --- a/src/common/platform/posix/cocoa/i_main.mm +++ b/src/common/platform/posix/cocoa/i_main.mm @@ -55,7 +55,6 @@ // --------------------------------------------------------------------------- -CVAR (Bool, i_soundinbackground, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) EXTERN_CVAR(Int, vid_defwidth ) EXTERN_CVAR(Int, vid_defheight) EXTERN_CVAR(Bool, vid_vsync ) @@ -90,10 +89,10 @@ static bool ReadSystemVersionFromPlist(NSOperatingSystemVersion& version) if (stat(plistPath, &dummy) != 0) return false; - + char commandLine[1024] = {}; snprintf(commandLine, sizeof commandLine, "defaults read %s ProductVersion", plistPath); - + FILE *const versionFile = popen(commandLine, "r"); if (versionFile == nullptr) @@ -146,7 +145,7 @@ void I_DetectOS() } const char* name = "Unknown version"; - + switch (version.majorVersion) { case 10: @@ -183,7 +182,7 @@ void I_DetectOS() #else "Unknown"; #endif - + Printf("%s running %s %d.%d.%d (%s) %s\n", model, name, int(version.majorVersion), int(version.minorVersion), int(version.patchVersion), release, architecture); @@ -266,14 +265,14 @@ ApplicationController* appCtrl; - (void)keyDown:(NSEvent*)theEvent { // Empty but present to avoid playing of 'beep' alert sound - + ZD_UNUSED(theEvent); } - (void)keyUp:(NSEvent*)theEvent { // Empty but present to avoid playing of 'beep' alert sound - + ZD_UNUSED(theEvent); } @@ -283,7 +282,7 @@ extern bool AppActive; - (void)applicationDidBecomeActive:(NSNotification*)aNotification { ZD_UNUSED(aNotification); - + S_SetSoundPaused(1); AppActive = true; @@ -292,8 +291,8 @@ extern bool AppActive; - (void)applicationWillResignActive:(NSNotification*)aNotification { ZD_UNUSED(aNotification); - - S_SetSoundPaused(i_soundinbackground); + + S_SetSoundPaused(0); AppActive = false; } diff --git a/src/common/platform/posix/cocoa/i_video.mm b/src/common/platform/posix/cocoa/i_video.mm index 8f730e488..2350ca954 100644 --- a/src/common/platform/posix/cocoa/i_video.mm +++ b/src/common/platform/posix/cocoa/i_video.mm @@ -449,7 +449,7 @@ public: } else #endif - + #ifdef HAVE_SOFTPOLY if (vid_preferbackend == 2) { @@ -832,7 +832,7 @@ bool I_SetCursor(FGameTexture *cursorpic) if (NULL != cursorpic && cursorpic->isValid()) { // Create bitmap image representation - + auto sbuffer = cursorpic->GetTexture()->CreateTexBuffer(0); const NSInteger imageWidth = sbuffer.mWidth; @@ -873,11 +873,11 @@ bool I_SetCursor(FGameTexture *cursorpic) cursor = [[NSCursor alloc] initWithImage:cursorImage hotSpot:NSMakePoint(0.0f, 0.0f)]; } - + SystemBaseFrameBuffer::SetCursor(cursor); - + [pool release]; - + return true; } diff --git a/src/common/platform/posix/osx/i_specialpaths.mm b/src/common/platform/posix/osx/i_specialpaths.mm index ff435b769..d51bd4ca5 100644 --- a/src/common/platform/posix/osx/i_specialpaths.mm +++ b/src/common/platform/posix/osx/i_specialpaths.mm @@ -256,7 +256,7 @@ FString M_GetDocumentsPath() FString M_GetDemoPath() { FString path = GetSpecialPath(NSDocumentDirectory); - + if (path.IsNotEmpty()) { path += "/" GAME_DIR "/Demos/"; diff --git a/src/common/platform/posix/osx/iwadpicker_cocoa.mm b/src/common/platform/posix/osx/iwadpicker_cocoa.mm index 4ff7d737b..e72aa5aad 100644 --- a/src/common/platform/posix/osx/iwadpicker_cocoa.mm +++ b/src/common/platform/posix/osx/iwadpicker_cocoa.mm @@ -446,7 +446,7 @@ int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad if (ret >= 0) { NSString* parametersToAppend = [picker commandLineParameters]; - + if (0 != [parametersToAppend length]) { RestartWithParameters(wads[ret], parametersToAppend); diff --git a/src/common/platform/posix/sdl/hardware.cpp b/src/common/platform/posix/sdl/hardware.cpp index ea008169e..46daca4f9 100644 --- a/src/common/platform/posix/sdl/hardware.cpp +++ b/src/common/platform/posix/sdl/hardware.cpp @@ -67,6 +67,7 @@ void I_InitGraphics () #ifdef __APPLE__ SDL_SetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, "0"); #endif // __APPLE__ + SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); if (SDL_InitSubSystem (SDL_INIT_VIDEO) < 0) { @@ -78,7 +79,7 @@ void I_InitGraphics () extern IVideo *gl_CreateVideo(); Video = gl_CreateVideo(); - + if (Video == NULL) I_FatalError ("Failed to initialize display"); } diff --git a/src/common/platform/posix/sdl/i_input.cpp b/src/common/platform/posix/sdl/i_input.cpp index a102b38a8..300e22370 100644 --- a/src/common/platform/posix/sdl/i_input.cpp +++ b/src/common/platform/posix/sdl/i_input.cpp @@ -205,7 +205,7 @@ static void MouseRead () static void I_CheckNativeMouse () { bool focus = SDL_GetKeyboardFocus() != NULL; - + bool captureModeInGame = sysCallbacks.CaptureModeInGame && sysCallbacks.CaptureModeInGame(); bool wantNative = !focus || (!use_mouse || GUICapture || !captureModeInGame); @@ -228,7 +228,7 @@ void MessagePump (const SDL_Event &sev) static int lastx = 0, lasty = 0; int x, y; event_t event = { 0,0,0,0,0,0,0 }; - + switch (sev.type) { case SDL_QUIT: @@ -369,7 +369,7 @@ void MessagePump (const SDL_Event &sev) { break; } - + event.type = sev.type == SDL_KEYDOWN ? EV_KeyDown : EV_KeyUp; // Try to look up our key mapped key for conversion to DirectInput. @@ -448,7 +448,7 @@ void MessagePump (const SDL_Event &sev) if (GUICapture) { int size; - + int unichar = utf8_decode((const uint8_t*)sev.text.text, &size); if (size != 4) { @@ -474,7 +474,7 @@ void MessagePump (const SDL_Event &sev) void I_GetEvent () { SDL_Event sev; - + while (SDL_PollEvent (&sev)) { MessagePump (sev); diff --git a/src/common/platform/posix/sdl/i_main.cpp b/src/common/platform/posix/sdl/i_main.cpp index b52561fdf..a28b90f01 100644 --- a/src/common/platform/posix/sdl/i_main.cpp +++ b/src/common/platform/posix/sdl/i_main.cpp @@ -171,7 +171,7 @@ int main (int argc, char **argv) } printf("\n"); - + Args = new FArgs(argc, argv); // Should we even be doing anything with progdir on Unix systems? @@ -188,7 +188,7 @@ int main (int argc, char **argv) { progdir = "./"; } - + I_StartupJoysticks(); const int result = GameMain(); diff --git a/src/common/platform/posix/sdl/i_system.cpp b/src/common/platform/posix/sdl/i_system.cpp index 922c228a3..0bca72304 100644 --- a/src/common/platform/posix/sdl/i_system.cpp +++ b/src/common/platform/posix/sdl/i_system.cpp @@ -159,7 +159,7 @@ void RedrawProgressBar(int CurPos, int MaxPos) memset(progressBuffer,'.',512); progressBuffer[sizeOfWindow.ws_col - 1] = 0; int lengthOfStr = 0; - + while (curProgVal-- > 0) { progressBuffer[lengthOfStr++] = '='; @@ -182,7 +182,9 @@ void I_PrintStr(const char *cp) if (*srcp == 0x1c && con_printansi && terminal) { srcp += 1; - EColorRange range = V_ParseFontColor((const uint8_t*&)srcp, CR_UNTRANSLATED, CR_YELLOW); + const uint8_t* scratch = (const uint8_t*)srcp; // GCC does not like direct casting of the parameter. + EColorRange range = V_ParseFontColor(scratch, CR_UNTRANSLATED, CR_YELLOW); + srcp = (char*)scratch; if (range != CR_UNDEFINED) { PalEntry color = V_LogColorFromColorRange(range); @@ -206,7 +208,7 @@ void I_PrintStr(const char *cp) else if (v < 0.90) attrib = 0x7; else attrib = 0xF; } - + printData.AppendFormat("\033[%um",((attrib & 0x8) ? 90 : 30) + (attrib & 0x7)); } else printData.AppendFormat("\033[38;2;%u;%u;%um",color.r,color.g,color.b); @@ -222,7 +224,7 @@ void I_PrintStr(const char *cp) else break; } } - + if (StartScreen) CleanProgressBar(); fputs(printData.GetChars(),stdout); if (terminal) fputs("\033[0m",stdout); @@ -301,7 +303,7 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) #ifdef __APPLE__ return I_PickIWad_Cocoa (wads, numwads, showwin, defaultiwad); #endif - + if (!isatty(fileno(stdin))) { return defaultiwad; diff --git a/src/common/platform/posix/sdl/i_system.mm b/src/common/platform/posix/sdl/i_system.mm index 50faf94a8..f9212f08c 100644 --- a/src/common/platform/posix/sdl/i_system.mm +++ b/src/common/platform/posix/sdl/i_system.mm @@ -5,13 +5,13 @@ void Mac_I_FatalError(const char* errortext) { // Close window or exit fullscreen and release mouse capture SDL_Quit(); - + const CFStringRef errorString = CFStringCreateWithCStringNoCopy( kCFAllocatorDefault, errortext, kCFStringEncodingASCII, kCFAllocatorNull ); if ( NULL != errorString ) { CFOptionFlags dummy; - + CFUserNotificationDisplayAlert( 0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, CFSTR( "Fatal Error" ), errorString, CFSTR( "Exit" ), NULL, NULL, &dummy ); CFRelease( errorString ); diff --git a/src/common/platform/posix/sdl/sdlglvideo.cpp b/src/common/platform/posix/sdl/sdlglvideo.cpp index 73ca00b99..a5f7e6b52 100644 --- a/src/common/platform/posix/sdl/sdlglvideo.cpp +++ b/src/common/platform/posix/sdl/sdlglvideo.cpp @@ -53,7 +53,7 @@ #ifdef HAVE_GLES2 #include "gles_framebuffer.h" #endif - + #ifdef HAVE_VULKAN #include "vulkan/system/vk_framebuffer.h" #endif @@ -95,8 +95,6 @@ CUSTOM_CVAR(Bool, gl_es, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCA Printf("This won't take effect until " GAMENAME " is restarted.\n"); } -CVAR(Bool, i_soundinbackground, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) - CVAR (Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CUSTOM_CVAR(String, vid_sdl_render_driver, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) @@ -517,7 +515,7 @@ int SystemBaseFrameBuffer::GetClientWidth() return width; } #endif - + #ifdef HAVE_VULKAN assert(Priv::vulkanEnabled); SDL_Vulkan_GetDrawableSize(Priv::window, &width, nullptr); @@ -721,7 +719,7 @@ void ProcessSDLWindowEvent(const SDL_WindowEvent &event) break; case SDL_WINDOWEVENT_FOCUS_LOST: - S_SetSoundPaused(i_soundinbackground); + S_SetSoundPaused(0); AppActive = false; break; diff --git a/src/common/platform/posix/sdl/st_start.cpp b/src/common/platform/posix/sdl/st_start.cpp index 6d41fa629..4c434bba9 100644 --- a/src/common/platform/posix/sdl/st_start.cpp +++ b/src/common/platform/posix/sdl/st_start.cpp @@ -228,7 +228,7 @@ void FTTYStartupScreen::NetMessage(const char *format, ...) { FString str; va_list argptr; - + va_start (argptr, format); str.VFormat (format, argptr); va_end (argptr); diff --git a/src/common/platform/win32/base_sysfb.cpp b/src/common/platform/win32/base_sysfb.cpp index 9c9bb4a54..8130b8b6c 100644 --- a/src/common/platform/win32/base_sysfb.cpp +++ b/src/common/platform/win32/base_sysfb.cpp @@ -279,7 +279,7 @@ void SystemBaseFrameBuffer::PositionWindow(bool fullscreen, bool initialcall) RECT r; LONG style, exStyle; - RECT monRect; + RECT monRect = {}; if (!m_Fullscreen && fullscreen && !initialcall) SaveWindowedPos(); if (m_Monitor) diff --git a/src/common/platform/win32/hardware.cpp b/src/common/platform/win32/hardware.cpp index 13e799594..a5e67604f 100644 --- a/src/common/platform/win32/hardware.cpp +++ b/src/common/platform/win32/hardware.cpp @@ -165,5 +165,5 @@ void I_InitGraphics () // we somehow STILL don't have a display!! if (Video == NULL) I_FatalError ("Failed to initialize display"); - + } diff --git a/src/common/platform/win32/i_crash.cpp b/src/common/platform/win32/i_crash.cpp index df2a6241e..94ca7d6c2 100644 --- a/src/common/platform/win32/i_crash.cpp +++ b/src/common/platform/win32/i_crash.cpp @@ -340,7 +340,7 @@ static HANDLE WriteMyMiniDump (void) MINIDUMP_EXCEPTION_INFORMATION exceptor = { DbgThreadID, &CrashPointers, FALSE }; WCHAR dbghelpPath[MAX_PATH+12], *bs; WRITEDUMP pMiniDumpWriteDump; - HANDLE file; + HANDLE file = INVALID_HANDLE_VALUE; BOOL good = FALSE; HMODULE dbghelp = NULL; @@ -710,14 +710,14 @@ HANDLE WriteTextReport () ctxt->Rip, ctxt->Rsp, ctxt->SegCs, ctxt->SegSs, ctxt->EFlags); #endif - DWORD j; + DWORD dw; - for (i = 0, j = 1; (size_t)i < sizeof(eflagsBits)/sizeof(eflagsBits[0]); j <<= 1, ++i) + for (i = 0, dw = 1; (size_t)i < sizeof(eflagsBits)/sizeof(eflagsBits[0]); dw <<= 1, ++i) { if (eflagsBits[i][0] != 'x') { Writef (file, " %c%c%c", eflagsBits[i][0], eflagsBits[i][1], - ctxt->EFlags & j ? '+' : '-'); + ctxt->EFlags & dw ? '+' : '-'); } } Writef (file, "\r\n"); @@ -1581,7 +1581,7 @@ static void AddZipFile (HANDLE ziphandle, TarFile *whichfile, short dosdate, sho local.ModDate = dosdate; local.UncompressedSize = LittleLong(whichfile->UncompressedSize); local.NameLength = LittleShort((uint16_t)strlen(whichfile->Filename)); - + whichfile->ZipOffset = SetFilePointer (ziphandle, 0, NULL, FILE_CURRENT); WriteFile (ziphandle, &local, sizeof(local), &wrote, NULL); WriteFile (ziphandle, whichfile->Filename, (DWORD)strlen(whichfile->Filename), &wrote, NULL); diff --git a/src/common/platform/win32/i_dijoy.cpp b/src/common/platform/win32/i_dijoy.cpp index e4021cc10..61e7605b3 100644 --- a/src/common/platform/win32/i_dijoy.cpp +++ b/src/common/platform/win32/i_dijoy.cpp @@ -281,14 +281,6 @@ CUSTOM_CVAR(Bool, joy_dinput, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCA static const uint8_t POVButtons[9] = { 0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09, 0x00 }; -//("dc12a687-737f-11cf-884d-00aa004b2e24") -static const IID IID_IWbemLocator = { 0xdc12a687, 0x737f, 0x11cf, - { 0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 } }; - -//("4590f811-1d3a-11d0-891f-00aa004b2e24") -static const CLSID CLSID_WbemLocator = { 0x4590f811, 0x1d3a, 0x11d0, - { 0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 } }; - // CODE -------------------------------------------------------------------- //=========================================================================== diff --git a/src/common/platform/win32/i_input.cpp b/src/common/platform/win32/i_input.cpp index 1b49f5680..06b1e9801 100644 --- a/src/common/platform/win32/i_input.cpp +++ b/src/common/platform/win32/i_input.cpp @@ -140,7 +140,6 @@ int BlockMouseMove; static bool EventHandlerResultForNativeMouse; -CVAR (Bool, i_soundinbackground, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, k_allowfullscreentoggle, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) extern int chatmodeon; @@ -508,14 +507,12 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS); } - S_SetSoundPaused ((!!i_soundinbackground) || wParam); + S_SetSoundPaused (wParam); break; case WM_WTSSESSION_CHANGE: case WM_POWERBROADCAST: { - int oldstate = SessionState; - if (message == WM_WTSSESSION_CHANGE && lParam == (LPARAM)SessionID) { #ifdef _DEBUG diff --git a/src/common/platform/win32/i_keyboard.cpp b/src/common/platform/win32/i_keyboard.cpp index ce204f71c..00f910949 100644 --- a/src/common/platform/win32/i_keyboard.cpp +++ b/src/common/platform/win32/i_keyboard.cpp @@ -58,7 +58,7 @@ class FDInputKeyboard : public FKeyboard public: FDInputKeyboard(); ~FDInputKeyboard(); - + bool GetDevice(); void ProcessInput(); diff --git a/src/common/platform/win32/i_main.cpp b/src/common/platform/win32/i_main.cpp index acdfd2eb5..68cd06a00 100644 --- a/src/common/platform/win32/i_main.cpp +++ b/src/common/platform/win32/i_main.cpp @@ -777,7 +777,7 @@ int DoMain (HINSTANCE hInstance) RECT cRect; TIMECAPS tc; DEVMODE displaysettings; - + // Do not use the multibyte __argv here because we want UTF-8 arguments // and those can only be done by converting the Unicode variants. Args = new FArgs(); @@ -787,17 +787,17 @@ int DoMain (HINSTANCE hInstance) { Args->AppendArg(FString(wargv[i])); } - + // Load Win32 modules Kernel32Module.Load({"kernel32.dll"}); Shell32Module.Load({"shell32.dll"}); User32Module.Load({"user32.dll"}); - + // Under XP, get our session ID so we can know when the user changes/locks sessions. // Since we need to remain binary compatible with older versions of Windows, we // need to extract the ProcessIdToSessionId function from kernel32.dll manually. HMODULE kernel = GetModuleHandleA ("kernel32.dll"); - + if (Args->CheckParm("-stdout")) { // As a GUI application, we don't normally get a console when we start. @@ -805,7 +805,7 @@ int DoMain (HINSTANCE hInstance) // console. Otherwise, we can create a new one. If we already have a // stdout handle, then we have been redirected and should just use that // handle instead of creating a console window. - + StdOut = GetStdHandle(STD_OUTPUT_HANDLE); if (StdOut != NULL) { @@ -832,18 +832,18 @@ int DoMain (HINSTANCE hInstance) { StdOut = GetStdHandle(STD_OUTPUT_HANDLE); } - + // These two functions do not exist in Windows XP. BOOL (WINAPI* p_GetCurrentConsoleFontEx)(HANDLE hConsoleOutput, BOOL bMaximumWindow, PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx); BOOL (WINAPI* p_SetCurrentConsoleFontEx)(HANDLE hConsoleOutput, BOOL bMaximumWindow, PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx); - + p_SetCurrentConsoleFontEx = (decltype(p_SetCurrentConsoleFontEx))GetProcAddress(kernel, "SetCurrentConsoleFontEx"); p_GetCurrentConsoleFontEx = (decltype(p_GetCurrentConsoleFontEx))GetProcAddress(kernel, "GetCurrentConsoleFontEx"); if (p_SetCurrentConsoleFontEx && p_GetCurrentConsoleFontEx) { CONSOLE_FONT_INFOEX cfi; cfi.cbSize = sizeof(cfi); - + if (p_GetCurrentConsoleFontEx(StdOut, false, &cfi)) { if (*cfi.FaceName == 0) // If the face name is empty, the default (useless) raster font is actoive. @@ -858,16 +858,16 @@ int DoMain (HINSTANCE hInstance) FancyStdOut = true; } } - + // Set the timer to be as accurate as possible if (timeGetDevCaps (&tc, sizeof(tc)) != TIMERR_NOERROR) TimerPeriod = 1; // Assume minimum resolution of 1 ms else TimerPeriod = tc.wPeriodMin; - + timeBeginPeriod (TimerPeriod); atexit(UnTbp); - + // Figure out what directory the program resides in. WCHAR progbuff[1024]; if (GetModuleFileNameW(nullptr, progbuff, sizeof progbuff) == 0) @@ -875,22 +875,22 @@ int DoMain (HINSTANCE hInstance) MessageBoxA(nullptr, "Fatal", "Could not determine program location.", MB_ICONEXCLAMATION|MB_OK); exit(-1); } - + progbuff[1023] = '\0'; if (auto lastsep = wcsrchr(progbuff, '\\')) { lastsep[1] = '\0'; } - + progdir = progbuff; FixPathSeperator(progdir); - + HDC screenDC = GetDC(0); int dpi = GetDeviceCaps(screenDC, LOGPIXELSX); ReleaseDC(0, screenDC); width = (512 * dpi + 96 / 2) / 96; height = (384 * dpi + 96 / 2) / 96; - + // Many Windows structures that specify their size do so with the first // element. DEVMODE is not one of those structures. memset (&displaysettings, 0, sizeof(displaysettings)); @@ -898,12 +898,12 @@ int DoMain (HINSTANCE hInstance) EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &displaysettings); x = (displaysettings.dmPelsWidth - width) / 2; y = (displaysettings.dmPelsHeight - height) / 2; - + if (Args->CheckParm ("-0")) { x = y = 0; } - + WNDCLASS WndClass; WndClass.style = 0; WndClass.lpfnWndProc = LConProc; @@ -915,14 +915,14 @@ int DoMain (HINSTANCE hInstance) WndClass.hbrBackground = NULL; WndClass.lpszMenuName = NULL; WndClass.lpszClassName = WinClassName; - + /* register this new class with Windows */ if (!RegisterClass((LPWNDCLASS)&WndClass)) { MessageBoxA(nullptr, "Could not register window class", "Fatal", MB_ICONEXCLAMATION|MB_OK); exit(-1); } - + /* create window */ FStringf caption("" GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime()); std::wstring wcaption = caption.WideString(); @@ -936,13 +936,13 @@ int DoMain (HINSTANCE hInstance) (HMENU) NULL, hInstance, NULL); - + if (!Window) { MessageBoxA(nullptr, "Unable to create main window", "Fatal", MB_ICONEXCLAMATION|MB_OK); exit(-1); } - + if (kernel != NULL) { typedef BOOL (WINAPI *pts)(DWORD, DWORD *); @@ -969,15 +969,15 @@ int DoMain (HINSTANCE hInstance) } } } - + GetClientRect (Window, &cRect); - + WinWidth = cRect.right; WinHeight = cRect.bottom; - + CoInitialize (NULL); atexit (UnCOM); - + int ret = GameMain (); CheckForRestart(); @@ -990,7 +990,7 @@ int DoMain (HINSTANCE hInstance) { // Outputting to a new console window: Wait for a keypress before quitting. DWORD bytes; HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE); - + ShowWindow(Window, SW_HIDE); WriteFile(StdOut, "Press any key to exit...", 24, &bytes, NULL); FlushConsoleInputBuffer(stdinput); @@ -1017,7 +1017,7 @@ void I_ShowFatalError(const char *msg) { Printf("%s", CVMAbortException::stacktrace.GetChars()); } - + if (!batchrun) { ShowErrorPane(msg); diff --git a/src/common/platform/win32/i_mouse.cpp b/src/common/platform/win32/i_mouse.cpp index 7da7e1c4b..4c2673e35 100644 --- a/src/common/platform/win32/i_mouse.cpp +++ b/src/common/platform/win32/i_mouse.cpp @@ -86,7 +86,7 @@ class FDInputMouse : public FMouse public: FDInputMouse(); ~FDInputMouse(); - + bool GetDevice(); void ProcessInput(); bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result); @@ -103,7 +103,7 @@ class FWin32Mouse : public FMouse public: FWin32Mouse(); ~FWin32Mouse(); - + bool GetDevice(); void ProcessInput(); bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result); @@ -268,7 +268,6 @@ void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult) } else { - bool pauseState = false; bool captureModeInGame = sysCallbacks.CaptureModeInGame && sysCallbacks.CaptureModeInGame(); want_native = ((!m_use_mouse || menuactive != MENU_WaitKey) && (!captureModeInGame || GUICapture)); @@ -698,7 +697,7 @@ bool FDInputMouse::GetDevice() { return false; } - + // How many buttons does this mouse have? DIDEVCAPS_DX3 caps = { sizeof(caps) }; hr = Device->GetCapabilities((DIDEVCAPS *)&caps); diff --git a/src/common/platform/win32/i_rawps2.cpp b/src/common/platform/win32/i_rawps2.cpp index 90e575a71..f418872e8 100644 --- a/src/common/platform/win32/i_rawps2.cpp +++ b/src/common/platform/win32/i_rawps2.cpp @@ -503,7 +503,7 @@ bool FRawPS2Controller::ProcessInput(RAWHID *raw, int code) // Generate events for buttons that have changed. int buttons = 0; - + // If we know we are digital, ignore the D-Pad. if (!digital) { @@ -538,7 +538,7 @@ void FRawPS2Controller::ProcessThumbstick(int value1, AxisInfo *axis1, int value { uint8_t buttonstate; double axisval1, axisval2; - + axisval1 = value1 * (2.0 / 255) - 1.0; axisval2 = value2 * (2.0 / 255) - 1.0; axisval1 = Joy_RemoveDeadZone(axisval1, axis1->DeadZone, NULL); diff --git a/src/common/platform/win32/i_system.cpp b/src/common/platform/win32/i_system.cpp index 0ec546567..9a3f4a795 100644 --- a/src/common/platform/win32/i_system.cpp +++ b/src/common/platform/win32/i_system.cpp @@ -288,8 +288,8 @@ static void DoPrintStr(const char *cpt, HWND edit, HANDLE StdOut) wchar_t wbuf[256]; int bpos = 0; - CHARRANGE selection; - CHARRANGE endselection; + CHARRANGE selection = {}; + CHARRANGE endselection = {}; LONG lines_before = 0, lines_after; CHARFORMAT format; @@ -868,7 +868,7 @@ static HCURSOR CreateBitmapCursor(int xhot, int yhot, HBITMAP and_mask, HBITMAP // Delete the bitmaps. DeleteObject(and_mask); DeleteObject(color_mask); - + return cursor; } diff --git a/src/common/platform/win32/i_xinput.cpp b/src/common/platform/win32/i_xinput.cpp index 2e8b79dc3..ba4605dd0 100644 --- a/src/common/platform/win32/i_xinput.cpp +++ b/src/common/platform/win32/i_xinput.cpp @@ -310,7 +310,7 @@ void FXInputController::ProcessThumbstick(int value1, AxisInfo *axis1, { uint8_t buttonstate; double axisval1, axisval2; - + axisval1 = (value1 - SHRT_MIN) * 2.0 / 65536 - 1.0; axisval2 = (value2 - SHRT_MIN) * 2.0 / 65536 - 1.0; axisval1 = Joy_RemoveDeadZone(axisval1, axis1->DeadZone, NULL); @@ -337,7 +337,7 @@ void FXInputController::ProcessTrigger(int value, AxisInfo *axis, int base) { uint8_t buttonstate; double axisval; - + axisval = Joy_RemoveDeadZone(value / 256.0, axis->DeadZone, &buttonstate); Joy_GenerateButtonEvents(axis->ButtonValue, buttonstate, 1, base); axis->ButtonValue = buttonstate; diff --git a/src/common/platform/win32/st_start.cpp b/src/common/platform/win32/st_start.cpp index 71ff4b1cd..3e67c795c 100644 --- a/src/common/platform/win32/st_start.cpp +++ b/src/common/platform/win32/st_start.cpp @@ -113,7 +113,7 @@ CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) FStartupScreen *FStartupScreen::CreateInstance(int max_progress) { FStartupScreen *scr = NULL; - HRESULT hr; + HRESULT hr = -1; if (!Args->CheckParm("-nostartup")) { @@ -310,7 +310,7 @@ void FBasicStartupScreen::NetMessage(const char *format, ...) { FString str; va_list argptr; - + va_start (argptr, format); str.VFormat (format, argptr); va_end (argptr); diff --git a/src/common/platform/win32/st_start_util.cpp b/src/common/platform/win32/st_start_util.cpp index bfad11662..ec9da4677 100644 --- a/src/common/platform/win32/st_start_util.cpp +++ b/src/common/platform/win32/st_start_util.cpp @@ -751,9 +751,9 @@ FStrifeStartupScreen::FStrifeStartupScreen(int max_progress, long& hr) if (lumpnum >= 0 && (lumplen = fileSystem.FileLength(lumpnum)) == StrifeStartupPicSizes[i]) { - auto lumpr = fileSystem.OpenFileReader(lumpnum); + auto lumpr1 = fileSystem.OpenFileReader(lumpnum); StartupPics[i] = new uint8_t[lumplen]; - lumpr.Read(StartupPics[i], lumplen); + lumpr1.Read(StartupPics[i], lumplen); } } diff --git a/src/common/platform/win32/win32glvideo.cpp b/src/common/platform/win32/win32glvideo.cpp index 3508f07da..1d0cbae8b 100644 --- a/src/common/platform/win32/win32glvideo.cpp +++ b/src/common/platform/win32/win32glvideo.cpp @@ -423,8 +423,6 @@ bool Win32GLVideo::InitHardware(HWND Window, int multisample) } int prof = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; - const char *version = Args->CheckValue("-glversion"); - for (; prof <= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; prof++) { diff --git a/src/common/platform/win32/win32vulkanvideo.cpp b/src/common/platform/win32/win32vulkanvideo.cpp index d2c2e7b40..4c8f887c0 100644 --- a/src/common/platform/win32/win32vulkanvideo.cpp +++ b/src/common/platform/win32/win32vulkanvideo.cpp @@ -17,7 +17,7 @@ void I_GetVulkanDrawableSize(int *width, int *height) RECT clientRect = { 0 }; GetClientRect(Window, &clientRect); - + if (width != nullptr) { *width = clientRect.right; diff --git a/src/common/platform/win32/win32vulkanvideo.h b/src/common/platform/win32/win32vulkanvideo.h index 2654597c7..0e77d18a7 100644 --- a/src/common/platform/win32/win32vulkanvideo.h +++ b/src/common/platform/win32/win32vulkanvideo.h @@ -21,7 +21,7 @@ public: { device = new VulkanDevice(); } - + ~Win32VulkanVideo() { delete device; diff --git a/src/common/rendering/gl/gl_buffers.cpp b/src/common/rendering/gl/gl_buffers.cpp index 9338fee98..5439319a9 100644 --- a/src/common/rendering/gl/gl_buffers.cpp +++ b/src/common/rendering/gl/gl_buffers.cpp @@ -192,12 +192,12 @@ void GLBuffer::GPUDropSync() void GLBuffer::GPUWaitSync() { GLenum status = glClientWaitSync(mGLSync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000 * 1000 * 50); // Wait for a max of 50ms... - + if (status != GL_ALREADY_SIGNALED && status != GL_CONDITION_SATISFIED) { //Printf("Error on glClientWaitSync: %d\n", status); } - + glDeleteSync(mGLSync); mGLSync = NULL; @@ -213,10 +213,10 @@ void GLVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t s { static int VFmtToGLFmt[] = { GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT_2_10_10_10_REV }; static uint8_t VFmtToSize[] = {4, 3, 2, 1, 4, 4}; - + mStride = stride; mNumBindingPoints = numBindingPoints; - + for(int i = 0; i < numAttributes; i++) { if (attrs[i].location >= 0 && attrs[i].location < VATTR_MAX) diff --git a/src/common/rendering/gl/gl_framebuffer.cpp b/src/common/rendering/gl/gl_framebuffer.cpp index 4e1af90b2..53a24bf06 100644 --- a/src/common/rendering/gl/gl_framebuffer.cpp +++ b/src/common/rendering/gl/gl_framebuffer.cpp @@ -69,7 +69,6 @@ EXTERN_CVAR(Int, gl_pipeline_depth); void gl_LoadExtensions(); void gl_PrintStartupLog(); -void Draw2D(F2DDrawer *drawer, FRenderState &state); extern bool vid_hdr_active; @@ -326,7 +325,6 @@ void OpenGLFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) { if (mat->Source()->GetUseType() == ETextureType::SWCanvas) return; - int flags = mat->GetScaleFlags(); int numLayers = mat->NumLayers(); MaterialLayerInfo* layer; auto base = static_cast(mat->GetLayer(0, translation, &layer)); diff --git a/src/common/rendering/gl/gl_framebuffer.h b/src/common/rendering/gl/gl_framebuffer.h index 8f8a139b6..37da64ba4 100644 --- a/src/common/rendering/gl/gl_framebuffer.h +++ b/src/common/rendering/gl/gl_framebuffer.h @@ -65,7 +65,7 @@ public: bool HWGammaActive = false; // Are we using hardware or software gamma? std::shared_ptr mDebug; // Debug API - + FTexture *WipeStartScreen() override; FTexture *WipeEndScreen() override; diff --git a/src/common/rendering/gl/gl_hwtexture.cpp b/src/common/rendering/gl/gl_hwtexture.cpp index a23ef82cc..37b066155 100644 --- a/src/common/rendering/gl/gl_hwtexture.cpp +++ b/src/common/rendering/gl/gl_hwtexture.cpp @@ -148,7 +148,7 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int { sourcetype = GL_BGRA; } - + if (!firstCall && glBufferID > 0) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rw, rh, sourcetype, GL_UNSIGNED_BYTE, buffer); else @@ -301,8 +301,6 @@ void FHardwareTexture::BindToFrameBuffer(int width, int height) bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags) { - int usebright = false; - bool needmipmap = (clampmode <= CLAMP_XY) && !forcenofilter; // Bind it to the system. @@ -317,7 +315,7 @@ bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, i int w = 0, h = 0; // Create this texture - + FTextureBuffer texbuffer; if (!tex->isHardwareCanvas()) diff --git a/src/common/rendering/gl/gl_renderbuffers.cpp b/src/common/rendering/gl/gl_renderbuffers.cpp index 08c3de3c1..88d7bce42 100644 --- a/src/common/rendering/gl/gl_renderbuffers.cpp +++ b/src/common/rendering/gl/gl_renderbuffers.cpp @@ -444,8 +444,6 @@ bool FGLRenderBuffers::CheckFrameBufferCompleteness() if (result == GL_FRAMEBUFFER_COMPLETE) return true; - bool FailedCreate = true; - if (gl_debug_level > 0) { FString error = "glCheckFramebufferStatus failed: "; diff --git a/src/common/rendering/gl/gl_renderer.h b/src/common/rendering/gl/gl_renderer.h index 3a4c55a70..71da1bf65 100644 --- a/src/common/rendering/gl/gl_renderer.h +++ b/src/common/rendering/gl/gl_renderer.h @@ -80,7 +80,7 @@ public: void DrawPresentTexture(const IntRect &box, bool applyGamma); void Flush(); void BeginFrame(); - + bool StartOffscreen(); void EndOffscreen(); diff --git a/src/common/rendering/gl/gl_renderstate.cpp b/src/common/rendering/gl/gl_renderstate.cpp index d742f35fd..688e46904 100644 --- a/src/common/rendering/gl/gl_renderstate.cpp +++ b/src/common/rendering/gl/gl_renderstate.cpp @@ -311,14 +311,13 @@ void FGLRenderState::ApplyMaterial(FMaterial *mat, int clampmode, int translatio if (tex->isHardwareCanvas()) static_cast(tex->GetTexture())->NeedUpdate(); clampmode = tex->GetClampMode(clampmode); - + // avoid rebinding the same texture multiple times. if (mat == lastMaterial && lastClamp == clampmode && translation == lastTranslation) return; lastMaterial = mat; lastClamp = clampmode; lastTranslation = translation; - int usebright = false; int maxbound = 0; int numLayers = mat->NumLayers(); diff --git a/src/common/rendering/gl/gl_samplers.cpp b/src/common/rendering/gl/gl_samplers.cpp index 3f1f53110..5ed7cbc19 100644 --- a/src/common/rendering/gl/gl_samplers.cpp +++ b/src/common/rendering/gl/gl_samplers.cpp @@ -98,7 +98,7 @@ void FSamplerManager::UnbindAll() glBindSampler(i, 0); } } - + uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) { unsigned int samp = mSamplers[num]; @@ -106,11 +106,11 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) return 255; } - + void FSamplerManager::SetTextureFilterMode() { GLint bounds[IHardwareTexture::MAX_TEXTURES]; - + // Unbind all for(int i = IHardwareTexture::MAX_TEXTURES-1; i >= 0; i--) { @@ -138,4 +138,4 @@ void FSamplerManager::SetTextureFilterMode() } -} \ No newline at end of file +} diff --git a/src/common/rendering/gl/gl_shader.cpp b/src/common/rendering/gl/gl_shader.cpp index 60c5677a6..f8287a499 100644 --- a/src/common/rendering/gl/gl_shader.cpp +++ b/src/common/rendering/gl/gl_shader.cpp @@ -336,7 +336,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * #endif )"; - + #ifdef __APPLE__ // The noise functions are completely broken in macOS OpenGL drivers @@ -620,7 +620,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * { char stringbuf[20]; mysnprintf(stringbuf, 20, "texture%d", i); - int tempindex = glGetUniformLocation(hShader, stringbuf); + tempindex = glGetUniformLocation(hShader, stringbuf); if (tempindex > 0) glUniform1i(tempindex, i - 1); } @@ -783,8 +783,8 @@ void FShaderCollection::CompileShaders(EPassType passType) mMaterialShaders.Push(shc); if (i < SHADER_NoTexture) { - FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType); - mMaterialShadersNAT.Push(shc); + FShader *shc1 = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType); + mMaterialShadersNAT.Push(shc1); } } diff --git a/src/common/rendering/gl/gl_shader.h b/src/common/rendering/gl/gl_shader.h index b42e144ef..ec2289833 100644 --- a/src/common/rendering/gl/gl_shader.h +++ b/src/common/rendering/gl/gl_shader.h @@ -325,7 +325,7 @@ class FShaderCollection void Clean(); void CompileShaders(EPassType passType); - + public: FShaderCollection(EPassType passType); ~FShaderCollection(); diff --git a/src/common/rendering/gl/gl_stereo3d.cpp b/src/common/rendering/gl/gl_stereo3d.cpp index 1d98874e3..c9a4bdd75 100644 --- a/src/common/rendering/gl/gl_stereo3d.cpp +++ b/src/common/rendering/gl/gl_stereo3d.cpp @@ -1,28 +1,38 @@ -// -//--------------------------------------------------------------------------- -// -// Copyright(C) 2015 Christopher Bruns -// All rights reserved. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program 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 Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//-------------------------------------------------------------------------- -// /* -** gl_stereo3d.cpp +** gl_stereo.cpp ** Stereoscopic 3D API ** +**--------------------------------------------------------------------------- +** Copyright 2015 Christopher Bruns +** Copyright 2016-2021 Christoph Oelckers +** 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 "gl_system.h" diff --git a/src/common/rendering/gl_load/gl_interface.cpp b/src/common/rendering/gl_load/gl_interface.cpp index 3b5309e8c..344a3d4fa 100644 --- a/src/common/rendering/gl_load/gl_interface.cpp +++ b/src/common/rendering/gl_load/gl_interface.cpp @@ -230,7 +230,7 @@ void gl_PrintStartupLog() Printf ("Max. texture units: %d\n", v); glGetIntegerv(GL_MAX_VARYING_FLOATS, &v); Printf ("Max. varying: %d\n", v); - + if (gl.flags & RFL_SHADER_STORAGE_BUFFER) { glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &v); diff --git a/src/common/rendering/gl_load/gl_load.c b/src/common/rendering/gl_load/gl_load.c index bf563afe0..e29207f4a 100644 --- a/src/common/rendering/gl_load/gl_load.c +++ b/src/common/rendering/gl_load/gl_load.c @@ -9,7 +9,7 @@ static void* AppleGLGetProcAddress (const char *name) { static void* image = NULL; - + if (NULL == image) image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); @@ -61,9 +61,9 @@ static int TestPointer(const PROC pTest) ptrdiff_t iTest; if(!pTest) return 0; iTest = (ptrdiff_t)pTest; - + if(iTest == 1 || iTest == 2 || iTest == 3 || iTest == -1) return 0; - + return 1; } @@ -119,7 +119,7 @@ static PROC WinGetProcAddress(const char *name) glMod = GetModuleHandleA("OpenGL32.dll"); return (PROC)GetProcAddress(glMod, (LPCSTR)name); } - + #define IntGetProcAddress(name) WinGetProcAddress(name) #else #if defined(__APPLE__) @@ -3363,7 +3363,7 @@ static ogl_StrToExtMap *FindExtEntry(const char *extensionName) if(strcmp(extensionName, currLoc->extensionName) == 0) return currLoc; } - + return NULL; } @@ -3465,7 +3465,7 @@ int ogl_LoadFunctions() { int numFailed = 0; ClearExtensionVars(); - + _ptrc_glGetIntegerv = (void (CODEGEN_FUNCPTR *)(GLenum, GLint *))IntGetProcAddress("glGetIntegerv"); if(!_ptrc_glGetIntegerv) return ogl_LOAD_FAILED; _ptrc_glGetStringi = (const GLubyte * (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glGetStringi"); @@ -3479,7 +3479,7 @@ int ogl_LoadFunctions() } numFailed = Load_Version_4_5(); - + if(numFailed == 0) return ogl_LOAD_SUCCEEDED; else @@ -3515,7 +3515,7 @@ int ogl_IsVersionGEQ(int majorVersion, int minorVersion) { if(g_major_version == 0) GetGLVersion(); - + if(majorVersion < g_major_version) return 1; if(majorVersion > g_major_version) return 0; if(minorVersion <= g_minor_version) return 1; diff --git a/src/common/rendering/gles/glad/include/glad/glad.h b/src/common/rendering/gles/glad/include/glad/glad.h index 5a7c1505e..212864bc1 100644 --- a/src/common/rendering/gles/glad/include/glad/glad.h +++ b/src/common/rendering/gles/glad/include/glad/glad.h @@ -7,7 +7,7 @@ APIs: gles2=2.0 Profile: compatibility Extensions: - + Loader: True Local files: False Omit khrplatform: False diff --git a/src/common/rendering/gles/glad/include/glad/glad_egl.h b/src/common/rendering/gles/glad/include/glad/glad_egl.h index fbc5b8630..1c47f7ced 100644 --- a/src/common/rendering/gles/glad/include/glad/glad_egl.h +++ b/src/common/rendering/gles/glad/include/glad/glad_egl.h @@ -7,7 +7,7 @@ APIs: egl=1.4 Profile: - Extensions: - + Loader: True Local files: False Omit khrplatform: False diff --git a/src/common/rendering/gles/glad/src/glad.c b/src/common/rendering/gles/glad/src/glad.c index 9da9f0ed1..6653cc3f6 100644 --- a/src/common/rendering/gles/glad/src/glad.c +++ b/src/common/rendering/gles/glad/src/glad.c @@ -7,7 +7,7 @@ APIs: gles2=2.0 Profile: compatibility Extensions: - + Loader: True Local files: False Omit khrplatform: False diff --git a/src/common/rendering/gles/glad/src/glad_egl.c b/src/common/rendering/gles/glad/src/glad_egl.c index 3c939401c..8d0744041 100644 --- a/src/common/rendering/gles/glad/src/glad_egl.c +++ b/src/common/rendering/gles/glad/src/glad_egl.c @@ -7,7 +7,7 @@ APIs: egl=1.4 Profile: - Extensions: - + Loader: True Local files: False Omit khrplatform: False diff --git a/src/common/rendering/gles/gles_buffers.cpp b/src/common/rendering/gles/gles_buffers.cpp index de815ea34..0b5f18024 100644 --- a/src/common/rendering/gles/gles_buffers.cpp +++ b/src/common/rendering/gles/gles_buffers.cpp @@ -79,7 +79,7 @@ GLBuffer::~GLBuffer() glBindBuffer(mUseType, 0); glDeleteBuffers(1, &mBufferId); } - + if (memory) delete[] memory; } @@ -129,9 +129,9 @@ void GLBuffer::SetData(size_t size, const void* data, BufferUsageType usage) void GLBuffer::SetSubData(size_t offset, size_t size, const void *data) { Bind(); - + memcpy(memory + offset, data, size); - + if (!isData) { glBufferSubData(mUseType, offset, size, data); @@ -143,7 +143,7 @@ void GLBuffer::Upload(size_t start, size_t size) if (!gles.useMappedBuffers) { Bind(); - + if(size) glBufferSubData(mUseType, start, size, memory + start); } @@ -278,10 +278,10 @@ void GLVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t s { static int VFmtToGLFmt[] = { GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_UNSIGNED_BYTE, GL_FLOAT }; // TODO Fix last entry GL_INT_2_10_10_10_REV, normals for models will be broken static uint8_t VFmtToSize[] = {4, 3, 2, 1, 4, 4}; - + mStride = stride; mNumBindingPoints = numBindingPoints; - + for(int i = 0; i < numAttributes; i++) { if (attrs[i].location >= 0 && attrs[i].location < VATTR_MAX) diff --git a/src/common/rendering/gles/gles_framebuffer.cpp b/src/common/rendering/gles/gles_framebuffer.cpp index 3391a6f02..c858e969f 100644 --- a/src/common/rendering/gles/gles_framebuffer.cpp +++ b/src/common/rendering/gles/gles_framebuffer.cpp @@ -67,8 +67,6 @@ EXTERN_CVAR(Int, gl_pipeline_depth); EXTERN_CVAR(Bool, gl_sort_textures); -void Draw2D(F2DDrawer *drawer, FRenderState &state); - extern bool vid_hdr_active; namespace OpenGLESRenderer @@ -136,8 +134,9 @@ void OpenGLFrameBuffer::InitializeState() glEnable(GL_DITHER); glDisable(GL_CULL_FACE); glDisable(GL_POLYGON_OFFSET_FILL); - + glEnable(GL_BLEND); + if (gles.depthClampAvailable) glEnable(GL_DEPTH_CLAMP); glDisable(GL_DEPTH_TEST); @@ -236,7 +235,7 @@ const char* OpenGLFrameBuffer::DeviceName() const void OpenGLFrameBuffer::Swap() { - + Finish.Reset(); Finish.Clock(); @@ -244,7 +243,7 @@ void OpenGLFrameBuffer::Swap() FPSLimit(); SwapBuffers(); - + mVertexData->NextPipelineBuffer(); mVertexData->WaitSync(); @@ -286,7 +285,6 @@ void OpenGLFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) { if (mat->Source()->GetUseType() == ETextureType::SWCanvas) return; - int flags = mat->GetScaleFlags(); int numLayers = mat->NumLayers(); MaterialLayerInfo* layer; auto base = static_cast(mat->GetLayer(0, translation, &layer)); diff --git a/src/common/rendering/gles/gles_framebuffer.h b/src/common/rendering/gles/gles_framebuffer.h index 25626c659..d550b8f10 100644 --- a/src/common/rendering/gles/gles_framebuffer.h +++ b/src/common/rendering/gles/gles_framebuffer.h @@ -61,7 +61,7 @@ public: bool HWGammaActive = false; // Are we using hardware or software gamma? std::shared_ptr mDebug; // Debug API - + FTexture *WipeStartScreen() override; FTexture *WipeEndScreen() override; diff --git a/src/common/rendering/gles/gles_hwtexture.cpp b/src/common/rendering/gles/gles_hwtexture.cpp index a342f24c2..43425ce7d 100644 --- a/src/common/rendering/gles/gles_hwtexture.cpp +++ b/src/common/rendering/gles/gles_hwtexture.cpp @@ -132,14 +132,23 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int #if USE_GLES2 - sourcetype = GL_BGRA; - texformat = GL_BGRA; + if (glTextureBytes == 1) + { + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + sourcetype = GL_ALPHA; + texformat = GL_ALPHA; + } + else + { + sourcetype = GL_BGRA; + texformat = GL_BGRA; + } #else if (glTextureBytes == 1) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); sourcetype = GL_RED; - texformat = GL_R8; + texformat = GL_RED; } else { @@ -150,6 +159,16 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int glTexImage2D(GL_TEXTURE_2D, 0, texformat, rw, rh, 0, sourcetype, GL_UNSIGNED_BYTE, buffer); +#if !(USE_GLES2) + // The shader is using the alpha channel instead of red, this work on GLES but not on GL + // So the texture uses GL_RED and this swizzels the red channel into the alpha channel + if (glTextureBytes == 1) + { + GLint swizzleMask[] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } +#endif + if (deletebuffer && buffer) free(buffer); if (mipmap && TexFilter[gl_texture_filter].mipmapping) @@ -157,7 +176,7 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int glGenerateMipmap(GL_TEXTURE_2D); mipmapped = true; } - + if (texunit > 0) glActiveTexture(GL_TEXTURE0); else if (texunit == -1) glBindTexture(GL_TEXTURE_2D, textureBinding); return glTexID; @@ -166,9 +185,6 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int void FHardwareTexture::AllocateBuffer(int w, int h, int texelsize) { - int rw = GetTexDimension(w); - int rh = GetTexDimension(h); - if (texelsize < 1 || texelsize > 4) texelsize = 4; glTextureBytes = texelsize; bufferpitch = w; @@ -287,8 +303,6 @@ void FHardwareTexture::BindToFrameBuffer(int width, int height) bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags) { - int usebright = false; - bool needmipmap = (clampmode <= CLAMP_XY) && !forcenofilter; // Bind it to the system. @@ -303,7 +317,7 @@ bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, i int w = 0, h = 0; // Create this texture - + FTextureBuffer texbuffer; if (!tex->isHardwareCanvas()) diff --git a/src/common/rendering/gles/gles_postprocess.cpp b/src/common/rendering/gles/gles_postprocess.cpp index b53de2f50..1bedaf9cc 100644 --- a/src/common/rendering/gles/gles_postprocess.cpp +++ b/src/common/rendering/gles/gles_postprocess.cpp @@ -158,10 +158,9 @@ void FGLRenderer::DrawPresentTexture(const IntRect &box, bool applyGamma) mPresentShader->Uniforms->Offset = { 0.0f, 0.0f }; mPresentShader->Uniforms.SetData(); - + for (size_t n = 0; n < mPresentShader->Uniforms.mFields.size(); n++) { - int index = -1; UniformFieldDesc desc = mPresentShader->Uniforms.mFields[n]; int loc = mPresentShader->Uniforms.UniformLocation[n]; switch (desc.Type) @@ -179,7 +178,7 @@ void FGLRenderer::DrawPresentTexture(const IntRect &box, bool applyGamma) break; } } - + RenderScreenQuad(); } @@ -224,4 +223,4 @@ void FGLRenderer::ClearBorders() glDisable(GL_SCISSOR_TEST); } -} \ No newline at end of file +} diff --git a/src/common/rendering/gles/gles_renderbuffers.cpp b/src/common/rendering/gles/gles_renderbuffers.cpp index 1d8147ae1..002734b99 100644 --- a/src/common/rendering/gles/gles_renderbuffers.cpp +++ b/src/common/rendering/gles/gles_renderbuffers.cpp @@ -44,7 +44,7 @@ namespace OpenGLESRenderer FGLRenderBuffers::FGLRenderBuffers() { - + } //========================================================================== @@ -56,7 +56,7 @@ namespace OpenGLESRenderer FGLRenderBuffers::~FGLRenderBuffers() { ClearScene(); - + DeleteTexture(mDitherTexture); } @@ -163,7 +163,7 @@ namespace OpenGLESRenderer mSceneTex = Create2DTexture("PipelineTexture", GL_RGBA, width, height); } - + //========================================================================== // @@ -178,7 +178,7 @@ namespace OpenGLESRenderer tex.Height = height; glGenTextures(1, &tex.handle); glBindTexture(GL_TEXTURE_2D, tex.handle); - + GLenum dataformat = 0, datatype = 0; /* switch (format) @@ -224,7 +224,7 @@ namespace OpenGLESRenderer PPGLRenderBuffer buf; glGenRenderbuffers(1, &buf.handle); glBindRenderbuffer(GL_RENDERBUFFER, buf.handle); - + glRenderbufferStorage(GL_RENDERBUFFER, format, width, height); return buf; } @@ -240,7 +240,7 @@ namespace OpenGLESRenderer PPGLFrameBuffer fb; glGenFramebuffers(1, &fb.handle); glBindFramebuffer(GL_FRAMEBUFFER, fb.handle); - + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer.handle, 0); if (CheckFrameBufferCompleteness()) ClearFrameBuffer(false, false); @@ -252,7 +252,7 @@ namespace OpenGLESRenderer PPGLFrameBuffer fb; glGenFramebuffers(1, &fb.handle); glBindFramebuffer(GL_FRAMEBUFFER, fb.handle); - + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer.handle, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthstencil.handle); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gles.depthStencilAvailable ? depthstencil.handle : stencil.handle); @@ -266,7 +266,7 @@ namespace OpenGLESRenderer PPGLFrameBuffer fb; glGenFramebuffers(1, &fb.handle); glBindFramebuffer(GL_FRAMEBUFFER, fb.handle); - + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer.handle); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthstencil.handle); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gles.depthStencilAvailable ? depthstencil.handle : stencil.handle); @@ -284,7 +284,7 @@ namespace OpenGLESRenderer glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer0.handle, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthstencil.handle); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gles.depthStencilAvailable ? depthstencil.handle : stencil.handle); - + if (CheckFrameBufferCompleteness()) ClearFrameBuffer(true, true); return fb; @@ -302,9 +302,6 @@ namespace OpenGLESRenderer if (result == GL_FRAMEBUFFER_COMPLETE) return true; - bool FailedCreate = true; - - FString error = "glCheckFramebufferStatus failed: "; switch (result) { @@ -314,7 +311,7 @@ namespace OpenGLESRenderer case GL_FRAMEBUFFER_UNSUPPORTED: error << "GL_FRAMEBUFFER_UNSUPPORTED"; break; } Printf("%s\n", error.GetChars()); - + return false; } @@ -372,7 +369,7 @@ namespace OpenGLESRenderer mDitherTexture.Bind(1, GL_NEAREST, GL_REPEAT); } - + //========================================================================== // // Makes the scene frame buffer active (multisample, depth, stecil, etc.) diff --git a/src/common/rendering/gles/gles_renderbuffers.h b/src/common/rendering/gles/gles_renderbuffers.h index ce052e26f..3369a864f 100644 --- a/src/common/rendering/gles/gles_renderbuffers.h +++ b/src/common/rendering/gles/gles_renderbuffers.h @@ -113,7 +113,7 @@ public: private: void ClearScene(); - + void CreateScene(int width, int height); void CreatePipeline(int width, int height); diff --git a/src/common/rendering/gles/gles_renderer.cpp b/src/common/rendering/gles/gles_renderer.cpp index b3b79ddae..1a33b3bd7 100644 --- a/src/common/rendering/gles/gles_renderer.cpp +++ b/src/common/rendering/gles/gles_renderer.cpp @@ -83,7 +83,7 @@ void FGLRenderer::Initialize(int width, int height) mScreenBuffers = new FGLRenderBuffers(); mBuffers = mScreenBuffers; mPresentShader = new FPresentShader(); - + mFBID = 0; mOldFBID = 0; @@ -97,7 +97,7 @@ FGLRenderer::~FGLRenderer() TexMan.FlushAll(); if (mShaderManager != nullptr) delete mShaderManager; if (mFBID != 0) glDeleteFramebuffers(1, &mFBID); - + if (mBuffers) delete mBuffers; if (mPresentShader) delete mPresentShader; } @@ -110,7 +110,6 @@ FGLRenderer::~FGLRenderer() bool FGLRenderer::StartOffscreen() { - bool firstBind = (mFBID == 0); if (mFBID == 0) glGenFramebuffers(1, &mFBID); glGetIntegerv(GL_FRAMEBUFFER_BINDING, &mOldFBID); diff --git a/src/common/rendering/gles/gles_renderer.h b/src/common/rendering/gles/gles_renderer.h index a19690029..3322e06bf 100644 --- a/src/common/rendering/gles/gles_renderer.h +++ b/src/common/rendering/gles/gles_renderer.h @@ -67,12 +67,12 @@ public: void PresentStereo(); void RenderScreenQuad(); void PostProcessScene(int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D); - + void CopyToBackbuffer(const IntRect *bounds, bool applyGamma); void DrawPresentTexture(const IntRect &box, bool applyGamma); void Flush(); void BeginFrame(); - + bool StartOffscreen(); void EndOffscreen(); diff --git a/src/common/rendering/gles/gles_renderstate.cpp b/src/common/rendering/gles/gles_renderstate.cpp index 961ec8121..76718f649 100644 --- a/src/common/rendering/gles/gles_renderstate.cpp +++ b/src/common/rendering/gles/gles_renderstate.cpp @@ -94,7 +94,7 @@ void FGLRenderState::Reset() bool FGLRenderState::ApplyShader() { static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; - + ShaderFlavourData flavour; // Need to calc light data now in order to select correct shader @@ -127,7 +127,7 @@ bool FGLRenderState::ApplyShader() if (modLights + subLights + addLights > (int)gles.maxlights) addLights = gles.maxlights - modLights - subLights; - + totalLights = modLights + subLights + addLights; // Skip passed the first 4 floats so the upload below only contains light data @@ -152,12 +152,13 @@ bool FGLRenderState::ApplyShader() flavour.texFlags = tm >> 16; //Move flags to start of word if (mTextureClamp && flavour.textureMode == TM_NORMAL) flavour.textureMode = TM_CLAMPY; // fixme. Clamp can now be combined with all modes. - + if (flavour.textureMode == -1) flavour.textureMode = 0; flavour.blendFlags = (int)(mStreamData.uTextureAddColor.a + 0.01); + flavour.paletteInterpolate = !!(flavour.blendFlags & 0x4000); flavour.twoDFog = false; flavour.fogEnabled = false; @@ -165,7 +166,7 @@ bool FGLRenderState::ApplyShader() flavour.colouredFog = false; flavour.fogEquationRadial = (gl_fogmode == 2); - + flavour.twoDFog = false; flavour.fogEnabled = false; flavour.colouredFog = false; @@ -196,7 +197,7 @@ bool FGLRenderState::ApplyShader() flavour.useObjectColor2 = (mStreamData.uObjectColor2.a > 0); flavour.useGlowTopColor = mGlowEnabled && (mStreamData.uGlowTopColor[3] > 0); flavour.useGlowBottomColor = mGlowEnabled && (mStreamData.uGlowBottomColor[3] > 0); - + flavour.useColorMap = (mColorMapSpecial >= CM_FIRSTSPECIALCOLORMAP) || (mColorMapFlash != 1); flavour.buildLighting = (mHwUniforms->mPalLightLevels >> 16) == 5; // Build engine mode @@ -217,7 +218,7 @@ bool FGLRenderState::ApplyShader() activeShader->Bind(flavour); } - + if (mHwUniforms) { activeShader->cur->muProjectionMatrix.Set(&mHwUniforms->mProjectionMatrix); @@ -334,7 +335,7 @@ bool FGLRenderState::ApplyShader() { // Calculate the total number of vec4s we need int totalVectors = totalLights * LIGHT_VEC4_NUM; - + if (totalVectors > (int)gles.numlightvectors) totalVectors = gles.numlightvectors; @@ -347,7 +348,7 @@ bool FGLRenderState::ApplyShader() activeShader->cur->muLightRange.Set(range); } - + return true; } @@ -389,19 +390,17 @@ void FGLRenderState::ApplyState() mMaterial.mChanged = false; } - if (mBias.mChanged) + + if (mBias.mFactor == 0 && mBias.mUnits == 0) { - if (mBias.mFactor == 0 && mBias.mUnits == 0) - { - glDisable(GL_POLYGON_OFFSET_FILL); - } - else - { - glEnable(GL_POLYGON_OFFSET_FILL); - } - glPolygonOffset(mBias.mFactor, mBias.mUnits); - mBias.mChanged = false; + glDisable(GL_POLYGON_OFFSET_FILL); } + else + { + glEnable(GL_POLYGON_OFFSET_FILL); + } + glPolygonOffset(mBias.mFactor, mBias.mUnits); + mBias.mChanged = false; } void FGLRenderState::ApplyBuffers() @@ -451,14 +450,13 @@ void FGLRenderState::ApplyMaterial(FMaterial *mat, int clampmode, int translatio if (tex->isHardwareCanvas()) static_cast(tex->GetTexture())->NeedUpdate(); clampmode = tex->GetClampMode(clampmode); - + // avoid rebinding the same texture multiple times. if (mat == lastMaterial && lastClamp == clampmode && translation == lastTranslation) return; lastMaterial = mat; lastClamp = clampmode; lastTranslation = translation; - int usebright = false; int maxbound = 0; int numLayers = mat->NumLayers(); diff --git a/src/common/rendering/gles/gles_samplers.cpp b/src/common/rendering/gles/gles_samplers.cpp index c088657c7..8d9ddecdf 100644 --- a/src/common/rendering/gles/gles_samplers.cpp +++ b/src/common/rendering/gles/gles_samplers.cpp @@ -60,9 +60,9 @@ FSamplerManager::~FSamplerManager() void FSamplerManager::UnbindAll() { - + } - + uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) { @@ -157,14 +157,14 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) return 255; } - + void FSamplerManager::SetTextureFilterMode() { /* GLRenderer->FlushTextures(); GLint bounds[IHardwareTexture::MAX_TEXTURES]; - + // Unbind all for(int i = IHardwareTexture::MAX_TEXTURES-1; i >= 0; i--) { diff --git a/src/common/rendering/gles/gles_shader.cpp b/src/common/rendering/gles/gles_shader.cpp index 37a9fd7ed..f67aa375e 100644 --- a/src/common/rendering/gles/gles_shader.cpp +++ b/src/common/rendering/gles/gles_shader.cpp @@ -266,7 +266,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * // light buffers uniform vec4 lights[MAXIMUM_LIGHT_VECTORS]; - + uniform mat4 ProjectionMatrix; uniform mat4 ViewMatrix; uniform mat4 NormalViewMatrix; @@ -370,7 +370,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * #define glowtexture texture4 #endif )"; - + #ifdef NPOT_EMULATION i_data += "#define NPOT_EMULATION\nuniform vec2 uNpotEmulation;\n"; #endif @@ -392,7 +392,6 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * assert(screen->mLights != NULL); - bool lightbuffertype = screen->mLights->GetBufferType(); unsigned int lightbuffersize = screen->mLights->GetBlockSize(); vp_comb.Format("#version 100\n#define NUM_UBO_LIGHTS %d\n#define NO_CLIPDISTANCE_SUPPORT\n", lightbuffersize); @@ -495,7 +494,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * } shaderData->hShader = glCreateProgram(); - + uint32_t binaryFormat = 0; TArray binary; if (IsShaderCacheActive()) @@ -687,7 +686,7 @@ bool FShader::Bind(ShaderFlavourData& flavour) variantConfig.AppendFormat("#define MAXIMUM_LIGHT_VECTORS %d\n", gles.numlightvectors); variantConfig.AppendFormat("#define DEF_TEXTURE_MODE %d\n", flavour.textureMode); variantConfig.AppendFormat("#define DEF_TEXTURE_FLAGS %d\n", flavour.texFlags); - variantConfig.AppendFormat("#define DEF_BLEND_FLAGS %d\n", flavour.blendFlags); + variantConfig.AppendFormat("#define DEF_BLEND_FLAGS %d\n", flavour.blendFlags & 0x7); variantConfig.AppendFormat("#define DEF_FOG_2D %d\n", flavour.twoDFog); variantConfig.AppendFormat("#define DEF_FOG_ENABLED %d\n", flavour.fogEnabled); variantConfig.AppendFormat("#define DEF_FOG_RADIAL %d\n", flavour.fogEquationRadial); @@ -695,7 +694,7 @@ bool FShader::Bind(ShaderFlavourData& flavour) variantConfig.AppendFormat("#define DEF_USE_U_LIGHT_LEVEL %d\n", flavour.useULightLevel); variantConfig.AppendFormat("#define DEF_DO_DESATURATE %d\n", flavour.doDesaturate); - + variantConfig.AppendFormat("#define DEF_DYNAMIC_LIGHTS_MOD %d\n", flavour.dynLightsMod); variantConfig.AppendFormat("#define DEF_DYNAMIC_LIGHTS_SUB %d\n", flavour.dynLightsSub); variantConfig.AppendFormat("#define DEF_DYNAMIC_LIGHTS_ADD %d\n", flavour.dynLightsAdd); @@ -703,7 +702,7 @@ bool FShader::Bind(ShaderFlavourData& flavour) variantConfig.AppendFormat("#define DEF_USE_OBJECT_COLOR_2 %d\n", flavour.useObjectColor2); variantConfig.AppendFormat("#define DEF_USE_GLOW_TOP_COLOR %d\n", flavour.useGlowTopColor); variantConfig.AppendFormat("#define DEF_USE_GLOW_BOTTOM_COLOR %d\n", flavour.useGlowBottomColor); - + variantConfig.AppendFormat("#define DEF_USE_COLOR_MAP %d\n", flavour.useColorMap); variantConfig.AppendFormat("#define DEF_BUILD_LIGHTING %d\n", flavour.buildLighting); variantConfig.AppendFormat("#define DEF_BANDED_SW_LIGHTING %d\n", flavour.bandedSwLight); @@ -715,6 +714,7 @@ bool FShader::Bind(ShaderFlavourData& flavour) #endif variantConfig.AppendFormat("#define DEF_HAS_SPOTLIGHT %d\n", flavour.hasSpotLight); + variantConfig.AppendFormat("#define DEF_PALETTE_INTERPOLATE %d\n", flavour.paletteInterpolate); //Printf("Shader: %s, %08x %s", mFragProg2.GetChars(), tag, variantConfig.GetChars()); @@ -851,7 +851,7 @@ void FShaderCollection::CompileShaders(EPassType passType) mMaterialShaders.Push(shc); if (i < SHADER_NoTexture) { - FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType); + shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType); mMaterialShadersNAT.Push(shc); } } diff --git a/src/common/rendering/gles/gles_shader.h b/src/common/rendering/gles/gles_shader.h index 66fcb1ebd..72a242c1b 100644 --- a/src/common/rendering/gles/gles_shader.h +++ b/src/common/rendering/gles/gles_shader.h @@ -277,13 +277,14 @@ public: #endif bool hasSpotLight; + bool paletteInterpolate; }; class FShader { friend class FShaderCollection; friend class FGLRenderState; - + FName mName; FString mVertProg; @@ -378,7 +379,7 @@ public: FShader(const char *name) : mName(name) { - + } ~FShader(); @@ -393,9 +394,9 @@ public: { uint32_t tag = 0; tag |= (flavour.textureMode & 0x7); - + tag |= (flavour.texFlags & 7) << 3; - + tag |= (flavour.blendFlags & 7) << 6; tag |= (flavour.twoDFog & 1) << 7; @@ -419,15 +420,15 @@ public: #ifdef NPOT_EMULATION tag |= (flavour.npotEmulation & 1) << 22; #endif - tag |= (flavour.hasSpotLight & 1) << 23; + tag |= (flavour.paletteInterpolate & 1) << 24; return tag; } bool Bind(ShaderFlavourData& flavour); - + }; //========================================================================== @@ -461,7 +462,7 @@ class FShaderCollection void Clean(); void CompileShaders(EPassType passType); - + public: FShaderCollection(EPassType passType); ~FShaderCollection(); @@ -480,7 +481,10 @@ public: { return mMaterialShaders[eff]; } - return NULL; + else // This can happen if we try and active a user shader which is not loaded, so return default shader so it does not crash + { + return mMaterialShaders[0]; + } } }; diff --git a/src/common/rendering/gles/gles_shaderprogram.cpp b/src/common/rendering/gles/gles_shaderprogram.cpp index 6aa9ec172..784c85c30 100644 --- a/src/common/rendering/gles/gles_shaderprogram.cpp +++ b/src/common/rendering/gles/gles_shaderprogram.cpp @@ -104,7 +104,7 @@ void FShaderProgram::CompileShader(ShaderType type) const auto &handle = mShaders[type]; - + const FString &patchedCode = mShaderSources[type]; int lengths[1] = { (int)patchedCode.Len() }; const char *sources[1] = { patchedCode.GetChars() }; @@ -290,4 +290,4 @@ void FPresentShader::Bind() mShader->Bind(); } -} \ No newline at end of file +} diff --git a/src/common/rendering/gles/gles_system.cpp b/src/common/rendering/gles/gles_system.cpp index 79f6e0a48..51f8ee6a2 100644 --- a/src/common/rendering/gles/gles_system.cpp +++ b/src/common/rendering/gles/gles_system.cpp @@ -63,7 +63,7 @@ static PROC(WINAPI* getprocaddress)(LPCSTR name); static void* LoadGLES2Proc(const char* name) { HINSTANCE hGetProcIDDLL = LoadLibraryA("libGLESv2.dll"); - + int error = GetLastError(); void* addr = GetProcAddress(hGetProcIDDLL, name); @@ -169,14 +169,14 @@ namespace OpenGLESRenderer gles.modelstring = (char*)glGetString(GL_RENDERER); gles.vendorstring = (char*)glGetString(GL_VENDOR); - + gl_customshader = false; GLint maxTextureSize[1]; glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxTextureSize); gles.max_texturesize = maxTextureSize[0]; - + Printf("GL_MAX_TEXTURE_SIZE: %d\n", gles.max_texturesize); #if USE_GLES2 @@ -189,7 +189,7 @@ namespace OpenGLESRenderer gles.useMappedBuffers = true; gles.depthClampAvailable = true; #endif - + gles.numlightvectors = (gles.maxlights * LIGHT_VEC4_NUM); } } diff --git a/src/common/rendering/hwrenderer/data/buffers.h b/src/common/rendering/hwrenderer/data/buffers.h index 980adde5e..021040de0 100644 --- a/src/common/rendering/hwrenderer/data/buffers.h +++ b/src/common/rendering/hwrenderer/data/buffers.h @@ -24,7 +24,7 @@ enum VATTR_VERTEX2, VATTR_NORMAL, VATTR_NORMAL2, - + VATTR_MAX }; diff --git a/src/common/rendering/hwrenderer/data/flatvertices.cpp b/src/common/rendering/hwrenderer/data/flatvertices.cpp index 6fe258b26..599f98793 100644 --- a/src/common/rendering/hwrenderer/data/flatvertices.cpp +++ b/src/common/rendering/hwrenderer/data/flatvertices.cpp @@ -149,7 +149,6 @@ std::pair FFlatVertexBuffer::AllocVertices(unsigned { FFlatVertex *p = GetBuffer(); auto index = mCurIndex.fetch_add(count); - auto offset = index; if (index + count >= BUFFER_SIZE_TO_USE) { // If a single scene needs 2'000'000 vertices there must be something very wrong. diff --git a/src/common/rendering/hwrenderer/data/flatvertices.h b/src/common/rendering/hwrenderer/data/flatvertices.h index 619128a33..b6f5b7eb1 100644 --- a/src/common/rendering/hwrenderer/data/flatvertices.h +++ b/src/common/rendering/hwrenderer/data/flatvertices.h @@ -52,7 +52,7 @@ public: IVertexBuffer *mVertexBufferPipeline[HW_MAX_PIPELINE_BUFFERS]; IIndexBuffer *mIndexBuffer; - + unsigned int mIndex; std::atomic mCurIndex; diff --git a/src/common/rendering/hwrenderer/data/hw_clock.cpp b/src/common/rendering/hwrenderer/data/hw_clock.cpp index e9affdbe6..a9209d236 100644 --- a/src/common/rendering/hwrenderer/data/hw_clock.cpp +++ b/src/common/rendering/hwrenderer/data/hw_clock.cpp @@ -167,7 +167,7 @@ void CheckBench() FString compose; if (sysCallbacks.GetLocationDescription) compose = sysCallbacks.GetLocationDescription(); - + AppendRenderStats(compose); AppendRenderTimes(compose); AppendLightStats(compose); diff --git a/src/common/rendering/hwrenderer/data/hw_cvars.cpp b/src/common/rendering/hwrenderer/data/hw_cvars.cpp index 5c1b64359..14f5f2a87 100644 --- a/src/common/rendering/hwrenderer/data/hw_cvars.cpp +++ b/src/common/rendering/hwrenderer/data/hw_cvars.cpp @@ -44,7 +44,7 @@ #include "printf.h" -CUSTOM_CVAR(Int, gl_fogmode, 1, CVAR_ARCHIVE | CVAR_NOINITCALL) +CUSTOM_CVAR(Int, gl_fogmode, 2, CVAR_ARCHIVE | CVAR_NOINITCALL) { if (self > 2) self = 2; if (self < 0) self = 0; diff --git a/src/common/rendering/hwrenderer/data/hw_dynlightdata.h b/src/common/rendering/hwrenderer/data/hw_dynlightdata.h index e24e49bed..7da1c1b5a 100644 --- a/src/common/rendering/hwrenderer/data/hw_dynlightdata.h +++ b/src/common/rendering/hwrenderer/data/hw_dynlightdata.h @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, @@ -23,6 +23,8 @@ #ifndef __GLC_DYNLIGHT_H #define __GLC_DYNLIGHT_H +#include "tarray.h" + struct FDynLightData { TArray arrays[3]; @@ -49,7 +51,7 @@ struct FDynLightData if (siz[1] > max) siz[1] = max; if (siz[2] > max) siz[2] = max; } - + }; diff --git a/src/common/rendering/hwrenderer/data/hw_lightbuffer.cpp b/src/common/rendering/hwrenderer/data/hw_lightbuffer.cpp index 9f7bb66c2..622626056 100644 --- a/src/common/rendering/hwrenderer/data/hw_lightbuffer.cpp +++ b/src/common/rendering/hwrenderer/data/hw_lightbuffer.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, @@ -37,10 +37,10 @@ FLightBuffer::FLightBuffer(int pipelineNbr): mPipelineNbr(pipelineNbr) { int maxNumberOfLights = 80000; - + mBufferSize = maxNumberOfLights * ELEMENTS_PER_LIGHT; mByteSize = mBufferSize * ELEMENT_SIZE; - + // Hack alert: On Intel's GL driver SSBO's perform quite worse than UBOs. // We only want to disable using SSBOs for lights but not disable the feature entirely. // Note that using an uniform buffer here will limit the number of lights per surface so it isn't done for NVidia and AMD. @@ -57,7 +57,7 @@ FLightBuffer::FLightBuffer(int pipelineNbr): mBlockSize = screen->maxuniformblock / ELEMENT_SIZE; mBlockAlign = screen->uniformblockalignment / ELEMENT_SIZE; mMaxUploadSize = (mBlockSize - mBlockAlign); - + //mByteSize += screen->maxuniformblock; // to avoid mapping beyond the end of the buffer. REMOVED this...This can try to allocate 100's of MB.. } @@ -96,7 +96,7 @@ int FLightBuffer::UploadLights(FDynLightData &data) if (totalsize > (int)mMaxUploadSize) { int diff = totalsize - (int)mMaxUploadSize; - + size2 -= diff; if (size2 < 0) { @@ -115,14 +115,14 @@ int FLightBuffer::UploadLights(FDynLightData &data) assert(mBufferPointer != nullptr); if (mBufferPointer == nullptr) return -1; if (totalsize <= 1) return -1; // there are no lights - + unsigned thisindex = mIndex.fetch_add(totalsize); float parmcnt[] = { 0, float(size0), float(size0 + size1), float(size0 + size1 + size2) }; if (thisindex + totalsize <= mBufferSize) { float *copyptr = mBufferPointer + thisindex*4; - + memcpy(©ptr[0], parmcnt, ELEMENT_SIZE); memcpy(©ptr[4], &data.arrays[0][0], size0 * ELEMENT_SIZE); memcpy(©ptr[4 + 4*size0], &data.arrays[1][0], size1 * ELEMENT_SIZE); diff --git a/src/common/rendering/hwrenderer/data/hw_lightbuffer.h b/src/common/rendering/hwrenderer/data/hw_lightbuffer.h index 441dc55ff..ad266bd94 100644 --- a/src/common/rendering/hwrenderer/data/hw_lightbuffer.h +++ b/src/common/rendering/hwrenderer/data/hw_lightbuffer.h @@ -23,7 +23,7 @@ class FLightBuffer unsigned int mBufferSize; unsigned int mByteSize; unsigned int mMaxUploadSize; - + void CheckSize(); public: diff --git a/src/common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp b/src/common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp index e4d5ba030..dcad82abd 100644 --- a/src/common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp +++ b/src/common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, diff --git a/src/common/rendering/hwrenderer/data/hw_renderstate.h b/src/common/rendering/hwrenderer/data/hw_renderstate.h index 5b4af5681..bd8fd4d9e 100644 --- a/src/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/src/common/rendering/hwrenderer/data/hw_renderstate.h @@ -585,7 +585,7 @@ public: void SetDepthBias(float a, float b) { - mBias.mChanged = mBias.mFactor != a || mBias.mUnits != b; + mBias.mChanged |= mBias.mFactor != a || mBias.mUnits != b; mBias.mFactor = a; mBias.mUnits = b; } @@ -597,7 +597,7 @@ public: void ClearDepthBias() { - mBias.mChanged = mBias.mFactor != 0 || mBias.mUnits != 0; + mBias.mChanged |= mBias.mFactor != 0 || mBias.mUnits != 0; mBias.mFactor = 0; mBias.mUnits = 0; } diff --git a/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp b/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp index 97420e0c2..2bb1747d3 100644 --- a/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp +++ b/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp @@ -152,7 +152,7 @@ FString RemoveSamplerBindings(FString code, TArray> &sam char *chars = code.LockBuffer(); ptrdiff_t startIndex = 0; - ptrdiff_t startpos, endpos; + ptrdiff_t startpos, endpos = 0; while (true) { ptrdiff_t matchIndex = code.IndexOf("layout(binding", startIndex); @@ -188,10 +188,10 @@ FString RemoveSamplerBindings(FString code, TArray> &sam if (isSamplerUniformName) { samplerstobind.Push(std::make_pair(identifier, val)); - for (auto pos = startpos; pos < endpos; pos++) + for (auto posi = startpos; posi < endpos; posi++) { - if (!IsGlslWhitespace(chars[pos])) - chars[pos] = ' '; + if (!IsGlslWhitespace(chars[posi])) + chars[posi] = ' '; } } } @@ -216,7 +216,6 @@ FString RemoveSamplerBindings(FString code, TArray> &sam FString RemoveLayoutLocationDecl(FString code, const char *inoutkeyword) { - ptrdiff_t len = code.Len(); char *chars = code.LockBuffer(); ptrdiff_t startIndex = 0; @@ -255,8 +254,8 @@ FString RemoveLayoutLocationDecl(FString code, const char *inoutkeyword) if (keywordFound && IsGlslWhitespace(chars[endIndex + i])) { // yes - replace declaration with spaces - for (auto i = matchIndex; i < endIndex; i++) - chars[i] = ' '; + for (auto ii = matchIndex; ii < endIndex; ii++) + chars[ii] = ' '; } startIndex = endIndex; diff --git a/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp b/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp index 26eaa2d2c..18f23e1d5 100644 --- a/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp +++ b/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp @@ -38,13 +38,13 @@ but then only in 2D where this reduces itself to a square. When main.fp samples from the shadow map it first decides in which direction the fragment is (relative to the light), like cubemap sampling does for 3D, but once again just for the 2D case. - + Texels 0-255 is Y positive, 256-511 is X positive, 512-767 is Y negative and 768-1023 is X negative. Generating the shadow map itself is done by FShadowMap::Update(). The shadow map texture's FBO is bound and then a screen quad is drawn to make a fragment shader cover all texels. For each fragment it shoots a ray and collects the distance to what it hit. - + The shadowmap.fp shader knows which light and texel it is processing by mapping gl_FragCoord.y back to the light index, and it knows which direction to ray trace by looking at gl_FragCoord.x. For example, if gl_FragCoord.y is 20.5, then it knows its processing light 20, and if gl_FragCoord.x is diff --git a/src/common/rendering/hwrenderer/data/hw_shadowmap.h b/src/common/rendering/hwrenderer/data/hw_shadowmap.h index e755c0f59..3bc2eb98f 100644 --- a/src/common/rendering/hwrenderer/data/hw_shadowmap.h +++ b/src/common/rendering/hwrenderer/data/hw_shadowmap.h @@ -4,6 +4,7 @@ #include "hw_aabbtree.h" #include "stats.h" #include +#include class IDataBuffer; diff --git a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp index 89a5a8436..0ab124025 100644 --- a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp +++ b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, @@ -98,7 +98,7 @@ void HWViewpointBuffer::Set2D(FRenderState &di, int width, int height, int pll) matrices.mProjectionMatrix.ortho(0, (float)width, (float)height, 0, -1.0f, 1.0f); matrices.CalcDependencies(); - + for (int n = 0; n < mPipelineNbr; n++) { mBufferPipeline[n]->Map(); diff --git a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h index 0fbd46dfa..90c64ca7f 100644 --- a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h +++ b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h @@ -18,7 +18,7 @@ class HWViewpointBuffer unsigned int mLastMappedIndex; unsigned int mByteSize; TArray mClipPlaneInfo; - + int m2DWidth = -1, m2DHeight = -1; unsigned int mBlockSize; diff --git a/src/common/rendering/hwrenderer/data/hw_vrmodes.cpp b/src/common/rendering/hwrenderer/data/hw_vrmodes.cpp index 35b5eea06..ac80eec54 100644 --- a/src/common/rendering/hwrenderer/data/hw_vrmodes.cpp +++ b/src/common/rendering/hwrenderer/data/hw_vrmodes.cpp @@ -1,27 +1,36 @@ -// -//--------------------------------------------------------------------------- -// -// Copyright(C) 2015 Christopher Bruns -// All rights reserved. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program 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 Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//-------------------------------------------------------------------------- -// /* -** gl_stereo_leftright.cpp -** Offsets for left and right eye views +** hw_vrmodes.cpp +** Matrix handling for stereo 3D rendering +** +**--------------------------------------------------------------------------- +** Copyright 2015 Christopher Bruns +** Copyright 2016-2021 Christoph Oelckers +** 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. +**--------------------------------------------------------------------------- +** ** */ @@ -154,9 +163,9 @@ VSMatrix VREyeInfo::GetProjection(float fov, float aspectRatio, float fovRatio) double bottom = -fH; double top = fH; - VSMatrix result(1); - result.frustum((float)left, (float)right, (float)bottom, (float)top, (float)zNear, (float)zFar); - return result; + VSMatrix fmat(1); + fmat.frustum((float)left, (float)right, (float)bottom, (float)top, (float)zNear, (float)zFar); + return fmat; } } diff --git a/src/common/rendering/hwrenderer/hw_draw2d.cpp b/src/common/rendering/hwrenderer/hw_draw2d.cpp index af10a7bf2..c54ba71d4 100644 --- a/src/common/rendering/hwrenderer/hw_draw2d.cpp +++ b/src/common/rendering/hwrenderer/hw_draw2d.cpp @@ -89,7 +89,6 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state) for(auto &cmd : commands) { - int gltrans = -1; state.SetRenderStyle(cmd.mRenderStyle); state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed)); state.EnableFog(2); // Special 2D mode 'fog'. diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp new file mode 100644 index 000000000..f23d4497f --- /dev/null +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp @@ -0,0 +1,139 @@ +/* +** Postprocessing framework +** Copyright (c) 2016-2020 Magnus Norddahl +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "vm.h" +#include "hwrenderer/postprocessing/hw_postprocessshader.h" +#include "hwrenderer/postprocessing/hw_postprocess.h" + +static void ShaderSetEnabled(const FString &shaderName, bool value) +{ + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (shader.Name == shaderName) + shader.Enabled = value; + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(_PPShader, SetEnabled, ShaderSetEnabled) +{ + PARAM_PROLOGUE; + PARAM_STRING(shaderName); + PARAM_BOOL(value); + ShaderSetEnabled(shaderName, value); + + return 0; +} + +static void ShaderSetUniform1f(const FString &shaderName, const FString &uniformName, double value) +{ + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (shader.Name == shaderName) + { + double *vec4 = shader.Uniforms[uniformName].Values; + vec4[0] = value; + vec4[1] = 0.0; + vec4[2] = 0.0; + vec4[3] = 1.0; + } + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(_PPShader, SetUniform1f, ShaderSetUniform1f) +{ + PARAM_PROLOGUE; + PARAM_STRING(shaderName); + PARAM_STRING(uniformName); + PARAM_FLOAT(value); + ShaderSetUniform1f(shaderName, uniformName, value); + return 0; +} + +DEFINE_ACTION_FUNCTION(_PPShader, SetUniform2f) +{ + PARAM_PROLOGUE; + PARAM_STRING(shaderName); + PARAM_STRING(uniformName); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (shader.Name == shaderName) + { + double *vec4 = shader.Uniforms[uniformName].Values; + vec4[0] = x; + vec4[1] = y; + vec4[2] = 0.0; + vec4[3] = 1.0; + } + } + return 0; +} + +DEFINE_ACTION_FUNCTION(_PPShader, SetUniform3f) +{ + PARAM_PROLOGUE; + PARAM_STRING(shaderName); + PARAM_STRING(uniformName); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (shader.Name == shaderName) + { + double *vec4 = shader.Uniforms[uniformName].Values; + vec4[0] = x; + vec4[1] = y; + vec4[2] = z; + vec4[3] = 1.0; + } + } + return 0; +} + +DEFINE_ACTION_FUNCTION(_PPShader, SetUniform1i) +{ + PARAM_PROLOGUE; + PARAM_STRING(shaderName); + PARAM_STRING(uniformName); + PARAM_INT(value); + + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (shader.Name == shaderName) + { + double *vec4 = shader.Uniforms[uniformName].Values; + vec4[0] = (double)value; + vec4[1] = 0.0; + vec4[2] = 0.0; + vec4[3] = 1.0; + } + } + return 0; +} diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp new file mode 100644 index 000000000..4608b9ce9 --- /dev/null +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp @@ -0,0 +1,136 @@ +/* +** Debug ccmds for post-process shaders +** Copyright (c) 2022 Rachael Alexanderson +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "hwrenderer/postprocessing/hw_postprocessshader.h" +#include "hwrenderer/postprocessing/hw_postprocess.h" +#include "printf.h" +#include "c_dispatch.h" + +CCMD (shaderenable) +{ + if (argv.argc() < 3) + { + Printf("Usage: shaderenable [name] [1/0/-1]\nState '-1' toggles the active shader state\n"); + return; + } + auto shaderName = argv[1]; + + int value = atoi(argv[2]); + + bool found = 0; + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (strcmp(shader.Name, shaderName) == 0) + { + if (value != -1) + shader.Enabled = value; + else + shader.Enabled = !shader.Enabled; //toggle + found = 1; + } + } + if (found && value != -1) + Printf("Changed active state of all instances of %s to %s\n", shaderName, value?"On":"Off"); + else if (found) + Printf("Toggled active state of all instances of %s\n", shaderName); + else + Printf("No shader named '%s' found\n", shaderName); +} + +CCMD (shaderuniform) +{ + if (argv.argc() < 3) + { + Printf("Usage: shaderuniform [shader name] [uniform name] [[value1 ..]]\n"); + return; + } + auto shaderName = argv[1]; + auto uniformName = argv[2]; + + bool found = 0; + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (strcmp(shader.Name, shaderName) == 0) + { + if (argv.argc() > 3) + { + double *vec4 = shader.Uniforms[uniformName].Values; + vec4[0] = argv.argc()>=4 ? atof(argv[3]) : 0.0; + vec4[1] = argv.argc()>=5 ? atof(argv[4]) : 0.0; + vec4[2] = argv.argc()>=6 ? atof(argv[5]) : 0.0; + vec4[3] = 1.0; + } + else + { + double *vec4 = shader.Uniforms[uniformName].Values; + Printf("Shader '%s' uniform '%s': %f %f %f\n", shaderName, uniformName, vec4[0], vec4[1], vec4[2]); + } + found = 1; + } + } + if (found && argv.argc() > 3) + Printf("Changed uniforms of %s named %s\n", shaderName, uniformName); + else if (!found) + Printf("No shader named '%s' found\n", shaderName); +} + +CCMD(listshaders) +{ + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + Printf("Shader (%i): %s\n", i, shader.Name.GetChars()); + } +} + +CCMD(listuniforms) +{ + if (argv.argc() < 2) + { + Printf("Usage: listuniforms [name]\n"); + return; + } + auto shaderName = argv[1]; + + bool found = 0; + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (strcmp(shader.Name, shaderName) == 0) + { + Printf("Shader '%s' uniforms:\n", shaderName); + + decltype(shader.Uniforms)::Iterator it(shader.Uniforms); + decltype(shader.Uniforms)::Pair* pair; + + while (it.NextPair(pair)) + { + double *vec4 = shader.Uniforms[pair->Key].Values; + Printf(" %s : %f %f %f\n", pair->Key.GetChars(), vec4[0], vec4[1], vec4[2]); + } + found = 1; + } + } + if (!found) + Printf("No shader named '%s' found\n", shaderName); +} diff --git a/src/common/rendering/polyrenderer/drawers/poly_thread.cpp b/src/common/rendering/polyrenderer/drawers/poly_thread.cpp index 502705ca5..35566138b 100644 --- a/src/common/rendering/polyrenderer/drawers/poly_thread.cpp +++ b/src/common/rendering/polyrenderer/drawers/poly_thread.cpp @@ -679,7 +679,7 @@ int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *const* verts) // -v.w <= v.x <= v.w // -v.w <= v.y <= v.w // -v.w <= v.z <= v.w - + // halfspace clip distances static const int numclipdistances = 9; #ifdef NO_SSE @@ -799,7 +799,7 @@ int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *const* verts) for (int k = 0; k < 3; k++) output[outputverts * 3 + k] = input[i * 3 + k] * (1.0f - t1) + input[j * 3 + k] * t1; outputverts++; - + if (t2 != 1.0f && t2 > t1) { // add t2 vertex diff --git a/src/common/rendering/polyrenderer/drawers/screen_shader.cpp b/src/common/rendering/polyrenderer/drawers/screen_shader.cpp index 7403a9336..66c4e6ffb 100644 --- a/src/common/rendering/polyrenderer/drawers/screen_shader.cpp +++ b/src/common/rendering/polyrenderer/drawers/screen_shader.cpp @@ -456,7 +456,7 @@ static void GetLightColor(int x0, int x1, PolyTriangleThreadData* thread) uint32_t fogG = (int)((thread->mainVertexShader.Data.uFogColor.g) * 255.0f); uint32_t fogB = (int)((thread->mainVertexShader.Data.uFogColor.b) * 255.0f); float uFogDensity = thread->PushConstants->uFogDensity; - + float* w = thread->scanline.W; for (int x = x0; x < x1; x++) { diff --git a/src/common/rendering/r_thread.cpp b/src/common/rendering/r_thread.cpp index 09ecde78b..552418605 100644 --- a/src/common/rendering/r_thread.cpp +++ b/src/common/rendering/r_thread.cpp @@ -60,7 +60,7 @@ void DrawerThreads::Execute(DrawerCommandQueuePtr commands) { if (!commands || commands->commands.empty()) return; - + auto queue = Instance(); queue->StartThreads(); diff --git a/src/common/rendering/r_thread.h b/src/common/rendering/r_thread.h index f1e49d416..f8db730cd 100644 --- a/src/common/rendering/r_thread.h +++ b/src/common/rendering/r_thread.h @@ -156,17 +156,17 @@ public: static void WaitForWorkers(); static void ResetDebugDrawPos(); - + private: DrawerThreads(); ~DrawerThreads(); - + void StartThreads(); void StopThreads(); void WorkerMain(DrawerThread *thread); static DrawerThreads *Instance(); - + std::mutex threads_mutex; std::vector threads; @@ -182,7 +182,7 @@ private: size_t debug_draw_end = 0; DrawerThread single_core_thread; - + friend class DrawerCommandQueue; }; @@ -192,9 +192,9 @@ class DrawerCommandQueue { public: DrawerCommandQueue(RenderMemory *memoryAllocator); - + void Clear() { commands.clear(); } - + // Queue command to be executed by drawer worker threads template void Push(Types &&... args) @@ -212,13 +212,13 @@ public: command.Execute(&threads->single_core_thread); } } - + private: // Allocate memory valid for the duration of a command execution void *AllocMemory(size_t size); - + std::vector commands; RenderMemory *FrameMemory; - + friend class DrawerThreads; }; diff --git a/src/common/rendering/r_videoscale.cpp b/src/common/rendering/r_videoscale.cpp index f94621e9d..705fe905f 100644 --- a/src/common/rendering/r_videoscale.cpp +++ b/src/common/rendering/r_videoscale.cpp @@ -105,7 +105,6 @@ namespace // minimum set in GZDoom 4.0.0, but only while those fonts are required. static bool lastspecialUI = false; - bool isInActualMenu = false; bool specialUI = (!sysCallbacks.IsSpecialUI || sysCallbacks.IsSpecialUI()); @@ -126,7 +125,7 @@ namespace min_height = VID_MIN_UI_HEIGHT; } } - + // the odd formatting of this struct definition is meant to resemble a table header. set your tab stops to 4 when editing this file. struct v_ScaleTable { bool isValid; uint32_t(*GetScaledWidth)(uint32_t Width, uint32_t Height); uint32_t(*GetScaledHeight)(uint32_t Width, uint32_t Height); float pixelAspect; bool isCustom; }; @@ -179,7 +178,7 @@ bool ViewportLinearScale() aspectmult = 1.f / aspectmult; if ((ViewportScaledWidth(x,y) > (x * aspectmult)) || (ViewportScaledHeight(x,y) > (y * aspectmult))) return true; - + return vid_scale_linear; } diff --git a/src/common/rendering/v_video.cpp b/src/common/rendering/v_video.cpp index 4a8638593..277144aa8 100644 --- a/src/common/rendering/v_video.cpp +++ b/src/common/rendering/v_video.cpp @@ -121,7 +121,6 @@ CUSTOM_CVAR(Int, vid_preferbackend, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_N Printf("Changing the video backend requires a restart for " GAMENAME ".\n"); } -CVAR(Int, vid_renderer, 1, 0) // for some stupid mods which threw caution out of the window... CUSTOM_CVAR(Int, uiscale, 0, CVAR_ARCHIVE | CVAR_NOINITCALL) { @@ -219,13 +218,13 @@ void DCanvas::Resize(int width, int height, bool optimizepitch) { Width = width; Height = height; - + // Making the pitch a power of 2 is very bad for performance // Try to maximize the number of cache lines that can be filled // for each column drawing operation by making the pitch slightly // longer than the width. The values used here are all based on // empirical evidence. - + if (width <= 640 || !optimizepitch) { // For low resolutions, just keep the pitch the same as the width. @@ -337,15 +336,15 @@ void V_InitScreenSize () { const char *i; int width, height, bits; - + width = height = bits = 0; - + if ( (i = Args->CheckValue ("-width")) ) width = atoi (i); - + if ( (i = Args->CheckValue ("-height")) ) height = atoi (i); - + if (width == 0) { if (height == 0) @@ -374,8 +373,6 @@ void V_InitScreen() void V_Init2() { - float gamma = static_cast(screen)->Gamma; - { DFrameBuffer *s = screen; screen = NULL; diff --git a/src/common/rendering/v_video.h b/src/common/rendering/v_video.h index b78afd4b0..e5d79d881 100644 --- a/src/common/rendering/v_video.h +++ b/src/common/rendering/v_video.h @@ -151,7 +151,7 @@ public: int mPipelineNbr = 1; // Number of HW buffers to pipeline int mPipelineType = 0; - + public: DFrameBuffer (int width=1, int height=1); virtual ~DFrameBuffer(); @@ -219,7 +219,7 @@ public: virtual int GetClientWidth() = 0; virtual int GetClientHeight() = 0; virtual void BlurScene(float amount) {} - + // Interface to hardware rendering resources virtual IVertexBuffer *CreateVertexBuffer() { return nullptr; } virtual IIndexBuffer *CreateIndexBuffer() { return nullptr; } diff --git a/src/common/rendering/vulkan/renderer/vk_renderbuffers.cpp b/src/common/rendering/vulkan/renderer/vk_renderbuffers.cpp index 466acd5f4..aa8598805 100644 --- a/src/common/rendering/vulkan/renderer/vk_renderbuffers.cpp +++ b/src/common/rendering/vulkan/renderer/vk_renderbuffers.cpp @@ -255,12 +255,12 @@ void VkRenderBuffers::CreateShadowmap() if (!ShadowmapSampler) { - SamplerBuilder builder; - builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST); - builder.setMinFilter(VK_FILTER_NEAREST); - builder.setMagFilter(VK_FILTER_NEAREST); - builder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); - ShadowmapSampler = builder.create(fb->device); + SamplerBuilder samplerBuilder; + samplerBuilder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST); + samplerBuilder.setMinFilter(VK_FILTER_NEAREST); + samplerBuilder.setMagFilter(VK_FILTER_NEAREST); + samplerBuilder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); + ShadowmapSampler = samplerBuilder.create(fb->device); ShadowmapSampler->SetDebugName("VkRenderBuffers.ShadowmapSampler"); } } diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index df065e1ce..b1994eb2d 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -150,7 +150,7 @@ static const char *shaderBindings = R"( int useVertexData; vec4 uVertexColor; vec4 uVertexNormal; - + vec4 uGlowTopPlane; vec4 uGlowTopColor; vec4 uGlowBottomPlane; diff --git a/src/common/rendering/vulkan/system/vk_device.cpp b/src/common/rendering/vulkan/system/vk_device.cpp index be83d8937..720188096 100644 --- a/src/common/rendering/vulkan/system/vk_device.cpp +++ b/src/common/rendering/vulkan/system/vk_device.cpp @@ -325,20 +325,20 @@ void VulkanDevice::CreateInstance() if (debugLayerFound) { - VkDebugUtilsMessengerCreateInfoEXT createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; - createInfo.messageSeverity = + VkDebugUtilsMessengerCreateInfoEXT dbgCreateInfo = {}; + dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + dbgCreateInfo.messageSeverity = //VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | //VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; - createInfo.messageType = + dbgCreateInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; - createInfo.pfnUserCallback = DebugCallback; - createInfo.pUserData = this; - result = vkCreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger); + dbgCreateInfo.pfnUserCallback = DebugCallback; + dbgCreateInfo.pUserData = this; + result = vkCreateDebugUtilsMessengerEXT(instance, &dbgCreateInfo, nullptr, &debugMessenger); CheckVulkanError(result, "vkCreateDebugUtilsMessengerEXT failed"); DebugLayerActive = true; @@ -347,8 +347,6 @@ void VulkanDevice::CreateInstance() VkBool32 VulkanDevice::DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* callbackData, void* userData) { - VulkanDevice *device = (VulkanDevice*)userData; - static std::mutex mtx; static std::set seenMessages; static int totalMessages; diff --git a/src/common/rendering/vulkan/system/vk_framebuffer.cpp b/src/common/rendering/vulkan/system/vk_framebuffer.cpp index e189f4b24..ee64909b4 100644 --- a/src/common/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/common/rendering/vulkan/system/vk_framebuffer.cpp @@ -57,8 +57,6 @@ #include "engineerrors.h" #include "c_dispatch.h" -void Draw2D(F2DDrawer *drawer, FRenderState &state); - EXTERN_CVAR(Bool, r_drawvoxels) EXTERN_CVAR(Int, gl_tonemap) EXTERN_CVAR(Int, screenblocks) @@ -392,8 +390,8 @@ void VulkanFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) int numLayers = mat->NumLayers(); for (int i = 1; i < numLayers; i++) { - auto systex = static_cast(mat->GetLayer(i, 0, &layer)); - systex->GetImage(layer->layerTexture, 0, layer->scaleFlags); + auto syslayer = static_cast(mat->GetLayer(i, 0, &layer)); + syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags); } } @@ -421,7 +419,6 @@ IDataBuffer *VulkanFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo, bo { auto buffer = new VKDataBuffer(bindingpoint, ssbo, needsresize); - auto fb = GetVulkanFrameBuffer(); switch (bindingpoint) { case LIGHTBUF_BINDINGPOINT: LightBufferSSO = buffer; break; diff --git a/src/common/rendering/vulkan/textures/vk_hwtexture.cpp b/src/common/rendering/vulkan/textures/vk_hwtexture.cpp index b3ad6e66b..83733d6ec 100644 --- a/src/common/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/common/rendering/vulkan/textures/vk_hwtexture.cpp @@ -407,18 +407,18 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) { for (int i = 1; i < numLayers; i++) { - auto systex = static_cast(GetLayer(i, 0, &layer)); - auto systeximage = systex->GetImage(layer->layerTexture, 0, layer->scaleFlags); - update.addCombinedImageSampler(descriptor.get(), i, systeximage->View.get(), sampler, systeximage->Layout); + auto syslayer = static_cast(GetLayer(i, 0, &layer)); + auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags); + update.addCombinedImageSampler(descriptor.get(), i, syslayerimage->View.get(), sampler, syslayerimage->Layout); } } else { for (int i = 1; i < 3; i++) { - auto systex = static_cast(GetLayer(i, translation, &layer)); - auto systeximage = systex->GetImage(layer->layerTexture, 0, layer->scaleFlags); - update.addCombinedImageSampler(descriptor.get(), i, systeximage->View.get(), sampler, systeximage->Layout); + auto syslayer = static_cast(GetLayer(i, translation, &layer)); + auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags); + update.addCombinedImageSampler(descriptor.get(), i, syslayerimage->View.get(), sampler, syslayerimage->Layout); } numLayers = 3; } diff --git a/src/common/rendering/vulkan/textures/vk_samplers.cpp b/src/common/rendering/vulkan/textures/vk_samplers.cpp index adc6dd2b4..06e105aed 100644 --- a/src/common/rendering/vulkan/textures/vk_samplers.cpp +++ b/src/common/rendering/vulkan/textures/vk_samplers.cpp @@ -82,7 +82,7 @@ void VkSamplerManager::SetTextureFilterMode() void VkSamplerManager::Create() { int filter = sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter()? 0 : gl_texture_filter; - + for (int i = CLAMP_NONE; i <= CLAMP_XY; i++) { SamplerBuilder builder; diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 185c79d59..a35ceea27 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -522,10 +522,10 @@ FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos) } else { - PSymbolConstString *csym = dyn_cast(sym); - if (csym != nullptr) + PSymbolConstString *csymbol = dyn_cast(sym); + if (csymbol != nullptr) { - x = new FxConstant(csym->Str, pos); + x = new FxConstant(csymbol->Str, pos); } else { @@ -1964,7 +1964,7 @@ ExpEmit FxUnaryNotBitwise::Emit(VMFunctionBuilder *build) from.Free(build); ExpEmit to(build, REGT_INT); assert(!from.Konst); - + build->Emit(OP_NOT, to.RegNum, from.RegNum, 0); return to; } @@ -2436,7 +2436,7 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build) ExpEmit result; bool intconst = false; - int intconstval; + int intconstval = 0; if (Right->isConstant() && Right->ValueType->GetRegType() == REGT_INT) { @@ -2746,7 +2746,7 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) delete this; return nullptr; } - + if (compileEnvironment.CheckForCustomAddition) { auto result = compileEnvironment.CheckForCustomAddition(this, ctx); @@ -2756,7 +2756,7 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) goto goon; } } - + if (left->ValueType == TypeTextureID && right->IsInteger()) { ValueType = TypeTextureID; @@ -4396,7 +4396,7 @@ ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build) build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 1 : 0); build->Emit(OP_JMP, 1); build->BackpatchListToHere(no); - auto ctarget = build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 0 : 1); + build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 0 : 1); list.DeleteAndClear(); list.ShrinkToFit(); return to; @@ -5125,16 +5125,16 @@ ExpEmit FxNew::Emit(VMFunctionBuilder *build) // Call DecoRandom to generate a random number. VMFunction *callfunc; auto sym = FindBuiltinFunction(compileEnvironment.CustomBuiltinNew != NAME_None? compileEnvironment.CustomBuiltinNew : NAME_BuiltinNew); - + assert(sym); callfunc = sym->Variants[0].Implementation; - + FunctionCallEmitter emitters(callfunc); int outerside = -1; if (!val->isConstant()) { - int outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags); + outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags); if (outerside == FScopeBarrier::Side_Virtual) outerside = FScopeBarrier::SideFromObjectFlags(CallingFunction->OwningClass->ScopeFlags); } @@ -5569,8 +5569,6 @@ FxExpression *FxRandomPick::Resolve(FCompileContext &ctx) ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) { - unsigned i; - assert(choices.Size() > 0); // Call BuiltinRandom to generate a random number. @@ -5603,7 +5601,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) // Allocate space for the jump table. size_t jumptable = build->Emit(OP_JMP, 0); - for (i = 1; i < choices.Size(); ++i) + for (unsigned i = 1; i < choices.Size(); ++i) { build->Emit(OP_JMP, 0); } @@ -5639,7 +5637,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) } } // Backpatch each case (except the last, since it ends here) to jump to here. - for (i = 0; i < choices.Size() - 1; ++i) + for (unsigned i = 0; i < choices.Size() - 1; ++i) { build->BackpatchToHere(finishes[i]); } @@ -5888,7 +5886,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) { PSymbol * sym; FxExpression *newex = nullptr; - + CHECKRESOLVED(); // Local variables have highest priority. @@ -6040,7 +6038,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) deprecationMessage.IsEmpty() ? "" : ", ", deprecationMessage.GetChars()); } } - + newex = new FxGlobalVariable(static_cast(sym), ScriptPosition); goto foundit; @@ -6070,7 +6068,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) newex = new FxCVar(cvar, ScriptPosition); goto foundit; } - + ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); delete this; return nullptr; @@ -6408,7 +6406,7 @@ bool FxLocalVariable::RequestAddress(FCompileContext &ctx, bool *writable) if (writable != nullptr) *writable = !ctx.CheckWritable(Variable->VarFlags); return true; } - + ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) { // 'Out' variables are actually pointers but this fact must be hidden to the script. @@ -6773,7 +6771,7 @@ FxExpression *FxStackVariable::Resolve(FCompileContext &ctx) ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) { int offsetreg = -1; - + if (membervar->Offset != 0) offsetreg = build->GetConstantInt((int)membervar->Offset); if (AddressRequested) @@ -6965,7 +6963,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) { locvar->RegOffset = int(membervar->Offset); } - + locvar->ValueType = membervar->Type; classx = nullptr; delete this; @@ -7247,7 +7245,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) { PArray *arraytype; - + if (arrayispointer) { auto ptr = Array->ValueType->toPointer(); @@ -7269,7 +7267,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) ExpEmit start; ExpEmit bound; bool nestedarray = false; - + if (SizeAddr != ~0u) { bool ismeta = Array->ExprType == EFX_ClassMember && static_cast(Array)->membervar->Flags & VARF_Meta; @@ -7671,7 +7669,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) return x->Resolve(ctx); } } - + if (compileEnvironment.CheckCustomGlobalFunctions) { auto result = compileEnvironment.CheckCustomGlobalFunctions(this, ctx); @@ -7855,8 +7853,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } else if (!ArgList.Size()) { - auto cls = static_cast(ctx.Class)->Descriptor; - ArgList.Push(new FxConstant(cls, NewClassPointer(cls), ScriptPosition)); + auto clss = static_cast(ctx.Class)->Descriptor; + ArgList.Push(new FxConstant(clss, NewClassPointer(clss), ScriptPosition)); } func = new FxNew(ArgList[0]); @@ -8036,7 +8034,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) } // No need to create a dedicated node here, all builtins map directly to trivial operations. Self->ValueType = TypeSInt32; // all builtins treat the texture index as integer. - FxExpression *x; + FxExpression *x = nullptr; switch (MethodName.GetIndex()) { case NAME_IsValid: @@ -8369,8 +8367,8 @@ isresolved: if (!novirtual || !(afd->Variants[0].Flags & VARF_Virtual)) { auto clstype = PType::toClass(ctx.Class); - auto ccls = PType::toClass(cls); - if (clstype == nullptr || ccls == nullptr || !clstype->Descriptor->IsDescendantOf(ccls->Descriptor)) + auto cclss = PType::toClass(cls); + if (clstype == nullptr || cclss == nullptr || !clstype->Descriptor->IsDescendantOf(cclss->Descriptor)) { ScriptPosition.Message(MSG_ERROR, "Cannot call non-static function %s::%s from here", cls->TypeName.GetChars(), MethodName.GetChars()); delete this; @@ -8510,7 +8508,7 @@ VMFunction *FxVMFunctionCall::GetDirectFunction(PFunction *callingfunc, const Ve if (Function->Variants[0].ArgFlags.Size() > imp && !(Function->Variants[0].ArgFlags[imp] & VARF_Optional)) return nullptr; return Function->Variants[0].Implementation; } - + return nullptr; } @@ -8569,7 +8567,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) delete this; return nullptr; } - + bool foundvarargs = false; PType * type = nullptr; int flag = 0; @@ -10511,7 +10509,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) delete this; return nullptr; } - + if (basex->ValueType != TypeName && basex->ValueType != TypeString) { ScriptPosition.Message(MSG_ERROR, "Cannot convert %s to class type", basex->ValueType->DescriptiveName()); @@ -10528,7 +10526,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) { if (Explicit) cls = FindClassType(clsname, ctx); else cls = PClass::FindClass(clsname); - + if (cls == nullptr || cls->VMType == nullptr) { /* lax */ @@ -10763,7 +10761,7 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) { auto sfunc = static_cast(ctx.Function->Variants[0].Implementation); StackOffset = sfunc->AllocExtraStack(ValueType); - + if (Init != nullptr) { ScriptPosition.Message(MSG_ERROR, "Cannot initialize non-scalar variable %s here", Name.GetChars()); @@ -11205,7 +11203,7 @@ ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build) break; } build->Registers[regtype].Return(regNum, 1); - + emitval.Free(build); } else diff --git a/src/common/scripting/backend/codegen.h b/src/common/scripting/backend/codegen.h index ac5f058ab..43fb7f061 100644 --- a/src/common/scripting/backend/codegen.h +++ b/src/common/scripting/backend/codegen.h @@ -206,7 +206,7 @@ struct ExpVal int regtype = Type->GetRegType(); return regtype == REGT_INT ? !!Int : regtype == REGT_FLOAT ? Float!=0. : false; } - + FName GetName() const { if (Type == TypeString) @@ -325,7 +325,7 @@ protected: public: virtual ~FxExpression() {} virtual FxExpression *Resolve(FCompileContext &ctx); - + virtual bool isConstant() const; virtual bool RequestAddress(FCompileContext &ctx, bool *writable); virtual PPrototype *ReturnProto(); @@ -525,7 +525,7 @@ public: } ValueType = value.Type = type; } - + static FxExpression *MakeConstant(PSymbol *sym, const FScriptPosition &pos); bool isConstant() const @@ -1864,7 +1864,7 @@ protected: : FxExpression(etype, pos) { } - + void Backpatch(VMFunctionBuilder *build, size_t loopstart, size_t loopend); FxExpression *Resolve(FCompileContext&) final; virtual FxExpression *DoResolve(FCompileContext&) = 0; diff --git a/src/common/scripting/backend/vmbuilder.cpp b/src/common/scripting/backend/vmbuilder.cpp index 4c1401e8e..1624aa42f 100644 --- a/src/common/scripting/backend/vmbuilder.cpp +++ b/src/common/scripting/backend/vmbuilder.cpp @@ -398,7 +398,7 @@ int VMFunctionBuilder::RegAvailability::Get(int count) { return -1; } - + mask = count == 32 ? ~0u : (1 << count) - 1; for (i = 0; i < 256 / 32; ++i) diff --git a/src/common/scripting/core/dynarrays.cpp b/src/common/scripting/core/dynarrays.cpp index 21a362248..8c51daa94 100644 --- a/src/common/scripting/core/dynarrays.cpp +++ b/src/common/scripting/core/dynarrays.cpp @@ -114,7 +114,7 @@ template void ArrayResize(T *self, int amount) { // This must ensure that all new entries get cleared. const int fillCount = int(self->Size() - oldSize); - if (fillCount > 0) memset(&(*self)[oldSize], 0, sizeof(*self)[0] * fillCount); + if (fillCount > 0) memset((void*)&(*self)[oldSize], 0, sizeof(*self)[0] * fillCount); } } @@ -130,7 +130,7 @@ template<> unsigned int ArrayReserve(TArray *self, int amount) if (fillCount > 0) memset(&(*self)[oldSize], 0, sizeof(DObject*) * fillCount); - + return oldSize; } diff --git a/src/common/scripting/core/scopebarrier.h b/src/common/scripting/core/scopebarrier.h index fb931d223..b5eeae78f 100644 --- a/src/common/scripting/core/scopebarrier.h +++ b/src/common/scripting/core/scopebarrier.h @@ -46,7 +46,7 @@ struct FScopeBarrier // static int FlagsFromSide(int side); static EScopeFlags ObjectFlagsFromSide(int side); - + // used for errors static const char* StringFromSide(int side); diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp index 3fb97cb32..c98cc7435 100644 --- a/src/common/scripting/core/types.cpp +++ b/src/common/scripting/core/types.cpp @@ -410,7 +410,7 @@ bool PContainerType::IsMatch(intptr_t id1, intptr_t id2) const { const PTypeBase *outer = (const PTypeBase *)id1; FName name = (ENamedName)(intptr_t)id2; - + return Outer == outer && TypeName == name; } diff --git a/src/common/scripting/core/vmdisasm.cpp b/src/common/scripting/core/vmdisasm.cpp index 0f68b3a1d..ae9078e62 100644 --- a/src/common/scripting/core/vmdisasm.cpp +++ b/src/common/scripting/core/vmdisasm.cpp @@ -265,7 +265,7 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func) void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction *func) { - VMFunction *callfunc; + VMFunction *callfunc = nullptr; const char *name; int col; int mode; @@ -526,7 +526,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction { printf_wrapper(out, ",%d\n", code[++i].i24); } - else if (code[i].op == OP_CALL_K) + else if (code[i].op == OP_CALL_K && callfunc) { printf_wrapper(out, " [%s]\n", callfunc->PrintableName.GetChars()); } @@ -665,7 +665,6 @@ static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const default: return col+printf_wrapper(out, "$%d", arg); } - return col; } //========================================================================== diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index 07c4fe346..8fc0bbe24 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -475,7 +475,7 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, if (ast.TopNode != NULL) { ZCC_TreeNode *node = ast.TopNode; - PSymbolTreeNode *tnode; + PSymbolTreeNode *tnode = nullptr; // [pbeta] Anything that must be processed before classes, structs, etc. should go here. do @@ -606,7 +606,6 @@ PSymbolTreeNode *ZCCCompiler::AddTreeNode(FName name, ZCC_TreeNode *node, PSymbo else { auto sy = Create(name, node); - FString name; treenodes->AddSymbol(sy); return sy; } @@ -1070,7 +1069,7 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) auto def = constant.node; auto val = def->Value; ExpVal &c = constant.constval; - + // This is for literal constants. if (val->NodeType == AST_ExprConstant) { @@ -1365,7 +1364,7 @@ void ZCCCompiler::CompileAllFields() for (unsigned i = 0; i < Classes.Size(); i++) { auto type = Classes[i]->ClassType(); - + if (type->Size == TentativeClass) { if (type->ParentClass->Size == TentativeClass) @@ -1529,7 +1528,7 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArrayFindSymbol(type->UserType->Id, true); if (sym == nullptr) sym = OutNamespace->Symbols.FindSymbol(type->UserType->Id, true); @@ -1930,19 +1929,19 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, if (mVersion >= MakeVersion(3, 7, 2)) { TArray fixedIndices; - for (auto node : indices) + for (auto index : indices) { - fixedIndices.Insert (0, node); + fixedIndices.Insert (0, index); } indices = std::move(fixedIndices); } FCompileContext ctx(OutNamespace, cls, false); - for (auto node : indices) + for (auto index : indices) { // There is no float->int casting here. - FxExpression *ex = ConvertNode(node); + FxExpression *ex = ConvertNode(index); ex = ex->Resolve(ctx); if (ex == nullptr) return TypeError; @@ -2245,7 +2244,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool flags |= VARF_Optional; hasoptionals = true; - + if ((varflags & VARF_Override) && !overridemsg) { // This is illegal, but in older compilers wasn't checked, so there it has to be demoted to a warning. @@ -2425,17 +2424,17 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool auto parentfunc = clstype->ParentClass? dyn_cast(clstype->ParentClass->VMType->Symbols.FindSymbol(sym->SymbolName, true)) : nullptr; - int vindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], parentfunc, exactReturnType); + int virtindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], parentfunc, exactReturnType); // specifying 'override' is necessary to prevent one of the biggest problem spots with virtual inheritance: Mismatching argument types. if (varflags & VARF_Override) { - if (vindex == -1) + if (virtindex == -1) { Error(f, "Attempt to override non-existent virtual function %s", FName(f->Name).GetChars()); } else { - auto oldfunc = clstype->Virtuals[vindex]; + auto oldfunc = clstype->Virtuals[virtindex]; if (parentfunc && parentfunc->mVersion > mVersion) { Error(f, "Attempt to override function %s which is incompatible with version %d.%d.%d", FName(f->Name).GetChars(), mVersion.major, mVersion.minor, mVersion.revision); @@ -2466,11 +2465,11 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool sym->Variants[0].Flags |= VARF_ReadOnly; if (oldfunc->VarFlags & VARF_Protected) sym->Variants[0].Flags |= VARF_Protected; - - clstype->Virtuals[vindex] = sym->Variants[0].Implementation; - sym->Variants[0].Implementation->VirtualIndex = vindex; + + clstype->Virtuals[virtindex] = sym->Variants[0].Implementation; + sym->Variants[0].Implementation->VirtualIndex = virtindex; sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags; - + // Defaults must be identical to parent class if (parentfunc->Variants[0].Implementation->DefaultArgs.Size() > 0) { @@ -2493,7 +2492,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool } else { - if (vindex != -1) + if (virtindex != -1) { Error(f, "Function %s attempts to override parent function without 'override' qualifier", FName(f->Name).GetChars()); } @@ -2507,8 +2506,8 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool } else if (forclass) { - int vindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], nullptr, exactReturnType); - if (vindex != -1) + int virtindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], nullptr, exactReturnType); + if (virtindex != -1) { Error(f, "Function %s attempts to override parent function without 'override' qualifier", FName(f->Name).GetChars()); } @@ -3113,7 +3112,7 @@ FxExpression *ZCCCompiler::ConvertImplicitScopeNode(ZCC_TreeNode *node, ZCC_Stat { return nullptr; } - + FxExpression *nestedExpr = ConvertNode(nested); assert(nullptr != nestedExpr); diff --git a/src/common/scripting/frontend/zcc_compile.h b/src/common/scripting/frontend/zcc_compile.h index ca19d8aff..ca1beb3f2 100644 --- a/src/common/scripting/frontend/zcc_compile.h +++ b/src/common/scripting/frontend/zcc_compile.h @@ -140,7 +140,7 @@ protected: void InitFunctions(); virtual void InitDefaults(); - + TArray Constants; TArray Structs; TArray Classes; diff --git a/src/common/scripting/frontend/zcc_parser.cpp b/src/common/scripting/frontend/zcc_parser.cpp index 0d1928653..1ac9342aa 100644 --- a/src/common/scripting/frontend/zcc_parser.cpp +++ b/src/common/scripting/frontend/zcc_parser.cpp @@ -1267,7 +1267,7 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c break; } - + case AST_ClassCast: { TreeNodeDeepCopy_Start(ClassCast); diff --git a/src/common/scripting/jit/jit_call.cpp b/src/common/scripting/jit/jit_call.cpp index ee35fc139..83808c0ed 100644 --- a/src/common/scripting/jit/jit_call.cpp +++ b/src/common/scripting/jit/jit_call.cpp @@ -340,7 +340,7 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target) I_Error("Unexpected register type for self pointer\n"); break; } - + cc.test(*reg, *reg); cc.jz(label); } diff --git a/src/common/scripting/jit/jit_flow.cpp b/src/common/scripting/jit/jit_flow.cpp index 8439481cf..6157bf340 100644 --- a/src/common/scripting/jit/jit_flow.cpp +++ b/src/common/scripting/jit/jit_flow.cpp @@ -7,7 +7,7 @@ void JitCompiler::EmitTEST() cc.cmp(regD[A], BC); cc.jne(GetLabel(i + 2)); } - + void JitCompiler::EmitTESTN() { int bc = BC; diff --git a/src/common/scripting/jit/jit_math.cpp b/src/common/scripting/jit/jit_math.cpp index d2fb45c7d..ea9402594 100644 --- a/src/common/scripting/jit/jit_math.cpp +++ b/src/common/scripting/jit/jit_math.cpp @@ -902,7 +902,7 @@ void JitCompiler::EmitMINF_RK() cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp)); cc.minpd(regF[A], rb); // minsd requires SSE 4.1 } - + void JitCompiler::EmitMAXF_RR() { auto rc = CheckRegF(C, A); @@ -919,7 +919,7 @@ void JitCompiler::EmitMAXF_RK() cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp)); cc.maxpd(regF[A], rb); // maxsd requires SSE 4.1 } - + void JitCompiler::EmitATAN2() { auto result = newResultXmmSd(); @@ -1441,7 +1441,7 @@ void JitCompiler::EmitEQV3_R() EmitVectorComparison<3> (check, fail, success); }); } - + void JitCompiler::EmitEQV3_K() { I_Error("EQV3_K is not used."); diff --git a/src/common/scripting/jit/jit_runtime.cpp b/src/common/scripting/jit/jit_runtime.cpp index a646ebf9b..647647442 100644 --- a/src/common/scripting/jit/jit_runtime.cpp +++ b/src/common/scripting/jit/jit_runtime.cpp @@ -403,7 +403,7 @@ static void WriteCIE(TArray &stream, const TArray &cieInstruct unsigned int lengthPos = stream.Size(); WriteUInt32(stream, 0); // Length WriteUInt32(stream, 0); // CIE ID - + WriteUInt8(stream, 1); // CIE Version WriteUInt8(stream, 'z'); WriteUInt8(stream, 'R'); // fde encoding @@ -428,7 +428,7 @@ static void WriteFDE(TArray &stream, const TArray &fdeInstruct WriteUInt32(stream, 0); // Length uint32_t offsetToCIE = stream.Size() - cieLocation; WriteUInt32(stream, offsetToCIE); - + functionStart = stream.Size(); WriteUInt64(stream, 0); // func start WriteUInt64(stream, 0); // func size @@ -499,7 +499,7 @@ static TArray CreateUnwindInfoUnix(asmjit::CCFunc *func, unsigned int & // // The CFI_Parser::decodeFDE parser on the other side.. // https://github.com/llvm-mirror/libunwind/blob/master/src/DwarfParser.hpp - + // Asmjit -> DWARF register id int dwarfRegId[16]; dwarfRegId[X86Gp::kIdAx] = 0; @@ -520,7 +520,7 @@ static TArray CreateUnwindInfoUnix(asmjit::CCFunc *func, unsigned int & dwarfRegId[X86Gp::kIdR15] = 15; int dwarfRegRAId = 16; int dwarfRegXmmId = 17; - + TArray cieInstructions; TArray fdeInstructions; @@ -529,7 +529,7 @@ static TArray CreateUnwindInfoUnix(asmjit::CCFunc *func, unsigned int & WriteDefineCFA(cieInstructions, dwarfRegId[X86Gp::kIdSp], stackOffset); WriteRegisterStackLocation(cieInstructions, returnAddressReg, stackOffset); - + FuncFrameLayout layout; Error error = layout.init(func->getDetail(), func->getFrameInfo()); if (error != kErrorOk) @@ -702,7 +702,7 @@ void *AddJitFunction(asmjit::CodeHolder* code, JitCompiler *compiler) uint64_t length64 = *((uint64_t *)(entry + 4)); if (length64 == 0) break; - + uint64_t offset = *((uint64_t *)(entry + 12)); if (offset != 0) { @@ -831,10 +831,10 @@ public: if (result) { IMAGEHLP_LINE64 line64; - DWORD displacement = 0; + DWORD displacement1 = 0; memset(&line64, 0, sizeof(IMAGEHLP_LINE64)); line64.SizeOfStruct = sizeof(IMAGEHLP_LINE64); - result = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)frame, &displacement, &line64); + result = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)frame, &displacement1, &line64); if (result) { s.Format("Called from %s at %s, line %d\n", symbol64->Name, line64.FileName, (int)line64.LineNumber); diff --git a/src/common/scripting/vm/vmexec.h b/src/common/scripting/vm/vmexec.h index defbcdf6d..a4d666dcc 100644 --- a/src/common/scripting/vm/vmexec.h +++ b/src/common/scripting/vm/vmexec.h @@ -515,7 +515,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) DoCast(reg, f, a, B, C); } NEXTOP; - + OP(CASTB): if (C == CASTB_I) { @@ -538,7 +538,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) reg.d[a] = reg.s[B].Len() > 0; } NEXTOP; - + OP(TEST): ASSERTD(a); if (reg.d[a] != BC) @@ -692,7 +692,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) { VMFunction *call = (VMFunction *)ptr; VMReturn returns[MAX_RETURNS]; - int numret; + int numret1; b = B; FillReturns(reg, f, returns, pc+1, C); @@ -701,7 +701,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) try { VMCycles[0].Unclock(); - numret = static_cast(call)->NativeCall(VM_INVOKE(reg.param + f->NumParam - b, b, returns, C, call->RegTypes)); + numret1 = static_cast(call)->NativeCall(VM_INVOKE(reg.param + f->NumParam - b, b, returns, C, call->RegTypes)); VMCycles[0].Clock(); } catch (CVMAbortException &err) @@ -714,10 +714,10 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) } else { - auto sfunc = static_cast(call); - numret = sfunc->ScriptCall(sfunc, reg.param + f->NumParam - b, b, returns, C); + auto sfunc1 = static_cast(call); + numret1 = sfunc1->ScriptCall(sfunc1, reg.param + f->NumParam - b, b, returns, C); } - assert(numret == C && "Number of parameters returned differs from what was expected by the caller"); + assert(numret1 == C && "Number of parameters returned differs from what was expected by the caller"); f->NumParam -= B; pc += C; // Skip RESULTs } @@ -852,37 +852,37 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) ASSERTD(a); ASSERTS(B); reg.d[a] = (int)reg.s[B].Len(); NEXTOP; - + OP(CMPS): // String comparison is a fairly expensive operation, so I've // chosen to conserve a few opcodes by condensing all the // string comparisons into a single one. { - const FString *b, *c; + const FString *b1, *c1; int test, method; bool cmp; if (a & CMP_BK) { ASSERTKS(B); - b = &konsts[B]; + b1 = &konsts[B]; } else { ASSERTS(B); - b = ®.s[B]; + b1 = ®.s[B]; } if (a & CMP_CK) { ASSERTKS(C); - c = &konsts[C]; + c1 = &konsts[C]; } else { ASSERTS(C); - c = ®.s[C]; + c1 = ®.s[C]; } - test = (a & CMP_APPROX) ? b->CompareNoCase(*c) : b->Compare(*c); + test = (a & CMP_APPROX) ? b1->CompareNoCase(*c1) : b1->Compare(*c1); method = a & CMP_METHOD_MASK; if (method == CMP_EQ) { @@ -1302,12 +1302,10 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) ASSERTF(a); ASSERTF(B); ASSERTKF(C); fb = reg.f[B]; fc = konstf[C]; goto Do_MODF; - NEXTOP; OP(MODF_KR): ASSERTF(a); ASSERTKF(B); ASSERTF(C); fb = konstf[B]; fc = reg.f[C]; goto Do_MODF; - NEXTOP; OP(POWF_RR): ASSERTF(a); ASSERTF(B); ASSERTF(C); @@ -1349,7 +1347,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) fb = reg.f[B]; reg.f[a] = (C == FLOP_ABS) ? fabs(fb) : (C == FLOP_NEG) ? -fb : DoFLOP(C, fb); NEXTOP; - + OP(EQF_R): ASSERTF(B); ASSERTF(C); if (a & CMP_APPROX) @@ -1712,7 +1710,6 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) // PrintParameters(reg.param + f->NumParam - B, B); throw; } - return 0; } static double DoFLOP(int flop, double v) diff --git a/src/common/scripting/vm/vmframe.cpp b/src/common/scripting/vm/vmframe.cpp index 1fc82549d..6cb03be43 100644 --- a/src/common/scripting/vm/vmframe.cpp +++ b/src/common/scripting/vm/vmframe.cpp @@ -694,7 +694,6 @@ void ThrowAbortException(EVMAbortException reason, const char *moreinfo, ...) va_list ap; va_start(ap, moreinfo); throw CVMAbortException(reason, moreinfo, ap); - va_end(ap); } void ThrowAbortException(VMScriptFunction *sfunc, VMOP *line, EVMAbortException reason, const char *moreinfo, ...) @@ -706,7 +705,6 @@ void ThrowAbortException(VMScriptFunction *sfunc, VMOP *line, EVMAbortException err.stacktrace.AppendFormat("Called from %s at %s, line %d\n", sfunc->PrintableName.GetChars(), sfunc->SourceFileName.GetChars(), sfunc->PCToLine(line)); throw err; - va_end(ap); } DEFINE_ACTION_FUNCTION(DObject, ThrowAbortException) diff --git a/src/common/statusbar/base_sbar.cpp b/src/common/statusbar/base_sbar.cpp index 9ea4a6d26..53d4c03b4 100644 --- a/src/common/statusbar/base_sbar.cpp +++ b/src/common/statusbar/base_sbar.cpp @@ -467,7 +467,7 @@ void DStatusBarCore::DrawGraphic(FGameTexture* tex, double x, double y, int flag double texheight = tex->GetDisplayHeight() * scaleY; double texleftoffs = tex->GetDisplayLeftOffset() * scaleY; double textopoffs = tex->GetDisplayTopOffset() * scaleY; - double boxleftoffs, boxtopoffs; + double boxleftoffs = 0, boxtopoffs = 0; if (boxwidth > 0 || boxheight > 0) { @@ -618,8 +618,6 @@ void DStatusBarCore::DrawRotated(FGameTexture* tex, double x, double y, int flag { double texwidth = tex->GetDisplayWidth() * scaleX; double texheight = tex->GetDisplayHeight() * scaleY; - double texleftoffs = tex->GetDisplayLeftOffset() * scaleY; - double textopoffs = tex->GetDisplayTopOffset() * scaleY; // resolve auto-alignment before making any adjustments to the position values. if (!(flags & DI_SCREEN_MANUAL_ALIGN)) diff --git a/src/common/statusbar/base_sbar.h b/src/common/statusbar/base_sbar.h index 9b1204412..972cbf0df 100644 --- a/src/common/statusbar/base_sbar.h +++ b/src/common/statusbar/base_sbar.h @@ -131,7 +131,7 @@ class DStatusBarCore : public DObject DECLARE_CLASS(DStatusBarCore, DObject) protected: - + public: diff --git a/src/common/textures/animlib.cpp b/src/common/textures/animlib.cpp index c712ae2bf..e42386bd9 100644 --- a/src/common/textures/animlib.cpp +++ b/src/common/textures/animlib.cpp @@ -44,38 +44,38 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) static inline uint16_t findpage(anim_t *anim, uint16_t framenumber) { - // curlpnum is initialized to 0xffff, obviously - size_t i = anim->curlpnum & ~0xffff; - size_t const nLps = anim->lpheader->nLps; - bool j = true; + // curlpnum is initialized to 0xffff, obviously + size_t i = anim->curlpnum & ~0xffff; + size_t const nLps = anim->lpheader->nLps; + bool j = true; - if (framenumber < anim->currentframe) - i = 0, j = false; + if (framenumber < anim->currentframe) + i = 0, j = false; - // this scans the last used page and higher first and then scans the - // previously accessed pages afterwards if it doesn't find anything - do - { - for (; i < nLps; ++i) - { - lp_descriptor & lp = anim->LpArray[i]; - if (lp.baseRecord <= framenumber && framenumber < lp.baseRecord + lp.nRecords) - return (uint16_t)i; - } + // this scans the last used page and higher first and then scans the + // previously accessed pages afterwards if it doesn't find anything + do + { + for (; i < nLps; ++i) + { + lp_descriptor & lp = anim->LpArray[i]; + if (lp.baseRecord <= framenumber && framenumber < lp.baseRecord + lp.nRecords) + return (uint16_t)i; + } - if (j && i == nLps) - { - // handle out of order pages... I don't think any Duke .ANM files - // have them, but they're part of the file spec - i = 0, j = false; - continue; - } + if (j && i == nLps) + { + // handle out of order pages... I don't think any Duke .ANM files + // have them, but they're part of the file spec + i = 0, j = false; + continue; + } - break; - } - while (1); + break; + } + while (1); - return (uint16_t)i; + return (uint16_t)i; } @@ -88,13 +88,13 @@ static inline uint16_t findpage(anim_t *anim, uint16_t framenumber) static inline void loadpage(anim_t *anim, uint16_t pagenumber, uint16_t **pagepointer) { - if (anim->curlpnum == pagenumber) - return; + if (anim->curlpnum == pagenumber) + return; - anim->curlpnum = pagenumber; - anim->curlp = &anim->LpArray[pagenumber]; - *pagepointer = (uint16_t *)(anim->buffer + 0xb00 + (pagenumber*IMAGEBUFFERSIZE) + - sizeof(lp_descriptor) + sizeof(uint16_t)); + anim->curlpnum = pagenumber; + anim->curlp = &anim->LpArray[pagenumber]; + *pagepointer = (uint16_t *)(anim->buffer + 0xb00 + (pagenumber*IMAGEBUFFERSIZE) + + sizeof(lp_descriptor) + sizeof(uint16_t)); } @@ -114,63 +114,63 @@ static inline void loadpage(anim_t *anim, uint16_t pagenumber, uint16_t **pagepo static void decodeframe(uint8_t * srcP, uint8_t * dstP) { - do - { - { - /* short op */ - uint8_t count = *srcP++; + do + { + { + /* short op */ + uint8_t count = *srcP++; - if (!count) /* short RLE */ - { - uint8_t color = *(srcP+1); - count = *(uint8_t *)srcP; - srcP += sizeof(int16_t); - memset(dstP, color, count); - dstP += count; - continue; - } - else if ((count & 0x80) == 0) /* short copy */ - { - memcpy(dstP, srcP, count); - dstP += count; - srcP += count; - continue; - } - else if ((count &= ~0x80) > 0) /* short skip */ - { - dstP += count; - continue; - } - } + if (!count) /* short RLE */ + { + uint8_t color = *(srcP+1); + count = *(uint8_t *)srcP; + srcP += sizeof(int16_t); + memset(dstP, color, count); + dstP += count; + continue; + } + else if ((count & 0x80) == 0) /* short copy */ + { + memcpy(dstP, srcP, count); + dstP += count; + srcP += count; + continue; + } + else if ((count &= ~0x80) > 0) /* short skip */ + { + dstP += count; + continue; + } + } - { - /* long op */ - uint16_t count = LittleShort((uint16_t)GetShort(srcP)); - srcP += sizeof(int16_t); + { + /* long op */ + uint16_t count = LittleShort((uint16_t)GetShort(srcP)); + srcP += sizeof(int16_t); - if (!count) /* stop sign */ - return; - else if ((count & 0x8000) == 0) /* long skip */ - { - dstP += count; - continue; - } - else if ((count &= ~0x8000) & 0x4000) /* long RLE */ - { - uint8_t color = *srcP++; - count &= ~0x4000; - memset(dstP, color, count); - dstP += count; - continue; - } + if (!count) /* stop sign */ + return; + else if ((count & 0x8000) == 0) /* long skip */ + { + dstP += count; + continue; + } + else if ((count &= ~0x8000) & 0x4000) /* long RLE */ + { + uint8_t color = *srcP++; + count &= ~0x4000; + memset(dstP, color, count); + dstP += count; + continue; + } - /* long copy */ - memcpy(dstP, srcP, count); - dstP += count; - srcP += count; - } - } - while (1); + /* long copy */ + memcpy(dstP, srcP, count); + dstP += count; + srcP += count; + } + } + while (1); } @@ -183,23 +183,23 @@ static void decodeframe(uint8_t * srcP, uint8_t * dstP) static void renderframe(anim_t *anim, uint16_t framenumber, uint16_t *pagepointer) { - uint16_t offset = 0; - uint16_t frame = framenumber - anim->curlp->baseRecord; + uint16_t offset = 0; + uint16_t frame = framenumber - anim->curlp->baseRecord; - while (frame--) offset += LittleShort(pagepointer[frame]); + while (frame--) offset += LittleShort(pagepointer[frame]); if (offset >= anim->curlp->nBytes) return; - uint8_t *ppointer = (uint8_t *)(pagepointer) + anim->curlp->nRecords*2 + offset + 4; + uint8_t *ppointer = (uint8_t *)(pagepointer) + anim->curlp->nRecords*2 + offset + 4; - if ((ppointer-4)[1]) - { - uint16_t const temp = LittleShort(((uint16_t *)(ppointer-4))[1]); - ppointer += temp + (temp & 1); - } + if ((ppointer-4)[1]) + { + uint16_t const temp = LittleShort(((uint16_t *)(ppointer-4))[1]); + ppointer += temp + (temp & 1); + } - decodeframe((uint8_t *)ppointer, (uint8_t *)anim->imagebuffer); + decodeframe((uint8_t *)ppointer, (uint8_t *)anim->imagebuffer); } @@ -212,79 +212,79 @@ static void renderframe(anim_t *anim, uint16_t framenumber, uint16_t *pagepointe static inline void drawframe(anim_t *anim, uint16_t framenumber) { - loadpage(anim, findpage(anim, framenumber), &anim->thepage); - renderframe(anim, framenumber, anim->thepage); + loadpage(anim, findpage(anim, framenumber), &anim->thepage); + renderframe(anim, framenumber, anim->thepage); } // is the file size, for consistency checking. int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, int32_t length) { - if (memcmp(buffer, "LPF ", 4)) return -1; + if (memcmp(buffer, "LPF ", 4)) return -1; - length -= sizeof(lpfileheader)+128+768; - if (length < 0) - return -1; + length -= sizeof(lpfileheader)+128+768; + if (length < 0) + return -1; - anim->curlpnum = 0xffff; - anim->currentframe = -1; + anim->curlpnum = 0xffff; + anim->currentframe = -1; - // this just modifies the data in-place instead of copying it elsewhere now - lpfileheader & lpheader = *(anim->lpheader = (lpfileheader *)(anim->buffer = buffer)); + // this just modifies the data in-place instead of copying it elsewhere now + lpfileheader & lpheader = *(anim->lpheader = (lpfileheader *)(anim->buffer = buffer)); - lpheader.id = LittleLong(lpheader.id); - lpheader.maxLps = LittleShort(lpheader.maxLps); - lpheader.nLps = LittleShort(lpheader.nLps); - lpheader.nRecords = LittleLong(lpheader.nRecords); - lpheader.maxRecsPerLp = LittleShort(lpheader.maxRecsPerLp); - lpheader.lpfTableOffset = LittleShort(lpheader.lpfTableOffset); - lpheader.contentType = LittleLong(lpheader.contentType); - lpheader.width = LittleShort(lpheader.width); - lpheader.height = LittleShort(lpheader.height); - lpheader.nFrames = LittleLong(lpheader.nFrames); - lpheader.framesPerSecond = LittleShort(lpheader.framesPerSecond); + lpheader.id = LittleLong(lpheader.id); + lpheader.maxLps = LittleShort(lpheader.maxLps); + lpheader.nLps = LittleShort(lpheader.nLps); + lpheader.nRecords = LittleLong(lpheader.nRecords); + lpheader.maxRecsPerLp = LittleShort(lpheader.maxRecsPerLp); + lpheader.lpfTableOffset = LittleShort(lpheader.lpfTableOffset); + lpheader.contentType = LittleLong(lpheader.contentType); + lpheader.width = LittleShort(lpheader.width); + lpheader.height = LittleShort(lpheader.height); + lpheader.nFrames = LittleLong(lpheader.nFrames); + lpheader.framesPerSecond = LittleShort(lpheader.framesPerSecond); - length -= lpheader.nLps * sizeof(lp_descriptor); - if (length < 0) - return -2; + length -= lpheader.nLps * sizeof(lp_descriptor); + if (length < 0) + return -2; - buffer += sizeof(lpfileheader)+128; + buffer += sizeof(lpfileheader)+128; - // load the color palette - for (uint8_t * pal = anim->pal, * pal_end = pal+768; pal < pal_end; pal += 3, buffer += 4) - { - pal[2] = buffer[0]; - pal[1] = buffer[1]; - pal[0] = buffer[2]; - } + // load the color palette + for (uint8_t * pal = anim->pal, * pal_end = pal+768; pal < pal_end; pal += 3, buffer += 4) + { + pal[2] = buffer[0]; + pal[1] = buffer[1]; + pal[0] = buffer[2]; + } - // set up large page descriptors - anim->LpArray = (lp_descriptor *)buffer; + // set up large page descriptors + anim->LpArray = (lp_descriptor *)buffer; - // theoretically we should be able to play files with more than 256 frames now - // assuming the utilities to create them can make them that way - for (lp_descriptor * lp = anim->LpArray, * lp_end = lp+lpheader.nLps; lp < lp_end; ++lp) - { - lp->baseRecord = LittleShort(lp->baseRecord); - lp->nRecords = LittleShort(lp->nRecords); - lp->nBytes = LittleShort(lp->nBytes); - } - return ANIM_NumFrames(anim) <= 0 ? -1 : 0; + // theoretically we should be able to play files with more than 256 frames now + // assuming the utilities to create them can make them that way + for (lp_descriptor * lp = anim->LpArray, * lp_end = lp+lpheader.nLps; lp < lp_end; ++lp) + { + lp->baseRecord = LittleShort(lp->baseRecord); + lp->nRecords = LittleShort(lp->nRecords); + lp->nBytes = LittleShort(lp->nBytes); + } + return ANIM_NumFrames(anim) <= 0 ? -1 : 0; } uint8_t * ANIM_DrawFrame(anim_t *anim, int32_t framenumber) { - uint32_t cnt = anim->currentframe; + uint32_t cnt = anim->currentframe; - // handle first play and looping or rewinding - if (cnt > (uint32_t)framenumber) - cnt = 0; + // handle first play and looping or rewinding + if (cnt > (uint32_t)framenumber) + cnt = 0; - do drawframe(anim, cnt++); - while (cnt < (uint32_t)framenumber); + do drawframe(anim, cnt++); + while (cnt < (uint32_t)framenumber); - anim->currentframe = framenumber; - return anim->imagebuffer; + anim->currentframe = framenumber; + return anim->imagebuffer; } diff --git a/src/common/textures/animlib.h b/src/common/textures/animlib.h index dd9415aa4..23d0d89da 100644 --- a/src/common/textures/animlib.h +++ b/src/common/textures/animlib.h @@ -45,37 +45,37 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) struct lpfileheader { - uint32_t id; /* 4 uint8_tacter ID == "LPF " */ - uint16_t maxLps; /* max # largePages allowed. 256 FOR NOW. */ - uint16_t nLps; /* # largePages in this file. */ - uint32_t nRecords; /* # records in this file. 65534 is current limit + ring */ - uint16_t maxRecsPerLp; /* # records permitted in an lp. 256 FOR NOW. */ - uint16_t lpfTableOffset; /* Absolute Seek position of lpfTable. 1280 FOR NOW. */ - uint32_t contentType; /* 4 character ID == "ANIM" */ - uint16_t width; /* Width of screen in pixels. */ - uint16_t height; /* Height of screen in pixels. */ - uint8_t variant; /* 0==ANIM. */ - uint8_t version; /* 0==frame rate in 18/sec, 1= 70/sec */ - uint8_t hasLastDelta; /* 1==Last record is a delta from last-to-first frame. */ - uint8_t lastDeltaValid; /* 0==Ignore ring frame. */ - uint8_t pixelType; /* 0==256 color. */ - uint8_t CompressionType; /* 1==(RunSkipDump) Only one used FOR NOW. */ - uint8_t otherRecsPerFrm; /* 0 FOR NOW. */ - uint8_t bitmaptype; /* 1==320x200, 256-color. Only one implemented so far. */ - uint8_t recordTypes[32]; /* Not yet implemented. */ - uint32_t nFrames; /* Number of actual frames in the file, includes ring frame. */ - uint16_t framesPerSecond; /* Number of frames to play per second. */ - uint16_t pad2[29]; /* 58 bytes of filler to round up to 128 bytes total. */ + uint32_t id; /* 4 uint8_tacter ID == "LPF " */ + uint16_t maxLps; /* max # largePages allowed. 256 FOR NOW. */ + uint16_t nLps; /* # largePages in this file. */ + uint32_t nRecords; /* # records in this file. 65534 is current limit + ring */ + uint16_t maxRecsPerLp; /* # records permitted in an lp. 256 FOR NOW. */ + uint16_t lpfTableOffset; /* Absolute Seek position of lpfTable. 1280 FOR NOW. */ + uint32_t contentType; /* 4 character ID == "ANIM" */ + uint16_t width; /* Width of screen in pixels. */ + uint16_t height; /* Height of screen in pixels. */ + uint8_t variant; /* 0==ANIM. */ + uint8_t version; /* 0==frame rate in 18/sec, 1= 70/sec */ + uint8_t hasLastDelta; /* 1==Last record is a delta from last-to-first frame. */ + uint8_t lastDeltaValid; /* 0==Ignore ring frame. */ + uint8_t pixelType; /* 0==256 color. */ + uint8_t CompressionType; /* 1==(RunSkipDump) Only one used FOR NOW. */ + uint8_t otherRecsPerFrm; /* 0 FOR NOW. */ + uint8_t bitmaptype; /* 1==320x200, 256-color. Only one implemented so far. */ + uint8_t recordTypes[32]; /* Not yet implemented. */ + uint32_t nFrames; /* Number of actual frames in the file, includes ring frame. */ + uint16_t framesPerSecond; /* Number of frames to play per second. */ + uint16_t pad2[29]; /* 58 bytes of filler to round up to 128 bytes total. */ }; // this is the format of a large page structure struct lp_descriptor { - uint16_t baseRecord; // Number of first record in this large page. - uint16_t nRecords; // Number of records in lp. - // bit 15 of "nRecords" == "has continuation from previous lp". - // bit 14 of "nRecords" == "final record continues on next lp". - uint16_t nBytes; // Total number of bytes of contents, excluding header. + uint16_t baseRecord; // Number of first record in this large page. + uint16_t nRecords; // Number of records in lp. + // bit 15 of "nRecords" == "has continuation from previous lp". + // bit 14 of "nRecords" == "final record continues on next lp". + uint16_t nBytes; // Total number of bytes of contents, excluding header. }; #pragma pack(pop) @@ -84,16 +84,16 @@ struct lp_descriptor struct anim_t { - uint16_t framecount; // current frame of anim - lpfileheader * lpheader; // file header will be loaded into this structure - lp_descriptor * LpArray; // arrays of large page structs used to find frames - uint16_t curlpnum; // initialize to an invalid Large page number - lp_descriptor * curlp; // header of large page currently in memory - uint16_t * thepage; // buffer where current large page is loaded - uint8_t imagebuffer[IMAGEBUFFERSIZE]; // buffer where anim frame is decoded - uint8_t * buffer; - uint8_t pal[768]; - int32_t currentframe; + uint16_t framecount; // current frame of anim + lpfileheader * lpheader; // file header will be loaded into this structure + lp_descriptor * LpArray; // arrays of large page structs used to find frames + uint16_t curlpnum; // initialize to an invalid Large page number + lp_descriptor * curlp; // header of large page currently in memory + uint16_t * thepage; // buffer where current large page is loaded + uint8_t imagebuffer[IMAGEBUFFERSIZE]; // buffer where anim frame is decoded + uint8_t * buffer; + uint8_t pal[768]; + int32_t currentframe; }; //**************************************************************************** @@ -116,7 +116,7 @@ int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, int32_t length); inline int32_t ANIM_NumFrames(anim_t* anim) { - return anim->lpheader->nRecords; + return anim->lpheader->nRecords; } //**************************************************************************** @@ -138,7 +138,7 @@ uint8_t * ANIM_DrawFrame(anim_t* anim, int32_t framenumber); inline uint8_t* ANIM_GetPalette(anim_t* anim) { - return anim->pal; + return anim->pal; } #endif diff --git a/src/common/textures/animtexture.cpp b/src/common/textures/animtexture.cpp index 039021641..a3be03079 100644 --- a/src/common/textures/animtexture.cpp +++ b/src/common/textures/animtexture.cpp @@ -44,42 +44,42 @@ void AnimTexture::SetFrameSize(int format, int width, int height) { - pixelformat = format; - FTexture::SetSize(width, height); - Image.Resize(width * height * (format == Paletted ? 1 : 3)); - memset(Image.Data(), 0, Image.Size()); + pixelformat = format; + FTexture::SetSize(width, height); + Image.Resize(width * height * (format == Paletted ? 1 : 3)); + memset(Image.Data(), 0, Image.Size()); } void AnimTexture::SetFrame(const uint8_t* palette, const void* data_) { - if (palette) memcpy(Palette, palette, 768); - if (data_) - { - if (pixelformat == YUV) - { - auto spix = (const uint8_t*)data_; - auto dpix = Image.Data(); - for (int i = 0; i < Width * Height; i++) - { - int p = i * 4; - int q = i * 3; - float y = spix[p] * (1 / 255.f); - float u = spix[p + 1] * (1 / 255.f) - 0.5f; - float v = spix[p + 2] * (1 / 255.f) - 0.5f; + if (palette) memcpy(Palette, palette, 768); + if (data_) + { + if (pixelformat == YUV) + { + auto spix = (const uint8_t*)data_; + auto dpix = Image.Data(); + for (int i = 0; i < Width * Height; i++) + { + int p = i * 4; + int q = i * 3; + float y = spix[p] * (1 / 255.f); + float u = spix[p + 1] * (1 / 255.f) - 0.5f; + float v = spix[p + 2] * (1 / 255.f) - 0.5f; - y = 1.1643f * (y - 0.0625f); + y = 1.1643f * (y - 0.0625f); - float r = y + 1.5958f * v; - float g = y - 0.39173f * u - 0.81290f * v; - float b = y + 2.017f * u; + float r = y + 1.5958f * v; + float g = y - 0.39173f * u - 0.81290f * v; + float b = y + 2.017f * u; - dpix[q + 0] = (uint8_t)(clamp(r, 0.f, 1.f) * 255); - dpix[q + 1] = (uint8_t)(clamp(g, 0.f, 1.f) * 255); - dpix[q + 2] = (uint8_t)(clamp(b, 0.f, 1.f) * 255); - } - } - else memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3)); - } + dpix[q + 0] = (uint8_t)(clamp(r, 0.f, 1.f) * 255); + dpix[q + 1] = (uint8_t)(clamp(g, 0.f, 1.f) * 255); + dpix[q + 2] = (uint8_t)(clamp(b, 0.f, 1.f) * 255); + } + } + else memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3)); + } } //=========================================================================== @@ -90,37 +90,37 @@ void AnimTexture::SetFrame(const uint8_t* palette, const void* data_) FBitmap AnimTexture::GetBgraBitmap(const PalEntry* remap, int* trans) { - FBitmap bmp; + FBitmap bmp; - bmp.Create(Width, Height); + bmp.Create(Width, Height); - auto spix = Image.Data(); - auto dpix = bmp.GetPixels(); - if (pixelformat == Paletted) - { - for (int i = 0; i < Width * Height; i++) - { - int p = i * 4; - int index = spix[i]; - dpix[p + 0] = Palette[index * 3 + 2]; - dpix[p + 1] = Palette[index * 3 + 1]; - dpix[p + 2] = Palette[index * 3]; - dpix[p + 3] = 255; - } - } - else if (pixelformat == RGB || pixelformat == YUV) - { - for (int i = 0; i < Width * Height; i++) - { - int p = i * 4; - int q = i * 3; - dpix[p + 0] = spix[q + 2]; - dpix[p + 1] = spix[q + 1]; - dpix[p + 2] = spix[q]; - dpix[p + 3] = 255; - } - } - return bmp; + auto spix = Image.Data(); + auto dpix = bmp.GetPixels(); + if (pixelformat == Paletted) + { + for (int i = 0; i < Width * Height; i++) + { + int p = i * 4; + int index = spix[i]; + dpix[p + 0] = Palette[index * 3 + 2]; + dpix[p + 1] = Palette[index * 3 + 1]; + dpix[p + 2] = Palette[index * 3]; + dpix[p + 3] = 255; + } + } + else if (pixelformat == RGB || pixelformat == YUV) + { + for (int i = 0; i < Width * Height; i++) + { + int p = i * 4; + int q = i * 3; + dpix[p + 0] = spix[q + 2]; + dpix[p + 1] = spix[q + 1]; + dpix[p + 2] = spix[q]; + dpix[p + 3] = 255; + } + } + return bmp; } //========================================================================== @@ -131,36 +131,36 @@ FBitmap AnimTexture::GetBgraBitmap(const PalEntry* remap, int* trans) AnimTextures::AnimTextures() { - active = 1; - tex[0] = TexMan.FindGameTexture("AnimTextureFrame1", ETextureType::Override); - tex[1] = TexMan.FindGameTexture("AnimTextureFrame2", ETextureType::Override); + active = 1; + tex[0] = TexMan.FindGameTexture("AnimTextureFrame1", ETextureType::Override); + tex[1] = TexMan.FindGameTexture("AnimTextureFrame2", ETextureType::Override); } AnimTextures::~AnimTextures() { - Clean(); + Clean(); } void AnimTextures::Clean() { - if (tex[0]) tex[0]->CleanHardwareData(true); - if (tex[1]) tex[1]->CleanHardwareData(true); - tex[0] = tex[1] = nullptr; + if (tex[0]) tex[0]->CleanHardwareData(true); + if (tex[1]) tex[1]->CleanHardwareData(true); + tex[0] = tex[1] = nullptr; } void AnimTextures::SetSize(int format, int width, int height) { - static_cast(tex[0]->GetTexture())->SetFrameSize(format, width, height); - static_cast(tex[1]->GetTexture())->SetFrameSize(format, width, height); - tex[0]->SetSize(width, height); - tex[1]->SetSize(width, height); - tex[0]->CleanHardwareData(); - tex[1]->CleanHardwareData(); + static_cast(tex[0]->GetTexture())->SetFrameSize(format, width, height); + static_cast(tex[1]->GetTexture())->SetFrameSize(format, width, height); + tex[0]->SetSize(width, height); + tex[1]->SetSize(width, height); + tex[0]->CleanHardwareData(); + tex[1]->CleanHardwareData(); } void AnimTextures::SetFrame(const uint8_t* palette, const void* data) { - active ^= 1; - static_cast(tex[active]->GetTexture())->SetFrame(palette, data); - tex[active]->CleanHardwareData(); + active ^= 1; + static_cast(tex[active]->GetTexture())->SetFrame(palette, data); + tex[active]->CleanHardwareData(); } diff --git a/src/common/textures/bitmap.cpp b/src/common/textures/bitmap.cpp index 2e9a32883..bfe79dbb4 100644 --- a/src/common/textures/bitmap.cpp +++ b/src/common/textures/bitmap.cpp @@ -68,7 +68,6 @@ void iCopyColors(uint8_t *pout, const uint8_t *pin, int count, int step, FCopyIn int i; int fac; uint8_t r,g,b; - int gray; int a; switch(inf? inf->blend : BLEND_NONE) @@ -98,7 +97,7 @@ void iCopyColors(uint8_t *pout, const uint8_t *pin, int count, int step, FCopyIn if (TBlend::ProcessAlpha0() || a) { int gray = TSrc::Gray(pin)>>4; - + TBlend::OpC(pout[TDest::RED], IcePalette[gray][0], a, inf); TBlend::OpC(pout[TDest::GREEN], IcePalette[gray][1], a, inf); TBlend::OpC(pout[TDest::BLUE], IcePalette[gray][2], a, inf); @@ -119,7 +118,7 @@ void iCopyColors(uint8_t *pout, const uint8_t *pin, int count, int step, FCopyIn a = TSrc::A(pin, tr, tg, tb); if (TBlend::ProcessAlpha0() || a) { - gray = clamp(TSrc::Gray(pin),0,255); + int gray = clamp(TSrc::Gray(pin),0,255); PalEntry pe = cm->GrayscaleToColor[gray]; TBlend::OpC(pout[TDest::RED], pe.r , a, inf); @@ -140,7 +139,7 @@ void iCopyColors(uint8_t *pout, const uint8_t *pin, int count, int step, FCopyIn a = TSrc::A(pin, tr, tg, tb); if (TBlend::ProcessAlpha0() || a) { - gray = TSrc::Gray(pin); + int gray = TSrc::Gray(pin); r = (TSrc::R(pin)*(31-fac) + gray*fac)/31; g = (TSrc::G(pin)*(31-fac) + gray*fac)/31; b = (TSrc::B(pin)*(31-fac) + gray*fac)/31; @@ -332,7 +331,7 @@ bool ClipCopyPixelRect(const FClipRect *cr, int &originx, int &originy, srcwidth = cr->x + cr->width - originx; if (srcwidth<=0) return false; } - + if (originy < cr->y) { int skip = cr->y - originy; diff --git a/src/common/textures/bitmap.h b/src/common/textures/bitmap.h index 88df40307..34fff5516 100644 --- a/src/common/textures/bitmap.h +++ b/src/common/textures/bitmap.h @@ -156,7 +156,7 @@ public: } } - + ~FBitmap() { Destroy(); diff --git a/src/common/textures/formats/anmtexture.cpp b/src/common/textures/formats/anmtexture.cpp index aa65dc693..3845bdc67 100644 --- a/src/common/textures/formats/anmtexture.cpp +++ b/src/common/textures/formats/anmtexture.cpp @@ -81,7 +81,7 @@ FImageSource *AnmImage_TryCreate(FileReader & file, int lumpnum) { return new FAnmTexture(lumpnum, 320, 200); } - + return nullptr; } @@ -132,7 +132,7 @@ TArray FAnmTexture::CreatePalettedPixels(int conversion) uint8_t buffer[64000]; uint8_t palette[768]; uint8_t remap[256]; - + ReadFrame(buffer, palette); for(int i=0;i<256;i++) { @@ -153,7 +153,7 @@ int FAnmTexture::CopyPixels(FBitmap *bmp, int conversion) uint8_t buffer[64000]; uint8_t palette[768]; ReadFrame(buffer, palette); - + auto dpix = bmp->GetPixels(); for (int i = 0; i < Width * Height; i++) { diff --git a/src/common/textures/formats/jpegtexture.cpp b/src/common/textures/formats/jpegtexture.cpp index e07f4425d..89ce068e2 100644 --- a/src/common/textures/formats/jpegtexture.cpp +++ b/src/common/textures/formats/jpegtexture.cpp @@ -296,7 +296,7 @@ TArray FJPEGTexture::CreatePalettedPixels(int conversion) while (cinfo.output_scanline < cinfo.output_height) { - int num_scanlines = jpeg_read_scanlines(&cinfo, &buff, 1); + jpeg_read_scanlines(&cinfo, &buff, 1); uint8_t *in = buff; uint8_t *out = Pixels.Data() + y; switch (cinfo.out_color_space) diff --git a/src/common/textures/formats/md5check.cpp b/src/common/textures/formats/md5check.cpp index 96e14b2f3..120371a8e 100644 --- a/src/common/textures/formats/md5check.cpp +++ b/src/common/textures/formats/md5check.cpp @@ -219,10 +219,10 @@ void makeMD5(const void *buffer, unsigned length, char *md5out) bool checkPatchForAlpha(const void *buffer, uint32_t length) { if (length > 10164) return false; // shortcut for anything too large - + char md5[33]; bool done = false; - + for(int i=0; alphapatches[i].length > 0; i++) { if (alphapatches[i].length == (int)length) // length check diff --git a/src/common/textures/formats/multipatchtexture.h b/src/common/textures/formats/multipatchtexture.h index 48223ec5e..c8cb16f24 100644 --- a/src/common/textures/formats/multipatchtexture.h +++ b/src/common/textures/formats/multipatchtexture.h @@ -120,6 +120,7 @@ struct BuildInfo bool bComplex = false; bool textual = false; bool bNoDecals = false; + bool bNoTrim = false; int LeftOffset[2] = {}; int TopOffset[2] = {}; FGameTexture *texture = nullptr; diff --git a/src/common/textures/formats/patchtexture.cpp b/src/common/textures/formats/patchtexture.cpp index f1f65291d..e680bf38a 100644 --- a/src/common/textures/formats/patchtexture.cpp +++ b/src/common/textures/formats/patchtexture.cpp @@ -76,15 +76,15 @@ public: static bool CheckIfPatch(FileReader & file, bool &isalpha) { if (file.GetLength() < 13) return false; // minimum length of a valid Doom patch - + file.Seek(0, FileReader::SeekSet); auto data = file.Read(file.GetLength()); - + const patch_t *foo = (const patch_t *)data.Data(); - + int height = LittleShort(foo->height); int width = LittleShort(foo->width); - + if (height > 0 && height <= 2048 && width > 0 && width <= 2048 && width < file.GetLength()/4) { // The dimensions seem like they might be valid for a patch, so @@ -93,7 +93,7 @@ static bool CheckIfPatch(FileReader & file, bool &isalpha) // and none of them must point past the end of the patch. bool gapAtStart = true; int x; - + for (x = 0; x < width; ++x) { uint32_t ofs = LittleLong(foo->columnofs[x]); diff --git a/src/common/textures/formats/pcxtexture.cpp b/src/common/textures/formats/pcxtexture.cpp index 89d05e427..32183155a 100644 --- a/src/common/textures/formats/pcxtexture.cpp +++ b/src/common/textures/formats/pcxtexture.cpp @@ -383,7 +383,7 @@ TArray FPCXTexture::CreatePalettedPixels(int conversion) else if (bitcount == 8) { lump.Seek(-769, FileReader::SeekEnd); - uint8_t c = lump.ReadUInt8(); + lump.ReadUInt8(); //if (c !=0x0c) memcpy(PaletteMap, GrayMap, 256); // Fallback for files without palette //else for(int i=0;i<256;i++) diff --git a/src/common/textures/formats/pngtexture.cpp b/src/common/textures/formats/pngtexture.cpp index dd0976a8e..c91723b95 100644 --- a/src/common/textures/formats/pngtexture.cpp +++ b/src/common/textures/formats/pngtexture.cpp @@ -684,7 +684,7 @@ public: virtual FBitmap GetBgraBitmap(const PalEntry *remap, int *trans) override; protected: - + FileReader fr; uint8_t ColorType; int PaletteSize; @@ -703,7 +703,7 @@ FGameTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename) { return nullptr; } - + // Savegame images can only be either 8 bit paletted or 24 bit RGB auto &data = png->File; int width = data.ReadInt32BE(); @@ -713,7 +713,7 @@ FGameTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename) uint8_t compression = data.ReadUInt8(); uint8_t filter = data.ReadUInt8(); uint8_t interlace = data.ReadUInt8(); - + // Reject anything that cannot be put into a savegame picture by GZDoom itself. if (compression != 0 || filter != 0 || interlace > 0 || bitdepth != 8 || (colortype != 2 && colortype != 3)) return nullptr; else return MakeGameTexture(new FPNGFileTexture (png->File, width, height, colortype), nullptr, ETextureType::Override); @@ -748,9 +748,9 @@ FBitmap FPNGFileTexture::GetBgraBitmap(const PalEntry *remap, int *trans) PalEntry pe[256]; uint32_t len, id; int pixwidth = Width * (ColorType == 2? 3:1); - + FileReader *lump = &fr; - + bmp.Create(Width, Height); lump->Seek(33, FileReader::SeekSet); lump->Read(&len, 4); @@ -779,12 +779,12 @@ FBitmap FPNGFileTexture::GetBgraBitmap(const PalEntry *remap, int *trans) auto StartOfIDAT = (uint32_t)lump->Tell() - 8; TArray Pixels(pixwidth * Height); - + lump->Seek (StartOfIDAT, FileReader::SeekSet); lump->Read(&len, 4); lump->Read(&id, 4); M_ReadIDAT (*lump, Pixels.Data(), Width, Height, pixwidth, 8, ColorType, 0, BigLong((unsigned int)len)); - + if (ColorType == 3) { bmp.CopyPixelData(0, 0, Pixels.Data(), Width, Height, 1, Width, 0, pe); diff --git a/src/common/textures/formats/stb_image.h b/src/common/textures/formats/stb_image.h index 196dfd5cc..44117802a 100644 --- a/src/common/textures/formats/stb_image.h +++ b/src/common/textures/formats/stb_image.h @@ -1198,7 +1198,7 @@ static FILE *stbi__fopen(char const *filename, char const *mode) wchar_t wFilename[1024]; if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename))) return 0; - + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode))) return 0; @@ -1302,7 +1302,7 @@ STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int * unsigned char *result; stbi__context s; stbi__start_mem(&s,buffer,len); - + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); if (stbi__vertically_flip_on_load) { stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); @@ -6522,7 +6522,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i g->color_table = (stbi_uc *) g->pal; } else return stbi__errpuc("missing color table", "Corrupt GIF"); - + o = stbi__process_gif_raster(s, g); if (!o) return NULL; @@ -6608,7 +6608,7 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, *y = g.h; ++layers; stride = g.w * g.h * 4; - + if (out) { out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); if (delays) { diff --git a/src/common/textures/formats/stbtexture.cpp b/src/common/textures/formats/stbtexture.cpp index bce080c62..7ffb6f01d 100644 --- a/src/common/textures/formats/stbtexture.cpp +++ b/src/common/textures/formats/stbtexture.cpp @@ -43,7 +43,7 @@ #define STBI_NO_HDR #define STBI_NO_PNM #include "stb_image.h" - + #include "files.h" #include "filesystem.h" @@ -92,7 +92,7 @@ FImageSource *StbImage_TryCreate(FileReader & file, int lumpnum) { return new FStbTexture(lumpnum, x, y); } - + return nullptr; } diff --git a/src/common/textures/formats/tgatexture.cpp b/src/common/textures/formats/tgatexture.cpp index d2e12e1aa..690c2bc29 100644 --- a/src/common/textures/formats/tgatexture.cpp +++ b/src/common/textures/formats/tgatexture.cpp @@ -57,7 +57,7 @@ struct TGAHeader int16_t cm_first; int16_t cm_length; uint8_t cm_size; - + int16_t x_origin; int16_t y_origin; int16_t width; @@ -97,12 +97,12 @@ FImageSource *TGAImage_TryCreate(FileReader & file, int lumpnum) TGAHeader hdr; if (file.GetLength() < (long)sizeof(hdr)) return NULL; - + file.Seek(0, FileReader::SeekSet); file.Read(&hdr, sizeof(hdr)); hdr.width = LittleShort(hdr.width); hdr.height = LittleShort(hdr.height); - + // Not much that can be done here because TGA does not have a proper // header to be identified with. if (hdr.has_cm != 0 && hdr.has_cm != 1) return NULL; @@ -145,7 +145,7 @@ void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytespe { uint8_t data[4]; int Size = Width * Height; - + while (Size > 0) { uint8_t b = lump.ReadUInt8(); @@ -188,7 +188,7 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) TArray Pixels(Width*Height, true); lump.Read(&hdr, sizeof(hdr)); lump.Seek(hdr.id_len, FileReader::SeekCur); - + hdr.width = LittleShort(hdr.width); hdr.height = LittleShort(hdr.height); hdr.cm_first = LittleShort(hdr.cm_first); @@ -209,14 +209,14 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) b = (w & 0x7C00) >> 7; a = 255; break; - + case 24: b = lump.ReadUInt8(); g = lump.ReadUInt8(); r = lump.ReadUInt8(); a=255; break; - + case 32: b = lump.ReadUInt8(); g = lump.ReadUInt8(); @@ -224,7 +224,7 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) a = lump.ReadUInt8(); if ((hdr.img_desc&15)!=8) a=255; break; - + default: // should never happen r=g=b=a=0; break; @@ -232,10 +232,10 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) PaletteMap[i] = ImageHelpers::RGBToPalettePrecise(conversion == luminance, r, g, b, a); } } - + int Size = Width * Height * (hdr.bpp>>3); TArray buffer(Size, true); - + if (hdr.img_type < 4) // uncompressed { lump.Read(buffer.Data(), Size); @@ -244,7 +244,7 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) { ReadCompressed(lump, buffer.Data(), hdr.bpp>>3); } - + uint8_t * ptr = buffer.Data(); int step_x = (hdr.bpp>>3); int Pitch = Width * step_x; @@ -293,7 +293,7 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) } } break; - + case 24: for(int y=0;y FTGATexture::CreatePalettedPixels(int conversion) } } break; - + case 32: if ((hdr.img_desc&15)!=8) // 32 bits without a valid alpha channel { @@ -332,12 +332,12 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) } } break; - + default: break; } break; - + case 3: // Grayscale { auto remap = ImageHelpers::GetRemap(conversion == luminance, true); @@ -395,7 +395,7 @@ int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) lump.Read(&hdr, sizeof(hdr)); lump.Seek(hdr.id_len, FileReader::SeekCur); - + hdr.width = LittleShort(hdr.width); hdr.height = LittleShort(hdr.height); hdr.cm_first = LittleShort(hdr.cm_first); @@ -440,10 +440,10 @@ int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) pe[i] = PalEntry(a, r, g, b); } } - + int Size = Width * Height * (hdr.bpp>>3); TArray sbuffer(Size); - + if (hdr.img_type < 4) // uncompressed { lump.Read(sbuffer.Data(), Size); @@ -452,7 +452,7 @@ int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) { ReadCompressed(lump, sbuffer.Data(), hdr.bpp>>3); } - + uint8_t * ptr = sbuffer.Data(); int step_x = (hdr.bpp>>3); int Pitch = Width * step_x; @@ -483,11 +483,11 @@ int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) case 16: bmp->CopyPixelDataRGB(0, 0, ptr, Width, Height, step_x, Pitch, 0, CF_RGB555); break; - + case 24: bmp->CopyPixelDataRGB(0, 0, ptr, Width, Height, step_x, Pitch, 0, CF_BGR); break; - + case 32: if ((hdr.img_desc&15)!=8) // 32 bits without a valid alpha channel { @@ -499,12 +499,12 @@ int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) transval = -1; } break; - + default: break; } break; - + case 3: // Grayscale switch (hdr.bpp) { @@ -512,11 +512,11 @@ int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) for(int i=0;i<256;i++) pe[i]=PalEntry(255,i,i,i); // gray map bmp->CopyPixelData(0, 0, ptr, Width, Height, step_x, Pitch, 0, pe); break; - + case 16: bmp->CopyPixelDataRGB(0, 0, ptr, Width, Height, step_x, Pitch, 0, CF_I16); break; - + default: break; } diff --git a/src/common/textures/gametexture.h b/src/common/textures/gametexture.h index e9851fbe3..a9e516ae4 100644 --- a/src/common/textures/gametexture.h +++ b/src/common/textures/gametexture.h @@ -59,6 +59,7 @@ enum EGameTexFlags GTexf_BrightmapChecked = 128, // Check for a colormap-based brightmap was already done. GTexf_AutoMaterialsAdded = 256, // AddAutoMaterials has been called on this texture. GTexf_OffsetsNotForFont = 512, // The offsets must be ignored when using this texture in a font. + GTexf_NoTrim = 1024, // Don't perform trimming on this texture. }; // Refactoring helper to allow piece by piece adjustment of the API @@ -136,8 +137,12 @@ public: void SetSpriteRect(); ETextureType GetUseType() const { return UseType; } - void SetUpscaleFlag(int what) { shouldUpscaleFlag = what; } - int GetUpscaleFlag() { return shouldUpscaleFlag == 1; } + void SetUpscaleFlag(int what, bool manual = false) + { + if ((shouldUpscaleFlag & 2) && !manual) return; // if set manually this may not be reset. + shouldUpscaleFlag = what | (manual? 2 : 0); + } + int GetUpscaleFlag() { return shouldUpscaleFlag & 1; } FTexture* GetTexture() { return Base.get(); } int GetSourceLump() const { return Base->GetSourceLump(); } @@ -155,6 +160,8 @@ public: bool expandSprites() { return expandSprite == -1? ShouldExpandSprite() : !!expandSprite; } bool useWorldPanning() const { return !!(flags & GTexf_WorldPanning); } void SetWorldPanning(bool on) { if (on) flags |= GTexf_WorldPanning; else flags &= ~GTexf_WorldPanning; } + void SetNoTrimming(bool on) { if (on) flags |= GTexf_NoTrim; else flags &= ~GTexf_NoTrim; } + bool GetNoTrimming() { return !!(flags & GTexf_NoTrim); } bool allowNoDecals() const { return !!(flags & GTexf_NoDecals); } void SetNoDecals(bool on) { if (on) flags |= GTexf_NoDecals; else flags &= ~GTexf_NoDecals; } void SetOffsetsNotForFont() { flags |= GTexf_OffsetsNotForFont; } diff --git a/src/common/textures/hires/hqnx_asm/hq4x_asm.cpp b/src/common/textures/hires/hqnx_asm/hq4x_asm.cpp index 7ce8a1621..5d22e1348 100644 --- a/src/common/textures/hires/hqnx_asm/hq4x_asm.cpp +++ b/src/common/textures/hires/hqnx_asm/hq4x_asm.cpp @@ -272,9 +272,9 @@ bool Diff(const unsigned int rgb1, const unsigned int rgb2) { return false; } - + static const hq_vec THRESHOLD = 0x00300706; - + const hq_vec yuv1 = RGBtoYUV[rgb1]; const hq_vec yuv2 = RGBtoYUV[rgb2]; diff --git a/src/common/textures/hires/hqresize.cpp b/src/common/textures/hires/hqresize.cpp index 16b2b4b13..9a6c42aa2 100644 --- a/src/common/textures/hires/hqresize.cpp +++ b/src/common/textures/hires/hqresize.cpp @@ -375,7 +375,7 @@ static unsigned char *xbrzHelper( void (*xbrzFunction) ( size_t, const uint32_t* outHeight = N *inHeight; unsigned char * newBuffer = new unsigned char[outWidth*outHeight*4]; - + const int thresholdWidth = gl_texture_hqresize_mt_width; const int thresholdHeight = gl_texture_hqresize_mt_height; diff --git a/src/common/textures/hires/xbr/xbrz_old.h b/src/common/textures/hires/xbr/xbrz_old.h index 9a46f2a97..10e60dcfc 100644 --- a/src/common/textures/hires/xbr/xbrz_old.h +++ b/src/common/textures/hires/xbr/xbrz_old.h @@ -47,7 +47,7 @@ http://board.byuu.org/viewtopic.php?f=10&t=2248 THREAD-SAFETY: - parts of the same image may be scaled by multiple threads as long as the [yFirst, yLast) ranges do not overlap! - there is a minor inefficiency for the first row of a slice, so avoid processing single rows only - + */ void scale(size_t factor, //valid range: 2 - 5 const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, diff --git a/src/common/textures/hw_texcontainer.h b/src/common/textures/hw_texcontainer.h index 91afa526f..a4ff33f93 100644 --- a/src/common/textures/hw_texcontainer.h +++ b/src/common/textures/hw_texcontainer.h @@ -58,7 +58,7 @@ private: TranslatedTexture hwDefTex[4]; TArray hwTex_Translated; - + TranslatedTexture * GetTexID(int translation, int scaleflags) { // Allow negative indices to pass through unchanged. @@ -108,13 +108,13 @@ public: hwDefTex[1].Delete(); hwTex_Translated.Clear(); } - + IHardwareTexture * GetHardwareTexture(int translation, int scaleflags) { auto tt = GetTexID(translation, scaleflags); return tt->hwTexture; } - + void AddHardwareTexture(int translation, int scaleflags, IHardwareTexture *tex) { auto tt = GetTexID(translation, scaleflags); @@ -170,6 +170,6 @@ public: for (auto & t : hwTex_Translated) if (t.hwTexture) callback(t.hwTexture); } - + }; diff --git a/src/common/textures/image.cpp b/src/common/textures/image.cpp index 73d6f5227..f8f480671 100644 --- a/src/common/textures/image.cpp +++ b/src/common/textures/image.cpp @@ -85,7 +85,6 @@ PalettedPixels FImageSource::GetCachedPalettedPixels(int conversion) FString name; fileSystem.GetFileShortName(name, SourceLump); - std::pair *info = nullptr; auto imageID = ImageID; // Do we have this image in the cache? @@ -196,14 +195,13 @@ int FImageSource::CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap) FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int *ptrans) { FBitmap ret; - + FString name; int trans = -1; fileSystem.GetFileShortName(name, SourceLump); - - std::pair *info = nullptr; + auto imageID = ImageID; - + if (remap != nullptr) { // Remapped images are never run through the cache because they would complicate matters too much for very little gain. @@ -220,7 +218,7 @@ FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int if (index < precacheDataRgba.Size()) { auto cache = &precacheDataRgba[index]; - + trans = cache->TransInfo; if (cache->RefCount > 1) { @@ -258,7 +256,7 @@ FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int //Printf("creating cached entry for %s, refcount = %d\n", name.GetChars(), info->first); // This is the first time it gets accessed and needs to be placed in the cache. PrecacheDataRgba *pdr = &precacheDataRgba[precacheDataRgba.Reserve(1)]; - + pdr->ImageID = imageID; pdr->RefCount = info->first - 1; info->first = 0; diff --git a/src/common/textures/image.h b/src/common/textures/image.h index 6ddd34bc2..0924fe97e 100644 --- a/src/common/textures/image.h +++ b/src/common/textures/image.h @@ -77,7 +77,7 @@ public: int8_t bTranslucent = -1; // Image has pixels with a non-0/1 value. (-1 means the user needs to do a real check) int GetId() const { return ImageID; } - + // 'noremap0' will only be looked at by FPatchTexture and forwarded by FMultipatchTexture. // Either returns a reference to the cache, or a newly created item. The return of this has to be considered transient. If you need to store the result, use GetPalettedPixels @@ -86,7 +86,7 @@ public: // tries to get a buffer from the cache. If not available, create a new one. If further references are pending, create a copy. TArray GetPalettedPixels(int conversion); - + // Unlile for paletted images there is no variant here that returns a persistent bitmap, because all users have to process the returned image into another format. FBitmap GetCachedBitmap(const PalEntry *remap, int conversion, int *trans = nullptr); @@ -102,25 +102,25 @@ public: luminance = 1, noremap0 = 2 }; - + FImageSource(int sourcelump = -1) : SourceLump(sourcelump) { ImageID = ++NextID; } virtual ~FImageSource() {} - + int GetWidth() const { return Width; } - + int GetHeight() const { return Height; } - + std::pair GetSize() const { return std::make_pair(Width, Height); } - + std::pair GetOffsets() const { return std::make_pair(LeftOffset, TopOffset); @@ -131,12 +131,12 @@ public: LeftOffset = x; TopOffset = y; } - + int LumpNum() const { return SourceLump; } - + bool UseGamePalette() const { return bUseGamePalette; diff --git a/src/common/textures/imagehelpers.h b/src/common/textures/imagehelpers.h index 8923f92db..a25187ef2 100644 --- a/src/common/textures/imagehelpers.h +++ b/src/common/textures/imagehelpers.h @@ -58,7 +58,7 @@ namespace ImageHelpers return srcisgrayscale ? GPalette.GrayMap : GPalette.Remap; } } - + inline uint8_t RGBToPalettePrecise(bool wantluminance, int r, int g, int b, int a = 255) { if (wantluminance) @@ -70,7 +70,7 @@ namespace ImageHelpers return ColorMatcher.Pick(r, g, b); } } - + inline uint8_t RGBToPalette(bool wantluminance, int r, int g, int b, int a = 255) { if (wantluminance) @@ -83,19 +83,19 @@ namespace ImageHelpers return a < 128? 0 : RGB256k.RGB[r >> 2][g >> 2][b >> 2]; } } - + inline uint8_t RGBToPalette(bool wantluminance, PalEntry pe, bool hasalpha = true) { return RGBToPalette(wantluminance, pe.r, pe.g, pe.b, hasalpha? pe.a : 255); } - + //========================================================================== // // Converts a texture between row-major and column-major format // by flipping it about the X=Y axis. // //========================================================================== - + template void FlipSquareBlock (T *block, int x) { @@ -109,7 +109,7 @@ namespace ImageHelpers } } } - + inline void FlipSquareBlockRemap (uint8_t *block, int x, const uint8_t *remap) { for (int i = 0; i < x; ++i) @@ -124,7 +124,7 @@ namespace ImageHelpers } } } - + template void FlipNonSquareBlock (T *dst, const T *src, int x, int y, int srcpitch) { @@ -136,7 +136,7 @@ namespace ImageHelpers } } } - + inline void FlipNonSquareBlockRemap (uint8_t *dst, const uint8_t *src, int x, int y, int srcpitch, const uint8_t *remap) { for (int i = 0; i < x; ++i) diff --git a/src/common/textures/imagetexture.cpp b/src/common/textures/imagetexture.cpp index 261333c98..d94ff8002 100644 --- a/src/common/textures/imagetexture.cpp +++ b/src/common/textures/imagetexture.cpp @@ -90,7 +90,7 @@ FBitmap FImageTexture::GetBgraBitmap(const PalEntry *p, int *trans) TArray FImageTexture::Get8BitPixels(bool alpha) { - return mImage->GetPalettedPixels(alpha? alpha : bNoRemap0 ? FImageSource::noremap0 : FImageSource::normal); + return mImage->GetPalettedPixels(alpha? FImageSource::luminance : bNoRemap0 ? FImageSource::noremap0 : FImageSource::normal); } //=========================================================================== diff --git a/src/common/textures/multipatchtexturebuilder.cpp b/src/common/textures/multipatchtexturebuilder.cpp index 6a49d87ae..2a8b77fea 100644 --- a/src/common/textures/multipatchtexturebuilder.cpp +++ b/src/common/textures/multipatchtexturebuilder.cpp @@ -144,6 +144,7 @@ void FMultipatchTextureBuilder::MakeTexture(BuildInfo &buildinfo, ETextureType u buildinfo.texture->SetScale((float)buildinfo.Scale.X, (float)buildinfo.Scale.Y); buildinfo.texture->SetWorldPanning(buildinfo.bWorldPanning); buildinfo.texture->SetNoDecals(buildinfo.bNoDecals); + buildinfo.texture->SetNoTrimming(buildinfo.bNoTrim); TexMan.AddGameTexture(buildinfo.texture); } @@ -295,12 +296,12 @@ void FMultipatchTextureBuilder::AddTexturesLump(const void *lumpdata, int lumpsi // Catalog the patches these textures use so we know which // textures they represent. patchlookup.Resize(numpatches); - for (uint32_t i = 0; i < numpatches; ++i) + for (uint32_t ii = 0; ii < numpatches; ++ii) { char pname[9]; pnames.Read(pname, 8); pname[8] = '\0'; - patchlookup[i].Name = pname; + patchlookup[ii].Name = pname; } } @@ -611,7 +612,7 @@ void FMultipatchTextureBuilder::ParseTexture(FScanner &sc, ETextureType UseType, BuildInfo &buildinfo = BuiltTextures[BuiltTextures.Reserve(1)]; bool bSilent = false; - + buildinfo.textual = true; sc.SetCMode(true); sc.MustGetString(); @@ -669,6 +670,10 @@ void FMultipatchTextureBuilder::ParseTexture(FScanner &sc, ETextureType UseType, { buildinfo.bNoDecals = true; } + else if (sc.Compare("NoTrim")) + { + buildinfo.bNoTrim = true; + } else if (sc.Compare("Patch")) { TexPartBuild part; @@ -777,12 +782,12 @@ void FMultipatchTextureBuilder::ResolvePatches(BuildInfo &buildinfo) { TArray list; TexMan.ListTextures(buildinfo.Inits[i].TexName, list, true); - for (int i = list.Size() - 1; i >= 0; i--) + for (int ii = list.Size() - 1; ii >= 0; ii--) { - auto gtex = TexMan.GetGameTexture(list[i]); + auto gtex = TexMan.GetGameTexture(list[ii]); if (gtex && gtex != buildinfo.texture && gtex->GetTexture() && gtex->GetTexture()->GetImage() && !dynamic_cast(gtex->GetTexture()->GetImage())) { - texno = list[i]; + texno = list[ii]; break; } } @@ -853,7 +858,6 @@ void FMultipatchTextureBuilder::ResolveAllPatches() ResolvePatches(bi); } // Now try to resolve the images. We only can do this at the end when all multipatch textures are set up. - int i = 0; // reverse the list so that the Delete operation in the loop below deletes at the end. // For normal sized lists this is of no real concern, but Total Chaos has over 250000 textures where this becomes a performance issue. diff --git a/src/common/textures/texture.cpp b/src/common/textures/texture.cpp index 5b88c3cef..db922a7b5 100644 --- a/src/common/textures/texture.cpp +++ b/src/common/textures/texture.cpp @@ -97,7 +97,7 @@ FBitmap FTexture::GetBgraBitmap(const PalEntry* remap, int* ptrans) int FTexture::CheckRealHeight() { auto pixels = Get8BitPixels(false); - + for(int h = GetHeight()-1; h>= 0; h--) { for(int w = 0; w < GetWidth(); w++) diff --git a/src/common/textures/texturemanager.cpp b/src/common/textures/texturemanager.cpp index 65e267b84..c7b5fad3d 100644 --- a/src/common/textures/texturemanager.cpp +++ b/src/common/textures/texturemanager.cpp @@ -86,11 +86,11 @@ FTextureManager::~FTextureManager () void FTextureManager::DeleteAll() { - FImageSource::ClearImages(); for (unsigned int i = 0; i < Textures.Size(); ++i) { delete Textures[i].Texture; } + FImageSource::ClearImages(); Textures.Clear(); Translation.Clear(); FirstTextureForFile.Clear(); @@ -235,7 +235,7 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset } } - + if (!(flags & TEXMAN_ShortNameOnly)) { // We intentionally only look for textures in subdirectories. @@ -376,18 +376,18 @@ bool FTextureManager::OkForLocalization(FTextureID texnum, const char *substitut if (*substitute == '$') substitute = GStrings.GetString(substitute+1, &langtable); else return true; // String literals from the source data should never override graphics from the same definition. if (substitute == nullptr) return true; // The text does not exist. - + // Modes 2, 3 and 4 must not replace localized textures. int localizedTex = ResolveLocalizedTexture(texnum.GetIndex()); if (localizedTex != texnum.GetIndex()) return true; // Do not substitute a localized variant of the graphics patch. - + // For mode 4 we are done now. if (locmode == 4) return false; - + // Mode 2 and 3 must reject any text replacement from the default language tables. if ((langtable & MAKE_ID(255,0,0,0)) == MAKE_ID('*', 0, 0, 0)) return true; // Do not substitute if the string comes from the default table. if (locmode == 2) return false; - + // Mode 3 must also reject substitutions for non-IWAD content. int file = fileSystem.GetFileContainer(Textures[texnum.GetIndex()].Texture->GetSourceLump()); if (file > fileSystem.GetMaxIwadNum()) return true; @@ -717,7 +717,7 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build sc.String[8]=0; tlist.Clear(); - int amount = ListTextures(sc.String, tlist); + ListTextures(sc.String, tlist); FName texname = sc.String; sc.MustGetString(); @@ -771,7 +771,7 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build else if (sc.Compare("define")) // define a new "fake" texture { sc.GetString(); - + FString base = ExtractFileBase(sc.String, false); if (!base.IsEmpty()) { @@ -811,6 +811,22 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build } //else Printf("Unable to define hires texture '%s'\n", tex->Name); } + else if (sc.Compare("notrim")) + { + sc.MustGetString(); + + FTextureID id = TexMan.CheckForTexture(sc.String, ETextureType::Sprite); + if (id.isValid()) + { + FGameTexture *tex = TexMan.GetGameTexture(id); + + if (tex) tex->SetNoTrimming(true); + else sc.ScriptError("NoTrim: %s not found", sc.String); + } + else + sc.ScriptError("NoTrim: %s is not a sprite", sc.String); + + } else if (sc.Compare("texture")) { build.ParseTexture(sc, ETextureType::Override, lump); @@ -919,7 +935,6 @@ void FTextureManager::LoadTextureX(int wadnum, FMultipatchTextureBuilder &build) void FTextureManager::AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &build) { int firsttexture = Textures.Size(); - int lumpcount = fileSystem.GetNumEntries(); bool iwad = wadnum >= fileSystem.GetIwadNum() && wadnum <= fileSystem.GetMaxIwadNum(); FirstTextureForFile.Push(firsttexture); @@ -1190,8 +1205,12 @@ void FTextureManager::Init(void (*progressFunc_)(), void (*checkForHacks)(BuildI AddGameTexture(CreateShaderTexture(true, false)); AddGameTexture(CreateShaderTexture(true, true)); // Add two animtexture entries so that movie playback can call functions using texture IDs. - AddGameTexture(MakeGameTexture(new AnimTexture(), "AnimTextureFrame1", ETextureType::Override)); - AddGameTexture(MakeGameTexture(new AnimTexture(), "AnimTextureFrame2", ETextureType::Override)); + auto mt = MakeGameTexture(new AnimTexture(), "AnimTextureFrame1", ETextureType::Override); + mt->SetUpscaleFlag(false, true); + AddGameTexture(mt); + mt = MakeGameTexture(new AnimTexture(), "AnimTextureFrame2", ETextureType::Override); + mt->SetUpscaleFlag(false, true); + AddGameTexture(mt); int wadcnt = fileSystem.GetNumWads(); @@ -1383,7 +1402,7 @@ int FTextureManager::ResolveLocalizedTexture(int tex) int FTextureManager::GuesstimateNumTextures () { int numtex = 0; - + for(int i = fileSystem.GetNumEntries()-1; i>=0; i--) { int space = fileSystem.GetFileNamespace(i); diff --git a/src/common/textures/texturemanager.h b/src/common/textures/texturemanager.h index 076ee1769..54d4aa8b8 100644 --- a/src/common/textures/texturemanager.h +++ b/src/common/textures/texturemanager.h @@ -21,7 +21,7 @@ class FTextureManager public: FTextureManager (); ~FTextureManager (); - + private: int ResolveLocalizedTexture(int texnum); @@ -57,7 +57,7 @@ public: { return InternalGetTexture(texnum.GetIndex(), animate, true); } - + FGameTexture* GetPalettedTexture(FTextureID texnum, bool animate = false, bool allowsubstitute = true) { auto texid = ResolveTextureIndex(texnum.GetIndex(), animate, true); @@ -171,7 +171,7 @@ public: private: void InitPalettedVersions(); - + // Switches struct TextureHash diff --git a/src/common/textures/textures.h b/src/common/textures/textures.h index a24dba5fa..ffb79c3e2 100644 --- a/src/common/textures/textures.h +++ b/src/common/textures/textures.h @@ -249,10 +249,10 @@ public: int GetWidth() { return Width; } int GetHeight() { return Height; } - + bool isHardwareCanvas() const { return bHasCanvas; } // There's two here so that this can deal with software canvases in the hardware renderer later. bool isCanvas() const { return bHasCanvas; } - + int GetSourceLump() { return SourceLump; } // needed by the scripted GetName method. void SetSourceLump(int sl) { SourceLump = sl; } bool FindHoles(const unsigned char * buffer, int w, int h); diff --git a/src/common/thirdparty/base64.h b/src/common/thirdparty/base64.h index f98e031fa..1f1bde61c 100644 --- a/src/common/thirdparty/base64.h +++ b/src/common/thirdparty/base64.h @@ -6,6 +6,8 @@ #ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A #define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A +#include "tarray.h" + TArray base64_encode(unsigned char const* bytes_to_encode, size_t in_len); void base64_decode(void* memory, size_t len, const char* encoded_string); diff --git a/src/common/thirdparty/gain_analysis.cpp b/src/common/thirdparty/gain_analysis.cpp index 23d618d27..2f92e2128 100644 --- a/src/common/thirdparty/gain_analysis.cpp +++ b/src/common/thirdparty/gain_analysis.cpp @@ -111,41 +111,41 @@ #endif static const Float_t ABYule[][2 * YULE_ORDER + 1] = { - {(const Float_t) 0.006471345933032, (const Float_t) -7.22103125152679, (const Float_t) -0.02567678242161, (const Float_t) 24.7034187975904, (const Float_t) 0.049805860704367, (const Float_t) -52.6825833623896, (const Float_t) -0.05823001743528, (const Float_t) 77.4825736677539, (const Float_t) 0.040611847441914, (const Float_t) -82.0074753444205, (const Float_t) -0.010912036887501, (const Float_t) 63.1566097101925, (const Float_t) -0.00901635868667, (const Float_t) -34.889569769245, (const Float_t) 0.012448886238123, (const Float_t) 13.2126852760198, (const Float_t) -0.007206683749426, (const Float_t) -3.09445623301669, (const Float_t) 0.002167156433951, (const Float_t) 0.340344741393305, (const Float_t) -0.000261819276949}, - {(const Float_t) 0.015415414474287, (const Float_t) -7.19001570087017, (const Float_t) -0.07691359399407, (const Float_t) 24.4109412087159, (const Float_t) 0.196677418516518, (const Float_t) -51.6306373580801, (const Float_t) -0.338855114128061, (const Float_t) 75.3978476863163, (const Float_t) 0.430094579594561, (const Float_t) -79.4164552507386, (const Float_t) -0.415015413747894, (const Float_t) 61.0373661948115, (const Float_t) 0.304942508151101, (const Float_t) -33.7446462547014, (const Float_t) -0.166191795926663, (const Float_t) 12.8168791146274, (const Float_t) 0.063198189938739, (const Float_t) -3.01332198541437, (const Float_t) -0.015003978694525, (const Float_t) 0.223619893831468, (const Float_t) 0.001748085184539}, - {(const Float_t) 0.021776466467053, (const Float_t) -5.74819833657784, (const Float_t) -0.062376961003801, (const Float_t) 16.246507961894, (const Float_t) 0.107731165328514, (const Float_t) -29.9691822642542, (const Float_t) -0.150994515142316, (const Float_t) 40.027597579378, (const Float_t) 0.170334807313632, (const Float_t) -40.3209196052655, (const Float_t) -0.157984942890531, (const Float_t) 30.8542077487718, (const Float_t) 0.121639833268721, (const Float_t) -17.5965138737281, (const Float_t) -0.074094040816409, (const Float_t) 7.10690214103873, (const Float_t) 0.031282852041061, (const Float_t) -1.82175564515191, (const Float_t) -0.00755421235941, (const Float_t) 0.223619893831468, (const Float_t) 0.00117925454213}, - {(const Float_t) 0.03857599435200, (const Float_t) -3.84664617118067, (const Float_t) -0.02160367184185, (const Float_t) 7.81501653005538, (const Float_t) -0.00123395316851, (const Float_t) -11.34170355132042, (const Float_t) -0.00009291677959, (const Float_t) 13.05504219327545, (const Float_t) -0.01655260341619, (const Float_t) -12.28759895145294, (const Float_t) 0.02161526843274, (const Float_t) 9.48293806319790, (const Float_t) -0.02074045215285, (const Float_t) -5.87257861775999, (const Float_t) 0.00594298065125, (const Float_t) 2.75465861874613, (const Float_t) 0.00306428023191, (const Float_t) -0.86984376593551, (const Float_t) 0.00012025322027, (const Float_t) 0.13919314567432, (const Float_t) 0.00288463683916}, - {(const Float_t) 0.05418656406430, (const Float_t) -3.47845948550071, (const Float_t) -0.02911007808948, (const Float_t) 6.36317777566148, (const Float_t) -0.00848709379851, (const Float_t) -8.54751527471874, (const Float_t) -0.00851165645469, (const Float_t) 9.47693607801280, (const Float_t) -0.00834990904936, (const Float_t) -8.81498681370155, (const Float_t) 0.02245293253339, (const Float_t) 6.85401540936998, (const Float_t) -0.02596338512915, (const Float_t) -4.39470996079559, (const Float_t) 0.01624864962975, (const Float_t) 2.19611684890774, (const Float_t) -0.00240879051584, (const Float_t) -0.75104302451432, (const Float_t) 0.00674613682247, (const Float_t) 0.13149317958808, (const Float_t) -0.00187763777362}, - {(const Float_t) 0.15457299681924, (const Float_t) -2.37898834973084, (const Float_t) -0.09331049056315, (const Float_t) 2.84868151156327, (const Float_t) -0.06247880153653, (const Float_t) -2.64577170229825, (const Float_t) 0.02163541888798, (const Float_t) 2.23697657451713, (const Float_t) -0.05588393329856, (const Float_t) -1.67148153367602, (const Float_t) 0.04781476674921, (const Float_t) 1.00595954808547, (const Float_t) 0.00222312597743, (const Float_t) -0.45953458054983, (const Float_t) 0.03174092540049, (const Float_t) 0.16378164858596, (const Float_t) -0.01390589421898, (const Float_t) -0.05032077717131, (const Float_t) 0.00651420667831, (const Float_t) 0.02347897407020, (const Float_t) -0.00881362733839}, - {(const Float_t) 0.30296907319327, (const Float_t) -1.61273165137247, (const Float_t) -0.22613988682123, (const Float_t) 1.07977492259970, (const Float_t) -0.08587323730772, (const Float_t) -0.25656257754070, (const Float_t) 0.03282930172664, (const Float_t) -0.16276719120440, (const Float_t) -0.00915702933434, (const Float_t) -0.22638893773906, (const Float_t) -0.02364141202522, (const Float_t) 0.39120800788284, (const Float_t) -0.00584456039913, (const Float_t) -0.22138138954925, (const Float_t) 0.06276101321749, (const Float_t) 0.04500235387352, (const Float_t) -0.00000828086748, (const Float_t) 0.02005851806501, (const Float_t) 0.00205861885564, (const Float_t) 0.00302439095741, (const Float_t) -0.02950134983287}, - {(const Float_t) 0.33642304856132, (const Float_t) -1.49858979367799, (const Float_t) -0.25572241425570, (const Float_t) 0.87350271418188, (const Float_t) -0.11828570177555, (const Float_t) 0.12205022308084, (const Float_t) 0.11921148675203, (const Float_t) -0.80774944671438, (const Float_t) -0.07834489609479, (const Float_t) 0.47854794562326, (const Float_t) -0.00469977914380, (const Float_t) -0.12453458140019, (const Float_t) -0.00589500224440, (const Float_t) -0.04067510197014, (const Float_t) 0.05724228140351, (const Float_t) 0.08333755284107, (const Float_t) 0.00832043980773, (const Float_t) -0.04237348025746, (const Float_t) -0.01635381384540, (const Float_t) 0.02977207319925, (const Float_t) -0.01760176568150}, - {(const Float_t) 0.44915256608450, (const Float_t) -0.62820619233671, (const Float_t) -0.14351757464547, (const Float_t) 0.29661783706366, (const Float_t) -0.22784394429749, (const Float_t) -0.37256372942400, (const Float_t) -0.01419140100551, (const Float_t) 0.00213767857124, (const Float_t) 0.04078262797139, (const Float_t) -0.42029820170918, (const Float_t) -0.12398163381748, (const Float_t) 0.22199650564824, (const Float_t) 0.04097565135648, (const Float_t) 0.00613424350682, (const Float_t) 0.10478503600251, (const Float_t) 0.06747620744683, (const Float_t) -0.01863887810927, (const Float_t) 0.05784820375801, (const Float_t) -0.03193428438915, (const Float_t) 0.03222754072173, (const Float_t) 0.00541907748707}, - {(const Float_t) 0.56619470757641, (const Float_t) -1.04800335126349, (const Float_t) -0.75464456939302, (const Float_t) 0.29156311971249, (const Float_t) 0.16242137742230, (const Float_t) -0.26806001042947, (const Float_t) 0.16744243493672, (const Float_t) 0.00819999645858, (const Float_t) -0.18901604199609, (const Float_t) 0.45054734505008, (const Float_t) 0.30931782841830, (const Float_t) -0.33032403314006, (const Float_t) -0.27562961986224, (const Float_t) 0.06739368333110, (const Float_t) 0.00647310677246, (const Float_t) -0.04784254229033, (const Float_t) 0.08647503780351, (const Float_t) 0.01639907836189, (const Float_t) -0.03788984554840, (const Float_t) 0.01807364323573, (const Float_t) -0.00588215443421}, - {(const Float_t) 0.58100494960553, (const Float_t) -0.51035327095184, (const Float_t) -0.53174909058578, (const Float_t) -0.31863563325245, (const Float_t) -0.14289799034253, (const Float_t) -0.20256413484477, (const Float_t) 0.17520704835522, (const Float_t) 0.14728154134330, (const Float_t) 0.02377945217615, (const Float_t) 0.38952639978999, (const Float_t) 0.15558449135573, (const Float_t) -0.23313271880868, (const Float_t) -0.25344790059353, (const Float_t) -0.05246019024463, (const Float_t) 0.01628462406333, (const Float_t) -0.02505961724053, (const Float_t) 0.06920467763959, (const Float_t) 0.02442357316099, (const Float_t) -0.03721611395801, (const Float_t) 0.01818801111503, (const Float_t) -0.00749618797172}, - {(const Float_t) 0.53648789255105, (const Float_t) -0.25049871956020, (const Float_t) -0.42163034350696, (const Float_t) -0.43193942311114, (const Float_t) -0.00275953611929, (const Float_t) -0.03424681017675, (const Float_t) 0.04267842219415, (const Float_t) -0.04678328784242, (const Float_t) -0.10214864179676, (const Float_t) 0.26408300200955, (const Float_t) 0.14590772289388, (const Float_t) 0.15113130533216, (const Float_t) -0.02459864859345, (const Float_t) -0.17556493366449, (const Float_t) -0.11202315195388, (const Float_t) -0.18823009262115, (const Float_t) -0.04060034127000, (const Float_t) 0.05477720428674, (const Float_t) 0.04788665548180, (const Float_t) 0.04704409688120, (const Float_t) -0.02217936801134}, + {(Float_t) 0.006471345933032, (Float_t) -7.22103125152679, (Float_t) -0.02567678242161, (Float_t) 24.7034187975904, (Float_t) 0.049805860704367, (Float_t) -52.6825833623896, (Float_t) -0.05823001743528, (Float_t) 77.4825736677539, (Float_t) 0.040611847441914, (Float_t) -82.0074753444205, (Float_t) -0.010912036887501, (Float_t) 63.1566097101925, (Float_t) -0.00901635868667, (Float_t) -34.889569769245, (Float_t) 0.012448886238123, (Float_t) 13.2126852760198, (Float_t) -0.007206683749426, (Float_t) -3.09445623301669, (Float_t) 0.002167156433951, (Float_t) 0.340344741393305, (Float_t) -0.000261819276949}, + {(Float_t) 0.015415414474287, (Float_t) -7.19001570087017, (Float_t) -0.07691359399407, (Float_t) 24.4109412087159, (Float_t) 0.196677418516518, (Float_t) -51.6306373580801, (Float_t) -0.338855114128061, (Float_t) 75.3978476863163, (Float_t) 0.430094579594561, (Float_t) -79.4164552507386, (Float_t) -0.415015413747894, (Float_t) 61.0373661948115, (Float_t) 0.304942508151101, (Float_t) -33.7446462547014, (Float_t) -0.166191795926663, (Float_t) 12.8168791146274, (Float_t) 0.063198189938739, (Float_t) -3.01332198541437, (Float_t) -0.015003978694525, (Float_t) 0.223619893831468, (Float_t) 0.001748085184539}, + {(Float_t) 0.021776466467053, (Float_t) -5.74819833657784, (Float_t) -0.062376961003801, (Float_t) 16.246507961894, (Float_t) 0.107731165328514, (Float_t) -29.9691822642542, (Float_t) -0.150994515142316, (Float_t) 40.027597579378, (Float_t) 0.170334807313632, (Float_t) -40.3209196052655, (Float_t) -0.157984942890531, (Float_t) 30.8542077487718, (Float_t) 0.121639833268721, (Float_t) -17.5965138737281, (Float_t) -0.074094040816409, (Float_t) 7.10690214103873, (Float_t) 0.031282852041061, (Float_t) -1.82175564515191, (Float_t) -0.00755421235941, (Float_t) 0.223619893831468, (Float_t) 0.00117925454213}, + {(Float_t) 0.03857599435200, (Float_t) -3.84664617118067, (Float_t) -0.02160367184185, (Float_t) 7.81501653005538, (Float_t) -0.00123395316851, (Float_t) -11.34170355132042, (Float_t) -0.00009291677959, (Float_t) 13.05504219327545, (Float_t) -0.01655260341619, (Float_t) -12.28759895145294, (Float_t) 0.02161526843274, (Float_t) 9.48293806319790, (Float_t) -0.02074045215285, (Float_t) -5.87257861775999, (Float_t) 0.00594298065125, (Float_t) 2.75465861874613, (Float_t) 0.00306428023191, (Float_t) -0.86984376593551, (Float_t) 0.00012025322027, (Float_t) 0.13919314567432, (Float_t) 0.00288463683916}, + {(Float_t) 0.05418656406430, (Float_t) -3.47845948550071, (Float_t) -0.02911007808948, (Float_t) 6.36317777566148, (Float_t) -0.00848709379851, (Float_t) -8.54751527471874, (Float_t) -0.00851165645469, (Float_t) 9.47693607801280, (Float_t) -0.00834990904936, (Float_t) -8.81498681370155, (Float_t) 0.02245293253339, (Float_t) 6.85401540936998, (Float_t) -0.02596338512915, (Float_t) -4.39470996079559, (Float_t) 0.01624864962975, (Float_t) 2.19611684890774, (Float_t) -0.00240879051584, (Float_t) -0.75104302451432, (Float_t) 0.00674613682247, (Float_t) 0.13149317958808, (Float_t) -0.00187763777362}, + {(Float_t) 0.15457299681924, (Float_t) -2.37898834973084, (Float_t) -0.09331049056315, (Float_t) 2.84868151156327, (Float_t) -0.06247880153653, (Float_t) -2.64577170229825, (Float_t) 0.02163541888798, (Float_t) 2.23697657451713, (Float_t) -0.05588393329856, (Float_t) -1.67148153367602, (Float_t) 0.04781476674921, (Float_t) 1.00595954808547, (Float_t) 0.00222312597743, (Float_t) -0.45953458054983, (Float_t) 0.03174092540049, (Float_t) 0.16378164858596, (Float_t) -0.01390589421898, (Float_t) -0.05032077717131, (Float_t) 0.00651420667831, (Float_t) 0.02347897407020, (Float_t) -0.00881362733839}, + {(Float_t) 0.30296907319327, (Float_t) -1.61273165137247, (Float_t) -0.22613988682123, (Float_t) 1.07977492259970, (Float_t) -0.08587323730772, (Float_t) -0.25656257754070, (Float_t) 0.03282930172664, (Float_t) -0.16276719120440, (Float_t) -0.00915702933434, (Float_t) -0.22638893773906, (Float_t) -0.02364141202522, (Float_t) 0.39120800788284, (Float_t) -0.00584456039913, (Float_t) -0.22138138954925, (Float_t) 0.06276101321749, (Float_t) 0.04500235387352, (Float_t) -0.00000828086748, (Float_t) 0.02005851806501, (Float_t) 0.00205861885564, (Float_t) 0.00302439095741, (Float_t) -0.02950134983287}, + {(Float_t) 0.33642304856132, (Float_t) -1.49858979367799, (Float_t) -0.25572241425570, (Float_t) 0.87350271418188, (Float_t) -0.11828570177555, (Float_t) 0.12205022308084, (Float_t) 0.11921148675203, (Float_t) -0.80774944671438, (Float_t) -0.07834489609479, (Float_t) 0.47854794562326, (Float_t) -0.00469977914380, (Float_t) -0.12453458140019, (Float_t) -0.00589500224440, (Float_t) -0.04067510197014, (Float_t) 0.05724228140351, (Float_t) 0.08333755284107, (Float_t) 0.00832043980773, (Float_t) -0.04237348025746, (Float_t) -0.01635381384540, (Float_t) 0.02977207319925, (Float_t) -0.01760176568150}, + {(Float_t) 0.44915256608450, (Float_t) -0.62820619233671, (Float_t) -0.14351757464547, (Float_t) 0.29661783706366, (Float_t) -0.22784394429749, (Float_t) -0.37256372942400, (Float_t) -0.01419140100551, (Float_t) 0.00213767857124, (Float_t) 0.04078262797139, (Float_t) -0.42029820170918, (Float_t) -0.12398163381748, (Float_t) 0.22199650564824, (Float_t) 0.04097565135648, (Float_t) 0.00613424350682, (Float_t) 0.10478503600251, (Float_t) 0.06747620744683, (Float_t) -0.01863887810927, (Float_t) 0.05784820375801, (Float_t) -0.03193428438915, (Float_t) 0.03222754072173, (Float_t) 0.00541907748707}, + {(Float_t) 0.56619470757641, (Float_t) -1.04800335126349, (Float_t) -0.75464456939302, (Float_t) 0.29156311971249, (Float_t) 0.16242137742230, (Float_t) -0.26806001042947, (Float_t) 0.16744243493672, (Float_t) 0.00819999645858, (Float_t) -0.18901604199609, (Float_t) 0.45054734505008, (Float_t) 0.30931782841830, (Float_t) -0.33032403314006, (Float_t) -0.27562961986224, (Float_t) 0.06739368333110, (Float_t) 0.00647310677246, (Float_t) -0.04784254229033, (Float_t) 0.08647503780351, (Float_t) 0.01639907836189, (Float_t) -0.03788984554840, (Float_t) 0.01807364323573, (Float_t) -0.00588215443421}, + {(Float_t) 0.58100494960553, (Float_t) -0.51035327095184, (Float_t) -0.53174909058578, (Float_t) -0.31863563325245, (Float_t) -0.14289799034253, (Float_t) -0.20256413484477, (Float_t) 0.17520704835522, (Float_t) 0.14728154134330, (Float_t) 0.02377945217615, (Float_t) 0.38952639978999, (Float_t) 0.15558449135573, (Float_t) -0.23313271880868, (Float_t) -0.25344790059353, (Float_t) -0.05246019024463, (Float_t) 0.01628462406333, (Float_t) -0.02505961724053, (Float_t) 0.06920467763959, (Float_t) 0.02442357316099, (Float_t) -0.03721611395801, (Float_t) 0.01818801111503, (Float_t) -0.00749618797172}, + {(Float_t) 0.53648789255105, (Float_t) -0.25049871956020, (Float_t) -0.42163034350696, (Float_t) -0.43193942311114, (Float_t) -0.00275953611929, (Float_t) -0.03424681017675, (Float_t) 0.04267842219415, (Float_t) -0.04678328784242, (Float_t) -0.10214864179676, (Float_t) 0.26408300200955, (Float_t) 0.14590772289388, (Float_t) 0.15113130533216, (Float_t) -0.02459864859345, (Float_t) -0.17556493366449, (Float_t) -0.11202315195388, (Float_t) -0.18823009262115, (Float_t) -0.04060034127000, (Float_t) 0.05477720428674, (Float_t) 0.04788665548180, (Float_t) 0.04704409688120, (Float_t) -0.02217936801134}, - {(const Float_t) 0.38524531015142, (const Float_t) -1.29708918404534, (const Float_t) -0.27682212062067, (const Float_t) 0.90399339674203, (const Float_t)-0.09980181488805, (const Float_t) -0.29613799017877, (const Float_t) 0.09951486755646, (const Float_t)-0.42326645916207, (const Float_t) -0.08934020156622, (const Float_t) 0.37934887402200, (const Float_t) -0.00322369330199, (const Float_t) -0.37919795944938, (const Float_t) -0.00110329090689, (const Float_t) 0.23410283284785, (const Float_t) 0.03784509844682, (const Float_t) -0.03892971758879, (const Float_t) 0.01683906213303, (const Float_t) 0.00403009552351, (const Float_t) -0.01147039862572, (const Float_t) 0.03640166626278, (const Float_t) -0.01941767987192 }, - {(const Float_t)0.08717879977844, (const Float_t)-2.62816311472146, (const Float_t)-0.01000374016172, (const Float_t)3.53734535817992, (const Float_t)-0.06265852122368, (const Float_t)-3.81003448678921, (const Float_t)-0.01119328800950, (const Float_t)3.91291636730132, (const Float_t)-0.00114279372960, (const Float_t)-3.53518605896288, (const Float_t)0.02081333954769, (const Float_t)2.71356866157873, (const Float_t)-0.01603261863207, (const Float_t)-1.86723311846592, (const Float_t)0.01936763028546, (const Float_t)1.12075382367659, (const Float_t)0.00760044736442, (const Float_t)-0.48574086886890, (const Float_t)-0.00303979112271, (const Float_t)0.11330544663849, (const Float_t)-0.00075088605788 }, + {(Float_t) 0.38524531015142, (Float_t) -1.29708918404534, (Float_t) -0.27682212062067, (Float_t) 0.90399339674203, (Float_t)-0.09980181488805, (Float_t) -0.29613799017877, (Float_t) 0.09951486755646, (Float_t)-0.42326645916207, (Float_t) -0.08934020156622, (Float_t) 0.37934887402200, (Float_t) -0.00322369330199, (Float_t) -0.37919795944938, (Float_t) -0.00110329090689, (Float_t) 0.23410283284785, (Float_t) 0.03784509844682, (Float_t) -0.03892971758879, (Float_t) 0.01683906213303, (Float_t) 0.00403009552351, (Float_t) -0.01147039862572, (Float_t) 0.03640166626278, (Float_t) -0.01941767987192 }, + {(Float_t)0.08717879977844, (Float_t)-2.62816311472146, (Float_t)-0.01000374016172, (Float_t)3.53734535817992, (Float_t)-0.06265852122368, (Float_t)-3.81003448678921, (Float_t)-0.01119328800950, (Float_t)3.91291636730132, (Float_t)-0.00114279372960, (Float_t)-3.53518605896288, (Float_t)0.02081333954769, (Float_t)2.71356866157873, (Float_t)-0.01603261863207, (Float_t)-1.86723311846592, (Float_t)0.01936763028546, (Float_t)1.12075382367659, (Float_t)0.00760044736442, (Float_t)-0.48574086886890, (Float_t)-0.00303979112271, (Float_t)0.11330544663849, (Float_t)-0.00075088605788 }, }; static const Float_t ABButter[][2 * BUTTER_ORDER + 1] = { - {(const Float_t) 0.99308203517541, (const Float_t) -1.98611621154089, (const Float_t) -1.98616407035082, (const Float_t) 0.986211929160751, (const Float_t) 0.99308203517541}, - {(const Float_t) 0.992472550461293, (const Float_t) -1.98488843762334, (const Float_t) -1.98494510092258, (const Float_t) 0.979389350028798, (const Float_t) 0.992472550461293}, - {(const Float_t) 0.989641019334721, (const Float_t) -1.97917472731008, (const Float_t) -1.97928203866944, (const Float_t) 0.979389350028798, (const Float_t) 0.989641019334721}, - {(const Float_t) 0.98621192462708, (const Float_t) -1.97223372919527, (const Float_t) -1.97242384925416, (const Float_t) 0.97261396931306, (const Float_t) 0.98621192462708}, - {(const Float_t) 0.98500175787242, (const Float_t) -1.96977855582618, (const Float_t) -1.97000351574484, (const Float_t) 0.97022847566350, (const Float_t) 0.98500175787242}, - {(const Float_t) 0.97938932735214, (const Float_t) -1.95835380975398, (const Float_t) -1.95877865470428, (const Float_t) 0.95920349965459, (const Float_t) 0.97938932735214}, - {(const Float_t) 0.97531843204928, (const Float_t) -1.95002759149878, (const Float_t) -1.95063686409857, (const Float_t) 0.95124613669835, (const Float_t) 0.97531843204928}, - {(const Float_t) 0.97316523498161, (const Float_t) -1.94561023566527, (const Float_t) -1.94633046996323, (const Float_t) 0.94705070426118, (const Float_t) 0.97316523498161}, - {(const Float_t) 0.96454515552826, (const Float_t) -1.92783286977036, (const Float_t) -1.92909031105652, (const Float_t) 0.93034775234268, (const Float_t) 0.96454515552826}, - {(const Float_t) 0.96009142950541, (const Float_t) -1.91858953033784, (const Float_t) -1.92018285901082, (const Float_t) 0.92177618768381, (const Float_t) 0.96009142950541}, - {(const Float_t) 0.95856916599601, (const Float_t) -1.91542108074780, (const Float_t) -1.91713833199203, (const Float_t) 0.91885558323625, (const Float_t) 0.95856916599601}, - {(const Float_t) 0.94597685600279, (const Float_t) -1.88903307939452, (const Float_t) -1.89195371200558, (const Float_t) 0.89487434461664, (const Float_t) 0.94597685600279}, + {(Float_t) 0.99308203517541, (Float_t) -1.98611621154089, (Float_t) -1.98616407035082, (Float_t) 0.986211929160751, (Float_t) 0.99308203517541}, + {(Float_t) 0.992472550461293, (Float_t) -1.98488843762334, (Float_t) -1.98494510092258, (Float_t) 0.979389350028798, (Float_t) 0.992472550461293}, + {(Float_t) 0.989641019334721, (Float_t) -1.97917472731008, (Float_t) -1.97928203866944, (Float_t) 0.979389350028798, (Float_t) 0.989641019334721}, + {(Float_t) 0.98621192462708, (Float_t) -1.97223372919527, (Float_t) -1.97242384925416, (Float_t) 0.97261396931306, (Float_t) 0.98621192462708}, + {(Float_t) 0.98500175787242, (Float_t) -1.96977855582618, (Float_t) -1.97000351574484, (Float_t) 0.97022847566350, (Float_t) 0.98500175787242}, + {(Float_t) 0.97938932735214, (Float_t) -1.95835380975398, (Float_t) -1.95877865470428, (Float_t) 0.95920349965459, (Float_t) 0.97938932735214}, + {(Float_t) 0.97531843204928, (Float_t) -1.95002759149878, (Float_t) -1.95063686409857, (Float_t) 0.95124613669835, (Float_t) 0.97531843204928}, + {(Float_t) 0.97316523498161, (Float_t) -1.94561023566527, (Float_t) -1.94633046996323, (Float_t) 0.94705070426118, (Float_t) 0.97316523498161}, + {(Float_t) 0.96454515552826, (Float_t) -1.92783286977036, (Float_t) -1.92909031105652, (Float_t) 0.93034775234268, (Float_t) 0.96454515552826}, + {(Float_t) 0.96009142950541, (Float_t) -1.91858953033784, (Float_t) -1.92018285901082, (Float_t) 0.92177618768381, (Float_t) 0.96009142950541}, + {(Float_t) 0.95856916599601, (Float_t) -1.91542108074780, (Float_t) -1.91713833199203, (Float_t) 0.91885558323625, (Float_t) 0.95856916599601}, + {(Float_t) 0.94597685600279, (Float_t) -1.88903307939452, (Float_t) -1.89195371200558, (Float_t) 0.89487434461664, (Float_t) 0.94597685600279}, - {(const Float_t)0.96535326815829, (const Float_t)-1.92950577983524, (const Float_t)-1.93070653631658, (const Float_t)0.93190729279793, (const Float_t)0.96535326815829 }, - {(const Float_t)0.98252400815195, (const Float_t)-1.96474258269041, (const Float_t)-1.96504801630391, (const Float_t)0.96535344991740, (const Float_t)0.98252400815195 }, + {(Float_t)0.96535326815829, (Float_t)-1.92950577983524, (Float_t)-1.93070653631658, (Float_t)0.93190729279793, (Float_t)0.96535326815829 }, + {(Float_t)0.98252400815195, (Float_t)-1.96474258269041, (Float_t)-1.96504801630391, (Float_t)0.96535344991740, (Float_t)0.98252400815195 }, }; diff --git a/src/common/thirdparty/rapidjson/document.h b/src/common/thirdparty/rapidjson/document.h index 7612801b5..9cab4e83d 100644 --- a/src/common/thirdparty/rapidjson/document.h +++ b/src/common/thirdparty/rapidjson/document.h @@ -1937,7 +1937,7 @@ private: if (count) { GenericValue* e = static_cast(allocator.Malloc(count * sizeof(GenericValue))); SetElementsPointer(e); - std::memcpy(e, values, count * sizeof(GenericValue)); + std::memcpy((void*)e, (void*)values, count * sizeof(GenericValue)); } else SetElementsPointer(0); @@ -1950,7 +1950,7 @@ private: if (count) { Member* m = static_cast(allocator.Malloc(count * sizeof(Member))); SetMembersPointer(m); - std::memcpy(m, members, count * sizeof(Member)); + std::memcpy((void*)m, (void*)members, count * sizeof(Member)); } else SetMembersPointer(0); diff --git a/src/common/thirdparty/strnatcmp.c b/src/common/thirdparty/strnatcmp.c index 58fa5571a..8caadfbd7 100644 --- a/src/common/thirdparty/strnatcmp.c +++ b/src/common/thirdparty/strnatcmp.c @@ -85,8 +85,6 @@ compare_right(nat_char const *a, nat_char const *b) } else if (!*a && !*b) return bias; } - - return 0; } @@ -107,8 +105,6 @@ compare_left(nat_char const *a, nat_char const *b) else if (*a > *b) return +1; } - - return 0; } diff --git a/src/common/utility/basics.h b/src/common/utility/basics.h index 29ee19593..8661372e9 100644 --- a/src/common/utility/basics.h +++ b/src/common/utility/basics.h @@ -38,6 +38,13 @@ typedef uint32_t angle_t; #define FORCE_PACKED #endif +// Todo: get rid of this. Static file name buffers suck. +#ifndef PATH_MAX +#define BMAX_PATH 256 +#else +#define BMAX_PATH PATH_MAX +#endif + #ifdef __GNUC__ #define GCCPRINTF(stri,firstargi) __attribute__((format(printf,stri,firstargi))) diff --git a/src/common/utility/cmdlib.cpp b/src/common/utility/cmdlib.cpp index b4fb3a479..0dd6f7750 100644 --- a/src/common/utility/cmdlib.cpp +++ b/src/common/utility/cmdlib.cpp @@ -248,7 +248,7 @@ bool GetFileInfo(const char* pathname, size_t *size, time_t *time) bool res = _wstat64(wstr.c_str(), &info) == 0; #endif if (!res || (info.st_mode & S_IFDIR)) return false; - if (size) *size = info.st_size; + if (size) *size = (size_t)info.st_size; if (time) *time = info.st_mtime; return res; } @@ -359,7 +359,7 @@ FString StripExtension(const char* path) src = path + strlen(path) - 1; // - // back up until a . and abort on a \ + // back up until a . and abort on a '/' // while (src != path && !IsSeperator(*(src - 1))) { @@ -557,7 +557,7 @@ void CreatePath(const char *fn) void CreatePath(const char *fn) { char *copy, *p; - + if (fn[0] == '/' && fn[1] == '\0') { return; diff --git a/src/common/utility/colormatcher.h b/src/common/utility/colormatcher.h index 6ec20879a..277505e81 100644 --- a/src/common/utility/colormatcher.h +++ b/src/common/utility/colormatcher.h @@ -58,7 +58,7 @@ public: return (uint8_t)BestColor ((uint32_t *)Pal, r, g, b, startindex, 255, indexmap); } - + uint8_t Pick (PalEntry pe) { return Pick(pe.r, pe.g, pe.b); diff --git a/src/common/utility/filereadermusicinterface.h b/src/common/utility/filereadermusicinterface.h index 70fc3b107..f261f9dd0 100644 --- a/src/common/utility/filereadermusicinterface.h +++ b/src/common/utility/filereadermusicinterface.h @@ -19,4 +19,5 @@ inline ZMusicCustomReader *GetMusicReader(FileReader& fr) delete zr; }; return zcr; -} \ No newline at end of file +} + diff --git a/src/common/utility/files_decompress.cpp b/src/common/utility/files_decompress.cpp index 7d7d65442..cd2e36ed7 100644 --- a/src/common/utility/files_decompress.cpp +++ b/src/common/utility/files_decompress.cpp @@ -107,7 +107,7 @@ class DecompressorZ : public DecompressorBase bool SawEOF; z_stream Stream; uint8_t InBuff[BUFF_SIZE]; - + public: DecompressorZ (FileReader *file, bool zip, const std::function& cb) : SawEOF(false) @@ -198,7 +198,7 @@ class DecompressorBZ2 : public DecompressorBase bool SawEOF; bz_stream Stream; uint8_t InBuff[BUFF_SIZE]; - + public: DecompressorBZ2 (FileReader *file, const std::function& cb) : SawEOF(false) @@ -627,7 +627,7 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, b case METHOD_LZSS: dec = new DecompressorLZSS(p, cb); break; - + // todo: METHOD_IMPLODE, METHOD_SHRINK default: return false; diff --git a/src/common/utility/findfile.cpp b/src/common/utility/findfile.cpp index 6006a34a1..bdfa865a8 100644 --- a/src/common/utility/findfile.cpp +++ b/src/common/utility/findfile.cpp @@ -128,7 +128,7 @@ int I_FindAttr(findstate_t *const fileinfo) } #else - + #include #include diff --git a/src/common/utility/findfile.h b/src/common/utility/findfile.h index 895bbde69..44bee1a35 100644 --- a/src/common/utility/findfile.h +++ b/src/common/utility/findfile.h @@ -43,7 +43,7 @@ inline const char *I_FindName(findstate_t *fileinfo) #else - + // Mirror WIN32_FIND_DATAW in struct findstate_t diff --git a/src/common/utility/i_time.cpp b/src/common/utility/i_time.cpp index cc8f5f1de..22516ed45 100644 --- a/src/common/utility/i_time.cpp +++ b/src/common/utility/i_time.cpp @@ -35,6 +35,7 @@ #include #include +#include #include "i_time.h" //========================================================================== @@ -46,6 +47,7 @@ static uint64_t FirstFrameStartTime; static uint64_t CurrentFrameStartTime; static uint64_t FreezeTime; +static double lastinputtime; int GameTicRate = 35; // make sure it is not 0, even if the client doesn't set it. double TimeScale = 1.0; @@ -195,3 +197,39 @@ void I_ResetFrameTime() I_SetFrameTime(); FirstFrameStartTime += (CurrentFrameStartTime - ft); } + +double I_GetInputFrac(bool const synchronised, double const ticrate) +{ + if (!synchronised) + { + const double max = 1000. / ticrate; + const double now = I_msTimeF(); + const double elapsedInputTicks = std::min(now - lastinputtime, max); + lastinputtime = now; + + if (elapsedInputTicks < max) + { + // Calculate an amplification to apply to the result before returning, + // factoring in the game's ticrate and the value of the result. + // This rectifies a deviation of 100+ ms or more depending on the length + // of the operation to be within 1-2 ms of synchronised input + // from 60 fps to at least 1000 fps at ticrates of 30 and 40 Hz. + const double result = elapsedInputTicks * ticrate * (1. / 1000.); + return result * (1. + 0.35 * (1. - ticrate * (1. / 50.)) * (1. - result)); + } + else + { + return 1; + } + } + else + { + return 1; + } +} + +void I_ResetInputTime() +{ + // Reset lastinputtime to current time. + lastinputtime = I_msTimeF(); +} diff --git a/src/common/utility/i_time.h b/src/common/utility/i_time.h index 27ebdae2a..dc0619c37 100644 --- a/src/common/utility/i_time.h +++ b/src/common/utility/i_time.h @@ -38,3 +38,9 @@ uint64_t I_nsTime(); // Reset the timer after a lengthy operation void I_ResetFrameTime(); + +// Return a decimal fraction to scale input operations at framerate +double I_GetInputFrac(bool const synchronised, double const ticrate = GameTicRate); + +// Reset the last input check to after a lengthy operation +void I_ResetInputTime(); diff --git a/src/common/utility/matrix.cpp b/src/common/utility/matrix.cpp index 006a5fe5d..476d09b60 100644 --- a/src/common/utility/matrix.cpp +++ b/src/common/utility/matrix.cpp @@ -58,7 +58,7 @@ VSMatrix::loadIdentity() void VSMatrix::multMatrix(const FLOATTYPE *aMatrix) { - + FLOATTYPE res[16]; for (int i = 0; i < 4; ++i) @@ -164,19 +164,19 @@ VSMatrix::rotate(FLOATTYPE angle, FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) mat[4] = v[0] * v[1] * (1 - co) - v[2] * si; mat[8] = v[0] * v[2] * (1 - co) + v[1] * si; mat[12]= 0.0f; - + mat[1] = v[0] * v[1] * (1 - co) + v[2] * si; // mat[5] = y2 + (x2 + z2) * co; mat[5] = co + y2 * (1 - co); mat[9] = v[1] * v[2] * (1 - co) - v[0] * si; mat[13]= 0.0f; - + mat[2] = v[0] * v[2] * (1 - co) - v[1] * si; mat[6] = v[1] * v[2] * (1 - co) + v[0] * si; // mat[10]= z2 + (x2 + y2) * co; mat[10]= co + z2 * (1 - co); mat[14]= 0.0f; - + mat[3] = 0.0f; mat[7] = 0.0f; mat[11]= 0.0f; @@ -323,9 +323,9 @@ VSMatrix::multMatrixPoint(const FLOATTYPE *point, FLOATTYPE *res) { res[i] = 0.0f; - + for (int j = 0; j < 4; j++) { - + res[i] += point[j] * mMatrix[j*4 + i]; } } @@ -444,7 +444,7 @@ VSMatrix::computeNormalMatrix(const FLOATTYPE *aMatrix) void VSMatrix::multMatrix(FLOATTYPE *resMat, const FLOATTYPE *aMatrix) { - + FLOATTYPE res[16]; for (int i = 0; i < 4; ++i) diff --git a/src/common/utility/matrix.h b/src/common/utility/matrix.h index 81d7be6f2..c1c7c873c 100644 --- a/src/common/utility/matrix.h +++ b/src/common/utility/matrix.h @@ -34,7 +34,7 @@ class VSMatrix { public: VSMatrix() = default; - + VSMatrix(int) { loadIdentity(); @@ -135,11 +135,11 @@ public: m[0][0] *=x; m[1][0] *=x; m[2][0] *=x; - + m[0][1] *=y; m[1][1] *=y; m[2][1] *=y; - + m[0][2] *=z; m[1][2] *=z; m[2][2] *=z; diff --git a/src/common/utility/memarena.cpp b/src/common/utility/memarena.cpp index 0e2be24ba..5439d7339 100644 --- a/src/common/utility/memarena.cpp +++ b/src/common/utility/memarena.cpp @@ -117,6 +117,14 @@ void *FMemArena::Alloc(size_t size) return iAlloc((size + 15) & ~15); } +void* FMemArena::Calloc(size_t size) +{ + size = (size + 15) & ~15; + auto mem = iAlloc(size); + memset(mem, 0, size); + return mem; +} + //========================================================================== // // FMemArena :: FreeAll diff --git a/src/common/utility/memarena.h b/src/common/utility/memarena.h index 7f4903546..bb7f60b9a 100644 --- a/src/common/utility/memarena.h +++ b/src/common/utility/memarena.h @@ -44,6 +44,7 @@ public: ~FMemArena(); void *Alloc(size_t size); + void* Calloc(size_t size); void FreeAll(); void FreeAllBlocks(); FString DumpInfo(); diff --git a/src/common/utility/name.cpp b/src/common/utility/name.cpp index b1355a020..c9960ca93 100644 --- a/src/common/utility/name.cpp +++ b/src/common/utility/name.cpp @@ -75,6 +75,9 @@ static const char *PredefinedNames[] = #define xx(n) #n, #define xy(n, s) s, #include "namedef.h" +#if __has_include("namedef_custom.h") + #include "namedef_custom.h" +#endif #undef xx #undef xy }; diff --git a/src/common/utility/name.h b/src/common/utility/name.h index de8984073..fe2424f45 100644 --- a/src/common/utility/name.h +++ b/src/common/utility/name.h @@ -42,6 +42,9 @@ enum ENamedName #define xx(n) NAME_##n, #define xy(n, s) NAME_##n, #include "namedef.h" +#if __has_include("namedef_custom.h") + #include "namedef_custom.h" +#endif #undef xx #undef xy }; diff --git a/src/common/utility/palentry.h b/src/common/utility/palentry.h index 6d6d5a86a..4acbbfff8 100644 --- a/src/common/utility/palentry.h +++ b/src/common/utility/palentry.h @@ -12,6 +12,7 @@ struct PalEntry { PalEntry() = default; + PalEntry(const PalEntry&) = default; constexpr PalEntry (uint32_t argb) : d(argb) { } operator uint32_t () const { return d; } void SetRGB(PalEntry other) diff --git a/src/common/utility/palette.cpp b/src/common/utility/palette.cpp index 28115a521..c1728a3ad 100644 --- a/src/common/utility/palette.cpp +++ b/src/common/utility/palette.cpp @@ -565,9 +565,9 @@ int V_GetColorFromString(const char* cstr, FScriptPosition* sc) { if (strlen(cstr) == 6) { - char* p; - int color = strtol(cstr, &p, 16); - if (*p == 0) + char* endp; + int color = strtol(cstr, &endp, 16); + if (*endp == 0) { // RRGGBB string c[0] = (color & 0xff0000) >> 16; @@ -903,7 +903,6 @@ int ReadPalette(int lumpnum, uint8_t* buffer) fr.Seek(33, FileReader::SeekSet); fr.Read(&len, 4); fr.Read(&id, 4); - bool succeeded = false; while (id != MAKE_ID('I', 'D', 'A', 'T') && id != MAKE_ID('I', 'E', 'N', 'D')) { len = BigLong((unsigned int)len); diff --git a/src/common/utility/r_memory.cpp b/src/common/utility/r_memory.cpp index 383cdbeb4..8ff821c38 100644 --- a/src/common/utility/r_memory.cpp +++ b/src/common/utility/r_memory.cpp @@ -28,7 +28,7 @@ void *RenderMemory::AllocBytes(int size) { size = (size + 15) / 16 * 16; // 16-byte align - + if (UsedBlocks.empty() || UsedBlocks.back()->Position + size > BlockSize) { if (!FreeBlocks.empty()) @@ -43,14 +43,14 @@ void *RenderMemory::AllocBytes(int size) UsedBlocks.push_back(std::unique_ptr(new MemoryBlock())); } } - + auto &block = UsedBlocks.back(); void *data = block->Data + block->Position; block->Position += size; return data; } - + void RenderMemory::Clear() { while (!UsedBlocks.empty()) diff --git a/src/common/utility/r_memory.h b/src/common/utility/r_memory.h index 8007b6cc1..d9db538ca 100644 --- a/src/common/utility/r_memory.h +++ b/src/common/utility/r_memory.h @@ -8,33 +8,33 @@ class RenderMemory { public: void Clear(); - + template T *AllocMemory(int size = 1) { return (T*)AllocBytes(sizeof(T) * size); } - + template T *NewObject(Types &&... args) { void *ptr = AllocBytes(sizeof(T)); return new (ptr)T(std::forward(args)...); } - + private: void *AllocBytes(int size); - + enum { BlockSize = 1024 * 1024 }; - + struct MemoryBlock { MemoryBlock(); ~MemoryBlock(); - + MemoryBlock(const MemoryBlock &) = delete; MemoryBlock &operator=(const MemoryBlock &) = delete; - + uint8_t *Data; uint32_t Position; }; diff --git a/src/common/utility/refcounted.h b/src/common/utility/refcounted.h index 81ea3fc6d..f8643f080 100644 --- a/src/common/utility/refcounted.h +++ b/src/common/utility/refcounted.h @@ -26,7 +26,7 @@ public: RefCountedPtr() : ptr(nullptr) {} - + explicit RefCountedPtr(T* p) : ptr(p) { if (ptr) ptr->IncRef(); @@ -52,7 +52,7 @@ public: } return *this; } - + RefCountedPtr& operator=(T* r) { if (ptr != r) @@ -99,18 +99,18 @@ public: { return *ptr; } - + T* operator-> () const { return ptr; } - + T* get() const { return ptr; } - + private: - + T * ptr; }; \ No newline at end of file diff --git a/src/common/utility/tarray.h b/src/common/utility/tarray.h index 10a164959..a8742a96b 100644 --- a/src/common/utility/tarray.h +++ b/src/common/utility/tarray.h @@ -105,6 +105,17 @@ protected: T* m_ptr; }; +// magic little helper. :) +template +class backwards +{ + T& _obj; +public: + backwards(T &obj) : _obj(obj) {} + auto begin() {return _obj.rbegin();} + auto end() {return _obj.rend();} +}; + // TArray ------------------------------------------------------------------- @@ -154,7 +165,7 @@ public: { return &Array[Count]; } - + reverse_iterator rbegin() { return reverse_iterator(end()); @@ -308,6 +319,16 @@ public: return &Array[0]; } + unsigned IndexOf(const T& elem) const + { + return &elem - Array; + } + + unsigned IndexOf(const T* elem) const + { + return elem - Array; + } + unsigned int Find(const T& item) const { unsigned int i; @@ -898,7 +919,7 @@ public: LastFree = o.LastFree; /* any free position is before this position */ Size = o.Size; /* must be a power of 2 */ NumUsed = o.NumUsed; - + o.Size = 0; o.NumUsed = 0; o.SetNodeVector(1); @@ -1672,6 +1693,12 @@ public: return !!(bytes[index >> 3] & (1 << (index & 7))); } + // for when array syntax cannot be used. + bool Check(size_t index) const + { + return !!(bytes[index >> 3] & (1 << (index & 7))); + } + void Set(size_t index, bool set = true) { if (!set) Clear(index); @@ -1850,18 +1877,20 @@ public: // Return a reference to an element T &operator[] (size_t index) const { + assert(index < Count); return Array[index]; } // Returns a reference to the last element T &Last() const { + assert(Count > 0); return Array[Count - 1]; } // returns address of first element T *Data() const { - return &Array[0]; + return Array; } unsigned Size() const @@ -1896,202 +1925,3 @@ private: unsigned int Count; }; - -template class TSparseIterator -{ -public: - using iterator_category = std::random_access_iterator_tag; - using value_type = T; - using difference_type = ptrdiff_t; - using pointer = value_type*; - using reference = value_type&; - - TSparseIterator(unsigned char* ptr = nullptr, unsigned stride = 0) { m_Ptr = ptr; Stride = stride; } - - // Comparison operators - bool operator==(const TSparseIterator &other) const { return m_Ptr == other.m_Ptr; } - bool operator!=(const TSparseIterator &other) const { return m_Ptr != other.m_Ptr; } - bool operator< (const TSparseIterator &other) const { return m_Ptr < other.m_Ptr; } - bool operator<=(const TSparseIterator &other) const { return m_Ptr <= other.m_Ptr; } - bool operator> (const TSparseIterator &other) const { return m_Ptr > other.m_Ptr; } - bool operator>=(const TSparseIterator &other) const { return m_Ptr >= other.m_Ptr; } - - // Arithmetic operators - TSparseIterator &operator++() { m_Ptr += Stride; return *this; } - TSparseIterator operator++(int) { auto tmp = *this; ++*this; return tmp; } - TSparseIterator &operator--() { m_Ptr -= Stride; return *this; } - TSparseIterator operator--(int) { auto tmp = *this; --*this; return tmp; } - TSparseIterator &operator+=(difference_type offset) { m_Ptr += offset * Stride; return *this; } - TSparseIterator operator+(difference_type offset) const { return TSparseIterator(m_Ptr + offset * Stride, Stride); } - friend TSparseIterator operator+(difference_type offset, const TSparseIterator &other) { return TSparseIterator(offset*other.Stride + other.m_Ptr, other.Stride); } - TSparseIterator &operator-=(difference_type offset) { m_Ptr -= offset * Stride; return *this; } - TSparseIterator operator-(difference_type offset) const { return TSparseIterator(m_Ptr - offset * Stride, Stride); } - difference_type operator-(const TSparseIterator &other) const { return (m_Ptr - other.m_Ptr) / Stride; } - - // Random access operators - T& operator[](difference_type i) { return *(T*)(m_Ptr + i * Stride); } - const T& operator[](difference_type i) const { return *(T*)(m_Ptr + i * Stride); } - - T &operator*() const { return (T*)m_Ptr; } - T* operator->() { return (T*)m_Ptr; } - -protected: - unsigned char* m_Ptr; - unsigned Stride; -}; - -// A wrapper to externally stored data. -// Like the above but with a customizable stride -template -class TSparseArrayView -{ -public: - - typedef TSparseIterator iterator; - typedef TSparseIterator const_iterator; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - typedef T value_type; - - iterator begin() - { - return iterator(Array, Stride); - } - const_iterator begin() const - { - return const_iterator(Array, Stride); - } - const_iterator cbegin() const - { - return const_iterator(Array, Stride); - } - - iterator end() - { - return iterator(Array + Count * Stride, Stride); - } - const_iterator end() const - { - return const_iterator(Array + Count * Stride, Stride); - } - const_iterator cend() const - { - return const_iterator(Array + Count * Stride, Stride); - } - - reverse_iterator rbegin() - { - return reverse_iterator(end()); - } - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(end()); - } - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(cend()); - } - - reverse_iterator rend() - { - return reverse_iterator(begin()); - } - const_reverse_iterator rend() const - { - return const_reverse_iterator(begin()); - } - const_reverse_iterator crend() const - { - return const_reverse_iterator(cbegin()); - } - - //////// - TSparseArrayView() = default; // intended to keep this type trivial. - TSparseArrayView(T *data, unsigned stride, unsigned count = 0) - { - Count = count; - Array = data; - Stride = stride; - } - TSparseArrayView(const TSparseArrayView &other) = default; - TSparseArrayView &operator= (const TSparseArrayView &other) = default; - - // Check equality of two arrays - bool operator==(const TArrayView &other) const - { - if (Count != other.Count) - { - return false; - } - for (unsigned int i = 0; i < Count; ++i) - { - if (Element(i) != other.Element(i)) - { - return false; - } - } - return true; - } - - T &Element(size_t index) - { - return (T*)Array[index*Stride]; - } - // Return a reference to an element - T &operator[] (size_t index) const - { - return Element(index); - } - // Returns a reference to the last element - T &Last() const - { - return Element(Count - 1); - } - - // returns address of first element - T *Data() const - { - return &Element(0); - } - - unsigned Size() const - { - return Count; - } - - unsigned int Find(const T& item) const - { - unsigned int i; - for (i = 0; i < Count; ++i) - { - if (Element(i) == item) - break; - } - return i; - } - - void Set(T *data, unsigned stride, unsigned count) - { - Array = reinterpret_cast(data); - Count = count; - Stride = stride; - } - - void Set(void *data, unsigned stride, unsigned count) - { - Array = reinterpret_cast(data); - Count = count; - Stride = stride; - } - - void Clear() - { - Count = 0; - Stride = 0; - Array = nullptr; - } -private: - unsigned char* Array; - unsigned int Count; - unsigned int Stride; -}; diff --git a/src/common/utility/tflags.h b/src/common/utility/tflags.h index 98516fce8..f872d4574 100644 --- a/src/common/utility/tflags.h +++ b/src/common/utility/tflags.h @@ -53,42 +53,42 @@ public: TFlags() = default; TFlags(const Self& other) = default; - TFlags (T value) : Value (static_cast (value)) {} + constexpr TFlags (T value) : Value (static_cast (value)) {} // This allows initializing the flagset with 0, as 0 implicitly converts into a null pointer. - TFlags (ZeroDummy*) : Value (0) {} + constexpr TFlags (ZeroDummy*) : Value (0) {} // Relation operators - Self operator| (Self other) const { return Self::FromInt (Value | other.GetValue()); } - Self operator& (Self other) const { return Self::FromInt (Value & other.GetValue()); } - Self operator^ (Self other) const { return Self::FromInt (Value ^ other.GetValue()); } - Self operator| (T value) const { return Self::FromInt (Value | value); } - Self operator& (T value) const { return Self::FromInt (Value & value); } - Self operator^ (T value) const { return Self::FromInt (Value ^ value); } - Self operator~() const { return Self::FromInt (~Value); } + constexpr Self operator| (const Self& other) const { return Self::FromInt (Value | other.GetValue()); } + constexpr Self operator& (const Self& other) const { return Self::FromInt (Value & other.GetValue()); } + constexpr Self operator^ (const Self& other) const { return Self::FromInt (Value ^ other.GetValue()); } + constexpr Self operator| (T value) const { return Self::FromInt (Value | value); } + constexpr Self operator& (T value) const { return Self::FromInt (Value & value); } + constexpr Self operator^ (T value) const { return Self::FromInt (Value ^ value); } + constexpr Self operator~() const { return Self::FromInt (~Value); } // Assignment operators - Self& operator= (Self other) { Value = other.GetValue(); return *this; } - Self& operator|= (Self other) { Value |= other.GetValue(); return *this; } - Self& operator&= (Self other) { Value &= other.GetValue(); return *this; } - Self& operator^= (Self other) { Value ^= other.GetValue(); return *this; } - Self& operator= (T value) { Value = value; return *this; } - Self& operator|= (T value) { Value |= value; return *this; } - Self& operator&= (T value) { Value &= value; return *this; } - Self& operator^= (T value) { Value ^= value; return *this; } + constexpr Self& operator= (const Self& other) = default; + constexpr Self& operator|= (const Self& other) { Value |= other.GetValue(); return *this; } + constexpr Self& operator&= (const Self& other) { Value &= other.GetValue(); return *this; } + constexpr Self& operator^= (const Self& other) { Value ^= other.GetValue(); return *this; } + constexpr Self& operator= (T value) { Value = value; return *this; } + constexpr Self& operator|= (T value) { Value |= value; return *this; } + constexpr Self& operator&= (T value) { Value &= value; return *this; } + constexpr Self& operator^= (T value) { Value ^= value; return *this; } // Access the value of the flagset - TT GetValue() const { return Value; } - operator TT() const { return Value; } + constexpr TT GetValue() const { return Value; } + constexpr operator TT() const { return Value; } // Set the value of the flagset manually with an integer. // Please think twice before using this. - static Self FromInt (TT value) { return Self (static_cast (value)); } + static constexpr Self FromInt (TT value) { return Self (static_cast (value)); } private: - template Self operator| (X value) const { return Self::FromInt (Value | value); } - template Self operator& (X value) const { return Self::FromInt (Value & value); } - template Self operator^ (X value) const { return Self::FromInt (Value ^ value); } + template constexpr Self operator| (X value) const { return Self::FromInt (Value | value); } + template constexpr Self operator& (X value) const { return Self::FromInt (Value & value); } + template constexpr Self operator^ (X value) const { return Self::FromInt (Value ^ value); } public: // to be removed. TT Value; @@ -98,11 +98,11 @@ public: // to be removed. * Additional operators for TFlags types. */ #define DEFINE_TFLAGS_OPERATORS(T) \ -inline T operator| (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) | T::IntType (b)); } \ -inline T operator& (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) & T::IntType (b)); } \ -inline T operator^ (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) ^ T::IntType (b)); } \ -inline T operator| (T::EnumType a, T b) { return T::FromInt (T::IntType (a) | T::IntType (b)); } \ -inline T operator& (T::EnumType a, T b) { return T::FromInt (T::IntType (a) & T::IntType (b)); } \ -inline T operator^ (T::EnumType a, T b) { return T::FromInt (T::IntType (a) ^ T::IntType (b)); } \ -inline T operator~ (T::EnumType a) { return T::FromInt (~T::IntType (a)); } +constexpr inline T operator| (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) | T::IntType (b)); } \ +constexpr inline T operator& (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) & T::IntType (b)); } \ +constexpr inline T operator^ (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) ^ T::IntType (b)); } \ +constexpr inline T operator| (T::EnumType a, T b) { return T::FromInt (T::IntType (a) | T::IntType (b)); } \ +constexpr inline T operator& (T::EnumType a, T b) { return T::FromInt (T::IntType (a) & T::IntType (b)); } \ +constexpr inline T operator^ (T::EnumType a, T b) { return T::FromInt (T::IntType (a) ^ T::IntType (b)); } \ +constexpr inline T operator~ (T::EnumType a) { return T::FromInt (~T::IntType (a)); } diff --git a/src/common/utility/utf8.cpp b/src/common/utility/utf8.cpp index b0b225ae5..5ca3506ef 100644 --- a/src/common/utility/utf8.cpp +++ b/src/common/utility/utf8.cpp @@ -124,7 +124,7 @@ int utf8_decode(const uint8_t *src, int *size) } return -1; } - + int c3 = src[3]; if (c3 < 0x80 || c1 >= 0xc0) return -1; c3 &= 0x3f; @@ -200,7 +200,7 @@ int GetCharFromString(const uint8_t *&string) if (z < 192) { string++; - + // Handle Windows 1252 characters if (z >= 128 && z < 160) { @@ -353,7 +353,7 @@ int getAlternative(int code) { default: return code; - + case '{': return '('; case '}': return ')'; case 0x17f: return 's'; // The 'long s' can be safely remapped to the regular variant, not that this gets used in any real text... @@ -428,7 +428,6 @@ int getAlternative(int code) case 0x457: return 0xef; case 0x458: return 'j'; } - return code; } //========================================================================== diff --git a/src/common/utility/vectors.h b/src/common/utility/vectors.h index 2118a22fa..1e5fa9f3a 100644 --- a/src/common/utility/vectors.h +++ b/src/common/utility/vectors.h @@ -1651,6 +1651,12 @@ public: m_d = d; } + void Init(const FVector3& p1, const FVector3& p2, const FVector3& p3) + { + m_normal = ((p2 - p1) ^ (p3 - p1)).Unit(); + m_d = -(p3 |m_normal); + } + // same for a play-vector. Note that y and z are inversed. void Set(DVector3 normal, double d) { @@ -1671,7 +1677,7 @@ public: return DistToPoint(x, y, z) < 0.f; } - bool PointOnSide(FVector3 &v) { return PointOnSide(v.X, v.Y, v.Z); } + bool PointOnSide(const FVector3 &v) { return PointOnSide(v.X, v.Y, v.Z); } float A() { return m_normal.X; } float B() { return m_normal.Y; } @@ -1684,4 +1690,5 @@ protected: float m_d; }; + #endif diff --git a/src/common/utility/x86.cpp b/src/common/utility/x86.cpp index 3312ff043..76e880834 100644 --- a/src/common/utility/x86.cpp +++ b/src/common/utility/x86.cpp @@ -164,7 +164,7 @@ void CheckCPUID(CPUInfo *cpu) FString DumpCPUInfo(const CPUInfo *cpu) { char cpustring[4*4*3+1]; - + // Why does Intel right-justify this string (on P4s) // or add extra spaces (on Cores)? const char *f = cpu->CPUString; diff --git a/src/common/utility/zstrformat.cpp b/src/common/utility/zstrformat.cpp index bf61ce282..0d8bcfbc2 100644 --- a/src/common/utility/zstrformat.cpp +++ b/src/common/utility/zstrformat.cpp @@ -318,9 +318,9 @@ namespace StringFormat */ const char *decimal_point = ".";/* locale specific decimal point */ int signflag; /* true if float is negative */ - int expt; /* integer value of exponent */ + int expt = 0; /* integer value of exponent */ char expchar = 'e'; /* exponent character: [eEpP\0] */ - char *dtoaend; /* pointer to end of converted digits */ + char* dtoaend = nullptr; /* pointer to end of converted digits */ int expsize = 0; /* character count for expstr */ int ndig = 0; /* actual number of digits returned by dtoa */ char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */ diff --git a/src/d_main.cpp b/src/d_main.cpp index efa8ca878..4f0c26465 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -128,6 +128,7 @@ EXTERN_CVAR(Int, vr_mode) EXTERN_CVAR(Bool, cl_customizeinvulmap) EXTERN_CVAR(Bool, log_vgafont) EXTERN_CVAR(Bool, dlg_vgafont) +CVAR(Int, vid_renderer, 1, 0) // for some stupid mods which threw caution out of the window... void DrawHUD(); void D_DoAnonStats(); diff --git a/src/g_game.cpp b/src/g_game.cpp index dac60dbf3..10b4ee4c0 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1316,15 +1316,6 @@ void G_Ticker () default: break; } - // Do some more aggressive GC maintenance when the game ticker is inactive. - if ((gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) || paused || P_CheckTickerPaused()) - { - size_t ac = max(10, GC::AllocCount); - for (size_t i = 0; i < ac; i++) - { - if (!GC::CheckGC()) break; - } - } // [MK] Additional ticker for UI events right after all others primaryLevel->localEventManager->PostUiTick(); @@ -3140,3 +3131,4 @@ DEFINE_GLOBAL(demoplayback) DEFINE_GLOBAL(automapactive); DEFINE_GLOBAL(Net_Arbitrator); DEFINE_GLOBAL(netgame); +DEFINE_GLOBAL(paused); diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index 8dd52cf95..7ed171374 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -184,7 +184,7 @@ struct MBFParamState int GetSoundArg(int i, int def = 0) { int num = argsused & (1 << i) ? (int)args[i] : def; - if (num > 0 && num < int(SoundMap.Size())) return SoundMap[num]; + if (num > 0 && num <= int(SoundMap.Size())) return SoundMap[num-1]; return 0; } @@ -237,6 +237,7 @@ static AmmoPerAttack AmmoPerAttacks[] = { { NAME_A_FireBFG, -1}, // uses deh.BFGCells { NAME_A_FireOldBFG, 1}, { NAME_A_FireRailgun, 1}, + { NAME_A_ConsumeAmmo, 1}, // MBF21 { NAME_None, 0} }; @@ -886,12 +887,12 @@ static void CreateWeaponBulletAttackFunc(FunctionCallEmitter &emitters, int valu static void CreateWeaponMeleeAttackFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state) { - state->ValidateArgCount(5, "A_WeaponBulletAttack"); + state->ValidateArgCount(5, "A_WeaponMeleeAttack"); emitters.AddParameterIntConst(state->GetIntArg(0, 2)); emitters.AddParameterIntConst(state->GetIntArg(1, 10)); emitters.AddParameterFloatConst(state->GetFloatArg(2, 1)); - emitters.AddParameterIntConst(state->GetIntArg(3)); - emitters.AddParameterIntConst(state->GetIntArg(4)); + emitters.AddParameterIntConst(state->GetSoundArg(3)); + emitters.AddParameterFloatConst(state->GetFloatArg(4)); } static void CreateWeaponSoundFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state) @@ -2059,60 +2060,54 @@ static int PatchWeapon (int weapNum) { int val = atoi (Line2); - if (strlen (Line1) >= 9) + size_t len = strlen(Line1); + if (len > 6 && stricmp (Line1 + len - 6, " frame") == 0) { - if (stricmp (Line1 + strlen (Line1) - 6, " frame") == 0) + FState *state = FindState (val); + + if (type != nullptr && !patchedStates) { - FState *state = FindState (val); - - if (type != NULL && !patchedStates) - { - statedef.MakeStateDefines(type); - patchedStates = true; - } - - if (strnicmp (Line1, "Deselect", 8) == 0) - statedef.SetStateLabel("Select", state); - else if (strnicmp (Line1, "Select", 6) == 0) - statedef.SetStateLabel("Deselect", state); - else if (strnicmp (Line1, "Bobbing", 7) == 0) - statedef.SetStateLabel("Ready", state); - else if (strnicmp (Line1, "Shooting", 8) == 0) - statedef.SetStateLabel("Fire", state); - else if (strnicmp (Line1, "Firing", 6) == 0) - statedef.SetStateLabel("Flash", state); + statedef.MakeStateDefines(type); + patchedStates = true; } - else if (stricmp (Line1, "Ammo type") == 0) + + if (strnicmp (Line1, "Deselect", 8) == 0) + statedef.SetStateLabel("Select", state); + else if (strnicmp (Line1, "Select", 6) == 0) + statedef.SetStateLabel("Deselect", state); + else if (strnicmp (Line1, "Bobbing", 7) == 0) + statedef.SetStateLabel("Ready", state); + else if (strnicmp (Line1, "Shooting", 8) == 0) + statedef.SetStateLabel("Fire", state); + else if (strnicmp (Line1, "Firing", 6) == 0) + statedef.SetStateLabel("Flash", state); + } + else if (stricmp (Line1, "Ammo type") == 0) + { + if (val < 0 || val >= 12 || (unsigned)val >= AmmoNames.Size()) { - if (val < 0 || val >= 12 || (unsigned)val >= AmmoNames.Size()) + val = 5; + } + if (info) + { + auto &AmmoType = info->PointerVar(NAME_AmmoType1); + AmmoType = AmmoNames[val]; + if (AmmoType != nullptr) { - val = 5; - } - if (info) - { - auto &AmmoType = info->PointerVar(NAME_AmmoType1); - AmmoType = AmmoNames[val]; - if (AmmoType != nullptr) + info->IntVar(NAME_AmmoGive1) = GetDefaultByType(AmmoType)->IntVar(NAME_Amount) * 2; + auto &AmmoUse = info->IntVar(NAME_AmmoUse1); + if (AmmoUse == 0) { - info->IntVar(NAME_AmmoGive1) = GetDefaultByType(AmmoType)->IntVar(NAME_Amount) * 2; - auto &AmmoUse = info->IntVar(NAME_AmmoUse1); - if (AmmoUse == 0) - { - AmmoUse = 1; - } + AmmoUse = 1; } } } - else - { - Printf (unknown_str, Line1, "Weapon", weapNum); - } } else if (stricmp (Line1, "Decal") == 0) { stripwhite (Line2); const FDecalTemplate *decal = DecalLibrary.GetDecalByName (Line2); - if (decal != NULL) + if (decal != nullptr) { if (info) info->DecalGenerator = const_cast (decal); } diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index 7ab94f58f..854512ec4 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -781,7 +781,6 @@ public: bool IsLinked(sector_t *other, bool ceiling) const; - sector_t *NextSpecialSector (int type, sector_t *prev) const; // [RH] void RemoveForceField(); int Index() const { return sectornum; } @@ -1726,6 +1725,8 @@ int GetCeilingLight(const sector_t *); double GetFriction(const sector_t *self, int plane, double *movefac); double HighestCeilingAt(sector_t *sec, double x, double y, sector_t **resultsec = nullptr); double LowestFloorAt(sector_t *sec, double x, double y, sector_t **resultsec = nullptr); +sector_t* P_NextSpecialSector(sector_t* sect, int type, sector_t* prev); +sector_t* P_NextSpecialSectorVC(sector_t* sect, int type); // uses validcount inline void sector_t::RemoveForceField() { return ::RemoveForceField(this); } inline bool sector_t::PlaneMoving(int pos) { return !!::PlaneMoving(this, pos); } diff --git a/src/gamedata/textures/animations.cpp b/src/gamedata/textures/animations.cpp index 55dcf060c..dd963cc90 100644 --- a/src/gamedata/textures/animations.cpp +++ b/src/gamedata/textures/animations.cpp @@ -455,6 +455,17 @@ void FTextureAnimator::ParseAnim (FScanner &sc, ETextureType usetype) defined = 1; ani = ParseRangeAnim (sc, picnum, usetype, missing); } + else if (sc.Compare("notrim")) + { + if (picnum.isValid()) + { + auto tex = TexMan.GetGameTexture(picnum); + + if (tex) tex->SetNoTrimming(true); + else sc.ScriptError("NoTrim: %s not found", sc.String); + } + else sc.ScriptError("NoTrim: %s is not a sprite", sc.String); + } else if (sc.Compare ("pic")) { if (defined == 1) diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index 14174a8cd..a0ef9991b 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -59,6 +59,7 @@ #include +#include // needed for std::floor on mac #include "maploader.h" #include "c_cvars.h" #include "actor.h" diff --git a/src/maploader/specials.cpp b/src/maploader/specials.cpp index b0a076131..64127bbab 100644 --- a/src/maploader/specials.cpp +++ b/src/maploader/specials.cpp @@ -1414,9 +1414,9 @@ void MapLoader::SpawnScrollers() else { auto it = Level->GetLineIdIterator(l->args[1]); - while (int ln = it.Next()) + while ((s = it.Next()) >= 0) { - Level->CreateThinker(EScroll::sc_side, dx, dy, control, nullptr, Level->lines[ln].sidedef[0], accel, SCROLLTYPE(l->args[0])); + Level->CreateThinker(EScroll::sc_side, dx, dy, control, nullptr, Level->lines[s].sidedef[0], accel, SCROLLTYPE(l->args[0])); } } break; diff --git a/src/namedef_custom.h b/src/namedef_custom.h new file mode 100644 index 000000000..1c188007c --- /dev/null +++ b/src/namedef_custom.h @@ -0,0 +1,861 @@ +// GZDoom specific names + +xx(Doom) +xx(Heretic) +xx(Hexen) +xx(Strife) +xx(Raven) + +// blood spawning +xx(Blood) +xx(BloodSplatter) +xx(AxeBlood) +xx(Spray) + +// Invulnerability types +xx(Ghost) +xx(Reflective) + +// Iron Feet types +//xx(Normal) // defined below +xx(Full) + +// Invisibility types +xx(Additive) +xx(Fuzzy) +xx(Stencil) +xx(AddStencil) + +// Healingradius types +xx(Mana) +xx(Armor) + +// Per-actor sound channels (for deprecated PlaySoundEx function) +xx(Auto) +xx(Weapon) +xx(Voice) +xx(Item) +xx(Body) +xx(SoundSlot5) +xx(SoundSlot6) +xx(SoundSlot7) + + +// Hexen sound sequence names +xx(Platform) +xx(PlatformMetal) +xx(Silence) +xx(Lava) +xx(Water) +xx(Ice) +xx(Earth) +xx(PlatformMetal2) +xx(DoorNormal) +xx(DoorHeavy) +xx(DoorMetal) +xx(DoorCreak) +xx(DoorMetal2) +xx(Wind) + +xx(PointPusher) +xx(PointPuller) + +xx(UpperStackLookOnly) +xx(LowerStackLookOnly) +xx(StackPoint) +xx(SkyCamCompat) + +xx(BasicArmorBonus) +xx(BasicArmorPickup) +xx(SaveAmount) +xx(SavePercent) +xx(MaxAbsorb) +xx(MaxFullAbsorb) +xx(MaxAmount) +xx(ActualSaveAmount) +xx(ArmorType) +xx(HexenArmor) +xx(Slots) +xx(SlotsIncrement) +xx(InterHubAmount) +xx(Icon) +xx(AltHUDIcon) +xx(PickupFlash) + +xx(BulletPuff) +xx(StrifePuff) +xx(MaulerPuff) + +// Special bosses A_BossDeath knows about +xx(Fatso) +xx(Arachnotron) +xx(BaronOfHell) +xx(Cyberdemon) +xx(SpiderMastermind) +xx(Ironlich) +xx(Minotaur) +xx(Sorcerer2) + +// Bots check this +xx(Megasphere) +xx(MegasphereHealth) + +// Standard player classes +xx(DoomPlayer) +xx(HereticPlayer) +xx(StrifePlayer) +xx(FighterPlayer) +xx(ClericPlayer) +xx(MagePlayer) +xx(ChexPlayer) +xx(ChickenPlayer) +xx(PigPlayer) + +// Flechette names for the different Hexen player classes +xx(ArtiPoisonBag1) +xx(ArtiPoisonBag2) +xx(ArtiPoisonBag3) + +// Strife quests +xx(QuestItem) +xx(Sigil) +xx(GiveSigilPiece) +xx(SetWeapon) +xx(SetSprite) + +// Armor +xx(BasicArmor) + +// Doom ammo types +xx(Clip) + +xx(PuzzleItem) +xx(PuzzleItemNumber) +xx(HealthPickup) +xx(autousemode) +xx(Ammo) +xx(WeaponGiver) +xx(DehackedPickup) +xx(PowerTargeter) +xx(PowerInvulnerable) +xx(PowerStrength) +xx(PowerInvisibility) +xx(PowerIronFeet) +xx(PowerLightAmp) +xx(PowerWeaponLevel2) +xx(PowerFlight) +xx(PowerSpeed) +xx(PowerTorch) +xx(PowerHighJump) +xx(PowerReflection) +xx(PowerDrain) +xx(Reflection) +xx(CustomInventory) +xx(Inventory) +xx(StateProvider) +xx(CallTryPickup) +xx(QuestItem25) +xx(QuestItem28) +xx(PowerDoubleFiringSpeed) +xx(PowerInfiniteAmmo) +xx(PowerBuddha) + +xx(TeleportDest) +xx(TeleportDest2) + + +xx(Fist) +//xx(Berserk) +xx(Chainsaw) +xx(Pistol) +xx(Shotgun) +xx(SSG) +xx(Chaingun) +xx(Rocket) +xx(Plasma) +xx(BFG) +//xx(Railgun) +xx(Dagger) + +// Damage types +//xx(Fire) already defined above +//xx(Ice) +//xx(Disintegrate) +xx(Drowning) +xx(Slime) +//xx(Crush) +xx(Telefrag) +xx(Falling) +xx(Suicide) +xx(Exit) +xx(Railgun) +xx(Poison) +xx(Electric) +xx(BFGSplash) +xx(DrainLife) // A weapon like the Sigil that drains your life away. +xx(Massacre) // For death by a cheater! +//(Melee) already defined above, so don't define it again +xx(InstantDeath) // Strife "instant death" +xx(PoisonCloud) // makes monsters howl. +xx(Hitscan) // for normal guns and the like +xx(Quake) + +// Special death name for getting killed excessively. Could be used as +// a damage type if you wanted to force an extreme death. +xx(Extreme) +xx(MDK) +xx(Cast) // 'damage type' for the cast call + +// Various actor names which are used internally +xx(MapSpot) +xx(PatrolPoint) +xx(PatrolSpecial) +xx(Communicator) +xx(PowerScanner) + +xx(DeathmatchStatusScreen) +xx(CoopStatusScreen) +xx(DoomStatusScreen) +xx(RavenStatusScreen) +xx(DoomStatusScreenSized) +xx(RavenStatusScreenSized) + +xx(Owner) +xx(FlameThrower) + +// Dehacked +xx(A_Punch) +xx(A_FirePistol) +xx(A_FireShotgun) +xx(A_FireShotgun2) +xx(A_FireCGun) +xx(A_FireMissile) +xx(A_Saw) +xx(A_FirePlasma) +xx(A_FireBFG) +xx(A_FireOldBFG) +xx(A_FireRailgun) +xx(A_ConsumeAmmo) + +// Special translation names +xx(RainPillar1) +xx(RainPillar2) +xx(RainPillar3) +xx(RainPillar4) +xx(RainPillar5) +xx(RainPillar6) +xx(RainPillar7) +xx(RainPillar8) + +xx(Player1) +xx(Player2) +xx(Player3) +xx(Player4) +xx(Player5) +xx(Player6) +xx(Player7) +xx(Player8) +xx(PlayerChunk) +xx(RestrictedToPlayerClass) +xx(ForbiddenToPlayerClass) + +// Weapon member fields that need direct access +xx(Ammo1) +xx(Ammo2) +xx(AmmoType1) +xx(AmmoType2) +xx(AmmoGive1) +xx(AmmoGive2) +xx(AmmoUse1) +xx(SisterWeapon) +xx(BobStyle) +xx(Kickback) +xx(MinSelAmmo1) +xx(bDehAmmo) +xx(FOVScale) +xx(LookScale) +xx(YAdjust) +xx(Crosshair) +xx(WeaponFlags) +xx(DropTime) +xx(PickupSound) + +// PlayerPawn member fields +xx(ColorRangeStart) +xx(ColorRangeEnd) +xx(InvFirst) +xx(ForwardMove1) +xx(ForwardMove2) +xx(SideMove1) +xx(SideMove2) +xx(Face) +xx(Slot) +xx(SoundClass) +xx(ViewBob) +xx(DamageFade) +xx(MaxHealth) +xx(crouchsprite) +xx(UseRange) +xx(AttackZOffset) +xx(SpawnMask) +xx(ScoreIcon) +xx(ViewHeight) +xx(ViewAngle) +xx(ViewPitch) +xx(ViewRoll) +xx(FallingScreamMinSpeed) +xx(FallingScreamMaxSpeed) +xx(GruntSpeed) +xx(JumpZ) +xx(MugShotMaxHealth) +xx(BonusHealth) +xx(PlayerFlags) +xx(InvSel) +xx(FullHeight) + +xx(BlueCard) +xx(YellowCard) +xx(RedCard) +xx(BlueSkull) +xx(YellowSkull) +xx(RedSkull) +xx(DynamicLight) +xx(SpotInnerAngle) +xx(SpotOuterAngle) +xx(lightflags) +xx(lighttype) +xx(InternalDynamicLight) +xx(_a_chase_default) +xx(MapMarker) +xx(Spawn2) +xx(LevelLocals) +xx(Level) +xx(PlayerTeam) +xx(PlayerColors) +xx(PlayerSkin) +xx(NewPlayerMenu) +xx(AltHud) +xx(GameScreen) +xx(ListM) + +// Standard animator names. +xx(Spawn) +xx(See) +xx(Pain) +xx(Melee) +xx(Missile) +xx(Crash) +xx(Death) +xx(Raise) +xx(Wound) +xx(Heal) +xx(Crush) +xx(Yes) +xx(No) +xx(Greetings) +xx(Idle) +xx(GenericFreezeDeath) +xx(GenericCrush) + +// Bounce state names +xx(Bounce) +xx(Wall) +xx(Floor) +xx(Ceiling) +xx(Creature) + +// Compatible death names for the decorate parser. +xx(XDeath) +xx(Burn) +//xx(Ice) // already defined above +xx(Disintegrate) +xx(Smash) + +// Weapon animator names. +xx(Select) +xx(Deselect) +xx(DeadLowered) +xx(Ready) +xx(Fire) +xx(Hold) +xx(AltFire) +xx(AltHold) +xx(Flash) +xx(AltFlash) +xx(Reload) +xx(Zoom) +xx(User1) +xx(User2) +xx(User3) +xx(User4) + +// State names used by ASwitchableDecoration +xx(Active) +xx(Inactive) + +// State names used by ACustomInventory +xx(Pickup) +xx(Use) +xx(Drop) + + +// ScriptUtil entry points +xx(ScriptUtil) +xx(SetMarineWeapon) +xx(SetMarineSprite) +xx(GiveInventory) +xx(TakeInventory) +xx(ClearInventory) + +// summary +xx(cwidth) +xx(cheight) +xx(wrapwidth) +xx(scalefactorx) +xx(scalefactory) +xx(scalemode) + +xx(Team) +xx(Skin) +xx(Gender) +xx(Autoaim) +xx(Crosshairs) +xx(Multiplayer) + +xx(CustomizeControls) +xx(MessageOptions) +xx(AutomapOptions) +xx(ScoreboardOptions) +xx(MapColorMenu) +xx(GameplayOptions) +xx(CompatibilityOptions) +xx(MouseOptions) +xx(JoystickOptions) +xx(SoundOptions) +xx(AdvSoundOptions) +xx(ModReplayerOptions) +xx(VideoOptions) +xx(JoystickConfigMenu) +xx(VideoModeMenu) + +// end sequences +xx(Inter_Chess) +xx(Inter_Strife) +xx(Inter_Strife_Good) +xx(Inter_Strife_Sad) +xx(Inter_Strife_Bad) +xx(Inter_Strife_Lose) +xx(Inter_Strife_MAP03) +xx(Inter_Strife_MAP10) + +xx(BuiltinCallLineSpecial) + +xx(MainmenuTextOnly) +xx(Playerclassmenu) +xx(HexenDefaultPlayerclassmenu) +xx(Readthismenu) +xx(Playermenu) + +// more stuff +xx(ColorSet) +xx(NeverSwitchOnPickup) +xx(MoveBob) +xx(StillBob) +xx(ClassicFlight) +xx(WBobSpeed) +xx(WBobFire) +xx(PlayerClass) +xx(MonsterClass) +xx(MorphedMonster) +xx(Wi_NoAutostartMap) + +xx(Duration) +xx(MorphStyle) +xx(MorphFlash) +xx(UnMorphFlash) +xx(Powerup) +xx(EffectTics) +xx(PowerupGiver) +xx(BlendColor) +xx(Strength) +xx(Mode) +xx(PowerupType) +xx(PlayerPawn) +xx(Key) +xx(RipSound) +xx(Archvile) + +xx(__decorate_internal_int__) +xx(__decorate_internal_bool__) +xx(__decorate_internal_float__) +xx(ResolveState) + + + +// UDMF keywords (todo: take these out of the global name table +xx(Alpha) +xx(Angle) +xx(Args) +xx(CeilingZ) +xx(FloorZ) +xx(Health) +xx(Pitch) +xx(SpecialName) +xx(Special) +xx(TID) +xx(TIDtoHate) +xx(WaterLevel) +xx(X) +xx(Y) +xx(Z) +xx(XY) +xx(MomX) +xx(MomY) +xx(MomZ) +xx(Threshold) +xx(DefThreshold) +xx(Abs) +xx(TeleportSpecial) +xx(Teleport) +xx(ACS_NamedExecuteWithResult) +xx(CallACS) +xx(IsPointerEqual) +xx(Pick) +xx(Mass) +xx(VelX) +xx(VelY) +xx(VelZ) +xx(Accuracy) +xx(Stamina) +xx(Radius) +xx(ReactionTime) +xx(MeleeRange) +xx(Speed) +xx(FastSpeed) +xx(HowlSound) +xx(Clamp) +xx(VisibleStartAngle) +xx(VisibleStartPitch) +xx(VisibleEndAngle) +xx(VisibleEndPitch) +xx(Format) +xx(PickupMsg) +xx(Respawnable) +xx(ExplosionDamage) +xx(ExplosionRadius) +xx(DontHurtShooter) +xx(Noattack) + +//xx(X) +//xx(Y) +xx(ZFloor) +xx(ZCeiling) +xx(Height) +//xx(Tid) +//xx(Angle) +xx(Type) +//xx(Special) +xx(Arg0) +xx(Arg1) +xx(Arg2) +xx(Arg3) +xx(Arg4) +xx(Arg0Str) +xx(Arg1Str) +xx(Id) +xx(MoreIds) +xx(V1) +xx(V2) + +xx(Sidefront) +xx(Sideback) +xx(Offsetx) +xx(Offsety) +xx(Texturetop) +xx(Texturebottom) +xx(Texturemiddle) +xx(Sector) +xx(Heightfloor) +xx(Heightceiling) +xx(Lightlevel) +xx(Texturefloor) +xx(Textureceiling) +xx(Nodecals) + +xx(Skill1) +xx(Skill2) +xx(Skill3) +xx(Skill4) +xx(Skill5) +xx(Skill6) +xx(Skill7) +xx(Skill8) +xx(Skill9) +xx(Skill10) +xx(Skill11) +xx(Skill12) +xx(Skill13) +xx(Skill14) +xx(Skill15) +xx(Skill16) +xx(Medium) +xx(Hard) +xx(Ambush) +xx(Dormant) +xx(Class0) +xx(Class1) +xx(Class2) +xx(Class3) +xx(Class4) +xx(Class5) +xx(Class6) +xx(Class7) +xx(Class8) +xx(Class9) +xx(Class10) +xx(Class11) +xx(Class12) +xx(Class13) +xx(Class14) +xx(Class15) +xx(Class16) +xx(Single) +xx(Coop) +xx(Dm) +xx(Translucent) +xx(Invisible) +xx(Friend) +xx(Strifeally) +xx(Standing) +xx(Countsecret) +xx(NoCount) +xx(Score) +xx(Roll) +xx(Scale) +xx(ScaleX) +xx(ScaleY) +xx(FriendlySeeBlocks) +xx(Floatbobphase) +xx(Floatbobstrength) +xx(Target) +xx(Master) +xx(Tracer) + +xx(Blocking) +xx(Blockmonsters) +xx(Twosided) +xx(Dontpegtop) +xx(Dontpegbottom) +xx(Secret) +xx(Blocksound) +xx(Dontdraw) +xx(Mapped) +xx(Monsteractivate) +xx(Blockplayers) +xx(Blockeverything) +xx(Zoneboundary) +xx(Jumpover) +xx(Blockfloaters) +xx(Blocklandmonsters) +xx(Clipmidtex) +xx(Wrapmidtex) +xx(Midtex3d) +xx(Checkswitchrange) +xx(Firstsideonly) +xx(Transparent) +xx(Passuse) +xx(Repeatspecial) +xx(Conversation) +xx(Locknumber) +xx(Midtex3dimpassible) +xx(Revealed) +xx(AutomapStyle) +xx(DrawFullHeight) + +xx(Playercross) +xx(Playeruse) +xx(Playeruseback) +xx(Monstercross) +xx(Impact) +xx(Playerpush) +xx(Missilecross) +xx(Anycross) +xx(Monsteruse) +xx(Monsterpush) + +xx(ZDoom) +xx(ZDoomTranslated) +xx(Vavoom) +xx(GZDoom) +xx(Eternity) + +xx(Xpanningfloor) +xx(Ypanningfloor) +xx(Xpanningceiling) +xx(Ypanningceiling) +xx(Xscalefloor) +xx(Yscalefloor) +xx(Xscaleceiling) +xx(Yscaleceiling) +xx(Rotationfloor) +xx(Rotationceiling) +xx(Lightfloor) +xx(Lightceiling) +xx(Lightfloorabsolute) +xx(Lightceilingabsolute) +xx(Gravity) +xx(Lightcolor) +xx(Fadecolor) +xx(Color_Floor) +xx(Color_Ceiling) +xx(Color_Walltop) +xx(Color_Wallbottom) +xx(Color_Sprites) +xx(ColorAdd_Floor) +xx(ColorAdd_Ceiling) +xx(ColorAdd_Sprites) +xx(ColorAdd_Walls) +xx(NoSkyWalls) +xx(Desaturation) +xx(SoundSequence) +xx(Silent) +xx(Nofallingdamage) +xx(Dropactors) +xx(NoRespawn) +xx(Alphafloor) +xx(Alphaceiling) +xx(Renderstylefloor) +xx(Renderstyleceiling) +xx(Waterzone) +xx(portal_ceil_blocksound) +xx(portal_ceil_disabled) +xx(portal_ceil_nopass) +xx(portal_ceil_norender) +xx(portal_ceil_overlaytype) +xx(portal_ceil_useglobaltex) +xx(portal_floor_blocksound) +xx(portal_floor_disabled) +xx(portal_floor_nopass) +xx(portal_floor_norender) +xx(portal_floor_overlaytype) +xx(portal_floor_useglobaltex) +xx(scroll_ceil_x) +xx(scroll_ceil_y) +xx(scroll_ceil_type) +xx(scroll_floor_x) +xx(scroll_floor_y) +xx(scroll_floor_type) + +xx(offsetx_top) +xx(offsety_top) +xx(offsetx_mid) +xx(offsety_mid) +xx(offsetx_bottom) +xx(offsety_bottom) +xx(scalex_top) +xx(scaley_top) +xx(scalex_mid) +xx(scaley_mid) +xx(scalex_bottom) +xx(scaley_bottom) +xx(light) +xx(lightabsolute) +xx(lightfog) +xx(nofakecontrast) +xx(smoothlighting) +xx(blockprojectiles) +xx(blockuse) +xx(hidden) +xx(blocksight) +xx(blockhitscan) + +xx(nogradient_top) +xx(flipgradient_top) +xx(clampgradient_top) +xx(useowncolors_top) +xx(uppercolor_top) +xx(lowercolor_top) +xx(nogradient_mid) +xx(flipgradient_mid) +xx(clampgradient_mid) +xx(useowncolors_mid) +xx(uppercolor_mid) +xx(lowercolor_mid) +xx(nogradient_bottom) +xx(flipgradient_bottom) +xx(clampgradient_bottom) +xx(useowncolors_bottom) +xx(uppercolor_bottom) +xx(lowercolor_bottom) +xx(useowncoloradd_top) +xx(coloradd_top) +xx(useowncoloradd_mid) +xx(coloradd_mid) +xx(useowncoloradd_bottom) +xx(coloradd_bottom) +xx(colorization_top) +xx(colorization_mid) +xx(colorization_bottom) +xx(colorization_floor) +xx(colorization_ceiling) + +xx(ceilingplane_a) +xx(ceilingplane_b) +xx(ceilingplane_c) +xx(ceilingplane_d) +xx(floorplane_a) +xx(floorplane_b) +xx(floorplane_c) +xx(floorplane_d) +xx(damageamount) +xx(damagetype) +xx(damageinterval) +xx(leakiness) +xx(damageterraineffect) +xx(damagehazard) +xx(floorterrain) +xx(ceilingterrain) +xx(floor_reflect) +xx(ceiling_reflect) +xx(floorglowcolor) +xx(floorglowheight) +xx(ceilingglowcolor) +xx(ceilingglowheight) +xx(fogdensity) + +xx(HealthFloor) +xx(HealthCeiling) +xx(Health3D) +xx(DamageSpecial) +xx(DeathSpecial) +xx(HealthFloorGroup) +xx(HealthCeilingGroup) +xx(Health3DGroup) +xx(HealthGroup) +xx(Renderstyle) + +// USDF keywords +xx(Amount) +xx(Text) +xx(Displaycost) +xx(Yesmessage) +xx(Nomessage) +xx(Log) +xx(Giveitem) +xx(Nextpage) +xx(Closedialog) +xx(Cost) +xx(Page) +xx(Count) +xx(Name) +xx(Panel) +xx(Dialog) +xx(Ifitem) +xx(Choice) +xx(Link) +xx(Goodbye) +xx(Require) +xx(Exclude) +xx(Userstring) +xx(Sky) +xx(Pagename) diff --git a/src/playsim/dthinker.cpp b/src/playsim/dthinker.cpp index d71e13880..115e16c53 100644 --- a/src/playsim/dthinker.cpp +++ b/src/playsim/dthinker.cpp @@ -616,7 +616,6 @@ int FThinkerList::TickThinkers(FThinkerList *dest) ThinkCount++; node->CallTick(); node->ObjectFlags &= ~OF_JustSpawned; - GC::CheckGC(); } node = NextToThink; } @@ -667,7 +666,6 @@ int FThinkerList::ProfileThinkers(FThinkerList *dest) node->CallTick(); prof.timer.Unclock(); node->ObjectFlags &= ~OF_JustSpawned; - GC::CheckGC(); } node = NextToThink; } diff --git a/src/playsim/mapthinkers/a_floor.cpp b/src/playsim/mapthinkers/a_floor.cpp index 27dc1cf0e..21eccaa4d 100644 --- a/src/playsim/mapthinkers/a_floor.cpp +++ b/src/playsim/mapthinkers/a_floor.cpp @@ -40,6 +40,7 @@ #include "r_data/r_interpolate.h" #include "g_levellocals.h" #include "vm.h" +#include "r_utility.h" //========================================================================== // @@ -661,6 +662,7 @@ bool FLevelLocals::EV_BuildStairs (int tag, DFloor::EStair type, line_t *line, d // 1. Find 2-sided line with same sector side[0] (lowest numbered) // 2. Other side is the next sector to raise // 3. Unless already moving, or different texture, then stop building + validcount++; do { ok = 0; @@ -668,12 +670,13 @@ bool FLevelLocals::EV_BuildStairs (int tag, DFloor::EStair type, line_t *line, d if (usespecials & DFloor::stairUseSpecials) { // [RH] Find the next sector by scanning for Stairs_Special? - tsec = sec->NextSpecialSector ( + tsec = P_NextSpecialSectorVC(sec, sec->special == Stairs_Special1 ? - Stairs_Special2 : Stairs_Special1, prev); + Stairs_Special2 : Stairs_Special1); - if ( (ok = (tsec != NULL)) ) + if ( (ok = (tsec != nullptr)) ) { + tsec->validcount = validcount; height += stairstep; // if sector's floor already moving, look for another diff --git a/src/playsim/mapthinkers/a_lights.cpp b/src/playsim/mapthinkers/a_lights.cpp index e53f1a5c5..9cd7fb20f 100644 --- a/src/playsim/mapthinkers/a_lights.cpp +++ b/src/playsim/mapthinkers/a_lights.cpp @@ -521,7 +521,7 @@ int DPhased::PhaseHelper (sector_t *sector, int index, int light, sector_t *prev else l = Level->CreateThinker (sector, baselevel); - int numsteps = PhaseHelper (sector->NextSpecialSector ( + int numsteps = PhaseHelper (P_NextSpecialSector (sector, sector->special == LightSequenceSpecial1 ? LightSequenceSpecial2 : LightSequenceSpecial1, prev), index + 1, l->m_BaseLevel, sector); diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index 545bdd9c8..215fb0e34 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -8570,7 +8570,7 @@ scriptwait: int capacity, offset, a, c; if (CharArrayParms(capacity, offset, a, Stack, sp, pcd == PCD_PRINTMAPCHRANGE)) { - while (capacity-- && (c = activeBehavior->GetArrayVal (a, offset)) != '\0') + while (capacity-- && (c = activeBehavior->GetArrayVal (*activeBehavior->MapVars[a], offset)) != '\0') { work += (char)c; offset++; diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 56980c6e3..970c86c6a 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -36,10 +36,13 @@ #include "vectors.h" #include "doomdef.h" -#define FX_ROCKET 0x00000001 -#define FX_GRENADE 0x00000002 -#define FX_RESPAWNINVUL 0x00000020 -#define FX_VISIBILITYPULSE 0x00000040 +enum +{ + FX_ROCKET = 0x00000001, + FX_GRENADE = 0x00000002, + FX_RESPAWNINVUL = 0x00000020, + FX_VISIBILITYPULSE = 0x00000040 +}; struct subsector_t; struct FLevelLocals; diff --git a/src/playsim/p_sectors.cpp b/src/playsim/p_sectors.cpp index 448808265..bb535ade8 100644 --- a/src/playsim/p_sectors.cpp +++ b/src/playsim/p_sectors.cpp @@ -89,27 +89,44 @@ CUSTOM_CVAR(Int, r_fakecontrast, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // // Returns the next special sector attached to this sector // with a certain special. -sector_t *sector_t::NextSpecialSector (int type, sector_t *nogood) const + +sector_t* P_NextSpecialSectorVC(sector_t* sec, int type) +{ + sector_t* tsec; + for (auto ln : sec->Lines) + { + if (nullptr != (tsec = getNextSector(ln, sec)) && + tsec->validcount != validcount && + tsec->special == type) + { + return tsec; + } + } + return nullptr; +} + + +sector_t *P_NextSpecialSector (sector_t* sec, int type, sector_t *nogood) { sector_t *tsec; - for (auto ln : Lines) + for (auto ln : sec->Lines) { - if (NULL != (tsec = getNextSector (ln, this)) && + if (nullptr != (tsec = getNextSector (ln, sec)) && tsec != nogood && tsec->special == type) { return tsec; } } - return NULL; + return nullptr; } -DEFINE_ACTION_FUNCTION(_Sector, NextSpecialSector) +DEFINE_ACTION_FUNCTION_NATIVE(_Sector, NextSpecialSector, P_NextSpecialSector) { PARAM_SELF_STRUCT_PROLOGUE(sector_t); PARAM_INT(type); PARAM_POINTER(nogood, sector_t); - ACTION_RETURN_POINTER(self->NextSpecialSector(type, nogood)); + ACTION_RETURN_POINTER(P_NextSpecialSector(self, type, nogood)); } // diff --git a/src/rendering/hwrenderer/hw_postprocessshader.cpp b/src/rendering/hwrenderer/hw_postprocessshader.cpp deleted file mode 100644 index f8e6e3e8b..000000000 --- a/src/rendering/hwrenderer/hw_postprocessshader.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* -** Postprocessing framework -** Copyright (c) 2016-2020 Magnus Norddahl -** -** This software is provided 'as-is', without any express or implied -** warranty. In no event will the authors be held liable for any damages -** arising from the use of this software. -** -** Permission is granted to anyone to use this software for any purpose, -** including commercial applications, and to alter it and redistribute it -** freely, subject to the following restrictions: -** -** 1. The origin of this software must not be misrepresented; you must not -** claim that you wrote the original software. If you use this software -** in a product, an acknowledgment in the product documentation would be -** appreciated but is not required. -** 2. Altered source versions must be plainly marked as such, and must not be -** misrepresented as being the original software. -** 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "vm.h" -#include "d_player.h" -#include "hwrenderer/postprocessing/hw_postprocessshader.h" -#include "g_levellocals.h" -#include "hwrenderer/postprocessing/hw_postprocess.h" - -static bool IsConsolePlayer(player_t *player) -{ - AActor *activator = player ? player->mo : nullptr; - if (activator == nullptr || activator->player == nullptr) - return false; - return activator->player == activator->Level->GetConsolePlayer(); -} - -static void ShaderSetEnabled(player_t *player, const FString &shaderName, bool value) -{ - if (IsConsolePlayer(player)) - { - for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) - { - PostProcessShader &shader = PostProcessShaders[i]; - if (shader.Name == shaderName) - shader.Enabled = value; - } - } -} - -DEFINE_ACTION_FUNCTION_NATIVE(_Shader, SetEnabled, ShaderSetEnabled) -{ - PARAM_PROLOGUE; - PARAM_POINTER(player, player_t); - PARAM_STRING(shaderName); - PARAM_BOOL(value); - ShaderSetEnabled(player, shaderName, value); - - return 0; -} - -static void ShaderSetUniform1f(player_t *player, const FString &shaderName, const FString &uniformName, double value) -{ - if (IsConsolePlayer(player)) - { - for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) - { - PostProcessShader &shader = PostProcessShaders[i]; - if (shader.Name == shaderName) - { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = value; - vec4[1] = 0.0; - vec4[2] = 0.0; - vec4[3] = 1.0; - } - } - } -} - -DEFINE_ACTION_FUNCTION_NATIVE(_Shader, SetUniform1f, ShaderSetUniform1f) -{ - PARAM_PROLOGUE; - PARAM_POINTER(player, player_t); - PARAM_STRING(shaderName); - PARAM_STRING(uniformName); - PARAM_FLOAT(value); - ShaderSetUniform1f(player, shaderName, uniformName, value); - return 0; -} - -DEFINE_ACTION_FUNCTION(_Shader, SetUniform2f) -{ - PARAM_PROLOGUE; - PARAM_POINTER(player, player_t); - PARAM_STRING(shaderName); - PARAM_STRING(uniformName); - PARAM_FLOAT(x); - PARAM_FLOAT(y); - - if (IsConsolePlayer(player)) - { - for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) - { - PostProcessShader &shader = PostProcessShaders[i]; - if (shader.Name == shaderName) - { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = x; - vec4[1] = y; - vec4[2] = 0.0; - vec4[3] = 1.0; - } - } - } - return 0; -} - -DEFINE_ACTION_FUNCTION(_Shader, SetUniform3f) -{ - PARAM_PROLOGUE; - PARAM_POINTER(player, player_t); - PARAM_STRING(shaderName); - PARAM_STRING(uniformName); - PARAM_FLOAT(x); - PARAM_FLOAT(y); - PARAM_FLOAT(z); - - if (IsConsolePlayer(player)) - { - for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) - { - PostProcessShader &shader = PostProcessShaders[i]; - if (shader.Name == shaderName) - { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = x; - vec4[1] = y; - vec4[2] = z; - vec4[3] = 1.0; - } - } - } - return 0; -} - -DEFINE_ACTION_FUNCTION(_Shader, SetUniform1i) -{ - PARAM_PROLOGUE; - PARAM_POINTER(player, player_t); - PARAM_STRING(shaderName); - PARAM_STRING(uniformName); - PARAM_INT(value); - - if (IsConsolePlayer(player)) - { - for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) - { - PostProcessShader &shader = PostProcessShaders[i]; - if (shader.Name == shaderName) - { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = (double)value; - vec4[1] = 0.0; - vec4[2] = 0.0; - vec4[3] = 1.0; - } - } - } - return 0; -} diff --git a/src/rendering/hwrenderer/scene/hw_spritelight.cpp b/src/rendering/hwrenderer/scene/hw_spritelight.cpp index 71b486888..8f2449994 100644 --- a/src/rendering/hwrenderer/scene/hw_spritelight.cpp +++ b/src/rendering/hwrenderer/scene/hw_spritelight.cpp @@ -37,6 +37,7 @@ #include "hwrenderer/scene/hw_drawinfo.h" #include "hwrenderer/scene/hw_drawstructs.h" #include "models.h" +#include // needed for std::floor on mac template T smoothstep(const T edge0, const T edge1, const T x) diff --git a/src/sound/s_advsound.cpp b/src/sound/s_advsound.cpp index 7d37c9952..2fd7428b3 100644 --- a/src/sound/s_advsound.cpp +++ b/src/sound/s_advsound.cpp @@ -416,7 +416,7 @@ static int S_AddSound (const char *logicalname, int lumpnum, FScanner *sc) sfxid = soundEngine->FindSoundNoHash (logicalname); - if (sfxid > 0) + if (sfxid > 0 && (unsigned int)sfxid < S_sfx.Size()) { // If the sound has already been defined, change the old definition sfxinfo_t *sfx = &S_sfx[sfxid]; @@ -483,7 +483,9 @@ int S_AddPlayerSound (const char *pclass, int gender, int refid, int S_AddPlayerSound (const char *pclass, int gender, int refid, int lumpnum, bool fromskin) { + auto &S_sfx = soundEngine->GetSounds(); + FString fakename; int id; diff --git a/src/sound/s_doomsound.cpp b/src/sound/s_doomsound.cpp index 6b9549067..d70318e60 100644 --- a/src/sound/s_doomsound.cpp +++ b/src/sound/s_doomsound.cpp @@ -71,6 +71,8 @@ FBoolCVar noisedebug("noise", false, 0); // [RH] Print sound debugging info? +CVAR (Bool, i_soundinbackground, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CVAR (Bool, i_pauseinbackground, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) static FString LastLocalSndInfo; @@ -930,7 +932,16 @@ void S_SerializeSounds(FSerializer &arc) void S_SetSoundPaused(int state) { - if (state) + if (!netgame && (i_pauseinbackground) +#ifdef _DEBUG + && !demoplayback +#endif + ) + { + pauseext = !state; + } + + if ((state || i_soundinbackground) && !pauseext) { if (paused == 0) { @@ -954,14 +965,6 @@ void S_SetSoundPaused(int state) } } } - if (!netgame -#ifdef _DEBUG - && !demoplayback -#endif - ) - { - pauseext = !state; - } } diff --git a/wadsrc/static/dehsupp.txt b/wadsrc/static/dehsupp.txt index 8525d1164..59858975f 100644 --- a/wadsrc/static/dehsupp.txt +++ b/wadsrc/static/dehsupp.txt @@ -1199,7 +1199,7 @@ Aliases A_MonsterMeleeAttack, MBF21_MonsterMeleeAttack, A_RadiusDamage, A_RadiusDamage, A_HealChase, MBF21_HealChase, - A_SeekTracer, A_SeekerMissile, + A_SeekTracer, MBF21_SeekTracer, A_FindTracer, A_FindTracer, A_JumpIfHealthBelow, MBF21_JumpIfHealthBelow, A_JumpIfTargetInSight, MBF21_JumpIfTargetInSight, diff --git a/wadsrc/static/menudef.zsimple b/wadsrc/static/menudef.zsimple index 2ebc60430..c0fc8b630 100644 --- a/wadsrc/static/menudef.zsimple +++ b/wadsrc/static/menudef.zsimple @@ -6,7 +6,7 @@ OptionMenu "OptionsMenuSimple" protected { Title "$OPTMNU_TITLE" Submenu "$OPTMNU_CONTROLS", "CustomizeControls" - Submenu "$OPTMNU_MOUSE", "MouseOptions" + Submenu "$OPTMNU_MOUSE", "MouseOptionsSimple" Submenu "$OPTMNU_JOYSTICK", "JoystickOptions" StaticText " " Submenu "$OPTMNU_PLAYER", "NewPlayerMenu" @@ -101,3 +101,21 @@ OptionMenu MiscOptionsSimple protected Option "$MISCMNU_ENABLESCRIPTSCREENSHOTS", "enablescriptscreenshot", "OnOff" Option "$OPTMNU_LANGUAGE", "language", "LanguageOptions" } + +OptionMenu "MouseOptionsSimple" protected +{ + Title "$MOUSEMNU_TITLE" + Option "$MOUSEMNU_ENABLEMOUSE", "use_mouse", "YesNo" + Option "$MOUSEMNU_MOUSEINMENU", "m_use_mouse", "MenuMouse", "use_mouse" + IfOption(Windows) + { + Option "$MOUSEMNU_SWAPBUTTONS", "m_swapbuttons", "YesNo" + } + Option "$MOUSEMNU_CURSOR", "vid_cursor", "Cursors" + StaticText "" + Slider "$MOUSEMNU_SENSITIVITY_X", "m_sensitivity_x", 0.5, 8, 0.25 + Slider "$MOUSEMNU_SENSITIVITY_Y", "m_sensitivity_y", 0.5, 8, 0.25 + Option "$MOUSEMNU_SMOOTHMOUSE", "m_filter", "YesNo" + StaticText "" + Option "$MOUSEMNU_INVERTMOUSE", "invertmouse", "OnOff" +} diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index a447a9b73..e6bd04830 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -6,6 +6,7 @@ version "4.6" #include "zscript/engine/dictionary.zs" #include "zscript/engine/inputevents.zs" #include "zscript/engine/service.zs" +#include "zscript/engine/ppshader.zs" #include "zscript/engine/ui/menu/colorpickermenu.zs" #include "zscript/engine/ui/menu/joystickmenu.zs" diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index b47ee9365..3124a7bd0 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -684,7 +684,7 @@ class Actor : Thinker native native Actor, Actor SpawnPlayerMissile(class type, double angle = 1e37, double x = 0, double y = 0, double z = 0, out FTranslatedLineTarget pLineTarget = null, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0); native void SpawnTeleportFog(Vector3 pos, bool beforeTele, bool setTarget); native Actor RoughMonsterSearch(int distance, bool onlyseekable = false, bool frontonly = false, double fov = 0); - native int ApplyDamageFactor(Name damagetype, int damage); + native clearscope int ApplyDamageFactor(Name damagetype, int damage); native int GetModifiedDamage(Name damagetype, int damage, bool passive, Actor inflictor = null, Actor source = null, int flags = 0); native bool CheckBossDeath(); native bool CheckFov(Actor target, double fov); diff --git a/wadsrc/static/zscript/actors/inventory/weapons.zs b/wadsrc/static/zscript/actors/inventory/weapons.zs index 3ef7080c8..eca912291 100644 --- a/wadsrc/static/zscript/actors/inventory/weapons.zs +++ b/wadsrc/static/zscript/actors/inventory/weapons.zs @@ -1001,7 +1001,7 @@ class Weapon : StateProvider // //=========================================================================== - virtual bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1) + virtual bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1, bool forceammouse = false) { if (!(sv_infiniteammo || (Owner.FindInventory ('PowerInfiniteAmmo', true) != null))) { @@ -1013,7 +1013,7 @@ class Weapon : StateProvider { if (Ammo1 != null) { - if (ammouse >= 0 && bDehAmmo) + if (ammouse >= 0 && (bDehAmmo || forceammouse)) { Ammo1.Amount -= ammouse; } diff --git a/wadsrc/static/zscript/actors/mbf21.zs b/wadsrc/static/zscript/actors/mbf21.zs index b6eb4ef89..a010f0e2c 100644 --- a/wadsrc/static/zscript/actors/mbf21.zs +++ b/wadsrc/static/zscript/actors/mbf21.zs @@ -198,7 +198,9 @@ extend class Actor // void A_FindTracer(double fov, int dist) { - if (!tracer) tracer = RoughMonsterSearch(dist, fov: fov); + // note: mbf21 fov is the angle of the entire cone, while + // zdoom fov is defined as 1/2 of the cone, so halve it. + if (!tracer) tracer = RoughMonsterSearch(dist, fov: fov/2); } // @@ -316,11 +318,9 @@ extend class Weapon FTranslatedLineTarget t; angle += self.angle; - double x = Spawnofs_xy * cos(angle); - double y = Spawnofs_xy * sin(angle); - let pos = self.Vec3Offset(x, y, Spawnofs_z); + Vector2 ofs = AngleToVector(self.Angle - 90, spawnofs_xy); - let mo = SpawnPlayerMissile(type, angle, pos.X, pos.Y, pos.Z, pLineTarget: t); + let mo = SpawnPlayerMissile(type, angle, ofs.x, ofs.y, Spawnofs_z, pLineTarget: t); if (!mo) return; Pitch += mo.PitchFromVel(); @@ -432,7 +432,7 @@ extend class Weapon if (!weap) return; if (consume == 0) consume = -1; - weap.DepleteAmmo(weap.bAltFire, false, consume); + weap.DepleteAmmo(weap.bAltFire, false, consume, true); } // @@ -503,5 +503,11 @@ extend class Weapon player.SetPsprite(PSP_FLASH, tstate); } + // needed to call A_SeekerMissile with proper defaults. + deprecated("2.3", "for Dehacked use only") + void MBF21_SeekTracer(double threshold, double turnmax) + { + A_SeekerMissile(threshold, turnmax, flags: SMF_PRECISE); // args get truncated to ints here, but it's close enough + } } \ No newline at end of file diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index 1a381c3a8..e72bef838 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -254,6 +254,11 @@ class PlayerPawn : Actor invul.EffectTics = 3 * TICRATE; invul.BlendColor = 0; // don't mess with the view invul.bUndroppable = true; // Don't drop self + if (!invul.CallTryPickup(self)) + { + invul.Destroy(); + return; + } bRespawnInvul = true; // [RH] special effect } } diff --git a/wadsrc/static/zscript/actors/shared/movingcamera.zs b/wadsrc/static/zscript/actors/shared/movingcamera.zs index 132370008..8f76bd179 100644 --- a/wadsrc/static/zscript/actors/shared/movingcamera.zs +++ b/wadsrc/static/zscript/actors/shared/movingcamera.zs @@ -488,19 +488,19 @@ class ActorMover : PathFollower Super.Activate (activator); let tracer = self.tracer; special1 = tracer.bNoGravity + (tracer.bNoBlockmap<<1) + (tracer.bSolid<<2) + (tracer.bInvulnerable<<4) + (tracer.bDormant<<8); - bNoGravity = true; + tracer.bNoGravity = true; if (args[2] & 128) { LinkContext ctx; tracer.UnlinkFromWorld (ctx); - bNoBlockmap = true; - bSolid = false; + tracer.bNoBlockmap = true; + tracer.bSolid = false; tracer.LinkToWorld (ctx); } if (tracer.bIsMonster) { - bInvulnerable = true; - bDormant = true; + tracer.bInvulnerable = true; + tracer.bDormant = true; } // Don't let the renderer interpolate between the actor's // old position and its new position. diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index f81596199..f1190cea8 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -701,11 +701,31 @@ class Lighting : SectorEffect native struct Shader native { - native clearscope static void SetEnabled(PlayerInfo player, string shaderName, bool enable); - native clearscope static void SetUniform1f(PlayerInfo player, string shaderName, string uniformName, float value); - native clearscope static void SetUniform2f(PlayerInfo player, string shaderName, string uniformName, vector2 value); - native clearscope static void SetUniform3f(PlayerInfo player, string shaderName, string uniformName, vector3 value); - native clearscope static void SetUniform1i(PlayerInfo player, string shaderName, string uniformName, int value); + // This interface was deprecated for the pointless player dependency + private static bool IsConsolePlayer(PlayerInfo player) + { + return player && player.mo && player == players[consoleplayer]; + } + deprecated("4.8", "Use PPShader.SetEnabled() instead") clearscope static void SetEnabled(PlayerInfo player, string shaderName, bool enable) + { + if (IsConsolePlayer(player)) PPShader.SetEnabled(shaderName, enable); + } + deprecated("4.8", "Use PPShader.SetUniform1f() instead") clearscope static void SetUniform1f(PlayerInfo player, string shaderName, string uniformName, float value) + { + if (IsConsolePlayer(player)) PPShader.SetUniform1f(shaderName, uniformName, value); + } + deprecated("4.8", "Use PPShader.SetUniform2f() instead") clearscope static void SetUniform2f(PlayerInfo player, string shaderName, string uniformName, vector2 value) + { + if (IsConsolePlayer(player)) PPShader.SetUniform2f(shaderName, uniformName, value); + } + deprecated("4.8", "Use PPShader.SetUniform3f() instead") clearscope static void SetUniform3f(PlayerInfo player, string shaderName, string uniformName, vector3 value) + { + if (IsConsolePlayer(player)) PPShader.SetUniform3f(shaderName, uniformName, value); + } + deprecated("4.8", "Use PPShader.SetUniform1i() instead") clearscope static void SetUniform1i(PlayerInfo player, string shaderName, string uniformName, int value) + { + if (IsConsolePlayer(player)) PPShader.SetUniform1i(shaderName, uniformName, value); + } } struct FRailParams diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index d4b896466..41bdb07f9 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -183,6 +183,7 @@ struct _ native // These are the global variables, the struct is only here to av native MenuDelegateBase menuDelegate; native readonly int consoleplayer; native readonly double NotifyFontScale; + native readonly int paused; } struct System native @@ -202,7 +203,6 @@ struct System native } return false; } - } struct MusPlayingInfo native diff --git a/wadsrc/static/zscript/engine/ppshader.zs b/wadsrc/static/zscript/engine/ppshader.zs new file mode 100644 index 000000000..5c94e7e23 --- /dev/null +++ b/wadsrc/static/zscript/engine/ppshader.zs @@ -0,0 +1,8 @@ +struct PPShader native +{ + native clearscope static void SetEnabled(string shaderName, bool enable); + native clearscope static void SetUniform1f(string shaderName, string uniformName, float value); + native clearscope static void SetUniform2f(string shaderName, string uniformName, vector2 value); + native clearscope static void SetUniform3f(string shaderName, string uniformName, vector3 value); + native clearscope static void SetUniform1i(string shaderName, string uniformName, int value); +} diff --git a/wadsrc_widepix/static/filter/chex.chex1/titlepic.lmp b/wadsrc_widepix/static/filter/chex.chex1/graphics/titlepic.lmp similarity index 100% rename from wadsrc_widepix/static/filter/chex.chex1/titlepic.lmp rename to wadsrc_widepix/static/filter/chex.chex1/graphics/titlepic.lmp diff --git a/wadsrc_widepix/static/filter/chex.chex1/wimap0.lmp b/wadsrc_widepix/static/filter/chex.chex1/graphics/wimap0.lmp similarity index 100% rename from wadsrc_widepix/static/filter/chex.chex1/wimap0.lmp rename to wadsrc_widepix/static/filter/chex.chex1/graphics/wimap0.lmp diff --git a/wadsrc_widepix/static/filter/doom.id/patches/SHT2E0.lmp b/wadsrc_widepix/static/filter/doom.id.doom2/sprites/SHT2E0.lmp similarity index 100% rename from wadsrc_widepix/static/filter/doom.id/patches/SHT2E0.lmp rename to wadsrc_widepix/static/filter/doom.id.doom2/sprites/SHT2E0.lmp diff --git a/wadsrc_widepix/static/filter/doom.id.doom2/textures.txt b/wadsrc_widepix/static/filter/doom.id.doom2/textures.txt deleted file mode 100644 index 4e2c7335f..000000000 --- a/wadsrc_widepix/static/filter/doom.id.doom2/textures.txt +++ /dev/null @@ -1,5 +0,0 @@ -sprite SHT2E0, 233, 63 -{ - offset 32, -105 - patch "/patches/SHT2E0.lmp", 0, 0 { } -} diff --git a/wadsrc_widepix/static/filter/doom.id.wadsmoosh/sprites/SHT2E0.lmp b/wadsrc_widepix/static/filter/doom.id.wadsmoosh/sprites/SHT2E0.lmp new file mode 100644 index 000000000..b73a84fcb Binary files /dev/null and b/wadsrc_widepix/static/filter/doom.id.wadsmoosh/sprites/SHT2E0.lmp differ diff --git a/wadsrc_widepix/static/filter/doom.id.wadsmoosh/textures.txt b/wadsrc_widepix/static/filter/doom.id.wadsmoosh/textures.txt deleted file mode 100644 index 4e2c7335f..000000000 --- a/wadsrc_widepix/static/filter/doom.id.wadsmoosh/textures.txt +++ /dev/null @@ -1,5 +0,0 @@ -sprite SHT2E0, 233, 63 -{ - offset 32, -105 - patch "/patches/SHT2E0.lmp", 0, 0 { } -}