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