{****************************************************************************
*                      The DOOM Hacker's Tool Kit                           *
*****************************************************************************
* Program: DFE v1.31                                                        *
* Purpose: DOOM 1.2  Front End                                              *
* Date:    4/28/94                                                          *
* Author:  Joshua Jackson        Internet: joshjackson@delphi.com           *
****************************************************************************}

{As of this point in time, I have not found a way to allow execution of
 the Watcom DOS extender while running under DPMI... however I am looking
 into a way to switch the system back to real mode before launching DOOM}

{$IFNDEF DPMI}
uses 	app,objects,menus,drivers,views,memory,dialogs,strings,windos,Dos,crt,
		WadDecl,Wad,mapread,StdDlg,Swap,MsgBox;
{$ELSE} {You CAN NOT use the SWAP unit under DPMI!!!}
uses 	app,objects,menus,drivers,views,memory,dialogs,strings,windos,Dos,crt,
		WadDecl,Wad,mapread,StdDlg,MsgBox;
{$ENDIF}

const	cmOnePlayerMenu	= 100;
		cmSerialMenu		= 101;
		cmIPXMenu			= 102;
		cmModemMenu			= 103;
		cmViewMaps			= 105;
		cmNull				= 255;

		gtNormal				= 00;
		gtIPXNet				= 01;
		gtModem				= 02;
		gtDirLinkModem		= 03;
		gtSerial				= 04;
		gtSetMode			= 05;
		gtViewSprites		= 06;
		gtViewMaps			= 07;

type	PMyApp=^TMyApp;
		TMyApp=Object(Tapplication)
			Constructor Init;
			Procedure InitMenuBar; virtual;
			Procedure Idle; virtual;
			Procedure HandleEvent(Var Event:TEvent); virtual;
			Function GetPalette:PPalette; virtual;
			Procedure RunDoom(GameType:integer;Params:string);
			Procedure OnePlayerMenu;
			Procedure SerialMenu;
			Procedure IPXMenu;
			Procedure ModemMenu;
			Procedure ViewMaps;
		end;
		SelLevelArray=array[1..4] of PCluster;
		LevelNameArray=array[1..9] of String;

var	MyApp:TMyApp;
		Debug:boolean;

Procedure SetLevelData(R:TRect;var SelLevel:PRadioButtons;Level:word);

	begin
		case Level of
			1:SelLevel:=New(PRadioButtons, Init(R,
			  NewSItem('~1~ Hanger',
			  NewSItem('~2~ Nuclear Plant',
			  NewSItem('~3~ Toxin Refinery',
			  NewSItem('~4~ Command Control',
			  NewSItem('~5~ Phobos Lab',
			  NewSItem('~6~ Central Processing',
			  NewSItem('~7~ Computer Station',
			  NewSItem('~8~ Phobos Anomaly',
			  NewSItem('~9~ Military Base',
			  nil)))))))))));
			2:SelLevel:=New(PRadioButtons, Init(R,
			  NewSItem('~1~ Deimos Anomaly',
			  NewSItem('~2~ Containment Area',
			  NewSItem('~3~ Refinery',
			  NewSItem('~4~ Deimos Lab',
			  NewSItem('~5~ Command Center',
			  NewSItem('~6~ Halls of the Damned',
			  NewSItem('~7~ Spawning Vats',
			  NewSItem('~8~ Towel of Babel',
			  NewSItem('~9~ Fortress of Mystery',
			  nil)))))))))));
			3:SelLevel:=New(PRadioButtons, Init(R,
			  NewSItem('~1~ Hell Keep',
			  NewSItem('~2~ Slough of Despair',
			  NewSItem('~3~ Pandemonium',
			  NewSItem('~4~ House of Pain',
			  NewSItem('~5~ Unholy Cathedrial',
			  NewSItem('~6~ Mount Erebus',
			  NewSItem('~7~ Limbo',
			  NewSItem('~8~ DIS',
			  NewSItem('~9~ Warrens',
			  nil)))))))))));
		end;
	end;

