sdlbomber/draw.c

473 lines
9.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include "bomber.h"
#include "draw.h"
#include "game.h"
#include "gfx.h"
#include "utils.h"
#ifndef DATADIR
#define DATADIR "data"
#endif
#define NUMCHARACTERS 50
static figure font[NUMCHARACTERS];
static figure bigfont[NUMCHARACTERS];
gfxset gfxsets[NUMGFX];
static char walkingname[256];
static char colorsetname[256];
static char backgroundname[256];
static char blocksname[256];
static char blocksxname[256];
static char bombs1name[256];
static char bombs2name[256];
static char flamesname[256];
static char tilesname[256];
static char deathname[256];
static char fontname[256];
static char bigfontname[256];
figure blocks[3];
figure blocksx[9];
figure bombs1[MAXSETS][NUMBOMBFRAMES];
figure bombs2[MAXSETS][NUMBOMBFRAMES];
figure flamefigs[MAXSETS][NUMFLAMEFRAMES];
figure tiles[15];
figure death[NUMDEATHFRAMES];
int fontxsize,fontysize;
int bigfontxsize,bigfontysize,bigfontyspace;
static int textx,texty;
static const unsigned char *remapstring = (const unsigned char*) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.:!?\177/\\*-,>< =";
static char asciiremap[256];
/* On screen array variables */
int arraynumx=15;
int arraynumy=11;
int arraystartx=20;
int arraystarty=70;
int arrayspacex=40;
int arrayspacey=36;
static sprite sprites[MAXSPRITES];
static int spritesused=0;
#define IBUFFLEN 1024
int ileft=0,ihand=0,byteswide;
unsigned char ibuff[IBUFFLEN],*itake;
static void freegfxset(gfxset *gs) {
if(gs->gs_pic) free(gs->gs_pic);
gs->gs_pic=0;
}
static int myci() {
if (!ileft) {
ileft=read(ihand,ibuff,IBUFFLEN);
if(!ileft) return -1;
itake=ibuff;
}
ileft--;
return *itake++;
}
static int dopcxreal(char *name,gfxset *gs) {
int xs,ys;
int i,j,k;
int totalsize;
int width,height;
unsigned char *bm,*lp;
char tname[256];
memset(gs,0,sizeof(gfxset));
ileft=0;
sprintf(tname,DATADIR "/%s",name);
ihand=open(tname,O_RDONLY);
if(ihand<0) {
char tname2[256];
sprintf(tname2,"%s.pcx",tname);
ihand=open(tname2,O_RDONLY);
if(ihand<0)
return 1;
}
if(myci()!=10) {close(ihand);return 2;} // 10=zsoft .pcx
if(myci()!=5) {close(ihand);return 3;} // version 3.0
if(myci()!=1) {close(ihand);return 4;} //encoding method
if(myci()!=8) {close(ihand);return 5;} //bpp
xs=myci();
xs|=myci()<<8;
ys=myci();
ys|=myci()<<8;
width=myci();
width|=myci()<<8;
height=myci();
height|=myci()<<8;
width=width+1-xs;
height=height+1-ys;
for(i=0;i<48+4;++i) myci();
myci();
if(myci()!=1) {close(ihand);return 6;} // # of planes
byteswide=myci();
byteswide|=myci()<<8;
i=myci();
i|=myci()<<8;
// if(i!=1) {close(ihand);return 7;} // 1=color/bw,2=grey
for(i=0;i<58;++i) myci();
totalsize=height*byteswide;
bm=malloc(totalsize+1);
if(!bm) {close(ihand);return 8;} // no memory
gs->gs_pic=bm;
gs->gs_xsize=width;
gs->gs_ysize=height;
while(height--) {
lp=bm;
i=byteswide;
while(i>0) {
j=myci();
if(j<0xc0) {
*lp++=j;
--i;
} else {
j&=0x3f;
k=myci();
while(j-- && i) {
*lp++=k;
--i;
}
}
}
bm+=width;
}
lseek(ihand,-0x300,SEEK_END);
read(ihand,gs->gs_colormap,0x300);
close(ihand);
return 0;
}
static int dopcx(char *name,gfxset *gs) {
int err;
err=dopcxreal(name,gs);
if(err)
printf("Error loading \"%s\":code %d\n",name,err);
return err;
}
static void getgroup(char *name,gfxset *colorgs,figure *fig,int count) {
int err;
int i;
gfxset gs;
err=dopcx(name,&gs);
if(err) exit(1000+err);
createinout(&gs);
for(i=0;i<MAXSETS;++i,fig+=count,++colorgs) {
if(!colorgs->gs_pic) continue;
memmove(gs.gs_colormap,colorgs->gs_colormap,
sizeof(gs.gs_colormap));
createinout(&gs);
gfxfetch(&gs,fig,count);
}
freegfxset(&gs);
}
static void getsingle(char *name,figure *fig,int count) {
gfxset gs;
int err;
err=dopcx(name,&gs);
if(err) exit(1000+err);
createinout(&gs);
gfxfetch(&gs,fig,count);
freegfxset(&gs);
}
static void texthome(void) {
textx=texty=10;
}
void drawstring(int xpos, int ypos, const char *str) {
char ch;
while((ch=*str++)) {
drawfigure(xpos,ypos,font+asciiremap[toupper(ch)]);
xpos+=fontxsize;
}
}
void drawbigstring(int xpos, int ypos, const char *str) {
char ch;
while('\0' != (ch=*str++)) {
drawfigure(xpos,ypos,bigfont+asciiremap[toupper(ch)]);
xpos+=bigfontxsize;
}
}
void centerbig(int y, const char *str) {
int w;
w=strlen(str)*bigfontxsize;
drawbigstring((IXSIZE-w)>>1,y,str);
}
// static void scrprintf(char *str,...) {
// char output[256],*p,*p2;
// va_list ap;
//
// va_start(ap, str);
//
// vsprintf(output,str,ap);
// p=output;
// for(;;) {
// p2=p;
// while(*p2 && *p2!='\n') ++p2;
// if(*p2) {
// *p2=0;
// drawstring(textx,texty,p);
// texty+=fontysize;
// textx=10;
// p=p2+1;
// } else {
// drawstring(textx,texty,p);
// textx+=fontxsize*(p2-p);
// break;
// }
// }
// copyup();
// }
static void bigscrprintf(char *str,...) {
char output[256],*p,*p2;
va_list ap;
va_start(ap, str);
vsprintf(output,str,ap);
p=output;
for(;;) {
p2=p;
while(*p2 && *p2!='\n') ++p2;
if(*p2) {
*p2=0;
drawbigstring(textx,texty,p);
texty+=bigfontysize;
textx=10;
p=p2+1;
} else {
drawbigstring(textx,texty,p);
textx+=bigfontxsize*(p2-p);
break;
}
}
copyup();
}
void addsprite(int x,int y,figure *fig) {
sprite *sp;
if(spritesused==MAXSPRITES) return;
sp=sprites+spritesused++;
sp->flags=0;
sp->xpos=x;
sp->ypos=y;
sp->fig=fig;
}
void plotsprites(void) {
int i;
sprite *sp;
sp=sprites;
for(i=0;i<spritesused;++i) {
drawfigure(sp->xpos,sp->ypos,sp->fig);
++sp;
}
}
void erasesprites(void) {
int i;
sprite *sp;
figure *fig;
sp=sprites;
for(i=0;i<spritesused;++i) {
fig=sp->fig;
solidcopy(&background,
sp->xpos+fig->xdelta,sp->ypos+fig->ydelta,
fig->xsize,fig->ysize);
++sp;
}
}
void clearsprites(void) {
int i;
sprite *sp;
figure *fig;
sp=sprites;
for(i=0;i<spritesused;++i) {
fig=sp->fig;
clearrect(sp->xpos+fig->xdelta,sp->ypos+fig->ydelta,
fig->xsize,fig->ysize);
++sp;
}
}
void clearspritelist(void) {
spritesused=0;
}
int tovideox(int x) {
return (x>>FRACTION)+arraystartx;
}
int tovideoy(int y) {
return (y>>FRACTION)+arraystarty;
}
int screentoarrayx(int x) {
x+=arrayspacex << (FRACTION+2);
return ((x>>FRACTION)+(arrayspacex>>1))/arrayspacex-4;
}
int screentoarrayy(int y) {
y+=arrayspacey << (FRACTION+2);
return ((y>>FRACTION)+(arrayspacey>>1))/arrayspacey-4;
}
int arraytoscreenx(int x) {
return arrayspacex*x<<FRACTION;
}
int arraytoscreeny(int y) {
return arrayspacey*y<<FRACTION;
}
static void loadfonts(void) {
int i,j;
const unsigned char *p;
getsingle(fontname,font,NUMCHARACTERS);
getsingle(bigfontname,bigfont,NUMCHARACTERS);
fontxsize=8;
fontysize=12;
bigfontxsize=16;
bigfontysize=24;
bigfontyspace=32;
p=remapstring;
j=0;while(*p && *p!=' ') ++p,++j;
memset(asciiremap,j,sizeof(asciiremap));
p=remapstring;
i=0;
while(*p && i<NUMCHARACTERS)
asciiremap[(int)*p++]=i++;
}
void loadgfx() {
gfxset *gs;
gfxset *colorgs;
int err;
int i;
char name[256];
strcpy(walkingname,"walk");
strcpy(colorsetname,"pal");
strcpy(backgroundname,"field0");
strcpy(blocksname,"blocks3");
strcpy(blocksxname,"blocks3x");
strcpy(bombs1name,"bomb1");
strcpy(bombs2name,"bomb2");
strcpy(flamesname,"flames");
strcpy(tilesname,"tiles");
strcpy(deathname,"death1");
strcpy(fontname,"font");
strcpy(bigfontname,"bigfont");
gs=malloc((MAXSETS+1)*sizeof(gfxset));
if(!gs)
nomem("loadgfx");
colorgs=gs+1;
for(i=0;i<MAXSETS;++i) {
sprintf(name,"%s%d",colorsetname,i);
err=dopcx(name,colorgs+i);
if(err) continue;
}
loadfonts();
texthome();
bigscrprintf("Loading graphics...\n");
err=dopcx(backgroundname,gs);
if(err) exit(1000+err);
createinout(gs);
solidfetch(gs,&background);
solidfetch(gs,&backgroundoriginal);
freegfxset(gs);
bigscrprintf("Loading blocks\n");
getsingle(blocksname,blocks,3);
bigscrprintf("Loading block explosions\n");
getsingle(blocksxname,blocksx,9);
bigscrprintf("Loading walking figures\n");
getgroup(walkingname,colorgs,walking[0],NUMWALKFRAMES);
bigscrprintf("Loading normal bombs\n");
getgroup(bombs1name,colorgs,bombs1[0],NUMBOMBFRAMES);
bigscrprintf("Loading controlled bombs\n");
getgroup(bombs2name,colorgs,bombs2[0],NUMBOMBFRAMES);
bigscrprintf("Loading flames\n");
// getgroup(flamesname,colorgs,flamefigs[0],NUMFLAMEFRAMES);
getsingle(flamesname,flamefigs[0],NUMFLAMEFRAMES);
bigscrprintf("Loading bonus tiles\n");
getsingle(tilesname,tiles,15);
bigscrprintf("Loading death sequence\n");
getsingle(deathname,death,NUMDEATHFRAMES);
for(i=0;i<MAXSETS;++i)
freegfxset(colorgs+i);
free(gs);
bigscrprintf("Done loading graphics\n");
}
void failure(char *str,...) {
char output[256];
va_list ap;
int len;
long now;
va_start(ap, str);
len = vsnprintf(output, sizeof(output), str, ap);
if (len >= 256) len = 255; /* truncated string */
clear();
drawbigstring((IXSIZE - len*bigfontxsize) / 2, (IYSIZE-bigfontysize) / 2, output);
copyup();
now = longtime();
while (!exitflag && longtime()-now < 3) {
scaninput();
if (anydown()) {
takedown();
return;
}
}
}