workaround a problem with the harmattan gcc
[drnoksnes] / sdd1emu.cpp
1 /*******************************************************************************
2   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  
4   (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and
5                             Jerremy Koot (jkoot@snes9x.com)
6
7   (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net)
8
9   (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net),
10                             funkyass (funkyass@spam.shaw.ca),
11                             Joel Yliluoma (http://iki.fi/bisqwit/)
12                             Kris Bleakley (codeviolation@hotmail.com),
13                             Matthew Kendora,
14                             Nach (n-a-c-h@users.sourceforge.net),
15                             Peter Bortas (peter@bortas.org) and
16                             zones (kasumitokoduck@yahoo.com)
17
18   C4 x86 assembler and some C emulation code
19   (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com),
20                             _Demo_ (_demo_@zsnes.com), and Nach
21
22   C4 C++ code
23   (c) Copyright 2003 Brad Jorsch
24
25   DSP-1 emulator code
26   (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson,
27                             John Weidman, neviksti (neviksti@hotmail.com),
28                             Kris Bleakley, Andreas Naive
29
30   DSP-2 emulator code
31   (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and
32                      Lord Nightmare (lord_nightmare@users.sourceforge.net
33
34   OBC1 emulator code
35   (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and
36                             Kris Bleakley
37   Ported from x86 assembler to C by sanmaiwashi
38
39   SPC7110 and RTC C++ emulator code
40   (c) Copyright 2002 Matthew Kendora with research by
41                      zsKnight, John Weidman, and Dark Force
42
43   S-DD1 C emulator code
44   (c) Copyright 2003 Brad Jorsch with research by
45                      Andreas Naive and John Weidman
46  
47   S-RTC C emulator code
48   (c) Copyright 2001 John Weidman
49   
50   ST010 C++ emulator code
51   (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora
52
53   Super FX x86 assembler emulator code 
54   (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault 
55
56   Super FX C emulator code 
57   (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman
58
59
60   SH assembler code partly based on x86 assembler code
61   (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) 
62
63  
64   Specific ports contains the works of other authors. See headers in
65   individual files.
66  
67   Snes9x homepage: http://www.snes9x.com
68  
69   Permission to use, copy, modify and distribute Snes9x in both binary and
70   source form, for non-commercial purposes, is hereby granted without fee,
71   providing that this license information and copyright notice appear with
72   all copies and any derived work.
73  
74   This software is provided 'as-is', without any express or implied
75   warranty. In no event shall the authors be held liable for any damages
76   arising from the use of this software.
77  
78   Snes9x is freeware for PERSONAL USE only. Commercial users should
79   seek permission of the copyright holders first. Commercial use includes
80   charging money for Snes9x or software derived from Snes9x.
81  
82   The copyright holders request that bug fixes and improvements to the code
83   should be forwarded to them so everyone can benefit from the modifications
84   in future versions.
85  
86   Super NES and Super Nintendo Entertainment System are trademarks of
87   Nintendo Co., Limited and its subsidiary companies.
88 *******************************************************************************/
89 /* S-DD1 decompressor
90  *
91  * Based on code and documentation by Andreas Naive, who deserves a great deal
92  * of thanks and credit for figuring this out.
93  *
94  * Andreas says:
95  * The author is greatly indebted with The Dumper, without whose help and 
96  * patience providing him with real S-DD1 data the research had never been 
97  * possible. He also wish to note that in the very beggining of his research,
98  * Neviksti had done some steps in the right direction. By last, the author is
99  * indirectly indebted to all the people that worked and contributed in the
100  * S-DD1 issue in the past.
101  */
102
103 #include <string.h>
104 #include "port.h"
105 #include "sdd1emu.h"
106
107 static int valid_bits;
108 static uint16 in_stream;
109 static uint8 *in_buf;
110 static uint8 bit_ctr[8];
111 static uint8 context_states[32];
112 static int context_MPS[32];
113 static int bitplane_type;
114 static int high_context_bits;
115 static int low_context_bits;
116 static int prev_bits[8];
117
118 static struct {
119     uint8 code_size;
120     uint8 MPS_next;
121     uint8 LPS_next;
122 } evolution_table[] = {
123     /*  0 */ { 0,25,25},
124     /*  1 */ { 0, 2, 1},
125     /*  2 */ { 0, 3, 1},
126     /*  3 */ { 0, 4, 2},
127     /*  4 */ { 0, 5, 3},
128     /*  5 */ { 1, 6, 4},
129     /*  6 */ { 1, 7, 5},
130     /*  7 */ { 1, 8, 6},
131     /*  8 */ { 1, 9, 7},
132     /*  9 */ { 2,10, 8},
133     /* 10 */ { 2,11, 9},
134     /* 11 */ { 2,12,10},
135     /* 12 */ { 2,13,11},
136     /* 13 */ { 3,14,12},
137     /* 14 */ { 3,15,13},
138     /* 15 */ { 3,16,14},
139     /* 16 */ { 3,17,15},
140     /* 17 */ { 4,18,16},
141     /* 18 */ { 4,19,17},
142     /* 19 */ { 5,20,18},
143     /* 20 */ { 5,21,19},
144     /* 21 */ { 6,22,20},
145     /* 22 */ { 6,23,21},
146     /* 23 */ { 7,24,22},
147     /* 24 */ { 7,24,23},
148     /* 25 */ { 0,26, 1},
149     /* 26 */ { 1,27, 2},
150     /* 27 */ { 2,28, 4},
151     /* 28 */ { 3,29, 8},
152     /* 29 */ { 4,30,12},
153     /* 30 */ { 5,31,16},
154     /* 31 */ { 6,32,18},
155     /* 32 */ { 7,24,22}
156 };
157
158 static uint8 run_table[128] = {
159     128,  64,  96,  32, 112,  48,  80,  16, 120,  56,  88,  24, 104,  40,  72,
160       8, 124,  60,  92,  28, 108,  44,  76,  12, 116,  52,  84,  20, 100,  36,
161      68,   4, 126,  62,  94,  30, 110,  46,  78,  14, 118,  54,  86,  22, 102,
162      38,  70,   6, 122,  58,  90,  26, 106,  42,  74,  10, 114,  50,  82,  18,
163      98,  34,  66,   2, 127,  63,  95,  31, 111,  47,  79,  15, 119,  55,  87,
164      23, 103,  39,  71,   7, 123,  59,  91,  27, 107,  43,  75,  11, 115,  51,
165      83,  19,  99,  35,  67,   3, 125,  61,  93,  29, 109,  45,  77,  13, 117,
166      53,  85,  21, 101,  37,  69,   5, 121,  57,  89,  25, 105,  41,  73,   9,
167     113,  49,  81,  17,  97,  33,  65,   1
168 };
169
170 static inline uint8 GetCodeword(int bits){
171     uint8 tmp;
172
173     if(!valid_bits){
174         in_stream|=*(in_buf++);
175         valid_bits=8;
176     }
177     in_stream<<=1;
178     valid_bits--;
179     in_stream^=0x8000;
180     if(in_stream&0x8000) return 0x80+(1<<bits);
181     tmp=(in_stream>>8) | (0x7f>>bits);
182     in_stream<<=bits;
183     valid_bits-=bits;
184     if(valid_bits<0){
185         in_stream |= (*(in_buf++))<<(-valid_bits);
186         valid_bits+=8;
187     }
188     return run_table[tmp];
189 }
190
191 static inline uint8 GolombGetBit(int code_size){
192     if(!bit_ctr[code_size]) bit_ctr[code_size]=GetCodeword(code_size);
193     bit_ctr[code_size]--;
194     if(bit_ctr[code_size]==0x80){
195         bit_ctr[code_size]=0;
196         return 2; /* secret code for 'last zero'. ones are always last. */
197     }
198     return (bit_ctr[code_size]==0)?1:0;
199 }
200
201 static inline uint8 ProbGetBit(uint8 context){
202     uint8 state=context_states[context];
203     uint8 bit=GolombGetBit(evolution_table[state].code_size);
204
205     if(bit&1){
206         context_states[context]=evolution_table[state].LPS_next;
207         if(state<2){
208             context_MPS[context]^=1;
209             return context_MPS[context]; /* just inverted, so just return it */
210         } else{
211             return context_MPS[context]^1; /* we know bit is 1, so use a constant */
212         }
213     } else if(bit){
214         context_states[context]=evolution_table[state].MPS_next;
215         /* zero here, zero there, no difference so drop through. */
216     }
217     return context_MPS[context]; /* we know bit is 0, so don't bother xoring */
218 }
219
220 static inline uint8 GetBit(uint8 cur_bitplane){
221     uint8 bit;
222     
223     bit=ProbGetBit(((cur_bitplane&1)<<4)
224                    | ((prev_bits[cur_bitplane]&high_context_bits)>>5)
225                    | (prev_bits[cur_bitplane]&low_context_bits));
226
227     prev_bits[cur_bitplane] <<= 1;
228     prev_bits[cur_bitplane] |= bit;
229     return bit;
230 }
231
232 void SDD1_decompress(uint8 *out, uint8 *in, int len){
233     uint8 bit, i, plane;
234     uint8 byte1, byte2;
235
236     if(len==0) len=0x10000;
237     
238     bitplane_type=in[0]>>6;
239
240     switch(in[0]&0x30){
241       case 0x00:
242         high_context_bits=0x01c0;
243         low_context_bits =0x0001;
244         break;
245       case 0x10:
246         high_context_bits=0x0180;
247         low_context_bits =0x0001;
248         break;
249       case 0x20:
250         high_context_bits=0x00c0;
251         low_context_bits =0x0001;
252         break;
253       case 0x30:
254         high_context_bits=0x0180;
255         low_context_bits =0x0003;
256         break;
257     }
258
259     in_stream=(in[0]<<11) | (in[1]<<3);
260     valid_bits=5;
261     in_buf=in+2;
262     memset(bit_ctr, 0, sizeof(bit_ctr));
263     memset(context_states, 0, sizeof(context_states));
264     memset(context_MPS, 0, sizeof(context_MPS));
265     memset(prev_bits, 0, sizeof(prev_bits));
266         
267     switch(bitplane_type){
268       case 0:
269         while(1) {
270             for(byte1=byte2=0, bit=0x80; bit; bit>>=1){
271                 if(GetBit(0)) byte1 |= bit;
272                 if(GetBit(1)) byte2 |= bit;
273             }
274             *(out++)=byte1;
275             if(!--len) return;
276             *(out++)=byte2;
277             if(!--len) return;
278         }
279         break;
280       case 1:
281         i=plane=0;
282         while(1) {
283             for(byte1=byte2=0, bit=0x80; bit; bit>>=1){
284                 if(GetBit(plane)) byte1 |= bit;
285                 if(GetBit(plane+1)) byte2 |= bit;
286             }
287             *(out++)=byte1;
288             if(!--len) return;
289             *(out++)=byte2;
290             if(!--len) return;
291             if(!(i+=32)) plane = (plane+2)&7;
292         }
293         break;
294       case 2:
295         i=plane=0;
296         while(1) {
297             for(byte1=byte2=0, bit=0x80; bit; bit>>=1){
298                 if(GetBit(plane)) byte1 |= bit;
299                 if(GetBit(plane+1)) byte2 |= bit;
300             }
301             *(out++)=byte1;
302             if(!--len) return;
303             *(out++)=byte2;
304             if(!--len) return;
305             if(!(i+=32)) plane ^= 2;
306         }
307         break;
308       case 3:
309         do {
310             for(byte1=plane=0, bit=1; bit; bit<<=1, plane++){
311                 if(GetBit(plane)) byte1 |= bit;
312             }
313             *(out++)=byte1;
314         } while(--len);
315         break;
316     }
317 }
318
319 static uint8 cur_plane;
320 static uint8 num_bits;
321 static uint8 next_byte;
322
323 void SDD1_init(uint8 *in){
324     bitplane_type=in[0]>>6;
325
326     switch(in[0]&0x30){
327       case 0x00:
328         high_context_bits=0x01c0;
329         low_context_bits =0x0001;
330         break;
331       case 0x10:
332         high_context_bits=0x0180;
333         low_context_bits =0x0001;
334         break;
335       case 0x20:
336         high_context_bits=0x00c0;
337         low_context_bits =0x0001;
338         break;
339       case 0x30:
340         high_context_bits=0x0180;
341         low_context_bits =0x0003;
342         break;
343     }
344
345     in_stream=(in[0]<<11) | (in[1]<<3);
346     valid_bits=5;
347     in_buf=in+2;
348     memset(bit_ctr, 0, sizeof(bit_ctr));
349     memset(context_states, 0, sizeof(context_states));
350     memset(context_MPS, 0, sizeof(context_MPS));
351     memset(prev_bits, 0, sizeof(prev_bits));
352
353     cur_plane=0;
354     num_bits=0;
355 }
356
357 uint8 SDD1_get_byte(void){
358     uint8 bit;
359     uint8 byte=0;
360     
361     switch(bitplane_type){
362       case 0:
363         num_bits+=16;
364         if(num_bits&16){
365             next_byte=0;
366             for(bit=0x80; bit; bit>>=1){
367                 if(GetBit(0)) byte |= bit;
368                 if(GetBit(1)) next_byte |= bit;
369             }
370             return byte;
371         } else {
372             return next_byte;
373         }
374
375       case 1:
376         num_bits+=16;
377         if(num_bits&16){
378             next_byte=0;
379             for(bit=0x80; bit; bit>>=1){
380                 if(GetBit(cur_plane)) byte |= bit;
381                 if(GetBit(cur_plane+1)) next_byte |= bit;
382             }
383             return byte;
384         } else {
385             if(!num_bits) cur_plane = (cur_plane+2)&7;
386             return next_byte;
387         }
388
389       case 2:
390         num_bits+=16;
391         if(num_bits&16){
392             next_byte=0;
393             for(bit=0x80; bit; bit>>=1){
394                 if(GetBit(cur_plane)) byte |= bit;
395                 if(GetBit(cur_plane+1)) next_byte |= bit;
396             }
397             return byte;
398         } else {
399             if(!num_bits) cur_plane ^= 2;
400             return next_byte;
401         }
402
403       case 3:
404         for(cur_plane=0, bit=1; bit; bit<<=1, cur_plane++){
405             if(GetBit(cur_plane)) byte |= bit;
406         }
407         return byte;
408
409       default:
410         /* should never happen */
411         return 0;
412     }
413 }
414