Procedure FindLevelNames(FileSpec:PathStr;var Levels:LevelNameArray;R:TRect; var SelLevel:PRadioButtons);

	var   PDir:PWadDirectory;
			t,i1,i2,CurLevel:integer;
			tmpstr:string;
			Code:integer;
			TmpArray:PSItem;
			CurItem,ItemList:PSitem;

	begin
		TmpStr:=FileSpec;
		PDir:=new(PWadDirectory, Init(FileSpec));
		if WadResult<>wrOk then begin
			MessageBox(WadResultMsg(WadResult),Nil,mfError+ mfOkButton);
			exit;
		end;
		CurLevel:=1;
		CurItem:=Nil;
		ItemList:=Nil;
		Levels[1]:='';
		for t:=1 to PDir^.DirEntries do begin
			if (PDir^.DirEntry^[t].ObjName[1]='E') and (PDir^.DirEntry^[t].ObjName[3]='M') then begin
				tmpstr:=PDir^.DirEntry^[t].ObjName[2];
				val(TmpStr,i1,Code);
				if Code<>0 then
					continue;
				tmpstr:=PDir^.DirEntry^[t].ObjName[4];
				val(TmpStr,i2,Code);
				if Code<>0 then
					continue;
				Levels[CurLevel]:=PDir^.DirEntry^[t].ObjName;
				if ItemList=Nil then begin
					ItemList:=New(PSItem);
					ItemList^.Value:=NewStr(Levels[CurLevel]);
					ItemList^.Next:=Nil;
					CurItem:=ItemList;
				 end
				else begin
					CurItem^.Next:=New(PSItem);
					CurItem:=CurItem^.Next;
					CurItem^.Value:=NewStr(Levels[CurLevel]);
					CurItem^.Next:=Nil;
				end;
				inc(CurLevel);
				if CurLevel=10 then begin
					PDir^.Done;
					Dispose(PDir);
					SelLevel:=New(PRadioButtons, Init(R,ItemList));
					exit;
				end;
			end;
		end;
		PDir^.Done;
		Dispose(PDir);
		SelLevel:=New(PRadioButtons, Init(R,ItemList));
	end;

