3 * Copyright (C) 2003 Florian Schulze <crow@icculus.org>
5 * This file is part of Jump'n'Bump.
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.
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.
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
23 The following scaling filter is called advancedmame2x.
24 The implementation found here was possible because of the great ideas of
28 typedef unsigned char byte
;
29 static int scale2x_inited
= 0;
30 static byte lookup_map
[4*16];
32 void init_scale2x(void)
39 //-------------------------------------------------------------------------
40 // scale2x takes the following source:
45 // and doubles the size of E to produce:
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;
54 // to make this comparison regimen faster, we encode source color
55 // equivalency into a single byte with the getCode() macro
57 // #define getCode(b,f,h,d) ( (b == f)<<0 | (f == h)<<1 | (h == d)<<2 | (d == b)<<3 )
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;
72 void do_scale2x(unsigned char *src
,
79 int dst_width
= src_width
* 2;
80 int dst_height
= src_height
* 2;
91 // special top case - b is always unknown
100 e2
= &dst
[dst_width
];
101 e3
= &dst
[dst_width
+ 1];
106 // special left case - d is unknown
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
]];
116 d
= &src
[src_width
]; // (src_width - 1) + 1
117 e0
+=2; e1
+=2; e2
+=2; e3
+=2;
120 for (x
=1; x
<(src_width
-1); x
++) {
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
]];
130 e0
+=2; e1
+=2; e2
+=2; e3
+=2;
133 // special right case - f is unknown
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
]];
144 // top and bottom always known
145 for (y
=1; y
<(src_height
-1); y
++) {
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
];
161 // special left case - d is unknown
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
]];
171 d
= &src
[y
* src_width
]; // (y * src_width - 1) + 1
172 e0
+=2; e1
+=2; e2
+=2; e3
+=2;
175 for (x
=1; x
<(src_width
-1); x
++) {
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;
188 // special right case - f is unknown
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
]];
199 // special bottom case - h is always unknown
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];
214 // special left case - d is unknown
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
]];
224 d
= &src
[y
* src_width
]; // (y * src_width - 1) + 1
225 e0
+=2; e1
+=2; e2
+=2; e3
+=2;
228 for (x
=1; x
<(src_width
-1); x
++) {
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
]];
238 e0
+=2; e1
+=2; e2
+=2; e3
+=2;
241 // special right case - f is unknown
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
]];