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