c1772f2344e59943469dc46a005e799bf6b7f726
[pcsx_rearmed.git] / deps / libchdr / deps / lzma-22.01 / src / Bcj2.c
1 /* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)\r
2 2021-02-09 : 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[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0];\r
65       p->state++;\r
66       p->dest = dest + 1;\r
67     }\r
68   }\r
69 \r
70   /*\r
71   if (BCJ2_IS_32BIT_STREAM(p->state))\r
72   {\r
73     const Byte *cur = p->bufs[p->state];\r
74     if (cur == p->lims[p->state])\r
75       return SZ_OK;\r
76     p->bufs[p->state] = cur + 4;\r
77     \r
78     {\r
79       UInt32 val;\r
80       Byte *dest;\r
81       SizeT rem;\r
82       \r
83       p->ip += 4;\r
84       val = GetBe32(cur) - p->ip;\r
85       dest = p->dest;\r
86       rem = p->destLim - dest;\r
87       if (rem < 4)\r
88       {\r
89         SizeT i;\r
90         SetUi32(p->temp, val);\r
91         for (i = 0; i < rem; i++)\r
92           dest[i] = p->temp[i];\r
93         p->dest = dest + rem;\r
94         p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;\r
95         return SZ_OK;\r
96       }\r
97       SetUi32(dest, val);\r
98       p->temp[3] = (Byte)(val >> 24);\r
99       p->dest = dest + 4;\r
100       p->state = BCJ2_DEC_STATE_OK;\r
101     }\r
102   }\r
103   */\r
104 \r
105   for (;;)\r
106   {\r
107     if (BCJ2_IS_32BIT_STREAM(p->state))\r
108       p->state = BCJ2_DEC_STATE_OK;\r
109     else\r
110     {\r
111       if (p->range < kTopValue)\r
112       {\r
113         if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])\r
114         {\r
115           p->state = BCJ2_STREAM_RC;\r
116           return SZ_OK;\r
117         }\r
118         p->range <<= 8;\r
119         p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;\r
120       }\r
121 \r
122       {\r
123         const Byte *src = p->bufs[BCJ2_STREAM_MAIN];\r
124         const Byte *srcLim;\r
125         Byte *dest;\r
126         SizeT num = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - src);\r
127         \r
128         if (num == 0)\r
129         {\r
130           p->state = BCJ2_STREAM_MAIN;\r
131           return SZ_OK;\r
132         }\r
133         \r
134         dest = p->dest;\r
135         if (num > (SizeT)(p->destLim - dest))\r
136         {\r
137           num = (SizeT)(p->destLim - dest);\r
138           if (num == 0)\r
139           {\r
140             p->state = BCJ2_DEC_STATE_ORIG;\r
141             return SZ_OK;\r
142           }\r
143         }\r
144        \r
145         srcLim = src + num;\r
146 \r
147         if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80)\r
148           *dest = src[0];\r
149         else for (;;)\r
150         {\r
151           Byte b = *src;\r
152           *dest = b;\r
153           if (b != 0x0F)\r
154           {\r
155             if ((b & 0xFE) == 0xE8)\r
156               break;\r
157             dest++;\r
158             if (++src != srcLim)\r
159               continue;\r
160             break;\r
161           }\r
162           dest++;\r
163           if (++src == srcLim)\r
164             break;\r
165           if ((*src & 0xF0) != 0x80)\r
166             continue;\r
167           *dest = *src;\r
168           break;\r
169         }\r
170         \r
171         num = (SizeT)(src - p->bufs[BCJ2_STREAM_MAIN]);\r
172         \r
173         if (src == srcLim)\r
174         {\r
175           p->temp[3] = src[-1];\r
176           p->bufs[BCJ2_STREAM_MAIN] = src;\r
177           p->ip += (UInt32)num;\r
178           p->dest += num;\r
179           p->state =\r
180             p->bufs[BCJ2_STREAM_MAIN] ==\r
181             p->lims[BCJ2_STREAM_MAIN] ?\r
182               (unsigned)BCJ2_STREAM_MAIN :\r
183               (unsigned)BCJ2_DEC_STATE_ORIG;\r
184           return SZ_OK;\r
185         }\r
186         \r
187         {\r
188           UInt32 bound, ttt;\r
189           CProb *prob;\r
190           Byte b = src[0];\r
191           Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]);\r
192           \r
193           p->temp[3] = b;\r
194           p->bufs[BCJ2_STREAM_MAIN] = src + 1;\r
195           num++;\r
196           p->ip += (UInt32)num;\r
197           p->dest += num;\r
198           \r
199           prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0));\r
200           \r
201           _IF_BIT_0\r
202           {\r
203             _UPDATE_0\r
204             continue;\r
205           }\r
206           _UPDATE_1\r
207             \r
208         }\r
209       }\r
210     }\r
211 \r
212     {\r
213       UInt32 val;\r
214       unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;\r
215       const Byte *cur = p->bufs[cj];\r
216       Byte *dest;\r
217       SizeT rem;\r
218       \r
219       if (cur == p->lims[cj])\r
220       {\r
221         p->state = cj;\r
222         break;\r
223       }\r
224       \r
225       val = GetBe32(cur);\r
226       p->bufs[cj] = cur + 4;\r
227 \r
228       p->ip += 4;\r
229       val -= p->ip;\r
230       dest = p->dest;\r
231       rem = (SizeT)(p->destLim - dest);\r
232       \r
233       if (rem < 4)\r
234       {\r
235         p->temp[0] = (Byte)val; if (rem > 0) dest[0] = (Byte)val; val >>= 8;\r
236         p->temp[1] = (Byte)val; if (rem > 1) dest[1] = (Byte)val; val >>= 8;\r
237         p->temp[2] = (Byte)val; if (rem > 2) dest[2] = (Byte)val; val >>= 8;\r
238         p->temp[3] = (Byte)val;\r
239         p->dest = dest + rem;\r
240         p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;\r
241         break;\r
242       }\r
243       \r
244       SetUi32(dest, val);\r
245       p->temp[3] = (Byte)(val >> 24);\r
246       p->dest = dest + 4;\r
247     }\r
248   }\r
249 \r
250   if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])\r
251   {\r
252     p->range <<= 8;\r
253     p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;\r
254   }\r
255 \r
256   return SZ_OK;\r
257 }\r