]> git.cworth.org Git - vogl/blob - src/voglcore/lzma_Bcj2.cpp
Initial vogl checkin
[vogl] / src / voglcore / lzma_Bcj2.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 /* Bcj2.c -- Converter for x86 code (BCJ2)
28 2008-10-04 : Igor Pavlov : Public domain */
29 #include "vogl_core.h"
30 #include "lzma_Bcj2.h"
31
32 namespace vogl
33 {
34
35 #ifdef _LZMA_PROB32
36 #define CProb UInt32
37 #else
38 #define CProb UInt16
39 #endif
40
41 #define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
42 #define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
43
44 #define kNumTopBits 24
45 #define kTopValue ((UInt32)1 << kNumTopBits)
46
47 #define kNumBitModelTotalBits 11
48 #define kBitModelTotal (1 << kNumBitModelTotalBits)
49 #define kNumMoveBits 5
50
51 #define RC_READ_BYTE (*buffer++)
52 #define RC_TEST                   \
53     {                             \
54         if (buffer == bufferLim)  \
55             return SZ_ERROR_DATA; \
56     }
57 #define RC_INIT2                               \
58     code = 0;                                  \
59     range = 0xFFFFFFFF;                        \
60     {                                          \
61         int i;                                 \
62         for (i = 0; i < 5; i++)                \
63         {                                      \
64             RC_TEST;                           \
65             code = (code << 8) | RC_READ_BYTE; \
66         }                                      \
67     }
68
69 #define NORMALIZE                          \
70     if (range < kTopValue)                 \
71     {                                      \
72         RC_TEST;                           \
73         range <<= 8;                       \
74         code = (code << 8) | RC_READ_BYTE; \
75     }
76
77 #define IF_BIT_0(p)                                 \
78     ttt = *(p);                                     \
79     bound = (range >> kNumBitModelTotalBits) * ttt; \
80     if (code < bound)
81 #define UPDATE_0(p)                                                 \
82     range = bound;                                                  \
83     *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); \
84     NORMALIZE;
85 #define UPDATE_1(p)                              \
86     range -= bound;                              \
87     code -= bound;                               \
88     *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); \
89     NORMALIZE;
90
91     int Bcj2_Decode(
92         const Byte *buf0, SizeT size0,
93         const Byte *buf1, SizeT size1,
94         const Byte *buf2, SizeT size2,
95         const Byte *buf3, SizeT size3,
96         Byte *outBuf, SizeT outSize)
97     {
98         CProb p[256 + 2];
99         SizeT inPos = 0, outPos = 0;
100
101         const Byte *buffer, *bufferLim;
102         UInt32 range, code;
103         Byte prevByte = 0;
104
105         unsigned int i;
106         for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
107             p[i] = kBitModelTotal >> 1;
108
109         buffer = buf3;
110         bufferLim = buffer + size3;
111         RC_INIT2
112
113         if (outSize == 0)
114             return SZ_OK;
115
116         for (;;)
117         {
118             Byte b;
119             CProb *prob;
120             UInt32 bound;
121             UInt32 ttt;
122
123             SizeT limit = size0 - inPos;
124             if (outSize - outPos < limit)
125                 limit = outSize - outPos;
126             while (limit != 0)
127             {
128                 Byte b = buf0[inPos];
129                 outBuf[outPos++] = b;
130                 if (IsJ(prevByte, b))
131                     break;
132                 inPos++;
133                 prevByte = b;
134                 limit--;
135             }
136
137             if (limit == 0 || outPos == outSize)
138                 break;
139
140             b = buf0[inPos++];
141
142             if (b == 0xE8)
143                 prob = p + prevByte;
144             else if (b == 0xE9)
145                 prob = p + 256;
146             else
147                 prob = p + 257;
148
149             IF_BIT_0(prob)
150             {
151                 UPDATE_0(prob)
152                 prevByte = b;
153             }
154             else
155             {
156                 UInt32 dest;
157                 const Byte *v;
158                 UPDATE_1(prob)
159                 if (b == 0xE8)
160                 {
161                     v = buf1;
162                     if (size1 < 4)
163                         return SZ_ERROR_DATA;
164                     buf1 += 4;
165                     size1 -= 4;
166                 }
167                 else
168                 {
169                     v = buf2;
170                     if (size2 < 4)
171                         return SZ_ERROR_DATA;
172                     buf2 += 4;
173                     size2 -= 4;
174                 }
175                 dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
176                         ((UInt32)v[2] << 8) | ((UInt32)v[3])) -
177                        ((UInt32)outPos + 4);
178                 outBuf[outPos++] = (Byte)dest;
179                 if (outPos == outSize)
180                     break;
181                 outBuf[outPos++] = (Byte)(dest >> 8);
182                 if (outPos == outSize)
183                     break;
184                 outBuf[outPos++] = (Byte)(dest >> 16);
185                 if (outPos == outSize)
186                     break;
187                 outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
188             }
189         }
190         return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
191     }
192 }