Procedure SetMenuData(MenuNum:byte;var Param1,Param2:string);

	var	R:Trect;
			SelModem,SelGame,Monsters,SelSkill,Players:PCluster;
			DialNum:PInputLine;
			SelLevel:PRadioButtons;
			Dialog1,Dialog2:PDialog;
			Dialog3:PFileDialog;
			ComPort:PCluster;
			Control,Episode:word;
			TmpStr,DmParam,ModeParam:string;
			ExtFile:PathStr;
			ExtLevelPos:byte;
			jb:byte;
			FileName: FNameStr;
			LevelNames:LevelNameArray;

	begin
		Case MenuNum of
			1:begin
				R.Assign(2,1,30,5);
				SelGame:=New(PRadioButtons, Init(R,
				  NewSItem('~K~nee-Deep In The Dead',
				  NewSItem('~S~hores Of Hell',
				  NewSItem('~I~nferno!',
				  NewSItem('~L~oad External Wad File',
				  nil))))));
				R.Assign(20,6,60,15);
				Dialog1:=New(PDialog,Init(r,'Episodes'));
				with Dialog1^ do begin
					R.Assign(5,6,15,8);
					Insert(New(PButton,Init(R,'~O~k',cmOk,bfDefault)));
					R.Assign(25,6,35,8);
					Insert(New(PButton,Init(R,'~C~ancel',cmCancel,bfNormal)));
					Insert(SelGame);
				end;
				Control:=Desktop^.ExecView(Dialog1);
				Episode:=SelGame^.Value + 1;
				Param1:='';
				DmParam:='';
				if Episode=4 then begin
					FileName := '*.WAD';
					Dialog3:=New(PFileDialog, Init('*.WAD', 'Select Wad File','~N~ame',fdOkButton,100));
					Dialog3^.SetData(FileName);
					Control:=Desktop^.ExecView(Dialog3);
					if Control=cmFileOpen then
						Control:=cmOk;
					if Control=cmOK then begin
						ExtFile:=Dialog3^.Directory^+(Dialog3^.FileName^.Data^);
						R.Assign(2, 1, 28, 10);
						FindLevelNames(ExtFile,LevelNames,R,SelLevel);
						if WadResult<>wrOk then
							exit;
						if LevelNames[1]='' then begin
							Param1:='';
							MessageBox('No valid level entries found.',Nil,mfError+mfOkButton);
							control:=cmCancel;
						 end
						else begin
							Episode:=4;
							Param1:='-file '+ExtFile+' ';
						end;
					end;
					Dialog3^.Done;
					Dispose(Dialog3);
				end;
				if Control=cmOK then begin
					R.Assign(30, 3, 55, 8);
					SelSkill:=New(PRadioButtons, Init(R,
					  NewSItem('~I~''m too young to die',
					  NewSItem('~H~ey Not too Rough',
					  NewSItem('H~u~rt Me Plenty',
					  NewSItem('U~l~tra Violence',
					  NewSItem('~N~ightmare!',
					  nil)))))));
					R.Assign(30, 1, 50, 2);
					Monsters:=New(PCheckBoxes, Init(R,
					  NewSItem('No ~M~onsters',
					  nil)));
					R.Assign(2, 1, 28, 10);
					if Episode < 4 then
						SetLevelData(R,SelLevel,1);
					R.Assign(11,4,69,18);
					Dialog2:=New(PDialog,Init(r,'Game Options'));
					with Dialog2^ do begin
						Insert(Monsters);
						Insert(SelSkill);
						R.Assign(15,11,25,13);
						Insert(New(PButton,Init(R,'~C~ancel',cmCancel,bfNormal)));
						R.Assign(2,11,12,13);
						Insert(New(PButton,Init(R,'~O~k',cmOk,bfDefault)));
						Insert(SelLevel);
					end;
					Control:=Desktop^.ExecView(Dialog2);
					if Control=cmOk then begin
						if Episode < 4 then begin
							Str(Episode,TmpStr);
							DmParam:='-devparm -warp '+TmpStr+' ';
							Str(SelLevel^.Value + 1,TmpStr);
							DmParam:=DmParam+TmpStr
						 end
						else begin
							DmParam:='-devparm -warp ';
							DmParam:=DmParam+LevelNames[SelLevel^.Value+1][2]+' ';
							DmParam:=DmParam+LevelNames[SelLevel^.Value+1][4];
						end;
						Str(SelSkill^.Value + 1,TmpStr);
						DmParam:=DmParam+' -skill '+TmpStr+' ';
						if (Monsters^.Value and 1) = 1 then
							DmParam:=DmParam+'-nomonsters';
					 end
					else
						Param1:='';
					Dialog2^.Done;
					Dispose(Dialog2);
					Param1:=Param1+DmParam;
				end;
				Dialog1^.Done;
				Dispose(Dialog1);
			  end;
			2:begin
				R.Assign(2,1,30,5);
				SelGame:=New(PRadioButtons, Init(R,
				  NewSItem('~K~nee-Deep In The Dead',
				  NewSItem('~S~hores Of Hell',
				  NewSItem('~I~nferno!',
				  NewSItem('~L~oad External Wad File',
				  nil))))));
				R.Assign(20,7,60,16);
				Dialog1:=New(PDialog,Init(r,'Episodes'));
				with Dialog1^ do begin
					R.Assign(5,6,15,8);
					Insert(New(PButton,Init(R,'~O~k',cmOk,bfDefault)));
					R.Assign(25,6,35,8);
					Insert(New(PButton,Init(R,'~C~ancel',cmCancel,bfNormal)));
					Insert(SelGame);
				end;
				Control:=Desktop^.ExecView(Dialog1);
				Episode:=SelGame^.Value + 1;
				DmParam:='';
				Param1:='';
				if Episode=4 then begin
					Dialog3:=New(PFileDialog,Init('*.WAD','Load External WAD','WAD Files',fdOkButton,jb));
					Control:=Desktop^.ExecView(Dialog3);
					if Control=cmFileOpen then
						Control:=cmOk;
					if Control=cmOK then begin
						ExtFile:=Dialog3^.Directory^+(Dialog3^.FileName^.Data^);
						R.Assign(2, 1, 28, 10);
						FindLevelNames(ExtFile,LevelNames,R,SelLevel);
						if WadResult<>wrOk then
							exit;
						if LevelNames[1]='' then begin
							Param1:='';
							MessageBox('No valid level entries found.',Nil,mfError+mfOkButton);
							control:=cmCancel;
						 end
						else begin
							Episode:=4;
							Param1:='-file '+ExtFile+' ';
						end;
					end;
					Dialog3^.Done;
					Dispose(Dialog3);
				end;
				if Control=cmOK then begin
					R.Assign(30,10,55,14);
					ComPort:=New(PRadioButtons, Init(R,
					  NewSItem('COM1',
					  NewSItem('COM2',
					  NewSItem('COM3',
					  NewSItem('COM4',
					  nil))))));
					R.Assign(30, 4, 55, 9);
					SelSkill:=New(PRadioButtons, Init(R,
					  NewSItem('~I~''m too young to die',
					  NewSItem('~H~ey Not too Rough',
					  NewSItem('H~u~rt Me Plenty',
					  NewSItem('U~l~tra Violence',
					  NewSItem('~N~ightmare!',
					  nil)))))));
					R.Assign(30, 1, 50, 3);
					Monsters:=New(PCheckBoxes, Init(R,
					  NewSItem('No ~M~onsters',
					  NewSItem('~D~eath Match',
					  nil))));
					R.Assign(2, 1, 28, 10);
					if Episode < 4 then
						SetLevelData(R,SelLevel,Episode);
					R.Assign(11,3,69,18);
					Dialog2:=New(PDialog,Init(r,'Game Options'));
					with Dialog2^ do begin
						Insert(Monsters);
						Insert(SelSkill);
						Insert(ComPort);
						R.Assign(15,12,25,14);
						Insert(New(PButton,Init(R,'~C~ancel',cmCancel,bfNormal)));
						R.Assign(2,12,12,14);
						Insert(New(PButton,Init(R,'~O~k',cmOk,bfDefault)));
						Insert(SelLevel);
					end;
					Control:=Desktop^.ExecView(Dialog2);
					if Control=cmOk then begin
						if Episode < 4 then begin
							Str(Episode,TmpStr);
							DmParam:='-devparm -warp '+TmpStr+' ';
							Str(SelLevel^.Value + 1,TmpStr);
							DmParam:=DmParam+TmpStr
						 end
						else begin
							DmParam:='-devparm -warp ';
							DmParam:=DmParam+LevelNames[SelLevel^.Value+1][2]+' ';
							DmParam:=DmParam+LevelNames[SelLevel^.Value+1][4];
						end;
						Str(SelSkill^.Value + 1,TmpStr);
						DmParam:=DmParam+' -skill '+TmpStr+' ';
						DmParam:=DmParam+' -COM';
						Str(ComPort^.Value + 1,TmpStr);
						ModeParam:='COM'+TmpStr+':9600,N,8,1';
						DmParam:=DmParam+TmpStr+' ';
						if (Monsters^.Value and 1) = 1 then
							DmParam:=DmParam+'-nomonsters ';
						if (Monsters^.Value and 2) = 2 then
							DmParam:=DmParam+'-deathmatch';
					 end
					else
						Param1:='';
					Dialog2^.Done;
					Dispose(Dialog2);
					Param1:=Param1+DmParam;
				end;
				Param2:=ModeParam;
				Param1:=Param1+dmParam;
				Dialog1^.Done;
				Dispose(Dialog1);
			  end;
			3:begin
				R.Assign(2,1,30,5);
				SelGame:=New(PRadioButtons, Init(R,
				  NewSItem('~K~nee-Deep In The Dead',
				  NewSItem('~S~hores Of Hell',
				  NewSItem('~I~nferno!',
				  NewSItem('~L~oad External Wad File',
				  nil))))));
				R.Assign(20,7,60,16);
				Dialog1:=New(PDialog,Init(r,'Episodes'));
				with Dialog1^ do begin
					R.Assign(5,6,15,8);
					Insert(New(PButton,Init(R,'~O~k',cmOk,bfDefault)));
					R.Assign(25,6,35,8);
					Insert(New(PButton,Init(R,'~C~ancel',cmCancel,bfNormal)));
					Insert(SelGame);
				end;
				Control:=Desktop^.ExecView(Dialog1);
				Episode:=SelGame^.Value + 1;
				DmParam:='';
				Param1:='';
				if Episode=4 then begin
					Dialog3:=New(PFileDialog,Init('*.WAD','Load External WAD','WAD Files',fdOkButton,jb));
					Control:=Desktop^.ExecView(Dialog3);
					if Control=cmFileOpen then
						Control:=cmOk;
					if Control=cmOK then begin
						ExtFile:=Dialog3^.Directory^+(Dialog3^.FileName^.Data^);
						R.Assign(2, 1, 28, 10);
						FindLevelNames(ExtFile,LevelNames,R,SelLevel);
						if WadResult<>wrOk then
							exit;
						if LevelNames[1]='' then begin
							Param1:='';
							MessageBox('No valid level entries found.',Nil,mfError+mfOkButton);
							control:=cmCancel;
						 end
						else begin
							Episode:=4;
							Param1:='-file '+ExtFile+' ';
						end;
					end;
					Dialog3^.Done;
					Dispose(Dialog3);
				end;
				if Control=cmOK then begin
					R.Assign(30,10,55,13);
					Players:=New(PRadioButtons, Init(R,
					  NewSItem('Two Players',
					  NewSItem('Three Players',
					  NewSItem('Four Players',
					  nil)))));
					R.Assign(30, 4, 55, 9);
					SelSkill:=New(PRadioButtons, Init(R,
					  NewSItem('~I~''m too young to die',
					  NewSItem('~H~ey Not too Rough',
					  NewSItem('H~u~rt Me Plenty',
					  NewSItem('U~l~tra Violence',
					  NewSItem('~N~ightmare!',
					  nil)))))));
					R.Assign(30, 1, 50, 3);
					Monsters:=New(PCheckBoxes, Init(R,
					  NewSItem('No ~M~onsters',
					  NewSItem('~D~eath Match',
					  nil))));
					R.Assign(2, 1, 28, 10);
					if Episode < 4 then
						SetLevelData(R,SelLevel,Episode);
					R.Assign(11,3,69,17);
					Dialog2:=New(PDialog,Init(r,'Game Options'));
					with Dialog2^ do begin
						Insert(Monsters);
						Insert(SelSkill);
						Insert(Players);
						R.Assign(15,11,25,13);
						Insert(New(PButton,Init(R,'~C~ancel',cmCancel,bfNormal)));
						R.Assign(2,11,12,13);
						Insert(New(PButton,Init(R,'~O~k',cmOk,bfDefault)));
						Insert(SelLevel);
					end;
					Control:=Desktop^.ExecView(Dialog2);
					if Control=cmOk then begin
						if Episode < 4 then begin
							Str(Episode,TmpStr);
							DmParam:='-devparm -warp '+TmpStr+' ';
							Str(SelLevel^.Value + 1,TmpStr);
							DmParam:=DmParam+TmpStr
						 end
						else begin
							DmParam:='-devparm -warp ';
							DmParam:=DmParam+LevelNames[SelLevel^.Value+1][2]+' ';
							DmParam:=DmParam+LevelNames[SelLevel^.Value+1][4];
						end;
						Str(SelSkill^.Value + 1,TmpStr);
						DmParam:=DmParam+' -skill '+TmpStr+' ';
						DmParam:=DmParam+' -nodes ';
						Str(Players^.Value + 2,TmpStr);
						DmParam:=DmParam+TmpStr+' ';
						if (Monsters^.Value and 1) = 1 then
							DmParam:=DmParam+'-nomonsters ';
						if (Monsters^.Value and 2) = 2 then
							DmParam:=DmParam+'-deathmatch';
					 end
					else
						Param1:='';
					Dialog2^.Done;
					Dispose(Dialog2);
					Param1:=Param1+DmParam;
				end;
				Param1:=Param1+DmParam;
				Dialog1^.Done;
				Dispose(Dialog1);
			  end;
			4:begin
				R.Assign(2,1,30,5);
				SelGame:=New(PRadioButtons, Init(R,
				  NewSItem('~K~nee-Deep In The Dead',
				  NewSItem('~S~hores Of Hell',
				  NewSItem('~I~nferno!',
				  NewSItem('~L~oad External Wad File',
				  nil))))));
				R.Assign(20,7,60,16);
				Dialog1:=New(PDialog,Init(r,'Episodes'));
				with Dialog1^ do begin
					R.Assign(5,6,15,8);
					Insert(New(PButton,Init(R,'~O~k',cmOk,bfDefault)));
					R.Assign(25,6,35,8);
					Insert(New(PButton,Init(R,'~C~ancel',cmCancel,bfNormal)));
					Insert(SelGame);
				end;
				Control:=Desktop^.ExecView(Dialog1);
				Episode:=SelGame^.Value + 1;
				DmParam:='';
				Param1:='';
				if Episode=4 then begin
					Dialog3:=New(PFileDialog,Init('*.WAD','Load External WAD','WAD Files',fdOkButton,jb));
					Control:=Desktop^.ExecView(Dialog3);
					if Control=cmFileOpen then
						Control:=cmOk;
					if Control=cmOK then begin
						ExtFile:=Dialog3^.Directory^+(Dialog3^.FileName^.Data^);
						R.Assign(2, 1, 28, 10);
						FindLevelNames(ExtFile,LevelNames,R,SelLevel);
						if WadResult<>wrOk then
							exit;
						if LevelNames[1]='' then begin
							Param1:='';
							MessageBox('No valid level entries found.',Nil,mfError+mfOkButton);
							control:=cmCancel;
						 end
						else begin
							Episode:=4;
							Param1:='-file '+ExtFile+' ';
						end;
					end;
					Dialog3^.Done;
					Dispose(Dialog3);
				end;
				if Control=cmOK then begin
					R.Assign(30,10,55,14);
					ComPort:=New(PRadioButtons, Init(R,
					  NewSItem('COM1',
					  NewSItem('COM2',
					  NewSItem('COM3',
					  NewSItem('COM4',
					  nil))))));
					R.Assign(2,11,28,14);
					SelModem:=New(PRadioButtons, Init(R,
					  NewSItem('~A~lready Connected',
					  NewSItem('~W~ait For Call',
					  NewSItem('~D~ial:',
					  nil)))));
					R.Assign(12,13,25,14);
					DialNum:=New(PInputLine, Init(R,11));
					R.Assign(30, 4, 55, 9);
					SelSkill:=New(PRadioButtons, Init(R,
					  NewSItem('~I~''m too young to die',
					  NewSItem('~H~ey Not too Rough',
					  NewSItem('H~u~rt Me Plenty',
					  NewSItem('U~l~tra Violence',
					  NewSItem('~N~ightmare!',
					  nil)))))));
					R.Assign(30, 1, 50, 3);
					Monsters:=New(PCheckBoxes, Init(R,
					  NewSItem('No ~M~onsters',
					  NewSItem('~D~eath Match',
					  nil))));
					R.Assign(2, 1, 28, 10);
					if Episode < 4 then
						SetLevelData(R,SelLevel,Episode);
					R.Assign(11,2,69,20);
					Dialog2:=New(PDialog,Init(r,'Game Options'));
					with Dialog2^ do begin
						Insert(SelModem);
						Insert(DialNum);
						Insert(Monsters);
						Insert(SelSkill);
						Insert(ComPort);
						R.Assign(15,15,25,17);
						Insert(New(PButton,Init(R,'~C~ancel',cmCancel,bfNormal)));
						R.Assign(2,15,12,17);
						Insert(New(PButton,Init(R,'~O~k',cmOk,bfDefault)));
						Insert(SelLevel);
					end;
					Control:=Desktop^.ExecView(Dialog2);
					if Control=cmOk then begin
						DmParam:='';
						if SelModem^.Value = 2 then
							DmParam:=DmParam+'-dial '+DialNum^.Data^;
						if SelModem^.Value = 1 then
							DmParam:=DmParam+'-answer ';
						if Episode < 4 then begin
							Str(Episode,TmpStr);
							DmParam:=DmParam+'-devparm -warp '+TmpStr+' ';
							Str(SelLevel^.Value + 1,TmpStr);
							DmParam:=DmParam+TmpStr
						 end
						else begin
							DmParam:=DmParam+'-devparm -warp ';
							DmParam:=DmParam+LevelNames[SelLevel^.Value+1][2]+' ';
							DmParam:=DmParam+LevelNames[SelLevel^.Value+1][4];
						end;
						Str(SelSkill^.Value + 1,TmpStr);
						DmParam:=DmParam+' -skill '+TmpStr+' ';
						DmParam:=DmParam+' -COM';
						Str(ComPort^.Value + 1,TmpStr);
						ModeParam:='COM'+TmpStr+':9600,N,8,1';
						DmParam:=DmParam+TmpStr+' ';
						if (Monsters^.Value and 1) = 1 then
							DmParam:=DmParam+'-nomonsters ';
						if (Monsters^.Value and 2) = 2 then
							DmParam:=DmParam+'-deathmatch ';
					 end
					else
						Param1:='';
					Dialog2^.Done;
					Dispose(Dialog2);
					Param1:=Param1+DmParam;
				end;
				Param1:=Param1+DmParam;
				Param2:=ModeParam;
				Dialog1^.Done;
				Dispose(Dialog1);
			  end;
		end;
	end;

