├── include ├── Precomp.h ├── 7zAlloc.h ├── Delta.h ├── 7zAssetFile.h ├── 7zCrc.h ├── 7zBuf.h ├── 7zVersion.h ├── 7zFunctions.h ├── Compiler.h ├── 7zFile.h ├── Bra.h ├── 7zExtractor.h ├── Ppmd.h ├── Bcj2.h ├── Lzma2Dec.h ├── Ppmd7.h ├── 7z.h ├── LzmaDec.h ├── CpuArch.h └── 7zTypes.h ├── .gitignore ├── example ├── main.c └── Makefile ├── source ├── 7zBuf.c ├── 7zBuf2.c ├── BraIA64.c ├── Delta.c ├── 7zAlloc.c ├── Bra86.c ├── 7zAssetFile.c ├── 7zCrc.c ├── 7zCrcOpt.c ├── 7zStream.c ├── Bra.c ├── CpuArch.c ├── Ppmd7Dec.c ├── Bcj2.c ├── 7zFunctions.c ├── 7zFile.c ├── 7zExtractor.c ├── Lzma2Dec.c ├── 7zDec.c └── Ppmd7.c ├── Makefile.psp ├── Makefile.vita ├── README.md ├── Makefile.PS4 ├── Makefile └── LICENSE /include/Precomp.h: -------------------------------------------------------------------------------- 1 | /* Precomp.h -- StdAfx 2 | 2013-11-12 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_PRECOMP_H 5 | #define __7Z_PRECOMP_H 6 | 7 | #include "Compiler.h" 8 | /* #include "7zTypes.h" */ 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /include/7zAlloc.h: -------------------------------------------------------------------------------- 1 | /* 7zAlloc.h -- Allocation functions 2 | 2017-04-03 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_ALLOC_H 5 | #define __7Z_ALLOC_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | void *SzAlloc(ISzAllocPtr p, size_t size); 12 | void SzFree(ISzAllocPtr p, void *address); 13 | 14 | void *SzAllocTemp(ISzAllocPtr p, size_t size); 15 | void SzFreeTemp(ISzAllocPtr p, void *address); 16 | 17 | EXTERN_C_END 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/Delta.h: -------------------------------------------------------------------------------- 1 | /* Delta.h -- Delta converter 2 | 2013-01-18 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __DELTA_H 5 | #define __DELTA_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | #define DELTA_STATE_SIZE 256 12 | 13 | void Delta_Init(Byte *state); 14 | void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size); 15 | void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size); 16 | 17 | EXTERN_C_END 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /example/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | void callback(const char* fileName, unsigned long fileSize, unsigned fileNum, unsigned numFiles) 7 | { 8 | printf("[%d/%d] File: %s Size: %ld\n", fileNum, numFiles, fileName, fileSize); 9 | } 10 | 11 | int main(void) 12 | { 13 | // List 7-Zip archive contents 14 | List7zFile("/dev_hdd0/tmp/archive.7z", &callback); 15 | 16 | // Test 7-Zip archive contents 17 | Test7zFile("/dev_hdd0/tmp/archive.7z"); 18 | 19 | // Extract 7-Zip archive contents to /dev_hdd0/tmp/ 20 | Extract7zFile("/dev_hdd0/tmp/archive.7z", "/dev_hdd0/tmp"); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /include/7zAssetFile.h: -------------------------------------------------------------------------------- 1 | /* 7zFile.h -- File IO 2 | 2009-11-24 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_ASSETS_H 5 | #define __7Z_ASSETS_H 6 | 7 | #include "7zTypes.h" 8 | 9 | /* ---------- Memory Asset ---------- */ 10 | 11 | typedef struct { 12 | const void *asset; 13 | UInt64 length; 14 | UInt64 pos; 15 | } CSzAssetFile; 16 | 17 | WRes InAssetFile_Open(CSzAssetFile *p, const void *buffer, UInt64 buf_size); 18 | 19 | WRes AssetFile_Close(CSzAssetFile *p); 20 | 21 | typedef struct { 22 | ISeekInStream vt; 23 | CSzAssetFile assetFile; 24 | } CAssetFileInStream; 25 | 26 | void AssetFileInStream_CreateVTable(CAssetFileInStream *p); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /source/7zBuf.c: -------------------------------------------------------------------------------- 1 | /* 7zBuf.c -- Byte Buffer 2 | 2017-04-03 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "7zBuf.h" 7 | 8 | void Buf_Init(CBuf *p) 9 | { 10 | p->data = 0; 11 | p->size = 0; 12 | } 13 | 14 | int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc) 15 | { 16 | p->size = 0; 17 | if (size == 0) 18 | { 19 | p->data = 0; 20 | return 1; 21 | } 22 | p->data = (Byte *)ISzAlloc_Alloc(alloc, size); 23 | if (p->data) 24 | { 25 | p->size = size; 26 | return 1; 27 | } 28 | return 0; 29 | } 30 | 31 | void Buf_Free(CBuf *p, ISzAllocPtr alloc) 32 | { 33 | ISzAlloc_Free(alloc, p->data); 34 | p->data = 0; 35 | p->size = 0; 36 | } 37 | -------------------------------------------------------------------------------- /include/7zCrc.h: -------------------------------------------------------------------------------- 1 | /* 7zCrc.h -- CRC32 calculation 2 | 2013-01-18 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_CRC_H 5 | #define __7Z_CRC_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | extern UInt32 g_CrcTable[]; 12 | 13 | /* Call CrcGenerateTable one time before other CRC functions */ 14 | void MY_FAST_CALL CrcGenerateTable(void); 15 | 16 | #define CRC_INIT_VAL 0xFFFFFFFF 17 | #define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL) 18 | #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) 19 | 20 | UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); 21 | UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); 22 | 23 | EXTERN_C_END 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/7zBuf.h: -------------------------------------------------------------------------------- 1 | /* 7zBuf.h -- Byte Buffer 2 | 2017-04-03 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_BUF_H 5 | #define __7Z_BUF_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | typedef struct 12 | { 13 | Byte *data; 14 | size_t size; 15 | } CBuf; 16 | 17 | void Buf_Init(CBuf *p); 18 | int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc); 19 | void Buf_Free(CBuf *p, ISzAllocPtr alloc); 20 | 21 | typedef struct 22 | { 23 | Byte *data; 24 | size_t size; 25 | size_t pos; 26 | } CDynBuf; 27 | 28 | void DynBuf_Construct(CDynBuf *p); 29 | void DynBuf_SeekToBeg(CDynBuf *p); 30 | int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc); 31 | void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc); 32 | 33 | EXTERN_C_END 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /include/7zVersion.h: -------------------------------------------------------------------------------- 1 | #define MY_VER_MAJOR 19 2 | #define MY_VER_MINOR 00 3 | #define MY_VER_BUILD 0 4 | #define MY_VERSION_NUMBERS "19.00" 5 | #define MY_VERSION MY_VERSION_NUMBERS 6 | 7 | #ifdef MY_CPU_NAME 8 | #define MY_VERSION_CPU MY_VERSION " (" MY_CPU_NAME ")" 9 | #else 10 | #define MY_VERSION_CPU MY_VERSION 11 | #endif 12 | 13 | #define MY_DATE "2019-02-21" 14 | #undef MY_COPYRIGHT 15 | #undef MY_VERSION_COPYRIGHT_DATE 16 | #define MY_AUTHOR_NAME "Igor Pavlov" 17 | #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" 18 | #define MY_COPYRIGHT_CR "Copyright (c) 1999-2018 Igor Pavlov" 19 | 20 | #ifdef USE_COPYRIGHT_CR 21 | #define MY_COPYRIGHT MY_COPYRIGHT_CR 22 | #else 23 | #define MY_COPYRIGHT MY_COPYRIGHT_PD 24 | #endif 25 | 26 | #define MY_COPYRIGHT_DATE MY_COPYRIGHT " : " MY_DATE 27 | #define MY_VERSION_COPYRIGHT_DATE MY_VERSION_CPU " : " MY_COPYRIGHT " : " MY_DATE 28 | -------------------------------------------------------------------------------- /Makefile.psp: -------------------------------------------------------------------------------- 1 | TARGET_LIB = psp-libun7zip.a 2 | OBJS = source/7zAlloc.o source/7zCrc.o source/7zFile.o source/Bra.o source/Delta.o source/Ppmd7Dec.o source/7zAssetFile.o \ 3 | source/7zArcIn.o source/7zCrcOpt.o source/7zFunctions.o source/Bra86.o source/Lzma2Dec.o \ 4 | source/7zBuf.o source/7zDec.o source/7zStream.o source/BraIA64.o source/LzmaDec.o \ 5 | source/7zBuf2.o source/7zExtractor.o source/Bcj2.o source/CpuArch.o source/Ppmd7.o 6 | 7 | 8 | INCDIR = include 9 | CFLAGS = -O2 -Wall -D__PS4__ -D__PSP__ -D_GNU_SOURCE 10 | CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti 11 | ASFLAGS = $(CFLAGS) 12 | 13 | LIBDIR = 14 | LDFLAGS = 15 | 16 | PSPSDK=$(shell psp-config --pspsdk-path) 17 | include $(PSPSDK)/lib/build.mak 18 | 19 | install: $(TARGET_LIB) 20 | @echo Copying... 21 | @cp -frv include/7zExtractor.h $(PSPDEV)/psp/include/un7zip.h 22 | @cp -frv $(TARGET_LIB) $(PSPDEV)/psp/lib/libun7zip.a 23 | @echo lib installed! 24 | -------------------------------------------------------------------------------- /include/7zFunctions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by HZY on 2017/11/25. 3 | // 4 | 5 | #include "7zTypes.h" 6 | #include "7zFile.h" 7 | #include "7z.h" 8 | #include "7zBuf.h" 9 | 10 | #ifndef ANDROIDUN7ZIP_7ZFUNCTIONS_H 11 | #define ANDROIDUN7ZIP_7ZFUNCTIONS_H 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | void Print(const char *s); 18 | 19 | void PrintError(const char *s); 20 | 21 | SRes Utf16_To_Char(CBuf *buf, const UInt16 *s); 22 | 23 | WRes MyCreateDir(const UInt16 *name, const char *dir); 24 | 25 | WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name, const char *dir); 26 | 27 | SRes PrintString(const UInt16 *s); 28 | 29 | void UInt64ToStr(UInt64 value, char *s, int numDigits); 30 | 31 | char *UIntToStr(char *s, unsigned value, int numDigits); 32 | 33 | void ConvertFileTimeToString(const CNtfsFileTime *nt, char *s); 34 | 35 | void GetAttribString(UInt32 wa, BoolInt isDir, char *s); 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif 40 | 41 | #endif //ANDROIDUN7ZIP_7ZFUNCTIONS_H 42 | -------------------------------------------------------------------------------- /source/7zBuf2.c: -------------------------------------------------------------------------------- 1 | /* 7zBuf2.c -- Byte Buffer 2 | 2017-04-03 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include 7 | 8 | #include "7zBuf.h" 9 | 10 | void DynBuf_Construct(CDynBuf *p) 11 | { 12 | p->data = 0; 13 | p->size = 0; 14 | p->pos = 0; 15 | } 16 | 17 | void DynBuf_SeekToBeg(CDynBuf *p) 18 | { 19 | p->pos = 0; 20 | } 21 | 22 | int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc) 23 | { 24 | if (size > p->size - p->pos) 25 | { 26 | size_t newSize = p->pos + size; 27 | Byte *data; 28 | newSize += newSize / 4; 29 | data = (Byte *)ISzAlloc_Alloc(alloc, newSize); 30 | if (!data) 31 | return 0; 32 | p->size = newSize; 33 | if (p->pos != 0) 34 | memcpy(data, p->data, p->pos); 35 | ISzAlloc_Free(alloc, p->data); 36 | p->data = data; 37 | } 38 | if (size != 0) 39 | { 40 | memcpy(p->data + p->pos, buf, size); 41 | p->pos += size; 42 | } 43 | return 1; 44 | } 45 | 46 | void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc) 47 | { 48 | ISzAlloc_Free(alloc, p->data); 49 | p->data = 0; 50 | p->size = 0; 51 | p->pos = 0; 52 | } 53 | -------------------------------------------------------------------------------- /Makefile.vita: -------------------------------------------------------------------------------- 1 | TARGET = vita-libun7zip.a 2 | OBJS = source/7zAlloc.o source/7zCrc.o source/7zFile.o source/Bra.o source/Delta.o source/Ppmd7Dec.o source/7zAssetFile.o \ 3 | source/7zArcIn.o source/7zCrcOpt.o source/7zFunctions.o source/Bra86.o source/Lzma2Dec.o \ 4 | source/7zBuf.o source/7zDec.o source/7zStream.o source/BraIA64.o source/LzmaDec.o \ 5 | source/7zBuf2.o source/7zExtractor.o source/Bcj2.o source/CpuArch.o source/Ppmd7.o 6 | 7 | PREFIX = $(VITASDK)/bin/arm-vita-eabi 8 | CC = $(PREFIX)-gcc 9 | CXX = $(PREFIX)-g++ 10 | AR = $(PREFIX)-ar 11 | CFLAGS = -Wl,-q -Wall -O3 -Wno-unused-variable -Wno-unused-but-set-variable -ffat-lto-objects -flto -D__PSVITA__ -Iinclude 12 | CXXFLAGS = $(CFLAGS) -std=gnu++11 -fno-rtti 13 | 14 | .PHONY: all clean 15 | 16 | all: $(TARGET) 17 | 18 | $(TARGET): $(OBJS) 19 | $(AR) rcu $@ $^ 20 | 21 | clean: 22 | @rm -rf $(TARGET) $(OBJS) 23 | @echo "Cleaned up!" 24 | 25 | install: $(TARGET) 26 | @echo Copying... 27 | @mkdir -p $(DESTDIR)$(VITASDK)/arm-vita-eabi/lib/ 28 | @mkdir -p $(DESTDIR)$(VITASDK)/arm-vita-eabi/include/ 29 | @cp -frv include/7zExtractor.h $(DESTDIR)$(VITASDK)/arm-vita-eabi/include/un7zip.h 30 | @cp -frv $(TARGET) $(DESTDIR)$(VITASDK)/arm-vita-eabi/lib/libun7zip.a 31 | @echo lib installed! 32 | -------------------------------------------------------------------------------- /include/Compiler.h: -------------------------------------------------------------------------------- 1 | /* Compiler.h 2 | 2017-04-03 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_COMPILER_H 5 | #define __7Z_COMPILER_H 6 | 7 | #ifdef _MSC_VER 8 | 9 | #ifdef UNDER_CE 10 | #define RPC_NO_WINDOWS_H 11 | /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */ 12 | #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union 13 | #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int 14 | #endif 15 | 16 | #if _MSC_VER >= 1300 17 | #pragma warning(disable : 4996) // This function or variable may be unsafe 18 | #else 19 | #pragma warning(disable : 4511) // copy constructor could not be generated 20 | #pragma warning(disable : 4512) // assignment operator could not be generated 21 | #pragma warning(disable : 4514) // unreferenced inline function has been removed 22 | #pragma warning(disable : 4702) // unreachable code 23 | #pragma warning(disable : 4710) // not inlined 24 | #pragma warning(disable : 4714) // function marked as __forceinline not inlined 25 | #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information 26 | #endif 27 | 28 | #endif 29 | 30 | #define UNUSED_VAR(x) (void)x; 31 | /* #define UNUSED_VAR(x) x=x; */ 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /source/BraIA64.c: -------------------------------------------------------------------------------- 1 | /* BraIA64.c -- Converter for IA-64 code 2 | 2017-01-26 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "CpuArch.h" 7 | #include "Bra.h" 8 | 9 | SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) 10 | { 11 | SizeT i; 12 | if (size < 16) 13 | return 0; 14 | size -= 16; 15 | i = 0; 16 | do 17 | { 18 | unsigned m = ((UInt32)0x334B0000 >> (data[i] & 0x1E)) & 3; 19 | if (m) 20 | { 21 | m++; 22 | do 23 | { 24 | Byte *p = data + (i + (size_t)m * 5 - 8); 25 | if (((p[3] >> m) & 15) == 5 26 | && (((p[-1] | ((UInt32)p[0] << 8)) >> m) & 0x70) == 0) 27 | { 28 | unsigned raw = GetUi32(p); 29 | unsigned v = raw >> m; 30 | v = (v & 0xFFFFF) | ((v & (1 << 23)) >> 3); 31 | 32 | v <<= 4; 33 | if (encoding) 34 | v += ip + (UInt32)i; 35 | else 36 | v -= ip + (UInt32)i; 37 | v >>= 4; 38 | 39 | v &= 0x1FFFFF; 40 | v += 0x700000; 41 | v &= 0x8FFFFF; 42 | raw &= ~((UInt32)0x8FFFFF << m); 43 | raw |= (v << m); 44 | SetUi32(p, raw); 45 | } 46 | } 47 | while (++m <= 4); 48 | } 49 | i += 16; 50 | } 51 | while (i <= size); 52 | return i; 53 | } 54 | -------------------------------------------------------------------------------- /source/Delta.c: -------------------------------------------------------------------------------- 1 | /* Delta.c -- Delta converter 2 | 2009-05-26 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "Delta.h" 7 | 8 | void Delta_Init(Byte *state) 9 | { 10 | unsigned i; 11 | for (i = 0; i < DELTA_STATE_SIZE; i++) 12 | state[i] = 0; 13 | } 14 | 15 | static void MyMemCpy(Byte *dest, const Byte *src, unsigned size) 16 | { 17 | unsigned i; 18 | for (i = 0; i < size; i++) 19 | dest[i] = src[i]; 20 | } 21 | 22 | void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size) 23 | { 24 | Byte buf[DELTA_STATE_SIZE]; 25 | unsigned j = 0; 26 | MyMemCpy(buf, state, delta); 27 | { 28 | SizeT i; 29 | for (i = 0; i < size;) 30 | { 31 | for (j = 0; j < delta && i < size; i++, j++) 32 | { 33 | Byte b = data[i]; 34 | data[i] = (Byte)(b - buf[j]); 35 | buf[j] = b; 36 | } 37 | } 38 | } 39 | if (j == delta) 40 | j = 0; 41 | MyMemCpy(state, buf + j, delta - j); 42 | MyMemCpy(state + delta - j, buf, j); 43 | } 44 | 45 | void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size) 46 | { 47 | Byte buf[DELTA_STATE_SIZE]; 48 | unsigned j = 0; 49 | MyMemCpy(buf, state, delta); 50 | { 51 | SizeT i; 52 | for (i = 0; i < size;) 53 | { 54 | for (j = 0; j < delta && i < size; i++, j++) 55 | { 56 | buf[j] = data[i] = (Byte)(buf[j] + data[i]); 57 | } 58 | } 59 | } 60 | if (j == delta) 61 | j = 0; 62 | MyMemCpy(state, buf + j, delta - j); 63 | MyMemCpy(state + delta - j, buf, j); 64 | } 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # un7zip library 2 | 3 | This library provides 7-Zip (.7z) archive handling and extraction to the PlayStation 3 using the [PSL1GHT SDK](https://github.com/ps3dev/PSL1GHT/). 4 | 5 | ## Source Version 6 | 7 | - 7-Zip [19.00](https://sourceforge.net/projects/sevenzip/files/7-Zip/19.00/) (2019-02-21) 8 | - based on [AndroidUn7zip](https://github.com/hzy3774/AndroidUn7zip) 9 | 10 | ### Exports 11 | 12 | - Extract7zFile 13 | - un7z_ExtractArchive 14 | - un7z_ExtractAsset 15 | ```c 16 | int Extract7zFile(const char *srcFile, const char *destDir); 17 | int un7z_ExtractArchive(const char *srcFile, const char *destDir, callback7z_t callback, unsigned long inBufSize); 18 | int un7z_ExtractAsset(const void *buffer, unsigned long size, const char *destDir, callback7z_t callback, unsigned long inBufSize); 19 | ``` 20 | 21 | - Test7zFile 22 | - un7z_TestArchive 23 | - un7z_TestAsset 24 | ```c 25 | int Test7zFile(const char *srcFile); 26 | int un7z_TestArchive(const char *srcFile, callback7z_t callback, unsigned long inBufSize); 27 | int un7z_TestAsset(const void *buffer, unsigned long size, callback7z_t callback, unsigned long inBufSize); 28 | ``` 29 | 30 | - un7z_ListArchive 31 | - un7z_ListAsset 32 | ```c 33 | int un7z_ListArchive(const char *srcFile, callback7z_t callback); 34 | int un7z_ListAsset(const void *buffer, unsigned long size, callback7z_t callback); 35 | ``` 36 | 37 | ## Build/Install 38 | 39 | Build the library with: 40 | ``` 41 | make 42 | ``` 43 | 44 | Install the library to your PSL1GHT setup with: 45 | ``` 46 | make install 47 | ``` 48 | 49 | ## Documentation 50 | 51 | - [7-Zip SDK](https://www.7-zip.org/sdk.html) 52 | 53 | ## Sample app 54 | 55 | You can find a sample PSL1GHT app using the library [here](./example). 56 | 57 | ## License 58 | 59 | `libun7zip` is released under the [Apache-2.0 License](./LICENSE). 60 | -------------------------------------------------------------------------------- /include/7zFile.h: -------------------------------------------------------------------------------- 1 | /* 7zFile.h -- File IO 2 | 2017-04-03 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_FILE_H 5 | #define __7Z_FILE_H 6 | 7 | #ifdef _WIN32 8 | #define USE_WINDOWS_FILE 9 | #endif 10 | 11 | #ifdef USE_WINDOWS_FILE 12 | #include 13 | #else 14 | #include 15 | #endif 16 | 17 | #include "7zTypes.h" 18 | 19 | EXTERN_C_BEGIN 20 | 21 | /* ---------- File ---------- */ 22 | 23 | typedef struct 24 | { 25 | #ifdef USE_WINDOWS_FILE 26 | HANDLE handle; 27 | #else 28 | FILE *file; 29 | #endif 30 | } CSzFile; 31 | 32 | void File_Construct(CSzFile *p); 33 | #if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) 34 | WRes InFile_Open(CSzFile *p, const char *name); 35 | WRes OutFile_Open(CSzFile *p, const char *name); 36 | #endif 37 | #ifdef USE_WINDOWS_FILE 38 | WRes InFile_OpenW(CSzFile *p, const WCHAR *name); 39 | WRes OutFile_OpenW(CSzFile *p, const WCHAR *name); 40 | #endif 41 | WRes File_Close(CSzFile *p); 42 | 43 | /* reads max(*size, remain file's size) bytes */ 44 | WRes File_Read(CSzFile *p, void *data, size_t *size); 45 | 46 | /* writes *size bytes */ 47 | WRes File_Write(CSzFile *p, const void *data, size_t *size); 48 | 49 | WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); 50 | WRes File_GetLength(CSzFile *p, UInt64 *length); 51 | 52 | 53 | /* ---------- FileInStream ---------- */ 54 | 55 | typedef struct 56 | { 57 | ISeqInStream vt; 58 | CSzFile file; 59 | } CFileSeqInStream; 60 | 61 | void FileSeqInStream_CreateVTable(CFileSeqInStream *p); 62 | 63 | 64 | typedef struct 65 | { 66 | ISeekInStream vt; 67 | CSzFile file; 68 | } CFileInStream; 69 | 70 | void FileInStream_CreateVTable(CFileInStream *p); 71 | 72 | 73 | typedef struct 74 | { 75 | ISeqOutStream vt; 76 | CSzFile file; 77 | } CFileOutStream; 78 | 79 | void FileOutStream_CreateVTable(CFileOutStream *p); 80 | 81 | EXTERN_C_END 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /source/7zAlloc.c: -------------------------------------------------------------------------------- 1 | /* 7zAlloc.c -- Allocation functions 2 | 2017-04-03 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include 7 | 8 | #include "7zAlloc.h" 9 | 10 | /* #define _SZ_ALLOC_DEBUG */ 11 | /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ 12 | 13 | #ifdef _SZ_ALLOC_DEBUG 14 | 15 | #ifdef _WIN32 16 | #include 17 | #endif 18 | 19 | #include 20 | int g_allocCount = 0; 21 | int g_allocCountTemp = 0; 22 | 23 | #endif 24 | 25 | void *SzAlloc(ISzAllocPtr p, size_t size) 26 | { 27 | UNUSED_VAR(p); 28 | if (size == 0) 29 | return 0; 30 | #ifdef _SZ_ALLOC_DEBUG 31 | fprintf(stderr, "\nAlloc %10u bytes; count = %10d", (unsigned)size, g_allocCount); 32 | g_allocCount++; 33 | #endif 34 | return malloc(size); 35 | } 36 | 37 | void SzFree(ISzAllocPtr p, void *address) 38 | { 39 | UNUSED_VAR(p); 40 | #ifdef _SZ_ALLOC_DEBUG 41 | if (address != 0) 42 | { 43 | g_allocCount--; 44 | fprintf(stderr, "\nFree; count = %10d", g_allocCount); 45 | } 46 | #endif 47 | free(address); 48 | } 49 | 50 | void *SzAllocTemp(ISzAllocPtr p, size_t size) 51 | { 52 | UNUSED_VAR(p); 53 | if (size == 0) 54 | return 0; 55 | #ifdef _SZ_ALLOC_DEBUG 56 | fprintf(stderr, "\nAlloc_temp %10u bytes; count = %10d", (unsigned)size, g_allocCountTemp); 57 | g_allocCountTemp++; 58 | #ifdef _WIN32 59 | return HeapAlloc(GetProcessHeap(), 0, size); 60 | #endif 61 | #endif 62 | return malloc(size); 63 | } 64 | 65 | void SzFreeTemp(ISzAllocPtr p, void *address) 66 | { 67 | UNUSED_VAR(p); 68 | #ifdef _SZ_ALLOC_DEBUG 69 | if (address != 0) 70 | { 71 | g_allocCountTemp--; 72 | fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); 73 | } 74 | #ifdef _WIN32 75 | HeapFree(GetProcessHeap(), 0, address); 76 | return; 77 | #endif 78 | #endif 79 | free(address); 80 | } 81 | -------------------------------------------------------------------------------- /source/Bra86.c: -------------------------------------------------------------------------------- 1 | /* Bra86.c -- Converter for x86 code (BCJ) 2 | 2017-04-03 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "Bra.h" 7 | 8 | #define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0) 9 | 10 | SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) 11 | { 12 | SizeT pos = 0; 13 | UInt32 mask = *state & 7; 14 | if (size < 5) 15 | return 0; 16 | size -= 4; 17 | ip += 5; 18 | 19 | for (;;) 20 | { 21 | Byte *p = data + pos; 22 | const Byte *limit = data + size; 23 | for (; p < limit; p++) 24 | if ((*p & 0xFE) == 0xE8) 25 | break; 26 | 27 | { 28 | SizeT d = (SizeT)(p - data - pos); 29 | pos = (SizeT)(p - data); 30 | if (p >= limit) 31 | { 32 | *state = (d > 2 ? 0 : mask >> (unsigned)d); 33 | return pos; 34 | } 35 | if (d > 2) 36 | mask = 0; 37 | else 38 | { 39 | mask >>= (unsigned)d; 40 | if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(size_t)(mask >> 1) + 1]))) 41 | { 42 | mask = (mask >> 1) | 4; 43 | pos++; 44 | continue; 45 | } 46 | } 47 | } 48 | 49 | if (Test86MSByte(p[4])) 50 | { 51 | UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); 52 | UInt32 cur = ip + (UInt32)pos; 53 | pos += 5; 54 | if (encoding) 55 | v += cur; 56 | else 57 | v -= cur; 58 | if (mask != 0) 59 | { 60 | unsigned sh = (mask & 6) << 2; 61 | if (Test86MSByte((Byte)(v >> sh))) 62 | { 63 | v ^= (((UInt32)0x100 << sh) - 1); 64 | if (encoding) 65 | v += cur; 66 | else 67 | v -= cur; 68 | } 69 | mask = 0; 70 | } 71 | p[1] = (Byte)v; 72 | p[2] = (Byte)(v >> 8); 73 | p[3] = (Byte)(v >> 16); 74 | p[4] = (Byte)(0 - ((v >> 24) & 1)); 75 | } 76 | else 77 | { 78 | mask = (mask >> 1) | 4; 79 | pos++; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /include/Bra.h: -------------------------------------------------------------------------------- 1 | /* Bra.h -- Branch converters for executables 2 | 2013-01-18 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __BRA_H 5 | #define __BRA_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | /* 12 | These functions convert relative addresses to absolute addresses 13 | in CALL instructions to increase the compression ratio. 14 | 15 | In: 16 | data - data buffer 17 | size - size of data 18 | ip - current virtual Instruction Pinter (IP) value 19 | state - state variable for x86 converter 20 | encoding - 0 (for decoding), 1 (for encoding) 21 | 22 | Out: 23 | state - state variable for x86 converter 24 | 25 | Returns: 26 | The number of processed bytes. If you call these functions with multiple calls, 27 | you must start next call with first byte after block of processed bytes. 28 | 29 | Type Endian Alignment LookAhead 30 | 31 | x86 little 1 4 32 | ARMT little 2 2 33 | ARM little 4 0 34 | PPC big 4 0 35 | SPARC big 4 0 36 | IA64 little 16 0 37 | 38 | size must be >= Alignment + LookAhead, if it's not last block. 39 | If (size < Alignment + LookAhead), converter returns 0. 40 | 41 | Example: 42 | 43 | UInt32 ip = 0; 44 | for () 45 | { 46 | ; size must be >= Alignment + LookAhead, if it's not last block 47 | SizeT processed = Convert(data, size, ip, 1); 48 | data += processed; 49 | size -= processed; 50 | ip += processed; 51 | } 52 | */ 53 | 54 | #define x86_Convert_Init(state) { state = 0; } 55 | SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); 56 | SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); 57 | SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); 58 | SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); 59 | SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); 60 | SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); 61 | 62 | EXTERN_C_END 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /include/7zExtractor.h: -------------------------------------------------------------------------------- 1 | // 2 | // un7zip library by Bucanero 3 | // https://github.com/bucanero/libun7zip 4 | // 5 | // Based on https://github.com/hzy3774/AndroidUn7zip 6 | // by huzongyao on 17-11-24. 7 | // 8 | 9 | #ifndef __UN7ZIP_7ZEXTRACTOR_H 10 | #define __UN7ZIP_7ZEXTRACTOR_H 11 | 12 | #define UN7Z_IN_BUF_SIZE 0x80000 13 | 14 | #ifndef __7Z_TYPES_H 15 | #define SZ_OK 0 16 | #define SZ_ERROR_DATA 1 17 | #define SZ_ERROR_MEM 2 18 | #define SZ_ERROR_CRC 3 19 | #define SZ_ERROR_UNSUPPORTED 4 20 | #define SZ_ERROR_PARAM 5 21 | #define SZ_ERROR_INPUT_EOF 6 22 | #define SZ_ERROR_OUTPUT_EOF 7 23 | #define SZ_ERROR_READ 8 24 | #define SZ_ERROR_WRITE 9 25 | #define SZ_ERROR_PROGRESS 10 26 | #define SZ_ERROR_FAIL 11 27 | #define SZ_ERROR_THREAD 12 28 | #define SZ_ERROR_ARCHIVE 16 29 | #define SZ_ERROR_NO_ARCHIVE 17 30 | #endif 31 | 32 | #define List7zFile un7z_ListArchive 33 | #define Test7zFileEx un7z_TestArchive 34 | #define Extract7zFileEx un7z_ExtractArchive 35 | #define Test7zFile(File) un7z_TestArchive(File, NULL, UN7Z_IN_BUF_SIZE) 36 | #define Extract7zFile(File, Dir) un7z_ExtractArchive(File, Dir, NULL, UN7Z_IN_BUF_SIZE) 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | /* 43 | void callback(const char* fileName, unsigned long fileSize, unsigned int fileNum, unsigned int totalFiles); 44 | */ 45 | typedef void (*callback7z_t)(const char*, unsigned long, unsigned int, unsigned int); 46 | 47 | // from storage 7z file 48 | int un7z_ListArchive(const char *srcFile, callback7z_t callback); 49 | int un7z_TestArchive(const char *srcFile, callback7z_t callback, unsigned long inBufSize); 50 | int un7z_ExtractArchive(const char *srcFile, const char *destDir, callback7z_t callback, unsigned long inBufSize); 51 | 52 | // from memory 7z buffer 53 | int un7z_ListAsset(const void *buffer, unsigned long size, callback7z_t callback); 54 | int un7z_TestAsset(const void *buffer, unsigned long size, callback7z_t callback, unsigned long inBufSize); 55 | int un7z_ExtractAsset(const void *buffer, unsigned long size, const char *destDir, callback7z_t callback, unsigned long inBufSize); 56 | 57 | #ifdef __cplusplus 58 | } 59 | #endif 60 | 61 | #endif // __UN7ZIP_7ZEXTRACTOR_H 62 | -------------------------------------------------------------------------------- /source/7zAssetFile.c: -------------------------------------------------------------------------------- 1 | /* 7zFile.c -- File IO 2 | 2009-11-24 : Igor Pavlov : Public domain */ 3 | #include 4 | #include "7zAssetFile.h" 5 | 6 | 7 | WRes InAssetFile_Open(CSzAssetFile *p, const void *buffer, UInt64 buf_size) { 8 | p->asset = buffer; 9 | p->length = buf_size; 10 | p->pos = 0; 11 | return 0; 12 | } 13 | 14 | WRes AssetFile_Close(CSzAssetFile *p) { 15 | if (p->asset != NULL) { 16 | p->length = 0; 17 | p->pos = 0; 18 | p->asset = NULL; 19 | } 20 | return 0; 21 | } 22 | 23 | WRes AssetFile_Read(CSzAssetFile *p, void *data, size_t *size) { 24 | size_t originalSize = *size; 25 | if (originalSize == 0) { 26 | return 0; 27 | } 28 | if (!p) return -1; 29 | 30 | if (p->pos + originalSize > p->length) { 31 | originalSize = p->length - p->pos; 32 | } 33 | memcpy(data, p->asset + p->pos, originalSize); 34 | if (*size != originalSize) { 35 | *size = originalSize; 36 | return -1; 37 | } 38 | return 0; 39 | } 40 | 41 | WRes AssetFile_Seek(CSzAssetFile *p, Int64 *pos, ESzSeek origin) { 42 | if (!p) return -1; 43 | 44 | switch (origin) { 45 | case SZ_SEEK_SET: 46 | p->pos = *pos; 47 | break; 48 | case SZ_SEEK_CUR: 49 | p->pos += *pos; 50 | break; 51 | case SZ_SEEK_END: 52 | p->pos = p->length + *pos; 53 | break; 54 | default: 55 | return -1; 56 | } 57 | if (p->pos < 0) { 58 | p->pos = 0; 59 | return -1; 60 | } 61 | if (p->pos > p->length) { 62 | p->pos = p->length; 63 | } 64 | 65 | *pos = p->pos; 66 | return 0; 67 | } 68 | 69 | static SRes AssetFileInStream_Read(const ISeekInStream *pp, void *buf, size_t *size) { 70 | CAssetFileInStream *p = (CAssetFileInStream *) pp; 71 | return (AssetFile_Read(&p->assetFile, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; 72 | } 73 | 74 | static SRes AssetFileInStream_Seek(const ISeekInStream *pp, Int64 *pos, ESzSeek origin) { 75 | CAssetFileInStream *p = (CAssetFileInStream *) pp; 76 | return AssetFile_Seek(&p->assetFile, pos, origin); 77 | } 78 | 79 | void AssetFileInStream_CreateVTable(CAssetFileInStream *p) { 80 | p->vt.Read = AssetFileInStream_Read; 81 | p->vt.Seek = AssetFileInStream_Seek; 82 | } 83 | -------------------------------------------------------------------------------- /include/Ppmd.h: -------------------------------------------------------------------------------- 1 | /* Ppmd.h -- PPMD codec common code 2 | 2017-04-03 : Igor Pavlov : Public domain 3 | This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ 4 | 5 | #ifndef __PPMD_H 6 | #define __PPMD_H 7 | 8 | #include "CpuArch.h" 9 | 10 | EXTERN_C_BEGIN 11 | 12 | #ifdef MY_CPU_32BIT 13 | #define PPMD_32BIT 14 | #endif 15 | 16 | #define PPMD_INT_BITS 7 17 | #define PPMD_PERIOD_BITS 7 18 | #define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS)) 19 | 20 | #define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift)) 21 | #define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2) 22 | #define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob)) 23 | #define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob)) 24 | 25 | #define PPMD_N1 4 26 | #define PPMD_N2 4 27 | #define PPMD_N3 4 28 | #define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4) 29 | #define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4) 30 | 31 | #pragma pack(push, 1) 32 | /* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */ 33 | 34 | /* SEE-contexts for PPM-contexts with masked symbols */ 35 | typedef struct 36 | { 37 | UInt16 Summ; /* Freq */ 38 | Byte Shift; /* Speed of Freq change; low Shift is for fast change */ 39 | Byte Count; /* Count to next change of Shift */ 40 | } CPpmd_See; 41 | 42 | #define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \ 43 | { (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); } 44 | 45 | typedef struct 46 | { 47 | Byte Symbol; 48 | Byte Freq; 49 | UInt16 SuccessorLow; 50 | UInt16 SuccessorHigh; 51 | } CPpmd_State; 52 | 53 | #pragma pack(pop) 54 | 55 | typedef 56 | #ifdef PPMD_32BIT 57 | CPpmd_State * 58 | #else 59 | UInt32 60 | #endif 61 | CPpmd_State_Ref; 62 | 63 | typedef 64 | #ifdef PPMD_32BIT 65 | void * 66 | #else 67 | UInt32 68 | #endif 69 | CPpmd_Void_Ref; 70 | 71 | typedef 72 | #ifdef PPMD_32BIT 73 | Byte * 74 | #else 75 | UInt32 76 | #endif 77 | CPpmd_Byte_Ref; 78 | 79 | #define PPMD_SetAllBitsIn256Bytes(p) \ 80 | { size_t z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \ 81 | p[z+7] = p[z+6] = p[z+5] = p[z+4] = p[z+3] = p[z+2] = p[z+1] = p[z+0] = ~(size_t)0; }} 82 | 83 | EXTERN_C_END 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /Makefile.PS4: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | # Clear the implicit built in rules 3 | #--------------------------------------------------------------------------------- 4 | .SUFFIXES: 5 | #--------------------------------------------------------------------------------- 6 | 7 | ifeq ($(strip $(OO_PS4_TOOLCHAIN)),) 8 | $(error "Please set OO_PS4_TOOLCHAIN in your environment. export OO_PS4_TOOLCHAIN=") 9 | endif 10 | 11 | include $(OO_PS4_TOOLCHAIN)/build_rules.mk 12 | 13 | #--------------------------------------------------------------------------------- 14 | ifeq ($(strip $(PLATFORM)),) 15 | #--------------------------------------------------------------------------------- 16 | export BASEDIR := $(CURDIR) 17 | export DEPS := $(BASEDIR)/deps 18 | export LIBS := $(BASEDIR)/lib 19 | 20 | #--------------------------------------------------------------------------------- 21 | else 22 | #--------------------------------------------------------------------------------- 23 | 24 | export LIBDIR := $(LIBS)/$(PLATFORM) 25 | export DEPSDIR := $(DEPS)/$(PLATFORM) 26 | 27 | #--------------------------------------------------------------------------------- 28 | endif 29 | #--------------------------------------------------------------------------------- 30 | 31 | TARGET := build-ps4/libun7zip 32 | BUILD := build-ps4 33 | SOURCE := source 34 | INCLUDE := include 35 | DATA := data 36 | LIBS := 37 | 38 | CFLAGS += --target=x86_64-pc-freebsd12-elf -fPIC -funwind-tables -c $(EXTRAFLAGS) -isysroot $(OO_PS4_TOOLCHAIN) -isystem $(OO_PS4_TOOLCHAIN)/include $(INCLUDES) 39 | CXXFLAGS += $(CFLAGS) -isystem $(OO_PS4_TOOLCHAIN)/include/c++/v1 40 | CXXFLAGS += -DLITTLE_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DRARDLL 41 | 42 | ifneq ($(BUILD),$(notdir $(CURDIR))) 43 | 44 | export OUTPUT := $(CURDIR)/$(TARGET) 45 | export VPATH := $(foreach dir,$(SOURCE),$(CURDIR)/$(dir)) \ 46 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 47 | export BUILDDIR := $(CURDIR)/$(BUILD) 48 | export DEPSDIR := $(BUILDDIR) 49 | 50 | CFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.c))) 51 | CXXFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.cpp))) 52 | SFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.S))) 53 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.bin))) 54 | 55 | export OFILES := $(CFILES:.c=.o) \ 56 | $(CXXFILES:.cpp=.o) \ 57 | $(SFILES:.S=.o) \ 58 | $(BINFILES:.bin=.bin.o) 59 | 60 | export BINFILES := $(BINFILES:.bin=.bin.h) 61 | 62 | export INCLUDES = $(foreach dir,$(INCLUDE),-I$(CURDIR)/$(dir)) \ 63 | -I$(CURDIR)/$(BUILD) -I$(OO_PS4_TOOLCHAIN)/include 64 | 65 | .PHONY: $(BUILD) install clean 66 | 67 | $(BUILD): 68 | @[ -d $@ ] || mkdir -p $@ 69 | @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.PS4 70 | 71 | install: $(BUILD) 72 | @echo Copying... 73 | @cp -frv include/7zExtractor.h $(OO_PS4_TOOLCHAIN)/include/un7zip.h 74 | @cp -frv $(TARGET).a $(OO_PS4_TOOLCHAIN)/lib 75 | @echo lib installed! 76 | clean: 77 | @echo Clean... 78 | @rm -rf $(BUILD) $(OUTPUT).elf $(OUTPUT).self $(OUTPUT).a 79 | 80 | else 81 | 82 | DEPENDS := $(OFILES:.o=.d) 83 | 84 | $(OUTPUT).a: $(OFILES) 85 | $(OFILES): $(BINFILES) 86 | 87 | -include $(DEPENDS) 88 | 89 | endif 90 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | # Clear the implicit built in rules 3 | #--------------------------------------------------------------------------------- 4 | .SUFFIXES: 5 | #--------------------------------------------------------------------------------- 6 | 7 | ifeq ($(strip $(PSL1GHT)),) 8 | $(error "Please set PSL1GHT in your environment. export PSL1GHT=") 9 | endif 10 | 11 | include $(PSL1GHT)/ppu_rules 12 | 13 | 14 | 15 | #--------------------------------------------------------------------------------- 16 | ifeq ($(strip $(PLATFORM)),) 17 | #--------------------------------------------------------------------------------- 18 | export BASEDIR := $(CURDIR) 19 | export DEPS := $(BASEDIR)/deps 20 | export LIBS := $(BASEDIR)/lib 21 | 22 | #--------------------------------------------------------------------------------- 23 | else 24 | #--------------------------------------------------------------------------------- 25 | 26 | export LIBDIR := $(LIBS)/$(PLATFORM) 27 | export DEPSDIR := $(DEPS)/$(PLATFORM) 28 | 29 | #--------------------------------------------------------------------------------- 30 | endif 31 | #--------------------------------------------------------------------------------- 32 | 33 | TARGET := libun7zip 34 | BUILD := build 35 | SOURCE := source 36 | INCLUDE := include 37 | DATA := data 38 | LIBS := 39 | 40 | CFLAGS += -O2 -Wall -mcpu=cell $(MACHDEP) -fno-strict-aliasing $(INCLUDES) 41 | CXXFLAGS += -O2 -mcpu=cell $(MACHDEP) -fno-strict-aliasing $(INCLUDES) 42 | 43 | LD := ppu-ld 44 | 45 | ifneq ($(BUILD),$(notdir $(CURDIR))) 46 | 47 | export OUTPUT := $(CURDIR)/$(TARGET) 48 | export VPATH := $(foreach dir,$(SOURCE),$(CURDIR)/$(dir)) \ 49 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 50 | export BUILDDIR := $(CURDIR)/$(BUILD) 51 | export DEPSDIR := $(BUILDDIR) 52 | 53 | CFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.c))) 54 | CXXFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.cpp))) 55 | SFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.S))) 56 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.bin))) 57 | VCGFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.vcg))) 58 | VSAFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.vsa))) 59 | 60 | 61 | export OFILES := $(CFILES:.c=.o) \ 62 | $(CXXFILES:.cpp=.o) \ 63 | $(SFILES:.S=.o) \ 64 | $(BINFILES:.bin=.bin.o) \ 65 | $(VCGFILES:.vcg=.vcg.o) \ 66 | $(VSAFILES:.vsa=.vsa.o) 67 | 68 | export BINFILES := $(BINFILES:.bin=.bin.h) 69 | export VCGFILES := $(VCGFILES:.vcg=.vcg.h) 70 | export VSAFILES := $(VSAFILES:.vsa=.vsa.h) 71 | 72 | export INCLUDES = $(foreach dir,$(INCLUDE),-I$(CURDIR)/$(dir)) \ 73 | -I$(CURDIR)/$(BUILD) -I$(PSL1GHT)/ppu/include -I$(PORTLIBS)/include 74 | 75 | .PHONY: $(BUILD) install clean shader 76 | 77 | $(BUILD): 78 | @[ -d $@ ] || mkdir -p $@ 79 | @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 80 | 81 | install: $(BUILD) 82 | @echo Copying... 83 | @cp -frv include/7zExtractor.h $(PORTLIBS)/include/un7zip.h 84 | @cp -frv $(TARGET).a $(PORTLIBS)/lib 85 | @echo lib installed! 86 | clean: 87 | @echo Clean... 88 | @rm -rf $(BUILD) $(OUTPUT).elf $(OUTPUT).self $(OUTPUT).a 89 | 90 | else 91 | 92 | DEPENDS := $(OFILES:.o=.d) 93 | 94 | $(OUTPUT).a: $(OFILES) 95 | $(OFILES): $(BINFILES) $(VCGFILES) $(VSAFILES) 96 | 97 | -include $(DEPENDS) 98 | 99 | endif -------------------------------------------------------------------------------- /source/7zCrc.c: -------------------------------------------------------------------------------- 1 | /* 7zCrc.c -- CRC32 init 2 | 2017-06-06 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "7zCrc.h" 7 | #include "CpuArch.h" 8 | 9 | #define kCrcPoly 0xEDB88320 10 | 11 | #ifdef MY_CPU_LE 12 | #define CRC_NUM_TABLES 8 13 | #else 14 | #define CRC_NUM_TABLES 9 15 | 16 | #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) 17 | 18 | UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table); 19 | UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table); 20 | #endif 21 | 22 | #ifndef MY_CPU_BE 23 | UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); 24 | UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); 25 | #endif 26 | 27 | typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); 28 | 29 | CRC_FUNC g_CrcUpdateT4; 30 | CRC_FUNC g_CrcUpdateT8; 31 | CRC_FUNC g_CrcUpdate; 32 | 33 | UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; 34 | 35 | UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) 36 | { 37 | return g_CrcUpdate(v, data, size, g_CrcTable); 38 | } 39 | 40 | UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) 41 | { 42 | return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL; 43 | } 44 | 45 | #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) 46 | 47 | UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) 48 | { 49 | const Byte *p = (const Byte *)data; 50 | const Byte *pEnd = p + size; 51 | for (; p != pEnd; p++) 52 | v = CRC_UPDATE_BYTE_2(v, *p); 53 | return v; 54 | } 55 | 56 | void MY_FAST_CALL CrcGenerateTable() 57 | { 58 | UInt32 i; 59 | for (i = 0; i < 256; i++) 60 | { 61 | UInt32 r = i; 62 | unsigned j; 63 | for (j = 0; j < 8; j++) 64 | r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1))); 65 | g_CrcTable[i] = r; 66 | } 67 | for (i = 256; i < 256 * CRC_NUM_TABLES; i++) 68 | { 69 | UInt32 r = g_CrcTable[(size_t)i - 256]; 70 | g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); 71 | } 72 | 73 | #if CRC_NUM_TABLES < 4 74 | 75 | g_CrcUpdate = CrcUpdateT1; 76 | 77 | #else 78 | 79 | #ifdef MY_CPU_LE 80 | 81 | g_CrcUpdateT4 = CrcUpdateT4; 82 | g_CrcUpdate = CrcUpdateT4; 83 | 84 | #if CRC_NUM_TABLES >= 8 85 | g_CrcUpdateT8 = CrcUpdateT8; 86 | 87 | #ifdef MY_CPU_X86_OR_AMD64 88 | if (!CPU_Is_InOrder()) 89 | #endif 90 | g_CrcUpdate = CrcUpdateT8; 91 | #endif 92 | 93 | #else 94 | { 95 | #ifndef MY_CPU_BE 96 | UInt32 k = 0x01020304; 97 | const Byte *p = (const Byte *)&k; 98 | if (p[0] == 4 && p[1] == 3) 99 | { 100 | g_CrcUpdateT4 = CrcUpdateT4; 101 | g_CrcUpdate = CrcUpdateT4; 102 | #if CRC_NUM_TABLES >= 8 103 | g_CrcUpdateT8 = CrcUpdateT8; 104 | g_CrcUpdate = CrcUpdateT8; 105 | #endif 106 | } 107 | else if (p[0] != 1 || p[1] != 2) 108 | g_CrcUpdate = CrcUpdateT1; 109 | else 110 | #endif 111 | { 112 | for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) 113 | { 114 | UInt32 x = g_CrcTable[(size_t)i - 256]; 115 | g_CrcTable[i] = CRC_UINT32_SWAP(x); 116 | } 117 | g_CrcUpdateT4 = CrcUpdateT1_BeT4; 118 | g_CrcUpdate = CrcUpdateT1_BeT4; 119 | #if CRC_NUM_TABLES >= 8 120 | g_CrcUpdateT8 = CrcUpdateT1_BeT8; 121 | g_CrcUpdate = CrcUpdateT1_BeT8; 122 | #endif 123 | } 124 | } 125 | #endif 126 | 127 | #endif 128 | } 129 | -------------------------------------------------------------------------------- /include/Bcj2.h: -------------------------------------------------------------------------------- 1 | /* Bcj2.h -- BCJ2 Converter for x86 code 2 | 2014-11-10 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __BCJ2_H 5 | #define __BCJ2_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | #define BCJ2_NUM_STREAMS 4 12 | 13 | enum 14 | { 15 | BCJ2_STREAM_MAIN, 16 | BCJ2_STREAM_CALL, 17 | BCJ2_STREAM_JUMP, 18 | BCJ2_STREAM_RC 19 | }; 20 | 21 | enum 22 | { 23 | BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS, 24 | BCJ2_DEC_STATE_ORIG_1, 25 | BCJ2_DEC_STATE_ORIG_2, 26 | BCJ2_DEC_STATE_ORIG_3, 27 | 28 | BCJ2_DEC_STATE_ORIG, 29 | BCJ2_DEC_STATE_OK 30 | }; 31 | 32 | enum 33 | { 34 | BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS, 35 | BCJ2_ENC_STATE_OK 36 | }; 37 | 38 | 39 | #define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP) 40 | 41 | /* 42 | CBcj2Dec / CBcj2Enc 43 | bufs sizes: 44 | BUF_SIZE(n) = lims[n] - bufs[n] 45 | bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4: 46 | (BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0 47 | (BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0 48 | */ 49 | 50 | /* 51 | CBcj2Dec: 52 | dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions: 53 | bufs[BCJ2_STREAM_MAIN] >= dest && 54 | bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv + 55 | BUF_SIZE(BCJ2_STREAM_CALL) + 56 | BUF_SIZE(BCJ2_STREAM_JUMP) 57 | tempReserv = 0 : for first call of Bcj2Dec_Decode 58 | tempReserv = 4 : for any other calls of Bcj2Dec_Decode 59 | overlap with offset = 1 is not allowed 60 | */ 61 | 62 | typedef struct 63 | { 64 | const Byte *bufs[BCJ2_NUM_STREAMS]; 65 | const Byte *lims[BCJ2_NUM_STREAMS]; 66 | Byte *dest; 67 | const Byte *destLim; 68 | 69 | unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */ 70 | 71 | UInt32 ip; 72 | Byte temp[4]; 73 | UInt32 range; 74 | UInt32 code; 75 | UInt16 probs[2 + 256]; 76 | } CBcj2Dec; 77 | 78 | void Bcj2Dec_Init(CBcj2Dec *p); 79 | 80 | /* Returns: SZ_OK or SZ_ERROR_DATA */ 81 | SRes Bcj2Dec_Decode(CBcj2Dec *p); 82 | 83 | #define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0) 84 | 85 | 86 | 87 | typedef enum 88 | { 89 | BCJ2_ENC_FINISH_MODE_CONTINUE, 90 | BCJ2_ENC_FINISH_MODE_END_BLOCK, 91 | BCJ2_ENC_FINISH_MODE_END_STREAM 92 | } EBcj2Enc_FinishMode; 93 | 94 | typedef struct 95 | { 96 | Byte *bufs[BCJ2_NUM_STREAMS]; 97 | const Byte *lims[BCJ2_NUM_STREAMS]; 98 | const Byte *src; 99 | const Byte *srcLim; 100 | 101 | unsigned state; 102 | EBcj2Enc_FinishMode finishMode; 103 | 104 | Byte prevByte; 105 | 106 | Byte cache; 107 | UInt32 range; 108 | UInt64 low; 109 | UInt64 cacheSize; 110 | 111 | UInt32 ip; 112 | 113 | /* 32-bit ralative offset in JUMP/CALL commands is 114 | - (mod 4 GB) in 32-bit mode 115 | - signed Int32 in 64-bit mode 116 | We use (mod 4 GB) check for fileSize. 117 | Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */ 118 | UInt32 fileIp; 119 | UInt32 fileSize; /* (fileSize <= ((UInt32)1 << 31)), 0 means no_limit */ 120 | UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)), 0 means desable_conversion */ 121 | 122 | UInt32 tempTarget; 123 | unsigned tempPos; 124 | Byte temp[4 * 2]; 125 | 126 | unsigned flushPos; 127 | 128 | UInt16 probs[2 + 256]; 129 | } CBcj2Enc; 130 | 131 | void Bcj2Enc_Init(CBcj2Enc *p); 132 | void Bcj2Enc_Encode(CBcj2Enc *p); 133 | 134 | #define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos) 135 | #define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5) 136 | 137 | 138 | #define BCJ2_RELAT_LIMIT_NUM_BITS 26 139 | #define BCJ2_RELAT_LIMIT ((UInt32)1 << BCJ2_RELAT_LIMIT_NUM_BITS) 140 | 141 | /* limit for CBcj2Enc::fileSize variable */ 142 | #define BCJ2_FileSize_MAX ((UInt32)1 << 31) 143 | 144 | EXTERN_C_END 145 | 146 | #endif 147 | -------------------------------------------------------------------------------- /source/7zCrcOpt.c: -------------------------------------------------------------------------------- 1 | /* 7zCrcOpt.c -- CRC32 calculation 2 | 2017-04-03 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "CpuArch.h" 7 | 8 | #ifndef MY_CPU_BE 9 | 10 | #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) 11 | 12 | UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) 13 | { 14 | const Byte *p = (const Byte *)data; 15 | for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) 16 | v = CRC_UPDATE_BYTE_2(v, *p); 17 | for (; size >= 4; size -= 4, p += 4) 18 | { 19 | v ^= *(const UInt32 *)p; 20 | v = 21 | (table + 0x300)[((v ) & 0xFF)] 22 | ^ (table + 0x200)[((v >> 8) & 0xFF)] 23 | ^ (table + 0x100)[((v >> 16) & 0xFF)] 24 | ^ (table + 0x000)[((v >> 24))]; 25 | } 26 | for (; size > 0; size--, p++) 27 | v = CRC_UPDATE_BYTE_2(v, *p); 28 | return v; 29 | } 30 | 31 | UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) 32 | { 33 | const Byte *p = (const Byte *)data; 34 | for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++) 35 | v = CRC_UPDATE_BYTE_2(v, *p); 36 | for (; size >= 8; size -= 8, p += 8) 37 | { 38 | UInt32 d; 39 | v ^= *(const UInt32 *)p; 40 | v = 41 | (table + 0x700)[((v ) & 0xFF)] 42 | ^ (table + 0x600)[((v >> 8) & 0xFF)] 43 | ^ (table + 0x500)[((v >> 16) & 0xFF)] 44 | ^ (table + 0x400)[((v >> 24))]; 45 | d = *((const UInt32 *)p + 1); 46 | v ^= 47 | (table + 0x300)[((d ) & 0xFF)] 48 | ^ (table + 0x200)[((d >> 8) & 0xFF)] 49 | ^ (table + 0x100)[((d >> 16) & 0xFF)] 50 | ^ (table + 0x000)[((d >> 24))]; 51 | } 52 | for (; size > 0; size--, p++) 53 | v = CRC_UPDATE_BYTE_2(v, *p); 54 | return v; 55 | } 56 | 57 | #endif 58 | 59 | 60 | #ifndef MY_CPU_LE 61 | 62 | #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) 63 | 64 | #define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8)) 65 | 66 | UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table) 67 | { 68 | const Byte *p = (const Byte *)data; 69 | table += 0x100; 70 | v = CRC_UINT32_SWAP(v); 71 | for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) 72 | v = CRC_UPDATE_BYTE_2_BE(v, *p); 73 | for (; size >= 4; size -= 4, p += 4) 74 | { 75 | v ^= *(const UInt32 *)p; 76 | v = 77 | (table + 0x000)[((v ) & 0xFF)] 78 | ^ (table + 0x100)[((v >> 8) & 0xFF)] 79 | ^ (table + 0x200)[((v >> 16) & 0xFF)] 80 | ^ (table + 0x300)[((v >> 24))]; 81 | } 82 | for (; size > 0; size--, p++) 83 | v = CRC_UPDATE_BYTE_2_BE(v, *p); 84 | return CRC_UINT32_SWAP(v); 85 | } 86 | 87 | UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table) 88 | { 89 | const Byte *p = (const Byte *)data; 90 | table += 0x100; 91 | v = CRC_UINT32_SWAP(v); 92 | for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++) 93 | v = CRC_UPDATE_BYTE_2_BE(v, *p); 94 | for (; size >= 8; size -= 8, p += 8) 95 | { 96 | UInt32 d; 97 | v ^= *(const UInt32 *)p; 98 | v = 99 | (table + 0x400)[((v ) & 0xFF)] 100 | ^ (table + 0x500)[((v >> 8) & 0xFF)] 101 | ^ (table + 0x600)[((v >> 16) & 0xFF)] 102 | ^ (table + 0x700)[((v >> 24))]; 103 | d = *((const UInt32 *)p + 1); 104 | v ^= 105 | (table + 0x000)[((d ) & 0xFF)] 106 | ^ (table + 0x100)[((d >> 8) & 0xFF)] 107 | ^ (table + 0x200)[((d >> 16) & 0xFF)] 108 | ^ (table + 0x300)[((d >> 24))]; 109 | } 110 | for (; size > 0; size--, p++) 111 | v = CRC_UPDATE_BYTE_2_BE(v, *p); 112 | return CRC_UINT32_SWAP(v); 113 | } 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /include/Lzma2Dec.h: -------------------------------------------------------------------------------- 1 | /* Lzma2Dec.h -- LZMA2 Decoder 2 | 2018-02-19 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __LZMA2_DEC_H 5 | #define __LZMA2_DEC_H 6 | 7 | #include "LzmaDec.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | /* ---------- State Interface ---------- */ 12 | 13 | typedef struct 14 | { 15 | unsigned state; 16 | Byte control; 17 | Byte needInitLevel; 18 | Byte isExtraMode; 19 | Byte _pad_; 20 | UInt32 packSize; 21 | UInt32 unpackSize; 22 | CLzmaDec decoder; 23 | } CLzma2Dec; 24 | 25 | #define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder) 26 | #define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc) 27 | #define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc) 28 | 29 | SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc); 30 | SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc); 31 | void Lzma2Dec_Init(CLzma2Dec *p); 32 | 33 | /* 34 | finishMode: 35 | It has meaning only if the decoding reaches output limit (*destLen or dicLimit). 36 | LZMA_FINISH_ANY - use smallest number of input bytes 37 | LZMA_FINISH_END - read EndOfStream marker after decoding 38 | 39 | Returns: 40 | SZ_OK 41 | status: 42 | LZMA_STATUS_FINISHED_WITH_MARK 43 | LZMA_STATUS_NOT_FINISHED 44 | LZMA_STATUS_NEEDS_MORE_INPUT 45 | SZ_ERROR_DATA - Data error 46 | */ 47 | 48 | SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, 49 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); 50 | 51 | SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, 52 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); 53 | 54 | 55 | /* ---------- LZMA2 block and chunk parsing ---------- */ 56 | 57 | /* 58 | Lzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data. 59 | It can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code: 60 | - LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input. 61 | - LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read. 62 | CLzma2Dec::unpackSize contains unpack size of that chunk 63 | */ 64 | 65 | typedef enum 66 | { 67 | /* 68 | LZMA_STATUS_NOT_SPECIFIED // data error 69 | LZMA_STATUS_FINISHED_WITH_MARK 70 | LZMA_STATUS_NOT_FINISHED // 71 | LZMA_STATUS_NEEDS_MORE_INPUT 72 | LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK // unused 73 | */ 74 | LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1, 75 | LZMA2_PARSE_STATUS_NEW_CHUNK 76 | } ELzma2ParseStatus; 77 | 78 | ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p, 79 | SizeT outSize, // output size 80 | const Byte *src, SizeT *srcLen, 81 | int checkFinishBlock // set (checkFinishBlock = 1), if it must read full input data, if decoder.dicPos reaches blockMax position. 82 | ); 83 | 84 | /* 85 | LZMA2 parser doesn't decode LZMA chunks, so we must read 86 | full input LZMA chunk to decode some part of LZMA chunk. 87 | 88 | Lzma2Dec_GetUnpackExtra() returns the value that shows 89 | max possible number of output bytes that can be output by decoder 90 | at current input positon. 91 | */ 92 | 93 | #define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0); 94 | 95 | 96 | /* ---------- One Call Interface ---------- */ 97 | 98 | /* 99 | finishMode: 100 | It has meaning only if the decoding reaches output limit (*destLen). 101 | LZMA_FINISH_ANY - use smallest number of input bytes 102 | LZMA_FINISH_END - read EndOfStream marker after decoding 103 | 104 | Returns: 105 | SZ_OK 106 | status: 107 | LZMA_STATUS_FINISHED_WITH_MARK 108 | LZMA_STATUS_NOT_FINISHED 109 | SZ_ERROR_DATA - Data error 110 | SZ_ERROR_MEM - Memory allocation error 111 | SZ_ERROR_UNSUPPORTED - Unsupported properties 112 | SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). 113 | */ 114 | 115 | SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, 116 | Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc); 117 | 118 | EXTERN_C_END 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /include/Ppmd7.h: -------------------------------------------------------------------------------- 1 | /* Ppmd7.h -- PPMdH compression codec 2 | 2018-07-04 : Igor Pavlov : Public domain 3 | This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ 4 | 5 | /* This code supports virtual RangeDecoder and includes the implementation 6 | of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H. 7 | If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */ 8 | 9 | #ifndef __PPMD7_H 10 | #define __PPMD7_H 11 | 12 | #include "Ppmd.h" 13 | 14 | EXTERN_C_BEGIN 15 | 16 | #define PPMD7_MIN_ORDER 2 17 | #define PPMD7_MAX_ORDER 64 18 | 19 | #define PPMD7_MIN_MEM_SIZE (1 << 11) 20 | #define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3) 21 | 22 | struct CPpmd7_Context_; 23 | 24 | typedef 25 | #ifdef PPMD_32BIT 26 | struct CPpmd7_Context_ * 27 | #else 28 | UInt32 29 | #endif 30 | CPpmd7_Context_Ref; 31 | 32 | typedef struct CPpmd7_Context_ 33 | { 34 | UInt16 NumStats; 35 | UInt16 SummFreq; 36 | CPpmd_State_Ref Stats; 37 | CPpmd7_Context_Ref Suffix; 38 | } CPpmd7_Context; 39 | 40 | #define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq) 41 | 42 | typedef struct 43 | { 44 | CPpmd7_Context *MinContext, *MaxContext; 45 | CPpmd_State *FoundState; 46 | unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag; 47 | Int32 RunLength, InitRL; /* must be 32-bit at least */ 48 | 49 | UInt32 Size; 50 | UInt32 GlueCount; 51 | Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart; 52 | UInt32 AlignOffset; 53 | 54 | Byte Indx2Units[PPMD_NUM_INDEXES]; 55 | Byte Units2Indx[128]; 56 | CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES]; 57 | Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256]; 58 | CPpmd_See DummySee, See[25][16]; 59 | UInt16 BinSumm[128][64]; 60 | } CPpmd7; 61 | 62 | void Ppmd7_Construct(CPpmd7 *p); 63 | BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc); 64 | void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc); 65 | void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder); 66 | #define Ppmd7_WasAllocated(p) ((p)->Base != NULL) 67 | 68 | 69 | /* ---------- Internal Functions ---------- */ 70 | 71 | extern const Byte PPMD7_kExpEscape[16]; 72 | 73 | #ifdef PPMD_32BIT 74 | #define Ppmd7_GetPtr(p, ptr) (ptr) 75 | #define Ppmd7_GetContext(p, ptr) (ptr) 76 | #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats) 77 | #else 78 | #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs))) 79 | #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs))) 80 | #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats))) 81 | #endif 82 | 83 | void Ppmd7_Update1(CPpmd7 *p); 84 | void Ppmd7_Update1_0(CPpmd7 *p); 85 | void Ppmd7_Update2(CPpmd7 *p); 86 | void Ppmd7_UpdateBin(CPpmd7 *p); 87 | 88 | #define Ppmd7_GetBinSumm(p) \ 89 | &p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \ 90 | p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \ 91 | (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \ 92 | 2 * p->HB2Flag[(unsigned)Ppmd7Context_OneState(p->MinContext)->Symbol] + \ 93 | ((p->RunLength >> 26) & 0x20)] 94 | 95 | CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale); 96 | 97 | 98 | /* ---------- Decode ---------- */ 99 | 100 | typedef struct IPpmd7_RangeDec IPpmd7_RangeDec; 101 | 102 | struct IPpmd7_RangeDec 103 | { 104 | UInt32 (*GetThreshold)(const IPpmd7_RangeDec *p, UInt32 total); 105 | void (*Decode)(const IPpmd7_RangeDec *p, UInt32 start, UInt32 size); 106 | UInt32 (*DecodeBit)(const IPpmd7_RangeDec *p, UInt32 size0); 107 | }; 108 | 109 | typedef struct 110 | { 111 | IPpmd7_RangeDec vt; 112 | UInt32 Range; 113 | UInt32 Code; 114 | IByteIn *Stream; 115 | } CPpmd7z_RangeDec; 116 | 117 | void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p); 118 | BoolInt Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p); 119 | #define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0) 120 | 121 | int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc); 122 | 123 | 124 | /* ---------- Encode ---------- */ 125 | 126 | typedef struct 127 | { 128 | UInt64 Low; 129 | UInt32 Range; 130 | Byte Cache; 131 | UInt64 CacheSize; 132 | IByteOut *Stream; 133 | } CPpmd7z_RangeEnc; 134 | 135 | void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p); 136 | void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p); 137 | 138 | void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol); 139 | 140 | EXTERN_C_END 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /source/7zStream.c: -------------------------------------------------------------------------------- 1 | /* 7zStream.c -- 7z Stream functions 2 | 2017-04-03 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include 7 | 8 | #include "7zTypes.h" 9 | 10 | SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType) 11 | { 12 | while (size != 0) 13 | { 14 | size_t processed = size; 15 | RINOK(ISeqInStream_Read(stream, buf, &processed)); 16 | if (processed == 0) 17 | return errorType; 18 | buf = (void *)((Byte *)buf + processed); 19 | size -= processed; 20 | } 21 | return SZ_OK; 22 | } 23 | 24 | SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size) 25 | { 26 | return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); 27 | } 28 | 29 | SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf) 30 | { 31 | size_t processed = 1; 32 | RINOK(ISeqInStream_Read(stream, buf, &processed)); 33 | return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; 34 | } 35 | 36 | 37 | 38 | SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset) 39 | { 40 | Int64 t = offset; 41 | return ILookInStream_Seek(stream, &t, SZ_SEEK_SET); 42 | } 43 | 44 | SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size) 45 | { 46 | const void *lookBuf; 47 | if (*size == 0) 48 | return SZ_OK; 49 | RINOK(ILookInStream_Look(stream, &lookBuf, size)); 50 | memcpy(buf, lookBuf, *size); 51 | return ILookInStream_Skip(stream, *size); 52 | } 53 | 54 | SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType) 55 | { 56 | while (size != 0) 57 | { 58 | size_t processed = size; 59 | RINOK(ILookInStream_Read(stream, buf, &processed)); 60 | if (processed == 0) 61 | return errorType; 62 | buf = (void *)((Byte *)buf + processed); 63 | size -= processed; 64 | } 65 | return SZ_OK; 66 | } 67 | 68 | SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size) 69 | { 70 | return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); 71 | } 72 | 73 | 74 | 75 | #define GET_LookToRead2 CLookToRead2 *p = CONTAINER_FROM_VTBL(pp, CLookToRead2, vt); 76 | 77 | static SRes LookToRead2_Look_Lookahead(const ILookInStream *pp, const void **buf, size_t *size) 78 | { 79 | SRes res = SZ_OK; 80 | GET_LookToRead2 81 | size_t size2 = p->size - p->pos; 82 | if (size2 == 0 && *size != 0) 83 | { 84 | p->pos = 0; 85 | p->size = 0; 86 | size2 = p->bufSize; 87 | res = ISeekInStream_Read(p->realStream, p->buf, &size2); 88 | p->size = size2; 89 | } 90 | if (*size > size2) 91 | *size = size2; 92 | *buf = p->buf + p->pos; 93 | return res; 94 | } 95 | 96 | static SRes LookToRead2_Look_Exact(const ILookInStream *pp, const void **buf, size_t *size) 97 | { 98 | SRes res = SZ_OK; 99 | GET_LookToRead2 100 | size_t size2 = p->size - p->pos; 101 | if (size2 == 0 && *size != 0) 102 | { 103 | p->pos = 0; 104 | p->size = 0; 105 | if (*size > p->bufSize) 106 | *size = p->bufSize; 107 | res = ISeekInStream_Read(p->realStream, p->buf, size); 108 | size2 = p->size = *size; 109 | } 110 | if (*size > size2) 111 | *size = size2; 112 | *buf = p->buf + p->pos; 113 | return res; 114 | } 115 | 116 | static SRes LookToRead2_Skip(const ILookInStream *pp, size_t offset) 117 | { 118 | GET_LookToRead2 119 | p->pos += offset; 120 | return SZ_OK; 121 | } 122 | 123 | static SRes LookToRead2_Read(const ILookInStream *pp, void *buf, size_t *size) 124 | { 125 | GET_LookToRead2 126 | size_t rem = p->size - p->pos; 127 | if (rem == 0) 128 | return ISeekInStream_Read(p->realStream, buf, size); 129 | if (rem > *size) 130 | rem = *size; 131 | memcpy(buf, p->buf + p->pos, rem); 132 | p->pos += rem; 133 | *size = rem; 134 | return SZ_OK; 135 | } 136 | 137 | static SRes LookToRead2_Seek(const ILookInStream *pp, Int64 *pos, ESzSeek origin) 138 | { 139 | GET_LookToRead2 140 | p->pos = p->size = 0; 141 | return ISeekInStream_Seek(p->realStream, pos, origin); 142 | } 143 | 144 | void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead) 145 | { 146 | p->vt.Look = lookahead ? 147 | LookToRead2_Look_Lookahead : 148 | LookToRead2_Look_Exact; 149 | p->vt.Skip = LookToRead2_Skip; 150 | p->vt.Read = LookToRead2_Read; 151 | p->vt.Seek = LookToRead2_Seek; 152 | } 153 | 154 | 155 | 156 | static SRes SecToLook_Read(const ISeqInStream *pp, void *buf, size_t *size) 157 | { 158 | CSecToLook *p = CONTAINER_FROM_VTBL(pp, CSecToLook, vt); 159 | return LookInStream_LookRead(p->realStream, buf, size); 160 | } 161 | 162 | void SecToLook_CreateVTable(CSecToLook *p) 163 | { 164 | p->vt.Read = SecToLook_Read; 165 | } 166 | 167 | static SRes SecToRead_Read(const ISeqInStream *pp, void *buf, size_t *size) 168 | { 169 | CSecToRead *p = CONTAINER_FROM_VTBL(pp, CSecToRead, vt); 170 | return ILookInStream_Read(p->realStream, buf, size); 171 | } 172 | 173 | void SecToRead_CreateVTable(CSecToRead *p) 174 | { 175 | p->vt.Read = SecToRead_Read; 176 | } 177 | -------------------------------------------------------------------------------- /source/Bra.c: -------------------------------------------------------------------------------- 1 | /* Bra.c -- Converters for RISC code 2 | 2017-04-04 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "CpuArch.h" 7 | #include "Bra.h" 8 | 9 | SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) 10 | { 11 | Byte *p; 12 | const Byte *lim; 13 | size &= ~(size_t)3; 14 | ip += 4; 15 | p = data; 16 | lim = data + size; 17 | 18 | if (encoding) 19 | 20 | for (;;) 21 | { 22 | for (;;) 23 | { 24 | if (p >= lim) 25 | return p - data; 26 | p += 4; 27 | if (p[-1] == 0xEB) 28 | break; 29 | } 30 | { 31 | UInt32 v = GetUi32(p - 4); 32 | v <<= 2; 33 | v += ip + (UInt32)(p - data); 34 | v >>= 2; 35 | v &= 0x00FFFFFF; 36 | v |= 0xEB000000; 37 | SetUi32(p - 4, v); 38 | } 39 | } 40 | 41 | for (;;) 42 | { 43 | for (;;) 44 | { 45 | if (p >= lim) 46 | return p - data; 47 | p += 4; 48 | if (p[-1] == 0xEB) 49 | break; 50 | } 51 | { 52 | UInt32 v = GetUi32(p - 4); 53 | v <<= 2; 54 | v -= ip + (UInt32)(p - data); 55 | v >>= 2; 56 | v &= 0x00FFFFFF; 57 | v |= 0xEB000000; 58 | SetUi32(p - 4, v); 59 | } 60 | } 61 | } 62 | 63 | 64 | SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) 65 | { 66 | Byte *p; 67 | const Byte *lim; 68 | size &= ~(size_t)1; 69 | p = data; 70 | lim = data + size - 4; 71 | 72 | if (encoding) 73 | 74 | for (;;) 75 | { 76 | UInt32 b1; 77 | for (;;) 78 | { 79 | UInt32 b3; 80 | if (p > lim) 81 | return p - data; 82 | b1 = p[1]; 83 | b3 = p[3]; 84 | p += 2; 85 | b1 ^= 8; 86 | if ((b3 & b1) >= 0xF8) 87 | break; 88 | } 89 | { 90 | UInt32 v = 91 | ((UInt32)b1 << 19) 92 | + (((UInt32)p[1] & 0x7) << 8) 93 | + (((UInt32)p[-2] << 11)) 94 | + (p[0]); 95 | 96 | p += 2; 97 | { 98 | UInt32 cur = (ip + (UInt32)(p - data)) >> 1; 99 | v += cur; 100 | } 101 | 102 | p[-4] = (Byte)(v >> 11); 103 | p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7)); 104 | p[-2] = (Byte)v; 105 | p[-1] = (Byte)(0xF8 | (v >> 8)); 106 | } 107 | } 108 | 109 | for (;;) 110 | { 111 | UInt32 b1; 112 | for (;;) 113 | { 114 | UInt32 b3; 115 | if (p > lim) 116 | return p - data; 117 | b1 = p[1]; 118 | b3 = p[3]; 119 | p += 2; 120 | b1 ^= 8; 121 | if ((b3 & b1) >= 0xF8) 122 | break; 123 | } 124 | { 125 | UInt32 v = 126 | ((UInt32)b1 << 19) 127 | + (((UInt32)p[1] & 0x7) << 8) 128 | + (((UInt32)p[-2] << 11)) 129 | + (p[0]); 130 | 131 | p += 2; 132 | { 133 | UInt32 cur = (ip + (UInt32)(p - data)) >> 1; 134 | v -= cur; 135 | } 136 | 137 | /* 138 | SetUi16(p - 4, (UInt16)(((v >> 11) & 0x7FF) | 0xF000)); 139 | SetUi16(p - 2, (UInt16)(v | 0xF800)); 140 | */ 141 | 142 | p[-4] = (Byte)(v >> 11); 143 | p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7)); 144 | p[-2] = (Byte)v; 145 | p[-1] = (Byte)(0xF8 | (v >> 8)); 146 | } 147 | } 148 | } 149 | 150 | 151 | SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) 152 | { 153 | Byte *p; 154 | const Byte *lim; 155 | size &= ~(size_t)3; 156 | ip -= 4; 157 | p = data; 158 | lim = data + size; 159 | 160 | for (;;) 161 | { 162 | for (;;) 163 | { 164 | if (p >= lim) 165 | return p - data; 166 | p += 4; 167 | /* if ((v & 0xFC000003) == 0x48000001) */ 168 | if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1) 169 | break; 170 | } 171 | { 172 | UInt32 v = GetBe32(p - 4); 173 | if (encoding) 174 | v += ip + (UInt32)(p - data); 175 | else 176 | v -= ip + (UInt32)(p - data); 177 | v &= 0x03FFFFFF; 178 | v |= 0x48000000; 179 | SetBe32(p - 4, v); 180 | } 181 | } 182 | } 183 | 184 | 185 | SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) 186 | { 187 | Byte *p; 188 | const Byte *lim; 189 | size &= ~(size_t)3; 190 | ip -= 4; 191 | p = data; 192 | lim = data + size; 193 | 194 | for (;;) 195 | { 196 | for (;;) 197 | { 198 | if (p >= lim) 199 | return p - data; 200 | /* 201 | v = GetBe32(p); 202 | p += 4; 203 | m = v + ((UInt32)5 << 29); 204 | m ^= (UInt32)7 << 29; 205 | m += (UInt32)1 << 22; 206 | if ((m & ((UInt32)0x1FF << 23)) == 0) 207 | break; 208 | */ 209 | p += 4; 210 | if ((p[-4] == 0x40 && (p[-3] & 0xC0) == 0) || 211 | (p[-4] == 0x7F && (p[-3] >= 0xC0))) 212 | break; 213 | } 214 | { 215 | UInt32 v = GetBe32(p - 4); 216 | v <<= 2; 217 | if (encoding) 218 | v += ip + (UInt32)(p - data); 219 | else 220 | v -= ip + (UInt32)(p - data); 221 | 222 | v &= 0x01FFFFFF; 223 | v -= (UInt32)1 << 24; 224 | v ^= 0xFF000000; 225 | v >>= 2; 226 | v |= 0x40000000; 227 | SetBe32(p - 4, v); 228 | } 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /source/CpuArch.c: -------------------------------------------------------------------------------- 1 | /* CpuArch.c -- CPU specific code 2 | 2018-02-18: Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "CpuArch.h" 7 | 8 | #ifdef MY_CPU_X86_OR_AMD64 9 | 10 | #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) 11 | #define USE_ASM 12 | #endif 13 | 14 | #if !defined(USE_ASM) && _MSC_VER >= 1500 15 | #include 16 | #endif 17 | 18 | #if defined(USE_ASM) && !defined(MY_CPU_AMD64) 19 | static UInt32 CheckFlag(UInt32 flag) 20 | { 21 | #ifdef _MSC_VER 22 | __asm pushfd; 23 | __asm pop EAX; 24 | __asm mov EDX, EAX; 25 | __asm xor EAX, flag; 26 | __asm push EAX; 27 | __asm popfd; 28 | __asm pushfd; 29 | __asm pop EAX; 30 | __asm xor EAX, EDX; 31 | __asm push EDX; 32 | __asm popfd; 33 | __asm and flag, EAX; 34 | #else 35 | __asm__ __volatile__ ( 36 | "pushf\n\t" 37 | "pop %%EAX\n\t" 38 | "movl %%EAX,%%EDX\n\t" 39 | "xorl %0,%%EAX\n\t" 40 | "push %%EAX\n\t" 41 | "popf\n\t" 42 | "pushf\n\t" 43 | "pop %%EAX\n\t" 44 | "xorl %%EDX,%%EAX\n\t" 45 | "push %%EDX\n\t" 46 | "popf\n\t" 47 | "andl %%EAX, %0\n\t": 48 | "=c" (flag) : "c" (flag) : 49 | "%eax", "%edx"); 50 | #endif 51 | return flag; 52 | } 53 | #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; 54 | #else 55 | #define CHECK_CPUID_IS_SUPPORTED 56 | #endif 57 | 58 | void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) 59 | { 60 | #ifdef USE_ASM 61 | 62 | #ifdef _MSC_VER 63 | 64 | UInt32 a2, b2, c2, d2; 65 | __asm xor EBX, EBX; 66 | __asm xor ECX, ECX; 67 | __asm xor EDX, EDX; 68 | __asm mov EAX, function; 69 | __asm cpuid; 70 | __asm mov a2, EAX; 71 | __asm mov b2, EBX; 72 | __asm mov c2, ECX; 73 | __asm mov d2, EDX; 74 | 75 | *a = a2; 76 | *b = b2; 77 | *c = c2; 78 | *d = d2; 79 | 80 | #else 81 | 82 | __asm__ __volatile__ ( 83 | #if defined(MY_CPU_AMD64) && defined(__PIC__) 84 | "mov %%rbx, %%rdi;" 85 | "cpuid;" 86 | "xchg %%rbx, %%rdi;" 87 | : "=a" (*a) , 88 | "=D" (*b) , 89 | #elif defined(MY_CPU_X86) && defined(__PIC__) 90 | "mov %%ebx, %%edi;" 91 | "cpuid;" 92 | "xchgl %%ebx, %%edi;" 93 | : "=a" (*a) , 94 | "=D" (*b) , 95 | #else 96 | "cpuid" 97 | : "=a" (*a) , 98 | "=b" (*b) , 99 | #endif 100 | "=c" (*c) , 101 | "=d" (*d) 102 | : "0" (function)) ; 103 | 104 | #endif 105 | 106 | #else 107 | 108 | int CPUInfo[4]; 109 | __cpuid(CPUInfo, function); 110 | *a = CPUInfo[0]; 111 | *b = CPUInfo[1]; 112 | *c = CPUInfo[2]; 113 | *d = CPUInfo[3]; 114 | 115 | #endif 116 | } 117 | 118 | BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p) 119 | { 120 | CHECK_CPUID_IS_SUPPORTED 121 | MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); 122 | MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); 123 | return True; 124 | } 125 | 126 | static const UInt32 kVendors[][3] = 127 | { 128 | { 0x756E6547, 0x49656E69, 0x6C65746E}, 129 | { 0x68747541, 0x69746E65, 0x444D4163}, 130 | { 0x746E6543, 0x48727561, 0x736C7561} 131 | }; 132 | 133 | int x86cpuid_GetFirm(const Cx86cpuid *p) 134 | { 135 | unsigned i; 136 | for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) 137 | { 138 | const UInt32 *v = kVendors[i]; 139 | if (v[0] == p->vendor[0] && 140 | v[1] == p->vendor[1] && 141 | v[2] == p->vendor[2]) 142 | return (int)i; 143 | } 144 | return -1; 145 | } 146 | 147 | BoolInt CPU_Is_InOrder() 148 | { 149 | Cx86cpuid p; 150 | int firm; 151 | UInt32 family, model; 152 | if (!x86cpuid_CheckAndRead(&p)) 153 | return True; 154 | 155 | family = x86cpuid_GetFamily(p.ver); 156 | model = x86cpuid_GetModel(p.ver); 157 | 158 | firm = x86cpuid_GetFirm(&p); 159 | 160 | switch (firm) 161 | { 162 | case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && ( 163 | /* In-Order Atom CPU */ 164 | model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */ 165 | || model == 0x26 /* 45 nm, Z6xx */ 166 | || model == 0x27 /* 32 nm, Z2460 */ 167 | || model == 0x35 /* 32 nm, Z2760 */ 168 | || model == 0x36 /* 32 nm, N2xxx, D2xxx */ 169 | ))); 170 | case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); 171 | case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); 172 | } 173 | return True; 174 | } 175 | 176 | #if !defined(MY_CPU_AMD64) && defined(_WIN32) 177 | #include 178 | static BoolInt CPU_Sys_Is_SSE_Supported() 179 | { 180 | OSVERSIONINFO vi; 181 | vi.dwOSVersionInfoSize = sizeof(vi); 182 | if (!GetVersionEx(&vi)) 183 | return False; 184 | return (vi.dwMajorVersion >= 5); 185 | } 186 | #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; 187 | #else 188 | #define CHECK_SYS_SSE_SUPPORT 189 | #endif 190 | 191 | BoolInt CPU_Is_Aes_Supported() 192 | { 193 | Cx86cpuid p; 194 | CHECK_SYS_SSE_SUPPORT 195 | if (!x86cpuid_CheckAndRead(&p)) 196 | return False; 197 | return (p.c >> 25) & 1; 198 | } 199 | 200 | BoolInt CPU_IsSupported_PageGB() 201 | { 202 | Cx86cpuid cpuid; 203 | if (!x86cpuid_CheckAndRead(&cpuid)) 204 | return False; 205 | { 206 | UInt32 d[4] = { 0 }; 207 | MyCPUID(0x80000000, &d[0], &d[1], &d[2], &d[3]); 208 | if (d[0] < 0x80000001) 209 | return False; 210 | } 211 | { 212 | UInt32 d[4] = { 0 }; 213 | MyCPUID(0x80000001, &d[0], &d[1], &d[2], &d[3]); 214 | return (d[3] >> 26) & 1; 215 | } 216 | } 217 | 218 | #endif 219 | -------------------------------------------------------------------------------- /source/Ppmd7Dec.c: -------------------------------------------------------------------------------- 1 | /* Ppmd7Dec.c -- PPMdH Decoder 2 | 2018-07-04 : Igor Pavlov : Public domain 3 | This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ 4 | 5 | #include "Precomp.h" 6 | 7 | #include "Ppmd7.h" 8 | 9 | #define kTopValue (1 << 24) 10 | 11 | BoolInt Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p) 12 | { 13 | unsigned i; 14 | p->Code = 0; 15 | p->Range = 0xFFFFFFFF; 16 | if (IByteIn_Read(p->Stream) != 0) 17 | return False; 18 | for (i = 0; i < 4; i++) 19 | p->Code = (p->Code << 8) | IByteIn_Read(p->Stream); 20 | return (p->Code < 0xFFFFFFFF); 21 | } 22 | 23 | #define GET_Ppmd7z_RangeDec CPpmd7z_RangeDec *p = CONTAINER_FROM_VTBL(pp, CPpmd7z_RangeDec, vt); 24 | 25 | static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total) 26 | { 27 | GET_Ppmd7z_RangeDec 28 | return p->Code / (p->Range /= total); 29 | } 30 | 31 | static void Range_Normalize(CPpmd7z_RangeDec *p) 32 | { 33 | if (p->Range < kTopValue) 34 | { 35 | p->Code = (p->Code << 8) | IByteIn_Read(p->Stream); 36 | p->Range <<= 8; 37 | if (p->Range < kTopValue) 38 | { 39 | p->Code = (p->Code << 8) | IByteIn_Read(p->Stream); 40 | p->Range <<= 8; 41 | } 42 | } 43 | } 44 | 45 | static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size) 46 | { 47 | GET_Ppmd7z_RangeDec 48 | p->Code -= start * p->Range; 49 | p->Range *= size; 50 | Range_Normalize(p); 51 | } 52 | 53 | static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0) 54 | { 55 | GET_Ppmd7z_RangeDec 56 | UInt32 newBound = (p->Range >> 14) * size0; 57 | UInt32 symbol; 58 | if (p->Code < newBound) 59 | { 60 | symbol = 0; 61 | p->Range = newBound; 62 | } 63 | else 64 | { 65 | symbol = 1; 66 | p->Code -= newBound; 67 | p->Range -= newBound; 68 | } 69 | Range_Normalize(p); 70 | return symbol; 71 | } 72 | 73 | void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p) 74 | { 75 | p->vt.GetThreshold = Range_GetThreshold; 76 | p->vt.Decode = Range_Decode; 77 | p->vt.DecodeBit = Range_DecodeBit; 78 | } 79 | 80 | 81 | #define MASK(sym) ((signed char *)charMask)[sym] 82 | 83 | int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc) 84 | { 85 | size_t charMask[256 / sizeof(size_t)]; 86 | if (p->MinContext->NumStats != 1) 87 | { 88 | CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); 89 | unsigned i; 90 | UInt32 count, hiCnt; 91 | if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq)) 92 | { 93 | Byte symbol; 94 | rc->Decode(rc, 0, s->Freq); 95 | p->FoundState = s; 96 | symbol = s->Symbol; 97 | Ppmd7_Update1_0(p); 98 | return symbol; 99 | } 100 | p->PrevSuccess = 0; 101 | i = p->MinContext->NumStats - 1; 102 | do 103 | { 104 | if ((hiCnt += (++s)->Freq) > count) 105 | { 106 | Byte symbol; 107 | rc->Decode(rc, hiCnt - s->Freq, s->Freq); 108 | p->FoundState = s; 109 | symbol = s->Symbol; 110 | Ppmd7_Update1(p); 111 | return symbol; 112 | } 113 | } 114 | while (--i); 115 | if (count >= p->MinContext->SummFreq) 116 | return -2; 117 | p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; 118 | rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt); 119 | PPMD_SetAllBitsIn256Bytes(charMask); 120 | MASK(s->Symbol) = 0; 121 | i = p->MinContext->NumStats - 1; 122 | do { MASK((--s)->Symbol) = 0; } while (--i); 123 | } 124 | else 125 | { 126 | UInt16 *prob = Ppmd7_GetBinSumm(p); 127 | if (rc->DecodeBit(rc, *prob) == 0) 128 | { 129 | Byte symbol; 130 | *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); 131 | symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol; 132 | Ppmd7_UpdateBin(p); 133 | return symbol; 134 | } 135 | *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); 136 | p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; 137 | PPMD_SetAllBitsIn256Bytes(charMask); 138 | MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0; 139 | p->PrevSuccess = 0; 140 | } 141 | for (;;) 142 | { 143 | CPpmd_State *ps[256], *s; 144 | UInt32 freqSum, count, hiCnt; 145 | CPpmd_See *see; 146 | unsigned i, num, numMasked = p->MinContext->NumStats; 147 | do 148 | { 149 | p->OrderFall++; 150 | if (!p->MinContext->Suffix) 151 | return -1; 152 | p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); 153 | } 154 | while (p->MinContext->NumStats == numMasked); 155 | hiCnt = 0; 156 | s = Ppmd7_GetStats(p, p->MinContext); 157 | i = 0; 158 | num = p->MinContext->NumStats - numMasked; 159 | do 160 | { 161 | int k = (int)(MASK(s->Symbol)); 162 | hiCnt += (s->Freq & k); 163 | ps[i] = s++; 164 | i -= k; 165 | } 166 | while (i != num); 167 | 168 | see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum); 169 | freqSum += hiCnt; 170 | count = rc->GetThreshold(rc, freqSum); 171 | 172 | if (count < hiCnt) 173 | { 174 | Byte symbol; 175 | CPpmd_State **pps = ps; 176 | for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++); 177 | s = *pps; 178 | rc->Decode(rc, hiCnt - s->Freq, s->Freq); 179 | Ppmd_See_Update(see); 180 | p->FoundState = s; 181 | symbol = s->Symbol; 182 | Ppmd7_Update2(p); 183 | return symbol; 184 | } 185 | if (count >= freqSum) 186 | return -2; 187 | rc->Decode(rc, hiCnt, freqSum - hiCnt); 188 | see->Summ = (UInt16)(see->Summ + freqSum); 189 | do { MASK(ps[--i]->Symbol) = 0; } while (i != 0); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /include/7z.h: -------------------------------------------------------------------------------- 1 | /* 7z.h -- 7z interface 2 | 2017-04-03 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_H 5 | #define __7Z_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | #define k7zStartHeaderSize 0x20 12 | #define k7zSignatureSize 6 13 | 14 | extern const Byte k7zSignature[k7zSignatureSize]; 15 | 16 | typedef struct 17 | { 18 | const Byte *Data; 19 | size_t Size; 20 | } CSzData; 21 | 22 | /* CSzCoderInfo & CSzFolder support only default methods */ 23 | 24 | typedef struct 25 | { 26 | size_t PropsOffset; 27 | UInt32 MethodID; 28 | Byte NumStreams; 29 | Byte PropsSize; 30 | } CSzCoderInfo; 31 | 32 | typedef struct 33 | { 34 | UInt32 InIndex; 35 | UInt32 OutIndex; 36 | } CSzBond; 37 | 38 | #define SZ_NUM_CODERS_IN_FOLDER_MAX 4 39 | #define SZ_NUM_BONDS_IN_FOLDER_MAX 3 40 | #define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4 41 | 42 | typedef struct 43 | { 44 | UInt32 NumCoders; 45 | UInt32 NumBonds; 46 | UInt32 NumPackStreams; 47 | UInt32 UnpackStream; 48 | UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX]; 49 | CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX]; 50 | CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX]; 51 | } CSzFolder; 52 | 53 | 54 | SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd); 55 | 56 | typedef struct 57 | { 58 | UInt32 Low; 59 | UInt32 High; 60 | } CNtfsFileTime; 61 | 62 | typedef struct 63 | { 64 | Byte *Defs; /* MSB 0 bit numbering */ 65 | UInt32 *Vals; 66 | } CSzBitUi32s; 67 | 68 | typedef struct 69 | { 70 | Byte *Defs; /* MSB 0 bit numbering */ 71 | // UInt64 *Vals; 72 | CNtfsFileTime *Vals; 73 | } CSzBitUi64s; 74 | 75 | #define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) 76 | 77 | #define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) 78 | 79 | typedef struct 80 | { 81 | UInt32 NumPackStreams; 82 | UInt32 NumFolders; 83 | 84 | UInt64 *PackPositions; // NumPackStreams + 1 85 | CSzBitUi32s FolderCRCs; // NumFolders 86 | 87 | size_t *FoCodersOffsets; // NumFolders + 1 88 | UInt32 *FoStartPackStreamIndex; // NumFolders + 1 89 | UInt32 *FoToCoderUnpackSizes; // NumFolders + 1 90 | Byte *FoToMainUnpackSizeIndex; // NumFolders 91 | UInt64 *CoderUnpackSizes; // for all coders in all folders 92 | 93 | Byte *CodersData; 94 | } CSzAr; 95 | 96 | UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex); 97 | 98 | SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, 99 | ILookInStream *stream, UInt64 startPos, 100 | Byte *outBuffer, size_t outSize, 101 | ISzAllocPtr allocMain); 102 | 103 | typedef struct 104 | { 105 | CSzAr db; 106 | 107 | UInt64 startPosAfterHeader; 108 | UInt64 dataPos; 109 | 110 | UInt32 NumFiles; 111 | 112 | UInt64 *UnpackPositions; // NumFiles + 1 113 | // Byte *IsEmptyFiles; 114 | Byte *IsDirs; 115 | CSzBitUi32s CRCs; 116 | 117 | CSzBitUi32s Attribs; 118 | // CSzBitUi32s Parents; 119 | CSzBitUi64s MTime; 120 | CSzBitUi64s CTime; 121 | 122 | UInt32 *FolderToFile; // NumFolders + 1 123 | UInt32 *FileToFolder; // NumFiles 124 | 125 | size_t *FileNameOffsets; /* in 2-byte steps */ 126 | Byte *FileNames; /* UTF-16-LE */ 127 | } CSzArEx; 128 | 129 | #define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i)) 130 | 131 | #define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i]) 132 | 133 | void SzArEx_Init(CSzArEx *p); 134 | void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc); 135 | UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); 136 | int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); 137 | 138 | /* 139 | if dest == NULL, the return value specifies the required size of the buffer, 140 | in 16-bit characters, including the null-terminating character. 141 | if dest != NULL, the return value specifies the number of 16-bit characters that 142 | are written to the dest, including the null-terminating character. */ 143 | 144 | size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest); 145 | 146 | /* 147 | size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex); 148 | UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest); 149 | */ 150 | 151 | 152 | 153 | /* 154 | SzArEx_Extract extracts file from archive 155 | 156 | *outBuffer must be 0 before first call for each new archive. 157 | 158 | Extracting cache: 159 | If you need to decompress more than one file, you can send 160 | these values from previous call: 161 | *blockIndex, 162 | *outBuffer, 163 | *outBufferSize 164 | You can consider "*outBuffer" as cache of solid block. If your archive is solid, 165 | it will increase decompression speed. 166 | 167 | If you use external function, you can declare these 3 cache variables 168 | (blockIndex, outBuffer, outBufferSize) as static in that external function. 169 | 170 | Free *outBuffer and set *outBuffer to 0, if you want to flush cache. 171 | */ 172 | 173 | SRes SzArEx_Extract( 174 | const CSzArEx *db, 175 | ILookInStream *inStream, 176 | UInt32 fileIndex, /* index of file */ 177 | UInt32 *blockIndex, /* index of solid block */ 178 | Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ 179 | size_t *outBufferSize, /* buffer size for output buffer */ 180 | size_t *offset, /* offset of stream for required file in *outBuffer */ 181 | size_t *outSizeProcessed, /* size of file in *outBuffer */ 182 | ISzAllocPtr allocMain, 183 | ISzAllocPtr allocTemp); 184 | 185 | 186 | /* 187 | SzArEx_Open Errors: 188 | SZ_ERROR_NO_ARCHIVE 189 | SZ_ERROR_ARCHIVE 190 | SZ_ERROR_UNSUPPORTED 191 | SZ_ERROR_MEM 192 | SZ_ERROR_CRC 193 | SZ_ERROR_INPUT_EOF 194 | SZ_ERROR_FAIL 195 | */ 196 | 197 | SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, 198 | ISzAllocPtr allocMain, ISzAllocPtr allocTemp); 199 | 200 | EXTERN_C_END 201 | 202 | #endif 203 | -------------------------------------------------------------------------------- /source/Bcj2.c: -------------------------------------------------------------------------------- 1 | /* Bcj2.c -- BCJ2 Decoder (Converter for x86 code) 2 | 2018-04-28 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "Bcj2.h" 7 | #include "CpuArch.h" 8 | 9 | #define CProb UInt16 10 | 11 | #define kTopValue ((UInt32)1 << 24) 12 | #define kNumModelBits 11 13 | #define kBitModelTotal (1 << kNumModelBits) 14 | #define kNumMoveBits 5 15 | 16 | #define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound) 17 | #define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); 18 | #define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits)); 19 | 20 | void Bcj2Dec_Init(CBcj2Dec *p) 21 | { 22 | unsigned i; 23 | 24 | p->state = BCJ2_DEC_STATE_OK; 25 | p->ip = 0; 26 | p->temp[3] = 0; 27 | p->range = 0; 28 | p->code = 0; 29 | for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++) 30 | p->probs[i] = kBitModelTotal >> 1; 31 | } 32 | 33 | SRes Bcj2Dec_Decode(CBcj2Dec *p) 34 | { 35 | if (p->range <= 5) 36 | { 37 | p->state = BCJ2_DEC_STATE_OK; 38 | for (; p->range != 5; p->range++) 39 | { 40 | if (p->range == 1 && p->code != 0) 41 | return SZ_ERROR_DATA; 42 | 43 | if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) 44 | { 45 | p->state = BCJ2_STREAM_RC; 46 | return SZ_OK; 47 | } 48 | 49 | p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; 50 | } 51 | 52 | if (p->code == 0xFFFFFFFF) 53 | return SZ_ERROR_DATA; 54 | 55 | p->range = 0xFFFFFFFF; 56 | } 57 | else if (p->state >= BCJ2_DEC_STATE_ORIG_0) 58 | { 59 | while (p->state <= BCJ2_DEC_STATE_ORIG_3) 60 | { 61 | Byte *dest = p->dest; 62 | if (dest == p->destLim) 63 | return SZ_OK; 64 | *dest = p->temp[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0]; 65 | p->state++; 66 | p->dest = dest + 1; 67 | } 68 | } 69 | 70 | /* 71 | if (BCJ2_IS_32BIT_STREAM(p->state)) 72 | { 73 | const Byte *cur = p->bufs[p->state]; 74 | if (cur == p->lims[p->state]) 75 | return SZ_OK; 76 | p->bufs[p->state] = cur + 4; 77 | 78 | { 79 | UInt32 val; 80 | Byte *dest; 81 | SizeT rem; 82 | 83 | p->ip += 4; 84 | val = GetBe32(cur) - p->ip; 85 | dest = p->dest; 86 | rem = p->destLim - dest; 87 | if (rem < 4) 88 | { 89 | SizeT i; 90 | SetUi32(p->temp, val); 91 | for (i = 0; i < rem; i++) 92 | dest[i] = p->temp[i]; 93 | p->dest = dest + rem; 94 | p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; 95 | return SZ_OK; 96 | } 97 | SetUi32(dest, val); 98 | p->temp[3] = (Byte)(val >> 24); 99 | p->dest = dest + 4; 100 | p->state = BCJ2_DEC_STATE_OK; 101 | } 102 | } 103 | */ 104 | 105 | for (;;) 106 | { 107 | if (BCJ2_IS_32BIT_STREAM(p->state)) 108 | p->state = BCJ2_DEC_STATE_OK; 109 | else 110 | { 111 | if (p->range < kTopValue) 112 | { 113 | if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) 114 | { 115 | p->state = BCJ2_STREAM_RC; 116 | return SZ_OK; 117 | } 118 | p->range <<= 8; 119 | p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; 120 | } 121 | 122 | { 123 | const Byte *src = p->bufs[BCJ2_STREAM_MAIN]; 124 | const Byte *srcLim; 125 | Byte *dest; 126 | SizeT num = p->lims[BCJ2_STREAM_MAIN] - src; 127 | 128 | if (num == 0) 129 | { 130 | p->state = BCJ2_STREAM_MAIN; 131 | return SZ_OK; 132 | } 133 | 134 | dest = p->dest; 135 | if (num > (SizeT)(p->destLim - dest)) 136 | { 137 | num = p->destLim - dest; 138 | if (num == 0) 139 | { 140 | p->state = BCJ2_DEC_STATE_ORIG; 141 | return SZ_OK; 142 | } 143 | } 144 | 145 | srcLim = src + num; 146 | 147 | if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80) 148 | *dest = src[0]; 149 | else for (;;) 150 | { 151 | Byte b = *src; 152 | *dest = b; 153 | if (b != 0x0F) 154 | { 155 | if ((b & 0xFE) == 0xE8) 156 | break; 157 | dest++; 158 | if (++src != srcLim) 159 | continue; 160 | break; 161 | } 162 | dest++; 163 | if (++src == srcLim) 164 | break; 165 | if ((*src & 0xF0) != 0x80) 166 | continue; 167 | *dest = *src; 168 | break; 169 | } 170 | 171 | num = src - p->bufs[BCJ2_STREAM_MAIN]; 172 | 173 | if (src == srcLim) 174 | { 175 | p->temp[3] = src[-1]; 176 | p->bufs[BCJ2_STREAM_MAIN] = src; 177 | p->ip += (UInt32)num; 178 | p->dest += num; 179 | p->state = 180 | p->bufs[BCJ2_STREAM_MAIN] == 181 | p->lims[BCJ2_STREAM_MAIN] ? 182 | (unsigned)BCJ2_STREAM_MAIN : 183 | (unsigned)BCJ2_DEC_STATE_ORIG; 184 | return SZ_OK; 185 | } 186 | 187 | { 188 | UInt32 bound, ttt; 189 | CProb *prob; 190 | Byte b = src[0]; 191 | Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]); 192 | 193 | p->temp[3] = b; 194 | p->bufs[BCJ2_STREAM_MAIN] = src + 1; 195 | num++; 196 | p->ip += (UInt32)num; 197 | p->dest += num; 198 | 199 | prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0)); 200 | 201 | _IF_BIT_0 202 | { 203 | _UPDATE_0 204 | continue; 205 | } 206 | _UPDATE_1 207 | 208 | } 209 | } 210 | } 211 | 212 | { 213 | UInt32 val; 214 | unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP; 215 | const Byte *cur = p->bufs[cj]; 216 | Byte *dest; 217 | SizeT rem; 218 | 219 | if (cur == p->lims[cj]) 220 | { 221 | p->state = cj; 222 | break; 223 | } 224 | 225 | val = GetBe32(cur); 226 | p->bufs[cj] = cur + 4; 227 | 228 | p->ip += 4; 229 | val -= p->ip; 230 | dest = p->dest; 231 | rem = p->destLim - dest; 232 | 233 | if (rem < 4) 234 | { 235 | p->temp[0] = (Byte)val; if (rem > 0) dest[0] = (Byte)val; val >>= 8; 236 | p->temp[1] = (Byte)val; if (rem > 1) dest[1] = (Byte)val; val >>= 8; 237 | p->temp[2] = (Byte)val; if (rem > 2) dest[2] = (Byte)val; val >>= 8; 238 | p->temp[3] = (Byte)val; 239 | p->dest = dest + rem; 240 | p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; 241 | break; 242 | } 243 | 244 | SetUi32(dest, val); 245 | p->temp[3] = (Byte)(val >> 24); 246 | p->dest = dest + 4; 247 | } 248 | } 249 | 250 | if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC]) 251 | { 252 | p->range <<= 8; 253 | p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; 254 | } 255 | 256 | return SZ_OK; 257 | } 258 | -------------------------------------------------------------------------------- /source/7zFunctions.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by HZY on 2017/11/25. 3 | // code copy from 7zMain.c 4 | // 5 | 6 | #include 7 | #include 8 | #include 9 | #include "7zFunctions.h" 10 | #include "7zAlloc.h" 11 | #include "7zBuf.h" 12 | 13 | #define PATH_MAX 4096 14 | 15 | #define _UTF8_START(n) (0x100 - (1 << (7 - (n)))) 16 | #define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6)) 17 | #define _UTF8_HEAD(n, val) ((Byte)(_UTF8_START(n) + (val >> (6 * (n))))) 18 | #define _UTF8_CHAR(n, val) ((Byte)(0x80 + (((val) >> (6 * (n))) & 0x3F))) 19 | 20 | #define PERIOD_4 (4 * 365 + 1) 21 | #define PERIOD_100 (PERIOD_4 * 25 - 1) 22 | #define PERIOD_400 (PERIOD_100 * 4 + 1) 23 | 24 | static const ISzAlloc g_Alloc = {SzAlloc, SzFree}; 25 | 26 | void Print(const char *s) { 27 | #ifdef PRINT_STDOUT 28 | printf("%s", s); 29 | #endif 30 | } 31 | 32 | void PrintError(const char *s) { 33 | #ifdef PRINT_STDOUT 34 | printf("%s", s); 35 | #endif 36 | } 37 | 38 | static int Buf_EnsureSize(CBuf *dest, size_t size) { 39 | if (dest->size >= size) 40 | return 1; 41 | Buf_Free(dest, &g_Alloc); 42 | return Buf_Create(dest, size, &g_Alloc); 43 | } 44 | 45 | static size_t Utf16_To_Utf8_Calc(const UInt16 *src, const UInt16 *srcLim) { 46 | size_t size = 0; 47 | for (;;) { 48 | UInt32 val; 49 | if (src == srcLim) 50 | return size; 51 | size++; 52 | val = *src++; 53 | if (val < 0x80) 54 | continue; 55 | if (val < _UTF8_RANGE(1)) { 56 | size++; 57 | continue; 58 | } 59 | if (val >= 0xD800 && val < 0xDC00 && src != srcLim) { 60 | UInt32 c2 = *src; 61 | if (c2 >= 0xDC00 && c2 < 0xE000) { 62 | src++; 63 | size += 3; 64 | continue; 65 | } 66 | } 67 | size += 2; 68 | } 69 | } 70 | 71 | static Byte *Utf16_To_Utf8(Byte *dest, const UInt16 *src, const UInt16 *srcLim) { 72 | for (;;) { 73 | UInt32 val; 74 | if (src == srcLim) 75 | return dest; 76 | val = *src++; 77 | if (val < 0x80) { 78 | *dest++ = (char) val; 79 | continue; 80 | } 81 | if (val < _UTF8_RANGE(1)) { 82 | dest[0] = _UTF8_HEAD(1, val); 83 | dest[1] = _UTF8_CHAR(0, val); 84 | dest += 2; 85 | continue; 86 | } 87 | if (val >= 0xD800 && val < 0xDC00 && src != srcLim) { 88 | UInt32 c2 = *src; 89 | if (c2 >= 0xDC00 && c2 < 0xE000) { 90 | src++; 91 | val = (((val - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; 92 | dest[0] = _UTF8_HEAD(3, val); 93 | dest[1] = _UTF8_CHAR(2, val); 94 | dest[2] = _UTF8_CHAR(1, val); 95 | dest[3] = _UTF8_CHAR(0, val); 96 | dest += 4; 97 | continue; 98 | } 99 | } 100 | dest[0] = _UTF8_HEAD(2, val); 101 | dest[1] = _UTF8_CHAR(1, val); 102 | dest[2] = _UTF8_CHAR(0, val); 103 | dest += 3; 104 | } 105 | } 106 | 107 | static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen) { 108 | size_t destLen = Utf16_To_Utf8_Calc(src, src + srcLen); 109 | destLen += 1; 110 | if (!Buf_EnsureSize(dest, destLen)) 111 | return SZ_ERROR_MEM; 112 | *Utf16_To_Utf8(dest->data, src, src + srcLen) = 0; 113 | return SZ_OK; 114 | } 115 | 116 | SRes Utf16_To_Char(CBuf *buf, const UInt16 *s) { 117 | unsigned len = 0; 118 | for (len = 0; s[len] != 0; len++); 119 | return Utf16_To_Utf8Buf(buf, s, len); 120 | } 121 | 122 | WRes MyCreateDir(const UInt16 *name, const char *dir) { 123 | CBuf buf; 124 | WRes res; 125 | char temp[PATH_MAX] = {0}; 126 | strcpy(temp, dir); 127 | Buf_Init(&buf); 128 | RINOK(Utf16_To_Char(&buf, name)); 129 | strcat(temp, STRING_PATH_SEPARATOR); 130 | strcat(temp, (const char *) buf.data); 131 | res = mkdir((const char *) temp, 0777) == 0 ? 0 : errno; 132 | Buf_Free(&buf, &g_Alloc); 133 | return res; 134 | } 135 | 136 | WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name, const char *dir) { 137 | CBuf buf; 138 | WRes res; 139 | Buf_Init(&buf); 140 | char temp[PATH_MAX] = {0}; 141 | RINOK(Utf16_To_Char(&buf, name)); 142 | strcpy(temp, dir); 143 | strcat(temp, STRING_PATH_SEPARATOR); 144 | strcat(temp, (const char *) buf.data); 145 | Print(temp); 146 | res = OutFile_Open(p, temp); 147 | Buf_Free(&buf, &g_Alloc); 148 | return res; 149 | } 150 | 151 | SRes PrintString(const UInt16 *s) { 152 | CBuf buf; 153 | SRes res; 154 | Buf_Init(&buf); 155 | res = Utf16_To_Char(&buf, s); 156 | if (res == SZ_OK) 157 | Print((const char *) buf.data); 158 | Buf_Free(&buf, &g_Alloc); 159 | return res; 160 | } 161 | 162 | void UInt64ToStr(UInt64 value, char *s, int numDigits) { 163 | char temp[32]; 164 | int pos = 0; 165 | do { 166 | temp[pos++] = (char) ('0' + (unsigned) (value % 10)); 167 | value /= 10; 168 | } while (value != 0); 169 | for (numDigits -= pos; numDigits > 0; numDigits--) 170 | *s++ = ' '; 171 | do 172 | *s++ = temp[--pos]; 173 | while (pos); 174 | *s = '\0'; 175 | } 176 | 177 | char *UIntToStr(char *s, unsigned value, int numDigits) { 178 | char temp[16]; 179 | int pos = 0; 180 | do 181 | temp[pos++] = (char) ('0' + (value % 10)); 182 | while (value /= 10); 183 | for (numDigits -= pos; numDigits > 0; numDigits--) 184 | *s++ = '0'; 185 | do 186 | *s++ = temp[--pos]; 187 | while (pos); 188 | *s = '\0'; 189 | return s; 190 | } 191 | 192 | static void UIntToStr_2(char *s, unsigned value) { 193 | s[0] = (char) ('0' + (value / 10)); 194 | s[1] = (char) ('0' + (value % 10)); 195 | } 196 | 197 | void ConvertFileTimeToString(const CNtfsFileTime *nt, char *s) { 198 | unsigned year, mon, hour, min, sec; 199 | Byte ms[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 200 | unsigned t; 201 | UInt32 v; 202 | UInt64 v64 = nt->Low | ((UInt64) nt->High << 32); 203 | v64 /= 10000000; 204 | sec = (unsigned) (v64 % 60); 205 | v64 /= 60; 206 | min = (unsigned) (v64 % 60); 207 | v64 /= 60; 208 | hour = (unsigned) (v64 % 24); 209 | v64 /= 24; 210 | v = (UInt32) v64; 211 | year = (unsigned) (1601 + v / PERIOD_400 * 400); 212 | v %= PERIOD_400; 213 | t = v / PERIOD_100; 214 | if (t == 4) t = 3; 215 | year += t * 100; 216 | v -= t * PERIOD_100; 217 | t = v / PERIOD_4; 218 | if (t == 25) t = 24; 219 | year += t * 4; 220 | v -= t * PERIOD_4; 221 | t = v / 365; 222 | if (t == 4) t = 3; 223 | year += t; 224 | v -= t * 365; 225 | if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) 226 | ms[1] = 29; 227 | for (mon = 0;; mon++) { 228 | unsigned d = ms[mon]; 229 | if (v < d) 230 | break; 231 | v -= d; 232 | } 233 | s = UIntToStr(s, year, 4); 234 | *s++ = '-'; 235 | UIntToStr_2(s, mon + 1); 236 | s[2] = '-'; 237 | s += 3; 238 | UIntToStr_2(s, (unsigned) v + 1); 239 | s[2] = ' '; 240 | s += 3; 241 | UIntToStr_2(s, hour); 242 | s[2] = ':'; 243 | s += 3; 244 | UIntToStr_2(s, min); 245 | s[2] = ':'; 246 | s += 3; 247 | UIntToStr_2(s, sec); 248 | s[2] = 0; 249 | } 250 | 251 | void GetAttribString(UInt32 wa, BoolInt isDir, char *s) { 252 | s[0] = (char) (((wa & (1 << 4)) != 0 || isDir) ? 'D' : '.'); 253 | s[1] = 0; 254 | } 255 | -------------------------------------------------------------------------------- /example/Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | # Clear the implicit built in rules 3 | #--------------------------------------------------------------------------------- 4 | .SUFFIXES: 5 | #--------------------------------------------------------------------------------- 6 | ifeq ($(strip $(PSL1GHT)),) 7 | $(error "Please set PSL1GHT in your environment. export PSL1GHT=") 8 | endif 9 | 10 | #--------------------------------------------------------------------------------- 11 | # TITLE, APPID, CONTENTID, ICON0 SFOXML before ppu_rules. 12 | #--------------------------------------------------------------------------------- 13 | TITLE := Un7Zip PS3 14 | APPID := NP0UN7ZIP 15 | CONTENTID := UP0001-$(APPID)_00-0000000000000000 16 | 17 | include $(PSL1GHT)/ppu_rules 18 | 19 | # aditional scetool flags (--self-ctrl-flags, --self-cap-flags...) 20 | SCETOOL_FLAGS += 21 | 22 | #--------------------------------------------------------------------------------- 23 | # TARGET is the name of the output 24 | # BUILD is the directory where object files & intermediate files will be placed 25 | # SOURCES is a list of directories containing source code 26 | # INCLUDES is a list of directories containing extra header files 27 | #--------------------------------------------------------------------------------- 28 | TARGET := $(notdir $(CURDIR)) 29 | BUILD := build 30 | SOURCES := ./ #source 31 | DATA := data 32 | SHADERS := shaders 33 | INCLUDES := include 34 | 35 | 36 | #--------------------------------------------------------------------------------- 37 | # any extra libraries we wish to link with the project 38 | #--------------------------------------------------------------------------------- 39 | LIBS := -lun7zip -lstdc++ -lsimdmath -lgcm_sys -lio -lsysutil -lrt -llv2 -lsysmodule -lm -lsysfs 40 | 41 | 42 | #--------------------------------------------------------------------------------- 43 | # options for code generation 44 | #--------------------------------------------------------------------------------- 45 | 46 | CFLAGS = -O2 -Wall -mcpu=cell -std=gnu99 $(MACHDEP) $(INCLUDE) 47 | CXXFLAGS = $(CFLAGS) 48 | 49 | LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map 50 | 51 | #--------------------------------------------------------------------------------- 52 | # list of directories containing libraries, this must be the top level containing 53 | # include and lib 54 | #--------------------------------------------------------------------------------- 55 | LIBDIRS := 56 | 57 | #--------------------------------------------------------------------------------- 58 | # no real need to edit anything past this point unless you need to add additional 59 | # rules for different file extensions 60 | #--------------------------------------------------------------------------------- 61 | ifneq ($(BUILD),$(notdir $(CURDIR))) 62 | #--------------------------------------------------------------------------------- 63 | 64 | export OUTPUT := $(CURDIR)/$(TARGET) 65 | 66 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 67 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ 68 | $(foreach dir,$(SHADERS),$(CURDIR)/$(dir)) 69 | 70 | export DEPSDIR := $(CURDIR)/$(BUILD) 71 | 72 | export BUILDDIR := $(CURDIR)/$(BUILD) 73 | 74 | #--------------------------------------------------------------------------------- 75 | # automatically build a list of object files for our project 76 | #--------------------------------------------------------------------------------- 77 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 78 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 79 | sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 80 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) 81 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.bin))) 82 | PNGFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.png))) 83 | JPGFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.jpg))) 84 | 85 | #--------------------------------------------------------------------------------- 86 | # use CXX for linking C++ projects, CC for standard C 87 | #--------------------------------------------------------------------------------- 88 | ifeq ($(strip $(CPPFILES)),) 89 | export LD := $(CC) 90 | else 91 | export LD := $(CXX) 92 | endif 93 | 94 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 95 | $(addsuffix .o,$(PNGFILES)) \ 96 | $(addsuffix .o,$(JPGFILES)) \ 97 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ 98 | $(sFILES:.s=.o) $(SFILES:.S=.o) 99 | 100 | #--------------------------------------------------------------------------------- 101 | # build a list of include paths 102 | #--------------------------------------------------------------------------------- 103 | export INCLUDE := $(foreach dir,$(INCLUDES), -I$(CURDIR)/$(dir)) \ 104 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 105 | $(LIBPSL1GHT_INC) \ 106 | -I$(CURDIR)/$(BUILD) -I$(PORTLIBS)/include 107 | 108 | #--------------------------------------------------------------------------------- 109 | # build a list of library paths 110 | #--------------------------------------------------------------------------------- 111 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ 112 | $(LIBPSL1GHT_LIB) -L$(PORTLIBS)/lib 113 | 114 | export OUTPUT := $(CURDIR)/$(TARGET) 115 | .PHONY: $(BUILD) clean 116 | 117 | 118 | #--------------------------------------------------------------------------------- 119 | $(BUILD): 120 | @[ -d $@ ] || mkdir -p $@ 121 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 122 | 123 | #--------------------------------------------------------------------------------- 124 | clean: 125 | @echo clean ... 126 | @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).self EBOOT.BIN 127 | 128 | #--------------------------------------------------------------------------------- 129 | run: 130 | ps3load $(OUTPUT).self 131 | 132 | #--------------------------------------------------------------------------------- 133 | pkg: $(BUILD) $(OUTPUT).pkg 134 | 135 | #--------------------------------------------------------------------------------- 136 | 137 | npdrm: $(BUILD) 138 | @$(SELF_NPDRM) $(SCETOOL_FLAGS) --np-content-id=$(CONTENTID) --encrypt $(BUILDDIR)/$(basename $(notdir $(OUTPUT))).elf $(BUILDDIR)/../EBOOT.BIN 139 | 140 | #--------------------------------------------------------------------------------- 141 | 142 | else 143 | 144 | DEPENDS := $(OFILES:.o=.d) 145 | 146 | #--------------------------------------------------------------------------------- 147 | # main targets 148 | #--------------------------------------------------------------------------------- 149 | $(OUTPUT).self: $(OUTPUT).elf 150 | $(OUTPUT).elf: $(OFILES) 151 | 152 | #--------------------------------------------------------------------------------- 153 | # This rule links in binary data with the .bin extension 154 | #--------------------------------------------------------------------------------- 155 | %.bin.o : %.bin 156 | #--------------------------------------------------------------------------------- 157 | @echo $(notdir $<) 158 | @$(bin2o) 159 | 160 | #--------------------------------------------------------------------------------- 161 | %.png.o : %.png 162 | #--------------------------------------------------------------------------------- 163 | @echo $(notdir $<) 164 | @$(bin2o) 165 | 166 | #--------------------------------------------------------------------------------- 167 | %.jpg.o : %.jpg 168 | #--------------------------------------------------------------------------------- 169 | @echo $(notdir $<) 170 | @$(bin2o) 171 | 172 | -include $(DEPENDS) 173 | 174 | #--------------------------------------------------------------------------------- 175 | endif 176 | #--------------------------------------------------------------------------------- 177 | 178 | -------------------------------------------------------------------------------- /include/LzmaDec.h: -------------------------------------------------------------------------------- 1 | /* LzmaDec.h -- LZMA Decoder 2 | 2018-04-21 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __LZMA_DEC_H 5 | #define __LZMA_DEC_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | /* #define _LZMA_PROB32 */ 12 | /* _LZMA_PROB32 can increase the speed on some CPUs, 13 | but memory usage for CLzmaDec::probs will be doubled in that case */ 14 | 15 | typedef 16 | #ifdef _LZMA_PROB32 17 | UInt32 18 | #else 19 | UInt16 20 | #endif 21 | CLzmaProb; 22 | 23 | 24 | /* ---------- LZMA Properties ---------- */ 25 | 26 | #define LZMA_PROPS_SIZE 5 27 | 28 | typedef struct _CLzmaProps 29 | { 30 | Byte lc; 31 | Byte lp; 32 | Byte pb; 33 | Byte _pad_; 34 | UInt32 dicSize; 35 | } CLzmaProps; 36 | 37 | /* LzmaProps_Decode - decodes properties 38 | Returns: 39 | SZ_OK 40 | SZ_ERROR_UNSUPPORTED - Unsupported properties 41 | */ 42 | 43 | SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); 44 | 45 | 46 | /* ---------- LZMA Decoder state ---------- */ 47 | 48 | /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. 49 | Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ 50 | 51 | #define LZMA_REQUIRED_INPUT_MAX 20 52 | 53 | typedef struct 54 | { 55 | /* Don't change this structure. ASM code can use it. */ 56 | CLzmaProps prop; 57 | CLzmaProb *probs; 58 | CLzmaProb *probs_1664; 59 | Byte *dic; 60 | SizeT dicBufSize; 61 | SizeT dicPos; 62 | const Byte *buf; 63 | UInt32 range; 64 | UInt32 code; 65 | UInt32 processedPos; 66 | UInt32 checkDicSize; 67 | UInt32 reps[4]; 68 | UInt32 state; 69 | UInt32 remainLen; 70 | 71 | UInt32 numProbs; 72 | unsigned tempBufSize; 73 | Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; 74 | } CLzmaDec; 75 | 76 | #define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; } 77 | 78 | void LzmaDec_Init(CLzmaDec *p); 79 | 80 | /* There are two types of LZMA streams: 81 | - Stream with end mark. That end mark adds about 6 bytes to compressed size. 82 | - Stream without end mark. You must know exact uncompressed size to decompress such stream. */ 83 | 84 | typedef enum 85 | { 86 | LZMA_FINISH_ANY, /* finish at any point */ 87 | LZMA_FINISH_END /* block must be finished at the end */ 88 | } ELzmaFinishMode; 89 | 90 | /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! 91 | 92 | You must use LZMA_FINISH_END, when you know that current output buffer 93 | covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. 94 | 95 | If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, 96 | and output value of destLen will be less than output buffer size limit. 97 | You can check status result also. 98 | 99 | You can use multiple checks to test data integrity after full decompression: 100 | 1) Check Result and "status" variable. 101 | 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 102 | 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. 103 | You must use correct finish mode in that case. */ 104 | 105 | typedef enum 106 | { 107 | LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ 108 | LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ 109 | LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ 110 | LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ 111 | LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ 112 | } ELzmaStatus; 113 | 114 | /* ELzmaStatus is used only as output value for function call */ 115 | 116 | 117 | /* ---------- Interfaces ---------- */ 118 | 119 | /* There are 3 levels of interfaces: 120 | 1) Dictionary Interface 121 | 2) Buffer Interface 122 | 3) One Call Interface 123 | You can select any of these interfaces, but don't mix functions from different 124 | groups for same object. */ 125 | 126 | 127 | /* There are two variants to allocate state for Dictionary Interface: 128 | 1) LzmaDec_Allocate / LzmaDec_Free 129 | 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs 130 | You can use variant 2, if you set dictionary buffer manually. 131 | For Buffer Interface you must always use variant 1. 132 | 133 | LzmaDec_Allocate* can return: 134 | SZ_OK 135 | SZ_ERROR_MEM - Memory allocation error 136 | SZ_ERROR_UNSUPPORTED - Unsupported properties 137 | */ 138 | 139 | SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc); 140 | void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc); 141 | 142 | SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc); 143 | void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc); 144 | 145 | /* ---------- Dictionary Interface ---------- */ 146 | 147 | /* You can use it, if you want to eliminate the overhead for data copying from 148 | dictionary to some other external buffer. 149 | You must work with CLzmaDec variables directly in this interface. 150 | 151 | STEPS: 152 | LzmaDec_Construct() 153 | LzmaDec_Allocate() 154 | for (each new stream) 155 | { 156 | LzmaDec_Init() 157 | while (it needs more decompression) 158 | { 159 | LzmaDec_DecodeToDic() 160 | use data from CLzmaDec::dic and update CLzmaDec::dicPos 161 | } 162 | } 163 | LzmaDec_Free() 164 | */ 165 | 166 | /* LzmaDec_DecodeToDic 167 | 168 | The decoding to internal dictionary buffer (CLzmaDec::dic). 169 | You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! 170 | 171 | finishMode: 172 | It has meaning only if the decoding reaches output limit (dicLimit). 173 | LZMA_FINISH_ANY - Decode just dicLimit bytes. 174 | LZMA_FINISH_END - Stream must be finished after dicLimit. 175 | 176 | Returns: 177 | SZ_OK 178 | status: 179 | LZMA_STATUS_FINISHED_WITH_MARK 180 | LZMA_STATUS_NOT_FINISHED 181 | LZMA_STATUS_NEEDS_MORE_INPUT 182 | LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK 183 | SZ_ERROR_DATA - Data error 184 | */ 185 | 186 | SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, 187 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); 188 | 189 | 190 | /* ---------- Buffer Interface ---------- */ 191 | 192 | /* It's zlib-like interface. 193 | See LzmaDec_DecodeToDic description for information about STEPS and return results, 194 | but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need 195 | to work with CLzmaDec variables manually. 196 | 197 | finishMode: 198 | It has meaning only if the decoding reaches output limit (*destLen). 199 | LZMA_FINISH_ANY - Decode just destLen bytes. 200 | LZMA_FINISH_END - Stream must be finished after (*destLen). 201 | */ 202 | 203 | SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, 204 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); 205 | 206 | 207 | /* ---------- One Call Interface ---------- */ 208 | 209 | /* LzmaDecode 210 | 211 | finishMode: 212 | It has meaning only if the decoding reaches output limit (*destLen). 213 | LZMA_FINISH_ANY - Decode just destLen bytes. 214 | LZMA_FINISH_END - Stream must be finished after (*destLen). 215 | 216 | Returns: 217 | SZ_OK 218 | status: 219 | LZMA_STATUS_FINISHED_WITH_MARK 220 | LZMA_STATUS_NOT_FINISHED 221 | LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK 222 | SZ_ERROR_DATA - Data error 223 | SZ_ERROR_MEM - Memory allocation error 224 | SZ_ERROR_UNSUPPORTED - Unsupported properties 225 | SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). 226 | */ 227 | 228 | SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, 229 | const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, 230 | ELzmaStatus *status, ISzAllocPtr alloc); 231 | 232 | EXTERN_C_END 233 | 234 | #endif 235 | -------------------------------------------------------------------------------- /source/7zFile.c: -------------------------------------------------------------------------------- 1 | /* 7zFile.c -- File IO 2 | 2017-04-03 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include "7zFile.h" 7 | 8 | #ifndef USE_WINDOWS_FILE 9 | 10 | #ifndef UNDER_CE 11 | #include 12 | #endif 13 | 14 | #else 15 | 16 | /* 17 | ReadFile and WriteFile functions in Windows have BUG: 18 | If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) 19 | from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES 20 | (Insufficient system resources exist to complete the requested service). 21 | Probably in some version of Windows there are problems with other sizes: 22 | for 32 MB (maybe also for 16 MB). 23 | And message can be "Network connection was lost" 24 | */ 25 | 26 | #define kChunkSizeMax (1 << 22) 27 | 28 | #endif 29 | 30 | void File_Construct(CSzFile *p) 31 | { 32 | #ifdef USE_WINDOWS_FILE 33 | p->handle = INVALID_HANDLE_VALUE; 34 | #else 35 | p->file = NULL; 36 | #endif 37 | } 38 | 39 | #if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) 40 | static WRes File_Open(CSzFile *p, const char *name, int writeMode) 41 | { 42 | #ifdef USE_WINDOWS_FILE 43 | p->handle = CreateFileA(name, 44 | writeMode ? GENERIC_WRITE : GENERIC_READ, 45 | FILE_SHARE_READ, NULL, 46 | writeMode ? CREATE_ALWAYS : OPEN_EXISTING, 47 | FILE_ATTRIBUTE_NORMAL, NULL); 48 | return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); 49 | #else 50 | p->file = fopen(name, writeMode ? "wb+" : "rb"); 51 | return (p->file != 0) ? 0 : 52 | #ifdef UNDER_CE 53 | 2; /* ENOENT */ 54 | #else 55 | errno; 56 | #endif 57 | #endif 58 | } 59 | 60 | WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } 61 | WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } 62 | #endif 63 | 64 | #ifdef USE_WINDOWS_FILE 65 | static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode) 66 | { 67 | p->handle = CreateFileW(name, 68 | writeMode ? GENERIC_WRITE : GENERIC_READ, 69 | FILE_SHARE_READ, NULL, 70 | writeMode ? CREATE_ALWAYS : OPEN_EXISTING, 71 | FILE_ATTRIBUTE_NORMAL, NULL); 72 | return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); 73 | } 74 | WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); } 75 | WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); } 76 | #endif 77 | 78 | WRes File_Close(CSzFile *p) 79 | { 80 | #ifdef USE_WINDOWS_FILE 81 | if (p->handle != INVALID_HANDLE_VALUE) 82 | { 83 | if (!CloseHandle(p->handle)) 84 | return GetLastError(); 85 | p->handle = INVALID_HANDLE_VALUE; 86 | } 87 | #else 88 | if (p->file != NULL) 89 | { 90 | int res = fclose(p->file); 91 | if (res != 0) 92 | return res; 93 | p->file = NULL; 94 | } 95 | #endif 96 | return 0; 97 | } 98 | 99 | WRes File_Read(CSzFile *p, void *data, size_t *size) 100 | { 101 | size_t originalSize = *size; 102 | if (originalSize == 0) 103 | return 0; 104 | 105 | #ifdef USE_WINDOWS_FILE 106 | 107 | *size = 0; 108 | do 109 | { 110 | DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; 111 | DWORD processed = 0; 112 | BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); 113 | data = (void *)((Byte *)data + processed); 114 | originalSize -= processed; 115 | *size += processed; 116 | if (!res) 117 | return GetLastError(); 118 | if (processed == 0) 119 | break; 120 | } 121 | while (originalSize > 0); 122 | return 0; 123 | 124 | #else 125 | 126 | *size = fread(data, 1, originalSize, p->file); 127 | if (*size == originalSize) 128 | return 0; 129 | return ferror(p->file); 130 | 131 | #endif 132 | } 133 | 134 | WRes File_Write(CSzFile *p, const void *data, size_t *size) 135 | { 136 | size_t originalSize = *size; 137 | if (originalSize == 0) 138 | return 0; 139 | 140 | #ifdef USE_WINDOWS_FILE 141 | 142 | *size = 0; 143 | do 144 | { 145 | DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; 146 | DWORD processed = 0; 147 | BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); 148 | data = (void *)((Byte *)data + processed); 149 | originalSize -= processed; 150 | *size += processed; 151 | if (!res) 152 | return GetLastError(); 153 | if (processed == 0) 154 | break; 155 | } 156 | while (originalSize > 0); 157 | return 0; 158 | 159 | #else 160 | 161 | *size = fwrite(data, 1, originalSize, p->file); 162 | if (*size == originalSize) 163 | return 0; 164 | return ferror(p->file); 165 | 166 | #endif 167 | } 168 | 169 | WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) 170 | { 171 | #ifdef USE_WINDOWS_FILE 172 | 173 | LARGE_INTEGER value; 174 | DWORD moveMethod; 175 | value.LowPart = (DWORD)*pos; 176 | value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ 177 | switch (origin) 178 | { 179 | case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; 180 | case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; 181 | case SZ_SEEK_END: moveMethod = FILE_END; break; 182 | default: return ERROR_INVALID_PARAMETER; 183 | } 184 | value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod); 185 | if (value.LowPart == 0xFFFFFFFF) 186 | { 187 | WRes res = GetLastError(); 188 | if (res != NO_ERROR) 189 | return res; 190 | } 191 | *pos = ((Int64)value.HighPart << 32) | value.LowPart; 192 | return 0; 193 | 194 | #else 195 | 196 | int moveMethod; 197 | int res; 198 | switch (origin) 199 | { 200 | case SZ_SEEK_SET: moveMethod = SEEK_SET; break; 201 | case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; 202 | case SZ_SEEK_END: moveMethod = SEEK_END; break; 203 | default: return 1; 204 | } 205 | res = fseek(p->file, (long)*pos, moveMethod); 206 | *pos = ftell(p->file); 207 | return res; 208 | 209 | #endif 210 | } 211 | 212 | WRes File_GetLength(CSzFile *p, UInt64 *length) 213 | { 214 | #ifdef USE_WINDOWS_FILE 215 | 216 | DWORD sizeHigh; 217 | DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); 218 | if (sizeLow == 0xFFFFFFFF) 219 | { 220 | DWORD res = GetLastError(); 221 | if (res != NO_ERROR) 222 | return res; 223 | } 224 | *length = (((UInt64)sizeHigh) << 32) + sizeLow; 225 | return 0; 226 | 227 | #else 228 | 229 | long pos = ftell(p->file); 230 | int res = fseek(p->file, 0, SEEK_END); 231 | *length = ftell(p->file); 232 | fseek(p->file, pos, SEEK_SET); 233 | return res; 234 | 235 | #endif 236 | } 237 | 238 | 239 | /* ---------- FileSeqInStream ---------- */ 240 | 241 | static SRes FileSeqInStream_Read(const ISeqInStream *pp, void *buf, size_t *size) 242 | { 243 | CFileSeqInStream *p = CONTAINER_FROM_VTBL(pp, CFileSeqInStream, vt); 244 | return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; 245 | } 246 | 247 | void FileSeqInStream_CreateVTable(CFileSeqInStream *p) 248 | { 249 | p->vt.Read = FileSeqInStream_Read; 250 | } 251 | 252 | 253 | /* ---------- FileInStream ---------- */ 254 | 255 | static SRes FileInStream_Read(const ISeekInStream *pp, void *buf, size_t *size) 256 | { 257 | CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt); 258 | return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; 259 | } 260 | 261 | static SRes FileInStream_Seek(const ISeekInStream *pp, Int64 *pos, ESzSeek origin) 262 | { 263 | CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt); 264 | return File_Seek(&p->file, pos, origin); 265 | } 266 | 267 | void FileInStream_CreateVTable(CFileInStream *p) 268 | { 269 | p->vt.Read = FileInStream_Read; 270 | p->vt.Seek = FileInStream_Seek; 271 | } 272 | 273 | 274 | /* ---------- FileOutStream ---------- */ 275 | 276 | static size_t FileOutStream_Write(const ISeqOutStream *pp, const void *data, size_t size) 277 | { 278 | CFileOutStream *p = CONTAINER_FROM_VTBL(pp, CFileOutStream, vt); 279 | File_Write(&p->file, data, &size); 280 | return size; 281 | } 282 | 283 | void FileOutStream_CreateVTable(CFileOutStream *p) 284 | { 285 | p->vt.Write = FileOutStream_Write; 286 | } 287 | -------------------------------------------------------------------------------- /source/7zExtractor.c: -------------------------------------------------------------------------------- 1 | // 2 | // un7zip library by Bucanero 3 | // https://github.com/bucanero/libun7zip 4 | // 5 | // Based on https://github.com/hzy3774/AndroidUn7zip 6 | // by huzongyao on 17-11-24. 7 | // 8 | 9 | #include 10 | #include "7zTypes.h" 11 | #include "7z.h" 12 | #include "7zFile.h" 13 | #include "7zAlloc.h" 14 | #include "7zCrc.h" 15 | #include "7zFunctions.h" 16 | #include "7zAssetFile.h" 17 | #include "7zExtractor.h" 18 | 19 | #define OPTION_DETAIL 0x01 20 | #define OPTION_TEST 0x02 21 | #define OPTION_OUTPUT 0x04 22 | #define OPTION_EXTRACT (OPTION_TEST|OPTION_OUTPUT) 23 | 24 | static const ISzAlloc g_Alloc = {SzAlloc, SzFree}; 25 | 26 | static SRes 27 | extractStream(ISeekInStream *seekStream, const char *destDir, 28 | const int options, callback7z_t callback, size_t inBufSize) { 29 | 30 | ISzAlloc allocImp = g_Alloc; 31 | ISzAlloc allocTempImp = g_Alloc; 32 | CLookToRead2 lookStream; 33 | CSzArEx db; 34 | SRes res; 35 | UInt16 *temp = NULL; 36 | size_t tempSize = 0; 37 | 38 | LookToRead2_CreateVTable(&lookStream, False); 39 | lookStream.buf = NULL; 40 | res = SZ_OK; 41 | lookStream.buf = (Byte *) ISzAlloc_Alloc(&allocImp, inBufSize); 42 | if (!lookStream.buf) 43 | res = SZ_ERROR_MEM; 44 | else { 45 | lookStream.bufSize = inBufSize; 46 | lookStream.realStream = seekStream; 47 | LookToRead2_Init(&lookStream); 48 | } 49 | 50 | CrcGenerateTable(); 51 | SzArEx_Init(&db); 52 | if (res == SZ_OK) { 53 | res = SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp); 54 | } 55 | if (res == SZ_OK) { 56 | UInt32 i; 57 | /* 58 | if you need cache, use these 3 variables. 59 | if you use external function, you can make these variable as static. 60 | */ 61 | UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ 62 | Byte *outBuffer = NULL; /* it must be 0 before first call for each new archive. */ 63 | size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ 64 | CBuf fileNameBuf; 65 | Buf_Init(&fileNameBuf); 66 | 67 | for (i = 0; i < db.NumFiles; i++) { 68 | size_t offset = 0; 69 | size_t outSizeProcessed = 0; 70 | size_t len; 71 | BoolInt isDir = SzArEx_IsDir(&db, i); 72 | len = SzArEx_GetFileNameUtf16(&db, i, NULL); 73 | if (len > tempSize) { 74 | SzFree(NULL, temp); 75 | tempSize = len; 76 | temp = (UInt16 *) SzAlloc(NULL, tempSize * sizeof(temp[0])); 77 | if (!temp) { 78 | res = SZ_ERROR_MEM; 79 | break; 80 | } 81 | } 82 | SzArEx_GetFileNameUtf16(&db, i, temp); 83 | res = Utf16_To_Char(&fileNameBuf, temp); 84 | if (res != SZ_OK) { 85 | break; 86 | } 87 | UInt64 fileSize = SzArEx_GetFileSize(&db, i); 88 | 89 | if (callback) 90 | callback ((char*) fileNameBuf.data, fileSize, i+1, db.NumFiles); 91 | 92 | if (options & OPTION_DETAIL) { 93 | char attr[8], file_size[32], file_time[32]; 94 | GetAttribString(SzBitWithVals_Check(&db.Attribs, i) 95 | ? db.Attribs.Vals[i] : 0, isDir, attr); 96 | UInt64ToStr(fileSize, file_size, 10); 97 | if (SzBitWithVals_Check(&db.MTime, i)) 98 | ConvertFileTimeToString(&db.MTime.Vals[i], file_time); 99 | else { 100 | size_t j; 101 | for (j = 0; j < 19; j++) 102 | file_time[j] = ' '; 103 | file_time[j] = '\0'; 104 | } 105 | } 106 | if (options & OPTION_TEST) { 107 | if (!isDir) { 108 | res = SzArEx_Extract(&db, &lookStream.vt, i, &blockIndex, &outBuffer, 109 | &outBufferSize, &offset, &outSizeProcessed, 110 | &allocImp, &allocTempImp); 111 | if (res != SZ_OK) 112 | break; 113 | } 114 | if (options & OPTION_OUTPUT) { 115 | CSzFile outFile; 116 | size_t processedSize; 117 | UInt16 *name = temp; 118 | const UInt16 *destPath = (const UInt16 *) name; 119 | for (size_t j = 0; name[j] != 0; j++) { 120 | if (name[j] == CHAR_PATH_SEPARATOR) { 121 | name[j] = 0; 122 | MyCreateDir(name, destDir); 123 | name[j] = CHAR_PATH_SEPARATOR; 124 | } 125 | } 126 | if (isDir) { 127 | MyCreateDir(name, destDir); 128 | continue; 129 | } else if (OutFile_OpenUtf16(&outFile, destPath, destDir)) { 130 | PrintError("can not open output file"); 131 | res = SZ_ERROR_FAIL; 132 | break; 133 | } 134 | processedSize = outSizeProcessed; 135 | if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || 136 | processedSize != outSizeProcessed) { 137 | PrintError("can not write output file"); 138 | res = SZ_ERROR_WRITE; 139 | break; 140 | } 141 | if (File_Close(&outFile)) { 142 | PrintError("can not close output file"); 143 | res = SZ_ERROR_FAIL; 144 | break; 145 | } 146 | } 147 | } 148 | } 149 | Buf_Free(&fileNameBuf, &g_Alloc); 150 | ISzAlloc_Free(&allocImp, outBuffer); 151 | } 152 | SzFree(NULL, temp); 153 | SzArEx_Free(&db, &allocImp); 154 | ISzAlloc_Free(&allocImp, lookStream.buf); 155 | if (res != SZ_OK) { 156 | PrintError("Stream Extract Error"); 157 | } 158 | return res; 159 | } 160 | 161 | static int _process7zFile(const char *srcFile, const char *destDir, int opts, callback7z_t callback, size_t inBufSize) 162 | { 163 | CFileInStream archiveStream; 164 | if (InFile_Open(&archiveStream.file, srcFile)) { 165 | PrintError("Input File Open Error"); 166 | return SZ_ERROR_ARCHIVE; 167 | } 168 | FileInStream_CreateVTable(&archiveStream); 169 | SRes res = extractStream(&archiveStream.vt, destDir, opts, callback, inBufSize); 170 | File_Close(&archiveStream.file); 171 | 172 | return res; 173 | } 174 | 175 | static int _process7zAsset(const void *buf, size_t buf_size, const char *destDir, int opts, callback7z_t callback, size_t inBufSize) 176 | { 177 | CAssetFileInStream archiveStream; 178 | if (InAssetFile_Open(&archiveStream.assetFile, buf, buf_size)) { 179 | PrintError("Memory Asset Open Error"); 180 | return SZ_ERROR_ARCHIVE; 181 | } 182 | AssetFileInStream_CreateVTable(&archiveStream); 183 | SRes res = extractStream(&archiveStream.vt, destDir, opts, callback, inBufSize); 184 | AssetFile_Close(&archiveStream.assetFile); 185 | 186 | return res; 187 | } 188 | 189 | /** 190 | * extract all from 7z 191 | */ 192 | int un7z_ExtractArchive(const char *srcFile, const char *destDir, callback7z_t callback, unsigned long inBufSize) 193 | { 194 | mkdir(destDir, 0777); 195 | return _process7zFile(srcFile, destDir, OPTION_EXTRACT, callback, inBufSize); 196 | } 197 | 198 | int un7z_TestArchive(const char *srcFile, callback7z_t callback, unsigned long inBufSize) 199 | { 200 | return _process7zFile(srcFile, NULL, OPTION_TEST, callback, inBufSize); 201 | } 202 | 203 | int un7z_ListArchive(const char *srcFile, callback7z_t callback) 204 | { 205 | return _process7zFile(srcFile, NULL, 0, callback, UN7Z_IN_BUF_SIZE); 206 | } 207 | 208 | /** 209 | * extract all from memory 7z buffer 210 | */ 211 | int un7z_ExtractAsset(const void *buffer, unsigned long size, const char *destDir, callback7z_t callback, unsigned long inBufSize) 212 | { 213 | mkdir(destDir, 0777); 214 | return _process7zAsset(buffer, size, destDir, OPTION_EXTRACT, callback, inBufSize); 215 | } 216 | 217 | int un7z_TestAsset(const void *buffer, unsigned long size, callback7z_t callback, unsigned long inBufSize) 218 | { 219 | return _process7zAsset(buffer, size, NULL, OPTION_TEST, callback, inBufSize); 220 | } 221 | 222 | int un7z_ListAsset(const void *buffer, unsigned long size, callback7z_t callback) 223 | { 224 | return _process7zAsset(buffer, size, NULL, 0, callback, UN7Z_IN_BUF_SIZE); 225 | } 226 | -------------------------------------------------------------------------------- /include/CpuArch.h: -------------------------------------------------------------------------------- 1 | /* CpuArch.h -- CPU specific code 2 | 2018-02-18 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __CPU_ARCH_H 5 | #define __CPU_ARCH_H 6 | 7 | #include "7zTypes.h" 8 | 9 | EXTERN_C_BEGIN 10 | 11 | /* 12 | MY_CPU_LE means that CPU is LITTLE ENDIAN. 13 | MY_CPU_BE means that CPU is BIG ENDIAN. 14 | If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform. 15 | 16 | MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. 17 | */ 18 | 19 | #if defined(_M_X64) \ 20 | || defined(_M_AMD64) \ 21 | || defined(__x86_64__) \ 22 | || defined(__AMD64__) \ 23 | || defined(__amd64__) 24 | #define MY_CPU_AMD64 25 | #ifdef __ILP32__ 26 | #define MY_CPU_NAME "x32" 27 | #else 28 | #define MY_CPU_NAME "x64" 29 | #endif 30 | #define MY_CPU_64BIT 31 | #endif 32 | 33 | 34 | #if defined(_M_IX86) \ 35 | || defined(__i386__) 36 | #define MY_CPU_X86 37 | #define MY_CPU_NAME "x86" 38 | #define MY_CPU_32BIT 39 | #endif 40 | 41 | 42 | #if defined(_M_ARM64) \ 43 | || defined(__AARCH64EL__) \ 44 | || defined(__AARCH64EB__) \ 45 | || defined(__aarch64__) 46 | #define MY_CPU_ARM64 47 | #define MY_CPU_NAME "arm64" 48 | #define MY_CPU_64BIT 49 | #endif 50 | 51 | 52 | #if defined(_M_ARM) \ 53 | || defined(_M_ARM_NT) \ 54 | || defined(_M_ARMT) \ 55 | || defined(__arm__) \ 56 | || defined(__thumb__) \ 57 | || defined(__ARMEL__) \ 58 | || defined(__ARMEB__) \ 59 | || defined(__THUMBEL__) \ 60 | || defined(__THUMBEB__) 61 | #define MY_CPU_ARM 62 | #define MY_CPU_NAME "arm" 63 | #define MY_CPU_32BIT 64 | #endif 65 | 66 | 67 | #if defined(_M_IA64) \ 68 | || defined(__ia64__) 69 | #define MY_CPU_IA64 70 | #define MY_CPU_NAME "ia64" 71 | #define MY_CPU_64BIT 72 | #endif 73 | 74 | 75 | #if defined(__mips64) \ 76 | || defined(__mips64__) \ 77 | || (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3)) 78 | #define MY_CPU_NAME "mips64" 79 | #define MY_CPU_64BIT 80 | #elif defined(__mips__) 81 | #define MY_CPU_NAME "mips" 82 | /* #define MY_CPU_32BIT */ 83 | #endif 84 | 85 | 86 | #if defined(__ppc64__) \ 87 | || defined(__powerpc64__) 88 | #ifdef __ILP32__ 89 | #define MY_CPU_NAME "ppc64-32" 90 | #else 91 | #define MY_CPU_NAME "ppc64" 92 | #endif 93 | #define MY_CPU_64BIT 94 | #elif defined(__ppc__) \ 95 | || defined(__powerpc__) 96 | #define MY_CPU_NAME "ppc" 97 | #define MY_CPU_32BIT 98 | #endif 99 | 100 | 101 | #if defined(__sparc64__) 102 | #define MY_CPU_NAME "sparc64" 103 | #define MY_CPU_64BIT 104 | #elif defined(__sparc__) 105 | #define MY_CPU_NAME "sparc" 106 | /* #define MY_CPU_32BIT */ 107 | #endif 108 | 109 | 110 | #if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) 111 | #define MY_CPU_X86_OR_AMD64 112 | #endif 113 | 114 | 115 | #ifdef _WIN32 116 | 117 | #ifdef MY_CPU_ARM 118 | #define MY_CPU_ARM_LE 119 | #endif 120 | 121 | #ifdef MY_CPU_ARM64 122 | #define MY_CPU_ARM64_LE 123 | #endif 124 | 125 | #ifdef _M_IA64 126 | #define MY_CPU_IA64_LE 127 | #endif 128 | 129 | #endif 130 | 131 | 132 | #if defined(MY_CPU_X86_OR_AMD64) \ 133 | || defined(MY_CPU_ARM_LE) \ 134 | || defined(MY_CPU_ARM64_LE) \ 135 | || defined(MY_CPU_IA64_LE) \ 136 | || defined(__LITTLE_ENDIAN__) \ 137 | || defined(__ARMEL__) \ 138 | || defined(__THUMBEL__) \ 139 | || defined(__AARCH64EL__) \ 140 | || defined(__MIPSEL__) \ 141 | || defined(__MIPSEL) \ 142 | || defined(_MIPSEL) \ 143 | || defined(__BFIN__) \ 144 | || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) 145 | #define MY_CPU_LE 146 | #endif 147 | 148 | #if defined(__BIG_ENDIAN__) \ 149 | || defined(__ARMEB__) \ 150 | || defined(__THUMBEB__) \ 151 | || defined(__AARCH64EB__) \ 152 | || defined(__MIPSEB__) \ 153 | || defined(__MIPSEB) \ 154 | || defined(_MIPSEB) \ 155 | || defined(__m68k__) \ 156 | || defined(__s390__) \ 157 | || defined(__s390x__) \ 158 | || defined(__zarch__) \ 159 | || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) 160 | #define MY_CPU_BE 161 | #endif 162 | 163 | 164 | #if defined(MY_CPU_LE) && defined(MY_CPU_BE) 165 | #error Stop_Compiling_Bad_Endian 166 | #endif 167 | 168 | 169 | #if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT) 170 | #error Stop_Compiling_Bad_32_64_BIT 171 | #endif 172 | 173 | 174 | #ifndef MY_CPU_NAME 175 | #ifdef MY_CPU_LE 176 | #define MY_CPU_NAME "LE" 177 | #elif defined(MY_CPU_BE) 178 | #define MY_CPU_NAME "BE" 179 | #else 180 | /* 181 | #define MY_CPU_NAME "" 182 | */ 183 | #endif 184 | #endif 185 | 186 | 187 | 188 | 189 | 190 | #ifdef MY_CPU_LE 191 | #if defined(MY_CPU_X86_OR_AMD64) \ 192 | || defined(MY_CPU_ARM64) \ 193 | || defined(__ARM_FEATURE_UNALIGNED) 194 | #define MY_CPU_LE_UNALIGN 195 | #endif 196 | #endif 197 | 198 | 199 | #ifdef MY_CPU_LE_UNALIGN 200 | 201 | #define GetUi16(p) (*(const UInt16 *)(const void *)(p)) 202 | #define GetUi32(p) (*(const UInt32 *)(const void *)(p)) 203 | #define GetUi64(p) (*(const UInt64 *)(const void *)(p)) 204 | 205 | #define SetUi16(p, v) { *(UInt16 *)(p) = (v); } 206 | #define SetUi32(p, v) { *(UInt32 *)(p) = (v); } 207 | #define SetUi64(p, v) { *(UInt64 *)(p) = (v); } 208 | 209 | #else 210 | 211 | #define GetUi16(p) ( (UInt16) ( \ 212 | ((const Byte *)(p))[0] | \ 213 | ((UInt16)((const Byte *)(p))[1] << 8) )) 214 | 215 | #define GetUi32(p) ( \ 216 | ((const Byte *)(p))[0] | \ 217 | ((UInt32)((const Byte *)(p))[1] << 8) | \ 218 | ((UInt32)((const Byte *)(p))[2] << 16) | \ 219 | ((UInt32)((const Byte *)(p))[3] << 24)) 220 | 221 | #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) 222 | 223 | #define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ 224 | _ppp_[0] = (Byte)_vvv_; \ 225 | _ppp_[1] = (Byte)(_vvv_ >> 8); } 226 | 227 | #define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ 228 | _ppp_[0] = (Byte)_vvv_; \ 229 | _ppp_[1] = (Byte)(_vvv_ >> 8); \ 230 | _ppp_[2] = (Byte)(_vvv_ >> 16); \ 231 | _ppp_[3] = (Byte)(_vvv_ >> 24); } 232 | 233 | #define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \ 234 | SetUi32(_ppp2_ , (UInt32)_vvv2_); \ 235 | SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); } 236 | 237 | #endif 238 | 239 | #ifdef __has_builtin 240 | #define MY__has_builtin(x) __has_builtin(x) 241 | #else 242 | #define MY__has_builtin(x) 0 243 | #endif 244 | 245 | #if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300) 246 | 247 | /* Note: we use bswap instruction, that is unsupported in 386 cpu */ 248 | 249 | #include 250 | 251 | #pragma intrinsic(_byteswap_ushort) 252 | #pragma intrinsic(_byteswap_ulong) 253 | #pragma intrinsic(_byteswap_uint64) 254 | 255 | /* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */ 256 | #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) 257 | #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) 258 | 259 | #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v) 260 | 261 | #elif defined(MY_CPU_LE_UNALIGN) && ( \ 262 | (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ 263 | || (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) ) 264 | 265 | /* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const Byte *)(p)) */ 266 | #define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p)) 267 | #define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p)) 268 | 269 | #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v) 270 | 271 | #else 272 | 273 | #define GetBe32(p) ( \ 274 | ((UInt32)((const Byte *)(p))[0] << 24) | \ 275 | ((UInt32)((const Byte *)(p))[1] << 16) | \ 276 | ((UInt32)((const Byte *)(p))[2] << 8) | \ 277 | ((const Byte *)(p))[3] ) 278 | 279 | #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) 280 | 281 | #define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ 282 | _ppp_[0] = (Byte)(_vvv_ >> 24); \ 283 | _ppp_[1] = (Byte)(_vvv_ >> 16); \ 284 | _ppp_[2] = (Byte)(_vvv_ >> 8); \ 285 | _ppp_[3] = (Byte)_vvv_; } 286 | 287 | #endif 288 | 289 | 290 | #ifndef GetBe16 291 | 292 | #define GetBe16(p) ( (UInt16) ( \ 293 | ((UInt16)((const Byte *)(p))[0] << 8) | \ 294 | ((const Byte *)(p))[1] )) 295 | 296 | #endif 297 | 298 | 299 | 300 | #ifdef MY_CPU_X86_OR_AMD64 301 | 302 | typedef struct 303 | { 304 | UInt32 maxFunc; 305 | UInt32 vendor[3]; 306 | UInt32 ver; 307 | UInt32 b; 308 | UInt32 c; 309 | UInt32 d; 310 | } Cx86cpuid; 311 | 312 | enum 313 | { 314 | CPU_FIRM_INTEL, 315 | CPU_FIRM_AMD, 316 | CPU_FIRM_VIA 317 | }; 318 | 319 | void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d); 320 | 321 | BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p); 322 | int x86cpuid_GetFirm(const Cx86cpuid *p); 323 | 324 | #define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF)) 325 | #define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF)) 326 | #define x86cpuid_GetStepping(ver) (ver & 0xF) 327 | 328 | BoolInt CPU_Is_InOrder(); 329 | BoolInt CPU_Is_Aes_Supported(); 330 | BoolInt CPU_IsSupported_PageGB(); 331 | 332 | #endif 333 | 334 | EXTERN_C_END 335 | 336 | #endif 337 | -------------------------------------------------------------------------------- /include/7zTypes.h: -------------------------------------------------------------------------------- 1 | /* 7zTypes.h -- Basic types 2 | 2018-08-04 : Igor Pavlov : Public domain */ 3 | 4 | #ifndef __7Z_TYPES_H 5 | #define __7Z_TYPES_H 6 | 7 | #ifdef _WIN32 8 | /* #include */ 9 | #endif 10 | 11 | #include 12 | 13 | #ifndef EXTERN_C_BEGIN 14 | #ifdef __cplusplus 15 | #define EXTERN_C_BEGIN extern "C" { 16 | #define EXTERN_C_END } 17 | #else 18 | #define EXTERN_C_BEGIN 19 | #define EXTERN_C_END 20 | #endif 21 | #endif 22 | 23 | EXTERN_C_BEGIN 24 | 25 | #define SZ_OK 0 26 | 27 | #define SZ_ERROR_DATA 1 28 | #define SZ_ERROR_MEM 2 29 | #define SZ_ERROR_CRC 3 30 | #define SZ_ERROR_UNSUPPORTED 4 31 | #define SZ_ERROR_PARAM 5 32 | #define SZ_ERROR_INPUT_EOF 6 33 | #define SZ_ERROR_OUTPUT_EOF 7 34 | #define SZ_ERROR_READ 8 35 | #define SZ_ERROR_WRITE 9 36 | #define SZ_ERROR_PROGRESS 10 37 | #define SZ_ERROR_FAIL 11 38 | #define SZ_ERROR_THREAD 12 39 | 40 | #define SZ_ERROR_ARCHIVE 16 41 | #define SZ_ERROR_NO_ARCHIVE 17 42 | 43 | typedef int SRes; 44 | 45 | 46 | #ifdef _WIN32 47 | 48 | /* typedef DWORD WRes; */ 49 | typedef unsigned WRes; 50 | #define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x) 51 | 52 | #else 53 | 54 | typedef int WRes; 55 | #define MY__FACILITY_WIN32 7 56 | #define MY__FACILITY__WRes MY__FACILITY_WIN32 57 | #define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000))) 58 | 59 | #endif 60 | 61 | 62 | #ifndef RINOK 63 | #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } 64 | #endif 65 | 66 | typedef unsigned char Byte; 67 | typedef short Int16; 68 | typedef unsigned short UInt16; 69 | 70 | #ifdef _LZMA_UINT32_IS_ULONG 71 | typedef long Int32; 72 | typedef unsigned long UInt32; 73 | #else 74 | typedef int Int32; 75 | typedef unsigned int UInt32; 76 | #endif 77 | 78 | #ifdef _SZ_NO_INT_64 79 | 80 | /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. 81 | NOTES: Some code will work incorrectly in that case! */ 82 | 83 | typedef long Int64; 84 | typedef unsigned long UInt64; 85 | 86 | #else 87 | 88 | #if defined(_MSC_VER) || defined(__BORLANDC__) 89 | typedef __int64 Int64; 90 | typedef unsigned __int64 UInt64; 91 | #define UINT64_CONST(n) n 92 | #else 93 | typedef long long int Int64; 94 | typedef unsigned long long int UInt64; 95 | #define UINT64_CONST(n) n ## ULL 96 | #endif 97 | 98 | #endif 99 | 100 | #ifdef _LZMA_NO_SYSTEM_SIZE_T 101 | typedef UInt32 SizeT; 102 | #else 103 | typedef size_t SizeT; 104 | #endif 105 | 106 | typedef int BoolInt; 107 | /* typedef BoolInt Bool; */ 108 | #define True 1 109 | #define False 0 110 | 111 | 112 | #ifdef _WIN32 113 | #define MY_STD_CALL __stdcall 114 | #else 115 | #define MY_STD_CALL 116 | #endif 117 | 118 | #ifdef _MSC_VER 119 | 120 | #if _MSC_VER >= 1300 121 | #define MY_NO_INLINE __declspec(noinline) 122 | #else 123 | #define MY_NO_INLINE 124 | #endif 125 | 126 | #define MY_FORCE_INLINE __forceinline 127 | 128 | #define MY_CDECL __cdecl 129 | #define MY_FAST_CALL __fastcall 130 | 131 | #else 132 | 133 | #define MY_NO_INLINE 134 | #define MY_FORCE_INLINE 135 | #define MY_CDECL 136 | #define MY_FAST_CALL 137 | 138 | /* inline keyword : for C++ / C99 */ 139 | 140 | /* GCC, clang: */ 141 | /* 142 | #if defined (__GNUC__) && (__GNUC__ >= 4) 143 | #define MY_FORCE_INLINE __attribute__((always_inline)) 144 | #define MY_NO_INLINE __attribute__((noinline)) 145 | #endif 146 | */ 147 | 148 | #endif 149 | 150 | 151 | /* The following interfaces use first parameter as pointer to structure */ 152 | 153 | typedef struct IByteIn IByteIn; 154 | struct IByteIn 155 | { 156 | Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */ 157 | }; 158 | #define IByteIn_Read(p) (p)->Read(p) 159 | 160 | 161 | typedef struct IByteOut IByteOut; 162 | struct IByteOut 163 | { 164 | void (*Write)(const IByteOut *p, Byte b); 165 | }; 166 | #define IByteOut_Write(p, b) (p)->Write(p, b) 167 | 168 | 169 | typedef struct ISeqInStream ISeqInStream; 170 | struct ISeqInStream 171 | { 172 | SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size); 173 | /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. 174 | (output(*size) < input(*size)) is allowed */ 175 | }; 176 | #define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size) 177 | 178 | /* it can return SZ_ERROR_INPUT_EOF */ 179 | SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size); 180 | SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType); 181 | SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf); 182 | 183 | 184 | typedef struct ISeqOutStream ISeqOutStream; 185 | struct ISeqOutStream 186 | { 187 | size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size); 188 | /* Returns: result - the number of actually written bytes. 189 | (result < size) means error */ 190 | }; 191 | #define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size) 192 | 193 | typedef enum 194 | { 195 | SZ_SEEK_SET = 0, 196 | SZ_SEEK_CUR = 1, 197 | SZ_SEEK_END = 2 198 | } ESzSeek; 199 | 200 | 201 | typedef struct ISeekInStream ISeekInStream; 202 | struct ISeekInStream 203 | { 204 | SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ 205 | SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin); 206 | }; 207 | #define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size) 208 | #define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) 209 | 210 | 211 | typedef struct ILookInStream ILookInStream; 212 | struct ILookInStream 213 | { 214 | SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size); 215 | /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. 216 | (output(*size) > input(*size)) is not allowed 217 | (output(*size) < input(*size)) is allowed */ 218 | SRes (*Skip)(const ILookInStream *p, size_t offset); 219 | /* offset must be <= output(*size) of Look */ 220 | 221 | SRes (*Read)(const ILookInStream *p, void *buf, size_t *size); 222 | /* reads directly (without buffer). It's same as ISeqInStream::Read */ 223 | SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin); 224 | }; 225 | 226 | #define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size) 227 | #define ILookInStream_Skip(p, offset) (p)->Skip(p, offset) 228 | #define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size) 229 | #define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) 230 | 231 | 232 | SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size); 233 | SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset); 234 | 235 | /* reads via ILookInStream::Read */ 236 | SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType); 237 | SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size); 238 | 239 | 240 | 241 | typedef struct 242 | { 243 | ILookInStream vt; 244 | const ISeekInStream *realStream; 245 | 246 | size_t pos; 247 | size_t size; /* it's data size */ 248 | 249 | /* the following variables must be set outside */ 250 | Byte *buf; 251 | size_t bufSize; 252 | } CLookToRead2; 253 | 254 | void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead); 255 | 256 | #define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; } 257 | 258 | 259 | typedef struct 260 | { 261 | ISeqInStream vt; 262 | const ILookInStream *realStream; 263 | } CSecToLook; 264 | 265 | void SecToLook_CreateVTable(CSecToLook *p); 266 | 267 | 268 | 269 | typedef struct 270 | { 271 | ISeqInStream vt; 272 | const ILookInStream *realStream; 273 | } CSecToRead; 274 | 275 | void SecToRead_CreateVTable(CSecToRead *p); 276 | 277 | 278 | typedef struct ICompressProgress ICompressProgress; 279 | 280 | struct ICompressProgress 281 | { 282 | SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize); 283 | /* Returns: result. (result != SZ_OK) means break. 284 | Value (UInt64)(Int64)-1 for size means unknown value. */ 285 | }; 286 | #define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize) 287 | 288 | 289 | 290 | typedef struct ISzAlloc ISzAlloc; 291 | typedef const ISzAlloc * ISzAllocPtr; 292 | 293 | struct ISzAlloc 294 | { 295 | void *(*Alloc)(ISzAllocPtr p, size_t size); 296 | void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */ 297 | }; 298 | 299 | #define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size) 300 | #define ISzAlloc_Free(p, a) (p)->Free(p, a) 301 | 302 | /* deprecated */ 303 | #define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size) 304 | #define IAlloc_Free(p, a) ISzAlloc_Free(p, a) 305 | 306 | 307 | 308 | 309 | 310 | #ifndef MY_offsetof 311 | #ifdef offsetof 312 | #define MY_offsetof(type, m) offsetof(type, m) 313 | /* 314 | #define MY_offsetof(type, m) FIELD_OFFSET(type, m) 315 | */ 316 | #else 317 | #define MY_offsetof(type, m) ((size_t)&(((type *)0)->m)) 318 | #endif 319 | #endif 320 | 321 | 322 | 323 | #ifndef MY_container_of 324 | 325 | /* 326 | #define MY_container_of(ptr, type, m) container_of(ptr, type, m) 327 | #define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m) 328 | #define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m))) 329 | #define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m)))) 330 | */ 331 | 332 | /* 333 | GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly" 334 | GCC 3.4.4 : classes with constructor 335 | GCC 4.8.1 : classes with non-public variable members" 336 | */ 337 | 338 | #define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m))) 339 | 340 | 341 | #endif 342 | 343 | #define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr)) 344 | 345 | /* 346 | #define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) 347 | */ 348 | #define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m) 349 | 350 | #define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) 351 | /* 352 | #define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m) 353 | */ 354 | 355 | 356 | 357 | #ifdef _WIN32 358 | 359 | #define CHAR_PATH_SEPARATOR '\\' 360 | #define WCHAR_PATH_SEPARATOR L'\\' 361 | #define STRING_PATH_SEPARATOR "\\" 362 | #define WSTRING_PATH_SEPARATOR L"\\" 363 | 364 | #else 365 | 366 | #define CHAR_PATH_SEPARATOR '/' 367 | #define WCHAR_PATH_SEPARATOR L'/' 368 | #define STRING_PATH_SEPARATOR "/" 369 | #define WSTRING_PATH_SEPARATOR L"/" 370 | 371 | #endif 372 | 373 | EXTERN_C_END 374 | 375 | #endif 376 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /source/Lzma2Dec.c: -------------------------------------------------------------------------------- 1 | /* Lzma2Dec.c -- LZMA2 Decoder 2 | 2019-02-02 : Igor Pavlov : Public domain */ 3 | 4 | /* #define SHOW_DEBUG_INFO */ 5 | 6 | #include "Precomp.h" 7 | 8 | #ifdef SHOW_DEBUG_INFO 9 | #include 10 | #endif 11 | 12 | #include 13 | 14 | #include "Lzma2Dec.h" 15 | 16 | /* 17 | 00000000 - End of data 18 | 00000001 U U - Uncompressed, reset dic, need reset state and set new prop 19 | 00000010 U U - Uncompressed, no reset 20 | 100uuuuu U U P P - LZMA, no reset 21 | 101uuuuu U U P P - LZMA, reset state 22 | 110uuuuu U U P P S - LZMA, reset state + set new prop 23 | 111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic 24 | 25 | u, U - Unpack Size 26 | P - Pack Size 27 | S - Props 28 | */ 29 | 30 | #define LZMA2_CONTROL_COPY_RESET_DIC 1 31 | 32 | #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0) 33 | 34 | #define LZMA2_LCLP_MAX 4 35 | #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) 36 | 37 | #ifdef SHOW_DEBUG_INFO 38 | #define PRF(x) x 39 | #else 40 | #define PRF(x) 41 | #endif 42 | 43 | typedef enum 44 | { 45 | LZMA2_STATE_CONTROL, 46 | LZMA2_STATE_UNPACK0, 47 | LZMA2_STATE_UNPACK1, 48 | LZMA2_STATE_PACK0, 49 | LZMA2_STATE_PACK1, 50 | LZMA2_STATE_PROP, 51 | LZMA2_STATE_DATA, 52 | LZMA2_STATE_DATA_CONT, 53 | LZMA2_STATE_FINISHED, 54 | LZMA2_STATE_ERROR 55 | } ELzma2State; 56 | 57 | static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props) 58 | { 59 | UInt32 dicSize; 60 | if (prop > 40) 61 | return SZ_ERROR_UNSUPPORTED; 62 | dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop); 63 | props[0] = (Byte)LZMA2_LCLP_MAX; 64 | props[1] = (Byte)(dicSize); 65 | props[2] = (Byte)(dicSize >> 8); 66 | props[3] = (Byte)(dicSize >> 16); 67 | props[4] = (Byte)(dicSize >> 24); 68 | return SZ_OK; 69 | } 70 | 71 | SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc) 72 | { 73 | Byte props[LZMA_PROPS_SIZE]; 74 | RINOK(Lzma2Dec_GetOldProps(prop, props)); 75 | return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc); 76 | } 77 | 78 | SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc) 79 | { 80 | Byte props[LZMA_PROPS_SIZE]; 81 | RINOK(Lzma2Dec_GetOldProps(prop, props)); 82 | return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc); 83 | } 84 | 85 | void Lzma2Dec_Init(CLzma2Dec *p) 86 | { 87 | p->state = LZMA2_STATE_CONTROL; 88 | p->needInitLevel = 0xE0; 89 | p->isExtraMode = False; 90 | p->unpackSize = 0; 91 | 92 | // p->decoder.dicPos = 0; // we can use it instead of full init 93 | LzmaDec_Init(&p->decoder); 94 | } 95 | 96 | static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) 97 | { 98 | switch (p->state) 99 | { 100 | case LZMA2_STATE_CONTROL: 101 | p->isExtraMode = False; 102 | p->control = b; 103 | PRF(printf("\n %8X", (unsigned)p->decoder.dicPos)); 104 | PRF(printf(" %02X", (unsigned)b)); 105 | if (b == 0) 106 | return LZMA2_STATE_FINISHED; 107 | if (LZMA2_IS_UNCOMPRESSED_STATE(p)) 108 | { 109 | if (b == LZMA2_CONTROL_COPY_RESET_DIC) 110 | p->needInitLevel = 0xC0; 111 | else if (b > 2 || p->needInitLevel == 0xE0) 112 | return LZMA2_STATE_ERROR; 113 | } 114 | else 115 | { 116 | if (b < p->needInitLevel) 117 | return LZMA2_STATE_ERROR; 118 | p->needInitLevel = 0; 119 | p->unpackSize = (UInt32)(b & 0x1F) << 16; 120 | } 121 | return LZMA2_STATE_UNPACK0; 122 | 123 | case LZMA2_STATE_UNPACK0: 124 | p->unpackSize |= (UInt32)b << 8; 125 | return LZMA2_STATE_UNPACK1; 126 | 127 | case LZMA2_STATE_UNPACK1: 128 | p->unpackSize |= (UInt32)b; 129 | p->unpackSize++; 130 | PRF(printf(" %7u", (unsigned)p->unpackSize)); 131 | return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; 132 | 133 | case LZMA2_STATE_PACK0: 134 | p->packSize = (UInt32)b << 8; 135 | return LZMA2_STATE_PACK1; 136 | 137 | case LZMA2_STATE_PACK1: 138 | p->packSize |= (UInt32)b; 139 | p->packSize++; 140 | // if (p->packSize < 5) return LZMA2_STATE_ERROR; 141 | PRF(printf(" %5u", (unsigned)p->packSize)); 142 | return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA; 143 | 144 | case LZMA2_STATE_PROP: 145 | { 146 | unsigned lc, lp; 147 | if (b >= (9 * 5 * 5)) 148 | return LZMA2_STATE_ERROR; 149 | lc = b % 9; 150 | b /= 9; 151 | p->decoder.prop.pb = (Byte)(b / 5); 152 | lp = b % 5; 153 | if (lc + lp > LZMA2_LCLP_MAX) 154 | return LZMA2_STATE_ERROR; 155 | p->decoder.prop.lc = (Byte)lc; 156 | p->decoder.prop.lp = (Byte)lp; 157 | return LZMA2_STATE_DATA; 158 | } 159 | } 160 | return LZMA2_STATE_ERROR; 161 | } 162 | 163 | static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size) 164 | { 165 | memcpy(p->dic + p->dicPos, src, size); 166 | p->dicPos += size; 167 | if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size) 168 | p->checkDicSize = p->prop.dicSize; 169 | p->processedPos += (UInt32)size; 170 | } 171 | 172 | void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState); 173 | 174 | 175 | SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, 176 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) 177 | { 178 | SizeT inSize = *srcLen; 179 | *srcLen = 0; 180 | *status = LZMA_STATUS_NOT_SPECIFIED; 181 | 182 | while (p->state != LZMA2_STATE_ERROR) 183 | { 184 | SizeT dicPos; 185 | 186 | if (p->state == LZMA2_STATE_FINISHED) 187 | { 188 | *status = LZMA_STATUS_FINISHED_WITH_MARK; 189 | return SZ_OK; 190 | } 191 | 192 | dicPos = p->decoder.dicPos; 193 | 194 | if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) 195 | { 196 | *status = LZMA_STATUS_NOT_FINISHED; 197 | return SZ_OK; 198 | } 199 | 200 | if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) 201 | { 202 | if (*srcLen == inSize) 203 | { 204 | *status = LZMA_STATUS_NEEDS_MORE_INPUT; 205 | return SZ_OK; 206 | } 207 | (*srcLen)++; 208 | p->state = Lzma2Dec_UpdateState(p, *src++); 209 | if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED) 210 | break; 211 | continue; 212 | } 213 | 214 | { 215 | SizeT inCur = inSize - *srcLen; 216 | SizeT outCur = dicLimit - dicPos; 217 | ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; 218 | 219 | if (outCur >= p->unpackSize) 220 | { 221 | outCur = (SizeT)p->unpackSize; 222 | curFinishMode = LZMA_FINISH_END; 223 | } 224 | 225 | if (LZMA2_IS_UNCOMPRESSED_STATE(p)) 226 | { 227 | if (inCur == 0) 228 | { 229 | *status = LZMA_STATUS_NEEDS_MORE_INPUT; 230 | return SZ_OK; 231 | } 232 | 233 | if (p->state == LZMA2_STATE_DATA) 234 | { 235 | BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); 236 | LzmaDec_InitDicAndState(&p->decoder, initDic, False); 237 | } 238 | 239 | if (inCur > outCur) 240 | inCur = outCur; 241 | if (inCur == 0) 242 | break; 243 | 244 | LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur); 245 | 246 | src += inCur; 247 | *srcLen += inCur; 248 | p->unpackSize -= (UInt32)inCur; 249 | p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; 250 | } 251 | else 252 | { 253 | SRes res; 254 | 255 | if (p->state == LZMA2_STATE_DATA) 256 | { 257 | BoolInt initDic = (p->control >= 0xE0); 258 | BoolInt initState = (p->control >= 0xA0); 259 | LzmaDec_InitDicAndState(&p->decoder, initDic, initState); 260 | p->state = LZMA2_STATE_DATA_CONT; 261 | } 262 | 263 | if (inCur > p->packSize) 264 | inCur = (SizeT)p->packSize; 265 | 266 | res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status); 267 | 268 | src += inCur; 269 | *srcLen += inCur; 270 | p->packSize -= (UInt32)inCur; 271 | outCur = p->decoder.dicPos - dicPos; 272 | p->unpackSize -= (UInt32)outCur; 273 | 274 | if (res != 0) 275 | break; 276 | 277 | if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) 278 | { 279 | if (p->packSize == 0) 280 | break; 281 | return SZ_OK; 282 | } 283 | 284 | if (inCur == 0 && outCur == 0) 285 | { 286 | if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK 287 | || p->unpackSize != 0 288 | || p->packSize != 0) 289 | break; 290 | p->state = LZMA2_STATE_CONTROL; 291 | } 292 | 293 | *status = LZMA_STATUS_NOT_SPECIFIED; 294 | } 295 | } 296 | } 297 | 298 | *status = LZMA_STATUS_NOT_SPECIFIED; 299 | p->state = LZMA2_STATE_ERROR; 300 | return SZ_ERROR_DATA; 301 | } 302 | 303 | 304 | 305 | 306 | ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p, 307 | SizeT outSize, 308 | const Byte *src, SizeT *srcLen, 309 | int checkFinishBlock) 310 | { 311 | SizeT inSize = *srcLen; 312 | *srcLen = 0; 313 | 314 | while (p->state != LZMA2_STATE_ERROR) 315 | { 316 | if (p->state == LZMA2_STATE_FINISHED) 317 | return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK; 318 | 319 | if (outSize == 0 && !checkFinishBlock) 320 | return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED; 321 | 322 | if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) 323 | { 324 | if (*srcLen == inSize) 325 | return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT; 326 | (*srcLen)++; 327 | 328 | p->state = Lzma2Dec_UpdateState(p, *src++); 329 | 330 | if (p->state == LZMA2_STATE_UNPACK0) 331 | { 332 | // if (p->decoder.dicPos != 0) 333 | if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0) 334 | return LZMA2_PARSE_STATUS_NEW_BLOCK; 335 | // if (outSize == 0) return LZMA_STATUS_NOT_FINISHED; 336 | } 337 | 338 | // The following code can be commented. 339 | // It's not big problem, if we read additional input bytes. 340 | // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state. 341 | 342 | if (outSize == 0 && p->state != LZMA2_STATE_FINISHED) 343 | { 344 | // checkFinishBlock is true. So we expect that block must be finished, 345 | // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here 346 | // break; 347 | return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED; 348 | } 349 | 350 | if (p->state == LZMA2_STATE_DATA) 351 | return LZMA2_PARSE_STATUS_NEW_CHUNK; 352 | 353 | continue; 354 | } 355 | 356 | if (outSize == 0) 357 | return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED; 358 | 359 | { 360 | SizeT inCur = inSize - *srcLen; 361 | 362 | if (LZMA2_IS_UNCOMPRESSED_STATE(p)) 363 | { 364 | if (inCur == 0) 365 | return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT; 366 | if (inCur > p->unpackSize) 367 | inCur = p->unpackSize; 368 | if (inCur > outSize) 369 | inCur = outSize; 370 | p->decoder.dicPos += inCur; 371 | src += inCur; 372 | *srcLen += inCur; 373 | outSize -= inCur; 374 | p->unpackSize -= (UInt32)inCur; 375 | p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; 376 | } 377 | else 378 | { 379 | p->isExtraMode = True; 380 | 381 | if (inCur == 0) 382 | { 383 | if (p->packSize != 0) 384 | return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT; 385 | } 386 | else if (p->state == LZMA2_STATE_DATA) 387 | { 388 | p->state = LZMA2_STATE_DATA_CONT; 389 | if (*src != 0) 390 | { 391 | // first byte of lzma chunk must be Zero 392 | *srcLen += 1; 393 | p->packSize--; 394 | break; 395 | } 396 | } 397 | 398 | if (inCur > p->packSize) 399 | inCur = (SizeT)p->packSize; 400 | 401 | src += inCur; 402 | *srcLen += inCur; 403 | p->packSize -= (UInt32)inCur; 404 | 405 | if (p->packSize == 0) 406 | { 407 | SizeT rem = outSize; 408 | if (rem > p->unpackSize) 409 | rem = p->unpackSize; 410 | p->decoder.dicPos += rem; 411 | p->unpackSize -= (UInt32)rem; 412 | outSize -= rem; 413 | if (p->unpackSize == 0) 414 | p->state = LZMA2_STATE_CONTROL; 415 | } 416 | } 417 | } 418 | } 419 | 420 | p->state = LZMA2_STATE_ERROR; 421 | return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED; 422 | } 423 | 424 | 425 | 426 | 427 | SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) 428 | { 429 | SizeT outSize = *destLen, inSize = *srcLen; 430 | *srcLen = *destLen = 0; 431 | 432 | for (;;) 433 | { 434 | SizeT inCur = inSize, outCur, dicPos; 435 | ELzmaFinishMode curFinishMode; 436 | SRes res; 437 | 438 | if (p->decoder.dicPos == p->decoder.dicBufSize) 439 | p->decoder.dicPos = 0; 440 | dicPos = p->decoder.dicPos; 441 | curFinishMode = LZMA_FINISH_ANY; 442 | outCur = p->decoder.dicBufSize - dicPos; 443 | 444 | if (outCur >= outSize) 445 | { 446 | outCur = outSize; 447 | curFinishMode = finishMode; 448 | } 449 | 450 | res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status); 451 | 452 | src += inCur; 453 | inSize -= inCur; 454 | *srcLen += inCur; 455 | outCur = p->decoder.dicPos - dicPos; 456 | memcpy(dest, p->decoder.dic + dicPos, outCur); 457 | dest += outCur; 458 | outSize -= outCur; 459 | *destLen += outCur; 460 | if (res != 0) 461 | return res; 462 | if (outCur == 0 || outSize == 0) 463 | return SZ_OK; 464 | } 465 | } 466 | 467 | 468 | SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, 469 | Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc) 470 | { 471 | CLzma2Dec p; 472 | SRes res; 473 | SizeT outSize = *destLen, inSize = *srcLen; 474 | *destLen = *srcLen = 0; 475 | *status = LZMA_STATUS_NOT_SPECIFIED; 476 | Lzma2Dec_Construct(&p); 477 | RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)); 478 | p.decoder.dic = dest; 479 | p.decoder.dicBufSize = outSize; 480 | Lzma2Dec_Init(&p); 481 | *srcLen = inSize; 482 | res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); 483 | *destLen = p.decoder.dicPos; 484 | if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) 485 | res = SZ_ERROR_INPUT_EOF; 486 | Lzma2Dec_FreeProbs(&p, alloc); 487 | return res; 488 | } 489 | -------------------------------------------------------------------------------- /source/7zDec.c: -------------------------------------------------------------------------------- 1 | /* 7zDec.c -- Decoding from 7z folder 2 | 2019-02-02 : Igor Pavlov : Public domain */ 3 | 4 | #include "Precomp.h" 5 | 6 | #include 7 | 8 | #define _7ZIP_PPMD_SUPPPORT 9 | 10 | #include "7z.h" 11 | #include "7zCrc.h" 12 | 13 | #include "Bcj2.h" 14 | #include "Bra.h" 15 | #include "CpuArch.h" 16 | #include "Delta.h" 17 | #include "LzmaDec.h" 18 | #include "Lzma2Dec.h" 19 | #ifdef _7ZIP_PPMD_SUPPPORT 20 | #include "Ppmd7.h" 21 | #endif 22 | 23 | #define k_Copy 0 24 | #define k_Delta 3 25 | #define k_LZMA2 0x21 26 | #define k_LZMA 0x30101 27 | #define k_BCJ 0x3030103 28 | #define k_BCJ2 0x303011B 29 | #define k_PPC 0x3030205 30 | #define k_IA64 0x3030401 31 | #define k_ARM 0x3030501 32 | #define k_ARMT 0x3030701 33 | #define k_SPARC 0x3030805 34 | 35 | 36 | #ifdef _7ZIP_PPMD_SUPPPORT 37 | 38 | #define k_PPMD 0x30401 39 | 40 | typedef struct 41 | { 42 | IByteIn vt; 43 | const Byte *cur; 44 | const Byte *end; 45 | const Byte *begin; 46 | UInt64 processed; 47 | BoolInt extra; 48 | SRes res; 49 | const ILookInStream *inStream; 50 | } CByteInToLook; 51 | 52 | static Byte ReadByte(const IByteIn *pp) 53 | { 54 | CByteInToLook *p = CONTAINER_FROM_VTBL(pp, CByteInToLook, vt); 55 | if (p->cur != p->end) 56 | return *p->cur++; 57 | if (p->res == SZ_OK) 58 | { 59 | size_t size = p->cur - p->begin; 60 | p->processed += size; 61 | p->res = ILookInStream_Skip(p->inStream, size); 62 | size = (1 << 25); 63 | p->res = ILookInStream_Look(p->inStream, (const void **)&p->begin, &size); 64 | p->cur = p->begin; 65 | p->end = p->begin + size; 66 | if (size != 0) 67 | return *p->cur++;; 68 | } 69 | p->extra = True; 70 | return 0; 71 | } 72 | 73 | static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, const ILookInStream *inStream, 74 | Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) 75 | { 76 | CPpmd7 ppmd; 77 | CByteInToLook s; 78 | SRes res = SZ_OK; 79 | 80 | s.vt.Read = ReadByte; 81 | s.inStream = inStream; 82 | s.begin = s.end = s.cur = NULL; 83 | s.extra = False; 84 | s.res = SZ_OK; 85 | s.processed = 0; 86 | 87 | if (propsSize != 5) 88 | return SZ_ERROR_UNSUPPORTED; 89 | 90 | { 91 | unsigned order = props[0]; 92 | UInt32 memSize = GetUi32(props + 1); 93 | if (order < PPMD7_MIN_ORDER || 94 | order > PPMD7_MAX_ORDER || 95 | memSize < PPMD7_MIN_MEM_SIZE || 96 | memSize > PPMD7_MAX_MEM_SIZE) 97 | return SZ_ERROR_UNSUPPORTED; 98 | Ppmd7_Construct(&ppmd); 99 | if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) 100 | return SZ_ERROR_MEM; 101 | Ppmd7_Init(&ppmd, order); 102 | } 103 | { 104 | CPpmd7z_RangeDec rc; 105 | Ppmd7z_RangeDec_CreateVTable(&rc); 106 | rc.Stream = &s.vt; 107 | if (!Ppmd7z_RangeDec_Init(&rc)) 108 | res = SZ_ERROR_DATA; 109 | else if (s.extra) 110 | res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); 111 | else 112 | { 113 | SizeT i; 114 | for (i = 0; i < outSize; i++) 115 | { 116 | int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.vt); 117 | if (s.extra || sym < 0) 118 | break; 119 | outBuffer[i] = (Byte)sym; 120 | } 121 | if (i != outSize) 122 | res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); 123 | else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) 124 | res = SZ_ERROR_DATA; 125 | } 126 | } 127 | Ppmd7_Free(&ppmd, allocMain); 128 | return res; 129 | } 130 | 131 | #endif 132 | 133 | 134 | static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, 135 | Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) 136 | { 137 | CLzmaDec state; 138 | SRes res = SZ_OK; 139 | 140 | LzmaDec_Construct(&state); 141 | RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain)); 142 | state.dic = outBuffer; 143 | state.dicBufSize = outSize; 144 | LzmaDec_Init(&state); 145 | 146 | for (;;) 147 | { 148 | const void *inBuf = NULL; 149 | size_t lookahead = (1 << 18); 150 | if (lookahead > inSize) 151 | lookahead = (size_t)inSize; 152 | res = ILookInStream_Look(inStream, &inBuf, &lookahead); 153 | if (res != SZ_OK) 154 | break; 155 | 156 | { 157 | SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; 158 | ELzmaStatus status; 159 | res = LzmaDec_DecodeToDic(&state, outSize, (const Byte *)inBuf, &inProcessed, LZMA_FINISH_END, &status); 160 | lookahead -= inProcessed; 161 | inSize -= inProcessed; 162 | if (res != SZ_OK) 163 | break; 164 | 165 | if (status == LZMA_STATUS_FINISHED_WITH_MARK) 166 | { 167 | if (outSize != state.dicPos || inSize != 0) 168 | res = SZ_ERROR_DATA; 169 | break; 170 | } 171 | 172 | if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) 173 | break; 174 | 175 | if (inProcessed == 0 && dicPos == state.dicPos) 176 | { 177 | res = SZ_ERROR_DATA; 178 | break; 179 | } 180 | 181 | res = ILookInStream_Skip(inStream, inProcessed); 182 | if (res != SZ_OK) 183 | break; 184 | } 185 | } 186 | 187 | LzmaDec_FreeProbs(&state, allocMain); 188 | return res; 189 | } 190 | 191 | 192 | #ifndef _7Z_NO_METHOD_LZMA2 193 | 194 | static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, 195 | Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) 196 | { 197 | CLzma2Dec state; 198 | SRes res = SZ_OK; 199 | 200 | Lzma2Dec_Construct(&state); 201 | if (propsSize != 1) 202 | return SZ_ERROR_DATA; 203 | RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain)); 204 | state.decoder.dic = outBuffer; 205 | state.decoder.dicBufSize = outSize; 206 | Lzma2Dec_Init(&state); 207 | 208 | for (;;) 209 | { 210 | const void *inBuf = NULL; 211 | size_t lookahead = (1 << 18); 212 | if (lookahead > inSize) 213 | lookahead = (size_t)inSize; 214 | res = ILookInStream_Look(inStream, &inBuf, &lookahead); 215 | if (res != SZ_OK) 216 | break; 217 | 218 | { 219 | SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; 220 | ELzmaStatus status; 221 | res = Lzma2Dec_DecodeToDic(&state, outSize, (const Byte *)inBuf, &inProcessed, LZMA_FINISH_END, &status); 222 | lookahead -= inProcessed; 223 | inSize -= inProcessed; 224 | if (res != SZ_OK) 225 | break; 226 | 227 | if (status == LZMA_STATUS_FINISHED_WITH_MARK) 228 | { 229 | if (outSize != state.decoder.dicPos || inSize != 0) 230 | res = SZ_ERROR_DATA; 231 | break; 232 | } 233 | 234 | if (inProcessed == 0 && dicPos == state.decoder.dicPos) 235 | { 236 | res = SZ_ERROR_DATA; 237 | break; 238 | } 239 | 240 | res = ILookInStream_Skip(inStream, inProcessed); 241 | if (res != SZ_OK) 242 | break; 243 | } 244 | } 245 | 246 | Lzma2Dec_FreeProbs(&state, allocMain); 247 | return res; 248 | } 249 | 250 | #endif 251 | 252 | 253 | static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) 254 | { 255 | while (inSize > 0) 256 | { 257 | const void *inBuf; 258 | size_t curSize = (1 << 18); 259 | if (curSize > inSize) 260 | curSize = (size_t)inSize; 261 | RINOK(ILookInStream_Look(inStream, &inBuf, &curSize)); 262 | if (curSize == 0) 263 | return SZ_ERROR_INPUT_EOF; 264 | memcpy(outBuffer, inBuf, curSize); 265 | outBuffer += curSize; 266 | inSize -= curSize; 267 | RINOK(ILookInStream_Skip(inStream, curSize)); 268 | } 269 | return SZ_OK; 270 | } 271 | 272 | static BoolInt IS_MAIN_METHOD(UInt32 m) 273 | { 274 | switch (m) 275 | { 276 | case k_Copy: 277 | case k_LZMA: 278 | #ifndef _7Z_NO_METHOD_LZMA2 279 | case k_LZMA2: 280 | #endif 281 | #ifdef _7ZIP_PPMD_SUPPPORT 282 | case k_PPMD: 283 | #endif 284 | return True; 285 | } 286 | return False; 287 | } 288 | 289 | static BoolInt IS_SUPPORTED_CODER(const CSzCoderInfo *c) 290 | { 291 | return 292 | c->NumStreams == 1 293 | /* && c->MethodID <= (UInt32)0xFFFFFFFF */ 294 | && IS_MAIN_METHOD((UInt32)c->MethodID); 295 | } 296 | 297 | #define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4) 298 | 299 | static SRes CheckSupportedFolder(const CSzFolder *f) 300 | { 301 | if (f->NumCoders < 1 || f->NumCoders > 4) 302 | return SZ_ERROR_UNSUPPORTED; 303 | if (!IS_SUPPORTED_CODER(&f->Coders[0])) 304 | return SZ_ERROR_UNSUPPORTED; 305 | if (f->NumCoders == 1) 306 | { 307 | if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0) 308 | return SZ_ERROR_UNSUPPORTED; 309 | return SZ_OK; 310 | } 311 | 312 | 313 | #ifndef _7Z_NO_METHODS_FILTERS 314 | 315 | if (f->NumCoders == 2) 316 | { 317 | const CSzCoderInfo *c = &f->Coders[1]; 318 | if ( 319 | /* c->MethodID > (UInt32)0xFFFFFFFF || */ 320 | c->NumStreams != 1 321 | || f->NumPackStreams != 1 322 | || f->PackStreams[0] != 0 323 | || f->NumBonds != 1 324 | || f->Bonds[0].InIndex != 1 325 | || f->Bonds[0].OutIndex != 0) 326 | return SZ_ERROR_UNSUPPORTED; 327 | switch ((UInt32)c->MethodID) 328 | { 329 | case k_Delta: 330 | case k_BCJ: 331 | case k_PPC: 332 | case k_IA64: 333 | case k_SPARC: 334 | case k_ARM: 335 | case k_ARMT: 336 | break; 337 | default: 338 | return SZ_ERROR_UNSUPPORTED; 339 | } 340 | return SZ_OK; 341 | } 342 | 343 | #endif 344 | 345 | 346 | if (f->NumCoders == 4) 347 | { 348 | if (!IS_SUPPORTED_CODER(&f->Coders[1]) 349 | || !IS_SUPPORTED_CODER(&f->Coders[2]) 350 | || !IS_BCJ2(&f->Coders[3])) 351 | return SZ_ERROR_UNSUPPORTED; 352 | if (f->NumPackStreams != 4 353 | || f->PackStreams[0] != 2 354 | || f->PackStreams[1] != 6 355 | || f->PackStreams[2] != 1 356 | || f->PackStreams[3] != 0 357 | || f->NumBonds != 3 358 | || f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0 359 | || f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1 360 | || f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2) 361 | return SZ_ERROR_UNSUPPORTED; 362 | return SZ_OK; 363 | } 364 | 365 | return SZ_ERROR_UNSUPPORTED; 366 | } 367 | 368 | #define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; 369 | 370 | static SRes SzFolder_Decode2(const CSzFolder *folder, 371 | const Byte *propsData, 372 | const UInt64 *unpackSizes, 373 | const UInt64 *packPositions, 374 | ILookInStream *inStream, UInt64 startPos, 375 | Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain, 376 | Byte *tempBuf[]) 377 | { 378 | UInt32 ci; 379 | SizeT tempSizes[3] = { 0, 0, 0}; 380 | SizeT tempSize3 = 0; 381 | Byte *tempBuf3 = 0; 382 | 383 | RINOK(CheckSupportedFolder(folder)); 384 | 385 | for (ci = 0; ci < folder->NumCoders; ci++) 386 | { 387 | const CSzCoderInfo *coder = &folder->Coders[ci]; 388 | 389 | if (IS_MAIN_METHOD((UInt32)coder->MethodID)) 390 | { 391 | UInt32 si = 0; 392 | UInt64 offset; 393 | UInt64 inSize; 394 | Byte *outBufCur = outBuffer; 395 | SizeT outSizeCur = outSize; 396 | if (folder->NumCoders == 4) 397 | { 398 | UInt32 indices[] = { 3, 2, 0 }; 399 | UInt64 unpackSize = unpackSizes[ci]; 400 | si = indices[ci]; 401 | if (ci < 2) 402 | { 403 | Byte *temp; 404 | outSizeCur = (SizeT)unpackSize; 405 | if (outSizeCur != unpackSize) 406 | return SZ_ERROR_MEM; 407 | temp = (Byte *)ISzAlloc_Alloc(allocMain, outSizeCur); 408 | if (!temp && outSizeCur != 0) 409 | return SZ_ERROR_MEM; 410 | outBufCur = tempBuf[1 - ci] = temp; 411 | tempSizes[1 - ci] = outSizeCur; 412 | } 413 | else if (ci == 2) 414 | { 415 | if (unpackSize > outSize) /* check it */ 416 | return SZ_ERROR_PARAM; 417 | tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); 418 | tempSize3 = outSizeCur = (SizeT)unpackSize; 419 | } 420 | else 421 | return SZ_ERROR_UNSUPPORTED; 422 | } 423 | offset = packPositions[si]; 424 | inSize = packPositions[(size_t)si + 1] - offset; 425 | RINOK(LookInStream_SeekTo(inStream, startPos + offset)); 426 | 427 | if (coder->MethodID == k_Copy) 428 | { 429 | if (inSize != outSizeCur) /* check it */ 430 | return SZ_ERROR_DATA; 431 | RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); 432 | } 433 | else if (coder->MethodID == k_LZMA) 434 | { 435 | RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); 436 | } 437 | #ifndef _7Z_NO_METHOD_LZMA2 438 | else if (coder->MethodID == k_LZMA2) 439 | { 440 | RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); 441 | } 442 | #endif 443 | #ifdef _7ZIP_PPMD_SUPPPORT 444 | else if (coder->MethodID == k_PPMD) 445 | { 446 | RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); 447 | } 448 | #endif 449 | else 450 | return SZ_ERROR_UNSUPPORTED; 451 | } 452 | else if (coder->MethodID == k_BCJ2) 453 | { 454 | UInt64 offset = packPositions[1]; 455 | UInt64 s3Size = packPositions[2] - offset; 456 | 457 | if (ci != 3) 458 | return SZ_ERROR_UNSUPPORTED; 459 | 460 | tempSizes[2] = (SizeT)s3Size; 461 | if (tempSizes[2] != s3Size) 462 | return SZ_ERROR_MEM; 463 | tempBuf[2] = (Byte *)ISzAlloc_Alloc(allocMain, tempSizes[2]); 464 | if (!tempBuf[2] && tempSizes[2] != 0) 465 | return SZ_ERROR_MEM; 466 | 467 | RINOK(LookInStream_SeekTo(inStream, startPos + offset)); 468 | RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2])); 469 | 470 | if ((tempSizes[0] & 3) != 0 || 471 | (tempSizes[1] & 3) != 0 || 472 | tempSize3 + tempSizes[0] + tempSizes[1] != outSize) 473 | return SZ_ERROR_DATA; 474 | 475 | { 476 | CBcj2Dec p; 477 | 478 | p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3; 479 | p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0]; 480 | p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1]; 481 | p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2]; 482 | 483 | p.dest = outBuffer; 484 | p.destLim = outBuffer + outSize; 485 | 486 | Bcj2Dec_Init(&p); 487 | RINOK(Bcj2Dec_Decode(&p)); 488 | 489 | { 490 | unsigned i; 491 | for (i = 0; i < 4; i++) 492 | if (p.bufs[i] != p.lims[i]) 493 | return SZ_ERROR_DATA; 494 | 495 | if (!Bcj2Dec_IsFinished(&p)) 496 | return SZ_ERROR_DATA; 497 | 498 | if (p.dest != p.destLim 499 | || p.state != BCJ2_STREAM_MAIN) 500 | return SZ_ERROR_DATA; 501 | } 502 | } 503 | } 504 | #ifndef _7Z_NO_METHODS_FILTERS 505 | else if (ci == 1) 506 | { 507 | if (coder->MethodID == k_Delta) 508 | { 509 | if (coder->PropsSize != 1) 510 | return SZ_ERROR_UNSUPPORTED; 511 | { 512 | Byte state[DELTA_STATE_SIZE]; 513 | Delta_Init(state); 514 | Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize); 515 | } 516 | } 517 | else 518 | { 519 | if (coder->PropsSize != 0) 520 | return SZ_ERROR_UNSUPPORTED; 521 | switch (coder->MethodID) 522 | { 523 | case k_BCJ: 524 | { 525 | UInt32 state; 526 | x86_Convert_Init(state); 527 | x86_Convert(outBuffer, outSize, 0, &state, 0); 528 | break; 529 | } 530 | CASE_BRA_CONV(PPC) 531 | CASE_BRA_CONV(IA64) 532 | CASE_BRA_CONV(SPARC) 533 | CASE_BRA_CONV(ARM) 534 | CASE_BRA_CONV(ARMT) 535 | default: 536 | return SZ_ERROR_UNSUPPORTED; 537 | } 538 | } 539 | } 540 | #endif 541 | else 542 | return SZ_ERROR_UNSUPPORTED; 543 | } 544 | 545 | return SZ_OK; 546 | } 547 | 548 | 549 | SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, 550 | ILookInStream *inStream, UInt64 startPos, 551 | Byte *outBuffer, size_t outSize, 552 | ISzAllocPtr allocMain) 553 | { 554 | SRes res; 555 | CSzFolder folder; 556 | CSzData sd; 557 | 558 | const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex]; 559 | sd.Data = data; 560 | sd.Size = p->FoCodersOffsets[(size_t)folderIndex + 1] - p->FoCodersOffsets[folderIndex]; 561 | 562 | res = SzGetNextFolderItem(&folder, &sd); 563 | 564 | if (res != SZ_OK) 565 | return res; 566 | 567 | if (sd.Size != 0 568 | || folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex] 569 | || outSize != SzAr_GetFolderUnpackSize(p, folderIndex)) 570 | return SZ_ERROR_FAIL; 571 | { 572 | unsigned i; 573 | Byte *tempBuf[3] = { 0, 0, 0}; 574 | 575 | res = SzFolder_Decode2(&folder, data, 576 | &p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]], 577 | p->PackPositions + p->FoStartPackStreamIndex[folderIndex], 578 | inStream, startPos, 579 | outBuffer, (SizeT)outSize, allocMain, tempBuf); 580 | 581 | for (i = 0; i < 3; i++) 582 | ISzAlloc_Free(allocMain, tempBuf[i]); 583 | 584 | if (res == SZ_OK) 585 | if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex)) 586 | if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex]) 587 | res = SZ_ERROR_CRC; 588 | 589 | return res; 590 | } 591 | } 592 | -------------------------------------------------------------------------------- /source/Ppmd7.c: -------------------------------------------------------------------------------- 1 | /* Ppmd7.c -- PPMdH codec 2 | 2018-07-04 : Igor Pavlov : Public domain 3 | This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ 4 | 5 | #include "Precomp.h" 6 | 7 | #include 8 | 9 | #include "Ppmd7.h" 10 | 11 | const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; 12 | static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; 13 | 14 | #define MAX_FREQ 124 15 | #define UNIT_SIZE 12 16 | 17 | #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE) 18 | #define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1]) 19 | #define I2U(indx) (p->Indx2Units[indx]) 20 | 21 | #ifdef PPMD_32BIT 22 | #define REF(ptr) (ptr) 23 | #else 24 | #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base)) 25 | #endif 26 | 27 | #define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr)) 28 | 29 | #define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) 30 | #define STATS(ctx) Ppmd7_GetStats(p, ctx) 31 | #define ONE_STATE(ctx) Ppmd7Context_OneState(ctx) 32 | #define SUFFIX(ctx) CTX((ctx)->Suffix) 33 | 34 | typedef CPpmd7_Context * CTX_PTR; 35 | 36 | struct CPpmd7_Node_; 37 | 38 | typedef 39 | #ifdef PPMD_32BIT 40 | struct CPpmd7_Node_ * 41 | #else 42 | UInt32 43 | #endif 44 | CPpmd7_Node_Ref; 45 | 46 | typedef struct CPpmd7_Node_ 47 | { 48 | UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */ 49 | UInt16 NU; 50 | CPpmd7_Node_Ref Next; /* must be at offset >= 4 */ 51 | CPpmd7_Node_Ref Prev; 52 | } CPpmd7_Node; 53 | 54 | #ifdef PPMD_32BIT 55 | #define NODE(ptr) (ptr) 56 | #else 57 | #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs))) 58 | #endif 59 | 60 | void Ppmd7_Construct(CPpmd7 *p) 61 | { 62 | unsigned i, k, m; 63 | 64 | p->Base = 0; 65 | 66 | for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) 67 | { 68 | unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); 69 | do { p->Units2Indx[k++] = (Byte)i; } while (--step); 70 | p->Indx2Units[i] = (Byte)k; 71 | } 72 | 73 | p->NS2BSIndx[0] = (0 << 1); 74 | p->NS2BSIndx[1] = (1 << 1); 75 | memset(p->NS2BSIndx + 2, (2 << 1), 9); 76 | memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11); 77 | 78 | for (i = 0; i < 3; i++) 79 | p->NS2Indx[i] = (Byte)i; 80 | for (m = i, k = 1; i < 256; i++) 81 | { 82 | p->NS2Indx[i] = (Byte)m; 83 | if (--k == 0) 84 | k = (++m) - 2; 85 | } 86 | 87 | memset(p->HB2Flag, 0, 0x40); 88 | memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40); 89 | } 90 | 91 | void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc) 92 | { 93 | ISzAlloc_Free(alloc, p->Base); 94 | p->Size = 0; 95 | p->Base = 0; 96 | } 97 | 98 | BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc) 99 | { 100 | if (!p->Base || p->Size != size) 101 | { 102 | size_t size2; 103 | Ppmd7_Free(p, alloc); 104 | size2 = 0 105 | #ifndef PPMD_32BIT 106 | + UNIT_SIZE 107 | #endif 108 | ; 109 | p->AlignOffset = 110 | #ifdef PPMD_32BIT 111 | (4 - size) & 3; 112 | #else 113 | 4 - (size & 3); 114 | #endif 115 | if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size + size2)) == 0) 116 | return False; 117 | p->Size = size; 118 | } 119 | return True; 120 | } 121 | 122 | static void InsertNode(CPpmd7 *p, void *node, unsigned indx) 123 | { 124 | *((CPpmd_Void_Ref *)node) = p->FreeList[indx]; 125 | p->FreeList[indx] = REF(node); 126 | } 127 | 128 | static void *RemoveNode(CPpmd7 *p, unsigned indx) 129 | { 130 | CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]); 131 | p->FreeList[indx] = *node; 132 | return node; 133 | } 134 | 135 | static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) 136 | { 137 | unsigned i, nu = I2U(oldIndx) - I2U(newIndx); 138 | ptr = (Byte *)ptr + U2B(I2U(newIndx)); 139 | if (I2U(i = U2I(nu)) != nu) 140 | { 141 | unsigned k = I2U(--i); 142 | InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1); 143 | } 144 | InsertNode(p, ptr, i); 145 | } 146 | 147 | static void GlueFreeBlocks(CPpmd7 *p) 148 | { 149 | #ifdef PPMD_32BIT 150 | CPpmd7_Node headItem; 151 | CPpmd7_Node_Ref head = &headItem; 152 | #else 153 | CPpmd7_Node_Ref head = p->AlignOffset + p->Size; 154 | #endif 155 | 156 | CPpmd7_Node_Ref n = head; 157 | unsigned i; 158 | 159 | p->GlueCount = 255; 160 | 161 | /* create doubly-linked list of free blocks */ 162 | for (i = 0; i < PPMD_NUM_INDEXES; i++) 163 | { 164 | UInt16 nu = I2U(i); 165 | CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i]; 166 | p->FreeList[i] = 0; 167 | while (next != 0) 168 | { 169 | CPpmd7_Node *node = NODE(next); 170 | node->Next = n; 171 | n = NODE(n)->Prev = next; 172 | next = *(const CPpmd7_Node_Ref *)node; 173 | node->Stamp = 0; 174 | node->NU = (UInt16)nu; 175 | } 176 | } 177 | NODE(head)->Stamp = 1; 178 | NODE(head)->Next = n; 179 | NODE(n)->Prev = head; 180 | if (p->LoUnit != p->HiUnit) 181 | ((CPpmd7_Node *)p->LoUnit)->Stamp = 1; 182 | 183 | /* Glue free blocks */ 184 | while (n != head) 185 | { 186 | CPpmd7_Node *node = NODE(n); 187 | UInt32 nu = (UInt32)node->NU; 188 | for (;;) 189 | { 190 | CPpmd7_Node *node2 = NODE(n) + nu; 191 | nu += node2->NU; 192 | if (node2->Stamp != 0 || nu >= 0x10000) 193 | break; 194 | NODE(node2->Prev)->Next = node2->Next; 195 | NODE(node2->Next)->Prev = node2->Prev; 196 | node->NU = (UInt16)nu; 197 | } 198 | n = node->Next; 199 | } 200 | 201 | /* Fill lists of free blocks */ 202 | for (n = NODE(head)->Next; n != head;) 203 | { 204 | CPpmd7_Node *node = NODE(n); 205 | unsigned nu; 206 | CPpmd7_Node_Ref next = node->Next; 207 | for (nu = node->NU; nu > 128; nu -= 128, node += 128) 208 | InsertNode(p, node, PPMD_NUM_INDEXES - 1); 209 | if (I2U(i = U2I(nu)) != nu) 210 | { 211 | unsigned k = I2U(--i); 212 | InsertNode(p, node + k, nu - k - 1); 213 | } 214 | InsertNode(p, node, i); 215 | n = next; 216 | } 217 | } 218 | 219 | static void *AllocUnitsRare(CPpmd7 *p, unsigned indx) 220 | { 221 | unsigned i; 222 | void *retVal; 223 | if (p->GlueCount == 0) 224 | { 225 | GlueFreeBlocks(p); 226 | if (p->FreeList[indx] != 0) 227 | return RemoveNode(p, indx); 228 | } 229 | i = indx; 230 | do 231 | { 232 | if (++i == PPMD_NUM_INDEXES) 233 | { 234 | UInt32 numBytes = U2B(I2U(indx)); 235 | p->GlueCount--; 236 | return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL); 237 | } 238 | } 239 | while (p->FreeList[i] == 0); 240 | retVal = RemoveNode(p, i); 241 | SplitBlock(p, retVal, i, indx); 242 | return retVal; 243 | } 244 | 245 | static void *AllocUnits(CPpmd7 *p, unsigned indx) 246 | { 247 | UInt32 numBytes; 248 | if (p->FreeList[indx] != 0) 249 | return RemoveNode(p, indx); 250 | numBytes = U2B(I2U(indx)); 251 | if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit)) 252 | { 253 | void *retVal = p->LoUnit; 254 | p->LoUnit += numBytes; 255 | return retVal; 256 | } 257 | return AllocUnitsRare(p, indx); 258 | } 259 | 260 | #define MyMem12Cpy(dest, src, num) \ 261 | { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \ 262 | do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while (--n); } 263 | 264 | static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU) 265 | { 266 | unsigned i0 = U2I(oldNU); 267 | unsigned i1 = U2I(newNU); 268 | if (i0 == i1) 269 | return oldPtr; 270 | if (p->FreeList[i1] != 0) 271 | { 272 | void *ptr = RemoveNode(p, i1); 273 | MyMem12Cpy(ptr, oldPtr, newNU); 274 | InsertNode(p, oldPtr, i0); 275 | return ptr; 276 | } 277 | SplitBlock(p, oldPtr, i0, i1); 278 | return oldPtr; 279 | } 280 | 281 | #define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16))) 282 | 283 | static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) 284 | { 285 | (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF); 286 | (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF); 287 | } 288 | 289 | static void RestartModel(CPpmd7 *p) 290 | { 291 | unsigned i, k, m; 292 | 293 | memset(p->FreeList, 0, sizeof(p->FreeList)); 294 | p->Text = p->Base + p->AlignOffset; 295 | p->HiUnit = p->Text + p->Size; 296 | p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE; 297 | p->GlueCount = 0; 298 | 299 | p->OrderFall = p->MaxOrder; 300 | p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1; 301 | p->PrevSuccess = 0; 302 | 303 | p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ 304 | p->MinContext->Suffix = 0; 305 | p->MinContext->NumStats = 256; 306 | p->MinContext->SummFreq = 256 + 1; 307 | p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */ 308 | p->LoUnit += U2B(256 / 2); 309 | p->MinContext->Stats = REF(p->FoundState); 310 | for (i = 0; i < 256; i++) 311 | { 312 | CPpmd_State *s = &p->FoundState[i]; 313 | s->Symbol = (Byte)i; 314 | s->Freq = 1; 315 | SetSuccessor(s, 0); 316 | } 317 | 318 | for (i = 0; i < 128; i++) 319 | for (k = 0; k < 8; k++) 320 | { 321 | UInt16 *dest = p->BinSumm[i] + k; 322 | UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2)); 323 | for (m = 0; m < 64; m += 8) 324 | dest[m] = val; 325 | } 326 | 327 | for (i = 0; i < 25; i++) 328 | for (k = 0; k < 16; k++) 329 | { 330 | CPpmd_See *s = &p->See[i][k]; 331 | s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4)); 332 | s->Count = 4; 333 | } 334 | } 335 | 336 | void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder) 337 | { 338 | p->MaxOrder = maxOrder; 339 | RestartModel(p); 340 | p->DummySee.Shift = PPMD_PERIOD_BITS; 341 | p->DummySee.Summ = 0; /* unused */ 342 | p->DummySee.Count = 64; /* unused */ 343 | } 344 | 345 | static CTX_PTR CreateSuccessors(CPpmd7 *p, BoolInt skip) 346 | { 347 | CPpmd_State upState; 348 | CTX_PTR c = p->MinContext; 349 | CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); 350 | CPpmd_State *ps[PPMD7_MAX_ORDER]; 351 | unsigned numPs = 0; 352 | 353 | if (!skip) 354 | ps[numPs++] = p->FoundState; 355 | 356 | while (c->Suffix) 357 | { 358 | CPpmd_Void_Ref successor; 359 | CPpmd_State *s; 360 | c = SUFFIX(c); 361 | if (c->NumStats != 1) 362 | { 363 | for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++); 364 | } 365 | else 366 | s = ONE_STATE(c); 367 | successor = SUCCESSOR(s); 368 | if (successor != upBranch) 369 | { 370 | c = CTX(successor); 371 | if (numPs == 0) 372 | return c; 373 | break; 374 | } 375 | ps[numPs++] = s; 376 | } 377 | 378 | upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch); 379 | SetSuccessor(&upState, upBranch + 1); 380 | 381 | if (c->NumStats == 1) 382 | upState.Freq = ONE_STATE(c)->Freq; 383 | else 384 | { 385 | UInt32 cf, s0; 386 | CPpmd_State *s; 387 | for (s = STATS(c); s->Symbol != upState.Symbol; s++); 388 | cf = s->Freq - 1; 389 | s0 = c->SummFreq - c->NumStats - cf; 390 | upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0)))); 391 | } 392 | 393 | do 394 | { 395 | /* Create Child */ 396 | CTX_PTR c1; /* = AllocContext(p); */ 397 | if (p->HiUnit != p->LoUnit) 398 | c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); 399 | else if (p->FreeList[0] != 0) 400 | c1 = (CTX_PTR)RemoveNode(p, 0); 401 | else 402 | { 403 | c1 = (CTX_PTR)AllocUnitsRare(p, 0); 404 | if (!c1) 405 | return NULL; 406 | } 407 | c1->NumStats = 1; 408 | *ONE_STATE(c1) = upState; 409 | c1->Suffix = REF(c); 410 | SetSuccessor(ps[--numPs], REF(c1)); 411 | c = c1; 412 | } 413 | while (numPs != 0); 414 | 415 | return c; 416 | } 417 | 418 | static void SwapStates(CPpmd_State *t1, CPpmd_State *t2) 419 | { 420 | CPpmd_State tmp = *t1; 421 | *t1 = *t2; 422 | *t2 = tmp; 423 | } 424 | 425 | static void UpdateModel(CPpmd7 *p) 426 | { 427 | CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState); 428 | CTX_PTR c; 429 | unsigned s0, ns; 430 | 431 | if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0) 432 | { 433 | c = SUFFIX(p->MinContext); 434 | 435 | if (c->NumStats == 1) 436 | { 437 | CPpmd_State *s = ONE_STATE(c); 438 | if (s->Freq < 32) 439 | s->Freq++; 440 | } 441 | else 442 | { 443 | CPpmd_State *s = STATS(c); 444 | if (s->Symbol != p->FoundState->Symbol) 445 | { 446 | do { s++; } while (s->Symbol != p->FoundState->Symbol); 447 | if (s[0].Freq >= s[-1].Freq) 448 | { 449 | SwapStates(&s[0], &s[-1]); 450 | s--; 451 | } 452 | } 453 | if (s->Freq < MAX_FREQ - 9) 454 | { 455 | s->Freq += 2; 456 | c->SummFreq += 2; 457 | } 458 | } 459 | } 460 | 461 | if (p->OrderFall == 0) 462 | { 463 | p->MinContext = p->MaxContext = CreateSuccessors(p, True); 464 | if (p->MinContext == 0) 465 | { 466 | RestartModel(p); 467 | return; 468 | } 469 | SetSuccessor(p->FoundState, REF(p->MinContext)); 470 | return; 471 | } 472 | 473 | *p->Text++ = p->FoundState->Symbol; 474 | successor = REF(p->Text); 475 | if (p->Text >= p->UnitsStart) 476 | { 477 | RestartModel(p); 478 | return; 479 | } 480 | 481 | if (fSuccessor) 482 | { 483 | if (fSuccessor <= successor) 484 | { 485 | CTX_PTR cs = CreateSuccessors(p, False); 486 | if (cs == NULL) 487 | { 488 | RestartModel(p); 489 | return; 490 | } 491 | fSuccessor = REF(cs); 492 | } 493 | if (--p->OrderFall == 0) 494 | { 495 | successor = fSuccessor; 496 | p->Text -= (p->MaxContext != p->MinContext); 497 | } 498 | } 499 | else 500 | { 501 | SetSuccessor(p->FoundState, successor); 502 | fSuccessor = REF(p->MinContext); 503 | } 504 | 505 | s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1); 506 | 507 | for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c)) 508 | { 509 | unsigned ns1; 510 | UInt32 cf, sf; 511 | if ((ns1 = c->NumStats) != 1) 512 | { 513 | if ((ns1 & 1) == 0) 514 | { 515 | /* Expand for one UNIT */ 516 | unsigned oldNU = ns1 >> 1; 517 | unsigned i = U2I(oldNU); 518 | if (i != U2I((size_t)oldNU + 1)) 519 | { 520 | void *ptr = AllocUnits(p, i + 1); 521 | void *oldPtr; 522 | if (!ptr) 523 | { 524 | RestartModel(p); 525 | return; 526 | } 527 | oldPtr = STATS(c); 528 | MyMem12Cpy(ptr, oldPtr, oldNU); 529 | InsertNode(p, oldPtr, i); 530 | c->Stats = STATS_REF(ptr); 531 | } 532 | } 533 | c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1))); 534 | } 535 | else 536 | { 537 | CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0); 538 | if (!s) 539 | { 540 | RestartModel(p); 541 | return; 542 | } 543 | *s = *ONE_STATE(c); 544 | c->Stats = REF(s); 545 | if (s->Freq < MAX_FREQ / 4 - 1) 546 | s->Freq <<= 1; 547 | else 548 | s->Freq = MAX_FREQ - 4; 549 | c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3)); 550 | } 551 | cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6); 552 | sf = (UInt32)s0 + c->SummFreq; 553 | if (cf < 6 * sf) 554 | { 555 | cf = 1 + (cf > sf) + (cf >= 4 * sf); 556 | c->SummFreq += 3; 557 | } 558 | else 559 | { 560 | cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); 561 | c->SummFreq = (UInt16)(c->SummFreq + cf); 562 | } 563 | { 564 | CPpmd_State *s = STATS(c) + ns1; 565 | SetSuccessor(s, successor); 566 | s->Symbol = p->FoundState->Symbol; 567 | s->Freq = (Byte)cf; 568 | c->NumStats = (UInt16)(ns1 + 1); 569 | } 570 | } 571 | p->MaxContext = p->MinContext = CTX(fSuccessor); 572 | } 573 | 574 | static void Rescale(CPpmd7 *p) 575 | { 576 | unsigned i, adder, sumFreq, escFreq; 577 | CPpmd_State *stats = STATS(p->MinContext); 578 | CPpmd_State *s = p->FoundState; 579 | { 580 | CPpmd_State tmp = *s; 581 | for (; s != stats; s--) 582 | s[0] = s[-1]; 583 | *s = tmp; 584 | } 585 | escFreq = p->MinContext->SummFreq - s->Freq; 586 | s->Freq += 4; 587 | adder = (p->OrderFall != 0); 588 | s->Freq = (Byte)((s->Freq + adder) >> 1); 589 | sumFreq = s->Freq; 590 | 591 | i = p->MinContext->NumStats - 1; 592 | do 593 | { 594 | escFreq -= (++s)->Freq; 595 | s->Freq = (Byte)((s->Freq + adder) >> 1); 596 | sumFreq += s->Freq; 597 | if (s[0].Freq > s[-1].Freq) 598 | { 599 | CPpmd_State *s1 = s; 600 | CPpmd_State tmp = *s1; 601 | do 602 | s1[0] = s1[-1]; 603 | while (--s1 != stats && tmp.Freq > s1[-1].Freq); 604 | *s1 = tmp; 605 | } 606 | } 607 | while (--i); 608 | 609 | if (s->Freq == 0) 610 | { 611 | unsigned numStats = p->MinContext->NumStats; 612 | unsigned n0, n1; 613 | do { i++; } while ((--s)->Freq == 0); 614 | escFreq += i; 615 | p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i); 616 | if (p->MinContext->NumStats == 1) 617 | { 618 | CPpmd_State tmp = *stats; 619 | do 620 | { 621 | tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); 622 | escFreq >>= 1; 623 | } 624 | while (escFreq > 1); 625 | InsertNode(p, stats, U2I(((numStats + 1) >> 1))); 626 | *(p->FoundState = ONE_STATE(p->MinContext)) = tmp; 627 | return; 628 | } 629 | n0 = (numStats + 1) >> 1; 630 | n1 = (p->MinContext->NumStats + 1) >> 1; 631 | if (n0 != n1) 632 | p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); 633 | } 634 | p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); 635 | p->FoundState = STATS(p->MinContext); 636 | } 637 | 638 | CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq) 639 | { 640 | CPpmd_See *see; 641 | unsigned nonMasked = p->MinContext->NumStats - numMasked; 642 | if (p->MinContext->NumStats != 256) 643 | { 644 | see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] + 645 | (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) + 646 | 2 * (unsigned)(p->MinContext->SummFreq < 11 * p->MinContext->NumStats) + 647 | 4 * (unsigned)(numMasked > nonMasked) + 648 | p->HiBitsFlag; 649 | { 650 | unsigned r = (see->Summ >> see->Shift); 651 | see->Summ = (UInt16)(see->Summ - r); 652 | *escFreq = r + (r == 0); 653 | } 654 | } 655 | else 656 | { 657 | see = &p->DummySee; 658 | *escFreq = 1; 659 | } 660 | return see; 661 | } 662 | 663 | static void NextContext(CPpmd7 *p) 664 | { 665 | CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); 666 | if (p->OrderFall == 0 && (Byte *)c > p->Text) 667 | p->MinContext = p->MaxContext = c; 668 | else 669 | UpdateModel(p); 670 | } 671 | 672 | void Ppmd7_Update1(CPpmd7 *p) 673 | { 674 | CPpmd_State *s = p->FoundState; 675 | s->Freq += 4; 676 | p->MinContext->SummFreq += 4; 677 | if (s[0].Freq > s[-1].Freq) 678 | { 679 | SwapStates(&s[0], &s[-1]); 680 | p->FoundState = --s; 681 | if (s->Freq > MAX_FREQ) 682 | Rescale(p); 683 | } 684 | NextContext(p); 685 | } 686 | 687 | void Ppmd7_Update1_0(CPpmd7 *p) 688 | { 689 | p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq); 690 | p->RunLength += p->PrevSuccess; 691 | p->MinContext->SummFreq += 4; 692 | if ((p->FoundState->Freq += 4) > MAX_FREQ) 693 | Rescale(p); 694 | NextContext(p); 695 | } 696 | 697 | void Ppmd7_UpdateBin(CPpmd7 *p) 698 | { 699 | p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0)); 700 | p->PrevSuccess = 1; 701 | p->RunLength++; 702 | NextContext(p); 703 | } 704 | 705 | void Ppmd7_Update2(CPpmd7 *p) 706 | { 707 | p->MinContext->SummFreq += 4; 708 | if ((p->FoundState->Freq += 4) > MAX_FREQ) 709 | Rescale(p); 710 | p->RunLength = p->InitRL; 711 | UpdateModel(p); 712 | } 713 | --------------------------------------------------------------------------------