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