add CHD support.
[pcsx_rearmed.git] / deps / lzma-16.04 / C / Bcj2.c
1 /* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)\r
2 2015-08-01 : Igor Pavlov : Public domain */\r
3 \r
4 #include "Precomp.h"\r
5 \r
6 #include "Bcj2.h"\r
7 #include "CpuArch.h"\r
8 \r
9 #define CProb UInt16\r
10 \r
11 #define kTopValue ((UInt32)1 << 24)\r
12 #define kNumModelBits 11\r
13 #define kBitModelTotal (1 << kNumModelBits)\r
14 #define kNumMoveBits 5\r
15 \r
16 #define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound)\r
17 #define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));\r
18 #define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits));\r
19 \r
20 void Bcj2Dec_Init(CBcj2Dec *p)\r
21 {\r
22   unsigned i;\r
23 \r
24   p->state = BCJ2_DEC_STATE_OK;\r
25   p->ip = 0;\r
26   p->temp[3] = 0;\r
27   p->range = 0;\r
28   p->code = 0;\r
29   for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)\r
30     p->probs[i] = kBitModelTotal >> 1;\r
31 }\r
32 \r
33 SRes Bcj2Dec_Decode(CBcj2Dec *p)\r
34 {\r
35   if (p->range <= 5)\r
36   {\r
37     p->state = BCJ2_DEC_STATE_OK;\r
38     for (; p->range != 5; p->range++)\r
39     {\r
40       if (p->range == 1 && p->code != 0)\r
41         return SZ_ERROR_DATA;\r
42       \r
43       if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])\r
44       {\r
45         p->state = BCJ2_STREAM_RC;\r
46         return SZ_OK;\r
47       }\r
48 \r
49       p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;\r
50     }\r
51     \r
52     if (p->code == 0xFFFFFFFF)\r
53       return SZ_ERROR_DATA;\r
54     \r
55     p->range = 0xFFFFFFFF;\r
56   }\r
57   else if (p->state >= BCJ2_DEC_STATE_ORIG_0)\r
58   {\r
59     while (p->state <= BCJ2_DEC_STATE_ORIG_3)\r
60     {\r
61       Byte *dest = p->dest;\r
62       if (dest == p->destLim)\r
63         return SZ_OK;\r
64       *dest = p->temp[p->state++ - BCJ2_DEC_STATE_ORIG_0];\r
65       p->dest = dest + 1;\r
66     }\r
67   }\r
68 \r
69   /*\r
70   if (BCJ2_IS_32BIT_STREAM(p->state))\r
71   {\r
72     const Byte *cur = p->bufs[p->state];\r
73     if (cur == p->lims[p->state])\r
74       return SZ_OK;\r
75     p->bufs[p->state] = cur + 4;\r
76     \r
77     {\r
78       UInt32 val;\r
79       Byte *dest;\r
80       SizeT rem;\r
81       \r
82       p->ip += 4;\r
83       val = GetBe32(cur) - p->ip;\r
84       dest = p->dest;\r
85       rem = p->destLim - dest;\r
86       if (rem < 4)\r
87       {\r
88         SizeT i;\r
89         SetUi32(p->temp, val);\r
90         for (i = 0; i < rem; i++)\r
91           dest[i] = p->temp[i];\r
92         p->dest = dest + rem;\r
93         p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;\r
94         return SZ_OK;\r
95       }\r
96       SetUi32(dest, val);\r
97       p->temp[3] = (Byte)(val >> 24);\r
98       p->dest = dest + 4;\r
99       p->state = BCJ2_DEC_STATE_OK;\r
100     }\r
101   }\r
102   */\r
103 \r
104   for (;;)\r
105   {\r
106     if (BCJ2_IS_32BIT_STREAM(p->state))\r
107       p->state = BCJ2_DEC_STATE_OK;\r
108     else\r
109     {\r
110       if (p->range < kTopValue)\r
111       {\r
112         if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])\r
113         {\r
114           p->state = BCJ2_STREAM_RC;\r
115           return SZ_OK;\r
116         }\r
117         p->range <<= 8;\r
118         p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;\r
119       }\r
120 \r
121       {\r
122         const Byte *src = p->bufs[BCJ2_STREAM_MAIN];\r
123         const Byte *srcLim;\r
124         Byte *dest;\r
125         SizeT num = p->lims[BCJ2_STREAM_MAIN] - src;\r
126         \r
127         if (num == 0)\r
128         {\r
129           p->state = BCJ2_STREAM_MAIN;\r
130           return SZ_OK;\r
131         }\r
132         \r
133         dest = p->dest;\r
134         if (num > (SizeT)(p->destLim - dest))\r
135         {\r
136           num = p->destLim - dest;\r
137           if (num == 0)\r
138           {\r
139             p->state = BCJ2_DEC_STATE_ORIG;\r
140             return SZ_OK;\r
141           }\r
142         }\r
143        \r
144         srcLim = src + num;\r
145 \r
146         if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80)\r
147           *dest = src[0];\r
148         else for (;;)\r
149         {\r
150           Byte b = *src;\r
151           *dest = b;\r
152           if (b != 0x0F)\r
153           {\r
154             if ((b & 0xFE) == 0xE8)\r
155               break;\r
156             dest++;\r
157             if (++src != srcLim)\r
158               continue;\r
159             break;\r
160           }\r
161           dest++;\r
162           if (++src == srcLim)\r
163             break;\r
164           if ((*src & 0xF0) != 0x80)\r
165             continue;\r
166           *dest = *src;\r
167           break;\r
168         }\r
169         \r
170         num = src - p->bufs[BCJ2_STREAM_MAIN];\r
171         \r
172         if (src == srcLim)\r
173         {\r
174           p->temp[3] = src[-1];\r
175           p->bufs[BCJ2_STREAM_MAIN] = src;\r
176           p->ip += (UInt32)num;\r
177           p->dest += num;\r
178           p->state =\r
179             p->bufs[BCJ2_STREAM_MAIN] ==\r
180             p->lims[BCJ2_STREAM_MAIN] ?\r
181               (unsigned)BCJ2_STREAM_MAIN :\r
182               (unsigned)BCJ2_DEC_STATE_ORIG;\r
183           return SZ_OK;\r
184         }\r
185         \r
186         {\r
187           UInt32 bound, ttt;\r
188           CProb *prob;\r
189           Byte b = src[0];\r
190           Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]);\r
191           \r
192           p->temp[3] = b;\r
193           p->bufs[BCJ2_STREAM_MAIN] = src + 1;\r
194           num++;\r
195           p->ip += (UInt32)num;\r
196           p->dest += num;\r
197           \r
198           prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0));\r
199           \r
200           _IF_BIT_0\r
201           {\r
202             _UPDATE_0\r
203             continue;\r
204           }\r
205           _UPDATE_1\r
206             \r
207         }\r
208       }\r
209     }\r
210 \r
211     {\r
212       UInt32 val;\r
213       unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;\r
214       const Byte *cur = p->bufs[cj];\r
215       Byte *dest;\r
216       SizeT rem;\r
217       \r
218       if (cur == p->lims[cj])\r
219       {\r
220         p->state = cj;\r
221         break;\r
222       }\r
223       \r
224       val = GetBe32(cur);\r
225       p->bufs[cj] = cur + 4;\r
226 \r
227       p->ip += 4;\r
228       val -= p->ip;\r
229       dest = p->dest;\r
230       rem = p->destLim - dest;\r
231       \r
232       if (rem < 4)\r
233       {\r
234         SizeT i;\r
235         SetUi32(p->temp, val);\r
236         for (i = 0; i < rem; i++)\r
237           dest[i] = p->temp[i];\r
238         p->dest = dest + rem;\r
239         p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;\r
240         break;\r
241       }\r
242       \r
243       SetUi32(dest, val);\r
244       p->temp[3] = (Byte)(val >> 24);\r
245       p->dest = dest + 4;\r
246     }\r
247   }\r
248 \r
249   if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])\r
250   {\r
251     p->range <<= 8;\r
252     p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;\r
253   }\r
254 \r
255   return SZ_OK;\r
256 }\r