1/* Bcj2.c -- Converter for x86 code (BCJ2) 22008-10-04 : Igor Pavlov : Public domain */ 3 4#include "Precomp.h" 5 6#include "Bcj2.h" 7 8#ifdef _LZMA_PROB32 9#define CProb UInt32 10#else 11#define CProb UInt16 12#endif 13 14#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) 15#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) 16 17#define kNumTopBits 24 18#define kTopValue ((UInt32)1 << kNumTopBits) 19 20#define kNumBitModelTotalBits 11 21#define kBitModelTotal (1 << kNumBitModelTotalBits) 22#define kNumMoveBits 5 23 24#define RC_READ_BYTE (*buffer++) 25#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } 26#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ 27 { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} 28 29#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } 30 31#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) 32#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; 33#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; 34 35int Bcj2_Decode( 36 const Byte *buf0, SizeT size0, 37 const Byte *buf1, SizeT size1, 38 const Byte *buf2, SizeT size2, 39 const Byte *buf3, SizeT size3, 40 Byte *outBuf, SizeT outSize) 41{ 42 CProb p[256 + 2]; 43 SizeT inPos = 0, outPos = 0; 44 45 const Byte *buffer, *bufferLim; 46 UInt32 range, code; 47 Byte prevByte = 0; 48 49 unsigned int i; 50 for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) 51 p[i] = kBitModelTotal >> 1; 52 53 buffer = buf3; 54 bufferLim = buffer + size3; 55 RC_INIT2 56 57 if (outSize == 0) 58 return SZ_OK; 59 60 for (;;) 61 { 62 Byte b; 63 CProb *prob; 64 UInt32 bound; 65 UInt32 ttt; 66 67 SizeT limit = size0 - inPos; 68 if (outSize - outPos < limit) 69 limit = outSize - outPos; 70 while (limit != 0) 71 { 72 Byte b = buf0[inPos]; 73 outBuf[outPos++] = b; 74 if (IsJ(prevByte, b)) 75 break; 76 inPos++; 77 prevByte = b; 78 limit--; 79 } 80 81 if (limit == 0 || outPos == outSize) 82 break; 83 84 b = buf0[inPos++]; 85 86 if (b == 0xE8) 87 prob = p + prevByte; 88 else if (b == 0xE9) 89 prob = p + 256; 90 else 91 prob = p + 257; 92 93 IF_BIT_0(prob) 94 { 95 UPDATE_0(prob) 96 prevByte = b; 97 } 98 else 99 { 100 UInt32 dest; 101 const Byte *v; 102 UPDATE_1(prob) 103 if (b == 0xE8) 104 { 105 v = buf1; 106 if (size1 < 4) 107 return SZ_ERROR_DATA; 108 buf1 += 4; 109 size1 -= 4; 110 } 111 else 112 { 113 v = buf2; 114 if (size2 < 4) 115 return SZ_ERROR_DATA; 116 buf2 += 4; 117 size2 -= 4; 118 } 119 dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | 120 ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); 121 outBuf[outPos++] = (Byte)dest; 122 if (outPos == outSize) 123 break; 124 outBuf[outPos++] = (Byte)(dest >> 8); 125 if (outPos == outSize) 126 break; 127 outBuf[outPos++] = (Byte)(dest >> 16); 128 if (outPos == outSize) 129 break; 130 outBuf[outPos++] = prevByte = (Byte)(dest >> 24); 131 } 132 } 133 return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; 134} 135