]> git.cworth.org Git - vogl/blob - src/voglcore/lzma_Bra86.cpp
Initial vogl checkin
[vogl] / src / voglcore / lzma_Bra86.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 /* Bra86.c -- Converter for x86 code (BCJ)
28 2008-10-04 : Igor Pavlov : Public domain */
29 #include "vogl_core.h"
30 #include "lzma_Bra.h"
31
32 namespace vogl
33 {
34
35 #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
36
37     const Byte kMaskToAllowedStatus[8] = { 1, 1, 1, 0, 1, 0, 0, 0 };
38     const Byte kMaskToBitNumber[8] = { 0, 1, 2, 2, 3, 3, 3, 3 };
39
40     SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
41     {
42         SizeT bufferPos = 0, prevPosT;
43         UInt32 prevMask = *state & 0x7;
44         if (size < 5)
45             return 0;
46         ip += 5;
47         prevPosT = (SizeT)0 - 1;
48
49         for (;;)
50         {
51             Byte *p = data + bufferPos;
52             Byte *limit = data + size - 4;
53             for (; p < limit; p++)
54                 if ((*p & 0xFE) == 0xE8)
55                     break;
56             bufferPos = (SizeT)(p - data);
57             if (p >= limit)
58                 break;
59             prevPosT = bufferPos - prevPosT;
60             if (prevPosT > 3)
61                 prevMask = 0;
62             else
63             {
64                 prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
65                 if (prevMask != 0)
66                 {
67                     Byte b = p[4 - kMaskToBitNumber[prevMask]];
68                     if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
69                     {
70                         prevPosT = bufferPos;
71                         prevMask = ((prevMask << 1) & 0x7) | 1;
72                         bufferPos++;
73                         continue;
74                     }
75                 }
76             }
77             prevPosT = bufferPos;
78
79             if (Test86MSByte(p[4]))
80             {
81                 UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
82                 UInt32 dest;
83                 for (;;)
84                 {
85                     Byte b;
86                     int index;
87                     if (encoding)
88                         dest = (ip + (UInt32)bufferPos) + src;
89                     else
90                         dest = src - (ip + (UInt32)bufferPos);
91                     if (prevMask == 0)
92                         break;
93                     index = kMaskToBitNumber[prevMask] * 8;
94                     b = (Byte)(dest >> (24 - index));
95                     if (!Test86MSByte(b))
96                         break;
97                     src = dest ^ ((1 << (32 - index)) - 1);
98                 }
99                 p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
100                 p[3] = (Byte)(dest >> 16);
101                 p[2] = (Byte)(dest >> 8);
102                 p[1] = (Byte)dest;
103                 bufferPos += 5;
104             }
105             else
106             {
107                 prevMask = ((prevMask << 1) & 0x7) | 1;
108                 bufferPos++;
109             }
110         }
111         prevPosT = bufferPos - prevPosT;
112         *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
113         return bufferPos;
114     }
115 }