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  * Copyright (C) 2015 Côme Chilliet <come@chilliet.eu>
10  *
11  * This file is part of Jump 'n Bump.
12  *
13  * Jump 'n Bump is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * Jump 'n Bump is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
26  */
27 
28 #include "globals.h"
29 #include "SDL_endian.h"
30 #include "filter.h"
31 
32 #ifdef _WIN32
33     #include "jumpnbump32.xpm"
34 #elif __APPLE__
35     #include "jumpnbump128.xpm"
36 #else
37     #include "jumpnbump64.xpm"
38 #endif
39 SDL_Surface *icon;
40 
41 int screen_width=400;
42 int screen_height=256;
43 int screen_pitch=400;
44 int scale_up=0;
45 int dirty_block_shift=4;
46 
47 static SDL_Window *sdlWindow;
48 static SDL_Renderer *sdlRenderer;
49 static SDL_Texture *jnb_texture;
50 static SDL_Surface *jnb_surface;
51 static int fullscreen = 0;
52 static int vinited = 0;
53 static void *screen_buffer[2];
54 static int drawing_enable = 0;
55 static void *background = NULL;
56 static int background_drawn;
57 static void *mask = NULL;
58 static int dirty_blocks[2][25*16*2];
59 
load_xpm_from_array(char ** xpm)60 static SDL_Surface *load_xpm_from_array(char **xpm)
61 {
62 #define NEXT_TOKEN { \
63 	while ((*p != ' ') && (*p != '\t')) p++; \
64 	while ((*p == ' ') || (*p == '\t')) p++; }
65 
66 	SDL_Surface *surface;
67 	char *p;
68 	int width;
69 	int height;
70 	int colors;
71 	int images;
72 	int color;
73 	int pal[256];
74 	int x,y;
75 
76 	p = *xpm++;
77 
78 	width = atoi(p);
79 	if (width <= 0)
80 		return NULL;
81 	NEXT_TOKEN;
82 
83 	height = atoi(p);
84 	if (height <= 0)
85 		return NULL;
86 	NEXT_TOKEN;
87 
88 	colors = atoi(p);
89 	if (colors <= 0)
90 		return NULL;
91 	NEXT_TOKEN;
92 
93 	images = atoi(p);
94 	if (images <= 0)
95 		return NULL;
96 
97 	surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
98 	if (!surface)
99 		return NULL;
100 
101 	SDL_SetColorKey(surface, SDL_TRUE, SDL_MapRGBA(surface->format, 0, 0, 0, 0));
102 	while (colors--) {
103 		p = *xpm++;
104 
105 		color = *p++;
106 		NEXT_TOKEN;
107 
108 		if (*p++ != 'c') {
109 			SDL_FreeSurface(surface);
110 			return NULL;
111 		}
112 		NEXT_TOKEN;
113 
114 		if (*p == '#')
115 			pal[color] = strtoul(++p, NULL, 16) | 0xff000000;
116 		else
117 			pal[color] = 0;
118 	}
119 
120 	y = 0;
121 	while (y < height) {
122 		int *pixels;
123 
124 		p = *xpm++;
125 
126 		pixels = (int *)&((char *)surface->pixels)[y++ * surface->pitch];
127 		x = 0;
128 		while (x < width) {
129 			Uint8 r,g,b,a;
130 
131 			if (*p == '\0') {
132 				SDL_FreeSurface(surface);
133 				return NULL;
134 			}
135 			r = (pal[(int)*p] >> 16) & 0xff;
136 			b = (pal[(int)*p] & 0xff);
137 			g = (pal[(int)*p] >> 8) & 0xff;
138 			a = (pal[(int)*p] >> 24) & 0xff;
139 			pixels[x] = SDL_MapRGBA(surface->format, r, g, b, a);
140 			x++;
141 			p++;
142 		}
143 	}
144 
145 	return surface;
146 }
147 
get_vgaptr(int page,int x,int y)148 unsigned char *get_vgaptr(int page, int x, int y)
149 {
150 	assert(drawing_enable==1);
151 
152 	return (unsigned char *)screen_buffer[page] + (y*screen_pitch)+(x);
153 }
154 
155 
set_scaling(int scale)156 void set_scaling(int scale)
157 {
158 	if (scale==1) {
159 		screen_width=800;
160 		screen_height=512;
161 		scale_up=1;
162 		dirty_block_shift=5;
163 		screen_pitch=screen_width;
164 	} else {
165 		screen_width=400;
166 		screen_height=256;
167 		scale_up=0;
168 		dirty_block_shift=4;
169 		screen_pitch=screen_width;
170 	}
171 }
172 
open_screen(void)173 void open_screen(void)
174 {
175 	int lval = 0;
176 	int flags;
177 
178 	lval = SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
179 	if (lval < 0) {
180 		fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError());
181 		exit(EXIT_FAILURE);
182 	}
183 
184 	flags = SDL_WINDOW_RESIZABLE;
185 	if (fullscreen)
186 		flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
187 	SDL_CreateWindowAndRenderer(screen_width, screen_height, flags, &sdlWindow, &sdlRenderer);
188 
189 	if (!sdlWindow || !sdlRenderer) {
190 		fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError());
191 		exit(EXIT_FAILURE);
192 	}
193 	SDL_RenderSetLogicalSize(sdlRenderer, screen_width, screen_height);
194 
195 	jnb_texture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, screen_width, screen_height);
196 	if (!jnb_texture) {
197 		fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError());
198 		exit(EXIT_FAILURE);
199 	}
200 
201 	jnb_surface = SDL_CreateRGBSurface(0, screen_width, screen_height, 8, 0, 0, 0, 0);
202 	if (!jnb_surface) {
203 		fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError());
204 		exit(EXIT_FAILURE);
205 	}
206 
207 	if(fullscreen)
208 		SDL_ShowCursor(0);
209 	else
210 		SDL_ShowCursor(1);
211 
212 	SDL_SetWindowTitle(sdlWindow, "Jump 'n Bump");
213 
214 	icon=load_xpm_from_array(jumpnbump_xpm);
215 	if (icon==NULL) {
216 	    printf("Couldn't load icon\n");
217 	} else {
218 	    SDL_SetWindowIcon(sdlWindow, icon);
219 	}
220 
221 	vinited = 1;
222 
223 	memset(dirty_blocks, 0, sizeof(dirty_blocks));
224 
225 	screen_buffer[0]=malloc(screen_width*screen_height);
226 	screen_buffer[1]=malloc(screen_width*screen_height);
227 
228 /*
229 	dirty_blocks[0]=malloc(sizeof(int)*25*16+1000);
230 	dirty_blocks[1]=malloc(sizeof(int)*25*16+1000);
231 */
232 
233 	return;
234 }
235 
236 
fs_toggle()237 void fs_toggle()
238 {
239 	if (!vinited) {
240 		fullscreen ^= 1;
241 		return;
242 	}
243 	if (SDL_SetWindowFullscreen(sdlWindow, (fullscreen?0:SDL_WINDOW_FULLSCREEN_DESKTOP)) == 0)
244 		fullscreen ^= 1;
245 	else
246 		fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError());
247 }
248 
249 
wait_vrt(int mix)250 void wait_vrt(int mix)
251 {
252 	return;
253 }
254 
255 
clear_page(int page,int color)256 void clear_page(int page, int color)
257 {
258 	int i,j;
259 	unsigned char *buf = get_vgaptr(page, 0, 0);
260 
261 	assert(drawing_enable==1);
262 
263 	for (i=0; i<(25*16); i++)
264 		dirty_blocks[page][i] = 1;
265 
266 	for (i=0; i<screen_height; i++)
267 		for (j=0; j<screen_width; j++)
268 			*buf++ = color;
269 }
270 
271 
clear_lines(int page,int y,int count,int color)272 void clear_lines(int page, int y, int count, int color)
273 {
274 	int i,j;
275 
276 	assert(drawing_enable==1);
277 
278 	if (scale_up) {
279 		count *= 2;
280 		y *= 2;
281 	}
282 
283 	for (i=0; i<count; i++) {
284 		if ((i+y)<screen_height) {
285 			unsigned char *buf = get_vgaptr(page, 0, i+y);
286 			for (j=0; j<screen_width; j++)
287 				*buf++ = color;
288 		}
289 	}
290 	count = ((y+count)>>dirty_block_shift) - (y>>dirty_block_shift) + 1;
291 	y >>= dirty_block_shift;
292 	for (i=0; i<count; i++)
293 		for (j=0; j<25; j++)
294 			dirty_blocks[page][(y+i)*25+j] = 1;
295 }
296 
297 
get_color(int color,char pal[768])298 int get_color(int color, char pal[768])
299 {
300 	assert(color<256);
301 	assert(pal);
302 	return SDL_MapRGB(jnb_surface->format, (Uint8)(pal[color*3+0]<<2), (Uint8)(pal[color*3+1]<<2), (Uint8)(pal[color*3+2]<<2));
303 }
304 
305 
get_pixel(int page,int x,int y)306 int get_pixel(int page, int x, int y)
307 {
308 	assert(drawing_enable==1);
309 
310 	if (scale_up) {
311 		x *= 2;
312 		y *= 2;
313 	}
314 
315 	assert(x<screen_width);
316 	assert(y<screen_height);
317 
318 	return *(unsigned char *)get_vgaptr(page, x, y);
319 }
320 
321 
set_pixel(int page,int x,int y,int color)322 void set_pixel(int page, int x, int y, int color)
323 {
324 	assert(drawing_enable==1);
325 
326 	if (scale_up) {
327 		x *= 2;
328 		y *= 2;
329 	}
330 
331 	assert(x<screen_width);
332 	assert(y<screen_height);
333 
334 	dirty_blocks[page][(y>>dirty_block_shift)*25+(x>>dirty_block_shift)] = 1;
335 
336 	*(unsigned char *)get_vgaptr(page, x, y) = color;
337 }
338 
339 
flippage(int page)340 void flippage(int page)
341 {
342 	int x,y;
343 	unsigned char *src;
344 	unsigned char *dest;
345 	SDL_Surface* surface;
346 
347 	assert(drawing_enable==0);
348 
349 	SDL_LockSurface(jnb_surface);
350 	if (!jnb_surface->pixels) {
351 
352 		for (x=0; x<(25*16); x++) {
353 			dirty_blocks[0][x] = 1;
354 			dirty_blocks[1][x] = 1;
355 		}
356 
357 		return;
358 	}
359 	dest=(unsigned char *)jnb_surface->pixels;
360 	src=screen_buffer[page];
361 	for (y=0; y<screen_height; y++) {
362 		for (x=0; x<25; x++) {
363 			int count;
364 			int test_x;
365 
366 			count=0;
367 			test_x=x;
368 			while ( (test_x<25) && (dirty_blocks[page][(y>>dirty_block_shift)*25+test_x]) ) {
369 				count++;
370 				test_x++;
371 			}
372 			if (count) {
373 				memcpy(
374 					&dest[y*jnb_surface->pitch+(x<<dirty_block_shift)],
375 					&src [y*screen_pitch+(x<<dirty_block_shift)],
376 					((16<<dirty_block_shift)>>4)*count);
377 			}
378 			x = test_x;
379 		}
380 	}
381 	memset(&dirty_blocks[page], 0, sizeof(int)*25*16);
382         SDL_UnlockSurface(jnb_surface);
383 
384 	surface = SDL_ConvertSurfaceFormat(jnb_surface, SDL_PIXELFORMAT_RGB888, 0);
385 	SDL_UpdateTexture(jnb_texture, NULL, surface->pixels, screen_width*sizeof(Uint32));
386 	SDL_FreeSurface(surface);
387 	SDL_RenderClear(sdlRenderer);
388 	SDL_RenderCopy(sdlRenderer, jnb_texture, NULL, NULL);
389 	SDL_RenderPresent(sdlRenderer);
390 }
391 
392 
draw_begin(void)393 void draw_begin(void)
394 {
395 	assert(drawing_enable==0);
396 
397 	drawing_enable = 1;
398 	if (background_drawn == 0) {
399 		if (background) {
400 			put_block(0, 0, 0, JNB_WIDTH, JNB_HEIGHT, background);
401 			put_block(1, 0, 0, JNB_WIDTH, JNB_HEIGHT, background);
402 		} else {
403 			clear_page(0, 0);
404 			clear_page(1, 0);
405 		}
406 		background_drawn = 1;
407 	}
408 }
409 
410 
draw_end(void)411 void draw_end(void)
412 {
413 	assert(drawing_enable==1);
414 
415 	drawing_enable = 0;
416 }
417 
418 
setpalette(int index,int count,char * palette)419 void setpalette(int index, int count, char *palette)
420 {
421 	SDL_Color colors[256];
422 	int i;
423 
424 	assert(drawing_enable==0);
425 
426 	for (i = 0; i < count; i++) {
427 		colors[i+index].r = palette[i * 3 + 0] << 2;
428 		colors[i+index].g = palette[i * 3 + 1] << 2;
429 		colors[i+index].b = palette[i * 3 + 2] << 2;
430 		colors[i+index].a = 255;
431 	}
432 	SDL_SetPaletteColors(jnb_surface->format->palette, &colors[index], index, count);
433 }
434 
435 
fillpalette(int red,int green,int blue)436 void fillpalette(int red, int green, int blue)
437 {
438 	SDL_Color colors[256];
439 	int i;
440 
441 	assert(drawing_enable==0);
442 
443 	for (i = 0; i < 256; i++) {
444 		colors[i].r = red << 2;
445 		colors[i].g = green << 2;
446 		colors[i].b = blue << 2;
447 		colors[i].a = 255;
448 	}
449 	SDL_SetPaletteColors(jnb_surface->format->palette, colors, 0, 256);
450 }
451 
452 
get_block(int page,int x,int y,int width,int height,void * buffer)453 void get_block(int page, int x, int y, int width, int height, void *buffer)
454 {
455 	unsigned char *buffer_ptr, *vga_ptr;
456 	int h;
457 
458 	assert(drawing_enable==1);
459 
460 	if (scale_up) {
461 		x *= 2;
462 		y *= 2;
463 		width *= 2;
464 		height *= 2;
465 	}
466 
467 	if (x < 0)
468 		x = 0;
469 	if (y < 0)
470 		y = 0;
471 	if (y + height >= screen_height)
472 		height = screen_height - y;
473 	if (x + width >= screen_width)
474 		width = screen_width - x;
475 	if (width<=0)
476 		return;
477 	if(height<=0)
478 		return;
479 
480 	vga_ptr = get_vgaptr(page, x, y);
481 	buffer_ptr = buffer;
482 	for (h = 0; h < height; h++) {
483 		memcpy(buffer_ptr, vga_ptr, width);
484 		vga_ptr += screen_pitch;
485 		buffer_ptr += width;
486 	}
487 
488 }
489 
490 
put_block(int page,int x,int y,int width,int height,void * buffer)491 void put_block(int page, int x, int y, int width, int height, void *buffer)
492 {
493 	int h;
494 	unsigned char *vga_ptr, *buffer_ptr;
495 
496 	assert(drawing_enable==1);
497 
498 	if (scale_up) {
499 		x *= 2;
500 		y *= 2;
501 		width *= 2;
502 		height *= 2;
503 	}
504 
505 	if (x < 0)
506 		x = 0;
507 	if (y < 0)
508 		y = 0;
509 	if (y + height >= screen_height)
510 		height = screen_height - y;
511 	if (x + width >= screen_width)
512 		width = screen_width - x;
513 	if (width<=0)
514 		return;
515 	if(height<=0)
516 		return;
517 
518 	vga_ptr = get_vgaptr(page, x, y);
519 	buffer_ptr = buffer;
520 	for (h = 0; h < height; h++) {
521 		memcpy(vga_ptr, buffer_ptr, width);
522 		vga_ptr += screen_pitch;
523 		buffer_ptr += width;
524 	}
525 	width = ((x+width)>>dirty_block_shift) - (x>>dirty_block_shift) + 1;
526 	height = ((y+height)>>dirty_block_shift) - (y>>dirty_block_shift) + 1;
527 	x >>= dirty_block_shift;
528 	y >>= dirty_block_shift;
529 	while (width--)
530 		for (h=0; h<height; h++)
531 			dirty_blocks[page][(y+h)*25+(x+width)] = 1;
532 }
533 
534 
put_text(int page,int x,int y,char * text,int align)535 void put_text(int page, int x, int y, char *text, int align)
536 {
537 	int c1;
538 	int t1;
539 	int width;
540 	int cur_x;
541 	int image;
542 
543 	assert(drawing_enable==1);
544 
545 	if (text == NULL || strlen(text) == 0)
546 		return;
547 	if (font_gobs.num_images == 0)
548 		return;
549 
550 	width = 0;
551 	c1 = 0;
552 	while (text[c1] != 0) {
553 		t1 = text[c1];
554 		c1++;
555 		if (t1 == ' ') {
556 			width += 5;
557 			continue;
558 		}
559 		if (t1 >= 33 && t1 <= 34)
560 			image = t1 - 33;
561 
562 		else if (t1 >= 39 && t1 <= 41)
563 			image = t1 - 37;
564 
565 		else if (t1 >= 44 && t1 <= 59)
566 			image = t1 - 39;
567 
568 		else if (t1 >= 64 && t1 <= 90)
569 			image = t1 - 43;
570 
571 		else if (t1 >= 97 && t1 <= 122)
572 			image = t1 - 49;
573 
574 		else if (t1 == '~')
575 			image = 74;
576 
577 		else if (t1 == 0x84)
578 			image = 75;
579 
580 		else if (t1 == 0x86)
581 			image = 76;
582 
583 		else if (t1 == 0x8e)
584 			image = 77;
585 
586 		else if (t1 == 0x8f)
587 			image = 78;
588 
589 		else if (t1 == 0x94)
590 			image = 79;
591 
592 		else if (t1 == 0x99)
593 			image = 80;
594 
595 		else
596 			continue;
597 		width += pob_width(image, &font_gobs) + 1;
598 	}
599 
600 	switch (align) {
601 	case 0:
602 		cur_x = x;
603 		break;
604 	case 1:
605 		cur_x = x - width;
606 		break;
607 	case 2:
608 		cur_x = x - width / 2;
609 		break;
610 	default:
611 		cur_x = 0;	/* this should cause error? -Chuck */
612 		break;
613 	}
614 	c1 = 0;
615 
616 	while (text[c1] != 0) {
617 		t1 = text[c1];
618 		c1++;
619 		if (t1 == ' ') {
620 			cur_x += 5;
621 			continue;
622 		}
623 		if (t1 >= 33 && t1 <= 34)
624 			image = t1 - 33;
625 
626 		else if (t1 >= 39 && t1 <= 41)
627 			image = t1 - 37;
628 
629 		else if (t1 >= 44 && t1 <= 59)
630 			image = t1 - 39;
631 
632 		else if (t1 >= 64 && t1 <= 90)
633 			image = t1 - 43;
634 
635 		else if (t1 >= 97 && t1 <= 122)
636 			image = t1 - 49;
637 
638 		else if (t1 == '~')
639 			image = 74;
640 
641 		else if (t1 == 0x84)
642 			image = 75;
643 
644 		else if (t1 == 0x86)
645 			image = 76;
646 
647 		else if (t1 == 0x8e)
648 			image = 77;
649 
650 		else if (t1 == 0x8f)
651 			image = 78;
652 
653 		else if (t1 == 0x94)
654 			image = 79;
655 
656 		else if (t1 == 0x99)
657 			image = 80;
658 
659 		else
660 			continue;
661 		put_pob(page, cur_x, y, image, &font_gobs, 1, mask_pic);
662 		cur_x += pob_width(image, &font_gobs) + 1;
663 	}
664 }
665 
666 
put_pob(int page,int x,int y,int image,gob_t * gob,int use_mask,void * mask_pic)667 void put_pob(int page, int x, int y, int image, gob_t *gob, int use_mask, void *mask_pic)
668 {
669 	int c1, c2;
670 	int pob_x, pob_y;
671 	int width, height;
672 	int draw_width, draw_height;
673 	int colour;
674 	unsigned char *vga_ptr;
675 	unsigned char *pob_ptr;
676 	unsigned char *mask_ptr;
677 
678 	assert(drawing_enable==1);
679 	assert(gob);
680 	assert(image>=0);
681 	assert(image<gob->num_images);
682 
683 	if (scale_up) {
684 		x *= 2;
685 		y *= 2;
686 		width = draw_width = gob->width[image]*2;
687 		height = draw_height = gob->height[image]*2;
688 		x -= gob->hs_x[image]*2;
689 		y -= gob->hs_y[image]*2;
690 	} else {
691 		width = draw_width = gob->width[image];
692 		height = draw_height = gob->height[image];
693 		x -= gob->hs_x[image];
694 		y -= gob->hs_y[image];
695 	}
696 
697 	if ((x + width) <= 0 || x >= screen_width)
698 		return;
699 	if ((y + height) <= 0 || y >= screen_height)
700 		return;
701 
702 	pob_x = 0;
703 	pob_y = 0;
704 	if (x < 0) {
705 		pob_x -= x;
706 		draw_width += x;
707 		x = 0;
708 	}
709 	if ((x + width) > screen_width)
710 		draw_width -= x + width - screen_width;
711 	if (y < 0) {
712 		pob_y -= y;
713 		draw_height += y;
714 		y = 0;
715 	}
716 	if ((y + height) > screen_height)
717 		draw_height -= y + height - screen_height;
718 
719 	vga_ptr = get_vgaptr(page, x, y);
720 	pob_ptr = ((unsigned char *)gob->data[image]) + ((pob_y * width) + pob_x);
721 	mask_ptr = ((unsigned char *)mask) + ((y * screen_pitch) + (x));
722 	for (c1 = 0; c1 < draw_height; c1++) {
723 		for (c2 = 0; c2 < draw_width; c2++) {
724 			colour = *mask_ptr;
725 			if (use_mask == 0 || (use_mask == 1 && colour == 0)) {
726 				colour = *pob_ptr;
727 				if (colour != 0) {
728 					*vga_ptr = colour;
729 				}
730 			}
731 			vga_ptr++;
732 			pob_ptr++;
733 			mask_ptr++;
734 		}
735 		pob_ptr += width - c2;
736 		vga_ptr += (screen_width - c2);
737 		mask_ptr += (screen_width - c2);
738 	}
739 	draw_width = ((x+draw_width)>>dirty_block_shift) - (x>>dirty_block_shift) + 1;
740 	draw_height = ((y+draw_height)>>dirty_block_shift) - (y>>dirty_block_shift) + 1;
741 	x >>= dirty_block_shift;
742 	y >>= dirty_block_shift;
743 	while (draw_width--)
744 		for (c1=0; c1<draw_height; c1++)
745 			dirty_blocks[page][(y+c1)*25+(x+draw_width)] = 1;
746 }
747 
748 
pob_width(int image,gob_t * gob)749 int pob_width(int image, gob_t *gob)
750 {
751 	assert(gob);
752 	assert(image>=0);
753 	assert(image<gob->num_images);
754 	return gob->width[image];
755 }
756 
757 
pob_height(int image,gob_t * gob)758 int pob_height(int image, gob_t *gob)
759 {
760 	assert(gob);
761 	assert(image>=0);
762 	assert(image<gob->num_images);
763 	return gob->height[image];
764 }
765 
766 
pob_hs_x(int image,gob_t * gob)767 int pob_hs_x(int image, gob_t *gob)
768 {
769 	assert(gob);
770 	assert(image>=0);
771 	assert(image<gob->num_images);
772 	return gob->hs_x[image];
773 }
774 
775 
pob_hs_y(int image,gob_t * gob)776 int pob_hs_y(int image, gob_t *gob)
777 {
778 	assert(gob);
779 	assert(image>=0);
780 	assert(image<gob->num_images);
781 	return gob->hs_y[image];
782 }
783 
784 
read_pcx(unsigned char * handle,void * buf,int buf_len,char * pal)785 int read_pcx(unsigned char * handle, void *buf, int buf_len, char *pal)
786 {
787 	unsigned char *buffer=buf;
788 	short c1;
789 	short a, b;
790 	long ofs1;
791 	if (buffer != 0) {
792 		handle += 128;
793 		ofs1 = 0;
794 		while (ofs1 < buf_len) {
795 			a = *(handle++);
796 			if ((a & 0xc0) == 0xc0) {
797 				b = *(handle++);
798 				a &= 0x3f;
799 				for (c1 = 0; c1 < a && ofs1 < buf_len; c1++)
800 					buffer[ofs1++] = (char) b;
801 			} else
802 				buffer[ofs1++] = (char) a;
803 		}
804 		if (pal != 0) {
805 			handle++;
806 			for (c1 = 0; c1 < 768; c1++)
807 				pal[c1] = *(handle++) /*fgetc(handle)*/ >> 2;
808 		}
809 	}
810 	return 0;
811 }
812 
813 
register_background(unsigned char * pixels,char pal[768])814 void register_background(unsigned char *pixels, char pal[768])
815 {
816 	if (background) {
817 		free(background);
818 		background = NULL;
819 	}
820 	background_drawn = 0;
821 	if (!pixels)
822 		return;
823 	assert(pal);
824 	if (scale_up) {
825 		background = malloc(screen_pitch*screen_height);
826 		assert(background);
827 		do_scale2x(pixels, JNB_WIDTH, JNB_HEIGHT, (unsigned char *)background);
828 	} else {
829 		background = malloc(JNB_WIDTH*JNB_HEIGHT);
830 		assert(background);
831 		memcpy(background, pixels, JNB_WIDTH*JNB_HEIGHT);
832 	}
833 }
834 
register_gob(unsigned char * handle,gob_t * gob,int len)835 int register_gob(unsigned char *handle, gob_t *gob, int len)
836 {
837 	unsigned char *gob_data;
838 	int i;
839 
840 	gob_data = malloc(len);
841 	memcpy(gob_data, handle, len);
842 
843 	gob->num_images = (short)((gob_data[0]) + (gob_data[1] << 8));
844 
845 	gob->width = malloc(gob->num_images*sizeof(int));
846 	gob->height = malloc(gob->num_images*sizeof(int));
847 	gob->hs_x = malloc(gob->num_images*sizeof(int));
848 	gob->hs_y = malloc(gob->num_images*sizeof(int));
849 	gob->data = malloc(gob->num_images*sizeof(void *));
850 	gob->orig_data = malloc(gob->num_images*sizeof(void *));
851 	for (i=0; i<gob->num_images; i++) {
852 		int image_size;
853 		int offset;
854 
855 		offset = (gob_data[i*4+2]) + (gob_data[i*4+3] << 8) + (gob_data[i*4+4] << 16) + (gob_data[i*4+5] << 24);
856 
857 		gob->width[i]  = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2;
858 		gob->height[i] = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2;
859 		gob->hs_x[i]   = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2;
860 		gob->hs_y[i]   = (short)((gob_data[offset]) + (gob_data[offset+1] << 8)); offset += 2;
861 
862 		image_size = gob->width[i] * gob->height[i];
863 		gob->orig_data[i] = malloc(image_size);
864 		memcpy(gob->orig_data[i], &gob_data[offset], image_size);
865 		if (scale_up) {
866 			image_size = gob->width[i] * gob->height[i] * 4;
867 			gob->data[i] = malloc(image_size);
868 			do_scale2x((unsigned char *)gob->orig_data[i], gob->width[i], gob->height[i], (unsigned char *)gob->data[i]);
869 		} else {
870 			gob->data[i] = (unsigned short *)gob->orig_data[i];
871 		}
872 	}
873 	free(gob_data);
874 	return 0;
875 }
876 
877 
recalculate_gob(gob_t * gob,char pal[768])878 void recalculate_gob(gob_t *gob, char pal[768])
879 {
880 }
881 
register_mask(void * pixels)882 void register_mask(void *pixels)
883 {
884 	if (mask) {
885 		free(mask);
886 		mask = NULL;
887 	}
888 	assert(pixels);
889 	if (scale_up) {
890 		mask = malloc(screen_pitch*screen_height);
891 		assert(mask);
892 		do_scale2x((unsigned char *)pixels, JNB_WIDTH, JNB_HEIGHT, (unsigned char *)mask);
893 	} else {
894 		mask = malloc(JNB_WIDTH*JNB_HEIGHT);
895 		assert(mask);
896 		memcpy(mask, pixels, JNB_WIDTH*JNB_HEIGHT);
897 	}
898 }
899