Constructor TMyApp.Init;

	var 	Regs:Registers;
			E:TEvent;
			AboutBox:PWindow;
			R:TRect;
			ch:char;

	begin
		TApplication.Init;
		if not Debug then begin
			R.Assign(28,6,52,15);
			AboutBox:=New(PWindow,Init(R,'',0));
			With AboutBox^ do begin
				Flags:=0;
				R.Assign(4,2,21,3);
				Insert(New(PStaticText,Init(R,'DOOM! Front End')));
				R.Assign(11,4,13,5);
				Insert(New(PStaticText,Init(R,'by')));
				R.Assign(4,6,21,7);
				Insert(New(PStaticText,Init(R,'Jackson Software')));
			end;
			Desktop^.Insert(AboutBox);
			delay(1000);
			Desktop^.Delete(AboutBox);
			AboutBox^.Done;
		end;
		Regs.ax:=$7A00;
		Intr($2F,Regs);
		if Regs.al <> $FF then
			DisableCommands([cmIPXMenu]);
		while keypressed do
			ch:=ReadKey;
		E.What:=evKeyDown;
		E.Command:=evKeyDown;
		E.KeyCode:=kbAltG;
		PutEvent(E);
	end;

Procedure TMyApp.Idle;

	begin
		Inherited Idle;
{		Gotoxy(65,1);
		writeln(MemAvail);}
	end;

