Dialog: "Compile" dialog triggers on read, rather than execution.
[gemrb.git] / gemrb / plugins / ACMReader / unpacker.cpp
blob9e94528b78074b3cc4d4137380c26a809883bc51
1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 //#include "stdafx.h"
22 // IP's ACM-stream unpacker.
24 #include <stdio.h>
25 #include "unpacker.h"
27 char Table1[27] = {
28 0, 1, 2, 4, 5, 6, 8, 9, 10, 16, 17, 18, 20, 21, 22, 24, 25, 26, 32, 33,
29 34, 36, 37, 38, 40, 41, 42
31 //Eng: in base-4 system it is:
32 //Rus: â ÷åòâåðè÷íîé ñèñòåìå ýòî áóäåò:
33 // 000 001 002 010 011 012 020 021 022
34 // 100 101 102 110 111 112 120 121 122
35 // 200 201 202 210 211 212 220 221 222
36 short Table2[125] = {
37 0, 1, 2, 3, 4, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 24, 25, 26, 27, 28,
38 32, 33, 34, 35, 36, 64, 65, 66, 67, 68, 72, 73, 74, 75, 76, 80, 81, 82,
39 83, 84, 88, 89, 90, 91, 92, 96, 97, 98, 99, 100, 128, 129, 130, 131, 132,
40 136, 137, 138, 139, 140, 144, 145, 146, 147, 148, 152, 153, 154, 155, 156,
41 160, 161, 162, 163, 164, 192, 193, 194, 195, 196, 200, 201, 202, 203, 204,
42 208, 209, 210, 211, 212, 216, 217, 218, 219, 220, 224, 225, 226, 227, 228,
43 256, 257, 258, 259, 260, 264, 265, 266, 267, 268, 272, 273, 274, 275, 276,
44 280, 281, 282, 283, 284, 288, 289, 290, 291, 292
46 //Eng: in base-8 system:
47 //Rus: â âîñüìåðè÷íîé ñèñòåìå:
48 // 000 001 002 003 004 010 011 012 013 014 ...
49 // 100 101 102 103 104 ...
50 // 200 ...
51 // ...
52 unsigned char Table3[121] = {
53 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x10,
54 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x20, 0x21,
55 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x30, 0x31, 0x32,
56 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x40, 0x41, 0x42, 0x43,
57 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x50, 0x51, 0x52, 0x53, 0x54,
58 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65,
59 0x66, 0x67, 0x68, 0x69, 0x6A, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
60 0x77, 0x78, 0x79, 0x7A, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
61 0x88, 0x89, 0x8A, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
62 0x99, 0x9A, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9,
63 0xAA
66 FillerProc Fillers[32] = {
67 &CValueUnpacker::zero_fill, & CValueUnpacker::return0,
68 & CValueUnpacker::return0, & CValueUnpacker::linear_fill,
69 & CValueUnpacker::linear_fill, & CValueUnpacker::linear_fill,
70 & CValueUnpacker::linear_fill, & CValueUnpacker::linear_fill,
71 & CValueUnpacker::linear_fill, & CValueUnpacker::linear_fill,
72 & CValueUnpacker::linear_fill, & CValueUnpacker::linear_fill,
73 & CValueUnpacker::linear_fill, & CValueUnpacker::linear_fill,
74 & CValueUnpacker::linear_fill, & CValueUnpacker::linear_fill,
75 & CValueUnpacker::linear_fill, & CValueUnpacker::k1_3bits,
76 & CValueUnpacker::k1_2bits, & CValueUnpacker::t1_5bits,
77 & CValueUnpacker::k2_4bits, & CValueUnpacker::k2_3bits,
78 & CValueUnpacker::t2_7bits, & CValueUnpacker::k3_5bits,
79 & CValueUnpacker::k3_4bits, & CValueUnpacker::return0,
80 & CValueUnpacker::k4_5bits, & CValueUnpacker::k4_4bits,
81 & CValueUnpacker::return0, & CValueUnpacker::t3_7bits,
82 & CValueUnpacker::return0, & CValueUnpacker::return0
85 void CValueUnpacker::prepare_bits(int bits)
87 while (bits > avail_bits) {
88 unsigned char one_byte;
89 //our stream read returns -1 instead of 0 on failure
90 //comparing with 1 will solve annoying interface changes
91 if (stream->Read( &one_byte, 1 )!=1) {
92 one_byte = 0;
94 next_bits |= ( ( unsigned int ) one_byte << avail_bits );
95 avail_bits += 8;
98 int CValueUnpacker::get_bits(int bits)
100 prepare_bits( bits );
101 int res = next_bits;
102 avail_bits -= bits;
103 next_bits >>= bits;
104 return res;
106 int CValueUnpacker::init_unpacker()
108 //using malloc, supposed to be faster
109 amp_buffer =(short *) malloc(sizeof(short)*0x10000);
110 if (!amp_buffer) {
111 return 0;
113 buff_middle = amp_buffer + 0x8000;
114 return 1;
116 int CValueUnpacker::get_one_block(int* block)
118 block_ptr = block;
119 int pwr = get_bits( 4 ) & 0xF, val = get_bits( 16 ) & 0xFFFF,
120 count = 1 << pwr, v = 0;
121 int i;
122 for (i = 0; i < count; i++) {
123 buff_middle[i] = ( short ) v;
124 v += val;
126 v = -val;
127 for (i = 0; i < count; i++) {
128 buff_middle[-i - 1] = ( short ) v;
129 v -= val;
132 for (int pass = 0; pass < sb_size; pass++) {
133 int ind = get_bits( 5 ) & 0x1F;
134 if (!( ( this->*Fillers[ind] ) ( pass, ind ) )) {
135 return 0;
138 return 1;
142 // Filling functions:
143 // int CValueUnpacker::FillerProc (int pass, int ind)
144 int CValueUnpacker::return0(int /*pass*/, int /*ind*/)
146 return 0;
148 int CValueUnpacker::zero_fill(int pass, int /*ind*/)
150 //Eng: used when the whole column #pass is zero-filled
151 //Rus: èñïîëüçóåòñÿ, êîãäà âåñü ñòîëáåö ñ íîìåðîì pass çàïîëíåí íóëÿìè
152 int* sb_ptr = &block_ptr[pass], step = sb_size, i = subblocks;
153 do {
154 *sb_ptr = 0;
155 sb_ptr += step;
156 } while (( --i ) != 0);
157 return 1;
159 int CValueUnpacker::linear_fill(int pass, int ind)
161 int mask = ( 1 << ind ) - 1;
162 short* lb_ptr = buff_middle + ( ( -1l ) << ( ind - 1 ) );
164 for (int i = 0; i < subblocks; i++)
165 block_ptr[i * sb_size + pass] = lb_ptr[get_bits( ind ) & mask];
166 return 1;
168 int CValueUnpacker::k1_3bits(int pass, int /*ind*/)
170 //Eng: column with number pass is filled with zeros, and also +/-1, zeros are repeated frequently
171 //Rus: còîëáåö pass çàïîëíåí íóëÿìè, à òàêæå +/- 1, íî íóëè ÷àñòî èäóò ïîäðÿä
172 // efficiency (bits per value): 3-p0-2.5*p00, p00 - cnt of paired zeros, p0 - cnt of single zeros.
173 //Eng: it makes sense to use, when the freqnecy of paired zeros (p00) is greater than 2/3
174 //Rus: èìååò ñìûñë èñïîëüçîâàòü, êîãäà âåðîÿòíîñòü ïàðíûõ íóëåé (p00) áîëüøå 2/3
175 for (int i = 0; i < subblocks; i++) {
176 prepare_bits( 3 );
177 if (( next_bits & 1 ) == 0) {
178 avail_bits--;
179 next_bits >>= 1;
180 block_ptr[i * sb_size + pass] = 0; if (( ++i ) == subblocks)
181 break;
182 block_ptr[i * sb_size + pass] = 0;
183 } else if (( next_bits & 2 ) == 0) {
184 avail_bits -= 2;
185 next_bits >>= 2;
186 block_ptr[i * sb_size + pass] = 0;
187 } else {
188 block_ptr[i * sb_size + pass] = ( next_bits & 4 ) ?
189 buff_middle[1] :
190 buff_middle[-1];
191 avail_bits -= 3;
192 next_bits >>= 3;
195 return 1;
197 int CValueUnpacker::k1_2bits(int pass, int /*ind*/)
199 //Eng: column is filled with zero and +/-1
200 //Rus: còîëáåö pass çàïîëíåí íóëÿìè, à òàêæå +/- 1
201 // efficiency: 2-P0. P0 - cnt of any zero (P0 = p0 + p00)
202 //Eng: use it when P0 > 1/3
203 //Rus: èìååò ñìûñë èñïîëüçîâàòü, êîãäà âåðîÿòíîñòü íóëÿ áîëüøå 1/3
204 for (int i = 0; i < subblocks; i++) {
205 prepare_bits( 2 );
206 if (( next_bits & 1 ) == 0) {
207 avail_bits--;
208 next_bits >>= 1;
209 block_ptr[i * sb_size + pass] = 0;
210 } else {
211 block_ptr[i * sb_size + pass] = ( next_bits & 2 ) ?
212 buff_middle[1] :
213 buff_middle[-1];
214 avail_bits -= 2;
215 next_bits >>= 2;
218 return 1;
220 int CValueUnpacker::t1_5bits(int pass, int /*ind*/)
222 //Eng: all the -1, 0, +1 triplets
223 //Rus: âñå êîìáèíàöèè òðîåê -1, 0, +1.
224 // efficiency: always 5/3 bits per value
225 // use it when P0 <= 1/3
226 for (int i = 0; i < subblocks; i++) {
227 int bits = ( int ) ( get_bits( 5 ) & 0x1f );
228 bits = ( int ) Table1[bits];
230 block_ptr[i * sb_size + pass] = buff_middle[-1 + ( bits & 3 )];
231 if (( ++i ) == subblocks)
232 break;
233 bits >>= 2;
234 block_ptr[i * sb_size + pass] = buff_middle[-1 + ( bits & 3 )];
235 if (( ++i ) == subblocks)
236 break;
237 bits >>= 2;
238 block_ptr[i * sb_size + pass] = buff_middle[-1 + bits];
240 return 1;
242 int CValueUnpacker::k2_4bits(int pass, int /*ind*/)
244 // -2, -1, 0, 1, 2, and repeating zeros
245 // efficiency: 4-2*p0-3.5*p00, p00 - cnt of paired zeros, p0 - cnt of single zeros.
246 //Eng: makes sense to use when p00>2/3
247 //Rus: èìååò ñìûñë èñïîëüçîâàòü, êîãäà âåðîÿòíîñòü ïàðíûõ íóëåé (p00) áîëüøå 2/3
248 for (int i = 0; i < subblocks; i++) {
249 prepare_bits( 4 );
250 if (( next_bits & 1 ) == 0) {
251 avail_bits--;
252 next_bits >>= 1;
253 block_ptr[i * sb_size + pass] = 0; if (( ++i ) == subblocks)
254 break;
255 block_ptr[i * sb_size + pass] = 0;
256 } else if (( next_bits & 2 ) == 0) {
257 avail_bits -= 2;
258 next_bits >>= 2;
259 block_ptr[i * sb_size + pass] = 0;
260 } else {
261 block_ptr[i * sb_size + pass] = ( next_bits & 8 ) ?
262 ( ( next_bits & 4 ) ? buff_middle[2] : buff_middle[1] ) :
263 ( ( next_bits & 4 ) ? buff_middle[-1] : buff_middle[-2] );
264 avail_bits -= 4;
265 next_bits >>= 4;
268 return 1;
270 int CValueUnpacker::k2_3bits(int pass, int /*ind*/)
272 // -2, -1, 0, 1, 2
273 // efficiency: 3-2*P0, P0 - cnt of any zero (P0 = p0 + p00)
274 //Eng: use when P0>1/3
275 //Rus: èìååò ñìûñë èñïîëüçîâàòü, êîãäà âåðîÿòíîñòü íóëÿ áîëüøå 1/3
276 for (int i = 0; i < subblocks; i++) {
277 prepare_bits( 3 );
278 if (( next_bits & 1 ) == 0) {
279 avail_bits--;
280 next_bits >>= 1;
281 block_ptr[i * sb_size + pass] = 0;
282 } else {
283 block_ptr[i * sb_size + pass] = ( next_bits & 4 ) ?
284 ( ( next_bits & 2 ) ? buff_middle[2] : buff_middle[1] ) :
285 ( ( next_bits & 2 ) ? buff_middle[-1] : buff_middle[-2] );
286 avail_bits -= 3;
287 next_bits >>= 3;
290 return 1;
292 int CValueUnpacker::t2_7bits(int pass, int /*ind*/)
294 //Eng: all the +/-2, +/-1, 0 triplets
295 // efficiency: always 7/3 bits per value
296 //Rus: âñå êîìáèíàöèè òðîåê -2, -1, 0, +1, 2.
297 // ýôôåêòèâíîñòü: 7/3 áèòà íà çíà÷åíèå - âñåãäà
298 // use it when p0 <= 1/3
299 for (int i = 0; i < subblocks; i++) {
300 int bits = ( int ) ( get_bits( 7 ) & 0x7f );
301 short val = Table2[bits];
303 block_ptr[i * sb_size + pass] = buff_middle[-2 + ( val & 7 )];
304 if (( ++i ) == subblocks)
305 break;
306 val >>= 3;
307 block_ptr[i * sb_size + pass] = buff_middle[-2 + ( val & 7 )];
308 if (( ++i ) == subblocks)
309 break;
310 val >>= 3;
311 block_ptr[i * sb_size + pass] = buff_middle[-2 + val];
313 return 1;
315 int CValueUnpacker::k3_5bits(int pass, int /*ind*/)
317 // fills with values: -3, -2, -1, 0, 1, 2, 3, and double zeros
318 // efficiency: 5-3*p0-4.5*p00-p1, p00 - cnt of paired zeros, p0 - cnt of single zeros, p1 - cnt of +/- 1.
319 // can be used when frequency of paired zeros (p00) is greater than 2/3
320 for (int i = 0; i < subblocks; i++) {
321 prepare_bits( 5 );
322 if (( next_bits & 1 ) == 0) {
323 avail_bits--;
324 next_bits >>= 1;
325 block_ptr[i * sb_size + pass] = 0; if (( ++i ) == subblocks)
326 break;
327 block_ptr[i * sb_size + pass] = 0;
328 } else if (( next_bits & 2 ) == 0) {
329 avail_bits -= 2;
330 next_bits >>= 2;
331 block_ptr[i * sb_size + pass] = 0;
332 } else if (( next_bits & 4 ) == 0) {
333 block_ptr[i * sb_size + pass] = ( next_bits & 8 ) ?
334 buff_middle[1] :
335 buff_middle[-1];
336 avail_bits -= 4;
337 next_bits >>= 4;
338 } else {
339 avail_bits -= 5;
340 int val = ( next_bits & 0x18 ) >> 3;
341 next_bits >>= 5;
342 if (val >= 2)
343 val += 3;
344 block_ptr[i * sb_size + pass] = buff_middle[-3 + val];
347 return 1;
349 int CValueUnpacker::k3_4bits(int pass, int /*ind*/)
351 // fills with values: -3, -2, -1, 0, 1, 2, 3.
352 // efficiency: 4-3*P0-p1, P0 - cnt of all zeros (P0 = p0 + p00), p1 - cnt of +/- 1.
353 for (int i = 0; i < subblocks; i++) {
354 prepare_bits( 4 );
355 if (( next_bits & 1 ) == 0) {
356 avail_bits--;
357 next_bits >>= 1;
358 block_ptr[i * sb_size + pass] = 0;
359 } else if (( next_bits & 2 ) == 0) {
360 avail_bits -= 3;
361 block_ptr[i * sb_size + pass] = ( next_bits & 4 ) ?
362 buff_middle[1] :
363 buff_middle[-1];
364 next_bits >>= 3;
365 } else {
366 int val = ( next_bits &0xC ) >> 2;
367 avail_bits -= 4;
368 next_bits >>= 4;
369 if (val >= 2)
370 val += 3;
371 block_ptr[i * sb_size + pass] = buff_middle[-3 + val];
374 return 1;
376 int CValueUnpacker::k4_5bits(int pass, int /*ind*/)
378 // fills with values: +/-4, +/-3, +/-2, +/-1, 0, and double zeros
379 // efficiency: 5-3*p0-4.5*p00, p00 - cnt of paired zeros, p0 - cnt of single zeros.
380 //Eng: makes sense to use when p00>2/3
381 //Rus: èìååò ñìûñë èñïîëüçîâàòü, êîãäà âåðîÿòíîñòü ïàðíûõ íóëåé (p00) áîëüøå 2/3
382 for (int i = 0; i < subblocks; i++) {
383 prepare_bits( 5 );
384 if (( next_bits & 1 ) == 0) {
385 avail_bits--;
386 next_bits >>= 1;
387 block_ptr[i * sb_size + pass] = 0; if (( ++i ) == subblocks)
388 break;
389 block_ptr[i * sb_size + pass] = 0;
390 } else if (( next_bits & 2 ) == 0) {
391 avail_bits -= 2;
392 next_bits >>= 2;
393 block_ptr[i * sb_size + pass] = 0;
394 } else {
395 int val = ( next_bits &0x1C ) >> 2;
396 if (val >= 4)
397 val++;
398 block_ptr[i * sb_size + pass] = buff_middle[-4 + val];
399 avail_bits -= 5;
400 next_bits >>= 5;
403 return 1;
405 int CValueUnpacker::k4_4bits(int pass, int /*ind*/)
407 // fills with values: +/-4, +/-3, +/-2, +/-1, 0, and double zeros
408 // efficiency: 4-3*P0, P0 - cnt of all zeros (both single and paired).
409 for (int i = 0; i < subblocks; i++) {
410 prepare_bits( 4 );
411 if (( next_bits & 1 ) == 0) {
412 avail_bits--;
413 next_bits >>= 1;
414 block_ptr[i * sb_size + pass] = 0;
415 } else {
416 int val = ( next_bits &0xE ) >> 1;
417 avail_bits -= 4;
418 next_bits >>= 4;
419 if (val >= 4)
420 val++;
421 block_ptr[i * sb_size + pass] = buff_middle[-4 + val];
424 return 1;
426 int CValueUnpacker::t3_7bits(int pass, int /*ind*/)
428 //Eng: all the pairs of values from -5 to +5
429 // efficiency: 7/2 bits per value
430 //Rus: âñå êîìáèíàöèè ïàð îò -5 äî +5
431 // ýôôåêòèâíîñòü: 7/2 áèòà íà çíà÷åíèå - âñåãäà
432 for (int i = 0; i < subblocks; i++) {
433 int bits = ( int ) ( get_bits( 7 ) & 0x7f );
434 unsigned char val = Table3[bits];
436 block_ptr[i * sb_size + pass] = buff_middle[-5 + ( val & 0xF )];
437 if (( ++i ) == subblocks)
438 break;
439 val >>= 4;
440 block_ptr[i * sb_size + pass] = buff_middle[-5 + val];
442 return 1;