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