Procedure TMyApp.HandleEvent(Var Event:TEvent);

	begin
		TApplication.HandleEvent(Event);
		if Event.What=evCommand then begin
			Case Event.Command of
				cmOnePlayerMenu:OnePlayerMenu;
				cmSerialMenu:SerialMenu;
				cmIPXMenu:IPXMenu;
				cmModemMenu:ModemMenu;
				cmViewMaps:ViewMaps;
			else
				exit;
			end;
			ClearEvent(Event);
		end;
	end;

procedure TMyApp.InitMenuBar;

	var	r:TRect;

	begin
		GetExtent(r);
		R.B.Y:=1;
		MenuBar:=New(PMenuBar,Init(r,NewMenu(
			NewSubMenu('~G~ames',hcNoContext,NewMenu(
				NewItem('~O~ne Player','',0,cmOnePlayerMenu,hcNoContext,
				NewItem('~S~erial Link','',0,cmSerialMenu,hcNoContext,
				NewItem('~I~PX Network','',0,cmIPXMenu,hcNoContext,
				NewItem('~M~odem Link','',0,cmModemMenu,hcNoContext,
				Nil))))),
			NewSubMenu('~V~iewers',hcNoContext,NewMenu(
				NewItem('~M~aps','',0,cmViewMaps,hcNoContext,
				Nil)),
			Nil)))));
	end;

