home *** CD-ROM | disk | FTP | other *** search
- {$A+,B-,D+,E+,F-,G+,I-,L+,N-,O-,P-,Q-,R-,S-,T-,V-,X+}
- {$M 16384,0,655360}
- { DM2CONV v3.0 by Vincenzo Alcamo }
- { This program is Public Domain }
- type
- CHAR8 = array[1..8] of char;
- WAD_HEADER = record
- Sig : longint;
- Num : longint;
- Start : longint;
- end;
- WAD_ENTRY = record
- Start : longint;
- Size : longint;
- Name : CHAR8;
- end;
- THING = record
- XPos : integer;
- YPos : integer;
- Angle: integer;
- Code : word;
- Flags: word;
- end;
- SIDEDEF = record
- XOffs,YOffs : integer;
- UpT,LoT,MidT : CHAR8;
- Sector : word;
- end;
- SECTOR = record
- Y1,Y2 : integer;
- Floor,Ceiling : CHAR8;
- Lum,Action,Tag : word;
- end;
- LINEDEF = record
- V1,V2 : word;
- Attr : word;
- Action,Tag : word;
- RSide,LSide: word;
- end;
- GAMETYPE = (GT_DOOM,GT_DOOM2,GT_HERETIC);
- ERRORS = (ERR_NONE,ERR_TOOSYM,ERR_ENDIF_NOIF,ERR_TOORESP,
- ERR_NORESP,ERR_READRESP,ERR_NOLABEL,
- ERR_BADEND,ERR_NOEQ,ERR_BADNUM,ERR_TOOREPN,
- ERR_NOTHINGMODE,ERR_NOCOND,
- ERR_LASTSYNTAX, {marks the last syntax error}
- ERR_BADELSE,ERR_BADENDIF,
- ERR_NOMEM,ERR_OPEN,ERR_READ,ERR_WRITE,ERR_TOOENTRY,ERR_PWAD);
-
- const
- IWAD_SIG = Ord('I')+(Ord('W')+(Ord('A')+Ord('D') shl 8) shl 8) shl 8;
- PWAD_SIG = Ord('P')+(Ord('W')+(Ord('A')+Ord('D') shl 8) shl 8) shl 8;
- N_THINGS = 'THINGS'#0#0;
- N_SECTORS= 'SECTORS'#0;
- N_SIDEDEFS='SIDEDEFS';
- N_LINEDEFS='LINEDEFS';
- NULL_NAME= #0#0#0#0#0#0#0#0;
- BUFFSIZE = 65528; {biggest allocable block }
- MAXENTRY = BUFFSIZE div sizeof(WAD_ENTRY);
- MAXTHING = BUFFSIZE div sizeof(THING);
- MAXSIDE = BUFFSIZE div sizeof(SIDEDEF);
- MAXSECT = BUFFSIZE div sizeof(SECTOR);
- MAXLINE = BUFFSIZE div sizeof(LINEDEF);
- MAXREPN = 1024; { maximum number of replace name}
- MAXREPT = 4096; { maximum number of rep thing info }
- MAXSYMS = 1024; { maximum space for symbol table }
- MAXRESP = 10; { maximum number of nested response files }
- MAXACTION= 256; { maximum number of linedef/sector action to replace }
- MAXOBJ = 500; { maximum number of object info }
- REP_FLAG = $4000; { maximum value for thing id / flag }
- REP_CONV = $2000; { flag for converted objects }
- REP_ALL = REP_FLAG+REP_CONV; {all objects}
- REP_DEAF = $0008; { flag for DEAF object: defined by DOOM engine }
- REP_MULTI= $0010; { flag for MULTI object: defined by DOOM engine }
- REP_ZERO = $0020; { flag for ZERO object }
- REP_RANGE= $8000; { flag for range expression}
- REP_QIF = $C000; { flag for question_mark }
- REP_QELSE= $C100; { ?ELSE command }
- REP_QEND = $C200; { ?END command }
-
- KEY_IFDEF = 'IFDEF';
- KEY_IFNDEF= 'IFNDEF';
- KEY_ELSE = 'ELSE';
- KEY_ENDIF = 'ENDIF';
-
- SYM_SOURCE = 'SOURCE';
- SYM_DEST = 'DEST';
- SYM_HELP = 'HELP';
- SYM_SEED = 'SEED';
- SYM_FROM = 'FROM';
- SYM_TO = 'TO';
- SYM_REMAP = 'REMAP';
- SYM_ONCE = 'ONCE';
- SYM_MIX = 'MIX';
- SYM_DEBUG = 'DEBUG';
-
- MUS2NAMES : array[1..32] of CHAR8 = (
- 'D_RUNNIN','D_STALKS','D_COUNTD','D_BETWEE','D_DOOM'#0#0,
- 'D_THE_DA','D_SHAWN'#0,'D_DDTBLU','D_IN_CIT','D_DEAD'#0#0,
- 'D_STLKS2','D_THEDA2','D_DOOM2'#0,'D_DDTBL2','D_RUNNI2',
- 'D_DEAD2'#0,'D_STLKS3','D_ROMERO','D_SHAWN2','D_MESSAG',
- 'D_COUNT2','D_DDTBL3','D_AMPIE'#0,'D_THEDA3','D_ADRIAN',
- 'D_MESSG2','D_ROMER2','D_TENSE'#0,'D_SHAWN3','D_OPENIN',
- 'D_EVIL'#0#0,'D_ULTIMA');
-
-
- type
- REPNAME = record
- Before : CHAR8;
- After : CHAR8;
- end;
- REPACTION = record
- After : word;
- Before : word;
- end;
- RESPONSE = record
- RFile : text;
- Name : string;
- IfLev : integer;
- Line : integer;
- end;
- S_GAMETYPE = set of GAMETYPE;
- OBJINFO = record
- Code : word;
- Radius : word;
- Height : word;
- Games : S_GAMETYPE;
- Name : string[20];
- end;
- A_REPNAME = array[1..MAXREPN] of REPNAME;
- A_BUFFER = array[1..BUFFSIZE] of byte;
- A_DIRLIST = array[1..MAXENTRY] of WAD_ENTRY;
- A_THINGS = array[1..MAXTHING] of THING;
- A_SIDEDEFS= array[1..MAXSIDE] of SIDEDEF;
- A_SECTORS = array[1..MAXSECT] of SECTOR;
- A_LINEDEFS= array[1..MAXLINE] of LINEDEF;
- A_REPLACE = array[1..MAXREPT] of word;
- A_REPACTION=array[1..MAXACTION] of REPACTION;
- A_OBJINFO = array[1..MAXOBJ] of OBJINFO;
- SYMBOLSPACE=array[1..MAXSYMS] of char;
-
- var
- Buffer : ^A_BUFFER;
- Dirlist : ^A_DIRLIST;
- Things : ^A_THINGS;
- Sidedefs : ^A_SIDEDEFS;
- Sectors : ^A_SECTORS;
- Linedefs : ^A_LINEDEFS;
-
- Symbols : ^SYMBOLSPACE;
-
- RepThing : ^A_REPLACE;
- RepText : ^A_REPNAME;
- RepFloor : ^A_REPNAME;
- RepDirs : ^A_REPNAME;
- RepLAct : ^A_REPACTION;
- RepSAct : ^A_REPACTION;
- Objects : ^A_OBJINFO;
-
- Resp : array[1..MAXRESP] of RESPONSE;
- RespLev : integer;
-
- SourceName : string; {name of source file}
- DestName : string; {name of destination file}
- RandomSeed : longint; {seed for random number generator}
-
- Game1 : GAMETYPE; {type of source wad}
- Game2 : GAMETYPE; {type of dest wad}
-
- const
- NRepThing: integer = 0; {number of replaces for each category}
- NRepText : integer = 0;
- NRepFloor: integer = 0;
- NRepDirs : integer = 0;
- NRepLAct : integer = 0;
- NRepSAct : integer = 0;
- NObjects : integer = 0;
-
- RemappedThing : word = 0; {various remap counters}
- RemappedText : word = 0;
- RemappedFloor : word = 0;
- RemappedDirs : word = 0;
- RemappedLAct : word = 0;
- RemappedSAct : word = 0;
- RemappedLev : word = 0;
- RemappedMus : word = 0;
-
- Debug : boolean = False; {debug mode}
-
-
- {Return a right-padded string of N characters from a string}
- function StringN(s:String;n:Integer):String;
- var i:Integer;
- begin
- StringN:=Copy(s,1,n);
- StringN[0]:=Char(n);
- for i:=Length(s)+1 to n do StringN[i]:=' ';
- end;
-
- {Converts string to uppercase}
- function Upper(s:String):String;
- var i:Integer;
- begin
- Upper[0]:=s[0];
- for i:=1 to Length(s) do Upper[i]:=UpCase(s[i]);
- end;
-
- {Add a suffix(extension) to a filename (only if the filename hasn't one)}
- function AddSuffix(s,n:String):String;
- var i:Integer;
- begin
- i:=Length(s);
- while i>0 do
- if s[i]='.' then break
- else dec(i);
- if i>0 then AddSuffix:=s
- else AddSuffix:=s+'.'+n;
- end;
-
- {Return the first word of a string}
- function GetWord(var s:string):string;
- var i,j:integer;
- begin
- j:=1;
- while (j<=length(s)) and (s[j]<=#32) do inc(j);
- i:=j;
- while (i<=length(s)) and (s[i]>#32) do inc(i);
- GetWord:=Copy(s,j,i-j);
- s:=Copy(s,i,255);
- end;
-
- {Add a long to a pointer}
- function AddPtr(p:pointer;l:longint):pointer;
- begin
- AddPtr:=pointer(longint(p)+l);
- end;
-
- {Return the value of a specified environment variable}
- {If name is '' the full path of the program is returned}
- function GetEnv(name:string):string; assembler;
- asm
- push ds
- mov ds, PrefixSeg
- mov ax, ds:[$2C]
- mov ds, ax
- xor si, si
- cld
- les di, name
- xor dx, dx
- mov dl, es:[di]
- inc di
- mov bx, di
- @@CICLO:
- cmp byte ptr ds:[si], 0
- je @@FINE
- mov di, bx
- mov cx, dx
- rep cmpsb
- jne @@NEXT
- lodsb
- cmp al, '='
- je @@FOUND
- @@NEXT:
- cmp dx, 0
- je @@ZERO
- dec si
- @@ZERO:
- lodsb
- cmp al, 0
- jne @@ZERO
- jmp @@CICLO
- @@FINE:
- cmp dx, 0
- jne @@FOUND
- add si, 3
- @@FOUND:
- les di, @RESULT
- push di
- inc di
- xor cx, cx
- @@COPY:
- lodsb
- stosb
- inc cx
- cmp al, 0
- jne @@COPY
- xchg ax, cx
- dec ax
- pop di
- stosb
- pop ds
- end;
-
- {Concat the exe path with the specified filename}
- function AsInEXEDir(s:string):string;
- var t:string;
- i:integer;
- begin
- t:=GetEnv('');
- i:=length(t);
- while (i>0) and (t[i]<>'\') and (t[i]<>'/') do dec(i);
- t[0]:=chr(i);
- i:=length(s);
- while (i>0) and (s[i]<>'\') and (s[i]<>'/') do dec(i);
- AsInEXEDir:=t+copy(s,i+1,255);
- end;
-
- procedure SyntaxHelp;
- begin
- if RespLev>0 then
- writeln('(Line ',Resp[RespLev].Line,' in file ',Resp[RespLev].Name,')');
- end;
-
- var ErrStr:string;
- procedure MyHalt(err:ERRORS);
- begin
- if err<>ERR_NONE then write('ERROR: ');
- case err of
- ERR_NOMEM: writeln('Not enough memory!');
- ERR_TOOSYM: writeln('Symbol table full!');
- ERR_ENDIF_NOIF: writeln('ENDIF without IF');
- ERR_TOORESP: writeln('Too many nested response files!');
- ERR_NORESP: writeln('Cannot find response file!');
- ERR_READRESP: writeln('Cannot read response file!');
- ERR_NOLABEL: writeln('Label not found in response file!');
- ERR_BADEND: writeln('Expression incorrectly terminated');
- ERR_NOEQ: writeln('Missing ''='' in expression!');
- ERR_BADNUM: writeln('Bad number in expression!');
- ERR_NOTHINGMODE: writeln('Command not allowed outside THINGS section!');
- ERR_NOCOND: writeln('No valid relational operator specified!');
- ERR_BADELSE: writeln('Bad ?ELSE expression found!');
- ERR_BADENDIF:writeln('Bad ?END expression found!');
- ERR_TOOREPN: writeln('Replace table full!');
- ERR_READ: writeln('Cannot read from file: ',SourceName);
- ERR_WRITE: writeln('Cannot write to file: ',DestName);
- ERR_OPEN: writeln('Cannot open file: ',ErrStr);
- ERR_PWAD: writeln('File is not a valid WAD: ',SourceName);
- ERR_TOOENTRY:writeln('Too many entries in file: ',SourceName);
- end;
- if (err>ERR_NONE) and (err<ERR_LASTSYNTAX) then SyntaxHelp;
- Halt(ord(err));
- end;
-
- function MyHeapError(size:word):integer; far;
- begin
- if size<>0 then MyHalt(ERR_NOMEM);
- MyHeapError:=1;
- end;
-
- procedure Initialize;
- begin
- RespLev:=0;
- HeapError:=@MyHeapError;
- New(RepText);
- New(RepFloor);
- New(RepDirs);
- New(RepThing);
- New(Buffer);
- New(DirList);
- New(RepLAct);
- New(RepSAct);
- New(Objects);
- New(Symbols);
- Symbols^[1]:=#0;
- Things:=pointer(Buffer);
- Linedefs:=pointer(Buffer);
- Sidedefs:=pointer(Buffer);
- Sectors:=pointer(Buffer);
- end;
-
- var SymbolName : ^string;
- SymbolValue: ^string;
- SymbolFound: boolean;
- function GetSymbol(name:string):string;
- begin
- SymbolName:=@Symbols^;
- while SymbolName^<>'' do begin
- SymbolValue:=AddPtr(SymbolName,length(SymbolName^)+1);
- if SymbolName^=name then begin
- GetSymbol:=SymbolValue^;
- SymbolFound:=True;
- exit;
- end;
- SymbolName:=AddPtr(SymbolValue,length(SymbolValue^)+1);
- end;
- SymbolFound:=False;
- GetSymbol:=Upper(GetEnv(name));
- end;
-
- procedure SetSymbol(name,value:string);
- begin
- GetSymbol(name);
- if SymbolFound then begin
- SymbolValue:=AddPtr(SymbolValue,length(SymbolValue^)+1);
- while SymbolValue^<>'' do begin
- SymbolName^:=SymbolValue^;
- SymbolValue:=AddPtr(SymbolValue,length(SymbolName^)+1);
- SymbolName:=AddPtr(SymbolName,length(SymbolName^)+1);
- end;
- end;
- if value<>'' then begin
- if longint(SymbolName)+length(name)+length(value)+2>longint(Symbols)+sizeof(SYMBOLSPACE) then
- MyHalt(ERR_TOOSYM);
- SymbolName^:=name;
- SymbolValue:=AddPtr(SymbolName,length(name)+1);
- SymbolValue^:=value;
- SymbolName:=AddPtr(SymbolValue,length(value)+1);
- end;
- SymbolName^:='';
- end;
-
- procedure Title;
- begin
- writeln('DM2CONV v3.0 by Vincenzo Alcamo (alcamo@arci01.bo.cnr.it) VERSION 950521');
- end;
-
- procedure Help;
- begin
- Title;
- writeln('Interchange maps among DOOM, DOOM II and HERETIC.');
- writeln;
- writeln('Usage: DM2CONV <input> [output] [/symbol[=[value]]]... <@response>...');
- writeln;
- writeln(' input name of wad file to convert');
- writeln(' output name of output file (if omitted, the source is overwritten)');
- writeln(' symbol symbol to define (/symbol=value) or undefine (/symbol=)');
- writeln(' @response name of response file');
- writeln;
- writeln('To convert levels from game_A to game_B use the appropriate response file,');
- writeln('following this name convention: D=DOOM, D2=DOOM II, H=HERETIC.');
- writeln('Example for DOOM to HERETIC conversion: DM2CONV input output @:DTOH');
- writeln('Example for DOOM II to DOOM conversion: DM2CONV input output @:D2TOD');
- writeln;
- writeln('If you use the wads built by GFXMAKER you should define the GFX symbol.');
- writeln('Example for HERETIC to DOOM conversion: DM2CONV input output /GFX @:HTOD');
- writeln;
- writeln('Full instructions are contained inside DM2CONV.DOC: this file and the official');
- writeln('response file DEFAULT.RSP are part of the DM2CONV distribution package.');
- writeln('REMEMBER: DM2CONV is PUBLIC DOMAIN (or FREEWARE if you prefer).');
- end;
-
- function MyVal(s:string):integer;
- var i,j:integer;
- begin
- Val(s,j,i);
- if (i<>0) or (j>=REP_FLAG) or (j<0) then MyHalt(ERR_BADNUM);
- MyVal:=j;
- end;
-
- procedure ParseSymbol(s:string);
- var i:integer;
- begin
- if s='' then begin
- SymbolName:=@Symbols^;
- while SymbolName^<>'' do begin
- SymbolValue:=AddPtr(SymbolName,length(SymbolName^)+1);
- writeln(SymbolName^,'=',SymbolValue^);
- SymbolName:=AddPtr(SymbolValue,length(SymbolValue^)+1);
- end;
- end
- else begin
- i:=1;
- while (i<=length(s)) and (s[i]<>'=') do inc(i);
- if i>length(s) then SetSymbol(s,s)
- else SetSymbol(copy(s,1,i-1),copy(s,i+1,255));
- end;
- end;
-
- function GetArgument:string;
- var i:integer;
- s:string;
- begin
- if eof(Resp[RespLev].RFile) then begin
- close(Resp[RespLev].RFile);
- dec(RespLev);
- s:='';
- end
- else begin
- readln(Resp[RespLev].RFile,s);
- inc(Resp[RespLev].Line);
- if ioresult<>0 then MyHalt(ERR_READRESP);
- i:=1;
- while (i<=length(s)) and (s[i]<=#32) do inc(i);
- s:=copy(s,i,255);
- end;
- i:=1;
- while i<=length(s) do begin
- if s[i]=';' then s[0]:=chr(i-1);
- inc(i);
- end;
- i:=length(s);
- while (i>0) and (s[i]<=#32) do dec(i);
- s[0]:=chr(i);
- GetArgument:=s;
- end;
-
- function GetIdentifier(var s:string):string;
- var i:integer;
- begin
- s:=s+#0;
- i:=1;
- while (s[i]='_') or ((s[i]>='0') and (s[i]<='9')) or ((s[i]>='A') and (s[i]<='Z')) do inc(i);
- GetIdentifier:=Copy(s,1,i-1);
- s:=Copy(s,i,length(s)-i);
- end;
-
- function CheckLevel(var s:string):word;
- var i,j:word;
- begin
- j:=0;
- if (length(s)>0) and (s[1]=':') then begin
- i:=2;
- while i<=length(s) do begin
- case s[i] of
- '0': j:=j or REP_ZERO; {allow no skill flags}
- '1': j:=j or 1; {skill level 1-2}
- '2': j:=j or 2; {skill level 3}
- '3': j:=j or 4; {skill level 4-5}
- 'D': j:=j or REP_DEAF; {deaf flag}
- 'M': j:=j or REP_MULTI; {multiplayer}
- 'O': j:=j or REP_FLAG; {only objects not already converted}
- 'A': j:=j or REP_ALL; {all objects}
- 'C': j:=j or REP_CONV; {only converted objects}
- else break;
- end;
- inc(i);
- end;
- s:=Copy(s,i,255);
- end;
- CheckLevel:=j;
- end;
-
- procedure ParseThing(var s:string);
- var i,j,k: integer;
- rnum : integer;
- once : word;
- procedure GetOnceFlag;
- var t:string;
- i,j:integer;
- begin
- t:=GetSymbol(SYM_ONCE);
- if t='' then j:=0
- else begin
- val(t,j,i);
- if i<>0 then j:=1;
- end;
- case j of
- 0: once:=REP_ALL;
- 2: once:=REP_CONV;
- else once:=REP_FLAG;
- end;
- end;
- function GetNum:word;
- var t:string;
- i,j,k,l:integer;
- begin
- s:=Copy(s,2,255);
- t:=GetIdentifier(s);
- if length(t)=0 then MyHalt(ERR_BADNUM);
- if (t[1]>='0') and (t[1]<='9') then GetNum:=MyVal(t)
- else begin
- l:=0;
- for i:=1 to NObjects do with Objects^[i] do begin
- j:=1;
- k:=1;
- repeat
- if Name[k]<=' ' then inc(k)
- else if t[j]<>UpCase(Name[k]) then break
- else begin
- inc(j);
- inc(k);
- end;
- until (j>length(t)) or (k>length(Name));
- if (j>length(t)) and ((l=0) or (k>length(Name))) then l:=Code;
- end;
- if l=0 then MyHalt(ERR_BADNUM);
- GetNum:=l;
- end;
- end;
- procedure PutRep(i:word);
- begin
- inc(NRepThing);
- if NRepThing>MAXREPT then MyHalt(ERR_TOOREPN);
- RepThing^[NRepThing]:=i;
- end;
- begin
- if s='?ELSE' then begin PutRep(REP_QELSE); exit; end;
- if s='?END' then begin PutRep(REP_QEND); exit; end;
- if s[1]='?' then begin
- inc(NRepThing);
- rnum:=NRepThing;
- s[1]:=',';
- end
- else begin
- rnum:=0;
- s:=','+s;
- end;
- GetOnceFlag;
- inc(s[0]);
- s[length(s)]:=#21; {#21 is a sentinel}
- while s[1]=',' do begin
- PutRep(GetNum);
- j:=CheckLevel(s);
- if s[1]='-' then begin
- PutRep(REP_RANGE);
- PutRep(GetNum);
- j:=CheckLevel(s);
- end;
- if j and REP_ALL=0 then j:=j or once;
- PutRep(j);
- end;
- if rnum>0 then begin
- case s[1] of
- '=': j:=0; { = 0 }
- '<': if s[2]='>' then j:=1 { <> 1 }
- else j:=2+ord(s[2]='='); { < 2 <= 3}
- '>': j:=4+ord(s[2]='='); { > 4 >= 5}
- else MyHalt(ERR_NOCOND);
- end;
- RepThing^[rnum]:=j+REP_QIF;
- s:=Copy(s,2+(j and 1),255);
- PutRep(REP_QIF+MyVal(GetIdentifier(s)));
- if s[1]<>#21 then MyHalt(ERR_BADEND);
- exit;
- end;
- if s[1]<>'=' then MyHalt(ERR_NOEQ);
-
- inc(NRepThing);
- rnum:=NRepThing;
- i:=0;
- s[1]:=',';
- while s[1]=',' do begin
- PutRep(GetNum);
- j:=0;
- if s[1]='@' then begin
- s:=Copy(s,2,255);
- j:=MyVal(GetIdentifier(s));
- if (s[1]>='#') and (s[1]<='&') then begin
- inc(j,REP_FLAG); { percentual quantity }
- s:=Copy(s,2,255);
- end;
- end;
- PutRep(j);
- PutRep(CheckLevel(s));
- inc(i);
- end;
- RepThing^[rnum]:=REP_FLAG+i;
- if (s[1]<>#21) or (i=0) then MyHalt(ERR_BADEND);
- end;
-
- procedure ParseName(s:string;i:integer;var table:A_REPNAME;var num:integer);
- var r:REPNAME;
- j:integer;
- begin
- FillChar(r,sizeof(r),0);
- j:=1;
- while (j<=8) and (j<i) do begin
- r.Before[j]:=UpCase(s[j]);
- inc(j);
- end;
- j:=1;
- while (j<=8) and (i<length(s)) do begin
- inc(i);
- r.After[j]:=UpCase(s[i]);
- inc(j);
- end;
- i:=1;
- while (i<=num) and (table[i].Before<>r.Before) do inc(i);
- if j=1 then begin {remove name}
- if i<=num then begin
- table[i]:=table[num];
- dec(num);
- end;
- end
- else begin {add name}
- if i>num then begin
- inc(num);
- if num>MAXREPN then MyHalt(ERR_TOOREPN);
- end;
- table[i]:=r;
- end;
- end;
-
- procedure ParseAction(s:string;var table:A_REPACTION;var num:integer);
- var t : string;
- i,j : integer;
- k : word;
- procedure PutAction;
- begin
- inc(num);
- if num>MAXREPN then MyHalt(ERR_TOOREPN);
- table[num].Before:=k;
- inc(j);
- end;
- begin
- j:=0;
- s:=','+s;
- while s[1]=',' do begin
- s:=copy(s,2,255);
- k:=MyVal(GetIdentifier(s));
- PutAction;
- if s[1]='-' then begin
- s:=copy(s,2,255);
- k:=MyVal(GetIdentifier(s));
- inc(k,REP_RANGE);
- PutAction;
- end;
- end;
- if s[1]<>'=' then MyHalt(ERR_NOEQ);
- s:=copy(s,2,255);
- k:=MyVal(GetIdentifier(s));
- if s<>'' then MyHalt(ERR_BADEND);
- for i:=num-j+1 to num do table[i].After:=k;
- end;
-
- procedure ParseObject(s:string);
- var obj : OBJINFO;
- i : integer;
- begin
- s:=s+#21;
- obj.Code:=MyVal(GetIdentifier(s));
- if s[1]<>'=' then MyHalt(ERR_NOEQ);
- obj.Radius:=0;
- obj.Height:=0;
- obj.Games:=[];
- if (s[2]='(') or (s[2]='[') then begin
- s:=copy(s,3,255);
- obj.Radius:=MyVal(GetIdentifier(s));
- if s[1]=',' then begin
- s:=copy(s,2,255);
- obj.Radius:=MyVal(GetIdentifier(s));
- end;
- if (s[1]<>')') and (s[1]<>']') then MyHalt(ERR_BADEND);
- end;
- i:=2;
- while (i<=length(s)) and (s[i]<>',') do begin
- case upcase(s[i]) of
- 'D': if s[i+1]='2' then begin
- Include(obj.Games,GT_DOOM2);
- inc(i);
- end
- else Include(obj.Games,GT_DOOM);
- 'H': Include(obj.Games,GT_HERETIC);
- end;
- inc(i);
- end;
- if (i>length(s)) or (s[i]<>',') then MyHalt(ERR_BADEND);
- obj.Name:=copy(s,i+1,length(s)-i-1);
- if NObjects=MAXOBJ then MyHalt(ERR_TOOREPN);
- inc(NObjects);
- Objects^[NObjects]:=obj;
- end;
-
- procedure Parse;
- type PARSE_TYPE = (PT_THING,PT_TEXTURE,PT_FLOOR,PT_LINEDEF,
- PT_SECTOR,PT_NAME,PT_OBJECT);
- var
- i,j : integer;
- s,t : string;
- index : integer;
- p_mode : PARSE_TYPE;
- begin
- p_mode:=PT_THING;
- RespLev:=0;
- index:=1;
- while index<=ParamCount do begin
- if RespLev>0 then t:=GetArgument
- else t:=ParamStr(index);
- s:=Upper(GetWord(t));
- if (s='') or (s[1]=':') then {DO NOTHING}
- else if s[1]='@' then begin
- if RespLev=MAXRESP then MyHalt(ERR_TOORESP)
- else begin
- s:=Copy(s,2,255);
- i:=1;
- while (i<=length(s)) and (s[i]<>':') do inc(i);
- t:=copy(s,i,255);
- s:=copy(s,1,i-1);
- if s='' then
- if RespLev>0 then s:=Resp[RespLev].Name
- else s:='DEFAULT';
- j:=RespLev+1;
- Resp[j].IfLev:=0;
- Resp[j].Line:=0;
- assign(Resp[j].RFile,s);
- FileMode:=0;
- reset(Resp[j].RFile);
- if ioresult<>0 then begin
- s:=AddSuffix(s,'RSP');
- assign(Resp[j].RFile,s);
- reset(Resp[j].RFile);
- end;
- if ioresult<>0 then begin
- s:=AsInEXEDir(s);
- assign(Resp[j].RFile,s);
- reset(Resp[j].RFile);
- end;
- if ioresult<>0 then MyHalt(ERR_NORESP);
- Resp[j].Name:=s;
- inc(RespLev);
- if t<>'' then begin
- i:=RespLev;
- s:=GetArgument;
- while (i=RespLev) and (Upper(GetWord(s))<>t) do s:=GetArgument;
- if i<>RespLev then MyHalt(ERR_NOLABEL);
- end;
- end;
- end
- else if (s[1]='/') or (s[1]='-') then begin
- while (s<>'') and ((s[1]='/') or (s[1]='-')) do begin
- ParseSymbol(copy(s,2,255));
- s:=Upper(GetWord(t));
- end;
- end
- else if s[1]='[' then begin
- t:=copy(s,2,3);
- if t='THI' then p_mode:=PT_THING
- else if t='TEX' then p_mode:=PT_TEXTURE
- else if t='FLO' then p_mode:=PT_FLOOR
- else if t='LIN' then p_mode:=PT_LINEDEF
- else if t='SEC' then p_mode:=PT_SECTOR
- else if t='NAM' then p_mode:=PT_NAME
- else if t='OBJ' then p_mode:=PT_OBJECT
- else begin
- writeln('WARNING: Unknown section ',s);
- SyntaxHelp;
- end;
- end
- else begin
- if s[1]='?' then i:=-1
- else i:=Pos('=',s);
- if i<>0 then begin
- repeat
- if s[1]<>'?' then begin
- if i=0 then i:=Pos('=',s);
- if i=0 then MyHalt(ERR_NOEQ);
- end
- else if p_mode<>PT_THING then MyHalt(ERR_NOTHINGMODE);
- case p_mode of
- PT_THING: ParseThing(s);
- PT_TEXTURE: ParseName(s,i,RepText^,NRepText);
- PT_FLOOR: ParseName(s,i,RepFloor^,NRepFloor);
- PT_NAME: ParseName(s,i,RepDirs^,NRepDirs);
- PT_LINEDEF: ParseAction(s,RepLAct^,NRepLAct);
- PT_SECTOR: ParseAction(s,RepSAct^,NRepSAct);
- PT_OBJECT: begin
- ParseObject(s+' '+t);
- t:='';
- end;
- end;
- s:=Upper(GetWord(t));
- i:=0;
- until (s='') or (s[1]=';');
- end
- else if RespLev>0 then begin
- if (s=KEY_IFDEF) or (s=KEY_IFNDEF) then begin
- i:=ord(s=KEY_IFDEF);
- s:=Upper(GetWord(t));
- inc(Resp[RespLev].IfLev);
- if i<>ord(GetSymbol(s)<>'') then begin {condition false}
- j:=Resp[RespLev].IfLev;
- i:=RespLev;
- while (i=RespLev) and (j<=Resp[RespLev].IfLev) do begin
- t:=GetArgument;
- s:=Upper(GetWord(t));
- if (s=KEY_IFDEF) or (s=KEY_IFNDEF) then inc(Resp[RespLev].IfLev)
- else if s=KEY_ENDIF then dec(Resp[RespLev].IfLev)
- else if (s=KEY_ELSE) and (j=Resp[RespLev].IfLev) then i:=0;
- end;
- end;
- end
- else if s=KEY_ELSE then begin
- j:=Resp[RespLev].IfLev;
- i:=RespLev;
- while (i=RespLev) and (j<=Resp[RespLev].IfLev) do begin
- t:=GetArgument;
- s:=Upper(GetWord(t));
- if (s=KEY_IFDEF) or (s=KEY_IFNDEF) then inc(Resp[RespLev].IfLev)
- else if s=KEY_ENDIF then dec(Resp[RespLev].IfLev);
- end;
- end
- else if s=KEY_ENDIF then begin
- if Resp[RespLev].IfLev=0 then MyHalt(ERR_ENDIF_NOIF);
- dec(Resp[RespLev].IfLev);
- end
- else if s='SET' then begin
- repeat
- ParseSymbol(Upper(GetWord(t)))
- until t='';
- end
- else if s='RETURN' then begin
- close(Resp[RespLev].RFile);
- dec(RespLev);
- end
- else if s='ABORT' then MyHalt(ERR_NONE)
- else if s='ECHO' then writeln(Copy(t,2,255))
- else begin
- writeln('WARNING: Unknown keyword ',s);
- SyntaxHelp;
- end;
- end
- else begin
- if GetSymbol(SYM_SOURCE)='' then SetSymbol(SYM_SOURCE,s)
- else if GetSymbol(SYM_DEST)='' then SetSymbol(SYM_DEST,s)
- else begin
- writeln('WARNING: Unknown keyword ',s);
- SyntaxHelp;
- end;
- end;
- end;
-
- if RespLev=0 then inc(index);
- end;
- SourceName:=GetSymbol(SYM_SOURCE);
- DestName:=GetSymbol(SYM_DEST);
- if SourceName<>'' then SourceName:=AddSuffix(SourceName,'WAD');
- if DestName<>'' then DestName:=AddSuffix(DestName,'WAD');
- Debug:=GetSymbol(SYM_DEBUG)<>'';
- end;
-
- procedure BlockR(var f:file;var dest;size:word);
- begin
- BlockRead(f,dest,size);
- if ioresult<>0 then MyHalt(ERR_READ);
- end;
-
- procedure BlockW(var f:file;var dest;size:word);
- begin
- BlockWrite(f,dest,size);
- if ioresult<>0 then MyHalt(ERR_WRITE);
- end;
-
- procedure FSeek(var f:file;p:longint);
- begin
- Seek(f,p);
- if ioresult<>0 then MyHalt(ERR_READ);
- end;
-
- procedure CopyDest;
- var a,b : file;
- l : longint;
- size : word;
- begin
- writeln('Copying source to destination');
- Assign(a,SourceName);
- FileMode:=0; {open for read only}
- ErrStr:=SourceName;
- Reset(a,1);
- if ioresult<>0 then MyHalt(ERR_OPEN);
- Assign(b,DestName);
- FileMode:=1; {open for write only}
- ErrStr:=DestName;
- Rewrite(b,1);
- if ioresult<>0 then MyHalt(ERR_OPEN);
- l:=FileSize(a);
- while l>0 do begin
- if l>BUFFSIZE then size:=BUFFSIZE
- else size:=l;
- BlockR(a,buffer^,size);
- BlockW(b,buffer^,size);
- dec(l,size);
- end;
- Close(a);
- Close(b);
- end;
-
- function RemapName(var table:A_REPNAME;var name:CHAR8;num:integer):integer; assembler;
- asm
- cld
- les di, name
- mov cx, 8
- @@LOOP:
- mov al, es:[di]
- cmp al, 0
- je @@FILLZERO
- cmp al, 'a'
- jb @@STORE
- cmp al, 'z'
- ja @@STORE
- sub al, 32
- @@STORE:
- stosb
- loop @@LOOP
- @@FILLZERO:
- rep stosb
- @@OK:
- push ds
- lds si, name
- les di, table
- mov cx, num
- cld
- lodsw
- mov bx, [si]
- mov dx, [si+2]
- mov si, [si+4]
- @@CICLO:
- scasw
- jnz @@NEXT
- cmp bx, es:[di]
- jnz @@NEXT
- cmp dx, es:[di+2]
- jnz @@NEXT
- cmp si, es:[di+4]
- jnz @@NEXT
- mov ax, es
- mov ds, ax
- mov si, di
- add si, 6
- les di, name
- mov cx, 8
- rep movsb
- mov ax, 1
- jmp @@FINE
- @@NEXT:
- add di, 14
- loop @@CICLO
- xor ax, ax
- @@FINE:
- pop ds
- end;
-
- function RemapNum(var table:A_REPACTION;var action:word;num:integer):integer; assembler;
- asm
- push ds
- les di, action
- mov bx, es:[di]
- lds si, table
- mov ax, num
- mov cx, ax
- add ax, ax
- add ax, ax
- add si, ax
- dec si
- dec si
- std
- @@LOOP:
- lodsw
- cmp ax, REP_RANGE
- jb @@NORANGE
- sub ax, REP_RANGE
- cmp ax, bx
- jb @@NEXT
- lodsw
- lodsw
- dec cx
- cmp ax, bx
- jbe @@FOUND
- jmp @@NEXT
- @@NORANGE:
- cmp ax, bx
- je @@FOUND
- @@NEXT:
- lodsw
- loop @@LOOP
- xor ax, ax
- jmp @@FINE
- @@FOUND:
- les di, action
- movsw
- mov ax, 1
- @@FINE:
- pop ds
- end;
-
- procedure SetRandomSeed;
- var s:string;
- i:integer;
- begin
- s:=GetSymbol(SYM_SEED);
- RandomSeed:=0;
- if s=SYM_SEED then begin
- Randomize;
- RandomSeed:=RandSeed;
- end
- else if s<>'' then begin
- Val(s,RandomSeed,i);
- if i<>0 then RandomSeed:=0;
- end;
- end;
-
- function LenNum(n:word):integer;
- begin
- if n<10 then LenNum:=1
- else if n<100 then LenNum:=2
- else if n<1000 then LenNum:=3
- else LenNum:=4;
- end;
-
- var ThingIndex : array[1..MAXTHING] of integer;
- procedure Choose(var max:integer;n,c,lev:integer);
- var i,j:integer;
- begin
- if n<max then begin
- for i:=1 to n do begin
- j:=Random(max)+1;
- with Things^[ThingIndex[j]] do begin
- Code:=c;
- if lev and (REP_ZERO+7)<>0 then Flags:=lev and 7;
- Flags:=Flags or REP_CONV or (lev and (REP_DEAF+REP_MULTI));
- end;
- ThingIndex[j]:=ThingIndex[max];
- dec(max);
- end;
- inc(RemappedThing,n);
- end
- else begin
- for i:=1 to max do with Things^[ThingIndex[i]] do begin
- Code:=c;
- if lev and (REP_ZERO+7)<>0 then Flags:=lev and 7;
- Flags:=Flags or REP_CONV or (lev and (REP_DEAF+REP_MULTI));
- end;
- inc(RemappedThing,max);
- max:=0;
- end;
- end;
- procedure ReplaceThings(totobj:Integer);
- var repn : integer;
- i,j,k,l: word;
- level : word;
- once : word;
- multi : boolean;
- numobj : integer;
- amount : array[1..128] of word;
- numrep : integer;
- numabs : integer;
- iflev : integer;
- runlev : integer;
- iflevs : array[0..16] of integer;
- condit : boolean;
- col : integer;
- const glev : integer = 0;
- begin
- inc(glev);
- if debug then writeln('=== OBJECT CONVERSION, LEVEL ',glev);
- RandSeed:=RandomSeed;
- repn:=1;
- iflev:=0;
- runlev:=0;
- while repn<=NRepThing do begin
- numobj:=0;
- l:=RepThing^[repn];
- if l=REP_QELSE then begin
- inc(repn);
- if odd(iflev) or (iflev=0) then MyHalt(ERR_BADELSE);
- iflev:=iflev or 1;
- continue;
- end;
- if l=REP_QEND then begin
- inc(repn);
- if iflev<2 then MyHalt(ERR_BADENDIF);
- iflev:=iflevs[(iflev-2)div 2];
- if iflev<runlev then runlev:=iflev;
- continue;
- end;
- if l>=REP_QIF then inc(repn);
- if (runlev=iflev) and debug then begin
- write('SOURCE OBJECTS: ');
- col:=1;
- end;
- while RepThing^[repn]<REP_FLAG do begin
- j:=RepThing^[repn];
- inc(repn);
- if RepThing^[repn] and REP_RANGE>0 then begin
- inc(repn);
- k:=RepThing^[repn];
- inc(repn);
- end
- else k:=j;
- once:=RepThing^[repn];
- inc(repn);
- level:=once and 7; {level 1 or 2 or 3}
- if level=0 then level:=7;
- multi:=once and REP_MULTI>0; {multiplayer flag}
- once:=once and REP_ALL;
- if runlev=iflev then begin
- if debug then begin
- if col<3 then write(#32#32)
- else writeln;
- col:=col mod 3+1;
- if j<>k then write('Objects #':18-LenNum(j)-LenNum(k),j,'-#',k)
- else begin
- i:=1;
- while (i<=NObjects) and ((Objects^[i].Code<>j) or not (Game1 in Objects^[i].Games)) do inc(i);
- if i<=NObjects then write(Objects^[i].Name:20)
- else write('Unknown object #':20-LenNum(j),j);
- end;
- numabs:=numobj;
- end;
- for i:=1 to totobj do with Things^[i] do
- if (Code>=j) and (Code<=k) and (Flags and level>0) and
- ((once=REP_ALL) or ((Flags xor once)and REP_CONV=0)) and
- (not multi or (Flags and REP_MULTI>0)) then begin
- inc(numobj);
- ThingIndex[numobj]:=i;
- end;
- if debug then begin
- numabs:=numobj-numabs;
- write('=',numabs,#32:4-LenNum(numabs));
- end;
- end;
- end;
- if (runlev=iflev) and debug then writeln;
- if l>=REP_QIF then begin
- i:=RepThing^[repn] and not REP_QIF;
- inc(repn);
- j:=iflev;
- iflevs[iflev div 2]:=iflev;
- iflev:=(iflev+2) and $FFFE;
- if runlev=j then begin
- l:=l and not REP_QIF;
- case l of
- 0: condit:=numobj=i;
- 1: condit:=numobj<>i;
- 2: condit:=numobj<i;
- 3: condit:=numobj<=i;
- 4: condit:=numobj>i;
- 5: condit:=numobj>=i;
- end;
- if debug then writeln('IF ',numobj,copy('= <>< <=> >=',l*2+1,2),i,condit:8);
- runlev:=iflev+1-ord(condit);
- end;
- continue;
- end;
-
- numrep:=RepThing^[repn]-REP_FLAG;
- inc(repn);
- if (numobj=0) or (numrep=0) then inc(repn,numrep*3)
- else begin
- numabs:=0;
- j:=repn+1;
- for i:=1 to numrep do begin
- k:=RepThing^[j];
- if k=0 then k:=REP_FLAG
- else begin
- if k>=REP_FLAG then k:=(longint(numobj)*(k-REP_FLAG)+50)div 100;
- inc(numabs,k);
- end;
- amount[i]:=k;
- inc(j,3);
- end;
-
- if numabs>numobj then begin
- k:=numobj;
- for i:=1 to numrep do begin
- j:=amount[i];
- if j<REP_FLAG then begin
- if numabs=0 then amount[i]:=0
- else amount[i]:=(longint(j)*k+numabs div 2)div numabs;
- dec(numabs,j);
- dec(k,amount[i]);
- end;
- end;
- numabs:=numobj;
- end;
-
- numabs:=numobj-numabs;
- j:=0;
- for i:=1 to numrep do if amount[i]>=REP_FLAG then inc(j);
- for i:=1 to numrep do if amount[i]>=REP_FLAG then begin
- amount[i]:=(numabs+j div 2)div j;
- dec(numabs,amount[i]);
- dec(j);
- end;
-
- if debug then begin
- write('CONVERTED OBJECTS: ');
- col:=1;
- end;
- for i:=1 to numrep do begin
- j:=RepThing^[repn];
- if debug then begin
- if col<3 then write(#32#32)
- else writeln;
- col:=col mod 3+1;
- k:=1;
- while (k<=NObjects) and ((Objects^[k].Code<>j) or not (Game2 in Objects^[k].Games)) do inc(k);
- if k<=NObjects then write(Objects^[k].Name:20)
- else write('Unknown object #':20-LenNum(j),j);
- write('=',amount[i],#32:4-LenNum(amount[i]));
- end;
- Choose(numobj,amount[i],j,RepThing^[repn+2]);
- inc(repn,3);
- end;
- if debug then writeln;
- end;
- end;
- for i:=1 to totobj do with Things^[i] do Flags:=Flags and not REP_CONV;
- end;
-
- function IdentifyGame(s:string;default:GAMETYPE):GAMETYPE;
- begin
- if (s='D') or (s='DOOM') then IdentifyGame:=GT_DOOM
- else if (s='D2') or (s='DOOM2') then IdentifyGame:=GT_DOOM2
- else if (s='H') or (s='HERETIC') then IdentifyGame:=GT_HERETIC
- else IdentifyGame:=default;
- end;
-
- function RemapStatus:integer;
- var s:string;
- i,j:integer;
- begin
- s:=GetSymbol(SYM_REMAP);
- if s='' then RemapStatus:=0
- else begin
- val(s,i,j);
- if j<>0 then i:=1;
- RemapStatus:=i;
- end;
- end;
-
- procedure SetMusicName(var d:WAD_ENTRY;j:integer);
- begin
- if (j>0) and (j<=99) then with d do case Game2 of
- GT_DOOM2: begin
- if j<=32 then Name:=MUS2NAMES[j]
- else begin
- Name:='D_MUSxy'#0;
- Name[6]:=chr(j div 10+48);
- Name[7]:=chr(j mod 10+48);
- end;
- end;
- GT_DOOM: begin
- Name:='D_ExMy'#0#0;
- Name[4]:=chr((j-1) div 9+49);
- Name[6]:=chr((j-1) mod 9+49);
- end;
- GT_HERETIC: begin
- Name:='MUS_ExMy';
- Name[6]:=chr((j-1) div 9+49);
- Name[8]:=chr((j-1) mod 9+49);
- end;
- end;
- end;
-
- procedure Process;
- var f : file;
- fpos : longint;
- head : WAD_HEADER;
- num : integer;
- i,j,k,l : integer;
- save : boolean;
- levpos : array[1..99] of integer;
- levmap : array[1..99] of integer;
- muspos : array[1..99] of integer;
- remap : integer;
- mix : boolean;
- begin
- save:=False;
- mix:=GetSymbol(SYM_MIX)<>'';
- Game1:=IdentifyGame(GetSymbol(SYM_FROM),GT_DOOM);
- Game2:=IdentifyGame(GetSymbol(SYM_TO),GT_DOOM2);
- remap:=RemapStatus;
- SetRandomSeed;
- if DestName<>'' then begin
- CopyDest;
- SourceName:=DestName;
- end
- else DestName:=SourceName;
- Assign(f,DestName);
- FileMode:=2; {open for read/write}
- ErrStr:=DestName;
- Reset(f,1);
- if ioresult<>0 then MyHalt(ERR_OPEN);
- BlockR(f,head,sizeof(head));
- if (head.Sig<>PWAD_SIG) and (head.Sig<>IWAD_SIG) then MyHalt(ERR_PWAD);
- num:=head.Num;
- if num>MAXENTRY then MyHalt(ERR_TOOENTRY);
- FSeek(f,head.Start);
- BlockR(f,Dirlist^,num*sizeof(WAD_ENTRY));
-
- write('Processing with ');
- write('REMAP=');
- if remap=0 then write('OFF') else write('ON(',remap,')');
- write(',MIX=');
- if mix then write('ON') else write('OFF');
- writeln(',SEED=',RandSeed);
-
- for i:=1 to 99 do begin
- levmap[i]:=0;
- muspos[i]:=0;
- end;
- k:=0;
- for i:=1 to num do with Dirlist^[i] do begin
- if copy(Name,1,3)='MAP' then begin
- j:=(ord(name[4])-48)*10+ord(name[5])-48;
- if (j>0) and (j<=99) then begin
- levpos[j]:=i;
- levmap[j]:=j;
- end;
- end
- else if (Name[1]='E') and (Name[3]='M') and (Name[5]=#0) then begin
- j:=(ord(Name[2])-49)*9+ord(Name[4])-48;
- if (j>0) and (j<=99) then begin
- levpos[j]:=i;
- levmap[j]:=j;
- end;
- end
- else if copy(Name,1,3)='MUS' then begin
- if mix then begin inc(k);j:=k; end
- else j:=(ord(Name[6])-49)*9+ord(Name[8])-48;
- if (j>0) and (j<=99) then muspos[j]:=i;
- end
- else if copy(Name,1,5)='D_MUS' then begin
- if mix then begin inc(k);j:=k; end
- else j:=(ord(name[6])-48)*10+ord(name[7])-48;
- if (j>0) and (j<=99) then muspos[j]:=i;
- end
- else if (Name[1]='D') and (Name[2]='_') then begin
- if (Name[3]='E') and (Name[5]='M') then begin
- if mix then begin inc(k);j:=k; end
- else j:=(ord(Name[4])-49)*9+ord(Name[6])-48
- end
- else begin
- j:=32;
- while (j>0) and (MUS2NAMES[j]<>Name) do dec(j);
- if mix and (j>0) then begin inc(k);j:=k; end
- end;
- if (j>0) and (j<=99) then muspos[j]:=i;
- end;
- end;
- if remap>0 then
- for i:=1 to 99 do if levmap[i]>0 then begin
- levmap[i]:=remap;
- inc(remap);
- end;
- for i:=1 to 99 do if levmap[i]>0 then with Dirlist^[levpos[i]] do begin
- j:=levmap[i];
- case Game2 of
- GT_DOOM2: begin
- Name:='MAPxy'#0#0#0;
- Name[4]:=chr(j div 10+48);
- Name[5]:=chr(j mod 10+48);
- end;
- GT_DOOM,GT_HERETIC: begin
- Name:='ExMy'#0#0#0#0;
- Name[2]:=chr((j-1) div 9+49);
- Name[4]:=chr((j-1) mod 9+49);
- end;
- end;
- inc(RemappedLev);
- save:=True;
- end;
- if mix then begin {mix musics}
- Randomize;
- for i:=1 to k-1 do begin
- j:=Random(k-i)+i;
- l:=muspos[i];
- muspos[i]:=muspos[j];
- muspos[j]:=l;
- end;
- for i:=1 to k do begin
- SetMusicName(Dirlist^[muspos[i]],i);
- inc(RemappedMus);
- save:=True;
- end;
- end
- else for i:=1 to 99 do if muspos[i]>0 then begin
- SetMusicName(Dirlist^[muspos[i]],levmap[i]);
- inc(RemappedMus);
- save:=True;
- end;
-
- if NRepDirs>0 then begin
- for i:=1 to num do with Dirlist^[i] do
- inc(RemappedDirs,RemapName(RepDirs^,Name,NRepDirs));
- end;
-
- for i:=1 to num do with Dirlist^[i] do begin
- if (Name=N_LINEDEFS) and (NRepLAct>0) then begin
- FSeek(f,Start);
- k:=Size div sizeof(LINEDEF);
- while k>0 do begin
- fpos:=FilePos(f);
- l:=MAXLINE;
- if l>k then l:=k;
- BlockR(f,Linedefs^,l*sizeof(LINEDEF));
- for j:=1 to l do
- inc(RemappedLAct,RemapNum(RepLAct^,Linedefs^[j].Action,NRepLAct));
- FSeek(f,fpos);
- BlockW(f,Linedefs^,l*sizeof(LINEDEF));
- dec(k,l);
- end;
- end
- else if (Name=N_SECTORS) and (NRepSAct+NRepFloor>0) then begin
- FSeek(f,Start);
- k:=Size div sizeof(SECTOR);
- while k>0 do begin
- fpos:=FilePos(f);
- l:=MAXSECT;
- if l>k then l:=k;
- BlockR(f,Sectors^,l*sizeof(SECTOR));
- if NRepSAct>0 then
- for j:=1 to l do
- inc(RemappedSAct,RemapNum(RepSAct^,Sectors^[j].Action,NRepSAct));
- if NRepFloor>0 then
- for j:=1 to l do
- inc(RemappedFloor,RemapName(RepFloor^,Sectors^[j].Floor,NRepFloor)+
- RemapName(RepFloor^,Sectors^[j].Ceiling,NRepFloor));
- FSeek(f,fpos);
- BlockW(f,Sectors^,l*sizeof(SECTOR));
- dec(k,l);
- end;
- end
- else if (Name=N_SIDEDEFS) and (NRepText>0) then begin
- FSeek(f,Start);
- k:=Size div sizeof(SIDEDEF);
- while k>0 do begin
- fpos:=FilePos(f);
- l:=MAXSIDE;
- if l>k then l:=k;
- BlockR(f,Sidedefs^,l*sizeof(SIDEDEF));
- for j:=1 to l do
- inc(RemappedText,RemapName(RepText^,Sidedefs^[j].UpT,NRepText)+
- RemapName(RepText^,Sidedefs^[j].LoT,NRepText)+
- RemapName(RepText^,Sidedefs^[j].MidT,NRepText));
- FSeek(f,fpos);
- BlockW(f,Sidedefs^,l*sizeof(SIDEDEF));
- dec(k,l);
- end;
- end
- else if (Name=N_THINGS) and (NRepThing>0) then begin
- FSeek(f,Start);
- k:=Size div sizeof(THING);
- BlockR(f,Things^,k*sizeof(THING));
- ReplaceThings(k);
- FSeek(f,Start);
- BlockW(f,Things^,k*sizeof(THING));
- end;
- end;
-
- if save or (RemappedDirs>0) then begin
- FSeek(f,head.Start);
- BlockW(f,Dirlist^,num*sizeof(WAD_ENTRY));
- end;
-
- Close(f);
- writeln('Remapped LEVELS:',RemappedLev:4,' MUSICS:',RemappedMus:4,
- ' TEXTURES:',RemappedText:4,' FLOORS :',RemappedFloor:4);
- writeln(' THINGS:',RemappedThing:4,' NAMES :',RemappedDirs:4,
- ' LACTIONS:',RemappedLAct:4,' SACTIONS:',RemappedSAct:4);
- end;
-
- begin
- Initialize;
- Parse;
- if (SourceName='') or (GetSymbol(SYM_HELP)<>'') then Help
- else Process;
- end.
-