Added AI by Ricardo Cruz. This also adds mouse controls.
[crow/jumpnbump.git] / filter.c
1 /*
2  * filter.c
3  * Copyright (C) 2003 Florian Schulze <crow@icculus.org>
4  *
5  * This file is part of Jump'n'Bump.
6  *
7  * Jump'n'Bump is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * Jump'n'Bump is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 /*
23  The following scaling filter is called advancedmame2x.
24  The implementation found here was possible because of the great ideas of
25  Lucas Pope.
26  */
27
28 typedef unsigned char byte;
29 static int scale2x_inited = 0;
30 static byte lookup_map[4*16];
31
32 void init_scale2x(void)
33 {
34         int i;
35
36         if (scale2x_inited)
37                 return;
38
39         //-------------------------------------------------------------------------  
40         // scale2x takes the following source:
41         // A B C
42         // D E F
43         // G H I
44         //
45         // and doubles the size of E to produce:
46         // E0 E1
47         // E2 E3
48         //
49         //  E0 = D == B && B != F && D != H ? D : E;
50         //  E1 = B == F && B != D && F != H ? F : E;
51         //  E2 = D == H && D != B && H != F ? D : E;
52         //  E3 = H == F && D != H && B != F ? F : E;
53         //
54         // to make this comparison regimen faster, we encode source color
55         // equivalency into a single byte with the getCode() macro
56         //
57         // #define getCode(b,f,h,d) ( (b == f)<<0 | (f == h)<<1 | (h == d)<<2 | (d == b)<<3 )
58   
59         // encode the scale2x conditionals into a lookup code
60         for (i=0; i<16; i++) {
61                 //  E0 = D == B && B != F && D != H ? D : E; // 10-0 => 1000 or 1010 => 8 or A
62                 lookup_map[0*16+i] = (i == 0x8 || i == 0xA) ? 0 : 1;
63                 //  E1 = B == F && B != D && F != H ? F : E; // 0-01 => 0101 or 0001 => 5 or 1
64                 lookup_map[1*16+i] = (i == 0x5 || i == 0x1) ? 2 : 1;
65                 //  E2 = D == H && D != B && H != F ? D : E; // 010- => 0101 or 0100 => 5 or 4
66                 lookup_map[2*16+i] = (i == 0x4 || i == 0x5) ? 0 : 1;
67                 //  E3 = H == F && D != H && B != F ? F : E; // -010 => 1010 or 0010 => A or 2
68                 lookup_map[3*16+i] = (i == 0xA || i == 0x2) ? 2 : 1;
69         }
70 }
71
72 void do_scale2x(unsigned char *src,
73                 int src_width,
74                 int src_height,
75                 unsigned char *dst)
76 {
77         int x;
78         int y;
79         int dst_width = src_width * 2;
80         int dst_height = src_height * 2;
81         int code;
82         byte rowColors[3];
83         byte *e0;
84         byte *e1;
85         byte *e2;
86         byte *e3;
87
88         if (!scale2x_inited)
89                 init_scale2x();
90
91         // special top case - b is always unknown
92         {
93                 byte *d;
94                 byte *e;
95                 byte *f;
96                 byte *h;
97
98                 e0 = &dst[0];
99                 e1 = &dst[1];
100                 e2 = &dst[dst_width];
101                 e3 = &dst[dst_width + 1];
102                 e = &src[0];
103                 f = &src[1];
104                 h = &src[src_width];
105
106                 // special left case - d is unknown
107                 rowColors[0] = *e;
108                 rowColors[1] = *e;
109                 rowColors[2] = *f;
110                 code = ( (*f == *h)<<1 );
111                 *e0 = rowColors[lookup_map[0*16+code]];
112                 *e1 = rowColors[lookup_map[1*16+code]];
113                 *e2 = rowColors[lookup_map[2*16+code]];
114                 *e3 = rowColors[lookup_map[3*16+code]];
115                 e++; f++; h++;
116                 d = &src[src_width]; // (src_width - 1) + 1
117                 e0+=2; e1+=2; e2+=2; e3+=2;
118
119                 // normal case
120                 for (x=1; x<(src_width-1); x++) {
121                         rowColors[0] = *d;
122                         rowColors[1] = *e;
123                         rowColors[2] = *f;
124                         code = ( (*f == *h)<<1 | (*h == *d)<<2 );
125                         *e0 = rowColors[lookup_map[0*16+code]];
126                         *e1 = rowColors[lookup_map[1*16+code]];
127                         *e2 = rowColors[lookup_map[2*16+code]];
128                         *e3 = rowColors[lookup_map[3*16+code]];
129                         d++; e++; f++; h++;
130                         e0+=2; e1+=2; e2+=2; e3+=2;
131                 }
132
133                 // special right case - f is unknown
134                 rowColors[0] = *d;
135                 rowColors[1] = *e;
136                 rowColors[2] = *e;
137                 code = ( (*h == *d)<<2 );
138                 *e0 = rowColors[lookup_map[0*16+code]];
139                 *e1 = rowColors[lookup_map[1*16+code]];
140                 *e2 = rowColors[lookup_map[2*16+code]];
141                 *e3 = rowColors[lookup_map[3*16+code]];
142         }
143
144         // top and bottom always known
145         for (y=1; y<(src_height-1); y++) {
146                 byte *b;
147                 byte *d;
148                 byte *e;
149                 byte *f;
150                 byte *h;
151
152                 e0 = &dst[y*dst_width*2];
153                 e1 = &dst[y*dst_width*2 + 1];
154                 e2 = &dst[y*dst_width*2 + dst_width];
155                 e3 = &dst[y*dst_width*2 + dst_width + 1];
156                 b = &src[y * src_width - src_width];
157                 e = &src[y * src_width];
158                 f = &src[y * src_width + 1];
159                 h = &src[y * src_width + src_width];
160
161                 // special left case - d is unknown
162                 rowColors[0] = *e;
163                 rowColors[1] = *e;
164                 rowColors[2] = *f;
165                 code = ( (*b == *f)<<0 | (*f == *h)<<1 );
166                 *e0 = rowColors[lookup_map[0*16+code]];
167                 *e1 = rowColors[lookup_map[1*16+code]];
168                 *e2 = rowColors[lookup_map[2*16+code]];
169                 *e3 = rowColors[lookup_map[3*16+code]];
170                 b++; e++; f++; h++;
171                 d = &src[y * src_width]; // (y * src_width - 1) + 1
172                 e0+=2; e1+=2; e2+=2; e3+=2;
173
174                 // normal case
175                 for (x=1; x<(src_width-1); x++) {
176                         rowColors[0] = *d;
177                         rowColors[1] = *e;
178                         rowColors[2] = *f;
179                         code = ( (*b == *f)<<0 | (*f == *h)<<1 | (*h == *d)<<2 | (*d == *b)<<3 );
180                         *e0 = rowColors[lookup_map[0*16+code]];
181                         *e1 = rowColors[lookup_map[1*16+code]];
182                         *e2 = rowColors[lookup_map[2*16+code]];
183                         *e3 = rowColors[lookup_map[3*16+code]];
184                         b++; d++; e++; f++; h++;
185                         e0+=2; e1+=2; e2+=2; e3+=2;
186                 }
187
188                 // special right case - f is unknown
189                 rowColors[0] = *d;
190                 rowColors[1] = *e;
191                 rowColors[2] = *e;
192                 code = ( (*h == *d)<<2 | (*d == *b)<<3 );
193                 *e0 = rowColors[lookup_map[0*16+code]];
194                 *e1 = rowColors[lookup_map[1*16+code]];
195                 *e2 = rowColors[lookup_map[2*16+code]];
196                 *e3 = rowColors[lookup_map[3*16+code]];
197         }
198
199         // special bottom case - h is always unknown
200         {
201                 byte *b;
202                 byte *d;
203                 byte *e;
204                 byte *f;
205
206                 e0 = &dst[y*dst_width*2];
207                 e1 = &dst[y*dst_width*2 + 1];
208                 e2 = &dst[y*dst_width*2 + dst_width];
209                 e3 = &dst[y*dst_width*2 + dst_width + 1];
210                 b = &src[y * src_width - src_width];
211                 e = &src[y * src_width];
212                 f = &src[y * src_width + 1];
213
214                 // special left case - d is unknown
215                 rowColors[0] = *e;
216                 rowColors[1] = *e;
217                 rowColors[2] = *f;
218                 code = ( (*b == *f)<<0 );
219                 *e0 = rowColors[lookup_map[0*16+code]];
220                 *e1 = rowColors[lookup_map[1*16+code]];
221                 *e2 = rowColors[lookup_map[2*16+code]];
222                 *e3 = rowColors[lookup_map[3*16+code]];
223                 b++; e++; f++;
224                 d = &src[y * src_width]; // (y * src_width - 1) + 1
225                 e0+=2; e1+=2; e2+=2; e3+=2;
226
227                 // normal case
228                 for (x=1; x<(src_width-1); x++) {
229                         rowColors[0] = *d;
230                         rowColors[1] = *e;
231                         rowColors[2] = *f;
232                         code = ( (*b == *f)<<0 | (*d == *b)<<3 );
233                         *e0 = rowColors[lookup_map[0*16+code]];
234                         *e1 = rowColors[lookup_map[1*16+code]];
235                         *e2 = rowColors[lookup_map[2*16+code]];
236                         *e3 = rowColors[lookup_map[3*16+code]];
237                         b++; d++; e++; f++;
238                         e0+=2; e1+=2; e2+=2; e3+=2;
239                 }
240
241                 // special right case - f is unknown
242                 rowColors[0] = *d;
243                 rowColors[1] = *e;
244                 rowColors[2] = *e;
245                 code = ( (*d == *b)<<3 );
246                 *e0 = rowColors[lookup_map[0*16+code]];
247                 *e1 = rowColors[lookup_map[1*16+code]];
248                 *e2 = rowColors[lookup_map[2*16+code]];
249                 *e3 = rowColors[lookup_map[3*16+code]];
250         }
251 }