#include #include #include #include #include #include #include #include #include #include #include #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; } } }