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
))
229 void exit_fullscreen()
235 void wait_vrt(int mix
)
241 void clear_page(int page
, int color
)
244 unsigned char *buf
= get_vgaptr(page
, 0, 0);
246 assert(drawing_enable
==1);
248 for (i
=0; i
<(25*16); i
++)
249 dirty_blocks
[page
][i
] = 1;
251 for (i
=0; i
<screen_height
; i
++)
252 for (j
=0; j
<screen_width
; j
++)
257 void clear_lines(int page
, int y
, int count
, int color
)
261 assert(drawing_enable
==1);
268 for (i
=0; i
<count
; i
++) {
269 if ((i
+y
)<screen_height
) {
270 unsigned char *buf
= get_vgaptr(page
, 0, i
+y
);
271 for (j
=0; j
<screen_width
; j
++)
275 count
= ((y
+count
)>>dirty_block_shift
) - (y
>>dirty_block_shift
) + 1;
276 y
>>= dirty_block_shift
;
277 for (i
=0; i
<count
; i
++)
279 dirty_blocks
[page
][(y
+i
)*25+j
] = 1;
283 int get_color(int color
, char pal
[768])
287 return SDL_MapRGB(jnb_surface
->format
, (Uint8
)(pal
[color
*3+0]<<2), (Uint8
)(pal
[color
*3+1]<<2), (Uint8
)(pal
[color
*3+2]<<2));
291 int get_pixel(int page
, int x
, int y
)
293 assert(drawing_enable
==1);
300 assert(x
<screen_width
);
301 assert(y
<screen_height
);
303 return *(unsigned char *)get_vgaptr(page
, x
, y
);
307 void set_pixel(int page
, int x
, int y
, int color
)
309 assert(drawing_enable
==1);
316 assert(x
<screen_width
);
317 assert(y
<screen_height
);
319 dirty_blocks
[page
][(y
>>dirty_block_shift
)*25+(x
>>dirty_block_shift
)] = 1;
321 *(unsigned char *)get_vgaptr(page
, x
, y
) = color
;
325 void flippage(int page
)
331 assert(drawing_enable
==0);
333 SDL_LockSurface(jnb_surface
);
334 if (!jnb_surface
->pixels
) {
336 for (x
=0; x
<(25*16); x
++) {
337 dirty_blocks
[0][x
] = 1;
338 dirty_blocks
[1][x
] = 1;
343 dest
=(unsigned char *)jnb_surface
->pixels
;
344 src
=screen_buffer
[page
];
345 for (y
=0; y
<screen_height
; y
++) {
346 for (x
=0; x
<25; x
++) {
352 while ( (test_x
<25) && (dirty_blocks
[page
][(y
>>dirty_block_shift
)*25+test_x
]) ) {
357 memcpy( &dest
[y
*jnb_surface
->pitch
+(x
<<dirty_block_shift
)],
358 &src
[y
*screen_pitch
+((x
<<dirty_block_shift
))],
359 ((16<<dirty_block_shift
)>>4)*count
);
364 memset(&dirty_blocks
[page
], 0, sizeof(int)*25*16);
365 SDL_UnlockSurface(jnb_surface
);
366 SDL_Flip(jnb_surface
);
370 void draw_begin(void)
372 assert(drawing_enable
==0);
375 if (background_drawn
== 0) {
377 put_block(0, 0, 0, JNB_WIDTH
, JNB_HEIGHT
, background
);
378 put_block(1, 0, 0, JNB_WIDTH
, JNB_HEIGHT
, background
);
383 background_drawn
= 1;
390 assert(drawing_enable
==1);
396 void setpalette(int index
, int count
, char *palette
)
398 SDL_Color colors
[256];
401 assert(drawing_enable
==0);
403 for (i
= 0; i
< count
; i
++) {
404 colors
[i
+index
].r
= palette
[i
* 3 + 0] << 2;
405 colors
[i
+index
].g
= palette
[i
* 3 + 1] << 2;
406 colors
[i
+index
].b
= palette
[i
* 3 + 2] << 2;
408 SDL_SetColors(jnb_surface
, &colors
[index
], index
, count
);
412 void fillpalette(int red
, int green
, int blue
)
414 SDL_Color colors
[256];
417 assert(drawing_enable
==0);
419 for (i
= 0; i
< 256; i
++) {
420 colors
[i
].r
= red
<< 2;
421 colors
[i
].g
= green
<< 2;
422 colors
[i
].b
= blue
<< 2;
424 SDL_SetColors(jnb_surface
, colors
, 0, 256);
428 void get_block(int page
, int x
, int y
, int width
, int height
, void *buffer
)
430 unsigned char *buffer_ptr
, *vga_ptr
;
433 assert(drawing_enable
==1);
446 if (y
+ height
>= screen_height
)
447 height
= screen_height
- y
;
448 if (x
+ width
>= screen_width
)
449 width
= screen_width
- x
;
455 vga_ptr
= get_vgaptr(page
, x
, y
);
457 for (h
= 0; h
< height
; h
++) {
458 memcpy(buffer_ptr
, vga_ptr
, width
);
459 vga_ptr
+= screen_pitch
;
466 void put_block(int page
, int x
, int y
, int width
, int height
, void *buffer
)
469 unsigned char *vga_ptr
, *buffer_ptr
;
471 assert(drawing_enable
==1);
484 if (y
+ height
>= screen_height
)
485 height
= screen_height
- y
;
486 if (x
+ width
>= screen_width
)
487 width
= screen_width
- x
;
493 vga_ptr
= get_vgaptr(page
, x
, y
);
495 for (h
= 0; h
< height
; h
++) {
496 memcpy(vga_ptr
, buffer_ptr
, width
);
497 vga_ptr
+= screen_pitch
;
500 width
= ((x
+width
)>>dirty_block_shift
) - (x
>>dirty_block_shift
) + 1;
501 height
= ((y
+height
)>>dirty_block_shift
) - (y
>>dirty_block_shift
) + 1;
502 x
>>= dirty_block_shift
;
503 y
>>= dirty_block_shift
;
505 for (h
=0; h
<height
; h
++)
506 dirty_blocks
[page
][(y
+h
)*25+(x
+width
)] = 1;
510 void put_text(int page
, int x
, int y
, char *text
, int align
)
518 assert(drawing_enable
==1);
520 if (text
== NULL
|| strlen(text
) == 0)
522 if (font_gobs
.num_images
== 0)
527 while (text
[c1
] != 0) {
534 if (t1
>= 33 && t1
<= 34)
537 else if (t1
>= 39 && t1
<= 41)
540 else if (t1
>= 44 && t1
<= 59)
543 else if (t1
>= 64 && t1
<= 90)
546 else if (t1
>= 97 && t1
<= 122)
572 width
+= pob_width(image
, &font_gobs
) + 1;
583 cur_x
= x
- width
/ 2;
586 cur_x
= 0; /* this should cause error? -Chuck */
591 while (text
[c1
] != 0) {
598 if (t1
>= 33 && t1
<= 34)
601 else if (t1
>= 39 && t1
<= 41)
604 else if (t1
>= 44 && t1
<= 59)
607 else if (t1
>= 64 && t1
<= 90)
610 else if (t1
>= 97 && t1
<= 122)
636 put_pob(page
, cur_x
, y
, image
, &font_gobs
, 1, mask_pic
);
637 cur_x
+= pob_width(image
, &font_gobs
) + 1;
642 void put_pob(int page
, int x
, int y
, int image
, gob_t
*gob
, int use_mask
, void *mask_pic
)
647 int draw_width
, draw_height
;
649 unsigned char *vga_ptr
;
650 unsigned char *pob_ptr
;
651 unsigned char *mask_ptr
;
653 assert(drawing_enable
==1);
656 assert(image
<gob
->num_images
);
661 width
= draw_width
= gob
->width
[image
]*2;
662 height
= draw_height
= gob
->height
[image
]*2;
663 x
-= gob
->hs_x
[image
]*2;
664 y
-= gob
->hs_y
[image
]*2;
666 width
= draw_width
= gob
->width
[image
];
667 height
= draw_height
= gob
->height
[image
];
668 x
-= gob
->hs_x
[image
];
669 y
-= gob
->hs_y
[image
];
672 if ((x
+ width
) <= 0 || x
>= screen_width
)
674 if ((y
+ height
) <= 0 || y
>= screen_height
)
684 if ((x
+ width
) > screen_width
)
685 draw_width
-= x
+ width
- screen_width
;
691 if ((y
+ height
) > screen_height
)
692 draw_height
-= y
+ height
- screen_height
;
694 vga_ptr
= get_vgaptr(page
, x
, y
);
695 pob_ptr
= ((unsigned char *)gob
->data
[image
]) + ((pob_y
* width
) + pob_x
);
696 mask_ptr
= ((unsigned char *)mask
) + ((y
* screen_pitch
) + (x
));
697 for (c1
= 0; c1
< draw_height
; c1
++) {
698 for (c2
= 0; c2
< draw_width
; c2
++) {
700 if (use_mask
== 0 || (use_mask
== 1 && colour
== 0)) {
710 pob_ptr
+= width
- c2
;
711 vga_ptr
+= (screen_width
- c2
);
712 mask_ptr
+= (screen_width
- c2
);
714 draw_width
= ((x
+draw_width
)>>dirty_block_shift
) - (x
>>dirty_block_shift
) + 1;
715 draw_height
= ((y
+draw_height
)>>dirty_block_shift
) - (y
>>dirty_block_shift
) + 1;
716 x
>>= dirty_block_shift
;
717 y
>>= dirty_block_shift
;
719 for (c1
=0; c1
<draw_height
; c1
++)
720 dirty_blocks
[page
][(y
+c1
)*25+(x
+draw_width
)] = 1;
724 int pob_width(int image
, gob_t
*gob
)
728 assert(image
<gob
->num_images
);
729 return gob
->width
[image
];
733 int pob_height(int image
, gob_t
*gob
)
737 assert(image
<gob
->num_images
);
738 return gob
->height
[image
];
742 int pob_hs_x(int image
, gob_t
*gob
)
746 assert(image
<gob
->num_images
);
747 return gob
->hs_x
[image
];
751 int pob_hs_y(int image
, gob_t
*gob
)
755 assert(image
<gob
->num_images
);
756 return gob
->hs_y
[image
];
760 int read_pcx(unsigned char * handle
, void *buf
, int buf_len
, char *pal
)
762 unsigned char *buffer
=buf
;
769 while (ofs1
< buf_len
) {
771 if ((a
& 0xc0) == 0xc0) {
774 for (c1
= 0; c1
< a
&& ofs1
< buf_len
; c1
++)
775 buffer
[ofs1
++] = (char) b
;
777 buffer
[ofs1
++] = (char) a
;
781 for (c1
= 0; c1
< 768; c1
++)
782 pal
[c1
] = *(handle
++) /*fgetc(handle)*/ >> 2;
789 void register_background(char *pixels
, char pal
[768])
795 background_drawn
= 0;
800 background
= malloc(screen_pitch
*screen_height
);
802 do_scale2x((unsigned char *)pixels
, JNB_WIDTH
, JNB_HEIGHT
, (unsigned char *)background
);
804 background
= malloc(JNB_WIDTH
*JNB_HEIGHT
);
806 memcpy(background
, pixels
, JNB_WIDTH
*JNB_HEIGHT
);
810 int register_gob(unsigned char *handle
, gob_t
*gob
, int len
)
812 unsigned char *gob_data
;
815 gob_data
= malloc(len
);
816 memcpy(gob_data
, handle
, len
);
818 gob
->num_images
= (short)((gob_data
[0]) + (gob_data
[1] << 8));
820 gob
->width
= malloc(gob
->num_images
*sizeof(int));
821 gob
->height
= malloc(gob
->num_images
*sizeof(int));
822 gob
->hs_x
= malloc(gob
->num_images
*sizeof(int));
823 gob
->hs_y
= malloc(gob
->num_images
*sizeof(int));
824 gob
->data
= malloc(gob
->num_images
*sizeof(void *));
825 gob
->orig_data
= malloc(gob
->num_images
*sizeof(void *));
826 for (i
=0; i
<gob
->num_images
; i
++) {
830 offset
= (gob_data
[i
*4+2]) + (gob_data
[i
*4+3] << 8) + (gob_data
[i
*4+4] << 16) + (gob_data
[i
*4+5] << 24);
832 gob
->width
[i
] = (short)((gob_data
[offset
]) + (gob_data
[offset
+1] << 8)); offset
+= 2;
833 gob
->height
[i
] = (short)((gob_data
[offset
]) + (gob_data
[offset
+1] << 8)); offset
+= 2;
834 gob
->hs_x
[i
] = (short)((gob_data
[offset
]) + (gob_data
[offset
+1] << 8)); offset
+= 2;
835 gob
->hs_y
[i
] = (short)((gob_data
[offset
]) + (gob_data
[offset
+1] << 8)); offset
+= 2;
837 image_size
= gob
->width
[i
] * gob
->height
[i
];
838 gob
->orig_data
[i
] = malloc(image_size
);
839 memcpy(gob
->orig_data
[i
], &gob_data
[offset
], image_size
);
841 image_size
= gob
->width
[i
] * gob
->height
[i
] * 4;
842 gob
->data
[i
] = malloc(image_size
);
843 do_scale2x((unsigned char *)gob
->orig_data
[i
], gob
->width
[i
], gob
->height
[i
], (unsigned char *)gob
->data
[i
]);
845 gob
->data
[i
] = (unsigned short *)gob
->orig_data
[i
];
853 void recalculate_gob(gob_t
*gob
, char pal
[768])
857 void register_mask(void *pixels
)
865 mask
= malloc(screen_pitch
*screen_height
);
867 do_scale2x((unsigned char *)pixels
, JNB_WIDTH
, JNB_HEIGHT
, (unsigned char *)mask
);
869 mask
= malloc(JNB_WIDTH
*JNB_HEIGHT
);
871 memcpy(mask
, pixels
, JNB_WIDTH
*JNB_HEIGHT
);