home *** CD-ROM | disk | FTP | other *** search
/ Crazy Collection 12 / CC-12_1.iso / update / doompack / data.a00 / LMPC280.ZIP / LMPC-2.8 / SRC / LMPC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-06  |  39.0 KB  |  1,303 lines

  1. /****************************************************************************\
  2. ;                                                                            ;
  3. ;  lmpc.c  -  projekt LMP control center                                     ;
  4. ;  main source code                                                          ;
  5. ;                                                                            ;
  6. ;  The program lmpc is a LMP conversion utility                              ;
  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. #ifndef VERSION
  18.   the version must be defined
  19. #endif
  20. #ifndef DATE
  21.   the date must be defined
  22. #endif
  23.  
  24. #include <ctype.h>
  25. #include <errno.h>
  26. #include <getopt.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <unistd.h>
  31. #include "ulmp.h"
  32. #include "tools.h"
  33.  
  34. #define acInfo          0x01
  35. #define acLMP2LS        0x02
  36. #define acLS2LMP        0x04
  37. #define acConvert       0x08
  38.  
  39. #define opVersion       0x01
  40. #define opViewPlayer    0x02
  41. #define opAddWT         0x04
  42. #define opRemovePause   0x08
  43. #define opSelectTics    0x10
  44. #define opDefineGame    0x20
  45.  
  46. #define OLD_NEW         1
  47. #define NEW_OLD         2
  48.  
  49. #define HEADER_START          0
  50. #define HEADER                1
  51. #define HEADER_END            2
  52. #define DATA_START            3
  53. #define DATA                  4
  54. #define DATA_END              5
  55.  
  56. #define LMP_INIT              1
  57. #define LMP_END               2
  58.  
  59. typedef struct {
  60.         unsigned char    action;
  61.         unsigned char    option;
  62.         unsigned char    versionbyte;
  63.         unsigned char    mainplayer;
  64.         long        tic_start;
  65.         long        tic_end;
  66.         long        addwt;
  67.         int        game;
  68.            } opt_t;
  69.  
  70.  
  71. /* prototypes */
  72. void syntax(void);
  73. void version(void);
  74. void ActionInfo(char *filename, opt_t *opt);
  75. void ActionLMP2LS(char *lmpfilename, char *lsfilename, opt_t *opt);
  76. void ActionLS2LMP(char *lsfilename, char *lmpfilename, int action);
  77. void ActionConvert(char *infilename, char *outfilename, opt_t *opt);
  78.  
  79. int argf;
  80. int argvf_base;
  81.  
  82. /******************************************************************************/
  83. /** Main program **************************************************************/
  84. /******************************************************************************/
  85.  
  86. int main(int argc, char **argv)
  87. {
  88.   int i;
  89.   int c;
  90.   char c_str[2]=" "; 
  91.   char *pos_r, *pos_l;
  92.   int a;
  93.   int sep;
  94.   opt_t opt;
  95.  
  96.   static struct option long_options[] = {
  97.     {"help",           0, 0, 'h'},
  98.     {"version",        0, 0, 'V'},
  99.     {"info",           0, 0, 'i'},
  100.     {"ls-to-lmp",      0, 0, 'l'},
  101.     {"lmp-to-ls",      0, 0, 's'},
  102.     {"change-version", 1, 0, 'v'},
  103.     {"change-player",  1, 0, 'p'},
  104.     {"add-WT",         1, 0, 'w'},
  105.     {"remove-pause",   0, 0, 'r'}, 
  106.     {"tic",            1, 0, 't'},
  107.     {"game",           1, 0, 'g'},
  108.     {0,                0, 0, 0}
  109.   };
  110.   int option_index = 0;
  111.  
  112.   opt.action    = 0;
  113.   opt.option    = 0;
  114.   opt.game      = UNKNOWN;
  115.   opt.tic_start = 0;
  116.   opt.tic_end   = 0;
  117.  
  118.   /* scan the command line */
  119.   while (1) {
  120.     c = getopt_long(argc, argv, "hVilsv:p:w:rt:g:", long_options, &option_index);
  121.  
  122.     if (c==-1) break;
  123.     *c_str = (char) c; 
  124.     switch (c) {
  125.       case ':': 
  126.         syserror(ARGMIS,c_str); 
  127.       break;
  128.       case 'h':
  129.         syntax();
  130.       break;
  131.       case 'V':
  132.         version(); 
  133.       break;
  134.       case 'i': 
  135.         if (opt.action) syserror(MANYACT,c_str);
  136.         opt.action |= acInfo; 
  137.       break;
  138.       case 'l':
  139.         if (opt.action) syserror(MANYACT,c_str);
  140.         opt.action = acLS2LMP;
  141.       break;
  142.       case 's':
  143.         if (opt.action) syserror(MANYACT,c_str);
  144.         opt.action = acLMP2LS;
  145.       break;
  146.       case 'v':
  147.         if (opt.action&(~acConvert)) syserror(MANYACT,c_str);
  148.         opt.action |= acConvert;
  149.         opt.option |= opVersion;
  150.         opt.versionbyte = strtoversionbyte(optarg); 
  151.       break;
  152.       case 'p':
  153.         if (opt.action&(~acConvert)) syserror(MANYACT,c_str);
  154.         opt.action |= acConvert;
  155.         opt.option |= opViewPlayer;
  156.         a = sscanf(optarg,"%i",&i);
  157.         opt.mainplayer = i % MAXPLAYER;
  158.         if (a!=1) syserror(INVOPT, optarg);
  159.       break;
  160.       case 'w':
  161.         if (opt.action&(~acConvert)) syserror(MANYACT,c_str);
  162.         opt.action |= acConvert;
  163.         opt.option |= opAddWT;
  164.         a = sscanf(optarg,"%li",&opt.addwt);
  165.         if ((a!=1) || (opt.addwt<0)) syserror(INVOPT,optarg);
  166.       break;
  167.       case 'r':
  168.         if (opt.action&(~acConvert)) syserror(MANYACT,c_str);
  169.         opt.action |= acConvert;
  170.         opt.option |= opRemovePause;
  171.       break;
  172.       case 't':
  173.         if (opt.option&opSelectTics) syserror(MANYARGS,c_str);
  174.         opt.option |= opSelectTics;
  175.         sep = (int)',';
  176.         pos_l = index(optarg,sep);
  177.         pos_r = rindex(optarg,sep);
  178.         if (pos_l == NULL) {
  179.           sep = (int)':';
  180.           pos_l=index(optarg,sep);
  181.           pos_r = rindex(optarg,sep);
  182.         }
  183.         if ((pos_l == NULL) || (pos_r!=pos_l)) syserror(INVOPT,optarg);
  184.         if (pos_l == optarg) {
  185.           opt.tic_start = 0;
  186.         } else {
  187.           *pos_l = '\0';
  188.           a = sscanf(optarg,"%li",&opt.tic_start);
  189.           if ((a!=1) || (opt.tic_start<0)) syserror(INVOPT,optarg);
  190.           *pos_l = (char)sep;
  191.         }
  192.         if (*(++pos_r) != '\0') {
  193.           a = sscanf(pos_r, "%li", &opt.tic_end);
  194.           if ((a!=1) || (opt.tic_end<opt.tic_start)) syserror(INVOPT,pos_r);
  195.         } else {
  196.           opt.tic_end = 0;
  197.         }
  198.       break;
  199.       case 'g':
  200.         if (opt.option&opDefineGame) syserror(MANYARGS,c_str);
  201.         opt.option |= opDefineGame;
  202.         for (a=0;a<strlen(optarg);a++) optarg[a]=toupper(optarg[a]);
  203.         if ((!strcmp(optarg,"DOOM")) || (!strcmp(optarg,"D"))) {
  204.           opt.game=(DOOM_old|DOOM_new);
  205.         }
  206.         else {
  207.           if ((!strcmp(optarg,"DOOM2")) || (!strcmp(optarg,"2"))) {
  208.             opt.game=DOOM2; 
  209.           }
  210.           else {
  211.             if ((!strcmp(optarg,"HERETIC")) || (!strcmp(optarg,"H"))) {
  212.               opt.game=HERETIC; 
  213.             }
  214.             else {
  215.               syserror(INVOPT, optarg);
  216.             }
  217.           }
  218.         }
  219.       break;
  220.       case '?':
  221.         exit(ILLOPT);
  222.       break;
  223.       default:
  224.         syserror(EINVAL, c_str);
  225.       break; 
  226.     }
  227.   }; 
  228.  
  229.   /* how many files ? */
  230.   argf = argc-optind;   /* number of files on the command line */
  231.   argvf_base = optind;  /* this is the first file */
  232.  
  233.   /* check the options */
  234.   /* without options means acInfo */
  235.   if (!opt.action) {
  236.     opt.action |= acInfo;
  237.     if (!argf) syntax();  /* without any actions and files */
  238.   }
  239.   /* --tic only with LMP2LS */
  240.   if ((opt.option&opSelectTics) && 
  241.       (opt.action&(~acLMP2LS))) 
  242.     syserror(ILLOPT,"--tic");
  243.   /* --game only with info, LMP2LS and convert */
  244.   if ((opt.option&opDefineGame) &&
  245.       (opt.action&(~(acInfo|acLMP2LS|acConvert)))) 
  246.     syserror(ILLOPT, "--game");
  247.  
  248.   /* convert MS-DOS filenames to lower case */
  249.   #ifdef __MSDOS__
  250.     for (i=0;i<argf;i++) { 
  251.       char *p;
  252.       for (p = argv[argvf_base+i]; *p; p++) *p = (char)tolower((int)*p);
  253.     }
  254.   #endif
  255.  
  256.   /* do the actions */
  257.   switch (opt.action) {
  258.     case acInfo:
  259.       if (argf<1) syserror(MISIFN, "command line");
  260.       for (i=0;i<argf;i++)
  261.         ActionInfo(argv[argvf_base+i], &opt);
  262.     break;
  263.     case acLMP2LS:
  264.       if (argf<1) syserror(MISIFN, "command line");
  265.       if (argf==1) syserror(MISOFN, "command line");
  266.       if (argf>2) syserror(MANYARGS, "command line");
  267.       ActionLMP2LS(argv[argvf_base], argv[argvf_base+1], &opt);
  268.     break;
  269.     case acLS2LMP:
  270.       if (argf<1) syserror(MISIFN, "command line");
  271.       if (argf==1) syserror(MISOFN, "command line");
  272.       /* argf >=2 */
  273.       for (i=0;i<argf-1;i++) { /* count the LS files */
  274.         /*
  275.            the first call has to init the LMP file,
  276.            the last one has to close it
  277.         */
  278.         ActionLS2LMP(argv[argvf_base+i], argv[argvf_base+argf-1],
  279.                        (i==0?LMP_INIT:0)|(i==argf-2?LMP_END:0)); 
  280.       }
  281.     break;
  282.     case acConvert:
  283.       if (argf<1) syserror(MISIFN, "command line");
  284.       if (argf>2) syserror(MANYARGS, "command line");
  285.       if (argf==1) 
  286.         ActionConvert(argv[argvf_base], argv[argvf_base], &opt);
  287.       else
  288.         ActionConvert(argv[argvf_base], argv[argvf_base+1], &opt);
  289.     break;
  290.   }
  291.  
  292.   return 0;
  293. }
  294.  
  295.  
  296. /******************************************************************************/
  297. /** Utility functions *********************************************************/
  298. /******************************************************************************/
  299.  
  300. void syntax(void)
  301. {
  302.   printf("LMP Control Center\n");
  303.   printf("LMPC (c) U. Girlich, 1994, 1995, Release %s %s\n", VERSION, DATE);
  304.   printf("lmpc [option ...] filename [filename ...]\n");
  305.   printf("-h, --help                   display this help and exit.\n");
  306.   printf("-V, --version                output version information and exit.\n");
  307.   printf("-i, --info                   prints out informations about the LMP-files.\n");
  308.   printf("-s, --lmp-to-ls              recompiles a LMP-file to a LS-file.\n");
  309.   printf("-l, --ls-to-lmp              compiles one or more LS-files to a LMP-file.\n");
  310.   printf("-v, --change-version VERSION changes the version of a LMP-file to VERSION\n");
  311.   printf("                             (0 means old DOOM).\n");
  312.   printf("-p, --change-player PLAYER   changes the recording player of a LMP-file to\n");
  313.   printf("                             PLAYER (0..3).\n");
  314.   printf("-w, --add-WT SECONDS         adds SECONDS WT game tics to the LMP file\n");
  315.   printf("                             (SECONDS must be integer).\n");
  316.   printf("-r, --remove-pause           remove the game tics between PS and PE.\n");
  317.   printf("-t, --tic FROM(,|:)TO        converts only a part of the LMP-file\n");
  318.   printf("                             (in connection with -s only).\n");
  319.   printf("-g, --game GAME              forces input game (GAME=DOOM, DOOM2 or HERETIC)\n");
  320.   printf("                             short: D,2,H (in connection with -(i|s|v|p|w|r)).\n");
  321.   exit(1);
  322. }
  323.  
  324.  
  325. void version(void)
  326. {
  327.   printf("lmpc %s, %s\n", VERSION, DATE);
  328.   exit(0);
  329. }
  330.  
  331.  
  332. /******************************************************************************/
  333. /** Actions *******************************************************************/
  334. /******************************************************************************/
  335.  
  336. void ActionInfo(char *filename, opt_t *opt)
  337. {
  338.   LMP_t l;
  339.   char buffer[10];
  340.  
  341.   LMP_init(&l,filename,"rb");
  342.   l.game = (opt->option&opDefineGame?opt->game:UNKNOWN);
  343.   LMP_readheader(&l); 
  344.   printf("%s: ",l.filename);
  345.   printf("%s %s ", l.gs, l.ns);
  346.   if (l.game==DOOM2)
  347.     printf("Map%02d", l.map); 
  348.   else
  349.     printf("E%dM%d", l.episode, l.map);
  350.   printf(" skill %d, ", l.skill+1);
  351.   if (l.playernum==1)
  352.     printf("single");
  353.   else {
  354.     printf("%d ", l.playernum);
  355.     if (l.game&(DOOM_new||DOOM2))
  356.       switch (l.multirule) {
  357.     case ruleCOOP:  printf("cooperative "); break;
  358.     case ruleDEATH: printf("deathmatch ");  break;
  359.     case ruleALT:   printf("altdeath ");    break;
  360.     default:   printf("unknown rule "); break;
  361.       }
  362.     printf("players"); 
  363.   }    
  364.   if (l.respawn) printf(", respawn ");
  365.   if (l.fast)    printf(", fast ");
  366.   if (l.nomonsters) printf(", nomonsters "); 
  367.   printf("\n");
  368.   if (l.playernum>1) printf("rec. by player %d, ", l.mainplayer);
  369.   printf("%li game tics, ", l.tics);
  370.   printf("%s.\n", Time2String(l.time,buffer));
  371.   LMP_done(&l);
  372. }
  373.  
  374.  
  375. void ActionLMP2LS(char *lmpfilename, char *lsfilename, opt_t *opt)
  376. {
  377.   LMP_t l;
  378.   LS_t s;
  379.   TIC_t t;
  380.   STAT_t GF[MAXPLAYER], GB[MAXPLAYER], 
  381.      SL[MAXPLAYER], SR[MAXPLAYER], 
  382.      TL[MAXPLAYER], TR[MAXPLAYER];
  383.   unsigned long wait_sum[MAXPLAYER];
  384.   char buffer[10];
  385.   unsigned char p;
  386.   int pause, empty_t, empty_c;
  387.   double time;
  388.   char ts[200];
  389.   char cs[200];
  390.   unsigned long tic;
  391.   unsigned char b;
  392.   int wb;
  393.   int KeyOld, KeyNew; 
  394.   int m;
  395.   
  396.   LMP_init(&l,lmpfilename,"rb");
  397.   l.game = (opt->option&opDefineGame?opt->game:UNKNOWN);
  398.   LMP_readheader(&l); 
  399.   LS_init(&s,lsfilename,"wb");
  400.   printf("%s -> %s\n", l.filename, s.filename);
  401.   wb=0;
  402.   switch (l.game) {
  403.     case HERETIC  : wb=16; break;
  404.     case DOOM_new : 
  405.     case DOOM_old : wb=0; break;
  406.     case DOOM2    : wb=8; break;
  407.     case DOOM_new|DOOM2 : wb=8; break;
  408.   }
  409.   fprintf(s.file,"# %s %.*s %s\n", l.gs, (int)(24-strlen(l.gs)), "LMP file:                ", l.filename);
  410.   fprintf(s.file,"# Number of players:        %d\n", l.playernum);
  411.   fprintf(s.file,"# Total play time:          %s\n", Time2String(l.time,buffer));
  412.   fprintf(s.file,"# Number of game tics:      %ld\n", l.tics);
  413.   fprintf(s.file,"\n");
  414.   fprintf(s.file,"HeaderStart\n");
  415.   fprintf(s.file," Game:         %s\n", l.gs);
  416.   if (l.game!=HERETIC) fprintf(s.file," Version:      %s\n", l.ns); 
  417.   fprintf(s.file," Skill:        %d\n", l.skill+1);
  418.   fprintf(s.file," Episode:      %d\n", l.episode);
  419.   fprintf(s.file," Map:          %d\n", l.map);
  420.   if (l.playernum>1) {
  421.     for (p=0;p<l.playernum;p++) {
  422.       fprintf(s.file," Player%d:      %d        # %s player\n",p,l.num[p],PlayerColor[l.num[p]]);
  423.     }
  424.   }
  425.   if (l.game&DOOM_new || l.game&DOOM2) {
  426.     if (l.playernum>1) {
  427.       fprintf(s.file," MultiRule:    ");
  428.       switch (l.multirule) {
  429.     case ruleCOOP : fprintf(s.file,"Cooperative")   ; break;
  430.     case ruleDEATH: fprintf(s.file,"DeathMeatch")   ; break;
  431.     case ruleALT  : fprintf(s.file,"AltDeath")      ; break;
  432.     default       : fprintf(s.file,"%d",l.multirule); break;
  433.       }
  434.       fprintf(s.file,"\n");
  435.     }
  436.     if (l.respawn   !=0) fprintf(s.file," Respawn:      %d\n", l.respawn);
  437.     if (l.fast      !=0) fprintf(s.file," Fast:         %d\n", l.fast);
  438.     if (l.nomonsters!=0) fprintf(s.file," NoMonsters:   %d\n", l.nomonsters);
  439.     if (l.playernum>1 || (l.playernum==1 && l.mainplayer!=0)) 
  440.              fprintf(s.file, "ViewOfPlayer: %d\n", l.mainplayer); 
  441.   }
  442.   fprintf(s.file,"HeaderEnd\n");
  443.   fprintf(s.file,"\n");
  444.   fprintf(s.file,"DataStart\n");
  445.   
  446.   for (p=0;p<l.playernum;p++) {
  447.     wait_sum[p] = 0;
  448.     STAT_init(&GF[p],"GF", 2);
  449.     STAT_init(&GB[p],"GB", 2);
  450.     STAT_init(&SL[p],"SL", 2);
  451.     STAT_init(&SR[p],"SR", 2);
  452.     STAT_init(&TL[p],"TL", 3);
  453.     STAT_init(&TR[p],"TR", 3);
  454.   }
  455.   
  456.   if (opt->tic_start==0) opt->tic_start=1;
  457.   if (opt->tic_end==0) opt->tic_end=l.tics;
  458.   pause=FALSE;
  459.   for (tic=1;tic<=l.tics;tic++) {
  460.     time=tic*TICTIME;
  461.     for (p=0;p<l.playernum;p++) {
  462.       LMP_getgametic(&l,&t);
  463.       strcpy(ts,"");
  464.       strcpy(cs,"");
  465.       empty_t=TRUE;
  466.       empty_c=TRUE;
  467.       if (t.go!=0) {
  468.     if (!empty_t) strcat(ts," ");
  469.     if (t.go<=0x7F) {
  470.       sprintf(ts+strlen(ts),"GF%d",t.go);
  471.       GF[p].hist[t.go]++;
  472.     } 
  473.     if (0x81<=t.go) {
  474.       sprintf(ts+strlen(ts),"GB%d",256-t.go);
  475.       GB[p].hist[256-t.go]++;
  476.     } 
  477.     if (t.go==0x80) {
  478.       sprintf(ts+strlen(ts),"G0x%02x",t.go);
  479.       if (!empty_c) strcat(cs," ");
  480.       strcat(cs,"Unknown Go");
  481.       empty_c=FALSE;
  482.     }
  483.     empty_t=FALSE; 
  484.       }
  485.       if (t.strafe!=0) {
  486.     if (!empty_t) strcat(ts," ");
  487.     if (t.strafe<=0x7F) {
  488.       sprintf(ts+strlen(ts),"SR%d",t.strafe);
  489.       SR[p].hist[t.strafe]++;
  490.     }
  491.     if (0x81<=t.strafe) { 
  492.       sprintf(ts+strlen(ts),"SL%d",256-t.strafe);
  493.       SL[p].hist[256-t.strafe]++;
  494.     }
  495.     if (t.strafe==0x80) {
  496.       sprintf(ts+strlen(ts),"S0x%02x",t.strafe);
  497.       if (!empty_c) strcat(cs," ");
  498.       strcat(cs,"Unknown Strafe");
  499.       empty_c=FALSE;
  500.     }
  501.     empty_t=FALSE;
  502.       }
  503.       if (t.turn!=0) {
  504.     if (!empty_t) strcat(ts," ");
  505.     if (t.turn<=0x7F) {
  506.       sprintf(ts+strlen(ts),"TL%d",t.turn);
  507.       TL[p].hist[t.turn]++;
  508.     }
  509.     if (0x81<=t.turn) {
  510.       sprintf(ts+strlen(ts),"TR%d",256-t.turn);
  511.       TR[p].hist[256-t.turn]++;
  512.     } 
  513.     if (t.turn==0x80) {
  514.       sprintf(ts+strlen(ts),"T0x%02x",t.turn);
  515.       if (!empty_c) strcat(cs," ");
  516.       strcat(cs,"Unknown Turn");
  517.       empty_c=FALSE;
  518.     }
  519.     empty_t=FALSE;
  520.       }
  521.       if (t.use!=0) {
  522.     if (!empty_t) strcat(ts," ");
  523.     if (t.use & 0x80) {
  524.       t.use ^= 0x80;
  525.       if (t.use==0x01) {
  526.         if (pause) {
  527.           strcat(ts,"PE");
  528.           pause=FALSE;
  529.         }
  530.         else {
  531.           strcat(ts,"PS");
  532.           pause=TRUE;
  533.         }
  534.       } /* t.use==0x01 */
  535.       else if ((t.use & 0x03) == 0x02) {
  536.         sprintf(ts+strlen(ts),"SG%d",(t.use>>2) & 0x07);
  537.       }
  538.       else {
  539.         sprintf(ts+strlen(ts),"U0x%02x",t.use | 0x80);
  540.         if (!empty_c) strcat(cs," ");
  541.         strcat(cs,"Unknown Use");
  542.         empty_c=FALSE;
  543.       }
  544.     } /* t.use & 0x80 */
  545.     else {
  546.       switch (t.use & 0x03) {
  547.         case 0x01: strcat(ts,"FW ");    break;
  548.         case 0x02: strcat(ts,"UT ");    break;
  549.         case 0x03: strcat(ts,"FW UT "); break;
  550.       }
  551.       if (t.use & 0x04) {
  552.         b = t.use >> 3;
  553.         if (0x07<b) {
  554.           sprintf(ts+strlen(ts),"U0x%02x",t.use);
  555.           if (!empty_c) strcat(cs," ");
  556.           strcat(cs,"Unknown Use");
  557.           empty_c=FALSE;
  558.         }
  559.         else {  
  560.           sprintf(ts+strlen(ts),"NW%d",b+1);
  561.           if (!empty_c) strcat(cs," ");
  562.           strcat(cs,WeaponName[wb+b]);
  563.           empty_c=FALSE;
  564.         }
  565.       }
  566.       else {
  567.         if ((t.use & (~0x03)) !=0) {
  568.           sprintf(ts+strlen(ts),"U0x%02x",t.use);
  569.           if (!empty_c) strcat(cs," ");
  570.           strcat(cs,"Unknown Use");
  571.           empty_c=FALSE;
  572.         }
  573.       }
  574.     }
  575.     empty_t=FALSE;
  576.       }
  577.       if (l.game==HERETIC && t.fl!=0) {
  578.     b=t.fl & 0x0F;
  579.     if (b!=0) {
  580.       if (!empty_t) strcat(ts," ");
  581.       if (b<=0x07) {
  582.         sprintf(ts+strlen(ts),"LU%d",b);
  583.       }
  584.       if (b>=0x09) {
  585.         sprintf(ts+strlen(ts),"LD%d",16-b);
  586.       }
  587.       if (b==0x08) {
  588.         strcat(ts,"LC");
  589.       }
  590.       empty_t=FALSE;
  591.     } 
  592.     b=t.fl >> 4;
  593.     if (b!=0) {
  594.       if (!empty_t) strcat(ts," ");
  595.       if (b<=0x07) {
  596.         sprintf(ts+strlen(ts),"FU%d",b);
  597.       }
  598.       if (b>=0x09) {
  599.         sprintf(ts+strlen(ts),"FD%d",16-b);
  600.       }
  601.       if (b==0x08) {
  602.         strcat(ts,"FC");
  603.       }
  604.       empty_t=FALSE;
  605.     } 
  606.       }
  607.       if (l.game==HERETIC && t.art!=0) {
  608.     if (!empty_t) strcat(ts," ");
  609.     if (t.art<=10) {
  610.       sprintf(ts+strlen(ts),"AT%c", t.art-1+'a');
  611.       if (!empty_c) strcat(cs," ");
  612.       sprintf(cs+strlen(cs),"%s",ArtifactName[t.art-1]);
  613.       empty_c=FALSE; 
  614.     }
  615.     if (11<=t.art) {
  616.       sprintf(ts+strlen(ts),"A0x%02x",t.art); 
  617.       if (!empty_c) strcat(cs," ");
  618.       strcat(cs,"Unknown Artifact");
  619.       empty_c=FALSE; 
  620.     } 
  621.     empty_t=FALSE;
  622.       }
  623.       if (empty_t) {
  624.     strcat(ts,"WT");
  625.     wait_sum[p]++;
  626.       }
  627.       if ((tic>=opt->tic_start) && (tic<=opt->tic_end)) {
  628.         if (p==0) {
  629.        fprintf(s.file,"%s%.*s# %5ld (%s) %s\n", ts, (int)(24-strlen(ts)), "                        ", tic, Time2String(time,buffer), cs);
  630.         } 
  631.         else {
  632.           fprintf(s.file,"%s%.*s# %s\n", ts, (int)(24-strlen(ts)), "                        ", cs);
  633.         }
  634.       }
  635.     }
  636.   }
  637.   fprintf(s.file,"DataEnd\n");
  638.   if (l.tics>0) {
  639.     m=0;
  640.     for(p=0;p<l.playernum;p++) {
  641.       STAT_calc(&GF[p]);
  642.       STAT_calc(&GB[p]);
  643.       STAT_calc(&SL[p]);
  644.       STAT_calc(&SR[p]);
  645.       STAT_calc(&TL[p]);
  646.       STAT_calc(&TR[p]);
  647.       fprintf(s.file,"\n# Statistics for player %d\n", p);
  648.       if (TL[p].control==C_KEY && TR[p].control==C_KEY) {
  649.     KeyOld=STAT_turncheck(&TL[p],1,2,5) && STAT_turncheck(&TR[p],2,3,5);
  650.     KeyNew=STAT_turncheck(&TL[p],1,3,5) && STAT_turncheck(&TR[p],1,2,5);
  651.     /* the following code isn't totally save. What happens, if 
  652.        KeyOld and KeyNew are both true ? */
  653.     if (!KeyOld && !KeyNew) 
  654.       TL[p].control=C_MOUSE;
  655.     else 
  656.       if (KeyOld)
  657.         TL[p].control=C_KEY_OLD;
  658.       else
  659.        TL[p].control=C_KEY_NEW;
  660.     TR[p].control=TL[p].control;
  661.       }
  662.       STAT_writehist(&GF[p],cs); if (strcmp(cs,"")!=0) fprintf(s.file,"# %s\n",cs);
  663.       STAT_writehist(&GB[p],cs); if (strcmp(cs,"")!=0) fprintf(s.file,"# %s\n",cs);
  664.       STAT_writehist(&SL[p],cs); if (strcmp(cs,"")!=0) fprintf(s.file,"# %s\n",cs);
  665.       STAT_writehist(&SR[p],cs); if (strcmp(cs,"")!=0) fprintf(s.file,"# %s\n",cs);
  666.       STAT_writehist(&TL[p],cs); if (strcmp(cs,"")!=0) fprintf(s.file,"# %s\n",cs);
  667.       STAT_writehist(&TR[p],cs); if (strcmp(cs,"")!=0) fprintf(s.file,"# %s\n",cs);
  668.       if (    GF[p].control==C_KEY && GB[p].control==C_KEY
  669.        && SL[p].control==C_KEY && SR[p].control==C_KEY
  670.        && (TL[p].control & C_KEY)
  671.        && (TR[p].control & C_KEY)
  672.      ) {
  673.     fprintf(s.file,"# This player plays with keyboard/joystick only. Give him a mouse.\n");
  674.       } 
  675.       if (SR[p].sum+SL[p].sum==0) {
  676.     fprintf(s.file,"# This player plays without STRAFE. Show him the README.\n");
  677.       }
  678.       fprintf(s.file,"# %lu * WT in %lu tics (%.1f%%)\n",wait_sum[p],l.tics,100.0*wait_sum[p]/l.tics);
  679.       if (TL[p].control==C_KEY_OLD && (l.game&DOOM_new || l.game&DOOM2)) m=OLD_NEW;
  680.       if (TL[p].control==C_KEY_NEW && l.game==DOOM_old) m=NEW_OLD; 
  681.     }
  682.     if (m==NEW_OLD) fprintf(s.file,"# This LMP was originally recorded with an old version (<1.4)\n");
  683.     if (m==OLD_NEW) fprintf(s.file,"# This LMP was originally recorded with a new version (>=1.4)\n");
  684.   }
  685.   LMP_done(&l);
  686.   LS_done(&s);
  687. }
  688.  
  689.  
  690. #define MAXLINELENGTH 200
  691.  
  692. void ActionLS2LMP(char *lsfilename, char *lmpfilename, int action)
  693. {
  694.   static LMP_t l;
  695.   LS_t s;
  696.   TIC_t t;
  697.   int state;
  698.   unsigned long linenumber;
  699.   char lsline[MAXLINELENGTH];
  700.   char *gt, *temp, *res, *token, *value;
  701.   int i, pause;
  702.   int notdecoded, numberused;
  703.   long number;
  704.   unsigned long repeatcounter;
  705.  
  706.   LS_init(&s,lsfilename,"rb");
  707.   if (action&LMP_INIT) LMP_init(&l,lmpfilename,"wb");
  708.   printf("%s ", s.filename);
  709.  
  710.   state=HEADER_START;
  711.   linenumber=0;
  712.   pause=FALSE;
  713.   while (fgets(lsline,MAXLINELENGTH,s.file)==lsline) {
  714.     linenumber++;
  715.     if (lsline[strlen(lsline)-1]!='\n') {
  716.       syntaxerror(linenumber,"line too long");
  717.     }
  718.     gt=lsline;
  719.     temp=strchr(gt,'#');
  720.     if (temp!=NULL) *temp='\0';
  721.     for (i=0;i<strlen(gt);i++) gt[i]=toupper(gt[i]);
  722.     gt=delspaces(gt);
  723.     if (strlen(gt)>0) switch (state) {
  724.       case HEADER_START:
  725.     l.game=UNKNOWN;
  726.     l.versionbyte=0;
  727.     l.skill=0;
  728.     l.episode=0;
  729.     l.map=0;
  730.     l.multirule=0;
  731.     l.respawn=0;
  732.     l.fast=0;
  733.     l.nomonsters=0;
  734.     l.playernum=1;
  735.     l.mainplayer=0;
  736.     for (i=0;i<MAXPLAYER;i++) l.num[i]=0; 
  737.     if (strcmp(gt,"HEADERSTART")) syntaxerror(linenumber,"HeaderStart expected");
  738.     state=HEADER;
  739.       break; /* end HEADER_START */
  740.       case HEADER:
  741.     if (strcmp(gt,"HEADEREND")==0)
  742.       state=HEADER_END;
  743.     else {
  744.       temp=strchr(gt,':');
  745.       if (temp==NULL) syntaxerror(linenumber,"a colon separates token and value in the header");
  746.       if (temp==gt) syntaxerror(linenumber,"token expected");
  747.       if (temp==gt+strlen(gt)-1) syntaxerror(linenumber,"value expected");
  748.       *temp='\0';
  749.       token=gt; 
  750.       token=delspaces(token);
  751.       value=temp+1;
  752.       value=delspaces(value);
  753.       notdecoded=TRUE;
  754.       numberused=FALSE;
  755.       number=strtol(value,&res,0);
  756.       if (notdecoded && strcmp(token,"GAME")==0) {
  757.         if (notdecoded && strcmp(value,"HERETIC")==0) {
  758.           l.game=HERETIC;
  759.           numberused=FALSE;
  760.           notdecoded=FALSE;
  761.         } 
  762.         if (notdecoded && strcmp(value,"DOOM")==0) {
  763.           l.game=DOOM_old|DOOM_new;
  764.           numberused=FALSE;
  765.           notdecoded=FALSE;
  766.         } 
  767.         if (notdecoded && strcmp(value,"DOOM ][")==0) {
  768.           l.game=DOOM2;
  769.           numberused=FALSE;
  770.           notdecoded=FALSE;
  771.         } 
  772.         if (notdecoded && strcmp(value,"DOOM OR DOOM ][")==0) {
  773.           l.game=DOOM_new|DOOM2;
  774.           numberused=FALSE;
  775.           notdecoded=FALSE;
  776.         } 
  777.       }
  778.       if (notdecoded && strcmp(token,"VERSION")==0) {
  779.             l.versionbyte=strtoversionbyte(value);
  780.         numberused=FALSE;
  781.         notdecoded=FALSE;
  782.       } 
  783.       if (notdecoded && strcmp(token,"SKILL")==0) {
  784.         l.skill=number-1;
  785.         numberused=TRUE;
  786.         notdecoded=FALSE;
  787.       }
  788.       if (notdecoded && strcmp(token,"EPISODE")==0) {
  789.         l.episode=number;
  790.         numberused=TRUE;
  791.         notdecoded=FALSE;
  792.       }
  793.       if (notdecoded && strcmp(token,"MAP")==0) {
  794.         l.map=number;
  795.         numberused=TRUE;
  796.         notdecoded=FALSE;
  797.       }
  798.       if (notdecoded && strcmp(token,"PLAYER0")==0) {
  799.         l.num[0]=number;
  800.         if (l.playernum<1) l.playernum=1;
  801.         numberused=TRUE;
  802.         notdecoded=FALSE;
  803.       }
  804.       if (notdecoded && strcmp(token,"PLAYER1")==0) {
  805.         l.num[1]=number;
  806.         if (l.playernum<2) l.playernum=2;
  807.         numberused=TRUE;
  808.         notdecoded=FALSE;
  809.       }
  810.       if (notdecoded && strcmp(token,"PLAYER2")==0) {
  811.         l.num[2]=number;
  812.         if (l.playernum<3) l.playernum=3;
  813.         numberused=TRUE;
  814.         notdecoded=FALSE;
  815.       }
  816.       if (notdecoded && strcmp(token,"PLAYER3")==0) {
  817.         l.num[3]=number;
  818.         if (l.playernum<4) l.playernum=4;
  819.         numberused=TRUE;
  820.         notdecoded=FALSE;
  821.       }
  822.       if (notdecoded && strcmp(token,"MULTIRULE")==0) {
  823.         if (notdecoded && strcmp(value,"COOPERATIVE")==0) {
  824.           l.multirule=ruleCOOP;
  825.           numberused=FALSE;
  826.           notdecoded=FALSE;
  827.         }
  828.         if (notdecoded && strcmp(value,"DEATHMATCH")==0) {
  829.           l.multirule=ruleDEATH;
  830.           numberused=FALSE;
  831.           notdecoded=FALSE;
  832.         }
  833.         if (notdecoded && strcmp(value,"ALTDEATH")==0) {
  834.           l.multirule=ruleALT;
  835.           numberused=FALSE;
  836.           notdecoded=FALSE;
  837.         }
  838.         if (notdecoded) { 
  839.           l.multirule=number;
  840.           numberused=TRUE;
  841.           notdecoded=FALSE;
  842.         }
  843.       }
  844.       if (notdecoded && strcmp(token,"RESPAWN")==0) {
  845.         l.respawn=number; 
  846.         numberused=TRUE;
  847.         notdecoded=FALSE;
  848.       }
  849.       if (notdecoded && strcmp(token,"FAST")==0) {
  850.         l.fast=number; 
  851.         numberused=TRUE;
  852.         notdecoded=FALSE;
  853.       }
  854.       if (notdecoded && strcmp(token,"NOMONSTERS")==0) {
  855.         l.nomonsters=number; 
  856.         numberused=TRUE;
  857.         notdecoded=FALSE;
  858.       }
  859.       if (notdecoded && strcmp(token,"VIEWOFPLAYER")==0) {
  860.         l.mainplayer=number; 
  861.         numberused=TRUE;
  862.         notdecoded=FALSE;
  863.       }
  864.       if (notdecoded) syntaxerror(linenumber,"token expected");
  865.       if (numberused && res[0]!='\0') syntaxerror(linenumber,"number expected");
  866.     }
  867.       break; /* end HEADER */
  868.       case HEADER_END:
  869.       case DATA_START:
  870.     if (l.game==UNKNOWN) syntaxerror(linenumber,"Game is not defined");
  871.     if (l.game==(DOOM_old|DOOM_new)) {
  872.       if (l.versionbyte==0) 
  873.         l.game=DOOM_old;
  874.       else
  875.         l.game=DOOM_new;
  876.     }
  877.     if (action&LMP_INIT) LMP_writeheader(&l);
  878.     l.ticsize=(l.game==HERETIC?LONG_TIC:SHORT_TIC);
  879.     state=DATA_START;
  880.     if (strcmp(gt,"DATASTART")) syntaxerror(linenumber,"DataStart expected");
  881.     state=DATA;
  882.       break;
  883.       case DATA:
  884.     if (strcmp(gt,"DATAEND")==0) {
  885.       state=DATA_END;
  886.       if (action&LMP_END) LMP_writequitbyte(&l);
  887.       state++;
  888.     }
  889.     else {
  890.       t.go=0;
  891.       t.strafe=0;
  892.       t.turn=0;
  893.       t.use=0;
  894.       if (l.game==HERETIC) {
  895.         t.fl=0;
  896.         t.art=0;
  897.       }
  898.       repeatcounter=1;
  899.       token=strtok(gt," ");
  900.       while (token!=NULL) {
  901.         notdecoded=TRUE;
  902.         if (notdecoded && strncmp(token,"*",1)==0) {
  903.           number=strtol(token+1,&res,0);
  904.           if (res[0]!='\0') syntaxerror(linenumber,"*number expected");
  905.           if (0<number) 
  906.         repeatcounter=number; 
  907.           else
  908.         syntaxerror(linenumber,"*number out of range");
  909.           notdecoded=FALSE;
  910.         }
  911.         if (notdecoded && strncmp(token,"GF",2)==0) {
  912.           number=strtol(token+2,&res,0);
  913.           if (res[0]!='\0') syntaxerror(linenumber,"GFnumber expected");
  914.           if (0<number && number<128)
  915.         t.go=number; 
  916.           else
  917.         syntaxerror(linenumber,"GFnumber out of range");
  918.           notdecoded=FALSE; 
  919.         }
  920.         if (notdecoded && strncmp(token,"GB",2)==0) {
  921.           number=strtol(token+2,&res,0);
  922.           if (res[0]!='\0') syntaxerror(linenumber,"GBnumber expected");
  923.           if (0<number && number<128)
  924.         t.go=256-number;
  925.           else
  926.         syntaxerror(linenumber,"GBnumber out of range");
  927.           notdecoded=FALSE; 
  928.         }
  929.         if (notdecoded && strncmp(token,"SR",2)==0) {
  930.           number=strtol(token+2,&res,0);
  931.           if (res[0]!='\0') syntaxerror(linenumber,"SRnumber expected");
  932.           if (0<number && number<128)
  933.         t.strafe=number; 
  934.           else
  935.         syntaxerror(linenumber,"SRnumber out of range");
  936.           notdecoded=FALSE; 
  937.         }
  938.         if (notdecoded && strncmp(token,"SL",2)==0) {
  939.           number=strtol(token+2,&res,0);
  940.           if (res[0]!='\0') syntaxerror(linenumber,"SLnumber expected");
  941.           if (0<number && number<128)
  942.         t.strafe=256-number;
  943.           else
  944.         syntaxerror(linenumber,"SLnumber out of range");
  945.           notdecoded=FALSE; 
  946.         }
  947.         if (notdecoded && strncmp(token,"TR",2)==0) {
  948.           number=strtol(token+2,&res,0);
  949.           if (res[0]!='\0') syntaxerror(linenumber,"TRnumber expected");
  950.           if (0<number && number<128) 
  951.         t.turn=256-number; 
  952.           else
  953.         syntaxerror(linenumber,"TRnumber out of range");
  954.           notdecoded=FALSE; 
  955.         }
  956.         if (notdecoded && strncmp(token,"TL",2)==0) {
  957.           number=strtol(token+2,&res,0);
  958.           if (res[0]!='\0') syntaxerror(linenumber,"TLnumber expected");
  959.           if (0<number && number<128)
  960.         t.turn=number;
  961.           else
  962.         syntaxerror(linenumber,"TLnumber out of range");
  963.           notdecoded=FALSE; 
  964.         }
  965.         if (notdecoded && strncmp(token,"PS",2)==0) {
  966.           if (strlen(token)>2) syntaxerror(linenumber,"PS expected");
  967.           if (pause) syntaxwarning(linenumber,"Pause is activ already");
  968.               pause=TRUE;
  969.           if (t.use!=0 && t.use!=0x81) syntaxerror(linenumber,"PS can''t be used with other use things");
  970.           t.use=0x81; 
  971.           notdecoded=FALSE; 
  972.         }
  973.         if (notdecoded && strncmp(token,"PE",2)==0) {
  974.           if (strlen(token)>2) syntaxerror(linenumber,"PE expected");
  975.           if (!pause) syntaxwarning(linenumber,"Pause is off already");
  976.               pause=FALSE;
  977.           if (t.use!=0 && t.use!=0x81) syntaxerror(linenumber,"PE can't be used with other use things");
  978.           t.use=0x81; 
  979.           notdecoded=FALSE; 
  980.         }
  981.         if (notdecoded && strncmp(token,"SG",2)==0) {
  982.           number=strtol(token+2,&res,0);
  983.           if (res[0]!='\0') syntaxerror(linenumber,"SGnumber expected");
  984.           if (0<=number && number<=7) {
  985.         if (t.use!=0) syntaxerror(linenumber,"SG can't be used with other use things");
  986.         t.use=0x82 | (number<<2);
  987.           }
  988.           else
  989.         syntaxerror(linenumber,"SGnumber out of range");
  990.           notdecoded=FALSE; 
  991.         }
  992.         if (notdecoded && strncmp(token,"FW",2)==0) {
  993.           if (strlen(token)>2) syntaxerror(linenumber,"FW expected");
  994.           if (t.use & 0x80) syntaxerror(linenumber,"FW can't be used with PS, PE and SG");
  995.           t.use |= 0x01;
  996.           notdecoded=FALSE; 
  997.         }
  998.         if (notdecoded && strncmp(token,"UT",2)==0) {
  999.           if (strlen(token)>2) syntaxerror(linenumber,"UT expected");
  1000.           if (t.use & 0x80) syntaxerror(linenumber,"UT can't be used with PS, PE and SG");
  1001.           t.use |= 0x02;
  1002.           notdecoded=FALSE; 
  1003.         }
  1004.         if (notdecoded && strncmp(token,"NW",2)==0) {
  1005.           number=strtol(token+2,&res,0);
  1006.           if (res[0]!='\0') syntaxerror(linenumber,"NWnumber expected");
  1007.           if (1<=number && number<=8) {
  1008.         if (t.use & 0x80) syntaxerror(linenumber,"NW can't be used with PS, PE and SG"); 
  1009.         t.use = (t.use & 0x03) | 0x04 | ((number-1)<<3);
  1010.           }
  1011.           else
  1012.         syntaxerror(linenumber,"NWnumber out of range");
  1013.           notdecoded=FALSE; 
  1014.         }
  1015.         if (notdecoded && strncmp(token,"WT",2)==0) {
  1016.           if (strlen(token)>2) syntaxerror(linenumber,"WT expected");
  1017.           notdecoded=FALSE;
  1018.         }
  1019.         if (l.game==HERETIC && notdecoded && strncmp(token,"LU",2)==0) {
  1020.           number=strtol(token+2,&res,0);
  1021.           if (res[0]!='\0') syntaxerror(linenumber,"LUnumber expected");
  1022.           if (0<number && number<16)
  1023.         t.fl=(t.fl & 0xF0) | number; 
  1024.           else
  1025.         syntaxerror(linenumber,"LUnumber out of range");
  1026.           notdecoded=FALSE; 
  1027.         }
  1028.         if (l.game==HERETIC && notdecoded && strncmp(token,"LD",2)==0) {
  1029.           number=strtol(token+2,&res,0);
  1030.           if (res[0]!='\0') syntaxerror(linenumber,"LDnumber expected");
  1031.           if (0<number && number<16)
  1032.         t.fl=(t.fl & 0xF0) | (16-number);
  1033.           else
  1034.         syntaxerror(linenumber,"LDnumber out of range");
  1035.           notdecoded=FALSE; 
  1036.         }
  1037.         if (l.game==HERETIC && notdecoded && strncmp(token,"LC",2)==0) {
  1038.           if (strlen(token)>2) syntaxerror(linenumber,"LC expected");
  1039.           t.fl=(t.fl & 0xF0) | 0x08; 
  1040.           notdecoded=FALSE; 
  1041.         }
  1042.         if (l.game==HERETIC && notdecoded && strncmp(token,"FU",2)==0) {
  1043.           number=strtol(token+2,&res,0);
  1044.           if (res[0]!='\0') syntaxerror(linenumber,"FUnumber expected");
  1045.           if (0<number && number<16)
  1046.         t.fl=(t.fl & 0x0F) | (number<<4); 
  1047.           else
  1048.         syntaxerror(linenumber,"FUnumber out of range");
  1049.           notdecoded=FALSE; 
  1050.         }
  1051.         if (l.game==HERETIC && notdecoded && strncmp(token,"FD",2)==0) {
  1052.           number=strtol(token+2,&res,0);
  1053.           if (res[0]!='\0') syntaxerror(linenumber,"FDnumber expected");
  1054.           if (0<number && number<16)
  1055.         t.fl=(t.fl & 0x0F) | ((16-number)<<4);
  1056.           else
  1057.         syntaxerror(linenumber,"FDnumber out of range");
  1058.           notdecoded=FALSE; 
  1059.         }
  1060.         if (l.game==HERETIC && notdecoded && strncmp(token,"FC",2)==0) {
  1061.           if (strlen(token)>2) syntaxerror(linenumber,"FC expected");
  1062.           t.fl=(t.fl & 0x0F) | 0x80; 
  1063.           notdecoded=FALSE; 
  1064.         }
  1065.         if (l.game==HERETIC && notdecoded && strncmp(token,"AT",2)==0) {
  1066.           if (strlen(token)!=3) syntaxerror(linenumber,"ATchar expected");
  1067.           number=token[2]-'A'+1; 
  1068.           if (1<=number && number<=10) 
  1069.         t.art=number;
  1070.           else
  1071.         syntaxerror(linenumber,"ATchar out of range");
  1072.           notdecoded=FALSE; 
  1073.         }
  1074.         if (notdecoded && strncmp(token,"G",1)==0) {
  1075.           number=strtol(token+1,&res,0);
  1076.           if (res[0]!='\0') syntaxerror(linenumber,"Gnumber expected");
  1077.           if (0<number && number<256) {
  1078.         if (t.go!=0) syntaxerror(linenumber,"Gnumber overwrites go-byte");
  1079.         t.go=number;
  1080.           }
  1081.           else
  1082.         syntaxerror(linenumber,"Gnumber out of range");
  1083.           notdecoded=FALSE; 
  1084.         }
  1085.         if (notdecoded && strncmp(token,"S",1)==0) {
  1086.           number=strtol(token+1,&res,0);
  1087.           if (res[0]!='\0') syntaxerror(linenumber,"Snumber expected");
  1088.           if (0<number && number<256) {
  1089.         if (t.strafe!=0) syntaxerror(linenumber,"Snumber overwrites strafe-byte");
  1090.         t.strafe=number;
  1091.           }
  1092.           else
  1093.         syntaxerror(linenumber,"Snumber out of range");
  1094.           notdecoded=FALSE; 
  1095.         }
  1096.         if (notdecoded && strncmp(token,"T",1)==0) {
  1097.           number=strtol(token+1,&res,0);
  1098.           if (res[0]!='\0') syntaxerror(linenumber,"Tnumber expected");
  1099.           if (0<number && number<256) {
  1100.         if (t.turn!=0) syntaxerror(linenumber,"Tnumber overwrites turn-byte");
  1101.         t.turn=number;
  1102.           }
  1103.           else
  1104.         syntaxerror(linenumber,"Tnumber out of range");
  1105.           notdecoded=FALSE; 
  1106.         }
  1107.         if (notdecoded && strncmp(token,"U",1)==0) {
  1108.           number=strtol(token+1,&res,0);
  1109.           if (res[0]!='\0') syntaxerror(linenumber,"Unumber expected");
  1110.           if (0<number && number<256) {
  1111.         if (t.use!=0) syntaxerror(linenumber,"Unumber overwrites use-byte");
  1112.         t.use=number;
  1113.           }
  1114.           else
  1115.         syntaxerror(linenumber,"Unumber out of range");
  1116.           notdecoded=FALSE; 
  1117.         }
  1118.         if (l.game==HERETIC && notdecoded && strncmp(token,"F",1)==0) {
  1119.           number=strtol(token+1,&res,0);
  1120.           if (res[0]!='\0') syntaxerror(linenumber,"Fnumber expected");
  1121.           if (0<number && number<256) {
  1122.         if (t.fl!=0) syntaxerror(linenumber,"Fnumber overwrites flight/look-byte");
  1123.         t.fl=number;
  1124.           }
  1125.           else
  1126.         syntaxerror(linenumber,"Fnumber out of range");
  1127.           notdecoded=FALSE; 
  1128.         }
  1129.         if (l.game==HERETIC && notdecoded && strncmp(token,"A",1)==0) {
  1130.           number=strtol(token+1,&res,0);
  1131.           if (res[0]!='\0') syntaxerror(linenumber,"Anumber expected");
  1132.           if (0<number && number<256) {
  1133.         if (t.art!=0) syntaxerror(linenumber,"Anumber overwrites use artifact-byte");
  1134.         t.art=number;
  1135.           }
  1136.           else
  1137.         syntaxerror(linenumber,"Anumber out of range");
  1138.           notdecoded=FALSE; 
  1139.         }
  1140.         if (notdecoded) syntaxerror(linenumber,"Data token expected");       
  1141.         token=strtok(NULL," ");
  1142.       }
  1143.       for (i=0;i<repeatcounter;i++) LMP_putgametic(&l, &t);
  1144.     }
  1145.       break;
  1146.       case DATA_END:
  1147.         /* ignore all the rest */
  1148.       break;
  1149.     } /* end switch (state) */
  1150.   } /* end while not end of file */
  1151.   LS_done(&s);
  1152.   if (action&LMP_END) {
  1153.     printf("-> %s\n", l.filename);
  1154.     LMP_done(&l); 
  1155.   }
  1156. }
  1157.  
  1158.  
  1159. void ActionConvert(char *infilename, char *outfilename, opt_t *opt)
  1160. {
  1161.   LMP_t li, lo;
  1162.   int NewFile, NewTics, NewHeader; 
  1163.   int o_game;
  1164.   char *gs, *o_version;
  1165.   long wttics=0, tic, ps=0;
  1166.   int p;
  1167.   TIC_t t[MAXPLAYER];
  1168.   TIC_t WT = {0,0,0,0,0,0};
  1169.   int pause=FALSE, allowput;
  1170.   #define TMP_FILE "lmpclmpc.tmp"
  1171.  
  1172.   LMP_init(&li, infilename, "rb");
  1173.   li.game = (opt->option&opDefineGame?opt->game:UNKNOWN);
  1174.   LMP_readheader(&li);
  1175.   printf("%s ", li.filename);
  1176.   NewFile=FALSE;
  1177.   NewTics=FALSE;
  1178.   NewHeader=FALSE;
  1179.   o_game=li.game;
  1180.   if (strcmp(infilename,outfilename)) NewFile=TRUE;
  1181.   if (opt->option&opVersion) {
  1182.     if (li.versionbyte==opt->versionbyte) {
  1183.       opt->option^=opVersion; /* nothing to do */
  1184.     }
  1185.     else {
  1186.       NewHeader=TRUE;
  1187.     }
  1188.     if (li.game==HERETIC) syserror(IMPVCH,li.filename);
  1189.     if (opt->versionbyte==0) {
  1190.       if (li.game==DOOM2) syserror(IMPVCH,li.filename);
  1191.       if (li.game&DOOM_new) {
  1192.         o_game=DOOM_old; 
  1193.         NewFile=TRUE;
  1194.       }
  1195.     }
  1196.     else {
  1197.       if (li.game==DOOM_old) {
  1198.         o_game=DOOM_new;
  1199.         NewFile=TRUE;
  1200.       }
  1201.     } 
  1202.     getversion(opt->versionbyte,&o_game,outfilename,&gs,&o_version); 
  1203.     printf("version %s -> %s ", li.ns, o_version);
  1204.   }
  1205.   if (opt->option&opViewPlayer) {
  1206.     if (li.game==HERETIC || li.game==DOOM_old) syserror(IMPVCH,li.filename);
  1207.     if (li.mainplayer==opt->mainplayer) {
  1208.       opt->option^=opViewPlayer; /* nothing to do */
  1209.     }
  1210.     else {
  1211.       NewHeader=TRUE;
  1212.     }
  1213.     printf("player %i -> %i ", li.mainplayer, opt->mainplayer);
  1214.   }
  1215.   if (opt->option&opAddWT) {
  1216.     if (opt->addwt==0) {
  1217.       opt->option^=opAddWT; /* nothing to do */
  1218.     }
  1219.     wttics = opt->addwt * 35 * li.playernum;   
  1220.     printf("+%lisec ", opt->addwt);
  1221.   }
  1222.   if (opt->option&opRemovePause) {
  1223.     NewFile=TRUE;
  1224.     NewTics=TRUE;
  1225.     pause = FALSE;
  1226.     ps = 0;
  1227.     printf("-PS -PE ");
  1228.   }
  1229.   printf("%s\n", outfilename);
  1230.   if (NewFile) {
  1231.     lo=li;
  1232.     LMP_init(&lo, TMP_FILE, "wb");
  1233.   }
  1234.   else {
  1235.     if (fclose(li.file)!=0) syserror(errno,li.filename);
  1236.     if ((li.file=fopen(li.filename, "r+b"))==NULL) syserror(errno,li.filename);
  1237.     lo=li;
  1238.   }
  1239.   lo.game=o_game;
  1240.   if (opt->option&opVersion) {
  1241.     lo.versionbyte=opt->versionbyte;
  1242.   }
  1243.   if (opt->option&opViewPlayer) {
  1244.     lo.mainplayer=opt->mainplayer;
  1245.   }
  1246.  
  1247.   /* header */
  1248.   if (NewHeader || NewFile) LMP_writeheader(&lo);
  1249.  
  1250.   /* game tics */
  1251.   if (NewFile) {
  1252.     if (NewTics) {
  1253.       allowput = TRUE;
  1254.       for (tic=1;tic<=li.tics;tic++) {
  1255.         for (p=0;p<li.playernum;p++) {
  1256.           LMP_getgametic(&li,&(t[p]));
  1257.         }
  1258.         if (opt->option&opRemovePause) {
  1259.           allowput = !pause;
  1260.           for (p=0;p<li.playernum;p++) {
  1261.             if (t[p].use==0x81) {
  1262.               if (pause) {
  1263.                 pause=FALSE; /* PE */
  1264.                 /* the PE game tic will not be stored */
  1265.                 printf(", PE at %lu (%lu tics removed)\n",tic, tic-ps);
  1266.               }
  1267.               else {
  1268.                 pause=TRUE; /* PS */
  1269.                 t[p].use=0;
  1270.                 /* the PS game will be stored (use=empty) */
  1271.                 printf("PS at %lu",tic);
  1272.                 ps=tic;
  1273.               }
  1274.               p=li.playernum; /* only one pause state change per tic */
  1275.             }
  1276.           }
  1277.         }
  1278.         if (allowput) for (p=0;p<li.playernum;p++) LMP_putgametic(&lo,&(t[p])); 
  1279.       }
  1280.     }
  1281.     else {
  1282.       copyopenfiles(li.file,lo.file);
  1283.       fseek(lo.file, -1, SEEK_END);  /* seek after the last tic */
  1284.     }
  1285.   }
  1286.   else {
  1287.     fseek(lo.file, -1, SEEK_END);    /* seek after the last tic */
  1288.   }
  1289.  
  1290.   if (opt->option&opAddWT) {
  1291.     for (tic=0;tic<wttics;tic++) LMP_putgametic(&lo, &WT);
  1292.   } 
  1293.   
  1294.   if (NewFile || (opt->option&opAddWT)) LMP_writequitbyte(&lo);
  1295.   LMP_done(&lo);
  1296.   if (NewFile) {
  1297.     LMP_done(&li);
  1298.     if (rename(TMP_FILE, outfilename)==-1) syserror(errno, outfilename);
  1299.   }
  1300. }
  1301.  
  1302. /*- file end lmpc.c ----------------------------------------------------------*/
  1303.