]> icculus.org git repositories - crow/jumpnbump.git/blob - sdl/gfx.c
Implemented my own XPM loader, so we don't have to link SDL_image for just this.
[crow/jumpnbump.git] / sdl / gfx.c
1 /*
2  * gfx.c
3  * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/
4  * 
5  * Copyright (C) 2001 Chuck Mason <cemason@users.sourceforge.net>
6  *
7  * Copyright (C) 2002 Florian Schulze <crow@icculus.org>
8  *
9  * Portions of this code are from the MPEG software simulation group
10  * idct implementation. This code will be replaced with a new
11  * implementation soon.
12  *
13  * This file is part of Jump'n'Bump.
14  *
15  * Jump'n'Bump is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * Jump'n'Bump is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  */
29
30 #include "globals.h"
31 #include <SDL_endian.h>
32 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
33 #define SWAP16(X)    (X)
34 #define SWAP32(X)    (X)
35 #else
36 #define SWAP16(X)    SDL_Swap16(X)
37 #define SWAP32(X)    SDL_Swap32(X)
38 #endif
39
40 #ifdef _MSC_VER
41     #include "jumpnbump32.xpm"
42 #elif __APPLE__
43     #include "jumpnbump128.xpm"
44 #else
45     #include "jumpnbump64.xpm"
46 #endif
47 SDL_Surface *icon;
48
49 int screen_width=400;
50 int screen_height=256;
51 int screen_pitch=400;
52 int scale_up=0;
53 int bytes_per_pixel=1;
54 int dirty_block_shift=4;
55
56 static int current_pal[256];
57 static SDL_Surface *jnb_surface;
58 static int fullscreen = 0;
59 static int vinited = 0;
60 static void *screen_buffer[2];
61 static int drawing_enable = 0;
62 static void *background = NULL;
63 static int background_drawn;
64 static void *mask = NULL;
65 static int dirty_blocks[2][25*16*2];
66
67 static SDL_Surface *load_xpm_from_array(char **xpm)
68 {
69 #define NEXT_TOKEN { \
70         while ((*p != ' ') && (*p != '\t')) p++; \
71         while ((*p == ' ') || (*p == '\t')) p++; }
72
73         SDL_Surface *surface;
74         char *p;
75         int width;
76         int height;
77         int colors;
78         int images;
79         int color;
80         int pal[256];
81         int x,y;
82
83         p = *xpm++;
84
85         width = atoi(p);
86         if (width <= 0)
87                 return NULL;
88         NEXT_TOKEN;
89
90         height = atoi(p);
91         if (height <= 0)
92                 return NULL;
93         NEXT_TOKEN;
94
95         colors = atoi(p);
96         if (colors <= 0)
97                 return NULL;
98         NEXT_TOKEN;
99
100         images = atoi(p);
101         if (images <= 0)
102                 return NULL;
103
104         surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
105         if (!surface)
106                 return NULL;
107
108         SDL_SetColorKey(surface, SDL_SRCCOLORKEY, SDL_MapRGBA(surface->format, 0, 0, 0, 0));
109         while (colors--) {
110                 p = *xpm++;
111
112                 color = *p++;
113                 NEXT_TOKEN;
114
115                 if (*p++ != 'c') {
116                         SDL_FreeSurface(surface);
117                         return NULL;
118                 }
119                 NEXT_TOKEN;
120
121                 if (*p == '#')
122                         pal[color] = strtoul(++p, NULL, 16) | 0xff000000;
123                 else
124                         pal[color] = 0;
125         }
126
127         y = 0;
128         while (y < height) {
129                 int *pixels;
130
131                 p = *xpm++;
132
133                 pixels = (int *)&((char *)surface->pixels)[y++ * surface->pitch];
134                 x = 0;
135                 while (x < width) {
136                         int r,g,b,a;
137
138                         if (*p == '\0') {
139                                 SDL_FreeSurface(surface);
140                                 return NULL;
141                         }
142                         r = (pal[*p] >> 16) & 0xff;
143                         b = (pal[*p] & 0xff);
144                         g = (pal[*p] >> 8) & 0xff;
145                         a = (pal[*p] >> 24) & 0xff;
146                         pixels[x] = SDL_MapRGBA(surface->format, r, g, b, a);
147                         x++;
148                         p++;
149                 }
150         }
151
152         return surface;
153 }
154
155 void *get_vgaptr(int page, int x, int y)
156 {
157         assert(drawing_enable==1);
158
159         return (unsigned char *)screen_buffer[page] + (y*screen_pitch)+(x*bytes_per_pixel);
160 }
161
162
163 void set_scaling(int scale)
164 {
165         if (scale==1) {
166                 screen_width=800;
167                 screen_height=512;
168                 scale_up=1;
169                 bytes_per_pixel=2;
170                 dirty_block_shift=5;
171                 screen_pitch=screen_width*bytes_per_pixel;
172         } else {
173                 screen_width=400;
174                 screen_height=256;
175                 scale_up=0;
176                 bytes_per_pixel=1;
177                 dirty_block_shift=4;
178                 screen_pitch=screen_width*bytes_per_pixel;
179         }
180 }
181
182 void open_screen(void)
183 {
184         int lval = 0;
185         int bpp;
186         int flags;
187
188 #ifdef __APPLE__
189         lval = SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO);
190 #else
191         lval = SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_AUDIO);
192 #endif
193         if (lval < 0) {
194                 fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError());
195                 exit(EXIT_FAILURE);
196         }
197
198         if (scale_up)
199                 bpp = 16;
200         else
201                 bpp = 8;
202         flags = SDL_SWSURFACE;
203         if (fullscreen)
204                 flags |= SDL_FULLSCREEN;
205         jnb_surface = SDL_SetVideoMode(screen_width, screen_height, bpp, flags);
206
207         if (!jnb_surface) {
208                 fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError());
209                 exit(EXIT_FAILURE);
210         }
211
212         if(fullscreen)
213                 SDL_ShowCursor(0);
214         else
215                 SDL_ShowCursor(1);
216
217         SDL_WM_SetCaption("Jump n Bump","");
218
219         icon=load_xpm_from_array(jumpnbump_xpm);
220         if (icon==NULL) {
221             printf("Couldn't load icon\n");
222         } else {
223             SDL_WM_SetIcon(icon,NULL);
224         }
225
226         vinited = 1;
227
228         memset(current_pal, 0, sizeof(current_pal));
229         memset(dirty_blocks, 0, sizeof(dirty_blocks));
230
231         screen_buffer[0]=malloc(screen_width*screen_height*bytes_per_pixel);
232         screen_buffer[1]=malloc(screen_width*screen_height*bytes_per_pixel);
233
234 /*
235         dirty_blocks[0]=malloc(sizeof(int)*25*16+1000);
236         dirty_blocks[1]=malloc(sizeof(int)*25*16+1000);
237 */
238
239         return;
240 }
241
242
243 void fs_toggle()
244 {
245         if (!vinited) {
246                 fullscreen ^= 1;
247                 return;
248         }
249         if (SDL_WM_ToggleFullScreen(jnb_surface))
250                 fullscreen ^= 1;
251 }
252
253
254 void wait_vrt(int mix)
255 {
256         return;
257 }
258
259
260 void clear_page(int page, int color)
261 {
262         int i,j;
263
264         assert(drawing_enable==1);
265
266         for (i=0; i<(25*16); i++)
267                 dirty_blocks[page][i] = 1;
268
269         if (bytes_per_pixel==1) {
270                 unsigned char *buf = get_vgaptr(page, 0, 0);
271
272                 for (i=0; i<screen_height; i++)
273                         for (j=0; j<screen_width; j++)
274                                 *buf++ = color;
275         } else if (bytes_per_pixel==2) {
276                 unsigned short *buf = get_vgaptr(page, 0, 0);
277
278                 for (i=0; i<screen_height; i++)
279                         for (j=0; j<screen_width; j++)
280                                 *buf++ = color;
281         } else {
282                 unsigned int *buf = get_vgaptr(page, 0, 0);
283
284                 for (i=0; i<screen_height; i++)
285                         for (j=0; j<screen_width; j++)
286                                 *buf++ = color;
287         }
288 }
289
290
291 void clear_lines(int page, int y, int count, int color)
292 {
293         int i,j;
294
295         assert(drawing_enable==1);
296
297         if (scale_up) {
298                 count *= 2;
299                 y *= 2;
300         }
301
302         if (bytes_per_pixel==1) {
303                 for (i=0; i<count; i++) {
304                         if ((i+y)<screen_height) {
305                                 unsigned char *buf = get_vgaptr(page, 0, i+y);
306                                 for (j=0; j<screen_width; j++)
307                                         *buf++ = color;
308                         }
309                 }
310         } else if (bytes_per_pixel==2) {
311                 for (i=0; i<count; i++) {
312                         if ((i+y)<screen_height) {
313                                 unsigned short *buf = get_vgaptr(page, 0, i+y);
314                                 for (j=0; j<screen_width; j++)
315                                         *buf++ = color;
316                         }
317                 }
318         } else {
319                 for (i=0; i<count; i++) {
320                         if ((i+y)<screen_height) {
321                                 unsigned int *buf = get_vgaptr(page, 0, i+y);
322                                 for (j=0; j<screen_width; j++)
323                                         *buf++ = color;
324                         }
325                 }
326         }
327         count = ((y+count)>>dirty_block_shift) - (y>>dirty_block_shift) + 1;
328         y >>= dirty_block_shift;
329         for (i=0; i<count; i++)
330                 for (j=0; j<25; j++)
331                         dirty_blocks[page][(y+i)*25+j] = 1;
332 }
333
334
335 int get_color(int color, char pal[768])
336 {
337         assert(color<256);
338         assert(pal);
339         return SDL_MapRGB(jnb_surface->format, (Uint8)(pal[color*3+0]<<2), (Uint8)(pal[color*3+1]<<2), (Uint8)(pal[color*3+2]<<2));
340 }
341
342
343 int get_pixel(int page, int x, int y)
344 {
345         assert(drawing_enable==1);
346
347         if (scale_up) {
348                 x *= 2;
349                 y *= 2;
350         }
351
352         assert(x<screen_width);
353         assert(y<screen_height);
354
355         if (bytes_per_pixel==1)
356                 return *(unsigned char *)get_vgaptr(page, x, y);
357         else if (bytes_per_pixel==2)
358                 return *(unsigned short *)get_vgaptr(page, x, y);
359         else
360                 return *(unsigned int *)get_vgaptr(page, x, y);
361 }
362
363
364 void set_pixel(int page, int x, int y, int color)
365 {
366         assert(drawing_enable==1);
367
368         if (scale_up) {
369                 x *= 2;
370                 y *= 2;
371         }
372
373         assert(x<screen_width);
374         assert(y<screen_height);
375
376         dirty_blocks[page][(y>>dirty_block_shift)*25+(x>>dirty_block_shift)] = 1;
377
378         if (bytes_per_pixel==1)
379                 *(unsigned char *)get_vgaptr(page, x, y) = color;
380         else if (bytes_per_pixel==2)
381                 *(unsigned short *)get_vgaptr(page, x, y) = color;
382         else
383                 *(unsigned int *)get_vgaptr(page, x, y) = color;
384 }
385
386
387 static unsigned int colorMask = 0xF7DEF7DE;
388 static unsigned int lowPixelMask = 0x08210821;
389 static unsigned int qcolorMask = 0xE79CE79C;
390 static unsigned int qlowpixelMask = 0x18631863;
391 static unsigned int redblueMask = 0xF81F;
392 static unsigned int greenMask = 0x7E0;
393
394 int Init_2xSaI (unsigned int BitFormat)
395 {
396     if (BitFormat == 565)
397     {
398         colorMask = SWAP32(0xF7DEF7DE);
399         lowPixelMask = SWAP32(0x08210821);
400         qcolorMask = SWAP32(0xE79CE79C);
401         qlowpixelMask = SWAP32(0x18631863);
402         redblueMask = SWAP16(0xF81F);
403         greenMask = SWAP16(0x7E0);
404     }
405     else if (BitFormat == 555)
406     {
407         colorMask = SWAP32(0x7BDE7BDE);
408         lowPixelMask = SWAP32(0x04210421);
409         qcolorMask = SWAP32(0x739C739C);
410         qlowpixelMask = SWAP32(0x0C630C63);
411         redblueMask = SWAP16(0x7C1F);
412         greenMask = SWAP16(0x3E0);
413     }
414     else
415     {
416         return 0;
417     }
418
419 #ifdef MMX
420     Init_2xSaIMMX (BitFormat);
421 #endif
422
423     return 1;
424 }
425
426
427 void Scale2x (unsigned char *src, unsigned int src_pitch, int src_bytes_per_pixel,
428                  unsigned char *dst, unsigned int dst_pitch, int dst_bytes_per_pixel,
429                  int width, int height, int pal[256])
430 {
431 #define GET_COLOR(x) (pal[(x)])
432
433         int x,y;
434         unsigned char *src_line;
435         unsigned char *dst_line[2];
436
437         src_line = src;
438         dst_line[0] = dst;
439         dst_line[1] = dst + dst_pitch;
440         for (y=0; y<height; y++) {
441                 for (x=0; x<width; x++) {
442                         int color;
443
444                         if (src_bytes_per_pixel == 1) {
445                                 color = GET_COLOR(*(((unsigned char*)src_line) + x));
446                         } else if (src_bytes_per_pixel == 2) {
447                                 color = *(((unsigned short*)src_line) + x);
448                         } else {
449                                 color = *(((unsigned int*)src_line) + x);
450                         }
451
452                         if (dst_bytes_per_pixel == 2) {
453                                 *((unsigned long *) (&dst_line[0][x * 4])) = color | (color << 16);
454                                 *((unsigned long *) (&dst_line[1][x * 4])) = color | (color << 16);
455                         } else {
456                                 *((unsigned long *) (&dst_line[0][x * 8])) = color;
457                                 *((unsigned long *) (&dst_line[0][x * 8 + 4])) = color;
458                                 *((unsigned long *) (&dst_line[1][x * 8])) = color;
459                                 *((unsigned long *) (&dst_line[1][x * 8 + 4])) = color;
460                         }
461                 }
462
463                 src_line += src_pitch;
464
465                 if (y < height - 1) {
466                         dst_line[0] += dst_pitch * 2;
467                         dst_line[1] += dst_pitch * 2;
468                 }
469         }
470 }
471
472
473 void Super2xSaI (unsigned char *src, unsigned int src_pitch, int src_bytes_per_pixel,
474                  unsigned char *dst, unsigned int dst_pitch, int dst_bytes_per_pixel,
475                  int width, int height, int pal[256])
476 {
477 #define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D))
478
479 #define INTERPOLATE(A, B) (((A & colorMask) >> 1) + ((B & colorMask) >> 1) + (A & B & lowPixelMask))
480
481 #define Q_INTERPOLATE(A, B, C, D) ((A & qcolorMask) >> 2) + ((B & qcolorMask) >> 2) + ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2) \
482         + ((((A & qlowpixelMask) + (B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask)) >> 2) & qlowpixelMask)
483
484 #define GET_COLOR(x) (pal[(x)])
485
486         unsigned char *src_line[4];
487         unsigned char *dst_line[2];
488         int x, y;
489         unsigned long color[16];
490
491         if ( (width<2) || (height<2) ) {
492                 Scale2x(src, src_pitch, src_bytes_per_pixel, dst, dst_pitch, dst_bytes_per_pixel, width, height, pal);
493                 return;
494         }
495
496         /* Point to the first 3 lines. */
497         src_line[0] = src;
498         src_line[1] = src;
499         src_line[2] = src + src_pitch;
500         src_line[3] = src + (src_pitch * 2);
501         
502         dst_line[0] = dst;
503         dst_line[1] = dst + dst_pitch;
504         
505         x = 0, y = 0;
506         
507         if (src_bytes_per_pixel == 1) {
508                 unsigned char *sbp;
509                 sbp = src_line[0];
510                 color[0] = GET_COLOR(*sbp);       color[1] = color[0];   color[2] = color[0];    color[3] = color[0];
511                 color[4] = color[0];   color[5] = color[0];   color[6] = GET_COLOR(*(sbp + 1));  color[7] = GET_COLOR(*(sbp + 2));
512                 sbp = src_line[2];
513                 color[8] = GET_COLOR(*sbp);     color[9] = color[8];     color[10] = GET_COLOR(*(sbp + 1)); color[11] = GET_COLOR(*(sbp + 2));
514                 sbp = src_line[3];
515                 color[12] = GET_COLOR(*sbp);    color[13] = color[12];   color[14] = GET_COLOR(*(sbp + 1)); color[15] = GET_COLOR(*(sbp + 2));
516         } else if (src_bytes_per_pixel == 2) {
517                 unsigned short *sbp;
518                 sbp = (unsigned short*)src_line[0];
519                 color[0] = *sbp;       color[1] = color[0];   color[2] = color[0];    color[3] = color[0];
520                 color[4] = color[0];   color[5] = color[0];   color[6] = *(sbp + 1);  color[7] = *(sbp + 2);
521                 sbp = (unsigned short*)src_line[2];
522                 color[8] = *sbp;     color[9] = color[8];     color[10] = *(sbp + 1); color[11] = *(sbp + 2);
523                 sbp = (unsigned short*)src_line[3];
524                 color[12] = *sbp;    color[13] = color[12];   color[14] = *(sbp + 1); color[15] = *(sbp + 2);
525         } else {
526                 unsigned long *lbp;
527                 lbp = (unsigned long*)src_line[0];
528                 color[0] = *lbp;       color[1] = color[0];   color[2] = color[0];    color[3] = color[0];
529                 color[4] = color[0];   color[5] = color[0];   color[6] = *(lbp + 1);  color[7] = *(lbp + 2);
530                 lbp = (unsigned long*)src_line[2];
531                 color[8] = *lbp;     color[9] = color[8];     color[10] = *(lbp + 1); color[11] = *(lbp + 2);
532                 lbp = (unsigned long*)src_line[3];
533                 color[12] = *lbp;    color[13] = color[12];   color[14] = *(lbp + 1); color[15] = *(lbp + 2);
534         }
535
536         for (y = 0; y < height; y++) {
537         
538                 /* Todo: x = width - 2, x = width - 1 */
539                 
540                 for (x = 0; x < width; x++) {
541                         unsigned long product1a, product1b, product2a, product2b;
542
543 //---------------------------------------  B0 B1 B2 B3    0  1  2  3
544 //                                         4  5* 6  S2 -> 4  5* 6  7
545 //                                         1  2  3  S1    8  9 10 11
546 //                                         A0 A1 A2 A3   12 13 14 15
547 //--------------------------------------
548                         if (color[9] == color[6] && color[5] != color[10]) {
549                                 product2b = color[9];
550                                 product1b = product2b;
551                         }
552                         else if (color[5] == color[10] && color[9] != color[6]) {
553                                 product2b = color[5];
554                                 product1b = product2b;
555                         }
556                         else if (color[5] == color[10] && color[9] == color[6]) {
557                                 int r = 0;
558
559                                 r += GET_RESULT(color[6], color[5], color[8], color[13]);
560                                 r += GET_RESULT(color[6], color[5], color[4], color[1]);
561                                 r += GET_RESULT(color[6], color[5], color[14], color[11]);
562                                 r += GET_RESULT(color[6], color[5], color[2], color[7]);
563
564                                 if (r > 0)
565                                         product1b = color[6];
566                                 else if (r < 0)
567                                         product1b = color[5];
568                                 else
569                                         product1b = INTERPOLATE(color[5], color[6]);
570                                         
571                                 product2b = product1b;
572
573                         }
574                         else {
575                                 if (color[6] == color[10] && color[10] == color[13] && color[9] != color[14] && color[10] != color[12])
576                                         product2b = Q_INTERPOLATE(color[10], color[10], color[10], color[9]);
577                                 else if (color[5] == color[9] && color[9] == color[14] && color[13] != color[10] && color[9] != color[15])
578                                         product2b = Q_INTERPOLATE(color[9], color[9], color[9], color[10]);
579                                 else
580                                         product2b = INTERPOLATE(color[9], color[10]);
581
582                                 if (color[6] == color[10] && color[6] == color[1] && color[5] != color[2] && color[6] != color[0])
583                                         product1b = Q_INTERPOLATE(color[6], color[6], color[6], color[5]);
584                                 else if (color[5] == color[9] && color[5] == color[2] && color[1] != color[6] && color[5] != color[3])
585                                         product1b = Q_INTERPOLATE(color[6], color[5], color[5], color[5]);
586                                 else
587                                         product1b = INTERPOLATE(color[5], color[6]);
588                         }
589
590                         if (color[5] == color[10] && color[9] != color[6] && color[4] == color[5] && color[5] != color[14])
591                                 product2a = INTERPOLATE(color[9], color[5]);
592                         else if (color[5] == color[8] && color[6] == color[5] && color[4] != color[9] && color[5] != color[12])
593                                 product2a = INTERPOLATE(color[9], color[5]);
594                         else
595                                 product2a = color[9];
596
597                         if (color[9] == color[6] && color[5] != color[10] && color[8] == color[9] && color[9] != color[2])
598                                 product1a = INTERPOLATE(color[9], color[5]);
599                         else if (color[4] == color[9] && color[10] == color[9] && color[8] != color[5] && color[9] != color[0])
600                                 product1a = INTERPOLATE(color[9], color[5]);
601                         else
602                                 product1a = color[5];
603         
604                         if (dst_bytes_per_pixel == 2) {
605                                 *((unsigned long *) (&dst_line[0][x * 4])) = product1a | (product1b << 16);
606                                 *((unsigned long *) (&dst_line[1][x * 4])) = product2a | (product2b << 16);
607                         } else {
608                                 *((unsigned long *) (&dst_line[0][x * 8])) = product1a;
609                                 *((unsigned long *) (&dst_line[0][x * 8 + 4])) = product1b;
610                                 *((unsigned long *) (&dst_line[1][x * 8])) = product2a;
611                                 *((unsigned long *) (&dst_line[1][x * 8 + 4])) = product2b;
612                         }
613                         
614                         /* Move color matrix forward */
615                         color[0] = color[1]; color[4] = color[5]; color[8] = color[9];   color[12] = color[13];
616                         color[1] = color[2]; color[5] = color[6]; color[9] = color[10];  color[13] = color[14];
617                         color[2] = color[3]; color[6] = color[7]; color[10] = color[11]; color[14] = color[15];
618                         
619                         if (x < width - 3) {
620                                 x+=3;
621                                 if (src_bytes_per_pixel == 1) {
622                                         color[3] = GET_COLOR(*(((unsigned char*)src_line[0]) + x));
623                                         color[7] = GET_COLOR(*(((unsigned char*)src_line[1]) + x));
624                                         color[11] = GET_COLOR(*(((unsigned char*)src_line[2]) + x));
625                                         color[15] = GET_COLOR(*(((unsigned char*)src_line[3]) + x));
626                                 } else if (src_bytes_per_pixel == 2) {
627                                         color[3] = *(((unsigned short*)src_line[0]) + x);                                       
628                                         color[7] = *(((unsigned short*)src_line[1]) + x);
629                                         color[11] = *(((unsigned short*)src_line[2]) + x);
630                                         color[15] = *(((unsigned short*)src_line[3]) + x);
631                                 } else {
632                                         color[3] = *(((unsigned long*)src_line[0]) + x);
633                                         color[7] = *(((unsigned long*)src_line[1]) + x);
634                                         color[11] = *(((unsigned long*)src_line[2]) + x);
635                                         color[15] = *(((unsigned long*)src_line[3]) + x);
636                                 }
637                                 x-=3;
638                         }
639                 }
640
641                 /* We're done with one line, so we shift the source lines up */
642                 src_line[0] = src_line[1];
643                 src_line[1] = src_line[2];
644                 src_line[2] = src_line[3];              
645
646                 /* Read next line */
647                 if (y + 3 >= height)
648                         src_line[3] = src_line[2];
649                 else
650                         src_line[3] = src_line[2] + src_pitch;
651                         
652                 /* Then shift the color matrix up */
653                 if (src_bytes_per_pixel == 1) {
654                         unsigned char *sbp;
655                         sbp = src_line[0];
656                         color[0] = GET_COLOR(*sbp);     color[1] = color[0];    color[2] = GET_COLOR(*(sbp + 1));  color[3] = GET_COLOR(*(sbp + 2));
657                         sbp = src_line[1];
658                         color[4] = GET_COLOR(*sbp);     color[5] = color[4];    color[6] = GET_COLOR(*(sbp + 1));  color[7] = GET_COLOR(*(sbp + 2));
659                         sbp = src_line[2];
660                         color[8] = GET_COLOR(*sbp);     color[9] = color[8];    color[10] = GET_COLOR(*(sbp + 1)); color[11] = GET_COLOR(*(sbp + 2));
661                         sbp = src_line[3];
662                         color[12] = GET_COLOR(*sbp);    color[13] = color[12];  color[14] = GET_COLOR(*(sbp + 1)); color[15] = GET_COLOR(*(sbp + 2));
663                 } else if (src_bytes_per_pixel == 2) {
664                         unsigned short *sbp;
665                         sbp = (unsigned short*)src_line[0];
666                         color[0] = *sbp;     color[1] = color[0];    color[2] = *(sbp + 1);  color[3] = *(sbp + 2);
667                         sbp = (unsigned short*)src_line[1];
668                         color[4] = *sbp;     color[5] = color[4];    color[6] = *(sbp + 1);  color[7] = *(sbp + 2);
669                         sbp = (unsigned short*)src_line[2];
670                         color[8] = *sbp;     color[9] = color[9];    color[10] = *(sbp + 1); color[11] = *(sbp + 2);
671                         sbp = (unsigned short*)src_line[3];
672                         color[12] = *sbp;    color[13] = color[12];  color[14] = *(sbp + 1); color[15] = *(sbp + 2);
673                 } else {
674                         unsigned long *lbp;
675                         lbp = (unsigned long*)src_line[0];
676                         color[0] = *lbp;     color[1] = color[0];    color[2] = *(lbp + 1);  color[3] = *(lbp + 2);
677                         lbp = (unsigned long*)src_line[1];
678                         color[4] = *lbp;     color[5] = color[4];    color[6] = *(lbp + 1);  color[7] = *(lbp + 2);
679                         lbp = (unsigned long*)src_line[2];
680                         color[8] = *lbp;     color[9] = color[9];    color[10] = *(lbp + 1); color[11] = *(lbp + 2);
681                         lbp = (unsigned long*)src_line[3];
682                         color[12] = *lbp;    color[13] = color[12];  color[14] = *(lbp + 1); color[15] = *(lbp + 2);
683                 }
684                 
685                 if (y < height - 1) {
686                         dst_line[0] += dst_pitch * 2;
687                         dst_line[1] += dst_pitch * 2;
688                 }
689         }
690 }
691
692
693 void flippage(int page)
694 {
695         int x,y;
696         unsigned char *src;
697         unsigned char *dest;
698
699         assert(drawing_enable==0);
700
701         SDL_LockSurface(jnb_surface);
702         if (!jnb_surface->pixels) {
703                 
704                 for (x=0; x<(25*16); x++) {
705                         dirty_blocks[0][x] = 1;
706                         dirty_blocks[1][x] = 1;
707                 }
708
709                 return;
710         }
711 #ifdef SCALE_UP
712         dest=(unsigned char *)jnb_surface->pixels;
713         src=screen_buffer[page];
714         Super2xSaI(src, JNB_WIDTH, 1, dest, jnb_surface->pitch, 2, JNB_WIDTH, JNB_HEIGHT, current_pal);
715 #else
716         dest=(unsigned char *)jnb_surface->pixels;
717         src=screen_buffer[page];
718         for (y=0; y<screen_height; y++) {
719                 //memset(&dest[y*jnb_surface->pitch],0,JNB_SURFACE_WIDTH*bytes_per_pixel);
720                 for (x=0; x<25; x++) {
721                         int count;
722                         int test_x;
723
724                         count=0;
725                         test_x=x;
726                         while ( (test_x<25) && (dirty_blocks[page][(y>>dirty_block_shift)*25+test_x]) ) {
727                                 count++;
728                                 test_x++;
729                         }
730                         if (count) {
731                                 memcpy( &dest[y*jnb_surface->pitch+(x<<dirty_block_shift)*bytes_per_pixel],
732                                         &src[y*screen_pitch+((x<<dirty_block_shift)*bytes_per_pixel)],
733                                         ((16<<dirty_block_shift)>>4)*bytes_per_pixel*count);
734                                 //*((pixel_t *)(&dest[(y>>dirty_block_shift)*jnb_surface->pitch+x*bytes_per_pixel]))=0xe0e0;
735                         }
736                         x = test_x;
737                 }
738         }
739         memset(&dirty_blocks[page], 0, sizeof(int)*25*16);
740 #endif
741         SDL_UnlockSurface(jnb_surface);
742         SDL_Flip(jnb_surface);
743 }
744
745
746 void draw_begin(void)
747 {
748         assert(drawing_enable==0);
749
750         drawing_enable = 1;
751         if (background_drawn == 0) {
752                 if (background) {
753                         put_block(0, 0, 0, JNB_WIDTH, JNB_HEIGHT, background);
754                         put_block(1, 0, 0, JNB_WIDTH, JNB_HEIGHT, background);
755                         //put_block(0, 0, 0, rabbit_gobs.width[1], rabbit_gobs.height[1], rabbit_gobs.data[1]);
756                         //put_block(1, 0, 0, rabbit_gobs.width[1], rabbit_gobs.height[1], rabbit_gobs.data[1]);
757                 } else {
758                         clear_page(0, 0);
759                         clear_page(1, 0);
760                 }
761                 background_drawn = 1;
762         }
763 }
764
765
766 void draw_end(void)
767 {
768         assert(drawing_enable==1);
769
770         drawing_enable = 0;
771 }
772
773
774 void setpalette(int index, int count, char *palette)
775 {
776         SDL_Color colors[256];
777         int i;
778
779         assert(drawing_enable==0);
780
781         for (i = 0; i < count; i++) {
782                 colors[i+index].r = palette[i * 3 + 0] << 2;
783                 colors[i+index].g = palette[i * 3 + 1] << 2;
784                 colors[i+index].b = palette[i * 3 + 2] << 2;
785                 current_pal[i+index] = SDL_MapRGB(jnb_surface->format, colors[i+index].r, colors[i+index].g, colors[i+index].b);
786         }
787         if (!scale_up)
788                 SDL_SetColors(jnb_surface, &colors[index], index, count);
789 }
790
791
792 void fillpalette(int red, int green, int blue)
793 {
794         SDL_Color colors[256];
795         int i;
796
797         assert(drawing_enable==0);
798
799         for (i = 0; i < 256; i++) {
800                 colors[i].r = red << 2;
801                 colors[i].g = green << 2;
802                 colors[i].b = blue << 2;
803                 current_pal[i] = SDL_MapRGB(jnb_surface->format, colors[i].r, colors[i].g, colors[i].b);
804         }
805         if (!scale_up)
806                 SDL_SetColors(jnb_surface, colors, 0, 256);
807 }
808
809
810 void get_block(int page, int x, int y, int width, int height, void *buffer)
811 {
812         unsigned char *buffer_ptr, *vga_ptr;
813         int h;
814
815         assert(drawing_enable==1);
816
817         if (scale_up) {
818                 x *= 2;
819                 y *= 2;
820                 width *= 2;
821                 height *= 2;
822         }
823
824         if (x < 0)
825                 x = 0;
826         if (y < 0)
827                 y = 0;
828         if (y + height >= screen_height)
829                 height = screen_height - y;
830         if (x + width >= screen_width)
831                 width = screen_width - x;
832         if (width<=0)
833                 return;
834         if(height<=0)
835                 return;
836
837         vga_ptr = get_vgaptr(page, x, y);
838         buffer_ptr = buffer;
839         for (h = 0; h < height; h++) {
840                 memcpy(buffer_ptr, vga_ptr, width * bytes_per_pixel);
841                 vga_ptr += screen_pitch;
842                 buffer_ptr += width * bytes_per_pixel;
843         }
844
845 }
846
847
848 void put_block(int page, int x, int y, int width, int height, void *buffer)
849 {
850         int h;
851         unsigned char *vga_ptr, *buffer_ptr;
852
853         assert(drawing_enable==1);
854
855         if (scale_up) {
856                 x *= 2;
857                 y *= 2;
858                 width *= 2;
859                 height *= 2;
860         }
861
862         if (x < 0)
863                 x = 0;
864         if (y < 0)
865                 y = 0;
866         if (y + height >= screen_height)
867                 height = screen_height - y;
868         if (x + width >= screen_width)
869                 width = screen_width - x;
870         if (width<=0)
871                 return;
872         if(height<=0)
873                 return;
874
875         vga_ptr = get_vgaptr(page, x, y);
876         buffer_ptr = buffer;
877         for (h = 0; h < height; h++) {
878                 memcpy(vga_ptr, buffer_ptr, width * bytes_per_pixel);
879                 vga_ptr += screen_pitch;
880                 buffer_ptr += width * bytes_per_pixel;
881         }
882         width = ((x+width)>>dirty_block_shift) - (x>>dirty_block_shift) + 1;
883         height = ((y+height)>>dirty_block_shift) - (y>>dirty_block_shift) + 1;
884         x >>= dirty_block_shift;
885         y >>= dirty_block_shift;
886         while (width--)
887                 for (h=0; h<height; h++)
888                         dirty_blocks[page][(y+h)*25+(x+width)] = 1;
889 }
890
891
892 void put_text(int page, int x, int y, char *text, int align)
893 {
894         int c1;
895         int t1;
896         int width;
897         int cur_x;
898         int image;
899
900         assert(drawing_enable==1);
901
902         if (text == NULL || strlen(text) == 0)
903                 return;
904         if (font_gobs.num_images == 0)
905                 return;
906
907         width = 0;
908         c1 = 0;
909         while (text[c1] != 0) {
910                 t1 = text[c1];
911                 c1++;
912                 if (t1 == ' ') {
913                         width += 5;
914                         continue;
915                 }
916                 if (t1 >= 33 && t1 <= 34)
917                         image = t1 - 33;
918
919                 else if (t1 >= 39 && t1 <= 41)
920                         image = t1 - 37;
921
922                 else if (t1 >= 44 && t1 <= 59)
923                         image = t1 - 39;
924
925                 else if (t1 >= 64 && t1 <= 90)
926                         image = t1 - 43;
927
928                 else if (t1 >= 97 && t1 <= 122)
929                         image = t1 - 49;
930
931                 else if (t1 == '~')
932                         image = 74;
933
934                 else if (t1 == 0x84)
935                         image = 75;
936
937                 else if (t1 == 0x86)
938                         image = 76;
939
940                 else if (t1 == 0x8e)
941                         image = 77;
942
943                 else if (t1 == 0x8f)
944                         image = 78;
945
946                 else if (t1 == 0x94)
947                         image = 79;
948
949                 else if (t1 == 0x99)
950                         image = 80;
951
952                 else
953                         continue;
954                 width += pob_width(image, &font_gobs) + 1;
955         }
956
957         switch (align) {
958         case 0:
959                 cur_x = x;
960                 break;
961         case 1:
962                 cur_x = x - width;
963                 break;
964         case 2:
965                 cur_x = x - width / 2;
966                 break;
967         default:
968                 cur_x = 0;      /* this should cause error? -Chuck */
969                 break;
970         }
971         c1 = 0;
972
973         while (text[c1] != 0) {
974                 t1 = text[c1];
975                 c1++;
976                 if (t1 == ' ') {
977                         cur_x += 5;
978                         continue;
979                 }
980                 if (t1 >= 33 && t1 <= 34)
981                         image = t1 - 33;
982
983                 else if (t1 >= 39 && t1 <= 41)
984                         image = t1 - 37;
985
986                 else if (t1 >= 44 && t1 <= 59)
987                         image = t1 - 39;
988
989                 else if (t1 >= 64 && t1 <= 90)
990                         image = t1 - 43;
991
992                 else if (t1 >= 97 && t1 <= 122)
993                         image = t1 - 49;
994
995                 else if (t1 == '~')
996                         image = 74;
997
998                 else if (t1 == 0x84)
999                         image = 75;
1000
1001                 else if (t1 == 0x86)
1002                         image = 76;
1003
1004                 else if (t1 == 0x8e)
1005                         image = 77;
1006
1007                 else if (t1 == 0x8f)
1008                         image = 78;
1009
1010                 else if (t1 == 0x94)
1011                         image = 79;
1012
1013                 else if (t1 == 0x99)
1014                         image = 80;
1015
1016                 else
1017                         continue;
1018                 put_pob(page, cur_x, y, image, &font_gobs, 1, mask_pic);
1019                 cur_x += pob_width(image, &font_gobs) + 1;
1020         }
1021 }
1022
1023
1024 void put_pob(int page, int x, int y, int image, gob_t *gob, int use_mask, void *mask_pic)
1025 {
1026         int c1, c2;
1027         int pob_x, pob_y;
1028         int width, height;
1029         int draw_width, draw_height;
1030         int colour;
1031
1032         assert(drawing_enable==1);
1033         assert(gob);
1034         assert(image>=0);
1035         assert(image<gob->num_images);
1036
1037         if (scale_up) {
1038                 x *= 2;
1039                 y *= 2;
1040                 width = draw_width = gob->width[image]*2;
1041                 height = draw_height = gob->height[image]*2;
1042                 x -= gob->hs_x[image]*2;
1043                 y -= gob->hs_y[image]*2;
1044         } else {
1045                 width = draw_width = gob->width[image];
1046                 height = draw_height = gob->height[image];
1047                 x -= gob->hs_x[image];
1048                 y -= gob->hs_y[image];
1049         }
1050
1051         if ((x + width) <= 0 || x >= screen_width)
1052                 return;
1053         if ((y + height) <= 0 || y >= screen_height)
1054                 return;
1055
1056         pob_x = 0;
1057         pob_y = 0;
1058         if (x < 0) {
1059                 pob_x -= x;
1060                 draw_width += x;
1061                 x = 0;
1062         }
1063         if ((x + width) > screen_width)
1064                 draw_width -= x + width - screen_width;
1065         if (y < 0) {
1066                 pob_y -= y;
1067                 draw_height += y;
1068                 y = 0;
1069         }
1070         if ((y + height) > screen_height)
1071                 draw_height -= y + height - screen_height;
1072
1073
1074         if (bytes_per_pixel==1) {
1075                 unsigned char *vga_ptr;
1076                 unsigned char *pob_ptr;
1077                 unsigned char *mask_ptr;
1078
1079                 vga_ptr = get_vgaptr(page, x, y);
1080                 pob_ptr = ((unsigned char *)gob->data[image]) + ((pob_y * width) + pob_x);
1081                 mask_ptr = ((unsigned char *)mask) + ((y * screen_pitch) + (x*bytes_per_pixel));
1082                 for (c1 = 0; c1 < draw_height; c1++) {
1083                         for (c2 = 0; c2 < draw_width; c2++) {
1084                                 colour = *mask_ptr;
1085                                 if (use_mask == 0 || (use_mask == 1 && colour == 0)) {
1086                                         colour = *pob_ptr;
1087                                         if (colour != 0) {
1088                                                 *vga_ptr = colour;
1089                                         }
1090                                 }
1091                                 vga_ptr++;
1092                                 pob_ptr++;
1093                                 mask_ptr++;
1094                         }
1095                         pob_ptr += width - c2;
1096                         vga_ptr += (screen_width - c2);
1097                         mask_ptr += (screen_width - c2);
1098                 }
1099         } else if (bytes_per_pixel==2) {
1100                 unsigned short *vga_ptr;
1101                 unsigned short *pob_ptr;
1102                 unsigned short *mask_ptr;
1103
1104                 vga_ptr = get_vgaptr(page, x, y);
1105                 pob_ptr = (unsigned short *)(((unsigned char *)gob->data[image]) + ((pob_y * width) + pob_x));
1106                 mask_ptr = (unsigned short *)(((unsigned char *)mask) + ((y * screen_pitch) + (x*bytes_per_pixel)));
1107                 for (c1 = 0; c1 < draw_height; c1++) {
1108                         for (c2 = 0; c2 < draw_width; c2++) {
1109                                 colour = *mask_ptr;
1110                                 if (use_mask == 0 || (use_mask == 1 && colour == 0)) {
1111                                         colour = *pob_ptr;
1112                                         if (colour != 0) {
1113                                                 *vga_ptr = colour;
1114                                         }
1115                                 }
1116                                 vga_ptr++;
1117                                 pob_ptr++;
1118                                 mask_ptr++;
1119                         }
1120                         pob_ptr += width - c2;
1121                         vga_ptr += (screen_width - c2);
1122                         mask_ptr += (screen_width - c2);
1123                 }
1124         } else {
1125                 unsigned int *vga_ptr;
1126                 unsigned int *pob_ptr;
1127                 unsigned int *mask_ptr;
1128
1129                 vga_ptr = get_vgaptr(page, x, y);
1130                 pob_ptr = (unsigned int *)(((unsigned char *)gob->data[image]) + ((pob_y * width) + pob_x));
1131                 mask_ptr = (unsigned int *)(((unsigned char *)mask) + ((y * screen_pitch) + (x*bytes_per_pixel)));
1132                 for (c1 = 0; c1 < draw_height; c1++) {
1133                         for (c2 = 0; c2 < draw_width; c2++) {
1134                                 colour = *mask_ptr;
1135                                 if (use_mask == 0 || (use_mask == 1 && colour == 0)) {
1136                                         colour = *pob_ptr;
1137                                         if (colour != 0) {
1138                                                 *vga_ptr = colour;
1139                                         }
1140                                 }
1141                                 vga_ptr++;
1142                                 pob_ptr++;
1143                                 mask_ptr++;
1144                         }
1145                         pob_ptr += width - c2;
1146                         vga_ptr += (screen_width - c2);
1147                         mask_ptr += (screen_width - c2);
1148                 }
1149         }
1150         draw_width = ((x+draw_width)>>dirty_block_shift) - (x>>dirty_block_shift) + 1;
1151         draw_height = ((y+draw_height)>>dirty_block_shift) - (y>>dirty_block_shift) + 1;
1152         x >>= dirty_block_shift;
1153         y >>= dirty_block_shift;
1154         while (draw_width--)
1155                 for (c1=0; c1<draw_height; c1++)
1156                         dirty_blocks[page][(y+c1)*25+(x+draw_width)] = 1;
1157 }
1158
1159
1160 int pob_width(int image, gob_t *gob)
1161 {
1162         assert(gob);
1163         assert(image>=0);
1164         assert(image<gob->num_images);
1165         return gob->width[image];
1166 }
1167
1168
1169 int pob_height(int image, gob_t *gob)
1170 {
1171         assert(gob);
1172         assert(image>=0);
1173         assert(image<gob->num_images);
1174         return gob->height[image];
1175 }
1176
1177
1178 int pob_hs_x(int image, gob_t *gob)
1179 {
1180         assert(gob);
1181         assert(image>=0);
1182         assert(image<gob->num_images);
1183         return gob->hs_x[image];
1184 }
1185
1186
1187 int pob_hs_y(int image, gob_t *gob)
1188 {
1189         assert(gob);
1190         assert(image>=0);
1191         assert(image<gob->num_images);
1192         return gob->hs_y[image];
1193 }
1194
1195
1196 int read_pcx(FILE * handle, void *buf, int buf_len, char *pal)
1197 {
1198         unsigned char *buffer=buf;
1199         short c1;
1200         short a, b;
1201         long ofs1;
1202         if (buffer != 0) {
1203                 fseek(handle, 128, SEEK_CUR);
1204                 ofs1 = 0;
1205                 while (ofs1 < buf_len) {
1206                         a = fgetc(handle);
1207                         if ((a & 0xc0) == 0xc0) {
1208                                 b = fgetc(handle);
1209                                 a &= 0x3f;
1210                                 for (c1 = 0; c1 < a && ofs1 < buf_len; c1++)
1211                                         buffer[ofs1++] = (char) b;
1212                         } else
1213                                 buffer[ofs1++] = (char) a;
1214                 }
1215                 if (pal != 0) {
1216                         fseek(handle, 1, SEEK_CUR);
1217                         for (c1 = 0; c1 < 768; c1++)
1218                                 pal[c1] = fgetc(handle) >> 2;
1219                 }
1220         }
1221         return 0;
1222 }
1223
1224
1225 void register_background(char *pixels, char pal[768])
1226 {
1227         if (background) {
1228                 free(background);
1229                 background = NULL;
1230         }
1231         background_drawn = 0;
1232         if (!pixels)
1233                 return;
1234         assert(pal);
1235         if (scale_up) {
1236                 int int_pal[256];
1237                 int i;
1238
1239                 for (i=0; i<256; i++)
1240                         int_pal[i] = SDL_MapRGB(jnb_surface->format, (Uint8)(pal[i*3+0]<<2), (Uint8)(pal[i*3+1]<<2), (Uint8)(pal[i*3+2]<<2));
1241                 background = malloc(screen_pitch*screen_height);
1242                 assert(background);
1243                 Super2xSaI(pixels, JNB_WIDTH, 1, (unsigned char *)background, screen_pitch, bytes_per_pixel, JNB_WIDTH, JNB_HEIGHT, int_pal);
1244         } else {
1245                 background = malloc(JNB_WIDTH*JNB_HEIGHT);
1246                 assert(background);
1247                 memcpy(background, pixels, JNB_WIDTH*JNB_HEIGHT);
1248         }
1249 }
1250
1251 int register_gob(FILE *handle, gob_t *gob, int len)
1252 {
1253         unsigned char *gob_data;
1254         int i;
1255
1256         gob_data = malloc(len);
1257         fread(gob_data, 1, len, handle);
1258
1259         gob->num_images = (short)((gob_data[0]) + (gob_data[1] << 8));
1260
1261         gob->width = malloc(gob->num_images*sizeof(int));
1262         gob->height = malloc(gob->num_images*sizeof(int));
1263         gob->hs_x = malloc(gob->num_images*sizeof(int));
1264         gob->hs_y = malloc(gob->num_images*sizeof(int));
1265         gob->data = malloc(gob->num_images*sizeof(void *));
1266         gob->orig_data = malloc(gob->num_images*sizeof(void *));
1267         for (i=0; i<gob->num_images; i++) {
1268                 int image_size;
1269                 int offset;
1270
1271                 offset = (gob_data[i*4+2]) + (gob_data[i*4+3] << 8) + (gob_data[i*4+4] << 16) + (gob_data[i*4+5] << 24);
1272
1273                 gob->width[i]  = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2;
1274                 gob->height[i] = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2;
1275                 gob->hs_x[i]   = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2;
1276                 gob->hs_y[i]   = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2;
1277
1278                 image_size = gob->width[i] * gob->height[i];
1279                 gob->orig_data[i] = malloc(image_size);
1280                 memcpy(gob->orig_data[i], &gob_data[offset], image_size);
1281                 if (scale_up) {
1282                         image_size = gob->width[i] * gob->height[i] * 4 * bytes_per_pixel;
1283                         gob->data[i] = malloc(image_size);
1284                 } else {
1285                         gob->data[i] = (unsigned short *)gob->orig_data[i];
1286                 }
1287         }
1288         free(gob_data);
1289         return 0;
1290 }
1291
1292
1293 void recalculate_gob(gob_t *gob, char pal[768])
1294 {
1295         int int_pal[256];
1296         int i;
1297
1298         if (!scale_up)
1299                 return;
1300
1301         for (i=1; i<256; i++) {
1302                 int_pal[i] = SDL_MapRGB(jnb_surface->format, (Uint8)(pal[i*3+0]<<2), (Uint8)(pal[i*3+1]<<2), (Uint8)(pal[i*3+2]<<2));
1303                 if (int_pal[i] == 0)
1304                         int_pal[i] = SDL_MapRGB(jnb_surface->format, 8, 8, 8);
1305         }
1306         int_pal[0] = 0;
1307
1308         for (i=0; i<gob->num_images; i++) {
1309                 Super2xSaI(gob->orig_data[i], gob->width[i], 1, (unsigned char *)gob->data[i], gob->width[i]*2*bytes_per_pixel, bytes_per_pixel, gob->width[i], gob->height[i], int_pal);
1310         }
1311 }
1312
1313 void register_mask(void *pixels)
1314 {
1315         if (mask) {
1316                 free(mask);
1317                 mask = NULL;
1318         }
1319         assert(pixels);
1320         if (scale_up) {
1321                 int int_pal[256];
1322                 int i;
1323
1324                 int_pal[0] = 0;
1325                 for (i=1; i<256; i++)
1326                         int_pal[i] = 0xffffffff;
1327                 mask = malloc(screen_pitch*screen_height);
1328                 assert(mask);
1329                 Scale2x(pixels, JNB_WIDTH, 1, (unsigned char *)mask, screen_pitch, bytes_per_pixel, JNB_WIDTH, JNB_HEIGHT, int_pal);
1330         } else {
1331                 mask = malloc(JNB_WIDTH*JNB_HEIGHT);
1332                 assert(mask);
1333                 memcpy(mask, pixels, JNB_WIDTH*JNB_HEIGHT);
1334         }
1335 }