home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************\
- ; ;
- ; lmpc.c - projekt LMP control center ;
- ; main source code ;
- ; ;
- ; The program lmpc is a LMP conversion utility ;
- ; ;
- ; Uwe Girlich ;
- ; Erika-von-Brockdorff-Strasse 2 ;
- ; 04159 Leipzig ;
- ; Deutschland / Germany ;
- ; E-mail: girlich@aix520.informatik.uni-leipzig.de ;
- ; ;
- \****************************************************************************/
-
-
- #ifndef VERSION
- the version must be defined
- #endif
- #ifndef DATE
- the date must be defined
- #endif
-
- #include <ctype.h>
- #include <errno.h>
- #include <getopt.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include "ulmp.h"
- #include "tools.h"
-
- #define acInfo 0x01
- #define acLMP2LS 0x02
- #define acLS2LMP 0x04
- #define acConvert 0x08
-
- #define opVersion 0x01
- #define opViewPlayer 0x02
- #define opAddWT 0x04
- #define opRemovePause 0x08
- #define opSelectTics 0x10
- #define opDefineGame 0x20
-
- #define OLD_NEW 1
- #define NEW_OLD 2
-
- #define HEADER_START 0
- #define HEADER 1
- #define HEADER_END 2
- #define DATA_START 3
- #define DATA 4
- #define DATA_END 5
-
- #define LMP_INIT 1
- #define LMP_END 2
-
- typedef struct {
- unsigned char action;
- unsigned char option;
- unsigned char versionbyte;
- unsigned char mainplayer;
- long tic_start;
- long tic_end;
- long addwt;
- int game;
- } opt_t;
-
-
- /* prototypes */
- void syntax(void);
- void version(void);
- void ActionInfo(char *filename, opt_t *opt);
- void ActionLMP2LS(char *lmpfilename, char *lsfilename, opt_t *opt);
- void ActionLS2LMP(char *lsfilename, char *lmpfilename, int action);
- void ActionConvert(char *infilename, char *outfilename, opt_t *opt);
-
- int argf;
- int argvf_base;
-
- /******************************************************************************/
- /** Main program **************************************************************/
- /******************************************************************************/
-
- int main(int argc, char **argv)
- {
- int i;
- int c;
- char c_str[2]=" ";
- char *pos_r, *pos_l;
- int a;
- int sep;
- opt_t opt;
-
- static struct option long_options[] = {
- {"help", 0, 0, 'h'},
- {"version", 0, 0, 'V'},
- {"info", 0, 0, 'i'},
- {"ls-to-lmp", 0, 0, 'l'},
- {"lmp-to-ls", 0, 0, 's'},
- {"change-version", 1, 0, 'v'},
- {"change-player", 1, 0, 'p'},
- {"add-WT", 1, 0, 'w'},
- {"remove-pause", 0, 0, 'r'},
- {"tic", 1, 0, 't'},
- {"game", 1, 0, 'g'},
- {0, 0, 0, 0}
- };
- int option_index = 0;
-
- opt.action = 0;
- opt.option = 0;
- opt.game = UNKNOWN;
- opt.tic_start = 0;
- opt.tic_end = 0;
-
- /* scan the command line */
- while (1) {
- c = getopt_long(argc, argv, "hVilsv:p:w:rt:g:", long_options, &option_index);
-
- if (c==-1) break;
- *c_str = (char) c;
- switch (c) {
- case ':':
- syserror(ARGMIS,c_str);
- break;
- case 'h':
- syntax();
- break;
- case 'V':
- version();
- break;
- case 'i':
- if (opt.action) syserror(MANYACT,c_str);
- opt.action |= acInfo;
- break;
- case 'l':
- if (opt.action) syserror(MANYACT,c_str);
- opt.action = acLS2LMP;
- break;
- case 's':
- if (opt.action) syserror(MANYACT,c_str);
- opt.action = acLMP2LS;
- break;
- case 'v':
- if (opt.action&(~acConvert)) syserror(MANYACT,c_str);
- opt.action |= acConvert;
- opt.option |= opVersion;
- opt.versionbyte = strtoversionbyte(optarg);
- break;
- case 'p':
- if (opt.action&(~acConvert)) syserror(MANYACT,c_str);
- opt.action |= acConvert;
- opt.option |= opViewPlayer;
- a = sscanf(optarg,"%i",&i);
- opt.mainplayer = i % MAXPLAYER;
- if (a!=1) syserror(INVOPT, optarg);
- break;
- case 'w':
- if (opt.action&(~acConvert)) syserror(MANYACT,c_str);
- opt.action |= acConvert;
- opt.option |= opAddWT;
- a = sscanf(optarg,"%li",&opt.addwt);
- if ((a!=1) || (opt.addwt<0)) syserror(INVOPT,optarg);
- break;
- case 'r':
- if (opt.action&(~acConvert)) syserror(MANYACT,c_str);
- opt.action |= acConvert;
- opt.option |= opRemovePause;
- break;
- case 't':
- if (opt.option&opSelectTics) syserror(MANYARGS,c_str);
- opt.option |= opSelectTics;
- sep = (int)',';
- pos_l = index(optarg,sep);
- pos_r = rindex(optarg,sep);
- if (pos_l == NULL) {
- sep = (int)':';
- pos_l=index(optarg,sep);
- pos_r = rindex(optarg,sep);
- }
- if ((pos_l == NULL) || (pos_r!=pos_l)) syserror(INVOPT,optarg);
- if (pos_l == optarg) {
- opt.tic_start = 0;
- } else {
- *pos_l = '\0';
- a = sscanf(optarg,"%li",&opt.tic_start);
- if ((a!=1) || (opt.tic_start<0)) syserror(INVOPT,optarg);
- *pos_l = (char)sep;
- }
- if (*(++pos_r) != '\0') {
- a = sscanf(pos_r, "%li", &opt.tic_end);
- if ((a!=1) || (opt.tic_end<opt.tic_start)) syserror(INVOPT,pos_r);
- } else {
- opt.tic_end = 0;
- }
- break;
- case 'g':
- if (opt.option&opDefineGame) syserror(MANYARGS,c_str);
- opt.option |= opDefineGame;
- for (a=0;a<strlen(optarg);a++) optarg[a]=toupper(optarg[a]);
- if ((!strcmp(optarg,"DOOM")) || (!strcmp(optarg,"D"))) {
- opt.game=(DOOM_old|DOOM_new);
- }
- else {
- if ((!strcmp(optarg,"DOOM2")) || (!strcmp(optarg,"2"))) {
- opt.game=DOOM2;
- }
- else {
- if ((!strcmp(optarg,"HERETIC")) || (!strcmp(optarg,"H"))) {
- opt.game=HERETIC;
- }
- else {
- syserror(INVOPT, optarg);
- }
- }
- }
- break;
- case '?':
- exit(ILLOPT);
- break;
- default:
- syserror(EINVAL, c_str);
- break;
- }
- };
-
- /* how many files ? */
- argf = argc-optind; /* number of files on the command line */
- argvf_base = optind; /* this is the first file */
-
- /* check the options */
- /* without options means acInfo */
- if (!opt.action) {
- opt.action |= acInfo;
- if (!argf) syntax(); /* without any actions and files */
- }
- /* --tic only with LMP2LS */
- if ((opt.option&opSelectTics) &&
- (opt.action&(~acLMP2LS)))
- syserror(ILLOPT,"--tic");
- /* --game only with info, LMP2LS and convert */
- if ((opt.option&opDefineGame) &&
- (opt.action&(~(acInfo|acLMP2LS|acConvert))))
- syserror(ILLOPT, "--game");
-
- /* convert MS-DOS filenames to lower case */
- #ifdef __MSDOS__
- for (i=0;i<argf;i++) {
- char *p;
- for (p = argv[argvf_base+i]; *p; p++) *p = (char)tolower((int)*p);
- }
- #endif
-
- /* do the actions */
- switch (opt.action) {
- case acInfo:
- if (argf<1) syserror(MISIFN, "command line");
- for (i=0;i<argf;i++)
- ActionInfo(argv[argvf_base+i], &opt);
- break;
- case acLMP2LS:
- if (argf<1) syserror(MISIFN, "command line");
- if (argf==1) syserror(MISOFN, "command line");
- if (argf>2) syserror(MANYARGS, "command line");
- ActionLMP2LS(argv[argvf_base], argv[argvf_base+1], &opt);
- break;
- case acLS2LMP:
- if (argf<1) syserror(MISIFN, "command line");
- if (argf==1) syserror(MISOFN, "command line");
- /* argf >=2 */
- for (i=0;i<argf-1;i++) { /* count the LS files */
- /*
- the first call has to init the LMP file,
- the last one has to close it
- */
- ActionLS2LMP(argv[argvf_base+i], argv[argvf_base+argf-1],
- (i==0?LMP_INIT:0)|(i==argf-2?LMP_END:0));
- }
- break;
- case acConvert:
- if (argf<1) syserror(MISIFN, "command line");
- if (argf>2) syserror(MANYARGS, "command line");
- if (argf==1)
- ActionConvert(argv[argvf_base], argv[argvf_base], &opt);
- else
- ActionConvert(argv[argvf_base], argv[argvf_base+1], &opt);
- break;
- }
-
- return 0;
- }
-
-
- /******************************************************************************/
- /** Utility functions *********************************************************/
- /******************************************************************************/
-
- void syntax(void)
- {
- printf("LMP Control Center\n");
- printf("LMPC (c) U. Girlich, 1994, 1995, Release %s %s\n", VERSION, DATE);
- printf("lmpc [option ...] filename [filename ...]\n");
- printf("-h, --help display this help and exit.\n");
- printf("-V, --version output version information and exit.\n");
- printf("-i, --info prints out informations about the LMP-files.\n");
- printf("-s, --lmp-to-ls recompiles a LMP-file to a LS-file.\n");
- printf("-l, --ls-to-lmp compiles one or more LS-files to a LMP-file.\n");
- printf("-v, --change-version VERSION changes the version of a LMP-file to VERSION\n");
- printf(" (0 means old DOOM).\n");
- printf("-p, --change-player PLAYER changes the recording player of a LMP-file to\n");
- printf(" PLAYER (0..3).\n");
- printf("-w, --add-WT SECONDS adds SECONDS WT game tics to the LMP file\n");
- printf(" (SECONDS must be integer).\n");
- printf("-r, --remove-pause remove the game tics between PS and PE.\n");
- printf("-t, --tic FROM(,|:)TO converts only a part of the LMP-file\n");
- printf(" (in connection with -s only).\n");
- printf("-g, --game GAME forces input game (GAME=DOOM, DOOM2 or HERETIC)\n");
- printf(" short: D,2,H (in connection with -(i|s|v|p|w|r)).\n");
- exit(1);
- }
-
-
- void version(void)
- {
- printf("lmpc %s, %s\n", VERSION, DATE);
- exit(0);
- }
-
-
- /******************************************************************************/
- /** Actions *******************************************************************/
- /******************************************************************************/
-
- void ActionInfo(char *filename, opt_t *opt)
- {
- LMP_t l;
- char buffer[10];
-
- LMP_init(&l,filename,"rb");
- l.game = (opt->option&opDefineGame?opt->game:UNKNOWN);
- LMP_readheader(&l);
- printf("%s: ",l.filename);
- printf("%s %s ", l.gs, l.ns);
- if (l.game==DOOM2)
- printf("Map%02d", l.map);
- else
- printf("E%dM%d", l.episode, l.map);
- printf(" skill %d, ", l.skill+1);
- if (l.playernum==1)
- printf("single");
- else {
- printf("%d ", l.playernum);
- if (l.game&(DOOM_new||DOOM2))
- switch (l.multirule) {
- case ruleCOOP: printf("cooperative "); break;
- case ruleDEATH: printf("deathmatch "); break;
- case ruleALT: printf("altdeath "); break;
- default: printf("unknown rule "); break;
- }
- printf("players");
- }
- if (l.respawn) printf(", respawn ");
- if (l.fast) printf(", fast ");
- if (l.nomonsters) printf(", nomonsters ");
- printf("\n");
- if (l.playernum>1) printf("rec. by player %d, ", l.mainplayer);
- printf("%li game tics, ", l.tics);
- printf("%s.\n", Time2String(l.time,buffer));
- LMP_done(&l);
- }
-
-
- void ActionLMP2LS(char *lmpfilename, char *lsfilename, opt_t *opt)
- {
- LMP_t l;
- LS_t s;
- TIC_t t;
- STAT_t GF[MAXPLAYER], GB[MAXPLAYER],
- SL[MAXPLAYER], SR[MAXPLAYER],
- TL[MAXPLAYER], TR[MAXPLAYER];
- unsigned long wait_sum[MAXPLAYER];
- char buffer[10];
- unsigned char p;
- int pause, empty_t, empty_c;
- double time;
- char ts[200];
- char cs[200];
- unsigned long tic;
- unsigned char b;
- int wb;
- int KeyOld, KeyNew;
- int m;
-
- LMP_init(&l,lmpfilename,"rb");
- l.game = (opt->option&opDefineGame?opt->game:UNKNOWN);
- LMP_readheader(&l);
- LS_init(&s,lsfilename,"wb");
- printf("%s -> %s\n", l.filename, s.filename);
- wb=0;
- switch (l.game) {
- case HERETIC : wb=16; break;
- case DOOM_new :
- case DOOM_old : wb=0; break;
- case DOOM2 : wb=8; break;
- case DOOM_new|DOOM2 : wb=8; break;
- }
- fprintf(s.file,"# %s %.*s %s\n", l.gs, (int)(24-strlen(l.gs)), "LMP file: ", l.filename);
- fprintf(s.file,"# Number of players: %d\n", l.playernum);
- fprintf(s.file,"# Total play time: %s\n", Time2String(l.time,buffer));
- fprintf(s.file,"# Number of game tics: %ld\n", l.tics);
- fprintf(s.file,"\n");
- fprintf(s.file,"HeaderStart\n");
- fprintf(s.file," Game: %s\n", l.gs);
- if (l.game!=HERETIC) fprintf(s.file," Version: %s\n", l.ns);
- fprintf(s.file," Skill: %d\n", l.skill+1);
- fprintf(s.file," Episode: %d\n", l.episode);
- fprintf(s.file," Map: %d\n", l.map);
- if (l.playernum>1) {
- for (p=0;p<l.playernum;p++) {
- fprintf(s.file," Player%d: %d # %s player\n",p,l.num[p],PlayerColor[l.num[p]]);
- }
- }
- if (l.game&DOOM_new || l.game&DOOM2) {
- if (l.playernum>1) {
- fprintf(s.file," MultiRule: ");
- switch (l.multirule) {
- case ruleCOOP : fprintf(s.file,"Cooperative") ; break;
- case ruleDEATH: fprintf(s.file,"DeathMeatch") ; break;
- case ruleALT : fprintf(s.file,"AltDeath") ; break;
- default : fprintf(s.file,"%d",l.multirule); break;
- }
- fprintf(s.file,"\n");
- }
- if (l.respawn !=0) fprintf(s.file," Respawn: %d\n", l.respawn);
- if (l.fast !=0) fprintf(s.file," Fast: %d\n", l.fast);
- if (l.nomonsters!=0) fprintf(s.file," NoMonsters: %d\n", l.nomonsters);
- if (l.playernum>1 || (l.playernum==1 && l.mainplayer!=0))
- fprintf(s.file, "ViewOfPlayer: %d\n", l.mainplayer);
- }
- fprintf(s.file,"HeaderEnd\n");
- fprintf(s.file,"\n");
- fprintf(s.file,"DataStart\n");
-
- for (p=0;p<l.playernum;p++) {
- wait_sum[p] = 0;
- STAT_init(&GF[p],"GF", 2);
- STAT_init(&GB[p],"GB", 2);
- STAT_init(&SL[p],"SL", 2);
- STAT_init(&SR[p],"SR", 2);
- STAT_init(&TL[p],"TL", 3);
- STAT_init(&TR[p],"TR", 3);
- }
-
- if (opt->tic_start==0) opt->tic_start=1;
- if (opt->tic_end==0) opt->tic_end=l.tics;
- pause=FALSE;
- for (tic=1;tic<=l.tics;tic++) {
- time=tic*TICTIME;
- for (p=0;p<l.playernum;p++) {
- LMP_getgametic(&l,&t);
- strcpy(ts,"");
- strcpy(cs,"");
- empty_t=TRUE;
- empty_c=TRUE;
- if (t.go!=0) {
- if (!empty_t) strcat(ts," ");
- if (t.go<=0x7F) {
- sprintf(ts+strlen(ts),"GF%d",t.go);
- GF[p].hist[t.go]++;
- }
- if (0x81<=t.go) {
- sprintf(ts+strlen(ts),"GB%d",256-t.go);
- GB[p].hist[256-t.go]++;
- }
- if (t.go==0x80) {
- sprintf(ts+strlen(ts),"G0x%02x",t.go);
- if (!empty_c) strcat(cs," ");
- strcat(cs,"Unknown Go");
- empty_c=FALSE;
- }
- empty_t=FALSE;
- }
- if (t.strafe!=0) {
- if (!empty_t) strcat(ts," ");
- if (t.strafe<=0x7F) {
- sprintf(ts+strlen(ts),"SR%d",t.strafe);
- SR[p].hist[t.strafe]++;
- }
- if (0x81<=t.strafe) {
- sprintf(ts+strlen(ts),"SL%d",256-t.strafe);
- SL[p].hist[256-t.strafe]++;
- }
- if (t.strafe==0x80) {
- sprintf(ts+strlen(ts),"S0x%02x",t.strafe);
- if (!empty_c) strcat(cs," ");
- strcat(cs,"Unknown Strafe");
- empty_c=FALSE;
- }
- empty_t=FALSE;
- }
- if (t.turn!=0) {
- if (!empty_t) strcat(ts," ");
- if (t.turn<=0x7F) {
- sprintf(ts+strlen(ts),"TL%d",t.turn);
- TL[p].hist[t.turn]++;
- }
- if (0x81<=t.turn) {
- sprintf(ts+strlen(ts),"TR%d",256-t.turn);
- TR[p].hist[256-t.turn]++;
- }
- if (t.turn==0x80) {
- sprintf(ts+strlen(ts),"T0x%02x",t.turn);
- if (!empty_c) strcat(cs," ");
- strcat(cs,"Unknown Turn");
- empty_c=FALSE;
- }
- empty_t=FALSE;
- }
- if (t.use!=0) {
- if (!empty_t) strcat(ts," ");
- if (t.use & 0x80) {
- t.use ^= 0x80;
- if (t.use==0x01) {
- if (pause) {
- strcat(ts,"PE");
- pause=FALSE;
- }
- else {
- strcat(ts,"PS");
- pause=TRUE;
- }
- } /* t.use==0x01 */
- else if ((t.use & 0x03) == 0x02) {
- sprintf(ts+strlen(ts),"SG%d",(t.use>>2) & 0x07);
- }
- else {
- sprintf(ts+strlen(ts),"U0x%02x",t.use | 0x80);
- if (!empty_c) strcat(cs," ");
- strcat(cs,"Unknown Use");
- empty_c=FALSE;
- }
- } /* t.use & 0x80 */
- else {
- switch (t.use & 0x03) {
- case 0x01: strcat(ts,"FW "); break;
- case 0x02: strcat(ts,"UT "); break;
- case 0x03: strcat(ts,"FW UT "); break;
- }
- if (t.use & 0x04) {
- b = t.use >> 3;
- if (0x07<b) {
- sprintf(ts+strlen(ts),"U0x%02x",t.use);
- if (!empty_c) strcat(cs," ");
- strcat(cs,"Unknown Use");
- empty_c=FALSE;
- }
- else {
- sprintf(ts+strlen(ts),"NW%d",b+1);
- if (!empty_c) strcat(cs," ");
- strcat(cs,WeaponName[wb+b]);
- empty_c=FALSE;
- }
- }
- else {
- if ((t.use & (~0x03)) !=0) {
- sprintf(ts+strlen(ts),"U0x%02x",t.use);
- if (!empty_c) strcat(cs," ");
- strcat(cs,"Unknown Use");
- empty_c=FALSE;
- }
- }
- }
- empty_t=FALSE;
- }
- if (l.game==HERETIC && t.fl!=0) {
- b=t.fl & 0x0F;
- if (b!=0) {
- if (!empty_t) strcat(ts," ");
- if (b<=0x07) {
- sprintf(ts+strlen(ts),"LU%d",b);
- }
- if (b>=0x09) {
- sprintf(ts+strlen(ts),"LD%d",16-b);
- }
- if (b==0x08) {
- strcat(ts,"LC");
- }
- empty_t=FALSE;
- }
- b=t.fl >> 4;
- if (b!=0) {
- if (!empty_t) strcat(ts," ");
- if (b<=0x07) {
- sprintf(ts+strlen(ts),"FU%d",b);
- }
- if (b>=0x09) {
- sprintf(ts+strlen(ts),"FD%d",16-b);
- }
- if (b==0x08) {
- strcat(ts,"FC");
- }
- empty_t=FALSE;
- }
- }
- if (l.game==HERETIC && t.art!=0) {
- if (!empty_t) strcat(ts," ");
- if (t.art<=10) {
- sprintf(ts+strlen(ts),"AT%c", t.art-1+'a');
- if (!empty_c) strcat(cs," ");
- sprintf(cs+strlen(cs),"%s",ArtifactName[t.art-1]);
- empty_c=FALSE;
- }
- if (11<=t.art) {
- sprintf(ts+strlen(ts),"A0x%02x",t.art);
- if (!empty_c) strcat(cs," ");
- strcat(cs,"Unknown Artifact");
- empty_c=FALSE;
- }
- empty_t=FALSE;
- }
- if (empty_t) {
- strcat(ts,"WT");
- wait_sum[p]++;
- }
- if ((tic>=opt->tic_start) && (tic<=opt->tic_end)) {
- if (p==0) {
- fprintf(s.file,"%s%.*s# %5ld (%s) %s\n", ts, (int)(24-strlen(ts)), " ", tic, Time2String(time,buffer), cs);
- }
- else {
- fprintf(s.file,"%s%.*s# %s\n", ts, (int)(24-strlen(ts)), " ", cs);
- }
- }
- }
- }
- fprintf(s.file,"DataEnd\n");
- if (l.tics>0) {
- m=0;
- for(p=0;p<l.playernum;p++) {
- STAT_calc(&GF[p]);
- STAT_calc(&GB[p]);
- STAT_calc(&SL[p]);
- STAT_calc(&SR[p]);
- STAT_calc(&TL[p]);
- STAT_calc(&TR[p]);
- fprintf(s.file,"\n# Statistics for player %d\n", p);
- if (TL[p].control==C_KEY && TR[p].control==C_KEY) {
- KeyOld=STAT_turncheck(&TL[p],1,2,5) && STAT_turncheck(&TR[p],2,3,5);
- KeyNew=STAT_turncheck(&TL[p],1,3,5) && STAT_turncheck(&TR[p],1,2,5);
- /* the following code isn't totally save. What happens, if
- KeyOld and KeyNew are both true ? */
- if (!KeyOld && !KeyNew)
- TL[p].control=C_MOUSE;
- else
- if (KeyOld)
- TL[p].control=C_KEY_OLD;
- else
- TL[p].control=C_KEY_NEW;
- TR[p].control=TL[p].control;
- }
- STAT_writehist(&GF[p],cs); if (strcmp(cs,"")!=0) fprintf(s.file,"# %s\n",cs);
- STAT_writehist(&GB[p],cs); if (strcmp(cs,"")!=0) fprintf(s.file,"# %s\n",cs);
- STAT_writehist(&SL[p],cs); if (strcmp(cs,"")!=0) fprintf(s.file,"# %s\n",cs);
- STAT_writehist(&SR[p],cs); if (strcmp(cs,"")!=0) fprintf(s.file,"# %s\n",cs);
- STAT_writehist(&TL[p],cs); if (strcmp(cs,"")!=0) fprintf(s.file,"# %s\n",cs);
- STAT_writehist(&TR[p],cs); if (strcmp(cs,"")!=0) fprintf(s.file,"# %s\n",cs);
- if ( GF[p].control==C_KEY && GB[p].control==C_KEY
- && SL[p].control==C_KEY && SR[p].control==C_KEY
- && (TL[p].control & C_KEY)
- && (TR[p].control & C_KEY)
- ) {
- fprintf(s.file,"# This player plays with keyboard/joystick only. Give him a mouse.\n");
- }
- if (SR[p].sum+SL[p].sum==0) {
- fprintf(s.file,"# This player plays without STRAFE. Show him the README.\n");
- }
- fprintf(s.file,"# %lu * WT in %lu tics (%.1f%%)\n",wait_sum[p],l.tics,100.0*wait_sum[p]/l.tics);
- if (TL[p].control==C_KEY_OLD && (l.game&DOOM_new || l.game&DOOM2)) m=OLD_NEW;
- if (TL[p].control==C_KEY_NEW && l.game==DOOM_old) m=NEW_OLD;
- }
- if (m==NEW_OLD) fprintf(s.file,"# This LMP was originally recorded with an old version (<1.4)\n");
- if (m==OLD_NEW) fprintf(s.file,"# This LMP was originally recorded with a new version (>=1.4)\n");
- }
- LMP_done(&l);
- LS_done(&s);
- }
-
-
- #define MAXLINELENGTH 200
-
- void ActionLS2LMP(char *lsfilename, char *lmpfilename, int action)
- {
- static LMP_t l;
- LS_t s;
- TIC_t t;
- int state;
- unsigned long linenumber;
- char lsline[MAXLINELENGTH];
- char *gt, *temp, *res, *token, *value;
- int i, pause;
- int notdecoded, numberused;
- long number;
- unsigned long repeatcounter;
-
- LS_init(&s,lsfilename,"rb");
- if (action&LMP_INIT) LMP_init(&l,lmpfilename,"wb");
- printf("%s ", s.filename);
-
- state=HEADER_START;
- linenumber=0;
- pause=FALSE;
- while (fgets(lsline,MAXLINELENGTH,s.file)==lsline) {
- linenumber++;
- if (lsline[strlen(lsline)-1]!='\n') {
- syntaxerror(linenumber,"line too long");
- }
- gt=lsline;
- temp=strchr(gt,'#');
- if (temp!=NULL) *temp='\0';
- for (i=0;i<strlen(gt);i++) gt[i]=toupper(gt[i]);
- gt=delspaces(gt);
- if (strlen(gt)>0) switch (state) {
- case HEADER_START:
- l.game=UNKNOWN;
- l.versionbyte=0;
- l.skill=0;
- l.episode=0;
- l.map=0;
- l.multirule=0;
- l.respawn=0;
- l.fast=0;
- l.nomonsters=0;
- l.playernum=1;
- l.mainplayer=0;
- for (i=0;i<MAXPLAYER;i++) l.num[i]=0;
- if (strcmp(gt,"HEADERSTART")) syntaxerror(linenumber,"HeaderStart expected");
- state=HEADER;
- break; /* end HEADER_START */
- case HEADER:
- if (strcmp(gt,"HEADEREND")==0)
- state=HEADER_END;
- else {
- temp=strchr(gt,':');
- if (temp==NULL) syntaxerror(linenumber,"a colon separates token and value in the header");
- if (temp==gt) syntaxerror(linenumber,"token expected");
- if (temp==gt+strlen(gt)-1) syntaxerror(linenumber,"value expected");
- *temp='\0';
- token=gt;
- token=delspaces(token);
- value=temp+1;
- value=delspaces(value);
- notdecoded=TRUE;
- numberused=FALSE;
- number=strtol(value,&res,0);
- if (notdecoded && strcmp(token,"GAME")==0) {
- if (notdecoded && strcmp(value,"HERETIC")==0) {
- l.game=HERETIC;
- numberused=FALSE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(value,"DOOM")==0) {
- l.game=DOOM_old|DOOM_new;
- numberused=FALSE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(value,"DOOM ][")==0) {
- l.game=DOOM2;
- numberused=FALSE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(value,"DOOM OR DOOM ][")==0) {
- l.game=DOOM_new|DOOM2;
- numberused=FALSE;
- notdecoded=FALSE;
- }
- }
- if (notdecoded && strcmp(token,"VERSION")==0) {
- l.versionbyte=strtoversionbyte(value);
- numberused=FALSE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(token,"SKILL")==0) {
- l.skill=number-1;
- numberused=TRUE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(token,"EPISODE")==0) {
- l.episode=number;
- numberused=TRUE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(token,"MAP")==0) {
- l.map=number;
- numberused=TRUE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(token,"PLAYER0")==0) {
- l.num[0]=number;
- if (l.playernum<1) l.playernum=1;
- numberused=TRUE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(token,"PLAYER1")==0) {
- l.num[1]=number;
- if (l.playernum<2) l.playernum=2;
- numberused=TRUE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(token,"PLAYER2")==0) {
- l.num[2]=number;
- if (l.playernum<3) l.playernum=3;
- numberused=TRUE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(token,"PLAYER3")==0) {
- l.num[3]=number;
- if (l.playernum<4) l.playernum=4;
- numberused=TRUE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(token,"MULTIRULE")==0) {
- if (notdecoded && strcmp(value,"COOPERATIVE")==0) {
- l.multirule=ruleCOOP;
- numberused=FALSE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(value,"DEATHMATCH")==0) {
- l.multirule=ruleDEATH;
- numberused=FALSE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(value,"ALTDEATH")==0) {
- l.multirule=ruleALT;
- numberused=FALSE;
- notdecoded=FALSE;
- }
- if (notdecoded) {
- l.multirule=number;
- numberused=TRUE;
- notdecoded=FALSE;
- }
- }
- if (notdecoded && strcmp(token,"RESPAWN")==0) {
- l.respawn=number;
- numberused=TRUE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(token,"FAST")==0) {
- l.fast=number;
- numberused=TRUE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(token,"NOMONSTERS")==0) {
- l.nomonsters=number;
- numberused=TRUE;
- notdecoded=FALSE;
- }
- if (notdecoded && strcmp(token,"VIEWOFPLAYER")==0) {
- l.mainplayer=number;
- numberused=TRUE;
- notdecoded=FALSE;
- }
- if (notdecoded) syntaxerror(linenumber,"token expected");
- if (numberused && res[0]!='\0') syntaxerror(linenumber,"number expected");
- }
- break; /* end HEADER */
- case HEADER_END:
- case DATA_START:
- if (l.game==UNKNOWN) syntaxerror(linenumber,"Game is not defined");
- if (l.game==(DOOM_old|DOOM_new)) {
- if (l.versionbyte==0)
- l.game=DOOM_old;
- else
- l.game=DOOM_new;
- }
- if (action&LMP_INIT) LMP_writeheader(&l);
- l.ticsize=(l.game==HERETIC?LONG_TIC:SHORT_TIC);
- state=DATA_START;
- if (strcmp(gt,"DATASTART")) syntaxerror(linenumber,"DataStart expected");
- state=DATA;
- break;
- case DATA:
- if (strcmp(gt,"DATAEND")==0) {
- state=DATA_END;
- if (action&LMP_END) LMP_writequitbyte(&l);
- state++;
- }
- else {
- t.go=0;
- t.strafe=0;
- t.turn=0;
- t.use=0;
- if (l.game==HERETIC) {
- t.fl=0;
- t.art=0;
- }
- repeatcounter=1;
- token=strtok(gt," ");
- while (token!=NULL) {
- notdecoded=TRUE;
- if (notdecoded && strncmp(token,"*",1)==0) {
- number=strtol(token+1,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"*number expected");
- if (0<number)
- repeatcounter=number;
- else
- syntaxerror(linenumber,"*number out of range");
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"GF",2)==0) {
- number=strtol(token+2,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"GFnumber expected");
- if (0<number && number<128)
- t.go=number;
- else
- syntaxerror(linenumber,"GFnumber out of range");
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"GB",2)==0) {
- number=strtol(token+2,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"GBnumber expected");
- if (0<number && number<128)
- t.go=256-number;
- else
- syntaxerror(linenumber,"GBnumber out of range");
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"SR",2)==0) {
- number=strtol(token+2,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"SRnumber expected");
- if (0<number && number<128)
- t.strafe=number;
- else
- syntaxerror(linenumber,"SRnumber out of range");
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"SL",2)==0) {
- number=strtol(token+2,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"SLnumber expected");
- if (0<number && number<128)
- t.strafe=256-number;
- else
- syntaxerror(linenumber,"SLnumber out of range");
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"TR",2)==0) {
- number=strtol(token+2,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"TRnumber expected");
- if (0<number && number<128)
- t.turn=256-number;
- else
- syntaxerror(linenumber,"TRnumber out of range");
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"TL",2)==0) {
- number=strtol(token+2,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"TLnumber expected");
- if (0<number && number<128)
- t.turn=number;
- else
- syntaxerror(linenumber,"TLnumber out of range");
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"PS",2)==0) {
- if (strlen(token)>2) syntaxerror(linenumber,"PS expected");
- if (pause) syntaxwarning(linenumber,"Pause is activ already");
- pause=TRUE;
- if (t.use!=0 && t.use!=0x81) syntaxerror(linenumber,"PS can''t be used with other use things");
- t.use=0x81;
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"PE",2)==0) {
- if (strlen(token)>2) syntaxerror(linenumber,"PE expected");
- if (!pause) syntaxwarning(linenumber,"Pause is off already");
- pause=FALSE;
- if (t.use!=0 && t.use!=0x81) syntaxerror(linenumber,"PE can't be used with other use things");
- t.use=0x81;
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"SG",2)==0) {
- number=strtol(token+2,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"SGnumber expected");
- if (0<=number && number<=7) {
- if (t.use!=0) syntaxerror(linenumber,"SG can't be used with other use things");
- t.use=0x82 | (number<<2);
- }
- else
- syntaxerror(linenumber,"SGnumber out of range");
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"FW",2)==0) {
- if (strlen(token)>2) syntaxerror(linenumber,"FW expected");
- if (t.use & 0x80) syntaxerror(linenumber,"FW can't be used with PS, PE and SG");
- t.use |= 0x01;
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"UT",2)==0) {
- if (strlen(token)>2) syntaxerror(linenumber,"UT expected");
- if (t.use & 0x80) syntaxerror(linenumber,"UT can't be used with PS, PE and SG");
- t.use |= 0x02;
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"NW",2)==0) {
- number=strtol(token+2,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"NWnumber expected");
- if (1<=number && number<=8) {
- if (t.use & 0x80) syntaxerror(linenumber,"NW can't be used with PS, PE and SG");
- t.use = (t.use & 0x03) | 0x04 | ((number-1)<<3);
- }
- else
- syntaxerror(linenumber,"NWnumber out of range");
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"WT",2)==0) {
- if (strlen(token)>2) syntaxerror(linenumber,"WT expected");
- notdecoded=FALSE;
- }
- if (l.game==HERETIC && notdecoded && strncmp(token,"LU",2)==0) {
- number=strtol(token+2,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"LUnumber expected");
- if (0<number && number<16)
- t.fl=(t.fl & 0xF0) | number;
- else
- syntaxerror(linenumber,"LUnumber out of range");
- notdecoded=FALSE;
- }
- if (l.game==HERETIC && notdecoded && strncmp(token,"LD",2)==0) {
- number=strtol(token+2,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"LDnumber expected");
- if (0<number && number<16)
- t.fl=(t.fl & 0xF0) | (16-number);
- else
- syntaxerror(linenumber,"LDnumber out of range");
- notdecoded=FALSE;
- }
- if (l.game==HERETIC && notdecoded && strncmp(token,"LC",2)==0) {
- if (strlen(token)>2) syntaxerror(linenumber,"LC expected");
- t.fl=(t.fl & 0xF0) | 0x08;
- notdecoded=FALSE;
- }
- if (l.game==HERETIC && notdecoded && strncmp(token,"FU",2)==0) {
- number=strtol(token+2,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"FUnumber expected");
- if (0<number && number<16)
- t.fl=(t.fl & 0x0F) | (number<<4);
- else
- syntaxerror(linenumber,"FUnumber out of range");
- notdecoded=FALSE;
- }
- if (l.game==HERETIC && notdecoded && strncmp(token,"FD",2)==0) {
- number=strtol(token+2,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"FDnumber expected");
- if (0<number && number<16)
- t.fl=(t.fl & 0x0F) | ((16-number)<<4);
- else
- syntaxerror(linenumber,"FDnumber out of range");
- notdecoded=FALSE;
- }
- if (l.game==HERETIC && notdecoded && strncmp(token,"FC",2)==0) {
- if (strlen(token)>2) syntaxerror(linenumber,"FC expected");
- t.fl=(t.fl & 0x0F) | 0x80;
- notdecoded=FALSE;
- }
- if (l.game==HERETIC && notdecoded && strncmp(token,"AT",2)==0) {
- if (strlen(token)!=3) syntaxerror(linenumber,"ATchar expected");
- number=token[2]-'A'+1;
- if (1<=number && number<=10)
- t.art=number;
- else
- syntaxerror(linenumber,"ATchar out of range");
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"G",1)==0) {
- number=strtol(token+1,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"Gnumber expected");
- if (0<number && number<256) {
- if (t.go!=0) syntaxerror(linenumber,"Gnumber overwrites go-byte");
- t.go=number;
- }
- else
- syntaxerror(linenumber,"Gnumber out of range");
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"S",1)==0) {
- number=strtol(token+1,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"Snumber expected");
- if (0<number && number<256) {
- if (t.strafe!=0) syntaxerror(linenumber,"Snumber overwrites strafe-byte");
- t.strafe=number;
- }
- else
- syntaxerror(linenumber,"Snumber out of range");
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"T",1)==0) {
- number=strtol(token+1,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"Tnumber expected");
- if (0<number && number<256) {
- if (t.turn!=0) syntaxerror(linenumber,"Tnumber overwrites turn-byte");
- t.turn=number;
- }
- else
- syntaxerror(linenumber,"Tnumber out of range");
- notdecoded=FALSE;
- }
- if (notdecoded && strncmp(token,"U",1)==0) {
- number=strtol(token+1,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"Unumber expected");
- if (0<number && number<256) {
- if (t.use!=0) syntaxerror(linenumber,"Unumber overwrites use-byte");
- t.use=number;
- }
- else
- syntaxerror(linenumber,"Unumber out of range");
- notdecoded=FALSE;
- }
- if (l.game==HERETIC && notdecoded && strncmp(token,"F",1)==0) {
- number=strtol(token+1,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"Fnumber expected");
- if (0<number && number<256) {
- if (t.fl!=0) syntaxerror(linenumber,"Fnumber overwrites flight/look-byte");
- t.fl=number;
- }
- else
- syntaxerror(linenumber,"Fnumber out of range");
- notdecoded=FALSE;
- }
- if (l.game==HERETIC && notdecoded && strncmp(token,"A",1)==0) {
- number=strtol(token+1,&res,0);
- if (res[0]!='\0') syntaxerror(linenumber,"Anumber expected");
- if (0<number && number<256) {
- if (t.art!=0) syntaxerror(linenumber,"Anumber overwrites use artifact-byte");
- t.art=number;
- }
- else
- syntaxerror(linenumber,"Anumber out of range");
- notdecoded=FALSE;
- }
- if (notdecoded) syntaxerror(linenumber,"Data token expected");
- token=strtok(NULL," ");
- }
- for (i=0;i<repeatcounter;i++) LMP_putgametic(&l, &t);
- }
- break;
- case DATA_END:
- /* ignore all the rest */
- break;
- } /* end switch (state) */
- } /* end while not end of file */
- LS_done(&s);
- if (action&LMP_END) {
- printf("-> %s\n", l.filename);
- LMP_done(&l);
- }
- }
-
-
- void ActionConvert(char *infilename, char *outfilename, opt_t *opt)
- {
- LMP_t li, lo;
- int NewFile, NewTics, NewHeader;
- int o_game;
- char *gs, *o_version;
- long wttics=0, tic, ps=0;
- int p;
- TIC_t t[MAXPLAYER];
- TIC_t WT = {0,0,0,0,0,0};
- int pause=FALSE, allowput;
- #define TMP_FILE "lmpclmpc.tmp"
-
- LMP_init(&li, infilename, "rb");
- li.game = (opt->option&opDefineGame?opt->game:UNKNOWN);
- LMP_readheader(&li);
- printf("%s ", li.filename);
- NewFile=FALSE;
- NewTics=FALSE;
- NewHeader=FALSE;
- o_game=li.game;
- if (strcmp(infilename,outfilename)) NewFile=TRUE;
- if (opt->option&opVersion) {
- if (li.versionbyte==opt->versionbyte) {
- opt->option^=opVersion; /* nothing to do */
- }
- else {
- NewHeader=TRUE;
- }
- if (li.game==HERETIC) syserror(IMPVCH,li.filename);
- if (opt->versionbyte==0) {
- if (li.game==DOOM2) syserror(IMPVCH,li.filename);
- if (li.game&DOOM_new) {
- o_game=DOOM_old;
- NewFile=TRUE;
- }
- }
- else {
- if (li.game==DOOM_old) {
- o_game=DOOM_new;
- NewFile=TRUE;
- }
- }
- getversion(opt->versionbyte,&o_game,outfilename,&gs,&o_version);
- printf("version %s -> %s ", li.ns, o_version);
- }
- if (opt->option&opViewPlayer) {
- if (li.game==HERETIC || li.game==DOOM_old) syserror(IMPVCH,li.filename);
- if (li.mainplayer==opt->mainplayer) {
- opt->option^=opViewPlayer; /* nothing to do */
- }
- else {
- NewHeader=TRUE;
- }
- printf("player %i -> %i ", li.mainplayer, opt->mainplayer);
- }
- if (opt->option&opAddWT) {
- if (opt->addwt==0) {
- opt->option^=opAddWT; /* nothing to do */
- }
- wttics = opt->addwt * 35 * li.playernum;
- printf("+%lisec ", opt->addwt);
- }
- if (opt->option&opRemovePause) {
- NewFile=TRUE;
- NewTics=TRUE;
- pause = FALSE;
- ps = 0;
- printf("-PS -PE ");
- }
- printf("%s\n", outfilename);
- if (NewFile) {
- lo=li;
- LMP_init(&lo, TMP_FILE, "wb");
- }
- else {
- if (fclose(li.file)!=0) syserror(errno,li.filename);
- if ((li.file=fopen(li.filename, "r+b"))==NULL) syserror(errno,li.filename);
- lo=li;
- }
- lo.game=o_game;
- if (opt->option&opVersion) {
- lo.versionbyte=opt->versionbyte;
- }
- if (opt->option&opViewPlayer) {
- lo.mainplayer=opt->mainplayer;
- }
-
- /* header */
- if (NewHeader || NewFile) LMP_writeheader(&lo);
-
- /* game tics */
- if (NewFile) {
- if (NewTics) {
- allowput = TRUE;
- for (tic=1;tic<=li.tics;tic++) {
- for (p=0;p<li.playernum;p++) {
- LMP_getgametic(&li,&(t[p]));
- }
- if (opt->option&opRemovePause) {
- allowput = !pause;
- for (p=0;p<li.playernum;p++) {
- if (t[p].use==0x81) {
- if (pause) {
- pause=FALSE; /* PE */
- /* the PE game tic will not be stored */
- printf(", PE at %lu (%lu tics removed)\n",tic, tic-ps);
- }
- else {
- pause=TRUE; /* PS */
- t[p].use=0;
- /* the PS game will be stored (use=empty) */
- printf("PS at %lu",tic);
- ps=tic;
- }
- p=li.playernum; /* only one pause state change per tic */
- }
- }
- }
- if (allowput) for (p=0;p<li.playernum;p++) LMP_putgametic(&lo,&(t[p]));
- }
- }
- else {
- copyopenfiles(li.file,lo.file);
- fseek(lo.file, -1, SEEK_END); /* seek after the last tic */
- }
- }
- else {
- fseek(lo.file, -1, SEEK_END); /* seek after the last tic */
- }
-
- if (opt->option&opAddWT) {
- for (tic=0;tic<wttics;tic++) LMP_putgametic(&lo, &WT);
- }
-
- if (NewFile || (opt->option&opAddWT)) LMP_writequitbyte(&lo);
- LMP_done(&lo);
- if (NewFile) {
- LMP_done(&li);
- if (rename(TMP_FILE, outfilename)==-1) syserror(errno, outfilename);
- }
- }
-
- /*- file end lmpc.c ----------------------------------------------------------*/
-