9585632680c2ae4666e9b00869ad913e02fc4240
3 * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/
5 * Copyright (C) 2001 Chuck Mason <cemason@users.sourceforge.net>
7 * Copyright (C) 2002 Florian Schulze <crow@icculus.org>
9 * This file is part of Jump'n'Bump.
11 * Jump'n'Bump is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * Jump'n'Bump is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "SDL_endian.h"
31 #include "jumpnbump32.xpm"
33 #include "jumpnbump128.xpm"
35 #include "jumpnbump64.xpm"
40 int screen_height
=256;
43 int dirty_block_shift
=4;
45 static SDL_Surface
*jnb_surface
;
46 static int fullscreen
= 0;
47 static int vinited
= 0;
48 static void *screen_buffer
[2];
49 static int drawing_enable
= 0;
50 static void *background
= NULL
;
51 static int background_drawn
;
52 static void *mask
= NULL
;
53 static int dirty_blocks
[2][25*16*2];
55 static SDL_Surface
*load_xpm_from_array(char **xpm
)
57 #define NEXT_TOKEN { \
58 while ((*p != ' ') && (*p != '\t')) p++; \
59 while ((*p == ' ') || (*p == '\t')) p++; }
92 surface
= SDL_CreateRGBSurface(SDL_SWSURFACE
, width
, height
, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
96 SDL_SetColorKey(surface
, SDL_SRCCOLORKEY
, SDL_MapRGBA(surface
->format
, 0, 0, 0, 0));
104 SDL_FreeSurface(surface
);
110 pal
[color
] = strtoul(++p
, NULL
, 16) | 0xff000000;
121 pixels
= (int *)&((char *)surface
->pixels
)[y
++ * surface
->pitch
];
127 SDL_FreeSurface(surface
);
130 r
= (pal
[(int)*p
] >> 16) & 0xff;
131 b
= (pal
[(int)*p
] & 0xff);
132 g
= (pal
[(int)*p
] >> 8) & 0xff;
133 a
= (pal
[(int)*p
] >> 24) & 0xff;
134 pixels
[x
] = SDL_MapRGBA(surface
->format
, r
, g
, b
, a
);
143 unsigned char *get_vgaptr(int page
, int x
, int y
)
145 assert(drawing_enable
==1);
147 return (unsigned char *)screen_buffer
[page
] + (y
*screen_pitch
)+(x
);
151 void set_scaling(int scale
)
158 screen_pitch
=screen_width
;
164 screen_pitch
=screen_width
;
168 void open_screen(void)
173 lval
= SDL_Init(SDL_INIT_TIMER
| SDL_INIT_AUDIO
| SDL_INIT_VIDEO
| SDL_INIT_JOYSTICK
);
175 fprintf(stderr
, "SDL ERROR: %s\n", SDL_GetError());
179 flags
= SDL_SWSURFACE
;
181 flags
|= SDL_FULLSCREEN
;
182 jnb_surface
= SDL_SetVideoMode(screen_width
, screen_height
, 8, flags
);
185 fprintf(stderr
, "SDL ERROR: %s\n", SDL_GetError());
194 SDL_WM_SetCaption("Jump'n'Bump","");
196 icon
=load_xpm_from_array(jumpnbump_xpm
);
198 printf("Couldn't load icon\n");
200 SDL_WM_SetIcon(icon
,NULL
);
205 memset(dirty_blocks
, 0, sizeof(dirty_blocks
));
207 screen_buffer
[0]=malloc(screen_width
*screen_height
);
208 screen_buffer
[1]=malloc(screen_width
*screen_height
);
211 dirty_blocks[0]=malloc(sizeof(int)*25*16+1000);
212 dirty_blocks[1]=malloc(sizeof(int)*25*16+1000);
225 if (SDL_WM_ToggleFullScreen(jnb_surface
))
230 void wait_vrt(int mix
)
236 void clear_page(int page
, int color
)
239 unsigned char *buf
= get_vgaptr(page
, 0, 0);
241 assert(drawing_enable
==1);
243 for (i
=0; i
<(25*16); i
++)
244 dirty_blocks
[page
][i
] = 1;
246 for (i
=0; i
<screen_height
; i
++)
247 for (j
=0; j
<screen_width
; j
++)
252 void clear_lines(int page
, int y
, int count
, int color
)
256 assert(drawing_enable
==1);
263 for (i
=0; i
<count
; i
++) {
264 if ((i
+y
)<screen_height
) {
265 unsigned char *buf
= get_vgaptr(page
, 0, i
+y
);
266 for (j
=0; j
<screen_width
; j
++)
270 count
= ((y
+count
)>>dirty_block_shift
) - (y
>>dirty_block_shift
) + 1;
271 y
>>= dirty_block_shift
;
272 for (i
=0; i
<count
; i
++)
274 dirty_blocks
[page
][(y
+i
)*25+j
] = 1;
278 int get_color(int color
, char pal
[768])
282 return SDL_MapRGB(jnb_surface
->format
, (Uint8
)(pal
[color
*3+0]<<2), (Uint8
)(pal
[color
*3+1]<<2), (Uint8
)(pal
[color
*3+2]<<2));
286 int get_pixel(int page
, int x
, int y
)
288 assert(drawing_enable
==1);
295 assert(x
<screen_width
);
296 assert(y
<screen_height
);
298 return *(unsigned char *)get_vgaptr(page
, x
, y
);
302 void set_pixel(int page
, int x
, int y
, int color
)
304 assert(drawing_enable
==1);
311 assert(x
<screen_width
);
312 assert(y
<screen_height
);
314 dirty_blocks
[page
][(y
>>dirty_block_shift
)*25+(x
>>dirty_block_shift
)] = 1;
316 *(unsigned char *)get_vgaptr(page
, x
, y
) = color
;
320 void flippage(int page
)
326 assert(drawing_enable
==0);
328 SDL_LockSurface(jnb_surface
);
329 if (!jnb_surface
->pixels
) {
331 for (x
=0; x
<(25*16); x
++) {
332 dirty_blocks
[0][x
] = 1;
333 dirty_blocks
[1][x
] = 1;
338 dest
=(unsigned char *)jnb_surface
->pixels
;
339 src
=screen_buffer
[page
];
340 for (y
=0; y
<screen_height
; y
++) {
341 for (x
=0; x
<25; x
++) {
347 while ( (test_x
<25) && (dirty_blocks
[page
][(y
>>dirty_block_shift
)*25+test_x
]) ) {
352 memcpy( &dest
[y
*jnb_surface
->pitch
+(x
<<dirty_block_shift
)],
353 &src
[y
*screen_pitch
+((x
<<dirty_block_shift
))],
354 ((16<<dirty_block_shift
)>>4)*count
);
359 memset(&dirty_blocks
[page
], 0, sizeof(int)*25*16);
360 SDL_UnlockSurface(jnb_surface
);
361 SDL_Flip(jnb_surface
);
365 void draw_begin(void)
367 assert(drawing_enable
==0);
370 if (background_drawn
== 0) {
372 put_block(0, 0, 0, JNB_WIDTH
, JNB_HEIGHT
, background
);
373 put_block(1, 0, 0, JNB_WIDTH
, JNB_HEIGHT
, background
);
378 background_drawn
= 1;
385 assert(drawing_enable
==1);
391 void setpalette(int index
, int count
, char *palette
)
393 SDL_Color colors
[256];
396 assert(drawing_enable
==0);
398 for (i
= 0; i
< count
; i
++) {
399 colors
[i
+index
].r
= palette
[i
* 3 + 0] << 2;
400 colors
[i
+index
].g
= palette
[i
* 3 + 1] << 2;
401 colors
[i
+index
].b
= palette
[i
* 3 + 2] << 2;
403 SDL_SetColors(jnb_surface
, &colors
[index
], index
, count
);
407 void fillpalette(int red
, int green
, int blue
)
409 SDL_Color colors
[256];
412 assert(drawing_enable
==0);
414 for (i
= 0; i
< 256; i
++) {
415 colors
[i
].r
= red
<< 2;
416 colors
[i
].g
= green
<< 2;
417 colors
[i
].b
= blue
<< 2;
419 SDL_SetColors(jnb_surface
, colors
, 0, 256);
423 void get_block(int page
, int x
, int y
, int width
, int height
, void *buffer
)
425 unsigned char *buffer_ptr
, *vga_ptr
;
428 assert(drawing_enable
==1);
441 if (y
+ height
>= screen_height
)
442 height
= screen_height
- y
;
443 if (x
+ width
>= screen_width
)
444 width
= screen_width
- x
;
450 vga_ptr
= get_vgaptr(page
, x
, y
);
452 for (h
= 0; h
< height
; h
++) {
453 memcpy(buffer_ptr
, vga_ptr
, width
);
454 vga_ptr
+= screen_pitch
;
461 void put_block(int page
, int x
, int y
, int width
, int height
, void *buffer
)
464 unsigned char *vga_ptr
, *buffer_ptr
;
466 assert(drawing_enable
==1);
479 if (y
+ height
>= screen_height
)
480 height
= screen_height
- y
;
481 if (x
+ width
>= screen_width
)
482 width
= screen_width
- x
;
488 vga_ptr
= get_vgaptr(page
, x
, y
);
490 for (h
= 0; h
< height
; h
++) {
491 memcpy(vga_ptr
, buffer_ptr
, width
);
492 vga_ptr
+= screen_pitch
;
495 width
= ((x
+width
)>>dirty_block_shift
) - (x
>>dirty_block_shift
) + 1;
496 height
= ((y
+height
)>>dirty_block_shift
) - (y
>>dirty_block_shift
) + 1;
497 x
>>= dirty_block_shift
;
498 y
>>= dirty_block_shift
;
500 for (h
=0; h
<height
; h
++)
501 dirty_blocks
[page
][(y
+h
)*25+(x
+width
)] = 1;
505 void put_text(int page
, int x
, int y
, char *text
, int align
)
513 assert(drawing_enable
==1);
515 if (text
== NULL
|| strlen(text
) == 0)
517 if (font_gobs
.num_images
== 0)
522 while (text
[c1
] != 0) {
529 if (t1
>= 33 && t1
<= 34)
532 else if (t1
>= 39 && t1
<= 41)
535 else if (t1
>= 44 && t1
<= 59)
538 else if (t1
>= 64 && t1
<= 90)
541 else if (t1
>= 97 && t1
<= 122)
567 width
+= pob_width(image
, &font_gobs
) + 1;
578 cur_x
= x
- width
/ 2;
581 cur_x
= 0; /* this should cause error? -Chuck */
586 while (text
[c1
] != 0) {
593 if (t1
>= 33 && t1
<= 34)
596 else if (t1
>= 39 && t1
<= 41)
599 else if (t1
>= 44 && t1
<= 59)
602 else if (t1
>= 64 && t1
<= 90)
605 else if (t1
>= 97 && t1
<= 122)
631 put_pob(page
, cur_x
, y
, image
, &font_gobs
, 1, mask_pic
);
632 cur_x
+= pob_width(image
, &font_gobs
) + 1;
637 void put_pob(int page
, int x
, int y
, int image
, gob_t
*gob
, int use_mask
, void *mask_pic
)
642 int draw_width
, draw_height
;
644 unsigned char *vga_ptr
;
645 unsigned char *pob_ptr
;
646 unsigned char *mask_ptr
;
648 assert(drawing_enable
==1);
651 assert(image
<gob
->num_images
);
656 width
= draw_width
= gob
->width
[image
]*2;
657 height
= draw_height
= gob
->height
[image
]*2;
658 x
-= gob
->hs_x
[image
]*2;
659 y
-= gob
->hs_y
[image
]*2;
661 width
= draw_width
= gob
->width
[image
];
662 height
= draw_height
= gob
->height
[image
];
663 x
-= gob
->hs_x
[image
];
664 y
-= gob
->hs_y
[image
];
667 if ((x
+ width
) <= 0 || x
>= screen_width
)
669 if ((y
+ height
) <= 0 || y
>= screen_height
)
679 if ((x
+ width
) > screen_width
)
680 draw_width
-= x
+ width
- screen_width
;
686 if ((y
+ height
) > screen_height
)
687 draw_height
-= y
+ height
- screen_height
;
689 vga_ptr
= get_vgaptr(page
, x
, y
);
690 pob_ptr
= ((unsigned char *)gob
->data
[image
]) + ((pob_y
* width
) + pob_x
);
691 mask_ptr
= ((unsigned char *)mask
) + ((y
* screen_pitch
) + (x
));
692 for (c1
= 0; c1
< draw_height
; c1
++) {
693 for (c2
= 0; c2
< draw_width
; c2
++) {
695 if (use_mask
== 0 || (use_mask
== 1 && colour
== 0)) {
705 pob_ptr
+= width
- c2
;
706 vga_ptr
+= (screen_width
- c2
);
707 mask_ptr
+= (screen_width
- c2
);
709 draw_width
= ((x
+draw_width
)>>dirty_block_shift
) - (x
>>dirty_block_shift
) + 1;
710 draw_height
= ((y
+draw_height
)>>dirty_block_shift
) - (y
>>dirty_block_shift
) + 1;
711 x
>>= dirty_block_shift
;
712 y
>>= dirty_block_shift
;
714 for (c1
=0; c1
<draw_height
; c1
++)
715 dirty_blocks
[page
][(y
+c1
)*25+(x
+draw_width
)] = 1;
719 int pob_width(int image
, gob_t
*gob
)
723 assert(image
<gob
->num_images
);
724 return gob
->width
[image
];
728 int pob_height(int image
, gob_t
*gob
)
732 assert(image
<gob
->num_images
);
733 return gob
->height
[image
];
737 int pob_hs_x(int image
, gob_t
*gob
)
741 assert(image
<gob
->num_images
);
742 return gob
->hs_x
[image
];
746 int pob_hs_y(int image
, gob_t
*gob
)
750 assert(image
<gob
->num_images
);
751 return gob
->hs_y
[image
];
755 int read_pcx(unsigned char * handle
, void *buf
, int buf_len
, char *pal
)
757 unsigned char *buffer
=buf
;
764 while (ofs1
< buf_len
) {
766 if ((a
& 0xc0) == 0xc0) {
769 for (c1
= 0; c1
< a
&& ofs1
< buf_len
; c1
++)
770 buffer
[ofs1
++] = (char) b
;
772 buffer
[ofs1
++] = (char) a
;
776 for (c1
= 0; c1
< 768; c1
++)
777 pal
[c1
] = *(handle
++) /*fgetc(handle)*/ >> 2;
784 void register_background(char *pixels
, char pal
[768])
790 background_drawn
= 0;
795 background
= malloc(screen_pitch
*screen_height
);
797 do_scale2x((unsigned char *)pixels
, JNB_WIDTH
, JNB_HEIGHT
, (unsigned char *)background
);
799 background
= malloc(JNB_WIDTH
*JNB_HEIGHT
);
801 memcpy(background
, pixels
, JNB_WIDTH
*JNB_HEIGHT
);
805 int register_gob(unsigned char *handle
, gob_t
*gob
, int len
)
807 unsigned char *gob_data
;
810 gob_data
= malloc(len
);
811 memcpy(gob_data
, handle
, len
);
813 gob
->num_images
= (short)((gob_data
[0]) + (gob_data
[1] << 8));
815 gob
->width
= malloc(gob
->num_images
*sizeof(int));
816 gob
->height
= malloc(gob
->num_images
*sizeof(int));
817 gob
->hs_x
= malloc(gob
->num_images
*sizeof(int));
818 gob
->hs_y
= malloc(gob
->num_images
*sizeof(int));
819 gob
->data
= malloc(gob
->num_images
*sizeof(void *));
820 gob
->orig_data
= malloc(gob
->num_images
*sizeof(void *));
821 for (i
=0; i
<gob
->num_images
; i
++) {
825 offset
= (gob_data
[i
*4+2]) + (gob_data
[i
*4+3] << 8) + (gob_data
[i
*4+4] << 16) + (gob_data
[i
*4+5] << 24);
827 gob
->width
[i
] = (short)((gob_data
[offset
]) + (gob_data
[offset
+1] << 8)); offset
+= 2;
828 gob
->height
[i
] = (short)((gob_data
[offset
]) + (gob_data
[offset
+1] << 8)); offset
+= 2;
829 gob
->hs_x
[i
] = (short)((gob_data
[offset
]) + (gob_data
[offset
+1] << 8)); offset
+= 2;
830 gob
->hs_y
[i
] = (short)((gob_data
[offset
]) + (gob_data
[offset
+1] << 8)); offset
+= 2;
832 image_size
= gob
->width
[i
] * gob
->height
[i
];
833 gob
->orig_data
[i
] = malloc(image_size
);
834 memcpy(gob
->orig_data
[i
], &gob_data
[offset
], image_size
);
836 image_size
= gob
->width
[i
] * gob
->height
[i
] * 4;
837 gob
->data
[i
] = malloc(image_size
);
838 do_scale2x((unsigned char *)gob
->orig_data
[i
], gob
->width
[i
], gob
->height
[i
], (unsigned char *)gob
->data
[i
]);
840 gob
->data
[i
] = (unsigned short *)gob
->orig_data
[i
];
848 void recalculate_gob(gob_t
*gob
, char pal
[768])
852 void register_mask(void *pixels
)
860 mask
= malloc(screen_pitch
*screen_height
);
862 do_scale2x((unsigned char *)pixels
, JNB_WIDTH
, JNB_HEIGHT
, (unsigned char *)mask
);
864 mask
= malloc(JNB_WIDTH
*JNB_HEIGHT
);
866 memcpy(mask
, pixels
, JNB_WIDTH
*JNB_HEIGHT
);