473 lines
9.1 KiB
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;
|
|
}
|
|
}
|
|
}
|