home *** CD-ROM | disk | FTP | other *** search
/ Crazy Collection 12 / CC-12_1.iso / update / doompack / data.a00 / LMPC280.ZIP / LMPC-2.8 / SRC / ULMP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-23  |  12.7 KB  |  446 lines

  1. /****************************************************************************\
  2. ;                                                                            ;
  3. ;  ulmp.c - project LMP control center                                       ;
  4. ;  implementation                                                            ;
  5. ;                                                                            ;
  6. ;  general LMP routines                                                      ;
  7. ;                                                                            ;
  8. ;  Uwe Girlich                                                               ;
  9. ;  Erika-von-Brockdorff-Strasse 2                                            ;
  10. ;  04159 Leipzig                                                             ;
  11. ;  Deutschland / Germany                                                     ;
  12. ;  E-mail: girlich@aix520.informatik.uni-leipzig.de                          ;
  13. ;                                                                            ;
  14. \****************************************************************************/
  15.  
  16.  
  17. #include <errno.h>
  18. #include <math.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <sys/stat.h>
  22. #include <unistd.h>
  23. #include "tools.h"
  24. #include "ulmp.h"
  25.  
  26.  
  27. char *PlayerColor[] = {
  28.                         "green",
  29.                         "indigo",
  30.                         "brown",
  31.                         "red"
  32.                       };
  33.  
  34. char *WeaponName[] = {
  35.                        "Fist/Chainsaw", "Pistol", "Shotgun", "Chaingun", "Rocket Launcher", "Plasma Rifle", "BFG 9000", "Chainsaw",
  36.                        "Fist/Chainsaw", "Pistol", "Shotgun/Super Shotgun", "Chaingun", "Rocket Launcher", "Plasma Rifle", "BFG 9000", "Chainsaw",
  37.                        "Staff/Gauntlets of the Necromancer", "Crystal", "Ethereal Crossbow", "Dragon Claw", "Hellstaff", "Phoenix Rod", "Mace", "Gauntlets of the Necromancer"
  38.                      };
  39.  
  40. char *ArtifactName[] = {
  41.                          "Ring of Invincibility",
  42.                          "Shadowsphere",
  43.                          "Quartz Flask",
  44.                          "Chaos Device",
  45.                          "Tome of Power",
  46.                          "Torch",
  47.                          "Time Bomb of the Ancients",
  48.                          "Morph Ovum",
  49.                          "Wings of Wrath",
  50.                          "Mystic Urn"
  51.                        };
  52.  
  53.  
  54. VK VersionKey[] = {
  55.                   { "1.0"     , HERETIC,          0, 1},
  56.           { "1.1"     , DOOM_old,         0, 1},
  57.                   { "1.2"     , DOOM_old,         0, 2},
  58.           { "<1.4"    , DOOM_old,         0, 4},
  59.           { "1.4beta" , DOOM_new,       104, 1},
  60.                   { "1.5beta" , DOOM_new,       105, 1},
  61.           { "1.6beta" , DOOM_new,       106, 1},
  62.           { "1.666"   , DOOM_new,       106, 2},
  63.           { "1.666"   , DOOM2,          106, 2},
  64.           { "1.7"     , DOOM2,          107, 1},
  65.           { "1.7a"    , DOOM_new,       107, 2},
  66.           { "1.7a"    , DOOM2,          107, 2},
  67.           { "1.8"     , DOOM_new,       108, 1},
  68.           { "1.8"     , DOOM2,          108, 1},
  69.           { "1.9"     , DOOM_new,       109, 1},
  70.           { "1.9"     , DOOM2,          109, 1}
  71.                 };
  72.  
  73.  
  74. #define MYBUFSIZE 65536
  75.  
  76.  
  77. /******************************************************************************/
  78. /** LMP ***********************************************************************/
  79. /******************************************************************************/
  80.  
  81. void LMP_init(LMP_t *l, char *filename, char *mode)
  82. {
  83.   struct stat buf;
  84.  
  85.   if ((l->filename = strdup(filename))==NULL) syserror(errno,"strdup");
  86.   if ((l->file=fopen(l->filename, mode))==NULL) syserror(errno,l->filename);
  87.   if (setvbuf(l->file,NULL,_IOFBF,BUFSIZ>MYBUFSIZE?BUFSIZ:MYBUFSIZE)!=0) syserror(errno,"setvbuf");
  88.   if (stat(l->filename,&buf)==-1) syserror(errno,l->filename);
  89.   l->filesize=buf.st_size;
  90. }
  91.  
  92. int LMP_checkgametype(LMP_t *l)
  93. {
  94.   signed char buffer[12];
  95.   long num, i;
  96.   double av_h, av_d;
  97.   long int n_h, n_d;
  98.  
  99.   fprintf(stderr,"determine game type");
  100.   fseek(l->file,l->headersize,SEEK_SET);
  101.   num=l->datasize/12;
  102.   if (num<200) return DOOM_old | HERETIC;
  103.   if (num>5000) num=5000; 
  104.   av_h = av_d = 0;
  105.   n_h = n_d = 0;
  106.   for (i=0;i<num;i++) {
  107.     if (fread(buffer,1,12,l->file)==0) syserror(FREAD,l->filename);
  108.     av_h += buffer[2] + buffer[8]; 
  109.     n_h += 2;
  110.     av_d += buffer[2] + buffer[6] + buffer[10];
  111.     n_d += 3;
  112.   }
  113.   av_h /= n_h;
  114.   av_d /= n_d;
  115.   fseek(l->file,l->headersize,SEEK_SET);
  116.   if (fabs(av_h)<fabs(av_d)) {
  117.     fprintf(stderr,": HERETIC\n"); 
  118.     return HERETIC;
  119.   }
  120.   else {
  121.     fprintf(stderr,": old DOOM\n");
  122.     return DOOM_old;
  123.   }
  124. }
  125.  
  126. void LMP_readheader(LMP_t *l)
  127. {
  128.   int game, i;
  129.  
  130.   rewind(l->file);
  131.   if (fread(l->header,1,SHORT_SIZE,l->file)==0) syserror(FREAD,l->filename);
  132.   if (l->header[0]<104) {
  133.     l->headersize  = SHORT_SIZE;
  134.     l->versionbyte = 0; 
  135.     l->skill       = l->header[0];
  136.     l->episode     = l->header[1];
  137.     l->map         = l->header[2];
  138.     l->multirule   = 0;
  139.     l->respawn     = 0;
  140.     l->fast        = 0;
  141.     l->nomonsters  = 0;
  142.     l->mainplayer  = 0;
  143.   }
  144.   else {
  145.     rewind(l->file);
  146.     if (fread(l->header,1,LONG_SIZE,l->file)==0) syserror(FREAD,l->filename);
  147.     l->headersize = LONG_SIZE;
  148.     l->versionbyte = l->header[0];
  149.     l->skill       = l->header[1];
  150.     l->episode     = l->header[2];
  151.     l->map         = l->header[3];
  152.     l->multirule   = l->header[4];
  153.     l->respawn     = l->header[5];
  154.     l->fast        = l->header[6];
  155.     l->nomonsters  = l->header[7];
  156.     l->mainplayer  = l->header[8];
  157.   }
  158.   for (i=0, l->playernum=0;i<MAXPLAYER;i++) 
  159.     if (l->header[l->headersize-MAXPLAYER+i]) l->num[l->playernum++] = i;
  160.   l->datasize=l->filesize-l->headersize-1;
  161.   
  162.   /* determine possible game type */
  163.   if (l->headersize==SHORT_SIZE) {
  164.     /* DOOM_old or HERETIC */
  165.     if (l->datasize % (SHORT_TIC*l->playernum)) {
  166.       /* not DOOM_old */
  167.       /* only HERETIC or WRONG */
  168.       if (l->datasize % (LONG_TIC*l->playernum)) {
  169.         game=WRONG; 
  170.       }
  171.       else {
  172.         /* HERETIC */
  173.         game=HERETIC;
  174.       }
  175.     }
  176.     else {
  177.       /* DOOM_old or HERETIC */
  178.       if (l->datasize % (LONG_TIC*l->playernum)) {
  179.         /* DOOM_old */
  180.         game=DOOM_old;
  181.         }
  182.       else {
  183.         /* DOOM_old or HERETIC */
  184.         game=LMP_checkgametype(l);
  185.       }
  186.     } 
  187.   }
  188.   else {
  189.     /* DOOM_new or DOOM2 */
  190.     if (l->episode>1) 
  191.       game=DOOM_new;
  192.     else 
  193.       if (l->map>9)
  194.         game=DOOM2;
  195.       else
  196.         game=DOOM_new|DOOM2;
  197.     if (l->datasize % (SHORT_TIC*l->playernum)) game=WRONG;
  198.   }
  199.   
  200.   if (game==WRONG) syserror(WLMP,l->filename); 
  201.   if (l->game==(DOOM_old|DOOM_new))
  202.     l->game=(l->headersize==SHORT_SIZE?DOOM_old:DOOM_new);
  203.   if (game==DOOM_old || 
  204.       game==DOOM_new || 
  205.       game==DOOM2    ||  
  206.       game==HERETIC  ||
  207.       game==(DOOM_new|DOOM2)) {
  208.     if (l->game==UNKNOWN) 
  209.       l->game=game;
  210.     else {
  211.       if (!(l->game & game)) 
  212.         syswarning(DEFTYPE,l->filename);
  213.     }
  214.   }      
  215.   else {
  216.     if (l->game==UNKNOWN)
  217.       syserror(UKTYPE,l->filename);
  218.     else {
  219.       if (!(l->game & game)) 
  220.         syswarning(DEFTYPE,l->filename);
  221.     }    
  222.   }
  223.   getversion(l->versionbyte,&(l->game),l->filename,&l->gs,&l->ns);  
  224.   l->ticsize=((l->game==HERETIC)?LONG_TIC:SHORT_TIC);
  225.   l->tics=l->datasize / (l->playernum * l->ticsize); 
  226.   l->time=l->tics*TICTIME;
  227. }
  228.  
  229. void LMP_writeheader(LMP_t *l)
  230. {
  231.   int i;
  232.  
  233.   switch (l->game) {
  234.     case HERETIC:
  235.     case DOOM_old:       l->headersize=SHORT_SIZE; break;
  236.     case DOOM_new:
  237.     case DOOM2:
  238.     case DOOM_new|DOOM2: l->headersize=LONG_SIZE;
  239.   }
  240.   if (l->headersize==SHORT_SIZE) {
  241.     l->header[0] = l->skill;
  242.     l->header[1] = l->episode;
  243.     l->header[2] = l->map;
  244.   }
  245.   else {
  246.     l->header[0] = l->versionbyte;
  247.     l->header[1] = l->skill;
  248.     l->header[2] = l->episode;
  249.     l->header[3] = l->map;
  250.     l->header[4] = l->multirule;
  251.     l->header[5] = l->respawn;
  252.     l->header[6] = l->fast;
  253.     l->header[7] = l->nomonsters;
  254.     l->header[8] = l->mainplayer;
  255.   }
  256.  
  257.   for (i=0;i<MAXPLAYER;i++) l->header[l->headersize-MAXPLAYER+i]=0;
  258.   for (i=0;i<l->playernum;i++) l->header[l->headersize-MAXPLAYER+l->num[i]] = 1;
  259.   
  260.   if (fwrite(l->header,1,l->headersize,l->file)==0) syserror(FWRITE,l->filename);
  261. }  
  262.  
  263. void LMP_writequitbyte(LMP_t *l)
  264. {
  265.   unsigned char a=0x80;
  266.  
  267.   if (fwrite(&a,1,1,l->file)==0) syserror(FWRITE,l->filename);
  268. }
  269.  
  270. void LMP_putgametic(LMP_t *l, TIC_t *t)
  271. {
  272.   if (fwrite(t,1,l->ticsize,l->file)==0) syserror(FWRITE,l->filename);
  273. }
  274.  
  275. void LMP_getgametic(LMP_t *l, TIC_t *t)
  276. {
  277.   if (fread(t,1,l->ticsize,l->file)==0) syserror(FREAD,l->filename);
  278. }
  279.  
  280. void LMP_done(LMP_t *l)
  281. {
  282.   if (fclose(l->file)!=0) syserror(errno,l->filename);
  283.   free(l->filename);
  284. }
  285.  
  286.  
  287. /******************************************************************************/
  288. /** LS ************************************************************************/
  289. /******************************************************************************/
  290.  
  291. void LS_init(LS_t *l, char *filename, char *mode)
  292. {
  293.   struct stat buf;
  294.  
  295.   if ((l->filename = strdup(filename))==NULL) syserror(errno,"strdup");
  296.   if ((l->file=fopen(l->filename, mode))==NULL) syserror(errno,l->filename);
  297.   if (setvbuf(l->file,NULL,_IOFBF,BUFSIZ>MYBUFSIZE?BUFSIZ:MYBUFSIZE)!=0) syserror(errno,"setvbuf");
  298.   if (stat(l->filename,&buf)==-1) syserror(errno,l->filename);
  299.   l->filesize=buf.st_size;
  300. }
  301.  
  302.  
  303. void LS_done(LS_t *l)
  304. {
  305.   if (fclose(l->file)!=0) syserror(errno,l->filename);
  306.   free(l->filename);
  307. }
  308.  
  309.  
  310. /******************************************************************************/
  311. /** STAT **********************************************************************/
  312. /******************************************************************************/
  313.  
  314. void STAT_init(STAT_t *s, char *command, int maxm)
  315. {
  316.   unsigned char i;
  317.  
  318.   for (i=0;i<128;i++) s->hist[i]=0;
  319.   s->sum=0;
  320.   if ((s->command=strdup(command))==NULL) syserror(errno,"strdup");
  321.   s->maxm=maxm;
  322. }
  323.  
  324.  
  325. void STAT_calc(STAT_t *s)
  326. {
  327.   unsigned char i;
  328.  
  329.   s->m[0]=s->m[1]=s->m[2];
  330.   s->sum = 0;
  331.   for (i=0;i<128;i++) {
  332.     s->sum+=s->hist[i];
  333.     if (s->hist[i]>s->hist[s->m[0]]) {
  334.       s->m[2]=s->m[1]; s->m[1]=s->m[0]; s->m[0]=i;
  335.     }
  336.     else if (s->hist[i]>s->hist[s->m[1]]) {
  337.       s->m[2]=s->m[1]; s->m[1]=i;
  338.     }
  339.     else if (s->hist[i]>s->hist[s->m[2]]) {
  340.       s->m[2]=i;
  341.     }  
  342.     if (s->hist[i]>0) s->last=i;
  343.   }
  344.   if (s->hist[s->m[0]]+s->hist[s->m[1]]+s->hist[s->m[2]]==s->sum) 
  345.     s->control = C_KEY;
  346.   else
  347.     s->control = C_MOUSE;
  348. }
  349.  
  350.  
  351. int STAT_turncheck(STAT_t *s, unsigned char t0, unsigned char t1, unsigned char t2)
  352. {
  353.   return    (s->m[0]==t0 || s->m[0]==t1 || s->m[0]==t2 || s->m[0]==0)
  354.          && (s->m[1]==t0 || s->m[1]==t1 || s->m[1]==t2 || s->m[1]==0)
  355.          && (s->m[2]==t0 || s->m[2]==t1 || s->m[2]==t2 || s->m[2]==0);
  356. }
  357.  
  358.  
  359. char *STAT_writehist(STAT_t *s, char *buf)
  360. {
  361.   int empty;
  362.   unsigned char i;
  363.  
  364.   empty=TRUE;
  365.   strcpy(buf,"");
  366.    
  367.   for (i=0;i<s->maxm;i++) {
  368.     if (s->hist[s->m[i]]!=0) {
  369.       if (!empty) strcat(buf,", ");
  370.       sprintf(buf+strlen(buf),"%lu * %s%d",s->hist[s->m[i]],s->command,s->m[i]);
  371.       empty=FALSE;
  372.     }
  373.   }
  374.   return buf;
  375. }
  376.  
  377.  
  378. void STAT_done(STAT_t *s)
  379. {
  380. }
  381.  
  382. /******************************************************************************/
  383. /** Outside *******************************************************************/
  384. /******************************************************************************/
  385.  
  386. void getversion(unsigned char versionbyte, int *game, char *filename, 
  387.                 char **gs, char **ns) 
  388. {
  389.   int i;
  390.   unsigned int n;
  391.  
  392.   *gs=(char*)malloc(100*sizeof(char));
  393.   *gs[0]='\0';
  394.   *ns=(char*)malloc(100*sizeof(char));
  395.   *ns[0]='\0';
  396.  
  397.   /* calculate version number string */
  398.   n=0; /* no version strings */
  399.   for (i=0;i<VersionKeys;i++) {
  400.     if (VersionKey[i].versionbyte==versionbyte) {
  401.       if (VersionKey[i].game & (*game)) {
  402.         if (!(n & VersionKey[i].string_no)) {
  403.           if(strlen(*ns)) strcat(*ns," or ");
  404.           strcat(*ns, VersionKey[i].versionstring);
  405.           n|=VersionKey[i].string_no;
  406.         } /* string not used */
  407.       } /* game ok */
  408.     } /* versionbyte ok */
  409.   } /* for i */
  410.  
  411.   /* calculate game string */
  412.   if ((*game & DOOM_old) || (*game & DOOM_new)) {
  413.     if (strlen(*gs)) strcat(*gs," or ");
  414.     strcat(*gs,"DOOM");
  415.   }
  416.   if (*game & DOOM2) {
  417.     if (strlen(*gs)) strcat(*gs," or ");
  418.     strcat(*gs,"DOOM ][");
  419.   }
  420.   if (*game & HERETIC) {
  421.     if (strlen(*gs)) strcat(*gs," or ");
  422.     strcat(*gs,"HERETIC");
  423.   }
  424. }
  425.  
  426.  
  427. unsigned char strtoversionbyte(char *s)
  428. {
  429.   long int i,l;
  430.   char *res;
  431.  
  432.   for (i=0;i<VersionKeys;i++) {
  433.     l=strlen(VersionKey[i].versionstring)>strlen(s)?strlen(VersionKey[i].versionstring):strlen(s);
  434.     if (l>3) l=3;
  435.     if (!strncmp(VersionKey[i].versionstring,s,l))
  436.       return VersionKey[i].versionbyte;
  437.   }   
  438.   i=strtol(s,&res,0)%256;
  439.   if (res[0]!='\0') syserror(EINVAL,res);
  440.   return i;
  441. }
  442.  
  443.  
  444. /*- file end ulmp.c ----------------------------------------------------------*/
  445.  
  446.