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