You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
482 lines
9.7 KiB
482 lines
9.7 KiB
|
|
#include <fcntl.h> |
|
#include <netdb.h> |
|
#include <signal.h> |
|
#include <stdarg.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <sys/socket.h> |
|
#include <sys/time.h> |
|
#include <sys/types.h> |
|
#include <unistd.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; |
|
snprintf(tname, sizeof(tname), DATADIR "/%s", name); |
|
ihand = open(tname, O_RDONLY); |
|
if (ihand < 0) { |
|
char tname2[260]; |
|
snprintf(tname2, sizeof(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); |
|
vsnprintf(output, sizeof(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[267]; |
|
|
|
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) { |
|
snprintf(name, sizeof(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; |
|
} |
|
} |
|
}
|
|
|