1 /* scalers.c: the actual graphics scalers
2 * Copyright (C) 2003-2008 Fredrick Meunier, Philip Kendall, Gergely Szasz
3 *
4 * $Id: scalers.c 4624 2012-01-09 20:59:35Z pak21 $
5 *
6 * Originally taken from ScummVM - Scumm Interpreter
7 * Copyright (C) 2001 Ludvig Strigeus
8 * Copyright (C) 2001-2003 The ScummVM project
9 *
10 * HQ2x and HQ3x scalers taken from HiEnd3D Demos (http://www.hiend3d.com)
11 * Copyright (C) 2003 MaxSt ( maxst@hiend3d.com )
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 *
27 */
28
29 #include <config.h>
30
31 #include <string.h>
32
33 #include <libspectrum.h>
34
35 #include "scaler.h"
36 #include "scaler_internals.h"
37 #include "settings.h"
38 #include "ui/ui.h"
39 #include "ui/uidisplay.h"
40
41 #ifndef MIN
42 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
43 #endif
44
45 #ifndef ABS
46 #define ABS(x) ((x)>=0?(x):-(x))
47 #endif
48
49 /* The actual code for the scalers starts here */
50
51 #if SCALER_DATA_SIZE == 2
52
53 typedef libspectrum_word scaler_data_type;
54 #define FUNCTION( name ) name##_16
55
56 static libspectrum_dword colorMask;
57 static libspectrum_dword lowPixelMask;
58 static libspectrum_dword qcolorMask;
59 static libspectrum_dword qlowpixelMask;
60 static libspectrum_dword redblueMask;
61 static libspectrum_dword redblue8_Mask;
62 static libspectrum_dword redblue16_Mask;
63 static libspectrum_dword redMask;
64 static libspectrum_dword greenMask;
65 static libspectrum_dword green8_Mask;
66 static libspectrum_dword green16_Mask;
67 static libspectrum_dword blueMask;
68 static int green6bit;
69
70 static const libspectrum_word dotmatrix_565[16] = {
71 0x01E0, 0x0007, 0x3800, 0x0000,
72 0x39E7, 0x0000, 0x39E7, 0x0000,
73 0x3800, 0x0000, 0x01E0, 0x0007,
74 0x39E7, 0x0000, 0x39E7, 0x0000
75 };
76 static const libspectrum_word dotmatrix_555[16] = {
77 0x00E0, 0x0007, 0x1C00, 0x0000,
78 0x1CE7, 0x0000, 0x1CE7, 0x0000,
79 0x1C00, 0x0000, 0x00E0, 0x0007,
80 0x1CE7, 0x0000, 0x1CE7, 0x0000
81 };
82 static const libspectrum_word *dotmatrix;
83
84 int
scaler_select_bitformat(libspectrum_dword BitFormat)85 scaler_select_bitformat( libspectrum_dword BitFormat )
86 {
87 switch( BitFormat ) {
88
89 /* FIXME(?): there is an assumption here that our colour fields
90 are (*) xxxx|xyyy|yyyz|zzzz for the 565 mode
91 and (*) xxxx|xyyy|yyzz|zzz0 for the 555 mode, where (*) is the
92 least significant bit on LSB machines and the most significant
93 bit on MSB machines. This is currently (April 2003) OK as the
94 only user interface to use this code is SDL, which hides all
95 variation in SDL_MapRGB(3), but be very careful (especially
96 about endianness) if we ever use the "interpolating" scalers
97 from another user interface */
98
99 case 565:
100 colorMask = 0x0000F7DE;
101 lowPixelMask = 0x00000821;
102 qcolorMask = 0x0000E79C;
103 qlowpixelMask = 0x00001863;
104 redblueMask = 0x0000F81F;
105 redblue8_Mask = 0x0007C0F8;
106 redblue16_Mask = 0x000F81F0;
107 green6bit = 1;
108 redMask = 0x0000001F;
109 greenMask = 0x000007E0;
110 green8_Mask = 0x00003F00;
111 green16_Mask = 0x00007E00;
112 blueMask = 0x0000F800;
113 dotmatrix = dotmatrix_565;
114 break;
115
116 case 555:
117 colorMask = 0x00007BDE;
118 lowPixelMask = 0x00000421;
119 qcolorMask = 0x0000739C;
120 qlowpixelMask = 0x00000C63;
121 redblueMask = 0x00007C1F;
122 redblue8_Mask = 0x0003E0F8;
123 redblue16_Mask = 0x0007C1F0;
124 green6bit = 0;
125 redMask = 0x0000001F;
126 greenMask = 0x000003E0;
127 green8_Mask = 0x00001F00;
128 green16_Mask = 0x00003E00;
129 blueMask = 0x00007C00;
130 dotmatrix = dotmatrix_555;
131 break;
132
133 default:
134 ui_error( UI_ERROR_ERROR, "unknown bitformat %d", BitFormat );
135 return 1;
136
137 }
138
139 return 0;
140 }
141
142 #elif SCALER_DATA_SIZE == 4 /* #if SCALER_DATA_SIZE == 2 */
143
144 typedef libspectrum_dword scaler_data_type;
145 #define FUNCTION( name ) name##_32
146
147 /* The assumption here is that the colour fields are laid out in
148 memory as (LSB) red|green|blue|padding (MSB). We wish to access
149 these as 32-bit entities, so make sure we get our masks the right
150 way round. */
151
152 #ifdef WORDS_BIGENDIAN
153
154 static const libspectrum_dword colorMask = 0xFEFEFE00;
155 static const libspectrum_dword lowPixelMask = 0x01010100;
156 static const libspectrum_dword qcolorMask = 0xFCFCFC00;
157 static const libspectrum_dword qlowpixelMask = 0x03030300;
158 static const libspectrum_qword redblueMask = 0xFF00FF00;
159 static const libspectrum_dword redblue8_Mask = 0xF807F807;
160 static const libspectrum_dword redblue16_Mask = 0x0FF00FF0;
161 static const libspectrum_dword redMask = 0xFF000000;
162 static const libspectrum_dword greenMask = 0x00FF0000;
163 static const libspectrum_dword blueMask = 0x0000FF00;
164 static const libspectrum_dword green8_Mask = 0x008F0700;
165 static const libspectrum_dword green16_Mask = 0x000FF000;
166
167 static const libspectrum_dword dotmatrix[16] = {
168 0x003F0000, 0x00003F00, 0x3F000000, 0x00000000,
169 0x3F3F3F00, 0x00000000, 0x3F3F3F00, 0x00000000,
170 0x3F000000, 0x00000000, 0x003F0000, 0x00003F00,
171 0x3F3F3F00, 0x00000000, 0x3F3F3F00, 0x00000000
172 };
173
174 #else /* #ifdef WORDS_BIGENDIAN */
175
176 static const libspectrum_dword colorMask = 0x00FEFEFE;
177 static const libspectrum_dword lowPixelMask = 0x00010101;
178 static const libspectrum_dword qcolorMask = 0x00FCFCFC;
179 static const libspectrum_dword qlowpixelMask = 0x00030303;
180 static const libspectrum_qword redblueMask = 0x00FF00FF;
181 static const libspectrum_dword redblue8_Mask = 0x07F807F8;
182 static const libspectrum_dword redblue16_Mask = 0x0FF00FF0;
183 static const libspectrum_dword redMask = 0x000000FF;
184 static const libspectrum_dword greenMask = 0x0000FF00;
185 static const libspectrum_dword blueMask = 0x00FF0000;
186 static const libspectrum_dword green8_Mask = 0x0007F800;
187 static const libspectrum_dword green16_Mask = 0x000FF000;
188
189 static const libspectrum_dword dotmatrix[16] = {
190 0x00003F00, 0x003F0000, 0x0000003F, 0x00000000,
191 0x003F3F3F, 0x00000000, 0x003F3F3F, 0x00000000,
192 0x0000003F, 0x00000000, 0x00003F00, 0x003F0000,
193 0x003F3F3F, 0x00000000, 0x003F3F3F, 0x00000000
194 };
195
196 #endif /* #ifdef WORDS_BIGENDIAN */
197
198 #else /* #if SCALER_DATA_SIZE == 2 or 4 */
199 #error Unknown SCALER_DATA_SIZE
200 #endif /* #if SCALER_DATA_SIZE == 2 or 4 */
201
202 static inline int
GetResult(libspectrum_dword A,libspectrum_dword B,libspectrum_dword C,libspectrum_dword D)203 GetResult( libspectrum_dword A, libspectrum_dword B, libspectrum_dword C,
204 libspectrum_dword D )
205 {
206 const int ac = (A==C);
207 const int bc = (B==C);
208 const int x1 = ac;
209 const int y1 = (bc & !ac);
210 const int ad = (A==D);
211 const int bd = (B==D);
212 const int x2 = ad;
213 const int y2 = (bd & !ad);
214 const int x = x1+x2;
215 const int y = y1+y2;
216 static const int rmap[3][3] = {
217 {0, 0, -1},
218 {0, 0, -1},
219 {1, 1, 0}
220 };
221 return rmap[y][x];
222 }
223
224 static inline libspectrum_dword
INTERPOLATE(libspectrum_dword A,libspectrum_dword B)225 INTERPOLATE( libspectrum_dword A, libspectrum_dword B )
226 {
227 if (A != B) {
228 return (((A & colorMask) >> 1) + ((B & colorMask) >> 1) + (A & B & lowPixelMask));
229 } else
230 return A;
231 }
232
233 static inline libspectrum_dword
Q_INTERPOLATE(libspectrum_dword A,libspectrum_dword B,libspectrum_dword C,libspectrum_dword D)234 Q_INTERPOLATE( libspectrum_dword A, libspectrum_dword B, libspectrum_dword C,
235 libspectrum_dword D )
236 {
237 register libspectrum_dword x = ((A & qcolorMask) >> 2) +
238 ((B & qcolorMask) >> 2) + ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2);
239 register libspectrum_dword y = (A & qlowpixelMask) +
240 (B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask);
241
242 y = (y >> 2) & qlowpixelMask;
243 return x + y;
244 }
245
246 /* HQ scalers */
247 #define HQ_INTERPOLATE_1(A,B) Q_INTERPOLATE(A,A,A,B)
248
249 #define HQ_INTERPOLATE_2(A,B,C) Q_INTERPOLATE(A,A,B,C)
250
251 static inline libspectrum_dword
HQ_INTERPOLATE_3(libspectrum_dword A,libspectrum_dword B)252 HQ_INTERPOLATE_3( libspectrum_dword A, libspectrum_dword B )
253 {
254 return ( ( ( ( A & greenMask ) * 7 + ( B & greenMask) ) & green8_Mask ) +
255 ( ( ( A & redblueMask ) * 7 + ( B & redblueMask ) ) & redblue8_Mask )
256 ) >> 3;
257 }
258
259 static inline libspectrum_dword
HQ_INTERPOLATE_4(libspectrum_dword A,libspectrum_dword B,libspectrum_dword C)260 HQ_INTERPOLATE_4( libspectrum_dword A, libspectrum_dword B,
261 libspectrum_dword C )
262 {
263 return ( ( ( ( A & greenMask ) * 2 + ( ( B & greenMask) +
264 ( C & greenMask ) ) * 7 ) & green16_Mask) +
265 ( ( ( A & redblueMask ) * 2 + ( ( B & redblueMask ) +
266 ( C & redblueMask ) ) * 7 ) & redblue16_Mask ) ) >> 4;
267 }
268
269 #define HQ_INTERPOLATE_5(A,B) INTERPOLATE(A,B)
270
271 static inline libspectrum_dword
HQ_INTERPOLATE_6(libspectrum_dword A,libspectrum_dword B,libspectrum_dword C)272 HQ_INTERPOLATE_6( libspectrum_dword A, libspectrum_dword B,
273 libspectrum_dword C )
274 {
275 return ( ( ( ( A & greenMask ) * 5 + ( B & greenMask) * 2 +
276 ( C & greenMask ) ) & green8_Mask) +
277 ( ( ( A & redblueMask ) * 5 + ( B & redblueMask ) * 2 +
278 ( C & redblueMask ) ) & redblue8_Mask ) ) >> 3;
279 }
280
281 static inline libspectrum_dword
HQ_INTERPOLATE_7(libspectrum_dword A,libspectrum_dword B,libspectrum_dword C)282 HQ_INTERPOLATE_7( libspectrum_dword A, libspectrum_dword B,
283 libspectrum_dword C )
284 {
285 return ( ( ( ( A & greenMask ) * 6 + ( B & greenMask) +
286 ( C & greenMask ) ) & green8_Mask) +
287 ( ( ( A & redblueMask ) * 6 + ( B & redblueMask ) +
288 ( C & redblueMask ) ) & redblue8_Mask ) ) >> 3;
289 }
290
291 static inline libspectrum_dword
HQ_INTERPOLATE_9(libspectrum_dword A,libspectrum_dword B,libspectrum_dword C)292 HQ_INTERPOLATE_9( libspectrum_dword A, libspectrum_dword B,
293 libspectrum_dword C )
294 {
295 return ( ( ( ( A & greenMask ) * 2 + ( ( B & greenMask) +
296 ( C & greenMask ) ) * 3 ) & green8_Mask) +
297 ( ( ( A & redblueMask ) * 2 + ( ( B & redblueMask ) +
298 ( C & redblueMask ) ) * 3 ) & redblue8_Mask ) ) >> 3;
299 }
300
301 static inline libspectrum_dword
HQ_INTERPOLATE_10(libspectrum_dword A,libspectrum_dword B,libspectrum_dword C)302 HQ_INTERPOLATE_10( libspectrum_dword A, libspectrum_dword B,
303 libspectrum_dword C )
304 {
305 return ( ( ( ( A & greenMask ) * 14 + ( B & greenMask) +
306 ( C & greenMask ) ) & green16_Mask) +
307 ( ( ( A & redblueMask ) * 14 + ( B & redblueMask ) +
308 ( C & redblueMask ) ) & redblue16_Mask ) ) >> 4;
309 }
310
311 /* dstPtr */
312 #define HQ_PIXEL00_0 w[5]
313 #define HQ_PIXEL00_10 HQ_INTERPOLATE_1(w[5], w[1])
314 #define HQ_PIXEL00_11 HQ_INTERPOLATE_1(w[5], w[4])
315 #define HQ_PIXEL00_12 HQ_INTERPOLATE_1(w[5], w[2])
316 #define HQ_PIXEL00_20 HQ_INTERPOLATE_2(w[5], w[4], w[2])
317 #define HQ_PIXEL00_21 HQ_INTERPOLATE_2(w[5], w[1], w[2])
318 #define HQ_PIXEL00_22 HQ_INTERPOLATE_2(w[5], w[1], w[4])
319 #define HQ_PIXEL00_60 HQ_INTERPOLATE_6(w[5], w[2], w[4])
320 #define HQ_PIXEL00_61 HQ_INTERPOLATE_6(w[5], w[4], w[2])
321 #define HQ_PIXEL00_70 HQ_INTERPOLATE_7(w[5], w[4], w[2])
322 #define HQ_PIXEL00_90 HQ_INTERPOLATE_9(w[5], w[4], w[2])
323 #define HQ_PIXEL00_100 HQ_INTERPOLATE_10(w[5], w[4], w[2])
324 /* +1 */
325 #define HQ_PIXEL01_0 w[5]
326 #define HQ_PIXEL01_10 HQ_INTERPOLATE_1(w[5], w[3])
327 #define HQ_PIXEL01_11 HQ_INTERPOLATE_1(w[5], w[2])
328 #define HQ_PIXEL01_12 HQ_INTERPOLATE_1(w[5], w[6])
329 #define HQ_PIXEL01_20 HQ_INTERPOLATE_2(w[5], w[2], w[6])
330 #define HQ_PIXEL01_21 HQ_INTERPOLATE_2(w[5], w[3], w[6])
331 #define HQ_PIXEL01_22 HQ_INTERPOLATE_2(w[5], w[3], w[2])
332 #define HQ_PIXEL01_60 HQ_INTERPOLATE_6(w[5], w[6], w[2])
333 #define HQ_PIXEL01_61 HQ_INTERPOLATE_6(w[5], w[2], w[6])
334 #define HQ_PIXEL01_70 HQ_INTERPOLATE_7(w[5], w[2], w[6])
335 #define HQ_PIXEL01_90 HQ_INTERPOLATE_9(w[5], w[2], w[6])
336 #define HQ_PIXEL01_100 HQ_INTERPOLATE_10(w[5], w[2], w[6])
337 /* +dstPitch */
338 #define HQ_PIXEL10_0 w[5]
339 #define HQ_PIXEL10_10 HQ_INTERPOLATE_1(w[5], w[7])
340 #define HQ_PIXEL10_11 HQ_INTERPOLATE_1(w[5], w[8])
341 #define HQ_PIXEL10_12 HQ_INTERPOLATE_1(w[5], w[4])
342 #define HQ_PIXEL10_20 HQ_INTERPOLATE_2(w[5], w[8], w[4])
343 #define HQ_PIXEL10_21 HQ_INTERPOLATE_2(w[5], w[7], w[4])
344 #define HQ_PIXEL10_22 HQ_INTERPOLATE_2(w[5], w[7], w[8])
345 #define HQ_PIXEL10_60 HQ_INTERPOLATE_6(w[5], w[4], w[8])
346 #define HQ_PIXEL10_61 HQ_INTERPOLATE_6(w[5], w[8], w[4])
347 #define HQ_PIXEL10_70 HQ_INTERPOLATE_7(w[5], w[8], w[4])
348 #define HQ_PIXEL10_90 HQ_INTERPOLATE_9(w[5], w[8], w[4])
349 #define HQ_PIXEL10_100 HQ_INTERPOLATE_10(w[5], w[8], w[4])
350 /* +dstPitch+1*/
351 #define HQ_PIXEL11_0 w[5]
352 #define HQ_PIXEL11_10 HQ_INTERPOLATE_1(w[5], w[9])
353 #define HQ_PIXEL11_11 HQ_INTERPOLATE_1(w[5], w[6])
354 #define HQ_PIXEL11_12 HQ_INTERPOLATE_1(w[5], w[8])
355 #define HQ_PIXEL11_20 HQ_INTERPOLATE_2(w[5], w[6], w[8])
356 #define HQ_PIXEL11_21 HQ_INTERPOLATE_2(w[5], w[9], w[8])
357 #define HQ_PIXEL11_22 HQ_INTERPOLATE_2(w[5], w[9], w[6])
358 #define HQ_PIXEL11_60 HQ_INTERPOLATE_6(w[5], w[8], w[6])
359 #define HQ_PIXEL11_61 HQ_INTERPOLATE_6(w[5], w[6], w[8])
360 #define HQ_PIXEL11_70 HQ_INTERPOLATE_7(w[5], w[6], w[8])
361 #define HQ_PIXEL11_90 HQ_INTERPOLATE_9(w[5], w[6], w[8])
362 #define HQ_PIXEL11_100 HQ_INTERPOLATE_10(w[5], w[6], w[8])
363
364 /* dstPtr */
365 #define HQ_PIXEL00_1M HQ_INTERPOLATE_1(w[5], w[1])
366 #define HQ_PIXEL00_1U HQ_INTERPOLATE_1(w[5], w[2])
367 #define HQ_PIXEL00_1L HQ_INTERPOLATE_1(w[5], w[4])
368 #define HQ_PIXEL00_2 HQ_INTERPOLATE_2(w[5], w[4], w[2])
369 #define HQ_PIXEL00_4 HQ_INTERPOLATE_4(w[5], w[4], w[2])
370 #define HQ_PIXEL00_5 HQ_INTERPOLATE_5(w[4], w[2])
371 #define HQ_PIXEL00_C w[5]
372 /* dstPtr+1*/
373 #define HQ_PIXEL01_1 HQ_INTERPOLATE_1(w[5], w[2])
374 #define HQ_PIXEL01_3 HQ_INTERPOLATE_3(w[5], w[2])
375 #define HQ_PIXEL01_6 HQ_INTERPOLATE_1(w[2], w[5])
376 #define HQ_PIXEL01_C w[5]
377 /* dstPtr+2*/
378 #define HQ_PIXEL02_1M HQ_INTERPOLATE_1(w[5], w[3])
379 #define HQ_PIXEL02_1U HQ_INTERPOLATE_1(w[5], w[2])
380 #define HQ_PIXEL02_1R HQ_INTERPOLATE_1(w[5], w[6])
381 #define HQ_PIXEL02_2 HQ_INTERPOLATE_2(w[5], w[2], w[6])
382 #define HQ_PIXEL02_4 HQ_INTERPOLATE_4(w[5], w[2], w[6])
383 #define HQ_PIXEL02_5 HQ_INTERPOLATE_5(w[2], w[6])
384 #define HQ_PIXEL02_C w[5]
385 /* + dstPitch*/
386 #define HQ_PIXEL10_1 HQ_INTERPOLATE_1(w[5], w[4])
387 #define HQ_PIXEL10_3 HQ_INTERPOLATE_3(w[5], w[4])
388 #define HQ_PIXEL10_6 HQ_INTERPOLATE_1(w[4], w[5])
389 #define HQ_PIXEL10_C w[5]
390 /* + dstPitch + 1 */
391 #define HQ_PIXEL11 w[5]
392 /* + dstPitch + 2 */
393 #define HQ_PIXEL12_1 HQ_INTERPOLATE_1(w[5], w[6])
394 #define HQ_PIXEL12_3 HQ_INTERPOLATE_3(w[5], w[6])
395 #define HQ_PIXEL12_6 HQ_INTERPOLATE_1(w[6], w[5])
396 #define HQ_PIXEL12_C w[5]
397 /* + 2*dstPitch */
398 #define HQ_PIXEL20_1M HQ_INTERPOLATE_1(w[5], w[7])
399 #define HQ_PIXEL20_1D HQ_INTERPOLATE_1(w[5], w[8])
400 #define HQ_PIXEL20_1L HQ_INTERPOLATE_1(w[5], w[4])
401 #define HQ_PIXEL20_2 HQ_INTERPOLATE_2(w[5], w[8], w[4])
402 #define HQ_PIXEL20_4 HQ_INTERPOLATE_4(w[5], w[8], w[4])
403 #define HQ_PIXEL20_5 HQ_INTERPOLATE_5(w[8], w[4])
404 #define HQ_PIXEL20_C w[5]
405 /* + 2*dstPitch + 1 */
406 #define HQ_PIXEL21_1 HQ_INTERPOLATE_1(w[5], w[8])
407 #define HQ_PIXEL21_3 HQ_INTERPOLATE_3(w[5], w[8])
408 #define HQ_PIXEL21_6 HQ_INTERPOLATE_1(w[8], w[5])
409 #define HQ_PIXEL21_C w[5]
410 /* + 2*dstPitch + 2 */
411 #define HQ_PIXEL22_1M HQ_INTERPOLATE_1(w[5], w[9])
412 #define HQ_PIXEL22_1D HQ_INTERPOLATE_1(w[5], w[8])
413 #define HQ_PIXEL22_1R HQ_INTERPOLATE_1(w[5], w[6])
414 #define HQ_PIXEL22_2 HQ_INTERPOLATE_2(w[5], w[6], w[8])
415 #define HQ_PIXEL22_4 HQ_INTERPOLATE_4(w[5], w[6], w[8])
416 #define HQ_PIXEL22_5 HQ_INTERPOLATE_5(w[6], w[8])
417 #define HQ_PIXEL22_C w[5]
418
419 #define HQ_trY 0x00000030
420 #define HQ_trU 0x00000007
421 #define HQ_trV 0x00000006
422
423 #define HQ_YUVDIFF(y1,u1,v1,y2,u2,v2) \
424 ( ( ABS( y1 - y2 ) > HQ_trY ) || \
425 ( ABS( u1 - u2 ) > HQ_trU ) || \
426 ( ABS( v1 - v2 ) > HQ_trV ) )
427
428 void
FUNCTION(scaler_Super2xSaI)429 FUNCTION( scaler_Super2xSaI )( const libspectrum_byte *srcPtr,
430 libspectrum_dword srcPitch,
431 libspectrum_byte *dstPtr,
432 libspectrum_dword dstPitch,
433 int width, int height )
434 {
435 const scaler_data_type *bP;
436 scaler_data_type *dP;
437
438 {
439 const libspectrum_dword nextlineSrc = srcPitch / sizeof( scaler_data_type );
440 libspectrum_dword nextDstLine = dstPitch / sizeof( scaler_data_type );
441 size_t i;
442
443 while (height--) {
444 bP = (const scaler_data_type*)srcPtr;
445 dP = (scaler_data_type*)dstPtr;
446
447 for( i = 0; i < width; ++i ) {
448 libspectrum_dword color4, color5, color6;
449 libspectrum_dword color1, color2, color3;
450 libspectrum_dword colorA0, colorA1, colorA2, colorA3, colorB0, colorB1, colorB2,
451 colorB3, colorS1, colorS2;
452 libspectrum_dword product1a, product1b, product2a, product2b;
453
454 /*--------------------------------------- B1 B2
455 4 5 6 S2
456 1 2 3 S1
457 A1 A2
458 */
459
460 colorB0 = *(bP - nextlineSrc - 1);
461 colorB1 = *(bP - nextlineSrc);
462 colorB2 = *(bP - nextlineSrc + 1);
463 colorB3 = *(bP - nextlineSrc + 2);
464
465 color4 = *(bP - 1);
466 color5 = *(bP);
467 color6 = *(bP + 1);
468 colorS2 = *(bP + 2);
469
470 color1 = *(bP + nextlineSrc - 1);
471 color2 = *(bP + nextlineSrc);
472 color3 = *(bP + nextlineSrc + 1);
473 colorS1 = *(bP + nextlineSrc + 2);
474
475 colorA0 = *(bP + 2 * nextlineSrc - 1);
476 colorA1 = *(bP + 2 * nextlineSrc);
477 colorA2 = *(bP + 2 * nextlineSrc + 1);
478 colorA3 = *(bP + 2 * nextlineSrc + 2);
479
480 /*--------------------------------------*/
481 if (color2 == color6 && color5 != color3) {
482 product2b = product1b = color2;
483 } else if (color5 == color3 && color2 != color6) {
484 product2b = product1b = color5;
485 } else if (color5 == color3 && color2 == color6) {
486 register int r = 0;
487
488 r += GetResult(color6, color5, color1, colorA1);
489 r += GetResult(color6, color5, color4, colorB1);
490 r += GetResult(color6, color5, colorA2, colorS1);
491 r += GetResult(color6, color5, colorB2, colorS2);
492
493 if (r > 0)
494 product2b = product1b = color6;
495 else if (r < 0)
496 product2b = product1b = color5;
497 else {
498 product2b = product1b = INTERPOLATE(color5, color6);
499 }
500 } else {
501 if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0)
502 product2b = Q_INTERPOLATE(color3, color3, color3, color2);
503 else if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3)
504 product2b = Q_INTERPOLATE(color2, color2, color2, color3);
505 else
506 product2b = INTERPOLATE(color2, color3);
507
508 if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0)
509 product1b = Q_INTERPOLATE(color6, color6, color6, color5);
510 else if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3)
511 product1b = Q_INTERPOLATE(color6, color5, color5, color5);
512 else
513 product1b = INTERPOLATE(color5, color6);
514 }
515
516 if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2)
517 product2a = INTERPOLATE(color2, color5);
518 else if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0)
519 product2a = INTERPOLATE(color2, color5);
520 else
521 product2a = color2;
522
523 if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2)
524 product1a = INTERPOLATE(color2, color5);
525 else if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0)
526 product1a = INTERPOLATE(color2, color5);
527 else
528 product1a = color5;
529
530 *dP = (scaler_data_type)product1a;
531 *(dP+nextDstLine) = (scaler_data_type)product2a;
532 dP++;
533 *dP = (scaler_data_type)product1b;
534 *(dP+nextDstLine) = (scaler_data_type)product2b;
535 dP++;
536
537 bP++;
538 }
539
540 srcPtr += srcPitch;
541 dstPtr += dstPitch * 2;
542 }
543 }
544 }
545
546 void
FUNCTION(scaler_SuperEagle)547 FUNCTION( scaler_SuperEagle )( const libspectrum_byte *srcPtr,
548 libspectrum_dword srcPitch,
549 libspectrum_byte *dstPtr,
550 libspectrum_dword dstPitch,
551 int width, int height )
552 {
553 const scaler_data_type *bP;
554 scaler_data_type *dP;
555
556 {
557 size_t i;
558 const libspectrum_dword nextlineSrc = srcPitch / sizeof( scaler_data_type );
559 libspectrum_dword nextDstLine = dstPitch / sizeof( scaler_data_type );
560
561 while (height--) {
562 bP = (const scaler_data_type*)srcPtr;
563 dP = (scaler_data_type*)dstPtr;
564 for( i = 0; i < width; ++i ) {
565 libspectrum_dword color4, color5, color6;
566 libspectrum_dword color1, color2, color3;
567 libspectrum_dword colorA1, colorA2, colorB1, colorB2, colorS1, colorS2;
568 libspectrum_dword product1a, product1b, product2a, product2b;
569
570 colorB1 = *(bP - nextlineSrc);
571 colorB2 = *(bP - nextlineSrc + 1);
572
573 color4 = *(bP - 1);
574 color5 = *(bP);
575 color6 = *(bP + 1);
576 colorS2 = *(bP + 2);
577
578 color1 = *(bP + nextlineSrc - 1);
579 color2 = *(bP + nextlineSrc);
580 color3 = *(bP + nextlineSrc + 1);
581 colorS1 = *(bP + nextlineSrc + 2);
582
583 colorA1 = *(bP + 2 * nextlineSrc);
584 colorA2 = *(bP + 2 * nextlineSrc + 1);
585
586 /* -------------------------------------- */
587 if (color5 != color3 )
588 {
589 if (color2 == color6)
590 {
591 product1b = product2a = color2;
592 if ((color1 == color2) || (color6 == colorB2)) {
593 product1a = INTERPOLATE(color2, color5);
594 product1a = INTERPOLATE(color2, product1a);
595 } else {
596 product1a = INTERPOLATE(color5, color6);
597 }
598
599 if ((color6 == colorS2) || (color2 == colorA1)) {
600 product2b = INTERPOLATE(color2, color3);
601 product2b = INTERPOLATE(color2, product2b);
602 } else {
603 product2b = INTERPOLATE(color2, color3);
604 }
605 }
606 else
607 {
608 product2b = product1a = INTERPOLATE(color2, color6);
609 product2b = Q_INTERPOLATE(color3, color3, color3, product2b);
610 product1a = Q_INTERPOLATE(color5, color5, color5, product1a);
611
612 product2a = product1b = INTERPOLATE(color5, color3);
613 product2a = Q_INTERPOLATE(color2, color2, color2, product2a);
614 product1b = Q_INTERPOLATE(color6, color6, color6, product1b);
615 }
616 }
617 else /*if (color5 == color3) */
618 {
619 if (color2 != color6)
620 {
621 product2b = product1a = color5;
622
623 if ((colorB1 == color5) || (color3 == colorS1)) {
624 product1b = INTERPOLATE(color5, color6);
625 product1b = INTERPOLATE(color5, product1b);
626 } else {
627 product1b = INTERPOLATE(color5, color6);
628 }
629
630 if ((color3 == colorA2) || (color4 == color5)) {
631 product2a = INTERPOLATE(color5, color2);
632 product2a = INTERPOLATE(color5, product2a);
633 } else {
634 product2a = INTERPOLATE(color2, color3);
635 }
636
637 }
638 else /* if (color2 != color6) */
639 {
640 register int r = 0;
641
642 r += GetResult(color6, color5, color1, colorA1);
643 r += GetResult(color6, color5, color4, colorB1);
644 r += GetResult(color6, color5, colorA2, colorS1);
645 r += GetResult(color6, color5, colorB2, colorS2);
646
647 if (r > 0) {
648 product1b = product2a = color2;
649 product1a = product2b = INTERPOLATE(color5, color6);
650 } else if (r < 0) {
651 product2b = product1a = color5;
652 product1b = product2a = INTERPOLATE(color5, color6);
653 } else {
654 product2b = product1a = color5;
655 product1b = product2a = color2;
656 }
657 }
658 }
659
660 *dP = (scaler_data_type)product1a;
661 *(dP+nextDstLine) = (scaler_data_type)product2a;
662 dP++;
663 *dP = (scaler_data_type)product1b;
664 *(dP+nextDstLine) = (scaler_data_type)product2b;
665 dP++;
666
667 bP++;
668 }
669
670 srcPtr += srcPitch;
671 dstPtr += dstPitch * 2;
672 }
673 }
674 }
675
676 void
FUNCTION(scaler_2xSaI)677 FUNCTION( scaler_2xSaI )( const libspectrum_byte *srcPtr,
678 libspectrum_dword srcPitch, libspectrum_byte *dstPtr,
679 libspectrum_dword dstPitch,
680 int width, int height )
681 {
682 const scaler_data_type *bP;
683 scaler_data_type *dP;
684
685 {
686 libspectrum_dword nextlineSrc = srcPitch / sizeof( scaler_data_type );
687 libspectrum_dword nextDstLine = dstPitch / sizeof( scaler_data_type );
688
689 while (height--) {
690 size_t i;
691 bP = (const scaler_data_type*)srcPtr;
692 dP = (scaler_data_type*)dstPtr;
693
694 for( i = 0; i < width; ++i ) {
695
696 register libspectrum_dword colorA, colorB;
697 libspectrum_dword colorC, colorD, colorE, colorF, colorG, colorH,
698 colorI, colorJ, colorK, colorL, colorM, colorN, colorO;
699 libspectrum_dword product, product1, product2;
700
701 /*---------------------------------------
702 Map of the pixels: I|E F|J
703 G|A B|K
704 H|C D|L
705 M|N O|P
706
707 Note that P does not contribute to the algorithm
708 */
709 colorI = *(bP - nextlineSrc - 1);
710 colorE = *(bP - nextlineSrc);
711 colorF = *(bP - nextlineSrc + 1);
712 colorJ = *(bP - nextlineSrc + 2);
713
714 colorG = *(bP - 1);
715 colorA = *(bP);
716 colorB = *(bP + 1);
717 colorK = *(bP + 2);
718
719 colorH = *(bP + nextlineSrc - 1);
720 colorC = *(bP + nextlineSrc);
721 colorD = *(bP + nextlineSrc + 1);
722 colorL = *(bP + nextlineSrc + 2);
723
724 colorM = *(bP + 2 * nextlineSrc - 1);
725 colorN = *(bP + 2 * nextlineSrc);
726 colorO = *(bP + 2 * nextlineSrc + 1);
727
728 if ((colorA == colorD) && (colorB != colorC)) {
729 if (((colorA == colorE) && (colorB == colorL)) ||
730 ((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ))) {
731 product = colorA;
732 } else {
733 product = INTERPOLATE(colorA, colorB);
734 }
735
736 if (((colorA == colorG) && (colorC == colorO)) ||
737 ((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM))) {
738 product1 = colorA;
739 } else {
740 product1 = INTERPOLATE(colorA, colorC);
741 }
742 product2 = colorA;
743 } else if ((colorB == colorC) && (colorA != colorD)) {
744 if (((colorB == colorF) && (colorA == colorH)) ||
745 ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI))) {
746 product = colorB;
747 } else {
748 product = INTERPOLATE(colorA, colorB);
749 }
750
751 if (((colorC == colorH) && (colorA == colorF)) ||
752 ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI))) {
753 product1 = colorC;
754 } else {
755 product1 = INTERPOLATE(colorA, colorC);
756 }
757 product2 = colorB;
758 } else if ((colorA == colorD) && (colorB == colorC)) {
759 if (colorA == colorB) {
760 product = colorA;
761 product1 = colorA;
762 product2 = colorA;
763 } else {
764 register int r = 0;
765
766 product1 = INTERPOLATE(colorA, colorC);
767 product = INTERPOLATE(colorA, colorB);
768
769 r += GetResult(colorA, colorB, colorG, colorE);
770 r -= GetResult(colorB, colorA, colorK, colorF);
771 r -= GetResult(colorB, colorA, colorH, colorN);
772 r += GetResult(colorA, colorB, colorL, colorO);
773
774 if (r > 0)
775 product2 = colorA;
776 else if (r < 0)
777 product2 = colorB;
778 else {
779 product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD);
780 }
781 }
782 } else {
783 product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD);
784
785 if ((colorA == colorC) && (colorA == colorF)
786 && (colorB != colorE) && (colorB == colorJ)) {
787 product = colorA;
788 } else if ((colorB == colorE) && (colorB == colorD)
789 && (colorA != colorF) && (colorA == colorI)) {
790 product = colorB;
791 } else {
792 product = INTERPOLATE(colorA, colorB);
793 }
794
795 if ((colorA == colorB) && (colorA == colorH)
796 && (colorG != colorC) && (colorC == colorM)) {
797 product1 = colorA;
798 } else if ((colorC == colorG) && (colorC == colorD)
799 && (colorA != colorH) && (colorA == colorI)) {
800 product1 = colorC;
801 } else {
802 product1 = INTERPOLATE(colorA, colorC);
803 }
804 }
805
806 *dP = (scaler_data_type)colorA;
807 *(dP+nextDstLine) = (scaler_data_type)product1;
808 dP++;
809 *dP = (scaler_data_type)product;
810 *(dP+nextDstLine) = (scaler_data_type)product2;
811 dP++;
812
813 bP++;
814 }
815
816 srcPtr += srcPitch;
817 dstPtr += dstPitch * 2;
818 }
819 }
820 }
821
822 void
FUNCTION(scaler_AdvMame2x)823 FUNCTION( scaler_AdvMame2x )( const libspectrum_byte *srcPtr,
824 libspectrum_dword srcPitch,
825 libspectrum_byte *dstPtr,
826 libspectrum_dword dstPitch,
827 int width, int height )
828 {
829 unsigned int nextlineSrc = srcPitch / sizeof( scaler_data_type );
830 const scaler_data_type *p = (const scaler_data_type*) srcPtr;
831
832 unsigned int nextlineDst = dstPitch / sizeof( scaler_data_type );
833 scaler_data_type *q = (scaler_data_type*) dstPtr;
834
835 scaler_data_type /* A, */ B, C;
836 scaler_data_type D, E, F;
837 scaler_data_type /* G, */ H, I;
838
839 while (height--) {
840 int i;
841
842 B = *(p - 1 - nextlineSrc);
843 E = *(p - 1);
844 H = *(p - 1 + nextlineSrc);
845 C = *(p - nextlineSrc);
846 F = *(p);
847 I = *(p + nextlineSrc);
848
849 for (i = 0; i < width; ++i) {
850 p++;
851 /* A = B; */ B = C; C = *(p - nextlineSrc);
852 D = E; E = F; F = *(p);
853 /* G = H; */ H = I; I = *(p + nextlineSrc);
854
855 *(q) = D == B && B != F && D != H ? D : E;
856 *(q + 1) = B == F && B != D && F != H ? F : E;
857 *(q + nextlineDst) = D == H && D != B && H != F ? D : E;
858 *(q + nextlineDst + 1) = H == F && D != H && B != F ? F : E;
859 q += 2;
860 }
861 p += nextlineSrc - width;
862 q += (nextlineDst - width) << 1;
863 }
864 }
865
866 void
FUNCTION(scaler_AdvMame3x)867 FUNCTION( scaler_AdvMame3x )( const libspectrum_byte *srcPtr,
868 libspectrum_dword srcPitch,
869 libspectrum_byte *dstPtr,
870 libspectrum_dword dstPitch,
871 int width, int height )
872 {
873 unsigned int nextlineSrc = srcPitch / sizeof( scaler_data_type );
874 const scaler_data_type *p = (const scaler_data_type*) srcPtr;
875
876 unsigned int nextlineDst = dstPitch / sizeof( scaler_data_type );
877 scaler_data_type *q = (scaler_data_type*) dstPtr;
878
879 scaler_data_type /* A, */ B, C;
880 scaler_data_type D, E, F;
881 scaler_data_type /* G, */ H, I;
882
883 while (height--) {
884 int i;
885
886 B = *(p - 1 - nextlineSrc);
887 E = *(p - 1);
888 H = *(p - 1 + nextlineSrc);
889 C = *(p - nextlineSrc);
890 F = *(p);
891 I = *(p + nextlineSrc);
892
893 for (i = 0; i < width; ++i) {
894 p++;
895 /* A = B; */ B = C; C = *(p - nextlineSrc);
896 D = E; E = F; F = *(p);
897 /* G = H; */ H = I; I = *(p + nextlineSrc);
898
899 *(q) = D == B && B != F && D != H ? D : E;
900 *(q + 1) = E;
901 *(q + 2) = B == F && B != D && F != H ? F : E;
902 *(q + nextlineDst) = E;
903 *(q + nextlineDst + 1) = E;
904 *(q + nextlineDst + 2) = E;
905 *(q + 2 * nextlineDst) = D == H && D != B && H != F ? D : E;
906 *(q + 2 * nextlineDst + 1) = E;
907 *(q + 2 * nextlineDst + 2) = H == F && D != H && B != F ? F : E;
908 q += 3;
909 }
910 p += nextlineSrc - width;
911 q += (nextlineDst - width) * 3;
912 }
913 }
914
915 void
FUNCTION(scaler_Half)916 FUNCTION( scaler_Half )( const libspectrum_byte *srcPtr,
917 libspectrum_dword srcPitch, libspectrum_byte *dstPtr,
918 libspectrum_dword dstPitch,
919 int width, int height )
920 {
921 scaler_data_type *r;
922
923 while (height--) {
924 int i;
925 r = (scaler_data_type*) dstPtr;
926
927 if( ( height & 1 ) == 0 ) {
928 for (i = 0; i < width; i+=2, ++r) {
929 scaler_data_type color1 = *(((scaler_data_type*) srcPtr) + i);
930 scaler_data_type color2 = *(((scaler_data_type*) srcPtr) + i + 1);
931
932 *r = INTERPOLATE(color1, color2);
933 }
934 dstPtr += dstPitch;
935 }
936
937 srcPtr += srcPitch;
938 }
939 }
940
941 void
FUNCTION(scaler_HalfSkip)942 FUNCTION( scaler_HalfSkip )( const libspectrum_byte *srcPtr,
943 libspectrum_dword srcPitch,
944 libspectrum_byte *dstPtr,
945 libspectrum_dword dstPitch,
946 int width, int height )
947 {
948 scaler_data_type *r;
949
950 while (height--) {
951 int i;
952 r = (scaler_data_type*) dstPtr;
953
954 if( ( height & 1 ) == 0 ) {
955 for (i = 0; i < width; i+=2, ++r) {
956 *r = *(((const scaler_data_type*) srcPtr) + i + 1);
957 }
958 dstPtr += dstPitch;
959 }
960
961 srcPtr += srcPitch;
962 }
963 }
964
965 void
FUNCTION(scaler_Normal1x)966 FUNCTION( scaler_Normal1x )( const libspectrum_byte *srcPtr,
967 libspectrum_dword srcPitch,
968 libspectrum_byte *dstPtr,
969 libspectrum_dword dstPitch,
970 int width, int height )
971 {
972 while( height-- ) {
973 memcpy( dstPtr, srcPtr, SCALER_DATA_SIZE * width );
974 srcPtr += srcPitch;
975 dstPtr += dstPitch;
976 }
977 }
978
979 void
FUNCTION(scaler_Normal2x)980 FUNCTION( scaler_Normal2x )( const libspectrum_byte *srcPtr,
981 libspectrum_dword srcPitch,
982 libspectrum_byte *dstPtr,
983 libspectrum_dword dstPitch,
984 int width, int height )
985 {
986 const scaler_data_type *s;
987 scaler_data_type i, *d, *d2;
988
989 while( height-- ) {
990
991 for( i = 0, s = (const scaler_data_type*)srcPtr,
992 d = (scaler_data_type*)dstPtr,
993 d2 = (scaler_data_type*)(dstPtr + dstPitch);
994 i < width;
995 i++ ) {
996 *d++ = *d2++ = *s; *d++ = *d2++ = *s++;
997 }
998
999 srcPtr += srcPitch;
1000 dstPtr += dstPitch << 1;
1001 }
1002 }
1003
1004 void
FUNCTION(scaler_Normal3x)1005 FUNCTION( scaler_Normal3x )( const libspectrum_byte *srcPtr,
1006 libspectrum_dword srcPitch,
1007 libspectrum_byte *dstPtr,
1008 libspectrum_dword dstPitch,
1009 int width, int height )
1010 {
1011 libspectrum_byte *r;
1012 libspectrum_dword dstPitch2 = dstPitch * 2;
1013 libspectrum_dword dstPitch3 = dstPitch * 3;
1014
1015 while (height--) {
1016 int i;
1017 r = dstPtr;
1018 for (i = 0; i < width; ++i, r += 3 * SCALER_DATA_SIZE ) {
1019 scaler_data_type color = *(((const scaler_data_type*) srcPtr) + i);
1020
1021 *(scaler_data_type*)( r + 0 ) = color;
1022 *(scaler_data_type*)( r + SCALER_DATA_SIZE ) = color;
1023 *(scaler_data_type*)( r + 2 * SCALER_DATA_SIZE ) = color;
1024 *(scaler_data_type*)( r + 0 + dstPitch ) = color;
1025 *(scaler_data_type*)( r + SCALER_DATA_SIZE + dstPitch ) = color;
1026 *(scaler_data_type*)( r + 2 * SCALER_DATA_SIZE + dstPitch ) = color;
1027 *(scaler_data_type*)( r + 0 + dstPitch2 ) = color;
1028 *(scaler_data_type*)( r + SCALER_DATA_SIZE + dstPitch2 ) = color;
1029 *(scaler_data_type*)( r + 2 * SCALER_DATA_SIZE + dstPitch2 ) = color;
1030 }
1031 srcPtr += srcPitch;
1032 dstPtr += dstPitch3;
1033 }
1034 }
1035
1036 void
FUNCTION(scaler_Timex1_5x)1037 FUNCTION( scaler_Timex1_5x )( const libspectrum_byte *srcPtr,
1038 libspectrum_dword srcPitch,
1039 libspectrum_byte *dstPtr,
1040 libspectrum_dword dstPitch,
1041 int width, int height )
1042 {
1043 libspectrum_byte *r;
1044 libspectrum_dword dstPitch2 = dstPitch * 2;
1045 libspectrum_dword dstPitch3 = dstPitch * 3;
1046
1047 while (height--) {
1048 int i;
1049 r = dstPtr;
1050 if( ( height & 1 ) == 0 ) {
1051 for (i = 0; i < width; i+=2, r += 3 * SCALER_DATA_SIZE ) {
1052 /* Interpolate a new pixel inbetween the source pixels */
1053 scaler_data_type color1 = *(((const scaler_data_type*) srcPtr) + i);
1054 scaler_data_type color2 = *(((const scaler_data_type*) srcPtr) + i + 1);
1055 scaler_data_type color3 = INTERPOLATE(color1, color2);
1056
1057 *(scaler_data_type*)( r + 0 ) = color1;
1058 *(scaler_data_type*)( r + SCALER_DATA_SIZE ) = color3;
1059 *(scaler_data_type*)( r + 2 * SCALER_DATA_SIZE ) = color2;
1060 *(scaler_data_type*)( r + 0 + dstPitch ) = color1;
1061 *(scaler_data_type*)( r + SCALER_DATA_SIZE + dstPitch ) = color3;
1062 *(scaler_data_type*)( r + 2 * SCALER_DATA_SIZE + dstPitch ) = color2;
1063 *(scaler_data_type*)( r + 0 + dstPitch2 ) = color1;
1064 *(scaler_data_type*)( r + SCALER_DATA_SIZE + dstPitch2 ) = color3;
1065 *(scaler_data_type*)( r + 2 * SCALER_DATA_SIZE + dstPitch2 ) = color2;
1066 }
1067 dstPtr += dstPitch3;
1068 }
1069 srcPtr += srcPitch;
1070 }
1071 }
1072
1073 void
FUNCTION(scaler_TV2x)1074 FUNCTION( scaler_TV2x )( const libspectrum_byte *srcPtr,
1075 libspectrum_dword srcPitch, libspectrum_byte *dstPtr,
1076 libspectrum_dword dstPitch,
1077 int width, int height )
1078 {
1079 int i, j;
1080 unsigned int nextlineSrc = srcPitch / sizeof( scaler_data_type );
1081 const scaler_data_type *p = (const scaler_data_type*)srcPtr;
1082
1083 unsigned int nextlineDst = dstPitch / sizeof( scaler_data_type );
1084 scaler_data_type *q = (scaler_data_type*)dstPtr;
1085
1086 while(height--) {
1087 for (i = 0, j = 0; i < width; ++i, j += 2) {
1088 scaler_data_type p1 = *(p + i);
1089 scaler_data_type pi;
1090
1091 pi = (((p1 & redblueMask) * 7) >> 3) & redblueMask;
1092 pi |= (((p1 & greenMask ) * 7) >> 3) & greenMask;
1093
1094 *(q + j) = p1;
1095 *(q + j + 1) = p1;
1096 *(q + j + nextlineDst) = pi;
1097 *(q + j + nextlineDst + 1) = pi;
1098 }
1099 p += nextlineSrc;
1100 q += nextlineDst << 1;
1101 }
1102 }
1103
1104 void
FUNCTION(scaler_TV3x)1105 FUNCTION( scaler_TV3x )( const libspectrum_byte *srcPtr,
1106 libspectrum_dword srcPitch, libspectrum_byte *dstPtr,
1107 libspectrum_dword dstPitch,
1108 int width, int height )
1109 {
1110 int i, j;
1111 unsigned int nextlineSrc = srcPitch / sizeof( scaler_data_type );
1112 const scaler_data_type *p = (const scaler_data_type*)srcPtr;
1113
1114 unsigned int nextlineDst = dstPitch / sizeof( scaler_data_type );
1115 scaler_data_type *q = (scaler_data_type*)dstPtr;
1116
1117 while(height--) {
1118 for (i = 0, j = 0; i < width; ++i, j += 3) {
1119 scaler_data_type p1 = *(p + i);
1120 scaler_data_type pi;
1121
1122 pi = (((p1 & redblueMask) * 7) >> 3) & redblueMask;
1123 pi |= (((p1 & greenMask ) * 7) >> 3) & greenMask;
1124
1125 *(q + j) = p1;
1126 *(q + j + 1) = p1;
1127 *(q + j + 2) = p1;
1128
1129 *(q + j + nextlineDst) = p1;
1130 *(q + j + nextlineDst + 1) = p1;
1131 *(q + j + nextlineDst + 2) = p1;
1132
1133 *(q + j + (nextlineDst << 1)) = pi;
1134 *(q + j + (nextlineDst << 1) + 1) = pi;
1135 *(q + j + (nextlineDst << 1) + 2) = pi;
1136 }
1137 p += nextlineSrc;
1138 q += nextlineDst * 3;
1139 }
1140 }
1141
1142 void
FUNCTION(scaler_TimexTV)1143 FUNCTION( scaler_TimexTV )( const libspectrum_byte *srcPtr,
1144 libspectrum_dword srcPitch,
1145 libspectrum_byte *dstPtr,
1146 libspectrum_dword dstPitch,
1147 int width, int height )
1148 {
1149 int i, j;
1150 unsigned int nextlineSrc = srcPitch / sizeof( scaler_data_type );
1151 const scaler_data_type *p = (const scaler_data_type *)srcPtr;
1152
1153 unsigned int nextlineDst = dstPitch / sizeof( scaler_data_type );
1154 scaler_data_type *q = (scaler_data_type *)dstPtr;
1155
1156 while(height--) {
1157 if( ( height & 1 ) == 0 ) {
1158 for (i = 0, j = 0; i < width; ++i, j++ ) {
1159 scaler_data_type p1 = *(p + i);
1160 scaler_data_type pi;
1161
1162 pi = (((p1 & redblueMask) * 7) >> 3) & redblueMask;
1163 pi |= (((p1 & greenMask ) * 7) >> 3) & greenMask;
1164
1165 *(q + j) = p1;
1166 *(q + j + nextlineDst) = pi;
1167 }
1168 q += nextlineDst << 1;
1169 }
1170 p += nextlineSrc;
1171 }
1172 }
1173
DOT_16(scaler_data_type c,int j,int i)1174 static inline scaler_data_type DOT_16(scaler_data_type c, int j, int i) {
1175 return c - ((c >> 2) & *(dotmatrix + ((j & 3) << 2) + (i & 3)));
1176 }
1177
1178 void
FUNCTION(scaler_DotMatrix)1179 FUNCTION( scaler_DotMatrix )( const libspectrum_byte *srcPtr,
1180 libspectrum_dword srcPitch,
1181 libspectrum_byte *dstPtr,
1182 libspectrum_dword dstPitch,
1183 int width, int height )
1184 {
1185 int i, j, ii, jj;
1186 unsigned int nextlineSrc = srcPitch / sizeof( scaler_data_type );
1187 const scaler_data_type *p = (const scaler_data_type *)srcPtr;
1188
1189 unsigned int nextlineDst = dstPitch / sizeof( scaler_data_type );
1190 scaler_data_type *q = (scaler_data_type *)dstPtr;
1191
1192 for (j = 0, jj = 0; j < height; ++j, jj += 2) {
1193 for (i = 0, ii = 0; i < width; ++i, ii += 2) {
1194 scaler_data_type c = *(p + i);
1195 *(q + ii) = DOT_16(c, jj, ii);
1196 *(q + ii + 1) = DOT_16(c, jj, ii + 1);
1197 *(q + ii + nextlineDst) = DOT_16(c, jj + 1, ii);
1198 *(q + ii + nextlineDst + 1) = DOT_16(c, jj + 1, ii + 1);
1199 }
1200 p += nextlineSrc;
1201 q += nextlineDst << 1;
1202 }
1203 }
1204
1205 /*
1206 Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
1207 U = -0.16874 * R - 0.33126 * G + 0.50000 * B (+ 128)
1208 V = 0.50000 * R - 0.41869 * G - 0.08131 * B (+ 128)
1209 */
1210
1211 #define RGB_TO_Y(r, g, b) ( ( 2449L * r + 4809L * g + 934L * b + 1024 ) >> 11 )
1212 #define RGB_TO_U(r, g, b) ( ( 4096L * b - 1383L * r - 2713L * g + 1024 ) >> 11 )
1213 #define RGB_TO_V(r, g, b) ( ( 4096L * r - 3430L * g - 666L * b + 1024 ) >> 11 )
1214
1215 /*
1216 R = Y + 1.402 (V-128)
1217 G = Y - 0.34414 (U-128) - 0.71414 (V-128)
1218 B = Y + 1.772 (U-128)
1219 */
1220
1221 #define YUV_TO_R(y, u, v) ( MIN( ABS( ( 8192L * y + 11485L * v + 16384 ) >> 15 ), 255 ) )
1222 #define YUV_TO_G(y, u, v) ( MIN( ABS( ( 8192L * y - 2819L * u - 5850L * v + 16384 ) >> 15 ), 255 ) )
1223 #define YUV_TO_B(y, u, v) ( MIN( ABS( ( 8192L * y + 14516L * u + 16384 ) >> 15 ), 255 ) )
1224
1225 #define RGB_TO_PIXEL_555(r,g,b) \
1226 (((r * 125) >> 10) + (((g * 125) >> 5) & greenMask) + \
1227 ((b * 125) & blueMask))
1228
1229 #define RGB_TO_PIXEL_565(r,g,b) \
1230 (((r * 125) >> 10) + (((g * 253) >> 5) & greenMask) + \
1231 ((b * 249) & blueMask))
1232
1233 #define R_TO_R(r) \
1234 ( ( ( (r) & redMask ) * 8424 ) >> 10 )
1235
1236 #define G_TO_G(g) \
1237 ( green6bit ? \
1238 ( ( ( (g) & greenMask ) >> 5 ) * 4145 ) >> 10 : \
1239 ( ( ( (g) & greenMask ) >> 5 ) * 8424 ) >> 10 )
1240
1241 #define B_TO_B(b) \
1242 ( green6bit ? \
1243 ( ( ( (b) & blueMask ) >> 11 ) * 8424 ) >> 10 : \
1244 ( ( ( (b) & blueMask ) >> 10 ) * 8424 ) >> 10 )
1245
1246 void
FUNCTION(scaler_PalTV)1247 FUNCTION( scaler_PalTV )( const libspectrum_byte *srcPtr,
1248 libspectrum_dword srcPitch,
1249 libspectrum_byte *dstPtr,
1250 libspectrum_dword dstPitch,
1251 int width, int height )
1252 {
1253 /*
1254 1.a. RGB => 255,255,255 RGB
1255 1.b. RGB => YUV
1256 2. 422 interstricial color subsampling
1257 3.a. YUV => RGB
1258 3.b 255,255,255 RGB => RGB
1259 */
1260 int i, j;
1261 unsigned int nextlineSrc = srcPitch / sizeof( scaler_data_type );
1262 const scaler_data_type *p, *p0 = (const scaler_data_type *)srcPtr;
1263
1264 unsigned int nextlineDst = dstPitch / sizeof( scaler_data_type );
1265 scaler_data_type *q, *q0 = (scaler_data_type *)dstPtr;
1266
1267 libspectrum_byte r0, g0, b0,
1268 r1, g1, b1,
1269 r2, g2, b2,
1270 r3, g3, b3;
1271 libspectrum_signed_word y1, y2, u1, u2, v1, v2;
1272
1273 /*
1274 422 cosited
1275 # + # + + only Y
1276 # Y and Cb Cr
1277 # + # +
1278
1279 abcd... => 1/2a + a + 1/2b / 2; ...; 1/2a + b + 1/2c; ... ; ...
1280 always 3 sample/proc
1281
1282 */
1283 for( j = height; j; j-- ) {
1284 p = p0 - 1; q = q0;
1285 #if SCALER_DATA_SIZE == 2
1286 /* 1.a. RGB => RGB */
1287 r2 = R_TO_R( *p );
1288 g2 = G_TO_G( *p );
1289 b2 = B_TO_B( *p );
1290 p++;
1291 r0 = R_TO_R( *p );
1292 g0 = G_TO_G( *p );
1293 b0 = B_TO_B( *p );
1294 p++;
1295 r1 = R_TO_R( *p );
1296 g1 = G_TO_G( *p );
1297 b1 = B_TO_B( *p );
1298 p++;
1299 #else
1300 r2 = (*p & redMask);
1301 g2 = (*p & greenMask) >> 8;
1302 b2 = (*p & blueMask) >> 16;
1303 p++;
1304 r0 = (*p & redMask);
1305 g0 = (*p & greenMask) >> 8;
1306 b0 = (*p & blueMask) >> 16;
1307 p++;
1308 r1 = (*p & redMask);
1309 g1 = (*p & greenMask) >> 8;
1310 b1 = (*p & blueMask) >> 16;
1311 p++;
1312 #endif
1313 u1 = ( RGB_TO_U( r2, g2, b2 ) + 2 * RGB_TO_U( r0, g0, b0 ) +
1314 RGB_TO_U( r1, g1, b1 ) ) >> 2;
1315 v1 = ( RGB_TO_V( r2, g2, b2 ) + 2 * RGB_TO_V( r0, g0, b0 ) +
1316 RGB_TO_V( r1, g1, b1 ) ) >> 2;
1317 for( i = width; i; i -= 2 ) {
1318 #if SCALER_DATA_SIZE == 2
1319 /* 1.a. RGB => RGB */
1320 r2 = R_TO_R( *p );
1321 g2 = G_TO_G( *p );
1322 b2 = B_TO_B( *p );
1323 p++;
1324 r3 = R_TO_R( *p );
1325 g3 = G_TO_G( *p );
1326 b3 = B_TO_B( *p );
1327 p++;
1328 #else
1329 r2 = (*p & redMask);
1330 g2 = (*p & greenMask) >> 8;
1331 b2 = (*p & blueMask) >> 16;
1332 p++;
1333 r3 = (*p & redMask);
1334 g3 = (*p & greenMask) >> 8;
1335 b3 = (*p & blueMask) >> 16;
1336 p++;
1337 #endif
1338 /* 1.b. RGB => YUV && 2. YUV subsampling */
1339 y1 = RGB_TO_Y( r0, g0, b0 );
1340 y2 = RGB_TO_Y( r1, g1, b1 );
1341
1342 u2 = ( RGB_TO_U( r1, g1, b1 ) + 2 * RGB_TO_U( r2, g2, b2 ) +
1343 RGB_TO_U( r3, g3, b3 ) ) >> 2;
1344 v2 = ( RGB_TO_V( r1, g1, b1 ) + 2 * RGB_TO_V( r2, g2, b2 ) +
1345 RGB_TO_V( r3, g3, b3 ) ) >> 2;
1346 /* 3.a. YUV => RGB */
1347 r0 = YUV_TO_R(y1, u1, v1);
1348 g0 = YUV_TO_G(y1, u1, v1);
1349 b0 = YUV_TO_B(y1, u1, v1);
1350
1351 u1 = (u1 + u2) >> 1;
1352 v1 = (v1 + v2) >> 1;
1353
1354 r1 = YUV_TO_R(y2, u1, v1);
1355 g1 = YUV_TO_G(y2, u1, v1);
1356 b1 = YUV_TO_B(y2, u1, v1);
1357 #if SCALER_DATA_SIZE == 2
1358 /* 3.b. RGB => RGB */
1359 if( green6bit ) {
1360 *q++ = RGB_TO_PIXEL_565( r0, g0, b0 );
1361 *q++ = RGB_TO_PIXEL_565( r1, g1, b1 );
1362 } else {
1363 *q++ = RGB_TO_PIXEL_555( r0, g0, b0 );
1364 *q++ = RGB_TO_PIXEL_555( r1, g1, b1 );
1365 }
1366 #else
1367 *q++ = r0 + (g0 << 8) + (b0 << 16);
1368 *q++ = r1 + (g1 << 8) + (b1 << 16);
1369 #endif
1370 u1 = u2; v1 = v2;
1371 r0 = r2; g0 = g2; b0 = b2;
1372 r1 = r3; g1 = g3; b1 = b3;
1373 }
1374 p0 += nextlineSrc;
1375 q0 += nextlineDst;
1376 }
1377 }
1378
1379 void
FUNCTION(scaler_PalTV2x)1380 FUNCTION( scaler_PalTV2x )( const libspectrum_byte *srcPtr,
1381 libspectrum_dword srcPitch,
1382 libspectrum_byte *dstPtr,
1383 libspectrum_dword dstPitch,
1384 int width, int height )
1385 {
1386 /*
1387 1.a. RGB => 255,255,255 RGB
1388 1.b. RGB => YUV
1389 2. 4:2:2 cosited color subsampling
1390 3.a. YUV => RGB
1391 3.b 255,255,255 RGB => RGB
1392 */
1393 int i, j;
1394 unsigned int nextlineSrc = srcPitch / sizeof( scaler_data_type );
1395 const scaler_data_type *p, *p0 = (const scaler_data_type *)srcPtr;
1396
1397 unsigned int nextlineDst = dstPitch / sizeof( scaler_data_type );
1398 scaler_data_type *q, *q0 = (scaler_data_type *)dstPtr;
1399
1400 libspectrum_byte r0, g0, b0,
1401 r1, g1, b1,
1402 rx, gx, bx;
1403 libspectrum_signed_dword y1, y2, u1, v1, u2, v2;
1404
1405 /*
1406 422 cosited
1407 # + # + + only Y
1408 # Y and Cb Cr
1409 # + # +
1410
1411 abcd... => 1/2a + a + 1/2b / 2; ...; 1/2a + b + 1/2c; ... ; ...
1412 always 3 sample/proc
1413
1414 */
1415 for( j = height; j; j-- ) {
1416 p = p0 - 1; q = q0;
1417 #if SCALER_DATA_SIZE == 2
1418 r0 = R_TO_R( *p );
1419 g0 = G_TO_G( *p );
1420 b0 = B_TO_B( *p );
1421 p++;
1422 r1 = R_TO_R( *p );
1423 g1 = G_TO_G( *p );
1424 b1 = B_TO_B( *p );
1425 #else
1426 r0 = *p & redMask;
1427 g0 = (*p & greenMask) >> 8;
1428 b0 = (*p & blueMask) >> 16;
1429 p++;
1430 r1 = *(p) & redMask;
1431 g1 = (*(p) & greenMask) >> 8;
1432 b1 = (*(p) & blueMask) >> 16;
1433 #endif
1434 y1 = RGB_TO_Y( r1, g1, b1 );
1435 u1 = ( RGB_TO_U( r0, g0, b0 ) + 3 * RGB_TO_U( r1, g1, b1 ) ) >> 2;
1436 v1 = ( RGB_TO_V( r0, g0, b0 ) + 3 * RGB_TO_V( r1, g1, b1 ) ) >> 2;
1437 for( i = width; i; i-- ) {
1438 p++; /* next point */
1439 #if SCALER_DATA_SIZE == 2
1440 /* 1.a. RGB => RGB */
1441 r0 = R_TO_R( *p );
1442 g0 = G_TO_G( *p );
1443 b0 = B_TO_B( *p );
1444 #else
1445 r0 = (*p & redMask);
1446 g0 = (*p & greenMask) >> 8;
1447 b0 = (*p & blueMask) >> 16;
1448 #endif
1449 /* 1.b. RGB => YUV && 2. YUV subsampling */
1450 y2 = RGB_TO_Y( r0, g0, b0 );
1451 u2 = ( RGB_TO_U( r1, g1, b1 ) + 3 * RGB_TO_U( r0, g0, b0 ) ) >> 2;
1452 v2 = ( RGB_TO_V( r1, g1, b1 ) + 3 * RGB_TO_V( r0, g0, b0 ) ) >> 2;
1453
1454 /* 3.a. YUV => RGB */
1455 rx = YUV_TO_R( y1, u1, v1 ); /* [x0][ ]*/
1456 gx = YUV_TO_G( y1, u1, v1 );
1457 bx = YUV_TO_B( y1, u1, v1 );
1458
1459 u1 = ( u1 + u2 ) >> 1;
1460 v1 = ( v1 + v2 ) >> 1;
1461
1462 r1 = YUV_TO_R( y1, u1, v1 );
1463 g1 = YUV_TO_G( y1, u1, v1 );
1464 b1 = YUV_TO_B( y1, u1, v1 );
1465
1466 #if SCALER_DATA_SIZE == 2
1467 /* 3.b. RGB => RGB */
1468 if( green6bit ) {
1469 *q = RGB_TO_PIXEL_565( rx, gx, bx );
1470 } else {
1471 *q = RGB_TO_PIXEL_555( rx, gx, bx );
1472 }
1473 #else
1474 *q = rx + ( gx << 8 ) + ( bx << 16 );
1475 #endif
1476
1477 if( settings_current.pal_tv2x )
1478 *(q + nextlineDst) =
1479 ((((*q & redblueMask) * 7) >> 3) & redblueMask) |
1480 ((((*q & greenMask ) * 7) >> 3) & greenMask);
1481 else
1482 *(q + nextlineDst) = *q;
1483
1484 q++;
1485 #if SCALER_DATA_SIZE == 2
1486 /* 3.b. RGB => RGB */
1487 if( green6bit ) {
1488 *q = RGB_TO_PIXEL_565( r1, g1, b1 );
1489 } else {
1490 *q = RGB_TO_PIXEL_555( r1, g1, b1 );
1491 }
1492 #else
1493 *q = r1 + ( g1 << 8 ) + ( b1 << 16 );
1494 #endif
1495 if( settings_current.pal_tv2x )
1496 *(q + nextlineDst) =
1497 ((((*q & redblueMask) * 7) >> 3) & redblueMask) |
1498 ((((*q & greenMask ) * 7) >> 3) & greenMask);
1499 else
1500 *(q + nextlineDst) = *q;
1501
1502 q++;
1503 y1 = y2; u1 = u2; v1 = v2; /* save for next point */
1504 r1 = r0; g1 = g0; b1 = b0;
1505 }
1506 p0 += nextlineSrc;
1507 q0 += nextlineDst << 1;
1508 }
1509 }
1510
1511 void
FUNCTION(scaler_PalTV3x)1512 FUNCTION( scaler_PalTV3x )( const libspectrum_byte *srcPtr,
1513 libspectrum_dword srcPitch,
1514 libspectrum_byte *dstPtr,
1515 libspectrum_dword dstPitch,
1516 int width, int height )
1517 {
1518 /*
1519 1.a. RGB => 255,255,255 RGB
1520 1.b. RGB => YUV
1521 2. 4:2:2 cosited color subsampling
1522 3.a. YUV => RGB
1523 3.b 255,255,255 RGB => RGB
1524 */
1525 int i, j;
1526 unsigned int nextlineSrc = srcPitch / sizeof( scaler_data_type );
1527 const scaler_data_type *p, *p0 = (const scaler_data_type *)srcPtr;
1528
1529 unsigned int nextlineDst = dstPitch / sizeof( scaler_data_type );
1530 scaler_data_type *q, *q0 = (scaler_data_type *)dstPtr;
1531
1532 libspectrum_byte r0, g0, b0,
1533 r1, g1, b1,
1534 r2, g2, b2,
1535 rx, gx, bx;
1536 libspectrum_signed_dword y1, y2, u1, v1, u2, v2;
1537
1538 /*
1539 422 cosited
1540 # + # + + only Y
1541 # Y and Cb Cr
1542 # + # +
1543
1544 abcd... => 1/2a + a + 1/2b / 2; ...; 1/2a + b + 1/2c; ... ; ...
1545 always 3 sample/proc
1546
1547 */
1548 for( j = height; j; j-- ) {
1549 p = p0 - 1; q = q0;
1550 #if SCALER_DATA_SIZE == 2
1551 r0 = R_TO_R( *p );
1552 g0 = G_TO_G( *p );
1553 b0 = B_TO_B( *p );
1554 p++;
1555 r1 = R_TO_R( *p );
1556 g1 = G_TO_G( *p );
1557 b1 = B_TO_B( *p );
1558 #else
1559 r0 = *p & redMask;
1560 g0 = (*p & greenMask) >> 8;
1561 b0 = (*p & blueMask) >> 16;
1562 p++; /* next point */
1563 r1 = *(p) & redMask;
1564 g1 = (*(p) & greenMask) >> 8;
1565 b1 = (*(p) & blueMask) >> 16;
1566 #endif
1567 y1 = RGB_TO_Y( r1, g1, b1 );
1568 u1 = ( RGB_TO_U( r0, g0, b0 ) + 3 * RGB_TO_U( r1, g1, b1 ) ) >> 2;
1569 v1 = ( RGB_TO_V( r0, g0, b0 ) + 3 * RGB_TO_V( r1, g1, b1 ) ) >> 2;
1570 for( i = width; i; i-- ) {
1571 p++;
1572 #if SCALER_DATA_SIZE == 2
1573 /* 1.a. RGB => RGB */
1574 r0 = R_TO_R( *p );
1575 g0 = G_TO_G( *p );
1576 b0 = B_TO_B( *p );
1577 #else
1578 r0 = (*p & redMask);
1579 g0 = (*p & greenMask) >> 8;
1580 b0 = (*p & blueMask) >> 16;
1581 #endif
1582 /* 1.b. RGB => YUV && 2. YUV subsampling */
1583 y2 = RGB_TO_Y( r0, g0, b0 );
1584 u2 = ( RGB_TO_U( r1, g1, b1 ) + 3 * RGB_TO_U( r0, g0, b0 ) ) >> 2;
1585 v2 = ( RGB_TO_V( r1, g1, b1 ) + 3 * RGB_TO_V( r0, g0, b0 ) ) >> 2;
1586
1587 /* 3.a. YUV => RGB */
1588 rx = YUV_TO_R( y1, u1, v1 ); /* [x0][ ]*/
1589 gx = YUV_TO_G( y1, u1, v1 );
1590 bx = YUV_TO_B( y1, u1, v1 );
1591
1592 u1 = ( u1 + u2 ) >> 1;
1593 v1 = ( v1 + v2 ) >> 1;
1594
1595 r1 = YUV_TO_R( y1, u1, v1 );
1596 g1 = YUV_TO_G( y1, u1, v1 );
1597 b1 = YUV_TO_B( y1, u1, v1 );
1598
1599 /*
1600 ab => EFG
1601 ab EFG
1602 efg
1603 */
1604 r2 = ((int)rx + r1) >> 1; /* F */
1605 g2 = ((int)gx + g1) >> 1;
1606 b2 = ((int)bx + b1) >> 1;
1607
1608 #if SCALER_DATA_SIZE == 2
1609 /* 3.b. RGB => RGB */
1610 if( green6bit ) {
1611 *q = RGB_TO_PIXEL_565( rx, gx, bx);
1612 } else {
1613 *q = RGB_TO_PIXEL_555( rx, gx, bx);
1614 }
1615 #else
1616 *q = rx + ( gx << 8 ) + ( bx << 16 ); /* E, E, e */
1617 #endif
1618 *(q + nextlineDst) = *q;
1619
1620 if( settings_current.pal_tv2x )
1621 *(q + (nextlineDst << 1)) =
1622 ((((*q & redblueMask) * 7) >> 3) & redblueMask) |
1623 ((((*q & greenMask ) * 7) >> 3) & greenMask);
1624 else
1625 *(q + (nextlineDst << 1)) = *q;
1626
1627 q++;
1628 #if SCALER_DATA_SIZE == 2
1629 /* 3.b. RGB => RGB */
1630 if( green6bit ) {
1631 *q = RGB_TO_PIXEL_565( r2, g2, b2 );
1632 } else {
1633 *q = RGB_TO_PIXEL_555( r2, g2, b2 );
1634 }
1635 #else
1636 *q = r2 + ( g2 << 8 ) + ( b2 << 16 ); /* F, F, f*/
1637 #endif
1638 *(q + nextlineDst) = *q;
1639
1640 if( settings_current.pal_tv2x )
1641 *(q + (nextlineDst << 1)) =
1642 ((((*q & redblueMask) * 7) >> 3) & redblueMask) |
1643 ((((*q & greenMask ) * 7) >> 3) & greenMask);
1644 else
1645 *(q + (nextlineDst << 1)) = *q;
1646
1647 q++;
1648 #if SCALER_DATA_SIZE == 2
1649 /* 3.b. RGB => RGB */
1650 if( green6bit ) {
1651 *q = RGB_TO_PIXEL_565( r1, g1, b1 );
1652 } else {
1653 *q = RGB_TO_PIXEL_555( r1, g1, b1 );
1654 }
1655 #else
1656 *q = r1 + ( g1 << 8 ) + ( b1 << 16 ); /* G, G, g*/
1657 #endif
1658 *(q + nextlineDst) = *q;
1659 if( settings_current.pal_tv2x )
1660 *(q + (nextlineDst << 1)) =
1661 ((((*q & redblueMask) * 7) >> 3) & redblueMask) |
1662 ((((*q & greenMask ) * 7) >> 3) & greenMask);
1663 else
1664 *(q + (nextlineDst << 1)) = *q;
1665
1666 q++;
1667 y1 = y2; u1 = u2; v1 = v2; /* save for next point */
1668 r1 = r0; g1 = g0; b1 = b0;
1669 }
1670 p0 += nextlineSrc;
1671 q0 += (nextlineDst << 1) + nextlineDst;
1672 }
1673 }
1674
1675 #define prevline (-nextlineSrc)
1676 #define nextline nextlineSrc
1677 #define MOVE_B_TO_A(A,B) \
1678 w[A] = w[B]; y[A] = y[B]; u[A] = u[B]; v[A] = v[B];
1679 #define MOVE_P_RIGHT \
1680 MOVE_B_TO_A(1,2) \
1681 MOVE_B_TO_A(4,5) \
1682 MOVE_B_TO_A(7,8) \
1683 MOVE_B_TO_A(2,3) \
1684 MOVE_B_TO_A(5,6) \
1685 MOVE_B_TO_A(8,9)
1686
1687 void
FUNCTION(scaler_HQ2x)1688 FUNCTION( scaler_HQ2x ) ( const libspectrum_byte *srcPtr,
1689 libspectrum_dword srcPitch,
1690 libspectrum_byte *dstPtr,
1691 libspectrum_dword dstPitch,
1692 int width, int height )
1693 {
1694 int i, j, k, pattern;
1695 int nextlineSrc = srcPitch / sizeof( scaler_data_type );
1696 const scaler_data_type *p, *p0 = (const scaler_data_type *)srcPtr;
1697 int nextlineDst = dstPitch / sizeof( scaler_data_type );
1698 scaler_data_type *q, *q1, *qN, *qN1, *q0 = (scaler_data_type *)dstPtr;
1699 libspectrum_qword w[10];
1700
1701 libspectrum_byte r, g, b;
1702 libspectrum_signed_dword y[10], u[10], v[10];
1703
1704 /* +----+----+----+
1705 | | | |
1706 | w1 | w2 | w3 |
1707 +----+----+----+
1708 | | | |
1709 | w4 | w5 | w6 |
1710 +----+----+----+
1711 | | | |
1712 | w7 | w8 | w9 |
1713 +----+----+----+ */
1714 for( j = 0; j < height; j++ ) {
1715 p = p0;
1716 q = q0; q1 = q + 1;
1717 qN = q + nextlineDst; qN1 = qN + 1;
1718 w[2] = *(p + prevline);
1719 w[5] = *p;
1720 w[8] = *(p + nextline);
1721 w[1] = *(p + prevline - 1);
1722 w[4] = *(p - 1);
1723 w[7] = *(p + nextline - 1);
1724 w[3] = *(p + prevline + 1);
1725 w[6] = *(p + 1);
1726 w[9] = *(p + nextline + 1);
1727 for( k = 1; k <= 9; k++ ) {
1728 #if SCALER_DATA_SIZE == 2
1729 r = R_TO_R( w[k] );
1730 g = G_TO_G( w[k] );
1731 b = B_TO_B( w[k] );
1732 #else
1733 r = w[k] & redMask;
1734 g = (w[k] & greenMask) >> 8;
1735 b = (w[k] & blueMask) >> 16;
1736 #endif
1737 y[k] = RGB_TO_Y( r, g, b );
1738 u[k] = RGB_TO_U( r, g, b );
1739 v[k] = RGB_TO_V( r, g, b );
1740 }
1741
1742 for( i = 0; i < width; i++ ) {
1743 pattern = 0;
1744 if( HQ_YUVDIFF( y[5], u[5], v[5], y[1], u[1], v[1] ) ) pattern |= 0x01;
1745 if( HQ_YUVDIFF( y[5], u[5], v[5], y[2], u[2], v[2] ) ) pattern |= 0x02;
1746 if( HQ_YUVDIFF( y[5], u[5], v[5], y[3], u[3], v[3] ) ) pattern |= 0x04;
1747 if( HQ_YUVDIFF( y[5], u[5], v[5], y[4], u[4], v[4] ) ) pattern |= 0x08;
1748 if( HQ_YUVDIFF( y[5], u[5], v[5], y[6], u[6], v[6] ) ) pattern |= 0x10;
1749 if( HQ_YUVDIFF( y[5], u[5], v[5], y[7], u[7], v[7] ) ) pattern |= 0x20;
1750 if( HQ_YUVDIFF( y[5], u[5], v[5], y[8], u[8], v[8] ) ) pattern |= 0x40;
1751 if( HQ_YUVDIFF( y[5], u[5], v[5], y[9], u[9], v[9] ) ) pattern |= 0x80;
1752
1753 #include "scaler_hq2x.c"
1754
1755 p++;
1756 q += 2; q1 += 2;
1757 qN += 2; qN1 += 2;
1758 MOVE_P_RIGHT
1759 w[3] = *(p + prevline + 1);
1760 w[6] = *(p + 1);
1761 w[9] = *(p + nextline + 1);
1762 for( k = 3; k <= 9; k += 3 ) {
1763 #if SCALER_DATA_SIZE == 2
1764 r = R_TO_R( w[k] );
1765 g = G_TO_G( w[k] );
1766 b = B_TO_B( w[k] );
1767 #else
1768 r = w[k] & redMask;
1769 g = ( w[k] & greenMask ) >> 8;
1770 b = ( w[k] & blueMask ) >> 16;
1771 #endif
1772 y[k] = RGB_TO_Y( r, g, b );
1773 u[k] = RGB_TO_U( r, g, b );
1774 v[k] = RGB_TO_V( r, g, b );
1775 }
1776 }
1777 p0 += nextlineSrc;
1778 q0 += nextlineDst << 1;
1779 }
1780 }
1781
1782 void
FUNCTION(scaler_HQ3x)1783 FUNCTION( scaler_HQ3x ) ( const libspectrum_byte *srcPtr,
1784 libspectrum_dword srcPitch,
1785 libspectrum_byte *dstPtr,
1786 libspectrum_dword dstPitch,
1787 int width, int height )
1788 {
1789 int i, j, k, pattern;
1790 int nextlineSrc = srcPitch / sizeof( scaler_data_type );
1791 const scaler_data_type *p, *p0 = (const scaler_data_type *)srcPtr;
1792 int nextlineDst = dstPitch / sizeof( scaler_data_type );
1793 scaler_data_type *q, *qN, *qNN, *q1, *qN1, *qNN1, *q2, *qN2, *qNN2,
1794 *q0 = (scaler_data_type *)dstPtr;
1795 libspectrum_qword w[10];
1796
1797 libspectrum_byte r, g, b;
1798 libspectrum_signed_dword y[10], u[10], v[10];
1799
1800 /* +----+----+----+
1801 | | | |
1802 | w1 | w2 | w3 |
1803 +----+----+----+
1804 | | | |
1805 | w4 | w5 | w6 |
1806 +----+----+----+
1807 | | | |
1808 | w7 | w8 | w9 |
1809 +----+----+----+ */
1810 for( j = 0; j < height; j++ ) {
1811 if( j == height - 1 ) nextline = 0;
1812
1813 p = p0;
1814 q = q0;
1815 q1 = q + 1; q2 = q + 2;
1816 qN = q + nextlineDst; qN1 = qN + 1; qN2 = qN + 2;
1817 qNN = qN + nextlineDst; qNN1 = qNN + 1; qNN2 = qNN + 2;
1818
1819 w[2] = *(p + prevline);
1820 w[5] = *p;
1821 w[8] = *(p + nextline);
1822 w[1] = *(p + prevline - 1);
1823 w[4] = *(p - 1);
1824 w[7] = *(p + nextline - 1);
1825 w[3] = *(p + prevline + 1);
1826 w[6] = *(p + 1);
1827 w[9] = *(p + nextline + 1);
1828 for( k = 1; k <= 9; k++ ) {
1829 #if SCALER_DATA_SIZE == 2
1830 r = R_TO_R( w[k] );
1831 g = G_TO_G( w[k] );
1832 b = B_TO_B( w[k] );
1833 #else
1834 r = w[k] & redMask;
1835 g = (w[k] & greenMask) >> 8;
1836 b = (w[k] & blueMask) >> 16;
1837 #endif
1838 y[k] = RGB_TO_Y( r, g, b );
1839 u[k] = RGB_TO_U( r, g, b );
1840 v[k] = RGB_TO_V( r, g, b );
1841 }
1842
1843 for( i = 0; i < width; i++ ) {
1844 pattern = 0;
1845 if( HQ_YUVDIFF( y[5], u[5], v[5], y[1], u[1], v[1] ) ) pattern |= 0x01;
1846 if( HQ_YUVDIFF( y[5], u[5], v[5], y[2], u[2], v[2] ) ) pattern |= 0x02;
1847 if( HQ_YUVDIFF( y[5], u[5], v[5], y[3], u[3], v[3] ) ) pattern |= 0x04;
1848 if( HQ_YUVDIFF( y[5], u[5], v[5], y[4], u[4], v[4] ) ) pattern |= 0x08;
1849 if( HQ_YUVDIFF( y[5], u[5], v[5], y[6], u[6], v[6] ) ) pattern |= 0x10;
1850 if( HQ_YUVDIFF( y[5], u[5], v[5], y[7], u[7], v[7] ) ) pattern |= 0x20;
1851 if( HQ_YUVDIFF( y[5], u[5], v[5], y[8], u[8], v[8] ) ) pattern |= 0x40;
1852 if( HQ_YUVDIFF( y[5], u[5], v[5], y[9], u[9], v[9] ) ) pattern |= 0x80;
1853
1854 #include "scaler_hq3x.c"
1855
1856 p++;
1857 q += 3; q1 += 3; q2 += 3;
1858 qN += 3; qN1 += 3; qN2 += 3;
1859 qNN += 3; qNN1 += 3; qNN2 += 3;
1860 MOVE_P_RIGHT
1861 w[3] = *(p + prevline + 1);
1862 w[6] = *(p + 1);
1863 w[9] = *(p + nextline + 1);
1864 for( k = 3; k <= 9; k += 3 ) {
1865 #if SCALER_DATA_SIZE == 2
1866 r = R_TO_R( w[k] );
1867 g = G_TO_G( w[k] );
1868 b = B_TO_B( w[k] );
1869 #else
1870 r = w[k] & redMask;
1871 g = ( w[k] & greenMask ) >> 8;
1872 b = ( w[k] & blueMask ) >> 16;
1873 #endif
1874 y[k] = RGB_TO_Y( r, g, b );
1875 u[k] = RGB_TO_U( r, g, b );
1876 v[k] = RGB_TO_V( r, g, b );
1877 }
1878 }
1879 p0 += nextlineSrc;
1880 q0 += ( nextlineDst << 1 ) + nextlineDst;
1881 }
1882 }
1883