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);