Function TMyApp.GetPalette:PPalette;

	const MyBackColor:TPalette=CColor;

	var	t:integer;

	begin
		for t:=8 to 15 do
			MyBackColor[t+24]:=MyBackColor[t];
		MyBackColor[46]:=#16;
		MyBackColor[50]:=#15;
		MyBackColor[42]:=#$2F;
		MyBackColor[47]:=#23;
		MyBackColor[48]:=#31;
		MyBackColor[49]:=#30;
		GetPalette:=@MyBackColor;
	end;

Procedure TMyApp.RunDoom(GameType:integer;Params:string);

	var 	RunName:String;
			R:TRect;
			e:TEvent;
			S,Rn:array[0..79] of char;
			InfoBox:PWindow;
			SwapErr:word;

	begin
		case GameType of
			gtNormal:RunName:='DOOM.EXE';
			gtModem,gtSerial,gtDirLinkModem:RunName:='SERSETUP.EXE';
			gtIPXNet:RunName:='IPXSETUP.EXE';
			gtSetMode:RunName:='MODE.COM';
		end;
		if GameType=gtSetMode then begin
			StrPCopy(Rn,RunName);
			FileSearch(S,Rn,GetEnvVar('Path'));
			RunName:=strpas(s);
			R.Assign(20,8,60,11);
			InfoBox:=New(PWindow, Init(R,'',0));
			R.Assign(5,1,35,2);
			InfoBox^.Insert(New(PStaticText, Init(R,'Initializing: '+Params)));
			InfoBox^.Flags:=0;
			DeskTop^.Insert(InfoBox);
			if RunName<>'' then begin
				DoneDosMem;
				SwapVectors;
				Exec(RunName,Params+' >NUL');
				SwapVectors;
				InitDosMem;
				DeskTop^.Delete(InfoBox);
				InfoBox^.Done;
			 end
			else begin
				DeskTop^.Delete(InfoBox);
				InfoBox^.Done;
				R.Assign(20,8,60,11);
				InfoBox:=New(PWindow, Init(R,'**Error**',0));
				R.Assign(5,1,35,2);
				InfoBox^.Insert(New(PStaticText, Init(R,'Could Not Locate MODE.COM')));
				InfoBox^.Flags:=0;
				DeskTop^.Insert(InfoBox);
				delay(2000);
				DeskTop^.Delete(InfoBox);
				InfoBox^.Done;
			end
		 end {If GameType}
		else begin
			DoneSysError;
			DoneEvents;
			DoneVideo;
			DoneDosMem;
			if Debug then
				writeln(RunName,' ',Params);
		{$IFNDEF DPMI}
			SwapErr:=ExecPrg(RunName+' '+Params);
		{$ELSE}
			Exec(RunName,Params);
		{$ENDIF}
			delay(500);
			InitDosMem;
			InitVideo;
			InitEvents;
			InitSysError;
			Redraw;
			E.What:=evKeyDown;
			E.Command:=evKeyDown;
			E.KeyCode:=kbAltG;
			PutEvent(E);
		end;
	end;

