home *** CD-ROM | disk | FTP | other *** search
Wrap
/****************************************************************************\ ; ; ; ulmp.c - project LMP control center ; ; implementation ; ; ; ; general LMP routines ; ; ; ; Uwe Girlich ; ; Erika-von-Brockdorff-Strasse 2 ; ; 04159 Leipzig ; ; Deutschland / Germany ; ; E-mail: girlich@aix520.informatik.uni-leipzig.de ; ; ; \****************************************************************************/ #include <errno.h> #include <math.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <unistd.h> #include "tools.h" #include "ulmp.h" char *PlayerColor[] = { "green", "indigo", "brown", "red" }; char *WeaponName[] = { "Fist/Chainsaw", "Pistol", "Shotgun", "Chaingun", "Rocket Launcher", "Plasma Rifle", "BFG 9000", "Chainsaw", "Fist/Chainsaw", "Pistol", "Shotgun/Super Shotgun", "Chaingun", "Rocket Launcher", "Plasma Rifle", "BFG 9000", "Chainsaw", "Staff/Gauntlets of the Necromancer", "Crystal", "Ethereal Crossbow", "Dragon Claw", "Hellstaff", "Phoenix Rod", "Mace", "Gauntlets of the Necromancer" }; char *ArtifactName[] = { "Ring of Invincibility", "Shadowsphere", "Quartz Flask", "Chaos Device", "Tome of Power", "Torch", "Time Bomb of the Ancients", "Morph Ovum", "Wings of Wrath", "Mystic Urn" }; VK VersionKey[] = { { "1.0" , HERETIC, 0, 1}, { "1.1" , DOOM_old, 0, 1}, { "1.2" , DOOM_old, 0, 2}, { "<1.4" , DOOM_old, 0, 4}, { "1.4beta" , DOOM_new, 104, 1}, { "1.5beta" , DOOM_new, 105, 1}, { "1.6beta" , DOOM_new, 106, 1}, { "1.666" , DOOM_new, 106, 2}, { "1.666" , DOOM2, 106, 2}, { "1.7" , DOOM2, 107, 1}, { "1.7a" , DOOM_new, 107, 2}, { "1.7a" , DOOM2, 107, 2}, { "1.8" , DOOM_new, 108, 1}, { "1.8" , DOOM2, 108, 1}, { "1.9" , DOOM_new, 109, 1}, { "1.9" , DOOM2, 109, 1} }; #define MYBUFSIZE 65536 /******************************************************************************/ /** LMP ***********************************************************************/ /******************************************************************************/ void LMP_init(LMP_t *l, char *filename, char *mode) { struct stat buf; if ((l->filename = strdup(filename))==NULL) syserror(errno,"strdup"); if ((l->file=fopen(l->filename, mode))==NULL) syserror(errno,l->filename); if (setvbuf(l->file,NULL,_IOFBF,BUFSIZ>MYBUFSIZE?BUFSIZ:MYBUFSIZE)!=0) syserror(errno,"setvbuf"); if (stat(l->filename,&buf)==-1) syserror(errno,l->filename); l->filesize=buf.st_size; } int LMP_checkgametype(LMP_t *l) { signed char buffer[12]; long num, i; double av_h, av_d; long int n_h, n_d; fprintf(stderr,"determine game type"); fseek(l->file,l->headersize,SEEK_SET); num=l->datasize/12; if (num<200) return DOOM_old | HERETIC; if (num>5000) num=5000; av_h = av_d = 0; n_h = n_d = 0; for (i=0;i<num;i++) { if (fread(buffer,1,12,l->file)==0) syserror(FREAD,l->filename); av_h += buffer[2] + buffer[8]; n_h += 2; av_d += buffer[2] + buffer[6] + buffer[10]; n_d += 3; } av_h /= n_h; av_d /= n_d; fseek(l->file,l->headersize,SEEK_SET); if (fabs(av_h)<fabs(av_d)) { fprintf(stderr,": HERETIC\n"); return HERETIC; } else { fprintf(stderr,": old DOOM\n"); return DOOM_old; } } void LMP_readheader(LMP_t *l) { int game, i; rewind(l->file); if (fread(l->header,1,SHORT_SIZE,l->file)==0) syserror(FREAD,l->filename); if (l->header[0]<104) { l->headersize = SHORT_SIZE; l->versionbyte = 0; l->skill = l->header[0]; l->episode = l->header[1]; l->map = l->header[2]; l->multirule = 0; l->respawn = 0; l->fast = 0; l->nomonsters = 0; l->mainplayer = 0; } else { rewind(l->file); if (fread(l->header,1,LONG_SIZE,l->file)==0) syserror(FREAD,l->filename); l->headersize = LONG_SIZE; l->versionbyte = l->header[0]; l->skill = l->header[1]; l->episode = l->header[2]; l->map = l->header[3]; l->multirule = l->header[4]; l->respawn = l->header[5]; l->fast = l->header[6]; l->nomonsters = l->header[7]; l->mainplayer = l->header[8]; } for (i=0, l->playernum=0;i<MAXPLAYER;i++) if (l->header[l->headersize-MAXPLAYER+i]) l->num[l->playernum++] = i; l->datasize=l->filesize-l->headersize-1; /* determine possible game type */ if (l->headersize==SHORT_SIZE) { /* DOOM_old or HERETIC */ if (l->datasize % (SHORT_TIC*l->playernum)) { /* not DOOM_old */ /* only HERETIC or WRONG */ if (l->datasize % (LONG_TIC*l->playernum)) { game=WRONG; } else { /* HERETIC */ game=HERETIC; } } else { /* DOOM_old or HERETIC */ if (l->datasize % (LONG_TIC*l->playernum)) { /* DOOM_old */ game=DOOM_old; } else { /* DOOM_old or HERETIC */ game=LMP_checkgametype(l); } } } else { /* DOOM_new or DOOM2 */ if (l->episode>1) game=DOOM_new; else if (l->map>9) game=DOOM2; else game=DOOM_new|DOOM2; if (l->datasize % (SHORT_TIC*l->playernum)) game=WRONG; } if (game==WRONG) syserror(WLMP,l->filename); if (l->game==(DOOM_old|DOOM_new)) l->game=(l->headersize==SHORT_SIZE?DOOM_old:DOOM_new); if (game==DOOM_old || game==DOOM_new || game==DOOM2 || game==HERETIC || game==(DOOM_new|DOOM2)) { if (l->game==UNKNOWN) l->game=game; else { if (!(l->game & game)) syswarning(DEFTYPE,l->filename); } } else { if (l->game==UNKNOWN) syserror(UKTYPE,l->filename); else { if (!(l->game & game)) syswarning(DEFTYPE,l->filename); } } getversion(l->versionbyte,&(l->game),l->filename,&l->gs,&l->ns); l->ticsize=((l->game==HERETIC)?LONG_TIC:SHORT_TIC); l->tics=l->datasize / (l->playernum * l->ticsize); l->time=l->tics*TICTIME; } void LMP_writeheader(LMP_t *l) { int i; switch (l->game) { case HERETIC: case DOOM_old: l->headersize=SHORT_SIZE; break; case DOOM_new: case DOOM2: case DOOM_new|DOOM2: l->headersize=LONG_SIZE; } if (l->headersize==SHORT_SIZE) { l->header[0] = l->skill; l->header[1] = l->episode; l->header[2] = l->map; } else { l->header[0] = l->versionbyte; l->header[1] = l->skill; l->header[2] = l->episode; l->header[3] = l->map; l->header[4] = l->multirule; l->header[5] = l->respawn; l->header[6] = l->fast; l->header[7] = l->nomonsters; l->header[8] = l->mainplayer; } for (i=0;i<MAXPLAYER;i++) l->header[l->headersize-MAXPLAYER+i]=0; for (i=0;i<l->playernum;i++) l->header[l->headersize-MAXPLAYER+l->num[i]] = 1; if (fwrite(l->header,1,l->headersize,l->file)==0) syserror(FWRITE,l->filename); } void LMP_writequitbyte(LMP_t *l) { unsigned char a=0x80; if (fwrite(&a,1,1,l->file)==0) syserror(FWRITE,l->filename); } void LMP_putgametic(LMP_t *l, TIC_t *t) { if (fwrite(t,1,l->ticsize,l->file)==0) syserror(FWRITE,l->filename); } void LMP_getgametic(LMP_t *l, TIC_t *t) { if (fread(t,1,l->ticsize,l->file)==0) syserror(FREAD,l->filename); } void LMP_done(LMP_t *l) { if (fclose(l->file)!=0) syserror(errno,l->filename); free(l->filename); } /******************************************************************************/ /** LS ************************************************************************/ /******************************************************************************/ void LS_init(LS_t *l, char *filename, char *mode) { struct stat buf; if ((l->filename = strdup(filename))==NULL) syserror(errno,"strdup"); if ((l->file=fopen(l->filename, mode))==NULL) syserror(errno,l->filename); if (setvbuf(l->file,NULL,_IOFBF,BUFSIZ>MYBUFSIZE?BUFSIZ:MYBUFSIZE)!=0) syserror(errno,"setvbuf"); if (stat(l->filename,&buf)==-1) syserror(errno,l->filename); l->filesize=buf.st_size; } void LS_done(LS_t *l) { if (fclose(l->file)!=0) syserror(errno,l->filename); free(l->filename); } /******************************************************************************/ /** STAT **********************************************************************/ /******************************************************************************/ void STAT_init(STAT_t *s, char *command, int maxm) { unsigned char i; for (i=0;i<128;i++) s->hist[i]=0; s->sum=0; if ((s->command=strdup(command))==NULL) syserror(errno,"strdup"); s->maxm=maxm; } void STAT_calc(STAT_t *s) { unsigned char i; s->m[0]=s->m[1]=s->m[2]; s->sum = 0; for (i=0;i<128;i++) { s->sum+=s->hist[i]; if (s->hist[i]>s->hist[s->m[0]]) { s->m[2]=s->m[1]; s->m[1]=s->m[0]; s->m[0]=i; } else if (s->hist[i]>s->hist[s->m[1]]) { s->m[2]=s->m[1]; s->m[1]=i; } else if (s->hist[i]>s->hist[s->m[2]]) { s->m[2]=i; } if (s->hist[i]>0) s->last=i; } if (s->hist[s->m[0]]+s->hist[s->m[1]]+s->hist[s->m[2]]==s->sum) s->control = C_KEY; else s->control = C_MOUSE; } int STAT_turncheck(STAT_t *s, unsigned char t0, unsigned char t1, unsigned char t2) { return (s->m[0]==t0 || s->m[0]==t1 || s->m[0]==t2 || s->m[0]==0) && (s->m[1]==t0 || s->m[1]==t1 || s->m[1]==t2 || s->m[1]==0) && (s->m[2]==t0 || s->m[2]==t1 || s->m[2]==t2 || s->m[2]==0); } char *STAT_writehist(STAT_t *s, char *buf) { int empty; unsigned char i; empty=TRUE; strcpy(buf,""); for (i=0;i<s->maxm;i++) { if (s->hist[s->m[i]]!=0) { if (!empty) strcat(buf,", "); sprintf(buf+strlen(buf),"%lu * %s%d",s->hist[s->m[i]],s->command,s->m[i]); empty=FALSE; } } return buf; } void STAT_done(STAT_t *s) { } /******************************************************************************/ /** Outside *******************************************************************/ /******************************************************************************/ void getversion(unsigned char versionbyte, int *game, char *filename, char **gs, char **ns) { int i; unsigned int n; *gs=(char*)malloc(100*sizeof(char)); *gs[0]='\0'; *ns=(char*)malloc(100*sizeof(char)); *ns[0]='\0'; /* calculate version number string */ n=0; /* no version strings */ for (i=0;i<VersionKeys;i++) { if (VersionKey[i].versionbyte==versionbyte) { if (VersionKey[i].game & (*game)) { if (!(n & VersionKey[i].string_no)) { if(strlen(*ns)) strcat(*ns," or "); strcat(*ns, VersionKey[i].versionstring); n|=VersionKey[i].string_no; } /* string not used */ } /* game ok */ } /* versionbyte ok */ } /* for i */ /* calculate game string */ if ((*game & DOOM_old) || (*game & DOOM_new)) { if (strlen(*gs)) strcat(*gs," or "); strcat(*gs,"DOOM"); } if (*game & DOOM2) { if (strlen(*gs)) strcat(*gs," or "); strcat(*gs,"DOOM ]["); } if (*game & HERETIC) { if (strlen(*gs)) strcat(*gs," or "); strcat(*gs,"HERETIC"); } } unsigned char strtoversionbyte(char *s) { long int i,l; char *res; for (i=0;i<VersionKeys;i++) { l=strlen(VersionKey[i].versionstring)>strlen(s)?strlen(VersionKey[i].versionstring):strlen(s); if (l>3) l=3; if (!strncmp(VersionKey[i].versionstring,s,l)) return VersionKey[i].versionbyte; } i=strtol(s,&res,0)%256; if (res[0]!='\0') syserror(EINVAL,res); return i; } /*- file end ulmp.c ----------------------------------------------------------*/