Procedure TMyApp.OnePlayerMenu;

	var	DmParam,TmpStr:String;

	begin
		SetMenuData(1,DmParam,TmpStr);
		if DmParam<>'' then
			RunDoom(gtNormal,DmParam);
	end;


Procedure TMyApp.SerialMenu;

	var	ModeParam,DmParam:String;

	begin
		SetMenuData(2,DmParam,ModeParam);
		if DmParam<>'' then begin
			RunDoom(gtSetMode,ModeParam);
			RunDoom(gtSerial,DmParam);
      end;
	end;

Procedure TMyApp.IPXMenu;

	var	DmParam,TmpStr:String;

	begin
		SetMenuData(3,DmParam,TmpStr);
		if DmParam<>'' then
			RunDoom(gtIPXNet,DmParam);
	end;

Procedure TMyApp.ModemMenu;

	var	ModeParam,DmParam:String;

	begin
		SetMenuData(4,DmParam,ModeParam);
		if DmParam<>'' then begin
			RunDoom(gtSetMode,ModeParam);
			RunDoom(gtModem,DmParam);
		end;
	end;

Procedure TMyApp.ViewMaps;

	var	r:TRect;
			Episode,Control:integer;
			SelGame,Monsters,SelSkill:PCluster;
			SelLevel:PRadioButtons;
			Dialog1,Dialog2:PDialog;
			Dialog3:PFileDialog;
			TmpStr:String;
			ExtFile,WadName:PathStr;
			DmParam:ObjNameStr;
			ViewerMask,ThingMask:word;
			LevelNames:LevelNameArray;

	begin
		R.Assign(2,1,30,5);
		SelGame:=New(PRadioButtons, Init(R,
		  NewSItem('~K~nee-Deep In The Dead',
		  NewSItem('~S~hores Of Hell',
		  NewSItem('~I~nferno!',
		  NewSItem('~E~xternal Map',
		  nil))))));
		R.Assign(20,7,60,16);
		Dialog1:=New(PDialog,Init(r,'Episodes'));
		with Dialog1^ do begin
			R.Assign(5,6,15,8);
			Insert(New(PButton,Init(R,'~O~k',cmOk,bfDefault)));
			R.Assign(25,6,35,8);
			Insert(New(PButton,Init(R,'~C~ancel',cmCancel,bfNormal)));
			Insert(SelGame);
		end;
		Control:=Desktop^.ExecView(Dialog1);
		Episode:=SelGame^.Value + 1;
		ExtFile:='DOOM.WAD';
		if Episode=4 then begin
			Dialog3:=New(PFileDialog,Init('*.WAD','Load External WAD','WAD Files',fdOpenButton,100));
			Control:=ExecView(Dialog3);
			if Control=cmFileOpen then
				Control:=cmOk;
			if Control=cmOK then begin
				ExtFile:=Dialog3^.Directory^+(Dialog3^.FileName^.Data^);
				R.Assign(2, 1, 28, 10);
				FindLevelNames(ExtFile,LevelNames,R,SelLevel);
				if WadResult<>wrOk then
					exit;
				if LevelNames[1]='' then begin
					MessageBox('No valid level entries found.',Nil,mfError+mfOkButton);
					Control:=cmCancel;
				end;
				Episode:=4;
			end;
			Dialog3^.Done;
			Dispose(Dialog3);
		end;
		if Control=cmOK then begin
			R.Assign(30, 6, 55, 11);
			SelSkill:=New(PRadioButtons, Init(R,
			  NewSItem('~I~''m too young to die',
			  NewSItem('~H~ey Not too Rough',
			  NewSItem('H~u~rt Me Plenty',
			  NewSItem('U~l~tra Violence',
			  NewSItem('~N~ightmare!',
			  nil)))))));
			R.Assign(30, 1, 50, 5);
			Monsters:=New(PCheckBoxes, Init(R,
			  NewSItem('Show ~M~onsters',
			  NewSItem('Show ~W~eapons',
			  NewSItem('Show ~G~oodies',
			  NewSItem('Muti~P~layer',
			  nil))))));
			R.Assign(2, 1, 28, 10);
			SetLevelData(R,SelLevel,Episode);
			R.Assign(11,2,69,16);
			Dialog2:=New(PDialog,Init(r,'Map Viewer Options'));
			with Dialog2^ do begin
				Insert(Monsters);
				Insert(SelSkill);
				R.Assign(15,11,25,13);
				Insert(New(PButton,Init(R,'~C~ancel',cmCancel,bfNormal)));
				R.Assign(2,11,12,13);
				Insert(New(PButton,Init(R,'~O~k',cmOk,bfDefault)));
				Insert(SelLevel);
			end;
			Control:=Desktop^.ExecView(Dialog2);
			ViewerMask:=0;
			ThingMask:=0;
			if Control=cmOk then begin
				if Episode < 4 then begin
					DmParam:='E M     ';
					Str(Episode,TmpStr);
					DmParam[2]:=TmpStr[1];
					Str(SelLevel^.Value + 1,TmpStr);
					DmParam[4]:=TmpStr[1];
				 end
				else begin
					TmpStr:=LevelNames[SelLevel^.Value + 1]+'        ';
					move(TmpStr[1],DmParam[1],8);
				end;
				if (Monsters^.Value and 1) = 1 then
					ViewerMask:=ViewerMask or 1;
				if (Monsters^.Value and 2) = 2 then
					ViewerMask:=ViewerMask or 4;
				if (Monsters^.Value and 4) = 4 then
					ViewerMask:=ViewerMask or 2;
				if (Monsters^.Value and 8) = 8 then
					ViewerMask:=ViewerMask or 64;
				if (SelSkill^.Value=3) or (SelSkill^.Value=4) then
					ViewerMask:=ViewerMask or 32;
				if SelSkill^.Value=2 then
					ViewerMask:=ViewerMask or 16;
				if (SelSkill^.Value=0) or (SelSkill^.Value=1) then
					ViewerMask:=ViewerMask or 8;
				DoneSysError;
				DoneEvents;
				DoneVideo;
				TerminateOnWadError:=True;
				WadName:=ExtFile;
				ViewMap(WadName,DmParam,ViewerMask,0);
				TerminateOnWadError:=False;
				InitVideo;
				InitEvents;
				InitSysError;
				Redraw;
			end;
			Dialog2^.Done;
			Dispose(Dialog2);
		end;
		Dialog1^.Done;
		Dispose(Dialog1);
	end;

begin
{$IFNDEF DFE}
	writeln('Please include the conditional symbol DFE in you compiler options');
   writeln('and recompile DFE!');
   halt;
{$ENDIF}
{$IFNDEF DPMI}
	if (ParamStr(1)='/NOEMS') or (ParamStr(1)='/noems') then
		AllowEMSswap:=False;
	if (ParamStr(1)='-NOEMS') or (ParamStr(1)='-noems') then
		AllowEMSswap:=False;
	if not AllowEMSswap then
		writeln('EMS_Swap: disabled');
	delay(1000);
{$ENDIF}
	TerminateOnWadError:=False;
{$IFDEF DPMI}
	writeln;
	write('================================>>WARNING<<=====================================');
	writeln('SysDPMI_Init:');
	writeln;
	writeln('DFE is not designed to be compiled under DPMI!  You will not be able to');
	writeln('successfully launch DOOM with the current system configuration.  Please');
	writeln('recompile for real mode before attempting to execute DOOM.');
	writeln;
	writeln('                          Press ENTER to continue.');
	write('================================================================================');
	readln;
{$ENDIF}
	writeln('SysApplication_Init');
	delay(500);
	MyApp.Init;
	MyApp.Run;
	MyApp.Done;
end.
